summaryrefslogtreecommitdiffstats
path: root/editor/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'editor/plugins')
-rw-r--r--editor/plugins/abstract_polygon_2d_editor.cpp3
-rw-r--r--editor/plugins/abstract_polygon_2d_editor.h1
-rw-r--r--editor/plugins/animation_library_editor.cpp4
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp2
-rw-r--r--editor/plugins/animation_tree_editor_plugin.cpp3
-rw-r--r--editor/plugins/animation_tree_editor_plugin.h1
-rw-r--r--editor/plugins/bone_map_editor_plugin.cpp11
-rw-r--r--editor/plugins/bone_map_editor_plugin.h2
-rw-r--r--editor/plugins/camera_3d_editor_plugin.cpp3
-rw-r--r--editor/plugins/camera_3d_editor_plugin.h1
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp46
-rw-r--r--editor/plugins/cpu_particles_2d_editor_plugin.cpp3
-rw-r--r--editor/plugins/cpu_particles_2d_editor_plugin.h1
-rw-r--r--editor/plugins/cpu_particles_3d_editor_plugin.cpp3
-rw-r--r--editor/plugins/cpu_particles_3d_editor_plugin.h1
-rw-r--r--editor/plugins/editor_plugin_settings.cpp3
-rw-r--r--editor/plugins/editor_plugin_settings.h2
-rw-r--r--editor/plugins/font_config_plugin.cpp7
-rw-r--r--editor/plugins/font_config_plugin.h1
-rw-r--r--editor/plugins/gdextension_export_plugin.h5
-rw-r--r--editor/plugins/gizmos/camera_3d_gizmo_plugin.cpp31
-rw-r--r--editor/plugins/gpu_particles_2d_editor_plugin.cpp3
-rw-r--r--editor/plugins/gpu_particles_2d_editor_plugin.h1
-rw-r--r--editor/plugins/gpu_particles_3d_editor_plugin.cpp6
-rw-r--r--editor/plugins/gpu_particles_3d_editor_plugin.h3
-rw-r--r--editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp3
-rw-r--r--editor/plugins/gpu_particles_collision_sdf_editor_plugin.h1
-rw-r--r--editor/plugins/input_event_editor_plugin.cpp3
-rw-r--r--editor/plugins/input_event_editor_plugin.h1
-rw-r--r--editor/plugins/material_editor_plugin.cpp33
-rw-r--r--editor/plugins/material_editor_plugin.h5
-rw-r--r--editor/plugins/mesh_instance_3d_editor_plugin.cpp67
-rw-r--r--editor/plugins/mesh_instance_3d_editor_plugin.h3
-rw-r--r--editor/plugins/mesh_library_editor_plugin.cpp3
-rw-r--r--editor/plugins/mesh_library_editor_plugin.h3
-rw-r--r--editor/plugins/multimesh_editor_plugin.cpp3
-rw-r--r--editor/plugins/multimesh_editor_plugin.h1
-rw-r--r--editor/plugins/node_3d_editor_gizmos.cpp37
-rw-r--r--editor/plugins/node_3d_editor_gizmos.h5
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp362
-rw-r--r--editor/plugins/node_3d_editor_plugin.h44
-rw-r--r--editor/plugins/packed_scene_translation_parser_plugin.cpp5
-rw-r--r--editor/plugins/physical_bone_3d_editor_plugin.cpp3
-rw-r--r--editor/plugins/physical_bone_3d_editor_plugin.h3
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.cpp82
-rw-r--r--editor/plugins/root_motion_editor_plugin.cpp3
-rw-r--r--editor/plugins/root_motion_editor_plugin.h1
-rw-r--r--editor/plugins/script_editor_plugin.cpp43
-rw-r--r--editor/plugins/script_editor_plugin.h9
-rw-r--r--editor/plugins/script_text_editor.cpp27
-rw-r--r--editor/plugins/script_text_editor.h4
-rw-r--r--editor/plugins/shader/shader_editor.h50
-rw-r--r--editor/plugins/shader_editor_plugin.cpp177
-rw-r--r--editor/plugins/shader_editor_plugin.h25
-rw-r--r--editor/plugins/shader_file_editor_plugin.cpp3
-rw-r--r--editor/plugins/shader_file_editor_plugin.h1
-rw-r--r--editor/plugins/skeleton_2d_editor_plugin.cpp3
-rw-r--r--editor/plugins/skeleton_2d_editor_plugin.h1
-rw-r--r--editor/plugins/skeleton_ik_3d_editor_plugin.cpp3
-rw-r--r--editor/plugins/skeleton_ik_3d_editor_plugin.h3
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp90
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.h3
-rw-r--r--editor/plugins/text_editor.cpp4
-rw-r--r--editor/plugins/text_editor.h2
-rw-r--r--editor/plugins/text_shader_editor.cpp7
-rw-r--r--editor/plugins/text_shader_editor.h19
-rw-r--r--editor/plugins/texture_3d_editor_plugin.cpp127
-rw-r--r--editor/plugins/texture_3d_editor_plugin.h8
-rw-r--r--editor/plugins/texture_editor_plugin.cpp7
-rw-r--r--editor/plugins/texture_layered_editor_plugin.cpp241
-rw-r--r--editor/plugins/texture_layered_editor_plugin.h8
-rw-r--r--editor/plugins/theme_editor_preview.cpp2
-rw-r--r--editor/plugins/tiles/tile_atlas_view.cpp2
-rw-r--r--editor/plugins/tiles/tile_data_editors.cpp39
-rw-r--r--editor/plugins/tiles/tile_map_layer_editor.cpp2
-rw-r--r--editor/plugins/tiles/tile_set_atlas_source_editor.cpp6
-rw-r--r--editor/plugins/tiles/tile_set_editor.cpp2
-rw-r--r--editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp3
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp522
-rw-r--r--editor/plugins/visual_shader_editor_plugin.h61
-rw-r--r--editor/plugins/voxel_gi_editor_plugin.cpp3
-rw-r--r--editor/plugins/voxel_gi_editor_plugin.h1
82 files changed, 1615 insertions, 711 deletions
diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp
index f73c494b25..60d808952e 100644
--- a/editor/plugins/abstract_polygon_2d_editor.cpp
+++ b/editor/plugins/abstract_polygon_2d_editor.cpp
@@ -620,9 +620,6 @@ void AbstractPolygon2DEditor::edit(Node *p_polygon) {
canvas_item_editor->update_viewport();
}
-void AbstractPolygon2DEditor::_bind_methods() {
-}
-
void AbstractPolygon2DEditor::remove_point(const Vertex &p_vertex) {
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
Vector<Vector2> vertices = _get_polygon(p_vertex.polygon);
diff --git a/editor/plugins/abstract_polygon_2d_editor.h b/editor/plugins/abstract_polygon_2d_editor.h
index 42170d9ffd..66d4e1b7ef 100644
--- a/editor/plugins/abstract_polygon_2d_editor.h
+++ b/editor/plugins/abstract_polygon_2d_editor.h
@@ -109,7 +109,6 @@ protected:
void _notification(int p_what);
void _node_removed(Node *p_node);
- static void _bind_methods();
void remove_point(const Vertex &p_vertex);
Vertex get_active_point() const;
diff --git a/editor/plugins/animation_library_editor.cpp b/editor/plugins/animation_library_editor.cpp
index b07db993ba..38f8b16b34 100644
--- a/editor/plugins/animation_library_editor.cpp
+++ b/editor/plugins/animation_library_editor.cpp
@@ -561,7 +561,9 @@ void AnimationLibraryEditor::_button_pressed(TreeItem *p_item, int p_column, int
return;
}
- anim = anim->duplicate(); // Users simply dont care about referencing, so making a copy works better here.
+ if (!anim->get_path().is_resource_file()) {
+ anim = anim->duplicate(); // Users simply dont care about referencing, so making a copy works better here.
+ }
String base_name;
if (anim->get_name() != "") {
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index f64c4532a1..660e4647a1 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -1295,7 +1295,7 @@ void AnimationPlayerEditor::_seek_value_changed(float p_value, bool p_timeline_o
}
pos = CLAMP(pos, 0, (double)anim->get_length() - CMP_EPSILON2); // Hack: Avoid fposmod with LOOP_LINEAR.
- if (!p_timeline_only && anim.is_valid()) {
+ if (!p_timeline_only && anim.is_valid() && (!player->is_valid() || !Math::is_equal_approx(pos, player->get_current_animation_position()))) {
player->seek_internal(pos, true, true, false);
}
diff --git a/editor/plugins/animation_tree_editor_plugin.cpp b/editor/plugins/animation_tree_editor_plugin.cpp
index 757d410b78..7906b50c2c 100644
--- a/editor/plugins/animation_tree_editor_plugin.cpp
+++ b/editor/plugins/animation_tree_editor_plugin.cpp
@@ -199,9 +199,6 @@ void AnimationTreeEditor::_notification(int p_what) {
}
}
-void AnimationTreeEditor::_bind_methods() {
-}
-
AnimationTreeEditor *AnimationTreeEditor::singleton = nullptr;
void AnimationTreeEditor::add_plugin(AnimationTreeNodeEditorPlugin *p_editor) {
diff --git a/editor/plugins/animation_tree_editor_plugin.h b/editor/plugins/animation_tree_editor_plugin.h
index 8dc820695a..a234af6874 100644
--- a/editor/plugins/animation_tree_editor_plugin.h
+++ b/editor/plugins/animation_tree_editor_plugin.h
@@ -72,7 +72,6 @@ class AnimationTreeEditor : public VBoxContainer {
protected:
void _notification(int p_what);
void _node_removed(Node *p_node);
- static void _bind_methods();
static AnimationTreeEditor *singleton;
diff --git a/editor/plugins/bone_map_editor_plugin.cpp b/editor/plugins/bone_map_editor_plugin.cpp
index c00436b01f..32ff478c33 100644
--- a/editor/plugins/bone_map_editor_plugin.cpp
+++ b/editor/plugins/bone_map_editor_plugin.cpp
@@ -252,9 +252,6 @@ StringName BonePicker::get_selected_bone() {
return selected->get_text(0);
}
-void BonePicker::_bind_methods() {
-}
-
void BonePicker::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
@@ -1232,9 +1229,11 @@ void BoneMapper::auto_mapping_process(Ref<BoneMap> &p_bone_map) {
picklist.push_back("face");
int head = search_bone_by_name(skeleton, picklist, BONE_SEGREGATION_NONE, neck);
if (head == -1) {
- search_path = skeleton->get_bone_children(neck);
- if (search_path.size() == 1) {
- head = search_path[0]; // Maybe only one child of the Neck is Head.
+ if (neck != -1) {
+ search_path = skeleton->get_bone_children(neck);
+ if (search_path.size() == 1) {
+ head = search_path[0]; // Maybe only one child of the Neck is Head.
+ }
}
}
if (head == -1) {
diff --git a/editor/plugins/bone_map_editor_plugin.h b/editor/plugins/bone_map_editor_plugin.h
index f3aa2fc84d..988ad40ec4 100644
--- a/editor/plugins/bone_map_editor_plugin.h
+++ b/editor/plugins/bone_map_editor_plugin.h
@@ -122,8 +122,6 @@ public:
protected:
void _notification(int p_what);
- static void _bind_methods();
-
void _confirm();
private:
diff --git a/editor/plugins/camera_3d_editor_plugin.cpp b/editor/plugins/camera_3d_editor_plugin.cpp
index 62b40043c1..f4116ed364 100644
--- a/editor/plugins/camera_3d_editor_plugin.cpp
+++ b/editor/plugins/camera_3d_editor_plugin.cpp
@@ -46,9 +46,6 @@ void Camera3DEditor::_pressed() {
Node3DEditor::get_singleton()->set_custom_camera(sn);
}
-void Camera3DEditor::_bind_methods() {
-}
-
void Camera3DEditor::edit(Node *p_camera) {
node = p_camera;
diff --git a/editor/plugins/camera_3d_editor_plugin.h b/editor/plugins/camera_3d_editor_plugin.h
index 2e4d8a1ee3..1c6838aa02 100644
--- a/editor/plugins/camera_3d_editor_plugin.h
+++ b/editor/plugins/camera_3d_editor_plugin.h
@@ -45,7 +45,6 @@ class Camera3DEditor : public Control {
protected:
void _node_removed(Node *p_node);
- static void _bind_methods();
public:
void edit(Node *p_camera);
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 1afe2ddda7..8dad6d6dbd 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -64,6 +64,7 @@
#include "scene/resources/style_box_texture.h"
#define RULER_WIDTH (15 * EDSCALE)
+#define DRAG_THRESHOLD (8 * EDSCALE)
constexpr real_t SCALE_HANDLE_DISTANCE = 25;
constexpr real_t MOVE_HANDLE_DISTANCE = 25;
@@ -2319,7 +2320,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseMotion> m = p_event;
Ref<InputEventKey> k = p_event;
- if (drag_type == DRAG_NONE) {
+ if (drag_type == DRAG_NONE || (drag_type == DRAG_BOX_SELECTION && b.is_valid() && !b->is_pressed())) {
if (b.is_valid() && b->is_pressed() &&
((b->get_button_index() == MouseButton::RIGHT && b->is_alt_pressed() && tool == TOOL_SELECT) ||
(b->get_button_index() == MouseButton::LEFT && tool == TOOL_LIST_SELECT))) {
@@ -2411,47 +2412,58 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
return true;
}
- if (b.is_valid() && b->get_button_index() == MouseButton::LEFT && b->is_pressed() && !panner->is_panning() && (tool == TOOL_SELECT || tool == TOOL_MOVE || tool == TOOL_SCALE || tool == TOOL_ROTATE)) {
- // Single item selection
- Point2 click = transform.affine_inverse().xform(b->get_position());
+ Point2 click;
+ bool can_select = b.is_valid() && b->get_button_index() == MouseButton::LEFT && !panner->is_panning() && (tool == TOOL_SELECT || tool == TOOL_MOVE || tool == TOOL_SCALE || tool == TOOL_ROTATE);
+ if (can_select) {
+ click = transform.affine_inverse().xform(b->get_position());
+ // Allow selecting on release when performed very small box selection (necessary when Shift is pressed, see below).
+ can_select = b->is_pressed() || (drag_type == DRAG_BOX_SELECTION && click.distance_to(drag_from) <= DRAG_THRESHOLD);
+ }
+ if (can_select) {
+ // Single item selection.
Node *scene = EditorNode::get_singleton()->get_edited_scene();
if (!scene) {
return true;
}
- // Find the item to select
+ // Find the item to select.
CanvasItem *ci = nullptr;
Vector<_SelectResult> selection = Vector<_SelectResult>();
- // Retrieve the canvas items
+ // Retrieve the canvas items.
_get_canvas_items_at_pos(click, selection);
if (!selection.is_empty()) {
ci = selection[0].item;
}
- if (!ci) {
- // Start a box selection
+ // Shift also allows forcing box selection when item was clicked.
+ if (!ci || (b->is_shift_pressed() && b->is_pressed())) {
+ // Start a box selection.
if (!b->is_shift_pressed()) {
- // Clear the selection if not additive
+ // Clear the selection if not additive.
editor_selection->clear();
viewport->queue_redraw();
selected_from_canvas = true;
};
- drag_from = click;
- drag_type = DRAG_BOX_SELECTION;
- box_selecting_to = drag_from;
- return true;
+ if (b->is_pressed()) {
+ drag_from = click;
+ drag_type = DRAG_BOX_SELECTION;
+ box_selecting_to = drag_from;
+ return true;
+ }
} else {
bool still_selected = _select_click_on_item(ci, click, b->is_shift_pressed());
- // Start dragging
- if (still_selected && (tool == TOOL_SELECT || tool == TOOL_MOVE)) {
- // Drag the node(s) if requested
+ // Start dragging.
+ if (still_selected && (tool == TOOL_SELECT || tool == TOOL_MOVE) && b->is_pressed()) {
+ // Drag the node(s) if requested.
drag_start_origin = click;
drag_type = DRAG_QUEUED;
+ } else if (!b->is_pressed()) {
+ _reset_drag();
}
- // Select the item
+ // Select the item.
return true;
}
}
diff --git a/editor/plugins/cpu_particles_2d_editor_plugin.cpp b/editor/plugins/cpu_particles_2d_editor_plugin.cpp
index 92c0fd847b..4869a202d7 100644
--- a/editor/plugins/cpu_particles_2d_editor_plugin.cpp
+++ b/editor/plugins/cpu_particles_2d_editor_plugin.cpp
@@ -258,9 +258,6 @@ void CPUParticles2DEditorPlugin::_notification(int p_what) {
}
}
-void CPUParticles2DEditorPlugin::_bind_methods() {
-}
-
CPUParticles2DEditorPlugin::CPUParticles2DEditorPlugin() {
particles = nullptr;
diff --git a/editor/plugins/cpu_particles_2d_editor_plugin.h b/editor/plugins/cpu_particles_2d_editor_plugin.h
index 4d59c9981e..645e6d8345 100644
--- a/editor/plugins/cpu_particles_2d_editor_plugin.h
+++ b/editor/plugins/cpu_particles_2d_editor_plugin.h
@@ -79,7 +79,6 @@ class CPUParticles2DEditorPlugin : public EditorPlugin {
protected:
void _notification(int p_what);
- static void _bind_methods();
public:
virtual String get_name() const override { return "CPUParticles2D"; }
diff --git a/editor/plugins/cpu_particles_3d_editor_plugin.cpp b/editor/plugins/cpu_particles_3d_editor_plugin.cpp
index be2847d1d7..69f287c134 100644
--- a/editor/plugins/cpu_particles_3d_editor_plugin.cpp
+++ b/editor/plugins/cpu_particles_3d_editor_plugin.cpp
@@ -157,9 +157,6 @@ void CPUParticles3DEditor::_generate_emission_points() {
}
}
-void CPUParticles3DEditor::_bind_methods() {
-}
-
CPUParticles3DEditor::CPUParticles3DEditor() {
particles_editor_hb = memnew(HBoxContainer);
Node3DEditor::get_singleton()->add_control_to_menu_panel(particles_editor_hb);
diff --git a/editor/plugins/cpu_particles_3d_editor_plugin.h b/editor/plugins/cpu_particles_3d_editor_plugin.h
index 99178b7fde..2a1ea93ac8 100644
--- a/editor/plugins/cpu_particles_3d_editor_plugin.h
+++ b/editor/plugins/cpu_particles_3d_editor_plugin.h
@@ -60,7 +60,6 @@ class CPUParticles3DEditor : public GPUParticles3DEditorBase {
protected:
void _notification(int p_notification);
void _node_removed(Node *p_node);
- static void _bind_methods();
public:
void edit(CPUParticles3D *p_particles);
diff --git a/editor/plugins/editor_plugin_settings.cpp b/editor/plugins/editor_plugin_settings.cpp
index afc60b09d6..5949bc141f 100644
--- a/editor/plugins/editor_plugin_settings.cpp
+++ b/editor/plugins/editor_plugin_settings.cpp
@@ -199,9 +199,6 @@ Vector<String> EditorPluginSettings::_get_plugins(const String &p_dir) {
return plugins;
}
-void EditorPluginSettings::_bind_methods() {
-}
-
EditorPluginSettings::EditorPluginSettings() {
ProjectSettings::get_singleton()->add_hidden_prefix("editor_plugins/");
diff --git a/editor/plugins/editor_plugin_settings.h b/editor/plugins/editor_plugin_settings.h
index 5b470b3e58..ea7d0ea8b3 100644
--- a/editor/plugins/editor_plugin_settings.h
+++ b/editor/plugins/editor_plugin_settings.h
@@ -67,8 +67,6 @@ class EditorPluginSettings : public VBoxContainer {
protected:
void _notification(int p_what);
- static void _bind_methods();
-
public:
void update_plugins();
diff --git a/editor/plugins/font_config_plugin.cpp b/editor/plugins/font_config_plugin.cpp
index e6ce63fe36..ec9513363d 100644
--- a/editor/plugins/font_config_plugin.cpp
+++ b/editor/plugins/font_config_plugin.cpp
@@ -30,6 +30,7 @@
#include "font_config_plugin.h"
+#include "core/string/translation_server.h"
#include "editor/editor_settings.h"
#include "editor/import/dynamic_font_import_settings.h"
#include "editor/themes/editor_scale.h"
@@ -63,9 +64,6 @@ bool EditorPropertyFontMetaObject::_get(const StringName &p_name, Variant &r_ret
return false;
}
-void EditorPropertyFontMetaObject::_bind_methods() {
-}
-
void EditorPropertyFontMetaObject::set_dict(const Dictionary &p_dict) {
dict = p_dict;
}
@@ -924,7 +922,8 @@ void FontPreview::_notification(int p_what) {
name = vformat("%s (%s)", prev_font->get_font_name(), prev_font->get_font_style_name());
}
if (prev_font->is_class("FontVariation")) {
- name += " " + TTR(" - Variation");
+ // TRANSLATORS: This refers to variable font config, appended to the font name.
+ name += " - " + TTR("Variation");
}
font->draw_string(get_canvas_item(), Point2(0, font->get_height(font_size) + 2 * EDSCALE), name, HORIZONTAL_ALIGNMENT_CENTER, get_size().x, font_size, text_color);
diff --git a/editor/plugins/font_config_plugin.h b/editor/plugins/font_config_plugin.h
index 4e798fc3e8..e83f29a77b 100644
--- a/editor/plugins/font_config_plugin.h
+++ b/editor/plugins/font_config_plugin.h
@@ -46,7 +46,6 @@ class EditorPropertyFontMetaObject : public RefCounted {
protected:
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
- static void _bind_methods();
public:
void set_dict(const Dictionary &p_dict);
diff --git a/editor/plugins/gdextension_export_plugin.h b/editor/plugins/gdextension_export_plugin.h
index da136b70ae..0de6b7b611 100644
--- a/editor/plugins/gdextension_export_plugin.h
+++ b/editor/plugins/gdextension_export_plugin.h
@@ -31,6 +31,7 @@
#ifndef GDEXTENSION_EXPORT_PLUGIN_H
#define GDEXTENSION_EXPORT_PLUGIN_H
+#include "core/extension/gdextension_library_loader.h"
#include "editor/export/editor_export.h"
class GDExtensionExportPlugin : public EditorExportPlugin {
@@ -92,7 +93,7 @@ void GDExtensionExportPlugin::_export_file(const String &p_path, const String &p
for (const String &arch_tag : archs) {
PackedStringArray tags;
- String library_path = GDExtension::find_extension_library(
+ String library_path = GDExtensionLibraryLoader::find_extension_library(
p_path, config, [features_wo_arch, arch_tag](const String &p_feature) { return features_wo_arch.has(p_feature) || (p_feature == arch_tag); }, &tags);
if (libs_added.has(library_path)) {
continue; // Universal library, already added for another arch, do not duplicate.
@@ -129,7 +130,7 @@ void GDExtensionExportPlugin::_export_file(const String &p_path, const String &p
ERR_FAIL_MSG(vformat("No suitable library found for GDExtension: %s. Possible feature flags for your platform: %s", p_path, String(", ").join(features_vector)));
}
- Vector<SharedObject> dependencies_shared_objects = GDExtension::find_extension_dependencies(p_path, config, [p_features](String p_feature) { return p_features.has(p_feature); });
+ Vector<SharedObject> dependencies_shared_objects = GDExtensionLibraryLoader::find_extension_dependencies(p_path, config, [p_features](String p_feature) { return p_features.has(p_feature); });
for (const SharedObject &shared_object : dependencies_shared_objects) {
_add_shared_object(shared_object);
}
diff --git a/editor/plugins/gizmos/camera_3d_gizmo_plugin.cpp b/editor/plugins/gizmos/camera_3d_gizmo_plugin.cpp
index 19dd45a3ea..8d0222215c 100644
--- a/editor/plugins/gizmos/camera_3d_gizmo_plugin.cpp
+++ b/editor/plugins/gizmos/camera_3d_gizmo_plugin.cpp
@@ -112,9 +112,12 @@ void Camera3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id,
float a = _find_closest_angle_to_half_pi_arc(s[0], s[1], 1.0, gt2);
camera->set("fov", CLAMP(a * 2.0, 1, 179));
} else {
+ Camera3D::KeepAspect aspect = camera->get_keep_aspect_mode();
+ Vector3 camera_far = aspect == Camera3D::KeepAspect::KEEP_WIDTH ? Vector3(4096, 0, -1) : Vector3(0, 4096, -1);
+
Vector3 ra, rb;
- Geometry3D::get_closest_points_between_segments(Vector3(0, 0, -1), Vector3(4096, 0, -1), s[0], s[1], ra, rb);
- float d = ra.x * 2;
+ Geometry3D::get_closest_points_between_segments(Vector3(0, 0, -1), camera_far, s[0], s[1], ra, rb);
+ float d = aspect == Camera3D::KeepAspect::KEEP_WIDTH ? ra.x * 2 : ra.y * 2;
if (Node3DEditor::get_singleton()->is_snap_enabled()) {
d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap());
}
@@ -213,25 +216,33 @@ void Camera3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
} break;
case Camera3D::PROJECTION_ORTHOGONAL: {
+ Camera3D::KeepAspect aspect = camera->get_keep_aspect_mode();
+
float size = camera->get_size();
+ float keep_size = size * 0.5;
- float hsize = size * 0.5;
- Vector3 right(hsize * size_factor.x, 0, 0);
- Vector3 up(0, hsize * size_factor.y, 0);
+ Vector3 right, up;
Vector3 back(0, 0, -1.0);
Vector3 front(0, 0, 0);
+ if (aspect == Camera3D::KeepAspect::KEEP_WIDTH) {
+ right = Vector3(keep_size, 0, 0);
+ up = Vector3(0, keep_size / viewport_aspect, 0);
+ handles.push_back(right + back);
+ } else {
+ right = Vector3(keep_size * viewport_aspect, 0, 0);
+ up = Vector3(0, keep_size, 0);
+ handles.push_back(up + back);
+ }
+
ADD_QUAD(-up - right, -up + right, up + right, up - right);
ADD_QUAD(-up - right + back, -up + right + back, up + right + back, up - right + back);
ADD_QUAD(up + right, up + right + back, up - right + back, up - right);
ADD_QUAD(-up + right, -up + right + back, -up - right + back, -up - right);
- handles.push_back(right + back);
-
- right.x = MIN(right.x, hsize * 0.25);
- Vector3 tup(0, up.y + hsize / 2, back.z);
+ right.x = MIN(right.x, keep_size * 0.25);
+ Vector3 tup(0, up.y + keep_size / 2, back.z);
ADD_TRIANGLE(tup, right + up + back, -right + up + back);
-
} break;
case Camera3D::PROJECTION_FRUSTUM: {
diff --git a/editor/plugins/gpu_particles_2d_editor_plugin.cpp b/editor/plugins/gpu_particles_2d_editor_plugin.cpp
index b70c34b785..1b68b55ff6 100644
--- a/editor/plugins/gpu_particles_2d_editor_plugin.cpp
+++ b/editor/plugins/gpu_particles_2d_editor_plugin.cpp
@@ -360,9 +360,6 @@ void GPUParticles2DEditorPlugin::_notification(int p_what) {
}
}
-void GPUParticles2DEditorPlugin::_bind_methods() {
-}
-
GPUParticles2DEditorPlugin::GPUParticles2DEditorPlugin() {
particles = nullptr;
diff --git a/editor/plugins/gpu_particles_2d_editor_plugin.h b/editor/plugins/gpu_particles_2d_editor_plugin.h
index bb0ca5de3a..658e4d87e5 100644
--- a/editor/plugins/gpu_particles_2d_editor_plugin.h
+++ b/editor/plugins/gpu_particles_2d_editor_plugin.h
@@ -86,7 +86,6 @@ class GPUParticles2DEditorPlugin : public EditorPlugin {
protected:
void _notification(int p_what);
- static void _bind_methods();
public:
virtual String get_name() const override { return "GPUParticles2D"; }
diff --git a/editor/plugins/gpu_particles_3d_editor_plugin.cpp b/editor/plugins/gpu_particles_3d_editor_plugin.cpp
index 00c5332464..4e9be0aa53 100644
--- a/editor/plugins/gpu_particles_3d_editor_plugin.cpp
+++ b/editor/plugins/gpu_particles_3d_editor_plugin.cpp
@@ -198,9 +198,6 @@ void GPUParticles3DEditorBase::_node_selected(const NodePath &p_path) {
emission_dialog->popup_centered(Size2(300, 130));
}
-void GPUParticles3DEditorBase::_bind_methods() {
-}
-
GPUParticles3DEditorBase::GPUParticles3DEditorBase() {
emission_dialog = memnew(ConfirmationDialog);
emission_dialog->set_title(TTR("Create Emitter"));
@@ -402,9 +399,6 @@ void GPUParticles3DEditor::_generate_emission_points() {
}
}
-void GPUParticles3DEditor::_bind_methods() {
-}
-
GPUParticles3DEditor::GPUParticles3DEditor() {
node = nullptr;
particles_editor_hb = memnew(HBoxContainer);
diff --git a/editor/plugins/gpu_particles_3d_editor_plugin.h b/editor/plugins/gpu_particles_3d_editor_plugin.h
index 3b2ab2f8ca..5f59f6dca7 100644
--- a/editor/plugins/gpu_particles_3d_editor_plugin.h
+++ b/editor/plugins/gpu_particles_3d_editor_plugin.h
@@ -62,8 +62,6 @@ protected:
virtual void _generate_emission_points(){};
void _node_selected(const NodePath &p_path);
- static void _bind_methods();
-
public:
GPUParticles3DEditorBase();
};
@@ -95,7 +93,6 @@ class GPUParticles3DEditor : public GPUParticles3DEditorBase {
protected:
void _notification(int p_notification);
void _node_removed(Node *p_node);
- static void _bind_methods();
public:
void edit(GPUParticles3D *p_particles);
diff --git a/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp b/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp
index 25b076d0e5..c21a1b5dd6 100644
--- a/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp
+++ b/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp
@@ -175,9 +175,6 @@ void GPUParticlesCollisionSDF3DEditorPlugin::_sdf_save_path_and_bake(const Strin
}
}
-void GPUParticlesCollisionSDF3DEditorPlugin::_bind_methods() {
-}
-
GPUParticlesCollisionSDF3DEditorPlugin::GPUParticlesCollisionSDF3DEditorPlugin() {
bake_hb = memnew(HBoxContainer);
bake_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
diff --git a/editor/plugins/gpu_particles_collision_sdf_editor_plugin.h b/editor/plugins/gpu_particles_collision_sdf_editor_plugin.h
index bba8bd2584..3e1dae77ea 100644
--- a/editor/plugins/gpu_particles_collision_sdf_editor_plugin.h
+++ b/editor/plugins/gpu_particles_collision_sdf_editor_plugin.h
@@ -58,7 +58,6 @@ class GPUParticlesCollisionSDF3DEditorPlugin : public EditorPlugin {
void _sdf_save_path_and_bake(const String &p_path);
protected:
- static void _bind_methods();
void _notification(int p_what);
public:
diff --git a/editor/plugins/input_event_editor_plugin.cpp b/editor/plugins/input_event_editor_plugin.cpp
index 5a90d2de61..30debfc14f 100644
--- a/editor/plugins/input_event_editor_plugin.cpp
+++ b/editor/plugins/input_event_editor_plugin.cpp
@@ -33,9 +33,6 @@
#include "editor/event_listener_line_edit.h"
#include "editor/input_event_configuration_dialog.h"
-void InputEventConfigContainer::_bind_methods() {
-}
-
void InputEventConfigContainer::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
diff --git a/editor/plugins/input_event_editor_plugin.h b/editor/plugins/input_event_editor_plugin.h
index 48c16a4807..276bb74f6b 100644
--- a/editor/plugins/input_event_editor_plugin.h
+++ b/editor/plugins/input_event_editor_plugin.h
@@ -51,7 +51,6 @@ class InputEventConfigContainer : public VBoxContainer {
protected:
void _notification(int p_what);
- static void _bind_methods();
public:
void set_event(const Ref<InputEvent> &p_event);
diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp
index 602e6f945c..2702b6c909 100644
--- a/editor/plugins/material_editor_plugin.cpp
+++ b/editor/plugins/material_editor_plugin.cpp
@@ -33,6 +33,7 @@
#include "core/config/project_settings.h"
#include "editor/editor_node.h"
#include "editor/editor_settings.h"
+#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/themes/editor_scale.h"
#include "scene/3d/camera_3d.h"
@@ -41,6 +42,7 @@
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
#include "scene/gui/color_rect.h"
+#include "scene/gui/label.h"
#include "scene/gui/subviewport_container.h"
#include "scene/main/viewport.h"
#include "scene/resources/3d/fog_material.h"
@@ -80,11 +82,15 @@ void MaterialEditor::_notification(int p_what) {
sphere_switch->set_icon(theme_cache.sphere_icon);
box_switch->set_icon(theme_cache.box_icon);
+
+ error_label->add_theme_color_override(SceneStringName(font_color), get_theme_color(SNAME("error_color"), EditorStringName(Editor)));
} break;
case NOTIFICATION_DRAW: {
- Size2 size = get_size();
- draw_texture_rect(theme_cache.checkerboard, Rect2(Point2(), size), true);
+ if (!is_unsupported_shader_mode) {
+ Size2 size = get_size();
+ draw_texture_rect(theme_cache.checkerboard, Rect2(Point2(), size), true);
+ }
} break;
}
}
@@ -99,16 +105,20 @@ void MaterialEditor::_update_rotation() {
void MaterialEditor::edit(Ref<Material> p_material, const Ref<Environment> &p_env) {
material = p_material;
camera->set_environment(p_env);
+
+ is_unsupported_shader_mode = false;
if (!material.is_null()) {
Shader::Mode mode = p_material->get_shader_mode();
switch (mode) {
case Shader::MODE_CANVAS_ITEM:
+ layout_error->hide();
layout_3d->hide();
layout_2d->show();
vc->hide();
rect_instance->set_material(material);
break;
case Shader::MODE_SPATIAL:
+ layout_error->hide();
layout_2d->hide();
layout_3d->show();
vc->show();
@@ -116,6 +126,11 @@ void MaterialEditor::edit(Ref<Material> p_material, const Ref<Environment> &p_en
box_instance->set_material_override(material);
break;
default:
+ layout_error->show();
+ layout_2d->hide();
+ layout_3d->hide();
+ vc->hide();
+ is_unsupported_shader_mode = true;
break;
}
} else {
@@ -175,6 +190,20 @@ MaterialEditor::MaterialEditor() {
layout_2d->set_visible(false);
+ layout_error = memnew(VBoxContainer);
+ layout_error->set_alignment(BoxContainer::ALIGNMENT_CENTER);
+ layout_error->set_anchors_and_offsets_preset(PRESET_FULL_RECT);
+
+ error_label = memnew(Label);
+ error_label->set_text(TTR("Preview is not available for this shader mode."));
+ error_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
+ error_label->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER);
+ error_label->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART);
+
+ layout_error->add_child(error_label);
+ layout_error->hide();
+ add_child(layout_error);
+
// Spatial
vc = memnew(SubViewportContainer);
diff --git a/editor/plugins/material_editor_plugin.h b/editor/plugins/material_editor_plugin.h
index fb6bafc0ef..28c59d27db 100644
--- a/editor/plugins/material_editor_plugin.h
+++ b/editor/plugins/material_editor_plugin.h
@@ -45,6 +45,7 @@ class MeshInstance3D;
class SubViewport;
class SubViewportContainer;
class Button;
+class Label;
class MaterialEditor : public Control {
GDCLASS(MaterialEditor, Control);
@@ -69,6 +70,10 @@ class MaterialEditor : public Control {
Ref<SphereMesh> sphere_mesh;
Ref<BoxMesh> box_mesh;
+ VBoxContainer *layout_error = nullptr;
+ Label *error_label = nullptr;
+ bool is_unsupported_shader_mode = false;
+
HBoxContainer *layout_3d = nullptr;
Ref<Material> material;
diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.cpp b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
index 4ebacbd0b3..369d6ab009 100644
--- a/editor/plugins/mesh_instance_3d_editor_plugin.cpp
+++ b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
@@ -214,28 +214,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
} break;
case MENU_OPTION_CREATE_NAVMESH: {
- Ref<NavigationMesh> nmesh = memnew(NavigationMesh);
-
- if (nmesh.is_null()) {
- return;
- }
-
- nmesh->create_from_mesh(mesh);
- NavigationRegion3D *nmi = memnew(NavigationRegion3D);
- nmi->set_navigation_mesh(nmesh);
-
- Node *owner = get_tree()->get_edited_scene_root();
-
- EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
- ur->create_action(TTR("Create Navigation Mesh"));
-
- ur->add_do_method(node, "add_child", nmi, true);
- ur->add_do_method(nmi, "set_owner", owner);
- ur->add_do_method(Node3DEditor::get_singleton(), SceneStringName(_request_gizmo), nmi);
-
- ur->add_do_reference(nmi);
- ur->add_undo_method(node, "remove_child", nmi);
- ur->commit_action();
+ navigation_mesh_dialog->popup_centered(Vector2(200, 90));
} break;
case MENU_OPTION_CREATE_OUTLINE_MESH: {
@@ -472,6 +451,36 @@ void MeshInstance3DEditor::_debug_uv_draw() {
debug_uv->draw_multiline(uv_lines, get_theme_color(SNAME("mono_color"), EditorStringName(Editor)) * Color(1, 1, 1, 0.5));
}
+void MeshInstance3DEditor::_create_navigation_mesh() {
+ Ref<Mesh> mesh = node->get_mesh();
+ if (mesh.is_null()) {
+ return;
+ }
+
+ Ref<NavigationMesh> nmesh = memnew(NavigationMesh);
+
+ if (nmesh.is_null()) {
+ return;
+ }
+
+ nmesh->create_from_mesh(mesh);
+ NavigationRegion3D *nmi = memnew(NavigationRegion3D);
+ nmi->set_navigation_mesh(nmesh);
+
+ Node *owner = get_tree()->get_edited_scene_root();
+
+ EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
+ ur->create_action(TTR("Create Navigation Mesh"));
+
+ ur->add_do_method(node, "add_child", nmi, true);
+ ur->add_do_method(nmi, "set_owner", owner);
+ ur->add_do_method(Node3DEditor::get_singleton(), SceneStringName(_request_gizmo), nmi);
+
+ ur->add_do_reference(nmi);
+ ur->add_undo_method(node, "remove_child", nmi);
+ ur->commit_action();
+}
+
void MeshInstance3DEditor::_create_outline_mesh() {
Ref<Mesh> mesh = node->get_mesh();
if (mesh.is_null()) {
@@ -608,6 +617,20 @@ MeshInstance3DEditor::MeshInstance3DEditor() {
debug_uv->set_custom_minimum_size(Size2(600, 600) * EDSCALE);
debug_uv->connect(SceneStringName(draw), callable_mp(this, &MeshInstance3DEditor::_debug_uv_draw));
debug_uv_dialog->add_child(debug_uv);
+
+ navigation_mesh_dialog = memnew(ConfirmationDialog);
+ navigation_mesh_dialog->set_title(TTR("Create NavigationMesh"));
+ navigation_mesh_dialog->set_ok_button_text(TTR("Create"));
+
+ VBoxContainer *navigation_mesh_dialog_vbc = memnew(VBoxContainer);
+ navigation_mesh_dialog->add_child(navigation_mesh_dialog_vbc);
+
+ Label *navigation_mesh_l = memnew(Label);
+ navigation_mesh_l->set_text(TTR("Before converting a rendering mesh to a navigation mesh, please verify:\n\n- The mesh is two-dimensional.\n- The mesh has no surface overlap.\n- The mesh has no self-intersection.\n- The mesh surfaces have indices.\n\nIf the mesh does not fulfill these requirements, the pathfinding will be broken."));
+ navigation_mesh_dialog_vbc->add_child(navigation_mesh_l);
+
+ add_child(navigation_mesh_dialog);
+ navigation_mesh_dialog->connect("confirmed", callable_mp(this, &MeshInstance3DEditor::_create_navigation_mesh));
}
void MeshInstance3DEditorPlugin::edit(Object *p_object) {
diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.h b/editor/plugins/mesh_instance_3d_editor_plugin.h
index 20c151fb92..c982df9c5f 100644
--- a/editor/plugins/mesh_instance_3d_editor_plugin.h
+++ b/editor/plugins/mesh_instance_3d_editor_plugin.h
@@ -82,10 +82,13 @@ class MeshInstance3DEditor : public Control {
Control *debug_uv = nullptr;
Vector<Vector2> uv_lines;
+ ConfirmationDialog *navigation_mesh_dialog = nullptr;
+
void _create_collision_shape();
Vector<Ref<Shape3D>> create_shape_from_mesh(Ref<Mesh> p_mesh, int p_option, bool p_verbose);
void _menu_option(int p_option);
void _create_outline_mesh();
+ void _create_navigation_mesh();
void _create_uv_lines(int p_layer);
friend class MeshInstance3DEditorPlugin;
diff --git a/editor/plugins/mesh_library_editor_plugin.cpp b/editor/plugins/mesh_library_editor_plugin.cpp
index 0b2549986c..58cc670475 100644
--- a/editor/plugins/mesh_library_editor_plugin.cpp
+++ b/editor/plugins/mesh_library_editor_plugin.cpp
@@ -242,9 +242,6 @@ void MeshLibraryEditor::_menu_cbk(int p_option) {
}
}
-void MeshLibraryEditor::_bind_methods() {
-}
-
MeshLibraryEditor::MeshLibraryEditor() {
file = memnew(EditorFileDialog);
file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
diff --git a/editor/plugins/mesh_library_editor_plugin.h b/editor/plugins/mesh_library_editor_plugin.h
index 94f46beea1..5a9e32178d 100644
--- a/editor/plugins/mesh_library_editor_plugin.h
+++ b/editor/plugins/mesh_library_editor_plugin.h
@@ -68,9 +68,6 @@ class MeshLibraryEditor : public Control {
static void _import_scene(Node *p_scene, Ref<MeshLibrary> p_library, bool p_merge, bool p_apply_xforms);
static void _import_scene_parse_node(Ref<MeshLibrary> p_library, HashMap<int, MeshInstance3D *> &p_mesh_instances, Node *p_node, bool p_merge, bool p_apply_xforms);
-protected:
- static void _bind_methods();
-
public:
MenuButton *get_menu_button() const { return menu; }
diff --git a/editor/plugins/multimesh_editor_plugin.cpp b/editor/plugins/multimesh_editor_plugin.cpp
index 3980f23c8a..76ffdb02e1 100644
--- a/editor/plugins/multimesh_editor_plugin.cpp
+++ b/editor/plugins/multimesh_editor_plugin.cpp
@@ -266,9 +266,6 @@ void MultiMeshEditor::_browse(bool p_source) {
std->popup_scenetree_dialog(browsed_node);
}
-void MultiMeshEditor::_bind_methods() {
-}
-
MultiMeshEditor::MultiMeshEditor() {
options = memnew(MenuButton);
options->set_switch_on_hover(true);
diff --git a/editor/plugins/multimesh_editor_plugin.h b/editor/plugins/multimesh_editor_plugin.h
index 5051926c64..3fe63bfa92 100644
--- a/editor/plugins/multimesh_editor_plugin.h
+++ b/editor/plugins/multimesh_editor_plugin.h
@@ -79,7 +79,6 @@ class MultiMeshEditor : public Control {
protected:
void _node_removed(Node *p_node);
- static void _bind_methods();
public:
void edit(MultiMeshInstance3D *p_multimesh);
diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp
index de56767929..67d5e44ce5 100644
--- a/editor/plugins/node_3d_editor_gizmos.cpp
+++ b/editor/plugins/node_3d_editor_gizmos.cpp
@@ -81,6 +81,8 @@ void EditorNode3DGizmo::redraw() {
gizmo_plugin->redraw(this);
}
+ _update_bvh();
+
if (Node3DEditor::get_singleton()->is_current_selected_gizmo(this)) {
Node3DEditor::get_singleton()->update_transform_gizmo();
}
@@ -244,6 +246,32 @@ void EditorNode3DGizmo::add_mesh(const Ref<Mesh> &p_mesh, const Ref<Material> &p
instances.push_back(ins);
}
+void EditorNode3DGizmo::_update_bvh() {
+ ERR_FAIL_NULL(spatial_node);
+
+ Transform3D transform = spatial_node->get_global_transform();
+
+ float effective_icon_size = selectable_icon_size > 0.0f ? selectable_icon_size : 0.0f;
+ Vector3 icon_size_vector3 = Vector3(effective_icon_size, effective_icon_size, effective_icon_size);
+ AABB aabb(spatial_node->get_position() - icon_size_vector3 * 100.0f, icon_size_vector3 * 200.0f);
+
+ for (const Vector3 &segment_end : collision_segments) {
+ aabb.expand_to(transform.xform(segment_end));
+ }
+
+ if (collision_mesh.is_valid()) {
+ for (const Face3 &face : collision_mesh->get_faces()) {
+ aabb.expand_to(transform.xform(face.vertex[0]));
+ aabb.expand_to(transform.xform(face.vertex[1]));
+ aabb.expand_to(transform.xform(face.vertex[2]));
+ }
+ }
+
+ Node3DEditor::get_singleton()->update_gizmo_bvh_node(
+ bvh_node_id,
+ aabb);
+}
+
void EditorNode3DGizmo::add_lines(const Vector<Vector3> &p_lines, const Ref<Material> &p_material, bool p_billboard, const Color &p_modulate) {
add_vertices(p_lines, p_material, Mesh::PRIMITIVE_LINES, p_billboard, p_modulate);
}
@@ -765,6 +793,10 @@ void EditorNode3DGizmo::create() {
instances.write[i].create_instance(spatial_node, hidden);
}
+ bvh_node_id = Node3DEditor::get_singleton()->insert_gizmo_bvh_node(
+ spatial_node,
+ AABB(spatial_node->get_position(), Vector3(0, 0, 0)));
+
transform();
}
@@ -774,6 +806,8 @@ void EditorNode3DGizmo::transform() {
for (int i = 0; i < instances.size(); i++) {
RS::get_singleton()->instance_set_transform(instances[i].instance, spatial_node->get_global_transform() * instances[i].xform);
}
+
+ _update_bvh();
}
void EditorNode3DGizmo::free() {
@@ -790,6 +824,9 @@ void EditorNode3DGizmo::free() {
clear();
+ Node3DEditor::get_singleton()->remove_gizmo_bvh_node(bvh_node_id);
+ bvh_node_id = DynamicBVH::ID();
+
valid = false;
}
diff --git a/editor/plugins/node_3d_editor_gizmos.h b/editor/plugins/node_3d_editor_gizmos.h
index d7c368d5d0..c4b275032a 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/math/dynamic_bvh.h"
#include "core/templates/hash_map.h"
#include "core/templates/local_vector.h"
#include "scene/3d/camera_3d.h"
@@ -72,8 +73,12 @@ class EditorNode3DGizmo : public Node3DGizmo {
Vector<Instance> instances;
Node3D *spatial_node = nullptr;
+ DynamicBVH::ID bvh_node_id;
+
void _set_node_3d(Node *p_node) { set_node_3d(Object::cast_to<Node3D>(p_node)); }
+ void _update_bvh();
+
protected:
static void _bind_methods();
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 59a4ac8075..c58109427b 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -800,7 +800,6 @@ ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos) const {
RS::get_singleton()->sdfgi_set_debug_probe_select(pos, ray);
}
- Vector<ObjectID> instances = RenderingServer::get_singleton()->instances_cull_ray(pos, pos + ray * camera->get_far(), get_tree()->get_root()->get_world_3d()->get_scenario());
HashSet<Ref<EditorNode3DGizmo>> found_gizmos;
Node *edited_scene = get_tree()->get_edited_scene_root();
@@ -808,9 +807,9 @@ ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos) const {
Node *item = nullptr;
float closest_dist = 1e20;
- for (int i = 0; i < instances.size(); i++) {
- Node3D *spat = Object::cast_to<Node3D>(ObjectDB::get_instance(instances[i]));
+ Vector<Node3D *> nodes_with_gizmos = Node3DEditor::get_singleton()->gizmo_bvh_ray_query(pos, pos + ray * camera->get_far());
+ for (Node3D *spat : nodes_with_gizmos) {
if (!spat) {
continue;
}
@@ -863,12 +862,11 @@ void Node3DEditorViewport::_find_items_at_pos(const Point2 &p_pos, Vector<_RayRe
Vector3 ray = get_ray(p_pos);
Vector3 pos = get_ray_pos(p_pos);
- Vector<ObjectID> instances = RenderingServer::get_singleton()->instances_cull_ray(pos, pos + ray * camera->get_far(), get_tree()->get_root()->get_world_3d()->get_scenario());
- HashSet<Node3D *> found_nodes;
+ Vector<Node3D *> nodes_with_gizmos = Node3DEditor::get_singleton()->gizmo_bvh_ray_query(pos, pos + ray * camera->get_far());
- for (int i = 0; i < instances.size(); i++) {
- Node3D *spat = Object::cast_to<Node3D>(ObjectDB::get_instance(instances[i]));
+ HashSet<Node3D *> found_nodes;
+ for (Node3D *spat : nodes_with_gizmos) {
if (!spat) {
continue;
}
@@ -1046,7 +1044,7 @@ void Node3DEditorViewport::_select_region() {
_clear_selected();
}
- Vector<ObjectID> instances = RenderingServer::get_singleton()->instances_cull_convex(frustum, get_tree()->get_root()->get_world_3d()->get_scenario());
+ Vector<Node3D *> nodes_with_gizmos = Node3DEditor::get_singleton()->gizmo_bvh_frustum_query(frustum);
HashSet<Node3D *> found_nodes;
Vector<Node *> selected;
@@ -1055,8 +1053,7 @@ void Node3DEditorViewport::_select_region() {
return;
}
- for (int i = 0; i < instances.size(); i++) {
- Node3D *sp = Object::cast_to<Node3D>(ObjectDB::get_instance(instances[i]));
+ for (Node3D *sp : nodes_with_gizmos) {
if (!sp || _is_node_locked(sp)) {
continue;
}
@@ -1064,21 +1061,23 @@ void Node3DEditorViewport::_select_region() {
if (found_nodes.has(sp)) {
continue;
}
-
found_nodes.insert(sp);
Node *node = Object::cast_to<Node>(sp);
+
+ // Selection requires that the node is the edited scene or its descendant, and has an owner.
if (node != edited_scene) {
+ if (!node->get_owner() || !edited_scene->is_ancestor_of(node)) {
+ continue;
+ }
node = edited_scene->get_deepest_editable_node(node);
- }
-
- // Prevent selection of nodes not owned by the edited scene.
- while (node && node != edited_scene->get_parent()) {
- Node *node_owner = node->get_owner();
- if (node_owner == edited_scene || node == edited_scene || (node_owner != nullptr && edited_scene->is_editable_instance(node_owner))) {
- break;
+ while (node != edited_scene) {
+ Node *node_owner = node->get_owner();
+ if (node_owner == edited_scene || (node_owner != nullptr && edited_scene->is_editable_instance(node_owner))) {
+ break;
+ }
+ node = node->get_parent();
}
- node = node->get_parent();
}
// Replace the node by the group if grouped
@@ -1179,7 +1178,7 @@ void Node3DEditorViewport::_update_name() {
if (auto_orthogonal) {
// TRANSLATORS: This will be appended to the view name when Auto Orthogonal is enabled.
- name += TTR(" [auto]");
+ name += " " + TTR("[auto]");
}
view_menu->set_text(name);
@@ -1693,6 +1692,10 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
if (b.is_valid()) {
emit_signal(SNAME("clicked"), this);
+ ViewportNavMouseButton orbit_mouse_preference = (ViewportNavMouseButton)EDITOR_GET("editors/3d/navigation/orbit_mouse_button").operator int();
+ ViewportNavMouseButton pan_mouse_preference = (ViewportNavMouseButton)EDITOR_GET("editors/3d/navigation/pan_mouse_button").operator int();
+ ViewportNavMouseButton zoom_mouse_preference = (ViewportNavMouseButton)EDITOR_GET("editors/3d/navigation/zoom_mouse_button").operator int();
+
const real_t zoom_factor = 1 + (ZOOM_FREELOOK_MULTIPLIER - 1) * b->get_factor();
switch (b->get_button_index()) {
case MouseButton::WHEEL_UP: {
@@ -1710,8 +1713,6 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
}
} break;
case MouseButton::RIGHT: {
- NavigationScheme nav_scheme = (NavigationScheme)EDITOR_GET("editors/3d/navigation/navigation_scheme").operator int();
-
if (b->is_pressed() && _edit.gizmo.is_valid()) {
//restore
_edit.gizmo->commit_handle(_edit.gizmo_handle, _edit.gizmo_handle_secondary, _edit.gizmo_initial_value, true);
@@ -1719,11 +1720,15 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
}
if (_edit.mode == TRANSFORM_NONE && b->is_pressed()) {
- if (b->is_alt_pressed()) {
- if (nav_scheme == NAVIGATION_MAYA) {
- break;
- }
+ if (orbit_mouse_preference == NAVIGATION_RIGHT_MOUSE && _is_nav_modifier_pressed("spatial_editor/viewport_orbit_modifier_1") && _is_nav_modifier_pressed("spatial_editor/viewport_orbit_modifier_2")) {
+ break;
+ } else if (pan_mouse_preference == NAVIGATION_RIGHT_MOUSE && _is_nav_modifier_pressed("spatial_editor/viewport_pan_modifier_1") && _is_nav_modifier_pressed("spatial_editor/viewport_pan_modifier_2")) {
+ break;
+ } else if (zoom_mouse_preference == NAVIGATION_RIGHT_MOUSE && _is_nav_modifier_pressed("spatial_editor/viewport_zoom_modifier_1") && _is_nav_modifier_pressed("spatial_editor/viewport_zoom_modifier_2")) {
+ break;
+ }
+ if (b->is_alt_pressed()) {
_list_select(b);
return;
}
@@ -1754,6 +1759,14 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
} break;
case MouseButton::MIDDLE: {
if (b->is_pressed() && _edit.mode != TRANSFORM_NONE) {
+ if (orbit_mouse_preference == NAVIGATION_MIDDLE_MOUSE && _is_nav_modifier_pressed("spatial_editor/viewport_orbit_modifier_1") && _is_nav_modifier_pressed("spatial_editor/viewport_orbit_modifier_2")) {
+ break;
+ } else if (pan_mouse_preference == NAVIGATION_MIDDLE_MOUSE && _is_nav_modifier_pressed("spatial_editor/viewport_pan_modifier_1") && _is_nav_modifier_pressed("spatial_editor/viewport_pan_modifier_2")) {
+ break;
+ } else if (zoom_mouse_preference == NAVIGATION_MIDDLE_MOUSE && _is_nav_modifier_pressed("spatial_editor/viewport_zoom_modifier_1") && _is_nav_modifier_pressed("spatial_editor/viewport_zoom_modifier_2")) {
+ break;
+ }
+
switch (_edit.plane) {
case TRANSFORM_VIEW: {
_edit.plane = TRANSFORM_X_AXIS;
@@ -1792,8 +1805,11 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
commit_transform();
break; // just commit the edit, stop processing the event so we don't deselect the object
}
- NavigationScheme nav_scheme = (NavigationScheme)EDITOR_GET("editors/3d/navigation/navigation_scheme").operator int();
- if ((nav_scheme == NAVIGATION_MAYA || nav_scheme == NAVIGATION_MODO) && b->is_alt_pressed()) {
+ if (orbit_mouse_preference == NAVIGATION_LEFT_MOUSE && _is_nav_modifier_pressed("spatial_editor/viewport_orbit_modifier_1") && _is_nav_modifier_pressed("spatial_editor/viewport_orbit_modifier_2")) {
+ break;
+ } else if (pan_mouse_preference == NAVIGATION_LEFT_MOUSE && _is_nav_modifier_pressed("spatial_editor/viewport_pan_modifier_1") && _is_nav_modifier_pressed("spatial_editor/viewport_pan_modifier_2")) {
+ break;
+ } else if (zoom_mouse_preference == NAVIGATION_LEFT_MOUSE && _is_nav_modifier_pressed("spatial_editor/viewport_zoom_modifier_1") && _is_nav_modifier_pressed("spatial_editor/viewport_zoom_modifier_2")) {
break;
}
@@ -1812,7 +1828,9 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
{
int idx = view_menu->get_popup()->get_item_index(VIEW_GIZMOS);
+ int idx2 = view_menu->get_popup()->get_item_index(VIEW_TRANSFORM_GIZMO);
can_select_gizmos = can_select_gizmos && view_menu->get_popup()->is_item_checked(idx);
+ transform_gizmo_visible = view_menu->get_popup()->is_item_checked(idx2);
}
// Gizmo handles
@@ -1916,12 +1934,17 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
}
if (after != EditorPlugin::AFTER_GUI_INPUT_CUSTOM) {
- //clicking is always deferred to either move or release
- clicked = _select_ray(b->get_position());
+ // Single item selection.
+ Vector<_RayResult> selection;
+ _find_items_at_pos(b->get_position(), selection, false);
+ if (!selection.is_empty()) {
+ clicked = selection[0].item->get_instance_id();
+ }
+
selection_in_progress = true;
if (clicked.is_null()) {
- //default to regionselect
+ // Default to region select.
cursor.region_select = true;
cursor.region_begin = b->get_position();
cursor.region_end = b->get_position();
@@ -1984,6 +2007,24 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
}
}
+ ViewportNavMouseButton orbit_mouse_preference = (ViewportNavMouseButton)EDITOR_GET("editors/3d/navigation/orbit_mouse_button").operator int();
+ ViewportNavMouseButton pan_mouse_preference = (ViewportNavMouseButton)EDITOR_GET("editors/3d/navigation/pan_mouse_button").operator int();
+ ViewportNavMouseButton zoom_mouse_preference = (ViewportNavMouseButton)EDITOR_GET("editors/3d/navigation/zoom_mouse_button").operator int();
+ bool orbit_mod_pressed = _is_nav_modifier_pressed("spatial_editor/viewport_orbit_modifier_1") && _is_nav_modifier_pressed("spatial_editor/viewport_orbit_modifier_2");
+ bool pan_mod_pressed = _is_nav_modifier_pressed("spatial_editor/viewport_pan_modifier_1") && _is_nav_modifier_pressed("spatial_editor/viewport_pan_modifier_2");
+ bool zoom_mod_pressed = _is_nav_modifier_pressed("spatial_editor/viewport_zoom_modifier_1") && _is_nav_modifier_pressed("spatial_editor/viewport_zoom_modifier_2");
+ int orbit_mod_input_count = _get_shortcut_input_count("spatial_editor/viewport_orbit_modifier_1") + _get_shortcut_input_count("spatial_editor/viewport_orbit_modifier_2");
+ int pan_mod_input_count = _get_shortcut_input_count("spatial_editor/viewport_pan_modifier_1") + _get_shortcut_input_count("spatial_editor/viewport_pan_modifier_2");
+ int zoom_mod_input_count = _get_shortcut_input_count("spatial_editor/viewport_zoom_modifier_1") + _get_shortcut_input_count("spatial_editor/viewport_zoom_modifier_2");
+ bool orbit_not_empty = !_is_shortcut_empty("spatial_editor/viewport_zoom_modifier_1") || !_is_shortcut_empty("spatial_editor/viewport_zoom_modifier_2");
+ bool pan_not_empty = !_is_shortcut_empty("spatial_editor/viewport_pan_modifier_1") || !_is_shortcut_empty("spatial_editor/viewport_pan_modifier_2");
+ bool zoom_not_empty = !_is_shortcut_empty("spatial_editor/viewport_orbit_modifier_1") || !_is_shortcut_empty("spatial_editor/viewport_orbit_modifier_2");
+ Vector<ShortcutCheckSet> shortcut_check_sets;
+ shortcut_check_sets.push_back(ShortcutCheckSet(orbit_mod_pressed, orbit_not_empty, orbit_mod_input_count, orbit_mouse_preference, NAVIGATION_ORBIT));
+ shortcut_check_sets.push_back(ShortcutCheckSet(pan_mod_pressed, pan_not_empty, pan_mod_input_count, pan_mouse_preference, NAVIGATION_PAN));
+ shortcut_check_sets.push_back(ShortcutCheckSet(zoom_mod_pressed, zoom_not_empty, zoom_mod_input_count, zoom_mouse_preference, NAVIGATION_ZOOM));
+ shortcut_check_sets.sort_custom<ShortcutCheckSetComparator>();
+
Ref<InputEventMouseMotion> m = p_event;
// Instant transforms process mouse motion in input() to handle wrapping.
@@ -2028,7 +2069,6 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
_transform_gizmo_select(_edit.mouse_pos, true);
}
- NavigationScheme nav_scheme = (NavigationScheme)EDITOR_GET("editors/3d/navigation/navigation_scheme").operator int();
NavigationMode nav_mode = NAVIGATION_NONE;
if (_edit.gizmo.is_valid()) {
@@ -2038,14 +2078,9 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
set_message(n + ": " + String(v));
} else if (m->get_button_mask().has_flag(MouseButtonMask::LEFT)) {
- if (nav_scheme == NAVIGATION_MAYA && m->is_alt_pressed()) {
- nav_mode = NAVIGATION_ORBIT;
- } else if (nav_scheme == NAVIGATION_MODO && m->is_alt_pressed() && m->is_shift_pressed()) {
- nav_mode = NAVIGATION_PAN;
- } else if (nav_scheme == NAVIGATION_MODO && m->is_alt_pressed() && m->is_command_or_control_pressed()) {
- nav_mode = NAVIGATION_ZOOM;
- } else if (nav_scheme == NAVIGATION_MODO && m->is_alt_pressed()) {
- nav_mode = NAVIGATION_ORBIT;
+ NavigationMode change_nav_from_shortcut = _get_nav_mode_from_shortcut_check(NAVIGATION_LEFT_MOUSE, shortcut_check_sets, false);
+ if (change_nav_from_shortcut != NAVIGATION_NONE) {
+ nav_mode = change_nav_from_shortcut;
} else {
const bool movement_threshold_passed = _edit.original_mouse_pos.distance_to(_edit.mouse_pos) > 8 * EDSCALE;
@@ -2076,8 +2111,9 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
update_transform(_get_key_modifier(m) == Key::SHIFT);
}
} else if (m->get_button_mask().has_flag(MouseButtonMask::RIGHT) || freelook_active) {
- if (nav_scheme == NAVIGATION_MAYA && m->is_alt_pressed()) {
- nav_mode = NAVIGATION_ZOOM;
+ NavigationMode change_nav_from_shortcut = _get_nav_mode_from_shortcut_check(NAVIGATION_RIGHT_MOUSE, shortcut_check_sets, false);
+ if (m->get_button_mask().has_flag(MouseButtonMask::RIGHT) && change_nav_from_shortcut != NAVIGATION_NONE) {
+ nav_mode = change_nav_from_shortcut;
} else if (freelook_active) {
nav_mode = NAVIGATION_LOOK;
} else if (orthogonal) {
@@ -2085,34 +2121,16 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
}
} else if (m->get_button_mask().has_flag(MouseButtonMask::MIDDLE)) {
- const Key mod = _get_key_modifier(m);
- if (nav_scheme == NAVIGATION_GODOT) {
- if (mod == _get_key_modifier_setting("editors/3d/navigation/pan_modifier")) {
- nav_mode = NAVIGATION_PAN;
- } else if (mod == _get_key_modifier_setting("editors/3d/navigation/zoom_modifier")) {
- nav_mode = NAVIGATION_ZOOM;
- } else if (mod == Key::ALT || mod == _get_key_modifier_setting("editors/3d/navigation/orbit_modifier")) {
- // Always allow Alt as a modifier to better support graphic tablets.
- nav_mode = NAVIGATION_ORBIT;
- }
- } else if (nav_scheme == NAVIGATION_MAYA) {
- if (mod == _get_key_modifier_setting("editors/3d/navigation/pan_modifier")) {
- nav_mode = NAVIGATION_PAN;
- }
+ NavigationMode change_nav_from_shortcut = _get_nav_mode_from_shortcut_check(NAVIGATION_MIDDLE_MOUSE, shortcut_check_sets, false);
+ if (change_nav_from_shortcut != NAVIGATION_NONE) {
+ nav_mode = change_nav_from_shortcut;
}
+
} else if (EDITOR_GET("editors/3d/navigation/emulate_3_button_mouse")) {
// Handle trackpad (no external mouse) use case
- const Key mod = _get_key_modifier(m);
-
- if (mod != Key::NONE) {
- if (mod == _get_key_modifier_setting("editors/3d/navigation/pan_modifier")) {
- nav_mode = NAVIGATION_PAN;
- } else if (mod == _get_key_modifier_setting("editors/3d/navigation/zoom_modifier")) {
- nav_mode = NAVIGATION_ZOOM;
- } else if (mod == Key::ALT || mod == _get_key_modifier_setting("editors/3d/navigation/orbit_modifier")) {
- // Always allow Alt as a modifier to better support graphic tablets.
- nav_mode = NAVIGATION_ORBIT;
- }
+ NavigationMode change_nav_from_shortcut = _get_nav_mode_from_shortcut_check(NAVIGATION_LEFT_MOUSE, shortcut_check_sets, true);
+ if (change_nav_from_shortcut != NAVIGATION_NONE) {
+ nav_mode = change_nav_from_shortcut;
}
}
@@ -2153,25 +2171,11 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
Ref<InputEventPanGesture> pan_gesture = p_event;
if (pan_gesture.is_valid()) {
- NavigationScheme nav_scheme = (NavigationScheme)EDITOR_GET("editors/3d/navigation/navigation_scheme").operator int();
NavigationMode nav_mode = NAVIGATION_NONE;
- if (nav_scheme == NAVIGATION_GODOT) {
- const Key mod = _get_key_modifier(pan_gesture);
-
- if (mod == _get_key_modifier_setting("editors/3d/navigation/pan_modifier")) {
- nav_mode = NAVIGATION_PAN;
- } else if (mod == _get_key_modifier_setting("editors/3d/navigation/zoom_modifier")) {
- nav_mode = NAVIGATION_ZOOM;
- } else if (mod == Key::ALT || mod == _get_key_modifier_setting("editors/3d/navigation/orbit_modifier")) {
- // Always allow Alt as a modifier to better support graphic tablets.
- nav_mode = NAVIGATION_ORBIT;
- }
-
- } else if (nav_scheme == NAVIGATION_MAYA) {
- if (pan_gesture->is_alt_pressed()) {
- nav_mode = NAVIGATION_PAN;
- }
+ NavigationMode change_nav_from_shortcut = _get_nav_mode_from_shortcut_check(NAVIGATION_LEFT_MOUSE, shortcut_check_sets, true);
+ if (change_nav_from_shortcut != NAVIGATION_NONE) {
+ nav_mode = change_nav_from_shortcut;
}
switch (nav_mode) {
@@ -2252,6 +2256,11 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
}
if (_edit.mode == TRANSFORM_NONE) {
+ if (_edit.gizmo.is_null() && is_freelook_active() && k->get_keycode() == Key::ESCAPE) {
+ set_freelook_active(false);
+ return;
+ }
+
if (_edit.gizmo.is_valid() && (k->get_keycode() == Key::ESCAPE || k->get_keycode() == Key::BACKSPACE)) {
// Restore.
_edit.gizmo->commit_handle(_edit.gizmo_handle, _edit.gizmo_handle_secondary, _edit.gizmo_initial_value, true);
@@ -2436,6 +2445,32 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
}
}
+int Node3DEditorViewport::_get_shortcut_input_count(const String &p_name) {
+ Ref<Shortcut> check_shortcut = ED_GET_SHORTCUT(p_name);
+
+ ERR_FAIL_COND_V_MSG(check_shortcut.is_null(), 0, "The Shortcut was null, possible name mismatch.");
+
+ return check_shortcut->get_events().size();
+}
+
+Node3DEditorViewport::NavigationMode Node3DEditorViewport::_get_nav_mode_from_shortcut_check(ViewportNavMouseButton p_mouse_button, Vector<ShortcutCheckSet> p_shortcut_check_sets, bool p_use_not_empty) {
+ if (p_use_not_empty) {
+ for (const ShortcutCheckSet &shortcut_check_set : p_shortcut_check_sets) {
+ if (shortcut_check_set.mod_pressed && shortcut_check_set.shortcut_not_empty) {
+ return shortcut_check_set.result_nav_mode;
+ }
+ }
+ } else {
+ for (const ShortcutCheckSet &shortcut_check_set : p_shortcut_check_sets) {
+ if (shortcut_check_set.mouse_preference == p_mouse_button && shortcut_check_set.mod_pressed) {
+ return shortcut_check_set.result_nav_mode;
+ }
+ }
+ }
+
+ return NAVIGATION_NONE;
+}
+
void Node3DEditorViewport::_nav_pan(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative) {
const NavigationScheme nav_scheme = (NavigationScheme)EDITOR_GET("editors/3d/navigation/navigation_scheme").operator int();
@@ -2635,6 +2670,18 @@ void Node3DEditorViewport::scale_freelook_speed(real_t scale) {
surface->queue_redraw();
}
+bool Node3DEditorViewport::_is_nav_modifier_pressed(const String &p_name) {
+ return _is_shortcut_empty(p_name) || Input::get_singleton()->is_action_pressed(p_name);
+}
+
+bool Node3DEditorViewport::_is_shortcut_empty(const String &p_name) {
+ Ref<Shortcut> check_shortcut = ED_GET_SHORTCUT(p_name);
+
+ ERR_FAIL_COND_V_MSG(check_shortcut.is_null(), true, "The Shortcut was null, possible name mismatch.");
+
+ return check_shortcut->get_events().is_empty();
+}
+
Point2 Node3DEditorViewport::_get_warped_mouse_motion(const Ref<InputEventMouseMotion> &p_ev_mouse_motion) const {
Point2 relative;
if (bool(EDITOR_GET("editors/3d/navigation/warped_mouse_panning"))) {
@@ -3107,6 +3154,7 @@ void Node3DEditorViewport::_notification(int p_what) {
case NOTIFICATION_DRAG_END: {
// Clear preview material when dropped outside applicable object.
if (spatial_editor->get_preview_material().is_valid() && !is_drag_successful()) {
+ _reset_preview_material();
_remove_preview_material();
} else {
_remove_preview_node();
@@ -3529,6 +3577,15 @@ void Node3DEditorViewport::_menu_option(int p_option) {
view_menu->get_popup()->set_item_checked(idx, current);
} break;
+ case VIEW_TRANSFORM_GIZMO: {
+ int idx = view_menu->get_popup()->get_item_index(VIEW_TRANSFORM_GIZMO);
+ bool current = view_menu->get_popup()->is_item_checked(idx);
+ current = !current;
+ transform_gizmo_visible = current;
+
+ spatial_editor->update_transform_gizmo();
+ view_menu->get_popup()->set_item_checked(idx, current);
+ } break;
case VIEW_HALF_RESOLUTION: {
int idx = view_menu->get_popup()->get_item_index(VIEW_HALF_RESOLUTION);
bool current = view_menu->get_popup()->is_item_checked(idx);
@@ -3893,7 +3950,7 @@ void Node3DEditorViewport::update_transform_gizmo_view() {
return;
}
- bool show_gizmo = spatial_editor->is_gizmo_visible() && !_edit.instant;
+ bool show_gizmo = spatial_editor->is_gizmo_visible() && !_edit.instant && transform_gizmo_visible;
for (int i = 0; i < 3; i++) {
Transform3D axis_angle;
if (xform.basis.get_column(i).normalized().dot(xform.basis.get_column((i + 1) % 3).normalized()) < 1.0) {
@@ -3924,7 +3981,7 @@ void Node3DEditorViewport::update_transform_gizmo_view() {
xform.orthonormalize();
xform.basis.scale(scale);
RenderingServer::get_singleton()->instance_set_transform(rotate_gizmo_instance[3], xform);
- RenderingServer::get_singleton()->instance_set_visible(rotate_gizmo_instance[3], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE));
+ RenderingServer::get_singleton()->instance_set_visible(rotate_gizmo_instance[3], spatial_editor->is_gizmo_visible() && transform_gizmo_visible && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE));
}
void Node3DEditorViewport::set_state(const Dictionary &p_state) {
@@ -4001,6 +4058,14 @@ void Node3DEditorViewport::set_state(const Dictionary &p_state) {
_menu_option(VIEW_GIZMOS);
}
}
+ if (p_state.has("grid")) {
+ bool grid = p_state["grid"];
+
+ int idx = view_menu->get_popup()->get_item_index(VIEW_GRID);
+ if (view_menu->get_popup()->is_item_checked(idx) != grid) {
+ _menu_option(VIEW_GRID);
+ }
+ }
if (p_state.has("information")) {
bool information = p_state["information"];
@@ -4079,6 +4144,7 @@ Dictionary Node3DEditorViewport::get_state() const {
d["listener"] = viewport->is_audio_listener_3d();
d["doppler"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_AUDIO_DOPPLER));
d["gizmos"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_GIZMOS));
+ d["grid"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_GRID));
d["information"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_INFORMATION));
d["frame_time"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_FRAME_TIME));
d["half_res"] = subviewport_container->get_stretch_shrink() > 1;
@@ -5001,14 +5067,24 @@ void Node3DEditorViewport::update_transform(bool p_shift) {
} break;
case TRANSFORM_ROTATE: {
- Plane plane = Plane(_get_camera_normal(), _edit.center);
+ Plane plane;
+ if (camera->get_projection() == Camera3D::PROJECTION_PERSPECTIVE) {
+ Vector3 cam_to_obj = _edit.center - _get_camera_position();
+ if (!cam_to_obj.is_zero_approx()) {
+ plane = Plane(cam_to_obj.normalized(), _edit.center);
+ } else {
+ plane = Plane(_get_camera_normal(), _edit.center);
+ }
+ } else {
+ plane = Plane(_get_camera_normal(), _edit.center);
+ }
Vector3 local_axis;
Vector3 global_axis;
switch (_edit.plane) {
case TRANSFORM_VIEW:
// local_axis unused
- global_axis = _get_camera_normal();
+ global_axis = plane.normal;
break;
case TRANSFORM_X_AXIS:
local_axis = Vector3(1, 0, 0);
@@ -5039,7 +5115,7 @@ void Node3DEditorViewport::update_transform(bool p_shift) {
break;
}
- static const float orthogonal_threshold = Math::cos(Math::deg_to_rad(87.0f));
+ static const float orthogonal_threshold = Math::cos(Math::deg_to_rad(85.0f));
bool axis_is_orthogonal = ABS(plane.normal.dot(global_axis)) < orthogonal_threshold;
double angle = 0.0f;
@@ -5301,6 +5377,7 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p
view_menu->get_popup()->add_separator();
view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_environment", TTR("View Environment")), VIEW_ENVIRONMENT);
view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_gizmos", TTR("View Gizmos")), VIEW_GIZMOS);
+ view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_transform_gizmo", TTR("View Transform Gizmo")), VIEW_TRANSFORM_GIZMO);
view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_grid_lines", TTR("View Grid")), VIEW_GRID);
view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_information", TTR("View Information")), VIEW_INFORMATION);
view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_fps", TTR("View Frame Time")), VIEW_FRAME_TIME);
@@ -5311,6 +5388,7 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p
view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_audio_listener", TTR("Audio Listener")), VIEW_AUDIO_LISTENER);
view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_audio_doppler", TTR("Enable Doppler")), VIEW_AUDIO_DOPPLER);
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_GIZMOS), true);
+ view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_TRANSFORM_GIZMO), true);
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_GRID), true);
view_menu->get_popup()->add_separator();
@@ -5345,6 +5423,14 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p
view_menu->get_popup()->set_item_tooltip(shadeless_idx, unsupported_tooltip);
}
+ // Registering with Key::NONE intentionally creates an empty Array.
+ register_shortcut_action("spatial_editor/viewport_orbit_modifier_1", TTR("Viewport Orbit Modifier 1"), Key::NONE);
+ register_shortcut_action("spatial_editor/viewport_orbit_modifier_2", TTR("Viewport Orbit Modifier 2"), Key::NONE);
+ register_shortcut_action("spatial_editor/viewport_pan_modifier_1", TTR("Viewport Pan Modifier 1"), Key::SHIFT);
+ register_shortcut_action("spatial_editor/viewport_pan_modifier_2", TTR("Viewport Pan Modifier 2"), Key::NONE);
+ register_shortcut_action("spatial_editor/viewport_zoom_modifier_1", TTR("Viewport Zoom Modifier 1"), Key::SHIFT);
+ register_shortcut_action("spatial_editor/viewport_zoom_modifier_2", TTR("Viewport Zoom Modifier 2"), Key::CTRL);
+
register_shortcut_action("spatial_editor/freelook_left", TTR("Freelook Left"), Key::A, true);
register_shortcut_action("spatial_editor/freelook_right", TTR("Freelook Right"), Key::D, true);
register_shortcut_action("spatial_editor/freelook_forward", TTR("Freelook Forward"), Key::W, true);
@@ -7289,9 +7375,15 @@ void Node3DEditor::_init_grid() {
bool orthogonal = camera->get_projection() == Camera3D::PROJECTION_ORTHOGONAL;
- Vector<Color> grid_colors[3];
- Vector<Vector3> grid_points[3];
- Vector<Vector3> grid_normals[3];
+ static LocalVector<Color> grid_colors[3];
+ static LocalVector<Vector3> grid_points[3];
+ static LocalVector<Vector3> grid_normals[3];
+
+ for (uint32_t n = 0; n < 3; n++) {
+ grid_colors[n].clear();
+ grid_points[n].clear();
+ grid_normals[n].clear();
+ }
Color primary_grid_color = EDITOR_GET("editors/3d/primary_grid_color");
Color secondary_grid_color = EDITOR_GET("editors/3d/secondary_grid_color");
@@ -7299,9 +7391,9 @@ void Node3DEditor::_init_grid() {
int primary_grid_steps = EDITOR_GET("editors/3d/primary_grid_steps");
// Which grid planes are enabled? Which should we generate?
- grid_enable[0] = grid_visible[0] = EDITOR_GET("editors/3d/grid_xy_plane");
- grid_enable[1] = grid_visible[1] = EDITOR_GET("editors/3d/grid_yz_plane");
- grid_enable[2] = grid_visible[2] = EDITOR_GET("editors/3d/grid_xz_plane");
+ grid_enable[0] = grid_visible[0] = orthogonal || EDITOR_GET("editors/3d/grid_xy_plane");
+ grid_enable[1] = grid_visible[1] = orthogonal || EDITOR_GET("editors/3d/grid_yz_plane");
+ grid_enable[2] = grid_visible[2] = orthogonal || EDITOR_GET("editors/3d/grid_xz_plane");
// Offsets division_level for bigger or smaller grids.
// Default value is -0.2. -1.0 gives Blender-like behavior, 0.5 gives huge grids.
@@ -7367,10 +7459,9 @@ void Node3DEditor::_init_grid() {
grid_mat[c]->set_shader_parameter("grid_size", grid_fade_size);
grid_mat[c]->set_shader_parameter("orthogonal", orthogonal);
- // Cache these so we don't have to re-access memory.
- Vector<Vector3> &ref_grid = grid_points[c];
- Vector<Vector3> &ref_grid_normals = grid_normals[c];
- Vector<Color> &ref_grid_colors = grid_colors[c];
+ LocalVector<Vector3> &ref_grid = grid_points[c];
+ LocalVector<Vector3> &ref_grid_normals = grid_normals[c];
+ LocalVector<Color> &ref_grid_colors = grid_colors[c];
// Count our elements same as code below it.
int expected_size = 0;
@@ -7415,12 +7506,12 @@ void Node3DEditor::_init_grid() {
line_end[a] = position_a;
line_bgn[b] = bgn_b;
line_end[b] = end_b;
- ref_grid.set(idx, line_bgn);
- ref_grid.set(idx + 1, line_end);
- ref_grid_colors.set(idx, line_color);
- ref_grid_colors.set(idx + 1, line_color);
- ref_grid_normals.set(idx, normal);
- ref_grid_normals.set(idx + 1, normal);
+ ref_grid[idx] = line_bgn;
+ ref_grid[idx + 1] = line_end;
+ ref_grid_colors[idx] = line_color;
+ ref_grid_colors[idx + 1] = line_color;
+ ref_grid_normals[idx] = normal;
+ ref_grid_normals[idx + 1] = normal;
idx += 2;
}
@@ -7431,12 +7522,12 @@ void Node3DEditor::_init_grid() {
line_end[b] = position_b;
line_bgn[a] = bgn_a;
line_end[a] = end_a;
- ref_grid.set(idx, line_bgn);
- ref_grid.set(idx + 1, line_end);
- ref_grid_colors.set(idx, line_color);
- ref_grid_colors.set(idx + 1, line_color);
- ref_grid_normals.set(idx, normal);
- ref_grid_normals.set(idx + 1, normal);
+ ref_grid[idx] = line_bgn;
+ ref_grid[idx + 1] = line_end;
+ ref_grid_colors[idx] = line_color;
+ ref_grid_colors[idx + 1] = line_color;
+ ref_grid_normals[idx] = normal;
+ ref_grid_normals[idx + 1] = normal;
idx += 2;
}
}
@@ -7445,9 +7536,9 @@ void Node3DEditor::_init_grid() {
grid[c] = RenderingServer::get_singleton()->mesh_create();
Array d;
d.resize(RS::ARRAY_MAX);
- d[RenderingServer::ARRAY_VERTEX] = grid_points[c];
- d[RenderingServer::ARRAY_COLOR] = grid_colors[c];
- d[RenderingServer::ARRAY_NORMAL] = grid_normals[c];
+ d[RenderingServer::ARRAY_VERTEX] = (Vector<Vector3>)grid_points[c];
+ d[RenderingServer::ARRAY_COLOR] = (Vector<Color>)grid_colors[c];
+ d[RenderingServer::ARRAY_NORMAL] = (Vector<Vector3>)grid_normals[c];
RenderingServer::get_singleton()->mesh_add_surface_from_arrays(grid[c], RenderingServer::PRIMITIVE_LINES, d);
RenderingServer::get_singleton()->mesh_surface_set_material(grid[c], 0, grid_mat[c]->get_rid());
grid_instance[c] = RenderingServer::get_singleton()->instance_create2(grid[c], get_tree()->get_root()->get_world_3d()->get_scenario());
@@ -9208,6 +9299,49 @@ void Node3DEditor::remove_gizmo_plugin(Ref<EditorNode3DGizmoPlugin> p_plugin) {
_update_gizmos_menu();
}
+DynamicBVH::ID Node3DEditor::insert_gizmo_bvh_node(Node3D *p_node, const AABB &p_aabb) {
+ return gizmo_bvh.insert(p_aabb, p_node);
+}
+
+void Node3DEditor::update_gizmo_bvh_node(DynamicBVH::ID p_id, const AABB &p_aabb) {
+ gizmo_bvh.update(p_id, p_aabb);
+ gizmo_bvh.optimize_incremental(1);
+}
+
+void Node3DEditor::remove_gizmo_bvh_node(DynamicBVH::ID p_id) {
+ gizmo_bvh.remove(p_id);
+}
+
+Vector<Node3D *> Node3DEditor::gizmo_bvh_ray_query(const Vector3 &p_ray_start, const Vector3 &p_ray_end) {
+ struct Result {
+ Vector<Node3D *> nodes;
+ bool operator()(void *p_data) {
+ nodes.append((Node3D *)p_data);
+ return false;
+ }
+ } result;
+
+ gizmo_bvh.ray_query(p_ray_start, p_ray_end, result);
+
+ return result.nodes;
+}
+
+Vector<Node3D *> Node3DEditor::gizmo_bvh_frustum_query(const Vector<Plane> &p_frustum) {
+ Vector<Vector3> points = Geometry3D::compute_convex_mesh_points(&p_frustum[0], p_frustum.size());
+
+ struct Result {
+ Vector<Node3D *> nodes;
+ bool operator()(void *p_data) {
+ nodes.append((Node3D *)p_data);
+ return false;
+ }
+ } result;
+
+ gizmo_bvh.convex_query(p_frustum.ptr(), p_frustum.size(), points.ptr(), points.size(), result);
+
+ return result.nodes;
+}
+
Node3DEditorPlugin::Node3DEditorPlugin() {
spatial_editor = memnew(Node3DEditor);
spatial_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h
index 5bd14748c0..2cfe784ca6 100644
--- a/editor/plugins/node_3d_editor_plugin.h
+++ b/editor/plugins/node_3d_editor_plugin.h
@@ -31,6 +31,7 @@
#ifndef NODE_3D_EDITOR_PLUGIN_H
#define NODE_3D_EDITOR_PLUGIN_H
+#include "core/math/dynamic_bvh.h"
#include "editor/plugins/editor_plugin.h"
#include "editor/plugins/node_3d_editor_gizmos.h"
#include "editor/themes/editor_scale.h"
@@ -124,6 +125,7 @@ class Node3DEditorViewport : public Control {
VIEW_AUDIO_LISTENER,
VIEW_AUDIO_DOPPLER,
VIEW_GIZMOS,
+ VIEW_TRANSFORM_GIZMO,
VIEW_GRID,
VIEW_INFORMATION,
VIEW_FRAME_TIME,
@@ -191,6 +193,7 @@ public:
NAVIGATION_GODOT,
NAVIGATION_MAYA,
NAVIGATION_MODO,
+ NAVIGATION_CUSTOM,
};
enum FreelookNavigationScheme {
@@ -199,6 +202,12 @@ public:
FREELOOK_FULLY_AXIS_LOCKED,
};
+ enum ViewportNavMouseButton {
+ NAVIGATION_LEFT_MOUSE,
+ NAVIGATION_MIDDLE_MOUSE,
+ NAVIGATION_RIGHT_MOUSE,
+ };
+
private:
double cpu_time_history[FRAME_TIME_HISTORY];
int cpu_time_history_index;
@@ -235,6 +244,7 @@ private:
bool orthogonal;
bool auto_orthogonal;
bool lock_rotation;
+ bool transform_gizmo_visible = true;
real_t gizmo_scale;
bool freelook_active;
@@ -293,6 +303,10 @@ private:
void _nav_orbit(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative);
void _nav_look(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative);
+ bool _is_shortcut_empty(const String &p_name);
+ bool _is_nav_modifier_pressed(const String &p_name);
+ int _get_shortcut_input_count(const String &p_name);
+
float get_znear() const;
float get_zfar() const;
float get_fov() const;
@@ -389,6 +403,28 @@ private:
void reset_fov();
void scale_cursor_distance(real_t scale);
+ struct ShortcutCheckSet {
+ bool mod_pressed = false;
+ bool shortcut_not_empty = true;
+ int input_count = 0;
+ ViewportNavMouseButton mouse_preference = NAVIGATION_LEFT_MOUSE;
+ NavigationMode result_nav_mode = NAVIGATION_NONE;
+
+ ShortcutCheckSet() {}
+
+ ShortcutCheckSet(bool p_mod_pressed, bool p_shortcut_not_empty, int p_input_count, const ViewportNavMouseButton &p_mouse_preference, const NavigationMode &p_result_nav_mode) :
+ mod_pressed(p_mod_pressed), shortcut_not_empty(p_shortcut_not_empty), input_count(p_input_count), mouse_preference(p_mouse_preference), result_nav_mode(p_result_nav_mode) {
+ }
+ };
+
+ struct ShortcutCheckSetComparator {
+ _FORCE_INLINE_ bool operator()(const ShortcutCheckSet &A, const ShortcutCheckSet &B) const {
+ return A.input_count > B.input_count;
+ }
+ };
+
+ NavigationMode _get_nav_mode_from_shortcut_check(ViewportNavMouseButton p_mouse_button, Vector<ShortcutCheckSet> p_shortcut_check_sets, bool p_use_not_empty);
+
void set_freelook_active(bool active_now);
void scale_freelook_speed(real_t scale);
@@ -629,6 +665,8 @@ private:
int current_hover_gizmo_handle;
bool current_hover_gizmo_handle_secondary;
+ DynamicBVH gizmo_bvh;
+
real_t snap_translate_value;
real_t snap_rotate_value;
real_t snap_scale_value;
@@ -933,6 +971,12 @@ public:
void add_gizmo_plugin(Ref<EditorNode3DGizmoPlugin> p_plugin);
void remove_gizmo_plugin(Ref<EditorNode3DGizmoPlugin> p_plugin);
+ DynamicBVH::ID insert_gizmo_bvh_node(Node3D *p_node, const AABB &p_aabb);
+ void update_gizmo_bvh_node(DynamicBVH::ID p_id, const AABB &p_aabb);
+ void remove_gizmo_bvh_node(DynamicBVH::ID p_id);
+ Vector<Node3D *> gizmo_bvh_ray_query(const Vector3 &p_ray_start, const Vector3 &p_ray_end);
+ Vector<Node3D *> gizmo_bvh_frustum_query(const Vector<Plane> &p_frustum);
+
void edit(Node3D *p_spatial);
void clear();
diff --git a/editor/plugins/packed_scene_translation_parser_plugin.cpp b/editor/plugins/packed_scene_translation_parser_plugin.cpp
index e9ddaeb3fe..b38965753e 100644
--- a/editor/plugins/packed_scene_translation_parser_plugin.cpp
+++ b/editor/plugins/packed_scene_translation_parser_plugin.cpp
@@ -83,9 +83,8 @@ Error PackedSceneEditorTranslationParserPlugin::parse_file(const String &p_path,
int idx_last = atr_owners.size() - 1;
if (idx_last > 0 && !parent_path.begins_with(atr_owners[idx_last].first)) {
- // Switch to the previous auto translation owner this was nested in, if that was the case.
+ // Exit from the current owner nesting into the previous one.
atr_owners.remove_at(idx_last);
- idx_last -= 1;
}
if (property == "auto_translate_mode") {
@@ -106,7 +105,7 @@ Error PackedSceneEditorTranslationParserPlugin::parse_file(const String &p_path,
// If `auto_translate_mode` wasn't found, that means it is set to its default value (`AUTO_TRANSLATE_MODE_INHERIT`).
if (!auto_translate_mode_found) {
int idx_last = atr_owners.size() - 1;
- if (idx_last > 0 && atr_owners[idx_last].first == parent_path) {
+ if (idx_last > 0 && parent_path.begins_with(atr_owners[idx_last].first)) {
auto_translating = atr_owners[idx_last].second;
} else {
atr_owners.push_back(Pair(state->get_node_path(i), true));
diff --git a/editor/plugins/physical_bone_3d_editor_plugin.cpp b/editor/plugins/physical_bone_3d_editor_plugin.cpp
index b7c12ab5c0..d7e9701452 100644
--- a/editor/plugins/physical_bone_3d_editor_plugin.cpp
+++ b/editor/plugins/physical_bone_3d_editor_plugin.cpp
@@ -36,9 +36,6 @@
#include "scene/3d/physics/physical_bone_3d.h"
#include "scene/gui/separator.h"
-void PhysicalBone3DEditor::_bind_methods() {
-}
-
void PhysicalBone3DEditor::_on_toggle_button_transform_joint(bool p_is_pressed) {
_set_move_joint();
}
diff --git a/editor/plugins/physical_bone_3d_editor_plugin.h b/editor/plugins/physical_bone_3d_editor_plugin.h
index fb6f30cc57..b057644bb1 100644
--- a/editor/plugins/physical_bone_3d_editor_plugin.h
+++ b/editor/plugins/physical_bone_3d_editor_plugin.h
@@ -45,9 +45,6 @@ class PhysicalBone3DEditor : public Object {
PhysicalBone3D *selected = nullptr;
-protected:
- static void _bind_methods();
-
private:
void _on_toggle_button_transform_joint(bool p_is_pressed);
void _set_move_joint();
diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp
index e442c37edd..7c350f1e6d 100644
--- a/editor/plugins/polygon_2d_editor_plugin.cpp
+++ b/editor/plugins/polygon_2d_editor_plugin.cpp
@@ -181,7 +181,7 @@ void Polygon2DEditor::_sync_bones() {
}
if (weights.size() == 0) { //create them
- weights.resize(node->get_polygon().size());
+ weights.resize(wc);
float *w = weights.ptrw();
for (int j = 0; j < wc; j++) {
w[j] = 0.0;
@@ -850,8 +850,8 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
if (mm.is_valid()) {
if (uv_drag) {
Vector2 uv_drag_to = mm->get_position();
- uv_drag_to = snap_point(uv_drag_to); // FIXME: Only works correctly with 'UV_MODE_EDIT_POINT', it's imprecise with the rest.
- Vector2 drag = mtx.affine_inverse().xform(uv_drag_to) - mtx.affine_inverse().xform(uv_drag_from);
+ uv_drag_to = snap_point(uv_drag_to);
+ Vector2 drag = mtx.affine_inverse().basis_xform(uv_drag_to - uv_drag_from);
switch (uv_move_current) {
case UV_MODE_CREATE: {
@@ -1166,12 +1166,8 @@ void Polygon2DEditor::_uv_draw() {
poly_line_color.a *= 0.25;
}
Color polygon_line_color = Color(0.5, 0.5, 0.9);
- Vector<Color> polygon_fill_color;
- {
- Color pf = polygon_line_color;
- pf.a *= 0.5;
- polygon_fill_color.push_back(pf);
- }
+ Color polygon_fill_color = polygon_line_color;
+ polygon_fill_color.a *= 0.5;
Color prev_color = Color(0.5, 0.5, 0.5);
int uv_draw_max = uvs.size();
@@ -1216,7 +1212,7 @@ void Polygon2DEditor::_uv_draw() {
uv_edit_draw->draw_line(mtx.xform(uvs[idx]), mtx.xform(uvs[idx_next]), polygon_line_color, Math::round(EDSCALE));
}
if (points.size() >= 3) {
- uv_edit_draw->draw_polygon(polypoints, polygon_fill_color);
+ uv_edit_draw->draw_colored_polygon(polypoints, polygon_fill_color);
}
}
@@ -1255,44 +1251,43 @@ void Polygon2DEditor::_uv_draw() {
//draw skeleton
NodePath skeleton_path = node->get_skeleton();
- if (node->has_node(skeleton_path)) {
- Skeleton2D *skeleton = Object::cast_to<Skeleton2D>(node->get_node(skeleton_path));
- if (skeleton) {
- for (int i = 0; i < skeleton->get_bone_count(); i++) {
- Bone2D *bone = skeleton->get_bone(i);
- if (bone->get_rest() == Transform2D(0, 0, 0, 0, 0, 0)) {
- continue; //not set
- }
+ Skeleton2D *skeleton = Object::cast_to<Skeleton2D>(node->get_node_or_null(skeleton_path));
+ if (skeleton) {
+ Transform2D skeleton_xform = node->get_global_transform().affine_inverse().translated(-node->get_offset()) * skeleton->get_global_transform();
+ for (int i = 0; i < skeleton->get_bone_count(); i++) {
+ Bone2D *bone = skeleton->get_bone(i);
+ if (bone->get_rest() == Transform2D(0, 0, 0, 0, 0, 0)) {
+ continue; //not set
+ }
- bool current = bone_path == skeleton->get_path_to(bone);
+ bool current = bone_path == skeleton->get_path_to(bone);
- bool found_child = false;
+ bool found_child = false;
- for (int j = 0; j < bone->get_child_count(); j++) {
- Bone2D *n = Object::cast_to<Bone2D>(bone->get_child(j));
- if (!n) {
- continue;
- }
+ for (int j = 0; j < bone->get_child_count(); j++) {
+ Bone2D *n = Object::cast_to<Bone2D>(bone->get_child(j));
+ if (!n) {
+ continue;
+ }
- found_child = true;
+ found_child = true;
- Transform2D bone_xform = node->get_global_transform().affine_inverse().translated(-node->get_offset()) * (skeleton->get_global_transform() * bone->get_skeleton_rest());
- Transform2D endpoint_xform = bone_xform * n->get_transform();
+ Transform2D bone_xform = skeleton_xform * bone->get_skeleton_rest();
+ Transform2D endpoint_xform = bone_xform * n->get_transform();
- Color color = current ? Color(1, 1, 1) : Color(0.5, 0.5, 0.5);
- uv_edit_draw->draw_line(mtx.xform(bone_xform.get_origin()), mtx.xform(endpoint_xform.get_origin()), Color(0, 0, 0), Math::round((current ? 5 : 4) * EDSCALE));
- uv_edit_draw->draw_line(mtx.xform(bone_xform.get_origin()), mtx.xform(endpoint_xform.get_origin()), color, Math::round((current ? 3 : 2) * EDSCALE));
- }
+ Color color = current ? Color(1, 1, 1) : Color(0.5, 0.5, 0.5);
+ uv_edit_draw->draw_line(mtx.xform(bone_xform.get_origin()), mtx.xform(endpoint_xform.get_origin()), Color(0, 0, 0), Math::round((current ? 5 : 4) * EDSCALE));
+ uv_edit_draw->draw_line(mtx.xform(bone_xform.get_origin()), mtx.xform(endpoint_xform.get_origin()), color, Math::round((current ? 3 : 2) * EDSCALE));
+ }
- if (!found_child) {
- //draw normally
- Transform2D bone_xform = node->get_global_transform().affine_inverse().translated(-node->get_offset()) * (skeleton->get_global_transform() * bone->get_skeleton_rest());
- Transform2D endpoint_xform = bone_xform * Transform2D(0, Vector2(bone->get_length(), 0));
+ if (!found_child) {
+ //draw normally
+ Transform2D bone_xform = skeleton_xform * bone->get_skeleton_rest();
+ Transform2D endpoint_xform = bone_xform * Transform2D(0, Vector2(bone->get_length(), 0)).rotated(bone->get_bone_angle());
- Color color = current ? Color(1, 1, 1) : Color(0.5, 0.5, 0.5);
- uv_edit_draw->draw_line(mtx.xform(bone_xform.get_origin()), mtx.xform(endpoint_xform.get_origin()), Color(0, 0, 0), Math::round((current ? 5 : 4) * EDSCALE));
- uv_edit_draw->draw_line(mtx.xform(bone_xform.get_origin()), mtx.xform(endpoint_xform.get_origin()), color, Math::round((current ? 3 : 2) * EDSCALE));
- }
+ Color color = current ? Color(1, 1, 1) : Color(0.5, 0.5, 0.5);
+ uv_edit_draw->draw_line(mtx.xform(bone_xform.get_origin()), mtx.xform(endpoint_xform.get_origin()), Color(0, 0, 0), Math::round((current ? 5 : 4) * EDSCALE));
+ uv_edit_draw->draw_line(mtx.xform(bone_xform.get_origin()), mtx.xform(endpoint_xform.get_origin()), color, Math::round((current ? 3 : 2) * EDSCALE));
}
}
}
@@ -1309,8 +1304,8 @@ void Polygon2DEditor::_bind_methods() {
Vector2 Polygon2DEditor::snap_point(Vector2 p_target) const {
if (use_snap) {
- p_target.x = Math::snap_scalar(snap_offset.x * uv_draw_zoom - uv_draw_ofs.x, snap_step.x * uv_draw_zoom, p_target.x);
- p_target.y = Math::snap_scalar(snap_offset.y * uv_draw_zoom - uv_draw_ofs.y, snap_step.y * uv_draw_zoom, p_target.y);
+ p_target.x = Math::snap_scalar((snap_offset.x - uv_draw_ofs.x) * uv_draw_zoom, snap_step.x * uv_draw_zoom, p_target.x);
+ p_target.y = Math::snap_scalar((snap_offset.y - uv_draw_ofs.y) * uv_draw_zoom, snap_step.y * uv_draw_zoom, p_target.y);
}
return p_target;
@@ -1388,7 +1383,8 @@ Polygon2DEditor::Polygon2DEditor() {
uv_button[UV_MODE_CREATE_INTERNAL]->set_tooltip_text(TTR("Create Internal Vertex"));
uv_button[UV_MODE_REMOVE_INTERNAL]->set_tooltip_text(TTR("Remove Internal Vertex"));
Key key = (OS::get_singleton()->has_feature("macos") || OS::get_singleton()->has_feature("web_macos") || OS::get_singleton()->has_feature("web_ios")) ? Key::META : Key::CTRL;
- uv_button[UV_MODE_EDIT_POINT]->set_tooltip_text(TTR("Move Points") + "\n" + find_keycode_name(key) + TTR(": Rotate") + "\n" + TTR("Shift: Move All") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("Shift: Scale"));
+ // TRANSLATORS: %s is Control or Command key name.
+ uv_button[UV_MODE_EDIT_POINT]->set_tooltip_text(TTR("Move Points") + "\n" + vformat(TTR("%s: Rotate"), find_keycode_name(key)) + "\n" + TTR("Shift: Move All") + "\n" + vformat(TTR("%s + Shift: Scale"), find_keycode_name(key)));
uv_button[UV_MODE_MOVE]->set_tooltip_text(TTR("Move Polygon"));
uv_button[UV_MODE_ROTATE]->set_tooltip_text(TTR("Rotate Polygon"));
uv_button[UV_MODE_SCALE]->set_tooltip_text(TTR("Scale Polygon"));
diff --git a/editor/plugins/root_motion_editor_plugin.cpp b/editor/plugins/root_motion_editor_plugin.cpp
index 8b31aa92b3..cd422fc291 100644
--- a/editor/plugins/root_motion_editor_plugin.cpp
+++ b/editor/plugins/root_motion_editor_plugin.cpp
@@ -193,9 +193,6 @@ void EditorPropertyRootMotion::_notification(int p_what) {
}
}
-void EditorPropertyRootMotion::_bind_methods() {
-}
-
EditorPropertyRootMotion::EditorPropertyRootMotion() {
HBoxContainer *hbc = memnew(HBoxContainer);
add_child(hbc);
diff --git a/editor/plugins/root_motion_editor_plugin.h b/editor/plugins/root_motion_editor_plugin.h
index 5befdb6006..a3e90360ae 100644
--- a/editor/plugins/root_motion_editor_plugin.h
+++ b/editor/plugins/root_motion_editor_plugin.h
@@ -52,7 +52,6 @@ class EditorPropertyRootMotion : public EditorProperty {
void _node_clear();
protected:
- static void _bind_methods();
void _notification(int p_what);
public:
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index c51eb44aee..7a052ebc19 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -493,7 +493,7 @@ void ScriptEditor::_goto_script_line(Ref<RefCounted> p_script, int p_line) {
if (ScriptTextEditor *script_text_editor = Object::cast_to<ScriptTextEditor>(current)) {
script_text_editor->goto_line_centered(p_line);
} else if (current) {
- current->goto_line(p_line, true);
+ current->goto_line(p_line);
}
_save_history();
@@ -1079,8 +1079,12 @@ void ScriptEditor::_mark_built_in_scripts_as_saved(const String &p_parent_path)
}
Ref<Script> scr = edited_res;
- if (scr.is_valid() && scr->is_tool()) {
- scr->reload(true);
+ if (scr.is_valid()) {
+ trigger_live_script_reload(scr->get_path());
+
+ if (scr->is_tool()) {
+ scr->reload(true);
+ }
}
}
}
@@ -1857,17 +1861,13 @@ void ScriptEditor::get_breakpoints(List<String> *p_breakpoints) {
}
void ScriptEditor::_members_overview_selected(int p_idx) {
- ScriptEditorBase *se = _get_current_editor();
- if (!se) {
- return;
+ int line = members_overview->get_item_metadata(p_idx);
+ ScriptEditorBase *current = _get_current_editor();
+ if (ScriptTextEditor *script_text_editor = Object::cast_to<ScriptTextEditor>(current)) {
+ script_text_editor->goto_line_centered(line);
+ } else if (current) {
+ current->goto_line(line);
}
- // Go to the member's line and reset the cursor column. We can't change scroll_position
- // directly until we have gone to the line first, since code might be folded.
- se->goto_line(members_overview->get_item_metadata(p_idx));
- Dictionary state = se->get_edit_state();
- state["column"] = 0;
- state["scroll_position"] = members_overview->get_item_metadata(p_idx);
- se->set_edit_state(state);
}
void ScriptEditor::_help_overview_selected(int p_idx) {
@@ -2711,9 +2711,11 @@ void ScriptEditor::apply_scripts() const {
}
void ScriptEditor::reload_scripts(bool p_refresh_only) {
- if (external_editor_active) {
- return;
- }
+ // Call deferred to make sure it runs on the main thread.
+ callable_mp(this, &ScriptEditor::_reload_scripts).call_deferred(p_refresh_only);
+}
+
+void ScriptEditor::_reload_scripts(bool p_refresh_only) {
for (int i = 0; i < tab_container->get_tab_count(); i++) {
ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(tab_container->get_tab_control(i));
if (!se) {
@@ -3799,7 +3801,10 @@ void ScriptEditor::_on_find_in_files_result_selected(const String &fpath, int li
ShaderEditorPlugin *shader_editor = Object::cast_to<ShaderEditorPlugin>(EditorNode::get_editor_data().get_editor_by_name("Shader"));
shader_editor->edit(res.ptr());
shader_editor->make_visible(true);
- shader_editor->get_shader_editor(res)->goto_line_selection(line_number - 1, begin, end);
+ TextShaderEditor *text_shader_editor = Object::cast_to<TextShaderEditor>(shader_editor->get_shader_editor(res));
+ if (text_shader_editor) {
+ text_shader_editor->goto_line_selection(line_number - 1, begin, end);
+ }
return;
} else if (fpath.get_extension() == "tscn") {
Ref<FileAccess> f = FileAccess::open(fpath, FileAccess::READ);
@@ -4412,13 +4417,9 @@ bool ScriptEditorPlugin::handles(Object *p_object) const {
void ScriptEditorPlugin::make_visible(bool p_visible) {
if (p_visible) {
window_wrapper->show();
- script_editor->set_process(true);
script_editor->ensure_select_current();
} else {
window_wrapper->hide();
- if (!window_wrapper->get_window_enabled()) {
- script_editor->set_process(false);
- }
}
}
diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h
index 9db1aff76a..66885790a7 100644
--- a/editor/plugins/script_editor_plugin.h
+++ b/editor/plugins/script_editor_plugin.h
@@ -55,7 +55,7 @@ class EditorSyntaxHighlighter : public SyntaxHighlighter {
GDCLASS(EditorSyntaxHighlighter, SyntaxHighlighter)
private:
- Ref<RefCounted> edited_resourse;
+ Ref<RefCounted> edited_resource;
protected:
static void _bind_methods();
@@ -67,8 +67,8 @@ public:
virtual String _get_name() const;
virtual PackedStringArray _get_supported_languages() const;
- void _set_edited_resource(const Ref<Resource> &p_res) { edited_resourse = p_res; }
- Ref<RefCounted> _get_edited_resource() { return edited_resourse; }
+ void _set_edited_resource(const Ref<Resource> &p_res) { edited_resource = p_res; }
+ Ref<RefCounted> _get_edited_resource() { return edited_resource; }
virtual Ref<EditorSyntaxHighlighter> _create() const;
};
@@ -170,7 +170,7 @@ public:
virtual Variant get_edit_state() = 0;
virtual void set_edit_state(const Variant &p_state) = 0;
virtual Variant get_navigation_state() = 0;
- virtual void goto_line(int p_line, bool p_with_error = false) = 0;
+ virtual void goto_line(int p_line, int p_column = 0) = 0;
virtual void set_executing_line(int p_line) = 0;
virtual void clear_executing_line() = 0;
virtual void trim_trailing_whitespace() = 0;
@@ -436,6 +436,7 @@ class ScriptEditor : public PanelContainer {
void _file_removed(const String &p_file);
void _autosave_scripts();
void _update_autosave_timer();
+ void _reload_scripts(bool p_refresh_only = false);
void _update_members_overview_visibility();
void _update_members_overview();
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index 070471f3f3..eb39a27d02 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -302,16 +302,14 @@ void ScriptTextEditor::_warning_clicked(const Variant &p_line) {
void ScriptTextEditor::_error_clicked(const Variant &p_line) {
if (p_line.get_type() == Variant::INT) {
- code_editor->get_text_editor()->remove_secondary_carets();
- code_editor->get_text_editor()->set_caret_line(p_line.operator int64_t());
+ goto_line_centered(p_line.operator int64_t());
} else if (p_line.get_type() == Variant::DICTIONARY) {
Dictionary meta = p_line.operator Dictionary();
const String path = meta["path"].operator String();
const int line = meta["line"].operator int64_t();
const int column = meta["column"].operator int64_t();
if (path.is_empty()) {
- code_editor->get_text_editor()->remove_secondary_carets();
- code_editor->get_text_editor()->set_caret_line(line);
+ goto_line_centered(line, column);
} else {
Ref<Resource> scr = ResourceLoader::load(path);
if (!scr.is_valid()) {
@@ -456,16 +454,16 @@ void ScriptTextEditor::tag_saved_version() {
code_editor->get_text_editor()->tag_saved_version();
}
-void ScriptTextEditor::goto_line(int p_line, bool p_with_error) {
- code_editor->goto_line(p_line);
+void ScriptTextEditor::goto_line(int p_line, int p_column) {
+ code_editor->goto_line(p_line, p_column);
}
void ScriptTextEditor::goto_line_selection(int p_line, int p_begin, int p_end) {
code_editor->goto_line_selection(p_line, p_begin, p_end);
}
-void ScriptTextEditor::goto_line_centered(int p_line) {
- code_editor->goto_line_centered(p_line);
+void ScriptTextEditor::goto_line_centered(int p_line, int p_column) {
+ code_editor->goto_line_centered(p_line, p_column);
}
void ScriptTextEditor::set_executing_line(int p_line) {
@@ -919,8 +917,7 @@ void ScriptTextEditor::_breakpoint_item_pressed(int p_idx) {
if (p_idx < 4) { // Any item before the separator.
_edit_option(breakpoints_menu->get_item_id(p_idx));
} else {
- code_editor->goto_line(breakpoints_menu->get_item_metadata(p_idx));
- callable_mp((TextEdit *)code_editor->get_text_editor(), &TextEdit::center_viewport_to_caret).call_deferred(0); // Needs to be deferred, because goto uses call_deferred().
+ code_editor->goto_line_centered(breakpoints_menu->get_item_metadata(p_idx));
}
}
@@ -1816,9 +1813,9 @@ static String _get_dropped_resource_line(const Ref<Resource> &p_resource, bool p
}
if (is_script) {
- variable_name = variable_name.to_pascal_case().validate_identifier();
+ variable_name = variable_name.to_pascal_case().validate_ascii_identifier();
} else {
- variable_name = variable_name.to_snake_case().to_upper().validate_identifier();
+ variable_name = variable_name.to_snake_case().to_upper().validate_ascii_identifier();
}
return vformat("const %s = preload(%s)", variable_name, _quote_drop_data(path));
}
@@ -1932,13 +1929,13 @@ void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data
path = sn->get_path_to(node);
}
for (const String &segment : path.split("/")) {
- if (!segment.is_valid_identifier()) {
+ if (!segment.is_valid_ascii_identifier()) {
path = _quote_drop_data(path);
break;
}
}
- String variable_name = String(node->get_name()).to_snake_case().validate_identifier();
+ String variable_name = String(node->get_name()).to_snake_case().validate_ascii_identifier();
if (use_type) {
StringName class_name = node->get_class_name();
Ref<Script> node_script = node->get_script();
@@ -1975,7 +1972,7 @@ void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data
}
for (const String &segment : path.split("/")) {
- if (!segment.is_valid_identifier()) {
+ if (!segment.is_valid_ascii_identifier()) {
path = _quote_drop_data(path);
break;
}
diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h
index 8c2ec1561b..7aa0726479 100644
--- a/editor/plugins/script_text_editor.h
+++ b/editor/plugins/script_text_editor.h
@@ -234,9 +234,9 @@ public:
virtual void convert_indent() override;
virtual void tag_saved_version() override;
- virtual void goto_line(int p_line, bool p_with_error = false) override;
+ virtual void goto_line(int p_line, int p_column = 0) override;
void goto_line_selection(int p_line, int p_begin, int p_end);
- void goto_line_centered(int p_line);
+ void goto_line_centered(int p_line, int p_column = 0);
virtual void set_executing_line(int p_line) override;
virtual void clear_executing_line() override;
diff --git a/editor/plugins/shader/shader_editor.h b/editor/plugins/shader/shader_editor.h
new file mode 100644
index 0000000000..32e690015b
--- /dev/null
+++ b/editor/plugins/shader/shader_editor.h
@@ -0,0 +1,50 @@
+/**************************************************************************/
+/* shader_editor.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef SHADER_EDITOR_H
+#define SHADER_EDITOR_H
+
+#include "scene/gui/control.h"
+#include "scene/resources/shader.h"
+
+class ShaderEditor : public Control {
+ GDCLASS(ShaderEditor, Control);
+
+public:
+ virtual void edit_shader(const Ref<Shader> &p_shader) = 0;
+ virtual void edit_shader_include(const Ref<ShaderInclude> &p_shader_inc) {}
+
+ virtual void apply_shaders() = 0;
+ virtual bool is_unsaved() const = 0;
+ virtual void save_external_data(const String &p_str = "") = 0;
+ virtual void validate_script() = 0;
+};
+
+#endif // SHADER_EDITOR_H
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index 9d1576cdf2..04a392768a 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -45,6 +45,16 @@
#include "scene/gui/item_list.h"
#include "scene/gui/texture_rect.h"
+Ref<Resource> ShaderEditorPlugin::_get_current_shader() {
+ int index = shader_tabs->get_current_tab();
+ ERR_FAIL_INDEX_V(index, shader_tabs->get_tab_count(), Ref<Resource>());
+ if (edited_shaders[index].shader.is_valid()) {
+ return edited_shaders[index].shader;
+ } else {
+ return edited_shaders[index].shader_inc;
+ }
+}
+
void ShaderEditorPlugin::_update_shader_list() {
shader_list->clear();
for (EditedShader &edited_shader : edited_shaders) {
@@ -93,9 +103,7 @@ void ShaderEditorPlugin::_update_shader_list() {
shader_list->select(shader_tabs->get_current_tab());
}
- for (int i = FILE_SAVE; i < FILE_MAX; i++) {
- file_menu->get_popup()->set_item_disabled(file_menu->get_popup()->get_item_index(i), edited_shaders.is_empty());
- }
+ _set_file_specific_items_disabled(edited_shaders.is_empty());
_update_shader_list_status();
}
@@ -142,7 +150,7 @@ void ShaderEditorPlugin::edit(Object *p_object) {
}
es.shader_inc = Ref<ShaderInclude>(si);
es.shader_editor = memnew(TextShaderEditor);
- es.shader_editor->edit(si);
+ es.shader_editor->edit_shader_include(si);
shader_tabs->add_child(es.shader_editor);
} else {
Shader *s = Object::cast_to<Shader>(p_object);
@@ -156,20 +164,18 @@ void ShaderEditorPlugin::edit(Object *p_object) {
es.shader = Ref<Shader>(s);
Ref<VisualShader> vs = es.shader;
if (vs.is_valid()) {
- es.visual_shader_editor = memnew(VisualShaderEditor);
- shader_tabs->add_child(es.visual_shader_editor);
- es.visual_shader_editor->edit(vs.ptr());
+ es.shader_editor = memnew(VisualShaderEditor);
} else {
es.shader_editor = memnew(TextShaderEditor);
- shader_tabs->add_child(es.shader_editor);
- es.shader_editor->edit(s);
}
+ shader_tabs->add_child(es.shader_editor);
+ es.shader_editor->edit_shader(es.shader);
}
- if (es.shader_editor) {
- es.shader_editor->connect("validation_changed", callable_mp(this, &ShaderEditorPlugin::_update_shader_list));
-
- CodeTextEditor *cte = es.shader_editor->get_code_editor();
+ TextShaderEditor *text_shader_editor = Object::cast_to<TextShaderEditor>(es.shader_editor);
+ if (text_shader_editor) {
+ text_shader_editor->connect("validation_changed", callable_mp(this, &ShaderEditorPlugin::_update_shader_list));
+ CodeTextEditor *cte = text_shader_editor->get_code_editor();
if (cte) {
cte->set_zoom_factor(text_shader_zoom_factor);
cte->connect("zoomed", callable_mp(this, &ShaderEditorPlugin::_set_text_shader_zoom_factor));
@@ -194,7 +200,7 @@ void ShaderEditorPlugin::make_visible(bool p_visible) {
void ShaderEditorPlugin::selected_notify() {
}
-TextShaderEditor *ShaderEditorPlugin::get_shader_editor(const Ref<Shader> &p_for_shader) {
+ShaderEditor *ShaderEditorPlugin::get_shader_editor(const Ref<Shader> &p_for_shader) {
for (EditedShader &edited_shader : edited_shaders) {
if (edited_shader.shader == p_for_shader) {
return edited_shader.shader_editor;
@@ -203,15 +209,6 @@ TextShaderEditor *ShaderEditorPlugin::get_shader_editor(const Ref<Shader> &p_for
return nullptr;
}
-VisualShaderEditor *ShaderEditorPlugin::get_visual_shader_editor(const Ref<Shader> &p_for_shader) {
- for (EditedShader &edited_shader : edited_shaders) {
- if (edited_shader.shader == p_for_shader) {
- return edited_shader.visual_shader_editor;
- }
- }
- return nullptr;
-}
-
void ShaderEditorPlugin::set_window_layout(Ref<ConfigFile> p_layout) {
if (EDITOR_GET("interface/multi_window/restore_windows_on_load") && window_wrapper->is_window_available() && p_layout->has_section_key("ShaderEditor", "window_rect")) {
window_wrapper->restore_window_from_saved_position(
@@ -280,7 +277,7 @@ void ShaderEditorPlugin::get_window_layout(Ref<ConfigFile> p_layout) {
String selected_shader;
for (int i = 0; i < shader_tabs->get_tab_count(); i++) {
EditedShader edited_shader = edited_shaders[i];
- if (edited_shader.shader_editor || edited_shader.visual_shader_editor) {
+ if (edited_shader.shader_editor) {
String shader_path;
if (edited_shader.shader.is_valid()) {
shader_path = edited_shader.shader->get_path();
@@ -290,10 +287,9 @@ void ShaderEditorPlugin::get_window_layout(Ref<ConfigFile> p_layout) {
}
shaders.push_back(shader_path);
- TextShaderEditor *shader_editor = Object::cast_to<TextShaderEditor>(shader_tabs->get_current_tab_control());
- VisualShaderEditor *visual_shader_editor = Object::cast_to<VisualShaderEditor>(shader_tabs->get_current_tab_control());
+ ShaderEditor *shader_editor = Object::cast_to<ShaderEditor>(shader_tabs->get_current_tab_control());
- if ((shader_editor && edited_shader.shader_editor == shader_editor) || (visual_shader_editor && edited_shader.visual_shader_editor == visual_shader_editor)) {
+ if (shader_editor && edited_shader.shader_editor == shader_editor) {
selected_shader = shader_path;
}
}
@@ -366,10 +362,6 @@ void ShaderEditorPlugin::_shader_selected(int p_index) {
edited_shaders[p_index].shader_editor->validate_script();
}
- if (edited_shaders[p_index].visual_shader_editor) {
- edited_shaders[p_index].visual_shader_editor->validate_script();
- }
-
shader_tabs->set_current_tab(p_index);
shader_list->select(p_index);
}
@@ -378,6 +370,61 @@ void ShaderEditorPlugin::_shader_list_clicked(int p_item, Vector2 p_local_mouse_
if (p_mouse_button_index == MouseButton::MIDDLE) {
_close_shader(p_item);
}
+ if (p_mouse_button_index == MouseButton::RIGHT) {
+ _make_script_list_context_menu();
+ }
+}
+
+void ShaderEditorPlugin::_setup_popup_menu(PopupMenuType p_type, PopupMenu *p_menu) {
+ if (p_type == FILE) {
+ p_menu->add_shortcut(ED_SHORTCUT("shader_editor/new", TTR("New Shader..."), KeyModifierMask::CMD_OR_CTRL | Key::N), FILE_NEW);
+ p_menu->add_shortcut(ED_SHORTCUT("shader_editor/new_include", TTR("New Shader Include..."), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::N), FILE_NEW_INCLUDE);
+ p_menu->add_separator();
+ p_menu->add_shortcut(ED_SHORTCUT("shader_editor/open", TTR("Load Shader File..."), KeyModifierMask::CMD_OR_CTRL | Key::O), FILE_OPEN);
+ p_menu->add_shortcut(ED_SHORTCUT("shader_editor/open_include", TTR("Load Shader Include File..."), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::O), FILE_OPEN_INCLUDE);
+ }
+
+ if (p_type == FILE || p_type == CONTEXT_VALID_ITEM) {
+ p_menu->add_shortcut(ED_SHORTCUT("shader_editor/save", TTR("Save File"), KeyModifierMask::ALT | KeyModifierMask::CMD_OR_CTRL | Key::S), FILE_SAVE);
+ p_menu->add_shortcut(ED_SHORTCUT("shader_editor/save_as", TTR("Save File As...")), FILE_SAVE_AS);
+ }
+
+ if (p_type == FILE) {
+ p_menu->add_separator();
+ p_menu->add_item(TTR("Open File in Inspector"), FILE_INSPECT);
+ p_menu->add_separator();
+ p_menu->add_shortcut(ED_SHORTCUT("shader_editor/close_file", TTR("Close File"), KeyModifierMask::CMD_OR_CTRL | Key::W), FILE_CLOSE);
+ } else {
+ p_menu->add_shortcut(ED_SHORTCUT("shader_editor/close_file", TTR("Close File"), KeyModifierMask::CMD_OR_CTRL | Key::W), FILE_CLOSE);
+ p_menu->add_item(TTR("Close All"), CLOSE_ALL);
+ p_menu->add_item(TTR("Close Other Tabs"), CLOSE_OTHER_TABS);
+ if (p_type == CONTEXT_VALID_ITEM) {
+ p_menu->add_separator();
+ p_menu->add_item(TTR("Copy Script Path"), COPY_PATH);
+ p_menu->add_item(TTR("Show in File System"), SHOW_IN_FILE_SYSTEM);
+ }
+ }
+}
+
+void ShaderEditorPlugin::_make_script_list_context_menu() {
+ context_menu->clear();
+
+ int selected = shader_tabs->get_current_tab();
+ if (selected < 0 || selected >= shader_tabs->get_tab_count()) {
+ return;
+ }
+
+ Control *control = shader_tabs->get_tab_control(selected);
+ bool is_valid_editor_control = Object::cast_to<TextShaderEditor>(control) || Object::cast_to<VisualShaderEditor>(control);
+
+ _setup_popup_menu(is_valid_editor_control ? CONTEXT_VALID_ITEM : CONTEXT, context_menu);
+
+ context_menu->set_item_disabled(context_menu->get_item_index(CLOSE_ALL), shader_tabs->get_tab_count() <= 0);
+ context_menu->set_item_disabled(context_menu->get_item_index(CLOSE_OTHER_TABS), shader_tabs->get_tab_count() <= 1);
+
+ context_menu->set_position(main_split->get_screen_position() + main_split->get_local_mouse_position());
+ context_menu->reset_size();
+ context_menu->popup();
}
void ShaderEditorPlugin::_close_shader(int p_index) {
@@ -440,7 +487,7 @@ void ShaderEditorPlugin::_menu_item_pressed(int p_index) {
case FILE_SAVE: {
int index = shader_tabs->get_current_tab();
ERR_FAIL_INDEX(index, shader_tabs->get_tab_count());
- TextShaderEditor *editor = edited_shaders[index].shader_editor;
+ TextShaderEditor *editor = Object::cast_to<TextShaderEditor>(edited_shaders[index].shader_editor);
if (editor) {
if (editor->get_trim_trailing_whitespace_on_save()) {
editor->trim_trailing_whitespace();
@@ -462,7 +509,7 @@ void ShaderEditorPlugin::_menu_item_pressed(int p_index) {
case FILE_SAVE_AS: {
int index = shader_tabs->get_current_tab();
ERR_FAIL_INDEX(index, shader_tabs->get_tab_count());
- TextShaderEditor *editor = edited_shaders[index].shader_editor;
+ TextShaderEditor *editor = Object::cast_to<TextShaderEditor>(edited_shaders[index].shader_editor);
if (editor) {
if (editor->get_trim_trailing_whitespace_on_save()) {
editor->trim_trailing_whitespace();
@@ -502,6 +549,31 @@ void ShaderEditorPlugin::_menu_item_pressed(int p_index) {
case FILE_CLOSE: {
_close_shader(shader_tabs->get_current_tab());
} break;
+ case CLOSE_ALL: {
+ while (shader_tabs->get_tab_count() > 0) {
+ _close_shader(0);
+ }
+ } break;
+ case CLOSE_OTHER_TABS: {
+ int index = shader_tabs->get_current_tab();
+ for (int i = 0; i < index; i++) {
+ _close_shader(0);
+ }
+ while (shader_tabs->get_tab_count() > 1) {
+ _close_shader(1);
+ }
+ } break;
+ case SHOW_IN_FILE_SYSTEM: {
+ Ref<Resource> shader = _get_current_shader();
+ String path = shader->get_path();
+ if (!path.is_empty()) {
+ FileSystemDock::get_singleton()->navigate_to_path(path);
+ }
+ } break;
+ case COPY_PATH: {
+ Ref<Resource> shader = _get_current_shader();
+ DisplayServer::get_singleton()->clipboard_set(shader->get_path());
+ } break;
}
}
@@ -623,8 +695,9 @@ void ShaderEditorPlugin::_set_text_shader_zoom_factor(float p_zoom_factor) {
if (text_shader_zoom_factor != p_zoom_factor) {
text_shader_zoom_factor = p_zoom_factor;
for (const EditedShader &edited_shader : edited_shaders) {
- if (edited_shader.shader_editor) {
- CodeTextEditor *cte = edited_shader.shader_editor->get_code_editor();
+ TextShaderEditor *text_shader_editor = Object::cast_to<TextShaderEditor>(edited_shader.shader_editor);
+ if (text_shader_editor) {
+ CodeTextEditor *cte = text_shader_editor->get_code_editor();
if (cte && cte->get_zoom_factor() != text_shader_zoom_factor) {
cte->set_zoom_factor(text_shader_zoom_factor);
}
@@ -655,17 +728,26 @@ void ShaderEditorPlugin::_res_saved_callback(const Ref<Resource> &p_res) {
}
ERR_FAIL_COND(shader_res.is_null());
- if (!edited.shader_editor || !shader_res->is_built_in()) {
+ TextShaderEditor *text_shader_editor = Object::cast_to<TextShaderEditor>(edited.shader_editor);
+ if (!text_shader_editor || !shader_res->is_built_in()) {
continue;
}
if (shader_res->get_path().get_slice("::", 0) == path) {
- edited.shader_editor->tag_saved_version();
+ text_shader_editor->tag_saved_version();
_update_shader_list();
}
}
}
+void ShaderEditorPlugin::_set_file_specific_items_disabled(bool p_disabled) {
+ PopupMenu *file_popup_menu = file_menu->get_popup();
+ file_popup_menu->set_item_disabled(file_popup_menu->get_item_index(FILE_SAVE), p_disabled);
+ file_popup_menu->set_item_disabled(file_popup_menu->get_item_index(FILE_SAVE_AS), p_disabled);
+ file_popup_menu->set_item_disabled(file_popup_menu->get_item_index(FILE_INSPECT), p_disabled);
+ file_popup_menu->set_item_disabled(file_popup_menu->get_item_index(FILE_CLOSE), p_disabled);
+}
+
void ShaderEditorPlugin::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY: {
@@ -693,23 +775,15 @@ ShaderEditorPlugin::ShaderEditorPlugin() {
file_menu = memnew(MenuButton);
file_menu->set_text(TTR("File"));
file_menu->set_shortcut_context(main_split);
- file_menu->get_popup()->add_item(TTR("New Shader..."), FILE_NEW);
- file_menu->get_popup()->add_item(TTR("New Shader Include..."), FILE_NEW_INCLUDE);
- file_menu->get_popup()->add_separator();
- file_menu->get_popup()->add_item(TTR("Load Shader File..."), FILE_OPEN);
- file_menu->get_popup()->add_item(TTR("Load Shader Include File..."), FILE_OPEN_INCLUDE);
- file_menu->get_popup()->add_shortcut(ED_SHORTCUT("shader_editor/save", TTR("Save File"), KeyModifierMask::ALT | KeyModifierMask::CMD_OR_CTRL | Key::S), FILE_SAVE);
- file_menu->get_popup()->add_shortcut(ED_SHORTCUT("shader_editor/save_as", TTR("Save File As...")), FILE_SAVE_AS);
- file_menu->get_popup()->add_separator();
- file_menu->get_popup()->add_item(TTR("Open File in Inspector"), FILE_INSPECT);
- file_menu->get_popup()->add_separator();
- file_menu->get_popup()->add_item(TTR("Close File"), FILE_CLOSE);
+ _setup_popup_menu(FILE, file_menu->get_popup());
file_menu->get_popup()->connect(SceneStringName(id_pressed), callable_mp(this, &ShaderEditorPlugin::_menu_item_pressed));
menu_hb->add_child(file_menu);
- for (int i = FILE_SAVE; i < FILE_MAX; i++) {
- file_menu->get_popup()->set_item_disabled(file_menu->get_popup()->get_item_index(i), true);
- }
+ _set_file_specific_items_disabled(true);
+
+ context_menu = memnew(PopupMenu);
+ add_child(context_menu);
+ context_menu->connect(SceneStringName(id_pressed), callable_mp(this, &ShaderEditorPlugin::_menu_item_pressed));
Control *padding = memnew(Control);
padding->set_h_size_flags(Control::SIZE_EXPAND_FILL);
@@ -732,6 +806,7 @@ ShaderEditorPlugin::ShaderEditorPlugin() {
vb->add_child(shader_list);
shader_list->connect(SceneStringName(item_selected), callable_mp(this, &ShaderEditorPlugin::_shader_selected));
shader_list->connect("item_clicked", callable_mp(this, &ShaderEditorPlugin::_shader_list_clicked));
+ shader_list->set_allow_rmb_select(true);
SET_DRAG_FORWARDING_GCD(shader_list, ShaderEditorPlugin);
main_split->add_child(vb);
diff --git a/editor/plugins/shader_editor_plugin.h b/editor/plugins/shader_editor_plugin.h
index 386261d844..31be64a56c 100644
--- a/editor/plugins/shader_editor_plugin.h
+++ b/editor/plugins/shader_editor_plugin.h
@@ -37,6 +37,7 @@ class HSplitContainer;
class ItemList;
class MenuButton;
class ShaderCreateDialog;
+class ShaderEditor;
class TabContainer;
class TextShaderEditor;
class VisualShaderEditor;
@@ -52,16 +53,13 @@ class ShaderEditorPlugin : public EditorPlugin {
struct EditedShader {
Ref<Shader> shader;
Ref<ShaderInclude> shader_inc;
- TextShaderEditor *shader_editor = nullptr;
- VisualShaderEditor *visual_shader_editor = nullptr;
+ ShaderEditor *shader_editor = nullptr;
String path;
String name;
};
LocalVector<EditedShader> edited_shaders;
- // Always valid operations come first in the enum, file-specific ones
- // should go after FILE_SAVE which is used to build the menu accordingly.
enum {
FILE_NEW,
FILE_NEW_INCLUDE,
@@ -71,7 +69,16 @@ class ShaderEditorPlugin : public EditorPlugin {
FILE_SAVE_AS,
FILE_INSPECT,
FILE_CLOSE,
- FILE_MAX
+ CLOSE_ALL,
+ CLOSE_OTHER_TABS,
+ SHOW_IN_FILE_SYSTEM,
+ COPY_PATH,
+ };
+
+ enum PopupMenuType {
+ FILE,
+ CONTEXT,
+ CONTEXT_VALID_ITEM,
};
HSplitContainer *main_split = nullptr;
@@ -80,6 +87,7 @@ class ShaderEditorPlugin : public EditorPlugin {
Button *button = nullptr;
MenuButton *file_menu = nullptr;
+ PopupMenu *context_menu = nullptr;
WindowWrapper *window_wrapper = nullptr;
Button *make_floating = nullptr;
@@ -88,15 +96,19 @@ class ShaderEditorPlugin : public EditorPlugin {
float text_shader_zoom_factor = 1.0f;
+ Ref<Resource> _get_current_shader();
void _update_shader_list();
void _shader_selected(int p_index);
void _shader_list_clicked(int p_item, Vector2 p_local_mouse_pos, MouseButton p_mouse_button_index);
+ void _setup_popup_menu(PopupMenuType p_type, PopupMenu *p_menu);
+ void _make_script_list_context_menu();
void _menu_item_pressed(int p_index);
void _resource_saved(Object *obj);
void _close_shader(int p_index);
void _close_builtin_shaders_from_scene(const String &p_scene);
void _file_removed(const String &p_removed_file);
void _res_saved_callback(const Ref<Resource> &p_res);
+ void _set_file_specific_items_disabled(bool p_disabled);
void _shader_created(Ref<Shader> p_shader);
void _shader_include_created(Ref<ShaderInclude> p_shader_inc);
@@ -121,8 +133,7 @@ public:
virtual void make_visible(bool p_visible) override;
virtual void selected_notify() override;
- TextShaderEditor *get_shader_editor(const Ref<Shader> &p_for_shader);
- VisualShaderEditor *get_visual_shader_editor(const Ref<Shader> &p_for_shader);
+ ShaderEditor *get_shader_editor(const Ref<Shader> &p_for_shader);
virtual void set_window_layout(Ref<ConfigFile> p_layout) override;
virtual void get_window_layout(Ref<ConfigFile> p_layout) override;
diff --git a/editor/plugins/shader_file_editor_plugin.cpp b/editor/plugins/shader_file_editor_plugin.cpp
index 05919fb0f6..d732d51f69 100644
--- a/editor/plugins/shader_file_editor_plugin.cpp
+++ b/editor/plugins/shader_file_editor_plugin.cpp
@@ -218,9 +218,6 @@ void ShaderFileEditor::_editor_settings_changed() {
}
}
-void ShaderFileEditor::_bind_methods() {
-}
-
void ShaderFileEditor::edit(const Ref<RDShaderFile> &p_shader) {
if (p_shader.is_null()) {
if (shader_file.is_valid()) {
diff --git a/editor/plugins/shader_file_editor_plugin.h b/editor/plugins/shader_file_editor_plugin.h
index 9a915513ef..fea770b7e0 100644
--- a/editor/plugins/shader_file_editor_plugin.h
+++ b/editor/plugins/shader_file_editor_plugin.h
@@ -62,7 +62,6 @@ class ShaderFileEditor : public PanelContainer {
protected:
void _notification(int p_what);
- static void _bind_methods();
public:
static ShaderFileEditor *singleton;
diff --git a/editor/plugins/skeleton_2d_editor_plugin.cpp b/editor/plugins/skeleton_2d_editor_plugin.cpp
index 8308fe6d6e..97c5c0c7dd 100644
--- a/editor/plugins/skeleton_2d_editor_plugin.cpp
+++ b/editor/plugins/skeleton_2d_editor_plugin.cpp
@@ -90,9 +90,6 @@ void Skeleton2DEditor::_menu_option(int p_option) {
}
}
-void Skeleton2DEditor::_bind_methods() {
-}
-
Skeleton2DEditor::Skeleton2DEditor() {
options = memnew(MenuButton);
diff --git a/editor/plugins/skeleton_2d_editor_plugin.h b/editor/plugins/skeleton_2d_editor_plugin.h
index 74fd59f1c4..89e2e5d0f2 100644
--- a/editor/plugins/skeleton_2d_editor_plugin.h
+++ b/editor/plugins/skeleton_2d_editor_plugin.h
@@ -57,7 +57,6 @@ class Skeleton2DEditor : public Control {
protected:
void _node_removed(Node *p_node);
- static void _bind_methods();
public:
void edit(Skeleton2D *p_sprite);
diff --git a/editor/plugins/skeleton_ik_3d_editor_plugin.cpp b/editor/plugins/skeleton_ik_3d_editor_plugin.cpp
index 1753df5cb7..9b98b6ffa2 100644
--- a/editor/plugins/skeleton_ik_3d_editor_plugin.cpp
+++ b/editor/plugins/skeleton_ik_3d_editor_plugin.cpp
@@ -73,9 +73,6 @@ void SkeletonIK3DEditorPlugin::make_visible(bool p_visible) {
}
}
-void SkeletonIK3DEditorPlugin::_bind_methods() {
-}
-
SkeletonIK3DEditorPlugin::SkeletonIK3DEditorPlugin() {
play_btn = memnew(Button);
play_btn->set_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Play"), EditorStringName(EditorIcons)));
diff --git a/editor/plugins/skeleton_ik_3d_editor_plugin.h b/editor/plugins/skeleton_ik_3d_editor_plugin.h
index 2ef5467263..95ab3696be 100644
--- a/editor/plugins/skeleton_ik_3d_editor_plugin.h
+++ b/editor/plugins/skeleton_ik_3d_editor_plugin.h
@@ -45,9 +45,6 @@ class SkeletonIK3DEditorPlugin : public EditorPlugin {
void _play();
-protected:
- static void _bind_methods();
-
public:
virtual String get_name() const override { return "SkeletonIK3D"; }
bool has_main_screen() const override { return false; }
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index 48087e3166..ff5aca6cb0 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -504,6 +504,82 @@ void SpriteFramesEditor::_update_show_settings() {
}
}
+void SpriteFramesEditor::_auto_slice_sprite_sheet() {
+ if (updating_split_settings) {
+ return;
+ }
+ updating_split_settings = true;
+
+ const Size2i size = split_sheet_preview->get_texture()->get_size();
+
+ const Size2i split_sheet = _estimate_sprite_sheet_size(split_sheet_preview->get_texture());
+ split_sheet_h->set_value(split_sheet.x);
+ split_sheet_v->set_value(split_sheet.y);
+ split_sheet_size_x->set_value(size.x / split_sheet.x);
+ split_sheet_size_y->set_value(size.y / split_sheet.y);
+ split_sheet_sep_x->set_value(0);
+ split_sheet_sep_y->set_value(0);
+ split_sheet_offset_x->set_value(0);
+ split_sheet_offset_y->set_value(0);
+
+ updating_split_settings = false;
+
+ frames_selected.clear();
+ selected_count = 0;
+ last_frame_selected = -1;
+ split_sheet_preview->queue_redraw();
+}
+
+bool SpriteFramesEditor::_matches_background_color(const Color &p_background_color, const Color &p_pixel_color) {
+ if ((p_background_color.a == 0 && p_pixel_color.a == 0) || p_background_color.is_equal_approx(p_pixel_color)) {
+ return true;
+ }
+
+ Color d = p_background_color - p_pixel_color;
+ // 0.04f is the threshold for how much a colour can deviate from background colour and still be considered a match. Arrived at through experimentation, can be tweaked.
+ return (d.r * d.r) + (d.g * d.g) + (d.b * d.b) + (d.a * d.a) < 0.04f;
+}
+
+Size2i SpriteFramesEditor::_estimate_sprite_sheet_size(const Ref<Texture2D> p_texture) {
+ Ref<Image> image = p_texture->get_image();
+ Size2i size = p_texture->get_size();
+
+ Color assumed_background_color = image->get_pixel(0, 0);
+ Size2i sheet_size;
+
+ bool previous_line_background = true;
+ for (int x = 0; x < size.x; x++) {
+ int y = 0;
+ while (y < size.y && _matches_background_color(assumed_background_color, image->get_pixel(x, y))) {
+ y++;
+ }
+ bool current_line_background = (y == size.y);
+ if (previous_line_background && !current_line_background) {
+ sheet_size.x++;
+ }
+ previous_line_background = current_line_background;
+ }
+
+ previous_line_background = true;
+ for (int y = 0; y < size.y; y++) {
+ int x = 0;
+ while (x < size.x && _matches_background_color(assumed_background_color, image->get_pixel(x, y))) {
+ x++;
+ }
+ bool current_line_background = (x == size.x);
+ if (previous_line_background && !current_line_background) {
+ sheet_size.y++;
+ }
+ previous_line_background = current_line_background;
+ }
+
+ if (sheet_size == Size2i(0, 0) || sheet_size == Size2i(1, 1)) {
+ sheet_size = Size2i(4, 4);
+ }
+
+ return sheet_size;
+}
+
void SpriteFramesEditor::_prepare_sprite_sheet(const String &p_file) {
Ref<Texture2D> texture = ResourceLoader::load(p_file);
if (texture.is_null()) {
@@ -530,10 +606,11 @@ void SpriteFramesEditor::_prepare_sprite_sheet(const String &p_file) {
// Different texture, reset to 4x4.
dominant_param = PARAM_FRAME_COUNT;
updating_split_settings = true;
- split_sheet_h->set_value(4);
- split_sheet_v->set_value(4);
- split_sheet_size_x->set_value(size.x / 4);
- split_sheet_size_y->set_value(size.y / 4);
+ const Size2i split_sheet = Size2i(4, 4);
+ split_sheet_h->set_value(split_sheet.x);
+ split_sheet_v->set_value(split_sheet.y);
+ split_sheet_size_x->set_value(size.x / split_sheet.x);
+ split_sheet_size_y->set_value(size.y / split_sheet.y);
split_sheet_sep_x->set_value(0);
split_sheet_sep_y->set_value(0);
split_sheet_offset_x->set_value(0);
@@ -2290,6 +2367,11 @@ SpriteFramesEditor::SpriteFramesEditor() {
split_sheet_offset_hb->add_child(split_sheet_offset_vb);
split_sheet_settings_vb->add_child(split_sheet_offset_hb);
+ Button *auto_slice = memnew(Button);
+ auto_slice->set_text(TTR("Auto Slice"));
+ auto_slice->connect(SceneStringName(pressed), callable_mp(this, &SpriteFramesEditor::_auto_slice_sprite_sheet));
+ split_sheet_settings_vb->add_child(auto_slice);
+
split_sheet_hb->add_child(split_sheet_settings_vb);
file_split_sheet = memnew(EditorFileDialog);
diff --git a/editor/plugins/sprite_frames_editor_plugin.h b/editor/plugins/sprite_frames_editor_plugin.h
index 9b6aaf98fe..d6345a3ac8 100644
--- a/editor/plugins/sprite_frames_editor_plugin.h
+++ b/editor/plugins/sprite_frames_editor_plugin.h
@@ -234,6 +234,9 @@ class SpriteFramesEditor : public HSplitContainer {
void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
void _open_sprite_sheet();
+ void _auto_slice_sprite_sheet();
+ bool _matches_background_color(const Color &p_background_color, const Color &p_pixel_color);
+ Size2i _estimate_sprite_sheet_size(const Ref<Texture2D> p_texture);
void _prepare_sprite_sheet(const String &p_file);
int _sheet_preview_position_to_frame_index(const Vector2 &p_position);
void _sheet_preview_draw();
diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp
index ecdc4acf47..cb1f6c1ec6 100644
--- a/editor/plugins/text_editor.cpp
+++ b/editor/plugins/text_editor.cpp
@@ -304,8 +304,8 @@ void TextEditor::tag_saved_version() {
code_editor->get_text_editor()->tag_saved_version();
}
-void TextEditor::goto_line(int p_line, bool p_with_error) {
- code_editor->goto_line(p_line);
+void TextEditor::goto_line(int p_line, int p_column) {
+ code_editor->goto_line(p_line, p_column);
}
void TextEditor::goto_line_selection(int p_line, int p_begin, int p_end) {
diff --git a/editor/plugins/text_editor.h b/editor/plugins/text_editor.h
index 268e5c32b4..1acec4e959 100644
--- a/editor/plugins/text_editor.h
+++ b/editor/plugins/text_editor.h
@@ -129,7 +129,7 @@ public:
virtual PackedInt32Array get_breakpoints() override;
virtual void set_breakpoint(int p_line, bool p_enabled) override{};
virtual void clear_breakpoints() override{};
- virtual void goto_line(int p_line, bool p_with_error = false) override;
+ virtual void goto_line(int p_line, int p_column = 0) override;
void goto_line_selection(int p_line, int p_begin, int p_end);
virtual void set_executing_line(int p_line) override;
virtual void clear_executing_line() override;
diff --git a/editor/plugins/text_shader_editor.cpp b/editor/plugins/text_shader_editor.cpp
index 276c57533f..4d8f3298b6 100644
--- a/editor/plugins/text_shader_editor.cpp
+++ b/editor/plugins/text_shader_editor.cpp
@@ -779,7 +779,7 @@ void TextShaderEditor::_show_warnings_panel(bool p_show) {
void TextShaderEditor::_warning_clicked(const Variant &p_line) {
if (p_line.get_type() == Variant::INT) {
- code_editor->get_text_editor()->set_caret_line(p_line.operator int64_t());
+ code_editor->goto_line_centered(p_line.operator int64_t());
}
}
@@ -895,7 +895,7 @@ void TextShaderEditor::_reload() {
}
}
-void TextShaderEditor::edit(const Ref<Shader> &p_shader) {
+void TextShaderEditor::edit_shader(const Ref<Shader> &p_shader) {
if (p_shader.is_null() || !p_shader->is_text_shader()) {
return;
}
@@ -910,7 +910,7 @@ void TextShaderEditor::edit(const Ref<Shader> &p_shader) {
code_editor->set_edited_shader(shader);
}
-void TextShaderEditor::edit(const Ref<ShaderInclude> &p_shader_inc) {
+void TextShaderEditor::edit_shader_include(const Ref<ShaderInclude> &p_shader_inc) {
if (p_shader_inc.is_null()) {
return;
}
@@ -1141,6 +1141,7 @@ TextShaderEditor::TextShaderEditor() {
context_menu->connect(SceneStringName(id_pressed), callable_mp(this, &TextShaderEditor::_menu_option));
VBoxContainer *main_container = memnew(VBoxContainer);
+ main_container->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
HBoxContainer *hbc = memnew(HBoxContainer);
edit_menu = memnew(MenuButton);
diff --git a/editor/plugins/text_shader_editor.h b/editor/plugins/text_shader_editor.h
index 61066ed7c6..55efb4e30e 100644
--- a/editor/plugins/text_shader_editor.h
+++ b/editor/plugins/text_shader_editor.h
@@ -32,6 +32,7 @@
#define TEXT_SHADER_EDITOR_H
#include "editor/code_editor.h"
+#include "editor/plugins/shader/shader_editor.h"
#include "scene/gui/margin_container.h"
#include "scene/gui/menu_button.h"
#include "scene/gui/rich_text_label.h"
@@ -104,8 +105,8 @@ public:
ShaderTextEditor();
};
-class TextShaderEditor : public MarginContainer {
- GDCLASS(TextShaderEditor, MarginContainer);
+class TextShaderEditor : public ShaderEditor {
+ GDCLASS(TextShaderEditor, ShaderEditor);
enum {
EDIT_UNDO,
@@ -188,19 +189,21 @@ protected:
void _bookmark_item_pressed(int p_idx);
public:
+ virtual void edit_shader(const Ref<Shader> &p_shader) override;
+ virtual void edit_shader_include(const Ref<ShaderInclude> &p_shader_inc) override;
+
+ virtual void apply_shaders() override;
+ virtual bool is_unsaved() const override;
+ virtual void save_external_data(const String &p_str = "") override;
+ virtual void validate_script() override;
+
bool was_compilation_successful() const { return compilation_success; }
bool get_trim_trailing_whitespace_on_save() const { return trim_trailing_whitespace_on_save; }
bool get_trim_final_newlines_on_save() const { return trim_final_newlines_on_save; }
- void apply_shaders();
void ensure_select_current();
- void edit(const Ref<Shader> &p_shader);
- void edit(const Ref<ShaderInclude> &p_shader_inc);
void goto_line_selection(int p_line, int p_begin, int p_end);
- void save_external_data(const String &p_str = "");
void trim_trailing_whitespace();
void trim_final_newlines();
- void validate_script();
- bool is_unsaved() const;
void tag_saved_version();
ShaderTextEditor *get_code_editor() { return code_editor; }
diff --git a/editor/plugins/texture_3d_editor_plugin.cpp b/editor/plugins/texture_3d_editor_plugin.cpp
index fa90e982fe..9fce79622a 100644
--- a/editor/plugins/texture_3d_editor_plugin.cpp
+++ b/editor/plugins/texture_3d_editor_plugin.cpp
@@ -30,8 +30,25 @@
#include "texture_3d_editor_plugin.h"
+#include "editor/editor_string_names.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/label.h"
+// Shader sources.
+
+constexpr const char *texture_3d_shader = R"(
+ // Texture3DEditor preview shader.
+
+ shader_type canvas_item;
+
+ uniform sampler3D tex;
+ uniform float layer;
+
+ void fragment() {
+ COLOR = textureLod(tex, vec3(UV, layer), 0.0);
+ }
+)";
+
void Texture3DEditor::_texture_rect_draw() {
texture_rect->draw_rect(Rect2(Point2(), texture_rect->get_size()), Color(1, 1, 1, 1));
}
@@ -48,6 +65,13 @@ void Texture3DEditor::_notification(int p_what) {
draw_texture_rect(checkerboard, Rect2(Point2(), size), true);
} break;
+
+ case NOTIFICATION_THEME_CHANGED: {
+ if (info) {
+ Ref<Font> metadata_label_font = get_theme_font(SNAME("expression"), EditorStringName(EditorFonts));
+ info->add_theme_font_override(SceneStringName(font), metadata_label_font);
+ }
+ } break;
}
}
@@ -55,35 +79,27 @@ void Texture3DEditor::_texture_changed() {
if (!is_visible()) {
return;
}
+
+ setting = true;
+ _update_gui();
+ setting = false;
+
+ _update_material(true);
queue_redraw();
}
-void Texture3DEditor::_update_material() {
+void Texture3DEditor::_update_material(bool p_texture_changed) {
material->set_shader_parameter("layer", (layer->get_value() + 0.5) / texture->get_depth());
- material->set_shader_parameter("tex", texture->get_rid());
-
- String format = Image::get_format_name(texture->get_format());
-
- String text;
- text = itos(texture->get_width()) + "x" + itos(texture->get_height()) + "x" + itos(texture->get_depth()) + " " + format;
- info->set_text(text);
+ if (p_texture_changed) {
+ material->set_shader_parameter("tex", texture->get_rid());
+ }
}
void Texture3DEditor::_make_shaders() {
shader.instantiate();
- shader->set_code(R"(
-// Texture3DEditor preview shader.
-
-shader_type canvas_item;
-
-uniform sampler3D tex;
-uniform float layer;
+ shader->set_code(texture_3d_shader);
-void fragment() {
- COLOR = textureLod(tex, vec3(UV, layer), 0.0);
-}
-)");
material.instantiate();
material->set_shader(shader);
}
@@ -113,6 +129,41 @@ void Texture3DEditor::_texture_rect_update_area() {
texture_rect->set_size(Vector2(tex_width, tex_height));
}
+void Texture3DEditor::_update_gui() {
+ if (texture.is_null()) {
+ return;
+ }
+
+ _texture_rect_update_area();
+
+ layer->set_max(texture->get_depth() - 1);
+
+ const String format = Image::get_format_name(texture->get_format());
+
+ if (texture->has_mipmaps()) {
+ const int mip_count = Image::get_image_required_mipmaps(texture->get_width(), texture->get_height(), texture->get_format());
+ const int memory = Image::get_image_data_size(texture->get_width(), texture->get_height(), texture->get_format(), true) * texture->get_depth();
+
+ info->set_text(vformat(String::utf8("%d×%d×%d %s\n") + TTR("%s Mipmaps") + "\n" + TTR("Memory: %s"),
+ texture->get_width(),
+ texture->get_height(),
+ texture->get_depth(),
+ format,
+ mip_count,
+ String::humanize_size(memory)));
+
+ } else {
+ const int memory = Image::get_image_data_size(texture->get_width(), texture->get_height(), texture->get_format(), false) * texture->get_depth();
+
+ info->set_text(vformat(String::utf8("%d×%d×%d %s\n") + TTR("No Mipmaps") + "\n" + TTR("Memory: %s"),
+ texture->get_width(),
+ texture->get_height(),
+ texture->get_depth(),
+ format,
+ String::humanize_size(memory)));
+ }
+}
+
void Texture3DEditor::edit(Ref<Texture3D> p_texture) {
if (!texture.is_null()) {
texture->disconnect_changed(callable_mp(this, &Texture3DEditor::_texture_changed));
@@ -126,15 +177,17 @@ void Texture3DEditor::edit(Ref<Texture3D> p_texture) {
}
texture->connect_changed(callable_mp(this, &Texture3DEditor::_texture_changed));
- queue_redraw();
texture_rect->set_material(material);
+
setting = true;
- layer->set_max(texture->get_depth() - 1);
layer->set_value(0);
layer->show();
- _update_material();
+ _update_gui();
setting = false;
- _texture_rect_update_area();
+
+ _update_material(true);
+ queue_redraw();
+
} else {
hide();
}
@@ -142,36 +195,43 @@ void Texture3DEditor::edit(Ref<Texture3D> p_texture) {
Texture3DEditor::Texture3DEditor() {
set_texture_repeat(TextureRepeat::TEXTURE_REPEAT_ENABLED);
- set_custom_minimum_size(Size2(1, 150));
+ set_custom_minimum_size(Size2(1, 256.0) * EDSCALE);
texture_rect = memnew(Control);
texture_rect->set_mouse_filter(MOUSE_FILTER_IGNORE);
- add_child(texture_rect);
texture_rect->connect(SceneStringName(draw), callable_mp(this, &Texture3DEditor::_texture_rect_draw));
+ add_child(texture_rect);
+
layer = memnew(SpinBox);
layer->set_step(1);
layer->set_max(100);
- layer->set_h_grow_direction(GROW_DIRECTION_BEGIN);
+
layer->set_modulate(Color(1, 1, 1, 0.8));
- add_child(layer);
+ layer->set_h_grow_direction(GROW_DIRECTION_BEGIN);
layer->set_anchor(SIDE_RIGHT, 1);
layer->set_anchor(SIDE_LEFT, 1);
layer->connect(SceneStringName(value_changed), callable_mp(this, &Texture3DEditor::_layer_changed));
+ add_child(layer);
+
info = memnew(Label);
+ info->add_theme_color_override(SceneStringName(font_color), Color(1, 1, 1));
+ info->add_theme_color_override("font_shadow_color", Color(0, 0, 0));
+ info->add_theme_font_size_override(SceneStringName(font_size), 14 * EDSCALE);
+ info->add_theme_color_override("font_outline_color", Color(0, 0, 0));
+ info->add_theme_constant_override("outline_size", 8 * EDSCALE);
+
info->set_h_grow_direction(GROW_DIRECTION_BEGIN);
info->set_v_grow_direction(GROW_DIRECTION_BEGIN);
- info->add_theme_color_override(SceneStringName(font_color), Color(1, 1, 1, 1));
- info->add_theme_color_override("font_shadow_color", Color(0, 0, 0, 0.5));
- info->add_theme_constant_override("shadow_outline_size", 1);
- info->add_theme_constant_override("shadow_offset_x", 2);
- info->add_theme_constant_override("shadow_offset_y", 2);
- add_child(info);
+ info->set_h_size_flags(Control::SIZE_SHRINK_END);
+ info->set_v_size_flags(Control::SIZE_SHRINK_END);
info->set_anchor(SIDE_RIGHT, 1);
info->set_anchor(SIDE_LEFT, 1);
info->set_anchor(SIDE_BOTTOM, 1);
info->set_anchor(SIDE_TOP, 1);
+
+ add_child(info);
}
Texture3DEditor::~Texture3DEditor() {
@@ -180,7 +240,6 @@ Texture3DEditor::~Texture3DEditor() {
}
}
-//
bool EditorInspectorPlugin3DTexture::can_handle(Object *p_object) {
return Object::cast_to<Texture3D>(p_object) != nullptr;
}
diff --git a/editor/plugins/texture_3d_editor_plugin.h b/editor/plugins/texture_3d_editor_plugin.h
index 7a33a97a8f..0712ff423a 100644
--- a/editor/plugins/texture_3d_editor_plugin.h
+++ b/editor/plugins/texture_3d_editor_plugin.h
@@ -52,23 +52,27 @@ class Texture3DEditor : public Control {
bool setting = false;
void _make_shaders();
- void _update_material();
void _layer_changed(double) {
if (!setting) {
- _update_material();
+ _update_material(false);
}
}
+
void _texture_changed();
void _texture_rect_update_area();
void _texture_rect_draw();
+ void _update_material(bool p_texture_changed);
+ void _update_gui();
+
protected:
void _notification(int p_what);
public:
void edit(Ref<Texture3D> p_texture);
+
Texture3DEditor();
~Texture3DEditor();
};
diff --git a/editor/plugins/texture_editor_plugin.cpp b/editor/plugins/texture_editor_plugin.cpp
index e9d7aa9eb8..a3c1405553 100644
--- a/editor/plugins/texture_editor_plugin.cpp
+++ b/editor/plugins/texture_editor_plugin.cpp
@@ -145,12 +145,13 @@ TexturePreview::TexturePreview(Ref<Texture2D> p_texture, bool p_show_metadata) {
p_texture->connect_changed(callable_mp(this, &TexturePreview::_update_metadata_label_text));
// It's okay that these colors are static since the grid color is static too.
- metadata_label->add_theme_color_override(SceneStringName(font_color), Color::named("white"));
- metadata_label->add_theme_color_override("font_shadow_color", Color::named("black"));
+ metadata_label->add_theme_color_override(SceneStringName(font_color), Color(1, 1, 1));
+ metadata_label->add_theme_color_override("font_shadow_color", Color(0, 0, 0));
metadata_label->add_theme_font_size_override(SceneStringName(font_size), 14 * EDSCALE);
- metadata_label->add_theme_color_override("font_outline_color", Color::named("black"));
+ metadata_label->add_theme_color_override("font_outline_color", Color(0, 0, 0));
metadata_label->add_theme_constant_override("outline_size", 8 * EDSCALE);
+
metadata_label->set_h_size_flags(Control::SIZE_SHRINK_END);
metadata_label->set_v_size_flags(Control::SIZE_SHRINK_END);
diff --git a/editor/plugins/texture_layered_editor_plugin.cpp b/editor/plugins/texture_layered_editor_plugin.cpp
index 4ec9c91cf9..a8aa89a8c4 100644
--- a/editor/plugins/texture_layered_editor_plugin.cpp
+++ b/editor/plugins/texture_layered_editor_plugin.cpp
@@ -30,16 +30,64 @@
#include "texture_layered_editor_plugin.h"
+#include "editor/editor_string_names.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/label.h"
+// Shader sources.
+
+constexpr const char *array_2d_shader = R"(
+ // TextureLayeredEditor preview shader (2D array).
+
+ shader_type canvas_item;
+
+ uniform sampler2DArray tex;
+ uniform float layer;
+
+ void fragment() {
+ COLOR = textureLod(tex, vec3(UV, layer), 0.0);
+ }
+)";
+
+constexpr const char *cubemap_shader = R"(
+ // TextureLayeredEditor preview shader (cubemap).
+
+ shader_type canvas_item;
+
+ uniform samplerCube tex;
+ uniform vec3 normal;
+ uniform mat3 rot;
+
+ void fragment() {
+ vec3 n = rot * normalize(vec3(normal.xy * (UV * 2.0 - 1.0), normal.z));
+ COLOR = textureLod(tex, n, 0.0);
+ }
+)";
+
+constexpr const char *cubemap_array_shader = R"(
+ // TextureLayeredEditor preview shader (cubemap array).
+
+ shader_type canvas_item;
+ uniform samplerCubeArray tex;
+ uniform vec3 normal;
+ uniform mat3 rot;
+ uniform float layer;
+
+ void fragment() {
+ vec3 n = rot * normalize(vec3(normal.xy * (UV * 2.0 - 1.0), normal.z));
+ COLOR = textureLod(tex, vec4(n, layer), 0.0);
+ }
+)";
+
void TextureLayeredEditor::gui_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
Ref<InputEventMouseMotion> mm = p_event;
if (mm.is_valid() && (mm->get_button_mask().has_flag(MouseButtonMask::LEFT))) {
y_rot += -mm->get_relative().x * 0.01;
- x_rot += mm->get_relative().y * 0.01;
- _update_material();
+ x_rot += -mm->get_relative().y * 0.01;
+
+ _update_material(false);
}
}
@@ -47,6 +95,69 @@ void TextureLayeredEditor::_texture_rect_draw() {
texture_rect->draw_rect(Rect2(Point2(), texture_rect->get_size()), Color(1, 1, 1, 1));
}
+void TextureLayeredEditor::_update_gui() {
+ if (texture.is_null()) {
+ return;
+ }
+
+ _texture_rect_update_area();
+
+ const String format = Image::get_format_name(texture->get_format());
+ String texture_info;
+
+ switch (texture->get_layered_type()) {
+ case TextureLayered::LAYERED_TYPE_2D_ARRAY: {
+ layer->set_max(texture->get_layers() - 1);
+
+ texture_info = vformat(String::utf8("%d×%d (×%d) %s\n"),
+ texture->get_width(),
+ texture->get_height(),
+ texture->get_layers(),
+ format);
+
+ } break;
+ case TextureLayered::LAYERED_TYPE_CUBEMAP: {
+ layer->hide();
+
+ texture_info = vformat(String::utf8("%d×%d %s\n"),
+ texture->get_width(),
+ texture->get_height(),
+ format);
+
+ } break;
+ case TextureLayered::LAYERED_TYPE_CUBEMAP_ARRAY: {
+ layer->set_max(texture->get_layers() / 6 - 1);
+
+ texture_info = vformat(String::utf8("%d×%d (×%d) %s\n"),
+ texture->get_width(),
+ texture->get_height(),
+ texture->get_layers() / 6,
+ format);
+
+ } break;
+
+ default: {
+ }
+ }
+
+ if (texture->has_mipmaps()) {
+ const int mip_count = Image::get_image_required_mipmaps(texture->get_width(), texture->get_height(), texture->get_format());
+ const int memory = Image::get_image_data_size(texture->get_width(), texture->get_height(), texture->get_format(), true) * texture->get_layers();
+
+ texture_info += vformat(TTR("%s Mipmaps") + "\n" + TTR("Memory: %s"),
+ mip_count,
+ String::humanize_size(memory));
+
+ } else {
+ const int memory = Image::get_image_data_size(texture->get_width(), texture->get_height(), texture->get_format(), false) * texture->get_layers();
+
+ texture_info += vformat(TTR("No Mipmaps") + "\n" + TTR("Memory: %s"),
+ String::humanize_size(memory));
+ }
+
+ info->set_text(texture_info);
+}
+
void TextureLayeredEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_RESIZED: {
@@ -59,6 +170,13 @@ void TextureLayeredEditor::_notification(int p_what) {
draw_texture_rect(checkerboard, Rect2(Point2(), size), true);
} break;
+
+ case NOTIFICATION_THEME_CHANGED: {
+ if (info) {
+ Ref<Font> metadata_label_font = get_theme_font(SNAME("expression"), EditorStringName(EditorFonts));
+ info->add_theme_font_override(SceneStringName(font), metadata_label_font);
+ }
+ } break;
}
}
@@ -66,13 +184,18 @@ void TextureLayeredEditor::_texture_changed() {
if (!is_visible()) {
return;
}
+
+ setting = true;
+ _update_gui();
+ setting = false;
+
+ _update_material(true);
queue_redraw();
}
-void TextureLayeredEditor::_update_material() {
+void TextureLayeredEditor::_update_material(bool p_texture_changed) {
materials[0]->set_shader_parameter("layer", layer->get_value());
materials[2]->set_shader_parameter("layer", layer->get_value());
- materials[texture->get_layered_type()]->set_shader_parameter("tex", texture->get_rid());
Vector3 v(1, 1, 1);
v.normalize();
@@ -86,67 +209,20 @@ void TextureLayeredEditor::_update_material() {
materials[2]->set_shader_parameter("normal", v);
materials[2]->set_shader_parameter("rot", b);
- String format = Image::get_format_name(texture->get_format());
-
- String text;
- if (texture->get_layered_type() == TextureLayered::LAYERED_TYPE_2D_ARRAY) {
- text = itos(texture->get_width()) + "x" + itos(texture->get_height()) + " (x " + itos(texture->get_layers()) + ")" + format;
- } else if (texture->get_layered_type() == TextureLayered::LAYERED_TYPE_CUBEMAP) {
- text = itos(texture->get_width()) + "x" + itos(texture->get_height()) + " " + format;
- } else if (texture->get_layered_type() == TextureLayered::LAYERED_TYPE_CUBEMAP_ARRAY) {
- text = itos(texture->get_width()) + "x" + itos(texture->get_height()) + " (x " + itos(texture->get_layers() / 6) + ")" + format;
+ if (p_texture_changed) {
+ materials[texture->get_layered_type()]->set_shader_parameter("tex", texture->get_rid());
}
-
- info->set_text(text);
}
void TextureLayeredEditor::_make_shaders() {
shaders[0].instantiate();
- shaders[0]->set_code(R"(
-// TextureLayeredEditor preview shader (2D array).
-
-shader_type canvas_item;
-
-uniform sampler2DArray tex;
-uniform float layer;
-
-void fragment() {
- COLOR = textureLod(tex, vec3(UV, layer), 0.0);
-}
-)");
+ shaders[0]->set_code(array_2d_shader);
shaders[1].instantiate();
- shaders[1]->set_code(R"(
-// TextureLayeredEditor preview shader (cubemap).
-
-shader_type canvas_item;
-
-uniform samplerCube tex;
-uniform vec3 normal;
-uniform mat3 rot;
-
-void fragment() {
- vec3 n = rot * normalize(vec3(normal.xy * (UV * 2.0 - 1.0), normal.z));
- COLOR = textureLod(tex, n, 0.0);
-}
-)");
+ shaders[1]->set_code(cubemap_shader);
shaders[2].instantiate();
- shaders[2]->set_code(R"(
-// TextureLayeredEditor preview shader (cubemap array).
-
-shader_type canvas_item;
-
-uniform samplerCubeArray tex;
-uniform vec3 normal;
-uniform mat3 rot;
-uniform float layer;
-
-void fragment() {
- vec3 n = rot * normalize(vec3(normal.xy * (UV * 2.0 - 1.0), normal.z));
- COLOR = textureLod(tex, vec4(n, layer), 0.0);
-}
-)");
+ shaders[2]->set_code(cubemap_array_shader);
for (int i = 0; i < 3; i++) {
materials[i].instantiate();
@@ -192,25 +268,20 @@ void TextureLayeredEditor::edit(Ref<TextureLayered> p_texture) {
}
texture->connect_changed(callable_mp(this, &TextureLayeredEditor::_texture_changed));
- queue_redraw();
texture_rect->set_material(materials[texture->get_layered_type()]);
+
setting = true;
- if (texture->get_layered_type() == TextureLayered::LAYERED_TYPE_2D_ARRAY) {
- layer->set_max(texture->get_layers() - 1);
- layer->set_value(0);
- layer->show();
- } else if (texture->get_layered_type() == TextureLayered::LAYERED_TYPE_CUBEMAP_ARRAY) {
- layer->set_max(texture->get_layers() / 6 - 1);
- layer->set_value(0);
- layer->show();
- } else {
- layer->hide();
- }
+ layer->set_value(0);
+ layer->show();
+ _update_gui();
+ setting = false;
+
x_rot = 0;
y_rot = 0;
- _update_material();
- setting = false;
- _texture_rect_update_area();
+
+ _update_material(true);
+ queue_redraw();
+
} else {
hide();
}
@@ -218,42 +289,48 @@ void TextureLayeredEditor::edit(Ref<TextureLayered> p_texture) {
TextureLayeredEditor::TextureLayeredEditor() {
set_texture_repeat(TextureRepeat::TEXTURE_REPEAT_ENABLED);
- set_custom_minimum_size(Size2(1, 150));
+ set_custom_minimum_size(Size2(0, 256.0) * EDSCALE);
texture_rect = memnew(Control);
texture_rect->set_mouse_filter(MOUSE_FILTER_IGNORE);
- add_child(texture_rect);
texture_rect->connect(SceneStringName(draw), callable_mp(this, &TextureLayeredEditor::_texture_rect_draw));
+ add_child(texture_rect);
+
layer = memnew(SpinBox);
layer->set_step(1);
layer->set_max(100);
- layer->set_h_grow_direction(GROW_DIRECTION_BEGIN);
+
layer->set_modulate(Color(1, 1, 1, 0.8));
- add_child(layer);
+ layer->set_h_grow_direction(GROW_DIRECTION_BEGIN);
layer->set_anchor(SIDE_RIGHT, 1);
layer->set_anchor(SIDE_LEFT, 1);
layer->connect(SceneStringName(value_changed), callable_mp(this, &TextureLayeredEditor::_layer_changed));
+ add_child(layer);
+
info = memnew(Label);
+ info->add_theme_color_override(SceneStringName(font_color), Color(1, 1, 1));
+ info->add_theme_color_override("font_shadow_color", Color(0, 0, 0));
+ info->add_theme_font_size_override(SceneStringName(font_size), 14 * EDSCALE);
+ info->add_theme_color_override("font_outline_color", Color(0, 0, 0));
+ info->add_theme_constant_override("outline_size", 8 * EDSCALE);
+
info->set_h_grow_direction(GROW_DIRECTION_BEGIN);
info->set_v_grow_direction(GROW_DIRECTION_BEGIN);
- info->add_theme_color_override(SceneStringName(font_color), Color(1, 1, 1, 1));
- info->add_theme_color_override("font_shadow_color", Color(0, 0, 0, 0.5));
- info->add_theme_constant_override("shadow_outline_size", 1);
- info->add_theme_constant_override("shadow_offset_x", 2);
- info->add_theme_constant_override("shadow_offset_y", 2);
- add_child(info);
+ info->set_h_size_flags(Control::SIZE_SHRINK_END);
+ info->set_v_size_flags(Control::SIZE_SHRINK_END);
info->set_anchor(SIDE_RIGHT, 1);
info->set_anchor(SIDE_LEFT, 1);
info->set_anchor(SIDE_BOTTOM, 1);
info->set_anchor(SIDE_TOP, 1);
+
+ add_child(info);
}
TextureLayeredEditor::~TextureLayeredEditor() {
}
-//
bool EditorInspectorPluginLayeredTexture::can_handle(Object *p_object) {
return Object::cast_to<TextureLayered>(p_object) != nullptr;
}
diff --git a/editor/plugins/texture_layered_editor_plugin.h b/editor/plugins/texture_layered_editor_plugin.h
index 83729f922e..900ba94c6d 100644
--- a/editor/plugins/texture_layered_editor_plugin.h
+++ b/editor/plugins/texture_layered_editor_plugin.h
@@ -54,24 +54,28 @@ class TextureLayeredEditor : public Control {
bool setting = false;
void _make_shaders();
- void _update_material();
+ void _update_material(bool p_texture_changed);
void _layer_changed(double) {
if (!setting) {
- _update_material();
+ _update_material(false);
}
}
+
void _texture_changed();
void _texture_rect_update_area();
void _texture_rect_draw();
+ void _update_gui();
+
protected:
void _notification(int p_what);
virtual void gui_input(const Ref<InputEvent> &p_event) override;
public:
void edit(Ref<TextureLayered> p_texture);
+
TextureLayeredEditor();
~TextureLayeredEditor();
};
diff --git a/editor/plugins/theme_editor_preview.cpp b/editor/plugins/theme_editor_preview.cpp
index 4d98b24ccc..2426cec521 100644
--- a/editor/plugins/theme_editor_preview.cpp
+++ b/editor/plugins/theme_editor_preview.cpp
@@ -205,7 +205,7 @@ void ThemeEditorPreview::_notification(int p_what) {
} break;
case NOTIFICATION_READY: {
- List<Ref<Theme>> preview_themes;
+ Vector<Ref<Theme>> preview_themes;
preview_themes.push_back(ThemeDB::get_singleton()->get_default_theme());
ThemeDB::get_singleton()->create_theme_context(preview_root, preview_themes);
} break;
diff --git a/editor/plugins/tiles/tile_atlas_view.cpp b/editor/plugins/tiles/tile_atlas_view.cpp
index 3942baed8a..b806d1e042 100644
--- a/editor/plugins/tiles/tile_atlas_view.cpp
+++ b/editor/plugins/tiles/tile_atlas_view.cpp
@@ -372,7 +372,7 @@ void TileAtlasView::_draw_base_tiles_shape_grid() {
for (int i = 0; i < tile_set_atlas_source->get_tiles_count(); i++) {
Vector2i tile_id = tile_set_atlas_source->get_tile_id(i);
Vector2 in_tile_base_offset = tile_set_atlas_source->get_tile_data(tile_id, 0)->get_texture_origin();
- if (tile_set_atlas_source->is_position_in_tile_texture_region(tile_id, 0, -tile_shape_size / 2) && tile_set_atlas_source->is_position_in_tile_texture_region(tile_id, 0, tile_shape_size / 2 - Vector2(1, 1))) {
+ if (tile_set_atlas_source->is_rect_in_tile_texture_region(tile_id, 0, Rect2(Vector2(-tile_shape_size) / 2, tile_shape_size))) {
for (int frame = 0; frame < tile_set_atlas_source->get_tile_animation_frames_count(tile_id); frame++) {
Color color = grid_color;
if (frame > 0) {
diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp
index f985bbc629..af52243c41 100644
--- a/editor/plugins/tiles/tile_data_editors.cpp
+++ b/editor/plugins/tiles/tile_data_editors.cpp
@@ -165,10 +165,14 @@ void GenericTilePolygonEditor::_base_control_draw() {
base_control->draw_set_transform_matrix(xform);
// Draw fill rect under texture region.
- Rect2 texture_rect(-background_region.size / 2, background_region.size);
+ Rect2 texture_rect(Vector2(), background_region.size);
if (tile_data) {
texture_rect.position -= tile_data->get_texture_origin();
+ if (tile_data->get_transpose()) {
+ texture_rect.size = Size2(texture_rect.size.y, texture_rect.size.x);
+ }
}
+ texture_rect.position -= texture_rect.size / 2; // Half-size offset must be applied after transposing.
base_control->draw_rect(texture_rect, Color(1, 1, 1, 0.3));
// Draw the background.
@@ -180,18 +184,14 @@ void GenericTilePolygonEditor::_base_control_draw() {
if (tile_data->get_flip_v()) {
region_size.y = -region_size.y;
}
- base_control->draw_texture_rect_region(background_atlas_source->get_texture(), Rect2(-background_region.size / 2 - tile_data->get_texture_origin(), region_size), background_region, tile_data->get_modulate(), tile_data->get_transpose());
+ // Destination rect position must account for transposing, size must not.
+ base_control->draw_texture_rect_region(background_atlas_source->get_texture(), Rect2(texture_rect.position, region_size), background_region, tile_data->get_modulate(), tile_data->get_transpose());
}
// Compute and draw the grid area.
Rect2 grid_area = Rect2(-base_tile_size / 2, base_tile_size);
- if (tile_data) {
- grid_area.expand_to(-background_region.get_size() / 2 - tile_data->get_texture_origin());
- grid_area.expand_to(background_region.get_size() / 2 - tile_data->get_texture_origin());
- } else {
- grid_area.expand_to(-background_region.get_size() / 2);
- grid_area.expand_to(background_region.get_size() / 2);
- }
+ grid_area.expand_to(texture_rect.position);
+ grid_area.expand_to(texture_rect.get_end());
base_control->draw_rect(grid_area, Color(1, 1, 1, 0.3), false);
// Draw grid.
@@ -523,6 +523,21 @@ void GenericTilePolygonEditor::_base_control_gui_input(Ref<InputEvent> p_event)
xform.set_origin(base_control->get_size() / 2 + panning);
xform.set_scale(Vector2(editor_zoom_widget->get_zoom(), editor_zoom_widget->get_zoom()));
+ Ref<InputEventPanGesture> pan_gesture = p_event;
+ if (pan_gesture.is_valid()) {
+ panning += pan_gesture->get_delta() * 8;
+ drag_last_pos = Vector2();
+ button_center_view->set_disabled(panning.is_zero_approx());
+ accept_event();
+ }
+
+ Ref<InputEventMagnifyGesture> magnify_gesture = p_event;
+ if (magnify_gesture.is_valid()) {
+ editor_zoom_widget->set_zoom(editor_zoom_widget->get_zoom() * magnify_gesture->get_factor());
+ _zoom_changed();
+ accept_event();
+ }
+
Ref<InputEventMouseMotion> mm = p_event;
if (mm.is_valid()) {
if (drag_type == DRAG_TYPE_DRAG_POINT) {
@@ -1385,10 +1400,8 @@ void TileDataTextureOriginEditor::draw_over_tile(CanvasItem *p_canvas_item, Tran
TileSetSource *source = *(tile_set->get_source(p_cell.source_id));
TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
- if (atlas_source->is_position_in_tile_texture_region(p_cell.get_atlas_coords(), p_cell.alternative_tile, -tile_set_tile_size / 2) && atlas_source->is_position_in_tile_texture_region(p_cell.get_atlas_coords(), p_cell.alternative_tile, tile_set_tile_size / 2 - Vector2(1, 1))) {
- Transform2D tile_xform;
- tile_xform.set_scale(tile_set_tile_size);
- tile_set->draw_tile_shape(p_canvas_item, p_transform * tile_xform, color);
+ if (atlas_source->is_rect_in_tile_texture_region(p_cell.get_atlas_coords(), p_cell.alternative_tile, Rect2(Vector2(-tile_set_tile_size) / 2, tile_set_tile_size))) {
+ tile_set->draw_tile_shape(p_canvas_item, p_transform.scaled_local(tile_set_tile_size), color);
}
if (atlas_source->is_position_in_tile_texture_region(p_cell.get_atlas_coords(), p_cell.alternative_tile, Vector2())) {
diff --git a/editor/plugins/tiles/tile_map_layer_editor.cpp b/editor/plugins/tiles/tile_map_layer_editor.cpp
index b76e673414..63a54372b5 100644
--- a/editor/plugins/tiles/tile_map_layer_editor.cpp
+++ b/editor/plugins/tiles/tile_map_layer_editor.cpp
@@ -2368,7 +2368,7 @@ TileMapLayerEditorTilesPlugin::TileMapLayerEditorTilesPlugin() {
tiles_bottom_panel->set_name(TTR("Tiles"));
missing_source_label = memnew(Label);
- missing_source_label->set_text(TTR("This TileMap's TileSet has no source configured. Go to the TileSet bottom panel to add one."));
+ missing_source_label->set_text(TTR("This TileMap's TileSet has no Tile Source configured. Go to the TileSet bottom panel to add one."));
missing_source_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
missing_source_label->set_v_size_flags(Control::SIZE_EXPAND_FILL);
missing_source_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
index 7e34a36a6e..224c4e434f 100644
--- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
+++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
@@ -2612,7 +2612,6 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
atlas_source_inspector->set_v_size_flags(SIZE_EXPAND_FILL);
atlas_source_inspector->set_show_categories(false, true);
atlas_source_inspector->set_use_doc_hints(true);
- atlas_source_inspector->add_inspector_plugin(memnew(TileSourceInspectorPlugin));
middle_vbox_container->add_child(atlas_source_inspector);
// -- Right side --
@@ -2740,9 +2739,8 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
add_child(confirm_auto_create_tiles);
// Inspector plugin.
- Ref<EditorInspectorPluginTileData> tile_data_inspector_plugin;
- tile_data_inspector_plugin.instantiate();
- EditorInspector::add_inspector_plugin(tile_data_inspector_plugin);
+ EditorInspector::add_inspector_plugin(memnew(EditorInspectorPluginTileData));
+ EditorInspector::add_inspector_plugin(memnew(TileSourceInspectorPlugin));
}
TileSetAtlasSourceEditor::~TileSetAtlasSourceEditor() {
diff --git a/editor/plugins/tiles/tile_set_editor.cpp b/editor/plugins/tiles/tile_set_editor.cpp
index 263e9cfa3b..7e5336ce06 100644
--- a/editor/plugins/tiles/tile_set_editor.cpp
+++ b/editor/plugins/tiles/tile_set_editor.cpp
@@ -818,7 +818,7 @@ TileSetEditor::TileSetEditor() {
tabs_bar = memnew(TabBar);
tabs_bar->set_tab_alignment(TabBar::ALIGNMENT_CENTER);
tabs_bar->set_clip_tabs(false);
- tabs_bar->add_tab(TTR("Tiles"));
+ tabs_bar->add_tab(TTR("Tile Sources"));
tabs_bar->add_tab(TTR("Patterns"));
tabs_bar->connect("tab_changed", callable_mp(this, &TileSetEditor::_tab_changed));
diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp
index 22ef779b8d..305407efdb 100644
--- a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp
+++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp
@@ -534,7 +534,6 @@ TileSetScenesCollectionSourceEditor::TileSetScenesCollectionSourceEditor() {
scenes_collection_source_inspector = memnew(EditorInspector);
scenes_collection_source_inspector->set_vertical_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED);
scenes_collection_source_inspector->set_use_doc_hints(true);
- scenes_collection_source_inspector->add_inspector_plugin(memnew(TileSourceInspectorPlugin));
middle_vbox_container->add_child(scenes_collection_source_inspector);
// Tile inspector.
@@ -581,6 +580,8 @@ TileSetScenesCollectionSourceEditor::TileSetScenesCollectionSourceEditor() {
scene_tile_delete_button->set_disabled(true);
scene_tile_delete_button->connect(SceneStringName(pressed), callable_mp(this, &TileSetScenesCollectionSourceEditor::_source_delete_pressed));
scenes_bottom_actions->add_child(scene_tile_delete_button);
+
+ EditorInspector::add_inspector_plugin(memnew(TileSourceInspectorPlugin));
}
TileSetScenesCollectionSourceEditor::~TileSetScenesCollectionSourceEditor() {
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index 351adc569c..0c541b6046 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -43,6 +43,7 @@
#include "editor/filesystem_dock.h"
#include "editor/inspector_dock.h"
#include "editor/plugins/curve_editor_plugin.h"
+#include "editor/plugins/material_editor_plugin.h"
#include "editor/plugins/shader_editor_plugin.h"
#include "editor/themes/editor_scale.h"
#include "scene/animation/tween.h"
@@ -50,12 +51,14 @@
#include "scene/gui/check_box.h"
#include "scene/gui/code_edit.h"
#include "scene/gui/color_picker.h"
+#include "scene/gui/flow_container.h"
#include "scene/gui/graph_edit.h"
#include "scene/gui/menu_button.h"
#include "scene/gui/option_button.h"
#include "scene/gui/popup.h"
#include "scene/gui/rich_text_label.h"
#include "scene/gui/separator.h"
+#include "scene/gui/split_container.h"
#include "scene/gui/tree.h"
#include "scene/gui/view_panner.h"
#include "scene/main/window.h"
@@ -115,8 +118,8 @@ void VSGraphNode::_draw_port(int p_slot_index, Point2i p_pos, bool p_left, const
icon_offset = -port_icon->get_size() * 0.5;
// Draw "shadow"/outline in the connection rim color.
- draw_texture_rect(port_icon, Rect2(p_pos + icon_offset - Size2(2, 2), port_icon->get_size() + Size2(4, 4)), false, p_rim_color);
- draw_texture(port_icon, p_pos + icon_offset, p_color);
+ draw_texture_rect(port_icon, Rect2(p_pos + (icon_offset - Size2(2, 2)) * EDSCALE, (port_icon->get_size() + Size2(4, 4)) * EDSCALE), false, p_rim_color);
+ draw_texture_rect(port_icon, Rect2(p_pos + icon_offset * EDSCALE, port_icon->get_size() * EDSCALE), false, p_color);
}
void VSGraphNode::draw_port(int p_slot_index, Point2i p_pos, bool p_left, const Color &p_color) {
@@ -154,7 +157,6 @@ VSRerouteNode::VSRerouteNode() {
title_lbl->hide();
const Size2 size = Size2(32, 32) * EDSCALE;
- print_line("VSRerouteNode size: " + size);
Control *slot_area = memnew(Control);
slot_area->set_custom_minimum_size(size);
@@ -256,7 +258,7 @@ void VisualShaderGraphPlugin::show_port_preview(VisualShader::Type p_type, int p
vbox->add_child(offset);
VisualShaderNodePortPreview *port_preview = memnew(VisualShaderNodePortPreview);
- port_preview->setup(visual_shader, visual_shader->get_shader_type(), p_node_id, p_port_id, p_is_valid);
+ port_preview->setup(visual_shader, editor->preview_material, visual_shader->get_shader_type(), p_node_id, p_port_id, p_is_valid);
port_preview->set_h_size_flags(Control::SIZE_SHRINK_CENTER);
vbox->add_child(port_preview);
link.preview_visible = true;
@@ -1096,14 +1098,14 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id, bool
default_value = vsnode->get_input_port_default_value(j);
}
- Button *button = memnew(Button);
- hb->add_child(button);
- register_default_input_button(p_id, j, button);
- button->connect(SceneStringName(pressed), callable_mp(editor, &VisualShaderEditor::_edit_port_default_input).bind(button, p_id, j));
+ Button *default_input_btn = memnew(Button);
+ hb->add_child(default_input_btn);
+ register_default_input_button(p_id, j, default_input_btn);
+ default_input_btn->connect(SceneStringName(pressed), callable_mp(editor, &VisualShaderEditor::_edit_port_default_input).bind(default_input_btn, p_id, j));
if (default_value.get_type() != Variant::NIL) { // only a label
set_input_port_default_value(p_type, p_id, j, default_value);
} else {
- button->hide();
+ default_input_btn->hide();
}
if (j == 0 && custom_editor) {
@@ -1144,7 +1146,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id, bool
Label *label = memnew(Label);
label->set_auto_translate_mode(Node::AUTO_TRANSLATE_MODE_DISABLED); // TODO: Implement proper translation switch.
label->set_text(name_left);
- label->add_theme_style_override(CoreStringName(normal), editor->get_theme_stylebox(SNAME("label_style"), SNAME("VShaderEditor"))); //more compact
+ label->add_theme_style_override(CoreStringName(normal), editor->get_theme_stylebox(SNAME("label_style"), SNAME("VShaderEditor")));
hb->add_child(label);
if (vsnode->is_input_port_default(j, mode) && !port_left_used) {
@@ -1509,23 +1511,25 @@ Vector2 VisualShaderEditor::selection_center;
List<VisualShaderEditor::CopyItem> VisualShaderEditor::copy_items_buffer;
List<VisualShader::Connection> VisualShaderEditor::copy_connections_buffer;
-void VisualShaderEditor::edit(VisualShader *p_visual_shader) {
+void VisualShaderEditor::edit_shader(const Ref<Shader> &p_shader) {
bool changed = false;
- if (p_visual_shader) {
+ VisualShader *visual_shader_ptr = Object::cast_to<VisualShader>(p_shader.ptr());
+ if (visual_shader_ptr) {
if (visual_shader.is_null()) {
changed = true;
} else {
- if (visual_shader.ptr() != p_visual_shader) {
+ if (visual_shader.ptr() != visual_shader_ptr) {
changed = true;
}
}
- visual_shader = Ref<VisualShader>(p_visual_shader);
+ visual_shader = p_shader;
graph_plugin->register_shader(visual_shader.ptr());
visual_shader->connect_changed(callable_mp(this, &VisualShaderEditor::_update_preview));
visual_shader->set_graph_offset(graph->get_scroll_offset() / EDSCALE);
_set_mode(visual_shader->get_mode());
+ preview_material->set_shader(visual_shader);
_update_nodes();
} else {
if (visual_shader.is_valid()) {
@@ -1546,6 +1550,19 @@ void VisualShaderEditor::edit(VisualShader *p_visual_shader) {
}
}
+void VisualShaderEditor::apply_shaders() {
+ // Stub. TODO: Implement apply_shaders in visual shaders for parity with text shaders.
+}
+
+bool VisualShaderEditor::is_unsaved() const {
+ // Stub. TODO: Implement is_unsaved in visual shaders for parity with text shaders.
+ return false;
+}
+
+void VisualShaderEditor::save_external_data(const String &p_str) {
+ ResourceSaver::save(visual_shader, visual_shader->get_path());
+}
+
void VisualShaderEditor::validate_script() {
if (visual_shader.is_valid()) {
_update_nodes();
@@ -1573,7 +1590,7 @@ void VisualShaderEditor::clear_custom_types() {
}
void VisualShaderEditor::add_custom_type(const String &p_name, const String &p_type, const Ref<Script> &p_script, const String &p_description, int p_return_icon_type, const String &p_category, bool p_highend) {
- ERR_FAIL_COND(!p_name.is_valid_identifier());
+ ERR_FAIL_COND(!p_name.is_valid_ascii_identifier());
ERR_FAIL_COND(p_type.is_empty() && !p_script.is_valid());
for (int i = 0; i < add_options.size(); i++) {
@@ -1936,6 +1953,96 @@ bool VisualShaderEditor::_is_available(int p_mode) {
return (p_mode == -1 || (p_mode & current_mode) != 0);
}
+bool VisualShaderEditor::_update_preview_parameter_tree() {
+ bool found = false;
+ bool use_filter = !param_filter_name.is_empty();
+
+ parameters->clear();
+ TreeItem *root = parameters->create_item();
+
+ for (const KeyValue<String, PropertyInfo> &prop : parameter_props) {
+ String param_name = prop.value.name;
+ if (use_filter && !param_name.containsn(param_filter_name)) {
+ continue;
+ }
+
+ TreeItem *item = parameters->create_item(root);
+ item->set_text(0, param_name);
+ item->set_meta("id", param_name);
+
+ if (param_name == selected_param_id) {
+ parameters->set_selected(item);
+ found = true;
+ }
+
+ if (prop.value.type == Variant::OBJECT) {
+ item->set_icon(0, get_editor_theme_icon(SNAME("ImageTexture")));
+ } else {
+ item->set_icon(0, get_editor_theme_icon(Variant::get_type_name(prop.value.type)));
+ }
+ }
+
+ return found;
+}
+
+void VisualShaderEditor::_clear_preview_param() {
+ selected_param_id = "";
+ current_prop = nullptr;
+
+ if (param_vbox2->get_child_count() > 0) {
+ param_vbox2->remove_child(param_vbox2->get_child(0));
+ }
+
+ param_vbox->hide();
+}
+
+void VisualShaderEditor::_update_preview_parameter_list() {
+ material_editor->edit(preview_material.ptr(), env);
+
+ List<PropertyInfo> properties;
+ RenderingServer::get_singleton()->get_shader_parameter_list(visual_shader->get_rid(), &properties);
+
+ HashSet<String> params_to_remove;
+ for (const KeyValue<String, PropertyInfo> &E : parameter_props) {
+ params_to_remove.insert(E.key);
+ }
+ parameter_props.clear();
+
+ for (const PropertyInfo &prop : properties) {
+ String param_name = prop.name;
+
+ if (visual_shader->_has_preview_shader_parameter(param_name)) {
+ preview_material->set_shader_parameter(param_name, visual_shader->_get_preview_shader_parameter(param_name));
+ } else {
+ preview_material->set_shader_parameter(param_name, RenderingServer::get_singleton()->shader_get_parameter_default(visual_shader->get_rid(), param_name));
+ }
+
+ parameter_props.insert(param_name, prop);
+ params_to_remove.erase(param_name);
+
+ if (param_name == selected_param_id) {
+ current_prop->update_property();
+ current_prop->update_editor_property_status();
+ current_prop->update_cache();
+ }
+ }
+
+ _update_preview_parameter_tree();
+
+ // Removes invalid parameters.
+ for (const String &param_name : params_to_remove) {
+ preview_material->set_shader_parameter(param_name, Variant());
+
+ if (visual_shader->_has_preview_shader_parameter(param_name)) {
+ visual_shader->_set_preview_shader_parameter(param_name, Variant());
+ }
+
+ if (param_name == selected_param_id) {
+ _clear_preview_param();
+ }
+ }
+}
+
void VisualShaderEditor::_update_nodes() {
clear_custom_types();
Dictionary added;
@@ -3560,6 +3667,7 @@ void VisualShaderEditor::_add_node(int p_idx, const Vector<Variant> &p_ops, cons
bool is_curve = (Object::cast_to<VisualShaderNodeCurveTexture>(vsnode.ptr()) != nullptr);
bool is_curve_xyz = (Object::cast_to<VisualShaderNodeCurveXYZTexture>(vsnode.ptr()) != nullptr);
bool is_parameter = (Object::cast_to<VisualShaderNodeParameter>(vsnode.ptr()) != nullptr);
+ bool is_mesh_emitter = (Object::cast_to<VisualShaderNodeParticleMeshEmitter>(vsnode.ptr()) != nullptr);
Point2 position = graph->get_scroll_offset();
@@ -3772,6 +3880,12 @@ void VisualShaderEditor::_add_node(int p_idx, const Vector<Variant> &p_ops, cons
if (is_texture2d_array) {
undo_redo->force_fixed_history();
undo_redo->add_do_method(vsnode.ptr(), "set_texture_array", ResourceLoader::load(p_resource_path));
+ return;
+ }
+
+ if (is_mesh_emitter) {
+ undo_redo->add_do_method(vsnode.ptr(), "set_mesh", ResourceLoader::load(p_resource_path));
+ return;
}
}
}
@@ -4859,6 +4973,74 @@ void VisualShaderEditor::_sbox_input(const Ref<InputEvent> &p_ie) {
}
}
+void VisualShaderEditor::_param_filter_changed(const String &p_text) {
+ param_filter_name = p_text;
+
+ if (!_update_preview_parameter_tree()) {
+ _clear_preview_param();
+ }
+}
+
+void VisualShaderEditor::_param_property_changed(const String &p_property, const Variant &p_value, const String &p_field, bool p_changing) {
+ if (p_changing) {
+ return;
+ }
+ String raw_prop_name = p_property.trim_prefix("shader_parameter/");
+
+ EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
+
+ undo_redo->create_action(vformat(TTR("Edit Preview Parameter: %s"), p_property));
+ undo_redo->add_do_method(visual_shader.ptr(), "_set_preview_shader_parameter", raw_prop_name, p_value);
+ undo_redo->add_undo_method(visual_shader.ptr(), "_set_preview_shader_parameter", raw_prop_name, preview_material->get(p_property));
+ undo_redo->add_do_method(this, "_update_current_param");
+ undo_redo->add_undo_method(this, "_update_current_param");
+ undo_redo->commit_action();
+}
+
+void VisualShaderEditor::_update_current_param() {
+ if (current_prop != nullptr) {
+ String name = current_prop->get_meta("id");
+ preview_material->set("shader_parameter/" + name, visual_shader->_get_preview_shader_parameter(name));
+
+ current_prop->update_property();
+ current_prop->update_editor_property_status();
+ current_prop->update_cache();
+ }
+}
+
+void VisualShaderEditor::_param_selected() {
+ _clear_preview_param();
+
+ TreeItem *item = parameters->get_selected();
+ selected_param_id = item->get_meta("id");
+
+ PropertyInfo pi = parameter_props.get(selected_param_id);
+ EditorProperty *prop = EditorInspector::instantiate_property_editor(preview_material.ptr(), pi.type, pi.name, pi.hint, pi.hint_string, pi.usage);
+ if (!prop) {
+ return;
+ }
+ prop->connect("property_changed", callable_mp(this, &VisualShaderEditor::_param_property_changed));
+ prop->set_h_size_flags(SIZE_EXPAND_FILL);
+ prop->set_object_and_property(preview_material.ptr(), "shader_parameter/" + pi.name);
+
+ prop->set_label(TTR("Value:"));
+ prop->update_property();
+ prop->update_editor_property_status();
+ prop->update_cache();
+
+ current_prop = prop;
+ current_prop->set_meta("id", selected_param_id);
+
+ param_vbox2->add_child(prop);
+ param_vbox->show();
+}
+
+void VisualShaderEditor::_param_unselected() {
+ parameters->deselect_all();
+
+ _clear_preview_param();
+}
+
void VisualShaderEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_POSTINITIALIZE: {
@@ -4902,9 +5084,11 @@ void VisualShaderEditor::_notification(int p_what) {
case NOTIFICATION_THEME_CHANGED: {
highend_label->set_modulate(get_theme_color(SNAME("highend_color"), EditorStringName(Editor)));
+ param_filter->set_right_icon(Control::get_editor_theme_icon(SNAME("Search")));
node_filter->set_right_icon(Control::get_editor_theme_icon(SNAME("Search")));
- preview_shader->set_icon(Control::get_editor_theme_icon(SNAME("Shader")));
+ code_preview_button->set_icon(Control::get_editor_theme_icon(SNAME("Shader")));
+ shader_preview_button->set_icon(Control::get_editor_theme_icon(SNAME("SubViewport")));
{
Color background_color = EDITOR_GET("text_editor/theme/highlighting/background_color");
@@ -4957,7 +5141,7 @@ void VisualShaderEditor::_notification(int p_what) {
tools->set_icon(get_editor_theme_icon(SNAME("Tools")));
- if (p_what == NOTIFICATION_THEME_CHANGED && is_visible_in_tree()) {
+ if (is_visible_in_tree()) {
_update_graph();
}
} break;
@@ -5614,7 +5798,7 @@ void VisualShaderEditor::_varying_create() {
}
void VisualShaderEditor::_varying_name_changed(const String &p_name) {
- if (!p_name.is_valid_identifier()) {
+ if (!p_name.is_valid_ascii_identifier()) {
varying_error_label->show();
varying_error_label->set_text(TTR("Invalid name for varying."));
add_varying_dialog->get_ok_button()->set_disabled(true);
@@ -5885,6 +6069,11 @@ void VisualShaderEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE);
saved_node_pos_dirty = true;
_add_node(cubemap_node_option_idx, {}, arr[i], i);
+ } else if (type == "Mesh" && visual_shader->get_mode() == Shader::MODE_PARTICLES &&
+ (visual_shader->get_shader_type() == VisualShader::TYPE_START || visual_shader->get_shader_type() == VisualShader::TYPE_START_CUSTOM)) {
+ saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE);
+ saved_node_pos_dirty = true;
+ _add_node(mesh_emitter_option_idx, {}, arr[i], i);
}
}
}
@@ -5894,14 +6083,14 @@ void VisualShaderEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
}
void VisualShaderEditor::_show_preview_text() {
- preview_showed = !preview_showed;
- if (preview_showed) {
- if (preview_first) {
- preview_window->set_size(Size2(400 * EDSCALE, 600 * EDSCALE));
- preview_window->popup_centered();
- preview_first = false;
+ code_preview_showed = !code_preview_showed;
+ if (code_preview_showed) {
+ if (code_preview_first) {
+ code_preview_window->set_size(Size2(400 * EDSCALE, 600 * EDSCALE));
+ code_preview_window->popup_centered();
+ code_preview_first = false;
} else {
- preview_window->popup();
+ code_preview_window->popup();
}
_preview_size_changed();
@@ -5910,18 +6099,18 @@ void VisualShaderEditor::_show_preview_text() {
pending_update_preview = false;
}
} else {
- preview_window->hide();
+ code_preview_window->hide();
}
}
void VisualShaderEditor::_preview_close_requested() {
- preview_showed = false;
- preview_window->hide();
- preview_shader->set_pressed(false);
+ code_preview_showed = false;
+ code_preview_window->hide();
+ code_preview_button->set_pressed(false);
}
void VisualShaderEditor::_preview_size_changed() {
- preview_vbox->set_custom_minimum_size(preview_window->get_size());
+ code_preview_vbox->set_custom_minimum_size(code_preview_window->get_size());
}
static ShaderLanguage::DataType _visual_shader_editor_get_global_shader_uniform_type(const StringName &p_variable) {
@@ -5930,7 +6119,7 @@ static ShaderLanguage::DataType _visual_shader_editor_get_global_shader_uniform_
}
void VisualShaderEditor::_update_preview() {
- if (!preview_showed) {
+ if (!code_preview_showed) {
pending_update_preview = true;
return;
}
@@ -6022,14 +6211,25 @@ void VisualShaderEditor::_get_next_nodes_recursively(VisualShader::Type p_type,
void VisualShaderEditor::_visibility_changed() {
if (!is_visible()) {
- if (preview_window->is_visible()) {
- preview_shader->set_pressed(false);
- preview_window->hide();
- preview_showed = false;
+ if (code_preview_window->is_visible()) {
+ code_preview_button->set_pressed(false);
+ code_preview_window->hide();
+ code_preview_showed = false;
}
}
}
+void VisualShaderEditor::_show_shader_preview() {
+ shader_preview_showed = !shader_preview_showed;
+ if (shader_preview_showed) {
+ shader_preview_vbox->show();
+ } else {
+ shader_preview_vbox->hide();
+
+ _param_unselected();
+ }
+}
+
void VisualShaderEditor::_bind_methods() {
ClassDB::bind_method("_update_nodes", &VisualShaderEditor::_update_nodes);
ClassDB::bind_method("_update_graph", &VisualShaderEditor::_update_graph);
@@ -6044,6 +6244,7 @@ void VisualShaderEditor::_bind_methods() {
ClassDB::bind_method("_update_constant", &VisualShaderEditor::_update_constant);
ClassDB::bind_method("_update_parameter", &VisualShaderEditor::_update_parameter);
ClassDB::bind_method("_update_next_previews", &VisualShaderEditor::_update_next_previews);
+ ClassDB::bind_method("_update_current_param", &VisualShaderEditor::_update_current_param);
}
VisualShaderEditor::VisualShaderEditor() {
@@ -6052,15 +6253,19 @@ VisualShaderEditor::VisualShaderEditor() {
FileSystemDock::get_singleton()->get_script_create_dialog()->connect("script_created", callable_mp(this, &VisualShaderEditor::_script_created));
FileSystemDock::get_singleton()->connect("resource_removed", callable_mp(this, &VisualShaderEditor::_resource_removed));
+ HSplitContainer *main_box = memnew(HSplitContainer);
+ main_box->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
+ add_child(main_box);
+
graph = memnew(GraphEdit);
- graph->get_menu_hbox()->set_h_size_flags(SIZE_EXPAND_FILL);
graph->set_v_size_flags(SIZE_EXPAND_FILL);
graph->set_h_size_flags(SIZE_EXPAND_FILL);
+ graph->set_custom_minimum_size(Size2(200 * EDSCALE, 0));
graph->set_grid_pattern(GraphEdit::GridPattern::GRID_PATTERN_DOTS);
int grid_pattern = EDITOR_GET("editors/visual_editors/grid_pattern");
graph->set_grid_pattern((GraphEdit::GridPattern)grid_pattern);
graph->set_show_zoom_label(true);
- add_child(graph);
+ main_box->add_child(graph);
SET_DRAG_FORWARDING_GCD(graph, VisualShaderEditor);
float graph_minimap_opacity = EDITOR_GET("editors/visual_editors/minimap_opacity");
graph->set_minimap_opacity(graph_minimap_opacity);
@@ -6148,9 +6353,30 @@ VisualShaderEditor::VisualShaderEditor() {
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShaderNode::PORT_TYPE_TRANSFORM);
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SAMPLER, VisualShaderNode::PORT_TYPE_SAMPLER);
+ PanelContainer *toolbar_panel = static_cast<PanelContainer *>(graph->get_menu_hbox()->get_parent());
+ toolbar_panel->set_anchors_and_offsets_preset(Control::PRESET_TOP_WIDE, PRESET_MODE_MINSIZE, 10);
+ toolbar_panel->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
+
+ HFlowContainer *toolbar = memnew(HFlowContainer);
+ {
+ LocalVector<Node *> nodes;
+ for (int i = 0; i < graph->get_menu_hbox()->get_child_count(); i++) {
+ Node *child = graph->get_menu_hbox()->get_child(i);
+ nodes.push_back(child);
+ }
+
+ for (Node *node : nodes) {
+ graph->get_menu_hbox()->remove_child(node);
+ toolbar->add_child(node);
+ }
+
+ graph->get_menu_hbox()->hide();
+ toolbar_panel->add_child(toolbar);
+ }
+
VSeparator *vs = memnew(VSeparator);
- graph->get_menu_hbox()->add_child(vs);
- graph->get_menu_hbox()->move_child(vs, 0);
+ toolbar->add_child(vs);
+ toolbar->move_child(vs, 0);
custom_mode_box = memnew(CheckBox);
custom_mode_box->set_text(TTR("Custom"));
@@ -6184,22 +6410,22 @@ VisualShaderEditor::VisualShaderEditor() {
edit_type = edit_type_standard;
- graph->get_menu_hbox()->add_child(custom_mode_box);
- graph->get_menu_hbox()->move_child(custom_mode_box, 0);
- graph->get_menu_hbox()->add_child(edit_type_standard);
- graph->get_menu_hbox()->move_child(edit_type_standard, 0);
- graph->get_menu_hbox()->add_child(edit_type_particles);
- graph->get_menu_hbox()->move_child(edit_type_particles, 0);
- graph->get_menu_hbox()->add_child(edit_type_sky);
- graph->get_menu_hbox()->move_child(edit_type_sky, 0);
- graph->get_menu_hbox()->add_child(edit_type_fog);
- graph->get_menu_hbox()->move_child(edit_type_fog, 0);
+ toolbar->add_child(custom_mode_box);
+ toolbar->move_child(custom_mode_box, 0);
+ toolbar->add_child(edit_type_standard);
+ toolbar->move_child(edit_type_standard, 0);
+ toolbar->add_child(edit_type_particles);
+ toolbar->move_child(edit_type_particles, 0);
+ toolbar->add_child(edit_type_sky);
+ toolbar->move_child(edit_type_sky, 0);
+ toolbar->add_child(edit_type_fog);
+ toolbar->move_child(edit_type_fog, 0);
add_node = memnew(Button);
add_node->set_flat(true);
add_node->set_text(TTR("Add Node..."));
- graph->get_menu_hbox()->add_child(add_node);
- graph->get_menu_hbox()->move_child(add_node, 0);
+ toolbar->add_child(add_node);
+ toolbar->move_child(add_node, 0);
add_node->connect(SceneStringName(pressed), callable_mp(this, &VisualShaderEditor::_show_members_dialog).bind(false, VisualShaderNode::PORT_TYPE_MAX, VisualShaderNode::PORT_TYPE_MAX));
graph->connect("graph_elements_linked_to_frame_request", callable_mp(this, &VisualShaderEditor::_nodes_linked_to_frame_request));
@@ -6208,46 +6434,54 @@ VisualShaderEditor::VisualShaderEditor() {
varying_button = memnew(MenuButton);
varying_button->set_text(TTR("Manage Varyings"));
varying_button->set_switch_on_hover(true);
- graph->get_menu_hbox()->add_child(varying_button);
+ toolbar->add_child(varying_button);
PopupMenu *varying_menu = varying_button->get_popup();
varying_menu->add_item(TTR("Add Varying"), int(VaryingMenuOptions::ADD));
varying_menu->add_item(TTR("Remove Varying"), int(VaryingMenuOptions::REMOVE));
varying_menu->connect(SceneStringName(id_pressed), callable_mp(this, &VisualShaderEditor::_varying_menu_id_pressed));
- preview_shader = memnew(Button);
- preview_shader->set_theme_type_variation("FlatButton");
- preview_shader->set_toggle_mode(true);
- preview_shader->set_tooltip_text(TTR("Show generated shader code."));
- graph->get_menu_hbox()->add_child(preview_shader);
- preview_shader->connect(SceneStringName(pressed), callable_mp(this, &VisualShaderEditor::_show_preview_text));
+ code_preview_button = memnew(Button);
+ code_preview_button->set_theme_type_variation("FlatButton");
+ code_preview_button->set_toggle_mode(true);
+ code_preview_button->set_tooltip_text(TTR("Show generated shader code."));
+ toolbar->add_child(code_preview_button);
+ code_preview_button->connect(SceneStringName(pressed), callable_mp(this, &VisualShaderEditor::_show_preview_text));
+
+ shader_preview_button = memnew(Button);
+ shader_preview_button->set_theme_type_variation("FlatButton");
+ shader_preview_button->set_toggle_mode(true);
+ shader_preview_button->set_tooltip_text(TTR("Toggle shader preview."));
+ shader_preview_button->set_pressed(true);
+ toolbar->add_child(shader_preview_button);
+ shader_preview_button->connect(SceneStringName(pressed), callable_mp(this, &VisualShaderEditor::_show_shader_preview));
///////////////////////////////////////
- // PREVIEW WINDOW
+ // CODE PREVIEW
///////////////////////////////////////
- preview_window = memnew(Window);
- preview_window->set_title(TTR("Generated Shader Code"));
- preview_window->set_visible(preview_showed);
- preview_window->set_exclusive(true);
- preview_window->connect("close_requested", callable_mp(this, &VisualShaderEditor::_preview_close_requested));
- preview_window->connect("size_changed", callable_mp(this, &VisualShaderEditor::_preview_size_changed));
- add_child(preview_window);
+ code_preview_window = memnew(Window);
+ code_preview_window->set_title(TTR("Generated Shader Code"));
+ code_preview_window->set_visible(code_preview_showed);
+ code_preview_window->set_exclusive(true);
+ code_preview_window->connect("close_requested", callable_mp(this, &VisualShaderEditor::_preview_close_requested));
+ code_preview_window->connect("size_changed", callable_mp(this, &VisualShaderEditor::_preview_size_changed));
+ add_child(code_preview_window);
- preview_vbox = memnew(VBoxContainer);
- preview_window->add_child(preview_vbox);
- preview_vbox->add_theme_constant_override("separation", 0);
+ code_preview_vbox = memnew(VBoxContainer);
+ code_preview_window->add_child(code_preview_vbox);
+ code_preview_vbox->add_theme_constant_override("separation", 0);
preview_text = memnew(CodeEdit);
syntax_highlighter.instantiate();
- preview_vbox->add_child(preview_text);
+ code_preview_vbox->add_child(preview_text);
preview_text->set_v_size_flags(Control::SIZE_EXPAND_FILL);
preview_text->set_syntax_highlighter(syntax_highlighter);
preview_text->set_draw_line_numbers(true);
preview_text->set_editable(false);
error_panel = memnew(PanelContainer);
- preview_vbox->add_child(error_panel);
+ code_preview_vbox->add_child(error_panel);
error_panel->set_visible(false);
error_label = memnew(Label);
@@ -6279,6 +6513,70 @@ VisualShaderEditor::VisualShaderEditor() {
connection_popup_menu->connect(SceneStringName(id_pressed), callable_mp(this, &VisualShaderEditor::_connection_menu_id_pressed));
///////////////////////////////////////
+ // SHADER PREVIEW
+ ///////////////////////////////////////
+
+ shader_preview_vbox = memnew(VBoxContainer);
+ shader_preview_vbox->set_custom_minimum_size(Size2(200 * EDSCALE, 0));
+ main_box->add_child(shader_preview_vbox);
+
+ VSplitContainer *preview_split = memnew(VSplitContainer);
+ preview_split->set_v_size_flags(SIZE_EXPAND_FILL);
+ shader_preview_vbox->add_child(preview_split);
+
+ // Initialize material editor.
+ {
+ env.instantiate();
+ Ref<Sky> sky = memnew(Sky());
+ env->set_sky(sky);
+ env->set_background(Environment::BG_COLOR);
+ env->set_ambient_source(Environment::AMBIENT_SOURCE_SKY);
+ env->set_reflection_source(Environment::REFLECTION_SOURCE_SKY);
+
+ preview_material.instantiate();
+ preview_material->connect(CoreStringName(property_list_changed), callable_mp(this, &VisualShaderEditor::_update_preview_parameter_list));
+
+ material_editor = memnew(MaterialEditor);
+ preview_split->add_child(material_editor);
+ }
+
+ VBoxContainer *params_vbox = memnew(VBoxContainer);
+ preview_split->add_child(params_vbox);
+
+ param_filter = memnew(LineEdit);
+ param_filter->connect(SceneStringName(text_changed), callable_mp(this, &VisualShaderEditor::_param_filter_changed));
+ param_filter->set_h_size_flags(SIZE_EXPAND_FILL);
+ param_filter->set_placeholder(TTR("Filter Parameters"));
+ params_vbox->add_child(param_filter);
+
+ ScrollContainer *sc = memnew(ScrollContainer);
+ sc->set_v_size_flags(SIZE_EXPAND_FILL);
+ params_vbox->add_child(sc);
+
+ parameters = memnew(Tree);
+ parameters->set_hide_root(true);
+ parameters->set_allow_reselect(true);
+ parameters->set_hide_folding(false);
+ parameters->set_h_size_flags(SIZE_EXPAND_FILL);
+ parameters->set_v_size_flags(SIZE_EXPAND_FILL);
+ parameters->connect(SceneStringName(item_selected), callable_mp(this, &VisualShaderEditor::_param_selected));
+ parameters->connect("nothing_selected", callable_mp(this, &VisualShaderEditor::_param_unselected));
+ sc->add_child(parameters);
+
+ param_vbox = memnew(VBoxContainer);
+ param_vbox->set_v_size_flags(SIZE_EXPAND_FILL);
+ param_vbox->hide();
+ params_vbox->add_child(param_vbox);
+
+ ScrollContainer *sc2 = memnew(ScrollContainer);
+ sc2->set_v_size_flags(SIZE_EXPAND_FILL);
+ param_vbox->add_child(sc2);
+
+ param_vbox2 = memnew(VBoxContainer);
+ param_vbox2->set_h_size_flags(SIZE_EXPAND_FILL);
+ sc2->add_child(param_vbox2);
+
+ ///////////////////////////////////////
// SHADER NODES TREE
///////////////////////////////////////
@@ -6521,6 +6819,7 @@ VisualShaderEditor::VisualShaderEditor() {
// NODE3D-FOR-ALL
+ add_options.push_back(AddOption("ClipSpaceFar", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "clip_space_far", "CLIP_SPACE_FAR"), { "clip_space_far" }, VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Exposure", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "exposure", "EXPOSURE"), { "exposure" }, VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("InvProjectionMatrix", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "inv_projection_matrix", "INV_PROJECTION_MATRIX"), { "inv_projection_matrix" }, VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("InvViewMatrix", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "inv_view_matrix", "INV_VIEW_MATRIX"), { "inv_view_matrix" }, VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::MODE_SPATIAL));
@@ -6579,14 +6878,20 @@ VisualShaderEditor::VisualShaderEditor() {
// NODE3D INPUTS
add_options.push_back(AddOption("Binormal", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "binormal", "BINORMAL"), { "binormal" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("CameraDirectionWorld", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_direction_world", "CAMERA_DIRECTION_WORLD"), { "camera_direction_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("CameraPositionWorld", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_position_world", "CAMERA_POSITION_WORLD"), { "camera_position_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("CameraVisibleLayers", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_visible_layers", "CAMERA_VISIBLE_LAYERS"), { "camera_visible_layers" }, VisualShaderNode::PORT_TYPE_SCALAR_UINT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Color", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "color", "COLOR"), { "color" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Custom0", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "custom0", "CUSTOM0"), { "custom0" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Custom1", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "custom1", "CUSTOM1"), { "custom1" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Custom2", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "custom2", "CUSTOM2"), { "custom2" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Custom3", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "custom3", "CUSTOM3"), { "custom3" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
- add_options.push_back(AddOption("InstanceId", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_id", "INSTANCE_ID"), { "instance_id" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("EyeOffset", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "eye_offset", "EYE_OFFSET"), { "eye_offset" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("InstanceCustom", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_custom", "INSTANCE_CUSTOM"), { "instance_custom" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("InstanceId", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_id", "INSTANCE_ID"), { "instance_id" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("ModelViewMatrix", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "modelview_matrix", "MODELVIEW_MATRIX"), { "modelview_matrix" }, VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("NodePositionView", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "node_position_view", "NODE_POSITION_VIEW"), { "node_position_view" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("NodePositionWorld", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "node_position_world", "NODE_POSITION_WORLD"), { "node_position_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("PointSize", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "point_size", "POINT_SIZE"), { "point_size" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Tangent", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_mode, "tangent", "TANGENT"), { "tangent" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Vertex", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "vertex", "VERTEX"), { "vertex" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
@@ -6594,17 +6899,17 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("ViewIndex", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_index", "VIEW_INDEX"), { "view_index" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("ViewMonoLeft", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_mono_left", "VIEW_MONO_LEFT"), { "view_mono_left" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("ViewRight", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_right", "VIEW_RIGHT"), { "view_right" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
- add_options.push_back(AddOption("EyeOffset", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "eye_offset", "EYE_OFFSET"), { "eye_offset" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
- add_options.push_back(AddOption("NodePositionWorld", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "node_position_world", "NODE_POSITION_WORLD"), { "node_position_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
- add_options.push_back(AddOption("CameraPositionWorld", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_position_world", "CAMERA_POSITION_WORLD"), { "camera_position_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
- add_options.push_back(AddOption("CameraDirectionWorld", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_direction_world", "CAMERA_DIRECTION_WORLD"), { "camera_direction_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
- add_options.push_back(AddOption("CameraVisibleLayers", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_visible_layers", "CAMERA_VISIBLE_LAYERS"), { "camera_visible_layers" }, VisualShaderNode::PORT_TYPE_SCALAR_UINT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
- add_options.push_back(AddOption("NodePositionView", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "node_position_view", "NODE_POSITION_VIEW"), { "node_position_view" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Binormal", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "binormal", "BINORMAL"), { "binormal" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("CameraDirectionWorld", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_direction_world", "CAMERA_DIRECTION_WORLD"), { "camera_direction_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("CameraPositionWorld", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_position_world", "CAMERA_POSITION_WORLD"), { "camera_position_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("CameraVisibleLayers", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_visible_layers", "CAMERA_VISIBLE_LAYERS"), { "camera_visible_layers" }, VisualShaderNode::PORT_TYPE_SCALAR_UINT, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Color", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "color", "COLOR"), { "color" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("EyeOffset", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "eye_offset", "EYE_OFFSET"), { "eye_offset" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("FragCoord", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord", "FRAGCOORD"), { "fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("FrontFacing", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "front_facing", "FRONT_FACING"), { "front_facing" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("NodePositionView", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "node_position_view", "NODE_POSITION_VIEW"), { "node_position_view" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("NodePositionWorld", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "node_position_world", "NODE_POSITION_WORLD"), { "node_position_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("PointCoord", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "point_coord", "POINT_COORD"), { "point_coord" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("ScreenUV", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_uv", "SCREEN_UV"), { "screen_uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Tangent", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "tangent", "TANGENT"), { "tangent" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
@@ -6613,12 +6918,6 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("ViewIndex", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_index", "VIEW_INDEX"), { "view_index" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("ViewMonoLeft", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_mono_left", "VIEW_MONO_LEFT"), { "view_mono_left" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("ViewRight", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_right", "VIEW_RIGHT"), { "view_right" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
- add_options.push_back(AddOption("EyeOffset", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "eye_offset", "EYE_OFFSET"), { "eye_offset" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
- add_options.push_back(AddOption("NodePositionWorld", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "node_position_world", "NODE_POSITION_WORLD"), { "node_position_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
- add_options.push_back(AddOption("CameraPositionWorld", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_position_world", "CAMERA_POSITION_WORLD"), { "camera_position_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
- add_options.push_back(AddOption("CameraDirectionWorld", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_direction_world", "CAMERA_DIRECTION_WORLD"), { "camera_direction_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
- add_options.push_back(AddOption("CameraVisibleLayers", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_visible_layers", "CAMERA_VISIBLE_LAYERS"), { "camera_visible_layers" }, VisualShaderNode::PORT_TYPE_SCALAR_UINT, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
- add_options.push_back(AddOption("NodePositionView", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "node_position_view", "NODE_POSITION_VIEW"), { "node_position_view" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Albedo", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "albedo", "ALBEDO"), { "albedo" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Attenuation", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "attenuation", "ATTENUATION"), { "attenuation" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
@@ -6661,10 +6960,10 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("FragCoord", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord", "FRAGCOORD"), { "fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("Light", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light", "LIGHT"), { "light" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("LightColor", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_color", "LIGHT_COLOR"), { "light_color" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
- add_options.push_back(AddOption("LightPosition", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_position", "LIGHT_POSITION"), { "light_position" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("LightDirection", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_direction", "LIGHT_DIRECTION"), { "light_direction" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
- add_options.push_back(AddOption("LightIsDirectional", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_is_directional", "LIGHT_IS_DIRECTIONAL"), { "light_is_directional" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("LightEnergy", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_energy", "LIGHT_ENERGY"), { "light_energy" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("LightIsDirectional", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_is_directional", "LIGHT_IS_DIRECTIONAL"), { "light_is_directional" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("LightPosition", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_position", "LIGHT_POSITION"), { "light_position" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("LightVertex", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "light_vertex", "LIGHT_VERTEX"), { "light_vertex" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("Normal", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "normal", "NORMAL"), { "normal" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("PointCoord", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "point_coord", "POINT_COORD"), { "point_coord" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
@@ -6679,6 +6978,7 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("AtHalfResPass", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "at_half_res_pass", "AT_HALF_RES_PASS"), { "at_half_res_pass" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_SKY, Shader::MODE_SKY));
add_options.push_back(AddOption("AtQuarterResPass", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "at_quarter_res_pass", "AT_QUARTER_RES_PASS"), { "at_quarter_res_pass" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_SKY, Shader::MODE_SKY));
add_options.push_back(AddOption("EyeDir", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "eyedir", "EYEDIR"), { "eyedir" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
+ add_options.push_back(AddOption("FragCoord", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "fragcoord", "FRAGCOORD"), { "fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
add_options.push_back(AddOption("HalfResColor", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "half_res_color", "HALF_RES_COLOR"), { "half_res_color" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
add_options.push_back(AddOption("Light0Color", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "light0_color", "LIGHT0_COLOR"), { "light0_color" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
add_options.push_back(AddOption("Light0Direction", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "light0_direction", "LIGHT0_DIRECTION"), { "light0_direction" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
@@ -6700,19 +7000,17 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("QuarterResColor", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "quarter_res_color", "QUARTER_RES_COLOR"), { "quarter_res_color" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
add_options.push_back(AddOption("Radiance", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "radiance", "RADIANCE"), { "radiance" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_SKY, Shader::MODE_SKY));
add_options.push_back(AddOption("ScreenUV", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "screen_uv", "SCREEN_UV"), { "screen_uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
- add_options.push_back(AddOption("FragCoord", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "fragcoord", "FRAGCOORD"), { "fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
-
add_options.push_back(AddOption("SkyCoords", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "sky_coords", "SKY_COORDS"), { "sky_coords" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
add_options.push_back(AddOption("Time", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "time", "TIME"), { "time" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_SKY, Shader::MODE_SKY));
// FOG INPUTS
- add_options.push_back(AddOption("WorldPosition", "Input/Fog", "VisualShaderNodeInput", vformat(input_param_for_fog_shader_mode, "world_position", "WORLD_POSITION"), { "world_position" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FOG, Shader::MODE_FOG));
add_options.push_back(AddOption("ObjectPosition", "Input/Fog", "VisualShaderNodeInput", vformat(input_param_for_fog_shader_mode, "object_position", "OBJECT_POSITION"), { "object_position" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FOG, Shader::MODE_FOG));
- add_options.push_back(AddOption("UVW", "Input/Fog", "VisualShaderNodeInput", vformat(input_param_for_fog_shader_mode, "uvw", "UVW"), { "uvw" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FOG, Shader::MODE_FOG));
- add_options.push_back(AddOption("Size", "Input/Fog", "VisualShaderNodeInput", vformat(input_param_for_fog_shader_mode, "size", "SIZE"), { "size" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FOG, Shader::MODE_FOG));
add_options.push_back(AddOption("SDF", "Input/Fog", "VisualShaderNodeInput", vformat(input_param_for_fog_shader_mode, "sdf", "SDF"), { "sdf" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FOG, Shader::MODE_FOG));
+ add_options.push_back(AddOption("Size", "Input/Fog", "VisualShaderNodeInput", vformat(input_param_for_fog_shader_mode, "size", "SIZE"), { "size" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FOG, Shader::MODE_FOG));
add_options.push_back(AddOption("Time", "Input/Fog", "VisualShaderNodeInput", vformat(input_param_for_fog_shader_mode, "time", "TIME"), { "time" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FOG, Shader::MODE_FOG));
+ add_options.push_back(AddOption("UVW", "Input/Fog", "VisualShaderNodeInput", vformat(input_param_for_fog_shader_mode, "uvw", "UVW"), { "uvw" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FOG, Shader::MODE_FOG));
+ add_options.push_back(AddOption("WorldPosition", "Input/Fog", "VisualShaderNodeInput", vformat(input_param_for_fog_shader_mode, "world_position", "WORLD_POSITION"), { "world_position" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FOG, Shader::MODE_FOG));
// PARTICLES INPUTS
@@ -6727,7 +7025,10 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("MultiplyByAxisAngle (*)", "Particles/Transform", "VisualShaderNodeParticleMultiplyByAxisAngle", TTR("A node for help to multiply a position input vector by rotation using specific axis. Intended to work with emitters."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_EMIT | TYPE_FLAGS_PROCESS | TYPE_FLAGS_COLLIDE, Shader::MODE_PARTICLES));
add_options.push_back(AddOption("BoxEmitter", "Particles/Emitters", "VisualShaderNodeParticleBoxEmitter", "", {}, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
+
+ mesh_emitter_option_idx = add_options.size();
add_options.push_back(AddOption("MeshEmitter", "Particles/Emitters", "VisualShaderNodeParticleMeshEmitter", "", {}, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
+
add_options.push_back(AddOption("RingEmitter", "Particles/Emitters", "VisualShaderNodeParticleRingEmitter", "", {}, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
add_options.push_back(AddOption("SphereEmitter", "Particles/Emitters", "VisualShaderNodeParticleSphereEmitter", "", {}, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
@@ -7562,7 +7863,7 @@ void EditorPropertyVisualShaderMode::_option_selected(int p_which) {
if (!shader_editor) {
return;
}
- VisualShaderEditor *editor = shader_editor->get_visual_shader_editor(visual_shader);
+ VisualShaderEditor *editor = Object::cast_to<VisualShaderEditor>(shader_editor->get_shader_editor(visual_shader));
if (!editor) {
return;
}
@@ -7653,9 +7954,6 @@ void EditorPropertyVisualShaderMode::set_option_button_clip(bool p_enable) {
options->set_clip_text(p_enable);
}
-void EditorPropertyVisualShaderMode::_bind_methods() {
-}
-
EditorPropertyVisualShaderMode::EditorPropertyVisualShaderMode() {
options = memnew(OptionButton);
options->set_clip_text(true);
@@ -7696,7 +7994,7 @@ void VisualShaderNodePortPreview::_shader_changed() {
preview_shader->set_code(shader_code);
for (int i = 0; i < default_textures.size(); i++) {
int j = 0;
- for (List<Ref<Texture2D>>::ConstIterator itr = default_textures[i].params.begin(); itr != default_textures[i].params.end(); ++itr, ++j) {
+ for (List<Ref<Texture>>::ConstIterator itr = default_textures[i].params.begin(); itr != default_textures[i].params.end(); ++itr, ++j) {
preview_shader->set_default_texture_parameter(default_textures[i].name, *itr, j);
}
}
@@ -7705,36 +8003,21 @@ void VisualShaderNodePortPreview::_shader_changed() {
mat.instantiate();
mat->set_shader(preview_shader);
- //find if a material is also being edited and copy parameters to this one
-
- for (int i = EditorNode::get_singleton()->get_editor_selection_history()->get_path_size() - 1; i >= 0; i--) {
- Object *object = ObjectDB::get_instance(EditorNode::get_singleton()->get_editor_selection_history()->get_path_object(i));
- ShaderMaterial *src_mat;
- if (!object) {
- continue;
- }
- if (object->has_method("get_material_override")) { // trying getting material from MeshInstance
- src_mat = Object::cast_to<ShaderMaterial>(object->call("get_material_override"));
- } else if (object->has_method("get_material")) { // from CanvasItem/Node2D
- src_mat = Object::cast_to<ShaderMaterial>(object->call("get_material"));
- } else {
- src_mat = Object::cast_to<ShaderMaterial>(object);
- }
- if (src_mat && src_mat->get_shader().is_valid()) {
- List<PropertyInfo> params;
- src_mat->get_shader()->get_shader_uniform_list(&params);
- for (const PropertyInfo &E : params) {
- mat->set_shader_parameter(E.name, src_mat->get_shader_parameter(E.name));
- }
+ if (preview_mat.is_valid() && preview_mat->get_shader().is_valid()) {
+ List<PropertyInfo> params;
+ preview_mat->get_shader()->get_shader_uniform_list(&params);
+ for (const PropertyInfo &E : params) {
+ mat->set_shader_parameter(E.name, preview_mat->get_shader_parameter(E.name));
}
}
set_material(mat);
}
-void VisualShaderNodePortPreview::setup(const Ref<VisualShader> &p_shader, VisualShader::Type p_type, int p_node, int p_port, bool p_is_valid) {
+void VisualShaderNodePortPreview::setup(const Ref<VisualShader> &p_shader, Ref<ShaderMaterial> &p_preview_material, VisualShader::Type p_type, int p_node, int p_port, bool p_is_valid) {
shader = p_shader;
shader->connect_changed(callable_mp(this, &VisualShaderNodePortPreview::_shader_changed), CONNECT_DEFERRED);
+ preview_mat = p_preview_material;
type = p_type;
port = p_port;
node = p_node;
@@ -7787,9 +8070,6 @@ void VisualShaderNodePortPreview::_notification(int p_what) {
}
}
-void VisualShaderNodePortPreview::_bind_methods() {
-}
-
//////////////////////////////////
String VisualShaderConversionPlugin::converts_to() const {
diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h
index a9826fd617..69b2f30c40 100644
--- a/editor/plugins/visual_shader_editor_plugin.h
+++ b/editor/plugins/visual_shader_editor_plugin.h
@@ -34,6 +34,7 @@
#include "editor/editor_properties.h"
#include "editor/plugins/editor_plugin.h"
#include "editor/plugins/editor_resource_conversion_plugin.h"
+#include "editor/plugins/shader/shader_editor.h"
#include "scene/gui/graph_edit.h"
#include "scene/resources/syntax_highlighter.h"
#include "scene/resources/visual_shader.h"
@@ -49,6 +50,7 @@ class RichTextLabel;
class Tree;
class VisualShaderEditor;
+class MaterialEditor;
class VisualShaderNodePlugin : public RefCounted {
GDCLASS(VisualShaderNodePlugin, RefCounted);
@@ -195,8 +197,8 @@ public:
VisualShaderEditedProperty() {}
};
-class VisualShaderEditor : public VBoxContainer {
- GDCLASS(VisualShaderEditor, VBoxContainer);
+class VisualShaderEditor : public ShaderEditor {
+ GDCLASS(VisualShaderEditor, ShaderEditor);
friend class VisualShaderGraphPlugin;
PopupPanel *property_editor_popup = nullptr;
@@ -205,11 +207,18 @@ class VisualShaderEditor : public VBoxContainer {
int editing_port = -1;
Ref<VisualShaderEditedProperty> edited_property_holder;
+ MaterialEditor *material_editor = nullptr;
Ref<VisualShader> visual_shader;
+ Ref<ShaderMaterial> preview_material;
+ Ref<Environment> env;
+ String param_filter_name;
+ EditorProperty *current_prop = nullptr;
+ VBoxContainer *shader_preview_vbox = nullptr;
GraphEdit *graph = nullptr;
Button *add_node = nullptr;
MenuButton *varying_button = nullptr;
- Button *preview_shader = nullptr;
+ Button *code_preview_button = nullptr;
+ Button *shader_preview_button = nullptr;
OptionButton *edit_type = nullptr;
OptionButton *edit_type_standard = nullptr;
@@ -221,8 +230,8 @@ class VisualShaderEditor : public VBoxContainer {
bool pending_update_preview = false;
bool shader_error = false;
- Window *preview_window = nullptr;
- VBoxContainer *preview_vbox = nullptr;
+ Window *code_preview_window = nullptr;
+ VBoxContainer *code_preview_vbox = nullptr;
CodeEdit *preview_text = nullptr;
Ref<CodeHighlighter> syntax_highlighter = nullptr;
PanelContainer *error_panel = nullptr;
@@ -260,8 +269,17 @@ class VisualShaderEditor : public VBoxContainer {
PopupPanel *frame_tint_color_pick_popup = nullptr;
ColorPicker *frame_tint_color_picker = nullptr;
- bool preview_first = true;
- bool preview_showed = false;
+ bool code_preview_first = true;
+ bool code_preview_showed = false;
+
+ bool shader_preview_showed = true;
+
+ LineEdit *param_filter = nullptr;
+ String selected_param_id;
+ Tree *parameters = nullptr;
+ HashMap<String, PropertyInfo> parameter_props;
+ VBoxContainer *param_vbox = nullptr;
+ VBoxContainer *param_vbox2 = nullptr;
enum ShaderModeFlags {
MODE_FLAGS_SPATIAL_CANVASITEM = 1,
@@ -348,6 +366,10 @@ class VisualShaderEditor : public VBoxContainer {
void _show_add_varying_dialog();
void _show_remove_varying_dialog();
+ void _clear_preview_param();
+ void _update_preview_parameter_list();
+ bool _update_preview_parameter_tree();
+
void _update_nodes();
void _update_graph();
@@ -392,6 +414,7 @@ class VisualShaderEditor : public VBoxContainer {
int custom_node_option_idx;
int curve_node_option_idx;
int curve_xyz_node_option_idx;
+ int mesh_emitter_option_idx;
List<String> keyword_list;
List<VisualShaderNodeParameterRef> uniform_refs;
@@ -413,6 +436,8 @@ class VisualShaderEditor : public VBoxContainer {
void _get_next_nodes_recursively(VisualShader::Type p_type, int p_node_id, LocalVector<int> &r_nodes) const;
String _get_description(int p_idx);
+ void _show_shader_preview();
+
Vector<int> nodes_link_to_frame_buffer; // Contains the nodes that are requested to be linked to a frame. This is used to perform one Undo/Redo operation for dragging nodes.
int frame_node_id_to_link_to = -1;
@@ -591,11 +616,23 @@ class VisualShaderEditor : public VBoxContainer {
void _resource_removed(const Ref<Resource> &p_resource);
void _resources_removed();
+ void _param_property_changed(const String &p_property, const Variant &p_value, const String &p_field = "", bool p_changing = false);
+ void _update_current_param();
+ void _param_filter_changed(const String &p_text);
+ void _param_selected();
+ void _param_unselected();
+
protected:
void _notification(int p_what);
static void _bind_methods();
public:
+ virtual void edit_shader(const Ref<Shader> &p_shader) override;
+ virtual void apply_shaders() override;
+ virtual bool is_unsaved() const override;
+ virtual void save_external_data(const String &p_str = "") override;
+ virtual void validate_script() override;
+
void add_plugin(const Ref<VisualShaderNodePlugin> &p_plugin);
void remove_plugin(const Ref<VisualShaderNodePlugin> &p_plugin);
@@ -609,11 +646,8 @@ public:
virtual Size2 get_minimum_size() const override;
- void edit(VisualShader *p_visual_shader);
Ref<VisualShader> get_visual_shader() const { return visual_shader; }
- void validate_script();
-
VisualShaderEditor();
};
@@ -630,9 +664,6 @@ class EditorPropertyVisualShaderMode : public EditorProperty {
void _option_selected(int p_which);
-protected:
- static void _bind_methods();
-
public:
void setup(const Vector<String> &p_options);
virtual void update_property() override;
@@ -651,6 +682,7 @@ public:
class VisualShaderNodePortPreview : public Control {
GDCLASS(VisualShaderNodePortPreview, Control);
Ref<VisualShader> shader;
+ Ref<ShaderMaterial> preview_mat;
VisualShader::Type type = VisualShader::Type::TYPE_MAX;
int node = 0;
int port = 0;
@@ -658,11 +690,10 @@ class VisualShaderNodePortPreview : public Control {
void _shader_changed(); //must regen
protected:
void _notification(int p_what);
- static void _bind_methods();
public:
virtual Size2 get_minimum_size() const override;
- void setup(const Ref<VisualShader> &p_shader, VisualShader::Type p_type, int p_node, int p_port, bool p_is_valid);
+ void setup(const Ref<VisualShader> &p_shader, Ref<ShaderMaterial> &p_preview_material, VisualShader::Type p_type, int p_node, int p_port, bool p_is_valid);
};
class VisualShaderConversionPlugin : public EditorResourceConversionPlugin {
diff --git a/editor/plugins/voxel_gi_editor_plugin.cpp b/editor/plugins/voxel_gi_editor_plugin.cpp
index e7b2435567..3e835d5cb6 100644
--- a/editor/plugins/voxel_gi_editor_plugin.cpp
+++ b/editor/plugins/voxel_gi_editor_plugin.cpp
@@ -177,9 +177,6 @@ void VoxelGIEditorPlugin::_voxel_gi_save_path_and_bake(const String &p_path) {
}
}
-void VoxelGIEditorPlugin::_bind_methods() {
-}
-
VoxelGIEditorPlugin::VoxelGIEditorPlugin() {
bake_hb = memnew(HBoxContainer);
bake_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
diff --git a/editor/plugins/voxel_gi_editor_plugin.h b/editor/plugins/voxel_gi_editor_plugin.h
index 58ef22ddc6..d09822dda6 100644
--- a/editor/plugins/voxel_gi_editor_plugin.h
+++ b/editor/plugins/voxel_gi_editor_plugin.h
@@ -58,7 +58,6 @@ class VoxelGIEditorPlugin : public EditorPlugin {
void _voxel_gi_save_path_and_bake(const String &p_path);
protected:
- static void _bind_methods();
void _notification(int p_what);
public: