summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
Diffstat (limited to 'editor')
-rw-r--r--editor/animation_bezier_editor.cpp35
-rw-r--r--editor/animation_track_editor.cpp5
-rw-r--r--editor/editor_command_palette.cpp68
-rw-r--r--editor/editor_node.cpp7
-rw-r--r--editor/editor_node.h1
-rw-r--r--editor/editor_plugin.cpp2
-rw-r--r--editor/icons/GridLayout.svg2
-rw-r--r--editor/icons/VisualScriptComment.svg1
-rw-r--r--editor/icons/VisualScriptExpression.svg1
-rw-r--r--editor/icons/VisualShaderGraphTextureUniform.svg1
-rw-r--r--editor/icons/VisualShaderNodeBooleanUniform.svg1
-rw-r--r--editor/icons/VisualShaderNodeColorConstant.svg1
-rw-r--r--editor/icons/VisualShaderNodeColorOp.svg1
-rw-r--r--editor/icons/VisualShaderNodeColorUniform.svg1
-rw-r--r--editor/icons/VisualShaderNodeComment.svg1
-rw-r--r--editor/icons/VisualShaderNodeCubemap.svg1
-rw-r--r--editor/icons/VisualShaderNodeCubemapUniform.svg1
-rw-r--r--editor/icons/VisualShaderNodeCurveTexture.svg1
-rw-r--r--editor/icons/VisualShaderNodeCurveXYZTexture.svg1
-rw-r--r--editor/icons/VisualShaderNodeExpression.svg1
-rw-r--r--editor/icons/VisualShaderNodeFloatFunc.svg1
-rw-r--r--editor/icons/VisualShaderNodeFloatOp.svg1
-rw-r--r--editor/icons/VisualShaderNodeFloatUniform.svg1
-rw-r--r--editor/icons/VisualShaderNodeGlobalExpression.svg1
-rw-r--r--editor/icons/VisualShaderNodeInput.svg1
-rw-r--r--editor/icons/VisualShaderNodeIntFunc.svg1
-rw-r--r--editor/icons/VisualShaderNodeIntOp.svg1
-rw-r--r--editor/icons/VisualShaderNodeIntUniform.svg1
-rw-r--r--editor/icons/VisualShaderNodeTexture2DUniformTriplanar.svg1
-rw-r--r--editor/icons/VisualShaderNodeTransformCompose.svg1
-rw-r--r--editor/icons/VisualShaderNodeTransformDecompose.svg1
-rw-r--r--editor/icons/VisualShaderNodeTransformUniform.svg1
-rw-r--r--editor/icons/VisualShaderNodeTransformVecMult.svg1
-rw-r--r--editor/icons/VisualShaderNodeVec3Uniform.svg1
-rw-r--r--editor/icons/VisualShaderNodeVectorCompose.svg1
-rw-r--r--editor/icons/VisualShaderNodeVectorDecompose.svg1
-rw-r--r--editor/icons/VisualShaderNodeVectorDistance.svg1
-rw-r--r--editor/icons/VisualShaderNodeVectorFunc.svg1
-rw-r--r--editor/icons/VisualShaderNodeVectorLen.svg1
-rw-r--r--editor/icons/WorldMarginShape2D.svg (renamed from editor/icons/LineShape2D.svg)0
-rw-r--r--editor/plugins/abstract_polygon_2d_editor.cpp4
-rw-r--r--editor/plugins/collision_shape_2d_editor_plugin.cpp22
-rw-r--r--editor/plugins/collision_shape_2d_editor_plugin.h2
-rw-r--r--editor/plugins/gpu_particles_2d_editor_plugin.cpp15
-rw-r--r--editor/plugins/gpu_particles_3d_editor_plugin.cpp14
-rw-r--r--editor/plugins/node_3d_editor_gizmos.cpp79
-rw-r--r--editor/plugins/node_3d_editor_gizmos.h1
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp90
-rw-r--r--editor/plugins/node_3d_editor_plugin.h12
-rw-r--r--editor/plugins/path_2d_editor_plugin.cpp2
-rw-r--r--editor/plugins/skeleton_3d_editor_plugin.cpp26
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp30
52 files changed, 286 insertions, 163 deletions
diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp
index 6ef36f16f5..ea2ae53e82 100644
--- a/editor/animation_bezier_editor.cpp
+++ b/editor/animation_bezier_editor.cpp
@@ -178,7 +178,7 @@ void AnimationBezierTrackEdit::_draw_track(int p_track, const Color &p_color) {
}
if (lines.size() >= 2) {
- draw_multiline(lines, p_color);
+ draw_multiline(lines, p_color, Math::round(EDSCALE));
}
}
}
@@ -212,7 +212,7 @@ void AnimationBezierTrackEdit::_draw_line_clipped(const Vector2 &p_from, const V
from = from.lerp(to, c);
}
- draw_line(from, to, p_color);
+ draw_line(from, to, p_color, Math::round(EDSCALE));
}
void AnimationBezierTrackEdit::_notification(int p_what) {
@@ -244,7 +244,7 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
if (has_focus()) {
Color accent = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
accent.a *= 0.7;
- draw_rect(Rect2(Point2(), get_size()), accent, false);
+ draw_rect(Rect2(Point2(), get_size()), accent, false, Math::round(EDSCALE));
}
Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
@@ -255,11 +255,11 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
Color linecolor = color;
linecolor.a = 0.2;
- draw_line(Point2(limit, 0), Point2(limit, get_size().height), linecolor);
+ draw_line(Point2(limit, 0), Point2(limit, get_size().height), linecolor, Math::round(EDSCALE));
int right_limit = get_size().width - timeline->get_buttons_width();
- draw_line(Point2(right_limit, 0), Point2(right_limit, get_size().height), linecolor);
+ draw_line(Point2(right_limit, 0), Point2(right_limit, get_size().height), linecolor, Math::round(EDSCALE));
Ref<Texture2D> close_icon = get_theme_icon(SNAME("Close"), SNAME("EditorIcons"));
@@ -387,7 +387,7 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
if (!first && iv != prev_iv) {
Color lc = linecolor;
lc.a *= 0.5;
- draw_line(Point2(limit, i), Point2(right_limit, i), lc);
+ draw_line(Point2(limit, i), Point2(right_limit, i), lc, Math::round(EDSCALE));
Color c = color;
c.a *= 0.5;
draw_string(font, Point2(limit + 8, i - 2), TS->format_number(rtos(Math::snapped((iv + 1) * scale, step))), HALIGN_LEFT, -1, font_size, c);
@@ -461,7 +461,7 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
ep.point_rect.size = bezier_icon->get_size();
if (selection.has(i)) {
draw_texture(selected_icon, ep.point_rect.position);
- draw_string(font, ep.point_rect.position + Vector2(8, -font->get_height(font_size) - 4), TTR("Time:") + " " + TS->format_number(rtos(Math::snapped(offset, 0.001))), HALIGN_LEFT, -1, font_size, accent);
+ draw_string(font, ep.point_rect.position + Vector2(8, -font->get_height(font_size) - 8), TTR("Time:") + " " + TS->format_number(rtos(Math::snapped(offset, 0.001))), HALIGN_LEFT, -1, font_size, accent);
draw_string(font, ep.point_rect.position + Vector2(8, -8), TTR("Value:") + " " + TS->format_number(rtos(Math::snapped(value, 0.001))), HALIGN_LEFT, -1, font_size, accent);
} else {
draw_texture(bezier_icon, ep.point_rect.position);
@@ -485,8 +485,6 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
}
if (box_selecting) {
- Color bs = accent;
- bs.a *= 0.5;
Vector2 bs_from = box_selection_from;
Vector2 bs_to = box_selection_to;
if (bs_from.x > bs_to.x) {
@@ -495,7 +493,14 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
if (bs_from.y > bs_to.y) {
SWAP(bs_from.y, bs_to.y);
}
- draw_rect(Rect2(bs_from, bs_to - bs_from), bs);
+ draw_rect(
+ Rect2(bs_from, bs_to - bs_from),
+ get_theme_color("box_selection_fill_color", "Editor"));
+ draw_rect(
+ Rect2(bs_from, bs_to - bs_from),
+ get_theme_color("box_selection_stroke_color", "Editor"),
+ false,
+ Math::round(EDSCALE));
}
}
}
@@ -618,9 +623,9 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) {
- float v_zoom_orig = v_zoom;
+ const float v_zoom_orig = v_zoom;
if (mb->is_command_pressed()) {
- timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() * 1.05);
+ timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() / 1.05);
} else {
if (v_zoom < 100000) {
v_zoom *= 1.2;
@@ -631,9 +636,9 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
}
if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) {
- float v_zoom_orig = v_zoom;
+ const float v_zoom_orig = v_zoom;
if (mb->is_command_pressed()) {
- timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() / 1.05);
+ timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() * 1.05);
} else {
if (v_zoom > 0.000001) {
v_zoom /= 1.2;
@@ -974,7 +979,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
if (moving_handle != 0 && mm.is_valid()) {
float y = (get_size().height / 2 - mm->get_position().y) * v_zoom + v_scroll;
- float x = ((mm->get_position().x - timeline->get_name_limit()) / timeline->get_zoom_scale()) + timeline->get_value();
+ float x = editor->snap_time((mm->get_position().x - timeline->get_name_limit()) / timeline->get_zoom_scale()) + timeline->get_value();
Vector2 key_pos = Vector2(animation->track_get_key_time(track, moving_handle_key), animation->bezier_track_get_key_value(track, moving_handle_key));
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index 964c37906f..ff2818f027 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -5642,6 +5642,11 @@ float AnimationTrackEditor::snap_time(float p_value, bool p_relative) {
snap_increment = step->get_value();
}
+ if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
+ // Use more precise snapping when holding Shift.
+ snap_increment *= 0.25;
+ }
+
if (p_relative) {
double rel = Math::fmod(timeline->get_value(), snap_increment);
p_value = Math::snapped(p_value + rel, snap_increment) - rel;
diff --git a/editor/editor_command_palette.cpp b/editor/editor_command_palette.cpp
index bffd0655a7..6349beeef4 100644
--- a/editor/editor_command_palette.cpp
+++ b/editor/editor_command_palette.cpp
@@ -60,7 +60,6 @@ void EditorCommandPalette::_update_command_search(const String &search_text) {
commands.get_key_list(&command_keys);
ERR_FAIL_COND(command_keys.is_empty());
- const bool empty_search = search_text.is_empty();
Map<String, TreeItem *> sections;
TreeItem *first_section = nullptr;
@@ -71,7 +70,7 @@ void EditorCommandPalette::_update_command_search(const String &search_text) {
r.key_name = command_keys[i];
r.display_name = commands[r.key_name].name;
r.shortcut_text = commands[r.key_name].shortcut;
- if (!empty_search && search_text.is_subsequence_ofi(r.display_name)) {
+ if (search_text.is_subsequence_ofi(r.display_name)) {
r.score = _score_path(search_text, r.display_name.to_lower());
entries.push_back(r);
}
@@ -83,7 +82,7 @@ void EditorCommandPalette::_update_command_search(const String &search_text) {
root->clear_children();
if (entries.size() > 0) {
- if (!empty_search) {
+ if (!search_text.is_empty()) {
SortArray<CommandEntry, CommandEntryComparator> sorter;
sorter.sort(entries.ptrw(), entries.size());
}
@@ -128,7 +127,7 @@ void EditorCommandPalette::_update_command_search(const String &search_text) {
get_ok_button()->set_disabled(false);
} else {
TreeItem *ti = search_options->create_item(root);
- ti->set_text(0, TTR("No Matching Command"));
+ ti->set_text(0, TTR("No matching commands found"));
ti->set_metadata(0, "");
Color c = Color(0.5, 0.5, 0.5, 0.5);
ti->set_custom_color(0, c);
@@ -179,35 +178,35 @@ void EditorCommandPalette::get_actions_list(List<String> *p_list) const {
}
void EditorCommandPalette::remove_command(String p_key_name) {
- ERR_FAIL_COND_MSG(!commands.has(p_key_name), "The EditorAction '" + String(p_key_name) + "' Doesn't exists. Unable to remove it.");
+ ERR_FAIL_COND_MSG(!commands.has(p_key_name), "The Command '" + String(p_key_name) + "' doesn't exists. Unable to remove it.");
commands.erase(p_key_name);
}
void EditorCommandPalette::add_command(String p_command_name, String p_key_name, Callable p_action, Vector<Variant> arguments, String p_shortcut_text) {
- ERR_FAIL_COND_MSG(commands.has(p_key_name), "The EditorAction '" + String(p_command_name) + "' already exists. Unable to add it.");
+ ERR_FAIL_COND_MSG(commands.has(p_key_name), "The Command '" + String(p_command_name) + "' already exists. Unable to add it.");
const Variant **argptrs = (const Variant **)alloca(sizeof(Variant *) * arguments.size());
for (int i = 0; i < arguments.size(); i++) {
argptrs[i] = &arguments[i];
}
- Command p_command;
- p_command.name = p_command_name;
- p_command.callable = p_action.bind(argptrs, arguments.size());
- p_command.shortcut = p_shortcut_text;
+ Command command;
+ command.name = p_command_name;
+ command.callable = p_action.bind(argptrs, arguments.size());
+ command.shortcut = p_shortcut_text;
- commands[p_key_name] = p_command;
+ commands[p_key_name] = command;
}
void EditorCommandPalette::_add_command(String p_command_name, String p_key_name, Callable p_binded_action, String p_shortcut_text) {
- ERR_FAIL_COND_MSG(commands.has(p_key_name), "The EditorAction '" + String(p_command_name) + "' already exists. Unable to add it.");
+ ERR_FAIL_COND_MSG(commands.has(p_key_name), "The Command '" + String(p_command_name) + "' already exists. Unable to add it.");
- Command p_command;
- p_command.name = p_command_name;
- p_command.callable = p_binded_action;
- p_command.shortcut = p_shortcut_text;
+ Command command;
+ command.name = p_command_name;
+ command.callable = p_binded_action;
+ command.shortcut = p_shortcut_text;
- commands[p_key_name] = p_command;
+ commands[p_key_name] = command;
}
void EditorCommandPalette::execute_command(String &p_command_key) {
@@ -216,17 +215,17 @@ void EditorCommandPalette::execute_command(String &p_command_key) {
}
void EditorCommandPalette::register_shortcuts_as_command() {
- const String *p_key = nullptr;
- p_key = unregistered_shortcuts.next(p_key);
- while (p_key != nullptr) {
- String command_name = unregistered_shortcuts[*p_key].first;
- Ref<Shortcut> p_shortcut = unregistered_shortcuts[*p_key].second;
+ const String *key = nullptr;
+ key = unregistered_shortcuts.next(key);
+ while (key != nullptr) {
+ String command_name = unregistered_shortcuts[*key].first;
+ Ref<Shortcut> shortcut = unregistered_shortcuts[*key].second;
Ref<InputEventShortcut> ev;
ev.instantiate();
- ev->set_shortcut(p_shortcut);
- String shortcut_text = String(p_shortcut->get_as_text());
- add_command(command_name, *p_key, callable_mp(EditorNode::get_singleton()->get_viewport(), &Viewport::unhandled_input), varray(ev, false), shortcut_text);
- p_key = unregistered_shortcuts.next(p_key);
+ ev->set_shortcut(shortcut);
+ String shortcut_text = String(shortcut->get_as_text());
+ add_command(command_name, *key, callable_mp(EditorNode::get_singleton()->get_viewport(), &Viewport::unhandled_input), varray(ev, false), shortcut_text);
+ key = unregistered_shortcuts.next(key);
}
unregistered_shortcuts.clear();
}
@@ -241,8 +240,8 @@ Ref<Shortcut> EditorCommandPalette::add_shortcut_command(const String &p_command
} else {
const String key_name = String(p_key);
const String command_name = String(p_command);
- Pair p_pair = Pair(command_name, p_shortcut);
- unregistered_shortcuts[key_name] = p_pair;
+ Pair pair = Pair(command_name, p_shortcut);
+ unregistered_shortcuts[key_name] = pair;
}
return p_shortcut;
}
@@ -264,12 +263,11 @@ EditorCommandPalette::EditorCommandPalette() {
add_child(vbc);
command_search_box = memnew(LineEdit);
- command_search_box->set_placeholder("search for a command");
- command_search_box->set_placeholder_alpha(0.5);
+ command_search_box->set_placeholder(TTR("Filter commands"));
command_search_box->connect("gui_input", callable_mp(this, &EditorCommandPalette::_sbox_input));
command_search_box->connect("text_changed", callable_mp(this, &EditorCommandPalette::_update_command_search));
- command_search_box->connect("text_submitted", callable_mp(this, &EditorCommandPalette::_confirmed).unbind(1));
command_search_box->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ command_search_box->set_clear_button_enabled(true);
MarginContainer *margin_container_csb = memnew(MarginContainer);
margin_container_csb->add_child(command_search_box);
vbc->add_child(margin_container_csb);
@@ -285,9 +283,9 @@ EditorCommandPalette::EditorCommandPalette() {
search_options->set_v_size_flags(Control::SIZE_EXPAND_FILL);
search_options->set_h_size_flags(Control::SIZE_EXPAND_FILL);
search_options->set_column_custom_minimum_width(0, int(8 * EDSCALE));
-
vbc->add_child(search_options, true);
+ connect("confirmed", callable_mp(this, &EditorCommandPalette::_confirmed));
set_hide_on_ok(false);
}
@@ -296,7 +294,7 @@ Ref<Shortcut> ED_SHORTCUT_AND_COMMAND(const String &p_path, const String &p_name
p_command_name = p_name;
}
- Ref<Shortcut> p_shortcut = ED_SHORTCUT(p_path, p_name, p_keycode);
- EditorCommandPalette::get_singleton()->add_shortcut_command(p_command_name, p_path, p_shortcut);
- return p_shortcut;
+ Ref<Shortcut> shortcut = ED_SHORTCUT(p_path, p_name, p_keycode);
+ EditorCommandPalette::get_singleton()->add_shortcut_command(p_command_name, p_path, shortcut);
+ return shortcut;
}
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 19a6d027bc..4cd2e8bdd0 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -6369,6 +6369,7 @@ EditorNode::EditorNode() {
#else
p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/editor_settings", TTR("Editor Settings...")), SETTINGS_PREFERENCES);
#endif
+ p->add_shortcut(ED_SHORTCUT("editor/command_palette", TTR("Command Palette..."), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_P), HELP_COMMAND_PALETTE);
p->add_separator();
editor_layouts = memnew(PopupMenu);
@@ -6682,7 +6683,7 @@ EditorNode::EditorNode() {
bottom_panel_raise->set_flat(true);
bottom_panel_raise->set_icon(gui_base->get_theme_icon(SNAME("ExpandBottomDock"), SNAME("EditorIcons")));
- bottom_panel_raise->set_shortcut(ED_SHORTCUT("editor/bottom_panel_expand", TTR("Expand Bottom Panel"), KEY_MASK_SHIFT | KEY_F12));
+ bottom_panel_raise->set_shortcut(ED_SHORTCUT_AND_COMMAND("editor/bottom_panel_expand", TTR("Expand Bottom Panel"), KEY_MASK_SHIFT | KEY_F12));
bottom_panel_hb->add_child(bottom_panel_raise);
bottom_panel_raise->hide();
@@ -7047,17 +7048,15 @@ EditorNode::EditorNode() {
ED_SHORTCUT_AND_COMMAND("editor/editor_3d", TTR("Open 3D Editor"), KEY_MASK_ALT | KEY_2);
ED_SHORTCUT_AND_COMMAND("editor/editor_script", TTR("Open Script Editor"), KEY_MASK_ALT | KEY_3);
ED_SHORTCUT_AND_COMMAND("editor/editor_assetlib", TTR("Open Asset Library"), KEY_MASK_ALT | KEY_4);
- ED_SHORTCUT("editor/command_palette", TTR("Open Command Palette"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_P);
#else
// Use the Ctrl modifier so F2 can be used to rename nodes in the scene tree dock.
ED_SHORTCUT_AND_COMMAND("editor/editor_2d", TTR("Open 2D Editor"), KEY_MASK_CTRL | KEY_F1);
ED_SHORTCUT_AND_COMMAND("editor/editor_3d", TTR("Open 3D Editor"), KEY_MASK_CTRL | KEY_F2);
ED_SHORTCUT_AND_COMMAND("editor/editor_script", TTR("Open Script Editor"), KEY_MASK_CTRL | KEY_F3);
ED_SHORTCUT_AND_COMMAND("editor/editor_assetlib", TTR("Open Asset Library"), KEY_MASK_CTRL | KEY_F4);
- ED_SHORTCUT("editor/command_palette", TTR("Open Command Palette"), KEY_MASK_CTRL | KEY_MASK_SHIFT | KEY_P);
#endif
ED_SHORTCUT_AND_COMMAND("editor/editor_next", TTR("Next Editor Tab"));
- ED_SHORTCUT_AND_COMMAND("editor/editor_prev", TTR("Next Editor Tab"));
+ ED_SHORTCUT_AND_COMMAND("editor/editor_prev", TTR("Previous Editor Tab"));
screenshot_timer = memnew(Timer);
screenshot_timer->set_one_shot(true);
diff --git a/editor/editor_node.h b/editor/editor_node.h
index fed4d23704..911139f470 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -708,7 +708,6 @@ public:
EditorInspector *get_inspector() { return inspector_dock->get_inspector(); }
Container *get_inspector_dock_addon_area() { return inspector_dock->get_addon_area(); }
ScriptCreateDialog *get_script_create_dialog() { return scene_tree_dock->get_script_create_dialog(); }
- EditorCommandPalette *get_editor_command_palette() { return command_palette; }
ProjectSettingsEditor *get_project_settings() { return project_settings; }
diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp
index b71a3944fc..98b5ec7d56 100644
--- a/editor/editor_plugin.cpp
+++ b/editor/editor_plugin.cpp
@@ -311,7 +311,7 @@ bool EditorInterface::is_distraction_free_mode_enabled() const {
}
EditorCommandPalette *EditorInterface::get_command_palette() const {
- return EditorNode::get_singleton()->get_editor_command_palette();
+ return EditorCommandPalette::get_singleton();
}
EditorInterface *EditorInterface::singleton = nullptr;
diff --git a/editor/icons/GridLayout.svg b/editor/icons/GridLayout.svg
index 71ad504477..f05bc239a9 100644
--- a/editor/icons/GridLayout.svg
+++ b/editor/icons/GridLayout.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m14 2.1992188v2.6152343l-2.625 1.3125v-2.6152343zm-12 4.0644531 2.625 1.3125v2.5507811l-2.625-1.3124999zm12 0v2.5507812l-2.625 1.3124999v-2.5507811zm-8 1.4550781h4v2.640625h-4zm-4 2.560547 2.625 1.3125v2.521484l-2.625-1.3125zm12 0v2.521484l-2.625 1.3125v-2.521484zm-8 1.455078h4v2.640625h-4zm1.7014535-8.109375h2.2985465v2.734375h-4.15625s-.7487346.647119-.8746377.640625c-.1310411-.0067594-1.5097373-1.4558594-1.5097373-1.4558594l-1.459375-.7296875v-2.6152343l.068419.034223s.026411-.4573464.062111-.6760553c.0346282-.2121439.1970747-.59225724.1970747-.59225724l-1.0483078-.52372301c-.0795772-.04012218-.1668141-.06276382-.2558594-.06640625-.35427845-.01325803-.64865004.27047362-.6484375.625v12c.00021484.236623.13402736.45284.34570312.558594l3.99999998 2c.086686.043505.1823067.06624.2792969.066406h6c.09699-.000166.192611-.0229.279297-.06641l4-2c.211676-.10575.345488-.321967.345703-.55859v-12c-.000468-.46423753-.488958-.76598317-.904297-.55859375l-3.869141 1.93359375h-2.9709527s.033448.4166167.015891.625c-.029188.3464401-.1950466.625-.1950468.625z" fill="#b05b5b"/><path d="m5 6s-2.21875-2.1616704-2.21875-3.2425057c0-1.0808352 0-2.6072392 2.21875-2.6072392s2.21875 1.526404 2.21875 2.6072392c0 1.0808353-2.21875 3.2425057-2.21875 3.2425057z" fill="#fff" fill-opacity=".68627"/></svg>
+<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="1.5" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="#e0e0e0" stroke-width="1.3"><path d="m1.87 6.54123h2.917v2.917h-2.917z"/><path d="m6.53582 6.54123h2.917v2.917h-2.917z"/><path d="m11.20164 6.54123h2.917v2.917h-2.917z"/><g transform="matrix(.99999939 .00000001 -.00000005 1.00000043 -.000003 .000001)"><path d="m5.432 1.112-1.95 1.95 1.95 1.95" stroke-linejoin="miter" stroke-miterlimit="10"/><path d="m3.482 3.062h9.386"/></g><g transform="matrix(.99999939 .00000001 -.00000005 1.00000043 0 -.000005)"><path d="m10.731 11.112 1.95 1.95-1.95 1.95" stroke-linejoin="miter" stroke-miterlimit="10"/><path d="m3.294 13.062h9.387"/></g></g></svg>
diff --git a/editor/icons/VisualScriptComment.svg b/editor/icons/VisualScriptComment.svg
new file mode 100644
index 0000000000..3887853b58
--- /dev/null
+++ b/editor/icons/VisualScriptComment.svg
@@ -0,0 +1 @@
+<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg"><path d="m3 1v2h-2v2h2v4h-2v2h2v2h2v-2h4v2h2v-2h2v-2h-2v-4h2v-2h-2v-2h-2v2h-4v-2zm2 4h4v4h-4z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/VisualScriptExpression.svg b/editor/icons/VisualScriptExpression.svg
new file mode 100644
index 0000000000..d6a3c2d9a8
--- /dev/null
+++ b/editor/icons/VisualScriptExpression.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="m4.859536 3.0412379c-2.0539867 0-3.7190721 1.6650852-3.7190721 3.719072v6.1984521h2.4793814v-2.479381h2.4793814v-2.4793803h-2.4793814v-1.2396908c0-.6846622.5550285-1.2396907 1.2396907-1.2396907h1.2396907v-2.4793813z"/><path d="m7.5889175 3.0000003 2.5000005 4.9999997-2.5000005 5h2.5000005l1.135249-2.727 1.36475 2.727h2.499999l-2.499999-5 2.499999-4.9999997h-2.499999l-1.13525 2.7269998-1.364749-2.7269998zm7.4999985 9.9999997v-6.25z"/></g></svg>
diff --git a/editor/icons/VisualShaderGraphTextureUniform.svg b/editor/icons/VisualShaderGraphTextureUniform.svg
new file mode 100644
index 0000000000..ed9e084fd3
--- /dev/null
+++ b/editor/icons/VisualShaderGraphTextureUniform.svg
@@ -0,0 +1 @@
+<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg"><path d="m2 0c-1.1045695 0-2 .8954-2 2v10c0 1.1046.8954305 2 2 2h10c1.104569 0 2-.8954 2-2v-10c0-1.1046-.895431-2-2-2zm0 2h10v10h-10zm9 2-4 4-2-2-2 3h8z" fill="#eae068"/></svg>
diff --git a/editor/icons/VisualShaderNodeBooleanUniform.svg b/editor/icons/VisualShaderNodeBooleanUniform.svg
new file mode 100644
index 0000000000..b4a7043fb3
--- /dev/null
+++ b/editor/icons/VisualShaderNodeBooleanUniform.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 .02734375c-1.108 0-2 .892-2 2.00000005v1.9726562h2v2a3 3 0 0 1 2.5 1.3457031 3 3 0 0 1 2.5-1.3457031 3 3 0 0 1 2 .7675781 3 3 0 0 1 2-.7675781 3 3 0 0 1 2 .7695312v-2.7695312h2v5a1 1 0 0 0 1 1v-7.9726562c0-1.10800005-.892-2.00000005-2-2.00000005zm0 7.97265625v2a1 1 0 0 0 1-1 1 1 0 0 0 -1-1zm5 0a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1zm4 0a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1zm-6.5 2.654297a3 3 0 0 1 -2.5 1.345703h-2v2.027344c0 1.108.892 2 2 2h12c1.108 0 2-.892 2-2v-2.027344a3 3 0 0 1 -2.5-1.345703 3 3 0 0 1 -2.5 1.345703 3 3 0 0 1 -2-.767578 3 3 0 0 1 -2 .767578 3 3 0 0 1 -2.5-1.345703z" fill="#6f91f0" stroke-linecap="square" stroke-opacity=".75" stroke-width="2"/></svg>
diff --git a/editor/icons/VisualShaderNodeColorConstant.svg b/editor/icons/VisualShaderNodeColorConstant.svg
new file mode 100644
index 0000000000..cbc5b3a471
--- /dev/null
+++ b/editor/icons/VisualShaderNodeColorConstant.svg
@@ -0,0 +1 @@
+<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg"><g fill-opacity=".392157" transform="translate(0 -1038.3622)"><path d="m7 1039.3622a4.0000172 4.0000172 0 0 0 -4 4 4.0000172 4.0000172 0 0 0 .03906.5195 4.0000172 4.0000172 0 0 0 -2.039062 3.4805 4.0000172 4.0000172 0 0 0 4 4 4.0000172 4.0000172 0 0 0 1.998047-.541 4.0000172 4.0000172 0 0 0 2.001953.541 4.0000172 4.0000172 0 0 0 4-4 4.0000172 4.0000172 0 0 0 -2.037109-3.4824 4.0000172 4.0000172 0 0 0 .03711-.5176 4.0000172 4.0000172 0 0 0 -4-4z" fill="#fff"/><path d="m7 1040.3622a3 3 0 0 0 -3 3 3 3 0 0 0 .210937 1.1055 3 3 0 0 0 -2.210937 2.8945 3 3 0 0 0 3 3 3 3 0 0 0 2-.7676 3 3 0 0 0 2 .7676 3 3 0 0 0 3-3 3 3 0 0 0 -2.2148438-2.8906 3 3 0 0 0 .2148438-1.1094 3 3 0 0 0 -3-3z" fill="#fff"/><circle cx="7" cy="1043.3622" fill="#f00" r="3"/><circle cx="5" cy="1047.3622" fill="#00f" r="3"/><circle cx="9" cy="1047.3622" fill="#0f0" r="3"/><circle cx="7" cy="1043.3622" fill="#f00" r="3"/><circle cx="5" cy="1047.3622" fill="#00f" r="3"/><circle cx="9" cy="1047.3622" fill="#0f0" r="3"/></g></svg>
diff --git a/editor/icons/VisualShaderNodeColorOp.svg b/editor/icons/VisualShaderNodeColorOp.svg
new file mode 100644
index 0000000000..7b6cd8149b
--- /dev/null
+++ b/editor/icons/VisualShaderNodeColorOp.svg
@@ -0,0 +1 @@
+<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1038.3622)"><g fill="#fff"><path d="m4 1050.3622h6v-10h-6z" fill-rule="evenodd" stroke="#fff" stroke-linejoin="round" stroke-width="2"/><path d="m1 1041.3622h2v2h-2z"/><path d="m1 1047.3622h2v2h-2z"/><path d="m11 1044.3622h2v2h-2z"/></g><g fill-opacity=".862745"><path d="m5 1041.3622h4v2h-4z" fill="#ff4646"/><path d="m5 1044.3622h4v2h-4z" fill="#46ff46"/><path d="m5 1047.3622h4v2h-4z" fill="#4646ff"/></g></g></svg>
diff --git a/editor/icons/VisualShaderNodeColorUniform.svg b/editor/icons/VisualShaderNodeColorUniform.svg
new file mode 100644
index 0000000000..ce89b16583
--- /dev/null
+++ b/editor/icons/VisualShaderNodeColorUniform.svg
@@ -0,0 +1 @@
+<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1038.3622)"><path d="m2 1038.3622c-1.10457 0-2 .8954-2 2v10c0 1.1046.89543 2 2 2h10c1.104569 0 2-.8954 2-2v-10c0-1.1046-.895431-2-2-2z" fill="#fff"/><g fill-opacity=".392157"><path d="m7 2a3 3 0 0 0 -3 3 3 3 0 0 0 .2109375 1.1054688 3 3 0 0 0 -2.2109375 2.8945312 3 3 0 0 0 3 3 3 3 0 0 0 2-.767578 3 3 0 0 0 2 .767578 3 3 0 0 0 3-3 3 3 0 0 0 -2.2148438-2.890625 3 3 0 0 0 .2148438-1.109375 3 3 0 0 0 -3-3z" fill="#fff" transform="translate(0 1038.3622)"/><circle cx="7" cy="1043.3622" fill="#f00" r="3"/><circle cx="5" cy="1047.3622" fill="#00f" r="3"/><circle cx="9" cy="1047.3622" fill="#0f0" r="3"/><circle cx="7" cy="1043.3622" fill="#f00" r="3"/><circle cx="5" cy="1047.3622" fill="#00f" r="3"/><circle cx="9" cy="1047.3622" fill="#0f0" r="3"/></g></g></svg>
diff --git a/editor/icons/VisualShaderNodeComment.svg b/editor/icons/VisualShaderNodeComment.svg
new file mode 100644
index 0000000000..3887853b58
--- /dev/null
+++ b/editor/icons/VisualShaderNodeComment.svg
@@ -0,0 +1 @@
+<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg"><path d="m3 1v2h-2v2h2v4h-2v2h2v2h2v-2h4v2h2v-2h2v-2h-2v-4h2v-2h-2v-2h-2v2h-4v-2zm2 4h4v4h-4z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/VisualShaderNodeCubemap.svg b/editor/icons/VisualShaderNodeCubemap.svg
new file mode 100644
index 0000000000..fecb4d1287
--- /dev/null
+++ b/editor/icons/VisualShaderNodeCubemap.svg
@@ -0,0 +1 @@
+<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg"><path d="m7 3.5136719-2.6894531 1.34375 2.6894531 1.34375 2.6894531-1.34375zm-3.5722656 2.4980469v2.6894531l2.8574218 1.4277341v-2.6874998zm7.1445316 0-2.8574222 1.4296874v2.6874998l2.8574222-1.4277341z" fill="#eac968"/></svg>
diff --git a/editor/icons/VisualShaderNodeCubemapUniform.svg b/editor/icons/VisualShaderNodeCubemapUniform.svg
new file mode 100644
index 0000000000..e3463de0a2
--- /dev/null
+++ b/editor/icons/VisualShaderNodeCubemapUniform.svg
@@ -0,0 +1 @@
+<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg"><path d="m2 0c-1.1045695 0-2 .8954-2 2v10c0 1.1046.8954305 2 2 2h10c1.104569 0 2-.8954 2-2v-10c0-1.1046-.895431-2-2-2zm4.9726562 2a.71438238.71438238 0 0 1 .3476563.0742188l4.2851565 2.1425781a.71438238.71438238 0 0 1 .394531.640625v4.2851562a.71438238.71438238 0 0 1 -.394531.6386719l-4.2851565 2.142578a.71438238.71438238 0 0 1 -.640625 0l-4.2851563-2.142578a.71438238.71438238 0 0 1 -.3945312-.6386719v-4.2851562a.71438238.71438238 0 0 1 .3945312-.640625l4.2851563-2.1425781a.71438238.71438238 0 0 1 .2929687-.0742188zm.0273438 1.5136719-2.6894531 1.34375 2.6894531 1.34375 2.6894531-1.34375zm-3.5722656 2.4980469v2.6894531l2.8574218 1.4277341v-2.6874998zm7.1445316 0-2.8574222 1.4296874v2.6874998l2.8574222-1.4277341z" fill="#eac968"/></svg>
diff --git a/editor/icons/VisualShaderNodeCurveTexture.svg b/editor/icons/VisualShaderNodeCurveTexture.svg
new file mode 100644
index 0000000000..c0ee634ca4
--- /dev/null
+++ b/editor/icons/VisualShaderNodeCurveTexture.svg
@@ -0,0 +1 @@
+<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1038.3622)"><path d="m2 1049.3622c8 0 9 0 9-9" fill="none" stroke="#f6f6f6" stroke-linecap="round" stroke-width="2"/><path d="m11 4a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm-5 5a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2z" fill="#68d0ea" transform="translate(0 1038.3622)"/></g></svg>
diff --git a/editor/icons/VisualShaderNodeCurveXYZTexture.svg b/editor/icons/VisualShaderNodeCurveXYZTexture.svg
new file mode 100644
index 0000000000..c0ee634ca4
--- /dev/null
+++ b/editor/icons/VisualShaderNodeCurveXYZTexture.svg
@@ -0,0 +1 @@
+<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1038.3622)"><path d="m2 1049.3622c8 0 9 0 9-9" fill="none" stroke="#f6f6f6" stroke-linecap="round" stroke-width="2"/><path d="m11 4a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm-5 5a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2z" fill="#68d0ea" transform="translate(0 1038.3622)"/></g></svg>
diff --git a/editor/icons/VisualShaderNodeExpression.svg b/editor/icons/VisualShaderNodeExpression.svg
new file mode 100644
index 0000000000..8a930d4078
--- /dev/null
+++ b/editor/icons/VisualShaderNodeExpression.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#ac73f1"><path d="m4.859536 3.0412379c-2.0539867 0-3.7190721 1.6650852-3.7190721 3.719072v6.1984521h2.4793814v-2.479381h2.4793814v-2.4793803h-2.4793814v-1.2396908c0-.6846622.5550285-1.2396907 1.2396907-1.2396907h1.2396907v-2.4793813z"/><path d="m7.5889175 3.0000003 2.5000005 4.9999997-2.5000005 5h2.5000005l1.135249-2.727 1.36475 2.727h2.499999l-2.499999-5 2.499999-4.9999997h-2.499999l-1.13525 2.7269998-1.364749-2.7269998zm7.4999985 9.9999997v-6.25z"/></g></svg>
diff --git a/editor/icons/VisualShaderNodeFloatFunc.svg b/editor/icons/VisualShaderNodeFloatFunc.svg
new file mode 100644
index 0000000000..382c4e66af
--- /dev/null
+++ b/editor/icons/VisualShaderNodeFloatFunc.svg
@@ -0,0 +1 @@
+<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg"><g fill="#cf68ea" transform="translate(0 -1038.3622)"><path d="m6 1042.3622h2v4.999982h-2z"/><path d="m9.0703125 1a3 3 0 0 0 -1.5703125.4023438 3 3 0 0 0 -1.5 2.5976562h2a1 1 0 0 1 1-1 1 1 0 0 1 1 1h2a3 3 0 0 0 -1.5-2.5976562 3 3 0 0 0 -1.4296875-.4023438z" transform="translate(0 1038.3622)"/><path d="m10 1042.3622h2v1.000017h-2z"/><path d="m2 10a3 3 0 0 0 1.5 2.597656 3 3 0 0 0 3 0 3 3 0 0 0 1.5-2.597656h-2a1 1 0 0 1 -1 1 1 1 0 0 1 -1-1z" transform="translate(0 1038.3622)"/><path d="m6-1048.3622h2v1.000017h-2z" transform="scale(1 -1)"/><path d="m4 1044.3622h6v2h-6z"/></g></svg>
diff --git a/editor/icons/VisualShaderNodeFloatOp.svg b/editor/icons/VisualShaderNodeFloatOp.svg
new file mode 100644
index 0000000000..546ffc148e
--- /dev/null
+++ b/editor/icons/VisualShaderNodeFloatOp.svg
@@ -0,0 +1 @@
+<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg"><g fill="#cf68ea" transform="translate(0 -1038.3622)"><path d="m4 1c-.5522619.0001-.9999448.4477-1 1v10c.0000552.5523.4477381.9999 1 1h6c.552262-.0001.999945-.4477 1-1v-10c-.000055-.5523-.447738-.9999-1-1zm1 3 4 3-4 3z" fill-rule="evenodd" transform="translate(0 1038.3622)"/><path d="m1 1041.3622h2v2h-2z"/><path d="m1 1047.3622h2v2h-2z"/><path d="m11 1044.3622h2v2h-2z"/></g></svg>
diff --git a/editor/icons/VisualShaderNodeFloatUniform.svg b/editor/icons/VisualShaderNodeFloatUniform.svg
new file mode 100644
index 0000000000..dda5d098a3
--- /dev/null
+++ b/editor/icons/VisualShaderNodeFloatUniform.svg
@@ -0,0 +1 @@
+<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg"><path d="m2 0a2 2 0 0 0 -2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-10a2 2 0 0 0 -2-2zm4 2h5v2h-5a1.0000174 1.0000174 0 0 0 -1 1 1.0000174 1.0000174 0 0 0 1 1h2c1.6568542 0 3 1.3431 3 3s-1.3431458 3-3 3h-5v-2h5a1.0000174 1.0000174 0 0 0 1-1 1.0000174 1.0000174 0 0 0 -1-1h-2c-1.6568542 0-3-1.3431-3-3s1.3431458-3 3-3z" fill="#cf68ea"/></svg>
diff --git a/editor/icons/VisualShaderNodeGlobalExpression.svg b/editor/icons/VisualShaderNodeGlobalExpression.svg
new file mode 100644
index 0000000000..0cafffb152
--- /dev/null
+++ b/editor/icons/VisualShaderNodeGlobalExpression.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#35d4f4"><path d="m4.859536 3.0412379c-2.0539867 0-3.7190721 1.6650852-3.7190721 3.719072v6.1984521h2.4793814v-2.479381h2.4793814v-2.4793803h-2.4793814v-1.2396908c0-.6846622.5550285-1.2396907 1.2396907-1.2396907h1.2396907v-2.4793813z"/><path d="m7.5889175 3.0000003 2.5000005 4.9999997-2.5000005 5h2.5000005l1.135249-2.727 1.36475 2.727h2.499999l-2.499999-5 2.499999-4.9999997h-2.499999l-1.13525 2.7269998-1.364749-2.7269998zm7.4999985 9.9999997v-6.25z"/></g></svg>
diff --git a/editor/icons/VisualShaderNodeInput.svg b/editor/icons/VisualShaderNodeInput.svg
new file mode 100644
index 0000000000..ec347100d7
--- /dev/null
+++ b/editor/icons/VisualShaderNodeInput.svg
@@ -0,0 +1 @@
+<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg"><circle cx="7" cy="7" fill="#f6f6f6" r="6"/></svg>
diff --git a/editor/icons/VisualShaderNodeIntFunc.svg b/editor/icons/VisualShaderNodeIntFunc.svg
new file mode 100644
index 0000000000..382c4e66af
--- /dev/null
+++ b/editor/icons/VisualShaderNodeIntFunc.svg
@@ -0,0 +1 @@
+<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg"><g fill="#cf68ea" transform="translate(0 -1038.3622)"><path d="m6 1042.3622h2v4.999982h-2z"/><path d="m9.0703125 1a3 3 0 0 0 -1.5703125.4023438 3 3 0 0 0 -1.5 2.5976562h2a1 1 0 0 1 1-1 1 1 0 0 1 1 1h2a3 3 0 0 0 -1.5-2.5976562 3 3 0 0 0 -1.4296875-.4023438z" transform="translate(0 1038.3622)"/><path d="m10 1042.3622h2v1.000017h-2z"/><path d="m2 10a3 3 0 0 0 1.5 2.597656 3 3 0 0 0 3 0 3 3 0 0 0 1.5-2.597656h-2a1 1 0 0 1 -1 1 1 1 0 0 1 -1-1z" transform="translate(0 1038.3622)"/><path d="m6-1048.3622h2v1.000017h-2z" transform="scale(1 -1)"/><path d="m4 1044.3622h6v2h-6z"/></g></svg>
diff --git a/editor/icons/VisualShaderNodeIntOp.svg b/editor/icons/VisualShaderNodeIntOp.svg
new file mode 100644
index 0000000000..546ffc148e
--- /dev/null
+++ b/editor/icons/VisualShaderNodeIntOp.svg
@@ -0,0 +1 @@
+<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg"><g fill="#cf68ea" transform="translate(0 -1038.3622)"><path d="m4 1c-.5522619.0001-.9999448.4477-1 1v10c.0000552.5523.4477381.9999 1 1h6c.552262-.0001.999945-.4477 1-1v-10c-.000055-.5523-.447738-.9999-1-1zm1 3 4 3-4 3z" fill-rule="evenodd" transform="translate(0 1038.3622)"/><path d="m1 1041.3622h2v2h-2z"/><path d="m1 1047.3622h2v2h-2z"/><path d="m11 1044.3622h2v2h-2z"/></g></svg>
diff --git a/editor/icons/VisualShaderNodeIntUniform.svg b/editor/icons/VisualShaderNodeIntUniform.svg
new file mode 100644
index 0000000000..dda5d098a3
--- /dev/null
+++ b/editor/icons/VisualShaderNodeIntUniform.svg
@@ -0,0 +1 @@
+<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg"><path d="m2 0a2 2 0 0 0 -2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-10a2 2 0 0 0 -2-2zm4 2h5v2h-5a1.0000174 1.0000174 0 0 0 -1 1 1.0000174 1.0000174 0 0 0 1 1h2c1.6568542 0 3 1.3431 3 3s-1.3431458 3-3 3h-5v-2h5a1.0000174 1.0000174 0 0 0 1-1 1.0000174 1.0000174 0 0 0 -1-1h-2c-1.6568542 0-3-1.3431-3-3s1.3431458-3 3-3z" fill="#cf68ea"/></svg>
diff --git a/editor/icons/VisualShaderNodeTexture2DUniformTriplanar.svg b/editor/icons/VisualShaderNodeTexture2DUniformTriplanar.svg
new file mode 100644
index 0000000000..ed9e084fd3
--- /dev/null
+++ b/editor/icons/VisualShaderNodeTexture2DUniformTriplanar.svg
@@ -0,0 +1 @@
+<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg"><path d="m2 0c-1.1045695 0-2 .8954-2 2v10c0 1.1046.8954305 2 2 2h10c1.104569 0 2-.8954 2-2v-10c0-1.1046-.895431-2-2-2zm0 2h10v10h-10zm9 2-4 4-2-2-2 3h8z" fill="#eae068"/></svg>
diff --git a/editor/icons/VisualShaderNodeTransformCompose.svg b/editor/icons/VisualShaderNodeTransformCompose.svg
new file mode 100644
index 0000000000..6c7b28cda3
--- /dev/null
+++ b/editor/icons/VisualShaderNodeTransformCompose.svg
@@ -0,0 +1 @@
+<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="1.000747" x2="13.014989" y1="1045.3622" y2="1045.3622"><stop offset="0" stop-color="#b8ea68"/><stop offset="1" stop-color="#ea686c"/></linearGradient><path d="m1.9909808 1039.3524a1.0001 1.0001 0 0 0 -.697265 1.7168l3.2929683 3.293h-2.5859373a1.0001 1.0001 0 1 0 0 2h2.5859373l-3.2929683 3.293a1.0001 1.0001 0 1 0 1.414062 1.414l4.7070313-4.707h4.5859379a1.0001 1.0001 0 1 0 0-2h-4.5859379l-4.7070313-4.707a1.0001 1.0001 0 0 0 -.716797-.3028z" fill="url(#a)" fill-rule="evenodd" transform="translate(0 -1038.3622)"/></svg>
diff --git a/editor/icons/VisualShaderNodeTransformDecompose.svg b/editor/icons/VisualShaderNodeTransformDecompose.svg
new file mode 100644
index 0000000000..276b3ea7c8
--- /dev/null
+++ b/editor/icons/VisualShaderNodeTransformDecompose.svg
@@ -0,0 +1 @@
+<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientTransform="matrix(-1 0 0 1 13.999754 1038.3622)" gradientUnits="userSpaceOnUse" x1="1" x2="13.014242" y1="7" y2="7"><stop offset="0" stop-color="#b8ea68"/><stop offset="1" stop-color="#ea686c"/></linearGradient><path d="m12.00952 1039.3524a1.0001 1.0001 0 0 1 .697265 1.7168l-3.2929683 3.293h2.5859373a1.0001 1.0001 0 1 1 0 2h-2.5859373l3.2929683 3.293a1.0001 1.0001 0 1 1 -1.414062 1.414l-4.7070313-4.707h-4.5859377a1.0001 1.0001 0 1 1 0-2h4.5859377l4.7070313-4.707a1.0001 1.0001 0 0 1 .716797-.3028z" fill="url(#a)" fill-rule="evenodd" transform="translate(0 -1038.3622)"/></svg>
diff --git a/editor/icons/VisualShaderNodeTransformUniform.svg b/editor/icons/VisualShaderNodeTransformUniform.svg
new file mode 100644
index 0000000000..5d3e6977e0
--- /dev/null
+++ b/editor/icons/VisualShaderNodeTransformUniform.svg
@@ -0,0 +1 @@
+<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg"><path d="m2 0c-1.1045695 0-2 .8954-2 2v10c0 1.1046.8954305 2 2 2h10c1.104569 0 2-.8954 2-2v-10c0-1.1046-.895431-2-2-2zm-1 1h1 2v1h-2v10h2v1h-2-1v-1-10zm9 0h3v11 1h-3v-1h2v-10h-2zm-.0292969 2a1.0001 1.0001 0 0 1 1.0292969 1v7h-2v-4.5859375l-1.2929688 1.2929687a1.0001 1.0001 0 0 1 -1.4140624 0l-1.2929688-1.2929687v4.5859375h-2v-7a1.0001 1.0001 0 0 1 .984375-.9980469 1.0001 1.0001 0 0 1 .7226562.2910157l2.2929688 2.2929687 2.2929688-2.2929687a1.0001 1.0001 0 0 1 .6777343-.2929688z" fill="#ea686c"/></svg>
diff --git a/editor/icons/VisualShaderNodeTransformVecMult.svg b/editor/icons/VisualShaderNodeTransformVecMult.svg
new file mode 100644
index 0000000000..fe133b6ffe
--- /dev/null
+++ b/editor/icons/VisualShaderNodeTransformVecMult.svg
@@ -0,0 +1 @@
+<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1038.3622)"><path d="m9 1042.3622 2 6 2-6" fill="none" stroke="#b8ea68" stroke-linejoin="round" stroke-width="2"/><circle cx="7" cy="1046.3622" fill="#b8ea68" r="1"/><path d="m1 1049.3621v-7l2 3 2-3v7" fill="none" stroke="#ea686c" stroke-linejoin="round" stroke-width="2"/></g></svg>
diff --git a/editor/icons/VisualShaderNodeVec3Uniform.svg b/editor/icons/VisualShaderNodeVec3Uniform.svg
new file mode 100644
index 0000000000..6e0175230c
--- /dev/null
+++ b/editor/icons/VisualShaderNodeVec3Uniform.svg
@@ -0,0 +1 @@
+<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg"><path d="m2 0c-1.1045695 0-2 .8954305-2 2v10c0 1.104569.8954305 2 2 2h10c1.104569 0 2-.895431 2-2v-10c0-1.1045695-.895431-2-2-2zm6 0 3 3-3 3v-2h-5v-2h5zm-3.65625 5.6289062.5136719.8574219 2.1425781 3.5703129 2.1425781-3.5703129.5136719-.8574219 1.714844 1.0292969-.513672.8574219-3.0000001 5c-.3885014.647055-1.3263424.647055-1.7148438 0l-3-5-.5136719-.8574219z" fill="#b8ea68"/><path d="m23 0v2h-5v2h5v2l3-3zm-3.65625 5.6289062-1.714844 1.0292969.513672.8574219 3 5c.388501.647056 1.326343.647056 1.714844 0l3-5 .513672-.8574219-1.714844-1.0292969-.513672.8574219-2.142578 3.5703129-2.142578-3.5703129z" fill-rule="evenodd"/></svg>
diff --git a/editor/icons/VisualShaderNodeVectorCompose.svg b/editor/icons/VisualShaderNodeVectorCompose.svg
new file mode 100644
index 0000000000..8e12ab2ff6
--- /dev/null
+++ b/editor/icons/VisualShaderNodeVectorCompose.svg
@@ -0,0 +1 @@
+<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="1" x2="13.014242" y1="7" y2="7"><stop offset="0" stop-color="#cf68ea"/><stop offset="1" stop-color="#b8ea68"/></linearGradient><path d="m1.9902344.99023438a1.0001 1.0001 0 0 0 -.6972656 1.71679682l3.2929687 3.2929688h-2.5859375a1.0001 1.0001 0 1 0 0 2h2.5859375l-3.2929687 3.292969a1.0001 1.0001 0 1 0 1.4140624 1.414062l4.7070313-4.707031h4.5859375a1.0001 1.0001 0 1 0 0-2h-4.5859375l-4.7070313-4.7070312a1.0001 1.0001 0 0 0 -.7167968-.30273442z" fill="url(#a)" fill-rule="evenodd"/></svg>
diff --git a/editor/icons/VisualShaderNodeVectorDecompose.svg b/editor/icons/VisualShaderNodeVectorDecompose.svg
new file mode 100644
index 0000000000..4bd2dc2138
--- /dev/null
+++ b/editor/icons/VisualShaderNodeVectorDecompose.svg
@@ -0,0 +1 @@
+<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientTransform="matrix(-1 0 0 1 13.999754 1038.3622)" gradientUnits="userSpaceOnUse" x1="1" x2="13.014242" y1="7" y2="7"><stop offset="0" stop-color="#cf68ea"/><stop offset="1" stop-color="#b8ea68"/></linearGradient><path d="m12.00952 1039.3524a1.0001 1.0001 0 0 1 .697265 1.7168l-3.2929685 3.293h2.5859375a1.0001 1.0001 0 1 1 0 2h-2.5859375l3.2929685 3.293a1.0001 1.0001 0 1 1 -1.414062 1.414l-4.7070315-4.707h-4.5859375a1.0001 1.0001 0 1 1 0-2h4.5859375l4.7070315-4.707a1.0001 1.0001 0 0 1 .716797-.3028z" fill="url(#a)" fill-rule="evenodd" transform="translate(0 -1038.3622)"/></svg>
diff --git a/editor/icons/VisualShaderNodeVectorDistance.svg b/editor/icons/VisualShaderNodeVectorDistance.svg
new file mode 100644
index 0000000000..74a46047bf
--- /dev/null
+++ b/editor/icons/VisualShaderNodeVectorDistance.svg
@@ -0,0 +1 @@
+<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg"><path d="m2 1050.3622 10-10" fill="none" stroke="#b8ea68" stroke-linecap="round" stroke-width="2" transform="translate(0 -1038.3622)"/></svg>
diff --git a/editor/icons/VisualShaderNodeVectorFunc.svg b/editor/icons/VisualShaderNodeVectorFunc.svg
new file mode 100644
index 0000000000..dcd4cee3e4
--- /dev/null
+++ b/editor/icons/VisualShaderNodeVectorFunc.svg
@@ -0,0 +1 @@
+<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg"><g fill="#b8ea68" transform="translate(0 -1038.3622)"><path d="m6 1042.3622h2v4.999982h-2z"/><path d="m9.0703125 1a3 3 0 0 0 -1.5703125.4023438 3 3 0 0 0 -1.5 2.5976562h2a1 1 0 0 1 1-1 1 1 0 0 1 1 1h2a3 3 0 0 0 -1.5-2.5976562 3 3 0 0 0 -1.4296875-.4023438z" transform="translate(0 1038.3622)"/><path d="m10 1042.3622h2v1.000017h-2z"/><path d="m2 10a3 3 0 0 0 1.5 2.597656 3 3 0 0 0 3 0 3 3 0 0 0 1.5-2.597656h-2a1 1 0 0 1 -1 1 1 1 0 0 1 -1-1z" transform="translate(0 1038.3622)"/><path d="m6-1048.3622h2v1.000017h-2z" transform="scale(1 -1)"/><path d="m4 1044.3622h6v2h-6z"/></g></svg>
diff --git a/editor/icons/VisualShaderNodeVectorLen.svg b/editor/icons/VisualShaderNodeVectorLen.svg
new file mode 100644
index 0000000000..71faffdc3f
--- /dev/null
+++ b/editor/icons/VisualShaderNodeVectorLen.svg
@@ -0,0 +1 @@
+<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg"><path d="m8 1038.3614v2h-5v2h5v2l3-3zm-3.65625 5.6289-1.714844 1.0293.513672.8574 3 5c.388501.647 1.326343.647 1.714844 0l3-5 .513672-.8574-1.714844-1.0293-.513672.8574-2.142578 3.5703-2.142578-3.5703z" fill="#b8ea68" fill-rule="evenodd" transform="translate(0 -1038.3622)"/></svg>
diff --git a/editor/icons/LineShape2D.svg b/editor/icons/WorldMarginShape2D.svg
index f1dbe97c6f..f1dbe97c6f 100644
--- a/editor/icons/LineShape2D.svg
+++ b/editor/icons/WorldMarginShape2D.svg
diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp
index df01ecd1be..ef3b0588b8 100644
--- a/editor/plugins/abstract_polygon_2d_editor.cpp
+++ b/editor/plugins/abstract_polygon_2d_editor.cpp
@@ -261,7 +261,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event)
Transform2D xform = canvas_item_editor->get_canvas_transform() * _get_node()->get_global_transform();
Vector2 gpoint = mb->get_position();
- Vector2 cpoint = _get_node()->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mb->get_position())));
+ Vector2 cpoint = _get_node()->to_local(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mb->get_position())));
if (mode == MODE_EDIT || (_is_line() && mode == MODE_CREATE)) {
if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
@@ -396,7 +396,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event)
Vector2 gpoint = mm->get_position();
if (edited_point.valid() && (wip_active || (mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT))) {
- Vector2 cpoint = _get_node()->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint)));
+ Vector2 cpoint = _get_node()->to_local(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint)));
//Move the point in a single axis. Should only work when editing a polygon and while holding shift.
if (mode == MODE_EDIT && mm->is_shift_pressed()) {
diff --git a/editor/plugins/collision_shape_2d_editor_plugin.cpp b/editor/plugins/collision_shape_2d_editor_plugin.cpp
index 4266e0f676..486f947e43 100644
--- a/editor/plugins/collision_shape_2d_editor_plugin.cpp
+++ b/editor/plugins/collision_shape_2d_editor_plugin.cpp
@@ -36,9 +36,9 @@
#include "scene/resources/circle_shape_2d.h"
#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/rectangle_shape_2d.h"
#include "scene/resources/segment_shape_2d.h"
+#include "scene/resources/world_margin_shape_2d.h"
void CollisionShape2DEditor::_node_removed(Node *p_node) {
if (p_node == node) {
@@ -74,8 +74,8 @@ Variant CollisionShape2DEditor::get_handle_value(int idx) const {
case CONVEX_POLYGON_SHAPE: {
} break;
- case LINE_SHAPE: {
- Ref<LineShape2D> line = node->get_shape();
+ case WORLD_MARGIN_SHAPE: {
+ Ref<WorldMarginShape2D> line = node->get_shape();
if (idx == 0) {
return line->get_distance();
@@ -142,9 +142,9 @@ void CollisionShape2DEditor::set_handle(int idx, Point2 &p_point) {
case CONVEX_POLYGON_SHAPE: {
} break;
- case LINE_SHAPE: {
+ case WORLD_MARGIN_SHAPE: {
if (idx < 2) {
- Ref<LineShape2D> line = node->get_shape();
+ Ref<WorldMarginShape2D> line = node->get_shape();
if (idx == 0) {
line->set_distance(p_point.length());
@@ -241,8 +241,8 @@ void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) {
// Cannot be edited directly, use CollisionPolygon2D instead.
} break;
- case LINE_SHAPE: {
- Ref<LineShape2D> line = node->get_shape();
+ case WORLD_MARGIN_SHAPE: {
+ Ref<WorldMarginShape2D> line = node->get_shape();
if (idx == 0) {
undo_redo->add_do_method(line.ptr(), "set_distance", line->get_distance());
@@ -397,8 +397,8 @@ void CollisionShape2DEditor::_get_current_shape_type() {
shape_type = CONCAVE_POLYGON_SHAPE;
} else if (Object::cast_to<ConvexPolygonShape2D>(*s)) {
shape_type = CONVEX_POLYGON_SHAPE;
- } else if (Object::cast_to<LineShape2D>(*s)) {
- shape_type = LINE_SHAPE;
+ } else if (Object::cast_to<WorldMarginShape2D>(*s)) {
+ shape_type = WORLD_MARGIN_SHAPE;
} else if (Object::cast_to<RectangleShape2D>(*s)) {
shape_type = RECTANGLE_SHAPE;
} else if (Object::cast_to<SegmentShape2D>(*s)) {
@@ -464,8 +464,8 @@ void CollisionShape2DEditor::forward_canvas_draw_over_viewport(Control *p_overla
case CONVEX_POLYGON_SHAPE: {
} break;
- case LINE_SHAPE: {
- Ref<LineShape2D> shape = node->get_shape();
+ case WORLD_MARGIN_SHAPE: {
+ Ref<WorldMarginShape2D> shape = node->get_shape();
handles.resize(2);
handles.write[0] = shape->get_normal() * shape->get_distance();
diff --git a/editor/plugins/collision_shape_2d_editor_plugin.h b/editor/plugins/collision_shape_2d_editor_plugin.h
index 130ec708cf..056e1b5b7d 100644
--- a/editor/plugins/collision_shape_2d_editor_plugin.h
+++ b/editor/plugins/collision_shape_2d_editor_plugin.h
@@ -46,7 +46,7 @@ class CollisionShape2DEditor : public Control {
CIRCLE_SHAPE,
CONCAVE_POLYGON_SHAPE,
CONVEX_POLYGON_SHAPE,
- LINE_SHAPE,
+ WORLD_MARGIN_SHAPE,
RECTANGLE_SHAPE,
SEGMENT_SHAPE
};
diff --git a/editor/plugins/gpu_particles_2d_editor_plugin.cpp b/editor/plugins/gpu_particles_2d_editor_plugin.cpp
index efec5a709d..dd91df747a 100644
--- a/editor/plugins/gpu_particles_2d_editor_plugin.cpp
+++ b/editor/plugins/gpu_particles_2d_editor_plugin.cpp
@@ -60,13 +60,16 @@ void GPUParticles2DEditorPlugin::_file_selected(const String &p_file) {
void GPUParticles2DEditorPlugin::_menu_callback(int p_idx) {
switch (p_idx) {
case MENU_GENERATE_VISIBILITY_RECT: {
- double gen_time = particles->get_lifetime();
- if (gen_time < 1.0) {
- generate_seconds->set_value(1.0);
+ // Add one second to the default generation lifetime, since the progress is updated every second.
+ generate_seconds->set_value(MAX(1.0, trunc(particles->get_lifetime()) + 1.0));
+
+ if (generate_seconds->get_value() >= 11.0 + CMP_EPSILON) {
+ // Only pop up the time dialog if the particle's lifetime is long enough to warrant shortening it.
+ generate_visibility_rect->popup_centered();
} else {
- generate_seconds->set_value(trunc(gen_time) + 1.0);
+ // Generate the visibility rect immediately.
+ _generate_visibility_rect();
}
- generate_visibility_rect->popup_centered();
} break;
case MENU_LOAD_EMISSION_MASK: {
file->popup_file_dialog();
@@ -104,7 +107,7 @@ void GPUParticles2DEditorPlugin::_generate_visibility_rect() {
float running = 0.0;
- EditorProgress ep("gen_vrect", TTR("Generating Visibility Rect"), int(time));
+ EditorProgress ep("gen_vrect", TTR("Generating Visibility Rect (Waiting for Particle Simulation)"), int(time));
bool was_emitting = particles->is_emitting();
if (!was_emitting) {
diff --git a/editor/plugins/gpu_particles_3d_editor_plugin.cpp b/editor/plugins/gpu_particles_3d_editor_plugin.cpp
index fff25b6f59..903a3689b0 100644
--- a/editor/plugins/gpu_particles_3d_editor_plugin.cpp
+++ b/editor/plugins/gpu_particles_3d_editor_plugin.cpp
@@ -238,14 +238,16 @@ void GPUParticles3DEditor::_notification(int p_notification) {
void GPUParticles3DEditor::_menu_option(int p_option) {
switch (p_option) {
case MENU_OPTION_GENERATE_AABB: {
- float gen_time = node->get_lifetime();
+ // Add one second to the default generation lifetime, since the progress is updated every second.
+ generate_seconds->set_value(MAX(1.0, trunc(node->get_lifetime()) + 1.0));
- if (gen_time < 1.0) {
- generate_seconds->set_value(1.0);
+ if (generate_seconds->get_value() >= 11.0 + CMP_EPSILON) {
+ // Only pop up the time dialog if the particle's lifetime is long enough to warrant shortening it.
+ generate_aabb->popup_centered();
} else {
- generate_seconds->set_value(trunc(gen_time) + 1.0);
+ // Generate the visibility AABB immediately.
+ _generate_aabb();
}
- generate_aabb->popup_centered();
} break;
case MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_NODE: {
Ref<ParticlesMaterial> material = node->get_process_material();
@@ -286,7 +288,7 @@ void GPUParticles3DEditor::_generate_aabb() {
double running = 0.0;
- EditorProgress ep("gen_aabb", TTR("Generating AABB"), int(time));
+ EditorProgress ep("gen_aabb", TTR("Generating Visibility AABB (Waiting for Particle Simulation)"), int(time));
bool was_emitting = node->is_emitting();
if (!was_emitting) {
diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp
index dcea7b26f3..b93e12d7fa 100644
--- a/editor/plugins/node_3d_editor_gizmos.cpp
+++ b/editor/plugins/node_3d_editor_gizmos.cpp
@@ -2100,64 +2100,76 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
surface_tool->begin(Mesh::PRIMITIVE_LINES);
surface_tool->set_material(material);
- Vector<Transform3D> grests;
+ LocalVector<Transform3D> grests;
grests.resize(skel->get_bone_count());
- Vector<int> bones;
- Vector<float> weights;
+ LocalVector<int> bones;
+ LocalVector<real_t> weights;
bones.resize(4);
weights.resize(4);
for (int i = 0; i < 4; i++) {
- bones.write[i] = 0;
- weights.write[i] = 0;
+ bones[i] = 0;
+ weights[i] = 0;
}
- weights.write[0] = 1;
+ weights[0] = 1;
AABB aabb;
Color bonecolor = Color(1.0, 0.4, 0.4, 0.3);
Color rootcolor = Color(0.4, 1.0, 0.4, 0.1);
- for (int i_bone = 0; i_bone < skel->get_bone_count(); i_bone++) {
- int i = skel->get_process_order(i_bone);
+ //LocalVector<int> bones_to_process = skel->get_parentless_bones();
+ LocalVector<int> bones_to_process;
+ bones_to_process = skel->get_parentless_bones();
- int parent = skel->get_bone_parent(i);
+ while (bones_to_process.size() > 0) {
+ int current_bone_idx = bones_to_process[0];
+ bones_to_process.erase(current_bone_idx);
- if (parent >= 0) {
- grests.write[i] = grests[parent] * skel->get_bone_rest(i);
+ LocalVector<int> child_bones_vector;
+ child_bones_vector = skel->get_bone_children(current_bone_idx);
+ int child_bones_size = child_bones_vector.size();
- Vector3 v0 = grests[parent].origin;
- Vector3 v1 = grests[i].origin;
- Vector3 d = (v1 - v0).normalized();
- float dist = v0.distance_to(v1);
+ // You have children but no parent, then you must be a root/parentless bone.
+ if (child_bones_size >= 0 && skel->get_bone_parent(current_bone_idx) <= 0) {
+ grests[current_bone_idx] = skel->global_pose_to_local_pose(current_bone_idx, skel->get_bone_global_pose(current_bone_idx));
+ }
- //find closest axis
- int closest = -1;
- float closest_d = 0.0;
+ for (int i = 0; i < child_bones_size; i++) {
+ int child_bone_idx = child_bones_vector[i];
+ grests[child_bone_idx] = skel->global_pose_to_local_pose(child_bone_idx, skel->get_bone_global_pose(child_bone_idx));
+ Vector3 v0 = grests[current_bone_idx].origin;
+ Vector3 v1 = grests[child_bone_idx].origin;
+ Vector3 d = skel->get_bone_rest(child_bone_idx).origin.normalized();
+ real_t dist = skel->get_bone_rest(child_bone_idx).origin.length();
+
+ // Find closest axis.
+ int closest = -1;
+ real_t closest_d = 0.0;
for (int j = 0; j < 3; j++) {
- float dp = Math::abs(grests[parent].basis[j].normalized().dot(d));
+ real_t dp = Math::abs(grests[current_bone_idx].basis[j].normalized().dot(d));
if (j == 0 || dp > closest_d) {
closest = j;
}
}
- //find closest other
+ // Find closest other.
Vector3 first;
Vector3 points[4];
- int pointidx = 0;
+ int point_idx = 0;
for (int j = 0; j < 3; j++) {
- bones.write[0] = parent;
+ bones[0] = current_bone_idx;
surface_tool->set_bones(bones);
surface_tool->set_weights(weights);
surface_tool->set_color(rootcolor);
- surface_tool->add_vertex(v0 - grests[parent].basis[j].normalized() * dist * 0.05);
+ surface_tool->add_vertex(v0 - grests[current_bone_idx].basis[j].normalized() * dist * 0.05);
surface_tool->set_bones(bones);
surface_tool->set_weights(weights);
surface_tool->set_color(rootcolor);
- surface_tool->add_vertex(v0 + grests[parent].basis[j].normalized() * dist * 0.05);
+ surface_tool->add_vertex(v0 + grests[current_bone_idx].basis[j].normalized() * dist * 0.05);
if (j == closest) {
continue;
@@ -2165,7 +2177,7 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
Vector3 axis;
if (first == Vector3()) {
- axis = d.cross(d.cross(grests[parent].basis[j])).normalized();
+ axis = d.cross(d.cross(grests[current_bone_idx].basis[j])).normalized();
first = axis;
} else {
axis = d.cross(first).normalized();
@@ -2178,7 +2190,7 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
Vector3 point = v0 + d * dist * 0.2;
point += axis * dist * 0.1;
- bones.write[0] = parent;
+ bones[0] = current_bone_idx;
surface_tool->set_bones(bones);
surface_tool->set_weights(weights);
surface_tool->set_color(bonecolor);
@@ -2188,23 +2200,22 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
surface_tool->set_color(bonecolor);
surface_tool->add_vertex(point);
- bones.write[0] = parent;
+ bones[0] = current_bone_idx;
surface_tool->set_bones(bones);
surface_tool->set_weights(weights);
surface_tool->set_color(bonecolor);
surface_tool->add_vertex(point);
- bones.write[0] = i;
+ bones[0] = child_bone_idx;
surface_tool->set_bones(bones);
surface_tool->set_weights(weights);
surface_tool->set_color(bonecolor);
surface_tool->add_vertex(v1);
- points[pointidx++] = point;
+ points[point_idx++] = point;
}
}
-
SWAP(points[1], points[2]);
for (int j = 0; j < 4; j++) {
- bones.write[0] = parent;
+ bones[0] = current_bone_idx;
surface_tool->set_bones(bones);
surface_tool->set_weights(weights);
surface_tool->set_color(bonecolor);
@@ -2214,9 +2225,9 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
surface_tool->set_color(bonecolor);
surface_tool->add_vertex(points[(j + 1) % 4]);
}
- } else {
- grests.write[i] = skel->get_bone_rest(i);
- bones.write[0] = i;
+
+ // Add the bone's children to the list of bones to be processed.
+ bones_to_process.push_back(child_bones_vector[i]);
}
}
diff --git a/editor/plugins/node_3d_editor_gizmos.h b/editor/plugins/node_3d_editor_gizmos.h
index 64f46f2b1a..2cc0951557 100644
--- a/editor/plugins/node_3d_editor_gizmos.h
+++ b/editor/plugins/node_3d_editor_gizmos.h
@@ -31,6 +31,7 @@
#ifndef NODE_3D_EDITOR_GIZMOS_H
#define NODE_3D_EDITOR_GIZMOS_H
+#include "core/templates/local_vector.h"
#include "core/templates/ordered_hash_map.h"
#include "scene/3d/node_3d.h"
#include "scene/3d/skeleton_3d.h"
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 4b2db9bd70..4300a56ef0 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -811,18 +811,66 @@ void Node3DEditorViewport::_select_region() {
}
void Node3DEditorViewport::_update_name() {
- String view_mode = orthogonal ? TTR("Orthogonal") : TTR("Perspective");
+ String name;
- if (auto_orthogonal) {
- view_mode += " [auto]";
+ switch (view_type) {
+ case VIEW_TYPE_USER: {
+ if (orthogonal) {
+ name = TTR("Orthogonal");
+ } else {
+ name = TTR("Perspective");
+ }
+ } break;
+ case VIEW_TYPE_TOP: {
+ if (orthogonal) {
+ name = TTR("Top Orthogonal");
+ } else {
+ name = TTR("Top Perspective");
+ }
+ } break;
+ case VIEW_TYPE_BOTTOM: {
+ if (orthogonal) {
+ name = TTR("Bottom Orthogonal");
+ } else {
+ name = TTR("Bottom Perspective");
+ }
+ } break;
+ case VIEW_TYPE_LEFT: {
+ if (orthogonal) {
+ name = TTR("Left Orthogonal");
+ } else {
+ name = TTR("Right Perspective");
+ }
+ } break;
+ case VIEW_TYPE_RIGHT: {
+ if (orthogonal) {
+ name = TTR("Right Orthogonal");
+ } else {
+ name = TTR("Right Perspective");
+ }
+ } break;
+ case VIEW_TYPE_FRONT: {
+ if (orthogonal) {
+ name = TTR("Front Orthogonal");
+ } else {
+ name = TTR("Front Perspective");
+ }
+ } break;
+ case VIEW_TYPE_REAR: {
+ if (orthogonal) {
+ name = TTR("Rear Orthogonal");
+ } else {
+ name = TTR("Rear Perspective");
+ }
+ } break;
}
- if (name != "") {
- view_menu->set_text(name + " " + view_mode);
- } else {
- view_menu->set_text(view_mode);
+ if (auto_orthogonal) {
+ // TRANSLATORS: This will be appended to the view name when Auto Orthogonal is enabled.
+ name += TTR(" [auto]");
}
+ view_menu->set_text(name);
view_menu->set_size(Vector2(0, 0)); // resets the button size
}
@@ -1386,7 +1434,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
case TRANSFORM_VIEW: {
_edit.plane = TRANSFORM_X_AXIS;
set_message(TTR("X-Axis Transform."), 2);
- name = "";
+ view_type = VIEW_TYPE_USER;
_update_name();
} break;
case TRANSFORM_X_AXIS: {
@@ -2327,7 +2375,7 @@ void Node3DEditorViewport::_nav_orbit(Ref<InputEventWithModifiers> p_event, cons
} else {
cursor.y_rot += p_relative.x * radians_per_pixel;
}
- name = "";
+ view_type = VIEW_TYPE_USER;
_update_name();
}
@@ -2365,7 +2413,7 @@ void Node3DEditorViewport::_nav_look(Ref<InputEventWithModifiers> p_event, const
Vector3 diff = prev_pos - pos;
cursor.pos += diff;
- name = "";
+ view_type = VIEW_TYPE_USER;
_update_name();
}
@@ -3010,7 +3058,7 @@ void Node3DEditorViewport::_menu_option(int p_option) {
cursor.y_rot = 0;
cursor.x_rot = Math_PI / 2.0;
set_message(TTR("Top View."), 2);
- name = TTR("Top");
+ view_type = VIEW_TYPE_TOP;
_set_auto_orthogonal();
_update_name();
@@ -3019,7 +3067,7 @@ void Node3DEditorViewport::_menu_option(int p_option) {
cursor.y_rot = 0;
cursor.x_rot = -Math_PI / 2.0;
set_message(TTR("Bottom View."), 2);
- name = TTR("Bottom");
+ view_type = VIEW_TYPE_BOTTOM;
_set_auto_orthogonal();
_update_name();
@@ -3028,7 +3076,7 @@ void Node3DEditorViewport::_menu_option(int p_option) {
cursor.x_rot = 0;
cursor.y_rot = Math_PI / 2.0;
set_message(TTR("Left View."), 2);
- name = TTR("Left");
+ view_type = VIEW_TYPE_LEFT;
_set_auto_orthogonal();
_update_name();
@@ -3037,7 +3085,7 @@ void Node3DEditorViewport::_menu_option(int p_option) {
cursor.x_rot = 0;
cursor.y_rot = -Math_PI / 2.0;
set_message(TTR("Right View."), 2);
- name = TTR("Right");
+ view_type = VIEW_TYPE_RIGHT;
_set_auto_orthogonal();
_update_name();
@@ -3046,7 +3094,7 @@ void Node3DEditorViewport::_menu_option(int p_option) {
cursor.x_rot = 0;
cursor.y_rot = Math_PI;
set_message(TTR("Front View."), 2);
- name = TTR("Front");
+ view_type = VIEW_TYPE_FRONT;
_set_auto_orthogonal();
_update_name();
@@ -3055,7 +3103,7 @@ void Node3DEditorViewport::_menu_option(int p_option) {
cursor.x_rot = 0;
cursor.y_rot = 0;
set_message(TTR("Rear View."), 2);
- name = TTR("Rear");
+ view_type = VIEW_TYPE_REAR;
_set_auto_orthogonal();
_update_name();
@@ -3599,8 +3647,8 @@ void Node3DEditorViewport::set_state(const Dictionary &p_state) {
_menu_option(VIEW_PERSPECTIVE);
}
}
- if (p_state.has("view_name")) {
- name = p_state["view_name"];
+ if (p_state.has("view_type")) {
+ view_type = ViewType(p_state["view_type"].operator int());
_update_name();
}
if (p_state.has("auto_orthogonal")) {
@@ -3708,7 +3756,7 @@ Dictionary Node3DEditorViewport::get_state() const {
d["distance"] = cursor.distance;
d["use_environment"] = camera->get_environment().is_valid();
d["use_orthogonal"] = camera->get_projection() == Camera3D::PROJECTION_ORTHOGONAL;
- d["view_name"] = name;
+ d["view_type"] = view_type;
d["auto_orthogonal"] = auto_orthogonal;
d["auto_orthogonal_enabled"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_AUTO_ORTHOGONAL));
if (view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_NORMAL))) {
@@ -3753,7 +3801,7 @@ void Node3DEditorViewport::reset() {
message_time = 0;
message = "";
last_message = "";
- name = "";
+ view_type = VIEW_TYPE_USER;
cursor = Cursor();
_update_name();
@@ -4368,7 +4416,7 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito
viewport->set_as_audio_listener_3d(true);
}
- name = "";
+ view_type = VIEW_TYPE_USER;
_update_name();
EditorSettings::get_singleton()->connect("settings_changed", callable_mp(this, &Node3DEditorViewport::update_transform_gizmo_view));
diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h
index 094aa5662f..d29c1efabb 100644
--- a/editor/plugins/node_3d_editor_plugin.h
+++ b/editor/plugins/node_3d_editor_plugin.h
@@ -143,6 +143,16 @@ class Node3DEditorViewport : public Control {
VIEW_MAX
};
+ enum ViewType {
+ VIEW_TYPE_USER,
+ VIEW_TYPE_TOP,
+ VIEW_TYPE_BOTTOM,
+ VIEW_TYPE_LEFT,
+ VIEW_TYPE_RIGHT,
+ VIEW_TYPE_FRONT,
+ VIEW_TYPE_REAR,
+ };
+
public:
enum {
GIZMO_BASE_LAYER = 27,
@@ -172,7 +182,7 @@ private:
int gpu_time_history_index;
int index;
- String name;
+ ViewType view_type;
void _menu_option(int p_option);
void _set_auto_orthogonal();
Node3D *preview_node;
diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp
index 8866e8c53e..584eb84ecd 100644
--- a/editor/plugins/path_2d_editor_plugin.cpp
+++ b/editor/plugins/path_2d_editor_plugin.cpp
@@ -77,7 +77,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
Vector2 gpoint = mb->get_position();
- Vector2 cpoint = node->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mb->get_position())));
+ Vector2 cpoint = node->to_local(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mb->get_position())));
if (mb->is_pressed() && action == ACTION_NONE) {
Ref<Curve2D> curve = node->get_curve();
diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp
index 0bb0bfde6f..309821b3dc 100644
--- a/editor/plugins/skeleton_3d_editor_plugin.cpp
+++ b/editor/plugins/skeleton_3d_editor_plugin.cpp
@@ -551,22 +551,30 @@ void Skeleton3DEditor::update_joint_tree() {
items.insert(-1, root);
- const Vector<int> &joint_porder = skeleton->get_bone_process_orders();
Ref<Texture> bone_icon = get_theme_icon(SNAME("BoneAttachment3D"), SNAME("EditorIcons"));
- for (int i = 0; i < joint_porder.size(); ++i) {
- const int b_idx = joint_porder[i];
+ Vector<int> bones_to_process = skeleton->get_parentless_bones();
+ while (bones_to_process.size() > 0) {
+ int current_bone_idx = bones_to_process[0];
+ bones_to_process.erase(current_bone_idx);
- const int p_idx = skeleton->get_bone_parent(b_idx);
- TreeItem *p_item = items.find(p_idx)->get();
+ const int parent_idx = skeleton->get_bone_parent(current_bone_idx);
+ TreeItem *parent_item = items.find(parent_idx)->get();
- TreeItem *joint_item = joint_tree->create_item(p_item);
- items.insert(b_idx, joint_item);
+ TreeItem *joint_item = joint_tree->create_item(parent_item);
+ items.insert(current_bone_idx, joint_item);
- joint_item->set_text(0, skeleton->get_bone_name(b_idx));
+ joint_item->set_text(0, skeleton->get_bone_name(current_bone_idx));
joint_item->set_icon(0, bone_icon);
joint_item->set_selectable(0, true);
- joint_item->set_metadata(0, "bones/" + itos(b_idx));
+ joint_item->set_metadata(0, "bones/" + itos(current_bone_idx));
+
+ // Add the bone's children to the list of bones to be processed
+ Vector<int> current_bone_child_bones = skeleton->get_bone_children(current_bone_idx);
+ int child_bone_size = current_bone_child_bones.size();
+ for (int i = 0; i < child_bone_size; i++) {
+ bones_to_process.push_back(current_bone_child_bones[i]);
+ }
}
}
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index 42f7d23da2..2883dbbc81 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -200,34 +200,36 @@ void SpriteFramesEditor::_sheet_scroll_input(const Ref<InputEvent> &p_event) {
void SpriteFramesEditor::_sheet_add_frames() {
Size2i size = split_sheet_preview->get_texture()->get_size();
- int h = split_sheet_h->get_value();
- int v = split_sheet_v->get_value();
+ int frame_count_x = split_sheet_h->get_value();
+ int frame_count_y = split_sheet_v->get_value();
+ Size2 frame_size(size.width / frame_count_x, size.height / frame_count_y);
undo_redo->create_action(TTR("Add Frame"));
int fc = frames->get_frame_count(edited_anim);
- AtlasTexture *atlas_source = Object::cast_to<AtlasTexture>(*split_sheet_preview->get_texture());
-
- Rect2 region_rect = Rect2();
+ Point2 src_origin;
+ Rect2 src_region(Point2(), size);
- if (atlas_source && atlas_source->get_atlas().is_valid()) {
- region_rect = atlas_source->get_region();
+ AtlasTexture *src_atlas = Object::cast_to<AtlasTexture>(*split_sheet_preview->get_texture());
+ if (src_atlas && src_atlas->get_atlas().is_valid()) {
+ src_origin = src_atlas->get_region().position - src_atlas->get_margin().position;
+ src_region = src_atlas->get_region();
}
for (Set<int>::Element *E = frames_selected.front(); E; E = E->next()) {
int idx = E->get();
- int width = size.width / h;
- int height = size.height / v;
- int xp = idx % h;
- int yp = (idx - xp) / h;
- int x = (xp * width) + region_rect.position.x;
- int y = (yp * height) + region_rect.position.y;
+ Point2 frame_coords(idx % frame_count_x, idx / frame_count_x);
+
+ Rect2 frame(frame_coords * frame_size + src_origin, frame_size);
+ Rect2 region = frame.intersection(src_region);
+ Rect2 margin(region == Rect2() ? Point2() : region.position - frame.position, frame.size - region.size);
Ref<AtlasTexture> at;
at.instantiate();
at->set_atlas(split_sheet_preview->get_texture());
- at->set_region(Rect2(x, y, width, height));
+ at->set_region(region);
+ at->set_margin(margin);
undo_redo->add_do_method(frames, "add_frame", edited_anim, at, -1);
undo_redo->add_undo_method(frames, "remove_frame", edited_anim, fc);