Allow to create a node at specific position
This commit is contained in:
parent
31143baa57
commit
ff7cae4c4c
5 changed files with 89 additions and 2 deletions
|
@ -1012,6 +1012,32 @@ void CanvasItemEditor::_selection_menu_hide() {
|
||||||
selection_menu->set_size(Vector2(0, 0));
|
selection_menu->set_size(Vector2(0, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CanvasItemEditor::_add_node_pressed(int p_result) {
|
||||||
|
if (p_result == AddNodeOption::ADD_NODE) {
|
||||||
|
editor->get_scene_tree_dock()->open_add_child_dialog();
|
||||||
|
} else if (p_result == AddNodeOption::ADD_INSTANCE) {
|
||||||
|
editor->get_scene_tree_dock()->open_instance_child_dialog();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasItemEditor::_node_created(Node *p_node) {
|
||||||
|
if (node_create_position == Point2()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CanvasItem *c = Object::cast_to<CanvasItem>(p_node);
|
||||||
|
if (c) {
|
||||||
|
Transform2D xform = c->get_global_transform_with_canvas().affine_inverse() * c->get_transform();
|
||||||
|
c->_edit_set_position(xform.xform(node_create_position));
|
||||||
|
}
|
||||||
|
|
||||||
|
call_deferred("_reset_create_position"); // Defer the call in case more than one node is added.
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasItemEditor::_reset_create_position() {
|
||||||
|
node_create_position = Point2();
|
||||||
|
}
|
||||||
|
|
||||||
bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_event) {
|
bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_event) {
|
||||||
Ref<InputEventMouseButton> b = p_event;
|
Ref<InputEventMouseButton> b = p_event;
|
||||||
Ref<InputEventMouseMotion> m = p_event;
|
Ref<InputEventMouseMotion> m = p_event;
|
||||||
|
@ -2397,6 +2423,14 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (b.is_valid() && b->is_pressed() && b->get_button_index() == BUTTON_RIGHT && b->get_control()) {
|
||||||
|
add_node_menu->set_position(get_global_transform().xform(get_local_mouse_position()));
|
||||||
|
add_node_menu->set_size(Vector2(1, 1));
|
||||||
|
add_node_menu->popup();
|
||||||
|
node_create_position = transform.affine_inverse().xform((get_local_mouse_position()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT) {
|
if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT) {
|
||||||
// Single item selection
|
// Single item selection
|
||||||
Point2 click = transform.affine_inverse().xform(b->get_position());
|
Point2 click = transform.affine_inverse().xform(b->get_position());
|
||||||
|
@ -5257,6 +5291,9 @@ void CanvasItemEditor::_bind_methods() {
|
||||||
ClassDB::bind_method("_tree_changed", &CanvasItemEditor::_tree_changed);
|
ClassDB::bind_method("_tree_changed", &CanvasItemEditor::_tree_changed);
|
||||||
ClassDB::bind_method("_selection_changed", &CanvasItemEditor::_selection_changed);
|
ClassDB::bind_method("_selection_changed", &CanvasItemEditor::_selection_changed);
|
||||||
ClassDB::bind_method("_popup_warning_depop", &CanvasItemEditor::_popup_warning_depop);
|
ClassDB::bind_method("_popup_warning_depop", &CanvasItemEditor::_popup_warning_depop);
|
||||||
|
ClassDB::bind_method("_add_node_pressed", &CanvasItemEditor::_add_node_pressed);
|
||||||
|
ClassDB::bind_method("_node_created", &CanvasItemEditor::_node_created);
|
||||||
|
ClassDB::bind_method("_reset_create_position", &CanvasItemEditor::_reset_create_position);
|
||||||
ClassDB::bind_method(D_METHOD("_selection_result_pressed"), &CanvasItemEditor::_selection_result_pressed);
|
ClassDB::bind_method(D_METHOD("_selection_result_pressed"), &CanvasItemEditor::_selection_result_pressed);
|
||||||
ClassDB::bind_method(D_METHOD("_selection_menu_hide"), &CanvasItemEditor::_selection_menu_hide);
|
ClassDB::bind_method(D_METHOD("_selection_menu_hide"), &CanvasItemEditor::_selection_menu_hide);
|
||||||
ClassDB::bind_method(D_METHOD("get_state"), &CanvasItemEditor::get_state);
|
ClassDB::bind_method(D_METHOD("get_state"), &CanvasItemEditor::get_state);
|
||||||
|
@ -5574,6 +5611,9 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
|
||||||
editor_selection->connect("selection_changed", this, "update");
|
editor_selection->connect("selection_changed", this, "update");
|
||||||
editor_selection->connect("selection_changed", this, "_selection_changed");
|
editor_selection->connect("selection_changed", this, "_selection_changed");
|
||||||
|
|
||||||
|
editor->get_scene_tree_dock()->connect("node_created", this, "_node_created");
|
||||||
|
editor->get_scene_tree_dock()->connect("add_node_used", this, "_reset_create_position");
|
||||||
|
|
||||||
editor->call_deferred("connect", "play_pressed", this, "_update_override_camera_button", make_binds(true));
|
editor->call_deferred("connect", "play_pressed", this, "_update_override_camera_button", make_binds(true));
|
||||||
editor->call_deferred("connect", "stop_pressed", this, "_update_override_camera_button", make_binds(false));
|
editor->call_deferred("connect", "stop_pressed", this, "_update_override_camera_button", make_binds(false));
|
||||||
|
|
||||||
|
@ -5950,6 +5990,12 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
|
||||||
selection_menu->connect("id_pressed", this, "_selection_result_pressed");
|
selection_menu->connect("id_pressed", this, "_selection_result_pressed");
|
||||||
selection_menu->connect("popup_hide", this, "_selection_menu_hide");
|
selection_menu->connect("popup_hide", this, "_selection_menu_hide");
|
||||||
|
|
||||||
|
add_node_menu = memnew(PopupMenu);
|
||||||
|
add_child(add_node_menu);
|
||||||
|
add_node_menu->add_icon_item(editor->get_scene_tree_dock()->get_icon("Add", "EditorIcons"), TTR("Add Node Here"));
|
||||||
|
add_node_menu->add_icon_item(editor->get_scene_tree_dock()->get_icon("Instance", "EditorIcons"), TTR("Instance Scene Here"));
|
||||||
|
add_node_menu->connect("id_pressed", this, "_add_node_pressed");
|
||||||
|
|
||||||
multiply_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/multiply_grid_step", TTR("Multiply grid step by 2"), KEY_KP_MULTIPLY);
|
multiply_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/multiply_grid_step", TTR("Multiply grid step by 2"), KEY_KP_MULTIPLY);
|
||||||
divide_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/divide_grid_step", TTR("Divide grid step by 2"), KEY_KP_DIVIDE);
|
divide_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/divide_grid_step", TTR("Divide grid step by 2"), KEY_KP_DIVIDE);
|
||||||
pan_view_shortcut = ED_SHORTCUT("canvas_item_editor/pan_view", TTR("Pan View"), KEY_SPACE);
|
pan_view_shortcut = ED_SHORTCUT("canvas_item_editor/pan_view", TTR("Pan View"), KEY_SPACE);
|
||||||
|
|
|
@ -82,6 +82,11 @@ public:
|
||||||
TOOL_MAX
|
TOOL_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum AddNodeOption {
|
||||||
|
ADD_NODE,
|
||||||
|
ADD_INSTANCE,
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EditorNode *editor;
|
EditorNode *editor;
|
||||||
|
|
||||||
|
@ -283,6 +288,7 @@ private:
|
||||||
|
|
||||||
bool ruler_tool_active;
|
bool ruler_tool_active;
|
||||||
Point2 ruler_tool_origin;
|
Point2 ruler_tool_origin;
|
||||||
|
Point2 node_create_position;
|
||||||
|
|
||||||
MenuOption last_option;
|
MenuOption last_option;
|
||||||
|
|
||||||
|
@ -379,6 +385,7 @@ private:
|
||||||
Button *key_auto_insert_button;
|
Button *key_auto_insert_button;
|
||||||
|
|
||||||
PopupMenu *selection_menu;
|
PopupMenu *selection_menu;
|
||||||
|
PopupMenu *add_node_menu;
|
||||||
|
|
||||||
Control *top_ruler;
|
Control *top_ruler;
|
||||||
Control *left_ruler;
|
Control *left_ruler;
|
||||||
|
@ -439,6 +446,9 @@ private:
|
||||||
void _snap_changed();
|
void _snap_changed();
|
||||||
void _selection_result_pressed(int);
|
void _selection_result_pressed(int);
|
||||||
void _selection_menu_hide();
|
void _selection_menu_hide();
|
||||||
|
void _add_node_pressed(int p_result);
|
||||||
|
void _node_created(Node *p_node);
|
||||||
|
void _reset_create_position();
|
||||||
|
|
||||||
UndoRedo *undo_redo;
|
UndoRedo *undo_redo;
|
||||||
bool _build_bones_list(Node *p_node);
|
bool _build_bones_list(Node *p_node);
|
||||||
|
|
|
@ -225,6 +225,9 @@ void SceneTreeDock::_perform_instance_scenes(const Vector<String> &p_files, Node
|
||||||
|
|
||||||
editor_data->get_undo_redo().commit_action();
|
editor_data->get_undo_redo().commit_action();
|
||||||
editor->push_item(instances[instances.size() - 1]);
|
editor->push_item(instances[instances.size() - 1]);
|
||||||
|
for (int i = 0; i < instances.size(); i++) {
|
||||||
|
emit_signal("node_created", instances[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneTreeDock::_replace_with_branch_scene(const String &p_file, Node *base) {
|
void SceneTreeDock::_replace_with_branch_scene(const String &p_file, Node *base) {
|
||||||
|
@ -353,6 +356,11 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (reset_create_dialog && !p_confirm_override) {
|
||||||
|
create_dialog->set_base_type("Node");
|
||||||
|
reset_create_dialog = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Prefer nodes that inherit from the current scene root.
|
// Prefer nodes that inherit from the current scene root.
|
||||||
Node *current_edited_scene_root = EditorNode::get_singleton()->get_edited_scene();
|
Node *current_edited_scene_root = EditorNode::get_singleton()->get_edited_scene();
|
||||||
if (current_edited_scene_root) {
|
if (current_edited_scene_root) {
|
||||||
|
@ -373,6 +381,9 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
|
||||||
}
|
}
|
||||||
|
|
||||||
create_dialog->popup_create(true);
|
create_dialog->popup_create(true);
|
||||||
|
if (!p_confirm_override) {
|
||||||
|
emit_signal("add_node_used");
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
case TOOL_INSTANCE: {
|
case TOOL_INSTANCE: {
|
||||||
if (!profile_allow_editing) {
|
if (!profile_allow_editing) {
|
||||||
|
@ -387,7 +398,9 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
|
||||||
|
|
||||||
quick_open->popup_dialog("PackedScene", true);
|
quick_open->popup_dialog("PackedScene", true);
|
||||||
quick_open->set_title(TTR("Instance Child Scene"));
|
quick_open->set_title(TTR("Instance Child Scene"));
|
||||||
|
if (!p_confirm_override) {
|
||||||
|
emit_signal("add_node_used");
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
case TOOL_EXPAND_COLLAPSE: {
|
case TOOL_EXPAND_COLLAPSE: {
|
||||||
if (!scene_tree->get_selected()) {
|
if (!scene_tree->get_selected()) {
|
||||||
|
@ -2168,6 +2181,8 @@ void SceneTreeDock::_do_create(Node *p_parent) {
|
||||||
}
|
}
|
||||||
ct->set_size(ms);
|
ct->set_size(ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emit_signal("node_created", c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneTreeDock::_create() {
|
void SceneTreeDock::_create() {
|
||||||
|
@ -2860,6 +2875,16 @@ void SceneTreeDock::open_script_dialog(Node *p_for_node, bool p_extend) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SceneTreeDock::open_add_child_dialog() {
|
||||||
|
create_dialog->set_base_type("CanvasItem");
|
||||||
|
_tool_selected(TOOL_NEW, true);
|
||||||
|
reset_create_dialog = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneTreeDock::open_instance_child_dialog() {
|
||||||
|
_tool_selected(TOOL_INSTANCE, true);
|
||||||
|
}
|
||||||
|
|
||||||
void SceneTreeDock::add_remote_tree_editor(Control *p_remote) {
|
void SceneTreeDock::add_remote_tree_editor(Control *p_remote) {
|
||||||
ERR_FAIL_COND(remote_tree != nullptr);
|
ERR_FAIL_COND(remote_tree != nullptr);
|
||||||
add_child(p_remote);
|
add_child(p_remote);
|
||||||
|
@ -3099,6 +3124,8 @@ void SceneTreeDock::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("replace_node"), &SceneTreeDock::replace_node);
|
ClassDB::bind_method(D_METHOD("replace_node"), &SceneTreeDock::replace_node);
|
||||||
|
|
||||||
ADD_SIGNAL(MethodInfo("remote_tree_selected"));
|
ADD_SIGNAL(MethodInfo("remote_tree_selected"));
|
||||||
|
ADD_SIGNAL(MethodInfo("add_node_used"));
|
||||||
|
ADD_SIGNAL(MethodInfo("node_created", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
|
||||||
}
|
}
|
||||||
|
|
||||||
SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSelection *p_editor_selection, EditorData &p_editor_data) {
|
SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSelection *p_editor_selection, EditorData &p_editor_data) {
|
||||||
|
|
|
@ -104,6 +104,7 @@ class SceneTreeDock : public VBoxContainer {
|
||||||
Vector<ObjectID> subresources;
|
Vector<ObjectID> subresources;
|
||||||
|
|
||||||
bool restore_script_editor_on_drag;
|
bool restore_script_editor_on_drag;
|
||||||
|
bool reset_create_dialog = false;
|
||||||
|
|
||||||
int current_option;
|
int current_option;
|
||||||
CreateDialog *create_dialog;
|
CreateDialog *create_dialog;
|
||||||
|
@ -282,6 +283,9 @@ public:
|
||||||
void attach_script_to_selected(bool p_extend);
|
void attach_script_to_selected(bool p_extend);
|
||||||
void open_script_dialog(Node *p_for_node, bool p_extend);
|
void open_script_dialog(Node *p_for_node, bool p_extend);
|
||||||
|
|
||||||
|
void open_add_child_dialog();
|
||||||
|
void open_instance_child_dialog();
|
||||||
|
|
||||||
ScriptCreateDialog *get_script_create_dialog() { return script_create_dialog; }
|
ScriptCreateDialog *get_script_create_dialog() { return script_create_dialog; }
|
||||||
|
|
||||||
SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSelection *p_editor_selection, EditorData &p_editor_data);
|
SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSelection *p_editor_selection, EditorData &p_editor_data);
|
||||||
|
|
|
@ -97,7 +97,7 @@ void Control::_edit_set_state(const Dictionary &p_state) {
|
||||||
void Control::_edit_set_position(const Point2 &p_position) {
|
void Control::_edit_set_position(const Point2 &p_position) {
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
ERR_FAIL_COND_MSG(!Engine::get_singleton()->is_editor_hint(), "This function can only be used from editor plugins.");
|
ERR_FAIL_COND_MSG(!Engine::get_singleton()->is_editor_hint(), "This function can only be used from editor plugins.");
|
||||||
set_position(p_position, CanvasItemEditor::get_singleton()->is_anchors_mode_enabled());
|
set_position(p_position, CanvasItemEditor::get_singleton()->is_anchors_mode_enabled() && Object::cast_to<Control>(data.parent));
|
||||||
#else
|
#else
|
||||||
// Unlikely to happen. TODO: enclose all _edit_ functions into TOOLS_ENABLED
|
// Unlikely to happen. TODO: enclose all _edit_ functions into TOOLS_ENABLED
|
||||||
set_position(p_position);
|
set_position(p_position);
|
||||||
|
|
Loading…
Reference in a new issue