summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/object/script_language.cpp7
-rw-r--r--core/object/script_language.h14
-rw-r--r--core/object/script_language_extension.cpp1
-rw-r--r--core/object/script_language_extension.h1
-rw-r--r--doc/classes/DisplayServer.xml8
-rw-r--r--doc/classes/EditorSettings.xml3
-rw-r--r--doc/classes/ProjectSettings.xml7
-rw-r--r--doc/classes/ScriptLanguage.xml10
-rw-r--r--doc/classes/ScriptLanguageExtension.xml5
-rw-r--r--doc/classes/TextEdit.xml3
-rw-r--r--doc/classes/TextServer.xml3
-rw-r--r--drivers/d3d12/rendering_context_driver_d3d12.cpp41
-rw-r--r--drivers/d3d12/rendering_context_driver_d3d12.h3
-rw-r--r--drivers/d3d12/rendering_device_driver_d3d12.cpp19
-rw-r--r--drivers/gles3/shaders/scene.glsl4
-rw-r--r--drivers/gles3/storage/light_storage.cpp4
-rw-r--r--drivers/gles3/storage/light_storage.h1
-rw-r--r--drivers/gles3/storage/texture_storage.cpp4
-rw-r--r--editor/action_map_editor.cpp4
-rw-r--r--editor/action_map_editor.h1
-rw-r--r--editor/code_editor.cpp1
-rw-r--r--editor/editor_autoload_settings.cpp6
-rw-r--r--editor/editor_autoload_settings.h2
-rw-r--r--editor/editor_node.cpp31
-rw-r--r--editor/editor_node.h7
-rw-r--r--editor/editor_settings.cpp1
-rw-r--r--editor/filesystem_dock.cpp7
-rw-r--r--editor/filesystem_dock.h1
-rw-r--r--editor/group_settings_editor.cpp4
-rw-r--r--editor/group_settings_editor.h1
-rw-r--r--editor/gui/editor_file_dialog.cpp6
-rw-r--r--editor/project_settings_editor.cpp28
-rw-r--r--editor/project_settings_editor.h1
-rw-r--r--editor/register_editor_types.cpp4
-rw-r--r--editor/script_create_dialog.cpp63
-rw-r--r--editor/script_create_dialog.h3
-rw-r--r--editor/shader_globals_editor.cpp4
-rw-r--r--editor/shader_globals_editor.h2
-rw-r--r--godot.manifest13
-rw-r--r--modules/mono/csharp_script.cpp4
-rw-r--r--modules/mono/csharp_script.h1
-rw-r--r--modules/text_server_adv/text_server_adv.cpp5
-rw-r--r--modules/text_server_fb/text_server_fb.cpp5
-rw-r--r--platform/windows/detect.py16
-rw-r--r--platform/windows/display_server_windows.cpp310
-rw-r--r--platform/windows/display_server_windows.h5
-rw-r--r--platform/windows/godot_res.rc5
-rw-r--r--scene/3d/label_3d.cpp13
-rw-r--r--scene/gui/file_dialog.cpp21
-rw-r--r--scene/gui/rich_text_label.cpp1
-rw-r--r--scene/gui/text_edit.cpp69
-rw-r--r--scene/gui/text_edit.h7
-rw-r--r--servers/rendering/dummy/storage/light_storage.h1
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp13
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.cpp22
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.h2
-rw-r--r--servers/rendering/renderer_scene_cull.cpp17
-rw-r--r--servers/rendering/storage/light_storage.h1
-rw-r--r--servers/text_server.cpp44
-rw-r--r--servers/text_server.h1
-rw-r--r--thirdparty/directx_headers/include/directx/d3dx12_root_signature.h30
-rw-r--r--thirdparty/directx_headers/patches/patch_d3d12_dynamic_load.diff82
62 files changed, 882 insertions, 121 deletions
diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp
index 3b9b1f9094..d358a8d2a0 100644
--- a/core/object/script_language.cpp
+++ b/core/object/script_language.cpp
@@ -535,6 +535,13 @@ TypedArray<int> ScriptLanguage::CodeCompletionOption::get_option_cached_characte
return charac;
}
+void ScriptLanguage::_bind_methods() {
+ BIND_ENUM_CONSTANT(SCRIPT_NAME_CASING_AUTO);
+ BIND_ENUM_CONSTANT(SCRIPT_NAME_CASING_PASCAL_CASE);
+ BIND_ENUM_CONSTANT(SCRIPT_NAME_CASING_SNAKE_CASE);
+ BIND_ENUM_CONSTANT(SCRIPT_NAME_CASING_KEBAB_CASE);
+}
+
bool PlaceHolderScriptInstance::set(const StringName &p_name, const Variant &p_value) {
if (script->is_placeholder_fallback_enabled()) {
return false;
diff --git a/core/object/script_language.h b/core/object/script_language.h
index 4217bc9f96..95e9d2b4af 100644
--- a/core/object/script_language.h
+++ b/core/object/script_language.h
@@ -193,6 +193,10 @@ public:
class ScriptLanguage : public Object {
GDCLASS(ScriptLanguage, Object)
+
+protected:
+ static void _bind_methods();
+
public:
virtual String get_name() const = 0;
@@ -224,6 +228,13 @@ public:
TEMPLATE_PROJECT
};
+ enum ScriptNameCasing {
+ SCRIPT_NAME_CASING_AUTO,
+ SCRIPT_NAME_CASING_PASCAL_CASE,
+ SCRIPT_NAME_CASING_SNAKE_CASE,
+ SCRIPT_NAME_CASING_KEBAB_CASE,
+ };
+
struct ScriptTemplate {
String inherit = "Object";
String name;
@@ -260,6 +271,7 @@ public:
virtual bool can_make_function() const { return true; }
virtual Error open_in_external_editor(const Ref<Script> &p_script, int p_line, int p_col) { return ERR_UNAVAILABLE; }
virtual bool overrides_external_editor() { return false; }
+ virtual ScriptNameCasing preferred_file_name_casing() const { return SCRIPT_NAME_CASING_SNAKE_CASE; }
// Keep enums in sync with:
// scene/gui/code_edit.h - CodeEdit::CodeCompletionKind
@@ -405,6 +417,8 @@ public:
virtual ~ScriptLanguage() {}
};
+VARIANT_ENUM_CAST(ScriptLanguage::ScriptNameCasing);
+
extern uint8_t script_encryption_key[32];
class PlaceHolderScriptInstance : public ScriptInstance {
diff --git a/core/object/script_language_extension.cpp b/core/object/script_language_extension.cpp
index 3a9b171f28..ec99c7cf4e 100644
--- a/core/object/script_language_extension.cpp
+++ b/core/object/script_language_extension.cpp
@@ -112,6 +112,7 @@ void ScriptLanguageExtension::_bind_methods() {
GDVIRTUAL_BIND(_can_make_function);
GDVIRTUAL_BIND(_open_in_external_editor, "script", "line", "column");
GDVIRTUAL_BIND(_overrides_external_editor);
+ GDVIRTUAL_BIND(_preferred_file_name_casing);
GDVIRTUAL_BIND(_complete_code, "code", "path", "owner");
GDVIRTUAL_BIND(_lookup_code, "code", "symbol", "path", "owner");
diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h
index aa0788b8bf..18105ec8cd 100644
--- a/core/object/script_language_extension.h
+++ b/core/object/script_language_extension.h
@@ -376,6 +376,7 @@ public:
EXBIND0RC(bool, can_make_function)
EXBIND3R(Error, open_in_external_editor, const Ref<Script> &, int, int)
EXBIND0R(bool, overrides_external_editor)
+ EXBIND0RC(ScriptNameCasing, preferred_file_name_casing)
GDVIRTUAL3RC(Dictionary, _complete_code, const String &, const String &, Object *)
diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml
index 9d36e548a2..d3c76737db 100644
--- a/doc/classes/DisplayServer.xml
+++ b/doc/classes/DisplayServer.xml
@@ -102,8 +102,8 @@
<param index="2" name="existing_text" type="String" />
<param index="3" name="callback" type="Callable" />
<description>
- Shows a text input dialog which uses the operating system's native look-and-feel. [param callback] will be called with a [String] argument equal to the text field's contents when the dialog is closed for any reason.
- [b]Note:[/b] This method is implemented only on macOS.
+ Shows a text input dialog which uses the operating system's native look-and-feel. [param callback] should accept a single [String] parameter which contains the text field's contents.
+ [b]Note:[/b] This method is implemented only on macOS and Windows.
</description>
</method>
<method name="dialog_show">
@@ -113,8 +113,8 @@
<param index="2" name="buttons" type="PackedStringArray" />
<param index="3" name="callback" type="Callable" />
<description>
- Shows a text dialog which uses the operating system's native look-and-feel. [param callback] will be called when the dialog is closed for any reason.
- [b]Note:[/b] This method is implemented only on macOS.
+ Shows a text dialog which uses the operating system's native look-and-feel. [param callback] should accept a single [int] parameter which corresponds to the index of the pressed button.
+ [b]Note:[/b] This method is implemented only on macOS and Windows.
</description>
</method>
<method name="enable_for_stealing_focus">
diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml
index 8a8955e95b..923c22e871 100644
--- a/doc/classes/EditorSettings.xml
+++ b/doc/classes/EditorSettings.xml
@@ -995,6 +995,9 @@
<member name="text_editor/behavior/indent/auto_indent" type="bool" setter="" getter="">
If [code]true[/code], automatically indents code when pressing the [kbd]Enter[/kbd] key based on blocks above the new line.
</member>
+ <member name="text_editor/behavior/indent/indent_wrapped_lines" type="bool" setter="" getter="">
+ If [code]true[/code], all wrapped lines are indented to the same amount as the unwrapped line.
+ </member>
<member name="text_editor/behavior/indent/size" type="int" setter="" getter="">
When using tab indentation, determines the length of each tab. When using space indentation, determines how many spaces are inserted when pressing [kbd]Tab[/kbd] and when automatic indentation is performed.
</member>
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 7c3dfeda4c..6e864316f1 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -948,13 +948,16 @@
The format of the default signal callback name when a signal connects to the same node that emits it (in the Signal Connection Dialog). The following substitutions are available: [code]{NodeName}[/code], [code]{nodeName}[/code], [code]{node_name}[/code], [code]{SignalName}[/code], [code]{signalName}[/code], and [code]{signal_name}[/code].
</member>
<member name="editor/naming/node_name_casing" type="int" setter="" getter="" default="0">
- When creating node names automatically, set the type of casing in this project. This is mostly an editor setting.
+ When creating node names automatically, set the type of casing to use in this project. This is mostly an editor setting.
</member>
<member name="editor/naming/node_name_num_separator" type="int" setter="" getter="" default="0">
What to use to separate node name from number. This is mostly an editor setting.
</member>
<member name="editor/naming/scene_name_casing" type="int" setter="" getter="" default="2">
- When generating file names from scene root node, set the type of casing in this project. This is mostly an editor setting.
+ When generating scene file names from scene root node, set the type of casing to use in this project. This is mostly an editor setting.
+ </member>
+ <member name="editor/naming/script_name_casing" type="int" setter="" getter="" default="0">
+ When generating script file names from the selected node, set the type of casing to use in this project. This is mostly an editor setting.
</member>
<member name="editor/run/main_run_args" type="String" setter="" getter="" default="&quot;&quot;">
The command-line arguments to append to Godot's own command line when running the project. This doesn't affect the editor itself.
diff --git a/doc/classes/ScriptLanguage.xml b/doc/classes/ScriptLanguage.xml
index 51134012c7..0a1b801f9b 100644
--- a/doc/classes/ScriptLanguage.xml
+++ b/doc/classes/ScriptLanguage.xml
@@ -6,4 +6,14 @@
</description>
<tutorials>
</tutorials>
+ <constants>
+ <constant name="SCRIPT_NAME_CASING_AUTO" value="0" enum="ScriptNameCasing">
+ </constant>
+ <constant name="SCRIPT_NAME_CASING_PASCAL_CASE" value="1" enum="ScriptNameCasing">
+ </constant>
+ <constant name="SCRIPT_NAME_CASING_SNAKE_CASE" value="2" enum="ScriptNameCasing">
+ </constant>
+ <constant name="SCRIPT_NAME_CASING_KEBAB_CASE" value="3" enum="ScriptNameCasing">
+ </constant>
+ </constants>
</class>
diff --git a/doc/classes/ScriptLanguageExtension.xml b/doc/classes/ScriptLanguageExtension.xml
index 87d82d8af7..a453866e27 100644
--- a/doc/classes/ScriptLanguageExtension.xml
+++ b/doc/classes/ScriptLanguageExtension.xml
@@ -267,6 +267,11 @@
<description>
</description>
</method>
+ <method name="_preferred_file_name_casing" qualifiers="virtual const">
+ <return type="int" enum="ScriptLanguage.ScriptNameCasing" />
+ <description>
+ </description>
+ </method>
<method name="_profiling_get_accumulated_data" qualifiers="virtual">
<return type="int" />
<param index="0" name="info_array" type="ScriptLanguageExtensionProfilingInfo*" />
diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml
index b8a838208b..04d05e7860 100644
--- a/doc/classes/TextEdit.xml
+++ b/doc/classes/TextEdit.xml
@@ -1154,6 +1154,9 @@
<member name="highlight_current_line" type="bool" setter="set_highlight_current_line" getter="is_highlight_current_line_enabled" default="false">
If [code]true[/code], the line containing the cursor is highlighted.
</member>
+ <member name="indent_wrapped_lines" type="bool" setter="set_indent_wrapped_lines" getter="is_indent_wrapped_lines" default="false">
+ If [code]true[/code], all wrapped lines are indented to the same amount as the unwrapped line.
+ </member>
<member name="language" type="String" setter="set_language" getter="get_language" default="&quot;&quot;">
Language code used for line-breaking and text shaping algorithms, if left empty current locale is used instead.
</member>
diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml
index d4b341b700..9a17fb3def 100644
--- a/doc/classes/TextServer.xml
+++ b/doc/classes/TextServer.xml
@@ -1837,6 +1837,9 @@
<constant name="BREAK_TRIM_EDGE_SPACES" value="16" enum="LineBreakFlag" is_bitfield="true">
Remove edge spaces from the broken line segments.
</constant>
+ <constant name="BREAK_TRIM_INDENT" value="32" enum="LineBreakFlag" is_bitfield="true">
+ Subtract first line indentation width from all lines after the first one.
+ </constant>
<constant name="VC_CHARS_BEFORE_SHAPING" value="0" enum="VisibleCharactersBehavior">
Trims text before the shaping. e.g, increasing [member Label.visible_characters] or [member RichTextLabel.visible_characters] value is visually identical to typing the text.
</constant>
diff --git a/drivers/d3d12/rendering_context_driver_d3d12.cpp b/drivers/d3d12/rendering_context_driver_d3d12.cpp
index ad3b793305..726be064bd 100644
--- a/drivers/d3d12/rendering_context_driver_d3d12.cpp
+++ b/drivers/d3d12/rendering_context_driver_d3d12.cpp
@@ -58,9 +58,10 @@
#endif
// Note: symbols are not available in MinGW and old MSVC import libraries.
-const CLSID CLSID_D3D12DeviceFactoryGodot = __uuidof(ID3D12DeviceFactory);
-const CLSID CLSID_D3D12DebugGodot = __uuidof(ID3D12Debug);
-const CLSID CLSID_D3D12SDKConfigurationGodot = __uuidof(ID3D12SDKConfiguration);
+// GUID values from https://github.com/microsoft/DirectX-Headers/blob/7a9f4d06911d30eecb56a4956dab29dcca2709ed/include/directx/d3d12.idl#L5877-L5881
+const GUID CLSID_D3D12DeviceFactoryGodot = { 0x114863bf, 0xc386, 0x4aee, { 0xb3, 0x9d, 0x8f, 0x0b, 0xbb, 0x06, 0x29, 0x55 } };
+const GUID CLSID_D3D12DebugGodot = { 0xf2352aeb, 0xdd84, 0x49fe, { 0xb9, 0x7b, 0xa9, 0xdc, 0xfd, 0xcc, 0x1b, 0x4f } };
+const GUID CLSID_D3D12SDKConfigurationGodot = { 0x7cda6aca, 0xa03e, 0x49c8, { 0x94, 0x58, 0x03, 0x34, 0xd2, 0x0e, 0x07, 0xce } };
extern "C" {
char godot_nir_arch_name[32];
@@ -83,17 +84,28 @@ RenderingContextDriverD3D12::RenderingContextDriverD3D12() {
}
RenderingContextDriverD3D12::~RenderingContextDriverD3D12() {
+ if (lib_d3d12) {
+ FreeLibrary(lib_d3d12);
+ }
+ if (lib_dxgi) {
+ FreeLibrary(lib_dxgi);
+ }
}
Error RenderingContextDriverD3D12::_init_device_factory() {
uint32_t agility_sdk_version = GLOBAL_GET("rendering/rendering_device/d3d12/agility_sdk_version");
String agility_sdk_path = String(".\\") + Engine::get_singleton()->get_architecture_name();
+ lib_d3d12 = LoadLibraryW(L"D3D12.dll");
+ ERR_FAIL_NULL_V(lib_d3d12, ERR_CANT_CREATE);
+
+ lib_dxgi = LoadLibraryW(L"DXGI.dll");
+ ERR_FAIL_NULL_V(lib_dxgi, ERR_CANT_CREATE);
+
// Note: symbol is not available in MinGW import library.
- PFN_D3D12_GET_INTERFACE d3d_D3D12GetInterface = (PFN_D3D12_GET_INTERFACE)GetProcAddress(LoadLibraryW(L"D3D12.dll"), "D3D12GetInterface");
- if (d3d_D3D12GetInterface == nullptr) {
- // FIXME: Is it intended for this to silently return when it fails to find the symbol?
- return OK;
+ PFN_D3D12_GET_INTERFACE d3d_D3D12GetInterface = (PFN_D3D12_GET_INTERFACE)(void *)GetProcAddress(lib_d3d12, "D3D12GetInterface");
+ if (!d3d_D3D12GetInterface) {
+ return OK; // Fallback to the system loader.
}
ID3D12SDKConfiguration *sdk_config = nullptr;
@@ -109,18 +121,22 @@ Error RenderingContextDriverD3D12::_init_device_factory() {
}
sdk_config->Release();
}
-
return OK;
}
Error RenderingContextDriverD3D12::_initialize_debug_layers() {
ComPtr<ID3D12Debug> debug_controller;
HRESULT res;
+
if (device_factory) {
res = device_factory->GetConfigurationInterface(CLSID_D3D12DebugGodot, IID_PPV_ARGS(&debug_controller));
} else {
- res = D3D12GetDebugInterface(IID_PPV_ARGS(&debug_controller));
+ PFN_D3D12_GET_DEBUG_INTERFACE d3d_D3D12GetDebugInterface = (PFN_D3D12_GET_DEBUG_INTERFACE)(void *)GetProcAddress(lib_d3d12, "D3D12GetDebugInterface");
+ ERR_FAIL_NULL_V(d3d_D3D12GetDebugInterface, ERR_CANT_CREATE);
+
+ res = d3d_D3D12GetDebugInterface(IID_PPV_ARGS(&debug_controller));
}
+
ERR_FAIL_COND_V(!SUCCEEDED(res), ERR_QUERY_FAILED);
debug_controller->EnableDebugLayer();
return OK;
@@ -128,7 +144,12 @@ Error RenderingContextDriverD3D12::_initialize_debug_layers() {
Error RenderingContextDriverD3D12::_initialize_devices() {
const UINT dxgi_factory_flags = use_validation_layers() ? DXGI_CREATE_FACTORY_DEBUG : 0;
- HRESULT res = CreateDXGIFactory2(dxgi_factory_flags, IID_PPV_ARGS(&dxgi_factory));
+
+ typedef HRESULT(WINAPI * PFN_DXGI_CREATE_DXGI_FACTORY2)(UINT, REFIID, void **);
+ PFN_DXGI_CREATE_DXGI_FACTORY2 dxgi_CreateDXGIFactory2 = (PFN_DXGI_CREATE_DXGI_FACTORY2)(void *)GetProcAddress(lib_dxgi, "CreateDXGIFactory2");
+ ERR_FAIL_NULL_V(dxgi_CreateDXGIFactory2, ERR_CANT_CREATE);
+
+ HRESULT res = dxgi_CreateDXGIFactory2(dxgi_factory_flags, IID_PPV_ARGS(&dxgi_factory));
ERR_FAIL_COND_V(!SUCCEEDED(res), ERR_CANT_CREATE);
// Enumerate all possible adapters.
diff --git a/drivers/d3d12/rendering_context_driver_d3d12.h b/drivers/d3d12/rendering_context_driver_d3d12.h
index 694d0b3e4c..f74105ed3d 100644
--- a/drivers/d3d12/rendering_context_driver_d3d12.h
+++ b/drivers/d3d12/rendering_context_driver_d3d12.h
@@ -107,6 +107,9 @@ public:
bool needs_resize = false;
};
+ HMODULE lib_d3d12 = nullptr;
+ HMODULE lib_dxgi = nullptr;
+
IDXGIAdapter1 *create_adapter(uint32_t p_adapter_index) const;
ID3D12DeviceFactory *device_factory_get() const;
IDXGIFactory2 *dxgi_factory_get() const;
diff --git a/drivers/d3d12/rendering_device_driver_d3d12.cpp b/drivers/d3d12/rendering_device_driver_d3d12.cpp
index b4bbc44d93..287726f4db 100644
--- a/drivers/d3d12/rendering_device_driver_d3d12.cpp
+++ b/drivers/d3d12/rendering_device_driver_d3d12.cpp
@@ -3222,7 +3222,7 @@ Vector<uint8_t> RenderingDeviceDriverD3D12::shader_compile_binary_from_spirv(Vec
root_sig_desc.Init_1_1(root_params.size(), root_params.ptr(), 0, nullptr, root_sig_flags);
ComPtr<ID3DBlob> error_blob;
- HRESULT res = D3DX12SerializeVersionedRootSignature(&root_sig_desc, D3D_ROOT_SIGNATURE_VERSION_1_1, root_sig_blob.GetAddressOf(), error_blob.GetAddressOf());
+ HRESULT res = D3DX12SerializeVersionedRootSignature(context_driver->lib_d3d12, &root_sig_desc, D3D_ROOT_SIGNATURE_VERSION_1_1, root_sig_blob.GetAddressOf(), error_blob.GetAddressOf());
ERR_FAIL_COND_V_MSG(!SUCCEEDED(res), Vector<uint8_t>(),
"Serialization of root signature failed with error " + vformat("0x%08ux", (uint64_t)res) + " and the following message:\n" + String((char *)error_blob->GetBufferPointer(), error_blob->GetBufferSize()));
@@ -3483,7 +3483,10 @@ RDD::ShaderID RenderingDeviceDriverD3D12::shader_create_from_bytecode(const Vect
const uint8_t *root_sig_data_ptr = binptr + read_offset;
- HRESULT res = D3D12CreateRootSignatureDeserializer(root_sig_data_ptr, binary_data.root_signature_len, IID_PPV_ARGS(shader_info_in.root_signature_deserializer.GetAddressOf()));
+ PFN_D3D12_CREATE_ROOT_SIGNATURE_DESERIALIZER d3d_D3D12CreateRootSignatureDeserializer = (PFN_D3D12_CREATE_ROOT_SIGNATURE_DESERIALIZER)(void *)GetProcAddress(context_driver->lib_d3d12, "D3D12CreateRootSignatureDeserializer");
+ ERR_FAIL_NULL_V(d3d_D3D12CreateRootSignatureDeserializer, ShaderID());
+
+ HRESULT res = d3d_D3D12CreateRootSignatureDeserializer(root_sig_data_ptr, binary_data.root_signature_len, IID_PPV_ARGS(shader_info_in.root_signature_deserializer.GetAddressOf()));
ERR_FAIL_COND_V_MSG(!SUCCEEDED(res), ShaderID(), "D3D12CreateRootSignatureDeserializer failed with error " + vformat("0x%08ux", (uint64_t)res) + ".");
read_offset += binary_data.root_signature_len;
@@ -6033,17 +6036,23 @@ Error RenderingDeviceDriverD3D12::_initialize_device() {
HRESULT res;
if (is_in_developer_mode()) {
+ typedef HRESULT(WINAPI * PFN_D3D12_ENABLE_EXPERIMENTAL_FEATURES)(_In_ UINT, _In_count_(NumFeatures) const IID *, _In_opt_count_(NumFeatures) void *, _In_opt_count_(NumFeatures) UINT *);
+ PFN_D3D12_ENABLE_EXPERIMENTAL_FEATURES d3d_D3D12EnableExperimentalFeatures = (PFN_D3D12_ENABLE_EXPERIMENTAL_FEATURES)(void *)GetProcAddress(context_driver->lib_d3d12, "D3D12EnableExperimentalFeatures");
+ ERR_FAIL_NULL_V(d3d_D3D12EnableExperimentalFeatures, ERR_CANT_CREATE);
+
UUID experimental_features[] = { D3D12ExperimentalShaderModels };
- D3D12EnableExperimentalFeatures(1, experimental_features, nullptr, nullptr);
+ d3d_D3D12EnableExperimentalFeatures(1, experimental_features, nullptr, nullptr);
}
ID3D12DeviceFactory *device_factory = context_driver->device_factory_get();
if (device_factory != nullptr) {
res = device_factory->CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(device.GetAddressOf()));
} else {
- res = D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(device.GetAddressOf()));
- }
+ PFN_D3D12_CREATE_DEVICE d3d_D3D12CreateDevice = (PFN_D3D12_CREATE_DEVICE)(void *)GetProcAddress(context_driver->lib_d3d12, "D3D12CreateDevice");
+ ERR_FAIL_NULL_V(d3d_D3D12CreateDevice, ERR_CANT_CREATE);
+ res = d3d_D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(device.GetAddressOf()));
+ }
ERR_FAIL_COND_V_MSG(!SUCCEEDED(res), ERR_CANT_CREATE, "D3D12CreateDevice failed with error " + vformat("0x%08ux", (uint64_t)res) + ".");
if (context_driver->use_validation_layers()) {
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index a6db90c3f5..d73407d674 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -913,8 +913,7 @@ ivec2 multiview_uv(ivec2 uv) {
uniform highp mat4 world_transform;
uniform mediump float opaque_prepass_threshold;
-#ifndef MODE_RENDER_DEPTH
-#ifdef RENDER_MATERIAL
+#if defined(RENDER_MATERIAL)
layout(location = 0) out vec4 albedo_output_buffer;
layout(location = 1) out vec4 normal_output_buffer;
layout(location = 2) out vec4 orm_output_buffer;
@@ -925,7 +924,6 @@ layout(location = 3) out vec4 emission_output_buffer;
layout(location = 0) out vec4 frag_color;
#endif // !RENDER_MATERIAL
-#endif // !MODE_RENDER_DEPTH
vec3 F0(float metallic, float specular, vec3 albedo) {
float dielectric = 0.16 * specular * specular;
diff --git a/drivers/gles3/storage/light_storage.cpp b/drivers/gles3/storage/light_storage.cpp
index 2259c61e5b..f5d1f8dabd 100644
--- a/drivers/gles3/storage/light_storage.cpp
+++ b/drivers/gles3/storage/light_storage.cpp
@@ -541,6 +541,10 @@ void LightStorage::reflection_probe_instance_free(RID p_instance) {
void LightStorage::reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) {
}
+bool LightStorage::reflection_probe_has_atlas_index(RID p_instance) {
+ return false;
+}
+
void LightStorage::reflection_probe_release_atlas_index(RID p_instance) {
}
diff --git a/drivers/gles3/storage/light_storage.h b/drivers/gles3/storage/light_storage.h
index a6b236f3ec..51c5c48106 100644
--- a/drivers/gles3/storage/light_storage.h
+++ b/drivers/gles3/storage/light_storage.h
@@ -601,6 +601,7 @@ public:
virtual RID reflection_probe_instance_create(RID p_probe) override;
virtual void reflection_probe_instance_free(RID p_instance) override;
virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) override;
+ virtual bool reflection_probe_has_atlas_index(RID p_instance) override;
virtual void reflection_probe_release_atlas_index(RID p_instance) override;
virtual bool reflection_probe_instance_needs_redraw(RID p_instance) override;
virtual bool reflection_probe_instance_has_reflection(RID p_instance) override;
diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp
index ffbad4c83b..5d2bc44377 100644
--- a/drivers/gles3/storage/texture_storage.cpp
+++ b/drivers/gles3/storage/texture_storage.cpp
@@ -1183,7 +1183,7 @@ Ref<Image> TextureStorage::texture_2d_layer_get(RID p_texture, int p_layer) cons
return image;
}
-Vector<Ref<Image>> TextureStorage::_texture_3d_read_framebuffer(Texture *p_texture) const {
+Vector<Ref<Image>> TextureStorage::_texture_3d_read_framebuffer(GLES3::Texture *p_texture) const {
ERR_FAIL_NULL_V(p_texture, Vector<Ref<Image>>());
Vector<Ref<Image>> ret;
@@ -1610,7 +1610,7 @@ void TextureStorage::_texture_set_3d_data(RID p_texture, const Vector<Ref<Image>
#endif
}
-void TextureStorage::_texture_set_swizzle(Texture *p_texture, Image::Format p_real_format) {
+void TextureStorage::_texture_set_swizzle(GLES3::Texture *p_texture, Image::Format p_real_format) {
#ifndef WEB_ENABLED
switch (p_texture->format) {
case Image::FORMAT_L8: {
diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp
index 5154d2e0e0..7856d454d0 100644
--- a/editor/action_map_editor.cpp
+++ b/editor/action_map_editor.cpp
@@ -380,6 +380,10 @@ LineEdit *ActionMapEditor::get_search_box() const {
return action_list_search;
}
+LineEdit *ActionMapEditor::get_path_box() const {
+ return add_edit;
+}
+
InputEventConfigurationDialog *ActionMapEditor::get_configuration_dialog() {
return event_config_dialog;
}
diff --git a/editor/action_map_editor.h b/editor/action_map_editor.h
index 2848d23e83..2b329f2fca 100644
--- a/editor/action_map_editor.h
+++ b/editor/action_map_editor.h
@@ -118,6 +118,7 @@ protected:
public:
LineEdit *get_search_box() const;
+ LineEdit *get_path_box() const;
InputEventConfigurationDialog *get_configuration_dialog();
// Dictionary represents an Action with "events" (Array) and "deadzone" (float) items. Pass with no param to update list from cached action map.
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index 08299da260..6c16951186 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -1036,6 +1036,7 @@ void CodeTextEditor::update_editor_settings() {
set_indent_using_spaces(EDITOR_GET("text_editor/behavior/indent/type"));
text_editor->set_indent_size(EDITOR_GET("text_editor/behavior/indent/size"));
text_editor->set_auto_indent_enabled(EDITOR_GET("text_editor/behavior/indent/auto_indent"));
+ text_editor->set_indent_wrapped_lines(EDITOR_GET("text_editor/behavior/indent/indent_wrapped_lines"));
// Completion
text_editor->set_auto_brace_completion_enabled(EDITOR_GET("text_editor/completion/auto_brace_complete"));
diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp
index 0e46990b41..a7b15e50d7 100644
--- a/editor/editor_autoload_settings.cpp
+++ b/editor/editor_autoload_settings.cpp
@@ -166,7 +166,7 @@ void EditorAutoloadSettings::_autoload_add() {
if (!fpath.ends_with("/")) {
fpath = fpath.get_base_dir();
}
- dialog->config("Node", fpath.path_join(vformat("%s.gd", autoload_add_name->get_text().to_snake_case())), false, false);
+ dialog->config("Node", fpath.path_join(vformat("%s.gd", autoload_add_name->get_text())), false, false);
dialog->popup_centered();
} else {
if (autoload_add(autoload_add_name->get_text(), autoload_add_path->get_text())) {
@@ -587,6 +587,10 @@ void EditorAutoloadSettings::_script_created(Ref<Script> p_script) {
_autoload_add();
}
+LineEdit *EditorAutoloadSettings::get_path_box() const {
+ return autoload_add_path;
+}
+
Variant EditorAutoloadSettings::get_drag_data_fw(const Point2 &p_point, Control *p_control) {
if (autoload_cache.size() <= 1) {
return false;
diff --git a/editor/editor_autoload_settings.h b/editor/editor_autoload_settings.h
index 11d7cdbe4d..e4ac62e700 100644
--- a/editor/editor_autoload_settings.h
+++ b/editor/editor_autoload_settings.h
@@ -108,6 +108,8 @@ public:
bool autoload_add(const String &p_name, const String &p_path);
void autoload_remove(const String &p_name);
+ LineEdit *get_path_box() const;
+
EditorAutoloadSettings();
~EditorAutoloadSettings();
};
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 44c9afebb6..7de3f58997 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -3089,17 +3089,40 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
}
}
-String EditorNode::adjust_scene_name_casing(const String &root_name) {
+String EditorNode::adjust_scene_name_casing(const String &p_root_name) {
switch (GLOBAL_GET("editor/naming/scene_name_casing").operator int()) {
case SCENE_NAME_CASING_AUTO:
// Use casing of the root node.
break;
case SCENE_NAME_CASING_PASCAL_CASE:
- return root_name.to_pascal_case();
+ return p_root_name.replace("-", "_").to_pascal_case();
case SCENE_NAME_CASING_SNAKE_CASE:
- return root_name.replace("-", "_").to_snake_case();
+ return p_root_name.replace("-", "_").to_snake_case();
+ case SCENE_NAME_CASING_KEBAB_CASE:
+ return p_root_name.to_snake_case().replace("_", "-");
}
- return root_name;
+ return p_root_name;
+}
+
+String EditorNode::adjust_script_name_casing(const String &p_file_name, ScriptLanguage::ScriptNameCasing p_auto_casing) {
+ int editor_casing = GLOBAL_GET("editor/naming/script_name_casing");
+ if (editor_casing == ScriptLanguage::SCRIPT_NAME_CASING_AUTO) {
+ // Use the script language's preferred casing.
+ editor_casing = p_auto_casing;
+ }
+
+ switch (editor_casing) {
+ case ScriptLanguage::SCRIPT_NAME_CASING_AUTO:
+ // Script language has no preference, so do not adjust.
+ break;
+ case ScriptLanguage::SCRIPT_NAME_CASING_PASCAL_CASE:
+ return p_file_name.replace("-", "_").to_pascal_case();
+ case ScriptLanguage::SCRIPT_NAME_CASING_SNAKE_CASE:
+ return p_file_name.replace("-", "_").to_snake_case();
+ case ScriptLanguage::SCRIPT_NAME_CASING_KEBAB_CASE:
+ return p_file_name.to_snake_case().replace("_", "-");
+ }
+ return p_file_name;
}
void EditorNode::_request_screenshot() {
diff --git a/editor/editor_node.h b/editor/editor_node.h
index d44f7b3bb4..b479626648 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -31,6 +31,7 @@
#ifndef EDITOR_NODE_H
#define EDITOR_NODE_H
+#include "core/object/script_language.h"
#include "core/templates/safe_refcount.h"
#include "editor/editor_data.h"
#include "editor/editor_folding.h"
@@ -135,7 +136,8 @@ public:
enum SceneNameCasing {
SCENE_NAME_CASING_AUTO,
SCENE_NAME_CASING_PASCAL_CASE,
- SCENE_NAME_CASING_SNAKE_CASE
+ SCENE_NAME_CASING_SNAKE_CASE,
+ SCENE_NAME_CASING_KEBAB_CASE,
};
struct ExecuteThreadArgs {
@@ -689,7 +691,8 @@ public:
static VSplitContainer *get_top_split() { return singleton->top_split; }
static EditorBottomPanel *get_bottom_panel() { return singleton->bottom_panel; }
- static String adjust_scene_name_casing(const String &root_name);
+ static String adjust_scene_name_casing(const String &p_root_name);
+ static String adjust_script_name_casing(const String &p_file_name, ScriptLanguage::ScriptNameCasing p_auto_casing);
static bool has_unsaved_changes() { return singleton->unsaved_cache; }
static void disambiguate_filenames(const Vector<String> p_full_paths, Vector<String> &r_filenames);
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index c39912d772..d0b633b136 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -631,6 +631,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "text_editor/behavior/indent/type", 0, "Tabs,Spaces")
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "text_editor/behavior/indent/size", 4, "1,64,1") // size of 0 crashes.
_initial_set("text_editor/behavior/indent/auto_indent", true);
+ _initial_set("text_editor/behavior/indent/indent_wrapped_lines", true);
// Behavior: Files
_initial_set("text_editor/behavior/files/trim_trailing_whitespace_on_save", false);
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index a7e40ce5b9..88fed16db1 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -2575,6 +2575,11 @@ void FileSystemDock::fix_dependencies(const String &p_for_file) {
deps_editor->edit(p_for_file);
}
+void FileSystemDock::focus_on_path() {
+ current_path_line_edit->grab_focus();
+ current_path_line_edit->select_all();
+}
+
void FileSystemDock::focus_on_filter() {
LineEdit *current_search_box = nullptr;
if (display_mode == DISPLAY_MODE_TREE_ONLY) {
@@ -3398,6 +3403,8 @@ void FileSystemDock::_tree_gui_input(Ref<InputEvent> p_event) {
_tree_rmb_option(FILE_OPEN_EXTERNAL);
} else if (ED_IS_SHORTCUT("filesystem_dock/open_in_terminal", p_event)) {
_tree_rmb_option(FILE_OPEN_IN_TERMINAL);
+ } else if (ED_IS_SHORTCUT("file_dialog/focus_path", p_event)) {
+ focus_on_path();
} else if (ED_IS_SHORTCUT("editor/open_search", p_event)) {
focus_on_filter();
} else {
diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h
index 06bf3eda52..acb7ca017b 100644
--- a/editor/filesystem_dock.h
+++ b/editor/filesystem_dock.h
@@ -386,6 +386,7 @@ public:
String get_current_directory() const;
void navigate_to_path(const String &p_path);
+ void focus_on_path();
void focus_on_filter();
ScriptCreateDialog *get_script_create_dialog() const;
diff --git a/editor/group_settings_editor.cpp b/editor/group_settings_editor.cpp
index 634192ab50..da169b36b2 100644
--- a/editor/group_settings_editor.cpp
+++ b/editor/group_settings_editor.cpp
@@ -483,6 +483,10 @@ void GroupSettingsEditor::_show_rename_dialog() {
rename_group->grab_focus();
}
+LineEdit *GroupSettingsEditor::get_name_box() const {
+ return group_name;
+}
+
GroupSettingsEditor::GroupSettingsEditor() {
ProjectSettings::get_singleton()->add_hidden_prefix("global_group/");
diff --git a/editor/group_settings_editor.h b/editor/group_settings_editor.h
index 660c15865e..5be0013e96 100644
--- a/editor/group_settings_editor.h
+++ b/editor/group_settings_editor.h
@@ -90,6 +90,7 @@ protected:
static void _bind_methods();
public:
+ LineEdit *get_name_box() const;
void show_message(const String &p_message);
void remove_references(const StringName &p_name);
diff --git a/editor/gui/editor_file_dialog.cpp b/editor/gui/editor_file_dialog.cpp
index d0b78a35cf..fe86ac442b 100644
--- a/editor/gui/editor_file_dialog.cpp
+++ b/editor/gui/editor_file_dialog.cpp
@@ -224,6 +224,7 @@ void EditorFileDialog::shortcut_input(const Ref<InputEvent> &p_event) {
}
if (ED_IS_SHORTCUT("file_dialog/focus_path", p_event)) {
dir->grab_focus();
+ dir->select_all();
handled = true;
}
if (ED_IS_SHORTCUT("file_dialog/move_favorite_up", p_event)) {
@@ -1783,7 +1784,10 @@ EditorFileDialog::EditorFileDialog() {
ED_SHORTCUT("file_dialog/toggle_mode", TTR("Toggle Mode"), KeyModifierMask::ALT | Key::V);
ED_SHORTCUT("file_dialog/create_folder", TTR("Create Folder"), KeyModifierMask::CMD_OR_CTRL | Key::N);
ED_SHORTCUT("file_dialog/delete", TTR("Delete"), Key::KEY_DELETE);
- ED_SHORTCUT("file_dialog/focus_path", TTR("Focus Path"), KeyModifierMask::CMD_OR_CTRL | Key::D);
+ ED_SHORTCUT("file_dialog/focus_path", TTR("Focus Path"), KeyModifierMask::CMD_OR_CTRL | Key::L);
+ // Allow both Cmd + L and Cmd + Shift + G to match Safari's and Finder's shortcuts respectively.
+ ED_SHORTCUT_OVERRIDE_ARRAY("file_dialog/focus_path", "macos",
+ { int32_t(KeyModifierMask::META | Key::L), int32_t(KeyModifierMask::META | KeyModifierMask::SHIFT | Key::G) });
ED_SHORTCUT("file_dialog/move_favorite_up", TTR("Move Favorite Up"), KeyModifierMask::CMD_OR_CTRL | Key::UP);
ED_SHORTCUT("file_dialog/move_favorite_down", TTR("Move Favorite Down"), KeyModifierMask::CMD_OR_CTRL | Key::DOWN);
diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp
index b7f28068b7..57fbbecb60 100644
--- a/editor/project_settings_editor.cpp
+++ b/editor/project_settings_editor.cpp
@@ -256,11 +256,16 @@ void ProjectSettingsEditor::shortcut_input(const Ref<InputEvent> &p_event) {
handled = true;
}
- if (k->is_match(InputEventKey::create_reference(KeyModifierMask::CMD_OR_CTRL | Key::F))) {
+ if (ED_IS_SHORTCUT("editor/open_search", p_event)) {
_focus_current_search_box();
handled = true;
}
+ if (ED_IS_SHORTCUT("file_dialog/focus_path", p_event)) {
+ _focus_current_path_box();
+ handled = true;
+ }
+
if (handled) {
set_input_as_handled();
}
@@ -347,6 +352,27 @@ void ProjectSettingsEditor::_focus_current_search_box() {
}
}
+void ProjectSettingsEditor::_focus_current_path_box() {
+ Control *tab = tab_container->get_current_tab_control();
+ LineEdit *current_path_box = nullptr;
+ if (tab == general_editor) {
+ current_path_box = property_box;
+ } else if (tab == action_map_editor) {
+ current_path_box = action_map_editor->get_path_box();
+ } else if (tab == autoload_settings) {
+ current_path_box = autoload_settings->get_path_box();
+ } else if (tab == shaders_global_shader_uniforms_editor) {
+ current_path_box = shaders_global_shader_uniforms_editor->get_name_box();
+ } else if (tab == group_settings) {
+ current_path_box = group_settings->get_name_box();
+ }
+
+ if (current_path_box) {
+ current_path_box->grab_focus();
+ current_path_box->select_all();
+ }
+}
+
void ProjectSettingsEditor::_editor_restart() {
ProjectSettings::get_singleton()->save();
EditorNode::get_singleton()->save_all_scenes();
diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h
index 7771bdda61..3107c18406 100644
--- a/editor/project_settings_editor.h
+++ b/editor/project_settings_editor.h
@@ -97,6 +97,7 @@ class ProjectSettingsEditor : public AcceptDialog {
void _tabs_tab_changed(int p_tab);
void _focus_current_search_box();
+ void _focus_current_path_box();
void _editor_restart_request();
void _editor_restart();
diff --git a/editor/register_editor_types.cpp b/editor/register_editor_types.cpp
index ab8aa4b68f..610ad3efdf 100644
--- a/editor/register_editor_types.cpp
+++ b/editor/register_editor_types.cpp
@@ -30,6 +30,7 @@
#include "register_editor_types.h"
+#include "core/object/script_language.h"
#include "editor/debugger/debug_adapter/debug_adapter_server.h"
#include "editor/editor_command_palette.h"
#include "editor/editor_feature_profile.h"
@@ -269,7 +270,8 @@ void register_editor_types() {
GLOBAL_DEF("editor/naming/default_signal_callback_name", "_on_{node_name}_{signal_name}");
GLOBAL_DEF("editor/naming/default_signal_callback_to_self_name", "_on_{signal_name}");
- GLOBAL_DEF(PropertyInfo(Variant::INT, "editor/naming/scene_name_casing", PROPERTY_HINT_ENUM, "Auto,PascalCase,snake_case"), EditorNode::SCENE_NAME_CASING_SNAKE_CASE);
+ GLOBAL_DEF(PropertyInfo(Variant::INT, "editor/naming/scene_name_casing", PROPERTY_HINT_ENUM, "Auto,PascalCase,snake_case,kebab-case"), EditorNode::SCENE_NAME_CASING_SNAKE_CASE);
+ GLOBAL_DEF(PropertyInfo(Variant::INT, "editor/naming/script_name_casing", PROPERTY_HINT_ENUM, "Auto,PascalCase,snake_case,kebab-case"), ScriptLanguage::SCRIPT_NAME_CASING_AUTO);
GLOBAL_DEF("editor/import/reimport_missing_imported_files", true);
GLOBAL_DEF("editor/import/use_multiple_threads", true);
diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp
index d111fe8f36..6ca128138e 100644
--- a/editor/script_create_dialog.cpp
+++ b/editor/script_create_dialog.cpp
@@ -125,7 +125,6 @@ void ScriptCreateDialog::_notification(int p_what) {
for (int i = 0; i < language_menu->get_item_count(); i++) {
if (language_menu->get_item_text(i) == last_language) {
language_menu->select(i);
- current_language = i;
break;
}
}
@@ -146,8 +145,8 @@ void ScriptCreateDialog::_notification(int p_what) {
void ScriptCreateDialog::_path_hbox_sorted() {
if (is_visible()) {
- int filename_start_pos = initial_bp.rfind("/") + 1;
- int filename_end_pos = initial_bp.length();
+ int filename_start_pos = file_path->get_text().rfind("/") + 1;
+ int filename_end_pos = file_path->get_text().length();
if (!is_built_in) {
file_path->select(filename_start_pos, filename_end_pos);
@@ -166,26 +165,30 @@ bool ScriptCreateDialog::_can_be_built_in() {
return (supports_built_in && built_in_enabled);
}
+String ScriptCreateDialog::_adjust_file_path(const String &p_base_path) const {
+ if (p_base_path.is_empty()) {
+ return p_base_path;
+ }
+
+ String base_dir = p_base_path.get_base_dir();
+ String file_name = p_base_path.get_file().get_basename();
+ file_name = EditorNode::adjust_script_name_casing(file_name, language->preferred_file_name_casing());
+ String extension = language->get_extension();
+ return base_dir.path_join(file_name + "." + extension);
+}
+
void ScriptCreateDialog::config(const String &p_base_name, const String &p_base_path, bool p_built_in_enabled, bool p_load_enabled) {
parent_name->set_text(p_base_name);
parent_name->deselect();
built_in_name->set_text("");
- if (!p_base_path.is_empty()) {
- initial_bp = p_base_path.get_basename();
- file_path->set_text(initial_bp + "." + ScriptServer::get_language(language_menu->get_selected())->get_extension());
- current_language = language_menu->get_selected();
- } else {
- initial_bp = "";
- file_path->set_text("");
- }
+ file_path->set_text(p_base_path);
file_path->deselect();
built_in_enabled = p_built_in_enabled;
load_enabled = p_load_enabled;
- _language_changed(current_language);
- _path_changed(file_path->get_text());
+ _language_changed(language_menu->get_selected());
}
void ScriptCreateDialog::set_inheritance_base_type(const String &p_base) {
@@ -388,38 +391,9 @@ void ScriptCreateDialog::_language_changed(int l) {
is_built_in = false;
}
- String selected_ext = "." + language->get_extension();
String path = file_path->get_text();
- String extension = "";
- if (!path.is_empty()) {
- if (path.contains(".")) {
- extension = path.get_extension();
- }
-
- if (extension.length() == 0) {
- // Add extension if none.
- path += selected_ext;
- _path_changed(path);
- } else {
- // Change extension by selected language.
- List<String> extensions;
- // Get all possible extensions for script.
- for (int m = 0; m < language_menu->get_item_count(); m++) {
- ScriptServer::get_language(m)->get_recognized_extensions(&extensions);
- }
-
- for (const String &E : extensions) {
- if (E.nocasecmp_to(extension) == 0) {
- path = path.get_basename() + selected_ext;
- _path_changed(path);
- break;
- }
- }
- }
- } else {
- path = "class" + selected_ext;
- _path_changed(path);
- }
+ path = _adjust_file_path(path);
+ _path_changed(path);
file_path->set_text(path);
EditorSettings::get_singleton()->set_project_metadata("script_setup", "last_selected_language", language_menu->get_item_text(language_menu->get_selected()));
@@ -896,7 +870,6 @@ ScriptCreateDialog::ScriptCreateDialog() {
if (default_language >= 0) {
language_menu->select(default_language);
}
- current_language = default_language;
language_menu->connect("item_selected", callable_mp(this, &ScriptCreateDialog::_language_changed));
diff --git a/editor/script_create_dialog.h b/editor/script_create_dialog.h
index 66301ea3b9..c8f043b420 100644
--- a/editor/script_create_dialog.h
+++ b/editor/script_create_dialog.h
@@ -71,7 +71,6 @@ class ScriptCreateDialog : public ConfirmationDialog {
bool is_browsing_parent = false;
String path_error;
String template_inactive_message;
- String initial_bp;
bool is_new_script_created = true;
bool is_path_valid = false;
bool supports_built_in = false;
@@ -82,7 +81,6 @@ class ScriptCreateDialog : public ConfirmationDialog {
bool is_using_templates = true;
bool built_in_enabled = true;
bool load_enabled = true;
- int current_language;
int default_language;
bool re_check_path = false;
@@ -117,6 +115,7 @@ class ScriptCreateDialog : public ConfirmationDialog {
Vector<ScriptLanguage::ScriptTemplate> _get_user_templates(const ScriptLanguage *p_language, const StringName &p_object, const String &p_dir, const ScriptLanguage::TemplateLocation &p_origin) const;
ScriptLanguage::ScriptTemplate _parse_template(const ScriptLanguage *p_language, const String &p_path, const String &p_filename, const ScriptLanguage::TemplateLocation &p_origin, const String &p_inherits) const;
String _get_script_origin_label(const ScriptLanguage::TemplateLocation &p_origin) const;
+ String _adjust_file_path(const String &p_base_path) const;
protected:
void _notification(int p_what);
diff --git a/editor/shader_globals_editor.cpp b/editor/shader_globals_editor.cpp
index 46f520df45..97f6ce2215 100644
--- a/editor/shader_globals_editor.cpp
+++ b/editor/shader_globals_editor.cpp
@@ -356,6 +356,10 @@ String ShaderGlobalsEditor::_check_new_variable_name(const String &p_variable_na
return "";
}
+LineEdit *ShaderGlobalsEditor::get_name_box() const {
+ return variable_name;
+}
+
void ShaderGlobalsEditor::_variable_name_text_changed(const String &p_variable_name) {
const String &warning = _check_new_variable_name(p_variable_name.strip_edges());
variable_add->set_tooltip_text(warning);
diff --git a/editor/shader_globals_editor.h b/editor/shader_globals_editor.h
index fc50564aae..de871f76bf 100644
--- a/editor/shader_globals_editor.h
+++ b/editor/shader_globals_editor.h
@@ -61,6 +61,8 @@ protected:
void _notification(int p_what);
public:
+ LineEdit *get_name_box() const;
+
ShaderGlobalsEditor();
~ShaderGlobalsEditor();
};
diff --git a/godot.manifest b/godot.manifest
new file mode 100644
index 0000000000..30b80aff25
--- /dev/null
+++ b/godot.manifest
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+ <dependency>
+ <dependentAssembly>
+ <assemblyIdentity
+ type='win32'
+ name='Microsoft.Windows.Common-Controls'
+ version='6.0.0.0' processorArchitecture='*'
+ publicKeyToken='6595b64144ccf1df'
+ language='*'/>
+ </dependentAssembly>
+ </dependency>
+</assembly>
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 9ccaa27e84..93fb5f1dc6 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -405,6 +405,10 @@ bool CSharpLanguage::supports_builtin_mode() const {
return false;
}
+ScriptLanguage::ScriptNameCasing CSharpLanguage::preferred_file_name_casing() const {
+ return SCRIPT_NAME_CASING_PASCAL_CASE;
+}
+
#ifdef TOOLS_ENABLED
struct VariantCsName {
Variant::Type variant_type;
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index 99e6ebf2e3..7821420620 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -518,6 +518,7 @@ public:
virtual String _get_indentation() const;
/* TODO? */ void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const override {}
/* TODO */ void add_global_constant(const StringName &p_variable, const Variant &p_value) override {}
+ virtual ScriptNameCasing preferred_file_name_casing() const override;
/* SCRIPT GLOBAL CLASS FUNCTIONS */
virtual bool handles_global_class_type(const String &p_type) const override;
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index ea88278a17..3da19aaee8 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -5360,11 +5360,14 @@ bool TextServerAdvanced::_shaped_text_update_breaks(const RID &p_shaped) {
// No data loaded - use fallback.
for (int j = r_start; j < r_end; j++) {
char32_t c = sd->text[j - sd->start];
+ char32_t c_next = (j < r_end) ? sd->text[j - sd->start + 1] : 0x0000;
if (is_whitespace(c)) {
sd->breaks[j + 1] = false;
}
if (is_linebreak(c)) {
- sd->breaks[j + 1] = true;
+ if (c != 0x000D || c_next != 0x000A) { // Skip first hard break in CR-LF pair.
+ sd->breaks[j + 1] = true;
+ }
}
}
} else {
diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp
index f2d70db7a4..7e34de0bbc 100644
--- a/modules/text_server_fb/text_server_fb.cpp
+++ b/modules/text_server_fb/text_server_fb.cpp
@@ -3617,6 +3617,7 @@ bool TextServerFallback::_shaped_text_update_breaks(const RID &p_shaped) {
for (int i = 0; i < sd_size; i++) {
if (sd_glyphs[i].count > 0) {
char32_t c = sd->text[sd_glyphs[i].start - sd->start];
+ char32_t c_next = i < sd_size ? sd->text[sd_glyphs[i].start - sd->start + 1] : 0x0000;
if (c_punct_size == 0) {
if (is_punct(c) && c != 0x005F && c != ' ') {
sd_glyphs[i].flags |= GRAPHEME_IS_PUNCTUATION;
@@ -3640,7 +3641,9 @@ bool TextServerFallback::_shaped_text_update_breaks(const RID &p_shaped) {
}
if (is_linebreak(c)) {
sd_glyphs[i].flags |= GRAPHEME_IS_SPACE;
- sd_glyphs[i].flags |= GRAPHEME_IS_BREAK_HARD;
+ if (c != 0x000D || c_next != 0x000A) { // Skip first hard break in CR-LF pair.
+ sd_glyphs[i].flags |= GRAPHEME_IS_BREAK_HARD;
+ }
}
if (c == 0x0009 || c == 0x000b) {
sd_glyphs[i].flags |= GRAPHEME_IS_TAB;
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index ca81bb615e..196beb423f 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -202,7 +202,9 @@ def get_opts():
BoolVariable("use_asan", "Use address sanitizer (ASAN)", False),
BoolVariable("debug_crt", "Compile with MSVC's debug CRT (/MDd)", False),
BoolVariable("incremental_link", "Use MSVC incremental linking. May increase or decrease build times.", False),
- BoolVariable("silence_msvc", "Silence MSVC's stdout. Decreases output log bloat by roughly half.", True),
+ BoolVariable(
+ "silence_msvc", "Silence MSVC's stdout to decrease output log bloat. May hide error messages.", False
+ ),
("angle_libs", "Path to the ANGLE static libraries", ""),
# Direct3D 12 support.
(
@@ -437,6 +439,10 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
else:
print("Missing environment variable: WindowsSdkDir")
+ if int(env["target_win_version"], 16) < 0x0601:
+ print("`target_win_version` should be 0x0601 or higher (Windows 7).")
+ sys.exit(255)
+
env.AppendUnique(
CPPDEFINES=[
"WINDOWS_ENABLED",
@@ -501,7 +507,7 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
sys.exit(255)
env.AppendUnique(CPPDEFINES=["D3D12_ENABLED", "RD_ENABLED"])
- LIBS += ["d3d12", "dxgi", "dxguid"]
+ LIBS += ["dxgi", "dxguid"]
LIBS += ["version"] # Mesa dependency.
# Needed for avoiding C1128.
@@ -666,6 +672,10 @@ def configure_mingw(env: "SConsEnvironment"):
## Compile flags
+ if int(env["target_win_version"], 16) < 0x0601:
+ print("`target_win_version` should be 0x0601 or higher (Windows 7).")
+ sys.exit(255)
+
if not env["use_llvm"]:
env.Append(CCFLAGS=["-mwindows"])
@@ -726,7 +736,7 @@ def configure_mingw(env: "SConsEnvironment"):
sys.exit(255)
env.AppendUnique(CPPDEFINES=["D3D12_ENABLED", "RD_ENABLED"])
- env.Append(LIBS=["d3d12", "dxgi", "dxguid"])
+ env.Append(LIBS=["dxgi", "dxguid"])
# PIX
if not env["arch"] in ["x86_64", "arm64"] or env["pix_path"] == "" or not os.path.exists(env["pix_path"]):
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index ced8dce65a..ada9202207 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -2490,6 +2490,299 @@ void DisplayServerWindows::enable_for_stealing_focus(OS::ProcessID pid) {
AllowSetForegroundWindow(pid);
}
+static HRESULT CALLBACK win32_task_dialog_callback(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, LONG_PTR lpRefData) {
+ if (msg == TDN_CREATED) {
+ // To match the input text dialog.
+ SendMessageW(hwnd, WM_SETICON, ICON_BIG, 0);
+ SendMessageW(hwnd, WM_SETICON, ICON_SMALL, 0);
+ }
+
+ return 0;
+}
+
+Error DisplayServerWindows::dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback) {
+ _THREAD_SAFE_METHOD_
+
+ TASKDIALOGCONFIG config;
+ ZeroMemory(&config, sizeof(TASKDIALOGCONFIG));
+ config.cbSize = sizeof(TASKDIALOGCONFIG);
+
+ Char16String title = p_title.utf16();
+ Char16String message = p_description.utf16();
+ List<Char16String> buttons;
+ for (String s : p_buttons) {
+ buttons.push_back(s.utf16());
+ }
+
+ config.pszWindowTitle = (LPCWSTR)(title.get_data());
+ config.pszContent = (LPCWSTR)(message.get_data());
+
+ const int button_count = MIN(buttons.size(), 8);
+ config.cButtons = button_count;
+
+ // No dynamic stack array size :(
+ TASKDIALOG_BUTTON *tbuttons = button_count != 0 ? (TASKDIALOG_BUTTON *)alloca(sizeof(TASKDIALOG_BUTTON) * button_count) : nullptr;
+ if (tbuttons) {
+ for (int i = 0; i < button_count; i++) {
+ tbuttons[i].nButtonID = i;
+ tbuttons[i].pszButtonText = (LPCWSTR)(buttons[i].get_data());
+ }
+ }
+ config.pButtons = tbuttons;
+ config.pfCallback = win32_task_dialog_callback;
+
+ HMODULE comctl = LoadLibraryW(L"comctl32.dll");
+ if (comctl) {
+ typedef HRESULT(WINAPI * TaskDialogIndirectPtr)(const TASKDIALOGCONFIG *pTaskConfig, int *pnButton, int *pnRadioButton, BOOL *pfVerificationFlagChecked);
+
+ TaskDialogIndirectPtr task_dialog_indirect = (TaskDialogIndirectPtr)GetProcAddress(comctl, "TaskDialogIndirect");
+ if (task_dialog_indirect) {
+ int button_pressed;
+ if (FAILED(task_dialog_indirect(&config, &button_pressed, nullptr, nullptr))) {
+ return FAILED;
+ }
+
+ if (!p_callback.is_null()) {
+ Variant button = button_pressed;
+ const Variant *args[1] = { &button };
+ Variant ret;
+ Callable::CallError ce;
+ p_callback.callp(args, 1, ret, ce);
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_PRINT(vformat("Failed to execute dialog callback: %s.", Variant::get_callable_error_text(p_callback, args, 1, ce)));
+ }
+ }
+
+ return OK;
+ }
+ FreeLibrary(comctl);
+ }
+
+ ERR_PRINT("Unable to create native dialog.");
+ return FAILED;
+}
+
+struct Win32InputTextDialogInit {
+ const char16_t *title;
+ const char16_t *description;
+ const char16_t *partial;
+ const Callable &callback;
+};
+
+static constexpr int scale_with_dpi(int p_pos, int p_dpi) {
+ return IsProcessDPIAware() ? (p_pos * p_dpi / 96) : p_pos;
+}
+
+static INT_PTR input_text_dialog_init(HWND hWnd, UINT code, WPARAM wParam, LPARAM lParam) {
+ Win32InputTextDialogInit init = *(Win32InputTextDialogInit *)lParam;
+ SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LONG_PTR)&init.callback); // Set dialog callback.
+
+ SetWindowTextW(hWnd, (LPCWSTR)init.title);
+
+ const int dpi = DisplayServerWindows::get_singleton()->screen_get_dpi();
+
+ const int margin = scale_with_dpi(7, dpi);
+ const SIZE dlg_size = { scale_with_dpi(300, dpi), scale_with_dpi(50, dpi) };
+
+ int str_len = lstrlenW((LPCWSTR)init.description);
+ SIZE str_size = { dlg_size.cx, 0 };
+ if (str_len > 0) {
+ HDC hdc = GetDC(nullptr);
+ RECT trect = { margin, margin, margin + dlg_size.cx, margin + dlg_size.cy };
+ SelectObject(hdc, (HFONT)SendMessageW(hWnd, WM_GETFONT, 0, 0));
+
+ // `+ margin` adds some space between the static text and the edit field.
+ // Don't scale this with DPI because DPI is already handled by DrawText.
+ str_size.cy = DrawTextW(hdc, (LPCWSTR)init.description, str_len, &trect, DT_LEFT | DT_WORDBREAK | DT_CALCRECT) + margin;
+
+ ReleaseDC(nullptr, hdc);
+ }
+
+ RECT crect, wrect;
+ GetClientRect(hWnd, &crect);
+ GetWindowRect(hWnd, &wrect);
+ int sw = GetSystemMetrics(SM_CXSCREEN);
+ int sh = GetSystemMetrics(SM_CYSCREEN);
+ int new_width = dlg_size.cx + margin * 2 + wrect.right - wrect.left - crect.right;
+ int new_height = dlg_size.cy + margin * 2 + wrect.bottom - wrect.top - crect.bottom + str_size.cy;
+
+ MoveWindow(hWnd, (sw - new_width) / 2, (sh - new_height) / 2, new_width, new_height, true);
+
+ HWND ok_button = GetDlgItem(hWnd, 1);
+ MoveWindow(ok_button,
+ dlg_size.cx + margin - scale_with_dpi(65, dpi),
+ dlg_size.cy + str_size.cy + margin - scale_with_dpi(20, dpi),
+ scale_with_dpi(65, dpi), scale_with_dpi(20, dpi), true);
+
+ HWND description = GetDlgItem(hWnd, 3);
+ MoveWindow(description, margin, margin, dlg_size.cx, str_size.cy, true);
+ SetWindowTextW(description, (LPCWSTR)init.description);
+
+ HWND text_edit = GetDlgItem(hWnd, 2);
+ MoveWindow(text_edit, margin, str_size.cy + margin, dlg_size.cx, scale_with_dpi(20, dpi), true);
+ SetWindowTextW(text_edit, (LPCWSTR)init.partial);
+
+ return TRUE;
+}
+
+static INT_PTR input_text_dialog_cmd_proc(HWND hWnd, UINT code, WPARAM wParam, LPARAM lParam) {
+ if (LOWORD(wParam) == 1) {
+ HWND text_edit = GetDlgItem(hWnd, 2);
+ ERR_FAIL_NULL_V(text_edit, false);
+
+ Char16String text;
+ text.resize(GetWindowTextLengthW(text_edit) + 1);
+ GetWindowTextW(text_edit, (LPWSTR)text.get_data(), text.size());
+
+ const Callable *callback = (const Callable *)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
+ if (callback && callback->is_valid()) {
+ Variant v_result = String((const wchar_t *)text.get_data());
+ Variant ret;
+ Callable::CallError ce;
+ const Variant *args[1] = { &v_result };
+
+ callback->callp(args, 1, ret, ce);
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_PRINT(vformat("Failed to execute input dialog callback: %s.", Variant::get_callable_error_text(*callback, args, 1, ce)));
+ }
+ }
+
+ return EndDialog(hWnd, 0);
+ }
+
+ return false;
+}
+
+static INT_PTR CALLBACK input_text_dialog_proc(HWND hWnd, UINT code, WPARAM wParam, LPARAM lParam) {
+ switch (code) {
+ case WM_INITDIALOG:
+ return input_text_dialog_init(hWnd, code, wParam, lParam);
+
+ case WM_COMMAND:
+ return input_text_dialog_cmd_proc(hWnd, code, wParam, lParam);
+
+ default:
+ return FALSE;
+ }
+}
+
+Error DisplayServerWindows::dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback) {
+#pragma pack(push, 1)
+
+ // NOTE: Use default/placeholder coordinates here. Windows uses its own coordinate system
+ // specifically for dialogs which relies on font sizes instead of pixels.
+ const struct {
+ WORD dlgVer; // must be 1
+ WORD signature; // must be 0xFFFF
+ DWORD helpID;
+ DWORD exStyle;
+ DWORD style;
+ WORD cDlgItems;
+ short x;
+ short y;
+ short cx;
+ short cy;
+ WCHAR menu[1]; // must be 0
+ WCHAR windowClass[7]; // must be "#32770" -- the default window class for dialogs
+ WCHAR title[1]; // must be 0
+ WORD pointsize;
+ WORD weight;
+ BYTE italic;
+ BYTE charset;
+ WCHAR font[13]; // must be "MS Shell Dlg"
+ } template_base = {
+ 1, 0xFFFF, 0, 0,
+ DS_SYSMODAL | DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU,
+ 3, 0, 0, 20, 20, L"", L"#32770", L"", 8, FW_NORMAL, 0, DEFAULT_CHARSET, L"MS Shell Dlg"
+ };
+
+ const struct {
+ DWORD helpID;
+ DWORD exStyle;
+ DWORD style;
+ short x;
+ short y;
+ short cx;
+ short cy;
+ DWORD id;
+ WCHAR windowClass[7]; // must be "Button"
+ WCHAR title[3]; // must be "OK"
+ WORD extraCount;
+ } ok_button = {
+ 0, 0, WS_VISIBLE | BS_DEFPUSHBUTTON, 0, 0, 50, 14, 1, WC_BUTTONW, L"OK", 0
+ };
+ const struct {
+ DWORD helpID;
+ DWORD exStyle;
+ DWORD style;
+ short x;
+ short y;
+ short cx;
+ short cy;
+ DWORD id;
+ WCHAR windowClass[5]; // must be "Edit"
+ WCHAR title[1]; // must be 0
+ WORD extraCount;
+ } text_field = {
+ 0, 0, WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL, 0, 0, 250, 14, 2, WC_EDITW, L"", 0
+ };
+ const struct {
+ DWORD helpID;
+ DWORD exStyle;
+ DWORD style;
+ short x;
+ short y;
+ short cx;
+ short cy;
+ DWORD id;
+ WCHAR windowClass[7]; // must be "Static"
+ WCHAR title[1]; // must be 0
+ WORD extraCount;
+ } static_text = {
+ 0, 0, WS_VISIBLE, 0, 0, 250, 14, 3, WC_STATICW, L"", 0
+ };
+
+#pragma pack(pop)
+
+ // Dialog template
+ const size_t data_size = sizeof(template_base) + (sizeof(template_base) % 4) +
+ sizeof(ok_button) + (sizeof(ok_button) % 4) +
+ sizeof(text_field) + (sizeof(text_field) % 4) +
+ sizeof(static_text) + (sizeof(static_text) % 4);
+
+ void *data_template = memalloc(data_size);
+ ERR_FAIL_NULL_V_MSG(data_template, FAILED, "Unable to allocate memory for the dialog template.");
+ ZeroMemory(data_template, data_size);
+
+ char *current_block = (char *)data_template;
+ CopyMemory(current_block, &template_base, sizeof(template_base));
+ current_block += sizeof(template_base) + (sizeof(template_base) % 4);
+ CopyMemory(current_block, &ok_button, sizeof(ok_button));
+ current_block += sizeof(ok_button) + (sizeof(ok_button) % 4);
+ CopyMemory(current_block, &text_field, sizeof(text_field));
+ current_block += sizeof(text_field) + (sizeof(text_field) % 4);
+ CopyMemory(current_block, &static_text, sizeof(static_text));
+
+ Char16String title16 = p_title.utf16();
+ Char16String description16 = p_description.utf16();
+ Char16String partial16 = p_partial.utf16();
+
+ Win32InputTextDialogInit init = {
+ title16.get_data(), description16.get_data(), partial16.get_data(), p_callback
+ };
+
+ // No modal dialogs for specific windows? Assume main window here.
+ INT_PTR ret = DialogBoxIndirectParamW(hInstance, (LPDLGTEMPLATEW)data_template, nullptr, (DLGPROC)input_text_dialog_proc, (LPARAM)(&init));
+
+ Error result = ret != -1 ? OK : FAILED;
+ memfree(data_template);
+
+ if (result == FAILED) {
+ ERR_PRINT("Unable to create native dialog.");
+ }
+ return result;
+}
+
int DisplayServerWindows::keyboard_get_layout_count() const {
return GetKeyboardLayoutList(0, nullptr);
}
@@ -5256,6 +5549,23 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
}
}
+ HMODULE comctl32 = LoadLibraryW(L"comctl32.dll");
+ if (comctl32) {
+ typedef BOOL(WINAPI * InitCommonControlsExPtr)(_In_ const INITCOMMONCONTROLSEX *picce);
+ InitCommonControlsExPtr init_common_controls_ex = (InitCommonControlsExPtr)GetProcAddress(comctl32, "InitCommonControlsEx");
+
+ // Fails if the incorrect version was loaded. Probably not a big enough deal to print an error about.
+ if (init_common_controls_ex) {
+ INITCOMMONCONTROLSEX icc = {};
+ icc.dwICC = ICC_STANDARD_CLASSES;
+ icc.dwSize = sizeof(INITCOMMONCONTROLSEX);
+ if (!init_common_controls_ex(&icc)) {
+ WARN_PRINT("Unable to initialize Windows common controls. Native dialogs may not work properly.");
+ }
+ }
+ FreeLibrary(comctl32);
+ }
+
memset(&wc, 0, sizeof(WNDCLASSEXW));
wc.cbSize = sizeof(WNDCLASSEXW);
wc.style = CS_OWNDC | CS_DBLCLKS;
diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h
index 81cddec49f..f749185080 100644
--- a/platform/windows/display_server_windows.h
+++ b/platform/windows/display_server_windows.h
@@ -192,6 +192,7 @@ typedef UINT32 PEN_MASK;
#define POINTER_MESSAGE_FLAG_FIRSTBUTTON 0x00000010
#endif
+#if WINVER < 0x0602
enum tagPOINTER_INPUT_TYPE {
PT_POINTER = 0x00000001,
PT_TOUCH = 0x00000002,
@@ -242,6 +243,7 @@ typedef struct tagPOINTER_PEN_INFO {
INT32 tiltX;
INT32 tiltY;
} POINTER_PEN_INFO;
+#endif
#endif //POINTER_STRUCTURES
@@ -642,6 +644,9 @@ public:
virtual void enable_for_stealing_focus(OS::ProcessID pid) override;
+ virtual Error dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback) override;
+ virtual Error dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback) override;
+
virtual int keyboard_get_layout_count() const override;
virtual int keyboard_get_current_layout() const override;
virtual void keyboard_set_current_layout(int p_index) override;
diff --git a/platform/windows/godot_res.rc b/platform/windows/godot_res.rc
index 8187c0c936..86191ad9d9 100644
--- a/platform/windows/godot_res.rc
+++ b/platform/windows/godot_res.rc
@@ -1,6 +1,11 @@
#include "core/version.h"
+#ifndef RT_MANIFEST
+#define RT_MANIFEST 24
+#endif
+
GODOT_ICON ICON platform/windows/godot.ico
+1 RT_MANIFEST "godot.manifest"
1 VERSIONINFO
FILEVERSION VERSION_MAJOR,VERSION_MINOR,VERSION_PATCH,0
diff --git a/scene/3d/label_3d.cpp b/scene/3d/label_3d.cpp
index 718ddd4982..02f40713bf 100644
--- a/scene/3d/label_3d.cpp
+++ b/scene/3d/label_3d.cpp
@@ -422,12 +422,6 @@ void Label3D::_generate_glyph_surfaces(const Glyph &p_glyph, Vector2 &r_offset,
s.mesh_tangents.write[(s.offset * 16) + (i * 4) + 3] = 1.0;
s.mesh_colors.write[(s.offset * 4) + i] = p_modulate;
s.mesh_uvs.write[(s.offset * 4) + i] = Vector2();
-
- if (aabb == AABB()) {
- aabb.position = s.mesh_vertices[(s.offset * 4) + i];
- } else {
- aabb.expand_to(s.mesh_vertices[(s.offset * 4) + i]);
- }
}
if (tex.is_valid()) {
@@ -598,6 +592,13 @@ void Label3D::_shape() {
} break;
}
offset.x += lbl_offset.x * pixel_size;
+ if (aabb == AABB()) {
+ aabb.position = Vector3(offset.x, offset.y, 0);
+ aabb.expand_to(Vector3(offset.x + line_width, offset.y - (TS->shaped_text_get_size(lines_rid[i]).y + line_spacing) * pixel_size, 0));
+ } else {
+ aabb.expand_to(Vector3(offset.x, offset.y, 0));
+ aabb.expand_to(Vector3(offset.x + line_width, offset.y - (TS->shaped_text_get_size(lines_rid[i]).y + line_spacing) * pixel_size, 0));
+ }
offset.y -= TS->shaped_text_get_ascent(lines_rid[i]) * pixel_size;
if (outline_modulate.a != 0.0 && outline_size > 0) {
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index abed3cf594..a53dffd0d2 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -263,6 +263,27 @@ void FileDialog::shortcut_input(const Ref<InputEvent> &p_event) {
case Key::BACKSPACE: {
_dir_submitted("..");
} break;
+#ifdef MACOS_ENABLED
+ // Cmd + Shift + G (matches Finder's "Go To" shortcut).
+ case Key::G: {
+ if (k->is_command_or_control_pressed() && k->is_shift_pressed()) {
+ dir->grab_focus();
+ dir->select_all();
+ } else {
+ handled = false;
+ }
+ } break;
+#endif
+ // Ctrl + L (matches most Windows/Linux file managers' "focus on path bar" shortcut,
+ // plus macOS Safari's "focus on address bar" shortcut).
+ case Key::L: {
+ if (k->is_command_or_control_pressed()) {
+ dir->grab_focus();
+ dir->select_all();
+ } else {
+ handled = false;
+ }
+ } break;
default: {
handled = false;
}
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 7230f87359..5fe26aac06 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -2261,6 +2261,7 @@ void RichTextLabel::gui_input(const Ref<InputEvent> &p_event) {
queue_redraw();
}
+ _find_click(main, m->get_position(), nullptr, nullptr, &c_item, nullptr, &outside, true);
Variant meta;
ItemMeta *item_meta;
ItemMeta *prev_meta = meta_hovering;
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index c2716c9ef6..40bc87846a 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -74,6 +74,18 @@ int TextEdit::Text::get_tab_size() const {
return tab_size;
}
+void TextEdit::Text::set_indent_wrapped_lines(bool p_enabled) {
+ if (indent_wrapped_lines == p_enabled) {
+ return;
+ }
+ indent_wrapped_lines = p_enabled;
+ tab_size_dirty = true;
+}
+
+bool TextEdit::Text::is_indent_wrapped_lines() const {
+ return indent_wrapped_lines;
+}
+
void TextEdit::Text::set_direction_and_language(TextServer::Direction p_direction, const String &p_language) {
if (direction == p_direction && language == p_language) {
return;
@@ -185,9 +197,14 @@ void TextEdit::Text::invalidate_cache(int p_line, int p_column, bool p_text_chan
text.write[p_line].data_buf->clear();
}
+ BitField<TextServer::LineBreakFlag> flags = brk_flags;
+ if (indent_wrapped_lines) {
+ flags.set_flag(TextServer::BREAK_TRIM_INDENT);
+ }
+
text.write[p_line].data_buf->set_width(width);
text.write[p_line].data_buf->set_direction((TextServer::Direction)direction);
- text.write[p_line].data_buf->set_break_flags(brk_flags);
+ text.write[p_line].data_buf->set_break_flags(flags);
text.write[p_line].data_buf->set_preserve_control(draw_control_chars);
if (p_ime_text.length() > 0) {
if (p_text_changed) {
@@ -251,8 +268,12 @@ void TextEdit::Text::invalidate_cache(int p_line, int p_column, bool p_text_chan
void TextEdit::Text::invalidate_all_lines() {
for (int i = 0; i < text.size(); i++) {
+ BitField<TextServer::LineBreakFlag> flags = brk_flags;
+ if (indent_wrapped_lines) {
+ flags.set_flag(TextServer::BREAK_TRIM_INDENT);
+ }
text.write[i].data_buf->set_width(width);
- text.write[i].data_buf->set_break_flags(brk_flags);
+ text.write[i].data_buf->set_break_flags(flags);
if (tab_size_dirty) {
if (tab_size > 0) {
Vector<float> tabs;
@@ -1075,9 +1096,12 @@ void TextEdit::_notification(int p_what) {
// Draw line.
RID rid = ldata->get_line_rid(line_wrap_index);
float text_height = TS->shaped_text_get_size(rid).y;
+ float wrap_indent = (text.is_indent_wrapped_lines() && line_wrap_index > 0) ? get_indent_level(line) * theme_cache.font->get_char_size(' ', theme_cache.font_size).width : 0.0;
if (rtl) {
- char_margin = size.width - char_margin - TS->shaped_text_get_size(rid).x;
+ char_margin = size.width - char_margin - (TS->shaped_text_get_size(rid).x + wrap_indent);
+ } else {
+ char_margin += wrap_indent;
}
// Draw selections.
@@ -2935,7 +2959,11 @@ void TextEdit::_update_placeholder() {
// Placeholder is generally smaller then text documents, and updates less so this should be fast enough for now.
placeholder_data_buf->clear();
placeholder_data_buf->set_width(text.get_width());
- placeholder_data_buf->set_break_flags(text.get_brk_flags());
+ BitField<TextServer::LineBreakFlag> flags = text.get_brk_flags();
+ if (text.is_indent_wrapped_lines()) {
+ flags.set_flag(TextServer::BREAK_TRIM_INDENT);
+ }
+ placeholder_data_buf->set_break_flags(flags);
if (text_direction == Control::TEXT_DIRECTION_INHERITED) {
placeholder_data_buf->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR);
} else {
@@ -3331,6 +3359,20 @@ int TextEdit::get_tab_size() const {
return text.get_tab_size();
}
+void TextEdit::set_indent_wrapped_lines(bool p_enabled) {
+ if (text.is_indent_wrapped_lines() == p_enabled) {
+ return;
+ }
+ text.set_indent_wrapped_lines(p_enabled);
+ text.invalidate_all_lines();
+ _update_placeholder();
+ queue_redraw();
+}
+
+bool TextEdit::is_indent_wrapped_lines() const {
+ return text.is_indent_wrapped_lines();
+}
+
// User controls
void TextEdit::set_overtype_mode_enabled(const bool p_enabled) {
if (overtype_mode == p_enabled) {
@@ -4336,8 +4378,11 @@ Point2i TextEdit::get_line_column_at_pos(const Point2i &p_pos, bool p_allow_out_
}
RID text_rid = text.get_line_data(row)->get_line_rid(wrap_index);
+ float wrap_indent = (text.is_indent_wrapped_lines() && wrap_index > 0) ? get_indent_level(row) * theme_cache.font->get_char_size(' ', theme_cache.font_size).width : 0.0;
if (is_layout_rtl()) {
- colx = TS->shaped_text_get_size(text_rid).x - colx;
+ colx = TS->shaped_text_get_size(text_rid).x - colx + wrap_indent;
+ } else {
+ colx -= wrap_indent;
}
col = TS->shaped_text_hit_test_position(text_rid, colx);
if (!caret_mid_grapheme_enabled) {
@@ -6073,6 +6118,9 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_tab_size", "size"), &TextEdit::set_tab_size);
ClassDB::bind_method(D_METHOD("get_tab_size"), &TextEdit::get_tab_size);
+ ClassDB::bind_method(D_METHOD("set_indent_wrapped_lines", "enabled"), &TextEdit::set_indent_wrapped_lines);
+ ClassDB::bind_method(D_METHOD("is_indent_wrapped_lines"), &TextEdit::is_indent_wrapped_lines);
+
// User controls
ClassDB::bind_method(D_METHOD("set_overtype_mode_enabled", "enabled"), &TextEdit::set_overtype_mode_enabled);
ClassDB::bind_method(D_METHOD("is_overtype_mode_enabled"), &TextEdit::is_overtype_mode_enabled);
@@ -6451,6 +6499,7 @@ void TextEdit::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "middle_mouse_paste_enabled"), "set_middle_mouse_paste_enabled", "is_middle_mouse_paste_enabled");
ADD_PROPERTY(PropertyInfo(Variant::INT, "wrap_mode", PROPERTY_HINT_ENUM, "None,Boundary"), "set_line_wrapping_mode", "get_line_wrapping_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "autowrap_mode", PROPERTY_HINT_ENUM, "Arbitrary:1,Word:2,Word (Smart):3"), "set_autowrap_mode", "get_autowrap_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "indent_wrapped_lines"), "set_indent_wrapped_lines", "is_indent_wrapped_lines");
ADD_GROUP("Scroll", "scroll_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_smooth"), "set_smooth_scroll_enabled", "is_smooth_scroll_enabled");
@@ -7075,8 +7124,11 @@ int TextEdit::_get_char_pos_for_line(int p_px, int p_line, int p_wrap_index) con
p_wrap_index = MIN(p_wrap_index, text.get_line_data(p_line)->get_line_count() - 1);
RID text_rid = text.get_line_data(p_line)->get_line_rid(p_wrap_index);
+ float wrap_indent = (text.is_indent_wrapped_lines() && p_wrap_index > 0) ? get_indent_level(p_line) * theme_cache.font->get_char_size(' ', theme_cache.font_size).width : 0.0;
if (is_layout_rtl()) {
- p_px = TS->shaped_text_get_size(text_rid).x - p_px;
+ p_px = TS->shaped_text_get_size(text_rid).x - p_px + wrap_indent;
+ } else {
+ p_px -= wrap_indent;
}
int ofs = TS->shaped_text_hit_test_position(text_rid, p_px);
if (!caret_mid_grapheme_enabled) {
@@ -7125,11 +7177,12 @@ int TextEdit::_get_column_x_offset_for_line(int p_char, int p_line, int p_column
}
RID text_rid = text.get_line_data(p_line)->get_line_rid(row);
+ float wrap_indent = (text.is_indent_wrapped_lines() && row > 0) ? get_indent_level(p_line) * theme_cache.font->get_char_size(' ', theme_cache.font_size).width : 0.0;
CaretInfo ts_caret = TS->shaped_text_get_carets(text_rid, p_column);
if ((ts_caret.l_caret != Rect2() && (ts_caret.l_dir == TextServer::DIRECTION_AUTO || ts_caret.l_dir == (TextServer::Direction)input_direction)) || (ts_caret.t_caret == Rect2())) {
- return ts_caret.l_caret.position.x;
+ return ts_caret.l_caret.position.x + (is_layout_rtl() ? -wrap_indent : wrap_indent);
} else {
- return ts_caret.t_caret.position.x;
+ return ts_caret.t_caret.position.x + (is_layout_rtl() ? -wrap_indent : wrap_indent);
}
}
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index d49be860a9..b8e30c7900 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -181,6 +181,7 @@ private:
int tab_size = 4;
int gutter_count = 0;
+ bool indent_wrapped_lines = false;
void _calculate_line_height();
void _calculate_max_line_width();
@@ -188,6 +189,9 @@ private:
public:
void set_tab_size(int p_tab_size);
int get_tab_size() const;
+ void set_indent_wrapped_lines(bool p_enabled);
+ bool is_indent_wrapped_lines() const;
+
void set_font(const Ref<Font> &p_font);
void set_font_size(int p_font_size);
void set_direction_and_language(TextServer::Direction p_direction, const String &p_language);
@@ -720,6 +724,9 @@ public:
void set_tab_size(const int p_size);
int get_tab_size() const;
+ void set_indent_wrapped_lines(bool p_enabled);
+ bool is_indent_wrapped_lines() const;
+
// User controls
void set_overtype_mode_enabled(const bool p_enabled);
bool is_overtype_mode_enabled() const;
diff --git a/servers/rendering/dummy/storage/light_storage.h b/servers/rendering/dummy/storage/light_storage.h
index 61a825f8c5..a76305cdaa 100644
--- a/servers/rendering/dummy/storage/light_storage.h
+++ b/servers/rendering/dummy/storage/light_storage.h
@@ -135,6 +135,7 @@ public:
virtual RID reflection_probe_instance_create(RID p_probe) override { return RID(); }
virtual void reflection_probe_instance_free(RID p_instance) override {}
virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) override {}
+ virtual bool reflection_probe_has_atlas_index(RID p_instance) override { return false; }
virtual void reflection_probe_release_atlas_index(RID p_instance) override {}
virtual bool reflection_probe_instance_needs_redraw(RID p_instance) override { return false; }
virtual bool reflection_probe_instance_has_reflection(RID p_instance) override { return false; }
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
index fa6e78750b..33bb5459f2 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -1615,15 +1615,16 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
gi.setup_voxel_gi_instances(p_render_data, p_render_data->render_buffers, p_render_data->scene_data->cam_transform, *p_render_data->voxel_gi_instances, p_render_data->voxel_gi_count);
} else {
- ERR_PRINT("No render buffer nor reflection atlas, bug"); //should never happen, will crash
+ ERR_PRINT("No render buffer nor reflection atlas, bug"); // Should never happen!
current_cluster_builder = nullptr;
+ return; // No point in continuing, we'll just crash.
}
- if (current_cluster_builder != nullptr) {
- p_render_data->cluster_buffer = current_cluster_builder->get_cluster_buffer();
- p_render_data->cluster_size = current_cluster_builder->get_cluster_size();
- p_render_data->cluster_max_elements = current_cluster_builder->get_max_cluster_elements();
- }
+ ERR_FAIL_NULL(current_cluster_builder);
+
+ p_render_data->cluster_buffer = current_cluster_builder->get_cluster_buffer();
+ p_render_data->cluster_size = current_cluster_builder->get_cluster_size();
+ p_render_data->cluster_max_elements = current_cluster_builder->get_max_cluster_elements();
_update_vrs(rb);
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
index 2786af65eb..cf8c29e624 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
@@ -1370,6 +1370,17 @@ void LightStorage::reflection_probe_instance_set_transform(RID p_instance, const
rpi->dirty = true;
}
+bool LightStorage::reflection_probe_has_atlas_index(RID p_instance) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
+ ERR_FAIL_NULL_V(rpi, false);
+
+ if (rpi->atlas.is_null()) {
+ return false;
+ }
+
+ return rpi->atlas_index >= 0;
+}
+
void LightStorage::reflection_probe_release_atlas_index(RID p_instance) {
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
ERR_FAIL_NULL(rpi);
@@ -1384,6 +1395,14 @@ void LightStorage::reflection_probe_release_atlas_index(RID p_instance) {
// TODO investigate if this is enough? shouldn't we be freeing our textures and framebuffers?
+ if (rpi->rendering) {
+ // We were cancelled mid rendering, trigger refresh.
+ rpi->rendering = false;
+ rpi->dirty = true;
+ rpi->processing_layer = 1;
+ rpi->processing_side = 0;
+ }
+
rpi->atlas_index = -1;
rpi->atlas = RID();
}
@@ -1535,11 +1554,10 @@ bool LightStorage::reflection_probe_instance_postprocess_step(RID p_instance) {
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
ERR_FAIL_NULL_V(rpi, false);
ERR_FAIL_COND_V(!rpi->rendering, false);
- ERR_FAIL_COND_V(rpi->atlas.is_null(), false);
ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas);
if (!atlas || rpi->atlas_index == -1) {
- //does not belong to an atlas anymore, cancel (was removed from atlas or atlas changed while rendering)
+ // Does not belong to an atlas anymore, cancel (was removed from atlas or atlas changed while rendering).
rpi->rendering = false;
return false;
}
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h
index b3d27cc6ed..b3d6bf5254 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h
@@ -277,7 +277,6 @@ private:
int processing_layer = 1;
int processing_side = 0;
- uint32_t render_step = 0;
uint64_t last_pass = 0;
uint32_t cull_mask = 0;
@@ -848,6 +847,7 @@ public:
virtual RID reflection_probe_instance_create(RID p_probe) override;
virtual void reflection_probe_instance_free(RID p_instance) override;
virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) override;
+ virtual bool reflection_probe_has_atlas_index(RID p_instance) override;
virtual void reflection_probe_release_atlas_index(RID p_instance) override;
virtual bool reflection_probe_instance_needs_redraw(RID p_instance) override;
virtual bool reflection_probe_instance_has_reflection(RID p_instance) override;
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 59d70958f1..4e5539e6a4 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -3482,8 +3482,13 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
if (p_step == 0) {
if (!RSG::light_storage->reflection_probe_instance_begin_render(reflection_probe->instance, scenario->reflection_atlas)) {
- return true; //all full
+ return true; // All full, no atlas entry to render to.
}
+ } else if (!RSG::light_storage->reflection_probe_has_atlas_index(reflection_probe->instance)) {
+ // We don't have an atlas to render to, just round off.
+ // This is likely due to the atlas being reset.
+ // If so the probe will be marked as dirty and start over.
+ return true;
}
if (p_step >= 0 && p_step < 6) {
@@ -3558,6 +3563,7 @@ void RendererSceneCull::render_probes() {
/* REFLECTION PROBES */
SelfList<InstanceReflectionProbeData> *ref_probe = reflection_probe_render_list.first();
+ Vector<SelfList<InstanceReflectionProbeData> *> done_list;
bool busy = false;
@@ -3573,7 +3579,7 @@ void RendererSceneCull::render_probes() {
bool done = _render_reflection_probe_step(ref_probe->self()->owner, ref_probe->self()->render_step);
if (done) {
- reflection_probe_render_list.remove(ref_probe);
+ done_list.push_back(ref_probe);
} else {
ref_probe->self()->render_step++;
}
@@ -3588,13 +3594,18 @@ void RendererSceneCull::render_probes() {
step++;
}
- reflection_probe_render_list.remove(ref_probe);
+ done_list.push_back(ref_probe);
} break;
}
ref_probe = next;
}
+ // Now remove from our list
+ for (SelfList<InstanceReflectionProbeData> *rp : done_list) {
+ reflection_probe_render_list.remove(rp);
+ }
+
/* VOXEL GIS */
SelfList<InstanceVoxelGIData> *voxel_gi = voxel_gi_update_list.first();
diff --git a/servers/rendering/storage/light_storage.h b/servers/rendering/storage/light_storage.h
index 27407305d1..d439598f3d 100644
--- a/servers/rendering/storage/light_storage.h
+++ b/servers/rendering/storage/light_storage.h
@@ -143,6 +143,7 @@ public:
virtual RID reflection_probe_instance_create(RID p_probe) = 0;
virtual void reflection_probe_instance_free(RID p_instance) = 0;
virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) = 0;
+ virtual bool reflection_probe_has_atlas_index(RID p_instance) = 0;
virtual void reflection_probe_release_atlas_index(RID p_instance) = 0;
virtual bool reflection_probe_instance_needs_redraw(RID p_instance) = 0;
virtual bool reflection_probe_instance_has_reflection(RID p_instance) = 0;
diff --git a/servers/text_server.cpp b/servers/text_server.cpp
index b67a698615..d1dadbc839 100644
--- a/servers/text_server.cpp
+++ b/servers/text_server.cpp
@@ -535,6 +535,7 @@ void TextServer::_bind_methods() {
BIND_BITFIELD_FLAG(BREAK_GRAPHEME_BOUND);
BIND_BITFIELD_FLAG(BREAK_ADAPTIVE);
BIND_BITFIELD_FLAG(BREAK_TRIM_EDGE_SPACES);
+ BIND_BITFIELD_FLAG(BREAK_TRIM_INDENT);
/* VisibleCharactersBehavior */
BIND_ENUM_CONSTANT(VC_CHARS_BEFORE_SHAPING);
@@ -750,13 +751,28 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
int l_size = shaped_text_get_glyph_count(p_shaped);
const Glyph *l_gl = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped);
+ double indent = 0.0;
+ if (p_break_flags.has_flag(BREAK_TRIM_INDENT)) {
+ for (int i = 0; i < l_size; i++) {
+ if ((l_gl[i].flags & GRAPHEME_IS_TAB) == GRAPHEME_IS_TAB || (l_gl[i].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE) {
+ indent += l_gl[i].advance * l_gl[i].repeat;
+ } else {
+ break;
+ }
+ }
+ }
+
for (int i = 0; i < l_size; i++) {
+ double l_width = p_width[chunk];
+ if (l_width > indent) {
+ l_width -= indent;
+ }
if (l_gl[i].start < p_start) {
prev_safe_break = i + 1;
continue;
}
if (l_gl[i].count > 0) {
- if ((p_width[chunk] > 0) && (width + l_gl[i].advance > p_width[chunk]) && (last_safe_break >= 0)) {
+ if ((l_width > 0) && (width + l_gl[i].advance > l_width) && (last_safe_break >= 0)) {
if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) {
int start_pos = prev_safe_break;
int end_pos = last_safe_break;
@@ -891,13 +907,25 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
int l_size = shaped_text_get_glyph_count(p_shaped);
const Glyph *l_gl = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped);
+ double indent = 0.0;
+ if (p_break_flags.has_flag(BREAK_TRIM_INDENT)) {
+ for (int i = 0; i < l_size; i++) {
+ if ((l_gl[i].flags & GRAPHEME_IS_TAB) == GRAPHEME_IS_TAB || (l_gl[i].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE) {
+ indent += l_gl[i].advance * l_gl[i].repeat;
+ } else {
+ break;
+ }
+ }
+ }
+
+ double l_width = p_width;
for (int i = 0; i < l_size; i++) {
if (l_gl[i].start < p_start) {
prev_safe_break = i + 1;
continue;
}
if (l_gl[i].count > 0) {
- if ((p_width > 0) && (width + l_gl[i].advance * l_gl[i].repeat > p_width) && (last_safe_break >= 0)) {
+ if ((l_width > 0) && (width + l_gl[i].advance * l_gl[i].repeat > l_width) && (last_safe_break >= 0)) {
if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) {
int start_pos = prev_safe_break;
int end_pos = last_safe_break;
@@ -910,6 +938,9 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
if (last_end <= l_gl[start_pos].start) {
lines.push_back(l_gl[start_pos].start);
lines.push_back(l_gl[end_pos].end);
+ if (p_width > indent) {
+ l_width = p_width - indent;
+ }
last_end = l_gl[end_pos].end;
}
trim_next = true;
@@ -917,6 +948,9 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
if (last_end <= line_start) {
lines.push_back(line_start);
lines.push_back(l_gl[last_safe_break].end);
+ if (p_width > indent) {
+ l_width = p_width - indent;
+ }
last_end = l_gl[last_safe_break].end;
}
}
@@ -943,12 +977,18 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
if (last_end <= l_gl[start_pos].start) {
lines.push_back(l_gl[start_pos].start);
lines.push_back(l_gl[end_pos].end);
+ if (p_width > indent) {
+ l_width = p_width - indent;
+ }
last_end = l_gl[end_pos].end;
}
} else {
if (last_end <= line_start) {
lines.push_back(line_start);
lines.push_back(l_gl[i].end);
+ if (p_width > indent) {
+ l_width = p_width - indent;
+ }
last_end = l_gl[i].end;
}
}
diff --git a/servers/text_server.h b/servers/text_server.h
index c2cc444646..dfd6140fde 100644
--- a/servers/text_server.h
+++ b/servers/text_server.h
@@ -108,6 +108,7 @@ public:
BREAK_GRAPHEME_BOUND = 1 << 2,
BREAK_ADAPTIVE = 1 << 3,
BREAK_TRIM_EDGE_SPACES = 1 << 4,
+ BREAK_TRIM_INDENT = 1 << 5,
};
enum OverrunBehavior {
diff --git a/thirdparty/directx_headers/include/directx/d3dx12_root_signature.h b/thirdparty/directx_headers/include/directx/d3dx12_root_signature.h
index 572efed852..a83d9d017c 100644
--- a/thirdparty/directx_headers/include/directx/d3dx12_root_signature.h
+++ b/thirdparty/directx_headers/include/directx/d3dx12_root_signature.h
@@ -996,6 +996,9 @@ struct CD3DX12_GPU_DESCRIPTOR_HANDLE : public D3D12_GPU_DESCRIPTOR_HANDLE
// two code paths for building root signatures, this helper method reconstructs a 1.0 signature when
// 1.1 is not supported.
inline HRESULT D3DX12SerializeVersionedRootSignature(
+/* GODOT start */
+ _In_ HMODULE pLibD3D12,
+/* GODOT end */
_In_ const D3D12_VERSIONED_ROOT_SIGNATURE_DESC* pRootSignatureDesc,
D3D_ROOT_SIGNATURE_VERSION MaxVersion,
_Outptr_ ID3DBlob** ppBlob,
@@ -1006,13 +1009,22 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
*ppErrorBlob = nullptr;
}
+ /* GODOT start */
+ PFN_D3D12_SERIALIZE_ROOT_SIGNATURE d3d_D3D12SerializeRootSignature = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)(void *)GetProcAddress(pLibD3D12, "D3D12SerializeRootSignature");
+ if (d3d_D3D12SerializeRootSignature == nullptr) {
+ return E_INVALIDARG;
+ }
+ PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE d3d_D3D12SerializeVersionedRootSignature = (PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE)(void *)GetProcAddress(pLibD3D12, "D3D12SerializeVersionedRootSignature");
+ /* GODOT end */
switch (MaxVersion)
{
case D3D_ROOT_SIGNATURE_VERSION_1_0:
switch (pRootSignatureDesc->Version)
{
case D3D_ROOT_SIGNATURE_VERSION_1_0:
- return D3D12SerializeRootSignature(&pRootSignatureDesc->Desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);
+/* GODOT start */
+ return d3d_D3D12SerializeRootSignature(&pRootSignatureDesc->Desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);
+/* GODOT end */
case D3D_ROOT_SIGNATURE_VERSION_1_1:
#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609)
@@ -1114,7 +1126,9 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
if (SUCCEEDED(hr))
{
const CD3DX12_ROOT_SIGNATURE_DESC desc_1_0(desc_1_1.NumParameters, pParameters_1_0, desc_1_1.NumStaticSamplers, pStaticSamplers == nullptr ? desc_1_1.pStaticSamplers : pStaticSamplers, desc_1_1.Flags);
- hr = D3D12SerializeRootSignature(&desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);
+/* GODOT start */
+ hr = d3d_D3D12SerializeRootSignature(&desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);
+/* GODOT end */
}
if (pParameters)
@@ -1145,7 +1159,9 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
{
case D3D_ROOT_SIGNATURE_VERSION_1_0:
case D3D_ROOT_SIGNATURE_VERSION_1_1:
- return D3D12SerializeVersionedRootSignature(pRootSignatureDesc, ppBlob, ppErrorBlob);
+/* GODOT start */
+ return d3d_D3D12SerializeVersionedRootSignature(pRootSignatureDesc, ppBlob, ppErrorBlob);
+/* GODOT end */
#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609)
case D3D_ROOT_SIGNATURE_VERSION_1_2:
@@ -1181,7 +1197,9 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
if (SUCCEEDED(hr))
{
const CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC desc(desc_1_1.NumParameters, desc_1_1.pParameters, desc_1_1.NumStaticSamplers, pStaticSamplers == nullptr ? desc_1_1.pStaticSamplers : pStaticSamplers, desc_1_1.Flags);
- hr = D3D12SerializeVersionedRootSignature(&desc, ppBlob, ppErrorBlob);
+/* GODOT start */
+ hr = d3d_D3D12SerializeVersionedRootSignature(&desc, ppBlob, ppErrorBlob);
+/* GODOT end */
}
if (pStaticSamplers)
@@ -1197,7 +1215,9 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609)
case D3D_ROOT_SIGNATURE_VERSION_1_2:
#endif
- return D3D12SerializeVersionedRootSignature(pRootSignatureDesc, ppBlob, ppErrorBlob);
+/* GODOT start */
+ return d3d_D3D12SerializeVersionedRootSignature(pRootSignatureDesc, ppBlob, ppErrorBlob);
+/* GODOT end */
}
return E_INVALIDARG;
diff --git a/thirdparty/directx_headers/patches/patch_d3d12_dynamic_load.diff b/thirdparty/directx_headers/patches/patch_d3d12_dynamic_load.diff
new file mode 100644
index 0000000000..d520a44172
--- /dev/null
+++ b/thirdparty/directx_headers/patches/patch_d3d12_dynamic_load.diff
@@ -0,0 +1,82 @@
+diff --git a/thirdparty/directx_headers/include/directx/d3dx12_root_signature.h b/thirdparty/directx_headers/include/directx/d3dx12_root_signature.h
+index 572efed852..18efa7a0cb 100644
+--- a/thirdparty/directx_headers/include/directx/d3dx12_root_signature.h
++++ b/thirdparty/directx_headers/include/directx/d3dx12_root_signature.h
+@@ -996,6 +996,9 @@ struct CD3DX12_GPU_DESCRIPTOR_HANDLE : public D3D12_GPU_DESCRIPTOR_HANDLE
+ // two code paths for building root signatures, this helper method reconstructs a 1.0 signature when
+ // 1.1 is not supported.
+ inline HRESULT D3DX12SerializeVersionedRootSignature(
++/* GODOT start */
++ _In_ HMODULE pLibD3D12,
++/* GODOT end */
+ _In_ const D3D12_VERSIONED_ROOT_SIGNATURE_DESC* pRootSignatureDesc,
+ D3D_ROOT_SIGNATURE_VERSION MaxVersion,
+ _Outptr_ ID3DBlob** ppBlob,
+@@ -1006,13 +1009,22 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
+ *ppErrorBlob = nullptr;
+ }
+
++ /* GODOT start */
++ PFN_D3D12_SERIALIZE_ROOT_SIGNATURE d3d_D3D12SerializeRootSignature = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)(void *)GetProcAddress(pLibD3D12, "D3D12SerializeRootSignature");
++ if (d3d_D3D12SerializeRootSignature == nullptr) {
++ return E_INVALIDARG;
++ }
++ PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE d3d_D3D12SerializeVersionedRootSignature = (PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE)(void *)GetProcAddress(pLibD3D12, "D3D12SerializeVersionedRootSignature");
++ /* GODOT end */
+ switch (MaxVersion)
+ {
+ case D3D_ROOT_SIGNATURE_VERSION_1_0:
+ switch (pRootSignatureDesc->Version)
+ {
+ case D3D_ROOT_SIGNATURE_VERSION_1_0:
+- return D3D12SerializeRootSignature(&pRootSignatureDesc->Desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);
++/* GODOT start */
++ return d3d_D3D12SerializeRootSignature(&pRootSignatureDesc->Desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);
++/* GODOT end */
+
+ case D3D_ROOT_SIGNATURE_VERSION_1_1:
+ #if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609)
+@@ -1114,7 +1126,9 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
+ if (SUCCEEDED(hr))
+ {
+ const CD3DX12_ROOT_SIGNATURE_DESC desc_1_0(desc_1_1.NumParameters, pParameters_1_0, desc_1_1.NumStaticSamplers, pStaticSamplers == nullptr ? desc_1_1.pStaticSamplers : pStaticSamplers, desc_1_1.Flags);
+- hr = D3D12SerializeRootSignature(&desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);
++/* GODOT start */
++ hr = d3d_D3D12SerializeRootSignature(&desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);
++/* GODOT end */
+ }
+
+ if (pParameters)
+@@ -1145,7 +1159,9 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
+ {
+ case D3D_ROOT_SIGNATURE_VERSION_1_0:
+ case D3D_ROOT_SIGNATURE_VERSION_1_1:
+- return D3D12SerializeVersionedRootSignature(pRootSignatureDesc, ppBlob, ppErrorBlob);
++/* GODOT start */
++ return d3d_D3D12SerializeVersionedRootSignature(pRootSignatureDesc, ppBlob, ppErrorBlob);
++/* GODOT end */
+
+ #if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609)
+ case D3D_ROOT_SIGNATURE_VERSION_1_2:
+@@ -1181,7 +1197,9 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
+ if (SUCCEEDED(hr))
+ {
+ const CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC desc(desc_1_1.NumParameters, desc_1_1.pParameters, desc_1_1.NumStaticSamplers, pStaticSamplers == nullptr ? desc_1_1.pStaticSamplers : pStaticSamplers, desc_1_1.Flags);
+- hr = D3D12SerializeVersionedRootSignature(&desc, ppBlob, ppErrorBlob);
++/* GODOT start */
++ hr = d3d_D3D12SerializeVersionedRootSignature(&desc, ppBlob, ppErrorBlob);
++/* GODOT end */
+ }
+
+ if (pStaticSamplers)
+@@ -1197,7 +1215,9 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
+ #if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609)
+ case D3D_ROOT_SIGNATURE_VERSION_1_2:
+ #endif
+- return D3D12SerializeVersionedRootSignature(pRootSignatureDesc, ppBlob, ppErrorBlob);
++/* GODOT start */
++ return d3d_D3D12SerializeVersionedRootSignature(pRootSignatureDesc, ppBlob, ppErrorBlob);
++/* GODOT end */
+ }
+
+ return E_INVALIDARG;