From e301e5fe5ecc66fd3fa187d055d018139dd496b8 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 29 Jan 2018 19:36:51 +0100 Subject: [PATCH 1/8] android: fix various compilation errors --- dtool/src/dtoolutil/filename.cxx | 5 +++++ panda/src/gobj/vertexDataSaveFile.cxx | 5 +++++ panda/src/net/connectionManager.cxx | 4 ++-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/dtool/src/dtoolutil/filename.cxx b/dtool/src/dtoolutil/filename.cxx index c862c0aabf..d2c566b557 100644 --- a/dtool/src/dtoolutil/filename.cxx +++ b/dtool/src/dtoolutil/filename.cxx @@ -48,6 +48,11 @@ #include #endif +#if defined(__ANDROID__) && !defined(HAVE_LOCKF) +// Needed for flock. +#include +#endif + TextEncoder::Encoding Filename::_filesystem_encoding = TextEncoder::E_utf8; TVOLATILE AtomicAdjust::Pointer Filename::_home_directory; diff --git a/panda/src/gobj/vertexDataSaveFile.cxx b/panda/src/gobj/vertexDataSaveFile.cxx index 0aa8abff56..fd7087ba5d 100644 --- a/panda/src/gobj/vertexDataSaveFile.cxx +++ b/panda/src/gobj/vertexDataSaveFile.cxx @@ -23,6 +23,11 @@ #include #endif // _WIN32 +#if defined(__ANDROID__) && !defined(HAVE_LOCKF) +// Needed for flock. +#include +#endif + /** * */ diff --git a/panda/src/net/connectionManager.cxx b/panda/src/net/connectionManager.cxx index f7fdbe7e3e..8a0bfc1e86 100644 --- a/panda/src/net/connectionManager.cxx +++ b/panda/src/net/connectionManager.cxx @@ -26,7 +26,7 @@ #elif defined(WIN32_VC) || defined(WIN64_VC) #include // For gethostname() #include // For GetAdaptersAddresses() -#elif defined(ANDROID) +#elif defined(__ANDROID__) #include #else #include @@ -538,7 +538,7 @@ scan_interfaces() { PANDA_FREE_ARRAY(addresses); } -#elif defined(ANDROID) +#elif defined(__ANDROID__) // TODO: implementation using netlink_socket? #else // WIN32_VC From 7c1dd4050bf8fa20bd8a5d4466cb0be665b14e33 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 29 Jan 2018 19:38:46 +0100 Subject: [PATCH 2/8] android: change assets mount dir, point binary path to .apk The binary path we get from /proc/self/exe isn't very useful; the path to the .apk is barely more useful but it still doesn't make a whole lot of sense. It might make more sense to set it to the path of the native .so that is being loaded by NativeActivity. --- dtool/src/dtoolutil/executionEnvironment.cxx | 5 +-- makepanda/makepanda.py | 2 +- panda/src/android/android_main.cxx | 45 +++++++++++++------- 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/dtool/src/dtoolutil/executionEnvironment.cxx b/dtool/src/dtoolutil/executionEnvironment.cxx index ad782b521e..c4f2e5093e 100644 --- a/dtool/src/dtoolutil/executionEnvironment.cxx +++ b/dtool/src/dtoolutil/executionEnvironment.cxx @@ -540,7 +540,6 @@ read_environment_variables() { */ void ExecutionEnvironment:: read_args() { -#ifndef ANDROID // First, we need to fill in _dtool_name. This contains the full path to // the p3dtool library. @@ -578,7 +577,7 @@ read_args() { } #endif -#if defined(IS_FREEBSD) || defined(IS_LINUX) +#if defined(IS_FREEBSD) || (defined(IS_LINUX) && !defined(__ANDROID__)) // FreeBSD and Linux have a function to get the origin of a loaded library. char origin[PATH_MAX + 1]; @@ -833,8 +832,6 @@ read_args() { } #endif // _WIN32 -#endif // ANDROID - if (_dtool_name.empty()) { _dtool_name = _binary_name; } diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index af552d10b8..c3856fcaed 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -2353,7 +2353,7 @@ def WriteConfigSettings(): dtool_config["HAVE_CGGL"] = '1' dtool_config["HAVE_CGDX9"] = '1' - if (GetTarget() != "linux"): + if GetTarget() not in ("linux", "android"): dtool_config["HAVE_PROC_SELF_EXE"] = 'UNDEF' dtool_config["HAVE_PROC_SELF_MAPS"] = 'UNDEF' dtool_config["HAVE_PROC_SELF_CMDLINE"] = 'UNDEF' diff --git a/panda/src/android/android_main.cxx b/panda/src/android/android_main.cxx index ebc777ffa3..6626817410 100644 --- a/panda/src/android/android_main.cxx +++ b/panda/src/android/android_main.cxx @@ -52,43 +52,58 @@ void android_main(struct android_app* app) { // Fetch the path to the data directory. jfieldID datadir_field = env->GetFieldID(appinfo_class, "dataDir", "Ljava/lang/String;"); jstring datadir = (jstring) env->GetObjectField(appinfo, datadir_field); - const char *data_path = env->GetStringUTFChars(datadir, NULL); + const char *data_path = env->GetStringUTFChars(datadir, nullptr); - Filename::_internal_data_dir = data_path; - android_cat.info() << "Path to data: " << data_path << "\n"; + if (data_path != nullptr) { + Filename::_internal_data_dir = data_path; + android_cat.info() << "Path to data: " << data_path << "\n"; - env->ReleaseStringUTFChars(datadir, data_path); + env->ReleaseStringUTFChars(datadir, data_path); + } // Fetch the path to the library directory. - jfieldID libdir_field = env->GetFieldID(appinfo_class, "nativeLibraryDir", "Ljava/lang/String;"); - jstring libdir = (jstring) env->GetObjectField(appinfo, libdir_field); - const char *lib_path = env->GetStringUTFChars(libdir, NULL); + if (ExecutionEnvironment::get_dtool_name().empty()) { + jfieldID libdir_field = env->GetFieldID(appinfo_class, "nativeLibraryDir", "Ljava/lang/String;"); + jstring libdir = (jstring) env->GetObjectField(appinfo, libdir_field); + const char *lib_path = env->GetStringUTFChars(libdir, nullptr); - string dtool_name = string(lib_path) + "/libp3dtool.so"; - ExecutionEnvironment::set_dtool_name(dtool_name); - android_cat.info() << "Path to dtool: " << dtool_name << "\n"; + if (lib_path != nullptr) { + string dtool_name = string(lib_path) + "/libp3dtool.so"; + ExecutionEnvironment::set_dtool_name(dtool_name); + android_cat.info() << "Path to dtool: " << dtool_name << "\n"; - env->ReleaseStringUTFChars(libdir, lib_path); + env->ReleaseStringUTFChars(libdir, lib_path); + } + } // Get the path to the APK. jmethodID methodID = env->GetMethodID(activity_class, "getPackageCodePath", "()Ljava/lang/String;"); jstring code_path = (jstring) env->CallObjectMethod(activity->clazz, methodID); const char* apk_path; - apk_path = env->GetStringUTFChars(code_path, NULL); + apk_path = env->GetStringUTFChars(code_path, nullptr); + + // We're going to set this as binary name, which is better than the + // default (which refers to the zygote). Or should we set it to the + // native library? How do we get the path to that? android_cat.info() << "Path to APK: " << apk_path << "\n"; + ExecutionEnvironment::set_binary_name(apk_path); // Mount the assets directory. + Filename apk_fn(apk_path); PT(VirtualFileMountAndroidAsset) asset_mount; - asset_mount = new VirtualFileMountAndroidAsset(app->activity->assetManager, apk_path); + asset_mount = new VirtualFileMountAndroidAsset(app->activity->assetManager, apk_fn); VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); - vfs->mount(asset_mount, "/android_asset", 0); + + Filename asset_dir(apk_fn.get_dirname(), "assets"); + vfs->mount(asset_mount, asset_dir, 0); // Release the apk_path. env->ReleaseStringUTFChars(code_path, apk_path); // Now add the asset directory to the model-path. - get_model_path().append_directory("/android_asset"); + //TODO: prevent it from adding the directory multiple times. + get_model_path().append_directory(asset_dir); // Create bogus argc and argv, then call our main function. char *argv[] = {NULL}; From e04cb17a30e88b4631f1817f0d218f91b400c439 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 29 Jan 2018 19:57:01 +0100 Subject: [PATCH 3/8] makepanda: change Android build model We no longer copy libs to a separate libs dir to entertain Ant (which is no longer the build system of choice on Android). Also, rather than copying the Java sources to built/src, we now compile them and put the classes in built/classes. Furthermore, executables are really compiled as executables now (rather than as libraries) to allow building and running Panda in termux. --- makepanda/makepanda.py | 68 ++++++++++++++++++++++---------------- makepanda/makepandacore.py | 26 ++------------- 2 files changed, 43 insertions(+), 51 deletions(-) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index c3856fcaed..b00c947208 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -943,7 +943,7 @@ if (COMPILER=="GCC"): if GetTarget() == 'android': LibName("ALWAYS", '-llog') - LibName("ALWAYS", '-landroid') + LibName("ANDROID", '-landroid') LibName("JNIGRAPHICS", '-ljnigraphics') for pkg in MAYAVERSIONS: @@ -1704,8 +1704,11 @@ def CompileLink(dll, obj, opts): if COMPILER == "GCC": cxx = GetCXX() - if GetOrigExt(dll) == ".exe" and GetTarget() != 'android': + if GetOrigExt(dll) == ".exe": cmd = cxx + ' -o ' + dll + ' -L' + GetOutputDir() + '/lib -L' + GetOutputDir() + '/tmp' + if GetTarget() == "android": + # Necessary to work around an issue with libandroid depending on vendor libraries + cmd += ' -Wl,--allow-shlib-undefined' else: if (GetTarget() == "darwin"): cmd = cxx + ' -undefined dynamic_lookup' @@ -1718,6 +1721,7 @@ def CompileLink(dll, obj, opts): cmd += ' -o ' + dll + ' -L' + GetOutputDir() + '/lib -L' + GetOutputDir() + '/tmp' else: cmd = cxx + ' -shared' + # Always set soname on Android to avoid a linker warning when loading the library. if "MODULE" not in opts or GetTarget() == 'android': cmd += " -Wl,-soname=" + os.path.basename(dll) cmd += ' -o ' + dll + ' -L' + GetOutputDir() + '/lib -L' + GetOutputDir() + '/tmp' @@ -1774,14 +1778,7 @@ def CompileLink(dll, obj, opts): oscmd(cmd) - if GetTarget() == 'android': - # Copy the library to built/libs/$ANDROID_ABI and strip it. - # This is the format that Android NDK projects should use. - new_path = '%s/libs/%s/%s' % (GetOutputDir(), SDK["ANDROID_ABI"], os.path.basename(dll)) - CopyFile(new_path, dll) - oscmd('%s --strip-unneeded %s' % (GetStrip(), BracketNameWithQuotes(new_path))) - - elif (GetOptimizeOption(opts)==4 and GetTarget() == 'linux'): + if GetOptimizeOption(opts) == 4 and GetTarget() in ('linux', 'android'): oscmd(GetStrip() + " --strip-unneeded " + BracketNameWithQuotes(dll)) os.system("chmod +x " + BracketNameWithQuotes(dll)) @@ -1890,6 +1887,25 @@ def CompileRsrc(target, src, opts): cmd += " " + BracketNameWithQuotes(src) oscmd(cmd) +########################################################################################## +# +# CompileJava (Android only) +# +########################################################################################## + +def CompileJava(target, src, opts): + """Compiles a .java file into a .class file.""" + cmd = "ecj " + + optlevel = GetOptimizeOption(opts) + if optlevel >= 4: + cmd += "-debug:none " + + cmd += "-cp " + GetOutputDir() + "/classes " + cmd += "-d " + GetOutputDir() + "/classes " + cmd += BracketNameWithQuotes(src) + oscmd(cmd) + ########################################################################################## # # FreezePy @@ -2143,6 +2159,9 @@ def CompileAnything(target, inputs, opts, progress = None): elif (origsuffix==".rsrc"): ProgressOutput(progress, "Building resource object", target) return CompileRsrc(target, infile, opts) + elif (origsuffix==".class"): + ProgressOutput(progress, "Building Java class", target) + return CompileJava(target, infile, opts) elif (origsuffix==".obj"): if (infile.endswith(".cxx")): ProgressOutput(progress, "Building C++ object", target) @@ -3233,15 +3252,6 @@ if (PkgSkip("CONTRIB")==0): CopyAllHeaders('contrib/src/contribbase') CopyAllHeaders('contrib/src/ai') -######################################################################## -# -# Copy Java files, if applicable -# -######################################################################## - -if GetTarget() == 'android': - CopyAllJavaSources('panda/src/android') - ######################################################################## # # These definitions are syntactic shorthand. They make it easy @@ -3561,7 +3571,7 @@ TargetAdd('libpandaexpress.dll', input='p3express_composite1.obj') TargetAdd('libpandaexpress.dll', input='p3express_composite2.obj') TargetAdd('libpandaexpress.dll', input='p3pandabase_pandabase.obj') TargetAdd('libpandaexpress.dll', input=COMMON_DTOOL_LIBS) -TargetAdd('libpandaexpress.dll', opts=['ADVAPI', 'WINSOCK2', 'OPENSSL', 'ZLIB', 'WINGDI', 'WINUSER']) +TargetAdd('libpandaexpress.dll', opts=['ADVAPI', 'WINSOCK2', 'OPENSSL', 'ZLIB', 'WINGDI', 'WINUSER', 'ANDROID']) # # DIRECTORY: panda/src/pipeline/ @@ -5059,6 +5069,8 @@ if (not RTDIST and not RUNTIME and PkgSkip("PVIEW")==0 and GetTarget() != 'andro if (not RUNTIME and GetTarget() == 'android'): OPTS=['DIR:panda/src/android'] + TargetAdd('org/panda3d/android/NativeIStream.class', opts=OPTS, input='NativeIStream.java') + TargetAdd('org/panda3d/android/PandaActivity.class', opts=OPTS, input='PandaActivity.java', dep='org/panda3d/android/NativeIStream.class') TargetAdd('p3android_composite1.obj', opts=OPTS, input='p3android_composite1.cxx') TargetAdd('libp3android.dll', input='p3android_composite1.obj') @@ -5070,15 +5082,15 @@ if (not RUNTIME and GetTarget() == 'android'): if (not RTDIST and PkgSkip("PVIEW")==0): TargetAdd('pview_pview.obj', opts=OPTS, input='pview.cxx') - TargetAdd('pview.exe', input='android_native_app_glue.obj') - TargetAdd('pview.exe', input='android_main.obj') - TargetAdd('pview.exe', input='pview_pview.obj') - TargetAdd('pview.exe', input='libp3framework.dll') + TargetAdd('libpview.dll', input='android_native_app_glue.obj') + TargetAdd('libpview.dll', input='android_main.obj') + TargetAdd('libpview.dll', input='pview_pview.obj') + TargetAdd('libpview.dll', input='libp3framework.dll') if not PkgSkip("EGG"): - TargetAdd('pview.exe', input='libpandaegg.dll') - TargetAdd('pview.exe', input='libp3android.dll') - TargetAdd('pview.exe', input=COMMON_PANDA_LIBS) - TargetAdd('AndroidManifest.xml', opts=OPTS, input='pview_manifest.xml') + TargetAdd('libpview.dll', input='libpandaegg.dll') + TargetAdd('libpview.dll', input='libp3android.dll') + TargetAdd('libpview.dll', input=COMMON_PANDA_LIBS) + TargetAdd('libpview.dll', opts=['MODULE', 'ANDROID']) # # DIRECTORY: panda/src/androiddisplay/ diff --git a/makepanda/makepandacore.py b/makepanda/makepandacore.py index 8c989f3d2c..75211d3979 100644 --- a/makepanda/makepandacore.py +++ b/makepanda/makepandacore.py @@ -1145,12 +1145,7 @@ def MakeBuildTree(): MakeDirectory(OUTPUTDIR + "/Frameworks") elif GetTarget() == 'android': - MakeDirectory(OUTPUTDIR + "/libs") - MakeDirectory(OUTPUTDIR + "/libs/" + ANDROID_ABI) - MakeDirectory(OUTPUTDIR + "/src") - MakeDirectory(OUTPUTDIR + "/src/org") - MakeDirectory(OUTPUTDIR + "/src/org/panda3d") - MakeDirectory(OUTPUTDIR + "/src/org/panda3d/android") + MakeDirectory(OUTPUTDIR + "/classes") ######################################################################## # @@ -2892,14 +2887,6 @@ def CopyAllHeaders(dir, skip=[]): WriteBinaryFile(dstfile, ReadBinaryFile(srcfile)) JustBuilt([dstfile], [srcfile]) -def CopyAllJavaSources(dir, skip=[]): - for filename in GetDirectoryContents(dir, ["*.java"], skip): - srcfile = dir + "/" + filename - dstfile = OUTPUTDIR + "/src/org/panda3d/android/" + filename - if (NeedsBuild([dstfile], [srcfile])): - WriteBinaryFile(dstfile, ReadBinaryFile(srcfile)) - JustBuilt([dstfile], [srcfile]) - def CopyTree(dstdir, srcdir, omitVCS=True): if os.path.isdir(dstdir): source_entries = os.listdir(srcdir) @@ -3147,6 +3134,7 @@ def CalcLocation(fn, ipath): if fn.startswith("panda3d/") and fn.endswith(".py"): return OUTPUTDIR + "/" + fn + if (fn.endswith(".class")):return OUTPUTDIR+"/classes/"+fn if (fn.count("/")): return fn dllext = "" target = GetTarget() @@ -3162,6 +3150,7 @@ def CalcLocation(fn, ipath): if (fn.endswith(".lxx")): return CxxFindSource(fn, ipath) if (fn.endswith(".pdef")):return CxxFindSource(fn, ipath) if (fn.endswith(".xml")): return CxxFindSource(fn, ipath) + if (fn.endswith(".java")):return CxxFindSource(fn, ipath) if (fn.endswith(".egg")): return OUTPUTDIR+"/models/"+fn if (fn.endswith(".egg.pz")):return OUTPUTDIR+"/models/"+fn if (fn.endswith(".pyd")): return OUTPUTDIR+"/panda3d/"+fn[:-4]+GetExtensionSuffix() @@ -3197,15 +3186,6 @@ def CalcLocation(fn, ipath): if (fn.endswith(".rsrc")): return OUTPUTDIR+"/tmp/"+fn if (fn.endswith(".plugin")):return OUTPUTDIR+"/plugins/"+fn if (fn.endswith(".app")): return OUTPUTDIR+"/bin/"+fn - elif (target == 'android'): - # On Android, we build the libraries into built/tmp, then copy them. - if (fn.endswith(".obj")): return OUTPUTDIR+"/tmp/"+fn[:-4]+".o" - if (fn.endswith(".dll")): return OUTPUTDIR+"/tmp/"+fn[:-4]+".so" - if (fn.endswith(".mll")): return OUTPUTDIR+"/plugins/"+fn - if (fn.endswith(".plugin")):return OUTPUTDIR+"/plugins/"+fn[:-7]+dllext+".so" - if (fn.endswith(".exe")): return OUTPUTDIR+"/tmp/lib"+fn[:-4]+".so" - if (fn.endswith(".lib")): return OUTPUTDIR+"/tmp/"+fn[:-4]+".a" - if (fn.endswith(".ilb")): return OUTPUTDIR+"/tmp/"+fn[:-4]+".a" else: if (fn.endswith(".obj")): return OUTPUTDIR+"/tmp/"+fn[:-4]+".o" if (fn.endswith(".dll")): return OUTPUTDIR+"/lib/"+fn[:-4]+".so" From 0fa8980be2fd01af38f446201ef0b97603c05319 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 29 Jan 2018 20:04:14 +0100 Subject: [PATCH 4/8] android: fix activity lifecycle issues (froze upon quit or resume) It seems Android doesn't want an application to just quit on its own accord; after main() returns we need to kindly request Android to finish the activity and keep handling events until Android destroys the app. --- panda/src/android/android_main.cxx | 45 +++++++++++++++++-- .../androiddisplay/androidGraphicsWindow.cxx | 7 +++ 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/panda/src/android/android_main.cxx b/panda/src/android/android_main.cxx index 6626817410..32c692489f 100644 --- a/panda/src/android/android_main.cxx +++ b/panda/src/android/android_main.cxx @@ -105,10 +105,49 @@ void android_main(struct android_app* app) { //TODO: prevent it from adding the directory multiple times. get_model_path().append_directory(asset_dir); - // Create bogus argc and argv, then call our main function. - char *argv[] = {NULL}; + // Create bogus argc and argv for calling the main function. + char *argv[] = {nullptr}; int argc = 0; - main(argc, argv); + + while (!app->destroyRequested) { + // Call the main function. This will not return until the app is done. + android_cat.info() << "Calling main()\n"; + main(argc, argv); + + if (app->destroyRequested) { + // The app closed responding to a destroy request. + break; + } + + // Ask Android to clean up the activity. + android_cat.info() << "Exited from main(), finishing activity\n"; + ANativeActivity_finish(activity); + + // We still need to keep an event loop going until Android gives us leave + // to end the process. + int looper_id; + int events; + struct android_poll_source *source; + while ((looper_id = ALooper_pollAll(-1, nullptr, &events, (void**)&source)) >= 0) { + // Process this event, but intercept application command events. + if (looper_id == LOOPER_ID_MAIN) { + int8_t cmd = android_app_read_cmd(app); + android_app_pre_exec_cmd(app, cmd); + android_app_post_exec_cmd(app, cmd); + + // I don't think we can get a resume command after we call finish(), + // but let's handle it just in case. + if (cmd == APP_CMD_RESUME || + cmd == APP_CMD_DESTROY) { + break; + } + } else if (source != nullptr) { + source->process(app, source); + } + } + } + + android_cat.info() << "Destroy requested, exiting from android_main\n"; // Detach the thread before exiting. activity->vm->DetachCurrentThread(); diff --git a/panda/src/androiddisplay/androidGraphicsWindow.cxx b/panda/src/androiddisplay/androidGraphicsWindow.cxx index 946e602aeb..ba875fb46d 100644 --- a/panda/src/androiddisplay/androidGraphicsWindow.cxx +++ b/panda/src/androiddisplay/androidGraphicsWindow.cxx @@ -246,6 +246,13 @@ close_window() { } GraphicsWindow::close_window(); + + nassertv(_app != nullptr); + if (_app->userData == this) { + _app->userData = nullptr; + _app->onAppCmd = nullptr; + _app->onInputEvent = nullptr; + } } /** From 18afcdbd0ab33e355526f036ffe96d790149b6d2 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 29 Jan 2018 20:09:39 +0100 Subject: [PATCH 5/8] android: handle right mouse button, more external keyboard keys --- .../androiddisplay/androidGraphicsWindow.cxx | 88 +++++++++++++++++-- .../androiddisplay/androidGraphicsWindow.h | 2 + 2 files changed, 84 insertions(+), 6 deletions(-) diff --git a/panda/src/androiddisplay/androidGraphicsWindow.cxx b/panda/src/androiddisplay/androidGraphicsWindow.cxx index ba875fb46d..d459f56339 100644 --- a/panda/src/androiddisplay/androidGraphicsWindow.cxx +++ b/panda/src/androiddisplay/androidGraphicsWindow.cxx @@ -44,7 +44,8 @@ AndroidGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe, int flags, GraphicsStateGuardian *gsg, GraphicsOutput *host) : - GraphicsWindow(engine, pipe, name, fb_prop, win_prop, flags, gsg, host) + GraphicsWindow(engine, pipe, name, fb_prop, win_prop, flags, gsg, host), + _mouse_button_state(0) { AndroidGraphicsPipe *android_pipe; DCAST_INTO_V(android_pipe, _pipe); @@ -533,10 +534,29 @@ handle_motion_event(const AInputEvent *event) { int32_t action = AMotionEvent_getAction(event); action &= AMOTION_EVENT_ACTION_MASK; - if (action == AMOTION_EVENT_ACTION_DOWN) { - _input_devices[0].button_down(MouseButton::one()); - } else if (action == AMOTION_EVENT_ACTION_UP) { - _input_devices[0].button_up(MouseButton::one()); + if (action == AMOTION_EVENT_ACTION_DOWN || + action == AMOTION_EVENT_ACTION_UP) { + // The up event doesn't let us know which button is up, so we need to + // keep track of the button state ourselves. + int32_t button_state = AMotionEvent_getButtonState(event); + int32_t changed = _mouse_button_state ^ button_state; + if (changed != 0) { + if (changed & AMOTION_EVENT_BUTTON_PRIMARY) { + if (button_state & AMOTION_EVENT_BUTTON_PRIMARY) { + _input_devices[0].button_down(MouseButton::one()); + } else { + _input_devices[0].button_up(MouseButton::one()); + } + } + if (changed & AMOTION_EVENT_BUTTON_SECONDARY) { + if (button_state & AMOTION_EVENT_BUTTON_SECONDARY) { + _input_devices[0].button_down(MouseButton::three()); + } else { + _input_devices[0].button_up(MouseButton::three()); + } + } + _mouse_button_state = button_state; + } } float x = AMotionEvent_getX(event, 0) - _app->contentRect.left; @@ -675,7 +695,7 @@ map_button(int32_t keycode) { case AKEYCODE_ENTER: return KeyboardButton::enter(); case AKEYCODE_DEL: - return KeyboardButton::del(); + return KeyboardButton::backspace(); case AKEYCODE_GRAVE: return KeyboardButton::ascii_key('`'); case AKEYCODE_MINUS: @@ -703,6 +723,7 @@ map_button(int32_t keycode) { case AKEYCODE_PLUS: return KeyboardButton::ascii_key('+'); case AKEYCODE_MENU: + return KeyboardButton::menu(); case AKEYCODE_NOTIFICATION: case AKEYCODE_SEARCH: case AKEYCODE_MEDIA_PLAY_PAUSE: @@ -734,6 +755,61 @@ map_button(int32_t keycode) { case AKEYCODE_BUTTON_START: case AKEYCODE_BUTTON_SELECT: case AKEYCODE_BUTTON_MODE: + break; + case AKEYCODE_ESCAPE: + return KeyboardButton::escape(); + case AKEYCODE_FORWARD_DEL: + return KeyboardButton::del(); + case AKEYCODE_CTRL_LEFT: + return KeyboardButton::lcontrol(); + case AKEYCODE_CTRL_RIGHT: + return KeyboardButton::rcontrol(); + case AKEYCODE_CAPS_LOCK: + return KeyboardButton::caps_lock(); + case AKEYCODE_SCROLL_LOCK: + return KeyboardButton::scroll_lock(); + case AKEYCODE_META_LEFT: + return KeyboardButton::lmeta(); + case AKEYCODE_META_RIGHT: + return KeyboardButton::rmeta(); + case AKEYCODE_FUNCTION: + break; + case AKEYCODE_SYSRQ: + return KeyboardButton::print_screen(); + case AKEYCODE_BREAK: + return KeyboardButton::pause(); + case AKEYCODE_MOVE_HOME: + return KeyboardButton::home(); + case AKEYCODE_MOVE_END: + return KeyboardButton::end(); + case AKEYCODE_INSERT: + return KeyboardButton::insert(); + case AKEYCODE_F1: + return KeyboardButton::f1(); + case AKEYCODE_F2: + return KeyboardButton::f2(); + case AKEYCODE_F3: + return KeyboardButton::f3(); + case AKEYCODE_F4: + return KeyboardButton::f4(); + case AKEYCODE_F5: + return KeyboardButton::f5(); + case AKEYCODE_F6: + return KeyboardButton::f6(); + case AKEYCODE_F7: + return KeyboardButton::f7(); + case AKEYCODE_F8: + return KeyboardButton::f8(); + case AKEYCODE_F9: + return KeyboardButton::f9(); + case AKEYCODE_F10: + return KeyboardButton::f10(); + case AKEYCODE_F11: + return KeyboardButton::f11(); + case AKEYCODE_F12: + return KeyboardButton::f12(); + case AKEYCODE_NUM_LOCK: + return KeyboardButton::num_lock(); default: break; } diff --git a/panda/src/androiddisplay/androidGraphicsWindow.h b/panda/src/androiddisplay/androidGraphicsWindow.h index 10ce6de983..3d1ca79946 100644 --- a/panda/src/androiddisplay/androidGraphicsWindow.h +++ b/panda/src/androiddisplay/androidGraphicsWindow.h @@ -71,6 +71,8 @@ private: EGLDisplay _egl_display; EGLSurface _egl_surface; + int32_t _mouse_button_state; + const ARect *rect; public: From b562aba4e0f423446b8d269929b004591d4b6998 Mon Sep 17 00:00:00 2001 From: nosyliam Date: Fri, 2 Feb 2018 13:40:11 -0800 Subject: [PATCH 6/8] Support static linking with FMOD Closes #241 --- panda/src/audiotraits/config_fmodAudio.cxx | 2 ++ panda/src/audiotraits/config_fmodAudio.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/panda/src/audiotraits/config_fmodAudio.cxx b/panda/src/audiotraits/config_fmodAudio.cxx index 0726118121..affc593636 100644 --- a/panda/src/audiotraits/config_fmodAudio.cxx +++ b/panda/src/audiotraits/config_fmodAudio.cxx @@ -51,6 +51,8 @@ init_libFmodAudio() { FmodAudioManager::init_type(); FmodAudioSound::init_type(); + AudioManager::register_AudioManager_creator(&Create_FmodAudioManager); + PandaSystem *ps = PandaSystem::get_global_ptr(); ps->add_system("FMOD"); ps->add_system("audio"); diff --git a/panda/src/audiotraits/config_fmodAudio.h b/panda/src/audiotraits/config_fmodAudio.h index 79e221ff31..336f9257d4 100644 --- a/panda/src/audiotraits/config_fmodAudio.h +++ b/panda/src/audiotraits/config_fmodAudio.h @@ -24,7 +24,7 @@ NotifyCategoryDecl(fmodAudio, EXPCL_FMOD_AUDIO, EXPTP_FMOD_AUDIO); extern ConfigVariableInt fmod_audio_preload_threshold; -extern EXPCL_FMOD_AUDIO void init_libFmodAudio(); +extern "C" EXPCL_FMOD_AUDIO void init_libFmodAudio(); extern "C" EXPCL_FMOD_AUDIO Create_AudioManager_proc *get_audio_manager_func_fmod_audio(); #endif // CONFIG_FMODAUDIO_H From ce79656141694e0e8c3477215f8bd5ac7207b4e6 Mon Sep 17 00:00:00 2001 From: deflected Date: Sun, 28 Jan 2018 20:52:43 +0200 Subject: [PATCH 7/8] bullet: Fixed crash when rendering bulletDebugNode - Fixed crash when rendering bulletDebugNode without calls to doPhysics. This is caused by _debug_world pointing to invalid memory, while _debug_stale is true when bulletDebugNode is initialized. Signed-off-by: deflected --- panda/src/bullet/bulletDebugNode.cxx | 4 +++- panda/src/bullet/bulletWorld.cxx | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/panda/src/bullet/bulletDebugNode.cxx b/panda/src/bullet/bulletDebugNode.cxx index b4575dd3cf..9b8c9c0bfb 100644 --- a/panda/src/bullet/bulletDebugNode.cxx +++ b/panda/src/bullet/bulletDebugNode.cxx @@ -31,8 +31,10 @@ PStatCollector BulletDebugNode::_pstat_debug("App:Bullet:DoPhysics:Debug"); * */ BulletDebugNode:: -BulletDebugNode(const char *name) : PandaNode(name), _debug_stale(true) { +BulletDebugNode(const char *name) : PandaNode(name) { + _debug_stale = false; + _debug_world = nullptr; _wireframe = true; _constraints = true; _bounds = false; diff --git a/panda/src/bullet/bulletWorld.cxx b/panda/src/bullet/bulletWorld.cxx index a7942aee02..d60339f360 100644 --- a/panda/src/bullet/bulletWorld.cxx +++ b/panda/src/bullet/bulletWorld.cxx @@ -134,6 +134,7 @@ void BulletWorld:: clear_debug_node() { if (_debug != nullptr) { LightMutexHolder holder(_debug->_lock); + _debug->_debug_stale = false; _debug->_debug_world = nullptr; _world->setDebugDrawer(nullptr); _debug = nullptr; From 50dafd087d18b870188287f9b3a55d3577ba6c41 Mon Sep 17 00:00:00 2001 From: deflected Date: Fri, 2 Feb 2018 11:23:37 +0200 Subject: [PATCH 8/8] bullet: Fixed calculating of Box dimensions - Fixed wrong claculation of box dimensions, when creating BoxShape from solids Signed-off-by: deflected --- panda/src/bullet/bulletBoxShape.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/panda/src/bullet/bulletBoxShape.cxx b/panda/src/bullet/bulletBoxShape.cxx index 02b5af45b3..f523184993 100644 --- a/panda/src/bullet/bulletBoxShape.cxx +++ b/panda/src/bullet/bulletBoxShape.cxx @@ -64,9 +64,9 @@ make_from_solid(const CollisionBox *solid) { LPoint3 p0 = solid->get_min(); LPoint3 p1 = solid->get_max(); - LVecBase3 extents(p1.get_x() - p0.get_x() / 2.0, - p1.get_y() - p0.get_y() / 2.0, - p1.get_z() - p0.get_z() / 2.0); + LVecBase3 extents((p1.get_x() - p0.get_x()) / 2.0, + (p1.get_y() - p0.get_y()) / 2.0, + (p1.get_z() - p0.get_z()) / 2.0); return new BulletBoxShape(extents); }