diff options
24 files changed, 683 insertions, 112 deletions
diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml index 8869d2a589..0f87ba2ae5 100644 --- a/doc/classes/EditorSettings.xml +++ b/doc/classes/EditorSettings.xml @@ -445,6 +445,66 @@ The color to use for the TileMap editor's grid. [b]Note:[/b] Only effective if [member editors/tiles_editor/display_grid] is [code]true[/code]. </member> + <member name="editors/visual_editors/category_colors/color_color" type="Color" setter="" getter=""> + The color of a graph node's header when it belongs to the "Color" category. + </member> + <member name="editors/visual_editors/category_colors/conditional_color" type="Color" setter="" getter=""> + The color of a graph node's header when it belongs to the "Conditional" category. + </member> + <member name="editors/visual_editors/category_colors/input_color" type="Color" setter="" getter=""> + The color of a graph node's header when it belongs to the "Input" category. + </member> + <member name="editors/visual_editors/category_colors/output_color" type="Color" setter="" getter=""> + The color of a graph node's header when it belongs to the "Output" category. + </member> + <member name="editors/visual_editors/category_colors/particle_color" type="Color" setter="" getter=""> + The color of a graph node's header when it belongs to the "Particle" category. + </member> + <member name="editors/visual_editors/category_colors/scalar_color" type="Color" setter="" getter=""> + The color of a graph node's header when it belongs to the "Scalar" category. + </member> + <member name="editors/visual_editors/category_colors/special_color" type="Color" setter="" getter=""> + The color of a graph node's header when it belongs to the "Special" category. + </member> + <member name="editors/visual_editors/category_colors/textures_color" type="Color" setter="" getter=""> + The color of a graph node's header when it belongs to the "Textures" category. + </member> + <member name="editors/visual_editors/category_colors/transform_color" type="Color" setter="" getter=""> + The color of a graph node's header when it belongs to the "Transform" category. + </member> + <member name="editors/visual_editors/category_colors/utility_color" type="Color" setter="" getter=""> + The color of a graph node's header when it belongs to the "Utility" category. + </member> + <member name="editors/visual_editors/category_colors/vector_color" type="Color" setter="" getter=""> + The color of a graph node's header when it belongs to the "Vector" category. + </member> + <member name="editors/visual_editors/color_theme" type="String" setter="" getter=""> + The color theme to use in the visual shader editor. + </member> + <member name="editors/visual_editors/connection_colors/boolean_color" type="Color" setter="" getter=""> + The color of a port/connection of boolean type. + </member> + <member name="editors/visual_editors/connection_colors/sampler_color" type="Color" setter="" getter=""> + The color of a port/connection of sampler type. + </member> + <member name="editors/visual_editors/connection_colors/scalar_color" type="Color" setter="" getter=""> + The color of a port/connection of scalar type (float, int, unsigned int). + </member> + <member name="editors/visual_editors/connection_colors/transform_color" type="Color" setter="" getter=""> + The color of a port/connection of transform type. + </member> + <member name="editors/visual_editors/connection_colors/vector2_color" type="Color" setter="" getter=""> + The color of a port/connection of Vector2 type. + </member> + <member name="editors/visual_editors/connection_colors/vector3_color" type="Color" setter="" getter=""> + The color of a port/connection of Vector3 type. + </member> + <member name="editors/visual_editors/connection_colors/vector4_color" type="Color" setter="" getter=""> + The color of a port/connection of Vector4 type. + </member> + <member name="editors/visual_editors/grid_pattern" type="int" setter="" getter=""> + The pattern used for the background grid. + </member> <member name="editors/visual_editors/lines_curvature" type="float" setter="" getter=""> The curvature to use for connection lines in the visual shader editor. Higher values will make connection lines appear more curved, with values above [code]0.5[/code] resulting in more "angular" turns in the middle of connection lines. </member> diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 84840a1c47..cc0e954087 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -7406,7 +7406,7 @@ EditorNode::EditorNode() { vcs_actions_menu = VersionControlEditorPlugin::get_singleton()->get_version_control_actions_panel(); vcs_actions_menu->set_name("Version Control"); vcs_actions_menu->connect("index_pressed", callable_mp(this, &EditorNode::_version_control_menu_option)); - vcs_actions_menu->add_item(TTR("Create Version Control Metadata..."), RUN_VCS_METADATA); + vcs_actions_menu->add_item(TTR("Create/Override Version Control Metadata..."), RUN_VCS_METADATA); vcs_actions_menu->add_item(TTR("Version Control Settings..."), RUN_VCS_SETTINGS); project_menu->add_child(vcs_actions_menu); project_menu->set_item_submenu(project_menu->get_item_index(VCS_MENU), "Version Control"); diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index e3c9996c97..94e55f347a 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -768,8 +768,13 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { _initial_set("editors/shader_editor/behavior/files/restore_shaders_on_load", true); // Visual editors + EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_ENUM, "editors/visual_editors/color_theme", "Default", "Default,Legacy,Custom") + + _load_default_visual_shader_editor_theme(); + EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/visual_editors/minimap_opacity", 0.85, "0.0,1.0,0.01") EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/visual_editors/lines_curvature", 0.5, "0.0,1.0,0.01") + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "editors/visual_editors/grid_pattern", 1, "Lines,Dots") EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "editors/visual_editors/visual_shader/port_preview_size", 160, "100,400,0.01") /* Run */ @@ -905,6 +910,30 @@ void EditorSettings::_load_godot2_text_editor_theme() { _initial_set("text_editor/theme/highlighting/search_result_border_color", Color(0.41, 0.61, 0.91, 0.38)); } +void EditorSettings::_load_default_visual_shader_editor_theme() { + // Connection type colors + _initial_set("editors/visual_editors/connection_colors/scalar_color", Color(0.55, 0.55, 0.55)); + _initial_set("editors/visual_editors/connection_colors/vector2_color", Color(0.44, 0.43, 0.64)); + _initial_set("editors/visual_editors/connection_colors/vector3_color", Color(0.337, 0.314, 0.71)); + _initial_set("editors/visual_editors/connection_colors/vector4_color", Color(0.7, 0.65, 0.147)); + _initial_set("editors/visual_editors/connection_colors/boolean_color", Color(0.243, 0.612, 0.349)); + _initial_set("editors/visual_editors/connection_colors/transform_color", Color(0.71, 0.357, 0.64)); + _initial_set("editors/visual_editors/connection_colors/sampler_color", Color(0.659, 0.4, 0.137)); + + // Node category colors (used for the node headers) + _initial_set("editors/visual_editors/category_colors/output_color", Color(0.26, 0.10, 0.15)); + _initial_set("editors/visual_editors/category_colors/color_color", Color(0.5, 0.5, 0.1)); + _initial_set("editors/visual_editors/category_colors/conditional_color", Color(0.208, 0.522, 0.298)); + _initial_set("editors/visual_editors/category_colors/input_color", Color(0.502, 0.2, 0.204)); + _initial_set("editors/visual_editors/category_colors/scalar_color", Color(0.1, 0.5, 0.6)); + _initial_set("editors/visual_editors/category_colors/textures_color", Color(0.5, 0.3, 0.1)); + _initial_set("editors/visual_editors/category_colors/transform_color", Color(0.5, 0.3, 0.5)); + _initial_set("editors/visual_editors/category_colors/utility_color", Color(0.2, 0.2, 0.2)); + _initial_set("editors/visual_editors/category_colors/vector_color", Color(0.2, 0.2, 0.5)); + _initial_set("editors/visual_editors/category_colors/special_color", Color(0.098, 0.361, 0.294)); + _initial_set("editors/visual_editors/category_colors/particle_color", Color(0.12, 0.358, 0.8)); +} + bool EditorSettings::_save_text_editor_theme(String p_file) { String theme_section = "color_theme"; Ref<ConfigFile> cf = memnew(ConfigFile); // hex is better? diff --git a/editor/editor_settings.h b/editor/editor_settings.h index 87ce0cfd57..5783bac770 100644 --- a/editor/editor_settings.h +++ b/editor/editor_settings.h @@ -110,6 +110,7 @@ private: void _load_defaults(Ref<ConfigFile> p_extra_config = Ref<ConfigFile>()); void _load_godot2_text_editor_theme(); + void _load_default_visual_shader_editor_theme(); bool _save_text_editor_theme(String p_file); bool _is_default_text_editor_theme(String p_theme_name); const String _get_project_metadata_path() const; diff --git a/editor/editor_settings_dialog.cpp b/editor/editor_settings_dialog.cpp index 13e3c41e3b..c339bbf365 100644 --- a/editor/editor_settings_dialog.cpp +++ b/editor/editor_settings_dialog.cpp @@ -71,6 +71,8 @@ void EditorSettingsDialog::_settings_property_edited(const String &p_name) { EditorSettings::get_singleton()->set_manually("interface/theme/spacing_preset", "Custom"); } else if (full_name.begins_with("text_editor/theme/highlighting")) { EditorSettings::get_singleton()->set_manually("text_editor/theme/color_theme", "Custom"); + } else if (full_name.begins_with("editors/visual_editors/connection_colors") || full_name.begins_with("editors/visual_editors/category_colors")) { + EditorSettings::get_singleton()->set_manually("editors/visual_editors/color_theme", "Custom"); } } diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index b9b342245f..15a9cfad22 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -646,6 +646,18 @@ void Node3DEditorViewport::cancel_transform() { continue; } + if (se && se->gizmo.is_valid()) { + Vector<int> ids; + Vector<Transform3D> restore; + + for (const KeyValue<int, Transform3D> &GE : se->subgizmos) { + ids.push_back(GE.key); + restore.push_back(GE.value); + } + + se->gizmo->commit_subgizmos(ids, restore, true); + } + sp->set_global_transform(se->original); } @@ -8071,6 +8083,7 @@ void Node3DEditor::_bind_methods() { ClassDB::bind_method("_refresh_menu_icons", &Node3DEditor::_refresh_menu_icons); ClassDB::bind_method("update_all_gizmos", &Node3DEditor::update_all_gizmos); + ClassDB::bind_method("update_transform_gizmo", &Node3DEditor::update_transform_gizmo); ADD_SIGNAL(MethodInfo("transform_key_request")); ADD_SIGNAL(MethodInfo("item_lock_status_changed")); diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index ed42e8e5ab..61b1d38cfc 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -509,7 +509,7 @@ public: RID sbox_instance_xray; RID sbox_instance_xray_offset; Ref<EditorNode3DGizmo> gizmo; - HashMap<int, Transform3D> subgizmos; // map ID -> initial transform + HashMap<int, Transform3D> subgizmos; // Key: Subgizmo ID, Value: Initial subgizmo transform. Node3DEditorSelectedItem() { sp = nullptr; diff --git a/editor/plugins/path_3d_editor_plugin.cpp b/editor/plugins/path_3d_editor_plugin.cpp index 6fe1949382..ffdc06ceee 100644 --- a/editor/plugins/path_3d_editor_plugin.cpp +++ b/editor/plugins/path_3d_editor_plugin.cpp @@ -200,22 +200,6 @@ void Path3DGizmo::commit_handle(int p_id, bool p_secondary, const Variant &p_res EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); - // Primary handles: position. - if (!p_secondary) { - // Special cas for primary handle, the handle id equals control point id. - const int idx = p_id; - if (p_cancel) { - c->set_point_position(idx, p_restore); - return; - } - ur->create_action(TTR("Set Curve Point Position")); - ur->add_do_method(c.ptr(), "set_point_position", idx, c->get_point_position(idx)); - ur->add_undo_method(c.ptr(), "set_point_position", idx, p_restore); - ur->commit_action(); - - return; - } - // Secondary handles: in, out, tilt. const HandleInfo info = _secondary_handles_info[p_id]; const int idx = info.point_idx; @@ -235,6 +219,7 @@ void Path3DGizmo::commit_handle(int p_id, bool p_secondary, const Variant &p_res ur->add_do_method(c.ptr(), "set_point_in", idx, Path3DEditorPlugin::singleton->mirror_length_enabled() ? -c->get_point_out(idx) : (-c->get_point_out(idx).normalized() * orig_in_length)); ur->add_undo_method(c.ptr(), "set_point_in", idx, Path3DEditorPlugin::singleton->mirror_length_enabled() ? -static_cast<Vector3>(p_restore) : (-static_cast<Vector3>(p_restore).normalized() * orig_in_length)); } + ur->commit_action(); break; } @@ -252,6 +237,7 @@ void Path3DGizmo::commit_handle(int p_id, bool p_secondary, const Variant &p_res ur->add_do_method(c.ptr(), "set_point_out", idx, Path3DEditorPlugin::singleton->mirror_length_enabled() ? -c->get_point_in(idx) : (-c->get_point_in(idx).normalized() * orig_out_length)); ur->add_undo_method(c.ptr(), "set_point_out", idx, Path3DEditorPlugin::singleton->mirror_length_enabled() ? -static_cast<Vector3>(p_restore) : (-static_cast<Vector3>(p_restore).normalized() * orig_out_length)); } + ur->commit_action(); break; } @@ -263,6 +249,7 @@ void Path3DGizmo::commit_handle(int p_id, bool p_secondary, const Variant &p_res ur->create_action(TTR("Set Curve Point Tilt")); ur->add_do_method(c.ptr(), "set_point_tilt", idx, c->get_point_tilt(idx)); ur->add_undo_method(c.ptr(), "set_point_tilt", idx, p_restore); + ur->commit_action(); break; } @@ -275,7 +262,7 @@ void Path3DGizmo::redraw() { Ref<StandardMaterial3D> path_material = gizmo_plugin->get_material("path_material", this); Ref<StandardMaterial3D> path_thin_material = gizmo_plugin->get_material("path_thin_material", this); Ref<StandardMaterial3D> path_tilt_material = gizmo_plugin->get_material("path_tilt_material", this); - Ref<StandardMaterial3D> handles_material = gizmo_plugin->get_material("handles"); + Ref<StandardMaterial3D> path_tilt_muted_material = gizmo_plugin->get_material("path_tilt_muted_material", this); Ref<StandardMaterial3D> sec_handles_material = gizmo_plugin->get_material("sec_handles"); Ref<Curve3D> c = path->get_curve(); @@ -353,48 +340,57 @@ void Path3DGizmo::redraw() { if (Path3DEditorPlugin::singleton->get_edited_path() == path) { PackedVector3Array handle_lines; PackedVector3Array tilt_handle_lines; - PackedVector3Array primary_handle_points; PackedVector3Array secondary_handle_points; PackedInt32Array collected_secondary_handle_ids; // Avoid shadowing member on Node3DEditorGizmo. _secondary_handles_info.resize(c->get_point_count() * 3); for (int idx = 0; idx < c->get_point_count(); idx++) { - // Collect primary-handles. const Vector3 pos = c->get_point_position(idx); - primary_handle_points.append(pos); + bool is_current_point_selected = is_subgizmo_selected(idx); + bool is_previous_point_selected = is_subgizmo_selected(idx - 1); + bool is_following_point_selected = is_subgizmo_selected(idx + 1); HandleInfo info; info.point_idx = idx; // Collect in-handles except for the first point. - if (idx > 0) { - info.type = HandleType::HANDLE_TYPE_IN; - const int handle_idx = idx * 3 + 0; - collected_secondary_handle_ids.append(handle_idx); - _secondary_handles_info.write[handle_idx] = info; - + if (idx > 0 && (is_current_point_selected || is_previous_point_selected)) { const Vector3 in = c->get_point_in(idx); - secondary_handle_points.append(pos + in); - handle_lines.append(pos); - handle_lines.append(pos + in); + + // Display in-handles only when they are "initialized". + if (in.length_squared() > 0) { + info.type = HandleType::HANDLE_TYPE_IN; + const int handle_idx = idx * 3 + 0; + collected_secondary_handle_ids.append(handle_idx); + _secondary_handles_info.write[handle_idx] = info; + + secondary_handle_points.append(pos + in); + handle_lines.append(pos); + handle_lines.append(pos + in); + } } // Collect out-handles except for the last point. - if (idx < c->get_point_count() - 1) { - info.type = HandleType::HANDLE_TYPE_OUT; - const int handle_idx = idx * 3 + 1; - collected_secondary_handle_ids.append(handle_idx); - _secondary_handles_info.write[handle_idx] = info; - + if (idx < c->get_point_count() - 1 && (is_current_point_selected || is_following_point_selected)) { const Vector3 out = c->get_point_out(idx); - secondary_handle_points.append(pos + out); - handle_lines.append(pos); - handle_lines.append(pos + out); + + // Display out-handles only when they are "initialized". + if (out.length_squared() > 0) { + info.type = HandleType::HANDLE_TYPE_OUT; + const int handle_idx = idx * 3 + 1; + collected_secondary_handle_ids.append(handle_idx); + _secondary_handles_info.write[handle_idx] = info; + + secondary_handle_points.append(pos + out); + handle_lines.append(pos); + handle_lines.append(pos + out); + } } // Collect tilt-handles. - { + if (is_current_point_selected || is_previous_point_selected || is_following_point_selected) { + // Tilt handle. { info.type = HandleType::HANDLE_TYPE_TILT; const int handle_idx = idx * 3 + 2; @@ -423,7 +419,7 @@ void Path3DGizmo::redraw() { const Vector3 edge = sin(a) * side + cos(a) * up; disk.append(pos + edge * disk_size); } - add_vertices(disk, path_tilt_material, Mesh::PRIMITIVE_LINE_STRIP); + add_vertices(disk, is_current_point_selected ? path_tilt_material : path_tilt_muted_material, Mesh::PRIMITIVE_LINE_STRIP); } } } @@ -436,21 +432,27 @@ void Path3DGizmo::redraw() { add_lines(tilt_handle_lines, path_tilt_material); } - if (primary_handle_points.size()) { - add_handles(primary_handle_points, handles_material); - } if (secondary_handle_points.size()) { add_handles(secondary_handle_points, sec_handles_material, collected_secondary_handle_ids, false, true); } + // Draw the gizmo plugin manually, because handles are registered. In which case, the caller code skips drawing the gizmo plugin. + gizmo_plugin->redraw(this); } } +void Path3DGizmo::_update_transform_gizmo() { + Node3DEditor::get_singleton()->update_transform_gizmo(); +} + Path3DGizmo::Path3DGizmo(Path3D *p_path, float p_disk_size) { path = p_path; disk_size = p_disk_size; set_node_3d(p_path); orig_in_length = 0; orig_out_length = 0; + + // Connecting to a signal once, rather than plaguing the implementation with calls to `Node3DEditor::update_transform_gizmo`. + path->connect("curve_changed", callable_mp(this, &Path3DGizmo::_update_transform_gizmo)); } EditorPlugin::AfterGUIInput Path3DEditorPlugin::forward_3d_gui_input(Camera3D *p_camera, const Ref<InputEvent> &p_event) { @@ -819,10 +821,130 @@ Ref<EditorNode3DGizmo> Path3DGizmoPlugin::create_gizmo(Node3D *p_spatial) { return ref; } +bool Path3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { + return Object::cast_to<Path3D>(p_spatial) != nullptr; +} + String Path3DGizmoPlugin::get_gizmo_name() const { return "Path3D"; } +void Path3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { + Path3D *path = Object::cast_to<Path3D>(p_gizmo->get_node_3d()); + ERR_FAIL_NULL(path); + + Ref<Curve3D> curve = path->get_curve(); + + Ref<StandardMaterial3D> handle_material = get_material("handles", p_gizmo); + PackedVector3Array handles; + + for (int idx = 0; idx < curve->get_point_count(); ++idx) { + // Collect handles. + const Vector3 pos = curve->get_point_position(idx); + + handles.append(pos); + } + + if (handles.size()) { + p_gizmo->add_vertices(handles, handle_material, Mesh::PRIMITIVE_POINTS); + } +} + +int Path3DGizmoPlugin::subgizmos_intersect_ray(const EditorNode3DGizmo *p_gizmo, Camera3D *p_camera, const Vector2 &p_point) const { + Path3D *path = Object::cast_to<Path3D>(p_gizmo->get_node_3d()); + ERR_FAIL_NULL_V(path, -1); + Ref<Curve3D> curve = path->get_curve(); + ERR_FAIL_COND_V(curve.is_null(), -1); + + for (int idx = 0; idx < curve->get_point_count(); ++idx) { + Vector3 pos = path->get_global_transform().xform(curve->get_point_position(idx)); + if (p_camera->unproject_position(pos).distance_to(p_point) < 20) { + return idx; + } + } + return -1; +} + +Vector<int> Path3DGizmoPlugin::subgizmos_intersect_frustum(const EditorNode3DGizmo *p_gizmo, const Camera3D *p_camera, const Vector<Plane> &p_frustum) const { + Vector<int> contained_points; + + Path3D *path = Object::cast_to<Path3D>(p_gizmo->get_node_3d()); + ERR_FAIL_NULL_V(path, contained_points); + Ref<Curve3D> curve = path->get_curve(); + ERR_FAIL_COND_V(curve.is_null(), contained_points); + + for (int idx = 0; idx < curve->get_point_count(); ++idx) { + Vector3 pos = path->get_global_transform().xform(curve->get_point_position(idx)); + bool is_contained_in_frustum = true; + for (int i = 0; i < p_frustum.size(); ++i) { + if (p_frustum[i].distance_to(pos) > 0) { + is_contained_in_frustum = false; + break; + } + } + + if (is_contained_in_frustum) { + contained_points.push_back(idx); + } + } + + return contained_points; +} + +Transform3D Path3DGizmoPlugin::get_subgizmo_transform(const EditorNode3DGizmo *p_gizmo, int p_id) const { + Path3D *path = Object::cast_to<Path3D>(p_gizmo->get_node_3d()); + ERR_FAIL_NULL_V(path, Transform3D()); + Ref<Curve3D> curve = path->get_curve(); + ERR_FAIL_COND_V(curve.is_null(), Transform3D()); + ERR_FAIL_INDEX_V(p_id, curve->get_point_count(), Transform3D()); + + Basis basis = transformation_locked_basis.has(p_id) ? transformation_locked_basis[p_id] : curve->get_point_baked_posture(p_id, true); + Vector3 pos = curve->get_point_position(p_id); + + Transform3D t = Transform3D(basis, pos); + return t; +} + +void Path3DGizmoPlugin::set_subgizmo_transform(const EditorNode3DGizmo *p_gizmo, int p_id, Transform3D p_transform) { + Path3D *path = Object::cast_to<Path3D>(p_gizmo->get_node_3d()); + ERR_FAIL_NULL(path); + Ref<Curve3D> curve = path->get_curve(); + ERR_FAIL_COND(curve.is_null()); + ERR_FAIL_INDEX(p_id, curve->get_point_count()); + + if (!transformation_locked_basis.has(p_id)) { + transformation_locked_basis[p_id] = Basis(curve->get_point_baked_posture(p_id, true)); + } + curve->set_point_position(p_id, p_transform.origin); +} + +void Path3DGizmoPlugin::commit_subgizmos(const EditorNode3DGizmo *p_gizmo, const Vector<int> &p_ids, const Vector<Transform3D> &p_restore, bool p_cancel) { + Path3D *path = Object::cast_to<Path3D>(p_gizmo->get_node_3d()); + ERR_FAIL_NULL(path); + Ref<Curve3D> curve = path->get_curve(); + ERR_FAIL_COND(curve.is_null()); + + transformation_locked_basis.clear(); + + if (p_cancel) { + for (int i = 0; i < p_ids.size(); ++i) { + curve->set_point_position(p_ids[i], p_restore[i].origin); + } + return; + } + + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); + + undo_redo->create_action(TTR("Set Curve Point Position")); + + for (int i = 0; i < p_ids.size(); ++i) { + const int idx = p_ids[i]; + undo_redo->add_do_method(curve.ptr(), "set_point_position", idx, curve->get_point_position(idx)); + undo_redo->add_undo_method(curve.ptr(), "set_point_position", idx, p_restore[i].origin); + } + undo_redo->commit_action(); +} + int Path3DGizmoPlugin::get_priority() const { return -1; } @@ -835,6 +957,7 @@ Path3DGizmoPlugin::Path3DGizmoPlugin(float p_disk_size) { create_material("path_material", path_color); create_material("path_thin_material", Color(0.6, 0.6, 0.6)); create_material("path_tilt_material", path_tilt_color); + create_material("path_tilt_muted_material", path_tilt_color * 0.7); create_handle_material("handles", false, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("EditorPathSmoothHandle"), EditorStringName(EditorIcons))); create_handle_material("sec_handles", false, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("EditorCurveHandle"), EditorStringName(EditorIcons))); } diff --git a/editor/plugins/path_3d_editor_plugin.h b/editor/plugins/path_3d_editor_plugin.h index 5a5f76b015..931ac7128c 100644 --- a/editor/plugins/path_3d_editor_plugin.h +++ b/editor/plugins/path_3d_editor_plugin.h @@ -63,6 +63,8 @@ class Path3DGizmo : public EditorNode3DGizmo { // Cache information of secondary handles. Vector<HandleInfo> _secondary_handles_info; + void _update_transform_gizmo(); + public: virtual String get_handle_name(int p_id, bool p_secondary) const override; virtual Variant get_handle_value(int p_id, bool p_secondary) const override; @@ -78,11 +80,25 @@ class Path3DGizmoPlugin : public EditorNode3DGizmoPlugin { float disk_size = 0.8; + // Locking basis is meant to ensure a predictable behavior during translation of the curve points in "local space transform mode". + // Without the locking, the gizmo/point, in "local space transform mode", wouldn't follow a straight path and would curve and twitch in an unpredictable way. + HashMap<int, Basis> transformation_locked_basis; + protected: Ref<EditorNode3DGizmo> create_gizmo(Node3D *p_spatial) override; public: + virtual bool has_gizmo(Node3D *p_spatial) override; String get_gizmo_name() const override; + + virtual void redraw(EditorNode3DGizmo *p_gizmo) override; + + virtual int subgizmos_intersect_ray(const EditorNode3DGizmo *p_gizmo, Camera3D *p_camera, const Vector2 &p_point) const override; + virtual Vector<int> subgizmos_intersect_frustum(const EditorNode3DGizmo *p_gizmo, const Camera3D *p_camera, const Vector<Plane> &p_frustum) const override; + virtual Transform3D get_subgizmo_transform(const EditorNode3DGizmo *p_gizmo, int p_id) const override; + virtual void set_subgizmo_transform(const EditorNode3DGizmo *p_gizmo, int p_id, Transform3D p_transform) override; + virtual void commit_subgizmos(const EditorNode3DGizmo *p_gizmo, const Vector<int> &p_ids, const Vector<Transform3D> &p_restore, bool p_cancel = false) override; + int get_priority() const override; Path3DGizmoPlugin(float p_disk_size); }; diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 4750179473..acca5810a9 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -104,6 +104,7 @@ void VisualShaderNodePlugin::_bind_methods() { /////////////////// VisualShaderGraphPlugin::VisualShaderGraphPlugin() { + vs_msdf_fonts_theme.instantiate(); } void VisualShaderGraphPlugin::_bind_methods() { @@ -358,6 +359,13 @@ void VisualShaderGraphPlugin::update_theme() { vector_expanded_color[1] = editor->get_theme_color(SNAME("axis_y_color"), EditorStringName(Editor)); // green vector_expanded_color[2] = editor->get_theme_color(SNAME("axis_z_color"), EditorStringName(Editor)); // blue vector_expanded_color[3] = editor->get_theme_color(SNAME("axis_w_color"), EditorStringName(Editor)); // alpha + + Ref<Font> label_font = EditorNode::get_singleton()->get_editor_theme()->get_font("main_msdf", EditorStringName(EditorFonts)); + Ref<Font> label_bold_font = EditorNode::get_singleton()->get_editor_theme()->get_font("main_bold_msdf", EditorStringName(EditorFonts)); + vs_msdf_fonts_theme->set_font("font", "Label", label_font); + vs_msdf_fonts_theme->set_font("font", "GraphNodeTitleLabel", label_bold_font); + vs_msdf_fonts_theme->set_font("font", "LineEdit", label_font); + vs_msdf_fonts_theme->set_font("font", "Button", label_font); } bool VisualShaderGraphPlugin::is_node_has_parameter_instances_relatively(VisualShader::Type p_type, int p_node) const { @@ -398,34 +406,35 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id, bool Control *offset; - static const Color type_color[] = { - Color(0.38, 0.85, 0.96), // scalar (float) - Color(0.49, 0.78, 0.94), // scalar (int) - Color(0.20, 0.88, 0.67), // scalar (uint) - Color(0.74, 0.57, 0.95), // vector2 - Color(0.84, 0.49, 0.93), // vector3 - Color(1.0, 0.125, 0.95), // vector4 - Color(0.55, 0.65, 0.94), // boolean - Color(0.96, 0.66, 0.43), // transform - Color(1.0, 1.0, 0.0), // sampler + const Color type_color[] = { + EDITOR_GET("editors/visual_editors/connection_colors/scalar_color"), + EDITOR_GET("editors/visual_editors/connection_colors/scalar_color"), + EDITOR_GET("editors/visual_editors/connection_colors/scalar_color"), + EDITOR_GET("editors/visual_editors/connection_colors/vector2_color"), + EDITOR_GET("editors/visual_editors/connection_colors/vector3_color"), + EDITOR_GET("editors/visual_editors/connection_colors/vector4_color"), + EDITOR_GET("editors/visual_editors/connection_colors/boolean_color"), + EDITOR_GET("editors/visual_editors/connection_colors/transform_color"), + EDITOR_GET("editors/visual_editors/connection_colors/sampler_color"), }; - static const String vector_expanded_name[4] = { - "red", - "green", - "blue", - "alpha" + // Keep in sync with VisualShaderNode::Category. + const Color category_color[VisualShaderNode::Category::CATEGORY_MAX] = { + Color(0.0, 0.0, 0.0), // None (default, not used) + EDITOR_GET("editors/visual_editors/category_colors/output_color"), + EDITOR_GET("editors/visual_editors/category_colors/color_color"), + EDITOR_GET("editors/visual_editors/category_colors/conditional_color"), + EDITOR_GET("editors/visual_editors/category_colors/input_color"), + EDITOR_GET("editors/visual_editors/category_colors/scalar_color"), + EDITOR_GET("editors/visual_editors/category_colors/textures_color"), + EDITOR_GET("editors/visual_editors/category_colors/transform_color"), + EDITOR_GET("editors/visual_editors/category_colors/utility_color"), + EDITOR_GET("editors/visual_editors/category_colors/vector_color"), + EDITOR_GET("editors/visual_editors/category_colors/special_color"), + EDITOR_GET("editors/visual_editors/category_colors/particle_color"), }; - // Visual shader specific theme for MSDF font. - Ref<Theme> vstheme; - vstheme.instantiate(); - Ref<Font> label_font = EditorNode::get_singleton()->get_editor_theme()->get_font("main_msdf", EditorStringName(EditorFonts)); - Ref<Font> label_bold_font = EditorNode::get_singleton()->get_editor_theme()->get_font("main_bold_msdf", EditorStringName(EditorFonts)); - vstheme->set_font("font", "Label", label_font); - vstheme->set_font("font", "GraphNodeTitleLabel", label_bold_font); - vstheme->set_font("font", "LineEdit", label_font); - vstheme->set_font("font", "Button", label_font); + static const String vector_expanded_name[4] = { "red", "green", "blue", "alpha" }; Ref<VisualShaderNode> vsnode = visual_shader->get_node(p_type, p_id); @@ -457,7 +466,18 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id, bool node->connect("delete_request", callable_mp(editor, &VisualShaderEditor::_delete_node_request).bind(p_type, p_id), CONNECT_DEFERRED); } graph->add_child(node); - node->set_theme(vstheme); + node->set_theme(vs_msdf_fonts_theme); + + // Set the node's titlebar color based on its category. + if (vsnode->get_category() != VisualShaderNode::CATEGORY_NONE) { + Ref<StyleBoxFlat> sb_colored = editor->get_theme_stylebox("titlebar", "GraphNode")->duplicate(); + sb_colored->set_bg_color(category_color[vsnode->get_category()]); + node->add_theme_style_override("titlebar", sb_colored); + + Ref<StyleBoxFlat> sb_colored_selected = editor->get_theme_stylebox("titlebar_selected", "GraphNode")->duplicate(); + sb_colored_selected->set_bg_color(category_color[vsnode->get_category()].lightened(0.2)); + node->add_theme_style_override("titlebar_selected", sb_colored_selected); + } if (p_just_update) { Link &link = links[p_id]; @@ -506,6 +526,11 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id, bool port_offset += 1; } + // Set the minimum width of a node based on the preview size to avoid a resize when toggling the preview. + Ref<StyleBoxFlat> graph_node_stylebox = graph->get_theme_stylebox("panel", "GraphNode"); + int port_preview_size = EDITOR_GET("editors/visual_editors/visual_shader/port_preview_size"); + node->set_custom_minimum_size(Size2((Math::ceil(graph_node_stylebox->get_minimum_size().width) + port_preview_size) * EDSCALE, 0)); + Ref<VisualShaderNodeParticleEmit> emit = vsnode; if (emit.is_valid()) { node->set_custom_minimum_size(Size2(200 * EDSCALE, 0)); @@ -4313,7 +4338,9 @@ void VisualShaderEditor::_notification(int p_what) { } if (EditorSettings::get_singleton()->check_changed_settings_in_group("editors/visual_editors")) { graph->set_minimap_opacity(EDITOR_GET("editors/visual_editors/minimap_opacity")); + graph->set_grid_pattern((GraphEdit::GridPattern) int(EDITOR_GET("editors/visual_editors/grid_pattern"))); graph->set_connection_lines_curvature(EDITOR_GET("editors/visual_editors/lines_curvature")); + _update_graph(); } } break; @@ -5424,6 +5451,9 @@ VisualShaderEditor::VisualShaderEditor() { 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_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); SET_DRAG_FORWARDING_GCD(graph, VisualShaderEditor); diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h index 39e721f226..2575866b10 100644 --- a/editor/plugins/visual_shader_editor_plugin.h +++ b/editor/plugins/visual_shader_editor_plugin.h @@ -99,6 +99,9 @@ private: Color vector_expanded_color[4]; + // Visual shader specific theme for using MSDF fonts (on GraphNodes) which reduce aliasing at higher zoom levels. + Ref<Theme> vs_msdf_fonts_theme; + protected: static void _bind_methods(); diff --git a/editor/themes/editor_theme_manager.cpp b/editor/themes/editor_theme_manager.cpp index 4ceffcc98c..4a67bd6b31 100644 --- a/editor/themes/editor_theme_manager.cpp +++ b/editor/themes/editor_theme_manager.cpp @@ -39,6 +39,7 @@ #include "editor/themes/editor_icons.h" #include "editor/themes/editor_scale.h" #include "editor/themes/editor_theme.h" +#include "scene/gui/graph_edit.h" #include "scene/resources/image_texture.h" #include "scene/resources/style_box_flat.h" #include "scene/resources/style_box_line.h" @@ -213,6 +214,7 @@ Ref<EditorTheme> EditorThemeManager::_create_base_theme(const Ref<EditorTheme> & _populate_standard_styles(theme, config); _populate_editor_styles(theme, config); _populate_text_editor_styles(theme, config); + _populate_visual_shader_styles(theme, config); OS::get_singleton()->benchmark_end_measure(get_benchmark_key(), "Create Base Theme"); return theme; @@ -1465,13 +1467,22 @@ void EditorThemeManager::_populate_standard_styles(const Ref<EditorTheme> &p_the p_theme->set_stylebox("panel", "GraphEdit", p_config.tree_panel_style); p_theme->set_stylebox("menu_panel", "GraphEdit", make_flat_stylebox(p_config.dark_color_1 * Color(1, 1, 1, 0.6), 4, 2, 4, 2, 3)); - if (p_config.dark_theme) { - p_theme->set_color("grid_major", "GraphEdit", Color(1.0, 1.0, 1.0, 0.1)); - p_theme->set_color("grid_minor", "GraphEdit", Color(1.0, 1.0, 1.0, 0.05)); - } else { - p_theme->set_color("grid_major", "GraphEdit", Color(0.0, 0.0, 0.0, 0.15)); - p_theme->set_color("grid_minor", "GraphEdit", Color(0.0, 0.0, 0.0, 0.07)); + float grid_base_brightness = p_config.dark_theme ? 1.0 : 0.0; + GraphEdit::GridPattern grid_pattern = (GraphEdit::GridPattern) int(EDITOR_GET("editors/visual_editors/grid_pattern")); + switch (grid_pattern) { + case GraphEdit::GRID_PATTERN_LINES: + p_theme->set_color("grid_major", "GraphEdit", Color(grid_base_brightness, grid_base_brightness, grid_base_brightness, 0.10)); + p_theme->set_color("grid_minor", "GraphEdit", Color(grid_base_brightness, grid_base_brightness, grid_base_brightness, 0.05)); + break; + case GraphEdit::GRID_PATTERN_DOTS: + p_theme->set_color("grid_major", "GraphEdit", Color(grid_base_brightness, grid_base_brightness, grid_base_brightness, 0.07)); + p_theme->set_color("grid_minor", "GraphEdit", Color(grid_base_brightness, grid_base_brightness, grid_base_brightness, 0.07)); + break; + default: + WARN_PRINT("Unknown grid pattern."); + break; } + p_theme->set_color("selection_fill", "GraphEdit", p_theme->get_color(SNAME("box_selection_fill_color"), EditorStringName(Editor))); p_theme->set_color("selection_stroke", "GraphEdit", p_theme->get_color(SNAME("box_selection_stroke_color"), EditorStringName(Editor))); p_theme->set_color("activity", "GraphEdit", p_config.dark_theme ? Color(1, 1, 1) : Color(0, 0, 0)); @@ -1522,31 +1533,48 @@ void EditorThemeManager::_populate_standard_styles(const Ref<EditorTheme> &p_the const int gn_margin_side = 2; const int gn_margin_bottom = 2; + const int gn_corner_radius = 3; + const Color gn_bg_color = p_config.dark_theme ? p_config.dark_color_3 : p_config.dark_color_1.lerp(p_config.mono_color, 0.09); - const Color gn_selected_border_color = gn_bg_color.lerp(p_config.accent_color, 0.275); + const Color gn_selected_border_color = p_config.dark_theme ? Color(1, 1, 1) : Color(0, 0, 0); const Color gn_frame_bg = gn_bg_color.lerp(p_config.tree_panel_style->get_bg_color(), 0.3); - Ref<StyleBoxFlat> gn_panel_style = make_flat_stylebox(gn_frame_bg, gn_margin_side, gn_margin_top, gn_margin_side, gn_margin_bottom, p_config.corner_radius); - gn_panel_style->set_border_width_all(p_config.border_width); - gn_panel_style->set_border_color(gn_bg_color); - gn_panel_style->set_corner_radius_individual(0, 0, p_config.corner_radius * EDSCALE, p_config.corner_radius * EDSCALE); - gn_panel_style->set_expand_margin(SIDE_TOP, 17 * EDSCALE); + const bool high_contrast_borders = p_config.draw_extra_borders && p_config.dark_theme; - Ref<StyleBoxFlat> gn_panel_selected_style = make_flat_stylebox(gn_frame_bg, gn_margin_side, gn_margin_top, gn_margin_side, gn_margin_bottom, p_config.corner_radius); - gn_panel_selected_style->set_border_width_all(2 * EDSCALE + p_config.border_width); + Ref<StyleBoxFlat> gn_panel_style = make_flat_stylebox(gn_frame_bg, gn_margin_side, gn_margin_top, gn_margin_side, gn_margin_bottom, p_config.corner_radius); + gn_panel_style->set_border_width(SIDE_BOTTOM, 2 * EDSCALE); + gn_panel_style->set_border_width(SIDE_LEFT, 2 * EDSCALE); + gn_panel_style->set_border_width(SIDE_RIGHT, 2 * EDSCALE); + gn_panel_style->set_border_color(high_contrast_borders ? gn_bg_color.lightened(0.2) : gn_bg_color.darkened(0.3)); + gn_panel_style->set_corner_radius_individual(0, 0, gn_corner_radius * EDSCALE, gn_corner_radius * EDSCALE); + gn_panel_style->set_anti_aliased(true); + + Ref<StyleBoxFlat> gn_panel_selected_style = gn_panel_style->duplicate(); + gn_panel_selected_style->set_bg_color(p_config.dark_theme ? gn_bg_color.lightened(0.15) : gn_bg_color.darkened(0.15)); + gn_panel_selected_style->set_border_width(SIDE_TOP, 0); + gn_panel_selected_style->set_border_width(SIDE_BOTTOM, 2 * EDSCALE); + gn_panel_selected_style->set_border_width(SIDE_LEFT, 2 * EDSCALE); + gn_panel_selected_style->set_border_width(SIDE_RIGHT, 2 * EDSCALE); gn_panel_selected_style->set_border_color(gn_selected_border_color); - gn_panel_selected_style->set_corner_radius_individual(0, 0, p_config.corner_radius * EDSCALE, p_config.corner_radius * EDSCALE); - gn_panel_selected_style->set_expand_margin(SIDE_TOP, 17 * EDSCALE); - const int gn_titlebar_margin_left = 12; - const int gn_titlebar_margin_right = 4; // The rest is for the close button. + const int gn_titlebar_margin_top = 8; + const int gn_titlebar_margin_side = 12; + const int gn_titlebar_margin_bottom = 8; - Ref<StyleBoxFlat> gn_titlebar_style = make_flat_stylebox(gn_bg_color, gn_titlebar_margin_left, gn_margin_top, gn_titlebar_margin_right, 0, p_config.corner_radius); + Ref<StyleBoxFlat> gn_titlebar_style = make_flat_stylebox(gn_bg_color, gn_titlebar_margin_side, gn_titlebar_margin_top, gn_titlebar_margin_side, gn_titlebar_margin_bottom, p_config.corner_radius); + gn_titlebar_style->set_border_width(SIDE_TOP, 2 * EDSCALE); + gn_titlebar_style->set_border_width(SIDE_LEFT, 2 * EDSCALE); + gn_titlebar_style->set_border_width(SIDE_RIGHT, 2 * EDSCALE); + gn_titlebar_style->set_border_color(high_contrast_borders ? gn_bg_color.lightened(0.2) : gn_bg_color.darkened(0.3)); gn_titlebar_style->set_expand_margin(SIDE_TOP, 2 * EDSCALE); - gn_titlebar_style->set_corner_radius_individual(p_config.corner_radius * EDSCALE, p_config.corner_radius * EDSCALE, 0, 0); - - Ref<StyleBoxFlat> gn_titlebar_selected_style = make_flat_stylebox(gn_selected_border_color, gn_titlebar_margin_left, gn_margin_top, gn_titlebar_margin_right, 0, p_config.corner_radius); - gn_titlebar_selected_style->set_corner_radius_individual(p_config.corner_radius * EDSCALE, p_config.corner_radius * EDSCALE, 0, 0); + gn_titlebar_style->set_corner_radius_individual(gn_corner_radius * EDSCALE, gn_corner_radius * EDSCALE, 0, 0); + gn_titlebar_style->set_anti_aliased(true); + + Ref<StyleBoxFlat> gn_titlebar_selected_style = gn_titlebar_style->duplicate(); + gn_titlebar_selected_style->set_border_color(gn_selected_border_color); + gn_titlebar_selected_style->set_border_width(SIDE_TOP, 2 * EDSCALE); + gn_titlebar_selected_style->set_border_width(SIDE_LEFT, 2 * EDSCALE); + gn_titlebar_selected_style->set_border_width(SIDE_RIGHT, 2 * EDSCALE); gn_titlebar_selected_style->set_expand_margin(SIDE_TOP, 2 * EDSCALE); Color gn_decoration_color = p_config.dark_color_1.inverted(); @@ -1573,7 +1601,7 @@ void EditorThemeManager::_populate_standard_styles(const Ref<EditorTheme> &p_the p_theme->set_color("resizer_color", "GraphNode", gn_decoration_color); - p_theme->set_constant("port_h_offset", "GraphNode", 0); + p_theme->set_constant("port_h_offset", "GraphNode", 1); p_theme->set_constant("separation", "GraphNode", 1 * EDSCALE); Ref<ImageTexture> port_icon = p_theme->get_icon(SNAME("GuiGraphNodePort"), EditorStringName(EditorIcons)); @@ -1584,7 +1612,11 @@ void EditorThemeManager::_populate_standard_styles(const Ref<EditorTheme> &p_the // GraphNode's title Label. p_theme->set_type_variation("GraphNodeTitleLabel", "Label"); p_theme->set_stylebox("normal", "GraphNodeTitleLabel", make_empty_stylebox(0, 0, 0, 0)); - p_theme->set_color("font_color", "GraphNodeTitleLabel", p_config.font_color); + p_theme->set_color("font_color", "GraphNodeTitleLabel", p_config.dark_theme ? p_config.font_color : Color(1, 1, 1)); // Also use a bright font color for light themes. + p_theme->set_color("font_shadow_color", "GraphNodeTitleLabel", Color(0, 0, 0, 0.35)); + p_theme->set_constant("shadow_outline_size", "GraphNodeTitleLabel", 4); + p_theme->set_constant("shadow_offset_x", "GraphNodeTitleLabel", 0); + p_theme->set_constant("shadow_offset_y", "GraphNodeTitleLabel", 1); p_theme->set_constant("line_spacing", "GraphNodeTitleLabel", 3 * EDSCALE); } } @@ -2339,6 +2371,59 @@ void EditorThemeManager::_populate_text_editor_styles(const Ref<EditorTheme> &p_ /* clang-format on */ } +void EditorThemeManager::_populate_visual_shader_styles(const Ref<EditorTheme> &p_theme, ThemeConfiguration &p_config) { + EditorSettings *ed_settings = EditorSettings::get_singleton(); + String visual_shader_color_theme = ed_settings->get("editors/visual_editors/color_theme"); + if (visual_shader_color_theme == "Default") { + // Connection type colors + ed_settings->set_initial_value("editors/visual_editors/connection_colors/scalar_color", Color(0.55, 0.55, 0.55), true); + ed_settings->set_initial_value("editors/visual_editors/connection_colors/vector2_color", Color(0.44, 0.43, 0.64), true); + ed_settings->set_initial_value("editors/visual_editors/connection_colors/vector3_color", Color(0.337, 0.314, 0.71), true); + ed_settings->set_initial_value("editors/visual_editors/connection_colors/vector4_color", Color(0.7, 0.65, 0.147), true); + ed_settings->set_initial_value("editors/visual_editors/connection_colors/boolean_color", Color(0.243, 0.612, 0.349), true); + ed_settings->set_initial_value("editors/visual_editors/connection_colors/transform_color", Color(0.71, 0.357, 0.64), true); + ed_settings->set_initial_value("editors/visual_editors/connection_colors/sampler_color", Color(0.659, 0.4, 0.137), true); + + // Node category colors (used for the node headers) + ed_settings->set_initial_value("editors/visual_editors/category_colors/output_color", Color(0.26, 0.10, 0.15), true); + ed_settings->set_initial_value("editors/visual_editors/category_colors/color_color", Color(0.5, 0.5, 0.1), true); + ed_settings->set_initial_value("editors/visual_editors/category_colors/conditional_color", Color(0.208, 0.522, 0.298), true); + ed_settings->set_initial_value("editors/visual_editors/category_colors/input_color", Color(0.502, 0.2, 0.204), true); + ed_settings->set_initial_value("editors/visual_editors/category_colors/scalar_color", Color(0.1, 0.5, 0.6), true); + ed_settings->set_initial_value("editors/visual_editors/category_colors/textures_color", Color(0.5, 0.3, 0.1), true); + ed_settings->set_initial_value("editors/visual_editors/category_colors/transform_color", Color(0.5, 0.3, 0.5), true); + ed_settings->set_initial_value("editors/visual_editors/category_colors/utility_color", Color(0.2, 0.2, 0.2), true); + ed_settings->set_initial_value("editors/visual_editors/category_colors/vector_color", Color(0.2, 0.2, 0.5), true); + ed_settings->set_initial_value("editors/visual_editors/category_colors/special_color", Color(0.098, 0.361, 0.294), true); + ed_settings->set_initial_value("editors/visual_editors/category_colors/particle_color", Color(0.12, 0.358, 0.8), true); + + } else if (visual_shader_color_theme == "Legacy") { + // Connection type colors + ed_settings->set_initial_value("editors/visual_editors/connection_colors/scalar_color", Color(0.38, 0.85, 0.96), true); + ed_settings->set_initial_value("editors/visual_editors/connection_colors/vector2_color", Color(0.74, 0.57, 0.95), true); + ed_settings->set_initial_value("editors/visual_editors/connection_colors/vector3_color", Color(0.84, 0.49, 0.93), true); + ed_settings->set_initial_value("editors/visual_editors/connection_colors/vector4_color", Color(1.0, 0.125, 0.95), true); + ed_settings->set_initial_value("editors/visual_editors/connection_colors/boolean_color", Color(0.55, 0.65, 0.94), true); + ed_settings->set_initial_value("editors/visual_editors/connection_colors/transform_color", Color(0.96, 0.66, 0.43), true); + ed_settings->set_initial_value("editors/visual_editors/connection_colors/sampler_color", Color(1.0, 1.0, 0.0), true); + + // Node category colors (used for the node headers) + Ref<StyleBoxFlat> gn_panel_style = p_theme->get_stylebox("panel", "GraphNode"); + Color gn_bg_color = gn_panel_style->get_bg_color(); + ed_settings->set_initial_value("editors/visual_editors/category_colors/output_color", gn_bg_color, true); + ed_settings->set_initial_value("editors/visual_editors/category_colors/color_color", gn_bg_color, true); + ed_settings->set_initial_value("editors/visual_editors/category_colors/conditional_color", gn_bg_color, true); + ed_settings->set_initial_value("editors/visual_editors/category_colors/input_color", gn_bg_color, true); + ed_settings->set_initial_value("editors/visual_editors/category_colors/scalar_color", gn_bg_color, true); + ed_settings->set_initial_value("editors/visual_editors/category_colors/textures_color", gn_bg_color, true); + ed_settings->set_initial_value("editors/visual_editors/category_colors/transform_color", gn_bg_color, true); + ed_settings->set_initial_value("editors/visual_editors/category_colors/utility_color", gn_bg_color, true); + ed_settings->set_initial_value("editors/visual_editors/category_colors/vector_color", gn_bg_color, true); + ed_settings->set_initial_value("editors/visual_editors/category_colors/special_color", gn_bg_color, true); + ed_settings->set_initial_value("editors/visual_editors/category_colors/particle_color", gn_bg_color, true); + } +} + void EditorThemeManager::_reset_dirty_flag() { outdated_cache_dirty = true; } @@ -2381,6 +2466,7 @@ bool EditorThemeManager::is_generated_theme_outdated() { EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/code_font") || EditorSettings::get_singleton()->check_changed_settings_in_group("interface/touchscreen/increase_scrollbar_touch_area") || EditorSettings::get_singleton()->check_changed_settings_in_group("interface/touchscreen/scale_gizmo_handles") || + EditorSettings::get_singleton()->check_changed_settings_in_group("editors/visual_editors") || EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor/theme") || EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor/help/help") || EditorSettings::get_singleton()->check_changed_settings_in_group("docks/property_editor/subresource_hue_tint") || diff --git a/editor/themes/editor_theme_manager.h b/editor/themes/editor_theme_manager.h index de088a1011..3eb1dd5ffd 100644 --- a/editor/themes/editor_theme_manager.h +++ b/editor/themes/editor_theme_manager.h @@ -156,6 +156,7 @@ class EditorThemeManager { static void _generate_text_editor_defaults(ThemeConfiguration &p_config); static void _populate_text_editor_styles(const Ref<EditorTheme> &p_theme, ThemeConfiguration &p_config); + static void _populate_visual_shader_styles(const Ref<EditorTheme> &p_theme, ThemeConfiguration &p_config); static void _reset_dirty_flag(); diff --git a/modules/basis_universal/image_compress_basisu.cpp b/modules/basis_universal/image_compress_basisu.cpp index 12856f33c1..72e7977eef 100644 --- a/modules/basis_universal/image_compress_basisu.cpp +++ b/modules/basis_universal/image_compress_basisu.cpp @@ -158,6 +158,8 @@ Ref<Image> basis_universal_unpacker_ptr(const uint8_t *p_data, int p_size) { bool s3tc_supported = RS::get_singleton()->has_os_feature("s3tc"); bool etc2_supported = RS::get_singleton()->has_os_feature("etc2"); + bool needs_ra_rg_swap = false; + switch (*(uint32_t *)(src_ptr)) { case BASIS_DECOMPRESS_RG: { // RGTC transcoding is currently performed with RG_AS_RA, fail. @@ -213,6 +215,7 @@ Ref<Image> basis_universal_unpacker_ptr(const uint8_t *p_data, int p_size) { // No supported VRAM compression formats, decompress. basisu_format = basist::transcoder_texture_format::cTFRGBA32; image_format = Image::FORMAT_RGBA8; + needs_ra_rg_swap = true; } } break; } @@ -228,6 +231,7 @@ Ref<Image> basis_universal_unpacker_ptr(const uint8_t *p_data, int p_size) { basist::basisu_image_info basisu_info; transcoder.get_image_info(src_ptr, src_size, basisu_info, 0); + // Create the buffer for transcoded/decompressed data. Vector<uint8_t> out_data; out_data.resize(Image::get_image_data_size(basisu_info.m_width, basisu_info.m_height, image_format, basisu_info.m_total_levels > 1)); @@ -239,8 +243,10 @@ Ref<Image> basis_universal_unpacker_ptr(const uint8_t *p_data, int p_size) { basist::basisu_image_level_info basisu_level; transcoder.get_image_level_info(src_ptr, src_size, basisu_level, 0, i); + uint32_t mip_block_or_pixel_count = image_format >= Image::FORMAT_DXT1 ? basisu_level.m_total_blocks : basisu_level.m_orig_width * basisu_level.m_orig_height; int ofs = Image::get_image_mipmap_offset(basisu_info.m_width, basisu_info.m_height, image_format, i); - bool result = transcoder.transcode_image_level(src_ptr, src_size, 0, i, dst + ofs, basisu_level.m_total_blocks, basisu_format); + + bool result = transcoder.transcode_image_level(src_ptr, src_size, 0, i, dst + ofs, mip_block_or_pixel_count, basisu_format); if (!result) { print_line(vformat("BasisUniversal cannot unpack level %d.", i)); @@ -250,6 +256,11 @@ Ref<Image> basis_universal_unpacker_ptr(const uint8_t *p_data, int p_size) { image = Image::create_from_data(basisu_info.m_width, basisu_info.m_height, basisu_info.m_total_levels > 1, image_format, out_data); + if (needs_ra_rg_swap) { + // Swap uncompressed RA-as-RG texture's color channels. + image->convert_ra_rgba8_to_rg(); + } + return image; } diff --git a/modules/gdscript/tests/gdscript_test_runner_suite.h b/modules/gdscript/tests/gdscript_test_runner_suite.h index 5acf436e42..b2289ef9cc 100644 --- a/modules/gdscript/tests/gdscript_test_runner_suite.h +++ b/modules/gdscript/tests/gdscript_test_runner_suite.h @@ -37,6 +37,8 @@ namespace GDScriptTests { +// TODO: Handle some cases failing on release builds. See: https://github.com/godotengine/godot/pull/88452 +#ifdef TOOLS_ENABLED TEST_SUITE("[Modules][GDScript]") { TEST_CASE("Script compilation and runtime") { bool print_filenames = OS::get_singleton()->get_cmdline_args().find("--print-filenames") != nullptr; @@ -68,6 +70,7 @@ func _init(): ref_counted->set_script(gdscript); CHECK_MESSAGE(int(ref_counted->get_meta("result")) == 42, "The script should assign object metadata successfully."); } +#endif // TOOLS_ENABLED TEST_CASE("[Modules][GDScript] Validate built-in API") { GDScriptLanguage *lang = GDScriptLanguage::get_singleton(); diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index c23d21775f..b7118d595f 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -52,6 +52,7 @@ constexpr int MINIMAP_PADDING = 5; constexpr int MIN_DRAG_DISTANCE_FOR_VALID_CONNECTION = 20; constexpr int MAX_CONNECTION_LINE_CURVE_TESSELATION_STAGES = 5; constexpr int GRID_MINOR_STEPS_PER_MAJOR_LINE = 10; +constexpr int GRID_MINOR_STEPS_PER_MAJOR_DOT = 5; constexpr int GRID_MIN_SNAPPING_DISTANCE = 2; constexpr int GRID_MAX_SNAPPING_DISTANCE = 100; @@ -1349,13 +1350,13 @@ void GraphEdit::_draw_grid() { } break; case GRID_PATTERN_DOTS: { Color transparent_grid_minor = theme_cache.grid_minor; - transparent_grid_minor.a *= CLAMP(2 * (zoom - 0.4), 0, 1); + transparent_grid_minor.a *= CLAMP(1.0 * (zoom - 0.4), 0, 1); for (int i = from_pos.x; i < from_pos.x + len.x; i++) { for (int j = from_pos.y; j < from_pos.y + len.y; j++) { Color color = transparent_grid_minor; - if (ABS(i) % GRID_MINOR_STEPS_PER_MAJOR_LINE == 0 && ABS(j) % GRID_MINOR_STEPS_PER_MAJOR_LINE == 0) { + if (ABS(i) % GRID_MINOR_STEPS_PER_MAJOR_DOT == 0 && ABS(j) % GRID_MINOR_STEPS_PER_MAJOR_DOT == 0) { color = theme_cache.grid_major; } diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index 218ca6322a..c7c2ddbb18 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -403,6 +403,11 @@ String VisualShaderNode::get_warning(Shader::Mode p_mode, VisualShader::Type p_t return String(); } +VisualShaderNode::Category VisualShaderNode::get_category() const { + WARN_PRINT(get_caption() + " is missing a category."); + return CATEGORY_NONE; +} + bool VisualShaderNode::is_input_port_default(int p_port, Shader::Mode p_mode) const { return false; } diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h index d4d77e7609..09ea9a8890 100644 --- a/scene/resources/visual_shader.h +++ b/scene/resources/visual_shader.h @@ -255,6 +255,37 @@ VARIANT_ENUM_CAST(VisualShader::VaryingType) class VisualShaderNode : public Resource { GDCLASS(VisualShaderNode, Resource); +public: + enum PortType { + PORT_TYPE_SCALAR, + PORT_TYPE_SCALAR_INT, + PORT_TYPE_SCALAR_UINT, + PORT_TYPE_VECTOR_2D, + PORT_TYPE_VECTOR_3D, + PORT_TYPE_VECTOR_4D, + PORT_TYPE_BOOLEAN, + PORT_TYPE_TRANSFORM, + PORT_TYPE_SAMPLER, + PORT_TYPE_MAX, + }; + + enum Category { + CATEGORY_NONE, + CATEGORY_OUTPUT, + CATEGORY_COLOR, + CATEGORY_CONDITIONAL, + CATEGORY_INPUT, + CATEGORY_SCALAR, + CATEGORY_TEXTURES, + CATEGORY_TRANSFORM, + CATEGORY_UTILITY, + CATEGORY_VECTOR, + CATEGORY_SPECIAL, + CATEGORY_PARTICLE, + CATEGORY_MAX + }; + +private: int port_preview = -1; HashMap<int, bool> connected_input_ports; @@ -270,19 +301,6 @@ protected: static void _bind_methods(); public: - enum PortType { - PORT_TYPE_SCALAR, - PORT_TYPE_SCALAR_INT, - PORT_TYPE_SCALAR_UINT, - PORT_TYPE_VECTOR_2D, - PORT_TYPE_VECTOR_3D, - PORT_TYPE_VECTOR_4D, - PORT_TYPE_BOOLEAN, - PORT_TYPE_TRANSFORM, - PORT_TYPE_SAMPLER, - PORT_TYPE_MAX, - }; - bool is_simple_decl() const; virtual String get_caption() const = 0; @@ -348,6 +366,8 @@ public: virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const; + virtual Category get_category() const; + VisualShaderNode(); }; @@ -507,6 +527,8 @@ public: virtual Vector<StringName> get_editable_properties() const override; + virtual Category get_category() const override { return CATEGORY_INPUT; } + VisualShaderNodeInput(); }; @@ -546,6 +568,8 @@ public: virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + virtual Category get_category() const override { return CATEGORY_OUTPUT; } + VisualShaderNodeOutput(); }; @@ -589,6 +613,8 @@ public: virtual Vector<StringName> get_editable_properties() const override; virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const override; + virtual Category get_category() const override { return CATEGORY_INPUT; } + VisualShaderNodeParameter(); }; @@ -661,6 +687,8 @@ public: virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + virtual Category get_category() const override { return CATEGORY_INPUT; } + VisualShaderNodeParameterRef(); }; @@ -713,6 +741,8 @@ public: void set_description(const String &p_description); String get_description() const; + virtual Category get_category() const override { return CATEGORY_SPECIAL; } + VisualShaderNodeComment(); }; @@ -781,6 +811,8 @@ public: virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + virtual Category get_category() const override { return CATEGORY_SPECIAL; } + VisualShaderNodeGroupBase(); }; @@ -887,6 +919,8 @@ public: virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + virtual Category get_category() const override { return CATEGORY_OUTPUT; } + VisualShaderNodeVaryingSetter(); }; @@ -907,6 +941,8 @@ public: virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + virtual Category get_category() const override { return CATEGORY_INPUT; } + VisualShaderNodeVaryingGetter(); }; diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h index 67e2c4633d..05c8fbd16c 100644 --- a/scene/resources/visual_shader_nodes.h +++ b/scene/resources/visual_shader_nodes.h @@ -76,6 +76,8 @@ public: virtual Vector<StringName> get_editable_properties() const override; + virtual Category get_category() const override { return CATEGORY_VECTOR; } + VisualShaderNodeVectorBase(); }; @@ -101,6 +103,8 @@ public: virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override = 0; + virtual Category get_category() const override { return CATEGORY_INPUT; } + VisualShaderNodeConstant(); }; @@ -437,6 +441,8 @@ public: virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const override; + virtual Category get_category() const override { return CATEGORY_TEXTURES; } + VisualShaderNodeTexture(); }; @@ -473,6 +479,8 @@ public: virtual Vector<StringName> get_editable_properties() const override; virtual bool is_use_prop_slots() const override; + virtual Category get_category() const override { return CATEGORY_TEXTURES; } + VisualShaderNodeCurveTexture(); }; @@ -543,6 +551,8 @@ public: virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const override; + virtual Category get_category() const override { return CATEGORY_TEXTURES; } + VisualShaderNodeSample3D(); }; @@ -671,8 +681,11 @@ public: virtual bool has_output_port_preview(int p_port) const override; virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + virtual Category get_category() const override { return CATEGORY_TEXTURES; } + VisualShaderNodeLinearSceneDepth(); }; @@ -695,6 +708,8 @@ public: virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + virtual Category get_category() const override { return CATEGORY_TEXTURES; } + VisualShaderNodeWorldPositionFromDepth(); }; @@ -717,6 +732,8 @@ public: virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + virtual Category get_category() const override { return CATEGORY_TEXTURES; } + VisualShaderNodeScreenNormalWorldSpace(); }; @@ -765,6 +782,8 @@ public: virtual Vector<StringName> get_editable_properties() const override; + virtual Category get_category() const override { return CATEGORY_SCALAR; } + VisualShaderNodeFloatOp(); }; @@ -957,6 +976,8 @@ public: virtual Vector<StringName> get_editable_properties() const override; + virtual Category get_category() const override { return CATEGORY_COLOR; } + VisualShaderNodeColorOp(); }; @@ -1006,6 +1027,8 @@ public: virtual Vector<StringName> get_editable_properties() const override; + virtual Category get_category() const override { return CATEGORY_TRANSFORM; } + VisualShaderNodeTransformOp(); }; @@ -1050,6 +1073,8 @@ public: virtual Vector<StringName> get_editable_properties() const override; + virtual Category get_category() const override { return CATEGORY_TRANSFORM; } + VisualShaderNodeTransformVecMult(); }; @@ -1122,6 +1147,8 @@ public: virtual Vector<StringName> get_editable_properties() const override; + virtual Category get_category() const override { return CATEGORY_SCALAR; } + VisualShaderNodeFloatFunc(); }; @@ -1166,6 +1193,8 @@ public: virtual Vector<StringName> get_editable_properties() const override; + virtual Category get_category() const override { return CATEGORY_SCALAR; } + VisualShaderNodeIntFunc(); }; @@ -1208,6 +1237,8 @@ public: virtual Vector<StringName> get_editable_properties() const override; + virtual Category get_category() const override { return CATEGORY_SCALAR; } + VisualShaderNodeUIntFunc(); }; @@ -1327,6 +1358,8 @@ public: virtual Vector<StringName> get_editable_properties() const override; + virtual Category get_category() const override { return CATEGORY_COLOR; } + VisualShaderNodeColorFunc(); }; @@ -1369,6 +1402,8 @@ public: virtual Vector<StringName> get_editable_properties() const override; + virtual Category get_category() const override { return CATEGORY_TRANSFORM; } + VisualShaderNodeTransformFunc(); }; @@ -1414,6 +1449,8 @@ public: virtual Vector<StringName> get_editable_properties() const override; + virtual Category get_category() const override { return CATEGORY_TEXTURES; } + VisualShaderNodeUVFunc(); }; @@ -1440,6 +1477,8 @@ public: virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + virtual Category get_category() const override { return CATEGORY_TEXTURES; } + VisualShaderNodeUVPolarCoord(); }; @@ -1620,6 +1659,8 @@ public: virtual Vector<StringName> get_editable_properties() const override; + virtual Category get_category() const override { return CATEGORY_UTILITY; } + VisualShaderNodeDerivativeFunc(); }; @@ -1669,6 +1710,8 @@ public: virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + virtual Category get_category() const override { return CATEGORY_TRANSFORM; } + VisualShaderNodeOuterProduct(); }; @@ -1714,6 +1757,14 @@ public: virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + virtual Category get_category() const override { + if (op_type == OP_TYPE_SCALAR) { + return CATEGORY_SCALAR; + } else { + return CATEGORY_VECTOR; + } + } + VisualShaderNodeStep(); }; @@ -1761,6 +1812,14 @@ public: virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + virtual Category get_category() const override { + if (op_type == OP_TYPE_SCALAR) { + return CATEGORY_SCALAR; + } else { + return CATEGORY_VECTOR; + } + } + VisualShaderNodeSmoothStep(); }; @@ -1852,6 +1911,14 @@ public: virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + virtual Category get_category() const override { + if (op_type == OP_TYPE_SCALAR) { + return CATEGORY_SCALAR; + } else { + return CATEGORY_VECTOR; + } + } + VisualShaderNodeMix(); }; @@ -1898,6 +1965,8 @@ public: virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + virtual Category get_category() const override { return CATEGORY_TRANSFORM; } + VisualShaderNodeTransformCompose(); }; @@ -1921,6 +1990,8 @@ public: virtual void set_op_type(OpType p_op_type) override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + virtual Category get_category() const override { return CATEGORY_VECTOR; } + VisualShaderNodeVectorDecompose(); }; @@ -1942,6 +2013,8 @@ public: virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + virtual Category get_category() const override { return CATEGORY_TRANSFORM; } + VisualShaderNodeTransformDecompose(); }; @@ -2584,6 +2657,8 @@ public: virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + virtual Category get_category() const override { return CATEGORY_CONDITIONAL; } + VisualShaderNodeIf(); }; @@ -2630,6 +2705,8 @@ public: virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + virtual Category get_category() const override { return CATEGORY_CONDITIONAL; } + VisualShaderNodeSwitch(); }; @@ -2698,6 +2775,8 @@ public: virtual Vector<StringName> get_editable_properties() const override; + virtual Category get_category() const override { return CATEGORY_CONDITIONAL; } + VisualShaderNodeIs(); }; @@ -2772,6 +2851,8 @@ public: virtual Vector<StringName> get_editable_properties() const override; virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const override; + virtual Category get_category() const override { return CATEGORY_CONDITIONAL; } + VisualShaderNodeCompare(); }; @@ -2815,6 +2896,14 @@ public: virtual Vector<StringName> get_editable_properties() const override; + virtual Category get_category() const override { + if (op_type == OP_TYPE_SCALAR) { + return CATEGORY_SCALAR; + } else { + return CATEGORY_VECTOR; + } + } + VisualShaderNodeMultiplyAdd(); }; @@ -2862,6 +2951,8 @@ public: virtual Vector<StringName> get_editable_properties() const override; + virtual Category get_category() const override { return CATEGORY_UTILITY; } + VisualShaderNodeBillboard(); }; @@ -2888,6 +2979,8 @@ public: virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + virtual Category get_category() const override { return CATEGORY_UTILITY; } + VisualShaderNodeDistanceFade(); }; @@ -2909,6 +3002,8 @@ public: virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + virtual Category get_category() const override { return CATEGORY_UTILITY; } + VisualShaderNodeProximityFade(); }; @@ -2929,6 +3024,8 @@ public: virtual String generate_global_per_node(Shader::Mode p_mode, int p_id) const override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + virtual Category get_category() const override { return CATEGORY_UTILITY; } + VisualShaderNodeRandomRange(); }; @@ -2948,6 +3045,8 @@ public: virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + virtual Category get_category() const override { return CATEGORY_UTILITY; } + VisualShaderNodeRemap(); }; @@ -2968,6 +3067,8 @@ public: virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + virtual Category get_category() const override { return CATEGORY_UTILITY; } + VisualShaderNodeRotationByAxis(); }; diff --git a/scene/resources/visual_shader_particle_nodes.h b/scene/resources/visual_shader_particle_nodes.h index 652b5dff03..23d06d4b7c 100644 --- a/scene/resources/visual_shader_particle_nodes.h +++ b/scene/resources/visual_shader_particle_nodes.h @@ -57,6 +57,8 @@ public: virtual HashMap<StringName, String> get_editable_properties_names() const override; bool is_show_prop_names() const override; + virtual Category get_category() const override { return CATEGORY_PARTICLE; } + VisualShaderNodeParticleEmitter(); }; @@ -73,6 +75,8 @@ public: virtual String generate_global_per_node(Shader::Mode p_mode, int p_id) const override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + virtual Category get_category() const override { return CATEGORY_PARTICLE; } + VisualShaderNodeParticleSphereEmitter(); }; @@ -90,6 +94,8 @@ public: virtual String generate_global_per_node(Shader::Mode p_mode, int p_id) const override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + virtual Category get_category() const override { return CATEGORY_PARTICLE; } + VisualShaderNodeParticleBoxEmitter(); }; @@ -106,6 +112,8 @@ public: virtual String generate_global_per_node(Shader::Mode p_mode, int p_id) const override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + virtual Category get_category() const override { return CATEGORY_PARTICLE; } + VisualShaderNodeParticleRingEmitter(); }; @@ -158,6 +166,8 @@ public: HashMap<StringName, String> get_editable_properties_names() const override; Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) const override; + virtual Category get_category() const override { return CATEGORY_PARTICLE; } + VisualShaderNodeParticleMeshEmitter(); }; @@ -187,6 +197,8 @@ public: bool is_degrees_mode() const; Vector<StringName> get_editable_properties() const override; + virtual Category get_category() const override { return CATEGORY_PARTICLE; } + VisualShaderNodeParticleMultiplyByAxisAngle(); }; @@ -207,6 +219,8 @@ public: virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + virtual Category get_category() const override { return CATEGORY_PARTICLE; } + VisualShaderNodeParticleConeVelocity(); }; @@ -248,6 +262,8 @@ public: void set_op_type(OpType p_type); OpType get_op_type() const; + virtual Category get_category() const override { return CATEGORY_PARTICLE; } + VisualShaderNodeParticleRandomness(); }; @@ -290,6 +306,8 @@ public: void set_mode(Mode p_mode); Mode get_mode() const; + virtual Category get_category() const override { return CATEGORY_PARTICLE; } + VisualShaderNodeParticleAccelerator(); }; @@ -352,6 +370,8 @@ public: virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + virtual Category get_category() const override { return CATEGORY_PARTICLE; } + VisualShaderNodeParticleEmit(); }; diff --git a/tests/core/config/test_project_settings.h b/tests/core/config/test_project_settings.h index 9bd072f511..8fc2489f8b 100644 --- a/tests/core/config/test_project_settings.h +++ b/tests/core/config/test_project_settings.h @@ -45,6 +45,8 @@ public: namespace TestProjectSettings { +// TODO: Handle some cases failing on release builds. See: https://github.com/godotengine/godot/pull/88452 +#ifdef TOOLS_ENABLED TEST_CASE("[ProjectSettings] Get existing setting") { CHECK(ProjectSettings::get_singleton()->has_setting("application/config/name")); @@ -64,6 +66,7 @@ TEST_CASE("[ProjectSettings] Default value is ignored if setting exists") { String name = variant; CHECK_EQ(name, "GDScript Integration Test Suite"); } +#endif // TOOLS_ENABLED TEST_CASE("[ProjectSettings] Non existing setting is null") { CHECK_FALSE(ProjectSettings::get_singleton()->has_setting("not_existing_setting")); diff --git a/tests/core/io/test_image.h b/tests/core/io/test_image.h index 945a7e1ba3..35d182f50c 100644 --- a/tests/core/io/test_image.h +++ b/tests/core/io/test_image.h @@ -88,11 +88,14 @@ TEST_CASE("[Image] Saving and loading") { err == OK, "The image should be saved successfully as a .png file."); + // Only available on editor builds. +#ifdef TOOLS_ENABLED // Save EXR err = image->save_exr(save_path_exr, false); CHECK_MESSAGE( err == OK, "The image should be saved successfully as an .exr file."); +#endif // TOOLS_ENABLED // Load using load() Ref<Image> image_load = memnew(Image()); diff --git a/tests/core/os/test_os.h b/tests/core/os/test_os.h index ef8216685f..1a5d360f57 100644 --- a/tests/core/os/test_os.h +++ b/tests/core/os/test_os.h @@ -93,6 +93,7 @@ TEST_CASE("[OS] Ticks") { } TEST_CASE("[OS] Feature tags") { +#ifdef TOOLS_ENABLED CHECK_MESSAGE( OS::get_singleton()->has_feature("editor"), "The binary has the \"editor\" feature tag."); @@ -105,6 +106,29 @@ TEST_CASE("[OS] Feature tags") { CHECK_MESSAGE( !OS::get_singleton()->has_feature("template_release"), "The binary does not have the \"template_release\" feature tag."); +#else + CHECK_MESSAGE( + !OS::get_singleton()->has_feature("editor"), + "The binary does not have the \"editor\" feature tag."); + CHECK_MESSAGE( + OS::get_singleton()->has_feature("template"), + "The binary has the \"template\" feature tag."); +#ifdef DEBUG_ENABLED + CHECK_MESSAGE( + OS::get_singleton()->has_feature("template_debug"), + "The binary has the \"template_debug\" feature tag."); + CHECK_MESSAGE( + !OS::get_singleton()->has_feature("template_release"), + "The binary does not have the \"template_release\" feature tag."); +#else + CHECK_MESSAGE( + !OS::get_singleton()->has_feature("template_debug"), + "The binary does not have the \"template_debug\" feature tag."); + CHECK_MESSAGE( + OS::get_singleton()->has_feature("template_release"), + "The binary has the \"template_release\" feature tag."); +#endif // DEBUG_ENABLED +#endif // TOOLS_ENABLED } TEST_CASE("[OS] Process ID") { diff --git a/tests/core/string/test_translation.h b/tests/core/string/test_translation.h index bf9674d6b1..acdd851b29 100644 --- a/tests/core/string/test_translation.h +++ b/tests/core/string/test_translation.h @@ -129,6 +129,7 @@ TEST_CASE("[TranslationPO] Plural messages") { CHECK(vformat(translation->get_plural_message("There are %d apples", "", 2), 2) == "Il y a 2 pommes"); } +#ifdef TOOLS_ENABLED TEST_CASE("[OptimizedTranslation] Generate from Translation and read messages") { Ref<Translation> translation = memnew(Translation); translation->set_locale("fr"); @@ -150,7 +151,6 @@ TEST_CASE("[OptimizedTranslation] Generate from Translation and read messages") CHECK(messages.size() == 0); } -#ifdef TOOLS_ENABLED TEST_CASE("[TranslationCSV] CSV import") { Ref<ResourceImporterCSVTranslation> import_csv_translation = memnew(ResourceImporterCSVTranslation); |