diff options
Diffstat (limited to 'editor/plugins')
79 files changed, 2448 insertions, 1922 deletions
diff --git a/editor/plugins/SCsub b/editor/plugins/SCsub index f1fa50148f..2b1e889fb0 100644 --- a/editor/plugins/SCsub +++ b/editor/plugins/SCsub @@ -1,5 +1,5 @@ #!/usr/bin/env python Import('env') -Export('env') + env.add_source_files(env.editor_sources, "*.cpp") diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index 2d341cdd93..16423decc4 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -132,8 +132,8 @@ Vector2 AbstractPolygon2DEditor::_get_offset(int p_idx) const { 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->add_do_method(canvas_item_editor, "update_viewport"); + undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); undo_redo->commit_action(); } @@ -218,7 +218,7 @@ void AbstractPolygon2DEditor::_node_removed(Node *p_node) { edit(NULL); hide(); - canvas_item_editor->get_viewport_control()->update(); + canvas_item_editor->update_viewport(); } } @@ -229,6 +229,18 @@ void AbstractPolygon2DEditor::_wip_changed() { } } +void AbstractPolygon2DEditor::_wip_cancel() { + + wip.clear(); + wip_active = false; + + edited_point = PosVertex(); + hover_point = Vertex(); + selected_point = Vertex(); + + canvas_item_editor->update_viewport(); +} + void AbstractPolygon2DEditor::_wip_close() { if (!wip_active) return; @@ -275,6 +287,10 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) return (mb.is_valid() && mb->get_button_index() == 1); } + CanvasItemEditor::Tool tool = CanvasItemEditor::get_singleton()->get_current_tool(); + if (tool != CanvasItemEditor::TOOL_SELECT) + return false; + if (mb.is_valid()) { Transform2D xform = canvas_item_editor->get_canvas_transform() * _get_node()->get_global_transform(); @@ -283,10 +299,10 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) Vector2 cpoint = _get_node()->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mb->get_position()))); if (mode == MODE_EDIT || (_is_line() && mode == MODE_CREATE)) { - if (mb->get_button_index() == BUTTON_LEFT) { - if (mb->is_pressed()) { + if (mb->get_control() || mb->get_shift() || mb->get_alt()) + return false; const PosVertex insert = closest_edge_point(gpoint); @@ -330,7 +346,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) edited_point = PosVertex(closest, xform.affine_inverse().xform(closest.pos)); selected_point = closest; edge_point = PosVertex(); - canvas_item_editor->get_viewport_control()->update(); + canvas_item_editor->update_viewport(); return true; } else { @@ -399,7 +415,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) wip_active = true; _wip_changed(); edited_point = PosVertex(-1, 1, cpoint); - canvas_item_editor->get_viewport_control()->update(); + canvas_item_editor->update_viewport(); hover_point = Vertex(); selected_point = Vertex(0); edge_point = PosVertex(); @@ -420,12 +436,12 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) _wip_changed(); edited_point = PosVertex(-1, wip.size(), cpoint); selected_point = Vertex(wip.size() - 1); - canvas_item_editor->get_viewport_control()->update(); + canvas_item_editor->update_viewport(); return true; } } } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && wip_active) { - _wip_close(); + _wip_cancel(); } } } @@ -449,7 +465,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) _set_polygon(edited_point.polygon, vertices); } - canvas_item_editor->get_viewport_control()->update(); + canvas_item_editor->update_viewport(); } else if (mode == MODE_EDIT || (_is_line() && mode == MODE_CREATE)) { const PosVertex onEdgeVertex = closest_edge_point(gpoint); @@ -458,20 +474,20 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) hover_point = Vertex(); edge_point = onEdgeVertex; - canvas_item_editor->get_viewport_control()->update(); + canvas_item_editor->update_viewport(); } else { if (edge_point.valid()) { edge_point = PosVertex(); - canvas_item_editor->get_viewport_control()->update(); + canvas_item_editor->update_viewport(); } const PosVertex new_hover_point = closest_point(gpoint); if (hover_point != new_hover_point) { hover_point = new_hover_point; - canvas_item_editor->get_viewport_control()->update(); + canvas_item_editor->update_viewport(); } } } @@ -490,7 +506,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) wip.remove(selected_point.vertex); _wip_changed(); selected_point = wip.size() - 1; - canvas_item_editor->get_viewport_control()->update(); + canvas_item_editor->update_viewport(); return true; } } else { @@ -506,18 +522,18 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) } else if (wip_active && k->get_scancode() == KEY_ENTER) { _wip_close(); + } else if (wip_active && k->get_scancode() == KEY_ESCAPE) { + _wip_cancel(); } } return false; } -void AbstractPolygon2DEditor::forward_draw_over_viewport(Control *p_overlay) { +void AbstractPolygon2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { 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(); const Ref<Texture> handle = get_icon("EditorHandle", "EditorIcons"); @@ -558,7 +574,7 @@ void AbstractPolygon2DEditor::forward_draw_over_viewport(Control *p_overlay) { Vector2 point = xform.xform(p); Vector2 next_point = xform.xform(p2); - vpc->draw_line(point, next_point, col, 2 * EDSCALE); + p_overlay->draw_line(point, next_point, col, 2 * EDSCALE); } } @@ -582,7 +598,7 @@ void AbstractPolygon2DEditor::forward_draw_over_viewport(Control *p_overlay) { p2 = points[(i + 1) % n_points] + offset; const Vector2 next_point = xform.xform(p2); - vpc->draw_line(point, next_point, col, 2 * EDSCALE); + p_overlay->draw_line(point, next_point, col, 2 * EDSCALE); } } @@ -594,14 +610,14 @@ void AbstractPolygon2DEditor::forward_draw_over_viewport(Control *p_overlay) { const Vector2 point = xform.xform(p); const Color modulate = vertex == active_point ? Color(0.5, 1, 2) : Color(1, 1, 1); - vpc->draw_texture(handle, point - handle->get_size() * 0.5, modulate); + p_overlay->draw_texture(handle, point - handle->get_size() * 0.5, modulate); } } if (edge_point.valid()) { Ref<Texture> add_handle = get_icon("EditorHandleAdd", "EditorIcons"); - vpc->draw_texture(add_handle, edge_point.pos - add_handle->get_size() * 0.5); + p_overlay->draw_texture(add_handle, edge_point.pos - add_handle->get_size() * 0.5); } } @@ -625,7 +641,7 @@ void AbstractPolygon2DEditor::edit(Node *p_polygon) { hover_point = Vertex(); selected_point = Vertex(); - canvas_item_editor->get_viewport_control()->update(); + canvas_item_editor->update_viewport(); } else { diff --git a/editor/plugins/abstract_polygon_2d_editor.h b/editor/plugins/abstract_polygon_2d_editor.h index 9ba03bcdf6..c03670f254 100644 --- a/editor/plugins/abstract_polygon_2d_editor.h +++ b/editor/plugins/abstract_polygon_2d_editor.h @@ -103,6 +103,7 @@ protected: virtual void _menu_option(int p_option); void _wip_changed(); void _wip_close(); + void _wip_cancel(); bool _delete_point(const Vector2 &p_gpoint); void _notification(int p_what); @@ -137,7 +138,7 @@ protected: public: bool forward_gui_input(const Ref<InputEvent> &p_event); - void forward_draw_over_viewport(Control *p_overlay); + void forward_canvas_draw_over_viewport(Control *p_overlay); void edit(Node *p_polygon); AbstractPolygon2DEditor(EditorNode *p_editor, bool p_wip_destructive = true); @@ -153,7 +154,7 @@ class AbstractPolygon2DEditorPlugin : public EditorPlugin { public: virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return polygon_editor->forward_gui_input(p_event); } - virtual void forward_draw_over_viewport(Control *p_overlay) { polygon_editor->forward_draw_over_viewport(p_overlay); } + virtual void forward_canvas_draw_over_viewport(Control *p_overlay) { polygon_editor->forward_canvas_draw_over_viewport(p_overlay); } bool has_main_screen() const { return false; } virtual String get_name() const { return klass; } diff --git a/editor/plugins/animation_blend_space_1d_editor.cpp b/editor/plugins/animation_blend_space_1d_editor.cpp index 5373015654..4b1e710705 100644 --- a/editor/plugins/animation_blend_space_1d_editor.cpp +++ b/editor/plugins/animation_blend_space_1d_editor.cpp @@ -1,6 +1,36 @@ +/*************************************************************************/ +/* animation_blend_space_1d_editor.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 "animation_blend_space_1d_editor.h" -#include "os/keyboard.h" +#include "core/os/keyboard.h" #include "scene/animation/animation_blend_tree.h" StringName AnimationNodeBlendSpace1DEditor::get_blend_position_path() const { diff --git a/editor/plugins/animation_blend_space_1d_editor.h b/editor/plugins/animation_blend_space_1d_editor.h index 278357b9c7..ca6135406c 100644 --- a/editor/plugins/animation_blend_space_1d_editor.h +++ b/editor/plugins/animation_blend_space_1d_editor.h @@ -1,3 +1,33 @@ +/*************************************************************************/ +/* animation_blend_space_1d_editor.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 ANIMATION_BLEND_SPACE_1D_EDITOR_H #define ANIMATION_BLEND_SPACE_1D_EDITOR_H diff --git a/editor/plugins/animation_blend_space_2d_editor.cpp b/editor/plugins/animation_blend_space_2d_editor.cpp index 2d240b5a5c..394b888d0e 100644 --- a/editor/plugins/animation_blend_space_2d_editor.cpp +++ b/editor/plugins/animation_blend_space_2d_editor.cpp @@ -1,10 +1,40 @@ +/*************************************************************************/ +/* animation_blend_space_2d_editor.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 "animation_blend_space_2d_editor.h" #include "core/io/resource_loader.h" +#include "core/math/delaunay.h" +#include "core/os/input.h" +#include "core/os/keyboard.h" #include "core/project_settings.h" -#include "math/delaunay.h" -#include "os/input.h" -#include "os/keyboard.h" #include "scene/animation/animation_blend_tree.h" #include "scene/animation/animation_player.h" #include "scene/gui/menu_button.h" @@ -404,7 +434,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_draw() { if (blend_space->get_snap().x > 0) { - int prev_idx; + int prev_idx = 0; for (int i = 0; i < s.x; i++) { float v = blend_space->get_min_space().x + i * (blend_space->get_max_space().x - blend_space->get_min_space().x) / s.x; @@ -420,7 +450,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_draw() { if (blend_space->get_snap().y > 0) { - int prev_idx; + int prev_idx = 0; for (int i = 0; i < s.y; i++) { float v = blend_space->get_max_space().y - i * (blend_space->get_max_space().y - blend_space->get_min_space().y) / s.y; diff --git a/editor/plugins/animation_blend_space_2d_editor.h b/editor/plugins/animation_blend_space_2d_editor.h index 0bf1e25d7a..613289e4d8 100644 --- a/editor/plugins/animation_blend_space_2d_editor.h +++ b/editor/plugins/animation_blend_space_2d_editor.h @@ -1,3 +1,33 @@ +/*************************************************************************/ +/* animation_blend_space_2d_editor.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 ANIMATION_BLEND_SPACE_2D_EDITOR_H #define ANIMATION_BLEND_SPACE_2D_EDITOR_H diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp index dbb5fa578b..eb3c432ee7 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.cpp +++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp @@ -1,10 +1,40 @@ +/*************************************************************************/ +/* animation_blend_tree_editor_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 "animation_blend_tree_editor_plugin.h" #include "core/io/resource_loader.h" +#include "core/os/input.h" +#include "core/os/keyboard.h" #include "core/project_settings.h" #include "editor/editor_inspector.h" -#include "os/input.h" -#include "os/keyboard.h" #include "scene/animation/animation_player.h" #include "scene/gui/menu_button.h" #include "scene/gui/panel.h" @@ -101,10 +131,6 @@ void AnimationNodeBlendTreeEditor::_update_graph() { Ref<AnimationNode> agnode = blend_tree->get_node(E->get()); - if (!agnode->is_connected("changed", this, "_node_changed")) { - agnode->connect("changed", this, "_node_changed", varray(agnode->get_instance_id()), CONNECT_DEFERRED); - } - node->set_offset(blend_tree->get_node_position(E->get()) * EDSCALE); node->set_title(agnode->get_caption()); @@ -211,7 +237,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() { mb->get_popup()->connect("index_pressed", this, "_anim_selected", varray(options, E->get()), CONNECT_DEFERRED); } - /* should be no longer necesary, as the boolean works + /* should be no longer necessary, as the boolean works Ref<AnimationNodeOneShot> oneshot = agnode; if (oneshot.is_valid()) { @@ -512,11 +538,7 @@ bool AnimationNodeBlendTreeEditor::_update_filters(const Ref<AnimationNode> &ano if (base->has_node(accum)) { Node *node = base->get_node(accum); - if (has_icon(node->get_class(), "EditorIcons")) { - ti->set_icon(0, get_icon(node->get_class(), "EditorIcons")); - } else { - ti->set_icon(0, get_icon("Node", "EditorIcons")); - } + ti->set_icon(0, EditorNode::get_singleton()->get_object_icon(node, "Node")); } } else { @@ -529,7 +551,7 @@ bool AnimationNodeBlendTreeEditor::_update_filters(const Ref<AnimationNode> &ano node = base->get_node(accum); } if (!node) - continue; //no node, cant edit + continue; //no node, can't edit if (path.get_subname_count()) { @@ -670,7 +692,9 @@ void AnimationNodeBlendTreeEditor::_notification(int p_what) { Ref<Animation> anim = player->get_animation(an->get_animation()); if (anim.is_valid()) { E->get()->set_max(anim->get_length()); - E->get()->set_value(an->get_playback_time()); + //StringName path = AnimationTreeEditor::get_singleton()->get_base_path() + E->get().input_node; + StringName time_path = AnimationTreeEditor::get_singleton()->get_base_path() + String(E->key()) + "/time"; + E->get()->set_value(AnimationTreeEditor::get_singleton()->get_tree()->get(time_path)); } } } @@ -695,14 +719,6 @@ void AnimationNodeBlendTreeEditor::_scroll_changed(const Vector2 &p_scroll) { updating = false; } -void AnimationNodeBlendTreeEditor::_node_changed(ObjectID p_node) { - - AnimationNode *an = Object::cast_to<AnimationNode>(ObjectDB::get_instance(p_node)); - //if (an && an->get_parent() == blend_tree) { - _update_graph(); - //} -} - void AnimationNodeBlendTreeEditor::_bind_methods() { ClassDB::bind_method("_update_graph", &AnimationNodeBlendTreeEditor::_update_graph); @@ -720,7 +736,6 @@ void AnimationNodeBlendTreeEditor::_bind_methods() { ClassDB::bind_method("_update_filters", &AnimationNodeBlendTreeEditor::_update_filters); ClassDB::bind_method("_filter_edited", &AnimationNodeBlendTreeEditor::_filter_edited); ClassDB::bind_method("_filter_toggled", &AnimationNodeBlendTreeEditor::_filter_toggled); - ClassDB::bind_method("_node_changed", &AnimationNodeBlendTreeEditor::_node_changed); ClassDB::bind_method("_removed_from_graph", &AnimationNodeBlendTreeEditor::_removed_from_graph); ClassDB::bind_method("_property_changed", &AnimationNodeBlendTreeEditor::_property_changed); ClassDB::bind_method("_file_opened", &AnimationNodeBlendTreeEditor::_file_opened); @@ -820,8 +835,6 @@ void AnimationNodeBlendTreeEditor::edit(const Ref<AnimationNode> &p_node) { if (p_node.is_valid()) { blend_tree = p_node; - } else { - blend_tree.unref(); } if (blend_tree.is_null()) { diff --git a/editor/plugins/animation_blend_tree_editor_plugin.h b/editor/plugins/animation_blend_tree_editor_plugin.h index 35ecc32979..e2daefdec6 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.h +++ b/editor/plugins/animation_blend_tree_editor_plugin.h @@ -1,3 +1,33 @@ +/*************************************************************************/ +/* animation_blend_tree_editor_plugin.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 ANIMATION_BLEND_TREE_EDITOR_PLUGIN_H #define ANIMATION_BLEND_TREE_EDITOR_PLUGIN_H @@ -74,8 +104,6 @@ class AnimationNodeBlendTreeEditor : public AnimationTreeNodeEditorPlugin { void _filter_toggled(); Ref<AnimationNode> _filter_edit; - void _node_changed(ObjectID p_node); - void _property_changed(const StringName &p_property, const Variant &p_value); void _removed_from_graph(); diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index 9ab5436de8..445664f8dd 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -30,12 +30,12 @@ #include "animation_player_editor_plugin.h" +#include "core/io/resource_loader.h" +#include "core/io/resource_saver.h" +#include "core/os/keyboard.h" +#include "core/project_settings.h" #include "editor/animation_track_editor.h" #include "editor/editor_settings.h" -#include "io/resource_loader.h" -#include "io/resource_saver.h" -#include "os/keyboard.h" -#include "project_settings.h" // For onion skinning #include "editor/plugins/canvas_item_editor_plugin.h" @@ -908,7 +908,7 @@ void AnimationPlayerEditor::edit(AnimationPlayer *p_player) { } } -void AnimationPlayerEditor::forward_force_draw_over_viewport(Control *p_overlay) { +void AnimationPlayerEditor::forward_canvas_force_draw_over_viewport(Control *p_overlay) { if (!onion.can_overlay) return; @@ -1515,7 +1515,7 @@ void AnimationPlayerEditor::_prepare_onion_layers_2() { void AnimationPlayerEditor::_start_onion_skinning() { - // FIXME: Using "idle_frame" makes onion layers update one frame behing the current + // FIXME: Using "idle_frame" makes onion layers update one frame behind the current if (!get_tree()->is_connected("idle_frame", this, "call_deferred")) { get_tree()->connect("idle_frame", this, "call_deferred", varray("_prepare_onion_layers_1")); } diff --git a/editor/plugins/animation_player_editor_plugin.h b/editor/plugins/animation_player_editor_plugin.h index 5ac7b99903..55f082aadb 100644 --- a/editor/plugins/animation_player_editor_plugin.h +++ b/editor/plugins/animation_player_editor_plugin.h @@ -246,7 +246,7 @@ public: void set_undo_redo(UndoRedo *p_undo_redo) { undo_redo = p_undo_redo; } void edit(AnimationPlayer *p_player); - void forward_force_draw_over_viewport(Control *p_overlay); + void forward_canvas_force_draw_over_viewport(Control *p_overlay); AnimationPlayerEditor(EditorNode *p_editor, AnimationPlayerEditorPlugin *p_plugin); }; @@ -271,7 +271,7 @@ public: virtual bool handles(Object *p_object) const; virtual void make_visible(bool p_visible); - virtual void forward_force_draw_over_viewport(Control *p_overlay) { anim_editor->forward_force_draw_over_viewport(p_overlay); } + virtual void forward_canvas_force_draw_over_viewport(Control *p_overlay) { anim_editor->forward_canvas_force_draw_over_viewport(p_overlay); } AnimationPlayerEditorPlugin(EditorNode *p_node); ~AnimationPlayerEditorPlugin(); diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp index 3a65cb9b38..e83773257b 100644 --- a/editor/plugins/animation_state_machine_editor.cpp +++ b/editor/plugins/animation_state_machine_editor.cpp @@ -1,10 +1,40 @@ +/*************************************************************************/ +/* animation_state_machine_editor.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 "animation_state_machine_editor.h" #include "core/io/resource_loader.h" +#include "core/math/delaunay.h" +#include "core/os/input.h" +#include "core/os/keyboard.h" #include "core/project_settings.h" -#include "math/delaunay.h" -#include "os/input.h" -#include "os/keyboard.h" #include "scene/animation/animation_blend_tree.h" #include "scene/animation/animation_player.h" #include "scene/gui/menu_button.h" @@ -633,7 +663,7 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() { transition_lines.clear(); - //draw conecting line for potential new transition + //draw connecting line for potential new transition if (connecting) { Vector2 from = (state_machine->get_node_position(connecting_from) * EDSCALE) - state_machine->get_graph_offset() * EDSCALE; Vector2 to; diff --git a/editor/plugins/animation_state_machine_editor.h b/editor/plugins/animation_state_machine_editor.h index 49d08607cf..7b8a4a0e94 100644 --- a/editor/plugins/animation_state_machine_editor.h +++ b/editor/plugins/animation_state_machine_editor.h @@ -1,3 +1,33 @@ +/*************************************************************************/ +/* animation_state_machine_editor.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 ANIMATION_STATE_MACHINE_EDITOR_H #define ANIMATION_STATE_MACHINE_EDITOR_H diff --git a/editor/plugins/animation_tree_editor_plugin.cpp b/editor/plugins/animation_tree_editor_plugin.cpp index 19921ef54f..24787a78e9 100644 --- a/editor/plugins/animation_tree_editor_plugin.cpp +++ b/editor/plugins/animation_tree_editor_plugin.cpp @@ -1,3 +1,33 @@ +/*************************************************************************/ +/* animation_tree_editor_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 "animation_tree_editor_plugin.h" #include "animation_blend_space_1d_editor.h" @@ -5,10 +35,10 @@ #include "animation_blend_tree_editor_plugin.h" #include "animation_state_machine_editor.h" #include "core/io/resource_loader.h" +#include "core/math/delaunay.h" +#include "core/os/input.h" +#include "core/os/keyboard.h" #include "core/project_settings.h" -#include "math/delaunay.h" -#include "os/input.h" -#include "os/keyboard.h" #include "scene/animation/animation_blend_tree.h" #include "scene/animation/animation_player.h" #include "scene/gui/menu_button.h" diff --git a/editor/plugins/animation_tree_editor_plugin.h b/editor/plugins/animation_tree_editor_plugin.h index b12054bb62..be8848d600 100644 --- a/editor/plugins/animation_tree_editor_plugin.h +++ b/editor/plugins/animation_tree_editor_plugin.h @@ -1,3 +1,33 @@ +/*************************************************************************/ +/* animation_tree_editor_plugin.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 ANIMATION_TREE_EDITOR_PLUGIN_H #define ANIMATION_TREE_EDITOR_PLUGIN_H diff --git a/editor/plugins/animation_tree_player_editor_plugin.cpp b/editor/plugins/animation_tree_player_editor_plugin.cpp index 36d10ab99e..c79e3a436d 100644 --- a/editor/plugins/animation_tree_player_editor_plugin.cpp +++ b/editor/plugins/animation_tree_player_editor_plugin.cpp @@ -31,9 +31,9 @@ #include "animation_tree_player_editor_plugin.h" #include "core/io/resource_loader.h" +#include "core/os/input.h" +#include "core/os/keyboard.h" #include "core/project_settings.h" -#include "os/input.h" -#include "os/keyboard.h" #include "scene/gui/menu_button.h" #include "scene/gui/panel.h" #include "scene/main/viewport.h" diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index 66770d98e5..138b8a491c 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -962,6 +962,9 @@ HBoxContainer *EditorAssetLibrary::_make_pages(int p_page, int p_page_count, int HBoxContainer *hbc = memnew(HBoxContainer); + if (p_page_count < 2) + return hbc; + //do the mario int from = p_page - 5; if (from < 0) diff --git a/editor/plugins/audio_stream_editor_plugin.cpp b/editor/plugins/audio_stream_editor_plugin.cpp index 454a5d72f2..06ca5833e2 100644 --- a/editor/plugins/audio_stream_editor_plugin.cpp +++ b/editor/plugins/audio_stream_editor_plugin.cpp @@ -30,9 +30,9 @@ #include "audio_stream_editor_plugin.h" +#include "core/io/resource_loader.h" +#include "core/project_settings.h" #include "editor/editor_settings.h" -#include "io/resource_loader.h" -#include "project_settings.h" void AudioStreamEditor::_notification(int p_what) { diff --git a/editor/plugins/baked_lightmap_editor_plugin.cpp b/editor/plugins/baked_lightmap_editor_plugin.cpp index 59b79bd070..40e3bb5be2 100644 --- a/editor/plugins/baked_lightmap_editor_plugin.cpp +++ b/editor/plugins/baked_lightmap_editor_plugin.cpp @@ -50,6 +50,7 @@ void BakedLightmapEditorPlugin::_bake() { case BakedLightmap::BAKE_ERROR_CANT_CREATE_IMAGE: EditorNode::get_singleton()->show_warning(TTR("Failed creating lightmap images, make sure path is writable.")); break; + default: {} } } } @@ -107,7 +108,7 @@ void BakedLightmapEditorPlugin::_bind_methods() { BakedLightmapEditorPlugin::BakedLightmapEditorPlugin(EditorNode *p_node) { editor = p_node; - bake = memnew(Button); + bake = memnew(ToolButton); bake->set_icon(editor->get_gui_base()->get_icon("Bake", "EditorIcons")); bake->set_text(TTR("Bake Lightmaps")); bake->hide(); diff --git a/editor/plugins/baked_lightmap_editor_plugin.h b/editor/plugins/baked_lightmap_editor_plugin.h index a32b573851..8d3b5b1dd6 100644 --- a/editor/plugins/baked_lightmap_editor_plugin.h +++ b/editor/plugins/baked_lightmap_editor_plugin.h @@ -42,7 +42,7 @@ class BakedLightmapEditorPlugin : public EditorPlugin { BakedLightmap *lightmap; - Button *bake; + ToolButton *bake; EditorNode *editor; static EditorProgress *tmp_progress; diff --git a/editor/plugins/camera_editor_plugin.cpp b/editor/plugins/camera_editor_plugin.cpp index 37fbb54c30..3d8b24ccc7 100644 --- a/editor/plugins/camera_editor_plugin.cpp +++ b/editor/plugins/camera_editor_plugin.cpp @@ -32,18 +32,6 @@ #include "spatial_editor_plugin.h" -void CameraEditor::_notification(int p_what) { - - switch (p_what) { - - /* case NOTIFICATION_PROCESS: { - - if (preview->is_pressed() && node) - node->call("make_current"); - - } break;*/ - } -} void CameraEditor::_node_removed(Node *p_node) { if (p_node == node) { diff --git a/editor/plugins/camera_editor_plugin.h b/editor/plugins/camera_editor_plugin.h index 275624beeb..0340808c9a 100644 --- a/editor/plugins/camera_editor_plugin.h +++ b/editor/plugins/camera_editor_plugin.h @@ -50,7 +50,6 @@ class CameraEditor : public Control { void _pressed(); protected: - void _notification(int p_what); void _node_removed(Node *p_node); static void _bind_methods(); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 72248b62a3..ee2283a035 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -30,15 +30,15 @@ #include "canvas_item_editor_plugin.h" +#include "core/os/input.h" +#include "core/os/keyboard.h" +#include "core/print_string.h" +#include "core/project_settings.h" #include "editor/editor_node.h" #include "editor/editor_settings.h" #include "editor/plugins/animation_player_editor_plugin.h" #include "editor/plugins/script_editor_plugin.h" #include "editor/script_editor_debugger.h" -#include "os/input.h" -#include "os/keyboard.h" -#include "print_string.h" -#include "project_settings.h" #include "scene/2d/light_2d.h" #include "scene/2d/particles_2d.h" #include "scene/2d/polygon_2d.h" @@ -55,6 +55,7 @@ #define MAX_ZOOM 100 #define RULER_WIDTH 15 * EDSCALE +#define SCALE_HANDLE_DISTANCE 25 class SnapDialog : public ConfirmationDialog { @@ -178,6 +179,23 @@ void CanvasItemEditor::_snap_if_closer_float(float p_value, float p_target_snap, } } +bool CanvasItemEditor::_is_node_locked(const Node *p_node) { + return p_node->has_meta("_edit_lock_") && p_node->get_meta("_edit_lock_"); +} + +bool CanvasItemEditor::_is_node_movable(const Node *p_node, bool p_popup_warning) { + if (_is_node_locked(p_node)) { + return false; + } + if (Object::cast_to<Control>(p_node) && Object::cast_to<Container>(p_node->get_parent())) { + if (p_popup_warning) { + _popup_warning_temporarily(warning_child_of_container, 3.0); + } + return false; + } + return true; +} + void CanvasItemEditor::_snap_if_closer_point(Point2 p_value, Point2 p_target_snap, Point2 &r_current_snap, bool (&r_snapped)[2], real_t rotation, float p_radius) { Transform2D rot_trans = Transform2D(rotation, Point2()); p_value = rot_trans.inverse().xform(p_value); @@ -335,10 +353,11 @@ void CanvasItemEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) { if (!is_visible_in_tree() || get_viewport()->gui_has_modal_stack()) return; - if (k->get_control()) - return; + if (k->get_scancode() == KEY_CONTROL || k->get_scancode() == KEY_ALT || k->get_scancode() == KEY_SHIFT) { + viewport->update(); + } - if (k->is_pressed() && !k->is_echo()) { + if (k->is_pressed() && !k->get_control() && !k->is_echo()) { if ((snap_grid || show_grid) && multiply_grid_step_shortcut.is_valid() && multiply_grid_step_shortcut->is_shortcut(p_ev)) { // Multiply the grid size grid_step_multiplier = MIN(grid_step_multiplier + 1, 12); @@ -409,7 +428,7 @@ void CanvasItemEditor::_expand_encompassing_rect_using_children(Rect2 &r_rect, c } } - if (canvas_item && canvas_item->is_visible_in_tree() && (include_locked_nodes || !canvas_item->has_meta("_edit_lock_"))) { + if (canvas_item && canvas_item->is_visible_in_tree() && (include_locked_nodes || !_is_node_locked(canvas_item))) { Transform2D xform = p_parent_xform * p_canvas_xform * canvas_item->get_transform(); Rect2 rect = canvas_item->_edit_get_rect(); if (r_first) { @@ -431,7 +450,7 @@ Rect2 CanvasItemEditor::_get_encompassing_rect(const Node *p_node) { return rect; } -void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_node, Vector<_SelectResult> &r_items, int p_limit, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) { +void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_node, Vector<_SelectResult> &r_items, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) { if (!p_node) return; if (Object::cast_to<Viewport>(p_node)) @@ -441,14 +460,16 @@ void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_no CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node); for (int i = p_node->get_child_count() - 1; i >= 0; i--) { - if (canvas_item && !canvas_item->is_set_as_toplevel()) { - _find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, p_limit, p_parent_xform * canvas_item->get_transform(), p_canvas_xform); + if (canvas_item) { + if (!canvas_item->is_set_as_toplevel()) { + _find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, p_parent_xform * canvas_item->get_transform(), p_canvas_xform); + } else { + _find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, canvas_item->get_transform(), p_canvas_xform); + } } else { CanvasLayer *cl = Object::cast_to<CanvasLayer>(p_node); - _find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, p_limit, Transform2D(), cl ? cl->get_transform() : p_canvas_xform); + _find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, Transform2D(), cl ? cl->get_transform() : p_canvas_xform); } - if (p_limit != 0 && r_items.size() >= p_limit) - return; } if (canvas_item && canvas_item->is_visible_in_tree()) { @@ -468,11 +489,11 @@ void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_no return; } -void CanvasItemEditor::_get_canvas_items_at_pos(const Point2 &p_pos, Vector<_SelectResult> &r_items, int p_limit) { +void CanvasItemEditor::_get_canvas_items_at_pos(const Point2 &p_pos, Vector<_SelectResult> &r_items) { Node *scene = editor->get_edited_scene(); - _find_canvas_items_at_pos(p_pos, scene, r_items, p_limit); + _find_canvas_items_at_pos(p_pos, scene, r_items); //Remove invalid results for (int i = 0; i < r_items.size(); i++) { @@ -503,7 +524,7 @@ void CanvasItemEditor::_get_canvas_items_at_pos(const Point2 &p_pos, Vector<_Sel } //Remove the item if invalid - if (!canvas_item || duplicate || (canvas_item != scene && canvas_item->get_owner() != scene && !scene->is_editable_instance(canvas_item->get_owner())) || (canvas_item->has_meta("_edit_lock_") && canvas_item->get_meta("_edit_lock_"))) { + if (!canvas_item || duplicate || (canvas_item != scene && canvas_item->get_owner() != scene && !scene->is_editable_instance(canvas_item->get_owner())) || _is_node_locked(canvas_item)) { r_items.remove(i); i--; } else { @@ -604,12 +625,16 @@ void CanvasItemEditor::_find_canvas_items_in_rect(const Rect2 &p_rect, Node *p_n bool editable = p_node == scene || p_node->get_owner() == scene || scene->is_editable_instance(p_node->get_owner()); bool lock_children = p_node->has_meta("_edit_group_") && p_node->get_meta("_edit_group_"); - bool locked = p_node->has_meta("_edit_lock_") && p_node->get_meta("_edit_lock_"); + bool locked = _is_node_locked(p_node); if (!lock_children || !editable) { for (int i = p_node->get_child_count() - 1; i >= 0; i--) { - if (canvas_item && !canvas_item->is_set_as_toplevel()) { - _find_canvas_items_in_rect(p_rect, p_node->get_child(i), r_items, p_parent_xform * canvas_item->get_transform(), p_canvas_xform); + if (canvas_item) { + if (!canvas_item->is_set_as_toplevel()) { + _find_canvas_items_in_rect(p_rect, p_node->get_child(i), r_items, p_parent_xform * canvas_item->get_transform(), p_canvas_xform); + } else { + _find_canvas_items_in_rect(p_rect, p_node->get_child(i), r_items, canvas_item->get_transform(), p_canvas_xform); + } } else { CanvasLayer *canvas_layer = Object::cast_to<CanvasLayer>(p_node); _find_canvas_items_in_rect(p_rect, p_node->get_child(i), r_items, Transform2D(), canvas_layer ? canvas_layer->get_transform() : p_canvas_xform); @@ -667,7 +692,7 @@ List<CanvasItem *> CanvasItemEditor::_get_edited_canvas_items(bool retreive_lock List<CanvasItem *> selection; for (Map<Node *, Object *>::Element *E = editor_selection->get_selection().front(); E; E = E->next()) { CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->key()); - if (canvas_item && canvas_item->is_visible_in_tree() && canvas_item->get_viewport() == EditorNode::get_singleton()->get_scene_root() && (!retreive_locked || !canvas_item->has_meta("_edit_lock_"))) { + if (canvas_item && canvas_item->is_visible_in_tree() && canvas_item->get_viewport() == EditorNode::get_singleton()->get_scene_root() && (retreive_locked || !_is_node_locked(canvas_item))) { CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); if (se) { selection.push_back(canvas_item); @@ -705,6 +730,46 @@ Vector2 CanvasItemEditor::_position_to_anchor(const Control *p_control, Vector2 return (p_control->get_transform().xform(position) - parent_rect.position) / parent_rect.size; } +void CanvasItemEditor::_save_canvas_item_ik_chain(const CanvasItem *p_canvas_item, List<float> *p_bones_length, List<Dictionary> *p_bones_state) { + if (p_bones_length) + *p_bones_length = List<float>(); + if (p_bones_state) + *p_bones_state = List<Dictionary>(); + + const Node2D *bone = Object::cast_to<Node2D>(p_canvas_item); + if (bone && bone->has_meta("_edit_bone_")) { + // Check if we have an IK chain + List<const Node2D *> bone_ik_list; + bool ik_found = false; + bone = Object::cast_to<Node2D>(bone->get_parent()); + while (bone) { + bone_ik_list.push_back(bone); + if (bone->has_meta("_edit_ik_")) { + ik_found = true; + break; + } else if (!bone->has_meta("_edit_bone_")) { + break; + } + bone = Object::cast_to<Node2D>(bone->get_parent()); + } + + //Save the bone state and length if we have an IK chain + if (ik_found) { + bone = Object::cast_to<Node2D>(p_canvas_item); + Transform2D bone_xform = bone->get_global_transform(); + for (List<const Node2D *>::Element *bone_E = bone_ik_list.front(); bone_E; bone_E = bone_E->next()) { + bone_xform = bone_xform * bone->get_transform().affine_inverse(); + const Node2D *parent_bone = bone_E->get(); + if (p_bones_length) + p_bones_length->push_back(parent_bone->get_global_transform().get_origin().distance_to(bone->get_global_position())); + if (p_bones_state) + p_bones_state->push_back(parent_bone->_edit_get_state()); + bone = parent_bone; + } + } + } +} + void CanvasItemEditor::_save_canvas_item_state(List<CanvasItem *> p_canvas_items, bool save_bones) { for (List<CanvasItem *>::Element *E = p_canvas_items.front(); E; E = E->next()) { CanvasItem *canvas_item = E->get(); @@ -717,54 +782,28 @@ void CanvasItemEditor::_save_canvas_item_state(List<CanvasItem *> p_canvas_items } else { se->pre_drag_rect = Rect2(); } - se->pre_drag_bones_length = List<float>(); - se->pre_drag_bones_undo_state = List<Dictionary>(); // If we have a bone, save the state of all nodes in the IK chain - Node2D *bone = Object::cast_to<Node2D>(canvas_item); - if (bone && bone->has_meta("_edit_bone_")) { - // Check if we have an IK chain - List<Node2D *> bone_ik_list; - bool ik_found = false; - bone = Object::cast_to<Node2D>(bone->get_parent()); - while (bone) { - bone_ik_list.push_back(bone); - if (bone->has_meta("_edit_ik_")) { - ik_found = true; - break; - } else if (!bone->has_meta("_edit_bone_")) { - break; - } - bone = Object::cast_to<Node2D>(bone->get_parent()); - } - - //Save the bone state and length if we have an IK chain - if (ik_found) { - bone = Object::cast_to<Node2D>(canvas_item); - Transform2D bone_xform = bone->get_global_transform(); - for (List<Node2D *>::Element *bone_E = bone_ik_list.front(); bone_E; bone_E = bone_E->next()) { - bone_xform = bone_xform * bone->get_transform().affine_inverse(); - Node2D *parent_bone = bone_E->get(); - se->pre_drag_bones_length.push_back(parent_bone->get_global_transform().get_origin().distance_to(bone->get_global_position())); - se->pre_drag_bones_undo_state.push_back(parent_bone->_edit_get_state()); - bone = parent_bone; - } - } - } + _save_canvas_item_ik_chain(canvas_item, &(se->pre_drag_bones_length), &(se->pre_drag_bones_undo_state)); } } } +void CanvasItemEditor::_restore_canvas_item_ik_chain(CanvasItem *p_canvas_item, const List<Dictionary> *p_bones_state) { + CanvasItem *canvas_item = p_canvas_item; + for (const List<Dictionary>::Element *E = p_bones_state->front(); E; E = E->next()) { + canvas_item = Object::cast_to<CanvasItem>(canvas_item->get_parent()); + canvas_item->_edit_set_state(E->get()); + } +} + void CanvasItemEditor::_restore_canvas_item_state(List<CanvasItem *> p_canvas_items, bool restore_bones) { for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) { CanvasItem *canvas_item = E->get(); CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); canvas_item->_edit_set_state(se->undo_state); if (restore_bones) { - for (List<Dictionary>::Element *E = se->pre_drag_bones_undo_state.front(); E; E = E->next()) { - canvas_item = Object::cast_to<CanvasItem>(canvas_item->get_parent()); - canvas_item->_edit_set_state(E->get()); - } + _restore_canvas_item_ik_chain(canvas_item, &(se->pre_drag_bones_undo_state)); } } } @@ -997,8 +1036,7 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event) { // Scroll or pan down if (bool(EditorSettings::get_singleton()->get("editors/2d/scroll_to_pan"))) { view_offset.y += int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); - _update_scrollbars(); - viewport->update(); + update_viewport(); } else { _zoom_on_position(zoom * (1 - (0.05 * b->get_factor())), b->get_position()); } @@ -1009,8 +1047,7 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event) { // Scroll or pan up if (bool(EditorSettings::get_singleton()->get("editors/2d/scroll_to_pan"))) { view_offset.y -= int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); - _update_scrollbars(); - viewport->update(); + update_viewport(); } else { _zoom_on_position(zoom * ((0.95 + (0.05 * b->get_factor())) / 0.95), b->get_position()); } @@ -1021,8 +1058,7 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event) { // Pan left if (bool(EditorSettings::get_singleton()->get("editors/2d/scroll_to_pan"))) { view_offset.x -= int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); - _update_scrollbars(); - viewport->update(); + update_viewport(); return true; } } @@ -1031,8 +1067,7 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event) { // Pan right if (bool(EditorSettings::get_singleton()->get("editors/2d/scroll_to_pan"))) { view_offset.x += int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); - _update_scrollbars(); - viewport->update(); + update_viewport(); return true; } } @@ -1084,8 +1119,7 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event) { } view_offset.x -= relative.x / zoom; view_offset.y -= relative.y / zoom; - _update_scrollbars(); - viewport->update(); + update_viewport(); return true; } } @@ -1103,8 +1137,7 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event) { const Vector2 delta = (int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom) * pan_gesture->get_delta(); view_offset.x += delta.x; view_offset.y += delta.y; - _update_scrollbars(); - viewport->update(); + update_viewport(); return true; } @@ -1189,73 +1222,72 @@ bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) { void CanvasItemEditor::_solve_IK(Node2D *leaf_node, Point2 target_position) { CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(leaf_node); - if (se && !se->pre_drag_bones_undo_state.empty()) { - - // Build the node list - Point2 leaf_pos = target_position; - - List<Node2D *> joints_list; - List<Point2> joints_pos; - Node2D *joint = leaf_node; - Transform2D joint_transform = leaf_node->get_global_transform_with_canvas(); - for (int i = 0; i < se->pre_drag_bones_undo_state.size() + 1; i++) { - joints_list.push_back(joint); - joints_pos.push_back(joint_transform.get_origin()); - joint_transform = joint_transform * joint->get_transform().affine_inverse(); - joint = Object::cast_to<Node2D>(joint->get_parent()); - } - Point2 root_pos = joints_list.back()->get()->get_global_transform_with_canvas().get_origin(); - - // Restraints the node to a maximum distance is necessary - float total_len = 0; - for (List<float>::Element *E = se->pre_drag_bones_length.front(); E; E = E->next()) { - total_len += E->get(); - } - if ((root_pos.distance_to(leaf_pos)) > total_len) { - Vector2 rel = leaf_pos - root_pos; - rel = rel.normalized() * total_len; - leaf_pos = root_pos + rel; - } - joints_pos[0] = leaf_pos; - - // Run the solver - int solver_iterations = 64; - float solver_k = 0.3; - - // Build the position list - for (int i = 0; i < solver_iterations; i++) { - // Handle the leaf joint - int node_id = 0; + if (se) { + int nb_bones = se->pre_drag_bones_undo_state.size(); + if (nb_bones > 0) { + + // Build the node list + Point2 leaf_pos = target_position; + + List<Node2D *> joints_list; + List<Point2> joints_pos; + Node2D *joint = leaf_node; + Transform2D joint_transform = leaf_node->get_global_transform_with_canvas(); + for (int i = 0; i < nb_bones + 1; i++) { + joints_list.push_back(joint); + joints_pos.push_back(joint_transform.get_origin()); + joint_transform = joint_transform * joint->get_transform().affine_inverse(); + joint = Object::cast_to<Node2D>(joint->get_parent()); + } + Point2 root_pos = joints_list.back()->get()->get_global_transform_with_canvas().get_origin(); + + // Restraints the node to a maximum distance is necessary + float total_len = 0; for (List<float>::Element *E = se->pre_drag_bones_length.front(); E; E = E->next()) { - Vector2 direction = (joints_pos[node_id + 1] - joints_pos[node_id]).normalized(); - int len = E->get(); - if (E == se->pre_drag_bones_length.front()) { - joints_pos[1] = joints_pos[1].linear_interpolate(joints_pos[0] + len * direction, solver_k); - } else if (E == se->pre_drag_bones_length.back()) { - joints_pos[node_id] = joints_pos[node_id].linear_interpolate(joints_pos[node_id + 1] - len * direction, solver_k); - } else { - Vector2 center = (joints_pos[node_id + 1] + joints_pos[node_id]) / 2.0; - joints_pos[node_id] = joints_pos[node_id].linear_interpolate(center - (direction * len) / 2.0, solver_k); - joints_pos[node_id + 1] = joints_pos[node_id + 1].linear_interpolate(center + (direction * len) / 2.0, solver_k); + total_len += E->get(); + } + if ((root_pos.distance_to(leaf_pos)) > total_len) { + Vector2 rel = leaf_pos - root_pos; + rel = rel.normalized() * total_len; + leaf_pos = root_pos + rel; + } + joints_pos[0] = leaf_pos; + + // Run the solver + int solver_iterations = 64; + float solver_k = 0.3; + + // Build the position list + for (int i = 0; i < solver_iterations; i++) { + // Handle the leaf joint + int node_id = 0; + for (List<float>::Element *E = se->pre_drag_bones_length.front(); E; E = E->next()) { + Vector2 direction = (joints_pos[node_id + 1] - joints_pos[node_id]).normalized(); + int len = E->get(); + if (E == se->pre_drag_bones_length.front()) { + joints_pos[1] = joints_pos[1].linear_interpolate(joints_pos[0] + len * direction, solver_k); + } else if (E == se->pre_drag_bones_length.back()) { + joints_pos[node_id] = joints_pos[node_id].linear_interpolate(joints_pos[node_id + 1] - len * direction, solver_k); + } else { + Vector2 center = (joints_pos[node_id + 1] + joints_pos[node_id]) / 2.0; + joints_pos[node_id] = joints_pos[node_id].linear_interpolate(center - (direction * len) / 2.0, solver_k); + joints_pos[node_id + 1] = joints_pos[node_id + 1].linear_interpolate(center + (direction * len) / 2.0, solver_k); + } + node_id++; } - node_id++; } - } - // Set the position - float total_rot = 0.0f; - for (int node_id = joints_list.size() - 1; node_id > 0; node_id--) { - Point2 current = (joints_list[node_id - 1]->get_global_position() - joints_list[node_id]->get_global_position()).normalized(); - Point2 target = (joints_pos[node_id - 1] - joints_list[node_id]->get_global_position()).normalized(); - float rot = current.angle_to(target); - if (joints_list[node_id]->get_global_transform().basis_determinant() < 0) { - rot = -rot; + // Set the position + for (int node_id = joints_list.size() - 1; node_id > 0; node_id--) { + Point2 current = (joints_list[node_id - 1]->get_global_position() - joints_list[node_id]->get_global_position()).normalized(); + Point2 target = (joints_pos[node_id - 1] - joints_list[node_id]->get_global_position()).normalized(); + float rot = current.angle_to(target); + if (joints_list[node_id]->get_global_transform().basis_determinant() < 0) { + rot = -rot; + } + joints_list[node_id]->rotate(rot); } - joints_list[node_id]->rotate(rot); - total_rot += rot; } - - joints_list[0]->rotate(-total_rot); } } @@ -1266,18 +1298,28 @@ bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) { // Start rotation if (drag_type == DRAG_NONE) { if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed()) { - drag_selection = _get_edited_canvas_items(); - if (drag_selection.size() > 0 && ((b->get_control() && tool == TOOL_SELECT) || tool == TOOL_ROTATE)) { - drag_type = DRAG_ROTATE; - drag_from = transform.affine_inverse().xform(b->get_position()); - CanvasItem *canvas_item = drag_selection[0]; - if (canvas_item->_edit_use_pivot()) { - drag_rotation_center = canvas_item->get_global_transform_with_canvas().xform(canvas_item->_edit_get_pivot()); - } else { - drag_rotation_center = canvas_item->get_global_transform_with_canvas().get_origin(); + if ((b->get_control() && !b->get_alt() && tool == TOOL_SELECT) || tool == TOOL_ROTATE) { + List<CanvasItem *> selection = _get_edited_canvas_items(); + + // Remove not movable nodes + for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) { + if (!_is_node_movable(E->get(), true)) + selection.erase(E); + } + + drag_selection = selection; + if (drag_selection.size() > 0) { + drag_type = DRAG_ROTATE; + drag_from = transform.affine_inverse().xform(b->get_position()); + CanvasItem *canvas_item = drag_selection[0]; + if (canvas_item->_edit_use_pivot()) { + drag_rotation_center = canvas_item->get_global_transform_with_canvas().xform(canvas_item->_edit_get_pivot()); + } else { + drag_rotation_center = canvas_item->get_global_transform_with_canvas().get_origin(); + } + _save_canvas_item_state(drag_selection); + return true; } - _save_canvas_item_state(drag_selection); - return true; } } } @@ -1340,7 +1382,7 @@ bool CanvasItemEditor::_gui_input_anchors(const Ref<InputEvent> &p_event) { List<CanvasItem *> selection = _get_edited_canvas_items(); if (selection.size() == 1) { Control *control = Object::cast_to<Control>(selection[0]); - if (control && !Object::cast_to<Container>(control->get_parent())) { + if (control && _is_node_movable(control)) { Vector2 anchor_pos[4]; anchor_pos[0] = Vector2(control->get_anchor(MARGIN_LEFT), control->get_anchor(MARGIN_TOP)); anchor_pos[1] = Vector2(control->get_anchor(MARGIN_RIGHT), control->get_anchor(MARGIN_TOP)); @@ -1459,7 +1501,7 @@ bool CanvasItemEditor::_gui_input_resize(const Ref<InputEvent> &p_event) { List<CanvasItem *> selection = _get_edited_canvas_items(); if (selection.size() == 1) { CanvasItem *canvas_item = selection[0]; - if (canvas_item->_edit_use_rect()) { + if (canvas_item->_edit_use_rect() && _is_node_movable(canvas_item)) { Rect2 rect = canvas_item->_edit_get_rect(); Transform2D xform = transform * canvas_item->get_global_transform_with_canvas(); @@ -1615,6 +1657,112 @@ bool CanvasItemEditor::_gui_input_resize(const Ref<InputEvent> &p_event) { return false; } +bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) { + + Ref<InputEventMouseButton> b = p_event; + Ref<InputEventMouseMotion> m = p_event; + + // Drag resize handles + if (drag_type == DRAG_NONE) { + if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && ((b->get_alt() && b->get_control()) || tool == TOOL_SCALE)) { + List<CanvasItem *> selection = _get_edited_canvas_items(); + if (selection.size() == 1) { + CanvasItem *canvas_item = selection[0]; + + if (_is_node_movable(canvas_item)) { + + Transform2D xform = transform * canvas_item->get_global_transform_with_canvas(); + Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * Transform2D(canvas_item->_edit_get_rotation(), canvas_item->_edit_get_position())).orthonormalized(); + Transform2D simple_xform = viewport->get_transform() * unscaled_transform; + + drag_type = DRAG_SCALE_BOTH; + + Size2 scale_factor = Size2(SCALE_HANDLE_DISTANCE, SCALE_HANDLE_DISTANCE); + Rect2 x_handle_rect = Rect2(scale_factor.x * EDSCALE, -5 * EDSCALE, 10 * EDSCALE, 10 * EDSCALE); + if (x_handle_rect.has_point(simple_xform.affine_inverse().xform(b->get_position()))) { + drag_type = DRAG_SCALE_X; + } + Rect2 y_handle_rect = Rect2(-5 * EDSCALE, -(scale_factor.y + 10) * EDSCALE, 10 * EDSCALE, 10 * EDSCALE); + if (y_handle_rect.has_point(simple_xform.affine_inverse().xform(b->get_position()))) { + drag_type = DRAG_SCALE_Y; + } + + drag_from = transform.affine_inverse().xform(b->get_position()); + drag_selection = List<CanvasItem *>(); + drag_selection.push_back(canvas_item); + _save_canvas_item_state(drag_selection); + return true; + } + } + } + } + + if (drag_type == DRAG_SCALE_BOTH || drag_type == DRAG_SCALE_X || drag_type == DRAG_SCALE_Y) { + // Resize the node + if (m.is_valid()) { + _restore_canvas_item_state(drag_selection); + CanvasItem *canvas_item = drag_selection[0]; + + drag_to = transform.affine_inverse().xform(m->get_position()); + + Transform2D parent_xform = canvas_item->get_global_transform_with_canvas() * canvas_item->get_transform().affine_inverse(); + Transform2D unscaled_transform = (transform * parent_xform * Transform2D(canvas_item->_edit_get_rotation(), canvas_item->_edit_get_position())).orthonormalized(); + Transform2D simple_xform = (viewport->get_transform() * unscaled_transform).affine_inverse() * transform; + + bool uniform = m->get_shift(); + + Point2 drag_from_local = simple_xform.xform(drag_from); + Point2 drag_to_local = simple_xform.xform(drag_to); + Point2 offset = drag_to_local - drag_from_local; + + Size2 scale = canvas_item->call("get_scale"); + float ratio = scale.y / scale.x; + if (drag_type == DRAG_SCALE_BOTH) { + Size2 scale_factor = drag_to_local / drag_from_local; + if (uniform) { + scale *= (scale_factor.x + scale_factor.y) / 2.0; + } else { + scale *= scale_factor; + } + } else { + Size2 scale_factor = Vector2(offset.x, -offset.y) / SCALE_HANDLE_DISTANCE; + Size2 parent_scale = parent_xform.get_scale(); + scale_factor *= Vector2(1.0 / parent_scale.x, 1.0 / parent_scale.y); + if (drag_type == DRAG_SCALE_X) { + scale.x += scale_factor.x; + if (uniform) { + scale.y = scale.x * ratio; + } + } else if (drag_type == DRAG_SCALE_Y) { + scale.y += scale_factor.y; + if (uniform) { + scale.x = scale.y / ratio; + } + } + } + canvas_item->call("set_scale", scale); + return true; + } + + // Confirm resize + if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) { + _commit_canvas_item_state(drag_selection, TTR("Scale CanvasItem")); + drag_type = DRAG_NONE; + viewport->update(); + return true; + } + + // Cancel a drag + if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) { + _restore_canvas_item_state(drag_selection); + drag_type = DRAG_NONE; + viewport->update(); + return true; + } + } + return false; +} + bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> b = p_event; Ref<InputEventMouseMotion> m = p_event; @@ -1623,20 +1771,39 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { if (drag_type == DRAG_NONE) { //Start moving the nodes if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed()) { - List<CanvasItem *> selection = _get_edited_canvas_items(); - if ((b->get_alt() || tool == TOOL_MOVE) && selection.size() > 0) { - drag_type = DRAG_ALL; - drag_from = transform.affine_inverse().xform(b->get_position()); - drag_selection = selection; - _save_canvas_item_state(drag_selection); + if ((b->get_alt() && !b->get_control()) || tool == TOOL_MOVE) { + List<CanvasItem *> selection = _get_edited_canvas_items(); + + // Remove not movable nodes + for (int i = 0; i < selection.size(); i++) { + if (!_is_node_movable(selection[i], true)) { + selection.erase(selection[i]); + } + } + + if (selection.size() > 0) { + drag_type = DRAG_MOVE; + drag_from = transform.affine_inverse().xform(b->get_position()); + drag_selection = selection; + _save_canvas_item_state(drag_selection); + } return true; } } } - if (drag_type == DRAG_ALL) { + if (drag_type == DRAG_MOVE) { // Move the nodes if (m.is_valid()) { + + // Save the ik chain for reapplying before IK solve + Vector<List<Dictionary> > all_bones_ik_states; + for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) { + List<Dictionary> bones_ik_states; + _save_canvas_item_ik_chain(E->get(), NULL, &bones_ik_states); + all_bones_ik_states.push_back(bones_ik_states); + } + _restore_canvas_item_state(drag_selection, true); drag_to = transform.affine_inverse().xform(m->get_position()); @@ -1658,6 +1825,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { } bool force_no_IK = m->get_alt(); + int index = 0; for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) { CanvasItem *canvas_item = E->get(); CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); @@ -1665,16 +1833,21 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { Node2D *node2d = Object::cast_to<Node2D>(canvas_item); if (node2d && se->pre_drag_bones_undo_state.size() > 0 && !force_no_IK) { + real_t initial_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation(); + _restore_canvas_item_ik_chain(node2d, &(all_bones_ik_states[index])); + real_t final_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation(); + node2d->rotate(initial_leaf_node_rotation - final_leaf_node_rotation); _solve_IK(node2d, new_pos); } else { canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos)); } + index++; } return true; } // Confirm the move (only if it was moved) - if (b.is_valid() && !b->is_pressed() && b->get_button_index() == BUTTON_LEFT && (drag_type == DRAG_ALL)) { + if (b.is_valid() && !b->is_pressed() && b->get_button_index() == BUTTON_LEFT && (drag_type == DRAG_MOVE)) { if (transform.affine_inverse().xform(b->get_position()) != drag_from) { _commit_canvas_item_state(drag_selection, TTR("Move CanvasItem"), true); } @@ -1707,6 +1880,14 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { if (drag_selection.size() > 0) { + // Save the ik chain for reapplying before IK solve + Vector<List<Dictionary> > all_bones_ik_states; + for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) { + List<Dictionary> bones_ik_states; + _save_canvas_item_ik_chain(E->get(), NULL, &bones_ik_states); + all_bones_ik_states.push_back(bones_ik_states); + } + _restore_canvas_item_state(drag_selection, true); bool move_local_base = k->get_alt(); @@ -1752,6 +1933,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { new_pos = previous_pos + (drag_to - drag_from); } + int index = 0; for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) { CanvasItem *canvas_item = E->get(); CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); @@ -1759,10 +1941,15 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { Node2D *node2d = Object::cast_to<Node2D>(canvas_item); if (node2d && se->pre_drag_bones_undo_state.size() > 0) { + real_t initial_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation(); + _restore_canvas_item_ik_chain(node2d, &(all_bones_ik_states[index])); + real_t final_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation(); + node2d->rotate(initial_leaf_node_rotation - final_leaf_node_rotation); _solve_IK(node2d, new_pos); } else { canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos)); } + index++; } } return true; @@ -1820,11 +2007,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { for (int i = 0; i < selection_results.size(); i++) { CanvasItem *item = selection_results[i].item; - Ref<Texture> icon; - if (item->has_meta("_editor_icon")) - icon = item->get_meta("_editor_icon"); - else - icon = get_icon(has_icon(item->get_class(), "EditorIcons") ? item->get_class() : String("Object"), "EditorIcons"); + Ref<Texture> icon = EditorNode::get_singleton()->get_object_icon(item, "Node"); String node_path = "/" + root_name + "/" + root_path.rel_path_to(item->get_path()); selection_menu->add_item(item->get_name()); @@ -1853,27 +2036,14 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { Vector<_SelectResult> selection; // Retrieve the items - _get_canvas_items_at_pos(click, selection, editor_selection->get_selection().empty() ? 1 : 0); + _get_canvas_items_at_pos(click, selection); // Retrieve the bones _get_bones_at_pos(click, selection); - for (int i = 0; i < selection.size(); i++) { - if (editor_selection->is_selected(selection[i].item)) { - // Drag the node(s) if requested - List<CanvasItem *> selection = _get_edited_canvas_items(); - - drag_type = DRAG_ALL; - drag_selection = selection; - drag_from = click; - _save_canvas_item_state(drag_selection); - - return true; - } - } - - if (!selection.empty()) + if (!selection.empty()) { canvas_item = selection[0].item; + } if (!canvas_item) { // Start a box selection @@ -1894,10 +2064,19 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { // Drag the node(s) if requested List<CanvasItem *> selection = _get_edited_canvas_items(); - drag_type = DRAG_ALL; - drag_selection = selection; - drag_from = click; - _save_canvas_item_state(drag_selection); + // Remove not movable nodes + for (int i = 0; i < selection.size(); i++) { + if (!_is_node_movable(selection[i], true)) { + selection.erase(selection[i]); + } + } + + if (selection.size() > 0) { + drag_type = DRAG_MOVE; + drag_selection = selection; + drag_from = click; + _save_canvas_item_state(drag_selection); + } } // Select the item return true; @@ -1974,10 +2153,7 @@ bool CanvasItemEditor::_gui_input_hover(const Ref<InputEvent> &p_event) { _HoverResult hover_result; hover_result.position = canvas_item->get_global_transform_with_canvas().get_origin(); - if (has_icon(canvas_item->get_class(), "EditorIcons")) - hover_result.icon = get_icon(canvas_item->get_class(), "EditorIcons"); - else - hover_result.icon = get_icon("Object", "EditorIcons"); + hover_result.icon = EditorNode::get_singleton()->get_object_icon(canvas_item); hover_result.name = canvas_item->get_name(); hovering_results_tmp.push_back(hover_result); @@ -2019,6 +2195,8 @@ void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) { //printf("Open scene on double click\n"); } else if ((accepted = _gui_input_anchors(p_event))) { //printf("Anchors\n"); + } else if ((accepted = _gui_input_scale(p_event))) { + //printf("Set scale\n"); } else if ((accepted = _gui_input_pivot(p_event))) { //printf("Set pivot\n"); } else if ((accepted = _gui_input_resize(p_event))) { @@ -2031,6 +2209,8 @@ void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) { //printf("Zoom or pan\n"); } else if ((accepted = _gui_input_select(p_event))) { //printf("Selection\n"); + } else { + //printf("Not accepted\n"); } if (accepted) @@ -2073,7 +2253,7 @@ void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) { case DRAG_BOTTOM_LEFT: c = CURSOR_BDIAGSIZE; break; - case DRAG_ALL: + case DRAG_MOVE: c = CURSOR_MOVE; break; case DRAG_PAN: @@ -2235,7 +2415,7 @@ void CanvasItemEditor::_draw_rulers() { if (i % minor_subdivision == 0) { viewport->draw_line(Point2(position.x, RULER_WIDTH * 0.33), Point2(position.x, RULER_WIDTH), graduation_color); } else { - viewport->draw_line(Point2(position.x, RULER_WIDTH * 0.66), Point2(position.x, RULER_WIDTH), graduation_color); + viewport->draw_line(Point2(position.x, RULER_WIDTH * 0.75), Point2(position.x, RULER_WIDTH), graduation_color); } } } @@ -2247,12 +2427,17 @@ void CanvasItemEditor::_draw_rulers() { if (i % (major_subdivision * minor_subdivision) == 0) { viewport->draw_line(Point2(0, position.y), Point2(RULER_WIDTH, position.y), graduation_color); float val = (ruler_transform * major_subdivide * minor_subdivide).xform(Point2(0, i)).y; - viewport->draw_string(font, Point2(2, position.y + 2 + font->get_height()), vformat(((int)val == val) ? "%d" : "%.1f", val), font_color); + + Transform2D text_xform = Transform2D(-Math_PI / 2.0, Point2(font->get_height(), position.y - 2)); + viewport->draw_set_transform_matrix(viewport->get_transform() * text_xform); + viewport->draw_string(font, Point2(), vformat(((int)val == val) ? "%d" : "%.1f", val), font_color); + viewport->draw_set_transform_matrix(viewport->get_transform()); + } else { if (i % minor_subdivision == 0) { viewport->draw_line(Point2(RULER_WIDTH * 0.33, position.y), Point2(RULER_WIDTH, position.y), graduation_color); } else { - viewport->draw_line(Point2(RULER_WIDTH * 0.66, position.y), Point2(RULER_WIDTH, position.y), graduation_color); + viewport->draw_line(Point2(RULER_WIDTH * 0.75, position.y), Point2(RULER_WIDTH, position.y), graduation_color); } } } @@ -2301,6 +2486,188 @@ void CanvasItemEditor::_draw_grid() { } } +void CanvasItemEditor::_draw_control_helpers(Control *control) { + Transform2D xform = transform * control->get_global_transform_with_canvas(); + RID ci = viewport->get_canvas_item(); + if (tool == TOOL_SELECT && show_helpers && !Object::cast_to<Container>(control->get_parent())) { + // Draw the helpers + Color color_base = Color(0.8, 0.8, 0.8, 0.5); + + float anchors_values[4]; + anchors_values[0] = control->get_anchor(MARGIN_LEFT); + anchors_values[1] = control->get_anchor(MARGIN_TOP); + anchors_values[2] = control->get_anchor(MARGIN_RIGHT); + anchors_values[3] = control->get_anchor(MARGIN_BOTTOM); + + // Draw the anchors + Vector2 anchors[4]; + Vector2 anchors_pos[4]; + for (int i = 0; i < 4; i++) { + anchors[i] = Vector2((i % 2 == 0) ? anchors_values[i] : anchors_values[(i + 1) % 4], (i % 2 == 1) ? anchors_values[i] : anchors_values[(i + 1) % 4]); + anchors_pos[i] = xform.xform(_anchor_to_position(control, anchors[i])); + } + + // Get which anchor is dragged + int dragged_anchor = -1; + switch (drag_type) { + case DRAG_ANCHOR_ALL: + case DRAG_ANCHOR_TOP_LEFT: + dragged_anchor = 0; + break; + case DRAG_ANCHOR_TOP_RIGHT: + dragged_anchor = 1; + break; + case DRAG_ANCHOR_BOTTOM_RIGHT: + dragged_anchor = 2; + break; + case DRAG_ANCHOR_BOTTOM_LEFT: + dragged_anchor = 3; + break; + default: + break; + } + + if (dragged_anchor >= 0) { + // Draw the 4 lines when dragged + bool snapped; + Color color_snapped = Color(0.64, 0.93, 0.67, 0.5); + + Vector2 corners_pos[4]; + for (int i = 0; i < 4; i++) { + corners_pos[i] = xform.xform(_anchor_to_position(control, Vector2((i == 0 || i == 3) ? ANCHOR_BEGIN : ANCHOR_END, (i <= 1) ? ANCHOR_BEGIN : ANCHOR_END))); + } + + Vector2 line_starts[4]; + Vector2 line_ends[4]; + for (int i = 0; i < 4; i++) { + float anchor_val = (i >= 2) ? ANCHOR_END - anchors_values[i] : anchors_values[i]; + line_starts[i] = Vector2::linear_interpolate(corners_pos[i], corners_pos[(i + 1) % 4], anchor_val); + line_ends[i] = Vector2::linear_interpolate(corners_pos[(i + 3) % 4], corners_pos[(i + 2) % 4], anchor_val); + snapped = anchors_values[i] == 0.0 || anchors_values[i] == 0.5 || anchors_values[i] == 1.0; + viewport->draw_line(line_starts[i], line_ends[i], snapped ? color_snapped : color_base, (i == dragged_anchor || (i + 3) % 4 == dragged_anchor) ? 2 : 1); + } + + // Display the percentages next to the lines + float percent_val; + percent_val = anchors_values[(dragged_anchor + 2) % 4] - anchors_values[dragged_anchor]; + percent_val = (dragged_anchor >= 2) ? -percent_val : percent_val; + _draw_percentage_at_position(percent_val, (anchors_pos[dragged_anchor] + anchors_pos[(dragged_anchor + 1) % 4]) / 2, (Margin)((dragged_anchor + 1) % 4)); + + percent_val = anchors_values[(dragged_anchor + 3) % 4] - anchors_values[(dragged_anchor + 1) % 4]; + percent_val = ((dragged_anchor + 1) % 4 >= 2) ? -percent_val : percent_val; + _draw_percentage_at_position(percent_val, (anchors_pos[dragged_anchor] + anchors_pos[(dragged_anchor + 3) % 4]) / 2, (Margin)(dragged_anchor)); + + percent_val = anchors_values[(dragged_anchor + 1) % 4]; + percent_val = ((dragged_anchor + 1) % 4 >= 2) ? ANCHOR_END - percent_val : percent_val; + _draw_percentage_at_position(percent_val, (line_starts[dragged_anchor] + anchors_pos[dragged_anchor]) / 2, (Margin)(dragged_anchor)); + + percent_val = anchors_values[dragged_anchor]; + percent_val = (dragged_anchor >= 2) ? ANCHOR_END - percent_val : percent_val; + _draw_percentage_at_position(percent_val, (line_ends[(dragged_anchor + 1) % 4] + anchors_pos[dragged_anchor]) / 2, (Margin)((dragged_anchor + 1) % 4)); + } + + Rect2 anchor_rects[4]; + anchor_rects[0] = Rect2(anchors_pos[0] - anchor_handle->get_size(), anchor_handle->get_size()); + anchor_rects[1] = Rect2(anchors_pos[1] - Vector2(0.0, anchor_handle->get_size().y), Point2(-anchor_handle->get_size().x, anchor_handle->get_size().y)); + anchor_rects[2] = Rect2(anchors_pos[2], -anchor_handle->get_size()); + anchor_rects[3] = Rect2(anchors_pos[3] - Vector2(anchor_handle->get_size().x, 0.0), Point2(anchor_handle->get_size().x, -anchor_handle->get_size().y)); + + for (int i = 0; i < 4; i++) { + anchor_handle->draw_rect(ci, anchor_rects[i]); + } + + // Draw the margin values and the node width/height when dragging control side + float ratio = 0.33; + Transform2D parent_transform = xform * control->get_transform().affine_inverse(); + float node_pos_in_parent[4]; + + Rect2 parent_rect = control->get_parent_anchorable_rect(); + + node_pos_in_parent[0] = control->get_anchor(MARGIN_LEFT) * parent_rect.size.width + control->get_margin(MARGIN_LEFT) + parent_rect.position.x; + node_pos_in_parent[1] = control->get_anchor(MARGIN_TOP) * parent_rect.size.height + control->get_margin(MARGIN_TOP) + parent_rect.position.y; + node_pos_in_parent[2] = control->get_anchor(MARGIN_RIGHT) * parent_rect.size.width + control->get_margin(MARGIN_RIGHT) + parent_rect.position.x; + node_pos_in_parent[3] = control->get_anchor(MARGIN_BOTTOM) * parent_rect.size.height + control->get_margin(MARGIN_BOTTOM) + parent_rect.position.y; + + Point2 start, end; + switch (drag_type) { + case DRAG_LEFT: + case DRAG_TOP_LEFT: + case DRAG_BOTTOM_LEFT: + _draw_margin_at_position(control->get_size().width, parent_transform.xform(Vector2((node_pos_in_parent[0] + node_pos_in_parent[2]) / 2, node_pos_in_parent[3])) + Vector2(0, 5), MARGIN_BOTTOM); + case DRAG_MOVE: + start = Vector2(node_pos_in_parent[0], Math::lerp(node_pos_in_parent[1], node_pos_in_parent[3], ratio)); + end = start - Vector2(control->get_margin(MARGIN_LEFT), 0); + _draw_margin_at_position(control->get_margin(MARGIN_LEFT), parent_transform.xform((start + end) / 2), MARGIN_TOP); + viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, 1); + break; + default: + break; + } + switch (drag_type) { + case DRAG_RIGHT: + case DRAG_TOP_RIGHT: + case DRAG_BOTTOM_RIGHT: + _draw_margin_at_position(control->get_size().width, parent_transform.xform(Vector2((node_pos_in_parent[0] + node_pos_in_parent[2]) / 2, node_pos_in_parent[3])) + Vector2(0, 5), MARGIN_BOTTOM); + case DRAG_MOVE: + start = Vector2(node_pos_in_parent[2], Math::lerp(node_pos_in_parent[3], node_pos_in_parent[1], ratio)); + end = start - Vector2(control->get_margin(MARGIN_RIGHT), 0); + _draw_margin_at_position(control->get_margin(MARGIN_RIGHT), parent_transform.xform((start + end) / 2), MARGIN_BOTTOM); + viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, 1); + break; + default: + break; + } + switch (drag_type) { + case DRAG_TOP: + case DRAG_TOP_LEFT: + case DRAG_TOP_RIGHT: + _draw_margin_at_position(control->get_size().height, parent_transform.xform(Vector2(node_pos_in_parent[2], (node_pos_in_parent[1] + node_pos_in_parent[3]) / 2)) + Vector2(5, 0), MARGIN_RIGHT); + case DRAG_MOVE: + start = Vector2(Math::lerp(node_pos_in_parent[0], node_pos_in_parent[2], ratio), node_pos_in_parent[1]); + end = start - Vector2(0, control->get_margin(MARGIN_TOP)); + _draw_margin_at_position(control->get_margin(MARGIN_TOP), parent_transform.xform((start + end) / 2), MARGIN_LEFT); + viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, 1); + break; + default: + break; + } + switch (drag_type) { + case DRAG_BOTTOM: + case DRAG_BOTTOM_LEFT: + case DRAG_BOTTOM_RIGHT: + _draw_margin_at_position(control->get_size().height, parent_transform.xform(Vector2(node_pos_in_parent[2], (node_pos_in_parent[1] + node_pos_in_parent[3]) / 2) + Vector2(5, 0)), MARGIN_RIGHT); + case DRAG_MOVE: + start = Vector2(Math::lerp(node_pos_in_parent[2], node_pos_in_parent[0], ratio), node_pos_in_parent[3]); + end = start - Vector2(0, control->get_margin(MARGIN_BOTTOM)); + _draw_margin_at_position(control->get_margin(MARGIN_BOTTOM), parent_transform.xform((start + end) / 2), MARGIN_RIGHT); + viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, 1); + break; + default: + break; + } + + switch (drag_type) { + //Draw the ghost rect if the node if rotated/scaled + case DRAG_LEFT: + case DRAG_TOP_LEFT: + case DRAG_TOP: + case DRAG_TOP_RIGHT: + case DRAG_RIGHT: + case DRAG_BOTTOM_RIGHT: + case DRAG_BOTTOM: + case DRAG_BOTTOM_LEFT: + case DRAG_MOVE: + if (control->get_rotation() != 0.0 || control->get_scale() != Vector2(1, 1)) { + Rect2 rect = Rect2(Vector2(node_pos_in_parent[0], node_pos_in_parent[1]), control->get_size()); + viewport->draw_rect(parent_transform.xform(rect), color_base, false); + } + break; + default: + break; + } + } +} + void CanvasItemEditor::_draw_selection() { Ref<Texture> pivot_icon = get_icon("EditorPivot", "EditorIcons"); Ref<Texture> position_icon = get_icon("EditorPosition", "EditorIcons"); @@ -2317,7 +2684,7 @@ void CanvasItemEditor::_draw_selection() { // Draw the previous position if we are dragging the node if (show_helpers && - (drag_type == DRAG_ALL || drag_type == DRAG_ROTATE || + (drag_type == DRAG_MOVE || drag_type == DRAG_ROTATE || drag_type == DRAG_LEFT || drag_type == DRAG_RIGHT || drag_type == DRAG_TOP || drag_type == DRAG_BOTTOM || drag_type == DRAG_TOP_LEFT || drag_type == DRAG_TOP_RIGHT || drag_type == DRAG_BOTTOM_LEFT || drag_type == DRAG_BOTTOM_RIGHT)) { const Transform2D pre_drag_xform = transform * se->pre_drag_xform; @@ -2359,200 +2726,27 @@ void CanvasItemEditor::_draw_selection() { } } else { - Transform2D transform = Transform2D(xform.get_rotation(), xform.get_origin()); - viewport->draw_set_transform_matrix(transform); + Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * Transform2D(canvas_item->_edit_get_rotation(), canvas_item->_edit_get_position())).orthonormalized(); + Transform2D simple_xform = viewport->get_transform() * unscaled_transform; + viewport->draw_set_transform_matrix(simple_xform); viewport->draw_texture(position_icon, -(position_icon->get_size() / 2)); - viewport->draw_set_transform_matrix(Transform2D()); + viewport->draw_set_transform_matrix(viewport->get_transform()); } - if (single && (tool == TOOL_SELECT || tool == TOOL_MOVE || tool == TOOL_ROTATE || tool == TOOL_EDIT_PIVOT)) { //kind of sucks + if (single && (tool == TOOL_SELECT || tool == TOOL_MOVE || tool == TOOL_SCALE || tool == TOOL_ROTATE || tool == TOOL_EDIT_PIVOT)) { //kind of sucks // Draw the pivot if (canvas_item->_edit_get_pivot() != Vector2() || drag_type == DRAG_PIVOT || tool == TOOL_EDIT_PIVOT) { // This is not really clean :/ viewport->draw_texture(pivot_icon, (xform.xform(canvas_item->_edit_get_pivot()) - (pivot_icon->get_size() / 2)).floor()); } + // Draw control-related helpers Control *control = Object::cast_to<Control>(canvas_item); - if (control) { - if (tool == TOOL_SELECT && show_helpers && !Object::cast_to<Container>(control->get_parent())) { - // Draw the helpers - Color color_base = Color(0.8, 0.8, 0.8, 0.5); - - float anchors_values[4]; - anchors_values[0] = control->get_anchor(MARGIN_LEFT); - anchors_values[1] = control->get_anchor(MARGIN_TOP); - anchors_values[2] = control->get_anchor(MARGIN_RIGHT); - anchors_values[3] = control->get_anchor(MARGIN_BOTTOM); - - // Draw the anchors - Vector2 anchors[4]; - Vector2 anchors_pos[4]; - for (int i = 0; i < 4; i++) { - anchors[i] = Vector2((i % 2 == 0) ? anchors_values[i] : anchors_values[(i + 1) % 4], (i % 2 == 1) ? anchors_values[i] : anchors_values[(i + 1) % 4]); - anchors_pos[i] = xform.xform(_anchor_to_position(control, anchors[i])); - } - - // Get which anchor is dragged - int dragged_anchor = -1; - switch (drag_type) { - case DRAG_ANCHOR_ALL: - case DRAG_ANCHOR_TOP_LEFT: - dragged_anchor = 0; - break; - case DRAG_ANCHOR_TOP_RIGHT: - dragged_anchor = 1; - break; - case DRAG_ANCHOR_BOTTOM_RIGHT: - dragged_anchor = 2; - break; - case DRAG_ANCHOR_BOTTOM_LEFT: - dragged_anchor = 3; - break; - default: - break; - } - - if (dragged_anchor >= 0) { - // Draw the 4 lines when dragged - bool snapped; - Color color_snapped = Color(0.64, 0.93, 0.67, 0.5); - - Vector2 corners_pos[4]; - for (int i = 0; i < 4; i++) { - corners_pos[i] = xform.xform(_anchor_to_position(control, Vector2((i == 0 || i == 3) ? ANCHOR_BEGIN : ANCHOR_END, (i <= 1) ? ANCHOR_BEGIN : ANCHOR_END))); - } - - Vector2 line_starts[4]; - Vector2 line_ends[4]; - for (int i = 0; i < 4; i++) { - float anchor_val = (i >= 2) ? ANCHOR_END - anchors_values[i] : anchors_values[i]; - line_starts[i] = Vector2::linear_interpolate(corners_pos[i], corners_pos[(i + 1) % 4], anchor_val); - line_ends[i] = Vector2::linear_interpolate(corners_pos[(i + 3) % 4], corners_pos[(i + 2) % 4], anchor_val); - snapped = anchors_values[i] == 0.0 || anchors_values[i] == 0.5 || anchors_values[i] == 1.0; - viewport->draw_line(line_starts[i], line_ends[i], snapped ? color_snapped : color_base, (i == dragged_anchor || (i + 3) % 4 == dragged_anchor) ? 2 : 1); - } - - // Display the percentages next to the lines - float percent_val; - percent_val = anchors_values[(dragged_anchor + 2) % 4] - anchors_values[dragged_anchor]; - percent_val = (dragged_anchor >= 2) ? -percent_val : percent_val; - _draw_percentage_at_position(percent_val, (anchors_pos[dragged_anchor] + anchors_pos[(dragged_anchor + 1) % 4]) / 2, (Margin)((dragged_anchor + 1) % 4)); - - percent_val = anchors_values[(dragged_anchor + 3) % 4] - anchors_values[(dragged_anchor + 1) % 4]; - percent_val = ((dragged_anchor + 1) % 4 >= 2) ? -percent_val : percent_val; - _draw_percentage_at_position(percent_val, (anchors_pos[dragged_anchor] + anchors_pos[(dragged_anchor + 3) % 4]) / 2, (Margin)(dragged_anchor)); - - percent_val = anchors_values[(dragged_anchor + 1) % 4]; - percent_val = ((dragged_anchor + 1) % 4 >= 2) ? ANCHOR_END - percent_val : percent_val; - _draw_percentage_at_position(percent_val, (line_starts[dragged_anchor] + anchors_pos[dragged_anchor]) / 2, (Margin)(dragged_anchor)); - - percent_val = anchors_values[dragged_anchor]; - percent_val = (dragged_anchor >= 2) ? ANCHOR_END - percent_val : percent_val; - _draw_percentage_at_position(percent_val, (line_ends[(dragged_anchor + 1) % 4] + anchors_pos[dragged_anchor]) / 2, (Margin)((dragged_anchor + 1) % 4)); - } - - Rect2 anchor_rects[4]; - anchor_rects[0] = Rect2(anchors_pos[0] - anchor_handle->get_size(), anchor_handle->get_size()); - anchor_rects[1] = Rect2(anchors_pos[1] - Vector2(0.0, anchor_handle->get_size().y), Point2(-anchor_handle->get_size().x, anchor_handle->get_size().y)); - anchor_rects[2] = Rect2(anchors_pos[2], -anchor_handle->get_size()); - anchor_rects[3] = Rect2(anchors_pos[3] - Vector2(anchor_handle->get_size().x, 0.0), Point2(anchor_handle->get_size().x, -anchor_handle->get_size().y)); - - for (int i = 0; i < 4; i++) { - anchor_handle->draw_rect(ci, anchor_rects[i]); - } - - // Draw the margin values and the node width/height when dragging control side - float ratio = 0.33; - Transform2D parent_transform = xform * control->get_transform().affine_inverse(); - float node_pos_in_parent[4]; - - Rect2 parent_rect = control->get_parent_anchorable_rect(); - - node_pos_in_parent[0] = control->get_anchor(MARGIN_LEFT) * parent_rect.size.width + control->get_margin(MARGIN_LEFT) + parent_rect.position.x; - node_pos_in_parent[1] = control->get_anchor(MARGIN_TOP) * parent_rect.size.height + control->get_margin(MARGIN_TOP) + parent_rect.position.y; - node_pos_in_parent[2] = control->get_anchor(MARGIN_RIGHT) * parent_rect.size.width + control->get_margin(MARGIN_RIGHT) + parent_rect.position.x; - node_pos_in_parent[3] = control->get_anchor(MARGIN_BOTTOM) * parent_rect.size.height + control->get_margin(MARGIN_BOTTOM) + parent_rect.position.y; - - Point2 start, end; - switch (drag_type) { - case DRAG_LEFT: - case DRAG_TOP_LEFT: - case DRAG_BOTTOM_LEFT: - _draw_margin_at_position(control->get_size().width, parent_transform.xform(Vector2((node_pos_in_parent[0] + node_pos_in_parent[2]) / 2, node_pos_in_parent[3])) + Vector2(0, 5), MARGIN_BOTTOM); - case DRAG_ALL: - start = Vector2(node_pos_in_parent[0], Math::lerp(node_pos_in_parent[1], node_pos_in_parent[3], ratio)); - end = start - Vector2(control->get_margin(MARGIN_LEFT), 0); - _draw_margin_at_position(control->get_margin(MARGIN_LEFT), parent_transform.xform((start + end) / 2), MARGIN_TOP); - viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, 1); - break; - default: - break; - } - switch (drag_type) { - case DRAG_RIGHT: - case DRAG_TOP_RIGHT: - case DRAG_BOTTOM_RIGHT: - _draw_margin_at_position(control->get_size().width, parent_transform.xform(Vector2((node_pos_in_parent[0] + node_pos_in_parent[2]) / 2, node_pos_in_parent[3])) + Vector2(0, 5), MARGIN_BOTTOM); - case DRAG_ALL: - start = Vector2(node_pos_in_parent[2], Math::lerp(node_pos_in_parent[3], node_pos_in_parent[1], ratio)); - end = start - Vector2(control->get_margin(MARGIN_RIGHT), 0); - _draw_margin_at_position(control->get_margin(MARGIN_RIGHT), parent_transform.xform((start + end) / 2), MARGIN_BOTTOM); - viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, 1); - break; - default: - break; - } - switch (drag_type) { - case DRAG_TOP: - case DRAG_TOP_LEFT: - case DRAG_TOP_RIGHT: - _draw_margin_at_position(control->get_size().height, parent_transform.xform(Vector2(node_pos_in_parent[2], (node_pos_in_parent[1] + node_pos_in_parent[3]) / 2)) + Vector2(5, 0), MARGIN_RIGHT); - case DRAG_ALL: - start = Vector2(Math::lerp(node_pos_in_parent[0], node_pos_in_parent[2], ratio), node_pos_in_parent[1]); - end = start - Vector2(0, control->get_margin(MARGIN_TOP)); - _draw_margin_at_position(control->get_margin(MARGIN_TOP), parent_transform.xform((start + end) / 2), MARGIN_LEFT); - viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, 1); - break; - default: - break; - } - switch (drag_type) { - case DRAG_BOTTOM: - case DRAG_BOTTOM_LEFT: - case DRAG_BOTTOM_RIGHT: - _draw_margin_at_position(control->get_size().height, parent_transform.xform(Vector2(node_pos_in_parent[2], (node_pos_in_parent[1] + node_pos_in_parent[3]) / 2) + Vector2(5, 0)), MARGIN_RIGHT); - case DRAG_ALL: - start = Vector2(Math::lerp(node_pos_in_parent[2], node_pos_in_parent[0], ratio), node_pos_in_parent[3]); - end = start - Vector2(0, control->get_margin(MARGIN_BOTTOM)); - _draw_margin_at_position(control->get_margin(MARGIN_BOTTOM), parent_transform.xform((start + end) / 2), MARGIN_RIGHT); - viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, 1); - break; - default: - break; - } - - switch (drag_type) { - //Draw the ghost rect if the node if rotated/scaled - case DRAG_LEFT: - case DRAG_TOP_LEFT: - case DRAG_TOP: - case DRAG_TOP_RIGHT: - case DRAG_RIGHT: - case DRAG_BOTTOM_RIGHT: - case DRAG_BOTTOM: - case DRAG_BOTTOM_LEFT: - case DRAG_ALL: - if (control->get_rotation() != 0.0 || control->get_scale() != Vector2(1, 1)) { - Rect2 rect = Rect2(Vector2(node_pos_in_parent[0], node_pos_in_parent[1]), control->get_size()); - viewport->draw_rect(parent_transform.xform(rect), color_base, false); - } - break; - default: - break; - } - } + if (control && _is_node_movable(control)) { + _draw_control_helpers(control); } - if (tool == TOOL_SELECT && canvas_item->_edit_use_rect()) { + // Draw the resize handles + if (tool == TOOL_SELECT && canvas_item->_edit_use_rect() && _is_node_movable(canvas_item)) { Rect2 rect = canvas_item->_edit_get_rect(); Vector2 endpoints[4] = { xform.xform(rect.position), @@ -2561,7 +2755,6 @@ void CanvasItemEditor::_draw_selection() { xform.xform(rect.position + Vector2(0, rect.size.y)) }; for (int i = 0; i < 4; i++) { - // Draw the resize handles int prev = (i + 3) % 4; int next = (i + 1) % 4; @@ -2576,6 +2769,47 @@ void CanvasItemEditor::_draw_selection() { select_handle->draw(ci, (ofs - (select_handle->get_size() / 2)).floor()); } } + + // Draw the rescale handles + bool is_ctrl = Input::get_singleton()->is_key_pressed(KEY_CONTROL); + bool is_alt = Input::get_singleton()->is_key_pressed(KEY_ALT); + if ((is_alt && is_ctrl) || tool == TOOL_SCALE || drag_type == DRAG_SCALE_X || drag_type == DRAG_SCALE_Y) { + if (_is_node_movable(canvas_item)) { + Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * Transform2D(canvas_item->_edit_get_rotation(), canvas_item->_edit_get_position())).orthonormalized(); + Transform2D simple_xform = viewport->get_transform() * unscaled_transform; + + Size2 scale_factor = Size2(SCALE_HANDLE_DISTANCE, SCALE_HANDLE_DISTANCE); + bool uniform = Input::get_singleton()->is_key_pressed(KEY_SHIFT); + Point2 offset = (simple_xform.affine_inverse().xform(drag_to) - simple_xform.affine_inverse().xform(drag_from)) * zoom; + + if (drag_type == DRAG_SCALE_X) { + scale_factor.x += offset.x; + if (uniform) { + scale_factor.y += offset.x; + } + } else if (drag_type == DRAG_SCALE_Y) { + scale_factor.y -= offset.y; + if (uniform) { + scale_factor.x -= offset.y; + } + } + + //scale_factor *= zoom; + + viewport->draw_set_transform_matrix(simple_xform); + Rect2 x_handle_rect = Rect2(scale_factor.x * EDSCALE, -5 * EDSCALE, 10 * EDSCALE, 10 * EDSCALE); + Color x_axis_color(1.0, 0.4, 0.4, 0.6); + viewport->draw_rect(x_handle_rect, x_axis_color); + viewport->draw_line(Point2(), Point2(scale_factor.x * EDSCALE, 0), x_axis_color); + + Rect2 y_handle_rect = Rect2(-5 * EDSCALE, -(scale_factor.y + 10) * EDSCALE, 10 * EDSCALE, 10 * EDSCALE); + Color y_axis_color(0.4, 1.0, 0.4, 0.6); + viewport->draw_rect(y_handle_rect, y_axis_color); + viewport->draw_line(Point2(), Point2(0, -scale_factor.y * EDSCALE), y_axis_color); + + viewport->draw_set_transform_matrix(viewport->get_transform()); + } + } } } @@ -2650,7 +2884,7 @@ void CanvasItemEditor::_draw_axis() { RID ci = viewport->get_canvas_item(); - Color area_axis_color(0.4, 0.4, 1.0, 0.4); + Color area_axis_color = EditorSettings::get_singleton()->get("editors/2d/viewport_border_color"); Size2 screen_size = Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height")); @@ -2750,15 +2984,16 @@ void CanvasItemEditor::_draw_invisible_nodes_positions(Node *p_node, const Trans _draw_invisible_nodes_positions(p_node->get_child(i), parent_xform, canvas_xform); } - if (canvas_item && !canvas_item->_edit_use_rect() && !editor_selection->is_selected(canvas_item)) { + if (canvas_item && !canvas_item->_edit_use_rect() && (!editor_selection->is_selected(canvas_item) || _is_node_locked(canvas_item))) { Transform2D xform = transform * canvas_xform * parent_xform; // Draw the node's position Ref<Texture> position_icon = get_icon("EditorPositionUnselected", "EditorIcons"); - Transform2D transform = Transform2D(xform.get_rotation(), xform.get_origin()); - viewport->draw_set_transform_matrix(transform); + Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * Transform2D(canvas_item->_edit_get_rotation(), canvas_item->_edit_get_position())).orthonormalized(); + Transform2D simple_xform = viewport->get_transform() * unscaled_transform; + viewport->draw_set_transform_matrix(simple_xform); viewport->draw_texture(position_icon, -position_icon->get_size() / 2, Color(1.0, 1.0, 1.0, 0.5)); - viewport->draw_set_transform_matrix(Transform2D()); + viewport->draw_set_transform_matrix(viewport->get_transform()); } } @@ -2775,7 +3010,7 @@ void CanvasItemEditor::_draw_hover() { Size2 item_size = Size2(node_icon->get_size().x + 4 + node_name_size.x, MAX(node_icon->get_size().y, node_name_size.y - 3)); Point2 pos = transform.xform(hovering_results[i].position) - Point2(0, item_size.y) + (Point2(node_icon->get_size().x, -node_icon->get_size().y) / 4); - // Rectify the position to avoid overlaping items + // Rectify the position to avoid overlapping items for (List<Rect2>::Element *E = previous_rects.front(); E; E = E->next()) { if (E->get().intersects(Rect2(pos, item_size))) { pos.y = E->get().get_position().y - item_size.y; @@ -2822,13 +3057,13 @@ void CanvasItemEditor::_draw_locks_and_groups(Node *p_node, const Transform2D &p float offset = 0; Ref<Texture> lock = get_icon("LockViewport", "EditorIcons"); - if (p_node->has_meta("_edit_lock_")) { + if (p_node->has_meta("_edit_lock_") && show_edit_locks) { lock->draw(viewport_canvas_item, (transform * canvas_xform * parent_xform).xform(Point2(0, 0)) + Point2(offset, 0)); offset += lock->get_size().x; } Ref<Texture> group = get_icon("GroupViewport", "EditorIcons"); - if (canvas_item->has_meta("_edit_group_")) { + if (canvas_item->has_meta("_edit_group_") && show_edit_locks) { group->draw(viewport_canvas_item, (transform * canvas_xform * parent_xform).xform(Point2(0, 0)) + Point2(offset, 0)); //offset += group->get_size().x; } @@ -2902,6 +3137,7 @@ bool CanvasItemEditor::_build_bones_list(Node *p_node) { } void CanvasItemEditor::_draw_viewport() { + // Update the transform transform = Transform2D(); transform.scale_basis(Size2(zoom, zoom)); @@ -2937,6 +3173,8 @@ void CanvasItemEditor::_draw_viewport() { group_button->set_disabled(selection.empty()); ungroup_button->set_visible(all_group); + info_overlay->set_margin(MARGIN_LEFT, (show_rulers ? RULER_WIDTH : 0) + 10); + _draw_grid(); _draw_selection(); _draw_axis(); @@ -2950,11 +3188,11 @@ void CanvasItemEditor::_draw_viewport() { EditorPluginList *over_plugin_list = editor->get_editor_plugins_over(); if (!over_plugin_list->empty()) { - over_plugin_list->forward_draw_over_viewport(viewport); + over_plugin_list->forward_canvas_draw_over_viewport(viewport); } EditorPluginList *force_over_plugin_list = editor->get_editor_plugins_force_over(); if (!force_over_plugin_list->empty()) { - force_over_plugin_list->forward_force_draw_over_viewport(viewport); + force_over_plugin_list->forward_canvas_force_draw_over_viewport(viewport); } _draw_bones(); @@ -2966,6 +3204,11 @@ void CanvasItemEditor::_draw_viewport() { _draw_hover(); } +void CanvasItemEditor::update_viewport() { + _update_scrollbars(); + viewport->update(); +} + void CanvasItemEditor::_notification(int p_what) { if (p_what == NOTIFICATION_PHYSICS_PROCESS) { @@ -3086,6 +3329,7 @@ void CanvasItemEditor::_notification(int p_what) { 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")); + scale_button->set_icon(get_icon("ToolScale", "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")); @@ -3159,11 +3403,14 @@ void CanvasItemEditor::_notification(int p_what) { void CanvasItemEditor::edit(CanvasItem *p_canvas_item) { - drag_type = DRAG_NONE; + Array selection = editor_selection->get_selected_nodes(); + if (selection.size() != 1 || (Node *)selection[0] != p_canvas_item) { + drag_type = DRAG_NONE; - // Clear the selection - editor_selection->clear(); //_clear_canvas_items(); - editor_selection->add_node(p_canvas_item); + // Clear the selection + editor_selection->clear(); //_clear_canvas_items(); + editor_selection->add_node(p_canvas_item); + } } void CanvasItemEditor::_queue_update_bone_list() { @@ -3295,6 +3542,35 @@ void CanvasItemEditor::_update_scrollbars() { updating_scroll = false; } +void CanvasItemEditor::_popup_warning_depop(Control *p_control) { + ERR_FAIL_COND(!popup_temporarily_timers.has(p_control)); + + Timer *timer = popup_temporarily_timers[p_control]; + p_control->hide(); + remove_child(timer); + popup_temporarily_timers.erase(p_control); + memdelete(timer); + info_overlay->set_margin(MARGIN_LEFT, (show_rulers ? RULER_WIDTH : 0) + 10); +} + +void CanvasItemEditor::_popup_warning_temporarily(Control *p_control, const float p_duration) { + Timer *timer; + if (!popup_temporarily_timers.has(p_control)) { + timer = memnew(Timer); + timer->connect("timeout", this, "_popup_warning_depop", varray(p_control)); + timer->set_one_shot(true); + add_child(timer); + + popup_temporarily_timers[p_control] = timer; + } else { + timer = popup_temporarily_timers[p_control]; + } + + timer->start(p_duration); + p_control->show(); + info_overlay->set_margin(MARGIN_LEFT, (show_rulers ? RULER_WIDTH : 0) + 10); +} + void CanvasItemEditor::_update_scroll(float) { if (updating_scroll) @@ -3371,8 +3647,7 @@ void CanvasItemEditor::_zoom_on_position(float p_zoom, Point2 p_position) { view_offset.x = Math::round(view_offset.x + ofs.x); view_offset.y = Math::round(view_offset.y + ofs.y); - _update_scrollbars(); - viewport->update(); + update_viewport(); } void CanvasItemEditor::_button_zoom_minus() { @@ -3394,7 +3669,7 @@ void CanvasItemEditor::_button_toggle_snap(bool p_status) { void CanvasItemEditor::_button_tool_select(int p_index) { - ToolButton *tb[TOOL_MAX] = { select_button, list_select_button, move_button, rotate_button, pivot_button, pan_button }; + ToolButton *tb[TOOL_MAX] = { select_button, list_select_button, move_button, scale_button, rotate_button, pivot_button, pan_button }; for (int i = 0; i < TOOL_MAX; i++) { tb[i]->set_pressed(i == p_index); } @@ -3426,6 +3701,12 @@ void CanvasItemEditor::_popup_callback(int p_op) { view_menu->get_popup()->set_item_checked(idx, show_viewport); viewport->update(); } break; + case SHOW_EDIT_LOCKS: { + show_edit_locks = !show_edit_locks; + int idx = view_menu->get_popup()->get_item_index(SHOW_EDIT_LOCKS); + view_menu->get_popup()->set_item_checked(idx, show_edit_locks); + viewport->update(); + } break; case SNAP_USE_NODE_PARENT: { snap_node_parent = !snap_node_parent; int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_PARENT); @@ -3963,8 +4244,7 @@ void CanvasItemEditor::_focus_selection(int p_op) { Vector2 offset = viewport->get_size() / 2 - editor->get_scene_root()->get_global_canvas_transform().xform(center); view_offset.x -= offset.x / zoom; view_offset.y -= offset.y / zoom; - _update_scrollbars(); - viewport->update(); + update_viewport(); } else { // VIEW_FRAME_TO_SELECTION @@ -3997,10 +4277,11 @@ void CanvasItemEditor::_bind_methods() { ClassDB::bind_method("_snap_changed", &CanvasItemEditor::_snap_changed); ClassDB::bind_method("_update_bone_list", &CanvasItemEditor::_update_bone_list); ClassDB::bind_method("_tree_changed", &CanvasItemEditor::_tree_changed); - + ClassDB::bind_method("_popup_warning_depop", &CanvasItemEditor::_popup_warning_depop); ClassDB::bind_method(D_METHOD("_selection_result_pressed"), &CanvasItemEditor::_selection_result_pressed); ClassDB::bind_method(D_METHOD("_selection_menu_hide"), &CanvasItemEditor::_selection_menu_hide); ClassDB::bind_method(D_METHOD("set_state"), &CanvasItemEditor::set_state); + ClassDB::bind_method(D_METHOD("update_viewport"), &CanvasItemEditor::update_viewport); ADD_SIGNAL(MethodInfo("item_lock_status_changed")); ADD_SIGNAL(MethodInfo("item_group_status_changed")); @@ -4029,6 +4310,7 @@ Dictionary CanvasItemEditor::get_state() const { state["show_rulers"] = show_rulers; state["show_guides"] = show_guides; state["show_helpers"] = show_helpers; + state["show_edit_locks"] = show_edit_locks; state["snap_rotation"] = snap_rotation; state["snap_relative"] = snap_relative; state["snap_pixel"] = snap_pixel; @@ -4148,6 +4430,12 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) { view_menu->get_popup()->set_item_checked(idx, show_helpers); } + if (state.has("show_edit_locks")) { + show_edit_locks = state["show_edit_locks"]; + int idx = view_menu->get_popup()->get_item_index(SHOW_EDIT_LOCKS); + view_menu->get_popup()->set_item_checked(idx, show_edit_locks); + } + if (state.has("snap_rotation")) { snap_rotation = state["snap_rotation"]; int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_ROTATION); @@ -4175,7 +4463,22 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) { viewport->update(); } +void CanvasItemEditor::add_control_to_info_overlay(Control *p_control) { + ERR_FAIL_COND(!p_control); + + p_control->set_h_size_flags(p_control->get_h_size_flags() & ~Control::SIZE_EXPAND_FILL); + info_overlay->add_child(p_control); + info_overlay->set_margin(MARGIN_LEFT, (show_rulers ? RULER_WIDTH : 0) + 10); +} + +void CanvasItemEditor::remove_control_from_info_overlay(Control *p_control) { + + info_overlay->remove_child(p_control); + info_overlay->set_margin(MARGIN_LEFT, (show_rulers ? RULER_WIDTH : 0) + 10); +} + void CanvasItemEditor::add_control_to_menu_panel(Control *p_control) { + ERR_FAIL_COND(!p_control); hb->add_child(p_control); } @@ -4201,6 +4504,46 @@ void CanvasItemEditor::focus_selection() { CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { + key_pos = true; + key_rot = true; + key_scale = false; + + show_grid = false; + show_origin = true; + show_viewport = true; + show_helpers = false; + show_rulers = true; + show_guides = true; + show_edit_locks = true; + zoom = 1; + view_offset = Point2(-150 - RULER_WIDTH, -95 - RULER_WIDTH); + previous_update_view_offset = view_offset; // Moves the view a little bit to the left so that (0,0) is visible. The values a relative to a 16/10 screen + grid_offset = Point2(); + grid_step = Point2(10, 10); + grid_step_multiplier = 0; + snap_rotation_offset = 0; + snap_rotation_step = 15 / (180 / Math_PI); + snap_active = false; + snap_node_parent = true; + snap_node_anchors = true; + snap_node_sides = true; + snap_node_center = true; + snap_other_nodes = true; + snap_grid = true; + snap_guides = true; + snap_rotation = false; + snap_pixel = false; + + skeleton_show_bones = true; + + drag_type = DRAG_NONE; + drag_from = Vector2(); + drag_to = Vector2(); + dragged_guide_pos = Point2(); + dragged_guide_index = -1; + + bone_last_frame = 0; + bone_list_dirty = false; tool = TOOL_SELECT; undo_redo = p_editor->get_undo_redo(); @@ -4244,6 +4587,28 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { viewport->connect("draw", this, "_draw_viewport"); viewport->connect("gui_input", this, "_gui_input_viewport"); + info_overlay = memnew(VBoxContainer); + info_overlay->set_anchors_and_margins_preset(Control::PRESET_BOTTOM_LEFT); + info_overlay->set_margin(MARGIN_LEFT, 10); + info_overlay->set_margin(MARGIN_BOTTOM, -15); + info_overlay->set_v_grow_direction(Control::GROW_DIRECTION_BEGIN); + info_overlay->add_constant_override("separation", 10); + viewport_scrollable->add_child(info_overlay); + + Theme *info_overlay_theme = memnew(Theme); + info_overlay_theme->copy_default_theme(); + info_overlay->set_theme(info_overlay_theme); + + StyleBoxFlat *info_overlay_label_stylebox = memnew(StyleBoxFlat); + info_overlay_label_stylebox->set_bg_color(Color(0.0, 0.0, 0.0, 0.2)); + info_overlay_label_stylebox->set_expand_margin_size_all(4); + info_overlay_theme->set_stylebox("normal", "Label", info_overlay_label_stylebox); + + warning_child_of_container = memnew(Label); + warning_child_of_container->hide(); + warning_child_of_container->set_text("Warning: Children of a container get their position and size determined only by their parent"); + add_control_to_info_overlay(warning_child_of_container); + h_scroll = memnew(HScrollBar); viewport->add_child(h_scroll); h_scroll->connect("value_changed", this, "_update_scroll"); @@ -4273,7 +4638,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { zoom_plus = memnew(ToolButton); zoom_hb->add_child(zoom_plus); zoom_plus->connect("pressed", this, "_button_zoom_plus"); - zoom_plus->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_plus", TTR("Zoom in"), KEY_MASK_CMD | KEY_PLUS)); + zoom_plus->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_plus", TTR("Zoom in"), KEY_MASK_CMD | KEY_EQUAL)); // Usually direct access key for PLUS zoom_plus->set_focus_mode(FOCUS_NONE); updating_scroll = false; @@ -4286,6 +4651,8 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { select_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/select_mode", TTR("Select Mode"), KEY_Q)); select_button->set_tooltip(keycode_get_string(KEY_MASK_CMD) + TTR("Drag: Rotate") + "\n" + TTR("Alt+Drag: Move") + "\n" + TTR("Press 'v' to Change Pivot, 'Shift+v' to Drag Pivot (while moving).") + "\n" + TTR("Alt+RMB: Depth list selection")); + hb->add_child(memnew(VSeparator)); + move_button = memnew(ToolButton); hb->add_child(move_button); move_button->set_toggle_mode(true); @@ -4300,6 +4667,13 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { rotate_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/rotate_mode", TTR("Rotate Mode"), KEY_E)); rotate_button->set_tooltip(TTR("Rotate Mode")); + scale_button = memnew(ToolButton); + hb->add_child(scale_button); + scale_button->set_toggle_mode(true); + scale_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_SCALE)); + scale_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/scale_mode", TTR("Scale Mode"), KEY_S)); + scale_button->set_tooltip(TTR("Scale Mode")); + hb->add_child(memnew(VSeparator)); list_select_button = memnew(ToolButton); @@ -4383,6 +4757,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { skeleton_menu = memnew(MenuButton); hb->add_child(skeleton_menu); + skeleton_menu->set_tooltip(TTR("Skeleton Options")); p = skeleton_menu->get_popup(); p->set_hide_on_checkable_item_selection(false); @@ -4409,6 +4784,8 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_guides", TTR("Show Guides"), KEY_Y), SHOW_GUIDES); p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_origin", TTR("Show Origin")), SHOW_ORIGIN); p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_viewport", TTR("Show Viewport")), SHOW_VIEWPORT); + p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_edit_locks", TTR("Show Group And Lock Icons")), SHOW_EDIT_LOCKS); + p->add_separator(); 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); @@ -4489,48 +4866,11 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { multiply_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/multiply_grid_step", TTR("Multiply grid step by 2"), KEY_KP_MULTIPLY); divide_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/divide_grid_step", TTR("Divide grid step by 2"), KEY_KP_DIVIDE); - key_pos = true; - key_rot = true; - key_scale = false; - - show_grid = false; - show_origin = true; - show_viewport = true; - show_helpers = false; - show_rulers = true; - show_guides = true; - zoom = 1; - view_offset = Point2(-150 - RULER_WIDTH, -95 - RULER_WIDTH); - previous_update_view_offset = view_offset; // Moves the view a little bit to the left so that (0,0) is visible. The values a relative to a 16/10 screen - grid_offset = Point2(); - grid_step = Point2(10, 10); - grid_step_multiplier = 0; - snap_rotation_offset = 0; - snap_rotation_step = 15 / (180 / Math_PI); - snap_active = false; - snap_node_parent = true; - snap_node_anchors = true; - snap_node_sides = true; - snap_node_center = true; - snap_other_nodes = true; - snap_grid = true; - snap_guides = true; - snap_rotation = false; - snap_pixel = false; - skeleton_show_bones = true; skeleton_menu->get_popup()->set_item_checked(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES), true); singleton = this; set_process_unhandled_key_input(true); - drag_type = DRAG_NONE; - drag_from = Vector2(); - drag_to = Vector2(); - dragged_guide_pos = Point2(); - dragged_guide_index = -1; - - bone_last_frame = 0; - // Update the menus' checkboxes call_deferred("set_state", get_state()); } @@ -4730,19 +5070,13 @@ void CanvasItemEditorViewport::_create_nodes(Node *parent, Node *child, String & editor_data->get_undo_redo().add_do_property(child, "polygon", list); } - // locate at preview position - Point2 pos = Point2(0, 0); - if (parent && parent->has_method("get_global_position")) { - pos = parent->call("get_global_position"); - } - Transform2D trans = canvas->get_canvas_transform(); - Point2 target_position = (p_point - trans.get_origin()) / trans.get_scale().x - pos; - if (default_type == "Polygon2D" || default_type == "TouchScreenButton" || default_type == "TextureRect" || default_type == "NinePatchRect") { - target_position -= texture_size / 2; - } + // Compute the global position + Transform2D xform = canvas_item_editor->get_canvas_transform(); + Point2 target_position = xform.affine_inverse().xform(p_point); + // there's nothing to be used as source position so snapping will work as absolute if enabled - target_position = canvas->snap_point(target_position); - editor_data->get_undo_redo().add_do_method(child, "set_position", target_position); + target_position = canvas_item_editor->snap_point(target_position); + editor_data->get_undo_redo().add_do_method(child, "set_global_position", target_position); } bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, const Point2 &p_point) { @@ -4777,8 +5111,8 @@ bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, cons CanvasItem *parent_ci = Object::cast_to<CanvasItem>(parent); if (parent_ci) { - Vector2 target_pos = canvas->get_canvas_transform().affine_inverse().xform(p_point); - target_pos = canvas->snap_point(target_pos); + Vector2 target_pos = canvas_item_editor->get_canvas_transform().affine_inverse().xform(p_point); + target_pos = canvas_item_editor->snap_point(target_pos); target_pos = parent_ci->get_global_transform_with_canvas().affine_inverse().xform(target_pos); editor_data->get_undo_redo().add_do_method(instanced_scene, "set_position", target_pos); } @@ -4791,7 +5125,6 @@ void CanvasItemEditorViewport::_perform_drop_data() { // Without root dropping multiple files is not allowed if (!target_node && selected_files.size() > 1) { - accept->get_ok()->set_text(TTR("Ok")); accept->set_text(TTR("Cannot instantiate multiple nodes without root.")); accept->popup_centered_minsize(); return; @@ -4853,7 +5186,6 @@ void CanvasItemEditorViewport::_perform_drop_data() { files_str += error_files[i].get_file().get_basename() + ","; } files_str = files_str.substr(0, files_str.length() - 1); - accept->get_ok()->set_text(TTR("OK")); accept->set_text(vformat(TTR("Error instancing scene from %s"), files_str.c_str())); accept->popup_centered_minsize(); } @@ -4887,7 +5219,7 @@ bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Varian type == "AtlasTexture" || type == "LargeTexture") { Ref<Texture> texture = Ref<Texture>(Object::cast_to<Texture>(*res)); - if (texture.is_valid() == false) { + if (!texture.is_valid()) { continue; } } else { @@ -4900,7 +5232,7 @@ bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Varian if (!preview_node->get_parent()) { // create preview only once _create_preview(files); } - Transform2D trans = canvas->get_canvas_transform(); + Transform2D trans = canvas_item_editor->get_canvas_transform(); preview_node->set_position((p_point - trans.get_origin()) / trans.get_scale().x); label->set_text(vformat(TTR("Adding %s..."), default_type)); } @@ -4995,7 +5327,7 @@ void CanvasItemEditorViewport::_bind_methods() { ClassDB::bind_method(D_METHOD("_on_mouse_exit"), &CanvasItemEditorViewport::_on_mouse_exit); } -CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasItemEditor *p_canvas) { +CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasItemEditor *p_canvas_item_editor) { default_type = "Sprite"; // Node2D types.push_back("Sprite"); @@ -5010,7 +5342,7 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasIte target_node = NULL; editor = p_node; editor_data = editor->get_scene_tree_dock()->get_editor_data(); - canvas = p_canvas; + canvas_item_editor = p_canvas_item_editor; preview_node = memnew(Node2D); accept = memnew(AcceptDialog); diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 2c943385ad..207e57dbe2 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -64,25 +64,31 @@ public: Dictionary undo_state; - CanvasItemEditorSelectedItem() { prev_rot = 0; } + CanvasItemEditorSelectedItem() : + prev_anchors() { + prev_rot = 0; + } }; class CanvasItemEditor : public VBoxContainer { GDCLASS(CanvasItemEditor, VBoxContainer); - EditorNode *editor; - +public: enum Tool { TOOL_SELECT, TOOL_LIST_SELECT, TOOL_MOVE, + TOOL_SCALE, TOOL_ROTATE, TOOL_EDIT_PIVOT, TOOL_PAN, TOOL_MAX }; +private: + EditorNode *editor; + enum MenuOption { SNAP_USE, SNAP_USE_NODE_PARENT, @@ -102,6 +108,7 @@ class CanvasItemEditor : public VBoxContainer { SHOW_GUIDES, SHOW_ORIGIN, SHOW_VIEWPORT, + SHOW_EDIT_LOCKS, LOCK_SELECTED, UNLOCK_SELECTED, GROUP_SELECTED, @@ -188,7 +195,10 @@ class CanvasItemEditor : public VBoxContainer { DRAG_ANCHOR_BOTTOM_RIGHT, DRAG_ANCHOR_BOTTOM_LEFT, DRAG_ANCHOR_ALL, - DRAG_ALL, + DRAG_MOVE, + DRAG_SCALE_X, + DRAG_SCALE_Y, + DRAG_SCALE_BOTH, DRAG_ROTATE, DRAG_PIVOT, DRAG_V_GUIDE, @@ -213,6 +223,11 @@ class CanvasItemEditor : public VBoxContainer { ToolButton *zoom_reset; ToolButton *zoom_plus; + Map<Control *, Timer *> popup_temporarily_timers; + + Label *warning_child_of_container; + VBoxContainer *info_overlay; + Transform2D transform; bool show_grid; bool show_rulers; @@ -220,6 +235,7 @@ class CanvasItemEditor : public VBoxContainer { bool show_origin; bool show_viewport; bool show_helpers; + bool show_edit_locks; float zoom; Point2 view_offset; Point2 previous_update_view_offset; @@ -272,6 +288,10 @@ class CanvasItemEditor : public VBoxContainer { Transform2D xform; float length; uint64_t last_pass; + + BoneList() : + length(0.f), + last_pass(0) {} }; uint64_t bone_last_frame; @@ -298,17 +318,19 @@ class CanvasItemEditor : public VBoxContainer { List<PoseClipboard> pose_clipboard; ToolButton *select_button; - ToolButton *list_select_button; + ToolButton *move_button; + ToolButton *scale_button; ToolButton *rotate_button; + ToolButton *list_select_button; + ToolButton *pivot_button; + ToolButton *pan_button; + ToolButton *snap_button; MenuButton *snap_config_menu; PopupMenu *smartsnap_config_popup; - ToolButton *pivot_button; - ToolButton *pan_button; - ToolButton *lock_button; ToolButton *unlock_button; @@ -355,8 +377,10 @@ class CanvasItemEditor : public VBoxContainer { Ref<ShortCut> multiply_grid_step_shortcut; Ref<ShortCut> divide_grid_step_shortcut; - void _find_canvas_items_at_pos(const Point2 &p_pos, Node *p_node, Vector<_SelectResult> &r_items, int p_limit = 0, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D()); - void _get_canvas_items_at_pos(const Point2 &p_pos, Vector<_SelectResult> &r_items, int p_limit = 0); + bool _is_node_locked(const Node *p_node); + bool _is_node_movable(const Node *p_node, bool p_popup_warning = false); + void _find_canvas_items_at_pos(const Point2 &p_pos, Node *p_node, Vector<_SelectResult> &r_items, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D()); + void _get_canvas_items_at_pos(const Point2 &p_pos, Vector<_SelectResult> &r_items); void _get_bones_at_pos(const Point2 &p_pos, Vector<_SelectResult> &r_items); void _find_canvas_items_in_rect(const Rect2 &p_rect, Node *p_node, List<CanvasItem *> *r_items, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D()); @@ -368,7 +392,9 @@ class CanvasItemEditor : public VBoxContainer { void _add_canvas_item(CanvasItem *p_canvas_item); + void _save_canvas_item_ik_chain(const CanvasItem *p_canvas_item, List<float> *p_bones_length, List<Dictionary> *p_bones_state); void _save_canvas_item_state(List<CanvasItem *> p_canvas_items, bool save_bones = false); + void _restore_canvas_item_ik_chain(CanvasItem *p_canvas_item, const List<Dictionary> *p_bones_state); void _restore_canvas_item_state(List<CanvasItem *> p_canvas_items, bool restore_bones = false); void _commit_canvas_item_state(List<CanvasItem *> p_canvas_items, String action_name, bool commit_bones = false); @@ -408,6 +434,7 @@ class CanvasItemEditor : public VBoxContainer { void _draw_guides(); void _draw_focus(); void _draw_grid(); + void _draw_control_helpers(Control *control); void _draw_selection(); void _draw_axis(); void _draw_bones(); @@ -420,6 +447,7 @@ class CanvasItemEditor : public VBoxContainer { bool _gui_input_anchors(const Ref<InputEvent> &p_event); bool _gui_input_move(const Ref<InputEvent> &p_event); bool _gui_input_open_scene_on_double_click(const Ref<InputEvent> &p_event); + bool _gui_input_scale(const Ref<InputEvent> &p_event); bool _gui_input_pivot(const Ref<InputEvent> &p_event); bool _gui_input_resize(const Ref<InputEvent> &p_event); bool _gui_input_rotate(const Ref<InputEvent> &p_event); @@ -458,6 +486,9 @@ class CanvasItemEditor : public VBoxContainer { void _update_bone_list(); void _tree_changed(Node *); + void _popup_warning_temporarily(Control *p_control, const float p_duration); + void _popup_warning_depop(Control *p_control); + friend class CanvasItemEditorPlugin; protected: @@ -523,11 +554,18 @@ public: void add_control_to_menu_panel(Control *p_control); void remove_control_from_menu_panel(Control *p_control); + void add_control_to_info_overlay(Control *p_control); + void remove_control_from_info_overlay(Control *p_control); + HSplitContainer *get_palette_split(); VSplitContainer *get_bottom_split(); Control *get_viewport_control() { return viewport; } + void update_viewport(); + + Tool get_current_tool() { return tool; } + void set_undo_redo(UndoRedo *p_undo_redo) { undo_redo = p_undo_redo; } void edit(CanvasItem *p_canvas_item); @@ -570,7 +608,7 @@ class CanvasItemEditorViewport : public Control { EditorNode *editor; EditorData *editor_data; - CanvasItemEditor *canvas; + CanvasItemEditor *canvas_item_editor; Node2D *preview_node; AcceptDialog *accept; WindowDialog *selector; @@ -604,7 +642,7 @@ public: virtual bool can_drop_data(const Point2 &p_point, const Variant &p_data) const; virtual void drop_data(const Point2 &p_point, const Variant &p_data); - CanvasItemEditorViewport(EditorNode *p_node, CanvasItemEditor *p_canvas); + CanvasItemEditorViewport(EditorNode *p_node, CanvasItemEditor *p_canvas_item_editor); ~CanvasItemEditorViewport(); }; diff --git a/editor/plugins/collision_polygon_editor_plugin.cpp b/editor/plugins/collision_polygon_editor_plugin.cpp index 5109379add..805a7d3835 100644 --- a/editor/plugins/collision_polygon_editor_plugin.cpp +++ b/editor/plugins/collision_polygon_editor_plugin.cpp @@ -31,10 +31,10 @@ #include "collision_polygon_editor_plugin.h" #include "canvas_item_editor_plugin.h" +#include "core/os/file_access.h" +#include "core/os/input.h" +#include "core/os/keyboard.h" #include "editor/editor_settings.h" -#include "os/file_access.h" -#include "os/input.h" -#include "os/keyboard.h" #include "scene/3d/camera.h" #include "spatial_editor_plugin.h" diff --git a/editor/plugins/collision_shape_2d_editor_plugin.cpp b/editor/plugins/collision_shape_2d_editor_plugin.cpp index 9e052bb027..313ba1ee6b 100644 --- a/editor/plugins/collision_shape_2d_editor_plugin.cpp +++ b/editor/plugins/collision_shape_2d_editor_plugin.cpp @@ -129,7 +129,7 @@ void CollisionShape2DEditor::set_handle(int idx, Point2 &p_point) { capsule->set_height(parameter * 2 - capsule->get_radius() * 2); } - canvas_item_editor->get_viewport_control()->update(); + canvas_item_editor->update_viewport(); } } break; @@ -138,7 +138,7 @@ void CollisionShape2DEditor::set_handle(int idx, Point2 &p_point) { Ref<CircleShape2D> circle = node->get_shape(); circle->set_radius(p_point.length()); - canvas_item_editor->get_viewport_control()->update(); + canvas_item_editor->update_viewport(); } break; @@ -160,7 +160,7 @@ void CollisionShape2DEditor::set_handle(int idx, Point2 &p_point) { line->set_normal(p_point.normalized()); } - canvas_item_editor->get_viewport_control()->update(); + canvas_item_editor->update_viewport(); } } break; @@ -170,7 +170,7 @@ void CollisionShape2DEditor::set_handle(int idx, Point2 &p_point) { ray->set_length(Math::abs(p_point.y)); - canvas_item_editor->get_viewport_control()->update(); + canvas_item_editor->update_viewport(); } break; @@ -183,7 +183,7 @@ void CollisionShape2DEditor::set_handle(int idx, Point2 &p_point) { rect->set_extents(extents.abs()); - canvas_item_editor->get_viewport_control()->update(); + canvas_item_editor->update_viewport(); } } break; @@ -198,16 +198,16 @@ void CollisionShape2DEditor::set_handle(int idx, Point2 &p_point) { seg->set_b(p_point); } - canvas_item_editor->get_viewport_control()->update(); + canvas_item_editor->update_viewport(); } } break; } + node->get_shape()->_change_notify(); } void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) { - Control *c = canvas_item_editor->get_viewport_control(); undo_redo->create_action(TTR("Set Handle")); switch (shape_type) { @@ -216,14 +216,14 @@ void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) { if (idx == 0) { undo_redo->add_do_method(capsule.ptr(), "set_radius", capsule->get_radius()); - undo_redo->add_do_method(c, "update"); + undo_redo->add_do_method(canvas_item_editor, "update_viewport"); undo_redo->add_undo_method(capsule.ptr(), "set_radius", p_org); - undo_redo->add_do_method(c, "update"); + undo_redo->add_do_method(canvas_item_editor, "update_viewport"); } else if (idx == 1) { undo_redo->add_do_method(capsule.ptr(), "set_height", capsule->get_height()); - undo_redo->add_do_method(c, "update"); + undo_redo->add_do_method(canvas_item_editor, "update_viewport"); undo_redo->add_undo_method(capsule.ptr(), "set_height", p_org); - undo_redo->add_undo_method(c, "update"); + undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); } } break; @@ -232,9 +232,9 @@ void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) { Ref<CircleShape2D> circle = node->get_shape(); undo_redo->add_do_method(circle.ptr(), "set_radius", circle->get_radius()); - undo_redo->add_do_method(c, "update"); + undo_redo->add_do_method(canvas_item_editor, "update_viewport"); undo_redo->add_undo_method(circle.ptr(), "set_radius", p_org); - undo_redo->add_undo_method(c, "update"); + undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); } break; @@ -251,14 +251,14 @@ void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) { if (idx == 0) { undo_redo->add_do_method(line.ptr(), "set_d", line->get_d()); - undo_redo->add_do_method(c, "update"); + undo_redo->add_do_method(canvas_item_editor, "update_viewport"); undo_redo->add_undo_method(line.ptr(), "set_d", p_org); - undo_redo->add_undo_method(c, "update"); + undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); } else { undo_redo->add_do_method(line.ptr(), "set_normal", line->get_normal()); - undo_redo->add_do_method(c, "update"); + undo_redo->add_do_method(canvas_item_editor, "update_viewport"); undo_redo->add_undo_method(line.ptr(), "set_normal", p_org); - undo_redo->add_undo_method(c, "update"); + undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); } } break; @@ -267,9 +267,9 @@ void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) { Ref<RayShape2D> ray = node->get_shape(); undo_redo->add_do_method(ray.ptr(), "set_length", ray->get_length()); - undo_redo->add_do_method(c, "update"); + undo_redo->add_do_method(canvas_item_editor, "update_viewport"); undo_redo->add_undo_method(ray.ptr(), "set_length", p_org); - undo_redo->add_undo_method(c, "update"); + undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); } break; @@ -277,9 +277,9 @@ void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) { Ref<RectangleShape2D> rect = node->get_shape(); undo_redo->add_do_method(rect.ptr(), "set_extents", rect->get_extents()); - undo_redo->add_do_method(c, "update"); + undo_redo->add_do_method(canvas_item_editor, "update_viewport"); undo_redo->add_undo_method(rect.ptr(), "set_extents", p_org); - undo_redo->add_undo_method(c, "update"); + undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); } break; @@ -287,14 +287,14 @@ void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) { Ref<SegmentShape2D> seg = node->get_shape(); if (idx == 0) { undo_redo->add_do_method(seg.ptr(), "set_a", seg->get_a()); - undo_redo->add_do_method(c, "update"); + undo_redo->add_do_method(canvas_item_editor, "update_viewport"); undo_redo->add_undo_method(seg.ptr(), "set_a", p_org); - undo_redo->add_undo_method(c, "update"); + undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); } else if (idx == 1) { undo_redo->add_do_method(seg.ptr(), "set_b", seg->get_b()); - undo_redo->add_do_method(c, "update"); + undo_redo->add_do_method(canvas_item_editor, "update_viewport"); undo_redo->add_undo_method(seg.ptr(), "set_b", p_org); - undo_redo->add_undo_method(c, "update"); + undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); } } break; @@ -323,7 +323,6 @@ bool CollisionShape2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_e if (mb.is_valid()) { 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()))); if (mb->get_button_index() == BUTTON_LEFT) { if (mb->is_pressed()) { @@ -412,10 +411,10 @@ void CollisionShape2DEditor::_get_current_shape_type() { shape_type = -1; } - canvas_item_editor->get_viewport_control()->update(); + canvas_item_editor->update_viewport(); } -void CollisionShape2DEditor::forward_draw_over_viewport(Control *p_overlay) { +void CollisionShape2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { if (!node) { return; @@ -539,7 +538,7 @@ void CollisionShape2DEditor::edit(Node *p_node) { node = NULL; } - canvas_item_editor->get_viewport_control()->update(); + canvas_item_editor->update_viewport(); } void CollisionShape2DEditor::_bind_methods() { diff --git a/editor/plugins/collision_shape_2d_editor_plugin.h b/editor/plugins/collision_shape_2d_editor_plugin.h index 10784f1129..fb7b2acb0f 100644 --- a/editor/plugins/collision_shape_2d_editor_plugin.h +++ b/editor/plugins/collision_shape_2d_editor_plugin.h @@ -75,7 +75,7 @@ protected: public: bool forward_canvas_gui_input(const Ref<InputEvent> &p_event); - void forward_draw_over_viewport(Control *p_overlay); + void forward_canvas_draw_over_viewport(Control *p_overlay); void edit(Node *p_node); CollisionShape2DEditor(EditorNode *p_editor); @@ -89,7 +89,7 @@ class CollisionShape2DEditorPlugin : public EditorPlugin { public: virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return collision_shape_2d_editor->forward_canvas_gui_input(p_event); } - virtual void forward_draw_over_viewport(Control *p_overlay) { return collision_shape_2d_editor->forward_draw_over_viewport(p_overlay); } + virtual void forward_canvas_draw_over_viewport(Control *p_overlay) { return collision_shape_2d_editor->forward_canvas_draw_over_viewport(p_overlay); } virtual String get_name() const { return "CollisionShape2D"; } bool has_main_screen() const { return false; } diff --git a/editor/plugins/cpu_particles_editor_plugin.cpp b/editor/plugins/cpu_particles_editor_plugin.cpp index b32f927249..8d3ebc5052 100644 --- a/editor/plugins/cpu_particles_editor_plugin.cpp +++ b/editor/plugins/cpu_particles_editor_plugin.cpp @@ -1,4 +1,35 @@ +/*************************************************************************/ +/* cpu_particles_editor_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 "cpu_particles_editor_plugin.h" + #include "editor/plugins/spatial_editor_plugin.h" void CPUParticlesEditor::_node_removed(Node *p_node) { diff --git a/editor/plugins/cpu_particles_editor_plugin.h b/editor/plugins/cpu_particles_editor_plugin.h index f47d17104d..16fb0bab0c 100644 --- a/editor/plugins/cpu_particles_editor_plugin.h +++ b/editor/plugins/cpu_particles_editor_plugin.h @@ -1,3 +1,33 @@ +/*************************************************************************/ +/* cpu_particles_editor_plugin.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 CPU_PARTICLES_EDITOR_PLUGIN_H #define CPU_PARTICLES_EDITOR_PLUGIN_H diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp index f5bdf77973..ace3012c10 100644 --- a/editor/plugins/curve_editor_plugin.cpp +++ b/editor/plugins/curve_editor_plugin.cpp @@ -31,9 +31,9 @@ #include "curve_editor_plugin.h" #include "canvas_item_editor_plugin.h" -#include "core_string_names.h" -#include "os/input.h" -#include "os/keyboard.h" +#include "core/core_string_names.h" +#include "core/os/input.h" +#include "core/os/keyboard.h" CurveEditor::CurveEditor() { _selected_point = -1; @@ -205,13 +205,13 @@ void CurveEditor::on_gui_input(const Ref<InputEvent> &p_event) { curve.set_point_left_tangent(_selected_point, tangent); // Note: if a tangent is set to linear, it shouldn't be linked to the other - if (link && _selected_point != curve.get_point_count() - 1 && !curve.get_point_right_mode(_selected_point) != Curve::TANGENT_FREE) + if (link && _selected_point != (curve.get_point_count() - 1) && curve.get_point_right_mode(_selected_point) != Curve::TANGENT_LINEAR) curve.set_point_right_tangent(_selected_point, tangent); } else { curve.set_point_right_tangent(_selected_point, tangent); - if (link && _selected_point != 0 && !curve.get_point_left_mode(_selected_point) != Curve::TANGENT_FREE) + if (link && _selected_point != 0 && curve.get_point_left_mode(_selected_point) != Curve::TANGENT_LINEAR) curve.set_point_left_tangent(_selected_point, tangent); } } @@ -782,12 +782,13 @@ bool CurvePreviewGenerator::handles(const String &p_type) const { return p_type == "Curve"; } -Ref<Texture> CurvePreviewGenerator::generate(const Ref<Resource> &p_from) { +Ref<Texture> CurvePreviewGenerator::generate(const Ref<Resource> &p_from, const Size2 p_size) const { Ref<Curve> curve_ref = p_from; ERR_FAIL_COND_V(curve_ref.is_null(), Ref<Texture>()); Curve &curve = **curve_ref; + // FIXME: Should be ported to use p_size as done in b2633a97 int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); thumbnail_size *= EDSCALE; Ref<Image> img_ref; diff --git a/editor/plugins/curve_editor_plugin.h b/editor/plugins/curve_editor_plugin.h index 255f359ed2..fa0b92e353 100644 --- a/editor/plugins/curve_editor_plugin.h +++ b/editor/plugins/curve_editor_plugin.h @@ -131,14 +131,14 @@ class CurveEditorPlugin : public EditorPlugin { public: CurveEditorPlugin(EditorNode *p_node); - String get_name() const { return "Curve"; } + virtual String get_name() const { return "Curve"; } }; class CurvePreviewGenerator : public EditorResourcePreviewGenerator { GDCLASS(CurvePreviewGenerator, EditorResourcePreviewGenerator) public: - bool handles(const String &p_type) const; - Ref<Texture> generate(const Ref<Resource> &p_from); + virtual bool handles(const String &p_type) const; + virtual Ref<Texture> generate(const Ref<Resource> &p_from, const Size2 p_size) const; }; #endif // CURVE_EDITOR_PLUGIN_H diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index 9acbceec92..7f83865777 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -30,12 +30,12 @@ #include "editor_preview_plugins.h" +#include "core/io/file_access_memory.h" +#include "core/io/resource_loader.h" +#include "core/os/os.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" -#include "io/file_access_memory.h" -#include "io/resource_loader.h" -#include "os/os.h" #include "scene/resources/bit_mask.h" #include "scene/resources/dynamic_font.h" #include "scene/resources/material.h" @@ -78,7 +78,11 @@ bool EditorTexturePreviewPlugin::handles(const String &p_type) const { return ClassDB::is_parent_class(p_type, "Texture"); } -Ref<Texture> EditorTexturePreviewPlugin::generate(const RES &p_from) const { +bool EditorTexturePreviewPlugin::should_generate_small_preview() const { + return true; +} + +Ref<Texture> EditorTexturePreviewPlugin::generate(const RES &p_from, const Size2 p_size) const { Ref<Image> img; Ref<AtlasTexture> atex = p_from; @@ -100,8 +104,6 @@ Ref<Texture> EditorTexturePreviewPlugin::generate(const RES &p_from) const { img = img->duplicate(); img->clear_mipmaps(); - int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); - thumbnail_size *= EDSCALE; if (img->is_compressed()) { if (img->decompress() != OK) return Ref<Texture>(); @@ -109,22 +111,15 @@ Ref<Texture> EditorTexturePreviewPlugin::generate(const RES &p_from) const { img->convert(Image::FORMAT_RGBA8); } - int width, height; - if (img->get_width() > thumbnail_size && img->get_width() >= img->get_height()) { - - width = thumbnail_size; - height = img->get_height() * thumbnail_size / img->get_width(); - } else if (img->get_height() > thumbnail_size && img->get_height() >= img->get_width()) { - - height = thumbnail_size; - width = img->get_width() * thumbnail_size / img->get_height(); - } else { - - width = img->get_width(); - height = img->get_height(); + Vector2 new_size = img->get_size(); + if (new_size.x > p_size.x) { + new_size = Vector2(p_size.x, new_size.y * p_size.x / new_size.x); } + if (new_size.y > p_size.y) { + new_size = Vector2(new_size.x * p_size.y / new_size.y, p_size.y); + } + img->resize(new_size.x, new_size.y, Image::INTERPOLATE_CUBIC); - img->resize(width, height); post_process_preview(img); Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture)); @@ -143,7 +138,7 @@ bool EditorImagePreviewPlugin::handles(const String &p_type) const { return p_type == "Image"; } -Ref<Texture> EditorImagePreviewPlugin::generate(const RES &p_from) const { +Ref<Texture> EditorImagePreviewPlugin::generate(const RES &p_from, const Size2 p_size) const { Ref<Image> img = p_from; @@ -153,8 +148,6 @@ Ref<Texture> EditorImagePreviewPlugin::generate(const RES &p_from) const { img = img->duplicate(); img->clear_mipmaps(); - int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); - thumbnail_size *= EDSCALE; if (img->is_compressed()) { if (img->decompress() != OK) return Ref<Image>(); @@ -162,22 +155,15 @@ Ref<Texture> EditorImagePreviewPlugin::generate(const RES &p_from) const { img->convert(Image::FORMAT_RGBA8); } - int width, height; - if (img->get_width() > thumbnail_size && img->get_width() >= img->get_height()) { - - width = thumbnail_size; - height = img->get_height() * thumbnail_size / img->get_width(); - } else if (img->get_height() > thumbnail_size && img->get_height() >= img->get_width()) { - - height = thumbnail_size; - width = img->get_width() * thumbnail_size / img->get_height(); - } else { - - width = img->get_width(); - height = img->get_height(); + Vector2 new_size = img->get_size(); + if (new_size.x > p_size.x) { + new_size = Vector2(p_size.x, new_size.y * p_size.x / new_size.x); + } + if (new_size.y > p_size.y) { + new_size = Vector2(new_size.x * p_size.y / new_size.y, p_size.y); } + img->resize(new_size.x, new_size.y, Image::INTERPOLATE_CUBIC); - img->resize(width, height); post_process_preview(img); Ref<ImageTexture> ptex; @@ -190,6 +176,9 @@ Ref<Texture> EditorImagePreviewPlugin::generate(const RES &p_from) const { EditorImagePreviewPlugin::EditorImagePreviewPlugin() { } +bool EditorImagePreviewPlugin::should_generate_small_preview() const { + return true; +} //////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////// bool EditorBitmapPreviewPlugin::handles(const String &p_type) const { @@ -197,7 +186,7 @@ bool EditorBitmapPreviewPlugin::handles(const String &p_type) const { return ClassDB::is_parent_class(p_type, "BitMap"); } -Ref<Texture> EditorBitmapPreviewPlugin::generate(const RES &p_from) const { +Ref<Texture> EditorBitmapPreviewPlugin::generate(const RES &p_from, const Size2 p_size) const { Ref<BitMap> bm = p_from; @@ -227,8 +216,6 @@ Ref<Texture> EditorBitmapPreviewPlugin::generate(const RES &p_from) const { img.instance(); img->create(bm->get_size().width, bm->get_size().height, 0, Image::FORMAT_L8, data); - int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); - thumbnail_size *= EDSCALE; if (img->is_compressed()) { if (img->decompress() != OK) return Ref<Texture>(); @@ -236,22 +223,15 @@ Ref<Texture> EditorBitmapPreviewPlugin::generate(const RES &p_from) const { img->convert(Image::FORMAT_RGBA8); } - int width, height; - if (img->get_width() > thumbnail_size && img->get_width() >= img->get_height()) { - - width = thumbnail_size; - height = img->get_height() * thumbnail_size / img->get_width(); - } else if (img->get_height() > thumbnail_size && img->get_height() >= img->get_width()) { - - height = thumbnail_size; - width = img->get_width() * thumbnail_size / img->get_height(); - } else { - - width = img->get_width(); - height = img->get_height(); + Vector2 new_size = img->get_size(); + if (new_size.x > p_size.x) { + new_size = Vector2(p_size.x, new_size.y * p_size.x / new_size.x); + } + if (new_size.y > p_size.y) { + new_size = Vector2(new_size.x * p_size.y / new_size.y, p_size.y); } + img->resize(new_size.x, new_size.y, Image::INTERPOLATE_CUBIC); - img->resize(width, height); post_process_preview(img); Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture)); @@ -260,6 +240,10 @@ Ref<Texture> EditorBitmapPreviewPlugin::generate(const RES &p_from) const { return ptex; } +bool EditorBitmapPreviewPlugin::should_generate_small_preview() const { + return true; +} + EditorBitmapPreviewPlugin::EditorBitmapPreviewPlugin() { } @@ -269,12 +253,12 @@ bool EditorPackedScenePreviewPlugin::handles(const String &p_type) const { return ClassDB::is_parent_class(p_type, "PackedScene"); } -Ref<Texture> EditorPackedScenePreviewPlugin::generate(const RES &p_from) const { +Ref<Texture> EditorPackedScenePreviewPlugin::generate(const RES &p_from, const Size2 p_size) const { - return generate_from_path(p_from->get_path()); + return generate_from_path(p_from->get_path(), p_size); } -Ref<Texture> EditorPackedScenePreviewPlugin::generate_from_path(const String &p_path) const { +Ref<Texture> EditorPackedScenePreviewPlugin::generate_from_path(const String &p_path, const Size2 p_size) const { String temp_path = EditorSettings::get_singleton()->get_cache_dir(); String cache_base = ProjectSettings::get_singleton()->globalize_path(p_path).md5_text(); @@ -323,7 +307,11 @@ bool EditorMaterialPreviewPlugin::handles(const String &p_type) const { return ClassDB::is_parent_class(p_type, "Material"); //any material } -Ref<Texture> EditorMaterialPreviewPlugin::generate(const RES &p_from) const { +bool EditorMaterialPreviewPlugin::should_generate_small_preview() const { + return true; +} + +Ref<Texture> EditorMaterialPreviewPlugin::generate(const RES &p_from, const Size2 p_size) const { Ref<Material> material = p_from; ERR_FAIL_COND_V(material.is_null(), Ref<Texture>()); @@ -346,10 +334,9 @@ Ref<Texture> EditorMaterialPreviewPlugin::generate(const RES &p_from) const { ERR_FAIL_COND_V(!img.is_valid(), Ref<ImageTexture>()); - int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); - thumbnail_size *= EDSCALE; img->convert(Image::FORMAT_RGBA8); - img->resize(thumbnail_size, thumbnail_size); + int thumbnail_size = MAX(p_size.x, p_size.y); + img->resize(thumbnail_size, thumbnail_size, Image::INTERPOLATE_CUBIC); post_process_preview(img); Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture)); ptex->create_from_image(img, 0); @@ -490,7 +477,7 @@ bool EditorScriptPreviewPlugin::handles(const String &p_type) const { return ClassDB::is_parent_class(p_type, "Script"); } -Ref<Texture> EditorScriptPreviewPlugin::generate(const RES &p_from) const { +Ref<Texture> EditorScriptPreviewPlugin::generate(const RES &p_from, const Size2 p_size) const { Ref<Script> scr = p_from; if (scr.is_null()) @@ -512,10 +499,9 @@ Ref<Texture> EditorScriptPreviewPlugin::generate(const RES &p_from) const { int line = 0; int col = 0; - int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); - thumbnail_size *= EDSCALE; Ref<Image> img; img.instance(); + int thumbnail_size = MAX(p_size.x, p_size.y); img->create(thumbnail_size, thumbnail_size, 0, Image::FORMAT_RGBA8); Color bg_color = EditorSettings::get_singleton()->get("text_editor/highlighting/background_color"); @@ -613,16 +599,15 @@ bool EditorAudioStreamPreviewPlugin::handles(const String &p_type) const { return ClassDB::is_parent_class(p_type, "AudioStream"); } -Ref<Texture> EditorAudioStreamPreviewPlugin::generate(const RES &p_from) const { +Ref<Texture> EditorAudioStreamPreviewPlugin::generate(const RES &p_from, const Size2 p_size) const { Ref<AudioStream> stream = p_from; ERR_FAIL_COND_V(stream.is_null(), Ref<Texture>()); - int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); - thumbnail_size *= EDSCALE; PoolVector<uint8_t> img; - int w = thumbnail_size; - int h = thumbnail_size; + + int w = p_size.x; + int h = p_size.y; img.resize(w * h * 3); PoolVector<uint8_t>::Write imgdata = img.write(); @@ -711,7 +696,7 @@ bool EditorMeshPreviewPlugin::handles(const String &p_type) const { return ClassDB::is_parent_class(p_type, "Mesh"); //any Mesh } -Ref<Texture> EditorMeshPreviewPlugin::generate(const RES &p_from) const { +Ref<Texture> EditorMeshPreviewPlugin::generate(const RES &p_from, const Size2 p_size) const { Ref<Mesh> mesh = p_from; ERR_FAIL_COND_V(mesh.is_null(), Ref<Texture>()); @@ -749,10 +734,17 @@ Ref<Texture> EditorMeshPreviewPlugin::generate(const RES &p_from) const { VS::get_singleton()->instance_set_base(mesh_instance, RID()); - int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); - thumbnail_size *= EDSCALE; img->convert(Image::FORMAT_RGBA8); - img->resize(thumbnail_size, thumbnail_size); + + Vector2 new_size = img->get_size(); + if (new_size.x > p_size.x) { + new_size = Vector2(p_size.x, new_size.y * p_size.x / new_size.x); + } + if (new_size.y > p_size.y) { + new_size = Vector2(new_size.x * p_size.y / new_size.y, p_size.y); + } + img->resize(new_size.x, new_size.y, Image::INTERPOLATE_CUBIC); + post_process_preview(img); Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture)); @@ -825,15 +817,12 @@ bool EditorFontPreviewPlugin::handles(const String &p_type) const { return ClassDB::is_parent_class(p_type, "DynamicFontData"); } -Ref<Texture> EditorFontPreviewPlugin::generate_from_path(const String &p_path) const { +Ref<Texture> EditorFontPreviewPlugin::generate_from_path(const String &p_path, const Size2 p_size) const { Ref<DynamicFontData> SampledFont; SampledFont.instance(); SampledFont->set_font_path(p_path); - int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); - thumbnail_size *= EDSCALE; - Ref<DynamicFont> sampled_font; sampled_font.instance(); sampled_font->set_size(50); @@ -864,7 +853,15 @@ Ref<Texture> EditorFontPreviewPlugin::generate_from_path(const String &p_path) c ERR_FAIL_COND_V(img.is_null(), Ref<ImageTexture>()); img->convert(Image::FORMAT_RGBA8); - img->resize(thumbnail_size, thumbnail_size); + + Vector2 new_size = img->get_size(); + if (new_size.x > p_size.x) { + new_size = Vector2(p_size.x, new_size.y * p_size.x / new_size.x); + } + if (new_size.y > p_size.y) { + new_size = Vector2(new_size.x * p_size.y / new_size.y, p_size.y); + } + img->resize(new_size.x, new_size.y, Image::INTERPOLATE_CUBIC); post_process_preview(img); @@ -874,9 +871,9 @@ Ref<Texture> EditorFontPreviewPlugin::generate_from_path(const String &p_path) c return ptex; } -Ref<Texture> EditorFontPreviewPlugin::generate(const RES &p_from) const { +Ref<Texture> EditorFontPreviewPlugin::generate(const RES &p_from, const Size2 p_size) const { - return generate_from_path(p_from->get_path()); + return generate_from_path(p_from->get_path(), p_size); } EditorFontPreviewPlugin::EditorFontPreviewPlugin() { diff --git a/editor/plugins/editor_preview_plugins.h b/editor/plugins/editor_preview_plugins.h index 8bd7943383..ed5d2a3ecd 100644 --- a/editor/plugins/editor_preview_plugins.h +++ b/editor/plugins/editor_preview_plugins.h @@ -39,7 +39,8 @@ class EditorTexturePreviewPlugin : public EditorResourcePreviewGenerator { GDCLASS(EditorTexturePreviewPlugin, EditorResourcePreviewGenerator) public: virtual bool handles(const String &p_type) const; - virtual Ref<Texture> generate(const RES &p_from) const; + virtual bool should_generate_small_preview() const; + virtual Ref<Texture> generate(const RES &p_from, const Size2 p_size) const; EditorTexturePreviewPlugin(); }; @@ -48,7 +49,8 @@ class EditorImagePreviewPlugin : public EditorResourcePreviewGenerator { GDCLASS(EditorImagePreviewPlugin, EditorResourcePreviewGenerator) public: virtual bool handles(const String &p_type) const; - virtual Ref<Texture> generate(const RES &p_from) const; + virtual bool should_generate_small_preview() const; + virtual Ref<Texture> generate(const RES &p_from, const Size2 p_size) const; EditorImagePreviewPlugin(); }; @@ -57,7 +59,8 @@ class EditorBitmapPreviewPlugin : public EditorResourcePreviewGenerator { GDCLASS(EditorBitmapPreviewPlugin, EditorResourcePreviewGenerator) public: virtual bool handles(const String &p_type) const; - virtual Ref<Texture> generate(const RES &p_from) const; + virtual bool should_generate_small_preview() const; + virtual Ref<Texture> generate(const RES &p_from, const Size2 p_size) const; EditorBitmapPreviewPlugin(); }; @@ -66,8 +69,8 @@ class EditorPackedScenePreviewPlugin : public EditorResourcePreviewGenerator { public: virtual bool handles(const String &p_type) const; - virtual Ref<Texture> generate(const RES &p_from) const; - virtual Ref<Texture> generate_from_path(const String &p_path) const; + virtual Ref<Texture> generate(const RES &p_from, const Size2 p_size) const; + virtual Ref<Texture> generate_from_path(const String &p_path, const Size2 p_size) const; EditorPackedScenePreviewPlugin(); }; @@ -95,7 +98,8 @@ protected: public: virtual bool handles(const String &p_type) const; - virtual Ref<Texture> generate(const RES &p_from) const; + virtual bool should_generate_small_preview() const; + virtual Ref<Texture> generate(const RES &p_from, const Size2 p_size) const; EditorMaterialPreviewPlugin(); ~EditorMaterialPreviewPlugin(); @@ -104,7 +108,7 @@ public: class EditorScriptPreviewPlugin : public EditorResourcePreviewGenerator { public: virtual bool handles(const String &p_type) const; - virtual Ref<Texture> generate(const RES &p_from) const; + virtual Ref<Texture> generate(const RES &p_from, const Size2 p_size) const; EditorScriptPreviewPlugin(); }; @@ -112,7 +116,7 @@ public: class EditorAudioStreamPreviewPlugin : public EditorResourcePreviewGenerator { public: virtual bool handles(const String &p_type) const; - virtual Ref<Texture> generate(const RES &p_from) const; + virtual Ref<Texture> generate(const RES &p_from, const Size2 p_size) const; EditorAudioStreamPreviewPlugin(); }; @@ -139,7 +143,7 @@ protected: public: virtual bool handles(const String &p_type) const; - virtual Ref<Texture> generate(const RES &p_from) const; + virtual Ref<Texture> generate(const RES &p_from, const Size2 p_size) const; EditorMeshPreviewPlugin(); ~EditorMeshPreviewPlugin(); @@ -162,8 +166,8 @@ protected: public: virtual bool handles(const String &p_type) const; - virtual Ref<Texture> generate(const RES &p_from) const; - virtual Ref<Texture> generate_from_path(const String &p_path) const; + virtual Ref<Texture> generate(const RES &p_from, const Size2 p_size) const; + virtual Ref<Texture> generate_from_path(const String &p_path, const Size2 p_size) const; EditorFontPreviewPlugin(); ~EditorFontPreviewPlugin(); diff --git a/editor/plugins/gi_probe_editor_plugin.cpp b/editor/plugins/gi_probe_editor_plugin.cpp index 06da64b181..5fc5cad1ef 100644 --- a/editor/plugins/gi_probe_editor_plugin.cpp +++ b/editor/plugins/gi_probe_editor_plugin.cpp @@ -90,7 +90,7 @@ void GIProbeEditorPlugin::_bind_methods() { GIProbeEditorPlugin::GIProbeEditorPlugin(EditorNode *p_node) { editor = p_node; - bake = memnew(Button); + bake = memnew(ToolButton); bake->set_icon(editor->get_gui_base()->get_icon("Bake", "EditorIcons")); bake->set_text(TTR("Bake GI Probe")); bake->hide(); diff --git a/editor/plugins/gi_probe_editor_plugin.h b/editor/plugins/gi_probe_editor_plugin.h index 017e9bd743..1b3b63f227 100644 --- a/editor/plugins/gi_probe_editor_plugin.h +++ b/editor/plugins/gi_probe_editor_plugin.h @@ -42,7 +42,7 @@ class GIProbeEditorPlugin : public EditorPlugin { GIProbe *gi_probe; - Button *bake; + ToolButton *bake; EditorNode *editor; static EditorProgress *tmp_progress; diff --git a/editor/plugins/item_list_editor_plugin.cpp b/editor/plugins/item_list_editor_plugin.cpp index f75fb0d109..8df40232b0 100644 --- a/editor/plugins/item_list_editor_plugin.cpp +++ b/editor/plugins/item_list_editor_plugin.cpp @@ -30,7 +30,7 @@ #include "item_list_editor_plugin.h" -#include "io/resource_loader.h" +#include "core/io/resource_loader.h" bool ItemListPlugin::_set(const StringName &p_name, const Variant &p_value) { @@ -278,25 +278,27 @@ void ItemListEditor::_add_pressed() { void ItemListEditor::_delete_pressed() { - TreeItem *ti = tree->get_selected(); - - if (!ti) + if (selected_idx == -1) return; - if (ti->get_parent() != tree->get_root()) + String current_selected = (String)property_editor->get_selected_path(); + + if (current_selected == "") return; - int idx = ti->get_text(0).to_int(); + // FIXME: Currently relying on selecting a *property* to derive what item to delete + // e.g. you select "1/enabled" to delete item 1. + // This should be fixed so that you can delete by selecting the item section header, + // or a delete button on that header. - if (selected_idx == -1) - return; + int idx = current_selected.get_slice("/", 0).to_int(); item_plugins[selected_idx]->erase(idx); } void ItemListEditor::_edit_items() { - dialog->popup_centered(Vector2(300, 400)); + dialog->popup_centered(Vector2(300, 400) * EDSCALE); } void ItemListEditor::edit(Node *p_item_list) { @@ -315,10 +317,7 @@ void ItemListEditor::edit(Node *p_item_list) { item_plugins[i]->set_object(p_item_list); property_editor->edit(item_plugins[i]); - if (has_icon(item_list->get_class(), "EditorIcons")) - toolbar_button->set_icon(get_icon(item_list->get_class(), "EditorIcons")); - else - toolbar_button->set_icon(Ref<Texture>()); + toolbar_button->set_icon(EditorNode::get_singleton()->get_object_icon(item_list, "")); selected_idx = i; return; @@ -351,8 +350,6 @@ ItemListEditor::ItemListEditor() { selected_idx = -1; - add_child(memnew(VSeparator)); - toolbar_button = memnew(ToolButton); toolbar_button->set_text(TTR("Items")); add_child(toolbar_button); @@ -382,13 +379,9 @@ ItemListEditor::ItemListEditor() { hbc->add_child(del_button); del_button->connect("pressed", this, "_delete_button"); - property_editor = memnew(PropertyEditor); - property_editor->hide_top_label(); - property_editor->set_subsection_selectable(true); + property_editor = memnew(EditorInspector); vbc->add_child(property_editor); property_editor->set_v_size_flags(SIZE_EXPAND_FILL); - - tree = property_editor->get_property_tree(); } ItemListEditor::~ItemListEditor() { diff --git a/editor/plugins/item_list_editor_plugin.h b/editor/plugins/item_list_editor_plugin.h index d6a071b9b9..3dc3775f83 100644 --- a/editor/plugins/item_list_editor_plugin.h +++ b/editor/plugins/item_list_editor_plugin.h @@ -32,9 +32,9 @@ #define ITEM_LIST_EDITOR_PLUGIN_H #include "canvas_item_editor_plugin.h" +#include "editor/editor_inspector.h" #include "editor/editor_node.h" #include "editor/editor_plugin.h" - #include "scene/gui/menu_button.h" #include "scene/gui/option_button.h" #include "scene/gui/popup_menu.h" @@ -210,7 +210,7 @@ class ItemListEditor : public HBoxContainer { ToolButton *toolbar_button; AcceptDialog *dialog; - PropertyEditor *property_editor; + EditorInspector *property_editor; Tree *tree; Button *add_button; Button *del_button; diff --git a/editor/plugins/light_occluder_2d_editor_plugin.cpp b/editor/plugins/light_occluder_2d_editor_plugin.cpp index 3351e5918f..6a16cf0989 100644 --- a/editor/plugins/light_occluder_2d_editor_plugin.cpp +++ b/editor/plugins/light_occluder_2d_editor_plugin.cpp @@ -31,8 +31,8 @@ #include "light_occluder_2d_editor_plugin.h" #include "canvas_item_editor_plugin.h" +#include "core/os/file_access.h" #include "editor/editor_settings.h" -#include "os/file_access.h" void LightOccluder2DEditor::_notification(int p_what) { @@ -57,7 +57,7 @@ void LightOccluder2DEditor::_node_removed(Node *p_node) { if (p_node == node) { node = NULL; hide(); - canvas_item_editor->get_viewport_control()->update(); + canvas_item_editor->update_viewport(); } } @@ -88,8 +88,8 @@ void LightOccluder2DEditor::_wip_close(bool p_closed) { 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->get_viewport_control(), "update"); - undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update"); + 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; @@ -139,7 +139,7 @@ bool LightOccluder2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { wip.push_back(cpoint); wip_active = true; edited_point_pos = cpoint; - canvas_item_editor->get_viewport_control()->update(); + canvas_item_editor->update_viewport(); edited_point = 1; return true; } else { @@ -158,7 +158,7 @@ bool LightOccluder2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { wip.push_back(cpoint); edited_point = wip.size(); - canvas_item_editor->get_viewport_control()->update(); + canvas_item_editor->update_viewport(); return true; //add wip point @@ -183,8 +183,8 @@ bool LightOccluder2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { 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->get_viewport_control(), "update"); - undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update"); + 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; } @@ -217,7 +217,7 @@ bool LightOccluder2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { 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->get_viewport_control()->update(); + canvas_item_editor->update_viewport(); return true; } } else { @@ -244,7 +244,7 @@ bool LightOccluder2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { pre_move_edit = poly; edited_point = closest_idx; edited_point_pos = xform.affine_inverse().xform(closest_pos); - canvas_item_editor->get_viewport_control()->update(); + canvas_item_editor->update_viewport(); return true; } } @@ -259,8 +259,8 @@ bool LightOccluder2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { 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->get_viewport_control(), "update"); - undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update"); + 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; @@ -290,8 +290,8 @@ bool LightOccluder2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { 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->get_viewport_control(), "update"); - undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update"); + 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; } @@ -312,20 +312,18 @@ bool LightOccluder2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { 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(); + canvas_item_editor->update_viewport(); } } return false; } -void LightOccluder2DEditor::forward_draw_over_viewport(Control *p_overlay) { +void LightOccluder2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { if (!node || !node->get_occluder_polygon().is_valid()) return; - Control *vpc = canvas_item_editor->get_viewport_control(); - Vector<Vector2> poly; if (wip_active) @@ -353,9 +351,9 @@ void LightOccluder2DEditor::forward_draw_over_viewport(Control *p_overlay) { if (i == poly.size() - 1 && (!node->get_occluder_polygon()->is_closed() || wip_active)) { } else { - vpc->draw_line(point, next_point, col, 2); + p_overlay->draw_line(point, next_point, col, 2); } - vpc->draw_texture(handle, point - handle->get_size() * 0.5); + p_overlay->draw_texture(handle, point - handle->get_size() * 0.5); } } @@ -371,7 +369,7 @@ void LightOccluder2DEditor::edit(Node *p_collision_polygon) { wip.clear(); wip_active = false; edited_point = -1; - canvas_item_editor->get_viewport_control()->update(); + canvas_item_editor->update_viewport(); } else { node = NULL; } diff --git a/editor/plugins/light_occluder_2d_editor_plugin.h b/editor/plugins/light_occluder_2d_editor_plugin.h index 39de8b1020..a1962892ee 100644 --- a/editor/plugins/light_occluder_2d_editor_plugin.h +++ b/editor/plugins/light_occluder_2d_editor_plugin.h @@ -83,7 +83,7 @@ protected: public: Vector2 snap_point(const Vector2 &p_point) const; - void forward_draw_over_viewport(Control *p_overlay); + void forward_canvas_draw_over_viewport(Control *p_overlay); bool forward_gui_input(const Ref<InputEvent> &p_event); void edit(Node *p_collision_polygon); LightOccluder2DEditor(EditorNode *p_editor); @@ -98,7 +98,7 @@ class LightOccluder2DEditorPlugin : public EditorPlugin { public: virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return light_occluder_editor->forward_gui_input(p_event); } - virtual void forward_draw_over_viewport(Control *p_overlay) { return light_occluder_editor->forward_draw_over_viewport(p_overlay); } + 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; } diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp index f282d391ff..5e59a73061 100644 --- a/editor/plugins/material_editor_plugin.cpp +++ b/editor/plugins/material_editor_plugin.cpp @@ -28,397 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -// FIXME: Disabled as (according to reduz) users were complaining that it gets in the way -// Waiting for PropertyEditor rewrite (planned for 3.1) to be refactored. - #include "material_editor_plugin.h" -#include "scene/3d/particles.h" - -#if 0 - -#include "scene/main/viewport.h" - -void MaterialEditor::_gui_input(InputEvent p_event) { - - -} - -void MaterialEditor::_notification(int p_what) { - - if (p_what==NOTIFICATION_PHYSICS_PROCESS) { - - } - - - if (p_what==NOTIFICATION_READY) { - - //get_scene()->connect("node_removed",this,"_node_removed"); - - if (first_enter) { - //it's in propertyeditor so.. could be moved around - - light_1_switch->set_normal_texture(get_icon("MaterialPreviewLight1","EditorIcons")); - light_1_switch->set_pressed_texture(get_icon("MaterialPreviewLight1Off","EditorIcons")); - light_2_switch->set_normal_texture(get_icon("MaterialPreviewLight2","EditorIcons")); - light_2_switch->set_pressed_texture(get_icon("MaterialPreviewLight2Off","EditorIcons")); - - sphere_switch->set_normal_texture(get_icon("MaterialPreviewSphereOff","EditorIcons")); - sphere_switch->set_pressed_texture(get_icon("MaterialPreviewSphere","EditorIcons")); - box_switch->set_normal_texture(get_icon("MaterialPreviewCubeOff","EditorIcons")); - box_switch->set_pressed_texture(get_icon("MaterialPreviewCube","EditorIcons")); - - first_enter=false; - } - - } - - if (p_what==NOTIFICATION_DRAW) { - - - Ref<Texture> checkerboard = get_icon("Checkerboard","EditorIcons"); - Size2 size = get_size(); - - draw_texture_rect(checkerboard,Rect2(Point2(),size),true); - - } -} - - - -void MaterialEditor::edit(Ref<Material> p_material) { - - material=p_material; - - if (!material.is_null()) { - sphere_mesh->surface_set_material(0,material); - box_mesh->surface_set_material(0,material); - } else { - - hide(); - } - -} - - -void MaterialEditor::_button_pressed(Node* p_button) { - - if (p_button==light_1_switch) { - light1->set_enabled(!light_1_switch->is_pressed()); - } - - if (p_button==light_2_switch) { - light2->set_enabled(!light_2_switch->is_pressed()); - } - - if (p_button==box_switch) { - box_instance->show(); - sphere_instance->hide(); - box_switch->set_pressed(true); - sphere_switch->set_pressed(false); - } - - if (p_button==sphere_switch) { - box_instance->hide(); - sphere_instance->show(); - box_switch->set_pressed(false); - sphere_switch->set_pressed(true); - } - -} - -void MaterialEditor::_bind_methods() { - - ClassDB::bind_method(D_METHOD("_gui_input"),&MaterialEditor::_gui_input); - ClassDB::bind_method(D_METHOD("_button_pressed"),&MaterialEditor::_button_pressed); - -} - -MaterialEditor::MaterialEditor() { - - viewport = memnew( Viewport ); - Ref<World> world; - world.instance(); - viewport->set_world(world); //use own world - add_child(viewport); - viewport->set_disable_input(true); - - camera = memnew( Camera ); - camera->set_transform(Transform(Matrix3(),Vector3(0,0,3))); - camera->set_perspective(45,0.1,10); - viewport->add_child(camera); - - light1 = memnew( DirectionalLight ); - light1->set_transform(Transform().looking_at(Vector3(-1,-1,-1),Vector3(0,1,0))); - viewport->add_child(light1); - - light2 = memnew( DirectionalLight ); - light2->set_transform(Transform().looking_at(Vector3(0,1,0),Vector3(0,0,1))); - light2->set_color(Light::COLOR_DIFFUSE,Color(0.7,0.7,0.7)); - light2->set_color(Light::COLOR_SPECULAR,Color(0.7,0.7,0.7)); - viewport->add_child(light2); - - sphere_instance = memnew( MeshInstance ); - viewport->add_child(sphere_instance); - - box_instance = memnew( MeshInstance ); - viewport->add_child(box_instance); - - Transform box_xform; - box_xform.basis.rotate(Vector3(1,0,0),Math::deg2rad(25)); - box_xform.basis = box_xform.basis * Matrix3().rotated(Vector3(0,1,0),Math::deg2rad(25)); - box_xform.basis.scale(Vector3(0.8,0.8,0.8)); - box_instance->set_transform(box_xform); - - { - - sphere_mesh.instance(); - - - int lats=32; - int lons=32; - float radius=1.0; - - PoolVector<Vector3> vertices; - PoolVector<Vector3> normals; - PoolVector<Vector2> uvs; - PoolVector<float> tangents; - Matrix3 tt = Matrix3(Vector3(0,1,0),Math_PI*0.5); - - for(int i = 1; i <= lats; i++) { - double lat0 = Math_PI * (-0.5 + (double) (i - 1) / lats); - double z0 = Math::sin(lat0); - double zr0 = Math::cos(lat0); - - double lat1 = Math_PI * (-0.5 + (double) i / lats); - double z1 = Math::sin(lat1); - double zr1 = Math::cos(lat1); - - for(int j = lons; j >= 1; j--) { - - double lng0 = 2 * Math_PI * (double) (j - 1) / lons; - double x0 = Math::cos(lng0); - double y0 = Math::sin(lng0); - - double lng1 = 2 * Math_PI * (double) (j) / lons; - double x1 = Math::cos(lng1); - double y1 = Math::sin(lng1); - - - Vector3 v[4]={ - Vector3(x1 * zr0, z0, y1 *zr0), - Vector3(x1 * zr1, z1, y1 *zr1), - Vector3(x0 * zr1, z1, y0 *zr1), - Vector3(x0 * zr0, z0, y0 *zr0) - }; - -#define ADD_POINT(m_idx) \ - normals.push_back(v[m_idx]); \ - vertices.push_back(v[m_idx] * radius); \ - { \ - Vector2 uv(Math::atan2(v[m_idx].x, v[m_idx].z), Math::atan2(-v[m_idx].y, v[m_idx].z)); \ - uv /= Math_PI; \ - uv *= 4.0; \ - uv = uv * 0.5 + Vector2(0.5, 0.5); \ - uvs.push_back(uv); \ - } \ - { \ - Vector3 t = tt.xform(v[m_idx]); \ - tangents.push_back(t.x); \ - tangents.push_back(t.y); \ - tangents.push_back(t.z); \ - tangents.push_back(1.0); \ - } - - - - ADD_POINT(0); - ADD_POINT(1); - ADD_POINT(2); - - ADD_POINT(2); - ADD_POINT(3); - ADD_POINT(0); - } - } - - Array arr; - arr.resize(VS::ARRAY_MAX); - arr[VS::ARRAY_VERTEX]=vertices; - arr[VS::ARRAY_NORMAL]=normals; - arr[VS::ARRAY_TANGENT]=tangents; - arr[VS::ARRAY_TEX_UV]=uvs; - - sphere_mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES,arr); - - sphere_instance->set_mesh(sphere_mesh); - - } - { - - - box_mesh.instance(); - - PoolVector<Vector3> vertices; - PoolVector<Vector3> normals; - PoolVector<float> tangents; - PoolVector<Vector3> uvs; - - int vtx_idx=0; -#define ADD_VTX(m_idx) \ - ; \ - vertices.push_back(face_points[m_idx]); \ - normals.push_back(normal_points[m_idx]); \ - tangents.push_back(normal_points[m_idx][1]); \ - tangents.push_back(normal_points[m_idx][2]); \ - tangents.push_back(normal_points[m_idx][0]); \ - tangents.push_back(1.0); \ - uvs.push_back(Vector3(uv_points[m_idx * 2 + 0], uv_points[m_idx * 2 + 1], 0)); \ - vtx_idx++;\ - - for (int i=0;i<6;i++) { - - - Vector3 face_points[4]; - Vector3 normal_points[4]; - float uv_points[8]={0,0,0,1,1,1,1,0}; - - for (int j=0;j<4;j++) { - - float v[3]; - v[0]=1.0; - v[1]=1-2*((j>>1)&1); - v[2]=v[1]*(1-2*(j&1)); - - for (int k=0;k<3;k++) { - - if (i<3) - face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1); - else - face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1); - } - normal_points[j]=Vector3(); - normal_points[j][i%3]=(i>=3?-1:1); - } - - //tri 1 - ADD_VTX(0); - ADD_VTX(1); - ADD_VTX(2); - //tri 2 - ADD_VTX(2); - ADD_VTX(3); - ADD_VTX(0); - - } - - - - Array d; - d.resize(VS::ARRAY_MAX); - d[VisualServer::ARRAY_NORMAL]= normals ; - d[VisualServer::ARRAY_TANGENT]= tangents ; - d[VisualServer::ARRAY_TEX_UV]= uvs ; - d[VisualServer::ARRAY_VERTEX]= vertices ; - - PoolVector<int> indices; - indices.resize(vertices.size()); - for(int i=0;i<vertices.size();i++) - indices.set(i,i); - d[VisualServer::ARRAY_INDEX]=indices; - - box_mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES,d); - box_instance->set_mesh(box_mesh); - box_instance->hide(); - - - - } - - set_custom_minimum_size(Size2(1,150)*EDSCALE); - - HBoxContainer *hb = memnew( HBoxContainer ); - add_child(hb); - hb->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 2); - - VBoxContainer *vb_shape = memnew( VBoxContainer ); - hb->add_child(vb_shape); - - sphere_switch = memnew( TextureButton ); - sphere_switch->set_toggle_mode(true); - sphere_switch->set_pressed(true); - vb_shape->add_child(sphere_switch); - sphere_switch->connect("pressed",this,"_button_pressed",varray(sphere_switch)); - - box_switch = memnew( TextureButton ); - box_switch->set_toggle_mode(true); - box_switch->set_pressed(false); - vb_shape->add_child(box_switch); - box_switch->connect("pressed",this,"_button_pressed",varray(box_switch)); - - hb->add_spacer(); - - VBoxContainer *vb_light = memnew( VBoxContainer ); - hb->add_child(vb_light); - - light_1_switch = memnew( TextureButton ); - light_1_switch->set_toggle_mode(true); - vb_light->add_child(light_1_switch); - light_1_switch->connect("pressed",this,"_button_pressed",varray(light_1_switch)); - - light_2_switch = memnew( TextureButton ); - light_2_switch->set_toggle_mode(true); - vb_light->add_child(light_2_switch); - light_2_switch->connect("pressed",this,"_button_pressed",varray(light_2_switch)); - - first_enter=true; - -} - - -void MaterialEditorPlugin::edit(Object *p_object) { - - Material * s = Object::cast_to<Material>(p_object); - if (!s) - return; - - material_editor->edit(Ref<Material>(s)); -} - -bool MaterialEditorPlugin::handles(Object *p_object) const { - - return p_object->is_type("Material"); -} - -void MaterialEditorPlugin::make_visible(bool p_visible) { - - if (p_visible) { - material_editor->show(); - //material_editor->set_process(true); - } else { - - material_editor->hide(); - //material_editor->set_process(false); - } - -} - -MaterialEditorPlugin::MaterialEditorPlugin(EditorNode *p_node) { - - editor=p_node; - material_editor = memnew( MaterialEditor ); - add_control_to_container(CONTAINER_PROPERTY_EDITOR_BOTTOM,material_editor); - material_editor->hide(); - - - -} - - -MaterialEditorPlugin::~MaterialEditorPlugin() -{ -} -#endif +#include "scene/resources/particles_material.h" String SpatialMaterialConversionPlugin::converts_to() const { diff --git a/editor/plugins/material_editor_plugin.h b/editor/plugins/material_editor_plugin.h index 31a927d83f..c06d95e700 100644 --- a/editor/plugins/material_editor_plugin.h +++ b/editor/plugins/material_editor_plugin.h @@ -32,77 +32,6 @@ #define MATERIAL_EDITOR_PLUGIN_H #include "editor/property_editor.h" -// FIXME: Disabled as (according to reduz) users were complaining that it gets in the way -// Waiting for PropertyEditor rewrite (planned for 3.1) to be refactored. -#if 0 - -#include "editor/editor_node.h" -#include "editor/editor_plugin.h" -#include "scene/3d/camera.h" -#include "scene/3d/light.h" -#include "scene/3d/mesh_instance.h" -#include "scene/resources/material.h" - -class MaterialEditor : public Control { - - GDCLASS(MaterialEditor, Control); - - - Viewport *viewport; - MeshInstance *sphere_instance; - MeshInstance *box_instance; - DirectionalLight *light1; - DirectionalLight *light2; - Camera *camera; - - Ref<Mesh> sphere_mesh; - Ref<Mesh> box_mesh; - - TextureButton *sphere_switch; - TextureButton *box_switch; - - TextureButton *light_1_switch; - TextureButton *light_2_switch; - - - Ref<Material> material; - - - void _button_pressed(Node* p_button); - bool first_enter; - -protected: - void _notification(int p_what); - void _gui_input(InputEvent p_event); - static void _bind_methods(); -public: - - void edit(Ref<Material> p_material); - MaterialEditor(); -}; - - -class MaterialEditorPlugin : public EditorPlugin { - - GDCLASS( MaterialEditorPlugin, EditorPlugin ); - - MaterialEditor *material_editor; - EditorNode *editor; - -public: - - virtual String get_name() const { return "Material"; } - bool has_main_screen() const { return false; } - virtual void edit(Object *p_node); - virtual bool handles(Object *p_node) const; - virtual void make_visible(bool p_visible); - - MaterialEditorPlugin(EditorNode *p_node); - ~MaterialEditorPlugin(); - -}; - -#endif class SpatialMaterialConversionPlugin : public EditorResourceConversionPlugin { GDCLASS(SpatialMaterialConversionPlugin, EditorResourceConversionPlugin) diff --git a/editor/plugins/mesh_editor_plugin.cpp b/editor/plugins/mesh_editor_plugin.cpp index 7b7e23531a..73a216e96f 100644 --- a/editor/plugins/mesh_editor_plugin.cpp +++ b/editor/plugins/mesh_editor_plugin.cpp @@ -65,14 +65,6 @@ void MeshEditor::_notification(int p_what) { first_enter = false; } } - - if (p_what == NOTIFICATION_DRAW) { - - Ref<Texture> checkerboard = get_icon("Checkerboard", "EditorIcons"); - Size2 size = get_size(); - - //draw_texture_rect(checkerboard, Rect2(Point2(), size), true); - } } void MeshEditor::_update_rotation() { diff --git a/editor/plugins/particles_2d_editor_plugin.cpp b/editor/plugins/particles_2d_editor_plugin.cpp index ae5d510502..ab94258c44 100644 --- a/editor/plugins/particles_2d_editor_plugin.cpp +++ b/editor/plugins/particles_2d_editor_plugin.cpp @@ -31,9 +31,10 @@ #include "particles_2d_editor_plugin.h" #include "canvas_item_editor_plugin.h" -#include "io/image_loader.h" -#include "scene/3d/particles.h" +#include "core/io/image_loader.h" +#include "scene/2d/cpu_particles_2d.h" #include "scene/gui/separator.h" +#include "scene/resources/particles_material.h" void Particles2DEditorPlugin::edit(Object *p_object) { @@ -82,6 +83,25 @@ void Particles2DEditorPlugin::_menu_callback(int p_idx) { emission_mask->popup_centered_minsize(); } break; + case MENU_OPTION_CONVERT_TO_CPU_PARTICLES: { + + UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo(); + + CPUParticles2D *cpu_particles = memnew(CPUParticles2D); + cpu_particles->convert_from_particles(particles); + cpu_particles->set_name(particles->get_name()); + cpu_particles->set_transform(particles->get_transform()); + cpu_particles->set_visible(particles->is_visible()); + cpu_particles->set_pause_mode(particles->get_pause_mode()); + + undo_redo->create_action("Replace Particles by CPUParticles"); + undo_redo->add_do_method(particles, "replace_by", cpu_particles); + undo_redo->add_undo_method(cpu_particles, "replace_by", particles); + undo_redo->add_do_reference(cpu_particles); + undo_redo->add_undo_reference(particles); + undo_redo->commit_action(); + + } break; } } @@ -355,6 +375,8 @@ Particles2DEditorPlugin::Particles2DEditorPlugin(EditorNode *p_node) { menu->get_popup()->add_separator(); menu->get_popup()->add_item(TTR("Load Emission Mask"), MENU_LOAD_EMISSION_MASK); // menu->get_popup()->add_item(TTR("Clear Emission Mask"), MENU_CLEAR_EMISSION_MASK); + menu->get_popup()->add_separator(); + menu->get_popup()->add_item(TTR("Convert to CPUParticles"), MENU_OPTION_CONVERT_TO_CPU_PARTICLES); menu->set_text(TTR("Particles")); toolbar->add_child(menu); diff --git a/editor/plugins/particles_2d_editor_plugin.h b/editor/plugins/particles_2d_editor_plugin.h index 2b6123141b..eaa96d84e9 100644 --- a/editor/plugins/particles_2d_editor_plugin.h +++ b/editor/plugins/particles_2d_editor_plugin.h @@ -34,7 +34,6 @@ #include "editor/editor_node.h" #include "editor/editor_plugin.h" #include "scene/2d/collision_polygon_2d.h" - #include "scene/2d/particles_2d.h" #include "scene/gui/box_container.h" #include "scene/gui/file_dialog.h" @@ -47,7 +46,8 @@ class Particles2DEditorPlugin : public EditorPlugin { MENU_GENERATE_VISIBILITY_RECT, MENU_LOAD_EMISSION_MASK, - MENU_CLEAR_EMISSION_MASK + MENU_CLEAR_EMISSION_MASK, + MENU_OPTION_CONVERT_TO_CPU_PARTICLES }; enum EmissionMode { diff --git a/editor/plugins/particles_editor_plugin.cpp b/editor/plugins/particles_editor_plugin.cpp index 3c381158a4..f2dfae7a9f 100644 --- a/editor/plugins/particles_editor_plugin.cpp +++ b/editor/plugins/particles_editor_plugin.cpp @@ -29,9 +29,12 @@ /*************************************************************************/ #include "particles_editor_plugin.h" + +#include "core/io/resource_loader.h" #include "editor/plugins/spatial_editor_plugin.h" -#include "io/resource_loader.h" #include "scene/3d/cpu_particles.h" +#include "scene/resources/particles_material.h" + bool ParticlesEditorBase::_generate(PoolVector<Vector3> &points, PoolVector<Vector3> &normals) { bool use_normals = emission_fill->get_selected() == 1; @@ -450,6 +453,7 @@ void ParticlesEditor::_bind_methods() { ParticlesEditor::ParticlesEditor() { + node = NULL; particles_editor_hb = memnew(HBoxContainer); SpatialEditor::get_singleton()->add_control_to_menu_panel(particles_editor_hb); options = memnew(MenuButton); diff --git a/editor/plugins/particles_editor_plugin.h b/editor/plugins/particles_editor_plugin.h index 622ce6e8a9..830d30d98f 100644 --- a/editor/plugins/particles_editor_plugin.h +++ b/editor/plugins/particles_editor_plugin.h @@ -43,6 +43,7 @@ class ParticlesEditorBase : public Control { GDCLASS(ParticlesEditorBase, Control) + protected: Spatial *base_node; Panel *panel; diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp index 33e182faef..c67c96798a 100644 --- a/editor/plugins/path_2d_editor_plugin.cpp +++ b/editor/plugins/path_2d_editor_plugin.cpp @@ -31,9 +31,9 @@ #include "path_2d_editor_plugin.h" #include "canvas_item_editor_plugin.h" +#include "core/os/file_access.h" +#include "core/os/keyboard.h" #include "editor/editor_settings.h" -#include "os/file_access.h" -#include "os/keyboard.h" void Path2DEditor::_notification(int p_what) { @@ -130,8 +130,8 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { undo_redo->create_action(TTR("Remove Point from Curve")); undo_redo->add_do_method(curve.ptr(), "remove_point", i); undo_redo->add_undo_method(curve.ptr(), "add_point", curve->get_point_position(i), curve->get_point_in(i), curve->get_point_out(i), i); - 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->add_do_method(canvas_item_editor, "update_viewport"); + undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); undo_redo->commit_action(); return true; } else if (dist_to_p_out < grab_threshold) { @@ -139,8 +139,8 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { undo_redo->create_action(TTR("Remove Out-Control from Curve")); undo_redo->add_do_method(curve.ptr(), "set_point_out", i, Vector2()); undo_redo->add_undo_method(curve.ptr(), "set_point_out", i, curve->get_point_out(i)); - 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->add_do_method(canvas_item_editor, "update_viewport"); + undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); undo_redo->commit_action(); return true; } else if (dist_to_p_in < grab_threshold) { @@ -148,8 +148,8 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { undo_redo->create_action(TTR("Remove In-Control from Curve")); undo_redo->add_do_method(curve.ptr(), "set_point_in", i, Vector2()); undo_redo->add_undo_method(curve.ptr(), "set_point_in", i, curve->get_point_in(i)); - 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->add_do_method(canvas_item_editor, "update_viewport"); + undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); undo_redo->commit_action(); return true; } @@ -165,8 +165,8 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { undo_redo->create_action(TTR("Add Point to Curve")); undo_redo->add_do_method(curve.ptr(), "add_point", cpoint); undo_redo->add_undo_method(curve.ptr(), "remove_point", curve->get_point_count()); - 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->add_do_method(canvas_item_editor, "update_viewport"); + undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); undo_redo->commit_action(); action = ACTION_MOVING_POINT; @@ -174,7 +174,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { moving_from = curve->get_point_position(action_point); moving_screen_from = gpoint; - canvas_item_editor->get_viewport_control()->update(); + canvas_item_editor->update_viewport(); return true; } @@ -196,8 +196,8 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { undo_redo->create_action(TTR("Move Point in Curve")); undo_redo->add_do_method(curve.ptr(), "set_point_position", action_point, cpoint); undo_redo->add_undo_method(curve.ptr(), "set_point_position", action_point, moving_from); - 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->add_do_method(canvas_item_editor, "update_viewport"); + undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); undo_redo->commit_action(); } break; @@ -212,8 +212,8 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { undo_redo->add_do_method(curve.ptr(), "set_point_out", action_point, mirror_handle_length ? -new_pos : (-new_pos.normalized() * orig_out_length)); undo_redo->add_undo_method(curve.ptr(), "set_point_out", action_point, mirror_handle_length ? -moving_from : (-moving_from.normalized() * orig_out_length)); } - 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->add_do_method(canvas_item_editor, "update_viewport"); + undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); undo_redo->commit_action(); } break; @@ -228,8 +228,8 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { undo_redo->add_do_method(curve.ptr(), "set_point_in", action_point, mirror_handle_length ? -new_pos : (-new_pos.normalized() * orig_in_length)); undo_redo->add_undo_method(curve.ptr(), "set_point_in", action_point, mirror_handle_length ? -moving_from : (-moving_from.normalized() * orig_in_length)); } - 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->add_do_method(canvas_item_editor, "update_viewport"); + undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); undo_redo->commit_action(); } break; @@ -280,7 +280,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { } break; } - canvas_item_editor->get_viewport_control()->update(); + canvas_item_editor->update_viewport(); return true; } } @@ -288,7 +288,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { return false; } -void Path2DEditor::forward_draw_over_viewport(Control *p_overlay) { +void Path2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { if (!node) return; @@ -331,7 +331,7 @@ void Path2DEditor::_node_visibility_changed() { if (!node) return; - canvas_item_editor->get_viewport_control()->update(); + canvas_item_editor->update_viewport(); } void Path2DEditor::edit(Node *p_path2d) { @@ -406,8 +406,8 @@ void Path2DEditor::_mode_selected(int p_mode) { undo_redo->create_action(TTR("Remove Point from Curve")); undo_redo->add_do_method(node->get_curve().ptr(), "add_point", begin); undo_redo->add_undo_method(node->get_curve().ptr(), "remove_point", node->get_curve()->get_point_count()); - 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->add_do_method(canvas_item_editor, "update_viewport"); + undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); undo_redo->commit_action(); return; } diff --git a/editor/plugins/path_2d_editor_plugin.h b/editor/plugins/path_2d_editor_plugin.h index 1e3955f84f..3a78657746 100644 --- a/editor/plugins/path_2d_editor_plugin.h +++ b/editor/plugins/path_2d_editor_plugin.h @@ -107,7 +107,7 @@ protected: public: bool forward_gui_input(const Ref<InputEvent> &p_event); - void forward_draw_over_viewport(Control *p_overlay); + void forward_canvas_draw_over_viewport(Control *p_overlay); void edit(Node *p_path2d); Path2DEditor(EditorNode *p_editor); }; @@ -121,7 +121,7 @@ class Path2DEditorPlugin : public EditorPlugin { public: virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return path2d_editor->forward_gui_input(p_event); } - virtual void forward_draw_over_viewport(Control *p_overlay) { return path2d_editor->forward_draw_over_viewport(p_overlay); } + virtual void forward_canvas_draw_over_viewport(Control *p_overlay) { return path2d_editor->forward_canvas_draw_over_viewport(p_overlay); } virtual String get_name() const { return "Path2D"; } bool has_main_screen() const { return false; } diff --git a/editor/plugins/path_editor_plugin.cpp b/editor/plugins/path_editor_plugin.cpp index 618c70d1a1..df6c40ed02 100644 --- a/editor/plugins/path_editor_plugin.cpp +++ b/editor/plugins/path_editor_plugin.cpp @@ -30,7 +30,7 @@ #include "path_editor_plugin.h" -#include "os/keyboard.h" +#include "core/os/keyboard.h" #include "scene/resources/curve.h" #include "spatial_editor_plugin.h" @@ -57,7 +57,7 @@ String PathSpatialGizmo::get_handle_name(int p_idx) const { return n; } -Variant PathSpatialGizmo::get_handle_value(int p_idx) const { +Variant PathSpatialGizmo::get_handle_value(int p_idx) { Ref<Curve3D> c = path->get_curve(); if (c.is_null()) @@ -215,8 +215,8 @@ void PathSpatialGizmo::redraw() { clear(); - Ref<SpatialMaterial> path_material = gizmo_plugin->get_material("path_material"); - Ref<SpatialMaterial> path_thin_material = gizmo_plugin->get_material("path_thin_material"); + Ref<SpatialMaterial> path_material = gizmo_plugin->get_material("path_material", this); + Ref<SpatialMaterial> path_thin_material = gizmo_plugin->get_material("path_thin_material", this); Ref<SpatialMaterial> handles_material = gizmo_plugin->get_material("handles"); Ref<Curve3D> c = path->get_curve(); @@ -641,24 +641,8 @@ String PathSpatialGizmoPlugin::get_name() const { PathSpatialGizmoPlugin::PathSpatialGizmoPlugin() { Color path_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/path", Color(0.5, 0.5, 1.0, 0.8)); - - Ref<SpatialMaterial> path_material = Ref<SpatialMaterial>(memnew(SpatialMaterial)); - path_color.a = 0.8; - path_material->set_albedo(path_color); - path_material->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); - path_material->set_line_width(3); - path_material->set_cull_mode(SpatialMaterial::CULL_DISABLED); - path_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true); - - Ref<SpatialMaterial> path_thin_material = Ref<SpatialMaterial>(memnew(SpatialMaterial)); + create_material("path_material", path_color); path_color.a = 0.4; - path_thin_material->set_albedo(path_color); - path_thin_material->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); - path_thin_material->set_line_width(1); - path_thin_material->set_cull_mode(SpatialMaterial::CULL_DISABLED); - path_thin_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true); - - add_material("path_material", path_material); - add_material("path_thin_material", path_thin_material); + create_material("path_thin_material", path_color); create_handle_material("handles"); } diff --git a/editor/plugins/path_editor_plugin.h b/editor/plugins/path_editor_plugin.h index 61f309e794..c77b2a41cc 100644 --- a/editor/plugins/path_editor_plugin.h +++ b/editor/plugins/path_editor_plugin.h @@ -45,7 +45,7 @@ class PathSpatialGizmo : public EditorSpatialGizmo { public: virtual String get_handle_name(int p_idx) const; - virtual Variant get_handle_value(int p_idx) const; + virtual Variant get_handle_value(int p_idx); virtual void set_handle(int p_idx, Camera *p_camera, const Point2 &p_point); virtual void commit_handle(int p_idx, const Variant &p_restore, bool p_cancel = false); diff --git a/editor/plugins/physical_bone_plugin.cpp b/editor/plugins/physical_bone_plugin.cpp index 42f1adcadf..6341d7f2ef 100644 --- a/editor/plugins/physical_bone_plugin.cpp +++ b/editor/plugins/physical_bone_plugin.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -69,15 +69,7 @@ PhysicalBoneEditor::PhysicalBoneEditor(EditorNode *p_editor) : hide(); } -PhysicalBoneEditor::~PhysicalBoneEditor() { - // TODO the spatial_editor_hb should be removed from SpatialEditor, but in this moment it's not possible - for (int i = spatial_editor_hb->get_child_count() - 1; 0 <= i; --i) { - Node *n = spatial_editor_hb->get_child(i); - spatial_editor_hb->remove_child(n); - memdelete(n); - } - memdelete(spatial_editor_hb); -} +PhysicalBoneEditor::~PhysicalBoneEditor() {} void PhysicalBoneEditor::set_selected(PhysicalBone *p_pb) { @@ -98,19 +90,17 @@ void PhysicalBoneEditor::show() { PhysicalBonePlugin::PhysicalBonePlugin(EditorNode *p_editor) : editor(p_editor), - selected(NULL) { - - physical_bone_editor = memnew(PhysicalBoneEditor(editor)); -} + selected(NULL), + physical_bone_editor(editor) {} void PhysicalBonePlugin::make_visible(bool p_visible) { if (p_visible) { - physical_bone_editor->show(); + physical_bone_editor.show(); } else { - physical_bone_editor->hide(); - physical_bone_editor->set_selected(NULL); + physical_bone_editor.hide(); + physical_bone_editor.set_selected(NULL); selected = NULL; } } @@ -119,5 +109,5 @@ void PhysicalBonePlugin::edit(Object *p_node) { selected = static_cast<PhysicalBone *>(p_node); // Trust it ERR_FAIL_COND(!selected); - physical_bone_editor->set_selected(selected); + physical_bone_editor.set_selected(selected); } diff --git a/editor/plugins/physical_bone_plugin.h b/editor/plugins/physical_bone_plugin.h index 9e7a50307a..e1f8c9ec47 100644 --- a/editor/plugins/physical_bone_plugin.h +++ b/editor/plugins/physical_bone_plugin.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -64,7 +64,7 @@ class PhysicalBonePlugin : public EditorPlugin { EditorNode *editor; PhysicalBone *selected; - PhysicalBoneEditor *physical_bone_editor; + PhysicalBoneEditor physical_bone_editor; public: virtual String get_name() const { return "PhysicalBone"; } diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index a437cd5362..f937744d45 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -31,10 +31,10 @@ #include "polygon_2d_editor_plugin.h" #include "canvas_item_editor_plugin.h" +#include "core/os/file_access.h" +#include "core/os/input.h" +#include "core/os/keyboard.h" #include "editor/editor_settings.h" -#include "os/file_access.h" -#include "os/input.h" -#include "os/keyboard.h" #include "scene/2d/skeleton_2d.h" Node2D *Polygon2DEditor::_get_node() const { @@ -767,6 +767,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { node->set_polygon(uv_new); } } break; + default: {} } if (bone_painting) { diff --git a/editor/plugins/resource_preloader_editor_plugin.cpp b/editor/plugins/resource_preloader_editor_plugin.cpp index c6e8ec1a2b..bd4a35c9d8 100644 --- a/editor/plugins/resource_preloader_editor_plugin.cpp +++ b/editor/plugins/resource_preloader_editor_plugin.cpp @@ -30,9 +30,9 @@ #include "resource_preloader_editor_plugin.h" +#include "core/io/resource_loader.h" +#include "core/project_settings.h" #include "editor/editor_settings.h" -#include "io/resource_loader.h" -#include "project_settings.h" void ResourcePreloaderEditor::_gui_input(Ref<InputEvent> p_event) { } @@ -44,7 +44,6 @@ void ResourcePreloaderEditor::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { load->set_icon(get_icon("Folder", "EditorIcons")); - _delete->set_icon(get_icon("Remove", "EditorIcons")); } if (p_what == NOTIFICATION_READY) { @@ -138,15 +137,11 @@ void ResourcePreloaderEditor::_item_edited() { } } -void ResourcePreloaderEditor::_delete_confirm_pressed() { +void ResourcePreloaderEditor::_remove_resource(const String &p_to_remove) { - if (!tree->get_selected()) - return; - - String to_remove = tree->get_selected()->get_text(0); undo_redo->create_action(TTR("Delete Resource")); - undo_redo->add_do_method(preloader, "remove_resource", to_remove); - undo_redo->add_undo_method(preloader, "add_resource", to_remove, preloader->get_resource(to_remove)); + undo_redo->add_do_method(preloader, "remove_resource", p_to_remove); + undo_redo->add_undo_method(preloader, "add_resource", p_to_remove, preloader->get_resource(p_to_remove)); undo_redo->add_do_method(this, "_update_library"); undo_redo->add_undo_method(this, "_update_library"); undo_redo->commit_action(); @@ -184,21 +179,6 @@ void ResourcePreloaderEditor::_paste_pressed() { undo_redo->commit_action(); } -void ResourcePreloaderEditor::_delete_pressed() { - - if (!tree->get_selected()) - return; - - _delete_confirm_pressed(); //it has undo.. why bother with a dialog.. - /* - dialog->set_title("Confirm..."); - dialog->set_text("Remove Resource '"+tree->get_selected()->get_text(0)+"' ?"); - //dialog->get_cancel()->set_text("Cancel"); - //dialog->get_ok()->show(); - dialog->get_ok()->set_text("Remove"); - dialog->popup_centered(Size2(300,60));*/ -} - void ResourcePreloaderEditor::_update_library() { tree->clear(); @@ -228,18 +208,20 @@ void ResourcePreloaderEditor::_update_library() { ERR_CONTINUE(r.is_null()); - ti->set_tooltip(0, r->get_path()); + String type = r->get_class(); + ti->set_icon(0, EditorNode::get_singleton()->get_class_icon(type, "Object")); + ti->set_tooltip(0, TTR("Instance:") + " " + r->get_path() + "\n" + TTR("Type:") + " " + type); + ti->set_text(1, r->get_path()); - ti->add_button(1, get_icon("InstanceOptions", "EditorIcons"), BUTTON_SUBSCENE, false, TTR("Open in Editor")); - ti->set_tooltip(1, TTR("Instance:") + " " + r->get_path() + "\n" + TTR("Type:") + " " + r->get_class()); ti->set_editable(1, false); ti->set_selectable(1, false); - String type = r->get_class(); - ti->set_text(2, type); - ti->set_selectable(2, false); - if (has_icon(type, "EditorIcons")) - ti->set_icon(2, get_icon(type, "EditorIcons")); + if (type == "PackedScene") { + ti->add_button(1, get_icon("InstanceOptions", "EditorIcons"), BUTTON_OPEN_SCENE, false, TTR("Open in Editor")); + } else { + ti->add_button(1, get_icon("Load", "EditorIcons"), BUTTON_EDIT_RESOURCE, false, TTR("Open in Editor")); + } + ti->add_button(1, get_icon("Remove", "EditorIcons"), BUTTON_REMOVE, false, TTR("Remove")); } //player->add_resource("default",resource); @@ -250,10 +232,16 @@ void ResourcePreloaderEditor::_cell_button_pressed(Object *p_item, int p_column, TreeItem *item = Object::cast_to<TreeItem>(p_item); ERR_FAIL_COND(!item); - String rpath = item->get_text(p_column); - - if (p_id == BUTTON_SUBSCENE) { + if (p_id == BUTTON_OPEN_SCENE) { + String rpath = item->get_text(p_column); EditorInterface::get_singleton()->open_scene_from_path(rpath); + + } else if (p_id == BUTTON_EDIT_RESOURCE) { + RES r = preloader->get_resource(item->get_text(0)); + EditorInterface::get_singleton()->edit_resource(r); + + } else if (p_id == BUTTON_REMOVE) { + _remove_resource(item->get_text(0)); } } @@ -366,12 +354,11 @@ void ResourcePreloaderEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("_gui_input"), &ResourcePreloaderEditor::_gui_input); ClassDB::bind_method(D_METHOD("_load_pressed"), &ResourcePreloaderEditor::_load_pressed); ClassDB::bind_method(D_METHOD("_item_edited"), &ResourcePreloaderEditor::_item_edited); - ClassDB::bind_method(D_METHOD("_delete_pressed"), &ResourcePreloaderEditor::_delete_pressed); ClassDB::bind_method(D_METHOD("_paste_pressed"), &ResourcePreloaderEditor::_paste_pressed); - ClassDB::bind_method(D_METHOD("_delete_confirm_pressed"), &ResourcePreloaderEditor::_delete_confirm_pressed); ClassDB::bind_method(D_METHOD("_files_load_request"), &ResourcePreloaderEditor::_files_load_request); ClassDB::bind_method(D_METHOD("_update_library"), &ResourcePreloaderEditor::_update_library); ClassDB::bind_method(D_METHOD("_cell_button_pressed"), &ResourcePreloaderEditor::_cell_button_pressed); + ClassDB::bind_method(D_METHOD("_remove_resource", "to_remove"), &ResourcePreloaderEditor::_remove_resource); ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &ResourcePreloaderEditor::get_drag_data_fw); ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &ResourcePreloaderEditor::can_drop_data_fw); @@ -392,9 +379,6 @@ ResourcePreloaderEditor::ResourcePreloaderEditor() { load->set_tooltip(TTR("Load Resource")); hbc->add_child(load); - _delete = memnew(Button); - hbc->add_child(_delete); - paste = memnew(Button); paste->set_text(TTR("Paste")); hbc->add_child(paste); @@ -404,13 +388,11 @@ ResourcePreloaderEditor::ResourcePreloaderEditor() { tree = memnew(Tree); tree->connect("button_pressed", this, "_cell_button_pressed"); - tree->set_columns(3); - tree->set_column_min_width(0, 3); - tree->set_column_min_width(1, 1); - tree->set_column_min_width(2, 1); + tree->set_columns(2); + tree->set_column_min_width(0, 2); + tree->set_column_min_width(1, 3); tree->set_column_expand(0, true); tree->set_column_expand(1, true); - tree->set_column_expand(2, true); tree->set_v_size_flags(SIZE_EXPAND_FILL); tree->set_drag_forwarding(this); @@ -420,10 +402,8 @@ ResourcePreloaderEditor::ResourcePreloaderEditor() { add_child(dialog); load->connect("pressed", this, "_load_pressed"); - _delete->connect("pressed", this, "_delete_pressed"); paste->connect("pressed", this, "_paste_pressed"); file->connect("files_selected", this, "_files_load_request"); - //dialog->connect("confirmed", this,"_delete_confirm_pressed"); tree->connect("item_edited", this, "_item_edited"); loading_scene = false; } diff --git a/editor/plugins/resource_preloader_editor_plugin.h b/editor/plugins/resource_preloader_editor_plugin.h index e737157785..0a8238ce18 100644 --- a/editor/plugins/resource_preloader_editor_plugin.h +++ b/editor/plugins/resource_preloader_editor_plugin.h @@ -43,11 +43,12 @@ class ResourcePreloaderEditor : public PanelContainer { GDCLASS(ResourcePreloaderEditor, PanelContainer); enum { - BUTTON_SUBSCENE = 0, + BUTTON_OPEN_SCENE, + BUTTON_EDIT_RESOURCE, + BUTTON_REMOVE }; Button *load; - Button *_delete; Button *paste; Tree *tree; bool loading_scene; @@ -62,8 +63,7 @@ class ResourcePreloaderEditor : public PanelContainer { void _load_scene_pressed(); void _files_load_request(const Vector<String> &p_paths); void _paste_pressed(); - void _delete_pressed(); - void _delete_confirm_pressed(); + void _remove_resource(const String &p_to_remove); void _update_library(); void _cell_button_pressed(Object *p_item, int p_column, int p_id); void _item_edited(); diff --git a/editor/plugins/root_motion_editor_plugin.cpp b/editor/plugins/root_motion_editor_plugin.cpp index af3c09afc5..b3adf19a64 100644 --- a/editor/plugins/root_motion_editor_plugin.cpp +++ b/editor/plugins/root_motion_editor_plugin.cpp @@ -1,3 +1,33 @@ +/*************************************************************************/ +/* root_motion_editor_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 "root_motion_editor_plugin.h" #include "editor/editor_node.h" #include "scene/main/viewport.h" @@ -79,11 +109,7 @@ void EditorPropertyRootMotion::_node_assign() { if (base->has_node(accum)) { Node *node = base->get_node(accum); - if (has_icon(node->get_class(), "EditorIcons")) { - ti->set_icon(0, get_icon(node->get_class(), "EditorIcons")); - } else { - ti->set_icon(0, get_icon("Node", "EditorIcons")); - } + ti->set_icon(0, EditorNode::get_singleton()->get_object_icon(node, "Node")); } } else { @@ -96,7 +122,7 @@ void EditorPropertyRootMotion::_node_assign() { node = base->get_node(accum); } if (!node) - continue; //no node, cant edit + continue; //no node, can't edit if (path.get_subname_count()) { @@ -205,14 +231,7 @@ void EditorPropertyRootMotion::update_property() { ERR_FAIL_COND(!target_node); assign->set_text(target_node->get_name()); - - Ref<Texture> icon; - if (has_icon(target_node->get_class(), "EditorIcons")) - icon = get_icon(target_node->get_class(), "EditorIcons"); - else - icon = get_icon("Node", "EditorIcons"); - - assign->set_icon(icon); + assign->set_icon(EditorNode::get_singleton()->get_object_icon(target_node, "Node")); } void EditorPropertyRootMotion::setup(const NodePath &p_base_hint) { @@ -284,7 +303,7 @@ bool EditorInspectorRootMotionPlugin::parse_property(Object *p_object, Variant:: return true; } - return false; //can be overriden, although it will most likely be last anyway + return false; //can be overridden, although it will most likely be last anyway } void EditorInspectorRootMotionPlugin::parse_end() { diff --git a/editor/plugins/root_motion_editor_plugin.h b/editor/plugins/root_motion_editor_plugin.h index 84af47872f..2b5492350b 100644 --- a/editor/plugins/root_motion_editor_plugin.h +++ b/editor/plugins/root_motion_editor_plugin.h @@ -1,3 +1,33 @@ +/*************************************************************************/ +/* root_motion_editor_plugin.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 ROOT_MOTION_EDITOR_PLUGIN_H #define ROOT_MOTION_EDITOR_PLUGIN_H diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index fa034c97c0..085660b79e 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -59,25 +59,10 @@ void ScriptEditorBase::_bind_methods() { ADD_SIGNAL(MethodInfo("search_in_files_requested", PropertyInfo(Variant::STRING, "text"))); } -static bool _can_open_in_editor(Script *p_script) { - +static bool _is_built_in_script(Script *p_script) { String path = p_script->get_path(); - if (path.find("::") != -1) { - //refuse handling this if it can't be edited - - bool valid = false; - for (int i = 0; i < EditorNode::get_singleton()->get_editor_data().get_edited_scene_count(); i++) { - if (path.begins_with(EditorNode::get_singleton()->get_editor_data().get_scene_path(i))) { - valid = true; - break; - } - } - - return valid; - } - - return true; + return path.find("::") != -1; } class EditorScriptCodeCompletionCache : public ScriptCodeCompletionCache { @@ -111,7 +96,7 @@ public: } } - RES get_cached_resource(const String &p_path) { + virtual RES get_cached_resource(const String &p_path) { Map<String, Cache>::Element *E = cached.find(p_path); if (!E) { @@ -149,9 +134,11 @@ public: max_cache_size = 128; max_time_cache = 5 * 60 * 1000; //minutes, five } + + virtual ~EditorScriptCodeCompletionCache() {} }; -void ScriptEditorQuickOpen::popup(const Vector<String> &p_functions, bool p_dontclear) { +void ScriptEditorQuickOpen::popup_dialog(const Vector<String> &p_functions, bool p_dontclear) { popup_centered_ratio(0.6); if (p_dontclear) @@ -223,6 +210,9 @@ void ScriptEditorQuickOpen::_notification(int p_what) { search_box->set_right_icon(get_icon("Search", "EditorIcons")); search_box->set_clear_button_enabled(true); } break; + case NOTIFICATION_EXIT_TREE: { + disconnect("confirmed", this, "_confirmed"); + } break; } } @@ -503,7 +493,14 @@ void ScriptEditor::_open_recent_script(int p_idx) { edit(text_file, true); return; } - // if it's a path then its most likely a deleted file not help + // if it's a path then it's most likely a deleted file not help + } else if (path.find("::") != -1) { + // built-in script + Ref<Script> script = ResourceLoader::load(path); + if (script.is_valid()) { + edit(script, true); + return; + } } else if (!path.is_resource_file()) { _help_class_open(path); return; @@ -805,7 +802,7 @@ bool ScriptEditor::_test_script_times_on_disk(RES p_for_script) { if (se) { RES edited_res = se->get_edited_resource(); - if (edited_res.is_valid() && p_for_script != edited_res) + if (p_for_script.is_valid() && edited_res.is_valid() && p_for_script != edited_res) continue; if (edited_res->get_path() == "" || edited_res->get_path().find("local://") != -1 || edited_res->get_path().find("::") != -1) @@ -862,7 +859,7 @@ void ScriptEditor::_file_dialog_action(String p_file) { if (extensions.find(p_file.get_extension())) { Ref<Script> scr = ResourceLoader::load(p_file); if (!scr.is_valid()) { - editor->show_warning(TTR("Error could not load file."), TTR("Error!")); + editor->show_warning(TTR("Error: could not load file."), TTR("Error!")); file_dialog_option = -1; return; } @@ -939,7 +936,7 @@ void ScriptEditor::_menu_option(int p_option) { switch (p_option) { case FILE_NEW: { - script_create_dialog->config("Node", ".gd"); + script_create_dialog->config("Node", "new_script"); script_create_dialog->popup_centered(Size2(300, 300) * EDSCALE); } break; case FILE_NEW_TEXTFILE: { @@ -976,15 +973,15 @@ void ScriptEditor::_menu_option(int p_option) { } break; case SEARCH_HELP: { - help_search_dialog->popup(); + help_search_dialog->popup_dialog(); } break; case SEARCH_CLASSES: { - help_index->popup(); + help_index->popup_dialog(); } break; case SEARCH_WEBSITE: { - OS::get_singleton()->shell_open("http://docs.godotengine.org/"); + OS::get_singleton()->shell_open("https://docs.godotengine.org/"); } break; case WINDOW_NEXT: { @@ -1212,7 +1209,7 @@ void ScriptEditor::_menu_option(int p_option) { case SEARCH_CLASSES: { - help_index->popup(); + help_index->popup_dialog(); help_index->call_deferred("select_class", help->get_class()); } break; case HELP_SEARCH_FIND: { @@ -1369,7 +1366,9 @@ void ScriptEditor::_notification(int p_what) { if (is_visible()) { find_in_files_button->show(); } else { - find_in_files->hide(); + if (find_in_files->is_visible_in_tree()) { + editor->hide_bottom_panel(); + } find_in_files_button->hide(); } @@ -1422,21 +1421,6 @@ void ScriptEditor::notify_script_changed(const Ref<Script> &p_script) { emit_signal("editor_script_changed", p_script); } -static const Node *_find_node_with_script(const Node *p_node, const RefPtr &p_script) { - - if (p_node->get_script() == p_script) - return p_node; - - for (int i = 0; i < p_node->get_child_count(); i++) { - - const Node *result = _find_node_with_script(p_node->get_child(i), p_script); - if (result) - return result; - } - - return NULL; -} - void ScriptEditor::get_breakpoints(List<String> *p_breakpoints) { for (int i = 0; i < tab_container->get_child_count(); i++) { @@ -1742,7 +1726,7 @@ void ScriptEditor::_update_script_names() { } break; case DISPLAY_DIR_AND_NAME: { if (!path.get_base_dir().get_file().empty()) { - sd.name = path.get_base_dir().get_file() + "/" + name; + sd.name = path.get_base_dir().get_file().plus_file(name); } else { sd.name = name; } @@ -1793,8 +1777,8 @@ void ScriptEditor::_update_script_names() { new_cur_tab = i; } } - tab_container->call_deferred("set_current_tab", new_prev_tab); - tab_container->call_deferred("set_current_tab", new_cur_tab); + tab_container->set_current_tab(new_prev_tab); + tab_container->set_current_tab(new_cur_tab); _sort_list_on_update = false; } @@ -1981,7 +1965,7 @@ bool ScriptEditor::edit(const RES &p_resource, int p_line, int p_col, bool p_gra // doesn't have it, make a new one - ScriptEditorBase *se; + ScriptEditorBase *se = NULL; for (int i = script_editor_func_count - 1; i >= 0; i--) { se = script_editor_funcs[i](p_resource); @@ -2017,6 +2001,7 @@ bool ScriptEditor::edit(const RES &p_resource, int p_line, int p_col, bool p_gra _go_to_tab(tab_container->get_tab_count() - 1); } + _sort_list_on_update = true; _update_script_names(); _save_layout(); se->connect("name_changed", this, "_update_script_names"); @@ -2106,8 +2091,6 @@ void ScriptEditor::_editor_play() { debug_menu->get_popup()->set_item_disabled(debug_menu->get_popup()->get_item_index(DEBUG_STEP), true); debug_menu->get_popup()->set_item_disabled(debug_menu->get_popup()->get_item_index(DEBUG_BREAK), false); debug_menu->get_popup()->set_item_disabled(debug_menu->get_popup()->get_item_index(DEBUG_CONTINUE), true); - - //debugger_gui->start_listening(Globals::get_singleton()->get("debug/debug_port")); } void ScriptEditor::_editor_pause() { @@ -2591,6 +2574,7 @@ void ScriptEditor::_help_class_open(const String &p_class) { eh->go_to_class(p_class, 0); eh->connect("go_to_help", this, "_help_class_goto"); _add_recent_script(p_class); + _sort_list_on_update = true; _update_script_names(); _save_layout(); } @@ -2620,6 +2604,7 @@ void ScriptEditor::_help_class_goto(const String &p_desc) { eh->go_to_help(p_desc); eh->connect("go_to_help", this, "_help_class_goto"); _add_recent_script(eh->get_class()); + _sort_list_on_update = true; _update_script_names(); _save_layout(); } @@ -2728,7 +2713,7 @@ void ScriptEditor::set_scene_root_script(Ref<Script> p_script) { if (bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor"))) return; - if (open_dominant && p_script.is_valid() && _can_open_in_editor(p_script.ptr())) { + if (open_dominant && p_script.is_valid()) { edit(p_script); } } @@ -2749,11 +2734,11 @@ void ScriptEditor::set_live_auto_reload_running_scripts(bool p_enabled) { } void ScriptEditor::_help_index(String p_text) { - help_index->popup(); + help_index->popup_dialog(); } void ScriptEditor::_help_search(String p_text) { - help_search_dialog->popup(p_text); + help_search_dialog->popup_dialog(p_text); } void ScriptEditor::_open_script_request(const String &p_path) { @@ -2826,8 +2811,7 @@ void ScriptEditor::_start_find_in_files(bool with_replace) { find_in_files->set_with_replace(with_replace); find_in_files->start_search(); - find_in_files_button->set_pressed(true); - find_in_files->show(); + editor->make_bottom_panel_item_visible(find_in_files); } void ScriptEditor::_on_find_in_files_modified_files(PoolStringArray paths) { @@ -2911,7 +2895,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { restoring_layout = false; waiting_update_names = false; pending_auto_reload = false; - auto_reload_running_scripts = false; + auto_reload_running_scripts = true; members_overview_enabled = EditorSettings::get_singleton()->get("text_editor/open_scripts/show_members_overview"); help_overview_enabled = EditorSettings::get_singleton()->get("text_editor/help/show_help_index"); editor = p_editor; @@ -2932,7 +2916,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { script_list = memnew(ItemList); list_split->add_child(script_list); - script_list->set_custom_minimum_size(Size2(150 * EDSCALE, 90)); //need to give a bit of limit to avoid it from disappearing + script_list->set_custom_minimum_size(Size2(150, 90) * EDSCALE); //need to give a bit of limit to avoid it from disappearing script_list->set_v_size_flags(SIZE_EXPAND_FILL); script_split->set_split_offset(140); _sort_list_on_update = true; @@ -2971,7 +2955,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { overview_vbox->add_child(members_overview); members_overview->set_allow_reselect(true); - members_overview->set_custom_minimum_size(Size2(0, 90)); //need to give a bit of limit to avoid it from disappearing + members_overview->set_custom_minimum_size(Size2(0, 90) * EDSCALE); //need to give a bit of limit to avoid it from disappearing members_overview->set_v_size_flags(SIZE_EXPAND_FILL); members_overview->set_allow_rmb_select(true); members_overview->set_drag_forwarding(this); @@ -2979,12 +2963,12 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { help_overview = memnew(ItemList); overview_vbox->add_child(help_overview); help_overview->set_allow_reselect(true); - help_overview->set_custom_minimum_size(Size2(0, 90)); //need to give a bit of limit to avoid it from disappearing + help_overview->set_custom_minimum_size(Size2(0, 90) * EDSCALE); //need to give a bit of limit to avoid it from disappearing help_overview->set_v_size_flags(SIZE_EXPAND_FILL); tab_container = memnew(TabContainer); tab_container->set_tabs_visible(false); - tab_container->set_custom_minimum_size(Size2(200 * EDSCALE, 0)); + tab_container->set_custom_minimum_size(Size2(200, 0) * EDSCALE); script_split->add_child(tab_container); tab_container->set_h_size_flags(SIZE_EXPAND_FILL); @@ -3017,10 +3001,10 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { file_menu->get_popup()->add_separator(); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/reload_script_soft", TTR("Soft Reload Script"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_R), FILE_TOOL_RELOAD_SOFT); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/copy_path", TTR("Copy Script Path")), FILE_COPY_PATH); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/show_in_file_system", TTR("Show In File System")), SHOW_IN_FILE_SYSTEM); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/show_in_file_system", TTR("Show in FileSystem")), SHOW_IN_FILE_SYSTEM); file_menu->get_popup()->add_separator(); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/history_previous", TTR("History Prev"), KEY_MASK_ALT | KEY_LEFT), WINDOW_PREV); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/history_previous", TTR("History Previous"), KEY_MASK_ALT | KEY_LEFT), WINDOW_PREV); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/history_next", TTR("History Next"), KEY_MASK_ALT | KEY_RIGHT), WINDOW_NEXT); file_menu->get_popup()->add_separator(); @@ -3067,7 +3051,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { debug_menu->get_popup()->add_separator(); //debug_menu->get_popup()->add_check_item("Show Debugger",DEBUG_SHOW); debug_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("debugger/keep_debugger_open", TTR("Keep Debugger Open")), DEBUG_SHOW_KEEP_OPEN); - debug_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("debugger/debug_with_exteral_editor", TTR("Debug with external editor")), DEBUG_WITH_EXTERNAL_EDITOR); + debug_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("debugger/debug_with_external_editor", TTR("Debug with External Editor")), DEBUG_WITH_EXTERNAL_EDITOR); debug_menu->get_popup()->connect("id_pressed", this, "_menu_option"); debug_menu->get_popup()->set_item_disabled(debug_menu->get_popup()->get_item_index(DEBUG_NEXT), true); @@ -3140,7 +3124,6 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { error_dialog = memnew(AcceptDialog); add_child(error_dialog); - error_dialog->get_ok()->set_text(TTR("OK")); debugger = memnew(ScriptEditorDebugger(editor)); debugger->connect("goto_script_line", this, "_goto_script_line"); @@ -3194,9 +3177,8 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { find_in_files_dialog->connect(FindInFilesDialog::SIGNAL_REPLACE_REQUESTED, this, "_start_find_in_files", varray(true)); add_child(find_in_files_dialog); find_in_files = memnew(FindInFilesPanel); - find_in_files_button = editor->add_bottom_panel_item(TTR("Search results"), find_in_files); - find_in_files_button->set_tooltip(TTR("Search in files")); - find_in_files->set_custom_minimum_size(Size2(0, 200)); + find_in_files_button = editor->add_bottom_panel_item(TTR("Search Results"), find_in_files); + find_in_files->set_custom_minimum_size(Size2(0, 200) * EDSCALE); find_in_files->connect(FindInFilesPanel::SIGNAL_RESULT_SELECTED, this, "_on_find_in_files_result_selected"); find_in_files->connect(FindInFilesPanel::SIGNAL_FILES_MODIFIED, this, "_on_find_in_files_modified_files"); find_in_files->hide(); @@ -3224,7 +3206,17 @@ ScriptEditor::~ScriptEditor() { void ScriptEditorPlugin::edit(Object *p_object) { if (Object::cast_to<Script>(p_object)) { - script_editor->edit(Object::cast_to<Script>(p_object)); + + Script *p_script = Object::cast_to<Script>(p_object); + String scene_path = p_script->get_path().get_slice("::", 0); + + if (_is_built_in_script(p_script) && !EditorNode::get_singleton()->is_scene_open(scene_path)) { + EditorNode::get_singleton()->load_scene(scene_path); + + script_editor->call_deferred("edit", p_script); + } else { + script_editor->edit(p_script); + } } if (Object::cast_to<TextFile>(p_object)) { @@ -3239,13 +3231,7 @@ bool ScriptEditorPlugin::handles(Object *p_object) const { } if (Object::cast_to<Script>(p_object)) { - - bool valid = _can_open_in_editor(Object::cast_to<Script>(p_object)); - - if (!valid) { //user tried to open it by clicking - EditorNode::get_singleton()->show_warning(TTR("Built-in scripts can only be edited when the scene they belong to is loaded")); - } - return valid; + return true; } return p_object->is_class("Script"); diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index 737f17358b..28c07393f7 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -31,6 +31,7 @@ #ifndef SCRIPT_EDITOR_PLUGIN_H #define SCRIPT_EDITOR_PLUGIN_H +#include "core/script_language.h" #include "editor/code_editor.h" #include "editor/editor_help.h" #include "editor/editor_plugin.h" @@ -44,7 +45,6 @@ #include "scene/gui/tree.h" #include "scene/main/timer.h" #include "scene/resources/text_file.h" -#include "script_language.h" class ScriptEditorQuickOpen : public ConfirmationDialog { @@ -67,7 +67,7 @@ protected: static void _bind_methods(); public: - void popup(const Vector<String> &p_functions, bool p_dontclear = false); + void popup_dialog(const Vector<String> &p_functions, bool p_dontclear = false); ScriptEditorQuickOpen(); }; diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 4e7047ee38..c3e2aa86f0 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -30,10 +30,10 @@ #include "script_text_editor.h" +#include "core/os/keyboard.h" #include "editor/editor_node.h" #include "editor/editor_settings.h" #include "editor/script_editor_debugger.h" -#include "os/keyboard.h" Vector<String> ScriptTextEditor::get_functions() { @@ -179,7 +179,7 @@ void ScriptTextEditor::_load_theme_settings() { text_edit->add_color_override("search_result_border_color", search_result_border_color); text_edit->add_color_override("symbol_color", symbol_color); - text_edit->add_constant_override("line_spacing", EDITOR_DEF("text_editor/theme/line_spacing", 4)); + text_edit->add_constant_override("line_spacing", EDITOR_DEF("text_editor/theme/line_spacing", 6)); colors_cache.symbol_color = symbol_color; colors_cache.keyword_color = keyword_color; @@ -317,6 +317,7 @@ void ScriptTextEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_READY: _load_theme_settings(); + _change_syntax_highlighter(EditorSettings::get_singleton()->get_project_metadata("script_text_editor", "syntax_highlighter", 0)); break; } } @@ -772,7 +773,7 @@ void ScriptTextEditor::_edit_option(int p_op) { } break; case EDIT_CLONE_DOWN: { - code_editor->code_lines_down(); + code_editor->clone_lines_down(); } break; case EDIT_TOGGLE_FOLD_LINE: { @@ -816,6 +817,9 @@ void ScriptTextEditor::_edit_option(int p_op) { if (tx->get_selection_to_column() == 0) end -= 1; + int col_to = tx->get_selection_to_column(); + int cursor_pos = tx->cursor_get_column(); + // Check if all lines in the selected block are commented bool is_commented = true; for (int i = begin; i <= end; i++) { @@ -838,19 +842,42 @@ void ScriptTextEditor::_edit_option(int p_op) { } tx->set_line(i, line_text); } + + // Adjust selection & cursor position. + int offset = is_commented ? -1 : 1; + int col_from = tx->get_selection_from_column() > 0 ? tx->get_selection_from_column() + offset : 0; + + if (is_commented && tx->cursor_get_column() == tx->get_line(tx->cursor_get_line()).length() + 1) + cursor_pos += 1; + + if (tx->get_selection_to_column() != 0 && col_to != tx->get_line(tx->get_selection_to_line()).length() + 1) + col_to += offset; + + if (tx->cursor_get_column() != 0) + cursor_pos += offset; + + tx->select(begin, col_from, tx->get_selection_to_line(), col_to); + tx->cursor_set_column(cursor_pos); + } else { int begin = tx->cursor_get_line(); String line_text = tx->get_line(begin); - if (line_text.begins_with(delimiter)) + int col = tx->cursor_get_column(); + if (line_text.begins_with(delimiter)) { line_text = line_text.substr(delimiter.length(), line_text.length()); - else + col -= 1; + } else { line_text = delimiter + line_text; + col += 1; + } + tx->set_line(begin, line_text); + tx->cursor_set_column(col); } tx->end_complex_operation(); tx->update(); - //tx->deselect(); + } break; case EDIT_COMPLETE: { @@ -939,7 +966,8 @@ void ScriptTextEditor::_edit_option(int p_op) { } break; case SEARCH_LOCATE_FUNCTION: { - quick_open->popup(get_functions()); + quick_open->popup_dialog(get_functions()); + quick_open->set_title(TTR("Go to Function")); } break; case SEARCH_GOTO_LINE: { @@ -1058,6 +1086,7 @@ void ScriptTextEditor::_change_syntax_highlighter(int p_idx) { } // highlighter_menu->set_item_checked(p_idx, true); set_syntax_highlighter(highlighters[highlighter_menu->get_item_text(p_idx)]); + EditorSettings::get_singleton()->set_project_metadata("script_text_editor", "syntax_highlighter", p_idx); } void ScriptTextEditor::_bind_methods() { @@ -1256,7 +1285,7 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { int to_column = tx->get_selection_to_column(); if (row < from_line || row > to_line || (row == from_line && col < from_column) || (row == to_line && col > to_column)) { - // Right click is outside the seleted text + // Right click is outside the selected text tx->deselect(); } } @@ -1273,7 +1302,6 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { word_at_mouse = tx->get_selection_text(); bool has_color = (word_at_mouse == "Color"); - int fold_state = 0; bool foldable = tx->can_fold(row) || tx->is_folded(row); bool open_docs = false; bool goto_definition = false; @@ -1475,9 +1503,9 @@ ScriptTextEditor::ScriptTextEditor() { convert_case->set_name("convert_case"); edit_menu->get_popup()->add_child(convert_case); edit_menu->get_popup()->add_submenu_item(TTR("Convert Case"), "convert_case"); - convert_case->add_shortcut(ED_SHORTCUT("script_text_editor/convert_to_uppercase", TTR("Uppercase")), EDIT_TO_UPPERCASE); - convert_case->add_shortcut(ED_SHORTCUT("script_text_editor/convert_to_lowercase", TTR("Lowercase")), EDIT_TO_LOWERCASE); - convert_case->add_shortcut(ED_SHORTCUT("script_text_editor/capitalize", TTR("Capitalize")), EDIT_CAPITALIZE); + convert_case->add_shortcut(ED_SHORTCUT("script_text_editor/convert_to_uppercase", TTR("Uppercase"), KEY_MASK_SHIFT | KEY_F4), EDIT_TO_UPPERCASE); + convert_case->add_shortcut(ED_SHORTCUT("script_text_editor/convert_to_lowercase", TTR("Lowercase"), KEY_MASK_SHIFT | KEY_F5), EDIT_TO_LOWERCASE); + convert_case->add_shortcut(ED_SHORTCUT("script_text_editor/capitalize", TTR("Capitalize"), KEY_MASK_SHIFT | KEY_F6), EDIT_CAPITALIZE); convert_case->connect("id_pressed", this, "_edit_option"); highlighters["Standard"] = NULL; @@ -1549,13 +1577,14 @@ void ScriptTextEditor::register_editor() { ED_SHORTCUT("script_text_editor/unfold_all_lines", TTR("Unfold All Lines"), 0); #ifdef OSX_ENABLED ED_SHORTCUT("script_text_editor/clone_down", TTR("Clone Down"), KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_C); + ED_SHORTCUT("script_text_editor/complete_symbol", TTR("Complete Symbol"), KEY_MASK_CTRL | KEY_SPACE); #else ED_SHORTCUT("script_text_editor/clone_down", TTR("Clone Down"), KEY_MASK_CMD | KEY_B); -#endif ED_SHORTCUT("script_text_editor/complete_symbol", TTR("Complete Symbol"), KEY_MASK_CMD | KEY_SPACE); +#endif ED_SHORTCUT("script_text_editor/trim_trailing_whitespace", TTR("Trim Trailing Whitespace"), KEY_MASK_CMD | KEY_MASK_ALT | KEY_T); - ED_SHORTCUT("script_text_editor/convert_indent_to_spaces", TTR("Convert Indent To Spaces"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_Y); - ED_SHORTCUT("script_text_editor/convert_indent_to_tabs", TTR("Convert Indent To Tabs"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_X); + ED_SHORTCUT("script_text_editor/convert_indent_to_spaces", TTR("Convert Indent to Spaces"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_Y); + ED_SHORTCUT("script_text_editor/convert_indent_to_tabs", TTR("Convert Indent to Tabs"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_I); ED_SHORTCUT("script_text_editor/auto_indent", TTR("Auto Indent"), KEY_MASK_CMD | KEY_I); #ifdef OSX_ENABLED @@ -1564,27 +1593,28 @@ void ScriptTextEditor::register_editor() { ED_SHORTCUT("script_text_editor/toggle_breakpoint", TTR("Toggle Breakpoint"), KEY_F9); #endif ED_SHORTCUT("script_text_editor/remove_all_breakpoints", TTR("Remove All Breakpoints"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F9); - ED_SHORTCUT("script_text_editor/goto_next_breakpoint", TTR("Goto Next Breakpoint"), KEY_MASK_CMD | KEY_PERIOD); - ED_SHORTCUT("script_text_editor/goto_previous_breakpoint", TTR("Goto Previous Breakpoint"), KEY_MASK_CMD | KEY_COMMA); - - ED_SHORTCUT("script_text_editor/convert_to_uppercase", TTR("Convert To Uppercase"), KEY_MASK_SHIFT | KEY_F4); - ED_SHORTCUT("script_text_editor/convert_to_lowercase", TTR("Convert To Lowercase"), KEY_MASK_SHIFT | KEY_F3); - ED_SHORTCUT("script_text_editor/capitalize", TTR("Capitalize"), KEY_MASK_SHIFT | KEY_F2); + ED_SHORTCUT("script_text_editor/goto_next_breakpoint", TTR("Go to Next Breakpoint"), KEY_MASK_CMD | KEY_PERIOD); + ED_SHORTCUT("script_text_editor/goto_previous_breakpoint", TTR("Go to Previous Breakpoint"), KEY_MASK_CMD | KEY_COMMA); ED_SHORTCUT("script_text_editor/find", TTR("Find..."), KEY_MASK_CMD | KEY_F); #ifdef OSX_ENABLED ED_SHORTCUT("script_text_editor/find_next", TTR("Find Next"), KEY_MASK_CMD | KEY_G); ED_SHORTCUT("script_text_editor/find_previous", TTR("Find Previous"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_G); + ED_SHORTCUT("script_text_editor/replace", TTR("Replace..."), KEY_MASK_ALT | KEY_MASK_CMD | KEY_F); #else ED_SHORTCUT("script_text_editor/find_next", TTR("Find Next"), KEY_F3); ED_SHORTCUT("script_text_editor/find_previous", TTR("Find Previous"), KEY_MASK_SHIFT | KEY_F3); -#endif ED_SHORTCUT("script_text_editor/replace", TTR("Replace..."), KEY_MASK_CMD | KEY_R); +#endif - ED_SHORTCUT("script_text_editor/find_in_files", TTR("Find in files..."), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F); + ED_SHORTCUT("script_text_editor/find_in_files", TTR("Find in Files..."), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F); - ED_SHORTCUT("script_text_editor/goto_function", TTR("Goto Function..."), KEY_MASK_ALT | KEY_MASK_CMD | KEY_F); - ED_SHORTCUT("script_text_editor/goto_line", TTR("Goto Line..."), KEY_MASK_CMD | KEY_L); +#ifdef OSX_ENABLED + ED_SHORTCUT("script_text_editor/goto_function", TTR("Go to Function..."), KEY_MASK_CTRL | KEY_MASK_CMD | KEY_J); +#else + ED_SHORTCUT("script_text_editor/goto_function", TTR("Go to Function..."), KEY_MASK_ALT | KEY_MASK_CMD | KEY_F); +#endif + ED_SHORTCUT("script_text_editor/goto_line", TTR("Go to Line..."), KEY_MASK_CMD | KEY_L); #ifdef OSX_ENABLED ED_SHORTCUT("script_text_editor/contextual_help", TTR("Contextual Help"), KEY_MASK_ALT | KEY_MASK_SHIFT | KEY_SPACE); diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 5ee40dc90a..638de1b213 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -86,10 +86,7 @@ void ShaderTextEditor::_load_theme_settings() { Color search_result_border_color = EDITOR_GET("text_editor/highlighting/search_result_border_color"); Color symbol_color = EDITOR_GET("text_editor/highlighting/symbol_color"); Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color"); - Color basetype_color = EDITOR_GET("text_editor/highlighting/base_type_color"); - Color type_color = EDITOR_GET("text_editor/highlighting/engine_type_color"); Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color"); - Color string_color = EDITOR_GET("text_editor/highlighting/string_color"); get_text_edit()->add_color_override("background_color", background_color); get_text_edit()->add_color_override("completion_background_color", completion_background_color); @@ -140,26 +137,9 @@ void ShaderTextEditor::_load_theme_settings() { get_text_edit()->add_keyword_color(E->get(), keyword_color); } - //colorize core types - //Color basetype_color= EDITOR_DEF("text_editor/base_type_color",Color(0.3,0.3,0.0)); - //colorize comments get_text_edit()->add_color_region("/*", "*/", comment_color, false); get_text_edit()->add_color_region("//", "", comment_color, false); - - /*//colorize strings - Color string_color = EDITOR_DEF("text_editor/string_color",Color::hex(0x6b6f00ff)); - - List<String> strings; - shader->get_shader_mode()->get_string_delimiters(&strings); - - for (List<String>::Element *E=strings.front();E;E=E->next()) { - - String string = E->get(); - String beg = string.get_slice(" ",0); - String end = string.get_slice_count(" ")>1?string.get_slice(" ",1):String(); - get_text_edit()->add_color_region(beg,end,string_color,end==""); - }*/ } void ShaderTextEditor::_check_shader_mode() { @@ -283,7 +263,7 @@ void ShaderEditor::_menu_option(int p_option) { shader_editor->delete_lines(); } break; case EDIT_CLONE_DOWN: { - shader_editor->code_lines_down(); + shader_editor->clone_lines_down(); } break; case EDIT_TOGGLE_COMMENT: { @@ -426,7 +406,7 @@ void ShaderEditor::ensure_select_current() { void ShaderEditor::edit(const Ref<Shader> &p_shader) { - if (p_shader.is_null()) + if (p_shader.is_null() || !p_shader->is_text_shader()) return; shader = p_shader; @@ -468,7 +448,6 @@ void ShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { int col, row; TextEdit *tx = shader_editor->get_text_edit(); tx->_get_mouse_pos(mb->get_global_position() - tx->get_global_position(), row, col); - Vector2 mpos = mb->get_global_position() - tx->get_global_position(); tx->set_right_click_moves_caret(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret")); if (tx->is_right_click_moving_caret()) { @@ -480,7 +459,7 @@ void ShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { int to_column = tx->get_selection_to_column(); if (row < from_line || row > to_line || (row == from_line && col < from_column) || (row == to_line && col > to_column)) { - // Right click is outside the seleted text + // Right click is outside the selected text tx->deselect(); } } @@ -606,7 +585,7 @@ void ShaderEditorPlugin::edit(Object *p_object) { bool ShaderEditorPlugin::handles(Object *p_object) const { Shader *shader = Object::cast_to<Shader>(p_object); - return shader != NULL; + return shader != NULL && shader->is_text_shader(); } void ShaderEditorPlugin::make_visible(bool p_visible) { diff --git a/editor/plugins/skeleton_editor_plugin.cpp b/editor/plugins/skeleton_editor_plugin.cpp index 314db4198d..8b0beefb3e 100644 --- a/editor/plugins/skeleton_editor_plugin.cpp +++ b/editor/plugins/skeleton_editor_plugin.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ @@ -29,9 +29,10 @@ /*************************************************************************/ #include "skeleton_editor_plugin.h" + #include "scene/3d/collision_shape.h" #include "scene/3d/physics_body.h" -#include "scene/3d/physics_joint.h"; +#include "scene/3d/physics_joint.h" #include "scene/resources/capsule_shape.h" #include "scene/resources/sphere_shape.h" #include "spatial_editor_plugin.h" @@ -150,6 +151,7 @@ void SkeletonEditor::_bind_methods() { } SkeletonEditor::SkeletonEditor() { + skeleton = NULL; options = memnew(MenuButton); SpatialEditor::get_singleton()->add_control_to_menu_panel(options); diff --git a/editor/plugins/skeleton_editor_plugin.h b/editor/plugins/skeleton_editor_plugin.h index 0ab94c15b5..aac3e06063 100644 --- a/editor/plugins/skeleton_editor_plugin.h +++ b/editor/plugins/skeleton_editor_plugin.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ diff --git a/editor/plugins/skeleton_ik_editor_plugin.cpp b/editor/plugins/skeleton_ik_editor_plugin.cpp index 2d343d3edd..c605548a6b 100644 --- a/editor/plugins/skeleton_ik_editor_plugin.cpp +++ b/editor/plugins/skeleton_ik_editor_plugin.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ diff --git a/editor/plugins/skeleton_ik_editor_plugin.h b/editor/plugins/skeleton_ik_editor_plugin.h index e645bea39a..3e412305c9 100644 --- a/editor/plugins/skeleton_ik_editor_plugin.h +++ b/editor/plugins/skeleton_ik_editor_plugin.h @@ -1,12 +1,12 @@ /*************************************************************************/ -/* skeleton_ik_editor_plugin.h */ +/* skeleton_ik_editor_plugin.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) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index 906c51b9f6..a5563c0497 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -30,23 +30,25 @@ #include "spatial_editor_plugin.h" -#include "camera_matrix.h" +#include "core/math/camera_matrix.h" #include "core/os/input.h" - +#include "core/os/keyboard.h" +#include "core/print_string.h" +#include "core/project_settings.h" +#include "core/sort.h" #include "editor/editor_node.h" #include "editor/editor_settings.h" #include "editor/plugins/animation_player_editor_plugin.h" #include "editor/plugins/script_editor_plugin.h" #include "editor/script_editor_debugger.h" #include "editor/spatial_editor_gizmos.h" -#include "os/keyboard.h" -#include "print_string.h" -#include "project_settings.h" #include "scene/3d/camera.h" +#include "scene/3d/collision_shape.h" +#include "scene/3d/mesh_instance.h" +#include "scene/3d/physics_body.h" #include "scene/3d/visual_instance.h" #include "scene/resources/packed_scene.h" #include "scene/resources/surface_tool.h" -#include "sort.h" #define DISTANCE_DEFAULT 4 @@ -274,7 +276,7 @@ void SpatialEditorViewport::_select_clicked(bool p_append, bool p_single) { _select(sp, clicked_wants_append, true); } -void SpatialEditorViewport::_select(Spatial *p_node, bool p_append, bool p_single) { +void SpatialEditorViewport::_select(Node *p_node, bool p_append, bool p_single) { if (!p_append) { editor_selection->clear(); @@ -307,7 +309,7 @@ ObjectID SpatialEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, Node *edited_scene = get_tree()->get_edited_scene_root(); ObjectID closest = 0; - Spatial *item = NULL; + Node *item = NULL; float closest_dist = 1e20; int selected_handle = -1; @@ -340,20 +342,15 @@ ObjectID SpatialEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, continue; if (dist < closest_dist) { - //make sure that whathever is selected is editable - while (spat && spat != edited_scene && spat->get_owner() != edited_scene && !edited_scene->is_editable_instance(spat->get_owner())) { - spat = Object::cast_to<Spatial>(spat->get_owner()); + item = Object::cast_to<Node>(spat); + while (item->get_owner() && item->get_owner() != edited_scene && !edited_scene->is_editable_instance(item->get_owner())) { + item = item->get_owner(); } - if (spat) { - item = spat; - closest = spat->get_instance_id(); - closest_dist = dist; - selected_handle = handle; - } else { - ERR_PRINT("Bug?"); - } + closest = item->get_instance_id(); + closest_dist = dist; + selected_handle = handle; } } @@ -499,7 +496,7 @@ void SpatialEditorViewport::_select_region() { } Vector<ObjectID> instances = VisualServer::get_singleton()->instances_cull_convex(frustum, get_tree()->get_root()->get_world()->get_scenario()); - Vector<Spatial *> selected; + Vector<Node *> selected; Node *edited_scene = get_tree()->get_edited_scene_root(); @@ -509,12 +506,12 @@ void SpatialEditorViewport::_select_region() { if (!sp) continue; - Spatial *root_sp = sp; - while (root_sp && root_sp != edited_scene && root_sp->get_owner() != edited_scene && !edited_scene->is_editable_instance(root_sp->get_owner())) { - root_sp = Object::cast_to<Spatial>(root_sp->get_owner()); + Node *item = Object::cast_to<Node>(sp); + while (item->get_owner() && item->get_owner() != edited_scene && !edited_scene->is_editable_instance(item->get_owner())) { + item = item->get_owner(); } - if (selected.find(root_sp) != -1) continue; + if (selected.find(item) != -1) continue; Ref<EditorSpatialGizmo> seg = sp->get_gizmo(); @@ -522,7 +519,7 @@ void SpatialEditorViewport::_select_region() { continue; if (seg->intersect_frustum(camera, frustum)) { - selected.push_back(root_sp); + selected.push_back(item); } } @@ -534,12 +531,12 @@ void SpatialEditorViewport::_select_region() { void SpatialEditorViewport::_update_name() { - String ortho = orthogonal ? TTR("Orthogonal") : TTR("Perspective"); + String view_mode = orthogonal ? TTR("Orthogonal") : TTR("Perspective"); if (name != "") - view_menu->set_text("[ " + name + " " + ortho + " ]"); + view_menu->set_text(name + " " + view_mode); else - view_menu->set_text("[ " + ortho + " ]"); + view_menu->set_text(view_mode); view_menu->set_size(Vector2(0, 0)); // resets the button size } @@ -850,11 +847,7 @@ void SpatialEditorViewport::_list_select(Ref<InputEventMouseButton> b) { Spatial *spat = selection_results[i].item; - Ref<Texture> icon; - if (spat->has_meta("_editor_icon")) - icon = spat->get_meta("_editor_icon"); - else - icon = get_icon(has_icon(spat->get_class(), "EditorIcons") ? spat->get_class() : String("Object"), "EditorIcons"); + Ref<Texture> icon = EditorNode::get_singleton()->get_object_icon(spat, "Node"); String node_path = "/" + root_name + "/" + root_path.rel_path_to(spat->get_path()); @@ -959,8 +952,10 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { if (b->is_pressed()) { int mod = _get_key_modifier(b); - if (mod == _get_key_modifier_setting("editors/3d/freelook/freelook_activation_modifier")) { - set_freelook_active(true); + if (!orthogonal) { + if (mod == _get_key_modifier_setting("editors/3d/freelook/freelook_activation_modifier")) { + set_freelook_active(true); + } } } else { set_freelook_active(false); @@ -1004,6 +999,10 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { set_message(TTR("View Plane Transform."), 2); } break; + case TRANSFORM_YZ: + case TRANSFORM_XZ: + case TRANSFORM_XY: { + } break; } } } break; @@ -1137,7 +1136,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { } if (clicked) { _select_clicked(clicked_wants_append, true); - //clickd processing was deferred + // Processing was deferred. clicked = 0; } @@ -1244,7 +1243,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { if (!clicked_includes_current) { _select_clicked(clicked_wants_append, true); - //clickd processing was deferred + // Processing was deferred. } _compute_edit(_edit.mouse_pos); @@ -1342,7 +1341,8 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { List<Node *> &selection = editor_selection->get_selected_node_list(); - bool local_coords = (spatial_editor->are_local_coords_enabled() && _edit.plane != TRANSFORM_VIEW); // Disable local transformation for TRANSFORM_VIEW + // Disable local transformation for TRANSFORM_VIEW + bool local_coords = (spatial_editor->are_local_coords_enabled() && _edit.plane != TRANSFORM_VIEW); float snap = 0; if (_edit.snap || spatial_editor->is_snap_enabled()) { @@ -1471,7 +1471,8 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { List<Node *> &selection = editor_selection->get_selected_node_list(); - bool local_coords = (spatial_editor->are_local_coords_enabled() && _edit.plane != TRANSFORM_VIEW); // Disable local transformation for TRANSFORM_VIEW + // Disable local transformation for TRANSFORM_VIEW + bool local_coords = (spatial_editor->are_local_coords_enabled() && _edit.plane != TRANSFORM_VIEW); float snap = 0; if (_edit.snap || spatial_editor->is_snap_enabled()) { @@ -1552,6 +1553,10 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { plane = Plane(_edit.center, spatial_editor->get_gizmo_transform().basis.get_axis(2)); axis = Vector3(0, 0, 1); break; + case TRANSFORM_YZ: + case TRANSFORM_XZ: + case TRANSFORM_XY: + break; } Vector3 intersection; @@ -1642,6 +1647,8 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { nav_mode = NAVIGATION_ZOOM; } else if (freelook_active) { nav_mode = NAVIGATION_LOOK; + } else if (orthogonal) { + nav_mode = NAVIGATION_PAN; } } else if (m->get_button_mask() & BUTTON_MASK_MIDDLE) { @@ -1792,7 +1799,8 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { if (ED_IS_SHORTCUT("spatial_editor/focus_selection", p_event)) { _menu_option(VIEW_CENTER_TO_SELECTION); } - if (ED_IS_SHORTCUT("spatial_editor/switch_perspective_orthogonal", p_event)) { + // Orthgonal mode doesn't work in freelook. + if (!freelook_active && ED_IS_SHORTCUT("spatial_editor/switch_perspective_orthogonal", p_event)) { _menu_option(orthogonal ? VIEW_PERSPECTIVE : VIEW_ORTHOGONAL); _update_name(); } @@ -1822,7 +1830,8 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { set_message(TTR("Animation Key Inserted.")); } - if (ED_IS_SHORTCUT("spatial_editor/freelook_toggle", p_event)) { + // Freelook doesn't work in orthogonal mode. + if (!orthogonal && ED_IS_SHORTCUT("spatial_editor/freelook_toggle", p_event)) { set_freelook_active(!is_freelook_active()); } else if (k->get_scancode() == KEY_ESCAPE) { @@ -1892,7 +1901,7 @@ void SpatialEditorViewport::_nav_orbit(Ref<InputEventWithModifiers> p_event, con real_t degrees_per_pixel = EditorSettings::get_singleton()->get("editors/3d/navigation_feel/orbit_sensitivity"); real_t radians_per_pixel = Math::deg2rad(degrees_per_pixel); - bool invert_y_axis = EditorSettings::get_singleton()->get("editors/3d/navigation/invert_y-axis"); + bool invert_y_axis = EditorSettings::get_singleton()->get("editors/3d/navigation/invert_y_axis"); if (invert_y_axis) { cursor.x_rot -= p_relative.y * radians_per_pixel; @@ -1910,37 +1919,38 @@ void SpatialEditorViewport::_nav_orbit(Ref<InputEventWithModifiers> p_event, con void SpatialEditorViewport::_nav_look(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative) { - // Freelook only works properly in perspective. - // It technically works too in ortho, but it's awful for a user due to fov being near zero - if (!orthogonal) { - real_t degrees_per_pixel = EditorSettings::get_singleton()->get("editors/3d/navigation_feel/orbit_sensitivity"); - real_t radians_per_pixel = Math::deg2rad(degrees_per_pixel); - bool invert_y_axis = EditorSettings::get_singleton()->get("editors/3d/navigation/invert_y-axis"); - - // Note: do NOT assume the camera has the "current" transform, because it is interpolated and may have "lag". - Transform prev_camera_transform = to_camera_transform(cursor); + if (orthogonal) { + _nav_pan(p_event, p_relative); + return; + } - if (invert_y_axis) { - cursor.x_rot -= p_relative.y * radians_per_pixel; - } else { - cursor.x_rot += p_relative.y * radians_per_pixel; - } - cursor.y_rot += p_relative.x * radians_per_pixel; - if (cursor.x_rot > Math_PI / 2.0) - cursor.x_rot = Math_PI / 2.0; - if (cursor.x_rot < -Math_PI / 2.0) - cursor.x_rot = -Math_PI / 2.0; + real_t degrees_per_pixel = EditorSettings::get_singleton()->get("editors/3d/navigation_feel/orbit_sensitivity"); + real_t radians_per_pixel = Math::deg2rad(degrees_per_pixel); + bool invert_y_axis = EditorSettings::get_singleton()->get("editors/3d/navigation/invert_y_axis"); - // Look is like the opposite of Orbit: the focus point rotates around the camera - Transform camera_transform = to_camera_transform(cursor); - Vector3 pos = camera_transform.xform(Vector3(0, 0, 0)); - Vector3 prev_pos = prev_camera_transform.xform(Vector3(0, 0, 0)); - Vector3 diff = prev_pos - pos; - cursor.pos += diff; + // Note: do NOT assume the camera has the "current" transform, because it is interpolated and may have "lag". + Transform prev_camera_transform = to_camera_transform(cursor); - name = ""; - _update_name(); + if (invert_y_axis) { + cursor.x_rot -= p_relative.y * radians_per_pixel; + } else { + cursor.x_rot += p_relative.y * radians_per_pixel; } + cursor.y_rot += p_relative.x * radians_per_pixel; + if (cursor.x_rot > Math_PI / 2.0) + cursor.x_rot = Math_PI / 2.0; + if (cursor.x_rot < -Math_PI / 2.0) + cursor.x_rot = -Math_PI / 2.0; + + // Look is like the opposite of Orbit: the focus point rotates around the camera + Transform camera_transform = to_camera_transform(cursor); + Vector3 pos = camera_transform.xform(Vector3(0, 0, 0)); + Vector3 prev_pos = prev_camera_transform.xform(Vector3(0, 0, 0)); + Vector3 diff = prev_pos - pos; + cursor.pos += diff; + + name = ""; + _update_name(); } void SpatialEditorViewport::set_freelook_active(bool active_now) { @@ -2082,7 +2092,7 @@ void SpatialEditorViewport::set_message(String p_message, float p_time) { } void SpatialEditorPlugin::edited_scene_changed() { - for (int i = 0; i < SpatialEditor::VIEWPORTS_COUNT; i++) { + for (uint32_t i = 0; i < SpatialEditor::VIEWPORTS_COUNT; i++) { SpatialEditorViewport *viewport = SpatialEditor::get_singleton()->get_editor_viewport(i); if (viewport->is_visible()) { viewport->notification(Control::NOTIFICATION_VISIBILITY_CHANGED); @@ -2123,7 +2133,7 @@ void SpatialEditorViewport::_notification(int p_what) { _update_freelook(delta); Node *scene_root = editor->get_scene_tree_dock()->get_editor_data()->get_edited_scene_root(); - if (previewing_cinema == true && scene_root != NULL) { + if (previewing_cinema && scene_root != NULL) { Camera *cam = scene_root->get_viewport()->get_camera(); if (cam != NULL && cam != previewing) { //then switch the viewport's camera to the scene's viewport camera @@ -2206,7 +2216,7 @@ void SpatialEditorViewport::_notification(int p_what) { bool shrink = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_HALF_RESOLUTION)); - if (shrink != viewport_container->get_stretch_shrink() > 1) { + if (shrink != (viewport_container->get_stretch_shrink() > 1)) { viewport_container->set_stretch_shrink(shrink ? 2 : 1); } @@ -2221,8 +2231,21 @@ void SpatialEditorViewport::_notification(int p_what) { bool show_info = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_INFORMATION)); info_label->set_visible(show_info); + Camera *current_camera; + + if (previewing) { + current_camera = previewing; + } else { + current_camera = camera; + } + if (show_info) { String text; + text += "X: " + rtos(current_camera->get_translation().x).pad_decimals(1) + "\n"; + text += "Y: " + rtos(current_camera->get_translation().y).pad_decimals(1) + "\n"; + text += "Z: " + rtos(current_camera->get_translation().z).pad_decimals(1) + "\n"; + text += TTR("Pitch") + ": " + itos(Math::round(current_camera->get_rotation_degrees().x)) + "\n"; + text += TTR("Yaw") + ": " + itos(Math::round(current_camera->get_rotation_degrees().y)) + "\n\n"; text += TTR("Objects Drawn") + ": " + itos(viewport->get_render_info(Viewport::RENDER_INFO_OBJECTS_IN_FRAME)) + "\n"; text += TTR("Material Changes") + ": " + itos(viewport->get_render_info(Viewport::RENDER_INFO_MATERIAL_CHANGES_IN_FRAME)) + "\n"; text += TTR("Shader Changes") + ": " + itos(viewport->get_render_info(Viewport::RENDER_INFO_SHADER_CHANGES_IN_FRAME)) + "\n"; @@ -2249,6 +2272,11 @@ void SpatialEditorViewport::_notification(int p_what) { float cinema_half_width = cinema_label->get_size().width / 2.0f; cinema_label->set_anchor_and_margin(MARGIN_LEFT, 0.5f, -cinema_half_width); } + + if (lock_rotation) { + float locked_half_width = locked_label->get_size().width / 2.0f; + locked_label->set_anchor_and_margin(MARGIN_LEFT, 0.5f, -locked_half_width); + } } if (p_what == NOTIFICATION_ENTER_TREE) { @@ -2259,21 +2287,36 @@ void SpatialEditorViewport::_notification(int p_what) { surface->connect("mouse_exited", this, "_surface_mouse_exit"); surface->connect("focus_entered", this, "_surface_focus_enter"); surface->connect("focus_exited", this, "_surface_focus_exit"); - info_label->add_style_override("normal", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); - fps_label->add_style_override("normal", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); - cinema_label->add_style_override("normal", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); - preview_camera->set_icon(get_icon("Camera", "EditorIcons")); + _init_gizmo_instance(index); } + if (p_what == NOTIFICATION_EXIT_TREE) { _finish_gizmo_instances(); } - if (p_what == NOTIFICATION_MOUSE_ENTER) { - } + if (p_what == NOTIFICATION_THEME_CHANGED) { - if (p_what == NOTIFICATION_DRAW) { + view_menu->set_icon(get_icon("GuiMiniTabMenu", "EditorIcons")); + preview_camera->set_icon(get_icon("Camera", "EditorIcons")); + + view_menu->add_style_override("normal", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); + view_menu->add_style_override("hover", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); + view_menu->add_style_override("pressed", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); + view_menu->add_style_override("focus", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); + view_menu->add_style_override("disabled", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); + + preview_camera->add_style_override("normal", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); + preview_camera->add_style_override("hover", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); + preview_camera->add_style_override("pressed", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); + preview_camera->add_style_override("focus", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); + preview_camera->add_style_override("disabled", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); + + info_label->add_style_override("normal", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); + fps_label->add_style_override("normal", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); + cinema_label->add_style_override("normal", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); + locked_label->add_style_override("normal", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); } } @@ -2319,12 +2362,12 @@ void SpatialEditorViewport::_draw() { EditorPluginList *over_plugin_list = EditorNode::get_singleton()->get_editor_plugins_over(); if (!over_plugin_list->empty()) { - over_plugin_list->forward_draw_over_viewport(surface); + over_plugin_list->forward_spatial_draw_over_viewport(surface); } EditorPluginList *force_over_plugin_list = editor->get_editor_plugins_force_over(); if (!force_over_plugin_list->empty()) { - force_over_plugin_list->forward_force_draw_over_viewport(surface); + force_over_plugin_list->forward_spatial_force_draw_over_viewport(surface); } if (surface->has_focus()) { @@ -2353,7 +2396,6 @@ void SpatialEditorViewport::_draw() { Point2 center = _point_to_screen(_edit.center); VisualServer::get_singleton()->canvas_item_add_line(ci, _edit.mouse_pos, center, Color(0.4, 0.7, 1.0, 0.8)); } - if (previewing) { Size2 ss = Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height")); @@ -2515,8 +2557,14 @@ void SpatialEditorViewport::_menu_option(int p_option) { if (!se) continue; - Transform xform = camera_transform; - xform.scale_basis(sp->get_scale()); + Transform xform; + if (orthogonal) { + xform = sp->get_global_transform(); + xform.basis.set_euler(camera_transform.basis.get_euler()); + } else { + xform = camera_transform; + xform.scale_basis(sp->get_scale()); + } undo_redo->add_do_method(sp, "set_global_transform", xform); undo_redo->add_undo_method(sp, "set_global_transform", sp->get_global_gizmo_transform()); @@ -2564,9 +2612,9 @@ void SpatialEditorViewport::_menu_option(int p_option) { lock_rotation = !current; view_menu->get_popup()->set_item_checked(idx, !current); if (lock_rotation) { - view_menu->set_icon(get_icon("Lock", "EditorIcons")); + locked_label->show(); } else { - view_menu->set_icon(Ref<Texture>()); + locked_label->hide(); } } break; @@ -2636,11 +2684,6 @@ void SpatialEditorViewport::_menu_option(int p_option) { bool current = view_menu->get_popup()->is_item_checked(idx); view_menu->get_popup()->set_item_checked(idx, !current); - if (current) - preview_camera->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 10 * EDSCALE); - else - preview_camera->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 15 * EDSCALE + fps_label->get_size().height); - } break; case VIEW_DISPLAY_NORMAL: { @@ -2754,7 +2797,7 @@ void SpatialEditorViewport::_toggle_camera_preview(bool p_activate) { VS::get_singleton()->viewport_attach_camera(viewport->get_viewport_rid(), camera->get_camera()); //restore if (!preview) preview_camera->hide(); - view_menu->show(); + view_menu->set_disabled(false); surface->update(); } else { @@ -2762,7 +2805,7 @@ void SpatialEditorViewport::_toggle_camera_preview(bool p_activate) { previewing = preview; previewing->connect("tree_exiting", this, "_preview_exited_scene"); VS::get_singleton()->viewport_attach_camera(viewport->get_viewport_rid(), preview->get_camera()); //replace - view_menu->hide(); + view_menu->set_disabled(true); surface->update(); } } @@ -3274,7 +3317,6 @@ void SpatialEditorViewport::_perform_drop_data() { files_str += error_files[i].get_file().get_basename() + ","; } files_str = files_str.substr(0, files_str.length() - 1); - accept->get_ok()->set_text(TTR("OK")); accept->set_text(vformat(TTR("Error instancing scene from %s"), files_str.c_str())); accept->popup_centered_minsize(); } @@ -3355,7 +3397,6 @@ void SpatialEditorViewport::drop_data_fw(const Point2 &p_point, const Variant &p if (root_node) { list.push_back(root_node); } else { - accept->get_ok()->set_text(TTR("OK")); accept->set_text(TTR("No parent to instance a child at.")); accept->popup_centered_minsize(); _remove_preview(); @@ -3363,7 +3404,6 @@ void SpatialEditorViewport::drop_data_fw(const Point2 &p_point, const Variant &p } } if (list.size() != 1) { - accept->get_ok()->set_text(TTR("OK")); accept->set_text(TTR("This operation requires a single selected node.")); accept->popup_centered_minsize(); _remove_preview(); @@ -3422,9 +3462,10 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed surface->set_focus_mode(FOCUS_ALL); view_menu = memnew(MenuButton); + view_menu->set_flat(false); surface->add_child(view_menu); - view_menu->set_position(Point2(4, 4) * EDSCALE); - view_menu->set_self_modulate(Color(1, 1, 1, 0.5)); + view_menu->set_position(Point2(10, 10) * EDSCALE); + view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/top_view"), VIEW_TOP); view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/bottom_view"), VIEW_BOTTOM); view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/left_view"), VIEW_LEFT); @@ -3475,12 +3516,8 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed ED_SHORTCUT("spatial_editor/freelook_down", TTR("Freelook Down"), KEY_Q); ED_SHORTCUT("spatial_editor/freelook_speed_modifier", TTR("Freelook Speed Modifier"), KEY_SHIFT); - preview_camera = memnew(Button); - preview_camera->set_toggle_mode(true); - preview_camera->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, -90 * EDSCALE); - preview_camera->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 10 * EDSCALE); - preview_camera->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, -10 * EDSCALE); - preview_camera->set_h_grow_direction(GROW_DIRECTION_BEGIN); + preview_camera = memnew(CheckBox); + preview_camera->set_position(Point2(10, 38) * EDSCALE); // Below the 'view_menu' MenuButton. preview_camera->set_text(TTR("Preview")); surface->add_child(preview_camera); preview_camera->hide(); @@ -3500,7 +3537,6 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed surface->add_child(info_label); info_label->hide(); - // FPS Counter. fps_label = memnew(Label); fps_label->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, -90 * EDSCALE); fps_label->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 10 * EDSCALE); @@ -3518,6 +3554,16 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed cinema_label->hide(); previewing_cinema = false; + locked_label = memnew(Label); + locked_label->set_anchor_and_margin(MARGIN_TOP, ANCHOR_END, -20 * EDSCALE); + locked_label->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, -10 * EDSCALE); + locked_label->set_h_grow_direction(GROW_DIRECTION_END); + locked_label->set_v_grow_direction(GROW_DIRECTION_BEGIN); + locked_label->set_align(Label::ALIGN_CENTER); + surface->add_child(locked_label); + locked_label->set_text(TTR("View Rotation Locked")); + locked_label->hide(); + accept = NULL; freelook_active = false; @@ -3546,69 +3592,77 @@ void SpatialEditorViewportContainer::_gui_input(const Ref<InputEvent> &p_event) Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT) { - Vector2 size = get_size(); + if (mb->is_pressed()) { + Vector2 size = get_size(); - int h_sep = get_constant("separation", "HSplitContainer"); - int v_sep = get_constant("separation", "VSplitContainer"); + int h_sep = get_constant("separation", "HSplitContainer"); + int v_sep = get_constant("separation", "VSplitContainer"); - int mid_w = size.width * ratio_h; - int mid_h = size.height * ratio_v; + int mid_w = size.width * ratio_h; + int mid_h = size.height * ratio_v; - dragging_h = mb->get_position().x > (mid_w - h_sep / 2) && mb->get_position().x < (mid_w + h_sep / 2); - dragging_v = mb->get_position().y > (mid_h - v_sep / 2) && mb->get_position().y < (mid_h + v_sep / 2); + dragging_h = mb->get_position().x > (mid_w - h_sep / 2) && mb->get_position().x < (mid_w + h_sep / 2); + dragging_v = mb->get_position().y > (mid_h - v_sep / 2) && mb->get_position().y < (mid_h + v_sep / 2); - drag_begin_pos = mb->get_position(); - drag_begin_ratio.x = ratio_h; - drag_begin_ratio.y = ratio_v; + drag_begin_pos = mb->get_position(); + drag_begin_ratio.x = ratio_h; + drag_begin_ratio.y = ratio_v; - switch (view) { - case VIEW_USE_1_VIEWPORT: { - - dragging_h = false; - dragging_v = false; - - } break; - case VIEW_USE_2_VIEWPORTS: { + switch (view) { + case VIEW_USE_1_VIEWPORT: { - dragging_h = false; + dragging_h = false; + dragging_v = false; - } break; - case VIEW_USE_2_VIEWPORTS_ALT: { + } break; + case VIEW_USE_2_VIEWPORTS: { - dragging_v = false; + dragging_h = false; - } break; - case VIEW_USE_3_VIEWPORTS: { + } break; + case VIEW_USE_2_VIEWPORTS_ALT: { - if (dragging_v) - dragging_h = false; - else dragging_v = false; - } break; - case VIEW_USE_3_VIEWPORTS_ALT: { + } break; + case VIEW_USE_3_VIEWPORTS: + case VIEW_USE_3_VIEWPORTS_ALT: + case VIEW_USE_4_VIEWPORTS: { - if (dragging_h) - dragging_v = false; - else - dragging_h = false; - } break; - case VIEW_USE_4_VIEWPORTS: { + // Do nothing. - } break; + } break; + } + } else { + dragging_h = false; + dragging_v = false; } } - if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { - dragging_h = false; - dragging_v = false; - } - Ref<InputEventMouseMotion> mm = p_event; - if (mm.is_valid() && (dragging_h || dragging_v)) { + if (mm.is_valid()) { + + if (view == VIEW_USE_3_VIEWPORTS || view == VIEW_USE_3_VIEWPORTS_ALT || view == VIEW_USE_4_VIEWPORTS) { + Vector2 size = get_size(); + + int h_sep = get_constant("separation", "HSplitContainer"); + int v_sep = get_constant("separation", "VSplitContainer"); + + int mid_w = size.width * ratio_h; + int mid_h = size.height * ratio_v; + + bool was_hovering_h = hovering_h; + bool was_hovering_v = hovering_v; + hovering_h = mm->get_position().x > (mid_w - h_sep / 2) && mm->get_position().x < (mid_w + h_sep / 2); + hovering_v = mm->get_position().y > (mid_h - v_sep / 2) && mm->get_position().y < (mid_h + v_sep / 2); + + if (was_hovering_h != hovering_h || was_hovering_v != hovering_v) { + update(); + } + } if (dragging_h) { float new_ratio = drag_begin_ratio.x + (mm->get_position().x - drag_begin_pos.x) / get_size().width; @@ -3638,9 +3692,12 @@ void SpatialEditorViewportContainer::_notification(int p_what) { if (p_what == NOTIFICATION_DRAW && mouseover) { Ref<Texture> h_grabber = get_icon("grabber", "HSplitContainer"); - Ref<Texture> v_grabber = get_icon("grabber", "VSplitContainer"); + Ref<Texture> hdiag_grabber = get_icon("GuiViewportHdiagsplitter", "EditorIcons"); + Ref<Texture> vdiag_grabber = get_icon("GuiViewportVdiagsplitter", "EditorIcons"); + Ref<Texture> vh_grabber = get_icon("GuiViewportVhsplitter", "EditorIcons"); + Vector2 size = get_size(); int h_sep = get_constant("separation", "HSplitContainer"); @@ -3657,35 +3714,62 @@ void SpatialEditorViewportContainer::_notification(int p_what) { case VIEW_USE_1_VIEWPORT: { - //nothing to show + // Nothing to show. } break; case VIEW_USE_2_VIEWPORTS: { draw_texture(v_grabber, Vector2((size.width - v_grabber->get_width()) / 2, mid_h - v_grabber->get_height() / 2)); + set_default_cursor_shape(CURSOR_VSPLIT); } break; case VIEW_USE_2_VIEWPORTS_ALT: { draw_texture(h_grabber, Vector2(mid_w - h_grabber->get_width() / 2, (size.height - h_grabber->get_height()) / 2)); + set_default_cursor_shape(CURSOR_HSPLIT); } break; case VIEW_USE_3_VIEWPORTS: { - draw_texture(v_grabber, Vector2((size.width - v_grabber->get_width()) / 2, mid_h - v_grabber->get_height() / 2)); - draw_texture(h_grabber, Vector2(mid_w - h_grabber->get_width() / 2, mid_h + v_grabber->get_height() / 2 + (size_bottom - h_grabber->get_height()) / 2)); + if ((hovering_v && hovering_h && !dragging_v && !dragging_h) || (dragging_v && dragging_h)) { + draw_texture(hdiag_grabber, Vector2(mid_w - hdiag_grabber->get_width() / 2, mid_h - v_grabber->get_height() / 4)); + set_default_cursor_shape(CURSOR_DRAG); + } else if ((hovering_v && !dragging_h) || dragging_v) { + draw_texture(v_grabber, Vector2((size.width - v_grabber->get_width()) / 2, mid_h - v_grabber->get_height() / 2)); + set_default_cursor_shape(CURSOR_VSPLIT); + } else if (hovering_h || dragging_h) { + draw_texture(h_grabber, Vector2(mid_w - h_grabber->get_width() / 2, mid_h + v_grabber->get_height() / 2 + (size_bottom - h_grabber->get_height()) / 2)); + set_default_cursor_shape(CURSOR_HSPLIT); + } } break; case VIEW_USE_3_VIEWPORTS_ALT: { - draw_texture(v_grabber, Vector2((size_left - v_grabber->get_width()) / 2, mid_h - v_grabber->get_height() / 2)); - draw_texture(h_grabber, Vector2(mid_w - h_grabber->get_width() / 2, (size.height - h_grabber->get_height()) / 2)); + if ((hovering_v && hovering_h && !dragging_v && !dragging_h) || (dragging_v && dragging_h)) { + draw_texture(vdiag_grabber, Vector2(mid_w - vdiag_grabber->get_width() + v_grabber->get_height() / 4, mid_h - vdiag_grabber->get_height() / 2)); + set_default_cursor_shape(CURSOR_DRAG); + } else if ((hovering_v && !dragging_h) || dragging_v) { + draw_texture(v_grabber, Vector2((size_left - v_grabber->get_width()) / 2, mid_h - v_grabber->get_height() / 2)); + set_default_cursor_shape(CURSOR_VSPLIT); + } else if (hovering_h || dragging_h) { + draw_texture(h_grabber, Vector2(mid_w - h_grabber->get_width() / 2, (size.height - h_grabber->get_height()) / 2)); + set_default_cursor_shape(CURSOR_HSPLIT); + } + } break; case VIEW_USE_4_VIEWPORTS: { Vector2 half(mid_w, mid_h); - draw_texture(v_grabber, half - v_grabber->get_size() / 2.0); - draw_texture(h_grabber, half - h_grabber->get_size() / 2.0); + if ((hovering_v && hovering_h && !dragging_v && !dragging_h) || (dragging_v && dragging_h)) { + draw_texture(vh_grabber, half - vh_grabber->get_size() / 2.0); + set_default_cursor_shape(CURSOR_DRAG); + } else if ((hovering_v && !dragging_h) || dragging_v) { + draw_texture(v_grabber, half - v_grabber->get_size() / 2.0); + set_default_cursor_shape(CURSOR_VSPLIT); + } else if (hovering_h || dragging_h) { + draw_texture(h_grabber, half - h_grabber->get_size() / 2.0); + set_default_cursor_shape(CURSOR_HSPLIT); + } } break; } @@ -3729,6 +3813,7 @@ void SpatialEditorViewportContainer::_notification(int p_what) { case VIEW_USE_1_VIEWPORT: { + viewports[0]->show(); for (int i = 1; i < 4; i++) { viewports[i]->hide(); @@ -3739,7 +3824,7 @@ void SpatialEditorViewportContainer::_notification(int p_what) { } break; case VIEW_USE_2_VIEWPORTS: { - for (int i = 1; i < 4; i++) { + for (int i = 0; i < 4; i++) { if (i == 1 || i == 3) viewports[i]->hide(); @@ -3753,7 +3838,7 @@ void SpatialEditorViewportContainer::_notification(int p_what) { } break; case VIEW_USE_2_VIEWPORTS_ALT: { - for (int i = 1; i < 4; i++) { + for (int i = 0; i < 4; i++) { if (i == 1 || i == 3) viewports[i]->hide(); @@ -3766,7 +3851,7 @@ void SpatialEditorViewportContainer::_notification(int p_what) { } break; case VIEW_USE_3_VIEWPORTS: { - for (int i = 1; i < 4; i++) { + for (int i = 0; i < 4; i++) { if (i == 1) viewports[i]->hide(); @@ -3781,7 +3866,7 @@ void SpatialEditorViewportContainer::_notification(int p_what) { } break; case VIEW_USE_3_VIEWPORTS_ALT: { - for (int i = 1; i < 4; i++) { + for (int i = 0; i < 4; i++) { if (i == 1) viewports[i]->hide(); @@ -3796,7 +3881,7 @@ void SpatialEditorViewportContainer::_notification(int p_what) { } break; case VIEW_USE_4_VIEWPORTS: { - for (int i = 1; i < 4; i++) { + for (int i = 0; i < 4; i++) { viewports[i]->show(); } @@ -3829,10 +3914,13 @@ void SpatialEditorViewportContainer::_bind_methods() { SpatialEditorViewportContainer::SpatialEditorViewportContainer() { + set_clip_contents(true); view = VIEW_USE_1_VIEWPORT; mouseover = false; ratio_h = 0.5; ratio_v = 0.5; + hovering_v = false; + hovering_h = false; dragging_v = false; dragging_h = false; } @@ -3914,8 +4002,9 @@ void _update_all_gizmos(Node *p_node) { } } -void SpatialEditor::update_all_gizmos() { - _update_all_gizmos(SceneTree::get_singleton()->get_root()); +void SpatialEditor::update_all_gizmos(Node *p_node) { + if (!p_node) p_node = SceneTree::get_singleton()->get_root(); + _update_all_gizmos(p_node); } Object *SpatialEditor::_get_editor_data(Object *p_what) { @@ -4103,7 +4192,7 @@ void SpatialEditor::set_state(const Dictionary &p_state) { for (int j = 0; j < gizmo_plugins.size(); ++j) { if (!gizmo_plugins[j]->can_be_hidden()) continue; int state = EditorSpatialGizmoPlugin::ON_TOP; - for (uint32_t i = 0; i < keys.size(); i++) { + for (int i = 0; i < keys.size(); i++) { if (gizmo_plugins.write[j]->get_name() == keys[i]) { state = gizmos_status[keys[i]]; } @@ -4115,10 +4204,10 @@ void SpatialEditor::set_state(const Dictionary &p_state) { gizmo_plugins.write[j]->set_state(state); switch (state) { - case EditorSpatialGizmoPlugin::ON_TOP: + case EditorSpatialGizmoPlugin::VISIBLE: gizmos_menu->set_item_icon(idx, gizmos_menu->get_icon("visibility_visible")); break; - case EditorSpatialGizmoPlugin::VISIBLE: + case EditorSpatialGizmoPlugin::ON_TOP: gizmos_menu->set_item_icon(idx, gizmos_menu->get_icon("visibility_xray")); break; case EditorSpatialGizmoPlugin::HIDDEN: @@ -4228,10 +4317,10 @@ void SpatialEditor::_menu_gizmo_toggled(int p_option) { // Change icon const int state = gizmos_menu->get_item_state(idx); switch (state) { - case EditorSpatialGizmoPlugin::ON_TOP: + case EditorSpatialGizmoPlugin::VISIBLE: gizmos_menu->set_item_icon(idx, view_menu->get_popup()->get_icon("visibility_visible")); break; - case EditorSpatialGizmoPlugin::VISIBLE: + case EditorSpatialGizmoPlugin::ON_TOP: gizmos_menu->set_item_icon(idx, view_menu->get_popup()->get_icon("visibility_xray")); break; case EditorSpatialGizmoPlugin::HIDDEN: @@ -4427,6 +4516,8 @@ void SpatialEditor::_menu_item_pressed(int p_option) { void SpatialEditor::_init_indicators() { { + origin_enabled = true; + grid_enabled = true; indicator_mat.instance(); indicator_mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true); @@ -4467,9 +4558,6 @@ void SpatialEditor::_init_indicators() { VS::get_singleton()->instance_set_layer_mask(origin_instance, 1 << SpatialEditorViewport::GIZMO_GRID_LAYER); VisualServer::get_singleton()->instance_geometry_set_cast_shadows_setting(origin_instance, VS::SHADOW_CASTING_SETTING_OFF); - - grid_enabled = true; - last_grid_snap = 1; } { @@ -4751,7 +4839,7 @@ void SpatialEditor::_init_gizmos_menu() { for (int i = 0; i < gizmo_plugins.size(); ++i) { if (!gizmo_plugins[i]->can_be_hidden()) continue; String plugin_name = gizmo_plugins[i]->get_name(); - gizmos_menu->add_multistate_item(TTR(plugin_name), 3, EditorSpatialGizmoPlugin::ON_TOP, i); + gizmos_menu->add_multistate_item(TTR(plugin_name), 3, EditorSpatialGizmoPlugin::VISIBLE, i); gizmos_menu->set_item_icon(gizmos_menu->get_item_index(i), gizmos_menu->get_icon("visibility_visible")); } } @@ -4990,32 +5078,29 @@ void SpatialEditor::_unhandled_key_input(Ref<InputEvent> p_event) { if (!k->is_pressed()) return; - if (ED_IS_SHORTCUT("spatial_editor/tool_select", p_event)) + if (ED_IS_SHORTCUT("spatial_editor/tool_select", p_event)) { _menu_item_pressed(MENU_TOOL_SELECT); - - else if (ED_IS_SHORTCUT("spatial_editor/tool_move", p_event)) + } else if (ED_IS_SHORTCUT("spatial_editor/tool_move", p_event)) { _menu_item_pressed(MENU_TOOL_MOVE); - - else if (ED_IS_SHORTCUT("spatial_editor/tool_rotate", p_event)) + } else if (ED_IS_SHORTCUT("spatial_editor/tool_rotate", p_event)) { _menu_item_pressed(MENU_TOOL_ROTATE); - - else if (ED_IS_SHORTCUT("spatial_editor/tool_scale", p_event)) + } else if (ED_IS_SHORTCUT("spatial_editor/tool_scale", p_event)) { _menu_item_pressed(MENU_TOOL_SCALE); - else if (ED_IS_SHORTCUT("spatial_editor/snap_to_floor", p_event)) + } else if (ED_IS_SHORTCUT("spatial_editor/snap_to_floor", p_event)) { snap_selected_nodes_to_floor(); - - else if (ED_IS_SHORTCUT("spatial_editor/local_coords", p_event)) + } else if (ED_IS_SHORTCUT("spatial_editor/local_coords", p_event)) { if (are_local_coords_enabled()) { _menu_item_toggled(false, MENU_TOOL_LOCAL_COORDS); } else { _menu_item_toggled(true, MENU_TOOL_LOCAL_COORDS); } - else if (ED_IS_SHORTCUT("spatial_editor/snap", p_event)) + } else if (ED_IS_SHORTCUT("spatial_editor/snap", p_event)) { if (is_snap_enabled()) { _menu_item_toggled(false, MENU_TOOL_USE_SNAP); } else { _menu_item_toggled(true, MENU_TOOL_USE_SNAP); } + } } } } @@ -5291,6 +5376,8 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { tool_button[TOOL_MODE_SELECT]->connect("pressed", this, "_menu_item_pressed", button_binds); tool_button[TOOL_MODE_SELECT]->set_tooltip(TTR("Select Mode (Q)") + "\n" + keycode_get_string(KEY_MASK_CMD) + TTR("Drag: Rotate\nAlt+Drag: Move\nAlt+RMB: Depth list selection")); + hbc_menu->add_child(memnew(VSeparator)); + tool_button[TOOL_MODE_MOVE] = memnew(ToolButton); hbc_menu->add_child(tool_button[TOOL_MODE_MOVE]); tool_button[TOOL_MODE_MOVE]->set_toggle_mode(true); @@ -5315,6 +5402,8 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { tool_button[TOOL_MODE_SCALE]->connect("pressed", this, "_menu_item_pressed", button_binds); tool_button[TOOL_MODE_SCALE]->set_tooltip(TTR("Scale Mode (R)")); + hbc_menu->add_child(memnew(VSeparator)); + tool_button[TOOL_MODE_LIST_SELECT] = memnew(ToolButton); hbc_menu->add_child(tool_button[TOOL_MODE_LIST_SELECT]); tool_button[TOOL_MODE_LIST_SELECT]->set_toggle_mode(true); @@ -5335,8 +5424,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { tool_button[TOOL_UNLOCK_SELECTED]->connect("pressed", this, "_menu_item_pressed", button_binds); tool_button[TOOL_UNLOCK_SELECTED]->set_tooltip(TTR("Unlock the selected object (can be moved).")); - VSeparator *vs = memnew(VSeparator); - hbc_menu->add_child(vs); + hbc_menu->add_child(memnew(VSeparator)); tool_option_button[TOOL_OPT_LOCAL_COORDS] = memnew(ToolButton); hbc_menu->add_child(tool_option_button[TOOL_OPT_LOCAL_COORDS]); @@ -5358,8 +5446,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { sct = ED_GET_SHORTCUT("spatial_editor/snap").ptr()->get_as_text(); tool_option_button[TOOL_OPT_USE_SNAP]->set_tooltip(vformat(TTR("Snap Mode (%s)"), sct)); - vs = memnew(VSeparator); - hbc_menu->add_child(vs); + hbc_menu->add_child(memnew(VSeparator)); // Drag and drop support; preview_node = memnew(Spatial); @@ -5381,7 +5468,6 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { ED_SHORTCUT("spatial_editor/tool_move", TTR("Tool Move"), KEY_W); ED_SHORTCUT("spatial_editor/tool_rotate", TTR("Tool Rotate"), KEY_E); ED_SHORTCUT("spatial_editor/tool_scale", TTR("Tool Scale"), KEY_R); - ED_SHORTCUT("spatial_editor/snap_to_floor", TTR("Snap To Floor"), KEY_PAGEDOWN); ED_SHORTCUT("spatial_editor/freelook_toggle", TTR("Toggle Freelook"), KEY_MASK_SHIFT + KEY_F); @@ -5392,7 +5478,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { hbc_menu->add_child(transform_menu); p = transform_menu->get_popup(); - p->add_shortcut(ED_SHORTCUT("spatial_editor/snap_to_floor", TTR("Snap object to floor")), MENU_SNAP_TO_FLOOR); + p->add_shortcut(ED_SHORTCUT("spatial_editor/snap_to_floor", TTR("Snap object to floor"), KEY_PAGEDOWN), MENU_SNAP_TO_FLOOR); p->add_shortcut(ED_SHORTCUT("spatial_editor/configure_snap", TTR("Configure Snap...")), MENU_TRANSFORM_CONFIGURE_SNAP); p->add_separator(); p->add_shortcut(ED_SHORTCUT("spatial_editor/transform_dialog", TTR("Transform Dialog...")), MENU_TRANSFORM_DIALOG); @@ -5401,7 +5487,6 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { view_menu = memnew(MenuButton); view_menu->set_text(TTR("View")); - view_menu->set_position(Point2(212, 0)); hbc_menu->add_child(view_menu); p = view_menu->get_popup(); @@ -5593,7 +5678,6 @@ void SpatialEditorPlugin::make_visible(bool p_visible) { spatial_editor->show(); spatial_editor->set_process(true); - spatial_editor->grab_focus(); } else { @@ -5664,7 +5748,7 @@ SpatialEditorPlugin::~SpatialEditorPlugin() { void EditorSpatialGizmoPlugin::create_material(const String &p_name, const Color &p_color, bool p_billboard, bool p_on_top, bool p_use_vertex_color) { - Color instanced_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/instanced", Color(0.7, 0.7, 0.7, 0.5)); + Color instanced_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/instanced", Color(0.7, 0.7, 0.7, 0.6)); Vector<Ref<SpatialMaterial> > mats; @@ -5706,7 +5790,7 @@ void EditorSpatialGizmoPlugin::create_material(const String &p_name, const Color void EditorSpatialGizmoPlugin::create_icon_material(const String &p_name, const Ref<Texture> &p_texture, bool p_on_top, const Color &p_albedo) { - Color instanced_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/instanced", Color(0.7, 0.7, 0.7, 0.5)); + Color instanced_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/instanced", Color(0.7, 0.7, 0.7, 0.6)); Vector<Ref<SpatialMaterial> > icons; @@ -5719,7 +5803,7 @@ void EditorSpatialGizmoPlugin::create_icon_material(const String &p_name, const Color color = instanced ? instanced_color : p_albedo; if (!selected) { - color.a *= 0.3; + color.a *= 0.85; } icon->set_albedo(color); @@ -5835,7 +5919,7 @@ void EditorSpatialGizmoPlugin::unregister_gizmo(EditorSpatialGizmo *p_gizmo) { } EditorSpatialGizmoPlugin::EditorSpatialGizmoPlugin() { - current_state = ON_TOP; + current_state = VISIBLE; } EditorSpatialGizmoPlugin::~EditorSpatialGizmoPlugin() { diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h index 5850c0dbf1..c515a4aaf9 100644 --- a/editor/plugins/spatial_editor_plugin.h +++ b/editor/plugins/spatial_editor_plugin.h @@ -86,7 +86,7 @@ public: Vector<Vector3> handles; Vector<Vector3> secondary_handles; - float selectable_icon_size = -1.0f; + float selectable_icon_size; bool billboard_handle; bool valid; @@ -127,9 +127,7 @@ public: virtual void redraw(); virtual void free(); - //TODO remove (?) virtual bool is_editable() const; - virtual bool can_draw() const; void set_hidden(bool p_hidden); void set_plugin(EditorSpatialGizmoPlugin *p_gizmo); @@ -194,7 +192,7 @@ private: EditorSelection *editor_selection; UndoRedo *undo_redo; - Button *preview_camera; + CheckBox *preview_camera; ViewportContainer *viewport_container; MenuButton *view_menu; @@ -213,6 +211,7 @@ private: Label *info_label; Label *fps_label; Label *cinema_label; + Label *locked_label; struct _RayResult { @@ -226,7 +225,7 @@ private: void _compute_edit(const Point2 &p_point); void _clear_selected(); void _select_clicked(bool p_append, bool p_single); - void _select(Spatial *p_node, bool p_append, bool p_single); + void _select(Node *p_node, bool p_append, bool p_single); ObjectID _select_ray(const Point2 &p_pos, bool p_append, bool &r_includes_current, int *r_gizmo_handle = NULL, bool p_alt_select = false); void _find_items_at_pos(const Point2 &p_pos, bool &r_includes_current, Vector<_RayResult> &results, bool p_alt_select = false); Vector3 _get_ray_pos(const Vector2 &p_pos) const; @@ -406,6 +405,7 @@ public: AcceptDialog *p_accept); Viewport *get_viewport_node() { return viewport; } + Camera *get_camera() { return camera; } // return the default camera object. SpatialEditorViewport(SpatialEditor *p_spatial_editor, EditorNode *p_editor, int p_index); }; @@ -445,6 +445,9 @@ private: float ratio_h; float ratio_v; + bool hovering_v; + bool hovering_h; + bool dragging_v; bool dragging_h; Vector2 drag_begin_pos; @@ -512,7 +515,6 @@ private: RID grid[3]; RID grid_instance[3]; bool grid_visible[3]; //currently visible - float last_grid_snap; bool grid_enable[3]; //should be always visible if true bool grid_enabled; @@ -677,7 +679,7 @@ public: Ref<ArrayMesh> get_scale_plane_gizmo(int idx) const { return scale_plane_gizmo[idx]; } void update_transform_gizmo(); - void update_all_gizmos(); + void update_all_gizmos(Node *p_node = NULL); void snap_selected_nodes_to_floor(); void select_gizmo_highlight_axis(int p_axis); void set_custom_camera(Node *p_camera) { custom_camera = p_camera; } @@ -710,7 +712,6 @@ public: void register_gizmo_plugin(Ref<EditorSpatialGizmoPlugin> ref); - Camera *get_camera() { return NULL; } void edit(Spatial *p_spatial); void clear(); @@ -753,9 +754,9 @@ class EditorSpatialGizmoPlugin : public Resource { GDCLASS(EditorSpatialGizmoPlugin, Resource); public: - static const int ON_TOP = 0; - static const int VISIBLE = 1; - static const int HIDDEN = 2; + static const int VISIBLE = 0; + static const int HIDDEN = 1; + static const int ON_TOP = 2; private: int current_state; diff --git a/editor/plugins/sprite_editor_plugin.cpp b/editor/plugins/sprite_editor_plugin.cpp index 58a1835e68..c574b5e8ba 100644 --- a/editor/plugins/sprite_editor_plugin.cpp +++ b/editor/plugins/sprite_editor_plugin.cpp @@ -97,7 +97,7 @@ Vector<Vector2> expand(const Vector<Vector2> &points, const Rect2i &rect, float int lasti = p2->Contour.size() - 1; Vector2 prev = Vector2(p2->Contour[lasti].X / PRECISION, p2->Contour[lasti].Y / PRECISION); - for (int i = 0; i < p2->Contour.size(); i++) { + for (unsigned int i = 0; i < p2->Contour.size(); i++) { Vector2 cur = Vector2(p2->Contour[i].X / PRECISION, p2->Contour[i].Y / PRECISION); if (cur.distance_to(prev) > 0.5) { diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index fcbbee2b9c..40781908fd 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -30,9 +30,9 @@ #include "sprite_frames_editor_plugin.h" +#include "core/io/resource_loader.h" +#include "core/project_settings.h" #include "editor/editor_settings.h" -#include "io/resource_loader.h" -#include "project_settings.h" #include "scene/3d/sprite_3d.h" void SpriteFramesEditor::_gui_input(Ref<InputEvent> p_event) { @@ -548,7 +548,6 @@ void SpriteFramesEditor::edit(SpriteFrames *p_frames) { } else { hide(); - //set_physics_process(false); } } @@ -816,16 +815,26 @@ SpriteFramesEditor::SpriteFramesEditor() { void SpriteFramesEditorPlugin::edit(Object *p_object) { frames_editor->set_undo_redo(&get_undo_redo()); - SpriteFrames *s = Object::cast_to<SpriteFrames>(p_object); - if (!s) - return; + + SpriteFrames *s; + AnimatedSprite *animated_sprite = Object::cast_to<AnimatedSprite>(p_object); + if (animated_sprite) { + s = *animated_sprite->get_sprite_frames(); + } else { + s = Object::cast_to<SpriteFrames>(p_object); + } frames_editor->edit(s); } bool SpriteFramesEditorPlugin::handles(Object *p_object) const { - return p_object->is_class("SpriteFrames"); + AnimatedSprite *animated_sprite = Object::cast_to<AnimatedSprite>(p_object); + if (animated_sprite && *animated_sprite->get_sprite_frames()) { + return true; + } else { + return p_object->is_class("SpriteFrames"); + } } void SpriteFramesEditorPlugin::make_visible(bool p_visible) { @@ -833,14 +842,11 @@ void SpriteFramesEditorPlugin::make_visible(bool p_visible) { if (p_visible) { button->show(); editor->make_bottom_panel_item_visible(frames_editor); - //frames_editor->set_process(true); } else { button->hide(); if (frames_editor->is_visible_in_tree()) editor->hide_bottom_panel(); - - //frames_editor->set_process(false); } } diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp index 16c25f3074..4a8eae1ba4 100644 --- a/editor/plugins/text_editor.cpp +++ b/editor/plugins/text_editor.cpp @@ -30,6 +30,8 @@ #include "text_editor.h" +#include "editor_node.h" + void TextEditor::add_syntax_highlighter(SyntaxHighlighter *p_highlighter) { highlighters[p_highlighter->get_name()] = p_highlighter; highlighter_menu->add_radio_check_item(p_highlighter->get_name()); @@ -64,6 +66,7 @@ void TextEditor::_change_syntax_highlighter(int p_idx) { el = el->next(); } set_syntax_highlighter(highlighters[highlighter_menu->get_item_text(p_idx)]); + EditorSettings::get_singleton()->set_project_metadata("text_editor", "syntax_highlighter", p_idx); } void TextEditor::_load_theme_settings() { @@ -128,7 +131,7 @@ void TextEditor::_load_theme_settings() { text_edit->add_color_override("search_result_border_color", search_result_border_color); text_edit->add_color_override("symbol_color", symbol_color); - text_edit->add_constant_override("line_spacing", EDITOR_DEF("text_editor/theme/line_spacing", 4)); + text_edit->add_constant_override("line_spacing", EDITOR_DEF("text_editor/theme/line_spacing", 6)); colors_cache.font_color = text_color; colors_cache.symbol_color = symbol_color; @@ -158,10 +161,7 @@ String TextEditor::get_name() { Ref<Texture> TextEditor::get_icon() { - if (get_parent_control() && get_parent_control()->has_icon(text_file->get_class(), "EditorIcons")) { - return get_parent_control()->get_icon(text_file->get_class(), "EditorIcons"); - } - return Ref<Texture>(); + return EditorNode::get_singleton()->get_object_icon(text_file.operator->(), ""); } RES TextEditor::get_edited_resource() const { @@ -299,7 +299,7 @@ void TextEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_READY: _load_theme_settings(); - set_syntax_highlighter(NULL); + _change_syntax_highlighter(EditorSettings::get_singleton()->get_project_metadata("text_editor", "syntax_highlighter", 0)); break; } } @@ -360,7 +360,7 @@ void TextEditor::_edit_option(int p_op) { } break; case EDIT_CLONE_DOWN: { - code_editor->code_lines_down(); + code_editor->clone_lines_down(); } break; case EDIT_TOGGLE_FOLD_LINE: { @@ -475,7 +475,7 @@ void TextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { int to_column = tx->get_selection_to_column(); if (row < from_line || row > to_line || (row == from_line && col < from_column) || (row == to_line && col > to_column)) { - // Right click is outside the seleted text + // Right click is outside the selected text tx->deselect(); } } diff --git a/editor/plugins/texture_editor_plugin.cpp b/editor/plugins/texture_editor_plugin.cpp index e891850870..140d37fdb5 100644 --- a/editor/plugins/texture_editor_plugin.cpp +++ b/editor/plugins/texture_editor_plugin.cpp @@ -30,9 +30,9 @@ #include "texture_editor_plugin.h" +#include "core/io/resource_loader.h" +#include "core/project_settings.h" #include "editor/editor_settings.h" -#include "io/resource_loader.h" -#include "project_settings.h" void TextureEditor::_gui_input(Ref<InputEvent> p_event) { } diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index 4390b94ece..7c3e524d89 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -31,8 +31,8 @@ #include "texture_region_editor_plugin.h" #include "core/core_string_names.h" -#include "os/input.h" -#include "os/keyboard.h" +#include "core/os/input.h" +#include "core/os/keyboard.h" #include "scene/gui/check_box.h" /** @@ -846,7 +846,8 @@ TextureRegionEditor::TextureRegionEditor(EditorNode *p_editor) { p->set_item_checked(0, true); p->connect("id_pressed", this, "_set_snap_mode"); hb_grid = memnew(HBoxContainer); - hb_tools->add_child(hb_grid); + //hb_tools->add_child(hb_grid); + main_vb->add_child(hb_grid); hb_grid->add_child(memnew(VSeparator)); hb_grid->add_child(memnew(Label(TTR("Offset:")))); diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index 92b95963f9..acee1a6942 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -30,8 +30,8 @@ #include "theme_editor_plugin.h" -#include "os/file_access.h" -#include "version.h" +#include "core/os/file_access.h" +#include "core/version.h" void ThemeEditor::edit(const Ref<Theme> &p_theme) { diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp index 598f7034d8..213cd2ce1a 100644 --- a/editor/plugins/tile_map_editor_plugin.cpp +++ b/editor/plugins/tile_map_editor_plugin.cpp @@ -31,10 +31,11 @@ #include "tile_map_editor_plugin.h" #include "canvas_item_editor_plugin.h" +#include "core/math/math_funcs.h" +#include "core/os/input.h" +#include "core/os/keyboard.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" -#include "os/input.h" -#include "os/keyboard.h" #include "scene/gui/split_container.h" void TileMapEditor::_notification(int p_what) { @@ -43,8 +44,8 @@ void TileMapEditor::_notification(int p_what) { case NOTIFICATION_PROCESS: { - if (bucket_queue.size() && canvas_item_editor) { - canvas_item_editor->update(); + if (bucket_queue.size()) { + CanvasItemEditor::get_singleton()->update_viewport(); } } break; @@ -65,13 +66,11 @@ void TileMapEditor::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { - transp->set_icon(get_icon("Transpose", "EditorIcons")); - mirror_x->set_icon(get_icon("MirrorX", "EditorIcons")); - mirror_y->set_icon(get_icon("MirrorY", "EditorIcons")); - rotate_0->set_icon(get_icon("Rotate0", "EditorIcons")); - rotate_90->set_icon(get_icon("Rotate90", "EditorIcons")); - rotate_180->set_icon(get_icon("Rotate180", "EditorIcons")); - rotate_270->set_icon(get_icon("Rotate270", "EditorIcons")); + rotate_left_button->set_icon(get_icon("Rotate270", "EditorIcons")); + rotate_right_button->set_icon(get_icon("Rotate90", "EditorIcons")); + flip_horizontal_button->set_icon(get_icon("MirrorX", "EditorIcons")); + flip_vertical_button->set_icon(get_icon("MirrorY", "EditorIcons")); + clear_transform_button->set_icon(get_icon("Clear", "EditorIcons")); search_box->set_right_icon(get_icon("Search", "EditorIcons")); search_box->set_clear_button_enabled(true); @@ -97,27 +96,27 @@ void TileMapEditor::_menu_option(int p_option) { // immediately without pressing the left mouse button first tool = TOOL_NONE; - canvas_item_editor->update(); + CanvasItemEditor::get_singleton()->update_viewport(); } break; case OPTION_BUCKET: { tool = TOOL_BUCKET; - canvas_item_editor->update(); + CanvasItemEditor::get_singleton()->update_viewport(); } break; case OPTION_PICK_TILE: { tool = TOOL_PICKING; - canvas_item_editor->update(); + CanvasItemEditor::get_singleton()->update_viewport(); } break; case OPTION_SELECT: { tool = TOOL_SELECTING; selection_active = false; - canvas_item_editor->update(); + CanvasItemEditor::get_singleton()->update_viewport(); } break; case OPTION_COPY: { @@ -126,7 +125,7 @@ void TileMapEditor::_menu_option(int p_option) { if (selection_active) { tool = TOOL_PASTING; - canvas_item_editor->update(); + CanvasItemEditor::get_singleton()->update_viewport(); } } break; case OPTION_ERASE_SELECTION: { @@ -141,7 +140,7 @@ void TileMapEditor::_menu_option(int p_option) { selection_active = false; copydata.clear(); - canvas_item_editor->update(); + CanvasItemEditor::get_singleton()->update_viewport(); } break; case OPTION_FIX_INVALID: { @@ -165,7 +164,7 @@ void TileMapEditor::_menu_option(int p_option) { tool = TOOL_PASTING; - canvas_item_editor->update(); + CanvasItemEditor::get_singleton()->update_viewport(); } } break; } @@ -182,13 +181,13 @@ void TileMapEditor::_palette_multi_selected(int index, bool selected) { void TileMapEditor::_canvas_mouse_enter() { mouse_over = true; - canvas_item_editor->update(); + CanvasItemEditor::get_singleton()->update_viewport(); } void TileMapEditor::_canvas_mouse_exit() { mouse_over = false; - canvas_item_editor->update(); + CanvasItemEditor::get_singleton()->update_viewport(); } Vector<int> TileMapEditor::get_selected_tiles() const { @@ -238,8 +237,8 @@ void TileMapEditor::_create_set_cell_undo(const Vector2 &p_vec, const CellOp &p_ cell_new["transpose"] = p_cell_new.tr; cell_new["auto_coord"] = p_cell_new.ac; - undo_redo->add_undo_method(node, "set_celld", p_vec, cell_old); - undo_redo->add_do_method(node, "set_celld", p_vec, cell_new); + undo_redo->add_undo_method(node, "_set_celld", p_vec, cell_old); + undo_redo->add_do_method(node, "_set_celld", p_vec, cell_new); } void TileMapEditor::_start_undo(const String &p_action) { @@ -301,7 +300,7 @@ void TileMapEditor::_set_cell(const Point2i &p_pos, Vector<int> p_values, bool p } node->set_cell(p_pos.x, p_pos.y, p_value, p_flip_h, p_flip_v, p_transpose); - if (manual_autotile || node->get_tileset()->tile_get_tile_mode(p_value) == TileSet::ATLAS_TILE) { + if (manual_autotile || (p_value != -1 && node->get_tileset()->tile_get_tile_mode(p_value) == TileSet::ATLAS_TILE)) { if (current != -1) { node->set_cell_autotile_coord(p_pos.x, p_pos.y, position); } @@ -318,7 +317,7 @@ void TileMapEditor::_manual_toggled(bool p_enabled) { void TileMapEditor::_text_entered(const String &p_text) { - canvas_item_editor->grab_focus(); + canvas_item_editor_viewport->grab_focus(); } void TileMapEditor::_text_changed(const String &p_text) { @@ -357,6 +356,10 @@ void TileMapEditor::_update_palette() { if (!node) return; + // Update the clear button + clear_transform_button->set_disabled(!flip_h && !flip_v && !transpose); + + // Update the palette Vector<int> selected = get_selected_tiles(); palette->clear(); manual_palette->clear(); @@ -429,9 +432,6 @@ void TileMapEditor::_update_palette() { Ref<Texture> tex = tileset->tile_get_texture(entries[i].id); if (tex.is_valid()) { - Color color = tileset->tile_get_modulate(entries[i].id); - palette->set_item_icon_modulate(palette->get_item_count() - 1, color); - Rect2 region = tileset->tile_get_region(entries[i].id); if (tileset->tile_get_tile_mode(entries[i].id) == TileSet::AUTO_TILE || tileset->tile_get_tile_mode(entries[i].id) == TileSet::ATLAS_TILE) { @@ -440,10 +440,25 @@ void TileMapEditor::_update_palette() { region.position += (region.size + Vector2(spacing, spacing)) * tileset->autotile_get_icon_coordinate(entries[i].id); } - if (!region.has_no_area()) + // Transpose and flip + palette->set_item_icon_transposed(palette->get_item_count() - 1, transpose); + if (flip_h) { + region.size.x = -region.size.x; + } + if (flip_v) { + region.size.y = -region.size.y; + } + + // Set region + if (region.size != Size2()) palette->set_item_icon_region(palette->get_item_count() - 1, region); + // Set icon palette->set_item_icon(palette->get_item_count() - 1, tex); + + // Modulation + Color color = tileset->tile_get_modulate(entries[i].id); + palette->set_item_icon_modulate(palette->get_item_count() - 1, color); } palette->set_item_metadata(palette->get_item_count() - 1, entries[i].id); @@ -519,12 +534,12 @@ void TileMapEditor::_pick_tile(const Point2 &p_pos) { selected.push_back(id); set_selected_tiles(selected); - mirror_x->set_pressed(node->is_cell_x_flipped(p_pos.x, p_pos.y)); - mirror_y->set_pressed(node->is_cell_y_flipped(p_pos.x, p_pos.y)); - transp->set_pressed(node->is_cell_transposed(p_pos.x, p_pos.y)); + flip_h = node->is_cell_x_flipped(p_pos.x, p_pos.y); + flip_v = node->is_cell_y_flipped(p_pos.x, p_pos.y); + transpose = node->is_cell_transposed(p_pos.x, p_pos.y); - _update_transform_buttons(); - canvas_item_editor->update(); + _update_palette(); + CanvasItemEditor::get_singleton()->update_viewport(); } PoolVector<Vector2> TileMapEditor::_bucket_fill(const Point2i &p_start, bool erase, bool preview) { @@ -671,7 +686,7 @@ void TileMapEditor::_select(const Point2i &p_from, const Point2i &p_to) { rectangle.position = begin; rectangle.size = end - begin; - canvas_item_editor->update(); + CanvasItemEditor::get_singleton()->update_viewport(); } void TileMapEditor::_erase_selection() { @@ -686,7 +701,7 @@ void TileMapEditor::_erase_selection() { } } -void TileMapEditor::_draw_cell(int p_cell, const Point2i &p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D &p_xform) { +void TileMapEditor::_draw_cell(Control *p_viewport, int p_cell, const Point2i &p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D &p_xform) { Ref<Texture> t = node->get_tileset()->tile_get_texture(p_cell); @@ -783,19 +798,19 @@ void TileMapEditor::_draw_cell(int p_cell, const Point2i &p_point, bool p_flip_h modulate.a = 0.5; if (r.has_no_area()) - canvas_item_editor->draw_texture_rect(t, rect, false, modulate, p_transpose); + p_viewport->draw_texture_rect(t, rect, false, modulate, p_transpose); else - canvas_item_editor->draw_texture_rect_region(t, rect, r, modulate, p_transpose); + p_viewport->draw_texture_rect_region(t, rect, r, modulate, p_transpose); } -void TileMapEditor::_draw_fill_preview(int p_cell, const Point2i &p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D &p_xform) { +void TileMapEditor::_draw_fill_preview(Control *p_viewport, int p_cell, const Point2i &p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D &p_xform) { PoolVector<Vector2> points = _bucket_fill(p_point, false, true); PoolVector<Vector2>::Read pr = points.read(); int len = points.size(); for (int i = 0; i < len; ++i) { - _draw_cell(p_cell, pr[i], p_flip_h, p_flip_v, p_transpose, p_xform); + _draw_cell(p_viewport, p_cell, pr[i], p_flip_h, p_flip_v, p_transpose, p_xform); } } @@ -978,7 +993,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { paint_undo.clear(); - canvas_item_editor->update(); + CanvasItemEditor::get_singleton()->update_viewport(); } } else if (tool == TOOL_RECTANGLE_PAINT) { @@ -995,7 +1010,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { } _finish_undo(); - canvas_item_editor->update(); + CanvasItemEditor::get_singleton()->update_viewport(); } } else if (tool == TOOL_PASTING) { @@ -1011,12 +1026,12 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { } _finish_undo(); - canvas_item_editor->update(); + CanvasItemEditor::get_singleton()->update_viewport(); return true; // We want to keep the Pasting tool } else if (tool == TOOL_SELECTING) { - canvas_item_editor->update(); + CanvasItemEditor::get_singleton()->update_viewport(); } else if (tool == TOOL_BUCKET) { @@ -1055,7 +1070,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { tool = TOOL_NONE; selection_active = false; - canvas_item_editor->update(); + CanvasItemEditor::get_singleton()->update_viewport(); return true; } @@ -1065,7 +1080,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { tool = TOOL_NONE; copydata.clear(); - canvas_item_editor->update(); + CanvasItemEditor::get_singleton()->update_viewport(); return true; } @@ -1106,7 +1121,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { _finish_undo(); if (tool == TOOL_RECTANGLE_ERASE || tool == TOOL_LINE_ERASE) { - canvas_item_editor->update(); + CanvasItemEditor::get_singleton()->update_viewport(); } tool = TOOL_NONE; @@ -1149,7 +1164,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { if (new_over_tile != over_tile) { over_tile = new_over_tile; - canvas_item_editor->update(); + CanvasItemEditor::get_singleton()->update_viewport(); } if (show_tile_info) { @@ -1235,7 +1250,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { _set_cell(points[i], invalid_cell); } - canvas_item_editor->update(); + CanvasItemEditor::get_singleton()->update_viewport(); } return true; @@ -1294,7 +1309,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { tool = TOOL_NONE; - canvas_item_editor->update(); + CanvasItemEditor::get_singleton()->update_viewport(); return true; } @@ -1308,13 +1323,13 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { // NOTE: We do not set tool = TOOL_PAINTING as this begins painting // immediately without pressing the left mouse button first tool = TOOL_NONE; - canvas_item_editor->update(); + CanvasItemEditor::get_singleton()->update_viewport(); return true; } if (ED_IS_SHORTCUT("tile_map_editor/bucket_fill", p_event)) { tool = TOOL_BUCKET; - canvas_item_editor->update(); + CanvasItemEditor::get_singleton()->update_viewport(); return true; } @@ -1327,7 +1342,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { tool = TOOL_SELECTING; selection_active = false; - canvas_item_editor->update(); + CanvasItemEditor::get_singleton()->update_viewport(); return true; } @@ -1337,7 +1352,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { if (selection_active) { tool = TOOL_PASTING; - canvas_item_editor->update(); + CanvasItemEditor::get_singleton()->update_viewport(); return true; } @@ -1354,7 +1369,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { tool = TOOL_PASTING; - canvas_item_editor->update(); + CanvasItemEditor::get_singleton()->update_viewport(); return true; } } @@ -1366,23 +1381,20 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { } if (ED_IS_SHORTCUT("tile_map_editor/mirror_x", p_event)) { flip_h = !flip_h; - mirror_x->set_pressed(flip_h); - _update_transform_buttons(); - canvas_item_editor->update(); + _update_palette(); + CanvasItemEditor::get_singleton()->update_viewport(); return true; } if (ED_IS_SHORTCUT("tile_map_editor/mirror_y", p_event)) { flip_v = !flip_v; - mirror_y->set_pressed(flip_v); - _update_transform_buttons(); - canvas_item_editor->update(); + _update_palette(); + CanvasItemEditor::get_singleton()->update_viewport(); return true; } if (ED_IS_SHORTCUT("tile_map_editor/transpose", p_event)) { transpose = !transpose; - transp->set_pressed(transpose); - _update_transform_buttons(); - canvas_item_editor->update(); + _update_palette(); + CanvasItemEditor::get_singleton()->update_viewport(); return true; } } @@ -1390,17 +1402,16 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { return false; } -void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) { +void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { if (!node) return; Transform2D cell_xf = node->get_cell_transform(); - Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * node->get_global_transform(); Transform2D xform_inv = xform.affine_inverse(); - Size2 screen_size = canvas_item_editor->get_size(); + Size2 screen_size = p_overlay->get_size(); { Rect2 aabb; aabb.position = node->world_to_map(xform_inv.xform(Vector2())); @@ -1419,7 +1430,7 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) { Vector2 to = xform.xform(node->map_to_world(Vector2(i, si.position.y + si.size.y + 1))); Color col = i == 0 ? Color(1, 0.8, 0.2, 0.5) : Color(1, 0.3, 0.1, 0.2); - canvas_item_editor->draw_line(from, to, col, 1); + p_overlay->draw_line(from, to, col, 1); if (max_lines-- == 0) break; } @@ -1439,7 +1450,7 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) { Vector2 from = xform.xform(node->map_to_world(Vector2(i, j), true) + ofs); Vector2 to = xform.xform(node->map_to_world(Vector2(i, j + 1), true) + ofs); Color col = i == 0 ? Color(1, 0.8, 0.2, 0.5) : Color(1, 0.3, 0.1, 0.2); - canvas_item_editor->draw_line(from, to, col, 1); + p_overlay->draw_line(from, to, col, 1); if (max_lines-- == 0) break; @@ -1457,7 +1468,7 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) { Vector2 to = xform.xform(node->map_to_world(Vector2(si.position.x + si.size.x + 1, i))); Color col = i == 0 ? Color(1, 0.8, 0.2, 0.5) : Color(1, 0.3, 0.1, 0.2); - canvas_item_editor->draw_line(from, to, col, 1); + p_overlay->draw_line(from, to, col, 1); if (max_lines-- == 0) break; @@ -1476,7 +1487,7 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) { Vector2 from = xform.xform(node->map_to_world(Vector2(j, i), true) + ofs); Vector2 to = xform.xform(node->map_to_world(Vector2(j + 1, i), true) + ofs); Color col = i == 0 ? Color(1, 0.8, 0.2, 0.5) : Color(1, 0.3, 0.1, 0.2); - canvas_item_editor->draw_line(from, to, col, 1); + p_overlay->draw_line(from, to, col, 1); if (max_lines-- == 0) break; @@ -1493,7 +1504,7 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) { points.push_back(xform.xform(node->map_to_world((rectangle.position + Point2(rectangle.size.x + 1, rectangle.size.y + 1))))); points.push_back(xform.xform(node->map_to_world((rectangle.position + Point2(0, rectangle.size.y + 1))))); - canvas_item_editor->draw_colored_polygon(points, Color(0.2, 0.8, 1, 0.4)); + p_overlay->draw_colored_polygon(points, Color(0.2, 0.8, 1, 0.4)); } if (mouse_over) { @@ -1519,7 +1530,7 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) { col = Color(1.0, 0.4, 0.2, 0.8); for (int i = 0; i < 4; i++) - canvas_item_editor->draw_line(endpoints[i], endpoints[(i + 1) % 4], col, 2); + p_overlay->draw_line(endpoints[i], endpoints[(i + 1) % 4], col, 2); bool bucket_preview = EditorSettings::get_singleton()->get("editors/tile_map/bucket_fill_preview"); if (tool == TOOL_SELECTING || tool == TOOL_PICKING || !bucket_preview) { @@ -1538,7 +1549,7 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) { for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) { - _draw_cell(ids[0], E->key(), flip_h, flip_v, transpose, xform); + _draw_cell(p_overlay, ids[0], E->key(), flip_h, flip_v, transpose, xform); } } else if (tool == TOOL_RECTANGLE_PAINT) { @@ -1551,7 +1562,7 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) { for (int i = rectangle.position.y; i <= rectangle.position.y + rectangle.size.y; i++) { for (int j = rectangle.position.x; j <= rectangle.position.x + rectangle.size.x; j++) { - _draw_cell(ids[0], Point2i(j, i), flip_h, flip_v, transpose, xform); + _draw_cell(p_overlay, ids[0], Point2i(j, i), flip_h, flip_v, transpose, xform); } } } else if (tool == TOOL_PASTING) { @@ -1573,7 +1584,7 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) { TileData tcd = E->get(); - _draw_cell(tcd.cell, tcd.pos + ofs, tcd.flip_h, tcd.flip_v, tcd.transpose, xform); + _draw_cell(p_overlay, tcd.cell, tcd.pos + ofs, tcd.flip_h, tcd.flip_v, tcd.transpose, xform); } Rect2i duplicate = rectangle; @@ -1585,12 +1596,12 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) { points.push_back(xform.xform(node->map_to_world((duplicate.position + Point2(duplicate.size.x + 1, duplicate.size.y + 1))))); points.push_back(xform.xform(node->map_to_world((duplicate.position + Point2(0, duplicate.size.y + 1))))); - canvas_item_editor->draw_colored_polygon(points, Color(0.2, 1.0, 0.8, 0.2)); + p_overlay->draw_colored_polygon(points, Color(0.2, 1.0, 0.8, 0.2)); } else if (tool == TOOL_BUCKET) { Vector<int> tiles = get_selected_tiles(); - _draw_fill_preview(tiles[0], over_tile, flip_h, flip_v, transpose, xform); + _draw_fill_preview(p_overlay, tiles[0], over_tile, flip_h, flip_v, transpose, xform); } else { @@ -1599,7 +1610,7 @@ void TileMapEditor::forward_draw_over_viewport(Control *p_overlay) { if (st.size() == 1 && st[0] == TileMap::INVALID_CELL) return; - _draw_cell(st[0], over_tile, flip_h, flip_v, transpose, xform); + _draw_cell(p_overlay, st[0], over_tile, flip_h, flip_v, transpose, xform); } } } @@ -1608,8 +1619,8 @@ void TileMapEditor::edit(Node *p_tile_map) { search_box->set_text(""); - if (!canvas_item_editor) { - canvas_item_editor = CanvasItemEditor::get_singleton()->get_viewport_control(); + if (!canvas_item_editor_viewport) { + canvas_item_editor_viewport = CanvasItemEditor::get_singleton()->get_viewport_control(); } if (node) @@ -1617,20 +1628,20 @@ void TileMapEditor::edit(Node *p_tile_map) { if (p_tile_map) { node = Object::cast_to<TileMap>(p_tile_map); - if (!canvas_item_editor->is_connected("mouse_entered", this, "_canvas_mouse_enter")) - canvas_item_editor->connect("mouse_entered", this, "_canvas_mouse_enter"); - if (!canvas_item_editor->is_connected("mouse_exited", this, "_canvas_mouse_exit")) - canvas_item_editor->connect("mouse_exited", this, "_canvas_mouse_exit"); + if (!canvas_item_editor_viewport->is_connected("mouse_entered", this, "_canvas_mouse_enter")) + canvas_item_editor_viewport->connect("mouse_entered", this, "_canvas_mouse_enter"); + if (!canvas_item_editor_viewport->is_connected("mouse_exited", this, "_canvas_mouse_exit")) + canvas_item_editor_viewport->connect("mouse_exited", this, "_canvas_mouse_exit"); _update_palette(); } else { node = NULL; - if (canvas_item_editor->is_connected("mouse_entered", this, "_canvas_mouse_enter")) - canvas_item_editor->disconnect("mouse_entered", this, "_canvas_mouse_enter"); - if (canvas_item_editor->is_connected("mouse_exited", this, "_canvas_mouse_exit")) - canvas_item_editor->disconnect("mouse_exited", this, "_canvas_mouse_exit"); + if (canvas_item_editor_viewport->is_connected("mouse_entered", this, "_canvas_mouse_enter")) + canvas_item_editor_viewport->disconnect("mouse_entered", this, "_canvas_mouse_enter"); + if (canvas_item_editor_viewport->is_connected("mouse_exited", this, "_canvas_mouse_exit")) + canvas_item_editor_viewport->disconnect("mouse_exited", this, "_canvas_mouse_exit"); _update_palette(); } @@ -1644,9 +1655,7 @@ void TileMapEditor::edit(Node *p_tile_map) { void TileMapEditor::_tileset_settings_changed() { _update_palette(); - - if (canvas_item_editor) - canvas_item_editor->update(); + CanvasItemEditor::get_singleton()->update_viewport(); } void TileMapEditor::_icon_size_changed(float p_value) { @@ -1667,7 +1676,10 @@ void TileMapEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("_canvas_mouse_enter"), &TileMapEditor::_canvas_mouse_enter); ClassDB::bind_method(D_METHOD("_canvas_mouse_exit"), &TileMapEditor::_canvas_mouse_exit); ClassDB::bind_method(D_METHOD("_tileset_settings_changed"), &TileMapEditor::_tileset_settings_changed); - ClassDB::bind_method(D_METHOD("_update_transform_buttons"), &TileMapEditor::_update_transform_buttons); + ClassDB::bind_method(D_METHOD("_rotate"), &TileMapEditor::_rotate); + ClassDB::bind_method(D_METHOD("_flip_horizontal"), &TileMapEditor::_flip_horizontal); + ClassDB::bind_method(D_METHOD("_flip_vertical"), &TileMapEditor::_flip_vertical); + ClassDB::bind_method(D_METHOD("_clear_transform"), &TileMapEditor::_clear_transform); ClassDB::bind_method(D_METHOD("_palette_selected"), &TileMapEditor::_palette_selected); ClassDB::bind_method(D_METHOD("_palette_multi_selected"), &TileMapEditor::_palette_multi_selected); @@ -1692,37 +1704,67 @@ TileMapEditor::CellOp TileMapEditor::_get_op_from_cell(const Point2i &p_pos) { return op; } -void TileMapEditor::_update_transform_buttons(Object *p_button) { - //ERR_FAIL_NULL(p_button); - ToolButton *b = Object::cast_to<ToolButton>(p_button); - //ERR_FAIL_COND(!b); - - if (b == rotate_0) { - mirror_x->set_pressed(false); - mirror_y->set_pressed(false); - transp->set_pressed(false); - } else if (b == rotate_90) { - mirror_x->set_pressed(true); - mirror_y->set_pressed(false); - transp->set_pressed(true); - } else if (b == rotate_180) { - mirror_x->set_pressed(true); - mirror_y->set_pressed(true); - transp->set_pressed(false); - } else if (b == rotate_270) { - mirror_x->set_pressed(false); - mirror_y->set_pressed(true); - transp->set_pressed(true); +void TileMapEditor::_rotate(int steps) { + const bool normal_rotation_matrix[][3] = { + { false, false, false }, + { true, true, false }, + { false, true, true }, + { true, false, true } + }; + + const bool mirrored_rotation_matrix[][3] = { + { false, true, false }, + { true, true, true }, + { false, false, true }, + { true, false, false } + }; + + if (transpose ^ flip_h ^ flip_v) { + // Odd number of flags activated = mirrored rotation + for (int i = 0; i < 4; i++) { + if (transpose == mirrored_rotation_matrix[i][0] && + flip_h == mirrored_rotation_matrix[i][1] && + flip_v == mirrored_rotation_matrix[i][2]) { + int new_id = Math::wrapi(i + steps, 0, 4); + transpose = mirrored_rotation_matrix[new_id][0]; + flip_h = mirrored_rotation_matrix[new_id][1]; + flip_v = mirrored_rotation_matrix[new_id][2]; + break; + } + } + } else { + // Even number of flags activated = normal rotation + for (int i = 0; i < 4; i++) { + if (transpose == normal_rotation_matrix[i][0] && + flip_h == normal_rotation_matrix[i][1] && + flip_v == normal_rotation_matrix[i][2]) { + int new_id = Math::wrapi(i + steps, 0, 4); + transpose = normal_rotation_matrix[new_id][0]; + flip_h = normal_rotation_matrix[new_id][1]; + flip_v = normal_rotation_matrix[new_id][2]; + break; + } + } } - flip_h = mirror_x->is_pressed(); - flip_v = mirror_y->is_pressed(); - transpose = transp->is_pressed(); + _update_palette(); +} + +void TileMapEditor::_flip_horizontal() { + flip_h = !flip_h; + _update_palette(); +} + +void TileMapEditor::_flip_vertical() { + flip_v = !flip_v; + _update_palette(); +} - rotate_0->set_pressed(!flip_h && !flip_v && !transpose); - rotate_90->set_pressed(flip_h && !flip_v && transpose); - rotate_180->set_pressed(flip_h && flip_v && !transpose); - rotate_270->set_pressed(!flip_h && flip_v && transpose); +void TileMapEditor::_clear_transform() { + transpose = false; + flip_h = false; + flip_v = false; + _update_palette(); } TileMapEditor::TileMapEditor(EditorNode *p_editor) { @@ -1730,7 +1772,7 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { node = NULL; manual_autotile = false; manual_position = Vector2(0, 0); - canvas_item_editor = NULL; + canvas_item_editor_viewport = NULL; editor = p_editor; undo_redo = editor->get_undo_redo(); @@ -1755,10 +1797,8 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { ED_SHORTCUT("tile_map_editor/mirror_x", TTR("Mirror X"), KEY_A); ED_SHORTCUT("tile_map_editor/mirror_y", TTR("Mirror Y"), KEY_S); - HBoxContainer *tool_hb1 = memnew(HBoxContainer); - add_child(tool_hb1); - HBoxContainer *tool_hb2 = memnew(HBoxContainer); - add_child(tool_hb2); + HBoxContainer *tool_hb = memnew(HBoxContainer); + add_child(tool_hb); manual_button = memnew(CheckBox); manual_button->set_text("Disable Autotile"); @@ -1843,52 +1883,37 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { p->connect("id_pressed", this, "_menu_option"); toolbar->add_child(options); - - transp = memnew(ToolButton); - transp->set_toggle_mode(true); - transp->set_tooltip(TTR("Transpose") + " (" + ED_GET_SHORTCUT("tile_map_editor/transpose")->get_as_text() + ")"); - transp->set_focus_mode(FOCUS_NONE); - transp->connect("pressed", this, "_update_transform_buttons", make_binds(transp)); - tool_hb1->add_child(transp); - mirror_x = memnew(ToolButton); - mirror_x->set_toggle_mode(true); - mirror_x->set_tooltip(TTR("Mirror X") + " (" + ED_GET_SHORTCUT("tile_map_editor/mirror_x")->get_as_text() + ")"); - mirror_x->set_focus_mode(FOCUS_NONE); - mirror_x->connect("pressed", this, "_update_transform_buttons", make_binds(mirror_x)); - tool_hb1->add_child(mirror_x); - mirror_y = memnew(ToolButton); - mirror_y->set_toggle_mode(true); - mirror_y->set_tooltip(TTR("Mirror Y") + " (" + ED_GET_SHORTCUT("tile_map_editor/mirror_y")->get_as_text() + ")"); - mirror_y->set_focus_mode(FOCUS_NONE); - mirror_y->connect("pressed", this, "_update_transform_buttons", make_binds(mirror_y)); - tool_hb1->add_child(mirror_y); - - rotate_0 = memnew(ToolButton); - rotate_0->set_toggle_mode(true); - rotate_0->set_tooltip(TTR("Rotate 0 degrees")); - rotate_0->set_focus_mode(FOCUS_NONE); - rotate_0->connect("pressed", this, "_update_transform_buttons", make_binds(rotate_0)); - tool_hb2->add_child(rotate_0); - rotate_90 = memnew(ToolButton); - rotate_90->set_toggle_mode(true); - rotate_90->set_tooltip(TTR("Rotate 90 degrees")); - rotate_90->set_focus_mode(FOCUS_NONE); - rotate_90->connect("pressed", this, "_update_transform_buttons", make_binds(rotate_90)); - tool_hb2->add_child(rotate_90); - rotate_180 = memnew(ToolButton); - rotate_180->set_toggle_mode(true); - rotate_180->set_tooltip(TTR("Rotate 180 degrees")); - rotate_180->set_focus_mode(FOCUS_NONE); - rotate_180->connect("pressed", this, "_update_transform_buttons", make_binds(rotate_180)); - tool_hb2->add_child(rotate_180); - rotate_270 = memnew(ToolButton); - rotate_270->set_toggle_mode(true); - rotate_270->set_tooltip(TTR("Rotate 270 degrees")); - rotate_270->set_focus_mode(FOCUS_NONE); - rotate_270->connect("pressed", this, "_update_transform_buttons", make_binds(rotate_270)); - tool_hb2->add_child(rotate_270); - - rotate_0->set_pressed(true); + rotate_left_button = memnew(ToolButton); + rotate_left_button->set_tooltip(TTR("Rotate left")); + rotate_left_button->set_focus_mode(FOCUS_NONE); + rotate_left_button->connect("pressed", this, "_rotate", varray(-1)); + tool_hb->add_child(rotate_left_button); + + rotate_right_button = memnew(ToolButton); + rotate_right_button->set_tooltip(TTR("Rotate right")); + rotate_right_button->set_focus_mode(FOCUS_NONE); + rotate_right_button->connect("pressed", this, "_rotate", varray(1)); + tool_hb->add_child(rotate_right_button); + + flip_horizontal_button = memnew(ToolButton); + flip_horizontal_button->set_tooltip(TTR("Flip horizontally")); + flip_horizontal_button->set_focus_mode(FOCUS_NONE); + flip_horizontal_button->connect("pressed", this, "_flip_horizontal"); + tool_hb->add_child(flip_horizontal_button); + + flip_vertical_button = memnew(ToolButton); + flip_vertical_button->set_tooltip(TTR("Flip vertically")); + flip_vertical_button->set_focus_mode(FOCUS_NONE); + flip_vertical_button->connect("pressed", this, "_flip_vertical"); + tool_hb->add_child(flip_vertical_button); + + clear_transform_button = memnew(ToolButton); + clear_transform_button->set_tooltip(TTR("Clear transform")); + clear_transform_button->set_focus_mode(FOCUS_NONE); + clear_transform_button->connect("pressed", this, "_clear_transform"); + tool_hb->add_child(clear_transform_button); + + clear_transform_button->set_disabled(true); } TileMapEditor::~TileMapEditor() { diff --git a/editor/plugins/tile_map_editor_plugin.h b/editor/plugins/tile_map_editor_plugin.h index c824824d56..68e5806ee5 100644 --- a/editor/plugins/tile_map_editor_plugin.h +++ b/editor/plugins/tile_map_editor_plugin.h @@ -82,7 +82,7 @@ class TileMapEditor : public VBoxContainer { EditorNode *editor; UndoRedo *undo_redo; - Control *canvas_item_editor; + Control *canvas_item_editor_viewport; LineEdit *search_box; HSlider *size_slider; @@ -93,13 +93,13 @@ class TileMapEditor : public VBoxContainer { Label *tile_info; MenuButton *options; - ToolButton *transp; - ToolButton *mirror_x; - ToolButton *mirror_y; - ToolButton *rotate_0; - ToolButton *rotate_90; - ToolButton *rotate_180; - ToolButton *rotate_270; + + ToolButton *flip_horizontal_button; + ToolButton *flip_vertical_button; + ToolButton *rotate_left_button; + ToolButton *rotate_right_button; + ToolButton *clear_transform_button; + CheckBox *manual_button; Tool tool; @@ -168,8 +168,8 @@ class TileMapEditor : public VBoxContainer { void _select(const Point2i &p_from, const Point2i &p_to); void _erase_selection(); - void _draw_cell(int p_cell, const Point2i &p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D &p_xform); - void _draw_fill_preview(int p_cell, const Point2i &p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D &p_xform); + void _draw_cell(Control *p_viewport, int p_cell, const Point2i &p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D &p_xform); + void _draw_fill_preview(Control *p_viewport, int p_cell, const Point2i &p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D &p_xform); void _clear_bucket_cache(); void _update_copydata(); @@ -196,17 +196,21 @@ class TileMapEditor : public VBoxContainer { void _tileset_settings_changed(); void _icon_size_changed(float p_value); + void _clear_transform(); + void _flip_horizontal(); + void _flip_vertical(); + void _rotate(int steps); + protected: void _notification(int p_what); static void _bind_methods(); CellOp _get_op_from_cell(const Point2i &p_pos); - void _update_transform_buttons(Object *p_button = NULL); public: HBoxContainer *get_toolbar() const { return toolbar; } bool forward_gui_input(const Ref<InputEvent> &p_event); - void forward_draw_over_viewport(Control *p_overlay); + void forward_canvas_draw_over_viewport(Control *p_overlay); void edit(Node *p_tile_map); @@ -225,7 +229,7 @@ protected: public: virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return tile_map_editor->forward_gui_input(p_event); } - virtual void forward_draw_over_viewport(Control *p_overlay) { tile_map_editor->forward_draw_over_viewport(p_overlay); } + virtual void forward_canvas_draw_over_viewport(Control *p_overlay) { tile_map_editor->forward_canvas_draw_over_viewport(p_overlay); } virtual String get_name() const { return "TileMap"; } bool has_main_screen() const { return false; } diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp index f981ead7eb..d0e0b3e006 100644 --- a/editor/plugins/tile_set_editor_plugin.cpp +++ b/editor/plugins/tile_set_editor_plugin.cpp @@ -483,6 +483,11 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { //--------------- helper = memnew(TilesetEditorContext(this)); tile_names_opacity = 0; + + // config scale + max_scale = 10.0f; + min_scale = 0.1f; + scale_ratio = 1.2f; } TileSetEditor::~TileSetEditor() { @@ -569,6 +574,10 @@ void TileSetEditor::_on_textures_added(const PoolStringArray &p_paths) { int invalid_count = 0; for (int i = 0; i < p_paths.size(); i++) { Ref<Texture> t = Ref<Texture>(ResourceLoader::load(p_paths[i])); + + ERR_EXPLAIN("'" + p_paths[i] + "' is not a valid texture."); + ERR_CONTINUE(!t.is_valid()); + if (texture_map.has(t->get_rid())) { invalid_count++; } else { @@ -577,11 +586,15 @@ void TileSetEditor::_on_textures_added(const PoolStringArray &p_paths) { texture_list->set_item_metadata(texture_list->get_item_count() - 1, t->get_rid()); } } - update_texture_list_icon(); - texture_list->select(texture_list->get_item_count() - 1); - _on_texture_list_selected(texture_list->get_item_count() - 1); + + if (texture_list->get_item_count() > 0) { + update_texture_list_icon(); + texture_list->select(texture_list->get_item_count() - 1); + _on_texture_list_selected(texture_list->get_item_count() - 1); + } + if (invalid_count > 0) { - err_dialog->set_text(String::num(invalid_count, 0) + TTR(" file(s) was not added because was already on the list.")); + err_dialog->set_text(vformat(TTR("%s file(s) were not added because was already on the list."), String::num(invalid_count, 0))); err_dialog->popup_centered(Size2(300, 60)); } } @@ -795,6 +808,7 @@ void TileSetEditor::_on_workspace_draw() { spin_priority->set_suffix(" / " + String::num(total, 0)); draw_highlight_subtile(edited_shape_coord, queue_others); } break; + default: {} } draw_tile_subdivision(get_current_tile(), Color(0.347214, 0.722656, 0.617063)); @@ -944,7 +958,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { Ref<InputEventMouseMotion> mm = p_ie; if (mb.is_valid()) { - if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && !creating_shape) { if (!current_tile_region.has_point(mb->get_position())) { List<int> *tiles = new List<int>(); tileset->get_tile_list(tiles); @@ -963,6 +977,15 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { } } } + + // Mouse Wheel Event + const int _mouse_button_index = mb->get_button_index(); + if (_mouse_button_index == BUTTON_WHEEL_UP && mb->get_control()) { + _zoom_in(); + + } else if (_mouse_button_index == BUTTON_WHEEL_DOWN && mb->get_control()) { + _zoom_out(); + } } // Drag Middle Mouse if (mm.is_valid()) { @@ -1365,6 +1388,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { } } } break; + default: {} } } } @@ -1434,26 +1458,15 @@ void TileSetEditor::_on_tool_clicked(int p_tool) { workspace->update(); } } break; + default: {} } } } else if (p_tool == ZOOM_OUT) { - float scale = workspace->get_scale().x; - if (scale > 0.1) { - scale /= 2; - workspace->set_scale(Vector2(scale, scale)); - workspace_container->set_custom_minimum_size(workspace->get_rect().size * scale); - workspace_overlay->set_custom_minimum_size(workspace->get_rect().size * scale); - } + _zoom_out(); } else if (p_tool == ZOOM_1) { - workspace->set_scale(Vector2(1, 1)); - workspace_container->set_custom_minimum_size(workspace->get_rect().size); - workspace_overlay->set_custom_minimum_size(workspace->get_rect().size); + _reset_zoom(); } else if (p_tool == ZOOM_IN) { - float scale = workspace->get_scale().x; - scale *= 2; - workspace->set_scale(Vector2(scale, scale)); - workspace_container->set_custom_minimum_size(workspace->get_rect().size * scale); - workspace_overlay->set_custom_minimum_size(workspace->get_rect().size * scale); + _zoom_in(); } else if (p_tool == TOOL_SELECT) { if (creating_shape) { // Cancel Creation @@ -1492,6 +1505,31 @@ void TileSetEditor::_set_snap_sep(Vector2 p_val) { workspace->update(); } +void TileSetEditor::_zoom_in() { + float scale = workspace->get_scale().x; + if (scale < max_scale) { + scale *= scale_ratio; + workspace->set_scale(Vector2(scale, scale)); + workspace_container->set_custom_minimum_size(workspace->get_rect().size * scale); + workspace_overlay->set_custom_minimum_size(workspace->get_rect().size * scale); + } +} +void TileSetEditor::_zoom_out() { + + float scale = workspace->get_scale().x; + if (scale > min_scale) { + scale /= scale_ratio; + workspace->set_scale(Vector2(scale, scale)); + workspace_container->set_custom_minimum_size(workspace->get_rect().size * scale); + workspace_overlay->set_custom_minimum_size(workspace->get_rect().size * scale); + } +} +void TileSetEditor::_reset_zoom() { + workspace->set_scale(Vector2(1, 1)); + workspace_container->set_custom_minimum_size(workspace->get_rect().size); + workspace_overlay->set_custom_minimum_size(workspace->get_rect().size); +} + void TileSetEditor::draw_highlight_current_tile() { if (get_current_tile() >= 0) { @@ -1862,6 +1900,7 @@ void TileSetEditor::draw_polygon_shapes() { } } } break; + default: {} } if (creating_shape) { for (int j = 0; j < current_shape.size() - 1; j++) { @@ -2072,13 +2111,24 @@ void TileSetEditor::update_texture_list() { List<int> ids; tileset->get_tile_list(&ids); + Vector<int> ids_to_remove; for (List<int>::Element *E = ids.front(); E; E = E->next()) { + // Clear tiles referencing gone textures (user has been already given the chance to fix broken deps) + if (!tileset->tile_get_texture(E->get()).is_valid()) { + ids_to_remove.push_back(E->get()); + ERR_CONTINUE(!tileset->tile_get_texture(E->get()).is_valid()); + } + if (!texture_map.has(tileset->tile_get_texture(E->get())->get_rid())) { texture_list->add_item(tileset->tile_get_texture(E->get())->get_path().get_file()); texture_map.insert(tileset->tile_get_texture(E->get())->get_rid(), tileset->tile_get_texture(E->get())); texture_list->set_item_metadata(texture_list->get_item_count() - 1, tileset->tile_get_texture(E->get())->get_rid()); } } + for (int i = 0; i < ids_to_remove.size(); i++) { + tileset->remove_tile(ids_to_remove[i]); + } + if (texture_list->get_item_count() > 0 && selected_texture.is_valid()) { texture_list->select(texture_list->find_metadata(selected_texture->get_rid())); if (texture_list->get_selected_items().size() > 0) diff --git a/editor/plugins/tile_set_editor_plugin.h b/editor/plugins/tile_set_editor_plugin.h index 23bf68b90f..bd8a2ddb98 100644 --- a/editor/plugins/tile_set_editor_plugin.h +++ b/editor/plugins/tile_set_editor_plugin.h @@ -141,6 +141,10 @@ class TileSetEditor : public Control { EditMode edit_mode; int current_tile; + float max_scale; + float min_scale; + float scale_ratio; + void update_texture_list(); void update_texture_list_icon(); @@ -178,6 +182,10 @@ private: void _set_snap_off(Vector2 p_val); void _set_snap_sep(Vector2 p_val); + void _zoom_in(); + void _zoom_out(); + void _reset_zoom(); + void draw_highlight_current_tile(); void draw_highlight_subtile(Vector2 coord, const Vector<Vector2> &other_highlighted = Vector<Vector2>()); void draw_tile_subdivision(int p_id, Color p_color) const; diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 63e89b78ea..39e50ec7f8 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -1,10 +1,40 @@ +/*************************************************************************/ +/* visual_shader_editor_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 "visual_shader_editor_plugin.h" #include "core/io/resource_loader.h" +#include "core/os/input.h" +#include "core/os/keyboard.h" #include "core/project_settings.h" #include "editor/editor_properties.h" -#include "os/input.h" -#include "os/keyboard.h" #include "scene/animation/animation_player.h" #include "scene/gui/menu_button.h" #include "scene/gui/panel.h" @@ -480,6 +510,17 @@ void VisualShaderEditor::_connection_request(const String &p_from, int p_from_in } undo_redo->create_action("Nodes Connected"); + + List<VisualShader::Connection> conns; + visual_shader->get_node_connections(type, &conns); + + for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) { + if (E->get().to_node == to && E->get().to_port == p_to_index) { + undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + } + } + undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, from, p_from_index, to, p_to_index); undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index); undo_redo->add_do_method(this, "_update_graph"); @@ -599,7 +640,7 @@ void VisualShaderEditor::_duplicate_nodes() { int id = String(graph->get_child(i)->get_name()).to_int(); Ref<VisualShaderNode> node = visual_shader->get_node(type, id); Ref<VisualShaderNodeOutput> output = node; - if (output.is_valid()) //cant duplicate output + if (output.is_valid()) //can't duplicate output continue; if (node.is_valid()) { nodes.push_back(id); @@ -902,7 +943,10 @@ public: class VisualShaderNodePluginDefaultEditor : public VBoxContainer { GDCLASS(VisualShaderNodePluginDefaultEditor, VBoxContainer) public: - void _property_changed(const String &prop, const Variant &p_value) { + void _property_changed(const String &prop, const Variant &p_value, bool p_changing = false) { + + if (p_changing) + return; UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo(); @@ -949,7 +993,7 @@ public: } static void _bind_methods() { - ClassDB::bind_method("_property_changed", &VisualShaderNodePluginDefaultEditor::_property_changed); + ClassDB::bind_method("_property_changed", &VisualShaderNodePluginDefaultEditor::_property_changed, DEFVAL(false)); ClassDB::bind_method("_node_changed", &VisualShaderNodePluginDefaultEditor::_node_changed); ClassDB::bind_method("_refresh_request", &VisualShaderNodePluginDefaultEditor::_refresh_request); } @@ -1128,7 +1172,7 @@ bool EditorInspectorShaderModePlugin::parse_property(Object *p_object, Variant:: return true; } - return false; //can be overriden, although it will most likely be last anyway + return false; //can be overridden, although it will most likely be last anyway } void EditorInspectorShaderModePlugin::parse_end() { diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h index f86374ff6b..49a51ede8f 100644 --- a/editor/plugins/visual_shader_editor_plugin.h +++ b/editor/plugins/visual_shader_editor_plugin.h @@ -1,3 +1,33 @@ +/*************************************************************************/ +/* visual_shader_editor_plugin.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 VISUAL_SHADER_EDITOR_PLUGIN_H #define VISUAL_SHADER_EDITOR_PLUGIN_H |