diff options
Diffstat (limited to 'scene')
| -rw-r--r-- | scene/2d/tile_map.cpp | 12 | ||||
| -rw-r--r-- | scene/3d/bone_attachment_3d.cpp | 5 | ||||
| -rw-r--r-- | scene/3d/bone_attachment_3d.h | 5 | ||||
| -rw-r--r-- | scene/3d/lightmap_gi.cpp | 207 | ||||
| -rw-r--r-- | scene/3d/lightmap_gi.h | 13 | ||||
| -rw-r--r-- | scene/3d/multimesh_instance_3d.cpp | 20 | ||||
| -rw-r--r-- | scene/3d/multimesh_instance_3d.h | 2 | ||||
| -rw-r--r-- | scene/3d/reflection_probe.cpp | 5 | ||||
| -rw-r--r-- | scene/3d/voxel_gi.cpp | 25 | ||||
| -rw-r--r-- | scene/3d/voxelizer.cpp | 2 | ||||
| -rw-r--r-- | scene/gui/base_button.cpp | 2 | ||||
| -rw-r--r-- | scene/gui/graph_edit_arranger.cpp | 28 | ||||
| -rw-r--r-- | scene/gui/menu_bar.cpp | 5 | ||||
| -rw-r--r-- | scene/gui/popup_menu.cpp | 1 | ||||
| -rw-r--r-- | scene/gui/tab_bar.cpp | 13 | ||||
| -rw-r--r-- | scene/gui/tab_container.cpp | 26 | ||||
| -rw-r--r-- | scene/gui/tab_container.h | 2 | ||||
| -rw-r--r-- | scene/gui/text_edit.cpp | 8 | ||||
| -rw-r--r-- | scene/gui/tree.cpp | 2 | ||||
| -rw-r--r-- | scene/resources/bone_map.cpp | 4 | ||||
| -rw-r--r-- | scene/resources/mesh.cpp | 4 | ||||
| -rw-r--r-- | scene/resources/particle_process_material.cpp | 28 | ||||
| -rw-r--r-- | scene/resources/skeleton_modification_stack_2d.cpp | 4 |
23 files changed, 265 insertions, 158 deletions
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 6eca32fbb6..3b19cb5566 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -472,7 +472,13 @@ void TileMapLayer::_rendering_quadrants_update_cell(CellData &r_cell_data, SelfL TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); if (atlas_source && atlas_source->has_tile(r_cell_data.cell.get_atlas_coords()) && atlas_source->has_alternative_tile(r_cell_data.cell.get_atlas_coords(), r_cell_data.cell.alternative_tile)) { is_valid = true; - tile_y_sort_origin = atlas_source->get_tile_data(r_cell_data.cell.get_atlas_coords(), r_cell_data.cell.alternative_tile)->get_y_sort_origin(); + const TileData *tile_data; + if (r_cell_data.runtime_tile_data_cache) { + tile_data = r_cell_data.runtime_tile_data_cache; + } else { + tile_data = atlas_source->get_tile_data(r_cell_data.cell.get_atlas_coords(), r_cell_data.cell.alternative_tile); + } + tile_y_sort_origin = tile_data->get_y_sort_origin(); } } @@ -652,7 +658,7 @@ void TileMapLayer::_physics_update() { const Ref<TileSet> &tile_set = tile_map_node->get_tileset(); // Check if we should cleanup everything. - bool forced_cleanup = in_destructor || !enabled || !tile_map_node->is_inside_tree() || !tile_set.is_valid() || !tile_map_node->is_visible_in_tree(); + bool forced_cleanup = in_destructor || !enabled || !tile_map_node->is_inside_tree() || !tile_set.is_valid(); if (forced_cleanup) { // Clean everything. for (KeyValue<Vector2i, CellData> &kv : tile_map) { @@ -902,7 +908,7 @@ void TileMapLayer::_navigation_update() { NavigationServer2D *ns = NavigationServer2D::get_singleton(); // Check if we should cleanup everything. - bool forced_cleanup = in_destructor || !enabled || !navigation_enabled || !tile_map_node->is_inside_tree() || !tile_set.is_valid() || !tile_map_node->is_visible_in_tree(); + bool forced_cleanup = in_destructor || !enabled || !navigation_enabled || !tile_map_node->is_inside_tree() || !tile_set.is_valid(); // ----------- Layer level processing ----------- if (forced_cleanup) { diff --git a/scene/3d/bone_attachment_3d.cpp b/scene/3d/bone_attachment_3d.cpp index 3b30bbf8b6..60fb6f87c9 100644 --- a/scene/3d/bone_attachment_3d.cpp +++ b/scene/3d/bone_attachment_3d.cpp @@ -333,7 +333,7 @@ void BoneAttachment3D::on_bone_pose_update(int p_bone_index) { } } #ifdef TOOLS_ENABLED -void BoneAttachment3D::_notify_skeleton_bones_renamed(Node *p_base_scene, Skeleton3D *p_skeleton, Dictionary p_rename_map) { +void BoneAttachment3D::notify_skeleton_bones_renamed(Node *p_base_scene, Skeleton3D *p_skeleton, Dictionary p_rename_map) { const Skeleton3D *parent = nullptr; if (use_external_skeleton) { if (external_skeleton_node_cache.is_valid()) { @@ -370,9 +370,6 @@ void BoneAttachment3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_use_external_skeleton"), &BoneAttachment3D::get_use_external_skeleton); ClassDB::bind_method(D_METHOD("set_external_skeleton", "external_skeleton"), &BoneAttachment3D::set_external_skeleton); ClassDB::bind_method(D_METHOD("get_external_skeleton"), &BoneAttachment3D::get_external_skeleton); -#ifdef TOOLS_ENABLED - ClassDB::bind_method(D_METHOD("_notify_skeleton_bones_renamed"), &BoneAttachment3D::_notify_skeleton_bones_renamed); -#endif // TOOLS_ENABLED ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "bone_name"), "set_bone_name", "get_bone_name"); ADD_PROPERTY(PropertyInfo(Variant::INT, "bone_idx"), "set_bone_idx", "get_bone_idx"); diff --git a/scene/3d/bone_attachment_3d.h b/scene/3d/bone_attachment_3d.h index 327cbaa0ab..bfa3db476d 100644 --- a/scene/3d/bone_attachment_3d.h +++ b/scene/3d/bone_attachment_3d.h @@ -65,11 +65,12 @@ protected: void _notification(int p_what); static void _bind_methods(); + +public: #ifdef TOOLS_ENABLED - virtual void _notify_skeleton_bones_renamed(Node *p_base_scene, Skeleton3D *p_skeleton, Dictionary p_rename_map); + virtual void notify_skeleton_bones_renamed(Node *p_base_scene, Skeleton3D *p_skeleton, Dictionary p_rename_map); #endif // TOOLS_ENABLED -public: virtual PackedStringArray get_configuration_warnings() const override; void set_bone_name(const String &p_name); diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp index 5175363538..4ba039becd 100644 --- a/scene/3d/lightmap_gi.cpp +++ b/scene/3d/lightmap_gi.cpp @@ -97,11 +97,16 @@ Array LightmapGIData::_get_user_data() const { return ret; } -void LightmapGIData::_set_light_textures_data(const Array &p_data) { - ERR_FAIL_COND(p_data.is_empty()); +void LightmapGIData::set_lightmap_textures(const TypedArray<TextureLayered> &p_data) { + light_textures = p_data; + if (p_data.is_empty()) { + light_texture = Ref<TextureLayered>(); + _reset_lightmap_textures(); + return; + } if (p_data.size() == 1) { - set_light_texture(p_data[0]); + light_texture = p_data[0]; } else { Vector<Ref<Image>> images; for (int i = 0; i < p_data.size(); i++) { @@ -116,73 +121,13 @@ void LightmapGIData::_set_light_textures_data(const Array &p_data) { combined_texture.instantiate(); combined_texture->create_from_images(images); - set_light_texture(combined_texture); + light_texture = combined_texture; } + _reset_lightmap_textures(); } -Array LightmapGIData::_get_light_textures_data() const { - Array ret; - if (light_texture.is_null() || light_texture->get_layers() == 0) { - return ret; - } - - Vector<Ref<Image>> images; - for (int i = 0; i < light_texture->get_layers(); i++) { - images.push_back(light_texture->get_layer_data(i)); - } - - int slice_count = images.size(); - int slice_width = images[0]->get_width(); - int slice_height = images[0]->get_height(); - - int slices_per_texture = Image::MAX_HEIGHT / slice_height; - int texture_count = Math::ceil(slice_count / (float)slices_per_texture); - - ret.resize(texture_count); - - String base_name = get_path().get_basename(); - - int last_count = slice_count % slices_per_texture; - for (int i = 0; i < texture_count; i++) { - int texture_slice_count = (i == texture_count - 1 && last_count != 0) ? last_count : slices_per_texture; - - Ref<Image> texture_image = Image::create_empty(slice_width, slice_height * texture_slice_count, false, images[0]->get_format()); - - for (int j = 0; j < texture_slice_count; j++) { - texture_image->blit_rect(images[i * slices_per_texture + j], Rect2i(0, 0, slice_width, slice_height), Point2i(0, slice_height * j)); - } - - String texture_path = texture_count > 1 ? base_name + "_" + itos(i) + ".exr" : base_name + ".exr"; - - Ref<ConfigFile> config; - config.instantiate(); - - if (FileAccess::exists(texture_path + ".import")) { - config->load(texture_path + ".import"); - } - - config->set_value("remap", "importer", "2d_array_texture"); - config->set_value("remap", "type", "CompressedTexture2DArray"); - if (!config->has_section_key("params", "compress/mode")) { - // User may want another compression, so leave it be, but default to VRAM uncompressed. - config->set_value("params", "compress/mode", 3); - } - config->set_value("params", "compress/channel_pack", 1); - config->set_value("params", "mipmaps/generate", false); - config->set_value("params", "slices/horizontal", 1); - config->set_value("params", "slices/vertical", texture_slice_count); - - config->save(texture_path + ".import"); - - Error err = texture_image->save_exr(texture_path, false); - ERR_FAIL_COND_V(err, ret); - ResourceLoader::import(texture_path); - Ref<TextureLayered> t = ResourceLoader::load(texture_path); //if already loaded, it will be updated on refocus? - ERR_FAIL_COND_V(t.is_null(), ret); - ret[i] = t; - } - - return ret; +TypedArray<TextureLayered> LightmapGIData::get_lightmap_textures() const { + return light_textures; } RID LightmapGIData::get_rid() const { @@ -193,18 +138,13 @@ void LightmapGIData::clear() { users.clear(); } -void LightmapGIData::set_light_texture(const Ref<TextureLayered> &p_light_texture) { - light_texture = p_light_texture; +void LightmapGIData::_reset_lightmap_textures() { RS::get_singleton()->lightmap_set_textures(lightmap, light_texture.is_valid() ? light_texture->get_rid() : RID(), uses_spherical_harmonics); } -Ref<TextureLayered> LightmapGIData::get_light_texture() const { - return light_texture; -} - void LightmapGIData::set_uses_spherical_harmonics(bool p_enable) { uses_spherical_harmonics = p_enable; - RS::get_singleton()->lightmap_set_textures(lightmap, light_texture.is_valid() ? light_texture->get_rid() : RID(), uses_spherical_harmonics); + _reset_lightmap_textures(); } bool LightmapGIData::is_using_spherical_harmonics() const { @@ -282,15 +222,35 @@ Dictionary LightmapGIData::_get_probe_data() const { return d; } +#ifndef DISABLE_DEPRECATED +void LightmapGIData::set_light_texture(const Ref<TextureLayered> &p_light_texture) { + TypedArray<TextureLayered> arr; + arr.append(p_light_texture); + set_lightmap_textures(arr); +} + +Ref<TextureLayered> LightmapGIData::get_light_texture() const { + if (light_textures.is_empty()) { + return Ref<TextureLayered>(); + } + return light_textures.get(0); +} + +void LightmapGIData::_set_light_textures_data(const Array &p_data) { + set_lightmap_textures(p_data); +} + +Array LightmapGIData::_get_light_textures_data() const { + return Array(light_textures); +} +#endif + void LightmapGIData::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_user_data", "data"), &LightmapGIData::_set_user_data); ClassDB::bind_method(D_METHOD("_get_user_data"), &LightmapGIData::_get_user_data); - ClassDB::bind_method(D_METHOD("set_light_texture", "light_texture"), &LightmapGIData::set_light_texture); - ClassDB::bind_method(D_METHOD("get_light_texture"), &LightmapGIData::get_light_texture); - - ClassDB::bind_method(D_METHOD("_set_light_textures_data", "data"), &LightmapGIData::_set_light_textures_data); - ClassDB::bind_method(D_METHOD("_get_light_textures_data"), &LightmapGIData::_get_light_textures_data); + ClassDB::bind_method(D_METHOD("set_lightmap_textures", "light_textures"), &LightmapGIData::set_lightmap_textures); + ClassDB::bind_method(D_METHOD("get_lightmap_textures"), &LightmapGIData::get_lightmap_textures); ClassDB::bind_method(D_METHOD("set_uses_spherical_harmonics", "uses_spherical_harmonics"), &LightmapGIData::set_uses_spherical_harmonics); ClassDB::bind_method(D_METHOD("is_using_spherical_harmonics"), &LightmapGIData::is_using_spherical_harmonics); @@ -303,11 +263,21 @@ void LightmapGIData::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_probe_data", "data"), &LightmapGIData::_set_probe_data); ClassDB::bind_method(D_METHOD("_get_probe_data"), &LightmapGIData::_get_probe_data); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_texture", PROPERTY_HINT_RESOURCE_TYPE, "TextureLayered", PROPERTY_USAGE_EDITOR), "set_light_texture", "get_light_texture"); // property usage default but no save - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "light_textures", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_light_textures_data", "_get_light_textures_data"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "lightmap_textures", PROPERTY_HINT_ARRAY_TYPE, "TextureLayered", PROPERTY_USAGE_NO_EDITOR), "set_lightmap_textures", "get_lightmap_textures"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uses_spherical_harmonics", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_uses_spherical_harmonics", "is_using_spherical_harmonics"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "user_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_user_data", "_get_user_data"); ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "probe_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_probe_data", "_get_probe_data"); + +#ifndef DISABLE_DEPRECATED + ClassDB::bind_method(D_METHOD("set_light_texture", "light_texture"), &LightmapGIData::set_light_texture); + ClassDB::bind_method(D_METHOD("get_light_texture"), &LightmapGIData::get_light_texture); + + ClassDB::bind_method(D_METHOD("_set_light_textures_data", "data"), &LightmapGIData::_set_light_textures_data); + ClassDB::bind_method(D_METHOD("_get_light_textures_data"), &LightmapGIData::_get_light_textures_data); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_texture", PROPERTY_HINT_RESOURCE_TYPE, "TextureLayered", PROPERTY_USAGE_EDITOR), "set_light_texture", "get_light_texture"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "light_textures", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_light_textures_data", "_get_light_textures_data"); +#endif } LightmapGIData::LightmapGIData() { @@ -1099,6 +1069,68 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa return BAKE_ERROR_MESHES_INVALID; } + // POSTBAKE: Save Textures. + + TypedArray<TextureLayered> textures; + { + Vector<Ref<Image>> images; + images.resize(lightmapper->get_bake_texture_count()); + for (int i = 0; i < images.size(); i++) { + images.set(i, lightmapper->get_bake_texture(i)); + } + + int slice_count = images.size(); + int slice_width = images[0]->get_width(); + int slice_height = images[0]->get_height(); + + int slices_per_texture = Image::MAX_HEIGHT / slice_height; + int texture_count = Math::ceil(slice_count / (float)slices_per_texture); + + textures.resize(texture_count); + + String base_path = p_image_data_path.get_basename(); + + int last_count = slice_count % slices_per_texture; + for (int i = 0; i < texture_count; i++) { + int texture_slice_count = (i == texture_count - 1 && last_count != 0) ? last_count : slices_per_texture; + + Ref<Image> texture_image = Image::create_empty(slice_width, slice_height * texture_slice_count, false, images[0]->get_format()); + + for (int j = 0; j < texture_slice_count; j++) { + texture_image->blit_rect(images[i * slices_per_texture + j], Rect2i(0, 0, slice_width, slice_height), Point2i(0, slice_height * j)); + } + + String texture_path = texture_count > 1 ? base_path + "_" + itos(i) + ".exr" : base_path + ".exr"; + + Ref<ConfigFile> config; + config.instantiate(); + + if (FileAccess::exists(texture_path + ".import")) { + config->load(texture_path + ".import"); + } + + config->set_value("remap", "importer", "2d_array_texture"); + config->set_value("remap", "type", "CompressedTexture2DArray"); + if (!config->has_section_key("params", "compress/mode")) { + // User may want another compression, so leave it be, but default to VRAM uncompressed. + config->set_value("params", "compress/mode", 3); + } + config->set_value("params", "compress/channel_pack", 1); + config->set_value("params", "mipmaps/generate", false); + config->set_value("params", "slices/horizontal", 1); + config->set_value("params", "slices/vertical", texture_slice_count); + + config->save(texture_path + ".import"); + + Error err = texture_image->save_exr(texture_path, false); + ERR_FAIL_COND_V(err, BAKE_ERROR_CANT_CREATE_IMAGE); + ResourceLoader::import(texture_path); + Ref<TextureLayered> t = ResourceLoader::load(texture_path); // If already loaded, it will be updated on refocus? + ERR_FAIL_COND_V(t.is_null(), BAKE_ERROR_CANT_CREATE_IMAGE); + textures[i] = t; + } + } + /* POSTBAKE: Save Light Data */ Ref<LightmapGIData> gi_data; @@ -1110,18 +1142,7 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa gi_data.instantiate(); } - Ref<Texture2DArray> texture; - { - Vector<Ref<Image>> images; - for (int i = 0; i < lightmapper->get_bake_texture_count(); i++) { - images.push_back(lightmapper->get_bake_texture(i)); - } - - texture.instantiate(); - texture->create_from_images(images); - } - - gi_data->set_light_texture(texture); + gi_data->set_lightmap_textures(textures); gi_data->set_uses_spherical_harmonics(directional); for (int i = 0; i < lightmapper->get_bake_mesh_count(); i++) { diff --git a/scene/3d/lightmap_gi.h b/scene/3d/lightmap_gi.h index b65d7f8c78..fec0075693 100644 --- a/scene/3d/lightmap_gi.h +++ b/scene/3d/lightmap_gi.h @@ -44,6 +44,7 @@ class LightmapGIData : public Resource { RES_BASE_EXTENSION("lmbake") Ref<TextureLayered> light_texture; + TypedArray<TextureLayered> light_textures; bool uses_spherical_harmonics = false; bool interior = false; @@ -65,8 +66,8 @@ class LightmapGIData : public Resource { Array _get_user_data() const; void _set_probe_data(const Dictionary &p_data); Dictionary _get_probe_data() const; - void _set_light_textures_data(const Array &p_data); - Array _get_light_textures_data() const; + + void _reset_lightmap_textures(); protected: static void _bind_methods(); @@ -80,9 +81,14 @@ public: int get_user_lightmap_slice_index(int p_user) const; void clear_users(); +#ifndef DISABLE_DEPRECATED void set_light_texture(const Ref<TextureLayered> &p_light_texture); Ref<TextureLayered> get_light_texture() const; + void _set_light_textures_data(const Array &p_data); + Array _get_light_textures_data() const; +#endif + void set_uses_spherical_harmonics(bool p_enable); bool is_using_spherical_harmonics() const; @@ -98,6 +104,9 @@ public: void clear(); + void set_lightmap_textures(const TypedArray<TextureLayered> &p_data); + TypedArray<TextureLayered> get_lightmap_textures() const; + virtual RID get_rid() const override; LightmapGIData(); ~LightmapGIData(); diff --git a/scene/3d/multimesh_instance_3d.cpp b/scene/3d/multimesh_instance_3d.cpp index 2158005f5f..55d6e49e6c 100644 --- a/scene/3d/multimesh_instance_3d.cpp +++ b/scene/3d/multimesh_instance_3d.cpp @@ -49,6 +49,26 @@ Ref<MultiMesh> MultiMeshInstance3D::get_multimesh() const { return multimesh; } +Array MultiMeshInstance3D::get_meshes() const { + if (multimesh.is_null() || multimesh->get_mesh().is_null() || multimesh->get_transform_format() != MultiMesh::TransformFormat::TRANSFORM_3D) { + return Array(); + } + + int count = multimesh->get_visible_instance_count(); + if (count == -1) { + count = multimesh->get_instance_count(); + } + + Ref<Mesh> mesh = multimesh->get_mesh(); + + Array results; + for (int i = 0; i < count; i++) { + results.push_back(multimesh->get_instance_transform(i)); + results.push_back(mesh); + } + return results; +} + AABB MultiMeshInstance3D::get_aabb() const { if (multimesh.is_null()) { return AABB(); diff --git a/scene/3d/multimesh_instance_3d.h b/scene/3d/multimesh_instance_3d.h index cd18281b91..404f31d1e3 100644 --- a/scene/3d/multimesh_instance_3d.h +++ b/scene/3d/multimesh_instance_3d.h @@ -47,6 +47,8 @@ public: void set_multimesh(const Ref<MultiMesh> &p_multimesh); Ref<MultiMesh> get_multimesh() const; + Array get_meshes() const; + virtual AABB get_aabb() const override; MultiMeshInstance3D(); diff --git a/scene/3d/reflection_probe.cpp b/scene/3d/reflection_probe.cpp index e533f08861..2e34f6aad0 100644 --- a/scene/3d/reflection_probe.cpp +++ b/scene/3d/reflection_probe.cpp @@ -68,8 +68,9 @@ Color ReflectionProbe::get_ambient_color() const { } void ReflectionProbe::set_max_distance(float p_distance) { - max_distance = p_distance; - RS::get_singleton()->reflection_probe_set_max_distance(probe, p_distance); + max_distance = CLAMP(p_distance, 0.0, 262'144.0); + // Reflection rendering breaks if distance exceeds 262,144 units (due to floating-point precision with the near plane being 0.01). + RS::get_singleton()->reflection_probe_set_max_distance(probe, max_distance); } float ReflectionProbe::get_max_distance() const { diff --git a/scene/3d/voxel_gi.cpp b/scene/3d/voxel_gi.cpp index 43906b2586..8250083a9f 100644 --- a/scene/3d/voxel_gi.cpp +++ b/scene/3d/voxel_gi.cpp @@ -314,9 +314,21 @@ Ref<CameraAttributes> VoxelGI::get_camera_attributes() const { return camera_attributes; } +static bool is_node_voxel_bakeable(Node3D *p_node) { + if (!p_node->is_visible_in_tree()) { + return false; + } + + GeometryInstance3D *geometry = Object::cast_to<GeometryInstance3D>(p_node); + if (geometry != nullptr && geometry->get_gi_mode() != GeometryInstance3D::GI_MODE_STATIC) { + return false; + } + return true; +} + void VoxelGI::_find_meshes(Node *p_at_node, List<PlotMesh> &plot_meshes) { MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_at_node); - if (mi && mi->get_gi_mode() == GeometryInstance3D::GI_MODE_STATIC && mi->is_visible_in_tree()) { + if (mi && is_node_voxel_bakeable(mi)) { Ref<Mesh> mesh = mi->get_mesh(); if (mesh.is_valid()) { AABB aabb = mesh->get_aabb(); @@ -338,8 +350,15 @@ void VoxelGI::_find_meshes(Node *p_at_node, List<PlotMesh> &plot_meshes) { Node3D *s = Object::cast_to<Node3D>(p_at_node); if (s) { - if (s->is_visible_in_tree()) { - Array meshes = p_at_node->call("get_meshes"); + if (is_node_voxel_bakeable(s)) { + Array meshes; + MultiMeshInstance3D *multi_mesh = Object::cast_to<MultiMeshInstance3D>(p_at_node); + if (multi_mesh) { + meshes = multi_mesh->get_meshes(); + } else { + meshes = p_at_node->call("get_meshes"); + } + for (int i = 0; i < meshes.size(); i += 2) { Transform3D mxf = meshes[i]; Ref<Mesh> mesh = meshes[i + 1]; diff --git a/scene/3d/voxelizer.cpp b/scene/3d/voxelizer.cpp index fec4bc2b05..99392e9ba0 100644 --- a/scene/3d/voxelizer.cpp +++ b/scene/3d/voxelizer.cpp @@ -383,6 +383,8 @@ Voxelizer::MaterialCache Voxelizer::_get_material_cache(Ref<Material> p_material } void Voxelizer::plot_mesh(const Transform3D &p_xform, Ref<Mesh> &p_mesh, const Vector<Ref<Material>> &p_materials, const Ref<Material> &p_override_material) { + ERR_FAIL_COND_MSG(!p_xform.is_finite(), "Invalid mesh bake transform."); + for (int i = 0; i < p_mesh->get_surface_count(); i++) { if (p_mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) { continue; //only triangles diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index f57afb66b3..66b14dc967 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -380,7 +380,7 @@ void BaseButton::shortcut_input(const Ref<InputEvent> &p_event) { queue_redraw(); accept_event(); - if (shortcut_feedback) { + if (shortcut_feedback && is_inside_tree()) { if (shortcut_feedback_timer == nullptr) { shortcut_feedback_timer = memnew(Timer); shortcut_feedback_timer->set_one_shot(true); diff --git a/scene/gui/graph_edit_arranger.cpp b/scene/gui/graph_edit_arranger.cpp index 1dc778254b..3f2007f7e0 100644 --- a/scene/gui/graph_edit_arranger.cpp +++ b/scene/gui/graph_edit_arranger.cpp @@ -65,6 +65,9 @@ void GraphEditArranger::arrange_nodes() { float gap_v = 100.0f; float gap_h = 100.0f; + List<GraphEdit::Connection> connection_list; + graph_edit->get_connection_list(&connection_list); + for (int i = graph_edit->get_child_count() - 1; i >= 0; i--) { GraphNode *graph_element = Object::cast_to<GraphNode>(graph_edit->get_child(i)); if (!graph_element) { @@ -74,8 +77,6 @@ void GraphEditArranger::arrange_nodes() { if (graph_element->is_selected() || arrange_entire_graph) { selected_nodes.insert(graph_element->get_name()); HashSet<StringName> s; - List<GraphEdit::Connection> connection_list; - graph_edit->get_connection_list(&connection_list); for (List<GraphEdit::Connection>::Element *E = connection_list.front(); E; E = E->next()) { GraphNode *p_from = Object::cast_to<GraphNode>(node_names[E->get().from_node]); if (E->get().to_node == graph_element->get_name() && (p_from->is_selected() || arrange_entire_graph) && E->get().to_node != E->get().from_node) { @@ -85,12 +86,6 @@ void GraphEditArranger::arrange_nodes() { String s_connection = String(p_from->get_name()) + " " + String(E->get().to_node); StringName _connection(s_connection); Pair<int, int> ports(E->get().from_port, E->get().to_port); - if (port_info.has(_connection)) { - Pair<int, int> p_ports = port_info[_connection]; - if (p_ports.first < ports.first) { - ports = p_ports; - } - } port_info.insert(_connection, ports); } } @@ -216,13 +211,14 @@ int GraphEditArranger::_set_operations(SET_OPERATIONS p_operation, HashSet<Strin return 1; } break; case GraphEditArranger::DIFFERENCE: { - for (HashSet<StringName>::Iterator E = r_u.begin(); E;) { - HashSet<StringName>::Iterator N = E; - ++N; - if (r_v.has(*E)) { - r_u.remove(E); + Vector<StringName> common; + for (const StringName &E : r_u) { + if (r_v.has(E)) { + common.append(E); } - E = N; + } + for (const StringName &E : common) { + r_u.erase(E); } return r_u.size(); } break; @@ -260,9 +256,7 @@ HashMap<int, Vector<StringName>> GraphEditArranger::_layering(const HashSet<Stri selected = true; t.append_array(l[current_layer]); l.insert(current_layer, t); - HashSet<StringName> V; - V.insert(E); - _set_operations(GraphEditArranger::UNION, u, V); + u.insert(E); } } if (!selected) { diff --git a/scene/gui/menu_bar.cpp b/scene/gui/menu_bar.cpp index 371d6c69af..7418ba7333 100644 --- a/scene/gui/menu_bar.cpp +++ b/scene/gui/menu_bar.cpp @@ -561,6 +561,7 @@ void MenuBar::add_child_notify(Node *p_child) { int index = DisplayServer::get_singleton()->global_menu_add_submenu_item("_main", atr(menu.name), submenu_name, _find_global_start_index() + menu_cache.size() - 1); DisplayServer::get_singleton()->global_menu_set_item_tag("_main", index, global_menu_name + "#" + itos(menu_cache.size() - 1)); } + update_minimum_size(); } void MenuBar::move_child_notify(Node *p_child) { @@ -621,6 +622,8 @@ void MenuBar::remove_child_notify(Node *p_child) { p_child->disconnect("renamed", callable_mp(this, &MenuBar::_refresh_menu_names)); p_child->disconnect("about_to_popup", callable_mp(this, &MenuBar::_popup_visibility_changed)); p_child->disconnect("popup_hide", callable_mp(this, &MenuBar::_popup_visibility_changed)); + + update_minimum_size(); } void MenuBar::_bind_methods() { @@ -808,6 +811,7 @@ void MenuBar::set_menu_title(int p_menu, const String &p_title) { if (!global_menu_name.is_empty()) { DisplayServer::get_singleton()->global_menu_set_item_text("_main", _find_global_start_index() + p_menu, atr(menu_cache[p_menu].name)); } + update_minimum_size(); } String MenuBar::get_menu_title(int p_menu) const { @@ -849,6 +853,7 @@ void MenuBar::set_menu_hidden(int p_menu, bool p_hidden) { if (!global_menu_name.is_empty()) { DisplayServer::get_singleton()->global_menu_set_item_hidden("_main", _find_global_start_index() + p_menu, p_hidden); } + update_minimum_size(); } bool MenuBar::is_menu_hidden(int p_menu) const { diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index dfaf7d88b7..ec9e2cacb4 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -2186,6 +2186,7 @@ void PopupMenu::scroll_to_item(int p_idx) { } bool PopupMenu::activate_item_by_event(const Ref<InputEvent> &p_event, bool p_for_global_only) { + ERR_FAIL_COND_V(p_event.is_null(), false); Key code = Key::NONE; Ref<InputEventKey> k = p_event; diff --git a/scene/gui/tab_bar.cpp b/scene/gui/tab_bar.cpp index bc776facaf..777ca96cc4 100644 --- a/scene/gui/tab_bar.cpp +++ b/scene/gui/tab_bar.cpp @@ -334,6 +334,12 @@ void TabBar::_shape(int p_tab) { void TabBar::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + if (scroll_to_selected) { + ensure_tab_visible(current); + } + } break; + case NOTIFICATION_INTERNAL_PROCESS: { Input *input = Input::get_singleton(); @@ -1762,7 +1768,10 @@ void TabBar::_bind_methods() { ADD_SIGNAL(MethodInfo("tab_hovered", PropertyInfo(Variant::INT, "tab"))); ADD_SIGNAL(MethodInfo("active_tab_rearranged", PropertyInfo(Variant::INT, "idx_to"))); - ADD_PROPERTY(PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE, "-1,4096,1", PROPERTY_USAGE_EDITOR), "set_current_tab", "get_current_tab"); + // "current_tab" property must come after "tab_count", otherwise the property isn't loaded correctly. + ADD_ARRAY_COUNT("Tabs", "tab_count", "set_tab_count", "get_tab_count", "tab_"); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE, "-1,4096,1"), "set_current_tab", "get_current_tab"); ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_tab_alignment", "get_tab_alignment"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_tabs"), "set_clip_tabs", "get_clip_tabs"); ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_close_display_policy", PROPERTY_HINT_ENUM, "Show Never,Show Active Only,Show Always"), "set_tab_close_display_policy", "get_tab_close_display_policy"); @@ -1773,8 +1782,6 @@ void TabBar::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_to_selected"), "set_scroll_to_selected", "get_scroll_to_selected"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "select_with_rmb"), "set_select_with_rmb", "get_select_with_rmb"); - ADD_ARRAY_COUNT("Tabs", "tab_count", "set_tab_count", "get_tab_count", "tab_"); - BIND_ENUM_CONSTANT(ALIGNMENT_LEFT); BIND_ENUM_CONSTANT(ALIGNMENT_CENTER); BIND_ENUM_CONSTANT(ALIGNMENT_RIGHT); diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index c21a9d14cb..aa9400847f 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -143,6 +143,13 @@ void TabContainer::_notification(int p_what) { } } break; + case NOTIFICATION_POST_ENTER_TREE: { + if (setup_current_tab >= 0) { + set_current_tab(setup_current_tab); + setup_current_tab = -1; + } + } break; + case NOTIFICATION_READY: case NOTIFICATION_RESIZED: { _update_margins(); @@ -330,14 +337,23 @@ Vector<Control *> TabContainer::_get_tab_controls() const { } Variant TabContainer::_get_drag_data_fw(const Point2 &p_point, Control *p_from_control) { + if (!drag_to_rearrange_enabled) { + return Variant(); + } return tab_bar->_handle_get_drag_data("tab_container_tab", p_point); } bool TabContainer::_can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from_control) const { + if (!drag_to_rearrange_enabled) { + return false; + } return tab_bar->_handle_can_drop_data("tab_container_tab", p_point, p_data); } void TabContainer::_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from_control) { + if (!drag_to_rearrange_enabled) { + return; + } return tab_bar->_handle_drop_data("tab_container_tab", p_point, p_data, callable_mp(this, &TabContainer::_drag_move_tab), callable_mp(this, &TabContainer::_drag_move_tab_from)); } @@ -519,6 +535,10 @@ int TabContainer::get_tab_count() const { } void TabContainer::set_current_tab(int p_current) { + if (!is_inside_tree()) { + setup_current_tab = p_current; + return; + } tab_bar->set_current_tab(p_current); } @@ -815,11 +835,11 @@ Popup *TabContainer::get_popup() const { } void TabContainer::set_drag_to_rearrange_enabled(bool p_enabled) { - tab_bar->set_drag_to_rearrange_enabled(p_enabled); + drag_to_rearrange_enabled = p_enabled; } bool TabContainer::get_drag_to_rearrange_enabled() const { - return tab_bar->get_drag_to_rearrange_enabled(); + return drag_to_rearrange_enabled; } void TabContainer::set_tabs_rearrange_group(int p_group_id) { @@ -903,7 +923,7 @@ void TabContainer::_bind_methods() { ADD_SIGNAL(MethodInfo("pre_popup_pressed")); ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_tab_alignment", "get_tab_alignment"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE, "-1,4096,1", PROPERTY_USAGE_EDITOR), "set_current_tab", "get_current_tab"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE, "-1,4096,1"), "set_current_tab", "get_current_tab"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_tabs"), "set_clip_tabs", "get_clip_tabs"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tabs_visible"), "set_tabs_visible", "are_tabs_visible"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "all_tabs_in_front"), "set_all_tabs_in_front", "is_all_tabs_in_front"); diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h index 5750c6b82e..450143cd0c 100644 --- a/scene/gui/tab_container.h +++ b/scene/gui/tab_container.h @@ -46,6 +46,8 @@ class TabContainer : public Container { bool use_hidden_tabs_for_min_size = false; bool theme_changing = false; Vector<Control *> children_removing; + bool drag_to_rearrange_enabled = false; + int setup_current_tab = -1; struct ThemeCache { int side_margin = 0; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 479480011c..86e726d9da 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -2948,6 +2948,8 @@ void TextEdit::_update_placeholder() { return; // Not in tree? } + const String placeholder_translated = atr(placeholder_text); + // Placeholder is generally smaller then text documents, and updates less so this should be fast enough for now. placeholder_data_buf->clear(); placeholder_data_buf->set_width(text.get_width()); @@ -2958,9 +2960,9 @@ void TextEdit::_update_placeholder() { placeholder_data_buf->set_direction((TextServer::Direction)text_direction); } placeholder_data_buf->set_preserve_control(draw_control_chars); - placeholder_data_buf->add_string(placeholder_text, theme_cache.font, theme_cache.font_size, language); + placeholder_data_buf->add_string(placeholder_translated, theme_cache.font, theme_cache.font_size, language); - placeholder_bidi_override = structured_text_parser(st_parser, st_args, placeholder_text); + placeholder_bidi_override = structured_text_parser(st_parser, st_args, placeholder_translated); if (placeholder_bidi_override.is_empty()) { TS->shaped_text_set_bidi_override(placeholder_data_buf->get_rid(), placeholder_bidi_override); } @@ -2985,7 +2987,7 @@ void TextEdit::_update_placeholder() { placeholder_wraped_rows.clear(); for (int i = 0; i <= wrap_amount; i++) { Vector2i line_range = placeholder_data_buf->get_line_range(i); - placeholder_wraped_rows.push_back(placeholder_text.substr(line_range.x, line_range.y - line_range.x)); + placeholder_wraped_rows.push_back(placeholder_translated.substr(line_range.x, line_range.y - line_range.x)); } } diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 2d3166270b..a4c239cf53 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -2050,7 +2050,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 int text_width = item_width - theme_cache.inner_item_margin_left - theme_cache.inner_item_margin_right; if (p_item->cells[i].icon.is_valid()) { - text_width -= p_item->cells[i].get_icon_size().x + theme_cache.h_separation; + text_width -= _get_cell_icon_size(p_item->cells[i]).x + theme_cache.h_separation; } p_item->cells.write[i].text_buf->set_width(text_width); diff --git a/scene/resources/bone_map.cpp b/scene/resources/bone_map.cpp index 759d189bfa..5363b8ec79 100644 --- a/scene/resources/bone_map.cpp +++ b/scene/resources/bone_map.cpp @@ -37,7 +37,7 @@ bool BoneMap::_set(const StringName &p_path, const Variant &p_value) { set_skeleton_bone_name(which, p_value); return true; } - return true; + return false; } bool BoneMap::_get(const StringName &p_path, Variant &r_ret) const { @@ -47,7 +47,7 @@ bool BoneMap::_get(const StringName &p_path, Variant &r_ret) const { r_ret = get_skeleton_bone_name(which); return true; } - return true; + return false; } void BoneMap::_get_property_list(List<PropertyInfo> *p_list) const { diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index 25a65b5cc4..b122189558 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -1019,7 +1019,7 @@ void _fix_array_compatibility(const Vector<uint8_t> &p_src, uint64_t p_old_forma uint32_t dst_offsets[Mesh::ARRAY_MAX]; RenderingServer::get_singleton()->mesh_surface_make_offsets_from_format(p_new_format & (~RS::ARRAY_FORMAT_INDEX), p_elements, 0, dst_offsets, dst_vertex_stride, dst_normal_tangent_stride, dst_attribute_stride, dst_skin_stride); - vertex_data.resize(dst_vertex_stride * p_elements); + vertex_data.resize((dst_vertex_stride + dst_normal_tangent_stride) * p_elements); attribute_data.resize(dst_attribute_stride * p_elements); skin_data.resize(dst_skin_stride * p_elements); @@ -1712,7 +1712,7 @@ bool ArrayMesh::_get(const StringName &p_name, Variant &r_ret) const { return true; } - return true; + return false; } void ArrayMesh::reset_state() { diff --git a/scene/resources/particle_process_material.cpp b/scene/resources/particle_process_material.cpp index 9ceddbc7b1..7e42cf3d63 100644 --- a/scene/resources/particle_process_material.cpp +++ b/scene/resources/particle_process_material.cpp @@ -531,10 +531,10 @@ void ParticleProcessMaterial::_update_shader() { code += "\n"; code += "void calculate_initial_physical_params(inout PhysicalParameters params, inout uint alt_seed){\n"; - code += " params.linear_accel = mix(linear_accel_min, linear_accel_min ,rand_from_seed(alt_seed));\n"; - code += " params.radial_accel = mix(radial_accel_min, radial_accel_min,rand_from_seed(alt_seed));\n"; - code += " params.tangent_accel = mix(tangent_accel_min, tangent_accel_max,rand_from_seed(alt_seed));\n"; - code += " params.damping = mix(damping_min, damping_max,rand_from_seed(alt_seed));\n"; + code += " params.linear_accel = mix(linear_accel_min, linear_accel_max, rand_from_seed(alt_seed));\n"; + code += " params.radial_accel = mix(radial_accel_min, radial_accel_max, rand_from_seed(alt_seed));\n"; + code += " params.tangent_accel = mix(tangent_accel_min, tangent_accel_max, rand_from_seed(alt_seed));\n"; + code += " params.damping = mix(damping_min, damping_max, rand_from_seed(alt_seed));\n"; code += "}\n"; code += "\n"; code += "void calculate_initial_dynamics_params(inout DynamicsParameters params,inout uint alt_seed){\n"; @@ -985,10 +985,6 @@ void ParticleProcessMaterial::_update_shader() { code += " VELOCITY = mix(VELOCITY,vec3(0.0),clamp(collision_friction, 0.0, 1.0));\n"; code += " } else {\n"; code += " VELOCITY = vec3(0.0);\n"; - // If turbulence is enabled, set the noise direction to up so the turbulence color is "neutral" - if (turbulence_enabled) { - code += " noise_direction = vec3(1.0, 0.0, 0.0);\n"; - } code += " }\n"; code += " }\n"; } else if (collision_mode == COLLISION_HIDE_ON_CONTACT) { @@ -1007,14 +1003,16 @@ void ParticleProcessMaterial::_update_shader() { } code += " \n"; code += " vec3 noise_direction = get_noise_direction(TRANSFORM[3].xyz);\n"; - // The following snippet causes massive performance hit. We don't need it as long as collision is disabled. - // Refer to GH-83744 for more info. - if (collision_mode != COLLISION_DISABLED) { + + // Godot detects when the COLLIDED keyword is used. If it's used anywhere in the shader then Godot will generate the screen space SDF for collisions. + // We don't need it as long as collision is disabled. Refer to GH-83744 for more info. + if (collision_mode == COLLISION_RIGID) { code += " if (!COLLIDED) {\n"; - code += " \n"; - code += " float vel_mag = length(final_velocity);\n"; - code += " float vel_infl = clamp(dynamic_params.turb_influence * turbulence_influence, 0.0,1.0);\n"; - code += " final_velocity = mix(final_velocity, normalize(noise_direction) * vel_mag * (1.0 + (1.0 - vel_infl) * 0.2), vel_infl);\n"; + } + code += " float vel_mag = length(final_velocity);\n"; + code += " float vel_infl = clamp(dynamic_params.turb_influence * turbulence_influence, 0.0,1.0);\n"; + code += " final_velocity = mix(final_velocity, normalize(noise_direction) * vel_mag * (1.0 + (1.0 - vel_infl) * 0.2), vel_infl);\n"; + if (collision_mode == COLLISION_RIGID) { code += " }\n"; } } diff --git a/scene/resources/skeleton_modification_stack_2d.cpp b/scene/resources/skeleton_modification_stack_2d.cpp index 71ddbc0898..5703185374 100644 --- a/scene/resources/skeleton_modification_stack_2d.cpp +++ b/scene/resources/skeleton_modification_stack_2d.cpp @@ -49,7 +49,7 @@ bool SkeletonModificationStack2D::_set(const StringName &p_path, const Variant & set_modification(mod_idx, p_value); return true; } - return true; + return false; } bool SkeletonModificationStack2D::_get(const StringName &p_path, Variant &r_ret) const { @@ -60,7 +60,7 @@ bool SkeletonModificationStack2D::_get(const StringName &p_path, Variant &r_ret) r_ret = get_modification(mod_idx); return true; } - return true; + return false; } void SkeletonModificationStack2D::setup() { |
