diff options
36 files changed, 2079 insertions, 659 deletions
@@ -2,7 +2,7 @@ <p align="center"> <a href="https://godotengine.org"> - <img src="logo.svg" width="400" alt="Godot Engine logo"> + <img src="logo_outlined.svg" width="400" alt="Godot Engine logo"> </a> </p> diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index d997073849..cb95deb9a0 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -348,6 +348,7 @@ </return> <description> Returns a string that is unique to the device. + [b]Note:[/b] This string may change without notice if the user reinstalls/upgrades their operating system or changes their hardware. This means it should generally not be used to encrypt persistent data as the data saved prior to an unexpected ID change would become inaccessible. The returned string may also be falsified using external programs, so do not rely on the string returned by [method get_unique_id] for security purposes. [b]Note:[/b] Returns an empty string on HTML5 and UWP, as this method isn't implemented on those platforms yet. </description> </method> diff --git a/doc/classes/Skeleton3D.xml b/doc/classes/Skeleton3D.xml index c6dd6fb142..0b278d7d25 100644 --- a/doc/classes/Skeleton3D.xml +++ b/doc/classes/Skeleton3D.xml @@ -91,6 +91,15 @@ Returns the overall transform of the specified bone, with respect to the skeleton. Being relative to the skeleton frame, this is not the actual "global" transform of the bone. </description> </method> + <method name="get_bone_global_pose_no_override" qualifiers="const"> + <return type="Transform"> + </return> + <argument index="0" name="bone_idx" type="int"> + </argument> + <description> + Returns the overall transform of the specified bone, with respect to the skeleton, but without any global pose overrides. Being relative to the skeleton frame, this is not the actual "global" transform of the bone. + </description> + </method> <method name="get_bone_name" qualifiers="const"> <return type="String"> </return> diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp index 12a67c0e07..4649cee17f 100644 --- a/drivers/vulkan/vulkan_context.cpp +++ b/drivers/vulkan/vulkan_context.cpp @@ -1656,13 +1656,13 @@ Error VulkanContext::prepare_buffers() { if (err == VK_ERROR_OUT_OF_DATE_KHR) { // swapchain is out of date (e.g. the window was resized) and // must be recreated: - print_line("early out of data"); + print_verbose("Vulkan: Early out of date swapchain, recreating."); //resize_notify(); _update_swap_chain(w); } else if (err == VK_SUBOPTIMAL_KHR) { - print_line("early suboptimal"); // swapchain is not as optimal as it could be, but the platform's // presentation engine will still present the image correctly. + print_verbose("Vulkan: Early suboptimal swapchain."); break; } else { ERR_FAIL_COND_V(err, ERR_CANT_CREATE); @@ -1870,12 +1870,12 @@ Error VulkanContext::swap_buffers() { if (err == VK_ERROR_OUT_OF_DATE_KHR) { // swapchain is out of date (e.g. the window was resized) and // must be recreated: - print_line("out of date"); + print_verbose("Vulkan: Swapchain is out of date, recreating."); resize_notify(); } else if (err == VK_SUBOPTIMAL_KHR) { // swapchain is not as optimal as it could be, but the platform's // presentation engine will still present the image correctly. - print_line("suboptimal"); + print_verbose("Vulkan: Swapchain is suboptimal."); } else { ERR_FAIL_COND_V(err, ERR_CANT_CREATE); } @@ -1971,13 +1971,13 @@ void VulkanContext::local_device_push_command_buffers(RID p_local_device, const VkResult err = vkQueueSubmit(ld->queue, 1, &submit_info, VK_NULL_HANDLE); if (err == VK_ERROR_OUT_OF_HOST_MEMORY) { - print_line("out of host memory"); + print_line("Vulkan: Out of host memory!"); } if (err == VK_ERROR_OUT_OF_DEVICE_MEMORY) { - print_line("out of device memory"); + print_line("Vulkan: Out of device memory!"); } if (err == VK_ERROR_DEVICE_LOST) { - print_line("device lost"); + print_line("Vulkan: Device lost!"); } ERR_FAIL_COND(err); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 7e39c4c654..7aed5b2b7f 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -2447,15 +2447,24 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { Node *scene = editor_data.get_edited_scene_root(scene_idx); if (!scene) { - int saved = _save_external_resources(); - String err_text; + if (p_option == FILE_SAVE_SCENE) { + // Pressing Ctrl + S saves the current script if a scene is currently open, but it won't if the scene has no root node. + // Work around this by explicitly saving the script in this case (similar to pressing Ctrl + Alt + S). + ScriptEditor::get_singleton()->save_current_script(); + } + + const int saved = _save_external_resources(); if (saved > 0) { - err_text = vformat(TTR("Saved %s modified resource(s)."), itos(saved)); - } else { - err_text = TTR("A root node is required to save the scene."); + show_accept( + vformat(TTR("The current scene has no root node, but %d modified external resource(s) were saved anyway."), saved), + TTR("OK")); + } else if (p_option == FILE_SAVE_AS_SCENE) { + // Don't show this dialog when pressing Ctrl + S to avoid interfering with script saving. + show_accept( + TTR("A root node is required to save the scene. You can add a root node using the Scene tree dock."), + TTR("OK")); } - show_accept(err_text, TTR("OK")); break; } @@ -6189,8 +6198,8 @@ EditorNode::EditorNode() { p = file_menu->get_popup(); - p->add_shortcut(ED_SHORTCUT("editor/new_scene", TTR("New Scene")), FILE_NEW_SCENE); - p->add_shortcut(ED_SHORTCUT("editor/new_inherited_scene", TTR("New Inherited Scene...")), FILE_NEW_INHERITED_SCENE); + p->add_shortcut(ED_SHORTCUT("editor/new_scene", TTR("New Scene"), KEY_MASK_CMD + KEY_N), FILE_NEW_SCENE); + p->add_shortcut(ED_SHORTCUT("editor/new_inherited_scene", TTR("New Inherited Scene..."), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_N), FILE_NEW_INHERITED_SCENE); p->add_shortcut(ED_SHORTCUT("editor/open_scene", TTR("Open Scene..."), KEY_MASK_CMD + KEY_O), FILE_OPEN_SCENE); p->add_shortcut(ED_SHORTCUT("editor/reopen_closed_scene", TTR("Reopen Closed Scene"), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_T), FILE_OPEN_PREV); p->add_submenu_item(TTR("Open Recent"), "RecentScenes", FILE_OPEN_RECENT); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 47c0e31da6..6638962c72 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -3254,6 +3254,8 @@ EditorPropertyResource::EditorPropertyResource() { preview->set_offset(SIDE_TOP, 1); preview->set_offset(SIDE_BOTTOM, -1); preview->set_offset(SIDE_RIGHT, -1); + // This is required to draw the focus outline in front of the preview, rather than behind. + preview->set_draw_behind_parent(true); assign->add_child(preview); assign->connect("gui_input", callable_mp(this, &EditorPropertyResource::_button_input)); diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index fdca508c9e..aba14df812 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -444,8 +444,8 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { hints["interface/theme/base_color"] = PropertyInfo(Variant::COLOR, "interface/theme/base_color", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT); _initial_set("interface/theme/accent_color", Color(0.41, 0.61, 0.91)); hints["interface/theme/accent_color"] = PropertyInfo(Variant::COLOR, "interface/theme/accent_color", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT); - _initial_set("interface/theme/contrast", 0.25); - hints["interface/theme/contrast"] = PropertyInfo(Variant::FLOAT, "interface/theme/contrast", PROPERTY_HINT_RANGE, "0.01, 1, 0.01"); + _initial_set("interface/theme/contrast", 0.3); + hints["interface/theme/contrast"] = PropertyInfo(Variant::FLOAT, "interface/theme/contrast", PROPERTY_HINT_RANGE, "-1, 1, 0.01"); _initial_set("interface/theme/icon_saturation", 1.0); hints["interface/theme/icon_saturation"] = PropertyInfo(Variant::FLOAT, "interface/theme/icon_saturation", PROPERTY_HINT_RANGE, "0,2,0.01", PROPERTY_USAGE_DEFAULT); _initial_set("interface/theme/relationship_line_opacity", 0.1); diff --git a/editor/icons/CollapseTree.svg b/editor/icons/CollapseTree.svg new file mode 100644 index 0000000000..ece9071e03 --- /dev/null +++ b/editor/icons/CollapseTree.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" fill-rule="nonzero"><path d="m8 9.669-3.536 2.583h2.536v2.537h2v-2.537h2.536z"/><path d="m8 6.355-3.536-2.583h2.536v-2.537h2v2.537h2.536z"/><path d="m.704 7.085h14.591v1.831h-14.591z"/></g></svg> diff --git a/editor/icons/ExpandTree.svg b/editor/icons/ExpandTree.svg new file mode 100644 index 0000000000..abdc1f9458 --- /dev/null +++ b/editor/icons/ExpandTree.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" fill-rule="nonzero"><path d="m8 16-3.536-2.597h2.536v-2.523h2v2.523h2.536z"/><path d="m8 0-3.536 2.583h2.536v2.537h2v-2.537h2.536z"/><path d="m.704 7.085h14.591v1.831h-14.591z"/></g></svg> diff --git a/editor/icons/FontSize.svg b/editor/icons/FontSize.svg index e608d89b6a..3e148009ce 100644 --- a/editor/icons/FontSize.svg +++ b/editor/icons/FontSize.svg @@ -1 +1 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><g id="SmallerT"><rect x="1.047" y="7.127" width="6.025" height="1.2" style="fill:#e0e0e0;fill-rule:nonzero;"/><rect x="3.452" y="7.127" width="1.214" height="6.508" style="fill:#e0e0e0;fill-rule:nonzero;"/><rect x="2.238" y="13.171" width="3.643" height="0.465" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M1.477,7.127l0,2.4l-0.43,0l-0,-2.4l0.43,0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M7.071,7.127l0,2.4l-0.43,0l0,-2.4l0.43,0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M1.477,8.327l0,1.2c0,-0.658 0.389,-1.2 0.861,-1.2l-0.861,0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M5.78,8.327c0.473,0 0.861,0.542 0.861,1.2l0,-1.2l-0.861,0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M2.238,13.171c0.666,-0 1.214,-0.42 1.214,-0.93l0,0.93l-1.214,-0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M5.88,13.171c-0.666,-0 -1.214,-0.42 -1.214,-0.93l0,0.93l1.214,-0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/></g><g id="BiggerT"><rect x="4.563" y="2.873" width="10.773" height="1.539" style="fill:#e0e0e0;fill-rule:nonzero;"/><rect x="9.18" y="2.873" width="1.539" height="10.773" style="fill:#e0e0e0;fill-rule:nonzero;"/><rect x="7.641" y="12.877" width="4.617" height="0.769" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M5.332,2.873l0,3.078l-0.769,0l-0,-3.078l0.769,0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M15.336,2.873l-0,3.078l-0.77,0l0,-3.078l0.77,0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M5.332,4.412l0,1.539c0,-0.844 0.695,-1.539 1.539,-1.539l-1.539,0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M13.027,4.412c0.844,0 1.539,0.695 1.539,1.539l0,-1.539l-1.539,0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M7.641,12.877c0.844,-0 1.539,-0.695 1.539,-1.539l-0,1.539l-1.539,-0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/><path d="M12.258,12.877c-0.845,-0 -1.539,-0.695 -1.539,-1.539l-0,1.539l1.539,-0Z" style="fill:#e0e0e0;fill-rule:nonzero;"/></g></svg> +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" fill-rule="nonzero"><path d="m1.047 7.127h6.025v1.2h-6.025z"/><path d="m3.452 7.127h1.214v6.508h-1.214z"/><path d="m2.238 13.171h3.643v.465h-3.643z"/><path d="m1.477 7.127v2.4h-.43v-2.4z"/><path d="m7.071 7.127v2.4h-.43v-2.4z"/><path d="m1.477 8.327v1.2c0-.658.389-1.2.861-1.2z"/><path d="m5.78 8.327c.473 0 .861.542.861 1.2v-1.2z"/><path d="m2.238 13.171c.666 0 1.214-.42 1.214-.93v.93z"/><path d="m5.88 13.171c-.666 0-1.214-.42-1.214-.93v.93z"/><path d="m4.563 2.873h10.773v1.539h-10.773z"/><path d="m9.18 2.873h1.539v10.773h-1.539z"/><path d="m7.641 12.877h4.617v.769h-4.617z"/><path d="m5.332 2.873v3.078h-.769v-3.078z"/><path d="m15.336 2.873v3.078h-.77v-3.078z"/><path d="m5.332 4.412v1.539c0-.844.695-1.539 1.539-1.539z"/><path d="m13.027 4.412c.844 0 1.539.695 1.539 1.539v-1.539z"/><path d="m7.641 12.877c.844 0 1.539-.695 1.539-1.539v1.539z"/><path d="m12.258 12.877c-.845 0-1.539-.695-1.539-1.539v1.539z"/></g></svg> diff --git a/editor/icons/ThemeDeselectAll.svg b/editor/icons/ThemeDeselectAll.svg new file mode 100644 index 0000000000..d43ca85163 --- /dev/null +++ b/editor/icons/ThemeDeselectAll.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="m5.952 6.976h8.063v2.005h-8.063z" fill-rule="nonzero"/><path d="m.989 5.995h4.011v4.01h-4.011zm.968.968h2.075v2.074h-2.075z"/><path d="m5.952 1.956h8.063v2.005h-8.063z" fill-rule="nonzero"/><path d="m.989.974h4.011v4.011h-4.011zm.968.968h2.075v2.075h-2.075z"/><path d="m5.952 11.996h8.063v2.005h-8.063z" fill-rule="nonzero"/><path d="m.989 11.015h4.011v4.011h-4.011zm.968.968h2.075v2.075h-2.075z"/></g></svg> diff --git a/editor/icons/ThemeRemoveAllItems.svg b/editor/icons/ThemeRemoveAllItems.svg index 47ed624d04..652274a0e7 100644 --- a/editor/icons/ThemeRemoveAllItems.svg +++ b/editor/icons/ThemeRemoveAllItems.svg @@ -1 +1 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><path d="M8,1.745c-0.595,0 -1.084,0.489 -1.084,1.084l0,3.699l-3.851,-1.927c-0.163,-0.08 -0.343,-0.119 -0.525,-0.112c-0.395,0.015 -0.752,0.244 -0.929,0.597c-0.076,0.151 -0.115,0.317 -0.115,0.485c0,0.41 0.233,0.786 0.599,0.97l3.481,1.74l-3.481,1.74c-0.366,0.184 -0.599,0.56 -0.599,0.97c0,0.168 0.039,0.334 0.115,0.485c0.183,0.367 0.559,0.599 0.969,0.599c0.168,0 0.334,-0.039 0.485,-0.114l3.851,-1.927l0,3.111c0,0.594 0.489,1.084 1.084,1.084c0.595,-0 1.084,-0.49 1.084,-1.084l-0,-3.111l3.851,1.927c0.151,0.075 0.317,0.114 0.485,0.114c0.41,0 0.786,-0.232 0.969,-0.599c0.076,-0.151 0.115,-0.317 0.115,-0.485c-0,-0.41 -0.233,-0.786 -0.599,-0.97l-3.481,-1.74l3.481,-1.74c0.366,-0.184 0.599,-0.56 0.599,-0.97c-0,-0.168 -0.039,-0.334 -0.115,-0.485c-0.182,-0.364 -0.554,-0.596 -0.961,-0.599c-0.171,-0.001 -0.34,0.038 -0.493,0.114l-3.851,1.927l-0,-3.699c-0,-0.595 -0.489,-1.084 -1.084,-1.084Z" style="fill:#a5efac;"/><path d="M8,1.745c-0,0 -0,1.783 -0,1.783l-1.084,0l0,-0.699c0,-0.595 0.489,-1.084 1.084,-1.084Z" style="fill:#ff7070;fill-rule:nonzero;"/><path d="M1.528,5.312l2.957,-0l-1.42,-0.711c-0.163,-0.08 -0.343,-0.119 -0.525,-0.112c-0.395,0.015 -0.752,0.244 -0.929,0.597c-0.036,0.072 -0.064,0.148 -0.083,0.226Zm5.388,-1.784l1.084,0l-0,1.784l-1.084,-0l0,-1.784Z" style="fill:#ffeb70;fill-rule:nonzero;"/><path d="M6.916,5.312l1.084,-0l-0,1.783l-4.796,0l-1.109,-0.554c-0.366,-0.184 -0.599,-0.56 -0.599,-0.97c0,-0.088 0.011,-0.175 0.032,-0.259l2.957,-0l2.431,1.216l0,-1.216Z" style="fill:#9dff70;fill-rule:nonzero;"/><path d="M3.204,7.095l4.796,0l-0,1.783l-3.619,0l1.195,-0.597l-2.372,-1.186Z" style="fill:#70ffb9;fill-rule:nonzero;"/><path d="M4.381,8.878l3.619,0l-0,1.784l-1.084,-0l0,-0.628l-1.255,0.628l-4.114,-0c0.088,-0.274 0.283,-0.508 0.548,-0.641l2.286,-1.143Z" style="fill:#70deff;fill-rule:nonzero;"/><path d="M6.916,12.445l1.084,0l-0,1.784l-0,-0c-0.595,-0.001 -1.084,-0.49 -1.084,-1.084l0,-0.7Z" style="fill:#ff70ac;fill-rule:nonzero;"/><path d="M6.916,10.662l1.084,-0l-0,1.783l-1.084,0l0,-1.783Zm-1.255,-0l-4.114,-0c-0.033,0.105 -0.051,0.216 -0.051,0.329c0,0.168 0.039,0.334 0.115,0.485c0.183,0.367 0.559,0.599 0.969,0.599c0.168,0 0.334,-0.039 0.485,-0.114l2.596,-1.299Z" style="fill:#9f70ff;fill-rule:nonzero;"/></svg> +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1.745c-.595 0-1.084.489-1.084 1.084v3.699l-3.851-1.927c-.163-.08-.343-.119-.525-.112-.395.015-.752.244-.929.597-.076.151-.115.317-.115.485 0 .41.233.786.599.97l3.481 1.74-3.481 1.74c-.366.184-.599.56-.599.97 0 .168.039.334.115.485.183.367.559.599.969.599.168 0 .334-.039.485-.114l3.851-1.927v3.111c0 .594.489 1.084 1.084 1.084s1.084-.49 1.084-1.084v-3.111l3.851 1.927c.151.075.317.114.485.114.41 0 .786-.232.969-.599.076-.151.115-.317.115-.485 0-.41-.233-.786-.599-.97l-3.481-1.74 3.481-1.74c.366-.184.599-.56.599-.97 0-.168-.039-.334-.115-.485-.182-.364-.554-.596-.961-.599-.171-.001-.34.038-.493.114l-3.851 1.927v-3.699c0-.595-.489-1.084-1.084-1.084z" fill="#a5efac"/><g fill-rule="nonzero"><path d="m8 1.745v1.783h-1.084v-.699c0-.595.489-1.084 1.084-1.084z" fill="#ff7070"/><path d="m1.528 5.312h2.957l-1.42-.711c-.163-.08-.343-.119-.525-.112-.395.015-.752.244-.929.597-.036.072-.064.148-.083.226zm5.388-1.784h1.084v1.784h-1.084z" fill="#ffeb70"/><path d="m6.916 5.312h1.084v1.783h-4.796l-1.109-.554c-.366-.184-.599-.56-.599-.97 0-.088.011-.175.032-.259h2.957l2.431 1.216z" fill="#9dff70"/><path d="m3.204 7.095h4.796v1.783h-3.619l1.195-.597z" fill="#70ffb9"/><path d="m4.381 8.878h3.619v1.784h-1.084v-.628l-1.255.628h-4.114c.088-.274.283-.508.548-.641z" fill="#70deff"/><path d="m6.916 12.445h1.084v1.784c-.595-.001-1.084-.49-1.084-1.084z" fill="#ff70ac"/><path d="m6.916 10.662h1.084v1.783h-1.084zm-1.255 0h-4.114c-.033.105-.051.216-.051.329 0 .168.039.334.115.485.183.367.559.599.969.599.168 0 .334-.039.485-.114z" fill="#9f70ff"/></g></svg> diff --git a/editor/icons/ThemeRemoveCustomItems.svg b/editor/icons/ThemeRemoveCustomItems.svg index bb8a8bd026..839f584fce 100644 --- a/editor/icons/ThemeRemoveCustomItems.svg +++ b/editor/icons/ThemeRemoveCustomItems.svg @@ -1 +1 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><path d="M11.299,3c0.772,0.513 1.42,1.199 1.888,2l-2.553,0c-0.706,-0.621 -1.629,-1 -2.634,-1c-1.005,0 -1.928,0.379 -2.634,1l-2.553,0c0.468,-0.801 1.116,-1.487 1.888,-2l6.598,-0Z" style="fill:#ffeb70;fill-rule:nonzero;"/><path d="M5.366,5c-0.593,0.522 -1.033,1.216 -1.238,2l-2.043,0c0.122,-0.717 0.373,-1.392 0.728,-2l2.553,-0Zm7.821,-0c0.355,0.608 0.606,1.283 0.728,2l-2.043,0c-0.205,-0.784 -0.645,-1.478 -1.238,-2l2.553,-0Z" style="fill:#9dff70;fill-rule:nonzero;"/><path d="M13.915,7c0.056,0.326 0.085,0.66 0.085,1c-0,0.34 -0.029,0.674 -0.085,1l-2.043,0c0.083,-0.32 0.128,-0.655 0.128,-1c0,-0.345 -0.045,-0.68 -0.128,-1l2.043,-0Zm-9.787,0c-0.083,0.32 -0.128,0.655 -0.128,1c0,0.345 0.045,0.68 0.128,1l-2.043,-0c-0.056,-0.326 -0.085,-0.66 -0.085,-1c0,-0.34 0.029,-0.674 0.085,-1l2.043,0Z" style="fill:#70ffb9;fill-rule:nonzero;"/><path d="M4.128,9c0.205,0.784 0.645,1.478 1.238,2l-2.553,0c-0.355,-0.608 -0.606,-1.283 -0.728,-2l2.043,0Zm9.787,0c-0.122,0.717 -0.373,1.392 -0.728,2l-2.553,0c0.593,-0.522 1.033,-1.216 1.238,-2l2.043,0Z" style="fill:#70deff;fill-rule:nonzero;"/><path d="M11.299,13l-6.598,0c0.949,0.631 2.084,1 3.299,1c1.215,0 2.35,-0.369 3.299,-1Z" style="fill:#ff70ac;fill-rule:nonzero;"/><path d="M13.187,11c-0.468,0.801 -1.116,1.487 -1.888,2l-6.598,0c-0.772,-0.513 -1.42,-1.199 -1.888,-2l2.553,0c0.706,0.621 1.629,1 2.634,1c1.005,0 1.928,-0.379 2.634,-1l2.553,0Z" style="fill:#9f70ff;fill-rule:nonzero;"/><path d="M4.701,3l6.598,0c-0.949,-0.631 -2.084,-1 -3.299,-1c-1.215,0 -2.35,0.369 -3.299,1Z" style="fill:#ff7070;fill-rule:nonzero;"/></svg> +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill-rule="nonzero"><path d="m11.299 3c.772.513 1.42 1.199 1.888 2h-2.553c-.706-.621-1.629-1-2.634-1s-1.928.379-2.634 1h-2.553c.468-.801 1.116-1.487 1.888-2z" fill="#ffeb70"/><path d="m5.366 5c-.593.522-1.033 1.216-1.238 2h-2.043c.122-.717.373-1.392.728-2zm7.821 0c.355.608.606 1.283.728 2h-2.043c-.205-.784-.645-1.478-1.238-2z" fill="#9dff70"/><path d="m13.915 7c.056.326.085.66.085 1s-.029.674-.085 1h-2.043c.083-.32.128-.655.128-1s-.045-.68-.128-1zm-9.787 0c-.083.32-.128.655-.128 1s.045.68.128 1h-2.043c-.056-.326-.085-.66-.085-1s.029-.674.085-1z" fill="#70ffb9"/><path d="m4.128 9c.205.784.645 1.478 1.238 2h-2.553c-.355-.608-.606-1.283-.728-2zm9.787 0c-.122.717-.373 1.392-.728 2h-2.553c.593-.522 1.033-1.216 1.238-2z" fill="#70deff"/><path d="m11.299 13h-6.598c.949.631 2.084 1 3.299 1s2.35-.369 3.299-1z" fill="#ff70ac"/><path d="m13.187 11c-.468.801-1.116 1.487-1.888 2h-6.598c-.772-.513-1.42-1.199-1.888-2h2.553c.706.621 1.629 1 2.634 1s1.928-.379 2.634-1z" fill="#9f70ff"/><path d="m4.701 3h6.598c-.949-.631-2.084-1-3.299-1s-2.35.369-3.299 1z" fill="#ff7070"/></g></svg> diff --git a/editor/icons/ThemeSelectAll.svg b/editor/icons/ThemeSelectAll.svg new file mode 100644 index 0000000000..59d9fb3387 --- /dev/null +++ b/editor/icons/ThemeSelectAll.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m5.952 6.976h8.049v2.005h-8.049z" fill="#e0e0e0" fill-rule="nonzero"/><path d="m.989 5.995h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m.989 5.995h4.011v4.01h-4.011zm.968.968h2.075v2.074h-2.075z" fill="#e0e0e0"/><path d="m5.952 1.956h8.049v2.005h-8.049z" fill="#e0e0e0" fill-rule="nonzero"/><path d="m.989.974h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m.989.974h4.011v4.011h-4.011zm.968.968h2.075v2.075h-2.075z" fill="#e0e0e0"/><path d="m5.952 11.996h8.049v2.005h-8.049z" fill="#e0e0e0" fill-rule="nonzero"/><path d="m.989 11.015h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m.989 11.015h4.011v4.011h-4.011zm.968.968h2.075v2.075h-2.075z" fill="#e0e0e0"/></svg> diff --git a/editor/icons/ThemeSelectFull.svg b/editor/icons/ThemeSelectFull.svg new file mode 100644 index 0000000000..0fabb9961a --- /dev/null +++ b/editor/icons/ThemeSelectFull.svg @@ -0,0 +1 @@ +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m11 6.976h3.015v2.005h-3.015z" fill="#e0e0e0" fill-rule="nonzero"/><path d="m.989 5.995h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m.989 5.995h4.011v4.01h-4.011zm.968.968h2.075v2.074h-2.075z" fill="#e0e0e0"/><path d="m11 1.956h3.015v2.005h-3.015z" fill="#e0e0e0" fill-rule="nonzero"/><path d="m.989.974h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m.989.974h4.011v4.011h-4.011zm.968.968h2.075v2.075h-2.075z" fill="#e0e0e0"/><path d="m11 11.996h3.015v2.005h-3.015z" fill="#e0e0e0" fill-rule="nonzero"/><path d="m.989 11.015h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m.989 11.015h4.011v4.011h-4.011zm.968.968h2.075v2.075h-2.075z" fill="#e0e0e0"/><path d="m5.995 5.995h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m5.995 5.995h4.01v4.01h-4.01zm.968.968h2.074v2.074h-2.074z" fill="#e0e0e0"/><path d="m5.995.974h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m5.995.974h4.01v4.011h-4.01zm.968.968h2.074v2.075h-2.074z" fill="#e0e0e0"/><path d="m5.995 11.015h4.011v4.011h-4.011z" fill="#fff" fill-rule="nonzero"/><path d="m5.995 11.015h4.01v4.011h-4.01zm.968.968h2.074v2.075h-2.074z" fill="#e0e0e0"/></svg> diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index adfeead33b..8c4c5a3461 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -703,7 +703,7 @@ void ScriptEditor::_close_tab(int p_idx, bool p_save, bool p_history_back) { // Do not try to save internal scripts, but prompt to save in-memory // scripts which are not saved to disk yet (have empty path). if (script->get_path().find("local://") == -1 && script->get_path().find("::") == -1) { - _save_current_script(); + save_current_script(); } } if (script.is_valid()) { @@ -1101,59 +1101,6 @@ bool ScriptEditor::is_scripts_panel_toggled() { return list_split->is_visible(); } -void ScriptEditor::_save_current_script() { - ScriptEditorBase *current = _get_current_editor(); - - if (_test_script_times_on_disk()) { - return; - } - - if (trim_trailing_whitespace_on_save) { - current->trim_trailing_whitespace(); - } - - current->insert_final_newline(); - - if (convert_indent_on_save) { - if (use_space_indentation) { - current->convert_indent_to_spaces(); - } else { - current->convert_indent_to_tabs(); - } - } - - RES resource = current->get_edited_resource(); - Ref<TextFile> text_file = resource; - Ref<Script> script = resource; - - if (text_file != nullptr) { - current->apply_code(); - _save_text_file(text_file, text_file->get_path()); - return; - } - - if (script != nullptr) { - const Vector<DocData::ClassDoc> &documentations = script->get_documentation(); - for (int j = 0; j < documentations.size(); j++) { - const DocData::ClassDoc &doc = documentations.get(j); - if (EditorHelp::get_doc_data()->has_doc(doc.name)) { - EditorHelp::get_doc_data()->remove_doc(doc.name); - } - } - } - - editor->save_resource(resource); - - if (script != nullptr) { - const Vector<DocData::ClassDoc> &documentations = script->get_documentation(); - for (int j = 0; j < documentations.size(); j++) { - const DocData::ClassDoc &doc = documentations.get(j); - EditorHelp::get_doc_data()->add_doc(doc); - update_doc(doc.name); - } - } -} - void ScriptEditor::_menu_option(int p_option) { ScriptEditorBase *current = _get_current_editor(); switch (p_option) { @@ -1282,7 +1229,7 @@ void ScriptEditor::_menu_option(int p_option) { if (current) { switch (p_option) { case FILE_SAVE: { - _save_current_script(); + save_current_script(); } break; case FILE_SAVE_AS: { if (trim_trailing_whitespace_on_save) { @@ -2330,6 +2277,59 @@ bool ScriptEditor::edit(const RES &p_resource, int p_line, int p_col, bool p_gra return true; } +void ScriptEditor::save_current_script() { + ScriptEditorBase *current = _get_current_editor(); + + if (_test_script_times_on_disk()) { + return; + } + + if (trim_trailing_whitespace_on_save) { + current->trim_trailing_whitespace(); + } + + current->insert_final_newline(); + + if (convert_indent_on_save) { + if (use_space_indentation) { + current->convert_indent_to_spaces(); + } else { + current->convert_indent_to_tabs(); + } + } + + RES resource = current->get_edited_resource(); + Ref<TextFile> text_file = resource; + Ref<Script> script = resource; + + if (text_file != nullptr) { + current->apply_code(); + _save_text_file(text_file, text_file->get_path()); + return; + } + + if (script != nullptr) { + const Vector<DocData::ClassDoc> &documentations = script->get_documentation(); + for (int j = 0; j < documentations.size(); j++) { + const DocData::ClassDoc &doc = documentations.get(j); + if (EditorHelp::get_doc_data()->has_doc(doc.name)) { + EditorHelp::get_doc_data()->remove_doc(doc.name); + } + } + } + + editor->save_resource(resource); + + if (script != nullptr) { + const Vector<DocData::ClassDoc> &documentations = script->get_documentation(); + for (int j = 0; j < documentations.size(); j++) { + const DocData::ClassDoc &doc = documentations.get(j); + EditorHelp::get_doc_data()->add_doc(doc); + update_doc(doc.name); + } + } +} + void ScriptEditor::save_all_scripts() { for (int i = 0; i < tab_container->get_child_count(); i++) { ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(tab_container->get_child(i)); @@ -2445,7 +2445,7 @@ void ScriptEditor::_add_callback(Object *p_obj, const String &p_function, const script_list->select(script_list->find_metadata(i)); // Save the current script so the changes can be picked up by an external editor. - _save_current_script(); + save_current_script(); break; } diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index c70fd2e555..570ebfba4e 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -312,7 +312,6 @@ class ScriptEditor : public PanelContainer { String _get_debug_tooltip(const String &p_text, Node *_se); - void _save_current_script(); void _resave_scripts(const String &p_str); void _reload_scripts(); @@ -464,6 +463,7 @@ public: void get_breakpoints(List<String> *p_breakpoints); + void save_current_script(); void save_all_scripts(); void set_window_layout(Ref<ConfigFile> p_layout); diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index c765aa0319..36c1bf3a09 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -34,12 +34,1187 @@ #include "core/os/keyboard.h" #include "core/version.h" #include "editor/editor_scale.h" +#include "editor/progress_dialog.h" #include "scene/gui/progress_bar.h" +void ThemeItemImportTree::_update_items_tree() { + import_items_tree->clear(); + TreeItem *root = import_items_tree->create_item(); + + if (base_theme.is_null()) { + return; + } + + String filter_text = import_items_filter->get_text(); + + List<StringName> types; + List<StringName> names; + List<StringName> filtered_names; + base_theme->get_type_list(&types); + types.sort_custom<StringName::AlphCompare>(); + + int color_amount = 0; + int constant_amount = 0; + int font_amount = 0; + int font_size_amount = 0; + int icon_amount = 0; + int stylebox_amount = 0; + + tree_color_items.clear(); + tree_constant_items.clear(); + tree_font_items.clear(); + tree_font_size_items.clear(); + tree_icon_items.clear(); + tree_stylebox_items.clear(); + + for (List<StringName>::Element *E = types.front(); E; E = E->next()) { + String type_name = (String)E->get(); + + TreeItem *type_node = import_items_tree->create_item(root); + type_node->set_meta("_can_be_imported", false); + type_node->set_collapsed(true); + type_node->set_text(0, type_name); + type_node->set_cell_mode(IMPORT_ITEM, TreeItem::CELL_MODE_CHECK); + type_node->set_checked(IMPORT_ITEM, false); + type_node->set_editable(IMPORT_ITEM, true); + type_node->set_cell_mode(IMPORT_ITEM_DATA, TreeItem::CELL_MODE_CHECK); + type_node->set_checked(IMPORT_ITEM_DATA, false); + type_node->set_editable(IMPORT_ITEM_DATA, true); + + bool is_matching_filter = (filter_text.is_empty() || type_name.findn(filter_text) > -1); + bool has_filtered_items = false; + bool any_checked = false; + bool any_checked_with_data = false; + + for (int i = 0; i < Theme::DATA_TYPE_MAX; i++) { + Theme::DataType dt = (Theme::DataType)i; + + names.clear(); + filtered_names.clear(); + base_theme->get_theme_item_list(dt, E->get(), &names); + + bool data_type_has_filtered_items = false; + + for (List<StringName>::Element *F = names.front(); F; F = F->next()) { + String item_name = (String)F->get(); + bool is_item_matching_filter = (item_name.findn(filter_text) > -1); + if (!filter_text.is_empty() && !is_matching_filter && !is_item_matching_filter) { + continue; + } + + // Only mark this if actual items match the filter and not just the type group. + if (!filter_text.is_empty() && is_item_matching_filter) { + has_filtered_items = true; + data_type_has_filtered_items = true; + } + filtered_names.push_back(F->get()); + } + + if (filtered_names.size() == 0) { + continue; + } + + TreeItem *data_type_node = import_items_tree->create_item(type_node); + data_type_node->set_meta("_can_be_imported", false); + data_type_node->set_metadata(0, i); + data_type_node->set_collapsed(!data_type_has_filtered_items); + data_type_node->set_cell_mode(IMPORT_ITEM, TreeItem::CELL_MODE_CHECK); + data_type_node->set_checked(IMPORT_ITEM, false); + data_type_node->set_editable(IMPORT_ITEM, true); + data_type_node->set_cell_mode(IMPORT_ITEM_DATA, TreeItem::CELL_MODE_CHECK); + data_type_node->set_checked(IMPORT_ITEM_DATA, false); + data_type_node->set_editable(IMPORT_ITEM_DATA, true); + + List<TreeItem *> *item_list; + + switch (dt) { + case Theme::DATA_TYPE_COLOR: + data_type_node->set_icon(0, get_theme_icon("Color", "EditorIcons")); + data_type_node->set_text(0, TTR("Colors")); + + item_list = &tree_color_items; + color_amount += filtered_names.size(); + break; + + case Theme::DATA_TYPE_CONSTANT: + data_type_node->set_icon(0, get_theme_icon("MemberConstant", "EditorIcons")); + data_type_node->set_text(0, TTR("Constants")); + + item_list = &tree_constant_items; + constant_amount += filtered_names.size(); + break; + + case Theme::DATA_TYPE_FONT: + data_type_node->set_icon(0, get_theme_icon("Font", "EditorIcons")); + data_type_node->set_text(0, TTR("Fonts")); + + item_list = &tree_font_items; + font_amount += filtered_names.size(); + break; + + case Theme::DATA_TYPE_FONT_SIZE: + data_type_node->set_icon(0, get_theme_icon("FontSize", "EditorIcons")); + data_type_node->set_text(0, TTR("Font Sizes")); + + item_list = &tree_font_size_items; + font_size_amount += filtered_names.size(); + break; + + case Theme::DATA_TYPE_ICON: + data_type_node->set_icon(0, get_theme_icon("ImageTexture", "EditorIcons")); + data_type_node->set_text(0, TTR("Icons")); + + item_list = &tree_icon_items; + icon_amount += filtered_names.size(); + break; + + case Theme::DATA_TYPE_STYLEBOX: + data_type_node->set_icon(0, get_theme_icon("StyleBoxFlat", "EditorIcons")); + data_type_node->set_text(0, TTR("Styleboxes")); + + item_list = &tree_stylebox_items; + stylebox_amount += filtered_names.size(); + break; + + case Theme::DATA_TYPE_MAX: + break; // Can't happen, but silences warning. + } + + bool data_type_any_checked = false; + bool data_type_any_checked_with_data = false; + + filtered_names.sort_custom<StringName::AlphCompare>(); + for (List<StringName>::Element *F = filtered_names.front(); F; F = F->next()) { + TreeItem *item_node = import_items_tree->create_item(data_type_node); + item_node->set_meta("_can_be_imported", true); + item_node->set_text(0, F->get()); + item_node->set_cell_mode(IMPORT_ITEM, TreeItem::CELL_MODE_CHECK); + item_node->set_checked(IMPORT_ITEM, false); + item_node->set_editable(IMPORT_ITEM, true); + item_node->set_cell_mode(IMPORT_ITEM_DATA, TreeItem::CELL_MODE_CHECK); + item_node->set_checked(IMPORT_ITEM_DATA, false); + item_node->set_editable(IMPORT_ITEM_DATA, true); + + _restore_selected_item(item_node); + if (item_node->is_checked(IMPORT_ITEM)) { + data_type_any_checked = true; + any_checked = true; + } + if (item_node->is_checked(IMPORT_ITEM_DATA)) { + data_type_any_checked_with_data = true; + any_checked_with_data = true; + } + + item_list->push_back(item_node); + } + + data_type_node->set_checked(IMPORT_ITEM, data_type_any_checked); + data_type_node->set_checked(IMPORT_ITEM_DATA, data_type_any_checked && data_type_any_checked_with_data); + } + + // Remove the item if it doesn't match the filter in any way. + if (!is_matching_filter && !has_filtered_items) { + root->remove_child(type_node); + memdelete(type_node); + continue; + } + + // Show one level inside of a type group if there are matches in items. + if (!filter_text.is_empty() && has_filtered_items) { + type_node->set_collapsed(false); + } + + type_node->set_checked(IMPORT_ITEM, any_checked); + type_node->set_checked(IMPORT_ITEM_DATA, any_checked && any_checked_with_data); + } + + if (color_amount > 0) { + Array arr; + arr.push_back(color_amount); + select_colors_label->set_text(TTRN("One color", "{num} colors", color_amount).format(arr, "{num}")); + select_all_colors_button->set_visible(true); + select_full_colors_button->set_visible(true); + deselect_all_colors_button->set_visible(true); + } else { + select_colors_label->set_text(TTR("No colors found.")); + select_all_colors_button->set_visible(false); + select_full_colors_button->set_visible(false); + deselect_all_colors_button->set_visible(false); + } + + if (constant_amount > 0) { + Array arr; + arr.push_back(constant_amount); + select_constants_label->set_text(TTRN("One constant", "{num} constants", constant_amount).format(arr, "{num}")); + select_all_constants_button->set_visible(true); + select_full_constants_button->set_visible(true); + deselect_all_constants_button->set_visible(true); + } else { + select_constants_label->set_text(TTR("No constants found.")); + select_all_constants_button->set_visible(false); + select_full_constants_button->set_visible(false); + deselect_all_constants_button->set_visible(false); + } + + if (font_amount > 0) { + Array arr; + arr.push_back(font_amount); + select_fonts_label->set_text(TTRN("One font", "{num} fonts", font_amount).format(arr, "{num}")); + select_all_fonts_button->set_visible(true); + select_full_fonts_button->set_visible(true); + deselect_all_fonts_button->set_visible(true); + } else { + select_fonts_label->set_text(TTR("No fonts found.")); + select_all_fonts_button->set_visible(false); + select_full_fonts_button->set_visible(false); + deselect_all_fonts_button->set_visible(false); + } + + if (font_size_amount > 0) { + Array arr; + arr.push_back(font_size_amount); + select_font_sizes_label->set_text(TTRN("One font size", "{num} font sizes", font_size_amount).format(arr, "{num}")); + select_all_font_sizes_button->set_visible(true); + select_full_font_sizes_button->set_visible(true); + deselect_all_font_sizes_button->set_visible(true); + } else { + select_font_sizes_label->set_text(TTR("No font sizes found.")); + select_all_font_sizes_button->set_visible(false); + select_full_font_sizes_button->set_visible(false); + deselect_all_font_sizes_button->set_visible(false); + } + + if (icon_amount > 0) { + Array arr; + arr.push_back(icon_amount); + select_icons_label->set_text(TTRN("One icon", "{num} icons", icon_amount).format(arr, "{num}")); + select_all_icons_button->set_visible(true); + select_full_icons_button->set_visible(true); + deselect_all_icons_button->set_visible(true); + select_icons_warning_hb->set_visible(true); + } else { + select_icons_label->set_text(TTR("No icons found.")); + select_all_icons_button->set_visible(false); + select_full_icons_button->set_visible(false); + deselect_all_icons_button->set_visible(false); + select_icons_warning_hb->set_visible(false); + } + + if (stylebox_amount > 0) { + Array arr; + arr.push_back(stylebox_amount); + select_styleboxes_label->set_text(TTRN("One stylebox", "{num} styleboxes", stylebox_amount).format(arr, "{num}")); + select_all_styleboxes_button->set_visible(true); + select_full_styleboxes_button->set_visible(true); + deselect_all_styleboxes_button->set_visible(true); + } else { + select_styleboxes_label->set_text(TTR("No styleboxes found.")); + select_all_styleboxes_button->set_visible(false); + select_full_styleboxes_button->set_visible(false); + deselect_all_styleboxes_button->set_visible(false); + } +} + +void ThemeItemImportTree::_toggle_type_items(bool p_collapse) { + TreeItem *root = import_items_tree->get_root(); + if (!root) { + return; + } + + TreeItem *type_node = root->get_children(); + while (type_node) { + type_node->set_collapsed(p_collapse); + type_node = type_node->get_next(); + } +} + +void ThemeItemImportTree::_filter_text_changed(const String &p_value) { + _update_items_tree(); +} + +void ThemeItemImportTree::_store_selected_item(TreeItem *p_tree_item) { + if (!p_tree_item->get_meta("_can_be_imported")) { + return; + } + + TreeItem *data_type_node = p_tree_item->get_parent(); + if (!data_type_node || data_type_node == import_items_tree->get_root()) { + return; + } + + TreeItem *type_node = data_type_node->get_parent(); + if (!type_node || type_node == import_items_tree->get_root()) { + return; + } + + ThemeItem ti; + ti.item_name = p_tree_item->get_text(0); + ti.data_type = (Theme::DataType)(int)data_type_node->get_metadata(0); + ti.type_name = type_node->get_text(0); + + bool import = p_tree_item->is_checked(IMPORT_ITEM); + bool with_data = p_tree_item->is_checked(IMPORT_ITEM_DATA); + + if (import && with_data) { + selected_items[ti] = SELECT_IMPORT_FULL; + } else if (import) { + selected_items[ti] = SELECT_IMPORT_DEFINITION; + } else { + selected_items.erase(ti); + } + + _update_total_selected(ti.data_type); +} + +void ThemeItemImportTree::_restore_selected_item(TreeItem *p_tree_item) { + if (!p_tree_item->get_meta("_can_be_imported")) { + return; + } + + TreeItem *data_type_node = p_tree_item->get_parent(); + if (!data_type_node || data_type_node == import_items_tree->get_root()) { + return; + } + + TreeItem *type_node = data_type_node->get_parent(); + if (!type_node || type_node == import_items_tree->get_root()) { + return; + } + + ThemeItem ti; + ti.item_name = p_tree_item->get_text(0); + ti.data_type = (Theme::DataType)(int)data_type_node->get_metadata(0); + ti.type_name = type_node->get_text(0); + + if (!selected_items.has(ti)) { + p_tree_item->set_checked(IMPORT_ITEM, false); + p_tree_item->set_checked(IMPORT_ITEM_DATA, false); + return; + } + + if (selected_items[ti] == SELECT_IMPORT_FULL) { + p_tree_item->set_checked(IMPORT_ITEM, true); + p_tree_item->set_checked(IMPORT_ITEM_DATA, true); + } else if (selected_items[ti] == SELECT_IMPORT_DEFINITION) { + p_tree_item->set_checked(IMPORT_ITEM, true); + p_tree_item->set_checked(IMPORT_ITEM_DATA, false); + } +} + +void ThemeItemImportTree::_update_total_selected(Theme::DataType p_data_type) { + ERR_FAIL_INDEX_MSG(p_data_type, Theme::DATA_TYPE_MAX, "Theme item data type is out of bounds."); + + Label *total_selected_items_label; + switch (p_data_type) { + case Theme::DATA_TYPE_COLOR: + total_selected_items_label = total_selected_colors_label; + break; + + case Theme::DATA_TYPE_CONSTANT: + total_selected_items_label = total_selected_constants_label; + break; + + case Theme::DATA_TYPE_FONT: + total_selected_items_label = total_selected_fonts_label; + break; + + case Theme::DATA_TYPE_FONT_SIZE: + total_selected_items_label = total_selected_font_sizes_label; + break; + + case Theme::DATA_TYPE_ICON: + total_selected_items_label = total_selected_icons_label; + break; + + case Theme::DATA_TYPE_STYLEBOX: + total_selected_items_label = total_selected_styleboxes_label; + break; + + case Theme::DATA_TYPE_MAX: + return; // Can't happen, but silences warning. + } + + if (!total_selected_items_label) { + return; + } + + int count = 0; + for (Map<ThemeItem, ItemCheckedState>::Element *E = selected_items.front(); E; E = E->next()) { + ThemeItem ti = E->key(); + if (ti.data_type == p_data_type) { + count++; + } + } + + if (count == 0) { + total_selected_items_label->hide(); + } else { + Array arr; + arr.push_back(count); + total_selected_items_label->set_text(TTRN("{num} currently selected", "{num} currently selected", count).format(arr, "{num}")); + total_selected_items_label->show(); + } +} + +void ThemeItemImportTree::_tree_item_edited() { + if (updating_tree) { + return; + } + + TreeItem *edited_item = import_items_tree->get_edited(); + if (!edited_item) { + return; + } + + updating_tree = true; + + int edited_column = import_items_tree->get_edited_column(); + bool is_checked = edited_item->is_checked(edited_column); + if (is_checked) { + if (edited_column == IMPORT_ITEM_DATA) { + edited_item->set_checked(IMPORT_ITEM, true); + } + + _select_all_subitems(edited_item, (edited_column == IMPORT_ITEM_DATA)); + } else { + if (edited_column == IMPORT_ITEM) { + edited_item->set_checked(IMPORT_ITEM_DATA, false); + } + + _deselect_all_subitems(edited_item, (edited_column == IMPORT_ITEM)); + } + + _update_parent_items(edited_item); + _store_selected_item(edited_item); + + updating_tree = false; +} + +void ThemeItemImportTree::_select_all_subitems(TreeItem *p_root_item, bool p_select_with_data) { + TreeItem *child_item = p_root_item->get_children(); + while (child_item) { + child_item->set_checked(IMPORT_ITEM, true); + if (p_select_with_data) { + child_item->set_checked(IMPORT_ITEM_DATA, true); + } + _store_selected_item(child_item); + + _select_all_subitems(child_item, p_select_with_data); + child_item = child_item->get_next(); + } +} + +void ThemeItemImportTree::_deselect_all_subitems(TreeItem *p_root_item, bool p_deselect_completely) { + TreeItem *child_item = p_root_item->get_children(); + while (child_item) { + child_item->set_checked(IMPORT_ITEM_DATA, false); + if (p_deselect_completely) { + child_item->set_checked(IMPORT_ITEM, false); + } + _store_selected_item(child_item); + + _deselect_all_subitems(child_item, p_deselect_completely); + child_item = child_item->get_next(); + } +} + +void ThemeItemImportTree::_update_parent_items(TreeItem *p_root_item) { + TreeItem *parent_item = p_root_item->get_parent(); + if (!parent_item) { + return; + } + + bool any_checked = false; + bool any_checked_with_data = false; + + TreeItem *child_item = parent_item->get_children(); + while (child_item) { + if (child_item->is_checked(IMPORT_ITEM)) { + any_checked = true; + } + if (child_item->is_checked(IMPORT_ITEM_DATA)) { + any_checked_with_data = true; + } + + child_item = child_item->get_next(); + } + + parent_item->set_checked(IMPORT_ITEM, any_checked); + parent_item->set_checked(IMPORT_ITEM_DATA, any_checked && any_checked_with_data); + _update_parent_items(parent_item); +} + +void ThemeItemImportTree::_select_all_items_pressed() { + if (updating_tree) { + return; + } + + updating_tree = true; + + TreeItem *root = import_items_tree->get_root(); + _select_all_subitems(root, false); + + updating_tree = false; +} + +void ThemeItemImportTree::_select_full_items_pressed() { + if (updating_tree) { + return; + } + + updating_tree = true; + + TreeItem *root = import_items_tree->get_root(); + _select_all_subitems(root, true); + + updating_tree = false; +} + +void ThemeItemImportTree::_deselect_all_items_pressed() { + if (updating_tree) { + return; + } + + updating_tree = true; + + TreeItem *root = import_items_tree->get_root(); + _deselect_all_subitems(root, true); + + updating_tree = false; +} + +void ThemeItemImportTree::_select_all_data_type_pressed(int p_data_type) { + ERR_FAIL_INDEX_MSG(p_data_type, Theme::DATA_TYPE_MAX, "Theme item data type is out of bounds."); + + if (updating_tree) { + return; + } + + Theme::DataType data_type = (Theme::DataType)p_data_type; + List<TreeItem *> *item_list; + + switch (data_type) { + case Theme::DATA_TYPE_COLOR: + item_list = &tree_color_items; + break; + + case Theme::DATA_TYPE_CONSTANT: + item_list = &tree_constant_items; + break; + + case Theme::DATA_TYPE_FONT: + item_list = &tree_font_items; + break; + + case Theme::DATA_TYPE_FONT_SIZE: + item_list = &tree_font_size_items; + break; + + case Theme::DATA_TYPE_ICON: + item_list = &tree_icon_items; + break; + + case Theme::DATA_TYPE_STYLEBOX: + item_list = &tree_stylebox_items; + break; + + case Theme::DATA_TYPE_MAX: + return; // Can't happen, but silences warning. + } + + updating_tree = true; + + for (List<TreeItem *>::Element *E = item_list->front(); E; E = E->next()) { + TreeItem *child_item = E->get(); + if (!child_item) { + continue; + } + + child_item->set_checked(IMPORT_ITEM, true); + _update_parent_items(child_item); + _store_selected_item(child_item); + } + + updating_tree = false; +} + +void ThemeItemImportTree::_select_full_data_type_pressed(int p_data_type) { + ERR_FAIL_INDEX_MSG(p_data_type, Theme::DATA_TYPE_MAX, "Theme item data type is out of bounds."); + + if (updating_tree) { + return; + } + + Theme::DataType data_type = (Theme::DataType)p_data_type; + List<TreeItem *> *item_list; + + switch (data_type) { + case Theme::DATA_TYPE_COLOR: + item_list = &tree_color_items; + break; + + case Theme::DATA_TYPE_CONSTANT: + item_list = &tree_constant_items; + break; + + case Theme::DATA_TYPE_FONT: + item_list = &tree_font_items; + break; + + case Theme::DATA_TYPE_FONT_SIZE: + item_list = &tree_font_size_items; + break; + + case Theme::DATA_TYPE_ICON: + item_list = &tree_icon_items; + break; + + case Theme::DATA_TYPE_STYLEBOX: + item_list = &tree_stylebox_items; + break; + + case Theme::DATA_TYPE_MAX: + return; // Can't happen, but silences warning. + } + + updating_tree = true; + + for (List<TreeItem *>::Element *E = item_list->front(); E; E = E->next()) { + TreeItem *child_item = E->get(); + if (!child_item) { + continue; + } + + child_item->set_checked(IMPORT_ITEM, true); + child_item->set_checked(IMPORT_ITEM_DATA, true); + _update_parent_items(child_item); + _store_selected_item(child_item); + } + + updating_tree = false; +} + +void ThemeItemImportTree::_deselect_all_data_type_pressed(int p_data_type) { + ERR_FAIL_INDEX_MSG(p_data_type, Theme::DATA_TYPE_MAX, "Theme item data type is out of bounds."); + + if (updating_tree) { + return; + } + + Theme::DataType data_type = (Theme::DataType)p_data_type; + List<TreeItem *> *item_list; + + switch (data_type) { + case Theme::DATA_TYPE_COLOR: + item_list = &tree_color_items; + break; + + case Theme::DATA_TYPE_CONSTANT: + item_list = &tree_constant_items; + break; + + case Theme::DATA_TYPE_FONT: + item_list = &tree_font_items; + break; + + case Theme::DATA_TYPE_FONT_SIZE: + item_list = &tree_font_size_items; + break; + + case Theme::DATA_TYPE_ICON: + item_list = &tree_icon_items; + break; + + case Theme::DATA_TYPE_STYLEBOX: + item_list = &tree_stylebox_items; + break; + + case Theme::DATA_TYPE_MAX: + return; // Can't happen, but silences warning. + } + + updating_tree = true; + + for (List<TreeItem *>::Element *E = item_list->front(); E; E = E->next()) { + TreeItem *child_item = E->get(); + if (!child_item) { + continue; + } + + child_item->set_checked(IMPORT_ITEM, false); + child_item->set_checked(IMPORT_ITEM_DATA, false); + _update_parent_items(child_item); + _store_selected_item(child_item); + } + + updating_tree = false; +} + +void ThemeItemImportTree::_import_selected() { + if (selected_items.size() == 0) { + EditorNode::get_singleton()->show_accept(TTR("Nothing was selected for the import."), TTR("OK")); + return; + } + + ProgressDialog::get_singleton()->add_task("import_theme_items", TTR("Importing Theme Items"), selected_items.size()); + + int idx = 0; + for (Map<ThemeItem, ItemCheckedState>::Element *E = selected_items.front(); E; E = E->next()) { + // Arbitrary number of items to skip from reporting. + // Reduces the number of UI updates that this causes when copying large themes. + if (idx % 10 == 0) { + Array arr; + arr.push_back(idx + 1); + arr.push_back(selected_items.size()); + ProgressDialog::get_singleton()->task_step("import_theme_items", TTR("Importing items {n}/{n}").format(arr, "{n}"), idx); + } + + ItemCheckedState cs = E->get(); + ThemeItem ti = E->key(); + + if (cs == SELECT_IMPORT_DEFINITION || cs == SELECT_IMPORT_FULL) { + Variant item_value = Variant(); + + if (cs == SELECT_IMPORT_FULL) { + item_value = base_theme->get_theme_item(ti.data_type, ti.item_name, ti.type_name); + } else { + switch (ti.data_type) { + case Theme::DATA_TYPE_COLOR: + item_value = Color(); + break; + + case Theme::DATA_TYPE_CONSTANT: + item_value = 0; + break; + + case Theme::DATA_TYPE_FONT: + item_value = Ref<Font>(); + break; + + case Theme::DATA_TYPE_FONT_SIZE: + item_value = -1; + break; + + case Theme::DATA_TYPE_ICON: + item_value = Ref<Texture2D>(); + break; + + case Theme::DATA_TYPE_STYLEBOX: + item_value = Ref<StyleBox>(); + break; + + case Theme::DATA_TYPE_MAX: + break; // Can't happen, but silences warning. + } + } + + edited_theme->set_theme_item(ti.data_type, ti.item_name, ti.type_name, item_value); + } + + idx++; + } + + ProgressDialog::get_singleton()->end_task("import_theme_items"); + emit_signal("items_imported"); +} + +void ThemeItemImportTree::set_edited_theme(const Ref<Theme> &p_theme) { + edited_theme = p_theme; +} + +void ThemeItemImportTree::set_base_theme(const Ref<Theme> &p_theme) { + base_theme = p_theme; +} + +void ThemeItemImportTree::reset_item_tree() { + import_items_filter->clear(); + selected_items.clear(); + + total_selected_colors_label->hide(); + total_selected_constants_label->hide(); + total_selected_fonts_label->hide(); + total_selected_font_sizes_label->hide(); + total_selected_icons_label->hide(); + total_selected_styleboxes_label->hide(); + + _update_items_tree(); +} + +bool ThemeItemImportTree::has_selected_items() const { + return (selected_items.size() > 0); +} + +void ThemeItemImportTree::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: + case NOTIFICATION_THEME_CHANGED: { + select_icons_warning_icon->set_texture(get_theme_icon("StatusWarning", "EditorIcons")); + select_icons_warning->add_theme_color_override("font_color", get_theme_color("disabled_font_color", "Editor")); + + // Bottom panel buttons. + import_collapse_types_button->set_icon(get_theme_icon("CollapseTree", "EditorIcons")); + import_expand_types_button->set_icon(get_theme_icon("ExpandTree", "EditorIcons")); + + import_select_all_button->set_icon(get_theme_icon("ThemeSelectAll", "EditorIcons")); + import_select_full_button->set_icon(get_theme_icon("ThemeSelectFull", "EditorIcons")); + import_deselect_all_button->set_icon(get_theme_icon("ThemeDeselectAll", "EditorIcons")); + + // Side panel buttons. + select_colors_icon->set_texture(get_theme_icon("Color", "EditorIcons")); + deselect_all_colors_button->set_icon(get_theme_icon("ThemeDeselectAll", "EditorIcons")); + select_all_colors_button->set_icon(get_theme_icon("ThemeSelectAll", "EditorIcons")); + select_full_colors_button->set_icon(get_theme_icon("ThemeSelectFull", "EditorIcons")); + + select_constants_icon->set_texture(get_theme_icon("MemberConstant", "EditorIcons")); + deselect_all_constants_button->set_icon(get_theme_icon("ThemeDeselectAll", "EditorIcons")); + select_all_constants_button->set_icon(get_theme_icon("ThemeSelectAll", "EditorIcons")); + select_full_constants_button->set_icon(get_theme_icon("ThemeSelectFull", "EditorIcons")); + + select_fonts_icon->set_texture(get_theme_icon("Font", "EditorIcons")); + deselect_all_fonts_button->set_icon(get_theme_icon("ThemeDeselectAll", "EditorIcons")); + select_all_fonts_button->set_icon(get_theme_icon("ThemeSelectAll", "EditorIcons")); + select_full_fonts_button->set_icon(get_theme_icon("ThemeSelectFull", "EditorIcons")); + + select_font_sizes_icon->set_texture(get_theme_icon("FontSize", "EditorIcons")); + deselect_all_font_sizes_button->set_icon(get_theme_icon("ThemeDeselectAll", "EditorIcons")); + select_all_font_sizes_button->set_icon(get_theme_icon("ThemeSelectAll", "EditorIcons")); + select_full_font_sizes_button->set_icon(get_theme_icon("ThemeSelectFull", "EditorIcons")); + + select_icons_icon->set_texture(get_theme_icon("ImageTexture", "EditorIcons")); + deselect_all_icons_button->set_icon(get_theme_icon("ThemeDeselectAll", "EditorIcons")); + select_all_icons_button->set_icon(get_theme_icon("ThemeSelectAll", "EditorIcons")); + select_full_icons_button->set_icon(get_theme_icon("ThemeSelectFull", "EditorIcons")); + + select_styleboxes_icon->set_texture(get_theme_icon("StyleBoxFlat", "EditorIcons")); + deselect_all_styleboxes_button->set_icon(get_theme_icon("ThemeDeselectAll", "EditorIcons")); + select_all_styleboxes_button->set_icon(get_theme_icon("ThemeSelectAll", "EditorIcons")); + select_full_styleboxes_button->set_icon(get_theme_icon("ThemeSelectFull", "EditorIcons")); + } break; + } +} + +void ThemeItemImportTree::_bind_methods() { + ADD_SIGNAL(MethodInfo("items_imported")); +} + +ThemeItemImportTree::ThemeItemImportTree() { + HBoxContainer *import_items_filter_hb = memnew(HBoxContainer); + add_child(import_items_filter_hb); + Label *import_items_filter_label = memnew(Label); + import_items_filter_label->set_text(TTR("Filter:")); + import_items_filter_hb->add_child(import_items_filter_label); + import_items_filter = memnew(LineEdit); + import_items_filter->set_clear_button_enabled(true); + import_items_filter->set_h_size_flags(Control::SIZE_EXPAND_FILL); + import_items_filter_hb->add_child(import_items_filter); + import_items_filter->connect("text_changed", callable_mp(this, &ThemeItemImportTree::_filter_text_changed)); + + HBoxContainer *import_main_hb = memnew(HBoxContainer); + import_main_hb->set_v_size_flags(Control::SIZE_EXPAND_FILL); + add_child(import_main_hb); + + import_items_tree = memnew(Tree); + import_items_tree->set_hide_root(true); + import_items_tree->set_h_size_flags(Control::SIZE_EXPAND_FILL); + import_main_hb->add_child(import_items_tree); + import_items_tree->connect("item_edited", callable_mp(this, &ThemeItemImportTree::_tree_item_edited)); + + import_items_tree->set_columns(3); + import_items_tree->set_column_titles_visible(true); + import_items_tree->set_column_title(IMPORT_ITEM, TTR("Import")); + import_items_tree->set_column_title(IMPORT_ITEM_DATA, TTR("With Data")); + 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); + + ScrollContainer *import_bulk_sc = memnew(ScrollContainer); + import_bulk_sc->set_custom_minimum_size(Size2(260.0, 0.0) * EDSCALE); + import_bulk_sc->set_enable_h_scroll(false); + import_main_hb->add_child(import_bulk_sc); + VBoxContainer *import_bulk_vb = memnew(VBoxContainer); + import_bulk_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL); + import_bulk_sc->add_child(import_bulk_vb); + + Label *import_bulk_label = memnew(Label); + import_bulk_label->set_text(TTR("Select by data type:")); + import_bulk_vb->add_child(import_bulk_label); + + select_colors_icon = memnew(TextureRect); + select_colors_label = memnew(Label); + deselect_all_colors_button = memnew(Button); + select_all_colors_button = memnew(Button); + select_full_colors_button = memnew(Button); + total_selected_colors_label = memnew(Label); + + select_constants_icon = memnew(TextureRect); + select_constants_label = memnew(Label); + deselect_all_constants_button = memnew(Button); + select_all_constants_button = memnew(Button); + select_full_constants_button = memnew(Button); + total_selected_constants_label = memnew(Label); + + select_fonts_icon = memnew(TextureRect); + select_fonts_label = memnew(Label); + deselect_all_fonts_button = memnew(Button); + select_all_fonts_button = memnew(Button); + select_full_fonts_button = memnew(Button); + total_selected_fonts_label = memnew(Label); + + select_font_sizes_icon = memnew(TextureRect); + select_font_sizes_label = memnew(Label); + deselect_all_font_sizes_button = memnew(Button); + select_all_font_sizes_button = memnew(Button); + select_full_font_sizes_button = memnew(Button); + total_selected_font_sizes_label = memnew(Label); + + select_icons_icon = memnew(TextureRect); + select_icons_label = memnew(Label); + deselect_all_icons_button = memnew(Button); + select_all_icons_button = memnew(Button); + select_full_icons_button = memnew(Button); + total_selected_icons_label = memnew(Label); + + select_styleboxes_icon = memnew(TextureRect); + select_styleboxes_label = memnew(Label); + deselect_all_styleboxes_button = memnew(Button); + select_all_styleboxes_button = memnew(Button); + select_full_styleboxes_button = memnew(Button); + total_selected_styleboxes_label = memnew(Label); + + for (int i = 0; i < Theme::DATA_TYPE_MAX; i++) { + Theme::DataType dt = (Theme::DataType)i; + + TextureRect *select_items_icon; + Label *select_items_label; + Button *deselect_all_items_button; + Button *select_all_items_button; + Button *select_full_items_button; + Label *total_selected_items_label; + + String items_title = ""; + String select_all_items_tooltip = ""; + String select_full_items_tooltip = ""; + String deselect_all_items_tooltip = ""; + + switch (dt) { + case Theme::DATA_TYPE_COLOR: + select_items_icon = select_colors_icon; + select_items_label = select_colors_label; + deselect_all_items_button = deselect_all_colors_button; + select_all_items_button = select_all_colors_button; + select_full_items_button = select_full_colors_button; + total_selected_items_label = total_selected_colors_label; + + items_title = TTR("Colors"); + select_all_items_tooltip = TTR("Select all visible color items."); + select_full_items_tooltip = TTR("Select all visible color items and their data."); + deselect_all_items_tooltip = TTR("Deselect all visible color items."); + break; + + case Theme::DATA_TYPE_CONSTANT: + select_items_icon = select_constants_icon; + select_items_label = select_constants_label; + deselect_all_items_button = deselect_all_constants_button; + select_all_items_button = select_all_constants_button; + select_full_items_button = select_full_constants_button; + total_selected_items_label = total_selected_constants_label; + + items_title = TTR("Constants"); + select_all_items_tooltip = TTR("Select all visible constant items."); + select_full_items_tooltip = TTR("Select all visible constant items and their data."); + deselect_all_items_tooltip = TTR("Deselect all visible constant items."); + break; + + case Theme::DATA_TYPE_FONT: + select_items_icon = select_fonts_icon; + select_items_label = select_fonts_label; + deselect_all_items_button = deselect_all_fonts_button; + select_all_items_button = select_all_fonts_button; + select_full_items_button = select_full_fonts_button; + total_selected_items_label = total_selected_fonts_label; + + items_title = TTR("Fonts"); + select_all_items_tooltip = TTR("Select all visible font items."); + select_full_items_tooltip = TTR("Select all visible font items and their data."); + deselect_all_items_tooltip = TTR("Deselect all visible font items."); + break; + + case Theme::DATA_TYPE_FONT_SIZE: + select_items_icon = select_font_sizes_icon; + select_items_label = select_font_sizes_label; + deselect_all_items_button = deselect_all_font_sizes_button; + select_all_items_button = select_all_font_sizes_button; + select_full_items_button = select_full_font_sizes_button; + total_selected_items_label = total_selected_font_sizes_label; + + items_title = TTR("Font sizes"); + select_all_items_tooltip = TTR("Select all visible font size items."); + select_full_items_tooltip = TTR("Select all visible font size items and their data."); + deselect_all_items_tooltip = TTR("Deselect all visible font size items."); + break; + + case Theme::DATA_TYPE_ICON: + select_items_icon = select_icons_icon; + select_items_label = select_icons_label; + deselect_all_items_button = deselect_all_icons_button; + select_all_items_button = select_all_icons_button; + select_full_items_button = select_full_icons_button; + total_selected_items_label = total_selected_icons_label; + + items_title = TTR("Icons"); + select_all_items_tooltip = TTR("Select all visible icon items."); + select_full_items_tooltip = TTR("Select all visible icon items and their data."); + deselect_all_items_tooltip = TTR("Deselect all visible icon items."); + break; + + case Theme::DATA_TYPE_STYLEBOX: + select_items_icon = select_styleboxes_icon; + select_items_label = select_styleboxes_label; + deselect_all_items_button = deselect_all_styleboxes_button; + select_all_items_button = select_all_styleboxes_button; + select_full_items_button = select_full_styleboxes_button; + total_selected_items_label = total_selected_styleboxes_label; + + items_title = TTR("Styleboxes"); + select_all_items_tooltip = TTR("Select all visible stylebox items."); + select_full_items_tooltip = TTR("Select all visible stylebox items and their data."); + deselect_all_items_tooltip = TTR("Deselect all visible stylebox items."); + break; + + case Theme::DATA_TYPE_MAX: + continue; // Can't happen, but silences warning. + } + + if (i > 0) { + import_bulk_vb->add_child(memnew(HSeparator)); + } + + HBoxContainer *all_set = memnew(HBoxContainer); + import_bulk_vb->add_child(all_set); + + HBoxContainer *label_set = memnew(HBoxContainer); + label_set->set_h_size_flags(Control::SIZE_EXPAND_FILL); + all_set->add_child(label_set); + select_items_icon->set_v_size_flags(Control::SIZE_SHRINK_CENTER); + label_set->add_child(select_items_icon); + select_items_label->set_h_size_flags(Control::SIZE_EXPAND_FILL); + select_items_label->set_clip_text(true); + select_items_label->set_text(items_title); + label_set->add_child(select_items_label); + + HBoxContainer *button_set = memnew(HBoxContainer); + button_set->set_alignment(BoxContainer::ALIGN_END); + all_set->add_child(button_set); + select_all_items_button->set_flat(true); + select_all_items_button->set_tooltip(select_all_items_tooltip); + button_set->add_child(select_all_items_button); + select_all_items_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_select_all_data_type_pressed), varray(i)); + select_full_items_button->set_flat(true); + select_full_items_button->set_tooltip(select_full_items_tooltip); + button_set->add_child(select_full_items_button); + select_full_items_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_select_full_data_type_pressed), varray(i)); + deselect_all_items_button->set_flat(true); + deselect_all_items_button->set_tooltip(deselect_all_items_tooltip); + button_set->add_child(deselect_all_items_button); + deselect_all_items_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_deselect_all_data_type_pressed), varray(i)); + + total_selected_items_label->set_align(Label::ALIGN_RIGHT); + total_selected_items_label->hide(); + import_bulk_vb->add_child(total_selected_items_label); + + if (dt == Theme::DATA_TYPE_ICON) { + select_icons_warning_hb = memnew(HBoxContainer); + import_bulk_vb->add_child(select_icons_warning_hb); + + select_icons_warning_icon = memnew(TextureRect); + select_icons_warning_icon->set_v_size_flags(Control::SIZE_SHRINK_CENTER); + select_icons_warning_hb->add_child(select_icons_warning_icon); + + select_icons_warning = memnew(Label); + select_icons_warning->set_text(TTR("Caution: Adding icon data may considerably increase the size of your Theme resource.")); + select_icons_warning->set_autowrap(true); + select_icons_warning->set_h_size_flags(Control::SIZE_EXPAND_FILL); + select_icons_warning_hb->add_child(select_icons_warning); + } + } + + add_child(memnew(HSeparator)); + + HBoxContainer *import_buttons = memnew(HBoxContainer); + add_child(import_buttons); + + import_collapse_types_button = memnew(Button); + import_collapse_types_button->set_flat(true); + import_collapse_types_button->set_tooltip(TTR("Collapse types.")); + import_buttons->add_child(import_collapse_types_button); + import_collapse_types_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_toggle_type_items), varray(true)); + import_expand_types_button = memnew(Button); + import_expand_types_button->set_flat(true); + import_expand_types_button->set_tooltip(TTR("Expand types.")); + import_buttons->add_child(import_expand_types_button); + import_expand_types_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_toggle_type_items), varray(false)); + + import_buttons->add_child(memnew(VSeparator)); + + import_select_all_button = memnew(Button); + import_select_all_button->set_flat(true); + import_select_all_button->set_text(TTR("Select All")); + import_select_all_button->set_tooltip(TTR("Select all Theme items.")); + import_buttons->add_child(import_select_all_button); + import_select_all_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_select_all_items_pressed)); + import_select_full_button = memnew(Button); + import_select_full_button->set_flat(true); + import_select_full_button->set_text(TTR("Select With Data")); + import_select_full_button->set_tooltip(TTR("Select all Theme items with item data.")); + import_buttons->add_child(import_select_full_button); + import_select_full_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_select_full_items_pressed)); + import_deselect_all_button = memnew(Button); + import_deselect_all_button->set_flat(true); + import_deselect_all_button->set_text(TTR("Deselect All")); + import_deselect_all_button->set_tooltip(TTR("Deselect all Theme items.")); + import_buttons->add_child(import_deselect_all_button); + import_deselect_all_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_deselect_all_items_pressed)); + + import_buttons->add_spacer(); + + Button *import_add_selected_button = memnew(Button); + import_add_selected_button->set_text(TTR("Import Selected")); + import_buttons->add_child(import_add_selected_button); + import_add_selected_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_import_selected)); +} + +void ThemeItemEditorDialog::ok_pressed() { + if (import_default_theme_items->has_selected_items() || import_editor_theme_items->has_selected_items() || import_other_theme_items->has_selected_items()) { + confirm_closing_dialog->set_text(TTR("Import Items tab has some items selected. Selection will be lost upon closing this window.\nClose anyway?")); + confirm_closing_dialog->popup_centered(Size2i(380, 120) * EDSCALE); + return; + } + + hide(); +} + +void ThemeItemEditorDialog::_close_dialog() { + hide(); +} + void ThemeItemEditorDialog::_dialog_about_to_show() { ERR_FAIL_COND(edited_theme.is_null()); _update_edit_types(); + + import_default_theme_items->set_edited_theme(edited_theme); + import_default_theme_items->set_base_theme(Theme::get_default()); + import_default_theme_items->reset_item_tree(); + + import_editor_theme_items->set_edited_theme(edited_theme); + import_editor_theme_items->set_base_theme(EditorNode::get_singleton()->get_theme_base()->get_theme()); + import_editor_theme_items->reset_item_tree(); + + import_other_theme_items->set_edited_theme(edited_theme); + import_other_theme_items->reset_item_tree(); } void ThemeItemEditorDialog::_update_edit_types() { @@ -79,11 +1254,6 @@ void ThemeItemEditorDialog::_update_edit_types() { base_theme->get_type_list(&default_types); default_types.sort_custom<StringName::AlphCompare>(); - edit_add_class_options->clear(); - for (List<StringName>::Element *E = default_types.front(); E; E = E->next()) { - edit_add_class_options->add_item(E->get()); - } - String selected_type = ""; Vector<int> selected_ids = edit_type_list->get_selected_items(); if (selected_ids.size() > 0) { @@ -127,7 +1297,7 @@ void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) { List<StringName> names; - { + { // Colors. names.clear(); edited_theme->get_color_list(p_item_type, &names); @@ -148,7 +1318,7 @@ void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) { } } - { + { // Constants. names.clear(); edited_theme->get_constant_list(p_item_type, &names); @@ -169,7 +1339,7 @@ void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) { } } - { + { // Fonts. names.clear(); edited_theme->get_font_list(p_item_type, &names); @@ -190,7 +1360,7 @@ void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) { } } - { + { // Font sizes. names.clear(); edited_theme->get_font_size_list(p_item_type, &names); @@ -211,7 +1381,7 @@ void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) { } } - { + { // Icons. names.clear(); edited_theme->get_icon_list(p_item_type, &names); @@ -232,7 +1402,7 @@ void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) { } } - { + { // Styleboxes. names.clear(); edited_theme->get_stylebox_list(p_item_type, &names); @@ -280,64 +1450,13 @@ void ThemeItemEditorDialog::_item_tree_button_pressed(Object *p_item, int p_colu _update_edit_item_tree(edited_item_type); } -void ThemeItemEditorDialog::_add_class_type_items() { - int selected_idx = edit_add_class_options->get_selected(); - String type_name = edit_add_class_options->get_item_text(selected_idx); - List<StringName> names; - - { - names.clear(); - Theme::get_default()->get_icon_list(type_name, &names); - for (List<StringName>::Element *E = names.front(); E; E = E->next()) { - edited_theme->set_icon(E->get(), type_name, Ref<Texture2D>()); - } - } - { - names.clear(); - Theme::get_default()->get_stylebox_list(type_name, &names); - for (List<StringName>::Element *E = names.front(); E; E = E->next()) { - edited_theme->set_stylebox(E->get(), type_name, Ref<StyleBox>()); - } - } - { - names.clear(); - Theme::get_default()->get_font_list(type_name, &names); - for (List<StringName>::Element *E = names.front(); E; E = E->next()) { - edited_theme->set_font(E->get(), type_name, Ref<Font>()); - } - } - { - names.clear(); - Theme::get_default()->get_font_size_list(type_name, &names); - for (List<StringName>::Element *E = names.front(); E; E = E->next()) { - edited_theme->set_font_size(E->get(), type_name, Theme::get_default()->get_font_size(E->get(), type_name)); - } - } - { - names.clear(); - Theme::get_default()->get_color_list(type_name, &names); - for (List<StringName>::Element *E = names.front(); E; E = E->next()) { - edited_theme->set_color(E->get(), type_name, Theme::get_default()->get_color(E->get(), type_name)); - } - } - { - names.clear(); - Theme::get_default()->get_constant_list(type_name, &names); - for (List<StringName>::Element *E = names.front(); E; E = E->next()) { - edited_theme->set_constant(E->get(), type_name, Theme::get_default()->get_constant(E->get(), type_name)); - } - } - - _update_edit_types(); -} - -void ThemeItemEditorDialog::_add_custom_type() { - edited_theme->add_icon_type(edit_add_custom_value->get_text()); - edited_theme->add_stylebox_type(edit_add_custom_value->get_text()); - edited_theme->add_font_type(edit_add_custom_value->get_text()); - edited_theme->add_font_size_type(edit_add_custom_value->get_text()); - edited_theme->add_color_type(edit_add_custom_value->get_text()); - edited_theme->add_constant_type(edit_add_custom_value->get_text()); +void ThemeItemEditorDialog::_add_theme_type() { + edited_theme->add_icon_type(edit_add_type_value->get_text()); + edited_theme->add_stylebox_type(edit_add_type_value->get_text()); + edited_theme->add_font_type(edit_add_type_value->get_text()); + edited_theme->add_font_size_type(edit_add_type_value->get_text()); + edited_theme->add_color_type(edit_add_type_value->get_text()); + edited_theme->add_constant_type(edit_add_type_value->get_text()); _update_edit_types(); } @@ -536,6 +1655,26 @@ void ThemeItemEditorDialog::_edit_theme_item_gui_input(const Ref<InputEvent> &p_ } } +void ThemeItemEditorDialog::_open_select_another_theme() { + import_another_theme_dialog->popup_file_dialog(); +} + +void ThemeItemEditorDialog::_select_another_theme_cbk(const String &p_path) { + Ref<Theme> loaded_theme = ResourceLoader::load(p_path); + if (loaded_theme.is_null()) { + EditorNode::get_singleton()->show_warning(TTR("Invalid file, not a Theme resource.")); + return; + } + if (loaded_theme == edited_theme) { + EditorNode::get_singleton()->show_warning(TTR("Invalid file, same as the edited Theme resource.")); + return; + } + + import_another_theme_value->set_text(p_path); + import_other_theme_items->set_base_theme(loaded_theme); + import_other_theme_items->reset_item_tree(); +} + void ThemeItemEditorDialog::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { @@ -553,6 +1692,8 @@ void ThemeItemEditorDialog::_notification(int p_what) { edit_items_remove_class->set_icon(get_theme_icon("Control", "EditorIcons")); edit_items_remove_custom->set_icon(get_theme_icon("ThemeRemoveCustomItems", "EditorIcons")); edit_items_remove_all->set_icon(get_theme_icon("ThemeRemoveAllItems", "EditorIcons")); + + import_another_theme_button->set_icon(get_theme_icon("Folder", "EditorIcons")); } break; } } @@ -562,10 +1703,18 @@ void ThemeItemEditorDialog::set_edited_theme(const Ref<Theme> &p_theme) { } ThemeItemEditorDialog::ThemeItemEditorDialog() { - set_title(TTR("Edit Theme Items")); + set_title(TTR("Manage Theme Items")); + get_ok_button()->set_text(TTR("Close")); + set_hide_on_ok(false); // Closing may require a confirmation in some cases. + TabContainer *tc = memnew(TabContainer); + tc->set_tab_align(TabContainer::TabAlign::ALIGN_LEFT); + add_child(tc); + + // Edit Items tab. HSplitContainer *edit_dialog_hs = memnew(HSplitContainer); - add_child(edit_dialog_hs); + tc->add_child(edit_dialog_hs); + tc->set_tab_title(0, TTR("Edit Items")); VBoxContainer *edit_dialog_side_vb = memnew(VBoxContainer); edit_dialog_side_vb->set_custom_minimum_size(Size2(200.0, 0.0) * EDSCALE); @@ -580,33 +1729,19 @@ ThemeItemEditorDialog::ThemeItemEditorDialog() { edit_dialog_side_vb->add_child(edit_type_list); edit_type_list->connect("item_selected", callable_mp(this, &ThemeItemEditorDialog::_edited_type_selected)); - Label *edit_add_class_label = memnew(Label); - edit_add_class_label->set_text(TTR("Add Type from Class:")); - edit_dialog_side_vb->add_child(edit_add_class_label); - - HBoxContainer *edit_add_class = memnew(HBoxContainer); - edit_dialog_side_vb->add_child(edit_add_class); - edit_add_class_options = memnew(OptionButton); - edit_add_class_options->set_h_size_flags(Control::SIZE_EXPAND_FILL); - edit_add_class->add_child(edit_add_class_options); - Button *edit_add_class_button = memnew(Button); - edit_add_class_button->set_text(TTR("Add")); - edit_add_class->add_child(edit_add_class_button); - edit_add_class_button->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_add_class_type_items)); - - Label *edit_add_custom_label = memnew(Label); - edit_add_custom_label->set_text(TTR("Add Custom Type:")); - edit_dialog_side_vb->add_child(edit_add_custom_label); - - HBoxContainer *edit_add_custom = memnew(HBoxContainer); - edit_dialog_side_vb->add_child(edit_add_custom); - edit_add_custom_value = memnew(LineEdit); - edit_add_custom_value->set_h_size_flags(Control::SIZE_EXPAND_FILL); - edit_add_custom->add_child(edit_add_custom_value); - Button *edit_add_custom_button = memnew(Button); - edit_add_custom_button->set_text(TTR("Add")); - edit_add_custom->add_child(edit_add_custom_button); - edit_add_custom_button->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_add_custom_type)); + Label *edit_add_type_label = memnew(Label); + edit_add_type_label->set_text(TTR("Add Type:")); + edit_dialog_side_vb->add_child(edit_add_type_label); + + HBoxContainer *edit_add_type_hb = memnew(HBoxContainer); + edit_dialog_side_vb->add_child(edit_add_type_hb); + edit_add_type_value = memnew(LineEdit); + edit_add_type_value->set_h_size_flags(Control::SIZE_EXPAND_FILL); + edit_add_type_hb->add_child(edit_add_type_value); + Button *edit_add_type_button = memnew(Button); + edit_add_type_button->set_text(TTR("Add")); + edit_add_type_hb->add_child(edit_add_type_button); + edit_add_type_button->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_add_theme_type)); VBoxContainer *edit_items_vb = memnew(VBoxContainer); edit_items_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL); @@ -616,7 +1751,7 @@ ThemeItemEditorDialog::ThemeItemEditorDialog() { edit_items_vb->add_child(edit_items_toolbar); Label *edit_items_toolbar_add_label = memnew(Label); - edit_items_toolbar_add_label->set_text(TTR("Add:")); + edit_items_toolbar_add_label->set_text(TTR("Add Item:")); edit_items_toolbar->add_child(edit_items_toolbar_add_label); edit_items_add_color = memnew(Button); @@ -664,7 +1799,7 @@ ThemeItemEditorDialog::ThemeItemEditorDialog() { edit_items_toolbar->add_child(memnew(VSeparator)); Label *edit_items_toolbar_remove_label = memnew(Label); - edit_items_toolbar_remove_label->set_text(TTR("Remove:")); + edit_items_toolbar_remove_label->set_text(TTR("Remove Items:")); edit_items_toolbar->add_child(edit_items_toolbar_remove_label); edit_items_remove_class = memnew(Button); @@ -716,6 +1851,57 @@ ThemeItemEditorDialog::ThemeItemEditorDialog() { edit_theme_item_vb->add_child(theme_item_name); theme_item_name->connect("gui_input", callable_mp(this, &ThemeItemEditorDialog::_edit_theme_item_gui_input)); edit_theme_item_dialog->connect("confirmed", callable_mp(this, &ThemeItemEditorDialog::_confirm_edit_theme_item)); + + // Import Items tab. + TabContainer *import_tc = memnew(TabContainer); + tc->add_child(import_tc); + tc->set_tab_title(1, TTR("Import Items")); + + import_default_theme_items = memnew(ThemeItemImportTree); + import_tc->add_child(import_default_theme_items); + import_tc->set_tab_title(0, TTR("Default Theme")); + import_default_theme_items->connect("items_imported", callable_mp(this, &ThemeItemEditorDialog::_update_edit_types)); + + import_editor_theme_items = memnew(ThemeItemImportTree); + import_tc->add_child(import_editor_theme_items); + import_tc->set_tab_title(1, TTR("Editor Theme")); + import_editor_theme_items->connect("items_imported", callable_mp(this, &ThemeItemEditorDialog::_update_edit_types)); + + VBoxContainer *import_another_theme_vb = memnew(VBoxContainer); + + HBoxContainer *import_another_file_hb = memnew(HBoxContainer); + import_another_theme_vb->add_child(import_another_file_hb); + import_another_theme_value = memnew(LineEdit); + import_another_theme_value->set_h_size_flags(Control::SIZE_EXPAND_FILL); + import_another_theme_value->set_editable(false); + import_another_file_hb->add_child(import_another_theme_value); + import_another_theme_button = memnew(Button); + import_another_file_hb->add_child(import_another_theme_button); + import_another_theme_button->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_select_another_theme)); + + import_another_theme_dialog = memnew(EditorFileDialog); + import_another_theme_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); + import_another_theme_dialog->set_title(TTR("Select Another Theme Resource:")); + List<String> ext; + ResourceLoader::get_recognized_extensions_for_type("Theme", &ext); + for (List<String>::Element *E = ext.front(); E; E = E->next()) { + import_another_theme_dialog->add_filter("*." + E->get() + "; Theme Resource"); + } + import_another_file_hb->add_child(import_another_theme_dialog); + import_another_theme_dialog->connect("file_selected", callable_mp(this, &ThemeItemEditorDialog::_select_another_theme_cbk)); + + import_other_theme_items = memnew(ThemeItemImportTree); + import_other_theme_items->set_v_size_flags(Control::SIZE_EXPAND_FILL); + import_another_theme_vb->add_child(import_other_theme_items); + + import_tc->add_child(import_another_theme_vb); + import_tc->set_tab_title(2, TTR("Another Theme")); + import_other_theme_items->connect("items_imported", callable_mp(this, &ThemeItemEditorDialog::_update_edit_types)); + + confirm_closing_dialog = memnew(ConfirmationDialog); + confirm_closing_dialog->set_autowrap(true); + add_child(confirm_closing_dialog); + confirm_closing_dialog->connect("confirmed", callable_mp(this, &ThemeItemEditorDialog::_close_dialog)); } void ThemeEditor::edit(const Ref<Theme> &p_theme) { @@ -742,299 +1928,8 @@ void ThemeEditor::_refresh_interval() { _propagate_redraw(main_container); } -struct _TECategory { - template <class T> - struct RefItem { - Ref<T> item; - StringName name; - bool operator<(const RefItem<T> &p) const { return item->get_instance_id() < p.item->get_instance_id(); } - }; - - template <class T> - struct Item { - T item; - String name; - bool operator<(const Item<T> &p) const { return name < p.name; } - }; - - Set<RefItem<StyleBox>> stylebox_items; - Set<RefItem<Font>> font_items; - Set<Item<int>> font_size_items; - Set<RefItem<Texture2D>> icon_items; - - Set<Item<Color>> color_items; - Set<Item<int>> constant_items; -}; - -void ThemeEditor::_save_template_cbk(String fname) { - String filename = file_dialog->get_current_path(); - - Map<String, _TECategory> categories; - - // Fill types. - List<StringName> type_list; - Theme::get_default()->get_type_list(&type_list); - for (List<StringName>::Element *E = type_list.front(); E; E = E->next()) { - categories.insert(E->get(), _TECategory()); - } - - // Fill default theme. - for (Map<String, _TECategory>::Element *E = categories.front(); E; E = E->next()) { - _TECategory &tc = E->get(); - - List<StringName> stylebox_list; - Theme::get_default()->get_stylebox_list(E->key(), &stylebox_list); - for (List<StringName>::Element *F = stylebox_list.front(); F; F = F->next()) { - _TECategory::RefItem<StyleBox> it; - it.name = F->get(); - it.item = Theme::get_default()->get_stylebox(F->get(), E->key()); - tc.stylebox_items.insert(it); - } - - List<StringName> font_list; - Theme::get_default()->get_font_list(E->key(), &font_list); - for (List<StringName>::Element *F = font_list.front(); F; F = F->next()) { - _TECategory::RefItem<Font> it; - it.name = F->get(); - it.item = Theme::get_default()->get_font(F->get(), E->key()); - tc.font_items.insert(it); - } - - List<StringName> font_size_list; - Theme::get_default()->get_font_size_list(E->key(), &font_list); - for (List<StringName>::Element *F = font_size_list.front(); F; F = F->next()) { - _TECategory::Item<int> it; - it.name = F->get(); - it.item = Theme::get_default()->get_font_size(F->get(), E->key()); - tc.font_size_items.insert(it); - } - - List<StringName> icon_list; - Theme::get_default()->get_icon_list(E->key(), &icon_list); - for (List<StringName>::Element *F = icon_list.front(); F; F = F->next()) { - _TECategory::RefItem<Texture2D> it; - it.name = F->get(); - it.item = Theme::get_default()->get_icon(F->get(), E->key()); - tc.icon_items.insert(it); - } - - List<StringName> color_list; - Theme::get_default()->get_color_list(E->key(), &color_list); - for (List<StringName>::Element *F = color_list.front(); F; F = F->next()) { - _TECategory::Item<Color> it; - it.name = F->get(); - it.item = Theme::get_default()->get_color(F->get(), E->key()); - tc.color_items.insert(it); - } - - List<StringName> constant_list; - Theme::get_default()->get_constant_list(E->key(), &constant_list); - for (List<StringName>::Element *F = constant_list.front(); F; F = F->next()) { - _TECategory::Item<int> it; - it.name = F->get(); - it.item = Theme::get_default()->get_constant(F->get(), E->key()); - tc.constant_items.insert(it); - } - } - - FileAccess *file = FileAccess::open(filename, FileAccess::WRITE); - - ERR_FAIL_COND_MSG(!file, "Can't save theme to file '" + filename + "'."); - - file->store_line("; ******************* "); - file->store_line("; Template Theme File "); - file->store_line("; ******************* "); - file->store_line("; "); - file->store_line("; Theme Syntax: "); - file->store_line("; ------------- "); - file->store_line("; "); - file->store_line("; Must be placed in section [theme]"); - file->store_line("; "); - file->store_line("; Type.item = [value] "); - file->store_line("; "); - file->store_line("; [value] examples:"); - file->store_line("; "); - file->store_line("; Type.item = 6 ; numeric constant. "); - file->store_line("; Type.item = #FF00FF ; HTML color (magenta)."); - file->store_line("; Type.item = #FF00FF55 ; HTML color (magenta with alpha 0x55)."); - file->store_line("; Type.item = icon(image.png) ; icon in a png file (relative to theme file)."); - file->store_line("; Type.item = font(font.xres) ; font in a resource (relative to theme file)."); - file->store_line("; Type.item = sbox(stylebox.xres) ; stylebox in a resource (relative to theme file)."); - file->store_line("; Type.item = sboxf(2,#FF00FF) ; flat stylebox with margin 2."); - file->store_line("; Type.item = sboxf(2,#FF00FF,#FFFFFF) ; flat stylebox with margin 2 and border."); - file->store_line("; Type.item = sboxf(2,#FF00FF,#FFFFFF,#000000) ; flat stylebox with margin 2, light & dark borders."); - file->store_line("; Type.item = sboxt(base.png,2,2,2,2) ; textured stylebox with 3x3 stretch and stretch margins."); - file->store_line("; -Additionally, 4 extra integers can be added to sboxf and sboxt to specify custom padding of contents:"); - file->store_line("; Type.item = sboxt(base.png,2,2,2,2,5,4,2,4) ;"); - file->store_line("; -Order for all is always left, top, right, bottom."); - file->store_line("; "); - file->store_line("; Special values:"); - file->store_line("; Type.item = default ; use the value in the default theme (must exist there)."); - file->store_line("; Type.item = @somebutton_color ; reference to a library value previously defined."); - file->store_line("; "); - file->store_line("; Library Syntax: "); - file->store_line("; --------------- "); - file->store_line("; "); - file->store_line("; Must be placed in section [library], but usage is optional."); - file->store_line("; "); - file->store_line("; item = [value] ; same as Theme, but assign to library."); - file->store_line("; "); - file->store_line("; examples:"); - file->store_line("; "); - file->store_line("; [library]"); - file->store_line("; "); - file->store_line("; default_button_color = #FF00FF"); - file->store_line("; "); - file->store_line("; [theme]"); - file->store_line("; "); - file->store_line("; Button.color = @default_button_color ; used reference."); - file->store_line("; "); - file->store_line("; ******************* "); - file->store_line("; "); - file->store_line("; Template Generated Using: " + String(VERSION_FULL_BUILD)); - file->store_line("; "); - file->store_line("; "); - file->store_line(""); - file->store_line("[library]"); - file->store_line(""); - file->store_line("; place library stuff here"); - file->store_line(""); - file->store_line("[theme]"); - file->store_line(""); - file->store_line(""); - - // Write default theme. - for (Map<String, _TECategory>::Element *E = categories.front(); E; E = E->next()) { - _TECategory &tc = E->get(); - - String underline = "; "; - for (int i = 0; i < E->key().length(); i++) { - underline += "*"; - } - - file->store_line(""); - file->store_line(underline); - file->store_line("; " + E->key()); - file->store_line(underline); - - if (tc.stylebox_items.size()) { - file->store_line("\n; StyleBox Items:\n"); - } - - for (Set<_TECategory::RefItem<StyleBox>>::Element *F = tc.stylebox_items.front(); F; F = F->next()) { - file->store_line(E->key() + "." + F->get().name + " = default"); - } - - if (tc.font_items.size()) { - file->store_line("\n; Font Items:\n"); - } - - for (Set<_TECategory::RefItem<Font>>::Element *F = tc.font_items.front(); F; F = F->next()) { - file->store_line(E->key() + "." + F->get().name + " = default"); - } - - if (tc.font_size_items.size()) { - file->store_line("\n; Font Size Items:\n"); - } - - for (Set<_TECategory::Item<int>>::Element *F = tc.font_size_items.front(); F; F = F->next()) { - file->store_line(E->key() + "." + F->get().name + " = default"); - } - - if (tc.icon_items.size()) { - file->store_line("\n; Icon Items:\n"); - } - - for (Set<_TECategory::RefItem<Texture2D>>::Element *F = tc.icon_items.front(); F; F = F->next()) { - file->store_line(E->key() + "." + F->get().name + " = default"); - } - - if (tc.color_items.size()) { - file->store_line("\n; Color Items:\n"); - } - - for (Set<_TECategory::Item<Color>>::Element *F = tc.color_items.front(); F; F = F->next()) { - file->store_line(E->key() + "." + F->get().name + " = default"); - } - - if (tc.constant_items.size()) { - file->store_line("\n; Constant Items:\n"); - } - - for (Set<_TECategory::Item<int>>::Element *F = tc.constant_items.front(); F; F = F->next()) { - file->store_line(E->key() + "." + F->get().name + " = default"); - } - } - - file->close(); - memdelete(file); -} - -void ThemeEditor::_theme_create_menu_cbk(int p_option) { - bool import = (p_option == POPUP_IMPORT_EDITOR_THEME); - - Ref<Theme> base_theme; - - if (p_option == POPUP_CREATE_EMPTY) { - base_theme = Theme::get_default(); - } else { - base_theme = EditorNode::get_singleton()->get_theme_base()->get_theme(); - } - - { - List<StringName> types; - base_theme->get_type_list(&types); - - for (List<StringName>::Element *T = types.front(); T; T = T->next()) { - StringName type = T->get(); - - List<StringName> icons; - base_theme->get_icon_list(type, &icons); - - for (List<StringName>::Element *E = icons.front(); E; E = E->next()) { - theme->set_icon(E->get(), type, import ? base_theme->get_icon(E->get(), type) : Ref<Texture2D>()); - } - - List<StringName> styleboxs; - base_theme->get_stylebox_list(type, &styleboxs); - - for (List<StringName>::Element *E = styleboxs.front(); E; E = E->next()) { - theme->set_stylebox(E->get(), type, import ? base_theme->get_stylebox(E->get(), type) : Ref<StyleBox>()); - } - - List<StringName> fonts; - base_theme->get_font_list(type, &fonts); - - for (List<StringName>::Element *E = fonts.front(); E; E = E->next()) { - theme->set_font(E->get(), type, Ref<Font>()); - } - - List<StringName> font_sizes; - base_theme->get_font_size_list(type, &font_sizes); - - for (List<StringName>::Element *E = font_sizes.front(); E; E = E->next()) { - theme->set_font_size(E->get(), type, base_theme->get_font_size(E->get(), type)); - } - - List<StringName> colors; - base_theme->get_color_list(type, &colors); - - for (List<StringName>::Element *E = colors.front(); E; E = E->next()) { - theme->set_color(E->get(), type, import ? base_theme->get_color(E->get(), type) : Color()); - } - - List<StringName> constants; - base_theme->get_constant_list(type, &constants); - - for (List<StringName>::Element *E = constants.front(); E; E = E->next()) { - theme->set_constant(E->get(), type, base_theme->get_constant(E->get(), type)); - } - } - } -} - void ThemeEditor::_theme_edit_button_cbk() { - theme_edit_dialog->popup_centered(Size2(800, 640) * EDSCALE); + theme_edit_dialog->popup_centered(Size2(850, 760) * EDSCALE); } void ThemeEditor::_notification(int p_what) { @@ -1059,19 +1954,9 @@ ThemeEditor::ThemeEditor() { top_menu->add_child(memnew(Label(TTR("Preview:")))); top_menu->add_spacer(false); - theme_create_menu = memnew(MenuButton); - theme_create_menu->set_text(TTR("Create Theme...")); - theme_create_menu->set_tooltip(TTR("Create a new Theme.")); - theme_create_menu->get_popup()->add_item(TTR("Empty Template"), POPUP_CREATE_EMPTY); - theme_create_menu->get_popup()->add_separator(); - theme_create_menu->get_popup()->add_item(TTR("Empty Editor Template"), POPUP_CREATE_EDITOR_EMPTY); - theme_create_menu->get_popup()->add_item(TTR("From Current Editor Theme"), POPUP_IMPORT_EDITOR_THEME); - top_menu->add_child(theme_create_menu); - theme_create_menu->get_popup()->connect("id_pressed", callable_mp(this, &ThemeEditor::_theme_create_menu_cbk)); - theme_edit_button = memnew(Button); - theme_edit_button->set_text(TTR("Edit Theme Items")); - theme_edit_button->set_tooltip(TTR("Customize Theme items.")); + theme_edit_button->set_text(TTR("Manage Items")); + theme_edit_button->set_tooltip(TTR("Add, remove, organize and import Theme items.")); theme_edit_button->set_flat(true); theme_edit_button->connect("pressed", callable_mp(this, &ThemeEditor::_theme_edit_button_cbk)); top_menu->add_child(theme_edit_button); @@ -1260,11 +2145,6 @@ ThemeEditor::ThemeEditor() { theme_edit_dialog = memnew(ThemeItemEditorDialog); theme_edit_dialog->hide(); add_child(theme_edit_dialog); - - file_dialog = memnew(EditorFileDialog); - file_dialog->add_filter("*.theme ; " + TTR("Theme File")); - add_child(file_dialog); - file_dialog->connect("file_selected", callable_mp(this, &ThemeEditor::_save_template_cbk)); } void ThemeEditorPlugin::edit(Object *p_node) { diff --git a/editor/plugins/theme_editor_plugin.h b/editor/plugins/theme_editor_plugin.h index 0a840aecd7..5f4de68f45 100644 --- a/editor/plugins/theme_editor_plugin.h +++ b/editor/plugins/theme_editor_plugin.h @@ -41,14 +41,148 @@ #include "editor/editor_node.h" +class ThemeItemImportTree : public VBoxContainer { + GDCLASS(ThemeItemImportTree, VBoxContainer); + + Ref<Theme> edited_theme; + Ref<Theme> base_theme; + + struct ThemeItem { + String type_name; + Theme::DataType data_type; + String item_name; + + bool operator<(const ThemeItem &p_item) const { + if (type_name == p_item.type_name && data_type == p_item.data_type) { + return item_name < p_item.item_name; + } + if (type_name == p_item.type_name) { + return data_type < p_item.data_type; + } + return type_name < p_item.type_name; + } + }; + + enum ItemCheckedState { + SELECT_IMPORT_DEFINITION, + SELECT_IMPORT_FULL, + }; + + Map<ThemeItem, ItemCheckedState> selected_items; + + LineEdit *import_items_filter; + + Tree *import_items_tree; + List<TreeItem *> tree_color_items; + List<TreeItem *> tree_constant_items; + List<TreeItem *> tree_font_items; + List<TreeItem *> tree_font_size_items; + List<TreeItem *> tree_icon_items; + List<TreeItem *> tree_stylebox_items; + + bool updating_tree = false; + + enum ItemActionFlag { + IMPORT_ITEM = 1, + IMPORT_ITEM_DATA = 2, + }; + + TextureRect *select_colors_icon; + Label *select_colors_label; + Button *select_all_colors_button; + Button *select_full_colors_button; + Button *deselect_all_colors_button; + Label *total_selected_colors_label; + + TextureRect *select_constants_icon; + Label *select_constants_label; + Button *select_all_constants_button; + Button *select_full_constants_button; + Button *deselect_all_constants_button; + Label *total_selected_constants_label; + + TextureRect *select_fonts_icon; + Label *select_fonts_label; + Button *select_all_fonts_button; + Button *select_full_fonts_button; + Button *deselect_all_fonts_button; + Label *total_selected_fonts_label; + + TextureRect *select_font_sizes_icon; + Label *select_font_sizes_label; + Button *select_all_font_sizes_button; + Button *select_full_font_sizes_button; + Button *deselect_all_font_sizes_button; + Label *total_selected_font_sizes_label; + + TextureRect *select_icons_icon; + Label *select_icons_label; + Button *select_all_icons_button; + Button *select_full_icons_button; + Button *deselect_all_icons_button; + Label *total_selected_icons_label; + + TextureRect *select_styleboxes_icon; + Label *select_styleboxes_label; + Button *select_all_styleboxes_button; + Button *select_full_styleboxes_button; + Button *deselect_all_styleboxes_button; + Label *total_selected_styleboxes_label; + + HBoxContainer *select_icons_warning_hb; + TextureRect *select_icons_warning_icon; + Label *select_icons_warning; + + Button *import_collapse_types_button; + Button *import_expand_types_button; + Button *import_select_all_button; + Button *import_select_full_button; + Button *import_deselect_all_button; + + void _update_items_tree(); + void _toggle_type_items(bool p_collapse); + void _filter_text_changed(const String &p_value); + + void _store_selected_item(TreeItem *p_tree_item); + void _restore_selected_item(TreeItem *p_tree_item); + void _update_total_selected(Theme::DataType p_data_type); + + void _tree_item_edited(); + void _select_all_subitems(TreeItem *p_root_item, bool p_select_with_data); + void _deselect_all_subitems(TreeItem *p_root_item, bool p_deselect_completely); + void _update_parent_items(TreeItem *p_root_item); + + void _select_all_items_pressed(); + void _select_full_items_pressed(); + void _deselect_all_items_pressed(); + + void _select_all_data_type_pressed(int p_data_type); + void _select_full_data_type_pressed(int p_data_type); + void _deselect_all_data_type_pressed(int p_data_type); + + void _import_selected(); + +protected: + void _notification(int p_what); + static void _bind_methods(); + +public: + void set_edited_theme(const Ref<Theme> &p_theme); + void set_base_theme(const Ref<Theme> &p_theme); + void reset_item_tree(); + + bool has_selected_items() const; + + ThemeItemImportTree(); +}; + class ThemeItemEditorDialog : public AcceptDialog { GDCLASS(ThemeItemEditorDialog, AcceptDialog); Ref<Theme> edited_theme; ItemList *edit_type_list; - OptionButton *edit_add_class_options; - LineEdit *edit_add_custom_value; + LineEdit *edit_add_type_value; String edited_item_type; Button *edit_items_add_color; @@ -83,6 +217,19 @@ class ThemeItemEditorDialog : public AcceptDialog { String edit_item_old_name; Theme::DataType edit_item_data_type = Theme::DATA_TYPE_MAX; + ThemeItemImportTree *import_default_theme_items; + ThemeItemImportTree *import_editor_theme_items; + ThemeItemImportTree *import_other_theme_items; + + LineEdit *import_another_theme_value; + Button *import_another_theme_button; + EditorFileDialog *import_another_theme_dialog; + + ConfirmationDialog *confirm_closing_dialog; + + void ok_pressed() override; + void _close_dialog(); + void _dialog_about_to_show(); void _update_edit_types(); void _edited_type_selected(int p_item_idx); @@ -90,8 +237,7 @@ class ThemeItemEditorDialog : public AcceptDialog { void _update_edit_item_tree(String p_item_type); void _item_tree_button_pressed(Object *p_item, int p_column, int p_id); - void _add_class_type_items(); - void _add_custom_type(); + void _add_theme_type(); void _add_theme_item(Theme::DataType p_data_type, String p_item_name, String p_item_type); void _remove_data_type_items(Theme::DataType p_data_type, String p_item_type); void _remove_class_items(); @@ -103,6 +249,9 @@ class ThemeItemEditorDialog : public AcceptDialog { void _confirm_edit_theme_item(); void _edit_theme_item_gui_input(const Ref<InputEvent> &p_event); + void _open_select_another_theme(); + void _select_another_theme_cbk(const String &p_path); + protected: void _notification(int p_what); @@ -115,29 +264,18 @@ public: class ThemeEditor : public VBoxContainer { GDCLASS(ThemeEditor, VBoxContainer); - Panel *main_panel; - MarginContainer *main_container; Ref<Theme> theme; - EditorFileDialog *file_dialog; - double time_left = 0; Button *theme_edit_button; - MenuButton *theme_create_menu; ThemeItemEditorDialog *theme_edit_dialog; - enum CreatePopupMode { - POPUP_CREATE_EMPTY, - POPUP_CREATE_EDITOR_EMPTY, - POPUP_IMPORT_EDITOR_THEME, - }; - + Panel *main_panel; + MarginContainer *main_container; Tree *test_tree; - void _save_template_cbk(String fname); void _theme_edit_button_cbk(); - void _theme_create_menu_cbk(int p_option); void _propagate_redraw(Control *p_at); void _refresh_interval(); diff --git a/icon_outlined.png b/icon_outlined.png Binary files differnew file mode 100644 index 0000000000..5f1440f287 --- /dev/null +++ b/icon_outlined.png diff --git a/icon_outlined.svg b/icon_outlined.svg new file mode 100644 index 0000000000..08f9f6f863 --- /dev/null +++ b/icon_outlined.svg @@ -0,0 +1,159 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="1024" + height="1024" + id="svg3030" + version="1.1" + inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)" + sodipodi:docname="icon_outlined.svg" + inkscape:export-filename="/home/riteo/srg/godot-riteo/icon_outlined.png" + inkscape:export-xdpi="24" + inkscape:export-ydpi="24"> + <defs + id="defs3032" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:zoom="0.8359375" + inkscape:cx="512" + inkscape:cy="512" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:window-width="1916" + inkscape:window-height="1025" + inkscape:window-x="1360" + inkscape:window-y="53" + inkscape:window-maximized="1" + inkscape:document-rotation="0" + inkscape:pagecheckerboard="true" + inkscape:snap-smooth-nodes="true" + inkscape:snap-intersection-paths="true" + inkscape:object-paths="true" + showguides="false" /> + <metadata + id="metadata3035"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(0,-98.519719)"> + <g + id="g78-3-5" + transform="matrix(4.1626099,0,0,-4.1626099,919.24188,771.67092)" + style="fill:none;fill-opacity:0.527344;stroke:#ffffff;stroke-width:15.58077612;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"> + <path + id="path80-6-3" + style="fill:none;fill-opacity:0.527344;fill-rule:nonzero;stroke:#ffffff;stroke-width:23.49692134;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" + d="m 226.33398,222.09961 c -15.35819,3.41427 -30.55118,8.16852 -44.79492,15.33789 0.32575,12.57731 1.13879,24.62813 2.78711,36.86914 -5.5316,3.54397 -11.34506,6.58567 -16.51172,10.73438 -5.24959,4.03861 -10.60984,7.90172 -15.36328,12.625 -9.49632,-6.28112 -19.54792,-12.18415 -29.90234,-17.39454 -11.16124,12.01179 -21.59792,24.97673 -30.123049,39.48438 6.699845,10.51682 13.887809,21.08874 20.542969,29.33203 0.0561,36.95701 -0.082,77.98955 0,113.01958 0,51.83844 65.75967,76.75448 147.46094,77.04102 h 0.0996 0.0996 c 81.70127,-0.28654 147.43945,-25.20258 147.43945,-77.04102 0.0505,-37.842 0.0165,-79.50966 0.0214,-113.01953 7.68652,-9.6765 14.96452,-20.35178 20.54102,-29.33203 -8.52211,-14.50765 -18.96376,-27.47259 -30.125,-39.48438 -10.3514,5.21039 -20.40602,11.11342 -29.90234,17.39454 -4.75194,-4.72328 -10.1042,-8.58639 -15.36133,-12.625 -5.16515,-4.14871 -10.98481,-7.19041 -16.50586,-10.73438 1.6438,-12.24101 2.45595,-24.29183 2.7832,-36.86914 -14.24524,-7.16937 -29.43699,-11.92362 -44.80273,-15.33789 -6.13484,10.31068 -11.74471,21.47716 -16.63086,32.39258 -5.79401,-0.96818 -11.61467,-1.32712 -17.44336,-1.39649 v -0.01 c -0.0407,0 -0.0786,0.01 -0.11328,0.01 -0.0362,0 -0.0732,-0.01 -0.10938,-0.01 v 0.01 c -5.83925,0.0694 -11.65565,0.42831 -17.45117,1.39649 -4.88313,-10.91542 -10.49088,-22.0819 -16.63477,-32.39258 z" + transform="matrix(0.66309862,0,0,-0.66309862,-270.58935,290.52015)" + sodipodi:nodetypes="ccccccccccccccccccccccccsccccc" /> + </g> + <g + id="g78" + transform="matrix(4.162611,0,0,-4.162611,919.24059,771.67186)" + style="stroke-width:0.32031175"> + <path + d="m 0,0 c 0,0 -0.325,1.994 -0.515,1.976 l -36.182,-3.491 c -2.879,-0.278 -5.115,-2.574 -5.317,-5.459 l -0.994,-14.247 -27.992,-1.997 -1.904,12.912 c -0.424,2.872 -2.932,5.037 -5.835,5.037 h -38.188 c -2.902,0 -5.41,-2.165 -5.834,-5.037 l -1.905,-12.912 -27.992,1.997 -0.994,14.247 c -0.202,2.886 -2.438,5.182 -5.317,5.46 l -36.2,3.49 c -0.187,0.018 -0.324,-1.978 -0.511,-1.978 l -0.049,-7.83 30.658,-4.944 1.004,-14.374 c 0.203,-2.91 2.551,-5.263 5.463,-5.472 l 38.551,-2.75 c 0.146,-0.01 0.29,-0.016 0.434,-0.016 2.897,0 5.401,2.166 5.825,5.038 l 1.959,13.286 h 28.005 l 1.959,-13.286 c 0.423,-2.871 2.93,-5.037 5.831,-5.037 0.142,0 0.284,0.005 0.423,0.015 l 38.556,2.75 c 2.911,0.209 5.26,2.562 5.463,5.472 l 1.003,14.374 30.645,4.966 z" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.32031175" + id="path80" + inkscape:connector-curvature="0" /> + </g> + <g + id="g82-3" + transform="matrix(4.162611,0,0,-4.162611,104.69892,525.90697)" + style="stroke-width:0.32031175"> + <path + d="m 0,0 v -47.514 -6.035 -5.492 c 0.108,-0.001 0.216,-0.005 0.323,-0.015 l 36.196,-3.49 c 1.896,-0.183 3.382,-1.709 3.514,-3.609 l 1.116,-15.978 31.574,-2.253 2.175,14.747 c 0.282,1.912 1.922,3.329 3.856,3.329 h 38.188 c 1.933,0 3.573,-1.417 3.855,-3.329 l 2.175,-14.747 31.575,2.253 1.115,15.978 c 0.133,1.9 1.618,3.425 3.514,3.609 l 36.182,3.49 c 0.107,0.01 0.214,0.014 0.322,0.015 v 4.711 l 0.015,0.005 V 0 c 5.09692,6.4164715 9.92323,13.494208 13.621,19.449 -5.651,9.62 -12.575,18.217 -19.976,26.182 -6.864,-3.455 -13.531,-7.369 -19.828,-11.534 -3.151,3.132 -6.7,5.694 -10.186,8.372 -3.425,2.751 -7.285,4.768 -10.946,7.118 1.09,8.117 1.629,16.108 1.846,24.448 -9.446,4.754 -19.519,7.906 -29.708,10.17 -4.068,-6.837 -7.788,-14.241 -11.028,-21.479 -3.842,0.642 -7.702,0.88 -11.567,0.926 v 0.006 c -0.027,0 -0.052,-0.006 -0.075,-0.006 -0.024,0 -0.049,0.006 -0.073,0.006 V 63.652 C 93.903,63.606 90.046,63.368 86.203,62.726 82.965,69.964 79.247,77.368 75.173,84.205 64.989,81.941 54.915,78.789 45.47,74.035 45.686,65.695 46.225,57.704 47.318,49.587 43.65,47.237 39.795,45.22 36.369,42.469 32.888,39.791 29.333,37.229 26.181,34.097 19.884,38.262 13.219,42.176 6.353,45.631 -1.048,37.666 -7.968,29.069 -13.621,19.449 -9.1783421,12.475308 -4.4130298,5.4661124 0,0 Z" + style="fill:#478cbf;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.320312" + id="path84-6" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccccccsssscccccccccccccccccccsccccccccccc" /> + </g> + <g + id="g86-7" + transform="matrix(4.162611,0,0,-4.162611,784.07144,817.24284)" + style="stroke-width:0.32031175"> + <path + d="m 0,0 -1.121,-16.063 c -0.135,-1.936 -1.675,-3.477 -3.611,-3.616 l -38.555,-2.751 c -0.094,-0.007 -0.188,-0.01 -0.281,-0.01 -1.916,0 -3.569,1.406 -3.852,3.33 l -2.211,14.994 H -81.09 l -2.211,-14.994 c -0.297,-2.018 -2.101,-3.469 -4.133,-3.32 l -38.555,2.751 c -1.936,0.139 -3.476,1.68 -3.611,3.616 L -130.721,0 -163.268,3.138 c 0.015,-3.498 0.06,-7.33 0.06,-8.093 0,-34.374 43.605,-50.896 97.781,-51.086 h 0.066 0.067 c 54.176,0.19 97.766,16.712 97.766,51.086 0,0.777 0.047,4.593 0.063,8.093 z" + style="fill:#478cbf;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.32031175" + id="path88-5" + inkscape:connector-curvature="0" /> + </g> + <g + id="g90-3" + transform="matrix(4.162611,0,0,-4.162611,389.21484,625.67104)" + style="stroke-width:0.32031175"> + <path + d="m 0,0 c 0,-12.052 -9.765,-21.815 -21.813,-21.815 -12.042,0 -21.81,9.763 -21.81,21.815 0,12.044 9.768,21.802 21.81,21.802 C -9.765,21.802 0,12.044 0,0" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.32031175" + id="path92-5" + inkscape:connector-curvature="0" /> + </g> + <g + id="g94-6" + transform="matrix(4.162611,0,0,-4.162611,367.36686,631.05679)" + style="stroke-width:0.32031175"> + <path + d="m 0,0 c 0,-7.994 -6.479,-14.473 -14.479,-14.473 -7.996,0 -14.479,6.479 -14.479,14.473 0,7.994 6.483,14.479 14.479,14.479 C -6.479,14.479 0,7.994 0,0" + style="fill:#414042;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.32031175" + id="path96-2" + inkscape:connector-curvature="0" /> + </g> + <g + id="g98-9" + transform="matrix(4.162611,0,0,-4.162611,511.99336,724.73954)" + style="stroke-width:0.32031175"> + <path + d="m 0,0 c -3.878,0 -7.021,2.858 -7.021,6.381 v 20.081 c 0,3.52 3.143,6.381 7.021,6.381 3.878,0 7.028,-2.861 7.028,-6.381 V 6.381 C 7.028,2.858 3.878,0 0,0" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.32031175" + id="path100-1" + inkscape:connector-curvature="0" /> + </g> + <g + id="g102-2" + transform="matrix(4.162611,0,0,-4.162611,634.78706,625.67104)" + style="stroke-width:0.32031175"> + <path + d="m 0,0 c 0,-12.052 9.765,-21.815 21.815,-21.815 12.041,0 21.808,9.763 21.808,21.815 0,12.044 -9.767,21.802 -21.808,21.802 C 9.765,21.802 0,12.044 0,0" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.32031175" + id="path104-7" + inkscape:connector-curvature="0" /> + </g> + <g + id="g106-0" + transform="matrix(4.162611,0,0,-4.162611,656.64056,631.05679)" + style="stroke-width:0.32031175"> + <path + d="m 0,0 c 0,-7.994 6.477,-14.473 14.471,-14.473 8.002,0 14.479,6.479 14.479,14.473 0,7.994 -6.477,14.479 -14.479,14.479 C 6.477,14.479 0,7.994 0,0" + style="fill:#414042;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.32031175" + id="path108-9" + inkscape:connector-curvature="0" /> + </g> + <g + id="g78-3" + transform="matrix(4.1626558,0,0,-4.1626558,918.83083,771.66929)" + style="fill:#000000;fill-opacity:0.527344;stroke:none;stroke-width:10.0248;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> +</svg> diff --git a/logo_outlined.png b/logo_outlined.png Binary files differnew file mode 100644 index 0000000000..44b85cde57 --- /dev/null +++ b/logo_outlined.png diff --git a/logo_outlined.svg b/logo_outlined.svg new file mode 100644 index 0000000000..4079a1dd56 --- /dev/null +++ b/logo_outlined.svg @@ -0,0 +1,185 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + id="svg2" + version="1.1" + inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)" + xml:space="preserve" + width="1024" + height="414" + viewBox="0 0 960.00002 388.12499" + sodipodi:docname="logo_outlined.svg" + inkscape:export-filename="/home/riteo/srg/godot-riteo/logo_outlined.png" + inkscape:export-xdpi="48" + inkscape:export-ydpi="48"><metadata + id="metadata8"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs + id="defs6"><clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath16"><path + d="M 0,595.276 H 841.89 V 0 H 0 Z" + id="path18" + inkscape:connector-curvature="0" /></clipPath></defs><sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1916" + inkscape:window-height="1025" + id="namedview4" + showgrid="false" + inkscape:zoom="1.2041016" + inkscape:cx="512" + inkscape:cy="207" + inkscape:window-x="1360" + inkscape:window-y="53" + inkscape:window-maximized="1" + inkscape:current-layer="g14" + fit-margin-top="48" + fit-margin-left="48" + fit-margin-right="48" + fit-margin-bottom="48" + inkscape:document-rotation="0" + inkscape:pagecheckerboard="true" + inkscape:snap-intersection-paths="true" + inkscape:object-paths="true" + inkscape:snap-smooth-nodes="true" + inkscape:snap-midpoints="true" + inkscape:snap-bbox="false" + inkscape:bbox-paths="false" + inkscape:snap-bbox-edge-midpoints="false" + inkscape:snap-bbox-midpoints="false" + inkscape:object-nodes="true" + inkscape:snap-others="false" + units="px" /><g + id="g10" + inkscape:groupmode="layer" + inkscape:label="godot_engine_logo_2017_curves-01" + transform="matrix(1.25,0,0,-1.25,-94.249997,597.49874)"><g + id="g12"><g + id="g14" + clip-path="url(#clipPath16)"><g + id="g78-3" + transform="matrix(1.1310535,0,0,1.1310535,348.13118,279.26721)" + style="fill:none;stroke:#ffffff;stroke-width:15.5885606;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"><path + id="path80-6" + style="fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:23.50866089;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 226.33398,222.09961 c -15.35819,3.41427 -30.55118,8.16852 -44.79492,15.33789 0.32575,12.57731 1.13879,24.62813 2.78711,36.86914 -5.5316,3.54397 -11.34506,6.58567 -16.51172,10.73438 -5.24959,4.03861 -10.60984,7.90172 -15.36328,12.625 -9.49632,-6.28112 -19.54792,-12.18415 -29.90234,-17.39454 -11.16124,12.01179 -21.59792,24.97673 -30.123049,39.48438 6.699845,10.51682 13.887809,21.08874 20.542969,29.33203 0.0561,36.95701 -0.082,77.98955 0,113.01958 0,51.83844 65.75967,76.75448 147.46094,77.04102 h 0.0996 0.0996 c 81.70127,-0.28654 147.43945,-25.20258 147.43945,-77.04102 0.0505,-37.842 0.0165,-79.50966 0.0214,-113.01953 7.68652,-9.6765 14.96452,-20.35178 20.54102,-29.33203 -8.52211,-14.50765 -18.96376,-27.47259 -30.125,-39.48438 -10.3514,5.21039 -20.40602,11.11342 -29.90234,17.39454 -4.75194,-4.72328 -10.1042,-8.58639 -15.36133,-12.625 -5.16515,-4.14871 -10.98481,-7.19041 -16.50586,-10.73438 1.6438,-12.24101 2.45595,-24.29183 2.7832,-36.86914 -14.24524,-7.16937 -29.43699,-11.92362 -44.80273,-15.33789 -6.13484,10.31068 -11.74471,21.47716 -16.63086,32.39258 -5.79401,-0.96818 -11.61467,-1.32712 -17.44336,-1.39649 v -0.01 c -0.0407,0 -0.0786,0.01 -0.11328,0.01 -0.0362,0 -0.0732,-0.01 -0.10938,-0.01 v 0.01 c -5.83925,0.0694 -11.65565,0.42831 -17.45117,1.39649 -4.88313,-10.91542 -10.49088,-22.0819 -16.63477,-32.39258 z" + transform="matrix(0.66309862,0,0,-0.66309862,-270.58935,290.52015)" + sodipodi:nodetypes="ccccccccccccccccccccccccsccccc" /></g><g + id="g20" + transform="matrix(1.1310535,0,0,1.1310535,531.44953,355.31567)" + style="stroke:none;stroke-width:10.60874228;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill" /><g + id="g24" + transform="matrix(1.1310535,0,0,1.1310535,607.8515,354.43097)" + style="stroke:none;stroke-width:10.60874228;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill" /><g + id="g28" + transform="matrix(1.1310535,0,0,1.1310535,700.81066,355.31567)" + style="stroke:none;stroke-width:10.60874228;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill" /><g + id="g32" + transform="matrix(1.1310535,0,0,1.1310535,789.01132,291.33514)" + style="stroke:none;stroke-width:10.60874228;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill" /><g + id="g36" + transform="matrix(1.1310535,0,0,1.1310535,468.26549,336.71278)" + style="stroke:none;stroke-width:10.60874228;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"><path + id="path38" + style="fill:#414042;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:15.5885606;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill" + d="m 0,0 c -6.078,0.094 -13.034,-1.173 -13.034,-1.173 v -11.863 h 6.995 l -0.078,-5.288 c 0,-1.959 -1.942,-2.943 -5.815,-2.943 -3.878,0 -7.303,1.642 -10.274,4.917 -2.978,3.279 -4.459,8.072 -4.459,14.388 0,6.329 1.447,10.995 4.345,14.006 2.892,3.008 6.683,4.517 11.346,4.517 1.959,0 3.987,-0.316 6.096,-0.961 2.11,-0.639 3.519,-1.238 4.238,-1.799 0.713,-0.577 1.391,-0.85 2.032,-0.85 0.638,0 1.671,0.746 3.1,2.255 1.431,1.505 2.713,3.786 3.844,6.827 1.126,3.057 1.69,5.4 1.69,7.062 0,1.649 -0.036,2.786 -0.109,3.386 -1.581,1.73 -4.499,3.102 -8.755,4.122 -4.248,1.017 -9.011,1.522 -14.28,1.522 -11.594,0 -20.66,-3.65 -27.207,-10.95 -6.552,-7.303 -9.822,-16.783 -9.822,-28.452 0,-13.701 3.347,-24.087 10.041,-31.162 6.706,-7.074 15.51,-10.607 26.425,-10.607 5.87,0 11.08,0.505 15.632,1.522 4.557,1.013 7.586,2.053 9.093,3.105 l 0.452,35.33 C 11.496,-1.036 6.078,-0.104 0,0 m 283.58148,-40.1198 c 0,-1.496 -3.721,-2.255 -11.176,-2.255 -7.448,0 -11.18,0.759 -11.18,2.255 v 56.681 h -13.545 c -1.281,0 -2.185,1.727 -2.71,5.198 -0.226,1.652 -0.334,3.343 -0.334,5.077 0,1.724 0.108,3.422 0.334,5.077 0.525,3.462 1.429,5.202 2.71,5.202 h 49.112 c 1.279,0 2.179,-1.74 2.712,-5.202 0.221,-1.655 0.335,-3.353 0.335,-5.077 0,-1.734 -0.114,-3.425 -0.335,-5.077 -0.533,-3.471 -1.433,-5.198 -2.712,-5.198 h -13.211 z M 205.6005,16.447401 c -3.612,0 -6.645,-1.659 -9.095,-4.967 -2.44,-3.3110004 -3.662,-7.9580004 -3.662,-13.9380004 0,-5.993 1.169,-10.5809996 3.499,-13.7779996 2.33,-3.207 5.398,-4.804 9.2,-4.804 3.801,0 6.89,1.617 9.258,4.862 2.372,3.233 3.56,7.8609996 3.56,13.8859996 0,6.02 -1.225,10.654 -3.671,13.8900004 -2.447,3.232 -5.473,4.849 -9.089,4.849 m -0.058,-59.493 c -10.577,0 -19.193,3.46 -25.851,10.379 -6.663,6.925 -9.993,17.03 -9.993,30.3139996 0,13.2920004 3.367,23.3560004 10.1,30.2090004 6.741,6.844 15.431,10.269 26.086,10.269 10.651,0 19.246,-3.363 25.797,-10.109 6.55,-6.733 9.822,-16.94 9.822,-30.5910004 0,-13.6609996 -3.349,-23.8219996 -10.05,-30.4899996 -6.699,-6.654 -15.338,-9.981 -25.911,-9.981 m -82.13011,58.710808 v -33.768 c 0,-1.577 0.116,-2.571 0.342,-2.988 0.224,-0.415 0.903,-0.623 2.029,-0.623 4.144,0 7.283,1.548 9.429,4.634 2.151,3.083 3.215,8.2160005 3.215,15.4050005 0,7.192 -1.113,11.8779995 -3.325,14.0549995 -2.223,2.183 -5.744,3.285 -10.561,3.285 z m -21.675,-52.392 v 67.735 c 0,1.883 0.468,3.369 1.413,4.471 0.939,1.085 2.161,1.636 3.671,1.636 h 18.854 c 11.965,0 21.053,-3.018 27.257,-9.04 6.215,-6.02 9.322,-15.499 9.322,-28.44699953 0,-27.70000047 -11.821,-41.54700047 -35.456,-41.54700047 h -19.302 c -3.836,0 -5.759,1.727 -5.759,5.192 M 55.862999,16.447401 c -3.611,0 -6.636,-1.659 -9.09,-4.967 -2.441,-3.3110004 -3.668,-7.9580004 -3.668,-13.9380004 0,-5.993 1.166,-10.5809996 3.503,-13.7779996 2.333,-3.207 5.398,-4.804 9.2,-4.804 3.8,0 6.887,1.617 9.258,4.862 2.371,3.233 3.559,7.8609996 3.559,13.8859996 0,6.02 -1.227,10.654 -3.673,13.8900004 -2.443,3.232 -5.473,4.849 -9.089,4.849 m -0.055,-59.493 c -10.573,0 -19.195,3.46 -25.859,10.379 -6.655,6.925 -9.984,17.03 -9.984,30.3139996 0,13.2920004 3.367,23.3560004 10.101,30.2090004 6.736,6.844 15.431,10.269 26.082,10.269 10.649,0 19.251,-3.363 25.794,-10.109 6.555,-6.733 9.827,-16.94 9.827,-30.5910004 0,-13.6609996 -3.348,-23.8219996 -10.05,-30.4899996 -6.702,-6.654 -15.333,-9.981 -25.911,-9.981" /></g><g + id="g40" + transform="matrix(1.1310535,0,0,1.1310535,441.34721,235.75121)" + style="stroke:none;stroke-width:4.31066306;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill" /><g + id="g44" + transform="matrix(1.1310535,0,0,1.1310535,456.01527,232.82495)" + style="stroke:none;stroke-width:4.31066306;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill" /><g + id="g48" + transform="matrix(1.1310535,0,0,1.1310535,476.7303,259.10521)" + style="stroke:none;stroke-width:4.31066306;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill" /><g + id="g52" + transform="matrix(1.1310535,0,0,1.1310535,522.82277,256.83868)" + style="stroke:none;stroke-width:4.31066306;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill" /><g + id="g56" + transform="matrix(1.1310535,0,0,1.1310535,558.0805,256.83868)" + style="stroke:none;stroke-width:4.31066306;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill" /><g + id="g60" + transform="matrix(1.1310535,0,0,1.1310535,575.91679,259.10521)" + style="stroke:none;stroke-width:4.31066306;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill" /><g + id="g64" + transform="matrix(1.1310535,0,0,1.1310535,600.8685,242.30884)" + style="stroke:none;stroke-width:4.31066306;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill" /><g + id="g70" + transform="matrix(1.1310535,0,0,1.1310535,638.15379,259.10521)" + style="stroke:none;stroke-width:4.31066306;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill" /><g + id="g74" + transform="matrix(1.1310535,0,0,1.1310535,669.70883,256.83868)" + style="stroke:none;stroke-width:4.31066306;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"><path + id="path76" + style="fill:#6d6e71;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:15.5885606;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill" + d="M 0,0 C -1.763,0 -3.208,-0.802 -4.334,-2.402 -5.463,-4.008 -6.052,-5.987 -6.102,-8.346 H 5.56 v 1.082 c 0,2.086 -0.486,3.823 -1.47,5.201 C 3.109,-0.684 1.747,0 0,0 m 0.401,-23.76 c -2.733,0 -4.958,1.026 -6.681,3.073 -1.73,2.043 -2.595,4.657 -2.595,7.841 v 4.197 c 0,3.19 0.865,5.85 2.6,7.965 1.739,2.105 3.831,3.158 6.275,3.158 2.646,0 4.706,-0.939 6.172,-2.823 1.462,-1.887 2.195,-4.422 2.195,-7.603 v -2.773 H -6.102 v -2.102 c 0,-2.447 0.59,-4.484 1.757,-6.11 1.166,-1.63 2.748,-2.438 4.746,-2.438 1.382,0 2.579,0.244 3.578,0.724 1.012,0.491 1.869,1.179 2.591,2.082 l 1.147,-1.988 c -0.769,-0.968 -1.755,-1.75 -2.962,-2.33 -1.203,-0.577 -2.658,-0.873 -4.354,-0.873 m -28.299804,25.7639105 0.23,-4.178 c 0.676,1.48300001 1.562,2.63400001 2.678,3.435 1.115,0.805 2.422,1.213 3.916,1.213 2.258,0 3.995,-0.835 5.199,-2.51299999 1.211,-1.67500001 1.807,-4.27900001 1.807,-7.81200001 V -23.271089 h -2.825 v 15.3939995 c 0,2.888 -0.422,4.905 -1.261,6.075 -0.843,1.17000001 -2.063,1.75300001 -3.668,1.75300001 -1.434,0 -2.635,-0.466 -3.599,-1.41400001 -0.967,-0.939 -1.692,-2.19 -2.171,-3.767 V -23.271089 h -2.809 V 2.0039105 Z m -9.133591,-25.2752055 h -2.830008 V 2.0037072 h 2.830008 z m 0,32.4710013 h -2.830008 v 3.9819957 h 2.830008 z M -60.863903,-12.846289 c 0,-2.565 0.486,-4.605 1.472,-6.123 0.974,-1.532 2.457,-2.288 4.436,-2.288 1.356,0 2.498,0.361 3.435,1.101 0.934,0.74 1.672,1.77 2.218,3.077 v 12.5200001 c -0.525,1.346 -1.246,2.434 -2.157,3.272 -0.91,0.82400002 -2.062,1.23800002 -3.448,1.23800002 -1.975,0 -3.468,-0.86 -4.46,-2.58700002 -0.999,-1.73 -1.496,-3.986 -1.496,-6.756 z m -2.833,3.4540001 c 0,3.582 0.723,6.459 2.177,8.62700002 1.442,2.15699998 3.448,3.23899998 6.004,3.23899998 1.419,0 2.664,-0.346 3.728,-1.04 1.066,-0.68099998 1.947,-1.67799998 2.654,-2.946 l 0.274,3.516 h 2.381 V -23.294289 c 0,-3.239 -0.751,-5.749 -2.26,-7.525 -1.511,-1.769 -3.657,-2.665 -6.428,-2.665 -0.996,0 -2.067,0.156 -3.212,0.459 -1.147,0.303 -2.162,0.701 -3.052,1.2 l 0.776,2.463 c 0.759,-0.492 1.608,-0.873 2.548,-1.141 0.932,-0.277 1.895,-0.41 2.894,-0.41 2.009,0 3.498,0.645 4.46,1.932 0.966,1.304 1.45,3.19 1.45,5.687 v 3.057 c -0.717,-1.138 -1.597,-2.011 -2.64,-2.614 -1.039,-0.606 -2.253,-0.909 -3.622,-0.909 -2.539,0 -4.53,0.994 -5.968,2.982 -1.441,1.984 -2.164,4.631 -2.164,7.932 z m -19.227592,11.3961994 0.23,-4.178 c 0.674,1.48300001 1.564,2.63400001 2.682,3.435 1.108,0.805 2.413,1.213 3.914,1.213 2.258,0 3.988,-0.835 5.189,-2.51299999 1.214,-1.67500001 1.815,-4.27900001 1.815,-7.81200001 V -23.271089 h -2.825 v 15.3939995 c 0,2.888 -0.423,4.905 -1.264,6.075 -0.836,1.17000001 -2.065,1.75300001 -3.665,1.75300001 -1.435,0 -2.638,-0.466 -3.603,-1.41400001 -0.969,-0.939 -1.691,-2.19 -2.172,-3.767 V -23.271089 h -2.805 V 2.0039105 Z M -98.69412,0 c -1.763,0 -3.21,-0.802 -4.341,-2.402 -1.126,-1.606 -1.712,-3.585 -1.763,-5.944 h 11.663 v 1.082 c 0,2.086 -0.488,3.823 -1.474,5.201 -0.981,1.379 -2.341,2.063 -4.085,2.063 m 0.394,-23.76 c -2.726,0 -4.951,1.026 -6.679,3.073 -1.733,2.043 -2.6,4.657 -2.6,7.841 v 4.197 c 0,3.19 0.871,5.85 2.602,7.965 1.744,2.105 3.834,3.158 6.283,3.158 2.643,0 4.703,-0.939 6.164,-2.823 1.463,-1.887 2.197,-4.422 2.197,-7.603 v -2.773 h -14.465 v -2.102 c 0,-2.447 0.587,-4.484 1.76,-6.11 1.162,-1.63 2.742,-2.438 4.738,-2.438 1.387,0 2.585,0.244 3.585,0.724 1.007,0.491 1.866,1.179 2.589,2.082 l 1.141,-1.988 c -0.764,-0.968 -1.75,-1.75 -2.959,-2.33 -1.204,-0.577 -2.658,-0.873 -4.356,-0.873 M -129.86659,0 c -1.758,0 -3.202,-0.802 -4.334,-2.402 -1.133,-1.606 -1.718,-3.585 -1.765,-5.944 h 11.66 v 1.082 c 0,2.086 -0.489,3.823 -1.469,5.201 -0.986,1.379 -2.347,2.063 -4.092,2.063 m 0.397,-23.76 c -2.725,0 -4.954,1.026 -6.685,3.073 -1.726,2.043 -2.591,4.657 -2.591,7.841 v 4.197 c 0,3.19 0.867,5.85 2.602,7.965 1.739,2.105 3.828,3.158 6.277,3.158 2.648,0 4.699,-0.939 6.164,-2.823 1.468,-1.887 2.201,-4.422 2.201,-7.603 v -2.773 h -14.464 v -2.102 c 0,-2.447 0.586,-4.484 1.752,-6.11 1.168,-1.63 2.755,-2.438 4.744,-2.438 1.382,0 2.585,0.244 3.588,0.724 1.003,0.491 1.863,1.179 2.578,2.082 l 1.149,-1.988 c -0.763,-0.968 -1.752,-1.75 -2.959,-2.33 -1.204,-0.577 -2.659,-0.873 -4.356,-0.873 m -41.1488,25.7639105 0.24,-3.923 c 0.664,1.40400001 1.554,2.48600001 2.657,3.255 1.107,0.759 2.41,1.138 3.906,1.138 1.527,0 2.814,-0.444 3.852,-1.343 1.039,-0.89599999 1.805,-2.252 2.292,-4.074 0.623,1.682 1.505,3.01100001 2.65,3.973 1.145,0.964 2.534,1.444 4.143,1.444 2.217,0 3.937,-0.897 5.156,-2.69199999 1.224,-1.79900001 1.834,-4.55900001 1.834,-8.28800001 V -23.271089 h -2.823 v 14.8139995 c 0,3.1 -0.429,5.283 -1.263,6.538 -0.839,1.25700001 -2.042,1.89000001 -3.598,1.89000001 -1.637,0 -2.915,-0.691 -3.834,-2.09600001 -0.914,-1.405 -1.478,-3.161 -1.683,-5.282 v -0.655 -15.2089995 h -2.809 v 14.7979995 c 0,3.027 -0.424,5.194 -1.292,6.488 -0.864,1.29400001 -2.066,1.93600001 -3.609,1.93600001 -1.475,0 -2.668,-0.45 -3.562,-1.34200001 -0.9,-0.897 -1.54,-2.125 -1.928,-3.683 V -23.271089 h -2.806 V 2.0039105 Z M -188.9332,-21.231295 c 1.553,0 2.936,0.44 4.144,1.336 1.21,0.9 2.058,2.037 2.561,3.422 v 5.468 h -4.492 c -1.91,0 -3.44,-0.541 -4.585,-1.623 -1.148,-1.075 -1.716,-2.418 -1.716,-4.015 0,-1.349 0.355,-2.457 1.074,-3.311 0.718,-0.857 1.722,-1.277 3.014,-1.277 m 7.124,-2.04 c -0.14,0.876 -0.249,1.587 -0.318,2.144 -0.067,0.567 -0.101,1.131 -0.101,1.704 -0.767,-1.254 -1.757,-2.294 -2.98,-3.109 -1.221,-0.821 -2.579,-1.228 -4.075,-1.228 -2.092,0 -3.701,0.648 -4.84,1.946 -1.132,1.303 -1.704,3.059 -1.704,5.276 0,2.343 0.823,4.223 2.473,5.618 1.649,1.3950005 3.89,2.0920005 6.709,2.0920005 h 4.417 v 3.106 c 0,1.786 -0.456,3.193 -1.351,4.21 -0.914,1.00399996 -2.17,1.51199995911 -3.791,1.51199995911 -1.508,0 -2.752,-0.47899999911 -3.728,-1.44999995911 -0.973,-0.965 -1.456,-2.144 -1.456,-3.549 l -2.623,0.023 -0.046,0.137 c -0.074,1.906 0.647,3.591 2.168,5.08399996 1.515,1.48900004 3.459,2.22900004 5.825,2.22900004 2.338,0 4.22,-0.711 5.657,-2.12800004 1.429,-1.43099996 2.146,-3.47099996 2.146,-6.12399996 V -18.174295 c 0,-0.903 0.042,-1.78 0.121,-2.617 0.081,-0.848 0.212,-1.665 0.417,-2.48 z m -20.0925,4.627199 c -0.624,-1.28 -1.771,-2.454 -3.449,-3.516 -1.676,-1.069 -3.805,-1.6 -6.391,-1.6 -3.412,0 -6.156,1.075 -8.24,3.249 -2.076,2.157 -3.116,5.266 -3.116,9.323 v 10.116 c 0,3.969 0.98,7.013 2.946,9.138 1.962,2.108 4.59,3.177 7.872,3.177 3.208,0 5.695,-0.844 7.455,-2.513 1.755,-1.675 2.677,-4.015 2.757,-7.003 l -0.044,-0.133 h -2.619 c -0.094,2.29 -0.759,4.057 -2.01,5.305 -1.244,1.238 -3.095,1.864 -5.539,1.864 -2.473,0 -4.432,-0.837 -5.866,-2.516 -1.43,-1.675 -2.143,-4.103 -2.143,-7.293 v -10.174 c 0,-3.308 0.771,-5.83 2.311,-7.567 1.54,-1.724 3.616,-2.588 6.236,-2.588 1.913,0 3.451,0.339 4.602,1.033 1.155,0.684 1.956,1.519 2.409,2.51 v 8.861 h -7.06 v 2.463 h 9.889 z" /></g><g + id="g78" + transform="matrix(1.1310535,0,0,1.1310535,348.13109,279.2668)" + style="stroke-width:0.884131"><path + d="m 0,0 c 0,0 -0.325,1.994 -0.515,1.976 l -36.182,-3.491 c -2.879,-0.278 -5.115,-2.574 -5.317,-5.459 l -0.994,-14.247 -27.992,-1.997 -1.904,12.912 c -0.424,2.872 -2.932,5.037 -5.835,5.037 h -38.188 c -2.902,0 -5.41,-2.165 -5.834,-5.037 l -1.905,-12.912 -27.992,1.997 -0.994,14.247 c -0.202,2.886 -2.438,5.182 -5.317,5.46 l -36.2,3.49 c -0.187,0.018 -0.324,-1.978 -0.511,-1.978 l -0.049,-7.83 30.658,-4.944 1.004,-14.374 c 0.203,-2.91 2.551,-5.263 5.463,-5.472 l 38.551,-2.75 c 0.146,-0.01 0.29,-0.016 0.434,-0.016 2.897,0 5.401,2.166 5.825,5.038 l 1.959,13.286 h 28.005 l 1.959,-13.286 c 0.423,-2.871 2.93,-5.037 5.831,-5.037 0.142,0 0.284,0.005 0.423,0.015 l 38.556,2.75 c 2.911,0.209 5.26,2.562 5.463,5.472 l 1.003,14.374 30.645,4.966 z" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.884131" + id="path80" + inkscape:connector-curvature="0" /></g><g + id="g82" + transform="matrix(1.1310535,0,0,1.1310535,126.80608,346.04533)" + style="stroke-width:0.884131"><path + d="m 0,0 v -47.514 -6.035 -5.492 c 0.108,-0.001 0.216,-0.005 0.323,-0.015 l 36.196,-3.49 c 1.896,-0.183 3.382,-1.709 3.514,-3.609 l 1.116,-15.978 31.574,-2.253 2.175,14.747 c 0.282,1.912 1.922,3.329 3.856,3.329 h 38.188 c 1.933,0 3.573,-1.417 3.855,-3.329 l 2.175,-14.747 31.575,2.253 1.115,15.978 c 0.133,1.9 1.618,3.425 3.514,3.609 l 36.182,3.49 c 0.107,0.01 0.214,0.014 0.322,0.015 v 4.711 l 0.015,0.005 V 0 c 5.09692,6.4164715 9.92323,13.494208 13.621,19.449 -5.651,9.62 -12.575,18.217 -19.976,26.182 -6.864,-3.455 -13.531,-7.369 -19.828,-11.534 -3.151,3.132 -6.7,5.694 -10.186,8.372 -3.425,2.751 -7.285,4.768 -10.946,7.118 1.09,8.117 1.629,16.108 1.846,24.448 -9.446,4.754 -19.519,7.906 -29.708,10.17 -4.068,-6.837 -7.788,-14.241 -11.028,-21.479 -3.842,0.642 -7.702,0.88 -11.567,0.926 v 0.006 c -0.027,0 -0.052,-0.006 -0.075,-0.006 -0.024,0 -0.049,0.006 -0.073,0.006 V 63.652 C 93.903,63.606 90.046,63.368 86.203,62.726 82.965,69.964 79.247,77.368 75.173,84.205 64.989,81.941 54.915,78.789 45.47,74.035 45.686,65.695 46.225,57.704 47.318,49.587 43.65,47.237 39.795,45.22 36.369,42.469 32.888,39.791 29.333,37.229 26.181,34.097 19.884,38.262 13.219,42.176 6.353,45.631 -1.048,37.666 -7.968,29.069 -13.621,19.449 -9.1783421,12.475308 -4.4130298,5.4661124 0,0 Z" + style="fill:#478cbf;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.884131" + id="path84" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccccccsssscccccccccccccccccccsccccccccccc" /></g><g + id="g86" + transform="matrix(1.1310535,0,0,1.1310535,311.40329,266.88437)" + style="stroke-width:0.884131"><path + d="m 0,0 -1.121,-16.063 c -0.135,-1.936 -1.675,-3.477 -3.611,-3.616 l -38.555,-2.751 c -0.094,-0.007 -0.188,-0.01 -0.281,-0.01 -1.916,0 -3.569,1.406 -3.852,3.33 l -2.211,14.994 H -81.09 l -2.211,-14.994 c -0.297,-2.018 -2.101,-3.469 -4.133,-3.32 l -38.555,2.751 c -1.936,0.139 -3.476,1.68 -3.611,3.616 L -130.721,0 -163.268,3.138 c 0.015,-3.498 0.06,-7.33 0.06,-8.093 0,-34.374 43.605,-50.896 97.781,-51.086 h 0.066 0.067 c 54.176,0.19 97.766,16.712 97.766,51.086 0,0.777 0.047,4.593 0.063,8.093 z" + style="fill:#478cbf;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.884131" + id="path88" + inkscape:connector-curvature="0" /></g><g + id="g90" + transform="matrix(1.1310535,0,0,1.1310535,204.11393,318.93771)" + style="stroke-width:0.884131"><path + d="m 0,0 c 0,-12.052 -9.765,-21.815 -21.813,-21.815 -12.042,0 -21.81,9.763 -21.81,21.815 0,12.044 9.768,21.802 21.81,21.802 C -9.765,21.802 0,12.044 0,0" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.884131" + id="path92" + inkscape:connector-curvature="0" /></g><g + id="g94" + transform="matrix(1.1310535,0,0,1.1310535,198.17748,317.47435)" + style="stroke-width:0.884131"><path + d="m 0,0 c 0,-7.994 -6.479,-14.473 -14.479,-14.473 -7.996,0 -14.479,6.479 -14.479,14.473 0,7.994 6.483,14.479 14.479,14.479 C -6.479,14.479 0,7.994 0,0" + style="fill:#414042;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.884131" + id="path96" + inkscape:connector-curvature="0" /></g><g + id="g98" + transform="matrix(1.1310535,0,0,1.1310535,237.47503,292.01909)" + style="stroke-width:0.884131"><path + d="m 0,0 c -3.878,0 -7.021,2.858 -7.021,6.381 v 20.081 c 0,3.52 3.143,6.381 7.021,6.381 3.878,0 7.028,-2.861 7.028,-6.381 V 6.381 C 7.028,2.858 3.878,0 0,0" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.884131" + id="path100" + inkscape:connector-curvature="0" /></g><g + id="g102" + transform="matrix(1.1310535,0,0,1.1310535,270.84021,318.93771)" + style="stroke-width:0.884131"><path + d="m 0,0 c 0,-12.052 9.765,-21.815 21.815,-21.815 12.041,0 21.808,9.763 21.808,21.815 0,12.044 -9.767,21.802 -21.808,21.802 C 9.765,21.802 0,12.044 0,0" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.884131" + id="path104" + inkscape:connector-curvature="0" /></g><g + id="g106" + transform="matrix(1.1310535,0,0,1.1310535,276.77813,317.47435)" + style="stroke-width:0.884131"><path + d="m 0,0 c 0,-7.994 6.477,-14.473 14.471,-14.473 8.002,0 14.479,6.479 14.479,14.473 0,7.994 -6.477,14.479 -14.479,14.479 C 6.477,14.479 0,7.994 0,0" + style="fill:#414042;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.884131" + id="path108" + inkscape:connector-curvature="0" /></g></g></g></g></svg> diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp index 12f030bd58..be69b2e5da 100644 --- a/platform/linuxbsd/display_server_x11.cpp +++ b/platform/linuxbsd/display_server_x11.cpp @@ -2606,7 +2606,6 @@ void DisplayServerX11::_window_changed(XEvent *event) { } #endif - print_line("DisplayServer::_window_changed: " + itos(window_id) + " rect: " + new_rect); if (!wd.rect_changed_callback.is_null()) { Rect2i r = new_rect; @@ -3833,8 +3832,6 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, u wd.position.y = xwa.y; wd.size.width = xwa.width; wd.size.height = xwa.height; - - print_line("DisplayServer::_create_window " + itos(id) + " want rect: " + p_rect + " got rect " + Rect2i(xwa.x, xwa.y, xwa.width, xwa.height)); } //set cursor diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp index 688509a979..914b3ad816 100644 --- a/scene/3d/collision_object_3d.cpp +++ b/scene/3d/collision_object_3d.cpp @@ -31,12 +31,27 @@ #include "collision_object_3d.h" #include "core/config/engine.h" -#include "mesh_instance_3d.h" #include "scene/scene_string_names.h" #include "servers/physics_server_3d.h" void CollisionObject3D::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + if (_are_collision_shapes_visible()) { + debug_shape_old_transform = get_global_transform(); + for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) { + debug_shapes_to_update.insert(E->key()); + } + _update_debug_shapes(); + } + } break; + + case NOTIFICATION_EXIT_TREE: { + if (debug_shapes_count > 0) { + _clear_debug_shapes(); + } + } break; + case NOTIFICATION_ENTER_WORLD: { if (area) { PhysicsServer3D::get_singleton()->area_set_transform(rid, get_global_transform()); @@ -62,6 +77,8 @@ void CollisionObject3D::_notification(int p_what) { PhysicsServer3D::get_singleton()->body_set_state(rid, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform()); } + _on_transform_changed(); + } break; case NOTIFICATION_VISIBILITY_CHANGED: { _update_pickable(); @@ -75,11 +92,6 @@ void CollisionObject3D::_notification(int p_what) { } } break; - case NOTIFICATION_PREDELETE: { - if (debug_shape_count > 0) { - _clear_debug_shapes(); - } - } break; } } @@ -175,6 +187,33 @@ void CollisionObject3D::_update_pickable() { } } +bool CollisionObject3D::_are_collision_shapes_visible() { + return is_inside_tree() && get_tree()->is_debugging_collisions_hint() && !Engine::get_singleton()->is_editor_hint(); +} + +void CollisionObject3D::_update_shape_data(uint32_t p_owner) { + if (_are_collision_shapes_visible()) { + if (debug_shapes_to_update.is_empty()) { + callable_mp(this, &CollisionObject3D::_update_debug_shapes).call_deferred({}, 0); + } + debug_shapes_to_update.insert(p_owner); + } +} + +void CollisionObject3D::_shape_changed(const Ref<Shape3D> &p_shape) { + for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) { + ShapeData &shapedata = E->get(); + ShapeData::ShapeBase *shapes = shapedata.shapes.ptrw(); + for (int i = 0; i < shapedata.shapes.size(); i++) { + ShapeData::ShapeBase &s = shapes[i]; + if (s.shape == p_shape && s.debug_shape.is_valid()) { + Ref<Mesh> mesh = s.shape->get_debug_mesh(); + RS::get_singleton()->instance_set_base(s.debug_shape, mesh->get_rid()); + } + } + } +} + void CollisionObject3D::_update_debug_shapes() { for (Set<uint32_t>::Element *shapedata_idx = debug_shapes_to_update.front(); shapedata_idx; shapedata_idx = shapedata_idx->next()) { if (shapes.has(shapedata_idx->get())) { @@ -182,23 +221,30 @@ void CollisionObject3D::_update_debug_shapes() { ShapeData::ShapeBase *shapes = shapedata.shapes.ptrw(); for (int i = 0; i < shapedata.shapes.size(); i++) { ShapeData::ShapeBase &s = shapes[i]; - if (s.debug_shape) { - s.debug_shape->queue_delete(); - s.debug_shape = nullptr; - --debug_shape_count; - } if (s.shape.is_null() || shapedata.disabled) { + if (s.debug_shape.is_valid()) { + RS::get_singleton()->free(s.debug_shape); + s.debug_shape = RID(); + --debug_shapes_count; + } continue; } + if (s.debug_shape.is_null()) { + s.debug_shape = RS::get_singleton()->instance_create(); + RS::get_singleton()->instance_set_scenario(s.debug_shape, get_world_3d()->get_scenario()); + + if (!s.shape->is_connected("changed", callable_mp(this, &CollisionObject3D::_shape_changed))) { + s.shape->connect("changed", callable_mp(this, &CollisionObject3D::_shape_changed), + varray(s.shape), CONNECT_DEFERRED); + } + + ++debug_shapes_count; + } + Ref<Mesh> mesh = s.shape->get_debug_mesh(); - MeshInstance3D *mi = memnew(MeshInstance3D); - mi->set_transform(shapedata.xform); - mi->set_mesh(mesh); - add_child(mi); - mi->force_update_transform(); - s.debug_shape = mi; - ++debug_shape_count; + RS::get_singleton()->instance_set_base(s.debug_shape, mesh->get_rid()); + RS::get_singleton()->instance_set_transform(s.debug_shape, get_global_transform() * shapedata.xform); } } } @@ -211,23 +257,28 @@ void CollisionObject3D::_clear_debug_shapes() { ShapeData::ShapeBase *shapes = shapedata.shapes.ptrw(); for (int i = 0; i < shapedata.shapes.size(); i++) { ShapeData::ShapeBase &s = shapes[i]; - if (s.debug_shape) { - s.debug_shape->queue_delete(); - s.debug_shape = nullptr; - --debug_shape_count; + if (s.debug_shape.is_valid()) { + RS::get_singleton()->free(s.debug_shape); + s.debug_shape = RID(); + if (s.shape.is_valid() && s.shape->is_connected("changed", callable_mp(this, &CollisionObject3D::_update_shape_data))) { + s.shape->disconnect("changed", callable_mp(this, &CollisionObject3D::_update_shape_data)); + } } } } - - debug_shape_count = 0; + debug_shapes_count = 0; } -void CollisionObject3D::_update_shape_data(uint32_t p_owner) { - if (is_inside_tree() && get_tree()->is_debugging_collisions_hint() && !Engine::get_singleton()->is_editor_hint()) { - if (debug_shapes_to_update.is_empty()) { - call_deferred("_update_debug_shapes"); +void CollisionObject3D::_on_transform_changed() { + if (debug_shapes_count > 0 && !debug_shape_old_transform.is_equal_approx(get_global_transform())) { + debug_shape_old_transform = get_global_transform(); + for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) { + ShapeData &shapedata = E->get(); + const ShapeData::ShapeBase *shapes = shapedata.shapes.ptr(); + for (int i = 0; i < shapedata.shapes.size(); i++) { + RS::get_singleton()->instance_set_transform(shapes[i].debug_shape, debug_shape_old_transform * shapedata.xform); + } } - debug_shapes_to_update.insert(p_owner); } } @@ -270,8 +321,6 @@ void CollisionObject3D::_bind_methods() { ClassDB::bind_method(D_METHOD("shape_owner_clear_shapes", "owner_id"), &CollisionObject3D::shape_owner_clear_shapes); ClassDB::bind_method(D_METHOD("shape_find_owner", "shape_index"), &CollisionObject3D::shape_find_owner); - ClassDB::bind_method(D_METHOD("_update_debug_shapes"), &CollisionObject3D::_update_debug_shapes); - BIND_VMETHOD(MethodInfo("_input_event", PropertyInfo(Variant::OBJECT, "camera"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "click_position"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx"))); ADD_SIGNAL(MethodInfo("input_event", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "click_position"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx"))); @@ -316,7 +365,11 @@ void CollisionObject3D::shape_owner_set_disabled(uint32_t p_owner, bool p_disabl ERR_FAIL_COND(!shapes.has(p_owner)); ShapeData &sd = shapes[p_owner]; + if (sd.disabled == p_disabled) { + return; + } sd.disabled = p_disabled; + for (int i = 0; i < sd.shapes.size(); i++) { if (area) { PhysicsServer3D::get_singleton()->area_set_shape_disabled(rid, sd.shapes[i].index, p_disabled); @@ -421,7 +474,7 @@ void CollisionObject3D::shape_owner_remove_shape(uint32_t p_owner, int p_shape) ERR_FAIL_COND(!shapes.has(p_owner)); ERR_FAIL_INDEX(p_shape, shapes[p_owner].shapes.size()); - const ShapeData::ShapeBase &s = shapes[p_owner].shapes[p_shape]; + ShapeData::ShapeBase &s = shapes[p_owner].shapes.write[p_shape]; int index_to_remove = s.index; if (area) { @@ -430,8 +483,12 @@ void CollisionObject3D::shape_owner_remove_shape(uint32_t p_owner, int p_shape) PhysicsServer3D::get_singleton()->body_remove_shape(rid, index_to_remove); } - if (s.debug_shape) { - s.debug_shape->queue_delete(); + if (s.debug_shape.is_valid()) { + RS::get_singleton()->free(s.debug_shape); + if (s.shape.is_valid() && s.shape->is_connected("changed", callable_mp(this, &CollisionObject3D::_shape_changed))) { + s.shape->disconnect("changed", callable_mp(this, &CollisionObject3D::_shape_changed)); + } + --debug_shapes_count; } shapes[p_owner].shapes.remove(p_shape); diff --git a/scene/3d/collision_object_3d.h b/scene/3d/collision_object_3d.h index e3901979d3..7ff3c5efde 100644 --- a/scene/3d/collision_object_3d.h +++ b/scene/3d/collision_object_3d.h @@ -48,7 +48,7 @@ class CollisionObject3D : public Node3D { Object *owner = nullptr; Transform xform; struct ShapeBase { - Node *debug_shape = nullptr; + RID debug_shape; Ref<Shape3D> shape; int index = 0; }; @@ -65,25 +65,30 @@ class CollisionObject3D : public Node3D { bool ray_pickable = true; Set<uint32_t> debug_shapes_to_update; - int debug_shape_count = 0; + int debug_shapes_count = 0; + Transform debug_shape_old_transform; void _update_pickable(); + bool _are_collision_shapes_visible(); void _update_shape_data(uint32_t p_owner); + void _shape_changed(const Ref<Shape3D> &p_shape); + void _update_debug_shapes(); + void _clear_debug_shapes(); protected: CollisionObject3D(RID p_rid, bool p_area); void _notification(int p_what); static void _bind_methods(); + + void _on_transform_changed(); + friend class Viewport; virtual void _input_event(Node *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape); virtual void _mouse_enter(); virtual void _mouse_exit(); - void _update_debug_shapes(); - void _clear_debug_shapes(); - public: void set_collision_layer(uint32_t p_layer); uint32_t get_collision_layer() const; diff --git a/scene/3d/collision_shape_3d.cpp b/scene/3d/collision_shape_3d.cpp index bec87914c0..70d9cebb83 100644 --- a/scene/3d/collision_shape_3d.cpp +++ b/scene/3d/collision_shape_3d.cpp @@ -161,12 +161,10 @@ void CollisionShape3D::set_shape(const Ref<Shape3D> &p_shape) { } if (!shape.is_null()) { shape->unregister_owner(this); - shape->disconnect("changed", callable_mp(this, &CollisionShape3D::_shape_changed)); } shape = p_shape; if (!shape.is_null()) { shape->register_owner(this); - shape->connect("changed", callable_mp(this, &CollisionShape3D::_shape_changed)); } update_gizmo(); if (parent) { @@ -176,8 +174,9 @@ void CollisionShape3D::set_shape(const Ref<Shape3D> &p_shape) { } } - if (is_inside_tree()) { - _shape_changed(); + if (is_inside_tree() && parent) { + // If this is a heightfield shape our center may have changed + _update_in_shape_owner(true); } update_configuration_warnings(); } @@ -209,10 +208,3 @@ CollisionShape3D::~CollisionShape3D() { } //RenderingServer::get_singleton()->free(indicator); } - -void CollisionShape3D::_shape_changed() { - // If this is a heightfield shape our center may have changed - if (parent) { - _update_in_shape_owner(true); - } -} diff --git a/scene/3d/collision_shape_3d.h b/scene/3d/collision_shape_3d.h index 56a4ae3039..f69c1e38eb 100644 --- a/scene/3d/collision_shape_3d.h +++ b/scene/3d/collision_shape_3d.h @@ -47,8 +47,6 @@ class CollisionShape3D : public Node3D { bool disabled = false; protected: - void _shape_changed(); - void _update_in_shape_owner(bool p_xform_only = false); protected: diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index 93d3e946fd..dd1a797568 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -292,6 +292,7 @@ void RigidBody3D::_direct_state_changed(Object *p_state) { get_script_instance()->call("_integrate_forces", state); } set_ignore_transform_notification(false); + _on_transform_changed(); if (contact_monitor) { contact_monitor->locked = true; @@ -1985,6 +1986,7 @@ void PhysicalBone3D::_direct_state_changed(Object *p_state) { set_ignore_transform_notification(true); set_global_transform(global_transform); set_ignore_transform_notification(false); + _on_transform_changed(); // Update skeleton if (parent_skeleton) { diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp index ebbb8985c9..59233708f6 100644 --- a/scene/3d/skeleton_3d.cpp +++ b/scene/3d/skeleton_3d.cpp @@ -237,53 +237,57 @@ void Skeleton3D::_notification(int p_what) { for (int i = 0; i < len; i++) { Bone &b = bonesptr[order[i]]; - if (b.global_pose_override_amount >= 0.999) { - b.pose_global = b.global_pose_override; - } else { - if (b.disable_rest) { - if (b.enabled) { - Transform pose = b.pose; - if (b.custom_pose_enable) { - pose = b.custom_pose * pose; - } - if (b.parent >= 0) { - b.pose_global = bonesptr[b.parent].pose_global * pose; - } else { - b.pose_global = pose; - } + if (b.disable_rest) { + if (b.enabled) { + Transform pose = b.pose; + if (b.custom_pose_enable) { + pose = b.custom_pose * pose; + } + if (b.parent >= 0) { + b.pose_global = bonesptr[b.parent].pose_global * pose; + b.pose_global_no_override = bonesptr[b.parent].pose_global * pose; } else { - if (b.parent >= 0) { - b.pose_global = bonesptr[b.parent].pose_global; - } else { - b.pose_global = Transform(); - } + b.pose_global = pose; + b.pose_global_no_override = pose; } - } else { - if (b.enabled) { - Transform pose = b.pose; - if (b.custom_pose_enable) { - pose = b.custom_pose * pose; - } - if (b.parent >= 0) { - b.pose_global = bonesptr[b.parent].pose_global * (b.rest * pose); - } else { - b.pose_global = b.rest * pose; - } + if (b.parent >= 0) { + b.pose_global = bonesptr[b.parent].pose_global; + b.pose_global_no_override = bonesptr[b.parent].pose_global; } else { - if (b.parent >= 0) { - b.pose_global = bonesptr[b.parent].pose_global * b.rest; - } else { - b.pose_global = b.rest; - } + b.pose_global = Transform(); + b.pose_global_no_override = Transform(); } } - if (b.global_pose_override_amount >= CMP_EPSILON) { - b.pose_global = b.pose_global.interpolate_with(b.global_pose_override, b.global_pose_override_amount); + } else { + if (b.enabled) { + Transform pose = b.pose; + if (b.custom_pose_enable) { + pose = b.custom_pose * pose; + } + if (b.parent >= 0) { + b.pose_global = bonesptr[b.parent].pose_global * (b.rest * pose); + b.pose_global_no_override = bonesptr[b.parent].pose_global * (b.rest * pose); + } else { + b.pose_global = b.rest * pose; + b.pose_global_no_override = b.rest * pose; + } + } else { + if (b.parent >= 0) { + b.pose_global = bonesptr[b.parent].pose_global * b.rest; + b.pose_global_no_override = bonesptr[b.parent].pose_global * b.rest; + } else { + b.pose_global = b.rest; + b.pose_global_no_override = b.rest; + } } } + if (b.global_pose_override_amount >= CMP_EPSILON) { + b.pose_global = b.pose_global.interpolate_with(b.global_pose_override, b.global_pose_override_amount); + } + if (b.global_pose_override_reset) { b.global_pose_override_amount = 0.0; } @@ -408,6 +412,14 @@ Transform Skeleton3D::get_bone_global_pose(int p_bone) const { return bones[p_bone].pose_global; } +Transform Skeleton3D::get_bone_global_pose_no_override(int p_bone) const { + ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform()); + if (dirty) { + const_cast<Skeleton3D *>(this)->notification(NOTIFICATION_UPDATE_SKELETON); + } + return bones[p_bone].pose_global_no_override; +} + // skeleton creation api void Skeleton3D::add_bone(const String &p_name) { ERR_FAIL_COND(p_name == "" || p_name.find(":") != -1 || p_name.find("/") != -1); @@ -912,6 +924,7 @@ void Skeleton3D::_bind_methods() { ClassDB::bind_method(D_METHOD("clear_bones_global_pose_override"), &Skeleton3D::clear_bones_global_pose_override); ClassDB::bind_method(D_METHOD("set_bone_global_pose_override", "bone_idx", "pose", "amount", "persistent"), &Skeleton3D::set_bone_global_pose_override, DEFVAL(false)); ClassDB::bind_method(D_METHOD("get_bone_global_pose", "bone_idx"), &Skeleton3D::get_bone_global_pose); + ClassDB::bind_method(D_METHOD("get_bone_global_pose_no_override", "bone_idx"), &Skeleton3D::get_bone_global_pose_no_override); ClassDB::bind_method(D_METHOD("get_bone_custom_pose", "bone_idx"), &Skeleton3D::get_bone_custom_pose); ClassDB::bind_method(D_METHOD("set_bone_custom_pose", "bone_idx", "custom_pose"), &Skeleton3D::set_bone_custom_pose); diff --git a/scene/3d/skeleton_3d.h b/scene/3d/skeleton_3d.h index 2941ac2c45..508cd7c329 100644 --- a/scene/3d/skeleton_3d.h +++ b/scene/3d/skeleton_3d.h @@ -83,6 +83,7 @@ private: Transform pose; Transform pose_global; + Transform pose_global_no_override; bool custom_pose_enable = false; Transform custom_pose; @@ -160,6 +161,7 @@ public: void set_bone_rest(int p_bone, const Transform &p_rest); Transform get_bone_rest(int p_bone) const; Transform get_bone_global_pose(int p_bone) const; + Transform get_bone_global_pose_no_override(int p_bone) const; void clear_bones_global_pose_override(); void set_bone_global_pose_override(int p_bone, const Transform &p_pose, float p_amount, bool p_persistent = false); diff --git a/scene/3d/skeleton_ik_3d.cpp b/scene/3d/skeleton_ik_3d.cpp index 898f94ccc1..bd1c202205 100644 --- a/scene/3d/skeleton_ik_3d.cpp +++ b/scene/3d/skeleton_ik_3d.cpp @@ -246,7 +246,7 @@ void FabrikInverseKinematic::make_goal(Task *p_task, const Transform &p_inverse_ p_task->end_effectors.write[0].goal_transform = p_inverse_transf * p_task->goal_global_transform; } else { // End effector in local transform - const Transform end_effector_pose(p_task->skeleton->get_bone_global_pose(p_task->end_effectors[0].tip_bone)); + const Transform end_effector_pose(p_task->skeleton->get_bone_global_pose_no_override(p_task->end_effectors[0].tip_bone)); // Update the end_effector (local transform) by blending with current pose p_task->end_effectors.write[0].goal_transform = end_effector_pose.interpolate_with(p_inverse_transf * p_task->goal_global_transform, blending_delta); @@ -270,18 +270,7 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool ove return; // Skip solving } - p_task->skeleton->set_bone_global_pose_override(p_task->chain.chain_root.bone, Transform(), 0.0, true); - - if (p_task->chain.middle_chain_item) { - p_task->skeleton->set_bone_global_pose_override(p_task->chain.middle_chain_item->bone, Transform(), 0.0, true); - } - - for (int i = 0; i < p_task->chain.tips.size(); i += 1) { - p_task->skeleton->set_bone_global_pose_override(p_task->chain.tips[i].chain_item->bone, Transform(), 0.0, true); - } - - // Update the transforms to their global poses - // (Needed to sync IK with animation) + // Update the initial root transform so its synced with any animation changes _update_chain(p_task->skeleton, &p_task->chain.chain_root); make_goal(p_task, p_task->skeleton->get_global_transform().affine_inverse(), blending_delta); @@ -298,48 +287,22 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool ove Transform new_bone_pose(ci->initial_transform); new_bone_pose.origin = ci->current_pos; - // The root bone needs to be rotated differently so it isn't frozen in place. - if (ci == &p_task->chain.chain_root && !ci->children.is_empty()) { - new_bone_pose = new_bone_pose.looking_at(ci->children[0].current_pos); - const Vector3 bone_rest_dir = p_task->skeleton->get_bone_rest(ci->children[0].bone).origin.normalized().abs(); - const Vector3 bone_rest_dir_abs = bone_rest_dir.abs(); - if (bone_rest_dir_abs.x > bone_rest_dir_abs.y && bone_rest_dir_abs.x > bone_rest_dir_abs.z) { - if (bone_rest_dir.x < 0) { - new_bone_pose.basis.rotate_local(Vector3(0, 1, 0), -Math_PI / 2.0f); - } else { - new_bone_pose.basis.rotate_local(Vector3(0, 1, 0), Math_PI / 2.0f); - } - } else if (bone_rest_dir_abs.y > bone_rest_dir_abs.x && bone_rest_dir_abs.y > bone_rest_dir_abs.z) { - if (bone_rest_dir.y < 0) { - new_bone_pose.basis.rotate_local(Vector3(1, 0, 0), Math_PI / 2.0f); - } else { - new_bone_pose.basis.rotate_local(Vector3(1, 0, 0), -Math_PI / 2.0f); - } - } else { - if (bone_rest_dir.z < 0) { - // Do nothing! - } else { - new_bone_pose.basis.rotate_local(Vector3(0, 0, 1), Math_PI); - } - } - } else { - if (!ci->children.is_empty()) { - /// Rotate basis - const Vector3 initial_ori((ci->children[0].initial_transform.origin - ci->initial_transform.origin).normalized()); - const Vector3 rot_axis(initial_ori.cross(ci->current_ori).normalized()); + if (!ci->children.is_empty()) { + /// Rotate basis + const Vector3 initial_ori((ci->children[0].initial_transform.origin - ci->initial_transform.origin).normalized()); + const Vector3 rot_axis(initial_ori.cross(ci->current_ori).normalized()); - if (rot_axis[0] != 0 && rot_axis[1] != 0 && rot_axis[2] != 0) { - const real_t rot_angle(Math::acos(CLAMP(initial_ori.dot(ci->current_ori), -1, 1))); - new_bone_pose.basis.rotate(rot_axis, rot_angle); - } + if (rot_axis[0] != 0 && rot_axis[1] != 0 && rot_axis[2] != 0) { + const real_t rot_angle(Math::acos(CLAMP(initial_ori.dot(ci->current_ori), -1, 1))); + new_bone_pose.basis.rotate(rot_axis, rot_angle); + } + } else { + // Set target orientation to tip + if (override_tip_basis) { + new_bone_pose.basis = p_task->chain.tips[0].end_effector->goal_transform.basis; } else { - // Set target orientation to tip - if (override_tip_basis) { - new_bone_pose.basis = p_task->chain.tips[0].end_effector->goal_transform.basis; - } else { - new_bone_pose.basis = new_bone_pose.basis * p_task->chain.tips[0].end_effector->goal_transform.basis; - } + new_bone_pose.basis = new_bone_pose.basis * p_task->chain.tips[0].end_effector->goal_transform.basis; } } @@ -362,7 +325,7 @@ void FabrikInverseKinematic::_update_chain(const Skeleton3D *p_sk, ChainItem *p_ return; } - p_chain_item->initial_transform = p_sk->get_bone_global_pose(p_chain_item->bone); + p_chain_item->initial_transform = p_sk->get_bone_global_pose_no_override(p_chain_item->bone); p_chain_item->current_pos = p_chain_item->initial_transform.origin; ChainItem *items = p_chain_item->children.ptrw(); diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index 44f2d38a84..2ad871ba61 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -597,9 +597,9 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { if (path.get_subname_count() == 1 && Object::cast_to<Skeleton3D>(spatial)) { Skeleton3D *sk = Object::cast_to<Skeleton3D>(spatial); + track_xform->skeleton = sk; int bone_idx = sk->find_bone(path.get_subname(0)); if (bone_idx != -1) { - track_xform->skeleton = sk; track_xform->bone_idx = bone_idx; } } @@ -1205,7 +1205,7 @@ void AnimationTree::_process_graph(float p_delta) { } else if (t->skeleton && t->bone_idx >= 0) { t->skeleton->set_bone_pose(t->bone_idx, xform); - } else { + } else if (!t->skeleton) { t->spatial->set_transform(xform); } diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index eb836b3bf7..bfd739788f 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -557,7 +557,7 @@ void LineEdit::drop_data(const Point2 &p_point, const Variant &p_data) { } Control::CursorShape LineEdit::get_cursor_shape(const Point2 &p_pos) const { - if (!text.is_empty() && is_editable() && _is_over_clear_button(p_pos)) { + if ((!text.is_empty() && is_editable() && _is_over_clear_button(p_pos)) || (!is_editable() && (!is_selecting_enabled() || text.is_empty()))) { return CURSOR_ARROW; } return Control::get_cursor_shape(p_pos); diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index ded912591f..c924f89709 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -4450,7 +4450,7 @@ Control::CursorShape TextEdit::get_cursor_shape(const Point2 &p_pos) const { return CURSOR_POINTING_HAND; } - if ((completion_active && completion_rect.has_point(p_pos))) { + if ((completion_active && completion_rect.has_point(p_pos)) || (is_readonly() && (!is_selecting_enabled() || text.size() == 0))) { return CURSOR_ARROW; } diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index d10ce584b7..7028d7aed4 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -3178,7 +3178,6 @@ void Tree::_notification(int p_what) { RID ci = get_canvas_item(); Ref<StyleBox> bg = cache.bg; - Ref<StyleBox> bg_focus = get_theme_stylebox("bg_focus"); Color font_outline_color = get_theme_color("font_outline_color"); int outline_size = get_theme_constant("outline_size"); @@ -3187,11 +3186,6 @@ void Tree::_notification(int p_what) { Size2 draw_size = get_size() - bg->get_minimum_size(); bg->draw(ci, Rect2(Point2(), get_size())); - if (has_focus()) { - RenderingServer::get_singleton()->canvas_item_add_clip_ignore(ci, true); - bg_focus->draw(ci, Rect2(Point2(), get_size())); - RenderingServer::get_singleton()->canvas_item_add_clip_ignore(ci, false); - } int tbh = _get_title_button_height(); @@ -3225,6 +3219,15 @@ void Tree::_notification(int p_what) { columns[i].text_buf->draw(ci, text_pos, cache.title_button_color); } } + + // Draw the background focus outline last, so that it is drawn in front of the section headings. + // Otherwise, section heading backgrounds can appear to be in front of the focus outline when scrolling. + if (has_focus()) { + RenderingServer::get_singleton()->canvas_item_add_clip_ignore(ci, true); + const Ref<StyleBox> bg_focus = get_theme_stylebox("bg_focus"); + bg_focus->draw(ci, Rect2(Point2(), get_size())); + RenderingServer::get_singleton()->canvas_item_add_clip_ignore(ci, false); + } } if (p_what == NOTIFICATION_THEME_CHANGED || p_what == NOTIFICATION_LAYOUT_DIRECTION_CHANGED || p_what == NOTIFICATION_TRANSLATION_CHANGED) { |