diff options
Diffstat (limited to 'scene')
-rw-r--r-- | scene/2d/area_2d.cpp | 8 | ||||
-rw-r--r-- | scene/2d/physics_body_2d.cpp | 4 | ||||
-rw-r--r-- | scene/2d/tile_map.cpp | 17 | ||||
-rw-r--r-- | scene/2d/tile_map.h | 2 | ||||
-rw-r--r-- | scene/3d/area_3d.cpp | 8 | ||||
-rw-r--r-- | scene/3d/bone_attachment_3d.cpp | 6 | ||||
-rw-r--r-- | scene/3d/bone_attachment_3d.h | 1 | ||||
-rw-r--r-- | scene/3d/mesh_instance_3d.cpp | 4 | ||||
-rw-r--r-- | scene/3d/physics_body_3d.cpp | 4 | ||||
-rw-r--r-- | scene/3d/skeleton_3d.cpp | 236 | ||||
-rw-r--r-- | scene/3d/skeleton_3d.h | 15 | ||||
-rw-r--r-- | scene/animation/animation_tree.cpp | 3 | ||||
-rw-r--r-- | scene/gui/texture_progress_bar.cpp | 12 | ||||
-rw-r--r-- | scene/gui/video_player.cpp | 4 | ||||
-rw-r--r-- | scene/resources/environment.cpp | 2 | ||||
-rw-r--r-- | scene/resources/importer_mesh.cpp | 6 | ||||
-rw-r--r-- | scene/resources/skeleton_modification_3d_fabrik.cpp | 2 | ||||
-rw-r--r-- | scene/resources/skeleton_modification_3d_twoboneik.cpp | 2 | ||||
-rw-r--r-- | scene/resources/tile_set.cpp | 87 | ||||
-rw-r--r-- | scene/resources/tile_set.h | 8 |
20 files changed, 213 insertions, 218 deletions
diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp index 33b1c7bcce..fff9c47d4d 100644 --- a/scene/2d/area_2d.cpp +++ b/scene/2d/area_2d.cpp @@ -533,13 +533,13 @@ void Area2D::_bind_methods() { ClassDB::bind_method(D_METHOD("_body_inout"), &Area2D::_body_inout); ClassDB::bind_method(D_METHOD("_area_inout"), &Area2D::_area_inout); - ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); - ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); + ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index"))); + ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index"))); ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"))); ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"))); - ADD_SIGNAL(MethodInfo("area_shape_entered", PropertyInfo(Variant::RID, "area_rid"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape"))); - ADD_SIGNAL(MethodInfo("area_shape_exited", PropertyInfo(Variant::RID, "area_rid"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape"))); + ADD_SIGNAL(MethodInfo("area_shape_entered", PropertyInfo(Variant::RID, "area_rid"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D"), PropertyInfo(Variant::INT, "area_shape_index"), PropertyInfo(Variant::INT, "local_shape_index"))); + ADD_SIGNAL(MethodInfo("area_shape_exited", PropertyInfo(Variant::RID, "area_rid"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D"), PropertyInfo(Variant::INT, "area_shape_index"), PropertyInfo(Variant::INT, "local_shape_index"))); ADD_SIGNAL(MethodInfo("area_entered", PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D"))); ADD_SIGNAL(MethodInfo("area_exited", PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D"))); diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index f493d97ceb..41288d646f 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -1000,8 +1000,8 @@ void RigidDynamicBody2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "applied_force"), "set_applied_force", "get_applied_force"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "applied_torque"), "set_applied_torque", "get_applied_torque"); - ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); - ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); + ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index"))); + ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index"))); ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); ADD_SIGNAL(MethodInfo("sleeping_state_changed")); diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 42c54a950d..c2f150ce00 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -811,8 +811,9 @@ void TileMap::_rendering_cleanup_layer(int p_layer) { ERR_FAIL_INDEX(p_layer, (int)layers.size()); RenderingServer *rs = RenderingServer::get_singleton(); - if (!layers[p_layer].canvas_item.is_valid()) { + if (layers[p_layer].canvas_item.is_valid()) { rs->free(layers[p_layer].canvas_item); + layers[p_layer].canvas_item = RID(); } } @@ -3094,6 +3095,8 @@ void TileMap::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_tile_data", "layer"), &TileMap::_set_tile_data); ClassDB::bind_method(D_METHOD("_get_tile_data", "layer"), &TileMap::_get_tile_data); + ClassDB::bind_method(D_METHOD("_tile_set_changed_deferred_update"), &TileMap::_tile_set_changed_deferred_update); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "tile_set", PROPERTY_HINT_RESOURCE_TYPE, "TileSet"), "set_tileset", "get_tileset"); ADD_PROPERTY(PropertyInfo(Variant::INT, "cell_quadrant_size", PROPERTY_HINT_RANGE, "1,128,1"), "set_quadrant_size", "get_quadrant_size"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collision_animatable"), "set_collision_animatable", "is_collision_animatable"); @@ -3113,8 +3116,16 @@ void TileMap::_bind_methods() { void TileMap::_tile_set_changed() { emit_signal(SNAME("changed")); - _clear_internals(); - _recreate_internals(); + _tile_set_changed_deferred_update_needed = true; + call_deferred("_tile_set_changed_deferred_update"); +} + +void TileMap::_tile_set_changed_deferred_update() { + if (_tile_set_changed_deferred_update_needed) { + _clear_internals(); + _recreate_internals(); + _tile_set_changed_deferred_update_needed = false; + } } TileMap::TileMap() { diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index b1fbdfdf8a..e5809deabb 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -285,6 +285,8 @@ private: Vector<int> _get_tile_data(int p_layer) const; void _tile_set_changed(); + bool _tile_set_changed_deferred_update_needed = false; + void _tile_set_changed_deferred_update(); protected: bool _set(const StringName &p_name, const Variant &p_value); diff --git a/scene/3d/area_3d.cpp b/scene/3d/area_3d.cpp index 7e4c40ca0e..d411525707 100644 --- a/scene/3d/area_3d.cpp +++ b/scene/3d/area_3d.cpp @@ -649,13 +649,13 @@ void Area3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_reverb_uniformity", "amount"), &Area3D::set_reverb_uniformity); ClassDB::bind_method(D_METHOD("get_reverb_uniformity"), &Area3D::get_reverb_uniformity); - ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node3D"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); - ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node3D"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); + ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node3D"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index"))); + ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node3D"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index"))); ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node3D"))); ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node3D"))); - ADD_SIGNAL(MethodInfo("area_shape_entered", PropertyInfo(Variant::RID, "area_rid"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape"))); - ADD_SIGNAL(MethodInfo("area_shape_exited", PropertyInfo(Variant::RID, "area_rid"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape"))); + ADD_SIGNAL(MethodInfo("area_shape_entered", PropertyInfo(Variant::RID, "area_rid"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D"), PropertyInfo(Variant::INT, "area_shape_index"), PropertyInfo(Variant::INT, "local_shape_index"))); + ADD_SIGNAL(MethodInfo("area_shape_exited", PropertyInfo(Variant::RID, "area_rid"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D"), PropertyInfo(Variant::INT, "area_shape_index"), PropertyInfo(Variant::INT, "local_shape_index"))); ADD_SIGNAL(MethodInfo("area_entered", PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D"))); ADD_SIGNAL(MethodInfo("area_exited", PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D"))); diff --git a/scene/3d/bone_attachment_3d.cpp b/scene/3d/bone_attachment_3d.cpp index afd11482e3..8e89f4fc54 100644 --- a/scene/3d/bone_attachment_3d.cpp +++ b/scene/3d/bone_attachment_3d.cpp @@ -215,8 +215,6 @@ void BoneAttachment3D::_transform_changed() { sk->set_bone_global_pose_override(bone_idx, our_trans, 1.0, true); } else if (override_mode == OVERRIDE_MODES::MODE_LOCAL_POSE) { sk->set_bone_local_pose_override(bone_idx, sk->global_pose_to_local_pose(bone_idx, our_trans), 1.0, true); - } else if (override_mode == OVERRIDE_MODES::MODE_CUSTOM_POSE) { - sk->set_bone_custom_pose(bone_idx, sk->global_pose_to_local_pose(bone_idx, our_trans)); } } } @@ -273,8 +271,6 @@ void BoneAttachment3D::set_override_pose(bool p_override) { sk->set_bone_global_pose_override(bone_idx, Transform3D(), 0.0, false); } else if (override_mode == OVERRIDE_MODES::MODE_LOCAL_POSE) { sk->set_bone_local_pose_override(bone_idx, Transform3D(), 0.0, false); - } else if (override_mode == OVERRIDE_MODES::MODE_CUSTOM_POSE) { - sk->set_bone_custom_pose(bone_idx, Transform3D()); } } _transform_changed(); @@ -294,8 +290,6 @@ void BoneAttachment3D::set_override_mode(int p_mode) { sk->set_bone_global_pose_override(bone_idx, Transform3D(), 0.0, false); } else if (override_mode == OVERRIDE_MODES::MODE_LOCAL_POSE) { sk->set_bone_local_pose_override(bone_idx, Transform3D(), 0.0, false); - } else if (override_mode == OVERRIDE_MODES::MODE_CUSTOM_POSE) { - sk->set_bone_custom_pose(bone_idx, Transform3D()); } } override_mode = p_mode; diff --git a/scene/3d/bone_attachment_3d.h b/scene/3d/bone_attachment_3d.h index cf681cace8..57b9854e0e 100644 --- a/scene/3d/bone_attachment_3d.h +++ b/scene/3d/bone_attachment_3d.h @@ -47,7 +47,6 @@ class BoneAttachment3D : public Node3D { enum OVERRIDE_MODES { MODE_GLOBAL_POSE, MODE_LOCAL_POSE, - MODE_CUSTOM_POSE }; bool use_external_skeleton = false; diff --git a/scene/3d/mesh_instance_3d.cpp b/scene/3d/mesh_instance_3d.cpp index 67f4a88228..cfd90e5da0 100644 --- a/scene/3d/mesh_instance_3d.cpp +++ b/scene/3d/mesh_instance_3d.cpp @@ -146,11 +146,13 @@ void MeshInstance3D::_resolve_skeleton_path() { if (!skeleton_path.is_empty()) { Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(get_node(skeleton_path)); if (skeleton) { - new_skin_reference = skeleton->register_skin(skin_internal); if (skin_internal.is_null()) { + new_skin_reference = skeleton->register_skin(skeleton->create_skin_from_rest_transforms()); //a skin was created for us skin_internal = new_skin_reference->get_skin(); notify_property_list_changed(); + } else { + new_skin_reference = skeleton->register_skin(skin_internal); } } } diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index 976bff4fbc..8cb348d6e3 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -1040,8 +1040,8 @@ void RigidDynamicBody3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "angular_velocity"), "set_angular_velocity", "get_angular_velocity"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp"); - ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); - ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); + ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index"))); + ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index"))); ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); ADD_SIGNAL(MethodInfo("sleeping_state_changed")); diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp index 79504b10bb..14506fd9bd 100644 --- a/scene/3d/skeleton_3d.cpp +++ b/scene/3d/skeleton_3d.cpp @@ -171,6 +171,45 @@ void Skeleton3D::_get_property_list(List<PropertyInfo> *p_list) const { "SkeletonModificationStack3D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE)); #endif //_3D_DISABLED + + for (PropertyInfo &E : *p_list) { + _validate_property(E); + } +} + +void Skeleton3D::_validate_property(PropertyInfo &property) const { + PackedStringArray spr = property.name.split("/"); + if (spr.size() == 3 && spr[0] == "bones") { + if (spr[2] == "rest") { + property.usage |= PROPERTY_USAGE_READ_ONLY; + } + if (is_show_rest_only()) { + if (spr[2] == "enabled") { + property.usage |= PROPERTY_USAGE_READ_ONLY; + } + if (spr[2] == "position") { + property.usage |= PROPERTY_USAGE_READ_ONLY; + } + if (spr[2] == "rotation") { + property.usage |= PROPERTY_USAGE_READ_ONLY; + } + if (spr[2] == "scale") { + property.usage |= PROPERTY_USAGE_READ_ONLY; + } + } else if (!is_bone_enabled(spr[1].to_int())) { + if (spr[2] == "position") { + property.usage |= PROPERTY_USAGE_READ_ONLY; + } + if (spr[2] == "rotation") { + property.usage |= PROPERTY_USAGE_READ_ONLY; + } + if (spr[2] == "scale") { + property.usage |= PROPERTY_USAGE_READ_ONLY; + } + } + } + + Node3D::_validate_property(property); } void Skeleton3D::_update_process_order() { @@ -557,18 +596,6 @@ void Skeleton3D::unparent_bone_and_rest(int p_bone) { _make_dirty(); } -void Skeleton3D::set_bone_disable_rest(int p_bone, bool p_disable) { - const int bone_size = bones.size(); - ERR_FAIL_INDEX(p_bone, bone_size); - bones.write[p_bone].disable_rest = p_disable; -} - -bool Skeleton3D::is_bone_rest_disabled(int p_bone) const { - const int bone_size = bones.size(); - ERR_FAIL_INDEX_V(p_bone, bone_size, false); - return bones[p_bone].disable_rest; -} - int Skeleton3D::get_bone_parent(int p_bone) const { const int bone_size = bones.size(); ERR_FAIL_INDEX_V(p_bone, bone_size, -1); @@ -723,23 +750,6 @@ Transform3D Skeleton3D::get_bone_pose(int p_bone) const { return bones[p_bone].pose_cache; } -void Skeleton3D::set_bone_custom_pose(int p_bone, const Transform3D &p_custom_pose) { - const int bone_size = bones.size(); - ERR_FAIL_INDEX(p_bone, bone_size); - //ERR_FAIL_COND( !is_inside_scene() ); - - bones.write[p_bone].custom_pose_enable = (p_custom_pose != Transform3D()); - bones.write[p_bone].custom_pose = p_custom_pose; - - _make_dirty(); -} - -Transform3D Skeleton3D::get_bone_custom_pose(int p_bone) const { - const int bone_size = bones.size(); - ERR_FAIL_INDEX_V(p_bone, bone_size, Transform3D()); - return bones[p_bone].custom_pose; -} - void Skeleton3D::_make_dirty() { if (dirty) { return; @@ -938,59 +948,57 @@ void Skeleton3D::_skin_changed() { _make_dirty(); } -Ref<SkinReference> Skeleton3D::register_skin(const Ref<Skin> &p_skin) { - for (Set<SkinReference *>::Element *E = skin_bindings.front(); E; E = E->next()) { - if (E->get()->skin == p_skin) { - return Ref<SkinReference>(E->get()); +Ref<Skin> Skeleton3D::create_skin_from_rest_transforms() { + Ref<Skin> skin; + + skin.instantiate(); + skin->set_bind_count(bones.size()); + _update_process_order(); // Just in case. + + // Pose changed, rebuild cache of inverses. + const Bone *bonesptr = bones.ptr(); + int len = bones.size(); + + // Calculate global rests and invert them. + LocalVector<int> bones_to_process; + bones_to_process = get_parentless_bones(); + while (bones_to_process.size() > 0) { + int current_bone_idx = bones_to_process[0]; + const Bone &b = bonesptr[current_bone_idx]; + bones_to_process.erase(current_bone_idx); + LocalVector<int> child_bones_vector; + child_bones_vector = get_bone_children(current_bone_idx); + int child_bones_size = child_bones_vector.size(); + if (b.parent < 0) { + skin->set_bind_pose(current_bone_idx, b.rest); + } + for (int i = 0; i < child_bones_size; i++) { + int child_bone_idx = child_bones_vector[i]; + const Bone &cb = bonesptr[child_bone_idx]; + skin->set_bind_pose(child_bone_idx, skin->get_bind_pose(current_bone_idx) * cb.rest); + // Add the bone's children to the list of bones to be processed. + bones_to_process.push_back(child_bones_vector[i]); } } - Ref<Skin> skin = p_skin; - - if (skin.is_null()) { - // Need to create one from existing code, this is for compatibility only - // when skeletons did not support skins. It is also used by gizmo - // to display the skeleton. - - skin.instantiate(); - skin->set_bind_count(bones.size()); - _update_process_order(); // Just in case. - - // Pose changed, rebuild cache of inverses. - const Bone *bonesptr = bones.ptr(); - int len = bones.size(); - - // Calculate global rests and invert them. - LocalVector<int> bones_to_process; - bones_to_process = get_parentless_bones(); - while (bones_to_process.size() > 0) { - int current_bone_idx = bones_to_process[0]; - const Bone &b = bonesptr[current_bone_idx]; - bones_to_process.erase(current_bone_idx); - LocalVector<int> child_bones_vector; - child_bones_vector = get_bone_children(current_bone_idx); - int child_bones_size = child_bones_vector.size(); - if (b.parent < 0) { - skin->set_bind_pose(current_bone_idx, b.rest); - } - for (int i = 0; i < child_bones_size; i++) { - int child_bone_idx = child_bones_vector[i]; - const Bone &cb = bonesptr[child_bone_idx]; - skin->set_bind_pose(child_bone_idx, skin->get_bind_pose(current_bone_idx) * cb.rest); - // Add the bone's children to the list of bones to be processed. - bones_to_process.push_back(child_bones_vector[i]); - } - } + for (int i = 0; i < len; i++) { + // The inverse is what is actually required. + skin->set_bind_bone(i, i); + skin->set_bind_pose(i, skin->get_bind_pose(i).affine_inverse()); + } + + return skin; +} - for (int i = 0; i < len; i++) { - // The inverse is what is actually required. - skin->set_bind_bone(i, i); - skin->set_bind_pose(i, skin->get_bind_pose(i).affine_inverse()); +Ref<SkinReference> Skeleton3D::register_skin(const Ref<Skin> &p_skin) { + ERR_FAIL_COND_V(p_skin.is_null(), Ref<SkinReference>()); + + for (Set<SkinReference *>::Element *E = skin_bindings.front(); E; E = E->next()) { + if (E->get()->skin == p_skin) { + return Ref<SkinReference>(E->get()); } } - ERR_FAIL_COND_V(skin.is_null(), Ref<SkinReference>()); - Ref<SkinReference> skin_ref; skin_ref.instantiate(); @@ -998,11 +1006,11 @@ Ref<SkinReference> Skeleton3D::register_skin(const Ref<Skin> &p_skin) { skin_ref->bind_count = 0; skin_ref->skeleton = RenderingServer::get_singleton()->skeleton_create(); skin_ref->skeleton_node = this; - skin_ref->skin = skin; + skin_ref->skin = p_skin; skin_bindings.insert(skin_ref.operator->()); - skin->connect("changed", Callable(skin_ref.operator->(), "_skin_changed")); + skin_ref->skin->connect("changed", Callable(skin_ref.operator->(), "_skin_changed")); _make_dirty(); // Skin needs to be updated, so update skeleton. @@ -1038,61 +1046,33 @@ void Skeleton3D::force_update_bone_children_transforms(int p_bone_idx) { Bone &b = bonesptr[current_bone_idx]; bool bone_enabled = b.enabled && !show_rest_only; - if (b.disable_rest) { - if (bone_enabled) { - b.update_pose_cache(); - Transform3D pose = b.pose_cache; - if (b.custom_pose_enable) { - pose = b.custom_pose * pose; - } - if (b.parent >= 0) { - b.pose_global = bonesptr[b.parent].pose_global * pose; - b.pose_global_no_override = b.pose_global; - } else { - b.pose_global = pose; - b.pose_global_no_override = b.pose_global; - } + if (bone_enabled) { + b.update_pose_cache(); + Transform3D pose = b.pose_cache; + + if (b.parent >= 0) { + b.pose_global = bonesptr[b.parent].pose_global * pose; + b.pose_global_no_override = b.pose_global; } else { - if (b.parent >= 0) { - b.pose_global = bonesptr[b.parent].pose_global; - b.pose_global_no_override = b.pose_global; - } else { - b.pose_global = Transform3D(); - b.pose_global_no_override = b.pose_global; - } + b.pose_global = pose; + b.pose_global_no_override = b.pose_global; } - } else { - if (bone_enabled) { - b.update_pose_cache(); - Transform3D pose = b.pose_cache; - if (b.custom_pose_enable) { - pose = b.custom_pose * pose; - } - if (b.parent >= 0) { - b.pose_global = bonesptr[b.parent].pose_global * (b.rest * pose); - b.pose_global_no_override = b.pose_global; - } else { - b.pose_global = b.rest * pose; - b.pose_global_no_override = b.pose_global; - } + if (b.parent >= 0) { + b.pose_global = bonesptr[b.parent].pose_global * b.rest; + b.pose_global_no_override = b.pose_global; } else { - if (b.parent >= 0) { - b.pose_global = bonesptr[b.parent].pose_global * b.rest; - b.pose_global_no_override = b.pose_global; - } else { - b.pose_global = b.rest; - b.pose_global_no_override = b.pose_global; - } + b.pose_global = b.rest; + b.pose_global_no_override = b.pose_global; } } if (b.local_pose_override_amount >= CMP_EPSILON) { Transform3D override_local_pose; if (b.parent >= 0) { - override_local_pose = bonesptr[b.parent].pose_global * (b.rest * b.local_pose_override); + override_local_pose = bonesptr[b.parent].pose_global * b.local_pose_override; } else { - override_local_pose = (b.rest * b.local_pose_override); + override_local_pose = b.local_pose_override; } b.pose_global = b.pose_global.interpolate_with(override_local_pose, b.local_pose_override_amount); } @@ -1133,8 +1113,8 @@ Transform3D Skeleton3D::global_pose_to_local_pose(int p_bone_idx, Transform3D p_ ERR_FAIL_INDEX_V(p_bone_idx, bone_size, Transform3D()); if (bones[p_bone_idx].parent >= 0) { int parent_bone_idx = bones[p_bone_idx].parent; - Transform3D conversion_transform = (bones[parent_bone_idx].pose_global * bones[p_bone_idx].rest); - return conversion_transform.affine_inverse() * p_global_pose; + Transform3D conversion_transform = bones[parent_bone_idx].pose_global.affine_inverse(); + return conversion_transform * p_global_pose; } else { return p_global_pose; } @@ -1145,8 +1125,7 @@ Transform3D Skeleton3D::local_pose_to_global_pose(int p_bone_idx, Transform3D p_ ERR_FAIL_INDEX_V(p_bone_idx, bone_size, Transform3D()); if (bones[p_bone_idx].parent >= 0) { int parent_bone_idx = bones[p_bone_idx].parent; - Transform3D conversion_transform = (bones[parent_bone_idx].pose_global * bones[p_bone_idx].rest); - return conversion_transform * p_local_pose; + return bones[parent_bone_idx].pose_global * p_local_pose; } else { return p_local_pose; } @@ -1236,13 +1215,11 @@ void Skeleton3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_bone_rest", "bone_idx"), &Skeleton3D::get_bone_rest); ClassDB::bind_method(D_METHOD("set_bone_rest", "bone_idx", "rest"), &Skeleton3D::set_bone_rest); + ClassDB::bind_method(D_METHOD("create_skin_from_rest_transforms"), &Skeleton3D::create_skin_from_rest_transforms); ClassDB::bind_method(D_METHOD("register_skin", "skin"), &Skeleton3D::register_skin); ClassDB::bind_method(D_METHOD("localize_rests"), &Skeleton3D::localize_rests); - ClassDB::bind_method(D_METHOD("set_bone_disable_rest", "bone_idx", "disable"), &Skeleton3D::set_bone_disable_rest); - ClassDB::bind_method(D_METHOD("is_bone_rest_disabled", "bone_idx"), &Skeleton3D::is_bone_rest_disabled); - ClassDB::bind_method(D_METHOD("clear_bones"), &Skeleton3D::clear_bones); ClassDB::bind_method(D_METHOD("get_bone_pose", "bone_idx"), &Skeleton3D::get_bone_pose); @@ -1267,9 +1244,6 @@ void Skeleton3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_bone_local_pose_override", "bone_idx", "pose", "amount", "persistent"), &Skeleton3D::set_bone_local_pose_override, DEFVAL(false)); ClassDB::bind_method(D_METHOD("get_bone_local_pose_override", "bone_idx"), &Skeleton3D::get_bone_local_pose_override); - ClassDB::bind_method(D_METHOD("get_bone_custom_pose", "bone_idx"), &Skeleton3D::get_bone_custom_pose); - ClassDB::bind_method(D_METHOD("set_bone_custom_pose", "bone_idx", "custom_pose"), &Skeleton3D::set_bone_custom_pose); - ClassDB::bind_method(D_METHOD("force_update_all_bone_transforms"), &Skeleton3D::force_update_all_bone_transforms); ClassDB::bind_method(D_METHOD("force_update_bone_child_transform", "bone_idx"), &Skeleton3D::force_update_bone_children_transforms); diff --git a/scene/3d/skeleton_3d.h b/scene/3d/skeleton_3d.h index aacee3da4e..f7bc3df94e 100644 --- a/scene/3d/skeleton_3d.h +++ b/scene/3d/skeleton_3d.h @@ -76,7 +76,6 @@ private: bool enabled; int parent; - bool disable_rest = false; Transform3D rest; _FORCE_INLINE_ void update_pose_cache() { @@ -95,9 +94,6 @@ private: Transform3D pose_global; Transform3D pose_global_no_override; - bool custom_pose_enable = false; - Transform3D custom_pose; - real_t global_pose_override_amount = 0.0; bool global_pose_override_reset = false; Transform3D global_pose_override; @@ -119,8 +115,6 @@ private: Bone() { parent = -1; enabled = true; - disable_rest = false; - custom_pose_enable = false; global_pose_override_amount = 0; global_pose_override_reset = false; #ifndef _3D_DISABLED @@ -159,6 +153,7 @@ protected: bool _get(const StringName &p_path, Variant &r_ret) const; bool _set(const StringName &p_path, const Variant &p_value); void _get_property_list(List<PropertyInfo> *p_list) const; + virtual void _validate_property(PropertyInfo &property) const override; void _notification(int p_what); static void _bind_methods(); @@ -199,9 +194,6 @@ public: void remove_bone_child(int p_bone, int p_child); Vector<int> get_parentless_bones(); - void set_bone_disable_rest(int p_bone, bool p_disable); - bool is_bone_rest_disabled(int p_bone) const; - int get_bone_count() const; void set_bone_rest(int p_bone, const Transform3D &p_rest); @@ -228,9 +220,6 @@ public: Quaternion get_bone_pose_rotation(int p_bone) const; Vector3 get_bone_pose_scale(int p_bone) const; - void set_bone_custom_pose(int p_bone, const Transform3D &p_custom_pose); - Transform3D get_bone_custom_pose(int p_bone) const; - void clear_bones_global_pose_override(); Transform3D get_bone_global_pose_override(int p_bone) const; void set_bone_global_pose_override(int p_bone, const Transform3D &p_pose, real_t p_amount, bool p_persistent = false); @@ -241,6 +230,8 @@ public: void localize_rests(); // used for loaders and tools + Ref<Skin> create_skin_from_rest_transforms(); + Ref<SkinReference> register_skin(const Ref<Skin> &p_skin); void force_update_all_dirty_bones(); diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index 2ed8268289..dd5fe46223 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -1360,9 +1360,6 @@ void AnimationTree::_process_graph(real_t p_delta) { root_motion_transform = xform; - if (t->skeleton && t->bone_idx >= 0) { - root_motion_transform = (t->skeleton->get_bone_rest(t->bone_idx) * root_motion_transform) * t->skeleton->get_bone_rest(t->bone_idx).affine_inverse(); - } } else if (t->skeleton && t->bone_idx >= 0) { if (t->loc_used) { t->skeleton->set_bone_pose_position(t->bone_idx, t->loc); diff --git a/scene/gui/texture_progress_bar.cpp b/scene/gui/texture_progress_bar.cpp index 35a098c6fd..fe11de128a 100644 --- a/scene/gui/texture_progress_bar.cpp +++ b/scene/gui/texture_progress_bar.cpp @@ -341,7 +341,11 @@ void TextureProgressBar::draw_nine_patch_stretched(const Ref<Texture2D> &p_textu } break; case FILL_BILINEAR_LEFT_AND_RIGHT: { double center_mapped_from_real_width = (width_total * 0.5 - topleft.x) / max_middle_real_size * max_middle_texture_size + topleft.x; - double drift_from_unscaled_center = (src_rect.size.x * 0.5 - center_mapped_from_real_width) * (last_section_size - first_section_size) / (bottomright.x - topleft.x); + double drift_from_unscaled_center = 0; + if (bottomright.y != topleft.y) { // To avoid division by zero. + drift_from_unscaled_center = (src_rect.size.x * 0.5 - center_mapped_from_real_width) * (last_section_size - first_section_size) / (bottomright.x - topleft.x); + } + src_rect.position.x += center_mapped_from_real_width + drift_from_unscaled_center - width_texture * 0.5; src_rect.size.x = width_texture; dst_rect.position.x += (width_total - width_filled) * 0.5; @@ -351,7 +355,11 @@ void TextureProgressBar::draw_nine_patch_stretched(const Ref<Texture2D> &p_textu } break; case FILL_BILINEAR_TOP_AND_BOTTOM: { double center_mapped_from_real_width = (width_total * 0.5 - topleft.y) / max_middle_real_size * max_middle_texture_size + topleft.y; - double drift_from_unscaled_center = (src_rect.size.y * 0.5 - center_mapped_from_real_width) * (last_section_size - first_section_size) / (bottomright.y - topleft.y); + double drift_from_unscaled_center = 0; + if (bottomright.y != topleft.y) { // To avoid division by zero. + drift_from_unscaled_center = (src_rect.size.y * 0.5 - center_mapped_from_real_width) * (last_section_size - first_section_size) / (bottomright.y - topleft.y); + } + src_rect.position.y += center_mapped_from_real_width + drift_from_unscaled_center - width_texture * 0.5; src_rect.size.y = width_texture; dst_rect.position.y += (width_total - width_filled) * 0.5; diff --git a/scene/gui/video_player.cpp b/scene/gui/video_player.cpp index 8734037a57..989aabc549 100644 --- a/scene/gui/video_player.cpp +++ b/scene/gui/video_player.cpp @@ -29,9 +29,9 @@ /*************************************************************************/ #include "video_player.h" -#include "scene/scene_string_names.h" #include "core/os/os.h" +#include "scene/scene_string_names.h" #include "servers/audio_server.h" int VideoPlayer::sp_get_channel_count() const { @@ -55,7 +55,7 @@ bool VideoPlayer::mix(AudioFrame *p_buffer, int p_frames) { return false; } -// Called from main thread (eg VideoStreamPlaybackWebm::update) +// Called from main thread (e.g. VideoStreamPlaybackTheora::update). int VideoPlayer::_audio_mix_callback(void *p_udata, const float *p_data, int p_frames) { ERR_FAIL_NULL_V(p_udata, 0); ERR_FAIL_NULL_V(p_data, 0); diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index 9a3f081a8b..be0d3a140e 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -1291,7 +1291,7 @@ void Environment::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_density", PROPERTY_HINT_RANGE, "0,16,0.0001"), "set_fog_density", "get_fog_density"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_aerial_perspective", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_fog_aerial_perspective", "get_fog_aerial_perspective"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_height", PROPERTY_HINT_RANGE, "-1024,1024,0.01,or_lesser,or_greater"), "set_fog_height", "get_fog_height"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_height_density", PROPERTY_HINT_RANGE, "0,128,0.001,or_greater"), "set_fog_height_density", "get_fog_height_density"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_height_density", PROPERTY_HINT_RANGE, "-16,16,0.0001,or_lesser,or_greater"), "set_fog_height_density", "get_fog_height_density"); ClassDB::bind_method(D_METHOD("set_volumetric_fog_enabled", "enabled"), &Environment::set_volumetric_fog_enabled); ClassDB::bind_method(D_METHOD("is_volumetric_fog_enabled"), &Environment::is_volumetric_fog_enabled); diff --git a/scene/resources/importer_mesh.cpp b/scene/resources/importer_mesh.cpp index 2572c5de33..076b8312b6 100644 --- a/scene/resources/importer_mesh.cpp +++ b/scene/resources/importer_mesh.cpp @@ -997,7 +997,7 @@ Ref<NavigationMesh> ImporterMesh::create_navigation_mesh() { extern bool (*array_mesh_lightmap_unwrap_callback)(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, int p_index_count, const uint8_t *p_cache_data, bool *r_use_cache, uint8_t **r_mesh_cache, int *r_mesh_cache_size, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y); -struct EditorSceneImporterMeshLightmapSurface { +struct EditorSceneFormatImporterMeshLightmapSurface { Ref<Material> material; LocalVector<SurfaceTool::Vertex> vertices; Mesh::PrimitiveType primitive = Mesh::PrimitiveType::PRIMITIVE_MAX; @@ -1015,7 +1015,7 @@ Error ImporterMesh::lightmap_unwrap_cached(const Transform3D &p_base_transform, LocalVector<float> uv; LocalVector<Pair<int, int>> uv_indices; - Vector<EditorSceneImporterMeshLightmapSurface> lightmap_surfaces; + Vector<EditorSceneFormatImporterMeshLightmapSurface> lightmap_surfaces; // Keep only the scale Basis basis = p_base_transform.get_basis(); @@ -1027,7 +1027,7 @@ Error ImporterMesh::lightmap_unwrap_cached(const Transform3D &p_base_transform, Basis normal_basis = transform.basis.inverse().transposed(); for (int i = 0; i < get_surface_count(); i++) { - EditorSceneImporterMeshLightmapSurface s; + EditorSceneFormatImporterMeshLightmapSurface s; s.primitive = get_surface_primitive_type(i); ERR_FAIL_COND_V_MSG(s.primitive != Mesh::PRIMITIVE_TRIANGLES, ERR_UNAVAILABLE, "Only triangles are supported for lightmap unwrap."); diff --git a/scene/resources/skeleton_modification_3d_fabrik.cpp b/scene/resources/skeleton_modification_3d_fabrik.cpp index e615615924..20ebbda256 100644 --- a/scene/resources/skeleton_modification_3d_fabrik.cpp +++ b/scene/resources/skeleton_modification_3d_fabrik.cpp @@ -168,7 +168,7 @@ void SkeletonModification3DFABRIK::_execute(real_t p_delta) { // Apply magnet positions: if (stack->skeleton->get_bone_parent(fabrik_data_chain[i].bone_idx) >= 0) { int parent_bone_idx = stack->skeleton->get_bone_parent(fabrik_data_chain[i].bone_idx); - Transform3D conversion_transform = (stack->skeleton->get_bone_global_pose(parent_bone_idx) * stack->skeleton->get_bone_rest(parent_bone_idx)); + Transform3D conversion_transform = (stack->skeleton->get_bone_global_pose(parent_bone_idx)); local_pose_override.origin += conversion_transform.basis.xform_inv(fabrik_data_chain[i].magnet_position); } else { local_pose_override.origin += fabrik_data_chain[i].magnet_position; diff --git a/scene/resources/skeleton_modification_3d_twoboneik.cpp b/scene/resources/skeleton_modification_3d_twoboneik.cpp index ae7a3bab7e..c1a71148a7 100644 --- a/scene/resources/skeleton_modification_3d_twoboneik.cpp +++ b/scene/resources/skeleton_modification_3d_twoboneik.cpp @@ -455,7 +455,7 @@ void SkeletonModification3DTwoBoneIK::calculate_joint_lengths() { joint_two_length = 0; for (int i = 0; i < bone_two_children.size(); i++) { joint_two_length += bone_two_rest_trans.origin.distance_to( - stack->skeleton->local_pose_to_global_pose(bone_two_children[i], stack->skeleton->get_bone_rest(bone_two_children[i])).origin); + stack->skeleton->get_bone_global_pose(bone_two_children[i]).origin); } joint_two_length = joint_two_length / bone_two_children.size(); } else { diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index f5e52b70e6..b988b2ab3e 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -3066,6 +3066,7 @@ void TileSetAtlasSource::reset_state() { void TileSetAtlasSource::set_texture(Ref<Texture2D> p_texture) { texture = p_texture; + _clear_tiles_outside_texture(); emit_changed(); } @@ -3081,6 +3082,7 @@ void TileSetAtlasSource::set_margins(Vector2i p_margins) { margins = p_margins; } + _clear_tiles_outside_texture(); emit_changed(); } Vector2i TileSetAtlasSource::get_margins() const { @@ -3095,6 +3097,7 @@ void TileSetAtlasSource::set_separation(Vector2i p_separation) { separation = p_separation; } + _clear_tiles_outside_texture(); emit_changed(); } Vector2i TileSetAtlasSource::get_separation() const { @@ -3109,6 +3112,7 @@ void TileSetAtlasSource::set_texture_region_size(Vector2i p_tile_size) { texture_region_size = p_tile_size; } + _clear_tiles_outside_texture(); emit_changed(); } Vector2i TileSetAtlasSource::get_texture_region_size() const { @@ -3354,7 +3358,7 @@ void TileSetAtlasSource::create_tile(const Vector2i p_atlas_coords, const Vector ERR_FAIL_COND(p_size.x <= 0 || p_size.y <= 0); bool room_for_tile = has_room_for_tile(p_atlas_coords, p_size, 1, Vector2i(), 1); - ERR_FAIL_COND_MSG(!room_for_tile, "Cannot create tile, tiles are already present in the space the tile would cover."); + ERR_FAIL_COND_MSG(!room_for_tile, "Cannot create tile. The tile is outside the texture or tiles are already present in the space the tile would cover."); // Initialize the tile data. TileAlternativesData tad; @@ -3552,9 +3556,7 @@ bool TileSetAtlasSource::has_room_for_tile(Vector2i p_atlas_coords, Vector2i p_s return false; } if (coords.x >= atlas_grid_size.x || coords.y >= atlas_grid_size.y) { - if (!(_coords_mapping_cache.has(coords) && _coords_mapping_cache[coords] == p_ignored_tile)) { - return false; // Only accept tiles outside the atlas if they are part of the ignored tile. - } + return false; } } } @@ -3562,6 +3564,37 @@ bool TileSetAtlasSource::has_room_for_tile(Vector2i p_atlas_coords, Vector2i p_s return true; } +PackedVector2Array TileSetAtlasSource::get_tiles_to_be_removed_on_change(Ref<Texture2D> p_texture, Vector2i p_margins, Vector2i p_separation, Vector2i p_texture_region_size) { + ERR_FAIL_COND_V(p_margins.x < 0 || p_margins.y < 0, PackedVector2Array()); + ERR_FAIL_COND_V(p_separation.x < 0 || p_separation.y < 0, PackedVector2Array()); + ERR_FAIL_COND_V(p_texture_region_size.x <= 0 || p_texture_region_size.y <= 0, PackedVector2Array()); + + // Compute the new atlas grid size. + Size2 new_grid_size; + if (p_texture.is_valid()) { + Size2i valid_area = p_texture->get_size() - p_margins; + + // Compute the number of valid tiles in the tiles atlas + if (valid_area.x >= p_texture_region_size.x && valid_area.y >= p_texture_region_size.y) { + valid_area -= p_texture_region_size; + new_grid_size = Size2i(1, 1) + valid_area / (p_texture_region_size + p_separation); + } + } + + Vector<Vector2> output; + for (KeyValue<Vector2i, TileAlternativesData> &E : tiles) { + for (unsigned int frame = 0; frame < E.value.animation_frames_durations.size(); frame++) { + Vector2i frame_coords = E.key + (E.value.size_in_atlas + E.value.animation_separation) * ((E.value.animation_columns > 0) ? Vector2i(frame % E.value.animation_columns, frame / E.value.animation_columns) : Vector2i(frame, 0)); + frame_coords += E.value.size_in_atlas; + if (frame_coords.x > new_grid_size.x || frame_coords.y > new_grid_size.y) { + output.push_back(E.key); + break; + } + } + } + return output; +} + Rect2i TileSetAtlasSource::get_tile_texture_region(Vector2i p_atlas_coords, int p_frame) const { ERR_FAIL_COND_V_MSG(!tiles.has(p_atlas_coords), Rect2i(), vformat("TileSetAtlasSource has no tile at %s.", String(p_atlas_coords))); ERR_FAIL_INDEX_V(p_frame, (int)tiles[p_atlas_coords].animation_frames_durations.size(), Rect2i()); @@ -3626,34 +3659,6 @@ void TileSetAtlasSource::move_tile_in_atlas(Vector2i p_atlas_coords, Vector2i p_ emit_signal(SNAME("changed")); } -bool TileSetAtlasSource::has_tiles_outside_texture() { - Vector2i grid_size = get_atlas_grid_size(); - Vector<Vector2i> to_remove; - - for (const KeyValue<Vector2i, TileSetAtlasSource::TileAlternativesData> &E : tiles) { - if (E.key.x >= grid_size.x || E.key.y >= grid_size.y) { - return true; - } - } - - return false; -} - -void TileSetAtlasSource::clear_tiles_outside_texture() { - Vector2i grid_size = get_atlas_grid_size(); - Vector<Vector2i> to_remove; - - for (const KeyValue<Vector2i, TileSetAtlasSource::TileAlternativesData> &E : tiles) { - if (E.key.x >= grid_size.x || E.key.y >= grid_size.y) { - to_remove.append(E.key); - } - } - - for (int i = 0; i < to_remove.size(); i++) { - remove_tile(to_remove[i]); - } -} - int TileSetAtlasSource::create_alternative_tile(const Vector2i p_atlas_coords, int p_alternative_id_override) { ERR_FAIL_COND_V_MSG(!tiles.has(p_atlas_coords), TileSetSource::INVALID_TILE_ALTERNATIVE, vformat("TileSetAtlasSource has no tile at %s.", String(p_atlas_coords))); ERR_FAIL_COND_V_MSG(p_alternative_id_override >= 0 && tiles[p_atlas_coords].alternatives.has(p_alternative_id_override), TileSetSource::INVALID_TILE_ALTERNATIVE, vformat("Cannot create alternative tile. Another alternative exists with id %d.", p_alternative_id_override)); @@ -3754,7 +3759,7 @@ void TileSetAtlasSource::_bind_methods() { ClassDB::bind_method(D_METHOD("get_tile_size_in_atlas", "atlas_coords"), &TileSetAtlasSource::get_tile_size_in_atlas); ClassDB::bind_method(D_METHOD("has_room_for_tile", "atlas_coords", "size", "animation_columns", "animation_separation", "frames_count", "ignored_tile"), &TileSetAtlasSource::has_room_for_tile, DEFVAL(INVALID_ATLAS_COORDS)); - + ClassDB::bind_method(D_METHOD("get_tiles_to_be_removed_on_change", "texture", "margins", "separation", "texture_region_size"), &TileSetAtlasSource::get_tiles_to_be_removed_on_change); ClassDB::bind_method(D_METHOD("get_tile_at_coords", "atlas_coords"), &TileSetAtlasSource::get_tile_at_coords); ClassDB::bind_method(D_METHOD("set_tile_animation_columns", "atlas_coords", "frame_columns"), &TileSetAtlasSource::set_tile_animation_columns); @@ -3779,8 +3784,6 @@ void TileSetAtlasSource::_bind_methods() { // Helpers. ClassDB::bind_method(D_METHOD("get_atlas_grid_size"), &TileSetAtlasSource::get_atlas_grid_size); - ClassDB::bind_method(D_METHOD("has_tiles_outside_texture"), &TileSetAtlasSource::has_tiles_outside_texture); - ClassDB::bind_method(D_METHOD("clear_tiles_outside_texture"), &TileSetAtlasSource::clear_tiles_outside_texture); ClassDB::bind_method(D_METHOD("get_tile_texture_region", "atlas_coords", "frame"), &TileSetAtlasSource::get_tile_texture_region, DEFVAL(0)); } @@ -3854,6 +3857,20 @@ void TileSetAtlasSource::_create_coords_mapping_cache(Vector2i p_atlas_coords) { } } +void TileSetAtlasSource::_clear_tiles_outside_texture() { + LocalVector<Vector2i> to_remove; + + for (const KeyValue<Vector2i, TileSetAtlasSource::TileAlternativesData> &E : tiles) { + if (!has_room_for_tile(E.key, E.value.size_in_atlas, E.value.animation_columns, E.value.animation_separation, E.value.animation_frames_durations.size(), E.key)) { + to_remove.push_back(E.key); + } + } + + for (unsigned int i = 0; i < to_remove.size(); i++) { + remove_tile(to_remove[i]); + } +} + /////////////////////////////// TileSetScenesCollectionSource ////////////////////////////////////// void TileSetScenesCollectionSource::_compute_next_alternative_id() { diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h index 716b66405f..351bdff89d 100644 --- a/scene/resources/tile_set.h +++ b/scene/resources/tile_set.h @@ -479,8 +479,10 @@ private: void _compute_next_alternative_id(const Vector2i p_atlas_coords); - void _create_coords_mapping_cache(Vector2i p_atlas_coords); void _clear_coords_mapping_cache(Vector2i p_atlas_coords); + void _create_coords_mapping_cache(Vector2i p_atlas_coords); + + void _clear_tiles_outside_texture(); protected: bool _set(const StringName &p_name, const Variant &p_value); @@ -534,7 +536,7 @@ public: virtual Vector2i get_tile_id(int p_index) const override; bool has_room_for_tile(Vector2i p_atlas_coords, Vector2i p_size, int p_animation_columns, Vector2i p_animation_separation, int p_frames_count, Vector2i p_ignored_tile = INVALID_ATLAS_COORDS) const; - + PackedVector2Array get_tiles_to_be_removed_on_change(Ref<Texture2D> p_texture, Vector2i p_margins, Vector2i p_separation, Vector2i p_texture_region_size); Vector2i get_tile_at_coords(Vector2i p_atlas_coords) const; // Animation. @@ -565,8 +567,6 @@ public: // Helpers. Vector2i get_atlas_grid_size() const; - bool has_tiles_outside_texture(); - void clear_tiles_outside_texture(); Rect2i get_tile_texture_region(Vector2i p_atlas_coords, int p_frame = 0) const; Vector2i get_tile_effective_texture_offset(Vector2i p_atlas_coords, int p_alternative_tile) const; |