summaryrefslogtreecommitdiff
path: root/editor/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'editor/plugins')
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp10
-rw-r--r--editor/plugins/animation_player_editor_plugin.h1
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp19
-rw-r--r--editor/plugins/asset_library_editor_plugin.h15
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp290
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h12
-rw-r--r--editor/plugins/curve_editor_plugin.cpp3
-rw-r--r--editor/plugins/script_editor_plugin.cpp41
-rw-r--r--editor/plugins/script_editor_plugin.h2
-rw-r--r--editor/plugins/script_text_editor.cpp75
-rw-r--r--editor/plugins/script_text_editor.h1
-rw-r--r--editor/plugins/shader_editor_plugin.cpp8
-rw-r--r--editor/plugins/spatial_editor_plugin.cpp70
-rw-r--r--editor/plugins/spatial_editor_plugin.h2
-rw-r--r--editor/plugins/sprite_editor_plugin.cpp77
-rw-r--r--editor/plugins/sprite_editor_plugin.h3
-rw-r--r--editor/plugins/style_box_editor_plugin.cpp13
-rw-r--r--editor/plugins/style_box_editor_plugin.h3
-rw-r--r--editor/plugins/text_editor.cpp2
-rw-r--r--editor/plugins/texture_region_editor_plugin.cpp4
-rw-r--r--editor/plugins/tile_set_editor_plugin.cpp4
-rw-r--r--editor/plugins/version_control_editor_plugin.cpp6
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp131
-rw-r--r--editor/plugins/visual_shader_editor_plugin.h9
24 files changed, 563 insertions, 238 deletions
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index 2d00324c84..80353bab01 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -304,6 +304,7 @@ void AnimationPlayerEditor::_animation_selected(int p_which) {
AnimationPlayerEditor::singleton->get_track_editor()->update_keying();
EditorNode::get_singleton()->update_keying();
+ _animation_key_editor_seek(timeline_position, false);
}
void AnimationPlayerEditor::_animation_new() {
@@ -483,6 +484,8 @@ double AnimationPlayerEditor::_get_editor_step() const {
if (track_editor->is_snap_enabled()) {
const String current = player->get_assigned_animation();
const Ref<Animation> anim = player->get_animation(current);
+ ERR_FAIL_COND_V(!anim.is_valid(), 0.0);
+
// Use more precise snapping when holding Shift
return Input::get_singleton()->is_key_pressed(KEY_SHIFT) ? anim->get_step() * 0.25 : anim->get_step();
}
@@ -1072,14 +1075,20 @@ void AnimationPlayerEditor::_animation_key_editor_anim_len_changed(float p_len)
void AnimationPlayerEditor::_animation_key_editor_seek(float p_pos, bool p_drag) {
+ timeline_position = p_pos;
+
if (!is_visible_in_tree())
return;
+
if (!player)
return;
if (player->is_playing())
return;
+ if (!player->has_animation(player->get_assigned_animation()))
+ return;
+
Ref<Animation> anim = player->get_animation(player->get_assigned_animation());
updating = true;
@@ -1753,6 +1762,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor, AnimationPlay
renaming = false;
last_active = false;
+ timeline_position = 0;
set_process_unhandled_key_input(true);
diff --git a/editor/plugins/animation_player_editor_plugin.h b/editor/plugins/animation_player_editor_plugin.h
index eed7344395..663ffd57f3 100644
--- a/editor/plugins/animation_player_editor_plugin.h
+++ b/editor/plugins/animation_player_editor_plugin.h
@@ -107,6 +107,7 @@ class AnimationPlayerEditor : public VBoxContainer {
UndoRedo *undo_redo;
Ref<Texture> autoplay_icon;
bool last_active;
+ float timeline_position;
EditorFileDialog *file;
AcceptDialog *accept;
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index 3d161dc5b9..95767a96d8 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -32,8 +32,8 @@
#include "core/io/json.h"
#include "core/version.h"
-#include "editor_node.h"
-#include "editor_settings.h"
+#include "editor/editor_node.h"
+#include "editor/editor_settings.h"
void EditorAssetLibraryItem::configure(const String &p_title, int p_asset_id, const String &p_category, int p_category_id, const String &p_author, int p_author_id, const String &p_cost) {
@@ -1137,9 +1137,12 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const
initial_loading = false;
- // The loading text only needs to be displayed before the first page is loaded
+ // The loading text only needs to be displayed before the first page is loaded.
+ // Therefore, we don't need to show it again.
library_loading->hide();
+ library_error->hide();
+
if (asset_items) {
memdelete(asset_items);
}
@@ -1187,6 +1190,11 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const
asset_bottom_page = _make_pages(page, pages, page_len, total_items, result.size());
library_vb->add_child(asset_bottom_page);
+ if (result.empty()) {
+ library_error->set_text(vformat(TTR("No results for \"%s\"."), filter->get_text()));
+ library_error->show();
+ }
+
for (int i = 0; i < result.size(); i++) {
Dictionary r = result[i];
@@ -1453,6 +1461,11 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) {
library_loading->set_align(Label::ALIGN_CENTER);
library_vb->add_child(library_loading);
+ library_error = memnew(Label);
+ library_error->set_align(Label::ALIGN_CENTER);
+ library_error->hide();
+ library_vb->add_child(library_error);
+
asset_top_page = memnew(HBoxContainer);
library_vb->add_child(asset_top_page);
diff --git a/editor/plugins/asset_library_editor_plugin.h b/editor/plugins/asset_library_editor_plugin.h
index 7e934ac6cb..70ffbd9eed 100644
--- a/editor/plugins/asset_library_editor_plugin.h
+++ b/editor/plugins/asset_library_editor_plugin.h
@@ -31,24 +31,22 @@
#ifndef ASSET_LIBRARY_EDITOR_PLUGIN_H
#define ASSET_LIBRARY_EDITOR_PLUGIN_H
-#include "editor_plugin.h"
+#include "editor/editor_asset_installer.h"
+#include "editor/editor_plugin.h"
+#include "editor/editor_plugin_settings.h"
#include "scene/gui/box_container.h"
#include "scene/gui/check_box.h"
+#include "scene/gui/grid_container.h"
#include "scene/gui/line_edit.h"
#include "scene/gui/link_button.h"
#include "scene/gui/option_button.h"
#include "scene/gui/panel_container.h"
#include "scene/gui/progress_bar.h"
-#include "scene/gui/separator.h"
-#include "scene/gui/tab_container.h"
-
-#include "editor_plugin_settings.h"
-#include "scene/gui/grid_container.h"
#include "scene/gui/rich_text_label.h"
#include "scene/gui/scroll_container.h"
+#include "scene/gui/separator.h"
+#include "scene/gui/tab_container.h"
#include "scene/gui/texture_button.h"
-
-#include "editor_asset_installer.h"
#include "scene/main/http_request.h"
class EditorAssetLibraryItem : public PanelContainer {
@@ -186,6 +184,7 @@ class EditorAssetLibrary : public PanelContainer {
ScrollContainer *library_scroll;
VBoxContainer *library_vb;
Label *library_loading;
+ Label *library_error;
LineEdit *filter;
OptionButton *categories;
OptionButton *repository;
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index a11c35e5f2..2d9a713cad 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -67,12 +67,13 @@ class SnapDialog : public ConfirmationDialog {
SpinBox *grid_offset_y;
SpinBox *grid_step_x;
SpinBox *grid_step_y;
+ SpinBox *primary_grid_steps;
SpinBox *rotation_offset;
SpinBox *rotation_step;
public:
SnapDialog() {
- const int SPIN_BOX_GRID_RANGE = 256;
+ const int SPIN_BOX_GRID_RANGE = 16384;
const int SPIN_BOX_ROTATION_RANGE = 360;
Label *label;
VBoxContainer *container;
@@ -96,6 +97,8 @@ public:
grid_offset_x = memnew(SpinBox);
grid_offset_x->set_min(-SPIN_BOX_GRID_RANGE);
grid_offset_x->set_max(SPIN_BOX_GRID_RANGE);
+ grid_offset_x->set_allow_lesser(true);
+ grid_offset_x->set_allow_greater(true);
grid_offset_x->set_suffix("px");
grid_offset_x->set_h_size_flags(SIZE_EXPAND_FILL);
child_container->add_child(grid_offset_x);
@@ -103,6 +106,8 @@ public:
grid_offset_y = memnew(SpinBox);
grid_offset_y->set_min(-SPIN_BOX_GRID_RANGE);
grid_offset_y->set_max(SPIN_BOX_GRID_RANGE);
+ grid_offset_y->set_allow_lesser(true);
+ grid_offset_y->set_allow_greater(true);
grid_offset_y->set_suffix("px");
grid_offset_y->set_h_size_flags(SIZE_EXPAND_FILL);
child_container->add_child(grid_offset_y);
@@ -115,6 +120,7 @@ public:
grid_step_x = memnew(SpinBox);
grid_step_x->set_min(0.01);
grid_step_x->set_max(SPIN_BOX_GRID_RANGE);
+ grid_step_x->set_allow_greater(true);
grid_step_x->set_suffix("px");
grid_step_x->set_h_size_flags(SIZE_EXPAND_FILL);
child_container->add_child(grid_step_x);
@@ -122,12 +128,33 @@ public:
grid_step_y = memnew(SpinBox);
grid_step_y->set_min(0.01);
grid_step_y->set_max(SPIN_BOX_GRID_RANGE);
+ grid_step_y->set_allow_greater(true);
grid_step_y->set_suffix("px");
grid_step_y->set_h_size_flags(SIZE_EXPAND_FILL);
child_container->add_child(grid_step_y);
+ child_container = memnew(GridContainer);
+ child_container->set_columns(2);
+ container->add_child(child_container);
+
+ label = memnew(Label);
+ label->set_text(TTR("Primary Line Every:"));
+ label->set_h_size_flags(SIZE_EXPAND_FILL);
+ child_container->add_child(label);
+
+ primary_grid_steps = memnew(SpinBox);
+ primary_grid_steps->set_min(0);
+ primary_grid_steps->set_step(1);
+ primary_grid_steps->set_max(100);
+ primary_grid_steps->set_allow_greater(true);
+ primary_grid_steps->set_suffix(TTR("steps"));
+ primary_grid_steps->set_h_size_flags(SIZE_EXPAND_FILL);
+ child_container->add_child(primary_grid_steps);
+
container->add_child(memnew(HSeparator));
+ // We need to create another GridContainer with the same column count,
+ // so we can put an HSeparator above
child_container = memnew(GridContainer);
child_container->set_columns(2);
container->add_child(child_container);
@@ -157,18 +184,20 @@ public:
child_container->add_child(rotation_step);
}
- void set_fields(const Point2 p_grid_offset, const Point2 p_grid_step, const float p_rotation_offset, const float p_rotation_step) {
+ void set_fields(const Point2 p_grid_offset, const Point2 p_grid_step, const int p_primary_grid_steps, const float p_rotation_offset, const float p_rotation_step) {
grid_offset_x->set_value(p_grid_offset.x);
grid_offset_y->set_value(p_grid_offset.y);
grid_step_x->set_value(p_grid_step.x);
grid_step_y->set_value(p_grid_step.y);
+ primary_grid_steps->set_value(p_primary_grid_steps);
rotation_offset->set_value(p_rotation_offset * (180 / Math_PI));
rotation_step->set_value(p_rotation_step * (180 / Math_PI));
}
- void get_fields(Point2 &p_grid_offset, Point2 &p_grid_step, float &p_rotation_offset, float &p_rotation_step) {
+ void get_fields(Point2 &p_grid_offset, Point2 &p_grid_step, int &p_primary_grid_steps, float &p_rotation_offset, float &p_rotation_step) {
p_grid_offset = Point2(grid_offset_x->get_value(), grid_offset_y->get_value());
p_grid_step = Point2(grid_step_x->get_value(), grid_step_y->get_value());
+ p_primary_grid_steps = int(primary_grid_steps->get_value());
p_rotation_offset = rotation_offset->get_value() / (180 / Math_PI);
p_rotation_step = rotation_step->get_value() / (180 / Math_PI);
}
@@ -278,7 +307,7 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, unsig
snap_target[0] = SNAP_TARGET_NONE;
snap_target[1] = SNAP_TARGET_NONE;
- bool is_snap_active = snap_active ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL);
+ bool is_snap_active = smart_snap_active ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL);
// Smart snap using the canvas position
Vector2 output = p_target;
@@ -378,7 +407,7 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, unsig
}
}
- if (((is_snap_active && snap_grid && (p_modes & SNAP_GRID)) || (p_forced_modes & SNAP_GRID)) && fmod(rotation, (real_t)360.0) == 0.0) {
+ if (((grid_snap_active && (p_modes & SNAP_GRID)) || (p_forced_modes & SNAP_GRID)) && fmod(rotation, (real_t)360.0) == 0.0) {
// Grid
Point2 offset = grid_offset;
if (snap_relative) {
@@ -406,7 +435,7 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, unsig
}
float CanvasItemEditor::snap_angle(float p_target, float p_start) const {
- return (((snap_active || snap_rotation) ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL)) && snap_rotation_step != 0) ? Math::stepify(p_target - snap_rotation_offset, snap_rotation_step) + snap_rotation_offset : p_target;
+ return (((smart_snap_active || snap_rotation) ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL)) && snap_rotation_step != 0) ? Math::stepify(p_target - snap_rotation_offset, snap_rotation_step) + snap_rotation_offset : p_target;
}
void CanvasItemEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) {
@@ -421,11 +450,11 @@ void CanvasItemEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) {
}
if (k->is_pressed() && !k->get_control() && !k->is_echo()) {
- if ((snap_grid || show_grid) && multiply_grid_step_shortcut.is_valid() && multiply_grid_step_shortcut->is_shortcut(p_ev)) {
+ if ((grid_snap_active || show_grid) && multiply_grid_step_shortcut.is_valid() && multiply_grid_step_shortcut->is_shortcut(p_ev)) {
// Multiply the grid size
grid_step_multiplier = MIN(grid_step_multiplier + 1, 12);
viewport->update();
- } else if ((snap_grid || show_grid) && divide_grid_step_shortcut.is_valid() && divide_grid_step_shortcut->is_shortcut(p_ev)) {
+ } else if ((grid_snap_active || show_grid) && divide_grid_step_shortcut.is_valid() && divide_grid_step_shortcut->is_shortcut(p_ev)) {
// Divide the grid size
Point2 new_grid_step = grid_step * Math::pow(2.0, grid_step_multiplier - 1);
if (new_grid_step.x >= 1.0 && new_grid_step.y >= 1.0)
@@ -892,7 +921,7 @@ void CanvasItemEditor::_commit_canvas_item_state(List<CanvasItem *> p_canvas_ite
}
void CanvasItemEditor::_snap_changed() {
- ((SnapDialog *)snap_dialog)->get_fields(grid_offset, grid_step, snap_rotation_offset, snap_rotation_step);
+ ((SnapDialog *)snap_dialog)->get_fields(grid_offset, grid_step, primary_grid_steps, snap_rotation_offset, snap_rotation_step);
grid_step_multiplier = 0;
viewport->update();
}
@@ -1191,7 +1220,7 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo
//Pan the viewport
panning = true;
}
- } else if (panning) {
+ } else {
if (!k->is_pressed()) {
// Stop panning the viewport (for any mouse button press)
panning = false;
@@ -1785,7 +1814,7 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) {
if (_is_node_movable(canvas_item)) {
Transform2D xform = transform * canvas_item->get_global_transform_with_canvas();
- Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * Transform2D(canvas_item->_edit_get_rotation(), canvas_item->_edit_get_position())).orthonormalized();
+ Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * canvas_item->_edit_get_transform()).orthonormalized();
Transform2D simple_xform = viewport->get_transform() * unscaled_transform;
drag_type = DRAG_SCALE_BOTH;
@@ -1819,7 +1848,7 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) {
drag_to = transform.affine_inverse().xform(m->get_position());
Transform2D parent_xform = canvas_item->get_global_transform_with_canvas() * canvas_item->get_transform().affine_inverse();
- Transform2D unscaled_transform = (transform * parent_xform * Transform2D(canvas_item->_edit_get_rotation(), canvas_item->_edit_get_position())).orthonormalized();
+ Transform2D unscaled_transform = (transform * parent_xform * canvas_item->_edit_get_transform()).orthonormalized();
Transform2D simple_xform = (viewport->get_transform() * unscaled_transform).affine_inverse() * transform;
bool uniform = m->get_shift();
@@ -2268,7 +2297,7 @@ bool CanvasItemEditor::_gui_input_ruler_tool(const Ref<InputEvent> &p_event) {
Point2 previous_origin = ruler_tool_origin;
if (!ruler_tool_active)
- ruler_tool_origin = snap_point(viewport->get_local_mouse_position() / zoom + view_offset) * zoom;
+ ruler_tool_origin = snap_point(viewport->get_local_mouse_position() / zoom + view_offset);
if (b.is_valid() && b->get_button_index() == BUTTON_LEFT) {
if (b->is_pressed()) {
@@ -2281,9 +2310,7 @@ bool CanvasItemEditor::_gui_input_ruler_tool(const Ref<InputEvent> &p_event) {
return true;
}
- bool is_snap_active = snap_active ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL);
-
- if (m.is_valid() && (ruler_tool_active || (is_snap_active && previous_origin != ruler_tool_origin))) {
+ if (m.is_valid() && (ruler_tool_active || (grid_snap_active && previous_origin != ruler_tool_origin))) {
viewport->update();
return true;
@@ -2552,11 +2579,10 @@ void CanvasItemEditor::_draw_rulers() {
Color font_color = get_color("font_color", "Editor");
font_color.a = 0.8;
Ref<Font> font = get_font("rulers", "EditorFonts");
- bool is_snap_active = snap_active ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL);
// The rule transform
Transform2D ruler_transform = Transform2D();
- if (show_grid || (is_snap_active && snap_grid)) {
+ if (show_grid || grid_snap_active) {
List<CanvasItem *> selection = _get_edited_canvas_items();
if (snap_relative && selection.size() > 0) {
ruler_transform.translate(_get_encompassing_rect_from_list(selection).position);
@@ -2636,41 +2662,72 @@ void CanvasItemEditor::_draw_rulers() {
}
void CanvasItemEditor::_draw_grid() {
- if (show_grid) {
- //Draw the grid
- Size2 s = viewport->get_size();
- int last_cell = 0;
- Transform2D xform = transform.affine_inverse();
+ if (show_grid || grid_snap_active) {
+ // Draw the grid
Vector2 real_grid_offset;
- List<CanvasItem *> selection = _get_edited_canvas_items();
+ const List<CanvasItem *> selection = _get_edited_canvas_items();
+
if (snap_relative && selection.size() > 0) {
- Vector2 topleft = _get_encompassing_rect_from_list(selection).position;
+ const Vector2 topleft = _get_encompassing_rect_from_list(selection).position;
real_grid_offset.x = fmod(topleft.x, grid_step.x * (real_t)Math::pow(2.0, grid_step_multiplier));
real_grid_offset.y = fmod(topleft.y, grid_step.y * (real_t)Math::pow(2.0, grid_step_multiplier));
} else {
real_grid_offset = grid_offset;
}
- const Color grid_color = EditorSettings::get_singleton()->get("editors/2d/grid_color");
+ // Draw a "primary" line every several lines to make measurements easier.
+ // The step is configurable in the Configure Snap dialog.
+ const Color secondary_grid_color = EditorSettings::get_singleton()->get("editors/2d/grid_color");
+ const Color primary_grid_color =
+ Color(secondary_grid_color.r, secondary_grid_color.g, secondary_grid_color.b, secondary_grid_color.a * 2.5);
+
+ const Size2 viewport_size = viewport->get_size();
+ const Transform2D xform = transform.affine_inverse();
+ int last_cell = 0;
+
if (grid_step.x != 0) {
- for (int i = 0; i < s.width; i++) {
- int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(i, 0)).x - real_grid_offset.x) / (grid_step.x * Math::pow(2.0, grid_step_multiplier))));
- if (i == 0)
+ for (int i = 0; i < viewport_size.width; i++) {
+ const int cell =
+ Math::fast_ftoi(Math::floor((xform.xform(Vector2(i, 0)).x - real_grid_offset.x) / (grid_step.x * Math::pow(2.0, grid_step_multiplier))));
+
+ if (i == 0) {
last_cell = cell;
- if (last_cell != cell)
- viewport->draw_line(Point2(i, 0), Point2(i, s.height), grid_color, Math::round(EDSCALE));
+ }
+
+ if (last_cell != cell) {
+ Color grid_color;
+ if (primary_grid_steps == 0) {
+ grid_color = secondary_grid_color;
+ } else {
+ grid_color = cell % primary_grid_steps == 0 ? primary_grid_color : secondary_grid_color;
+ }
+
+ viewport->draw_line(Point2(i, 0), Point2(i, viewport_size.height), grid_color, Math::round(EDSCALE));
+ }
last_cell = cell;
}
}
if (grid_step.y != 0) {
- for (int i = 0; i < s.height; i++) {
- int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(0, i)).y - real_grid_offset.y) / (grid_step.y * Math::pow(2.0, grid_step_multiplier))));
- if (i == 0)
+ for (int i = 0; i < viewport_size.height; i++) {
+ const int cell =
+ Math::fast_ftoi(Math::floor((xform.xform(Vector2(0, i)).y - real_grid_offset.y) / (grid_step.y * Math::pow(2.0, grid_step_multiplier))));
+
+ if (i == 0) {
last_cell = cell;
- if (last_cell != cell)
- viewport->draw_line(Point2(0, i), Point2(s.width, i), grid_color, Math::round(EDSCALE));
+ }
+
+ if (last_cell != cell) {
+ Color grid_color;
+ if (primary_grid_steps == 0) {
+ grid_color = secondary_grid_color;
+ } else {
+ grid_color = cell % primary_grid_steps == 0 ? primary_grid_color : secondary_grid_color;
+ }
+
+ viewport->draw_line(Point2(0, i), Point2(viewport_size.width, i), grid_color, Math::round(EDSCALE));
+ }
last_cell = cell;
}
}
@@ -2682,19 +2739,17 @@ void CanvasItemEditor::_draw_ruler_tool() {
if (tool != TOOL_RULER)
return;
- bool is_snap_active = snap_active ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL);
-
if (ruler_tool_active) {
Color ruler_primary_color = get_color("accent_color", "Editor");
Color ruler_secondary_color = ruler_primary_color;
ruler_secondary_color.a = 0.5;
- Point2 begin = ruler_tool_origin - view_offset * zoom;
+ Point2 begin = (ruler_tool_origin - view_offset) * zoom;
Point2 end = snap_point(viewport->get_local_mouse_position() / zoom + view_offset) * zoom - view_offset * zoom;
Point2 corner = Point2(begin.x, end.y);
Vector2 length_vector = (begin - end).abs() / zoom;
- bool draw_secondary_lines = (begin.y != corner.y && end.x != corner.x);
+ bool draw_secondary_lines = !(Math::is_equal_approx(begin.y, corner.y) || Math::is_equal_approx(end.x, corner.x));
viewport->draw_line(begin, end, ruler_primary_color, Math::round(EDSCALE * 3), true);
if (draw_secondary_lines) {
@@ -2708,6 +2763,7 @@ void CanvasItemEditor::_draw_ruler_tool() {
font_secondary_color.a = 0.5;
float text_height = font->get_height();
const float text_width = 76;
+ const float angle_text_width = 54;
Point2 text_pos = (begin + end) / 2 - Vector2(text_width / 2, text_height / 2);
text_pos.x = CLAMP(text_pos.x, text_width / 2, viewport->get_rect().size.x - text_width * 1.5);
@@ -2715,17 +2771,71 @@ void CanvasItemEditor::_draw_ruler_tool() {
viewport->draw_string(font, text_pos, vformat("%.2f px", length_vector.length()), font_color);
if (draw_secondary_lines) {
+ const float horizontal_angle_rad = atan2(length_vector.y, length_vector.x);
+ const float vertical_angle_rad = Math_PI / 2.0 - horizontal_angle_rad;
+ const int horizontal_angle = round(180 * horizontal_angle_rad / Math_PI);
+ const int vertical_angle = round(180 * vertical_angle_rad / Math_PI);
Point2 text_pos2 = text_pos;
text_pos2.x = begin.x < text_pos.x ? MIN(text_pos.x - text_width, begin.x - text_width / 2) : MAX(text_pos.x + text_width, begin.x - text_width / 2);
viewport->draw_string(font, text_pos2, vformat("%.2f px", length_vector.y), font_secondary_color);
+ Point2 v_angle_text_pos = Point2();
+ v_angle_text_pos.x = CLAMP(begin.x - angle_text_width / 2, angle_text_width / 2, viewport->get_rect().size.x - angle_text_width);
+ v_angle_text_pos.y = begin.y < end.y ? MIN(text_pos2.y - 2 * text_height, begin.y - text_height * 0.5) : MAX(text_pos2.y + text_height * 3, begin.y + text_height * 1.5);
+ viewport->draw_string(font, v_angle_text_pos, vformat("%d deg", vertical_angle), font_secondary_color);
+
text_pos2 = text_pos;
text_pos2.y = end.y < text_pos.y ? MIN(text_pos.y - text_height * 2, end.y - text_height / 2) : MAX(text_pos.y + text_height * 2, end.y - text_height / 2);
viewport->draw_string(font, text_pos2, vformat("%.2f px", length_vector.x), font_secondary_color);
+
+ Point2 h_angle_text_pos = Point2();
+ h_angle_text_pos.x = CLAMP(end.x - angle_text_width / 2, angle_text_width / 2, viewport->get_rect().size.x - angle_text_width);
+ if (begin.y < end.y) {
+ h_angle_text_pos.y = end.y + text_height * 1.5;
+ if (ABS(text_pos2.x - h_angle_text_pos.x) < text_width) {
+ int height_multiplier = 1.5 + (int)grid_snap_active;
+ h_angle_text_pos.y = MAX(text_pos.y + height_multiplier * text_height, MAX(end.y + text_height * 1.5, text_pos2.y + height_multiplier * text_height));
+ }
+ } else {
+ h_angle_text_pos.y = end.y - text_height * 0.5;
+ if (ABS(text_pos2.x - h_angle_text_pos.x) < text_width) {
+ int height_multiplier = 1 + (int)grid_snap_active;
+ h_angle_text_pos.y = MIN(text_pos.y - height_multiplier * text_height, MIN(end.y - text_height * 0.5, text_pos2.y - height_multiplier * text_height));
+ }
+ }
+ viewport->draw_string(font, h_angle_text_pos, vformat("%d deg", horizontal_angle), font_secondary_color);
+
+ // Angle arcs
+ int arc_point_count = 8;
+ float arc_radius_max_length_percent = 0.1;
+ float ruler_length = length_vector.length() * zoom;
+ float arc_max_radius = 50.0;
+ float arc_line_width = 2.0;
+
+ const Vector2 end_to_begin = (end - begin);
+
+ float arc_1_start_angle =
+ end_to_begin.x < 0 ?
+ (end_to_begin.y < 0 ? 3.0 * Math_PI / 2.0 - vertical_angle_rad : Math_PI / 2.0) :
+ (end_to_begin.y < 0 ? 3.0 * Math_PI / 2.0 : Math_PI / 2.0 - vertical_angle_rad);
+ float arc_1_end_angle = arc_1_start_angle + vertical_angle_rad;
+ // Constrain arc to triangle height & max size
+ float arc_1_radius = MIN(MIN(arc_radius_max_length_percent * ruler_length, ABS(end_to_begin.y)), arc_max_radius);
+
+ float arc_2_start_angle =
+ end_to_begin.x < 0 ?
+ (end_to_begin.y < 0 ? 0.0 : -horizontal_angle_rad) :
+ (end_to_begin.y < 0 ? Math_PI - horizontal_angle_rad : Math_PI);
+ float arc_2_end_angle = arc_2_start_angle + horizontal_angle_rad;
+ // Constrain arc to triangle width & max size
+ float arc_2_radius = MIN(MIN(arc_radius_max_length_percent * ruler_length, ABS(end_to_begin.x)), arc_max_radius);
+
+ viewport->draw_arc(begin, arc_1_radius, arc_1_start_angle, arc_1_end_angle, arc_point_count, ruler_primary_color, Math::round(EDSCALE * arc_line_width));
+ viewport->draw_arc(end, arc_2_radius, arc_2_start_angle, arc_2_end_angle, arc_point_count, ruler_primary_color, Math::round(EDSCALE * arc_line_width));
}
- if (is_snap_active) {
+ if (grid_snap_active) {
text_pos = (begin + end) / 2 + Vector2(-text_width / 2, text_height / 2);
text_pos.x = CLAMP(text_pos.x, text_width / 2, viewport->get_rect().size.x - text_width * 1.5);
@@ -2736,20 +2846,20 @@ void CanvasItemEditor::_draw_ruler_tool() {
Point2 text_pos2 = text_pos;
text_pos2.x = begin.x < text_pos.x ? MIN(text_pos.x - text_width, begin.x - text_width / 2) : MAX(text_pos.x + text_width, begin.x - text_width / 2);
- viewport->draw_string(font, text_pos2, vformat("%d units", (int)(length_vector.y / grid_step.y)), font_secondary_color);
+ viewport->draw_string(font, text_pos2, vformat("%d units", roundf(length_vector.y / grid_step.y)), font_secondary_color);
text_pos2 = text_pos;
text_pos2.y = end.y < text_pos.y ? MIN(text_pos.y - text_height * 2, end.y + text_height / 2) : MAX(text_pos.y + text_height * 2, end.y + text_height / 2);
- viewport->draw_string(font, text_pos2, vformat("%d units", (int)(length_vector.x / grid_step.x)), font_secondary_color);
+ viewport->draw_string(font, text_pos2, vformat("%d units", roundf(length_vector.x / grid_step.x)), font_secondary_color);
} else {
viewport->draw_string(font, text_pos, vformat("%d units", roundf((length_vector / grid_step).length())), font_color);
}
}
} else {
- if (is_snap_active) {
+ if (grid_snap_active) {
Ref<Texture> position_icon = get_icon("EditorPosition", "EditorIcons");
- viewport->draw_texture(get_icon("EditorPosition", "EditorIcons"), ruler_tool_origin - view_offset * zoom - position_icon->get_size() / 2);
+ viewport->draw_texture(get_icon("EditorPosition", "EditorIcons"), (ruler_tool_origin - view_offset) * zoom - position_icon->get_size() / 2);
}
}
}
@@ -3018,7 +3128,7 @@ void CanvasItemEditor::_draw_selection() {
}
} else {
- Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * Transform2D(canvas_item->_edit_get_rotation(), canvas_item->_edit_get_position())).orthonormalized();
+ Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * canvas_item->_edit_get_transform()).orthonormalized();
Transform2D simple_xform = viewport->get_transform() * unscaled_transform;
viewport->draw_set_transform_matrix(simple_xform);
viewport->draw_texture(position_icon, -(position_icon->get_size() / 2));
@@ -3030,7 +3140,7 @@ void CanvasItemEditor::_draw_selection() {
if (canvas_item->_edit_use_pivot()) {
// Draw the node's pivot
- Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * Transform2D(canvas_item->_edit_get_rotation(), canvas_item->_edit_get_position() + canvas_item->_edit_get_pivot())).orthonormalized();
+ Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * canvas_item->_edit_get_transform()).orthonormalized();
Transform2D simple_xform = viewport->get_transform() * unscaled_transform;
viewport->draw_set_transform_matrix(simple_xform);
@@ -3075,7 +3185,7 @@ void CanvasItemEditor::_draw_selection() {
bool is_alt = Input::get_singleton()->is_key_pressed(KEY_ALT);
if ((is_alt && is_ctrl) || tool == TOOL_SCALE || drag_type == DRAG_SCALE_X || drag_type == DRAG_SCALE_Y) {
if (_is_node_movable(canvas_item)) {
- Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * Transform2D(canvas_item->_edit_get_rotation(), canvas_item->_edit_get_position())).orthonormalized();
+ Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * canvas_item->_edit_get_transform()).orthonormalized();
Transform2D simple_xform = viewport->get_transform() * unscaled_transform;
Size2 scale_factor = Size2(SCALE_HANDLE_DISTANCE, SCALE_HANDLE_DISTANCE);
@@ -3294,7 +3404,7 @@ void CanvasItemEditor::_draw_invisible_nodes_positions(Node *p_node, const Trans
// Draw the node's position
Ref<Texture> position_icon = get_icon("EditorPositionUnselected", "EditorIcons");
- Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * Transform2D(canvas_item->_edit_get_rotation(), canvas_item->_edit_get_position())).orthonormalized();
+ Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * canvas_item->_edit_get_transform()).orthonormalized();
Transform2D simple_xform = viewport->get_transform() * unscaled_transform;
viewport->draw_set_transform_matrix(simple_xform);
viewport->draw_texture(position_icon, -position_icon->get_size() / 2, Color(1.0, 1.0, 1.0, 0.5));
@@ -3666,7 +3776,8 @@ void CanvasItemEditor::_notification(int p_what) {
move_button->set_icon(get_icon("ToolMove", "EditorIcons"));
scale_button->set_icon(get_icon("ToolScale", "EditorIcons"));
rotate_button->set_icon(get_icon("ToolRotate", "EditorIcons"));
- snap_button->set_icon(get_icon("Snap", "EditorIcons"));
+ smart_snap_button->set_icon(get_icon("Snap", "EditorIcons"));
+ grid_snap_button->set_icon(get_icon("SnapGrid", "EditorIcons"));
snap_config_menu->set_icon(get_icon("GuiTabMenu", "EditorIcons"));
skeleton_menu->set_icon(get_icon("Bone", "EditorIcons"));
pan_button->set_icon(get_icon("ToolPan", "EditorIcons"));
@@ -4070,8 +4181,13 @@ void CanvasItemEditor::_button_zoom_plus() {
_zoom_on_position(zoom * Math_SQRT2, viewport_scrollable->get_size() / 2.0);
}
-void CanvasItemEditor::_button_toggle_snap(bool p_status) {
- snap_active = p_status;
+void CanvasItemEditor::_button_toggle_smart_snap(bool p_status) {
+ smart_snap_active = p_status;
+ viewport->update();
+}
+
+void CanvasItemEditor::_button_toggle_grid_snap(bool p_status) {
+ grid_snap_active = p_status;
viewport->update();
}
@@ -4230,11 +4346,6 @@ void CanvasItemEditor::_popup_callback(int p_op) {
int idx = smartsnap_config_popup->get_item_index(SNAP_USE_GUIDES);
smartsnap_config_popup->set_item_checked(idx, snap_guides);
} break;
- case SNAP_USE_GRID: {
- snap_grid = !snap_grid;
- int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_GRID);
- snap_config_menu->get_popup()->set_item_checked(idx, snap_grid);
- } break;
case SNAP_USE_ROTATION: {
snap_rotation = !snap_rotation;
int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_ROTATION);
@@ -4252,8 +4363,8 @@ void CanvasItemEditor::_popup_callback(int p_op) {
snap_config_menu->get_popup()->set_item_checked(idx, snap_pixel);
} break;
case SNAP_CONFIGURE: {
- ((SnapDialog *)snap_dialog)->set_fields(grid_offset, grid_step, snap_rotation_offset, snap_rotation_step);
- snap_dialog->popup_centered(Size2(220, 160));
+ ((SnapDialog *)snap_dialog)->set_fields(grid_offset, grid_step, primary_grid_steps, snap_rotation_offset, snap_rotation_step);
+ snap_dialog->popup_centered(Size2(220, 160) * EDSCALE);
} break;
case SKELETON_SHOW_BONES: {
skeleton_show_bones = !skeleton_show_bones;
@@ -4766,7 +4877,8 @@ void CanvasItemEditor::_bind_methods() {
ClassDB::bind_method("_button_zoom_minus", &CanvasItemEditor::_button_zoom_minus);
ClassDB::bind_method("_button_zoom_reset", &CanvasItemEditor::_button_zoom_reset);
ClassDB::bind_method("_button_zoom_plus", &CanvasItemEditor::_button_zoom_plus);
- ClassDB::bind_method("_button_toggle_snap", &CanvasItemEditor::_button_toggle_snap);
+ ClassDB::bind_method("_button_toggle_smart_snap", &CanvasItemEditor::_button_toggle_smart_snap);
+ ClassDB::bind_method("_button_toggle_grid_snap", &CanvasItemEditor::_button_toggle_grid_snap);
ClassDB::bind_method("_button_toggle_anchor_mode", &CanvasItemEditor::_button_toggle_anchor_mode);
ClassDB::bind_method("_update_scroll", &CanvasItemEditor::_update_scroll);
ClassDB::bind_method("_update_scrollbars", &CanvasItemEditor::_update_scrollbars);
@@ -4799,15 +4911,16 @@ Dictionary CanvasItemEditor::get_state() const {
state["ofs"] = view_offset;
state["grid_offset"] = grid_offset;
state["grid_step"] = grid_step;
+ state["primary_grid_steps"] = primary_grid_steps;
state["snap_rotation_offset"] = snap_rotation_offset;
state["snap_rotation_step"] = snap_rotation_step;
- state["snap_active"] = snap_active;
+ state["smart_snap_active"] = smart_snap_active;
+ state["grid_snap_active"] = grid_snap_active;
state["snap_node_parent"] = snap_node_parent;
state["snap_node_anchors"] = snap_node_anchors;
state["snap_node_sides"] = snap_node_sides;
state["snap_node_center"] = snap_node_center;
state["snap_other_nodes"] = snap_other_nodes;
- state["snap_grid"] = snap_grid;
state["snap_guides"] = snap_guides;
state["show_grid"] = show_grid;
state["show_origin"] = show_origin;
@@ -4847,6 +4960,10 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) {
grid_step = state["grid_step"];
}
+ if (state.has("primary_grid_steps")) {
+ primary_grid_steps = state["primary_grid_steps"];
+ }
+
if (state.has("snap_rotation_step")) {
snap_rotation_step = state["snap_rotation_step"];
}
@@ -4855,9 +4972,14 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) {
snap_rotation_offset = state["snap_rotation_offset"];
}
- if (state.has("snap_active")) {
- snap_active = state["snap_active"];
- snap_button->set_pressed(snap_active);
+ if (state.has("smart_snap_active")) {
+ smart_snap_active = state["smart_snap_active"];
+ smart_snap_button->set_pressed(smart_snap_active);
+ }
+
+ if (state.has("grid_snap_active")) {
+ grid_snap_active = state["grid_snap_active"];
+ grid_snap_button->set_pressed(grid_snap_active);
}
if (state.has("snap_node_parent")) {
@@ -4896,12 +5018,6 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) {
smartsnap_config_popup->set_item_checked(idx, snap_guides);
}
- if (state.has("snap_grid")) {
- snap_grid = state["snap_grid"];
- int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_GRID);
- snap_config_menu->get_popup()->set_item_checked(idx, snap_grid);
- }
-
if (state.has("show_grid")) {
show_grid = state["show_grid"];
int idx = view_menu->get_popup()->get_item_index(SHOW_GRID);
@@ -5037,16 +5153,17 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
previous_update_view_offset = view_offset; // Moves the view a little bit to the left so that (0,0) is visible. The values a relative to a 16/10 screen
grid_offset = Point2();
grid_step = Point2(10, 10);
+ primary_grid_steps = 8; // A power-of-two value works better as a default
grid_step_multiplier = 0;
snap_rotation_offset = 0;
snap_rotation_step = 15 / (180 / Math_PI);
- snap_active = false;
+ smart_snap_active = false;
+ grid_snap_active = false;
snap_node_parent = true;
snap_node_anchors = true;
snap_node_sides = true;
snap_node_center = true;
snap_other_nodes = true;
- snap_grid = true;
snap_guides = true;
snap_rotation = false;
snap_relative = false;
@@ -5135,6 +5252,8 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
warning_child_of_container = memnew(Label);
warning_child_of_container->hide();
warning_child_of_container->set_text(TTR("Warning: Children of a container get their position and size determined only by their parent."));
+ warning_child_of_container->add_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_color("warning_color", "Editor"));
+ warning_child_of_container->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("main", "EditorFonts"));
add_control_to_info_overlay(warning_child_of_container);
h_scroll = memnew(HScrollBar);
@@ -5236,12 +5355,19 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
hb->add_child(memnew(VSeparator));
- snap_button = memnew(ToolButton);
- hb->add_child(snap_button);
- snap_button->set_toggle_mode(true);
- snap_button->connect("toggled", this, "_button_toggle_snap");
- snap_button->set_tooltip(TTR("Toggle snapping."));
- snap_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/use_snap", TTR("Use Snap"), KEY_MASK_SHIFT | KEY_S));
+ smart_snap_button = memnew(ToolButton);
+ hb->add_child(smart_snap_button);
+ smart_snap_button->set_toggle_mode(true);
+ smart_snap_button->connect("toggled", this, "_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);
+ hb->add_child(grid_snap_button);
+ grid_snap_button->set_toggle_mode(true);
+ grid_snap_button->connect("toggled", this, "_button_toggle_grid_snap");
+ grid_snap_button->set_tooltip(TTR("Toggle grid snapping."));
+ grid_snap_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/use_grid_snap", TTR("Use Grid Snap"), KEY_MASK_SHIFT | KEY_G));
snap_config_menu = memnew(MenuButton);
hb->add_child(snap_config_menu);
@@ -5252,7 +5378,6 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
PopupMenu *p = snap_config_menu->get_popup();
p->connect("id_pressed", this, "_popup_callback");
p->set_hide_on_checkable_item_selection(false);
- p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_grid", TTR("Snap to Grid")), SNAP_USE_GRID);
p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_rotation_snap", TTR("Use Rotation Snap")), SNAP_USE_ROTATION);
p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_relative", TTR("Snap Relative")), SNAP_RELATIVE);
p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_pixel_snap", TTR("Use Pixel Snap")), SNAP_USE_PIXEL);
@@ -5324,9 +5449,9 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
p = view_menu->get_popup();
p->set_hide_on_checkable_item_selection(false);
- p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_grid", TTR("Show Grid"), KEY_G), SHOW_GRID);
+ p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_grid", TTR("Always Show Grid"), KEY_G), SHOW_GRID);
p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_helpers", TTR("Show Helpers"), KEY_H), SHOW_HELPERS);
- p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_rulers", TTR("Show Rulers"), KEY_MASK_CMD | KEY_R), SHOW_RULERS);
+ p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_rulers", TTR("Show Rulers")), SHOW_RULERS);
p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_guides", TTR("Show Guides"), KEY_Y), SHOW_GUIDES);
p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_origin", TTR("Show Origin")), SHOW_ORIGIN);
p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_viewport", TTR("Show Viewport")), SHOW_VIEWPORT);
@@ -5528,6 +5653,7 @@ void CanvasItemEditorViewport::_create_preview(const Vector<String> &files) cons
for (int i = 0; i < files.size(); i++) {
String path = files[i];
RES res = ResourceLoader::load(path);
+ ERR_FAIL_COND(res.is_null());
Ref<Texture> texture = Ref<Texture>(Object::cast_to<Texture>(*res));
Ref<PackedScene> scene = Ref<PackedScene>(Object::cast_to<PackedScene>(*res));
if (texture != NULL || scene != NULL) {
diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
index 6cce1ca10e..35efc14b5e 100644
--- a/editor/plugins/canvas_item_editor_plugin.h
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -255,17 +255,19 @@ private:
Point2 grid_offset;
Point2 grid_step;
+ int primary_grid_steps;
int grid_step_multiplier;
float snap_rotation_step;
float snap_rotation_offset;
- bool snap_active;
+ bool smart_snap_active;
+ bool grid_snap_active;
+
bool snap_node_parent;
bool snap_node_anchors;
bool snap_node_sides;
bool snap_node_center;
bool snap_other_nodes;
- bool snap_grid;
bool snap_guides;
bool snap_rotation;
bool snap_relative;
@@ -347,7 +349,8 @@ private:
ToolButton *ruler_button;
- ToolButton *snap_button;
+ ToolButton *smart_snap_button;
+ ToolButton *grid_snap_button;
MenuButton *snap_config_menu;
PopupMenu *smartsnap_config_popup;
@@ -529,7 +532,8 @@ private:
void _button_zoom_minus();
void _button_zoom_reset();
void _button_zoom_plus();
- void _button_toggle_snap(bool p_status);
+ void _button_toggle_smart_snap(bool p_status);
+ void _button_toggle_grid_snap(bool p_status);
void _button_tool_select(int p_index);
HSplitContainer *palette_split;
diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp
index 9160920c50..727d92ba05 100644
--- a/editor/plugins/curve_editor_plugin.cpp
+++ b/editor/plugins/curve_editor_plugin.cpp
@@ -736,6 +736,9 @@ void CurveEditor::_draw() {
if (_selected_point > 0 && _selected_point + 1 < curve.get_point_count()) {
text_color.a *= 0.4;
draw_string(font, Vector2(50, font_height), TTR("Hold Shift to edit tangents individually"), text_color);
+ } else if (curve.get_point_count() == 0) {
+ text_color.a *= 0.4;
+ draw_string(font, Vector2(50, font_height), TTR("Right click to add point"), text_color);
}
}
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 80b0f0738a..f7e997a269 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -43,6 +43,7 @@
#include "editor/plugins/shader_editor_plugin.h"
#include "editor/script_editor_debugger.h"
#include "scene/main/viewport.h"
+#include "scene/scene_string_names.h"
#include "script_text_editor.h"
#include "text_editor.h"
@@ -1325,6 +1326,9 @@ void ScriptEditor::_menu_option(int p_option) {
case HELP_SEARCH_FIND_NEXT: {
help->search_again();
} break;
+ case HELP_SEARCH_FIND_PREVIOUS: {
+ help->search_again(true);
+ } break;
case FILE_CLOSE: {
_close_current_tab();
} break;
@@ -1417,16 +1421,6 @@ void ScriptEditor::_notification(int p_what) {
members_overview->connect("item_selected", this, "_members_overview_selected");
help_overview->connect("item_selected", this, "_help_overview_selected");
script_split->connect("dragged", this, "_script_split_dragged");
- autosave_timer->connect("timeout", this, "_autosave_scripts");
- {
- float autosave_time = EditorSettings::get_singleton()->get("text_editor/files/autosave_interval_secs");
- if (autosave_time > 0) {
- autosave_timer->set_wait_time(autosave_time);
- autosave_timer->start();
- } else {
- autosave_timer->stop();
- }
- }
EditorSettings::get_singleton()->connect("settings_changed", this, "_editor_settings_changed");
FALLTHROUGH;
@@ -2332,13 +2326,7 @@ void ScriptEditor::_editor_settings_changed() {
_update_members_overview_visibility();
_update_help_overview_visibility();
- float autosave_time = EditorSettings::get_singleton()->get("text_editor/files/autosave_interval_secs");
- if (autosave_time > 0) {
- autosave_timer->set_wait_time(autosave_time);
- autosave_timer->start();
- } else {
- autosave_timer->stop();
- }
+ _update_autosave_timer();
if (current_theme == "") {
current_theme = EditorSettings::get_singleton()->get("text_editor/theme/color_theme");
@@ -2366,6 +2354,21 @@ void ScriptEditor::_autosave_scripts() {
save_all_scripts();
}
+void ScriptEditor::_update_autosave_timer() {
+
+ if (!autosave_timer->is_inside_tree()) {
+ return;
+ }
+
+ float autosave_time = EditorSettings::get_singleton()->get("text_editor/files/autosave_interval_secs");
+ if (autosave_time > 0) {
+ autosave_timer->set_wait_time(autosave_time);
+ autosave_timer->start();
+ } else {
+ autosave_timer->stop();
+ }
+}
+
void ScriptEditor::_tree_changed() {
if (waiting_update_names)
@@ -2827,6 +2830,7 @@ void ScriptEditor::_update_selected_editor_menu() {
script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find", TTR("Find..."), KEY_MASK_CMD | KEY_F), HELP_SEARCH_FIND);
script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_next", TTR("Find Next"), KEY_F3), HELP_SEARCH_FIND_NEXT);
+ script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_previous", TTR("Find Previous"), KEY_MASK_SHIFT | KEY_F3), HELP_SEARCH_FIND_PREVIOUS);
script_search_menu->get_popup()->add_separator();
script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_in_files", TTR("Find in Files"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F), SEARCH_IN_FILES);
script_search_menu->show();
@@ -3088,6 +3092,7 @@ void ScriptEditor::_bind_methods() {
ClassDB::bind_method("_show_debugger", &ScriptEditor::_show_debugger);
ClassDB::bind_method("_get_debug_tooltip", &ScriptEditor::_get_debug_tooltip);
ClassDB::bind_method("_autosave_scripts", &ScriptEditor::_autosave_scripts);
+ ClassDB::bind_method("_update_autosave_timer", &ScriptEditor::_update_autosave_timer);
ClassDB::bind_method("_editor_settings_changed", &ScriptEditor::_editor_settings_changed);
ClassDB::bind_method("_update_script_names", &ScriptEditor::_update_script_names);
ClassDB::bind_method("_update_script_connections", &ScriptEditor::_update_script_connections);
@@ -3424,6 +3429,8 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
autosave_timer = memnew(Timer);
autosave_timer->set_one_shot(false);
+ autosave_timer->connect(SceneStringNames::get_singleton()->tree_entered, this, "_update_autosave_timer");
+ autosave_timer->connect("timeout", this, "_autosave_scripts");
add_child(autosave_timer);
grab_focus_block = false;
diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h
index 0c876108a5..294294fc56 100644
--- a/editor/plugins/script_editor_plugin.h
+++ b/editor/plugins/script_editor_plugin.h
@@ -168,6 +168,7 @@ class ScriptEditor : public PanelContainer {
REQUEST_DOCS,
HELP_SEARCH_FIND,
HELP_SEARCH_FIND_NEXT,
+ HELP_SEARCH_FIND_PREVIOUS,
WINDOW_MOVE_UP,
WINDOW_MOVE_DOWN,
WINDOW_NEXT,
@@ -342,6 +343,7 @@ class ScriptEditor : public PanelContainer {
void _save_layout();
void _editor_settings_changed();
void _autosave_scripts();
+ void _update_autosave_timer();
void _update_members_overview_visibility();
void _update_members_overview();
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index 073e6f74e9..603a2365c1 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -224,6 +224,7 @@ void ScriptTextEditor::_load_theme_settings() {
Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color");
Color basetype_color = EDITOR_GET("text_editor/highlighting/base_type_color");
Color type_color = EDITOR_GET("text_editor/highlighting/engine_type_color");
+ Color usertype_color = EDITOR_GET("text_editor/highlighting/user_type_color");
Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color");
Color string_color = EDITOR_GET("text_editor/highlighting/string_color");
@@ -262,6 +263,7 @@ void ScriptTextEditor::_load_theme_settings() {
colors_cache.keyword_color = keyword_color;
colors_cache.basetype_color = basetype_color;
colors_cache.type_color = type_color;
+ colors_cache.usertype_color = usertype_color;
colors_cache.comment_color = comment_color;
colors_cache.string_color = string_color;
@@ -325,6 +327,29 @@ void ScriptTextEditor::_set_theme_for_script() {
}
_update_member_keywords();
+ //colorize user types
+ List<StringName> global_classes;
+ ScriptServer::get_global_class_list(&global_classes);
+
+ for (List<StringName>::Element *E = global_classes.front(); E; E = E->next()) {
+
+ text_edit->add_keyword_color(E->get(), colors_cache.usertype_color);
+ }
+
+ //colorize singleton autoloads (as types, just as engine singletons are)
+ List<PropertyInfo> props;
+ ProjectSettings::get_singleton()->get_property_list(&props);
+ for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
+ String s = E->get().name;
+ if (!s.begins_with("autoload/")) {
+ continue;
+ }
+ String path = ProjectSettings::get_singleton()->get(s);
+ if (path.begins_with("*")) {
+ text_edit->add_keyword_color(s.get_slice("/", 1), colors_cache.usertype_color);
+ }
+ }
+
//colorize comments
List<String> comments;
script->get_language()->get_comment_delimiters(&comments);
@@ -789,7 +814,7 @@ void ScriptTextEditor::_code_complete_script(const String &p_code, List<ScriptCo
}
String hint;
Error err = script->get_language()->complete_code(p_code, script->get_path(), base, r_options, r_force, hint);
- if (err == OK && hint != "") {
+ if (err == OK) {
code_editor->get_text_edit()->set_code_hint(hint);
}
}
@@ -942,12 +967,17 @@ void ScriptTextEditor::_update_connected_methods() {
text_edit->clear_info_icons();
missing_connections.clear();
+ if (!script->is_valid()) {
+ return;
+ }
+
Node *base = get_tree()->get_edited_scene_root();
if (!base) {
return;
}
Vector<Node *> nodes = _find_all_node_for_script(base, base, script);
+ Set<StringName> methods_found;
for (int i = 0; i < nodes.size(); i++) {
List<Connection> connections;
nodes[i]->get_signals_connected_to_this(&connections);
@@ -964,28 +994,33 @@ void ScriptTextEditor::_update_connected_methods() {
continue;
}
+ if (methods_found.has(connection.method)) {
+ continue;
+ }
+
if (!ClassDB::has_method(script->get_instance_base_type(), connection.method)) {
+ int line = -1;
+ if (script->has_method(connection.method)) {
+ line = script->get_member_line(connection.method);
+ text_edit->set_line_info_icon(line - 1, get_parent_control()->get_icon("Slot", "EditorIcons"), connection.method);
+ methods_found.insert(connection.method);
+ continue;
+ }
- int line = script->get_language()->find_function(connection.method, text_edit->get_text());
- if (line < 0) {
- // There is a chance that the method is inherited from another script.
- bool found_inherited_function = false;
- Ref<Script> inherited_script = script->get_base_script();
- while (!inherited_script.is_null()) {
- line = inherited_script->get_language()->find_function(connection.method, inherited_script->get_source_code());
- if (line != -1) {
- found_inherited_function = true;
- break;
- }
-
- inherited_script = inherited_script->get_base_script();
+ // There is a chance that the method is inherited from another script.
+ bool found_inherited_function = false;
+ Ref<Script> inherited_script = script->get_base_script();
+ while (!inherited_script.is_null()) {
+ if (inherited_script->has_method(connection.method)) {
+ found_inherited_function = true;
+ break;
}
- if (!found_inherited_function) {
- missing_connections.push_back(connection);
- }
- } else {
- text_edit->set_line_info_icon(line - 1, get_parent_control()->get_icon("Slot", "EditorIcons"), connection.method);
+ inherited_script = inherited_script->get_base_script();
+ }
+
+ if (!found_inherited_function) {
+ missing_connections.push_back(connection);
}
}
}
@@ -1161,7 +1196,7 @@ void ScriptTextEditor::_edit_option(int p_op) {
if (expression.parse(line) == OK) {
Variant result = expression.execute(Array(), Variant(), false);
if (expression.get_error_text() == "") {
- results.append(whitespace + (String)result);
+ results.append(whitespace + result.get_construct_string());
} else {
results.append(line);
}
diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h
index 0ea8726ecc..eba75befd4 100644
--- a/editor/plugins/script_text_editor.h
+++ b/editor/plugins/script_text_editor.h
@@ -91,6 +91,7 @@ class ScriptTextEditor : public ScriptEditorBase {
Color keyword_color;
Color basetype_color;
Color type_color;
+ Color usertype_color;
Color comment_color;
Color string_color;
} colors_cache;
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index df3e23a9e9..97f194e40f 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -198,13 +198,9 @@ void ShaderTextEditor::_code_complete_script(const String &p_code, List<ScriptCo
ShaderLanguage sl;
String calltip;
- Error err = sl.complete(p_code, ShaderTypes::get_singleton()->get_functions(VisualServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_types(), r_options, calltip);
- if (err != OK)
- ERR_PRINT("Shaderlang complete failed");
+ sl.complete(p_code, ShaderTypes::get_singleton()->get_functions(VisualServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_types(), r_options, calltip);
- if (calltip != "") {
- get_text_edit()->set_code_hint(calltip);
- }
+ get_text_edit()->set_code_hint(calltip);
}
void ShaderTextEditor::_validate_script() {
diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp
index ba40fc5612..eb39496106 100644
--- a/editor/plugins/spatial_editor_plugin.cpp
+++ b/editor/plugins/spatial_editor_plugin.cpp
@@ -2049,12 +2049,11 @@ void SpatialEditorViewport::_update_freelook(real_t delta) {
return;
}
- Vector3 forward = camera->get_transform().basis.xform(Vector3(0, 0, -1));
- Vector3 right = camera->get_transform().basis.xform(Vector3(1, 0, 0));
- Vector3 up = camera->get_transform().basis.xform(Vector3(0, 1, 0));
+ const Vector3 forward = camera->get_transform().basis.xform(Vector3(0, 0, -1));
+ const Vector3 right = camera->get_transform().basis.xform(Vector3(1, 0, 0));
+ const Vector3 up = camera->get_transform().basis.xform(Vector3(0, 1, 0));
Vector3 direction;
- bool speed_modifier = false;
if (is_shortcut_pressed("spatial_editor/freelook_left")) {
direction -= right;
@@ -2074,17 +2073,17 @@ void SpatialEditorViewport::_update_freelook(real_t delta) {
if (is_shortcut_pressed("spatial_editor/freelook_down")) {
direction -= up;
}
- if (is_shortcut_pressed("spatial_editor/freelook_speed_modifier")) {
- speed_modifier = true;
- }
real_t speed = freelook_speed;
- if (speed_modifier) {
- real_t modifier_speed_factor = EditorSettings::get_singleton()->get("editors/3d/freelook/freelook_modifier_speed_factor");
- speed *= modifier_speed_factor;
+
+ if (is_shortcut_pressed("spatial_editor/freelook_speed_modifier")) {
+ speed *= 3.0;
+ }
+ if (is_shortcut_pressed("spatial_editor/freelook_slow_modifier")) {
+ speed *= 0.333333;
}
- Vector3 motion = direction * speed * delta;
+ const Vector3 motion = direction * speed * delta;
cursor.pos += motion;
cursor.eye_pos += motion;
}
@@ -2172,7 +2171,7 @@ void SpatialEditorViewport::_notification(int p_what) {
VisualInstance *vi = Object::cast_to<VisualInstance>(sp);
- se->aabb = vi ? vi->get_aabb() : AABB(Vector3(-0.2, -0.2, -0.2), Vector3(0.4, 0.4, 0.4));
+ se->aabb = vi ? vi->get_aabb() : _calculate_spatial_bounds(sp);
Transform t = sp->get_global_gizmo_transform();
t.translate(se->aabb.position);
@@ -2761,6 +2760,7 @@ void SpatialEditorViewport::_menu_option(int p_option) {
void SpatialEditorViewport::_preview_exited_scene() {
+ preview_camera->disconnect("toggled", this, "_toggle_camera_preview");
preview_camera->set_pressed(false);
_toggle_camera_preview(false);
view_menu->show();
@@ -3032,6 +3032,9 @@ void SpatialEditorViewport::set_state(const Dictionary &p_state) {
view_menu->get_popup()->set_item_checked(idx, previewing_cinema);
}
+ if (preview_camera->is_connected("toggled", this, "_toggle_camera_preview")) {
+ preview_camera->disconnect("toggled", this, "_toggle_camera_preview");
+ }
if (p_state.has("previewing")) {
Node *pv = EditorNode::get_singleton()->get_edited_scene()->get_node(p_state["previewing"]);
if (Object::cast_to<Camera>(pv)) {
@@ -3044,6 +3047,7 @@ void SpatialEditorViewport::set_state(const Dictionary &p_state) {
preview_camera->show();
}
}
+ preview_camera->connect("toggled", this, "_toggle_camera_preview");
}
Dictionary SpatialEditorViewport::get_state() const {
@@ -3209,20 +3213,35 @@ Vector3 SpatialEditorViewport::_get_instance_position(const Point2 &p_pos) const
return point + offset;
}
-AABB SpatialEditorViewport::_calculate_spatial_bounds(const Spatial *p_parent, const AABB &p_bounds) {
- AABB bounds = p_bounds;
+AABB SpatialEditorViewport::_calculate_spatial_bounds(const Spatial *p_parent, bool p_exclude_toplevel_transform) {
+ AABB bounds;
+
+ const MeshInstance *mesh_instance = Object::cast_to<MeshInstance>(p_parent);
+ if (mesh_instance) {
+ bounds = mesh_instance->get_aabb();
+ }
+
for (int i = 0; i < p_parent->get_child_count(); i++) {
Spatial *child = Object::cast_to<Spatial>(p_parent->get_child(i));
if (child) {
- MeshInstance *mesh_instance = Object::cast_to<MeshInstance>(child);
- if (mesh_instance) {
- AABB mesh_instance_bounds = mesh_instance->get_aabb();
- mesh_instance_bounds.position += mesh_instance->get_global_gizmo_transform().origin - p_parent->get_global_gizmo_transform().origin;
- bounds.merge_with(mesh_instance_bounds);
+ AABB child_bounds = _calculate_spatial_bounds(child, false);
+
+ if (bounds.size == Vector3() && p_parent->get_class_name() == StringName("Spatial")) {
+ bounds = child_bounds;
+ } else {
+ bounds.merge_with(child_bounds);
}
- bounds = _calculate_spatial_bounds(child, bounds);
}
}
+
+ if (bounds.size == Vector3() && p_parent->get_class_name() != StringName("Spatial")) {
+ bounds = AABB(Vector3(-0.2, -0.2, -0.2), Vector3(0.4, 0.4, 0.4));
+ }
+
+ if (!p_exclude_toplevel_transform) {
+ bounds = p_parent->get_transform().xform(bounds);
+ }
+
return bounds;
}
@@ -3230,6 +3249,7 @@ void SpatialEditorViewport::_create_preview(const Vector<String> &files) const {
for (int i = 0; i < files.size(); i++) {
String path = files[i];
RES res = ResourceLoader::load(path);
+ ERR_CONTINUE(res.is_null());
Ref<PackedScene> scene = Ref<PackedScene>(Object::cast_to<PackedScene>(*res));
Ref<Mesh> mesh = Ref<Mesh>(Object::cast_to<Mesh>(*res));
if (mesh != NULL || scene != NULL) {
@@ -3248,7 +3268,7 @@ void SpatialEditorViewport::_create_preview(const Vector<String> &files) const {
editor->get_scene_root()->add_child(preview_node);
}
}
- *preview_bounds = _calculate_spatial_bounds(preview_node, AABB());
+ *preview_bounds = _calculate_spatial_bounds(preview_node);
}
void SpatialEditorViewport::_remove_preview() {
@@ -3279,6 +3299,7 @@ bool SpatialEditorViewport::_cyclical_dependency_exists(const String &p_target_s
bool SpatialEditorViewport::_create_instance(Node *parent, String &path, const Point2 &p_point) {
RES res = ResourceLoader::load(path);
+ ERR_FAIL_COND_V(res.is_null(), false);
Ref<PackedScene> scene = Ref<PackedScene>(Object::cast_to<PackedScene>(*res));
Ref<Mesh> mesh = Ref<Mesh>(Object::cast_to<Mesh>(*res));
@@ -3571,13 +3592,13 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
ED_SHORTCUT("spatial_editor/freelook_up", TTR("Freelook Up"), KEY_E);
ED_SHORTCUT("spatial_editor/freelook_down", TTR("Freelook Down"), KEY_Q);
ED_SHORTCUT("spatial_editor/freelook_speed_modifier", TTR("Freelook Speed Modifier"), KEY_SHIFT);
+ ED_SHORTCUT("spatial_editor/freelook_slow_modifier", TTR("Freelook Slow Modifier"), KEY_ALT);
preview_camera = memnew(CheckBox);
preview_camera->set_text(TTR("Preview"));
vbox->add_child(preview_camera);
preview_camera->set_h_size_flags(0);
preview_camera->hide();
- preview_camera->connect("toggled", this, "_toggle_camera_preview");
previewing = NULL;
gizmo_scale = 1.0;
@@ -4062,7 +4083,6 @@ void _update_all_gizmos(Node *p_node) {
void SpatialEditor::update_all_gizmos(Node *p_node) {
if (!p_node) {
- if (!SceneTree::get_singleton()) return;
p_node = SceneTree::get_singleton()->get_root();
}
_update_all_gizmos(p_node);
@@ -6269,5 +6289,7 @@ EditorSpatialGizmoPlugin::~EditorSpatialGizmoPlugin() {
current_gizmos[i]->set_plugin(NULL);
current_gizmos[i]->get_spatial_node()->set_gizmo(NULL);
}
- SpatialEditor::get_singleton()->update_all_gizmos();
+ if (SpatialEditor::get_singleton()) {
+ SpatialEditor::get_singleton()->update_all_gizmos();
+ }
}
diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h
index 208495c2f5..fe91c33642 100644
--- a/editor/plugins/spatial_editor_plugin.h
+++ b/editor/plugins/spatial_editor_plugin.h
@@ -375,7 +375,7 @@ private:
Point2i _get_warped_mouse_motion(const Ref<InputEventMouseMotion> &p_ev_mouse_motion) const;
Vector3 _get_instance_position(const Point2 &p_pos) const;
- static AABB _calculate_spatial_bounds(const Spatial *p_parent, const AABB &p_bounds);
+ static AABB _calculate_spatial_bounds(const Spatial *p_parent, bool p_exclude_toplevel_transform = true);
void _create_preview(const Vector<String> &files) const;
void _remove_preview();
bool _cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node);
diff --git a/editor/plugins/sprite_editor_plugin.cpp b/editor/plugins/sprite_editor_plugin.cpp
index 69fd592652..40734cffc4 100644
--- a/editor/plugins/sprite_editor_plugin.cpp
+++ b/editor/plugins/sprite_editor_plugin.cpp
@@ -178,6 +178,7 @@ void SpriteEditor::_update_mesh_data() {
err_dialog->popup_centered_minsize();
return;
}
+
Ref<Image> image = texture->get_data();
ERR_FAIL_COND(image.is_null());
Rect2 rect;
@@ -190,7 +191,12 @@ void SpriteEditor::_update_mesh_data() {
bm.instance();
bm->create_from_image_alpha(image);
- int grow = island_merging->get_value();
+ int shrink = shrink_pixels->get_value();
+ if (shrink > 0) {
+ bm->shrink_mask(shrink, rect);
+ }
+
+ int grow = grow_pixels->get_value();
if (grow > 0) {
bm->grow_mask(grow, rect);
}
@@ -338,6 +344,13 @@ void SpriteEditor::_convert_to_mesh_2d_node() {
}
void SpriteEditor::_convert_to_polygon_2d_node() {
+
+ if (computed_outline_lines.empty()) {
+ err_dialog->set_text(TTR("Invalid geometry, can't create polygon."));
+ err_dialog->popup_centered_minsize();
+ return;
+ }
+
Polygon2D *polygon_2d_instance = memnew(Polygon2D);
int total_point_count = 0;
@@ -362,12 +375,6 @@ void SpriteEditor::_convert_to_polygon_2d_node() {
Vector<Vector2> outline = computed_outline_lines[i];
Vector<Vector2> uv_outline = outline_lines[i];
- if (outline.size() < 3) {
- err_dialog->set_text(TTR("Invalid geometry, can't create polygon."));
- err_dialog->popup_centered_minsize();
- return;
- }
-
PoolIntArray pia;
pia.resize(outline.size());
PoolIntArray::Write pia_write = pia.write();
@@ -396,16 +403,17 @@ void SpriteEditor::_convert_to_polygon_2d_node() {
}
void SpriteEditor::_create_collision_polygon_2d_node() {
+
+ if (computed_outline_lines.empty()) {
+ err_dialog->set_text(TTR("Invalid geometry, can't create collision polygon."));
+ err_dialog->popup_centered_minsize();
+ return;
+ }
+
for (int i = 0; i < computed_outline_lines.size(); i++) {
Vector<Vector2> outline = computed_outline_lines[i];
- if (outline.size() < 3) {
- err_dialog->set_text(TTR("Invalid geometry, can't create collision polygon."));
- err_dialog->popup_centered_minsize();
- continue;
- }
-
CollisionPolygon2D *collision_polygon_2d_instance = memnew(CollisionPolygon2D);
collision_polygon_2d_instance->set_polygon(outline);
@@ -419,16 +427,17 @@ void SpriteEditor::_create_collision_polygon_2d_node() {
}
void SpriteEditor::_create_light_occluder_2d_node() {
+
+ if (computed_outline_lines.empty()) {
+ err_dialog->set_text(TTR("Invalid geometry, can't create light occluder."));
+ err_dialog->popup_centered_minsize();
+ return;
+ }
+
for (int i = 0; i < computed_outline_lines.size(); i++) {
Vector<Vector2> outline = computed_outline_lines[i];
- if (outline.size() < 3) {
- err_dialog->set_text(TTR("Invalid geometry, can't create light occluder."));
- err_dialog->popup_centered_minsize();
- continue;
- }
-
Ref<OccluderPolygon2D> polygon;
polygon.instance();
@@ -531,10 +540,14 @@ void SpriteEditor::_debug_uv_draw() {
Ref<Texture> tex = node->get_texture();
ERR_FAIL_COND(!tex.is_valid());
+
+ Point2 draw_pos_offset = Point2(1.0, 1.0);
+ Size2 draw_size_offset = Size2(2.0, 2.0);
+
debug_uv->set_clip_contents(true);
- debug_uv->draw_texture(tex, Point2());
- debug_uv->set_custom_minimum_size(tex->get_size());
- //debug_uv->draw_set_transform(Vector2(), 0, debug_uv->get_size());
+ debug_uv->draw_texture(tex, draw_pos_offset);
+ debug_uv->set_custom_minimum_size(tex->get_size() + draw_size_offset);
+ debug_uv->draw_set_transform(draw_pos_offset, 0, Size2(1.0, 1.0));
Color color = Color(1.0, 0.8, 0.7);
@@ -604,13 +617,21 @@ SpriteEditor::SpriteEditor() {
simplification->set_value(2);
hb->add_child(simplification);
hb->add_spacer();
+ hb->add_child(memnew(Label(TTR("Shrink (Pixels): "))));
+ shrink_pixels = memnew(SpinBox);
+ shrink_pixels->set_min(0);
+ shrink_pixels->set_max(10);
+ shrink_pixels->set_step(1);
+ shrink_pixels->set_value(0);
+ hb->add_child(shrink_pixels);
+ hb->add_spacer();
hb->add_child(memnew(Label(TTR("Grow (Pixels): "))));
- island_merging = memnew(SpinBox);
- island_merging->set_min(0);
- island_merging->set_max(10);
- island_merging->set_step(1);
- island_merging->set_value(2);
- hb->add_child(island_merging);
+ grow_pixels = memnew(SpinBox);
+ grow_pixels->set_min(0);
+ grow_pixels->set_max(10);
+ grow_pixels->set_step(1);
+ grow_pixels->set_value(2);
+ hb->add_child(grow_pixels);
hb->add_spacer();
update_preview = memnew(Button);
update_preview->set_text(TTR("Update Preview"));
diff --git a/editor/plugins/sprite_editor_plugin.h b/editor/plugins/sprite_editor_plugin.h
index 81be4a19e9..4ca7bca1a8 100644
--- a/editor/plugins/sprite_editor_plugin.h
+++ b/editor/plugins/sprite_editor_plugin.h
@@ -67,7 +67,8 @@ class SpriteEditor : public Control {
Vector<int> computed_indices;
SpinBox *simplification;
- SpinBox *island_merging;
+ SpinBox *grow_pixels;
+ SpinBox *shrink_pixels;
Button *update_preview;
void _menu_option(int p_option);
diff --git a/editor/plugins/style_box_editor_plugin.cpp b/editor/plugins/style_box_editor_plugin.cpp
index defc0a40ea..c4a9803ff4 100644
--- a/editor/plugins/style_box_editor_plugin.cpp
+++ b/editor/plugins/style_box_editor_plugin.cpp
@@ -64,21 +64,24 @@ void StyleBoxPreview::edit(const Ref<StyleBox> &p_stylebox) {
void StyleBoxPreview::_sb_changed() {
preview->update();
+}
+
+void StyleBoxPreview::_redraw() {
if (stylebox.is_valid()) {
- Size2 ms = stylebox->get_minimum_size() * 4 / 3;
- ms.height = MAX(ms.height, 150 * EDSCALE);
- preview->set_custom_minimum_size(ms);
+ preview->draw_style_box(stylebox, preview->get_rect());
}
}
void StyleBoxPreview::_bind_methods() {
ClassDB::bind_method("_sb_changed", &StyleBoxPreview::_sb_changed);
+ ClassDB::bind_method("_redraw", &StyleBoxPreview::_redraw);
}
StyleBoxPreview::StyleBoxPreview() {
-
- preview = memnew(Panel);
+ preview = memnew(Control);
+ preview->set_custom_minimum_size(Size2(0, 150 * EDSCALE));
+ preview->connect("draw", this, "_redraw");
add_margin_child(TTR("Preview:"), preview);
}
diff --git a/editor/plugins/style_box_editor_plugin.h b/editor/plugins/style_box_editor_plugin.h
index d31a28b3e4..fead8e0de8 100644
--- a/editor/plugins/style_box_editor_plugin.h
+++ b/editor/plugins/style_box_editor_plugin.h
@@ -41,10 +41,11 @@ class StyleBoxPreview : public VBoxContainer {
GDCLASS(StyleBoxPreview, VBoxContainer);
- Panel *preview;
+ Control *preview;
Ref<StyleBox> stylebox;
void _sb_changed();
+ void _redraw();
protected:
static void _bind_methods();
diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp
index d0320bcd8b..0cef5a8b6f 100644
--- a/editor/plugins/text_editor.cpp
+++ b/editor/plugins/text_editor.cpp
@@ -31,7 +31,7 @@
#include "text_editor.h"
#include "core/os/keyboard.h"
-#include "editor_node.h"
+#include "editor/editor_node.h"
void TextEditor::add_syntax_highlighter(SyntaxHighlighter *p_highlighter) {
highlighters[p_highlighter->get_name()] = p_highlighter;
diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp
index 21eebf9ca2..bda3d142fa 100644
--- a/editor/plugins/texture_region_editor_plugin.cpp
+++ b/editor/plugins/texture_region_editor_plugin.cpp
@@ -866,8 +866,8 @@ void TextureRegionEditor::_edit_region() {
Vector2 TextureRegionEditor::snap_point(Vector2 p_target) const {
if (snap_mode == SNAP_GRID) {
- p_target.x = Math::snap_scalar_seperation(snap_offset.x, snap_step.x, p_target.x, snap_separation.x);
- p_target.y = Math::snap_scalar_seperation(snap_offset.y, snap_step.y, p_target.y, snap_separation.y);
+ p_target.x = Math::snap_scalar_separation(snap_offset.x, snap_step.x, p_target.x, snap_separation.x);
+ p_target.y = Math::snap_scalar_separation(snap_offset.y, snap_step.y, p_target.y, snap_separation.y);
}
return p_target;
diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp
index e0bf8dfdb2..d81c6d3f96 100644
--- a/editor/plugins/tile_set_editor_plugin.cpp
+++ b/editor/plugins/tile_set_editor_plugin.cpp
@@ -3038,8 +3038,8 @@ Vector2 TileSetEditor::snap_point(const Vector2 &point) {
}
if (tools[TOOL_GRID_SNAP]->is_pressed()) {
- p.x = Math::snap_scalar_seperation(snap_offset.x, snap_step.x, p.x, snap_separation.x);
- p.y = Math::snap_scalar_seperation(snap_offset.y, snap_step.y, p.y, snap_separation.y);
+ p.x = Math::snap_scalar_separation(snap_offset.x, snap_step.x, p.x, snap_separation.x);
+ p.y = Math::snap_scalar_separation(snap_offset.y, snap_step.y, p.y, snap_separation.y);
}
if (tools[SHAPE_KEEP_INSIDE_TILE]->is_pressed()) {
if (p.x < region.position.x)
diff --git a/editor/plugins/version_control_editor_plugin.cpp b/editor/plugins/version_control_editor_plugin.cpp
index e8cd7692b6..66b16b82a0 100644
--- a/editor/plugins/version_control_editor_plugin.cpp
+++ b/editor/plugins/version_control_editor_plugin.cpp
@@ -380,6 +380,7 @@ void VersionControlEditorPlugin::fetch_available_vcs_addon_names() {
String path = ScriptServer::get_global_class_path(global_classes[i]);
Ref<Script> script = ResourceLoader::load(path);
+ ERR_FAIL_COND(script.is_null());
if (script->get_instance_base_type() == "EditorVCSInterface") {
@@ -396,8 +397,9 @@ void VersionControlEditorPlugin::clear_stage_area() {
void VersionControlEditorPlugin::shut_down() {
if (EditorVCSInterface::get_singleton()) {
-
- EditorFileSystem::get_singleton()->disconnect("filesystem_changed", this, "_refresh_stage_area");
+ if (EditorFileSystem::get_singleton()->is_connected("filesystem_changed", this, "_refresh_stage_area")) {
+ EditorFileSystem::get_singleton()->disconnect("filesystem_changed", this, "_refresh_stage_area");
+ }
EditorVCSInterface::get_singleton()->shut_down();
memdelete(EditorVCSInterface::get_singleton());
EditorVCSInterface::set_singleton(NULL);
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index 82baa99da2..3a9e48cfdb 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -88,7 +88,6 @@ void VisualShaderEditor::edit(VisualShader *p_visual_shader) {
} else {
if (changed) { // to avoid tree collapse
_clear_buffer();
- _update_custom_nodes();
_update_options_menu();
_update_preview();
}
@@ -178,7 +177,10 @@ bool VisualShaderEditor::_is_available(int p_mode) {
return (p_mode == -1 || (p_mode & current_mode) != 0);
}
-void VisualShaderEditor::_update_custom_nodes() {
+void VisualShaderEditor::update_custom_nodes() {
+ if (members_dialog->is_visible()) {
+ return;
+ }
clear_custom_types();
List<StringName> class_list;
ScriptServer::get_global_class_list(&class_list);
@@ -228,6 +230,7 @@ void VisualShaderEditor::_update_custom_nodes() {
add_custom_type(name, script, description, return_icon_type, category, sub_category);
}
}
+ _update_options_menu();
}
String VisualShaderEditor::_get_description(int p_idx) {
@@ -359,8 +362,8 @@ void VisualShaderEditor::_update_options_menu() {
case VisualShaderNode::PORT_TYPE_TRANSFORM:
item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("Transform", "EditorIcons"));
break;
- case VisualShaderNode::PORT_TYPE_ICON_COLOR:
- item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("Color", "EditorIcons"));
+ case VisualShaderNode::PORT_TYPE_SAMPLER:
+ item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("ImageTexture", "EditorIcons"));
break;
default:
break;
@@ -437,11 +440,12 @@ void VisualShaderEditor::_update_graph() {
}
}
- static const Color type_color[4] = {
+ static const Color type_color[5] = {
Color(0.38, 0.85, 0.96), // scalar
Color(0.84, 0.49, 0.93), // vector
Color(0.55, 0.65, 0.94), // boolean
- Color(0.96, 0.66, 0.43) // transform
+ Color(0.96, 0.66, 0.43), // transform
+ Color(1.0, 1.0, 0.0) // sampler
};
List<VisualShader::Connection> connections;
@@ -546,14 +550,14 @@ void VisualShaderEditor::_update_graph() {
HBoxContainer *hb2 = memnew(HBoxContainer);
Button *add_input_btn = memnew(Button);
- add_input_btn->set_text(TTR("Add input +"));
+ add_input_btn->set_text(TTR("Add Input"));
add_input_btn->connect("pressed", this, "_add_input_port", varray(nodes[n_i], group_node->get_free_input_port_id(), VisualShaderNode::PORT_TYPE_VECTOR, "input" + itos(group_node->get_free_input_port_id())), CONNECT_DEFERRED);
hb2->add_child(add_input_btn);
hb2->add_spacer();
Button *add_output_btn = memnew(Button);
- add_output_btn->set_text(TTR("Add output +"));
+ add_output_btn->set_text(TTR("Add Output"));
add_output_btn->connect("pressed", this, "_add_output_port", varray(nodes[n_i], group_node->get_free_output_port_id(), VisualShaderNode::PORT_TYPE_VECTOR, "output" + itos(group_node->get_free_output_port_id())), CONNECT_DEFERRED);
hb2->add_child(add_output_btn);
@@ -640,6 +644,7 @@ void VisualShaderEditor::_update_graph() {
type_box->add_item(TTR("Vector"));
type_box->add_item(TTR("Boolean"));
type_box->add_item(TTR("Transform"));
+ type_box->add_item(TTR("Sampler"));
type_box->select(group_node->get_input_port_type(i));
type_box->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
type_box->connect("item_selected", this, "_change_input_port_type", varray(nodes[n_i], i), CONNECT_DEFERRED);
@@ -663,6 +668,15 @@ void VisualShaderEditor::_update_graph() {
label->set_text(name_left);
label->add_style_override("normal", label_style); //more compact
hb->add_child(label);
+
+ if (vsnode->get_input_port_default_hint(i) != "" && !port_left_used) {
+
+ Label *hint_label = memnew(Label);
+ hint_label->set_text("[" + vsnode->get_input_port_default_hint(i) + "]");
+ hint_label->add_color_override("font_color", get_color("font_color_readonly", "TextEdit"));
+ hint_label->add_style_override("normal", label_style);
+ hb->add_child(hint_label);
+ }
}
}
@@ -704,7 +718,7 @@ void VisualShaderEditor::_update_graph() {
}
}
- if (valid_right && edit_type->get_selected() == VisualShader::TYPE_FRAGMENT && port_right != VisualShaderNode::PORT_TYPE_TRANSFORM) {
+ if (valid_right && edit_type->get_selected() == VisualShader::TYPE_FRAGMENT && port_right != VisualShaderNode::PORT_TYPE_TRANSFORM && port_right != VisualShaderNode::PORT_TYPE_SAMPLER) {
TextureButton *preview = memnew(TextureButton);
preview->set_toggle_mode(true);
preview->set_normal_texture(get_icon("GuiVisibilityHidden", "EditorIcons"));
@@ -731,15 +745,19 @@ void VisualShaderEditor::_update_graph() {
node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], valid_right, port_right, type_color[port_right]);
}
- if (vsnode->get_output_port_for_preview() >= 0 && vsnode->get_output_port_type(vsnode->get_output_port_for_preview()) != VisualShaderNode::PORT_TYPE_TRANSFORM) {
- offset = memnew(Control);
- offset->set_custom_minimum_size(Size2(0, 5 * EDSCALE));
- node->add_child(offset);
+ if (vsnode->get_output_port_for_preview() >= 0) {
+ int port_type = vsnode->get_output_port_type(vsnode->get_output_port_for_preview());
- VisualShaderNodePortPreview *port_preview = memnew(VisualShaderNodePortPreview);
- port_preview->setup(visual_shader, type, nodes[n_i], vsnode->get_output_port_for_preview());
- port_preview->set_h_size_flags(SIZE_SHRINK_CENTER);
- node->add_child(port_preview);
+ if (port_type != VisualShaderNode::PORT_TYPE_TRANSFORM && port_type != VisualShaderNode::PORT_TYPE_SAMPLER) {
+ offset = memnew(Control);
+ offset->set_custom_minimum_size(Size2(0, 5 * EDSCALE));
+ node->add_child(offset);
+
+ VisualShaderNodePortPreview *port_preview = memnew(VisualShaderNodePortPreview);
+ port_preview->setup(visual_shader, type, nodes[n_i], vsnode->get_output_port_for_preview());
+ port_preview->set_h_size_flags(SIZE_SHRINK_CENTER);
+ node->add_child(port_preview);
+ }
}
offset = memnew(Control);
@@ -1213,9 +1231,31 @@ void VisualShaderEditor::_edit_port_default_input(Object *p_button, int p_node,
editing_port = p_port;
}
-void VisualShaderEditor::_add_node(int p_idx, int p_op_idx) {
+void VisualShaderEditor::_add_custom_node(const String &p_path) {
+
+ int idx = -1;
+
+ for (int i = custom_node_option_idx; i < add_options.size(); i++) {
+ if (add_options[i].script.is_valid()) {
+ if (add_options[i].script->get_path() == p_path) {
+ idx = i;
+ break;
+ }
+ }
+ }
+ if (idx != -1) {
+ _add_node(idx);
+ }
+}
+
+void VisualShaderEditor::_add_texture_node(const String &p_path) {
+ VisualShaderNodeTexture *texture = (VisualShaderNodeTexture *)_add_node(texture_node_option_idx, -1);
+ texture->set_texture(ResourceLoader::load(p_path));
+}
- ERR_FAIL_INDEX(p_idx, add_options.size());
+VisualShaderNode *VisualShaderEditor::_add_node(int p_idx, int p_op_idx) {
+
+ ERR_FAIL_INDEX_V(p_idx, add_options.size(), NULL);
Ref<VisualShaderNode> vsnode;
@@ -1223,7 +1263,7 @@ void VisualShaderEditor::_add_node(int p_idx, int p_op_idx) {
if (!is_custom && add_options[p_idx].type != String()) {
VisualShaderNode *vsn = Object::cast_to<VisualShaderNode>(ClassDB::instance(add_options[p_idx].type));
- ERR_FAIL_COND(!vsn);
+ ERR_FAIL_COND_V(!vsn, NULL);
VisualShaderNodeScalarConstant *constant = Object::cast_to<VisualShaderNodeScalarConstant>(vsn);
@@ -1309,10 +1349,10 @@ void VisualShaderEditor::_add_node(int p_idx, int p_op_idx) {
vsnode = Ref<VisualShaderNode>(vsn);
} else {
- ERR_FAIL_COND(add_options[p_idx].script.is_null());
+ ERR_FAIL_COND_V(add_options[p_idx].script.is_null(), NULL);
String base_type = add_options[p_idx].script->get_instance_base_type();
VisualShaderNode *vsn = Object::cast_to<VisualShaderNode>(ClassDB::instance(base_type));
- ERR_FAIL_COND(!vsn);
+ ERR_FAIL_COND_V(!vsn, NULL);
vsnode = Ref<VisualShaderNode>(vsn);
vsnode->set_script(add_options[p_idx].script.get_ref_ptr());
}
@@ -1367,6 +1407,7 @@ void VisualShaderEditor::_add_node(int p_idx, int p_op_idx) {
undo_redo->add_do_method(this, "_update_graph");
undo_redo->add_undo_method(this, "_update_graph");
undo_redo->commit_action();
+ return vsnode.ptr();
}
void VisualShaderEditor::_node_dragged(const Vector2 &p_from, const Vector2 &p_to, int p_node) {
@@ -2038,6 +2079,9 @@ bool VisualShaderEditor::can_drop_data_fw(const Point2 &p_point, const Variant &
if (d.has("id")) {
return true;
}
+ if (d.has("files")) {
+ return true;
+ }
}
return false;
@@ -2054,6 +2098,30 @@ void VisualShaderEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
saved_node_pos = p_point;
saved_node_pos_dirty = true;
_add_node(idx, add_options[idx].sub_func);
+ } else if (d.has("files")) {
+ if (d["files"].get_type() == Variant::POOL_STRING_ARRAY) {
+
+ int j = 0;
+ PoolStringArray arr = d["files"];
+ for (int i = 0; i < arr.size(); i++) {
+
+ String type = ResourceLoader::get_resource_type(arr[i]);
+ if (type == "GDScript") {
+ Ref<Script> script = ResourceLoader::load(arr[i]);
+ if (script->get_instance_base_type() == "VisualShaderNodeCustom") {
+ saved_node_pos = p_point + Vector2(0, j * 210 * EDSCALE);
+ saved_node_pos_dirty = true;
+ _add_custom_node(arr[i]);
+ j++;
+ }
+ } else if (ClassDB::get_parent_class(type) == "Texture") {
+ saved_node_pos = p_point + Vector2(0, j * 210 * EDSCALE);
+ saved_node_pos_dirty = true;
+ _add_texture_node(arr[i]);
+ j++;
+ }
+ }
+ }
}
}
}
@@ -2191,6 +2259,7 @@ VisualShaderEditor::VisualShaderEditor() {
graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_BOOLEAN);
graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_VECTOR);
graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_TRANSFORM);
+ graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_SAMPLER);
//graph->add_valid_left_disconnect_type(0);
graph->set_v_size_flags(SIZE_EXPAND_FILL);
graph->connect("connection_request", this, "_connection_request", varray(), CONNECT_DEFERRED);
@@ -2214,6 +2283,7 @@ VisualShaderEditor::VisualShaderEditor() {
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_VECTOR);
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_BOOLEAN);
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShaderNode::PORT_TYPE_TRANSFORM);
+ graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SAMPLER, VisualShaderNode::PORT_TYPE_SAMPLER);
VSeparator *vs = memnew(VSeparator);
graph->get_zoom_hbox()->add_child(vs);
@@ -2350,8 +2420,8 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("Screen", "Color", "Operators", "VisualShaderNodeColorOp", TTR("Screen operator."), VisualShaderNodeColorOp::OP_SCREEN, VisualShaderNode::PORT_TYPE_VECTOR));
add_options.push_back(AddOption("SoftLight", "Color", "Operators", "VisualShaderNodeColorOp", TTR("SoftLight operator."), VisualShaderNodeColorOp::OP_SOFT_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR));
- add_options.push_back(AddOption("ColorConstant", "Color", "Variables", "VisualShaderNodeColorConstant", TTR("Color constant."), -1, VisualShaderNode::PORT_TYPE_ICON_COLOR));
- add_options.push_back(AddOption("ColorUniform", "Color", "Variables", "VisualShaderNodeColorUniform", TTR("Color uniform."), -1, VisualShaderNode::PORT_TYPE_ICON_COLOR));
+ add_options.push_back(AddOption("ColorConstant", "Color", "Variables", "VisualShaderNodeColorConstant", TTR("Color constant."), -1, -1));
+ add_options.push_back(AddOption("ColorUniform", "Color", "Variables", "VisualShaderNodeColorUniform", TTR("Color uniform."), -1, -1));
// CONDITIONAL
@@ -2557,12 +2627,13 @@ VisualShaderEditor::VisualShaderEditor() {
// TEXTURES
- add_options.push_back(AddOption("CubeMap", "Textures", "Functions", "VisualShaderNodeCubeMap", TTR("Perform the cubic texture lookup."), -1, VisualShaderNode::PORT_TYPE_ICON_COLOR));
- add_options.push_back(AddOption("Texture", "Textures", "Functions", "VisualShaderNodeTexture", TTR("Perform the texture lookup."), -1, VisualShaderNode::PORT_TYPE_ICON_COLOR));
+ add_options.push_back(AddOption("CubeMap", "Textures", "Functions", "VisualShaderNodeCubeMap", TTR("Perform the cubic texture lookup."), -1, -1));
+ texture_node_option_idx = add_options.size();
+ add_options.push_back(AddOption("Texture", "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, VisualShaderNode::PORT_TYPE_ICON_COLOR));
- add_options.push_back(AddOption("TextureUniform", "Textures", "Variables", "VisualShaderNodeTextureUniform", TTR("2D texture uniform lookup."), -1, VisualShaderNode::PORT_TYPE_ICON_COLOR));
- add_options.push_back(AddOption("TextureUniformTriplanar", "Textures", "Variables", "VisualShaderNodeTextureUniformTriplanar", TTR("2D texture uniform lookup with triplanar."), -1, VisualShaderNode::PORT_TYPE_ICON_COLOR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("CubeMapUniform", "Textures", "Variables", "VisualShaderNodeCubeMapUniform", TTR("Cubic texture uniform lookup."), -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));
// TRANSFORM
@@ -2666,6 +2737,7 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("DdYS", "Special", "Derivative", "VisualShaderNodeScalarDerivativeFunc", TTR("(Fragment/Light mode only) (Scalar) Derivative in 'y' using local differencing."), VisualShaderNodeScalarDerivativeFunc::FUNC_Y, VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT, -1, -1, true));
add_options.push_back(AddOption("Sum", "Special", "Derivative", "VisualShaderNodeVectorDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Sum of absolute derivative in 'x' and 'y'."), VisualShaderNodeVectorDerivativeFunc::FUNC_SUM, VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT, -1, -1, true));
add_options.push_back(AddOption("SumS", "Special", "Derivative", "VisualShaderNodeScalarDerivativeFunc", TTR("(Fragment/Light mode only) (Scalar) Sum of absolute derivative in 'x' and 'y'."), VisualShaderNodeScalarDerivativeFunc::FUNC_SUM, VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT, -1, -1, true));
+ custom_node_option_idx = add_options.size();
/////////////////////////////////////////////////////////////////////
@@ -2707,6 +2779,7 @@ void VisualShaderEditorPlugin::make_visible(bool p_visible) {
//editor->animation_panel_make_visible(true);
button->show();
editor->make_bottom_panel_item_visible(visual_shader_editor);
+ visual_shader_editor->update_custom_nodes();
visual_shader_editor->set_process_input(true);
//visual_shader_editor->set_process(true);
} else {
diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h
index cd5efc366b..6f77641936 100644
--- a/editor/plugins/visual_shader_editor_plugin.h
+++ b/editor/plugins/visual_shader_editor_plugin.h
@@ -137,6 +137,7 @@ class VisualShaderEditor : public VBoxContainer {
category = p_category;
sub_category = p_sub_category;
description = p_description;
+ sub_func = 0;
sub_func_str = p_sub_func;
return_type = p_return_type;
mode = p_mode;
@@ -148,12 +149,15 @@ class VisualShaderEditor : public VBoxContainer {
};
Vector<AddOption> add_options;
+ int texture_node_option_idx;
+ int custom_node_option_idx;
List<String> keyword_list;
void _draw_color_over_button(Object *obj, Color p_color);
- void _add_node(int p_idx, int p_op_idx = -1);
- void _update_custom_nodes();
+ void _add_custom_node(const String &p_path);
+ void _add_texture_node(const String &p_path);
+ VisualShaderNode *_add_node(int p_idx, int p_op_idx = -1);
void _update_options_menu();
void _show_preview_text();
@@ -253,6 +257,7 @@ protected:
static void _bind_methods();
public:
+ void update_custom_nodes();
void add_plugin(const Ref<VisualShaderNodePlugin> &p_plugin);
void remove_plugin(const Ref<VisualShaderNodePlugin> &p_plugin);