summaryrefslogtreecommitdiff
path: root/editor/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'editor/plugins')
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp6
-rw-r--r--editor/plugins/input_event_editor_plugin.cpp122
-rw-r--r--editor/plugins/input_event_editor_plugin.h79
-rw-r--r--editor/plugins/mesh_instance_3d_editor_plugin.cpp19
-rw-r--r--editor/plugins/mesh_instance_3d_editor_plugin.h1
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp82
-rw-r--r--editor/plugins/node_3d_editor_plugin.h4
-rw-r--r--editor/plugins/resource_preloader_editor_plugin.cpp6
-rw-r--r--editor/plugins/theme_editor_plugin.cpp3
-rw-r--r--editor/plugins/version_control_editor_plugin.cpp1
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp140
-rw-r--r--editor/plugins/visual_shader_editor_plugin.h6
-rw-r--r--editor/plugins/voxel_gi_editor_plugin.cpp5
13 files changed, 416 insertions, 58 deletions
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index 48d7cfdee2..2b92943f7e 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -569,8 +569,10 @@ void AnimationPlayerEditor::_animation_blend() {
blend_editor.dialog->popup_centered(Size2(400, 400) * EDSCALE);
blend_editor.tree->set_hide_root(true);
- blend_editor.tree->set_column_custom_minimum_width(0, 10);
- blend_editor.tree->set_column_custom_minimum_width(1, 3);
+ blend_editor.tree->set_column_expand_ratio(0, 10);
+ blend_editor.tree->set_column_clip_content(0, true);
+ blend_editor.tree->set_column_expand_ratio(1, 3);
+ blend_editor.tree->set_column_clip_content(1, true);
List<StringName> anims;
player->get_animation_list(&anims);
diff --git a/editor/plugins/input_event_editor_plugin.cpp b/editor/plugins/input_event_editor_plugin.cpp
new file mode 100644
index 0000000000..f1aa10844b
--- /dev/null
+++ b/editor/plugins/input_event_editor_plugin.cpp
@@ -0,0 +1,122 @@
+/*************************************************************************/
+/* input_event_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#include "input_event_editor_plugin.h"
+
+void InputEventConfigContainer::_bind_methods() {
+}
+
+void InputEventConfigContainer::_configure_pressed() {
+ config_dialog->popup_and_configure(input_event);
+}
+
+void InputEventConfigContainer::_event_changed() {
+ input_event_text->set_text(input_event->as_text());
+}
+
+void InputEventConfigContainer::_config_dialog_confirmed() {
+ Ref<InputEvent> ie = config_dialog->get_event();
+ input_event->copy_from(ie);
+ _event_changed();
+}
+
+Size2 InputEventConfigContainer::get_minimum_size() const {
+ // Don't bother with a minimum x size for the control - we don't want the inspector
+ // to jump in size if a long text is placed in the label (e.g. Joypad Axis description)
+ return Size2(0, HBoxContainer::get_minimum_size().y);
+}
+
+void InputEventConfigContainer::set_event(const Ref<InputEvent> &p_event) {
+ Ref<InputEventKey> k = p_event;
+ Ref<InputEventMouseButton> m = p_event;
+ Ref<InputEventJoypadButton> jb = p_event;
+ Ref<InputEventJoypadMotion> jm = p_event;
+
+ if (k.is_valid()) {
+ config_dialog->set_allowed_input_types(InputEventConfigurationDialog::InputType::INPUT_KEY);
+ } else if (m.is_valid()) {
+ config_dialog->set_allowed_input_types(InputEventConfigurationDialog::InputType::INPUT_MOUSE_BUTTON);
+ } else if (jb.is_valid()) {
+ config_dialog->set_allowed_input_types(InputEventConfigurationDialog::InputType::INPUT_JOY_BUTTON);
+ } else if (jm.is_valid()) {
+ config_dialog->set_allowed_input_types(InputEventConfigurationDialog::InputType::INPUT_JOY_MOTION);
+ }
+
+ input_event = p_event;
+ _event_changed();
+ input_event->connect("changed", callable_mp(this, &InputEventConfigContainer::_event_changed));
+}
+
+InputEventConfigContainer::InputEventConfigContainer() {
+ MarginContainer *mc = memnew(MarginContainer);
+ mc->add_theme_constant_override("margin_left", 10);
+ mc->add_theme_constant_override("margin_right", 10);
+ mc->add_theme_constant_override("margin_top", 10);
+ mc->add_theme_constant_override("margin_bottom", 10);
+ add_child(mc);
+
+ HBoxContainer *hb = memnew(HBoxContainer);
+ mc->add_child(hb);
+
+ open_config_button = memnew(Button);
+ open_config_button->set_text("Configure");
+ open_config_button->connect("pressed", callable_mp(this, &InputEventConfigContainer::_configure_pressed));
+ hb->add_child(open_config_button);
+
+ input_event_text = memnew(Label);
+ hb->add_child(input_event_text);
+
+ config_dialog = memnew(InputEventConfigurationDialog);
+ config_dialog->connect("confirmed", callable_mp(this, &InputEventConfigContainer::_config_dialog_confirmed));
+ add_child(config_dialog);
+}
+
+bool EditorInspectorPluginInputEvent::can_handle(Object *p_object) {
+ Ref<InputEventKey> k = Ref<InputEventKey>(p_object);
+ Ref<InputEventMouseButton> m = Ref<InputEventMouseButton>(p_object);
+ Ref<InputEventJoypadButton> jb = Ref<InputEventJoypadButton>(p_object);
+ Ref<InputEventJoypadMotion> jm = Ref<InputEventJoypadMotion>(p_object);
+
+ return k.is_valid() || m.is_valid() || jb.is_valid() || jm.is_valid();
+}
+
+void EditorInspectorPluginInputEvent::parse_begin(Object *p_object) {
+ Ref<InputEvent> ie = Ref<InputEvent>(p_object);
+
+ InputEventConfigContainer *picker_controls = memnew(InputEventConfigContainer);
+ picker_controls->set_event(ie);
+ add_custom_control(picker_controls);
+}
+
+InputEventEditorPlugin::InputEventEditorPlugin(EditorNode *p_node) {
+ Ref<EditorInspectorPluginInputEvent> plugin;
+ plugin.instantiate();
+ add_inspector_plugin(plugin);
+}
diff --git a/editor/plugins/input_event_editor_plugin.h b/editor/plugins/input_event_editor_plugin.h
new file mode 100644
index 0000000000..bc8293c9e5
--- /dev/null
+++ b/editor/plugins/input_event_editor_plugin.h
@@ -0,0 +1,79 @@
+/*************************************************************************/
+/* input_event_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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 INPUT_EVENT_EDITOR_PLUGIN_H
+#define INPUT_EVENT_EDITOR_PLUGIN_H
+
+#include "editor/action_map_editor.h"
+#include "editor/editor_inspector.h"
+#include "editor/editor_node.h"
+
+class InputEventConfigContainer : public HBoxContainer {
+ GDCLASS(InputEventConfigContainer, HBoxContainer);
+
+ Label *input_event_text;
+ Button *open_config_button;
+
+ Ref<InputEvent> input_event;
+ InputEventConfigurationDialog *config_dialog;
+
+ void _config_dialog_confirmed();
+ void _configure_pressed();
+
+ void _event_changed();
+
+protected:
+ static void _bind_methods();
+
+public:
+ virtual Size2 get_minimum_size() const override;
+ void set_event(const Ref<InputEvent> &p_event);
+
+ InputEventConfigContainer();
+};
+
+class EditorInspectorPluginInputEvent : public EditorInspectorPlugin {
+ GDCLASS(EditorInspectorPluginInputEvent, EditorInspectorPlugin);
+
+public:
+ virtual bool can_handle(Object *p_object) override;
+ virtual void parse_begin(Object *p_object) override;
+};
+
+class InputEventEditorPlugin : public EditorPlugin {
+ GDCLASS(InputEventEditorPlugin, EditorPlugin);
+
+public:
+ virtual String get_name() const override { return "InputEvent"; }
+
+ InputEventEditorPlugin(EditorNode *p_node);
+};
+
+#endif // INPUT_EVENT_EDITOR_PLUGIN_H
diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.cpp b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
index 0d2b2ea2f5..7434accc1a 100644
--- a/editor/plugins/mesh_instance_3d_editor_plugin.cpp
+++ b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
@@ -153,14 +153,18 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
ur->add_undo_method(node->get_parent(), "remove_child", cshape);
ur->commit_action();
} break;
- case MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE: {
+
+ case MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE:
+ case MENU_OPTION_CREATE_SIMPLIFIED_CONVEX_COLLISION_SHAPE: {
if (node == get_tree()->get_edited_scene_root()) {
err_dialog->set_text(TTR("Can't create a single convex collision shape for the scene root."));
err_dialog->popup_centered();
return;
}
- Ref<Shape3D> shape = mesh->create_convex_shape();
+ bool simplify = (p_option == MENU_OPTION_CREATE_SIMPLIFIED_CONVEX_COLLISION_SHAPE);
+
+ Ref<Shape3D> shape = mesh->create_convex_shape(true, simplify);
if (shape.is_null()) {
err_dialog->set_text(TTR("Couldn't create a single convex collision shape."));
@@ -169,7 +173,11 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
}
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Create Single Convex Shape"));
+ if (simplify) {
+ ur->create_action(TTR("Create Simplified Convex Shape"));
+ } else {
+ ur->create_action(TTR("Create Single Convex Shape"));
+ }
CollisionShape3D *cshape = memnew(CollisionShape3D);
cshape->set_shape(shape);
@@ -186,6 +194,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
ur->commit_action();
} break;
+
case MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES: {
if (node == get_tree()->get_edited_scene_root()) {
err_dialog->set_text(TTR("Can't create multiple convex collision shapes for the scene root."));
@@ -441,8 +450,10 @@ MeshInstance3DEditor::MeshInstance3DEditor() {
options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a polygon-based collision shape.\nThis is the most accurate (but slowest) option for collision detection."));
options->get_popup()->add_item(TTR("Create Single Convex Collision Sibling"), MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE);
options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a single convex collision shape.\nThis is the fastest (but least accurate) option for collision detection."));
+ options->get_popup()->add_item(TTR("Create Simplified Convex Collision Sibling"), MENU_OPTION_CREATE_SIMPLIFIED_CONVEX_COLLISION_SHAPE);
+ options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a simplified convex collision shape.\nThis is similar to single collision shape, but can result in a simpler geometry in some cases, at the cost of accuracy."));
options->get_popup()->add_item(TTR("Create Multiple Convex Collision Siblings"), MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES);
- options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a polygon-based collision shape.\nThis is a performance middle-ground between the two above options."));
+ options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a polygon-based collision shape.\nThis is a performance middle-ground between a single convex collision and a polygon-based collision."));
options->get_popup()->add_separator();
options->get_popup()->add_item(TTR("Create Navigation Mesh"), MENU_OPTION_CREATE_NAVMESH);
options->get_popup()->add_separator();
diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.h b/editor/plugins/mesh_instance_3d_editor_plugin.h
index 69f494de7f..98b667c978 100644
--- a/editor/plugins/mesh_instance_3d_editor_plugin.h
+++ b/editor/plugins/mesh_instance_3d_editor_plugin.h
@@ -43,6 +43,7 @@ class MeshInstance3DEditor : public Control {
MENU_OPTION_CREATE_STATIC_TRIMESH_BODY,
MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE,
MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE,
+ MENU_OPTION_CREATE_SIMPLIFIED_CONVEX_COLLISION_SHAPE,
MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES,
MENU_OPTION_CREATE_NAVMESH,
MENU_OPTION_CREATE_OUTLINE_MESH,
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 5a4d79cdc8..72a63539b3 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -467,22 +467,31 @@ void Node3DEditorViewport::_select_clicked(bool p_append, bool p_single, bool p_
}
void Node3DEditorViewport::_select(Node *p_node, bool p_append, bool p_single) {
- if (!p_append) {
- editor_selection->clear();
- }
-
- if (editor_selection->is_selected(p_node)) {
- //erase
- editor_selection->remove_node(p_node);
+ // Add or remove a single node from the selection
+ if (p_append && p_single) {
+ if (editor_selection->is_selected(p_node)) {
+ // Already in the selection, remove it from the selected nodes
+ editor_selection->remove_node(p_node);
+ } else {
+ // Add the item to the selection
+ editor_selection->add_node(p_node);
+ }
+ } else if (p_append && !p_single) {
+ // Add the item to the selection
+ editor_selection->add_node(p_node);
} else {
+ // No append; single select
+ editor_selection->clear();
editor_selection->add_node(p_node);
- }
-
- if (p_single) {
+ // Reselect
if (Engine::get_singleton()->is_editor_hint()) {
editor->call("edit_node", p_node);
}
}
+
+ if (editor_selection->get_selected_node_list().size() == 1) {
+ editor->push_item(editor_selection->get_selected_node_list()[0]);
+ }
}
ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, bool &r_includes_current, int *r_gizmo_handle, bool p_alt_select) {
@@ -1967,6 +1976,13 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
return;
}
+ if (EditorSettings::get_singleton()->get("editors/3d/navigation/emulate_numpad")) {
+ const uint32_t code = k->get_keycode();
+ if (code >= KEY_0 && code <= KEY_9) {
+ k->set_keycode(code - KEY_0 + KEY_KP_0);
+ }
+ }
+
if (ED_IS_SHORTCUT("spatial_editor/snap", p_event)) {
if (_edit.mode != TRANSFORM_NONE) {
_edit.snap = !_edit.snap;
@@ -2504,15 +2520,15 @@ void Node3DEditorViewport::_notification(int p_what) {
}
if (show_info) {
+ const String viewport_size = vformat(String::utf8("%d × %d"), viewport->get_size().x, viewport->get_size().y);
String text;
text += vformat(TTR("X: %s\n"), rtos(current_camera->get_position().x).pad_decimals(1));
text += vformat(TTR("Y: %s\n"), rtos(current_camera->get_position().y).pad_decimals(1));
text += vformat(TTR("Z: %s\n"), rtos(current_camera->get_position().z).pad_decimals(1));
text += "\n";
text += vformat(
- TTR("Size: %dx%d (%.1fMP)\n"),
- viewport->get_size().x,
- viewport->get_size().y,
+ TTR("Size: %s (%.1fMP)\n"),
+ viewport_size,
viewport->get_size().x * viewport->get_size().y * 0.000001);
text += "\n";
@@ -3250,14 +3266,12 @@ void Node3DEditorViewport::_toggle_camera_preview(bool p_activate) {
if (!preview) {
preview_camera->hide();
}
- view_menu->set_disabled(false);
surface->update();
} else {
previewing = preview;
previewing->connect("tree_exiting", callable_mp(this, &Node3DEditorViewport::_preview_exited_scene));
RS::get_singleton()->viewport_attach_camera(viewport->get_viewport_rid(), preview->get_camera()); //replace
- view_menu->set_disabled(true);
surface->update();
}
}
@@ -3504,7 +3518,6 @@ void Node3DEditorViewport::set_state(const Dictionary &p_state) {
previewing = Object::cast_to<Camera3D>(pv);
previewing->connect("tree_exiting", callable_mp(this, &Node3DEditorViewport::_preview_exited_scene));
RS::get_singleton()->viewport_attach_camera(viewport->get_viewport_rid(), previewing->get_camera()); //replace
- view_menu->set_disabled(true);
surface->update();
preview_camera->set_pressed(true);
preview_camera->show();
@@ -6214,31 +6227,47 @@ void Node3DEditor::_sun_environ_settings_pressed() {
sun_environ_popup->popup();
}
-void Node3DEditor::_add_sun_to_scene() {
+void Node3DEditor::_add_sun_to_scene(bool p_already_added_environment) {
sun_environ_popup->hide();
+ if (!p_already_added_environment && world_env_count == 0 && Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
+ // Prevent infinite feedback loop between the sun and environment methods.
+ _add_environment_to_scene(true);
+ }
+
Node *base = get_tree()->get_edited_scene_root();
if (!base) {
- EditorNode::get_singleton()->show_warning(TTR("A root node is needed for this operation"));
- return;
+ // Create a root node so we can add child nodes to it.
+ EditorNode::get_singleton()->get_scene_tree_dock()->add_root_node(memnew(Node3D));
+ base = get_tree()->get_edited_scene_root();
}
ERR_FAIL_COND(!base);
Node *new_sun = preview_sun->duplicate();
undo_redo->create_action("Add Preview Sun to Scene");
undo_redo->add_do_method(base, "add_child", new_sun);
+ // Move to the beginning of the scene tree since more "global" nodes
+ // generally look better when placed at the top.
+ undo_redo->add_do_method(base, "move_child", new_sun, 0);
undo_redo->add_do_method(new_sun, "set_owner", base);
undo_redo->add_undo_method(base, "remove_child", new_sun);
undo_redo->add_do_reference(new_sun);
undo_redo->commit_action();
}
-void Node3DEditor::_add_environment_to_scene() {
+
+void Node3DEditor::_add_environment_to_scene(bool p_already_added_sun) {
sun_environ_popup->hide();
+ if (!p_already_added_sun && directional_light_count == 0 && Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
+ // Prevent infinite feedback loop between the sun and environment methods.
+ _add_sun_to_scene(true);
+ }
+
Node *base = get_tree()->get_edited_scene_root();
if (!base) {
- EditorNode::get_singleton()->show_warning(TTR("A root node is needed for this operation"));
- return;
+ // Create a root node so we can add child nodes to it.
+ EditorNode::get_singleton()->get_scene_tree_dock()->add_root_node(memnew(Node3D));
+ base = get_tree()->get_edited_scene_root();
}
ERR_FAIL_COND(!base);
@@ -6247,6 +6276,9 @@ void Node3DEditor::_add_environment_to_scene() {
undo_redo->create_action("Add Preview Environment to Scene");
undo_redo->add_do_method(base, "add_child", new_env);
+ // Move to the beginning of the scene tree since more "global" nodes
+ // generally look better when placed at the top.
+ undo_redo->add_do_method(base, "move_child", new_env, 0);
undo_redo->add_do_method(new_env, "set_owner", base);
undo_redo->add_undo_method(base, "remove_child", new_env);
undo_redo->add_do_reference(new_env);
@@ -7174,7 +7206,8 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) {
sun_add_to_scene = memnew(Button);
sun_add_to_scene->set_text(TTR("Add Sun to Scene"));
- sun_add_to_scene->connect("pressed", callable_mp(this, &Node3DEditor::_add_sun_to_scene));
+ sun_add_to_scene->set_tooltip(TTR("Adds a DirectionalLight3D node matching the preview sun settings to the current scene.\nHold Shift while clicking to also add the preview environment to the current scene."));
+ sun_add_to_scene->connect("pressed", callable_mp(this, &Node3DEditor::_add_sun_to_scene), varray(false));
sun_vb->add_spacer();
sun_vb->add_child(sun_add_to_scene);
@@ -7238,7 +7271,8 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) {
environ_add_to_scene = memnew(Button);
environ_add_to_scene->set_text(TTR("Add Environment to Scene"));
- environ_add_to_scene->connect("pressed", callable_mp(this, &Node3DEditor::_add_environment_to_scene));
+ environ_add_to_scene->set_tooltip(TTR("Adds a WorldEnvironment node matching the preview environment settings to the current scene.\nHold Shift while clicking to also add the preview sun to the current scene."));
+ environ_add_to_scene->connect("pressed", callable_mp(this, &Node3DEditor::_add_environment_to_scene), varray(false));
environ_vb->add_spacer();
environ_vb->add_child(environ_add_to_scene);
diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h
index ac0b2e1859..a195a0eee0 100644
--- a/editor/plugins/node_3d_editor_plugin.h
+++ b/editor/plugins/node_3d_editor_plugin.h
@@ -805,8 +805,8 @@ private:
void _preview_settings_changed();
void _sun_environ_settings_pressed();
- void _add_sun_to_scene();
- void _add_environment_to_scene();
+ void _add_sun_to_scene(bool p_already_added_environment = false);
+ void _add_environment_to_scene(bool p_already_added_sun = false);
protected:
void _notification(int p_what);
diff --git a/editor/plugins/resource_preloader_editor_plugin.cpp b/editor/plugins/resource_preloader_editor_plugin.cpp
index a7c11f8521..488aa8c861 100644
--- a/editor/plugins/resource_preloader_editor_plugin.cpp
+++ b/editor/plugins/resource_preloader_editor_plugin.cpp
@@ -367,8 +367,10 @@ ResourcePreloaderEditor::ResourcePreloaderEditor() {
tree = memnew(Tree);
tree->connect("button_pressed", callable_mp(this, &ResourcePreloaderEditor::_cell_button_pressed));
tree->set_columns(2);
- tree->set_column_custom_minimum_width(0, 2);
- tree->set_column_custom_minimum_width(1, 3);
+ tree->set_column_expand_ratio(0, 2);
+ tree->set_column_clip_content(0, true);
+ tree->set_column_expand_ratio(1, 3);
+ tree->set_column_clip_content(1, true);
tree->set_column_expand(0, true);
tree->set_column_expand(1, true);
tree->set_v_size_flags(SIZE_EXPAND_FILL);
diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp
index 99d7267eac..be1aeb309f 100644
--- a/editor/plugins/theme_editor_plugin.cpp
+++ b/editor/plugins/theme_editor_plugin.cpp
@@ -930,11 +930,14 @@ ThemeItemImportTree::ThemeItemImportTree() {
import_items_tree->set_column_title(IMPORT_ITEM, TTR("Import"));
import_items_tree->set_column_title(IMPORT_ITEM_DATA, TTR("With Data"));
import_items_tree->set_column_expand(0, true);
+ import_items_tree->set_column_clip_content(0, true);
import_items_tree->set_column_expand(IMPORT_ITEM, false);
import_items_tree->set_column_expand(IMPORT_ITEM_DATA, false);
import_items_tree->set_column_custom_minimum_width(0, 160 * EDSCALE);
import_items_tree->set_column_custom_minimum_width(IMPORT_ITEM, 80 * EDSCALE);
import_items_tree->set_column_custom_minimum_width(IMPORT_ITEM_DATA, 80 * EDSCALE);
+ import_items_tree->set_column_clip_content(1, true);
+ import_items_tree->set_column_clip_content(2, true);
ScrollContainer *import_bulk_sc = memnew(ScrollContainer);
import_bulk_sc->set_custom_minimum_size(Size2(260.0, 0.0) * EDSCALE);
diff --git a/editor/plugins/version_control_editor_plugin.cpp b/editor/plugins/version_control_editor_plugin.cpp
index 75a944e910..10679ad6f2 100644
--- a/editor/plugins/version_control_editor_plugin.cpp
+++ b/editor/plugins/version_control_editor_plugin.cpp
@@ -476,6 +476,7 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() {
version_control_dock = memnew(PanelContainer);
version_control_dock->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ version_control_dock->set_custom_minimum_size(Size2(0, 300) * EDSCALE);
version_control_dock->hide();
diff_vbc = memnew(VBoxContainer);
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index 1183da4d04..fb91cbb866 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -110,6 +110,7 @@ void VisualShaderGraphPlugin::_bind_methods() {
ClassDB::bind_method("set_uniform_name", &VisualShaderGraphPlugin::set_uniform_name);
ClassDB::bind_method("set_expression", &VisualShaderGraphPlugin::set_expression);
ClassDB::bind_method("update_curve", &VisualShaderGraphPlugin::update_curve);
+ ClassDB::bind_method("update_curve3", &VisualShaderGraphPlugin::update_curve3);
ClassDB::bind_method("update_constant", &VisualShaderGraphPlugin::update_constant);
}
@@ -211,9 +212,19 @@ void VisualShaderGraphPlugin::set_uniform_name(VisualShader::Type p_type, int p_
}
void VisualShaderGraphPlugin::update_curve(int p_node_id) {
- if (links.has(p_node_id) && links[p_node_id].curve_editor) {
+ if (links.has(p_node_id) && links[p_node_id].curve_editors[0]) {
if (((VisualShaderNodeCurveTexture *)links[p_node_id].visual_node)->get_texture().is_valid()) {
- links[p_node_id].curve_editor->set_curve(((VisualShaderNodeCurveTexture *)links[p_node_id].visual_node)->get_texture()->get_curve());
+ links[p_node_id].curve_editors[0]->set_curve(((VisualShaderNodeCurveTexture *)links[p_node_id].visual_node)->get_texture()->get_curve());
+ }
+ }
+}
+
+void VisualShaderGraphPlugin::update_curve3(int p_node_id) {
+ if (links.has(p_node_id) && links[p_node_id].curve_editors[0] && links[p_node_id].curve_editors[1] && links[p_node_id].curve_editors[2]) {
+ if (((VisualShaderNodeCurve3Texture *)links[p_node_id].visual_node)->get_texture().is_valid()) {
+ links[p_node_id].curve_editors[0]->set_curve(((VisualShaderNodeCurve3Texture *)links[p_node_id].visual_node)->get_texture()->get_curve_x());
+ links[p_node_id].curve_editors[1]->set_curve(((VisualShaderNodeCurve3Texture *)links[p_node_id].visual_node)->get_texture()->get_curve_y());
+ links[p_node_id].curve_editors[2]->set_curve(((VisualShaderNodeCurve3Texture *)links[p_node_id].visual_node)->get_texture()->get_curve_z());
}
}
}
@@ -265,8 +276,8 @@ void VisualShaderGraphPlugin::register_expression_edit(int p_node_id, CodeEdit *
links[p_node_id].expression_edit = p_expression_edit;
}
-void VisualShaderGraphPlugin::register_curve_editor(int p_node_id, CurveEditor *p_curve_editor) {
- links[p_node_id].curve_editor = p_curve_editor;
+void VisualShaderGraphPlugin::register_curve_editor(int p_node_id, int p_index, CurveEditor *p_curve_editor) {
+ links[p_node_id].curve_editors[p_index] = p_curve_editor;
}
void VisualShaderGraphPlugin::update_uniform_refs() {
@@ -312,7 +323,7 @@ void VisualShaderGraphPlugin::make_dirty(bool p_enabled) {
}
void VisualShaderGraphPlugin::register_link(VisualShader::Type p_type, int p_id, VisualShaderNode *p_visual_node, GraphNode *p_graph_node) {
- links.insert(p_id, { p_type, p_visual_node, p_graph_node, p_visual_node->get_output_port_for_preview() != -1, -1, Map<int, InputPort>(), Map<int, Port>(), nullptr, nullptr, nullptr, nullptr, nullptr });
+ links.insert(p_id, { p_type, p_visual_node, p_graph_node, p_visual_node->get_output_port_for_preview() != -1, -1, Map<int, InputPort>(), Map<int, Port>(), nullptr, nullptr, nullptr, nullptr, { nullptr, nullptr, nullptr } });
}
void VisualShaderGraphPlugin::register_output_port(int p_node_id, int p_port, TextureButton *p_button) {
@@ -472,6 +483,18 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
custom_editor = hbox;
}
+ Ref<VisualShaderNodeCurve3Texture> curve3 = vsnode;
+ if (curve3.is_valid()) {
+ if (curve3->get_texture().is_valid() && !curve3->get_texture()->is_connected("changed", callable_mp(VisualShaderEditor::get_singleton()->get_graph_plugin(), &VisualShaderGraphPlugin::update_curve3))) {
+ curve3->get_texture()->connect("changed", callable_mp(VisualShaderEditor::get_singleton()->get_graph_plugin(), &VisualShaderGraphPlugin::update_curve3), varray(p_id));
+ }
+
+ HBoxContainer *hbox = memnew(HBoxContainer);
+ custom_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ hbox->add_child(custom_editor);
+ custom_editor = hbox;
+ }
+
Ref<VisualShaderNodeFloatConstant> float_const = vsnode;
if (float_const.is_valid()) {
HBoxContainer *hbox = memnew(HBoxContainer);
@@ -495,19 +518,12 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
port_offset++;
node->add_child(custom_editor);
- if (curve.is_valid()) {
+ bool is_curve = curve.is_valid() || curve3.is_valid();
+
+ if (is_curve) {
VisualShaderEditor::get_singleton()->graph->add_child(node);
VisualShaderEditor::get_singleton()->_update_created_node(node);
- CurveEditor *curve_editor = memnew(CurveEditor);
- node->add_child(curve_editor);
- register_curve_editor(p_id, curve_editor);
- curve_editor->set_custom_minimum_size(Size2(300, 0));
- curve_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- if (curve->get_texture().is_valid()) {
- curve_editor->set_curve(curve->get_texture()->get_curve());
- }
-
TextureButton *preview = memnew(TextureButton);
preview->set_toggle_mode(true);
preview->set_normal_texture(VisualShaderEditor::get_singleton()->get_theme_icon("GuiVisibilityHidden", "EditorIcons"));
@@ -519,12 +535,59 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
preview->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_preview_select_port), varray(p_id, 0), CONNECT_DEFERRED);
custom_editor->add_child(preview);
+ if (vsnode->get_output_port_for_preview() >= 0) {
+ show_port_preview(p_type, p_id, vsnode->get_output_port_for_preview());
+ }
+ }
+
+ if (curve.is_valid()) {
+ CurveEditor *curve_editor = memnew(CurveEditor);
+ node->add_child(curve_editor);
+ register_curve_editor(p_id, 0, curve_editor);
+ curve_editor->set_custom_minimum_size(Size2(300, 0));
+ curve_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ if (curve->get_texture().is_valid()) {
+ curve_editor->set_curve(curve->get_texture()->get_curve());
+ }
+ }
+
+ if (curve3.is_valid()) {
+ CurveEditor *curve_editor_x = memnew(CurveEditor);
+ node->add_child(curve_editor_x);
+ register_curve_editor(p_id, 0, curve_editor_x);
+ curve_editor_x->set_custom_minimum_size(Size2(300, 0));
+ curve_editor_x->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ if (curve3->get_texture().is_valid()) {
+ curve_editor_x->set_curve(curve3->get_texture()->get_curve_x());
+ }
+
+ CurveEditor *curve_editor_y = memnew(CurveEditor);
+ node->add_child(curve_editor_y);
+ register_curve_editor(p_id, 1, curve_editor_y);
+ curve_editor_y->set_custom_minimum_size(Size2(300, 0));
+ curve_editor_y->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ if (curve3->get_texture().is_valid()) {
+ curve_editor_y->set_curve(curve3->get_texture()->get_curve_y());
+ }
+
+ CurveEditor *curve_editor_z = memnew(CurveEditor);
+ node->add_child(curve_editor_z);
+ register_curve_editor(p_id, 2, curve_editor_z);
+ curve_editor_z->set_custom_minimum_size(Size2(300, 0));
+ curve_editor_z->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ if (curve3->get_texture().is_valid()) {
+ curve_editor_z->set_curve(curve3->get_texture()->get_curve_z());
+ }
+ }
+
+ if (is_curve) {
VisualShaderNode::PortType port_left = vsnode->get_input_port_type(0);
VisualShaderNode::PortType port_right = vsnode->get_output_port_type(0);
node->set_slot(0, true, port_left, type_color[port_left], true, port_right, type_color[port_right]);
VisualShaderEditor::get_singleton()->call_deferred("_set_node_size", (int)p_type, p_id, size);
}
+
if (vsnode->is_use_prop_slots()) {
return;
}
@@ -888,6 +951,7 @@ void VisualShaderGraphPlugin::remove_node(VisualShader::Type p_type, int p_id) {
void VisualShaderGraphPlugin::connect_nodes(VisualShader::Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) {
if (visual_shader->get_shader_type() == p_type) {
VisualShaderEditor::get_singleton()->graph->connect_node(itos(p_from_node), p_from_port, itos(p_to_node), p_to_port);
+ connections.push_back({ p_from_node, p_from_port, p_to_node, p_to_port });
if (links[p_to_node].input_ports.has(p_to_port) && links[p_to_node].input_ports[p_to_port].default_input_button != nullptr) {
links[p_to_node].input_ports[p_to_port].default_input_button->hide();
}
@@ -897,6 +961,12 @@ void VisualShaderGraphPlugin::connect_nodes(VisualShader::Type p_type, int p_fro
void VisualShaderGraphPlugin::disconnect_nodes(VisualShader::Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) {
if (visual_shader->get_shader_type() == p_type) {
VisualShaderEditor::get_singleton()->graph->disconnect_node(itos(p_from_node), p_from_port, itos(p_to_node), p_to_port);
+ for (List<VisualShader::Connection>::Element *E = connections.front(); E; E = E->next()) {
+ if (E->get().from_node == p_from_node && E->get().from_port == p_from_port && E->get().to_node == p_to_node && E->get().to_port == p_to_port) {
+ connections.erase(E);
+ break;
+ }
+ }
if (links[p_to_node].input_ports.has(p_to_port) && links[p_to_node].input_ports[p_to_port].default_input_button != nullptr && links[p_to_node].visual_node->get_input_port_default_value(p_to_port).get_type() != Variant::NIL) {
links[p_to_node].input_ports[p_to_port].default_input_button->show();
set_input_port_default_value(p_type, p_to_node, p_to_port, links[p_to_node].visual_node->get_input_port_default_value(p_to_port));
@@ -2204,6 +2274,8 @@ void VisualShaderEditor::_setup_node(VisualShaderNode *p_node, int p_op_idx) {
void VisualShaderEditor::_add_node(int p_idx, int p_op_idx, String p_resource_path, int p_node_idx) {
ERR_FAIL_INDEX(p_idx, add_options.size());
+ VisualShader::Type type = get_current_shader_type();
+
Ref<VisualShaderNode> vsnode;
bool is_custom = add_options[p_idx].is_custom;
@@ -2230,6 +2302,29 @@ void VisualShaderEditor::_add_node(int p_idx, int p_op_idx, String p_resource_pa
}
}
+ VisualShaderNodeUniformRef *uniform_ref = Object::cast_to<VisualShaderNodeUniformRef>(vsn);
+
+ if (uniform_ref && to_node != -1 && to_slot != -1) {
+ VisualShaderNode::PortType input_port_type = visual_shader->get_node(type, to_node)->get_input_port_type(to_slot);
+ bool success = false;
+
+ for (int i = 0; i < uniform_ref->get_uniforms_count(); i++) {
+ if (uniform_ref->get_port_type_by_index(i) == input_port_type) {
+ uniform_ref->set_uniform_name(uniform_ref->get_uniform_name_by_index(i));
+ success = true;
+ break;
+ }
+ }
+ if (!success) {
+ for (int i = 0; i < uniform_ref->get_uniforms_count(); i++) {
+ if (visual_shader->is_port_types_compatible(uniform_ref->get_port_type_by_index(i), input_port_type)) {
+ uniform_ref->set_uniform_name(uniform_ref->get_uniform_name_by_index(i));
+ break;
+ }
+ }
+ }
+ }
+
vsnode = Ref<VisualShaderNode>(vsn);
} else {
ERR_FAIL_COND(add_options[p_idx].script.is_null());
@@ -2250,8 +2345,6 @@ void VisualShaderEditor::_add_node(int p_idx, int p_op_idx, String p_resource_pa
}
saved_node_pos_dirty = false;
- VisualShader::Type type = get_current_shader_type();
-
int id_to_use = visual_shader->get_valid_node_id(type);
if (p_resource_path.is_empty()) {
@@ -2380,6 +2473,11 @@ void VisualShaderEditor::_add_node(int p_idx, int p_op_idx, String p_resource_pa
graph_plugin->call_deferred("update_curve", id_to_use);
}
+ VisualShaderNodeCurve3Texture *curve3 = Object::cast_to<VisualShaderNodeCurve3Texture>(vsnode.ptr());
+ if (curve3) {
+ graph_plugin->call_deferred("update_curve3", id_to_use);
+ }
+
if (p_resource_path.is_empty()) {
undo_redo->commit_action();
} else {
@@ -2388,7 +2486,7 @@ void VisualShaderEditor::_add_node(int p_idx, int p_op_idx, String p_resource_pa
VisualShaderNodeTexture *texture2d = Object::cast_to<VisualShaderNodeTexture>(vsnode.ptr());
VisualShaderNodeTexture3D *texture3d = Object::cast_to<VisualShaderNodeTexture3D>(vsnode.ptr());
- if (texture2d || texture3d || curve) {
+ if (texture2d || texture3d || curve || curve3) {
undo_redo->add_do_method(vsnode.ptr(), "set_texture", ResourceLoader::load(p_resource_path));
return;
}
@@ -3583,6 +3681,10 @@ 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(curve_node_option_idx, -1, arr[i], i);
+ } else if (type == "Curve3Texture") {
+ saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE);
+ saved_node_pos_dirty = true;
+ _add_node(curve3_node_option_idx, -1, arr[i], i);
} else if (ClassDB::get_parent_class(type) == "Texture2D") {
saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE);
saved_node_pos_dirty = true;
@@ -4304,6 +4406,8 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("CubeMap", "Textures", "Functions", "VisualShaderNodeCubemap", TTR("Perform the cubic texture lookup."), -1, -1));
curve_node_option_idx = add_options.size();
add_options.push_back(AddOption("CurveTexture", "Textures", "Functions", "VisualShaderNodeCurveTexture", TTR("Perform the curve texture lookup."), -1, -1));
+ curve3_node_option_idx = add_options.size();
+ add_options.push_back(AddOption("CurveTexture3", "Textures", "Functions", "VisualShaderNodeCurve3Texture", TTR("Perform the ternary curve texture lookup."), -1, -1));
texture2d_node_option_idx = add_options.size();
add_options.push_back(AddOption("Texture2D", "Textures", "Functions", "VisualShaderNodeTexture", TTR("Perform the 2D texture lookup."), -1, -1));
texture2d_array_node_option_idx = add_options.size();
diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h
index d549a35306..2b354db7b3 100644
--- a/editor/plugins/visual_shader_editor_plugin.h
+++ b/editor/plugins/visual_shader_editor_plugin.h
@@ -75,7 +75,7 @@ private:
LineEdit *uniform_name = nullptr;
OptionButton *const_op = nullptr;
CodeEdit *expression_edit = nullptr;
- CurveEditor *curve_editor = nullptr;
+ CurveEditor *curve_editors[3] = { nullptr, nullptr, nullptr };
};
Ref<VisualShader> visual_shader;
@@ -97,7 +97,7 @@ public:
void register_default_input_button(int p_node_id, int p_port_id, Button *p_button);
void register_constant_option_btn(int p_node_id, OptionButton *p_button);
void register_expression_edit(int p_node_id, CodeEdit *p_expression_edit);
- void register_curve_editor(int p_node_id, CurveEditor *p_curve_editor);
+ void register_curve_editor(int p_node_id, int p_index, CurveEditor *p_curve_editor);
void clear_links();
void set_shader_type(VisualShader::Type p_type);
bool is_preview_visible(int p_id) const;
@@ -117,6 +117,7 @@ public:
void update_uniform_refs();
void set_uniform_name(VisualShader::Type p_type, int p_node_id, const String &p_name);
void update_curve(int p_node_id);
+ void update_curve3(int p_node_id);
void update_constant(VisualShader::Type p_type, int p_node_id);
void set_expression(VisualShader::Type p_type, int p_node_id, const String &p_expression);
int get_constant_index(float p_constant) const;
@@ -289,6 +290,7 @@ class VisualShaderEditor : public VBoxContainer {
int texture3d_node_option_idx;
int custom_node_option_idx;
int curve_node_option_idx;
+ int curve3_node_option_idx;
List<String> keyword_list;
List<VisualShaderNodeUniformRef> uniform_refs;
diff --git a/editor/plugins/voxel_gi_editor_plugin.cpp b/editor/plugins/voxel_gi_editor_plugin.cpp
index d30cc7ad17..162379a49d 100644
--- a/editor/plugins/voxel_gi_editor_plugin.cpp
+++ b/editor/plugins/voxel_gi_editor_plugin.cpp
@@ -69,10 +69,7 @@ void VoxelGIEditorPlugin::_notification(int p_what) {
const Vector3i size = voxel_gi->get_estimated_cell_size();
String text = vformat(String::utf8("%d × %d × %d"), size.x, size.y, size.z);
- int data_size = 4;
- if (GLOBAL_GET("rendering/quality/voxel_gi/anisotropic")) {
- data_size += 4;
- }
+ const int data_size = 4;
const double size_mb = size.x * size.y * size.z * data_size / (1024.0 * 1024.0);
text += " - " + vformat(TTR("VRAM Size: %s MB"), String::num(size_mb, 2));