diff --git a/editor/scene/canvas_item_editor_plugin.cpp b/editor/scene/canvas_item_editor_plugin.cpp index 75d3f81938..c939e3a142 100644 --- a/editor/scene/canvas_item_editor_plugin.cpp +++ b/editor/scene/canvas_item_editor_plugin.cpp @@ -6290,42 +6290,59 @@ bool CanvasItemEditorViewport::_cyclical_dependency_exists(const String &p_targe return false; } +void CanvasItemEditorViewport::_add_node_to_scene(Node *p_parent, Node *p_child, const Vector2 &p_target_position) { + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); + if (p_parent) { + undo_redo->add_do_method(p_parent, "add_child", p_child, true); + undo_redo->add_do_method(p_child, "set_owner", EditorNode::get_singleton()->get_edited_scene()); + undo_redo->add_do_reference(p_child); + undo_redo->add_undo_method(p_parent, "remove_child", p_child); + + const String new_name = p_parent->validate_child_name(p_child); + EditorDebuggerNode *ed = EditorDebuggerNode::get_singleton(); + undo_redo->add_do_method(ed, "live_debug_create_node", EditorNode::get_singleton()->get_edited_scene()->get_path_to(p_parent), p_child->get_class(), new_name); + undo_redo->add_undo_method(ed, "live_debug_remove_node", NodePath(String(EditorNode::get_singleton()->get_edited_scene()->get_path_to(p_parent)) + "/" + new_name)); + } else { // If no parent is selected, set as root node of the scene. + undo_redo->add_do_method(EditorNode::get_singleton(), "set_edited_scene", p_child); + undo_redo->add_do_reference(p_child); + undo_redo->add_undo_method(EditorNode::get_singleton(), "set_edited_scene", (Object *)nullptr); + } + // There's nothing to be used as source position, so snapping will work as absolute if enabled. + Vector2 target_position = canvas_item_editor->snap_point(p_target_position); + CanvasItem *parent_ci = Object::cast_to(p_parent); + // Set position via undo_redo for proper live editing support. + undo_redo->add_do_method(p_child, "set_position", parent_ci ? parent_ci->get_global_transform().affine_inverse().xform(target_position) : target_position); + + EditorSelection *editor_selection = EditorNode::get_singleton()->get_editor_selection(); + undo_redo->add_do_method(editor_selection, "add_node", p_child); +} + void CanvasItemEditorViewport::_create_texture_node(Node *p_parent, Node *p_child, const String &p_path, const Point2 &p_point) { // Adjust casing according to project setting. The file name is expected to be in snake_case, but will work for others. const String &node_name = Node::adjust_name_casing(p_path.get_file().get_basename()); if (!node_name.is_empty()) { p_child->set_name(node_name); } + // Compute the global position. + Transform2D xform = canvas_item_editor->get_canvas_transform(); + Point2 target_position = xform.affine_inverse().xform(p_point); - EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); + // Adjust position for Control and TouchScreenButton. Ref texture = ResourceCache::get_ref(p_path); - - if (p_parent) { - undo_redo->add_do_method(p_parent, "add_child", p_child, true); - undo_redo->add_do_method(p_child, "set_owner", EditorNode::get_singleton()->get_edited_scene()); - undo_redo->add_do_reference(p_child); - undo_redo->add_undo_method(p_parent, "remove_child", p_child); - } else { // If no parent is selected, set as root node of the scene. - undo_redo->add_do_method(EditorNode::get_singleton(), "set_edited_scene", p_child); - undo_redo->add_do_method(p_child, "set_owner", EditorNode::get_singleton()->get_edited_scene()); - undo_redo->add_do_reference(p_child); - undo_redo->add_undo_method(EditorNode::get_singleton(), "set_edited_scene", (Object *)nullptr); - } - - if (p_parent) { - String new_name = p_parent->validate_child_name(p_child); - EditorDebuggerNode *ed = EditorDebuggerNode::get_singleton(); - undo_redo->add_do_method(ed, "live_debug_create_node", EditorNode::get_singleton()->get_edited_scene()->get_path_to(p_parent), p_child->get_class(), new_name); - undo_redo->add_undo_method(ed, "live_debug_remove_node", NodePath(String(EditorNode::get_singleton()->get_edited_scene()->get_path_to(p_parent)) + "/" + new_name)); + if (Object::cast_to(p_child) || Object::cast_to(p_child) || Object::cast_to(p_child)) { + target_position -= texture->get_size() / 2; } + _add_node_to_scene(p_parent, p_child, target_position); + // Use undo_redo for properties to support live editing. + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); if (Object::cast_to(p_child) || Object::cast_to(p_child)) { undo_redo->add_do_property(p_child, "texture_normal", texture); } else { undo_redo->add_do_property(p_child, "texture", texture); } - // make visible for certain node type + // Make visible for certain node type. if (Object::cast_to(p_child)) { Size2 texture_size = texture->get_size(); undo_redo->add_do_property(p_child, "size", texture_size); @@ -6339,28 +6356,10 @@ void CanvasItemEditorViewport::_create_texture_node(Node *p_parent, Node *p_chil }; undo_redo->add_do_property(p_child, "polygon", list); } - - // Compute the global position - Transform2D xform = canvas_item_editor->get_canvas_transform(); - Point2 target_position = xform.affine_inverse().xform(p_point); - - // Adjust position for Control and TouchScreenButton - if (Object::cast_to(p_child) || Object::cast_to(p_child)) { - target_position -= texture->get_size() / 2; - } - - // There's nothing to be used as source position, so snapping will work as absolute if enabled. - target_position = canvas_item_editor->snap_point(target_position); - - CanvasItem *parent_ci = Object::cast_to(p_parent); - Point2 local_target_pos = parent_ci ? parent_ci->get_global_transform().affine_inverse().xform(target_position) : target_position; - - undo_redo->add_do_method(p_child, "set_position", local_target_pos); } void CanvasItemEditorViewport::_create_audio_node(Node *p_parent, const String &p_path, const Point2 &p_point) { AudioStreamPlayer2D *child = memnew(AudioStreamPlayer2D); - child->set_stream(ResourceCache::get_ref(p_path)); // Adjust casing according to project setting. The file name is expected to be in snake_case, but will work for others. const String &node_name = Node::adjust_name_casing(p_path.get_file().get_basename()); @@ -6368,41 +6367,14 @@ void CanvasItemEditorViewport::_create_audio_node(Node *p_parent, const String & child->set_name(node_name); } - EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); - - if (p_parent) { - undo_redo->add_do_method(p_parent, "add_child", child, true); - undo_redo->add_do_method(child, "set_owner", EditorNode::get_singleton()->get_edited_scene()); - undo_redo->add_do_reference(child); - undo_redo->add_undo_method(p_parent, "remove_child", child); - } else { // If no parent is selected, set as root node of the scene. - undo_redo->add_do_method(EditorNode::get_singleton(), "set_edited_scene", child); - undo_redo->add_do_method(child, "set_owner", EditorNode::get_singleton()->get_edited_scene()); - undo_redo->add_do_reference(child); - undo_redo->add_undo_method(EditorNode::get_singleton(), "set_edited_scene", (Object *)nullptr); - } - - if (p_parent) { - String new_name = p_parent->validate_child_name(child); - EditorDebuggerNode *ed = EditorDebuggerNode::get_singleton(); - undo_redo->add_do_method(ed, "live_debug_create_node", EditorNode::get_singleton()->get_edited_scene()->get_path_to(p_parent), child->get_class(), new_name); - undo_redo->add_undo_method(ed, "live_debug_remove_node", NodePath(String(EditorNode::get_singleton()->get_edited_scene()->get_path_to(p_parent)) + "/" + new_name)); - } - // Compute the global position Transform2D xform = canvas_item_editor->get_canvas_transform(); Point2 target_position = xform.affine_inverse().xform(p_point); - // There's nothing to be used as source position, so snapping will work as absolute if enabled. - target_position = canvas_item_editor->snap_point(target_position); + _add_node_to_scene(p_parent, child, target_position); - CanvasItem *parent_ci = Object::cast_to(p_parent); - Point2 local_target_pos = parent_ci ? parent_ci->get_global_transform().affine_inverse().xform(target_position) : target_position; - - undo_redo->add_do_method(child, "set_position", local_target_pos); - - EditorSelection *editor_selection = EditorNode::get_singleton()->get_editor_selection(); - undo_redo->add_do_method(editor_selection, "add_node", child); + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); + undo_redo->add_do_property(child, "stream", ResourceCache::get_ref(p_path)); } bool CanvasItemEditorViewport::_create_instance(Node *p_parent, const String &p_path, const Point2 &p_point) { @@ -6512,7 +6484,6 @@ void CanvasItemEditorViewport::_perform_drop_data() { if (texture.is_valid()) { Node *child = Object::cast_to(ClassDB::instantiate(default_texture_node_type)); _create_texture_node(target_node, child, path, drop_pos); - undo_redo->add_do_method(editor_selection, "add_node", child); } Ref audio = res; @@ -6567,9 +6538,9 @@ bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Varian String error_message; for (const String &path : files) { - const String &res_type = ResourceLoader::get_resource_type(path); + const StringName res_type = ResourceLoader::get_resource_type(path); - if (ClassDB::is_parent_class(res_type, "PackedScene")) { + if (ClassDB::is_parent_class(res_type, SNAME("PackedScene"))) { Ref scn = ResourceLoader::load(path); ERR_CONTINUE(scn.is_null()); @@ -6583,11 +6554,9 @@ bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Varian } memdelete(instantiated_scene); instantiate_type |= SCENE; - } - if (ClassDB::is_parent_class(res_type, "Texture2D")) { + } else if (ClassDB::is_parent_class(res_type, SNAME("Texture2D"))) { instantiate_type |= TEXTURE; - } - if (ClassDB::is_parent_class(res_type, "AudioStream")) { + } else if (ClassDB::is_parent_class(res_type, SNAME("AudioStream"))) { instantiate_type |= AUDIO; } } diff --git a/editor/scene/canvas_item_editor_plugin.h b/editor/scene/canvas_item_editor_plugin.h index 29ea7e5fc1..1982fda3a4 100644 --- a/editor/scene/canvas_item_editor_plugin.h +++ b/editor/scene/canvas_item_editor_plugin.h @@ -685,6 +685,7 @@ class CanvasItemEditorViewport : public Control { bool _cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node) const; bool _is_any_texture_selected() const; + void _add_node_to_scene(Node *p_parent, Node *p_child, const Vector2 &p_target_position); void _create_texture_node(Node *p_parent, Node *p_child, const String &p_path, const Point2 &p_point); void _create_audio_node(Node *p_parent, const String &p_path, const Point2 &p_point); bool _create_instance(Node *p_parent, const String &p_path, const Point2 &p_point);