diff options
Diffstat (limited to 'editor/plugins')
55 files changed, 1588 insertions, 534 deletions
diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index 1abba45f9e..49e67f3605 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -31,6 +31,7 @@ #include "abstract_polygon_2d_editor.h" #include "canvas_item_editor_plugin.h" +#include "core/math/geometry_2d.h" #include "core/os/keyboard.h" #include "editor/editor_scale.h" @@ -368,7 +369,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) } else { const real_t grab_threshold = EDITOR_GET("editors/poly_editor/point_grab_radius"); - if (!_is_line() && wip.size() > 1 && xform.xform(wip[0]).distance_to(gpoint) < grab_threshold) { + if (!_is_line() && wip.size() > 1 && xform.xform(wip[0]).distance_to(xform.xform(cpoint)) < grab_threshold) { //wip closed _wip_close(); @@ -671,7 +672,7 @@ AbstractPolygon2DEditor::PosVertex AbstractPolygon2DEditor::closest_edge_point(c Vector2 segment[2] = { xform.xform(points[i] + offset), xform.xform(points[(i + 1) % n_points] + offset) }; - Vector2 cp = Geometry::get_closest_point_to_segment_2d(p_pos, segment); + Vector2 cp = Geometry2D::get_closest_point_to_segment(p_pos, segment); if (cp.distance_squared_to(segment[0]) < eps2 || cp.distance_squared_to(segment[1]) < eps2) { continue; //not valid to reuse point @@ -702,17 +703,20 @@ AbstractPolygon2DEditor::AbstractPolygon2DEditor(EditorNode *p_editor, bool p_wi edge_point = PosVertex(); add_child(memnew(VSeparator)); - button_create = memnew(ToolButton); + button_create = memnew(Button); + button_create->set_flat(true); add_child(button_create); button_create->connect("pressed", callable_mp(this, &AbstractPolygon2DEditor::_menu_option), varray(MODE_CREATE)); button_create->set_toggle_mode(true); - button_edit = memnew(ToolButton); + button_edit = memnew(Button); + button_edit->set_flat(true); add_child(button_edit); button_edit->connect("pressed", callable_mp(this, &AbstractPolygon2DEditor::_menu_option), varray(MODE_EDIT)); button_edit->set_toggle_mode(true); - button_delete = memnew(ToolButton); + button_delete = memnew(Button); + button_delete->set_flat(true); add_child(button_delete); button_delete->connect("pressed", callable_mp(this, &AbstractPolygon2DEditor::_menu_option), varray(MODE_DELETE)); button_delete->set_toggle_mode(true); diff --git a/editor/plugins/abstract_polygon_2d_editor.h b/editor/plugins/abstract_polygon_2d_editor.h index d5b3a916d1..b3a17f7660 100644 --- a/editor/plugins/abstract_polygon_2d_editor.h +++ b/editor/plugins/abstract_polygon_2d_editor.h @@ -34,16 +34,15 @@ #include "editor/editor_node.h" #include "editor/editor_plugin.h" #include "scene/2d/polygon_2d.h" -#include "scene/gui/tool_button.h" class CanvasItemEditor; class AbstractPolygon2DEditor : public HBoxContainer { GDCLASS(AbstractPolygon2DEditor, HBoxContainer); - ToolButton *button_create; - ToolButton *button_edit; - ToolButton *button_delete; + Button *button_create; + Button *button_edit; + Button *button_delete; struct Vertex { Vertex() {} diff --git a/editor/plugins/animation_blend_space_1d_editor.cpp b/editor/plugins/animation_blend_space_1d_editor.cpp index 75eacf56ec..959301907c 100644 --- a/editor/plugins/animation_blend_space_1d_editor.cpp +++ b/editor/plugins/animation_blend_space_1d_editor.cpp @@ -595,7 +595,8 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() { Ref<ButtonGroup> bg; bg.instance(); - tool_blend = memnew(ToolButton); + tool_blend = memnew(Button); + tool_blend->set_flat(true); tool_blend->set_toggle_mode(true); tool_blend->set_button_group(bg); top_hb->add_child(tool_blend); @@ -603,14 +604,16 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() { tool_blend->set_tooltip(TTR("Set the blending position within the space")); tool_blend->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_tool_switch), varray(3)); - tool_select = memnew(ToolButton); + tool_select = memnew(Button); + tool_select->set_flat(true); tool_select->set_toggle_mode(true); tool_select->set_button_group(bg); top_hb->add_child(tool_select); tool_select->set_tooltip(TTR("Select and move points, create points with RMB.")); tool_select->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_tool_switch), varray(0)); - tool_create = memnew(ToolButton); + tool_create = memnew(Button); + tool_create->set_flat(true); tool_create->set_toggle_mode(true); tool_create->set_button_group(bg); top_hb->add_child(tool_create); @@ -619,14 +622,16 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() { tool_erase_sep = memnew(VSeparator); top_hb->add_child(tool_erase_sep); - tool_erase = memnew(ToolButton); + tool_erase = memnew(Button); + tool_erase->set_flat(true); top_hb->add_child(tool_erase); tool_erase->set_tooltip(TTR("Erase points.")); tool_erase->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_erase_selected)); top_hb->add_child(memnew(VSeparator)); - snap = memnew(ToolButton); + snap = memnew(Button); + snap->set_flat(true); snap->set_toggle_mode(true); top_hb->add_child(snap); snap->set_pressed(true); diff --git a/editor/plugins/animation_blend_space_1d_editor.h b/editor/plugins/animation_blend_space_1d_editor.h index 8cfd6714ad..c319b648ba 100644 --- a/editor/plugins/animation_blend_space_1d_editor.h +++ b/editor/plugins/animation_blend_space_1d_editor.h @@ -47,15 +47,15 @@ class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin { Ref<AnimationNodeBlendSpace1D> blend_space; HBoxContainer *goto_parent_hb; - ToolButton *goto_parent; + Button *goto_parent; PanelContainer *panel; - ToolButton *tool_blend; - ToolButton *tool_select; - ToolButton *tool_create; + Button *tool_blend; + Button *tool_select; + Button *tool_create; VSeparator *tool_erase_sep; - ToolButton *tool_erase; - ToolButton *snap; + Button *tool_erase; + Button *snap; SpinBox *snap_value; LineEdit *label_value; diff --git a/editor/plugins/animation_blend_space_2d_editor.cpp b/editor/plugins/animation_blend_space_2d_editor.cpp index df67482dfb..1ab114fc01 100644 --- a/editor/plugins/animation_blend_space_2d_editor.cpp +++ b/editor/plugins/animation_blend_space_2d_editor.cpp @@ -32,7 +32,7 @@ #include "core/input/input.h" #include "core/io/resource_loader.h" -#include "core/math/delaunay_2d.h" +#include "core/math/geometry_2d.h" #include "core/os/keyboard.h" #include "core/project_settings.h" #include "editor/editor_scale.h" @@ -165,7 +165,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven triangle.push_back(points[idx]); } - if (Geometry::is_point_in_triangle(mb->get_position(), triangle[0], triangle[1], triangle[2])) { + if (Geometry2D::is_point_in_triangle(mb->get_position(), triangle[0], triangle[1], triangle[2])) { selected_triangle = i; _update_tool_erase(); return; @@ -819,7 +819,8 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() { Ref<ButtonGroup> bg; bg.instance(); - tool_blend = memnew(ToolButton); + tool_blend = memnew(Button); + tool_blend->set_flat(true); tool_blend->set_toggle_mode(true); tool_blend->set_button_group(bg); top_hb->add_child(tool_blend); @@ -827,21 +828,24 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() { tool_blend->set_tooltip(TTR("Set the blending position within the space")); tool_blend->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_tool_switch), varray(3)); - tool_select = memnew(ToolButton); + tool_select = memnew(Button); + tool_select->set_flat(true); tool_select->set_toggle_mode(true); tool_select->set_button_group(bg); top_hb->add_child(tool_select); tool_select->set_tooltip(TTR("Select and move points, create points with RMB.")); tool_select->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_tool_switch), varray(0)); - tool_create = memnew(ToolButton); + tool_create = memnew(Button); + tool_create->set_flat(true); tool_create->set_toggle_mode(true); tool_create->set_button_group(bg); top_hb->add_child(tool_create); tool_create->set_tooltip(TTR("Create points.")); tool_create->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_tool_switch), varray(1)); - tool_triangle = memnew(ToolButton); + tool_triangle = memnew(Button); + tool_triangle->set_flat(true); tool_triangle->set_toggle_mode(true); tool_triangle->set_button_group(bg); top_hb->add_child(tool_triangle); @@ -850,7 +854,8 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() { tool_erase_sep = memnew(VSeparator); top_hb->add_child(tool_erase_sep); - tool_erase = memnew(ToolButton); + tool_erase = memnew(Button); + tool_erase->set_flat(true); top_hb->add_child(tool_erase); tool_erase->set_tooltip(TTR("Erase points and triangles.")); tool_erase->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_erase_selected)); @@ -858,7 +863,8 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() { top_hb->add_child(memnew(VSeparator)); - auto_triangles = memnew(ToolButton); + auto_triangles = memnew(Button); + auto_triangles->set_flat(true); top_hb->add_child(auto_triangles); auto_triangles->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_auto_triangles_toggled)); auto_triangles->set_toggle_mode(true); @@ -866,7 +872,8 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() { top_hb->add_child(memnew(VSeparator)); - snap = memnew(ToolButton); + snap = memnew(Button); + snap->set_flat(true); snap->set_toggle_mode(true); top_hb->add_child(snap); snap->set_pressed(true); diff --git a/editor/plugins/animation_blend_space_2d_editor.h b/editor/plugins/animation_blend_space_2d_editor.h index b430a12297..659b96cefa 100644 --- a/editor/plugins/animation_blend_space_2d_editor.h +++ b/editor/plugins/animation_blend_space_2d_editor.h @@ -47,18 +47,18 @@ class AnimationNodeBlendSpace2DEditor : public AnimationTreeNodeEditorPlugin { Ref<AnimationNodeBlendSpace2D> blend_space; PanelContainer *panel; - ToolButton *tool_blend; - ToolButton *tool_select; - ToolButton *tool_create; - ToolButton *tool_triangle; + Button *tool_blend; + Button *tool_select; + Button *tool_create; + Button *tool_triangle; VSeparator *tool_erase_sep; - ToolButton *tool_erase; - ToolButton *snap; + Button *tool_erase; + Button *snap; SpinBox *snap_x; SpinBox *snap_y; OptionButton *interpolation; - ToolButton *auto_triangles; + Button *auto_triangles; LineEdit *label_x; LineEdit *label_y; diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index 1e0a9535e2..035526ca55 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -380,26 +380,25 @@ void AnimationPlayerEditor::_animation_save_as(const Ref<Resource> &p_resource) file->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper()); } + String path; //file->set_current_path(current_path); if (p_resource->get_path() != "") { - file->set_current_path(p_resource->get_path()); + path = p_resource->get_path(); if (extensions.size()) { - String ext = p_resource->get_path().get_extension().to_lower(); - if (extensions.find(ext) == nullptr) { - file->set_current_path(p_resource->get_path().replacen("." + ext, "." + extensions.front()->get())); + if (extensions.find(p_resource->get_path().get_extension().to_lower()) == nullptr) { + path = p_resource->get_path().get_base_dir() + p_resource->get_name() + "." + extensions.front()->get(); } } } else { - String existing; if (extensions.size()) { if (p_resource->get_name() != "") { - existing = p_resource->get_name() + "." + extensions.front()->get().to_lower(); + path = p_resource->get_name() + "." + extensions.front()->get().to_lower(); } else { - existing = "new_" + p_resource->get_class().to_lower() + "." + extensions.front()->get().to_lower(); + path = "new_" + p_resource->get_class().to_lower() + "." + extensions.front()->get().to_lower(); } } - file->set_current_path(existing); } + file->set_current_path(path); file->popup_centered_ratio(); file->set_title(TTR("Save Resource As...")); current_option = RESOURCE_SAVE; @@ -1503,24 +1502,29 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor, AnimationPlay HBoxContainer *hb = memnew(HBoxContainer); add_child(hb); - play_bw_from = memnew(ToolButton); + play_bw_from = memnew(Button); + play_bw_from->set_flat(true); play_bw_from->set_tooltip(TTR("Play selected animation backwards from current pos. (A)")); hb->add_child(play_bw_from); - play_bw = memnew(ToolButton); + play_bw = memnew(Button); + play_bw->set_flat(true); play_bw->set_tooltip(TTR("Play selected animation backwards from end. (Shift+A)")); hb->add_child(play_bw); - stop = memnew(ToolButton); + stop = memnew(Button); + stop->set_flat(true); stop->set_toggle_mode(true); hb->add_child(stop); stop->set_tooltip(TTR("Stop animation playback. (S)")); - play = memnew(ToolButton); + play = memnew(Button); + play->set_flat(true); play->set_tooltip(TTR("Play selected animation from start. (Shift+D)")); hb->add_child(play); - play_from = memnew(ToolButton); + play_from = memnew(Button); + play_from->set_flat(true); play_from->set_tooltip(TTR("Play selected animation from current pos. (D)")); hb->add_child(play_from); @@ -1572,7 +1576,8 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor, AnimationPlay animation->set_tooltip(TTR("Display list of animations in player.")); animation->set_clip_text(true); - autoplay = memnew(ToolButton); + autoplay = memnew(Button); + autoplay->set_flat(true); hb->add_child(autoplay); autoplay->set_tooltip(TTR("Autoplay on Load")); @@ -1584,7 +1589,8 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor, AnimationPlay hb->add_child(memnew(VSeparator)); - onion_toggle = memnew(ToolButton); + onion_toggle = memnew(Button); + onion_toggle->set_flat(true); onion_toggle->set_toggle_mode(true); onion_toggle->set_tooltip(TTR("Enable Onion Skinning")); onion_toggle->connect("pressed", callable_mp(this, &AnimationPlayerEditor::_onion_skinning_menu), varray(ONION_SKINNING_ENABLE)); @@ -1609,7 +1615,8 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor, AnimationPlay hb->add_child(memnew(VSeparator)); - pin = memnew(ToolButton); + pin = memnew(Button); + pin->set_flat(true); pin->set_toggle_mode(true); pin->set_tooltip(TTR("Pin AnimationPlayer")); hb->add_child(pin); diff --git a/editor/plugins/animation_player_editor_plugin.h b/editor/plugins/animation_player_editor_plugin.h index 18f2d3b25e..fe96deecf2 100644 --- a/editor/plugins/animation_player_editor_plugin.h +++ b/editor/plugins/animation_player_editor_plugin.h @@ -96,9 +96,9 @@ class AnimationPlayerEditor : public VBoxContainer { Button *autoplay; MenuButton *tool_anim; - ToolButton *onion_toggle; + Button *onion_toggle; MenuButton *onion_skinning; - ToolButton *pin; + Button *pin; SpinBox *frame; LineEdit *scale; LineEdit *name; diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp index 652754a146..0970608853 100644 --- a/editor/plugins/animation_state_machine_editor.cpp +++ b/editor/plugins/animation_state_machine_editor.cpp @@ -32,7 +32,7 @@ #include "core/input/input.h" #include "core/io/resource_loader.h" -#include "core/math/delaunay_2d.h" +#include "core/math/geometry_2d.h" #include "core/os/keyboard.h" #include "core/project_settings.h" #include "editor/editor_scale.h" @@ -191,7 +191,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv transition_lines[i].from, transition_lines[i].to }; - Vector2 cpoint = Geometry::get_closest_point_to_segment_2d(mb->get_position(), s); + Vector2 cpoint = Geometry2D::get_closest_point_to_segment(mb->get_position(), s); float d = cpoint.distance_to(mb->get_position()); if (d > transition_lines[i].width) { continue; @@ -1208,7 +1208,8 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() { Ref<ButtonGroup> bg; bg.instance(); - tool_select = memnew(ToolButton); + tool_select = memnew(Button); + tool_select->set_flat(true); top_hb->add_child(tool_select); tool_select->set_toggle_mode(true); tool_select->set_button_group(bg); @@ -1216,14 +1217,16 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() { tool_select->set_tooltip(TTR("Select and move nodes.\nRMB to add new nodes.\nShift+LMB to create connections.")); tool_select->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_update_mode), varray(), CONNECT_DEFERRED); - tool_create = memnew(ToolButton); + tool_create = memnew(Button); + tool_create->set_flat(true); top_hb->add_child(tool_create); tool_create->set_toggle_mode(true); tool_create->set_button_group(bg); tool_create->set_tooltip(TTR("Create new nodes.")); tool_create->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_update_mode), varray(), CONNECT_DEFERRED); - tool_connect = memnew(ToolButton); + tool_connect = memnew(Button); + tool_connect->set_flat(true); top_hb->add_child(tool_connect); tool_connect->set_toggle_mode(true); tool_connect->set_button_group(bg); @@ -1233,7 +1236,8 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() { tool_erase_hb = memnew(HBoxContainer); top_hb->add_child(tool_erase_hb); tool_erase_hb->add_child(memnew(VSeparator)); - tool_erase = memnew(ToolButton); + tool_erase = memnew(Button); + tool_erase->set_flat(true); tool_erase->set_tooltip(TTR("Remove selected node or transition.")); tool_erase_hb->add_child(tool_erase); tool_erase->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_erase_selected)); @@ -1241,13 +1245,15 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() { tool_erase_hb->add_child(memnew(VSeparator)); - tool_autoplay = memnew(ToolButton); + tool_autoplay = memnew(Button); + tool_autoplay->set_flat(true); tool_autoplay->set_tooltip(TTR("Toggle autoplay this animation on start, restart or seek to zero.")); tool_erase_hb->add_child(tool_autoplay); tool_autoplay->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_autoplay_selected)); tool_autoplay->set_disabled(true); - tool_end = memnew(ToolButton); + tool_end = memnew(Button); + tool_end->set_flat(true); tool_end->set_tooltip(TTR("Set the end animation. This is useful for sub-transitions.")); tool_erase_hb->add_child(tool_end); tool_end->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_end_selected)); diff --git a/editor/plugins/animation_state_machine_editor.h b/editor/plugins/animation_state_machine_editor.h index 022c32ef48..c4caf2e52b 100644 --- a/editor/plugins/animation_state_machine_editor.h +++ b/editor/plugins/animation_state_machine_editor.h @@ -46,16 +46,16 @@ class AnimationNodeStateMachineEditor : public AnimationTreeNodeEditorPlugin { Ref<AnimationNodeStateMachine> state_machine; - ToolButton *tool_select; - ToolButton *tool_create; - ToolButton *tool_connect; + Button *tool_select; + Button *tool_create; + Button *tool_connect; Popup *name_edit_popup; LineEdit *name_edit; HBoxContainer *tool_erase_hb; - ToolButton *tool_erase; - ToolButton *tool_autoplay; - ToolButton *tool_end; + Button *tool_erase; + Button *tool_autoplay; + Button *tool_end; OptionButton *transition_mode; OptionButton *play_mode; diff --git a/editor/plugins/audio_stream_editor_plugin.cpp b/editor/plugins/audio_stream_editor_plugin.cpp index 3b7a9320f0..b0f65af245 100644 --- a/editor/plugins/audio_stream_editor_plugin.cpp +++ b/editor/plugins/audio_stream_editor_plugin.cpp @@ -220,12 +220,14 @@ AudioStreamEditor::AudioStreamEditor() { hbox->add_theme_constant_override("separation", 0); vbox->add_child(hbox); - _play_button = memnew(ToolButton); + _play_button = memnew(Button); + _play_button->set_flat(true); hbox->add_child(_play_button); _play_button->set_focus_mode(Control::FOCUS_NONE); _play_button->connect("pressed", callable_mp(this, &AudioStreamEditor::_play)); - _stop_button = memnew(ToolButton); + _stop_button = memnew(Button); + _stop_button->set_flat(true); hbox->add_child(_stop_button); _stop_button->set_focus_mode(Control::FOCUS_NONE); _stop_button->connect("pressed", callable_mp(this, &AudioStreamEditor::_stop)); diff --git a/editor/plugins/audio_stream_editor_plugin.h b/editor/plugins/audio_stream_editor_plugin.h index dd7caaa15e..de176aab49 100644 --- a/editor/plugins/audio_stream_editor_plugin.h +++ b/editor/plugins/audio_stream_editor_plugin.h @@ -47,8 +47,8 @@ class AudioStreamEditor : public ColorRect { Label *_current_label; Label *_duration_label; - ToolButton *_play_button; - ToolButton *_stop_button; + Button *_play_button; + Button *_stop_button; float _current; bool _dragging; diff --git a/editor/plugins/baked_lightmap_editor_plugin.cpp b/editor/plugins/baked_lightmap_editor_plugin.cpp index 8fbe1646f7..ee9feb7f74 100644 --- a/editor/plugins/baked_lightmap_editor_plugin.cpp +++ b/editor/plugins/baked_lightmap_editor_plugin.cpp @@ -117,7 +117,8 @@ void BakedLightmapEditorPlugin::_bind_methods() { BakedLightmapEditorPlugin::BakedLightmapEditorPlugin(EditorNode *p_node) { editor = p_node; - bake = memnew(ToolButton); + bake = memnew(Button); + bake->set_flat(true); bake->set_icon(editor->get_gui_base()->get_theme_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 67fb368a86..54eb0f71ec 100644 --- a/editor/plugins/baked_lightmap_editor_plugin.h +++ b/editor/plugins/baked_lightmap_editor_plugin.h @@ -41,7 +41,7 @@ class BakedLightmapEditorPlugin : public EditorPlugin { BakedLightmap *lightmap; - ToolButton *bake; + Button *bake; EditorNode *editor; EditorFileDialog *file_dialog; diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 744c7907af..3af0b0d4e1 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -31,6 +31,7 @@ #include "canvas_item_editor_plugin.h" #include "core/input/input.h" +#include "core/math/geometry_2d.h" #include "core/os/keyboard.h" #include "core/print_string.h" #include "core/project_settings.h" @@ -53,8 +54,10 @@ #include "scene/main/window.h" #include "scene/resources/packed_scene.h" -#define MIN_ZOOM 0.01 -#define MAX_ZOOM 100 +// Min and Max are power of two in order to play nicely with successive increment. +// That way, we can naturally reach a 100% zoom from boundaries. +#define MIN_ZOOM 1. / 128 +#define MAX_ZOOM 128 #define RULER_WIDTH (15 * EDSCALE) #define SCALE_HANDLE_DISTANCE 25 @@ -86,7 +89,6 @@ public: GridContainer *child_container; set_title(TTR("Configure Snap")); - get_ok()->set_text(TTR("Close")); container = memnew(VBoxContainer); add_child(container); @@ -672,7 +674,7 @@ void CanvasItemEditor::_get_bones_at_pos(const Point2 &p_pos, Vector<_SelectResu } // Check if the point is inside the Polygon2D - if (Geometry::is_point_in_polygon(screen_pos, bone_shape)) { + if (Geometry2D::is_point_in_polygon(screen_pos, bone_shape)) { // Check if the item is already in the list bool duplicate = false; for (int i = 0; i < r_items.size(); i++) { @@ -1205,7 +1207,26 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_eve bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bool p_already_accepted) { Ref<InputEventMouseButton> b = p_event; if (b.is_valid() && !p_already_accepted) { - bool pan_on_scroll = bool(EditorSettings::get_singleton()->get("editors/2d/scroll_to_pan")) && !b->get_control(); + const bool pan_on_scroll = bool(EditorSettings::get_singleton()->get("editors/2d/scroll_to_pan")) && !b->get_control(); + + if (pan_on_scroll) { + // Perform horizontal scrolling first so we can check for Shift being held. + if (b->is_pressed() && + (b->get_button_index() == BUTTON_WHEEL_LEFT || (b->get_shift() && b->get_button_index() == BUTTON_WHEEL_UP))) { + // Pan left + view_offset.x -= int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); + update_viewport(); + return true; + } + + if (b->is_pressed() && + (b->get_button_index() == BUTTON_WHEEL_RIGHT || (b->get_shift() && b->get_button_index() == BUTTON_WHEEL_DOWN))) { + // Pan right + view_offset.x += int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); + update_viewport(); + return true; + } + } if (b->is_pressed() && b->get_button_index() == BUTTON_WHEEL_DOWN) { // Scroll or pan down @@ -1213,7 +1234,11 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo view_offset.y += int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); update_viewport(); } else { - _zoom_on_position(zoom * (1 - (0.05 * b->get_factor())), b->get_position()); + float new_zoom = _get_next_zoom_value(-1); + if (b->get_factor() != 1.f) { + new_zoom = zoom * ((new_zoom / zoom - 1.f) * b->get_factor() + 1.f); + } + _zoom_on_position(new_zoom, b->get_position()); } return true; } @@ -1224,29 +1249,15 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo view_offset.y -= int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); update_viewport(); } else { - _zoom_on_position(zoom * ((0.95 + (0.05 * b->get_factor())) / 0.95), b->get_position()); + float new_zoom = _get_next_zoom_value(1); + if (b->get_factor() != 1.f) { + new_zoom = zoom * ((new_zoom / zoom - 1.f) * b->get_factor() + 1.f); + } + _zoom_on_position(new_zoom, b->get_position()); } return true; } - if (b->is_pressed() && b->get_button_index() == BUTTON_WHEEL_LEFT) { - // Pan left - if (pan_on_scroll) { - view_offset.x -= int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); - update_viewport(); - return true; - } - } - - if (b->is_pressed() && b->get_button_index() == BUTTON_WHEEL_RIGHT) { - // Pan right - if (pan_on_scroll) { - view_offset.x += int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); - update_viewport(); - return true; - } - } - if (!panning) { if (b->is_pressed() && (b->get_button_index() == BUTTON_MIDDLE || @@ -1315,6 +1326,18 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo Ref<InputEventPanGesture> pan_gesture = p_event; if (pan_gesture.is_valid() && !p_already_accepted) { + // If control key pressed, then zoom instead of pan + if (pan_gesture->get_control()) { + const float factor = pan_gesture->get_delta().y; + float new_zoom = _get_next_zoom_value(-1); + + if (factor != 1.f) { + new_zoom = zoom * ((new_zoom / zoom - 1.f) * factor + 1.f); + } + _zoom_on_position(new_zoom, pan_gesture->get_position()); + return true; + } + // Pan gesture const Vector2 delta = (int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom) * pan_gesture->get_delta(); view_offset.x += delta.x; @@ -2240,7 +2263,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { return true; } - if (k.is_valid() && !k->is_pressed() && drag_type == DRAG_KEY_MOVE && tool == TOOL_SELECT && + if (k.is_valid() && !k->is_pressed() && drag_type == DRAG_KEY_MOVE && (tool == TOOL_SELECT || tool == TOOL_MOVE) && (k->get_keycode() == KEY_UP || k->get_keycode() == KEY_DOWN || k->get_keycode() == KEY_LEFT || k->get_keycode() == KEY_RIGHT)) { // Confirm canvas items move by arrow keys if ((!Input::get_singleton()->is_key_pressed(KEY_UP)) && @@ -4333,8 +4356,37 @@ void CanvasItemEditor::_set_anchors_preset(Control::LayoutPreset p_preset) { undo_redo->commit_action(); } +float CanvasItemEditor::_get_next_zoom_value(int p_increment_count) const { + // Base increment factor defined as the twelveth root of two. + // This allow a smooth geometric evolution of the zoom, with the advantage of + // visiting all integer power of two scale factors. + // note: this is analogous to the 'semitones' interval in the music world + // In order to avoid numerical imprecisions, we compute and edit a zoom index + // with the following relation: zoom = 2 ^ (index / 12) + + if (zoom < CMP_EPSILON || p_increment_count == 0) { + return 1.f; + } + + // Remove Editor scale from the index computation + float zoom_noscale = zoom / MAX(1, EDSCALE); + + // zoom = 2**(index/12) => log2(zoom) = index/12 + float closest_zoom_index = Math::round(Math::log(zoom_noscale) * 12.f / Math::log(2.f)); + + float new_zoom_index = closest_zoom_index + p_increment_count; + float new_zoom = Math::pow(2.f, new_zoom_index / 12.f); + + // Restore Editor scale transformation + new_zoom *= MAX(1, EDSCALE); + + return new_zoom; +} + void CanvasItemEditor::_zoom_on_position(float p_zoom, Point2 p_position) { - if (p_zoom < MIN_ZOOM || p_zoom > MAX_ZOOM) { + p_zoom = CLAMP(p_zoom, MIN_ZOOM, MAX_ZOOM); + + if (p_zoom == zoom) { return; } @@ -4376,7 +4428,7 @@ void CanvasItemEditor::_update_zoom_label() { } void CanvasItemEditor::_button_zoom_minus() { - _zoom_on_position(zoom / Math_SQRT2, viewport_scrollable->get_size() / 2.0); + _zoom_on_position(_get_next_zoom_value(-6), viewport_scrollable->get_size() / 2.0); } void CanvasItemEditor::_button_zoom_reset() { @@ -4384,7 +4436,7 @@ void CanvasItemEditor::_button_zoom_reset() { } void CanvasItemEditor::_button_zoom_plus() { - _zoom_on_position(zoom * Math_SQRT2, viewport_scrollable->get_size() / 2.0); + _zoom_on_position(_get_next_zoom_value(6), viewport_scrollable->get_size() / 2.0); } void CanvasItemEditor::_button_toggle_smart_snap(bool p_status) { @@ -4408,7 +4460,7 @@ void CanvasItemEditor::_button_override_camera(bool p_pressed) { } void CanvasItemEditor::_button_tool_select(int p_index) { - ToolButton *tb[TOOL_MAX] = { select_button, list_select_button, move_button, scale_button, rotate_button, pivot_button, pan_button, ruler_button }; + Button *tb[TOOL_MAX] = { select_button, list_select_button, move_button, scale_button, rotate_button, pivot_button, pan_button, ruler_button }; for (int i = 0; i < TOOL_MAX; i++) { tb[i]->set_pressed(i == p_index); } @@ -5538,13 +5590,15 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { viewport->add_child(controls_vb); - zoom_minus = memnew(ToolButton); + zoom_minus = memnew(Button); + zoom_minus->set_flat(true); zoom_hb->add_child(zoom_minus); zoom_minus->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_zoom_minus)); zoom_minus->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_minus", TTR("Zoom Out"), KEY_MASK_CMD | KEY_MINUS)); zoom_minus->set_focus_mode(FOCUS_NONE); - zoom_reset = memnew(ToolButton); + zoom_reset = memnew(Button); + zoom_reset->set_flat(true); zoom_hb->add_child(zoom_reset); zoom_reset->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_zoom_reset)); zoom_reset->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_reset", TTR("Zoom Reset"), KEY_MASK_CMD | KEY_0)); @@ -5553,7 +5607,8 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { // Prevent the button's size from changing when the text size changes zoom_reset->set_custom_minimum_size(Size2(75 * EDSCALE, 0)); - zoom_plus = memnew(ToolButton); + zoom_plus = memnew(Button); + zoom_plus->set_flat(true); zoom_hb->add_child(zoom_plus); zoom_plus->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_zoom_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 @@ -5561,7 +5616,8 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { updating_scroll = false; - select_button = memnew(ToolButton); + select_button = memnew(Button); + select_button->set_flat(true); hb->add_child(select_button); select_button->set_toggle_mode(true); select_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_SELECT)); @@ -5571,21 +5627,24 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { hb->add_child(memnew(VSeparator)); - move_button = memnew(ToolButton); + move_button = memnew(Button); + move_button->set_flat(true); hb->add_child(move_button); move_button->set_toggle_mode(true); move_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_MOVE)); move_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/move_mode", TTR("Move Mode"), KEY_W)); move_button->set_tooltip(TTR("Move Mode")); - rotate_button = memnew(ToolButton); + rotate_button = memnew(Button); + rotate_button->set_flat(true); hb->add_child(rotate_button); rotate_button->set_toggle_mode(true); rotate_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_ROTATE)); 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); + scale_button = memnew(Button); + scale_button->set_flat(true); hb->add_child(scale_button); scale_button->set_toggle_mode(true); scale_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_SCALE)); @@ -5594,25 +5653,30 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { hb->add_child(memnew(VSeparator)); - list_select_button = memnew(ToolButton); + list_select_button = memnew(Button); + list_select_button->set_flat(true); hb->add_child(list_select_button); list_select_button->set_toggle_mode(true); list_select_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_LIST_SELECT)); list_select_button->set_tooltip(TTR("Show a list of all objects at the position clicked\n(same as Alt+RMB in select mode).")); - pivot_button = memnew(ToolButton); + pivot_button = memnew(Button); + pivot_button->set_flat(true); hb->add_child(pivot_button); pivot_button->set_toggle_mode(true); pivot_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_EDIT_PIVOT)); pivot_button->set_tooltip(TTR("Click to change object's rotation pivot.")); - pan_button = memnew(ToolButton); + pan_button = memnew(Button); + pan_button->set_flat(true); hb->add_child(pan_button); pan_button->set_toggle_mode(true); pan_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_PAN)); + pan_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/pan_mode", TTR("Pan Mode"), KEY_G)); pan_button->set_tooltip(TTR("Pan Mode")); - ruler_button = memnew(ToolButton); + ruler_button = memnew(Button); + ruler_button->set_flat(true); hb->add_child(ruler_button); ruler_button->set_toggle_mode(true); ruler_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_RULER)); @@ -5621,14 +5685,16 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { hb->add_child(memnew(VSeparator)); - smart_snap_button = memnew(ToolButton); + smart_snap_button = memnew(Button); + smart_snap_button->set_flat(true); hb->add_child(smart_snap_button); smart_snap_button->set_toggle_mode(true); smart_snap_button->connect("toggled", callable_mp(this, &CanvasItemEditor::_button_toggle_smart_snap)); smart_snap_button->set_tooltip(TTR("Toggle smart snapping.")); smart_snap_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/use_smart_snap", TTR("Use Smart Snap"), KEY_MASK_SHIFT | KEY_S)); - grid_snap_button = memnew(ToolButton); + grid_snap_button = memnew(Button); + grid_snap_button->set_flat(true); hb->add_child(grid_snap_button); grid_snap_button->set_toggle_mode(true); grid_snap_button->connect("toggled", callable_mp(this, &CanvasItemEditor::_button_toggle_grid_snap)); @@ -5667,23 +5733,27 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { hb->add_child(memnew(VSeparator)); - lock_button = memnew(ToolButton); + lock_button = memnew(Button); + lock_button->set_flat(true); hb->add_child(lock_button); lock_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(LOCK_SELECTED)); lock_button->set_tooltip(TTR("Lock the selected object in place (can't be moved).")); - unlock_button = memnew(ToolButton); + unlock_button = memnew(Button); + unlock_button->set_flat(true); hb->add_child(unlock_button); unlock_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(UNLOCK_SELECTED)); unlock_button->set_tooltip(TTR("Unlock the selected object (can be moved).")); - group_button = memnew(ToolButton); + group_button = memnew(Button); + group_button->set_flat(true); hb->add_child(group_button); group_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(GROUP_SELECTED)); group_button->set_tooltip(TTR("Makes sure the object's children are not selectable.")); - ungroup_button = memnew(ToolButton); + ungroup_button = memnew(Button); + ungroup_button->set_flat(true); hb->add_child(ungroup_button); ungroup_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(UNGROUP_SELECTED)); ungroup_button->set_tooltip(TTR("Restores the object's children's ability to be selected.")); @@ -5708,7 +5778,8 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { hb->add_child(memnew(VSeparator)); - override_camera_button = memnew(ToolButton); + override_camera_button = memnew(Button); + override_camera_button->set_flat(true); hb->add_child(override_camera_button); override_camera_button->connect("toggled", callable_mp(this, &CanvasItemEditor::_button_override_camera)); override_camera_button->set_toggle_mode(true); @@ -5755,7 +5826,8 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { anchors_popup->set_name("Anchors"); anchors_popup->connect("id_pressed", callable_mp(this, &CanvasItemEditor::_popup_callback)); - anchor_mode_button = memnew(ToolButton); + anchor_mode_button = memnew(Button); + anchor_mode_button->set_flat(true); hb->add_child(anchor_mode_button); anchor_mode_button->set_toggle_mode(true); anchor_mode_button->hide(); @@ -6077,6 +6149,11 @@ bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, cons 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); + // Preserve instance position of the original scene. + CanvasItem *instance_ci = Object::cast_to<CanvasItem>(instanced_scene); + if (instance_ci) { + target_pos += instance_ci->_edit_get_position(); + } editor_data->get_undo_redo().add_do_method(instanced_scene, "set_position", target_pos); } diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index a686c98f65..c5d74c6fc9 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -228,9 +228,9 @@ private: VScrollBar *v_scroll; HBoxContainer *hb; - ToolButton *zoom_minus; - ToolButton *zoom_reset; - ToolButton *zoom_plus; + Button *zoom_minus; + Button *zoom_reset; + Button *zoom_plus; Map<Control *, Timer *> popup_temporarily_timers; @@ -336,31 +336,31 @@ private: }; List<PoseClipboard> pose_clipboard; - ToolButton *select_button; + Button *select_button; - ToolButton *move_button; - ToolButton *scale_button; - ToolButton *rotate_button; + Button *move_button; + Button *scale_button; + Button *rotate_button; - ToolButton *list_select_button; - ToolButton *pivot_button; - ToolButton *pan_button; + Button *list_select_button; + Button *pivot_button; + Button *pan_button; - ToolButton *ruler_button; + Button *ruler_button; - ToolButton *smart_snap_button; - ToolButton *grid_snap_button; + Button *smart_snap_button; + Button *grid_snap_button; MenuButton *snap_config_menu; PopupMenu *smartsnap_config_popup; - ToolButton *lock_button; - ToolButton *unlock_button; + Button *lock_button; + Button *unlock_button; - ToolButton *group_button; - ToolButton *ungroup_button; + Button *group_button; + Button *ungroup_button; MenuButton *skeleton_menu; - ToolButton *override_camera_button; + Button *override_camera_button; MenuButton *view_menu; HBoxContainer *animation_hb; MenuButton *animation_menu; @@ -369,7 +369,7 @@ private: PopupMenu *anchors_and_margins_popup; PopupMenu *anchors_popup; - ToolButton *anchor_mode_button; + Button *anchor_mode_button; Button *key_loc_button; Button *key_rot_button; @@ -528,6 +528,7 @@ private: VBoxContainer *controls_vb; HBoxContainer *zoom_hb; + float _get_next_zoom_value(int p_increment_count) const; void _zoom_on_position(float p_zoom, Point2 p_position = Point2()); void _update_zoom_label(); void _button_zoom_minus(); diff --git a/editor/plugins/collision_polygon_3d_editor_plugin.cpp b/editor/plugins/collision_polygon_3d_editor_plugin.cpp index c61d410d38..6eb17685f6 100644 --- a/editor/plugins/collision_polygon_3d_editor_plugin.cpp +++ b/editor/plugins/collision_polygon_3d_editor_plugin.cpp @@ -32,6 +32,7 @@ #include "canvas_item_editor_plugin.h" #include "core/input/input.h" +#include "core/math/geometry_2d.h" #include "core/os/file_access.h" #include "core/os/keyboard.h" #include "editor/editor_settings.h" @@ -196,7 +197,7 @@ bool CollisionPolygon3DEditor::forward_spatial_gui_input(Camera3D *p_camera, con p_camera->unproject_position(gt.xform(Vector3(poly[(i + 1) % poly.size()].x, poly[(i + 1) % poly.size()].y, depth))) }; - Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint, points); + Vector2 cp = Geometry2D::get_closest_point_to_segment(gpoint, points); if (cp.distance_squared_to(points[0]) < CMP_EPSILON2 || cp.distance_squared_to(points[1]) < CMP_EPSILON2) { continue; //not valid to reuse point } @@ -500,12 +501,14 @@ CollisionPolygon3DEditor::CollisionPolygon3DEditor(EditorNode *p_editor) { undo_redo = EditorNode::get_undo_redo(); add_child(memnew(VSeparator)); - button_create = memnew(ToolButton); + button_create = memnew(Button); + button_create->set_flat(true); add_child(button_create); button_create->connect("pressed", callable_mp(this, &CollisionPolygon3DEditor::_menu_option), varray(MODE_CREATE)); button_create->set_toggle_mode(true); - button_edit = memnew(ToolButton); + button_edit = memnew(Button); + button_edit->set_flat(true); add_child(button_edit); button_edit->connect("pressed", callable_mp(this, &CollisionPolygon3DEditor::_menu_option), varray(MODE_EDIT)); button_edit->set_toggle_mode(true); diff --git a/editor/plugins/collision_polygon_3d_editor_plugin.h b/editor/plugins/collision_polygon_3d_editor_plugin.h index 5215cbb678..05b8df520c 100644 --- a/editor/plugins/collision_polygon_3d_editor_plugin.h +++ b/editor/plugins/collision_polygon_3d_editor_plugin.h @@ -36,7 +36,6 @@ #include "scene/3d/collision_polygon_3d.h" #include "scene/3d/immediate_geometry_3d.h" #include "scene/3d/mesh_instance_3d.h" -#include "scene/gui/tool_button.h" class CanvasItemEditor; @@ -53,8 +52,8 @@ class CollisionPolygon3DEditor : public HBoxContainer { Mode mode; - ToolButton *button_create; - ToolButton *button_edit; + Button *button_create; + Button *button_edit; Ref<StandardMaterial3D> line_material; Ref<StandardMaterial3D> handle_material; diff --git a/editor/plugins/collision_shape_2d_editor_plugin.cpp b/editor/plugins/collision_shape_2d_editor_plugin.cpp index 0f381c06b4..596629f8e8 100644 --- a/editor/plugins/collision_shape_2d_editor_plugin.cpp +++ b/editor/plugins/collision_shape_2d_editor_plugin.cpp @@ -36,6 +36,7 @@ #include "scene/resources/concave_polygon_shape_2d.h" #include "scene/resources/convex_polygon_shape_2d.h" #include "scene/resources/line_shape_2d.h" +#include "scene/resources/ray_shape_2d.h" #include "scene/resources/rectangle_shape_2d.h" #include "scene/resources/segment_shape_2d.h" diff --git a/editor/plugins/debugger_editor_plugin.cpp b/editor/plugins/debugger_editor_plugin.cpp index 0ca479555d..0a4d173923 100644 --- a/editor/plugins/debugger_editor_plugin.cpp +++ b/editor/plugins/debugger_editor_plugin.cpp @@ -68,13 +68,10 @@ DebuggerEditorPlugin::DebuggerEditorPlugin(EditorNode *p_editor, MenuButton *p_d p->add_check_shortcut(ED_SHORTCUT("editor/visible_navigation", TTR("Visible Navigation")), RUN_DEBUG_NAVIGATION); p->set_item_tooltip(p->get_item_count() - 1, TTR("Navigation meshes and polygons will be visible on the running game if this option is turned on.")); p->add_separator(); - //those are now on by default, since they are harmless p->add_check_shortcut(ED_SHORTCUT("editor/sync_scene_changes", TTR("Sync Scene Changes")), RUN_LIVE_DEBUG); p->set_item_tooltip(p->get_item_count() - 1, TTR("When this option is turned on, any changes made to the scene in the editor will be replicated in the running game.\nWhen used remotely on a device, this is more efficient with network filesystem.")); - p->set_item_checked(p->get_item_count() - 1, true); p->add_check_shortcut(ED_SHORTCUT("editor/sync_script_changes", TTR("Sync Script Changes")), RUN_RELOAD_SCRIPTS); p->set_item_tooltip(p->get_item_count() - 1, TTR("When this option is turned on, any script that is saved will be reloaded on the running game.\nWhen used remotely on a device, this is more efficient with network filesystem.")); - p->set_item_checked(p->get_item_count() - 1, true); // Multi-instance, start/stop instances_menu = memnew(PopupMenu); @@ -174,8 +171,8 @@ void DebuggerEditorPlugin::_update_debug_options() { bool check_file_server = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_file_server", false); bool check_debug_collisions = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_debug_collisons", false); bool check_debug_navigation = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_debug_navigation", false); - bool check_live_debug = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_live_debug", false); - bool check_reload_scripts = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_reload_scripts", false); + bool check_live_debug = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_live_debug", true); + bool check_reload_scripts = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_reload_scripts", true); int instances = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_debug_instances", 1); if (check_deploy_remote) { diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index 9cb167b41c..2889cb50a0 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -127,7 +127,8 @@ Ref<Texture2D> EditorTexturePreviewPlugin::generate(const RES &p_from, const Siz 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); + Vector2i new_size_i(MAX(1, (int)new_size.x), MAX(1, (int)new_size.y)); + img->resize(new_size_i.x, new_size_i.y, Image::INTERPOLATE_CUBIC); post_process_preview(img); diff --git a/editor/plugins/gi_probe_editor_plugin.cpp b/editor/plugins/gi_probe_editor_plugin.cpp index 94f771e643..1b48e17772 100644 --- a/editor/plugins/gi_probe_editor_plugin.cpp +++ b/editor/plugins/gi_probe_editor_plugin.cpp @@ -144,7 +144,8 @@ GIProbeEditorPlugin::GIProbeEditorPlugin(EditorNode *p_node) { bake_hb = memnew(HBoxContainer); bake_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL); bake_hb->hide(); - bake = memnew(ToolButton); + bake = memnew(Button); + bake->set_flat(true); bake->set_icon(editor->get_gui_base()->get_theme_icon("Bake", "EditorIcons")); bake->set_text(TTR("Bake GI Probe")); bake->connect("pressed", callable_mp(this, &GIProbeEditorPlugin::_bake)); diff --git a/editor/plugins/gi_probe_editor_plugin.h b/editor/plugins/gi_probe_editor_plugin.h index 508c3d825b..e55f287908 100644 --- a/editor/plugins/gi_probe_editor_plugin.h +++ b/editor/plugins/gi_probe_editor_plugin.h @@ -43,7 +43,7 @@ class GIProbeEditorPlugin : public EditorPlugin { HBoxContainer *bake_hb; Label *bake_info; - ToolButton *bake; + Button *bake; EditorNode *editor; EditorFileDialog *probe_file; diff --git a/editor/plugins/item_list_editor_plugin.cpp b/editor/plugins/item_list_editor_plugin.cpp index 7402baad57..b4dcbdfe20 100644 --- a/editor/plugins/item_list_editor_plugin.cpp +++ b/editor/plugins/item_list_editor_plugin.cpp @@ -325,7 +325,8 @@ ItemListEditor::ItemListEditor() { selected_idx = -1; item_list = nullptr; - toolbar_button = memnew(ToolButton); + toolbar_button = memnew(Button); + toolbar_button->set_flat(true); toolbar_button->set_text(TTR("Items")); add_child(toolbar_button); toolbar_button->connect("pressed", callable_mp(this, &ItemListEditor::_edit_items)); diff --git a/editor/plugins/item_list_editor_plugin.h b/editor/plugins/item_list_editor_plugin.h index 61dd617e3b..d89631633c 100644 --- a/editor/plugins/item_list_editor_plugin.h +++ b/editor/plugins/item_list_editor_plugin.h @@ -198,7 +198,7 @@ class ItemListEditor : public HBoxContainer { Node *item_list; - ToolButton *toolbar_button; + Button *toolbar_button; AcceptDialog *dialog; EditorInspector *property_editor; diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 3c12022854..b51ea9e1c6 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -328,17 +328,13 @@ void Node3DEditorViewport::_update_camera(float p_interp_delta) { //------- // Apply camera transform - float tolerance = 0.001; + real_t tolerance = 0.001; bool equal = true; - if (Math::abs(old_camera_cursor.x_rot - camera_cursor.x_rot) > tolerance || Math::abs(old_camera_cursor.y_rot - camera_cursor.y_rot) > tolerance) { + if (!Math::is_equal_approx(old_camera_cursor.x_rot, camera_cursor.x_rot, tolerance) || !Math::is_equal_approx(old_camera_cursor.y_rot, camera_cursor.y_rot, tolerance)) { equal = false; - } - - if (equal && old_camera_cursor.pos.distance_squared_to(camera_cursor.pos) > tolerance * tolerance) { + } else if (!old_camera_cursor.pos.is_equal_approx(camera_cursor.pos)) { equal = false; - } - - if (equal && Math::abs(old_camera_cursor.distance - camera_cursor.distance) > tolerance) { + } else if (!Math::is_equal_approx(old_camera_cursor.distance, camera_cursor.distance, tolerance)) { equal = false; } @@ -356,6 +352,7 @@ void Node3DEditorViewport::_update_camera(float p_interp_delta) { update_transform_gizmo_view(); rotation_control->update(); } + spatial_editor->update_grid(); } Transform Node3DEditorViewport::to_camera_transform(const Cursor &p_cursor) const { @@ -490,6 +487,10 @@ ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, b Vector3 pos = _get_ray_pos(p_pos); Vector2 shrinked_pos = p_pos / subviewport_container->get_stretch_shrink(); + if (viewport->get_debug_draw() == Viewport::DEBUG_DRAW_SDFGI_PROBES) { + RS::get_singleton()->sdfgi_set_debug_probe_select(pos, ray); + } + Vector<ObjectID> instances = RenderingServer::get_singleton()->instances_cull_ray(pos, ray, get_tree()->get_root()->get_world_3d()->get_scenario()); Set<Ref<EditorNode3DGizmo>> found_gizmos; @@ -835,7 +836,7 @@ bool Node3DEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_high Vector3 r; - if (Geometry::segment_intersects_sphere(ray_pos, ray_pos + ray * MAX_Z, grabber_pos, grabber_radius, &r)) { + if (Geometry3D::segment_intersects_sphere(ray_pos, ray_pos + ray * MAX_Z, grabber_pos, grabber_radius, &r)) { float d = r.distance_to(ray_pos); if (d < col_d) { col_d = d; @@ -932,7 +933,7 @@ bool Node3DEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_high Vector3 r; - if (Geometry::segment_intersects_sphere(ray_pos, ray_pos + ray * MAX_Z, grabber_pos, grabber_radius, &r)) { + if (Geometry3D::segment_intersects_sphere(ray_pos, ray_pos + ray * MAX_Z, grabber_pos, grabber_radius, &r)) { float d = r.distance_to(ray_pos); if (d < col_d) { col_d = d; @@ -2109,12 +2110,7 @@ void Node3DEditorViewport::_nav_orbit(Ref<InputEventWithModifiers> p_event, cons 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; - } + cursor.x_rot = CLAMP(cursor.x_rot, -1.57, 1.57); name = ""; _update_name(); } @@ -2142,12 +2138,7 @@ void Node3DEditorViewport::_nav_look(Ref<InputEventWithModifiers> p_event, const 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; - } + cursor.x_rot = CLAMP(cursor.x_rot, -1.57, 1.57); // Look is like the opposite of Orbit: the focus point rotates around the camera Transform camera_transform = to_camera_transform(cursor); @@ -2177,6 +2168,8 @@ void Node3DEditorViewport::set_freelook_active(bool active_now) { freelook_speed = base_speed * cursor.distance; } + previous_mouse_position = get_local_mouse_position(); + // Hide mouse like in an FPS (warping doesn't work) Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED); @@ -2186,6 +2179,11 @@ void Node3DEditorViewport::set_freelook_active(bool active_now) { // Restore mouse Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); + + // Restore the previous mouse position when leaving freelook mode. + // This is done because leaving `Input.MOUSE_MODE_CAPTURED` will center the cursor + // due to OS limitations. + warp_mouse(previous_mouse_position); } freelook_active = active_now; @@ -2344,13 +2342,6 @@ void Node3DEditorViewport::_notification(int p_what) { call_deferred("update_transform_gizmo_view"); } - if (p_what == NOTIFICATION_READY) { - // The crosshair icon doesn't depend on the editor theme. - crosshair->set_texture(get_theme_icon("Crosshair", "EditorIcons")); - // Set the anchors and margins after changing the icon to ensure it's centered correctly. - crosshair->set_anchors_and_margins_preset(PRESET_CENTER); - } - if (p_what == NOTIFICATION_PROCESS) { real_t delta = get_process_delta_time(); @@ -2476,10 +2467,6 @@ void Node3DEditorViewport::_notification(int p_what) { current_camera = camera; } - // Display the crosshair only while freelooking. Hide it otherwise, - // as the crosshair can be distracting. - crosshair->set_visible(freelook_active); - if (show_info) { String text; text += "X: " + rtos(current_camera->get_translation().x).pad_decimals(1) + "\n"; @@ -2586,14 +2573,14 @@ void Node3DEditorViewport::_notification(int p_what) { } } -static void draw_indicator_bar(Control &surface, real_t fill, Ref<Texture2D> icon) { +static void draw_indicator_bar(Control &surface, real_t fill, const Ref<Texture2D> icon, const Ref<Font> font, const String &text) { // Adjust bar size from control height - Vector2 surface_size = surface.get_size(); - real_t h = surface_size.y / 2.0; - real_t y = (surface_size.y - h) / 2.0; + const Vector2 surface_size = surface.get_size(); + const real_t h = surface_size.y / 2.0; + const real_t y = (surface_size.y - h) / 2.0; - Rect2 r(10, y, 6, h); - real_t sy = r.size.y * fill; + const Rect2 r(10 * EDSCALE, y, 6 * EDSCALE, h); + const real_t sy = r.size.y * fill; // Note: because this bar appears over the viewport, it has to stay readable for any background color // Draw both neutral dark and bright colors to account this @@ -2601,9 +2588,12 @@ static void draw_indicator_bar(Control &surface, real_t fill, Ref<Texture2D> ico surface.draw_rect(Rect2(r.position.x, r.position.y + r.size.y - sy, r.size.x, sy), Color(1, 1, 1, 0.6)); surface.draw_rect(r.grow(1), Color(0, 0, 0, 0.7), false, Math::round(EDSCALE)); - Vector2 icon_size = icon->get_size(); - Vector2 icon_pos = Vector2(r.position.x - (icon_size.x - r.size.x) / 2, r.position.y + r.size.y + 2); + const Vector2 icon_size = icon->get_size(); + const Vector2 icon_pos = Vector2(r.position.x - (icon_size.x - r.size.x) / 2, r.position.y + r.size.y + 2 * EDSCALE); surface.draw_texture(icon, icon_pos); + + // Draw text below the bar (for speed/zoom information). + surface.draw_string(font, Vector2(icon_pos.x, icon_pos.y + icon_size.y + 16 * EDSCALE), text); } void Node3DEditorViewport::_draw() { @@ -2700,7 +2690,14 @@ void Node3DEditorViewport::_draw() { logscale_t = 0.25 * Math::exp(4.0 * logscale_t - 1.0); } - draw_indicator_bar(*surface, 1.0 - logscale_t, get_theme_icon("ViewportSpeed", "EditorIcons")); + // Display the freelook speed to help the user get a better sense of scale. + const int precision = freelook_speed < 1.0 ? 2 : 1; + draw_indicator_bar( + *surface, + 1.0 - logscale_t, + get_theme_icon("ViewportSpeed", "EditorIcons"), + get_theme_font("font", "Label"), + vformat("%s u/s", String::num(freelook_speed).pad_decimals(precision))); } } else { @@ -2719,7 +2716,14 @@ void Node3DEditorViewport::_draw() { logscale_t = 0.25 * Math::exp(4.0 * logscale_t - 1.0); } - draw_indicator_bar(*surface, logscale_t, get_theme_icon("ViewportZoom", "EditorIcons")); + // Display the zoom center distance to help the user get a better sense of scale. + const int precision = cursor.distance < 1.0 ? 2 : 1; + draw_indicator_bar( + *surface, + logscale_t, + get_theme_icon("ViewportZoom", "EditorIcons"), + get_theme_font("font", "Label"), + vformat("%s u", String::num(cursor.distance).pad_decimals(precision))); } } } @@ -2984,7 +2988,9 @@ void Node3DEditorViewport::_menu_option(int p_option) { case VIEW_DISPLAY_DEBUG_SSAO: case VIEW_DISPLAY_DEBUG_PSSM_SPLITS: case VIEW_DISPLAY_DEBUG_DECAL_ATLAS: - case VIEW_DISPLAY_DEBUG_ROUGHNESS_LIMITER: { + case VIEW_DISPLAY_DEBUG_SDFGI: + case VIEW_DISPLAY_DEBUG_SDFGI_PROBES: + case VIEW_DISPLAY_DEBUG_GI_BUFFER: { static const int display_options[] = { VIEW_DISPLAY_NORMAL, VIEW_DISPLAY_WIREFRAME, @@ -3000,9 +3006,11 @@ void Node3DEditorViewport::_menu_option(int p_option) { VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION, VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE, VIEW_DISPLAY_DEBUG_SSAO, - VIEW_DISPLAY_DEBUG_ROUGHNESS_LIMITER, + VIEW_DISPLAY_DEBUG_GI_BUFFER, VIEW_DISPLAY_DEBUG_PSSM_SPLITS, VIEW_DISPLAY_DEBUG_DECAL_ATLAS, + VIEW_DISPLAY_DEBUG_SDFGI, + VIEW_DISPLAY_DEBUG_SDFGI_PROBES, VIEW_MAX }; static const Viewport::DebugDraw debug_draw_modes[] = { @@ -3020,9 +3028,11 @@ void Node3DEditorViewport::_menu_option(int p_option) { Viewport::DEBUG_DRAW_GI_PROBE_EMISSION, Viewport::DEBUG_DRAW_SCENE_LUMINANCE, Viewport::DEBUG_DRAW_SSAO, - Viewport::DEBUG_DRAW_ROUGHNESS_LIMITER, + Viewport::DEBUG_DRAW_GI_BUFFER, Viewport::DEBUG_DRAW_PSSM_SPLITS, Viewport::DEBUG_DRAW_DECAL_ATLAS, + Viewport::DEBUG_DRAW_SDFGI, + Viewport::DEBUG_DRAW_SDFGI_PROBES, }; int idx = 0; @@ -3208,7 +3218,7 @@ void Node3DEditorViewport::update_transform_gizmo_view() { Vector3 camz = -camera_xform.get_basis().get_axis(2).normalized(); Vector3 camy = -camera_xform.get_basis().get_axis(1).normalized(); Plane p(camera_xform.origin, camz); - float gizmo_d = Math::abs(p.distance_to(xform.origin)); + float gizmo_d = MAX(Math::abs(p.distance_to(xform.origin)), CMP_EPSILON); float d0 = camera->unproject_position(camera_xform.origin + camz * gizmo_d).y; float d1 = camera->unproject_position(camera_xform.origin + camz * gizmo_d + camy).y; float dd = Math::abs(d0 - d1); @@ -3422,11 +3432,7 @@ void Node3DEditorViewport::reset() { last_message = ""; name = ""; - cursor.x_rot = 0.5; - cursor.y_rot = 0.5; - cursor.distance = 4; - cursor.region_select = false; - cursor.pos = Vector3(); + cursor = Cursor(); _update_name(); } @@ -3661,15 +3667,19 @@ bool Node3DEditorViewport::_create_instance(Node *parent, String &path, const Po editor_data->get_undo_redo().add_do_method(ed, "live_debug_instance_node", editor->get_edited_scene()->get_path_to(parent), path, new_name); editor_data->get_undo_redo().add_undo_method(ed, "live_debug_remove_node", NodePath(String(editor->get_edited_scene()->get_path_to(parent)) + "/" + new_name)); - Transform global_transform; - Node3D *parent_spatial = Object::cast_to<Node3D>(parent); - if (parent_spatial) { - global_transform = parent_spatial->get_global_gizmo_transform(); - } + Node3D *node3d = Object::cast_to<Node3D>(instanced_scene); + if (node3d) { + Transform global_transform; + Node3D *parent_node3d = Object::cast_to<Node3D>(parent); + if (parent_node3d) { + global_transform = parent_node3d->get_global_gizmo_transform(); + } - global_transform.origin = spatial_editor->snap_point(_get_instance_position(p_point)); + global_transform.origin = spatial_editor->snap_point(_get_instance_position(p_point)); + global_transform.basis *= node3d->get_transform().basis; - editor_data->get_undo_redo().add_do_method(instanced_scene, "set_global_transform", global_transform); + editor_data->get_undo_redo().add_do_method(instanced_scene, "set_global_transform", global_transform); + } return true; } @@ -3852,10 +3862,6 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito camera->make_current(); surface->set_focus_mode(FOCUS_ALL); - crosshair = memnew(TextureRect); - crosshair->set_mouse_filter(MOUSE_FILTER_IGNORE); - surface->add_child(crosshair); - VBoxContainer *vbox = memnew(VBoxContainer); surface->add_child(vbox); vbox->set_position(Point2(10, 10) * EDSCALE); @@ -3902,11 +3908,14 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito display_submenu->add_radio_check_item(TTR("GIProbe Albedo"), VIEW_DISPLAY_DEBUG_GIPROBE_ALBEDO); display_submenu->add_radio_check_item(TTR("GIProbe Emission"), VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION); display_submenu->add_separator(); + display_submenu->add_radio_check_item(TTR("SDFGI Cascades"), VIEW_DISPLAY_DEBUG_SDFGI); + display_submenu->add_radio_check_item(TTR("SDFGI Probes"), VIEW_DISPLAY_DEBUG_SDFGI_PROBES); + display_submenu->add_separator(); display_submenu->add_radio_check_item(TTR("Scene Luminance"), VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE); display_submenu->add_separator(); display_submenu->add_radio_check_item(TTR("SSAO"), VIEW_DISPLAY_DEBUG_SSAO); display_submenu->add_separator(); - display_submenu->add_radio_check_item(TTR("Roughness Limiter"), VIEW_DISPLAY_DEBUG_ROUGHNESS_LIMITER); + display_submenu->add_radio_check_item(TTR("GI Buffer"), VIEW_DISPLAY_DEBUG_GI_BUFFER); display_submenu->set_name("display_advanced"); view_menu->get_popup()->add_submenu_item(TTR("Display Advanced..."), "display_advanced", VIEW_DISPLAY_ADVANCED); view_menu->get_popup()->add_separator(); @@ -4929,8 +4938,10 @@ void Node3DEditor::_menu_item_pressed(int p_option) { for (int i = 0; i < 3; ++i) { if (grid_enable[i]) { - RenderingServer::get_singleton()->instance_set_visible(grid_instance[i], grid_enabled); grid_visible[i] = grid_enabled; + if (grid_instance[i].is_valid()) { + RenderingServer::get_singleton()->instance_set_visible(grid_instance[i], grid_enabled); + } } } @@ -4950,7 +4961,7 @@ void Node3DEditor::_menu_item_pressed(int p_option) { for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { Node3D *spatial = Object::cast_to<Node3D>(E->get()); - if (!spatial || !spatial->is_visible_in_tree()) { + if (!spatial || !spatial->is_inside_tree()) { continue; } @@ -4964,8 +4975,8 @@ void Node3DEditor::_menu_item_pressed(int p_option) { undo_redo->add_undo_method(this, "emit_signal", "item_lock_status_changed"); } - undo_redo->add_do_method(this, "_refresh_menu_icons", Variant()); - undo_redo->add_undo_method(this, "_refresh_menu_icons", Variant()); + undo_redo->add_do_method(this, "_refresh_menu_icons"); + undo_redo->add_undo_method(this, "_refresh_menu_icons"); undo_redo->commit_action(); } break; case MENU_UNLOCK_SELECTED: { @@ -4975,7 +4986,7 @@ void Node3DEditor::_menu_item_pressed(int p_option) { for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { Node3D *spatial = Object::cast_to<Node3D>(E->get()); - if (!spatial || !spatial->is_visible_in_tree()) { + if (!spatial || !spatial->is_inside_tree()) { continue; } @@ -4989,8 +5000,8 @@ void Node3DEditor::_menu_item_pressed(int p_option) { undo_redo->add_undo_method(this, "emit_signal", "item_lock_status_changed"); } - undo_redo->add_do_method(this, "_refresh_menu_icons", Variant()); - undo_redo->add_undo_method(this, "_refresh_menu_icons", Variant()); + undo_redo->add_do_method(this, "_refresh_menu_icons"); + undo_redo->add_undo_method(this, "_refresh_menu_icons"); undo_redo->commit_action(); } break; case MENU_GROUP_SELECTED: { @@ -5000,7 +5011,7 @@ void Node3DEditor::_menu_item_pressed(int p_option) { for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { Node3D *spatial = Object::cast_to<Node3D>(E->get()); - if (!spatial || !spatial->is_visible_in_tree()) { + if (!spatial || !spatial->is_inside_tree()) { continue; } @@ -5014,8 +5025,8 @@ void Node3DEditor::_menu_item_pressed(int p_option) { undo_redo->add_undo_method(this, "emit_signal", "item_group_status_changed"); } - undo_redo->add_do_method(this, "_refresh_menu_icons", Variant()); - undo_redo->add_undo_method(this, "_refresh_menu_icons", Variant()); + undo_redo->add_do_method(this, "_refresh_menu_icons"); + undo_redo->add_undo_method(this, "_refresh_menu_icons"); undo_redo->commit_action(); } break; case MENU_UNGROUP_SELECTED: { @@ -5024,7 +5035,7 @@ void Node3DEditor::_menu_item_pressed(int p_option) { for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { Node3D *spatial = Object::cast_to<Node3D>(E->get()); - if (!spatial || !spatial->is_visible_in_tree()) { + if (!spatial || !spatial->is_inside_tree()) { continue; } @@ -5038,8 +5049,8 @@ void Node3DEditor::_menu_item_pressed(int p_option) { undo_redo->add_undo_method(this, "emit_signal", "item_group_status_changed"); } - undo_redo->add_do_method(this, "_refresh_menu_icons", Variant()); - undo_redo->add_undo_method(this, "_refresh_menu_icons", Variant()); + undo_redo->add_do_method(this, "_refresh_menu_icons"); + undo_redo->add_undo_method(this, "_refresh_menu_icons"); undo_redo->commit_action(); } break; } @@ -5054,6 +5065,7 @@ void Node3DEditor::_init_indicators() { indicator_mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); indicator_mat->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); indicator_mat->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true); + indicator_mat->set_transparency(StandardMaterial3D::Transparency::TRANSPARENCY_ALPHA_DEPTH_PRE_PASS); Vector<Color> origin_colors; Vector<Vector3> origin_points; @@ -5082,12 +5094,27 @@ void Node3DEditor::_init_indicators() { origin_colors.push_back(origin_color); origin_colors.push_back(origin_color); - origin_points.push_back(axis * 4096); - origin_points.push_back(axis * -4096); - } - - grid_enable[1] = true; - grid_visible[1] = true; + origin_colors.push_back(origin_color); + origin_colors.push_back(origin_color); + origin_colors.push_back(origin_color); + origin_colors.push_back(origin_color); + // To both allow having a large origin size and avoid jitter + // at small scales, we should segment the line into pieces. + // 3 pieces seems to do the trick, and let's use powers of 2. + origin_points.push_back(axis * 1048576); + origin_points.push_back(axis * 1024); + origin_points.push_back(axis * 1024); + origin_points.push_back(axis * -1024); + origin_points.push_back(axis * -1024); + origin_points.push_back(axis * -1048576); + } + + grid_enable[0] = EditorSettings::get_singleton()->get("editors/3d/grid_xy_plane"); + grid_enable[1] = EditorSettings::get_singleton()->get("editors/3d/grid_yz_plane"); + grid_enable[2] = EditorSettings::get_singleton()->get("editors/3d/grid_xz_plane"); + grid_visible[0] = grid_enable[0]; + grid_visible[1] = grid_enable[1]; + grid_visible[2] = grid_enable[2]; _init_grid(); @@ -5382,6 +5409,9 @@ void Node3DEditor::_update_gizmos_menu() { const int plugin_state = gizmo_plugins_by_name[i]->get_state(); gizmos_menu->add_multistate_item(TTR(plugin_name), 3, plugin_state, i); const int idx = gizmos_menu->get_item_index(i); + gizmos_menu->set_item_tooltip( + idx, + TTR("Click to toggle between visibility states.\n\nOpen eye: Gizmo is visible.\nClosed eye: Gizmo is hidden.\nHalf-open eye: Gizmo is also visible through opaque surfaces (\"x-ray\").")); switch (plugin_state) { case EditorNode3DGizmoPlugin::VISIBLE: gizmos_menu->set_item_icon(idx, gizmos_menu->get_theme_icon("visibility_visible")); @@ -5418,6 +5448,15 @@ void Node3DEditor::_update_gizmos_menu_theme() { } void Node3DEditor::_init_grid() { + if (!grid_enabled) { + return; + } + Camera3D *camera = get_editor_viewport(0)->camera; + Vector3 camera_position = camera->get_translation(); + if (camera_position == Vector3()) { + return; // Camera3D is invalid, don't draw the grid. + } + Vector<Color> grid_colors[3]; Vector<Vector3> grid_points[3]; @@ -5426,52 +5465,111 @@ void Node3DEditor::_init_grid() { int grid_size = EditorSettings::get_singleton()->get("editors/3d/grid_size"); int primary_grid_steps = EditorSettings::get_singleton()->get("editors/3d/primary_grid_steps"); - for (int i = 0; i < 3; i++) { - Vector3 axis; - axis[i] = 1; - Vector3 axis_n1; - axis_n1[(i + 1) % 3] = 1; - Vector3 axis_n2; - axis_n2[(i + 2) % 3] = 1; - - for (int j = -grid_size; j <= grid_size; j++) { - Vector3 p1 = axis_n1 * j + axis_n2 * -grid_size; - Vector3 p1_dest = p1 * (-axis_n2 + axis_n1); - Vector3 p2 = axis_n2 * j + axis_n1 * -grid_size; - Vector3 p2_dest = p2 * (-axis_n1 + axis_n2); - - Color line_color = secondary_grid_color; - if (origin_enabled && j == 0) { - // Don't draw the center lines of the grid if the origin is enabled - // The origin would overlap the grid lines in this case, causing flickering - continue; - } else if (j % primary_grid_steps == 0) { - line_color = primary_grid_color; + // Which grid planes are enabled? Which should we generate? + grid_enable[0] = grid_visible[0] = EditorSettings::get_singleton()->get("editors/3d/grid_xy_plane"); + grid_enable[1] = grid_visible[1] = EditorSettings::get_singleton()->get("editors/3d/grid_yz_plane"); + grid_enable[2] = grid_visible[2] = EditorSettings::get_singleton()->get("editors/3d/grid_xz_plane"); + + // Offsets division_level for bigger or smaller grids. + // Default value is -0.2. -1.0 gives Blender-like behavior, 0.5 gives huge grids. + real_t division_level_bias = EditorSettings::get_singleton()->get("editors/3d/grid_division_level_bias"); + // Default largest grid size is 100m, 10^2 (default value is 2). + int division_level_max = EditorSettings::get_singleton()->get("editors/3d/grid_division_level_max"); + // Default smallest grid size is 1cm, 10^-2 (default value is -2). + int division_level_min = EditorSettings::get_singleton()->get("editors/3d/grid_division_level_min"); + ERR_FAIL_COND_MSG(division_level_max < division_level_min, "The 3D grid's maximum division level cannot be lower than its minimum division level."); + + if (primary_grid_steps != 10) { // Log10 of 10 is 1. + // Change of base rule, divide by ln(10). + real_t div = Math::log((real_t)primary_grid_steps) / (real_t)2.302585092994045901094; + // Trucation (towards zero) is intentional. + division_level_max = (int)(division_level_max / div); + division_level_min = (int)(division_level_min / div); + } + + for (int a = 0; a < 3; a++) { + if (!grid_enable[a]) { + continue; // If this grid plane is disabled, skip generation. + } + int b = (a + 1) % 3; + int c = (a + 2) % 3; + + real_t division_level = Math::log(Math::abs(camera_position[c])) / Math::log((double)primary_grid_steps) + division_level_bias; + division_level = CLAMP(division_level, division_level_min, division_level_max); + real_t division_level_floored = Math::floor(division_level); + real_t division_level_decimals = division_level - division_level_floored; + + real_t small_step_size = Math::pow(primary_grid_steps, division_level_floored); + real_t large_step_size = small_step_size * primary_grid_steps; + real_t center_a = large_step_size * (int)(camera_position[a] / large_step_size); + real_t center_b = large_step_size * (int)(camera_position[b] / large_step_size); + + real_t bgn_a = center_a - grid_size * small_step_size; + real_t end_a = center_a + grid_size * small_step_size; + real_t bgn_b = center_b - grid_size * small_step_size; + real_t end_b = center_b + grid_size * small_step_size; + + // In each iteration of this loop, draw one line in each direction (so two lines per loop, in each if statement). + for (int i = -grid_size; i <= grid_size; i++) { + Color line_color; + // Is this a primary line? Set the appropriate color. + if (i % primary_grid_steps == 0) { + line_color = primary_grid_color.lerp(secondary_grid_color, division_level_decimals); + } else { + line_color = secondary_grid_color; + line_color.a = line_color.a * (1 - division_level_decimals); + } + // Makes lines farther from the center fade out. + // Due to limitations of lines, any that come near the camera have full opacity always. + // This should eventually be replaced by some kind of "distance fade" system, outside of this function. + // But the effect is still somewhat convincing... + line_color.a *= 1 - (1 - division_level_decimals * 0.9) * (Math::abs(i / (float)grid_size)); + + real_t position_a = center_a + i * small_step_size; + real_t position_b = center_b + i * small_step_size; + + // Don't draw lines over the origin if it's enabled. + if (!(origin_enabled && Math::is_zero_approx(position_a))) { + Vector3 line_bgn = Vector3(); + Vector3 line_end = Vector3(); + line_bgn[a] = position_a; + line_end[a] = position_a; + line_bgn[b] = bgn_b; + line_end[b] = end_b; + grid_points[c].push_back(line_bgn); + grid_points[c].push_back(line_end); + grid_colors[c].push_back(line_color); + grid_colors[c].push_back(line_color); } - grid_points[i].push_back(p1); - grid_points[i].push_back(p1_dest); - grid_colors[i].push_back(line_color); - grid_colors[i].push_back(line_color); - - grid_points[i].push_back(p2); - grid_points[i].push_back(p2_dest); - grid_colors[i].push_back(line_color); - grid_colors[i].push_back(line_color); + if (!(origin_enabled && Math::is_zero_approx(position_b))) { + Vector3 line_bgn = Vector3(); + Vector3 line_end = Vector3(); + line_bgn[b] = position_b; + line_end[b] = position_b; + line_bgn[a] = bgn_a; + line_end[a] = end_a; + grid_points[c].push_back(line_bgn); + grid_points[c].push_back(line_end); + grid_colors[c].push_back(line_color); + grid_colors[c].push_back(line_color); + } } - grid[i] = RenderingServer::get_singleton()->mesh_create(); + // Create a mesh from the pushed vector points and colors. + grid[c] = RenderingServer::get_singleton()->mesh_create(); Array d; d.resize(RS::ARRAY_MAX); - d[RenderingServer::ARRAY_VERTEX] = grid_points[i]; - d[RenderingServer::ARRAY_COLOR] = grid_colors[i]; - RenderingServer::get_singleton()->mesh_add_surface_from_arrays(grid[i], RenderingServer::PRIMITIVE_LINES, d); - RenderingServer::get_singleton()->mesh_surface_set_material(grid[i], 0, indicator_mat->get_rid()); - grid_instance[i] = RenderingServer::get_singleton()->instance_create2(grid[i], get_tree()->get_root()->get_world_3d()->get_scenario()); + d[RenderingServer::ARRAY_VERTEX] = grid_points[c]; + d[RenderingServer::ARRAY_COLOR] = grid_colors[c]; + RenderingServer::get_singleton()->mesh_add_surface_from_arrays(grid[c], RenderingServer::PRIMITIVE_LINES, d); + RenderingServer::get_singleton()->mesh_surface_set_material(grid[c], 0, indicator_mat->get_rid()); + grid_instance[c] = RenderingServer::get_singleton()->instance_create2(grid[c], get_tree()->get_root()->get_world_3d()->get_scenario()); - RenderingServer::get_singleton()->instance_set_visible(grid_instance[i], grid_visible[i]); - RenderingServer::get_singleton()->instance_geometry_set_cast_shadows_setting(grid_instance[i], RS::SHADOW_CASTING_SETTING_OFF); - RS::get_singleton()->instance_set_layer_mask(grid_instance[i], 1 << Node3DEditorViewport::GIZMO_GRID_LAYER); + // Yes, the end of this line is supposed to be a. + RenderingServer::get_singleton()->instance_set_visible(grid_instance[c], grid_visible[a]); + RenderingServer::get_singleton()->instance_geometry_set_cast_shadows_setting(grid_instance[c], RS::SHADOW_CASTING_SETTING_OFF); + RS::get_singleton()->instance_set_layer_mask(grid_instance[c], 1 << Node3DEditorViewport::GIZMO_GRID_LAYER); } } @@ -5489,6 +5587,11 @@ void Node3DEditor::_finish_grid() { } } +void Node3DEditor::update_grid() { + _finish_grid(); + _init_grid(); +} + bool Node3DEditor::is_any_freelook_active() const { for (unsigned int i = 0; i < VIEWPORTS_COUNT; ++i) { if (viewports[i]->is_freelook_active()) { @@ -5889,6 +5992,7 @@ void Node3DEditor::_bind_methods() { ClassDB::bind_method("_unhandled_key_input", &Node3DEditor::_unhandled_key_input); ClassDB::bind_method("_get_editor_data", &Node3DEditor::_get_editor_data); ClassDB::bind_method("_request_gizmo", &Node3DEditor::_request_gizmo); + ClassDB::bind_method("_refresh_menu_icons", &Node3DEditor::_refresh_menu_icons); ADD_SIGNAL(MethodInfo("transform_key_request")); ADD_SIGNAL(MethodInfo("item_lock_status_changed")); @@ -5948,7 +6052,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { button_binds.resize(1); String sct; - tool_button[TOOL_MODE_SELECT] = memnew(ToolButton); + tool_button[TOOL_MODE_SELECT] = memnew(Button); hbc_menu->add_child(tool_button[TOOL_MODE_SELECT]); tool_button[TOOL_MODE_SELECT]->set_toggle_mode(true); tool_button[TOOL_MODE_SELECT]->set_flat(true); @@ -5960,7 +6064,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { hbc_menu->add_child(memnew(VSeparator)); - tool_button[TOOL_MODE_MOVE] = memnew(ToolButton); + tool_button[TOOL_MODE_MOVE] = memnew(Button); hbc_menu->add_child(tool_button[TOOL_MODE_MOVE]); tool_button[TOOL_MODE_MOVE]->set_toggle_mode(true); tool_button[TOOL_MODE_MOVE]->set_flat(true); @@ -5968,7 +6072,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { tool_button[TOOL_MODE_MOVE]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_MODE_MOVE]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_move", TTR("Move Mode"), KEY_W)); - tool_button[TOOL_MODE_ROTATE] = memnew(ToolButton); + tool_button[TOOL_MODE_ROTATE] = memnew(Button); hbc_menu->add_child(tool_button[TOOL_MODE_ROTATE]); tool_button[TOOL_MODE_ROTATE]->set_toggle_mode(true); tool_button[TOOL_MODE_ROTATE]->set_flat(true); @@ -5976,7 +6080,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { tool_button[TOOL_MODE_ROTATE]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_MODE_ROTATE]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_rotate", TTR("Rotate Mode"), KEY_E)); - tool_button[TOOL_MODE_SCALE] = memnew(ToolButton); + tool_button[TOOL_MODE_SCALE] = memnew(Button); hbc_menu->add_child(tool_button[TOOL_MODE_SCALE]); tool_button[TOOL_MODE_SCALE]->set_toggle_mode(true); tool_button[TOOL_MODE_SCALE]->set_flat(true); @@ -5986,7 +6090,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { hbc_menu->add_child(memnew(VSeparator)); - tool_button[TOOL_MODE_LIST_SELECT] = memnew(ToolButton); + tool_button[TOOL_MODE_LIST_SELECT] = memnew(Button); hbc_menu->add_child(tool_button[TOOL_MODE_LIST_SELECT]); tool_button[TOOL_MODE_LIST_SELECT]->set_toggle_mode(true); tool_button[TOOL_MODE_LIST_SELECT]->set_flat(true); @@ -5994,33 +6098,37 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { tool_button[TOOL_MODE_LIST_SELECT]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_MODE_LIST_SELECT]->set_tooltip(TTR("Show a list of all objects at the position clicked\n(same as Alt+RMB in select mode).")); - tool_button[TOOL_LOCK_SELECTED] = memnew(ToolButton); + tool_button[TOOL_LOCK_SELECTED] = memnew(Button); hbc_menu->add_child(tool_button[TOOL_LOCK_SELECTED]); + tool_button[TOOL_LOCK_SELECTED]->set_flat(true); button_binds.write[0] = MENU_LOCK_SELECTED; tool_button[TOOL_LOCK_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_LOCK_SELECTED]->set_tooltip(TTR("Lock the selected object in place (can't be moved).")); - tool_button[TOOL_UNLOCK_SELECTED] = memnew(ToolButton); + tool_button[TOOL_UNLOCK_SELECTED] = memnew(Button); hbc_menu->add_child(tool_button[TOOL_UNLOCK_SELECTED]); + tool_button[TOOL_UNLOCK_SELECTED]->set_flat(true); button_binds.write[0] = MENU_UNLOCK_SELECTED; tool_button[TOOL_UNLOCK_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_UNLOCK_SELECTED]->set_tooltip(TTR("Unlock the selected object (can be moved).")); - tool_button[TOOL_GROUP_SELECTED] = memnew(ToolButton); + tool_button[TOOL_GROUP_SELECTED] = memnew(Button); hbc_menu->add_child(tool_button[TOOL_GROUP_SELECTED]); + tool_button[TOOL_GROUP_SELECTED]->set_flat(true); button_binds.write[0] = MENU_GROUP_SELECTED; tool_button[TOOL_GROUP_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_GROUP_SELECTED]->set_tooltip(TTR("Makes sure the object's children are not selectable.")); - tool_button[TOOL_UNGROUP_SELECTED] = memnew(ToolButton); + tool_button[TOOL_UNGROUP_SELECTED] = memnew(Button); hbc_menu->add_child(tool_button[TOOL_UNGROUP_SELECTED]); + tool_button[TOOL_UNGROUP_SELECTED]->set_flat(true); button_binds.write[0] = MENU_UNGROUP_SELECTED; tool_button[TOOL_UNGROUP_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_UNGROUP_SELECTED]->set_tooltip(TTR("Restores the object's children's ability to be selected.")); hbc_menu->add_child(memnew(VSeparator)); - tool_option_button[TOOL_OPT_LOCAL_COORDS] = memnew(ToolButton); + tool_option_button[TOOL_OPT_LOCAL_COORDS] = memnew(Button); hbc_menu->add_child(tool_option_button[TOOL_OPT_LOCAL_COORDS]); tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_toggle_mode(true); tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_flat(true); @@ -6028,7 +6136,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { tool_option_button[TOOL_OPT_LOCAL_COORDS]->connect("toggled", callable_mp(this, &Node3DEditor::_menu_item_toggled), button_binds); tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_shortcut(ED_SHORTCUT("spatial_editor/local_coords", TTR("Use Local Space"), KEY_T)); - tool_option_button[TOOL_OPT_USE_SNAP] = memnew(ToolButton); + tool_option_button[TOOL_OPT_USE_SNAP] = memnew(Button); hbc_menu->add_child(tool_option_button[TOOL_OPT_USE_SNAP]); tool_option_button[TOOL_OPT_USE_SNAP]->set_toggle_mode(true); tool_option_button[TOOL_OPT_USE_SNAP]->set_flat(true); @@ -6038,7 +6146,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { hbc_menu->add_child(memnew(VSeparator)); - tool_option_button[TOOL_OPT_OVERRIDE_CAMERA] = memnew(ToolButton); + tool_option_button[TOOL_OPT_OVERRIDE_CAMERA] = memnew(Button); hbc_menu->add_child(tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]); tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_toggle_mode(true); tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_flat(true); diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index 3d92e7e7e1..a40de78795 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -214,9 +214,11 @@ class Node3DEditorViewport : public Control { VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION, VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE, VIEW_DISPLAY_DEBUG_SSAO, - VIEW_DISPLAY_DEBUG_ROUGHNESS_LIMITER, VIEW_DISPLAY_DEBUG_PSSM_SPLITS, VIEW_DISPLAY_DEBUG_DECAL_ATLAS, + VIEW_DISPLAY_DEBUG_SDFGI, + VIEW_DISPLAY_DEBUG_SDFGI_PROBES, + VIEW_DISPLAY_DEBUG_GI_BUFFER, VIEW_LOCK_ROTATION, VIEW_CINEMATIC_PREVIEW, VIEW_AUTO_ORTHOGONAL, @@ -284,8 +286,8 @@ private: bool freelook_active; real_t freelook_speed; + Vector2 previous_mouse_position; - TextureRect *crosshair; Label *info_label; Label *cinema_label; Label *locked_label; @@ -391,7 +393,9 @@ private: Point2 region_begin, region_end; Cursor() { - x_rot = y_rot = 0.5; + // These rotations place the camera in +X +Y +Z, aka south east, facing north west. + x_rot = 0.5; + y_rot = -0.5; distance = 4; region_select = false; } @@ -766,6 +770,7 @@ public: Ref<ArrayMesh> get_scale_gizmo(int idx) const { return scale_gizmo[idx]; } Ref<ArrayMesh> get_scale_plane_gizmo(int idx) const { return scale_plane_gizmo[idx]; } + void update_grid(); void update_transform_gizmo(); void update_all_gizmos(Node *p_node = nullptr); void snap_selected_nodes_to_floor(); diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp index a3dab665b8..f79098ce5d 100644 --- a/editor/plugins/path_2d_editor_plugin.cpp +++ b/editor/plugins/path_2d_editor_plugin.cpp @@ -532,35 +532,40 @@ Path2DEditor::Path2DEditor(EditorNode *p_editor) { sep = memnew(VSeparator); base_hb->add_child(sep); - curve_edit = memnew(ToolButton); + curve_edit = memnew(Button); + curve_edit->set_flat(true); curve_edit->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveEdit", "EditorIcons")); curve_edit->set_toggle_mode(true); curve_edit->set_focus_mode(Control::FOCUS_NONE); curve_edit->set_tooltip(TTR("Select Points") + "\n" + TTR("Shift+Drag: Select Control Points") + "\n" + keycode_get_string(KEY_MASK_CMD) + TTR("Click: Add Point") + "\n" + TTR("Left Click: Split Segment (in curve)") + "\n" + TTR("Right Click: Delete Point")); curve_edit->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected), varray(MODE_EDIT)); base_hb->add_child(curve_edit); - curve_edit_curve = memnew(ToolButton); + curve_edit_curve = memnew(Button); + curve_edit_curve->set_flat(true); curve_edit_curve->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveCurve", "EditorIcons")); curve_edit_curve->set_toggle_mode(true); curve_edit_curve->set_focus_mode(Control::FOCUS_NONE); curve_edit_curve->set_tooltip(TTR("Select Control Points (Shift+Drag)")); curve_edit_curve->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected), varray(MODE_EDIT_CURVE)); base_hb->add_child(curve_edit_curve); - curve_create = memnew(ToolButton); + curve_create = memnew(Button); + curve_create->set_flat(true); curve_create->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveCreate", "EditorIcons")); curve_create->set_toggle_mode(true); curve_create->set_focus_mode(Control::FOCUS_NONE); curve_create->set_tooltip(TTR("Add Point (in empty space)")); curve_create->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected), varray(MODE_CREATE)); base_hb->add_child(curve_create); - curve_del = memnew(ToolButton); + curve_del = memnew(Button); + curve_del->set_flat(true); curve_del->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveDelete", "EditorIcons")); curve_del->set_toggle_mode(true); curve_del->set_focus_mode(Control::FOCUS_NONE); curve_del->set_tooltip(TTR("Delete Point")); curve_del->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected), varray(MODE_DELETE)); base_hb->add_child(curve_del); - curve_close = memnew(ToolButton); + curve_close = memnew(Button); + curve_close->set_flat(true); curve_close->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveClose", "EditorIcons")); curve_close->set_focus_mode(Control::FOCUS_NONE); curve_close->set_tooltip(TTR("Close Curve")); diff --git a/editor/plugins/path_2d_editor_plugin.h b/editor/plugins/path_2d_editor_plugin.h index 390dfdfdf7..d0c02b28d4 100644 --- a/editor/plugins/path_2d_editor_plugin.h +++ b/editor/plugins/path_2d_editor_plugin.h @@ -34,7 +34,6 @@ #include "editor/editor_node.h" #include "editor/editor_plugin.h" #include "scene/2d/path_2d.h" -#include "scene/gui/tool_button.h" class CanvasItemEditor; @@ -60,11 +59,11 @@ class Path2DEditor : public HBoxContainer { }; Mode mode; - ToolButton *curve_create; - ToolButton *curve_edit; - ToolButton *curve_edit_curve; - ToolButton *curve_del; - ToolButton *curve_close; + Button *curve_create; + Button *curve_edit; + Button *curve_edit_curve; + Button *curve_del; + Button *curve_close; MenuButton *handle_menu; bool mirror_handle_angle; diff --git a/editor/plugins/path_3d_editor_plugin.cpp b/editor/plugins/path_3d_editor_plugin.cpp index a44fe69ff6..f53130c24d 100644 --- a/editor/plugins/path_3d_editor_plugin.cpp +++ b/editor/plugins/path_3d_editor_plugin.cpp @@ -30,6 +30,8 @@ #include "path_3d_editor_plugin.h" +#include "core/math/geometry_2d.h" +#include "core/math/geometry_3d.h" #include "core/os/keyboard.h" #include "node_3d_editor_plugin.h" #include "scene/resources/curve.h" @@ -344,7 +346,7 @@ bool Path3DEditorPlugin::forward_spatial_gui_input(Camera3D *p_camera, const Ref Vector2 s[2]; s[0] = p_camera->unproject_position(from); s[1] = p_camera->unproject_position(to); - Vector2 inters = Geometry::get_closest_point_to_segment_2d(mbpos, s); + Vector2 inters = Geometry2D::get_closest_point_to_segment(mbpos, s); float d = inters.distance_to(mbpos); if (d < 10 && d < closest_d) { @@ -354,7 +356,7 @@ bool Path3DEditorPlugin::forward_spatial_gui_input(Camera3D *p_camera, const Ref Vector3 ray_dir = p_camera->project_ray_normal(mbpos); Vector3 ra, rb; - Geometry::get_closest_points_between_segments(ray_from, ray_from + ray_dir * 4096, from, to, ra, rb); + Geometry3D::get_closest_points_between_segments(ray_from, ray_from + ray_dir * 4096, from, to, ra, rb); closest_seg_point = it.xform(rb); } @@ -555,28 +557,32 @@ Path3DEditorPlugin::Path3DEditorPlugin(EditorNode *p_node) { sep = memnew(VSeparator); sep->hide(); Node3DEditor::get_singleton()->add_control_to_menu_panel(sep); - curve_edit = memnew(ToolButton); + curve_edit = memnew(Button); + curve_edit->set_flat(true); curve_edit->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveEdit", "EditorIcons")); curve_edit->set_toggle_mode(true); curve_edit->hide(); curve_edit->set_focus_mode(Control::FOCUS_NONE); curve_edit->set_tooltip(TTR("Select Points") + "\n" + TTR("Shift+Drag: Select Control Points") + "\n" + keycode_get_string(KEY_MASK_CMD) + TTR("Click: Add Point") + "\n" + TTR("Right Click: Delete Point")); Node3DEditor::get_singleton()->add_control_to_menu_panel(curve_edit); - curve_create = memnew(ToolButton); + curve_create = memnew(Button); + curve_create->set_flat(true); curve_create->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveCreate", "EditorIcons")); curve_create->set_toggle_mode(true); curve_create->hide(); curve_create->set_focus_mode(Control::FOCUS_NONE); curve_create->set_tooltip(TTR("Add Point (in empty space)") + "\n" + TTR("Split Segment (in curve)")); Node3DEditor::get_singleton()->add_control_to_menu_panel(curve_create); - curve_del = memnew(ToolButton); + curve_del = memnew(Button); + curve_del->set_flat(true); curve_del->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveDelete", "EditorIcons")); curve_del->set_toggle_mode(true); curve_del->hide(); curve_del->set_focus_mode(Control::FOCUS_NONE); curve_del->set_tooltip(TTR("Delete Point")); Node3DEditor::get_singleton()->add_control_to_menu_panel(curve_del); - curve_close = memnew(ToolButton); + curve_close = memnew(Button); + curve_close->set_flat(true); curve_close->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveClose", "EditorIcons")); curve_close->hide(); curve_close->set_focus_mode(Control::FOCUS_NONE); diff --git a/editor/plugins/path_3d_editor_plugin.h b/editor/plugins/path_3d_editor_plugin.h index 8bec5df797..3a75717b73 100644 --- a/editor/plugins/path_3d_editor_plugin.h +++ b/editor/plugins/path_3d_editor_plugin.h @@ -68,10 +68,10 @@ class Path3DEditorPlugin : public EditorPlugin { GDCLASS(Path3DEditorPlugin, EditorPlugin); Separator *sep; - ToolButton *curve_create; - ToolButton *curve_edit; - ToolButton *curve_del; - ToolButton *curve_close; + Button *curve_create; + Button *curve_edit; + Button *curve_del; + Button *curve_close; MenuButton *handle_menu; EditorNode *editor; diff --git a/editor/plugins/physical_bone_3d_editor_plugin.cpp b/editor/plugins/physical_bone_3d_editor_plugin.cpp index bcbf88e7dc..30bf827b3c 100644 --- a/editor/plugins/physical_bone_3d_editor_plugin.cpp +++ b/editor/plugins/physical_bone_3d_editor_plugin.cpp @@ -55,7 +55,8 @@ PhysicalBone3DEditor::PhysicalBone3DEditor(EditorNode *p_editor) : spatial_editor_hb->add_child(memnew(VSeparator)); - button_transform_joint = memnew(ToolButton); + button_transform_joint = memnew(Button); + button_transform_joint->set_flat(true); spatial_editor_hb->add_child(button_transform_joint); button_transform_joint->set_text(TTR("Move Joint")); diff --git a/editor/plugins/physical_bone_3d_editor_plugin.h b/editor/plugins/physical_bone_3d_editor_plugin.h index 79c7cc4bb1..8699176fe0 100644 --- a/editor/plugins/physical_bone_3d_editor_plugin.h +++ b/editor/plugins/physical_bone_3d_editor_plugin.h @@ -38,7 +38,7 @@ class PhysicalBone3DEditor : public Object { EditorNode *editor; HBoxContainer *spatial_editor_hb; - ToolButton *button_transform_joint; + Button *button_transform_joint; PhysicalBone3D *selected = nullptr; diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index 7ee695b9fe..633863041f 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -32,6 +32,7 @@ #include "canvas_item_editor_plugin.h" #include "core/input/input.h" +#include "core/math/geometry_2d.h" #include "core/os/file_access.h" #include "core/os/keyboard.h" #include "editor/editor_scale.h" @@ -484,7 +485,8 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { } else { Vector2 tuv = mtx.affine_inverse().xform(snap_point(Vector2(mb->get_position().x, mb->get_position().y))); - if (points_prev.size() > 2 && tuv.distance_to(points_prev[0]) < 8) { + // Close the polygon if selected point is near start. Threshold for closing scaled by zoom level + if (points_prev.size() > 2 && tuv.distance_to(points_prev[0]) < (8 / uv_draw_zoom)) { undo_redo->create_action(TTR("Create Polygon & UV")); undo_redo->add_do_method(node, "set_uv", node->get_uv()); undo_redo->add_undo_method(node, "set_uv", uv_create_uv_prev); @@ -693,7 +695,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { polys.write[j] = mtx.xform(points_prev[idx]); } - if (Geometry::is_point_in_polygon(Vector2(mb->get_position().x, mb->get_position().y), polys)) { + if (Geometry2D::is_point_in_polygon(Vector2(mb->get_position().x, mb->get_position().y), polys)) { erase_index = i; break; } @@ -1213,7 +1215,8 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) : use_snap = EditorSettings::get_singleton()->get_project_metadata("polygon_2d_uv_editor", "snap_enabled", false); snap_show_grid = EditorSettings::get_singleton()->get_project_metadata("polygon_2d_uv_editor", "show_grid", false); - button_uv = memnew(ToolButton); + button_uv = memnew(Button); + button_uv->set_flat(true); add_child(button_uv); button_uv->set_tooltip(TTR("Open Polygon 2D UV editor.")); button_uv->connect("pressed", callable_mp(this, &Polygon2DEditor::_menu_option), varray(MODE_EDIT_UV)); @@ -1230,16 +1233,16 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) : uv_edit_group.instance(); - uv_edit_mode[0] = memnew(ToolButton); + uv_edit_mode[0] = memnew(Button); uv_mode_hb->add_child(uv_edit_mode[0]); uv_edit_mode[0]->set_toggle_mode(true); - uv_edit_mode[1] = memnew(ToolButton); + uv_edit_mode[1] = memnew(Button); uv_mode_hb->add_child(uv_edit_mode[1]); uv_edit_mode[1]->set_toggle_mode(true); - uv_edit_mode[2] = memnew(ToolButton); + uv_edit_mode[2] = memnew(Button); uv_mode_hb->add_child(uv_edit_mode[2]); uv_edit_mode[2]->set_toggle_mode(true); - uv_edit_mode[3] = memnew(ToolButton); + uv_edit_mode[3] = memnew(Button); uv_mode_hb->add_child(uv_edit_mode[3]); uv_edit_mode[3]->set_toggle_mode(true); @@ -1263,7 +1266,7 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) : uv_main_vb->add_child(uv_mode_hb); for (int i = 0; i < UV_MODE_MAX; i++) { - uv_button[i] = memnew(ToolButton); + uv_button[i] = memnew(Button); uv_button[i]->set_toggle_mode(true); uv_mode_hb->add_child(uv_button[i]); uv_button[i]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_mode), varray(i)); @@ -1333,7 +1336,8 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) : uv_mode_hb->add_child(memnew(VSeparator)); - b_snap_enable = memnew(ToolButton); + b_snap_enable = memnew(Button); + b_snap_enable->set_flat(true); uv_mode_hb->add_child(b_snap_enable); b_snap_enable->set_text(TTR("Snap")); b_snap_enable->set_focus_mode(FOCUS_NONE); @@ -1342,7 +1346,8 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) : b_snap_enable->set_tooltip(TTR("Enable Snap")); b_snap_enable->connect("toggled", callable_mp(this, &Polygon2DEditor::_set_use_snap)); - b_snap_grid = memnew(ToolButton); + b_snap_grid = memnew(Button); + b_snap_grid->set_flat(true); uv_mode_hb->add_child(b_snap_grid); b_snap_grid->set_text(TTR("Grid")); b_snap_grid->set_focus_mode(FOCUS_NONE); diff --git a/editor/plugins/polygon_2d_editor_plugin.h b/editor/plugins/polygon_2d_editor_plugin.h index b94ae53e2b..33ea7722ac 100644 --- a/editor/plugins/polygon_2d_editor_plugin.h +++ b/editor/plugins/polygon_2d_editor_plugin.h @@ -60,16 +60,16 @@ class Polygon2DEditor : public AbstractPolygon2DEditor { UV_MODE_MAX }; - ToolButton *uv_edit_mode[4]; + Button *uv_edit_mode[4]; Ref<ButtonGroup> uv_edit_group; Polygon2D *node; UVMode uv_mode; AcceptDialog *uv_edit; - ToolButton *uv_button[UV_MODE_MAX]; - ToolButton *b_snap_enable; - ToolButton *b_snap_grid; + Button *uv_button[UV_MODE_MAX]; + Button *b_snap_enable; + Button *b_snap_grid; Panel *uv_edit_draw; HSlider *uv_zoom; SpinBox *uv_zoom_value; @@ -115,7 +115,7 @@ class Polygon2DEditor : public AbstractPolygon2DEditor { AcceptDialog *error; - ToolButton *button_uv; + Button *button_uv; bool use_snap; bool snap_show_grid; diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 8d6dac3907..96079d5418 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -837,7 +837,6 @@ void ScriptEditor::_file_dialog_action(String p_file) { Error err; FileAccess *file = FileAccess::open(p_file, FileAccess::WRITE, &err); if (err) { - memdelete(file); editor->show_warning(TTR("Error writing TextFile:") + "\n" + p_file, TTR("Error!")); break; } @@ -2989,7 +2988,8 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { filename->add_theme_style_override("normal", EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox("normal", "LineEdit")); buttons_hbox->add_child(filename); - members_overview_alphabeta_sort_button = memnew(ToolButton); + members_overview_alphabeta_sort_button = memnew(Button); + members_overview_alphabeta_sort_button->set_flat(true); members_overview_alphabeta_sort_button->set_tooltip(TTR("Toggle alphabetical sorting of the method list.")); members_overview_alphabeta_sort_button->set_toggle_mode(true); members_overview_alphabeta_sort_button->set_pressed(EditorSettings::get_singleton()->get("text_editor/tools/sort_members_outline_alphabetically")); @@ -3050,7 +3050,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { file_menu->get_popup()->add_separator(); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save", TTR("Save"), KEY_MASK_ALT | KEY_MASK_CMD | KEY_S), FILE_SAVE); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save_as", TTR("Save As...")), FILE_SAVE_AS); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save_all", TTR("Save All"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_MASK_ALT | KEY_S), FILE_SAVE_ALL); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save_all", TTR("Save All"), KEY_MASK_SHIFT | KEY_MASK_ALT | KEY_S), FILE_SAVE_ALL); 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_ALT | 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); @@ -3116,13 +3116,15 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { menu_hb->add_spacer(); - site_search = memnew(ToolButton); + site_search = memnew(Button); + site_search->set_flat(true); site_search->set_text(TTR("Online Docs")); site_search->connect("pressed", callable_mp(this, &ScriptEditor::_menu_option), varray(SEARCH_WEBSITE)); menu_hb->add_child(site_search); site_search->set_tooltip(TTR("Open Godot online documentation.")); - help_search = memnew(ToolButton); + help_search = memnew(Button); + help_search->set_flat(true); help_search->set_text(TTR("Search Help")); help_search->connect("pressed", callable_mp(this, &ScriptEditor::_menu_option), varray(SEARCH_HELP)); menu_hb->add_child(help_search); @@ -3130,13 +3132,15 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { menu_hb->add_child(memnew(VSeparator)); - script_back = memnew(ToolButton); + script_back = memnew(Button); + script_back->set_flat(true); script_back->connect("pressed", callable_mp(this, &ScriptEditor::_history_back)); menu_hb->add_child(script_back); script_back->set_disabled(true); script_back->set_tooltip(TTR("Go to previous edited document.")); - script_forward = memnew(ToolButton); + script_forward = memnew(Button); + script_forward->set_flat(true); script_forward->connect("pressed", callable_mp(this, &ScriptEditor::_history_forward)); menu_hb->add_child(script_forward); script_forward->set_disabled(true); diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index f7352be7e8..8c4b7de27d 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -43,7 +43,6 @@ #include "scene/gui/split_container.h" #include "scene/gui/tab_container.h" #include "scene/gui/text_edit.h" -#include "scene/gui/tool_button.h" #include "scene/gui/tree.h" #include "scene/main/timer.h" #include "scene/resources/text_file.h" @@ -211,7 +210,7 @@ class ScriptEditor : public PanelContainer { VBoxContainer *overview_vbox; HBoxContainer *buttons_hbox; Label *filename; - ToolButton *members_overview_alphabeta_sort_button; + Button *members_overview_alphabeta_sort_button; bool members_overview_enabled; ItemList *help_overview; bool help_overview_enabled; @@ -221,15 +220,15 @@ class ScriptEditor : public PanelContainer { AcceptDialog *error_dialog; ConfirmationDialog *erase_tab_confirm; ScriptCreateDialog *script_create_dialog; - ToolButton *scripts_visible; + Button *scripts_visible; String current_theme; TextureRect *script_icon; Label *script_name_label; - ToolButton *script_back; - ToolButton *script_forward; + Button *script_back; + Button *script_forward; FindInFilesDialog *find_in_files_dialog; FindInFilesPanel *find_in_files; diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index e7f8a56e5e..1c9dadc0dd 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -383,10 +383,6 @@ void ScriptTextEditor::_show_warnings_panel(bool p_show) { warnings_panel->set_visible(p_show); } -void ScriptTextEditor::_error_pressed() { - code_editor->goto_error(); -} - void ScriptTextEditor::_warning_clicked(Variant p_line) { if (p_line.get_type() == Variant::INT) { code_editor->get_text_edit()->cursor_set_line(p_line.operator int64_t()); @@ -609,6 +605,18 @@ void ScriptTextEditor::_validate_script() { for (List<ScriptLanguage::Warning>::Element *E = warnings.front(); E; E = E->next()) { ScriptLanguage::Warning w = E->get(); + Dictionary ignore_meta; + ignore_meta["line"] = w.line; + ignore_meta["code"] = w.string_code.to_lower(); + warnings_panel->push_cell(); + warnings_panel->push_meta(ignore_meta); + warnings_panel->push_color( + warnings_panel->get_theme_color("accent_color", "Editor").lerp(warnings_panel->get_theme_color("mono_color", "Editor"), 0.5)); + warnings_panel->add_text(TTR("[Ignore]")); + warnings_panel->pop(); // Color. + warnings_panel->pop(); // Meta ignore. + warnings_panel->pop(); // Cell. + warnings_panel->push_cell(); warnings_panel->push_meta(w.line - 1); warnings_panel->push_color(warnings_panel->get_theme_color("warning_color", "Editor")); @@ -621,15 +629,6 @@ void ScriptTextEditor::_validate_script() { warnings_panel->push_cell(); warnings_panel->add_text(w.message); warnings_panel->pop(); // Cell. - - Dictionary ignore_meta; - ignore_meta["line"] = w.line; - ignore_meta["code"] = w.string_code.to_lower(); - warnings_panel->push_cell(); - warnings_panel->push_meta(ignore_meta); - warnings_panel->add_text(TTR("(ignore)")); - warnings_panel->pop(); // Meta ignore. - warnings_panel->pop(); // Cell. } warnings_panel->pop(); // Table. @@ -1747,6 +1746,8 @@ ScriptTextEditor::ScriptTextEditor() { warnings_panel = memnew(RichTextLabel); editor_box->add_child(warnings_panel); + warnings_panel->add_theme_font_override( + "normal_font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("main", "EditorFonts")); warnings_panel->set_custom_minimum_size(Size2(0, 100 * EDSCALE)); warnings_panel->set_h_size_flags(SIZE_EXPAND_FILL); warnings_panel->set_meta_underline(true); @@ -1754,7 +1755,6 @@ ScriptTextEditor::ScriptTextEditor() { warnings_panel->set_focus_mode(FOCUS_CLICK); warnings_panel->hide(); - code_editor->connect("error_pressed", callable_mp(this, &ScriptTextEditor::_error_pressed)); code_editor->connect("show_warnings_panel", callable_mp(this, &ScriptTextEditor::_show_warnings_panel)); warnings_panel->connect("meta_clicked", callable_mp(this, &ScriptTextEditor::_warning_clicked)); diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h index adcd0218bc..8fa380b64d 100644 --- a/editor/plugins/script_text_editor.h +++ b/editor/plugins/script_text_editor.h @@ -159,7 +159,6 @@ protected: void _load_theme_settings(); void _set_theme_for_script(); void _show_warnings_panel(bool p_show); - void _error_pressed(); void _warning_clicked(Variant p_line); void _notification(int p_what); diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp index c256acd17b..52da8dea19 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.cpp +++ b/editor/plugins/skeleton_3d_editor_plugin.cpp @@ -30,13 +30,289 @@ #include "skeleton_3d_editor_plugin.h" +#include "core/io/resource_saver.h" +#include "editor/editor_file_dialog.h" +#include "editor/editor_properties.h" +#include "editor/editor_scale.h" +#include "editor/plugins/animation_player_editor_plugin.h" #include "node_3d_editor_plugin.h" #include "scene/3d/collision_shape_3d.h" +#include "scene/3d/mesh_instance_3d.h" #include "scene/3d/physics_body_3d.h" #include "scene/3d/physics_joint_3d.h" #include "scene/resources/capsule_shape_3d.h" #include "scene/resources/sphere_shape_3d.h" +void BoneTransformEditor::create_editors() { + const Color section_color = get_theme_color("prop_subsection", "Editor"); + + section = memnew(EditorInspectorSection); + section->setup("trf_properties", label, this, section_color, true); + add_child(section); + + key_button = memnew(Button); + key_button->set_text(TTR("Key Transform")); + key_button->set_visible(keyable); + key_button->set_icon(get_theme_icon("Key", "EditorIcons")); + key_button->set_flat(true); + section->get_vbox()->add_child(key_button); + + enabled_checkbox = memnew(CheckBox(TTR("Pose Enabled"))); + enabled_checkbox->set_flat(true); + enabled_checkbox->set_visible(toggle_enabled); + section->get_vbox()->add_child(enabled_checkbox); + + // Translation property + translation_property = memnew(EditorPropertyVector3()); + translation_property->setup(-10000, 10000, 0.001f, true); + translation_property->set_label("Translation"); + translation_property->set_use_folding(true); + translation_property->set_read_only(false); + translation_property->connect("property_changed", callable_mp(this, &BoneTransformEditor::_value_changed_vector3)); + section->get_vbox()->add_child(translation_property); + + // Rotation property + rotation_property = memnew(EditorPropertyVector3()); + rotation_property->setup(-10000, 10000, 0.001f, true); + rotation_property->set_label("Rotation Degrees"); + rotation_property->set_use_folding(true); + rotation_property->set_read_only(false); + rotation_property->connect("property_changed", callable_mp(this, &BoneTransformEditor::_value_changed_vector3)); + section->get_vbox()->add_child(rotation_property); + + // Scale property + scale_property = memnew(EditorPropertyVector3()); + scale_property->setup(-10000, 10000, 0.001f, true); + scale_property->set_label("Scale"); + scale_property->set_use_folding(true); + scale_property->set_read_only(false); + scale_property->connect("property_changed", callable_mp(this, &BoneTransformEditor::_value_changed_vector3)); + section->get_vbox()->add_child(scale_property); + + // Transform/Matrix section + transform_section = memnew(EditorInspectorSection); + transform_section->setup("trf_properties_transform", "Matrix", this, section_color, true); + section->get_vbox()->add_child(transform_section); + + // Transform/Matrix property + transform_property = memnew(EditorPropertyTransform()); + transform_property->setup(-10000, 10000, 0.001f, true); + transform_property->set_label("Transform"); + transform_property->set_use_folding(true); + transform_property->set_read_only(false); + transform_property->connect("property_changed", callable_mp(this, &BoneTransformEditor::_value_changed_transform)); + transform_section->get_vbox()->add_child(transform_property); +} + +void BoneTransformEditor::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + create_editors(); + key_button->connect("pressed", callable_mp(this, &BoneTransformEditor::_key_button_pressed)); + enabled_checkbox->connect("toggled", callable_mp(this, &BoneTransformEditor::_checkbox_toggled)); + [[fallthrough]]; + } + case NOTIFICATION_SORT_CHILDREN: { + const Ref<Font> font = get_theme_font("font", "Tree"); + + Point2 buffer; + buffer.x += get_theme_constant("inspector_margin", "Editor"); + buffer.y += font->get_height(); + buffer.y += get_theme_constant("vseparation", "Tree"); + + const float vector_height = translation_property->get_size().y; + const float transform_height = transform_property->get_size().y; + const float button_height = key_button->get_size().y; + + const float width = get_size().x - get_theme_constant("inspector_margin", "Editor"); + Vector<Rect2> input_rects; + if (keyable && section->get_vbox()->is_visible()) { + input_rects.push_back(Rect2(key_button->get_position() + buffer, Size2(width, button_height))); + } else { + input_rects.push_back(Rect2(0, 0, 0, 0)); + } + + if (section->get_vbox()->is_visible()) { + input_rects.push_back(Rect2(translation_property->get_position() + buffer, Size2(width, vector_height))); + input_rects.push_back(Rect2(rotation_property->get_position() + buffer, Size2(width, vector_height))); + input_rects.push_back(Rect2(scale_property->get_position() + buffer, Size2(width, vector_height))); + input_rects.push_back(Rect2(transform_property->get_position() + buffer, Size2(width, transform_height))); + } else { + const int32_t start = input_rects.size(); + const int32_t empty_input_rect_elements = 4; + const int32_t end = start + empty_input_rect_elements; + for (int i = start; i < end; ++i) { + input_rects.push_back(Rect2(0, 0, 0, 0)); + } + } + + for (int32_t i = 0; i < input_rects.size(); i++) { + background_rects[i] = input_rects[i]; + } + + update(); + break; + } + case NOTIFICATION_DRAW: { + const Color dark_color = get_theme_color("dark_color_2", "Editor"); + + for (int i = 0; i < 5; ++i) { + draw_rect(background_rects[i], dark_color); + } + + break; + } + } +} + +void BoneTransformEditor::_value_changed(const double p_value) { + if (updating) + return; + + Transform tform = compute_transform_from_vector3s(); + _change_transform(tform); +} + +void BoneTransformEditor::_value_changed_vector3(const String p_property_name, const Vector3 p_vector, const StringName p_edited_property_name, const bool p_boolean) { + if (updating) + return; + Transform tform = compute_transform_from_vector3s(); + _change_transform(tform); +} + +Transform BoneTransformEditor::compute_transform_from_vector3s() const { + // Convert rotation from degrees to radians. + Vector3 prop_rotation = rotation_property->get_vector(); + prop_rotation.x = Math::deg2rad(prop_rotation.x); + prop_rotation.y = Math::deg2rad(prop_rotation.y); + prop_rotation.z = Math::deg2rad(prop_rotation.z); + + return Transform( + Basis(prop_rotation, scale_property->get_vector()), + translation_property->get_vector()); +} + +void BoneTransformEditor::_value_changed_transform(const String p_property_name, const Transform p_transform, const StringName p_edited_property_name, const bool p_boolean) { + if (updating) + return; + _change_transform(p_transform); +} + +void BoneTransformEditor::_change_transform(Transform p_new_transform) { + if (property.get_slicec('/', 0) == "bones" && property.get_slicec('/', 2) == "custom_pose") { + undo_redo->create_action(TTR("Set Custom Bone Pose Transform"), UndoRedo::MERGE_ENDS); + undo_redo->add_undo_method(skeleton, "set_bone_custom_pose", property.get_slicec('/', 1).to_int(), skeleton->get_bone_custom_pose(property.get_slicec('/', 1).to_int())); + undo_redo->add_do_method(skeleton, "set_bone_custom_pose", property.get_slicec('/', 1).to_int(), p_new_transform); + undo_redo->commit_action(); + } else if (property.get_slicec('/', 0) == "bones") { + undo_redo->create_action(TTR("Set Bone Transform"), UndoRedo::MERGE_ENDS); + undo_redo->add_undo_property(skeleton, property, skeleton->get(property)); + undo_redo->add_do_property(skeleton, property, p_new_transform); + undo_redo->commit_action(); + } +} + +void BoneTransformEditor::update_enabled_checkbox() { + if (enabled_checkbox) { + const String path = "bones/" + property.get_slicec('/', 1) + "/enabled"; + const bool is_enabled = skeleton->get(path); + enabled_checkbox->set_pressed(is_enabled); + } +} + +void BoneTransformEditor::_update_properties() { + if (updating) + return; + + if (skeleton == nullptr) + return; + + updating = true; + + Transform tform = skeleton->get(property); + _update_transform_properties(tform); +} + +void BoneTransformEditor::_update_custom_pose_properties() { + if (updating) + return; + + if (skeleton == nullptr) + return; + + updating = true; + + Transform tform = skeleton->get_bone_custom_pose(property.to_int()); + _update_transform_properties(tform); +} + +void BoneTransformEditor::_update_transform_properties(Transform tform) { + Basis rotation_basis = tform.get_basis(); + Vector3 rotation_radians = rotation_basis.get_rotation_euler(); + Vector3 rotation_degrees = Vector3(Math::rad2deg(rotation_radians.x), Math::rad2deg(rotation_radians.y), Math::rad2deg(rotation_radians.z)); + Vector3 translation = tform.get_origin(); + Vector3 scale = tform.basis.get_scale(); + + translation_property->update_using_vector(translation); + rotation_property->update_using_vector(rotation_degrees); + scale_property->update_using_vector(scale); + transform_property->update_using_transform(tform); + + update_enabled_checkbox(); + updating = false; +} + +BoneTransformEditor::BoneTransformEditor(Skeleton3D *p_skeleton) : + skeleton(p_skeleton), + key_button(nullptr), + enabled_checkbox(nullptr), + keyable(false), + toggle_enabled(false), + updating(false) { + undo_redo = EditorNode::get_undo_redo(); +} + +void BoneTransformEditor::set_target(const String &p_prop) { + property = p_prop; +} + +void BoneTransformEditor::set_keyable(const bool p_keyable) { + keyable = p_keyable; + if (key_button) { + key_button->set_visible(p_keyable); + } +} + +void BoneTransformEditor::set_toggle_enabled(const bool p_enabled) { + toggle_enabled = p_enabled; + if (enabled_checkbox) { + enabled_checkbox->set_visible(p_enabled); + } +} + +void BoneTransformEditor::_key_button_pressed() { + if (skeleton == nullptr) + return; + + const BoneId bone_id = property.get_slicec('/', 1).to_int(); + const String name = skeleton->get_bone_name(bone_id); + + if (name.empty()) + return; + + // Need to normalize the basis before you key it + Transform tform = compute_transform_from_vector3s(); + tform.orthonormalize(); + AnimationPlayerEditor::singleton->get_track_editor()->insert_transform_key(skeleton, name, tform); +} + +void BoneTransformEditor::_checkbox_toggled(const bool p_toggled) { + if (enabled_checkbox) { + const String path = "bones/" + property.get_slicec('/', 1) + "/enabled"; + skeleton->set(path, p_toggled); + } +} + void Skeleton3DEditor::_on_click_option(int p_option) { if (!skeleton) { return; @@ -45,12 +321,14 @@ void Skeleton3DEditor::_on_click_option(int p_option) { switch (p_option) { case MENU_OPTION_CREATE_PHYSICAL_SKELETON: { create_physical_skeleton(); - } break; + break; + } } } void Skeleton3DEditor::create_physical_skeleton() { UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); + ERR_FAIL_COND(!get_tree()); Node *owner = skeleton == get_tree()->get_edited_scene_root() ? skeleton : skeleton->get_owner(); const int bc = skeleton->get_bone_count(); @@ -124,28 +402,163 @@ PhysicalBone3D *Skeleton3DEditor::create_physical_bone(int bone_id, int bone_chi return physical_bone; } -void Skeleton3DEditor::edit(Skeleton3D *p_node) { - skeleton = p_node; +Variant Skeleton3DEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) { + TreeItem *selected = joint_tree->get_selected(); + + if (!selected) + return Variant(); + + Ref<Texture> icon = selected->get_icon(0); + + VBoxContainer *vb = memnew(VBoxContainer); + HBoxContainer *hb = memnew(HBoxContainer); + TextureRect *tf = memnew(TextureRect); + tf->set_texture(icon); + tf->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED); + hb->add_child(tf); + Label *label = memnew(Label(selected->get_text(0))); + hb->add_child(label); + vb->add_child(hb); + hb->set_modulate(Color(1, 1, 1, 1)); + + set_drag_preview(vb); + Dictionary drag_data; + drag_data["type"] = "nodes"; + drag_data["node"] = selected; + + return drag_data; } -void Skeleton3DEditor::_notification(int p_what) { - if (p_what == NOTIFICATION_ENTER_TREE) { - get_tree()->connect("node_removed", callable_mp(this, &Skeleton3DEditor::_node_removed)); +bool Skeleton3DEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const { + TreeItem *target = joint_tree->get_item_at_position(p_point); + if (!target) + return false; + + const String path = target->get_metadata(0); + if (!path.begins_with("bones/")) + return false; + + TreeItem *selected = Object::cast_to<TreeItem>(Dictionary(p_data)["node"]); + if (target == selected) + return false; + + const String path2 = target->get_metadata(0); + if (!path2.begins_with("bones/")) + return false; + + return true; +} + +void Skeleton3DEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) { + if (!can_drop_data_fw(p_point, p_data, p_from)) + return; + + TreeItem *target = joint_tree->get_item_at_position(p_point); + TreeItem *selected = Object::cast_to<TreeItem>(Dictionary(p_data)["node"]); + + const BoneId target_boneidx = String(target->get_metadata(0)).get_slicec('/', 1).to_int(); + const BoneId selected_boneidx = String(selected->get_metadata(0)).get_slicec('/', 1).to_int(); + + move_skeleton_bone(skeleton->get_path(), selected_boneidx, target_boneidx); +} + +void Skeleton3DEditor::move_skeleton_bone(NodePath p_skeleton_path, int32_t p_selected_boneidx, int32_t p_target_boneidx) { + Node *node = get_node_or_null(p_skeleton_path); + Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(node); + ERR_FAIL_NULL(skeleton); + UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); + ur->create_action(TTR("Set Bone Parentage")); + // If the target is a child of ourselves, we move only *us* and not our children + if (skeleton->is_bone_parent_of(p_target_boneidx, p_selected_boneidx)) { + const BoneId parent_idx = skeleton->get_bone_parent(p_selected_boneidx); + const int bone_count = skeleton->get_bone_count(); + for (BoneId i = 0; i < bone_count; ++i) { + if (skeleton->get_bone_parent(i) == p_selected_boneidx) { + ur->add_undo_method(skeleton, "set_bone_parent", i, skeleton->get_bone_parent(i)); + ur->add_do_method(skeleton, "set_bone_parent", i, parent_idx); + skeleton->set_bone_parent(i, parent_idx); + } + } } + ur->add_undo_method(skeleton, "set_bone_parent", p_selected_boneidx, skeleton->get_bone_parent(p_selected_boneidx)); + ur->add_do_method(skeleton, "set_bone_parent", p_selected_boneidx, p_target_boneidx); + skeleton->set_bone_parent(p_selected_boneidx, p_target_boneidx); + + update_joint_tree(); + ur->commit_action(); } -void Skeleton3DEditor::_node_removed(Node *p_node) { - if (p_node == skeleton) { - skeleton = nullptr; - options->hide(); +void Skeleton3DEditor::_joint_tree_selection_changed() { + TreeItem *selected = joint_tree->get_selected(); + const String path = selected->get_metadata(0); + + if (path.begins_with("bones/")) { + const int b_idx = path.get_slicec('/', 1).to_int(); + const String bone_path = "bones/" + itos(b_idx) + "/"; + + pose_editor->set_target(bone_path + "pose"); + rest_editor->set_target(bone_path + "rest"); + custom_pose_editor->set_target(bone_path + "custom_pose"); + + pose_editor->set_visible(true); + rest_editor->set_visible(true); + custom_pose_editor->set_visible(true); } } -void Skeleton3DEditor::_bind_methods() { +void Skeleton3DEditor::_joint_tree_rmb_select(const Vector2 &p_pos) { +} + +void Skeleton3DEditor::_update_properties() { + if (rest_editor) + rest_editor->_update_properties(); + if (pose_editor) + pose_editor->_update_properties(); + if (custom_pose_editor) + custom_pose_editor->_update_custom_pose_properties(); +} + +void Skeleton3DEditor::update_joint_tree() { + joint_tree->clear(); + + if (skeleton == nullptr) + return; + + TreeItem *root = joint_tree->create_item(); + + Map<int, TreeItem *> items; + + items.insert(-1, root); + + const Vector<int> &joint_porder = skeleton->get_bone_process_orders(); + Ref<Texture> bone_icon = get_theme_icon("BoneAttachment3D", "EditorIcons"); + + for (int i = 0; i < joint_porder.size(); ++i) { + const int b_idx = joint_porder[i]; + + const int p_idx = skeleton->get_bone_parent(b_idx); + TreeItem *p_item = items.find(p_idx)->get(); + + TreeItem *joint_item = joint_tree->create_item(p_item); + items.insert(b_idx, joint_item); + + joint_item->set_text(0, skeleton->get_bone_name(b_idx)); + joint_item->set_icon(0, bone_icon); + joint_item->set_selectable(0, true); + joint_item->set_metadata(0, "bones/" + itos(b_idx)); + } } -Skeleton3DEditor::Skeleton3DEditor() { - skeleton = nullptr; +void Skeleton3DEditor::update_editors() { +} + +void Skeleton3DEditor::create_editors() { + set_h_size_flags(SIZE_EXPAND_FILL); + add_theme_constant_override("separation", 0); + + set_focus_mode(FOCUS_ALL); + + // Create Top Menu Bar options = memnew(MenuButton); Node3DEditor::get_singleton()->add_control_to_menu_panel(options); @@ -155,32 +568,119 @@ Skeleton3DEditor::Skeleton3DEditor() { options->get_popup()->add_item(TTR("Create physical skeleton"), MENU_OPTION_CREATE_PHYSICAL_SKELETON); options->get_popup()->connect("id_pressed", callable_mp(this, &Skeleton3DEditor::_on_click_option)); - options->hide(); + + const Color section_color = get_theme_color("prop_subsection", "Editor"); + + EditorInspectorSection *bones_section = memnew(EditorInspectorSection); + bones_section->setup("bones", "Bones", skeleton, section_color, true); + add_child(bones_section); + bones_section->unfold(); + + ScrollContainer *s_con = memnew(ScrollContainer); + s_con->set_h_size_flags(SIZE_EXPAND_FILL); + s_con->set_custom_minimum_size(Size2(1, 350) * EDSCALE); + bones_section->get_vbox()->add_child(s_con); + + joint_tree = memnew(Tree); + joint_tree->set_columns(1); + joint_tree->set_focus_mode(Control::FocusMode::FOCUS_NONE); + joint_tree->set_select_mode(Tree::SELECT_SINGLE); + joint_tree->set_hide_root(true); + joint_tree->set_v_size_flags(SIZE_EXPAND_FILL); + joint_tree->set_h_size_flags(SIZE_EXPAND_FILL); + joint_tree->set_allow_rmb_select(true); + joint_tree->set_drag_forwarding(this); + s_con->add_child(joint_tree); + + pose_editor = memnew(BoneTransformEditor(skeleton)); + pose_editor->set_label(TTR("Bone Pose")); + pose_editor->set_keyable(AnimationPlayerEditor::singleton->get_track_editor()->has_keying()); + pose_editor->set_toggle_enabled(true); + pose_editor->set_visible(false); + add_child(pose_editor); + + rest_editor = memnew(BoneTransformEditor(skeleton)); + rest_editor->set_label(TTR("Bone Rest")); + rest_editor->set_visible(false); + add_child(rest_editor); + + custom_pose_editor = memnew(BoneTransformEditor(skeleton)); + custom_pose_editor->set_label(TTR("Bone Custom Pose")); + custom_pose_editor->set_visible(false); + add_child(custom_pose_editor); +} + +void Skeleton3DEditor::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + create_editors(); + update_joint_tree(); + update_editors(); + + get_tree()->connect("node_removed", callable_mp(this, &Skeleton3DEditor::_node_removed), Vector<Variant>(), Object::CONNECT_ONESHOT); + joint_tree->connect("item_selected", callable_mp(this, &Skeleton3DEditor::_joint_tree_selection_changed)); + joint_tree->connect("item_rmb_selected", callable_mp(this, &Skeleton3DEditor::_joint_tree_rmb_select)); +#ifdef TOOLS_ENABLED + skeleton->connect("pose_updated", callable_mp(this, &Skeleton3DEditor::_update_properties)); +#endif // TOOLS_ENABLED + + break; + } + } } -Skeleton3DEditor::~Skeleton3DEditor() {} +void Skeleton3DEditor::_node_removed(Node *p_node) { + if (skeleton && p_node == skeleton) { + skeleton = nullptr; + options->hide(); + } + + _update_properties(); +} -void Skeleton3DEditorPlugin::edit(Object *p_object) { - skeleton_editor->edit(Object::cast_to<Skeleton3D>(p_object)); +void Skeleton3DEditor::_bind_methods() { + ClassDB::bind_method(D_METHOD("_node_removed"), &Skeleton3DEditor::_node_removed); + ClassDB::bind_method(D_METHOD("_joint_tree_selection_changed"), &Skeleton3DEditor::_joint_tree_selection_changed); + ClassDB::bind_method(D_METHOD("_joint_tree_rmb_select"), &Skeleton3DEditor::_joint_tree_rmb_select); + ClassDB::bind_method(D_METHOD("_update_properties"), &Skeleton3DEditor::_update_properties); + ClassDB::bind_method(D_METHOD("_on_click_option"), &Skeleton3DEditor::_on_click_option); + + ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &Skeleton3DEditor::get_drag_data_fw); + ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &Skeleton3DEditor::can_drop_data_fw); + ClassDB::bind_method(D_METHOD("drop_data_fw"), &Skeleton3DEditor::drop_data_fw); + ClassDB::bind_method(D_METHOD("move_skeleton_bone"), &Skeleton3DEditor::move_skeleton_bone); } -bool Skeleton3DEditorPlugin::handles(Object *p_object) const { - return p_object->is_class("Skeleton3D"); +Skeleton3DEditor::Skeleton3DEditor(EditorInspectorPluginSkeleton *e_plugin, EditorNode *p_editor, Skeleton3D *p_skeleton) : + editor(p_editor), + editor_plugin(e_plugin), + skeleton(p_skeleton) { } -void Skeleton3DEditorPlugin::make_visible(bool p_visible) { - if (p_visible) { - skeleton_editor->options->show(); - } else { - skeleton_editor->options->hide(); - skeleton_editor->edit(nullptr); +Skeleton3DEditor::~Skeleton3DEditor() { + if (options) { + Node3DEditor::get_singleton()->remove_control_from_menu_panel(options); } } +bool EditorInspectorPluginSkeleton::can_handle(Object *p_object) { + return Object::cast_to<Skeleton3D>(p_object) != nullptr; +} + +void EditorInspectorPluginSkeleton::parse_begin(Object *p_object) { + Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(p_object); + ERR_FAIL_COND(!skeleton); + + Skeleton3DEditor *skel_editor = memnew(Skeleton3DEditor(this, editor, skeleton)); + add_custom_control(skel_editor); +} + Skeleton3DEditorPlugin::Skeleton3DEditorPlugin(EditorNode *p_node) { editor = p_node; - skeleton_editor = memnew(Skeleton3DEditor); - editor->get_viewport()->add_child(skeleton_editor); -} -Skeleton3DEditorPlugin::~Skeleton3DEditorPlugin() {} + Ref<EditorInspectorPluginSkeleton> skeleton_plugin; + skeleton_plugin.instance(); + skeleton_plugin->editor = editor; + + EditorInspector::add_inspector_plugin(skeleton_plugin); +} diff --git a/editor/plugins/skeleton_3d_editor_plugin.h b/editor/plugins/skeleton_3d_editor_plugin.h index af9ebb6246..a5b8ce80a9 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.h +++ b/editor/plugins/skeleton_3d_editor_plugin.h @@ -35,11 +35,91 @@ #include "editor/editor_plugin.h" #include "scene/3d/skeleton_3d.h" +class EditorInspectorPluginSkeleton; +class Joint; class PhysicalBone3D; -class Joint3D; +class Skeleton3DEditorPlugin; +class Button; +class CheckBox; +class EditorPropertyTransform; +class EditorPropertyVector3; -class Skeleton3DEditor : public Node { - GDCLASS(Skeleton3DEditor, Node); +class BoneTransformEditor : public VBoxContainer { + GDCLASS(BoneTransformEditor, VBoxContainer); + + EditorInspectorSection *section; + + EditorPropertyVector3 *translation_property; + EditorPropertyVector3 *rotation_property; + EditorPropertyVector3 *scale_property; + EditorInspectorSection *transform_section; + EditorPropertyTransform *transform_property; + + Rect2 background_rects[5]; + + Skeleton3D *skeleton; + String property; + + UndoRedo *undo_redo; + + Button *key_button; + CheckBox *enabled_checkbox; + + bool keyable; + bool toggle_enabled; + bool updating; + + String label; + + void create_editors(); + + // Called when one of the EditorSpinSliders are changed. + void _value_changed(const double p_value); + // Called when the one of the EditorPropertyVector3 are updated. + void _value_changed_vector3(const String p_property_name, const Vector3 p_vector, const StringName p_edited_property_name, const bool p_boolean); + // Called when the transform_property is updated. + void _value_changed_transform(const String p_property_name, const Transform p_transform, const StringName p_edited_property_name, const bool p_boolean); + // Changes the transform to the given transform and updates the UI accordingly. + void _change_transform(Transform p_new_transform); + // Creates a Transform using the EditorPropertyVector3 properties. + Transform compute_transform_from_vector3s() const; + + void update_enabled_checkbox(); + +protected: + void _notification(int p_what); + +public: + BoneTransformEditor(Skeleton3D *p_skeleton); + + // Which transform target to modify + void set_target(const String &p_prop); + void set_label(const String &p_label) { label = p_label; } + + void _update_properties(); + void _update_custom_pose_properties(); + void _update_transform_properties(Transform p_transform); + + // Can/cannot modify the spinner values for the Transform + void set_read_only(const bool p_read_only); + + // Transform can be keyed, whether or not to show the button + void set_keyable(const bool p_keyable); + + // Bone can be toggled enabled or disabled, whether or not to show the checkbox + void set_toggle_enabled(const bool p_enabled); + + // Key Transform Button pressed + void _key_button_pressed(); + + // Bone Enabled Checkbox toggled + void _checkbox_toggled(const bool p_toggled); +}; + +class Skeleton3DEditor : public VBoxContainer { + GDCLASS(Skeleton3DEditor, VBoxContainer); + + friend class Skeleton3DEditorPlugin; enum Menu { MENU_OPTION_CREATE_PHYSICAL_SKELETON @@ -51,44 +131,78 @@ class Skeleton3DEditor : public Node { BoneInfo() {} }; + EditorNode *editor; + EditorInspectorPluginSkeleton *editor_plugin; + Skeleton3D *skeleton; + Tree *joint_tree; + BoneTransformEditor *rest_editor; + BoneTransformEditor *pose_editor; + BoneTransformEditor *custom_pose_editor; + MenuButton *options; + EditorFileDialog *file_dialog; + + UndoRedo *undo_redo; void _on_click_option(int p_option); + void _file_selected(const String &p_file); - friend class Skeleton3DEditorPlugin; + EditorFileDialog *file_export_lib; + + void update_joint_tree(); + void update_editors(); + + void create_editors(); + + void create_physical_skeleton(); + PhysicalBone3D *create_physical_bone(int bone_id, int bone_child_id, const Vector<BoneInfo> &bones_infos); + + Variant get_drag_data_fw(const Point2 &p_point, Control *p_from); + bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; + void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from); protected: void _notification(int p_what); void _node_removed(Node *p_node); static void _bind_methods(); - void create_physical_skeleton(); - PhysicalBone3D *create_physical_bone(int bone_id, int bone_child_id, const Vector<BoneInfo> &bones_infos); - public: - void edit(Skeleton3D *p_node); + void move_skeleton_bone(NodePath p_skeleton_path, int32_t p_selected_boneidx, int32_t p_target_boneidx); + + Skeleton3D *get_skeleton() const { return skeleton; }; - Skeleton3DEditor(); + void _joint_tree_selection_changed(); + void _joint_tree_rmb_select(const Vector2 &p_pos); + + void _update_properties(); + + Skeleton3DEditor(EditorInspectorPluginSkeleton *e_plugin, EditorNode *p_editor, Skeleton3D *skeleton); ~Skeleton3DEditor(); }; +class EditorInspectorPluginSkeleton : public EditorInspectorPlugin { + GDCLASS(EditorInspectorPluginSkeleton, EditorInspectorPlugin); + + friend class Skeleton3DEditorPlugin; + + EditorNode *editor; + +public: + virtual bool can_handle(Object *p_object); + virtual void parse_begin(Object *p_object); +}; + class Skeleton3DEditorPlugin : public EditorPlugin { GDCLASS(Skeleton3DEditorPlugin, EditorPlugin); EditorNode *editor; - Skeleton3DEditor *skeleton_editor; public: - virtual String get_name() const { return "Skeleton3D"; } - virtual bool has_main_screen() const { return false; } - virtual void edit(Object *p_object); - virtual bool handles(Object *p_object) const; - virtual void make_visible(bool p_visible); - Skeleton3DEditorPlugin(EditorNode *p_node); - ~Skeleton3DEditorPlugin(); + + virtual String get_name() const { return "Skeleton3D"; } }; #endif // SKELETON_3D_EDITOR_PLUGIN_H diff --git a/editor/plugins/sprite_2d_editor_plugin.cpp b/editor/plugins/sprite_2d_editor_plugin.cpp index b21586a6b0..f5fafb68a5 100644 --- a/editor/plugins/sprite_2d_editor_plugin.cpp +++ b/editor/plugins/sprite_2d_editor_plugin.cpp @@ -31,6 +31,7 @@ #include "sprite_2d_editor_plugin.h" #include "canvas_item_editor_plugin.h" +#include "core/math/geometry_2d.h" #include "editor/editor_scale.h" #include "scene/2d/collision_polygon_2d.h" #include "scene/2d/light_occluder_2d.h" @@ -233,7 +234,7 @@ void Sprite2DEditor::_update_mesh_data() { computed_vertices.push_back(vtx); } - Vector<int> poly = Geometry::triangulate_polygon(lines[j]); + Vector<int> poly = Geometry2D::triangulate_polygon(lines[j]); for (int i = 0; i < poly.size(); i += 3) { for (int k = 0; k < 3; k++) { diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index 859fec1628..7102faf58a 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -873,12 +873,14 @@ SpriteFramesEditor::SpriteFramesEditor() { HBoxContainer *hbc_animlist = memnew(HBoxContainer); sub_vb->add_child(hbc_animlist); - new_anim = memnew(ToolButton); + new_anim = memnew(Button); + new_anim->set_flat(true); new_anim->set_tooltip(TTR("New Animation")); hbc_animlist->add_child(new_anim); new_anim->connect("pressed", callable_mp(this, &SpriteFramesEditor::_animation_add)); - remove_anim = memnew(ToolButton); + remove_anim = memnew(Button); + remove_anim->set_flat(true); remove_anim->set_tooltip(TTR("Remove Animation")); hbc_animlist->add_child(remove_anim); remove_anim->connect("pressed", callable_mp(this, &SpriteFramesEditor::_animation_remove)); @@ -913,45 +915,54 @@ SpriteFramesEditor::SpriteFramesEditor() { HBoxContainer *hbc = memnew(HBoxContainer); sub_vb->add_child(hbc); - load = memnew(ToolButton); + load = memnew(Button); + load->set_flat(true); load->set_tooltip(TTR("Add a Texture from File")); hbc->add_child(load); - load_sheet = memnew(ToolButton); + load_sheet = memnew(Button); + load_sheet->set_flat(true); load_sheet->set_tooltip(TTR("Add Frames from a Sprite Sheet")); hbc->add_child(load_sheet); hbc->add_child(memnew(VSeparator)); - copy = memnew(ToolButton); + copy = memnew(Button); + copy->set_flat(true); copy->set_tooltip(TTR("Copy")); hbc->add_child(copy); - paste = memnew(ToolButton); + paste = memnew(Button); + paste->set_flat(true); paste->set_tooltip(TTR("Paste")); hbc->add_child(paste); hbc->add_child(memnew(VSeparator)); - empty = memnew(ToolButton); + empty = memnew(Button); + empty->set_flat(true); empty->set_tooltip(TTR("Insert Empty (Before)")); hbc->add_child(empty); - empty2 = memnew(ToolButton); + empty2 = memnew(Button); + empty2->set_flat(true); empty2->set_tooltip(TTR("Insert Empty (After)")); hbc->add_child(empty2); hbc->add_child(memnew(VSeparator)); - move_up = memnew(ToolButton); + move_up = memnew(Button); + move_up->set_flat(true); move_up->set_tooltip(TTR("Move (Before)")); hbc->add_child(move_up); - move_down = memnew(ToolButton); + move_down = memnew(Button); + move_down->set_flat(true); move_down->set_tooltip(TTR("Move (After)")); hbc->add_child(move_down); - _delete = memnew(ToolButton); + _delete = memnew(Button); + _delete->set_flat(true); _delete->set_tooltip(TTR("Delete")); hbc->add_child(_delete); diff --git a/editor/plugins/sprite_frames_editor_plugin.h b/editor/plugins/sprite_frames_editor_plugin.h index 45646eb9e4..c050ae484b 100644 --- a/editor/plugins/sprite_frames_editor_plugin.h +++ b/editor/plugins/sprite_frames_editor_plugin.h @@ -43,22 +43,22 @@ class SpriteFramesEditor : public HSplitContainer { GDCLASS(SpriteFramesEditor, HSplitContainer); - ToolButton *load; - ToolButton *load_sheet; - ToolButton *_delete; - ToolButton *copy; - ToolButton *paste; - ToolButton *empty; - ToolButton *empty2; - ToolButton *move_up; - ToolButton *move_down; + Button *load; + Button *load_sheet; + Button *_delete; + Button *copy; + Button *paste; + Button *empty; + Button *empty2; + Button *move_up; + Button *move_down; ItemList *tree; bool loading_scene; int sel; HSplitContainer *split; - ToolButton *new_anim; - ToolButton *remove_anim; + Button *new_anim; + Button *remove_anim; Tree *animations; SpinBox *anim_speed; diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index 9b8b111be5..3a92818779 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -1037,17 +1037,20 @@ TextureRegionEditor::TextureRegionEditor(EditorNode *p_editor) { edit_draw->add_child(zoom_hb); zoom_hb->set_begin(Point2(5, 5)); - zoom_out = memnew(ToolButton); + zoom_out = memnew(Button); + zoom_out->set_flat(true); zoom_out->set_tooltip(TTR("Zoom Out")); zoom_out->connect("pressed", callable_mp(this, &TextureRegionEditor::_zoom_out)); zoom_hb->add_child(zoom_out); - zoom_reset = memnew(ToolButton); + zoom_reset = memnew(Button); + zoom_reset->set_flat(true); zoom_reset->set_tooltip(TTR("Zoom Reset")); zoom_reset->connect("pressed", callable_mp(this, &TextureRegionEditor::_zoom_reset)); zoom_hb->add_child(zoom_reset); - zoom_in = memnew(ToolButton); + zoom_in = memnew(Button); + zoom_in->set_flat(true); zoom_in->set_tooltip(TTR("Zoom In")); zoom_in->connect("pressed", callable_mp(this, &TextureRegionEditor::_zoom_in)); zoom_hb->add_child(zoom_in); diff --git a/editor/plugins/texture_region_editor_plugin.h b/editor/plugins/texture_region_editor_plugin.h index 93da23fd50..8991603c0f 100644 --- a/editor/plugins/texture_region_editor_plugin.h +++ b/editor/plugins/texture_region_editor_plugin.h @@ -56,9 +56,9 @@ class TextureRegionEditor : public VBoxContainer { friend class TextureRegionEditorPlugin; OptionButton *snap_mode_button; - ToolButton *zoom_in; - ToolButton *zoom_reset; - ToolButton *zoom_out; + Button *zoom_in; + Button *zoom_reset; + Button *zoom_out; HBoxContainer *hb_grid; //For showing/hiding the grid controls when changing the SnapMode SpinBox *sb_step_y; SpinBox *sb_step_x; diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index eb028659fd..43ace737c0 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -672,8 +672,9 @@ ThemeEditor::ThemeEditor() { bt->set_text(TTR("Disabled Button")); bt->set_disabled(true); first_vb->add_child(bt); - ToolButton *tb = memnew(ToolButton); - tb->set_text("ToolButton"); + Button *tb = memnew(Button); + tb->set_flat(true); + tb->set_text("Button"); first_vb->add_child(tb); CheckButton *cb = memnew(CheckButton); diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp index 3010d72d81..307a8a9001 100644 --- a/editor/plugins/tile_map_editor_plugin.cpp +++ b/editor/plugins/tile_map_editor_plugin.cpp @@ -64,6 +64,8 @@ void TileMapEditor::_notification(int p_what) { } paint_button->set_icon(get_theme_icon("Edit", "EditorIcons")); + line_button->set_icon(get_theme_icon("CurveLinear", "EditorIcons")); + rectangle_button->set_icon(get_theme_icon("RectangleShape2D", "EditorIcons")); bucket_fill_button->set_icon(get_theme_icon("Bucket", "EditorIcons")); picker_button->set_icon(get_theme_icon("ColorPick", "EditorIcons")); select_button->set_icon(get_theme_icon("ActionCopy", "EditorIcons")); @@ -91,9 +93,10 @@ void TileMapEditor::_notification(int p_what) { } void TileMapEditor::_update_button_tool() { - ToolButton *tb[4] = { paint_button, bucket_fill_button, picker_button, select_button }; + Button *tb[6] = { paint_button, line_button, rectangle_button, bucket_fill_button, picker_button, select_button }; + // Unpress all buttons - for (int i = 0; i < 4; i++) { + for (int i = 0; i < 6; i++) { tb[i]->set_pressed(false); } @@ -103,6 +106,12 @@ void TileMapEditor::_update_button_tool() { case TOOL_PAINTING: { paint_button->set_pressed(true); } break; + case TOOL_LINE_PAINT: { + line_button->set_pressed(true); + } break; + case TOOL_RECTANGLE_PAINT: { + rectangle_button->set_pressed(true); + } break; case TOOL_BUCKET: { bucket_fill_button->set_pressed(true); } break; @@ -194,6 +203,21 @@ void TileMapEditor::_palette_multi_selected(int index, bool selected) { _update_palette(); } +void TileMapEditor::_palette_input(const Ref<InputEvent> &p_event) { + const Ref<InputEventMouseButton> mb = p_event; + + // Zoom in/out using Ctrl + mouse wheel. + if (mb.is_valid() && mb->is_pressed() && mb->get_command()) { + if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_UP) { + size_slider->set_value(size_slider->get_value() + 0.2); + } + + if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_DOWN) { + size_slider->set_value(size_slider->get_value() - 0.2); + } + } +} + void TileMapEditor::_canvas_mouse_enter() { mouse_over = true; CanvasItemEditor::get_singleton()->update_viewport(); @@ -978,19 +1002,8 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { } if (tool == TOOL_NONE) { - if (mb->get_shift()) { - if (mb->get_command()) { - tool = TOOL_RECTANGLE_PAINT; - } else { - tool = TOOL_LINE_PAINT; - } - - selection_active = false; - rectangle_begin = over_tile; - - _update_button_tool(); - return true; - } + tool = TOOL_PAINTING; + _update_button_tool(); if (mb->get_command()) { tool = TOOL_PICKING; @@ -999,12 +1012,14 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { return true; } - - tool = TOOL_PAINTING; - _update_button_tool(); } - if (tool == TOOL_PAINTING) { + if (tool == TOOL_LINE_PAINT || tool == TOOL_RECTANGLE_PAINT) { + selection_active = false; + rectangle_begin = over_tile; + + mouse_down = true; + } else if (tool == TOOL_PAINTING) { Vector<int> ids = get_selected_tiles(); if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) { @@ -1035,6 +1050,10 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { paint_undo.clear(); } } else if (tool == TOOL_LINE_PAINT) { + if (!mouse_down) { + return true; + } + Vector<int> ids = get_selected_tiles(); if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) { @@ -1047,8 +1066,17 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { paint_undo.clear(); CanvasItemEditor::get_singleton()->update_viewport(); + + mouse_down = false; + return true; } + + mouse_down = false; } else if (tool == TOOL_RECTANGLE_PAINT) { + if (!mouse_down) { + return true; + } + Vector<int> ids = get_selected_tiles(); if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) { @@ -1061,7 +1089,12 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { _finish_undo(); CanvasItemEditor::get_singleton()->update_viewport(); + + mouse_down = false; + return true; } + + mouse_down = false; } else if (tool == TOOL_PASTING) { Point2 ofs = over_tile - rectangle.position; Vector<int> ids; @@ -1126,6 +1159,28 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { if (tool == TOOL_PASTING) { tool = TOOL_NONE; + + CanvasItemEditor::get_singleton()->update_viewport(); + + _update_button_tool(); + return true; + } + + if (tool == TOOL_LINE_PAINT) { + tool = TOOL_LINE_ERASE; + mouse_down = true; + rectangle_begin = over_tile; + + CanvasItemEditor::get_singleton()->update_viewport(); + + _update_button_tool(); + return true; + } + + if (tool == TOOL_RECTANGLE_PAINT) { + tool = TOOL_RECTANGLE_ERASE; + mouse_down = true; + rectangle_begin = over_tile; copydata.clear(); CanvasItemEditor::get_singleton()->update_viewport(); @@ -1140,39 +1195,74 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { Point2 local = node->world_to_map(xform_inv.xform(mb->get_position())); _start_undo(TTR("Erase TileMap")); + tool = TOOL_ERASING; + _set_cell(local, invalid_cell); - if (mb->get_shift()) { - if (mb->get_command()) { - tool = TOOL_RECTANGLE_ERASE; - } else { - tool = TOOL_LINE_ERASE; + _update_button_tool(); + return true; + } + + } else { + if (tool == TOOL_LINE_ERASE) { + if (!mouse_down) { + return true; + } + + tool = TOOL_LINE_PAINT; + _update_button_tool(); + + Vector<int> ids = get_selected_tiles(); + + if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) { + _start_undo(TTR("Line Erase")); + for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) { + _set_cell(E->key(), invalid_cell, flip_h, flip_v, transpose); } + _finish_undo(); + paint_undo.clear(); - selection_active = false; - rectangle_begin = local; - } else { - tool = TOOL_ERASING; + CanvasItemEditor::get_singleton()->update_viewport(); - _set_cell(local, invalid_cell); + mouse_down = false; + return true; } + mouse_down = false; + } else if (tool == TOOL_RECTANGLE_ERASE) { + if (!mouse_down) { + return true; + } + + tool = TOOL_RECTANGLE_PAINT; _update_button_tool(); - return true; - } - } else { - if (tool == TOOL_ERASING || tool == TOOL_RECTANGLE_ERASE || tool == TOOL_LINE_ERASE) { - _finish_undo(); + Vector<int> ids = get_selected_tiles(); + + if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) { + _start_undo(TTR("Rectangle Erase")); + 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++) { + _set_cell(Point2i(j, i), invalid_cell, flip_h, flip_v, transpose); + } + } + _finish_undo(); + paint_undo.clear(); - if (tool == TOOL_RECTANGLE_ERASE || tool == TOOL_LINE_ERASE) { CanvasItemEditor::get_singleton()->update_viewport(); + + mouse_down = false; + return true; } - tool = TOOL_NONE; + mouse_down = false; + tool = TOOL_RECTANGLE_PAINT; + } + if (tool == TOOL_ERASING) { + tool = TOOL_NONE; _update_button_tool(); - return true; + return true; } else if (tool == TOOL_BUCKET) { Vector<int> ids; ids.push_back(node->get_cell(over_tile.x, over_tile.y)); @@ -1263,6 +1353,10 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { Vector<int> tmp_cell; bool erasing = (tool == TOOL_LINE_ERASE); + if (!mouse_down) { + return true; + } + tmp_cell.push_back(0); if (erasing && paint_undo.size()) { for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) { @@ -1293,7 +1387,20 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { Vector<int> tmp_cell; tmp_cell.push_back(0); - _select(rectangle_begin, over_tile); + Point2i end_tile = over_tile; + + if (!mouse_down) { + return true; + } + + if (mm->get_shift()) { + int size = fmax(ABS(end_tile.x - rectangle_begin.x), ABS(end_tile.y - rectangle_begin.y)); + int xDirection = MAX(MIN(end_tile.x - rectangle_begin.x, 1), -1); + int yDirection = MAX(MIN(end_tile.y - rectangle_begin.y, 1), -1); + end_tile = rectangle_begin + Point2i(xDirection * size, yDirection * size); + } + + _select(rectangle_begin, end_tile); if (tool == TOOL_RECTANGLE_ERASE) { if (paint_undo.size()) { @@ -1364,6 +1471,20 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { _update_button_tool(); return true; } + if (ED_IS_SHORTCUT("tile_map_editor/line_fill", p_event)) { + tool = TOOL_LINE_PAINT; + CanvasItemEditor::get_singleton()->update_viewport(); + + _update_button_tool(); + return true; + } + if (ED_IS_SHORTCUT("tile_map_editor/rectangle_fill", p_event)) { + tool = TOOL_RECTANGLE_PAINT; + CanvasItemEditor::get_singleton()->update_viewport(); + + _update_button_tool(); + return true; + } if (ED_IS_SHORTCUT("tile_map_editor/bucket_fill", p_event)) { tool = TOOL_BUCKET; CanvasItemEditor::get_singleton()->update_viewport(); @@ -1622,6 +1743,10 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { } if (tool == TOOL_LINE_PAINT) { + if (!mouse_down) { + return; + } + if (paint_undo.empty()) { return; } @@ -1637,6 +1762,10 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { } } else if (tool == TOOL_RECTANGLE_PAINT) { + if (!mouse_down) { + return; + } + Vector<int> ids = get_selected_tiles(); if (ids.size() == 1 && ids[0] == TileMap::INVALID_CELL) { @@ -1850,6 +1979,7 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { tool = TOOL_NONE; selection_active = false; mouse_over = false; + mouse_down = false; flip_h = false; flip_v = false; @@ -1913,6 +2043,7 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { palette->add_theme_constant_override("vseparation", 8 * EDSCALE); palette->connect("item_selected", callable_mp(this, &TileMapEditor::_palette_selected)); palette->connect("multi_selected", callable_mp(this, &TileMapEditor::_palette_multi_selected)); + palette->connect("gui_input", callable_mp(this, &TileMapEditor::_palette_input)); palette_container->add_child(palette); // Add message for when no texture is selected. @@ -1943,26 +2074,46 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { toolbar->add_child(memnew(VSeparator)); // Tools. - paint_button = memnew(ToolButton); + paint_button = memnew(Button); + paint_button->set_flat(true); paint_button->set_shortcut(ED_SHORTCUT("tile_map_editor/paint_tile", TTR("Paint Tile"), KEY_P)); - paint_button->set_tooltip(TTR("Shift+LMB: Line Draw\nShift+Ctrl+LMB: Rectangle Paint")); + paint_button->set_tooltip(TTR("RMB: Erase")); paint_button->connect("pressed", callable_mp(this, &TileMapEditor::_button_tool_select), make_binds(TOOL_NONE)); paint_button->set_toggle_mode(true); toolbar->add_child(paint_button); - bucket_fill_button = memnew(ToolButton); - bucket_fill_button->set_shortcut(ED_SHORTCUT("tile_map_editor/bucket_fill", TTR("Bucket Fill"), KEY_G)); + line_button = memnew(Button); + line_button->set_flat(true); + line_button->set_shortcut(ED_SHORTCUT("tile_map_editor/line_fill", TTR("Line Fill"), KEY_L)); + line_button->set_tooltip(TTR("RMB: Erase")); + line_button->connect("pressed", callable_mp(this, &TileMapEditor::_button_tool_select), make_binds(TOOL_LINE_PAINT)); + line_button->set_toggle_mode(true); + toolbar->add_child(line_button); + + rectangle_button = memnew(Button); + rectangle_button->set_flat(true); + rectangle_button->set_shortcut(ED_SHORTCUT("tile_map_editor/rectangle_fill", TTR("Rectangle Fill"), KEY_O)); + rectangle_button->set_tooltip(TTR("Shift+LMB: Keep 1:1 proporsions\nRMB: Erase")); + rectangle_button->connect("pressed", callable_mp(this, &TileMapEditor::_button_tool_select), make_binds(TOOL_RECTANGLE_PAINT)); + rectangle_button->set_toggle_mode(true); + toolbar->add_child(rectangle_button); + + bucket_fill_button = memnew(Button); + bucket_fill_button->set_flat(true); + bucket_fill_button->set_shortcut(ED_SHORTCUT("tile_map_editor/bucket_fill", TTR("Bucket Fill"), KEY_B)); bucket_fill_button->connect("pressed", callable_mp(this, &TileMapEditor::_button_tool_select), make_binds(TOOL_BUCKET)); bucket_fill_button->set_toggle_mode(true); toolbar->add_child(bucket_fill_button); - picker_button = memnew(ToolButton); + picker_button = memnew(Button); + picker_button->set_flat(true); picker_button->set_shortcut(ED_SHORTCUT("tile_map_editor/pick_tile", TTR("Pick Tile"), KEY_I)); picker_button->connect("pressed", callable_mp(this, &TileMapEditor::_button_tool_select), make_binds(TOOL_PICKING)); picker_button->set_toggle_mode(true); toolbar->add_child(picker_button); - select_button = memnew(ToolButton); + select_button = memnew(Button); + select_button->set_flat(true); select_button->set_shortcut(ED_SHORTCUT("tile_map_editor/select", TTR("Select"), KEY_M)); select_button->connect("pressed", callable_mp(this, &TileMapEditor::_button_tool_select), make_binds(TOOL_SELECTING)); select_button->set_toggle_mode(true); @@ -2001,35 +2152,40 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { p->add_item(TTR("Fix Invalid Tiles"), OPTION_FIX_INVALID); p->connect("id_pressed", callable_mp(this, &TileMapEditor::_menu_option)); - rotate_left_button = memnew(ToolButton); + rotate_left_button = memnew(Button); + rotate_left_button->set_flat(true); rotate_left_button->set_tooltip(TTR("Rotate Left")); rotate_left_button->set_focus_mode(FOCUS_NONE); rotate_left_button->connect("pressed", callable_mp(this, &TileMapEditor::_rotate), varray(-1)); rotate_left_button->set_shortcut(ED_SHORTCUT("tile_map_editor/rotate_left", TTR("Rotate Left"), KEY_A)); tool_hb->add_child(rotate_left_button); - rotate_right_button = memnew(ToolButton); + rotate_right_button = memnew(Button); + rotate_right_button->set_flat(true); rotate_right_button->set_tooltip(TTR("Rotate Right")); rotate_right_button->set_focus_mode(FOCUS_NONE); rotate_right_button->connect("pressed", callable_mp(this, &TileMapEditor::_rotate), varray(1)); rotate_right_button->set_shortcut(ED_SHORTCUT("tile_map_editor/rotate_right", TTR("Rotate Right"), KEY_S)); tool_hb->add_child(rotate_right_button); - flip_horizontal_button = memnew(ToolButton); + flip_horizontal_button = memnew(Button); + flip_horizontal_button->set_flat(true); flip_horizontal_button->set_tooltip(TTR("Flip Horizontally")); flip_horizontal_button->set_focus_mode(FOCUS_NONE); flip_horizontal_button->connect("pressed", callable_mp(this, &TileMapEditor::_flip_horizontal)); flip_horizontal_button->set_shortcut(ED_SHORTCUT("tile_map_editor/flip_horizontal", TTR("Flip Horizontally"), KEY_X)); tool_hb->add_child(flip_horizontal_button); - flip_vertical_button = memnew(ToolButton); + flip_vertical_button = memnew(Button); + flip_vertical_button->set_flat(true); flip_vertical_button->set_tooltip(TTR("Flip Vertically")); flip_vertical_button->set_focus_mode(FOCUS_NONE); flip_vertical_button->connect("pressed", callable_mp(this, &TileMapEditor::_flip_vertical)); flip_vertical_button->set_shortcut(ED_SHORTCUT("tile_map_editor/flip_vertical", TTR("Flip Vertically"), KEY_Z)); tool_hb->add_child(flip_vertical_button); - clear_transform_button = memnew(ToolButton); + clear_transform_button = memnew(Button); + clear_transform_button->set_flat(true); clear_transform_button->set_tooltip(TTR("Clear Transform")); clear_transform_button->set_focus_mode(FOCUS_NONE); clear_transform_button->connect("pressed", callable_mp(this, &TileMapEditor::_clear_transform)); diff --git a/editor/plugins/tile_map_editor_plugin.h b/editor/plugins/tile_map_editor_plugin.h index 5f82d7bfb8..135a9bd5a5 100644 --- a/editor/plugins/tile_map_editor_plugin.h +++ b/editor/plugins/tile_map_editor_plugin.h @@ -38,7 +38,6 @@ #include "scene/gui/label.h" #include "scene/gui/line_edit.h" #include "scene/gui/menu_button.h" -#include "scene/gui/tool_button.h" class TileMapEditor : public VBoxContainer { GDCLASS(TileMapEditor, VBoxContainer); @@ -88,16 +87,18 @@ class TileMapEditor : public VBoxContainer { Label *tile_info; MenuButton *options; - ToolButton *paint_button; - ToolButton *bucket_fill_button; - ToolButton *picker_button; - ToolButton *select_button; + Button *paint_button; + Button *line_button; + Button *rectangle_button; + Button *bucket_fill_button; + Button *picker_button; + Button *select_button; - ToolButton *flip_horizontal_button; - ToolButton *flip_vertical_button; - ToolButton *rotate_left_button; - ToolButton *rotate_right_button; - ToolButton *clear_transform_button; + Button *flip_horizontal_button; + Button *flip_vertical_button; + Button *rotate_left_button; + Button *rotate_right_button; + Button *clear_transform_button; CheckBox *manual_button; CheckBox *priority_button; @@ -107,6 +108,7 @@ class TileMapEditor : public VBoxContainer { bool selection_active; bool mouse_over; + bool mouse_down; bool flip_h; bool flip_v; @@ -182,6 +184,7 @@ class TileMapEditor : public VBoxContainer { void _menu_option(int p_option); void _palette_selected(int index); void _palette_multi_selected(int index, bool selected); + void _palette_input(const Ref<InputEvent> &p_event); Dictionary _create_cell_dictionary(int tile, bool flip_x, bool flip_y, bool transpose, Vector2 autotile_coord); void _start_undo(const String &p_action); diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp index 644facd5bd..a37cf7e426 100644 --- a/editor/plugins/tile_set_editor_plugin.cpp +++ b/editor/plugins/tile_set_editor_plugin.cpp @@ -341,12 +341,12 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { HBoxContainer *tileset_toolbar_container = memnew(HBoxContainer); left_container->add_child(tileset_toolbar_container); - tileset_toolbar_buttons[TOOL_TILESET_ADD_TEXTURE] = memnew(ToolButton); + tileset_toolbar_buttons[TOOL_TILESET_ADD_TEXTURE] = memnew(Button); tileset_toolbar_buttons[TOOL_TILESET_ADD_TEXTURE]->connect("pressed", callable_mp(this, &TileSetEditor::_on_tileset_toolbar_button_pressed), varray(TOOL_TILESET_ADD_TEXTURE)); tileset_toolbar_container->add_child(tileset_toolbar_buttons[TOOL_TILESET_ADD_TEXTURE]); tileset_toolbar_buttons[TOOL_TILESET_ADD_TEXTURE]->set_tooltip(TTR("Add Texture(s) to TileSet.")); - tileset_toolbar_buttons[TOOL_TILESET_REMOVE_TEXTURE] = memnew(ToolButton); + tileset_toolbar_buttons[TOOL_TILESET_REMOVE_TEXTURE] = memnew(Button); tileset_toolbar_buttons[TOOL_TILESET_REMOVE_TEXTURE]->connect("pressed", callable_mp(this, &TileSetEditor::_on_tileset_toolbar_button_pressed), varray(TOOL_TILESET_REMOVE_TEXTURE)); tileset_toolbar_container->add_child(tileset_toolbar_buttons[TOOL_TILESET_REMOVE_TEXTURE]); tileset_toolbar_buttons[TOOL_TILESET_REMOVE_TEXTURE]->set_tooltip(TTR("Remove selected Texture from TileSet.")); @@ -402,13 +402,13 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { tool_hb->add_child(spacer); tool_hb->move_child(spacer, WORKSPACE_CREATE_SINGLE); - tools[SELECT_NEXT] = memnew(ToolButton); + tools[SELECT_NEXT] = memnew(Button); tool_hb->add_child(tools[SELECT_NEXT]); tool_hb->move_child(tools[SELECT_NEXT], WORKSPACE_CREATE_SINGLE); tools[SELECT_NEXT]->set_shortcut(ED_SHORTCUT("tileset_editor/next_shape", TTR("Next Coordinate"), KEY_PAGEDOWN)); tools[SELECT_NEXT]->connect("pressed", callable_mp(this, &TileSetEditor::_on_tool_clicked), varray(SELECT_NEXT)); tools[SELECT_NEXT]->set_tooltip(TTR("Select the next shape, subtile, or Tile.")); - tools[SELECT_PREVIOUS] = memnew(ToolButton); + tools[SELECT_PREVIOUS] = memnew(Button); tool_hb->add_child(tools[SELECT_PREVIOUS]); tool_hb->move_child(tools[SELECT_PREVIOUS], WORKSPACE_CREATE_SINGLE); tools[SELECT_PREVIOUS]->set_shortcut(ED_SHORTCUT("tileset_editor/previous_shape", TTR("Previous Coordinate"), KEY_PAGEUP)); @@ -465,7 +465,7 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { toolbar = memnew(HBoxContainer); Ref<ButtonGroup> tg(memnew(ButtonGroup)); - tools[TOOL_SELECT] = memnew(ToolButton); + tools[TOOL_SELECT] = memnew(Button); toolbar->add_child(tools[TOOL_SELECT]); tools[TOOL_SELECT]->set_toggle_mode(true); tools[TOOL_SELECT]->set_button_group(tg); @@ -474,40 +474,42 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { separator_bitmask = memnew(VSeparator); toolbar->add_child(separator_bitmask); - tools[BITMASK_COPY] = memnew(ToolButton); + tools[BITMASK_COPY] = memnew(Button); tools[BITMASK_COPY]->set_tooltip(TTR("Copy bitmask.")); tools[BITMASK_COPY]->connect("pressed", callable_mp(this, &TileSetEditor::_on_tool_clicked), varray(BITMASK_COPY)); toolbar->add_child(tools[BITMASK_COPY]); - tools[BITMASK_PASTE] = memnew(ToolButton); + tools[BITMASK_PASTE] = memnew(Button); tools[BITMASK_PASTE]->set_tooltip(TTR("Paste bitmask.")); tools[BITMASK_PASTE]->connect("pressed", callable_mp(this, &TileSetEditor::_on_tool_clicked), varray(BITMASK_PASTE)); toolbar->add_child(tools[BITMASK_PASTE]); - tools[BITMASK_CLEAR] = memnew(ToolButton); + tools[BITMASK_CLEAR] = memnew(Button); tools[BITMASK_CLEAR]->set_tooltip(TTR("Erase bitmask.")); tools[BITMASK_CLEAR]->connect("pressed", callable_mp(this, &TileSetEditor::_on_tool_clicked), varray(BITMASK_CLEAR)); toolbar->add_child(tools[BITMASK_CLEAR]); - tools[SHAPE_NEW_RECTANGLE] = memnew(ToolButton); + tools[SHAPE_NEW_RECTANGLE] = memnew(Button); toolbar->add_child(tools[SHAPE_NEW_RECTANGLE]); tools[SHAPE_NEW_RECTANGLE]->set_toggle_mode(true); tools[SHAPE_NEW_RECTANGLE]->set_button_group(tg); tools[SHAPE_NEW_RECTANGLE]->set_tooltip(TTR("Create a new rectangle.")); + tools[SHAPE_NEW_RECTANGLE]->connect("pressed", callable_mp(this, &TileSetEditor::_on_tool_clicked), varray(SHAPE_NEW_RECTANGLE)); - tools[SHAPE_NEW_POLYGON] = memnew(ToolButton); + tools[SHAPE_NEW_POLYGON] = memnew(Button); toolbar->add_child(tools[SHAPE_NEW_POLYGON]); tools[SHAPE_NEW_POLYGON]->set_toggle_mode(true); tools[SHAPE_NEW_POLYGON]->set_button_group(tg); tools[SHAPE_NEW_POLYGON]->set_tooltip(TTR("Create a new polygon.")); + tools[SHAPE_NEW_POLYGON]->connect("pressed", callable_mp(this, &TileSetEditor::_on_tool_clicked), varray(SHAPE_NEW_POLYGON)); separator_shape_toggle = memnew(VSeparator); toolbar->add_child(separator_shape_toggle); - tools[SHAPE_TOGGLE_TYPE] = memnew(ToolButton); + tools[SHAPE_TOGGLE_TYPE] = memnew(Button); tools[SHAPE_TOGGLE_TYPE]->connect("pressed", callable_mp(this, &TileSetEditor::_on_tool_clicked), varray(SHAPE_TOGGLE_TYPE)); toolbar->add_child(tools[SHAPE_TOGGLE_TYPE]); separator_delete = memnew(VSeparator); toolbar->add_child(separator_delete); - tools[SHAPE_DELETE] = memnew(ToolButton); + tools[SHAPE_DELETE] = memnew(Button); tools[SHAPE_DELETE]->connect("pressed", callable_mp(this, &TileSetEditor::_on_tool_clicked), varray(SHAPE_DELETE)); toolbar->add_child(tools[SHAPE_DELETE]); @@ -531,12 +533,12 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { separator_grid = memnew(VSeparator); toolbar->add_child(separator_grid); - tools[SHAPE_KEEP_INSIDE_TILE] = memnew(ToolButton); + tools[SHAPE_KEEP_INSIDE_TILE] = memnew(Button); tools[SHAPE_KEEP_INSIDE_TILE]->set_toggle_mode(true); tools[SHAPE_KEEP_INSIDE_TILE]->set_pressed(true); tools[SHAPE_KEEP_INSIDE_TILE]->set_tooltip(TTR("Keep polygon inside region Rect.")); toolbar->add_child(tools[SHAPE_KEEP_INSIDE_TILE]); - tools[TOOL_GRID_SNAP] = memnew(ToolButton); + tools[TOOL_GRID_SNAP] = memnew(Button); tools[TOOL_GRID_SNAP]->set_toggle_mode(true); tools[TOOL_GRID_SNAP]->set_tooltip(TTR("Enable snap and show grid (configurable via the Inspector).")); tools[TOOL_GRID_SNAP]->connect("toggled", callable_mp(this, &TileSetEditor::_on_grid_snap_toggled)); @@ -546,20 +548,20 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { separator->set_h_size_flags(SIZE_EXPAND_FILL); toolbar->add_child(separator); - tools[ZOOM_OUT] = memnew(ToolButton); + tools[ZOOM_OUT] = memnew(Button); tools[ZOOM_OUT]->connect("pressed", callable_mp(this, &TileSetEditor::_zoom_out)); toolbar->add_child(tools[ZOOM_OUT]); tools[ZOOM_OUT]->set_tooltip(TTR("Zoom Out")); - tools[ZOOM_1] = memnew(ToolButton); + tools[ZOOM_1] = memnew(Button); tools[ZOOM_1]->connect("pressed", callable_mp(this, &TileSetEditor::_zoom_reset)); toolbar->add_child(tools[ZOOM_1]); tools[ZOOM_1]->set_tooltip(TTR("Zoom Reset")); - tools[ZOOM_IN] = memnew(ToolButton); + tools[ZOOM_IN] = memnew(Button); tools[ZOOM_IN]->connect("pressed", callable_mp(this, &TileSetEditor::_zoom_in)); toolbar->add_child(tools[ZOOM_IN]); tools[ZOOM_IN]->set_tooltip(TTR("Zoom In")); - tools[VISIBLE_INFO] = memnew(ToolButton); + tools[VISIBLE_INFO] = memnew(Button); tools[VISIBLE_INFO]->set_toggle_mode(true); tools[VISIBLE_INFO]->set_tooltip(TTR("Display Tile Names (Hold Alt Key)")); toolbar->add_child(tools[VISIBLE_INFO]); @@ -569,6 +571,7 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { scroll = memnew(ScrollContainer); main_vb->add_child(scroll); scroll->set_v_size_flags(SIZE_EXPAND_FILL); + scroll->connect("gui_input", callable_mp(this, &TileSetEditor::_on_scroll_container_input)); scroll->set_clip_contents(true); empty_message = memnew(Label); @@ -1198,6 +1201,27 @@ bool TileSetEditor::is_within_grabbing_distance_of_first_point(const Vector2 &p_ return distance < p_grab_threshold; } +void TileSetEditor::_on_scroll_container_input(const Ref<InputEvent> &p_event) { + const Ref<InputEventMouseButton> mb = p_event; + + if (mb.is_valid()) { + // Zoom in/out using Ctrl + mouse wheel. This is done on the ScrollContainer + // to allow performing this action anywhere, even if the cursor isn't + // hovering the texture in the workspace. + if (mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed() && mb->get_control()) { + print_line("zooming in"); + _zoom_in(); + // Don't scroll up after zooming in. + accept_event(); + } else if (mb->get_button_index() == BUTTON_WHEEL_DOWN && mb->is_pressed() && mb->get_control()) { + print_line("zooming out"); + _zoom_out(); + // Don't scroll down after zooming out. + accept_event(); + } + } +} + void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { if (tileset.is_null() || !get_current_texture().is_valid()) { return; @@ -1214,8 +1238,8 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { } current_tile_region.position += WORKSPACE_MARGIN; - Ref<InputEventMouseButton> mb = p_ie; - Ref<InputEventMouseMotion> mm = p_ie; + const Ref<InputEventMouseButton> mb = p_ie; + const Ref<InputEventMouseMotion> mm = p_ie; if (mb.is_valid()) { if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && !creating_shape) { @@ -1239,13 +1263,6 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { delete tiles; } } - - // Mouse Wheel Event - if (mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed() && mb->get_control()) { - _zoom_in(); - } else if (mb->get_button_index() == BUTTON_WHEEL_DOWN && mb->is_pressed() && mb->get_control()) { - _zoom_out(); - } } // Drag Middle Mouse if (mm.is_valid()) { @@ -1893,7 +1910,7 @@ void TileSetEditor::_on_tool_clicked(int p_tool) { } } } - } else if (p_tool == TOOL_SELECT) { + } else if (p_tool == TOOL_SELECT || p_tool == SHAPE_NEW_POLYGON || p_tool == SHAPE_NEW_RECTANGLE) { if (creating_shape) { // Cancel Creation creating_shape = false; diff --git a/editor/plugins/tile_set_editor_plugin.h b/editor/plugins/tile_set_editor_plugin.h index 827325cfd7..d2687e7a4b 100644 --- a/editor/plugins/tile_set_editor_plugin.h +++ b/editor/plugins/tile_set_editor_plugin.h @@ -46,7 +46,7 @@ class TileSetEditor : public HSplitContainer { GDCLASS(TileSetEditor, HSplitContainer); - enum TextureToolButtons { + enum TextureButtons { TOOL_TILESET_ADD_TEXTURE, TOOL_TILESET_REMOVE_TEXTURE, TOOL_TILESET_CREATE_SCENE, @@ -111,7 +111,7 @@ class TileSetEditor : public HSplitContainer { ItemList *texture_list; int option; - ToolButton *tileset_toolbar_buttons[TOOL_TILESET_MAX]; + Button *tileset_toolbar_buttons[TOOL_TILESET_MAX]; MenuButton *tileset_toolbar_tools; Map<RID, Ref<Texture2D>> texture_map; @@ -146,7 +146,7 @@ class TileSetEditor : public HSplitContainer { Button *tool_editmode[EDITMODE_MAX]; HSeparator *separator_editmode; HBoxContainer *toolbar; - ToolButton *tools[TOOL_MAX]; + Button *tools[TOOL_MAX]; VSeparator *separator_shape_toggle; VSeparator *separator_bitmask; VSeparator *separator_delete; @@ -200,6 +200,7 @@ private: void _on_workspace_overlay_draw(); void _on_workspace_draw(); void _on_workspace_process(); + void _on_scroll_container_input(const Ref<InputEvent> &p_event); void _on_workspace_input(const Ref<InputEvent> &p_ie); void _on_tool_clicked(int p_tool); void _on_priority_changed(float val); diff --git a/editor/plugins/version_control_editor_plugin.cpp b/editor/plugins/version_control_editor_plugin.cpp index a1436e123d..cfbe54ef61 100644 --- a/editor/plugins/version_control_editor_plugin.cpp +++ b/editor/plugins/version_control_editor_plugin.cpp @@ -300,7 +300,7 @@ void VersionControlEditorPlugin::register_editor() { TabContainer *dock_vbc = (TabContainer *)version_commit_dock->get_parent_control(); dock_vbc->set_tab_title(version_commit_dock->get_index(), TTR("Commit")); - ToolButton *vc = EditorNode::get_singleton()->add_bottom_panel_item(TTR("Version Control"), version_control_dock); + Button *vc = EditorNode::get_singleton()->add_bottom_panel_item(TTR("Version Control"), version_control_dock); set_version_control_tool_button(vc); } } diff --git a/editor/plugins/version_control_editor_plugin.h b/editor/plugins/version_control_editor_plugin.h index 664e38d65f..248a1435fd 100644 --- a/editor/plugins/version_control_editor_plugin.h +++ b/editor/plugins/version_control_editor_plugin.h @@ -90,7 +90,7 @@ private: Label *commit_status; PanelContainer *version_control_dock; - ToolButton *version_control_dock_button; + Button *version_control_dock_button; VBoxContainer *diff_vbc; HBoxContainer *diff_hbc; Button *diff_refresh_button; @@ -121,7 +121,7 @@ public: static VersionControlEditorPlugin *get_singleton(); void popup_vcs_set_up_dialog(const Control *p_gui_base); - void set_version_control_tool_button(ToolButton *p_button) { version_control_dock_button = p_button; } + void set_version_control_tool_button(Button *p_button) { version_control_dock_button = p_button; } PopupMenu *get_version_control_actions_panel() const { return version_control_actions; } VBoxContainer *get_version_commit_dock() const { return version_commit_dock; } diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 92bdba93e7..89ab747cde 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -2341,13 +2341,15 @@ VisualShaderEditor::VisualShaderEditor() { graph->get_zoom_hbox()->add_child(edit_type); graph->get_zoom_hbox()->move_child(edit_type, 0); - add_node = memnew(ToolButton); + add_node = memnew(Button); + add_node->set_flat(true); graph->get_zoom_hbox()->add_child(add_node); add_node->set_text(TTR("Add Node...")); graph->get_zoom_hbox()->move_child(add_node, 0); add_node->connect("pressed", callable_mp(this, &VisualShaderEditor::_show_members_dialog), varray(false)); - preview_shader = memnew(ToolButton); + preview_shader = memnew(Button); + preview_shader->set_flat(true); preview_shader->set_toggle_mode(true); preview_shader->set_tooltip(TTR("Show resulted shader code.")); graph->get_zoom_hbox()->add_child(preview_shader); @@ -2750,8 +2752,10 @@ VisualShaderEditor::VisualShaderEditor() { texture_node_option_idx = add_options.size(); add_options.push_back(AddOption("Texture2D", "Textures", "Functions", "VisualShaderNodeTexture", TTR("Perform the texture lookup."), -1, -1)); add_options.push_back(AddOption("CubeMapUniform", "Textures", "Variables", "VisualShaderNodeCubemapUniform", TTR("Cubic texture uniform lookup."), -1, -1)); + add_options.push_back(AddOption("Texture2DArray", "Textures", "Functions", "VisualShaderNodeTexture2DArray", TTR("Perform the 2D-array texture lookup."), -1, -1, -1, -1, -1)); add_options.push_back(AddOption("TextureUniform", "Textures", "Variables", "VisualShaderNodeTextureUniform", TTR("2D texture uniform lookup."), -1, -1)); add_options.push_back(AddOption("TextureUniformTriplanar", "Textures", "Variables", "VisualShaderNodeTextureUniformTriplanar", TTR("2D texture uniform lookup with triplanar."), -1, -1, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("Texture2DArrayUniform", "Textures", "Variables", "VisualShaderNodeTexture2DArrayUniform", TTR("2D array of textures uniform lookup."), -1, -1, -1, -1, -1)); // TRANSFORM diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h index d2f10d9407..b7c0fb8e45 100644 --- a/editor/plugins/visual_shader_editor_plugin.h +++ b/editor/plugins/visual_shader_editor_plugin.h @@ -60,8 +60,8 @@ class VisualShaderEditor : public VBoxContainer { Ref<VisualShader> visual_shader; HSplitContainer *main_box; GraphEdit *graph; - ToolButton *add_node; - ToolButton *preview_shader; + Button *add_node; + Button *preview_shader; OptionButton *edit_type; |