diff options
61 files changed, 624 insertions, 269 deletions
diff --git a/core/core_bind.cpp b/core/core_bind.cpp index 53c58084ac..892b74c26a 100644 --- a/core/core_bind.cpp +++ b/core/core_bind.cpp @@ -1072,7 +1072,6 @@ Error File::open_compressed(const String &p_path, ModeFlags p_mode_flags, Compre } Error File::open(const String &p_path, ModeFlags p_mode_flags) { - close(); Error err; f = FileAccess::open(p_path, p_mode_flags, &err); if (f.is_valid()) { diff --git a/core/extension/gdnative_interface.cpp b/core/extension/gdnative_interface.cpp index b5b340731d..a312ce4ebd 100644 --- a/core/extension/gdnative_interface.cpp +++ b/core/extension/gdnative_interface.cpp @@ -241,6 +241,13 @@ static GDNativeBool gdnative_variant_booleanize(const GDNativeVariantPtr p_self) return self->booleanize(); } +static void gdnative_variant_sub(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, GDNativeVariantPtr r_dst) { + const Variant *a = (const Variant *)p_a; + const Variant *b = (const Variant *)p_b; + memnew_placement(r_dst, Variant); + Variant::sub(*a, *b, *(Variant *)r_dst); +} + static void gdnative_variant_blend(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, float p_c, GDNativeVariantPtr r_dst) { const Variant *a = (const Variant *)p_a; const Variant *b = (const Variant *)p_b; @@ -939,6 +946,7 @@ void gdnative_setup_interface(GDNativeInterface *p_interface) { gdni.variant_iter_get = gdnative_variant_iter_get; gdni.variant_hash_compare = gdnative_variant_hash_compare; gdni.variant_booleanize = gdnative_variant_booleanize; + gdni.variant_sub = gdnative_variant_sub; gdni.variant_blend = gdnative_variant_blend; gdni.variant_interpolate = gdnative_variant_interpolate; gdni.variant_duplicate = gdnative_variant_duplicate; diff --git a/core/extension/gdnative_interface.h b/core/extension/gdnative_interface.h index 732a1b5af0..2bac52dc4a 100644 --- a/core/extension/gdnative_interface.h +++ b/core/extension/gdnative_interface.h @@ -416,6 +416,7 @@ typedef struct { void (*variant_iter_get)(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeVariantPtr r_ret, GDNativeBool *r_valid); GDNativeBool (*variant_hash_compare)(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_other); GDNativeBool (*variant_booleanize)(const GDNativeVariantPtr p_self); + void (*variant_sub)(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, GDNativeVariantPtr r_dst); void (*variant_blend)(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, float p_c, GDNativeVariantPtr r_dst); void (*variant_interpolate)(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, float p_c, GDNativeVariantPtr r_dst); void (*variant_duplicate)(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_ret, GDNativeBool p_deep); diff --git a/core/input/input.cpp b/core/input/input.cpp index 343076b4e1..0db20a7c82 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -855,6 +855,8 @@ void Input::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, co return; } + ERR_FAIL_INDEX(p_shape, CursorShape::CURSOR_MAX); + set_custom_mouse_cursor_func(p_cursor, p_shape, p_hotspot); } diff --git a/core/io/image.cpp b/core/io/image.cpp index fad9942017..4aed5a913a 100644 --- a/core/io/image.cpp +++ b/core/io/image.cpp @@ -3276,7 +3276,7 @@ Ref<Image> Image::rgbe_to_srgb() { for (int row = 0; row < height; row++) { for (int col = 0; col < width; col++) { - new_image->set_pixel(col, row, get_pixel(col, row).to_srgb()); + new_image->set_pixel(col, row, get_pixel(col, row).linear_to_srgb()); } } diff --git a/core/math/color.h b/core/math/color.h index b90a0f33a2..91e0bf5532 100644 --- a/core/math/color.h +++ b/core/math/color.h @@ -169,14 +169,14 @@ struct _NO_DISCARD_ Color { return res; } - _FORCE_INLINE_ Color to_linear() const { + _FORCE_INLINE_ Color srgb_to_linear() const { return Color( r < 0.04045f ? r * (1.0 / 12.92) : Math::pow((r + 0.055f) * (float)(1.0 / (1 + 0.055)), 2.4f), g < 0.04045f ? g * (1.0 / 12.92) : Math::pow((g + 0.055f) * (float)(1.0 / (1 + 0.055)), 2.4f), b < 0.04045f ? b * (1.0 / 12.92) : Math::pow((b + 0.055f) * (float)(1.0 / (1 + 0.055)), 2.4f), a); } - _FORCE_INLINE_ Color to_srgb() const { + _FORCE_INLINE_ Color linear_to_srgb() const { return Color( r < 0.0031308f ? 12.92f * r : (1.0f + 0.055f) * Math::pow(r, 1.0f / 2.4f) - 0.055f, g < 0.0031308f ? 12.92f * g : (1.0f + 0.055f) * Math::pow(g, 1.0f / 2.4f) - 0.055f, diff --git a/core/variant/variant.h b/core/variant/variant.h index ca18249f36..475bf7158d 100644 --- a/core/variant/variant.h +++ b/core/variant/variant.h @@ -511,6 +511,7 @@ public: Variant recursive_duplicate(bool p_deep, int recursion_count) const; static void blend(const Variant &a, const Variant &b, float c, Variant &r_dst); static void interpolate(const Variant &a, const Variant &b, float c, Variant &r_dst); + static void sub(const Variant &a, const Variant &b, Variant &r_dst); /* Built-In Methods */ diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index c11925fa8c..f1daf1de13 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -1656,8 +1656,8 @@ static void _register_variant_builtin_methods() { bind_method(Color, darkened, sarray("amount"), varray()); bind_method(Color, blend, sarray("over"), varray()); bind_method(Color, get_luminance, sarray(), varray()); - bind_method(Color, to_linear, sarray(), varray()); - bind_method(Color, to_srgb, sarray(), varray()); + bind_method(Color, srgb_to_linear, sarray(), varray()); + bind_method(Color, linear_to_srgb, sarray(), varray()); bind_method(Color, is_equal_approx, sarray("to"), varray()); diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp index e604ff9567..705aa27be6 100644 --- a/core/variant/variant_setget.cpp +++ b/core/variant/variant_setget.cpp @@ -1868,6 +1868,110 @@ Variant Variant::recursive_duplicate(bool p_deep, int recursion_count) const { } } +void Variant::sub(const Variant &a, const Variant &b, Variant &r_dst) { + if (a.type != b.type) { + return; + } + + switch (a.type) { + case NIL: { + r_dst = Variant(); + } + return; + case INT: { + int64_t va = a._data._int; + int64_t vb = b._data._int; + r_dst = int(va - vb); + } + return; + case FLOAT: { + double ra = a._data._float; + double rb = b._data._float; + r_dst = ra - rb; + } + return; + case VECTOR2: { + r_dst = *reinterpret_cast<const Vector2 *>(a._data._mem) - *reinterpret_cast<const Vector2 *>(b._data._mem); + } + return; + case VECTOR2I: { + int32_t vax = reinterpret_cast<const Vector2i *>(a._data._mem)->x; + int32_t vbx = reinterpret_cast<const Vector2i *>(b._data._mem)->x; + int32_t vay = reinterpret_cast<const Vector2i *>(a._data._mem)->y; + int32_t vby = reinterpret_cast<const Vector2i *>(b._data._mem)->y; + r_dst = Vector2i(int32_t(vax - vbx), int32_t(vay - vby)); + } + return; + case RECT2: { + const Rect2 *ra = reinterpret_cast<const Rect2 *>(a._data._mem); + const Rect2 *rb = reinterpret_cast<const Rect2 *>(b._data._mem); + r_dst = Rect2(ra->position - rb->position, ra->size - rb->size); + } + return; + case RECT2I: { + const Rect2i *ra = reinterpret_cast<const Rect2i *>(a._data._mem); + const Rect2i *rb = reinterpret_cast<const Rect2i *>(b._data._mem); + + int32_t vax = ra->position.x; + int32_t vay = ra->position.y; + int32_t vbx = ra->size.x; + int32_t vby = ra->size.y; + int32_t vcx = rb->position.x; + int32_t vcy = rb->position.y; + int32_t vdx = rb->size.x; + int32_t vdy = rb->size.y; + + r_dst = Rect2i(int32_t(vax - vbx), int32_t(vay - vby), int32_t(vcx - vdx), int32_t(vcy - vdy)); + } + return; + case VECTOR3: { + r_dst = *reinterpret_cast<const Vector3 *>(a._data._mem) - *reinterpret_cast<const Vector3 *>(b._data._mem); + } + return; + case VECTOR3I: { + int32_t vax = reinterpret_cast<const Vector3i *>(a._data._mem)->x; + int32_t vbx = reinterpret_cast<const Vector3i *>(b._data._mem)->x; + int32_t vay = reinterpret_cast<const Vector3i *>(a._data._mem)->y; + int32_t vby = reinterpret_cast<const Vector3i *>(b._data._mem)->y; + int32_t vaz = reinterpret_cast<const Vector3i *>(a._data._mem)->z; + int32_t vbz = reinterpret_cast<const Vector3i *>(b._data._mem)->z; + r_dst = Vector3i(int32_t(vax - vbx), int32_t(vay - vby), int32_t(vaz - vbz)); + } + return; + case AABB: { + const ::AABB *ra = reinterpret_cast<const ::AABB *>(a._data._mem); + const ::AABB *rb = reinterpret_cast<const ::AABB *>(b._data._mem); + r_dst = ::AABB(ra->position - rb->position, ra->size - rb->size); + } + return; + case QUATERNION: { + Quaternion empty_rot; + const Quaternion *qa = reinterpret_cast<const Quaternion *>(a._data._mem); + const Quaternion *qb = reinterpret_cast<const Quaternion *>(b._data._mem); + r_dst = (*qb).inverse() * *qa; + } + return; + case COLOR: { + const Color *ca = reinterpret_cast<const Color *>(a._data._mem); + const Color *cb = reinterpret_cast<const Color *>(b._data._mem); + float new_r = ca->r - cb->r; + float new_g = ca->g - cb->g; + float new_b = ca->b - cb->b; + float new_a = ca->a - cb->a; + new_r = new_r > 1.0 ? 1.0 : new_r; + new_g = new_g > 1.0 ? 1.0 : new_g; + new_b = new_b > 1.0 ? 1.0 : new_b; + new_a = new_a > 1.0 ? 1.0 : new_a; + r_dst = Color(new_r, new_g, new_b, new_a); + } + return; + default: { + r_dst = a; + } + return; + } +} + void Variant::blend(const Variant &a, const Variant &b, float c, Variant &r_dst) { if (a.type != b.type) { if (a.is_num() && b.is_num()) { diff --git a/doc/classes/Camera3D.xml b/doc/classes/Camera3D.xml index f7a0d41626..5008cd826e 100644 --- a/doc/classes/Camera3D.xml +++ b/doc/classes/Camera3D.xml @@ -192,7 +192,7 @@ The camera's projection mode. In [constant PROJECTION_PERSPECTIVE] mode, objects' Z distance from the camera's local space scales their perceived size. </member> <member name="size" type="float" setter="set_size" getter="get_size" default="1.0"> - The camera's size measured as 1/2 the width or height. Only applicable in orthogonal mode. Since [member keep_aspect] locks on axis, [code]size[/code] sets the other axis' size length. + The camera's size measured as 1/2 the width or height. Only applicable in orthogonal and frustum modes. Since [member keep_aspect] locks on axis, [code]size[/code] sets the other axis' size length. </member> <member name="v_offset" type="float" setter="set_v_offset" getter="get_v_offset" default="0.0"> The vertical (Y) offset of the camera viewport. diff --git a/doc/classes/CollisionObject2D.xml b/doc/classes/CollisionObject2D.xml index 99bf9f7853..5d025985cc 100644 --- a/doc/classes/CollisionObject2D.xml +++ b/doc/classes/CollisionObject2D.xml @@ -5,6 +5,7 @@ </brief_description> <description> CollisionObject2D is the base class for 2D physics objects. It can hold any number of 2D collision [Shape2D]s. Each shape must be assigned to a [i]shape owner[/i]. The CollisionObject2D can have any number of shape owners. Shape owners are not nodes and do not appear in the editor, but are accessible through code using the [code]shape_owner_*[/code] methods. + [b]Note:[/b] Only collisions between objects within the same canvas ([Viewport] canvas or [CanvasLayer]) are supported. The behavior of collisions between objects in different canvases is undefined. </description> <tutorials> </tutorials> diff --git a/doc/classes/Color.xml b/doc/classes/Color.xml index 5b48804d9d..7b8a57ed22 100644 --- a/doc/classes/Color.xml +++ b/doc/classes/Color.xml @@ -183,7 +183,7 @@ <description> Returns the luminance of the color in the [code][0.0, 1.0][/code] range. This is useful when determining light or dark color. Colors with a luminance smaller than 0.5 can be generally considered dark. - [b]Note:[/b] [method get_luminance] relies on the colour being in the linear color space to return an accurate relative luminance value. If the color is in the sRGB color space, use [method to_linear] to convert it to the linear color space first. + [b]Note:[/b] [method get_luminance] relies on the colour being in the linear color space to return an accurate relative luminance value. If the color is in the sRGB color space, use [method srgb_to_linear] to convert it to the linear color space first. </description> </method> <method name="get_named_color" qualifiers="static"> @@ -321,6 +321,18 @@ [/codeblocks] </description> </method> + <method name="linear_to_srgb" qualifiers="const"> + <return type="Color" /> + <description> + Returns the color converted to the [url=https://en.wikipedia.org/wiki/SRGB]sRGB[/url] color space. This assumes the original color is in the linear color space. See also [method srgb_to_linear] which performs the opposite operation. + </description> + </method> + <method name="srgb_to_linear" qualifiers="const"> + <return type="Color" /> + <description> + Returns the color converted to the linear color space. This assumes the original color is in the sRGB color space. See also [method linear_to_srgb] which performs the opposite operation. + </description> + </method> <method name="to_abgr32" qualifiers="const"> <return type="int" /> <description> @@ -405,12 +417,6 @@ [/codeblocks] </description> </method> - <method name="to_linear" qualifiers="const"> - <return type="Color" /> - <description> - Returns the color converted to the linear color space. This assumes the original color is in the sRGB color space. See also [method to_srgb] which performs the opposite operation. - </description> - </method> <method name="to_rgba32" qualifiers="const"> <return type="int" /> <description> @@ -443,12 +449,6 @@ [/codeblocks] </description> </method> - <method name="to_srgb" qualifiers="const"> - <return type="Color" /> - <description> - Returns the color converted to the [url=https://en.wikipedia.org/wiki/SRGB]sRGB[/url] color space. This assumes the original color is in the linear color space. See also [method to_linear] which performs the opposite operation. - </description> - </method> </methods> <members> <member name="a" type="float" setter="" getter="" default="1.0"> diff --git a/doc/classes/EditorSceneFormatImporter.xml b/doc/classes/EditorSceneFormatImporter.xml index 63c1498f20..0290d7207d 100644 --- a/doc/classes/EditorSceneFormatImporter.xml +++ b/doc/classes/EditorSceneFormatImporter.xml @@ -29,16 +29,8 @@ <method name="_get_option_visibility" qualifiers="virtual const"> <return type="Variant" /> <argument index="0" name="path" type="String" /> - <argument index="1" name="option" type="String" /> - <description> - </description> - </method> - <method name="_import_animation" qualifiers="virtual"> - <return type="Animation" /> - <argument index="0" name="path" type="String" /> - <argument index="1" name="flags" type="int" /> - <argument index="2" name="options" type="Dictionary" /> - <argument index="3" name="bake_fps" type="int" /> + <argument index="1" name="for_animation" type="bool" /> + <argument index="2" name="option" type="String" /> <description> </description> </method> @@ -63,5 +55,7 @@ </constant> <constant name="IMPORT_USE_NAMED_SKIN_BINDS" value="16"> </constant> + <constant name="IMPORT_DISCARD_MESHES_AND_MATERIALS" value="32"> + </constant> </constants> </class> diff --git a/doc/classes/EditorScenePostImportPlugin.xml b/doc/classes/EditorScenePostImportPlugin.xml index de9d5e067a..0fdbd5db1e 100644 --- a/doc/classes/EditorScenePostImportPlugin.xml +++ b/doc/classes/EditorScenePostImportPlugin.xml @@ -34,7 +34,8 @@ <method name="_get_internal_option_visibility" qualifiers="virtual const"> <return type="Variant" /> <argument index="0" name="category" type="int" /> - <argument index="1" name="option" type="String" /> + <argument index="1" name="for_animation" type="bool" /> + <argument index="2" name="option" type="String" /> <description> Return true or false whether a given option should be visible. Return null to ignore. </description> @@ -42,7 +43,8 @@ <method name="_get_option_visibility" qualifiers="virtual const"> <return type="Variant" /> <argument index="0" name="path" type="String" /> - <argument index="1" name="option" type="String" /> + <argument index="1" name="for_animation" type="bool" /> + <argument index="2" name="option" type="String" /> <description> Return true or false whether a given option should be visible. Return null to ignore. </description> diff --git a/doc/classes/Signal.xml b/doc/classes/Signal.xml index c5855e30a4..049e7f8777 100644 --- a/doc/classes/Signal.xml +++ b/doc/classes/Signal.xml @@ -6,6 +6,8 @@ <description> </description> <tutorials> + <link title="Using Signals">$DOCS_URL/getting_started/step_by_step/signals.html</link> + <link title="GDScript Basics">$DOCS_URL/tutorials/scripting/gdscript/gdscript_basics.html#signals</link> </tutorials> <constructors> <constructor name="Signal"> diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 53631c1e3b..685dde4d98 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -2252,6 +2252,8 @@ void AnimationTrackEdit::_notification(int p_what) { break; case NOTIFICATION_MOUSE_EXIT: hovered = false; + // When the mouse cursor exits the track, we're no longer hovering any keyframe. + hovering_key_idx = -1; update(); [[fallthrough]]; case NOTIFICATION_DRAG_END: { @@ -2365,7 +2367,13 @@ void AnimationTrackEdit::draw_key(int p_index, float p_pixels_sec, int p_x, bool } } - draw_texture(icon_to_draw, ofs); + // Use a different color for the currently hovered key. + // The color multiplier is chosen to work with both dark and light editor themes, + // and on both unselected and selected key icons. + draw_texture( + icon_to_draw, + ofs, + p_index == hovering_key_idx ? get_theme_color(SNAME("folder_icon_modulate"), SNAME("FileDialog")) : Color(1, 1, 1)); } // Helper. @@ -2952,6 +2960,59 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) { } Ref<InputEventMouseMotion> mm = p_event; + if (mm.is_valid()) { + const int previous_hovering_key_idx = hovering_key_idx; + + // Hovering compressed keyframes for editing is not possible. + if (!animation->track_is_compressed(track)) { + const float scale = timeline->get_zoom_scale(); + const int limit = timeline->get_name_limit(); + const int limit_end = get_size().width - timeline->get_buttons_width(); + // Left Border including space occupied by keyframes on t=0. + const int limit_start_hitbox = limit - type_icon->get_width(); + const Point2 pos = mm->get_position(); + + if (pos.x >= limit_start_hitbox && pos.x <= limit_end) { + // Use the same logic as key selection to ensure that hovering accurately represents + // which key will be selected when clicking. + int key_idx = -1; + float key_distance = 1e20; + + hovering_key_idx = -1; + + // Hovering should happen in the opposite order of drawing for more accurate overlap hovering. + for (int i = animation->track_get_key_count(track) - 1; i >= 0; i--) { + Rect2 rect = get_key_rect(i, scale); + float offset = animation->track_get_key_time(track, i) - timeline->get_value(); + offset = offset * scale + limit; + rect.position.x += offset; + + if (rect.has_point(pos)) { + if (is_key_selectable_by_distance()) { + const float distance = ABS(offset - pos.x); + if (key_idx == -1 || distance < key_distance) { + key_idx = i; + key_distance = distance; + hovering_key_idx = i; + } + } else { + // First one does it. + hovering_key_idx = i; + break; + } + } + } + + print_line(hovering_key_idx); + + if (hovering_key_idx != previous_hovering_key_idx) { + // Required to draw keyframe hover feedback on the correct keyframe. + update(); + } + } + } + } + if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE && moving_selection_attempt) { if (!moving_selection) { moving_selection = true; diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h index a8a5d11c12..0f6d12b4d4 100644 --- a/editor/animation_track_editor.h +++ b/editor/animation_track_editor.h @@ -173,6 +173,7 @@ class AnimationTrackEdit : public Control { bool hovered = false; bool clicking_on_name = false; + int hovering_key_idx = -1; void _zoom_changed(); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 99e30593a9..6fe6309eed 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -5997,18 +5997,22 @@ EditorNode::EditorNode() { import_scene.instantiate(); ResourceFormatImporter::get_singleton()->add_importer(import_scene); + Ref<ResourceImporterScene> import_animation; + import_animation = Ref<ResourceImporterScene>(memnew(ResourceImporterScene(true))); + ResourceFormatImporter::get_singleton()->add_importer(import_animation); + { Ref<EditorSceneFormatImporterCollada> import_collada; import_collada.instantiate(); - import_scene->add_importer(import_collada); + ResourceImporterScene::add_importer(import_collada); Ref<EditorOBJImporter> import_obj2; import_obj2.instantiate(); - import_scene->add_importer(import_obj2); + ResourceImporterScene::add_importer(import_obj2); Ref<EditorSceneFormatImporterESCN> import_escn; import_escn.instantiate(); - import_scene->add_importer(import_escn); + ResourceImporterScene::add_importer(import_escn); } Ref<ResourceImporterBitMap> import_bitmap; @@ -7245,6 +7249,7 @@ EditorNode::EditorNode() { EditorNode::~EditorNode() { EditorInspector::cleanup_plugins(); EditorTranslationParser::get_singleton()->clean_parsers(); + ResourceImporterScene::clean_up_importer_plugins(); remove_print_handler(&print_handler); EditorHelp::cleanup_doc(); diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index 5166200ee3..6596c245bc 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -763,20 +763,20 @@ void EditorPlugin::remove_inspector_plugin(const Ref<EditorInspectorPlugin> &p_p void EditorPlugin::add_scene_format_importer_plugin(const Ref<EditorSceneFormatImporter> &p_importer, bool p_first_priority) { ERR_FAIL_COND(!p_importer.is_valid()); - ResourceImporterScene::get_singleton()->add_importer(p_importer, p_first_priority); + ResourceImporterScene::add_importer(p_importer, p_first_priority); } void EditorPlugin::remove_scene_format_importer_plugin(const Ref<EditorSceneFormatImporter> &p_importer) { ERR_FAIL_COND(!p_importer.is_valid()); - ResourceImporterScene::get_singleton()->remove_importer(p_importer); + ResourceImporterScene::remove_importer(p_importer); } void EditorPlugin::add_scene_post_import_plugin(const Ref<EditorScenePostImportPlugin> &p_plugin, bool p_first_priority) { - ResourceImporterScene::get_singleton()->add_post_importer_plugin(p_plugin, p_first_priority); + ResourceImporterScene::add_post_importer_plugin(p_plugin, p_first_priority); } void EditorPlugin::remove_scene_post_import_plugin(const Ref<EditorScenePostImportPlugin> &p_plugin) { - ResourceImporterScene::get_singleton()->remove_post_importer_plugin(p_plugin); + ResourceImporterScene::remove_post_importer_plugin(p_plugin); } int find(const PackedStringArray &a, const String &v) { diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index a45568db48..778c5c33ff 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -989,7 +989,7 @@ void FileSystemDock::_select_file(const String &p_path, bool p_select_in_favorit { List<String> importer_exts; - ResourceImporterScene::get_singleton()->get_recognized_extensions(&importer_exts); + ResourceImporterScene::get_scene_singleton()->get_recognized_extensions(&importer_exts); String extension = fpath.get_extension(); for (const String &E : importer_exts) { if (extension.nocasecmp_to(E) == 0) { @@ -1000,7 +1000,27 @@ void FileSystemDock::_select_file(const String &p_path, bool p_select_in_favorit } if (is_imported) { - ResourceImporterScene::get_singleton()->show_advanced_options(fpath); + ResourceImporterScene::get_scene_singleton()->show_advanced_options(fpath); + } else { + EditorNode::get_singleton()->open_request(fpath); + } + } else if (ResourceLoader::get_resource_type(fpath) == "AnimationLibrary") { + bool is_imported = false; + + { + List<String> importer_exts; + ResourceImporterScene::get_animation_singleton()->get_recognized_extensions(&importer_exts); + String extension = fpath.get_extension(); + for (const String &E : importer_exts) { + if (extension.nocasecmp_to(E) == 0) { + is_imported = true; + break; + } + } + } + + if (is_imported) { + ResourceImporterScene::get_animation_singleton()->show_advanced_options(fpath); } else { EditorNode::get_singleton()->open_request(fpath); } diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp index 97fc33ad25..013dcb5deb 100644 --- a/editor/import/editor_import_collada.cpp +++ b/editor/import/editor_import_collada.cpp @@ -1817,26 +1817,5 @@ Node *EditorSceneFormatImporterCollada::import_scene(const String &p_path, uint3 return state.scene; } -Ref<Animation> EditorSceneFormatImporterCollada::import_animation(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps) { - ColladaImport state; - - state.use_mesh_builtin_materials = false; - - Error err = state.load(p_path, Collada::IMPORT_FLAG_ANIMATION, p_flags & EditorSceneFormatImporter::IMPORT_GENERATE_TANGENT_ARRAYS); - ERR_FAIL_COND_V_MSG(err != OK, RES(), "Cannot load animation from file '" + p_path + "'."); - - state.create_animations(true); - if (state.scene) { - memdelete(state.scene); - } - - if (state.animations.size() == 0) { - return Ref<Animation>(); - } - Ref<Animation> anim = state.animations[0]; - - return anim; -} - EditorSceneFormatImporterCollada::EditorSceneFormatImporterCollada() { } diff --git a/editor/import/editor_import_collada.h b/editor/import/editor_import_collada.h index c32d785d1c..be3f74d821 100644 --- a/editor/import/editor_import_collada.h +++ b/editor/import/editor_import_collada.h @@ -40,7 +40,6 @@ public: virtual uint32_t get_import_flags() const override; virtual void get_extensions(List<String> *r_extensions) const override; virtual Node *import_scene(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps = nullptr, Error *r_err = nullptr) override; - virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps) override; EditorSceneFormatImporterCollada(); }; diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/resource_importer_obj.cpp index 308eb9cefa..88837d089a 100644 --- a/editor/import/resource_importer_obj.cpp +++ b/editor/import/resource_importer_obj.cpp @@ -457,10 +457,6 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, co return scene; } -Ref<Animation> EditorOBJImporter::import_animation(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps) { - return Ref<Animation>(); -} - void EditorOBJImporter::get_extensions(List<String> *r_extensions) const { r_extensions->push_back("obj"); } diff --git a/editor/import/resource_importer_obj.h b/editor/import/resource_importer_obj.h index d7e3f0209d..1b5e8bbdc1 100644 --- a/editor/import/resource_importer_obj.h +++ b/editor/import/resource_importer_obj.h @@ -40,7 +40,6 @@ public: virtual uint32_t get_import_flags() const override; virtual void get_extensions(List<String> *r_extensions) const override; virtual Node *import_scene(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr) override; - virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps) override; EditorOBJImporter(); }; diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index bfa71bfda4..bdb0c3c493 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -87,26 +87,13 @@ Node *EditorSceneFormatImporter::import_scene(const String &p_path, uint32_t p_f ERR_FAIL_V(nullptr); } -Ref<Animation> EditorSceneFormatImporter::import_animation(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps) { - Dictionary options_dict; - for (const KeyValue<StringName, Variant> &elem : p_options) { - options_dict[elem.key] = elem.value; - } - Ref<Animation> ret; - if (GDVIRTUAL_CALL(_import_animation, p_path, p_flags, options_dict, p_bake_fps, ret)) { - return ret; - } - - ERR_FAIL_V(nullptr); -} - void EditorSceneFormatImporter::get_import_options(const String &p_path, List<ResourceImporter::ImportOption> *r_options) { GDVIRTUAL_CALL(_get_import_options, p_path); } -Variant EditorSceneFormatImporter::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) { +Variant EditorSceneFormatImporter::get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, const Map<StringName, Variant> &p_options) { Variant ret; - GDVIRTUAL_CALL(_get_option_visibility, p_path, p_option, ret); + GDVIRTUAL_CALL(_get_option_visibility, p_path, p_for_animation, p_option, ret); return ret; } @@ -114,15 +101,15 @@ void EditorSceneFormatImporter::_bind_methods() { GDVIRTUAL_BIND(_get_import_flags); GDVIRTUAL_BIND(_get_extensions); GDVIRTUAL_BIND(_import_scene, "path", "flags", "options", "bake_fps"); - GDVIRTUAL_BIND(_import_animation, "path", "flags", "options", "bake_fps"); GDVIRTUAL_BIND(_get_import_options, "path"); - GDVIRTUAL_BIND(_get_option_visibility, "path", "option"); + GDVIRTUAL_BIND(_get_option_visibility, "path", "for_animation", "option"); BIND_CONSTANT(IMPORT_SCENE); BIND_CONSTANT(IMPORT_ANIMATION); BIND_CONSTANT(IMPORT_FAIL_ON_MISSING_DEPENDENCIES); BIND_CONSTANT(IMPORT_GENERATE_TANGENT_ARRAYS); BIND_CONSTANT(IMPORT_USE_NAMED_SKIN_BINDS); + BIND_CONSTANT(IMPORT_DISCARD_MESHES_AND_MATERIALS); } ///////////////////////////////// @@ -179,10 +166,10 @@ void EditorScenePostImportPlugin::get_internal_import_options(InternalImportCate GDVIRTUAL_CALL(_get_internal_import_options, p_category); current_option_list = nullptr; } -Variant EditorScenePostImportPlugin::get_internal_option_visibility(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const { +Variant EditorScenePostImportPlugin::get_internal_option_visibility(InternalImportCategory p_category, bool p_for_animation, const String &p_option, const Map<StringName, Variant> &p_options) const { current_options = &p_options; Variant ret; - GDVIRTUAL_CALL(_get_internal_option_visibility, p_category, p_option, ret); + GDVIRTUAL_CALL(_get_internal_option_visibility, p_category, p_for_animation, p_option, ret); current_options = nullptr; return ret; } @@ -205,10 +192,10 @@ void EditorScenePostImportPlugin::get_import_options(const String &p_path, List< GDVIRTUAL_CALL(_get_import_options, p_path); current_option_list = nullptr; } -Variant EditorScenePostImportPlugin::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { +Variant EditorScenePostImportPlugin::get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, const Map<StringName, Variant> &p_options) const { current_options = &p_options; Variant ret; - GDVIRTUAL_CALL(_get_option_visibility, p_path, p_option, ret); + GDVIRTUAL_CALL(_get_option_visibility, p_path, p_for_animation, p_option, ret); current_options = nullptr; return ret; } @@ -231,11 +218,11 @@ void EditorScenePostImportPlugin::_bind_methods() { ClassDB::bind_method(D_METHOD("add_import_option_advanced", "type", "name", "default_value", "hint", "hint_string", "usage_flags"), &EditorScenePostImportPlugin::add_import_option_advanced, DEFVAL(PROPERTY_HINT_NONE), DEFVAL(""), DEFVAL(PROPERTY_USAGE_DEFAULT)); GDVIRTUAL_BIND(_get_internal_import_options, "category"); - GDVIRTUAL_BIND(_get_internal_option_visibility, "category", "option"); + GDVIRTUAL_BIND(_get_internal_option_visibility, "category", "for_animation", "option"); GDVIRTUAL_BIND(_get_internal_option_update_view_required, "category", "option"); GDVIRTUAL_BIND(_internal_process, "category", "base_node", "node", "resource"); GDVIRTUAL_BIND(_get_import_options, "path"); - GDVIRTUAL_BIND(_get_option_visibility, "path", "option"); + GDVIRTUAL_BIND(_get_option_visibility, "path", "for_animation", "option"); GDVIRTUAL_BIND(_pre_process, "scene"); GDVIRTUAL_BIND(_post_process, "scene"); @@ -251,11 +238,11 @@ void EditorScenePostImportPlugin::_bind_methods() { ///////////////////////////////////////////////////////// String ResourceImporterScene::get_importer_name() const { - return "scene"; + return animation_importer ? "animation_library" : "scene"; } String ResourceImporterScene::get_visible_name() const { - return "Scene"; + return animation_importer ? "Animation Library" : "Scene"; } void ResourceImporterScene::get_recognized_extensions(List<String> *p_extensions) const { @@ -265,11 +252,11 @@ void ResourceImporterScene::get_recognized_extensions(List<String> *p_extensions } String ResourceImporterScene::get_save_extension() const { - return "scn"; + return animation_importer ? "res" : "scn"; } String ResourceImporterScene::get_resource_type() const { - return "PackedScene"; + return animation_importer ? "AnimationLibrary" : "PackedScene"; } int ResourceImporterScene::get_format_version() const { @@ -277,26 +264,34 @@ int ResourceImporterScene::get_format_version() const { } bool ResourceImporterScene::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { - if (p_option.begins_with("animation/")) { + if (animation_importer) { + if (p_option == "animation/import") { // Option ignored, animation always imported. + return false; + } + } else if (p_option.begins_with("animation/")) { if (p_option != "animation/import" && !bool(p_options["animation/import"])) { return false; } } + if (animation_importer && (p_option.begins_with("nodes/") || p_option.begins_with("meshes/") || p_option.begins_with("skins/"))) { + return false; // Nothing to do here for animations. + } + if (p_option == "meshes/lightmap_texel_size" && int(p_options["meshes/light_baking"]) != 2) { // Only display the lightmap texel size import option when using the Static Lightmaps light baking mode. return false; } for (int i = 0; i < post_importer_plugins.size(); i++) { - Variant ret = post_importer_plugins.write[i]->get_option_visibility(p_path, p_option, p_options); + Variant ret = post_importer_plugins.write[i]->get_option_visibility(p_path, animation_importer, p_option, p_options); if (ret.get_type() == Variant::BOOL) { return ret; } } for (Ref<EditorSceneFormatImporter> importer : importers) { - Variant ret = importer->get_option_visibility(p_path, p_option, p_options); + Variant ret = importer->get_option_visibility(p_path, animation_importer, p_option, p_options); if (ret.get_type() == Variant::BOOL) { return ret; } @@ -1482,7 +1477,7 @@ bool ResourceImporterScene::get_internal_option_visibility(InternalImportCategor } for (int i = 0; i < post_importer_plugins.size(); i++) { - Variant ret = post_importer_plugins.write[i]->get_internal_option_visibility(EditorScenePostImportPlugin::InternalImportCategory(p_category), p_option, p_options); + Variant ret = post_importer_plugins.write[i]->get_internal_option_visibility(EditorScenePostImportPlugin::InternalImportCategory(p_category), animation_importer, p_option, p_options); if (ret.get_type() == Variant::BOOL) { return ret; } @@ -1974,8 +1969,13 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p int import_flags = 0; - if (bool(p_options["animation/import"])) { + if (animation_importer) { import_flags |= EditorSceneFormatImporter::IMPORT_ANIMATION; + import_flags |= EditorSceneFormatImporter::IMPORT_DISCARD_MESHES_AND_MATERIALS; + } else { + if (bool(p_options["animation/import"])) { + import_flags |= EditorSceneFormatImporter::IMPORT_ANIMATION; + } } if (bool(p_options["skins/use_named_skins"])) { @@ -2139,11 +2139,35 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p progress.step(TTR("Saving..."), 104); - Ref<PackedScene> packer = memnew(PackedScene); - packer->pack(scene); - print_verbose("Saving scene to: " + p_save_path + ".scn"); - err = ResourceSaver::save(p_save_path + ".scn", packer); //do not take over, let the changed files reload themselves - ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save scene to file '" + p_save_path + ".scn'."); + if (animation_importer) { + Ref<AnimationLibrary> library; + for (int i = 0; i < scene->get_child_count(); i++) { + AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(scene->get_child(i)); + if (ap) { + List<StringName> libs; + ap->get_animation_library_list(&libs); + if (libs.size()) { + library = ap->get_animation_library(libs.front()->get()); + break; + } + } + } + + if (!library.is_valid()) { + library.instantiate(); // Will be empty + } + + print_verbose("Saving animation to: " + p_save_path + ".scn"); + err = ResourceSaver::save(p_save_path + ".res", library); //do not take over, let the changed files reload themselves + ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save animation to file '" + p_save_path + ".res'."); + + } else { + Ref<PackedScene> packer = memnew(PackedScene); + packer->pack(scene); + print_verbose("Saving scene to: " + p_save_path + ".scn"); + err = ResourceSaver::save(p_save_path + ".scn", packer); //do not take over, let the changed files reload themselves + ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save scene to file '" + p_save_path + ".scn'."); + } memdelete(scene); @@ -2153,17 +2177,26 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p return OK; } -ResourceImporterScene *ResourceImporterScene::singleton = nullptr; +ResourceImporterScene *ResourceImporterScene::scene_singleton = nullptr; +ResourceImporterScene *ResourceImporterScene::animation_singleton = nullptr; + +Vector<Ref<EditorSceneFormatImporter>> ResourceImporterScene::importers; +Vector<Ref<EditorScenePostImportPlugin>> ResourceImporterScene::post_importer_plugins; bool ResourceImporterScene::ResourceImporterScene::has_advanced_options() const { return true; } void ResourceImporterScene::ResourceImporterScene::show_advanced_options(const String &p_path) { - SceneImportSettings::get_singleton()->open_settings(p_path); + SceneImportSettings::get_singleton()->open_settings(p_path, animation_importer); } -ResourceImporterScene::ResourceImporterScene() { - singleton = this; +ResourceImporterScene::ResourceImporterScene(bool p_animation_import) { + if (p_animation_import) { + animation_singleton = this; + } else { + scene_singleton = this; + } + animation_importer = p_animation_import; } void ResourceImporterScene::add_importer(Ref<EditorSceneFormatImporter> p_importer, bool p_first_priority) { @@ -2192,6 +2225,11 @@ void ResourceImporterScene::remove_importer(Ref<EditorSceneFormatImporter> p_imp importers.erase(p_importer); } +void ResourceImporterScene::clean_up_importer_plugins() { + importers.clear(); + post_importer_plugins.clear(); +} + /////////////////////////////////////// uint32_t EditorSceneFormatImporterESCN::get_import_flags() const { @@ -2212,7 +2250,3 @@ Node *EditorSceneFormatImporterESCN::import_scene(const String &p_path, uint32_t return scene; } - -Ref<Animation> EditorSceneFormatImporterESCN::import_animation(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps) { - ERR_FAIL_V(Ref<Animation>()); -} diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h index a819be682d..368f68ae8f 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/resource_importer_scene.h @@ -56,9 +56,8 @@ protected: GDVIRTUAL0RC(int, _get_import_flags) GDVIRTUAL0RC(Vector<String>, _get_extensions) GDVIRTUAL4R(Object *, _import_scene, String, uint32_t, Dictionary, uint32_t) - GDVIRTUAL4R(Ref<Animation>, _import_animation, String, uint32_t, Dictionary, uint32_t) GDVIRTUAL1(_get_import_options, String) - GDVIRTUAL2RC(Variant, _get_option_visibility, String, String) + GDVIRTUAL3RC(Variant, _get_option_visibility, String, bool, String) public: enum ImportFlags { @@ -67,14 +66,14 @@ public: IMPORT_FAIL_ON_MISSING_DEPENDENCIES = 4, IMPORT_GENERATE_TANGENT_ARRAYS = 8, IMPORT_USE_NAMED_SKIN_BINDS = 16, + IMPORT_DISCARD_MESHES_AND_MATERIALS = 32, //used for optimizing animation import }; virtual uint32_t get_import_flags() const; virtual void get_extensions(List<String> *r_extensions) const; virtual Node *import_scene(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr); - virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps); virtual void get_import_options(const String &p_path, List<ResourceImporter::ImportOption> *r_options); - virtual Variant get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options); + virtual Variant get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, const Map<StringName, Variant> &p_options); EditorSceneFormatImporter() {} }; @@ -118,11 +117,11 @@ private: protected: GDVIRTUAL1(_get_internal_import_options, int) - GDVIRTUAL2RC(Variant, _get_internal_option_visibility, int, String) + GDVIRTUAL3RC(Variant, _get_internal_option_visibility, int, bool, String) GDVIRTUAL2RC(Variant, _get_internal_option_update_view_required, int, String) GDVIRTUAL4(_internal_process, int, Node *, Node *, RES) GDVIRTUAL1(_get_import_options, String) - GDVIRTUAL2RC(Variant, _get_option_visibility, String, String) + GDVIRTUAL3RC(Variant, _get_option_visibility, String, bool, String) GDVIRTUAL1(_pre_process, Node *) GDVIRTUAL1(_post_process, Node *) @@ -134,13 +133,13 @@ public: void add_import_option_advanced(Variant::Type p_type, const String &p_name, Variant p_default_value, PropertyHint p_hint = PROPERTY_HINT_NONE, const String &p_hint_string = String(), int p_usage_flags = PROPERTY_USAGE_DEFAULT); virtual void get_internal_import_options(InternalImportCategory p_category, List<ResourceImporter::ImportOption> *r_options); - virtual Variant get_internal_option_visibility(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const; + virtual Variant get_internal_option_visibility(InternalImportCategory p_category, bool p_for_animation, const String &p_option, const Map<StringName, Variant> &p_options) const; virtual Variant get_internal_option_update_view_required(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const; virtual void internal_process(InternalImportCategory p_category, Node *p_base_scene, Node *p_node, RES p_resource, const Dictionary &p_options); virtual void get_import_options(const String &p_path, List<ResourceImporter::ImportOption> *r_options); - virtual Variant get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const; + virtual Variant get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, const Map<StringName, Variant> &p_options) const; virtual void pre_process(Node *p_scene, const Map<StringName, Variant> &p_options); virtual void post_process(Node *p_scene, const Map<StringName, Variant> &p_options); @@ -153,9 +152,11 @@ VARIANT_ENUM_CAST(EditorScenePostImportPlugin::InternalImportCategory) class ResourceImporterScene : public ResourceImporter { GDCLASS(ResourceImporterScene, ResourceImporter); - Vector<Ref<EditorSceneFormatImporter>> importers; + static Vector<Ref<EditorSceneFormatImporter>> importers; + static Vector<Ref<EditorScenePostImportPlugin>> post_importer_plugins; - static ResourceImporterScene *singleton; + static ResourceImporterScene *scene_singleton; + static ResourceImporterScene *animation_singleton; enum LightBakeMode { LIGHT_BAKE_DISABLED, @@ -225,18 +226,21 @@ class ResourceImporterScene : public ResourceImporter { void _optimize_track_usage(AnimationPlayer *p_player, AnimationImportTracks *p_track_actions); - mutable Vector<Ref<EditorScenePostImportPlugin>> post_importer_plugins; + bool animation_importer = false; public: - static ResourceImporterScene *get_singleton() { return singleton; } + static ResourceImporterScene *get_scene_singleton() { return scene_singleton; } + static ResourceImporterScene *get_animation_singleton() { return animation_singleton; } - void add_post_importer_plugin(const Ref<EditorScenePostImportPlugin> &p_plugin, bool p_first_priority = false); - void remove_post_importer_plugin(const Ref<EditorScenePostImportPlugin> &p_plugin); + static void add_post_importer_plugin(const Ref<EditorScenePostImportPlugin> &p_plugin, bool p_first_priority = false); + static void remove_post_importer_plugin(const Ref<EditorScenePostImportPlugin> &p_plugin); const Vector<Ref<EditorSceneFormatImporter>> &get_importers() const { return importers; } - void add_importer(Ref<EditorSceneFormatImporter> p_importer, bool p_first_priority = false); - void remove_importer(Ref<EditorSceneFormatImporter> p_importer); + static void add_importer(Ref<EditorSceneFormatImporter> p_importer, bool p_first_priority = false); + static void remove_importer(Ref<EditorSceneFormatImporter> p_importer); + + static void clean_up_importer_plugins(); virtual String get_importer_name() const override; virtual String get_visible_name() const override; @@ -283,7 +287,7 @@ public: virtual bool can_import_threaded() const override { return false; } - ResourceImporterScene(); + ResourceImporterScene(bool p_animation_import = false); template <class M> static Vector<Ref<Shape3D>> get_collision_shapes(const Ref<Mesh> &p_mesh, const M &p_options); @@ -299,7 +303,6 @@ public: virtual uint32_t get_import_flags() const override; virtual void get_extensions(List<String> *r_extensions) const override; virtual Node *import_scene(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr) override; - virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps) override; }; #include "scene/resources/box_shape_3d.h" diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp index 302bc98499..4e53a644ee 100644 --- a/editor/import/scene_import_settings.cpp +++ b/editor/import/scene_import_settings.cpp @@ -47,6 +47,8 @@ class SceneImportSettingsData : public Object { Map<StringName, Variant> current; Map<StringName, Variant> defaults; List<ResourceImporter::ImportOption> options; + bool hide_options = false; + String path; ResourceImporterScene::InternalImportCategory category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX; @@ -60,8 +62,26 @@ class SceneImportSettingsData : public Object { current[p_name] = p_value; - if (ResourceImporterScene::get_singleton()->get_internal_option_update_view_required(category, p_name, current)) { - SceneImportSettings::get_singleton()->update_view(); + if (SceneImportSettings::get_singleton()->is_editing_animation()) { + if (category == ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX) { + if (ResourceImporterScene::get_animation_singleton()->get_option_visibility(path, p_name, current)) { + SceneImportSettings::get_singleton()->update_view(); + } + } else { + if (ResourceImporterScene::get_animation_singleton()->get_internal_option_update_view_required(category, p_name, current)) { + SceneImportSettings::get_singleton()->update_view(); + } + } + } else { + if (category == ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX) { + if (ResourceImporterScene::get_scene_singleton()->get_option_visibility(path, p_name, current)) { + SceneImportSettings::get_singleton()->update_view(); + } + } else { + if (ResourceImporterScene::get_scene_singleton()->get_internal_option_update_view_required(category, p_name, current)) { + SceneImportSettings::get_singleton()->update_view(); + } + } } return true; @@ -82,9 +102,30 @@ class SceneImportSettingsData : public Object { return false; } void _get_property_list(List<PropertyInfo> *p_list) const { + if (hide_options) { + return; + } for (const ResourceImporter::ImportOption &E : options) { - if (ResourceImporterScene::get_singleton()->get_internal_option_visibility(category, E.option.name, current)) { - p_list->push_back(E.option); + if (SceneImportSettings::get_singleton()->is_editing_animation()) { + if (category == ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX) { + if (ResourceImporterScene::get_animation_singleton()->get_option_visibility(path, E.option.name, current)) { + p_list->push_back(E.option); + } + } else { + if (ResourceImporterScene::get_animation_singleton()->get_internal_option_visibility(category, E.option.name, current)) { + p_list->push_back(E.option); + } + } + } else { + if (category == ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX) { + if (ResourceImporterScene::get_scene_singleton()->get_option_visibility(path, E.option.name, current)) { + p_list->push_back(E.option); + } + } else { + if (ResourceImporterScene::get_scene_singleton()->get_internal_option_visibility(category, E.option.name, current)) { + p_list->push_back(E.option); + } + } } } } @@ -326,7 +367,9 @@ void SceneImportSettings::_fill_scene(Node *p_node, TreeItem *p_parent_item) { } MeshInstance3D *mesh_node = Object::cast_to<MeshInstance3D>(p_node); if (mesh_node && mesh_node->get_mesh().is_valid()) { - _fill_mesh(scene_tree, mesh_node->get_mesh(), item); + if (!editing_animation) { + _fill_mesh(scene_tree, mesh_node->get_mesh(), item); + } // Add the collider view. MeshInstance3D *collider_view = memnew(MeshInstance3D); @@ -365,6 +408,9 @@ void SceneImportSettings::_update_scene() { } void SceneImportSettings::_update_view_gizmos() { + if (!is_visible()) { + return; + } for (const KeyValue<String, NodeData> &e : node_map) { bool generate_collider = false; if (e.value.settings.has(SNAME("generate/physics"))) { @@ -378,6 +424,7 @@ void SceneImportSettings::_update_view_gizmos() { } TypedArray<Node> descendants = mesh_node->find_nodes("collider_view", "MeshInstance3D"); + CRASH_COND_MSG(descendants.is_empty(), "This is unreachable, since the collider view is always created even when the collision is not used! If this is triggered there is a bug on the function `_fill_scene`."); MeshInstance3D *collider_view = static_cast<MeshInstance3D *>(descendants[0].operator Object *()); @@ -460,7 +507,11 @@ void SceneImportSettings::_load_default_subresource_settings(Map<StringName, Var if (d.has(p_import_id)) { d = d[p_import_id]; List<ResourceImporterScene::ImportOption> options; - ResourceImporterScene::get_singleton()->get_internal_import_options(p_category, &options); + if (editing_animation) { + ResourceImporterScene::get_animation_singleton()->get_internal_import_options(p_category, &options); + } else { + ResourceImporterScene::get_scene_singleton()->get_internal_import_options(p_category, &options); + } for (const ResourceImporterScene::ImportOption &E : options) { String key = E.option.name; if (d.has(key)) { @@ -472,21 +523,32 @@ void SceneImportSettings::_load_default_subresource_settings(Map<StringName, Var } void SceneImportSettings::update_view() { - _update_view_gizmos(); + update_view_timer->start(); } -void SceneImportSettings::open_settings(const String &p_path) { +void SceneImportSettings::open_settings(const String &p_path, bool p_for_animation) { if (scene) { memdelete(scene); scene = nullptr; } + + editing_animation = p_for_animation; scene_import_settings_data->settings = nullptr; - scene = ResourceImporterScene::get_singleton()->pre_import(p_path); + scene_import_settings_data->path = p_path; + + scene = ResourceImporterScene::get_scene_singleton()->pre_import(p_path); // Use the scene singleton here because we want to see the full thing. if (scene == nullptr) { EditorNode::get_singleton()->show_warning(TTR("Error opening scene")); return; } + // Visibility + data_mode->set_tab_hidden(1, p_for_animation); + data_mode->set_tab_hidden(2, p_for_animation); + + action_menu->get_popup()->set_item_disabled(action_menu->get_popup()->get_item_id(ACTION_EXTRACT_MATERIALS), p_for_animation); + action_menu->get_popup()->set_item_disabled(action_menu->get_popup()->get_item_id(ACTION_CHOOSE_MESH_SAVE_PATHS), p_for_animation); + base_path = p_path; material_set.clear(); @@ -540,7 +602,11 @@ void SceneImportSettings::open_settings(const String &p_path) { _update_view_gizmos(); _update_camera(); - set_title(vformat(TTR("Advanced Import Settings for '%s'"), base_path.get_file())); + if (p_for_animation) { + set_title(vformat(TTR("Advanced Import Settings for AnimationLibrary '%s'"), base_path.get_file())); + } else { + set_title(vformat(TTR("Advanced Import Settings for Scene '%s'"), base_path.get_file())); + } } SceneImportSettings *SceneImportSettings::singleton = nullptr; @@ -551,6 +617,7 @@ SceneImportSettings *SceneImportSettings::get_singleton() { void SceneImportSettings::_select(Tree *p_from, String p_type, String p_id) { selecting = true; + scene_import_settings_data->hide_options = false; if (p_type == "Node") { node_selected->hide(); //always hide just in case @@ -585,10 +652,12 @@ void SceneImportSettings::_select(Tree *p_from, String p_type, String p_id) { scene_import_settings_data->settings = &nd.settings; if (mi) { scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE; + scene_import_settings_data->hide_options = editing_animation; } else if (Object::cast_to<AnimationPlayer>(nd.node)) { scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE; } else { scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_NODE; + scene_import_settings_data->hide_options = editing_animation; } } } else if (p_type == "Animation") { @@ -671,24 +740,36 @@ void SceneImportSettings::_select(Tree *p_from, String p_type, String p_id) { List<ResourceImporter::ImportOption> options; - if (scene_import_settings_data->category == ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX) { - ResourceImporterScene::get_singleton()->get_import_options(base_path, &options); + if (editing_animation) { + if (scene_import_settings_data->category == ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX) { + ResourceImporterScene::get_animation_singleton()->get_import_options(base_path, &options); + } else { + ResourceImporterScene::get_animation_singleton()->get_internal_import_options(scene_import_settings_data->category, &options); + } + } else { - ResourceImporterScene::get_singleton()->get_internal_import_options(scene_import_settings_data->category, &options); + if (scene_import_settings_data->category == ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX) { + ResourceImporterScene::get_scene_singleton()->get_import_options(base_path, &options); + } else { + ResourceImporterScene::get_scene_singleton()->get_internal_import_options(scene_import_settings_data->category, &options); + } } scene_import_settings_data->defaults.clear(); scene_import_settings_data->current.clear(); - for (const ResourceImporter::ImportOption &E : options) { - scene_import_settings_data->defaults[E.option.name] = E.default_value; - //needed for visibility toggling (fails if something is missing) - if (scene_import_settings_data->settings->has(E.option.name)) { - scene_import_settings_data->current[E.option.name] = (*scene_import_settings_data->settings)[E.option.name]; - } else { - scene_import_settings_data->current[E.option.name] = E.default_value; + if (scene_import_settings_data->settings) { + for (const ResourceImporter::ImportOption &E : options) { + scene_import_settings_data->defaults[E.option.name] = E.default_value; + //needed for visibility toggling (fails if something is missing) + if (scene_import_settings_data->settings->has(E.option.name)) { + scene_import_settings_data->current[E.option.name] = (*scene_import_settings_data->settings)[E.option.name]; + } else { + scene_import_settings_data->current[E.option.name] = E.default_value; + } } } + scene_import_settings_data->options = options; inspector->edit(scene_import_settings_data); scene_import_settings_data->notify_property_list_changed(); @@ -836,7 +917,7 @@ void SceneImportSettings::_re_import() { main_settings["_subresources"] = subresources; } - EditorFileSystem::get_singleton()->reimport_file_with_custom_parameters(base_path, "scene", main_settings); + EditorFileSystem::get_singleton()->reimport_file_with_custom_parameters(base_path, editing_animation ? "animation_library" : "scene", main_settings); } void SceneImportSettings::_notification(int p_what) { @@ -1282,6 +1363,11 @@ SceneImportSettings::SceneImportSettings() { item_save_path->connect("file_selected", callable_mp(this, &SceneImportSettings::_save_path_changed)); save_path->connect("dir_selected", callable_mp(this, &SceneImportSettings::_save_dir_callback)); + + update_view_timer = memnew(Timer); + update_view_timer->set_wait_time(0.2); + update_view_timer->connect("timeout", callable_mp(this, &SceneImportSettings::_update_view_gizmos)); + add_child(update_view_timer); } SceneImportSettings::~SceneImportSettings() { diff --git a/editor/import/scene_import_settings.h b/editor/import/scene_import_settings.h index 3cf708740b..55cfba3275 100644 --- a/editor/import/scene_import_settings.h +++ b/editor/import/scene_import_settings.h @@ -189,12 +189,17 @@ class SceneImportSettings : public ConfirmationDialog { void _load_default_subresource_settings(Map<StringName, Variant> &settings, const String &p_type, const String &p_import_id, ResourceImporterScene::InternalImportCategory p_category); + bool editing_animation = false; + + Timer *update_view_timer; + protected: void _notification(int p_what); public: + bool is_editing_animation() const { return editing_animation; } void update_view(); - void open_settings(const String &p_path); + void open_settings(const String &p_path, bool p_for_animation = false); static SceneImportSettings *get_singleton(); SceneImportSettings(); ~SceneImportSettings(); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index a90e151adb..8d0db697e2 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -2298,7 +2298,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { } add_node_menu->reset_size(); - add_node_menu->set_position(get_screen_transform().xform(b->get_position())); + add_node_menu->set_position(viewport->get_screen_transform().xform(b->get_position())); add_node_menu->popup(); node_create_position = transform.affine_inverse().xform(b->get_position()); return true; diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 855fc2b2a9..f2ca1fcfeb 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -7120,7 +7120,9 @@ void Node3DEditor::_request_gizmo(Object *p_obj) { } } } - sp->update_gizmos(); + if (!sp->get_gizmos().is_empty()) { + sp->update_gizmos(); + } } } diff --git a/modules/gltf/editor/editor_scene_importer_blend.cpp b/modules/gltf/editor/editor_scene_importer_blend.cpp index ae05c1b68d..173d5131cf 100644 --- a/modules/gltf/editor/editor_scene_importer_blend.cpp +++ b/modules/gltf/editor/editor_scene_importer_blend.cpp @@ -238,13 +238,12 @@ Node *EditorSceneFormatImporterBlend::import_scene(const String &p_path, uint32_ return gltf->generate_scene(state, p_bake_fps); } -Ref<Animation> EditorSceneFormatImporterBlend::import_animation(const String &p_path, uint32_t p_flags, - const Map<StringName, Variant> &p_options, int p_bake_fps) { - return Ref<Animation>(); -} - -Variant EditorSceneFormatImporterBlend::get_option_visibility(const String &p_path, const String &p_option, +Variant EditorSceneFormatImporterBlend::get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, const Map<StringName, Variant> &p_options) { + if (p_path.get_extension().to_lower() != "blend") { + return true; + } + if (p_option.begins_with("animation/")) { if (p_option != "animation/import" && !bool(p_options["animation/import"])) { return false; @@ -254,6 +253,9 @@ Variant EditorSceneFormatImporterBlend::get_option_visibility(const String &p_pa } void EditorSceneFormatImporterBlend::get_import_options(const String &p_path, List<ResourceImporter::ImportOption> *r_options) { + if (p_path.get_extension().to_lower() != "blend") { + return; + } #define ADD_OPTION_BOOL(PATH, VALUE) \ r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, SNAME(PATH)), VALUE)); #define ADD_OPTION_ENUM(PATH, ENUM_HINT, VALUE) \ diff --git a/modules/gltf/editor/editor_scene_importer_blend.h b/modules/gltf/editor/editor_scene_importer_blend.h index 9a1b5f5803..0925333a28 100644 --- a/modules/gltf/editor/editor_scene_importer_blend.h +++ b/modules/gltf/editor/editor_scene_importer_blend.h @@ -68,11 +68,9 @@ public: virtual Node *import_scene(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr) override; - virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, - const Map<StringName, Variant> &p_options, int p_bake_fps) override; virtual void get_import_options(const String &p_path, List<ResourceImporter::ImportOption> *r_options) override; - virtual Variant get_option_visibility(const String &p_path, const String &p_option, + virtual Variant get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, const Map<StringName, Variant> &p_options) override; }; diff --git a/modules/gltf/editor/editor_scene_importer_fbx.cpp b/modules/gltf/editor/editor_scene_importer_fbx.cpp index 24564f55be..893d2efcec 100644 --- a/modules/gltf/editor/editor_scene_importer_fbx.cpp +++ b/modules/gltf/editor/editor_scene_importer_fbx.cpp @@ -105,12 +105,7 @@ Node *EditorSceneFormatImporterFBX::import_scene(const String &p_path, uint32_t return gltf->generate_scene(state, p_bake_fps); } -Ref<Animation> EditorSceneFormatImporterFBX::import_animation(const String &p_path, - uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps) { - return Ref<Animation>(); -} - -Variant EditorSceneFormatImporterFBX::get_option_visibility(const String &p_path, +Variant EditorSceneFormatImporterFBX::get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, const Map<StringName, Variant> &p_options) { return true; } diff --git a/modules/gltf/editor/editor_scene_importer_fbx.h b/modules/gltf/editor/editor_scene_importer_fbx.h index bb69cfaa30..84de7fd1cc 100644 --- a/modules/gltf/editor/editor_scene_importer_fbx.h +++ b/modules/gltf/editor/editor_scene_importer_fbx.h @@ -47,11 +47,9 @@ public: virtual Node *import_scene(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr) override; - virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, - const Map<StringName, Variant> &p_options, int p_bake_fps) override; virtual void get_import_options(const String &p_path, List<ResourceImporter::ImportOption> *r_options) override; - virtual Variant get_option_visibility(const String &p_path, const String &p_option, + virtual Variant get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, const Map<StringName, Variant> &p_options) override; }; diff --git a/modules/gltf/editor/editor_scene_importer_gltf.cpp b/modules/gltf/editor/editor_scene_importer_gltf.cpp index 1d6a82e58a..5e7811ad2b 100644 --- a/modules/gltf/editor/editor_scene_importer_gltf.cpp +++ b/modules/gltf/editor/editor_scene_importer_gltf.cpp @@ -64,9 +64,4 @@ Node *EditorSceneFormatImporterGLTF::import_scene(const String &p_path, uint32_t return doc->generate_scene(state, p_bake_fps); } -Ref<Animation> EditorSceneFormatImporterGLTF::import_animation(const String &p_path, - uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps) { - return Ref<Animation>(); -} - #endif // TOOLS_ENABLED diff --git a/modules/gltf/editor/editor_scene_importer_gltf.h b/modules/gltf/editor/editor_scene_importer_gltf.h index 1f62ca9537..b714ada124 100644 --- a/modules/gltf/editor/editor_scene_importer_gltf.h +++ b/modules/gltf/editor/editor_scene_importer_gltf.h @@ -47,8 +47,6 @@ public: virtual Node *import_scene(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr) override; - virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, - const Map<StringName, Variant> &p_options, int p_bake_fps) override; }; #endif // TOOLS_ENABLED diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index 73222330db..784733aba2 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -3272,7 +3272,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { Dictionary mr; { Array arr; - const Color c = material->get_albedo().to_linear(); + const Color c = material->get_albedo().srgb_to_linear(); arr.push_back(c.r); arr.push_back(c.g); arr.push_back(c.b); @@ -3473,7 +3473,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { } if (material->get_feature(BaseMaterial3D::FEATURE_EMISSION)) { - const Color c = material->get_emission().to_srgb(); + const Color c = material->get_emission().linear_to_srgb(); Array arr; arr.push_back(c.r); arr.push_back(c.g); @@ -3555,7 +3555,7 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) { if (sgm.has("diffuseFactor")) { const Array &arr = sgm["diffuseFactor"]; ERR_FAIL_COND_V(arr.size() != 4, ERR_PARSE_ERROR); - const Color c = Color(arr[0], arr[1], arr[2], arr[3]).to_srgb(); + const Color c = Color(arr[0], arr[1], arr[2], arr[3]).linear_to_srgb(); spec_gloss->diffuse_factor = c; material->set_albedo(spec_gloss->diffuse_factor); } @@ -3586,7 +3586,7 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) { if (mr.has("baseColorFactor")) { const Array &arr = mr["baseColorFactor"]; ERR_FAIL_COND_V(arr.size() != 4, ERR_PARSE_ERROR); - const Color c = Color(arr[0], arr[1], arr[2], arr[3]).to_srgb(); + const Color c = Color(arr[0], arr[1], arr[2], arr[3]).linear_to_srgb(); material->set_albedo(c); } @@ -3653,7 +3653,7 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) { if (d.has("emissiveFactor")) { const Array &arr = d["emissiveFactor"]; ERR_FAIL_COND_V(arr.size() != 3, ERR_PARSE_ERROR); - const Color c = Color(arr[0], arr[1], arr[2]).to_srgb(); + const Color c = Color(arr[0], arr[1], arr[2]).linear_to_srgb(); material->set_feature(BaseMaterial3D::FEATURE_EMISSION, true); material->set_emission(c); @@ -3737,11 +3737,11 @@ void GLTFDocument::spec_gloss_to_rough_metal(Ref<GLTFSpecGloss> r_spec_gloss, Re } for (int32_t y = 0; y < r_spec_gloss->spec_gloss_img->get_height(); y++) { for (int32_t x = 0; x < r_spec_gloss->spec_gloss_img->get_width(); x++) { - const Color specular_pixel = r_spec_gloss->spec_gloss_img->get_pixel(x, y).to_linear(); + const Color specular_pixel = r_spec_gloss->spec_gloss_img->get_pixel(x, y).srgb_to_linear(); Color specular = Color(specular_pixel.r, specular_pixel.g, specular_pixel.b); specular *= r_spec_gloss->specular_factor; Color diffuse = Color(1.0f, 1.0f, 1.0f); - diffuse *= r_spec_gloss->diffuse_img->get_pixel(x, y).to_linear(); + diffuse *= r_spec_gloss->diffuse_img->get_pixel(x, y).srgb_to_linear(); float metallic = 0.0f; Color base_color; spec_gloss_to_metal_base_color(specular, diffuse, base_color, metallic); @@ -3758,7 +3758,7 @@ void GLTFDocument::spec_gloss_to_rough_metal(Ref<GLTFSpecGloss> r_spec_gloss, Re mr.g = 1.0f - mr.g; rm_img->set_pixel(x, y, mr); if (r_spec_gloss->diffuse_img.is_valid()) { - r_spec_gloss->diffuse_img->set_pixel(x, y, base_color.to_srgb()); + r_spec_gloss->diffuse_img->set_pixel(x, y, base_color.linear_to_srgb()); } } } @@ -4626,7 +4626,7 @@ Error GLTFDocument::_parse_lights(Ref<GLTFState> state) { if (d.has("color")) { const Array &arr = d["color"]; ERR_FAIL_COND_V(arr.size() != 3, ERR_PARSE_ERROR); - const Color c = Color(arr[0], arr[1], arr[2]).to_srgb(); + const Color c = Color(arr[0], arr[1], arr[2]).linear_to_srgb(); light->color = c; } if (d.has("intensity")) { diff --git a/modules/gltf/register_types.cpp b/modules/gltf/register_types.cpp index e09c76f052..b656788a10 100644 --- a/modules/gltf/register_types.cpp +++ b/modules/gltf/register_types.cpp @@ -60,7 +60,7 @@ static void _editor_init() { Ref<EditorSceneFormatImporterGLTF> import_gltf; import_gltf.instantiate(); - ResourceImporterScene::get_singleton()->add_importer(import_gltf); + ResourceImporterScene::add_importer(import_gltf); // Blend to glTF importer. @@ -72,7 +72,7 @@ static void _editor_init() { if (blend_enabled) { Ref<EditorSceneFormatImporterBlend> importer; importer.instantiate(); - ResourceImporterScene::get_singleton()->add_importer(importer); + ResourceImporterScene::add_importer(importer); Ref<EditorFileSystemImportFormatSupportQueryBlend> blend_import_query; blend_import_query.instantiate(); @@ -95,7 +95,7 @@ static void _editor_init() { } else { Ref<EditorSceneFormatImporterFBX> importer; importer.instantiate(); - ResourceImporterScene::get_singleton()->add_importer(importer); + ResourceImporterScene::add_importer(importer); } } } diff --git a/modules/hdr/image_loader_hdr.cpp b/modules/hdr/image_loader_hdr.cpp index 4588caf0a5..eca689e87a 100644 --- a/modules/hdr/image_loader_hdr.cpp +++ b/modules/hdr/image_loader_hdr.cpp @@ -132,7 +132,7 @@ Error ImageLoaderHDR::load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_f ptr[2] * exp / 255.0); if (p_force_linear) { - c = c.to_linear(); + c = c.srgb_to_linear(); } *(uint32_t *)ptr = c.to_rgbe9995(); diff --git a/modules/tinyexr/image_loader_tinyexr.cpp b/modules/tinyexr/image_loader_tinyexr.cpp index 1ff2600839..864df765ee 100644 --- a/modules/tinyexr/image_loader_tinyexr.cpp +++ b/modules/tinyexr/image_loader_tinyexr.cpp @@ -230,7 +230,7 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, Ref<FileAccess> f, bool } if (p_force_linear) { - color = color.to_linear(); + color = color.srgb_to_linear(); } *row_w++ = Math::make_half_float(color.r); @@ -261,7 +261,7 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, Ref<FileAccess> f, bool } if (p_force_linear) { - color = color.to_linear(); + color = color.srgb_to_linear(); } *row_w++ = color.r; diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp index db2fe274d9..7da30ac363 100644 --- a/platform/linuxbsd/display_server_x11.cpp +++ b/platform/linuxbsd/display_server_x11.cpp @@ -3062,7 +3062,7 @@ void DisplayServerX11::_dispatch_input_event(const Ref<InputEvent> &p_event) { Callable::CallError ce; { - List<WindowID>::Element *E = popup_list.front(); + List<WindowID>::Element *E = popup_list.back(); if (E && Object::cast_to<InputEventKey>(*p_event)) { // Redirect keyboard input to active popup. if (windows.has(E->get())) { diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm index c7381f06e3..d209c90d87 100644 --- a/platform/osx/display_server_osx.mm +++ b/platform/osx/display_server_osx.mm @@ -326,7 +326,7 @@ void DisplayServerOSX::_dispatch_input_event(const Ref<InputEvent> &p_event) { Callable::CallError ce; { - List<WindowID>::Element *E = popup_list.front(); + List<WindowID>::Element *E = popup_list.back(); if (E && Object::cast_to<InputEventKey>(*p_event)) { // Redirect keyboard input to active popup. if (windows.has(E->get())) { diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 736dc7d383..31bad0f053 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -2003,7 +2003,7 @@ void DisplayServerWindows::_dispatch_input_event(const Ref<InputEvent> &p_event) Callable::CallError ce; { - List<WindowID>::Element *E = popup_list.front(); + List<WindowID>::Element *E = popup_list.back(); if (E && Object::cast_to<InputEventKey>(*p_event)) { // Redirect keyboard input to active popup. if (windows.has(E->get())) { diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp index 4eace17cc0..1f0c9acef5 100644 --- a/scene/3d/camera_3d.cpp +++ b/scene/3d/camera_3d.cpp @@ -509,7 +509,7 @@ void Camera3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "projection", PROPERTY_HINT_ENUM, "Perspective,Orthogonal,Frustum"), "set_projection", "get_projection"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "current"), "set_current", "is_current"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fov", PROPERTY_HINT_RANGE, "1,179,0.1,degrees"), "set_fov", "get_fov"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "size", PROPERTY_HINT_RANGE, "0.1,16384,0.01"), "set_size", "get_size"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "size", PROPERTY_HINT_RANGE, "0.001,16384,0.001"), "set_size", "get_size"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frustum_offset"), "set_frustum_offset", "get_frustum_offset"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "near", PROPERTY_HINT_RANGE, "0.001,10,0.001,or_greater,exp"), "set_near", "get_near"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "far", PROPERTY_HINT_RANGE, "0.01,4000,0.01,or_greater,exp"), "set_far", "get_far"); @@ -557,7 +557,7 @@ void Camera3D::set_fov(real_t p_fov) { } void Camera3D::set_size(real_t p_size) { - ERR_FAIL_COND(p_size < 0.1 || p_size > 16384); + ERR_FAIL_COND(p_size < 0.001 || p_size > 16384); size = p_size; _update_camera_mode(); } diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp index 3461caf638..8b457b683d 100644 --- a/scene/3d/lightmap_gi.cpp +++ b/scene/3d/lightmap_gi.cpp @@ -884,7 +884,7 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa Light3D *light = lights_found[i].light; Transform3D xf = lights_found[i].xform; - Color linear_color = light->get_color().to_linear(); + Color linear_color = light->get_color().srgb_to_linear(); if (Object::cast_to<DirectionalLight3D>(light)) { DirectionalLight3D *l = Object::cast_to<DirectionalLight3D>(light); lightmapper->add_directional_light(light->get_bake_mode() == Light3D::BAKE_STATIC, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), linear_color, l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_SIZE)); diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp index 62cc7c143b..bbc977647e 100644 --- a/scene/3d/node_3d.cpp +++ b/scene/3d/node_3d.cpp @@ -181,15 +181,6 @@ void Node3D::_notification(int p_what) { #ifdef TOOLS_ENABLED if (Engine::get_singleton()->is_editor_hint() && get_tree()->is_node_being_edited(this)) { get_tree()->call_group_flags(0, SceneStringNames::get_singleton()->_spatial_editor_group, SceneStringNames::get_singleton()->_request_gizmo, this); - if (!data.gizmos_disabled) { - for (int i = 0; i < data.gizmos.size(); i++) { - data.gizmos.write[i]->create(); - if (is_visible_in_tree()) { - data.gizmos.write[i]->redraw(); - } - data.gizmos.write[i]->transform(); - } - } } #endif } break; @@ -427,6 +418,7 @@ void Node3D::update_gizmos() { } if (data.gizmos.is_empty()) { + get_tree()->call_group_flags(0, SceneStringNames::get_singleton()->_spatial_editor_group, SceneStringNames::get_singleton()->_request_gizmo, this); return; } if (data.gizmos_dirty) { diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index ea9fbe8381..60f2623267 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -540,6 +540,11 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { List<StringName> sname; player->get_animation_list(&sname); + Ref<Animation> reset_anim; + bool has_reset_anim = player->has_animation("RESET"); + if (has_reset_anim) { + reset_anim = player->get_animation("RESET"); + } for (const StringName &E : sname) { Ref<Animation> anim = player->get_animation(E); for (int i = 0; i < anim->get_track_count(); i++) { @@ -593,6 +598,12 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { track = track_value; + if (has_reset_anim) { + int rt = reset_anim->find_track(path, track_type); + if (rt >= 0 && reset_anim->track_get_key_count(rt) > 0) { + track_value->init_value = reset_anim->track_get_key_value(rt, 0); + } + } } break; case Animation::TYPE_POSITION_3D: case Animation::TYPE_ROTATION_3D: @@ -645,6 +656,25 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { } } + if (has_reset_anim) { + int rt = reset_anim->find_track(path, track_type); + if (rt >= 0 && reset_anim->track_get_key_count(rt) > 0) { + switch (track_type) { + case Animation::TYPE_POSITION_3D: { + track_xform->init_loc = reset_anim->track_get_key_value(rt, 0); + } break; + case Animation::TYPE_ROTATION_3D: { + track_xform->ref_rot = reset_anim->track_get_key_value(rt, 0); + track_xform->init_rot = track_xform->ref_rot.log(); + } break; + case Animation::TYPE_SCALE_3D: { + track_xform->init_scale = reset_anim->track_get_key_value(rt, 0); + } break; + default: { + } + } + } + } #endif // _3D_DISABLED } break; case Animation::TYPE_BLEND_SHAPE: { @@ -675,6 +705,13 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { track_bshape->object = mesh_3d; track_bshape->object_id = mesh_3d->get_instance_id(); track = track_bshape; + + if (has_reset_anim) { + int rt = reset_anim->find_track(path, track_type); + if (rt >= 0 && reset_anim->track_get_key_count(rt) > 0) { + track_bshape->init_value = reset_anim->track_get_key_value(rt, 0); + } + } #endif } break; case Animation::TYPE_METHOD: { @@ -704,6 +741,13 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { track_bezier->object_id = track_bezier->object->get_instance_id(); track = track_bezier; + + if (has_reset_anim) { + int rt = reset_anim->find_track(path, track_type); + if (rt >= 0 && reset_anim->track_get_key_count(rt) > 0) { + track_bezier->init_value = reset_anim->track_get_key_value(rt, 0); + } + } } break; case Animation::TYPE_AUDIO: { TrackCacheAudio *track_audio = memnew(TrackCacheAudio); @@ -1244,7 +1288,7 @@ void AnimationTree::_process_graph(double p_delta) { if (t->process_pass != process_pass) { t->process_pass = process_pass; - t->value = 0; + t->value = t->init_value; } float value; @@ -1256,7 +1300,7 @@ void AnimationTree::_process_graph(double p_delta) { continue; } - t->value += value * blend; + t->value += (value - t->init_value) * blend; #endif // _3D_DISABLED } break; case Animation::TYPE_VALUE: { @@ -1274,10 +1318,15 @@ void AnimationTree::_process_graph(double p_delta) { if (t->process_pass != process_pass) { t->process_pass = process_pass; - t->value = value; - t->value.zero(); + if (!t->init_value) { + t->init_value = value; + t->init_value.zero(); + } else { + t->value = t->init_value; + } } + Variant::sub(value, t->init_value, value); Variant::blend(t->value, value, blend, t->value); } else { if (blend < CMP_EPSILON) { @@ -1321,10 +1370,10 @@ void AnimationTree::_process_graph(double p_delta) { if (t->process_pass != process_pass) { t->process_pass = process_pass; - t->value = 0; + t->value = t->init_value; } - t->value += bezier * blend; + t->value += (bezier - t->init_value) * blend; } break; case Animation::TYPE_AUDIO: { if (blend < CMP_EPSILON) { diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h index 3ccb6be073..524f735894 100644 --- a/scene/animation/animation_tree.h +++ b/scene/animation/animation_tree.h @@ -212,12 +212,14 @@ private: struct TrackCacheBlendShape : public TrackCache { MeshInstance3D *mesh_3d = nullptr; + float init_value = 0; float value = 0; int shape_index = -1; TrackCacheBlendShape() { type = Animation::TYPE_BLEND_SHAPE; } }; struct TrackCacheValue : public TrackCache { + Variant init_value; Variant value; Vector<StringName> subpath; TrackCacheValue() { type = Animation::TYPE_VALUE; } @@ -228,6 +230,7 @@ private: }; struct TrackCacheBezier : public TrackCache { + real_t init_value = 0.0; real_t value = 0.0; Vector<StringName> subpath; TrackCacheBezier() { diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 9fc1fb072c..b01f45e9ab 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -169,7 +169,7 @@ int PopupMenu::_get_mouse_over(const Point2 &p_over) const { return -1; } -void PopupMenu::_activate_submenu(int p_over) { +void PopupMenu::_activate_submenu(int p_over, bool p_by_keyboard) { Node *n = get_node(items[p_over].submenu); ERR_FAIL_COND_MSG(!n, "Item subnode does not exist: " + items[p_over].submenu + "."); Popup *submenu_popup = Object::cast_to<Popup>(n); @@ -213,8 +213,10 @@ void PopupMenu::_activate_submenu(int p_over) { return; } + submenu_pum->activated_by_keyboard = p_by_keyboard; + // If not triggered by the mouse, start the popup with its first item selected. - if (submenu_pum->get_item_count() > 0 && Input::get_singleton()->is_action_just_pressed("ui_accept")) { + if (submenu_pum->get_item_count() > 0 && p_by_keyboard) { submenu_pum->set_current_index(0); } @@ -323,14 +325,14 @@ void PopupMenu::gui_input(const Ref<InputEvent> &p_event) { set_input_as_handled(); } } else if (p_event->is_action("ui_right") && p_event->is_pressed()) { - if (mouse_over >= 0 && mouse_over < items.size() && !!items[mouse_over].separator && items[mouse_over].submenu.is_empty() && submenu_over != mouse_over) { - _activate_submenu(mouse_over); + if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator && !items[mouse_over].submenu.is_empty() && submenu_over != mouse_over) { + _activate_submenu(mouse_over, true); set_input_as_handled(); } } else if (p_event->is_action("ui_accept") && p_event->is_pressed()) { if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator) { if (!items[mouse_over].submenu.is_empty() && submenu_over != mouse_over) { - _activate_submenu(mouse_over); + _activate_submenu(mouse_over, true); } else { activate_item(mouse_over); } @@ -396,6 +398,11 @@ void PopupMenu::gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseMotion> m = p_event; if (m.is_valid()) { + if (m->get_velocity().is_equal_approx(Vector2())) { + return; + } + activated_by_keyboard = false; + for (const Rect2 &E : autohide_areas) { if (!Rect2(Point2(), get_size()).has_point(m->get_position()) && E.has_point(m->get_position())) { _close_pressed(); @@ -687,7 +694,7 @@ void PopupMenu::_draw_background() { void PopupMenu::_minimum_lifetime_timeout() { close_allowed = true; // If the mouse still isn't in this popup after timer expires, close. - if (!get_visible_rect().has_point(get_mouse_position())) { + if (!activated_by_keyboard && !get_visible_rect().has_point(get_mouse_position())) { _close_pressed(); } } @@ -772,7 +779,7 @@ void PopupMenu::_notification(int p_what) { case NOTIFICATION_INTERNAL_PROCESS: { // Only used when using operating system windows. - if (!is_embedded() && autohide_areas.size()) { + if (!activated_by_keyboard && !is_embedded() && autohide_areas.size()) { Point2 mouse_pos = DisplayServer::get_singleton()->mouse_get_position(); mouse_pos -= get_position(); diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h index 518ba14dae..98d76875cb 100644 --- a/scene/gui/popup_menu.h +++ b/scene/gui/popup_menu.h @@ -87,6 +87,7 @@ class PopupMenu : public Popup { }; bool close_allowed = false; + bool activated_by_keyboard = false; Timer *minimum_lifetime_timer = nullptr; Timer *submenu_timer = nullptr; @@ -107,7 +108,7 @@ class PopupMenu : public Popup { void _shape_item(int p_item); virtual void gui_input(const Ref<InputEvent> &p_event); - void _activate_submenu(int p_over); + void _activate_submenu(int p_over, bool p_by_keyboard = false); void _submenu_timeout(); uint64_t popup_time_msec = 0; diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index c00298ff2f..ec13399f82 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -4257,7 +4257,7 @@ void RichTextLabel::select_all() { while (it) { if (it->type != ITEM_FRAME) { - if (from_item == nullptr) { + if (!from_item) { from_item = it; } else { to_item = it; @@ -4265,13 +4265,22 @@ void RichTextLabel::select_all() { } it = _get_next_item(it, true); } + if (!from_item || !to_item) { + return; + } ItemFrame *from_frame = nullptr; int from_line = 0; _find_frame(from_item, &from_frame, &from_line); + if (!from_frame) { + return; + } ItemFrame *to_frame = nullptr; int to_line = 0; _find_frame(to_item, &to_frame, &to_line); + if (!to_frame) { + return; + } selection.from_line = from_line; selection.from_frame = from_frame; selection.from_char = 0; diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index 0ddf164c79..e045a379d2 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -3828,7 +3828,7 @@ void Animation::_bind_methods() { ClassDB::bind_method(D_METHOD("compress", "page_size", "fps", "split_tolerance"), &Animation::compress, DEFVAL(8192), DEFVAL(120), DEFVAL(4.0)); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "length", PROPERTY_HINT_RANGE, "0.001,99999,0.001"), "set_length", "get_length"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_mode"), "set_loop_mode", "get_loop_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_mode", PROPERTY_HINT_ENUM, "None,Linear,Ping-Pong"), "set_loop_mode", "get_loop_mode"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "step", PROPERTY_HINT_RANGE, "0,4096,0.001"), "set_step", "get_step"); ADD_SIGNAL(MethodInfo("tracks_changed")); diff --git a/scene/resources/animation_library.cpp b/scene/resources/animation_library.cpp index f7b8c6a648..229d9ab218 100644 --- a/scene/resources/animation_library.cpp +++ b/scene/resources/animation_library.cpp @@ -55,7 +55,7 @@ void AnimationLibrary::remove_animation(const StringName &p_name) { void AnimationLibrary::rename_animation(const StringName &p_name, const StringName &p_new_name) { ERR_FAIL_COND(!animations.has(p_name)); - ERR_FAIL_COND_MSG(String(p_name).contains("/") || String(p_name).contains(":") || String(p_name).contains(",") || String(p_name).contains("["), "Invalid animation name: " + String(p_name) + "."); + ERR_FAIL_COND_MSG(String(p_new_name).contains("/") || String(p_new_name).contains(":") || String(p_new_name).contains(",") || String(p_new_name).contains("["), "Invalid animation name: " + String(p_new_name) + "."); ERR_FAIL_COND(animations.has(p_new_name)); animations.insert(p_new_name, animations[p_name]); 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 365bef896f..b541e6ca88 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -783,7 +783,7 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat //ambient if (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && (env_bg == RS::ENV_BG_CLEAR_COLOR || env_bg == RS::ENV_BG_COLOR)) { Color color = env_bg == RS::ENV_BG_CLEAR_COLOR ? p_default_bg_color : environment_get_bg_color(p_render_data->environment); - color = color.to_linear(); + color = color.srgb_to_linear(); scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy; scene_state.ubo.ambient_light_color_energy[1] = color.g * bg_energy; @@ -793,7 +793,7 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat } else { float energy = environment_get_ambient_light_energy(p_render_data->environment); Color color = environment_get_ambient_light_color(p_render_data->environment); - color = color.to_linear(); + color = color.srgb_to_linear(); scene_state.ubo.ambient_light_color_energy[0] = color.r * energy; scene_state.ubo.ambient_light_color_energy[1] = color.g * energy; scene_state.ubo.ambient_light_color_energy[2] = color.b * energy; @@ -829,7 +829,7 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat scene_state.ubo.fog_height_density = environment_get_fog_height_density(p_render_data->environment); scene_state.ubo.fog_aerial_perspective = environment_get_fog_aerial_perspective(p_render_data->environment); - Color fog_color = environment_get_fog_light_color(p_render_data->environment).to_linear(); + Color fog_color = environment_get_fog_light_color(p_render_data->environment).srgb_to_linear(); float fog_energy = environment_get_fog_light_energy(p_render_data->environment); scene_state.ubo.fog_light_color[0] = fog_color.r * fog_energy; @@ -844,7 +844,7 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat } else { scene_state.ubo.use_ambient_light = true; Color clear_color = p_default_bg_color; - clear_color = clear_color.to_linear(); + clear_color = clear_color.srgb_to_linear(); scene_state.ubo.ambient_light_color_energy[0] = clear_color.r; scene_state.ubo.ambient_light_color_energy[1] = clear_color.g; scene_state.ubo.ambient_light_color_energy[2] = clear_color.b; @@ -1391,7 +1391,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co clear_color.b *= bg_energy; if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) { draw_sky_fog_only = true; - RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear())); + RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear())); } } break; case RS::ENV_BG_COLOR: { @@ -1401,7 +1401,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co clear_color.b *= bg_energy; if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) { draw_sky_fog_only = true; - RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear())); + RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear())); } } break; case RS::ENV_BG_SKY: { @@ -1520,7 +1520,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co Vector<Color> c; { - Color cc = clear_color.to_linear(); + Color cc = clear_color.srgb_to_linear(); if (using_separate_specular) { cc.a = 0; //subsurf scatter must be 0 } diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index 99a7fe6280..6b0d245e44 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -293,16 +293,16 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { raster_state.cull_mode = cull_mode_rd; raster_state.wireframe = wireframe; - RD::PipelineColorBlendState blend_state; - RD::PipelineDepthStencilState depth_stencil = depth_stencil_state; - RD::PipelineMultisampleState multisample_state; - if (k == PIPELINE_VERSION_COLOR_PASS) { for (int l = 0; l < PIPELINE_COLOR_PASS_FLAG_COUNT; l++) { if (!shader_singleton->valid_color_pass_pipelines.has(l)) { continue; } + RD::PipelineColorBlendState blend_state; + RD::PipelineDepthStencilState depth_stencil = depth_stencil_state; + RD::PipelineMultisampleState multisample_state; + int shader_flags = 0; if (l & PIPELINE_COLOR_PASS_FLAG_TRANSPARENT) { if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) { @@ -338,6 +338,10 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { color_pipelines[i][j][l].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants); } } else { + RD::PipelineColorBlendState blend_state; + RD::PipelineDepthStencilState depth_stencil = depth_stencil_state; + RD::PipelineMultisampleState multisample_state; + if (k == PIPELINE_VERSION_DEPTH_PASS || k == PIPELINE_VERSION_DEPTH_PASS_DP || k == PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW) { //none, leave empty } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) { 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 7272b2f8d0..6988e3c1dd 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -596,7 +596,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color /* if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) { draw_sky_fog_only = true; - RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear())); + RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear())); } */ } break; @@ -608,7 +608,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color /* if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) { draw_sky_fog_only = true; - RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear())); + RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear())); } */ } break; @@ -723,10 +723,10 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color { // regular forward for now Vector<Color> c; - c.push_back(clear_color.to_linear()); // our render buffer + c.push_back(clear_color.srgb_to_linear()); // our render buffer if (render_buffer) { if (render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) { - c.push_back(clear_color.to_linear()); // our resolve buffer + c.push_back(clear_color.srgb_to_linear()); // our resolve buffer } if (using_subpass_post_process) { c.push_back(Color()); // our 2D buffer we're copying into @@ -1616,7 +1616,7 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data, //ambient if (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && (env_bg == RS::ENV_BG_CLEAR_COLOR || env_bg == RS::ENV_BG_COLOR)) { Color color = env_bg == RS::ENV_BG_CLEAR_COLOR ? p_default_bg_color : environment_get_bg_color(p_render_data->environment); - color = color.to_linear(); + color = color.srgb_to_linear(); scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy; scene_state.ubo.ambient_light_color_energy[1] = color.g * bg_energy; @@ -1626,7 +1626,7 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data, } else { float energy = environment_get_ambient_light_energy(p_render_data->environment); Color color = environment_get_ambient_light_color(p_render_data->environment); - color = color.to_linear(); + color = color.srgb_to_linear(); scene_state.ubo.ambient_light_color_energy[0] = color.r * energy; scene_state.ubo.ambient_light_color_energy[1] = color.g * energy; scene_state.ubo.ambient_light_color_energy[2] = color.b * energy; @@ -1657,7 +1657,7 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data, scene_state.ubo.fog_height_density = environment_get_fog_height_density(p_render_data->environment); scene_state.ubo.fog_aerial_perspective = environment_get_fog_aerial_perspective(p_render_data->environment); - Color fog_color = environment_get_fog_light_color(p_render_data->environment).to_linear(); + Color fog_color = environment_get_fog_light_color(p_render_data->environment).srgb_to_linear(); float fog_energy = environment_get_fog_light_energy(p_render_data->environment); scene_state.ubo.fog_light_color[0] = fog_color.r * fog_energy; @@ -1672,7 +1672,7 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data, } else { scene_state.ubo.use_ambient_light = true; Color clear_color = p_default_bg_color; - clear_color = clear_color.to_linear(); + clear_color = clear_color.srgb_to_linear(); scene_state.ubo.ambient_light_color_energy[0] = clear_color.r; scene_state.ubo.ambient_light_color_energy[1] = clear_color.g; scene_state.ubo.ambient_light_color_energy[2] = clear_color.b; diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp index 75202d5abb..c735fda5f8 100644 --- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp @@ -921,7 +921,7 @@ void RendererSceneGIRD::SDFGI::update_probes(RendererSceneEnvironmentRD *p_env, if (p_env->background == RS::ENV_BG_CLEAR_COLOR) { push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_COLOR; - Color c = storage->get_default_clear_color().to_linear(); + Color c = storage->get_default_clear_color().srgb_to_linear(); push_constant.sky_color[0] = c.r; push_constant.sky_color[1] = c.g; push_constant.sky_color[2] = c.b; @@ -1469,7 +1469,7 @@ void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, Re lights[idx].direction[1] = dir.y; lights[idx].direction[2] = dir.z; Color color = storage->light_get_color(li->light); - color = color.to_linear(); + color = color.srgb_to_linear(); lights[idx].color[0] = color.r; lights[idx].color[1] = color.g; lights[idx].color[2] = color.b; @@ -1514,7 +1514,7 @@ void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, Re lights[idx].position[1] = pos.y; lights[idx].position[2] = pos.z; Color color = storage->light_get_color(li->light); - color = color.to_linear(); + color = color.srgb_to_linear(); lights[idx].color[0] = color.r; lights[idx].color[1] = color.g; lights[idx].color[2] = color.b; @@ -1953,7 +1953,7 @@ void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32 lights[idx].position[1] = pos.y; lights[idx].position[2] = pos.z; Color color = storage->light_get_color(li->light); - color = color.to_linear(); + color = color.srgb_to_linear(); lights[idx].color[0] = color.r; lights[idx].color[1] = color.g; lights[idx].color[2] = color.b; @@ -2396,7 +2396,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c l.attenuation = storage->light_get_param(light, RS::LIGHT_PARAM_ATTENUATION); l.energy = storage->light_get_param(light, RS::LIGHT_PARAM_ENERGY) * storage->light_get_param(light, RS::LIGHT_PARAM_INDIRECT_ENERGY); l.radius = to_cell.basis.xform(Vector3(storage->light_get_param(light, RS::LIGHT_PARAM_RANGE), 0, 0)).length(); - Color color = storage->light_get_color(light).to_linear(); + Color color = storage->light_get_color(light).srgb_to_linear(); l.color[0] = color.r; l.color[1] = color.g; l.color[2] = color.b; diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index ac7ac692ce..b342e8f043 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -517,7 +517,7 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba ambient_color_sky_mix = env->ambient_sky_contribution; const float ambient_energy = env->ambient_light_energy; ambient_color = env->ambient_light; - ambient_color = ambient_color.to_linear(); + ambient_color = ambient_color.srgb_to_linear(); ambient_color.r *= ambient_energy; ambient_color.g *= ambient_energy; ambient_color.b *= ambient_energy; @@ -536,7 +536,7 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba } else { const float bg_energy = env->bg_energy; Color panorama_color = ((environment_background == RS::ENV_BG_CLEAR_COLOR) ? storage->get_default_clear_color() : env->bg_color); - panorama_color = panorama_color.to_linear(); + panorama_color = panorama_color.srgb_to_linear(); panorama_color.r *= bg_energy; panorama_color.g *= bg_energy; panorama_color.b *= bg_energy; @@ -3245,7 +3245,7 @@ void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflecti reflection_ubo.exterior = !storage->reflection_probe_is_interior(base_probe); reflection_ubo.box_project = storage->reflection_probe_is_box_projection(base_probe); - Color ambient_linear = storage->reflection_probe_get_ambient_color(base_probe).to_linear(); + Color ambient_linear = storage->reflection_probe_get_ambient_color(base_probe).srgb_to_linear(); float interior_ambient_energy = storage->reflection_probe_get_ambient_color_energy(base_probe); reflection_ubo.ambient[0] = ambient_linear.r * interior_ambient_energy; reflection_ubo.ambient[1] = ambient_linear.g * interior_ambient_energy; @@ -3312,7 +3312,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const light_data.energy = sign * storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI; - Color linear_col = storage->light_get_color(base).to_linear(); + Color linear_col = storage->light_get_color(base).srgb_to_linear(); light_data.color[0] = linear_col.r; light_data.color[1] = linear_col.g; light_data.color[2] = linear_col.b; @@ -3491,7 +3491,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const Transform3D light_transform = li->transform; float sign = storage->light_is_negative(base) ? -1 : 1; - Color linear_col = storage->light_get_color(base).to_linear(); + Color linear_col = storage->light_get_color(base).srgb_to_linear(); light_data.attenuation = storage->light_get_param(base, RS::LIGHT_PARAM_ATTENUATION); @@ -4641,7 +4641,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e params.fog_frustum_end = fog_end; - Color ambient_color = env->ambient_light.to_linear(); + Color ambient_color = env->ambient_light.srgb_to_linear(); params.ambient_color[0] = ambient_color.r; params.ambient_color[1] = ambient_color.g; params.ambient_color[2] = ambient_color.b; @@ -4653,13 +4653,13 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e params.directional_light_count = p_directional_light_count; - Color emission = env->volumetric_fog_emission.to_linear(); + Color emission = env->volumetric_fog_emission.srgb_to_linear(); params.base_emission[0] = emission.r * env->volumetric_fog_emission_energy; params.base_emission[1] = emission.g * env->volumetric_fog_emission_energy; params.base_emission[2] = emission.b * env->volumetric_fog_emission_energy; params.base_density = env->volumetric_fog_density; - Color base_scattering = env->volumetric_fog_scattering.to_linear(); + Color base_scattering = env->volumetric_fog_scattering.srgb_to_linear(); params.base_scattering[0] = base_scattering.r; params.base_scattering[1] = base_scattering.g; params.base_scattering[2] = base_scattering.b; diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp index 061aa8b4aa..44298711cd 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp @@ -1194,7 +1194,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b float sign = storage->light_is_negative(base) ? -1 : 1; sky_light_data.energy = sign * storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY); - Color linear_col = storage->light_get_color(base).to_linear(); + Color linear_col = storage->light_get_color(base).srgb_to_linear(); sky_light_data.color[0] = linear_col.r; sky_light_data.color[1] = linear_col.g; sky_light_data.color[2] = linear_col.b; @@ -1286,7 +1286,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b sky_scene_state.ubo.fog_enabled = p_env->fog_enabled; sky_scene_state.ubo.fog_density = p_env->fog_density; sky_scene_state.ubo.fog_aerial_perspective = p_env->fog_aerial_perspective; - Color fog_color = p_env->fog_light_color.to_linear(); + Color fog_color = p_env->fog_light_color.srgb_to_linear(); float fog_energy = p_env->fog_light_energy; sky_scene_state.ubo.fog_light_color[0] = fog_color.r * fog_energy; sky_scene_state.ubo.fog_light_color[1] = fog_color.g * fog_energy; diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp index 9e3d124bbb..2a2c5f350a 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp @@ -422,7 +422,7 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy if (i < s) { Color color = a[i]; if (p_linear_color) { - color = color.to_linear(); + color = color.srgb_to_linear(); } gui[j] = color.r; gui[j + 1] = color.g; @@ -459,7 +459,7 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy Color v = value; if (p_linear_color) { - v = v.to_linear(); + v = v.srgb_to_linear(); } gui[0] = v.r; @@ -1498,7 +1498,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob bv.w = v.a; GlobalVariables::Value &bv_linear = global_variables.buffer_values[p_index + 1]; - v = v.to_linear(); + v = v.srgb_to_linear(); bv_linear.x = v.r; bv_linear.y = v.g; bv_linear.z = v.b; diff --git a/tests/core/math/test_color.h b/tests/core/math/test_color.h index 6f40f8ecc0..51c3bc8bdc 100644 --- a/tests/core/math/test_color.h +++ b/tests/core/math/test_color.h @@ -146,8 +146,8 @@ TEST_CASE("[Color] Conversion methods") { TEST_CASE("[Color] Linear <-> sRGB conversion") { const Color color = Color(0.35, 0.5, 0.6, 0.7); - const Color color_linear = color.to_linear(); - const Color color_srgb = color.to_srgb(); + const Color color_linear = color.srgb_to_linear(); + const Color color_srgb = color.linear_to_srgb(); CHECK_MESSAGE( color_linear.is_equal_approx(Color(0.100481, 0.214041, 0.318547, 0.7)), "The color converted to linear color space should match the expected value."); @@ -155,10 +155,10 @@ TEST_CASE("[Color] Linear <-> sRGB conversion") { color_srgb.is_equal_approx(Color(0.62621, 0.735357, 0.797738, 0.7)), "The color converted to sRGB color space should match the expected value."); CHECK_MESSAGE( - color_linear.to_srgb().is_equal_approx(Color(0.35, 0.5, 0.6, 0.7)), + color_linear.linear_to_srgb().is_equal_approx(Color(0.35, 0.5, 0.6, 0.7)), "The linear color converted back to sRGB color space should match the expected value."); CHECK_MESSAGE( - color_srgb.to_linear().is_equal_approx(Color(0.35, 0.5, 0.6, 0.7)), + color_srgb.srgb_to_linear().is_equal_approx(Color(0.35, 0.5, 0.6, 0.7)), "The sRGB color converted back to linear color space should match the expected value."); } |