diff options
Diffstat (limited to 'platform')
85 files changed, 1200 insertions, 816 deletions
diff --git a/platform/android/AndroidManifest.xml.template b/platform/android/AndroidManifest.xml.template index d8fb9326ea..daaf847f11 100644 --- a/platform/android/AndroidManifest.xml.template +++ b/platform/android/AndroidManifest.xml.template @@ -36,4 +36,9 @@ $$ADD_APPLICATION_CHUNKS$$ </application> + <instrumentation android:icon="@drawable/icon" + android:label="@string/godot_project_name_string" + android:name="org.godotengine.godot.GodotInstrumentation" + android:targetPackage="com.godot.game" /> + </manifest> diff --git a/platform/android/audio_driver_opensl.cpp b/platform/android/audio_driver_opensl.cpp index e259380a63..8913950fac 100644 --- a/platform/android/audio_driver_opensl.cpp +++ b/platform/android/audio_driver_opensl.cpp @@ -211,6 +211,119 @@ void AudioDriverOpenSL::start() { active = true; } +void AudioDriverOpenSL::_record_buffer_callback(SLAndroidSimpleBufferQueueItf queueItf) { + + for (int i = 0; i < rec_buffer.size(); i++) { + int32_t sample = rec_buffer[i] << 16; + input_buffer_write(sample); + input_buffer_write(sample); // call twice to convert to Stereo + } + + SLresult res = (*recordBufferQueueItf)->Enqueue(recordBufferQueueItf, rec_buffer.ptrw(), rec_buffer.size() * sizeof(int16_t)); + ERR_FAIL_COND(res != SL_RESULT_SUCCESS); +} + +void AudioDriverOpenSL::_record_buffer_callbacks(SLAndroidSimpleBufferQueueItf queueItf, void *pContext) { + + AudioDriverOpenSL *ad = (AudioDriverOpenSL *)pContext; + + ad->_record_buffer_callback(queueItf); +} + +Error AudioDriverOpenSL::capture_init_device() { + + SLDataLocator_IODevice loc_dev = { + SL_DATALOCATOR_IODEVICE, + SL_IODEVICE_AUDIOINPUT, + SL_DEFAULTDEVICEID_AUDIOINPUT, + NULL + }; + SLDataSource recSource = { &loc_dev, NULL }; + + SLDataLocator_AndroidSimpleBufferQueue loc_bq = { + SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, + 2 + }; + SLDataFormat_PCM format_pcm = { + SL_DATAFORMAT_PCM, + 1, + SL_SAMPLINGRATE_44_1, + SL_PCMSAMPLEFORMAT_FIXED_16, + SL_PCMSAMPLEFORMAT_FIXED_16, + SL_SPEAKER_FRONT_CENTER, + SL_BYTEORDER_LITTLEENDIAN + }; + SLDataSink recSnk = { &loc_bq, &format_pcm }; + + const SLInterfaceID ids[2] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION }; + const SLboolean req[2] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE }; + + SLresult res = (*EngineItf)->CreateAudioRecorder(EngineItf, &recorder, &recSource, &recSnk, 2, ids, req); + ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); + + res = (*recorder)->Realize(recorder, SL_BOOLEAN_FALSE); + ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); + + res = (*recorder)->GetInterface(recorder, SL_IID_RECORD, (void *)&recordItf); + ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); + + res = (*recorder)->GetInterface(recorder, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, (void *)&recordBufferQueueItf); + ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); + + res = (*recordBufferQueueItf)->RegisterCallback(recordBufferQueueItf, _record_buffer_callbacks, this); + ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); + + SLuint32 state; + res = (*recordItf)->GetRecordState(recordItf, &state); + ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); + + if (state != SL_RECORDSTATE_STOPPED) { + res = (*recordItf)->SetRecordState(recordItf, SL_RECORDSTATE_STOPPED); + ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); + + res = (*recordBufferQueueItf)->Clear(recordBufferQueueItf); + ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); + } + + const int rec_buffer_frames = 2048; + rec_buffer.resize(rec_buffer_frames); + input_buffer_init(rec_buffer_frames); + + res = (*recordBufferQueueItf)->Enqueue(recordBufferQueueItf, rec_buffer.ptrw(), rec_buffer.size() * sizeof(int16_t)); + ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); + + res = (*recordItf)->SetRecordState(recordItf, SL_RECORDSTATE_RECORDING); + ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); + + return OK; +} + +Error AudioDriverOpenSL::capture_start() { + + if (OS::get_singleton()->request_permission("RECORD_AUDIO")) { + return capture_init_device(); + } + + return OK; +} + +Error AudioDriverOpenSL::capture_stop() { + + SLuint32 state; + SLresult res = (*recordItf)->GetRecordState(recordItf, &state); + ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); + + if (state != SL_RECORDSTATE_STOPPED) { + res = (*recordItf)->SetRecordState(recordItf, SL_RECORDSTATE_STOPPED); + ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); + + res = (*recordBufferQueueItf)->Clear(recordBufferQueueItf); + ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); + } + + return OK; +} + int AudioDriverOpenSL::get_mix_rate() const { return 44100; diff --git a/platform/android/audio_driver_opensl.h b/platform/android/audio_driver_opensl.h index 77e16e507a..2981073cec 100644 --- a/platform/android/audio_driver_opensl.h +++ b/platform/android/audio_driver_opensl.h @@ -54,13 +54,18 @@ class AudioDriverOpenSL : public AudioDriver { int32_t *mixdown_buffer; int last_free; + Vector<int16_t> rec_buffer; + SLPlayItf playItf; + SLRecordItf recordItf; SLObjectItf sl; SLEngineItf EngineItf; SLObjectItf OutputMix; SLVolumeItf volumeItf; SLObjectItf player; + SLObjectItf recorder; SLAndroidSimpleBufferQueueItf bufferQueueItf; + SLAndroidSimpleBufferQueueItf recordBufferQueueItf; SLDataSource audioSource; SLDataFormat_PCM pcm; SLDataSink audioSink; @@ -76,6 +81,15 @@ class AudioDriverOpenSL : public AudioDriver { SLAndroidSimpleBufferQueueItf queueItf, void *pContext); + void _record_buffer_callback( + SLAndroidSimpleBufferQueueItf queueItf); + + static void _record_buffer_callbacks( + SLAndroidSimpleBufferQueueItf queueItf, + void *pContext); + + virtual Error capture_init_device(); + public: void set_singleton(); @@ -91,6 +105,9 @@ public: virtual void set_pause(bool p_pause); + virtual Error capture_start(); + virtual Error capture_stop(); + AudioDriverOpenSL(); }; diff --git a/platform/android/detect.py b/platform/android/detect.py index aa48252435..80cda68a9e 100644 --- a/platform/android/detect.py +++ b/platform/android/detect.py @@ -298,12 +298,6 @@ def configure(env): env.Append(CPPFLAGS=['-DANDROID_ENABLED', '-DUNIX_ENABLED', '-DNO_FCNTL']) env.Append(LIBS=['OpenSLES', 'EGL', 'GLESv3', 'android', 'log', 'z', 'dl']) - # TODO: Move that to opus module's config - if 'module_opus_enabled' in env and env['module_opus_enabled']: - if (env["android_arch"] == "armv6" or env["android_arch"] == "armv7"): - env.Append(CFLAGS=["-DOPUS_ARM_OPT"]) - env.opus_fixed_point = "yes" - # Return NDK version string in source.properties (adapted from the Chromium project). def get_ndk_version(path): if path is None: diff --git a/platform/android/dir_access_jandroid.cpp b/platform/android/dir_access_jandroid.cpp index 4b3d93aaa7..8c464465ca 100644 --- a/platform/android/dir_access_jandroid.cpp +++ b/platform/android/dir_access_jandroid.cpp @@ -31,6 +31,7 @@ #include "dir_access_jandroid.h" #include "core/print_string.h" #include "file_access_jandroid.h" +#include "string_android.h" #include "thread_jandroid.h" jobject DirAccessJAndroid::io = NULL; @@ -69,7 +70,7 @@ String DirAccessJAndroid::get_next() { if (!str) return ""; - String ret = String::utf8(env->GetStringUTFChars((jstring)str, NULL)); + String ret = jstring_to_string((jstring)str, env); env->DeleteLocalRef((jobject)str); return ret; } diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index f293eef2ba..e489bce3f8 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -206,9 +206,9 @@ static const LauncherIcon launcher_icons[] = { { "launcher_icons/mdpi_48x48", "res/drawable-mdpi-v4/icon.png" } }; -class EditorExportAndroid : public EditorExportPlatform { +class EditorExportPlatformAndroid : public EditorExportPlatform { - GDCLASS(EditorExportAndroid, EditorExportPlatform) + GDCLASS(EditorExportPlatformAndroid, EditorExportPlatform) Ref<ImageTexture> logo; Ref<ImageTexture> run_icon; @@ -235,7 +235,7 @@ class EditorExportAndroid : public EditorExportPlatform { static void _device_poll_thread(void *ud) { - EditorExportAndroid *ea = (EditorExportAndroid *)ud; + EditorExportPlatformAndroid *ea = (EditorExportPlatformAndroid *)ud; while (!ea->quit_request) { @@ -301,10 +301,10 @@ class EditorExportAndroid : public EditorExportPlatform { args.push_back(d.id); args.push_back("shell"); args.push_back("getprop"); - int ec; + int ec2; String dp; - OS::get_singleton()->execute(adb, args, true, NULL, &dp, &ec); + OS::get_singleton()->execute(adb, args, true, NULL, &dp, &ec2); Vector<String> props = dp.split("\n"); String vendor; @@ -658,6 +658,8 @@ class EditorExportAndroid : public EditorExportPlatform { int orientation = p_preset->get("screen/orientation"); + bool min_gles3 = ProjectSettings::get_singleton()->get("rendering/quality/driver/driver_name") == "GLES3" && + !ProjectSettings::get_singleton()->get("rendering/quality/driver/fallback_to_gles2"); bool screen_support_small = p_preset->get("screen/support_small"); bool screen_support_normal = p_preset->get("screen/support_normal"); bool screen_support_large = p_preset->get("screen/support_large"); @@ -815,6 +817,11 @@ class EditorExportAndroid : public EditorExportPlatform { } } + if (tname == "uses-feature" && attrname == "glEsVersion") { + + encode_uint32(min_gles3 ? 0x00030000 : 0x00020000, &p_manifest.write[iofs + 16]); + } + iofs += 20; } @@ -1114,17 +1121,14 @@ public: public: virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) { - // Re-enable when a GLES 2.0 backend is read - /*int api = p_preset->get("graphics/api"); - if (api == 0) - r_features->push_back("etc"); - else*/ String driver = ProjectSettings::get_singleton()->get("rendering/quality/driver/driver_name"); - if (driver == "GLES2" || driver == "GLES3") { + if (driver == "GLES2") { r_features->push_back("etc"); - } - if (driver == "GLES3") { + } else if (driver == "GLES3") { r_features->push_back("etc2"); + if (ProjectSettings::get_singleton()->get("rendering/quality/driver/fallback_to_gles2")) { + r_features->push_back("etc"); + } } Vector<String> abis = get_enabled_abis(p_preset); @@ -1453,6 +1457,12 @@ public: err += TTR("Invalid package name:") + " " + pn_err + "\n"; } + String etc_error = test_etc2(); + if (etc_error != String()) { + valid = false; + err += etc_error; + } + r_error = err; return valid; } @@ -1489,6 +1499,10 @@ public: } } + if (!DirAccess::exists(p_path.get_base_dir())) { + return ERR_FILE_BAD_PATH; + } + FileAccess *src_f = NULL; zlib_filefunc_def io = zipio_create_io_from_file(&src_f); @@ -1925,7 +1939,7 @@ public: virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) { } - EditorExportAndroid() { + EditorExportPlatformAndroid() { Ref<Image> img = memnew(Image(_android_logo)); logo.instance(); @@ -1941,7 +1955,7 @@ public: device_thread = Thread::create(_device_poll_thread, this); } - ~EditorExportAndroid() { + ~EditorExportPlatformAndroid() { quit_request = true; Thread::wait_to_finish(device_thread); memdelete(device_lock); @@ -1969,6 +1983,6 @@ void register_android_exporter() { EDITOR_DEF("export/android/timestamping_authority_url", ""); EDITOR_DEF("export/android/shutdown_adb_on_exit", true); - Ref<EditorExportAndroid> exporter = Ref<EditorExportAndroid>(memnew(EditorExportAndroid)); + Ref<EditorExportPlatformAndroid> exporter = Ref<EditorExportPlatformAndroid>(memnew(EditorExportPlatformAndroid)); EditorExport::get_singleton()->add_export_platform(exporter); } diff --git a/platform/android/java/src/org/godotengine/godot/Godot.java b/platform/android/java/src/org/godotengine/godot/Godot.java index a10d7876f4..e42099ba0b 100644 --- a/platform/android/java/src/org/godotengine/godot/Godot.java +++ b/platform/android/java/src/org/godotengine/godot/Godot.java @@ -38,12 +38,14 @@ import android.app.AlertDialog; import android.app.PendingIntent; import android.content.ClipData; import android.content.ClipboardManager; +import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.content.pm.ConfigurationInfo; +import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.graphics.Point; import android.graphics.Rect; @@ -51,11 +53,13 @@ import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; +import android.Manifest; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.Messenger; import android.provider.Settings.Secure; +import android.support.v4.content.ContextCompat; import android.util.Log; import android.view.Display; import android.view.KeyEvent; @@ -98,6 +102,7 @@ import javax.microedition.khronos.opengles.GL10; public class Godot extends Activity implements SensorEventListener, IDownloaderClient { static final int MAX_SINGLETONS = 64; + static final int REQUEST_RECORD_AUDIO_PERMISSION = 1; private IStub mDownloaderClientStub; private IDownloaderService mRemoteService; private TextView mStatusText; @@ -258,6 +263,10 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC for (int i = 0; i < singleton_count; i++) { singletons[i].onMainRequestPermissionsResult(requestCode, permissions, grantResults); } + + for (int i = 0; i < permissions.length; i++) { + GodotLib.requestPermissionResult(permissions[i], grantResults[i] == PackageManager.PERMISSION_GRANTED); + } }; public void onVideoInit() { @@ -318,6 +327,23 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC }); } + public void restart() { + // HACK: + // + // Currently it's very hard to properly deinitialize Godot on Android to restart the game + // from scratch. Therefore, we need to kill the whole app process and relaunch it. + // + // Restarting only the activity, wouldn't be enough unless it did proper cleanup (including + // releasing and reloading native libs or resetting their state somehow and clearing statics). + // + // Using instrumentation is a way of making the whole app process restart, because Android + // will kill any process of the same package which was already running. + // + Bundle args = new Bundle(); + args.putParcelable("intent", mCurrentIntent); + startInstrumentation(new ComponentName(Godot.this, GodotInstrumentation.class), null, args); + } + public void alert(final String message, final String title) { final Activity activity = this; runOnUiThread(new Runnable() { @@ -415,7 +441,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC mGyroscope = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE); mSensorManager.registerListener(this, mGyroscope, SensorManager.SENSOR_DELAY_GAME); - GodotLib.initialize(this, io.needsReloadHooks(), getAssets(), use_apk_expansion); + GodotLib.initialize(this, getAssets(), use_apk_expansion); result_callback = null; @@ -918,13 +944,27 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC } */ - // Audio + public boolean requestPermission(String p_name) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + // Not necessary, asked on install already + return true; + } + + if (p_name.equals("RECORD_AUDIO")) { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { + requestPermissions(new String[] { Manifest.permission.RECORD_AUDIO }, REQUEST_RECORD_AUDIO_PERMISSION); + return false; + } + } + + return true; + } /** - * The download state should trigger changes in the UI --- it may be useful - * to show the state as being indeterminate at times. This sample can be - * considered a guideline. - */ + * The download state should trigger changes in the UI --- it may be useful + * to show the state as being indeterminate at times. This sample can be + * considered a guideline. + */ @Override public void onDownloadStateChanged(int newState) { setState(newState); diff --git a/platform/android/java/src/org/godotengine/godot/GodotIO.java b/platform/android/java/src/org/godotengine/godot/GodotIO.java index 8cee20e435..1b2ff61314 100644 --- a/platform/android/java/src/org/godotengine/godot/GodotIO.java +++ b/platform/android/java/src/org/godotengine/godot/GodotIO.java @@ -500,11 +500,6 @@ public class GodotIO { return (int)(metrics.density * 160f); } - public boolean needsReloadHooks() { - - return false; - } - public void showKeyboard(String p_existing_text) { if (edit != null) edit.showKeyboard(p_existing_text); @@ -516,14 +511,6 @@ public class GodotIO { public void hideKeyboard() { if (edit != null) edit.hideKeyboard(); - - InputMethodManager inputMgr = (InputMethodManager)activity.getSystemService(Context.INPUT_METHOD_SERVICE); - View v = activity.getCurrentFocus(); - if (v != null) { - inputMgr.hideSoftInputFromWindow(v.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); - } else { - inputMgr.hideSoftInputFromWindow(new View(activity).getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); - } }; public void setScreenOrientation(int p_orientation) { diff --git a/platform/windows/ctxgl_procaddr.h b/platform/android/java/src/org/godotengine/godot/GodotInstrumentation.java index cc40804ae6..0466f380e8 100644 --- a/platform/windows/ctxgl_procaddr.h +++ b/platform/android/java/src/org/godotengine/godot/GodotInstrumentation.java @@ -1,5 +1,5 @@ /*************************************************************************/ -/* ctxgl_procaddr.h */ +/* GodotInstrumentation.java */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,12 +28,23 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef CTXGL_PROCADDR_H -#define CTXGL_PROCADDR_H +package org.godotengine.godot; -#ifdef OPENGL_ENABLED -#include <windows.h> +import android.app.Instrumentation; +import android.content.Intent; +import android.os.Bundle; -PROC get_gl_proc_address(const char *p_address); -#endif -#endif // CTXGL_PROCADDR_H +public class GodotInstrumentation extends Instrumentation { + private Intent intent; + + @Override + public void onCreate(Bundle arguments) { + intent = arguments.getParcelable("intent"); + start(); + } + + @Override + public void onStart() { + startActivitySync(intent); + } +} diff --git a/platform/android/java/src/org/godotengine/godot/GodotLib.java b/platform/android/java/src/org/godotengine/godot/GodotLib.java index 29e7918645..6e6b398a5d 100644 --- a/platform/android/java/src/org/godotengine/godot/GodotLib.java +++ b/platform/android/java/src/org/godotengine/godot/GodotLib.java @@ -45,9 +45,9 @@ public class GodotLib { * @param height the current view height */ - public static native void initialize(Godot p_instance, boolean need_reload_hook, Object p_asset_manager, boolean use_apk_expansion); + public static native void initialize(Godot p_instance, Object p_asset_manager, boolean use_apk_expansion); public static native void setup(String[] p_cmdline); - public static native void resize(int width, int height, boolean reload); + public static native void resize(int width, int height); public static native void newcontext(boolean p_32_bits); public static native void back(); public static native void step(); @@ -69,6 +69,7 @@ public class GodotLib { public static native String getGlobal(String p_key); public static native void callobject(int p_ID, String p_method, Object[] p_params); public static native void calldeferred(int p_ID, String p_method, Object[] p_params); + public static native void requestPermissionResult(String p_permission, boolean p_result); public static native void setVirtualKeyboardHeight(int p_height); } diff --git a/platform/android/java/src/org/godotengine/godot/GodotView.java b/platform/android/java/src/org/godotengine/godot/GodotView.java index ba8e8bd07b..ccf78f26f3 100644 --- a/platform/android/java/src/org/godotengine/godot/GodotView.java +++ b/platform/android/java/src/org/godotengine/godot/GodotView.java @@ -79,7 +79,6 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener { private Context ctx; private GodotIO io; - private static boolean firsttime = true; private static boolean use_gl3 = false; private static boolean use_32 = false; private static boolean use_debug_opengl = false; @@ -97,10 +96,8 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener { activity = p_activity; - if (!p_io.needsReloadHooks()) { - //will only work on SDK 11+!! - setPreserveEGLContextOnPause(true); - } + setPreserveEGLContextOnPause(true); + mInputManager = InputManagerCompat.Factory.getInputManager(this.getContext()); mInputManager.registerInputDeviceListener(this, null); init(false, 16, 0); @@ -718,8 +715,7 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener { public void onSurfaceChanged(GL10 gl, int width, int height) { - GodotLib.resize(width, height, !firsttime); - firsttime = false; + GodotLib.resize(width, height); for (int i = 0; i < Godot.singleton_count; i++) { Godot.singletons[i].onGLSurfaceChanged(gl, width, height); } diff --git a/platform/android/java_class_wrapper.cpp b/platform/android/java_class_wrapper.cpp index 4be1106967..2bed1f0892 100644 --- a/platform/android/java_class_wrapper.cpp +++ b/platform/android/java_class_wrapper.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "java_class_wrapper.h" +#include "string_android.h" #include "thread_jandroid.h" bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error, Variant &ret) { @@ -553,7 +554,7 @@ void JavaClassWrapper::_bind_methods() { bool JavaClassWrapper::_get_type_sig(JNIEnv *env, jobject obj, uint32_t &sig, String &strsig) { jstring name2 = (jstring)env->CallObjectMethod(obj, Class_getName); - String str_type = env->GetStringUTFChars(name2, NULL); + String str_type = jstring_to_string(name2, env); env->DeleteLocalRef(name2); uint32_t t = 0; @@ -697,7 +698,7 @@ bool JavaClass::_convert_object_to_variant(JNIEnv *env, jobject obj, Variant &va } break; case ARG_TYPE_STRING: { - var = String::utf8(env->GetStringUTFChars((jstring)obj, NULL)); + var = jstring_to_string((jstring)obj, env); return true; } break; case ARG_TYPE_CLASS: { @@ -1030,7 +1031,7 @@ bool JavaClass::_convert_object_to_variant(JNIEnv *env, jobject obj, Variant &va if (!o) ret.push_back(Variant()); else { - String val = String::utf8(env->GetStringUTFChars((jstring)o, NULL)); + String val = jstring_to_string((jstring)o, env); ret.push_back(val); } env->DeleteLocalRef(o); @@ -1075,7 +1076,7 @@ Ref<JavaClass> JavaClassWrapper::wrap(const String &p_class) { ERR_CONTINUE(!obj); jstring name = (jstring)env->CallObjectMethod(obj, getName); - String str_method = env->GetStringUTFChars(name, NULL); + String str_method = jstring_to_string(name, env); env->DeleteLocalRef(name); Vector<String> params; @@ -1204,7 +1205,7 @@ Ref<JavaClass> JavaClassWrapper::wrap(const String &p_class) { ERR_CONTINUE(!obj); jstring name = (jstring)env->CallObjectMethod(obj, Field_getName); - String str_field = env->GetStringUTFChars(name, NULL); + String str_field = jstring_to_string(name, env); env->DeleteLocalRef(name); int mods = env->CallIntMethod(obj, Field_getModifiers); if ((mods & 0x8) && (mods & 0x10) && (mods & 0x1)) { //static final public! diff --git a/platform/android/java_glue.cpp b/platform/android/java_glue.cpp index 885fb185a7..e9c0e5564f 100644 --- a/platform/android/java_glue.cpp +++ b/platform/android/java_glue.cpp @@ -41,6 +41,7 @@ #include "main/input_default.h" #include "main/main.h" #include "os_android.h" +#include "string_android.h" #include "thread_jandroid.h" #include <unistd.h> @@ -223,7 +224,7 @@ String _get_class_name(JNIEnv *env, jclass cls, bool *array) { jboolean isarr = env->CallBooleanMethod(cls, isArray); (*array) = isarr ? true : false; } - String name = env->GetStringUTFChars(clsName, NULL); + String name = jstring_to_string(clsName, env); env->DeleteLocalRef(clsName); return name; @@ -241,7 +242,7 @@ Variant _jobject_to_variant(JNIEnv *env, jobject obj) { if (name == "java.lang.String") { - return String::utf8(env->GetStringUTFChars((jstring)obj, NULL)); + return jstring_to_string((jstring)obj, env); }; if (name == "[Ljava.lang.String;") { @@ -252,7 +253,7 @@ Variant _jobject_to_variant(JNIEnv *env, jobject obj) { for (int i = 0; i < stringCount; i++) { jstring string = (jstring)env->GetObjectArrayElement(arr, i); - sarr.push_back(String::utf8(env->GetStringUTFChars(string, NULL))); + sarr.push_back(jstring_to_string(string, env)); env->DeleteLocalRef(string); } @@ -487,7 +488,7 @@ public: case Variant::STRING: { jobject o = env->CallObjectMethodA(instance, E->get().method, v); - ret = String::utf8(env->GetStringUTFChars((jstring)o, NULL)); + ret = jstring_to_string((jstring)o, env); env->DeleteLocalRef(o); } break; case Variant::POOL_STRING_ARRAY: { @@ -598,6 +599,7 @@ static jobject godot_io; typedef void (*GFXInitFunc)(void *ud, bool gl2); static jmethodID _on_video_init = 0; +static jmethodID _restart = 0; static jobject _godot_instance; static jmethodID _openURI = 0; @@ -619,6 +621,7 @@ static jmethodID _pauseVideo = 0; static jmethodID _stopVideo = 0; static jmethodID _setKeepScreenOn = 0; static jmethodID _alertDialog = 0; +static jmethodID _requestPermission = 0; static void _gfx_init_func(void *ud, bool gl2) { } @@ -634,20 +637,20 @@ static String _get_user_data_dir() { JNIEnv *env = ThreadAndroid::get_env(); jstring s = (jstring)env->CallObjectMethod(godot_io, _getDataDir); - return String(env->GetStringUTFChars(s, NULL)); + return jstring_to_string(s, env); } static String _get_locale() { JNIEnv *env = ThreadAndroid::get_env(); jstring s = (jstring)env->CallObjectMethod(godot_io, _getLocale); - return String(env->GetStringUTFChars(s, NULL)); + return jstring_to_string(s, env); } static String _get_clipboard() { JNIEnv *env = ThreadAndroid::get_env(); jstring s = (jstring)env->CallObjectMethod(_godot_instance, _getClipboard); - return String(env->GetStringUTFChars(s, NULL)); + return jstring_to_string(s, env); } static void _set_clipboard(const String &p_text) { @@ -661,7 +664,7 @@ static String _get_model() { JNIEnv *env = ThreadAndroid::get_env(); jstring s = (jstring)env->CallObjectMethod(godot_io, _getModel); - return String(env->GetStringUTFChars(s, NULL)); + return jstring_to_string(s, env); } static int _get_screen_dpi() { @@ -674,7 +677,7 @@ static String _get_unique_id() { JNIEnv *env = ThreadAndroid::get_env(); jstring s = (jstring)env->CallObjectMethod(godot_io, _getUniqueID); - return String(env->GetStringUTFChars(s, NULL)); + return jstring_to_string(s, env); } static void _show_vk(const String &p_existing) { @@ -694,7 +697,7 @@ static String _get_system_dir(int p_dir) { JNIEnv *env = ThreadAndroid::get_env(); jstring s = (jstring)env->CallObjectMethod(godot_io, _getSystemDir, p_dir); - return String(env->GetStringUTFChars(s, NULL)); + return jstring_to_string(s, env); } static int _get_gles_version_code() { @@ -744,6 +747,12 @@ static void _alert(const String &p_message, const String &p_title) { env->CallVoidMethod(_godot_instance, _alertDialog, jStrMessage, jStrTitle); } +static bool _request_permission(const String &p_name) { + JNIEnv *env = ThreadAndroid::get_env(); + jstring jStrName = env->NewStringUTF(p_name.utf8().get_data()); + return env->CallBooleanMethod(_godot_instance, _requestPermission, jStrName); +} + // volatile because it can be changed from non-main thread and we need to // ensure the change is immediately visible to other threads. static volatile int virtual_keyboard_height; @@ -756,7 +765,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setVirtualKeyboardHei virtual_keyboard_height = p_height; } -JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jobject obj, jobject activity, jboolean p_need_reload_hook, jobject p_asset_manager, jboolean p_use_apk_expansion) { +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jobject obj, jobject activity, jobject p_asset_manager, jboolean p_use_apk_expansion) { initialized = true; @@ -782,11 +791,13 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *en godot_io = gob; _on_video_init = env->GetMethodID(cls, "onVideoInit", "()V"); + _restart = env->GetMethodID(cls, "restart", "()V"); _setKeepScreenOn = env->GetMethodID(cls, "setKeepScreenOn", "(Z)V"); _alertDialog = env->GetMethodID(cls, "alert", "(Ljava/lang/String;Ljava/lang/String;)V"); _getGLESVersionCode = env->GetMethodID(cls, "getGLESVersionCode", "()I"); _getClipboard = env->GetMethodID(cls, "getClipboard", "()Ljava/lang/String;"); _setClipboard = env->GetMethodID(cls, "setClipboard", "(Ljava/lang/String;)V"); + _requestPermission = env->GetMethodID(cls, "requestPermission", "(Ljava/lang/String;)Z"); if (cls) { jclass c = env->GetObjectClass(gob); @@ -819,8 +830,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *en AudioDriverAndroid::setup(gob); } - os_android = new OS_Android(_gfx_init_func, env, _open_uri, _get_user_data_dir, _get_locale, _get_model, _get_screen_dpi, _show_vk, _hide_vk, _get_vk_height, _set_screen_orient, _get_unique_id, _get_system_dir, _get_gles_version_code, _play_video, _is_video_playing, _pause_video, _stop_video, _set_keep_screen_on, _alert, _set_clipboard, _get_clipboard, p_use_apk_expansion); - os_android->set_need_reload_hooks(p_need_reload_hook); + os_android = new OS_Android(_gfx_init_func, env, _open_uri, _get_user_data_dir, _get_locale, _get_model, _get_screen_dpi, _show_vk, _hide_vk, _get_vk_height, _set_screen_orient, _get_unique_id, _get_system_dir, _get_gles_version_code, _play_video, _is_video_playing, _pause_video, _stop_video, _set_keep_screen_on, _alert, _set_clipboard, _get_clipboard, _request_permission, p_use_apk_expansion); char wd[500]; getcwd(wd, 500); @@ -831,7 +841,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *en static void _initialize_java_modules() { if (!ProjectSettings::get_singleton()->has_setting("android/modules")) { - print_line("Android modules: Nothing to load, aborting"); return; } @@ -851,19 +860,16 @@ static void _initialize_java_modules() { jmethodID getClassLoader = env->GetMethodID(activityClass, "getClassLoader", "()Ljava/lang/ClassLoader;"); jobject cls = env->CallObjectMethod(_godot_instance, getClassLoader); - //cls=env->NewGlobalRef(cls); jclass classLoader = env->FindClass("java/lang/ClassLoader"); - //classLoader=(jclass)env->NewGlobalRef(classLoader); jmethodID findClass = env->GetMethodID(classLoader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;"); for (int i = 0; i < mods.size(); i++) { String m = mods[i]; - //jclass singletonClass = env->FindClass(m.utf8().get_data()); - print_line("Loading module: " + m); + print_line("Loading Android module: " + m); jstring strClassName = env->NewStringUTF(m.utf8().get_data()); jclass singletonClass = (jclass)env->CallObjectMethod(cls, findClass, strClassName); @@ -872,7 +878,6 @@ static void _initialize_java_modules() { ERR_EXPLAIN("Couldn't find singleton for class: " + m); ERR_CONTINUE(!singletonClass); } - //singletonClass=(jclass)env->NewGlobalRef(singletonClass); jmethodID initialize = env->GetStaticMethodID(singletonClass, "initialize", "(Landroid/app/Activity;)Lorg/godotengine/godot/Godot$SingletonBase;"); @@ -891,12 +896,14 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jo ThreadAndroid::setup_thread(); const char **cmdline = NULL; + jstring *j_cmdline = NULL; int cmdlen = 0; if (p_cmdline) { cmdlen = env->GetArrayLength(p_cmdline); if (cmdlen) { - cmdline = (const char **)malloc((env->GetArrayLength(p_cmdline) + 1) * sizeof(const char *)); + cmdline = (const char **)malloc((cmdlen + 1) * sizeof(const char *)); cmdline[cmdlen] = NULL; + j_cmdline = (jstring *)malloc(cmdlen * sizeof(jstring)); for (int i = 0; i < cmdlen; i++) { @@ -904,12 +911,19 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jo const char *rawString = env->GetStringUTFChars(string, 0); cmdline[i] = rawString; + j_cmdline[i] = string; } } } Error err = Main::setup("apk", cmdlen, (char **)cmdline, false); if (cmdline) { + if (j_cmdline) { + for (int i = 0; i < cmdlen; ++i) { + env->ReleaseStringUTFChars(j_cmdline[i], cmdline[i]); + } + free(j_cmdline); + } free(cmdline); } @@ -922,7 +936,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jo _initialize_java_modules(); } -JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, jobject obj, jint width, jint height, jboolean reload) { +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, jobject obj, jint width, jint height) { if (os_android) os_android->set_display_size(Size2(width, height)); @@ -931,12 +945,15 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, j JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *env, jobject obj, bool p_32_bits) { if (os_android) { - os_android->set_context_is_16_bits(!p_32_bits); - } - - if (os_android && step > 0) { - - os_android->reload_gfx(); + if (step == 0) { + // During startup + os_android->set_context_is_16_bits(!p_32_bits); + } else { + // GL context recreated because it was lost; restart app to let it reload everything + os_android->main_loop_end(); + env->CallVoidMethod(_godot_instance, _restart); + step = -1; // Ensure no further steps are attempted + } } } @@ -948,6 +965,9 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_back(JNIEnv *env, job } JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, jobject obj) { + if (step == -1) + return; + if (step == 0) { // Since Godot is initialized on the UI thread, _main_thread_id was set to that thread's id, @@ -1313,7 +1333,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyhat(JNIEnv *env, j JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyconnectionchanged(JNIEnv *env, jobject obj, jint p_device, jboolean p_connected, jstring p_name) { if (os_android) { - String name = env->GetStringUTFChars(p_name, NULL); + String name = jstring_to_string(p_name, env); os_android->joy_connection_changed(p_device, p_connected, name); } } @@ -1386,7 +1406,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_audio(JNIEnv *env, jo JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_singleton(JNIEnv *env, jobject obj, jstring name, jobject p_object) { - String singname = env->GetStringUTFChars(name, NULL); + String singname = jstring_to_string(name, env); JNISingleton *s = memnew(JNISingleton); s->set_instance(env->NewGlobalRef(p_object)); jni_singletons[singname] = s; @@ -1463,21 +1483,21 @@ static const char *get_jni_sig(const String &p_type) { JNIEXPORT jstring JNICALL Java_org_godotengine_godot_GodotLib_getGlobal(JNIEnv *env, jobject obj, jstring path) { - String js = env->GetStringUTFChars(path, NULL); + String js = jstring_to_string(path, env); return env->NewStringUTF(ProjectSettings::get_singleton()->get(js).operator String().utf8().get_data()); } JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_method(JNIEnv *env, jobject obj, jstring sname, jstring name, jstring ret, jobjectArray args) { - String singname = env->GetStringUTFChars(sname, NULL); + String singname = jstring_to_string(sname, env); ERR_FAIL_COND(!jni_singletons.has(singname)); JNISingleton *s = jni_singletons.get(singname); - String mname = env->GetStringUTFChars(name, NULL); - String retval = env->GetStringUTFChars(ret, NULL); + String mname = jstring_to_string(name, env); + String retval = jstring_to_string(ret, env); Vector<Variant::Type> types; String cs = "("; @@ -1486,9 +1506,9 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_method(JNIEnv *env, j for (int i = 0; i < stringCount; i++) { jstring string = (jstring)env->GetObjectArrayElement(args, i); - const char *rawString = env->GetStringUTFChars(string, 0); - types.push_back(get_jni_type(String(rawString))); - cs += get_jni_sig(String(rawString)); + const String rawString = jstring_to_string(string, env); + types.push_back(get_jni_type(rawString)); + cs += get_jni_sig(rawString); } cs += ")"; @@ -1511,7 +1531,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_callobject(JNIEnv *en int res = env->PushLocalFrame(16); ERR_FAIL_COND(res != 0); - String str_method = env->GetStringUTFChars(method, NULL); + String str_method = jstring_to_string(method, env); int count = env->GetArrayLength(params); Variant *vlist = (Variant *)alloca(sizeof(Variant) * count); @@ -1543,7 +1563,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_calldeferred(JNIEnv * int res = env->PushLocalFrame(16); ERR_FAIL_COND(res != 0); - String str_method = env->GetStringUTFChars(method, NULL); + String str_method = jstring_to_string(method, env); int count = env->GetArrayLength(params); Variant args[VARIANT_ARG_MAX]; @@ -1561,6 +1581,9 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_calldeferred(JNIEnv * env->PopLocalFrame(NULL); } -//Main::cleanup(); - -//return os.get_exit_code(); +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_requestPermissionResult(JNIEnv *env, jobject p_obj, jstring p_permission, jboolean p_result) { + String permission = jstring_to_string(p_permission, env); + if (permission == "android.permission.RECORD_AUDIO" && p_result) { + AudioDriver::get_singleton()->capture_start(); + } +} diff --git a/platform/android/java_glue.h b/platform/android/java_glue.h index e8d0d55bb3..3b93c9b42a 100644 --- a/platform/android/java_glue.h +++ b/platform/android/java_glue.h @@ -35,9 +35,9 @@ #include <jni.h> extern "C" { -JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jobject obj, jobject activity, jboolean p_need_reload_hook, jobject p_asset_manager, jboolean p_use_apk_expansion); +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jobject obj, jobject activity, jobject p_asset_manager, jboolean p_use_apk_expansion); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jobject obj, jobjectArray p_cmdline); -JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, jobject obj, jint width, jint height, jboolean reload); +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, jobject obj, jint width, jint height); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *env, jobject obj, bool p_32_bits); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, jobject obj); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_back(JNIEnv *env, jobject obj); @@ -60,6 +60,7 @@ JNIEXPORT jstring JNICALL Java_org_godotengine_godot_GodotLib_getGlobal(JNIEnv * JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_callobject(JNIEnv *env, jobject p_obj, jint ID, jstring method, jobjectArray params); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_calldeferred(JNIEnv *env, jobject p_obj, jint ID, jstring method, jobjectArray params); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setVirtualKeyboardHeight(JNIEnv *env, jobject obj, jint p_height); +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_requestPermissionResult(JNIEnv *env, jobject p_obj, jstring p_permission, jboolean p_result); } #endif // JAVA_GLUE_H diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 2ee0b34c48..837713f9c9 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -131,7 +131,7 @@ Error OS_Android::initialize(const VideoMode &p_desired, int p_video_driver, int RasterizerGLES3::make_current(); break; } else { - if (GLOBAL_GET("rendering/quality/driver/driver_fallback") == "Best") { + if (GLOBAL_GET("rendering/quality/driver/fallback_to_gles2")) { p_video_driver = VIDEO_DRIVER_GLES2; use_gl3 = false; continue; @@ -175,7 +175,7 @@ Error OS_Android::initialize(const VideoMode &p_desired, int p_video_driver, int input = memnew(InputDefault); input->set_fallback_mapping("Default Android Gamepad"); - //power_manager = memnew(power_android); + //power_manager = memnew(PowerAndroid); return OK; } @@ -202,6 +202,12 @@ void OS_Android::alert(const String &p_alert, const String &p_title) { alert_func(p_alert, p_title); } +bool OS_Android::request_permission(const String &p_name) { + if (request_permission_func) + return request_permission_func(p_name); + return false; +} + Error OS_Android::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) { p_library_handle = dlopen(p_path.utf8().get_data(), RTLD_NOW); if (!p_library_handle) { @@ -548,14 +554,6 @@ void OS_Android::set_display_size(Size2 p_size) { default_videomode.height = p_size.y; } -void OS_Android::reload_gfx() { - - if (gfx_init_func) - gfx_init_func(gfx_init_ud, use_gl2); - //if (rasterizer) - // rasterizer->reload_vram(); -} - Error OS_Android::shell_open(String p_uri) { if (open_uri_func) @@ -607,11 +605,6 @@ int OS_Android::get_screen_dpi(int p_screen) const { return 160; } -void OS_Android::set_need_reload_hooks(bool p_needs_them) { - - use_reload_hooks = p_needs_them; -} - String OS_Android::get_user_data_dir() const { if (data_dir_cache != String()) @@ -706,7 +699,7 @@ String OS_Android::get_joy_guid(int p_device) const { } bool OS_Android::_check_internal_feature_support(const String &p_feature) { - if (p_feature == "mobile" || p_feature == "etc" || p_feature == "etc2") { + if (p_feature == "mobile") { //TODO support etc2 only if GLES3 driver is selected return true; } @@ -726,7 +719,7 @@ bool OS_Android::_check_internal_feature_support(const String &p_feature) { return false; } -OS_Android::OS_Android(GFXInitFunc p_gfx_init_func, void *p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetUserDataDirFunc p_get_user_data_dir_func, GetLocaleFunc p_get_locale_func, GetModelFunc p_get_model_func, GetScreenDPIFunc p_get_screen_dpi_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, VirtualKeyboardHeightFunc p_vk_height_func, SetScreenOrientationFunc p_screen_orient, GetUniqueIDFunc p_get_unique_id, GetSystemDirFunc p_get_sdir_func, GetGLVersionCodeFunc p_get_gl_version_func, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func, SetKeepScreenOnFunc p_set_keep_screen_on_func, AlertFunc p_alert_func, SetClipboardFunc p_set_clipboard_func, GetClipboardFunc p_get_clipboard_func, bool p_use_apk_expansion) { +OS_Android::OS_Android(GFXInitFunc p_gfx_init_func, void *p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetUserDataDirFunc p_get_user_data_dir_func, GetLocaleFunc p_get_locale_func, GetModelFunc p_get_model_func, GetScreenDPIFunc p_get_screen_dpi_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, VirtualKeyboardHeightFunc p_vk_height_func, SetScreenOrientationFunc p_screen_orient, GetUniqueIDFunc p_get_unique_id, GetSystemDirFunc p_get_sdir_func, GetGLVersionCodeFunc p_get_gl_version_func, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func, SetKeepScreenOnFunc p_set_keep_screen_on_func, AlertFunc p_alert_func, SetClipboardFunc p_set_clipboard_func, GetClipboardFunc p_get_clipboard_func, RequestPermissionFunc p_request_permission, bool p_use_apk_expansion) { use_apk_expansion = p_use_apk_expansion; default_videomode.width = 800; @@ -765,7 +758,7 @@ OS_Android::OS_Android(GFXInitFunc p_gfx_init_func, void *p_gfx_init_ud, OpenURI set_screen_orientation_func = p_screen_orient; set_keep_screen_on_func = p_set_keep_screen_on_func; alert_func = p_alert_func; - use_reload_hooks = false; + request_permission_func = p_request_permission; Vector<Logger *> loggers; loggers.push_back(memnew(AndroidLogger)); diff --git a/platform/android/os_android.h b/platform/android/os_android.h index 3c591af4bb..44c5a206d4 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -63,6 +63,7 @@ typedef void (*VideoStopFunc)(); typedef void (*SetKeepScreenOnFunc)(bool p_enabled); typedef void (*AlertFunc)(const String &, const String &); typedef int (*VirtualKeyboardHeightFunc)(); +typedef bool (*RequestPermissionFunc)(const String &); class OS_Android : public OS_Unix { public: @@ -94,7 +95,6 @@ private: void *gfx_init_ud; bool use_gl2; - bool use_reload_hooks; bool use_apk_expansion; bool use_16bits_fbo; @@ -133,8 +133,9 @@ private: VideoStopFunc video_stop_func; SetKeepScreenOnFunc set_keep_screen_on_func; AlertFunc alert_func; + RequestPermissionFunc request_permission_func; - //power_android *power_manager; + //PowerAndroid *power_manager; int video_driver_index; public: @@ -160,6 +161,7 @@ public: static OS *get_singleton(); virtual void alert(const String &p_alert, const String &p_title = "ALERT!"); + virtual bool request_permission(const String &p_name); virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false); @@ -203,10 +205,8 @@ public: void set_opengl_extensions(const char *p_gl_extensions); void set_display_size(Size2 p_size); - void reload_gfx(); void set_context_is_16_bits(bool p_is_16); - void set_need_reload_hooks(bool p_needs_them); virtual void set_screen_orientation(ScreenOrientation p_orientation); virtual Error shell_open(String p_uri); @@ -241,7 +241,7 @@ public: void joy_connection_changed(int p_device, bool p_connected, String p_name); virtual bool _check_internal_feature_support(const String &p_feature); - OS_Android(GFXInitFunc p_gfx_init_func, void *p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetUserDataDirFunc p_get_user_data_dir_func, GetLocaleFunc p_get_locale_func, GetModelFunc p_get_model_func, GetScreenDPIFunc p_get_screen_dpi_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, VirtualKeyboardHeightFunc p_vk_height_func, SetScreenOrientationFunc p_screen_orient, GetUniqueIDFunc p_get_unique_id, GetSystemDirFunc p_get_sdir_func, GetGLVersionCodeFunc p_get_gl_version_func, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func, SetKeepScreenOnFunc p_set_keep_screen_on_func, AlertFunc p_alert_func, SetClipboardFunc p_set_clipboard, GetClipboardFunc p_get_clipboard, bool p_use_apk_expansion); + OS_Android(GFXInitFunc p_gfx_init_func, void *p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetUserDataDirFunc p_get_user_data_dir_func, GetLocaleFunc p_get_locale_func, GetModelFunc p_get_model_func, GetScreenDPIFunc p_get_screen_dpi_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, VirtualKeyboardHeightFunc p_vk_height_func, SetScreenOrientationFunc p_screen_orient, GetUniqueIDFunc p_get_unique_id, GetSystemDirFunc p_get_sdir_func, GetGLVersionCodeFunc p_get_gl_version_func, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func, SetKeepScreenOnFunc p_set_keep_screen_on_func, AlertFunc p_alert_func, SetClipboardFunc p_set_clipboard, GetClipboardFunc p_get_clipboard, RequestPermissionFunc p_request_permission, bool p_use_apk_expansion); ~OS_Android(); }; diff --git a/platform/android/power_android.cpp b/platform/android/power_android.cpp index 40b9d81189..4d2fbfbf1a 100644 --- a/platform/android/power_android.cpp +++ b/platform/android/power_android.cpp @@ -190,7 +190,7 @@ int Android_JNI_GetPowerInfo(int *plugged, int *charged, int *battery, int *seco return 0; } -bool power_android::GetPowerInfo_Android() { +bool PowerAndroid::GetPowerInfo_Android() { int battery; int plugged; int charged; @@ -218,7 +218,7 @@ bool power_android::GetPowerInfo_Android() { return true; } -OS::PowerState power_android::get_power_state() { +OS::PowerState PowerAndroid::get_power_state() { if (GetPowerInfo_Android()) { return power_state; } else { @@ -227,7 +227,7 @@ OS::PowerState power_android::get_power_state() { } } -int power_android::get_power_seconds_left() { +int PowerAndroid::get_power_seconds_left() { if (GetPowerInfo_Android()) { return nsecs_left; } else { @@ -236,7 +236,7 @@ int power_android::get_power_seconds_left() { } } -int power_android::get_power_percent_left() { +int PowerAndroid::get_power_percent_left() { if (GetPowerInfo_Android()) { return percent_left; } else { @@ -245,11 +245,11 @@ int power_android::get_power_percent_left() { } } -power_android::power_android() : +PowerAndroid::PowerAndroid() : nsecs_left(-1), percent_left(-1), power_state(OS::POWERSTATE_UNKNOWN) { } -power_android::~power_android() { +PowerAndroid::~PowerAndroid() { } diff --git a/platform/android/power_android.h b/platform/android/power_android.h index 9730c53674..6cb745b6c0 100644 --- a/platform/android/power_android.h +++ b/platform/android/power_android.h @@ -28,13 +28,14 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PLATFORM_ANDROID_POWER_ANDROID_H_ -#define PLATFORM_ANDROID_POWER_ANDROID_H_ +#ifndef POWER_ANDROID_H +#define POWER_ANDROID_H #include "core/os/os.h" + #include <android/native_window_jni.h> -class power_android { +class PowerAndroid { struct LocalReferenceHolder { JNIEnv *m_env; @@ -65,8 +66,8 @@ private: public: static int s_active; - power_android(); - virtual ~power_android(); + PowerAndroid(); + virtual ~PowerAndroid(); static bool LocalReferenceHolder_Init(struct LocalReferenceHolder *refholder, JNIEnv *env); static struct LocalReferenceHolder LocalReferenceHolder_Setup(const char *func); static void LocalReferenceHolder_Cleanup(struct LocalReferenceHolder *refholder); @@ -76,4 +77,4 @@ public: int get_power_percent_left(); }; -#endif /* PLATFORM_ANDROID_POWER_ANDROID_H_ */ +#endif // POWER_ANDROID_H diff --git a/platform/android/string_android.h b/platform/android/string_android.h new file mode 100644 index 0000000000..fe627a3e0c --- /dev/null +++ b/platform/android/string_android.h @@ -0,0 +1,58 @@ +/*************************************************************************/ +/* string_android.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 STRING_ANDROID_H +#define STRING_ANDROID_H +#include "core/ustring.h" +#include "thread_jandroid.h" +#include <jni.h> + +/** + * Converts JNI jstring to Godot String. + * @param source Source JNI string. If null an empty string is returned. + * @param env JNI environment instance. If null obtained by ThreadAndroid::get_env(). + * @return Godot string instance. + */ +static inline String jstring_to_string(jstring source, JNIEnv *env = NULL) { + String result; + if (source) { + if (!env) { + env = ThreadAndroid::get_env(); + } + const char *const source_utf8 = env->GetStringUTFChars(source, NULL); + if (source_utf8) { + result.parse_utf8(source_utf8); + env->ReleaseStringUTFChars(source, source_utf8); + } + } + return result; +} + +#endif // STRING_ANDROID_H diff --git a/platform/haiku/os_haiku.cpp b/platform/haiku/os_haiku.cpp index a5b2e66a22..a6d5a00852 100644 --- a/platform/haiku/os_haiku.cpp +++ b/platform/haiku/os_haiku.cpp @@ -322,7 +322,7 @@ String OS_Haiku::get_executable_path() const { bool OS_Haiku::_check_internal_feature_support(const String &p_feature) { - return p_feature == "pc" || p_feature == "s3tc"; + return p_feature == "pc"; } String OS_Haiku::get_config_path() const { diff --git a/platform/iphone/SCsub b/platform/iphone/SCsub index d5540fe8db..41991bce86 100644 --- a/platform/iphone/SCsub +++ b/platform/iphone/SCsub @@ -7,7 +7,7 @@ import os iphone_lib = [ 'godot_iphone.cpp', 'os_iphone.cpp', - 'sem_iphone.cpp', + 'semaphore_iphone.cpp', 'gl_view.mm', 'main.m', 'app_delegate.mm', diff --git a/platform/iphone/app_delegate.mm b/platform/iphone/app_delegate.mm index bb0c11c767..64405bfa5b 100644 --- a/platform/iphone/app_delegate.mm +++ b/platform/iphone/app_delegate.mm @@ -598,8 +598,10 @@ static int frame_count = 0; }; - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application { - OS::get_singleton()->get_main_loop()->notification( - MainLoop::NOTIFICATION_OS_MEMORY_WARNING); + if (OS::get_singleton()->get_main_loop()) { + OS::get_singleton()->get_main_loop()->notification( + MainLoop::NOTIFICATION_OS_MEMORY_WARNING); + } }; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { @@ -613,18 +615,6 @@ static int frame_count = 0; // Create a full-screen window window = [[UIWindow alloc] initWithFrame:rect]; - // window.autoresizesSubviews = YES; - //[window setAutoresizingMask:UIViewAutoresizingFlexibleWidth | - // UIViewAutoresizingFlexibleWidth]; - - // Create the OpenGL ES view and add it to the window - GLView *glView = [[GLView alloc] initWithFrame:rect]; - printf("glview is %p\n", glView); - //[window addSubview:glView]; - glView.delegate = self; - // glView.autoresizesSubviews = YES; - //[glView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | - // UIViewAutoresizingFlexibleWidth]; OS::VideoMode vm = _get_video_mode(); @@ -639,6 +629,12 @@ static int frame_count = 0; return FALSE; }; + // WARNING: We must *always* create the GLView after we have constructed the + // OS with iphone_main. This allows the GLView to access project settings so + // it can properly initialize the OpenGL context + GLView *glView = [[GLView alloc] initWithFrame:rect]; + glView.delegate = self; + view_controller = [[ViewController alloc] init]; view_controller.view = glView; window.rootViewController = view_controller; diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py index d0e6a4cefe..172572bcb4 100644 --- a/platform/iphone/detect.py +++ b/platform/iphone/detect.py @@ -174,11 +174,3 @@ def configure(env): env.Append(CPPPATH=['#platform/iphone']) env.Append(CPPFLAGS=['-DIPHONE_ENABLED', '-DUNIX_ENABLED', '-DGLES_ENABLED', '-DCOREAUDIO_ENABLED']) - - # TODO: Move that to opus module's config - if 'module_opus_enabled' in env and env['module_opus_enabled']: - env.opus_fixed_point = "yes" - if (env["arch"] == "arm"): - env.Append(CFLAGS=["-DOPUS_ARM_OPT"]) - elif (env["arch"] == "arm64"): - env.Append(CFLAGS=["-DOPUS_ARM64_OPT"]) diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp index 849e6d4a14..85d4b9e847 100644 --- a/platform/iphone/export/export.cpp +++ b/platform/iphone/export/export.cpp @@ -196,15 +196,16 @@ public: void EditorExportPlatformIOS::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) { - if (p_preset->get("texture_format/s3tc")) { - r_features->push_back("s3tc"); - } - if (p_preset->get("texture_format/etc")) { + String driver = ProjectSettings::get_singleton()->get("rendering/quality/driver/driver_name"); + if (driver == "GLES2") { r_features->push_back("etc"); - } - if (p_preset->get("texture_format/etc2")) { + } else if (driver == "GLES3") { r_features->push_back("etc2"); + if (ProjectSettings::get_singleton()->get("rendering/quality/driver/fallback_to_gles2")) { + r_features->push_back("etc"); + } } + Vector<String> architectures = _get_preset_architectures(p_preset); for (int i = 0; i < architectures.size(); ++i) { r_features->push_back(architectures[i]); @@ -246,7 +247,7 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/app_store_team_id"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/provisioning_profile_uuid_debug"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/code_sign_identity_debug", PROPERTY_HINT_PLACEHOLDER_TEXT, "iPhone Developer"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/code_sign_identity_debug", PROPERTY_HINT_PLACEHOLDER_TEXT, "iPhone Developer"), "iPhone Developer")); r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/export_method_debug", PROPERTY_HINT_ENUM, "App Store,Development,Ad-Hoc,Enterprise"), 1)); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/provisioning_profile_uuid_release"), "")); @@ -255,12 +256,26 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/info"), "Made with Godot Engine")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/identifier", PROPERTY_HINT_PLACEHOLDER_TEXT, "come.example.game"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/identifier", PROPERTY_HINT_PLACEHOLDER_TEXT, "com.example.game"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/signature"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version"), "1.0")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/arkit"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/access_wifi"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/game_center"), true)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/in_app_purchases"), false)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/push_notifications"), false)); + + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/camera_usage_description"), "Godot would like to use your camera")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/photolibrary_usage_description"), "Godot would like to use your photos")); + + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "orientation/portrait"), true)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "orientation/landscape_left"), true)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "orientation/landscape_right"), true)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "orientation/portrait_upside_down"), true)); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "required_icons/iphone_120x120", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPhone/iPod Touch with retina display r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "required_icons/ipad_76x76", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPad r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "required_icons/app_store_1024x1024", PROPERTY_HINT_FILE, "*.png"), "")); // App Store @@ -275,10 +290,6 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, loading_screen_infos[i].preset_key, PROPERTY_HINT_FILE, "*.png"), "")); } - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/s3tc"), false)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc"), false)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc2"), true)); - Vector<ExportArchitecture> architectures = _get_supported_architectures(); for (int i = 0; i < architectures.size(); ++i) { r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "architectures/" + architectures[i].name), architectures[i].is_default)); @@ -337,6 +348,59 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_ strnew += lines[i].replace("$linker_flags", p_config.linker_flags) + "\n"; } else if (lines[i].find("$cpp_code") != -1) { strnew += lines[i].replace("$cpp_code", p_config.cpp_code) + "\n"; + } else if (lines[i].find("$access_wifi") != -1) { + bool is_on = p_preset->get("capabilities/access_wifi"); + strnew += lines[i].replace("$access_wifi", is_on ? "1" : "0") + "\n"; + } else if (lines[i].find("$game_center") != -1) { + bool is_on = p_preset->get("capabilities/game_center"); + strnew += lines[i].replace("$game_center", is_on ? "1" : "0") + "\n"; + } else if (lines[i].find("$in_app_purchases") != -1) { + bool is_on = p_preset->get("capabilities/in_app_purchases"); + strnew += lines[i].replace("$in_app_purchases", is_on ? "1" : "0") + "\n"; + } else if (lines[i].find("$push_notifications") != -1) { + bool is_on = p_preset->get("capabilities/push_notifications"); + strnew += lines[i].replace("$push_notifications", is_on ? "1" : "0") + "\n"; + } else if (lines[i].find("$required_device_capabilities") != -1) { + String capabilities; + + // I've removed armv7 as we can run on 64bit only devices + // Note that capabilities listed here are requirements for the app to be installed. + // They don't enable anything. + + if ((bool)p_preset->get("capabilities/arkit")) { + capabilities += "<string>arkit</string>\n"; + } + if ((bool)p_preset->get("capabilities/game_center")) { + capabilities += "<string>gamekit</string>\n"; + } + if ((bool)p_preset->get("capabilities/access_wifi")) { + capabilities += "<string>wifi</string>\n"; + } + + strnew += lines[i].replace("$required_device_capabilities", capabilities); + } else if (lines[i].find("$interface_orientations") != -1) { + String orientations; + + if ((bool)p_preset->get("orientation/portrait")) { + orientations += "<string>UIInterfaceOrientationPortrait</string>\n"; + } + if ((bool)p_preset->get("orientation/landscape_left")) { + orientations += "<string>UIInterfaceOrientationLandscapeLeft</string>\n"; + } + if ((bool)p_preset->get("orientation/landscape_right")) { + orientations += "<string>UIInterfaceOrientationLandscapeRight</string>\n"; + } + if ((bool)p_preset->get("orientation/portrait_upside_down")) { + orientations += "<string>UIInterfaceOrientationPortraitUpsideDown</string>\n"; + } + + strnew += lines[i].replace("$interface_orientations", orientations); + } else if (lines[i].find("$camera_usage_description") != -1) { + String description = p_preset->get("privacy/camera_usage_description"); + strnew += lines[i].replace("$camera_usage_description", description) + "\n"; + } else if (lines[i].find("$photolibrary_usage_description") != -1) { + String description = p_preset->get("privacy/photolibrary_usage_description"); + strnew += lines[i].replace("$photolibrary_usage_description", description) + "\n"; } else { strnew += lines[i] + "\n"; } @@ -648,6 +712,10 @@ void EditorExportPlatformIOS::_add_assets_to_project(Vector<uint8_t> &p_project_ pbx_files += file_info_format.format(format_dict, "$_"); } + // Note, frameworks like gamekit are always included in our project.pbxprof file + // even if turned off in capabilities. + // Frameworks that are used by modules (like arkit) we may need to optionally add here. + String str = String::utf8((const char *)p_project_data.ptr(), p_project_data.size()); str = str.replace("$additional_pbx_files", pbx_files); str = str.replace("$additional_pbx_frameworks_build", pbx_frameworks_build); @@ -771,6 +839,10 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p } } + if (!DirAccess::exists(dest_dir)) { + return ERR_FILE_BAD_PATH; + } + DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); if (da) { String current_dir = da->get_current_dir(); @@ -1075,6 +1147,12 @@ bool EditorExportPlatformIOS::can_export(const Ref<EditorExportPreset> &p_preset } } + String etc_error = test_etc2(); + if (etc_error != String()) { + valid = false; + err += etc_error; + } + if (!err.empty()) r_error = err; diff --git a/platform/iphone/gl_view.mm b/platform/iphone/gl_view.mm index 6f4d0ddb57..1cb8d0e44e 100644 --- a/platform/iphone/gl_view.mm +++ b/platform/iphone/gl_view.mm @@ -284,19 +284,37 @@ static void clear_touches() { kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil]; + bool fallback_gl2 = false; + // Create a GL ES 3 context based on the gl driver from project settings + if (GLOBAL_GET("rendering/quality/driver/driver_name") == "GLES3") { + context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3]; + NSLog(@"Setting up an OpenGL ES 3.0 context. Based on Project Settings \"rendering/quality/driver/driver_name\""); + if (!context && GLOBAL_GET("rendering/quality/driver/fallback_to_gles2")) { + gles3_available = false; + fallback_gl2 = true; + NSLog(@"Failed to create OpenGL ES 3.0 context. Falling back to OpenGL ES 2.0"); + } + } - // Create our EAGLContext, and if successful make it current and create our framebuffer. - context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3]; - - if (!context || ![EAGLContext setCurrentContext:context] || ![self createFramebuffer]) { + // Create GL ES 2 context + if (GLOBAL_GET("rendering/quality/driver/driver_name") == "GLES2" || fallback_gl2) { context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - gles3_available = false; - if (!context || ![EAGLContext setCurrentContext:context] || ![self createFramebuffer]) { - [self release]; + NSLog(@"Setting up an OpenGL ES 2.0 context."); + if (!context) { + NSLog(@"Failed to create OpenGL ES 2.0 context!"); return nil; } } + if (![EAGLContext setCurrentContext:context]) { + NSLog(@"Failed to set EAGLContext!"); + return nil; + } + if (![self createFramebuffer]) { + NSLog(@"Failed to create frame buffer!"); + return nil; + } + // Default the animation interval to 1/60th of a second. animationInterval = 1.0 / 60.0; return self; diff --git a/platform/iphone/os_iphone.cpp b/platform/iphone/os_iphone.cpp index 16634c3b30..7d0fdd2078 100644 --- a/platform/iphone/os_iphone.cpp +++ b/platform/iphone/os_iphone.cpp @@ -45,9 +45,10 @@ #include "core/project_settings.h" #include "drivers/unix/syslog_logger.h" -#include "sem_iphone.h" +#include "semaphore_iphone.h" #include "ios.h" + #include <dlfcn.h> int OSIPhone::get_video_driver_count() const { @@ -119,7 +120,7 @@ Error OSIPhone::initialize(const VideoMode &p_desired, int p_video_driver, int p RasterizerGLES3::make_current(); break; } else { - if (GLOBAL_GET("rendering/quality/driver/driver_fallback") == "Best") { + if (GLOBAL_GET("rendering/quality/driver/fallback_to_gles2")) { p_video_driver = VIDEO_DRIVER_GLES2; use_gl3 = false; continue; @@ -586,7 +587,7 @@ void OSIPhone::native_video_stop() { bool OSIPhone::_check_internal_feature_support(const String &p_feature) { - return p_feature == "mobile" || p_feature == "etc" || p_feature == "pvrtc" || p_feature == "etc2"; + return p_feature == "mobile"; } // Initialization order between compilation units is not guaranteed, diff --git a/platform/iphone/power_iphone.h b/platform/iphone/power_iphone.h index eb930b99c5..d7d4bf4a69 100644 --- a/platform/iphone/power_iphone.h +++ b/platform/iphone/power_iphone.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PLATFORM_IPHONE_POWER_IPHONE_H_ -#define PLATFORM_IPHONE_POWER_IPHONE_H_ +#ifndef POWER_IPHONE_H +#define POWER_IPHONE_H #include <os/os.h> @@ -50,4 +50,4 @@ public: int get_power_percent_left(); }; -#endif /* PLATFORM_IPHONE_POWER_IPHONE_H_ */ +#endif // POWER_IPHONE_H diff --git a/platform/iphone/sem_iphone.cpp b/platform/iphone/semaphore_iphone.cpp index 05cdb6a2f7..cc7dde72f7 100644 --- a/platform/iphone/sem_iphone.cpp +++ b/platform/iphone/semaphore_iphone.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* sem_iphone.cpp */ +/* semaphore_iphone.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "sem_iphone.h" +#include "semaphore_iphone.h" #include <fcntl.h> #include <unistd.h> @@ -71,6 +71,7 @@ void cgsem_destroy(cgsem_t *cgsem) { } #include "core/os/memory.h" + #include <errno.h> Error SemaphoreIphone::wait() { diff --git a/platform/iphone/sem_iphone.h b/platform/iphone/semaphore_iphone.h index 134bc723d9..16658384e6 100644 --- a/platform/iphone/sem_iphone.h +++ b/platform/iphone/semaphore_iphone.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* sem_iphone.h */ +/* semaphore_iphone.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SEM_IPHONE_H -#define SEM_IPHONE_H +#ifndef SEMAPHORE_IPHONE_H +#define SEMAPHORE_IPHONE_H struct cgsem { int pipefd[2]; @@ -56,4 +56,4 @@ public: ~SemaphoreIphone(); }; -#endif +#endif // SEMAPHORE_IPHONE_H diff --git a/platform/javascript/audio_driver_javascript.cpp b/platform/javascript/audio_driver_javascript.cpp index 16fdc267f3..11104007e2 100644 --- a/platform/javascript/audio_driver_javascript.cpp +++ b/platform/javascript/audio_driver_javascript.cpp @@ -209,7 +209,7 @@ Error AudioDriverJavaScript::capture_start() { } function gotMediaInputError(e) { - console.log(e); + out(e); } if (navigator.mediaDevices.getUserMedia) { diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py index 22b5f1f87a..47da8de5df 100644 --- a/platform/javascript/detect.py +++ b/platform/javascript/detect.py @@ -129,10 +129,6 @@ def configure(env): # us since we don't know requirements at compile-time. env.Append(LINKFLAGS=['-s', 'ALLOW_MEMORY_GROWTH=1']) - # Since we use both memory growth and MEMFS preloading, - # this avoids unecessary copying on start-up. - env.Append(LINKFLAGS=['--no-heap-copy']) - # This setting just makes WebGL 2 APIs available, it does NOT disable WebGL 1. env.Append(LINKFLAGS=['-s', 'USE_WEBGL2=1']) @@ -140,7 +136,3 @@ def configure(env): # 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. - if 'module_opus_enabled' in env and env['module_opus_enabled']: - env.opus_fixed_point = 'yes' diff --git a/platform/javascript/engine.js b/platform/javascript/engine.js index 91458eb4c3..860d6707ff 100644 --- a/platform/javascript/engine.js +++ b/platform/javascript/engine.js @@ -199,7 +199,8 @@ } LIBS.FS.mkdirTree(dir); } - LIBS.FS.createDataFile('/', file.path, new Uint8Array(file.buffer), true, true, true); + // With memory growth, canOwn should be false. + LIBS.FS.createDataFile(file.path, null, new Uint8Array(file.buffer), true, true, false); }, this); preloadedFiles = null; diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp index 123c6ae645..487da77b10 100644 --- a/platform/javascript/export/export.cpp +++ b/platform/javascript/export/export.cpp @@ -104,22 +104,27 @@ void EditorExportPlatformJavaScript::_fix_html(Vector<uint8_t> &p_html, const Re void EditorExportPlatformJavaScript::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) { - if (p_preset->get("texture_format/s3tc")) { + if (p_preset->get("vram_texture_compression/for_desktop")) { r_features->push_back("s3tc"); } - if (p_preset->get("texture_format/etc")) { - r_features->push_back("etc"); - } - if (p_preset->get("texture_format/etc2")) { - r_features->push_back("etc2"); + + if (p_preset->get("vram_texture_compression/for_mobile")) { + String driver = ProjectSettings::get_singleton()->get("rendering/quality/driver/driver_name"); + if (driver == "GLES2") { + r_features->push_back("etc"); + } else if (driver == "GLES3") { + r_features->push_back("etc2"); + if (ProjectSettings::get_singleton()->get("rendering/quality/driver/fallback_to_gles2")) { + r_features->push_back("etc"); + } + } } } void EditorExportPlatformJavaScript::get_export_options(List<ExportOption> *r_options) { - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/s3tc"), true)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc"), false)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc2"), true)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "vram_texture_compression/for_desktop"), true)); // S3TC + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "vram_texture_compression/for_mobile"), false)); // ETC or ETC2, depending on renderer r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "html/custom_html_shell", PROPERTY_HINT_FILE, "*.html"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "html/head_include", PROPERTY_HINT_MULTILINE_TEXT), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), "")); @@ -167,10 +172,19 @@ bool EditorExportPlatformJavaScript::can_export(const Ref<EditorExportPreset> &p } } + r_missing_templates = !valid; + + if (p_preset->get("vram_texture_compression/for_mobile")) { + String etc_error = test_etc2(); + if (etc_error != String()) { + valid = false; + err += etc_error; + } + } + if (!err.empty()) r_error = err; - r_missing_templates = !valid; return valid; } @@ -200,6 +214,10 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese template_path = find_export_template(EXPORT_TEMPLATE_WEBASSEMBLY_RELEASE); } + if (!DirAccess::exists(p_path.get_base_dir())) { + return ERR_FILE_BAD_PATH; + } + if (template_path != String() && !FileAccess::exists(template_path)) { EditorNode::get_singleton()->show_warning(TTR("Template file not found:") + "\n" + template_path); return ERR_FILE_NOT_FOUND; @@ -349,7 +367,7 @@ Error EditorExportPlatformJavaScript::run(const Ref<EditorExportPreset> &p_prese if (err) { return err; } - OS::get_singleton()->shell_open(path); + OS::get_singleton()->shell_open(String("file://") + path); return OK; } diff --git a/platform/javascript/http_request.js b/platform/javascript/http_request.js index 7acd32d8bf..66dacfc3d4 100644 --- a/platform/javascript/http_request.js +++ b/platform/javascript/http_request.js @@ -82,7 +82,7 @@ var GodotHTTPRequest = { godot_xhr_send_string: function(xhrId, strPtr) { if (!strPtr) { - console.warn("Failed to send string per XHR: null pointer"); + err("Failed to send string per XHR: null pointer"); return; } GodotHTTPRequest.requests[xhrId].send(UTF8ToString(strPtr)); @@ -90,11 +90,11 @@ var GodotHTTPRequest = { godot_xhr_send_data: function(xhrId, ptr, len) { if (!ptr) { - console.warn("Failed to send data per XHR: null pointer"); + err("Failed to send data per XHR: null pointer"); return; } if (len < 0) { - console.warn("Failed to send data per XHR: buffer length less than 0"); + err("Failed to send data per XHR: buffer length less than 0"); return; } GodotHTTPRequest.requests[xhrId].send(HEAPU8.subarray(ptr, ptr + len)); diff --git a/platform/javascript/javascript_eval.cpp b/platform/javascript/javascript_eval.cpp index bb43e2d46b..dd3eba74e4 100644 --- a/platform/javascript/javascript_eval.cpp +++ b/platform/javascript/javascript_eval.cpp @@ -69,7 +69,7 @@ Variant JavaScript::eval(const String &p_code, bool p_use_global_exec_context) { eval_ret = eval(UTF8ToString(CODE)); } } catch (e) { - console.warn(e); + err(e); eval_ret = null; } @@ -97,7 +97,7 @@ Variant JavaScript::eval(const String &p_code, bool p_use_global_exec_context) { if (array_ptr!==0) { _free(array_ptr) } - console.warn(e); + err(e); // fall through } break; diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp index e820d07a2a..34781ce365 100644 --- a/platform/javascript/os_javascript.cpp +++ b/platform/javascript/os_javascript.cpp @@ -829,7 +829,7 @@ Error OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, RasterizerGLES3::make_current(); break; } else { - if (GLOBAL_GET("rendering/quality/driver/driver_fallback") == "Best") { + if (GLOBAL_GET("rendering/quality/driver/fallback_to_gles2")) { p_video_driver = VIDEO_DRIVER_GLES2; gles3 = false; continue; @@ -986,8 +986,8 @@ bool OS_JavaScript::main_loop_iterate() { if (sync_wait_time < 0) { /* clang-format off */ EM_ASM( - FS.syncfs(function(err) { - if (err) { console.warn('Failed to save IDB file system: ' + err.message); } + FS.syncfs(function(error) { + if (error) { err('Failed to save IDB file system: ' + error.message); } }); ); /* clang-format on */ @@ -1071,16 +1071,6 @@ bool OS_JavaScript::_check_internal_feature_support(const String &p_feature) { return true; #endif - EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx = emscripten_webgl_get_current_context(); - // All extensions are already automatically enabled, this function allows - // checking WebGL extension support without inline JavaScript - if (p_feature == "s3tc") - return emscripten_webgl_enable_extension(ctx, "WEBGL_compressed_texture_s3tc_srgb"); - if (p_feature == "etc") - return emscripten_webgl_enable_extension(ctx, "WEBGL_compressed_texture_etc1"); - if (p_feature == "etc2") - return emscripten_webgl_enable_extension(ctx, "WEBGL_compressed_texture_etc"); - return false; } diff --git a/platform/osx/SCsub b/platform/osx/SCsub index dc407eee9e..d2952ebdc0 100644 --- a/platform/osx/SCsub +++ b/platform/osx/SCsub @@ -10,7 +10,7 @@ files = [ 'crash_handler_osx.mm', 'os_osx.mm', 'godot_main_osx.mm', - 'sem_osx.cpp', + 'semaphore_osx.cpp', 'dir_access_osx.mm', 'joypad_osx.cpp', 'power_osx.cpp', diff --git a/platform/osx/crash_handler_osx.h b/platform/osx/crash_handler_osx.h index dead90ca90..6a72ce8ae9 100644 --- a/platform/osx/crash_handler_osx.h +++ b/platform/osx/crash_handler_osx.h @@ -45,4 +45,4 @@ public: ~CrashHandler(); }; -#endif +#endif // CRASH_HANDLER_OSX_H diff --git a/platform/osx/crash_handler_osx.mm b/platform/osx/crash_handler_osx.mm index 6684898085..ed8a955ae5 100644 --- a/platform/osx/crash_handler_osx.mm +++ b/platform/osx/crash_handler_osx.mm @@ -28,9 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#include "crash_handler_osx.h" + +#include "core/os/os.h" #include "core/project_settings.h" #include "main/main.h" -#include "os_osx.h" #include <string.h> #include <unistd.h> diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp index b8f6977b39..5e94bc457b 100644 --- a/platform/osx/export/export.cpp +++ b/platform/osx/export/export.cpp @@ -425,6 +425,10 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p } } + if (!DirAccess::exists(p_path.get_base_dir())) { + return ERR_FILE_BAD_PATH; + } + FileAccess *src_f = NULL; zlib_filefunc_def io = zipio_create_io_from_file(&src_f); diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h index 927c8c9b00..dfe7b27bd0 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -34,7 +34,7 @@ #include "core/os/input.h" #include "crash_handler_osx.h" #include "drivers/coreaudio/audio_driver_coreaudio.h" -#include "drivers/coremidi/core_midi.h" +#include "drivers/coremidi/midi_driver_coremidi.h" #include "drivers/unix/os_unix.h" #include "joypad_osx.h" #include "main/input_default.h" @@ -43,6 +43,7 @@ #include "servers/visual/rasterizer.h" #include "servers/visual/visual_server_wrap_mt.h" #include "servers/visual_server.h" + #include <AppKit/AppKit.h> #include <AppKit/NSCursor.h> #include <ApplicationServices/ApplicationServices.h> @@ -132,7 +133,7 @@ public: String im_text; Point2 im_selection; - power_osx *power_manager; + PowerOSX *power_manager; CrashHandler crash_handler; diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index 3f80d19fa1..b45d0d80e6 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -37,7 +37,7 @@ #include "drivers/gles2/rasterizer_gles2.h" #include "drivers/gles3/rasterizer_gles3.h" #include "main/main.h" -#include "sem_osx.h" +#include "semaphore_osx.h" #include "servers/visual/visual_server_raster.h" #include <mach-o/dyld.h> @@ -102,8 +102,6 @@ static void push_to_key_event_buffer(const OS_OSX::KeyEvent &p_event) { static int mouse_x = 0; static int mouse_y = 0; -static int prev_mouse_x = 0; -static int prev_mouse_y = 0; static int button_mask = 0; static bool mouse_down_control = false; @@ -282,7 +280,9 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt NSWindow *window = (NSWindow *)[notification object]; CGFloat newBackingScaleFactor = [window backingScaleFactor]; CGFloat oldBackingScaleFactor = [[[notification userInfo] objectForKey:@"NSBackingPropertyOldScaleFactorKey"] doubleValue]; - [OS_OSX::singleton->window_view setWantsBestResolutionOpenGLSurface:YES]; + if (OS_OSX::singleton->is_hidpi_allowed()) { + [OS_OSX::singleton->window_view setWantsBestResolutionOpenGLSurface:YES]; + } if (newBackingScaleFactor != oldBackingScaleFactor) { //Set new display scale and window size @@ -599,12 +599,13 @@ static void _mouseDownEvent(NSEvent *event, int index, int mask, bool pressed) { Ref<InputEventMouseButton> mb; mb.instance(); - + const CGFloat backingScaleFactor = [[event window] backingScaleFactor]; + const Vector2 pos = get_mouse_pos([event locationInWindow], backingScaleFactor); get_key_modifier_state([event modifierFlags], mb); mb->set_button_index(index); mb->set_pressed(pressed); - mb->set_position(Vector2(mouse_x, mouse_y)); - mb->set_global_position(Vector2(mouse_x, mouse_y)); + mb->set_position(pos); + mb->set_global_position(pos); mb->set_button_mask(button_mask); if (index == BUTTON_LEFT && pressed) { mb->set_doubleclick([event clickCount] == 2); @@ -640,8 +641,6 @@ static void _mouseDownEvent(NSEvent *event, int index, int mask, bool pressed) { mm.instance(); mm->set_button_mask(button_mask); - prev_mouse_x = mouse_x; - prev_mouse_y = mouse_y; const CGFloat backingScaleFactor = [[event window] backingScaleFactor]; const Vector2 pos = get_mouse_pos([event locationInWindow], backingScaleFactor); mm->set_position(pos); @@ -763,9 +762,41 @@ static void _mouseDownEvent(NSEvent *event, int index, int mask, bool pressed) { [super updateTrackingAreas]; } +static bool isNumpadKey(unsigned int key) { + + static const unsigned int table[] = { + 0x41, /* kVK_ANSI_KeypadDecimal */ + 0x43, /* kVK_ANSI_KeypadMultiply */ + 0x45, /* kVK_ANSI_KeypadPlus */ + 0x47, /* kVK_ANSI_KeypadClear */ + 0x4b, /* kVK_ANSI_KeypadDivide */ + 0x4c, /* kVK_ANSI_KeypadEnter */ + 0x4e, /* kVK_ANSI_KeypadMinus */ + 0x51, /* kVK_ANSI_KeypadEquals */ + 0x52, /* kVK_ANSI_Keypad0 */ + 0x53, /* kVK_ANSI_Keypad1 */ + 0x54, /* kVK_ANSI_Keypad2 */ + 0x55, /* kVK_ANSI_Keypad3 */ + 0x56, /* kVK_ANSI_Keypad4 */ + 0x57, /* kVK_ANSI_Keypad5 */ + 0x58, /* kVK_ANSI_Keypad6 */ + 0x59, /* kVK_ANSI_Keypad7 */ + 0x5b, /* kVK_ANSI_Keypad8 */ + 0x5c, /* kVK_ANSI_Keypad9 */ + 0x5f, /* kVK_JIS_KeypadComma */ + 0x00 + }; + for (int i = 0; table[i] != 0; i++) { + if (key == table[i]) + return true; + } + return false; +} + // Translates a OS X keycode to a Godot keycode // static int translateKey(unsigned int key) { + // Keyboard symbol translation table static const unsigned int table[128] = { /* 00 */ KEY_A, @@ -778,7 +809,7 @@ static int translateKey(unsigned int key) { /* 07 */ KEY_X, /* 08 */ KEY_C, /* 09 */ KEY_V, - /* 0a */ KEY_UNKNOWN, + /* 0a */ KEY_SECTION, /* ISO Section */ /* 0b */ KEY_B, /* 0c */ KEY_Q, /* 0d */ KEY_W, @@ -832,7 +863,7 @@ static int translateKey(unsigned int key) { /* 3d */ KEY_ALT, /* 3e */ KEY_CONTROL, /* 3f */ KEY_UNKNOWN, /* Function */ - /* 40 */ KEY_UNKNOWN, + /* 40 */ KEY_UNKNOWN, /* F17 */ /* 41 */ KEY_KP_PERIOD, /* 42 */ KEY_UNKNOWN, /* 43 */ KEY_KP_MULTIPLY, @@ -840,16 +871,16 @@ static int translateKey(unsigned int key) { /* 45 */ KEY_KP_ADD, /* 46 */ KEY_UNKNOWN, /* 47 */ KEY_NUMLOCK, /* Really KeypadClear... */ - /* 48 */ KEY_UNKNOWN, /* VolumeUp */ - /* 49 */ KEY_UNKNOWN, /* VolumeDown */ - /* 4a */ KEY_UNKNOWN, /* Mute */ + /* 48 */ KEY_VOLUMEUP, /* VolumeUp */ + /* 49 */ KEY_VOLUMEDOWN, /* VolumeDown */ + /* 4a */ KEY_VOLUMEMUTE, /* Mute */ /* 4b */ KEY_KP_DIVIDE, /* 4c */ KEY_KP_ENTER, /* 4d */ KEY_UNKNOWN, /* 4e */ KEY_KP_SUBTRACT, - /* 4f */ KEY_UNKNOWN, - /* 50 */ KEY_UNKNOWN, - /* 51 */ KEY_EQUAL, //wtf equal? + /* 4f */ KEY_UNKNOWN, /* F18 */ + /* 50 */ KEY_UNKNOWN, /* F19 */ + /* 51 */ KEY_EQUAL, /* KeypadEqual */ /* 52 */ KEY_KP_0, /* 53 */ KEY_KP_1, /* 54 */ KEY_KP_2, @@ -858,27 +889,27 @@ static int translateKey(unsigned int key) { /* 57 */ KEY_KP_5, /* 58 */ KEY_KP_6, /* 59 */ KEY_KP_7, - /* 5a */ KEY_UNKNOWN, + /* 5a */ KEY_UNKNOWN, /* F20 */ /* 5b */ KEY_KP_8, /* 5c */ KEY_KP_9, - /* 5d */ KEY_UNKNOWN, - /* 5e */ KEY_UNKNOWN, - /* 5f */ KEY_UNKNOWN, + /* 5d */ KEY_YEN, /* JIS Yen */ + /* 5e */ KEY_UNDERSCORE, /* JIS Underscore */ + /* 5f */ KEY_COMMA, /* JIS KeypadComma */ /* 60 */ KEY_F5, /* 61 */ KEY_F6, /* 62 */ KEY_F7, /* 63 */ KEY_F3, /* 64 */ KEY_F8, /* 65 */ KEY_F9, - /* 66 */ KEY_UNKNOWN, + /* 66 */ KEY_UNKNOWN, /* JIS Eisu */ /* 67 */ KEY_F11, - /* 68 */ KEY_UNKNOWN, + /* 68 */ KEY_UNKNOWN, /* JIS Kana */ /* 69 */ KEY_F13, /* 6a */ KEY_F16, /* 6b */ KEY_F14, /* 6c */ KEY_UNKNOWN, /* 6d */ KEY_F10, - /* 6e */ KEY_UNKNOWN, + /* 6e */ KEY_MENU, /* 6f */ KEY_F12, /* 70 */ KEY_UNKNOWN, /* 71 */ KEY_F15, @@ -969,6 +1000,9 @@ static const _KeyCodeMap _keycodes[55] = { static int remapKey(unsigned int key) { + if (isNumpadKey(key)) + return translateKey(key); + TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource(); if (!currentKeyboard) return translateKey(key); @@ -1094,6 +1128,7 @@ static int remapKey(unsigned int key) { inline void sendScrollEvent(int button, double factor, int modifierFlags) { unsigned int mask = 1 << (button - 1); + Vector2 mouse_pos = Vector2(mouse_x, mouse_y); Ref<InputEventMouseButton> sc; sc.instance(); @@ -1102,14 +1137,18 @@ inline void sendScrollEvent(int button, double factor, int modifierFlags) { sc->set_button_index(button); sc->set_factor(factor); sc->set_pressed(true); - Vector2 mouse_pos = Vector2(mouse_x, mouse_y); sc->set_position(mouse_pos); sc->set_global_position(mouse_pos); button_mask |= mask; sc->set_button_mask(button_mask); OS_OSX::singleton->push_input(sc); + sc.instance(); + sc->set_button_index(button); + sc->set_factor(factor); sc->set_pressed(false); + sc->set_position(mouse_pos); + sc->set_global_position(mouse_pos); button_mask &= ~mask; sc->set_button_mask(button_mask); OS_OSX::singleton->push_input(sc); @@ -1418,7 +1457,7 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a RasterizerGLES3::make_current(); break; } else { - if (GLOBAL_GET("rendering/quality/driver/driver_fallback") == "Best" || editor) { + if (GLOBAL_GET("rendering/quality/driver/fallback_to_gles2") || editor) { p_video_driver = VIDEO_DRIVER_GLES2; gles3 = false; continue; @@ -1459,7 +1498,7 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a input = memnew(InputDefault); joypad_osx = memnew(JoypadOSX); - power_manager = memnew(power_osx); + power_manager = memnew(PowerOSX); _ensure_user_data_dir(); @@ -2322,7 +2361,8 @@ bool OS_OSX::is_window_maximized() const { void OS_OSX::move_window_to_foreground() { - [window_object orderFrontRegardless]; + [[NSApplication sharedApplication] activateIgnoringOtherApps:YES]; + [window_object makeKeyAndOrderFront:nil]; } void OS_OSX::set_window_always_on_top(bool p_enabled) { @@ -2526,6 +2566,8 @@ void OS_OSX::process_events() { [autoreleasePool drain]; autoreleasePool = [[NSAutoreleasePool alloc] init]; + + input->flush_accumulated_events(); } void OS_OSX::process_key_events() { @@ -2568,7 +2610,7 @@ void OS_OSX::process_key_events() { void OS_OSX::push_input(const Ref<InputEvent> &p_event) { Ref<InputEvent> ev = p_event; - input->parse_input_event(ev); + input->accumulate_input_event(ev); } void OS_OSX::force_process_input() { @@ -2809,7 +2851,7 @@ OS_OSX::OS_OSX() { } bool OS_OSX::_check_internal_feature_support(const String &p_feature) { - return p_feature == "pc" || p_feature == "s3tc"; + return p_feature == "pc"; } void OS_OSX::disable_crash_handler() { diff --git a/platform/osx/power_osx.cpp b/platform/osx/power_osx.cpp index a7cf9d831f..04d423d8c5 100644 --- a/platform/osx/power_osx.cpp +++ b/platform/osx/power_osx.cpp @@ -67,7 +67,7 @@ Adapted from corresponding SDL 2.0 code. CFDictionaryGetValueIfPresent(dict, CFSTR(k), (const void **)v) /* Note that AC power sources also include a laptop battery it is charging. */ -void power_osx::checkps(CFDictionaryRef dict, bool *have_ac, bool *have_battery, bool *charging) { +void PowerOSX::checkps(CFDictionaryRef dict, bool *have_ac, bool *have_battery, bool *charging) { CFStringRef strval; /* don't CFRelease() this. */ CFBooleanRef bval; CFNumberRef numval; @@ -169,7 +169,7 @@ void power_osx::checkps(CFDictionaryRef dict, bool *have_ac, bool *have_battery, #undef STRMATCH // CODE CHUNK IMPORTED FROM SDL 2.0 -bool power_osx::GetPowerInfo_MacOSX() { +bool PowerOSX::GetPowerInfo_MacOSX() { CFTypeRef blob = IOPSCopyPowerSourcesInfo(); nsecs_left = -1; @@ -211,14 +211,14 @@ bool power_osx::GetPowerInfo_MacOSX() { return true; /* always the definitive answer on Mac OS X. */ } -bool power_osx::UpdatePowerInfo() { +bool PowerOSX::UpdatePowerInfo() { if (GetPowerInfo_MacOSX()) { return true; } return false; } -OS::PowerState power_osx::get_power_state() { +OS::PowerState PowerOSX::get_power_state() { if (UpdatePowerInfo()) { return power_state; } else { @@ -226,7 +226,7 @@ OS::PowerState power_osx::get_power_state() { } } -int power_osx::get_power_seconds_left() { +int PowerOSX::get_power_seconds_left() { if (UpdatePowerInfo()) { return nsecs_left; } else { @@ -234,7 +234,7 @@ int power_osx::get_power_seconds_left() { } } -int power_osx::get_power_percent_left() { +int PowerOSX::get_power_percent_left() { if (UpdatePowerInfo()) { return percent_left; } else { @@ -242,11 +242,11 @@ int power_osx::get_power_percent_left() { } } -power_osx::power_osx() : +PowerOSX::PowerOSX() : nsecs_left(-1), percent_left(-1), power_state(OS::POWERSTATE_UNKNOWN) { } -power_osx::~power_osx() { +PowerOSX::~PowerOSX() { } diff --git a/platform/osx/power_osx.h b/platform/osx/power_osx.h index 0f18f9f691..40d0d40fd4 100644 --- a/platform/osx/power_osx.h +++ b/platform/osx/power_osx.h @@ -28,15 +28,16 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PLATFORM_OSX_POWER_OSX_H_ -#define PLATFORM_OSX_POWER_OSX_H_ +#ifndef POWER_OSX_H +#define POWER_OSX_H #include "core/os/file_access.h" #include "core/os/os.h" #include "dir_access_osx.h" + #include <CoreFoundation/CoreFoundation.h> -class power_osx { +class PowerOSX { private: int nsecs_left; @@ -47,12 +48,12 @@ private: bool UpdatePowerInfo(); public: - power_osx(); - virtual ~power_osx(); + PowerOSX(); + virtual ~PowerOSX(); OS::PowerState get_power_state(); int get_power_seconds_left(); int get_power_percent_left(); }; -#endif /* PLATFORM_OSX_POWER_OSX_H_ */ +#endif // POWER_OSX_H diff --git a/platform/osx/sem_osx.cpp b/platform/osx/semaphore_osx.cpp index 4c3bad4379..fe7d19bd9e 100644 --- a/platform/osx/sem_osx.cpp +++ b/platform/osx/semaphore_osx.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* sem_osx.cpp */ +/* semaphore_osx.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "sem_osx.h" +#include "semaphore_osx.h" #include <fcntl.h> #include <unistd.h> @@ -66,6 +66,7 @@ void cgsem_destroy(cgsem_t *cgsem) { } #include "core/os/memory.h" + #include <errno.h> Error SemaphoreOSX::wait() { diff --git a/platform/osx/sem_osx.h b/platform/osx/semaphore_osx.h index 563bdfdcb1..c8e7c45227 100644 --- a/platform/osx/sem_osx.h +++ b/platform/osx/semaphore_osx.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* sem_osx.h */ +/* semaphore_osx.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SEM_OSX_H -#define SEM_OSX_H +#ifndef SEMAPHORE_OSX_H +#define SEMAPHORE_OSX_H struct cgsem { int pipefd[2]; @@ -56,4 +56,4 @@ public: ~SemaphoreOSX(); }; -#endif +#endif // SEMAPHORE_OSX_H diff --git a/platform/server/SCsub b/platform/server/SCsub index 51fd05a87e..62d45efbc0 100644 --- a/platform/server/SCsub +++ b/platform/server/SCsub @@ -13,7 +13,7 @@ common_server = [\ if sys.platform == "darwin": common_server.append("#platform/osx/crash_handler_osx.mm") common_server.append("#platform/osx/power_osx.cpp") - common_server.append("#platform/osx/sem_osx.cpp") + common_server.append("#platform/osx/semaphore_osx.cpp") else: common_server.append("#platform/x11/crash_handler_x11.cpp") common_server.append("#platform/x11/power_x11.cpp") diff --git a/platform/server/detect.py b/platform/server/detect.py index 392a987ee9..90a4092412 100644 --- a/platform/server/detect.py +++ b/platform/server/detect.py @@ -1,7 +1,10 @@ import os import platform import sys +from methods import get_compiler_version, use_gcc +# This file is mostly based on platform/x11/detect.py. +# If editing this file, make sure to apply relevant changes here too. def is_active(): return True @@ -26,10 +29,16 @@ def can_build(): def get_opts(): - from SCons.Variables import BoolVariable + from SCons.Variables import BoolVariable, EnumVariable return [ BoolVariable('use_llvm', 'Use the LLVM compiler', False), BoolVariable('use_static_cpp', 'Link libgcc and libstdc++ statically for better portability', False), + BoolVariable('use_ubsan', 'Use LLVM/GCC compiler undefined behavior sanitizer (UBSAN)', False), + BoolVariable('use_asan', 'Use LLVM/GCC compiler address sanitizer (ASAN))', False), + BoolVariable('use_lsan', 'Use LLVM/GCC compiler leak sanitizer (LSAN))', False), + EnumVariable('debug_symbols', 'Add debugging symbols to release builds', 'yes', ('yes', 'no', 'full')), + BoolVariable('separate_debug_symbols', 'Create a separate file containing debugging symbols', False), + BoolVariable('execinfo', 'Use libexecinfo on systems where glibc is not available', False), ] @@ -43,13 +52,30 @@ def configure(env): ## Build type if (env["target"] == "release"): - env.Append(CCFLAGS=['-O2', '-fomit-frame-pointer']) + if (env["optimize"] == "speed"): #optimize for speed (default) + env.Prepend(CCFLAGS=['-O3']) + else: #optimize for size + env.Prepend(CCFLAGS=['-Os']) + + if (env["debug_symbols"] == "yes"): + env.Prepend(CCFLAGS=['-g1']) + if (env["debug_symbols"] == "full"): + env.Prepend(CCFLAGS=['-g2']) elif (env["target"] == "release_debug"): - env.Append(CCFLAGS=['-O2', '-DDEBUG_ENABLED']) + if (env["optimize"] == "speed"): #optimize for speed (default) + env.Prepend(CCFLAGS=['-O2', '-DDEBUG_ENABLED']) + else: #optimize for size + env.Prepend(CCFLAGS=['-Os', '-DDEBUG_ENABLED']) + + if (env["debug_symbols"] == "yes"): + env.Prepend(CCFLAGS=['-g1']) + if (env["debug_symbols"] == "full"): + env.Prepend(CCFLAGS=['-g2']) elif (env["target"] == "debug"): - env.Append(CCFLAGS=['-g2', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED']) + env.Prepend(CCFLAGS=['-g3', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED']) + env.Append(LINKFLAGS=['-rdynamic']) ## Architecture @@ -59,6 +85,10 @@ def configure(env): ## Compiler configuration + if 'CXX' in env and 'clang' in os.path.basename(env['CXX']): + # Convenience check to enforce the use_llvm overrides when CXX is clang(++) + env['use_llvm'] = True + if env['use_llvm']: if ('clang++' not in os.path.basename(env['CXX'])): env["CC"] = "clang" @@ -67,6 +97,35 @@ def configure(env): env.Append(CPPFLAGS=['-DTYPED_METHOD_BIND']) env.extra_suffix = ".llvm" + env.extra_suffix + + if env['use_ubsan'] or env['use_asan'] or env['use_lsan']: + env.extra_suffix += "s" + + if env['use_ubsan']: + env.Append(CCFLAGS=['-fsanitize=undefined']) + env.Append(LINKFLAGS=['-fsanitize=undefined']) + + if env['use_asan']: + env.Append(CCFLAGS=['-fsanitize=address']) + env.Append(LINKFLAGS=['-fsanitize=address']) + + if env['use_lsan']: + env.Append(CCFLAGS=['-fsanitize=leak']) + env.Append(LINKFLAGS=['-fsanitize=leak']) + + if env['use_lto']: + env.Append(CCFLAGS=['-flto']) + if not env['use_llvm'] and env.GetOption("num_jobs") > 1: + env.Append(LINKFLAGS=['-flto=' + str(env.GetOption("num_jobs"))]) + else: + env.Append(LINKFLAGS=['-flto']) + if not env['use_llvm']: + env['RANLIB'] = 'gcc-ranlib' + env['AR'] = 'gcc-ar' + + env.Append(CCFLAGS=['-pipe']) + env.Append(LINKFLAGS=['-pipe']) + ## Dependencies # FIXME: Check for existence of the libs before parsing their flags with pkg-config @@ -110,6 +169,10 @@ def configure(env): env['builtin_libogg'] = False # Needed to link against system libtheora env['builtin_libvorbis'] = False # Needed to link against system libtheora env.ParseConfig('pkg-config theora theoradec --cflags --libs') + else: + list_of_x86 = ['x86_64', 'x86', 'i386', 'i586'] + if any(platform.machine() in s for s in list_of_x86): + env["x86_libtheora_opt_gcc"] = True if not env['builtin_libvpx']: env.ParseConfig('pkg-config vpx --cflags --libs') @@ -163,6 +226,9 @@ def configure(env): env.Append(LIBS=['dl']) if (platform.system().find("BSD") >= 0): + env["execinfo"] = True + + if env["execinfo"]: env.Append(LIBS=['execinfo']) # Link those statically for portability diff --git a/platform/server/os_server.cpp b/platform/server/os_server.cpp index 9b6e7864e1..e643d3e8bb 100644 --- a/platform/server/os_server.cpp +++ b/platform/server/os_server.cpp @@ -93,7 +93,7 @@ Error OS_Server::initialize(const VideoMode &p_desired, int p_video_driver, int input = memnew(InputDefault); #ifdef __APPLE__ - power_manager = memnew(power_osx); + power_manager = memnew(PowerOSX); #else power_manager = memnew(PowerX11); #endif diff --git a/platform/server/os_server.h b/platform/server/os_server.h index 7273a690ca..eebe8ae777 100644 --- a/platform/server/os_server.h +++ b/platform/server/os_server.h @@ -32,13 +32,12 @@ #define OS_SERVER_H #include "drivers/dummy/texture_loader_dummy.h" -#include "drivers/rtaudio/audio_driver_rtaudio.h" #include "drivers/unix/os_unix.h" #include "main/input_default.h" #ifdef __APPLE__ #include "platform/osx/crash_handler_osx.h" #include "platform/osx/power_osx.h" -#include "platform/osx/sem_osx.h" +#include "platform/osx/semaphore_osx.h" #else #include "platform/x11/crash_handler_x11.h" #include "platform/x11/power_x11.h" @@ -69,7 +68,7 @@ class OS_Server : public OS_Unix { InputDefault *input; #ifdef __APPLE__ - power_osx *power_manager; + PowerOSX *power_manager; #else PowerX11 *power_manager; #endif diff --git a/platform/uwp/SCsub b/platform/uwp/SCsub index fb0c4a92ae..c14290f0c4 100644 --- a/platform/uwp/SCsub +++ b/platform/uwp/SCsub @@ -4,11 +4,11 @@ Import('env') files = [ 'thread_uwp.cpp', - '#platform/windows/key_mapping_win.cpp', + '#platform/windows/key_mapping_windows.cpp', '#platform/windows/windows_terminal_logger.cpp', 'joypad_uwp.cpp', 'power_uwp.cpp', - 'gl_context_egl.cpp', + 'context_egl_uwp.cpp', 'app.cpp', 'os_uwp.cpp', ] diff --git a/platform/uwp/app.cpp b/platform/uwp/app.cpp index 1b8f9f3f9e..4f2ee0237a 100644 --- a/platform/uwp/app.cpp +++ b/platform/uwp/app.cpp @@ -39,7 +39,7 @@ #include "core/os/keyboard.h" #include "main/main.h" -#include "platform/windows/key_mapping_win.h" +#include "platform/windows/key_mapping_windows.h" #include <collection.h> @@ -99,7 +99,7 @@ void App::Initialize(CoreApplicationView ^ applicationView) { // Information about the Suspending and Resuming event handlers can be found here: // http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh994930.aspx - os = new OSUWP; + os = new OS_UWP; } // Called when the CoreWindow object is created (or re-created). @@ -398,7 +398,7 @@ void App::OnMouseMoved(MouseDevice ^ mouse_device, MouseEventArgs ^ args) { void App::key_event(Windows::UI::Core::CoreWindow ^ sender, bool p_pressed, Windows::UI::Core::KeyEventArgs ^ key_args, Windows::UI::Core::CharacterReceivedEventArgs ^ char_args) { - OSUWP::KeyEvent ke; + OS_UWP::KeyEvent ke; ke.control = sender->GetAsyncKeyState(VirtualKey::Control) == CoreVirtualKeyStates::Down; ke.alt = sender->GetAsyncKeyState(VirtualKey::Menu) == CoreVirtualKeyStates::Down; @@ -408,14 +408,14 @@ void App::key_event(Windows::UI::Core::CoreWindow ^ sender, bool p_pressed, Wind if (key_args != nullptr) { - ke.type = OSUWP::KeyEvent::MessageType::KEY_EVENT_MESSAGE; + ke.type = OS_UWP::KeyEvent::MessageType::KEY_EVENT_MESSAGE; ke.unicode = 0; ke.scancode = KeyMappingWindows::get_keysym((unsigned int)key_args->VirtualKey); ke.echo = (!p_pressed && !key_args->KeyStatus.IsKeyReleased) || (p_pressed && key_args->KeyStatus.WasKeyDown); } else { - ke.type = OSUWP::KeyEvent::MessageType::CHAR_EVENT_MESSAGE; + ke.type = OS_UWP::KeyEvent::MessageType::CHAR_EVENT_MESSAGE; ke.unicode = char_args->KeyCode; ke.scancode = 0; ke.echo = (!p_pressed && !char_args->KeyStatus.IsKeyReleased) || (p_pressed && char_args->KeyStatus.WasKeyDown); diff --git a/platform/uwp/app.h b/platform/uwp/app.h index d403dace9d..0bd996d483 100644 --- a/platform/uwp/app.h +++ b/platform/uwp/app.h @@ -103,7 +103,7 @@ namespace GodotUWP EGLSurface mEglSurface; CoreWindow^ window; - OSUWP* os; + OS_UWP* os; int last_touch_x[32]; // 20 fingers, index 31 reserved for the mouse int last_touch_y[32]; diff --git a/platform/uwp/gl_context_egl.cpp b/platform/uwp/context_egl_uwp.cpp index db15be3e06..061c54687c 100644 --- a/platform/uwp/gl_context_egl.cpp +++ b/platform/uwp/context_egl_uwp.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* gl_context_egl.cpp */ +/* context_egl_uwp.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,33 +28,33 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "gl_context_egl.h" +#include "context_egl_uwp.h" #include "EGL/eglext.h" using Platform::Exception; -void ContextEGL::release_current() { +void ContextEGL_UWP::release_current() { eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, mEglContext); }; -void ContextEGL::make_current() { +void ContextEGL_UWP::make_current() { eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext); }; -int ContextEGL::get_window_width() { +int ContextEGL_UWP::get_window_width() { return width; }; -int ContextEGL::get_window_height() { +int ContextEGL_UWP::get_window_height() { return height; }; -void ContextEGL::reset() { +void ContextEGL_UWP::reset() { cleanup(); @@ -62,7 +62,7 @@ void ContextEGL::reset() { initialize(); }; -void ContextEGL::swap_buffers() { +void ContextEGL_UWP::swap_buffers() { if (eglSwapBuffers(mEglDisplay, mEglSurface) != EGL_TRUE) { cleanup(); @@ -74,7 +74,7 @@ void ContextEGL::swap_buffers() { } }; -Error ContextEGL::initialize() { +Error ContextEGL_UWP::initialize() { EGLint configAttribList[] = { EGL_RED_SIZE, 8, @@ -190,7 +190,7 @@ Error ContextEGL::initialize() { return OK; }; -void ContextEGL::cleanup() { +void ContextEGL_UWP::cleanup() { if (mEglDisplay != EGL_NO_DISPLAY && mEglSurface != EGL_NO_SURFACE) { eglDestroySurface(mEglDisplay, mEglSurface); @@ -208,14 +208,14 @@ void ContextEGL::cleanup() { } }; -ContextEGL::ContextEGL(CoreWindow ^ p_window, Driver p_driver) : +ContextEGL_UWP::ContextEGL_UWP(CoreWindow ^ p_window, Driver p_driver) : mEglDisplay(EGL_NO_DISPLAY), mEglContext(EGL_NO_CONTEXT), mEglSurface(EGL_NO_SURFACE), driver(p_driver), window(p_window) {} -ContextEGL::~ContextEGL() { +ContextEGL_UWP::~ContextEGL_UWP() { cleanup(); }; diff --git a/platform/uwp/gl_context_egl.h b/platform/uwp/context_egl_uwp.h index 60feed2e24..812bdfb688 100644 --- a/platform/uwp/gl_context_egl.h +++ b/platform/uwp/context_egl_uwp.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* gl_context_egl.h */ +/* context_egl_uwp.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,19 +28,20 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef CONTEXT_EGL_H -#define CONTEXT_EGL_H +#ifndef CONTEXT_EGL_UWP_H +#define CONTEXT_EGL_UWP_H #include <wrl.h> -#include "EGL/egl.h" +#include <EGL/egl.h> + #include "core/error_list.h" #include "core/os/os.h" #include "drivers/gl_context/context_gl.h" using namespace Windows::UI::Core; -class ContextEGL : public ContextGL { +class ContextEGL_UWP : public ContextGL { public: enum Driver { @@ -79,8 +80,8 @@ public: void cleanup(); - ContextEGL(CoreWindow ^ p_window, Driver p_driver); - virtual ~ContextEGL(); + ContextEGL_UWP(CoreWindow ^ p_window, Driver p_driver); + virtual ~ContextEGL_UWP(); }; -#endif +#endif // CONTEXT_EGL_UWP_H diff --git a/platform/uwp/detect.py b/platform/uwp/detect.py index f25b9ba9cd..c32a11b396 100644 --- a/platform/uwp/detect.py +++ b/platform/uwp/detect.py @@ -29,7 +29,6 @@ def get_opts(): return [ ('msvc_version', 'MSVC version to use (ignored if the VCINSTALLDIR environment variable is set)', None), - BoolVariable('use_mingw', 'Use the MinGW compiler even if MSVC is installed (only used on Windows)', False), ] diff --git a/platform/uwp/export/export.cpp b/platform/uwp/export/export.cpp index 6808016f13..8ccf122d9f 100644 --- a/platform/uwp/export/export.cpp +++ b/platform/uwp/export/export.cpp @@ -646,9 +646,9 @@ AppxPackager::~AppxPackager() {} //////////////////////////////////////////////////////////////////// -class EditorExportUWP : public EditorExportPlatform { +class EditorExportPlatformUWP : public EditorExportPlatform { - GDCLASS(EditorExportUWP, EditorExportPlatform); + GDCLASS(EditorExportPlatformUWP, EditorExportPlatform); Ref<ImageTexture> logo; @@ -1035,13 +1035,13 @@ public: r_features->push_back("s3tc"); r_features->push_back("etc"); switch ((int)p_preset->get("architecture/target")) { - case EditorExportUWP::ARM: { + case EditorExportPlatformUWP::ARM: { r_features->push_back("arm"); } break; - case EditorExportUWP::X86: { + case EditorExportPlatformUWP::X86: { r_features->push_back("32"); } break; - case EditorExportUWP::X64: { + case EditorExportPlatformUWP::X64: { r_features->push_back("64"); } break; } @@ -1123,13 +1123,13 @@ public: String platform_infix; switch (arch) { - case EditorExportUWP::ARM: { + case EditorExportPlatformUWP::ARM: { platform_infix = "arm"; } break; - case EditorExportUWP::X86: { + case EditorExportPlatformUWP::X86: { platform_infix = "x86"; } break; - case EditorExportUWP::X64: { + case EditorExportPlatformUWP::X64: { platform_infix = "x64"; } break; } @@ -1265,6 +1265,10 @@ public: } } + if (!DirAccess::exists(p_path.get_base_dir())) { + return ERR_FILE_BAD_PATH; + } + Error err = OK; FileAccess *fa_pack = FileAccess::open(p_path, FileAccess::WRITE, &err); @@ -1459,7 +1463,7 @@ public: virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) { } - EditorExportUWP() { + EditorExportPlatformUWP() { Ref<Image> img = memnew(Image(_uwp_logo)); logo.instance(); logo->create_from_image(img); @@ -1478,7 +1482,7 @@ void register_uwp_exporter() { EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "export/uwp/debug_algorithm", PROPERTY_HINT_ENUM, "MD5,SHA1,SHA256")); #endif // WINDOWS_ENABLED - Ref<EditorExportUWP> exporter; + Ref<EditorExportPlatformUWP> exporter; exporter.instance(); EditorExport::get_singleton()->add_export_platform(exporter); } diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp index ea0193b8ed..bc74da8a1b 100644 --- a/platform/uwp/os_uwp.cpp +++ b/platform/uwp/os_uwp.cpp @@ -67,22 +67,22 @@ using namespace Windows::Devices::Sensors; using namespace Windows::ApplicationModel::DataTransfer; using namespace concurrency; -int OSUWP::get_video_driver_count() const { +int OS_UWP::get_video_driver_count() const { return 2; } -Size2 OSUWP::get_window_size() const { +Size2 OS_UWP::get_window_size() const { Size2 size; size.width = video_mode.width; size.height = video_mode.height; return size; } -int OSUWP::get_current_video_driver() const { +int OS_UWP::get_current_video_driver() const { return video_driver_index; } -void OSUWP::set_window_size(const Size2 p_size) { +void OS_UWP::set_window_size(const Size2 p_size) { Windows::Foundation::Size new_size; new_size.Width = p_size.width; @@ -97,7 +97,7 @@ void OSUWP::set_window_size(const Size2 p_size) { } } -void OSUWP::set_window_fullscreen(bool p_enabled) { +void OS_UWP::set_window_fullscreen(bool p_enabled) { ApplicationView ^ view = ApplicationView::GetForCurrentView(); @@ -117,12 +117,12 @@ void OSUWP::set_window_fullscreen(bool p_enabled) { } } -bool OSUWP::is_window_fullscreen() const { +bool OS_UWP::is_window_fullscreen() const { return ApplicationView::GetForCurrentView()->IsFullScreenMode; } -void OSUWP::set_keep_screen_on(bool p_enabled) { +void OS_UWP::set_keep_screen_on(bool p_enabled) { if (is_keep_screen_on() == p_enabled) return; @@ -134,7 +134,7 @@ void OSUWP::set_keep_screen_on(bool p_enabled) { OS::set_keep_screen_on(p_enabled); } -void OSUWP::initialize_core() { +void OS_UWP::initialize_core() { last_button_state = 0; @@ -167,49 +167,49 @@ void OSUWP::initialize_core() { cursor_shape = CURSOR_ARROW; } -bool OSUWP::can_draw() const { +bool OS_UWP::can_draw() const { return !minimized; }; -void OSUWP::set_window(Windows::UI::Core::CoreWindow ^ p_window) { +void OS_UWP::set_window(Windows::UI::Core::CoreWindow ^ p_window) { window = p_window; } -void OSUWP::screen_size_changed() { +void OS_UWP::screen_size_changed() { gl_context->reset(); }; -Error OSUWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { +Error OS_UWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { main_loop = NULL; outside = true; - ContextEGL::Driver opengl_api_type = ContextEGL::GLES_2_0; + ContextEGL_UWP::Driver opengl_api_type = ContextEGL_UWP::GLES_2_0; if (p_video_driver == VIDEO_DRIVER_GLES2) { - opengl_api_type = ContextEGL::GLES_2_0; + opengl_api_type = ContextEGL_UWP::GLES_2_0; } bool gl_initialization_error = false; gl_context = NULL; while (!gl_context) { - gl_context = memnew(ContextEGL(window, opengl_api_type)); + gl_context = memnew(ContextEGL_UWP(window, opengl_api_type)); if (gl_context->initialize() != OK) { memdelete(gl_context); gl_context = NULL; - if (GLOBAL_GET("rendering/quality/driver/driver_fallback") == "Best") { + if (GLOBAL_GET("rendering/quality/driver/fallback_to_gles2")) { if (p_video_driver == VIDEO_DRIVER_GLES2) { gl_initialization_error = true; break; } p_video_driver = VIDEO_DRIVER_GLES2; - opengl_api_type = ContextEGL::GLES_2_0; + opengl_api_type = ContextEGL_UWP::GLES_2_0; } else { gl_initialization_error = true; break; @@ -218,15 +218,15 @@ Error OSUWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_au } while (true) { - if (opengl_api_type == ContextEGL::GLES_3_0) { + if (opengl_api_type == ContextEGL_UWP::GLES_3_0) { if (RasterizerGLES3::is_viable() == OK) { RasterizerGLES3::register_config(); RasterizerGLES3::make_current(); break; } else { - if (GLOBAL_GET("rendering/quality/driver/driver_fallback") == "Best") { + if (GLOBAL_GET("rendering/quality/driver/fallback_to_gles2")) { p_video_driver = VIDEO_DRIVER_GLES2; - opengl_api_type = ContextEGL::GLES_2_0; + opengl_api_type = ContextEGL_UWP::GLES_2_0; continue; } else { gl_initialization_error = true; @@ -235,7 +235,7 @@ Error OSUWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_au } } - if (opengl_api_type == ContextEGL::GLES_2_0) { + if (opengl_api_type == ContextEGL_UWP::GLES_2_0) { if (RasterizerGLES2::is_viable() == OK) { RasterizerGLES2::register_config(); RasterizerGLES2::make_current(); @@ -349,7 +349,7 @@ Error OSUWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_au return OK; } -void OSUWP::set_clipboard(const String &p_text) { +void OS_UWP::set_clipboard(const String &p_text) { DataPackage ^ clip = ref new DataPackage(); clip->RequestedOperation = DataPackageOperation::Copy; @@ -358,7 +358,7 @@ void OSUWP::set_clipboard(const String &p_text) { Clipboard::SetContent(clip); }; -String OSUWP::get_clipboard() const { +String OS_UWP::get_clipboard() const { if (managed_object->clipboard != nullptr) return managed_object->clipboard->Data(); @@ -366,25 +366,25 @@ String OSUWP::get_clipboard() const { return ""; }; -void OSUWP::input_event(const Ref<InputEvent> &p_event) { +void OS_UWP::input_event(const Ref<InputEvent> &p_event) { input->parse_input_event(p_event); }; -void OSUWP::delete_main_loop() { +void OS_UWP::delete_main_loop() { if (main_loop) memdelete(main_loop); main_loop = NULL; } -void OSUWP::set_main_loop(MainLoop *p_main_loop) { +void OS_UWP::set_main_loop(MainLoop *p_main_loop) { input->set_main_loop(p_main_loop); main_loop = p_main_loop; } -void OSUWP::finalize() { +void OS_UWP::finalize() { if (main_loop) memdelete(main_loop); @@ -403,19 +403,19 @@ void OSUWP::finalize() { joypad = nullptr; } -void OSUWP::finalize_core() { +void OS_UWP::finalize_core() { NetSocketPosix::cleanup(); } -void OSUWP::alert(const String &p_alert, const String &p_title) { +void OS_UWP::alert(const String &p_alert, const String &p_title) { Platform::String ^ alert = ref new Platform::String(p_alert.c_str()); Platform::String ^ title = ref new Platform::String(p_title.c_str()); MessageDialog ^ msg = ref new MessageDialog(alert, title); - UICommand ^ close = ref new UICommand("Close", ref new UICommandInvokedHandler(managed_object, &OSUWP::ManagedType::alert_close)); + UICommand ^ close = ref new UICommand("Close", ref new UICommandInvokedHandler(managed_object, &OS_UWP::ManagedType::alert_close)); msg->Commands->Append(close); msg->DefaultCommandIndex = 0; @@ -424,17 +424,17 @@ void OSUWP::alert(const String &p_alert, const String &p_title) { msg->ShowAsync(); } -void OSUWP::ManagedType::alert_close(IUICommand ^ command) { +void OS_UWP::ManagedType::alert_close(IUICommand ^ command) { alert_close_handle = false; } -void OSUWP::ManagedType::on_clipboard_changed(Platform::Object ^ sender, Platform::Object ^ ev) { +void OS_UWP::ManagedType::on_clipboard_changed(Platform::Object ^ sender, Platform::Object ^ ev) { update_clipboard(); } -void OSUWP::ManagedType::update_clipboard() { +void OS_UWP::ManagedType::update_clipboard() { DataPackageView ^ data = Clipboard::GetContent(); @@ -446,7 +446,7 @@ void OSUWP::ManagedType::update_clipboard() { } } -void OSUWP::ManagedType::on_accelerometer_reading_changed(Accelerometer ^ sender, AccelerometerReadingChangedEventArgs ^ args) { +void OS_UWP::ManagedType::on_accelerometer_reading_changed(Accelerometer ^ sender, AccelerometerReadingChangedEventArgs ^ args) { AccelerometerReading ^ reading = args->Reading; @@ -456,7 +456,7 @@ void OSUWP::ManagedType::on_accelerometer_reading_changed(Accelerometer ^ sender reading->AccelerationZ)); } -void OSUWP::ManagedType::on_magnetometer_reading_changed(Magnetometer ^ sender, MagnetometerReadingChangedEventArgs ^ args) { +void OS_UWP::ManagedType::on_magnetometer_reading_changed(Magnetometer ^ sender, MagnetometerReadingChangedEventArgs ^ args) { MagnetometerReading ^ reading = args->Reading; @@ -466,7 +466,7 @@ void OSUWP::ManagedType::on_magnetometer_reading_changed(Magnetometer ^ sender, reading->MagneticFieldZ)); } -void OSUWP::ManagedType::on_gyroscope_reading_changed(Gyrometer ^ sender, GyrometerReadingChangedEventArgs ^ args) { +void OS_UWP::ManagedType::on_gyroscope_reading_changed(Gyrometer ^ sender, GyrometerReadingChangedEventArgs ^ args) { GyrometerReading ^ reading = args->Reading; @@ -476,7 +476,7 @@ void OSUWP::ManagedType::on_gyroscope_reading_changed(Gyrometer ^ sender, Gyrome reading->AngularVelocityZ)); } -void OSUWP::set_mouse_mode(MouseMode p_mode) { +void OS_UWP::set_mouse_mode(MouseMode p_mode) { if (p_mode == MouseMode::MOUSE_MODE_CAPTURED) { @@ -501,41 +501,41 @@ void OSUWP::set_mouse_mode(MouseMode p_mode) { SetEvent(mouse_mode_changed); } -OSUWP::MouseMode OSUWP::get_mouse_mode() const { +OS_UWP::MouseMode OS_UWP::get_mouse_mode() const { return mouse_mode; } -Point2 OSUWP::get_mouse_position() const { +Point2 OS_UWP::get_mouse_position() const { return Point2(old_x, old_y); } -int OSUWP::get_mouse_button_state() const { +int OS_UWP::get_mouse_button_state() const { return last_button_state; } -void OSUWP::set_window_title(const String &p_title) { +void OS_UWP::set_window_title(const String &p_title) { } -void OSUWP::set_video_mode(const VideoMode &p_video_mode, int p_screen) { +void OS_UWP::set_video_mode(const VideoMode &p_video_mode, int p_screen) { video_mode = p_video_mode; } -OS::VideoMode OSUWP::get_video_mode(int p_screen) const { +OS::VideoMode OS_UWP::get_video_mode(int p_screen) const { return video_mode; } -void OSUWP::get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen) const { +void OS_UWP::get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen) const { } -String OSUWP::get_name() { +String OS_UWP::get_name() { return "UWP"; } -OS::Date OSUWP::get_date(bool utc) const { +OS::Date OS_UWP::get_date(bool utc) const { SYSTEMTIME systemtime; if (utc) @@ -551,7 +551,7 @@ OS::Date OSUWP::get_date(bool utc) const { date.dst = false; return date; } -OS::Time OSUWP::get_time(bool utc) const { +OS::Time OS_UWP::get_time(bool utc) const { SYSTEMTIME systemtime; if (utc) @@ -566,7 +566,7 @@ OS::Time OSUWP::get_time(bool utc) const { return time; } -OS::TimeZoneInfo OSUWP::get_time_zone_info() const { +OS::TimeZoneInfo OS_UWP::get_time_zone_info() const { TIME_ZONE_INFORMATION info; bool daylight = false; if (GetTimeZoneInformation(&info) == TIME_ZONE_ID_DAYLIGHT) @@ -579,11 +579,13 @@ OS::TimeZoneInfo OSUWP::get_time_zone_info() const { ret.name = info.StandardName; } - ret.bias = info.Bias; + // Bias value returned by GetTimeZoneInformation is inverted of what we expect + // For example on GMT-3 GetTimeZoneInformation return a Bias of 180, so invert the value to get -180 + ret.bias = -info.Bias; return ret; } -uint64_t OSUWP::get_unix_time() const { +uint64_t OS_UWP::get_unix_time() const { FILETIME ft; SYSTEMTIME st; @@ -605,14 +607,14 @@ uint64_t OSUWP::get_unix_time() const { return (*(uint64_t *)&ft - *(uint64_t *)&fep) / 10000000; }; -void OSUWP::delay_usec(uint32_t p_usec) const { +void OS_UWP::delay_usec(uint32_t p_usec) const { int msec = p_usec < 1000 ? 1 : p_usec / 1000; // no Sleep() WaitForSingleObjectEx(GetCurrentThread(), msec, false); } -uint64_t OSUWP::get_ticks_usec() const { +uint64_t OS_UWP::get_ticks_usec() const { uint64_t ticks; uint64_t time; @@ -626,13 +628,13 @@ uint64_t OSUWP::get_ticks_usec() const { return time; } -void OSUWP::process_events() { +void OS_UWP::process_events() { joypad->process_controllers(); process_key_events(); } -void OSUWP::process_key_events() { +void OS_UWP::process_key_events() { for (int i = 0; i < key_event_pos; i++) { @@ -653,7 +655,7 @@ void OSUWP::process_key_events() { key_event_pos = 0; } -void OSUWP::queue_key_event(KeyEvent &p_event) { +void OS_UWP::queue_key_event(KeyEvent &p_event) { // This merges Char events with the previous Key event, so // the unicode can be retrieved without sending duplicate events. if (p_event.type == KeyEvent::MessageType::CHAR_EVENT_MESSAGE && key_event_pos > 0) { @@ -670,7 +672,7 @@ void OSUWP::queue_key_event(KeyEvent &p_event) { key_event_buffer[key_event_pos++] = p_event; } -void OSUWP::set_cursor_shape(CursorShape p_shape) { +void OS_UWP::set_cursor_shape(CursorShape p_shape) { ERR_FAIL_INDEX(p_shape, CURSOR_MAX); @@ -702,57 +704,62 @@ void OSUWP::set_cursor_shape(CursorShape p_shape) { cursor_shape = p_shape; } -void OSUWP::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { +void OS_UWP::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { // TODO } -Error OSUWP::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr) { +Error OS_UWP::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr) { return FAILED; }; -Error OSUWP::kill(const ProcessID &p_pid) { +Error OS_UWP::kill(const ProcessID &p_pid) { return FAILED; }; -Error OSUWP::set_cwd(const String &p_cwd) { +Error OS_UWP::set_cwd(const String &p_cwd) { return FAILED; } -String OSUWP::get_executable_path() const { +String OS_UWP::get_executable_path() const { return ""; } -void OSUWP::set_icon(const Ref<Image> &p_icon) { +void OS_UWP::set_icon(const Ref<Image> &p_icon) { } -bool OSUWP::has_environment(const String &p_var) const { +bool OS_UWP::has_environment(const String &p_var) const { return false; }; -String OSUWP::get_environment(const String &p_var) const { +String OS_UWP::get_environment(const String &p_var) const { return ""; }; -String OSUWP::get_stdin_string(bool p_block) { +bool OS_UWP::set_environment(const String &p_var, const String &p_value) const { + + return false; +} + +String OS_UWP::get_stdin_string(bool p_block) { return String(); } -void OSUWP::move_window_to_foreground() { +void OS_UWP::move_window_to_foreground() { } -Error OSUWP::shell_open(String p_uri) { +Error OS_UWP::shell_open(String p_uri) { return FAILED; } -String OSUWP::get_locale() const { +String OS_UWP::get_locale() const { #if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP // this should work on phone 8.1, but it doesn't return "en"; @@ -762,39 +769,39 @@ String OSUWP::get_locale() const { #endif } -void OSUWP::release_rendering_thread() { +void OS_UWP::release_rendering_thread() { gl_context->release_current(); } -void OSUWP::make_rendering_thread() { +void OS_UWP::make_rendering_thread() { gl_context->make_current(); } -void OSUWP::swap_buffers() { +void OS_UWP::swap_buffers() { gl_context->swap_buffers(); } -bool OSUWP::has_touchscreen_ui_hint() const { +bool OS_UWP::has_touchscreen_ui_hint() const { TouchCapabilities ^ tc = ref new TouchCapabilities(); return tc->TouchPresent != 0 || UIViewSettings::GetForCurrentView()->UserInteractionMode == UserInteractionMode::Touch; } -bool OSUWP::has_virtual_keyboard() const { +bool OS_UWP::has_virtual_keyboard() const { return UIViewSettings::GetForCurrentView()->UserInteractionMode == UserInteractionMode::Touch; } -void OSUWP::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect) { +void OS_UWP::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect) { InputPane ^ pane = InputPane::GetForCurrentView(); pane->TryShow(); } -void OSUWP::hide_virtual_keyboard() { +void OS_UWP::hide_virtual_keyboard() { InputPane ^ pane = InputPane::GetForCurrentView(); pane->TryHide(); @@ -813,7 +820,7 @@ static String format_error_message(DWORD id) { return msg; } -Error OSUWP::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) { +Error OS_UWP::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) { String full_path = "game/" + p_path; p_library_handle = (void *)LoadPackagedLibrary(full_path.c_str(), 0); @@ -825,14 +832,14 @@ Error OSUWP::open_dynamic_library(const String p_path, void *&p_library_handle, return OK; } -Error OSUWP::close_dynamic_library(void *p_library_handle) { +Error OS_UWP::close_dynamic_library(void *p_library_handle) { if (!FreeLibrary((HMODULE)p_library_handle)) { return FAILED; } return OK; } -Error OSUWP::get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional) { +Error OS_UWP::get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional) { p_symbol_handle = (void *)GetProcAddress((HMODULE)p_library_handle, p_name.utf8().get_data()); if (!p_symbol_handle) { if (!p_optional) { @@ -845,7 +852,7 @@ Error OSUWP::get_dynamic_library_symbol_handle(void *p_library_handle, const Str return OK; } -void OSUWP::run() { +void OS_UWP::run() { if (!main_loop) return; @@ -869,35 +876,35 @@ void OSUWP::run() { main_loop->finish(); } -MainLoop *OSUWP::get_main_loop() const { +MainLoop *OS_UWP::get_main_loop() const { return main_loop; } -String OSUWP::get_user_data_dir() const { +String OS_UWP::get_user_data_dir() const { Windows::Storage::StorageFolder ^ data_folder = Windows::Storage::ApplicationData::Current->LocalFolder; return String(data_folder->Path->Data()).replace("\\", "/"); } -bool OSUWP::_check_internal_feature_support(const String &p_feature) { - return p_feature == "pc" || p_feature == "s3tc"; +bool OS_UWP::_check_internal_feature_support(const String &p_feature) { + return p_feature == "pc"; } -OS::PowerState OSUWP::get_power_state() { +OS::PowerState OS_UWP::get_power_state() { return power_manager->get_power_state(); } -int OSUWP::get_power_seconds_left() { +int OS_UWP::get_power_seconds_left() { return power_manager->get_power_seconds_left(); } -int OSUWP::get_power_percent_left() { +int OS_UWP::get_power_percent_left() { return power_manager->get_power_percent_left(); } -OSUWP::OSUWP() { +OS_UWP::OS_UWP() { key_event_pos = 0; force_quit = false; @@ -931,7 +938,7 @@ OSUWP::OSUWP() { _set_logger(memnew(CompositeLogger(loggers))); } -OSUWP::~OSUWP() { +OS_UWP::~OS_UWP() { #ifdef STDOUT_FILE fclose(stdo); #endif diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h index 491c9bce03..fd78b3cdf7 100644 --- a/platform/uwp/os_uwp.h +++ b/platform/uwp/os_uwp.h @@ -28,15 +28,15 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef OSUWP_H -#define OSUWP_H +#ifndef OS_UWP_H +#define OS_UWP_H +#include "context_egl_uwp.h" #include "core/math/transform_2d.h" #include "core/os/input.h" #include "core/os/os.h" #include "core/ustring.h" #include "drivers/xaudio2/audio_driver_xaudio2.h" -#include "gl_context_egl.h" #include "joypad_uwp.h" #include "main/input_default.h" #include "power_uwp.h" @@ -52,7 +52,7 @@ /** @author Juan Linietsky <reduzio@gmail.com> */ -class OSUWP : public OS { +class OS_UWP : public OS { public: struct KeyEvent { @@ -95,7 +95,7 @@ private: VisualServer *visual_server; int pressrc; - ContextEGL *gl_context; + ContextEGL_UWP *gl_context; Windows::UI::Core::CoreWindow ^ window; VideoMode video_mode; @@ -144,7 +144,7 @@ private: /* clang-format off */ internal: ManagedType() { alert_close_handle = false; } - property OSUWP* os; + property OS_UWP* os; /* clang-format on */ }; ManagedType ^ managed_object; @@ -213,6 +213,7 @@ public: virtual bool has_environment(const String &p_var) const; virtual String get_environment(const String &p_var) const; + virtual bool set_environment(const String &p_var, const String &p_value) const; virtual void set_clipboard(const String &p_text); virtual String get_clipboard() const; @@ -261,8 +262,8 @@ public: void queue_key_event(KeyEvent &p_event); - OSUWP(); - ~OSUWP(); + OS_UWP(); + ~OS_UWP(); }; #endif diff --git a/platform/uwp/power_uwp.h b/platform/uwp/power_uwp.h index d6623f9340..cc19904a62 100644 --- a/platform/uwp/power_uwp.h +++ b/platform/uwp/power_uwp.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PLATFORM_UWP_POWER_UWP_H_ -#define PLATFORM_UWP_POWER_UWP_H_ +#ifndef POWER_UWP_H +#define POWER_UWP_H #include "core/os/dir_access.h" #include "core/os/file_access.h" @@ -53,4 +53,4 @@ public: int get_power_percent_left(); }; -#endif /* PLATFORM_UWP_POWER_UWP_H_ */ +#endif // POWER_UWP_H diff --git a/platform/windows/SCsub b/platform/windows/SCsub index e07d373c4b..892d734734 100644 --- a/platform/windows/SCsub +++ b/platform/windows/SCsub @@ -7,13 +7,12 @@ from platform_methods import run_in_subprocess import platform_windows_builders common_win = [ - "godot_win.cpp", - "context_gl_win.cpp", - "crash_handler_win.cpp", + "godot_windows.cpp", + "context_gl_windows.cpp", + "crash_handler_windows.cpp", "os_windows.cpp", - "ctxgl_procaddr.cpp", - "key_mapping_win.cpp", - "joypad.cpp", + "key_mapping_windows.cpp", + "joypad_windows.cpp", "power_windows.cpp", "windows_terminal_logger.cpp" ] diff --git a/platform/windows/context_gl_win.cpp b/platform/windows/context_gl_windows.cpp index 9d267c699f..e715999378 100644 --- a/platform/windows/context_gl_win.cpp +++ b/platform/windows/context_gl_windows.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* context_gl_win.cpp */ +/* context_gl_windows.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -32,7 +32,7 @@ // Author: Juan Linietsky <reduzio@gmail.com>, (C) 2008 -#include "context_gl_win.h" +#include "context_gl_windows.h" #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 @@ -43,32 +43,32 @@ typedef HGLRC(APIENTRY *PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC, HGLRC, const int *); -void ContextGL_Win::release_current() { +void ContextGL_Windows::release_current() { wglMakeCurrent(hDC, NULL); } -void ContextGL_Win::make_current() { +void ContextGL_Windows::make_current() { wglMakeCurrent(hDC, hRC); } -int ContextGL_Win::get_window_width() { +int ContextGL_Windows::get_window_width() { return OS::get_singleton()->get_video_mode().width; } -int ContextGL_Win::get_window_height() { +int ContextGL_Windows::get_window_height() { return OS::get_singleton()->get_video_mode().height; } -void ContextGL_Win::swap_buffers() { +void ContextGL_Windows::swap_buffers() { SwapBuffers(hDC); } -void ContextGL_Win::set_use_vsync(bool p_use) { +void ContextGL_Windows::set_use_vsync(bool p_use) { if (wglSwapIntervalEXT) { wglSwapIntervalEXT(p_use ? 1 : 0); @@ -76,14 +76,14 @@ void ContextGL_Win::set_use_vsync(bool p_use) { use_vsync = p_use; } -bool ContextGL_Win::is_using_vsync() const { +bool ContextGL_Windows::is_using_vsync() const { return use_vsync; } #define _WGL_CONTEXT_DEBUG_BIT_ARB 0x0001 -Error ContextGL_Win::initialize() { +Error ContextGL_Windows::initialize() { static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor @@ -172,14 +172,14 @@ Error ContextGL_Win::initialize() { return OK; } -ContextGL_Win::ContextGL_Win(HWND hwnd, bool p_opengl_3_context) { +ContextGL_Windows::ContextGL_Windows(HWND hwnd, bool p_opengl_3_context) { opengl_3_context = p_opengl_3_context; hWnd = hwnd; use_vsync = false; } -ContextGL_Win::~ContextGL_Win() { +ContextGL_Windows::~ContextGL_Windows() { } #endif diff --git a/platform/windows/context_gl_win.h b/platform/windows/context_gl_windows.h index 3076bbb1e8..09801b9146 100644 --- a/platform/windows/context_gl_win.h +++ b/platform/windows/context_gl_windows.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* context_gl_win.h */ +/* context_gl_windows.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -43,7 +43,7 @@ typedef bool(APIENTRY *PFNWGLSWAPINTERVALEXTPROC)(int interval); -class ContextGL_Win : public ContextGL { +class ContextGL_Windows : public ContextGL { HDC hDC; HGLRC hRC; @@ -68,8 +68,8 @@ public: virtual void set_use_vsync(bool p_use); virtual bool is_using_vsync() const; - ContextGL_Win(HWND hwnd, bool p_opengl_3_context); - virtual ~ContextGL_Win(); + ContextGL_Windows(HWND hwnd, bool p_opengl_3_context); + virtual ~ContextGL_Windows(); }; #endif diff --git a/platform/windows/crash_handler_win.cpp b/platform/windows/crash_handler_windows.cpp index 1d93c6d8dd..4006c4c60e 100644 --- a/platform/windows/crash_handler_win.cpp +++ b/platform/windows/crash_handler_windows.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* crash_handler_win.cpp */ +/* crash_handler_windows.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,9 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#include "crash_handler_windows.h" + +#include "core/os/os.h" #include "core/project_settings.h" #include "main/main.h" -#include "os_windows.h" #ifdef CRASH_HANDLER_EXCEPTION @@ -39,6 +41,7 @@ #include <psapi.h> #include <algorithm> #include <iterator> +#include <vector> #pragma comment(lib, "psapi.lib") #pragma comment(lib, "dbghelp.lib") diff --git a/platform/windows/crash_handler_win.h b/platform/windows/crash_handler_windows.h index 016612a00e..eba72beb7e 100644 --- a/platform/windows/crash_handler_win.h +++ b/platform/windows/crash_handler_windows.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* crash_handler_win.h */ +/* crash_handler_windows.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef CRASH_HANDLER_WIN_H -#define CRASH_HANDLER_WIN_H +#ifndef CRASH_HANDLER_WINDOWS_H +#define CRASH_HANDLER_WINDOWS_H #include <windows.h> @@ -54,4 +54,4 @@ public: ~CrashHandler(); }; -#endif +#endif // CRASH_HANDLER_WINDOWS_H diff --git a/platform/windows/ctxgl_procaddr.cpp b/platform/windows/ctxgl_procaddr.cpp deleted file mode 100644 index ecff8f7a4d..0000000000 --- a/platform/windows/ctxgl_procaddr.cpp +++ /dev/null @@ -1,188 +0,0 @@ -/*************************************************************************/ -/* ctxgl_procaddr.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2019 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. */ -/*************************************************************************/ - -#ifdef OPENGL_ENABLED -#include "ctxgl_procaddr.h" -#include <GL/gl.h> -#include <stdio.h> - -static PROC _gl_procs[] = { - (PROC)glCullFace, - (PROC)glFrontFace, - (PROC)glHint, - (PROC)glLineWidth, - (PROC)glPointSize, - (PROC)glPolygonMode, - (PROC)glScissor, - (PROC)glTexParameterf, - (PROC)glTexParameterfv, - (PROC)glTexParameteri, - (PROC)glTexParameteriv, - (PROC)glTexImage1D, - (PROC)glTexImage2D, - (PROC)glDrawBuffer, - (PROC)glClear, - (PROC)glClearColor, - (PROC)glClearStencil, - (PROC)glClearDepth, - (PROC)glStencilMask, - (PROC)glColorMask, - (PROC)glDepthMask, - (PROC)glDisable, - (PROC)glEnable, - (PROC)glFinish, - (PROC)glFlush, - (PROC)glBlendFunc, - (PROC)glLogicOp, - (PROC)glStencilFunc, - (PROC)glStencilOp, - (PROC)glDepthFunc, - (PROC)glPixelStoref, - (PROC)glPixelStorei, - (PROC)glReadBuffer, - (PROC)glReadPixels, - (PROC)glGetBooleanv, - (PROC)glGetDoublev, - (PROC)glGetError, - (PROC)glGetFloatv, - (PROC)glGetIntegerv, - (PROC)glGetString, - (PROC)glGetTexImage, - (PROC)glGetTexParameterfv, - (PROC)glGetTexParameteriv, - (PROC)glGetTexLevelParameterfv, - (PROC)glGetTexLevelParameteriv, - (PROC)glIsEnabled, - (PROC)glDepthRange, - (PROC)glViewport, - /* not detected in ATI */ - (PROC)glDrawArrays, - (PROC)glDrawElements, - (PROC)glGetPointerv, - (PROC)glPolygonOffset, - (PROC)glCopyTexImage1D, - (PROC)glCopyTexImage2D, - (PROC)glCopyTexSubImage1D, - (PROC)glCopyTexSubImage2D, - (PROC)glTexSubImage1D, - (PROC)glTexSubImage2D, - (PROC)glBindTexture, - (PROC)glDeleteTextures, - (PROC)glGenTextures, - (PROC)glIsTexture, - - 0 -}; - -static const char *_gl_proc_names[] = { - "glCullFace", - "glFrontFace", - "glHint", - "glLineWidth", - "glPointSize", - "glPolygonMode", - "glScissor", - "glTexParameterf", - "glTexParameterfv", - "glTexParameteri", - "glTexParameteriv", - "glTexImage1D", - "glTexImage2D", - "glDrawBuffer", - "glClear", - "glClearColor", - "glClearStencil", - "glClearDepth", - "glStencilMask", - "glColorMask", - "glDepthMask", - "glDisable", - "glEnable", - "glFinish", - "glFlush", - "glBlendFunc", - "glLogicOp", - "glStencilFunc", - "glStencilOp", - "glDepthFunc", - "glPixelStoref", - "glPixelStorei", - "glReadBuffer", - "glReadPixels", - "glGetBooleanv", - "glGetDoublev", - "glGetError", - "glGetFloatv", - "glGetIntegerv", - "glGetString", - "glGetTexImage", - "glGetTexParameterfv", - "glGetTexParameteriv", - "glGetTexLevelParameterfv", - "glGetTexLevelParameteriv", - "glIsEnabled", - "glDepthRange", - "glViewport", - /* not detected in ati */ - "glDrawArrays", - "glDrawElements", - "glGetPointerv", - "glPolygonOffset", - "glCopyTexImage1D", - "glCopyTexImage2D", - "glCopyTexSubImage1D", - "glCopyTexSubImage2D", - "glTexSubImage1D", - "glTexSubImage2D", - "glBindTexture", - "glDeleteTextures", - "glGenTextures", - "glIsTexture", - - 0 -}; - -PROC get_gl_proc_address(const char *p_address) { - - PROC proc = wglGetProcAddress((const CHAR *)p_address); - if (!proc) { - - int i = 0; - while (_gl_procs[i]) { - - if (strcmp(p_address, _gl_proc_names[i]) == 0) { - return _gl_procs[i]; - } - i++; - } - } - return proc; -} -#endif diff --git a/platform/windows/detect.py b/platform/windows/detect.py index 0662bc2edc..426a5e9e61 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -205,8 +205,8 @@ def configure_msvc(env, manual_msvc_config): print("Missing environment variable: WindowsSdkDir") env.AppendUnique(CPPDEFINES = ['WINDOWS_ENABLED', 'OPENGL_ENABLED', - 'RTAUDIO_ENABLED', 'WASAPI_ENABLED', - 'WINMIDI_ENABLED', 'TYPED_METHOD_BIND', + 'WASAPI_ENABLED', 'WINMIDI_ENABLED', + 'TYPED_METHOD_BIND', 'WIN32', 'MSVC', 'WINVER=%s' % env["target_win_version"], '_WIN32_WINNT=%s' % env["target_win_version"]]) @@ -326,8 +326,8 @@ def configure_mingw(env): env.Append(CCFLAGS=['-DWINDOWS_ENABLED', '-mwindows']) env.Append(CCFLAGS=['-DOPENGL_ENABLED']) - env.Append(CCFLAGS=['-DRTAUDIO_ENABLED']) env.Append(CCFLAGS=['-DWASAPI_ENABLED']) + env.Append(CCFLAGS=['-DWINMIDI_ENABLED']) env.Append(CCFLAGS=['-DWINVER=%s' % env['target_win_version'], '-D_WIN32_WINNT=%s' % env['target_win_version']]) env.Append(LIBS=['mingw32', 'opengl32', 'dsound', 'ole32', 'd3d9', 'winmm', 'gdi32', 'iphlpapi', 'shlwapi', 'wsock32', 'ws2_32', 'kernel32', 'oleaut32', 'dinput8', 'dxguid', 'ksuser', 'imm32', 'bcrypt','avrt']) @@ -347,12 +347,12 @@ def configure(env): env['ENV']['TMP'] = os.environ['TMP'] # First figure out which compiler, version, and target arch we're using - if os.getenv("VCINSTALLDIR"): + if os.getenv("VCINSTALLDIR") and not env["use_mingw"]: # Manual setup of MSVC setup_msvc_manual(env) env.msvc = True manual_msvc_config = True - elif env.get('MSVC_VERSION', ''): + elif env.get('MSVC_VERSION', '') and not env["use_mingw"]: setup_msvc_auto(env) env.msvc = True manual_msvc_config = False diff --git a/platform/windows/export/export.cpp b/platform/windows/export/export.cpp index ca2f71ca18..141ab96370 100644 --- a/platform/windows/export/export.cpp +++ b/platform/windows/export/export.cpp @@ -73,7 +73,7 @@ Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset> } #endif - String icon_path = p_preset->get("application/icon"); + String icon_path = ProjectSettings::get_singleton()->globalize_path(p_preset->get("application/icon")); String file_verion = p_preset->get("application/file_version"); String product_version = p_preset->get("application/product_version"); String company_name = p_preset->get("application/company_name"); @@ -137,7 +137,7 @@ Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset> void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_options) { EditorExportPlatformPC::get_export_options(r_options); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_GLOBAL_FILE, "*.ico"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.ico"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_version"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_version"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/company_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Company Name"), "")); diff --git a/platform/windows/godot.natvis b/platform/windows/godot.natvis index 01963035a1..55c83c3f3c 100644 --- a/platform/windows/godot.natvis +++ b/platform/windows/godot.natvis @@ -2,92 +2,109 @@ <AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010"> <Type Name="Vector<*>"> <Expand> - <Item Name="size">(_cowdata && _cowdata->_ptr) ? (((const unsigned int *)(_cowdata->_ptr))[-1]) : 0</Item> + <Item Name="[size]">_cowdata._ptr ? (((const unsigned int *)(_cowdata._ptr))[-1]) : 0</Item> <ArrayItems> - <Size>(_cowdata && _cowdata->_ptr) ? (((const unsigned int *)(_cowdata->_ptr))[-1]) : 0</Size> - <ValuePointer>(_cowdata) ? (_cowdata->_ptr) : 0</ValuePointer> + <Size>_cowdata._ptr ? (((const unsigned int *)(_cowdata._ptr))[-1]) : 0</Size> + <ValuePointer>_cowdata._ptr</ValuePointer> </ArrayItems> </Expand> </Type> <Type Name="PoolVector<*>"> <Expand> - <Item Name="size">alloc ? (alloc->size / sizeof($T1)) : 0</Item> + <Item Name="[size]">alloc ? (alloc->size / sizeof($T1)) : 0</Item> <ArrayItems> <Size>alloc ? (alloc->size / sizeof($T1)) : 0</Size> <ValuePointer>alloc ? (($T1 *)alloc->mem) : 0</ValuePointer> </ArrayItems> </Expand> </Type> + + <Type Name="List<*>"> + <Expand> + <Item Name="[size]">_data ? (_data->size_cache) : 0</Item> + <LinkedListItems> + <Size>_data ? (_data->size_cache) : 0</Size> + <HeadPointer>_data->first</HeadPointer> + <NextPointer>next_ptr</NextPointer> + <ValueNode>value</ValueNode> + </LinkedListItems> + </Expand> + </Type> <Type Name="Variant"> - <DisplayString Condition="this->type == Variant::NIL">nil</DisplayString> - <DisplayString Condition="this->type == Variant::BOOL">{_data._bool}</DisplayString> - <DisplayString Condition="this->type == Variant::INT">{_data._int}</DisplayString> - <DisplayString Condition="this->type == Variant::REAL">{_data._real}</DisplayString> - <DisplayString Condition="this->type == Variant::TRANSFORM2D">{_data._transform2d}</DisplayString> - <DisplayString Condition="this->type == Variant::AABB">{_data._aabb}</DisplayString> - <DisplayString Condition="this->type == Variant::BASIS">{_data._basis}</DisplayString> - <DisplayString Condition="this->type == Variant::TRANSFORM">{_data._transform}</DisplayString> - <DisplayString Condition="this->type == Variant::ARRAY">{*(Array *)_data._mem}</DisplayString> - <DisplayString Condition="this->type == Variant::STRING && ((String *)(&_data._mem[0]))->_cowdata._ptr == 0">""</DisplayString> - <DisplayString Condition="this->type == Variant::STRING && ((String *)(&_data._mem[0]))->_cowdata._ptr != 0">{((String *)(&_data._mem[0]))->_cowdata._ptr,su}</DisplayString> - <DisplayString Condition="this->type == Variant::VECTOR2">{*(Vector2 *)_data._mem}</DisplayString> - <DisplayString Condition="this->type == Variant::RECT2">{*(Rect2 *)_data._mem}</DisplayString> - <DisplayString Condition="this->type == Variant::VECTOR3">{*(Vector3 *)_data._mem}</DisplayString> - <DisplayString Condition="this->type == Variant::PLANE">{*(Plane *)_data._mem}</DisplayString> - <DisplayString Condition="this->type == Variant::QUAT">{*(Quat *)_data._mem}</DisplayString> - <DisplayString Condition="this->type == Variant::COLOR">{*(Color *)_data._mem}</DisplayString> - <DisplayString Condition="this->type == Variant::NODE_PATH">{*(NodePath *)_data._mem}</DisplayString> - <DisplayString Condition="this->type == Variant::_RID">{*(RID *)_data._mem}</DisplayString> - <DisplayString Condition="this->type == Variant::OBJECT">{*(Object *)_data._mem}</DisplayString> - <DisplayString Condition="this->type == Variant::DICTIONARY">{*(Dictionary *)_data._mem}</DisplayString> - <DisplayString Condition="this->type == Variant::ARRAY">{*(Array *)_data._mem}</DisplayString> - <DisplayString Condition="this->type == Variant::POOL_BYTE_ARRAY">{*(PoolByteArray *)_data._mem}</DisplayString> - <DisplayString Condition="this->type == Variant::POOL_INT_ARRAY">{*(PoolIntArray *)_data._mem}</DisplayString> - <DisplayString Condition="this->type == Variant::POOL_REAL_ARRAY">{*(PoolRealArray *)_data._mem}</DisplayString> - <DisplayString Condition="this->type == Variant::POOL_STRING_ARRAY">{*(PoolStringArray *)_data._mem}</DisplayString> - <DisplayString Condition="this->type == Variant::POOL_VECTOR2_ARRAY">{*(PoolVector2Array *)_data._mem}</DisplayString> - <DisplayString Condition="this->type == Variant::POOL_VECTOR3_ARRAY">{*(PoolVector3Array *)_data._mem}</DisplayString> - <DisplayString Condition="this->type == Variant::POOL_COLOR_ARRAY">{*(PoolColorArray *)_data._mem}</DisplayString> - - <StringView Condition="this->type == Variant::STRING && ((String *)(&_data._mem[0]))->_cowdata._ptr != 0">((String *)(&_data._mem[0]))->_cowdata._ptr,su</StringView> + <DisplayString Condition="type == Variant::NIL">nil</DisplayString> + <DisplayString Condition="type == Variant::BOOL">{_data._bool}</DisplayString> + <DisplayString Condition="type == Variant::INT">{_data._int}</DisplayString> + <DisplayString Condition="type == Variant::REAL">{_data._real}</DisplayString> + <DisplayString Condition="type == Variant::TRANSFORM2D">{_data._transform2d}</DisplayString> + <DisplayString Condition="type == Variant::AABB">{_data._aabb}</DisplayString> + <DisplayString Condition="type == Variant::BASIS">{_data._basis}</DisplayString> + <DisplayString Condition="type == Variant::TRANSFORM">{_data._transform}</DisplayString> + <DisplayString Condition="type == Variant::STRING">{*(String *)_data._mem}</DisplayString> + <DisplayString Condition="type == Variant::VECTOR2">{*(Vector2 *)_data._mem}</DisplayString> + <DisplayString Condition="type == Variant::RECT2">{*(Rect2 *)_data._mem}</DisplayString> + <DisplayString Condition="type == Variant::VECTOR3">{*(Vector3 *)_data._mem}</DisplayString> + <DisplayString Condition="type == Variant::PLANE">{*(Plane *)_data._mem}</DisplayString> + <DisplayString Condition="type == Variant::QUAT">{*(Quat *)_data._mem}</DisplayString> + <DisplayString Condition="type == Variant::COLOR">{*(Color *)_data._mem}</DisplayString> + <DisplayString Condition="type == Variant::NODE_PATH">{*(NodePath *)_data._mem}</DisplayString> + <DisplayString Condition="type == Variant::_RID">{*(RID *)_data._mem}</DisplayString> + <DisplayString Condition="type == Variant::OBJECT">{*(Object *)_data._mem}</DisplayString> + <DisplayString Condition="type == Variant::DICTIONARY">{*(Dictionary *)_data._mem}</DisplayString> + <DisplayString Condition="type == Variant::ARRAY">{*(Array *)_data._mem}</DisplayString> + <DisplayString Condition="type == Variant::POOL_BYTE_ARRAY">{*(PoolByteArray *)_data._mem}</DisplayString> + <DisplayString Condition="type == Variant::POOL_INT_ARRAY">{*(PoolIntArray *)_data._mem}</DisplayString> + <DisplayString Condition="type == Variant::POOL_REAL_ARRAY">{*(PoolRealArray *)_data._mem}</DisplayString> + <DisplayString Condition="type == Variant::POOL_STRING_ARRAY">{*(PoolStringArray *)_data._mem}</DisplayString> + <DisplayString Condition="type == Variant::POOL_VECTOR2_ARRAY">{*(PoolVector2Array *)_data._mem}</DisplayString> + <DisplayString Condition="type == Variant::POOL_VECTOR3_ARRAY">{*(PoolVector3Array *)_data._mem}</DisplayString> + <DisplayString Condition="type == Variant::POOL_COLOR_ARRAY">{*(PoolColorArray *)_data._mem}</DisplayString> + <StringView Condition="type == Variant::STRING && ((String *)(_data._mem))->_cowdata._ptr">((String *)(_data._mem))->_cowdata._ptr,su</StringView> + <Expand> - <Item Name="value" Condition="this->type == Variant::BOOL">_data._bool</Item> - <Item Name="value" Condition="this->type == Variant::INT">_data._int</Item> - <Item Name="value" Condition="this->type == Variant::REAL">_data._real</Item> - <Item Name="value" Condition="this->type == Variant::TRANSFORM2D">_data._transform2d</Item> - <Item Name="value" Condition="this->type == Variant::AABB">_data._aabb</Item> - <Item Name="value" Condition="this->type == Variant::BASIS">_data._basis</Item> - <Item Name="value" Condition="this->type == Variant::TRANSFORM">_data._transform</Item> - <Item Name="value" Condition="this->type == Variant::ARRAY">*(Array *)_data._mem</Item> - <Item Name="value" Condition="this->type == Variant::STRING">*(String *)_data._mem</Item> - <Item Name="value" Condition="this->type == Variant::VECTOR2">*(Vector2 *)_data._mem</Item> - <Item Name="value" Condition="this->type == Variant::RECT2">*(Rect2 *)_data._mem</Item> - <Item Name="value" Condition="this->type == Variant::VECTOR3">*(Vector3 *)_data._mem</Item> - <Item Name="value" Condition="this->type == Variant::PLANE">*(Plane *)_data._mem</Item> - <Item Name="value" Condition="this->type == Variant::QUAT">*(Quat *)_data._mem</Item> - <Item Name="value" Condition="this->type == Variant::COLOR">*(Color *)_data._mem</Item> - <Item Name="value" Condition="this->type == Variant::NODE_PATH">*(NodePath *)_data._mem</Item> - <Item Name="value" Condition="this->type == Variant::_RID">*(RID *)_data._mem</Item> - <Item Name="value" Condition="this->type == Variant::OBJECT">*(Object *)_data._mem</Item> - <Item Name="value" Condition="this->type == Variant::DICTIONARY">*(Dictionary *)_data._mem</Item> - <Item Name="value" Condition="this->type == Variant::ARRAY">*(Array *)_data._mem</Item> - <Item Name="value" Condition="this->type == Variant::POOL_BYTE_ARRAY">*(PoolByteArray *)_data._mem</Item> - <Item Name="value" Condition="this->type == Variant::POOL_INT_ARRAY">*(PoolIntArray *)_data._mem</Item> - <Item Name="value" Condition="this->type == Variant::POOL_REAL_ARRAY">*(PoolRealArray *)_data._mem</Item> - <Item Name="value" Condition="this->type == Variant::POOL_STRING_ARRAY">*(PoolStringArray *)_data._mem</Item> - <Item Name="value" Condition="this->type == Variant::POOL_VECTOR2_ARRAY">*(PoolVector2Array *)_data._mem</Item> - <Item Name="value" Condition="this->type == Variant::POOL_VECTOR3_ARRAY">*(PoolVector3Array *)_data._mem</Item> - <Item Name="value" Condition="this->type == Variant::POOL_COLOR_ARRAY">*(PoolColorArray *)_data._mem</Item> + <Item Name="[value]" Condition="type == Variant::BOOL">_data._bool</Item> + <Item Name="[value]" Condition="type == Variant::INT">_data._int</Item> + <Item Name="[value]" Condition="type == Variant::REAL">_data._real</Item> + <Item Name="[value]" Condition="type == Variant::TRANSFORM2D">_data._transform2d</Item> + <Item Name="[value]" Condition="type == Variant::AABB">_data._aabb</Item> + <Item Name="[value]" Condition="type == Variant::BASIS">_data._basis</Item> + <Item Name="[value]" Condition="type == Variant::TRANSFORM">_data._transform</Item> + <Item Name="[value]" Condition="type == Variant::STRING">*(String *)_data._mem</Item> + <Item Name="[value]" Condition="type == Variant::VECTOR2">*(Vector2 *)_data._mem</Item> + <Item Name="[value]" Condition="type == Variant::RECT2">*(Rect2 *)_data._mem</Item> + <Item Name="[value]" Condition="type == Variant::VECTOR3">*(Vector3 *)_data._mem</Item> + <Item Name="[value]" Condition="type == Variant::PLANE">*(Plane *)_data._mem</Item> + <Item Name="[value]" Condition="type == Variant::QUAT">*(Quat *)_data._mem</Item> + <Item Name="[value]" Condition="type == Variant::COLOR">*(Color *)_data._mem</Item> + <Item Name="[value]" Condition="type == Variant::NODE_PATH">*(NodePath *)_data._mem</Item> + <Item Name="[value]" Condition="type == Variant::_RID">*(RID *)_data._mem</Item> + <Item Name="[value]" Condition="type == Variant::OBJECT">*(Object *)_data._mem</Item> + <Item Name="[value]" Condition="type == Variant::DICTIONARY">*(Dictionary *)_data._mem</Item> + <Item Name="[value]" Condition="type == Variant::ARRAY">*(Array *)_data._mem</Item> + <Item Name="[value]" Condition="type == Variant::POOL_BYTE_ARRAY">*(PoolByteArray *)_data._mem</Item> + <Item Name="[value]" Condition="type == Variant::POOL_INT_ARRAY">*(PoolIntArray *)_data._mem</Item> + <Item Name="[value]" Condition="type == Variant::POOL_REAL_ARRAY">*(PoolRealArray *)_data._mem</Item> + <Item Name="[value]" Condition="type == Variant::POOL_STRING_ARRAY">*(PoolStringArray *)_data._mem</Item> + <Item Name="[value]" Condition="type == Variant::POOL_VECTOR2_ARRAY">*(PoolVector2Array *)_data._mem</Item> + <Item Name="[value]" Condition="type == Variant::POOL_VECTOR3_ARRAY">*(PoolVector3Array *)_data._mem</Item> + <Item Name="[value]" Condition="type == Variant::POOL_COLOR_ARRAY">*(PoolColorArray *)_data._mem</Item> </Expand> </Type> <Type Name="String"> - <DisplayString Condition="this->_cowdata._ptr == 0">empty</DisplayString> - <DisplayString Condition="this->_cowdata._ptr != 0">{this->_cowdata._ptr,su}</DisplayString> - <StringView Condition="this->_cowdata._ptr != 0">this->_cowdata._ptr,su</StringView> + <DisplayString Condition="_cowdata._ptr == 0">[empty]</DisplayString> + <DisplayString Condition="_cowdata._ptr != 0">{_cowdata._ptr,su}</DisplayString> + <StringView Condition="_cowdata._ptr != 0">_cowdata._ptr,su</StringView> + </Type> + + <Type Name="StringName"> + <DisplayString Condition="_data && _data->cname">{_data->cname}</DisplayString> + <DisplayString Condition="_data && !_data->cname">{_data->name,su}</DisplayString> + <DisplayString Condition="!_data">[empty]</DisplayString> + <StringView Condition="_data && _data->cname">_data->cname</StringView> + <StringView Condition="_data && !_data->cname">_data->name,su</StringView> </Type> <Type Name="Vector2"> diff --git a/platform/windows/godot_win.cpp b/platform/windows/godot_windows.cpp index 0f5065d816..0b52682c7c 100644 --- a/platform/windows/godot_win.cpp +++ b/platform/windows/godot_windows.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* godot_win.cpp */ +/* godot_windows.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -30,6 +30,7 @@ #include "main/main.h" #include "os_windows.h" + #include <locale.h> #include <stdio.h> diff --git a/platform/windows/joypad.cpp b/platform/windows/joypad_windows.cpp index 5fafc7c8c0..5a399cdf90 100644 --- a/platform/windows/joypad.cpp +++ b/platform/windows/joypad_windows.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* joypad.cpp */ +/* joypad_windows.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "joypad.h" +#include "joypad_windows.h" #include <oleauto.h> #include <wbemidl.h> diff --git a/platform/windows/joypad.h b/platform/windows/joypad_windows.h index 3a6c0cef9f..4af5d9bd6a 100644 --- a/platform/windows/joypad.h +++ b/platform/windows/joypad_windows.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* joypad.h */ +/* joypad_windows.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,10 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef JOYPAD_H -#define JOYPAD_H +#ifndef JOYPAD_WINDOWS_H +#define JOYPAD_WINDOWS_H #include "os_windows.h" + #define DIRECTINPUT_VERSION 0x0800 #include <dinput.h> #include <xinput.h> // on unix the file is called "xinput.h", on windows I'm sure it won't mind @@ -145,4 +146,4 @@ private: XInputSetState_t xinput_set_state; }; -#endif +#endif // JOYPAD_WINDOWS_H diff --git a/platform/windows/key_mapping_win.cpp b/platform/windows/key_mapping_windows.cpp index f9b01e5532..01bbb072bb 100644 --- a/platform/windows/key_mapping_win.cpp +++ b/platform/windows/key_mapping_windows.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* key_mapping_win.cpp */ +/* key_mapping_windows.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "key_mapping_win.h" +#include "key_mapping_windows.h" #include <stdio.h> diff --git a/platform/windows/key_mapping_win.h b/platform/windows/key_mapping_windows.h index e4f8a61d04..dbb8c20f1e 100644 --- a/platform/windows/key_mapping_win.h +++ b/platform/windows/key_mapping_windows.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* key_mapping_win.h */ +/* key_mapping_windows.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -45,4 +45,4 @@ public: static unsigned int get_keysym(unsigned int p_code); }; -#endif +#endif // KEY_MAPPING_WINDOWS_H diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 35f9d541ef..6125455e74 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -43,15 +43,16 @@ #include "drivers/windows/rw_lock_windows.h" #include "drivers/windows/semaphore_windows.h" #include "drivers/windows/thread_windows.h" -#include "joypad.h" +#include "joypad_windows.h" #include "lang_table.h" #include "main/main.h" #include "servers/audio_server.h" #include "servers/visual/visual_server_raster.h" #include "servers/visual/visual_server_wrap_mt.h" #include "windows_terminal_logger.h" -#include <avrt.h> +#include <avrt.h> +#include <direct.h> #include <process.h> #include <regstr.h> #include <shlobj.h> @@ -270,7 +271,7 @@ void OS_Windows::_touch_event(bool p_pressed, float p_x, float p_y, int idx) { event->set_position(Vector2(p_x, p_y)); if (main_loop) { - input->parse_input_event(event); + input->accumulate_input_event(event); } }; @@ -292,11 +293,21 @@ void OS_Windows::_drag_event(float p_x, float p_y, int idx) { event->set_position(Vector2(p_x, p_y)); if (main_loop) - input->parse_input_event(event); + input->accumulate_input_event(event); }; LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + if (drop_events) { + + if (user_proc) { + + return CallWindowProcW(user_proc, hWnd, uMsg, wParam, lParam); + } else { + return DefWindowProcW(hWnd, uMsg, wParam, lParam); + } + }; + switch (uMsg) // Check For Windows Messages { case WM_SETFOCUS: { @@ -447,7 +458,7 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) } if (window_has_focus && main_loop && mm->get_relative() != Vector2()) - input->parse_input_event(mm); + input->accumulate_input_event(mm); } delete[] lpb; } break; @@ -534,7 +545,7 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) old_x = mm->get_position().x; old_y = mm->get_position().y; if (window_has_focus && main_loop) - input->parse_input_event(mm); + input->accumulate_input_event(mm); } break; case WM_LBUTTONDOWN: @@ -707,14 +718,14 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) mb->set_global_position(mb->get_position()); if (main_loop) { - input->parse_input_event(mb); + input->accumulate_input_event(mb); if (mb->is_pressed() && mb->get_button_index() > 3 && mb->get_button_index() < 8) { //send release for mouse wheel Ref<InputEventMouseButton> mbd = mb->duplicate(); last_button_state &= ~(1 << (mbd->get_button_index() - 1)); mbd->set_button_mask(last_button_state); mbd->set_pressed(false); - input->parse_input_event(mbd); + input->accumulate_input_event(mbd); } } } break; @@ -977,7 +988,7 @@ void OS_Windows::process_key_events() { if (k->get_unicode() < 32) k->set_unicode(0); - input->parse_input_event(k); + input->accumulate_input_event(k); } //do nothing @@ -1015,7 +1026,7 @@ void OS_Windows::process_key_events() { k->set_echo((ke.uMsg == WM_KEYDOWN && (ke.lParam & (1 << 30)))); - input->parse_input_event(k); + input->accumulate_input_event(k); } break; } @@ -1273,13 +1284,13 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int gl_context = NULL; while (!gl_context) { - gl_context = memnew(ContextGL_Win(hWnd, gles3_context)); + gl_context = memnew(ContextGL_Windows(hWnd, gles3_context)); if (gl_context->initialize() != OK) { memdelete(gl_context); gl_context = NULL; - if (GLOBAL_GET("rendering/quality/driver/driver_fallback") == "Best" || editor) { + if (GLOBAL_GET("rendering/quality/driver/fallback_to_gles2") || editor) { if (p_video_driver == VIDEO_DRIVER_GLES2) { gl_initialization_error = true; break; @@ -1301,7 +1312,7 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int RasterizerGLES3::make_current(); break; } else { - if (GLOBAL_GET("rendering/quality/driver/driver_fallback") == "Best" || editor) { + if (GLOBAL_GET("rendering/quality/driver/fallback_to_gles2") || editor) { p_video_driver = VIDEO_DRIVER_GLES2; gles3_context = false; continue; @@ -1394,6 +1405,8 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); } + update_real_mouse_position(); + return OK; } @@ -1595,6 +1608,19 @@ Point2 OS_Windows::get_mouse_position() const { return Point2(old_x, old_y); } +void OS_Windows::update_real_mouse_position() { + + POINT mouse_pos; + if (GetCursorPos(&mouse_pos) && ScreenToClient(hWnd, &mouse_pos)) { + if (mouse_pos.x > 0 && mouse_pos.y > 0 && mouse_pos.x <= video_mode.width && mouse_pos.y <= video_mode.height) { + old_x = mouse_pos.x; + old_y = mouse_pos.y; + old_invalid = false; + input->set_mouse_position(Point2i(mouse_pos.x, mouse_pos.y)); + } + } +} + int OS_Windows::get_mouse_button_state() const { return last_button_state; @@ -1737,6 +1763,7 @@ void OS_Windows::set_window_position(const Point2 &p_position) { } last_pos = p_position; + update_real_mouse_position(); } Size2 OS_Windows::get_window_size() const { @@ -2137,7 +2164,9 @@ OS::TimeZoneInfo OS_Windows::get_time_zone_info() const { ret.name = info.StandardName; } - ret.bias = info.Bias; + // Bias value returned by GetTimeZoneInformation is inverted of what we expect + // For example on GMT-3 GetTimeZoneInformation return a Bias of 180, so invert the value to get -180 + ret.bias = -info.Bias; return ret; } @@ -2211,7 +2240,9 @@ void OS_Windows::process_events() { MSG msg; - joypad->process_joypads(); + if (!drop_events) { + joypad->process_joypads(); + } while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) { @@ -2219,7 +2250,10 @@ void OS_Windows::process_events() { DispatchMessageW(&msg); } - process_key_events(); + if (!drop_events) { + process_key_events(); + input->flush_accumulated_events(); + } } void OS_Windows::set_cursor_shape(CursorShape p_shape) { @@ -2604,6 +2638,11 @@ String OS_Windows::get_environment(const String &p_var) const { return ""; } +bool OS_Windows::set_environment(const String &p_var, const String &p_value) const { + + return (bool)SetEnvironmentVariableW(p_var.c_str(), p_value.c_str()); +} + String OS_Windows::get_stdin_string(bool p_block) { if (p_block) { @@ -2952,7 +2991,7 @@ int OS_Windows::get_power_percent_left() { bool OS_Windows::_check_internal_feature_support(const String &p_feature) { - return p_feature == "pc" || p_feature == "s3tc" || p_feature == "bptc"; + return p_feature == "pc"; } void OS_Windows::disable_crash_handler() { @@ -2963,6 +3002,13 @@ bool OS_Windows::is_disable_crash_handler() const { return crash_handler.is_disabled(); } +void OS_Windows::process_and_drop_events() { + + drop_events = true; + process_events(); + drop_events = false; +} + Error OS_Windows::move_to_trash(const String &p_path) { SHFILEOPSTRUCTW sf; WCHAR *from = new WCHAR[p_path.length() + 2]; @@ -2991,6 +3037,7 @@ Error OS_Windows::move_to_trash(const String &p_path) { OS_Windows::OS_Windows(HINSTANCE _hInstance) { + drop_events = false; key_event_pos = 0; layered_window = false; hBitmap = NULL; @@ -3014,9 +3061,6 @@ OS_Windows::OS_Windows(HINSTANCE _hInstance) { #ifdef WASAPI_ENABLED AudioDriverManager::add_driver(&driver_wasapi); #endif -#ifdef RTAUDIO_ENABLED - AudioDriverManager::add_driver(&driver_rtaudio); -#endif #ifdef XAUDIO2_ENABLED AudioDriverManager::add_driver(&driver_xaudio2); #endif diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index 4936a69120..2d03532c69 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -30,14 +30,17 @@ #ifndef OS_WINDOWS_H #define OS_WINDOWS_H -#include "context_gl_win.h" + +#include "context_gl_windows.h" #include "core/os/input.h" #include "core/os/os.h" #include "core/project_settings.h" -#include "crash_handler_win.h" -#include "drivers/rtaudio/audio_driver_rtaudio.h" +#include "crash_handler_windows.h" +#include "drivers/unix/ip_unix.h" #include "drivers/wasapi/audio_driver_wasapi.h" -#include "drivers/winmidi/win_midi.h" +#include "drivers/winmidi/midi_driver_winmidi.h" +#include "key_mapping_windows.h" +#include "main/input_default.h" #include "power_windows.h" #include "servers/audio_server.h" #include "servers/visual/rasterizer.h" @@ -45,9 +48,6 @@ #ifdef XAUDIO2_ENABLED #include "drivers/xaudio2/audio_driver_xaudio2.h" #endif -#include "drivers/unix/ip_unix.h" -#include "key_mapping_win.h" -#include "main/input_default.h" #include <fcntl.h> #include <io.h> @@ -86,7 +86,7 @@ class OS_Windows : public OS { int old_x, old_y; Point2i center; #if defined(OPENGL_ENABLED) - ContextGL_Win *gl_context; + ContextGL_Windows *gl_context; #endif VisualServer *visual_server; int pressrc; @@ -127,6 +127,7 @@ class OS_Windows : public OS { bool window_has_focus; uint32_t last_button_state; bool use_raw_input; + bool drop_events; HCURSOR cursors[CURSOR_MAX] = { NULL }; CursorShape cursor_shape; @@ -141,9 +142,6 @@ class OS_Windows : public OS { #ifdef WASAPI_ENABLED AudioDriverWASAPI driver_wasapi; #endif -#ifdef RTAUDIO_ENABLED - AudioDriverRtAudio driver_rtaudio; -#endif #ifdef XAUDIO2_ENABLED AudioDriverXAudio2 driver_xaudio2; #endif @@ -200,6 +198,7 @@ public: virtual void warp_mouse_position(const Point2 &p_to); virtual Point2 get_mouse_position() const; + void update_real_mouse_position(); virtual int get_mouse_button_state() const; virtual void set_window_title(const String &p_title); @@ -268,6 +267,7 @@ public: virtual bool has_environment(const String &p_var) const; virtual String get_environment(const String &p_var) const; + virtual bool set_environment(const String &p_var, const String &p_value) const; virtual void set_clipboard(const String &p_text); virtual String get_clipboard() const; @@ -331,6 +331,8 @@ public: virtual Error move_to_trash(const String &p_path); + virtual void process_and_drop_events(); + OS_Windows(HINSTANCE _hInstance); ~OS_Windows(); }; diff --git a/platform/windows/power_windows.h b/platform/windows/power_windows.h index 4d83d75e00..ef75ce6271 100644 --- a/platform/windows/power_windows.h +++ b/platform/windows/power_windows.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PLATFORM_WINDOWS_POWER_WINDOWS_H_ -#define PLATFORM_WINDOWS_POWER_WINDOWS_H_ +#ifndef POWER_WINDOWS_H +#define POWER_WINDOWS_H #include "core/os/dir_access.h" #include "core/os/file_access.h" @@ -55,4 +55,4 @@ public: int get_power_percent_left(); }; -#endif /* PLATFORM_WINDOWS_POWER_WINDOWS_H_ */ +#endif // POWER_WINDOWS_H diff --git a/platform/x11/crash_handler_x11.cpp b/platform/x11/crash_handler_x11.cpp index 8737a2b92b..1e7f393bdd 100644 --- a/platform/x11/crash_handler_x11.cpp +++ b/platform/x11/crash_handler_x11.cpp @@ -28,15 +28,16 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef DEBUG_ENABLED -#define CRASH_HANDLER_ENABLED 1 -#endif - #include "crash_handler_x11.h" + #include "core/os/os.h" #include "core/project_settings.h" #include "main/main.h" +#ifdef DEBUG_ENABLED +#define CRASH_HANDLER_ENABLED 1 +#endif + #ifdef CRASH_HANDLER_ENABLED #include <cxxabi.h> #include <dlfcn.h> diff --git a/platform/x11/crash_handler_x11.h b/platform/x11/crash_handler_x11.h index 6efdd33d9d..d0664aef85 100644 --- a/platform/x11/crash_handler_x11.h +++ b/platform/x11/crash_handler_x11.h @@ -45,4 +45,4 @@ public: ~CrashHandler(); }; -#endif +#endif // CRASH_HANDLER_X11_H diff --git a/platform/x11/detect.py b/platform/x11/detect.py index 72139538b7..b5ad59e60a 100644 --- a/platform/x11/detect.py +++ b/platform/x11/detect.py @@ -2,7 +2,7 @@ import os import platform import sys from compat import decode_utf8 - +from methods import get_compiler_version, use_gcc def is_active(): return True @@ -20,12 +20,10 @@ def can_build(): # Check the minimal dependencies x11_error = os.system("pkg-config --version > /dev/null") if (x11_error): - print("pkg-config not found.. x11 disabled.") return False x11_error = os.system("pkg-config x11 --modversion > /dev/null ") if (x11_error): - print("X11 not found.. x11 disabled.") return False x11_error = os.system("pkg-config xcursor --modversion > /dev/null ") @@ -161,16 +159,10 @@ def configure(env): env.Append(CCFLAGS=['-pipe']) env.Append(LINKFLAGS=['-pipe']) - # Check for gcc version > 5 before adding -no-pie - import re - import subprocess - proc = subprocess.Popen([env['CXX'], '--version'], stdout=subprocess.PIPE) - (stdout, _) = proc.communicate() - stdout = decode_utf8(stdout) - match = re.search('[0-9][0-9.]*', stdout) - if match is not None: - version = match.group().split('.') - if (version[0] > '5'): + # Check for gcc version >= 6 before adding -no-pie + if use_gcc(env): + version = get_compiler_version(env) + if version != None and version[0] >= '6': env.Append(CCFLAGS=['-fpie']) env.Append(LINKFLAGS=['-no-pie']) diff --git a/platform/x11/detect_prime.cpp b/platform/x11/detect_prime.cpp index 04a825fac9..0fde2a0c04 100644 --- a/platform/x11/detect_prime.cpp +++ b/platform/x11/detect_prime.cpp @@ -180,8 +180,8 @@ int detect_prime() { const char *vendor = (const char *)glGetString(GL_VENDOR); const char *renderer = (const char *)glGetString(GL_RENDERER); - int vendor_len = strlen(vendor) + 1; - int renderer_len = strlen(renderer) + 1; + unsigned int vendor_len = strlen(vendor) + 1; + unsigned int renderer_len = strlen(renderer) + 1; if (vendor_len + renderer_len >= sizeof(string)) { renderer_len = 200 - vendor_len; diff --git a/platform/x11/joypad_linux.cpp b/platform/x11/joypad_linux.cpp index 907c652ab4..c4dd8fe0e0 100644 --- a/platform/x11/joypad_linux.cpp +++ b/platform/x11/joypad_linux.cpp @@ -367,12 +367,12 @@ void JoypadLinux::open_joypad(const char *p_path) { joy.fd = fd; joy.devpath = String(p_path); setup_joypad_properties(joy_num); - sprintf(uid, "%04x%04x", __bswap_16(inpid.bustype), 0); + sprintf(uid, "%04x%04x", BSWAP16(inpid.bustype), 0); if (inpid.vendor && inpid.product && inpid.version) { - uint16_t vendor = __bswap_16(inpid.vendor); - uint16_t product = __bswap_16(inpid.product); - uint16_t version = __bswap_16(inpid.version); + uint16_t vendor = BSWAP16(inpid.vendor); + uint16_t product = BSWAP16(inpid.product); + uint16_t version = BSWAP16(inpid.version); sprintf(uid + String(uid).length(), "%04x%04x%04x%04x%04x%04x", vendor, 0, product, 0, version, 0); input->joy_connection_changed(joy_num, true, name, uid); @@ -476,7 +476,7 @@ void JoypadLinux::process_joypads() { // ev may be tainted and out of MAX_KEY range, which will cause // joy->key_map[ev.code] to crash - if (ev.code < 0 || ev.code >= MAX_KEY) + if (ev.code >= MAX_KEY) return; switch (ev.type) { diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index e0924fc982..0fe91f3d00 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -243,8 +243,37 @@ Error OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_a // maybe contextgl wants to be in charge of creating the window #if defined(OPENGL_ENABLED) if (getenv("DRI_PRIME") == NULL) { - print_verbose("Detecting GPUs, set DRI_PRIME in the environment to override GPU detection logic."); - int use_prime = detect_prime(); + int use_prime = -1; + + if (getenv("PRIMUS_DISPLAY") || + getenv("PRIMUS_libGLd") || + getenv("PRIMUS_libGLa") || + getenv("PRIMUS_libGL") || + getenv("PRIMUS_LOAD_GLOBAL") || + getenv("BUMBLEBEE_SOCKET")) { + + print_verbose("Optirun/primusrun detected. Skipping GPU detection"); + use_prime = 0; + } + + if (getenv("LD_LIBRARY_PATH")) { + String ld_library_path(getenv("LD_LIBRARY_PATH")); + Vector<String> libraries = ld_library_path.split(":"); + + for (int i = 0; i < libraries.size(); ++i) { + if (FileAccess::exists(libraries[i] + "/libGL.so.1") || + FileAccess::exists(libraries[i] + "/libGL.so")) { + + print_verbose("Custom libGL override detected. Skipping GPU detection"); + use_prime = 0; + } + } + } + + if (use_prime == -1) { + print_verbose("Detecting GPUs, set DRI_PRIME in the environment to override GPU detection logic."); + use_prime = detect_prime(); + } if (use_prime) { print_line("Found discrete GPU, setting DRI_PRIME=1 to use it."); @@ -270,7 +299,7 @@ Error OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_a memdelete(context_gl); context_gl = NULL; - if (GLOBAL_GET("rendering/quality/driver/driver_fallback") == "Best" || editor) { + if (GLOBAL_GET("rendering/quality/driver/fallback_to_gles2") || editor) { if (p_video_driver == VIDEO_DRIVER_GLES2) { gl_initialization_error = true; break; @@ -292,7 +321,7 @@ Error OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_a RasterizerGLES3::make_current(); break; } else { - if (GLOBAL_GET("rendering/quality/driver/driver_fallback") == "Best" || editor) { + if (GLOBAL_GET("rendering/quality/driver/fallback_to_gles2") || editor) { p_video_driver = VIDEO_DRIVER_GLES2; opengl_api_type = ContextGL_X11::GLES_2_0_COMPATIBLE; continue; @@ -1631,7 +1660,7 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) { k->set_shift(true); } - input->parse_input_event(k); + input->accumulate_input_event(k); } return; } @@ -1714,7 +1743,7 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) { // is correct, but the xorg developers are // not very helpful today. - ::Time tresh = ABS(peek_event.xkey.time - xkeyevent->time); + ::Time tresh = ABSDIFF(peek_event.xkey.time, xkeyevent->time); if (peek_event.type == KeyPress && tresh < 5) { KeySym rk; XLookupString((XKeyEvent *)&peek_event, str, 256, &rk, NULL); @@ -1775,7 +1804,7 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) { } //printf("key: %x\n",k->get_scancode()); - input->parse_input_event(k); + input->accumulate_input_event(k); } struct Property { @@ -1962,12 +1991,12 @@ void OS_X11::process_xevents() { // in a spurious mouse motion event being sent to Godot; remember it to be able to filter it out xi.mouse_pos_to_filter = pos; } - input->parse_input_event(st); + input->accumulate_input_event(st); } else { if (!xi.state.has(index)) // Defensive break; xi.state.erase(index); - input->parse_input_event(st); + input->accumulate_input_event(st); } } break; @@ -1985,7 +2014,7 @@ void OS_X11::process_xevents() { sd->set_index(index); sd->set_position(pos); sd->set_relative(pos - curr_pos_elem->value()); - input->parse_input_event(sd); + input->accumulate_input_event(sd); curr_pos_elem->value() = pos; } @@ -2073,7 +2102,7 @@ void OS_X11::process_xevents() { st.instance(); st->set_index(E->key()); st->set_position(E->get()); - input->parse_input_event(st); + input->accumulate_input_event(st); } xi.state.clear(); #endif @@ -2134,7 +2163,7 @@ void OS_X11::process_xevents() { } } - input->parse_input_event(mb); + input->accumulate_input_event(mb); } break; case MotionNotify: { @@ -2244,7 +2273,7 @@ void OS_X11::process_xevents() { // this is so that the relative motion doesn't get messed up // after we regain focus. if (window_has_focus || !mouse_mode_grab) - input->parse_input_event(mm); + input->accumulate_input_event(mm); } break; case KeyPress: @@ -2326,7 +2355,7 @@ void OS_X11::process_xevents() { Vector<String> files = String((char *)p.data).split("\n", false); for (int i = 0; i < files.size(); i++) { - files.write[i] = files[i].replace("file://", "").replace("%20", " ").strip_escapes(); + files.write[i] = files[i].replace("file://", "").http_unescape().strip_escapes(); } main_loop->drop_files(files); @@ -2428,6 +2457,8 @@ void OS_X11::process_xevents() { printf("Win: %d,%d\n", win_x, win_y); */ } + + input->flush_accumulated_events(); } MainLoop *OS_X11::get_main_loop() const { @@ -2564,7 +2595,7 @@ Error OS_X11::shell_open(String p_uri) { bool OS_X11::_check_internal_feature_support(const String &p_feature) { - return p_feature == "pc" || p_feature == "s3tc" || p_feature == "bptc"; + return p_feature == "pc"; } String OS_X11::get_config_path() const { @@ -3004,7 +3035,9 @@ bool OS_X11::is_vsync_enabled() const { */ void OS_X11::set_context(int p_context) { + char *config_name = NULL; XClassHint *classHint = XAllocClassHint(); + if (classHint) { char *wm_class = (char *)"Godot"; @@ -3015,13 +3048,21 @@ void OS_X11::set_context(int p_context) { if (p_context == CONTEXT_ENGINE) { classHint->res_name = (char *)"Godot_Engine"; - wm_class = (char *)((String)GLOBAL_GET("application/config/name")).utf8().ptrw(); + String config_name_tmp = GLOBAL_GET("application/config/name"); + if (config_name_tmp.length() > 0) { + config_name = strdup(config_name_tmp.utf8().get_data()); + } else { + config_name = strdup("Godot Engine"); + } + + wm_class = config_name; } classHint->res_class = wm_class; XSetClassHint(x11_display, x11_window, classHint); XFree(classHint); + free(config_name); } } diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h index cf1619bae2..6d1a66af84 100644 --- a/platform/x11/os_x11.h +++ b/platform/x11/os_x11.h @@ -35,7 +35,7 @@ #include "core/os/input.h" #include "crash_handler_x11.h" #include "drivers/alsa/audio_driver_alsa.h" -#include "drivers/alsamidi/alsa_midi.h" +#include "drivers/alsamidi/midi_driver_alsamidi.h" #include "drivers/pulseaudio/audio_driver_pulseaudio.h" #include "drivers/unix/os_unix.h" #include "joypad_linux.h" diff --git a/platform/x11/power_x11.h b/platform/x11/power_x11.h index 56fbd602f4..469e3910f4 100644 --- a/platform/x11/power_x11.h +++ b/platform/x11/power_x11.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef X11_POWER_H_ -#define X11_POWER_H_ +#ifndef POWER_X11_H +#define POWER_X11_H #include "core/os/dir_access.h" #include "core/os/file_access.h" @@ -63,4 +63,4 @@ public: int get_power_percent_left(); }; -#endif /* X11_POWER_H_ */ +#endif // POWER_X11_H |