summaryrefslogtreecommitdiffstats
path: root/editor/plugins/node_3d_editor_plugin.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'editor/plugins/node_3d_editor_plugin.cpp')
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp180
1 files changed, 114 insertions, 66 deletions
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 52f17c4a45..e4d24832bf 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -1839,17 +1839,17 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
clicked = ObjectID();
- if ((spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT && b->is_command_or_control_pressed()) || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE) {
+ if (can_select_gizmos && ((spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT && b->is_command_or_control_pressed()) || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE)) {
begin_transform(TRANSFORM_ROTATE, false);
break;
}
- if (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_MOVE) {
+ if (can_select_gizmos && spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_MOVE) {
begin_transform(TRANSFORM_TRANSLATE, false);
break;
}
- if (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SCALE) {
+ if (can_select_gizmos && spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SCALE) {
begin_transform(TRANSFORM_SCALE, false);
break;
}
@@ -2734,11 +2734,11 @@ void Node3DEditorViewport::_notification(int p_what) {
} else {
set_freelook_active(false);
}
- call_deferred(SNAME("update_transform_gizmo_view"));
+ callable_mp(this, &Node3DEditorViewport::update_transform_gizmo_view).call_deferred();
} break;
case NOTIFICATION_RESIZED: {
- call_deferred(SNAME("update_transform_gizmo_view"));
+ callable_mp(this, &Node3DEditorViewport::update_transform_gizmo_view).call_deferred();
} break;
case NOTIFICATION_PROCESS: {
@@ -3355,7 +3355,7 @@ void Node3DEditorViewport::_menu_option(int p_option) {
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_ORTHOGONAL), false);
orthogonal = false;
auto_orthogonal = false;
- call_deferred(SNAME("update_transform_gizmo_view"));
+ callable_mp(this, &Node3DEditorViewport::update_transform_gizmo_view).call_deferred();
_update_camera(0);
_update_name();
@@ -3365,7 +3365,7 @@ void Node3DEditorViewport::_menu_option(int p_option) {
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_ORTHOGONAL), true);
orthogonal = true;
auto_orthogonal = false;
- call_deferred(SNAME("update_transform_gizmo_view"));
+ callable_mp(this, &Node3DEditorViewport::update_transform_gizmo_view).call_deferred();
_update_camera(0);
_update_name();
} break;
@@ -3985,8 +3985,6 @@ Dictionary Node3DEditorViewport::get_state() const {
}
void Node3DEditorViewport::_bind_methods() {
- ClassDB::bind_method(D_METHOD("update_transform_gizmo_view"), &Node3DEditorViewport::update_transform_gizmo_view); // Used by call_deferred.
-
ADD_SIGNAL(MethodInfo("toggle_maximize_view", PropertyInfo(Variant::OBJECT, "viewport")));
ADD_SIGNAL(MethodInfo("clicked", PropertyInfo(Variant::OBJECT, "viewport")));
}
@@ -4247,17 +4245,16 @@ bool Node3DEditorViewport::_apply_preview_material(ObjectID p_target, const Poin
return false;
}
- if (spatial_editor->get_preview_material() != mesh_instance->get_surface_override_material(closest_surface)) {
- spatial_editor->set_preview_material_surface(closest_surface);
- spatial_editor->set_preview_reset_material(mesh_instance->get_surface_override_material(closest_surface));
- mesh_instance->set_surface_override_material(closest_surface, spatial_editor->get_preview_material());
- }
+ spatial_editor->set_preview_material_surface(closest_surface);
+ spatial_editor->set_preview_reset_material(mesh_instance->get_surface_override_material(closest_surface));
+ mesh_instance->set_surface_override_material(closest_surface, spatial_editor->get_preview_material());
return true;
}
GeometryInstance3D *geometry_instance = Object::cast_to<GeometryInstance3D>(target_inst);
- if (geometry_instance && spatial_editor->get_preview_material() != geometry_instance->get_material_override()) {
+ if (geometry_instance) {
+ spatial_editor->set_preview_material_surface(-1);
spatial_editor->set_preview_reset_material(geometry_instance->get_material_override());
geometry_instance->set_material_override(spatial_editor->get_preview_material());
return true;
@@ -4277,7 +4274,6 @@ void Node3DEditorViewport::_reset_preview_material() const {
GeometryInstance3D *geometry_instance = Object::cast_to<GeometryInstance3D>(last_target_inst);
if (mesh_instance && spatial_editor->get_preview_material_surface() != -1) {
mesh_instance->set_surface_override_material(spatial_editor->get_preview_material_surface(), spatial_editor->get_preview_reset_material());
- spatial_editor->set_preview_material_surface(-1);
} else if (geometry_instance) {
geometry_instance->set_material_override(spatial_editor->get_preview_reset_material());
}
@@ -6489,25 +6485,91 @@ void Node3DEditor::_init_indicators() {
origin_enabled = true;
grid_enabled = true;
- indicator_mat.instantiate();
- indicator_mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
- indicator_mat->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
- indicator_mat->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
- indicator_mat->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true);
- indicator_mat->set_transparency(StandardMaterial3D::Transparency::TRANSPARENCY_ALPHA_DEPTH_PRE_PASS);
+ Ref<Shader> origin_shader = memnew(Shader);
+ origin_shader->set_code(R"(
+// 3D editor origin line shader.
+
+shader_type spatial;
+render_mode blend_mix,cull_disabled,unshaded, fog_disabled;
+
+void vertex() {
+ vec3 point_a = MODEL_MATRIX[3].xyz;
+ // Encoded in scale.
+ vec3 point_b = vec3(MODEL_MATRIX[0].x, MODEL_MATRIX[1].y, MODEL_MATRIX[2].z);
+
+ // Points are already in world space, so no need for MODEL_MATRIX anymore.
+ vec4 clip_a = PROJECTION_MATRIX * (VIEW_MATRIX * vec4(point_a, 1.0));
+ vec4 clip_b = PROJECTION_MATRIX * (VIEW_MATRIX * vec4(point_b, 1.0));
+
+ vec2 screen_a = VIEWPORT_SIZE * (0.5 * clip_a.xy / clip_a.w + 0.5);
+ vec2 screen_b = VIEWPORT_SIZE * (0.5 * clip_b.xy / clip_b.w + 0.5);
+
+ vec2 x_basis = normalize(screen_b - screen_a);
+ vec2 y_basis = vec2(-x_basis.y, x_basis.x);
+
+ float width = 3.0;
+ vec2 screen_point_a = screen_a + width * (VERTEX.x * x_basis + VERTEX.y * y_basis);
+ vec2 screen_point_b = screen_b + width * (VERTEX.x * x_basis + VERTEX.y * y_basis);
+ vec2 screen_point_final = mix(screen_point_a, screen_point_b, VERTEX.z);
+
+ vec4 clip_final = mix(clip_a, clip_b, VERTEX.z);
+
+ POSITION = vec4(clip_final.w * ((2.0 * screen_point_final) / VIEWPORT_SIZE - 1.0), clip_final.z, clip_final.w);
+ UV = VERTEX.yz * clip_final.w;
+
+ if (!OUTPUT_IS_SRGB) {
+ COLOR.rgb = mix(pow((COLOR.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), COLOR.rgb * (1.0 / 12.92), lessThan(COLOR.rgb, vec3(0.04045)));
+ }
+}
+
+void fragment() {
+ // Multiply by 0.5 since UV is actually UV is [-1, 1].
+ float line_width = fwidth(UV.x * 0.5);
+ float line_uv = abs(UV.x * 0.5);
+ float line = smoothstep(line_width * 1.0, line_width * 0.25, line_uv);
+
+ ALBEDO = COLOR.rgb;
+ ALPHA *= COLOR.a * line;
+}
+)");
+
+ origin_mat.instantiate();
+ origin_mat->set_shader(origin_shader);
- Vector<Color> origin_colors;
Vector<Vector3> origin_points;
+ origin_points.resize(6);
+
+ origin_points.set(0, Vector3(0.0, -0.5, 0.0));
+ origin_points.set(1, Vector3(0.0, -0.5, 1.0));
+ origin_points.set(2, Vector3(0.0, 0.5, 1.0));
+
+ origin_points.set(3, Vector3(0.0, -0.5, 0.0));
+ origin_points.set(4, Vector3(0.0, 0.5, 1.0));
+ origin_points.set(5, Vector3(0.0, 0.5, 0.0));
+
+ Array d;
+ d.resize(RS::ARRAY_MAX);
+ d[RenderingServer::ARRAY_VERTEX] = origin_points;
- const int count_of_elements = 3 * 6;
- origin_colors.resize(count_of_elements);
- origin_points.resize(count_of_elements);
+ origin_mesh = RenderingServer::get_singleton()->mesh_create();
- int x = 0;
+ RenderingServer::get_singleton()->mesh_add_surface_from_arrays(origin_mesh, RenderingServer::PRIMITIVE_TRIANGLES, d);
+ RenderingServer::get_singleton()->mesh_surface_set_material(origin_mesh, 0, origin_mat->get_rid());
+
+ origin_multimesh = RenderingServer::get_singleton()->multimesh_create();
+ RenderingServer::get_singleton()->multimesh_set_mesh(origin_multimesh, origin_mesh);
+ RenderingServer::get_singleton()->multimesh_allocate_data(origin_multimesh, 12, RS::MultimeshTransformFormat::MULTIMESH_TRANSFORM_3D, true, false);
+ RenderingServer::get_singleton()->multimesh_set_visible_instances(origin_multimesh, -1);
+
+ LocalVector<float> distances;
+ distances.resize(5);
+ distances[0] = -1000000.0;
+ distances[1] = -1000.0;
+ distances[2] = 0.0;
+ distances[3] = 1000.0;
+ distances[4] = 1000000.0;
for (int i = 0; i < 3; i++) {
- Vector3 axis;
- axis[i] = 1;
Color origin_color;
switch (i) {
case 0:
@@ -6524,27 +6586,26 @@ void Node3DEditor::_init_indicators() {
break;
}
- grid_enable[i] = false;
- grid_visible[i] = false;
+ Vector3 axis;
+ axis[i] = 1;
- origin_colors.set(x, origin_color);
- origin_colors.set(x + 1, origin_color);
- origin_colors.set(x + 2, origin_color);
- origin_colors.set(x + 3, origin_color);
- origin_colors.set(x + 4, origin_color);
- origin_colors.set(x + 5, origin_color);
- // To both allow having a large origin size and avoid jitter
- // at small scales, we should segment the line into pieces.
- // 3 pieces seems to do the trick, and let's use powers of 2.
- origin_points.set(x, axis * 1048576);
- origin_points.set(x + 1, axis * 1024);
- origin_points.set(x + 2, axis * 1024);
- origin_points.set(x + 3, axis * -1024);
- origin_points.set(x + 4, axis * -1024);
- origin_points.set(x + 5, axis * -1048576);
- x += 6;
+ for (int j = 0; j < 4; j++) {
+ Transform3D t = Transform3D();
+ t = t.scaled(axis * distances[j + 1]);
+ t = t.translated(axis * distances[j]);
+ RenderingServer::get_singleton()->multimesh_instance_set_transform(origin_multimesh, i * 4 + j, t);
+ RenderingServer::get_singleton()->multimesh_instance_set_color(origin_multimesh, i * 4 + j, origin_color);
+ }
}
+ origin_instance = RenderingServer::get_singleton()->instance_create2(origin_multimesh, get_tree()->get_root()->get_world_3d()->get_scenario());
+ RS::get_singleton()->instance_set_layer_mask(origin_instance, 1 << Node3DEditorViewport::GIZMO_GRID_LAYER);
+ RS::get_singleton()->instance_geometry_set_flag(origin_instance, RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true);
+ RS::get_singleton()->instance_geometry_set_flag(origin_instance, RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false);
+ RS::get_singleton()->instance_set_ignore_culling(origin_instance, true);
+
+ RenderingServer::get_singleton()->instance_geometry_set_cast_shadows_setting(origin_instance, RS::SHADOW_CASTING_SETTING_OFF);
+
Ref<Shader> grid_shader = memnew(Shader);
grid_shader->set_code(R"(
// 3D editor grid shader.
@@ -6593,22 +6654,6 @@ void fragment() {
grid_visible[2] = grid_enable[2];
_init_grid();
-
- origin = RenderingServer::get_singleton()->mesh_create();
- Array d;
- d.resize(RS::ARRAY_MAX);
- d[RenderingServer::ARRAY_VERTEX] = origin_points;
- d[RenderingServer::ARRAY_COLOR] = origin_colors;
-
- RenderingServer::get_singleton()->mesh_add_surface_from_arrays(origin, RenderingServer::PRIMITIVE_LINES, d);
- RenderingServer::get_singleton()->mesh_surface_set_material(origin, 0, indicator_mat->get_rid());
-
- origin_instance = RenderingServer::get_singleton()->instance_create2(origin, get_tree()->get_root()->get_world_3d()->get_scenario());
- RS::get_singleton()->instance_set_layer_mask(origin_instance, 1 << Node3DEditorViewport::GIZMO_GRID_LAYER);
- RS::get_singleton()->instance_geometry_set_flag(origin_instance, RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true);
- RS::get_singleton()->instance_geometry_set_flag(origin_instance, RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false);
-
- RenderingServer::get_singleton()->instance_geometry_set_cast_shadows_setting(origin_instance, RS::SHADOW_CASTING_SETTING_OFF);
}
{
@@ -7226,7 +7271,8 @@ void Node3DEditor::_init_grid() {
void Node3DEditor::_finish_indicators() {
RenderingServer::get_singleton()->free(origin_instance);
- RenderingServer::get_singleton()->free(origin);
+ RenderingServer::get_singleton()->free(origin_multimesh);
+ RenderingServer::get_singleton()->free(origin_mesh);
_finish_grid();
}
@@ -8013,6 +8059,8 @@ void Node3DEditor::_bind_methods() {
ClassDB::bind_method("_clear_subgizmo_selection", &Node3DEditor::_clear_subgizmo_selection);
ClassDB::bind_method("_refresh_menu_icons", &Node3DEditor::_refresh_menu_icons);
+ ClassDB::bind_method("update_all_gizmos", &Node3DEditor::update_all_gizmos);
+
ADD_SIGNAL(MethodInfo("transform_key_request"));
ADD_SIGNAL(MethodInfo("item_lock_status_changed"));
ADD_SIGNAL(MethodInfo("item_group_status_changed"));
@@ -8300,7 +8348,7 @@ Node3DEditor::Node3DEditor() {
main_menu_hbox->add_child(tool_button[TOOL_GROUP_SELECTED]);
tool_button[TOOL_GROUP_SELECTED]->set_theme_type_variation("FlatButton");
tool_button[TOOL_GROUP_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_GROUP_SELECTED));
- tool_button[TOOL_GROUP_SELECTED]->set_tooltip_text(TTR("Make selected node's children not selectable."));
+ tool_button[TOOL_GROUP_SELECTED]->set_tooltip_text(TTR("Groups the selected node with its children. This selects the parent when any child node is clicked in 2D and 3D view."));
// Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused.
tool_button[TOOL_GROUP_SELECTED]->set_shortcut(ED_SHORTCUT("editor/group_selected_nodes", TTR("Group Selected Node(s)"), KeyModifierMask::CMD_OR_CTRL | Key::G));
@@ -8308,7 +8356,7 @@ Node3DEditor::Node3DEditor() {
main_menu_hbox->add_child(tool_button[TOOL_UNGROUP_SELECTED]);
tool_button[TOOL_UNGROUP_SELECTED]->set_theme_type_variation("FlatButton");
tool_button[TOOL_UNGROUP_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_UNGROUP_SELECTED));
- tool_button[TOOL_UNGROUP_SELECTED]->set_tooltip_text(TTR("Make selected node's children selectable."));
+ tool_button[TOOL_UNGROUP_SELECTED]->set_tooltip_text(TTR("Ungroups the selected node from its children. Child nodes will be individual items in 2D and 3D view."));
// Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused.
tool_button[TOOL_UNGROUP_SELECTED]->set_shortcut(ED_SHORTCUT("editor/ungroup_selected_nodes", TTR("Ungroup Selected Node(s)"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::G));