diff --git a/editor/plugins/light_occluder_2d_editor_plugin.cpp b/editor/plugins/light_occluder_2d_editor_plugin.cpp index 6a16cf0989b..646883fbda5 100644 --- a/editor/plugins/light_occluder_2d_editor_plugin.cpp +++ b/editor/plugins/light_occluder_2d_editor_plugin.cpp @@ -30,425 +30,91 @@ #include "light_occluder_2d_editor_plugin.h" -#include "canvas_item_editor_plugin.h" -#include "core/os/file_access.h" -#include "editor/editor_settings.h" +Ref LightOccluder2DEditor::_ensure_occluder() const { -void LightOccluder2DEditor::_notification(int p_what) { + Ref occluder = node->get_occluder_polygon(); + if (!occluder.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_poly->connect("confirmed", this, "_create_poly"); - - } break; - case NOTIFICATION_PHYSICS_PROCESS: { - - } break; - } -} -void LightOccluder2DEditor::_node_removed(Node *p_node) { - - if (p_node == node) { - node = NULL; - hide(); - canvas_item_editor->update_viewport(); + occluder = Ref(memnew(OccluderPolygon2D)); + node->set_occluder_polygon(occluder); } + return occluder; } -void LightOccluder2DEditor::_menu_option(int p_option) { +Node2D *LightOccluder2DEditor::_get_node() const { - 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; - } + return node; } -void LightOccluder2DEditor::_wip_close(bool p_closed) { +void LightOccluder2DEditor::_set_node(Node *p_polygon) { - undo_redo->create_action(TTR("Create Poly")); - undo_redo->add_undo_method(node->get_occluder_polygon().ptr(), "set_polygon", node->get_occluder_polygon()->get_polygon()); - undo_redo->add_do_method(node->get_occluder_polygon().ptr(), "set_polygon", wip); - undo_redo->add_undo_method(node->get_occluder_polygon().ptr(), "set_closed", node->get_occluder_polygon()->is_closed()); - undo_redo->add_do_method(node->get_occluder_polygon().ptr(), "set_closed", p_closed); - - undo_redo->add_do_method(canvas_item_editor, "update_viewport"); - undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); - 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; + node = Object::cast_to(p_polygon); } -bool LightOccluder2DEditor::forward_gui_input(const Ref &p_event) { +bool LightOccluder2DEditor::_is_line() const { - if (!node) - return false; - - if (node->get_occluder_polygon().is_null()) { - Ref mb = p_event; - if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) { - create_poly->set_text(TTR("No OccluderPolygon2D resource on this node.\nCreate and assign one?")); - create_poly->popup_centered_minsize(); - } - return (mb.is_valid() && mb->get_button_index() == 1); - } - - Ref 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 = node->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mb->get_position()))); - - Vector poly = Variant(node->get_occluder_polygon()->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->update_viewport(); - edited_point = 1; - return true; - } else { - - if (wip.size() > 1 && xform.xform(wip[0]).distance_to(gpoint) < grab_threshold) { - //wip closed - _wip_close(true); - - return true; - } else if (wip.size() > 1 && xform.xform(wip[wip.size() - 1]).distance_to(gpoint) < grab_threshold) { - //wip closed - _wip_close(false); - return true; - - } else { - - wip.push_back(cpoint); - edited_point = wip.size(); - canvas_item_editor->update_viewport(); - return true; - - //add wip point - } - } - } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && wip_active) { - _wip_close(true); - } - - } 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->get_occluder_polygon().ptr(), "set_polygon", poly); - poly.push_back(cpoint); - undo_redo->add_do_method(node->get_occluder_polygon().ptr(), "set_polygon", poly); - undo_redo->add_do_method(canvas_item_editor, "update_viewport"); - undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); - 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->get_occluder_polygon()->set_polygon(Variant(poly)); - canvas_item_editor->update_viewport(); - 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->update_viewport(); - return true; - } - } - } else { - - if (edited_point != -1) { - - //apply - - ERR_FAIL_INDEX_V(edited_point, poly.size(), false); - poly.write[edited_point] = edited_point_pos; - undo_redo->create_action(TTR("Edit Poly")); - undo_redo->add_do_method(node->get_occluder_polygon().ptr(), "set_polygon", poly); - undo_redo->add_undo_method(node->get_occluder_polygon().ptr(), "set_polygon", pre_move_edit); - undo_redo->add_do_method(canvas_item_editor, "update_viewport"); - undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); - 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->get_occluder_polygon().ptr(), "set_polygon", poly); - poly.remove(closest_idx); - undo_redo->add_do_method(node->get_occluder_polygon().ptr(), "set_polygon", poly); - undo_redo->add_do_method(canvas_item_editor, "update_viewport"); - undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); - undo_redo->commit_action(); - return true; - } - } - - } break; - } - } - - Ref 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->update_viewport(); - } - } - - return false; -} - -void LightOccluder2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { - - if (!node || !node->get_occluder_polygon().is_valid()) - return; - - Vector poly; - - if (wip_active) - poly = wip; + Ref occluder = node->get_occluder_polygon(); + if (occluder.is_valid()) + return !occluder->is_closed(); else - poly = Variant(node->get_occluder_polygon()->get_polygon()); - - Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); - Ref handle = get_icon("EditorHandle", "EditorIcons"); - - 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); - - if (i == poly.size() - 1 && (!node->get_occluder_polygon()->is_closed() || wip_active)) { - - } else { - p_overlay->draw_line(point, next_point, col, 2); - } - p_overlay->draw_texture(handle, point - handle->get_size() * 0.5); - } + return false; } -void LightOccluder2DEditor::edit(Node *p_collision_polygon) { +int LightOccluder2DEditor::_get_polygon_count() const { - if (!canvas_item_editor) { - canvas_item_editor = CanvasItemEditor::get_singleton(); - } - - if (p_collision_polygon) { - - node = Object::cast_to(p_collision_polygon); - wip.clear(); - wip_active = false; - edited_point = -1; - canvas_item_editor->update_viewport(); - } else { - node = NULL; - } + Ref occluder = node->get_occluder_polygon(); + if (occluder.is_valid()) + return occluder->get_polygon().size(); + else + return 0; } -void LightOccluder2DEditor::_create_poly() { +Variant LightOccluder2DEditor::_get_polygon(int p_idx) const { + + Ref occluder = node->get_occluder_polygon(); + if (occluder.is_valid()) + return occluder->get_polygon(); + else + return Variant(Vector()); +} + +void LightOccluder2DEditor::_set_polygon(int p_idx, const Variant &p_polygon) const { + + Ref occluder = _ensure_occluder(); + occluder->set_polygon(p_polygon); +} + +void LightOccluder2DEditor::_action_set_polygon(int p_idx, const Variant &p_previous, const Variant &p_polygon) { + + Ref occluder = _ensure_occluder(); + undo_redo->add_do_method(occluder.ptr(), "set_polygon", p_polygon); + undo_redo->add_undo_method(occluder.ptr(), "set_polygon", p_previous); +} + +bool LightOccluder2DEditor::_has_resource() const { + + return node && node->get_occluder_polygon().is_valid(); +} + +void LightOccluder2DEditor::_create_resource() { if (!node) return; + undo_redo->create_action(TTR("Create Occluder Polygon")); undo_redo->add_do_method(node, "set_occluder_polygon", Ref(memnew(OccluderPolygon2D))); undo_redo->add_undo_method(node, "set_occluder_polygon", Variant(REF())); undo_redo->commit_action(); + + _menu_option(MODE_CREATE); } -void LightOccluder2DEditor::_bind_methods() { - - ClassDB::bind_method(D_METHOD("_menu_option"), &LightOccluder2DEditor::_menu_option); - ClassDB::bind_method(D_METHOD("_node_removed"), &LightOccluder2DEditor::_node_removed); - ClassDB::bind_method(D_METHOD("_create_poly"), &LightOccluder2DEditor::_create_poly); -} - -LightOccluder2DEditor::LightOccluder2DEditor(EditorNode *p_editor) { +LightOccluder2DEditor::LightOccluder2DEditor(EditorNode *p_editor) : + AbstractPolygon2DEditor(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:") + "\n" + TTR("LMB: Move Point.") + "\n" + TTR("Ctrl+LMB: Split Segment.") + "\n" + TTR("RMB: Erase Point.")); - - create_poly = memnew(ConfirmationDialog); - add_child(create_poly); - create_poly->get_ok()->set_text(TTR("Create")); - - mode = MODE_EDIT; - wip_active = false; } -void LightOccluder2DEditorPlugin::edit(Object *p_object) { - - light_occluder_editor->edit(Object::cast_to(p_object)); -} - -bool LightOccluder2DEditorPlugin::handles(Object *p_object) const { - - return p_object->is_class("LightOccluder2D"); -} - -void LightOccluder2DEditorPlugin::make_visible(bool p_visible) { - - if (p_visible) { - light_occluder_editor->show(); - } else { - - light_occluder_editor->hide(); - light_occluder_editor->edit(NULL); - } -} - -LightOccluder2DEditorPlugin::LightOccluder2DEditorPlugin(EditorNode *p_node) { - - editor = p_node; - light_occluder_editor = memnew(LightOccluder2DEditor(p_node)); - CanvasItemEditor::get_singleton()->add_control_to_menu_panel(light_occluder_editor); - - light_occluder_editor->hide(); -} - -LightOccluder2DEditorPlugin::~LightOccluder2DEditorPlugin() { +LightOccluder2DEditorPlugin::LightOccluder2DEditorPlugin(EditorNode *p_node) : + AbstractPolygon2DEditorPlugin(p_node, memnew(LightOccluder2DEditor(p_node)), "LightOccluder2D") { } diff --git a/editor/plugins/light_occluder_2d_editor_plugin.h b/editor/plugins/light_occluder_2d_editor_plugin.h index a1962892ee2..6117d50e898 100644 --- a/editor/plugins/light_occluder_2d_editor_plugin.h +++ b/editor/plugins/light_occluder_2d_editor_plugin.h @@ -31,83 +31,44 @@ #ifndef LIGHT_OCCLUDER_2D_EDITOR_PLUGIN_H #define LIGHT_OCCLUDER_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/light_occluder_2d.h" -#include "scene/gui/tool_button.h" /** @author Juan Linietsky */ -class CanvasItemEditor; +class LightOccluder2DEditor : public AbstractPolygon2DEditor { -class LightOccluder2DEditor : public HBoxContainer { + GDCLASS(LightOccluder2DEditor, AbstractPolygon2DEditor); - GDCLASS(LightOccluder2DEditor, 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; LightOccluder2D *node; - MenuButton *options; - int edited_point; - Vector2 edited_point_pos; - Vector pre_move_edit; - Vector wip; - bool wip_active; - - ConfirmationDialog *create_poly; - - void _wip_close(bool p_closed); - void _menu_option(int p_option); - void _create_poly(); + Ref _ensure_occluder() const; 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); + + virtual bool _is_line() const; + 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; + + 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: - Vector2 snap_point(const Vector2 &p_point) const; - void forward_canvas_draw_over_viewport(Control *p_overlay); - bool forward_gui_input(const Ref &p_event); - void edit(Node *p_collision_polygon); LightOccluder2DEditor(EditorNode *p_editor); }; -class LightOccluder2DEditorPlugin : public EditorPlugin { +class LightOccluder2DEditorPlugin : public AbstractPolygon2DEditorPlugin { - GDCLASS(LightOccluder2DEditorPlugin, EditorPlugin); - - LightOccluder2DEditor *light_occluder_editor; - EditorNode *editor; + GDCLASS(LightOccluder2DEditorPlugin, AbstractPolygon2DEditorPlugin); public: - virtual bool forward_canvas_gui_input(const Ref &p_event) { return light_occluder_editor->forward_gui_input(p_event); } - virtual void forward_canvas_draw_over_viewport(Control *p_overlay) { return light_occluder_editor->forward_canvas_draw_over_viewport(p_overlay); } - - virtual String get_name() const { return "LightOccluder2D"; } - 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); - LightOccluder2DEditorPlugin(EditorNode *p_node); - ~LightOccluder2DEditorPlugin(); }; #endif // LIGHT_OCCLUDER_2D_EDITOR_PLUGIN_H