diff options
Diffstat (limited to 'platform')
-rw-r--r-- | platform/android/AndroidManifest.xml.template | 3 | ||||
-rw-r--r-- | platform/android/export/export.cpp | 10 | ||||
-rw-r--r-- | platform/android/java_glue.cpp | 27 | ||||
-rw-r--r-- | platform/iphone/SCsub | 7 | ||||
-rw-r--r-- | platform/iphone/power_iphone.cpp | 2 | ||||
-rw-r--r-- | platform/javascript/SCsub | 49 | ||||
-rw-r--r-- | platform/javascript/detect.py | 127 | ||||
-rw-r--r-- | platform/javascript/engine.js | 40 | ||||
-rw-r--r-- | platform/javascript/http_client_javascript.cpp | 2 | ||||
-rw-r--r-- | platform/javascript/javascript_main.cpp | 2 | ||||
-rw-r--r-- | platform/javascript/os_javascript.cpp | 19 | ||||
-rw-r--r-- | platform/javascript/os_javascript.h | 3 | ||||
-rw-r--r-- | platform/javascript/power_javascript.cpp | 73 | ||||
-rw-r--r-- | platform/javascript/power_javascript.h | 53 | ||||
-rw-r--r-- | platform/javascript/pre.js | 2 | ||||
-rw-r--r-- | platform/osx/detect.py | 1 | ||||
-rw-r--r-- | platform/osx/godot_main_osx.mm | 2 | ||||
-rw-r--r-- | platform/osx/os_osx.h | 2 | ||||
-rw-r--r-- | platform/osx/os_osx.mm | 115 | ||||
-rw-r--r-- | platform/uwp/detect.py | 2 | ||||
-rw-r--r-- | platform/windows/os_windows.cpp | 13 | ||||
-rw-r--r-- | platform/x11/detect.py | 4 | ||||
-rw-r--r-- | platform/x11/os_x11.cpp | 10 |
23 files changed, 311 insertions, 257 deletions
diff --git a/platform/android/AndroidManifest.xml.template b/platform/android/AndroidManifest.xml.template index a42ceb3c21..3e42b7a3cd 100644 --- a/platform/android/AndroidManifest.xml.template +++ b/platform/android/AndroidManifest.xml.template @@ -16,7 +16,8 @@ android:theme="@android:style/Theme.NoTitleBar.Fullscreen" android:launchMode="singleTask" android:screenOrientation="landscape" - android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize"> + android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize" + android:resizeableActivity="false"> <intent-filter> <action android:name="android.intent.action.MAIN" /> diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index 6b4d0ff8c4..6d9f0a7e9a 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -301,8 +301,7 @@ class EditorExportAndroid : public EditorExportPlatform { args.push_back("-s"); args.push_back(d.id); args.push_back("shell"); - args.push_back("cat"); - args.push_back("/system/build.prop"); + args.push_back("getprop"); int ec; String dp; @@ -315,7 +314,14 @@ class EditorExportAndroid : public EditorExportPlatform { d.api_level = 0; for (int j = 0; j < props.size(); j++) { + // got information by `shell cat /system/build.prop` before and its format is "property=value" + // it's now changed to use `shell getporp` because of permission issue with Android 8.0 and above + // its format is "[property]: [value]" so changed it as like build.prop String p = props[j]; + p = p.replace("]: ", "="); + p = p.replace("[", ""); + p = p.replace("]", ""); + if (p.begins_with("ro.product.model=")) { device = p.get_slice("=", 1).strip_edges(); } else if (p.begins_with("ro.product.brand=")) { diff --git a/platform/android/java_glue.cpp b/platform/android/java_glue.cpp index 9baf58c3eb..579c06f76b 100644 --- a/platform/android/java_glue.cpp +++ b/platform/android/java_glue.cpp @@ -936,6 +936,9 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *en } JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_back(JNIEnv *env, jobject obj) { + if (step == 0) + return; + os_android->main_loop_request_go_back(); } @@ -976,6 +979,9 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, job JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch(JNIEnv *env, jobject obj, jint ev, jint pointer, jint count, jintArray positions) { + if (step == 0) + return; + Vector<OS_Android::TouchPos> points; for (int i = 0; i < count; i++) { @@ -1250,6 +1256,8 @@ static unsigned int android_get_keysym(unsigned int p_code) { } JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joybutton(JNIEnv *env, jobject obj, jint p_device, jint p_button, jboolean p_pressed) { + if (step == 0) + return; OS_Android::JoypadEvent jevent; jevent.device = p_device; @@ -1261,6 +1269,8 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joybutton(JNIEnv *env } JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv *env, jobject obj, jint p_device, jint p_axis, jfloat p_value) { + if (step == 0) + return; OS_Android::JoypadEvent jevent; jevent.device = p_device; @@ -1272,6 +1282,9 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv *env, } JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyhat(JNIEnv *env, jobject obj, jint p_device, jint p_hat_x, jint p_hat_y) { + if (step == 0) + return; + OS_Android::JoypadEvent jevent; jevent.device = p_device; jevent.type = OS_Android::JOY_EVENT_HAT; @@ -1301,6 +1314,8 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyconnectionchanged( } JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv *env, jobject obj, jint p_scancode, jint p_unicode_char, jboolean p_pressed) { + if (step == 0) + return; Ref<InputEventKey> ievent; ievent.instance(); @@ -1344,14 +1359,18 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_gyroscope(JNIEnv *env JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_focusin(JNIEnv *env, jobject obj) { - if (os_android && step > 0) - os_android->main_loop_focusin(); + if (step == 0) + return; + + os_android->main_loop_focusin(); } JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_focusout(JNIEnv *env, jobject obj) { - if (os_android && step > 0) - os_android->main_loop_focusout(); + if (step == 0) + return; + + os_android->main_loop_focusout(); } JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_audio(JNIEnv *env, jobject obj) { diff --git a/platform/iphone/SCsub b/platform/iphone/SCsub index 6b5f30dc41..b96bec16b4 100644 --- a/platform/iphone/SCsub +++ b/platform/iphone/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +import os Import('env') @@ -21,6 +22,10 @@ ios_lib = env_ios.add_library('iphone', iphone_lib) def combine_libs(target=None, source=None, env=None): lib_path = target[0].srcnode().abspath - env.Execute('$IPHONEPATH/usr/bin/libtool -static -o "' + lib_path + '" ' + ' '.join([('"' + lib.srcnode().abspath + '"') for lib in source])) + if ("OSXCROSS_IOS" in os.environ): + libtool = '$IPHONEPATH/usr/bin/${ios_triple}libtool' + else: + libtool = "$IPHONEPATH/usr/bin/libtool" + env.Execute(libtool + ' -static -o "' + lib_path + '" ' + ' '.join([('"' + lib.srcnode().abspath + '"') for lib in source])) combine_command = env_ios.Command('#bin/libgodot' + env_ios['LIBSUFFIX'], [ios_lib] + env_ios['LIBS'], combine_libs) diff --git a/platform/iphone/power_iphone.cpp b/platform/iphone/power_iphone.cpp index 95a9aa9705..7f9dadc363 100644 --- a/platform/iphone/power_iphone.cpp +++ b/platform/iphone/power_iphone.cpp @@ -30,7 +30,7 @@ #include "power_iphone.h" -bool OS::PowerState::UpdatePowerInfo() { +bool PowerIphone::UpdatePowerInfo() { return false; } diff --git a/platform/javascript/SCsub b/platform/javascript/SCsub index 66a8a8d93c..5991075e29 100644 --- a/platform/javascript/SCsub +++ b/platform/javascript/SCsub @@ -3,38 +3,35 @@ Import('env') javascript_files = [ - "os_javascript.cpp", - "audio_driver_javascript.cpp", - "javascript_main.cpp", - "power_javascript.cpp", - "http_client_javascript.cpp", - "javascript_eval.cpp", + 'audio_driver_javascript.cpp', + 'http_client_javascript.cpp', + 'javascript_eval.cpp', + 'javascript_main.cpp', + 'os_javascript.cpp', ] -env_javascript = env.Clone() -if env['target'] == "profile": - env_javascript.Append(CPPFLAGS=['-DPROFILER_ENABLED']) - -javascript_objects = [] -for x in javascript_files: - javascript_objects.append(env_javascript.Object(x)) - -env.Append(LINKFLAGS=["-s", "EXPORTED_FUNCTIONS=\"['_main','_main_after_fs_sync','_send_notification']\""]) - -target_dir = env.Dir("#bin") -build = env.add_program(['#bin/godot', target_dir.File('godot' + env['PROGSUFFIX'] + '.wasm')], javascript_objects, PROGSUFFIX=env['PROGSUFFIX'] + '.js'); +build = env.add_program(['#bin/godot${PROGSUFFIX}.js', '#bin/godot${PROGSUFFIX}.wasm'], javascript_files); js, wasm = build -js_libraries = [] -js_libraries.append(env.File('http_request.js')) +js_libraries = [ + 'http_request.js', +] for lib in js_libraries: - env.Append(LINKFLAGS=['--js-library', lib.path]) + env.Append(LINKFLAGS=['--js-library', env.File(lib).path]) env.Depends(build, js_libraries) wrapper_start = env.File('pre.js') wrapper_end = env.File('engine.js') -js_final = env.Textfile('#bin/godot', [wrapper_start, js, wrapper_end], TEXTFILESUFFIX=env['PROGSUFFIX'] + '.wrapped.js') - -zip_dir = target_dir.Dir('.javascript_zip') -zip_files = env.InstallAs([zip_dir.File('godot.js'), zip_dir.File('godot.wasm'), zip_dir.File('godot.html')], [js_final, wasm, '#misc/dist/html/default.html']) -Zip('#bin/godot', zip_files, ZIPSUFFIX=env['PROGSUFFIX'] + env['ZIPSUFFIX'], ZIPROOT=zip_dir, ZIPCOMSTR="Archving $SOURCES as $TARGET") +js_wrapped = env.Textfile('#bin/godot', [wrapper_start, js, wrapper_end], TEXTFILESUFFIX='${PROGSUFFIX}.wrapped.js') + +zip_dir = env.Dir('#bin/.javascript_zip') +zip_files = env.InstallAs([ + zip_dir.File('godot.js'), + zip_dir.File('godot.wasm'), + zip_dir.File('godot.html') +], [ + js_wrapped, + wasm, + '#misc/dist/html/default.html' +]) +env.Zip('#bin/godot', zip_files, ZIPROOT=zip_dir, ZIPSUFFIX='${PROGSUFFIX}${ZIPSUFFIX}', ZIPCOMSTR='Archving $SOURCES as $TARGET') diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py index 7e6a1518ed..a48cb872ee 100644 --- a/platform/javascript/detect.py +++ b/platform/javascript/detect.py @@ -8,23 +8,22 @@ def is_active(): def get_name(): - return "JavaScript" + return 'JavaScript' def can_build(): - - return ("EMSCRIPTEN_ROOT" in os.environ or "EMSCRIPTEN" in os.environ) + return 'EM_CONFIG' in os.environ or os.path.exists(os.path.expanduser('~/.emscripten')) def get_opts(): from SCons.Variables import BoolVariable return [ + # eval() can be a security concern, so it can be disabled. BoolVariable('javascript_eval', 'Enable JavaScript eval interface', True), ] def get_flags(): - return [ ('tools', False), ('module_theora_enabled', False), @@ -36,24 +35,11 @@ def get_flags(): ] -def create(env): - - # remove Windows' .exe suffix - return env.Clone(tools=['textfile', 'zip'], PROGSUFFIX='') - - -def escape_sources_backslashes(target, source, env, for_signature): - return [path.replace('\\','\\\\') for path in env.GetBuildPath(source)] - -def escape_target_backslashes(target, source, env, for_signature): - return env.GetBuildPath(target[0]).replace('\\','\\\\') - - def configure(env): ## Build type - if (env["target"] == "release"): + if env['target'] == 'release' or env['target'] == 'profile': # Use -Os to prioritize optimizing for reduced file size. This is # particularly valuable for the web platform because it directly # decreases download time. @@ -62,65 +48,102 @@ def configure(env): # run-time performance. env.Append(CCFLAGS=['-Os']) env.Append(LINKFLAGS=['-Os']) - - elif (env["target"] == "release_debug"): - env.Append(CCFLAGS=['-O2', '-DDEBUG_ENABLED']) - env.Append(LINKFLAGS=['-O2', '-s', 'ASSERTIONS=1']) - # retain function names at the cost of file size, for backtraces and profiling + if env['target'] == 'profile': + env.Append(LINKFLAGS=['--profiling-funcs']) + + elif env['target'] == 'release_debug': + env.Append(CPPDEFINES=['DEBUG_ENABLED']) + env.Append(CCFLAGS=['-O2']) + env.Append(LINKFLAGS=['-O2']) + # Retain function names for backtraces at the cost of file size. env.Append(LINKFLAGS=['--profiling-funcs']) - elif (env["target"] == "debug"): - env.Append(CCFLAGS=['-O1', '-D_DEBUG', '-g', '-DDEBUG_ENABLED']) + elif env['target'] == 'debug': + env.Append(CPPDEFINES=['DEBUG_ENABLED']) + env.Append(CCFLAGS=['-O1', '-g']) env.Append(LINKFLAGS=['-O1', '-g']) + env.Append(LINKFLAGS=['-s', 'ASSERTIONS=1']) ## Compiler configuration env['ENV'] = os.environ - if ("EMSCRIPTEN_ROOT" in os.environ): - env.PrependENVPath('PATH', os.environ['EMSCRIPTEN_ROOT']) - elif ("EMSCRIPTEN" in os.environ): - env.PrependENVPath('PATH', os.environ['EMSCRIPTEN']) - env['CC'] = 'emcc' - env['CXX'] = 'em++' - env['LINK'] = 'emcc' - env['RANLIB'] = 'emranlib' - # Emscripten's ar has issues with duplicate file names, so use cc - env['AR'] = 'emcc' - env['ARFLAGS'] = '-o' - - if (os.name == 'nt'): - # use TempFileMunge on Windows since some commands get too long for - # cmd.exe even with spawn_fix - # need to escape backslashes for this - env['ESCAPED_SOURCES'] = escape_sources_backslashes - env['ESCAPED_TARGET'] = escape_target_backslashes - env['ARCOM'] = '${TEMPFILE("%s")}' % env['ARCOM'].replace('$SOURCES', '$ESCAPED_SOURCES').replace('$TARGET', '$ESCAPED_TARGET') + em_config_file = os.getenv('EM_CONFIG') or os.path.expanduser('~/.emscripten') + if not os.path.exists(em_config_file): + raise RuntimeError("Emscripten configuration file '%s' does not exist" % em_config_file) + with open(em_config_file) as f: + em_config = {} + try: + # Emscripten configuration file is a Python file with simple assignments. + exec(f.read(), em_config) + except StandardError as e: + raise RuntimeError("Emscripten configuration file '%s' is invalid:\n%s" % (em_config_file, e)) + if 'EMSCRIPTEN_ROOT' not in em_config: + raise RuntimeError("'EMSCRIPTEN_ROOT' missing in Emscripten configuration file '%s'" % em_config_file) + env.PrependENVPath('PATH', em_config['EMSCRIPTEN_ROOT']) + + env['CC'] = 'emcc' + env['CXX'] = 'em++' + env['LINK'] = 'emcc' + + # Emscripten's ar has issues with duplicate file names, so use cc. + env['AR'] = 'emcc' + env['ARFLAGS'] = '-o' + # emranlib is a noop, so it's safe to use with AR=emcc. + env['RANLIB'] = 'emranlib' + + # Use TempFileMunge since some AR invocations are too long for cmd.exe. + # Use POSIX-style paths, required with TempFileMunge. + env['ARCOM_POSIX'] = env['ARCOM'].replace( + '$TARGET', '$TARGET.posix').replace( + '$SOURCES', '$SOURCES.posix') + env['ARCOM'] = '${TEMPFILE(ARCOM_POSIX)}' + + # All intermediate files are just LLVM bitcode. + env['OBJPREFIX'] = '' env['OBJSUFFIX'] = '.bc' + env['PROGPREFIX'] = '' + # Program() output consists of multiple files, so specify suffixes manually at builder. + env['PROGSUFFIX'] = '' + env['LIBPREFIX'] = 'lib' env['LIBSUFFIX'] = '.bc' + env['LIBPREFIXES'] = ['$LIBPREFIX'] + env['LIBSUFFIXES'] = ['$LIBSUFFIX'] ## Compile flags env.Append(CPPPATH=['#platform/javascript']) - env.Append(CPPFLAGS=['-DJAVASCRIPT_ENABLED', '-DUNIX_ENABLED', '-DPTHREAD_NO_RENAME', '-DTYPED_METHOD_BIND', '-DNO_THREADS']) - env.Append(CPPFLAGS=['-DGLES3_ENABLED']) + env.Append(CPPDEFINES=['JAVASCRIPT_ENABLED', 'UNIX_ENABLED']) - # These flags help keep the file size down - env.Append(CPPFLAGS=["-fno-exceptions", '-DNO_SAFE_CAST', '-fno-rtti']) + # No multi-threading (SharedArrayBuffer) available yet, + # once feasible also consider memory buffer size issues. + env.Append(CPPDEFINES=['NO_THREADS']) + + # These flags help keep the file size down. + env.Append(CCFLAGS=['-fno-exceptions', '-fno-rtti']) + # Don't use dynamic_cast, necessary with no-rtti. + env.Append(CPPDEFINES=['NO_SAFE_CAST']) if env['javascript_eval']: - env.Append(CPPFLAGS=['-DJAVASCRIPT_EVAL_ENABLED']) + env.Append(CPPDEFINES=['JAVASCRIPT_EVAL_ENABLED']) ## Link flags env.Append(LINKFLAGS=['-s', 'BINARYEN=1']) + + # Allow increasing memory buffer size during runtime. This is efficient + # when using WebAssembly (in comparison to asm.js) and works well for + # us since we don't know requirements at compile-time. env.Append(LINKFLAGS=['-s', 'ALLOW_MEMORY_GROWTH=1']) + + # This setting just makes WebGL 2 APIs available, it does NOT disable WebGL 1. env.Append(LINKFLAGS=['-s', 'USE_WEBGL2=1']) - env.Append(LINKFLAGS=['-s', 'EXTRA_EXPORTED_RUNTIME_METHODS="[\'FS\']"']) env.Append(LINKFLAGS=['-s', 'INVOKE_RUN=0']) + + # TODO: Reevaluate usage of this setting now that engine.js manages engine runtime. env.Append(LINKFLAGS=['-s', 'NO_EXIT_RUNTIME=1']) - # TODO: Move that to opus module's config + # TODO: Move that to opus module's config. if 'module_opus_enabled' in env and env['module_opus_enabled']: - env.opus_fixed_point = "yes" + env.opus_fixed_point = 'yes' diff --git a/platform/javascript/engine.js b/platform/javascript/engine.js index e6fb48d0d2..e4839af433 100644 --- a/platform/javascript/engine.js +++ b/platform/javascript/engine.js @@ -1,3 +1,5 @@ + exposedLibs['PATH'] = PATH; + exposedLibs['FS'] = FS; return Module; }, }; @@ -12,6 +14,13 @@ var loadingFiles = {}; + function getPathLeaf(path) { + + while (path.endsWith('/')) + path = path.slice(0, -1); + return path.slice(path.lastIndexOf('/') + 1); + } + function getBasePath(path) { if (path.endsWith('/')) @@ -23,14 +32,15 @@ function getBaseName(path) { - path = getBasePath(path); - return path.slice(path.lastIndexOf('/') + 1); + return getPathLeaf(getBasePath(path)); } Engine = function Engine() { this.rtenv = null; + var LIBS = {}; + var initPromise = null; var unloadAfterInit = true; @@ -80,11 +90,11 @@ return new Promise(function(resolve, reject) { rtenvProps.onRuntimeInitialized = resolve; rtenvProps.onAbort = reject; - rtenvProps.engine.rtenv = Engine.RuntimeEnvironment(rtenvProps); + rtenvProps.engine.rtenv = Engine.RuntimeEnvironment(rtenvProps, LIBS); }); } - this.preloadFile = function(pathOrBuffer, bufferFilename) { + this.preloadFile = function(pathOrBuffer, destPath) { if (pathOrBuffer instanceof ArrayBuffer) { pathOrBuffer = new Uint8Array(pathOrBuffer); @@ -93,14 +103,14 @@ } if (pathOrBuffer instanceof Uint8Array) { preloadedFiles.push({ - name: bufferFilename, + path: destPath, buffer: pathOrBuffer }); return Promise.resolve(); } else if (typeof pathOrBuffer === 'string') { return loadPromise(pathOrBuffer, preloadProgressTracker).then(function(xhr) { preloadedFiles.push({ - name: pathOrBuffer, + path: destPath || pathOrBuffer, buffer: xhr.response }); }); @@ -119,7 +129,12 @@ this.startGame = function(mainPack) { executableName = getBaseName(mainPack); - return Promise.all([this.init(getBasePath(mainPack)), this.preloadFile(mainPack)]).then( + return Promise.all([ + // Load from directory, + this.init(getBasePath(mainPack)), + // ...but write to root where the engine expects it. + this.preloadFile(mainPack, getPathLeaf(mainPack)) + ]).then( Function.prototype.apply.bind(synchronousStart, this, []) ); }; @@ -163,7 +178,16 @@ this.rtenv.thisProgram = executableName || getBaseName(basePath); preloadedFiles.forEach(function(file) { - this.rtenv.FS.createDataFile('/', file.name, new Uint8Array(file.buffer), true, true, true); + var dir = LIBS.PATH.dirname(file.path); + try { + LIBS.FS.stat(dir); + } catch (e) { + if (e.code !== 'ENOENT') { + throw e; + } + LIBS.FS.mkdirTree(dir); + } + LIBS.FS.createDataFile('/', file.path, new Uint8Array(file.buffer), true, true, true); }, this); preloadedFiles = null; diff --git a/platform/javascript/http_client_javascript.cpp b/platform/javascript/http_client_javascript.cpp index 118a77835e..8d90e01ae1 100644 --- a/platform/javascript/http_client_javascript.cpp +++ b/platform/javascript/http_client_javascript.cpp @@ -88,7 +88,7 @@ Error HTTPClient::prepare_request(Method p_method, const String &p_url, const Ve ERR_FAIL_COND_V(port < 0, ERR_UNCONFIGURED); ERR_FAIL_COND_V(!p_url.begins_with("/"), ERR_INVALID_PARAMETER); - String url = (use_tls ? "https://" : "http://") + host + ":" + itos(port) + "/" + p_url; + String url = (use_tls ? "https://" : "http://") + host + ":" + itos(port) + p_url; godot_xhr_reset(xhr_id); godot_xhr_open(xhr_id, _methods[p_method], url.utf8().get_data(), username.empty() ? NULL : username.utf8().get_data(), diff --git a/platform/javascript/javascript_main.cpp b/platform/javascript/javascript_main.cpp index e85fe0800f..54d4755bd7 100644 --- a/platform/javascript/javascript_main.cpp +++ b/platform/javascript/javascript_main.cpp @@ -40,7 +40,7 @@ static void main_loop() { os->main_loop_iterate(); } -extern "C" void main_after_fs_sync(char *p_idbfs_err) { +extern "C" EMSCRIPTEN_KEEPALIVE void main_after_fs_sync(char *p_idbfs_err) { String idbfs_err = String::utf8(p_idbfs_err); if (!idbfs_err.empty()) { diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp index cbfe99ba2d..a275fb7929 100644 --- a/platform/javascript/os_javascript.cpp +++ b/platform/javascript/os_javascript.cpp @@ -413,14 +413,13 @@ static EM_BOOL joy_callback_func(int p_type, const EmscriptenGamepadEvent *p_eve return false; } -extern "C" { -void send_notification(int notif) { +extern "C" EMSCRIPTEN_KEEPALIVE void send_notification(int notif) { + if (notif == MainLoop::NOTIFICATION_WM_MOUSE_ENTER || notif == MainLoop::NOTIFICATION_WM_MOUSE_EXIT) { _cursor_inside_canvas = notif == MainLoop::NOTIFICATION_WM_MOUSE_ENTER; } OS_JavaScript::get_singleton()->get_main_loop()->notification(notif); } -} Error OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { @@ -480,8 +479,6 @@ Error OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, input = memnew(InputDefault); _input = input; - power_manager = memnew(PowerJavascript); - #define EM_CHECK(ev) \ if (result != EMSCRIPTEN_RESULT_SUCCESS) \ ERR_PRINTS("Error while setting " #ev " callback: Code " + itos(result)) @@ -968,15 +965,21 @@ String OS_JavaScript::get_joy_guid(int p_device) const { } OS::PowerState OS_JavaScript::get_power_state() { - return power_manager->get_power_state(); + + WARN_PRINT("Power management is not supported for the HTML5 platform, defaulting to POWERSTATE_UNKNOWN"); + return OS::POWERSTATE_UNKNOWN; } int OS_JavaScript::get_power_seconds_left() { - return power_manager->get_power_seconds_left(); + + WARN_PRINT("Power management is not supported for the HTML5 platform, defaulting to -1"); + return -1; } int OS_JavaScript::get_power_percent_left() { - return power_manager->get_power_percent_left(); + + WARN_PRINT("Power management is not supported for the HTML5 platform, defaulting to -1"); + return -1; } bool OS_JavaScript::_check_internal_feature_support(const String &p_feature) { diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h index f0ba9422e8..46eb1b3f13 100644 --- a/platform/javascript/os_javascript.h +++ b/platform/javascript/os_javascript.h @@ -36,7 +36,6 @@ #include "main/input_default.h" #include "os/input.h" #include "os/main_loop.h" -#include "power_javascript.h" #include "servers/audio_server.h" #include "servers/visual/rasterizer.h" @@ -64,8 +63,6 @@ class OS_JavaScript : public OS_Unix { GetUserDataDirFunc get_user_data_dir_func; - PowerJavascript *power_manager; - static void _close_notification_funcs(const String &p_file, int p_flags); void process_joypads(); diff --git a/platform/javascript/power_javascript.cpp b/platform/javascript/power_javascript.cpp deleted file mode 100644 index 5241644dbc..0000000000 --- a/platform/javascript/power_javascript.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/*************************************************************************/ -/* power_javascript.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "power_javascript.h" -#include "error_macros.h" - -bool PowerJavascript::UpdatePowerInfo() { - // TODO Javascript implementation - return false; -} - -OS::PowerState PowerJavascript::get_power_state() { - if (UpdatePowerInfo()) { - return power_state; - } else { - WARN_PRINT("Power management is not implemented on this platform, defaulting to POWERSTATE_UNKNOWN"); - return OS::POWERSTATE_UNKNOWN; - } -} - -int PowerJavascript::get_power_seconds_left() { - if (UpdatePowerInfo()) { - return nsecs_left; - } else { - WARN_PRINT("Power management is not implemented on this platform, defaulting to -1"); - return -1; - } -} - -int PowerJavascript::get_power_percent_left() { - if (UpdatePowerInfo()) { - return percent_left; - } else { - WARN_PRINT("Power management is not implemented on this platform, defaulting to -1"); - return -1; - } -} - -PowerJavascript::PowerJavascript() : - nsecs_left(-1), - percent_left(-1), - power_state(OS::POWERSTATE_UNKNOWN) { -} - -PowerJavascript::~PowerJavascript() { -} diff --git a/platform/javascript/power_javascript.h b/platform/javascript/power_javascript.h deleted file mode 100644 index c0c564aa60..0000000000 --- a/platform/javascript/power_javascript.h +++ /dev/null @@ -1,53 +0,0 @@ -/*************************************************************************/ -/* power_javascript.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef PLATFORM_JAVASCRIPT_POWER_JAVASCRIPT_H_ -#define PLATFORM_JAVASCRIPT_POWER_JAVASCRIPT_H_ - -#include "os/os.h" - -class PowerJavascript { -private: - int nsecs_left; - int percent_left; - OS::PowerState power_state; - - bool UpdatePowerInfo(); - -public: - PowerJavascript(); - virtual ~PowerJavascript(); - - OS::PowerState get_power_state(); - int get_power_seconds_left(); - int get_power_percent_left(); -}; - -#endif /* PLATFORM_JAVASCRIPT_POWER_JAVASCRIPT_H_ */ diff --git a/platform/javascript/pre.js b/platform/javascript/pre.js index 311aa44fda..02194bc75e 100644 --- a/platform/javascript/pre.js +++ b/platform/javascript/pre.js @@ -1,2 +1,2 @@ var Engine = { - RuntimeEnvironment: function(Module) { + RuntimeEnvironment: function(Module, exposedLibs) { diff --git a/platform/osx/detect.py b/platform/osx/detect.py index e51a8082f7..1e9631fae0 100644 --- a/platform/osx/detect.py +++ b/platform/osx/detect.py @@ -93,6 +93,7 @@ def configure(env): env['AR'] = basecmd + "ar" env['RANLIB'] = basecmd + "ranlib" env['AS'] = basecmd + "as" + env.Append(CCFLAGS=['-D__MACPORTS__']) #hack to fix libvpx MM256_BROADCASTSI128_SI256 define if (env["CXX"] == "clang++"): env.Append(CPPFLAGS=['-DTYPED_METHOD_BIND']) diff --git a/platform/osx/godot_main_osx.mm b/platform/osx/godot_main_osx.mm index 6ccbaf896b..64116fa1e0 100644 --- a/platform/osx/godot_main_osx.mm +++ b/platform/osx/godot_main_osx.mm @@ -101,5 +101,5 @@ int main(int argc, char **argv) { Main::cleanup(); - return 0; + return os.get_exit_code(); }; diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h index 486d7af1c1..fee25e98cb 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -100,7 +100,7 @@ public: id context; CursorShape cursor_shape; - NSCursor *cursors[CURSOR_MAX] = { NULL }; + NSCursor *cursors[CURSOR_MAX]; MouseMode mouse_mode; String title; diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index a811ff585d..0c5524dd08 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -192,6 +192,7 @@ static Vector2 get_mouse_pos(NSEvent *event) { // Note: called before main loop init! char *utfs = strdup([filename UTF8String]); OS_OSX::singleton->open_with_filename.parse_utf8(utfs); + free(utfs); return YES; } @@ -263,6 +264,7 @@ static Vector2 get_mouse_pos(NSEvent *event) { NSWindow *window = (NSWindow *)[notification object]; CGFloat newBackingScaleFactor = [window backingScaleFactor]; CGFloat oldBackingScaleFactor = [[[notification userInfo] objectForKey:@"NSBackingPropertyOldScaleFactorKey"] doubleValue]; + [OS_OSX::singleton->window_view setWantsBestResolutionOpenGLSurface:YES]; if (newBackingScaleFactor != oldBackingScaleFactor) { //Set new display scale and window size @@ -837,6 +839,108 @@ static int translateKey(unsigned int key) { return table[key]; } +struct _KeyCodeMap { + UniChar kchar; + int kcode; +}; + +static const _KeyCodeMap _keycodes[55] = { + { '`', KEY_QUOTELEFT }, + { '~', KEY_ASCIITILDE }, + { '0', KEY_KP_0 }, + { '1', KEY_KP_1 }, + { '2', KEY_KP_2 }, + { '3', KEY_KP_3 }, + { '4', KEY_KP_4 }, + { '5', KEY_KP_5 }, + { '6', KEY_KP_6 }, + { '7', KEY_KP_7 }, + { '8', KEY_KP_8 }, + { '9', KEY_KP_9 }, + { '-', KEY_MINUS }, + { '_', KEY_UNDERSCORE }, + { '=', KEY_EQUAL }, + { '+', KEY_PLUS }, + { 'q', KEY_Q }, + { 'w', KEY_W }, + { 'e', KEY_E }, + { 'r', KEY_R }, + { 't', KEY_T }, + { 'y', KEY_Y }, + { 'u', KEY_U }, + { 'i', KEY_I }, + { 'o', KEY_O }, + { 'p', KEY_P }, + { '[', KEY_BRACERIGHT }, + { ']', KEY_BRACELEFT }, + { '{', KEY_BRACERIGHT }, + { '}', KEY_BRACELEFT }, + { 'a', KEY_A }, + { 's', KEY_S }, + { 'd', KEY_D }, + { 'f', KEY_F }, + { 'g', KEY_G }, + { 'h', KEY_H }, + { 'j', KEY_J }, + { 'k', KEY_K }, + { 'l', KEY_L }, + { ';', KEY_SEMICOLON }, + { ':', KEY_COLON }, + { '\'', KEY_APOSTROPHE }, + { '\"', KEY_QUOTEDBL }, + { '\\', KEY_BACKSLASH }, + { '#', KEY_NUMBERSIGN }, + { 'z', KEY_Z }, + { 'x', KEY_X }, + { 'c', KEY_C }, + { 'v', KEY_V }, + { 'b', KEY_B }, + { 'n', KEY_N }, + { 'm', KEY_M }, + { ',', KEY_COMMA }, + { '.', KEY_PERIOD }, + { '/', KEY_SLASH } +}; + +static int remapKey(unsigned int key) { + + TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource(); + if (!currentKeyboard) + return translateKey(key); + + CFDataRef layoutData = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData); + if (!layoutData) + return nil; + + const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout *)CFDataGetBytePtr(layoutData); + + UInt32 keysDown = 0; + UniChar chars[4]; + UniCharCount realLength; + + OSStatus err = UCKeyTranslate(keyboardLayout, + key, + kUCKeyActionDisplay, + 0, + LMGetKbdType(), + kUCKeyTranslateNoDeadKeysBit, + &keysDown, + sizeof(chars) / sizeof(chars[0]), + &realLength, + chars); + + if (err != noErr) { + return translateKey(key); + } + + for (unsigned int i = 0; i < 55; i++) { + if (_keycodes[i].kchar == chars[0]) { + return _keycodes[i].kcode; + } + } + return translateKey(key); +} + - (void)keyDown:(NSEvent *)event { //disable raw input in IME mode @@ -846,7 +950,7 @@ static int translateKey(unsigned int key) { ke.osx_state = [event modifierFlags]; ke.pressed = true; ke.echo = [event isARepeat]; - ke.scancode = latin_keyboard_keycode_convert(translateKey([event keyCode])); + ke.scancode = remapKey([event keyCode]); ke.unicode = 0; push_to_key_event_buffer(ke); @@ -899,7 +1003,7 @@ static int translateKey(unsigned int key) { } ke.osx_state = mod; - ke.scancode = latin_keyboard_keycode_convert(translateKey(key)); + ke.scancode = remapKey(key); ke.unicode = 0; push_to_key_event_buffer(ke); @@ -915,7 +1019,7 @@ static int translateKey(unsigned int key) { ke.osx_state = [event modifierFlags]; ke.pressed = false; ke.echo = false; - ke.scancode = latin_keyboard_keycode_convert(translateKey([event keyCode])); + ke.scancode = remapKey([event keyCode]); ke.unicode = 0; push_to_key_event_buffer(ke); @@ -1403,9 +1507,7 @@ void OS_OSX::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, c Ref<Texture> texture = p_cursor; Ref<Image> image = texture->get_data(); - int image_size = 32 * 32; - - ERR_FAIL_COND(texture->get_width() != 32 || texture->get_height() != 32); + ERR_FAIL_COND(texture->get_width() > 256 || texture->get_height() > 256); NSBitmapImageRep *imgrep = [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL @@ -2320,6 +2422,7 @@ OS_OSX *OS_OSX::singleton = NULL; OS_OSX::OS_OSX() { + memset(cursors, 0, sizeof(cursors)); key_event_pos = 0; mouse_mode = OS::MOUSE_MODE_VISIBLE; main_loop = NULL; diff --git a/platform/uwp/detect.py b/platform/uwp/detect.py index 3ee195e4f9..0e7b125dc5 100644 --- a/platform/uwp/detect.py +++ b/platform/uwp/detect.py @@ -43,6 +43,8 @@ def get_flags(): def configure(env): + env.msvc = True + if (env["bits"] != "default"): print("Error: bits argument is disabled for MSVC") print(""" diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 13fe781ff3..f51d969c16 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -1896,26 +1896,25 @@ void OS_Windows::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shap Ref<Texture> texture = p_cursor; Ref<Image> image = texture->get_data(); - UINT image_size = 32 * 32; + UINT image_size = texture->get_width() * texture->get_height(); UINT size = sizeof(UINT) * image_size; - ERR_FAIL_COND(texture->get_width() != 32 || texture->get_height() != 32); + ERR_FAIL_COND(texture->get_width() > 256 || texture->get_height() > 256); // Create the BITMAP with alpha channel COLORREF *buffer = (COLORREF *)malloc(sizeof(COLORREF) * image_size); image->lock(); for (UINT index = 0; index < image_size; index++) { - int column_index = floor(index / 32); - int row_index = index % 32; + int row_index = floor(index / texture->get_width()); + int column_index = index % texture->get_width(); - Color pcColor = image->get_pixel(row_index, column_index); - *(buffer + index) = image->get_pixel(row_index, column_index).to_argb32(); + *(buffer + index) = image->get_pixel(column_index, row_index).to_argb32(); } image->unlock(); // Using 4 channels, so 4 * 8 bits - HBITMAP bitmap = CreateBitmap(32, 32, 1, 4 * 8, buffer); + HBITMAP bitmap = CreateBitmap(texture->get_width(), texture->get_height(), 1, 4 * 8, buffer); COLORREF clrTransparent = -1; // Create the AND and XOR masks for the bitmap diff --git a/platform/x11/detect.py b/platform/x11/detect.py index da2b0701b6..5820a926e9 100644 --- a/platform/x11/detect.py +++ b/platform/x11/detect.py @@ -234,10 +234,10 @@ def configure(env): print("ALSA libraries not found, disabling driver") if env['pulseaudio']: - if (os.system("pkg-config --exists libpulse-simple") == 0): # 0 means found + if (os.system("pkg-config --exists libpulse") == 0): # 0 means found print("Enabling PulseAudio") env.Append(CPPFLAGS=["-DPULSEAUDIO_ENABLED"]) - env.ParseConfig('pkg-config --cflags --libs libpulse-simple') + env.ParseConfig('pkg-config --cflags --libs libpulse') else: print("PulseAudio development libraries not found, disabling driver") diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index c06c7516d0..338d13410f 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -2375,11 +2375,11 @@ void OS_X11::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, c Ref<Texture> texture = p_cursor; Ref<Image> image = texture->get_data(); - ERR_FAIL_COND(texture->get_width() != 32 || texture->get_height() != 32); + ERR_FAIL_COND(texture->get_width() > 256 || texture->get_height() > 256); // Create the cursor structure XcursorImage *cursor_image = XcursorImageCreate(texture->get_width(), texture->get_height()); - XcursorUInt image_size = 32 * 32; + XcursorUInt image_size = texture->get_width() * texture->get_height(); XcursorDim size = sizeof(XcursorPixel) * image_size; cursor_image->version = 1; @@ -2393,10 +2393,10 @@ void OS_X11::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, c image->lock(); for (XcursorPixel index = 0; index < image_size; index++) { - int column_index = floor(index / 32); - int row_index = index % 32; + int row_index = floor(index / texture->get_width()); + int column_index = index % texture->get_width(); - *(cursor_image->pixels + index) = image->get_pixel(row_index, column_index).to_argb32(); + *(cursor_image->pixels + index) = image->get_pixel(column_index, row_index).to_argb32(); } image->unlock(); |