diff options
Diffstat (limited to 'platform')
-rw-r--r-- | platform/android/os_android.cpp | 74 | ||||
-rw-r--r-- | platform/android/os_android.h | 4 | ||||
-rw-r--r-- | platform/ios/os_ios.h | 2 | ||||
-rw-r--r-- | platform/ios/os_ios.mm | 9 | ||||
-rw-r--r-- | platform/linuxbsd/os_linuxbsd.cpp | 37 | ||||
-rw-r--r-- | platform/linuxbsd/os_linuxbsd.h | 4 | ||||
-rw-r--r-- | platform/macos/os_macos.h | 2 | ||||
-rw-r--r-- | platform/macos/os_macos.mm | 9 | ||||
-rw-r--r-- | platform/uwp/os_uwp.cpp | 10 | ||||
-rw-r--r-- | platform/uwp/os_uwp.h | 2 | ||||
-rw-r--r-- | platform/web/.eslintrc.engine.js | 1 | ||||
-rw-r--r-- | platform/web/SCsub | 1 | ||||
-rw-r--r-- | platform/web/js/engine/engine.js | 25 | ||||
-rw-r--r-- | platform/web/js/engine/features.js | 96 | ||||
-rw-r--r-- | platform/web/package.json | 2 | ||||
-rw-r--r-- | platform/windows/godot.natvis | 84 | ||||
-rw-r--r-- | platform/windows/os_windows.cpp | 18 | ||||
-rw-r--r-- | platform/windows/os_windows.h | 2 |
18 files changed, 348 insertions, 34 deletions
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 142dc54c45..4469c7a0f7 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -44,6 +44,7 @@ #include "net_socket_android.h" #include <dlfcn.h> +#include <sys/system_properties.h> #include "java_godot_io_wrapper.h" #include "java_godot_wrapper.h" @@ -175,6 +176,79 @@ String OS_Android::get_name() const { return "Android"; } +String OS_Android::get_system_property(const char *key) const { + static String value; + char value_str[PROP_VALUE_MAX]; + if (__system_property_get(key, value_str)) { + value = String(value_str); + } + return value; +} + +String OS_Android::get_distribution_name() const { + if (!get_system_property("ro.havoc.version").is_empty()) { + return "Havoc OS"; + } else if (!get_system_property("org.pex.version").is_empty()) { // Putting before "Pixel Experience", because it's derivating from it. + return "Pixel Extended"; + } else if (!get_system_property("org.pixelexperience.version").is_empty()) { + return "Pixel Experience"; + } else if (!get_system_property("ro.potato.version").is_empty()) { + return "POSP"; + } else if (!get_system_property("ro.xtended.version").is_empty()) { + return "Project-Xtended"; + } else if (!get_system_property("org.evolution.version").is_empty()) { + return "Evolution X"; + } else if (!get_system_property("ro.corvus.version").is_empty()) { + return "Corvus-Q"; + } else if (!get_system_property("ro.pa.version").is_empty()) { + return "Paranoid Android"; + } else if (!get_system_property("ro.crdroid.version").is_empty()) { + return "crDroid Android"; + } else if (!get_system_property("ro.syberia.version").is_empty()) { + return "Syberia Project"; + } else if (!get_system_property("ro.arrow.version").is_empty()) { + return "ArrowOS"; + } else if (!get_system_property("ro.lineage.version").is_empty()) { // Putting LineageOS last, just in case any derivative writes to "ro.lineage.version". + return "LineageOS"; + } + + if (!get_system_property("ro.modversion").is_empty()) { // Handles other Android custom ROMs. + return vformat("%s %s", get_name(), "Custom ROM"); + } + + // Handles stock Android. + return get_name(); +} + +String OS_Android::get_version() const { + const Vector<const char *> roms = { "ro.havoc.version", "org.pex.version", "org.pixelexperience.version", + "ro.potato.version", "ro.xtended.version", "org.evolution.version", "ro.corvus.version", "ro.pa.version", + "ro.crdroid.version", "ro.syberia.version", "ro.arrow.version", "ro.lineage.version" }; + for (int i = 0; i < roms.size(); i++) { + static String rom_version = get_system_property(roms[i]); + if (!rom_version.is_empty()) { + return rom_version; + } + } + + static String mod_version = get_system_property("ro.modversion"); // Handles other Android custom ROMs. + if (!mod_version.is_empty()) { + return mod_version; + } + + // Handles stock Android. + static String sdk_version = get_system_property("ro.build.version.sdk_int"); + static String build = get_system_property("ro.build.version.incremental"); + if (!sdk_version.is_empty()) { + if (!build.is_empty()) { + return vformat("%s.%s", sdk_version, build); + } + return sdk_version; + } + + return ""; +} + MainLoop *OS_Android::get_main_loop() const { return main_loop; } diff --git a/platform/android/os_android.h b/platform/android/os_android.h index 96c06d715c..d6546a3507 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -65,6 +65,8 @@ private: GodotJavaWrapper *godot_java = nullptr; GodotIOJavaWrapper *godot_io_java = nullptr; + String get_system_property(const char *key) const; + public: static const char *ANDROID_EXEC_PATH; @@ -93,6 +95,8 @@ public: virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr) override; virtual String get_name() const override; + virtual String get_distribution_name() const override; + virtual String get_version() const override; virtual MainLoop *get_main_loop() const override; void main_loop_begin(); diff --git a/platform/ios/os_ios.h b/platform/ios/os_ios.h index 3b88f53b6a..00d91da771 100644 --- a/platform/ios/os_ios.h +++ b/platform/ios/os_ios.h @@ -100,6 +100,8 @@ public: virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false) override; virtual String get_name() const override; + virtual String get_distribution_name() const override; + virtual String get_version() const override; virtual String get_model_name() const override; virtual Error shell_open(String p_uri) override; diff --git a/platform/ios/os_ios.mm b/platform/ios/os_ios.mm index b9d186f355..a674498620 100644 --- a/platform/ios/os_ios.mm +++ b/platform/ios/os_ios.mm @@ -240,6 +240,15 @@ String OS_IOS::get_name() const { return "iOS"; } +String OS_IOS::get_distribution_name() const { + return get_name(); +} + +String OS_IOS::get_version() const { + NSOperatingSystemVersion ver = [NSProcessInfo processInfo].operatingSystemVersion; + return vformat("%d.%d.%d", (int64_t)ver.majorVersion, (int64_t)ver.minorVersion, (int64_t)ver.patchVersion); +} + String OS_IOS::get_model_name() const { String model = ios->get_model(); if (model != "") { diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp index f0d7b6ede5..f4e94f1a91 100644 --- a/platform/linuxbsd/os_linuxbsd.cpp +++ b/platform/linuxbsd/os_linuxbsd.cpp @@ -50,6 +50,7 @@ #include <fcntl.h> #include <sys/stat.h> #include <sys/types.h> +#include <sys/utsname.h> #include <unistd.h> #ifdef FONTCONFIG_ENABLED @@ -205,6 +206,42 @@ String OS_LinuxBSD::get_name() const { #endif } +String OS_LinuxBSD::get_systemd_os_release_info_value(const String &key) const { + static String info; + if (info.is_empty()) { + Ref<FileAccess> f = FileAccess::open("/etc/os-release", FileAccess::READ); + if (f.is_valid()) { + while (!f->eof_reached()) { + const String line = f->get_line(); + if (line.find(key) != -1) { + return line.split("=")[1].strip_edges(); + } + } + } + } + return info; +} + +String OS_LinuxBSD::get_distribution_name() const { + static String systemd_name = get_systemd_os_release_info_value("NAME"); // returns a value for systemd users, otherwise an empty string. + if (!systemd_name.is_empty()) { + return systemd_name; + } + struct utsname uts; // returns a decent value for BSD family. + uname(&uts); + return uts.sysname; +} + +String OS_LinuxBSD::get_version() const { + static String systemd_version = get_systemd_os_release_info_value("VERSION"); // returns a value for systemd users, otherwise an empty string. + if (!systemd_version.is_empty()) { + return systemd_version; + } + struct utsname uts; // returns a decent value for BSD family. + uname(&uts); + return uts.version; +} + Error OS_LinuxBSD::shell_open(String p_uri) { Error ok; int err_code; diff --git a/platform/linuxbsd/os_linuxbsd.h b/platform/linuxbsd/os_linuxbsd.h index d5b2321316..722d83ba19 100644 --- a/platform/linuxbsd/os_linuxbsd.h +++ b/platform/linuxbsd/os_linuxbsd.h @@ -67,6 +67,8 @@ class OS_LinuxBSD : public OS_Unix { MainLoop *main_loop = nullptr; + String get_systemd_os_release_info_value(const String &key) const; + protected: virtual void initialize() override; virtual void finalize() override; @@ -77,6 +79,8 @@ protected: public: virtual String get_name() const override; + virtual String get_distribution_name() const override; + virtual String get_version() const override; virtual MainLoop *get_main_loop() const override; diff --git a/platform/macos/os_macos.h b/platform/macos/os_macos.h index 61db99689c..46e7c17ebe 100644 --- a/platform/macos/os_macos.h +++ b/platform/macos/os_macos.h @@ -75,6 +75,8 @@ public: virtual List<String> get_cmdline_platform_args() const override; virtual String get_name() const override; + virtual String get_distribution_name() const override; + virtual String get_version() const override; virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override; diff --git a/platform/macos/os_macos.mm b/platform/macos/os_macos.mm index c250a9d71a..ae8534f6ab 100644 --- a/platform/macos/os_macos.mm +++ b/platform/macos/os_macos.mm @@ -134,6 +134,15 @@ String OS_MacOS::get_name() const { return "macOS"; } +String OS_MacOS::get_distribution_name() const { + return get_name(); +} + +String OS_MacOS::get_version() const { + NSOperatingSystemVersion ver = [NSProcessInfo processInfo].operatingSystemVersion; + return vformat("%d.%d.%d", (int64_t)ver.majorVersion, (int64_t)ver.minorVersion, (int64_t)ver.patchVersion); +} + void OS_MacOS::alert(const String &p_alert, const String &p_title) { NSAlert *window = [[NSAlert alloc] init]; NSString *ns_title = [NSString stringWithUTF8String:p_title.utf8().get_data()]; diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp index 791328964b..8050d299f0 100644 --- a/platform/uwp/os_uwp.cpp +++ b/platform/uwp/os_uwp.cpp @@ -444,6 +444,16 @@ String OS_UWP::get_name() const { return "UWP"; } +String OS_UWP::get_distribution_name() const { + return get_name(); +} + +String OS_UWP::get_version() const { + winrt::hstring df_version = VersionInfo().DeviceFamilyVersion(); + static String version = String(winrt::to_string(df_version).c_str()); + return version; +} + OS::DateTime OS_UWP::get_datetime(bool p_utc) const { SYSTEMTIME systemtime; if (p_utc) { diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h index 7d4224cf74..0c1c4a793a 100644 --- a/platform/uwp/os_uwp.h +++ b/platform/uwp/os_uwp.h @@ -183,6 +183,8 @@ public: virtual MainLoop *get_main_loop() const; virtual String get_name() const; + virtual String get_distribution_name() const; + virtual String get_version() const; virtual DateTime get_datetime(bool p_utc) const; virtual TimeZoneInfo get_time_zone_info() const; diff --git a/platform/web/.eslintrc.engine.js b/platform/web/.eslintrc.engine.js index 78df6d41d9..a76bd46b9e 100644 --- a/platform/web/.eslintrc.engine.js +++ b/platform/web/.eslintrc.engine.js @@ -5,6 +5,7 @@ module.exports = { "globals": { "InternalConfig": true, "Godot": true, + "Features": true, "Preloader": true, }, }; diff --git a/platform/web/SCsub b/platform/web/SCsub index e8d0181ede..013b734be2 100644 --- a/platform/web/SCsub +++ b/platform/web/SCsub @@ -66,6 +66,7 @@ sys_env.Depends(build[0], sys_env["JS_PRE"]) sys_env.Depends(build[0], sys_env["JS_EXTERNS"]) engine = [ + "js/engine/features.js", "js/engine/preloader.js", "js/engine/config.js", "js/engine/engine.js", diff --git a/platform/web/js/engine/engine.js b/platform/web/js/engine/engine.js index 6f0d51b2be..9227aa1f05 100644 --- a/platform/web/js/engine/engine.js +++ b/platform/web/js/engine/engine.js @@ -61,20 +61,6 @@ const Engine = (function () { }; /** - * Check whether WebGL is available. Optionally, specify a particular version of WebGL to check for. - * - * @param {number=} [majorVersion=1] The major WebGL version to check for. - * @returns {boolean} If the given major version of WebGL is available. - * @function Engine.isWebGLAvailable - */ - Engine.isWebGLAvailable = function (majorVersion = 1) { - try { - return !!document.createElement('canvas').getContext(['webgl', 'webgl2'][majorVersion - 1]); - } catch (e) { /* Not available */ } - return false; - }; - - /** * Safe Engine constructor, creates a new prototype for every new instance to avoid prototype pollution. * @ignore * @constructor @@ -265,14 +251,21 @@ const Engine = (function () { // Also expose static methods as instance methods Engine.prototype['load'] = Engine.load; Engine.prototype['unload'] = Engine.unload; - Engine.prototype['isWebGLAvailable'] = Engine.isWebGLAvailable; return new Engine(initConfig); } // Closure compiler exported static methods. SafeEngine['load'] = Engine.load; SafeEngine['unload'] = Engine.unload; - SafeEngine['isWebGLAvailable'] = Engine.isWebGLAvailable; + + // Feature-detection utilities. + SafeEngine['isWebGLAvailable'] = Features.isWebGLAvailable; + SafeEngine['isFetchAvailable'] = Features.isFetchAvailable; + SafeEngine['isSecureContext'] = Features.isSecureContext; + SafeEngine['isCrossOriginIsolated'] = Features.isCrossOriginIsolated; + SafeEngine['isSharedArrayBufferAvailable'] = Features.isSharedArrayBufferAvailable; + SafeEngine['isAudioWorkletAvailable'] = Features.isAudioWorkletAvailable; + SafeEngine['getMissingFeatures'] = Features.getMissingFeatures; return SafeEngine; }()); diff --git a/platform/web/js/engine/features.js b/platform/web/js/engine/features.js new file mode 100644 index 0000000000..f91a4eff81 --- /dev/null +++ b/platform/web/js/engine/features.js @@ -0,0 +1,96 @@ +const Features = { // eslint-disable-line no-unused-vars + /** + * Check whether WebGL is available. Optionally, specify a particular version of WebGL to check for. + * + * @param {number=} [majorVersion=1] The major WebGL version to check for. + * @returns {boolean} If the given major version of WebGL is available. + * @function Engine.isWebGLAvailable + */ + isWebGLAvailable: function (majorVersion = 1) { + try { + return !!document.createElement('canvas').getContext(['webgl', 'webgl2'][majorVersion - 1]); + } catch (e) { /* Not available */ } + return false; + }, + + /** + * Check whether the Fetch API available and supports streaming responses. + * + * @returns {boolean} If the Fetch API is available and supports streaming responses. + * @function Engine.isFetchAvailable + */ + isFetchAvailable: function () { + return 'fetch' in window && 'Response' in window && 'body' in window.Response.prototype; + }, + + /** + * Check whether the engine is running in a Secure Context. + * + * @returns {boolean} If the engine is running in a Secure Context. + * @function Engine.isSecureContext + */ + isSecureContext: function () { + return window['isSecureContext'] === true; + }, + + /** + * Check whether the engine is cross origin isolated. + * This value is dependent on Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy headers sent by the server. + * + * @returns {boolean} If the engine is running in a Secure Context. + * @function Engine.isSecureContext + */ + isCrossOriginIsolated: function () { + return window['crossOriginIsolated'] === true; + }, + + /** + * Check whether SharedBufferArray is available. + * + * Most browsers require the page to be running in a secure context, and the + * the server to provide specific CORS headers for SharedArrayBuffer to be available. + * + * @returns {boolean} If SharedArrayBuffer is available. + * @function Engine.isSharedArrayBufferAvailable + */ + isSharedArrayBufferAvailable: function () { + return 'SharedArrayBuffer' in window; + }, + + /** + * Check whether the AudioContext supports AudioWorkletNodes. + * + * @returns {boolean} If AudioWorkletNode is available. + * @function Engine.isAudioWorkletAvailable + */ + isAudioWorkletAvailable: function () { + return 'AudioContext' in window && 'audioWorklet' in AudioContext.prototype; + }, + + /** + * Return an array of missing required features (as string). + * + * @returns {Array<string>} A list of human-readable missing features. + * @function Engine.getMissingFeatures + */ + getMissingFeatures: function () { + const missing = []; + if (!Features.isWebGLAvailable(2)) { + missing.push('WebGL2'); + } + if (!Features.isFetchAvailable()) { + missing.push('Fetch'); + } + if (!Features.isSecureContext()) { + missing.push('Secure Context'); + } + if (!Features.isCrossOriginIsolated()) { + missing.push('Cross Origin Isolation'); + } + if (!Features.isSharedArrayBufferAvailable()) { + missing.push('SharedArrayBuffer'); + } + // Audio is normally optional since we have a dummy fallback. + return missing; + }, +}; diff --git a/platform/web/package.json b/platform/web/package.json index a57205415a..0a8d9e4334 100644 --- a/platform/web/package.json +++ b/platform/web/package.json @@ -4,7 +4,7 @@ "version": "1.0.0", "description": "Development and linting setup for Godot's Web platform code", "scripts": { - "docs": "jsdoc --template js/jsdoc2rst/ js/engine/engine.js js/engine/config.js --destination ''", + "docs": "jsdoc --template js/jsdoc2rst/ js/engine/engine.js js/engine/config.js js/engine/features.js --destination ''", "lint": "npm run lint:engine && npm run lint:libs && npm run lint:modules && npm run lint:tools", "lint:engine": "eslint \"js/engine/*.js\" --no-eslintrc -c .eslintrc.engine.js", "lint:libs": "eslint \"js/libs/*.js\" --no-eslintrc -c .eslintrc.libs.js", diff --git a/platform/windows/godot.natvis b/platform/windows/godot.natvis index cdd1c14978..36b0919185 100644 --- a/platform/windows/godot.natvis +++ b/platform/windows/godot.natvis @@ -32,6 +32,38 @@ </Expand> </Type> + <Type Name="HashMap<*,*>"> + <Expand> + <Item Name="[size]">num_elements</Item> + <LinkedListItems> + <Size>num_elements</Size> + <HeadPointer>head_element</HeadPointer> + <NextPointer>next</NextPointer> + <ValueNode>data</ValueNode> + </LinkedListItems> + </Expand> + </Type> + + <Type Name="VMap<*,*>"> + <Expand> + <Item Condition="_cowdata._ptr" Name="[size]">*(reinterpret_cast<int*>(_cowdata._ptr) - 1)</Item> + <ArrayItems Condition="_cowdata._ptr"> + <Size>*(reinterpret_cast<int*>(_cowdata._ptr) - 1)</Size> + <ValuePointer>reinterpret_cast<VMap<$T1,$T2>::Pair*>(_cowdata._ptr)</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="VMap<Callable,*>::Pair"> + <DisplayString Condition="dynamic_cast<CallableCustomMethodPointerBase*>(key.custom)">{dynamic_cast<CallableCustomMethodPointerBase*>(key.custom)->text}</DisplayString> + </Type> + + <!-- requires PR 64364 + <Type Name="GDScriptThreadContext"> + <DisplayString Condition="_is_main == true">main thread {_debug_thread_id}</DisplayString> + </Type> + --> + <Type Name="Variant"> <DisplayString Condition="type == Variant::NIL">nil</DisplayString> <DisplayString Condition="type == Variant::BOOL">{_data._bool}</DisplayString> @@ -55,15 +87,17 @@ <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::PACKED_BYTE_ARRAY">{*(PackedByteArray *)_data._mem}</DisplayString> - <DisplayString Condition="type == Variant::PACKED_INT32_ARRAY">{*(PackedInt32Array *)_data._mem}</DisplayString> + <DisplayString Condition="type == Variant::PACKED_BYTE_ARRAY">{reinterpret_cast<const Variant::PackedArrayRef<unsigned char>*>(_data.packed_array)->array}</DisplayString> + <DisplayString Condition="type == Variant::PACKED_INT32_ARRAY">{reinterpret_cast<const Variant::PackedArrayRef<int>*>(_data.packed_array)->array}</DisplayString> + <!-- broken, will show incorrect data <DisplayString Condition="type == Variant::PACKED_INT64_ARRAY">{*(PackedInt64Array *)_data._mem}</DisplayString> - <DisplayString Condition="type == Variant::PACKED_FLOAT32_ARRAY">{*(PackedFloat32Array *)_data._mem}</DisplayString> - <DisplayString Condition="type == Variant::PACKED_FLOAT64_ARRAY">{*(PackedFloat64Array *)_data._mem}</DisplayString> - <DisplayString Condition="type == Variant::PACKED_STRING_ARRAY">{*(PackedStringArray *)_data._mem}</DisplayString> - <DisplayString Condition="type == Variant::PACKED_VECTOR2_ARRAY">{*(PackedVector2Array *)_data._mem}</DisplayString> - <DisplayString Condition="type == Variant::PACKED_VECTOR3_ARRAY">{*(PackedVector3Array *)_data._mem}</DisplayString> - <DisplayString Condition="type == Variant::PACKED_COLOR_ARRAY">{*(PackedColorArray *)_data._mem}</DisplayString> + --> + <DisplayString Condition="type == Variant::PACKED_FLOAT32_ARRAY">{reinterpret_cast<const Variant::PackedArrayRef<float>*>(_data.packed_array)->array}</DisplayString> + <DisplayString Condition="type == Variant::PACKED_FLOAT64_ARRAY">{reinterpret_cast<const Variant::PackedArrayRef<double>*>(_data.packed_array)->array}</DisplayString> + <DisplayString Condition="type == Variant::PACKED_STRING_ARRAY">{reinterpret_cast<const Variant::PackedArrayRef<String>*>(_data.packed_array)->array}</DisplayString> + <DisplayString Condition="type == Variant::PACKED_VECTOR2_ARRAY">{reinterpret_cast<const Variant::PackedArrayRef<Vector2>*>(_data.packed_array)->array}</DisplayString> + <DisplayString Condition="type == Variant::PACKED_VECTOR3_ARRAY">{reinterpret_cast<const Variant::PackedArrayRef<Vector3>*>(_data.packed_array)->array}</DisplayString> + <DisplayString Condition="type == Variant::PACKED_COLOR_ARRAY">{reinterpret_cast<const Variant::PackedArrayRef<Color>*>(_data.packed_array)->array}</DisplayString> <StringView Condition="type == Variant::STRING && ((String *)(_data._mem))->_cowdata._ptr">((String *)(_data._mem))->_cowdata._ptr,s32</StringView> @@ -87,7 +121,7 @@ <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::PACKED_BYTE_ARRAY">*(PackedByteArray *)_data._mem</Item> + <Item Name="[value]" Condition="type == Variant::PACKED_BYTE_ARRAY">reinterpret_cast<const Variant::PackedArrayRef<unsigned char>*>(_data.packed_array)->array</Item> <Item Name="[value]" Condition="type == Variant::PACKED_INT32_ARRAY">*(PackedInt32Array *)_data._mem</Item> <Item Name="[value]" Condition="type == Variant::PACKED_INT64_ARRAY">*(PackedInt64Array *)_data._mem</Item> <Item Name="[value]" Condition="type == Variant::PACKED_FLOAT32_ARRAY">*(PackedFloat32Array *)_data._mem</Item> @@ -105,6 +139,14 @@ <StringView Condition="_cowdata._ptr != 0">_cowdata._ptr,s32</StringView> </Type> + <Type Name="godot::String"> + <DisplayString>{*reinterpret_cast<void**>(opaque),s32}</DisplayString> + <Expand> + <Item Name="opaque_ptr">*reinterpret_cast<void**>(opaque)</Item> + <Item Name="string">*reinterpret_cast<void**>(opaque),s32</Item> + </Expand> + </Type> + <Type Name="StringName"> <DisplayString Condition="_data && _data->cname">{_data->cname}</DisplayString> <DisplayString Condition="_data && !_data->cname">{_data->name,s32}</DisplayString> @@ -113,6 +155,22 @@ <StringView Condition="_data && !_data->cname">_data->name,s32</StringView> </Type> + <!-- can't cast the opaque to ::StringName because Natvis does not support global namespace specifier? --> + <Type Name="godot::StringName"> + <DisplayString Condition="(*reinterpret_cast<const char***>(opaque))[1]">{(*reinterpret_cast<const char***>(opaque))[1],s8}</DisplayString> + <DisplayString Condition="!(*reinterpret_cast<const char***>(opaque))[1]">{(*reinterpret_cast<const char***>(opaque))[2],s32}</DisplayString> + <Expand> + <Item Name="opaque_ptr">*reinterpret_cast<void**>(opaque)</Item> + <Item Name="&cname">(*reinterpret_cast<const char***>(opaque))+1</Item> + <Item Name="cname">(*reinterpret_cast<const char***>(opaque))[1],s8</Item> + </Expand> + </Type> + + <Type Name="Object::SignalData"> + <DisplayString Condition="user.name._cowdata._ptr">"{user.name}" {slot_map}</DisplayString> + <DisplayString Condition="!user.name._cowdata._ptr">"{slot_map}</DisplayString> + </Type> + <Type Name="Vector2"> <DisplayString>{{{x},{y}}}</DisplayString> <Expand> @@ -149,12 +207,4 @@ <Item Name="alpha">a</Item> </Expand> </Type> - - <Type Name="Node" Inheritable="false"> - <Expand> - <Item Name="Object">(Object*)this</Item> - <Item Name="class_name">(StringName*)(((char*)this) + sizeof(Object))</Item> - <Item Name="data">(Node::Data*)(((char*)this) + sizeof(Object) + sizeof(StringName))</Item> - </Expand> - </Type> </AutoVisualizer> diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 2c268ff3d5..1978ec5ab6 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -290,6 +290,24 @@ String OS_Windows::get_name() const { return "Windows"; } +String OS_Windows::get_distribution_name() const { + return get_name(); +} + +String OS_Windows::get_version() const { + typedef LONG NTSTATUS, *PNTSTATUS; + typedef NTSTATUS(WINAPI * RtlGetVersionPtr)(PRTL_OSVERSIONINFOW); + RtlGetVersionPtr version_ptr = (RtlGetVersionPtr)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlGetVersion"); + if (version_ptr != nullptr) { + RTL_OSVERSIONINFOW fow = { 0 }; + fow.dwOSVersionInfoSize = sizeof(fow); + if (version_ptr(&fow) == 0x00000000) { + return vformat("%d.%d.%d", (int64_t)fow.dwMajorVersion, (int64_t)fow.dwMinorVersion, (int64_t)fow.dwBuildNumber); + } + } + return ""; +} + OS::DateTime OS_Windows::get_datetime(bool p_utc) const { SYSTEMTIME systemtime; if (p_utc) { diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index 53451b780e..491de2266f 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -143,6 +143,8 @@ public: virtual MainLoop *get_main_loop() const override; virtual String get_name() const override; + virtual String get_distribution_name() const override; + virtual String get_version() const override; virtual void initialize_joypads() override {} |