summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/actions/godot-build/action.yml4
-rw-r--r--.github/actions/godot-cache/action.yml6
-rw-r--r--.github/actions/godot-deps/action.yml21
-rw-r--r--.github/workflows/android_builds.yml2
-rw-r--r--.github/workflows/godot_cpp_test.yml4
-rw-r--r--.github/workflows/ios_builds.yml2
-rw-r--r--.github/workflows/linux_builds.yml13
-rw-r--r--.github/workflows/macos_builds.yml2
-rw-r--r--.github/workflows/web_builds.yml2
-rw-r--r--.github/workflows/windows_builds.yml2
-rw-r--r--.pre-commit-config.yaml14
-rw-r--r--SConstruct6
-rw-r--r--core/io/resource.cpp15
-rw-r--r--doc/classes/ProjectSettings.xml4
-rw-r--r--doc/classes/TextEdit.xml2
-rw-r--r--drivers/gles3/storage/texture_storage.cpp18
-rw-r--r--drivers/wasapi/audio_driver_wasapi.cpp55
-rw-r--r--drivers/wasapi/audio_driver_wasapi.h9
-rw-r--r--editor/editor_help.cpp2
-rw-r--r--editor/editor_run_native.cpp18
-rw-r--r--editor/filesystem_dock.cpp16
-rw-r--r--editor/filesystem_dock.h1
-rw-r--r--editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp2
-rw-r--r--editor/import/resource_importer_imagefont.cpp32
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp16
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp7
-rw-r--r--editor/plugins/script_editor_plugin.cpp42
-rw-r--r--editor/plugins/script_editor_plugin.h2
-rw-r--r--editor/plugins/text_shader_editor.cpp2
-rw-r--r--main/main.cpp11
-rwxr-xr-x[-rw-r--r--]misc/scripts/dotnet_format.py0
-rwxr-xr-x[-rw-r--r--]misc/scripts/file_format.py0
-rwxr-xr-x[-rw-r--r--]misc/scripts/gitignore_check.sh0
-rwxr-xr-x[-rw-r--r--]misc/scripts/header_guards.py0
-rw-r--r--modules/gdscript/doc_classes/@GDScript.xml3
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp1
-rw-r--r--modules/gdscript/gdscript_editor.cpp29
-rw-r--r--modules/gdscript/gdscript_parser.cpp47
-rw-r--r--modules/gdscript/gdscript_parser.h1
-rw-r--r--modules/gdscript/gdscript_warning.cpp2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.out10
-rw-r--r--modules/gdscript/tests/scripts/parser/features/annotations.out24
-rw-r--r--modules/gdscript/tests/scripts/parser/features/export_arrays.out138
-rw-r--r--modules/gdscript/tests/scripts/parser/features/export_enum.out40
-rw-r--r--modules/gdscript/tests/scripts/parser/features/export_variable.gd34
-rw-r--r--modules/gdscript/tests/scripts/parser/features/export_variable.out60
-rw-r--r--modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.gd1
-rw-r--r--modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out4
-rw-r--r--modules/gdscript/tests/scripts/parser/warnings/standalone_expression.gd13
-rw-r--r--modules/gdscript/tests/scripts/parser/warnings/standalone_expression.out8
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/export_group_no_name_conflict_with_properties.out6
-rw-r--r--modules/gdscript/tests/scripts/utils.notest.gd15
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/BuildProblemsView.cs2
-rw-r--r--modules/noise/noise_texture_2d.cpp1
-rw-r--r--modules/svg/SCsub14
-rw-r--r--platform/web/export/export_plugin.cpp7
-rw-r--r--platform/web/export/export_plugin.h1
-rw-r--r--scene/gui/button.cpp115
-rw-r--r--scene/gui/button.h9
-rw-r--r--scene/gui/check_box.cpp2
-rw-r--r--scene/gui/check_button.cpp2
-rw-r--r--scene/gui/option_button.cpp2
-rw-r--r--scene/gui/popup.cpp12
-rw-r--r--scene/gui/text_edit.cpp105
-rw-r--r--scene/gui/tree.cpp26
-rw-r--r--scene/gui/tree.h1
-rw-r--r--scene/resources/gradient_texture.cpp2
-rw-r--r--scene/resources/shader.cpp2
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.cpp6
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.cpp18
-rw-r--r--servers/rendering/rendering_device.cpp3
-rw-r--r--servers/rendering/rendering_device.h2
-rwxr-xr-x[-rw-r--r--]tests/create_test.py0
-rw-r--r--[-rwxr-xr-x]thirdparty/glslang/SPIRV/GlslangToSpv.cpp0
-rw-r--r--[-rwxr-xr-x]thirdparty/glslang/SPIRV/doc.cpp0
-rw-r--r--[-rwxr-xr-x]thirdparty/glslang/glslang/Include/BaseTypes.h0
-rw-r--r--[-rwxr-xr-x]thirdparty/glslang/glslang/MachineIndependent/Initialize.cpp0
-rw-r--r--[-rwxr-xr-x]thirdparty/glslang/glslang/MachineIndependent/Versions.h0
-rw-r--r--thirdparty/thorvg/inc/config.h4
-rwxr-xr-xthirdparty/thorvg/update-thorvg.sh4
80 files changed, 738 insertions, 370 deletions
diff --git a/.github/actions/godot-build/action.yml b/.github/actions/godot-build/action.yml
index 0a0899db78..bf29b7e430 100644
--- a/.github/actions/godot-build/action.yml
+++ b/.github/actions/godot-build/action.yml
@@ -13,10 +13,10 @@ inputs:
sconsflags:
default: ""
scons-cache:
- description: The scons cache path.
+ description: The SCons cache path.
default: "${{ github.workspace }}/.scons-cache/"
scons-cache-limit:
- description: The scons cache size limit.
+ description: The SCons cache size limit.
# actions/cache has 10 GiB limit, and GitHub runners have a 14 GiB disk.
# Limit to 7 GiB to avoid having the extracted cache fill the disk.
default: 7168
diff --git a/.github/actions/godot-cache/action.yml b/.github/actions/godot-cache/action.yml
index b7ca01bb47..13142e7ed1 100644
--- a/.github/actions/godot-cache/action.yml
+++ b/.github/actions/godot-cache/action.yml
@@ -5,13 +5,13 @@ inputs:
description: The cache base name (job name by default).
default: "${{github.job}}"
scons-cache:
- description: The scons cache path.
+ description: The SCons cache path.
default: "${{github.workspace}}/.scons-cache/"
runs:
using: "composite"
steps:
- # Upload cache on completion and check it out now
- - name: Load .scons_cache directory
+ # Upload cache on completion and check it out now.
+ - name: Load SCons cache directory
uses: actions/cache@v4
with:
path: ${{inputs.scons-cache}}
diff --git a/.github/actions/godot-deps/action.yml b/.github/actions/godot-deps/action.yml
index cac72c436e..07a364cd79 100644
--- a/.github/actions/godot-deps/action.yml
+++ b/.github/actions/godot-deps/action.yml
@@ -1,27 +1,30 @@
-name: Setup python and scons
-description: Setup python, install the pip version of scons.
+name: Setup Python and SCons
+description: Setup Python, install the pip version of SCons.
inputs:
python-version:
- description: The python version to use.
+ description: The Python version to use.
default: "3.x"
python-arch:
- description: The python architecture.
+ description: The Python architecture.
default: "x64"
+ scons-version:
+ description: The SCons version to use.
+ default: "4.7.0"
runs:
using: "composite"
steps:
- # Use python 3.x release (works cross platform)
- name: Set up Python 3.x
uses: actions/setup-python@v5
with:
- # Semantic version range syntax or exact version of a Python version
+ # Semantic version range syntax or exact version of a Python version.
python-version: ${{ inputs.python-version }}
- # Optional - x64 or x86 architecture, defaults to x64
+ # Optional - x64 or x86 architecture, defaults to x64.
architecture: ${{ inputs.python-arch }}
- - name: Setup scons
+ - name: Setup SCons
shell: bash
run: |
python -c "import sys; print(sys.version)"
- python -m pip install scons==4.7.0
+ python -m pip install wheel
+ python -m pip install scons==${{ inputs.scons-version }}
scons --version
diff --git a/.github/workflows/android_builds.yml b/.github/workflows/android_builds.yml
index 5cb66a40ab..9a488bd095 100644
--- a/.github/workflows/android_builds.yml
+++ b/.github/workflows/android_builds.yml
@@ -32,7 +32,7 @@ jobs:
uses: ./.github/actions/godot-cache
continue-on-error: true
- - name: Setup python and scons
+ - name: Setup Python and SCons
uses: ./.github/actions/godot-deps
- name: Compilation (arm32)
diff --git a/.github/workflows/godot_cpp_test.yml b/.github/workflows/godot_cpp_test.yml
index 7350920810..57114dacfc 100644
--- a/.github/workflows/godot_cpp_test.yml
+++ b/.github/workflows/godot_cpp_test.yml
@@ -22,7 +22,7 @@ jobs:
with:
submodules: recursive
- - name: Setup python and scons
+ - name: Setup Python and SCons
uses: ./.github/actions/godot-deps
# Checkout godot-cpp
@@ -47,7 +47,7 @@ jobs:
cp -f godot-api/gdextension_interface.h godot-cpp/gdextension/
cp -f godot-api/extension_api.json godot-cpp/gdextension/
- # TODO: Add caching to the scons build and store it for CI via the godot-cache
+ # TODO: Add caching to the SCons build and store it for CI via the godot-cache
# action.
# Build godot-cpp test extension
diff --git a/.github/workflows/ios_builds.yml b/.github/workflows/ios_builds.yml
index e205d551ed..0546f43acc 100644
--- a/.github/workflows/ios_builds.yml
+++ b/.github/workflows/ios_builds.yml
@@ -26,7 +26,7 @@ jobs:
uses: ./.github/actions/godot-cache
continue-on-error: true
- - name: Setup python and scons
+ - name: Setup Python and SCons
uses: ./.github/actions/godot-deps
- name: Compilation (arm64)
diff --git a/.github/workflows/linux_builds.yml b/.github/workflows/linux_builds.yml
index 0420a02b1d..6b98256110 100644
--- a/.github/workflows/linux_builds.yml
+++ b/.github/workflows/linux_builds.yml
@@ -58,6 +58,8 @@ jobs:
tests: true
# Skip 2GiB artifact speeding up action.
artifact: false
+ # Test our oldest supported SCons/Python versions on one arbitrary editor build.
+ legacy-scons: true
- name: Editor with ThreadSanitizer (target=editor, tests=yes, dev_build=yes, use_tsan=yes, use_llvm=yes, linker=lld)
cache-name: linux-editor-thread-sanitizer
@@ -115,9 +117,18 @@ jobs:
cache-name: ${{ matrix.cache-name }}
continue-on-error: true
- - name: Setup python and scons
+ - name: Setup Python and SCons
+ if: ${{ ! matrix.legacy-scons }}
uses: ./.github/actions/godot-deps
+ - name: Setup Python and SCons (legacy versions)
+ if: ${{ matrix.legacy-scons }}
+ uses: ./.github/actions/godot-deps
+ with:
+ # Sync with Ensure*Version in SConstruct.
+ python-version: 3.6
+ scons-version: 3.1.2
+
- name: Setup GCC problem matcher
uses: ammaraskar/gcc-problem-matcher@master
diff --git a/.github/workflows/macos_builds.yml b/.github/workflows/macos_builds.yml
index 70031ec4c3..badcb688d1 100644
--- a/.github/workflows/macos_builds.yml
+++ b/.github/workflows/macos_builds.yml
@@ -43,7 +43,7 @@ jobs:
cache-name: ${{ matrix.cache-name }}
continue-on-error: true
- - name: Setup python and scons
+ - name: Setup Python and SCons
uses: ./.github/actions/godot-deps
- name: Setup Vulkan SDK
diff --git a/.github/workflows/web_builds.yml b/.github/workflows/web_builds.yml
index cfa1571d1f..1eb7b901cd 100644
--- a/.github/workflows/web_builds.yml
+++ b/.github/workflows/web_builds.yml
@@ -58,7 +58,7 @@ jobs:
cache-name: ${{ matrix.cache-name }}
continue-on-error: true
- - name: Setup python and scons
+ - name: Setup Python and SCons
uses: ./.github/actions/godot-deps
- name: Compilation
diff --git a/.github/workflows/windows_builds.yml b/.github/workflows/windows_builds.yml
index 5443ba20ab..f9513af5e3 100644
--- a/.github/workflows/windows_builds.yml
+++ b/.github/workflows/windows_builds.yml
@@ -48,7 +48,7 @@ jobs:
cache-name: ${{ matrix.cache-name }}
continue-on-error: true
- - name: Setup python and scons
+ - name: Setup Python and SCons
uses: ./.github/actions/godot-deps
- name: Download Direct3D 12 SDK components
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 5c0c0b6917..5a0e919c47 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -125,8 +125,18 @@ repos:
language: node
entry: jsdoc
files: ^platform/web/js/engine/(engine|config|features)\.js$
- args: [--template, platform/web/js/jsdoc2rst/, --destination, '', -d, dry-run]
- additional_dependencies: ["jsdoc@4.0.2"]
+ args:
+ - --template
+ - platform/web/js/jsdoc2rst/
+ - platform/web/js/engine/engine.js
+ - platform/web/js/engine/config.js
+ - platform/web/js/engine/features.js
+ - --destination
+ - ''
+ - -d
+ - dry-run
+ pass_filenames: false
+ additional_dependencies: ['jsdoc@^4.0.3']
- id: copyright-headers
name: copyright-headers
diff --git a/SConstruct b/SConstruct
index 07ec014cf9..c668ac7df3 100644
--- a/SConstruct
+++ b/SConstruct
@@ -1,6 +1,6 @@
#!/usr/bin/env python
-EnsureSConsVersion(3, 0, 0)
+EnsureSConsVersion(3, 1, 2)
EnsurePythonVersion(3, 6)
# System
@@ -365,7 +365,7 @@ if env["platform"] in platform_opts:
opts.Add(opt)
# Update the environment to take platform-specific options into account.
-opts.Update(env, {**ARGUMENTS, **env})
+opts.Update(env, {**ARGUMENTS, **env.Dictionary()})
# Detect modules.
modules_detected = OrderedDict()
@@ -425,7 +425,7 @@ for name, path in modules_detected.items():
env.modules_detected = modules_detected
# Update the environment again after all the module options are added.
-opts.Update(env, {**ARGUMENTS, **env})
+opts.Update(env, {**ARGUMENTS, **env.Dictionary()})
Help(opts.GenerateHelpText(env))
# add default include paths
diff --git a/core/io/resource.cpp b/core/io/resource.cpp
index 573692f41e..1ecfd8366d 100644
--- a/core/io/resource.cpp
+++ b/core/io/resource.cpp
@@ -569,11 +569,18 @@ Resource::Resource() :
remapped_list(this) {}
Resource::~Resource() {
- if (!path_cache.is_empty()) {
- ResourceCache::lock.lock();
- ResourceCache::resources.erase(path_cache);
- ResourceCache::lock.unlock();
+ if (unlikely(path_cache.is_empty())) {
+ return;
}
+
+ ResourceCache::lock.lock();
+ // Only unregister from the cache if this is the actual resource listed there.
+ // (Other resources can have the same value in `path_cache` if loaded with `CACHE_IGNORE`.)
+ HashMap<String, Resource *>::Iterator E = ResourceCache::resources.find(path_cache);
+ if (likely(E && E->value == this)) {
+ ResourceCache::resources.remove(E);
+ }
+ ResourceCache::lock.unlock();
}
HashMap<String, Resource *> ResourceCache::resources;
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 926d981f68..5ac4c96d93 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -554,10 +554,10 @@
When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when defining a local or subclass member variable that would shadow a variable that is inherited from a parent class.
</member>
<member name="debug/gdscript/warnings/standalone_expression" type="int" setter="" getter="" default="1">
- When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when calling an expression that has no effect on the surrounding code, such as writing [code]2 + 2[/code] as a statement.
+ When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when calling an expression that may have no effect on the surrounding code, such as writing [code]2 + 2[/code] as a statement.
</member>
<member name="debug/gdscript/warnings/standalone_ternary" type="int" setter="" getter="" default="1">
- When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when calling a ternary expression that has no effect on the surrounding code, such as writing [code]42 if active else 0[/code] as a statement.
+ When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when calling a ternary expression that may have no effect on the surrounding code, such as writing [code]42 if active else 0[/code] as a statement.
</member>
<member name="debug/gdscript/warnings/static_called_on_instance" type="int" setter="" getter="" default="1">
When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when calling a static method from an instance of a class instead of from the class directly.
diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml
index 4dda1f8db8..75cad4d08b 100644
--- a/doc/classes/TextEdit.xml
+++ b/doc/classes/TextEdit.xml
@@ -1314,7 +1314,7 @@
[b]Note:[/b] This method is only implemented on Linux.
</member>
<member name="minimap_draw" type="bool" setter="set_draw_minimap" getter="is_drawing_minimap" default="false">
- If [code]true[/code], a minimap is shown, providing an outline of your source code.
+ If [code]true[/code], a minimap is shown, providing an outline of your source code. The minimap uses a fixed-width text size.
</member>
<member name="minimap_width" type="int" setter="set_minimap_width" getter="get_minimap_width" default="80">
The width, in pixels, of the minimap.
diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp
index a65347a5b1..2dcf623995 100644
--- a/drivers/gles3/storage/texture_storage.cpp
+++ b/drivers/gles3/storage/texture_storage.cpp
@@ -1391,7 +1391,7 @@ void TextureStorage::texture_debug_usage(List<RS::TextureInfo> *r_info) {
tinfo.format = t->format;
tinfo.width = t->alloc_width;
tinfo.height = t->alloc_height;
- tinfo.depth = 0;
+ tinfo.depth = t->depth;
tinfo.bytes = t->total_data_size;
r_info->push_back(tinfo);
}
@@ -1495,14 +1495,18 @@ void TextureStorage::_texture_set_data(RID p_texture, const Ref<Image> &p_image,
for (int i = 0; i < mipmaps; i++) {
int size, ofs;
img->get_mipmap_offset_and_size(i, ofs, size);
-
if (compressed) {
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
-
- int bw = w;
- int bh = h;
-
- glCompressedTexImage2D(blit_target, i, internal_format, bw, bh, 0, size, &read[ofs]);
+ if (texture->target == GL_TEXTURE_2D_ARRAY) {
+ if (p_initialize) {
+ glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, i, internal_format, w, h, texture->layers, 0,
+ size * texture->layers, &read[ofs]);
+ } else {
+ glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, i, 0, 0, p_layer, w, h, 1, internal_format, size, &read[ofs]);
+ }
+ } else {
+ glCompressedTexImage2D(blit_target, i, internal_format, w, h, 0, size, &read[ofs]);
+ }
} else {
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
if (texture->target == GL_TEXTURE_2D_ARRAY) {
diff --git a/drivers/wasapi/audio_driver_wasapi.cpp b/drivers/wasapi/audio_driver_wasapi.cpp
index 8ea1f52d15..a349a66f75 100644
--- a/drivers/wasapi/audio_driver_wasapi.cpp
+++ b/drivers/wasapi/audio_driver_wasapi.cpp
@@ -107,12 +107,6 @@ const IID IID_IAudioClient3 = __uuidof(IAudioClient3);
const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient);
const IID IID_IAudioCaptureClient = __uuidof(IAudioCaptureClient);
-#define SAFE_RELEASE(memory) \
- if ((memory) != nullptr) { \
- (memory)->Release(); \
- (memory) = nullptr; \
- }
-
#define REFTIMES_PER_SEC 10000000
#define REFTIMES_PER_MILLISEC 10000
@@ -129,16 +123,10 @@ static bool default_input_device_changed = false;
class CMMNotificationClient : public IMMNotificationClient {
LONG _cRef = 1;
- IMMDeviceEnumerator *_pEnumerator = nullptr;
public:
CMMNotificationClient() {}
- virtual ~CMMNotificationClient() {
- if ((_pEnumerator) != nullptr) {
- (_pEnumerator)->Release();
- (_pEnumerator) = nullptr;
- }
- }
+ virtual ~CMMNotificationClient() {}
ULONG STDMETHODCALLTYPE AddRef() {
return InterlockedIncrement(&_cRef);
@@ -203,8 +191,8 @@ static CMMNotificationClient notif_client;
Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_input, bool p_reinit, bool p_no_audio_client_3) {
WAVEFORMATEX *pwfex;
- IMMDeviceEnumerator *enumerator = nullptr;
- IMMDevice *output_device = nullptr;
+ ComPtr<IMMDeviceEnumerator> enumerator = nullptr;
+ ComPtr<IMMDevice> output_device = nullptr;
HRESULT hr = CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void **)&enumerator);
ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
@@ -212,7 +200,7 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_i
if (p_device->device_name == "Default") {
hr = enumerator->GetDefaultAudioEndpoint(p_input ? eCapture : eRender, eConsole, &output_device);
} else {
- IMMDeviceCollection *devices = nullptr;
+ ComPtr<IMMDeviceCollection> devices = nullptr;
hr = enumerator->EnumAudioEndpoints(p_input ? eCapture : eRender, DEVICE_STATE_ACTIVE, &devices);
ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
@@ -225,12 +213,12 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_i
ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
for (ULONG i = 0; i < count && !found; i++) {
- IMMDevice *tmp_device = nullptr;
+ ComPtr<IMMDevice> tmp_device = nullptr;
hr = devices->Item(i, &tmp_device);
ERR_BREAK(hr != S_OK);
- IPropertyStore *props = nullptr;
+ ComPtr<IPropertyStore> props = nullptr;
hr = tmp_device->OpenPropertyStore(STGM_READ, &props);
ERR_BREAK(hr != S_OK);
@@ -248,8 +236,6 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_i
}
PropVariantClear(&propvar);
- props->Release();
- tmp_device->Release();
}
if (found) {
@@ -276,7 +262,6 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_i
}
hr = enumerator->RegisterEndpointNotificationCallback(&notif_client);
- SAFE_RELEASE(enumerator)
if (hr != S_OK) {
ERR_PRINT("WASAPI: RegisterEndpointNotificationCallback error");
@@ -303,8 +288,6 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_i
hr = output_device->Activate(IID_IAudioClient, CLSCTX_ALL, nullptr, (void **)&p_device->audio_client);
}
- SAFE_RELEASE(output_device)
-
if (p_reinit) {
if (hr != S_OK) {
return ERR_CANT_OPEN;
@@ -319,7 +302,7 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_i
audioProps.bIsOffload = FALSE;
audioProps.eCategory = AudioCategory_GameEffects;
- hr = ((IAudioClient3 *)p_device->audio_client)->SetClientProperties(&audioProps);
+ hr = ((IAudioClient3 *)p_device->audio_client.Get())->SetClientProperties(&audioProps);
ERR_FAIL_COND_V_MSG(hr != S_OK, ERR_CANT_OPEN, "WASAPI: SetClientProperties failed with error 0x" + String::num_uint64(hr, 16) + ".");
}
@@ -402,7 +385,7 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_i
}
} else {
- IAudioClient3 *device_audio_client_3 = (IAudioClient3 *)p_device->audio_client;
+ IAudioClient3 *device_audio_client_3 = (IAudioClient3 *)p_device->audio_client.Get();
// AUDCLNT_STREAMFLAGS_RATEADJUST is an invalid flag with IAudioClient3, therefore we have to use
// the closest supported mix rate supported by the audio driver.
@@ -419,7 +402,6 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_i
if (hr != S_OK) {
print_verbose("WASAPI: GetSharedModeEnginePeriod failed with error 0x" + String::num_uint64(hr, 16) + ", falling back to IAudioClient.");
CoTaskMemFree(pwfex);
- SAFE_RELEASE(output_device)
return audio_device_init(p_device, p_input, p_reinit, true);
}
@@ -441,7 +423,6 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_i
if (hr != S_OK) {
print_verbose("WASAPI: InitializeSharedAudioStream failed with error 0x" + String::num_uint64(hr, 16) + ", falling back to IAudioClient.");
CoTaskMemFree(pwfex);
- SAFE_RELEASE(output_device);
return audio_device_init(p_device, p_input, p_reinit, true);
} else {
uint32_t output_latency_in_frames;
@@ -453,7 +434,6 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_i
} else {
print_verbose("WASAPI: GetCurrentSharedModeEnginePeriod failed with error 0x" + String::num_uint64(hr, 16) + ", falling back to IAudioClient.");
CoTaskMemFree(pwfex);
- SAFE_RELEASE(output_device);
return audio_device_init(p_device, p_input, p_reinit, true);
}
}
@@ -468,7 +448,6 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_i
// Free memory
CoTaskMemFree(pwfex);
- SAFE_RELEASE(output_device)
return OK;
}
@@ -537,9 +516,9 @@ Error AudioDriverWASAPI::audio_device_finish(AudioDeviceWASAPI *p_device) {
p_device->active.clear();
}
- SAFE_RELEASE(p_device->audio_client)
- SAFE_RELEASE(p_device->render_client)
- SAFE_RELEASE(p_device->capture_client)
+ p_device->audio_client.Reset();
+ p_device->render_client.Reset();
+ p_device->capture_client.Reset();
return OK;
}
@@ -581,8 +560,8 @@ AudioDriver::SpeakerMode AudioDriverWASAPI::get_speaker_mode() const {
PackedStringArray AudioDriverWASAPI::audio_device_get_list(bool p_input) {
PackedStringArray list;
- IMMDeviceCollection *devices = nullptr;
- IMMDeviceEnumerator *enumerator = nullptr;
+ ComPtr<IMMDeviceCollection> devices = nullptr;
+ ComPtr<IMMDeviceEnumerator> enumerator = nullptr;
list.push_back(String("Default"));
@@ -597,12 +576,12 @@ PackedStringArray AudioDriverWASAPI::audio_device_get_list(bool p_input) {
ERR_FAIL_COND_V(hr != S_OK, PackedStringArray());
for (ULONG i = 0; i < count; i++) {
- IMMDevice *output_device = nullptr;
+ ComPtr<IMMDevice> output_device = nullptr;
hr = devices->Item(i, &output_device);
ERR_BREAK(hr != S_OK);
- IPropertyStore *props = nullptr;
+ ComPtr<IPropertyStore> props = nullptr;
hr = output_device->OpenPropertyStore(STGM_READ, &props);
ERR_BREAK(hr != S_OK);
@@ -615,12 +594,8 @@ PackedStringArray AudioDriverWASAPI::audio_device_get_list(bool p_input) {
list.push_back(String(propvar.pwszVal));
PropVariantClear(&propvar);
- props->Release();
- output_device->Release();
}
- devices->Release();
- enumerator->Release();
return list;
}
diff --git a/drivers/wasapi/audio_driver_wasapi.h b/drivers/wasapi/audio_driver_wasapi.h
index 367c30607a..d73cbf4a8a 100644
--- a/drivers/wasapi/audio_driver_wasapi.h
+++ b/drivers/wasapi/audio_driver_wasapi.h
@@ -40,15 +40,18 @@
#include <audioclient.h>
#include <mmdeviceapi.h>
+#include <wrl/client.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
+using Microsoft::WRL::ComPtr;
+
class AudioDriverWASAPI : public AudioDriver {
class AudioDeviceWASAPI {
public:
- IAudioClient *audio_client = nullptr;
- IAudioRenderClient *render_client = nullptr; // Output
- IAudioCaptureClient *capture_client = nullptr; // Input
+ ComPtr<IAudioClient> audio_client = nullptr;
+ ComPtr<IAudioRenderClient> render_client = nullptr; // Output
+ ComPtr<IAudioCaptureClient> capture_client = nullptr; // Input
SafeFlag active;
WORD format_tag = 0;
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index a8d978c66d..9884241708 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -1967,7 +1967,7 @@ void EditorHelp::_update_doc() {
class_desc->add_text(argument.name);
class_desc->add_text(": ");
- _add_type(argument.type);
+ _add_type(argument.type, argument.enumeration, argument.is_bitfield);
if (!argument.default_value.is_empty()) {
class_desc->push_color(theme_cache.symbol_color);
diff --git a/editor/editor_run_native.cpp b/editor/editor_run_native.cpp
index 4eb3f07c47..5c50231623 100644
--- a/editor/editor_run_native.cpp
+++ b/editor/editor_run_native.cpp
@@ -35,7 +35,6 @@
#include "editor/export/editor_export.h"
#include "editor/export/editor_export_platform.h"
#include "editor/themes/editor_scale.h"
-#include "scene/resources/image_texture.h"
void EditorRunNative::_notification(int p_what) {
switch (p_what) {
@@ -49,17 +48,26 @@ void EditorRunNative::_notification(int p_what) {
if (changed) {
PopupMenu *popup = remote_debug->get_popup();
popup->clear();
- for (int i = 0; i < EditorExport::get_singleton()->get_export_platform_count(); i++) {
- Ref<EditorExportPlatform> eep = EditorExport::get_singleton()->get_export_platform(i);
+ for (int i = 0; i < EditorExport::get_singleton()->get_export_preset_count(); i++) {
+ Ref<EditorExportPreset> preset = EditorExport::get_singleton()->get_export_preset(i);
+ Ref<EditorExportPlatform> eep = preset->get_platform();
if (eep.is_null()) {
continue;
}
+ int platform_idx = -1;
+ for (int j = 0; j < EditorExport::get_singleton()->get_export_platform_count(); j++) {
+ if (eep->get_name() == EditorExport::get_singleton()->get_export_platform(j)->get_name()) {
+ platform_idx = j;
+ }
+ }
int dc = MIN(eep->get_options_count(), 9000);
- if (dc > 0) {
+ bool needs_templates;
+ String error;
+ if (dc > 0 && preset->is_runnable() && eep->can_export(preset, error, needs_templates)) {
popup->add_icon_item(eep->get_run_icon(), eep->get_name(), -1);
popup->set_item_disabled(-1, true);
for (int j = 0; j < dc; j++) {
- popup->add_icon_item(eep->get_option_icon(j), eep->get_option_label(j), 10000 * i + j);
+ popup->add_icon_item(eep->get_option_icon(j), eep->get_option_label(j), 10000 * platform_idx + j);
popup->set_item_tooltip(-1, eep->get_option_tooltip(j));
popup->set_item_indent(-1, 2);
}
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index b05cafa694..5f311ae445 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -79,6 +79,15 @@ Control *FileSystemList::make_custom_tooltip(const String &p_text) const {
}
void FileSystemList::_line_editor_submit(const String &p_text) {
+ if (popup_edit_commited) {
+ return; // Already processed by _text_editor_popup_modal_close
+ }
+
+ if (popup_editor->get_hide_reason() == Popup::HIDE_REASON_CANCELED) {
+ return; // ESC pressed, app focus lost, or forced close from code.
+ }
+
+ popup_edit_commited = true; // End edit popup processing.
popup_editor->hide();
emit_signal(SNAME("item_edited"));
@@ -127,6 +136,7 @@ bool FileSystemList::edit_selected() {
line_editor->set_text(name);
line_editor->select(0, name.rfind("."));
+ popup_edit_commited = false; // Start edit popup processing.
popup_editor->popup();
popup_editor->child_controls_changed();
line_editor->grab_focus();
@@ -138,8 +148,12 @@ String FileSystemList::get_edit_text() {
}
void FileSystemList::_text_editor_popup_modal_close() {
+ if (popup_edit_commited) {
+ return; // Already processed by _text_editor_popup_modal_close
+ }
+
if (popup_editor->get_hide_reason() == Popup::HIDE_REASON_CANCELED) {
- return;
+ return; // ESC pressed, app focus lost, or forced close from code.
}
_line_editor_submit(line_editor->get_text());
diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h
index 7449657c06..3fbff3ef19 100644
--- a/editor/filesystem_dock.h
+++ b/editor/filesystem_dock.h
@@ -59,6 +59,7 @@ class FileSystemTree : public Tree {
class FileSystemList : public ItemList {
GDCLASS(FileSystemList, ItemList);
+ bool popup_edit_commited = true;
VBoxContainer *popup_editor_vb = nullptr;
Popup *popup_editor = nullptr;
LineEdit *line_editor = nullptr;
diff --git a/editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp b/editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp
index 3eabe46950..b69d38afa0 100644
--- a/editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp
+++ b/editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp
@@ -204,7 +204,7 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
} else {
for (int j = 0; j < key_len; j++) {
Basis sc = Basis().scaled(static_cast<Vector3>(anim->track_get_key_value(i, j)));
- anim->track_set_key_value(i, j, (global_transform.basis * sc).get_scale());
+ anim->track_set_key_value(i, j, (global_transform.orthonormalized().basis * sc).get_scale());
}
}
}
diff --git a/editor/import/resource_importer_imagefont.cpp b/editor/import/resource_importer_imagefont.cpp
index c454ebc6eb..94e5dd0f12 100644
--- a/editor/import/resource_importer_imagefont.cpp
+++ b/editor/import/resource_importer_imagefont.cpp
@@ -158,17 +158,16 @@ Error ResourceImporterImageFont::import(const String &p_source_file, const Strin
c++; // Skip "+".
continue;
}
- } else if (range[c] == '0') {
- if ((c <= range.length() - 2) && range[c + 1] == 'x') {
- token = String();
- if (step == STEP_START_BEGIN) {
- step = STEP_START_READ_HEX;
- } else {
- step = STEP_END_READ_HEX;
- }
- c++; // Skip "x".
- continue;
+ } else if (range[c] == '0' && (c <= range.length() - 2) && range[c + 1] == 'x') {
+ // Read hexadecimal value, start.
+ token = String();
+ if (step == STEP_START_BEGIN) {
+ step = STEP_START_READ_HEX;
+ } else {
+ step = STEP_END_READ_HEX;
}
+ c++; // Skip "x".
+ continue;
} else if (range[c] == '\'' || range[c] == '\"') {
if ((c <= range.length() - 3) && (range[c + 2] == '\'' || range[c + 2] == '\"')) {
token = String();
@@ -184,14 +183,13 @@ Error ResourceImporterImageFont::import(const String &p_source_file, const Strin
}
} else if (is_digit(range[c])) {
// Read decimal value, start.
- c++;
token = String();
+ token += range[c];
if (step == STEP_START_BEGIN) {
step = STEP_START_READ_DEC;
} else {
step = STEP_END_READ_DEC;
}
- token += range[c];
continue;
}
[[fallthrough]];
@@ -254,9 +252,19 @@ Error ResourceImporterImageFont::import(const String &p_source_file, const Strin
} break;
}
}
+ if (step == STEP_START_READ_HEX) {
+ start = token.hex_to_int();
+ } else if (step == STEP_START_READ_DEC) {
+ start = token.to_int();
+ } else if (step == STEP_END_READ_HEX) {
+ end = token.hex_to_int();
+ } else if (step == STEP_END_READ_DEC) {
+ end = token.to_int();
+ }
if (end == -1) {
end = start;
}
+
if (start == -1) {
WARN_PRINT(vformat("Invalid range: \"%s\"", range));
continue;
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 731c89250e..a44430ca7f 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -5732,11 +5732,10 @@ void CanvasItemEditorViewport::_create_preview(const Vector<String> &files) cons
Ref<Texture2D> texture = Ref<Texture2D>(Object::cast_to<Texture2D>(*res));
Ref<PackedScene> scene = Ref<PackedScene>(Object::cast_to<PackedScene>(*res));
if (texture != nullptr || scene != nullptr) {
- bool root_node_selected = EditorNode::get_singleton()->get_editor_selection()->is_selected(EditorNode::get_singleton()->get_edited_scene());
- String desc = TTR("Drag and drop to add as child of selected node.") + "\n" + TTR("Hold Alt when dropping to add as child of root node.");
- if (!root_node_selected) {
- desc += "\n" + TTR("Hold Shift when dropping to add as sibling of selected node.");
- }
+ String desc = TTR("Drag and drop to add as sibling of selected node (except when root is selected).") +
+ "\n" + TTR("Hold Shift when dropping to add as child of selected node.") +
+ "\n" + TTR("Hold Alt when dropping to add as child of root node.");
+
if (texture != nullptr) {
Sprite2D *sprite = memnew(Sprite2D);
sprite->set_texture(texture);
@@ -6099,11 +6098,12 @@ void CanvasItemEditorViewport::drop_data(const Point2 &p_point, const Variant &p
Node *root_node = EditorNode::get_singleton()->get_edited_scene();
if (selected_nodes.size() > 0) {
Node *selected_node = selected_nodes.front()->get();
- target_node = selected_node;
if (is_alt) {
target_node = root_node;
- } else if (is_shift && selected_node != root_node) {
- target_node = selected_node->get_parent();
+ } else if (is_shift) {
+ target_node = selected_node;
+ } else { // Default behavior.
+ target_node = (selected_node != root_node) ? selected_node->get_parent() : root_node;
}
} else {
if (root_node) {
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 5873d10e76..ca7ea821e8 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -4593,11 +4593,12 @@ void Node3DEditorViewport::drop_data_fw(const Point2 &p_point, const Variant &p_
Node *root_node = EditorNode::get_singleton()->get_edited_scene();
if (selected_nodes.size() > 0) {
Node *selected_node = selected_nodes.front()->get();
- target_node = selected_node;
if (is_alt) {
target_node = root_node;
- } else if (is_shift && selected_node != root_node) {
- target_node = selected_node->get_parent();
+ } else if (is_shift) {
+ target_node = selected_node;
+ } else { // Default behavior.
+ target_node = (selected_node != root_node) ? selected_node->get_parent() : root_node;
}
} else {
if (root_node) {
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 6cb49bbfa6..eb6282ca0c 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -731,6 +731,7 @@ void ScriptEditor::_go_to_tab(int p_idx) {
_update_members_overview();
_update_help_overview();
_update_selected_editor_menu();
+ _update_online_doc();
_update_members_overview_visibility();
_update_help_overview_visibility();
}
@@ -903,6 +904,7 @@ void ScriptEditor::_close_tab(int p_idx, bool p_save, bool p_history_back) {
_go_to_tab(idx);
} else {
_update_selected_editor_menu();
+ _update_online_doc();
}
_update_history_arrows();
@@ -1350,7 +1352,21 @@ void ScriptEditor::_menu_option(int p_option) {
help_search_dialog->popup_dialog();
} break;
case SEARCH_WEBSITE: {
- OS::get_singleton()->shell_open(VERSION_DOCS_URL "/");
+ Control *tab = tab_container->get_current_tab_control();
+
+ EditorHelp *eh = Object::cast_to<EditorHelp>(tab);
+ bool native_class_doc = false;
+ if (eh) {
+ const HashMap<String, DocData::ClassDoc>::ConstIterator E = EditorHelp::get_doc_data()->class_list.find(eh->get_class());
+ native_class_doc = E && !E->value.is_script_doc;
+ }
+ if (native_class_doc) {
+ String name = eh->get_class().to_lower();
+ String doc_url = vformat(VERSION_DOCS_URL "/classes/class_%s.html", name);
+ OS::get_singleton()->shell_open(doc_url);
+ } else {
+ OS::get_singleton()->shell_open(VERSION_DOCS_URL "/");
+ }
} break;
case WINDOW_NEXT: {
_history_forward();
@@ -2029,6 +2045,26 @@ void ScriptEditor::_update_help_overview() {
}
}
+void ScriptEditor::_update_online_doc() {
+ Node *current = tab_container->get_tab_control(tab_container->get_current_tab());
+
+ EditorHelp *eh = Object::cast_to<EditorHelp>(current);
+ bool native_class_doc = false;
+ if (eh) {
+ const HashMap<String, DocData::ClassDoc>::ConstIterator E = EditorHelp::get_doc_data()->class_list.find(eh->get_class());
+ native_class_doc = E && !E->value.is_script_doc;
+ }
+ if (native_class_doc) {
+ String name = eh->get_class();
+ String tooltip = vformat(TTR("Open '%s' in Godot online documentation."), name);
+ site_search->set_text(TTR("Open in Online Docs"));
+ site_search->set_tooltip_text(tooltip);
+ } else {
+ site_search->set_text(TTR("Online Docs"));
+ site_search->set_tooltip_text(TTR("Open Godot online documentation."));
+ }
+}
+
void ScriptEditor::_update_script_colors() {
bool script_temperature_enabled = EDITOR_GET("text_editor/script_list/script_temperature_enabled");
@@ -4147,10 +4183,8 @@ ScriptEditor::ScriptEditor(WindowWrapper *p_wrapper) {
site_search = memnew(Button);
site_search->set_flat(true);
- site_search->set_text(TTR("Online Docs"));
site_search->connect(SceneStringName(pressed), callable_mp(this, &ScriptEditor::_menu_option).bind(SEARCH_WEBSITE));
menu_hb->add_child(site_search);
- site_search->set_tooltip_text(TTR("Open Godot online documentation."));
help_search = memnew(Button);
help_search->set_flat(true);
@@ -4271,6 +4305,8 @@ ScriptEditor::ScriptEditor(WindowWrapper *p_wrapper) {
Ref<EditorJSONSyntaxHighlighter> json_syntax_highlighter;
json_syntax_highlighter.instantiate();
register_syntax_highlighter(json_syntax_highlighter);
+
+ _update_online_doc();
}
ScriptEditor::~ScriptEditor() {
diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h
index e6bb8f14a9..6f8e71ce75 100644
--- a/editor/plugins/script_editor_plugin.h
+++ b/editor/plugins/script_editor_plugin.h
@@ -450,6 +450,8 @@ class ScriptEditor : public PanelContainer {
void _update_help_overview();
void _help_overview_selected(int p_idx);
+ void _update_online_doc();
+
void _find_scripts(Node *p_base, Node *p_current, HashSet<Ref<Script>> &used);
void _tree_changed();
diff --git a/editor/plugins/text_shader_editor.cpp b/editor/plugins/text_shader_editor.cpp
index 637547062c..bb74bf8d1f 100644
--- a/editor/plugins/text_shader_editor.cpp
+++ b/editor/plugins/text_shader_editor.cpp
@@ -318,6 +318,8 @@ void ShaderTextEditor::_load_theme_settings() {
const Color doc_comment_color = EDITOR_GET("text_editor/theme/highlighting/doc_comment_color");
syntax_highlighter->add_color_region("/**", "*/", doc_comment_color, false);
+ // "/**/" will be treated as the start of the "/**" region, this line is guaranteed to end the color_region.
+ syntax_highlighter->add_color_region("/**/", "", comment_color, true);
// Disabled preprocessor branches use translucent text color to be easier to distinguish from comments.
syntax_highlighter->set_disabled_branch_color(Color(EDITOR_GET("text_editor/theme/highlighting/text_color")) * Color(1, 1, 1, 0.5));
diff --git a/main/main.cpp b/main/main.cpp
index 66706be745..65f637d778 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -2196,11 +2196,11 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
if (globals->has_setting("display/window/size/window_width_override") &&
globals->has_setting("display/window/size/window_height_override")) {
- int desired_width = globals->get("display/window/size/window_width_override");
+ int desired_width = GLOBAL_GET("display/window/size/window_width_override");
if (desired_width > 0) {
window_size.width = desired_width;
}
- int desired_height = globals->get("display/window/size/window_height_override");
+ int desired_height = GLOBAL_GET("display/window/size/window_height_override");
if (desired_height > 0) {
window_size.height = desired_height;
}
@@ -4295,9 +4295,6 @@ void Main::cleanup(bool p_force) {
if (globals) {
memdelete(globals);
}
- if (engine) {
- memdelete(engine);
- }
if (OS::get_singleton()->is_restart_on_exit_set()) {
//attempt to restart with arguments
@@ -4315,6 +4312,10 @@ void Main::cleanup(bool p_force) {
uninitialize_modules(MODULE_INITIALIZATION_LEVEL_CORE);
unregister_core_types();
+ if (engine) {
+ memdelete(engine);
+ }
+
OS::get_singleton()->benchmark_end_measure("Shutdown", "Total");
OS::get_singleton()->benchmark_dump();
diff --git a/misc/scripts/dotnet_format.py b/misc/scripts/dotnet_format.py
index 51fd7a1223..51fd7a1223 100644..100755
--- a/misc/scripts/dotnet_format.py
+++ b/misc/scripts/dotnet_format.py
diff --git a/misc/scripts/file_format.py b/misc/scripts/file_format.py
index a4ea544a45..a4ea544a45 100644..100755
--- a/misc/scripts/file_format.py
+++ b/misc/scripts/file_format.py
diff --git a/misc/scripts/gitignore_check.sh b/misc/scripts/gitignore_check.sh
index f162e25391..f162e25391 100644..100755
--- a/misc/scripts/gitignore_check.sh
+++ b/misc/scripts/gitignore_check.sh
diff --git a/misc/scripts/header_guards.py b/misc/scripts/header_guards.py
index b554be5159..b554be5159 100644..100755
--- a/misc/scripts/header_guards.py
+++ b/misc/scripts/header_guards.py
diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml
index 07d917ea04..1909ca5ab5 100644
--- a/modules/gdscript/doc_classes/@GDScript.xml
+++ b/modules/gdscript/doc_classes/@GDScript.xml
@@ -349,10 +349,11 @@
<param index="1" name="hint_string" type="String" />
<param index="2" name="usage" type="int" enum="PropertyUsageFlags" is_bitfield="true" default="6" />
<description>
- Allows you to set a custom hint, hint string, and usage flags for the exported property. Note that there's no validation done in GDScript, it will just pass the hint along to the editor.
+ Allows you to set a custom hint, hint string, and usage flags for the exported property. Note that there's no validation done in GDScript, it will just pass the parameters to the editor.
[codeblock]
@export_custom(PROPERTY_HINT_NONE, "suffix:m") var suffix: Vector3
[/codeblock]
+ [b]Note:[/b] Regardless of the [param usage] value, the [constant PROPERTY_USAGE_SCRIPT_VARIABLE] flag is always added, as with any explicitly declared script variable.
</description>
</annotation>
<annotation name="@export_dir">
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index 38d5c59e0e..a2680c932f 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -3394,6 +3394,7 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a
}
#ifdef DEBUG_ENABLED
+ // FIXME: No warning for built-in constructors and utilities due to early return.
if (p_is_root && return_type.kind != GDScriptParser::DataType::UNRESOLVED && return_type.builtin_type != Variant::NIL &&
!(p_call->is_super && p_call->function_name == GDScriptLanguage::get_singleton()->strings._init)) {
parser->push_warning(p_call, GDScriptWarning::RETURN_VALUE_DISCARDED, p_call->function_name);
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index cae85d7c70..4ae39d80cd 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -911,6 +911,29 @@ static void _find_annotation_arguments(const GDScriptParser::AnnotationNode *p_a
option.insert_text = option.display.quote(p_quote_style);
r_result.insert(option.display, option);
}
+ } else if (p_annotation->name == SNAME("@export_custom")) {
+ switch (p_argument) {
+ case 0: {
+ static HashMap<StringName, int64_t> items;
+ if (unlikely(items.is_empty())) {
+ CoreConstants::get_enum_values(SNAME("PropertyHint"), &items);
+ }
+ for (const KeyValue<StringName, int64_t> &item : items) {
+ ScriptLanguage::CodeCompletionOption option(item.key, ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT);
+ r_result.insert(option.display, option);
+ }
+ } break;
+ case 2: {
+ static HashMap<StringName, int64_t> items;
+ if (unlikely(items.is_empty())) {
+ CoreConstants::get_enum_values(SNAME("PropertyUsageFlags"), &items);
+ }
+ for (const KeyValue<StringName, int64_t> &item : items) {
+ ScriptLanguage::CodeCompletionOption option(item.key, ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT);
+ r_result.insert(option.display, option);
+ }
+ } break;
+ }
} else if (p_annotation->name == SNAME("@warning_ignore")) {
for (int warning_code = 0; warning_code < GDScriptWarning::WARNING_MAX; warning_code++) {
ScriptLanguage::CodeCompletionOption warning(GDScriptWarning::get_name_from_code((GDScriptWarning::Code)warning_code).to_lower(), ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
@@ -2065,6 +2088,12 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context,
found = false;
}
+ // If the found type was not fully analyzed we analyze it now.
+ if (found && r_type.type.kind == GDScriptParser::DataType::CLASS && !r_type.type.class_type->resolved_body) {
+ Error err;
+ Ref<GDScriptParserRef> r = GDScriptCache::get_parser(r_type.type.script_path, GDScriptParserRef::FULLY_SOLVED, err);
+ }
+
// Check type hint last. For collections we want chance to get the actual value first
// This way we can detect types from the content of dictionaries and arrays
if (!found && p_expression->get_datatype().is_hard_type()) {
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 9be9307b8a..9a4c92f601 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -101,7 +101,6 @@ GDScriptParser::GDScriptParser() {
register_annotation(MethodInfo("@onready"), AnnotationInfo::VARIABLE, &GDScriptParser::onready_annotation);
// Export annotations.
register_annotation(MethodInfo("@export"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_NONE, Variant::NIL>);
- register_annotation(MethodInfo("@export_storage"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_NONE, Variant::NIL>);
register_annotation(MethodInfo("@export_enum", PropertyInfo(Variant::STRING, "names")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_ENUM, Variant::NIL>, varray(), true);
register_annotation(MethodInfo("@export_file", PropertyInfo(Variant::STRING, "filter")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_FILE, Variant::STRING>, varray(""), true);
register_annotation(MethodInfo("@export_dir"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_DIR, Variant::STRING>);
@@ -121,6 +120,7 @@ GDScriptParser::GDScriptParser() {
register_annotation(MethodInfo("@export_flags_3d_physics"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_3D_PHYSICS, Variant::INT>);
register_annotation(MethodInfo("@export_flags_3d_navigation"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_3D_NAVIGATION, Variant::INT>);
register_annotation(MethodInfo("@export_flags_avoidance"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_AVOIDANCE, Variant::INT>);
+ register_annotation(MethodInfo("@export_storage"), AnnotationInfo::VARIABLE, &GDScriptParser::export_storage_annotation);
register_annotation(MethodInfo("@export_custom", PropertyInfo(Variant::INT, "hint", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_CLASS_IS_ENUM, "PropertyHint"), PropertyInfo(Variant::STRING, "hint_string"), PropertyInfo(Variant::INT, "usage", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_CLASS_IS_BITFIELD, "PropertyUsageFlags")), AnnotationInfo::VARIABLE, &GDScriptParser::export_custom_annotation, varray(PROPERTY_USAGE_DEFAULT));
// Export grouping annotations.
register_annotation(MethodInfo("@export_category", PropertyInfo(Variant::STRING, "name")), AnnotationInfo::STANDALONE, &GDScriptParser::export_group_annotations<PROPERTY_USAGE_CATEGORY>);
@@ -1877,6 +1877,10 @@ GDScriptParser::Node *GDScriptParser::parse_statement() {
case Node::CALL:
// Fine.
break;
+ case Node::PRELOAD:
+ // `preload` is a function-like keyword.
+ push_warning(expression, GDScriptWarning::RETURN_VALUE_DISCARDED, "preload");
+ break;
case Node::LAMBDA:
// Standalone lambdas can't be used, so make this an error.
push_error("Standalone lambdas cannot be accessed. Consider assigning it to a variable.", expression);
@@ -4295,7 +4299,7 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node
case GDScriptParser::DataType::BUILTIN:
variable->export_info.type = export_type.builtin_type;
variable->export_info.hint = PROPERTY_HINT_NONE;
- variable->export_info.hint_string = Variant::get_type_name(export_type.builtin_type);
+ variable->export_info.hint_string = String();
break;
case GDScriptParser::DataType::NATIVE:
if (ClassDB::is_parent_class(export_type.native_type, SNAME("Resource"))) {
@@ -4396,12 +4400,6 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node
push_error(_get_annotation_error_string(p_annotation->name, expected_types, variable->get_datatype()), p_annotation);
return false;
}
- } else if (p_annotation->name == SNAME("@export_storage")) {
- use_default_variable_type_check = false; // Can be applied to a variable of any type.
-
- // Save the info because the compiler uses export info for overwriting member info.
- variable->export_info = export_type.to_property_info(variable->identifier->name);
- variable->export_info.usage |= PROPERTY_USAGE_STORAGE;
}
if (use_default_variable_type_check) {
@@ -4421,19 +4419,50 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node
if (variable->export_info.hint) {
hint_prefix += "/" + itos(variable->export_info.hint);
}
+ variable->export_info.type = original_export_type_builtin;
variable->export_info.hint = PROPERTY_HINT_TYPE_STRING;
variable->export_info.hint_string = hint_prefix + ":" + variable->export_info.hint_string;
- variable->export_info.type = original_export_type_builtin;
+ variable->export_info.usage = PROPERTY_USAGE_DEFAULT;
+ variable->export_info.class_name = StringName();
}
return true;
}
+// For `@export_storage` and `@export_custom`, there is no need to check the variable type, argument values,
+// or handle array exports in a special way, so they are implemented as separate methods.
+
+bool GDScriptParser::export_storage_annotation(const AnnotationNode *p_annotation, Node *p_node, ClassNode *p_class) {
+ ERR_FAIL_COND_V_MSG(p_node->type != Node::VARIABLE, false, vformat(R"("%s" annotation can only be applied to variables.)", p_annotation->name));
+
+ VariableNode *variable = static_cast<VariableNode *>(p_node);
+ if (variable->is_static) {
+ push_error(vformat(R"(Annotation "%s" cannot be applied to a static variable.)", p_annotation->name), p_annotation);
+ return false;
+ }
+ if (variable->exported) {
+ push_error(vformat(R"(Annotation "%s" cannot be used with another "@export" annotation.)", p_annotation->name), p_annotation);
+ return false;
+ }
+
+ variable->exported = true;
+
+ // Save the info because the compiler uses export info for overwriting member info.
+ variable->export_info = variable->get_datatype().to_property_info(variable->identifier->name);
+ variable->export_info.usage |= PROPERTY_USAGE_STORAGE;
+
+ return true;
+}
+
bool GDScriptParser::export_custom_annotation(const AnnotationNode *p_annotation, Node *p_node, ClassNode *p_class) {
ERR_FAIL_COND_V_MSG(p_node->type != Node::VARIABLE, false, vformat(R"("%s" annotation can only be applied to variables.)", p_annotation->name));
ERR_FAIL_COND_V_MSG(p_annotation->resolved_arguments.size() < 2, false, R"(Annotation "@export_custom" requires 2 arguments.)");
VariableNode *variable = static_cast<VariableNode *>(p_node);
+ if (variable->is_static) {
+ push_error(vformat(R"(Annotation "%s" cannot be applied to a static variable.)", p_annotation->name), p_annotation);
+ return false;
+ }
if (variable->exported) {
push_error(vformat(R"(Annotation "%s" cannot be used with another "@export" annotation.)", p_annotation->name), p_annotation);
return false;
diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h
index 4c11fa7f8b..96358165c0 100644
--- a/modules/gdscript/gdscript_parser.h
+++ b/modules/gdscript/gdscript_parser.h
@@ -1497,6 +1497,7 @@ private:
bool onready_annotation(const AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
template <PropertyHint t_hint, Variant::Type t_type>
bool export_annotations(const AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
+ bool export_storage_annotation(const AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
bool export_custom_annotation(const AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
template <PropertyUsageFlags t_usage>
bool export_group_annotations(const AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
diff --git a/modules/gdscript/gdscript_warning.cpp b/modules/gdscript/gdscript_warning.cpp
index 48a0abe617..611a9ad2d9 100644
--- a/modules/gdscript/gdscript_warning.cpp
+++ b/modules/gdscript/gdscript_warning.cpp
@@ -74,7 +74,7 @@ String GDScriptWarning::get_message() const {
case UNREACHABLE_PATTERN:
return "Unreachable pattern (pattern after wildcard or bind).";
case STANDALONE_EXPRESSION:
- return "Standalone expression (the line has no effect).";
+ return "Standalone expression (the line may have no effect).";
case STANDALONE_TERNARY:
return "Standalone ternary operator: the return value is being discarded.";
case INCOMPATIBLE_TERNARY:
diff --git a/modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.out b/modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.out
index 505af5f1f3..0d96f8c021 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.out
+++ b/modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.out
@@ -1,11 +1,11 @@
GDTEST_OK
var test_1: Dictionary
- hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_2: TestExportEnumAsDictionary.MyEnum
- hint=ENUM hint_string="A:0,B:1,C:2" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM
+ hint=ENUM hint_string="A:0,B:1,C:2" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM class_name=&"TestExportEnumAsDictionary.MyEnum"
var test_3: Dictionary
- hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_4: TestExportEnumAsDictionary.MyEnum
- hint=ENUM hint_string="A:0,B:1,C:2" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM
+ hint=ENUM hint_string="A:0,B:1,C:2" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM class_name=&"TestExportEnumAsDictionary.MyEnum"
var test_5: TestExportEnumAsDictionary.MyEnum
- hint=ENUM hint_string="A:0,B:1,C:2" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM
+ hint=ENUM hint_string="A:0,B:1,C:2" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM class_name=&"TestExportEnumAsDictionary.MyEnum"
diff --git a/modules/gdscript/tests/scripts/parser/features/annotations.out b/modules/gdscript/tests/scripts/parser/features/annotations.out
index 2ba9dd7496..6516672820 100644
--- a/modules/gdscript/tests/scripts/parser/features/annotations.out
+++ b/modules/gdscript/tests/scripts/parser/features/annotations.out
@@ -1,25 +1,25 @@
GDTEST_OK
var test_1: int = null
- hint=ENUM hint_string="A,B,C" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=ENUM hint_string="A,B,C" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_2: int = null
- hint=ENUM hint_string="A,B,C" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=ENUM hint_string="A,B,C" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_3: int = null
- hint=ENUM hint_string="A,B,C" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=ENUM hint_string="A,B,C" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_4: int = null
- hint=ENUM hint_string="A,B,C" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=ENUM hint_string="A,B,C" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_5: int = 0
- hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_6: int = 0
- hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_7: int = 42
- hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_8: int = 0
- hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_9: int = 0
- hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_10: int = 0
- hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_11: int = 0
- hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_12: int = 0
- hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
diff --git a/modules/gdscript/tests/scripts/parser/features/export_arrays.out b/modules/gdscript/tests/scripts/parser/features/export_arrays.out
index acbf389645..f1522d096f 100644
--- a/modules/gdscript/tests/scripts/parser/features/export_arrays.out
+++ b/modules/gdscript/tests/scripts/parser/features/export_arrays.out
@@ -1,139 +1,139 @@
GDTEST_OK
var test_dir: Array
- hint=TYPE_STRING hint_string="String/DIR:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<String>/<DIR>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_dir_packed: PackedStringArray
- hint=TYPE_STRING hint_string="String/DIR:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<String>/<DIR>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_file: Array
- hint=TYPE_STRING hint_string="String/FILE:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<String>/<FILE>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_file_packed: PackedStringArray
- hint=TYPE_STRING hint_string="String/FILE:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<String>/<FILE>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_global_dir: Array
- hint=TYPE_STRING hint_string="String/GLOBAL_DIR:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<String>/<GLOBAL_DIR>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_global_dir_packed: PackedStringArray
- hint=TYPE_STRING hint_string="String/GLOBAL_DIR:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<String>/<GLOBAL_DIR>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_global_file: Array
- hint=TYPE_STRING hint_string="String/GLOBAL_FILE:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<String>/<GLOBAL_FILE>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_global_file_packed: PackedStringArray
- hint=TYPE_STRING hint_string="String/GLOBAL_FILE:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<String>/<GLOBAL_FILE>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_bit_flag: Array
- hint=TYPE_STRING hint_string="int/FLAGS:A,B,C" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<FLAGS>:A,B,C" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_bit_flag_packed_byte: PackedByteArray
- hint=TYPE_STRING hint_string="int/FLAGS:A,B,C" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<FLAGS>:A,B,C" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_bit_flag_packed32: PackedInt32Array
- hint=TYPE_STRING hint_string="int/FLAGS:A,B,C" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<FLAGS>:A,B,C" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_bit_flag_packed64: PackedInt64Array
- hint=TYPE_STRING hint_string="int/FLAGS:A,B,C" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<FLAGS>:A,B,C" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_bit_flag_2d_nav: Array
- hint=TYPE_STRING hint_string="int/LAYERS_2D_NAVIGATION:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<LAYERS_2D_NAVIGATION>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_bit_flag_2d_nav_packed_byte: PackedByteArray
- hint=TYPE_STRING hint_string="int/LAYERS_2D_NAVIGATION:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<LAYERS_2D_NAVIGATION>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_bit_flag_2d_nav_packed32: PackedInt32Array
- hint=TYPE_STRING hint_string="int/LAYERS_2D_NAVIGATION:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<LAYERS_2D_NAVIGATION>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_bit_flag_2d_nav_packed64: PackedInt64Array
- hint=TYPE_STRING hint_string="int/LAYERS_2D_NAVIGATION:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<LAYERS_2D_NAVIGATION>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_bit_flag_2d_phys: Array
- hint=TYPE_STRING hint_string="int/LAYERS_2D_PHYSICS:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<LAYERS_2D_PHYSICS>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_bit_flag_2d_phys_packed_byte: PackedByteArray
- hint=TYPE_STRING hint_string="int/LAYERS_2D_PHYSICS:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<LAYERS_2D_PHYSICS>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_bit_flag_2d_phys_packed32: PackedInt32Array
- hint=TYPE_STRING hint_string="int/LAYERS_2D_PHYSICS:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<LAYERS_2D_PHYSICS>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_bit_flag_2d_phys_packed64: PackedInt64Array
- hint=TYPE_STRING hint_string="int/LAYERS_2D_PHYSICS:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<LAYERS_2D_PHYSICS>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_bit_flag_2d_render: Array
- hint=TYPE_STRING hint_string="int/LAYERS_2D_RENDER:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<LAYERS_2D_RENDER>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_bit_flag_2d_render_packed_byte: PackedByteArray
- hint=TYPE_STRING hint_string="int/LAYERS_2D_RENDER:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<LAYERS_2D_RENDER>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_bit_flag_2d_render_packed32: PackedInt32Array
- hint=TYPE_STRING hint_string="int/LAYERS_2D_RENDER:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<LAYERS_2D_RENDER>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_bit_flag_2d_render_packed64: PackedInt64Array
- hint=TYPE_STRING hint_string="int/LAYERS_2D_RENDER:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<LAYERS_2D_RENDER>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_bit_flag_3d_nav: Array
- hint=TYPE_STRING hint_string="int/LAYERS_3D_NAVIGATION:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<LAYERS_3D_NAVIGATION>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_bit_flag_3d_nav_packed_byte: PackedByteArray
- hint=TYPE_STRING hint_string="int/LAYERS_3D_NAVIGATION:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<LAYERS_3D_NAVIGATION>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_bit_flag_3d_nav_packed32: PackedInt32Array
- hint=TYPE_STRING hint_string="int/LAYERS_3D_NAVIGATION:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<LAYERS_3D_NAVIGATION>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_bit_flag_3d_nav_packed64: PackedInt64Array
- hint=TYPE_STRING hint_string="int/LAYERS_3D_NAVIGATION:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<LAYERS_3D_NAVIGATION>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_bit_flag_3d_phys: Array
- hint=TYPE_STRING hint_string="int/LAYERS_3D_PHYSICS:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<LAYERS_3D_PHYSICS>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_bit_flag_3d_phys_packed_byte: PackedByteArray
- hint=TYPE_STRING hint_string="int/LAYERS_3D_PHYSICS:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<LAYERS_3D_PHYSICS>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_bit_flag_3d_phys_packed32: PackedInt32Array
- hint=TYPE_STRING hint_string="int/LAYERS_3D_PHYSICS:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<LAYERS_3D_PHYSICS>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_bit_flag_3d_phys_packed64: PackedInt64Array
- hint=TYPE_STRING hint_string="int/LAYERS_3D_PHYSICS:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<LAYERS_3D_PHYSICS>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_bit_flag_3d_render: Array
- hint=TYPE_STRING hint_string="int/LAYERS_3D_RENDER:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<LAYERS_3D_RENDER>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_bit_flag_3d_render_packed_byte: PackedByteArray
- hint=TYPE_STRING hint_string="int/LAYERS_3D_RENDER:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<LAYERS_3D_RENDER>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_bit_flag_3d_render_packed32: PackedInt32Array
- hint=TYPE_STRING hint_string="int/LAYERS_3D_RENDER:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<LAYERS_3D_RENDER>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_bit_flag_3d_render_packed64: PackedInt64Array
- hint=TYPE_STRING hint_string="int/LAYERS_3D_RENDER:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<LAYERS_3D_RENDER>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_multiline: Array
- hint=TYPE_STRING hint_string="String/MULTILINE_TEXT:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<String>/<MULTILINE_TEXT>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_multiline_packed: PackedStringArray
- hint=TYPE_STRING hint_string="String/MULTILINE_TEXT:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<String>/<MULTILINE_TEXT>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_placeholder: Array
- hint=TYPE_STRING hint_string="String/PLACEHOLDER_TEXT:Placeholder" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<String>/<PLACEHOLDER_TEXT>:Placeholder" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_placeholder_packed: PackedStringArray
- hint=TYPE_STRING hint_string="String/PLACEHOLDER_TEXT:Placeholder" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<String>/<PLACEHOLDER_TEXT>:Placeholder" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_range_int: Array
- hint=TYPE_STRING hint_string="int/RANGE:1,10" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<RANGE>:1,10" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_range_int_packed_byte: PackedByteArray
- hint=TYPE_STRING hint_string="int/RANGE:1,10" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<RANGE>:1,10" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_range_int_packed32: PackedInt32Array
- hint=TYPE_STRING hint_string="int/RANGE:1,10" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<RANGE>:1,10" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_range_int_packed64: PackedInt64Array
- hint=TYPE_STRING hint_string="int/RANGE:1,10" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<RANGE>:1,10" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_range_int_float_step: Array
- hint=TYPE_STRING hint_string="int/RANGE:1,10,0.01" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<RANGE>:1,10,0.01" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_range_float: Array
- hint=TYPE_STRING hint_string="float/RANGE:1,10" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<float>/<RANGE>:1,10" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_range_float_packed32: PackedFloat32Array
- hint=TYPE_STRING hint_string="float/RANGE:1,10" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<float>/<RANGE>:1,10" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_range_float_packed64: PackedFloat64Array
- hint=TYPE_STRING hint_string="float/RANGE:1,10" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<float>/<RANGE>:1,10" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_exp_easing: Array
- hint=TYPE_STRING hint_string="float/EXP_EASING:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<float>/<EXP_EASING>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_exp_easing_packed32: PackedFloat32Array
- hint=TYPE_STRING hint_string="float/EXP_EASING:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<float>/<EXP_EASING>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_exp_easing_packed64: PackedFloat64Array
- hint=TYPE_STRING hint_string="float/EXP_EASING:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<float>/<EXP_EASING>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_node_path: Array
- hint=TYPE_STRING hint_string="NodePath/NODE_PATH_VALID_TYPES:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<NodePath>/<NODE_PATH_VALID_TYPES>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_color: Array
- hint=TYPE_STRING hint_string="Color/COLOR_NO_ALPHA:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<Color>/<COLOR_NO_ALPHA>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_color_packed: PackedColorArray
- hint=TYPE_STRING hint_string="Color/COLOR_NO_ALPHA:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<Color>/<COLOR_NO_ALPHA>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_weak_packed_byte_array: PackedByteArray
- hint=TYPE_STRING hint_string="int:int" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_weak_packed_int32_array: PackedInt32Array
- hint=TYPE_STRING hint_string="int:int" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_weak_packed_int64_array: PackedInt64Array
- hint=TYPE_STRING hint_string="int:int" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_weak_packed_float32_array: PackedFloat32Array
- hint=TYPE_STRING hint_string="float:float" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<float>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_weak_packed_float64_array: PackedFloat64Array
- hint=TYPE_STRING hint_string="float:float" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<float>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_weak_packed_color_array: PackedColorArray
- hint=TYPE_STRING hint_string="Color:Color" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<Color>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_weak_packed_vector2_array: PackedVector2Array
- hint=TYPE_STRING hint_string="Vector2:Vector2" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<Vector2>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_weak_packed_vector3_array: PackedVector3Array
- hint=TYPE_STRING hint_string="Vector3:Vector3" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<Vector3>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_weak_packed_vector4_array: PackedVector4Array
- hint=TYPE_STRING hint_string="Vector4:Vector4" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<Vector4>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_range_weak_packed_byte_array: PackedByteArray
- hint=TYPE_STRING hint_string="int/RANGE:1,10" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<RANGE>:1,10" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_range_weak_packed_int32_array: PackedInt32Array
- hint=TYPE_STRING hint_string="int/RANGE:1,10" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<RANGE>:1,10" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_range_weak_packed_int64_array: PackedInt64Array
- hint=TYPE_STRING hint_string="int/RANGE:1,10" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<RANGE>:1,10" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_range_weak_packed_float32_array: PackedFloat32Array
- hint=TYPE_STRING hint_string="float/RANGE:1,10" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<float>/<RANGE>:1,10" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_range_weak_packed_float64_array: PackedFloat64Array
- hint=TYPE_STRING hint_string="float/RANGE:1,10" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<float>/<RANGE>:1,10" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_noalpha_weak_packed_color_array: PackedColorArray
- hint=TYPE_STRING hint_string="Color/COLOR_NO_ALPHA:" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<Color>/<COLOR_NO_ALPHA>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
diff --git a/modules/gdscript/tests/scripts/parser/features/export_enum.out b/modules/gdscript/tests/scripts/parser/features/export_enum.out
index c87f9b17f0..31d3fa8902 100644
--- a/modules/gdscript/tests/scripts/parser/features/export_enum.out
+++ b/modules/gdscript/tests/scripts/parser/features/export_enum.out
@@ -1,41 +1,41 @@
GDTEST_OK
var test_untyped: int = null
- hint=ENUM hint_string="Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=ENUM hint_string="Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_with_values: int = null
- hint=ENUM hint_string="Red:10,Green:20,Blue:30" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=ENUM hint_string="Red:10,Green:20,Blue:30" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_weak_variant: int = null
- hint=ENUM hint_string="Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=ENUM hint_string="Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_weak_int: int = 0
- hint=ENUM hint_string="Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=ENUM hint_string="Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_weak_string: String = ""
- hint=ENUM hint_string="Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=ENUM hint_string="Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_weak_array_int: Array = Array[int]([])
- hint=TYPE_STRING hint_string="int/ENUM:Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<ENUM>:Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_weak_array_string: Array = Array[String]([])
- hint=TYPE_STRING hint_string="String/ENUM:Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<String>/<ENUM>:Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_weak_packed_byte_array: PackedByteArray = PackedByteArray()
- hint=TYPE_STRING hint_string="int/ENUM:Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<ENUM>:Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_weak_packed_int32_array: PackedInt32Array = PackedInt32Array()
- hint=TYPE_STRING hint_string="int/ENUM:Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<ENUM>:Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_weak_packed_int64_array: PackedInt64Array = PackedInt64Array()
- hint=TYPE_STRING hint_string="int/ENUM:Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<ENUM>:Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_weak_packed_string_array: PackedStringArray = PackedStringArray()
- hint=TYPE_STRING hint_string="String/ENUM:Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<String>/<ENUM>:Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_hard_variant: int = null
- hint=ENUM hint_string="Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=ENUM hint_string="Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_hard_int: int = 0
- hint=ENUM hint_string="Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=ENUM hint_string="Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_hard_string: String = ""
- hint=ENUM hint_string="Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=ENUM hint_string="Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_hard_array_int: Array = Array[int]([])
- hint=TYPE_STRING hint_string="int/ENUM:Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<ENUM>:Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_hard_array_string: Array = Array[String]([])
- hint=TYPE_STRING hint_string="String/ENUM:Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<String>/<ENUM>:Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_variant_array_int: Array = Array[int]([])
- hint=TYPE_STRING hint_string="int/ENUM:Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<ENUM>:Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_variant_packed_int32_array: PackedInt32Array = PackedInt32Array()
- hint=TYPE_STRING hint_string="int/ENUM:Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<int>/<ENUM>:Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_variant_array_string: Array = Array[String]([])
- hint=TYPE_STRING hint_string="String/ENUM:Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<String>/<ENUM>:Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_variant_packed_string_array: PackedStringArray = PackedStringArray()
- hint=TYPE_STRING hint_string="String/ENUM:Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=TYPE_STRING hint_string="<String>/<ENUM>:Red,Green,Blue" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
diff --git a/modules/gdscript/tests/scripts/parser/features/export_variable.gd b/modules/gdscript/tests/scripts/parser/features/export_variable.gd
index 2a218774de..8b343de5ef 100644
--- a/modules/gdscript/tests/scripts/parser/features/export_variable.gd
+++ b/modules/gdscript/tests/scripts/parser/features/export_variable.gd
@@ -2,19 +2,43 @@ extends Node
const Utils = preload("../../utils.notest.gd")
+# Built-in types.
@export var test_weak_int = 1
@export var test_hard_int: int = 2
-@export_storage var test_storage_untyped
-@export_storage var test_storage_weak_int = 3 # Property info still `Variant`, unlike `@export`.
-@export_storage var test_storage_hard_int: int = 4
@export_range(0, 100) var test_range = 100
@export_range(0, 100, 1) var test_range_step = 101
@export_range(0, 100, 1, "or_greater") var test_range_step_or_greater = 102
@export var test_color: Color
@export_color_no_alpha var test_color_no_alpha: Color
@export_node_path("Sprite2D", "Sprite3D", "Control", "Node") var test_node_path := ^"hello"
-@export var test_node: Node
-@export var test_node_array: Array[Node]
+
+# Enums.
+@export var test_side: Side
+@export var test_atm: AutoTranslateMode
+
+# Resources and nodes.
+@export var test_image: Image
+@export var test_timer: Timer
+
+# Arrays.
+@export var test_array: Array
+@export var test_array_bool: Array[bool]
+@export var test_array_array: Array[Array]
+@export var test_array_side: Array[Side]
+@export var test_array_atm: Array[AutoTranslateMode]
+@export var test_array_image: Array[Image]
+@export var test_array_timer: Array[Timer]
+
+# `@export_storage`.
+@export_storage var test_storage_untyped
+@export_storage var test_storage_weak_int = 3 # Property info still `Variant`, unlike `@export`.
+@export_storage var test_storage_hard_int: int = 4
+
+# `@export_custom`.
+# NOTE: `PROPERTY_USAGE_NIL_IS_VARIANT` flag will be removed.
+@export_custom(PROPERTY_HINT_ENUM, "A,B,C") var test_export_custom_untyped
+@export_custom(PROPERTY_HINT_ENUM, "A,B,C") var test_export_custom_weak_int = 5
+@export_custom(PROPERTY_HINT_ENUM, "A,B,C") var test_export_custom_hard_int: int = 6
func test():
for property in get_property_list():
diff --git a/modules/gdscript/tests/scripts/parser/features/export_variable.out b/modules/gdscript/tests/scripts/parser/features/export_variable.out
index b3f9d0ca9c..99d7b27130 100644
--- a/modules/gdscript/tests/scripts/parser/features/export_variable.out
+++ b/modules/gdscript/tests/scripts/parser/features/export_variable.out
@@ -1,27 +1,51 @@
GDTEST_OK
var test_weak_int: int = 1
- hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_hard_int: int = 2
- hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
-var test_storage_untyped: Variant = null
- hint=NONE hint_string="" usage=STORAGE|SCRIPT_VARIABLE|NIL_IS_VARIANT
-var test_storage_weak_int: Variant = 3
- hint=NONE hint_string="" usage=STORAGE|SCRIPT_VARIABLE|NIL_IS_VARIANT
-var test_storage_hard_int: int = 4
- hint=NONE hint_string="" usage=STORAGE|SCRIPT_VARIABLE
+ hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_range: int = 100
- hint=RANGE hint_string="0,100" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=RANGE hint_string="0,100" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_range_step: int = 101
- hint=RANGE hint_string="0,100,1" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=RANGE hint_string="0,100,1" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_range_step_or_greater: int = 102
- hint=RANGE hint_string="0,100,1,or_greater" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=RANGE hint_string="0,100,1,or_greater" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_color: Color = Color(0, 0, 0, 1)
- hint=NONE hint_string="Color" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_color_no_alpha: Color = Color(0, 0, 0, 1)
- hint=COLOR_NO_ALPHA hint_string="" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=COLOR_NO_ALPHA hint_string="" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
var test_node_path: NodePath = NodePath("hello")
- hint=NODE_PATH_VALID_TYPES hint_string="Sprite2D,Sprite3D,Control,Node" usage=DEFAULT|SCRIPT_VARIABLE
-var test_node: Node = null
- hint=NODE_TYPE hint_string="Node" usage=DEFAULT|SCRIPT_VARIABLE
-var test_node_array: Array = Array[Node]([])
- hint=TYPE_STRING hint_string="Object/NODE_TYPE:Node" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=NODE_PATH_VALID_TYPES hint_string="Sprite2D,Sprite3D,Control,Node" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
+var test_side: Side = 0
+ hint=ENUM hint_string="Side Left:0,Side Top:1,Side Right:2,Side Bottom:3" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM class_name=&"Side"
+var test_atm: Node.AutoTranslateMode = 0
+ hint=ENUM hint_string="Auto Translate Mode Inherit:0,Auto Translate Mode Always:1,Auto Translate Mode Disabled:2" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM class_name=&"Node.AutoTranslateMode"
+var test_image: Image = null
+ hint=RESOURCE_TYPE hint_string="Image" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"Image"
+var test_timer: Timer = null
+ hint=NODE_TYPE hint_string="Timer" usage=DEFAULT|SCRIPT_VARIABLE class_name=&"Timer"
+var test_array: Array = []
+ hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
+var test_array_bool: Array = Array[bool]([])
+ hint=TYPE_STRING hint_string="<bool>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
+var test_array_array: Array = Array[Array]([])
+ hint=TYPE_STRING hint_string="<Array>:" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
+var test_array_side: Array = Array[int]([])
+ hint=TYPE_STRING hint_string="<int>/<ENUM>:Side Left:0,Side Top:1,Side Right:2,Side Bottom:3" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
+var test_array_atm: Array = Array[int]([])
+ hint=TYPE_STRING hint_string="<int>/<ENUM>:Auto Translate Mode Inherit:0,Auto Translate Mode Always:1,Auto Translate Mode Disabled:2" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
+var test_array_image: Array = Array[Image]([])
+ hint=TYPE_STRING hint_string="<Object>/<RESOURCE_TYPE>:Image" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
+var test_array_timer: Array = Array[Timer]([])
+ hint=TYPE_STRING hint_string="<Object>/<NODE_TYPE>:Timer" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
+var test_storage_untyped: Variant = null
+ hint=NONE hint_string="" usage=STORAGE|SCRIPT_VARIABLE|NIL_IS_VARIANT class_name=&""
+var test_storage_weak_int: Variant = 3
+ hint=NONE hint_string="" usage=STORAGE|SCRIPT_VARIABLE|NIL_IS_VARIANT class_name=&""
+var test_storage_hard_int: int = 4
+ hint=NONE hint_string="" usage=STORAGE|SCRIPT_VARIABLE class_name=&""
+var test_export_custom_untyped: null = null
+ hint=ENUM hint_string="A,B,C" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
+var test_export_custom_weak_int: int = 5
+ hint=ENUM hint_string="A,B,C" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
+var test_export_custom_hard_int: int = 6
+ hint=ENUM hint_string="A,B,C" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
diff --git a/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.gd b/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.gd
index 00598e4d50..f8f70b8cc3 100644
--- a/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.gd
+++ b/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.gd
@@ -4,3 +4,4 @@ func i_return_int() -> int:
func test():
i_return_int()
+ preload("../../utils.notest.gd") # `preload` is a function-like keyword.
diff --git a/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out b/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out
index f2db4e9307..107051df6c 100644
--- a/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out
+++ b/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out
@@ -3,3 +3,7 @@ GDTEST_OK
>> Line: 6
>> RETURN_VALUE_DISCARDED
>> The function "i_return_int()" returns a value that will be discarded if not used.
+>> WARNING
+>> Line: 7
+>> RETURN_VALUE_DISCARDED
+>> The function "preload()" returns a value that will be discarded if not used.
diff --git a/modules/gdscript/tests/scripts/parser/warnings/standalone_expression.gd b/modules/gdscript/tests/scripts/parser/warnings/standalone_expression.gd
index dc4223ec2d..74f42b012b 100644
--- a/modules/gdscript/tests/scripts/parser/warnings/standalone_expression.gd
+++ b/modules/gdscript/tests/scripts/parser/warnings/standalone_expression.gd
@@ -6,3 +6,16 @@ func test():
Vector3.ZERO
[true, false]
float(125)
+ # The following statements should not produce `STANDALONE_EXPRESSION`:
+ var _a = 1
+ _a = 2 # Assignment is a local (or global) side effect.
+ @warning_ignore("redundant_await")
+ await 3 # The `await` operand is usually a coroutine or a signal.
+ absi(4) # A call (in general) can have side effects.
+ @warning_ignore("return_value_discarded")
+ preload("../../utils.notest.gd") # A static initializer may have side effects.
+ """
+ Python-like "comment".
+ """
+ @warning_ignore("standalone_ternary")
+ 1 if 2 else 3 # Produces `STANDALONE_TERNARY` instead.
diff --git a/modules/gdscript/tests/scripts/parser/warnings/standalone_expression.out b/modules/gdscript/tests/scripts/parser/warnings/standalone_expression.out
index a2c67a6e51..72c659c952 100644
--- a/modules/gdscript/tests/scripts/parser/warnings/standalone_expression.out
+++ b/modules/gdscript/tests/scripts/parser/warnings/standalone_expression.out
@@ -2,16 +2,16 @@ GDTEST_OK
>> WARNING
>> Line: 3
>> STANDALONE_EXPRESSION
->> Standalone expression (the line has no effect).
+>> Standalone expression (the line may have no effect).
>> WARNING
>> Line: 4
>> STANDALONE_EXPRESSION
->> Standalone expression (the line has no effect).
+>> Standalone expression (the line may have no effect).
>> WARNING
>> Line: 6
>> STANDALONE_EXPRESSION
->> Standalone expression (the line has no effect).
+>> Standalone expression (the line may have no effect).
>> WARNING
>> Line: 7
>> STANDALONE_EXPRESSION
->> Standalone expression (the line has no effect).
+>> Standalone expression (the line may have no effect).
diff --git a/modules/gdscript/tests/scripts/runtime/features/export_group_no_name_conflict_with_properties.out b/modules/gdscript/tests/scripts/runtime/features/export_group_no_name_conflict_with_properties.out
index 9387ec50d7..a1e7233078 100644
--- a/modules/gdscript/tests/scripts/runtime/features/export_group_no_name_conflict_with_properties.out
+++ b/modules/gdscript/tests/scripts/runtime/features/export_group_no_name_conflict_with_properties.out
@@ -1,8 +1,8 @@
GDTEST_OK
Not shadowed: Resource
var test_1: int = 0
- hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
@export_category("test_1")
- hint=NONE hint_string="" usage=CATEGORY
+ hint=NONE hint_string="" usage=CATEGORY class_name=&""
var test_2: int = 0
- hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
+ hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
diff --git a/modules/gdscript/tests/scripts/utils.notest.gd b/modules/gdscript/tests/scripts/utils.notest.gd
index 1cf46c179e..7fdd6556ec 100644
--- a/modules/gdscript/tests/scripts/utils.notest.gd
+++ b/modules/gdscript/tests/scripts/utils.notest.gd
@@ -55,18 +55,18 @@ static func get_human_readable_hint_string(property: Dictionary) -> String:
if elem_type_hint.is_valid_int():
elem_type = elem_type_hint.to_int()
- type_hint_prefixes += type_string(elem_type) + ":"
+ type_hint_prefixes += "<%s>:" % type_string(elem_type)
else:
if elem_type_hint.count("/") != 1:
push_error("Invalid PROPERTY_HINT_TYPE_STRING format.")
elem_type = elem_type_hint.get_slice("/", 0).to_int()
elem_hint = elem_type_hint.get_slice("/", 1).to_int()
- type_hint_prefixes += "%s/%s:" % [
- type_string(elem_type),
- get_property_hint_name(elem_hint).trim_prefix("PROPERTY_HINT_"),
+ type_hint_prefixes += "<%s>/<%s>:" % [
+ type_string(elem_type),
+ get_property_hint_name(elem_hint).trim_prefix("PROPERTY_HINT_"),
]
- if elem_type < TYPE_ARRAY:
+ if elem_type < TYPE_ARRAY or hint_string.is_empty():
break
return type_hint_prefixes + hint_string
@@ -76,10 +76,11 @@ static func get_human_readable_hint_string(property: Dictionary) -> String:
static func print_property_extended_info(property: Dictionary, base: Object = null, is_static: bool = false) -> void:
print(get_property_signature(property, base, is_static))
- print(' hint=%s hint_string="%s" usage=%s' % [
+ print(' hint=%s hint_string="%s" usage=%s class_name=&"%s"' % [
get_property_hint_name(property.hint).trim_prefix("PROPERTY_HINT_"),
- get_human_readable_hint_string(property),
+ get_human_readable_hint_string(property).c_escape(),
get_property_usage_string(property.usage).replace("PROPERTY_USAGE_", ""),
+ property.class_name.c_escape(),
])
diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildProblemsView.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildProblemsView.cs
index b6d6d9ebf8..35a62a0eab 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildProblemsView.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildProblemsView.cs
@@ -280,7 +280,7 @@ namespace GodotTools.Build
if (_problemsContextMenu.ItemCount > 0)
{
- _problemsContextMenu.Position = (Vector2I)(_problemsTree.GlobalPosition + position);
+ _problemsContextMenu.Position = (Vector2I)(GetScreenPosition() + position);
_problemsContextMenu.Popup();
}
}
diff --git a/modules/noise/noise_texture_2d.cpp b/modules/noise/noise_texture_2d.cpp
index 0443fec4a0..0960b2ad36 100644
--- a/modules/noise/noise_texture_2d.cpp
+++ b/modules/noise/noise_texture_2d.cpp
@@ -119,6 +119,7 @@ void NoiseTexture2D::_set_texture_image(const Ref<Image> &p_image) {
} else {
texture = RS::get_singleton()->texture_2d_create(p_image);
}
+ RS::get_singleton()->texture_set_path(texture, get_path());
}
emit_changed();
}
diff --git a/modules/svg/SCsub b/modules/svg/SCsub
index 0e21c1e6d7..a32be0e41a 100644
--- a/modules/svg/SCsub
+++ b/modules/svg/SCsub
@@ -26,7 +26,6 @@ thirdparty_sources = [
"src/loaders/raw/tvgRawLoader.cpp",
# image loaders
"src/loaders/external_png/tvgPngLoader.cpp",
- "src/loaders/external_webp/tvgWebpLoader.cpp",
"src/loaders/jpg/tvgJpgd.cpp",
"src/loaders/jpg/tvgJpgLoader.cpp",
# renderer common
@@ -59,6 +58,10 @@ thirdparty_sources = [
"src/renderer/sw_engine/tvgSwStroke.cpp",
]
+if env["module_webp_enabled"]:
+ thirdparty_sources += ["src/loaders/external_webp/tvgWebpLoader.cpp"]
+ env_svg.Append(CPPDEFINES=["THORVG_WEBP_LOADER_SUPPORT"])
+
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
env_svg.Prepend(CPPPATH=[thirdparty_dir + "inc"])
@@ -76,12 +79,15 @@ env_thirdparty.Prepend(
thirdparty_dir + "src/renderer/sw_engine",
thirdparty_dir + "src/loaders/raw",
thirdparty_dir + "src/loaders/external_png",
- thirdparty_dir + "src/loaders/external_webp",
thirdparty_dir + "src/loaders/jpg",
- "#thirdparty/libpng",
- "#thirdparty/libwebp/src",
]
)
+if env["builtin_libpng"]:
+ env_thirdparty.Prepend(CPPPATH=["#thirdparty/libpng"])
+if env["module_webp_enabled"]:
+ env_thirdparty.Prepend(CPPPATH=[thirdparty_dir + "src/loaders/external_webp"])
+ if env["builtin_libwebp"]:
+ env_thirdparty.Prepend(CPPPATH=["#thirdparty/libwebp/src"])
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_sources)
env.modules_sources += thirdparty_obj
diff --git a/platform/web/export/export_plugin.cpp b/platform/web/export/export_plugin.cpp
index 0bf3927e14..06dfe7d646 100644
--- a/platform/web/export/export_plugin.cpp
+++ b/platform/web/export/export_plugin.cpp
@@ -585,17 +585,20 @@ bool EditorExportPlatformWeb::poll_export() {
}
}
+ int prev = menu_options;
+ menu_options = preset.is_valid();
HTTPServerState prev_server_state = server_state;
server_state = HTTP_SERVER_STATE_OFF;
if (server->is_listening()) {
- if (preset.is_null()) {
+ if (preset.is_null() || menu_options == 0) {
server->stop();
} else {
server_state = HTTP_SERVER_STATE_ON;
+ menu_options += 1;
}
}
- return server_state != prev_server_state;
+ return server_state != prev_server_state || menu_options != prev;
}
Ref<ImageTexture> EditorExportPlatformWeb::get_option_icon(int p_index) const {
diff --git a/platform/web/export/export_plugin.h b/platform/web/export/export_plugin.h
index 9d3a1a7861..d3d2083a23 100644
--- a/platform/web/export/export_plugin.h
+++ b/platform/web/export/export_plugin.h
@@ -58,6 +58,7 @@ class EditorExportPlatformWeb : public EditorExportPlatform {
HTTPServerState server_state = HTTP_SERVER_STATE_OFF;
Ref<EditorHTTPServer> server;
+ int menu_options = 0;
String _get_template_name(bool p_extension, bool p_thread_support, bool p_debug) const {
String name = "web";
diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp
index 15b7f62036..3bf9d79c7f 100644
--- a/scene/gui/button.cpp
+++ b/scene/gui/button.cpp
@@ -50,6 +50,83 @@ void Button::_set_internal_margin(Side p_side, float p_value) {
void Button::_queue_update_size_cache() {
}
+void Button::_update_theme_item_cache() {
+ Control::_update_theme_item_cache();
+
+ const bool rtl = is_layout_rtl();
+ if (rtl && has_theme_stylebox(SNAME("normal_mirrored"))) {
+ theme_cache.max_style_size = theme_cache.normal_mirrored->get_minimum_size();
+ theme_cache.style_margin_left = theme_cache.normal_mirrored->get_margin(SIDE_LEFT);
+ theme_cache.style_margin_right = theme_cache.normal_mirrored->get_margin(SIDE_RIGHT);
+ theme_cache.style_margin_top = theme_cache.normal_mirrored->get_margin(SIDE_TOP);
+ theme_cache.style_margin_bottom = theme_cache.normal_mirrored->get_margin(SIDE_BOTTOM);
+ } else {
+ theme_cache.max_style_size = theme_cache.normal->get_minimum_size();
+ theme_cache.style_margin_left = theme_cache.normal->get_margin(SIDE_LEFT);
+ theme_cache.style_margin_right = theme_cache.normal->get_margin(SIDE_RIGHT);
+ theme_cache.style_margin_top = theme_cache.normal->get_margin(SIDE_TOP);
+ theme_cache.style_margin_bottom = theme_cache.normal->get_margin(SIDE_BOTTOM);
+ }
+ if (has_theme_stylebox("hover_pressed")) {
+ if (rtl && has_theme_stylebox(SNAME("hover_pressed_mirrored"))) {
+ theme_cache.max_style_size = theme_cache.max_style_size.max(theme_cache.hover_pressed_mirrored->get_minimum_size());
+ theme_cache.style_margin_left = MAX(theme_cache.style_margin_left, theme_cache.hover_pressed_mirrored->get_margin(SIDE_LEFT));
+ theme_cache.style_margin_right = MAX(theme_cache.style_margin_right, theme_cache.hover_pressed_mirrored->get_margin(SIDE_RIGHT));
+ theme_cache.style_margin_top = MAX(theme_cache.style_margin_top, theme_cache.hover_pressed_mirrored->get_margin(SIDE_TOP));
+ theme_cache.style_margin_bottom = MAX(theme_cache.style_margin_bottom, theme_cache.hover_pressed_mirrored->get_margin(SIDE_BOTTOM));
+ } else {
+ theme_cache.max_style_size = theme_cache.max_style_size.max(theme_cache.hover_pressed->get_minimum_size());
+ theme_cache.style_margin_left = MAX(theme_cache.style_margin_left, theme_cache.hover_pressed->get_margin(SIDE_LEFT));
+ theme_cache.style_margin_right = MAX(theme_cache.style_margin_right, theme_cache.hover_pressed->get_margin(SIDE_RIGHT));
+ theme_cache.style_margin_top = MAX(theme_cache.style_margin_top, theme_cache.hover_pressed->get_margin(SIDE_TOP));
+ theme_cache.style_margin_bottom = MAX(theme_cache.style_margin_bottom, theme_cache.hover_pressed->get_margin(SIDE_BOTTOM));
+ }
+ }
+ if (rtl && has_theme_stylebox(SNAME("pressed_mirrored"))) {
+ theme_cache.max_style_size = theme_cache.max_style_size.max(theme_cache.pressed_mirrored->get_minimum_size());
+ theme_cache.style_margin_left = MAX(theme_cache.style_margin_left, theme_cache.pressed_mirrored->get_margin(SIDE_LEFT));
+ theme_cache.style_margin_right = MAX(theme_cache.style_margin_right, theme_cache.pressed_mirrored->get_margin(SIDE_RIGHT));
+ theme_cache.style_margin_top = MAX(theme_cache.style_margin_top, theme_cache.pressed_mirrored->get_margin(SIDE_TOP));
+ theme_cache.style_margin_bottom = MAX(theme_cache.style_margin_bottom, theme_cache.pressed_mirrored->get_margin(SIDE_BOTTOM));
+ } else {
+ theme_cache.max_style_size = theme_cache.max_style_size.max(theme_cache.pressed->get_minimum_size());
+ theme_cache.style_margin_left = MAX(theme_cache.style_margin_left, theme_cache.pressed->get_margin(SIDE_LEFT));
+ theme_cache.style_margin_right = MAX(theme_cache.style_margin_right, theme_cache.pressed->get_margin(SIDE_RIGHT));
+ theme_cache.style_margin_top = MAX(theme_cache.style_margin_top, theme_cache.pressed->get_margin(SIDE_TOP));
+ theme_cache.style_margin_bottom = MAX(theme_cache.style_margin_bottom, theme_cache.pressed->get_margin(SIDE_BOTTOM));
+ }
+ if (rtl && has_theme_stylebox(SNAME("hover_mirrored"))) {
+ theme_cache.max_style_size = theme_cache.max_style_size.max(theme_cache.hover_mirrored->get_minimum_size());
+ theme_cache.style_margin_left = MAX(theme_cache.style_margin_left, theme_cache.hover_mirrored->get_margin(SIDE_LEFT));
+ theme_cache.style_margin_right = MAX(theme_cache.style_margin_right, theme_cache.hover_mirrored->get_margin(SIDE_RIGHT));
+ theme_cache.style_margin_top = MAX(theme_cache.style_margin_top, theme_cache.hover_mirrored->get_margin(SIDE_TOP));
+ theme_cache.style_margin_bottom = MAX(theme_cache.style_margin_bottom, theme_cache.hover_mirrored->get_margin(SIDE_BOTTOM));
+ } else {
+ theme_cache.max_style_size = theme_cache.max_style_size.max(theme_cache.hover->get_minimum_size());
+ theme_cache.style_margin_left = MAX(theme_cache.style_margin_left, theme_cache.hover->get_margin(SIDE_LEFT));
+ theme_cache.style_margin_right = MAX(theme_cache.style_margin_right, theme_cache.hover->get_margin(SIDE_RIGHT));
+ theme_cache.style_margin_top = MAX(theme_cache.style_margin_top, theme_cache.hover->get_margin(SIDE_TOP));
+ theme_cache.style_margin_bottom = MAX(theme_cache.style_margin_bottom, theme_cache.hover->get_margin(SIDE_BOTTOM));
+ }
+ if (rtl && has_theme_stylebox(SNAME("disabled_mirrored"))) {
+ theme_cache.max_style_size = theme_cache.max_style_size.max(theme_cache.disabled_mirrored->get_minimum_size());
+ theme_cache.style_margin_left = MAX(theme_cache.style_margin_left, theme_cache.disabled_mirrored->get_margin(SIDE_LEFT));
+ theme_cache.style_margin_right = MAX(theme_cache.style_margin_right, theme_cache.disabled_mirrored->get_margin(SIDE_RIGHT));
+ theme_cache.style_margin_top = MAX(theme_cache.style_margin_top, theme_cache.disabled_mirrored->get_margin(SIDE_TOP));
+ theme_cache.style_margin_bottom = MAX(theme_cache.style_margin_bottom, theme_cache.disabled_mirrored->get_margin(SIDE_BOTTOM));
+ } else {
+ theme_cache.max_style_size = theme_cache.max_style_size.max(theme_cache.disabled->get_minimum_size());
+ theme_cache.style_margin_left = MAX(theme_cache.style_margin_left, theme_cache.disabled->get_margin(SIDE_LEFT));
+ theme_cache.style_margin_right = MAX(theme_cache.style_margin_right, theme_cache.disabled->get_margin(SIDE_RIGHT));
+ theme_cache.style_margin_top = MAX(theme_cache.style_margin_top, theme_cache.disabled->get_margin(SIDE_TOP));
+ theme_cache.style_margin_bottom = MAX(theme_cache.style_margin_bottom, theme_cache.disabled->get_margin(SIDE_BOTTOM));
+ }
+}
+
+Size2 Button::_get_largest_stylebox_size() const {
+ return theme_cache.max_style_size;
+}
+
Ref<StyleBox> Button::_get_current_stylebox() const {
Ref<StyleBox> stylebox = theme_cache.normal;
const bool rtl = is_layout_rtl();
@@ -137,16 +214,13 @@ void Button::_notification(int p_what) {
const RID ci = get_canvas_item();
const Size2 size = get_size();
- const Ref<StyleBox> style = _get_current_stylebox();
- { // Draws the stylebox in the current state.
- if (!flat) {
- style->draw(ci, Rect2(Point2(), size));
- }
+ // Draws the stylebox in the current state.
+ if (!flat) {
+ _get_current_stylebox()->draw(ci, Rect2(Point2(), size));
+ }
- if (has_focus()) {
- Ref<StyleBox> style2 = theme_cache.focus;
- style2->draw(ci, Rect2(Point2(), size));
- }
+ if (has_focus()) {
+ theme_cache.focus->draw(ci, Rect2(Point2(), size));
}
Ref<Texture2D> _icon = icon;
@@ -158,16 +232,11 @@ void Button::_notification(int p_what) {
break;
}
- const float style_margin_left = style->get_margin(SIDE_LEFT);
- const float style_margin_right = style->get_margin(SIDE_RIGHT);
- const float style_margin_top = style->get_margin(SIDE_TOP);
- const float style_margin_bottom = style->get_margin(SIDE_BOTTOM);
-
Size2 drawable_size_remained = size;
{ // The size after the stelybox is stripped.
- drawable_size_remained.width -= style_margin_left + style_margin_right;
- drawable_size_remained.height -= style_margin_top + style_margin_bottom;
+ drawable_size_remained.width -= theme_cache.style_margin_left + theme_cache.style_margin_right;
+ drawable_size_remained.height -= theme_cache.style_margin_top + theme_cache.style_margin_bottom;
}
const int h_separation = MAX(0, theme_cache.h_separation);
@@ -312,12 +381,12 @@ void Button::_notification(int p_what) {
[[fallthrough]];
case HORIZONTAL_ALIGNMENT_FILL:
case HORIZONTAL_ALIGNMENT_LEFT: {
- icon_ofs.x += style_margin_left;
+ icon_ofs.x += theme_cache.style_margin_left;
icon_ofs.x += left_internal_margin_with_h_separation;
} break;
case HORIZONTAL_ALIGNMENT_RIGHT: {
- icon_ofs.x = size.x - style_margin_right;
+ icon_ofs.x = size.x - theme_cache.style_margin_right;
icon_ofs.x -= right_internal_margin_with_h_separation;
icon_ofs.x -= icon_size.width;
} break;
@@ -330,11 +399,11 @@ void Button::_notification(int p_what) {
[[fallthrough]];
case VERTICAL_ALIGNMENT_FILL:
case VERTICAL_ALIGNMENT_TOP: {
- icon_ofs.y += style_margin_top;
+ icon_ofs.y += theme_cache.style_margin_top;
} break;
case VERTICAL_ALIGNMENT_BOTTOM: {
- icon_ofs.y = size.y - style_margin_bottom - icon_size.height;
+ icon_ofs.y = size.y - theme_cache.style_margin_bottom - icon_size.height;
} break;
}
icon_ofs = icon_ofs.floor();
@@ -373,7 +442,7 @@ void Button::_notification(int p_what) {
case HORIZONTAL_ALIGNMENT_FILL:
case HORIZONTAL_ALIGNMENT_LEFT:
case HORIZONTAL_ALIGNMENT_RIGHT: {
- text_ofs.x += style_margin_left;
+ text_ofs.x += theme_cache.style_margin_left;
text_ofs.x += left_internal_margin_with_h_separation;
if (icon_align_rtl_checked == HORIZONTAL_ALIGNMENT_LEFT) {
// Offset by the space's width that occupied by icon and h_separation together.
@@ -382,7 +451,7 @@ void Button::_notification(int p_what) {
} break;
}
- text_ofs.y = (drawable_size_remained.height - text_buf->get_size().height) / 2.0f + style_margin_top;
+ text_ofs.y = (drawable_size_remained.height - text_buf->get_size().height) / 2.0f + theme_cache.style_margin_top;
if (vertical_icon_alignment == VERTICAL_ALIGNMENT_TOP) {
text_ofs.y += custom_element_size.height - drawable_size_remained.height; // Offset by the icon's height.
}
@@ -452,7 +521,7 @@ Size2 Button::get_minimum_size_for_text_and_icon(const String &p_text, Ref<Textu
}
}
- return _get_current_stylebox()->get_minimum_size() + minsize;
+ return _get_largest_stylebox_size() + minsize;
}
void Button::_shape(Ref<TextParagraph> p_paragraph, String p_text) {
diff --git a/scene/gui/button.h b/scene/gui/button.h
index 86fdbd35d5..d2f80893e0 100644
--- a/scene/gui/button.h
+++ b/scene/gui/button.h
@@ -69,6 +69,12 @@ private:
Ref<StyleBox> disabled_mirrored;
Ref<StyleBox> focus;
+ Size2 max_style_size;
+ float style_margin_left = 0;
+ float style_margin_right = 0;
+ float style_margin_top = 0;
+ float style_margin_bottom = 0;
+
Color font_color;
Color font_focus_color;
Color font_pressed_color;
@@ -100,10 +106,13 @@ private:
void _texture_changed();
protected:
+ virtual void _update_theme_item_cache() override;
+
void _set_internal_margin(Side p_side, float p_value);
virtual void _queue_update_size_cache();
Ref<StyleBox> _get_current_stylebox() const;
+ Size2 _get_largest_stylebox_size() const;
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/gui/check_box.cpp b/scene/gui/check_box.cpp
index af6696834e..0dcd1d4ac4 100644
--- a/scene/gui/check_box.cpp
+++ b/scene/gui/check_box.cpp
@@ -66,7 +66,7 @@ Size2 CheckBox::get_minimum_size() const {
Size2 minsize = Button::get_minimum_size();
const Size2 tex_size = get_icon_size();
if (tex_size.width > 0 || tex_size.height > 0) {
- const Size2 padding = _get_current_stylebox()->get_minimum_size();
+ const Size2 padding = _get_largest_stylebox_size();
Size2 content_size = minsize - padding;
if (content_size.width > 0 && tex_size.width > 0) {
content_size.width += MAX(0, theme_cache.h_separation);
diff --git a/scene/gui/check_button.cpp b/scene/gui/check_button.cpp
index ab3b74a3c3..fe449fbfc3 100644
--- a/scene/gui/check_button.cpp
+++ b/scene/gui/check_button.cpp
@@ -70,7 +70,7 @@ Size2 CheckButton::get_minimum_size() const {
Size2 minsize = Button::get_minimum_size();
const Size2 tex_size = get_icon_size();
if (tex_size.width > 0 || tex_size.height > 0) {
- const Size2 padding = _get_current_stylebox()->get_minimum_size();
+ const Size2 padding = _get_largest_stylebox_size();
Size2 content_size = minsize - padding;
if (content_size.width > 0 && tex_size.width > 0) {
content_size.width += MAX(0, theme_cache.h_separation);
diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp
index 0f161a014a..68e72ea996 100644
--- a/scene/gui/option_button.cpp
+++ b/scene/gui/option_button.cpp
@@ -60,7 +60,7 @@ Size2 OptionButton::get_minimum_size() const {
}
if (has_theme_icon(SNAME("arrow"))) {
- const Size2 padding = _get_current_stylebox()->get_minimum_size();
+ const Size2 padding = _get_largest_stylebox_size();
const Size2 arrow_size = theme_cache.arrow_icon->get_size();
Size2 content_size = minsize - padding;
diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp
index 1d45a10d2a..38204af6d5 100644
--- a/scene/gui/popup.cpp
+++ b/scene/gui/popup.cpp
@@ -37,6 +37,7 @@
void Popup::_input_from_window(const Ref<InputEvent> &p_event) {
if (get_flag(FLAG_POPUP) && p_event->is_action_pressed(SNAME("ui_cancel"), false, true)) {
+ hide_reason = HIDE_REASON_CANCELED; // ESC pressed, mark as canceled unconditionally.
_close_pressed();
}
Window::_input_from_window(p_event);
@@ -104,13 +105,18 @@ void Popup::_notification(int p_what) {
case NOTIFICATION_WM_CLOSE_REQUEST: {
if (!is_in_edited_scene_root()) {
- hide_reason = HIDE_REASON_UNFOCUSED;
+ if (hide_reason == HIDE_REASON_NONE) {
+ hide_reason = HIDE_REASON_UNFOCUSED;
+ }
_close_pressed();
}
} break;
case NOTIFICATION_APPLICATION_FOCUS_OUT: {
if (!is_in_edited_scene_root() && get_flag(FLAG_POPUP)) {
+ if (hide_reason == HIDE_REASON_NONE) {
+ hide_reason = HIDE_REASON_UNFOCUSED;
+ }
_close_pressed();
}
} break;
@@ -119,7 +125,9 @@ void Popup::_notification(int p_what) {
void Popup::_parent_focused() {
if (popped_up && get_flag(FLAG_POPUP)) {
- hide_reason = HIDE_REASON_UNFOCUSED;
+ if (hide_reason == HIDE_REASON_NONE) {
+ hide_reason = HIDE_REASON_UNFOCUSED;
+ }
_close_pressed();
}
}
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 49cfa8a030..69b84da23d 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -558,8 +558,6 @@ void TextEdit::_notification(int p_what) {
int visible_rows = get_visible_line_count() + 1;
- Color color = !editable ? theme_cache.font_readonly_color : theme_cache.font_color;
-
if (theme_cache.background_color.a > 0.01) {
RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(), get_size()), theme_cache.background_color);
}
@@ -734,7 +732,7 @@ void TextEdit::_notification(int p_what) {
if (draw_minimap) {
int minimap_visible_lines = get_minimap_visible_lines();
int minimap_line_height = (minimap_char_size.y + minimap_line_spacing);
- int minimap_tab_size = minimap_char_size.x * text.get_tab_size();
+ int tab_size = text.get_tab_size();
// Calculate viewport size and y offset.
int viewport_height = (draw_amount - 1) * minimap_line_height;
@@ -839,68 +837,74 @@ void TextEdit::_notification(int p_what) {
}
}
- Color previous_color;
+ Color next_color = current_color;
int characters = 0;
- int tabs = 0;
+ int tab_alignment = 0;
+ int xpos = xmargin_end + 2 + indent_px;
for (int j = 0; j < str.length(); j++) {
- const Variant *color_data = color_map.getptr(last_wrap_column + j);
- if (color_data != nullptr) {
- current_color = (color_data->operator Dictionary()).get("color", theme_cache.font_color);
- if (!editable) {
- current_color.a = theme_cache.font_readonly_color.a;
+ bool next_is_whitespace = false;
+ bool next_is_tab = false;
+ // Get the number of characters to draw together.
+ for (characters = 0; j + characters < str.length(); characters++) {
+ int next_char_index = j + characters;
+ const Variant *color_data = color_map.getptr(last_wrap_column + next_char_index);
+ if (color_data != nullptr) {
+ next_color = (color_data->operator Dictionary()).get("color", theme_cache.font_color);
+ if (!editable) {
+ next_color.a = theme_cache.font_readonly_color.a;
+ }
+ next_color.a *= 0.6;
}
- }
- color = current_color;
-
- if (j == 0) {
- previous_color = color;
- }
-
- int xpos = indent_px + ((xmargin_end + minimap_char_size.x) + (minimap_char_size.x * j)) + tabs;
- bool out_of_bounds = (xpos >= xmargin_end + minimap_width);
-
- bool whitespace = is_whitespace(str[j]);
- if (!whitespace) {
- characters++;
-
- if (j < str.length() - 1 && color == previous_color && !out_of_bounds) {
- continue;
+ if (characters == 0) {
+ current_color = next_color;
}
-
- // If we've changed color we are at the start of a new section, therefore we need to go back to the end
- // of the previous section to draw it, we'll also add the character back on.
- if (color != previous_color) {
- characters--;
- j--;
-
- if (str[j] == '\t') {
- tabs -= minimap_tab_size;
+ if (next_color != current_color) {
+ break;
+ }
+ next_is_whitespace = is_whitespace(str[next_char_index]);
+ if (next_is_whitespace) {
+ if (str[next_char_index] == '\t') {
+ next_is_tab = true;
}
+ break;
+ }
+ bool out_of_bounds = xpos + minimap_char_size.x * characters >= xmargin_end + minimap_width;
+ if (out_of_bounds) {
+ break;
}
}
+ if (!next_is_whitespace && characters == 0) {
+ break;
+ }
if (characters > 0) {
- previous_color.a *= 0.6;
- // Take one for zero indexing, and if we hit whitespace / the end of a word.
- int chars = MAX(0, (j - (characters - 1)) - (whitespace ? 1 : 0)) + 1;
- int char_x_ofs = indent_px + ((xmargin_end + minimap_char_size.x) + (minimap_char_size.x * chars)) + tabs;
if (rtl) {
- RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(size.width - char_x_ofs - minimap_char_size.x * characters, minimap_line_height * i), Point2(minimap_char_size.x * characters, minimap_char_size.y)), previous_color);
+ RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(size.width - xpos - minimap_char_size.x * characters, minimap_line_height * i), Point2(minimap_char_size.x * characters, minimap_char_size.y)), current_color);
} else {
- RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(char_x_ofs, minimap_line_height * i), Point2(minimap_char_size.x * characters, minimap_char_size.y)), previous_color);
+ RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(xpos, minimap_line_height * i), Point2(minimap_char_size.x * characters, minimap_char_size.y)), current_color);
}
}
- if (out_of_bounds) {
- break;
- }
+ j += characters - 1;
+ xpos += minimap_char_size.x * characters;
+ tab_alignment += characters;
- if (str[j] == '\t') {
- tabs += minimap_tab_size;
+ if (next_is_whitespace) {
+ if (next_is_tab) {
+ tab_alignment %= tab_size;
+ xpos += minimap_char_size.x * (tab_size - tab_alignment);
+ tab_alignment = 0;
+ } else {
+ xpos += minimap_char_size.x;
+ tab_alignment += 1;
+ }
+ j += 1;
}
- previous_color = color;
- characters = 0;
+ if (xpos >= xmargin_end + minimap_width) {
+ // Out of bounds.
+ break;
+ }
}
}
}
@@ -1188,6 +1192,7 @@ void TextEdit::_notification(int p_what) {
if (!clipped && lookup_symbol_word.length() != 0) { // Highlight word
if (is_ascii_alphabet_char(lookup_symbol_word[0]) || lookup_symbol_word[0] == '_' || lookup_symbol_word[0] == '.') {
+ Color highlight_underline_color = !editable ? theme_cache.font_readonly_color : theme_cache.font_color;
int lookup_symbol_word_col = _get_column_pos_of_word(lookup_symbol_word, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, 0);
int lookup_symbol_word_len = lookup_symbol_word.length();
while (lookup_symbol_word_col != -1) {
@@ -1205,7 +1210,7 @@ void TextEdit::_notification(int p_what) {
}
rect.position.y += ceil(TS->shaped_text_get_ascent(rid)) + ceil(theme_cache.font->get_underline_position(theme_cache.font_size));
rect.size.y = MAX(1, theme_cache.font->get_underline_thickness(theme_cache.font_size));
- draw_rect(rect, color);
+ draw_rect(rect, highlight_underline_color);
}
lookup_symbol_word_col = _get_column_pos_of_word(lookup_symbol_word, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, lookup_symbol_word_col + lookup_symbol_word_len);
@@ -7973,7 +7978,7 @@ void TextEdit::_update_minimap_click() {
Point2 mp = get_local_mouse_pos();
int xmargin_end = get_size().width - theme_cache.style_normal->get_margin(SIDE_RIGHT);
- if (!dragging_minimap && (mp.x < xmargin_end - minimap_width || mp.y > xmargin_end)) {
+ if (!dragging_minimap && (mp.x < xmargin_end - minimap_width || mp.x > xmargin_end)) {
minimap_clicked = false;
return;
}
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 133515754b..fc5b942918 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -3152,8 +3152,12 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
}
void Tree::_text_editor_popup_modal_close() {
+ if (popup_edit_commited) {
+ return; // Already processed by LineEdit/TextEdit commit.
+ }
+
if (popup_editor->get_hide_reason() == Popup::HIDE_REASON_CANCELED) {
- return;
+ return; // ESC pressed, app focus lost, or forced close from code.
}
if (value_editor->has_point(value_editor->get_local_mouse_position())) {
@@ -3172,9 +3176,18 @@ void Tree::_text_editor_popup_modal_close() {
}
void Tree::_text_editor_gui_input(const Ref<InputEvent> &p_event) {
+ if (popup_edit_commited) {
+ return; // Already processed by _text_editor_popup_modal_close
+ }
+
+ if (popup_editor->get_hide_reason() == Popup::HIDE_REASON_CANCELED) {
+ return; // ESC pressed, app focus lost, or forced close from code.
+ }
+
if (p_event->is_action_pressed("ui_text_newline_blank", true)) {
accept_event();
} else if (p_event->is_action_pressed("ui_text_newline")) {
+ popup_edit_commited = true; // End edit popup processing.
popup_editor->hide();
_apply_multiline_edit();
accept_event();
@@ -3205,6 +3218,15 @@ void Tree::_apply_multiline_edit() {
}
void Tree::_line_editor_submit(String p_text) {
+ if (popup_edit_commited) {
+ return; // Already processed by _text_editor_popup_modal_close
+ }
+
+ if (popup_editor->get_hide_reason() == Popup::HIDE_REASON_CANCELED) {
+ return; // ESC pressed, app focus lost, or forced close from code.
+ }
+
+ popup_edit_commited = true; // End edit popup processing.
popup_editor->hide();
if (!popup_edited_item) {
@@ -4072,6 +4094,7 @@ bool Tree::edit_selected(bool p_force_edit) {
if (!popup_editor->is_embedded()) {
popup_editor->set_content_scale_factor(popup_scale);
}
+ popup_edit_commited = false; // Start edit popup processing.
popup_editor->popup();
popup_editor->child_controls_changed();
@@ -4091,6 +4114,7 @@ bool Tree::edit_selected(bool p_force_edit) {
if (!popup_editor->is_embedded()) {
popup_editor->set_content_scale_factor(popup_scale);
}
+ popup_edit_commited = false; // Start edit popup processing.
popup_editor->popup();
popup_editor->child_controls_changed();
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index 311055a2f8..e9c93c6e03 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -479,6 +479,7 @@ private:
VBoxContainer *popup_editor_vb = nullptr;
+ bool popup_edit_commited = true;
Popup *popup_editor = nullptr;
LineEdit *line_editor = nullptr;
TextEdit *text_editor = nullptr;
diff --git a/scene/resources/gradient_texture.cpp b/scene/resources/gradient_texture.cpp
index 7df439a799..6ec9422d2d 100644
--- a/scene/resources/gradient_texture.cpp
+++ b/scene/resources/gradient_texture.cpp
@@ -136,6 +136,7 @@ void GradientTexture1D::_update() {
texture = RS::get_singleton()->texture_2d_create(image);
}
}
+ RS::get_singleton()->texture_set_path(texture, get_path());
}
void GradientTexture1D::set_width(int p_width) {
@@ -275,6 +276,7 @@ void GradientTexture2D::_update() {
} else {
texture = RS::get_singleton()->texture_2d_create(image);
}
+ RS::get_singleton()->texture_set_path(texture, get_path());
}
float GradientTexture2D::_get_gradient_offset_at(int x, int y) const {
diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp
index 5e9510c1ac..8267e958b4 100644
--- a/scene/resources/shader.cpp
+++ b/scene/resources/shader.cpp
@@ -155,7 +155,7 @@ void Shader::get_shader_uniform_list(List<PropertyInfo> *p_params, bool p_get_gr
DocData::PropertyDoc prop_doc;
prop_doc.name = "shader_parameter/" + pi.name;
#ifdef MODULE_REGEX_ENABLED
- const RegEx pattern("/\\*\\*([^*]|[\\r\\n]|(\\*+([^*/]|[\\r\\n])))*\\*+/\\s*uniform\\s+\\w+\\s+" + pi.name + "(?=[\\s:;=])");
+ const RegEx pattern("/\\*\\*\\s([^*]|[\\r\\n]|(\\*+([^*/]|[\\r\\n])))*\\*+/\\s*uniform\\s+\\w+\\s+" + pi.name + "(?=[\\s:;=])");
Ref<RegExMatch> pattern_ref = pattern.search(code);
if (pattern_ref != nullptr) {
RegExMatch *match = pattern_ref.ptr();
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
index 012451a5cd..14d138181f 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
@@ -169,7 +169,11 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color
return;
}
- RD::get_singleton()->screen_prepare_for_drawing(DisplayServer::MAIN_WINDOW_ID);
+ Error err = RD::get_singleton()->screen_prepare_for_drawing(DisplayServer::MAIN_WINDOW_ID);
+ if (err != OK) {
+ // Window is minimized and does not have valid swapchain, skip drawing without printing errors.
+ return;
+ }
RID texture = texture_storage->texture_allocate();
texture_storage->texture_2d_initialize(texture, p_image);
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
index f844919df1..6e5e8f63e0 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
@@ -1457,6 +1457,23 @@ void TextureStorage::texture_set_detect_roughness_callback(RID p_texture, RS::Te
}
void TextureStorage::texture_debug_usage(List<RS::TextureInfo> *r_info) {
+ List<RID> textures;
+ texture_owner.get_owned_list(&textures);
+
+ for (List<RID>::Element *E = textures.front(); E; E = E->next()) {
+ Texture *t = texture_owner.get_or_null(E->get());
+ if (!t) {
+ continue;
+ }
+ RS::TextureInfo tinfo;
+ tinfo.path = t->path;
+ tinfo.format = t->format;
+ tinfo.width = t->width;
+ tinfo.height = t->height;
+ tinfo.depth = t->depth;
+ tinfo.bytes = Image::get_image_data_size(t->width, t->height, t->format, t->mipmaps);
+ r_info->push_back(tinfo);
+ }
}
void TextureStorage::texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) {
@@ -3042,6 +3059,7 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
texture_2d_placeholder_initialize(rt->texture);
Texture *tex = get_texture(rt->texture);
tex->is_render_target = true;
+ tex->path = "Render Target (Internal)";
}
_clear_render_target(rt);
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index d630238cb9..15e1731823 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -3154,9 +3154,6 @@ Error RenderingDevice::screen_create(DisplayServer::WindowID p_screen) {
RDD::SwapChainID swap_chain = driver->swap_chain_create(surface);
ERR_FAIL_COND_V_MSG(swap_chain.id == 0, ERR_CANT_CREATE, "Unable to create swap chain.");
- Error err = driver->swap_chain_resize(main_queue, swap_chain, _get_swap_chain_desired_count());
- ERR_FAIL_COND_V_MSG(err != OK, ERR_CANT_CREATE, "Unable to resize the new swap chain.");
-
screen_swap_chains[p_screen] = swap_chain;
return OK;
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index 020be6be18..42773fc347 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -797,6 +797,8 @@ private:
#endif
public:
+ RenderingContextDriver *get_context_driver() const { return context; }
+
const RDD::Capabilities &get_device_capabilities() const { return driver->get_capabilities(); }
bool has_feature(const Features p_feature) const;
diff --git a/tests/create_test.py b/tests/create_test.py
index deb53aca20..deb53aca20 100644..100755
--- a/tests/create_test.py
+++ b/tests/create_test.py
diff --git a/thirdparty/glslang/SPIRV/GlslangToSpv.cpp b/thirdparty/glslang/SPIRV/GlslangToSpv.cpp
index ec40f663a7..ec40f663a7 100755..100644
--- a/thirdparty/glslang/SPIRV/GlslangToSpv.cpp
+++ b/thirdparty/glslang/SPIRV/GlslangToSpv.cpp
diff --git a/thirdparty/glslang/SPIRV/doc.cpp b/thirdparty/glslang/SPIRV/doc.cpp
index 1a05c67360..1a05c67360 100755..100644
--- a/thirdparty/glslang/SPIRV/doc.cpp
+++ b/thirdparty/glslang/SPIRV/doc.cpp
diff --git a/thirdparty/glslang/glslang/Include/BaseTypes.h b/thirdparty/glslang/glslang/Include/BaseTypes.h
index 64bffa8926..64bffa8926 100755..100644
--- a/thirdparty/glslang/glslang/Include/BaseTypes.h
+++ b/thirdparty/glslang/glslang/Include/BaseTypes.h
diff --git a/thirdparty/glslang/glslang/MachineIndependent/Initialize.cpp b/thirdparty/glslang/glslang/MachineIndependent/Initialize.cpp
index af333f3f16..af333f3f16 100755..100644
--- a/thirdparty/glslang/glslang/MachineIndependent/Initialize.cpp
+++ b/thirdparty/glslang/glslang/MachineIndependent/Initialize.cpp
diff --git a/thirdparty/glslang/glslang/MachineIndependent/Versions.h b/thirdparty/glslang/glslang/MachineIndependent/Versions.h
index 475cb89341..475cb89341 100755..100644
--- a/thirdparty/glslang/glslang/MachineIndependent/Versions.h
+++ b/thirdparty/glslang/glslang/MachineIndependent/Versions.h
diff --git a/thirdparty/thorvg/inc/config.h b/thirdparty/thorvg/inc/config.h
index f271b52faf..3ae166cf22 100644
--- a/thirdparty/thorvg/inc/config.h
+++ b/thirdparty/thorvg/inc/config.h
@@ -5,9 +5,11 @@
#define THORVG_SVG_LOADER_SUPPORT
#define THORVG_PNG_LOADER_SUPPORT
#define THORVG_JPG_LOADER_SUPPORT
-#define THORVG_WEBP_LOADER_SUPPORT
#define THORVG_THREAD_SUPPORT
+// Added conditionally if webp module is enabled.
+//#define THORVG_WEBP_LOADER_SUPPORT
+
// For internal debugging:
//#define THORVG_LOG_ENABLED
diff --git a/thirdparty/thorvg/update-thorvg.sh b/thirdparty/thorvg/update-thorvg.sh
index 23604afbcd..796060d3fb 100755
--- a/thirdparty/thorvg/update-thorvg.sh
+++ b/thirdparty/thorvg/update-thorvg.sh
@@ -38,9 +38,11 @@ cat << EOF > ../inc/config.h
#define THORVG_SVG_LOADER_SUPPORT
#define THORVG_PNG_LOADER_SUPPORT
#define THORVG_JPG_LOADER_SUPPORT
-#define THORVG_WEBP_LOADER_SUPPORT
#define THORVG_THREAD_SUPPORT
+// Added conditionally if webp module is enabled.
+//#define THORVG_WEBP_LOADER_SUPPORT
+
// For internal debugging:
//#define THORVG_LOG_ENABLED