summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
Diffstat (limited to 'editor')
-rw-r--r--editor/create_dialog.cpp2
-rw-r--r--editor/editor_help.cpp95
-rw-r--r--editor/editor_node.cpp2
-rw-r--r--editor/editor_resource_preview.cpp23
-rw-r--r--editor/editor_resource_preview.h8
-rw-r--r--editor/plugins/mesh_instance_3d_editor_plugin.cpp69
-rw-r--r--editor/plugins/script_text_editor.cpp15
-rw-r--r--editor/plugins/skeleton_3d_editor_plugin.cpp63
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp2
-rw-r--r--editor/scene_tree_editor.cpp21
10 files changed, 176 insertions, 124 deletions
diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp
index fbb61a1614..b064f6aec7 100644
--- a/editor/create_dialog.cpp
+++ b/editor/create_dialog.cpp
@@ -125,7 +125,7 @@ bool CreateDialog::_should_hide_type(const String &p_type) const {
return true; // Do not show editor nodes.
}
- if (p_type == base_type) {
+ if (p_type == base_type && !EditorNode::get_editor_data().get_custom_types().has(p_type)) {
return true; // Root is already added.
}
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index dfd768d0d0..b24268ade7 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -123,37 +123,34 @@ void EditorHelp::_class_desc_select(const String &p_select) {
return;
}
- if (link.contains(".")) {
- emit_signal(SNAME("go_to_help"), topic + ":" + link.get_slice(".", 0) + ":" + link.get_slice(".", 1));
- } else {
- if (table->has(link)) {
- // Found in the current page
- class_desc->scroll_to_paragraph((*table)[link]);
- } else {
- if (topic == "class_enum") {
- // Try to find the enum in @GlobalScope
- const DocData::ClassDoc &cd = doc->class_list["@GlobalScope"];
-
- for (int i = 0; i < cd.constants.size(); i++) {
- if (cd.constants[i].enumeration == link) {
- // Found in @GlobalScope
- emit_signal(SNAME("go_to_help"), topic + ":@GlobalScope:" + link);
- break;
- }
- }
- } else if (topic == "class_constant") {
- // Try to find the constant in @GlobalScope
- const DocData::ClassDoc &cd = doc->class_list["@GlobalScope"];
-
- for (int i = 0; i < cd.constants.size(); i++) {
- if (cd.constants[i].name == link) {
- // Found in @GlobalScope
- emit_signal(SNAME("go_to_help"), topic + ":@GlobalScope:" + link);
- break;
- }
- }
+ // Case order is important here to correctly handle edge cases like Variant.Type in @GlobalScope.
+ if (table->has(link)) {
+ // Found in the current page.
+ class_desc->scroll_to_paragraph((*table)[link]);
+ } else if (topic == "class_enum") {
+ // Try to find the enum in @GlobalScope.
+ const DocData::ClassDoc &cd = doc->class_list["@GlobalScope"];
+
+ for (int i = 0; i < cd.constants.size(); i++) {
+ if (cd.constants[i].enumeration == link) {
+ // Found in @GlobalScope.
+ emit_signal(SNAME("go_to_help"), topic + ":@GlobalScope:" + link);
+ break;
}
}
+ } else if (topic == "class_constant") {
+ // Try to find the constant in @GlobalScope.
+ const DocData::ClassDoc &cd = doc->class_list["@GlobalScope"];
+
+ for (int i = 0; i < cd.constants.size(); i++) {
+ if (cd.constants[i].name == link) {
+ // Found in @GlobalScope.
+ emit_signal(SNAME("go_to_help"), topic + ":@GlobalScope:" + link);
+ break;
+ }
+ }
+ } else if (link.contains(".")) {
+ emit_signal(SNAME("go_to_help"), topic + ":" + link.get_slice(".", 0) + ":" + link.get_slice(".", 1));
}
} else if (p_select.begins_with("http")) {
OS::get_singleton()->shell_open(p_select);
@@ -339,7 +336,7 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
description_line = 0;
if (p_class == edited_class) {
- return OK; //already there
+ return OK; // Already there.
}
edited_class = p_class;
@@ -885,7 +882,7 @@ void EditorHelp::_update_doc() {
data_type_names["style"] = TTR("Styles");
for (int i = 0; i < cd.theme_properties.size(); i++) {
- theme_property_line[cd.theme_properties[i].name] = class_desc->get_line_count() - 2; //gets overridden if description
+ theme_property_line[cd.theme_properties[i].name] = class_desc->get_line_count() - 2; // Gets overridden if description.
if (theme_data_type != cd.theme_properties[i].data_type) {
theme_data_type = cd.theme_properties[i].data_type;
@@ -970,7 +967,7 @@ void EditorHelp::_update_doc() {
class_desc->push_indent(1);
for (int i = 0; i < cd.signals.size(); i++) {
- signal_line[cd.signals[i].name] = class_desc->get_line_count() - 2; //gets overridden if description
+ signal_line[cd.signals[i].name] = class_desc->get_line_count() - 2; // Gets overridden if description.
class_desc->push_font(doc_code_font); // monofont
class_desc->push_color(headline_color);
@@ -1100,7 +1097,7 @@ void EditorHelp::_update_doc() {
enumValuesContainer[enum_list[i].name] = enumStartingLine;
}
- // Add the enum constant line to the constant_line map so we can locate it as a constant
+ // Add the enum constant line to the constant_line map so we can locate it as a constant.
constant_line[enum_list[i].name] = class_desc->get_line_count() - 2;
class_desc->push_font(doc_code_font);
@@ -1417,7 +1414,7 @@ void EditorHelp::_help_callback(const String &p_topic) {
name = p_topic.get_slice(":", 2);
}
- _request_help(clss); //first go to class
+ _request_help(clss); // First go to class.
int line = 0;
@@ -1486,7 +1483,7 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) {
String bbcode = p_bbcode.dedent().replace("\t", "").replace("\r", "").strip_edges();
- // Select the correct code examples
+ // Select the correct code examples.
switch ((int)EDITOR_GET("text_editor/help/class_reference_examples")) {
case 0: // GDScript
bbcode = bbcode.replace("[gdscript]", "[codeblock]");
@@ -1531,13 +1528,13 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) {
break;
}
- // Remove codeblocks (they would be printed otherwise)
+ // Remove codeblocks (they would be printed otherwise).
bbcode = bbcode.replace("[codeblocks]\n", "");
bbcode = bbcode.replace("\n[/codeblocks]", "");
bbcode = bbcode.replace("[codeblocks]", "");
bbcode = bbcode.replace("[/codeblocks]", "");
- // remove extra new lines around code blocks
+ // Remove extra new lines around code blocks.
bbcode = bbcode.replace("[codeblock]\n", "[codeblock]");
bbcode = bbcode.replace("\n[/codeblock]", "[/codeblock]");
@@ -1561,7 +1558,7 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) {
}
if (brk_pos == bbcode.length()) {
- break; //nothing else to add
+ break; // Nothing else to add.
}
int brk_end = bbcode.find("]", brk_pos + 1);
@@ -1627,45 +1624,45 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) {
pos = brk_end + 1;
} else if (tag == "b") {
- //use bold font
+ // Use bold font.
p_rt->push_font(doc_bold_font);
pos = brk_end + 1;
tag_stack.push_front(tag);
} else if (tag == "i") {
- //use italics font
+ // Use italics font.
p_rt->push_font(doc_italic_font);
pos = brk_end + 1;
tag_stack.push_front(tag);
} else if (tag == "code" || tag == "codeblock") {
- //use monospace font
+ // Use monospace font.
p_rt->push_font(doc_code_font);
p_rt->push_color(code_color);
code_tag = true;
pos = brk_end + 1;
tag_stack.push_front(tag);
} else if (tag == "kbd") {
- //use keyboard font with custom color
+ // Use keyboard font with custom color.
p_rt->push_font(doc_kbd_font);
p_rt->push_color(kbd_color);
- code_tag = true; // though not strictly a code tag, logic is similar
+ code_tag = true; // Though not strictly a code tag, logic is similar.
pos = brk_end + 1;
tag_stack.push_front(tag);
} else if (tag == "center") {
- //align to center
+ // Align to center.
p_rt->push_paragraph(HORIZONTAL_ALIGNMENT_CENTER, Control::TEXT_DIRECTION_AUTO, "");
pos = brk_end + 1;
tag_stack.push_front(tag);
} else if (tag == "br") {
- //force a line break
+ // Force a line break.
p_rt->add_newline();
pos = brk_end + 1;
} else if (tag == "u") {
- //use underline
+ // Use underline.
p_rt->push_underline();
pos = brk_end + 1;
tag_stack.push_front(tag);
} else if (tag == "s") {
- //use strikethrough
+ // Use strikethrough.
p_rt->push_strikethrough();
pos = brk_end + 1;
tag_stack.push_front(tag);
@@ -1741,7 +1738,7 @@ void EditorHelp::_wait_for_thread() {
void EditorHelp::_gen_doc_thread(void *p_udata) {
DocTools compdoc;
compdoc.load_compressed(_doc_data_compressed, _doc_data_compressed_size, _doc_data_uncompressed_size);
- doc->merge_from(compdoc); //ensure all is up to date
+ doc->merge_from(compdoc); // Ensure all is up to date.
}
static bool doc_gen_use_threads = true;
@@ -1935,7 +1932,7 @@ void EditorHelpBit::_meta_clicked(String p_select) {
String m = p_select.substr(1, p_select.length());
if (m.contains(".")) {
- _go_to_help("class_method:" + m.get_slice(".", 0) + ":" + m.get_slice(".", 0)); //must go somewhere else
+ _go_to_help("class_method:" + m.get_slice(".", 0) + ":" + m.get_slice(".", 0)); // Must go somewhere else.
}
}
}
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index efbdf91d2f..f31ad3a68d 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -623,8 +623,6 @@ void EditorNode::_notification(int p_what) {
ResourceImporterTexture::get_singleton()->update_imports();
- // if using a main thread only renderer, we need to update the resource previews
- EditorResourcePreview::get_singleton()->update();
} break;
case NOTIFICATION_ENTER_TREE: {
diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp
index 6d5b20e591..dffb378408 100644
--- a/editor/editor_resource_preview.cpp
+++ b/editor/editor_resource_preview.cpp
@@ -430,12 +430,8 @@ void EditorResourcePreview::check_for_invalidation(const String &p_path) {
}
void EditorResourcePreview::start() {
- if (OS::get_singleton()->get_render_main_thread_mode() == OS::RENDER_ANY_THREAD) {
- ERR_FAIL_COND_MSG(thread.is_started(), "Thread already started.");
- thread.start(_thread_func, this);
- } else {
- _mainthread_only = true;
- }
+ ERR_FAIL_COND_MSG(thread.is_started(), "Thread already started.");
+ thread.start(_thread_func, this);
}
void EditorResourcePreview::stop() {
@@ -458,18 +454,3 @@ EditorResourcePreview::EditorResourcePreview() {
EditorResourcePreview::~EditorResourcePreview() {
stop();
}
-
-void EditorResourcePreview::update() {
- if (!_mainthread_only) {
- return;
- }
-
- if (!exit.is_set()) {
- // no need to even lock the mutex if the size is zero
- // there is no problem if queue.size() is wrong, even if
- // there was a race condition.
- if (queue.size()) {
- _iterate();
- }
- }
-}
diff --git a/editor/editor_resource_preview.h b/editor/editor_resource_preview.h
index 769340c36f..4e91df8e08 100644
--- a/editor/editor_resource_preview.h
+++ b/editor/editor_resource_preview.h
@@ -81,11 +81,6 @@ class EditorResourcePreview : public Node {
SafeFlag exit;
SafeFlag exited;
- // when running from GLES, we want to run the previews
- // in the main thread using an update, rather than create
- // a separate thread
- bool _mainthread_only = false;
-
struct Item {
Ref<Texture2D> preview;
Ref<Texture2D> small_preview;
@@ -125,9 +120,6 @@ public:
void start();
void stop();
- // for single threaded mode
- void update();
-
EditorResourcePreview();
~EditorResourcePreview();
};
diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.cpp b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
index d33803213a..1c75591b34 100644
--- a/editor/plugins/mesh_instance_3d_editor_plugin.cpp
+++ b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
@@ -77,12 +77,14 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
StaticBody3D *body = memnew(StaticBody3D);
body->add_child(cshape, true);
- Node *owner = node == get_tree()->get_edited_scene_root() ? node : node->get_owner();
+ Node *owner = get_tree()->get_edited_scene_root();
ur->create_action(TTR("Create Static Trimesh Body"));
ur->add_do_method(node, "add_child", body, true);
ur->add_do_method(body, "set_owner", owner);
ur->add_do_method(cshape, "set_owner", owner);
+ ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", body);
+ ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", cshape);
ur->add_do_reference(body);
ur->add_undo_method(node, "remove_child", body);
ur->commit_action();
@@ -112,11 +114,13 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
StaticBody3D *body = memnew(StaticBody3D);
body->add_child(cshape, true);
- Node *owner = instance == get_tree()->get_edited_scene_root() ? instance : instance->get_owner();
+ Node *owner = get_tree()->get_edited_scene_root();
ur->add_do_method(instance, "add_child", body, true);
ur->add_do_method(body, "set_owner", owner);
ur->add_do_method(cshape, "set_owner", owner);
+ ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", body);
+ ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", cshape);
ur->add_do_reference(body);
ur->add_undo_method(instance, "remove_child", body);
}
@@ -141,7 +145,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
cshape->set_shape(shape);
cshape->set_transform(node->get_transform());
- Node *owner = node->get_owner();
+ Node *owner = get_tree()->get_edited_scene_root();
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
@@ -150,6 +154,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
ur->add_do_method(node->get_parent(), "add_child", cshape, true);
ur->add_do_method(node->get_parent(), "move_child", cshape, node->get_index() + 1);
ur->add_do_method(cshape, "set_owner", owner);
+ ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", cshape);
ur->add_do_reference(cshape);
ur->add_undo_method(node->get_parent(), "remove_child", cshape);
ur->commit_action();
@@ -184,11 +189,12 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
cshape->set_shape(shape);
cshape->set_transform(node->get_transform());
- Node *owner = node->get_owner();
+ Node *owner = get_tree()->get_edited_scene_root();
ur->add_do_method(node->get_parent(), "add_child", cshape, true);
ur->add_do_method(node->get_parent(), "move_child", cshape, node->get_index() + 1);
ur->add_do_method(cshape, "set_owner", owner);
+ ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", cshape);
ur->add_do_reference(cshape);
ur->add_undo_method(node->get_parent(), "remove_child", cshape);
@@ -217,14 +223,17 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
for (int i = 0; i < shapes.size(); i++) {
CollisionShape3D *cshape = memnew(CollisionShape3D);
+ cshape->set_name("CollisionShape3D");
+
cshape->set_shape(shapes[i]);
cshape->set_transform(node->get_transform());
- Node *owner = node->get_owner();
+ Node *owner = get_tree()->get_edited_scene_root();
ur->add_do_method(node->get_parent(), "add_child", cshape);
ur->add_do_method(node->get_parent(), "move_child", cshape, node->get_index() + 1);
ur->add_do_method(cshape, "set_owner", owner);
+ ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", cshape);
ur->add_do_reference(cshape);
ur->add_undo_method(node->get_parent(), "remove_child", cshape);
}
@@ -243,13 +252,14 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
NavigationRegion3D *nmi = memnew(NavigationRegion3D);
nmi->set_navigation_mesh(nmesh);
- Node *owner = node == get_tree()->get_edited_scene_root() ? node : node->get_owner();
+ Node *owner = get_tree()->get_edited_scene_root();
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
ur->create_action(TTR("Create Navigation Mesh"));
ur->add_do_method(node, "add_child", nmi, true);
ur->add_do_method(nmi, "set_owner", owner);
+ ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", nmi);
ur->add_do_reference(nmi);
ur->add_undo_method(node, "remove_child", nmi);
@@ -267,13 +277,52 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
return;
}
- Error err = mesh2->lightmap_unwrap(node->get_global_transform());
+ String path = mesh2->get_path();
+ int srpos = path.find("::");
+ if (srpos != -1) {
+ String base = path.substr(0, srpos);
+ if (ResourceLoader::get_resource_type(base) == "PackedScene") {
+ if (!get_tree()->get_edited_scene_root() || get_tree()->get_edited_scene_root()->get_scene_file_path() != base) {
+ err_dialog->set_text(TTR("Mesh cannot unwrap UVs because it does not belong to the edited scene. Make it unique first."));
+ err_dialog->popup_centered();
+ return;
+ }
+ } else {
+ if (FileAccess::exists(path + ".import")) {
+ err_dialog->set_text(TTR("Mesh cannot unwrap UVs because it belongs to another resource which was imported from another file type. Make it unique first."));
+ err_dialog->popup_centered();
+ return;
+ }
+ }
+ } else {
+ if (FileAccess::exists(path + ".import")) {
+ err_dialog->set_text(TTR("Mesh cannot unwrap UVs because it was imported from another file type. Make it unique first."));
+ err_dialog->popup_centered();
+ return;
+ }
+ }
+
+ Ref<ArrayMesh> unwrapped_mesh = mesh2->duplicate(false);
+
+ Error err = unwrapped_mesh->lightmap_unwrap(node->get_global_transform());
if (err != OK) {
err_dialog->set_text(TTR("UV Unwrap failed, mesh may not be manifold?"));
err_dialog->popup_centered();
return;
}
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Unwrap UV2"));
+
+ ur->add_do_method(node, "set_mesh", unwrapped_mesh);
+ ur->add_do_reference(node);
+ ur->add_do_reference(mesh2.ptr());
+
+ ur->add_undo_method(node, "set_mesh", mesh2);
+ ur->add_undo_reference(unwrapped_mesh.ptr());
+
+ ur->commit_action();
+
} break;
case MENU_OPTION_DEBUG_UV1: {
Ref<Mesh> mesh2 = node->get_mesh();
@@ -418,10 +467,7 @@ void MeshInstance3DEditor::_create_outline_mesh() {
MeshInstance3D *mi = memnew(MeshInstance3D);
mi->set_mesh(mesho);
- Node *owner = node->get_owner();
- if (get_tree()->get_edited_scene_root() == node) {
- owner = node;
- }
+ Node *owner = get_tree()->get_edited_scene_root();
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
@@ -429,6 +475,7 @@ void MeshInstance3DEditor::_create_outline_mesh() {
ur->add_do_method(node, "add_child", mi, true);
ur->add_do_method(mi, "set_owner", owner);
+ ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", mi);
ur->add_do_reference(mi);
ur->add_undo_method(node, "remove_child", mi);
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index 981881fb9b..bed7739239 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -855,6 +855,21 @@ void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_c
emit_signal(SNAME("go_to_help"), "class_method:" + result.class_name + ":" + result.class_member);
} break;
+ case ScriptLanguage::LOOKUP_RESULT_CLASS_SIGNAL: {
+ StringName cname = result.class_name;
+
+ while (true) {
+ if (ClassDB::has_signal(cname, result.class_member)) {
+ result.class_name = cname;
+ cname = ClassDB::get_parent_class(cname);
+ } else {
+ break;
+ }
+ }
+
+ emit_signal(SNAME("go_to_help"), "class_signal:" + result.class_name + ":" + result.class_member);
+
+ } break;
case ScriptLanguage::LOOKUP_RESULT_CLASS_ENUM: {
StringName cname = result.class_name;
StringName success;
diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp
index 1b703a097c..26a982a091 100644
--- a/editor/plugins/skeleton_3d_editor_plugin.cpp
+++ b/editor/plugins/skeleton_3d_editor_plugin.cpp
@@ -357,7 +357,7 @@ void Skeleton3DEditor::pose_to_rest(const bool p_all_bones) {
void Skeleton3DEditor::create_physical_skeleton() {
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
ERR_FAIL_COND(!get_tree());
- Node *owner = skeleton == get_tree()->get_edited_scene_root() ? skeleton : skeleton->get_owner();
+ Node *owner = get_tree()->get_edited_scene_root();
const int bc = skeleton->get_bone_count();
@@ -368,37 +368,47 @@ void Skeleton3DEditor::create_physical_skeleton() {
Vector<BoneInfo> bones_infos;
bones_infos.resize(bc);
- for (int bone_id = 0; bc > bone_id; ++bone_id) {
- const int parent = skeleton->get_bone_parent(bone_id);
+ if (bc > 0) {
+ ur->create_action(TTR("Create physical bones"), UndoRedo::MERGE_ALL);
+ for (int bone_id = 0; bc > bone_id; ++bone_id) {
+ const int parent = skeleton->get_bone_parent(bone_id);
- if (parent < 0) {
- bones_infos.write[bone_id].relative_rest = skeleton->get_bone_rest(bone_id);
-
- } else {
- const int parent_parent = skeleton->get_bone_parent(parent);
-
- bones_infos.write[bone_id].relative_rest = bones_infos[parent].relative_rest * skeleton->get_bone_rest(bone_id);
-
- // Create physical bone on parent.
- if (!bones_infos[parent].physical_bone) {
- bones_infos.write[parent].physical_bone = create_physical_bone(parent, bone_id, bones_infos);
-
- ur->create_action(TTR("Create physical bones"), UndoRedo::MERGE_ALL);
- ur->add_do_method(skeleton, "add_child", bones_infos[parent].physical_bone);
- ur->add_do_reference(bones_infos[parent].physical_bone);
- ur->add_undo_method(skeleton, "remove_child", bones_infos[parent].physical_bone);
- ur->commit_action();
+ if (parent < 0) {
+ bones_infos.write[bone_id].relative_rest = skeleton->get_bone_rest(bone_id);
+ } else {
+ const int parent_parent = skeleton->get_bone_parent(parent);
+
+ bones_infos.write[bone_id].relative_rest = bones_infos[parent].relative_rest * skeleton->get_bone_rest(bone_id);
+
+ // Create physical bone on parent.
+ if (!bones_infos[parent].physical_bone) {
+ PhysicalBone3D *physical_bone = create_physical_bone(parent, bone_id, bones_infos);
+ if (physical_bone && physical_bone->get_child(0)) {
+ CollisionShape3D *collision_shape = Object::cast_to<CollisionShape3D>(physical_bone->get_child(0));
+ if (collision_shape) {
+ bones_infos.write[parent].physical_bone = physical_bone;
+
+ ur->add_do_method(skeleton, "add_child", physical_bone);
+ ur->add_do_method(physical_bone, "set_owner", owner);
+ ur->add_do_method(collision_shape, "set_owner", owner);
+ ur->add_do_property(physical_bone, "bone_name", skeleton->get_bone_name(parent));
+
+ // Create joint between parent of parent.
+ if (parent_parent != -1) {
+ ur->add_do_method(physical_bone, "set_joint_type", PhysicalBone3D::JOINT_TYPE_PIN);
+ }
- bones_infos[parent].physical_bone->set_bone_name(skeleton->get_bone_name(parent));
- bones_infos[parent].physical_bone->set_owner(owner);
- bones_infos[parent].physical_bone->get_child(0)->set_owner(owner); // set shape owner
+ ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", physical_bone);
+ ur->add_do_method(Node3DEditor::get_singleton(), "_request_gizmo", collision_shape);
- // Create joint between parent of parent.
- if (-1 != parent_parent) {
- bones_infos[parent].physical_bone->set_joint_type(PhysicalBone3D::JOINT_TYPE_PIN);
+ ur->add_do_reference(physical_bone);
+ ur->add_undo_method(skeleton, "remove_child", physical_bone);
+ }
+ }
}
}
}
+ ur->commit_action();
}
}
@@ -414,6 +424,7 @@ PhysicalBone3D *Skeleton3DEditor::create_physical_bone(int bone_id, int bone_chi
CollisionShape3D *bone_shape = memnew(CollisionShape3D);
bone_shape->set_shape(bone_shape_capsule);
+ bone_shape->set_name("CollisionShape3D");
Transform3D capsule_transform;
capsule_transform.basis = Basis(Vector3(1, 0, 0), Vector3(0, 0, 1), Vector3(0, -1, 0));
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index b0844828df..ff35e3e6f3 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -4801,7 +4801,7 @@ VisualShaderEditor::VisualShaderEditor() {
///////////////////////////////////////
preview_window = memnew(Window);
- preview_window->set_title(TTR("Generated shader code"));
+ preview_window->set_title(TTR("Generated Shader Code"));
preview_window->set_visible(preview_showed);
preview_window->connect("close_requested", callable_mp(this, &VisualShaderEditor::_preview_close_requested));
preview_window->connect("size_changed", callable_mp(this, &VisualShaderEditor::_preview_size_changed));
diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp
index b588c01bce..4efd22aa1e 100644
--- a/editor/scene_tree_editor.cpp
+++ b/editor/scene_tree_editor.cpp
@@ -279,15 +279,26 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent, bool p_scroll
Array arr;
arr.push_back(num_connections);
msg_temp += TTRN("Node has one connection.", "Node has {num} connections.", num_connections).format(arr, "{num}");
- msg_temp += " ";
+ if (num_groups >= 1) {
+ msg_temp += "\n";
+ }
}
if (num_groups >= 1) {
- Array arr;
- arr.push_back(num_groups);
- msg_temp += TTRN("Node is in one group.", "Node is in {num} groups.", num_groups).format(arr, "{num}");
+ msg_temp += TTRN("Node is in this group:", "Node is in the following groups:", num_groups) + "\n";
+
+ List<GroupInfo> groups;
+ p_node->get_groups(&groups);
+ for (const GroupInfo &E : groups) {
+ if (E.persistent) {
+ msg_temp += String::utf8("• ") + String(E.name) + "\n";
+ }
+ }
}
if (num_connections >= 1 || num_groups >= 1) {
- msg_temp += "\n" + TTR("Click to show signals dock.");
+ if (num_groups < 1) {
+ msg_temp += "\n";
+ }
+ msg_temp += TTR("Click to show signals dock.");
}
Ref<Texture2D> icon_temp;