summaryrefslogtreecommitdiff
path: root/editor/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'editor/plugins')
-rw-r--r--editor/plugins/audio_stream_editor_plugin.cpp4
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp113
-rw-r--r--editor/plugins/gradient_editor_plugin.h8
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp10
-rw-r--r--editor/plugins/node_3d_editor_plugin.h6
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.cpp13
-rw-r--r--editor/plugins/tile_map_editor_plugin.cpp31
-rw-r--r--editor/plugins/tile_map_editor_plugin.h1
-rw-r--r--editor/plugins/tile_set_editor_plugin.cpp4
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp417
-rw-r--r--editor/plugins/visual_shader_editor_plugin.h15
11 files changed, 401 insertions, 221 deletions
diff --git a/editor/plugins/audio_stream_editor_plugin.cpp b/editor/plugins/audio_stream_editor_plugin.cpp
index b0f65af245..231f5588a4 100644
--- a/editor/plugins/audio_stream_editor_plugin.cpp
+++ b/editor/plugins/audio_stream_editor_plugin.cpp
@@ -44,8 +44,8 @@ void AudioStreamEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_THEME_CHANGED || p_what == NOTIFICATION_ENTER_TREE) {
_play_button->set_icon(get_theme_icon("MainPlay", "EditorIcons"));
_stop_button->set_icon(get_theme_icon("Stop", "EditorIcons"));
- _preview->set_frame_color(get_theme_color("dark_color_2", "Editor"));
- set_frame_color(get_theme_color("dark_color_1", "Editor"));
+ _preview->set_color(get_theme_color("dark_color_2", "Editor"));
+ set_color(get_theme_color("dark_color_1", "Editor"));
_indicator->update();
_preview->update();
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index c06580df26..1af60b59a2 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -52,6 +52,7 @@
#include "scene/gui/subviewport_container.h"
#include "scene/main/canvas_layer.h"
#include "scene/main/window.h"
+#include "scene/resources/dynamic_font.h"
#include "scene/resources/packed_scene.h"
// Min and Max are power of two in order to play nicely with successive increment.
@@ -1410,9 +1411,16 @@ bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) {
}
// Confirm the pivot move
- if ((b.is_valid() && !b->is_pressed() && b->get_button_index() == BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) ||
- (k.is_valid() && !k->is_pressed() && k->get_keycode() == KEY_V)) {
- _commit_canvas_item_state(drag_selection, TTR("Move pivot"));
+ if (drag_selection.size() >= 1 &&
+ ((b.is_valid() && !b->is_pressed() && b->get_button_index() == BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) ||
+ (k.is_valid() && !k->is_pressed() && k->get_keycode() == KEY_V))) {
+ _commit_canvas_item_state(
+ drag_selection,
+ vformat(
+ TTR("Set CanvasItem \"%s\" Pivot Offset to (%d, %d)"),
+ drag_selection[0]->get_name(),
+ drag_selection[0]->_edit_get_pivot().x,
+ drag_selection[0]->_edit_get_pivot().y));
drag_type = DRAG_NONE;
return true;
}
@@ -1549,7 +1557,20 @@ bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) {
// Confirms the node rotation
if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) {
- _commit_canvas_item_state(drag_selection, TTR("Rotate CanvasItem"));
+ if (drag_selection.size() != 1) {
+ _commit_canvas_item_state(
+ drag_selection,
+ vformat(TTR("Rotate %d CanvasItems"), drag_selection.size()),
+ true);
+ } else {
+ _commit_canvas_item_state(
+ drag_selection,
+ vformat(TTR("Rotate CanvasItem \"%s\" to %d degrees"),
+ drag_selection[0]->get_name(),
+ Math::rad2deg(drag_selection[0]->_edit_get_rotation())),
+ true);
+ }
+
if (key_auto_insert_button->is_pressed()) {
_insert_animation_keys(false, true, false, true);
}
@@ -1708,8 +1729,10 @@ bool CanvasItemEditor::_gui_input_anchors(const Ref<InputEvent> &p_event) {
}
// Confirms new anchor position
- if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) {
- _commit_canvas_item_state(drag_selection, TTR("Move anchor"));
+ if (drag_selection.size() >= 1 && b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) {
+ _commit_canvas_item_state(
+ drag_selection,
+ vformat(TTR("Move CanvasItem \"%s\" Anchor"), drag_selection[0]->get_name()));
drag_type = DRAG_NONE;
return true;
}
@@ -1885,8 +1908,31 @@ bool CanvasItemEditor::_gui_input_resize(const Ref<InputEvent> &p_event) {
}
// Confirm resize
- if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) {
- _commit_canvas_item_state(drag_selection, TTR("Resize CanvasItem"));
+ if (drag_selection.size() >= 1 && b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) {
+ const Node2D *node2d = Object::cast_to<Node2D>(drag_selection[0]);
+ if (node2d) {
+ // Extends from Node2D.
+ // Node2D doesn't have an actual stored rect size, unlike Controls.
+ _commit_canvas_item_state(
+ drag_selection,
+ vformat(
+ TTR("Scale Node2D \"%s\" to (%s, %s)"),
+ drag_selection[0]->get_name(),
+ Math::stepify(drag_selection[0]->_edit_get_scale().x, 0.01),
+ Math::stepify(drag_selection[0]->_edit_get_scale().y, 0.01)),
+ true);
+ } else {
+ // Extends from Control.
+ _commit_canvas_item_state(
+ drag_selection,
+ vformat(
+ TTR("Resize Control \"%s\" to (%d, %d)"),
+ drag_selection[0]->get_name(),
+ drag_selection[0]->_edit_get_rect().size.x,
+ drag_selection[0]->_edit_get_rect().size.y),
+ true);
+ }
+
if (key_auto_insert_button->is_pressed()) {
_insert_animation_keys(false, false, true, true);
}
@@ -2014,7 +2060,20 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) {
// Confirm resize
if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) {
- _commit_canvas_item_state(drag_selection, TTR("Scale CanvasItem"));
+ if (drag_selection.size() != 1) {
+ _commit_canvas_item_state(
+ drag_selection,
+ vformat(TTR("Scale %d CanvasItems"), drag_selection.size()),
+ true);
+ } else {
+ _commit_canvas_item_state(
+ drag_selection,
+ vformat(TTR("Scale CanvasItem \"%s\" to (%s, %s)"),
+ drag_selection[0]->get_name(),
+ Math::stepify(drag_selection[0]->_edit_get_scale().x, 0.01),
+ Math::stepify(drag_selection[0]->_edit_get_scale().y, 0.01)),
+ true);
+ }
if (key_auto_insert_button->is_pressed()) {
_insert_animation_keys(false, false, true, true);
}
@@ -2145,7 +2204,21 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
// Confirm the move (only if it was moved)
if (b.is_valid() && !b->is_pressed() && b->get_button_index() == BUTTON_LEFT) {
if (transform.affine_inverse().xform(b->get_position()) != drag_from) {
- _commit_canvas_item_state(drag_selection, TTR("Move CanvasItem"), true);
+ if (drag_selection.size() != 1) {
+ _commit_canvas_item_state(
+ drag_selection,
+ vformat(TTR("Move %d CanvasItems"), drag_selection.size()),
+ true);
+ } else {
+ _commit_canvas_item_state(
+ drag_selection,
+ vformat(
+ TTR("Move CanvasItem \"%s\" to (%d, %d)"),
+ drag_selection[0]->get_name(),
+ drag_selection[0]->_edit_get_position().x,
+ drag_selection[0]->_edit_get_position().y),
+ true);
+ }
}
if (key_auto_insert_button->is_pressed()) {
@@ -2270,7 +2343,20 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
(!Input::get_singleton()->is_key_pressed(KEY_DOWN)) &&
(!Input::get_singleton()->is_key_pressed(KEY_LEFT)) &&
(!Input::get_singleton()->is_key_pressed(KEY_RIGHT))) {
- _commit_canvas_item_state(drag_selection, TTR("Move CanvasItem"), true);
+ if (drag_selection.size() != 1) {
+ _commit_canvas_item_state(
+ drag_selection,
+ vformat(TTR("Move %d CanvasItems"), drag_selection.size()),
+ true);
+ } else {
+ _commit_canvas_item_state(
+ drag_selection,
+ vformat(TTR("Move CanvasItem \"%s\" to (%d, %d)"),
+ drag_selection[0]->get_name(),
+ drag_selection[0]->_edit_get_position().x,
+ drag_selection[0]->_edit_get_position().y),
+ true);
+ }
drag_type = DRAG_NONE;
}
viewport->update();
@@ -5642,6 +5728,11 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
zoom_reset = memnew(Button);
zoom_reset->set_flat(true);
zoom_hb->add_child(zoom_reset);
+ Ref<DynamicFont> font = zoom_reset->get_theme_font("font")->duplicate(false);
+ font->set_outline_size(1);
+ font->set_outline_color(Color(0, 0, 0));
+ zoom_reset->add_theme_font_override("font", font);
+ zoom_reset->add_theme_color_override("font_color", Color(1, 1, 1));
zoom_reset->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_zoom_reset));
zoom_reset->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_reset", TTR("Zoom Reset"), KEY_MASK_CMD | KEY_0));
zoom_reset->set_focus_mode(FOCUS_NONE);
diff --git a/editor/plugins/gradient_editor_plugin.h b/editor/plugins/gradient_editor_plugin.h
index 59cf787020..4d3fc0d8a9 100644
--- a/editor/plugins/gradient_editor_plugin.h
+++ b/editor/plugins/gradient_editor_plugin.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef TOOLS_EDITOR_PLUGINS_COLOR_RAMP_EDITOR_PLUGIN_H_
-#define TOOLS_EDITOR_PLUGINS_COLOR_RAMP_EDITOR_PLUGIN_H_
+#ifndef GRADIENT_EDITOR_PLUGIN_H
+#define GRADIENT_EDITOR_PLUGIN_H
#include "editor/editor_node.h"
#include "editor/editor_plugin.h"
@@ -65,9 +65,9 @@ class GradientEditorPlugin : public EditorPlugin {
GDCLASS(GradientEditorPlugin, EditorPlugin);
public:
- virtual String get_name() const override { return "ColorRamp"; }
+ virtual String get_name() const override { return "Gradient"; }
GradientEditorPlugin(EditorNode *p_node);
};
-#endif /* TOOLS_EDITOR_PLUGINS_COLOR_RAMP_EDITOR_PLUGIN_H_ */
+#endif // GRADIENT_EDITOR_PLUGIN_H
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index aecbf817c4..5038941784 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -2464,12 +2464,14 @@ void Node3DEditorViewport::_notification(int p_what) {
subviewport_container->set_stretch_shrink(shrink ? 2 : 1);
}
- //update msaa if changed
+ // Update MSAA, screen-space AA and debanding if changed
- int msaa_mode = ProjectSettings::get_singleton()->get("rendering/quality/screen_filters/msaa");
+ const int msaa_mode = ProjectSettings::get_singleton()->get("rendering/quality/screen_filters/msaa");
viewport->set_msaa(Viewport::MSAA(msaa_mode));
- int ssaa_mode = GLOBAL_GET("rendering/quality/screen_filters/screen_space_aa");
+ const int ssaa_mode = GLOBAL_GET("rendering/quality/screen_filters/screen_space_aa");
viewport->set_screen_space_aa(Viewport::ScreenSpaceAA(ssaa_mode));
+ const bool use_debanding = GLOBAL_GET("rendering/quality/screen_filters/use_debanding");
+ viewport->set_use_debanding(use_debanding);
bool show_info = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_INFORMATION));
if (show_info != info_label->is_visible()) {
@@ -6725,7 +6727,6 @@ void EditorNode3DGizmoPlugin::create_handle_material(const String &p_name, bool
handle_material->set_point_size(handle_t->get_width());
handle_material->set_texture(StandardMaterial3D::TEXTURE_ALBEDO, handle_t);
handle_material->set_albedo(Color(1, 1, 1));
- handle_material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
handle_material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
handle_material->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
handle_material->set_on_top_of_alpha();
@@ -6733,6 +6734,7 @@ void EditorNode3DGizmoPlugin::create_handle_material(const String &p_name, bool
handle_material->set_billboard_mode(StandardMaterial3D::BILLBOARD_ENABLED);
handle_material->set_on_top_of_alpha();
}
+ handle_material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
materials[p_name] = Vector<Ref<StandardMaterial3D>>();
materials[p_name].push_back(handle_material);
diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h
index 4f627b1d0c..e4a384449b 100644
--- a/editor/plugins/node_3d_editor_plugin.h
+++ b/editor/plugins/node_3d_editor_plugin.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SPATIAL_EDITOR_PLUGIN_H
-#define SPATIAL_EDITOR_PLUGIN_H
+#ifndef NODE_3D_EDITOR_PLUGIN_H
+#define NODE_3D_EDITOR_PLUGIN_H
#include "editor/editor_node.h"
#include "editor/editor_plugin.h"
@@ -890,4 +890,4 @@ public:
virtual ~EditorNode3DGizmoPlugin();
};
-#endif
+#endif // NODE_3D_EDITOR_PLUGIN_H
diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp
index dd1194d020..ac90ee9570 100644
--- a/editor/plugins/polygon_2d_editor_plugin.cpp
+++ b/editor/plugins/polygon_2d_editor_plugin.cpp
@@ -79,8 +79,8 @@ void Polygon2DEditor::_notification(int p_what) {
uv_button[UV_MODE_SCALE]->set_icon(get_theme_icon("ToolScale", "EditorIcons"));
uv_button[UV_MODE_ADD_POLYGON]->set_icon(get_theme_icon("Edit", "EditorIcons"));
uv_button[UV_MODE_REMOVE_POLYGON]->set_icon(get_theme_icon("Close", "EditorIcons"));
- uv_button[UV_MODE_PAINT_WEIGHT]->set_icon(get_theme_icon("PaintVertex", "EditorIcons"));
- uv_button[UV_MODE_CLEAR_WEIGHT]->set_icon(get_theme_icon("UnpaintVertex", "EditorIcons"));
+ uv_button[UV_MODE_PAINT_WEIGHT]->set_icon(get_theme_icon("Bucket", "EditorIcons"));
+ uv_button[UV_MODE_CLEAR_WEIGHT]->set_icon(get_theme_icon("Clear", "EditorIcons"));
b_snap_grid->set_icon(get_theme_icon("Grid", "EditorIcons"));
b_snap_enable->set_icon(get_theme_icon("SnapGrid", "EditorIcons"));
@@ -1325,11 +1325,16 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) :
uv_main_hsc->add_child(uv_edit_draw);
uv_edit_draw->set_h_size_flags(SIZE_EXPAND_FILL);
uv_edit_draw->set_custom_minimum_size(Size2(200, 200) * EDSCALE);
+
+ Control *space = memnew(Control);
+ uv_mode_hb->add_child(space);
+ space->set_h_size_flags(SIZE_EXPAND_FILL);
+
uv_menu = memnew(MenuButton);
uv_mode_hb->add_child(uv_menu);
uv_menu->set_text(TTR("Edit"));
- uv_menu->get_popup()->add_item(TTR("Polygon->UV"), UVEDIT_POLYGON_TO_UV);
- uv_menu->get_popup()->add_item(TTR("UV->Polygon"), UVEDIT_UV_TO_POLYGON);
+ uv_menu->get_popup()->add_item(TTR("Copy Polygon to UV"), UVEDIT_POLYGON_TO_UV);
+ uv_menu->get_popup()->add_item(TTR("Copy UV to Polygon"), UVEDIT_UV_TO_POLYGON);
uv_menu->get_popup()->add_separator();
uv_menu->get_popup()->add_item(TTR("Clear UV"), UVEDIT_UV_CLEAR);
uv_menu->get_popup()->add_separator();
diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp
index 8cd8aaf277..e43b8c4b7f 100644
--- a/editor/plugins/tile_map_editor_plugin.cpp
+++ b/editor/plugins/tile_map_editor_plugin.cpp
@@ -65,7 +65,7 @@ void TileMapEditor::_notification(int p_what) {
paint_button->set_icon(get_theme_icon("Edit", "EditorIcons"));
line_button->set_icon(get_theme_icon("CurveLinear", "EditorIcons"));
- rectangle_button->set_icon(get_theme_icon("RectangleShape2D", "EditorIcons"));
+ rectangle_button->set_icon(get_theme_icon("Rectangle", "EditorIcons"));
bucket_fill_button->set_icon(get_theme_icon("Bucket", "EditorIcons"));
picker_button->set_icon(get_theme_icon("ColorPick", "EditorIcons"));
select_button->set_icon(get_theme_icon("ActionCopy", "EditorIcons"));
@@ -89,6 +89,25 @@ void TileMapEditor::_notification(int p_what) {
case NOTIFICATION_EXIT_TREE: {
get_tree()->disconnect("node_removed", callable_mp(this, &TileMapEditor::_node_removed));
} break;
+
+ case NOTIFICATION_APPLICATION_FOCUS_OUT: {
+ if (tool == TOOL_PAINTING) {
+ Vector<int> ids = get_selected_tiles();
+
+ if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) {
+ _set_cell(over_tile, ids, flip_h, flip_v, transpose);
+ _finish_undo();
+
+ paint_undo.clear();
+ }
+
+ tool = TOOL_NONE;
+ _update_button_tool();
+ }
+
+ // set flag to ignore over_tile on refocus
+ refocus_over_tile = true;
+ } break;
}
}
@@ -394,7 +413,9 @@ struct _PaletteEntry {
String name;
bool operator<(const _PaletteEntry &p_rhs) const {
- return name < p_rhs.name;
+ // Natural no case comparison will compare strings based on CharType
+ // order (except digits) and on numbers that start on the same position.
+ return name.naturalnocasecmp_to(p_rhs.name) < 0;
}
};
} // namespace
@@ -1299,6 +1320,12 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
CanvasItemEditor::get_singleton()->update_viewport();
}
+ if (refocus_over_tile) {
+ // editor lost focus; forget last tile position
+ old_over_tile = new_over_tile;
+ refocus_over_tile = false;
+ }
+
int tile_under = node->get_cell(over_tile.x, over_tile.y);
String tile_name = "none";
diff --git a/editor/plugins/tile_map_editor_plugin.h b/editor/plugins/tile_map_editor_plugin.h
index 996e904853..f57616db1f 100644
--- a/editor/plugins/tile_map_editor_plugin.h
+++ b/editor/plugins/tile_map_editor_plugin.h
@@ -119,6 +119,7 @@ class TileMapEditor : public VBoxContainer {
Rect2i rectangle;
Point2i over_tile;
+ bool refocus_over_tile = false;
bool *bucket_cache_visited;
Rect2i bucket_cache_rect;
diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp
index 684d8f0f10..9c589267fc 100644
--- a/editor/plugins/tile_set_editor_plugin.cpp
+++ b/editor/plugins/tile_set_editor_plugin.cpp
@@ -60,7 +60,6 @@ void TileSetEditor::_import_node(Node *p_node, Ref<TileSet> p_library) {
Sprite2D *mi = Object::cast_to<Sprite2D>(child);
Ref<Texture2D> texture = mi->get_texture();
- Ref<Texture2D> normal_map = mi->get_normal_map();
Ref<ShaderMaterial> material = mi->get_material();
if (texture.is_null()) {
@@ -75,7 +74,6 @@ void TileSetEditor::_import_node(Node *p_node, Ref<TileSet> p_library) {
}
p_library->tile_set_texture(id, texture);
- p_library->tile_set_normal_map(id, normal_map);
p_library->tile_set_material(id, material);
p_library->tile_set_modulate(id, mi->get_modulate());
@@ -2368,7 +2366,6 @@ void TileSetEditor::_select_edited_shape_coord() {
void TileSetEditor::_undo_tile_removal(int p_id) {
undo_redo->add_undo_method(tileset.ptr(), "create_tile", p_id);
undo_redo->add_undo_method(tileset.ptr(), "tile_set_name", p_id, tileset->tile_get_name(p_id));
- undo_redo->add_undo_method(tileset.ptr(), "tile_set_normal_map", p_id, tileset->tile_get_normal_map(p_id));
undo_redo->add_undo_method(tileset.ptr(), "tile_set_texture_offset", p_id, tileset->tile_get_texture_offset(p_id));
undo_redo->add_undo_method(tileset.ptr(), "tile_set_material", p_id, tileset->tile_get_material(p_id));
undo_redo->add_undo_method(tileset.ptr(), "tile_set_modulate", p_id, tileset->tile_get_modulate(p_id));
@@ -3541,7 +3538,6 @@ void TilesetEditorContext::_get_property_list(List<PropertyInfo> *p_list) const
int id = tileset_editor->get_current_tile();
p_list->push_back(PropertyInfo(Variant::NIL, "Selected Tile", PROPERTY_HINT_NONE, "tile_", PROPERTY_USAGE_GROUP));
p_list->push_back(PropertyInfo(Variant::STRING, "tile_name"));
- p_list->push_back(PropertyInfo(Variant::OBJECT, "tile_normal_map", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"));
p_list->push_back(PropertyInfo(Variant::VECTOR2, "tile_tex_offset"));
p_list->push_back(PropertyInfo(Variant::OBJECT, "tile_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial"));
p_list->push_back(PropertyInfo(Variant::COLOR, "tile_modulate"));
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index 2d0f4a19e7..ddcba18a78 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -107,6 +107,8 @@ void VisualShaderGraphPlugin::_bind_methods() {
ClassDB::bind_method("update_node_deferred", &VisualShaderGraphPlugin::update_node_deferred);
ClassDB::bind_method("set_input_port_default_value", &VisualShaderGraphPlugin::set_input_port_default_value);
ClassDB::bind_method("set_uniform_name", &VisualShaderGraphPlugin::set_uniform_name);
+ ClassDB::bind_method("set_expression", &VisualShaderGraphPlugin::set_expression);
+ ClassDB::bind_method("update_curve", &VisualShaderGraphPlugin::update_curve);
ClassDB::bind_method("update_constant", &VisualShaderGraphPlugin::update_constant);
}
@@ -205,6 +207,14 @@ void VisualShaderGraphPlugin::set_uniform_name(VisualShader::Type p_type, int p_
}
}
+void VisualShaderGraphPlugin::update_curve(int p_node_id) {
+ if (links.has(p_node_id) && links[p_node_id].curve_editor) {
+ if (((VisualShaderNodeCurveTexture *)links[p_node_id].visual_node)->get_texture().is_valid()) {
+ links[p_node_id].curve_editor->set_curve(((VisualShaderNodeCurveTexture *)links[p_node_id].visual_node)->get_texture()->get_curve());
+ }
+ }
+}
+
int VisualShaderGraphPlugin::get_constant_index(float p_constant) const {
for (int i = 0; i < MAX_FLOAT_CONST_DEFS; i++) {
if (Math::is_equal_approx(p_constant, float_constant_defs[i].value)) {
@@ -226,6 +236,13 @@ void VisualShaderGraphPlugin::update_constant(VisualShader::Type p_type, int p_n
links[p_node_id].graph_node->set_size(Size2(-1, -1));
}
+void VisualShaderGraphPlugin::set_expression(VisualShader::Type p_type, int p_node_id, const String &p_expression) {
+ if (p_type != visual_shader->get_shader_type() || !links.has(p_node_id) || !links[p_node_id].expression_edit) {
+ return;
+ }
+ links[p_node_id].expression_edit->set_text(p_expression);
+}
+
void VisualShaderGraphPlugin::update_node_size(int p_node_id) {
if (!links.has(p_node_id)) {
return;
@@ -241,6 +258,14 @@ void VisualShaderGraphPlugin::register_constant_option_btn(int p_node_id, Option
links[p_node_id].const_op = p_button;
}
+void VisualShaderGraphPlugin::register_expression_edit(int p_node_id, CodeEdit *p_expression_edit) {
+ links[p_node_id].expression_edit = p_expression_edit;
+}
+
+void VisualShaderGraphPlugin::register_curve_editor(int p_node_id, CurveEditor *p_curve_editor) {
+ links[p_node_id].curve_editor = p_curve_editor;
+}
+
void VisualShaderGraphPlugin::update_uniform_refs() {
for (Map<int, Link>::Element *E = links.front(); E; E = E->next()) {
VisualShaderNodeUniformRef *ref = Object::cast_to<VisualShaderNodeUniformRef>(E->get().visual_node);
@@ -284,7 +309,7 @@ void VisualShaderGraphPlugin::make_dirty(bool p_enabled) {
}
void VisualShaderGraphPlugin::register_link(VisualShader::Type p_type, int p_id, VisualShaderNode *p_visual_node, GraphNode *p_graph_node) {
- links.insert(p_id, { p_type, p_visual_node, p_graph_node, p_visual_node->get_output_port_for_preview() != -1, -1, Map<int, InputPort>(), Map<int, Port>(), nullptr, nullptr, nullptr });
+ links.insert(p_id, { p_type, p_visual_node, p_graph_node, p_visual_node->get_output_port_for_preview() != -1, -1, Map<int, InputPort>(), Map<int, Port>(), nullptr, nullptr, nullptr, nullptr, nullptr });
}
void VisualShaderGraphPlugin::register_output_port(int p_node_id, int p_port, TextureButton *p_button) {
@@ -315,9 +340,12 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
Ref<VisualShaderNode> vsnode = visual_shader->get_node(p_type, p_id);
+ Ref<VisualShaderNodeResizableBase> resizable_node = Object::cast_to<VisualShaderNodeResizableBase>(vsnode.ptr());
+ bool is_resizable = !resizable_node.is_null();
+ Size2 size = Size2(0, 0);
+
Ref<VisualShaderNodeGroupBase> group_node = Object::cast_to<VisualShaderNodeGroupBase>(vsnode.ptr());
bool is_group = !group_node.is_null();
- Size2 size = Size2(0, 0);
Ref<VisualShaderNodeExpression> expression_node = Object::cast_to<VisualShaderNodeExpression>(group_node.ptr());
bool is_expression = !expression_node.is_null();
@@ -326,8 +354,8 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
GraphNode *node = memnew(GraphNode);
register_link(p_type, p_id, vsnode.ptr(), node);
- if (is_group) {
- size = group_node->get_size();
+ if (is_resizable) {
+ size = resizable_node->get_size();
node->set_resizable(true);
node->connect("resize_request", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_node_resized), varray((int)p_type, p_id));
@@ -342,7 +370,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
if (p_id >= 2) {
node->set_show_close_button(true);
- node->connect("close_request", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_delete_request), varray(p_id), CONNECT_DEFERRED);
+ node->connect("close_request", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_delete_node_request), varray(p_type, p_id), CONNECT_DEFERRED);
}
node->connect("dragged", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_node_dragged), varray(p_id));
@@ -391,6 +419,18 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
}
}
+ Ref<VisualShaderNodeCurveTexture> curve = vsnode;
+ if (curve.is_valid()) {
+ if (curve->get_texture().is_valid() && !curve->get_texture()->is_connected("changed", callable_mp(VisualShaderEditor::get_singleton()->get_graph_plugin(), &VisualShaderGraphPlugin::update_curve))) {
+ curve->get_texture()->connect("changed", callable_mp(VisualShaderEditor::get_singleton()->get_graph_plugin(), &VisualShaderGraphPlugin::update_curve), varray(p_id));
+ }
+
+ HBoxContainer *hbox = memnew(HBoxContainer);
+ custom_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ hbox->add_child(custom_editor);
+ custom_editor = hbox;
+ }
+
Ref<VisualShaderNodeFloatConstant> float_const = vsnode;
if (float_const.is_valid()) {
HBoxContainer *hbox = memnew(HBoxContainer);
@@ -413,6 +453,37 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
} else if (custom_editor) {
port_offset++;
node->add_child(custom_editor);
+
+ if (curve.is_valid()) {
+ VisualShaderEditor::get_singleton()->graph->add_child(node);
+ VisualShaderEditor::get_singleton()->_update_created_node(node);
+
+ CurveEditor *curve_editor = memnew(CurveEditor);
+ node->add_child(curve_editor);
+ register_curve_editor(p_id, curve_editor);
+ curve_editor->set_custom_minimum_size(Size2(300, 0));
+ curve_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ if (curve->get_texture().is_valid()) {
+ curve_editor->set_curve(curve->get_texture()->get_curve());
+ }
+
+ TextureButton *preview = memnew(TextureButton);
+ preview->set_toggle_mode(true);
+ preview->set_normal_texture(VisualShaderEditor::get_singleton()->get_theme_icon("GuiVisibilityHidden", "EditorIcons"));
+ preview->set_pressed_texture(VisualShaderEditor::get_singleton()->get_theme_icon("GuiVisibilityVisible", "EditorIcons"));
+ preview->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
+
+ register_output_port(p_id, 0, preview);
+
+ preview->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_preview_select_port), varray(p_id, 0), CONNECT_DEFERRED);
+ custom_editor->add_child(preview);
+
+ VisualShaderNode::PortType port_left = vsnode->get_input_port_type(0);
+ VisualShaderNode::PortType port_right = vsnode->get_output_port_type(0);
+ node->set_slot(0, true, port_left, type_color[port_left], true, port_right, type_color[port_right]);
+
+ VisualShaderEditor::get_singleton()->call_deferred("_set_node_size", (int)p_type, p_id, size);
+ }
if (vsnode->is_use_prop_slots()) {
return;
}
@@ -623,6 +694,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
expression_syntax_highlighter.instance();
expression_node->set_control(expression_box, 0);
node->add_child(expression_box);
+ register_expression_edit(p_id, expression_box);
Color background_color = EDITOR_GET("text_editor/highlighting/background_color");
Color text_color = EDITOR_GET("text_editor/highlighting/text_color");
@@ -659,7 +731,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
if (!uniform.is_valid()) {
VisualShaderEditor::get_singleton()->graph->add_child(node);
VisualShaderEditor::get_singleton()->_update_created_node(node);
- if (is_group) {
+ if (is_resizable) {
VisualShaderEditor::get_singleton()->call_deferred("_set_node_size", (int)p_type, p_id, size);
}
}
@@ -1210,7 +1282,7 @@ void VisualShaderEditor::_add_input_port(int p_node, int p_port, int p_port_type
return;
}
- undo_redo->create_action(TTR("Add input port"));
+ undo_redo->create_action(TTR("Add Input Port"));
undo_redo->add_do_method(node.ptr(), "add_input_port", p_port, p_port_type, p_name);
undo_redo->add_undo_method(node.ptr(), "remove_input_port", p_port);
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node);
@@ -1225,7 +1297,7 @@ void VisualShaderEditor::_add_output_port(int p_node, int p_port, int p_port_typ
return;
}
- undo_redo->create_action(TTR("Add output port"));
+ undo_redo->create_action(TTR("Add Output Port"));
undo_redo->add_do_method(node.ptr(), "add_output_port", p_port, p_port_type, p_name);
undo_redo->add_undo_method(node.ptr(), "remove_output_port", p_port);
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node);
@@ -1240,7 +1312,7 @@ void VisualShaderEditor::_change_input_port_type(int p_type, int p_node, int p_p
return;
}
- undo_redo->create_action(TTR("Change input port type"));
+ undo_redo->create_action(TTR("Change Input Port Type"));
undo_redo->add_do_method(node.ptr(), "set_input_port_type", p_port, p_type);
undo_redo->add_undo_method(node.ptr(), "set_input_port_type", p_port, node->get_input_port_type(p_port));
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node);
@@ -1255,7 +1327,7 @@ void VisualShaderEditor::_change_output_port_type(int p_type, int p_node, int p_
return;
}
- undo_redo->create_action(TTR("Change output port type"));
+ undo_redo->create_action(TTR("Change Output Port Type"));
undo_redo->add_do_method(node.ptr(), "set_output_port_type", p_port, p_type);
undo_redo->add_undo_method(node.ptr(), "set_output_port_type", p_port, node->get_output_port_type(p_port));
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node);
@@ -1269,7 +1341,7 @@ void VisualShaderEditor::_change_input_port_name(const String &p_text, Object *l
Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node_id);
ERR_FAIL_COND(!node.is_valid());
- undo_redo->create_action(TTR("Change input port name"));
+ undo_redo->create_action(TTR("Change Input Port Name"));
undo_redo->add_do_method(node.ptr(), "set_input_port_name", p_port_id, p_text);
undo_redo->add_undo_method(node.ptr(), "set_input_port_name", p_port_id, node->get_input_port_name(p_port_id));
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node_id);
@@ -1283,7 +1355,7 @@ void VisualShaderEditor::_change_output_port_name(const String &p_text, Object *
Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node_id);
ERR_FAIL_COND(!node.is_valid());
- undo_redo->create_action(TTR("Change output port name"));
+ undo_redo->create_action(TTR("Change Output Port Name"));
undo_redo->add_do_method(node.ptr(), "set_output_port_name", p_port_id, p_text);
undo_redo->add_undo_method(node.ptr(), "set_output_port_name", p_port_id, node->get_output_port_name(p_port_id));
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node_id);
@@ -1298,7 +1370,7 @@ void VisualShaderEditor::_remove_input_port(int p_node, int p_port) {
return;
}
- undo_redo->create_action(TTR("Remove input port"));
+ undo_redo->create_action(TTR("Remove Input Port"));
List<VisualShader::Connection> conns;
visual_shader->get_node_connections(type, &conns);
@@ -1347,7 +1419,7 @@ void VisualShaderEditor::_remove_output_port(int p_node, int p_port) {
return;
}
- undo_redo->create_action(TTR("Remove output port"));
+ undo_redo->create_action(TTR("Remove Output Port"));
List<VisualShader::Connection> conns;
visual_shader->get_node_connections(type, &conns);
@@ -1402,31 +1474,39 @@ void VisualShaderEditor::_expression_focus_out(Object *code_edit, int p_node) {
return;
}
- undo_redo->create_action(TTR("Set expression"));
+ undo_redo->create_action(TTR("Set VisualShader Expression"));
undo_redo->add_do_method(node.ptr(), "set_expression", expression_box->get_text());
undo_redo->add_undo_method(node.ptr(), "set_expression", node->get_expression());
+ undo_redo->add_do_method(graph_plugin.ptr(), "set_expression", type, p_node, expression_box->get_text());
+ undo_redo->add_undo_method(graph_plugin.ptr(), "set_expression", type, p_node, node->get_expression());
undo_redo->commit_action();
}
void VisualShaderEditor::_set_node_size(int p_type, int p_node, const Vector2 &p_size) {
- VisualShader::Type type = get_current_shader_type();
- Ref<VisualShaderNode> node = visual_shader->get_node(type, p_node);
+ VisualShader::Type type = VisualShader::Type(p_type);
+ Ref<VisualShaderNodeResizableBase> node = visual_shader->get_node(type, p_node);
if (node.is_null()) {
return;
}
- Ref<VisualShaderNodeGroupBase> group_node = Object::cast_to<VisualShaderNodeGroupBase>(node.ptr());
-
- if (group_node.is_null()) {
- return;
+ Size2 size = p_size;
+ if (!node->is_allow_v_resize()) {
+ size.y = 0;
}
- Vector2 size = p_size;
+ node->set_size(size);
- group_node->set_size(size);
+ if (get_current_shader_type() == type) {
+ Ref<VisualShaderNodeExpression> expression_node = Object::cast_to<VisualShaderNodeExpression>(node.ptr());
+ Control *text_box = nullptr;
+ if (!expression_node.is_null()) {
+ text_box = expression_node->get_control(0);
+ if (text_box) {
+ text_box->set_custom_minimum_size(Size2(0, 0));
+ }
+ }
- GraphNode *gn = nullptr;
- if (edit_type->get_selected() == p_type) { // check - otherwise the error will be emitted
+ GraphNode *gn = nullptr;
Node *node2 = graph->get_node(itos(p_node));
gn = Object::cast_to<GraphNode>(node2);
if (!gn) {
@@ -1435,34 +1515,31 @@ void VisualShaderEditor::_set_node_size(int p_type, int p_node, const Vector2 &p
gn->set_custom_minimum_size(size);
gn->set_size(Size2(1, 1));
- }
- Ref<VisualShaderNodeExpression> expression_node = Object::cast_to<VisualShaderNodeExpression>(node.ptr());
- if (!expression_node.is_null()) {
- Control *text_box = expression_node->get_control(0);
- Size2 box_size = size;
- if (gn != nullptr) {
- if (box_size.x < 150 * EDSCALE || box_size.y < 0) {
- box_size.x = gn->get_size().x;
+ if (!expression_node.is_null() && text_box) {
+ Size2 box_size = size;
+ if (gn != nullptr) {
+ if (box_size.x < 150 * EDSCALE || box_size.y < 0) {
+ box_size.x = gn->get_size().x;
+ }
}
+ box_size.x -= text_box->get_margin(MARGIN_LEFT);
+ box_size.x -= 28 * EDSCALE;
+ box_size.y -= text_box->get_margin(MARGIN_TOP);
+ box_size.y -= 28 * EDSCALE;
+ text_box->set_custom_minimum_size(Size2(box_size.x, box_size.y));
+ text_box->set_size(Size2(1, 1));
}
- box_size.x -= text_box->get_margin(MARGIN_LEFT);
- box_size.x -= 28 * EDSCALE;
- box_size.y -= text_box->get_margin(MARGIN_TOP);
- box_size.y -= 28 * EDSCALE;
- text_box->set_custom_minimum_size(Size2(box_size.x, box_size.y));
- text_box->set_size(Size2(1, 1));
}
}
void VisualShaderEditor::_node_resized(const Vector2 &p_new_size, int p_type, int p_node) {
- VisualShader::Type type = get_current_shader_type();
- Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node);
+ Ref<VisualShaderNodeResizableBase> node = visual_shader->get_node(VisualShader::Type(p_type), p_node);
if (node.is_null()) {
return;
}
- undo_redo->create_action(TTR("Resize VisualShader node"), UndoRedo::MERGE_ENDS);
+ undo_redo->create_action(TTR("Resize VisualShader Node"), UndoRedo::MERGE_ENDS);
undo_redo->add_do_method(this, "_set_node_size", p_type, p_node, p_new_size);
undo_redo->add_undo_method(this, "_set_node_size", p_type, p_node, node->get_size());
undo_redo->commit_action();
@@ -1637,6 +1714,11 @@ void VisualShaderEditor::_add_texture3d_node(const String &p_path) {
texture3d->set_texture(ResourceLoader::load(p_path));
}
+void VisualShaderEditor::_add_curve_node(const String &p_path) {
+ VisualShaderNodeCurveTexture *curve = (VisualShaderNodeCurveTexture *)_add_node(curve_node_option_idx, -1);
+ curve->set_texture(ResourceLoader::load(p_path));
+}
+
VisualShaderNode *VisualShaderEditor::_add_node(int p_idx, int p_op_idx) {
ERR_FAIL_INDEX_V(p_idx, add_options.size(), nullptr);
@@ -1815,6 +1897,11 @@ VisualShaderNode *VisualShaderEditor::_add_node(int p_idx, int p_op_idx) {
undo_redo->add_undo_method(this, "_update_uniforms", true);
}
+ VisualShaderNodeCurveTexture *curve = Object::cast_to<VisualShaderNodeCurveTexture>(vsnode.ptr());
+ if (curve) {
+ graph_plugin->call_deferred("update_curve", id_to_use);
+ }
+
undo_redo->commit_action();
return vsnode.ptr();
}
@@ -1903,61 +1990,112 @@ void VisualShaderEditor::_connection_from_empty(const String &p_to, int p_to_slo
_show_members_dialog(true);
}
-void VisualShaderEditor::_delete_request(int which) {
- VisualShader::Type type = get_current_shader_type();
- Ref<VisualShaderNode> node = Ref<VisualShaderNode>(visual_shader->get_node(type, which));
-
- undo_redo->create_action(TTR("Delete Node"));
-
+void VisualShaderEditor::_delete_nodes(int p_type, const List<int> &p_nodes) {
+ VisualShader::Type type = VisualShader::Type(p_type);
List<VisualShader::Connection> conns;
visual_shader->get_node_connections(type, &conns);
- for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
- if (E->get().from_node == which || E->get().to_node == which) {
- undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
+
+ for (const List<int>::Element *F = p_nodes.front(); F; F = F->next()) {
+ for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
+ if (E->get().from_node == F->get() || E->get().to_node == F->get()) {
+ undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
+ }
}
}
- undo_redo->add_do_method(visual_shader.ptr(), "remove_node", type, which);
- undo_redo->add_undo_method(visual_shader.ptr(), "add_node", type, node, visual_shader->get_node_position(type, which), which);
- undo_redo->add_undo_method(graph_plugin.ptr(), "add_node", type, which);
+ Set<String> uniform_names;
- undo_redo->add_do_method(this, "_clear_buffer");
- undo_redo->add_undo_method(this, "_clear_buffer");
+ for (const List<int>::Element *F = p_nodes.front(); F; F = F->next()) {
+ Ref<VisualShaderNode> node = visual_shader->get_node(type, F->get());
- // restore size, inputs and outputs if node is group
- VisualShaderNodeGroupBase *group = Object::cast_to<VisualShaderNodeGroupBase>(node.ptr());
- if (group) {
- undo_redo->add_undo_method(group, "set_size", group->get_size());
- undo_redo->add_undo_method(group, "set_inputs", group->get_inputs());
- undo_redo->add_undo_method(group, "set_outputs", group->get_outputs());
- }
+ undo_redo->add_do_method(visual_shader.ptr(), "remove_node", type, F->get());
+ undo_redo->add_undo_method(visual_shader.ptr(), "add_node", type, node, visual_shader->get_node_position(type, F->get()), F->get());
+ undo_redo->add_undo_method(graph_plugin.ptr(), "add_node", type, F->get());
+
+ undo_redo->add_do_method(this, "_clear_buffer");
+ undo_redo->add_undo_method(this, "_clear_buffer");
+
+ // restore size, inputs and outputs if node is group
+ VisualShaderNodeGroupBase *group = Object::cast_to<VisualShaderNodeGroupBase>(node.ptr());
+ if (group) {
+ undo_redo->add_undo_method(group, "set_size", group->get_size());
+ undo_redo->add_undo_method(group, "set_inputs", group->get_inputs());
+ undo_redo->add_undo_method(group, "set_outputs", group->get_outputs());
+ }
- // restore expression text if node is expression
- VisualShaderNodeExpression *expression = Object::cast_to<VisualShaderNodeExpression>(node.ptr());
- if (expression) {
- undo_redo->add_undo_method(expression, "set_expression", expression->get_expression());
+ // restore expression text if node is expression
+ VisualShaderNodeExpression *expression = Object::cast_to<VisualShaderNodeExpression>(node.ptr());
+ if (expression) {
+ undo_redo->add_undo_method(expression, "set_expression", expression->get_expression());
+ }
+
+ VisualShaderNodeUniform *uniform = Object::cast_to<VisualShaderNodeUniform>(node.ptr());
+ if (uniform) {
+ uniform_names.insert(uniform->get_uniform_name());
+ }
}
- for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
- if (E->get().from_node == which || E->get().to_node == which) {
- undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
- undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
+ List<VisualShader::Connection> used_conns;
+ for (const List<int>::Element *F = p_nodes.front(); F; F = F->next()) {
+ for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
+ if (E->get().from_node == F->get() || E->get().to_node == F->get()) {
+ bool cancel = false;
+ for (List<VisualShader::Connection>::Element *R = used_conns.front(); R; R = R->next()) {
+ if (R->get().from_node == E->get().from_node && R->get().from_port == E->get().from_port && R->get().to_node == E->get().to_node && R->get().to_port == E->get().to_port) {
+ cancel = true; // to avoid ERR_ALREADY_EXISTS warning
+ break;
+ }
+ }
+ if (!cancel) {
+ undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
+ undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
+ used_conns.push_back(E->get());
+ }
+ }
}
}
- // delete a node from the graph
- undo_redo->add_do_method(graph_plugin.ptr(), "remove_node", type, which);
- VisualShaderNodeUniform *uniform = Object::cast_to<VisualShaderNodeUniform>(node.ptr());
- if (uniform) {
+ // delete nodes from the graph
+ for (const List<int>::Element *F = p_nodes.front(); F; F = F->next()) {
+ undo_redo->add_do_method(graph_plugin.ptr(), "remove_node", type, F->get());
+ }
+
+ // update uniform refs if any uniform has been deleted
+ if (uniform_names.size() > 0) {
undo_redo->add_do_method(this, "_update_uniforms", true);
undo_redo->add_undo_method(this, "_update_uniforms", true);
- Set<String> uniform_names;
- uniform_names.insert(uniform->get_uniform_name());
-
_update_uniform_refs(uniform_names);
}
+}
+
+void VisualShaderEditor::_delete_node_request(int p_type, int p_node) {
+ List<int> to_erase;
+ to_erase.push_back(p_node);
+
+ undo_redo->create_action(TTR("Delete VisualShader Node"));
+ _delete_nodes(p_type, to_erase);
+ undo_redo->commit_action();
+}
+
+void VisualShaderEditor::_delete_nodes_request() {
+ List<int> to_erase;
+
+ for (int i = 0; i < graph->get_child_count(); i++) {
+ GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(i));
+ if (gn) {
+ if (gn->is_selected() && gn->is_close_button_visible()) {
+ to_erase.push_back(gn->get_name().operator String().to_int());
+ }
+ }
+ }
+
+ if (to_erase.empty()) {
+ return;
+ }
+ undo_redo->create_action(TTR("Delete VisualShader Node(s)"));
+ _delete_nodes(get_current_shader_type(), to_erase);
undo_redo->commit_action();
}
@@ -2280,7 +2418,7 @@ void VisualShaderEditor::_clear_buffer() {
}
void VisualShaderEditor::_duplicate_nodes() {
- int type = edit_type->get_selected();
+ int type = get_current_shader_type();
List<int> nodes;
Set<int> excluded;
@@ -2291,13 +2429,13 @@ void VisualShaderEditor::_duplicate_nodes() {
return;
}
- undo_redo->create_action(TTR("Duplicate Nodes"));
+ undo_redo->create_action(TTR("Duplicate VisualShader Node(s)"));
_dup_paste_nodes(type, type, nodes, excluded, Vector2(10, 10) * EDSCALE, true);
}
void VisualShaderEditor::_copy_nodes() {
- copy_type = edit_type->get_selected();
+ copy_type = get_current_shader_type();
_clear_buffer();
@@ -2309,9 +2447,7 @@ void VisualShaderEditor::_paste_nodes(bool p_use_custom_position, const Vector2
return;
}
- int type = edit_type->get_selected();
-
- undo_redo->create_action(TTR("Paste Nodes"));
+ int type = get_current_shader_type();
float scale = graph->get_zoom();
@@ -2322,109 +2458,13 @@ void VisualShaderEditor::_paste_nodes(bool p_use_custom_position, const Vector2
mpos = graph->get_local_mouse_position();
}
+ undo_redo->create_action(TTR("Paste VisualShader Node(s)"));
+
_dup_paste_nodes(type, copy_type, copy_nodes_buffer, copy_nodes_excluded_buffer, (graph->get_scroll_ofs() / scale + mpos / scale - selection_center), false);
_dup_update_excluded(type, copy_nodes_excluded_buffer); // to prevent selection of previous copies at new paste
}
-void VisualShaderEditor::_delete_nodes() {
- VisualShader::Type type = get_current_shader_type();
- List<int> to_erase;
-
- for (int i = 0; i < graph->get_child_count(); i++) {
- GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(i));
- if (gn) {
- if (gn->is_selected() && gn->is_close_button_visible()) {
- to_erase.push_back(gn->get_name().operator String().to_int());
- }
- }
- }
-
- if (to_erase.empty()) {
- return;
- }
-
- undo_redo->create_action(TTR("Delete Nodes"));
-
- List<VisualShader::Connection> conns;
- visual_shader->get_node_connections(type, &conns);
-
- for (List<int>::Element *F = to_erase.front(); F; F = F->next()) {
- for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
- if (E->get().from_node == F->get() || E->get().to_node == F->get()) {
- undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
- }
- }
- }
-
- Set<String> uniform_names;
-
- for (List<int>::Element *F = to_erase.front(); F; F = F->next()) {
- Ref<VisualShaderNode> node = visual_shader->get_node(type, F->get());
-
- undo_redo->add_do_method(visual_shader.ptr(), "remove_node", type, F->get());
- undo_redo->add_undo_method(visual_shader.ptr(), "add_node", type, node, visual_shader->get_node_position(type, F->get()), F->get());
- undo_redo->add_undo_method(graph_plugin.ptr(), "add_node", type, F->get());
-
- undo_redo->add_do_method(this, "_clear_buffer");
- undo_redo->add_undo_method(this, "_clear_buffer");
-
- // restore size, inputs and outputs if node is group
- VisualShaderNodeGroupBase *group = Object::cast_to<VisualShaderNodeGroupBase>(node.ptr());
- if (group) {
- undo_redo->add_undo_method(group, "set_size", group->get_size());
- undo_redo->add_undo_method(group, "set_inputs", group->get_inputs());
- undo_redo->add_undo_method(group, "set_outputs", group->get_outputs());
- }
-
- // restore expression text if node is expression
- VisualShaderNodeExpression *expression = Object::cast_to<VisualShaderNodeExpression>(node.ptr());
- if (expression) {
- undo_redo->add_undo_method(expression, "set_expression", expression->get_expression());
- }
-
- VisualShaderNodeUniform *uniform = Object::cast_to<VisualShaderNodeUniform>(node.ptr());
- if (uniform) {
- uniform_names.insert(uniform->get_uniform_name());
- }
- }
-
- List<VisualShader::Connection> used_conns;
- for (List<int>::Element *F = to_erase.front(); F; F = F->next()) {
- for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
- if (E->get().from_node == F->get() || E->get().to_node == F->get()) {
- bool cancel = false;
- for (List<VisualShader::Connection>::Element *R = used_conns.front(); R; R = R->next()) {
- if (R->get().from_node == E->get().from_node && R->get().from_port == E->get().from_port && R->get().to_node == E->get().to_node && R->get().to_port == E->get().to_port) {
- cancel = true; // to avoid ERR_ALREADY_EXISTS warning
- break;
- }
- }
- if (!cancel) {
- undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
- undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
- used_conns.push_back(E->get());
- }
- }
- }
- }
-
- // delete nodes from the graph
- for (List<int>::Element *F = to_erase.front(); F; F = F->next()) {
- undo_redo->add_do_method(graph_plugin.ptr(), "remove_node", type, F->get());
- }
-
- // update uniform refs if any uniform has been deleted
- if (uniform_names.size() > 0) {
- undo_redo->add_do_method(this, "_update_uniforms", true);
- undo_redo->add_undo_method(this, "_update_uniforms", true);
-
- _update_uniform_refs(uniform_names);
- }
-
- undo_redo->commit_action();
-}
-
void VisualShaderEditor::_mode_selected(int p_id) {
visual_shader->set_shader_type(particles_mode ? VisualShader::Type(p_id + 3) : VisualShader::Type(p_id));
_update_options_menu();
@@ -2630,7 +2670,7 @@ void VisualShaderEditor::_node_menu_id_pressed(int p_idx) {
_paste_nodes(true, menu_point);
break;
case NodeMenuOptions::DELETE:
- _delete_nodes();
+ _delete_nodes_request();
break;
case NodeMenuOptions::DUPLICATE:
_duplicate_nodes();
@@ -2705,6 +2745,11 @@ void VisualShaderEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
_add_custom_node(arr[i]);
j++;
}
+ } else if (type == "CurveTexture") {
+ saved_node_pos = p_point + Vector2(0, j * 210 * EDSCALE);
+ saved_node_pos_dirty = true;
+ _add_curve_node(arr[i]);
+ j++;
} else if (ClassDB::get_parent_class(type) == "Texture2D") {
saved_node_pos = p_point + Vector2(0, j * 210 * EDSCALE);
saved_node_pos_dirty = true;
@@ -2842,8 +2887,8 @@ VisualShaderEditor::VisualShaderEditor() {
graph->connect("scroll_offset_changed", callable_mp(this, &VisualShaderEditor::_scroll_changed));
graph->connect("duplicate_nodes_request", callable_mp(this, &VisualShaderEditor::_duplicate_nodes));
graph->connect("copy_nodes_request", callable_mp(this, &VisualShaderEditor::_copy_nodes));
- graph->connect("paste_nodes_request", callable_mp(this, &VisualShaderEditor::_paste_nodes));
- graph->connect("delete_nodes_request", callable_mp(this, &VisualShaderEditor::_delete_nodes));
+ graph->connect("paste_nodes_request", callable_mp(this, &VisualShaderEditor::_paste_nodes), varray(false, Point2()));
+ graph->connect("delete_nodes_request", callable_mp(this, &VisualShaderEditor::_delete_nodes_request));
graph->connect("gui_input", callable_mp(this, &VisualShaderEditor::_graph_gui_input));
graph->connect("connection_to_empty", callable_mp(this, &VisualShaderEditor::_connection_to_empty));
graph->connect("connection_from_empty", callable_mp(this, &VisualShaderEditor::_connection_from_empty));
@@ -3330,6 +3375,8 @@ VisualShaderEditor::VisualShaderEditor() {
// TEXTURES
cubemap_node_option_idx = add_options.size();
add_options.push_back(AddOption("CubeMap", "Textures", "Functions", "VisualShaderNodeCubemap", TTR("Perform the cubic texture lookup."), -1, -1));
+ curve_node_option_idx = add_options.size();
+ add_options.push_back(AddOption("CurveTexture", "Textures", "Functions", "VisualShaderNodeCurveTexture", TTR("Perform the curve texture lookup."), -1, -1));
texture2d_node_option_idx = add_options.size();
add_options.push_back(AddOption("Texture2D", "Textures", "Functions", "VisualShaderNodeTexture", TTR("Perform the 2D texture lookup."), -1, -1));
texture2d_array_node_option_idx = add_options.size();
diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h
index d43af82238..73bebcd192 100644
--- a/editor/plugins/visual_shader_editor_plugin.h
+++ b/editor/plugins/visual_shader_editor_plugin.h
@@ -33,6 +33,7 @@
#include "editor/editor_node.h"
#include "editor/editor_plugin.h"
+#include "editor/plugins/curve_editor_plugin.h"
#include "editor/property_editor.h"
#include "scene/gui/button.h"
#include "scene/gui/graph_edit.h"
@@ -73,6 +74,8 @@ private:
VBoxContainer *preview_box;
LineEdit *uniform_name;
OptionButton *const_op;
+ CodeEdit *expression_edit;
+ CurveEditor *curve_editor;
};
Ref<VisualShader> visual_shader;
@@ -91,6 +94,8 @@ public:
void register_uniform_name(int p_id, LineEdit *p_uniform_name);
void register_default_input_button(int p_node_id, int p_port_id, Button *p_button);
void register_constant_option_btn(int p_node_id, OptionButton *p_button);
+ void register_expression_edit(int p_node_id, CodeEdit *p_expression_edit);
+ void register_curve_editor(int p_node_id, CurveEditor *p_curve_editor);
void clear_links();
void set_shader_type(VisualShader::Type p_type);
bool is_preview_visible(int p_id) const;
@@ -109,7 +114,9 @@ public:
void set_input_port_default_value(VisualShader::Type p_type, int p_node_id, int p_port_id, Variant p_value);
void update_uniform_refs();
void set_uniform_name(VisualShader::Type p_type, int p_node_id, const String &p_name);
+ void update_curve(int p_node_id);
void update_constant(VisualShader::Type p_type, int p_node_id);
+ void set_expression(VisualShader::Type p_type, int p_node_id, const String &p_expression);
int get_constant_index(float p_constant) const;
void update_node_size(int p_node_id);
VisualShader::Type get_shader_type() const;
@@ -251,6 +258,7 @@ class VisualShaderEditor : public VBoxContainer {
int texture2d_array_node_option_idx;
int texture3d_node_option_idx;
int custom_node_option_idx;
+ int curve_node_option_idx;
List<String> keyword_list;
List<VisualShaderNodeUniformRef> uniform_refs;
@@ -262,6 +270,8 @@ class VisualShaderEditor : public VBoxContainer {
void _add_texture2d_node(const String &p_path);
void _add_texture2d_array_node(const String &p_path);
void _add_texture3d_node(const String &p_path);
+ void _add_curve_node(const String &p_path);
+
VisualShaderNode *_add_node(int p_idx, int p_op_idx = -1);
void _update_options_menu();
void _set_mode(int p_which);
@@ -290,8 +300,9 @@ class VisualShaderEditor : public VBoxContainer {
void _scroll_changed(const Vector2 &p_scroll);
void _node_selected(Object *p_node);
- void _delete_request(int);
- void _delete_nodes();
+ void _delete_nodes(int p_type, const List<int> &p_nodes);
+ void _delete_node_request(int p_type, int p_node);
+ void _delete_nodes_request();
void _removed_from_graph();