summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/classes/Tree.xml20
-rw-r--r--doc/classes/TreeItem.xml8
-rw-r--r--drivers/vulkan/rendering_device_vulkan.cpp5
-rw-r--r--drivers/vulkan/vulkan_context.cpp63
-rw-r--r--drivers/vulkan/vulkan_context.h6
-rw-r--r--editor/action_map_editor.cpp4
-rw-r--r--editor/debugger/editor_network_profiler.cpp10
-rw-r--r--editor/debugger/editor_profiler.cpp6
-rw-r--r--editor/debugger/editor_visual_profiler.cpp6
-rw-r--r--editor/debugger/script_editor_debugger.cpp8
-rw-r--r--editor/dependency_editor.cpp2
-rw-r--r--editor/editor_autoload_settings.cpp8
-rw-r--r--editor/editor_help_search.cpp2
-rw-r--r--editor/editor_plugin_settings.cpp8
-rw-r--r--editor/find_in_files.cpp2
-rw-r--r--editor/import/scene_import_settings.cpp6
-rw-r--r--editor/localization_editor.cpp2
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp4
-rw-r--r--editor/plugins/resource_preloader_editor_plugin.cpp4
-rw-r--r--editor/plugins/theme_editor_plugin.cpp6
-rw-r--r--modules/gdnative/gdnative_library_editor_plugin.cpp4
-rw-r--r--modules/gltf/gltf_document.cpp2
-rw-r--r--modules/websocket/websocket_client.cpp9
-rw-r--r--modules/websocket/wsl_client.cpp1
-rw-r--r--scene/gui/tree.cpp228
-rw-r--r--scene/gui/tree.h25
-rw-r--r--scene/resources/material.cpp14
27 files changed, 335 insertions, 128 deletions
diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml
index 6a65d4ff7d..be770e6e03 100644
--- a/doc/classes/Tree.xml
+++ b/doc/classes/Tree.xml
@@ -232,7 +232,7 @@
Returns the last pressed button's index.
</description>
</method>
- <method name="get_root">
+ <method name="get_root" qualifiers="const">
<return type="TreeItem">
</return>
<description>
@@ -272,26 +272,26 @@
<description>
</description>
</method>
- <method name="set_column_expand">
+ <method name="set_column_custom_minimum_width">
<return type="void">
</return>
<argument index="0" name="column" type="int">
</argument>
- <argument index="1" name="expand" type="bool">
+ <argument index="1" name="min_width" type="int">
</argument>
<description>
- If [code]true[/code], the column will have the "Expand" flag of [Control]. Columns that have the "Expand" flag will use their "min_width" in a similar fashion to [member Control.size_flags_stretch_ratio].
+ Overrides the calculated minimum width of a column. It can be set to `0` to restore the default behavior. Columns that have the "Expand" flag will use their "min_width" in a similar fashion to [member Control.size_flags_stretch_ratio].
</description>
</method>
- <method name="set_column_min_width">
+ <method name="set_column_expand">
<return type="void">
</return>
<argument index="0" name="column" type="int">
</argument>
- <argument index="1" name="min_width" type="int">
+ <argument index="1" name="expand" type="bool">
</argument>
<description>
- Sets the minimum width of a column. Columns that have the "Expand" flag will use their "min_width" in a similar fashion to [member Control.size_flags_stretch_ratio].
+ If [code]true[/code], the column will have the "Expand" flag of [Control]. Columns that have the "Expand" flag will use their "min_width" in a similar fashion to [member Control.size_flags_stretch_ratio].
</description>
</method>
<method name="set_column_title">
@@ -372,6 +372,12 @@
If [code]true[/code], the tree's root is hidden.
</member>
<member name="rect_clip_content" type="bool" setter="set_clip_contents" getter="is_clipping_contents" override="true" default="true" />
+ <member name="scroll_horizontal_enabled" type="bool" setter="set_h_scroll_enabled" getter="is_h_scroll_enabled" default="true">
+ If [code]true[/code], enables horizontal scrolling.
+ </member>
+ <member name="scroll_vertical_enabled" type="bool" setter="set_v_scroll_enabled" getter="is_v_scroll_enabled" default="true">
+ If [code]true[/code], enables vertical scrolling.
+ </member>
<member name="select_mode" type="int" setter="set_select_mode" getter="get_select_mode" enum="Tree.SelectMode" default="0">
Allows single or multiple selection. See the [enum SelectMode] constants.
</member>
diff --git a/doc/classes/TreeItem.xml b/doc/classes/TreeItem.xml
index 0256d83fea..85c9caa101 100644
--- a/doc/classes/TreeItem.xml
+++ b/doc/classes/TreeItem.xml
@@ -192,7 +192,7 @@
Returns [code]true[/code] if [code]expand_right[/code] is set.
</description>
</method>
- <method name="get_first_child">
+ <method name="get_first_child" qualifiers="const">
<return type="TreeItem">
</return>
<description>
@@ -260,7 +260,7 @@
Returns the metadata value that was set for the given column using [method set_metadata].
</description>
</method>
- <method name="get_next">
+ <method name="get_next" qualifiers="const">
<return type="TreeItem">
</return>
<description>
@@ -288,7 +288,7 @@
Returns OpenType feature [code]tag[/code] of the item's text.
</description>
</method>
- <method name="get_parent">
+ <method name="get_parent" qualifiers="const">
<return type="TreeItem">
</return>
<description>
@@ -391,7 +391,7 @@
Returns the given column's tooltip.
</description>
</method>
- <method name="get_tree">
+ <method name="get_tree" qualifiers="const">
<return type="Tree">
</return>
<description>
diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp
index 1539962803..6c4e590586 100644
--- a/drivers/vulkan/rendering_device_vulkan.cpp
+++ b/drivers/vulkan/rendering_device_vulkan.cpp
@@ -3524,7 +3524,10 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
depth_stencil_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
attachment_last_pass[attachment] = i;
- if (!is_multisample_first) {
+ if (is_multisample_first) {
+ texture_samples = p_attachments[attachment].samples;
+ is_multisample_first = false;
+ } else {
ERR_FAIL_COND_V_MSG(texture_samples != p_attachments[attachment].samples, VK_NULL_HANDLE, "Invalid framebuffer depth format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), if an attachment is marked as multisample, all of them should be multisample and use the same number of samples including the depth.");
}
diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp
index 6ed43b5d31..9939611a83 100644
--- a/drivers/vulkan/vulkan_context.cpp
+++ b/drivers/vulkan/vulkan_context.cpp
@@ -1013,11 +1013,11 @@ Error VulkanContext::_create_device() {
return OK;
}
-Error VulkanContext::_initialize_queues(VkSurfaceKHR surface) {
+Error VulkanContext::_initialize_queues(VkSurfaceKHR p_surface) {
// Iterate over each queue to learn whether it supports presenting:
VkBool32 *supportsPresent = (VkBool32 *)malloc(queue_family_count * sizeof(VkBool32));
for (uint32_t i = 0; i < queue_family_count; i++) {
- fpGetPhysicalDeviceSurfaceSupportKHR(gpu, i, surface, &supportsPresent[i]);
+ fpGetPhysicalDeviceSurfaceSupportKHR(gpu, i, p_surface, &supportsPresent[i]);
}
// Search for a graphics and a present queue in the array of queue
@@ -1091,10 +1091,10 @@ Error VulkanContext::_initialize_queues(VkSurfaceKHR surface) {
// Get the list of VkFormat's that are supported:
uint32_t formatCount;
- VkResult err = fpGetPhysicalDeviceSurfaceFormatsKHR(gpu, surface, &formatCount, nullptr);
+ VkResult err = fpGetPhysicalDeviceSurfaceFormatsKHR(gpu, p_surface, &formatCount, nullptr);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
VkSurfaceFormatKHR *surfFormats = (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
- err = fpGetPhysicalDeviceSurfaceFormatsKHR(gpu, surface, &formatCount, surfFormats);
+ err = fpGetPhysicalDeviceSurfaceFormatsKHR(gpu, p_surface, &formatCount, surfFormats);
if (err) {
free(surfFormats);
ERR_FAIL_V(ERR_CANT_CREATE);
@@ -1169,9 +1169,6 @@ Error VulkanContext::_create_semaphores() {
err = vkCreateFence(device, &fence_ci, nullptr, &fences[i]);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
- err = vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &image_acquired_semaphores[i]);
- ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
-
err = vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &draw_complete_semaphores[i]);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
@@ -1201,6 +1198,19 @@ Error VulkanContext::_window_create(DisplayServer::WindowID p_window_id, VkSurfa
// is created.
Error err = _initialize_queues(p_surface);
ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
+ } else {
+ // make sure any of the surfaces supports present (validation layer complains if this is not done).
+ bool any_supports_present = false;
+ for (uint32_t i = 0; i < queue_family_count; i++) {
+ VkBool32 supports;
+ fpGetPhysicalDeviceSurfaceSupportKHR(gpu, i, p_surface, &supports);
+ if (supports) {
+ any_supports_present = true;
+ break;
+ }
+ }
+
+ ERR_FAIL_COND_V_MSG(!any_supports_present, ERR_CANT_CREATE, "Surface passed for sub-window creation does not support presenting");
}
Window window;
@@ -1210,6 +1220,17 @@ Error VulkanContext::_window_create(DisplayServer::WindowID p_window_id, VkSurfa
Error err = _update_swap_chain(&window);
ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
+ VkSemaphoreCreateInfo semaphoreCreateInfo = {
+ /*sType*/ VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
+ /*pNext*/ nullptr,
+ /*flags*/ 0,
+ };
+
+ for (uint32_t i = 0; i < FRAME_LAG; i++) {
+ VkResult vkerr = vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &window.image_acquired_semaphores[i]);
+ ERR_FAIL_COND_V(vkerr, ERR_CANT_CREATE);
+ }
+
windows[p_window_id] = window;
return OK;
}
@@ -1249,6 +1270,10 @@ VkFramebuffer VulkanContext::window_get_framebuffer(DisplayServer::WindowID p_wi
void VulkanContext::window_destroy(DisplayServer::WindowID p_window_id) {
ERR_FAIL_COND(!windows.has(p_window_id));
_clean_up_swap_chain(&windows[p_window_id]);
+ for (uint32_t i = 0; i < FRAME_LAG; i++) {
+ vkDestroySemaphore(device, windows[p_window_id].image_acquired_semaphores[i], nullptr);
+ }
+
vkDestroySurfaceKHR(inst, windows[p_window_id].surface, nullptr);
windows.erase(p_window_id);
}
@@ -1703,6 +1728,8 @@ Error VulkanContext::prepare_buffers() {
for (Map<int, Window>::Element *E = windows.front(); E; E = E->next()) {
Window *w = &E->get();
+ w->semaphore_acquired = false;
+
if (w->swapchain == VK_NULL_HANDLE) {
continue;
}
@@ -1711,7 +1738,7 @@ Error VulkanContext::prepare_buffers() {
// Get the index of the next available swapchain image:
err =
fpAcquireNextImageKHR(device, w->swapchain, UINT64_MAX,
- image_acquired_semaphores[frame_index], VK_NULL_HANDLE, &w->current_buffer);
+ w->image_acquired_semaphores[frame_index], VK_NULL_HANDLE, &w->current_buffer);
if (err == VK_ERROR_OUT_OF_DATE_KHR) {
// swapchain is out of date (e.g. the window was resized) and
@@ -1724,8 +1751,10 @@ Error VulkanContext::prepare_buffers() {
// presentation engine will still present the image correctly.
print_verbose("Vulkan: Early suboptimal swapchain.");
break;
+ } else if (err != VK_SUCCESS) {
+ ERR_BREAK(ERR_CANT_CREATE);
} else {
- ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
+ w->semaphore_acquired = true;
}
} while (err != VK_SUCCESS);
}
@@ -1775,14 +1804,25 @@ Error VulkanContext::swap_buffers() {
commands_to_submit = command_buffer_count;
}
+ VkSemaphore *semaphores_to_acquire = (VkSemaphore *)alloca(windows.size() * sizeof(VkSemaphore));
+ uint32_t semaphores_to_acquire_count = 0;
+
+ for (Map<int, Window>::Element *E = windows.front(); E; E = E->next()) {
+ Window *w = &E->get();
+
+ if (w->semaphore_acquired) {
+ semaphores_to_acquire[semaphores_to_acquire_count++] = w->image_acquired_semaphores[frame_index];
+ }
+ }
+
VkPipelineStageFlags pipe_stage_flags;
VkSubmitInfo submit_info;
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.pNext = nullptr;
submit_info.pWaitDstStageMask = &pipe_stage_flags;
pipe_stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- submit_info.waitSemaphoreCount = 1;
- submit_info.pWaitSemaphores = &image_acquired_semaphores[frame_index];
+ submit_info.waitSemaphoreCount = semaphores_to_acquire_count;
+ submit_info.pWaitSemaphores = semaphores_to_acquire;
submit_info.commandBufferCount = commands_to_submit;
submit_info.pCommandBuffers = commands_ptr;
submit_info.signalSemaphoreCount = 1;
@@ -2134,7 +2174,6 @@ VulkanContext::~VulkanContext() {
if (device_initialized) {
for (uint32_t i = 0; i < FRAME_LAG; i++) {
vkDestroyFence(device, fences[i], nullptr);
- vkDestroySemaphore(device, image_acquired_semaphores[i], nullptr);
vkDestroySemaphore(device, draw_complete_semaphores[i], nullptr);
if (separate_present_queue) {
vkDestroySemaphore(device, image_ownership_semaphores[i], nullptr);
diff --git a/drivers/vulkan/vulkan_context.h b/drivers/vulkan/vulkan_context.h
index 738ead4f96..8f1005d07f 100644
--- a/drivers/vulkan/vulkan_context.h
+++ b/drivers/vulkan/vulkan_context.h
@@ -70,7 +70,6 @@ private:
};
VkInstance inst = VK_NULL_HANDLE;
- VkSurfaceKHR surface = VK_NULL_HANDLE;
VkPhysicalDevice gpu = VK_NULL_HANDLE;
VkPhysicalDeviceProperties gpu_props;
uint32_t queue_family_count = 0;
@@ -101,7 +100,6 @@ private:
VkQueue present_queue = VK_NULL_HANDLE;
VkColorSpaceKHR color_space;
VkFormat format;
- VkSemaphore image_acquired_semaphores[FRAME_LAG];
VkSemaphore draw_complete_semaphores[FRAME_LAG];
VkSemaphore image_ownership_semaphores[FRAME_LAG];
int frame_index = 0;
@@ -121,6 +119,8 @@ private:
VkSwapchainKHR swapchain = VK_NULL_HANDLE;
SwapchainImageResources *swapchain_image_resources = VK_NULL_HANDLE;
VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;
+ VkSemaphore image_acquired_semaphores[FRAME_LAG];
+ bool semaphore_acquired = false;
uint32_t current_buffer = 0;
int width = 0;
int height = 0;
@@ -208,7 +208,7 @@ private:
Error _create_physical_device();
- Error _initialize_queues(VkSurfaceKHR surface);
+ Error _initialize_queues(VkSurfaceKHR p_surface);
Error _create_device();
diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp
index 0a0c3b1987..fe1401bdf9 100644
--- a/editor/action_map_editor.cpp
+++ b/editor/action_map_editor.cpp
@@ -1125,9 +1125,9 @@ ActionMapEditor::ActionMapEditor() {
action_tree->set_column_title(0, TTR("Action"));
action_tree->set_column_title(1, TTR("Deadzone"));
action_tree->set_column_expand(1, false);
- action_tree->set_column_min_width(1, 80 * EDSCALE);
+ action_tree->set_column_custom_minimum_width(1, 80 * EDSCALE);
action_tree->set_column_expand(2, false);
- action_tree->set_column_min_width(2, 50 * EDSCALE);
+ action_tree->set_column_custom_minimum_width(2, 50 * EDSCALE);
action_tree->connect("item_edited", callable_mp(this, &ActionMapEditor::_action_edited));
action_tree->connect("item_activated", callable_mp(this, &ActionMapEditor::_tree_item_activated));
action_tree->connect("button_pressed", callable_mp(this, &ActionMapEditor::_tree_button_pressed));
diff --git a/editor/debugger/editor_network_profiler.cpp b/editor/debugger/editor_network_profiler.cpp
index 2d57dff69d..af83baeff8 100644
--- a/editor/debugger/editor_network_profiler.cpp
+++ b/editor/debugger/editor_network_profiler.cpp
@@ -178,19 +178,19 @@ EditorNetworkProfiler::EditorNetworkProfiler() {
counters_display->set_column_titles_visible(true);
counters_display->set_column_title(0, TTR("Node"));
counters_display->set_column_expand(0, true);
- counters_display->set_column_min_width(0, 60 * EDSCALE);
+ counters_display->set_column_custom_minimum_width(0, 60 * EDSCALE);
counters_display->set_column_title(1, TTR("Incoming RPC"));
counters_display->set_column_expand(1, false);
- counters_display->set_column_min_width(1, 120 * EDSCALE);
+ counters_display->set_column_custom_minimum_width(1, 120 * EDSCALE);
counters_display->set_column_title(2, TTR("Incoming RSET"));
counters_display->set_column_expand(2, false);
- counters_display->set_column_min_width(2, 120 * EDSCALE);
+ counters_display->set_column_custom_minimum_width(2, 120 * EDSCALE);
counters_display->set_column_title(3, TTR("Outgoing RPC"));
counters_display->set_column_expand(3, false);
- counters_display->set_column_min_width(3, 120 * EDSCALE);
+ counters_display->set_column_custom_minimum_width(3, 120 * EDSCALE);
counters_display->set_column_title(4, TTR("Outgoing RSET"));
counters_display->set_column_expand(4, false);
- counters_display->set_column_min_width(4, 120 * EDSCALE);
+ counters_display->set_column_custom_minimum_width(4, 120 * EDSCALE);
add_child(counters_display);
frame_delay = memnew(Timer);
diff --git a/editor/debugger/editor_profiler.cpp b/editor/debugger/editor_profiler.cpp
index 1bfef67e8c..449aaa42ff 100644
--- a/editor/debugger/editor_profiler.cpp
+++ b/editor/debugger/editor_profiler.cpp
@@ -631,13 +631,13 @@ EditorProfiler::EditorProfiler() {
variables->set_column_titles_visible(true);
variables->set_column_title(0, TTR("Name"));
variables->set_column_expand(0, true);
- variables->set_column_min_width(0, 60 * EDSCALE);
+ variables->set_column_custom_minimum_width(0, 60 * EDSCALE);
variables->set_column_title(1, TTR("Time"));
variables->set_column_expand(1, false);
- variables->set_column_min_width(1, 100 * EDSCALE);
+ variables->set_column_custom_minimum_width(1, 100 * EDSCALE);
variables->set_column_title(2, TTR("Calls"));
variables->set_column_expand(2, false);
- variables->set_column_min_width(2, 60 * EDSCALE);
+ variables->set_column_custom_minimum_width(2, 60 * EDSCALE);
variables->connect("item_edited", callable_mp(this, &EditorProfiler::_item_edited));
graph = memnew(TextureRect);
diff --git a/editor/debugger/editor_visual_profiler.cpp b/editor/debugger/editor_visual_profiler.cpp
index cc2e00d021..d3948dee97 100644
--- a/editor/debugger/editor_visual_profiler.cpp
+++ b/editor/debugger/editor_visual_profiler.cpp
@@ -773,13 +773,13 @@ EditorVisualProfiler::EditorVisualProfiler() {
variables->set_column_titles_visible(true);
variables->set_column_title(0, TTR("Name"));
variables->set_column_expand(0, true);
- variables->set_column_min_width(0, 60);
+ variables->set_column_custom_minimum_width(0, 60);
variables->set_column_title(1, TTR("CPU"));
variables->set_column_expand(1, false);
- variables->set_column_min_width(1, 60 * EDSCALE);
+ variables->set_column_custom_minimum_width(1, 60 * EDSCALE);
variables->set_column_title(2, TTR("GPU"));
variables->set_column_expand(2, false);
- variables->set_column_min_width(2, 60 * EDSCALE);
+ variables->set_column_custom_minimum_width(2, 60 * EDSCALE);
variables->connect("cell_selected", callable_mp(this, &EditorVisualProfiler::_item_selected));
graph = memnew(TextureRect);
diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp
index 7493cc2a8d..0d3fd8c7f6 100644
--- a/editor/debugger/script_editor_debugger.cpp
+++ b/editor/debugger/script_editor_debugger.cpp
@@ -1643,7 +1643,7 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) {
error_tree->set_columns(2);
error_tree->set_column_expand(0, false);
- error_tree->set_column_min_width(0, 140);
+ error_tree->set_column_custom_minimum_width(0, 140);
error_tree->set_column_expand(1, true);
@@ -1731,13 +1731,13 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) {
vmem_tree->set_column_expand(0, true);
vmem_tree->set_column_expand(1, false);
vmem_tree->set_column_title(1, TTR("Type"));
- vmem_tree->set_column_min_width(1, 100 * EDSCALE);
+ vmem_tree->set_column_custom_minimum_width(1, 100 * EDSCALE);
vmem_tree->set_column_expand(2, false);
vmem_tree->set_column_title(2, TTR("Format"));
- vmem_tree->set_column_min_width(2, 150 * EDSCALE);
+ vmem_tree->set_column_custom_minimum_width(2, 150 * EDSCALE);
vmem_tree->set_column_expand(3, false);
vmem_tree->set_column_title(3, TTR("Usage"));
- vmem_tree->set_column_min_width(3, 80 * EDSCALE);
+ vmem_tree->set_column_custom_minimum_width(3, 80 * EDSCALE);
vmem_tree->set_hide_root(true);
tabs->add_child(vmem_vb);
diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp
index 7534b419fe..74a8ad9077 100644
--- a/editor/dependency_editor.cpp
+++ b/editor/dependency_editor.cpp
@@ -769,7 +769,7 @@ OrphanResourcesDialog::OrphanResourcesDialog() {
files = memnew(Tree);
files->set_columns(2);
files->set_column_titles_visible(true);
- files->set_column_min_width(1, 100);
+ files->set_column_custom_minimum_width(1, 100);
files->set_column_expand(0, true);
files->set_column_expand(1, false);
files->set_column_title(0, TTR("Resource"));
diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp
index dbb23d8603..306a88047a 100644
--- a/editor/editor_autoload_settings.cpp
+++ b/editor/editor_autoload_settings.cpp
@@ -882,19 +882,19 @@ EditorAutoloadSettings::EditorAutoloadSettings() {
tree->set_column_title(0, TTR("Name"));
tree->set_column_expand(0, true);
- tree->set_column_min_width(0, 100 * EDSCALE);
+ tree->set_column_custom_minimum_width(0, 100 * EDSCALE);
tree->set_column_title(1, TTR("Path"));
tree->set_column_expand(1, true);
- tree->set_column_min_width(1, 100 * EDSCALE);
+ tree->set_column_custom_minimum_width(1, 100 * EDSCALE);
tree->set_column_title(2, TTR("Global Variable"));
tree->set_column_expand(2, false);
// Reserve enough space for translations of "Global Variable" which may be longer.
- tree->set_column_min_width(2, 150 * EDSCALE);
+ tree->set_column_custom_minimum_width(2, 150 * EDSCALE);
tree->set_column_expand(3, false);
- tree->set_column_min_width(3, 120 * EDSCALE);
+ tree->set_column_custom_minimum_width(3, 120 * EDSCALE);
tree->connect("cell_selected", callable_mp(this, &EditorAutoloadSettings::_autoload_selected));
tree->connect("item_edited", callable_mp(this, &EditorAutoloadSettings::_autoload_edited));
diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp
index b93ffa9321..57ddc64e95 100644
--- a/editor/editor_help_search.cpp
+++ b/editor/editor_help_search.cpp
@@ -239,7 +239,7 @@ EditorHelpSearch::EditorHelpSearch() {
results_tree->set_column_title(0, TTR("Name"));
results_tree->set_column_title(1, TTR("Member Type"));
results_tree->set_column_expand(1, false);
- results_tree->set_column_min_width(1, 150 * EDSCALE);
+ results_tree->set_column_custom_minimum_width(1, 150 * EDSCALE);
results_tree->set_custom_minimum_size(Size2(0, 100) * EDSCALE);
results_tree->set_hide_root(true);
results_tree->set_select_mode(Tree::SELECT_ROW);
diff --git a/editor/editor_plugin_settings.cpp b/editor/editor_plugin_settings.cpp
index 67ce1ade4d..62fbad7bcf 100644
--- a/editor/editor_plugin_settings.cpp
+++ b/editor/editor_plugin_settings.cpp
@@ -216,10 +216,10 @@ EditorPluginSettings::EditorPluginSettings() {
plugin_list->set_column_expand(2, false);
plugin_list->set_column_expand(3, false);
plugin_list->set_column_expand(4, false);
- plugin_list->set_column_min_width(1, 100 * EDSCALE);
- plugin_list->set_column_min_width(2, 250 * EDSCALE);
- plugin_list->set_column_min_width(3, 80 * EDSCALE);
- plugin_list->set_column_min_width(4, 40 * EDSCALE);
+ plugin_list->set_column_custom_minimum_width(1, 100 * EDSCALE);
+ plugin_list->set_column_custom_minimum_width(2, 250 * EDSCALE);
+ plugin_list->set_column_custom_minimum_width(3, 80 * EDSCALE);
+ plugin_list->set_column_custom_minimum_width(4, 40 * EDSCALE);
plugin_list->set_hide_root(true);
plugin_list->connect("item_edited", callable_mp(this, &EditorPluginSettings::_plugin_activity_changed));
diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp
index c29b5d5906..cb8de09a9a 100644
--- a/editor/find_in_files.cpp
+++ b/editor/find_in_files.cpp
@@ -638,7 +638,7 @@ void FindInFilesPanel::set_with_replace(bool with_replace) {
// Results show checkboxes on their left so they can be opted out
_results_display->set_columns(2);
_results_display->set_column_expand(0, false);
- _results_display->set_column_min_width(0, 48 * EDSCALE);
+ _results_display->set_column_custom_minimum_width(0, 48 * EDSCALE);
} else {
// Results are single-cell items
diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp
index cb9fd1f28e..f9f47ec4f4 100644
--- a/editor/import/scene_import_settings.cpp
+++ b/editor/import/scene_import_settings.cpp
@@ -1163,13 +1163,13 @@ SceneImportSettings::SceneImportSettings() {
external_path_tree->set_columns(3);
external_path_tree->set_column_titles_visible(true);
external_path_tree->set_column_expand(0, true);
- external_path_tree->set_column_min_width(0, 100 * EDSCALE);
+ external_path_tree->set_column_custom_minimum_width(0, 100 * EDSCALE);
external_path_tree->set_column_title(0, TTR("Resource"));
external_path_tree->set_column_expand(1, true);
- external_path_tree->set_column_min_width(1, 100 * EDSCALE);
+ external_path_tree->set_column_custom_minimum_width(1, 100 * EDSCALE);
external_path_tree->set_column_title(1, TTR("Path"));
external_path_tree->set_column_expand(2, false);
- external_path_tree->set_column_min_width(2, 200 * EDSCALE);
+ external_path_tree->set_column_custom_minimum_width(2, 200 * EDSCALE);
external_path_tree->set_column_title(2, TTR("Status"));
save_path = memnew(EditorFileDialog);
save_path->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_DIR);
diff --git a/editor/localization_editor.cpp b/editor/localization_editor.cpp
index 161f1dde0d..91a15f1131 100644
--- a/editor/localization_editor.cpp
+++ b/editor/localization_editor.cpp
@@ -729,7 +729,7 @@ LocalizationEditor::LocalizationEditor() {
translation_remap_options->set_column_titles_visible(true);
translation_remap_options->set_column_expand(0, true);
translation_remap_options->set_column_expand(1, false);
- translation_remap_options->set_column_min_width(1, 200);
+ translation_remap_options->set_column_custom_minimum_width(1, 200);
translation_remap_options->connect("item_edited", callable_mp(this, &LocalizationEditor::_translation_res_option_changed));
translation_remap_options->connect("button_pressed", callable_mp(this, &LocalizationEditor::_translation_res_option_delete));
tmc->add_child(translation_remap_options);
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index e31c98db92..48d7cfdee2 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -569,8 +569,8 @@ void AnimationPlayerEditor::_animation_blend() {
blend_editor.dialog->popup_centered(Size2(400, 400) * EDSCALE);
blend_editor.tree->set_hide_root(true);
- blend_editor.tree->set_column_min_width(0, 10);
- blend_editor.tree->set_column_min_width(1, 3);
+ blend_editor.tree->set_column_custom_minimum_width(0, 10);
+ blend_editor.tree->set_column_custom_minimum_width(1, 3);
List<StringName> anims;
player->get_animation_list(&anims);
diff --git a/editor/plugins/resource_preloader_editor_plugin.cpp b/editor/plugins/resource_preloader_editor_plugin.cpp
index b8b2c6d343..a7c11f8521 100644
--- a/editor/plugins/resource_preloader_editor_plugin.cpp
+++ b/editor/plugins/resource_preloader_editor_plugin.cpp
@@ -367,8 +367,8 @@ ResourcePreloaderEditor::ResourcePreloaderEditor() {
tree = memnew(Tree);
tree->connect("button_pressed", callable_mp(this, &ResourcePreloaderEditor::_cell_button_pressed));
tree->set_columns(2);
- tree->set_column_min_width(0, 2);
- tree->set_column_min_width(1, 3);
+ tree->set_column_custom_minimum_width(0, 2);
+ tree->set_column_custom_minimum_width(1, 3);
tree->set_column_expand(0, true);
tree->set_column_expand(1, true);
tree->set_v_size_flags(SIZE_EXPAND_FILL);
diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp
index 4ab5887cd7..99d7267eac 100644
--- a/editor/plugins/theme_editor_plugin.cpp
+++ b/editor/plugins/theme_editor_plugin.cpp
@@ -932,9 +932,9 @@ ThemeItemImportTree::ThemeItemImportTree() {
import_items_tree->set_column_expand(0, true);
import_items_tree->set_column_expand(IMPORT_ITEM, false);
import_items_tree->set_column_expand(IMPORT_ITEM_DATA, false);
- import_items_tree->set_column_min_width(0, 160 * EDSCALE);
- import_items_tree->set_column_min_width(IMPORT_ITEM, 80 * EDSCALE);
- import_items_tree->set_column_min_width(IMPORT_ITEM_DATA, 80 * EDSCALE);
+ import_items_tree->set_column_custom_minimum_width(0, 160 * EDSCALE);
+ import_items_tree->set_column_custom_minimum_width(IMPORT_ITEM, 80 * EDSCALE);
+ import_items_tree->set_column_custom_minimum_width(IMPORT_ITEM_DATA, 80 * EDSCALE);
ScrollContainer *import_bulk_sc = memnew(ScrollContainer);
import_bulk_sc->set_custom_minimum_size(Size2(260.0, 0.0) * EDSCALE);
diff --git a/modules/gdnative/gdnative_library_editor_plugin.cpp b/modules/gdnative/gdnative_library_editor_plugin.cpp
index b4ac0d886e..bdbf151393 100644
--- a/modules/gdnative/gdnative_library_editor_plugin.cpp
+++ b/modules/gdnative/gdnative_library_editor_plugin.cpp
@@ -356,12 +356,12 @@ GDNativeLibraryEditor::GDNativeLibraryEditor() {
tree->set_column_titles_visible(true);
tree->set_columns(4);
tree->set_column_expand(0, false);
- tree->set_column_min_width(0, int(200 * EDSCALE));
+ tree->set_column_custom_minimum_width(0, int(200 * EDSCALE));
tree->set_column_title(0, TTR("Platform"));
tree->set_column_title(1, TTR("Dynamic Library"));
tree->set_column_title(2, TTR("Dependencies"));
tree->set_column_expand(3, false);
- tree->set_column_min_width(3, int(110 * EDSCALE));
+ tree->set_column_custom_minimum_width(3, int(110 * EDSCALE));
tree->connect("button_pressed", callable_mp(this, &GDNativeLibraryEditor::_on_item_button));
tree->connect("item_collapsed", callable_mp(this, &GDNativeLibraryEditor::_on_item_collapsed));
tree->connect("item_activated", callable_mp(this, &GDNativeLibraryEditor::_on_item_activated));
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp
index 674403905a..a5080f9c41 100644
--- a/modules/gltf/gltf_document.cpp
+++ b/modules/gltf/gltf_document.cpp
@@ -5537,6 +5537,8 @@ struct EditorSceneImporterGLTFInterpolate<Quaternion> {
template <class T>
T GLTFDocument::_interpolate_track(const Vector<float> &p_times, const Vector<T> &p_values, const float p_time, const GLTFAnimation::Interpolation p_interp) {
+ ERR_FAIL_COND_V(!p_values.size(), T());
+ ERR_FAIL_COND_V(p_times.size() != p_values.size(), p_values[0]);
//could use binary search, worth it?
int idx = -1;
for (int i = 0; i < p_times.size(); i++) {
diff --git a/modules/websocket/websocket_client.cpp b/modules/websocket/websocket_client.cpp
index 27f0f9af6b..af1dc8ff54 100644
--- a/modules/websocket/websocket_client.cpp
+++ b/modules/websocket/websocket_client.cpp
@@ -42,9 +42,9 @@ Error WebSocketClient::connect_to_url(String p_url, const Vector<String> p_proto
_is_multiplayer = gd_mp_api;
String host = p_url;
- String path = "/";
- String scheme = "";
- int port = 80;
+ String path;
+ String scheme;
+ int port = 0;
Error err = p_url.parse_url(scheme, host, port, path);
ERR_FAIL_COND_V_MSG(err != OK, err, "Invalid URL: " + p_url);
@@ -55,6 +55,9 @@ Error WebSocketClient::connect_to_url(String p_url, const Vector<String> p_proto
if (port == 0) {
port = ssl ? 443 : 80;
}
+ if (path.is_empty()) {
+ path = "/";
+ }
return connect_to_host(host, path, port, ssl, p_protocols, p_custom_headers);
}
diff --git a/modules/websocket/wsl_client.cpp b/modules/websocket/wsl_client.cpp
index af1bdb532c..74017fedd7 100644
--- a/modules/websocket/wsl_client.cpp
+++ b/modules/websocket/wsl_client.cpp
@@ -158,6 +158,7 @@ bool WSLClient::_verify_headers(String &r_protocol) {
Error WSLClient::connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, const Vector<String> p_protocols, const Vector<String> p_custom_headers) {
ERR_FAIL_COND_V(_connection.is_valid(), ERR_ALREADY_IN_USE);
+ ERR_FAIL_COND_V(p_path.is_empty(), ERR_INVALID_PARAMETER);
_peer = Ref<WSLPeer>(memnew(WSLPeer));
IPAddress addr;
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index f677b3592a..521d37060a 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -489,11 +489,11 @@ TreeItem *TreeItem::create_child(int p_idx) {
return ti;
}
-Tree *TreeItem::get_tree() {
+Tree *TreeItem::get_tree() const {
return tree;
}
-TreeItem *TreeItem::get_next() {
+TreeItem *TreeItem::get_next() const {
return next;
}
@@ -516,11 +516,11 @@ TreeItem *TreeItem::get_prev() {
return prev;
}
-TreeItem *TreeItem::get_parent() {
+TreeItem *TreeItem::get_parent() const {
return parent;
}
-TreeItem *TreeItem::get_first_child() {
+TreeItem *TreeItem::get_first_child() const {
return first_child;
}
@@ -953,6 +953,53 @@ bool TreeItem::is_folding_disabled() const {
return disable_folding;
}
+Size2 TreeItem::get_minimum_size(int p_column) {
+ ERR_FAIL_INDEX_V(p_column, cells.size(), Size2());
+ Tree *tree = get_tree();
+ ERR_FAIL_COND_V(!tree, Size2());
+
+ Size2 size;
+
+ // Default offset?
+ //size.width += (disable_folding || tree->hide_folding) ? tree->cache.hseparation : tree->cache.item_margin;
+
+ // Text.
+ const TreeItem::Cell &cell = cells[p_column];
+ if (!cell.text.is_empty()) {
+ if (cell.dirty) {
+ tree->update_item_cell(this, p_column);
+ }
+ Size2 text_size = cell.text_buf->get_size();
+ size.width += text_size.width;
+ size.height = MAX(size.height, text_size.height);
+ }
+
+ // Icon.
+ if (cell.icon.is_valid()) {
+ Size2i icon_size = cell.get_icon_size();
+ if (cell.icon_max_w > 0 && icon_size.width > cell.icon_max_w) {
+ icon_size.width = cell.icon_max_w;
+ }
+ size.width += icon_size.width + tree->cache.hseparation;
+ size.height = MAX(size.height, icon_size.height);
+ }
+
+ // Buttons.
+ for (int i = 0; i < cell.buttons.size(); i++) {
+ Ref<Texture2D> texture = cell.buttons[i].texture;
+ if (texture.is_valid()) {
+ Size2 button_size = texture->get_size() + tree->cache.button_pressed->get_minimum_size();
+ size.width += button_size.width;
+ size.height = MAX(size.height, button_size.height);
+ }
+ }
+ if (cell.buttons.size() >= 2) {
+ size.width += (cell.buttons.size() - 1) * tree->cache.button_margin;
+ }
+
+ return size;
+}
+
Variant TreeItem::_call_recursive_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
if (p_argcount < 1) {
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
@@ -3276,7 +3323,7 @@ Size2 Tree::get_internal_min_size() const {
size.height += get_item_height(root);
}
for (int i = 0; i < columns.size(); i++) {
- size.width += columns[i].min_width;
+ size.width += get_column_minimum_width(i);
}
return size;
@@ -3300,26 +3347,38 @@ void Tree::update_scrollbars() {
h_scroll->set_begin(Point2(0, size.height - hmin.height));
h_scroll->set_end(Point2(size.width - vmin.width, size.height));
- Size2 min = get_internal_min_size();
+ Size2 internal_min_size = get_internal_min_size();
- if (min.height < size.height - hmin.height) {
- v_scroll->hide();
- cache.offset.y = 0;
- } else {
+ bool display_vscroll = internal_min_size.height + cache.bg->get_margin(SIDE_TOP) > size.height;
+ bool display_hscroll = internal_min_size.width + cache.bg->get_margin(SIDE_LEFT) > size.width;
+ for (int i = 0; i < 2; i++) {
+ // Check twice, as both values are dependent on each other.
+ if (display_hscroll) {
+ display_vscroll = internal_min_size.height + cache.bg->get_margin(SIDE_TOP) + hmin.height > size.height;
+ }
+ if (display_vscroll) {
+ display_hscroll = internal_min_size.width + cache.bg->get_margin(SIDE_LEFT) + vmin.width > size.width;
+ }
+ }
+
+ if (display_vscroll) {
v_scroll->show();
- v_scroll->set_max(min.height);
+ v_scroll->set_max(internal_min_size.height);
v_scroll->set_page(size.height - hmin.height - tbh);
cache.offset.y = v_scroll->get_value();
+ } else {
+ v_scroll->hide();
+ cache.offset.y = 0;
}
- if (min.width < size.width - vmin.width) {
- h_scroll->hide();
- cache.offset.x = 0;
- } else {
+ if (display_hscroll) {
h_scroll->show();
- h_scroll->set_max(min.width);
+ h_scroll->set_max(internal_min_size.width);
h_scroll->set_page(size.width - vmin.width);
cache.offset.x = h_scroll->get_value();
+ } else {
+ h_scroll->hide();
+ cache.offset.x = 0;
}
}
@@ -3445,7 +3504,7 @@ void Tree::_notification(int p_what) {
draw_ofs.y += tbh;
draw_size.y -= tbh;
- if (root) {
+ if (root && get_size().x > 0 && get_size().y > 0) {
draw_item(Point2(), draw_ofs, draw_size, root);
}
@@ -3513,7 +3572,17 @@ void Tree::_update_all() {
}
Size2 Tree::get_minimum_size() const {
- return Size2(1, 1);
+ if (h_scroll_enabled && v_scroll_enabled) {
+ return Size2();
+ } else {
+ Vector2 min_size = get_internal_min_size();
+ Ref<StyleBox> bg = cache.bg;
+ if (bg.is_valid()) {
+ min_size.x += bg->get_margin(SIDE_LEFT) + bg->get_margin(SIDE_RIGHT);
+ min_size.y += bg->get_margin(SIDE_TOP) + bg->get_margin(SIDE_BOTTOM);
+ }
+ return Vector2(h_scroll_enabled ? 0 : min_size.x, v_scroll_enabled ? 0 : min_size.y);
+ }
}
TreeItem *Tree::create_item(TreeItem *p_parent, int p_idx) {
@@ -3541,11 +3610,11 @@ TreeItem *Tree::create_item(TreeItem *p_parent, int p_idx) {
return ti;
}
-TreeItem *Tree::get_root() {
+TreeItem *Tree::get_root() const {
return root;
}
-TreeItem *Tree::get_last_item() {
+TreeItem *Tree::get_last_item() const {
TreeItem *last = root;
while (last) {
@@ -3675,13 +3744,13 @@ bool Tree::is_root_hidden() const {
return hide_root;
}
-void Tree::set_column_min_width(int p_column, int p_min_width) {
+void Tree::set_column_custom_minimum_width(int p_column, int p_min_width) {
ERR_FAIL_INDEX(p_column, columns.size());
- if (p_min_width < 1) {
+ if (p_min_width < 0) {
return;
}
- columns.write[p_column].min_width = p_min_width;
+ columns.write[p_column].custom_min_width = p_min_width;
update();
}
@@ -3748,44 +3817,79 @@ TreeItem *Tree::get_next_selected(TreeItem *p_item) {
return nullptr;
}
-int Tree::get_column_width(int p_column) const {
+int Tree::get_column_minimum_width(int p_column) const {
ERR_FAIL_INDEX_V(p_column, columns.size(), -1);
- if (!columns[p_column].expand) {
- return columns[p_column].min_width;
+ if (columns[p_column].custom_min_width != 0) {
+ return columns[p_column].custom_min_width;
+ } else {
+ int depth = 0;
+ int min_width = 0;
+ TreeItem *next;
+ for (TreeItem *item = get_root(); item; item = next) {
+ next = item->get_next_visible();
+ // Compute the depth in tree.
+ if (next && p_column == 0) {
+ if (next->get_parent() == item) {
+ depth += 1;
+ } else {
+ TreeItem *common_parent = item->get_parent();
+ while (common_parent != next->get_parent()) {
+ common_parent = common_parent->get_parent();
+ depth -= 1;
+ }
+ }
+ }
+
+ // Get the item minimum size.
+ Size2 item_size = item->get_minimum_size(p_column);
+ if (p_column == 0) {
+ item_size.width += cache.item_margin * depth;
+ }
+ min_width = MAX(min_width, item_size.width);
+ }
+ return min_width;
}
+}
- int expand_area = get_size().width;
+int Tree::get_column_width(int p_column) const {
+ ERR_FAIL_INDEX_V(p_column, columns.size(), -1);
- Ref<StyleBox> bg = cache.bg;
+ if (columns[p_column].expand) {
+ int expand_area = get_size().width;
- if (bg.is_valid()) {
- expand_area -= bg->get_margin(SIDE_LEFT) + bg->get_margin(SIDE_RIGHT);
- }
+ Ref<StyleBox> bg = cache.bg;
- if (v_scroll->is_visible_in_tree()) {
- expand_area -= v_scroll->get_combined_minimum_size().width;
- }
+ if (bg.is_valid()) {
+ expand_area -= bg->get_margin(SIDE_LEFT) + bg->get_margin(SIDE_RIGHT);
+ }
- int expanding_columns = 0;
- int expanding_total = 0;
+ if (v_scroll->is_visible_in_tree()) {
+ expand_area -= v_scroll->get_combined_minimum_size().width;
+ }
- for (int i = 0; i < columns.size(); i++) {
- if (!columns[i].expand) {
- expand_area -= columns[i].min_width;
- } else {
- expanding_total += columns[i].min_width;
- expanding_columns++;
+ int expanding_columns = 0;
+ int expanding_total = 0;
+
+ for (int i = 0; i < columns.size(); i++) {
+ if (!columns[i].expand) {
+ expand_area -= get_column_minimum_width(i);
+ } else {
+ expanding_total += get_column_minimum_width(i);
+ expanding_columns++;
+ }
}
- }
- if (expand_area < expanding_total) {
- return columns[p_column].min_width;
- }
+ if (expand_area < expanding_total) {
+ return get_column_minimum_width(p_column);
+ }
- ERR_FAIL_COND_V(expanding_columns == 0, -1); // shouldn't happen
+ ERR_FAIL_COND_V(expanding_columns == 0, -1); // shouldn't happen
- return expand_area * columns[p_column].min_width / expanding_total;
+ return expand_area * get_column_minimum_width(p_column) / expanding_total;
+ } else {
+ return get_column_minimum_width(p_column);
+ }
}
void Tree::propagate_set_columns(TreeItem *p_item) {
@@ -4047,6 +4151,24 @@ void Tree::scroll_to_item(TreeItem *p_item) {
}
}
+void Tree::set_h_scroll_enabled(bool p_enable) {
+ h_scroll_enabled = p_enable;
+ minimum_size_changed();
+}
+
+bool Tree::is_h_scroll_enabled() const {
+ return h_scroll_enabled;
+}
+
+void Tree::set_v_scroll_enabled(bool p_enable) {
+ v_scroll_enabled = p_enable;
+ minimum_size_changed();
+}
+
+bool Tree::is_v_scroll_enabled() const {
+ return v_scroll_enabled;
+}
+
TreeItem *Tree::_search_item_text(TreeItem *p_at, const String &p_find, int *r_col, bool p_selectable, bool p_backwards) {
TreeItem *from = p_at;
TreeItem *loop = nullptr; // Safe-guard against infinite loop.
@@ -4422,7 +4544,7 @@ void Tree::_bind_methods() {
ClassDB::bind_method(D_METHOD("create_item", "parent", "idx"), &Tree::_create_item, DEFVAL(Variant()), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("get_root"), &Tree::get_root);
- ClassDB::bind_method(D_METHOD("set_column_min_width", "column", "min_width"), &Tree::set_column_min_width);
+ ClassDB::bind_method(D_METHOD("set_column_custom_minimum_width", "column", "min_width"), &Tree::set_column_custom_minimum_width);
ClassDB::bind_method(D_METHOD("set_column_expand", "column", "expand"), &Tree::set_column_expand);
ClassDB::bind_method(D_METHOD("get_column_width", "column"), &Tree::get_column_width);
@@ -4468,6 +4590,12 @@ void Tree::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_scroll"), &Tree::get_scroll);
ClassDB::bind_method(D_METHOD("scroll_to_item", "item"), &Tree::_scroll_to_item);
+ ClassDB::bind_method(D_METHOD("set_h_scroll_enabled", "h_scroll"), &Tree::set_h_scroll_enabled);
+ ClassDB::bind_method(D_METHOD("is_h_scroll_enabled"), &Tree::is_h_scroll_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_v_scroll_enabled", "h_scroll"), &Tree::set_v_scroll_enabled);
+ ClassDB::bind_method(D_METHOD("is_v_scroll_enabled"), &Tree::is_v_scroll_enabled);
+
ClassDB::bind_method(D_METHOD("set_hide_folding", "hide"), &Tree::set_hide_folding);
ClassDB::bind_method(D_METHOD("is_folding_hidden"), &Tree::is_folding_hidden);
@@ -4487,6 +4615,8 @@ void Tree::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_root"), "set_hide_root", "is_root_hidden");
ADD_PROPERTY(PropertyInfo(Variant::INT, "drop_mode_flags", PROPERTY_HINT_FLAGS, "On Item,In Between"), "set_drop_mode_flags", "get_drop_mode_flags");
ADD_PROPERTY(PropertyInfo(Variant::INT, "select_mode", PROPERTY_HINT_ENUM, "Single,Row,Multi"), "set_select_mode", "get_select_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_horizontal_enabled"), "set_h_scroll_enabled", "is_h_scroll_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_vertical_enabled"), "set_v_scroll_enabled", "is_v_scroll_enabled");
ADD_SIGNAL(MethodInfo("item_selected"));
ADD_SIGNAL(MethodInfo("cell_selected"));
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index 42dd27cb55..fd5fcd7838 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -315,16 +315,18 @@ public:
void set_disable_folding(bool p_disable);
bool is_folding_disabled() const;
+ Size2 get_minimum_size(int p_column);
+
/* Item manipulation */
TreeItem *create_child(int p_idx = -1);
- Tree *get_tree();
+ Tree *get_tree() const;
TreeItem *get_prev();
- TreeItem *get_next();
- TreeItem *get_parent();
- TreeItem *get_first_child();
+ TreeItem *get_next() const;
+ TreeItem *get_parent() const;
+ TreeItem *get_first_child() const;
TreeItem *get_prev_visible(bool p_wrap = false);
TreeItem *get_next_visible(bool p_wrap = false);
@@ -408,7 +410,7 @@ private:
int drop_mode_flags = 0;
struct ColumnInfo {
- int min_width = 1;
+ int custom_min_width = 0;
bool expand = true;
String title;
Ref<TextLine> text_buf;
@@ -545,6 +547,8 @@ private:
void _scroll_moved(float p_value);
HScrollBar *h_scroll;
VScrollBar *v_scroll;
+ bool h_scroll_enabled = true;
+ bool v_scroll_enabled = true;
Size2 get_internal_min_size() const;
void update_cache();
@@ -623,11 +627,12 @@ public:
void clear();
TreeItem *create_item(TreeItem *p_parent = nullptr, int p_idx = -1);
- TreeItem *get_root();
- TreeItem *get_last_item();
+ TreeItem *get_root() const;
+ TreeItem *get_last_item() const;
- void set_column_min_width(int p_column, int p_min_width);
+ void set_column_custom_minimum_width(int p_column, int p_min_width);
void set_column_expand(int p_column, bool p_expand);
+ int get_column_minimum_width(int p_column) const;
int get_column_width(int p_column) const;
void set_hide_root(bool p_enabled);
@@ -679,6 +684,10 @@ public:
Point2 get_scroll() const;
void scroll_to_item(TreeItem *p_item);
+ void set_h_scroll_enabled(bool p_enable);
+ bool is_h_scroll_enabled() const;
+ void set_v_scroll_enabled(bool p_enable);
+ bool is_v_scroll_enabled() const;
void set_cursor_can_exit_tree(bool p_enable);
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 092aba8b33..cb66d5724d 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -878,6 +878,20 @@ void BaseMaterial3D::_update_shader() {
code += "\tvec2 base_uv2 = UV2;\n";
}
+ if (features[FEATURE_HEIGHT_MAPPING] && flags[FLAG_UV1_USE_TRIPLANAR]) {
+ // Display both resource name and albedo texture name.
+ // Materials are often built-in to scenes, so displaying the resource name alone may not be meaningful.
+ // On the other hand, albedo textures are almost always external to the scene.
+ if (textures[TEXTURE_ALBEDO].is_valid()) {
+ WARN_PRINT(vformat("%s (albedo %s): Height mapping is not supported on triplanar materials. Ignoring height mapping in favor of triplanar mapping.", get_path(), textures[TEXTURE_ALBEDO]->get_path()));
+ } else if (!get_path().is_empty()) {
+ WARN_PRINT(vformat("%s: Height mapping is not supported on triplanar materials. Ignoring height mapping in favor of triplanar mapping.", get_path()));
+ } else {
+ // Resource wasn't saved yet.
+ WARN_PRINT("Height mapping is not supported on triplanar materials. Ignoring height mapping in favor of triplanar mapping.");
+ }
+ }
+
if (!RenderingServer::get_singleton()->is_low_end() && features[FEATURE_HEIGHT_MAPPING] && !flags[FLAG_UV1_USE_TRIPLANAR]) { //heightmap not supported with triplanar
code += "\t{\n";
code += "\t\tvec3 view_dir = normalize(normalize(-VERTEX)*mat3(TANGENT*heightmap_flip.x,-BINORMAL*heightmap_flip.y,NORMAL));\n"; // binormal is negative due to mikktspace, flip 'unflips' it ;-)