summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/variant/callable.h2
-rw-r--r--core/variant/variant.h2
-rw-r--r--doc/classes/MainLoop.xml1
-rw-r--r--doc/classes/NavigationServer2D.xml8
-rw-r--r--doc/classes/NavigationServer3D.xml8
-rw-r--r--doc/classes/Sprite2D.xml2
-rw-r--r--drivers/d3d12/rendering_device_driver_d3d12.cpp46
-rw-r--r--drivers/d3d12/rendering_device_driver_d3d12.h3
-rw-r--r--drivers/gles3/rasterizer_gles3.cpp17
-rw-r--r--drivers/gles3/rasterizer_gles3.h1
-rw-r--r--drivers/gles3/shaders/canvas.glsl43
-rw-r--r--drivers/gles3/shaders/scene.glsl5
-rw-r--r--drivers/gles3/storage/config.cpp5
-rw-r--r--drivers/gles3/storage/config.h2
-rw-r--r--drivers/vulkan/rendering_device_driver_vulkan.cpp223
-rw-r--r--drivers/vulkan/rendering_device_driver_vulkan.h6
-rw-r--r--editor/code_editor.cpp265
-rw-r--r--editor/code_editor.h29
-rw-r--r--editor/editor_properties_array_dict.cpp16
-rw-r--r--editor/plugins/script_editor_plugin.cpp46
-rw-r--r--editor/plugins/script_editor_plugin.h7
-rw-r--r--editor/plugins/script_text_editor.cpp10
-rw-r--r--editor/plugins/script_text_editor.h1
-rw-r--r--editor/plugins/shader_editor_plugin.cpp29
-rw-r--r--editor/plugins/shader_editor_plugin.h4
-rw-r--r--editor/plugins/text_editor.cpp8
-rw-r--r--editor/plugins/text_editor.h1
-rw-r--r--editor/plugins/text_shader_editor.cpp166
-rw-r--r--editor/plugins/text_shader_editor.h4
-rw-r--r--modules/basis_universal/image_compress_basisu.cpp7
-rw-r--r--modules/navigation/godot_navigation_server.cpp19
-rw-r--r--modules/navigation/godot_navigation_server.h3
-rw-r--r--modules/navigation/godot_navigation_server_2d.cpp4
-rw-r--r--modules/navigation/godot_navigation_server_2d.h1
-rw-r--r--modules/navigation/nav_agent.cpp4
-rw-r--r--modules/navigation/nav_agent.h2
-rw-r--r--modules/navigation/nav_map.cpp15
-rw-r--r--modules/navigation/nav_map.h8
-rw-r--r--modules/navigation/nav_obstacle.cpp4
-rw-r--r--modules/navigation/nav_obstacle.h2
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/gl/GLSurfaceView.java19
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularContextFactory.java10
-rw-r--r--scene/animation/animation_blend_tree.cpp1
-rw-r--r--scene/animation/animation_tree.cpp4
-rw-r--r--scene/gui/tab_bar.cpp9
-rw-r--r--servers/navigation_server_2d.cpp1
-rw-r--r--servers/navigation_server_2d.h1
-rw-r--r--servers/navigation_server_2d_dummy.h1
-rw-r--r--servers/navigation_server_3d.cpp1
-rw-r--r--servers/navigation_server_3d.h1
-rw-r--r--servers/navigation_server_3d_dummy.h8
-rw-r--r--servers/register_server_types.cpp108
-rw-r--r--servers/rendering/rendering_device.cpp36
-rw-r--r--servers/rendering/rendering_device.h3
-rw-r--r--servers/rendering/rendering_device_driver.h3
-rw-r--r--servers/rendering/rendering_device_graph.cpp9
-rw-r--r--servers/rendering/rendering_device_graph.h2
57 files changed, 728 insertions, 518 deletions
diff --git a/core/variant/callable.h b/core/variant/callable.h
index 3ae424e9bf..38872b71ef 100644
--- a/core/variant/callable.h
+++ b/core/variant/callable.h
@@ -99,7 +99,7 @@ public:
bool is_valid() const;
template <typename... VarArgs>
- Callable bind(VarArgs... p_args);
+ Callable bind(VarArgs... p_args) const;
Callable bindv(const Array &p_arguments);
Callable bindp(const Variant **p_arguments, int p_argcount) const;
diff --git a/core/variant/variant.h b/core/variant/variant.h
index d685444c30..c358559c9b 100644
--- a/core/variant/variant.h
+++ b/core/variant/variant.h
@@ -865,7 +865,7 @@ Variant Callable::call(VarArgs... p_args) const {
}
template <typename... VarArgs>
-Callable Callable::bind(VarArgs... p_args) {
+Callable Callable::bind(VarArgs... p_args) const {
Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
const Variant *argptrs[sizeof...(p_args) + 1];
for (uint32_t i = 0; i < sizeof...(p_args); i++) {
diff --git a/doc/classes/MainLoop.xml b/doc/classes/MainLoop.xml
index 458b3d4107..17cc0d78d3 100644
--- a/doc/classes/MainLoop.xml
+++ b/doc/classes/MainLoop.xml
@@ -30,6 +30,7 @@
[csharp]
using Godot;
+ [GlobalClass]
public partial class CustomMainLoop : MainLoop
{
private double _timeElapsed = 0;
diff --git a/doc/classes/NavigationServer2D.xml b/doc/classes/NavigationServer2D.xml
index 39f0718a71..dccdd02d0a 100644
--- a/doc/classes/NavigationServer2D.xml
+++ b/doc/classes/NavigationServer2D.xml
@@ -504,6 +504,14 @@
Returns the edge connection margin of the map. The edge connection margin is a distance used to connect two regions.
</description>
</method>
+ <method name="map_get_iteration_id" qualifiers="const">
+ <return type="int" />
+ <param index="0" name="map" type="RID" />
+ <description>
+ Returns the current iteration id of the navigation map. Every time the navigation map changes and synchronizes the iteration id increases. An iteration id of 0 means the navigation map has never synchronized.
+ [b]Note:[/b] The iteration id will wrap back to 1 after reaching its range limit.
+ </description>
+ </method>
<method name="map_get_link_connection_radius" qualifiers="const">
<return type="float" />
<param index="0" name="map" type="RID" />
diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml
index e88792cade..4fc75461e7 100644
--- a/doc/classes/NavigationServer3D.xml
+++ b/doc/classes/NavigationServer3D.xml
@@ -568,6 +568,14 @@
Returns the edge connection margin of the map. This distance is the minimum vertex distance needed to connect two edges from different regions.
</description>
</method>
+ <method name="map_get_iteration_id" qualifiers="const">
+ <return type="int" />
+ <param index="0" name="map" type="RID" />
+ <description>
+ Returns the current iteration id of the navigation map. Every time the navigation map changes and synchronizes the iteration id increases. An iteration id of 0 means the navigation map has never synchronized.
+ [b]Note:[/b] The iteration id will wrap back to 1 after reaching its range limit.
+ </description>
+ </method>
<method name="map_get_link_connection_radius" qualifiers="const">
<return type="float" />
<param index="0" name="map" type="RID" />
diff --git a/doc/classes/Sprite2D.xml b/doc/classes/Sprite2D.xml
index e5c4c01d65..8dcf286b3a 100644
--- a/doc/classes/Sprite2D.xml
+++ b/doc/classes/Sprite2D.xml
@@ -44,7 +44,7 @@
<return type="bool" />
<param index="0" name="pos" type="Vector2" />
<description>
- Returns [code]true[/code], if the pixel at the given position is opaque and [code]false[/code] in other case.
+ Returns [code]true[/code], if the pixel at the given position is opaque and [code]false[/code] in other case. The position is in local coordinates.
[b]Note:[/b] It also returns [code]false[/code], if the sprite's texture is [code]null[/code] or if the given position is invalid.
</description>
</method>
diff --git a/drivers/d3d12/rendering_device_driver_d3d12.cpp b/drivers/d3d12/rendering_device_driver_d3d12.cpp
index 6517b4e91b..8c92737374 100644
--- a/drivers/d3d12/rendering_device_driver_d3d12.cpp
+++ b/drivers/d3d12/rendering_device_driver_d3d12.cpp
@@ -1955,48 +1955,44 @@ RDD::CommandQueueID RenderingDeviceDriverD3D12::command_queue_create(CommandQueu
return CommandQueueID(command_queue);
}
-Error RenderingDeviceDriverD3D12::command_queue_execute(CommandQueueID p_cmd_queue, VectorView<CommandBufferID> p_cmd_buffers, VectorView<SemaphoreID> p_wait_semaphores, VectorView<SemaphoreID> p_signal_semaphores, FenceID p_signal_fence) {
+Error RenderingDeviceDriverD3D12::command_queue_execute_and_present(CommandQueueID p_cmd_queue, VectorView<SemaphoreID> p_wait_semaphores, VectorView<CommandBufferID> p_cmd_buffers, VectorView<SemaphoreID> p_cmd_semaphores, FenceID p_cmd_fence, VectorView<SwapChainID> p_swap_chains) {
CommandQueueInfo *command_queue = (CommandQueueInfo *)(p_cmd_queue.id);
for (uint32_t i = 0; i < p_wait_semaphores.size(); i++) {
const SemaphoreInfo *semaphore = (const SemaphoreInfo *)(p_wait_semaphores[i].id);
command_queue->d3d_queue->Wait(semaphore->d3d_fence.Get(), semaphore->fence_value);
}
- thread_local LocalVector<ID3D12CommandList *> command_lists;
- command_lists.resize(p_cmd_buffers.size());
- for (uint32_t i = 0; i < p_cmd_buffers.size(); i++) {
- const CommandBufferInfo *cmd_buf_info = (const CommandBufferInfo *)(p_cmd_buffers[i].id);
- command_lists[i] = cmd_buf_info->cmd_list.Get();
- }
+ if (p_cmd_buffers.size() > 0) {
+ thread_local LocalVector<ID3D12CommandList *> command_lists;
+ command_lists.resize(p_cmd_buffers.size());
+ for (uint32_t i = 0; i < p_cmd_buffers.size(); i++) {
+ const CommandBufferInfo *cmd_buf_info = (const CommandBufferInfo *)(p_cmd_buffers[i].id);
+ command_lists[i] = cmd_buf_info->cmd_list.Get();
+ }
- command_queue->d3d_queue->ExecuteCommandLists(command_lists.size(), command_lists.ptr());
+ command_queue->d3d_queue->ExecuteCommandLists(command_lists.size(), command_lists.ptr());
- for (uint32_t i = 0; i < p_signal_semaphores.size(); i++) {
- SemaphoreInfo *semaphore = (SemaphoreInfo *)(p_signal_semaphores[i].id);
- semaphore->fence_value++;
- command_queue->d3d_queue->Signal(semaphore->d3d_fence.Get(), semaphore->fence_value);
- }
+ for (uint32_t i = 0; i < p_cmd_semaphores.size(); i++) {
+ SemaphoreInfo *semaphore = (SemaphoreInfo *)(p_cmd_semaphores[i].id);
+ semaphore->fence_value++;
+ command_queue->d3d_queue->Signal(semaphore->d3d_fence.Get(), semaphore->fence_value);
+ }
- if (p_signal_fence) {
- FenceInfo *fence = (FenceInfo *)(p_signal_fence.id);
- fence->fence_value++;
- command_queue->d3d_queue->Signal(fence->d3d_fence.Get(), fence->fence_value);
- fence->d3d_fence->SetEventOnCompletion(fence->fence_value, fence->event_handle);
+ if (p_cmd_fence) {
+ FenceInfo *fence = (FenceInfo *)(p_cmd_fence.id);
+ fence->fence_value++;
+ command_queue->d3d_queue->Signal(fence->d3d_fence.Get(), fence->fence_value);
+ fence->d3d_fence->SetEventOnCompletion(fence->fence_value, fence->event_handle);
+ }
}
- return OK;
-}
-
-Error RenderingDeviceDriverD3D12::command_queue_present(CommandQueueID p_cmd_queue, VectorView<SwapChainID> p_swap_chains, VectorView<SemaphoreID> p_wait_semaphores) {
- // D3D12 does not require waiting for the command queue's semaphores to handle presentation.
- // We just present the swap chains that were specified and ignore the command queue and the semaphores.
HRESULT res;
bool any_present_failed = false;
for (uint32_t i = 0; i < p_swap_chains.size(); i++) {
SwapChain *swap_chain = (SwapChain *)(p_swap_chains[i].id);
res = swap_chain->d3d_swap_chain->Present(swap_chain->sync_interval, swap_chain->present_flags);
if (!SUCCEEDED(res)) {
- print_verbose("D3D12: Presenting swapchain failed with error " + vformat("0x%08ux", (uint64_t)res) + ".");
+ print_verbose(vformat("D3D12: Presenting swapchain failed with error 0x%08ux.", (uint64_t)res));
any_present_failed = true;
}
}
diff --git a/drivers/d3d12/rendering_device_driver_d3d12.h b/drivers/d3d12/rendering_device_driver_d3d12.h
index 595ee30966..06d5cb65c4 100644
--- a/drivers/d3d12/rendering_device_driver_d3d12.h
+++ b/drivers/d3d12/rendering_device_driver_d3d12.h
@@ -413,8 +413,7 @@ private:
public:
virtual CommandQueueID command_queue_create(CommandQueueFamilyID p_cmd_queue_family, bool p_identify_as_main_queue = false) override;
- virtual Error command_queue_execute(CommandQueueID p_cmd_queue, VectorView<CommandBufferID> p_cmd_buffers, VectorView<SemaphoreID> p_wait_semaphores, VectorView<SemaphoreID> p_signal_semaphores, FenceID p_signal_fence) override;
- virtual Error command_queue_present(CommandQueueID p_cmd_queue, VectorView<SwapChainID> p_swap_chains, VectorView<SemaphoreID> p_wait_semaphores) override;
+ virtual Error command_queue_execute_and_present(CommandQueueID p_cmd_queue, VectorView<SemaphoreID> p_wait_semaphores, VectorView<CommandBufferID> p_cmd_buffers, VectorView<SemaphoreID> p_cmd_semaphores, FenceID p_cmd_fence, VectorView<SwapChainID> p_swap_chains) override;
virtual void command_queue_free(CommandQueueID p_cmd_queue) override;
private:
diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp
index 14ef0f40cf..da2320c23d 100644
--- a/drivers/gles3/rasterizer_gles3.cpp
+++ b/drivers/gles3/rasterizer_gles3.cpp
@@ -194,6 +194,11 @@ typedef void(GLAPIENTRY *DebugMessageCallbackARB)(DEBUGPROCARB callback, const v
void RasterizerGLES3::initialize() {
Engine::get_singleton()->print_header(vformat("OpenGL API %s - Compatibility - Using Device: %s - %s", RS::get_singleton()->get_video_adapter_api_version(), RS::get_singleton()->get_video_adapter_vendor(), RS::get_singleton()->get_video_adapter_name()));
+
+ // FLIP XY Bug: Are more devices affected?
+ // Confirmed so far: all Adreno 3xx
+ // ok on some tested Adreno devices: 4xx, 5xx and 6xx
+ flip_xy_bugfix = GLES3::Config::get_singleton()->adreno_3xx_compatibility;
}
void RasterizerGLES3::finalize() {
@@ -398,8 +403,18 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display
}
Vector2i screen_rect_end = p_screen_rect.get_end();
+
+ // Adreno (TM) 3xx devices have a bug that create wrong Landscape rotation of 180 degree
+ // Reversing both the X and Y axis is equivalent to rotating 180 degrees
+ bool flip_x = false;
+ if (flip_xy_bugfix && screen_rect_end.x > screen_rect_end.y) {
+ flip_y = !flip_y;
+ flip_x = !flip_x;
+ }
+
glBlitFramebuffer(0, 0, rt->size.x, rt->size.y,
- p_screen_rect.position.x, flip_y ? screen_rect_end.y : p_screen_rect.position.y, screen_rect_end.x, flip_y ? p_screen_rect.position.y : screen_rect_end.y,
+ flip_x ? screen_rect_end.x : p_screen_rect.position.x, flip_y ? screen_rect_end.y : p_screen_rect.position.y,
+ flip_x ? p_screen_rect.position.x : screen_rect_end.x, flip_y ? p_screen_rect.position.y : screen_rect_end.y,
GL_COLOR_BUFFER_BIT, GL_NEAREST);
if (read_fbo != 0) {
diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h
index fc1315035b..8d52dc2365 100644
--- a/drivers/gles3/rasterizer_gles3.h
+++ b/drivers/gles3/rasterizer_gles3.h
@@ -55,6 +55,7 @@ private:
float delta = 0;
double time_total = 0.0;
+ bool flip_xy_bugfix = false;
static bool gles_over_gl;
diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl
index 80e28cf9fc..8da7d7dc80 100644
--- a/drivers/gles3/shaders/canvas.glsl
+++ b/drivers/gles3/shaders/canvas.glsl
@@ -187,8 +187,31 @@ void main() {
#endif // !USE_INSTANCING
#else // !USE_ATTRIBUTES
- vec2 vertex_base_arr[6] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0), vec2(0.0, 0.0), vec2(1.0, 1.0));
- vec2 vertex_base = vertex_base_arr[gl_VertexID % 6];
+
+ // crash on Adreno 320/330
+ //vec2 vertex_base_arr[6] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0), vec2(0.0, 0.0), vec2(1.0, 1.0));
+ //vec2 vertex_base = vertex_base_arr[gl_VertexID % 6];
+ //-----------------------------------------
+ // ID | 0 | 1 | 2 | 3 | 4 | 5 |
+ //-----------------------------------------
+ // X | 0.0 | 0.0 | 1.0 | 1.0 | 0.0 | 1.0 |
+ // Y | 0.0 | 1.0 | 1.0 | 0.0 | 0.0 | 1.0 |
+ //-----------------------------------------
+ // no crash or freeze on all Adreno 3xx with 'if / else if' and slightly faster!
+ int vertex_id = gl_VertexID % 6;
+ vec2 vertex_base;
+ if (vertex_id == 0)
+ vertex_base = vec2(0.0, 0.0);
+ else if (vertex_id == 1)
+ vertex_base = vec2(0.0, 1.0);
+ else if (vertex_id == 2)
+ vertex_base = vec2(1.0, 1.0);
+ else if (vertex_id == 3)
+ vertex_base = vec2(1.0, 0.0);
+ else if (vertex_id == 4)
+ vertex_base = vec2(0.0, 0.0);
+ else if (vertex_id == 5)
+ vertex_base = vec2(1.0, 1.0);
vec2 uv = read_draw_data_src_rect.xy + abs(read_draw_data_src_rect.zw) * ((read_draw_data_flags & FLAGS_TRANSPOSE_RECT) != uint(0) ? vertex_base.yx : vertex_base.xy);
vec4 color = read_draw_data_modulation;
@@ -475,16 +498,12 @@ vec4 light_shadow_compute(uint light_base, vec4 light_color, vec4 shadow_uv
void light_blend_compute(uint light_base, vec4 light_color, inout vec3 color) {
uint blend_mode = light_array[light_base].flags & LIGHT_FLAGS_BLEND_MASK;
- switch (blend_mode) {
- case LIGHT_FLAGS_BLEND_MODE_ADD: {
- color.rgb += light_color.rgb * light_color.a;
- } break;
- case LIGHT_FLAGS_BLEND_MODE_SUB: {
- color.rgb -= light_color.rgb * light_color.a;
- } break;
- case LIGHT_FLAGS_BLEND_MODE_MIX: {
- color.rgb = mix(color.rgb, light_color.rgb, light_color.a);
- } break;
+ if (blend_mode == LIGHT_FLAGS_BLEND_MODE_ADD) {
+ color.rgb += light_color.rgb * light_color.a;
+ } else if (blend_mode == LIGHT_FLAGS_BLEND_MODE_SUB) {
+ color.rgb -= light_color.rgb * light_color.a;
+ } else if (blend_mode == LIGHT_FLAGS_BLEND_MODE_MIX) {
+ color.rgb = mix(color.rgb, light_color.rgb, light_color.a);
}
}
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index 27c292d163..a6db90c3f5 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -1200,7 +1200,10 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f
vec3 spot_dir = spot_lights[idx].direction;
float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_lights[idx].cone_angle);
float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_lights[idx].cone_angle));
- spot_attenuation *= 1.0 - pow(spot_rim, spot_lights[idx].cone_attenuation);
+
+ mediump float cone_attenuation = spot_lights[idx].cone_attenuation;
+ spot_attenuation *= 1.0 - pow(spot_rim, cone_attenuation);
+
vec3 color = spot_lights[idx].color;
float size_A = 0.0;
diff --git a/drivers/gles3/storage/config.cpp b/drivers/gles3/storage/config.cpp
index 5d01ab0346..1a41b60836 100644
--- a/drivers/gles3/storage/config.cpp
+++ b/drivers/gles3/storage/config.cpp
@@ -166,6 +166,11 @@ Config::Config() {
max_renderable_elements = GLOBAL_GET("rendering/limits/opengl/max_renderable_elements");
max_renderable_lights = GLOBAL_GET("rendering/limits/opengl/max_renderable_lights");
max_lights_per_object = GLOBAL_GET("rendering/limits/opengl/max_lights_per_object");
+
+ //Adreno 3xx Compatibility
+ const String rendering_device_name = String::utf8((const char *)glGetString(GL_RENDERER));
+ //TODO: Check the number between 300 and 399(?)
+ adreno_3xx_compatibility = (rendering_device_name.left(13) == "Adreno (TM) 3");
}
Config::~Config() {
diff --git a/drivers/gles3/storage/config.h b/drivers/gles3/storage/config.h
index 1c0a5178bd..c3ab65f0bc 100644
--- a/drivers/gles3/storage/config.h
+++ b/drivers/gles3/storage/config.h
@@ -91,6 +91,8 @@ public:
bool rt_msaa_multiview_supported = false;
bool multiview_supported = false;
+ bool adreno_3xx_compatibility = false;
+
#ifdef ANDROID_ENABLED
PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC eglFramebufferTextureMultiviewOVR = nullptr;
PFNGLTEXSTORAGE3DMULTISAMPLEPROC eglTexStorage3DMultisample = nullptr;
diff --git a/drivers/vulkan/rendering_device_driver_vulkan.cpp b/drivers/vulkan/rendering_device_driver_vulkan.cpp
index f48e6eb7ed..21cf54b4be 100644
--- a/drivers/vulkan/rendering_device_driver_vulkan.cpp
+++ b/drivers/vulkan/rendering_device_driver_vulkan.cpp
@@ -1113,12 +1113,12 @@ void RenderingDeviceDriverVulkan::_set_object_name(VkObjectType p_object_type, u
}
Error RenderingDeviceDriverVulkan::initialize(uint32_t p_device_index, uint32_t p_frame_count) {
- // Frame count is not required for the Vulkan driver, so we just ignore it.
-
context_device = context_driver->device_get(p_device_index);
physical_device = context_driver->physical_device_get(p_device_index);
vkGetPhysicalDeviceProperties(physical_device, &physical_device_properties);
+ frame_count = p_frame_count;
+
// Copy the queue family properties the context already retrieved.
uint32_t queue_family_count = context_driver->queue_family_get_count(p_device_index);
queue_family_properties.resize(queue_family_count);
@@ -2131,21 +2131,18 @@ RDD::CommandQueueID RenderingDeviceDriverVulkan::command_queue_create(CommandQue
return CommandQueueID(command_queue);
}
-Error RenderingDeviceDriverVulkan::command_queue_execute(CommandQueueID p_cmd_queue, VectorView<CommandBufferID> p_cmd_buffers, VectorView<SemaphoreID> p_wait_semaphores, VectorView<SemaphoreID> p_signal_semaphores, FenceID p_signal_fence) {
+Error RenderingDeviceDriverVulkan::command_queue_execute_and_present(CommandQueueID p_cmd_queue, VectorView<SemaphoreID> p_wait_semaphores, VectorView<CommandBufferID> p_cmd_buffers, VectorView<SemaphoreID> p_cmd_semaphores, FenceID p_cmd_fence, VectorView<SwapChainID> p_swap_chains) {
DEV_ASSERT(p_cmd_queue.id != 0);
+ VkResult err;
CommandQueue *command_queue = (CommandQueue *)(p_cmd_queue.id);
Queue &device_queue = queue_families[command_queue->queue_family][command_queue->queue_index];
- Fence *fence = (Fence *)(p_signal_fence.id);
+ Fence *fence = (Fence *)(p_cmd_fence.id);
VkFence vk_fence = (fence != nullptr) ? fence->vk_fence : VK_NULL_HANDLE;
- thread_local LocalVector<VkCommandBuffer> command_buffers;
thread_local LocalVector<VkSemaphore> wait_semaphores;
- thread_local LocalVector<VkSemaphore> signal_semaphores;
thread_local LocalVector<VkPipelineStageFlags> wait_semaphores_stages;
- command_buffers.clear();
wait_semaphores.clear();
- signal_semaphores.clear();
wait_semaphores_stages.clear();
if (!command_queue->pending_semaphores_for_execute.is_empty()) {
@@ -2158,117 +2155,142 @@ Error RenderingDeviceDriverVulkan::command_queue_execute(CommandQueueID p_cmd_qu
command_queue->pending_semaphores_for_execute.clear();
}
- for (uint32_t i = 0; i < p_cmd_buffers.size(); i++) {
- command_buffers.push_back(VkCommandBuffer(p_cmd_buffers[i].id));
- }
-
for (uint32_t i = 0; i < p_wait_semaphores.size(); i++) {
// FIXME: Allow specifying the stage mask in more detail.
wait_semaphores.push_back(VkSemaphore(p_wait_semaphores[i].id));
wait_semaphores_stages.push_back(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
}
- for (uint32_t i = 0; i < p_signal_semaphores.size(); i++) {
- signal_semaphores.push_back(VkSemaphore(p_signal_semaphores[i].id));
- }
-
- VkSubmitInfo submit_info = {};
- submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
- submit_info.waitSemaphoreCount = wait_semaphores.size();
- submit_info.pWaitSemaphores = wait_semaphores.ptr();
- submit_info.pWaitDstStageMask = wait_semaphores_stages.ptr();
- submit_info.commandBufferCount = command_buffers.size();
- submit_info.pCommandBuffers = command_buffers.ptr();
- submit_info.signalSemaphoreCount = signal_semaphores.size();
- submit_info.pSignalSemaphores = signal_semaphores.ptr();
+ if (p_cmd_buffers.size() > 0) {
+ thread_local LocalVector<VkCommandBuffer> command_buffers;
+ thread_local LocalVector<VkSemaphore> signal_semaphores;
+ command_buffers.clear();
+ signal_semaphores.clear();
- device_queue.submit_mutex.lock();
- VkResult err = vkQueueSubmit(device_queue.queue, 1, &submit_info, vk_fence);
- device_queue.submit_mutex.unlock();
- ERR_FAIL_COND_V(err != VK_SUCCESS, FAILED);
-
- if (fence != nullptr && !command_queue->pending_semaphores_for_fence.is_empty()) {
- fence->queue_signaled_from = command_queue;
+ for (uint32_t i = 0; i < p_cmd_buffers.size(); i++) {
+ command_buffers.push_back(VkCommandBuffer(p_cmd_buffers[i].id));
+ }
- // Indicate to the fence that it should release the semaphores that were waited on this submission the next time the fence is waited on.
- for (uint32_t i = 0; i < command_queue->pending_semaphores_for_fence.size(); i++) {
- command_queue->image_semaphores_for_fences.push_back({ fence, command_queue->pending_semaphores_for_fence[i] });
+ for (uint32_t i = 0; i < p_cmd_semaphores.size(); i++) {
+ signal_semaphores.push_back(VkSemaphore(p_cmd_semaphores[i].id));
}
- command_queue->pending_semaphores_for_fence.clear();
- }
+ VkSemaphore present_semaphore = VK_NULL_HANDLE;
+ if (p_swap_chains.size() > 0) {
+ if (command_queue->present_semaphores.is_empty()) {
+ // Create the semaphores used for presentation if they haven't been created yet.
+ VkSemaphore semaphore = VK_NULL_HANDLE;
+ VkSemaphoreCreateInfo create_info = {};
+ create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+
+ for (uint32_t i = 0; i < frame_count; i++) {
+ err = vkCreateSemaphore(vk_device, &create_info, nullptr, &semaphore);
+ ERR_FAIL_COND_V(err != VK_SUCCESS, FAILED);
+ command_queue->present_semaphores.push_back(semaphore);
+ }
+ }
- return OK;
-}
+ // If a presentation semaphore is required, cycle across the ones available on the queue. It is technically possible
+ // and valid to reuse the same semaphore for this particular operation, but we create multiple ones anyway in case
+ // some hardware expects multiple semaphores to be used.
+ present_semaphore = command_queue->present_semaphores[command_queue->present_semaphore_index];
+ signal_semaphores.push_back(present_semaphore);
+ command_queue->present_semaphore_index = (command_queue->present_semaphore_index + 1) % command_queue->present_semaphores.size();
+ }
-Error RenderingDeviceDriverVulkan::command_queue_present(CommandQueueID p_cmd_queue, VectorView<SwapChainID> p_swap_chains, VectorView<SemaphoreID> p_wait_semaphores) {
- DEV_ASSERT(p_cmd_queue.id != 0);
+ VkSubmitInfo submit_info = {};
+ submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submit_info.waitSemaphoreCount = wait_semaphores.size();
+ submit_info.pWaitSemaphores = wait_semaphores.ptr();
+ submit_info.pWaitDstStageMask = wait_semaphores_stages.ptr();
+ submit_info.commandBufferCount = command_buffers.size();
+ submit_info.pCommandBuffers = command_buffers.ptr();
+ submit_info.signalSemaphoreCount = signal_semaphores.size();
+ submit_info.pSignalSemaphores = signal_semaphores.ptr();
+
+ device_queue.submit_mutex.lock();
+ err = vkQueueSubmit(device_queue.queue, 1, &submit_info, vk_fence);
+ device_queue.submit_mutex.unlock();
+ ERR_FAIL_COND_V(err != VK_SUCCESS, FAILED);
+
+ if (fence != nullptr && !command_queue->pending_semaphores_for_fence.is_empty()) {
+ fence->queue_signaled_from = command_queue;
+
+ // Indicate to the fence that it should release the semaphores that were waited on this submission the next time the fence is waited on.
+ for (uint32_t i = 0; i < command_queue->pending_semaphores_for_fence.size(); i++) {
+ command_queue->image_semaphores_for_fences.push_back({ fence, command_queue->pending_semaphores_for_fence[i] });
+ }
- CommandQueue *command_queue = (CommandQueue *)(p_cmd_queue.id);
- Queue &device_queue = queue_families[command_queue->queue_family][command_queue->queue_index];
+ command_queue->pending_semaphores_for_fence.clear();
+ }
- thread_local LocalVector<VkSwapchainKHR> swapchains;
- thread_local LocalVector<uint32_t> image_indices;
- thread_local LocalVector<VkSemaphore> wait_semaphores;
- thread_local LocalVector<VkResult> results;
- swapchains.clear();
- image_indices.clear();
- for (uint32_t i = 0; i < p_swap_chains.size(); i++) {
- SwapChain *swap_chain = (SwapChain *)(p_swap_chains[i].id);
- swapchains.push_back(swap_chain->vk_swapchain);
- DEV_ASSERT(swap_chain->image_index < swap_chain->images.size());
- image_indices.push_back(swap_chain->image_index);
+ if (present_semaphore != VK_NULL_HANDLE) {
+ // If command buffers were executed, swap chains must wait on the present semaphore used by the command queue.
+ wait_semaphores.clear();
+ wait_semaphores.push_back(present_semaphore);
+ }
}
- wait_semaphores.clear();
- for (uint32_t i = 0; i < p_wait_semaphores.size(); i++) {
- wait_semaphores.push_back(VkSemaphore(p_wait_semaphores[i].id));
- }
+ if (p_swap_chains.size() > 0) {
+ thread_local LocalVector<VkSwapchainKHR> swapchains;
+ thread_local LocalVector<uint32_t> image_indices;
+ thread_local LocalVector<VkResult> results;
+ swapchains.clear();
+ image_indices.clear();
- results.resize(swapchains.size());
-
- VkPresentInfoKHR present_info = {};
- present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
- present_info.waitSemaphoreCount = wait_semaphores.size();
- present_info.pWaitSemaphores = wait_semaphores.ptr();
- present_info.swapchainCount = swapchains.size();
- present_info.pSwapchains = swapchains.ptr();
- present_info.pImageIndices = image_indices.ptr();
- present_info.pResults = results.ptr();
- device_queue.submit_mutex.lock();
- VkResult err = device_functions.QueuePresentKHR(device_queue.queue, &present_info);
- device_queue.submit_mutex.unlock();
-
- // Set the index to an invalid value. If any of the swap chains returned out of date, indicate it should be resized the next time it's acquired.
- bool any_result_is_out_of_date = false;
- for (uint32_t i = 0; i < p_swap_chains.size(); i++) {
- SwapChain *swap_chain = (SwapChain *)(p_swap_chains[i].id);
- swap_chain->image_index = UINT_MAX;
- if (results[i] == VK_ERROR_OUT_OF_DATE_KHR) {
- context_driver->surface_set_needs_resize(swap_chain->surface, true);
- any_result_is_out_of_date = true;
+ for (uint32_t i = 0; i < p_swap_chains.size(); i++) {
+ SwapChain *swap_chain = (SwapChain *)(p_swap_chains[i].id);
+ swapchains.push_back(swap_chain->vk_swapchain);
+ DEV_ASSERT(swap_chain->image_index < swap_chain->images.size());
+ image_indices.push_back(swap_chain->image_index);
}
- }
- if (any_result_is_out_of_date || err == VK_ERROR_OUT_OF_DATE_KHR) {
- // It is possible for presentation to fail with out of date while acquire might've succeeded previously. This case
- // will be considered a silent failure as it can be triggered easily by resizing a window in the OS natively.
- return FAILED;
- }
+ results.resize(swapchains.size());
+
+ VkPresentInfoKHR present_info = {};
+ present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
+ present_info.waitSemaphoreCount = wait_semaphores.size();
+ present_info.pWaitSemaphores = wait_semaphores.ptr();
+ present_info.swapchainCount = swapchains.size();
+ present_info.pSwapchains = swapchains.ptr();
+ present_info.pImageIndices = image_indices.ptr();
+ present_info.pResults = results.ptr();
+
+ device_queue.submit_mutex.lock();
+ err = device_functions.QueuePresentKHR(device_queue.queue, &present_info);
+ device_queue.submit_mutex.unlock();
+
+ // Set the index to an invalid value. If any of the swap chains returned out of date, indicate it should be resized the next time it's acquired.
+ bool any_result_is_out_of_date = false;
+ for (uint32_t i = 0; i < p_swap_chains.size(); i++) {
+ SwapChain *swap_chain = (SwapChain *)(p_swap_chains[i].id);
+ swap_chain->image_index = UINT_MAX;
+ if (results[i] == VK_ERROR_OUT_OF_DATE_KHR) {
+ context_driver->surface_set_needs_resize(swap_chain->surface, true);
+ any_result_is_out_of_date = true;
+ }
+ }
- // Handling VK_SUBOPTIMAL_KHR the same as VK_SUCCESS is completely intentional.
- //
- // Godot does not currently support native rotation in Android when creating the swap chain. It intentionally uses
- // VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR instead of the current transform bits available in the surface capabilities.
- // Choosing the transform that leads to optimal presentation leads to distortion that makes the application unusable,
- // as the rotation of all the content is not handled at the moment.
- //
- // VK_SUBOPTIMAL_KHR is accepted as a successful case even if it's not the most efficient solution to work around this
- // problem. This behavior should not be changed unless the swap chain recreation uses the current transform bits, as
- // it'll lead to very low performance in Android by entering an endless loop where it'll always resize the swap chain
- // every frame.
+ if (any_result_is_out_of_date || err == VK_ERROR_OUT_OF_DATE_KHR) {
+ // It is possible for presentation to fail with out of date while acquire might've succeeded previously. This case
+ // will be considered a silent failure as it can be triggered easily by resizing a window in the OS natively.
+ return FAILED;
+ }
- ERR_FAIL_COND_V(err != VK_SUCCESS && err != VK_SUBOPTIMAL_KHR, FAILED);
+ // Handling VK_SUBOPTIMAL_KHR the same as VK_SUCCESS is completely intentional.
+ //
+ // Godot does not currently support native rotation in Android when creating the swap chain. It intentionally uses
+ // VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR instead of the current transform bits available in the surface capabilities.
+ // Choosing the transform that leads to optimal presentation leads to distortion that makes the application unusable,
+ // as the rotation of all the content is not handled at the moment.
+ //
+ // VK_SUBOPTIMAL_KHR is accepted as a successful case even if it's not the most efficient solution to work around this
+ // problem. This behavior should not be changed unless the swap chain recreation uses the current transform bits, as
+ // it'll lead to very low performance in Android by entering an endless loop where it'll always resize the swap chain
+ // every frame.
+
+ ERR_FAIL_COND_V(err != VK_SUCCESS && err != VK_SUBOPTIMAL_KHR, FAILED);
+ }
return OK;
}
@@ -2278,6 +2300,11 @@ void RenderingDeviceDriverVulkan::command_queue_free(CommandQueueID p_cmd_queue)
CommandQueue *command_queue = (CommandQueue *)(p_cmd_queue.id);
+ // Erase all the semaphores used for presentation.
+ for (VkSemaphore semaphore : command_queue->present_semaphores) {
+ vkDestroySemaphore(vk_device, semaphore, nullptr);
+ }
+
// Erase all the semaphores used for image acquisition.
for (VkSemaphore semaphore : command_queue->image_semaphores) {
vkDestroySemaphore(vk_device, semaphore, nullptr);
diff --git a/drivers/vulkan/rendering_device_driver_vulkan.h b/drivers/vulkan/rendering_device_driver_vulkan.h
index 4abaeecd11..70c4cebba5 100644
--- a/drivers/vulkan/rendering_device_driver_vulkan.h
+++ b/drivers/vulkan/rendering_device_driver_vulkan.h
@@ -115,6 +115,7 @@ class RenderingDeviceDriverVulkan : public RenderingDeviceDriver {
VkDevice vk_device = VK_NULL_HANDLE;
RenderingContextDriverVulkan *context_driver = nullptr;
RenderingContextDriver::Device context_device = {};
+ uint32_t frame_count = 1;
VkPhysicalDevice physical_device = VK_NULL_HANDLE;
VkPhysicalDeviceProperties physical_device_properties = {};
VkPhysicalDeviceFeatures physical_device_features = {};
@@ -276,6 +277,7 @@ public:
// ----- QUEUE -----
private:
struct CommandQueue {
+ LocalVector<VkSemaphore> present_semaphores;
LocalVector<VkSemaphore> image_semaphores;
LocalVector<SwapChain *> image_semaphores_swap_chains;
LocalVector<uint32_t> pending_semaphores_for_execute;
@@ -284,12 +286,12 @@ private:
LocalVector<Pair<Fence *, uint32_t>> image_semaphores_for_fences;
uint32_t queue_family = 0;
uint32_t queue_index = 0;
+ uint32_t present_semaphore_index = 0;
};
public:
virtual CommandQueueID command_queue_create(CommandQueueFamilyID p_cmd_queue_family, bool p_identify_as_main_queue = false) override final;
- virtual Error command_queue_execute(CommandQueueID p_cmd_queue, VectorView<CommandBufferID> p_cmd_buffers, VectorView<SemaphoreID> p_wait_semaphores, VectorView<SemaphoreID> p_signal_semaphores, FenceID p_signal_fence) override final;
- virtual Error command_queue_present(CommandQueueID p_cmd_queue, VectorView<SwapChainID> p_swap_chains, VectorView<SemaphoreID> p_wait_semaphores) override final;
+ virtual Error command_queue_execute_and_present(CommandQueueID p_cmd_queue, VectorView<SemaphoreID> p_wait_semaphores, VectorView<CommandBufferID> p_cmd_buffers, VectorView<SemaphoreID> p_cmd_semaphores, FenceID p_cmd_fence, VectorView<SwapChainID> p_swap_chains) override final;
virtual void command_queue_free(CommandQueueID p_cmd_queue) override final;
private:
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index e7d2f2bda7..d3872349e9 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -39,6 +39,8 @@
#include "editor/plugins/script_editor_plugin.h"
#include "editor/themes/editor_scale.h"
#include "editor/themes/editor_theme_manager.h"
+#include "scene/gui/menu_button.h"
+#include "scene/gui/separator.h"
#include "scene/resources/font.h"
void GotoLineDialog::popup_find_line(CodeEdit *p_edit) {
@@ -763,6 +765,8 @@ FindReplaceBar::FindReplaceBar() {
/*** CODE EDITOR ****/
+static constexpr float ZOOM_FACTOR_PRESETS[7] = { 0.25f, 0.5f, 0.75f, 1.0f, 1.5f, 2.0f, 3.0f };
+
// This function should be used to handle shortcuts that could otherwise
// be handled too late if they weren't handled here.
void CodeTextEditor::input(const Ref<InputEvent> &event) {
@@ -827,18 +831,21 @@ void CodeTextEditor::_text_editor_gui_input(const Ref<InputEvent> &p_event) {
if (mb->is_pressed() && mb->is_command_or_control_pressed()) {
if (mb->get_button_index() == MouseButton::WHEEL_UP) {
_zoom_in();
- } else if (mb->get_button_index() == MouseButton::WHEEL_DOWN) {
+ accept_event();
+ return;
+ }
+ if (mb->get_button_index() == MouseButton::WHEEL_DOWN) {
_zoom_out();
+ accept_event();
+ return;
}
}
}
Ref<InputEventMagnifyGesture> magnify_gesture = p_event;
if (magnify_gesture.is_valid()) {
- font_size = text_editor->get_theme_font_size(SNAME("font_size"));
- font_size *= powf(magnify_gesture->get_factor(), 0.25);
-
- _add_font_size((int)font_size - text_editor->get_theme_font_size(SNAME("font_size")));
+ _zoom_to(zoom_factor * powf(magnify_gesture->get_factor(), 0.25f));
+ accept_event();
return;
}
@@ -849,40 +856,22 @@ void CodeTextEditor::_text_editor_gui_input(const Ref<InputEvent> &p_event) {
if (ED_IS_SHORTCUT("script_editor/zoom_in", p_event)) {
_zoom_in();
accept_event();
+ return;
}
if (ED_IS_SHORTCUT("script_editor/zoom_out", p_event)) {
_zoom_out();
accept_event();
+ return;
}
if (ED_IS_SHORTCUT("script_editor/reset_zoom", p_event)) {
- _reset_zoom();
+ _zoom_to(1);
accept_event();
+ return;
}
}
}
}
-void CodeTextEditor::_zoom_in() {
- font_resize_val += MAX(EDSCALE, 1.0f);
- _zoom_changed();
-}
-
-void CodeTextEditor::_zoom_out() {
- font_resize_val -= MAX(EDSCALE, 1.0f);
- _zoom_changed();
-}
-
-void CodeTextEditor::_zoom_changed() {
- if (font_resize_timer->get_time_left() == 0) {
- font_resize_timer->start();
- }
-}
-
-void CodeTextEditor::_reset_zoom() {
- EditorSettings::get_singleton()->set("interface/editor/code_font_size", 14);
- text_editor->add_theme_font_size_override("font_size", 14 * EDSCALE);
-}
-
void CodeTextEditor::_line_col_changed() {
if (!code_complete_timer->is_stopped() && code_complete_timer_line != text_editor->get_caret_line()) {
code_complete_timer->stop();
@@ -904,9 +893,6 @@ void CodeTextEditor::_line_col_changed() {
sb.append(" : ");
sb.append(itos(positional_column + 1).lpad(3));
- sb.append(" | ");
- sb.append(text_editor->is_indent_using_spaces() ? TTR("Spaces", "Indentation") : TTR("Tabs", "Indentation"));
-
line_and_col_txt->set_text(sb.as_string());
if (find_replace_bar) {
@@ -1010,24 +996,6 @@ Ref<Texture2D> CodeTextEditor::_get_completion_icon(const ScriptLanguage::CodeCo
return tex;
}
-void CodeTextEditor::_font_resize_timeout() {
- if (_add_font_size(font_resize_val)) {
- font_resize_val = 0;
- }
-}
-
-bool CodeTextEditor::_add_font_size(int p_delta) {
- int old_size = text_editor->get_theme_font_size(SNAME("font_size"));
- int new_size = CLAMP(old_size + p_delta, 8 * EDSCALE, 96 * EDSCALE);
-
- if (new_size != old_size) {
- EditorSettings::get_singleton()->set("interface/editor/code_font_size", new_size / EDSCALE);
- text_editor->add_theme_font_size_override("font_size", new_size);
- }
-
- return true;
-}
-
void CodeTextEditor::update_editor_settings() {
// Theme: Highlighting
completion_font_color = EDITOR_GET("text_editor/theme/highlighting/completion_font_color");
@@ -1068,12 +1036,16 @@ void CodeTextEditor::update_editor_settings() {
text_editor->set_drag_and_drop_selection_enabled(EDITOR_GET("text_editor/behavior/navigation/drag_and_drop_selection"));
// Behavior: indent
- text_editor->set_indent_using_spaces(EDITOR_GET("text_editor/behavior/indent/type"));
+ 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"));
// Completion
text_editor->set_auto_brace_completion_enabled(EDITOR_GET("text_editor/completion/auto_brace_complete"));
+ text_editor->set_code_hint_draw_below(EDITOR_GET("text_editor/completion/put_callhint_tooltip_below_current_line"));
+ code_complete_enabled = EDITOR_GET("text_editor/completion/code_complete_enabled");
+ code_complete_timer->set_wait_time(EDITOR_GET("text_editor/completion/code_complete_delay"));
+ idle->set_wait_time(EDITOR_GET("text_editor/completion/idle_parse_delay"));
// Appearance: Guidelines
if (EDITOR_GET("text_editor/appearance/guidelines/show_line_length_guidelines")) {
@@ -1086,6 +1058,9 @@ void CodeTextEditor::update_editor_settings() {
} else {
text_editor->set_line_length_guidelines(TypedArray<int>());
}
+
+ _update_font_ligatures();
+ set_zoom_factor(zoom_factor);
}
void CodeTextEditor::set_find_replace_bar(FindReplaceBar *p_bar) {
@@ -1203,6 +1178,11 @@ void CodeTextEditor::convert_case(CaseStyle p_case) {
text_editor->end_complex_operation();
}
+void CodeTextEditor::set_indent_using_spaces(bool p_use_spaces) {
+ text_editor->set_indent_using_spaces(p_use_spaces);
+ indentation_txt->set_text(p_use_spaces ? TTR("Spaces", "Indentation") : TTR("Tabs", "Indentation"));
+}
+
void CodeTextEditor::move_lines_up() {
text_editor->begin_complex_operation();
@@ -1703,41 +1683,38 @@ void CodeTextEditor::goto_error() {
}
void CodeTextEditor::_update_text_editor_theme() {
+ if (!EditorThemeManager::is_generated_theme_outdated()) {
+ return;
+ }
+
emit_signal(SNAME("load_theme_settings"));
- error->begin_bulk_theme_override();
- error->add_theme_font_override(SNAME("font"), get_theme_font(SNAME("status_source"), EditorStringName(EditorFonts)));
- error->add_theme_font_size_override(SNAME("font_size"), get_theme_font_size(SNAME("status_source_size"), EditorStringName(EditorFonts)));
- error->add_theme_color_override(SNAME("font_color"), get_theme_color(SNAME("error_color"), EditorStringName(Editor)));
+ error_button->set_icon(get_editor_theme_icon(SNAME("StatusError")));
+ warning_button->set_icon(get_editor_theme_icon(SNAME("NodeWarning")));
Ref<Font> status_bar_font = get_theme_font(SNAME("status_source"), EditorStringName(EditorFonts));
int status_bar_font_size = get_theme_font_size(SNAME("status_source_size"), EditorStringName(EditorFonts));
- error->add_theme_font_override("font", status_bar_font);
- error->add_theme_font_size_override("font_size", status_bar_font_size);
- error->end_bulk_theme_override();
int count = status_bar->get_child_count();
for (int i = 0; i < count; i++) {
Control *n = Object::cast_to<Control>(status_bar->get_child(i));
if (n) {
- n->add_theme_font_override("font", status_bar_font);
- n->add_theme_font_size_override("font_size", status_bar_font_size);
+ n->add_theme_font_override(SNAME("font"), status_bar_font);
+ n->add_theme_font_size_override(SNAME("font_size"), status_bar_font_size);
}
}
-}
-void CodeTextEditor::_on_settings_change() {
- if (EditorThemeManager::is_generated_theme_outdated() ||
- EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor") ||
- EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor/completion")) {
- _apply_settings_change();
- }
-}
+ const Color &error_color = get_theme_color(SNAME("error_color"), EditorStringName(Editor));
+ const Color &warning_color = get_theme_color(SNAME("warning_color"), EditorStringName(Editor));
-void CodeTextEditor::_apply_settings_change() {
- _update_text_editor_theme();
+ error->add_theme_color_override(SNAME("font_color"), error_color);
+ error_button->add_theme_color_override(SNAME("font_color"), error_color);
+ warning_button->add_theme_color_override(SNAME("font_color"), warning_color);
+
+ _update_font_ligatures();
+}
- font_size = EDITOR_GET("interface/editor/code_font_size");
+void CodeTextEditor::_update_font_ligatures() {
int ot_mode = EDITOR_GET("interface/editor/code_font_contextual_ligatures");
Ref<FontVariation> fc = text_editor->get_theme_font(SNAME("font"));
@@ -1768,12 +1745,6 @@ void CodeTextEditor::_apply_settings_change() {
} break;
}
}
-
- text_editor->set_code_hint_draw_below(EDITOR_GET("text_editor/completion/put_callhint_tooltip_below_current_line"));
-
- code_complete_enabled = EDITOR_GET("text_editor/completion/code_complete_enabled");
- code_complete_timer->set_wait_time(EDITOR_GET("text_editor/completion/code_complete_delay"));
- idle->set_wait_time(EDITOR_GET("text_editor/completion/idle_parse_delay"));
}
void CodeTextEditor::_text_changed_idle_timeout() {
@@ -1795,6 +1766,10 @@ void CodeTextEditor::_warning_button_pressed() {
_set_show_errors_panel(false);
}
+void CodeTextEditor::_zoom_popup_id_pressed(int p_idx) {
+ _zoom_to(zoom_button->get_popup()->get_item_metadata(p_idx));
+}
+
void CodeTextEditor::_set_show_errors_panel(bool p_show) {
is_errors_panel_opened = p_show;
emit_signal(SNAME("show_errors_panel"), p_show);
@@ -1833,32 +1808,9 @@ void CodeTextEditor::_error_pressed(const Ref<InputEvent> &p_event) {
}
}
-void CodeTextEditor::_update_status_bar_theme() {
- error_button->set_icon(get_editor_theme_icon(SNAME("StatusError")));
- warning_button->set_icon(get_editor_theme_icon(SNAME("NodeWarning")));
-
- error_button->begin_bulk_theme_override();
- error_button->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), EditorStringName(Editor)));
- error_button->add_theme_font_override("font", get_theme_font(SNAME("status_source"), EditorStringName(EditorFonts)));
- error_button->add_theme_font_size_override("font_size", get_theme_font_size(SNAME("status_source_size"), EditorStringName(EditorFonts)));
- error_button->end_bulk_theme_override();
-
- warning_button->begin_bulk_theme_override();
- warning_button->add_theme_color_override("font_color", get_theme_color(SNAME("warning_color"), EditorStringName(Editor)));
- warning_button->add_theme_font_override("font", get_theme_font(SNAME("status_source"), EditorStringName(EditorFonts)));
- warning_button->add_theme_font_size_override("font_size", get_theme_font_size(SNAME("status_source_size"), EditorStringName(EditorFonts)));
- warning_button->end_bulk_theme_override();
-
- line_and_col_txt->begin_bulk_theme_override();
- line_and_col_txt->add_theme_font_override("font", get_theme_font(SNAME("status_source"), EditorStringName(EditorFonts)));
- line_and_col_txt->add_theme_font_size_override("font_size", get_theme_font_size(SNAME("status_source_size"), EditorStringName(EditorFonts)));
- line_and_col_txt->end_bulk_theme_override();
-}
-
void CodeTextEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED: {
- _update_status_bar_theme();
if (toggle_scripts_button->is_visible()) {
update_toggle_scripts_button();
}
@@ -1966,11 +1918,54 @@ void CodeTextEditor::remove_all_bookmarks() {
text_editor->clear_bookmarked_lines();
}
+void CodeTextEditor::_zoom_in() {
+ int s = text_editor->get_theme_font_size("font_size");
+ _zoom_to(zoom_factor * (s + MAX(1.0f, EDSCALE)) / s);
+}
+
+void CodeTextEditor::_zoom_out() {
+ int s = text_editor->get_theme_font_size("font_size");
+ _zoom_to(zoom_factor * (s - MAX(1.0f, EDSCALE)) / s);
+}
+
+void CodeTextEditor::_zoom_to(float p_zoom_factor) {
+ if (zoom_factor == p_zoom_factor) {
+ return;
+ }
+
+ float old_zoom_factor = zoom_factor;
+
+ set_zoom_factor(p_zoom_factor);
+
+ if (old_zoom_factor != zoom_factor) {
+ emit_signal(SNAME("zoomed"), zoom_factor);
+ }
+}
+
+void CodeTextEditor::set_zoom_factor(float p_zoom_factor) {
+ int preset_count = sizeof(ZOOM_FACTOR_PRESETS) / sizeof(float);
+ zoom_factor = CLAMP(p_zoom_factor, ZOOM_FACTOR_PRESETS[0], ZOOM_FACTOR_PRESETS[preset_count - 1]);
+ int neutral_font_size = int(EDITOR_GET("interface/editor/code_font_size")) * EDSCALE;
+ int new_font_size = Math::round(zoom_factor * neutral_font_size);
+
+ zoom_button->set_text(itos(Math::round(zoom_factor * 100)) + " %");
+
+ if (text_editor->has_theme_font_size_override("font_size")) {
+ text_editor->remove_theme_font_size_override("font_size");
+ }
+ text_editor->add_theme_font_size_override("font_size", new_font_size);
+}
+
+float CodeTextEditor::get_zoom_factor() {
+ return zoom_factor;
+}
+
void CodeTextEditor::_bind_methods() {
ADD_SIGNAL(MethodInfo("validate_script"));
ADD_SIGNAL(MethodInfo("load_theme_settings"));
ADD_SIGNAL(MethodInfo("show_errors_panel"));
ADD_SIGNAL(MethodInfo("show_warnings_panel"));
+ ADD_SIGNAL(MethodInfo("zoomed", PropertyInfo(Variant::FLOAT, "p_zoom_factor")));
}
void CodeTextEditor::set_code_complete_func(CodeTextEditorCodeCompleteFunc p_code_complete_func, void *p_ud) {
@@ -2004,36 +1999,6 @@ CodeTextEditor::CodeTextEditor() {
text_editor->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_GDSCRIPT);
text_editor->set_draw_bookmarks_gutter(true);
- int ot_mode = EDITOR_GET("interface/editor/code_font_contextual_ligatures");
- Ref<FontVariation> fc = text_editor->get_theme_font(SNAME("font"));
- if (fc.is_valid()) {
- switch (ot_mode) {
- case 1: { // Disable ligatures.
- Dictionary ftrs;
- ftrs[TS->name_to_tag("calt")] = 0;
- fc->set_opentype_features(ftrs);
- } break;
- case 2: { // Custom.
- Vector<String> subtag = String(EDITOR_GET("interface/editor/code_font_custom_opentype_features")).split(",");
- Dictionary ftrs;
- for (int i = 0; i < subtag.size(); i++) {
- Vector<String> subtag_a = subtag[i].split("=");
- if (subtag_a.size() == 2) {
- ftrs[TS->name_to_tag(subtag_a[0])] = subtag_a[1].to_int();
- } else if (subtag_a.size() == 1) {
- ftrs[TS->name_to_tag(subtag_a[0])] = 1;
- }
- }
- fc->set_opentype_features(ftrs);
- } break;
- default: { // Enabled.
- Dictionary ftrs;
- ftrs[TS->name_to_tag("calt")] = 1;
- fc->set_opentype_features(ftrs);
- } break;
- }
- }
-
text_editor->set_draw_line_numbers(true);
text_editor->set_highlight_matching_braces_enabled(true);
text_editor->set_auto_indent_enabled(true);
@@ -2047,19 +2012,18 @@ CodeTextEditor::CodeTextEditor() {
idle = memnew(Timer);
add_child(idle);
idle->set_one_shot(true);
- idle->set_wait_time(EDITOR_GET("text_editor/completion/idle_parse_delay"));
code_complete_enabled = EDITOR_GET("text_editor/completion/code_complete_enabled");
code_complete_timer = memnew(Timer);
add_child(code_complete_timer);
code_complete_timer->set_one_shot(true);
- code_complete_timer->set_wait_time(EDITOR_GET("text_editor/completion/code_complete_delay"));
error_line = 0;
error_column = 0;
toggle_scripts_button = memnew(Button);
toggle_scripts_button->set_flat(true);
+ toggle_scripts_button->set_v_size_flags(SIZE_EXPAND | SIZE_SHRINK_CENTER);
toggle_scripts_button->connect("pressed", callable_mp(this, &CodeTextEditor::_toggle_scripts_pressed));
status_bar->add_child(toggle_scripts_button);
toggle_scripts_button->hide();
@@ -2097,6 +2061,29 @@ CodeTextEditor::CodeTextEditor() {
warning_button->set_tooltip_text(TTR("Warnings"));
set_warning_count(0);
+ status_bar->add_child(memnew(VSeparator));
+
+ // Zoom
+ zoom_button = memnew(MenuButton);
+ status_bar->add_child(zoom_button);
+ zoom_button->set_flat(true);
+ zoom_button->set_v_size_flags(SIZE_EXPAND | SIZE_SHRINK_CENTER);
+ zoom_button->set_tooltip_text(TTR("Zoom factor"));
+ zoom_button->set_text("100 %");
+
+ PopupMenu *zoom_menu = zoom_button->get_popup();
+ int preset_count = sizeof(ZOOM_FACTOR_PRESETS) / sizeof(float);
+
+ for (int i = 0; i < preset_count; i++) {
+ float z = ZOOM_FACTOR_PRESETS[i];
+ zoom_menu->add_item(itos(Math::round(z * 100)) + " %");
+ zoom_menu->set_item_metadata(i, z);
+ }
+
+ zoom_menu->connect("id_pressed", callable_mp(this, &CodeTextEditor::_zoom_popup_id_pressed));
+
+ status_bar->add_child(memnew(VSeparator));
+
// Line and column
line_and_col_txt = memnew(Label);
status_bar->add_child(line_and_col_txt);
@@ -2104,6 +2091,15 @@ CodeTextEditor::CodeTextEditor() {
line_and_col_txt->set_tooltip_text(TTR("Line and column numbers."));
line_and_col_txt->set_mouse_filter(MOUSE_FILTER_STOP);
+ status_bar->add_child(memnew(VSeparator));
+
+ // Indentation
+ indentation_txt = memnew(Label);
+ status_bar->add_child(indentation_txt);
+ indentation_txt->set_v_size_flags(SIZE_EXPAND | SIZE_SHRINK_CENTER);
+ indentation_txt->set_tooltip_text(TTR("Indentation"));
+ indentation_txt->set_mouse_filter(MOUSE_FILTER_STOP);
+
text_editor->connect("gui_input", callable_mp(this, &CodeTextEditor::_text_editor_gui_input));
text_editor->connect("caret_changed", callable_mp(this, &CodeTextEditor::_line_col_changed));
text_editor->connect("text_changed", callable_mp(this, &CodeTextEditor::_text_changed));
@@ -2122,14 +2118,5 @@ CodeTextEditor::CodeTextEditor() {
code_complete_timer->connect("timeout", callable_mp(this, &CodeTextEditor::_code_complete_timer_timeout));
- font_resize_val = 0;
- font_size = EDITOR_GET("interface/editor/code_font_size");
- font_resize_timer = memnew(Timer);
- add_child(font_resize_timer);
- font_resize_timer->set_one_shot(true);
- font_resize_timer->set_wait_time(0.07);
- font_resize_timer->connect("timeout", callable_mp(this, &CodeTextEditor::_font_resize_timeout));
-
- EditorSettings::get_singleton()->connect("settings_changed", callable_mp(this, &CodeTextEditor::_on_settings_change));
add_theme_constant_override("separation", 4 * EDSCALE);
}
diff --git a/editor/code_editor.h b/editor/code_editor.h
index 9d8a3a2229..c888619ac0 100644
--- a/editor/code_editor.h
+++ b/editor/code_editor.h
@@ -40,6 +40,8 @@
#include "scene/gui/line_edit.h"
#include "scene/main/timer.h"
+class MenuButton;
+
class GotoLineDialog : public ConfirmationDialog {
GDCLASS(GotoLineDialog, ConfirmationDialog);
@@ -156,7 +158,9 @@ class CodeTextEditor : public VBoxContainer {
Button *error_button = nullptr;
Button *warning_button = nullptr;
+ MenuButton *zoom_button = nullptr;
Label *line_and_col_txt = nullptr;
+ Label *indentation_txt = nullptr;
Label *info = nullptr;
Timer *idle = nullptr;
@@ -164,29 +168,19 @@ class CodeTextEditor : public VBoxContainer {
Timer *code_complete_timer = nullptr;
int code_complete_timer_line = 0;
- Timer *font_resize_timer = nullptr;
- int font_resize_val;
- real_t font_size;
+ float zoom_factor = 1.0f;
Label *error = nullptr;
int error_line;
int error_column;
- void _on_settings_change();
- void _apply_settings_change();
-
void _update_text_editor_theme();
+ void _update_font_ligatures();
void _complete_request();
Ref<Texture2D> _get_completion_icon(const ScriptLanguage::CodeCompletionOption &p_option);
- void _font_resize_timeout();
- bool _add_font_size(int p_delta);
virtual void input(const Ref<InputEvent> &event) override;
void _text_editor_gui_input(const Ref<InputEvent> &p_event);
- void _zoom_in();
- void _zoom_out();
- void _zoom_changed();
- void _reset_zoom();
Color completion_font_color;
Color completion_string_color;
@@ -195,13 +189,17 @@ class CodeTextEditor : public VBoxContainer {
CodeTextEditorCodeCompleteFunc code_complete_func;
void *code_complete_ud = nullptr;
+ void _zoom_in();
+ void _zoom_out();
+ void _zoom_to(float p_zoom_factor);
+
void _error_button_pressed();
void _warning_button_pressed();
void _set_show_errors_panel(bool p_show);
void _set_show_warnings_panel(bool p_show);
void _error_pressed(const Ref<InputEvent> &p_event);
- void _update_status_bar_theme();
+ void _zoom_popup_id_pressed(int p_idx);
void _toggle_scripts_pressed();
@@ -234,6 +232,8 @@ public:
};
void convert_case(CaseStyle p_case);
+ void set_indent_using_spaces(bool p_use_spaces);
+
void move_lines_up();
void move_lines_down();
void delete_lines();
@@ -273,6 +273,9 @@ public:
void goto_prev_bookmark();
void remove_all_bookmarks();
+ void set_zoom_factor(float p_zoom_factor);
+ float get_zoom_factor();
+
void set_code_complete_func(CodeTextEditorCodeCompleteFunc p_code_complete_func, void *p_ud);
void validate_script();
diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp
index f5b8d04444..9b883f7661 100644
--- a/editor/editor_properties_array_dict.cpp
+++ b/editor/editor_properties_array_dict.cpp
@@ -780,9 +780,19 @@ void EditorPropertyDictionary::_add_key_value() {
}
Dictionary dict = object->get_dict().duplicate();
- dict[object->get_new_item_key()] = object->get_new_item_value();
- object->set_new_item_key(Variant());
- object->set_new_item_value(Variant());
+ Variant new_key = object->get_new_item_key();
+ Variant new_value = object->get_new_item_value();
+ dict[new_key] = new_value;
+
+ Variant::Type type = new_key.get_type();
+ new_key.zero();
+ VariantInternal::initialize(&new_key, type);
+ object->set_new_item_key(new_key);
+
+ type = new_value.get_type();
+ new_value.zero();
+ VariantInternal::initialize(&new_value, type);
+ object->set_new_item_value(new_value);
emit_changed(get_edited_property(), dict, "", false);
update_property();
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index d1d858b4db..32dae74ba4 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -38,6 +38,7 @@
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "core/version.h"
+#include "editor/code_editor.h"
#include "editor/debugger/editor_debugger_node.h"
#include "editor/debugger/script_editor_debugger.h"
#include "editor/editor_command_palette.h"
@@ -1639,7 +1640,7 @@ void ScriptEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
EditorRunBar::get_singleton()->connect("stop_pressed", callable_mp(this, &ScriptEditor::_editor_stop));
- _editor_settings_changed();
+ _apply_editor_settings();
[[fallthrough]];
}
@@ -2481,6 +2482,12 @@ bool ScriptEditor::edit(const Ref<Resource> &p_resource, int p_line, int p_col,
se->connect("replace_in_files_requested", callable_mp(this, &ScriptEditor::_on_replace_in_files_requested));
se->connect("go_to_method", callable_mp(this, &ScriptEditor::script_goto_method));
+ CodeTextEditor *cte = se->get_code_editor();
+ if (cte) {
+ cte->set_zoom_factor(zoom_factor);
+ cte->connect("zoomed", callable_mp(this, &ScriptEditor::_set_zoom_factor));
+ }
+
//test for modification, maybe the script was not edited but was loaded
_test_script_times_on_disk(p_resource);
@@ -2779,11 +2786,16 @@ void ScriptEditor::_save_layout() {
}
void ScriptEditor::_editor_settings_changed() {
- if (!EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor") &&
+ if (!EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor") &&
+ !EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor") &&
!EditorSettings::get_singleton()->check_changed_settings_in_group("docks/filesystem")) {
return;
}
+ _apply_editor_settings();
+}
+
+void ScriptEditor::_apply_editor_settings() {
textfile_extensions.clear();
const Vector<String> textfile_ext = ((String)(EDITOR_GET("docks/filesystem/textfile_extensions"))).split(",", false);
for (const String &E : textfile_ext) {
@@ -2808,6 +2820,11 @@ void ScriptEditor::_editor_settings_changed() {
EditorSettings::get_singleton()->load_text_editor_theme();
}
+ _update_script_colors();
+ _update_script_names();
+
+ ScriptServer::set_reload_scripts_on_save(EDITOR_GET("text_editor/behavior/files/auto_reload_and_parse_scripts_on_save"));
+
for (int i = 0; i < tab_container->get_tab_count(); i++) {
ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(tab_container->get_tab_control(i));
if (!se) {
@@ -2816,10 +2833,6 @@ void ScriptEditor::_editor_settings_changed() {
se->update_settings();
}
- _update_script_colors();
- _update_script_names();
-
- ScriptServer::set_reload_scripts_on_save(EDITOR_GET("text_editor/behavior/files/auto_reload_and_parse_scripts_on_save"));
}
void ScriptEditor::_filesystem_changed() {
@@ -3322,6 +3335,8 @@ void ScriptEditor::set_window_layout(Ref<ConfigFile> p_layout) {
}
}
+ _set_zoom_factor(p_layout->get_value("ScriptEditor", "zoom_factor", 1.0f));
+
restoring_layout = false;
_update_script_names();
@@ -3371,6 +3386,7 @@ void ScriptEditor::get_window_layout(Ref<ConfigFile> p_layout) {
p_layout->set_value("ScriptEditor", "open_help", helps);
p_layout->set_value("ScriptEditor", "script_split_offset", script_split->get_split_offset());
p_layout->set_value("ScriptEditor", "list_split_offset", list_split->get_split_offset());
+ p_layout->set_value("ScriptEditor", "zoom_factor", zoom_factor);
// Save the cache.
script_editor_cache->save(EditorPaths::get_singleton()->get_project_settings_dir().path_join("script_editor_cache.cfg"));
@@ -3806,6 +3822,24 @@ void ScriptEditor::_on_find_in_files_modified_files(PackedStringArray paths) {
_update_modified_scripts_for_external_editor();
}
+void ScriptEditor::_set_zoom_factor(float p_zoom_factor) {
+ if (zoom_factor == p_zoom_factor) {
+ return;
+ }
+ zoom_factor = p_zoom_factor;
+ for (int i = 0; i < tab_container->get_tab_count(); i++) {
+ ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(tab_container->get_tab_control(i));
+ if (se) {
+ CodeTextEditor *cte = se->get_code_editor();
+ if (cte) {
+ if (zoom_factor != cte->get_zoom_factor()) {
+ cte->set_zoom_factor(zoom_factor);
+ }
+ }
+ }
+ }
+}
+
void ScriptEditor::_window_changed(bool p_visible) {
make_floating->set_visible(!p_visible);
is_floating = p_visible;
diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h
index 68eb23c838..752c1a6a05 100644
--- a/editor/plugins/script_editor_plugin.h
+++ b/editor/plugins/script_editor_plugin.h
@@ -38,6 +38,7 @@
#include "scene/resources/syntax_highlighter.h"
#include "scene/resources/text_file.h"
+class CodeTextEditor;
class EditorFileDialog;
class EditorHelpSearch;
class FindReplaceBar;
@@ -192,6 +193,7 @@ public:
virtual void set_find_replace_bar(FindReplaceBar *p_bar) = 0;
virtual Control *get_base_editor() const = 0;
+ virtual CodeTextEditor *get_code_editor() const = 0;
virtual void validate() = 0;
@@ -306,6 +308,8 @@ class ScriptEditor : public PanelContainer {
String current_theme;
+ float zoom_factor = 1.0f;
+
TextureRect *script_icon = nullptr;
Label *script_name_label = nullptr;
@@ -420,6 +424,7 @@ class ScriptEditor : public PanelContainer {
void _save_editor_state(ScriptEditorBase *p_editor);
void _save_layout();
void _editor_settings_changed();
+ void _apply_editor_settings();
void _filesystem_changed();
void _files_moved(const String &p_old_file, const String &p_new_file);
void _file_removed(const String &p_file);
@@ -491,6 +496,8 @@ class ScriptEditor : public PanelContainer {
void _start_find_in_files(bool with_replace);
void _on_find_in_files_modified_files(PackedStringArray paths);
+ void _set_zoom_factor(float p_zoom_factor);
+
void _window_changed(bool p_visible);
static void _open_script_request(const String &p_path);
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index 9fbeab494e..ce5535432c 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -1393,11 +1393,11 @@ void ScriptTextEditor::_edit_option(int p_op) {
trim_trailing_whitespace();
} break;
case EDIT_CONVERT_INDENT_TO_SPACES: {
- tx->set_indent_using_spaces(true);
+ code_editor->set_indent_using_spaces(true);
convert_indent();
} break;
case EDIT_CONVERT_INDENT_TO_TABS: {
- tx->set_indent_using_spaces(false);
+ code_editor->set_indent_using_spaces(false);
convert_indent();
} break;
case EDIT_PICK_COLOR: {
@@ -1691,6 +1691,10 @@ Control *ScriptTextEditor::get_base_editor() const {
return code_editor->get_text_editor();
}
+CodeTextEditor *ScriptTextEditor::get_code_editor() const {
+ return code_editor;
+}
+
Variant ScriptTextEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
return Variant();
}
@@ -2374,8 +2378,6 @@ ScriptTextEditor::ScriptTextEditor() {
update_settings();
- code_editor->get_text_editor()->set_code_hint_draw_below(EDITOR_GET("text_editor/completion/put_callhint_tooltip_below_current_line"));
-
code_editor->get_text_editor()->set_symbol_lookup_on_click_enabled(true);
code_editor->get_text_editor()->set_context_menu_enabled(false);
diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h
index 8c0ba6d7e6..820e86df61 100644
--- a/editor/plugins/script_text_editor.h
+++ b/editor/plugins/script_text_editor.h
@@ -256,6 +256,7 @@ public:
static void register_editor();
virtual Control *get_base_editor() const override;
+ virtual CodeTextEditor *get_code_editor() const override;
virtual void validate() override;
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index f8e2bd0915..cce1f160b2 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -143,7 +143,6 @@ void ShaderEditorPlugin::edit(Object *p_object) {
es.shader_editor = memnew(TextShaderEditor);
es.shader_editor->edit(si);
shader_tabs->add_child(es.shader_editor);
- es.shader_editor->connect("validation_changed", callable_mp(this, &ShaderEditorPlugin::_update_shader_list));
} else {
Shader *s = Object::cast_to<Shader>(p_object);
for (uint32_t i = 0; i < edited_shaders.size(); i++) {
@@ -163,7 +162,16 @@ void ShaderEditorPlugin::edit(Object *p_object) {
es.shader_editor = memnew(TextShaderEditor);
shader_tabs->add_child(es.shader_editor);
es.shader_editor->edit(s);
- es.shader_editor->connect("validation_changed", callable_mp(this, &ShaderEditorPlugin::_update_shader_list));
+ }
+ }
+
+ if (es.shader_editor) {
+ es.shader_editor->connect("validation_changed", callable_mp(this, &ShaderEditorPlugin::_update_shader_list));
+
+ CodeTextEditor *cte = es.shader_editor->get_code_editor();
+ if (cte) {
+ cte->set_zoom_factor(text_shader_zoom_factor);
+ cte->connect("zoomed", callable_mp(this, &ShaderEditorPlugin::_set_text_shader_zoom_factor));
}
}
@@ -244,6 +252,8 @@ void ShaderEditorPlugin::set_window_layout(Ref<ConfigFile> p_layout) {
_update_shader_list();
_shader_selected(selected_shader_idx);
+
+ _set_text_shader_zoom_factor(p_layout->get_value("ShaderEditor", "text_shader_zoom_factor", 1.0f));
}
void ShaderEditorPlugin::get_window_layout(Ref<ConfigFile> p_layout) {
@@ -290,6 +300,7 @@ void ShaderEditorPlugin::get_window_layout(Ref<ConfigFile> p_layout) {
p_layout->set_value("ShaderEditor", "open_shaders", shaders);
p_layout->set_value("ShaderEditor", "split_offset", main_split->get_split_offset());
p_layout->set_value("ShaderEditor", "selected_shader", selected_shader);
+ p_layout->set_value("ShaderEditor", "text_shader_zoom_factor", text_shader_zoom_factor);
}
String ShaderEditorPlugin::get_unsaved_status(const String &p_for_scene) const {
@@ -590,6 +601,20 @@ void ShaderEditorPlugin::_window_changed(bool p_visible) {
make_floating->set_visible(!p_visible);
}
+void ShaderEditorPlugin::_set_text_shader_zoom_factor(float p_zoom_factor) {
+ if (text_shader_zoom_factor != p_zoom_factor) {
+ text_shader_zoom_factor = p_zoom_factor;
+ for (const EditedShader &edited_shader : edited_shaders) {
+ if (edited_shader.shader_editor) {
+ CodeTextEditor *cte = edited_shader.shader_editor->get_code_editor();
+ if (cte && cte->get_zoom_factor() != text_shader_zoom_factor) {
+ cte->set_zoom_factor(text_shader_zoom_factor);
+ }
+ }
+ }
+ }
+}
+
void ShaderEditorPlugin::_file_removed(const String &p_removed_file) {
for (uint32_t i = 0; i < edited_shaders.size(); i++) {
if (edited_shaders[i].path == p_removed_file) {
diff --git a/editor/plugins/shader_editor_plugin.h b/editor/plugins/shader_editor_plugin.h
index ea50d62b8f..84c5a620a7 100644
--- a/editor/plugins/shader_editor_plugin.h
+++ b/editor/plugins/shader_editor_plugin.h
@@ -86,6 +86,8 @@ class ShaderEditorPlugin : public EditorPlugin {
ShaderCreateDialog *shader_create_dialog = nullptr;
+ float text_shader_zoom_factor = 1.0f;
+
void _update_shader_list();
void _shader_selected(int p_index);
void _shader_list_clicked(int p_item, Vector2 p_local_mouse_pos, MouseButton p_mouse_button_index);
@@ -106,6 +108,8 @@ class ShaderEditorPlugin : public EditorPlugin {
void _window_changed(bool p_visible);
+ void _set_text_shader_zoom_factor(float p_zoom_factor);
+
protected:
void _notification(int p_what);
diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp
index c9a0cbd2de..465785a3b7 100644
--- a/editor/plugins/text_editor.cpp
+++ b/editor/plugins/text_editor.cpp
@@ -150,6 +150,10 @@ Control *TextEditor::get_base_editor() const {
return code_editor->get_text_editor();
}
+CodeTextEditor *TextEditor::get_code_editor() const {
+ return code_editor;
+}
+
PackedInt32Array TextEditor::get_breakpoints() {
return PackedInt32Array();
}
@@ -419,11 +423,11 @@ void TextEditor::_edit_option(int p_op) {
trim_trailing_whitespace();
} break;
case EDIT_CONVERT_INDENT_TO_SPACES: {
- tx->set_indent_using_spaces(true);
+ code_editor->set_indent_using_spaces(true);
convert_indent();
} break;
case EDIT_CONVERT_INDENT_TO_TABS: {
- tx->set_indent_using_spaces(false);
+ code_editor->set_indent_using_spaces(false);
convert_indent();
} break;
case EDIT_TO_UPPERCASE: {
diff --git a/editor/plugins/text_editor.h b/editor/plugins/text_editor.h
index a4ec2d882b..38dca9eb28 100644
--- a/editor/plugins/text_editor.h
+++ b/editor/plugins/text_editor.h
@@ -152,6 +152,7 @@ public:
virtual void validate() override;
virtual Control *get_base_editor() const override;
+ virtual CodeTextEditor *get_code_editor() const override;
static void register_editor();
diff --git a/editor/plugins/text_shader_editor.cpp b/editor/plugins/text_shader_editor.cpp
index 17b48118ac..ad64e1d1d7 100644
--- a/editor/plugins/text_shader_editor.cpp
+++ b/editor/plugins/text_shader_editor.cpp
@@ -628,100 +628,100 @@ ShaderTextEditor::ShaderTextEditor() {
/*** SCRIPT EDITOR ******/
void TextShaderEditor::_menu_option(int p_option) {
- shader_editor->get_text_editor()->apply_ime();
+ code_editor->get_text_editor()->apply_ime();
switch (p_option) {
case EDIT_UNDO: {
- shader_editor->get_text_editor()->undo();
+ code_editor->get_text_editor()->undo();
} break;
case EDIT_REDO: {
- shader_editor->get_text_editor()->redo();
+ code_editor->get_text_editor()->redo();
} break;
case EDIT_CUT: {
- shader_editor->get_text_editor()->cut();
+ code_editor->get_text_editor()->cut();
} break;
case EDIT_COPY: {
- shader_editor->get_text_editor()->copy();
+ code_editor->get_text_editor()->copy();
} break;
case EDIT_PASTE: {
- shader_editor->get_text_editor()->paste();
+ code_editor->get_text_editor()->paste();
} break;
case EDIT_SELECT_ALL: {
- shader_editor->get_text_editor()->select_all();
+ code_editor->get_text_editor()->select_all();
} break;
case EDIT_MOVE_LINE_UP: {
- shader_editor->move_lines_up();
+ code_editor->move_lines_up();
} break;
case EDIT_MOVE_LINE_DOWN: {
- shader_editor->move_lines_down();
+ code_editor->move_lines_down();
} break;
case EDIT_INDENT: {
if (shader.is_null() && shader_inc.is_null()) {
return;
}
- shader_editor->get_text_editor()->indent_lines();
+ code_editor->get_text_editor()->indent_lines();
} break;
case EDIT_UNINDENT: {
if (shader.is_null() && shader_inc.is_null()) {
return;
}
- shader_editor->get_text_editor()->unindent_lines();
+ code_editor->get_text_editor()->unindent_lines();
} break;
case EDIT_DELETE_LINE: {
- shader_editor->delete_lines();
+ code_editor->delete_lines();
} break;
case EDIT_DUPLICATE_SELECTION: {
- shader_editor->duplicate_selection();
+ code_editor->duplicate_selection();
} break;
case EDIT_DUPLICATE_LINES: {
- shader_editor->get_text_editor()->duplicate_lines();
+ code_editor->get_text_editor()->duplicate_lines();
} break;
case EDIT_TOGGLE_WORD_WRAP: {
- TextEdit::LineWrappingMode wrap = shader_editor->get_text_editor()->get_line_wrapping_mode();
- shader_editor->get_text_editor()->set_line_wrapping_mode(wrap == TextEdit::LINE_WRAPPING_BOUNDARY ? TextEdit::LINE_WRAPPING_NONE : TextEdit::LINE_WRAPPING_BOUNDARY);
+ TextEdit::LineWrappingMode wrap = code_editor->get_text_editor()->get_line_wrapping_mode();
+ code_editor->get_text_editor()->set_line_wrapping_mode(wrap == TextEdit::LINE_WRAPPING_BOUNDARY ? TextEdit::LINE_WRAPPING_NONE : TextEdit::LINE_WRAPPING_BOUNDARY);
} break;
case EDIT_TOGGLE_COMMENT: {
if (shader.is_null() && shader_inc.is_null()) {
return;
}
- shader_editor->toggle_inline_comment("//");
+ code_editor->toggle_inline_comment("//");
} break;
case EDIT_COMPLETE: {
- shader_editor->get_text_editor()->request_code_completion();
+ code_editor->get_text_editor()->request_code_completion();
} break;
case SEARCH_FIND: {
- shader_editor->get_find_replace_bar()->popup_search();
+ code_editor->get_find_replace_bar()->popup_search();
} break;
case SEARCH_FIND_NEXT: {
- shader_editor->get_find_replace_bar()->search_next();
+ code_editor->get_find_replace_bar()->search_next();
} break;
case SEARCH_FIND_PREV: {
- shader_editor->get_find_replace_bar()->search_prev();
+ code_editor->get_find_replace_bar()->search_prev();
} break;
case SEARCH_REPLACE: {
- shader_editor->get_find_replace_bar()->popup_replace();
+ code_editor->get_find_replace_bar()->popup_replace();
} break;
case SEARCH_GOTO_LINE: {
- goto_line_dialog->popup_find_line(shader_editor->get_text_editor());
+ goto_line_dialog->popup_find_line(code_editor->get_text_editor());
} break;
case BOOKMARK_TOGGLE: {
- shader_editor->toggle_bookmark();
+ code_editor->toggle_bookmark();
} break;
case BOOKMARK_GOTO_NEXT: {
- shader_editor->goto_next_bookmark();
+ code_editor->goto_next_bookmark();
} break;
case BOOKMARK_GOTO_PREV: {
- shader_editor->goto_prev_bookmark();
+ code_editor->goto_prev_bookmark();
} break;
case BOOKMARK_REMOVE_ALL: {
- shader_editor->remove_all_bookmarks();
+ code_editor->remove_all_bookmarks();
} break;
case HELP_DOCS: {
OS::get_singleton()->shell_open(vformat("%s/tutorials/shaders/shader_reference/index.html", VERSION_DOCS_URL));
} break;
}
if (p_option != SEARCH_FIND && p_option != SEARCH_REPLACE && p_option != SEARCH_GOTO_LINE) {
- callable_mp((Control *)shader_editor->get_text_editor(), &Control::grab_focus).call_deferred();
+ callable_mp((Control *)code_editor->get_text_editor(), &Control::grab_focus).call_deferred();
}
}
@@ -740,14 +740,16 @@ void TextShaderEditor::_notification(int p_what) {
}
void TextShaderEditor::_editor_settings_changed() {
- if (!EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor")) {
+ if (!EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor") &&
+ !EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor")) {
return;
}
- shader_editor->update_editor_settings();
- shader_editor->get_text_editor()->add_theme_constant_override("line_spacing", EDITOR_GET("text_editor/appearance/whitespace/line_spacing"));
- shader_editor->get_text_editor()->set_draw_breakpoints_gutter(false);
- shader_editor->get_text_editor()->set_draw_executing_lines_gutter(false);
+ _apply_editor_settings();
+}
+
+void TextShaderEditor::_apply_editor_settings() {
+ code_editor->update_editor_settings();
trim_trailing_whitespace_on_save = EDITOR_GET("text_editor/behavior/files/trim_trailing_whitespace_on_save");
}
@@ -758,7 +760,7 @@ void TextShaderEditor::_show_warnings_panel(bool p_show) {
void TextShaderEditor::_warning_clicked(Variant p_line) {
if (p_line.get_type() == Variant::INT) {
- shader_editor->get_text_editor()->set_caret_line(p_line.operator int64_t());
+ code_editor->get_text_editor()->set_caret_line(p_line.operator int64_t());
}
}
@@ -773,7 +775,7 @@ void TextShaderEditor::ensure_select_current() {
}
void TextShaderEditor::goto_line_selection(int p_line, int p_begin, int p_end) {
- shader_editor->goto_line_selection(p_line, p_begin, p_end);
+ code_editor->goto_line_selection(p_line, p_begin, p_end);
}
void TextShaderEditor::_project_settings_changed() {
@@ -812,8 +814,8 @@ void TextShaderEditor::_update_warnings(bool p_validate) {
saved_warning_flags = (uint32_t)ShaderWarning::get_flags_from_codemap(saved_warnings);
}
- if (p_validate && changed && shader_editor && shader_editor->get_edited_shader().is_valid()) {
- shader_editor->validate_script();
+ if (p_validate && changed && code_editor && code_editor->get_edited_shader().is_valid()) {
+ code_editor->validate_script();
}
}
@@ -848,22 +850,22 @@ void TextShaderEditor::_reload_shader_from_disk() {
Ref<Shader> rel_shader = ResourceLoader::load(shader->get_path(), shader->get_class(), ResourceFormatLoader::CACHE_MODE_IGNORE);
ERR_FAIL_COND(!rel_shader.is_valid());
- shader_editor->set_block_shader_changed(true);
+ code_editor->set_block_shader_changed(true);
shader->set_code(rel_shader->get_code());
- shader_editor->set_block_shader_changed(false);
+ code_editor->set_block_shader_changed(false);
shader->set_last_modified_time(rel_shader->get_last_modified_time());
- shader_editor->reload_text();
+ code_editor->reload_text();
}
void TextShaderEditor::_reload_shader_include_from_disk() {
Ref<ShaderInclude> rel_shader_include = ResourceLoader::load(shader_inc->get_path(), shader_inc->get_class(), ResourceFormatLoader::CACHE_MODE_IGNORE);
ERR_FAIL_COND(!rel_shader_include.is_valid());
- shader_editor->set_block_shader_changed(true);
+ code_editor->set_block_shader_changed(true);
shader_inc->set_code(rel_shader_include->get_code());
- shader_editor->set_block_shader_changed(false);
+ code_editor->set_block_shader_changed(false);
shader_inc->set_last_modified_time(rel_shader_include->get_last_modified_time());
- shader_editor->reload_text();
+ code_editor->reload_text();
}
void TextShaderEditor::_reload() {
@@ -886,7 +888,7 @@ void TextShaderEditor::edit(const Ref<Shader> &p_shader) {
shader = p_shader;
shader_inc = Ref<ShaderInclude>();
- shader_editor->set_edited_shader(shader);
+ code_editor->set_edited_shader(shader);
}
void TextShaderEditor::edit(const Ref<ShaderInclude> &p_shader_inc) {
@@ -901,7 +903,7 @@ void TextShaderEditor::edit(const Ref<ShaderInclude> &p_shader_inc) {
shader_inc = p_shader_inc;
shader = Ref<Shader>();
- shader_editor->set_edited_shader_include(p_shader_inc);
+ code_editor->set_edited_shader_include(p_shader_inc);
}
void TextShaderEditor::save_external_data(const String &p_str) {
@@ -916,7 +918,7 @@ void TextShaderEditor::save_external_data(const String &p_str) {
apply_shaders();
- Ref<Shader> edited_shader = shader_editor->get_edited_shader();
+ Ref<Shader> edited_shader = code_editor->get_edited_shader();
if (edited_shader.is_valid()) {
ResourceSaver::save(edited_shader);
}
@@ -924,56 +926,56 @@ void TextShaderEditor::save_external_data(const String &p_str) {
ResourceSaver::save(shader);
}
- Ref<ShaderInclude> edited_shader_inc = shader_editor->get_edited_shader_include();
+ Ref<ShaderInclude> edited_shader_inc = code_editor->get_edited_shader_include();
if (edited_shader_inc.is_valid()) {
ResourceSaver::save(edited_shader_inc);
}
if (shader_inc.is_valid() && shader_inc != edited_shader_inc) {
ResourceSaver::save(shader_inc);
}
- shader_editor->get_text_editor()->tag_saved_version();
+ code_editor->get_text_editor()->tag_saved_version();
disk_changed->hide();
}
void TextShaderEditor::trim_trailing_whitespace() {
- shader_editor->trim_trailing_whitespace();
+ code_editor->trim_trailing_whitespace();
}
void TextShaderEditor::validate_script() {
- shader_editor->_validate_script();
+ code_editor->_validate_script();
}
bool TextShaderEditor::is_unsaved() const {
- return shader_editor->get_text_editor()->get_saved_version() != shader_editor->get_text_editor()->get_version();
+ return code_editor->get_text_editor()->get_saved_version() != code_editor->get_text_editor()->get_version();
}
void TextShaderEditor::tag_saved_version() {
- shader_editor->get_text_editor()->tag_saved_version();
+ code_editor->get_text_editor()->tag_saved_version();
}
void TextShaderEditor::apply_shaders() {
- String editor_code = shader_editor->get_text_editor()->get_text();
+ String editor_code = code_editor->get_text_editor()->get_text();
if (shader.is_valid()) {
String shader_code = shader->get_code();
- if (shader_code != editor_code || dependencies_version != shader_editor->get_dependencies_version()) {
- shader_editor->set_block_shader_changed(true);
+ if (shader_code != editor_code || dependencies_version != code_editor->get_dependencies_version()) {
+ code_editor->set_block_shader_changed(true);
shader->set_code(editor_code);
- shader_editor->set_block_shader_changed(false);
+ code_editor->set_block_shader_changed(false);
shader->set_edited(true);
}
}
if (shader_inc.is_valid()) {
String shader_inc_code = shader_inc->get_code();
- if (shader_inc_code != editor_code || dependencies_version != shader_editor->get_dependencies_version()) {
- shader_editor->set_block_shader_changed(true);
+ if (shader_inc_code != editor_code || dependencies_version != code_editor->get_dependencies_version()) {
+ code_editor->set_block_shader_changed(true);
shader_inc->set_code(editor_code);
- shader_editor->set_block_shader_changed(false);
+ code_editor->set_block_shader_changed(false);
shader_inc->set_edited(true);
}
}
- dependencies_version = shader_editor->get_dependencies_version();
+ dependencies_version = code_editor->get_dependencies_version();
}
void TextShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
@@ -981,7 +983,7 @@ void TextShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
if (mb.is_valid()) {
if (mb->get_button_index() == MouseButton::RIGHT && mb->is_pressed()) {
- CodeEdit *tx = shader_editor->get_text_editor();
+ CodeEdit *tx = code_editor->get_text_editor();
tx->apply_ime();
@@ -1014,7 +1016,7 @@ void TextShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
Ref<InputEventKey> k = ev;
if (k.is_valid() && k->is_pressed() && k->is_action("ui_menu", true)) {
- CodeEdit *tx = shader_editor->get_text_editor();
+ CodeEdit *tx = code_editor->get_text_editor();
tx->adjust_viewport_to_caret();
_make_context_menu(tx->has_selection(), (get_global_transform().inverse() * tx->get_global_transform()).xform(tx->get_caret_draw_pos()));
context_menu->grab_focus();
@@ -1029,7 +1031,7 @@ void TextShaderEditor::_update_bookmark_list() {
bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_next_bookmark"), BOOKMARK_GOTO_NEXT);
bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_previous_bookmark"), BOOKMARK_GOTO_PREV);
- PackedInt32Array bookmark_list = shader_editor->get_text_editor()->get_bookmarked_lines();
+ PackedInt32Array bookmark_list = code_editor->get_text_editor()->get_bookmarked_lines();
if (bookmark_list.size() == 0) {
return;
}
@@ -1037,7 +1039,7 @@ void TextShaderEditor::_update_bookmark_list() {
bookmarks_menu->add_separator();
for (int i = 0; i < bookmark_list.size(); i++) {
- String line = shader_editor->get_text_editor()->get_line(bookmark_list[i]).strip_edges();
+ String line = code_editor->get_text_editor()->get_line(bookmark_list[i]).strip_edges();
// Limit the size of the line if too big.
if (line.length() > 50) {
line = line.substr(0, 50);
@@ -1052,7 +1054,7 @@ void TextShaderEditor::_bookmark_item_pressed(int p_idx) {
if (p_idx < 4) { // Any item before the separator.
_menu_option(bookmarks_menu->get_item_id(p_idx));
} else {
- shader_editor->goto_line(bookmarks_menu->get_item_metadata(p_idx));
+ code_editor->goto_line(bookmarks_menu->get_item_metadata(p_idx));
}
}
@@ -1083,26 +1085,26 @@ void TextShaderEditor::_make_context_menu(bool p_selection, Vector2 p_position)
TextShaderEditor::TextShaderEditor() {
_update_warnings(false);
- shader_editor = memnew(ShaderTextEditor);
+ code_editor = memnew(ShaderTextEditor);
- shader_editor->connect("script_validated", callable_mp(this, &TextShaderEditor::_script_validated));
+ code_editor->connect("script_validated", callable_mp(this, &TextShaderEditor::_script_validated));
- shader_editor->set_v_size_flags(SIZE_EXPAND_FILL);
- shader_editor->add_theme_constant_override("separation", 0);
- shader_editor->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
+ code_editor->set_v_size_flags(SIZE_EXPAND_FILL);
+ code_editor->add_theme_constant_override("separation", 0);
+ code_editor->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
- shader_editor->connect("show_warnings_panel", callable_mp(this, &TextShaderEditor::_show_warnings_panel));
- shader_editor->connect("script_changed", callable_mp(this, &TextShaderEditor::apply_shaders));
+ code_editor->connect("show_warnings_panel", callable_mp(this, &TextShaderEditor::_show_warnings_panel));
+ code_editor->connect("script_changed", callable_mp(this, &TextShaderEditor::apply_shaders));
EditorSettings::get_singleton()->connect("settings_changed", callable_mp(this, &TextShaderEditor::_editor_settings_changed));
ProjectSettings::get_singleton()->connect("settings_changed", callable_mp(this, &TextShaderEditor::_project_settings_changed));
- shader_editor->get_text_editor()->set_code_hint_draw_below(EDITOR_GET("text_editor/completion/put_callhint_tooltip_below_current_line"));
-
- shader_editor->get_text_editor()->set_symbol_lookup_on_click_enabled(true);
- shader_editor->get_text_editor()->set_context_menu_enabled(false);
- shader_editor->get_text_editor()->connect("gui_input", callable_mp(this, &TextShaderEditor::_text_edit_gui_input));
+ code_editor->get_text_editor()->set_symbol_lookup_on_click_enabled(true);
+ code_editor->get_text_editor()->set_context_menu_enabled(false);
+ code_editor->get_text_editor()->set_draw_breakpoints_gutter(false);
+ code_editor->get_text_editor()->set_draw_executing_lines_gutter(false);
+ code_editor->get_text_editor()->connect("gui_input", callable_mp(this, &TextShaderEditor::_text_edit_gui_input));
- shader_editor->update_editor_settings();
+ code_editor->update_editor_settings();
context_menu = memnew(PopupMenu);
add_child(context_menu);
@@ -1184,12 +1186,12 @@ TextShaderEditor::TextShaderEditor() {
main_container->add_child(editor_box);
editor_box->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
editor_box->set_v_size_flags(SIZE_EXPAND_FILL);
- editor_box->add_child(shader_editor);
+ editor_box->add_child(code_editor);
FindReplaceBar *bar = memnew(FindReplaceBar);
main_container->add_child(bar);
bar->hide();
- shader_editor->set_find_replace_bar(bar);
+ code_editor->set_find_replace_bar(bar);
warnings_panel = memnew(RichTextLabel);
warnings_panel->set_custom_minimum_size(Size2(0, 100 * EDSCALE));
@@ -1201,7 +1203,7 @@ TextShaderEditor::TextShaderEditor() {
warnings_panel->hide();
warnings_panel->connect("meta_clicked", callable_mp(this, &TextShaderEditor::_warning_clicked));
editor_box->add_child(warnings_panel);
- shader_editor->set_warnings_panel(warnings_panel);
+ code_editor->set_warnings_panel(warnings_panel);
goto_line_dialog = memnew(GotoLineDialog);
add_child(goto_line_dialog);
@@ -1221,8 +1223,6 @@ TextShaderEditor::TextShaderEditor() {
disk_changed->add_button(TTR("Resave"), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "resave");
disk_changed->connect("custom_action", callable_mp(this, &TextShaderEditor::save_external_data));
- trim_trailing_whitespace_on_save = EDITOR_GET("text_editor/behavior/files/trim_trailing_whitespace_on_save");
-
add_child(disk_changed);
_editor_settings_changed();
diff --git a/editor/plugins/text_shader_editor.h b/editor/plugins/text_shader_editor.h
index eba2ec0bb9..a1b45d1b2e 100644
--- a/editor/plugins/text_shader_editor.h
+++ b/editor/plugins/text_shader_editor.h
@@ -148,7 +148,7 @@ class TextShaderEditor : public MarginContainer {
ConfirmationDialog *erase_tab_confirm = nullptr;
ConfirmationDialog *disk_changed = nullptr;
- ShaderTextEditor *shader_editor = nullptr;
+ ShaderTextEditor *code_editor = nullptr;
bool compilation_success = true;
void _menu_option(int p_option);
@@ -156,6 +156,7 @@ class TextShaderEditor : public MarginContainer {
mutable Ref<ShaderInclude> shader_inc;
void _editor_settings_changed();
+ void _apply_editor_settings();
void _project_settings_changed();
void _check_for_external_edit();
@@ -197,6 +198,7 @@ public:
void validate_script();
bool is_unsaved() const;
void tag_saved_version();
+ ShaderTextEditor *get_code_editor() { return code_editor; }
virtual Size2 get_minimum_size() const override { return Size2(0, 200); }
diff --git a/modules/basis_universal/image_compress_basisu.cpp b/modules/basis_universal/image_compress_basisu.cpp
index 41de62b20b..12856f33c1 100644
--- a/modules/basis_universal/image_compress_basisu.cpp
+++ b/modules/basis_universal/image_compress_basisu.cpp
@@ -154,6 +154,7 @@ Ref<Image> basis_universal_unpacker_ptr(const uint8_t *p_data, int p_size) {
// Get supported compression formats.
bool bptc_supported = RS::get_singleton()->has_os_feature("bptc");
+ bool astc_supported = RS::get_singleton()->has_os_feature("astc");
bool s3tc_supported = RS::get_singleton()->has_os_feature("s3tc");
bool etc2_supported = RS::get_singleton()->has_os_feature("etc2");
@@ -166,6 +167,9 @@ Ref<Image> basis_universal_unpacker_ptr(const uint8_t *p_data, int p_size) {
if (bptc_supported) {
basisu_format = basist::transcoder_texture_format::cTFBC7_M6_OPAQUE_ONLY;
image_format = Image::FORMAT_BPTC_RGBA;
+ } else if (astc_supported) {
+ basisu_format = basist::transcoder_texture_format::cTFASTC_4x4_RGBA;
+ image_format = Image::FORMAT_ASTC_4x4;
} else if (s3tc_supported) {
basisu_format = basist::transcoder_texture_format::cTFBC1;
image_format = Image::FORMAT_DXT1;
@@ -183,6 +187,9 @@ Ref<Image> basis_universal_unpacker_ptr(const uint8_t *p_data, int p_size) {
if (bptc_supported) {
basisu_format = basist::transcoder_texture_format::cTFBC7_M5;
image_format = Image::FORMAT_BPTC_RGBA;
+ } else if (astc_supported) {
+ basisu_format = basist::transcoder_texture_format::cTFASTC_4x4_RGBA;
+ image_format = Image::FORMAT_ASTC_4x4;
} else if (s3tc_supported) {
basisu_format = basist::transcoder_texture_format::cTFBC3;
image_format = Image::FORMAT_DXT5;
diff --git a/modules/navigation/godot_navigation_server.cpp b/modules/navigation/godot_navigation_server.cpp
index 14c72f3db4..4bb9c27b1d 100644
--- a/modules/navigation/godot_navigation_server.cpp
+++ b/modules/navigation/godot_navigation_server.cpp
@@ -121,13 +121,13 @@ COMMAND_2(map_set_active, RID, p_map, bool, p_active) {
if (p_active) {
if (!map_is_active(p_map)) {
active_maps.push_back(map);
- active_maps_update_id.push_back(map->get_map_update_id());
+ active_maps_iteration_id.push_back(map->get_iteration_id());
}
} else {
int map_index = active_maps.find(map);
ERR_FAIL_COND(map_index < 0);
active_maps.remove_at(map_index);
- active_maps_update_id.remove_at(map_index);
+ active_maps_iteration_id.remove_at(map_index);
}
}
@@ -1165,7 +1165,7 @@ COMMAND_1(free, RID, p_object) {
int map_index = active_maps.find(map);
if (map_index >= 0) {
active_maps.remove_at(map_index);
- active_maps_update_id.remove_at(map_index);
+ active_maps_iteration_id.remove_at(map_index);
}
map_owner.free(p_object);
@@ -1258,6 +1258,13 @@ void GodotNavigationServer::map_force_update(RID p_map) {
map->sync();
}
+uint32_t GodotNavigationServer::map_get_iteration_id(RID p_map) const {
+ NavMap *map = map_owner.get_or_null(p_map);
+ ERR_FAIL_NULL_V(map, 0);
+
+ return map->get_iteration_id();
+}
+
void GodotNavigationServer::sync() {
#ifndef _3D_DISABLED
if (navmesh_generator_3d) {
@@ -1300,10 +1307,10 @@ void GodotNavigationServer::process(real_t p_delta_time) {
_new_pm_edge_free_count += active_maps[i]->get_pm_edge_free_count();
// Emit a signal if a map changed.
- const uint32_t new_map_update_id = active_maps[i]->get_map_update_id();
- if (new_map_update_id != active_maps_update_id[i]) {
+ const uint32_t new_map_iteration_id = active_maps[i]->get_iteration_id();
+ if (new_map_iteration_id != active_maps_iteration_id[i]) {
emit_signal(SNAME("map_changed"), active_maps[i]->get_self());
- active_maps_update_id[i] = new_map_update_id;
+ active_maps_iteration_id[i] = new_map_iteration_id;
}
}
diff --git a/modules/navigation/godot_navigation_server.h b/modules/navigation/godot_navigation_server.h
index f3bc1185d8..8af0eb1874 100644
--- a/modules/navigation/godot_navigation_server.h
+++ b/modules/navigation/godot_navigation_server.h
@@ -80,7 +80,7 @@ class GodotNavigationServer : public NavigationServer3D {
bool active = true;
LocalVector<NavMap *> active_maps;
- LocalVector<uint32_t> active_maps_update_id;
+ LocalVector<uint32_t> active_maps_iteration_id;
#ifndef _3D_DISABLED
NavMeshGenerator3D *navmesh_generator_3d = nullptr;
@@ -142,6 +142,7 @@ public:
virtual TypedArray<RID> map_get_obstacles(RID p_map) const override;
virtual void map_force_update(RID p_map) override;
+ virtual uint32_t map_get_iteration_id(RID p_map) const override;
virtual Vector3 map_get_random_point(RID p_map, uint32_t p_navigation_layers, bool p_uniformly) const override;
diff --git a/modules/navigation/godot_navigation_server_2d.cpp b/modules/navigation/godot_navigation_server_2d.cpp
index 5bd4a37fd7..4b8640249d 100644
--- a/modules/navigation/godot_navigation_server_2d.cpp
+++ b/modules/navigation/godot_navigation_server_2d.cpp
@@ -253,6 +253,10 @@ void GodotNavigationServer2D::map_force_update(RID p_map) {
NavigationServer3D::get_singleton()->map_force_update(p_map);
}
+uint32_t GodotNavigationServer2D::map_get_iteration_id(RID p_map) const {
+ return NavigationServer3D::get_singleton()->map_get_iteration_id(p_map);
+}
+
void FORWARD_2(map_set_cell_size, RID, p_map, real_t, p_cell_size, rid_to_rid, real_to_real);
real_t FORWARD_1_C(map_get_cell_size, RID, p_map, rid_to_rid);
diff --git a/modules/navigation/godot_navigation_server_2d.h b/modules/navigation/godot_navigation_server_2d.h
index 08f1730441..225fd8f3a6 100644
--- a/modules/navigation/godot_navigation_server_2d.h
+++ b/modules/navigation/godot_navigation_server_2d.h
@@ -77,6 +77,7 @@ public:
virtual TypedArray<RID> map_get_obstacles(RID p_map) const override;
virtual void map_force_update(RID p_map) override;
virtual Vector2 map_get_random_point(RID p_map, uint32_t p_navigation_layers, bool p_uniformly) const override;
+ virtual uint32_t map_get_iteration_id(RID p_map) const override;
virtual RID region_create() override;
virtual void region_set_enabled(RID p_region, bool p_enabled) override;
diff --git a/modules/navigation/nav_agent.cpp b/modules/navigation/nav_agent.cpp
index 5a87ff6c4b..2dbe57eb4a 100644
--- a/modules/navigation/nav_agent.cpp
+++ b/modules/navigation/nav_agent.cpp
@@ -111,8 +111,8 @@ void NavAgent::set_map(NavMap *p_map) {
bool NavAgent::is_map_changed() {
if (map) {
- bool is_changed = map->get_map_update_id() != map_update_id;
- map_update_id = map->get_map_update_id();
+ bool is_changed = map->get_iteration_id() != last_map_iteration_id;
+ last_map_iteration_id = map->get_iteration_id();
return is_changed;
} else {
return false;
diff --git a/modules/navigation/nav_agent.h b/modules/navigation/nav_agent.h
index 9ab6f55544..00b5bc13ab 100644
--- a/modules/navigation/nav_agent.h
+++ b/modules/navigation/nav_agent.h
@@ -72,7 +72,7 @@ class NavAgent : public NavRid {
bool agent_dirty = true;
- uint32_t map_update_id = 0;
+ uint32_t last_map_iteration_id = 0;
bool paused = false;
public:
diff --git a/modules/navigation/nav_map.cpp b/modules/navigation/nav_map.cpp
index 9482da39ef..f163f4e529 100644
--- a/modules/navigation/nav_map.cpp
+++ b/modules/navigation/nav_map.cpp
@@ -128,7 +128,7 @@ gd::PointKey NavMap::get_point_key(const Vector3 &p_pos) const {
Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers, Vector<int32_t> *r_path_types, TypedArray<RID> *r_path_rids, Vector<int64_t> *r_path_owners) const {
RWLockRead read_lock(map_rwlock);
- if (map_update_id == 0) {
+ if (iteration_id == 0) {
ERR_FAIL_V_MSG(Vector<Vector3>(), "NavigationServer map query failed because it was made before first map synchronization.");
}
@@ -592,7 +592,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
Vector3 NavMap::get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision) const {
RWLockRead read_lock(map_rwlock);
- if (map_update_id == 0) {
+ if (iteration_id == 0) {
ERR_FAIL_V_MSG(Vector3(), "NavigationServer map query failed because it was made before first map synchronization.");
}
@@ -644,7 +644,7 @@ Vector3 NavMap::get_closest_point_to_segment(const Vector3 &p_from, const Vector
Vector3 NavMap::get_closest_point(const Vector3 &p_point) const {
RWLockRead read_lock(map_rwlock);
- if (map_update_id == 0) {
+ if (iteration_id == 0) {
ERR_FAIL_V_MSG(Vector3(), "NavigationServer map query failed because it was made before first map synchronization.");
}
gd::ClosestPointQueryResult cp = get_closest_point_info(p_point);
@@ -653,7 +653,7 @@ Vector3 NavMap::get_closest_point(const Vector3 &p_point) const {
Vector3 NavMap::get_closest_point_normal(const Vector3 &p_point) const {
RWLockRead read_lock(map_rwlock);
- if (map_update_id == 0) {
+ if (iteration_id == 0) {
ERR_FAIL_V_MSG(Vector3(), "NavigationServer map query failed because it was made before first map synchronization.");
}
gd::ClosestPointQueryResult cp = get_closest_point_info(p_point);
@@ -662,7 +662,7 @@ Vector3 NavMap::get_closest_point_normal(const Vector3 &p_point) const {
RID NavMap::get_closest_point_owner(const Vector3 &p_point) const {
RWLockRead read_lock(map_rwlock);
- if (map_update_id == 0) {
+ if (iteration_id == 0) {
ERR_FAIL_V_MSG(RID(), "NavigationServer map query failed because it was made before first map synchronization.");
}
gd::ClosestPointQueryResult cp = get_closest_point_info(p_point);
@@ -1160,9 +1160,8 @@ void NavMap::sync() {
}
}
- // Update the update ID.
- // Some code treats 0 as a failure case, so we avoid returning 0.
- map_update_id = map_update_id % 9999999 + 1;
+ // Some code treats 0 as a failure case, so we avoid returning 0 and modulo wrap UINT32_MAX manually.
+ iteration_id = iteration_id % UINT32_MAX + 1;
}
// Do we have modified obstacle positions?
diff --git a/modules/navigation/nav_map.h b/modules/navigation/nav_map.h
index 311a265e0c..d6215ea57f 100644
--- a/modules/navigation/nav_map.h
+++ b/modules/navigation/nav_map.h
@@ -108,7 +108,7 @@ class NavMap : public NavRid {
real_t deltatime = 0.0;
/// Change the id each time the map is updated.
- uint32_t map_update_id = 0;
+ uint32_t iteration_id = 0;
bool use_threads = true;
bool avoidance_use_multiple_threads = true;
@@ -128,6 +128,8 @@ public:
NavMap();
~NavMap();
+ uint32_t get_iteration_id() const { return iteration_id; }
+
void set_up(Vector3 p_up);
Vector3 get_up() const {
return up;
@@ -199,10 +201,6 @@ public:
return obstacles;
}
- uint32_t get_map_update_id() const {
- return map_update_id;
- }
-
Vector3 get_random_point(uint32_t p_navigation_layers, bool p_uniformly) const;
void sync();
diff --git a/modules/navigation/nav_obstacle.cpp b/modules/navigation/nav_obstacle.cpp
index 34e5f7aa85..14dfd4eae3 100644
--- a/modules/navigation/nav_obstacle.cpp
+++ b/modules/navigation/nav_obstacle.cpp
@@ -149,8 +149,8 @@ void NavObstacle::set_vertices(const Vector<Vector3> &p_vertices) {
bool NavObstacle::is_map_changed() {
if (map) {
- bool is_changed = map->get_map_update_id() != map_update_id;
- map_update_id = map->get_map_update_id();
+ bool is_changed = map->get_iteration_id() != last_map_iteration_id;
+ last_map_iteration_id = map->get_iteration_id();
return is_changed;
} else {
return false;
diff --git a/modules/navigation/nav_obstacle.h b/modules/navigation/nav_obstacle.h
index eb44f63d03..e231e83836 100644
--- a/modules/navigation/nav_obstacle.h
+++ b/modules/navigation/nav_obstacle.h
@@ -55,7 +55,7 @@ class NavObstacle : public NavRid {
bool obstacle_dirty = true;
- uint32_t map_update_id = 0;
+ uint32_t last_map_iteration_id = 0;
bool paused = false;
public:
diff --git a/platform/android/java/lib/src/org/godotengine/godot/gl/GLSurfaceView.java b/platform/android/java/lib/src/org/godotengine/godot/gl/GLSurfaceView.java
index ef97aaeab9..bd8c58ad69 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/gl/GLSurfaceView.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/gl/GLSurfaceView.java
@@ -1673,7 +1673,24 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
mWantRenderNotification = true;
mRequestRender = true;
mRenderComplete = false;
- mFinishDrawingRunnable = finishDrawing;
+
+ // fix lost old callback when continuous call requestRenderAndNotify
+ //
+ // If continuous call requestRenderAndNotify before trigger old
+ // callback, old callback will lose, cause VRI will wait for SV's
+ // draw to finish forever not calling finishDraw.
+ // https://android.googlesource.com/platform/frameworks/base/+/044fce0b826f2da3a192aac56785b5089143e693%5E%21/
+ //+++++++++++++++++++++++++++++++++++++++++++++++++++
+ final Runnable oldCallback = mFinishDrawingRunnable;
+ mFinishDrawingRunnable = () -> {
+ if (oldCallback != null) {
+ oldCallback.run();
+ }
+ if (finishDrawing != null) {
+ finishDrawing.run();
+ }
+ };
+ //----------------------------------------------------
sGLThreadManager.notifyAll();
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularContextFactory.java b/platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularContextFactory.java
index 01ee41e30b..1f0d8592b3 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularContextFactory.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularContextFactory.java
@@ -66,11 +66,15 @@ public class RegularContextFactory implements GLSurfaceView.EGLContextFactory {
GLUtils.checkEglError(TAG, "Before eglCreateContext", egl);
EGLContext context;
+ int[] debug_attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 3, _EGL_CONTEXT_FLAGS_KHR, _EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR, EGL10.EGL_NONE };
+ int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 3, EGL10.EGL_NONE };
if (mUseDebugOpengl) {
- int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 3, _EGL_CONTEXT_FLAGS_KHR, _EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR, EGL10.EGL_NONE };
- context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
+ context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, debug_attrib_list);
+ if (context == null || context == EGL10.EGL_NO_CONTEXT) {
+ Log.w(TAG, "creating 'OpenGL Debug' context failed");
+ context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
+ }
} else {
- int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 3, EGL10.EGL_NONE };
context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
}
GLUtils.checkEglError(TAG, "After eglCreateContext", egl);
diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp
index de7948dca7..1b9a9e812d 100644
--- a/scene/animation/animation_blend_tree.cpp
+++ b/scene/animation/animation_blend_tree.cpp
@@ -1403,6 +1403,7 @@ String AnimationNodeBlendTree::get_caption() const {
double AnimationNodeBlendTree::_process(const AnimationMixer::PlaybackInfo p_playback_info, bool p_test_only) {
Ref<AnimationNodeOutput> output = nodes[SceneStringNames::get_singleton()->output].node;
node_state.connections = nodes[SceneStringNames::get_singleton()->output].connections;
+ ERR_FAIL_COND_V(output.is_null(), 0);
AnimationMixer::PlaybackInfo pi = p_playback_info;
pi.weight = 1.0;
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp
index 2b7c47c869..2c2d8387f3 100644
--- a/scene/animation/animation_tree.cpp
+++ b/scene/animation/animation_tree.cpp
@@ -140,6 +140,7 @@ double AnimationNode::blend_input(int p_input, AnimationMixer::PlaybackInfo p_pl
}
Ref<AnimationNode> node = blend_tree->get_node(node_name);
+ ERR_FAIL_COND_V(node.is_null(), 0);
real_t activity = 0.0;
Vector<AnimationTree::Activity> *activity_ptr = process_state->tree->input_activity_map.getptr(node_state.base_path);
@@ -153,12 +154,13 @@ double AnimationNode::blend_input(int p_input, AnimationMixer::PlaybackInfo p_pl
}
double AnimationNode::blend_node(Ref<AnimationNode> p_node, const StringName &p_subpath, AnimationMixer::PlaybackInfo p_playback_info, FilterAction p_filter, bool p_sync, bool p_test_only) {
+ ERR_FAIL_COND_V(p_node.is_null(), 0);
+
p_node->node_state.connections.clear();
return _blend_node(p_node, p_subpath, this, p_playback_info, p_filter, p_sync, p_test_only, nullptr);
}
double AnimationNode::_blend_node(Ref<AnimationNode> p_node, const StringName &p_subpath, AnimationNode *p_new_parent, AnimationMixer::PlaybackInfo p_playback_info, FilterAction p_filter, bool p_sync, bool p_test_only, real_t *r_activity) {
- ERR_FAIL_COND_V(!p_node.is_valid(), 0);
ERR_FAIL_NULL_V(process_state, 0);
int blend_count = node_state.track_weights.size();
diff --git a/scene/gui/tab_bar.cpp b/scene/gui/tab_bar.cpp
index f87bccdfe7..d20fef8164 100644
--- a/scene/gui/tab_bar.cpp
+++ b/scene/gui/tab_bar.cpp
@@ -627,6 +627,10 @@ void TabBar::set_tab_count(int p_count) {
offset = MIN(offset, p_count - 1);
max_drawn_tab = MIN(max_drawn_tab, p_count - 1);
current = MIN(current, p_count - 1);
+ // Fix range if unable to deselect.
+ if (current == -1 && !_can_deselect()) {
+ current = 0;
+ }
_update_cache();
_ensure_no_over_offset();
@@ -1557,10 +1561,7 @@ bool TabBar::_can_deselect() const {
}
void TabBar::ensure_tab_visible(int p_idx) {
- if (!is_inside_tree() || !buttons_visible) {
- return;
- }
- if (p_idx == -1 && _can_deselect()) {
+ if (p_idx == -1 || !is_inside_tree() || !buttons_visible) {
return;
}
ERR_FAIL_INDEX(p_idx, tabs.size());
diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp
index 32c77195f8..d87ac00e32 100644
--- a/servers/navigation_server_2d.cpp
+++ b/servers/navigation_server_2d.cpp
@@ -58,6 +58,7 @@ void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("map_get_obstacles", "map"), &NavigationServer2D::map_get_obstacles);
ClassDB::bind_method(D_METHOD("map_force_update", "map"), &NavigationServer2D::map_force_update);
+ ClassDB::bind_method(D_METHOD("map_get_iteration_id", "map"), &NavigationServer2D::map_get_iteration_id);
ClassDB::bind_method(D_METHOD("map_get_random_point", "map", "navigation_layers", "uniformly"), &NavigationServer2D::map_get_random_point);
diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h
index c7d97c004b..d7dc9d6526 100644
--- a/servers/navigation_server_2d.h
+++ b/servers/navigation_server_2d.h
@@ -102,6 +102,7 @@ public:
virtual TypedArray<RID> map_get_obstacles(RID p_map) const = 0;
virtual void map_force_update(RID p_map) = 0;
+ virtual uint32_t map_get_iteration_id(RID p_map) const = 0;
virtual Vector2 map_get_random_point(RID p_map, uint32_t p_navigation_layers, bool p_uniformly) const = 0;
diff --git a/servers/navigation_server_2d_dummy.h b/servers/navigation_server_2d_dummy.h
index 3ec6d11352..94c6dfd6a7 100644
--- a/servers/navigation_server_2d_dummy.h
+++ b/servers/navigation_server_2d_dummy.h
@@ -59,6 +59,7 @@ public:
TypedArray<RID> map_get_obstacles(RID p_map) const override { return TypedArray<RID>(); }
void map_force_update(RID p_map) override {}
Vector2 map_get_random_point(RID p_map, uint32_t p_naviation_layers, bool p_uniformly) const override { return Vector2(); };
+ uint32_t map_get_iteration_id(RID p_map) const override { return 0; }
RID region_create() override { return RID(); }
void region_set_enabled(RID p_region, bool p_enabled) override {}
diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp
index 7fc027284b..00db1440f6 100644
--- a/servers/navigation_server_3d.cpp
+++ b/servers/navigation_server_3d.cpp
@@ -65,6 +65,7 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("map_get_obstacles", "map"), &NavigationServer3D::map_get_obstacles);
ClassDB::bind_method(D_METHOD("map_force_update", "map"), &NavigationServer3D::map_force_update);
+ ClassDB::bind_method(D_METHOD("map_get_iteration_id", "map"), &NavigationServer3D::map_get_iteration_id);
ClassDB::bind_method(D_METHOD("map_get_random_point", "map", "navigation_layers", "uniformly"), &NavigationServer3D::map_get_random_point);
diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h
index 552e318586..975ffdee94 100644
--- a/servers/navigation_server_3d.h
+++ b/servers/navigation_server_3d.h
@@ -116,6 +116,7 @@ public:
virtual TypedArray<RID> map_get_obstacles(RID p_map) const = 0;
virtual void map_force_update(RID p_map) = 0;
+ virtual uint32_t map_get_iteration_id(RID p_map) const = 0;
virtual Vector3 map_get_random_point(RID p_map, uint32_t p_navigation_layers, bool p_uniformly) const = 0;
diff --git a/servers/navigation_server_3d_dummy.h b/servers/navigation_server_3d_dummy.h
index d595fcde7e..9ba9b20d00 100644
--- a/servers/navigation_server_3d_dummy.h
+++ b/servers/navigation_server_3d_dummy.h
@@ -66,6 +66,8 @@ public:
TypedArray<RID> map_get_agents(RID p_map) const override { return TypedArray<RID>(); }
TypedArray<RID> map_get_obstacles(RID p_map) const override { return TypedArray<RID>(); }
void map_force_update(RID p_map) override {}
+ uint32_t map_get_iteration_id(RID p_map) const override { return 0; }
+
RID region_create() override { return RID(); }
void region_set_enabled(RID p_region, bool p_enabled) override {}
bool region_get_enabled(RID p_region) const override { return false; }
@@ -92,6 +94,7 @@ public:
Vector3 region_get_connection_pathway_start(RID p_region, int p_connection_id) const override { return Vector3(); }
Vector3 region_get_connection_pathway_end(RID p_region, int p_connection_id) const override { return Vector3(); }
Vector3 region_get_random_point(RID p_region, uint32_t p_navigation_layers, bool p_uniformly) const override { return Vector3(); }
+
RID link_create() override { return RID(); }
void link_set_map(RID p_link, RID p_map) override {}
RID link_get_map(RID p_link) const override { return RID(); }
@@ -111,6 +114,7 @@ public:
real_t link_get_travel_cost(RID p_link) const override { return 0; }
void link_set_owner_id(RID p_link, ObjectID p_owner_id) override {}
ObjectID link_get_owner_id(RID p_link) const override { return ObjectID(); }
+
RID agent_create() override { return RID(); }
void agent_set_map(RID p_agent, RID p_map) override {}
RID agent_get_map(RID p_agent) const override { return RID(); }
@@ -148,6 +152,7 @@ public:
uint32_t agent_get_avoidance_mask(RID p_agent) const override { return 0; }
void agent_set_avoidance_priority(RID p_agent, real_t p_priority) override {}
real_t agent_get_avoidance_priority(RID p_agent) const override { return 0; }
+
RID obstacle_create() override { return RID(); }
void obstacle_set_map(RID p_obstacle, RID p_map) override {}
RID obstacle_get_map(RID p_obstacle) const override { return RID(); }
@@ -169,6 +174,7 @@ public:
Vector<Vector3> obstacle_get_vertices(RID p_obstacle) const override { return Vector<Vector3>(); }
void obstacle_set_avoidance_layers(RID p_obstacle, uint32_t p_layers) override {}
uint32_t obstacle_get_avoidance_layers(RID p_obstacle) const override { return 0; }
+
void parse_source_geometry_data(const Ref<NavigationMesh> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData3D> &p_source_geometry_data, Node *p_root_node, const Callable &p_callback = Callable()) override {}
void bake_from_source_geometry_data(const Ref<NavigationMesh> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData3D> &p_source_geometry_data, const Callable &p_callback = Callable()) override {}
void bake_from_source_geometry_data_async(const Ref<NavigationMesh> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData3D> &p_source_geometry_data, const Callable &p_callback = Callable()) override {}
@@ -180,8 +186,10 @@ public:
void init() override {}
void sync() override {}
void finish() override {}
+
NavigationUtilities::PathQueryResult _query_path(const NavigationUtilities::PathQueryParameters &p_parameters) const override { return NavigationUtilities::PathQueryResult(); }
int get_process_info(ProcessInfo p_info) const override { return 0; }
+
void set_debug_enabled(bool p_enabled) {}
bool get_debug_enabled() const { return false; }
};
diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp
index 150c155f1a..66843aaad8 100644
--- a/servers/register_server_types.cpp
+++ b/servers/register_server_types.cpp
@@ -60,14 +60,6 @@
#include "movie_writer/movie_writer.h"
#include "movie_writer/movie_writer_mjpeg.h"
#include "movie_writer/movie_writer_pngwav.h"
-#include "navigation_server_2d.h"
-#include "navigation_server_3d.h"
-#include "physics_2d/godot_physics_server_2d.h"
-#include "physics_3d/godot_physics_server_3d.h"
-#include "physics_server_2d.h"
-#include "physics_server_2d_wrap_mt.h"
-#include "physics_server_3d.h"
-#include "physics_server_3d_wrap_mt.h"
#include "rendering/renderer_compositor.h"
#include "rendering/renderer_rd/framebuffer_cache_rd.h"
#include "rendering/renderer_rd/storage_rd/render_data_rd.h"
@@ -80,8 +72,6 @@
#include "rendering/storage/render_scene_buffers.h"
#include "rendering/storage/render_scene_data.h"
#include "rendering_server.h"
-#include "servers/extensions/physics_server_2d_extension.h"
-#include "servers/extensions/physics_server_3d_extension.h"
#include "servers/rendering/shader_types.h"
#include "text/text_server_dummy.h"
#include "text/text_server_extension.h"
@@ -92,8 +82,25 @@
#include "xr/xr_positional_tracker.h"
#include "xr_server.h"
+// 2D physics and navigation.
+#include "navigation_server_2d.h"
+#include "physics_2d/godot_physics_server_2d.h"
+#include "physics_server_2d.h"
+#include "physics_server_2d_wrap_mt.h"
+#include "servers/extensions/physics_server_2d_extension.h"
+
+// 3D physics and navigation (3D navigation is needed for 2D).
+#include "navigation_server_3d.h"
+#ifndef _3D_DISABLED
+#include "physics_3d/godot_physics_server_3d.h"
+#include "physics_server_3d.h"
+#include "physics_server_3d_wrap_mt.h"
+#include "servers/extensions/physics_server_3d_extension.h"
+#endif // _3D_DISABLED
+
ShaderTypes *shader_types = nullptr;
+#ifndef _3D_DISABLED
static PhysicsServer3D *_createGodotPhysics3DCallback() {
#ifdef THREADS_ENABLED
bool using_threads = GLOBAL_GET("physics/3d/run_on_separate_thread");
@@ -105,6 +112,7 @@ static PhysicsServer3D *_createGodotPhysics3DCallback() {
return memnew(PhysicsServer3DWrapMT(physics_server_3d, using_threads));
}
+#endif // _3D_DISABLED
static PhysicsServer2D *_createGodotPhysics2DCallback() {
#ifdef THREADS_ENABLED
@@ -152,34 +160,6 @@ void register_server_types() {
GDREGISTER_ABSTRACT_CLASS(RenderingServer);
GDREGISTER_CLASS(AudioServer);
- GDREGISTER_CLASS(PhysicsServer2DManager);
- Engine::get_singleton()->add_singleton(Engine::Singleton("PhysicsServer2DManager", PhysicsServer2DManager::get_singleton(), "PhysicsServer2DManager"));
-
- GDREGISTER_ABSTRACT_CLASS(PhysicsServer2D);
- GDREGISTER_VIRTUAL_CLASS(PhysicsServer2DExtension);
- GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState2DExtension);
- GDREGISTER_VIRTUAL_CLASS(PhysicsDirectSpaceState2DExtension);
-
- GDREGISTER_NATIVE_STRUCT(PhysicsServer2DExtensionRayResult, "Vector2 position;Vector2 normal;RID rid;ObjectID collider_id;Object *collider;int shape");
- GDREGISTER_NATIVE_STRUCT(PhysicsServer2DExtensionShapeResult, "RID rid;ObjectID collider_id;Object *collider;int shape");
- GDREGISTER_NATIVE_STRUCT(PhysicsServer2DExtensionShapeRestInfo, "Vector2 point;Vector2 normal;RID rid;ObjectID collider_id;int shape;Vector2 linear_velocity");
- GDREGISTER_NATIVE_STRUCT(PhysicsServer2DExtensionMotionResult, "Vector2 travel;Vector2 remainder;Vector2 collision_point;Vector2 collision_normal;Vector2 collider_velocity;real_t collision_depth;real_t collision_safe_fraction;real_t collision_unsafe_fraction;int collision_local_shape;ObjectID collider_id;RID collider;int collider_shape");
-
- GDREGISTER_CLASS(PhysicsServer3DManager);
- Engine::get_singleton()->add_singleton(Engine::Singleton("PhysicsServer3DManager", PhysicsServer3DManager::get_singleton(), "PhysicsServer3DManager"));
-
- GDREGISTER_ABSTRACT_CLASS(PhysicsServer3D);
- GDREGISTER_VIRTUAL_CLASS(PhysicsServer3DExtension);
- GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState3DExtension);
- GDREGISTER_VIRTUAL_CLASS(PhysicsDirectSpaceState3DExtension)
- GDREGISTER_VIRTUAL_CLASS(PhysicsServer3DRenderingServerHandler)
-
- GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionRayResult, "Vector3 position;Vector3 normal;RID rid;ObjectID collider_id;Object *collider;int shape;int face_index");
- GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionShapeResult, "RID rid;ObjectID collider_id;Object *collider;int shape");
- GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionShapeRestInfo, "Vector3 point;Vector3 normal;RID rid;ObjectID collider_id;int shape;Vector3 linear_velocity");
- GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionMotionCollision, "Vector3 position;Vector3 normal;Vector3 collider_velocity;Vector3 collider_angular_velocity;real_t depth;int local_shape;ObjectID collider_id;RID collider;int collider_shape");
- GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionMotionResult, "Vector3 travel;Vector3 remainder;real_t collision_depth;real_t collision_safe_fraction;real_t collision_unsafe_fraction;PhysicsServer3DExtensionMotionCollision collisions[32];int collision_count");
-
GDREGISTER_ABSTRACT_CLASS(NavigationServer2D);
GDREGISTER_ABSTRACT_CLASS(NavigationServer3D);
GDREGISTER_CLASS(NavigationPathQueryParameters2D);
@@ -285,6 +265,24 @@ void register_server_types() {
GDREGISTER_CLASS(CameraFeed);
+ GDREGISTER_VIRTUAL_CLASS(MovieWriter);
+
+ ServersDebugger::initialize();
+
+ // Physics 2D
+ GDREGISTER_CLASS(PhysicsServer2DManager);
+ Engine::get_singleton()->add_singleton(Engine::Singleton("PhysicsServer2DManager", PhysicsServer2DManager::get_singleton(), "PhysicsServer2DManager"));
+
+ GDREGISTER_ABSTRACT_CLASS(PhysicsServer2D);
+ GDREGISTER_VIRTUAL_CLASS(PhysicsServer2DExtension);
+ GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState2DExtension);
+ GDREGISTER_VIRTUAL_CLASS(PhysicsDirectSpaceState2DExtension);
+
+ GDREGISTER_NATIVE_STRUCT(PhysicsServer2DExtensionRayResult, "Vector2 position;Vector2 normal;RID rid;ObjectID collider_id;Object *collider;int shape");
+ GDREGISTER_NATIVE_STRUCT(PhysicsServer2DExtensionShapeResult, "RID rid;ObjectID collider_id;Object *collider;int shape");
+ GDREGISTER_NATIVE_STRUCT(PhysicsServer2DExtensionShapeRestInfo, "Vector2 point;Vector2 normal;RID rid;ObjectID collider_id;int shape;Vector2 linear_velocity");
+ GDREGISTER_NATIVE_STRUCT(PhysicsServer2DExtensionMotionResult, "Vector2 travel;Vector2 remainder;Vector2 collision_point;Vector2 collision_normal;Vector2 collider_velocity;real_t collision_depth;real_t collision_safe_fraction;real_t collision_unsafe_fraction;int collision_local_shape;ObjectID collider_id;RID collider;int collider_shape");
+
GDREGISTER_ABSTRACT_CLASS(PhysicsDirectBodyState2D);
GDREGISTER_ABSTRACT_CLASS(PhysicsDirectSpaceState2D);
GDREGISTER_CLASS(PhysicsRayQueryParameters2D);
@@ -293,6 +291,28 @@ void register_server_types() {
GDREGISTER_CLASS(PhysicsTestMotionParameters2D);
GDREGISTER_CLASS(PhysicsTestMotionResult2D);
+ GLOBAL_DEF(PropertyInfo(Variant::STRING, PhysicsServer2DManager::setting_property_name, PROPERTY_HINT_ENUM, "DEFAULT"), "DEFAULT");
+
+ PhysicsServer2DManager::get_singleton()->register_server("GodotPhysics2D", callable_mp_static(_createGodotPhysics2DCallback));
+ PhysicsServer2DManager::get_singleton()->set_default_server("GodotPhysics2D");
+
+#ifndef _3D_DISABLED
+ // Physics 3D
+ GDREGISTER_CLASS(PhysicsServer3DManager);
+ Engine::get_singleton()->add_singleton(Engine::Singleton("PhysicsServer3DManager", PhysicsServer3DManager::get_singleton(), "PhysicsServer3DManager"));
+
+ GDREGISTER_ABSTRACT_CLASS(PhysicsServer3D);
+ GDREGISTER_VIRTUAL_CLASS(PhysicsServer3DExtension);
+ GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState3DExtension);
+ GDREGISTER_VIRTUAL_CLASS(PhysicsDirectSpaceState3DExtension)
+ GDREGISTER_VIRTUAL_CLASS(PhysicsServer3DRenderingServerHandler)
+
+ GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionRayResult, "Vector3 position;Vector3 normal;RID rid;ObjectID collider_id;Object *collider;int shape;int face_index");
+ GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionShapeResult, "RID rid;ObjectID collider_id;Object *collider;int shape");
+ GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionShapeRestInfo, "Vector3 point;Vector3 normal;RID rid;ObjectID collider_id;int shape;Vector3 linear_velocity");
+ GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionMotionCollision, "Vector3 position;Vector3 normal;Vector3 collider_velocity;Vector3 collider_angular_velocity;real_t depth;int local_shape;ObjectID collider_id;RID collider;int collider_shape");
+ GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionMotionResult, "Vector3 travel;Vector3 remainder;real_t collision_depth;real_t collision_safe_fraction;real_t collision_unsafe_fraction;PhysicsServer3DExtensionMotionCollision collisions[32];int collision_count");
+
GDREGISTER_ABSTRACT_CLASS(PhysicsDirectBodyState3D);
GDREGISTER_ABSTRACT_CLASS(PhysicsDirectSpaceState3D);
GDREGISTER_CLASS(PhysicsRayQueryParameters3D);
@@ -301,21 +321,11 @@ void register_server_types() {
GDREGISTER_CLASS(PhysicsTestMotionParameters3D);
GDREGISTER_CLASS(PhysicsTestMotionResult3D);
- GDREGISTER_VIRTUAL_CLASS(MovieWriter);
-
- ServersDebugger::initialize();
-
- // Physics 2D
- GLOBAL_DEF(PropertyInfo(Variant::STRING, PhysicsServer2DManager::setting_property_name, PROPERTY_HINT_ENUM, "DEFAULT"), "DEFAULT");
-
- PhysicsServer2DManager::get_singleton()->register_server("GodotPhysics2D", callable_mp_static(_createGodotPhysics2DCallback));
- PhysicsServer2DManager::get_singleton()->set_default_server("GodotPhysics2D");
-
- // Physics 3D
GLOBAL_DEF(PropertyInfo(Variant::STRING, PhysicsServer3DManager::setting_property_name, PROPERTY_HINT_ENUM, "DEFAULT"), "DEFAULT");
PhysicsServer3DManager::get_singleton()->register_server("GodotPhysics3D", callable_mp_static(_createGodotPhysics3DCallback));
PhysicsServer3DManager::get_singleton()->set_default_server("GodotPhysics3D");
+#endif // _3D_DISABLED
writer_mjpeg = memnew(MovieWriterMJPEG);
MovieWriter::add_writer(writer_mjpeg);
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index 3b51f5274a..2cfee25f91 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -2853,17 +2853,6 @@ RID RenderingDevice::uniform_set_create(const Vector<Uniform> &p_uniforms, RID p
DEV_ASSERT(!texture->owner.is_valid() || texture_owner.get_or_null(texture->owner));
- if (_texture_make_mutable(texture, texture_id)) {
- // The texture must be mutable as a layout transition will be required.
- draw_graph.add_synchronization();
- }
-
- if (texture->draw_tracker != nullptr) {
- bool depth_stencil_read = (texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
- draw_trackers.push_back(texture->draw_tracker);
- draw_trackers_usage.push_back(depth_stencil_read ? RDG::RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ : RDG::RESOURCE_USAGE_ATTACHMENT_COLOR_READ);
- }
-
driver_uniform.ids.push_back(texture->driver_id);
}
} break;
@@ -3185,7 +3174,7 @@ Error RenderingDevice::screen_prepare_for_drawing(DisplayServer::WindowID p_scre
uint32_t to_present_index = 0;
while (to_present_index < frames[frame].swap_chains_to_present.size()) {
if (frames[frame].swap_chains_to_present[to_present_index] == it->value) {
- driver->command_queue_present(present_queue, it->value, {});
+ driver->command_queue_execute_and_present(present_queue, {}, {}, {}, {}, it->value);
frames[frame].swap_chains_to_present.remove_at(to_present_index);
} else {
to_present_index++;
@@ -4717,7 +4706,6 @@ void RenderingDevice::swap_buffers() {
_end_frame();
_execute_frame(true);
- _present_frame();
// Advance to the next frame and begin recording again.
frame = (frame + 1) % frames.size();
@@ -4890,17 +4878,21 @@ void RenderingDevice::_end_frame() {
driver->end_segment();
}
-void RenderingDevice::_execute_frame(bool p_signal_for_present) {
- const bool frame_can_present = !frames[frame].swap_chains_to_present.is_empty();
- const VectorView<RDD::SemaphoreID> execute_draw_semaphore = p_signal_for_present && frame_can_present ? frames[frame].draw_semaphore : VectorView<RDD::SemaphoreID>();
- driver->command_queue_execute(main_queue, frames[frame].setup_command_buffer, {}, frames[frame].setup_semaphore, {});
- driver->command_queue_execute(main_queue, frames[frame].draw_command_buffer, frames[frame].setup_semaphore, execute_draw_semaphore, frames[frame].draw_fence);
+void RenderingDevice::_execute_frame(bool p_present) {
+ const bool frame_can_present = p_present && !frames[frame].swap_chains_to_present.is_empty();
+ const bool separate_present_queue = main_queue != present_queue;
+ const VectorView<RDD::SemaphoreID> execute_draw_semaphore = frame_can_present && separate_present_queue ? frames[frame].draw_semaphore : VectorView<RDD::SemaphoreID>();
+ const VectorView<RDD::SwapChainID> execute_draw_swap_chains = frame_can_present && !separate_present_queue ? frames[frame].swap_chains_to_present : VectorView<RDD::SwapChainID>();
+ driver->command_queue_execute_and_present(main_queue, {}, frames[frame].setup_command_buffer, frames[frame].setup_semaphore, {}, {});
+ driver->command_queue_execute_and_present(main_queue, frames[frame].setup_semaphore, frames[frame].draw_command_buffer, execute_draw_semaphore, frames[frame].draw_fence, execute_draw_swap_chains);
frames[frame].draw_fence_signaled = true;
-}
-void RenderingDevice::_present_frame() {
- if (!frames[frame].swap_chains_to_present.is_empty()) {
- driver->command_queue_present(present_queue, frames[frame].swap_chains_to_present, frames[frame].draw_semaphore);
+ if (frame_can_present) {
+ if (separate_present_queue) {
+ // Issue the presentation separately if the presentation queue is different from the main queue.
+ driver->command_queue_execute_and_present(present_queue, frames[frame].draw_semaphore, {}, {}, {}, frames[frame].swap_chains_to_present);
+ }
+
frames[frame].swap_chains_to_present.clear();
}
}
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index f4b7683d6e..ce7128d564 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -1291,8 +1291,7 @@ private:
void _free_internal(RID p_id);
void _begin_frame();
void _end_frame();
- void _execute_frame(bool p_signal_for_present);
- void _present_frame();
+ void _execute_frame(bool p_present);
void _stall_for_previous_frames();
void _flush_and_stall_for_all_frames();
diff --git a/servers/rendering/rendering_device_driver.h b/servers/rendering/rendering_device_driver.h
index 753b3668bc..9706d3219a 100644
--- a/servers/rendering/rendering_device_driver.h
+++ b/servers/rendering/rendering_device_driver.h
@@ -408,8 +408,7 @@ public:
// ----- QUEUE -----
virtual CommandQueueID command_queue_create(CommandQueueFamilyID p_cmd_queue_family, bool p_identify_as_main_queue = false) = 0;
- virtual Error command_queue_execute(CommandQueueID p_cmd_queue, VectorView<CommandBufferID> p_cmd_buffers, VectorView<SemaphoreID> p_wait_semaphores, VectorView<SemaphoreID> p_signal_semaphores, FenceID p_signal_fence) = 0;
- virtual Error command_queue_present(CommandQueueID p_cmd_queue, VectorView<SwapChainID> p_swap_chains, VectorView<SemaphoreID> p_wait_semaphores) = 0;
+ virtual Error command_queue_execute_and_present(CommandQueueID p_cmd_queue, VectorView<SemaphoreID> p_wait_semaphores, VectorView<CommandBufferID> p_cmd_buffers, VectorView<SemaphoreID> p_cmd_semaphores, FenceID p_cmd_fence, VectorView<SwapChainID> p_swap_chains) = 0;
virtual void command_queue_free(CommandQueueID p_cmd_queue) = 0;
// ----- POOL -----
diff --git a/servers/rendering/rendering_device_graph.cpp b/servers/rendering/rendering_device_graph.cpp
index 3e4890e866..4b85d1c2bf 100644
--- a/servers/rendering/rendering_device_graph.cpp
+++ b/servers/rendering/rendering_device_graph.cpp
@@ -53,8 +53,6 @@ bool RenderingDeviceGraph::_is_write_usage(ResourceUsage p_usage) {
case RESOURCE_USAGE_INDEX_BUFFER_READ:
case RESOURCE_USAGE_TEXTURE_SAMPLE:
case RESOURCE_USAGE_STORAGE_IMAGE_READ:
- case RESOURCE_USAGE_ATTACHMENT_COLOR_READ:
- case RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ:
return false;
case RESOURCE_USAGE_TRANSFER_TO:
case RESOURCE_USAGE_TEXTURE_BUFFER_READ_WRITE:
@@ -80,11 +78,8 @@ RDD::TextureLayout RenderingDeviceGraph::_usage_to_image_layout(ResourceUsage p_
case RESOURCE_USAGE_STORAGE_IMAGE_READ:
case RESOURCE_USAGE_STORAGE_IMAGE_READ_WRITE:
return RDD::TEXTURE_LAYOUT_GENERAL;
- case RESOURCE_USAGE_ATTACHMENT_COLOR_READ:
case RESOURCE_USAGE_ATTACHMENT_COLOR_READ_WRITE:
return RDD::TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- case RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ:
- return RDD::TEXTURE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
case RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ_WRITE:
return RDD::TEXTURE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
case RESOURCE_USAGE_NONE:
@@ -123,12 +118,8 @@ RDD::BarrierAccessBits RenderingDeviceGraph::_usage_to_access_bits(ResourceUsage
return RDD::BARRIER_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
case RESOURCE_USAGE_INDEX_BUFFER_READ:
return RDD::BARRIER_ACCESS_INDEX_READ_BIT;
- case RESOURCE_USAGE_ATTACHMENT_COLOR_READ:
- return RDD::BARRIER_ACCESS_COLOR_ATTACHMENT_READ_BIT;
case RESOURCE_USAGE_ATTACHMENT_COLOR_READ_WRITE:
return RDD::BarrierAccessBits(RDD::BARRIER_ACCESS_COLOR_ATTACHMENT_READ_BIT | RDD::BARRIER_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
- case RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ:
- return RDD::BARRIER_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
case RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ_WRITE:
return RDD::BarrierAccessBits(RDD::BARRIER_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | RDD::BARRIER_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT);
default:
diff --git a/servers/rendering/rendering_device_graph.h b/servers/rendering/rendering_device_graph.h
index 9bb109ea0e..3bc63bb297 100644
--- a/servers/rendering/rendering_device_graph.h
+++ b/servers/rendering/rendering_device_graph.h
@@ -142,9 +142,7 @@ public:
RESOURCE_USAGE_TEXTURE_SAMPLE,
RESOURCE_USAGE_STORAGE_IMAGE_READ,
RESOURCE_USAGE_STORAGE_IMAGE_READ_WRITE,
- RESOURCE_USAGE_ATTACHMENT_COLOR_READ,
RESOURCE_USAGE_ATTACHMENT_COLOR_READ_WRITE,
- RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ,
RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ_WRITE
};