diff options
40 files changed, 490 insertions, 139 deletions
diff --git a/core/math/basis.cpp b/core/math/basis.cpp index 6159e78bab..a9b4651664 100644 --- a/core/math/basis.cpp +++ b/core/math/basis.cpp @@ -94,6 +94,18 @@ Basis Basis::orthonormalized() const { return c; } +void Basis::orthogonalize() { + Vector3 scl = get_scale(); + orthonormalize(); + scale_local(scl); +} + +Basis Basis::orthogonalized() const { + Basis c = *this; + c.orthogonalize(); + return c; +} + bool Basis::is_orthogonal() const { Basis identity; Basis m = (*this) * transposed(); @@ -237,6 +249,24 @@ void Basis::scale_local(const Vector3 &p_scale) { *this = scaled_local(p_scale); } +void Basis::scale_orthogonal(const Vector3 &p_scale) { + *this = scaled_orthogonal(p_scale); +} + +Basis Basis::scaled_orthogonal(const Vector3 &p_scale) const { + Basis m = *this; + Vector3 s = Vector3(-1, -1, -1) + p_scale; + Vector3 dots; + Basis b; + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + dots[j] += s[i] * abs(m.get_axis(i).normalized().dot(b.get_axis(j))); + } + } + m.scale_local(Vector3(1, 1, 1) + dots); + return m; +} + float Basis::get_uniform_scale() const { return (elements[0].length() + elements[1].length() + elements[2].length()) / 3.0; } @@ -931,6 +961,15 @@ void Basis::_set_diagonal(const Vector3 &p_diag) { elements[2][2] = p_diag.z; } +Basis Basis::lerp(const Basis &p_to, const real_t &p_weight) const { + Basis b; + b.elements[0] = elements[0].lerp(p_to.elements[0], p_weight); + b.elements[1] = elements[1].lerp(p_to.elements[1], p_weight); + b.elements[2] = elements[2].lerp(p_to.elements[2], p_weight); + + return b; +} + Basis Basis::slerp(const Basis &p_to, const real_t &p_weight) const { //consider scale Quaternion from(*this); diff --git a/core/math/basis.h b/core/math/basis.h index 48367631d5..709f2cb3cf 100644 --- a/core/math/basis.h +++ b/core/math/basis.h @@ -123,6 +123,9 @@ public: void scale_local(const Vector3 &p_scale); Basis scaled_local(const Vector3 &p_scale) const; + void scale_orthogonal(const Vector3 &p_scale); + Basis scaled_orthogonal(const Vector3 &p_scale) const; + void make_scale_uniform(); float get_uniform_scale() const; @@ -168,6 +171,7 @@ public: bool is_diagonal() const; bool is_rotation() const; + Basis lerp(const Basis &p_to, const real_t &p_weight) const; Basis slerp(const Basis &p_to, const real_t &p_weight) const; void rotate_sh(real_t *p_values); @@ -233,6 +237,9 @@ public: void orthonormalize(); Basis orthonormalized() const; + void orthogonalize(); + Basis orthogonalized() const; + #ifdef MATH_CHECKS bool is_symmetric() const; #endif diff --git a/core/math/transform_3d.cpp b/core/math/transform_3d.cpp index 1e0ee13504..e5374315e2 100644 --- a/core/math/transform_3d.cpp +++ b/core/math/transform_3d.cpp @@ -80,9 +80,11 @@ void Transform3D::set_look_at(const Vector3 &p_eye, const Vector3 &p_target, con origin = p_eye; } -Transform3D Transform3D::interpolate_with(const Transform3D &p_transform, real_t p_c) const { +Transform3D Transform3D::sphere_interpolate_with(const Transform3D &p_transform, real_t p_c) const { /* not sure if very "efficient" but good enough? */ + Transform3D interp; + Vector3 src_scale = basis.get_scale(); Quaternion src_rot = basis.get_rotation_quaternion(); Vector3 src_loc = origin; @@ -91,13 +93,21 @@ Transform3D Transform3D::interpolate_with(const Transform3D &p_transform, real_t Quaternion dst_rot = p_transform.basis.get_rotation_quaternion(); Vector3 dst_loc = p_transform.origin; - Transform3D interp; interp.basis.set_quaternion_scale(src_rot.slerp(dst_rot, p_c).normalized(), src_scale.lerp(dst_scale, p_c)); interp.origin = src_loc.lerp(dst_loc, p_c); return interp; } +Transform3D Transform3D::interpolate_with(const Transform3D &p_transform, real_t p_c) const { + Transform3D interp; + + interp.basis = basis.lerp(p_transform.basis, p_c); + interp.origin = origin.lerp(p_transform.origin, p_c); + + return interp; +} + void Transform3D::scale(const Vector3 &p_scale) { basis.scale(p_scale); origin *= p_scale; @@ -139,6 +149,16 @@ Transform3D Transform3D::orthonormalized() const { return _copy; } +void Transform3D::orthogonalize() { + basis.orthogonalize(); +} + +Transform3D Transform3D::orthogonalized() const { + Transform3D _copy = *this; + _copy.orthogonalize(); + return _copy; +} + bool Transform3D::is_equal_approx(const Transform3D &p_transform) const { return basis.is_equal_approx(p_transform.basis) && origin.is_equal_approx(p_transform.origin); } diff --git a/core/math/transform_3d.h b/core/math/transform_3d.h index 4356aa4e79..c0ef2ecfc1 100644 --- a/core/math/transform_3d.h +++ b/core/math/transform_3d.h @@ -69,6 +69,8 @@ public: void orthonormalize(); Transform3D orthonormalized() const; + void orthogonalize(); + Transform3D orthogonalized() const; bool is_equal_approx(const Transform3D &p_transform) const; bool operator==(const Transform3D &p_transform) const; @@ -99,6 +101,7 @@ public: void operator*=(const real_t p_val); Transform3D operator*(const real_t p_val) const; + Transform3D sphere_interpolate_with(const Transform3D &p_transform, real_t p_c) const; Transform3D interpolate_with(const Transform3D &p_transform, real_t p_c) const; _FORCE_INLINE_ Transform3D inverse_xform(const Transform3D &t) const { diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp index dff46f2042..fa8d26a72b 100644 --- a/core/variant/variant_setget.cpp +++ b/core/variant/variant_setget.cpp @@ -2120,7 +2120,7 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & } return; case BASIS: { - r_dst = Transform3D(*a._data._basis).interpolate_with(Transform3D(*b._data._basis), c).basis; + r_dst = a._data._basis->lerp(*b._data._basis, c); } return; case TRANSFORM3D: { diff --git a/doc/classes/EditorExportPlugin.xml b/doc/classes/EditorExportPlugin.xml index 3830bfc60e..9c01921df1 100644 --- a/doc/classes/EditorExportPlugin.xml +++ b/doc/classes/EditorExportPlugin.xml @@ -96,12 +96,22 @@ Adds a static lib from the given [code]path[/code] to the iOS project. </description> </method> + <method name="add_osx_plugin_file"> + <return type="void" /> + <argument index="0" name="path" type="String" /> + <description> + Adds file or directory matching [code]path[/code] to [code]PlugIns[/code] directory of macOS app bundle. + [b]Note:[/b] This is useful only for macOS exports. + </description> + </method> <method name="add_shared_object"> <return type="void" /> <argument index="0" name="path" type="String" /> <argument index="1" name="tags" type="PackedStringArray" /> <description> - Adds a shared object with the given [code]tags[/code] and destination [code]path[/code]. + Adds a shared object or a directory containing only shared objects with the given [code]tags[/code] and destination [code]path[/code]. + [b]Note:[/b] In case of macOS exports, those shared objects will be added to [code]Frameworks[/code] directory of app bundle. + In case of a directory code-sign will error if you place non code object in directory. </description> </method> <method name="skip"> diff --git a/doc/classes/GeometryInstance3D.xml b/doc/classes/GeometryInstance3D.xml index 0d230288a8..cecd1e518f 100644 --- a/doc/classes/GeometryInstance3D.xml +++ b/doc/classes/GeometryInstance3D.xml @@ -47,6 +47,10 @@ </member> <member name="lod_bias" type="float" setter="set_lod_bias" getter="get_lod_bias" default="1.0"> </member> + <member name="material_overlay" type="Material" setter="set_material_overlay" getter="get_material_overlay"> + The material overlay for the whole geometry. + If a material is assigned to this property, it will be rendered on top of any other active material for all the surfaces. + </member> <member name="material_override" type="Material" setter="set_material_override" getter="get_material_override"> The material override for the whole geometry. If a material is assigned to this property, it will be used instead of any material set in any material slot of the mesh. diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index 5d82126839..f17f6293bc 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -1403,6 +1403,14 @@ <description> </description> </method> + <method name="instance_geometry_set_material_overlay"> + <return type="void" /> + <argument index="0" name="instance" type="RID" /> + <argument index="1" name="material" type="RID" /> + <description> + Sets a material that will be rendered for all surfaces on top of active materials for the mesh associated with this instance. Equivalent to [member GeometryInstance3D.material_overlay]. + </description> + </method> <method name="instance_geometry_set_material_override"> <return type="void" /> <argument index="0" name="instance" type="RID" /> diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index ac4684c2d8..77e0366f0e 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -43,6 +43,9 @@ void RasterizerSceneGLES3::geometry_instance_set_skeleton(GeometryInstance *p_ge void RasterizerSceneGLES3::geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) { } +void RasterizerSceneGLES3::geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_overlay) { +} + void RasterizerSceneGLES3::geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) { } diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 14a4432c08..9b356f28df 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -52,6 +52,7 @@ public: GeometryInstance *geometry_instance_create(RID p_base) override; void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override; void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override; + void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_overlay) override; void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) override; void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override; void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) override; diff --git a/editor/editor_asset_installer.cpp b/editor/editor_asset_installer.cpp index 4d6b2e2750..1de67149c6 100644 --- a/editor/editor_asset_installer.cpp +++ b/editor/editor_asset_installer.cpp @@ -124,7 +124,7 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) { char fname[16384]; unzGetCurrentFileInfo(pkg, &info, fname, 16384, nullptr, 0, nullptr, 0); - String name = fname; + String name = String::utf8(fname); files_sorted.insert(name); ret = unzGoToNextFile(pkg); @@ -303,7 +303,7 @@ void EditorAssetInstaller::ok_pressed() { char fname[16384]; ret = unzGetCurrentFileInfo(pkg, &info, fname, 16384, nullptr, 0, nullptr, 0); - String name = fname; + String name = String::utf8(fname); if (status_map.has(name) && status_map[name]->is_checked(0)) { String path = status_map[name]->get_metadata(0); diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp index d681074bf5..014e27ae15 100644 --- a/editor/editor_export.cpp +++ b/editor/editor_export.cpp @@ -620,6 +620,14 @@ String EditorExportPlugin::get_ios_cpp_code() const { return ios_cpp_code; } +void EditorExportPlugin::add_osx_plugin_file(const String &p_path) { + osx_plugin_files.push_back(p_path); +} + +const Vector<String> &EditorExportPlugin::get_osx_plugin_files() const { + return osx_plugin_files; +} + void EditorExportPlugin::add_ios_project_static_lib(const String &p_path) { ios_project_static_libs.push_back(p_path); } @@ -660,6 +668,7 @@ void EditorExportPlugin::_bind_methods() { ClassDB::bind_method(D_METHOD("add_ios_linker_flags", "flags"), &EditorExportPlugin::add_ios_linker_flags); ClassDB::bind_method(D_METHOD("add_ios_bundle_file", "path"), &EditorExportPlugin::add_ios_bundle_file); ClassDB::bind_method(D_METHOD("add_ios_cpp_code", "code"), &EditorExportPlugin::add_ios_cpp_code); + ClassDB::bind_method(D_METHOD("add_osx_plugin_file", "path"), &EditorExportPlugin::add_osx_plugin_file); ClassDB::bind_method(D_METHOD("skip"), &EditorExportPlugin::skip); GDVIRTUAL_BIND(_export_file, "path", "type", "features"); diff --git a/editor/editor_export.h b/editor/editor_export.h index fd885ad313..3d46ae1996 100644 --- a/editor/editor_export.h +++ b/editor/editor_export.h @@ -308,6 +308,8 @@ class EditorExportPlugin : public RefCounted { Vector<String> ios_bundle_files; String ios_cpp_code; + Vector<String> osx_plugin_files; + _FORCE_INLINE_ void _clear() { shared_objects.clear(); extra_files.clear(); @@ -321,6 +323,7 @@ class EditorExportPlugin : public RefCounted { ios_plist_content = ""; ios_linker_flags = ""; ios_cpp_code = ""; + osx_plugin_files.clear(); } void _export_file_script(const String &p_path, const String &p_type, const Vector<String> &p_features); @@ -341,6 +344,7 @@ protected: void add_ios_linker_flags(const String &p_flags); void add_ios_bundle_file(const String &p_path); void add_ios_cpp_code(const String &p_code); + void add_osx_plugin_file(const String &p_path); void skip(); @@ -361,6 +365,7 @@ public: String get_ios_linker_flags() const; Vector<String> get_ios_bundle_files() const; String get_ios_cpp_code() const; + const Vector<String> &get_osx_plugin_files() const; EditorExportPlugin(); }; diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp index f12a851388..8c34609e9c 100644 --- a/editor/export_template_manager.cpp +++ b/editor/export_template_manager.cpp @@ -396,7 +396,7 @@ bool ExportTemplateManager::_install_file_selected(const String &p_file, bool p_ char fname[16384]; ret = unzGetCurrentFileInfo(pkg, &info, fname, 16384, nullptr, 0, nullptr, 0); - String file = fname; + String file = String::utf8(fname); if (file.ends_with("version.txt")) { Vector<uint8_t> data; data.resize(info.uncompressed_size); @@ -457,7 +457,7 @@ bool ExportTemplateManager::_install_file_selected(const String &p_file, bool p_ char fname[16384]; unzGetCurrentFileInfo(pkg, &info, fname, 16384, nullptr, 0, nullptr, 0); - String file_path(String(fname).simplify_path()); + String file_path(String::utf8(fname).simplify_path()); String file = file_path.get_file(); @@ -698,7 +698,7 @@ Error ExportTemplateManager::install_android_template_from_file(const String &p_ char fpath[16384]; ret = unzGetCurrentFileInfo(pkg, &info, fpath, 16384, nullptr, 0, nullptr, 0); - String path = fpath; + String path = String::utf8(fpath); String base_dir = path.get_base_dir(); if (!path.ends_with("/")) { diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index d6fd153665..089c37d7a6 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -2097,8 +2097,16 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { if (k.is_valid() && k->is_pressed() && (tool == TOOL_SELECT || tool == TOOL_MOVE) && (k->get_keycode() == Key::UP || k->get_keycode() == Key::DOWN || k->get_keycode() == Key::LEFT || k->get_keycode() == Key::RIGHT)) { if (!k->is_echo()) { - // Start moving the canvas items with the keyboard - drag_selection = _get_edited_canvas_items(); + // Start moving the canvas items with the keyboard, if they are movable + List<CanvasItem *> selection = _get_edited_canvas_items(); + + drag_selection.clear(); + for (CanvasItem *item : selection) { + if (_is_node_movable(item, true)) { + drag_selection.push_back(item); + } + } + drag_type = DRAG_KEY_MOVE; drag_from = Vector2(); drag_to = Vector2(); @@ -5852,7 +5860,7 @@ bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, cons instantiated_scene->set_scene_file_path(ProjectSettings::get_singleton()->localize_path(path)); - editor_data->get_undo_redo().add_do_method(parent, "add_child", instantiated_scene); + editor_data->get_undo_redo().add_do_method(parent, "add_child", instantiated_scene, true); editor_data->get_undo_redo().add_do_method(instantiated_scene, "set_owner", editor->get_edited_scene()); editor_data->get_undo_redo().add_do_reference(instantiated_scene); editor_data->get_undo_redo().add_undo_method(parent, "remove_child", instantiated_scene); diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index c86f6c02cb..957d1483bc 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -954,7 +954,7 @@ bool Node3DEditorViewport::_transform_gizmo_select(const Vector2 &p_screenpos, b real_t col_d = 1e20; for (int i = 0; i < 3; i++) { - const Vector3 grabber_pos = gt.origin + gt.basis.get_axis(i) * gizmo_scale * (GIZMO_ARROW_OFFSET + (GIZMO_ARROW_SIZE * 0.5)); + const Vector3 grabber_pos = gt.origin + gt.basis.get_axis(i).normalized() * gizmo_scale * (GIZMO_ARROW_OFFSET + (GIZMO_ARROW_SIZE * 0.5)); const real_t grabber_radius = gizmo_scale * GIZMO_ARROW_SIZE; Vector3 r; @@ -1058,7 +1058,7 @@ bool Node3DEditorViewport::_transform_gizmo_select(const Vector2 &p_screenpos, b float col_d = 1e20; for (int i = 0; i < 3; i++) { - const Vector3 grabber_pos = gt.origin + gt.basis.get_axis(i) * gizmo_scale * GIZMO_SCALE_OFFSET; + const Vector3 grabber_pos = gt.origin + gt.basis.get_axis(i).normalized() * gizmo_scale * GIZMO_SCALE_OFFSET; const real_t grabber_radius = gizmo_scale * GIZMO_ARROW_SIZE; Vector3 r; @@ -1138,68 +1138,62 @@ void Node3DEditorViewport::_transform_gizmo_apply(Node3D *p_node, const Transfor } } -Transform3D Node3DEditorViewport::_compute_transform(TransformMode p_mode, const Transform3D &p_original, const Transform3D &p_original_local, Vector3 p_motion, double p_extra, bool p_local) { +Transform3D Node3DEditorViewport::_compute_transform(TransformMode p_mode, const Transform3D &p_original, const Transform3D &p_original_local, Vector3 p_motion, double p_extra, bool p_local, bool p_orthogonal) { switch (p_mode) { case TRANSFORM_SCALE: { + if (_edit.snap || spatial_editor->is_snap_enabled()) { + p_motion.snap(Vector3(p_extra, p_extra, p_extra)); + } + Transform3D s; if (p_local) { - Basis g = p_original.basis.orthonormalized(); - Vector3 local_motion = g.inverse().xform(p_motion); - - if (_edit.snap || spatial_editor->is_snap_enabled()) { - local_motion.snap(Vector3(p_extra, p_extra, p_extra)); - } - - Transform3D local_t; - local_t.basis = p_original_local.basis.scaled_local(local_motion + Vector3(1, 1, 1)); - local_t.origin = p_original_local.origin; - return local_t; + s.basis = p_original_local.basis.scaled_local(p_motion + Vector3(1, 1, 1)); + s.origin = p_original_local.origin; } else { + s.basis.scale(p_motion + Vector3(1, 1, 1)); Transform3D base = Transform3D(Basis(), _edit.center); - if (_edit.snap || spatial_editor->is_snap_enabled()) { - p_motion.snap(Vector3(p_extra, p_extra, p_extra)); + s = base * (s * (base.inverse() * p_original)); + + // Recalculate orthogonalized scale without moving origin. + if (p_orthogonal) { + s.basis = p_original_local.basis.scaled_orthogonal(p_motion + Vector3(1, 1, 1)); + // The scaled_orthogonal() does not require orthogonal Basis, + // but it may make a bit skew by precision problems. + s.basis.orthogonalize(); } - - Transform3D global_t; - global_t.basis.scale(p_motion + Vector3(1, 1, 1)); - return base * (global_t * (base.inverse() * p_original)); } + + return s; } case TRANSFORM_TRANSLATE: { - if (p_local) { - if (_edit.snap || spatial_editor->is_snap_enabled()) { - Basis g = p_original.basis.orthonormalized(); - Vector3 local_motion = g.inverse().xform(p_motion); - local_motion.snap(Vector3(p_extra, p_extra, p_extra)); - - p_motion = g.xform(local_motion); - } + if (_edit.snap || spatial_editor->is_snap_enabled()) { + p_motion.snap(Vector3(p_extra, p_extra, p_extra)); + } - } else { - if (_edit.snap || spatial_editor->is_snap_enabled()) { - p_motion.snap(Vector3(p_extra, p_extra, p_extra)); - } + if (p_local) { + p_motion = p_original.basis.xform(p_motion); } // Apply translation Transform3D t = p_original; t.origin += p_motion; + return t; } case TRANSFORM_ROTATE: { + Transform3D r; + if (p_local) { - Transform3D r; Vector3 axis = p_original_local.basis.xform(p_motion); r.basis = Basis(axis.normalized(), p_extra) * p_original_local.basis; r.origin = p_original_local.origin; - return r; } else { - Transform3D r; Basis local = p_original.basis * p_original_local.basis.inverse(); Vector3 axis = local.xform_inv(p_motion); r.basis = local * Basis(axis.normalized(), p_extra) * p_original_local.basis; r.origin = Basis(p_motion, p_extra).xform(p_original.origin - _edit.center) + _edit.center; - return r; } + + return r; } default: { ERR_FAIL_V_MSG(Transform3D(), "Invalid mode in '_compute_transform'"); @@ -1480,6 +1474,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { _edit.original_mouse_pos = b->get_position(); _edit.snap = spatial_editor->is_snap_enabled(); _edit.mode = TRANSFORM_NONE; + _edit.original = spatial_editor->get_gizmo_transform(); // To prevent to break when flipping with scale. bool can_select_gizmos = spatial_editor->get_single_selected_node(); @@ -1783,30 +1778,30 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { plane = Plane(_get_camera_normal(), _edit.center); break; case TRANSFORM_X_AXIS: - motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(0); + motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(0).normalized(); plane = Plane(motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized(), _edit.center); break; case TRANSFORM_Y_AXIS: - motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(1); + motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(1).normalized(); plane = Plane(motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized(), _edit.center); break; case TRANSFORM_Z_AXIS: - motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(2); + motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(2).normalized(); plane = Plane(motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized(), _edit.center); break; case TRANSFORM_YZ: - motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(2) + spatial_editor->get_gizmo_transform().basis.get_axis(1); - plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(0), _edit.center); + motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(2).normalized() + spatial_editor->get_gizmo_transform().basis.get_axis(1).normalized(); + plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(0).normalized(), _edit.center); plane_mv = true; break; case TRANSFORM_XZ: - motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(2) + spatial_editor->get_gizmo_transform().basis.get_axis(0); - plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(1), _edit.center); + motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(2).normalized() + spatial_editor->get_gizmo_transform().basis.get_axis(0).normalized(); + plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(1).normalized(), _edit.center); plane_mv = true; break; case TRANSFORM_XY: - motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(0) + spatial_editor->get_gizmo_transform().basis.get_axis(1); - plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(2), _edit.center); + motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(0).normalized() + spatial_editor->get_gizmo_transform().basis.get_axis(1).normalized(); + plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(2).normalized(), _edit.center); plane_mv = true; break; } @@ -1857,6 +1852,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { // This might not be necessary anymore after issue #288 is solved (in 4.0?). set_message(TTR("Scaling: ") + "(" + String::num(motion_snapped.x, snap_step_decimals) + ", " + String::num(motion_snapped.y, snap_step_decimals) + ", " + String::num(motion_snapped.z, snap_step_decimals) + ")"); + motion = _edit.original.basis.inverse().xform(motion); List<Node *> &selection = editor_selection->get_selected_node_list(); for (Node *E : selection) { @@ -1877,14 +1873,14 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { if (se->gizmo.is_valid()) { for (KeyValue<int, Transform3D> &GE : se->subgizmos) { Transform3D xform = GE.value; - Transform3D new_xform = _compute_transform(TRANSFORM_SCALE, se->original * xform, xform, motion, snap, local_coords); + Transform3D new_xform = _compute_transform(TRANSFORM_SCALE, se->original * xform, xform, motion, snap, local_coords, true); // Force orthogonal with subgizmo. if (!local_coords) { new_xform = se->original.affine_inverse() * new_xform; } se->gizmo->set_subgizmo_transform(GE.key, new_xform); } } else { - Transform3D new_xform = _compute_transform(TRANSFORM_SCALE, se->original, se->original_local, motion, snap, local_coords); + Transform3D new_xform = _compute_transform(TRANSFORM_SCALE, se->original, se->original_local, motion, snap, local_coords, sp->get_rotation_edit_mode() != Node3D::ROTATION_EDIT_MODE_BASIS); _transform_gizmo_apply(se->sp, new_xform, local_coords); } } @@ -1904,27 +1900,27 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { plane = Plane(_get_camera_normal(), _edit.center); break; case TRANSFORM_X_AXIS: - motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(0); + motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(0).normalized(); plane = Plane(motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized(), _edit.center); break; case TRANSFORM_Y_AXIS: - motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(1); + motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(1).normalized(); plane = Plane(motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized(), _edit.center); break; case TRANSFORM_Z_AXIS: - motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(2); + motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(2).normalized(); plane = Plane(motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized(), _edit.center); break; case TRANSFORM_YZ: - plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(0), _edit.center); + plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(0).normalized(), _edit.center); plane_mv = true; break; case TRANSFORM_XZ: - plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(1), _edit.center); + plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(1).normalized(), _edit.center); plane_mv = true; break; case TRANSFORM_XY: - plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(2), _edit.center); + plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(2).normalized(), _edit.center); plane_mv = true; break; } @@ -1956,6 +1952,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { motion_snapped.snap(Vector3(snap, snap, snap)); set_message(TTR("Translating: ") + "(" + String::num(motion_snapped.x, snap_step_decimals) + ", " + String::num(motion_snapped.y, snap_step_decimals) + ", " + String::num(motion_snapped.z, snap_step_decimals) + ")"); + motion = spatial_editor->get_gizmo_transform().basis.inverse().xform(motion); List<Node *> &selection = editor_selection->get_selected_node_list(); for (Node *E : selection) { @@ -1976,12 +1973,12 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { if (se->gizmo.is_valid()) { for (KeyValue<int, Transform3D> &GE : se->subgizmos) { Transform3D xform = GE.value; - Transform3D new_xform = _compute_transform(TRANSFORM_TRANSLATE, se->original * xform, xform, motion, snap, local_coords); + Transform3D new_xform = _compute_transform(TRANSFORM_TRANSLATE, se->original * xform, xform, motion, snap, local_coords, true); // Force orthogonal with subgizmo. new_xform = se->original.affine_inverse() * new_xform; se->gizmo->set_subgizmo_transform(GE.key, new_xform); } } else { - Transform3D new_xform = _compute_transform(TRANSFORM_TRANSLATE, se->original, se->original_local, motion, snap, local_coords); + Transform3D new_xform = _compute_transform(TRANSFORM_TRANSLATE, se->original, se->original_local, motion, snap, local_coords, sp->get_rotation_edit_mode() != Node3D::ROTATION_EDIT_MODE_BASIS); _transform_gizmo_apply(se->sp, new_xform, false); } } @@ -2000,15 +1997,15 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { plane = Plane(_get_camera_normal(), _edit.center); break; case TRANSFORM_X_AXIS: - plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(0), _edit.center); + plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(0).normalized(), _edit.center); axis = Vector3(1, 0, 0); break; case TRANSFORM_Y_AXIS: - plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(1), _edit.center); + plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(1).normalized(), _edit.center); axis = Vector3(0, 1, 0); break; case TRANSFORM_Z_AXIS: - plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(2), _edit.center); + plane = Plane(spatial_editor->get_gizmo_transform().basis.get_axis(2).normalized(), _edit.center); axis = Vector3(0, 0, 1); break; case TRANSFORM_YZ: @@ -2063,14 +2060,14 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { for (KeyValue<int, Transform3D> &GE : se->subgizmos) { Transform3D xform = GE.value; - Transform3D new_xform = _compute_transform(TRANSFORM_ROTATE, se->original * xform, xform, compute_axis, angle, local_coords); + Transform3D new_xform = _compute_transform(TRANSFORM_ROTATE, se->original * xform, xform, compute_axis, angle, local_coords, true); // Force orthogonal with subgizmo. if (!local_coords) { new_xform = se->original.affine_inverse() * new_xform; } se->gizmo->set_subgizmo_transform(GE.key, new_xform); } } else { - Transform3D new_xform = _compute_transform(TRANSFORM_ROTATE, se->original, se->original_local, compute_axis, angle, local_coords); + Transform3D new_xform = _compute_transform(TRANSFORM_ROTATE, se->original, se->original_local, compute_axis, angle, local_coords, sp->get_rotation_edit_mode() != Node3D::ROTATION_EDIT_MODE_BASIS); _transform_gizmo_apply(se->sp, new_xform, local_coords); } } @@ -3676,8 +3673,6 @@ void Node3DEditorViewport::update_transform_gizmo_view() { subviewport_container->get_stretch_shrink(); Vector3 scale = Vector3(1, 1, 1) * gizmo_scale; - xform.basis.scale(scale); - // if the determinant is zero, we should disable the gizmo from being rendered // this prevents supplying bad values to the renderer and then having to filter it out again if (xform.basis.determinant() == 0) { @@ -3694,18 +3689,26 @@ void Node3DEditorViewport::update_transform_gizmo_view() { } for (int i = 0; i < 3; i++) { - RenderingServer::get_singleton()->instance_set_transform(move_gizmo_instance[i], xform); + Transform3D axis_angle = Transform3D(); + if (xform.basis.get_axis(i).normalized().dot(xform.basis.get_axis((i + 1) % 3).normalized()) < 1.0) { + axis_angle = axis_angle.looking_at(xform.basis.get_axis(i).normalized(), xform.basis.get_axis((i + 1) % 3).normalized()); + } + axis_angle.basis.scale(scale); + axis_angle.origin = xform.origin; + RenderingServer::get_singleton()->instance_set_transform(move_gizmo_instance[i], axis_angle); RenderingServer::get_singleton()->instance_set_visible(move_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_MOVE)); - RenderingServer::get_singleton()->instance_set_transform(move_plane_gizmo_instance[i], xform); + RenderingServer::get_singleton()->instance_set_transform(move_plane_gizmo_instance[i], axis_angle); RenderingServer::get_singleton()->instance_set_visible(move_plane_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_MOVE)); - RenderingServer::get_singleton()->instance_set_transform(rotate_gizmo_instance[i], xform); + RenderingServer::get_singleton()->instance_set_transform(rotate_gizmo_instance[i], axis_angle); RenderingServer::get_singleton()->instance_set_visible(rotate_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE)); - RenderingServer::get_singleton()->instance_set_transform(scale_gizmo_instance[i], xform); + RenderingServer::get_singleton()->instance_set_transform(scale_gizmo_instance[i], axis_angle); RenderingServer::get_singleton()->instance_set_visible(scale_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SCALE)); - RenderingServer::get_singleton()->instance_set_transform(scale_plane_gizmo_instance[i], xform); + RenderingServer::get_singleton()->instance_set_transform(scale_plane_gizmo_instance[i], axis_angle); RenderingServer::get_singleton()->instance_set_visible(scale_plane_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SCALE)); } // Rotation white outline + xform.orthonormalize(); + xform.basis.scale(scale); RenderingServer::get_singleton()->instance_set_transform(rotate_gizmo_instance[3], xform); RenderingServer::get_singleton()->instance_set_visible(rotate_gizmo_instance[3], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE)); } @@ -4127,7 +4130,7 @@ bool Node3DEditorViewport::_create_instance(Node *parent, String &path, const Po instantiated_scene->set_scene_file_path(ProjectSettings::get_singleton()->localize_path(path)); } - editor_data->get_undo_redo().add_do_method(parent, "add_child", instantiated_scene); + editor_data->get_undo_redo().add_do_method(parent, "add_child", instantiated_scene, true); editor_data->get_undo_redo().add_do_method(instantiated_scene, "set_owner", editor->get_edited_scene()); editor_data->get_undo_redo().add_do_reference(instantiated_scene); editor_data->get_undo_redo().add_undo_method(parent, "remove_child", instantiated_scene); @@ -4915,7 +4918,6 @@ void Node3DEditor::update_transform_gizmo() { gizmo_center += xf.origin; if (count == 0 && local_gizmo_coords) { gizmo_basis = xf.basis; - gizmo_basis.orthonormalize(); } count++; } @@ -4940,7 +4942,6 @@ void Node3DEditor::update_transform_gizmo() { gizmo_center += xf.origin; if (count == 0 && local_gizmo_coords) { gizmo_basis = xf.basis; - gizmo_basis.orthonormalize(); } count++; } @@ -5815,6 +5816,12 @@ void fragment() { { //move gizmo + // Inverted zxy. + Vector3 ivec = Vector3(0, 0, -1); + Vector3 nivec = Vector3(-1, -1, 0); + Vector3 ivec2 = Vector3(-1, 0, 0); + Vector3 ivec3 = Vector3(0, -1, 0); + for (int i = 0; i < 3; i++) { Color col; switch (i) { @@ -5852,16 +5859,6 @@ void fragment() { mat_hl->set_albedo(albedo); gizmo_color_hl[i] = mat_hl; - Vector3 ivec; - ivec[i] = 1; - Vector3 nivec; - nivec[(i + 1) % 3] = 1; - nivec[(i + 2) % 3] = 1; - Vector3 ivec2; - ivec2[(i + 1) % 3] = 1; - Vector3 ivec3; - ivec3[(i + 2) % 3] = 1; - //translate { Ref<SurfaceTool> surftool = memnew(SurfaceTool); diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index eba3989f9d..8d42e88b53 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -399,7 +399,7 @@ private: void _project_settings_changed(); - Transform3D _compute_transform(TransformMode p_mode, const Transform3D &p_original, const Transform3D &p_original_local, Vector3 p_motion, double p_extra, bool p_local); + Transform3D _compute_transform(TransformMode p_mode, const Transform3D &p_original, const Transform3D &p_original_local, Vector3 p_motion, double p_extra, bool p_local, bool p_orthogonal); protected: void _notification(int p_what); diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 4b7380c83f..08e0f7ae30 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -204,7 +204,7 @@ private: char fname[16384]; ret = unzGetCurrentFileInfo(pkg, &info, fname, 16384, nullptr, 0, nullptr, 0); - if (String(fname).ends_with("project.godot")) { + if (String::utf8(fname).ends_with("project.godot")) { break; } @@ -524,7 +524,7 @@ private: char fname[16384]; unzGetCurrentFileInfo(pkg, &info, fname, 16384, nullptr, 0, nullptr, 0); - String name = fname; + String name = String::utf8(fname); if (name.ends_with("project.godot")) { zip_root = name.substr(0, name.rfind("project.godot")); break; @@ -544,7 +544,7 @@ private: char fname[16384]; ret = unzGetCurrentFileInfo(pkg, &info, fname, 16384, nullptr, 0, nullptr, 0); - String path = fname; + String path = String::utf8(fname); if (path.is_empty() || path == zip_root || !zip_root.is_subsequence_of(path)) { // diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp index 8997d31e1f..cbecde787f 100644 --- a/platform/android/export/export_plugin.cpp +++ b/platform/android/export/export_plugin.cpp @@ -2794,7 +2794,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP bool skip = false; - String file = fname; + String file = String::utf8(fname); Vector<uint8_t> data; data.resize(info.uncompressed_size); @@ -2976,7 +2976,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP char extra[16384]; ret = unzGetCurrentFileInfo(tmp_unaligned, &info, fname, 16384, extra, 16384 - ZIP_ALIGNMENT, nullptr, 0); - String file = fname; + String file = String::utf8(fname); Vector<uint8_t> data; data.resize(info.compressed_size); diff --git a/platform/iphone/export/export_plugin.cpp b/platform/iphone/export/export_plugin.cpp index 4a55ca1cbf..0ad68086a7 100644 --- a/platform/iphone/export/export_plugin.cpp +++ b/platform/iphone/export/export_plugin.cpp @@ -1484,7 +1484,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p char fname[16384]; ret = unzGetCurrentFileInfo(src_pkg_zip, &info, fname, 16384, nullptr, 0, nullptr, 0); - String file = fname; + String file = String::utf8(fname); print_line("READ: " + file); Vector<uint8_t> data; diff --git a/platform/javascript/export/export_plugin.cpp b/platform/javascript/export/export_plugin.cpp index 2134deebcb..81ffae82bf 100644 --- a/platform/javascript/export/export_plugin.cpp +++ b/platform/javascript/export/export_plugin.cpp @@ -52,7 +52,7 @@ Error EditorExportPlatformJavaScript::_extract_template(const String &p_template char fname[16384]; unzGetCurrentFileInfo(pkg, &info, fname, 16384, nullptr, 0, nullptr, 0); - String file = fname; + String file = String::utf8(fname); // Skip service worker and offline page if not exporting pwa. if (!pwa && (file == "godot.service.worker.js" || file == "godot.offline.html")) { diff --git a/platform/osx/export/export_plugin.cpp b/platform/osx/export/export_plugin.cpp index 786a8f38d8..ab50144303 100644 --- a/platform/osx/export/export_plugin.cpp +++ b/platform/osx/export/export_plugin.cpp @@ -435,6 +435,101 @@ Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_prese return OK; } +Error EditorExportPlatformOSX::_code_sign_directory(const Ref<EditorExportPreset> &p_preset, const String &p_path, + const String &p_ent_path, bool p_should_error_on_non_code) { +#ifdef OSX_ENABLED + static Vector<String> extensions_to_sign; + + if (extensions_to_sign.is_empty()) { + extensions_to_sign.push_back("dylib"); + extensions_to_sign.push_back("framework"); + } + + Error dir_access_error; + DirAccessRef dir_access{ DirAccess::open(p_path, &dir_access_error) }; + + if (dir_access_error != OK) { + return dir_access_error; + } + + dir_access->list_dir_begin(); + String current_file{ dir_access->get_next() }; + while (!current_file.is_empty()) { + String current_file_path{ p_path.plus_file(current_file) }; + + if (current_file == ".." || current_file == ".") { + current_file = dir_access->get_next(); + continue; + } + + if (extensions_to_sign.find(current_file.get_extension()) > -1) { + Error code_sign_error{ _code_sign(p_preset, current_file_path, p_ent_path) }; + if (code_sign_error != OK) { + return code_sign_error; + } + } else if (dir_access->current_is_dir()) { + Error code_sign_error{ _code_sign_directory(p_preset, current_file_path, p_ent_path, p_should_error_on_non_code) }; + if (code_sign_error != OK) { + return code_sign_error; + } + } else if (p_should_error_on_non_code) { + ERR_PRINT(vformat("Cannot sign file %s.", current_file)); + return Error::FAILED; + } + + current_file = dir_access->get_next(); + } +#endif + + return OK; +} + +Error EditorExportPlatformOSX::_copy_and_sign_files(DirAccessRef &dir_access, const String &p_src_path, + const String &p_in_app_path, bool p_sign_enabled, + const Ref<EditorExportPreset> &p_preset, const String &p_ent_path, + bool p_should_error_on_non_code_sign) { + Error err{ OK }; + if (dir_access->dir_exists(p_src_path)) { +#ifndef UNIX_ENABLED + WARN_PRINT("Relative symlinks are not supported, exported " + p_src_path.get_file() + " might be broken!"); +#endif + print_verbose("export framework: " + p_src_path + " -> " + p_in_app_path); + err = dir_access->make_dir_recursive(p_in_app_path); + if (err == OK) { + err = dir_access->copy_dir(p_src_path, p_in_app_path, -1, true); + } + } else { + print_verbose("export dylib: " + p_src_path + " -> " + p_in_app_path); + err = dir_access->copy(p_src_path, p_in_app_path); + } + if (err == OK && p_sign_enabled) { + if (dir_access->dir_exists(p_src_path) && p_src_path.get_extension().is_empty()) { + // If it is a directory, find and sign all dynamic libraries. + err = _code_sign_directory(p_preset, p_in_app_path, p_ent_path, p_should_error_on_non_code_sign); + } else { + err = _code_sign(p_preset, p_in_app_path, p_ent_path); + } + } + return err; +} + +Error EditorExportPlatformOSX::_export_osx_plugins_for(Ref<EditorExportPlugin> p_editor_export_plugin, + const String &p_app_path_name, DirAccessRef &dir_access, + bool p_sign_enabled, const Ref<EditorExportPreset> &p_preset, + const String &p_ent_path) { + Error error{ OK }; + const Vector<String> &osx_plugins{ p_editor_export_plugin->get_osx_plugin_files() }; + for (int i = 0; i < osx_plugins.size(); ++i) { + String src_path{ ProjectSettings::get_singleton()->globalize_path(osx_plugins[i]) }; + String path_in_app{ p_app_path_name + "/Contents/PlugIns/" + src_path.get_file() }; + error = _copy_and_sign_files(dir_access, src_path, path_in_app, p_sign_enabled, p_preset, p_ent_path, false); + if (error != OK) { + break; + } + } + return error; +} + Error EditorExportPlatformOSX::_create_dmg(const String &p_dmg_path, const String &p_pkg_name, const String &p_app_path_name) { List<String> args; @@ -571,7 +666,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p char fname[16384]; ret = unzGetCurrentFileInfo(src_pkg_zip, &info, fname, 16384, nullptr, 0, nullptr, 0); - String file = fname; + String file = String::utf8(fname); Vector<uint8_t> data; data.resize(info.uncompressed_size); @@ -860,26 +955,22 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p FileAccess::set_unix_permissions(tmp_app_path_name + "/Contents/Helpers/" + hlp_path.get_file(), 0755); } } - if (err == OK) { DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); for (int i = 0; i < shared_objects.size(); i++) { String src_path = ProjectSettings::get_singleton()->globalize_path(shared_objects[i].path); - if (da->dir_exists(src_path)) { -#ifndef UNIX_ENABLED - WARN_PRINT("Relative symlinks are not supported, exported " + src_path.get_file() + " might be broken!"); -#endif - print_verbose("export framework: " + src_path + " -> " + tmp_app_path_name + "/Contents/Frameworks/" + src_path.get_file()); - err = da->make_dir_recursive(tmp_app_path_name + "/Contents/Frameworks/" + src_path.get_file()); - if (err == OK) { - err = da->copy_dir(src_path, tmp_app_path_name + "/Contents/Frameworks/" + src_path.get_file(), -1, true); - } - } else { - print_verbose("export dylib: " + src_path + " -> " + tmp_app_path_name + "/Contents/Frameworks/" + src_path.get_file()); - err = da->copy(src_path, tmp_app_path_name + "/Contents/Frameworks/" + src_path.get_file()); + String path_in_app{ tmp_app_path_name + "/Contents/Frameworks/" + src_path.get_file() }; + err = _copy_and_sign_files(da, src_path, path_in_app, sign_enabled, p_preset, ent_path, true); + if (err != OK) { + break; } - if (err == OK && sign_enabled) { - err = _code_sign(p_preset, tmp_app_path_name + "/Contents/Frameworks/" + src_path.get_file(), ent_path); + } + + Vector<Ref<EditorExportPlugin>> export_plugins{ EditorExport::get_singleton()->get_export_plugins() }; + for (int i = 0; i < export_plugins.size(); ++i) { + err = _export_osx_plugins_for(export_plugins[i], tmp_app_path_name, da, sign_enabled, p_preset, ent_path); + if (err != OK) { + break; } } } diff --git a/platform/osx/export/export_plugin.h b/platform/osx/export/export_plugin.h index 036fa006ec..aa22ad6384 100644 --- a/platform/osx/export/export_plugin.h +++ b/platform/osx/export/export_plugin.h @@ -58,6 +58,13 @@ class EditorExportPlatformOSX : public EditorExportPlatform { Error _notarize(const Ref<EditorExportPreset> &p_preset, const String &p_path); Error _code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path, const String &p_ent_path); + Error _code_sign_directory(const Ref<EditorExportPreset> &p_preset, const String &p_path, const String &p_ent_path, bool p_should_error_on_non_code = true); + Error _copy_and_sign_files(DirAccessRef &dir_access, const String &p_src_path, const String &p_in_app_path, + bool p_sign_enabled, const Ref<EditorExportPreset> &p_preset, const String &p_ent_path, + bool p_should_error_on_non_code_sign); + Error _export_osx_plugins_for(Ref<EditorExportPlugin> p_editor_export_plugin, const String &p_app_path_name, + DirAccessRef &dir_access, bool p_sign_enabled, const Ref<EditorExportPreset> &p_preset, + const String &p_ent_path); Error _create_dmg(const String &p_dmg_path, const String &p_pkg_name, const String &p_app_path_name); void _zip_folder_recursive(zipFile &p_zip, const String &p_root_path, const String &p_folder, const String &p_pkg_name); diff --git a/platform/uwp/export/export_plugin.cpp b/platform/uwp/export/export_plugin.cpp index f1f100bdd3..594495375a 100644 --- a/platform/uwp/export/export_plugin.cpp +++ b/platform/uwp/export/export_plugin.cpp @@ -325,7 +325,7 @@ Error EditorExportPlatformUWP::export_project(const Ref<EditorExportPreset> &p_p char fname[16834]; ret = unzGetCurrentFileInfo(pkg, &info, fname, 16834, nullptr, 0, nullptr, 0); - String path = fname; + String path = String::utf8(fname); if (path.ends_with("/")) { // Ignore directories diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp index e189b705d8..4426a646f4 100644 --- a/scene/3d/node_3d.cpp +++ b/scene/3d/node_3d.cpp @@ -84,6 +84,9 @@ void Node3D::_notify_dirty() { } void Node3D::_update_local_transform() const { + if (this->get_rotation_edit_mode() != ROTATION_EDIT_MODE_BASIS) { + data.local_transform = data.local_transform.orthogonalized(); + } data.local_transform.basis.set_euler_scale(data.rotation, data.scale); data.dirty &= ~DIRTY_LOCAL; @@ -321,6 +324,14 @@ void Node3D::set_rotation_edit_mode(RotationEditMode p_mode) { return; } data.rotation_edit_mode = p_mode; + + // Shearing is not allowed except in ROTATION_EDIT_MODE_BASIS. + data.dirty |= DIRTY_LOCAL; + _propagate_transform_changed(this); + if (data.notify_local_transform) { + notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); + } + notify_property_list_changed(); } diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp index 13729db618..0db2fe9fc6 100644 --- a/scene/3d/visual_instance_3d.cpp +++ b/scene/3d/visual_instance_3d.cpp @@ -152,6 +152,15 @@ Ref<Material> GeometryInstance3D::get_material_override() const { return material_override; } +void GeometryInstance3D::set_material_overlay(const Ref<Material> &p_material) { + material_overlay = p_material; + RS::get_singleton()->instance_geometry_set_material_overlay(get_instance(), p_material.is_valid() ? p_material->get_rid() : RID()); +} + +Ref<Material> GeometryInstance3D::get_material_overlay() const { + return material_overlay; +} + void GeometryInstance3D::set_transparecy(float p_transparency) { transparency = CLAMP(p_transparency, 0.0f, 1.0f); RS::get_singleton()->instance_geometry_set_transparency(get_instance(), transparency); @@ -398,6 +407,9 @@ void GeometryInstance3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_material_override", "material"), &GeometryInstance3D::set_material_override); ClassDB::bind_method(D_METHOD("get_material_override"), &GeometryInstance3D::get_material_override); + ClassDB::bind_method(D_METHOD("set_material_overlay", "material"), &GeometryInstance3D::set_material_overlay); + ClassDB::bind_method(D_METHOD("get_material_overlay"), &GeometryInstance3D::get_material_overlay); + ClassDB::bind_method(D_METHOD("set_cast_shadows_setting", "shadow_casting_setting"), &GeometryInstance3D::set_cast_shadows_setting); ClassDB::bind_method(D_METHOD("get_cast_shadows_setting"), &GeometryInstance3D::get_cast_shadows_setting); @@ -443,6 +455,7 @@ void GeometryInstance3D::_bind_methods() { ADD_GROUP("Geometry", ""); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material_override", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE), "set_material_override", "get_material_override"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material_overlay", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE), "set_material_overlay", "get_material_overlay"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "transparency", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_transparency", "get_transparency"); ADD_PROPERTY(PropertyInfo(Variant::INT, "cast_shadow", PROPERTY_HINT_ENUM, "Off,On,Double-Sided,Shadows Only"), "set_cast_shadows_setting", "get_cast_shadows_setting"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "extra_cull_margin", PROPERTY_HINT_RANGE, "0,16384,0.01"), "set_extra_cull_margin", "get_extra_cull_margin"); diff --git a/scene/3d/visual_instance_3d.h b/scene/3d/visual_instance_3d.h index b08f54b3ec..dd0eb25001 100644 --- a/scene/3d/visual_instance_3d.h +++ b/scene/3d/visual_instance_3d.h @@ -110,6 +110,7 @@ public: private: ShadowCastingSetting shadow_casting_setting = SHADOW_CASTING_SETTING_ON; Ref<Material> material_override; + Ref<Material> material_overlay; float visibility_range_begin = 0.0; float visibility_range_end = 0.0; @@ -164,6 +165,9 @@ public: void set_material_override(const Ref<Material> &p_material); Ref<Material> get_material_override() const; + void set_material_overlay(const Ref<Material> &p_material); + Ref<Material> get_material_overlay() const; + void set_extra_cull_margin(float p_margin); float get_extra_cull_margin() const; diff --git a/scene/main/node.cpp b/scene/main/node.cpp index bec01762d8..8b5883a742 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -229,15 +229,32 @@ void Node::_propagate_enter_tree() { } void Node::_propagate_after_exit_tree() { + // Clear owner if it was not part of the pruned branch if (data.owner) { - data.owner->data.owned.erase(data.OW); - data.owner = nullptr; + bool found = false; + Node *parent = data.parent; + + while (parent) { + if (parent == data.owner) { + found = true; + break; + } + + parent = parent->data.parent; + } + + if (!found) { + data.owner->data.owned.erase(data.OW); + data.owner = nullptr; + } } + data.blocked++; for (int i = data.children.size() - 1; i >= 0; i--) { data.children[i]->_propagate_after_exit_tree(); } data.blocked--; + emit_signal(SceneStringNames::get_singleton()->tree_exited); } diff --git a/servers/rendering/rasterizer_dummy.h b/servers/rendering/rasterizer_dummy.h index 39d1debd40..f02a01c97d 100644 --- a/servers/rendering/rasterizer_dummy.h +++ b/servers/rendering/rasterizer_dummy.h @@ -44,6 +44,7 @@ public: GeometryInstance *geometry_instance_create(RID p_base) override { return nullptr; } void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override {} void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override {} + void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_override) override {} void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) override {} void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override {} void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) override {} diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index f5d6f7c3d0..cd7b2622ab 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -2674,6 +2674,24 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet sdcache->sort.uses_softshadow = ginstance->using_softshadows; } +void RenderForwardClustered::_geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, RID p_mat_src, RID p_mesh) { + SceneShaderForwardClustered::MaterialData *material = p_material; + + _geometry_instance_add_surface_with_material(ginstance, p_surface, material, p_mat_src.get_local_index(), storage->material_get_shader_id(p_mat_src), p_mesh); + + while (material->next_pass.is_valid()) { + RID next_pass = material->next_pass; + material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(next_pass, RendererStorageRD::SHADER_TYPE_3D); + if (!material || !material->shader_data->valid) { + break; + } + if (ginstance->data->dirty_dependencies) { + storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker); + } + _geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), storage->material_get_shader_id(next_pass), p_mesh); + } +} + void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, RID p_material, RID p_mesh) { RID m_src; @@ -2699,18 +2717,19 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw ERR_FAIL_COND(!material); - _geometry_instance_add_surface_with_material(ginstance, p_surface, material, m_src.get_local_index(), storage->material_get_shader_id(m_src), p_mesh); + _geometry_instance_add_surface_with_material_chain(ginstance, p_surface, material, m_src, p_mesh); - while (material->next_pass.is_valid()) { - RID next_pass = material->next_pass; - material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(next_pass, RendererStorageRD::SHADER_TYPE_3D); - if (!material || !material->shader_data->valid) { - break; - } - if (ginstance->data->dirty_dependencies) { - storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker); + if (ginstance->data->material_overlay.is_valid()) { + m_src = ginstance->data->material_overlay; + + material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D); + if (material && material->shader_data->valid) { + if (ginstance->data->dirty_dependencies) { + storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); + } + + _geometry_instance_add_surface_with_material_chain(ginstance, p_surface, material, m_src, p_mesh); } - _geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), storage->material_get_shader_id(next_pass), p_mesh); } } @@ -2919,6 +2938,13 @@ void RenderForwardClustered::geometry_instance_set_material_override(GeometryIns _geometry_instance_mark_dirty(ginstance); ginstance->data->dirty_dependencies = true; } +void RenderForwardClustered::geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_overlay) { + GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + ginstance->data->material_overlay = p_overlay; + _geometry_instance_mark_dirty(ginstance); + ginstance->data->dirty_dependencies = true; +} void RenderForwardClustered::geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) { GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); ERR_FAIL_COND(!ginstance); diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h index 95e5e77b96..f858887bd0 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -496,6 +496,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { RID skeleton; Vector<RID> surface_materials; RID material_override; + RID material_overlay; AABB aabb; bool use_dynamic_gi = false; @@ -523,6 +524,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { PagedAllocator<GeometryInstanceLightmapSH> geometry_instance_lightmap_sh; void _geometry_instance_add_surface_with_material(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh); + void _geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, RID p_mat_src, RID p_mesh); void _geometry_instance_add_surface(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, RID p_material, RID p_mesh); void _geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance); void _geometry_instance_update(GeometryInstance *p_geometry_instance); @@ -612,6 +614,7 @@ public: virtual GeometryInstance *geometry_instance_create(RID p_base) override; virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override; virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override; + virtual void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_override) override; virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) override; virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override; virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override; diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index 22a7c48103..8b2a60c487 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -2033,6 +2033,15 @@ void RenderForwardMobile::geometry_instance_set_material_override(GeometryInstan ginstance->data->dirty_dependencies = true; } +void RenderForwardMobile::geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_overlay) { + GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + ginstance->data->material_overlay = p_overlay; + + _geometry_instance_mark_dirty(ginstance); + ginstance->data->dirty_dependencies = true; +} + void RenderForwardMobile::geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) { GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance); ERR_FAIL_COND(!ginstance); @@ -2359,6 +2368,24 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI sdcache->sort.priority = p_material->priority; } +void RenderForwardMobile::_geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, RID p_mat_src, RID p_mesh) { + SceneShaderForwardMobile::MaterialData *material = p_material; + + _geometry_instance_add_surface_with_material(ginstance, p_surface, material, p_mat_src.get_local_index(), storage->material_get_shader_id(p_mat_src), p_mesh); + + while (material->next_pass.is_valid()) { + RID next_pass = material->next_pass; + material = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(next_pass, RendererStorageRD::SHADER_TYPE_3D); + if (!material || !material->shader_data->valid) { + break; + } + if (ginstance->data->dirty_dependencies) { + storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker); + } + _geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), storage->material_get_shader_id(next_pass), p_mesh); + } +} + void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, RID p_material, RID p_mesh) { RID m_src; @@ -2384,18 +2411,19 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward ERR_FAIL_COND(!material); - _geometry_instance_add_surface_with_material(ginstance, p_surface, material, m_src.get_local_index(), storage->material_get_shader_id(m_src), p_mesh); + _geometry_instance_add_surface_with_material_chain(ginstance, p_surface, material, m_src, p_mesh); - while (material->next_pass.is_valid()) { - RID next_pass = material->next_pass; - material = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(next_pass, RendererStorageRD::SHADER_TYPE_3D); - if (!material || !material->shader_data->valid) { - break; - } - if (ginstance->data->dirty_dependencies) { - storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker); + if (ginstance->data->material_overlay.is_valid()) { + m_src = ginstance->data->material_overlay; + + material = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D); + if (material && material->shader_data->valid) { + if (ginstance->data->dirty_dependencies) { + storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); + } + + _geometry_instance_add_surface_with_material_chain(ginstance, p_surface, material, m_src, p_mesh); } - _geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), storage->material_get_shader_id(next_pass), p_mesh); } } diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h index ea3f36a983..8274dc3b0c 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h @@ -586,6 +586,7 @@ protected: RID skeleton; Vector<RID> surface_materials; RID material_override; + RID material_overlay; AABB aabb; bool use_baked_light = false; @@ -620,6 +621,7 @@ public: PagedAllocator<GeometryInstanceLightmapSH> geometry_instance_lightmap_sh; void _geometry_instance_add_surface_with_material(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh); + void _geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, RID p_mat_src, RID p_mesh); void _geometry_instance_add_surface(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, RID p_material, RID p_mesh); void _geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance); void _geometry_instance_update(GeometryInstance *p_geometry_instance); @@ -628,6 +630,7 @@ public: virtual GeometryInstance *geometry_instance_create(RID p_base) override; virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override; virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override; + virtual void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_overlay) override; virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) override; virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override; virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override; diff --git a/servers/rendering/renderer_scene.h b/servers/rendering/renderer_scene.h index ecafb7bc08..20ca49cd71 100644 --- a/servers/rendering/renderer_scene.h +++ b/servers/rendering/renderer_scene.h @@ -95,6 +95,7 @@ public: virtual void instance_geometry_set_flag(RID p_instance, RS::InstanceFlags p_flags, bool p_enabled) = 0; virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, RS::ShadowCastingSetting p_shadow_casting_setting) = 0; virtual void instance_geometry_set_material_override(RID p_instance, RID p_material) = 0; + virtual void instance_geometry_set_material_overlay(RID p_instance, RID p_material) = 0; virtual void instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin, RS::VisibilityRangeFadeMode p_fade_mode) = 0; virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index) = 0; diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index d68038610f..8ded180633 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -636,6 +636,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) { scene_render->geometry_instance_set_skeleton(geom->geometry_instance, instance->skeleton); scene_render->geometry_instance_set_material_override(geom->geometry_instance, instance->material_override); + scene_render->geometry_instance_set_material_overlay(geom->geometry_instance, instance->material_overlay); scene_render->geometry_instance_set_surface_materials(geom->geometry_instance, instance->materials); scene_render->geometry_instance_set_transform(geom->geometry_instance, instance->transform, instance->aabb, instance->transformed_aabb); scene_render->geometry_instance_set_layer_mask(geom->geometry_instance, instance->layer_mask); @@ -1222,6 +1223,19 @@ void RendererSceneCull::instance_geometry_set_material_override(RID p_instance, } } +void RendererSceneCull::instance_geometry_set_material_overlay(RID p_instance, RID p_material) { + Instance *instance = instance_owner.get_or_null(p_instance); + ERR_FAIL_COND(!instance); + + instance->material_overlay = p_material; + _instance_queue_update(instance, false, true); + + if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) { + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); + scene_render->geometry_instance_set_material_overlay(geom->geometry_instance, p_material); + } +} + void RendererSceneCull::instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin, RS::VisibilityRangeFadeMode p_fade_mode) { Instance *instance = instance_owner.get_or_null(p_instance); ERR_FAIL_COND(!instance); @@ -3656,6 +3670,10 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { RSG::storage->material_update_dependency(p_instance->material_override, &p_instance->dependency_tracker); } + if (p_instance->material_overlay.is_valid()) { + RSG::storage->material_update_dependency(p_instance->material_overlay, &p_instance->dependency_tracker); + } + if (p_instance->base_type == RS::INSTANCE_MESH) { //remove materials no longer used and un-own them @@ -3785,6 +3803,12 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { } } + if (p_instance->material_overlay.is_valid()) { + can_cast_shadows = can_cast_shadows || RSG::storage->material_casts_shadows(p_instance->material_overlay); + is_animated = is_animated || RSG::storage->material_is_animated(p_instance->material_overlay); + _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, p_instance->material_overlay); + } + if (can_cast_shadows != geom->can_cast_shadows) { //ability to cast shadows change, let lights now for (Set<Instance *>::Element *E = geom->lights.front(); E; E = E->next()) { @@ -3897,6 +3921,7 @@ bool RendererSceneCull::free(RID p_rid) { instance_set_scenario(p_rid, RID()); instance_set_base(p_rid, RID()); instance_geometry_set_material_override(p_rid, RID()); + instance_geometry_set_material_overlay(p_rid, RID()); instance_attach_skeleton(p_rid, RID()); if (instance->instance_allocated_shader_parameters) { diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h index 81170cbd20..071d88233f 100644 --- a/servers/rendering/renderer_scene_cull.h +++ b/servers/rendering/renderer_scene_cull.h @@ -390,6 +390,7 @@ public: RID skeleton; RID material_override; + RID material_overlay; RID mesh_instance; //only used for meshes and when skeleton/blendshapes exist @@ -961,6 +962,7 @@ public: virtual void instance_geometry_set_flag(RID p_instance, RS::InstanceFlags p_flags, bool p_enabled); virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, RS::ShadowCastingSetting p_shadow_casting_setting); virtual void instance_geometry_set_material_override(RID p_instance, RID p_material); + virtual void instance_geometry_set_material_overlay(RID p_instance, RID p_material); virtual void instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin, RS::VisibilityRangeFadeMode p_fade_mode); diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h index ba4be09f7d..f99d34d292 100644 --- a/servers/rendering/renderer_scene_render.h +++ b/servers/rendering/renderer_scene_render.h @@ -51,6 +51,7 @@ public: virtual GeometryInstance *geometry_instance_create(RID p_base) = 0; virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) = 0; virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) = 0; + virtual void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_override) = 0; virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) = 0; virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) = 0; virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) = 0; diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index 9e72a9983c..ead49f053c 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -712,6 +712,7 @@ public: FUNC3(instance_geometry_set_flag, RID, InstanceFlags, bool) FUNC2(instance_geometry_set_cast_shadows_setting, RID, ShadowCastingSetting) FUNC2(instance_geometry_set_material_override, RID, RID) + FUNC2(instance_geometry_set_material_overlay, RID, RID) FUNC6(instance_geometry_set_visibility_range, RID, float, float, float, float, VisibilityRangeFadeMode) FUNC4(instance_geometry_set_lightmap, RID, RID, const Rect2 &, int) diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 29a7d1108d..1db9593473 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -32,6 +32,7 @@ #include "core/config/project_settings.h" #include "servers/rendering/rendering_server_globals.h" + RenderingServer *RenderingServer::singleton = nullptr; RenderingServer *(*RenderingServer::create_func)() = nullptr; @@ -2462,6 +2463,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("instance_geometry_set_flag", "instance", "flag", "enabled"), &RenderingServer::instance_geometry_set_flag); ClassDB::bind_method(D_METHOD("instance_geometry_set_cast_shadows_setting", "instance", "shadow_casting_setting"), &RenderingServer::instance_geometry_set_cast_shadows_setting); ClassDB::bind_method(D_METHOD("instance_geometry_set_material_override", "instance", "material"), &RenderingServer::instance_geometry_set_material_override); + ClassDB::bind_method(D_METHOD("instance_geometry_set_material_overlay", "instance", "material"), &RenderingServer::instance_geometry_set_material_overlay); ClassDB::bind_method(D_METHOD("instance_geometry_set_visibility_range", "instance", "min", "max", "min_margin", "max_margin", "fade_mode"), &RenderingServer::instance_geometry_set_visibility_range); ClassDB::bind_method(D_METHOD("instance_geometry_set_lightmap", "instance", "lightmap", "lightmap_uv_scale", "lightmap_slice"), &RenderingServer::instance_geometry_set_lightmap); ClassDB::bind_method(D_METHOD("instance_geometry_set_lod_bias", "instance", "lod_bias"), &RenderingServer::instance_geometry_set_lod_bias); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 5d3ebf7c98..d36784dbab 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -1220,6 +1220,7 @@ public: virtual void instance_geometry_set_flag(RID p_instance, InstanceFlags p_flags, bool p_enabled) = 0; virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, ShadowCastingSetting p_shadow_casting_setting) = 0; virtual void instance_geometry_set_material_override(RID p_instance, RID p_material) = 0; + virtual void instance_geometry_set_material_overlay(RID p_instance, RID p_material) = 0; virtual void instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin, VisibilityRangeFadeMode p_fade_mode) = 0; virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice) = 0; virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias) = 0; |