diff options
Diffstat (limited to 'editor/plugins/node_3d_editor_plugin.cpp')
-rw-r--r-- | editor/plugins/node_3d_editor_plugin.cpp | 180 |
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)); |