diff options
Diffstat (limited to 'editor')
18 files changed, 1137 insertions, 1532 deletions
diff --git a/editor/SCsub b/editor/SCsub index e44b4e4bb2..772feca5f8 100644 --- a/editor/SCsub +++ b/editor/SCsub @@ -237,7 +237,7 @@ def make_license_header(target, source, env): g.write("static const char *about_license =") for line in f: - escaped_string = escape_string(line.strip().replace("\"", "\\\"")) + escaped_string = escape_string(line.strip()) g.write("\n\t\"" + escaped_string + "\\n\"") g.write(";\n") @@ -323,12 +323,12 @@ def make_license_header(target, source, env): for k in j[0].split("\n"): if file_body != "": file_body += "\\n\"\n" - escaped_string = escape_string(k.strip().replace("\"", "\\\"")) + escaped_string = escape_string(k.strip()) file_body += "\t\"" + escaped_string for k in j[1].split("\n"): if copyright_body != "": copyright_body += "\\n\"\n" - escaped_string = escape_string(k.strip().replace("\"", "\\\"")) + escaped_string = escape_string(k.strip()) copyright_body += "\t\"" + escaped_string about_tp_file += "\t" + file_body + "\",\n" @@ -343,7 +343,7 @@ def make_license_header(target, source, env): for j in i[1].split("\n"): if body != "": body += "\\n\"\n" - escaped_string = escape_string(j.strip().replace("\"", "\\\"")) + escaped_string = escape_string(j.strip()) body += "\t\"" + escaped_string about_license_name += "\t\"" + i[0] + "\",\n" diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 4e0ad38320..ff415c83f1 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -4588,7 +4588,8 @@ EditorNode::EditorNode() { { int dpi_mode = EditorSettings::get_singleton()->get("interface/editor/hidpi_mode"); if (dpi_mode == 0) { - editor_set_scale(OS::get_singleton()->get_screen_dpi(0) >= 192 && OS::get_singleton()->get_screen_size(OS::get_singleton()->get_current_screen()).x > 2000 ? 2.0 : 1.0); + const int screen = OS::get_singleton()->get_current_screen(); + editor_set_scale(OS::get_singleton()->get_screen_dpi(screen) >= 192 && OS::get_singleton()->get_screen_size(screen).x > 2000 ? 2.0 : 1.0); } else if (dpi_mode == 1) { editor_set_scale(0.75); } else if (dpi_mode == 2) { diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp new file mode 100644 index 0000000000..2fd74d529e --- /dev/null +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -0,0 +1,619 @@ +/*************************************************************************/ +/* abstract_polygon_2d_editor.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "abstract_polygon_2d_editor.h" + +#include "canvas_item_editor_plugin.h" + +bool AbstractPolygon2DEditor::_is_empty() const { + + if (!_get_node()) + return true; + + const int n = _get_polygon_count(); + + for (int i = 0; i < n; i++) { + + Vector<Vector2> vertices = _get_polygon(i); + + if (vertices.size() != 0) + return false; + } + + return true; +} + +int AbstractPolygon2DEditor::_get_polygon_count() const { + + return 1; +} + +Variant AbstractPolygon2DEditor::_get_polygon(int p_idx) const { + + return _get_node()->get("polygon"); +} + +void AbstractPolygon2DEditor::_set_polygon(int p_idx, const Variant &p_polygon) const { + + _get_node()->set("polygon", p_polygon); +} + +void AbstractPolygon2DEditor::_action_set_polygon(int p_idx, const Variant &p_previous, const Variant &p_polygon) { + + Node2D *node = _get_node(); + undo_redo->add_do_method(node, "set_polygon", p_polygon); + undo_redo->add_undo_method(node, "set_polygon", p_previous); +} + +Vector2 AbstractPolygon2DEditor::_get_offset(int p_idx) const { + + return Vector2(0, 0); +} + +void AbstractPolygon2DEditor::_commit_action() { + + undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update"); + undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update"); + undo_redo->commit_action(); +} + +void AbstractPolygon2DEditor::_action_add_polygon(const Variant &p_polygon) { + + _action_set_polygon(0, p_polygon); +} + +void AbstractPolygon2DEditor::_action_remove_polygon(int p_idx) { + + _action_set_polygon(p_idx, _get_polygon(p_idx), PoolVector<Vector2>()); +} + +void AbstractPolygon2DEditor::_action_set_polygon(int p_idx, const Variant &p_polygon) { + + _action_set_polygon(p_idx, _get_polygon(p_idx), p_polygon); +} + +bool AbstractPolygon2DEditor::_has_resource() const { + + return true; +} + +void AbstractPolygon2DEditor::_create_resource() { +} + +void AbstractPolygon2DEditor::_menu_option(int p_option) { + + switch (p_option) { + + case MODE_CREATE: { + + mode = MODE_CREATE; + button_create->set_pressed(true); + button_edit->set_pressed(false); + } break; + case MODE_EDIT: { + + mode = MODE_EDIT; + button_create->set_pressed(false); + button_edit->set_pressed(true); + } break; + } +} + +void AbstractPolygon2DEditor::_notification(int p_what) { + + switch (p_what) { + + case NOTIFICATION_READY: { + + button_create->set_icon(get_icon("Edit", "EditorIcons")); + button_edit->set_icon(get_icon("MovePoint", "EditorIcons")); + button_edit->set_pressed(true); + + get_tree()->connect("node_removed", this, "_node_removed"); + + create_resource->connect("confirmed", this, "_create_resource"); + + } break; + case NOTIFICATION_PHYSICS_PROCESS: { + + } break; + } +} + +void AbstractPolygon2DEditor::_node_removed(Node *p_node) { + + if (p_node == _get_node()) { + edit(NULL); + hide(); + + canvas_item_editor->get_viewport_control()->update(); + } +} + +void AbstractPolygon2DEditor::_wip_close() { + + if (wip.size() >= 3) { + + undo_redo->create_action(TTR("Create Poly")); + _action_add_polygon(wip); + _commit_action(); + + mode = MODE_EDIT; + button_edit->set_pressed(true); + button_create->set_pressed(false); + } + + wip.clear(); + wip_active = false; + edited_point = -1; +} + +bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { + + if (!_get_node()) + return false; + + Ref<InputEventMouseButton> mb = p_event; + + if (!_has_resource()) { + + if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) { + create_resource->set_text(String("No polygon resource on this node.\nCreate and assign one?")); + create_resource->popup_centered_minsize(); + } + return (mb.is_valid() && mb->get_button_index() == 1); + } + + if (mb.is_valid()) { + + Transform2D xform = canvas_item_editor->get_canvas_transform() * _get_node()->get_global_transform(); + + Vector2 gpoint = mb->get_position(); + Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint); + cpoint = canvas_item_editor->snap_point(cpoint); + cpoint = _get_node()->get_global_transform().affine_inverse().xform(cpoint); + + //first check if a point is to be added (segment split) + real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8); + + if (mode == MODE_CREATE) { + + if (mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) { + + if (!wip_active) { + + wip.clear(); + wip.push_back(cpoint); + wip_active = true; + edited_point_pos = cpoint; + edited_polygon = -1; + edited_point = 1; + canvas_item_editor->get_viewport_control()->update(); + return true; + } else { + + if (wip.size() > 1 && xform.xform(wip[0]).distance_to(gpoint) < grab_threshold) { + //wip closed + _wip_close(); + + return true; + } else { + + wip.push_back(cpoint); + edited_point = wip.size(); + canvas_item_editor->get_viewport_control()->update(); + return true; + + //add wip point + } + } + } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && wip_active) { + _wip_close(); + } + } else if (mode == MODE_EDIT) { + + if (mb->get_button_index() == BUTTON_LEFT) { + + if (mb->is_pressed()) { + + if (mb->get_control()) { + + const int n_polygons = _get_polygon_count(); + + if (n_polygons >= 1) { + + Vector<Vector2> vertices = _get_polygon(n_polygons - 1); + + if (vertices.size() < 3) { + + vertices.push_back(cpoint); + undo_redo->create_action(TTR("Edit Poly")); + _action_set_polygon(n_polygons - 1, vertices); + _commit_action(); + return true; + } + } + + //search edges + int closest_poly = -1; + int closest_idx = -1; + Vector2 closest_pos; + real_t closest_dist = 1e10; + + for (int j = 0; j < n_polygons; j++) { + + PoolVector<Vector2> points = _get_polygon(j); + const Vector2 offset = _get_offset(j); + const int n_points = points.size(); + + for (int i = 0; i < n_points; i++) { + + Vector2 p[2] = { xform.xform(points[i] + offset), + xform.xform(points[(i + 1) % n_points] + offset) }; + + Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint, p); + if (cp.distance_squared_to(points[0]) < CMP_EPSILON2 || cp.distance_squared_to(points[1]) < CMP_EPSILON2) + continue; //not valid to reuse point + + real_t d = cp.distance_to(gpoint); + if (d < closest_dist && d < grab_threshold) { + closest_poly = j; + closest_dist = d; + closest_pos = cp; + closest_idx = i; + } + } + } + + if (closest_idx >= 0) { + + Vector<Vector2> vertices = _get_polygon(closest_poly); + pre_move_edit = vertices; + vertices.insert(closest_idx + 1, xform.affine_inverse().xform(closest_pos)); + edited_point = closest_idx + 1; + edited_polygon = closest_poly; + edited_point_pos = xform.affine_inverse().xform(closest_pos); + + undo_redo->create_action(TTR("Insert Point")); + _action_set_polygon(closest_poly, vertices); + _commit_action(); + + return true; + } + } else { + + //look for points to move + int closest_poly = -1; + int closest_idx = -1; + Vector2 closest_pos; + real_t closest_dist = 1e10; + + const int n_polygons = _get_polygon_count(); + + for (int j = 0; j < n_polygons; j++) { + + PoolVector<Vector2> points = _get_polygon(j); + const Vector2 offset = _get_offset(j); + const int n_points = points.size(); + + for (int i = 0; i < n_points; i++) { + + Vector2 cp = xform.xform(points[i] + offset); + + real_t d = cp.distance_to(gpoint); + if (d < closest_dist && d < grab_threshold) { + closest_poly = j; + closest_dist = d; + closest_pos = cp; + closest_idx = i; + } + } + } + + if (closest_idx >= 0) { + + pre_move_edit = _get_polygon(closest_poly); + edited_polygon = closest_poly; + edited_point = closest_idx; + edited_point_pos = xform.affine_inverse().xform(closest_pos); + canvas_item_editor->get_viewport_control()->update(); + return true; + } + } + } else { + + if (edited_point != -1) { + + //apply + + Vector<Vector2> vertices = _get_polygon(edited_polygon); + ERR_FAIL_INDEX_V(edited_point, vertices.size(), false); + vertices[edited_point] = edited_point_pos - _get_offset(edited_polygon); + + undo_redo->create_action(TTR("Edit Poly")); + _action_set_polygon(edited_polygon, pre_move_edit, vertices); + _commit_action(); + + edited_point = -1; + return true; + } + } + } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && edited_point == -1) { + + int closest_poly = -1; + int closest_idx = -1; + Vector2 closest_pos; + real_t closest_dist = 1e10; + const int n_polygons = _get_polygon_count(); + + for (int j = 0; j < n_polygons; j++) { + + PoolVector<Vector2> points = _get_polygon(j); + const int n_points = points.size(); + const Vector2 offset = _get_offset(j); + + for (int i = 0; i < n_points; i++) { + + Vector2 cp = xform.xform(points[i] + offset); + + real_t d = cp.distance_to(gpoint); + if (d < closest_dist && d < grab_threshold) { + closest_poly = j; + closest_dist = d; + closest_pos = cp; + closest_idx = i; + } + } + } + + if (closest_idx >= 0) { + + PoolVector<Vector2> vertices = _get_polygon(closest_poly); + + if (vertices.size() > 3) { + + vertices.remove(closest_idx); + + undo_redo->create_action(TTR("Edit Poly (Remove Point)")); + _action_set_polygon(closest_poly, vertices); + _commit_action(); + } else { + + undo_redo->create_action(TTR("Remove Poly And Point")); + _action_remove_polygon(closest_poly); + _commit_action(); + } + + if (_is_empty()) + _menu_option(MODE_CREATE); + return true; + } + } + } + } + + Ref<InputEventMouseMotion> mm = p_event; + + if (mm.is_valid()) { + + if (edited_point != -1 && (wip_active || (mm->get_button_mask() & BUTTON_MASK_LEFT))) { + + Vector2 gpoint = mm->get_position(); + Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint); + cpoint = canvas_item_editor->snap_point(cpoint); + edited_point_pos = _get_node()->get_global_transform().affine_inverse().xform(cpoint); + + if (!wip_active) { + + Vector<Vector2> vertices = _get_polygon(edited_polygon); + ERR_FAIL_INDEX_V(edited_point, vertices.size(), false); + vertices[edited_point] = edited_point_pos - _get_offset(edited_polygon); + _set_polygon(edited_polygon, vertices); + } + + canvas_item_editor->get_viewport_control()->update(); + } + } + + return false; +} + +void AbstractPolygon2DEditor::_canvas_draw() { + + if (!_get_node()) + return; + + Control *vpc = canvas_item_editor->get_viewport_control(); + + Transform2D xform = canvas_item_editor->get_canvas_transform() * _get_node()->get_global_transform(); + Ref<Texture> handle = get_icon("EditorHandle", "EditorIcons"); + const int n_polygons = _get_polygon_count(); + + for (int j = -1; j < n_polygons; j++) { + + if (wip_active && wip_destructive && j != -1) + continue; + + PoolVector<Vector2> points; + Vector2 offset; + + if (wip_active && j == edited_polygon) { + + points = Variant(wip); + offset = Vector2(0, 0); + } else { + + if (j == -1) + continue; + points = _get_polygon(j); + offset = _get_offset(j); + } + + if (!wip_active && j == edited_polygon && edited_point >= 0 && EDITOR_DEF("editors/poly_editor/show_previous_outline", true)) { + + const Color col = Color(0.5, 0.5, 0.5); // FIXME polygon->get_outline_color(); + const int n = pre_move_edit.size(); + for (int i = 0; i < n; i++) { + + Vector2 p, p2; + p = pre_move_edit[i] + offset; + p2 = pre_move_edit[(i + 1) % n] + offset; + + Vector2 point = xform.xform(p); + Vector2 next_point = xform.xform(p2); + + vpc->draw_line(point, next_point, col, 2); + } + } + + const int n_points = points.size(); + const Color col = Color(1, 0.3, 0.1, 0.8); + + for (int i = 0; i < n_points; i++) { + + Vector2 p, p2; + p = (j == edited_polygon && i == edited_point) ? edited_point_pos : (points[i] + offset); + if (j == edited_polygon && ((wip_active && i == n_points - 1) || (((i + 1) % n_points) == edited_point))) + p2 = edited_point_pos; + else + p2 = points[(i + 1) % n_points] + offset; + + Vector2 point = xform.xform(p); + Vector2 next_point = xform.xform(p2); + + vpc->draw_line(point, next_point, col, 2); + vpc->draw_texture(handle, point - handle->get_size() * 0.5); + } + } +} + +void AbstractPolygon2DEditor::edit(Node *p_polygon) { + + if (!canvas_item_editor) { + canvas_item_editor = CanvasItemEditor::get_singleton(); + } + + if (p_polygon) { + + _set_node(p_polygon); + + //Enable the pencil tool if the polygon is empty + if (_is_empty()) + _menu_option(MODE_CREATE); + + if (!canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw")) + canvas_item_editor->get_viewport_control()->connect("draw", this, "_canvas_draw"); + + wip.clear(); + wip_active = false; + edited_point = -1; + + canvas_item_editor->get_viewport_control()->update(); + + } else { + + _set_node(NULL); + + if (canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw")) + canvas_item_editor->get_viewport_control()->disconnect("draw", this, "_canvas_draw"); + } +} + +void AbstractPolygon2DEditor::_bind_methods() { + + ClassDB::bind_method(D_METHOD("_canvas_draw"), &AbstractPolygon2DEditor::_canvas_draw); + ClassDB::bind_method(D_METHOD("_node_removed"), &AbstractPolygon2DEditor::_node_removed); + ClassDB::bind_method(D_METHOD("_menu_option"), &AbstractPolygon2DEditor::_menu_option); + ClassDB::bind_method(D_METHOD("_create_resource"), &AbstractPolygon2DEditor::_create_resource); +} + +AbstractPolygon2DEditor::AbstractPolygon2DEditor(EditorNode *p_editor, bool p_wip_destructive) { + + canvas_item_editor = NULL; + editor = p_editor; + undo_redo = editor->get_undo_redo(); + + wip_active = false; + edited_polygon = -1; + wip_destructive = p_wip_destructive; + + add_child(memnew(VSeparator)); + button_create = memnew(ToolButton); + add_child(button_create); + button_create->connect("pressed", this, "_menu_option", varray(MODE_CREATE)); + button_create->set_toggle_mode(true); + button_create->set_tooltip(TTR("Create a new polygon from scratch.")); + + button_edit = memnew(ToolButton); + add_child(button_edit); + button_edit->connect("pressed", this, "_menu_option", varray(MODE_EDIT)); + button_edit->set_toggle_mode(true); + button_edit->set_tooltip(TTR("Edit existing polygon:\nLMB: Move Point.\nCtrl+LMB: Split Segment.\nRMB: Erase Point.")); + + create_resource = memnew(ConfirmationDialog); + add_child(create_resource); + create_resource->get_ok()->set_text(TTR("Create")); + + mode = MODE_EDIT; +} + +void AbstractPolygon2DEditorPlugin::edit(Object *p_object) { + + polygon_editor->edit(Object::cast_to<Node>(p_object)); +} + +bool AbstractPolygon2DEditorPlugin::handles(Object *p_object) const { + + return p_object->is_class(klass); +} + +void AbstractPolygon2DEditorPlugin::make_visible(bool p_visible) { + + if (p_visible) { + + polygon_editor->show(); + } else { + + polygon_editor->hide(); + polygon_editor->edit(NULL); + } +} + +AbstractPolygon2DEditorPlugin::AbstractPolygon2DEditorPlugin(EditorNode *p_node, AbstractPolygon2DEditor *p_polygon_editor, String p_class) { + + editor = p_node; + polygon_editor = p_polygon_editor; + klass = p_class; + CanvasItemEditor::get_singleton()->add_control_to_menu_panel(polygon_editor); + + polygon_editor->hide(); +} + +AbstractPolygon2DEditorPlugin::~AbstractPolygon2DEditorPlugin() { +} diff --git a/editor/plugins/abstract_polygon_2d_editor.h b/editor/plugins/abstract_polygon_2d_editor.h new file mode 100644 index 0000000000..86e14694da --- /dev/null +++ b/editor/plugins/abstract_polygon_2d_editor.h @@ -0,0 +1,131 @@ +/*************************************************************************/ +/* abstract_polygon_2d_editor.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef ABSTRACT_POLYGON_2D_EDITOR_H +#define ABSTRACT_POLYGON_2D_EDITOR_H + +#include "editor/editor_node.h" +#include "editor/editor_plugin.h" +#include "scene/2d/polygon_2d.h" +#include "scene/gui/tool_button.h" + +/** + @author Juan Linietsky <reduzio@gmail.com> +*/ +class CanvasItemEditor; + +class AbstractPolygon2DEditor : public HBoxContainer { + + GDCLASS(AbstractPolygon2DEditor, HBoxContainer); + + ToolButton *button_create; + ToolButton *button_edit; + + int edited_polygon; + int edited_point; + Vector2 edited_point_pos; + Vector<Vector2> pre_move_edit; + Vector<Vector2> wip; + bool wip_active; + bool wip_destructive; + + CanvasItemEditor *canvas_item_editor; + EditorNode *editor; + Panel *panel; + ConfirmationDialog *create_resource; + +protected: + enum { + + MODE_CREATE, + MODE_EDIT, + MODE_CONT, + + }; + + int mode; + + UndoRedo *undo_redo; + + virtual void _menu_option(int p_option); + void _wip_close(); + void _canvas_draw(); + + void _notification(int p_what); + void _node_removed(Node *p_node); + static void _bind_methods(); + + bool _is_empty() const; + void _commit_action(); + +protected: + virtual Node2D *_get_node() const = 0; + virtual void _set_node(Node *p_polygon) = 0; + + virtual int _get_polygon_count() const; + virtual Vector2 _get_offset(int p_idx) const; + virtual Variant _get_polygon(int p_idx) const; + virtual void _set_polygon(int p_idx, const Variant &p_polygon) const; + + virtual void _action_add_polygon(const Variant &p_polygon); + virtual void _action_remove_polygon(int p_idx); + virtual void _action_set_polygon(int p_idx, const Variant &p_polygon); + virtual void _action_set_polygon(int p_idx, const Variant &p_previous, const Variant &p_polygon); + + virtual bool _has_resource() const; + virtual void _create_resource(); + +public: + bool forward_gui_input(const Ref<InputEvent> &p_event); + void edit(Node *p_polygon); + AbstractPolygon2DEditor(EditorNode *p_editor, bool p_wip_destructive = true); +}; + +class AbstractPolygon2DEditorPlugin : public EditorPlugin { + + GDCLASS(AbstractPolygon2DEditorPlugin, EditorPlugin); + + AbstractPolygon2DEditor *polygon_editor; + EditorNode *editor; + String klass; + +public: + virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) { return polygon_editor->forward_gui_input(p_event); } + + bool has_main_screen() const { return false; } + virtual String get_name() const { return klass; } + virtual void edit(Object *p_object); + virtual bool handles(Object *p_object) const; + virtual void make_visible(bool p_visible); + + AbstractPolygon2DEditorPlugin(EditorNode *p_node, AbstractPolygon2DEditor *p_polygon_editor, String p_class); + ~AbstractPolygon2DEditorPlugin(); +}; + +#endif // ABSTRACT_POLYGON_2D_EDITOR_H diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 4f6c8f89ee..4b216d63f5 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -993,7 +993,7 @@ void CanvasItemEditor::_prepare_drag(const Point2 &p_click_pos) { se->pre_drag_rect = canvas_item->get_item_rect(); } - if (selection.size() == 1 && Object::cast_to<Node2D>(selection[0])) { + if (selection.size() == 1 && Object::cast_to<Node2D>(selection[0]) && bone_ik_list.size() == 0) { drag = DRAG_NODE_2D; drag_point_from = Object::cast_to<Node2D>(selection[0])->get_global_position(); } else { @@ -2748,9 +2748,9 @@ void CanvasItemEditor::_notification(int p_what) { } if (all_control && has_control) - anchor_menu->show(); + presets_menu->show(); else - anchor_menu->hide(); + presets_menu->hide(); for (Map<ObjectID, BoneList>::Element *E = bone_list.front(); E; E = E->next()) { @@ -2782,57 +2782,15 @@ void CanvasItemEditor::_notification(int p_what) { select_sb->set_default_margin(Margin(i), 4); } - select_button->set_icon(get_icon("ToolSelect", "EditorIcons")); - list_select_button->set_icon(get_icon("ListSelect", "EditorIcons")); - move_button->set_icon(get_icon("ToolMove", "EditorIcons")); - rotate_button->set_icon(get_icon("ToolRotate", "EditorIcons")); - snap_button->set_icon(get_icon("Snap", "EditorIcons")); - snap_config_menu->set_icon(get_icon("GuiMiniTabMenu", "EditorIcons")); - skeleton_menu->set_icon(get_icon("Bone", "EditorIcons")); - pan_button->set_icon(get_icon("ToolPan", "EditorIcons")); - pivot_button->set_icon(get_icon("EditPivot", "EditorIcons")); - select_handle = get_icon("EditorHandle", "EditorIcons"); - anchor_handle = get_icon("EditorControlAnchor", "EditorIcons"); - lock_button->set_icon(get_icon("Lock", "EditorIcons")); - unlock_button->set_icon(get_icon("Unlock", "EditorIcons")); - group_button->set_icon(get_icon("Group", "EditorIcons")); - ungroup_button->set_icon(get_icon("Ungroup", "EditorIcons")); - key_insert_button->set_icon(get_icon("Key", "EditorIcons")); - - zoom_minus->set_icon(get_icon("ZoomLess", "EditorIcons")); - zoom_reset->set_icon(get_icon("ZoomReset", "EditorIcons")); - zoom_plus->set_icon(get_icon("ZoomMore", "EditorIcons")); - - anchor_menu->set_icon(get_icon("Anchor", "EditorIcons")); - PopupMenu *p = anchor_menu->get_popup(); - - p->add_icon_item(get_icon("ControlAlignTopLeft", "EditorIcons"), "Top Left", ANCHOR_ALIGN_TOP_LEFT); - p->add_icon_item(get_icon("ControlAlignTopRight", "EditorIcons"), "Top Right", ANCHOR_ALIGN_TOP_RIGHT); - p->add_icon_item(get_icon("ControlAlignBottomRight", "EditorIcons"), "Bottom Right", ANCHOR_ALIGN_BOTTOM_RIGHT); - p->add_icon_item(get_icon("ControlAlignBottomLeft", "EditorIcons"), "Bottom Left", ANCHOR_ALIGN_BOTTOM_LEFT); - p->add_separator(); - p->add_icon_item(get_icon("ControlAlignLeftCenter", "EditorIcons"), "Center Left", ANCHOR_ALIGN_CENTER_LEFT); - p->add_icon_item(get_icon("ControlAlignTopCenter", "EditorIcons"), "Center Top", ANCHOR_ALIGN_CENTER_TOP); - p->add_icon_item(get_icon("ControlAlignRightCenter", "EditorIcons"), "Center Right", ANCHOR_ALIGN_CENTER_RIGHT); - p->add_icon_item(get_icon("ControlAlignBottomCenter", "EditorIcons"), "Center Bottom", ANCHOR_ALIGN_CENTER_BOTTOM); - p->add_icon_item(get_icon("ControlAlignCenter", "EditorIcons"), "Center", ANCHOR_ALIGN_CENTER); - p->add_separator(); - p->add_icon_item(get_icon("ControlAlignLeftWide", "EditorIcons"), "Left Wide", ANCHOR_ALIGN_LEFT_WIDE); - p->add_icon_item(get_icon("ControlAlignTopWide", "EditorIcons"), "Top Wide", ANCHOR_ALIGN_TOP_WIDE); - p->add_icon_item(get_icon("ControlAlignRightWide", "EditorIcons"), "Right Wide", ANCHOR_ALIGN_RIGHT_WIDE); - p->add_icon_item(get_icon("ControlAlignBottomWide", "EditorIcons"), "Bottom Wide", ANCHOR_ALIGN_BOTTOM_WIDE); - p->add_icon_item(get_icon("ControlVcenterWide", "EditorIcons"), "VCenter Wide ", ANCHOR_ALIGN_VCENTER_WIDE); - p->add_icon_item(get_icon("ControlHcenterWide", "EditorIcons"), "HCenter Wide ", ANCHOR_ALIGN_HCENTER_WIDE); - p->add_separator(); - p->add_icon_item(get_icon("ControlAlignWide", "EditorIcons"), "Full Rect", ANCHOR_ALIGN_WIDE); - p->add_icon_item(get_icon("ControlAlignWide", "EditorIcons"), "Full Rect and Fit Parent", ANCHOR_ALIGN_WIDE_FIT); - AnimationPlayerEditor::singleton->get_key_editor()->connect("visibility_changed", this, "_keying_changed"); _keying_changed(); + } else if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { select_sb->set_texture(get_icon("EditorRect2D", "EditorIcons")); + } + if (p_what == NOTIFICATION_ENTER_TREE || p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { select_button->set_icon(get_icon("ToolSelect", "EditorIcons")); list_select_button->set_icon(get_icon("ListSelect", "EditorIcons")); move_button->set_icon(get_icon("ToolMove", "EditorIcons")); @@ -2850,30 +2808,56 @@ void CanvasItemEditor::_notification(int p_what) { ungroup_button->set_icon(get_icon("Ungroup", "EditorIcons")); key_insert_button->set_icon(get_icon("Key", "EditorIcons")); - anchor_menu->set_icon(get_icon("Anchor", "EditorIcons")); - PopupMenu *p = anchor_menu->get_popup(); - p->clear(); + zoom_minus->set_icon(get_icon("ZoomLess", "EditorIcons")); + zoom_reset->set_icon(get_icon("ZoomReset", "EditorIcons")); + zoom_plus->set_icon(get_icon("ZoomMore", "EditorIcons")); - p->add_icon_item(get_icon("ControlAlignTopLeft", "EditorIcons"), "Top Left", ANCHOR_ALIGN_TOP_LEFT); - p->add_icon_item(get_icon("ControlAlignTopRight", "EditorIcons"), "Top Right", ANCHOR_ALIGN_TOP_RIGHT); - p->add_icon_item(get_icon("ControlAlignBottomRight", "EditorIcons"), "Bottom Right", ANCHOR_ALIGN_BOTTOM_RIGHT); - p->add_icon_item(get_icon("ControlAlignBottomLeft", "EditorIcons"), "Bottom Left", ANCHOR_ALIGN_BOTTOM_LEFT); + PopupMenu *p = presets_menu->get_popup(); + + p->clear(); + p->add_icon_item(get_icon("ControlAlignTopLeft", "EditorIcons"), "Top Left", ANCHORS_AND_MARGINS_PRESET_TOP_LEFT); + p->add_icon_item(get_icon("ControlAlignTopRight", "EditorIcons"), "Top Right", ANCHORS_AND_MARGINS_PRESET_TOP_RIGHT); + p->add_icon_item(get_icon("ControlAlignBottomRight", "EditorIcons"), "Bottom Right", ANCHORS_AND_MARGINS_PRESET_BOTTOM_RIGHT); + p->add_icon_item(get_icon("ControlAlignBottomLeft", "EditorIcons"), "Bottom Left", ANCHORS_AND_MARGINS_PRESET_BOTTOM_LEFT); p->add_separator(); - p->add_icon_item(get_icon("ControlAlignLeftCenter", "EditorIcons"), "Center Left", ANCHOR_ALIGN_CENTER_LEFT); - p->add_icon_item(get_icon("ControlAlignTopCenter", "EditorIcons"), "Center Top", ANCHOR_ALIGN_CENTER_TOP); - p->add_icon_item(get_icon("ControlAlignRightCenter", "EditorIcons"), "Center Right", ANCHOR_ALIGN_CENTER_RIGHT); - p->add_icon_item(get_icon("ControlAlignBottomCenter", "EditorIcons"), "Center Bottom", ANCHOR_ALIGN_CENTER_BOTTOM); - p->add_icon_item(get_icon("ControlAlignCenter", "EditorIcons"), "Center", ANCHOR_ALIGN_CENTER); + p->add_icon_item(get_icon("ControlAlignLeftCenter", "EditorIcons"), "Center Left", ANCHORS_AND_MARGINS_PRESET_CENTER_LEFT); + p->add_icon_item(get_icon("ControlAlignTopCenter", "EditorIcons"), "Center Top", ANCHORS_AND_MARGINS_PRESET_CENTER_TOP); + p->add_icon_item(get_icon("ControlAlignRightCenter", "EditorIcons"), "Center Right", ANCHORS_AND_MARGINS_PRESET_CENTER_RIGHT); + p->add_icon_item(get_icon("ControlAlignBottomCenter", "EditorIcons"), "Center Bottom", ANCHORS_AND_MARGINS_PRESET_CENTER_BOTTOM); + p->add_icon_item(get_icon("ControlAlignCenter", "EditorIcons"), "Center", ANCHORS_AND_MARGINS_PRESET_CENTER); p->add_separator(); - p->add_icon_item(get_icon("ControlAlignLeftWide", "EditorIcons"), "Left Wide", ANCHOR_ALIGN_LEFT_WIDE); - p->add_icon_item(get_icon("ControlAlignTopWide", "EditorIcons"), "Top Wide", ANCHOR_ALIGN_TOP_WIDE); - p->add_icon_item(get_icon("ControlAlignRightWide", "EditorIcons"), "Right Wide", ANCHOR_ALIGN_RIGHT_WIDE); - p->add_icon_item(get_icon("ControlAlignBottomWide", "EditorIcons"), "Bottom Wide", ANCHOR_ALIGN_BOTTOM_WIDE); - p->add_icon_item(get_icon("ControlVcenterWide", "EditorIcons"), "VCenter Wide ", ANCHOR_ALIGN_VCENTER_WIDE); - p->add_icon_item(get_icon("ControlHcenterWide", "EditorIcons"), "HCenter Wide ", ANCHOR_ALIGN_HCENTER_WIDE); + p->add_icon_item(get_icon("ControlAlignLeftWide", "EditorIcons"), "Left Wide", ANCHORS_AND_MARGINS_PRESET_LEFT_WIDE); + p->add_icon_item(get_icon("ControlAlignTopWide", "EditorIcons"), "Top Wide", ANCHORS_AND_MARGINS_PRESET_TOP_WIDE); + p->add_icon_item(get_icon("ControlAlignRightWide", "EditorIcons"), "Right Wide", ANCHORS_AND_MARGINS_PRESET_RIGHT_WIDE); + p->add_icon_item(get_icon("ControlAlignBottomWide", "EditorIcons"), "Bottom Wide", ANCHORS_AND_MARGINS_PRESET_BOTTOM_WIDE); + p->add_icon_item(get_icon("ControlVcenterWide", "EditorIcons"), "VCenter Wide ", ANCHORS_AND_MARGINS_PRESET_VCENTER_WIDE); + p->add_icon_item(get_icon("ControlHcenterWide", "EditorIcons"), "HCenter Wide ", ANCHORS_AND_MARGINS_PRESET_HCENTER_WIDE); p->add_separator(); - p->add_icon_item(get_icon("ControlAlignWide", "EditorIcons"), "Full Rect", ANCHOR_ALIGN_WIDE); - p->add_icon_item(get_icon("ControlAlignWide", "EditorIcons"), "Full Rect and Fit Parent", ANCHOR_ALIGN_WIDE_FIT); + p->add_icon_item(get_icon("ControlAlignWide", "EditorIcons"), "Full Rect", ANCHORS_AND_MARGINS_PRESET_WIDE); + p->add_separator(); + p->add_submenu_item(TTR("Anchors only"), "Anchors"); + p->set_item_icon(20, get_icon("Anchor", "EditorIcons")); + + anchors_popup->clear(); + anchors_popup->add_icon_item(get_icon("ControlAlignTopLeft", "EditorIcons"), "Top Left", ANCHORS_PRESET_TOP_LEFT); + anchors_popup->add_icon_item(get_icon("ControlAlignTopRight", "EditorIcons"), "Top Right", ANCHORS_PRESET_TOP_RIGHT); + anchors_popup->add_icon_item(get_icon("ControlAlignBottomRight", "EditorIcons"), "Bottom Right", ANCHORS_PRESET_BOTTOM_RIGHT); + anchors_popup->add_icon_item(get_icon("ControlAlignBottomLeft", "EditorIcons"), "Bottom Left", ANCHORS_PRESET_BOTTOM_LEFT); + anchors_popup->add_separator(); + anchors_popup->add_icon_item(get_icon("ControlAlignLeftCenter", "EditorIcons"), "Center Left", ANCHORS_PRESET_CENTER_LEFT); + anchors_popup->add_icon_item(get_icon("ControlAlignTopCenter", "EditorIcons"), "Center Top", ANCHORS_PRESET_CENTER_TOP); + anchors_popup->add_icon_item(get_icon("ControlAlignRightCenter", "EditorIcons"), "Center Right", ANCHORS_PRESET_CENTER_RIGHT); + anchors_popup->add_icon_item(get_icon("ControlAlignBottomCenter", "EditorIcons"), "Center Bottom", ANCHORS_PRESET_CENTER_BOTTOM); + anchors_popup->add_icon_item(get_icon("ControlAlignCenter", "EditorIcons"), "Center", ANCHORS_PRESET_CENTER); + anchors_popup->add_separator(); + anchors_popup->add_icon_item(get_icon("ControlAlignLeftWide", "EditorIcons"), "Left Wide", ANCHORS_PRESET_LEFT_WIDE); + anchors_popup->add_icon_item(get_icon("ControlAlignTopWide", "EditorIcons"), "Top Wide", ANCHORS_PRESET_TOP_WIDE); + anchors_popup->add_icon_item(get_icon("ControlAlignRightWide", "EditorIcons"), "Right Wide", ANCHORS_PRESET_RIGHT_WIDE); + anchors_popup->add_icon_item(get_icon("ControlAlignBottomWide", "EditorIcons"), "Bottom Wide", ANCHORS_PRESET_BOTTOM_WIDE); + anchors_popup->add_icon_item(get_icon("ControlVcenterWide", "EditorIcons"), "VCenter Wide ", ANCHORS_PRESET_VCENTER_WIDE); + anchors_popup->add_icon_item(get_icon("ControlHcenterWide", "EditorIcons"), "HCenter Wide ", ANCHORS_PRESET_HCENTER_WIDE); + anchors_popup->add_separator(); + anchors_popup->add_icon_item(get_icon("ControlAlignWide", "EditorIcons"), "Full Rect", ANCHORS_PRESET_WIDE); } } @@ -3005,25 +2989,51 @@ void CanvasItemEditor::_update_scroll(float) { viewport_base->update(); } -void CanvasItemEditor::_set_anchors_preset(Control::LayoutPreset p_preset) { +void CanvasItemEditor::_set_anchors_and_margins_preset(Control::LayoutPreset p_preset) { List<Node *> &selection = editor_selection->get_selected_node_list(); - undo_redo->create_action(TTR("Change Anchors")); + undo_redo->create_action(TTR("Change Anchors and Margins")); for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { Control *c = Object::cast_to<Control>(E->get()); undo_redo->add_do_method(c, "set_anchors_preset", p_preset); + switch (p_preset) { + case PRESET_TOP_LEFT: + case PRESET_TOP_RIGHT: + case PRESET_BOTTOM_LEFT: + case PRESET_BOTTOM_RIGHT: + case PRESET_CENTER_LEFT: + case PRESET_CENTER_TOP: + case PRESET_CENTER_RIGHT: + case PRESET_CENTER_BOTTOM: + case PRESET_CENTER: + undo_redo->add_do_method(c, "set_margins_preset", p_preset, Control::PRESET_MODE_KEEP_SIZE); + break; + case PRESET_LEFT_WIDE: + case PRESET_TOP_WIDE: + case PRESET_RIGHT_WIDE: + case PRESET_BOTTOM_WIDE: + case PRESET_VCENTER_WIDE: + case PRESET_HCENTER_WIDE: + case PRESET_WIDE: + undo_redo->add_do_method(c, "set_margins_preset", p_preset, Control::PRESET_MODE_MINSIZE); + break; + } undo_redo->add_undo_method(c, "set_anchor", MARGIN_LEFT, c->get_anchor(MARGIN_LEFT)); undo_redo->add_undo_method(c, "set_anchor", MARGIN_TOP, c->get_anchor(MARGIN_TOP)); undo_redo->add_undo_method(c, "set_anchor", MARGIN_RIGHT, c->get_anchor(MARGIN_RIGHT)); undo_redo->add_undo_method(c, "set_anchor", MARGIN_BOTTOM, c->get_anchor(MARGIN_BOTTOM)); + undo_redo->add_undo_method(c, "set_margin", MARGIN_LEFT, c->get_margin(MARGIN_LEFT)); + undo_redo->add_undo_method(c, "set_margin", MARGIN_TOP, c->get_margin(MARGIN_TOP)); + undo_redo->add_undo_method(c, "set_margin", MARGIN_RIGHT, c->get_margin(MARGIN_RIGHT)); + undo_redo->add_undo_method(c, "set_margin", MARGIN_BOTTOM, c->get_margin(MARGIN_BOTTOM)); } undo_redo->commit_action(); } -void CanvasItemEditor::_set_full_rect() { +void CanvasItemEditor::_set_anchors_preset(Control::LayoutPreset p_preset) { List<Node *> &selection = editor_selection->get_selected_node_list(); undo_redo->create_action(TTR("Change Anchors")); @@ -3031,19 +3041,11 @@ void CanvasItemEditor::_set_full_rect() { Control *c = Object::cast_to<Control>(E->get()); - undo_redo->add_do_method(c, "set_anchors_preset", Control::PRESET_WIDE); - undo_redo->add_do_method(c, "set_margin", MARGIN_LEFT, 0); - undo_redo->add_do_method(c, "set_margin", MARGIN_TOP, 0); - undo_redo->add_do_method(c, "set_margin", MARGIN_RIGHT, 0); - undo_redo->add_do_method(c, "set_margin", MARGIN_BOTTOM, 0); + undo_redo->add_do_method(c, "set_anchors_preset", p_preset); undo_redo->add_undo_method(c, "set_anchor", MARGIN_LEFT, c->get_anchor(MARGIN_LEFT)); undo_redo->add_undo_method(c, "set_anchor", MARGIN_TOP, c->get_anchor(MARGIN_TOP)); undo_redo->add_undo_method(c, "set_anchor", MARGIN_RIGHT, c->get_anchor(MARGIN_RIGHT)); undo_redo->add_undo_method(c, "set_anchor", MARGIN_BOTTOM, c->get_anchor(MARGIN_BOTTOM)); - undo_redo->add_undo_method(c, "set_margin", MARGIN_LEFT, c->get_margin(MARGIN_LEFT)); - undo_redo->add_undo_method(c, "set_margin", MARGIN_TOP, c->get_margin(MARGIN_TOP)); - undo_redo->add_undo_method(c, "set_margin", MARGIN_RIGHT, c->get_margin(MARGIN_RIGHT)); - undo_redo->add_undo_method(c, "set_margin", MARGIN_BOTTOM, c->get_margin(MARGIN_BOTTOM)); } undo_redo->commit_action(); @@ -3237,57 +3239,104 @@ void CanvasItemEditor::_popup_callback(int p_op) { viewport->update(); } break; - case ANCHOR_ALIGN_TOP_LEFT: { + + case ANCHORS_AND_MARGINS_PRESET_TOP_LEFT: { + _set_anchors_and_margins_preset(PRESET_TOP_LEFT); + } break; + case ANCHORS_AND_MARGINS_PRESET_TOP_RIGHT: { + _set_anchors_and_margins_preset(PRESET_TOP_RIGHT); + } break; + case ANCHORS_AND_MARGINS_PRESET_BOTTOM_LEFT: { + _set_anchors_and_margins_preset(PRESET_BOTTOM_LEFT); + } break; + case ANCHORS_AND_MARGINS_PRESET_BOTTOM_RIGHT: { + _set_anchors_and_margins_preset(PRESET_BOTTOM_RIGHT); + } break; + case ANCHORS_AND_MARGINS_PRESET_CENTER_LEFT: { + _set_anchors_and_margins_preset(PRESET_CENTER_LEFT); + } break; + case ANCHORS_AND_MARGINS_PRESET_CENTER_RIGHT: { + _set_anchors_and_margins_preset(PRESET_CENTER_RIGHT); + } break; + case ANCHORS_AND_MARGINS_PRESET_CENTER_TOP: { + _set_anchors_and_margins_preset(PRESET_CENTER_TOP); + } break; + case ANCHORS_AND_MARGINS_PRESET_CENTER_BOTTOM: { + _set_anchors_and_margins_preset(PRESET_CENTER_BOTTOM); + } break; + case ANCHORS_AND_MARGINS_PRESET_CENTER: { + _set_anchors_and_margins_preset(PRESET_CENTER); + } break; + case ANCHORS_AND_MARGINS_PRESET_TOP_WIDE: { + _set_anchors_and_margins_preset(PRESET_TOP_WIDE); + } break; + case ANCHORS_AND_MARGINS_PRESET_LEFT_WIDE: { + _set_anchors_and_margins_preset(PRESET_LEFT_WIDE); + } break; + case ANCHORS_AND_MARGINS_PRESET_RIGHT_WIDE: { + _set_anchors_and_margins_preset(PRESET_RIGHT_WIDE); + } break; + case ANCHORS_AND_MARGINS_PRESET_BOTTOM_WIDE: { + _set_anchors_and_margins_preset(PRESET_BOTTOM_WIDE); + } break; + case ANCHORS_AND_MARGINS_PRESET_VCENTER_WIDE: { + _set_anchors_and_margins_preset(PRESET_VCENTER_WIDE); + } break; + case ANCHORS_AND_MARGINS_PRESET_HCENTER_WIDE: { + _set_anchors_and_margins_preset(PRESET_HCENTER_WIDE); + } break; + case ANCHORS_AND_MARGINS_PRESET_WIDE: { + _set_anchors_and_margins_preset(Control::PRESET_WIDE); + } break; + + case ANCHORS_PRESET_TOP_LEFT: { _set_anchors_preset(PRESET_TOP_LEFT); } break; - case ANCHOR_ALIGN_TOP_RIGHT: { + case ANCHORS_PRESET_TOP_RIGHT: { _set_anchors_preset(PRESET_TOP_RIGHT); } break; - case ANCHOR_ALIGN_BOTTOM_LEFT: { + case ANCHORS_PRESET_BOTTOM_LEFT: { _set_anchors_preset(PRESET_BOTTOM_LEFT); } break; - case ANCHOR_ALIGN_BOTTOM_RIGHT: { + case ANCHORS_PRESET_BOTTOM_RIGHT: { _set_anchors_preset(PRESET_BOTTOM_RIGHT); } break; - case ANCHOR_ALIGN_CENTER_LEFT: { + case ANCHORS_PRESET_CENTER_LEFT: { _set_anchors_preset(PRESET_CENTER_LEFT); } break; - case ANCHOR_ALIGN_CENTER_RIGHT: { + case ANCHORS_PRESET_CENTER_RIGHT: { _set_anchors_preset(PRESET_CENTER_RIGHT); } break; - case ANCHOR_ALIGN_CENTER_TOP: { + case ANCHORS_PRESET_CENTER_TOP: { _set_anchors_preset(PRESET_CENTER_TOP); } break; - case ANCHOR_ALIGN_CENTER_BOTTOM: { + case ANCHORS_PRESET_CENTER_BOTTOM: { _set_anchors_preset(PRESET_CENTER_BOTTOM); } break; - case ANCHOR_ALIGN_CENTER: { + case ANCHORS_PRESET_CENTER: { _set_anchors_preset(PRESET_CENTER); } break; - case ANCHOR_ALIGN_TOP_WIDE: { + case ANCHORS_PRESET_TOP_WIDE: { _set_anchors_preset(PRESET_TOP_WIDE); } break; - case ANCHOR_ALIGN_LEFT_WIDE: { + case ANCHORS_PRESET_LEFT_WIDE: { _set_anchors_preset(PRESET_LEFT_WIDE); } break; - case ANCHOR_ALIGN_RIGHT_WIDE: { + case ANCHORS_PRESET_RIGHT_WIDE: { _set_anchors_preset(PRESET_RIGHT_WIDE); } break; - case ANCHOR_ALIGN_BOTTOM_WIDE: { + case ANCHORS_PRESET_BOTTOM_WIDE: { _set_anchors_preset(PRESET_BOTTOM_WIDE); } break; - case ANCHOR_ALIGN_VCENTER_WIDE: { + case ANCHORS_PRESET_VCENTER_WIDE: { _set_anchors_preset(PRESET_VCENTER_WIDE); } break; - case ANCHOR_ALIGN_HCENTER_WIDE: { + case ANCHORS_PRESET_HCENTER_WIDE: { _set_anchors_preset(PRESET_HCENTER_WIDE); } break; - case ANCHOR_ALIGN_WIDE: { + case ANCHORS_PRESET_WIDE: { _set_anchors_preset(Control::PRESET_WIDE); } break; - case ANCHOR_ALIGN_WIDE_FIT: { - _set_full_rect(); - } break; case ANIM_INSERT_KEY: case ANIM_INSERT_KEY_EXISTING: { @@ -3865,7 +3914,6 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { p->add_separator(); p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_set_ik_chain", TTR("Make IK Chain")), SKELETON_SET_IK_CHAIN); p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_ik_chain", TTR("Clear IK Chain")), SKELETON_CLEAR_IK_CHAIN); - p->set_hide_on_checkable_item_selection(false); p->connect("id_pressed", this, "_popup_callback"); hb->add_child(memnew(VSeparator)); @@ -3883,13 +3931,18 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { p->add_shortcut(ED_SHORTCUT("canvas_item_editor/center_selection", TTR("Center Selection"), KEY_F), VIEW_CENTER_TO_SELECTION); p->add_shortcut(ED_SHORTCUT("canvas_item_editor/frame_selection", TTR("Frame Selection"), KEY_MASK_SHIFT | KEY_F), VIEW_FRAME_TO_SELECTION); - anchor_menu = memnew(MenuButton); - anchor_menu->set_text(TTR("Anchor")); - hb->add_child(anchor_menu); - anchor_menu->get_popup()->connect("id_pressed", this, "_popup_callback"); - anchor_menu->hide(); + presets_menu = memnew(MenuButton); + presets_menu->set_text(TTR("Layout")); + hb->add_child(presets_menu); + presets_menu->hide(); + + p = presets_menu->get_popup(); + p->connect("id_pressed", this, "_popup_callback"); - //p = anchor_menu->get_popup(); + anchors_popup = memnew(PopupMenu); + p->add_child(anchors_popup); + anchors_popup->set_name("Anchors"); + anchors_popup->connect("id_pressed", this, "_popup_callback"); animation_hb = memnew(HBoxContainer); hb->add_child(animation_hb); diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index f87bfef8ad..69dc25d180 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -98,23 +98,54 @@ class CanvasItemEditor : public VBoxContainer { UNLOCK_SELECTED, GROUP_SELECTED, UNGROUP_SELECTED, - ANCHOR_ALIGN_TOP_LEFT, - ANCHOR_ALIGN_TOP_RIGHT, - ANCHOR_ALIGN_BOTTOM_LEFT, - ANCHOR_ALIGN_BOTTOM_RIGHT, - ANCHOR_ALIGN_CENTER_LEFT, - ANCHOR_ALIGN_CENTER_RIGHT, - ANCHOR_ALIGN_CENTER_TOP, - ANCHOR_ALIGN_CENTER_BOTTOM, - ANCHOR_ALIGN_CENTER, - ANCHOR_ALIGN_TOP_WIDE, - ANCHOR_ALIGN_LEFT_WIDE, - ANCHOR_ALIGN_RIGHT_WIDE, - ANCHOR_ALIGN_BOTTOM_WIDE, - ANCHOR_ALIGN_VCENTER_WIDE, - ANCHOR_ALIGN_HCENTER_WIDE, - ANCHOR_ALIGN_WIDE, - ANCHOR_ALIGN_WIDE_FIT, + ANCHORS_AND_MARGINS_PRESET_TOP_LEFT, + ANCHORS_AND_MARGINS_PRESET_TOP_RIGHT, + ANCHORS_AND_MARGINS_PRESET_BOTTOM_LEFT, + ANCHORS_AND_MARGINS_PRESET_BOTTOM_RIGHT, + ANCHORS_AND_MARGINS_PRESET_CENTER_LEFT, + ANCHORS_AND_MARGINS_PRESET_CENTER_RIGHT, + ANCHORS_AND_MARGINS_PRESET_CENTER_TOP, + ANCHORS_AND_MARGINS_PRESET_CENTER_BOTTOM, + ANCHORS_AND_MARGINS_PRESET_CENTER, + ANCHORS_AND_MARGINS_PRESET_TOP_WIDE, + ANCHORS_AND_MARGINS_PRESET_LEFT_WIDE, + ANCHORS_AND_MARGINS_PRESET_RIGHT_WIDE, + ANCHORS_AND_MARGINS_PRESET_BOTTOM_WIDE, + ANCHORS_AND_MARGINS_PRESET_VCENTER_WIDE, + ANCHORS_AND_MARGINS_PRESET_HCENTER_WIDE, + ANCHORS_AND_MARGINS_PRESET_WIDE, + ANCHORS_PRESET_TOP_LEFT, + ANCHORS_PRESET_TOP_RIGHT, + ANCHORS_PRESET_BOTTOM_LEFT, + ANCHORS_PRESET_BOTTOM_RIGHT, + ANCHORS_PRESET_CENTER_LEFT, + ANCHORS_PRESET_CENTER_RIGHT, + ANCHORS_PRESET_CENTER_TOP, + ANCHORS_PRESET_CENTER_BOTTOM, + ANCHORS_PRESET_CENTER, + ANCHORS_PRESET_TOP_WIDE, + ANCHORS_PRESET_LEFT_WIDE, + ANCHORS_PRESET_RIGHT_WIDE, + ANCHORS_PRESET_BOTTOM_WIDE, + ANCHORS_PRESET_VCENTER_WIDE, + ANCHORS_PRESET_HCENTER_WIDE, + ANCHORS_PRESET_WIDE, + MARGINS_PRESET_TOP_LEFT, + MARGINS_PRESET_TOP_RIGHT, + MARGINS_PRESET_BOTTOM_LEFT, + MARGINS_PRESET_BOTTOM_RIGHT, + MARGINS_PRESET_CENTER_LEFT, + MARGINS_PRESET_CENTER_RIGHT, + MARGINS_PRESET_CENTER_TOP, + MARGINS_PRESET_CENTER_BOTTOM, + MARGINS_PRESET_CENTER, + MARGINS_PRESET_TOP_WIDE, + MARGINS_PRESET_LEFT_WIDE, + MARGINS_PRESET_RIGHT_WIDE, + MARGINS_PRESET_BOTTOM_WIDE, + MARGINS_PRESET_VCENTER_WIDE, + MARGINS_PRESET_HCENTER_WIDE, + MARGINS_PRESET_WIDE, ANIM_INSERT_KEY, ANIM_INSERT_KEY_EXISTING, ANIM_INSERT_POS, @@ -279,7 +310,10 @@ class CanvasItemEditor : public VBoxContainer { MenuButton *view_menu; HBoxContainer *animation_hb; MenuButton *animation_menu; - MenuButton *anchor_menu; + + MenuButton *presets_menu; + PopupMenu *anchors_and_margins_popup; + PopupMenu *anchors_popup; Button *key_loc_button; Button *key_rot_button; @@ -386,7 +420,8 @@ class CanvasItemEditor : public VBoxContainer { void _snap_other_nodes(Point2 p_value, Point2 &r_current_snap, bool (&r_snapped)[2], const Node *p_current, const CanvasItem *p_to_snap); void _set_anchors_preset(Control::LayoutPreset p_preset); - void _set_full_rect(); + void _set_margins_preset(Control::LayoutPreset p_preset); + void _set_anchors_and_margins_preset(Control::LayoutPreset p_preset); void _zoom_on_position(float p_zoom, Point2 p_position = Point2()); void _zoom_minus(); diff --git a/editor/plugins/collision_polygon_2d_editor_plugin.cpp b/editor/plugins/collision_polygon_2d_editor_plugin.cpp index 4501136e19..00e6d617a1 100644..100755 --- a/editor/plugins/collision_polygon_2d_editor_plugin.cpp +++ b/editor/plugins/collision_polygon_2d_editor_plugin.cpp @@ -29,400 +29,20 @@ /*************************************************************************/ #include "collision_polygon_2d_editor_plugin.h" -#include "canvas_item_editor_plugin.h" -#include "editor/editor_settings.h" -#include "os/file_access.h" +Node2D *CollisionPolygon2DEditor::_get_node() const { -void CollisionPolygon2DEditor::_notification(int p_what) { - - switch (p_what) { - - case NOTIFICATION_READY: { - - button_create->set_icon(get_icon("Edit", "EditorIcons")); - button_edit->set_icon(get_icon("MovePoint", "EditorIcons")); - button_edit->set_pressed(true); - get_tree()->connect("node_removed", this, "_node_removed"); - - } break; - case NOTIFICATION_PHYSICS_PROCESS: { - - } break; - } -} -void CollisionPolygon2DEditor::_node_removed(Node *p_node) { - - if (p_node == node) { - node = NULL; - hide(); - canvas_item_editor->get_viewport_control()->update(); - } -} - -void CollisionPolygon2DEditor::_menu_option(int p_option) { - - switch (p_option) { - - case MODE_CREATE: { - - mode = MODE_CREATE; - button_create->set_pressed(true); - button_edit->set_pressed(false); - } break; - case MODE_EDIT: { - - mode = MODE_EDIT; - button_create->set_pressed(false); - button_edit->set_pressed(true); - } break; - } -} - -void CollisionPolygon2DEditor::_wip_close() { - - undo_redo->create_action(TTR("Create Poly")); - undo_redo->add_undo_method(node, "set_polygon", node->get_polygon()); - undo_redo->add_do_method(node, "set_polygon", wip); - undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update"); - undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update"); - undo_redo->commit_action(); - wip.clear(); - wip_active = false; - mode = MODE_EDIT; - button_edit->set_pressed(true); - button_create->set_pressed(false); - edited_point = -1; -} - -bool CollisionPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { - - if (!node) - return false; - - Ref<InputEventMouseButton> mb = p_event; - - if (mb.is_valid()) { - Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); - - Vector2 gpoint = mb->get_position(); - Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint); - cpoint = canvas_item_editor->snap_point(cpoint); - cpoint = node->get_global_transform().affine_inverse().xform(cpoint); - - Vector<Vector2> poly = node->get_polygon(); - - //first check if a point is to be added (segment split) - real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8); - - switch (mode) { - - case MODE_CREATE: { - - if (mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) { - - if (!wip_active) { - - wip.clear(); - wip.push_back(cpoint); - wip_active = true; - edited_point_pos = cpoint; - canvas_item_editor->get_viewport_control()->update(); - edited_point = 1; - return true; - } else { - - if (wip.size() > 1 && xform.xform(wip[0]).distance_to(gpoint) < grab_threshold) { - //wip closed - _wip_close(); - - return true; - } else { - - wip.push_back(cpoint); - edited_point = wip.size(); - canvas_item_editor->get_viewport_control()->update(); - return true; - - //add wip point - } - } - } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && wip_active) { - _wip_close(); - } - - } break; - - case MODE_EDIT: { - - if (mb->get_button_index() == BUTTON_LEFT) { - if (mb->is_pressed()) { - - if (mb->get_control()) { - - if (poly.size() < 3) { - - undo_redo->create_action(TTR("Edit Poly")); - undo_redo->add_undo_method(node, "set_polygon", poly); - poly.push_back(cpoint); - undo_redo->add_do_method(node, "set_polygon", poly); - undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update"); - undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update"); - undo_redo->commit_action(); - return true; - } - - //search edges - int closest_idx = -1; - Vector2 closest_pos; - real_t closest_dist = 1e10; - for (int i = 0; i < poly.size(); i++) { - - Vector2 points[2] = { xform.xform(poly[i]), - xform.xform(poly[(i + 1) % poly.size()]) }; - - Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint, points); - if (cp.distance_squared_to(points[0]) < CMP_EPSILON2 || cp.distance_squared_to(points[1]) < CMP_EPSILON2) - continue; //not valid to reuse point - - real_t d = cp.distance_to(gpoint); - if (d < closest_dist && d < grab_threshold) { - closest_dist = d; - closest_pos = cp; - closest_idx = i; - } - } - - if (closest_idx >= 0) { - - pre_move_edit = poly; - poly.insert(closest_idx + 1, xform.affine_inverse().xform(closest_pos)); - edited_point = closest_idx + 1; - edited_point_pos = xform.affine_inverse().xform(closest_pos); - node->set_polygon(poly); - canvas_item_editor->get_viewport_control()->update(); - return true; - } - } else { - - //look for points to move - - int closest_idx = -1; - Vector2 closest_pos; - real_t closest_dist = 1e10; - for (int i = 0; i < poly.size(); i++) { - - Vector2 cp = xform.xform(poly[i]); - - real_t d = cp.distance_to(gpoint); - if (d < closest_dist && d < grab_threshold) { - closest_dist = d; - closest_pos = cp; - closest_idx = i; - } - } - - if (closest_idx >= 0) { - - pre_move_edit = poly; - edited_point = closest_idx; - edited_point_pos = xform.affine_inverse().xform(closest_pos); - canvas_item_editor->get_viewport_control()->update(); - return true; - } - } - } else { - - if (edited_point != -1) { - - //apply - - ERR_FAIL_INDEX_V(edited_point, poly.size(), false); - poly[edited_point] = edited_point_pos; - undo_redo->create_action(TTR("Edit Poly")); - undo_redo->add_do_method(node, "set_polygon", poly); - undo_redo->add_undo_method(node, "set_polygon", pre_move_edit); - undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update"); - undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update"); - undo_redo->commit_action(); - - edited_point = -1; - return true; - } - } - } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && edited_point == -1) { - - int closest_idx = -1; - Vector2 closest_pos; - real_t closest_dist = 1e10; - for (int i = 0; i < poly.size(); i++) { - - Vector2 cp = xform.xform(poly[i]); - - real_t d = cp.distance_to(gpoint); - if (d < closest_dist && d < grab_threshold) { - closest_dist = d; - closest_pos = cp; - closest_idx = i; - } - } - - if (closest_idx >= 0) { - - undo_redo->create_action(TTR("Edit Poly (Remove Point)")); - undo_redo->add_undo_method(node, "set_polygon", poly); - poly.remove(closest_idx); - undo_redo->add_do_method(node, "set_polygon", poly); - undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update"); - undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update"); - undo_redo->commit_action(); - return true; - } - } - - } break; - } - } - - Ref<InputEventMouseMotion> mm = p_event; - - if (mm.is_valid()) { - - if (edited_point != -1 && (wip_active || mm->get_button_mask() & BUTTON_MASK_LEFT)) { - - Vector2 gpoint = mm->get_position(); - Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint); - cpoint = canvas_item_editor->snap_point(cpoint); - edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint); - - canvas_item_editor->get_viewport_control()->update(); - } - } - - return false; + return node; } -void CollisionPolygon2DEditor::_canvas_draw() { - - if (!node) - return; - - Control *vpc = canvas_item_editor->get_viewport_control(); - - Vector<Vector2> poly; - - if (wip_active) - poly = wip; - else - poly = node->get_polygon(); - Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); - Ref<Texture> handle = get_icon("EditorHandle", "EditorIcons"); +void CollisionPolygon2DEditor::_set_node(Node *p_polygon) { - for (int i = 0; i < poly.size(); i++) { - - Vector2 p, p2; - p = i == edited_point ? edited_point_pos : poly[i]; - if ((wip_active && i == poly.size() - 1) || (((i + 1) % poly.size()) == edited_point)) - p2 = edited_point_pos; - else - p2 = poly[(i + 1) % poly.size()]; - - Vector2 point = xform.xform(p); - Vector2 next_point = xform.xform(p2); - - Color col = Color(1, 0.3, 0.1, 0.8); - vpc->draw_line(point, next_point, col, 2); - vpc->draw_texture(handle, point - handle->get_size() * 0.5); - } + node = Object::cast_to<CollisionPolygon2D>(p_polygon); } -void CollisionPolygon2DEditor::edit(Node *p_collision_polygon) { - - if (!canvas_item_editor) { - canvas_item_editor = CanvasItemEditor::get_singleton(); - } - - if (p_collision_polygon) { - - node = Object::cast_to<CollisionPolygon2D>(p_collision_polygon); - //Enable the pencil tool if the polygon is empty - if (node->get_polygon().size() == 0) { - _menu_option(MODE_CREATE); - } - if (!canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw")) - canvas_item_editor->get_viewport_control()->connect("draw", this, "_canvas_draw"); - wip.clear(); - wip_active = false; - edited_point = -1; - canvas_item_editor->get_viewport_control()->update(); - - } else { - node = NULL; - - if (canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw")) - canvas_item_editor->get_viewport_control()->disconnect("draw", this, "_canvas_draw"); - } -} - -void CollisionPolygon2DEditor::_bind_methods() { - - ClassDB::bind_method(D_METHOD("_menu_option"), &CollisionPolygon2DEditor::_menu_option); - ClassDB::bind_method(D_METHOD("_canvas_draw"), &CollisionPolygon2DEditor::_canvas_draw); - ClassDB::bind_method(D_METHOD("_node_removed"), &CollisionPolygon2DEditor::_node_removed); -} - -CollisionPolygon2DEditor::CollisionPolygon2DEditor(EditorNode *p_editor) { - - node = NULL; - canvas_item_editor = NULL; - editor = p_editor; - undo_redo = editor->get_undo_redo(); - - add_child(memnew(VSeparator)); - button_create = memnew(ToolButton); - add_child(button_create); - button_create->connect("pressed", this, "_menu_option", varray(MODE_CREATE)); - button_create->set_toggle_mode(true); - button_create->set_tooltip(TTR("Create a new polygon from scratch.")); - - button_edit = memnew(ToolButton); - add_child(button_edit); - button_edit->connect("pressed", this, "_menu_option", varray(MODE_EDIT)); - button_edit->set_toggle_mode(true); - button_edit->set_tooltip(TTR("Edit existing polygon:\nLMB: Move Point.\nCtrl+LMB: Split Segment.\nRMB: Erase Point.")); - - mode = MODE_EDIT; - wip_active = false; -} - -void CollisionPolygon2DEditorPlugin::edit(Object *p_object) { - - collision_polygon_editor->edit(Object::cast_to<Node>(p_object)); -} - -bool CollisionPolygon2DEditorPlugin::handles(Object *p_object) const { - - return p_object->is_class("CollisionPolygon2D"); -} - -void CollisionPolygon2DEditorPlugin::make_visible(bool p_visible) { - - if (p_visible) { - collision_polygon_editor->show(); - } else { - - collision_polygon_editor->hide(); - collision_polygon_editor->edit(NULL); - } -} - -CollisionPolygon2DEditorPlugin::CollisionPolygon2DEditorPlugin(EditorNode *p_node) { - - editor = p_node; - collision_polygon_editor = memnew(CollisionPolygon2DEditor(p_node)); - CanvasItemEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor); - - collision_polygon_editor->hide(); +CollisionPolygon2DEditor::CollisionPolygon2DEditor(EditorNode *p_editor) + : AbstractPolygon2DEditor(p_editor) { } -CollisionPolygon2DEditorPlugin::~CollisionPolygon2DEditorPlugin() { +CollisionPolygon2DEditorPlugin::CollisionPolygon2DEditorPlugin(EditorNode *p_node) + : AbstractPolygon2DEditorPlugin(p_node, memnew(CollisionPolygon2DEditor(p_node)), "CollisionPolygon2D") { } diff --git a/editor/plugins/collision_polygon_2d_editor_plugin.h b/editor/plugins/collision_polygon_2d_editor_plugin.h index 4715abd2e6..edf3bbcc08 100644..100755 --- a/editor/plugins/collision_polygon_2d_editor_plugin.h +++ b/editor/plugins/collision_polygon_2d_editor_plugin.h @@ -30,78 +30,32 @@ #ifndef COLLISION_POLYGON_2D_EDITOR_PLUGIN_H #define COLLISION_POLYGON_2D_EDITOR_PLUGIN_H -#include "editor/editor_node.h" -#include "editor/editor_plugin.h" +#include "editor/plugins/abstract_polygon_2d_editor.h" #include "scene/2d/collision_polygon_2d.h" -#include "scene/gui/tool_button.h" /** @author Juan Linietsky <reduzio@gmail.com> */ -class CanvasItemEditor; +class CollisionPolygon2DEditor : public AbstractPolygon2DEditor { -class CollisionPolygon2DEditor : public HBoxContainer { + GDCLASS(CollisionPolygon2DEditor, AbstractPolygon2DEditor); - GDCLASS(CollisionPolygon2DEditor, HBoxContainer); - - UndoRedo *undo_redo; - enum Mode { - - MODE_CREATE, - MODE_EDIT, - - }; - - Mode mode; - - ToolButton *button_create; - ToolButton *button_edit; - - CanvasItemEditor *canvas_item_editor; - EditorNode *editor; - Panel *panel; CollisionPolygon2D *node; - MenuButton *options; - - int edited_point; - Vector2 edited_point_pos; - Vector<Vector2> pre_move_edit; - Vector<Vector2> wip; - bool wip_active; - - void _wip_close(); - void _canvas_draw(); - void _menu_option(int p_option); protected: - void _notification(int p_what); - void _node_removed(Node *p_node); - static void _bind_methods(); + virtual Node2D *_get_node() const; + virtual void _set_node(Node *p_polygon); public: - bool forward_gui_input(const Ref<InputEvent> &p_event); - void edit(Node *p_collision_polygon); CollisionPolygon2DEditor(EditorNode *p_editor); }; -class CollisionPolygon2DEditorPlugin : public EditorPlugin { - - GDCLASS(CollisionPolygon2DEditorPlugin, EditorPlugin); +class CollisionPolygon2DEditorPlugin : public AbstractPolygon2DEditorPlugin { - CollisionPolygon2DEditor *collision_polygon_editor; - EditorNode *editor; + GDCLASS(CollisionPolygon2DEditorPlugin, AbstractPolygon2DEditorPlugin); public: - virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) { return collision_polygon_editor->forward_gui_input(p_event); } - - virtual String get_name() const { return "CollisionPolygon2D"; } - bool has_main_screen() const { return false; } - virtual void edit(Object *p_object); - virtual bool handles(Object *p_object) const; - virtual void make_visible(bool p_visible); - CollisionPolygon2DEditorPlugin(EditorNode *p_node); - ~CollisionPolygon2DEditorPlugin(); }; #endif // COLLISION_POLYGON_2D_EDITOR_PLUGIN_H diff --git a/editor/plugins/navigation_mesh_generator.cpp b/editor/plugins/navigation_mesh_generator.cpp index 526db3a582..86dc5c3663 100644 --- a/editor/plugins/navigation_mesh_generator.cpp +++ b/editor/plugins/navigation_mesh_generator.cpp @@ -38,9 +38,11 @@ void NavigationMeshGenerator::_add_vertex(const Vector3 &p_vec3, Vector<float> & } void NavigationMeshGenerator::_add_mesh(const Ref<Mesh> &p_mesh, const Transform &p_xform, Vector<float> &p_verticies, Vector<int> &p_indices) { - int current_vertex_count = p_verticies.size() / 3; + int current_vertex_count = 0; for (int i = 0; i < p_mesh->get_surface_count(); i++) { + current_vertex_count = p_verticies.size() / 3; + if (p_mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) continue; diff --git a/editor/plugins/navigation_polygon_editor_plugin.cpp b/editor/plugins/navigation_polygon_editor_plugin.cpp index 69e553eefb..6560a8dac7 100644..100755 --- a/editor/plugins/navigation_polygon_editor_plugin.cpp +++ b/editor/plugins/navigation_polygon_editor_plugin.cpp @@ -29,485 +29,101 @@ /*************************************************************************/ #include "navigation_polygon_editor_plugin.h" -#include "canvas_item_editor_plugin.h" -#include "editor/editor_settings.h" -#include "os/file_access.h" +Ref<NavigationPolygon> NavigationPolygonEditor::_ensure_navpoly() const { -void NavigationPolygonEditor::_notification(int p_what) { + Ref<NavigationPolygon> navpoly = node->get_navigation_polygon(); + if (!navpoly.is_valid()) { - switch (p_what) { - - case NOTIFICATION_READY: { - - button_create->set_icon(get_icon("Edit", "EditorIcons")); - button_edit->set_icon(get_icon("MovePoint", "EditorIcons")); - button_edit->set_pressed(true); - get_tree()->connect("node_removed", this, "_node_removed"); - create_nav->connect("confirmed", this, "_create_nav"); - - } break; - case NOTIFICATION_PHYSICS_PROCESS: { - - } break; + navpoly = Ref<NavigationPolygon>(memnew(NavigationPolygon)); + node->set_navigation_polygon(navpoly); } + return navpoly; } -void NavigationPolygonEditor::_node_removed(Node *p_node) { - if (p_node == node) { - node = NULL; - hide(); - canvas_item_editor->get_viewport_control()->update(); - } -} +Node2D *NavigationPolygonEditor::_get_node() const { -void NavigationPolygonEditor::_create_nav() { - - if (!node) - return; - - undo_redo->create_action(TTR("Create Navigation Polygon")); - undo_redo->add_do_method(node, "set_navigation_polygon", Ref<NavigationPolygon>(memnew(NavigationPolygon))); - undo_redo->add_undo_method(node, "set_navigation_polygon", Variant(REF())); - undo_redo->commit_action(); - _menu_option(MODE_CREATE); + return node; } -void NavigationPolygonEditor::_menu_option(int p_option) { +void NavigationPolygonEditor::_set_node(Node *p_polygon) { - switch (p_option) { - - case MODE_CREATE: { - - mode = MODE_CREATE; - button_create->set_pressed(true); - button_edit->set_pressed(false); - } break; - case MODE_EDIT: { - - mode = MODE_EDIT; - button_create->set_pressed(false); - button_edit->set_pressed(true); - } break; - } + node = Object::cast_to<NavigationPolygonInstance>(p_polygon); } -void NavigationPolygonEditor::_wip_close() { +int NavigationPolygonEditor::_get_polygon_count() const { - if (wip.size() >= 3) { - - undo_redo->create_action(TTR("Create Poly")); - undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "remove_outline", node->get_navigation_polygon()->get_outline_count()); - undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "add_outline", wip); - undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines"); - undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines"); - undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update"); - undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update"); - undo_redo->commit_action(); - mode = MODE_EDIT; - button_edit->set_pressed(true); - button_create->set_pressed(false); - } - - wip.clear(); - wip_active = false; - edited_point = -1; + Ref<NavigationPolygon> navpoly = node->get_navigation_polygon(); + if (navpoly.is_valid()) + return navpoly->get_outline_count(); + else + return 0; } -bool NavigationPolygonEditor::forward_gui_input(const Ref<InputEvent> &p_event) { - - if (!node) - return false; - - if (node->get_navigation_polygon().is_null()) { - - Ref<InputEventMouseButton> mb = p_event; - - if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) { - create_nav->set_text("No NavigationPolygon resource on this node.\nCreate and assign one?"); - create_nav->popup_centered_minsize(); - } - return (mb.is_valid() && mb->get_button_index() == 1); - } - - Ref<InputEventMouseButton> mb = p_event; - - if (mb.is_valid()) { - - Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); - - Vector2 gpoint = mb->get_position(); - Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint); - cpoint = canvas_item_editor->snap_point(cpoint); - cpoint = node->get_global_transform().affine_inverse().xform(cpoint); - - //first check if a point is to be added (segment split) - real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8); - - switch (mode) { - - case MODE_CREATE: { - - if (mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) { - - if (!wip_active) { - - wip.clear(); - wip.push_back(cpoint); - wip_active = true; - edited_point_pos = cpoint; - edited_outline = -1; - canvas_item_editor->get_viewport_control()->update(); - edited_point = 1; - return true; - } else { - - if (wip.size() > 1 && xform.xform(wip[0]).distance_to(gpoint) < grab_threshold) { - //wip closed - _wip_close(); - - return true; - } else { - - wip.push_back(cpoint); - edited_point = wip.size(); - canvas_item_editor->get_viewport_control()->update(); - return true; - - //add wip point - } - } - } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && wip_active) { - _wip_close(); - } - - } break; - - case MODE_EDIT: { - - if (mb->get_button_index() == BUTTON_LEFT) { - if (mb->is_pressed()) { - - if (mb->get_control()) { - - //search edges - int closest_outline = -1; - int closest_idx = -1; - Vector2 closest_pos; - real_t closest_dist = 1e10; - - for (int j = 0; j < node->get_navigation_polygon()->get_outline_count(); j++) { - - PoolVector<Vector2> points = node->get_navigation_polygon()->get_outline(j); - - int pc = points.size(); - PoolVector<Vector2>::Read poly = points.read(); - - for (int i = 0; i < pc; i++) { - - Vector2 points[2] = { xform.xform(poly[i]), - xform.xform(poly[(i + 1) % pc]) }; - - Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint, points); - if (cp.distance_squared_to(points[0]) < CMP_EPSILON2 || cp.distance_squared_to(points[1]) < CMP_EPSILON2) - continue; //not valid to reuse point - - real_t d = cp.distance_to(gpoint); - if (d < closest_dist && d < grab_threshold) { - closest_dist = d; - closest_outline = j; - closest_pos = cp; - closest_idx = i; - } - } - } - - if (closest_idx >= 0) { - - pre_move_edit = node->get_navigation_polygon()->get_outline(closest_outline); - PoolVector<Point2> poly = pre_move_edit; - poly.insert(closest_idx + 1, xform.affine_inverse().xform(closest_pos)); - edited_point = closest_idx + 1; - edited_outline = closest_outline; - edited_point_pos = xform.affine_inverse().xform(closest_pos); - node->get_navigation_polygon()->set_outline(closest_outline, poly); - canvas_item_editor->get_viewport_control()->update(); - return true; - } - } else { - - //look for points to move - int closest_outline = -1; - int closest_idx = -1; - Vector2 closest_pos; - real_t closest_dist = 1e10; - - for (int j = 0; j < node->get_navigation_polygon()->get_outline_count(); j++) { - - PoolVector<Vector2> points = node->get_navigation_polygon()->get_outline(j); - - int pc = points.size(); - PoolVector<Vector2>::Read poly = points.read(); +Variant NavigationPolygonEditor::_get_polygon(int p_idx) const { - for (int i = 0; i < pc; i++) { - - Vector2 cp = xform.xform(poly[i]); - - real_t d = cp.distance_to(gpoint); - if (d < closest_dist && d < grab_threshold) { - closest_dist = d; - closest_pos = cp; - closest_outline = j; - closest_idx = i; - } - } - } - - if (closest_idx >= 0) { - - pre_move_edit = node->get_navigation_polygon()->get_outline(closest_outline); - edited_point = closest_idx; - edited_outline = closest_outline; - edited_point_pos = xform.affine_inverse().xform(closest_pos); - canvas_item_editor->get_viewport_control()->update(); - return true; - } - } - } else { - - if (edited_point != -1) { - - //apply - - PoolVector<Vector2> poly = node->get_navigation_polygon()->get_outline(edited_outline); - ERR_FAIL_INDEX_V(edited_point, poly.size(), false); - poly.set(edited_point, edited_point_pos); - undo_redo->create_action(TTR("Edit Poly")); - undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "set_outline", edited_outline, poly); - undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "set_outline", edited_outline, pre_move_edit); - undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines"); - undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines"); - undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update"); - undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update"); - undo_redo->commit_action(); - - edited_point = -1; - return true; - } - } - } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && edited_point == -1) { - - int closest_outline = -1; - int closest_idx = -1; - Vector2 closest_pos; - real_t closest_dist = 1e10; - - for (int j = 0; j < node->get_navigation_polygon()->get_outline_count(); j++) { - - PoolVector<Vector2> points = node->get_navigation_polygon()->get_outline(j); - - int pc = points.size(); - PoolVector<Vector2>::Read poly = points.read(); - - for (int i = 0; i < pc; i++) { - - Vector2 cp = xform.xform(poly[i]); - - real_t d = cp.distance_to(gpoint); - if (d < closest_dist && d < grab_threshold) { - closest_dist = d; - closest_pos = cp; - closest_outline = j; - closest_idx = i; - } - } - } - - if (closest_idx >= 0) { - - PoolVector<Vector2> poly = node->get_navigation_polygon()->get_outline(closest_outline); - - if (poly.size() > 3) { - undo_redo->create_action(TTR("Edit Poly (Remove Point)")); - undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "set_outline", closest_outline, poly); - poly.remove(closest_idx); - undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "set_outline", closest_outline, poly); - undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines"); - undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines"); - undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update"); - undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update"); - undo_redo->commit_action(); - } else { - - undo_redo->create_action(TTR("Remove Poly And Point")); - undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "add_outline_at_index", poly, closest_outline); - poly.remove(closest_idx); - undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "remove_outline", closest_outline); - undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines"); - undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines"); - undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update"); - undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update"); - undo_redo->commit_action(); - } - return true; - } - } - - } break; - } - } - - Ref<InputEventMouseMotion> mm = p_event; - - if (mm.is_valid()) { - - if (edited_point != -1 && (wip_active || mm->get_button_mask() & BUTTON_MASK_LEFT)) { - - Vector2 gpoint = mm->get_position(); - Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint); - cpoint = canvas_item_editor->snap_point(cpoint); - edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint); - - canvas_item_editor->get_viewport_control()->update(); - } - } - - return false; + Ref<NavigationPolygon> navpoly = node->get_navigation_polygon(); + if (navpoly.is_valid()) + return navpoly->get_outline(p_idx); + else + return Variant(Vector<Vector2>()); } -void NavigationPolygonEditor::_canvas_draw() { - if (!node) - return; +void NavigationPolygonEditor::_set_polygon(int p_idx, const Variant &p_polygon) const { - Control *vpc = canvas_item_editor->get_viewport_control(); - if (node->get_navigation_polygon().is_null()) - return; - - Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); - Ref<Texture> handle = get_icon("EditorHandle", "EditorIcons"); - - for (int j = -1; j < node->get_navigation_polygon()->get_outline_count(); j++) { - Vector<Vector2> poly; - - if (wip_active && j == edited_outline) { - poly = wip; - } else { - if (j == -1) - continue; - poly = Variant(node->get_navigation_polygon()->get_outline(j)); - } - - for (int i = 0; i < poly.size(); i++) { - - Vector2 p, p2; - p = (j == edited_outline && i == edited_point) ? edited_point_pos : poly[i]; - if (j == edited_outline && ((wip_active && i == poly.size() - 1) || (((i + 1) % poly.size()) == edited_point))) - p2 = edited_point_pos; - else - p2 = poly[(i + 1) % poly.size()]; - - Vector2 point = xform.xform(p); - Vector2 next_point = xform.xform(p2); - - Color col = Color(1, 0.3, 0.1, 0.8); - vpc->draw_line(point, next_point, col, 2); - vpc->draw_texture(handle, point - handle->get_size() * 0.5); - } - } + Ref<NavigationPolygon> navpoly = _ensure_navpoly(); + navpoly->set_outline(p_idx, p_polygon); + navpoly->make_polygons_from_outlines(); } -void NavigationPolygonEditor::edit(Node *p_collision_polygon) { - - if (!canvas_item_editor) { - canvas_item_editor = CanvasItemEditor::get_singleton(); - } - - if (p_collision_polygon) { +void NavigationPolygonEditor::_action_add_polygon(const Variant &p_polygon) { - node = Object::cast_to<NavigationPolygonInstance>(p_collision_polygon); - //Enable the pencil tool if the polygon is empty - if (!node->get_navigation_polygon().is_null()) { - if (node->get_navigation_polygon()->get_polygon_count() == 0) - _menu_option(MODE_CREATE); - } - if (!canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw")) - canvas_item_editor->get_viewport_control()->connect("draw", this, "_canvas_draw"); - wip.clear(); - wip_active = false; - edited_point = -1; - canvas_item_editor->get_viewport_control()->update(); - - } else { - node = NULL; - - if (canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw")) - canvas_item_editor->get_viewport_control()->disconnect("draw", this, "_canvas_draw"); - } + Ref<NavigationPolygon> navpoly = _ensure_navpoly(); + undo_redo->add_do_method(navpoly.ptr(), "add_outline", p_polygon); + undo_redo->add_undo_method(navpoly.ptr(), "remove_outline", navpoly->get_outline_count()); + undo_redo->add_do_method(navpoly.ptr(), "make_polygons_from_outlines"); + undo_redo->add_undo_method(navpoly.ptr(), "make_polygons_from_outlines"); } -void NavigationPolygonEditor::_bind_methods() { +void NavigationPolygonEditor::_action_remove_polygon(int p_idx) { - ClassDB::bind_method(D_METHOD("_menu_option"), &NavigationPolygonEditor::_menu_option); - ClassDB::bind_method(D_METHOD("_canvas_draw"), &NavigationPolygonEditor::_canvas_draw); - ClassDB::bind_method(D_METHOD("_node_removed"), &NavigationPolygonEditor::_node_removed); - ClassDB::bind_method(D_METHOD("_create_nav"), &NavigationPolygonEditor::_create_nav); + Ref<NavigationPolygon> navpoly = _ensure_navpoly(); + undo_redo->add_do_method(navpoly.ptr(), "remove_outline", p_idx); + undo_redo->add_undo_method(navpoly.ptr(), "add_outline_at_index", navpoly->get_outline(p_idx), p_idx); + undo_redo->add_do_method(navpoly.ptr(), "make_polygons_from_outlines"); + undo_redo->add_undo_method(navpoly.ptr(), "make_polygons_from_outlines"); } -NavigationPolygonEditor::NavigationPolygonEditor(EditorNode *p_editor) { - node = NULL; - canvas_item_editor = NULL; - editor = p_editor; - undo_redo = editor->get_undo_redo(); +void NavigationPolygonEditor::_action_set_polygon(int p_idx, const Variant &p_previous, const Variant &p_polygon) { - add_child(memnew(VSeparator)); - button_create = memnew(ToolButton); - add_child(button_create); - button_create->connect("pressed", this, "_menu_option", varray(MODE_CREATE)); - button_create->set_toggle_mode(true); - button_create->set_tooltip(TTR("Create a new polygon from scratch.")); - - button_edit = memnew(ToolButton); - add_child(button_edit); - button_edit->connect("pressed", this, "_menu_option", varray(MODE_EDIT)); - button_edit->set_toggle_mode(true); - button_edit->set_tooltip(TTR("Edit existing polygon:") + "\n" + TTR("LMB: Move Point.") + "\n" + TTR("Ctrl+LMB: Split Segment.") + "\n" + TTR("RMB: Erase Point.")); - create_nav = memnew(ConfirmationDialog); - add_child(create_nav); - create_nav->get_ok()->set_text(TTR("Create")); - - mode = MODE_EDIT; - wip_active = false; - edited_outline = -1; + Ref<NavigationPolygon> navpoly = _ensure_navpoly(); + undo_redo->add_do_method(navpoly.ptr(), "set_outline", p_idx, p_polygon); + undo_redo->add_undo_method(navpoly.ptr(), "set_outline", p_idx, p_previous); + undo_redo->add_do_method(navpoly.ptr(), "make_polygons_from_outlines"); + undo_redo->add_undo_method(navpoly.ptr(), "make_polygons_from_outlines"); } -void NavigationPolygonEditorPlugin::edit(Object *p_object) { +bool NavigationPolygonEditor::_has_resource() const { - collision_polygon_editor->edit(Object::cast_to<Node>(p_object)); + return node && node->get_navigation_polygon().is_valid(); } -bool NavigationPolygonEditorPlugin::handles(Object *p_object) const { - - return p_object->is_class("NavigationPolygonInstance"); -} +void NavigationPolygonEditor::_create_resource() { -void NavigationPolygonEditorPlugin::make_visible(bool p_visible) { + if (!node) + return; - if (p_visible) { - collision_polygon_editor->show(); - } else { + undo_redo->create_action(TTR("Create Navigation Polygon")); + undo_redo->add_do_method(node, "set_navigation_polygon", Ref<NavigationPolygon>(memnew(NavigationPolygon))); + undo_redo->add_undo_method(node, "set_navigation_polygon", Variant(REF())); + undo_redo->commit_action(); - collision_polygon_editor->hide(); - collision_polygon_editor->edit(NULL); - } + _menu_option(MODE_CREATE); } -NavigationPolygonEditorPlugin::NavigationPolygonEditorPlugin(EditorNode *p_node) { - - editor = p_node; - collision_polygon_editor = memnew(NavigationPolygonEditor(p_node)); - CanvasItemEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor); - - collision_polygon_editor->hide(); +NavigationPolygonEditor::NavigationPolygonEditor(EditorNode *p_editor) + : AbstractPolygon2DEditor(p_editor) { } -NavigationPolygonEditorPlugin::~NavigationPolygonEditorPlugin() { +NavigationPolygonEditorPlugin::NavigationPolygonEditorPlugin(EditorNode *p_node) + : AbstractPolygon2DEditorPlugin(p_node, memnew(NavigationPolygonEditor(p_node)), "NavigationPolygonInstance") { } diff --git a/editor/plugins/navigation_polygon_editor_plugin.h b/editor/plugins/navigation_polygon_editor_plugin.h index 7dd555e9c9..54cc347a8c 100644..100755 --- a/editor/plugins/navigation_polygon_editor_plugin.h +++ b/editor/plugins/navigation_polygon_editor_plugin.h @@ -30,83 +30,45 @@ #ifndef NAVIGATIONPOLYGONEDITORPLUGIN_H #define NAVIGATIONPOLYGONEDITORPLUGIN_H -#include "editor/editor_node.h" -#include "editor/editor_plugin.h" +#include "editor/plugins/abstract_polygon_2d_editor.h" #include "scene/2d/navigation_polygon.h" -#include "scene/gui/tool_button.h" /** @author Juan Linietsky <reduzio@gmail.com> */ -class CanvasItemEditor; +class NavigationPolygonEditor : public AbstractPolygon2DEditor { -class NavigationPolygonEditor : public HBoxContainer { + GDCLASS(NavigationPolygonEditor, AbstractPolygon2DEditor); - GDCLASS(NavigationPolygonEditor, HBoxContainer); - - UndoRedo *undo_redo; - enum Mode { - - MODE_CREATE, - MODE_EDIT, - - }; - - Mode mode; - - ToolButton *button_create; - ToolButton *button_edit; - - ConfirmationDialog *create_nav; - - CanvasItemEditor *canvas_item_editor; - EditorNode *editor; - Panel *panel; NavigationPolygonInstance *node; - MenuButton *options; - int edited_outline; - int edited_point; - Vector2 edited_point_pos; - PoolVector<Vector2> pre_move_edit; - Vector<Vector2> wip; - bool wip_active; + Ref<NavigationPolygon> _ensure_navpoly() const; - void _wip_close(); - void _canvas_draw(); - void _create_nav(); +protected: + virtual Node2D *_get_node() const; + virtual void _set_node(Node *p_polygon); - void _menu_option(int p_option); + virtual int _get_polygon_count() const; + virtual Variant _get_polygon(int p_idx) const; + virtual void _set_polygon(int p_idx, const Variant &p_polygon) const; -protected: - void _notification(int p_what); - void _node_removed(Node *p_node); - static void _bind_methods(); + virtual void _action_add_polygon(const Variant &p_polygon); + virtual void _action_remove_polygon(int p_idx); + virtual void _action_set_polygon(int p_idx, const Variant &p_previous, const Variant &p_polygon); + + virtual bool _has_resource() const; + virtual void _create_resource(); public: - bool forward_gui_input(const Ref<InputEvent> &p_event); - void edit(Node *p_collision_polygon); NavigationPolygonEditor(EditorNode *p_editor); }; -class NavigationPolygonEditorPlugin : public EditorPlugin { +class NavigationPolygonEditorPlugin : public AbstractPolygon2DEditorPlugin { - GDCLASS(NavigationPolygonEditorPlugin, EditorPlugin); - - NavigationPolygonEditor *collision_polygon_editor; - EditorNode *editor; + GDCLASS(NavigationPolygonEditorPlugin, AbstractPolygon2DEditorPlugin); public: - virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) { return collision_polygon_editor->forward_gui_input(p_event); } - - virtual String get_name() const { return "NavigationPolygonInstance"; } - bool has_main_screen() const { return false; } - virtual void edit(Object *p_object); - virtual bool handles(Object *p_object) const; - virtual void make_visible(bool p_visible); - NavigationPolygonEditorPlugin(EditorNode *p_node); - ~NavigationPolygonEditorPlugin(); }; #endif // NAVIGATIONPOLYGONEDITORPLUGIN_H diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index af2349983d..0e8c13b067 100644..100755 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -35,15 +35,27 @@ #include "os/input.h" #include "os/keyboard.h" +Node2D *Polygon2DEditor::_get_node() const { + + return node; +} + +void Polygon2DEditor::_set_node(Node *p_polygon) { + + node = Object::cast_to<Polygon2D>(p_polygon); +} + +Vector2 Polygon2DEditor::_get_offset(int p_idx) const { + + return node->get_offset(); +} + void Polygon2DEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_READY: { - button_create->set_icon(get_icon("Edit", "EditorIcons")); - button_edit->set_icon(get_icon("MovePoint", "EditorIcons")); - button_edit->set_pressed(true); button_uv->set_icon(get_icon("Uv", "EditorIcons")); uv_button[UV_MODE_EDIT_POINT]->set_icon(get_icon("ToolSelect", "EditorIcons")); @@ -55,40 +67,17 @@ void Polygon2DEditor::_notification(int p_what) { b_snap_enable->set_icon(get_icon("SnapGrid", "EditorIcons")); uv_icon_zoom->set_texture(get_icon("Zoom", "EditorIcons")); - get_tree()->connect("node_removed", this, "_node_removed"); - } break; case NOTIFICATION_PHYSICS_PROCESS: { } break; } } -void Polygon2DEditor::_node_removed(Node *p_node) { - - if (p_node == node) { - edit(NULL); - hide(); - - canvas_item_editor->get_viewport_control()->update(); - } -} void Polygon2DEditor::_menu_option(int p_option) { switch (p_option) { - case MODE_CREATE: { - - mode = MODE_CREATE; - button_create->set_pressed(true); - button_edit->set_pressed(false); - } break; - case MODE_EDIT: { - - mode = MODE_EDIT; - button_create->set_pressed(false); - button_edit->set_pressed(true); - } break; case MODE_EDIT_UV: { if (node->get_texture().is_null()) { @@ -153,6 +142,9 @@ void Polygon2DEditor::_menu_option(int p_option) { undo_redo->commit_action(); } break; + default: { + AbstractPolygon2DEditor::_menu_option(p_option); + } break; } } @@ -185,289 +177,6 @@ void Polygon2DEditor::_set_snap_step_y(float p_val) { uv_edit_draw->update(); } -void Polygon2DEditor::_wip_close() { - - undo_redo->create_action(TTR("Create Poly")); - undo_redo->add_undo_method(node, "set_polygon", node->get_polygon()); - undo_redo->add_do_method(node, "set_polygon", wip); - undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update"); - undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update"); - undo_redo->commit_action(); - wip.clear(); - wip_active = false; - mode = MODE_EDIT; - button_edit->set_pressed(true); - button_create->set_pressed(false); - edited_point = -1; -} - -bool Polygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { - - if (node == NULL) - return false; - - Ref<InputEventMouseButton> mb = p_event; - - if (mb.is_valid()) { - - Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); - - Vector2 gpoint = mb->get_position(); - Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint); - cpoint = canvas_item_editor->snap_point(cpoint); - cpoint = node->get_global_transform().affine_inverse().xform(cpoint); - - Vector<Vector2> poly = Variant(node->get_polygon()); - - //first check if a point is to be added (segment split) - real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8); - - switch (mode) { - - case MODE_CREATE: { - - if (mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) { - - if (!wip_active) { - - wip.clear(); - wip.push_back(cpoint - node->get_offset()); - wip_active = true; - edited_point_pos = cpoint; - canvas_item_editor->get_viewport_control()->update(); - edited_point = 1; - return true; - } else { - - if (wip.size() > 1 && xform.xform(wip[0] + node->get_offset()).distance_to(gpoint) < grab_threshold) { - //wip closed - _wip_close(); - - return true; - } else { - - wip.push_back(cpoint - node->get_offset()); - edited_point = wip.size(); - canvas_item_editor->get_viewport_control()->update(); - return true; - - //add wip point - } - } - } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && wip_active) { - _wip_close(); - } - - } break; - - case MODE_EDIT: { - - if (mb->get_button_index() == BUTTON_LEFT) { - if (mb->is_pressed()) { - - if (mb->get_control()) { - - if (poly.size() < 3) { - - undo_redo->create_action(TTR("Edit Poly")); - undo_redo->add_undo_method(node, "set_polygon", poly); - poly.push_back(cpoint); - undo_redo->add_do_method(node, "set_polygon", poly); - undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update"); - undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update"); - undo_redo->commit_action(); - return true; - } - - //search edges - int closest_idx = -1; - Vector2 closest_pos; - real_t closest_dist = 1e10; - for (int i = 0; i < poly.size(); i++) { - - Vector2 points[2] = { xform.xform(poly[i] + node->get_offset()), - xform.xform(poly[(i + 1) % poly.size()] + node->get_offset()) }; - - Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint, points); - if (cp.distance_squared_to(points[0]) < CMP_EPSILON2 || cp.distance_squared_to(points[1]) < CMP_EPSILON2) - continue; //not valid to reuse point - - real_t d = cp.distance_to(gpoint); - if (d < closest_dist && d < grab_threshold) { - closest_dist = d; - closest_pos = cp; - closest_idx = i; - } - } - - if (closest_idx >= 0) { - - pre_move_edit = poly; - poly.insert(closest_idx + 1, xform.affine_inverse().xform(closest_pos) - node->get_offset()); - edited_point = closest_idx + 1; - edited_point_pos = xform.affine_inverse().xform(closest_pos); - node->set_polygon(Variant(poly)); - canvas_item_editor->get_viewport_control()->update(); - return true; - } - } else { - - //look for points to move - - int closest_idx = -1; - Vector2 closest_pos; - real_t closest_dist = 1e10; - for (int i = 0; i < poly.size(); i++) { - - Vector2 cp = xform.xform(poly[i] + node->get_offset()); - - real_t d = cp.distance_to(gpoint); - if (d < closest_dist && d < grab_threshold) { - closest_dist = d; - closest_pos = cp; - closest_idx = i; - } - } - - if (closest_idx >= 0) { - - pre_move_edit = poly; - edited_point = closest_idx; - edited_point_pos = xform.affine_inverse().xform(closest_pos); - canvas_item_editor->get_viewport_control()->update(); - return true; - } - } - } else { - - if (edited_point != -1) { - - //apply - - ERR_FAIL_INDEX_V(edited_point, poly.size(), false); - poly[edited_point] = edited_point_pos - node->get_offset(); - undo_redo->create_action(TTR("Edit Poly")); - undo_redo->add_do_method(node, "set_polygon", poly); - undo_redo->add_undo_method(node, "set_polygon", pre_move_edit); - undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update"); - undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update"); - undo_redo->commit_action(); - - edited_point = -1; - return true; - } - } - } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && edited_point == -1) { - - int closest_idx = -1; - Vector2 closest_pos; - real_t closest_dist = 1e10; - for (int i = 0; i < poly.size(); i++) { - - Vector2 cp = xform.xform(poly[i] + node->get_offset()); - - real_t d = cp.distance_to(gpoint); - if (d < closest_dist && d < grab_threshold) { - closest_dist = d; - closest_pos = cp; - closest_idx = i; - } - } - - if (closest_idx >= 0) { - - undo_redo->create_action(TTR("Edit Poly (Remove Point)")); - undo_redo->add_undo_method(node, "set_polygon", poly); - poly.remove(closest_idx); - undo_redo->add_do_method(node, "set_polygon", poly); - undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update"); - undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update"); - undo_redo->commit_action(); - return true; - } - } - - } break; - } - } - - Ref<InputEventMouseMotion> mm = p_event; - - if (mm.is_valid()) { - - if (edited_point != -1 && (wip_active || (mm->get_button_mask() & BUTTON_MASK_LEFT))) { - - Vector2 gpoint = mm->get_position(); - Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint); - cpoint = canvas_item_editor->snap_point(cpoint); - edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint); - - if (!wip_active) { - - Vector<Vector2> poly = Variant(node->get_polygon()); - ERR_FAIL_INDEX_V(edited_point, poly.size(), false); - poly[edited_point] = edited_point_pos - node->get_offset(); - node->set_polygon(Variant(poly)); - } - - canvas_item_editor->get_viewport_control()->update(); - } - } - - return false; -} -void Polygon2DEditor::_canvas_draw() { - - if (!node) - return; - - Control *vpc = canvas_item_editor->get_viewport_control(); - - Vector<Vector2> poly; - - if (wip_active) - poly = wip; - else - poly = Variant(node->get_polygon()); - - Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); - Ref<Texture> handle = get_icon("EditorHandle", "EditorIcons"); - - if (!wip_active && edited_point >= 0 && EDITOR_DEF("editors/poly_editor/show_previous_outline", true)) { - - const Color col = node->get_color().contrasted(); - const int n = pre_move_edit.size(); - for (int i = 0; i < n; i++) { - - Vector2 p, p2; - p = pre_move_edit[i] + node->get_offset(); - p2 = pre_move_edit[(i + 1) % n] + node->get_offset(); - - Vector2 point = xform.xform(p); - Vector2 next_point = xform.xform(p2); - - vpc->draw_line(point, next_point, col, 2); - } - } - - for (int i = 0; i < poly.size(); i++) { - - Vector2 p, p2; - p = i == edited_point ? edited_point_pos : (poly[i] + node->get_offset()); - if ((wip_active && i == poly.size() - 1) || (((i + 1) % poly.size()) == edited_point)) - p2 = edited_point_pos; - else - p2 = poly[(i + 1) % poly.size()] + node->get_offset(); - - Vector2 point = xform.xform(p); - Vector2 next_point = xform.xform(p2); - - Color col = Color(1, 0.3, 0.1, 0.8); - vpc->draw_line(point, next_point, col, 2); - vpc->draw_texture(handle, point - handle->get_size() * 0.5); - } -} - void Polygon2DEditor::_uv_mode(int p_mode) { uv_mode = UVMode(p_mode); @@ -714,44 +423,12 @@ void Polygon2DEditor::_uv_draw() { updating_uv_scroll = false; } -void Polygon2DEditor::edit(Node *p_collision_polygon) { - - if (!canvas_item_editor) { - canvas_item_editor = CanvasItemEditor::get_singleton(); - } - - if (p_collision_polygon) { - - node = Object::cast_to<Polygon2D>(p_collision_polygon); - //Enable the pencil tool if the polygon is empty - if (node->get_polygon().size() == 0) { - _menu_option(MODE_CREATE); - } - if (!canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw")) - canvas_item_editor->get_viewport_control()->connect("draw", this, "_canvas_draw"); - - wip.clear(); - wip_active = false; - edited_point = -1; - - } else { - - node = NULL; - - if (canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw")) - canvas_item_editor->get_viewport_control()->disconnect("draw", this, "_canvas_draw"); - } -} - void Polygon2DEditor::_bind_methods() { - ClassDB::bind_method(D_METHOD("_menu_option"), &Polygon2DEditor::_menu_option); - ClassDB::bind_method(D_METHOD("_canvas_draw"), &Polygon2DEditor::_canvas_draw); ClassDB::bind_method(D_METHOD("_uv_mode"), &Polygon2DEditor::_uv_mode); ClassDB::bind_method(D_METHOD("_uv_draw"), &Polygon2DEditor::_uv_draw); ClassDB::bind_method(D_METHOD("_uv_input"), &Polygon2DEditor::_uv_input); ClassDB::bind_method(D_METHOD("_uv_scroll_changed"), &Polygon2DEditor::_uv_scroll_changed); - ClassDB::bind_method(D_METHOD("_node_removed"), &Polygon2DEditor::_node_removed); ClassDB::bind_method(D_METHOD("_set_use_snap"), &Polygon2DEditor::_set_use_snap); ClassDB::bind_method(D_METHOD("_set_show_grid"), &Polygon2DEditor::_set_show_grid); ClassDB::bind_method(D_METHOD("_set_snap_off_x"), &Polygon2DEditor::_set_snap_off_x); @@ -773,35 +450,17 @@ Vector2 Polygon2DEditor::snap_point(Vector2 p_target) const { return p_target; } -Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) { - - node = NULL; - canvas_item_editor = NULL; - editor = p_editor; - undo_redo = editor->get_undo_redo(); +Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) + : AbstractPolygon2DEditor(p_editor) { snap_step = Vector2(10, 10); use_snap = false; snap_show_grid = false; - add_child(memnew(VSeparator)); - button_create = memnew(ToolButton); - add_child(button_create); - button_create->connect("pressed", this, "_menu_option", varray(MODE_CREATE)); - button_create->set_toggle_mode(true); - - button_edit = memnew(ToolButton); - add_child(button_edit); - button_edit->connect("pressed", this, "_menu_option", varray(MODE_EDIT)); - button_edit->set_toggle_mode(true); - button_uv = memnew(ToolButton); add_child(button_uv); button_uv->connect("pressed", this, "_menu_option", varray(MODE_EDIT_UV)); - mode = MODE_EDIT; - wip_active = false; - uv_mode = UV_MODE_EDIT_POINT; uv_edit = memnew(AcceptDialog); add_child(uv_edit); @@ -941,35 +600,6 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) { uv_edit_draw->set_clip_contents(true); } -void Polygon2DEditorPlugin::edit(Object *p_object) { - - collision_polygon_editor->edit(Object::cast_to<Node>(p_object)); -} - -bool Polygon2DEditorPlugin::handles(Object *p_object) const { - - return p_object->is_class("Polygon2D"); -} - -void Polygon2DEditorPlugin::make_visible(bool p_visible) { - - if (p_visible) { - collision_polygon_editor->show(); - } else { - - collision_polygon_editor->hide(); - collision_polygon_editor->edit(NULL); - } -} - -Polygon2DEditorPlugin::Polygon2DEditorPlugin(EditorNode *p_node) { - - editor = p_node; - collision_polygon_editor = memnew(Polygon2DEditor(p_node)); - CanvasItemEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor); - - collision_polygon_editor->hide(); -} - -Polygon2DEditorPlugin::~Polygon2DEditorPlugin() { +Polygon2DEditorPlugin::Polygon2DEditorPlugin(EditorNode *p_node) + : AbstractPolygon2DEditorPlugin(p_node, memnew(Polygon2DEditor(p_node)), "Polygon2D") { } diff --git a/editor/plugins/polygon_2d_editor_plugin.h b/editor/plugins/polygon_2d_editor_plugin.h index f9d6a6b4b6..90da3e61c1 100644..100755 --- a/editor/plugins/polygon_2d_editor_plugin.h +++ b/editor/plugins/polygon_2d_editor_plugin.h @@ -30,26 +30,18 @@ #ifndef POLYGON_2D_EDITOR_PLUGIN_H #define POLYGON_2D_EDITOR_PLUGIN_H -#include "editor/editor_node.h" -#include "editor/editor_plugin.h" -#include "scene/2d/polygon_2d.h" -#include "scene/gui/tool_button.h" +#include "editor/plugins/abstract_polygon_2d_editor.h" /** @author Juan Linietsky <reduzio@gmail.com> */ -class CanvasItemEditor; +class Polygon2DEditor : public AbstractPolygon2DEditor { -class Polygon2DEditor : public HBoxContainer { + GDCLASS(Polygon2DEditor, AbstractPolygon2DEditor); - GDCLASS(Polygon2DEditor, HBoxContainer); - - UndoRedo *undo_redo; enum Mode { - MODE_CREATE, - MODE_EDIT, - MODE_EDIT_UV, + MODE_EDIT_UV = MODE_CONT, UVEDIT_POLYGON_TO_UV, UVEDIT_UV_TO_POLYGON, UVEDIT_UV_CLEAR @@ -64,7 +56,7 @@ class Polygon2DEditor : public HBoxContainer { UV_MODE_MAX }; - Mode mode; + Polygon2D *node; UVMode uv_mode; AcceptDialog *uv_edit; @@ -90,34 +82,19 @@ class Polygon2DEditor : public HBoxContainer { AcceptDialog *error; - ToolButton *button_create; - ToolButton *button_edit; ToolButton *button_uv; - CanvasItemEditor *canvas_item_editor; - EditorNode *editor; - Panel *panel; - Polygon2D *node; - MenuButton *options; - - int edited_point; - Vector2 edited_point_pos; - Vector<Vector2> pre_move_edit; - Vector<Vector2> wip; - bool wip_active; - bool use_snap; bool snap_show_grid; Vector2 snap_offset; Vector2 snap_step; + virtual void _menu_option(int p_option); + void _uv_scroll_changed(float); void _uv_input(const Ref<InputEvent> &p_input); void _uv_draw(); void _uv_mode(int p_mode); - void _wip_close(); - void _canvas_draw(); - void _menu_option(int p_option); void _set_use_snap(bool p_use); void _set_show_grid(bool p_show); @@ -127,36 +104,26 @@ class Polygon2DEditor : public HBoxContainer { void _set_snap_step_y(float p_val); protected: + virtual Node2D *_get_node() const; + virtual void _set_node(Node *p_polygon); + + virtual Vector2 _get_offset(int p_idx) const; + void _notification(int p_what); - void _node_removed(Node *p_node); static void _bind_methods(); Vector2 snap_point(Vector2 p_target) const; public: - bool forward_gui_input(const Ref<InputEvent> &p_event); - void edit(Node *p_collision_polygon); Polygon2DEditor(EditorNode *p_editor); }; -class Polygon2DEditorPlugin : public EditorPlugin { - - GDCLASS(Polygon2DEditorPlugin, EditorPlugin); +class Polygon2DEditorPlugin : public AbstractPolygon2DEditorPlugin { - Polygon2DEditor *collision_polygon_editor; - EditorNode *editor; + GDCLASS(Polygon2DEditorPlugin, AbstractPolygon2DEditorPlugin); public: - virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) { return collision_polygon_editor->forward_gui_input(p_event); } - - virtual String get_name() const { return "Polygon2D"; } - bool has_main_screen() const { return false; } - virtual void edit(Object *p_object); - virtual bool handles(Object *p_object) const; - virtual void make_visible(bool p_visible); - Polygon2DEditorPlugin(EditorNode *p_node); - ~Polygon2DEditorPlugin(); }; #endif // POLYGON_2D_EDITOR_PLUGIN_H diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 5e66488afb..477d440f28 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -1278,7 +1278,11 @@ void ScriptEditor::_members_overview_selected(int p_idx) { if (!se) { return; } - se->goto_line(members_overview->get_item_metadata(p_idx)); + Dictionary state; + state["scroll_position"] = members_overview->get_item_metadata(p_idx); + state["column"] = 0; + state["row"] = members_overview->get_item_metadata(p_idx); + se->set_edit_state(state); se->ensure_focus(); } diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index a24856dad7..adf65c11e1 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -529,9 +529,9 @@ void ScriptTextEditor::ensure_focus() { void ScriptTextEditor::set_edit_state(const Variant &p_state) { Dictionary state = p_state; - code_editor->get_text_edit()->set_v_scroll(state["scroll_position"]); code_editor->get_text_edit()->cursor_set_column(state["column"]); code_editor->get_text_edit()->cursor_set_line(state["row"]); + code_editor->get_text_edit()->set_v_scroll(state["scroll_position"]); code_editor->get_text_edit()->grab_focus(); //int scroll_pos; diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index 425390723c..32973db6ec 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -1442,6 +1442,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { case TRANSFORM_ROTATE: { Plane plane; + Vector3 axis; switch (_edit.plane) { case TRANSFORM_VIEW: @@ -1449,12 +1450,15 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { break; case TRANSFORM_X_AXIS: plane = Plane(_edit.center, spatial_editor->get_gizmo_transform().basis.get_axis(0)); + axis = Vector3(1, 0, 0); break; case TRANSFORM_Y_AXIS: plane = Plane(_edit.center, spatial_editor->get_gizmo_transform().basis.get_axis(1)); + axis = Vector3(0, 1, 0); break; case TRANSFORM_Z_AXIS: plane = Plane(_edit.center, spatial_editor->get_gizmo_transform().basis.get_axis(2)); + axis = Vector3(0, 0, 1); break; } @@ -1470,6 +1474,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { Vector3 x_axis = plane.normal.cross(y_axis).normalized(); float angle = Math::atan2(x_axis.dot(intersection - _edit.center), y_axis.dot(intersection - _edit.center)); + if (_edit.snap || spatial_editor->is_snap_enabled()) { float snap = spatial_editor->get_rotate_snap(); @@ -1486,11 +1491,10 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { set_message(vformat(TTR("Rotating %s degrees."), rtos(Math::rad2deg(angle)))); } - Transform r; - r.basis.rotate(plane.normal, angle); - List<Node *> &selection = editor_selection->get_selected_node_list(); + bool local_coords = spatial_editor->are_local_coords_enabled(); + for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { Spatial *sp = Object::cast_to<Spatial>(E->get()); @@ -1501,27 +1505,33 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { if (!se) continue; - Transform original = se->original; + Transform t; - Transform base = Transform(Basis(), _edit.center); - Transform t = base * r * base.inverse() * original; + if (local_coords) { - sp->set_global_transform(t); + Transform original_local = se->original_local; + Basis rot = Basis(axis, angle); + + t.basis = original_local.get_basis() * rot; + t.origin = original_local.origin; + + sp->set_transform(t); + + } else { + + Transform original = se->original; + Transform r; + Transform base = Transform(Basis(), _edit.center); + + r.basis.rotate(plane.normal, angle); + t = base * r * base.inverse() * original; + + sp->set_global_transform(t); + } } surface->update(); - /* - VisualServer::get_singleton()->poly_clear(indicators); - - Vector<Vector3> points; - Vector<Vector3> empty; - Vector<Color> colors; - points.push_back(intersection); - points.push_back(_edit.original.origin); - colors.push_back( Color(255,155,100) ); - colors.push_back( Color(255,155,100) ); - VisualServer::get_singleton()->poly_add_primitive(indicators,points,empty,colors,empty); - */ + } break; default: {} } diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 1fb3fb2ed1..9f23df5c03 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -1420,7 +1420,8 @@ ProjectManager::ProjectManager() { { int dpi_mode = EditorSettings::get_singleton()->get("interface/editor/hidpi_mode"); if (dpi_mode == 0) { - editor_set_scale(OS::get_singleton()->get_screen_dpi(0) >= 192 && OS::get_singleton()->get_screen_size(OS::get_singleton()->get_current_screen()).x > 2000 ? 2.0 : 1.0); + const int screen = OS::get_singleton()->get_current_screen(); + editor_set_scale(OS::get_singleton()->get_screen_dpi(screen) >= 192 && OS::get_singleton()->get_screen_size(screen).x > 2000 ? 2.0 : 1.0); } else if (dpi_mode == 1) { editor_set_scale(0.75); } else if (dpi_mode == 2) { diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index 47ebf49c43..658f67d6a4 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -861,7 +861,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: names.push_back(TTR("Assign")); names.push_back(TTR("Clear")); - if (owner->is_class("Node") && (v.get_type() == Variant::NODE_PATH) && Object::cast_to<Node>(owner)->has_node(v)) + if (owner && owner->is_class("Node") && (v.get_type() == Variant::NODE_PATH) && Object::cast_to<Node>(owner)->has_node(v)) names.push_back(TTR("Select Node")); config_action_buttons(names); |