diff options
Diffstat (limited to 'scene/resources')
61 files changed, 1313 insertions, 832 deletions
diff --git a/scene/resources/2d/SCsub b/scene/resources/2d/SCsub index fdf20e0bde..408aa3cf7e 100644 --- a/scene/resources/2d/SCsub +++ b/scene/resources/2d/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/scene/resources/2d/navigation_mesh_source_geometry_data_2d.cpp b/scene/resources/2d/navigation_mesh_source_geometry_data_2d.cpp index e3f14539a8..07e9caa713 100644 --- a/scene/resources/2d/navigation_mesh_source_geometry_data_2d.cpp +++ b/scene/resources/2d/navigation_mesh_source_geometry_data_2d.cpp @@ -43,7 +43,7 @@ void NavigationMeshSourceGeometryData2D::clear() { bool NavigationMeshSourceGeometryData2D::has_data() { RWLockRead read_lock(geometry_rwlock); return traversable_outlines.size(); -}; +} void NavigationMeshSourceGeometryData2D::clear_projected_obstructions() { RWLockWrite write_lock(geometry_rwlock); diff --git a/scene/resources/2d/navigation_mesh_source_geometry_data_2d.h b/scene/resources/2d/navigation_mesh_source_geometry_data_2d.h index b29c106fb5..2812925770 100644 --- a/scene/resources/2d/navigation_mesh_source_geometry_data_2d.h +++ b/scene/resources/2d/navigation_mesh_source_geometry_data_2d.h @@ -36,6 +36,8 @@ #include "scene/resources/2d/navigation_polygon.h" class NavigationMeshSourceGeometryData2D : public Resource { + friend class NavMeshGenerator2D; + GDCLASS(NavigationMeshSourceGeometryData2D, Resource); RWLock geometry_rwlock; diff --git a/scene/resources/2d/navigation_polygon.cpp b/scene/resources/2d/navigation_polygon.cpp index 3dfa906e3b..37240e8038 100644 --- a/scene/resources/2d/navigation_polygon.cpp +++ b/scene/resources/2d/navigation_polygon.cpp @@ -36,7 +36,7 @@ #include "thirdparty/misc/polypartition.h" -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED Rect2 NavigationPolygon::_edit_get_rect() const { RWLockRead read_lock(rwlock); if (rect_cache_dirty) { @@ -79,7 +79,7 @@ bool NavigationPolygon::_edit_is_selected_on_click(const Point2 &p_point, double } return false; } -#endif +#endif // DEBUG_ENABLED void NavigationPolygon::set_vertices(const Vector<Vector2> &p_vertices) { RWLockWrite write_lock(rwlock); diff --git a/scene/resources/2d/navigation_polygon.h b/scene/resources/2d/navigation_polygon.h index ed2c606c55..59e5eeed68 100644 --- a/scene/resources/2d/navigation_polygon.h +++ b/scene/resources/2d/navigation_polygon.h @@ -68,10 +68,11 @@ protected: TypedArray<Vector<Vector2>> _get_outlines() const; public: -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED Rect2 _edit_get_rect() const; bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; -#endif +#endif // DEBUG_ENABLED + enum SamplePartitionType { SAMPLE_PARTITION_CONVEX_PARTITION = 0, SAMPLE_PARTITION_TRIANGULATE, diff --git a/scene/resources/2d/skeleton/skeleton_modification_stack_2d.h b/scene/resources/2d/skeleton/skeleton_modification_stack_2d.h index 0732153997..d1e50cb702 100644 --- a/scene/resources/2d/skeleton/skeleton_modification_stack_2d.h +++ b/scene/resources/2d/skeleton/skeleton_modification_stack_2d.h @@ -64,7 +64,7 @@ public: execution_mode_physics_process }; - Vector<Ref<SkeletonModification2D>> modifications = Vector<Ref<SkeletonModification2D>>(); + Vector<Ref<SkeletonModification2D>> modifications; void setup(); void execute(float p_delta, int p_execution_mode); diff --git a/scene/resources/2d/tile_set.cpp b/scene/resources/2d/tile_set.cpp index 229e18be23..5ecfc32622 100644 --- a/scene/resources/2d/tile_set.cpp +++ b/scene/resources/2d/tile_set.cpp @@ -174,13 +174,13 @@ void TileMapPattern::set_size(const Size2i &p_size) { bool TileMapPattern::is_empty() const { return pattern.is_empty(); -}; +} void TileMapPattern::clear() { size = Size2i(); pattern.clear(); emit_changed(); -}; +} bool TileMapPattern::_set(const StringName &p_name, const Variant &p_value) { if (p_name == "tile_data") { @@ -571,11 +571,11 @@ void TileSet::set_uv_clipping(bool p_uv_clipping) { bool TileSet::is_uv_clipping() const { return uv_clipping; -}; +} int TileSet::get_occlusion_layers_count() const { return occlusion_layers.size(); -}; +} void TileSet::add_occlusion_layer(int p_index) { if (p_index < 0) { @@ -699,6 +699,17 @@ uint32_t TileSet::get_physics_layer_collision_mask(int p_layer_index) const { return physics_layers[p_layer_index].collision_mask; } +void TileSet::set_physics_layer_collision_priority(int p_layer_index, real_t p_priority) { + ERR_FAIL_INDEX(p_layer_index, physics_layers.size()); + physics_layers.write[p_layer_index].collision_priority = p_priority; + emit_changed(); +} + +real_t TileSet::get_physics_layer_collision_priority(int p_layer_index) const { + ERR_FAIL_INDEX_V(p_layer_index, physics_layers.size(), 0); + return physics_layers[p_layer_index].collision_priority; +} + void TileSet::set_physics_layer_physics_material(int p_layer_index, Ref<PhysicsMaterial> p_physics_material) { ERR_FAIL_INDEX(p_layer_index, physics_layers.size()); physics_layers.write[p_layer_index].physics_material = p_physics_material; @@ -3691,7 +3702,7 @@ Array TileSet::compatibility_tilemap_map(int p_tile_id, Vector2i p_coords, bool return cannot_convert_array; break; } -}; +} #endif // DISABLE_DEPRECATED @@ -3900,6 +3911,13 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) { } set_physics_layer_collision_mask(index, p_value); return true; + } else if (components[1] == "collision_priority") { + ERR_FAIL_COND_V(p_value.get_type() != Variant::FLOAT, false); + while (index >= physics_layers.size()) { + add_physics_layer(); + } + set_physics_layer_collision_priority(index, p_value); + return true; } else if (components[1] == "physics_material") { Ref<PhysicsMaterial> physics_material = p_value; while (index >= physics_layers.size()) { @@ -4051,6 +4069,9 @@ bool TileSet::_get(const StringName &p_name, Variant &r_ret) const { } else if (components[1] == "collision_mask") { r_ret = get_physics_layer_collision_mask(index); return true; + } else if (components[1] == "collision_priority") { + r_ret = get_physics_layer_collision_priority(index); + return true; } else if (components[1] == "physics_material") { r_ret = get_physics_layer_physics_material(index); return true; @@ -4176,6 +4197,13 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { } p_list->push_back(property_info); + // physics_layer_%d/collision_priority + property_info = PropertyInfo(Variant::FLOAT, vformat("physics_layer_%d/collision_priority", i)); + if (physics_layers[i].collision_priority == 1.0) { + property_info.usage ^= PROPERTY_USAGE_STORAGE; + } + p_list->push_back(property_info); + // physics_layer_%d/physics_material property_info = PropertyInfo(Variant::OBJECT, vformat("physics_layer_%d/physics_material", i), PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"); if (!physics_layers[i].physics_material.is_valid()) { @@ -4220,10 +4248,10 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { // Tile Proxies. // Note: proxies need to be set after sources are set. - p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Tile Proxies", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); - p_list->push_back(PropertyInfo(Variant::ARRAY, PNAME("tile_proxies/source_level"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); - p_list->push_back(PropertyInfo(Variant::ARRAY, PNAME("tile_proxies/coords_level"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); - p_list->push_back(PropertyInfo(Variant::ARRAY, PNAME("tile_proxies/alternative_level"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::NIL, "Tile Proxies", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/source_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/coords_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/alternative_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); // Patterns. for (unsigned int pattern_index = 0; pattern_index < patterns.size(); pattern_index++) { @@ -4287,6 +4315,8 @@ void TileSet::_bind_methods() { ClassDB::bind_method(D_METHOD("get_physics_layer_collision_layer", "layer_index"), &TileSet::get_physics_layer_collision_layer); ClassDB::bind_method(D_METHOD("set_physics_layer_collision_mask", "layer_index", "mask"), &TileSet::set_physics_layer_collision_mask); ClassDB::bind_method(D_METHOD("get_physics_layer_collision_mask", "layer_index"), &TileSet::get_physics_layer_collision_mask); + ClassDB::bind_method(D_METHOD("set_physics_layer_collision_priority", "layer_index", "priority"), &TileSet::set_physics_layer_collision_priority); + ClassDB::bind_method(D_METHOD("get_physics_layer_collision_priority", "layer_index"), &TileSet::get_physics_layer_collision_priority); ClassDB::bind_method(D_METHOD("set_physics_layer_physics_material", "layer_index", "physics_material"), &TileSet::set_physics_layer_physics_material); ClassDB::bind_method(D_METHOD("get_physics_layer_physics_material", "layer_index"), &TileSet::get_physics_layer_physics_material); @@ -4432,7 +4462,7 @@ TileSet *TileSetSource::get_tile_set() const { void TileSetSource::reset_state() { tile_set = nullptr; -}; +} void TileSetSource::_bind_methods() { // Base tiles @@ -4931,10 +4961,13 @@ void TileSetAtlasSource::_get_property_list(List<PropertyInfo> *p_list) const { } for (const KeyValue<int, TileData *> &E_alternative : E_tile.value.alternatives) { + const String formatted_key = itos(E_alternative.key); + // Add a dummy property to show the alternative exists. - tile_property_list.push_back(PropertyInfo(Variant::INT, vformat("%d", E_alternative.key), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + tile_property_list.push_back(PropertyInfo(Variant::INT, formatted_key, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); // Get the alternative tile's properties and append them to the list of properties. + const String alternative_property_info_prefix = formatted_key + '/'; List<PropertyInfo> alternative_property_list; E_alternative.value->get_property_list(&alternative_property_list); for (PropertyInfo &alternative_property_info : alternative_property_list) { @@ -4943,14 +4976,15 @@ void TileSetAtlasSource::_get_property_list(List<PropertyInfo> *p_list) const { if (default_value.get_type() != Variant::NIL && bool(Variant::evaluate(Variant::OP_EQUAL, value, default_value))) { alternative_property_info.usage ^= PROPERTY_USAGE_STORAGE; } - alternative_property_info.name = vformat("%s/%s", vformat("%d", E_alternative.key), alternative_property_info.name); + alternative_property_info.name = alternative_property_info_prefix + alternative_property_info.name; tile_property_list.push_back(alternative_property_info); } } // Add all alternative. + const String property_info_prefix = vformat("%d:%d/", E_tile.key.x, E_tile.key.y); for (PropertyInfo &tile_property_info : tile_property_list) { - tile_property_info.name = vformat("%s/%s", vformat("%d:%d", E_tile.key.x, E_tile.key.y), tile_property_info.name); + tile_property_info.name = property_info_prefix + tile_property_info.name; p_list->push_back(tile_property_info); } } @@ -6480,9 +6514,9 @@ int TileData::get_terrain_set() const { } void TileData::set_terrain(int p_terrain) { - ERR_FAIL_COND(terrain_set < 0); ERR_FAIL_COND(p_terrain < -1); - if (tile_set) { + ERR_FAIL_COND(terrain_set < 0 && p_terrain != -1); + if (tile_set && terrain_set >= 0) { ERR_FAIL_COND(p_terrain >= tile_set->get_terrains_count(terrain_set)); } terrain = p_terrain; @@ -6495,9 +6529,9 @@ int TileData::get_terrain() const { void TileData::set_terrain_peering_bit(TileSet::CellNeighbor p_peering_bit, int p_terrain_index) { ERR_FAIL_INDEX(p_peering_bit, TileSet::CellNeighbor::CELL_NEIGHBOR_MAX); - ERR_FAIL_COND(terrain_set < 0); ERR_FAIL_COND(p_terrain_index < -1); - if (tile_set) { + ERR_FAIL_COND(terrain_set < 0 && p_terrain_index != -1); + if (tile_set && terrain_set >= 0) { ERR_FAIL_COND(p_terrain_index >= tile_set->get_terrains_count(terrain_set)); ERR_FAIL_COND(!is_valid_terrain_peering_bit(p_peering_bit)); } diff --git a/scene/resources/2d/tile_set.h b/scene/resources/2d/tile_set.h index 15e1a16359..6d3ccd1d2d 100644 --- a/scene/resources/2d/tile_set.h +++ b/scene/resources/2d/tile_set.h @@ -278,7 +278,7 @@ public: bool operator==(const TerrainsPattern &p_terrains_pattern) const; bool operator!=(const TerrainsPattern &p_terrains_pattern) const { return !operator==(p_terrains_pattern); - }; + } void set_terrain(int p_terrain); int get_terrain() const; @@ -327,6 +327,7 @@ private: struct PhysicsLayer { uint32_t collision_layer = 1; uint32_t collision_mask = 1; + real_t collision_priority = 1.0; Ref<PhysicsMaterial> physics_material; }; Vector<PhysicsLayer> physics_layers; @@ -448,6 +449,8 @@ public: uint32_t get_physics_layer_collision_layer(int p_layer_index) const; void set_physics_layer_collision_mask(int p_layer_index, uint32_t p_mask); uint32_t get_physics_layer_collision_mask(int p_layer_index) const; + void set_physics_layer_collision_priority(int p_layer_index, real_t p_priority); + real_t get_physics_layer_collision_priority(int p_layer_index) const; void set_physics_layer_physics_material(int p_layer_index, Ref<PhysicsMaterial> p_physics_material); Ref<PhysicsMaterial> get_physics_layer_physics_material(int p_layer_index) const; @@ -812,8 +815,8 @@ public: // Scenes accessors. Lot are similar to "Alternative tiles". int get_scene_tiles_count() { return get_alternative_tiles_count(Vector2i()); } - int get_scene_tile_id(int p_index) { return get_alternative_tile_id(Vector2i(), p_index); }; - bool has_scene_tile_id(int p_id) { return has_alternative_tile(Vector2i(), p_id); }; + int get_scene_tile_id(int p_index) { return get_alternative_tile_id(Vector2i(), p_index); } + bool has_scene_tile_id(int p_id) { return has_alternative_tile(Vector2i(), p_id); } int create_scene_tile(Ref<PackedScene> p_packed_scene = Ref<PackedScene>(), int p_id_override = -1); void set_scene_tile_id(int p_id, int p_new_id); void set_scene_tile_scene(int p_id, Ref<PackedScene> p_packed_scene); @@ -836,7 +839,7 @@ private: bool flip_v = false; bool transpose = false; Vector2i texture_origin; - Ref<Material> material = Ref<Material>(); + Ref<Material> material; Color modulate = Color(1.0, 1.0, 1.0, 1.0); int z_index = 0; int y_sort_origin = 0; diff --git a/scene/resources/3d/SCsub b/scene/resources/3d/SCsub index fdf20e0bde..408aa3cf7e 100644 --- a/scene/resources/3d/SCsub +++ b/scene/resources/3d/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/scene/resources/3d/convex_polygon_shape_3d.cpp b/scene/resources/3d/convex_polygon_shape_3d.cpp index 3bfeeca461..586d5f4678 100644 --- a/scene/resources/3d/convex_polygon_shape_3d.cpp +++ b/scene/resources/3d/convex_polygon_shape_3d.cpp @@ -35,7 +35,7 @@ Vector<Vector3> ConvexPolygonShape3D::get_debug_mesh_lines() const { Vector<Vector3> poly_points = get_points(); - if (poly_points.size() > 3) { + if (poly_points.size() > 1) { // Need at least 2 points for a line. Vector<Vector3> varr = Variant(poly_points); Geometry3D::MeshData md; Error err = ConvexHullComputer::convex_hull(varr, md); diff --git a/scene/resources/3d/fog_material.cpp b/scene/resources/3d/fog_material.cpp index 92246b50db..6c6e98b50d 100644 --- a/scene/resources/3d/fog_material.cpp +++ b/scene/resources/3d/fog_material.cpp @@ -168,6 +168,8 @@ void fog() { } FogMaterial::FogMaterial() { + _set_material(RS::get_singleton()->material_create()); + set_density(1.0); set_albedo(Color(1, 1, 1, 1)); set_emission(Color(0, 0, 0, 1)); diff --git a/scene/resources/3d/importer_mesh.cpp b/scene/resources/3d/importer_mesh.cpp index 47cd64f19a..f040f04cd8 100644 --- a/scene/resources/3d/importer_mesh.cpp +++ b/scene/resources/3d/importer_mesh.cpp @@ -33,108 +33,10 @@ #include "core/io/marshalls.h" #include "core/math/convex_hull.h" #include "core/math/random_pcg.h" -#include "core/math/static_raycaster.h" -#include "scene/resources/animation_library.h" #include "scene/resources/surface_tool.h" #include <cstdint> -void ImporterMesh::Surface::split_normals(const LocalVector<int> &p_indices, const LocalVector<Vector3> &p_normals) { - _split_normals(arrays, p_indices, p_normals); - - for (BlendShape &blend_shape : blend_shape_data) { - _split_normals(blend_shape.arrays, p_indices, p_normals); - } -} - -void ImporterMesh::Surface::_split_normals(Array &r_arrays, const LocalVector<int> &p_indices, const LocalVector<Vector3> &p_normals) { - ERR_FAIL_COND(r_arrays.size() != RS::ARRAY_MAX); - - const PackedVector3Array &vertices = r_arrays[RS::ARRAY_VERTEX]; - int current_vertex_count = vertices.size(); - int new_vertex_count = p_indices.size(); - int final_vertex_count = current_vertex_count + new_vertex_count; - const int *indices_ptr = p_indices.ptr(); - - for (int i = 0; i < r_arrays.size(); i++) { - if (i == RS::ARRAY_INDEX) { - continue; - } - - if (r_arrays[i].get_type() == Variant::NIL) { - continue; - } - - switch (r_arrays[i].get_type()) { - case Variant::PACKED_VECTOR3_ARRAY: { - PackedVector3Array data = r_arrays[i]; - data.resize(final_vertex_count); - Vector3 *data_ptr = data.ptrw(); - if (i == RS::ARRAY_NORMAL) { - const Vector3 *normals_ptr = p_normals.ptr(); - memcpy(&data_ptr[current_vertex_count], normals_ptr, sizeof(Vector3) * new_vertex_count); - } else { - for (int j = 0; j < new_vertex_count; j++) { - data_ptr[current_vertex_count + j] = data_ptr[indices_ptr[j]]; - } - } - r_arrays[i] = data; - } break; - case Variant::PACKED_VECTOR2_ARRAY: { - PackedVector2Array data = r_arrays[i]; - data.resize(final_vertex_count); - Vector2 *data_ptr = data.ptrw(); - for (int j = 0; j < new_vertex_count; j++) { - data_ptr[current_vertex_count + j] = data_ptr[indices_ptr[j]]; - } - r_arrays[i] = data; - } break; - case Variant::PACKED_FLOAT32_ARRAY: { - PackedFloat32Array data = r_arrays[i]; - int elements = data.size() / current_vertex_count; - data.resize(final_vertex_count * elements); - float *data_ptr = data.ptrw(); - for (int j = 0; j < new_vertex_count; j++) { - memcpy(&data_ptr[(current_vertex_count + j) * elements], &data_ptr[indices_ptr[j] * elements], sizeof(float) * elements); - } - r_arrays[i] = data; - } break; - case Variant::PACKED_INT32_ARRAY: { - PackedInt32Array data = r_arrays[i]; - int elements = data.size() / current_vertex_count; - data.resize(final_vertex_count * elements); - int32_t *data_ptr = data.ptrw(); - for (int j = 0; j < new_vertex_count; j++) { - memcpy(&data_ptr[(current_vertex_count + j) * elements], &data_ptr[indices_ptr[j] * elements], sizeof(int32_t) * elements); - } - r_arrays[i] = data; - } break; - case Variant::PACKED_BYTE_ARRAY: { - PackedByteArray data = r_arrays[i]; - int elements = data.size() / current_vertex_count; - data.resize(final_vertex_count * elements); - uint8_t *data_ptr = data.ptrw(); - for (int j = 0; j < new_vertex_count; j++) { - memcpy(&data_ptr[(current_vertex_count + j) * elements], &data_ptr[indices_ptr[j] * elements], sizeof(uint8_t) * elements); - } - r_arrays[i] = data; - } break; - case Variant::PACKED_COLOR_ARRAY: { - PackedColorArray data = r_arrays[i]; - data.resize(final_vertex_count); - Color *data_ptr = data.ptrw(); - for (int j = 0; j < new_vertex_count; j++) { - data_ptr[current_vertex_count + j] = data_ptr[indices_ptr[j]]; - } - r_arrays[i] = data; - } break; - default: { - ERR_FAIL_MSG("Unhandled array type."); - } break; - } - } -} - String ImporterMesh::validate_blend_shape_name(const String &p_name) { String name = p_name; const char *characters = ":"; @@ -266,10 +168,56 @@ void ImporterMesh::set_surface_material(int p_surface, const Ref<Material> &p_ma mesh.unref(); } -void ImporterMesh::optimize_indices_for_cache() { +template <typename T> +static Vector<T> _remap_array(Vector<T> p_array, const Vector<uint32_t> &p_remap, uint32_t p_vertex_count) { + ERR_FAIL_COND_V(p_array.size() % p_remap.size() != 0, p_array); + int num_elements = p_array.size() / p_remap.size(); + T *data = p_array.ptrw(); + SurfaceTool::remap_vertex_func(data, data, p_remap.size(), sizeof(T) * num_elements, p_remap.ptr()); + p_array.resize(p_vertex_count * num_elements); + return p_array; +} + +static void _remap_arrays(Array &r_arrays, const Vector<uint32_t> &p_remap, uint32_t p_vertex_count) { + for (int i = 0; i < r_arrays.size(); i++) { + if (i == RS::ARRAY_INDEX) { + continue; + } + + switch (r_arrays[i].get_type()) { + case Variant::NIL: + break; + case Variant::PACKED_VECTOR3_ARRAY: + r_arrays[i] = _remap_array<Vector3>(r_arrays[i], p_remap, p_vertex_count); + break; + case Variant::PACKED_VECTOR2_ARRAY: + r_arrays[i] = _remap_array<Vector2>(r_arrays[i], p_remap, p_vertex_count); + break; + case Variant::PACKED_FLOAT32_ARRAY: + r_arrays[i] = _remap_array<float>(r_arrays[i], p_remap, p_vertex_count); + break; + case Variant::PACKED_INT32_ARRAY: + r_arrays[i] = _remap_array<int32_t>(r_arrays[i], p_remap, p_vertex_count); + break; + case Variant::PACKED_BYTE_ARRAY: + r_arrays[i] = _remap_array<uint8_t>(r_arrays[i], p_remap, p_vertex_count); + break; + case Variant::PACKED_COLOR_ARRAY: + r_arrays[i] = _remap_array<Color>(r_arrays[i], p_remap, p_vertex_count); + break; + default: + ERR_FAIL_MSG("Unhandled array type."); + } + } +} + +void ImporterMesh::optimize_indices() { if (!SurfaceTool::optimize_vertex_cache_func) { return; } + if (!SurfaceTool::optimize_vertex_fetch_remap_func || !SurfaceTool::remap_vertex_func || !SurfaceTool::remap_index_func) { + return; + } for (int i = 0; i < surfaces.size(); i++) { if (surfaces[i].primitive != Mesh::PRIMITIVE_TRIANGLES) { @@ -286,10 +234,48 @@ void ImporterMesh::optimize_indices_for_cache() { continue; } + // Optimize indices for vertex cache to establish final triangle order. int *indices_ptr = indices.ptrw(); SurfaceTool::optimize_vertex_cache_func((unsigned int *)indices_ptr, (const unsigned int *)indices_ptr, index_count, vertex_count); + surfaces.write[i].arrays[RS::ARRAY_INDEX] = indices; + + for (int j = 0; j < surfaces[i].lods.size(); ++j) { + Surface::LOD &lod = surfaces.write[i].lods.write[j]; + int *lod_indices_ptr = lod.indices.ptrw(); + SurfaceTool::optimize_vertex_cache_func((unsigned int *)lod_indices_ptr, (const unsigned int *)lod_indices_ptr, lod.indices.size(), vertex_count); + } + // Concatenate indices for all LODs in the order of coarse->fine; this establishes the effective order of vertices, + // and is important to optimize for vertex fetch (all GPUs) and shading (Mali GPUs) + PackedInt32Array merged_indices; + for (int j = surfaces[i].lods.size() - 1; j >= 0; --j) { + merged_indices.append_array(surfaces[i].lods[j].indices); + } + merged_indices.append_array(indices); + + // Generate remap array that establishes optimal vertex order according to the order of indices above. + Vector<uint32_t> remap; + remap.resize(vertex_count); + unsigned int new_vertex_count = SurfaceTool::optimize_vertex_fetch_remap_func(remap.ptrw(), (const unsigned int *)merged_indices.ptr(), merged_indices.size(), vertex_count); + + // We need to remap all vertex and index arrays in lockstep according to the remap. + SurfaceTool::remap_index_func((unsigned int *)indices_ptr, (const unsigned int *)indices_ptr, index_count, remap.ptr()); surfaces.write[i].arrays[RS::ARRAY_INDEX] = indices; + + for (int j = 0; j < surfaces[i].lods.size(); ++j) { + Surface::LOD &lod = surfaces.write[i].lods.write[j]; + int *lod_indices_ptr = lod.indices.ptrw(); + SurfaceTool::remap_index_func((unsigned int *)lod_indices_ptr, (const unsigned int *)lod_indices_ptr, lod.indices.size(), remap.ptr()); + } + + _remap_arrays(surfaces.write[i].arrays, remap, new_vertex_count); + for (int j = 0; j < surfaces[i].blend_shape_data.size(); j++) { + _remap_arrays(surfaces.write[i].blend_shape_data.write[j].arrays, remap, new_vertex_count); + } + } + + if (shadow_mesh.is_valid()) { + shadow_mesh->optimize_indices(); } } @@ -306,16 +292,13 @@ void ImporterMesh::optimize_indices_for_cache() { } \ write_array[vert_idx] = transformed_vert; -void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_split_angle, Array p_bone_transform_array, bool p_raycast_normals) { +void ImporterMesh::generate_lods(float p_normal_merge_angle, Array p_bone_transform_array) { if (!SurfaceTool::simplify_scale_func) { return; } if (!SurfaceTool::simplify_with_attrib_func) { return; } - if (!SurfaceTool::optimize_vertex_cache_func) { - return; - } LocalVector<Transform3D> bone_transform_vector; for (int i = 0; i < p_bone_transform_array.size(); i++) { @@ -379,8 +362,6 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_spli } float normal_merge_threshold = Math::cos(Math::deg_to_rad(p_normal_merge_angle)); - float normal_pre_split_threshold = Math::cos(Math::deg_to_rad(MIN(180.0f, p_normal_split_angle * 2.0f))); - float normal_split_threshold = Math::cos(Math::deg_to_rad(p_normal_split_angle)); const Vector3 *normals_ptr = normals.ptr(); HashMap<Vector3, LocalVector<Pair<int, int>>> unique_vertices; @@ -469,22 +450,6 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_spli unsigned int index_target = 12; // Start with the smallest target, 4 triangles unsigned int last_index_count = 0; - // Only used for normal raycasting - int split_vertex_count = vertex_count; - LocalVector<Vector3> split_vertex_normals; - LocalVector<int> split_vertex_indices; - split_vertex_normals.reserve(index_count / 3); - split_vertex_indices.reserve(index_count / 3); - - RandomPCG pcg; - pcg.seed(123456789); // Keep seed constant across imports - - Ref<StaticRaycaster> raycaster = p_raycast_normals ? StaticRaycaster::create() : Ref<StaticRaycaster>(); - if (raycaster.is_valid()) { - raycaster->add_mesh(vertices, indices, 0); - raycaster->commit(); - } - const float max_mesh_error = FLT_MAX; // We don't want to limit by error, just by index target float mesh_error = 0.0f; @@ -503,6 +468,7 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_spli merged_normals_f32.ptr(), sizeof(float) * 3, // Attribute stride normal_weights, 3, + nullptr, // Vertex lock index_target, max_mesh_error, simplify_options, @@ -533,173 +499,6 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_spli } } - if (raycaster.is_valid()) { - LocalVector<LocalVector<int>> vertex_corners; - vertex_corners.resize(vertex_count); - - int *ptrw = new_indices.ptrw(); - for (unsigned int j = 0; j < new_index_count; j++) { - vertex_corners[ptrw[j]].push_back(j); - } - - float error_factor = 1.0f / (scale * MAX(mesh_error, 0.15)); - const float ray_bias = 0.05; - float ray_length = ray_bias + mesh_error * scale * 3.0f; - - Vector<StaticRaycaster::Ray> rays; - LocalVector<Vector2> ray_uvs; - - int32_t *new_indices_ptr = new_indices.ptrw(); - - int current_ray_count = 0; - for (unsigned int j = 0; j < new_index_count; j += 3) { - const Vector3 &v0 = vertices_ptr[new_indices_ptr[j + 0]]; - const Vector3 &v1 = vertices_ptr[new_indices_ptr[j + 1]]; - const Vector3 &v2 = vertices_ptr[new_indices_ptr[j + 2]]; - Vector3 face_normal = vec3_cross(v0 - v2, v0 - v1); - float face_area = face_normal.length(); // Actually twice the face area, since it's the same error_factor on all faces, we don't care - if (!Math::is_finite(face_area) || face_area == 0) { - WARN_PRINT_ONCE("Ignoring face with non-finite normal in LOD generation."); - continue; - } - - Vector3 dir = face_normal / face_area; - int ray_count = CLAMP(5.0 * face_area * error_factor, 16, 64); - - rays.resize(current_ray_count + ray_count); - StaticRaycaster::Ray *rays_ptr = rays.ptrw(); - - ray_uvs.resize(current_ray_count + ray_count); - Vector2 *ray_uvs_ptr = ray_uvs.ptr(); - - for (int k = 0; k < ray_count; k++) { - float u = pcg.randf(); - float v = pcg.randf(); - - if (u + v >= 1.0f) { - u = 1.0f - u; - v = 1.0f - v; - } - - u = 0.9f * u + 0.05f / 3.0f; // Give barycentric coordinates some padding, we don't want to sample right on the edge - v = 0.9f * v + 0.05f / 3.0f; // v = (v - one_third) * 0.95f + one_third; - float w = 1.0f - u - v; - - Vector3 org = v0 * w + v1 * u + v2 * v; - org -= dir * ray_bias; - rays_ptr[current_ray_count + k] = StaticRaycaster::Ray(org, dir, 0.0f, ray_length); - rays_ptr[current_ray_count + k].id = j / 3; - ray_uvs_ptr[current_ray_count + k] = Vector2(u, v); - } - - current_ray_count += ray_count; - } - - raycaster->intersect(rays); - - LocalVector<Vector3> ray_normals; - LocalVector<real_t> ray_normal_weights; - - ray_normals.resize(new_index_count); - ray_normal_weights.resize(new_index_count); - - for (unsigned int j = 0; j < new_index_count; j++) { - ray_normal_weights[j] = 0.0f; - } - - const StaticRaycaster::Ray *rp = rays.ptr(); - for (int j = 0; j < rays.size(); j++) { - if (rp[j].geomID != 0) { // Ray missed - continue; - } - - if (rp[j].normal.normalized().dot(rp[j].dir) > 0.0f) { // Hit a back face. - continue; - } - - const float &u = rp[j].u; - const float &v = rp[j].v; - const float w = 1.0f - u - v; - - const unsigned int &hit_tri_id = rp[j].primID; - const unsigned int &orig_tri_id = rp[j].id; - - const Vector3 &n0 = normals_ptr[indices_ptr[hit_tri_id * 3 + 0]]; - const Vector3 &n1 = normals_ptr[indices_ptr[hit_tri_id * 3 + 1]]; - const Vector3 &n2 = normals_ptr[indices_ptr[hit_tri_id * 3 + 2]]; - Vector3 normal = n0 * w + n1 * u + n2 * v; - - Vector2 orig_uv = ray_uvs[j]; - const real_t orig_bary[3] = { 1.0f - orig_uv.x - orig_uv.y, orig_uv.x, orig_uv.y }; - for (int k = 0; k < 3; k++) { - int idx = orig_tri_id * 3 + k; - real_t weight = orig_bary[k]; - ray_normals[idx] += normal * weight; - ray_normal_weights[idx] += weight; - } - } - - for (unsigned int j = 0; j < new_index_count; j++) { - if (ray_normal_weights[j] < 1.0f) { // Not enough data, the new normal would be just a bad guess - ray_normals[j] = Vector3(); - } else { - ray_normals[j] /= ray_normal_weights[j]; - } - } - - LocalVector<LocalVector<int>> normal_group_indices; - LocalVector<Vector3> normal_group_averages; - normal_group_indices.reserve(24); - normal_group_averages.reserve(24); - - for (unsigned int j = 0; j < vertex_count; j++) { - const LocalVector<int> &corners = vertex_corners[j]; - const Vector3 &vertex_normal = normals_ptr[j]; - - for (const int &corner_idx : corners) { - const Vector3 &ray_normal = ray_normals[corner_idx]; - - if (ray_normal.length_squared() < CMP_EPSILON2) { - continue; - } - - bool found = false; - for (unsigned int l = 0; l < normal_group_indices.size(); l++) { - LocalVector<int> &group_indices = normal_group_indices[l]; - Vector3 n = normal_group_averages[l] / group_indices.size(); - if (n.dot(ray_normal) > normal_pre_split_threshold) { - found = true; - group_indices.push_back(corner_idx); - normal_group_averages[l] += ray_normal; - break; - } - } - - if (!found) { - normal_group_indices.push_back({ corner_idx }); - normal_group_averages.push_back(ray_normal); - } - } - - for (unsigned int k = 0; k < normal_group_indices.size(); k++) { - LocalVector<int> &group_indices = normal_group_indices[k]; - Vector3 n = normal_group_averages[k] / group_indices.size(); - - if (vertex_normal.dot(n) < normal_split_threshold) { - split_vertex_indices.push_back(j); - split_vertex_normals.push_back(n); - int new_idx = split_vertex_count++; - for (const int &index : group_indices) { - new_indices_ptr[index] = new_idx; - } - } - } - - normal_group_indices.clear(); - normal_group_averages.clear(); - } - } - Surface::LOD lod; lod.distance = MAX(mesh_error * scale, CMP_EPSILON2); lod.indices = new_indices; @@ -712,22 +511,13 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_spli } } - if (raycaster.is_valid()) { - surfaces.write[i].split_normals(split_vertex_indices, split_vertex_normals); - } - surfaces.write[i].lods.sort_custom<Surface::LODComparator>(); - - for (int j = 0; j < surfaces.write[i].lods.size(); j++) { - Surface::LOD &lod = surfaces.write[i].lods.write[j]; - unsigned int *lod_indices_ptr = (unsigned int *)lod.indices.ptrw(); - SurfaceTool::optimize_vertex_cache_func(lod_indices_ptr, lod_indices_ptr, lod.indices.size(), split_vertex_count); - } } } void ImporterMesh::_generate_lods_bind(float p_normal_merge_angle, float p_normal_split_angle, Array p_skin_pose_transform_array) { - generate_lods(p_normal_merge_angle, p_normal_split_angle, p_skin_pose_transform_array); + // p_normal_split_angle is unused, but kept for compatibility + generate_lods(p_normal_merge_angle, p_skin_pose_transform_array); } bool ImporterMesh::has_mesh() const { @@ -859,10 +649,6 @@ void ImporterMesh::create_shadow_mesh() { index_wptr[j] = vertex_remap[index]; } - if (SurfaceTool::optimize_vertex_cache_func && surfaces[i].primitive == Mesh::PRIMITIVE_TRIANGLES) { - SurfaceTool::optimize_vertex_cache_func((unsigned int *)index_wptr, (const unsigned int *)index_wptr, index_count, new_vertices.size()); - } - new_surface[RS::ARRAY_INDEX] = new_indices; // Make sure the same LODs as the full version are used. @@ -881,10 +667,6 @@ void ImporterMesh::create_shadow_mesh() { index_wptr[k] = vertex_remap[index]; } - if (SurfaceTool::optimize_vertex_cache_func && surfaces[i].primitive == Mesh::PRIMITIVE_TRIANGLES) { - SurfaceTool::optimize_vertex_cache_func((unsigned int *)index_wptr, (const unsigned int *)index_wptr, index_count, new_vertices.size()); - } - lods[surfaces[i].lods[j].distance] = new_indices; } } diff --git a/scene/resources/3d/importer_mesh.h b/scene/resources/3d/importer_mesh.h index c7e3a059d6..2bdf759da6 100644 --- a/scene/resources/3d/importer_mesh.h +++ b/scene/resources/3d/importer_mesh.h @@ -68,9 +68,6 @@ class ImporterMesh : public Resource { return l.distance < r.distance; } }; - - void split_normals(const LocalVector<int> &p_indices, const LocalVector<Vector3> &p_normals); - static void _split_normals(Array &r_arrays, const LocalVector<int> &p_indices, const LocalVector<Vector3> &p_normals); }; Vector<Surface> surfaces; Vector<String> blend_shapes; @@ -116,9 +113,9 @@ public: void set_surface_material(int p_surface, const Ref<Material> &p_material); - void optimize_indices_for_cache(); + void optimize_indices(); - void generate_lods(float p_normal_merge_angle, float p_normal_split_angle, Array p_skin_pose_transform_array, bool p_raycast_normals = false); + void generate_lods(float p_normal_merge_angle, Array p_skin_pose_transform_array); void create_shadow_mesh(); Ref<ImporterMesh> get_shadow_mesh() const; diff --git a/scene/resources/3d/navigation_mesh_source_geometry_data_3d.cpp b/scene/resources/3d/navigation_mesh_source_geometry_data_3d.cpp index 59366592ce..74dca88423 100644 --- a/scene/resources/3d/navigation_mesh_source_geometry_data_3d.cpp +++ b/scene/resources/3d/navigation_mesh_source_geometry_data_3d.cpp @@ -71,7 +71,7 @@ void NavigationMeshSourceGeometryData3D::append_arrays(const Vector<float> &p_ve bool NavigationMeshSourceGeometryData3D::has_data() { RWLockRead read_lock(geometry_rwlock); return vertices.size() && indices.size(); -}; +} void NavigationMeshSourceGeometryData3D::clear() { RWLockWrite write_lock(geometry_rwlock); diff --git a/scene/resources/3d/primitive_meshes.cpp b/scene/resources/3d/primitive_meshes.cpp index ceeb73d0ef..4d04ae77b1 100644 --- a/scene/resources/3d/primitive_meshes.cpp +++ b/scene/resources/3d/primitive_meshes.cpp @@ -31,6 +31,7 @@ #include "primitive_meshes.h" #include "core/config/project_settings.h" +#include "core/math/math_funcs.h" #include "scene/resources/theme.h" #include "scene/theme/theme_db.h" #include "servers/rendering_server.h" @@ -261,6 +262,9 @@ void PrimitiveMesh::_bind_methods() { } void PrimitiveMesh::set_material(const Ref<Material> &p_material) { + if (p_material == material) { + return; + } material = p_material; if (!pending_request) { // just apply it, else it'll happen when _update is called. @@ -279,6 +283,9 @@ Array PrimitiveMesh::get_mesh_arrays() const { } void PrimitiveMesh::set_custom_aabb(const AABB &p_custom) { + if (p_custom.is_equal_approx(custom_aabb)) { + return; + } custom_aabb = p_custom; RS::get_singleton()->mesh_set_custom_aabb(mesh, custom_aabb); emit_changed(); @@ -289,6 +296,9 @@ AABB PrimitiveMesh::get_custom_aabb() const { } void PrimitiveMesh::set_flip_faces(bool p_enable) { + if (p_enable == flip_faces) { + return; + } flip_faces = p_enable; request_update(); } @@ -298,12 +308,18 @@ bool PrimitiveMesh::get_flip_faces() const { } void PrimitiveMesh::set_add_uv2(bool p_enable) { + if (p_enable == add_uv2) { + return; + } add_uv2 = p_enable; _update_lightmap_size(); request_update(); } void PrimitiveMesh::set_uv2_padding(float p_padding) { + if (Math::is_equal_approx(p_padding, uv2_padding)) { + return; + } uv2_padding = p_padding; _update_lightmap_size(); request_update(); @@ -578,6 +594,10 @@ void CapsuleMesh::_bind_methods() { } void CapsuleMesh::set_radius(const float p_radius) { + if (Math::is_equal_approx(radius, p_radius)) { + return; + } + radius = p_radius; if (radius > height * 0.5) { height = radius * 2.0; @@ -591,6 +611,10 @@ float CapsuleMesh::get_radius() const { } void CapsuleMesh::set_height(const float p_height) { + if (Math::is_equal_approx(height, p_height)) { + return; + } + height = p_height; if (radius > height * 0.5) { radius = height * 0.5; @@ -604,6 +628,10 @@ float CapsuleMesh::get_height() const { } void CapsuleMesh::set_radial_segments(const int p_segments) { + if (radial_segments == p_segments) { + return; + } + radial_segments = p_segments > 4 ? p_segments : 4; request_update(); } @@ -613,6 +641,10 @@ int CapsuleMesh::get_radial_segments() const { } void CapsuleMesh::set_rings(const int p_rings) { + if (rings == p_rings) { + return; + } + ERR_FAIL_COND(p_rings < 0); rings = p_rings; request_update(); @@ -908,6 +940,10 @@ void BoxMesh::_bind_methods() { } void BoxMesh::set_size(const Vector3 &p_size) { + if (p_size.is_equal_approx(size)) { + return; + } + size = p_size; _update_lightmap_size(); request_update(); @@ -918,6 +954,10 @@ Vector3 BoxMesh::get_size() const { } void BoxMesh::set_subdivide_width(const int p_divisions) { + if (p_divisions == subdivide_w) { + return; + } + subdivide_w = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -927,6 +967,10 @@ int BoxMesh::get_subdivide_width() const { } void BoxMesh::set_subdivide_height(const int p_divisions) { + if (p_divisions == subdivide_h) { + return; + } + subdivide_h = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -936,6 +980,10 @@ int BoxMesh::get_subdivide_height() const { } void BoxMesh::set_subdivide_depth(const int p_divisions) { + if (p_divisions == subdivide_d) { + return; + } + subdivide_d = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -1183,6 +1231,10 @@ void CylinderMesh::_bind_methods() { } void CylinderMesh::set_top_radius(const float p_radius) { + if (Math::is_equal_approx(p_radius, top_radius)) { + return; + } + top_radius = p_radius; _update_lightmap_size(); request_update(); @@ -1193,6 +1245,10 @@ float CylinderMesh::get_top_radius() const { } void CylinderMesh::set_bottom_radius(const float p_radius) { + if (Math::is_equal_approx(p_radius, bottom_radius)) { + return; + } + bottom_radius = p_radius; _update_lightmap_size(); request_update(); @@ -1203,6 +1259,10 @@ float CylinderMesh::get_bottom_radius() const { } void CylinderMesh::set_height(const float p_height) { + if (Math::is_equal_approx(p_height, height)) { + return; + } + height = p_height; _update_lightmap_size(); request_update(); @@ -1213,6 +1273,10 @@ float CylinderMesh::get_height() const { } void CylinderMesh::set_radial_segments(const int p_segments) { + if (p_segments == radial_segments) { + return; + } + radial_segments = p_segments > 4 ? p_segments : 4; request_update(); } @@ -1222,6 +1286,10 @@ int CylinderMesh::get_radial_segments() const { } void CylinderMesh::set_rings(const int p_rings) { + if (p_rings == rings) { + return; + } + ERR_FAIL_COND(p_rings < 0); rings = p_rings; request_update(); @@ -1232,6 +1300,10 @@ int CylinderMesh::get_rings() const { } void CylinderMesh::set_cap_top(bool p_cap_top) { + if (p_cap_top == cap_top) { + return; + } + cap_top = p_cap_top; request_update(); } @@ -1241,6 +1313,10 @@ bool CylinderMesh::is_cap_top() const { } void CylinderMesh::set_cap_bottom(bool p_cap_bottom) { + if (p_cap_bottom == cap_bottom) { + return; + } + cap_bottom = p_cap_bottom; request_update(); } @@ -1375,6 +1451,9 @@ void PlaneMesh::_bind_methods() { } void PlaneMesh::set_size(const Size2 &p_size) { + if (p_size == size) { + return; + } size = p_size; _update_lightmap_size(); request_update(); @@ -1385,6 +1464,9 @@ Size2 PlaneMesh::get_size() const { } void PlaneMesh::set_subdivide_width(const int p_divisions) { + if (p_divisions == subdivide_w || (subdivide_w == 0 && p_divisions < 0)) { + return; + } subdivide_w = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -1394,6 +1476,9 @@ int PlaneMesh::get_subdivide_width() const { } void PlaneMesh::set_subdivide_depth(const int p_divisions) { + if (p_divisions == subdivide_d || (subdivide_d == 0 && p_divisions < 0)) { + return; + } subdivide_d = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -1403,6 +1488,9 @@ int PlaneMesh::get_subdivide_depth() const { } void PlaneMesh::set_center_offset(const Vector3 p_offset) { + if (p_offset.is_equal_approx(center_offset)) { + return; + } center_offset = p_offset; request_update(); } @@ -1412,6 +1500,9 @@ Vector3 PlaneMesh::get_center_offset() const { } void PlaneMesh::set_orientation(const Orientation p_orientation) { + if (p_orientation == orientation) { + return; + } orientation = p_orientation; request_update(); } @@ -1719,6 +1810,9 @@ void PrismMesh::_bind_methods() { } void PrismMesh::set_left_to_right(const float p_left_to_right) { + if (Math::is_equal_approx(p_left_to_right, left_to_right)) { + return; + } left_to_right = p_left_to_right; request_update(); } @@ -1728,6 +1822,9 @@ float PrismMesh::get_left_to_right() const { } void PrismMesh::set_size(const Vector3 &p_size) { + if (p_size.is_equal_approx(size)) { + return; + } size = p_size; _update_lightmap_size(); request_update(); @@ -1738,6 +1835,9 @@ Vector3 PrismMesh::get_size() const { } void PrismMesh::set_subdivide_width(const int p_divisions) { + if (p_divisions == subdivide_w || (p_divisions < 0 && subdivide_w == 0)) { + return; + } subdivide_w = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -1747,6 +1847,9 @@ int PrismMesh::get_subdivide_width() const { } void PrismMesh::set_subdivide_height(const int p_divisions) { + if (p_divisions == subdivide_h || (p_divisions < 0 && subdivide_h == 0)) { + return; + } subdivide_h = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -1756,6 +1859,9 @@ int PrismMesh::get_subdivide_height() const { } void PrismMesh::set_subdivide_depth(const int p_divisions) { + if (p_divisions == subdivide_d || (p_divisions < 0 && subdivide_d == 0)) { + return; + } subdivide_d = p_divisions > 0 ? p_divisions : 0; request_update(); } @@ -1902,6 +2008,9 @@ void SphereMesh::_bind_methods() { } void SphereMesh::set_radius(const float p_radius) { + if (Math::is_equal_approx(p_radius, radius)) { + return; + } radius = p_radius; _update_lightmap_size(); request_update(); @@ -1912,6 +2021,9 @@ float SphereMesh::get_radius() const { } void SphereMesh::set_height(const float p_height) { + if (Math::is_equal_approx(height, p_height)) { + return; + } height = p_height; _update_lightmap_size(); request_update(); @@ -1922,6 +2034,9 @@ float SphereMesh::get_height() const { } void SphereMesh::set_radial_segments(const int p_radial_segments) { + if (p_radial_segments == radial_segments || (radial_segments == 4 && p_radial_segments < 4)) { + return; + } radial_segments = p_radial_segments > 4 ? p_radial_segments : 4; request_update(); } @@ -1931,6 +2046,9 @@ int SphereMesh::get_radial_segments() const { } void SphereMesh::set_rings(const int p_rings) { + if (p_rings == rings) { + return; + } ERR_FAIL_COND(p_rings < 1); rings = p_rings; request_update(); @@ -1941,6 +2059,9 @@ int SphereMesh::get_rings() const { } void SphereMesh::set_is_hemisphere(const bool p_is_hemisphere) { + if (p_is_hemisphere == is_hemisphere) { + return; + } is_hemisphere = p_is_hemisphere; _update_lightmap_size(); request_update(); @@ -2086,6 +2207,9 @@ void TorusMesh::_bind_methods() { } void TorusMesh::set_inner_radius(const float p_inner_radius) { + if (Math::is_equal_approx(p_inner_radius, inner_radius)) { + return; + } inner_radius = p_inner_radius; request_update(); } @@ -2095,6 +2219,9 @@ float TorusMesh::get_inner_radius() const { } void TorusMesh::set_outer_radius(const float p_outer_radius) { + if (Math::is_equal_approx(p_outer_radius, outer_radius)) { + return; + } outer_radius = p_outer_radius; request_update(); } @@ -2104,6 +2231,9 @@ float TorusMesh::get_outer_radius() const { } void TorusMesh::set_rings(const int p_rings) { + if (p_rings == rings) { + return; + } ERR_FAIL_COND(p_rings < 3); rings = p_rings; request_update(); @@ -2114,6 +2244,9 @@ int TorusMesh::get_rings() const { } void TorusMesh::set_ring_segments(const int p_ring_segments) { + if (p_ring_segments == ring_segments) { + return; + } ERR_FAIL_COND(p_ring_segments < 3); ring_segments = p_ring_segments; request_update(); @@ -2143,6 +2276,9 @@ PointMesh::PointMesh() { // TUBE TRAIL void TubeTrailMesh::set_radius(const float p_radius) { + if (Math::is_equal_approx(p_radius, radius)) { + return; + } radius = p_radius; request_update(); } @@ -2151,6 +2287,9 @@ float TubeTrailMesh::get_radius() const { } void TubeTrailMesh::set_radial_steps(const int p_radial_steps) { + if (p_radial_steps == radial_steps) { + return; + } ERR_FAIL_COND(p_radial_steps < 3 || p_radial_steps > 128); radial_steps = p_radial_steps; request_update(); @@ -2160,6 +2299,9 @@ int TubeTrailMesh::get_radial_steps() const { } void TubeTrailMesh::set_sections(const int p_sections) { + if (p_sections == sections) { + return; + } ERR_FAIL_COND(p_sections < 2 || p_sections > 128); sections = p_sections; request_update(); @@ -2169,6 +2311,9 @@ int TubeTrailMesh::get_sections() const { } void TubeTrailMesh::set_section_length(float p_section_length) { + if (p_section_length == section_length) { + return; + } section_length = p_section_length; request_update(); } @@ -2177,6 +2322,9 @@ float TubeTrailMesh::get_section_length() const { } void TubeTrailMesh::set_section_rings(const int p_section_rings) { + if (p_section_rings == section_rings) { + return; + } ERR_FAIL_COND(p_section_rings < 1 || p_section_rings > 1024); section_rings = p_section_rings; request_update(); @@ -2186,6 +2334,9 @@ int TubeTrailMesh::get_section_rings() const { } void TubeTrailMesh::set_cap_top(bool p_cap_top) { + if (p_cap_top == cap_top) { + return; + } cap_top = p_cap_top; request_update(); } @@ -2195,6 +2346,9 @@ bool TubeTrailMesh::is_cap_top() const { } void TubeTrailMesh::set_cap_bottom(bool p_cap_bottom) { + if (p_cap_bottom == cap_bottom) { + return; + } cap_bottom = p_cap_bottom; request_update(); } @@ -2501,6 +2655,9 @@ TubeTrailMesh::TubeTrailMesh() { // RIBBON TRAIL void RibbonTrailMesh::set_shape(Shape p_shape) { + if (p_shape == shape) { + return; + } shape = p_shape; request_update(); } @@ -2509,6 +2666,9 @@ RibbonTrailMesh::Shape RibbonTrailMesh::get_shape() const { } void RibbonTrailMesh::set_size(const float p_size) { + if (Math::is_equal_approx(p_size, size)) { + return; + } size = p_size; request_update(); } @@ -2517,6 +2677,9 @@ float RibbonTrailMesh::get_size() const { } void RibbonTrailMesh::set_sections(const int p_sections) { + if (p_sections == sections) { + return; + } ERR_FAIL_COND(p_sections < 2 || p_sections > 128); sections = p_sections; request_update(); @@ -2526,6 +2689,9 @@ int RibbonTrailMesh::get_sections() const { } void RibbonTrailMesh::set_section_length(float p_section_length) { + if (p_section_length == section_length) { + return; + } section_length = p_section_length; request_update(); } @@ -2534,6 +2700,9 @@ float RibbonTrailMesh::get_section_length() const { } void RibbonTrailMesh::set_section_segments(const int p_section_segments) { + if (p_section_segments == section_segments) { + return; + } ERR_FAIL_COND(p_section_segments < 1 || p_section_segments > 1024); section_segments = p_section_segments; request_update(); diff --git a/scene/resources/3d/primitive_meshes.h b/scene/resources/3d/primitive_meshes.h index 85f46a482a..e68ac7fb26 100644 --- a/scene/resources/3d/primitive_meshes.h +++ b/scene/resources/3d/primitive_meshes.h @@ -545,7 +545,7 @@ private: ContourPoint(const Vector2 &p_pt, bool p_sharp) { point = p_pt; sharp = p_sharp; - }; + } }; struct ContourInfo { diff --git a/scene/resources/3d/shape_3d.cpp b/scene/resources/3d/shape_3d.cpp index 5a79392ba5..259d82b7a0 100644 --- a/scene/resources/3d/shape_3d.cpp +++ b/scene/resources/3d/shape_3d.cpp @@ -73,7 +73,7 @@ Ref<ArrayMesh> Shape3D::get_debug_mesh() { Vector<Vector3> lines = get_debug_mesh_lines(); - debug_mesh_cache = Ref<ArrayMesh>(memnew(ArrayMesh)); + debug_mesh_cache.instantiate(); if (!lines.is_empty()) { //make mesh diff --git a/scene/resources/3d/sky_material.cpp b/scene/resources/3d/sky_material.cpp index c470db5d7f..10ef516f7a 100644 --- a/scene/resources/3d/sky_material.cpp +++ b/scene/resources/3d/sky_material.cpp @@ -357,6 +357,7 @@ void sky() { } ProceduralSkyMaterial::ProceduralSkyMaterial() { + _set_material(RS::get_singleton()->material_create()); set_sky_top_color(Color(0.385, 0.454, 0.55)); set_sky_horizon_color(Color(0.6463, 0.6558, 0.6708)); set_sky_curve(0.15); @@ -486,6 +487,7 @@ void sky() { } PanoramaSkyMaterial::PanoramaSkyMaterial() { + _set_material(RS::get_singleton()->material_create()); set_energy_multiplier(1.0); } @@ -785,6 +787,7 @@ void sky() { } PhysicalSkyMaterial::PhysicalSkyMaterial() { + _set_material(RS::get_singleton()->material_create()); set_rayleigh_coefficient(2.0); set_rayleigh_color(Color(0.3, 0.405, 0.6)); set_mie_coefficient(0.005); diff --git a/scene/resources/SCsub b/scene/resources/SCsub index 2b6aa88d2c..46f6251b91 100644 --- a/scene/resources/SCsub +++ b/scene/resources/SCsub @@ -1,4 +1,5 @@ #!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index a2ed6af23c..f0b182503a 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -63,6 +63,23 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) { } compression.enabled = true; return true; + } else if (prop_name == SNAME("markers")) { + Array markers = p_value; + for (const Dictionary marker : markers) { + ERR_FAIL_COND_V(!marker.has("name"), false); + ERR_FAIL_COND_V(!marker.has("time"), false); + StringName marker_name = marker["name"]; + double time = marker["time"]; + _marker_insert(time, marker_names, MarkerKey(time, marker_name)); + marker_times.insert(marker_name, time); + Color color = Color(1, 1, 1); + if (marker.has("color")) { + color = marker["color"]; + } + marker_colors.insert(marker_name, color); + } + + return true; } else if (prop_name.begins_with("tracks/")) { int track = prop_name.get_slicec('/', 1).to_int(); String what = prop_name.get_slicec('/', 2); @@ -321,8 +338,12 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) { Vector<real_t> times = d["times"]; Vector<real_t> values = d["points"]; #ifdef TOOLS_ENABLED - ERR_FAIL_COND_V(!d.has("handle_modes"), false); - Vector<int> handle_modes = d["handle_modes"]; + Vector<int> handle_modes; + if (d.has("handle_modes")) { + handle_modes = d["handle_modes"]; + } else { + handle_modes.resize_zeroed(times.size()); + } #endif // TOOLS_ENABLED ERR_FAIL_COND_V(times.size() * 5 != values.size(), false); @@ -466,6 +487,18 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const { r_ret = comp; return true; + } else if (prop_name == SNAME("markers")) { + Array markers; + + for (HashMap<StringName, double>::ConstIterator E = marker_times.begin(); E; ++E) { + Dictionary d; + d["name"] = E->key; + d["time"] = E->value; + d["color"] = marker_colors[E->key]; + markers.push_back(d); + } + + r_ret = markers; } else if (prop_name == "length") { r_ret = length; } else if (prop_name == "loop_mode") { @@ -835,6 +868,7 @@ void Animation::_get_property_list(List<PropertyInfo> *p_list) const { if (compression.enabled) { p_list->push_back(PropertyInfo(Variant::DICTIONARY, "_compression", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); } + p_list->push_back(PropertyInfo(Variant::ARRAY, "markers", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); for (int i = 0; i < tracks.size(); i++) { p_list->push_back(PropertyInfo(Variant::STRING, "tracks/" + itos(i) + "/type", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); p_list->push_back(PropertyInfo(Variant::BOOL, "tracks/" + itos(i) + "/imported", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL)); @@ -1014,7 +1048,7 @@ int Animation::find_track(const NodePath &p_path, const TrackType p_type) const } }; return -1; -}; +} Animation::TrackType Animation::get_cache_type(TrackType p_type) { if (p_type == Animation::TYPE_BEZIER) { @@ -1083,6 +1117,27 @@ int Animation::_insert(double p_time, T &p_keys, const V &p_value) { return -1; } +int Animation::_marker_insert(double p_time, Vector<MarkerKey> &p_keys, const MarkerKey &p_value) { + int idx = p_keys.size(); + + while (true) { + // Condition for replacement. + if (idx > 0 && Math::is_equal_approx((double)p_keys[idx - 1].time, p_time)) { + p_keys.write[idx - 1] = p_value; + return idx - 1; + + // Condition for insert. + } else if (idx == 0 || p_keys[idx - 1].time < p_time) { + p_keys.insert(idx, p_value); + return idx; + } + + idx--; + } + + return -1; +} + template <typename T> void Animation::_clear(T &p_keys) { p_keys.clear(); @@ -3159,6 +3214,90 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl } } +void Animation::add_marker(const StringName &p_name, double p_time) { + int idx = _find(marker_names, p_time); + + if (idx >= 0 && idx < marker_names.size() && Math::is_equal_approx(p_time, marker_names[idx].time)) { + marker_times.erase(marker_names[idx].name); + marker_colors.erase(marker_names[idx].name); + marker_names.write[idx].name = p_name; + marker_times.insert(p_name, p_time); + marker_colors.insert(p_name, Color(1, 1, 1)); + } else { + _marker_insert(p_time, marker_names, MarkerKey(p_time, p_name)); + marker_times.insert(p_name, p_time); + marker_colors.insert(p_name, Color(1, 1, 1)); + } +} + +void Animation::remove_marker(const StringName &p_name) { + HashMap<StringName, double>::Iterator E = marker_times.find(p_name); + ERR_FAIL_COND(!E); + int idx = _find(marker_names, E->value); + bool success = idx >= 0 && idx < marker_names.size() && Math::is_equal_approx(marker_names[idx].time, E->value); + ERR_FAIL_COND(!success); + marker_names.remove_at(idx); + marker_times.remove(E); + marker_colors.erase(p_name); +} + +bool Animation::has_marker(const StringName &p_name) const { + return marker_times.has(p_name); +} + +StringName Animation::get_marker_at_time(double p_time) const { + int idx = _find(marker_names, p_time); + + if (idx >= 0 && idx < marker_names.size() && Math::is_equal_approx(marker_names[idx].time, p_time)) { + return marker_names[idx].name; + } + + return StringName(); +} + +StringName Animation::get_next_marker(double p_time) const { + int idx = _find(marker_names, p_time); + + if (idx >= -1 && idx < marker_names.size() - 1) { + // _find ensures that the time at idx is always the closest time to p_time that is also smaller to it. + // So we add 1 to get the next marker. + return marker_names[idx + 1].name; + } + return StringName(); +} + +StringName Animation::get_prev_marker(double p_time) const { + int idx = _find(marker_names, p_time); + + if (idx >= 0 && idx < marker_names.size()) { + return marker_names[idx].name; + } + return StringName(); +} + +double Animation::get_marker_time(const StringName &p_name) const { + ERR_FAIL_COND_V(!marker_times.has(p_name), -1); + return marker_times.get(p_name); +} + +PackedStringArray Animation::get_marker_names() const { + PackedStringArray names; + // We iterate on marker_names so the result is sorted by time. + for (const MarkerKey &marker_name : marker_names) { + names.push_back(marker_name.name); + } + return names; +} + +Color Animation::get_marker_color(const StringName &p_name) const { + ERR_FAIL_COND_V(!marker_colors.has(p_name), Color()); + return marker_colors[p_name]; +} + +void Animation::set_marker_color(const StringName &p_name, const Color &p_color) { + marker_colors[p_name] = p_color; +} + Vector<Variant> Animation::method_track_get_params(int p_track, int p_key_idx) const { ERR_FAIL_INDEX_V(p_track, tracks.size(), Vector<Variant>()); Track *t = tracks[p_track]; @@ -3890,6 +4029,17 @@ void Animation::_bind_methods() { ClassDB::bind_method(D_METHOD("animation_track_set_key_animation", "track_idx", "key_idx", "animation"), &Animation::animation_track_set_key_animation); ClassDB::bind_method(D_METHOD("animation_track_get_key_animation", "track_idx", "key_idx"), &Animation::animation_track_get_key_animation); + ClassDB::bind_method(D_METHOD("add_marker", "name", "time"), &Animation::add_marker); + ClassDB::bind_method(D_METHOD("remove_marker", "name"), &Animation::remove_marker); + ClassDB::bind_method(D_METHOD("has_marker", "name"), &Animation::has_marker); + ClassDB::bind_method(D_METHOD("get_marker_at_time", "time"), &Animation::get_marker_at_time); + ClassDB::bind_method(D_METHOD("get_next_marker", "time"), &Animation::get_next_marker); + ClassDB::bind_method(D_METHOD("get_prev_marker", "time"), &Animation::get_prev_marker); + ClassDB::bind_method(D_METHOD("get_marker_time", "name"), &Animation::get_marker_time); + ClassDB::bind_method(D_METHOD("get_marker_names"), &Animation::get_marker_names); + ClassDB::bind_method(D_METHOD("get_marker_color", "name"), &Animation::get_marker_color); + ClassDB::bind_method(D_METHOD("set_marker_color", "name", "color"), &Animation::set_marker_color); + ClassDB::bind_method(D_METHOD("set_length", "time_sec"), &Animation::set_length); ClassDB::bind_method(D_METHOD("get_length"), &Animation::get_length); @@ -3902,6 +4052,7 @@ void Animation::_bind_methods() { ClassDB::bind_method(D_METHOD("clear"), &Animation::clear); ClassDB::bind_method(D_METHOD("copy_track", "track_idx", "to_animation"), &Animation::copy_track); + ClassDB::bind_method(D_METHOD("optimize", "allowed_velocity_err", "allowed_angular_err", "precision"), &Animation::optimize, DEFVAL(0.01), DEFVAL(0.01), DEFVAL(3)); ClassDB::bind_method(D_METHOD("compress", "page_size", "fps", "split_tolerance"), &Animation::compress, DEFVAL(8192), DEFVAL(120), DEFVAL(4.0)); ClassDB::bind_method(D_METHOD("is_capture_included"), &Animation::is_capture_included); @@ -4804,9 +4955,9 @@ void Animation::compress(uint32_t p_page_size, uint32_t p_fps, float p_split_tol continue; // This track is exhausted (all keys were added already), don't consider. } } - - uint32_t key_frame = double(track_get_key_time(uncomp_track, time_tracks[i].key_index)) / frame_len; - + double key_time = track_get_key_time(uncomp_track, time_tracks[i].key_index); + double result = key_time / frame_len; + uint32_t key_frame = Math::fast_ftoi(result); if (time_tracks[i].needs_start_frame && key_frame > base_page_frame) { start_frame = true; best_frame = base_page_frame; diff --git a/scene/resources/animation.h b/scene/resources/animation.h index 0c29790ea4..618dc9ca17 100644 --- a/scene/resources/animation.h +++ b/scene/resources/animation.h @@ -237,6 +237,20 @@ private: } }; + /* Marker */ + + struct MarkerKey { + double time; + StringName name; + MarkerKey(double p_time, const StringName &p_name) : + time(p_time), name(p_name) {} + MarkerKey() = default; + }; + + Vector<MarkerKey> marker_names; // time -> name + HashMap<StringName, double> marker_times; // name -> time + HashMap<StringName, Color> marker_colors; // name -> color + Vector<Track *> tracks; template <typename T> @@ -245,6 +259,8 @@ private: template <typename T, typename V> int _insert(double p_time, T &p_keys, const V &p_value); + int _marker_insert(double p_time, Vector<MarkerKey> &p_keys, const MarkerKey &p_value); + template <typename K> inline int _find(const Vector<K> &p_keys, double p_time, bool p_backward = false, bool p_limit = false) const; @@ -501,6 +517,17 @@ public: void track_get_key_indices_in_range(int p_track, double p_time, double p_delta, List<int> *p_indices, Animation::LoopedFlag p_looped_flag = Animation::LOOPED_FLAG_NONE) const; + void add_marker(const StringName &p_name, double p_time); + void remove_marker(const StringName &p_name); + bool has_marker(const StringName &p_name) const; + StringName get_marker_at_time(double p_time) const; + StringName get_next_marker(double p_time) const; + StringName get_prev_marker(double p_time) const; + double get_marker_time(const StringName &p_time) const; + PackedStringArray get_marker_names() const; + Color get_marker_color(const StringName &p_name) const; + void set_marker_color(const StringName &p_name, const Color &p_color); + void set_length(real_t p_length); real_t get_length() const; diff --git a/scene/resources/audio_stream_wav.cpp b/scene/resources/audio_stream_wav.cpp index f9787dde2e..539001bf25 100644 --- a/scene/resources/audio_stream_wav.cpp +++ b/scene/resources/audio_stream_wav.cpp @@ -624,7 +624,7 @@ Error AudioStreamWAV::save_to_wav(const String &p_path) { } String file_path = p_path; - if (!(file_path.substr(file_path.length() - 4, 4) == ".wav")) { + if (file_path.substr(file_path.length() - 4, 4).to_lower() != ".wav") { file_path += ".wav"; } diff --git a/scene/resources/camera_attributes.cpp b/scene/resources/camera_attributes.cpp index 3a021720c6..3a0c207a5d 100644 --- a/scene/resources/camera_attributes.cpp +++ b/scene/resources/camera_attributes.cpp @@ -487,7 +487,7 @@ void CameraAttributesPhysical::_bind_methods() { ADD_GROUP("Auto Exposure", "auto_exposure_"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_min_exposure_value", PROPERTY_HINT_RANGE, "-16.0,16.0,0.01,or_greater,suffix:EV100"), "set_auto_exposure_min_exposure_value", "get_auto_exposure_min_exposure_value"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_max_exposure_value", PROPERTY_HINT_RANGE, "-16.0,16.0,0.01,or_greater,suffix:EV100"), "set_auto_exposure_max_exposure_value", "get_auto_exposure_max_exposure_value"); -}; +} CameraAttributesPhysical::CameraAttributesPhysical() { _update_exposure(); diff --git a/scene/resources/camera_texture.cpp b/scene/resources/camera_texture.cpp index b575a099ed..b219f89e59 100644 --- a/scene/resources/camera_texture.cpp +++ b/scene/resources/camera_texture.cpp @@ -47,6 +47,11 @@ void CameraTexture::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "camera_is_active"), "set_camera_active", "get_camera_active"); } +void CameraTexture::_on_format_changed() { + // FIXME: `emit_changed` is more appropriate, but causes errors for some reason. + callable_mp((Resource *)this, &Resource::emit_changed).call_deferred(); +} + int CameraTexture::get_width() const { Ref<CameraFeed> feed = CameraServer::get_singleton()->get_feed_by_id(camera_feed_id); if (feed.is_valid()) { @@ -82,13 +87,26 @@ RID CameraTexture::get_rid() const { } Ref<Image> CameraTexture::get_image() const { - // not (yet) supported - return Ref<Image>(); + return RenderingServer::get_singleton()->texture_2d_get(get_rid()); } void CameraTexture::set_camera_feed_id(int p_new_id) { + Ref<CameraFeed> feed = CameraServer::get_singleton()->get_feed_by_id(camera_feed_id); + if (feed.is_valid()) { + if (feed->is_connected("format_changed", callable_mp(this, &CameraTexture::_on_format_changed))) { + feed->disconnect("format_changed", callable_mp(this, &CameraTexture::_on_format_changed)); + } + } + camera_feed_id = p_new_id; + + feed = CameraServer::get_singleton()->get_feed_by_id(camera_feed_id); + if (feed.is_valid()) { + feed->connect("format_changed", callable_mp(this, &CameraTexture::_on_format_changed)); + } + notify_property_list_changed(); + callable_mp((Resource *)this, &Resource::emit_changed).call_deferred(); } int CameraTexture::get_camera_feed_id() const { @@ -98,6 +116,7 @@ int CameraTexture::get_camera_feed_id() const { void CameraTexture::set_which_feed(CameraServer::FeedImage p_which) { which_feed = p_which; notify_property_list_changed(); + callable_mp((Resource *)this, &Resource::emit_changed).call_deferred(); } CameraServer::FeedImage CameraTexture::get_which_feed() const { @@ -109,6 +128,7 @@ void CameraTexture::set_camera_active(bool p_active) { if (feed.is_valid()) { feed->set_active(p_active); notify_property_list_changed(); + callable_mp((Resource *)this, &Resource::emit_changed).call_deferred(); } } diff --git a/scene/resources/camera_texture.h b/scene/resources/camera_texture.h index 521121f9ea..dd216a72d6 100644 --- a/scene/resources/camera_texture.h +++ b/scene/resources/camera_texture.h @@ -43,6 +43,7 @@ private: protected: static void _bind_methods(); + void _on_format_changed(); public: virtual int get_width() const override; diff --git a/scene/resources/canvas_item_material.cpp b/scene/resources/canvas_item_material.cpp index 76e99aca92..6f43106ea9 100644 --- a/scene/resources/canvas_item_material.cpp +++ b/scene/resources/canvas_item_material.cpp @@ -274,6 +274,8 @@ void CanvasItemMaterial::_bind_methods() { CanvasItemMaterial::CanvasItemMaterial() : element(this) { + _set_material(RS::get_singleton()->material_create()); + set_particles_anim_h_frames(1); set_particles_anim_v_frames(1); set_particles_anim_loop(false); diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp index 8926eb1d51..91d3757590 100644 --- a/scene/resources/curve.cpp +++ b/scene/resources/curve.cpp @@ -479,6 +479,9 @@ void Curve::set_bake_resolution(int p_resolution) { } real_t Curve::sample_baked(real_t p_offset) const { + // Make sure that p_offset is finite. + ERR_FAIL_COND_V_MSG(!Math::is_finite(p_offset), 0, "Offset is non-finite"); + if (_baked_cache_dirty) { // Last-second bake if not done already const_cast<Curve *>(this)->bake(); @@ -981,6 +984,9 @@ Transform2D Curve2D::_sample_posture(Interval p_interval) const { } Vector2 Curve2D::sample_baked(real_t p_offset, bool p_cubic) const { + // Make sure that p_offset is finite. + ERR_FAIL_COND_V_MSG(!Math::is_finite(p_offset), Vector2(), "Offset is non-finite"); + if (baked_cache_dirty) { _bake(); } @@ -1000,6 +1006,9 @@ Vector2 Curve2D::sample_baked(real_t p_offset, bool p_cubic) const { } Transform2D Curve2D::sample_baked_with_rotation(real_t p_offset, bool p_cubic) const { + // Make sure that p_offset is finite. + ERR_FAIL_COND_V_MSG(!Math::is_finite(p_offset), Transform2D(), "Offset is non-finite"); + if (baked_cache_dirty) { _bake(); } @@ -1454,6 +1463,9 @@ void Curve3D::_remove_point(int p_index) { void Curve3D::remove_point(int p_index) { _remove_point(p_index); + if (closed && points.size() < 2) { + set_closed(false); + } notify_property_list_changed(); } @@ -1470,15 +1482,25 @@ Vector3 Curve3D::sample(int p_index, real_t p_offset) const { ERR_FAIL_COND_V(pc == 0, Vector3()); if (p_index >= pc - 1) { - return points[pc - 1].position; + if (!closed) { + return points[pc - 1].position; + } else { + p_index = pc - 1; + } } else if (p_index < 0) { return points[0].position; } Vector3 p0 = points[p_index].position; Vector3 p1 = p0 + points[p_index].out; - Vector3 p3 = points[p_index + 1].position; - Vector3 p2 = p3 + points[p_index + 1].in; + Vector3 p3, p2; + if (!closed || p_index < pc - 1) { + p3 = points[p_index + 1].position; + p2 = p3 + points[p_index + 1].in; + } else { + p3 = points[0].position; + p2 = p3 + points[0].in; + } return p0.bezier_interpolate(p1, p2, p3, p_offset); } @@ -1596,13 +1618,16 @@ void Curve3D::_bake() const { { Vector<RBMap<real_t, Vector3>> midpoints = _tessellate_even_length(10, bake_interval); + const int num_intervals = closed ? points.size() : points.size() - 1; + #ifdef TOOLS_ENABLED - points_in_cache.resize(points.size()); + points_in_cache.resize(closed ? (points.size() + 1) : points.size()); points_in_cache.set(0, 0); #endif + // Point Count: Begins at 1 to account for the last point. int pc = 1; - for (int i = 0; i < points.size() - 1; i++) { + for (int i = 0; i < num_intervals; i++) { pc++; pc += midpoints[i].size(); #ifdef TOOLS_ENABLED @@ -1625,18 +1650,29 @@ void Curve3D::_bake() const { btw[0] = points[0].tilt; int pidx = 0; - for (int i = 0; i < points.size() - 1; i++) { + for (int i = 0; i < num_intervals; i++) { for (const KeyValue<real_t, Vector3> &E : midpoints[i]) { pidx++; bpw[pidx] = E.value; - bfw[pidx] = _calculate_tangent(points[i].position, points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position, E.key); - btw[pidx] = Math::lerp(points[i].tilt, points[i + 1].tilt, E.key); + if (!closed || i < num_intervals - 1) { + bfw[pidx] = _calculate_tangent(points[i].position, points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position, E.key); + btw[pidx] = Math::lerp(points[i].tilt, points[i + 1].tilt, E.key); + } else { + bfw[pidx] = _calculate_tangent(points[i].position, points[i].position + points[i].out, points[0].position + points[0].in, points[0].position, E.key); + btw[pidx] = Math::lerp(points[i].tilt, points[0].tilt, E.key); + } } pidx++; - bpw[pidx] = points[i + 1].position; - bfw[pidx] = _calculate_tangent(points[i].position, points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position, 1.0); - btw[pidx] = points[i + 1].tilt; + if (!closed || i < num_intervals - 1) { + bpw[pidx] = points[i + 1].position; + bfw[pidx] = _calculate_tangent(points[i].position, points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position, 1.0); + btw[pidx] = points[i + 1].tilt; + } else { + bpw[pidx] = points[0].position; + bfw[pidx] = _calculate_tangent(points[i].position, points[i].position + points[i].out, points[0].position + points[0].in, points[0].position, 1.0); + btw[pidx] = points[0].tilt; + } } // Recalculate the baked distances. @@ -1881,6 +1917,9 @@ Basis Curve3D::get_point_baked_posture(int p_index, bool p_apply_tilt) const { #endif Vector3 Curve3D::sample_baked(real_t p_offset, bool p_cubic) const { + // Make sure that p_offset is finite. + ERR_FAIL_COND_V_MSG(!Math::is_finite(p_offset), Vector3(), "Offset is non-finite"); + if (baked_cache_dirty) { _bake(); } @@ -1900,6 +1939,9 @@ Vector3 Curve3D::sample_baked(real_t p_offset, bool p_cubic) const { } Transform3D Curve3D::sample_baked_with_rotation(real_t p_offset, bool p_cubic, bool p_apply_tilt) const { + // Make sure that p_offset is finite. + ERR_FAIL_COND_V_MSG(!Math::is_finite(p_offset), Transform3D(), "Offset is non-finite"); + if (baked_cache_dirty) { _bake(); } @@ -1929,6 +1971,9 @@ Transform3D Curve3D::sample_baked_with_rotation(real_t p_offset, bool p_cubic, b } real_t Curve3D::sample_baked_tilt(real_t p_offset) const { + // Make sure that p_offset is finite. + ERR_FAIL_COND_V_MSG(!Math::is_finite(p_offset), 0, "Offset is non-finite"); + if (baked_cache_dirty) { _bake(); } @@ -1948,6 +1993,9 @@ real_t Curve3D::sample_baked_tilt(real_t p_offset) const { } Vector3 Curve3D::sample_baked_up_vector(real_t p_offset, bool p_apply_tilt) const { + // Make sure that p_offset is finite. + ERR_FAIL_COND_V_MSG(!Math::is_finite(p_offset), Vector3(0, 1, 0), "Offset is non-finite"); + if (baked_cache_dirty) { _bake(); } @@ -2075,6 +2123,20 @@ real_t Curve3D::get_closest_offset(const Vector3 &p_to_point) const { return nearest; } +void Curve3D::set_closed(bool p_closed) { + if (closed == p_closed) { + return; + } + + closed = p_closed; + mark_dirty(); + notify_property_list_changed(); +} + +bool Curve3D::is_closed() const { + return closed; +} + void Curve3D::set_bake_interval(real_t p_tolerance) { bake_interval = p_tolerance; mark_dirty(); @@ -2153,11 +2215,17 @@ PackedVector3Array Curve3D::tessellate(int p_max_stages, real_t p_tolerance) con } Vector<RBMap<real_t, Vector3>> midpoints; - midpoints.resize(points.size() - 1); + const int num_intervals = closed ? points.size() : points.size() - 1; + midpoints.resize(num_intervals); + // Point Count: Begins at 1 to account for the last point. int pc = 1; - for (int i = 0; i < points.size() - 1; i++) { - _bake_segment3d(midpoints.write[i], 0, 1, points[i].position, points[i].out, points[i + 1].position, points[i + 1].in, 0, p_max_stages, p_tolerance); + for (int i = 0; i < num_intervals; i++) { + if (!closed || i < num_intervals - 1) { + _bake_segment3d(midpoints.write[i], 0, 1, points[i].position, points[i].out, points[i + 1].position, points[i + 1].in, 0, p_max_stages, p_tolerance); + } else { + _bake_segment3d(midpoints.write[i], 0, 1, points[i].position, points[i].out, points[0].position, points[0].in, 0, p_max_stages, p_tolerance); + } pc++; pc += midpoints[i].size(); } @@ -2167,14 +2235,18 @@ PackedVector3Array Curve3D::tessellate(int p_max_stages, real_t p_tolerance) con bpw[0] = points[0].position; int pidx = 0; - for (int i = 0; i < points.size() - 1; i++) { + for (int i = 0; i < num_intervals; i++) { for (const KeyValue<real_t, Vector3> &E : midpoints[i]) { pidx++; bpw[pidx] = E.value; } pidx++; - bpw[pidx] = points[i + 1].position; + if (!closed || i < num_intervals - 1) { + bpw[pidx] = points[i + 1].position; + } else { + bpw[pidx] = points[0].position; + } } return tess; @@ -2184,10 +2256,15 @@ Vector<RBMap<real_t, Vector3>> Curve3D::_tessellate_even_length(int p_max_stages Vector<RBMap<real_t, Vector3>> midpoints; ERR_FAIL_COND_V_MSG(points.size() < 2, midpoints, "Curve must have at least 2 control point"); - midpoints.resize(points.size() - 1); + const int num_intervals = closed ? points.size() : points.size() - 1; + midpoints.resize(num_intervals); - for (int i = 0; i < points.size() - 1; i++) { - _bake_segment3d_even_length(midpoints.write[i], 0, 1, points[i].position, points[i].out, points[i + 1].position, points[i + 1].in, 0, p_max_stages, p_length); + for (int i = 0; i < num_intervals; i++) { + if (!closed || i < num_intervals - 1) { + _bake_segment3d_even_length(midpoints.write[i], 0, 1, points[i].position, points[i].out, points[i + 1].position, points[i + 1].in, 0, p_max_stages, p_length); + } else { + _bake_segment3d_even_length(midpoints.write[i], 0, 1, points[i].position, points[i].out, points[0].position, points[0].in, 0, p_max_stages, p_length); + } } return midpoints; } @@ -2200,8 +2277,10 @@ PackedVector3Array Curve3D::tessellate_even_length(int p_max_stages, real_t p_le return tess; } + const int num_intervals = closed ? points.size() : points.size() - 1; + // Point Count: Begins at 1 to account for the last point. int pc = 1; - for (int i = 0; i < points.size() - 1; i++) { + for (int i = 0; i < num_intervals; i++) { pc++; pc += midpoints[i].size(); } @@ -2211,14 +2290,18 @@ PackedVector3Array Curve3D::tessellate_even_length(int p_max_stages, real_t p_le bpw[0] = points[0].position; int pidx = 0; - for (int i = 0; i < points.size() - 1; i++) { + for (int i = 0; i < num_intervals; i++) { for (const KeyValue<real_t, Vector3> &E : midpoints[i]) { pidx++; bpw[pidx] = E.value; } pidx++; - bpw[pidx] = points[i + 1].position; + if (!closed || i < num_intervals - 1) { + bpw[pidx] = points[i + 1].position; + } else { + bpw[pidx] = points[0].position; + } } return tess; @@ -2274,13 +2357,13 @@ void Curve3D::_get_property_list(List<PropertyInfo> *p_list) const { pi.usage &= ~PROPERTY_USAGE_STORAGE; p_list->push_back(pi); - if (i != 0) { + if (closed || i != 0) { pi = PropertyInfo(Variant::VECTOR3, vformat("point_%d/in", i)); pi.usage &= ~PROPERTY_USAGE_STORAGE; p_list->push_back(pi); } - if (i != points.size() - 1) { + if (closed || i != points.size() - 1) { pi = PropertyInfo(Variant::VECTOR3, vformat("point_%d/out", i)); pi.usage &= ~PROPERTY_USAGE_STORAGE; p_list->push_back(pi); @@ -2308,6 +2391,8 @@ void Curve3D::_bind_methods() { ClassDB::bind_method(D_METHOD("clear_points"), &Curve3D::clear_points); ClassDB::bind_method(D_METHOD("sample", "idx", "t"), &Curve3D::sample); ClassDB::bind_method(D_METHOD("samplef", "fofs"), &Curve3D::samplef); + ClassDB::bind_method(D_METHOD("set_closed", "closed"), &Curve3D::set_closed); + ClassDB::bind_method(D_METHOD("is_closed"), &Curve3D::is_closed); //ClassDB::bind_method(D_METHOD("bake","subdivs"),&Curve3D::bake,DEFVAL(10)); ClassDB::bind_method(D_METHOD("set_bake_interval", "distance"), &Curve3D::set_bake_interval); ClassDB::bind_method(D_METHOD("get_bake_interval"), &Curve3D::get_bake_interval); @@ -2329,6 +2414,8 @@ void Curve3D::_bind_methods() { ClassDB::bind_method(D_METHOD("_get_data"), &Curve3D::_get_data); ClassDB::bind_method(D_METHOD("_set_data", "data"), &Curve3D::_set_data); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "closed"), "set_closed", "is_closed"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bake_interval", PROPERTY_HINT_RANGE, "0.01,512,0.01"), "set_bake_interval", "get_bake_interval"); ADD_PROPERTY(PropertyInfo(Variant::INT, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); ADD_ARRAY_COUNT("Points", "point_count", "set_point_count", "get_point_count", "point_"); diff --git a/scene/resources/curve.h b/scene/resources/curve.h index 6da337a93f..154d91e23b 100644 --- a/scene/resources/curve.h +++ b/scene/resources/curve.h @@ -264,6 +264,8 @@ class Curve3D : public Resource { mutable Vector<size_t> points_in_cache; #endif + bool closed = false; + mutable bool baked_cache_dirty = false; mutable PackedVector3Array baked_point_cache; mutable Vector<real_t> baked_tilt_cache; @@ -330,6 +332,8 @@ public: Vector3 sample(int p_index, real_t p_offset) const; Vector3 samplef(real_t p_findex) const; + void set_closed(bool p_closed); + bool is_closed() const; void set_bake_interval(real_t p_tolerance); real_t get_bake_interval() const; void set_up_vector_enabled(bool p_enable); diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index f8c70c3002..b5e23e9832 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -130,10 +130,7 @@ int Environment::get_canvas_max_layer() const { void Environment::set_camera_feed_id(int p_id) { bg_camera_feed_id = p_id; -// FIXME: Disabled during Vulkan refactoring, should be ported. -#if 0 - RS::get_singleton()->environment_set_camera_feed_id(environment, camera_feed_id); -#endif + RS::get_singleton()->environment_set_camera_feed_id(environment, bg_camera_feed_id); } int Environment::get_camera_feed_id() const { diff --git a/scene/resources/external_texture.cpp b/scene/resources/external_texture.cpp index 0552bbd081..c8b714372a 100644 --- a/scene/resources/external_texture.cpp +++ b/scene/resources/external_texture.cpp @@ -39,12 +39,14 @@ void ExternalTexture::_bind_methods() { } uint64_t ExternalTexture::get_external_texture_id() const { + _ensure_created(); return RenderingServer::get_singleton()->texture_get_native_handle(texture); } void ExternalTexture::set_size(const Size2 &p_size) { if (p_size.width > 0 && p_size.height > 0 && p_size != size) { size = p_size; + _ensure_created(); RenderingServer::get_singleton()->texture_external_update(texture, size.width, size.height, external_buffer); emit_changed(); } @@ -57,6 +59,7 @@ Size2 ExternalTexture::get_size() const { void ExternalTexture::set_external_buffer_id(uint64_t p_external_buffer) { if (p_external_buffer != external_buffer) { external_buffer = p_external_buffer; + _ensure_created(); RenderingServer::get_singleton()->texture_external_update(texture, size.width, size.height, external_buffer); } } @@ -74,11 +77,29 @@ bool ExternalTexture::has_alpha() const { } RID ExternalTexture::get_rid() const { + if (!texture.is_valid()) { + texture = RenderingServer::get_singleton()->texture_2d_placeholder_create(); + using_placeholder = true; + } return texture; } +void ExternalTexture::_ensure_created() const { + if (texture.is_valid() && !using_placeholder) { + return; + } + + RID new_texture = RenderingServer::get_singleton()->texture_external_create(size.width, size.height); + if (using_placeholder) { + DEV_ASSERT(texture.is_valid()); + RenderingServer::get_singleton()->texture_replace(texture, new_texture); + using_placeholder = false; + } else { + texture = new_texture; + } +} + ExternalTexture::ExternalTexture() { - texture = RenderingServer::get_singleton()->texture_external_create(size.width, size.height); } ExternalTexture::~ExternalTexture() { diff --git a/scene/resources/external_texture.h b/scene/resources/external_texture.h index 96bcd8d0fe..cd60bcc030 100644 --- a/scene/resources/external_texture.h +++ b/scene/resources/external_texture.h @@ -38,10 +38,13 @@ class ExternalTexture : public Texture2D { GDCLASS(ExternalTexture, Texture2D); private: - RID texture; + mutable RID texture; + mutable bool using_placeholder = false; Size2 size = Size2(256, 256); uint64_t external_buffer = 0; + void _ensure_created() const; + protected: static void _bind_methods(); diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index 5e4136f449..ae70443e6a 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -647,13 +647,13 @@ void FontFile::_convert_packed_8bit(Ref<Image> &p_source, int p_page, int p_sz) wa[ofs_dst + 1] = r[ofs_src + 3]; } } - Ref<Image> img_r = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_r)); + Ref<Image> img_r = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_r)); set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 0, img_r); - Ref<Image> img_g = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_g)); + Ref<Image> img_g = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_g)); set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 1, img_g); - Ref<Image> img_b = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_b)); + Ref<Image> img_b = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_b)); set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 2, img_b); - Ref<Image> img_a = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_a)); + Ref<Image> img_a = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_a)); set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 3, img_a); } @@ -738,22 +738,22 @@ void FontFile::_convert_packed_4bit(Ref<Image> &p_source, int p_page, int p_sz) } } } - Ref<Image> img_r = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_r)); + Ref<Image> img_r = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_r)); set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 0, img_r); - Ref<Image> img_g = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_g)); + Ref<Image> img_g = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_g)); set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 1, img_g); - Ref<Image> img_b = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_b)); + Ref<Image> img_b = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_b)); set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 2, img_b); - Ref<Image> img_a = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_a)); + Ref<Image> img_a = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_a)); set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 3, img_a); - Ref<Image> img_ro = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_ro)); + Ref<Image> img_ro = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_ro)); set_texture_image(0, Vector2i(p_sz, 1), p_page * 4 + 0, img_ro); - Ref<Image> img_go = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_go)); + Ref<Image> img_go = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_go)); set_texture_image(0, Vector2i(p_sz, 1), p_page * 4 + 1, img_go); - Ref<Image> img_bo = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_bo)); + Ref<Image> img_bo = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_bo)); set_texture_image(0, Vector2i(p_sz, 1), p_page * 4 + 2, img_bo); - Ref<Image> img_ao = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_ao)); + Ref<Image> img_ao = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_ao)); set_texture_image(0, Vector2i(p_sz, 1), p_page * 4 + 3, img_ao); } @@ -806,10 +806,10 @@ void FontFile::_convert_rgba_4bit(Ref<Image> &p_source, int p_page, int p_sz) { } } } - Ref<Image> img_g = memnew(Image(w, h, 0, Image::FORMAT_RGBA8, imgdata_g)); + Ref<Image> img_g = memnew(Image(w, h, false, Image::FORMAT_RGBA8, imgdata_g)); set_texture_image(0, Vector2i(p_sz, 0), p_page, img_g); - Ref<Image> img_o = memnew(Image(w, h, 0, Image::FORMAT_RGBA8, imgdata_o)); + Ref<Image> img_o = memnew(Image(w, h, false, Image::FORMAT_RGBA8, imgdata_o)); set_texture_image(0, Vector2i(p_sz, 1), p_page, img_o); } @@ -838,7 +838,7 @@ void FontFile::_convert_mono_8bit(Ref<Image> &p_source, int p_page, int p_ch, in wg[ofs_dst + 1] = r[ofs_src + p_ch]; } } - Ref<Image> img_g = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_g)); + Ref<Image> img_g = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_g)); set_texture_image(0, Vector2i(p_sz, p_ol), p_page, img_g); } @@ -878,10 +878,10 @@ void FontFile::_convert_mono_4bit(Ref<Image> &p_source, int p_page, int p_ch, in } } } - Ref<Image> img_g = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_g)); + Ref<Image> img_g = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_g)); set_texture_image(0, Vector2i(p_sz, 0), p_page, img_g); - Ref<Image> img_o = memnew(Image(w, h, 0, Image::FORMAT_LA8, imgdata_o)); + Ref<Image> img_o = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_o)); set_texture_image(0, Vector2i(p_sz, p_ol), p_page, img_o); } @@ -1734,7 +1734,7 @@ Error FontFile::_load_bitmap_font(const String &p_path, List<String> *r_image_fi while (true) { String line = f->get_line(); - int delimiter = line.find(" "); + int delimiter = line.find_char(' '); String type = line.substr(0, delimiter); int pos = delimiter + 1; HashMap<String, String> keys; @@ -1744,7 +1744,7 @@ Error FontFile::_load_bitmap_font(const String &p_path, List<String> *r_image_fi } while (pos < line.size()) { - int eq = line.find("=", pos); + int eq = line.find_char('=', pos); if (eq == -1) { break; } @@ -1752,14 +1752,14 @@ Error FontFile::_load_bitmap_font(const String &p_path, List<String> *r_image_fi int end = -1; String value; if (line[eq + 1] == '"') { - end = line.find("\"", eq + 2); + end = line.find_char('"', eq + 2); if (end == -1) { break; } value = line.substr(eq + 2, end - 1 - eq - 1); pos = end + 1; } else { - end = line.find(" ", eq + 1); + end = line.find_char(' ', eq + 1); if (end == -1) { end = line.size(); } diff --git a/scene/resources/gradient_texture.cpp b/scene/resources/gradient_texture.cpp index 6ec9422d2d..2b0e455efb 100644 --- a/scene/resources/gradient_texture.cpp +++ b/scene/resources/gradient_texture.cpp @@ -85,7 +85,7 @@ void GradientTexture1D::_queue_update() { callable_mp(this, &GradientTexture1D::update_now).call_deferred(); } -void GradientTexture1D::_update() { +void GradientTexture1D::_update() const { update_pending = false; if (gradient.is_null()) { @@ -172,14 +172,14 @@ RID GradientTexture1D::get_rid() const { } Ref<Image> GradientTexture1D::get_image() const { - const_cast<GradientTexture1D *>(this)->update_now(); + update_now(); if (!texture.is_valid()) { return Ref<Image>(); } return RenderingServer::get_singleton()->texture_2d_get(texture); } -void GradientTexture1D::update_now() { +void GradientTexture1D::update_now() const { if (update_pending) { _update(); } @@ -225,7 +225,7 @@ void GradientTexture2D::_queue_update() { callable_mp(this, &GradientTexture2D::update_now).call_deferred(); } -void GradientTexture2D::_update() { +void GradientTexture2D::_update() const { update_pending = false; if (gradient.is_null()) { @@ -405,14 +405,14 @@ RID GradientTexture2D::get_rid() const { } Ref<Image> GradientTexture2D::get_image() const { - const_cast<GradientTexture2D *>(this)->update_now(); + update_now(); if (!texture.is_valid()) { return Ref<Image>(); } return RenderingServer::get_singleton()->texture_2d_get(texture); } -void GradientTexture2D::update_now() { +void GradientTexture2D::update_now() const { if (update_pending) { _update(); } diff --git a/scene/resources/gradient_texture.h b/scene/resources/gradient_texture.h index 761e8d995b..764e5e6645 100644 --- a/scene/resources/gradient_texture.h +++ b/scene/resources/gradient_texture.h @@ -38,13 +38,13 @@ class GradientTexture1D : public Texture2D { private: Ref<Gradient> gradient; - bool update_pending = false; + mutable bool update_pending = false; mutable RID texture; int width = 256; bool use_hdr = false; void _queue_update(); - void _update(); + void _update() const; protected: static void _bind_methods(); @@ -64,7 +64,7 @@ public: virtual bool has_alpha() const override { return true; } virtual Ref<Image> get_image() const override; - void update_now(); + void update_now() const; GradientTexture1D(); virtual ~GradientTexture1D(); @@ -102,9 +102,9 @@ private: float _get_gradient_offset_at(int x, int y) const; - bool update_pending = false; + mutable bool update_pending = false; void _queue_update(); - void _update(); + void _update() const; protected: static void _bind_methods(); @@ -134,7 +134,7 @@ public: virtual RID get_rid() const override; virtual bool has_alpha() const override { return true; } virtual Ref<Image> get_image() const override; - void update_now(); + void update_now() const; GradientTexture2D(); virtual ~GradientTexture2D(); diff --git a/scene/resources/immediate_mesh.cpp b/scene/resources/immediate_mesh.cpp index 907c0ab4ca..072542f0ad 100644 --- a/scene/resources/immediate_mesh.cpp +++ b/scene/resources/immediate_mesh.cpp @@ -312,6 +312,8 @@ void ImmediateMesh::surface_end() { uses_uv2s = false; surface_active = false; + + emit_changed(); } void ImmediateMesh::clear_surfaces() { diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 927e76e4b2..ecc1982aa5 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -46,11 +46,15 @@ void Material::set_next_pass(const Ref<Material> &p_pass) { } next_pass = p_pass; - RID next_pass_rid; - if (next_pass.is_valid()) { - next_pass_rid = next_pass->get_rid(); + + if (material.is_valid()) { + RID next_pass_rid; + if (next_pass.is_valid()) { + next_pass_rid = next_pass->get_rid(); + } + + RS::get_singleton()->material_set_next_pass(material, next_pass_rid); } - RS::get_singleton()->material_set_next_pass(material, next_pass_rid); } Ref<Material> Material::get_next_pass() const { @@ -61,7 +65,10 @@ void Material::set_render_priority(int p_priority) { ERR_FAIL_COND(p_priority < RENDER_PRIORITY_MIN); ERR_FAIL_COND(p_priority > RENDER_PRIORITY_MAX); render_priority = p_priority; - RS::get_singleton()->material_set_render_priority(material, p_priority); + + if (material.is_valid()) { + RS::get_singleton()->material_set_render_priority(material, p_priority); + } } int Material::get_render_priority() const { @@ -113,12 +120,12 @@ void Material::inspect_native_shader_code() { RID Material::get_shader_rid() const { RID ret; - GDVIRTUAL_REQUIRED_CALL(_get_shader_rid, ret); + GDVIRTUAL_CALL(_get_shader_rid, ret); return ret; } Shader::Mode Material::get_shader_mode() const { Shader::Mode ret = Shader::MODE_MAX; - GDVIRTUAL_REQUIRED_CALL(_get_shader_mode, ret); + GDVIRTUAL_CALL(_get_shader_mode, ret); return ret; } @@ -165,13 +172,14 @@ void Material::_bind_methods() { } Material::Material() { - material = RenderingServer::get_singleton()->material_create(); render_priority = 0; } Material::~Material() { - ERR_FAIL_NULL(RenderingServer::get_singleton()); - RenderingServer::get_singleton()->free(material); + if (material.is_valid()) { + ERR_FAIL_NULL(RenderingServer::get_singleton()); + RenderingServer::get_singleton()->free(material); + } } /////////////////////////////////// @@ -374,14 +382,11 @@ void ShaderMaterial::_get_property_list(List<PropertyInfo> *p_list) const { bool ShaderMaterial::_property_can_revert(const StringName &p_name) const { if (shader.is_valid()) { - const StringName *pr = remap_cache.getptr(p_name); - if (pr) { - Variant default_value = RenderingServer::get_singleton()->shader_get_parameter_default(shader->get_rid(), *pr); - Variant current_value = get_shader_parameter(*pr); - return default_value.get_type() != Variant::NIL && default_value != current_value; - } else if (p_name == "render_priority" || p_name == "next_pass") { + if (remap_cache.has(p_name)) { return true; } + const String sname = p_name; + return sname == "render_priority" || sname == "next_pass"; } return false; } @@ -422,7 +427,11 @@ void ShaderMaterial::set_shader(const Ref<Shader> &p_shader) { } } - RS::get_singleton()->material_set_shader(_get_material(), rid); + RID material_rid = _get_material(); + if (material_rid.is_valid()) { + RS::get_singleton()->material_set_shader(material_rid, rid); + } + notify_property_list_changed(); //properties for shader exposed emit_changed(); } @@ -432,9 +441,12 @@ Ref<Shader> ShaderMaterial::get_shader() const { } void ShaderMaterial::set_shader_parameter(const StringName &p_param, const Variant &p_value) { + RID material_rid = _get_material(); if (p_value.get_type() == Variant::NIL) { param_cache.erase(p_param); - RS::get_singleton()->material_set_param(_get_material(), p_param, Variant()); + if (material_rid.is_valid()) { + RS::get_singleton()->material_set_param(material_rid, p_param, Variant()); + } } else { Variant *v = param_cache.getptr(p_param); if (!v) { @@ -449,12 +461,15 @@ void ShaderMaterial::set_shader_parameter(const StringName &p_param, const Varia RID tex_rid = p_value; if (tex_rid == RID()) { param_cache.erase(p_param); - RS::get_singleton()->material_set_param(_get_material(), p_param, Variant()); - } else { - RS::get_singleton()->material_set_param(_get_material(), p_param, tex_rid); + + if (material_rid.is_valid()) { + RS::get_singleton()->material_set_param(material_rid, p_param, Variant()); + } + } else if (material_rid.is_valid()) { + RS::get_singleton()->material_set_param(material_rid, p_param, tex_rid); } - } else { - RS::get_singleton()->material_set_param(_get_material(), p_param, p_value); + } else if (material_rid.is_valid()) { + RS::get_singleton()->material_set_param(material_rid, p_param, p_value); } } } @@ -471,6 +486,32 @@ void ShaderMaterial::_shader_changed() { notify_property_list_changed(); //update all properties } +void ShaderMaterial::_check_material_rid() const { + MutexLock lock(material_rid_mutex); + if (_get_material().is_null()) { + RID shader_rid = shader.is_valid() ? shader->get_rid() : RID(); + RID next_pass_rid; + if (get_next_pass().is_valid()) { + next_pass_rid = get_next_pass()->get_rid(); + } + + _set_material(RS::get_singleton()->material_create_from_shader(next_pass_rid, get_render_priority(), shader_rid)); + + for (KeyValue<StringName, Variant> param : param_cache) { + if (param.value.get_type() == Variant::OBJECT) { + RID tex_rid = param.value; + if (tex_rid.is_valid()) { + RS::get_singleton()->material_set_param(_get_material(), param.key, tex_rid); + } else { + RS::get_singleton()->material_set_param(_get_material(), param.key, Variant()); + } + } else { + RS::get_singleton()->material_set_param(_get_material(), param.key, param.value); + } + } + } +} + void ShaderMaterial::_bind_methods() { ClassDB::bind_method(D_METHOD("set_shader", "shader"), &ShaderMaterial::set_shader); ClassDB::bind_method(D_METHOD("get_shader"), &ShaderMaterial::get_shader); @@ -511,6 +552,12 @@ Shader::Mode ShaderMaterial::get_shader_mode() const { return Shader::MODE_SPATIAL; } } + +RID ShaderMaterial::get_rid() const { + _check_material_rid(); + return Material::get_rid(); +} + RID ShaderMaterial::get_shader_rid() const { if (shader.is_valid()) { return shader->get_rid(); @@ -520,6 +567,7 @@ RID ShaderMaterial::get_shader_rid() const { } ShaderMaterial::ShaderMaterial() { + // Material RID will be empty until it is required. } ShaderMaterial::~ShaderMaterial() { @@ -527,9 +575,8 @@ ShaderMaterial::~ShaderMaterial() { ///////////////////////////////// -Mutex BaseMaterial3D::material_mutex; -SelfList<BaseMaterial3D>::List BaseMaterial3D::dirty_materials; HashMap<BaseMaterial3D::MaterialKey, BaseMaterial3D::ShaderData, BaseMaterial3D::MaterialKey> BaseMaterial3D::shader_map; +Mutex BaseMaterial3D::shader_map_mutex; BaseMaterial3D::ShaderNames *BaseMaterial3D::shader_names = nullptr; void BaseMaterial3D::init_shaders() { @@ -619,22 +666,31 @@ HashMap<uint64_t, Ref<StandardMaterial3D>> BaseMaterial3D::materials_for_2d; void BaseMaterial3D::finish_shaders() { materials_for_2d.clear(); - dirty_materials.clear(); - memdelete(shader_names); shader_names = nullptr; } +void BaseMaterial3D::_mark_dirty() { + dirty = true; +} + void BaseMaterial3D::_update_shader() { + if (!dirty) { + return; + } + + dirty = false; + MaterialKey mk = _compute_key(); if (mk == current_key) { return; //no update required in the end } + MutexLock lock(shader_map_mutex); if (shader_map.has(current_key)) { shader_map[current_key].users--; if (shader_map[current_key].users == 0) { - //deallocate shader, as it's no longer in use + // Deallocate shader which is no longer in use. RS::get_singleton()->free(shader_map[current_key].shader); shader_map.erase(current_key); } @@ -643,8 +699,13 @@ void BaseMaterial3D::_update_shader() { current_key = mk; if (shader_map.has(mk)) { - RS::get_singleton()->material_set_shader(_get_material(), shader_map[mk].shader); + shader_rid = shader_map[mk].shader; shader_map[mk].users++; + + if (_get_material().is_valid()) { + RS::get_singleton()->material_set_shader(_get_material(), shader_rid); + } + return; } @@ -946,7 +1007,7 @@ uniform vec4 refraction_texture_channel; code += "uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_linear_mipmap;\n"; } - if (proximity_fade_enabled) { + if (features[FEATURE_REFRACTION] || proximity_fade_enabled) { code += "uniform sampler2D depth_texture : hint_depth_texture, repeat_disable, filter_nearest;\n"; } @@ -1627,7 +1688,14 @@ void fragment() {)"; } code += R"( float ref_amount = 1.0 - albedo.a * albedo_tex.a; - EMISSION += textureLod(screen_texture, ref_ofs, ROUGHNESS * 8.0).rgb * ref_amount * EXPOSURE; + + float refraction_depth_tex = textureLod(depth_texture, ref_ofs, 0.0).r; + vec4 refraction_view_pos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV * 2.0 - 1.0, refraction_depth_tex, 1.0); + refraction_view_pos.xyz /= refraction_view_pos.w; + + // If the depth buffer is lower then the model's Z position, use the refracted UV, otherwise use the normal screen UV. + // At low depth differences, decrease refraction intensity to avoid sudden discontinuities. + EMISSION += textureLod(screen_texture, mix(SCREEN_UV, ref_ofs, smoothstep(0.0, 1.0, VERTEX.z - refraction_view_pos.z)), ROUGHNESS * 8.0).rgb * ref_amount * EXPOSURE; ALBEDO *= 1.0 - ref_amount; // Force transparency on the material (required for refraction). ALPHA = 1.0; @@ -1649,10 +1717,10 @@ void fragment() {)"; if (proximity_fade_enabled) { code += R"( // Proximity Fade: Enabled - float depth_tex = textureLod(depth_texture, SCREEN_UV, 0.0).r; - vec4 world_pos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV * 2.0 - 1.0, depth_tex, 1.0); - world_pos.xyz /= world_pos.w; - ALPHA *= clamp(1.0 - smoothstep(world_pos.z + proximity_fade_distance, world_pos.z, VERTEX.z), 0.0, 1.0); + float proximity_depth_tex = textureLod(depth_texture, SCREEN_UV, 0.0).r; + vec4 proximity_view_pos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV * 2.0 - 1.0, proximity_depth_tex, 1.0); + proximity_view_pos.xyz /= proximity_view_pos.w; + ALPHA *= clamp(1.0 - smoothstep(proximity_view_pos.z + proximity_fade_distance, proximity_view_pos.z, VERTEX.z), 0.0, 1.0); )"; } @@ -1866,37 +1934,45 @@ void fragment() {)"; code += "}\n"; ShaderData shader_data; - shader_data.shader = RS::get_singleton()->shader_create(); + shader_data.shader = RS::get_singleton()->shader_create_from_code(code); shader_data.users = 1; - - RS::get_singleton()->shader_set_code(shader_data.shader, code); - shader_map[mk] = shader_data; + shader_rid = shader_data.shader; - RS::get_singleton()->material_set_shader(_get_material(), shader_data.shader); + if (_get_material().is_valid()) { + RS::get_singleton()->material_set_shader(_get_material(), shader_rid); + } } -void BaseMaterial3D::flush_changes() { - MutexLock lock(material_mutex); +void BaseMaterial3D::_check_material_rid() { + MutexLock lock(material_rid_mutex); + if (_get_material().is_null()) { + RID next_pass_rid; + if (get_next_pass().is_valid()) { + next_pass_rid = get_next_pass()->get_rid(); + } + + _set_material(RS::get_singleton()->material_create_from_shader(next_pass_rid, get_render_priority(), shader_rid)); + + for (KeyValue<StringName, Variant> param : pending_params) { + RS::get_singleton()->material_set_param(_get_material(), param.key, param.value); + } - while (dirty_materials.first()) { - dirty_materials.first()->self()->_update_shader(); - dirty_materials.first()->remove_from_list(); + pending_params.clear(); } } -void BaseMaterial3D::_queue_shader_change() { - MutexLock lock(material_mutex); - - if (_is_initialized() && !element.in_list()) { - dirty_materials.add(&element); +void BaseMaterial3D::_material_set_param(const StringName &p_name, const Variant &p_value) { + if (_get_material().is_valid()) { + RS::get_singleton()->material_set_param(_get_material(), p_name, p_value); + } else { + pending_params[p_name] = p_value; } } void BaseMaterial3D::set_albedo(const Color &p_albedo) { albedo = p_albedo; - - RS::get_singleton()->material_set_param(_get_material(), shader_names->albedo, p_albedo); + _material_set_param(shader_names->albedo, p_albedo); } Color BaseMaterial3D::get_albedo() const { @@ -1905,7 +1981,7 @@ Color BaseMaterial3D::get_albedo() const { void BaseMaterial3D::set_specular(float p_specular) { specular = p_specular; - RS::get_singleton()->material_set_param(_get_material(), shader_names->specular, p_specular); + _material_set_param(shader_names->specular, p_specular); } float BaseMaterial3D::get_specular() const { @@ -1914,7 +1990,7 @@ float BaseMaterial3D::get_specular() const { void BaseMaterial3D::set_roughness(float p_roughness) { roughness = p_roughness; - RS::get_singleton()->material_set_param(_get_material(), shader_names->roughness, p_roughness); + _material_set_param(shader_names->roughness, p_roughness); } float BaseMaterial3D::get_roughness() const { @@ -1923,7 +1999,7 @@ float BaseMaterial3D::get_roughness() const { void BaseMaterial3D::set_metallic(float p_metallic) { metallic = p_metallic; - RS::get_singleton()->material_set_param(_get_material(), shader_names->metallic, p_metallic); + _material_set_param(shader_names->metallic, p_metallic); } float BaseMaterial3D::get_metallic() const { @@ -1932,7 +2008,7 @@ float BaseMaterial3D::get_metallic() const { void BaseMaterial3D::set_emission(const Color &p_emission) { emission = p_emission; - RS::get_singleton()->material_set_param(_get_material(), shader_names->emission, p_emission); + _material_set_param(shader_names->emission, p_emission); } Color BaseMaterial3D::get_emission() const { @@ -1941,10 +2017,11 @@ Color BaseMaterial3D::get_emission() const { void BaseMaterial3D::set_emission_energy_multiplier(float p_emission_energy_multiplier) { emission_energy_multiplier = p_emission_energy_multiplier; + if (GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) { - RS::get_singleton()->material_set_param(_get_material(), shader_names->emission_energy, p_emission_energy_multiplier * emission_intensity); + _material_set_param(shader_names->emission_energy, p_emission_energy_multiplier * emission_intensity); } else { - RS::get_singleton()->material_set_param(_get_material(), shader_names->emission_energy, p_emission_energy_multiplier); + _material_set_param(shader_names->emission_energy, p_emission_energy_multiplier); } } @@ -1955,7 +2032,7 @@ float BaseMaterial3D::get_emission_energy_multiplier() const { void BaseMaterial3D::set_emission_intensity(float p_emission_intensity) { ERR_FAIL_COND_EDMSG(!GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units"), "Cannot set material emission intensity when Physical Light Units disabled."); emission_intensity = p_emission_intensity; - RS::get_singleton()->material_set_param(_get_material(), shader_names->emission_energy, emission_energy_multiplier * emission_intensity); + _material_set_param(shader_names->emission_energy, emission_energy_multiplier * emission_intensity); } float BaseMaterial3D::get_emission_intensity() const { @@ -1964,7 +2041,7 @@ float BaseMaterial3D::get_emission_intensity() const { void BaseMaterial3D::set_normal_scale(float p_normal_scale) { normal_scale = p_normal_scale; - RS::get_singleton()->material_set_param(_get_material(), shader_names->normal_scale, p_normal_scale); + _material_set_param(shader_names->normal_scale, p_normal_scale); } float BaseMaterial3D::get_normal_scale() const { @@ -1973,7 +2050,7 @@ float BaseMaterial3D::get_normal_scale() const { void BaseMaterial3D::set_rim(float p_rim) { rim = p_rim; - RS::get_singleton()->material_set_param(_get_material(), shader_names->rim, p_rim); + _material_set_param(shader_names->rim, p_rim); } float BaseMaterial3D::get_rim() const { @@ -1982,7 +2059,7 @@ float BaseMaterial3D::get_rim() const { void BaseMaterial3D::set_rim_tint(float p_rim_tint) { rim_tint = p_rim_tint; - RS::get_singleton()->material_set_param(_get_material(), shader_names->rim_tint, p_rim_tint); + _material_set_param(shader_names->rim_tint, p_rim_tint); } float BaseMaterial3D::get_rim_tint() const { @@ -1991,7 +2068,7 @@ float BaseMaterial3D::get_rim_tint() const { void BaseMaterial3D::set_ao_light_affect(float p_ao_light_affect) { ao_light_affect = p_ao_light_affect; - RS::get_singleton()->material_set_param(_get_material(), shader_names->ao_light_affect, p_ao_light_affect); + _material_set_param(shader_names->ao_light_affect, p_ao_light_affect); } float BaseMaterial3D::get_ao_light_affect() const { @@ -2000,7 +2077,7 @@ float BaseMaterial3D::get_ao_light_affect() const { void BaseMaterial3D::set_clearcoat(float p_clearcoat) { clearcoat = p_clearcoat; - RS::get_singleton()->material_set_param(_get_material(), shader_names->clearcoat, p_clearcoat); + _material_set_param(shader_names->clearcoat, p_clearcoat); } float BaseMaterial3D::get_clearcoat() const { @@ -2009,7 +2086,7 @@ float BaseMaterial3D::get_clearcoat() const { void BaseMaterial3D::set_clearcoat_roughness(float p_clearcoat_roughness) { clearcoat_roughness = p_clearcoat_roughness; - RS::get_singleton()->material_set_param(_get_material(), shader_names->clearcoat_roughness, p_clearcoat_roughness); + _material_set_param(shader_names->clearcoat_roughness, p_clearcoat_roughness); } float BaseMaterial3D::get_clearcoat_roughness() const { @@ -2018,7 +2095,7 @@ float BaseMaterial3D::get_clearcoat_roughness() const { void BaseMaterial3D::set_anisotropy(float p_anisotropy) { anisotropy = p_anisotropy; - RS::get_singleton()->material_set_param(_get_material(), shader_names->anisotropy, p_anisotropy); + _material_set_param(shader_names->anisotropy, p_anisotropy); } float BaseMaterial3D::get_anisotropy() const { @@ -2027,7 +2104,7 @@ float BaseMaterial3D::get_anisotropy() const { void BaseMaterial3D::set_heightmap_scale(float p_heightmap_scale) { heightmap_scale = p_heightmap_scale; - RS::get_singleton()->material_set_param(_get_material(), shader_names->heightmap_scale, p_heightmap_scale); + _material_set_param(shader_names->heightmap_scale, p_heightmap_scale); } float BaseMaterial3D::get_heightmap_scale() const { @@ -2036,7 +2113,7 @@ float BaseMaterial3D::get_heightmap_scale() const { void BaseMaterial3D::set_subsurface_scattering_strength(float p_subsurface_scattering_strength) { subsurface_scattering_strength = p_subsurface_scattering_strength; - RS::get_singleton()->material_set_param(_get_material(), shader_names->subsurface_scattering_strength, subsurface_scattering_strength); + _material_set_param(shader_names->subsurface_scattering_strength, subsurface_scattering_strength); } float BaseMaterial3D::get_subsurface_scattering_strength() const { @@ -2045,7 +2122,7 @@ float BaseMaterial3D::get_subsurface_scattering_strength() const { void BaseMaterial3D::set_transmittance_color(const Color &p_color) { transmittance_color = p_color; - RS::get_singleton()->material_set_param(_get_material(), shader_names->transmittance_color, p_color); + _material_set_param(shader_names->transmittance_color, p_color); } Color BaseMaterial3D::get_transmittance_color() const { @@ -2054,7 +2131,7 @@ Color BaseMaterial3D::get_transmittance_color() const { void BaseMaterial3D::set_transmittance_depth(float p_depth) { transmittance_depth = p_depth; - RS::get_singleton()->material_set_param(_get_material(), shader_names->transmittance_depth, p_depth); + _material_set_param(shader_names->transmittance_depth, p_depth); } float BaseMaterial3D::get_transmittance_depth() const { @@ -2063,7 +2140,7 @@ float BaseMaterial3D::get_transmittance_depth() const { void BaseMaterial3D::set_transmittance_boost(float p_boost) { transmittance_boost = p_boost; - RS::get_singleton()->material_set_param(_get_material(), shader_names->transmittance_boost, p_boost); + _material_set_param(shader_names->transmittance_boost, p_boost); } float BaseMaterial3D::get_transmittance_boost() const { @@ -2072,7 +2149,7 @@ float BaseMaterial3D::get_transmittance_boost() const { void BaseMaterial3D::set_backlight(const Color &p_backlight) { backlight = p_backlight; - RS::get_singleton()->material_set_param(_get_material(), shader_names->backlight, backlight); + _material_set_param(shader_names->backlight, backlight); } Color BaseMaterial3D::get_backlight() const { @@ -2081,7 +2158,7 @@ Color BaseMaterial3D::get_backlight() const { void BaseMaterial3D::set_refraction(float p_refraction) { refraction = p_refraction; - RS::get_singleton()->material_set_param(_get_material(), shader_names->refraction, refraction); + _material_set_param(shader_names->refraction, refraction); } float BaseMaterial3D::get_refraction() const { @@ -2094,7 +2171,7 @@ void BaseMaterial3D::set_detail_uv(DetailUV p_detail_uv) { } detail_uv = p_detail_uv; - _queue_shader_change(); + _mark_dirty(); } BaseMaterial3D::DetailUV BaseMaterial3D::get_detail_uv() const { @@ -2107,7 +2184,7 @@ void BaseMaterial3D::set_blend_mode(BlendMode p_mode) { } blend_mode = p_mode; - _queue_shader_change(); + _mark_dirty(); } BaseMaterial3D::BlendMode BaseMaterial3D::get_blend_mode() const { @@ -2116,7 +2193,7 @@ BaseMaterial3D::BlendMode BaseMaterial3D::get_blend_mode() const { void BaseMaterial3D::set_detail_blend_mode(BlendMode p_mode) { detail_blend_mode = p_mode; - _queue_shader_change(); + _mark_dirty(); } BaseMaterial3D::BlendMode BaseMaterial3D::get_detail_blend_mode() const { @@ -2129,7 +2206,7 @@ void BaseMaterial3D::set_transparency(Transparency p_transparency) { } transparency = p_transparency; - _queue_shader_change(); + _mark_dirty(); notify_property_list_changed(); } @@ -2143,7 +2220,7 @@ void BaseMaterial3D::set_alpha_antialiasing(AlphaAntiAliasing p_alpha_aa) { } alpha_antialiasing_mode = p_alpha_aa; - _queue_shader_change(); + _mark_dirty(); notify_property_list_changed(); } @@ -2157,7 +2234,7 @@ void BaseMaterial3D::set_shading_mode(ShadingMode p_shading_mode) { } shading_mode = p_shading_mode; - _queue_shader_change(); + _mark_dirty(); notify_property_list_changed(); } @@ -2171,7 +2248,7 @@ void BaseMaterial3D::set_depth_draw_mode(DepthDrawMode p_mode) { } depth_draw_mode = p_mode; - _queue_shader_change(); + _mark_dirty(); } BaseMaterial3D::DepthDrawMode BaseMaterial3D::get_depth_draw_mode() const { @@ -2184,7 +2261,7 @@ void BaseMaterial3D::set_cull_mode(CullMode p_mode) { } cull_mode = p_mode; - _queue_shader_change(); + _mark_dirty(); } BaseMaterial3D::CullMode BaseMaterial3D::get_cull_mode() const { @@ -2197,7 +2274,7 @@ void BaseMaterial3D::set_diffuse_mode(DiffuseMode p_mode) { } diffuse_mode = p_mode; - _queue_shader_change(); + _mark_dirty(); } BaseMaterial3D::DiffuseMode BaseMaterial3D::get_diffuse_mode() const { @@ -2210,7 +2287,7 @@ void BaseMaterial3D::set_specular_mode(SpecularMode p_mode) { } specular_mode = p_mode; - _queue_shader_change(); + _mark_dirty(); } BaseMaterial3D::SpecularMode BaseMaterial3D::get_specular_mode() const { @@ -2240,7 +2317,7 @@ void BaseMaterial3D::set_flag(Flags p_flag, bool p_enabled) { update_configuration_warning(); } - _queue_shader_change(); + _mark_dirty(); } bool BaseMaterial3D::get_flag(Flags p_flag) const { @@ -2256,7 +2333,7 @@ void BaseMaterial3D::set_feature(Feature p_feature, bool p_enabled) { features[p_feature] = p_enabled; notify_property_list_changed(); - _queue_shader_change(); + _mark_dirty(); } bool BaseMaterial3D::get_feature(Feature p_feature) const { @@ -2269,15 +2346,14 @@ void BaseMaterial3D::set_texture(TextureParam p_param, const Ref<Texture2D> &p_t textures[p_param] = p_texture; Variant rid = p_texture.is_valid() ? Variant(p_texture->get_rid()) : Variant(); - RS::get_singleton()->material_set_param(_get_material(), shader_names->texture_names[p_param], rid); + _material_set_param(shader_names->texture_names[p_param], rid); if (p_texture.is_valid() && p_param == TEXTURE_ALBEDO) { - RS::get_singleton()->material_set_param(_get_material(), shader_names->albedo_texture_size, - Vector2i(p_texture->get_width(), p_texture->get_height())); + _material_set_param(shader_names->albedo_texture_size, Vector2i(p_texture->get_width(), p_texture->get_height())); } notify_property_list_changed(); - _queue_shader_change(); + _mark_dirty(); } Ref<Texture2D> BaseMaterial3D::get_texture(TextureParam p_param) const { @@ -2297,7 +2373,7 @@ Ref<Texture2D> BaseMaterial3D::get_texture_by_name(const StringName &p_name) con void BaseMaterial3D::set_texture_filter(TextureFilter p_filter) { texture_filter = p_filter; - _queue_shader_change(); + _mark_dirty(); } BaseMaterial3D::TextureFilter BaseMaterial3D::get_texture_filter() const { @@ -2469,7 +2545,7 @@ void BaseMaterial3D::_validate_property(PropertyInfo &p_property) const { void BaseMaterial3D::set_point_size(float p_point_size) { point_size = p_point_size; - RS::get_singleton()->material_set_param(_get_material(), shader_names->point_size, p_point_size); + _material_set_param(shader_names->point_size, p_point_size); } float BaseMaterial3D::get_point_size() const { @@ -2478,7 +2554,7 @@ float BaseMaterial3D::get_point_size() const { void BaseMaterial3D::set_uv1_scale(const Vector3 &p_scale) { uv1_scale = p_scale; - RS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_scale, p_scale); + _material_set_param(shader_names->uv1_scale, p_scale); } Vector3 BaseMaterial3D::get_uv1_scale() const { @@ -2487,7 +2563,7 @@ Vector3 BaseMaterial3D::get_uv1_scale() const { void BaseMaterial3D::set_uv1_offset(const Vector3 &p_offset) { uv1_offset = p_offset; - RS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_offset, p_offset); + _material_set_param(shader_names->uv1_offset, p_offset); } Vector3 BaseMaterial3D::get_uv1_offset() const { @@ -2497,7 +2573,7 @@ Vector3 BaseMaterial3D::get_uv1_offset() const { void BaseMaterial3D::set_uv1_triplanar_blend_sharpness(float p_sharpness) { // Negative values or values higher than 150 can result in NaNs, leading to broken rendering. uv1_triplanar_sharpness = CLAMP(p_sharpness, 0.0, 150.0); - RS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_blend_sharpness, uv1_triplanar_sharpness); + _material_set_param(shader_names->uv1_blend_sharpness, uv1_triplanar_sharpness); } float BaseMaterial3D::get_uv1_triplanar_blend_sharpness() const { @@ -2506,7 +2582,7 @@ float BaseMaterial3D::get_uv1_triplanar_blend_sharpness() const { void BaseMaterial3D::set_uv2_scale(const Vector3 &p_scale) { uv2_scale = p_scale; - RS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_scale, p_scale); + _material_set_param(shader_names->uv2_scale, p_scale); } Vector3 BaseMaterial3D::get_uv2_scale() const { @@ -2515,7 +2591,7 @@ Vector3 BaseMaterial3D::get_uv2_scale() const { void BaseMaterial3D::set_uv2_offset(const Vector3 &p_offset) { uv2_offset = p_offset; - RS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_offset, p_offset); + _material_set_param(shader_names->uv2_offset, p_offset); } Vector3 BaseMaterial3D::get_uv2_offset() const { @@ -2525,7 +2601,7 @@ Vector3 BaseMaterial3D::get_uv2_offset() const { void BaseMaterial3D::set_uv2_triplanar_blend_sharpness(float p_sharpness) { // Negative values or values higher than 150 can result in NaNs, leading to broken rendering. uv2_triplanar_sharpness = CLAMP(p_sharpness, 0.0, 150.0); - RS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_blend_sharpness, uv2_triplanar_sharpness); + _material_set_param(shader_names->uv2_blend_sharpness, uv2_triplanar_sharpness); } float BaseMaterial3D::get_uv2_triplanar_blend_sharpness() const { @@ -2534,7 +2610,7 @@ float BaseMaterial3D::get_uv2_triplanar_blend_sharpness() const { void BaseMaterial3D::set_billboard_mode(BillboardMode p_mode) { billboard_mode = p_mode; - _queue_shader_change(); + _mark_dirty(); notify_property_list_changed(); } @@ -2544,7 +2620,7 @@ BaseMaterial3D::BillboardMode BaseMaterial3D::get_billboard_mode() const { void BaseMaterial3D::set_particles_anim_h_frames(int p_frames) { particles_anim_h_frames = p_frames; - RS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_h_frames, p_frames); + _material_set_param(shader_names->particles_anim_h_frames, p_frames); } int BaseMaterial3D::get_particles_anim_h_frames() const { @@ -2553,7 +2629,7 @@ int BaseMaterial3D::get_particles_anim_h_frames() const { void BaseMaterial3D::set_particles_anim_v_frames(int p_frames) { particles_anim_v_frames = p_frames; - RS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_v_frames, p_frames); + _material_set_param(shader_names->particles_anim_v_frames, p_frames); } int BaseMaterial3D::get_particles_anim_v_frames() const { @@ -2562,7 +2638,7 @@ int BaseMaterial3D::get_particles_anim_v_frames() const { void BaseMaterial3D::set_particles_anim_loop(bool p_loop) { particles_anim_loop = p_loop; - RS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_loop, particles_anim_loop); + _material_set_param(shader_names->particles_anim_loop, particles_anim_loop); } bool BaseMaterial3D::get_particles_anim_loop() const { @@ -2571,7 +2647,7 @@ bool BaseMaterial3D::get_particles_anim_loop() const { void BaseMaterial3D::set_heightmap_deep_parallax(bool p_enable) { deep_parallax = p_enable; - _queue_shader_change(); + _mark_dirty(); notify_property_list_changed(); } @@ -2581,7 +2657,7 @@ bool BaseMaterial3D::is_heightmap_deep_parallax_enabled() const { void BaseMaterial3D::set_heightmap_deep_parallax_min_layers(int p_layer) { deep_parallax_min_layers = p_layer; - RS::get_singleton()->material_set_param(_get_material(), shader_names->heightmap_min_layers, p_layer); + _material_set_param(shader_names->heightmap_min_layers, p_layer); } int BaseMaterial3D::get_heightmap_deep_parallax_min_layers() const { @@ -2590,7 +2666,7 @@ int BaseMaterial3D::get_heightmap_deep_parallax_min_layers() const { void BaseMaterial3D::set_heightmap_deep_parallax_max_layers(int p_layer) { deep_parallax_max_layers = p_layer; - RS::get_singleton()->material_set_param(_get_material(), shader_names->heightmap_max_layers, p_layer); + _material_set_param(shader_names->heightmap_max_layers, p_layer); } int BaseMaterial3D::get_heightmap_deep_parallax_max_layers() const { @@ -2599,7 +2675,7 @@ int BaseMaterial3D::get_heightmap_deep_parallax_max_layers() const { void BaseMaterial3D::set_heightmap_deep_parallax_flip_tangent(bool p_flip) { heightmap_parallax_flip_tangent = p_flip; - RS::get_singleton()->material_set_param(_get_material(), shader_names->heightmap_flip, Vector2(heightmap_parallax_flip_tangent ? -1 : 1, heightmap_parallax_flip_binormal ? -1 : 1)); + _material_set_param(shader_names->heightmap_flip, Vector2(heightmap_parallax_flip_tangent ? -1 : 1, heightmap_parallax_flip_binormal ? -1 : 1)); } bool BaseMaterial3D::get_heightmap_deep_parallax_flip_tangent() const { @@ -2608,7 +2684,7 @@ bool BaseMaterial3D::get_heightmap_deep_parallax_flip_tangent() const { void BaseMaterial3D::set_heightmap_deep_parallax_flip_binormal(bool p_flip) { heightmap_parallax_flip_binormal = p_flip; - RS::get_singleton()->material_set_param(_get_material(), shader_names->heightmap_flip, Vector2(heightmap_parallax_flip_tangent ? -1 : 1, heightmap_parallax_flip_binormal ? -1 : 1)); + _material_set_param(shader_names->heightmap_flip, Vector2(heightmap_parallax_flip_tangent ? -1 : 1, heightmap_parallax_flip_binormal ? -1 : 1)); } bool BaseMaterial3D::get_heightmap_deep_parallax_flip_binormal() const { @@ -2617,7 +2693,7 @@ bool BaseMaterial3D::get_heightmap_deep_parallax_flip_binormal() const { void BaseMaterial3D::set_grow_enabled(bool p_enable) { grow_enabled = p_enable; - _queue_shader_change(); + _mark_dirty(); notify_property_list_changed(); } @@ -2627,7 +2703,7 @@ bool BaseMaterial3D::is_grow_enabled() const { void BaseMaterial3D::set_alpha_scissor_threshold(float p_threshold) { alpha_scissor_threshold = p_threshold; - RS::get_singleton()->material_set_param(_get_material(), shader_names->alpha_scissor_threshold, p_threshold); + _material_set_param(shader_names->alpha_scissor_threshold, p_threshold); } float BaseMaterial3D::get_alpha_scissor_threshold() const { @@ -2636,7 +2712,7 @@ float BaseMaterial3D::get_alpha_scissor_threshold() const { void BaseMaterial3D::set_alpha_hash_scale(float p_scale) { alpha_hash_scale = p_scale; - RS::get_singleton()->material_set_param(_get_material(), shader_names->alpha_hash_scale, p_scale); + _material_set_param(shader_names->alpha_hash_scale, p_scale); } float BaseMaterial3D::get_alpha_hash_scale() const { @@ -2645,7 +2721,7 @@ float BaseMaterial3D::get_alpha_hash_scale() const { void BaseMaterial3D::set_alpha_antialiasing_edge(float p_edge) { alpha_antialiasing_edge = p_edge; - RS::get_singleton()->material_set_param(_get_material(), shader_names->alpha_antialiasing_edge, p_edge); + _material_set_param(shader_names->alpha_antialiasing_edge, p_edge); } float BaseMaterial3D::get_alpha_antialiasing_edge() const { @@ -2654,7 +2730,7 @@ float BaseMaterial3D::get_alpha_antialiasing_edge() const { void BaseMaterial3D::set_grow(float p_grow) { grow = p_grow; - RS::get_singleton()->material_set_param(_get_material(), shader_names->grow, p_grow); + _material_set_param(shader_names->grow, p_grow); } float BaseMaterial3D::get_grow() const { @@ -2676,7 +2752,7 @@ static Plane _get_texture_mask(BaseMaterial3D::TextureChannel p_channel) { void BaseMaterial3D::set_metallic_texture_channel(TextureChannel p_channel) { ERR_FAIL_INDEX(p_channel, 5); metallic_texture_channel = p_channel; - RS::get_singleton()->material_set_param(_get_material(), shader_names->metallic_texture_channel, _get_texture_mask(p_channel)); + _material_set_param(shader_names->metallic_texture_channel, _get_texture_mask(p_channel)); } BaseMaterial3D::TextureChannel BaseMaterial3D::get_metallic_texture_channel() const { @@ -2686,7 +2762,7 @@ BaseMaterial3D::TextureChannel BaseMaterial3D::get_metallic_texture_channel() co void BaseMaterial3D::set_roughness_texture_channel(TextureChannel p_channel) { ERR_FAIL_INDEX(p_channel, 5); roughness_texture_channel = p_channel; - _queue_shader_change(); + _mark_dirty(); } BaseMaterial3D::TextureChannel BaseMaterial3D::get_roughness_texture_channel() const { @@ -2696,7 +2772,7 @@ BaseMaterial3D::TextureChannel BaseMaterial3D::get_roughness_texture_channel() c void BaseMaterial3D::set_ao_texture_channel(TextureChannel p_channel) { ERR_FAIL_INDEX(p_channel, 5); ao_texture_channel = p_channel; - RS::get_singleton()->material_set_param(_get_material(), shader_names->ao_texture_channel, _get_texture_mask(p_channel)); + _material_set_param(shader_names->ao_texture_channel, _get_texture_mask(p_channel)); } BaseMaterial3D::TextureChannel BaseMaterial3D::get_ao_texture_channel() const { @@ -2706,7 +2782,7 @@ BaseMaterial3D::TextureChannel BaseMaterial3D::get_ao_texture_channel() const { void BaseMaterial3D::set_refraction_texture_channel(TextureChannel p_channel) { ERR_FAIL_INDEX(p_channel, 5); refraction_texture_channel = p_channel; - RS::get_singleton()->material_set_param(_get_material(), shader_names->refraction_texture_channel, _get_texture_mask(p_channel)); + _material_set_param(shader_names->refraction_texture_channel, _get_texture_mask(p_channel)); } BaseMaterial3D::TextureChannel BaseMaterial3D::get_refraction_texture_channel() const { @@ -2768,7 +2844,7 @@ void BaseMaterial3D::set_on_top_of_alpha() { void BaseMaterial3D::set_proximity_fade_enabled(bool p_enable) { proximity_fade_enabled = p_enable; - _queue_shader_change(); + _mark_dirty(); notify_property_list_changed(); } @@ -2778,7 +2854,7 @@ bool BaseMaterial3D::is_proximity_fade_enabled() const { void BaseMaterial3D::set_proximity_fade_distance(float p_distance) { proximity_fade_distance = MAX(p_distance, 0.01); - RS::get_singleton()->material_set_param(_get_material(), shader_names->proximity_fade_distance, proximity_fade_distance); + _material_set_param(shader_names->proximity_fade_distance, proximity_fade_distance); } float BaseMaterial3D::get_proximity_fade_distance() const { @@ -2787,7 +2863,7 @@ float BaseMaterial3D::get_proximity_fade_distance() const { void BaseMaterial3D::set_msdf_pixel_range(float p_range) { msdf_pixel_range = p_range; - RS::get_singleton()->material_set_param(_get_material(), shader_names->msdf_pixel_range, p_range); + _material_set_param(shader_names->msdf_pixel_range, p_range); } float BaseMaterial3D::get_msdf_pixel_range() const { @@ -2796,7 +2872,7 @@ float BaseMaterial3D::get_msdf_pixel_range() const { void BaseMaterial3D::set_msdf_outline_size(float p_size) { msdf_outline_size = p_size; - RS::get_singleton()->material_set_param(_get_material(), shader_names->msdf_outline_size, p_size); + _material_set_param(shader_names->msdf_outline_size, p_size); } float BaseMaterial3D::get_msdf_outline_size() const { @@ -2805,7 +2881,7 @@ float BaseMaterial3D::get_msdf_outline_size() const { void BaseMaterial3D::set_distance_fade(DistanceFadeMode p_mode) { distance_fade = p_mode; - _queue_shader_change(); + _mark_dirty(); notify_property_list_changed(); } @@ -2815,7 +2891,7 @@ BaseMaterial3D::DistanceFadeMode BaseMaterial3D::get_distance_fade() const { void BaseMaterial3D::set_distance_fade_max_distance(float p_distance) { distance_fade_max_distance = p_distance; - RS::get_singleton()->material_set_param(_get_material(), shader_names->distance_fade_max, distance_fade_max_distance); + _material_set_param(shader_names->distance_fade_max, distance_fade_max_distance); } float BaseMaterial3D::get_distance_fade_max_distance() const { @@ -2824,7 +2900,7 @@ float BaseMaterial3D::get_distance_fade_max_distance() const { void BaseMaterial3D::set_distance_fade_min_distance(float p_distance) { distance_fade_min_distance = p_distance; - RS::get_singleton()->material_set_param(_get_material(), shader_names->distance_fade_min, distance_fade_min_distance); + _material_set_param(shader_names->distance_fade_min, distance_fade_min_distance); } float BaseMaterial3D::get_distance_fade_min_distance() const { @@ -2836,20 +2912,22 @@ void BaseMaterial3D::set_emission_operator(EmissionOperator p_op) { return; } emission_op = p_op; - _queue_shader_change(); + _mark_dirty(); } BaseMaterial3D::EmissionOperator BaseMaterial3D::get_emission_operator() const { return emission_op; } +RID BaseMaterial3D::get_rid() const { + const_cast<BaseMaterial3D *>(this)->_update_shader(); + const_cast<BaseMaterial3D *>(this)->_check_material_rid(); + return _get_material(); +} + RID BaseMaterial3D::get_shader_rid() const { - MutexLock lock(material_mutex); - if (element.in_list()) { - ((BaseMaterial3D *)this)->_update_shader(); - } - ERR_FAIL_COND_V(!shader_map.has(current_key), RID()); - return shader_map[current_key].shader; + const_cast<BaseMaterial3D *>(this)->_update_shader(); + return shader_rid; } Shader::Mode BaseMaterial3D::get_shader_mode() const { @@ -3365,8 +3443,7 @@ void BaseMaterial3D::_bind_methods() { BIND_ENUM_CONSTANT(DISTANCE_FADE_OBJECT_DITHER); } -BaseMaterial3D::BaseMaterial3D(bool p_orm) : - element(this) { +BaseMaterial3D::BaseMaterial3D(bool p_orm) { orm = p_orm; // Initialize to the same values as the shader set_albedo(Color(1.0, 1.0, 1.0, 1.0)); @@ -3433,21 +3510,25 @@ BaseMaterial3D::BaseMaterial3D(bool p_orm) : current_key.invalid_key = 1; - _mark_initialized(callable_mp(this, &BaseMaterial3D::_queue_shader_change), callable_mp(this, &BaseMaterial3D::_update_shader)); + _mark_dirty(); } BaseMaterial3D::~BaseMaterial3D() { - ERR_FAIL_NULL(RenderingServer::get_singleton()); - MutexLock lock(material_mutex); + ERR_FAIL_NULL(RS::get_singleton()); - if (shader_map.has(current_key)) { - shader_map[current_key].users--; - if (shader_map[current_key].users == 0) { - //deallocate shader, as it's no longer in use - RS::get_singleton()->free(shader_map[current_key].shader); - shader_map.erase(current_key); + { + MutexLock lock(shader_map_mutex); + if (shader_map.has(current_key)) { + shader_map[current_key].users--; + if (shader_map[current_key].users == 0) { + // Deallocate shader which is no longer in use. + RS::get_singleton()->free(shader_map[current_key].shader); + shader_map.erase(current_key); + } } + } + if (_get_material().is_valid()) { RS::get_singleton()->material_set_shader(_get_material(), RID()); } } diff --git a/scene/resources/material.h b/scene/resources/material.h index 50a774e961..edd82b779e 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -42,7 +42,7 @@ class Material : public Resource { RES_BASE_EXTENSION("material") OBJ_SAVE_TYPE(Material); - RID material; + mutable RID material; Ref<Material> next_pass; int render_priority; @@ -55,6 +55,7 @@ class Material : public Resource { void inspect_native_shader_code(); protected: + _FORCE_INLINE_ void _set_material(RID p_material) const { material = p_material; } _FORCE_INLINE_ RID _get_material() const { return material; } static void _bind_methods(); virtual bool _can_do_next_pass() const; @@ -66,8 +67,8 @@ protected: void _mark_initialized(const Callable &p_add_to_dirty_list, const Callable &p_update_shader); bool _is_initialized() { return init_state == INIT_STATE_READY; } - GDVIRTUAL0RC(RID, _get_shader_rid) - GDVIRTUAL0RC(Shader::Mode, _get_shader_mode) + GDVIRTUAL0RC_REQUIRED(RID, _get_shader_rid) + GDVIRTUAL0RC_REQUIRED(Shader::Mode, _get_shader_mode) GDVIRTUAL0RC(bool, _can_do_next_pass) GDVIRTUAL0RC(bool, _can_use_render_priority) public: @@ -97,6 +98,7 @@ class ShaderMaterial : public Material { mutable HashMap<StringName, StringName> remap_cache; mutable HashMap<StringName, Variant> param_cache; + mutable Mutex material_rid_mutex; protected: bool _set(const StringName &p_name, const Variant &p_value); @@ -115,6 +117,7 @@ protected: virtual bool _can_use_render_priority() const override; void _shader_changed(); + void _check_material_rid() const; public: void set_shader(const Ref<Shader> &p_shader); @@ -125,6 +128,7 @@ public: virtual Shader::Mode get_shader_mode() const override; + virtual RID get_rid() const override; virtual RID get_shader_rid() const override; ShaderMaterial(); @@ -136,6 +140,9 @@ class StandardMaterial3D; class BaseMaterial3D : public Material { GDCLASS(BaseMaterial3D, Material); +private: + mutable Mutex material_rid_mutex; + public: enum TextureParam { TEXTURE_ALBEDO, @@ -361,6 +368,7 @@ private: }; static HashMap<MaterialKey, ShaderData, MaterialKey> shader_map; + static Mutex shader_map_mutex; MaterialKey current_key; @@ -459,16 +467,17 @@ private: StringName albedo_texture_size; }; - static Mutex material_mutex; - static SelfList<BaseMaterial3D>::List dirty_materials; static ShaderNames *shader_names; - SelfList<BaseMaterial3D> element; - + void _mark_dirty(); void _update_shader(); - _FORCE_INLINE_ void _queue_shader_change(); + void _check_material_rid(); + void _material_set_param(const StringName &p_name, const Variant &p_value); bool orm; + bool dirty = true; + RID shader_rid; + HashMap<StringName, Variant> pending_params; Color albedo; float specular = 0.0f; @@ -771,10 +780,10 @@ public: static void init_shaders(); static void finish_shaders(); - static void flush_changes(); static Ref<Material> get_material_for_2d(bool p_shaded, Transparency p_transparency, bool p_double_sided, bool p_billboard = false, bool p_billboard_y = false, bool p_msdf = false, bool p_no_depth = false, bool p_fixed_size = false, TextureFilter p_filter = TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, AlphaAntiAliasing p_alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF, RID *r_shader_rid = nullptr); + virtual RID get_rid() const override; virtual RID get_shader_rid() const override; virtual Shader::Mode get_shader_mode() const override; diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index 22e2e9138f..8c0e087902 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -45,23 +45,23 @@ void MeshConvexDecompositionSettings::set_max_concavity(real_t p_max_concavity) real_t MeshConvexDecompositionSettings::get_max_concavity() const { return max_concavity; -}; +} void MeshConvexDecompositionSettings::set_symmetry_planes_clipping_bias(real_t p_symmetry_planes_clipping_bias) { symmetry_planes_clipping_bias = CLAMP(p_symmetry_planes_clipping_bias, 0.0, 1.0); -}; +} real_t MeshConvexDecompositionSettings::get_symmetry_planes_clipping_bias() const { return symmetry_planes_clipping_bias; -}; +} void MeshConvexDecompositionSettings::set_revolution_axes_clipping_bias(real_t p_revolution_axes_clipping_bias) { revolution_axes_clipping_bias = CLAMP(p_revolution_axes_clipping_bias, 0.0, 1.0); -}; +} real_t MeshConvexDecompositionSettings::get_revolution_axes_clipping_bias() const { return revolution_axes_clipping_bias; -}; +} void MeshConvexDecompositionSettings::set_min_volume_per_convex_hull(real_t p_min_volume_per_convex_hull) { min_volume_per_convex_hull = CLAMP(p_min_volume_per_convex_hull, 0.0001, 0.01); @@ -205,81 +205,81 @@ Mesh::ConvexDecompositionFunc Mesh::convex_decomposition_function = nullptr; int Mesh::get_surface_count() const { int ret = 0; - GDVIRTUAL_REQUIRED_CALL(_get_surface_count, ret); + GDVIRTUAL_CALL(_get_surface_count, ret); return ret; } int Mesh::surface_get_array_len(int p_idx) const { int ret = 0; - GDVIRTUAL_REQUIRED_CALL(_surface_get_array_len, p_idx, ret); + GDVIRTUAL_CALL(_surface_get_array_len, p_idx, ret); return ret; } int Mesh::surface_get_array_index_len(int p_idx) const { int ret = 0; - GDVIRTUAL_REQUIRED_CALL(_surface_get_array_index_len, p_idx, ret); + GDVIRTUAL_CALL(_surface_get_array_index_len, p_idx, ret); return ret; } Array Mesh::surface_get_arrays(int p_surface) const { Array ret; - GDVIRTUAL_REQUIRED_CALL(_surface_get_arrays, p_surface, ret); + GDVIRTUAL_CALL(_surface_get_arrays, p_surface, ret); return ret; } TypedArray<Array> Mesh::surface_get_blend_shape_arrays(int p_surface) const { TypedArray<Array> ret; - GDVIRTUAL_REQUIRED_CALL(_surface_get_blend_shape_arrays, p_surface, ret); + GDVIRTUAL_CALL(_surface_get_blend_shape_arrays, p_surface, ret); return ret; } Dictionary Mesh::surface_get_lods(int p_surface) const { Dictionary ret; - GDVIRTUAL_REQUIRED_CALL(_surface_get_lods, p_surface, ret); + GDVIRTUAL_CALL(_surface_get_lods, p_surface, ret); return ret; } BitField<Mesh::ArrayFormat> Mesh::surface_get_format(int p_idx) const { uint32_t ret = 0; - GDVIRTUAL_REQUIRED_CALL(_surface_get_format, p_idx, ret); + GDVIRTUAL_CALL(_surface_get_format, p_idx, ret); return ret; } Mesh::PrimitiveType Mesh::surface_get_primitive_type(int p_idx) const { uint32_t ret = PRIMITIVE_MAX; - GDVIRTUAL_REQUIRED_CALL(_surface_get_primitive_type, p_idx, ret); + GDVIRTUAL_CALL(_surface_get_primitive_type, p_idx, ret); return (Mesh::PrimitiveType)ret; } void Mesh::surface_set_material(int p_idx, const Ref<Material> &p_material) { - GDVIRTUAL_REQUIRED_CALL(_surface_set_material, p_idx, p_material); + GDVIRTUAL_CALL(_surface_set_material, p_idx, p_material); } Ref<Material> Mesh::surface_get_material(int p_idx) const { Ref<Material> ret; - GDVIRTUAL_REQUIRED_CALL(_surface_get_material, p_idx, ret); + GDVIRTUAL_CALL(_surface_get_material, p_idx, ret); return ret; } int Mesh::get_blend_shape_count() const { int ret = 0; - GDVIRTUAL_REQUIRED_CALL(_get_blend_shape_count, ret); + GDVIRTUAL_CALL(_get_blend_shape_count, ret); return ret; } StringName Mesh::get_blend_shape_name(int p_index) const { StringName ret; - GDVIRTUAL_REQUIRED_CALL(_get_blend_shape_name, p_index, ret); + GDVIRTUAL_CALL(_get_blend_shape_name, p_index, ret); return ret; } void Mesh::set_blend_shape_name(int p_index, const StringName &p_name) { - GDVIRTUAL_REQUIRED_CALL(_set_blend_shape_name, p_index, p_name); + GDVIRTUAL_CALL(_set_blend_shape_name, p_index, p_name); } AABB Mesh::get_aabb() const { AABB ret; - GDVIRTUAL_REQUIRED_CALL(_get_aabb, ret); + GDVIRTUAL_CALL(_get_aabb, ret); return ret; } @@ -385,7 +385,7 @@ Ref<TriangleMesh> Mesh::generate_triangle_mesh() const { } } - triangle_mesh = Ref<TriangleMesh>(memnew(TriangleMesh)); + triangle_mesh.instantiate(); triangle_mesh->create(faces); return triangle_mesh; @@ -1315,7 +1315,7 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { String sname = p_name; if (sname.begins_with("surface_")) { - int sl = sname.find("/"); + int sl = sname.find_char('/'); if (sl == -1) { return false; } @@ -1708,7 +1708,7 @@ bool ArrayMesh::_get(const StringName &p_name, Variant &r_ret) const { String sname = p_name; if (sname.begins_with("surface_")) { - int sl = sname.find("/"); + int sl = sname.find_char('/'); if (sl == -1) { return false; } diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h index 13fd986e81..068bfb6708 100644 --- a/scene/resources/mesh.h +++ b/scene/resources/mesh.h @@ -68,20 +68,20 @@ public: protected: static void _bind_methods(); - GDVIRTUAL0RC(int, _get_surface_count) - GDVIRTUAL1RC(int, _surface_get_array_len, int) - GDVIRTUAL1RC(int, _surface_get_array_index_len, int) - GDVIRTUAL1RC(Array, _surface_get_arrays, int) - GDVIRTUAL1RC(TypedArray<Array>, _surface_get_blend_shape_arrays, int) - GDVIRTUAL1RC(Dictionary, _surface_get_lods, int) - GDVIRTUAL1RC(uint32_t, _surface_get_format, int) - GDVIRTUAL1RC(uint32_t, _surface_get_primitive_type, int) - GDVIRTUAL2(_surface_set_material, int, Ref<Material>) - GDVIRTUAL1RC(Ref<Material>, _surface_get_material, int) - GDVIRTUAL0RC(int, _get_blend_shape_count) - GDVIRTUAL1RC(StringName, _get_blend_shape_name, int) - GDVIRTUAL2(_set_blend_shape_name, int, StringName) - GDVIRTUAL0RC(AABB, _get_aabb) + GDVIRTUAL0RC_REQUIRED(int, _get_surface_count) + GDVIRTUAL1RC_REQUIRED(int, _surface_get_array_len, int) + GDVIRTUAL1RC_REQUIRED(int, _surface_get_array_index_len, int) + GDVIRTUAL1RC_REQUIRED(Array, _surface_get_arrays, int) + GDVIRTUAL1RC_REQUIRED(TypedArray<Array>, _surface_get_blend_shape_arrays, int) + GDVIRTUAL1RC_REQUIRED(Dictionary, _surface_get_lods, int) + GDVIRTUAL1RC_REQUIRED(uint32_t, _surface_get_format, int) + GDVIRTUAL1RC_REQUIRED(uint32_t, _surface_get_primitive_type, int) + GDVIRTUAL2_REQUIRED(_surface_set_material, int, Ref<Material>) + GDVIRTUAL1RC_REQUIRED(Ref<Material>, _surface_get_material, int) + GDVIRTUAL0RC_REQUIRED(int, _get_blend_shape_count) + GDVIRTUAL1RC_REQUIRED(StringName, _get_blend_shape_name, int) + GDVIRTUAL2_REQUIRED(_set_blend_shape_name, int, StringName) + GDVIRTUAL0RC_REQUIRED(AABB, _get_aabb) public: enum { diff --git a/scene/resources/navigation_mesh.cpp b/scene/resources/navigation_mesh.cpp index 67ed65df0d..034d4d6996 100644 --- a/scene/resources/navigation_mesh.cpp +++ b/scene/resources/navigation_mesh.cpp @@ -392,8 +392,8 @@ Ref<ArrayMesh> NavigationMesh::get_debug_mesh() { return debug_mesh; } - if (!debug_mesh.is_valid()) { - debug_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); + if (debug_mesh.is_null()) { + debug_mesh.instantiate(); } else { debug_mesh->clear_surfaces(); } diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index d6fe4385c4..d7036fd6d5 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -786,7 +786,7 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Has Dictionary missing_resource_properties = p_node->get_meta(META_MISSING_RESOURCES, Dictionary()); for (const PropertyInfo &E : plist) { - if (!(E.usage & PROPERTY_USAGE_STORAGE)) { + if (!(E.usage & PROPERTY_USAGE_STORAGE) && !missing_resource_properties.has(E.name)) { continue; } @@ -822,10 +822,10 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Has value = missing_resource_properties[E.name]; } } else if (E.type == Variant::ARRAY && E.hint == PROPERTY_HINT_TYPE_STRING) { - int hint_subtype_separator = E.hint_string.find(":"); + int hint_subtype_separator = E.hint_string.find_char(':'); if (hint_subtype_separator >= 0) { String subtype_string = E.hint_string.substr(0, hint_subtype_separator); - int slash_pos = subtype_string.find("/"); + int slash_pos = subtype_string.find_char('/'); PropertyHint subtype_hint = PropertyHint::PROPERTY_HINT_NONE; if (slash_pos >= 0) { subtype_hint = PropertyHint(subtype_string.get_slice("/", 1).to_int()); @@ -851,11 +851,11 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Has } } } else if (E.type == Variant::DICTIONARY && E.hint == PROPERTY_HINT_TYPE_STRING) { - int key_value_separator = E.hint_string.find(";"); + int key_value_separator = E.hint_string.find_char(';'); if (key_value_separator >= 0) { - int key_subtype_separator = E.hint_string.find(":"); + int key_subtype_separator = E.hint_string.find_char(':'); String key_subtype_string = E.hint_string.substr(0, key_subtype_separator); - int key_slash_pos = key_subtype_string.find("/"); + int key_slash_pos = key_subtype_string.find_char('/'); PropertyHint key_subtype_hint = PropertyHint::PROPERTY_HINT_NONE; if (key_slash_pos >= 0) { key_subtype_hint = PropertyHint(key_subtype_string.get_slice("/", 1).to_int()); @@ -864,9 +864,9 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Has Variant::Type key_subtype = Variant::Type(key_subtype_string.to_int()); bool convert_key = key_subtype == Variant::OBJECT && key_subtype_hint == PROPERTY_HINT_NODE_TYPE; - int value_subtype_separator = E.hint_string.find(":", key_value_separator) - (key_value_separator + 1); + int value_subtype_separator = E.hint_string.find_char(':', key_value_separator) - (key_value_separator + 1); String value_subtype_string = E.hint_string.substr(key_value_separator + 1, value_subtype_separator); - int value_slash_pos = value_subtype_string.find("/"); + int value_slash_pos = value_subtype_string.find_char('/'); PropertyHint value_subtype_hint = PropertyHint::PROPERTY_HINT_NONE; if (value_slash_pos >= 0) { value_subtype_hint = PropertyHint(value_subtype_string.get_slice("/", 1).to_int()); @@ -2195,7 +2195,7 @@ void PackedScene::replace_state(Ref<SceneState> p_by) { } void PackedScene::recreate_state() { - state = Ref<SceneState>(memnew(SceneState)); + state.instantiate(); state->set_path(get_path()); #ifdef TOOLS_ENABLED state->set_last_modified_time(get_last_modified_time()); @@ -2286,5 +2286,5 @@ void PackedScene::_bind_methods() { } PackedScene::PackedScene() { - state = Ref<SceneState>(memnew(SceneState)); + state.instantiate(); } diff --git a/scene/resources/particle_process_material.cpp b/scene/resources/particle_process_material.cpp index 8cfe4c92b7..09bc1fa8e4 100644 --- a/scene/resources/particle_process_material.cpp +++ b/scene/resources/particle_process_material.cpp @@ -2261,6 +2261,8 @@ void ParticleProcessMaterial::_bind_methods() { ParticleProcessMaterial::ParticleProcessMaterial() : element(this) { + _set_material(RS::get_singleton()->material_create()); + set_direction(Vector3(1, 0, 0)); set_spread(45); set_flatness(0); diff --git a/scene/resources/portable_compressed_texture.cpp b/scene/resources/portable_compressed_texture.cpp index 06b5ec6d5a..55bbed7c47 100644 --- a/scene/resources/portable_compressed_texture.cpp +++ b/scene/resources/portable_compressed_texture.cpp @@ -89,7 +89,7 @@ void PortableCompressedTexture2D::_set_data(const Vector<uint8_t> &p_data) { data_size -= mipsize; } - image = Ref<Image>(memnew(Image(size.width, size.height, mipmaps, format, image_data))); + image.instantiate(size.width, size.height, mipmaps, format, image_data); } break; case COMPRESSION_MODE_BASIS_UNIVERSAL: { @@ -100,7 +100,7 @@ void PortableCompressedTexture2D::_set_data(const Vector<uint8_t> &p_data) { case COMPRESSION_MODE_S3TC: case COMPRESSION_MODE_ETC2: case COMPRESSION_MODE_BPTC: { - image = Ref<Image>(memnew(Image(size.width, size.height, mipmaps, format, p_data.slice(20)))); + image.instantiate(size.width, size.height, mipmaps, format, p_data.slice(20)); } break; } ERR_FAIL_COND(image.is_null()); diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp index d531eea311..03f0e107e4 100644 --- a/scene/resources/resource_format_text.cpp +++ b/scene/resources/resource_format_text.cpp @@ -600,7 +600,7 @@ Error ResourceLoaderText::load() { if (do_assign) { bool set_valid = true; - if (value.get_type() == Variant::OBJECT && missing_resource != nullptr) { + if (value.get_type() == Variant::OBJECT && missing_resource == nullptr && ResourceLoader::is_creating_missing_resources_if_class_unavailable_enabled()) { // If the property being set is a missing resource (and the parent is not), // then setting it will most likely not work. // Instead, save it as metadata. @@ -612,29 +612,27 @@ Error ResourceLoaderText::load() { } } - if (ClassDB::has_property(res->get_class_name(), assign)) { - if (value.get_type() == Variant::ARRAY) { - Array set_array = value; - bool is_get_valid = false; - Variant get_value = res->get(assign, &is_get_valid); - if (is_get_valid && get_value.get_type() == Variant::ARRAY) { - Array get_array = get_value; - if (!set_array.is_same_typed(get_array)) { - value = Array(set_array, get_array.get_typed_builtin(), get_array.get_typed_class_name(), get_array.get_typed_script()); - } + if (value.get_type() == Variant::ARRAY) { + Array set_array = value; + bool is_get_valid = false; + Variant get_value = res->get(assign, &is_get_valid); + if (is_get_valid && get_value.get_type() == Variant::ARRAY) { + Array get_array = get_value; + if (!set_array.is_same_typed(get_array)) { + value = Array(set_array, get_array.get_typed_builtin(), get_array.get_typed_class_name(), get_array.get_typed_script()); } } + } - if (value.get_type() == Variant::DICTIONARY) { - Dictionary set_dict = value; - bool is_get_valid = false; - Variant get_value = res->get(assign, &is_get_valid); - if (is_get_valid && get_value.get_type() == Variant::DICTIONARY) { - Dictionary get_dict = get_value; - if (!set_dict.is_same_typed(get_dict)) { - value = Dictionary(set_dict, get_dict.get_typed_key_builtin(), get_dict.get_typed_key_class_name(), get_dict.get_typed_key_script(), - get_dict.get_typed_value_builtin(), get_dict.get_typed_value_class_name(), get_dict.get_typed_value_script()); - } + if (value.get_type() == Variant::DICTIONARY) { + Dictionary set_dict = value; + bool is_get_valid = false; + Variant get_value = res->get(assign, &is_get_valid); + if (is_get_valid && get_value.get_type() == Variant::DICTIONARY) { + Dictionary get_dict = get_value; + if (!set_dict.is_same_typed(get_dict)) { + value = Dictionary(set_dict, get_dict.get_typed_key_builtin(), get_dict.get_typed_key_class_name(), get_dict.get_typed_key_script(), + get_dict.get_typed_value_builtin(), get_dict.get_typed_value_class_name(), get_dict.get_typed_value_script()); } } } @@ -725,24 +723,25 @@ Error ResourceLoaderText::load() { if (error) { if (error != ERR_FILE_EOF) { _printerr(); - } else { - error = OK; - if (cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE) { - if (!ResourceCache::has(res_path)) { - resource->set_path(res_path); - } - resource->set_as_translation_remapped(translation_remapped); - } else { - resource->set_path_cache(res_path); + return error; + } + // EOF, Done parsing. + error = OK; + if (cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE) { + if (!ResourceCache::has(res_path)) { + resource->set_path(res_path); } + resource->set_as_translation_remapped(translation_remapped); + } else { + resource->set_path_cache(res_path); } - return error; + break; } if (!assign.is_empty()) { bool set_valid = true; - if (value.get_type() == Variant::OBJECT && missing_resource != nullptr) { + if (value.get_type() == Variant::OBJECT && missing_resource == nullptr && ResourceLoader::is_creating_missing_resources_if_class_unavailable_enabled()) { // If the property being set is a missing resource (and the parent is not), // then setting it will most likely not work. // Instead, save it as metadata. @@ -754,29 +753,27 @@ Error ResourceLoaderText::load() { } } - if (ClassDB::has_property(resource->get_class_name(), assign)) { - if (value.get_type() == Variant::ARRAY) { - Array set_array = value; - bool is_get_valid = false; - Variant get_value = resource->get(assign, &is_get_valid); - if (is_get_valid && get_value.get_type() == Variant::ARRAY) { - Array get_array = get_value; - if (!set_array.is_same_typed(get_array)) { - value = Array(set_array, get_array.get_typed_builtin(), get_array.get_typed_class_name(), get_array.get_typed_script()); - } + if (value.get_type() == Variant::ARRAY) { + Array set_array = value; + bool is_get_valid = false; + Variant get_value = resource->get(assign, &is_get_valid); + if (is_get_valid && get_value.get_type() == Variant::ARRAY) { + Array get_array = get_value; + if (!set_array.is_same_typed(get_array)) { + value = Array(set_array, get_array.get_typed_builtin(), get_array.get_typed_class_name(), get_array.get_typed_script()); } } + } - if (value.get_type() == Variant::DICTIONARY) { - Dictionary set_dict = value; - bool is_get_valid = false; - Variant get_value = resource->get(assign, &is_get_valid); - if (is_get_valid && get_value.get_type() == Variant::DICTIONARY) { - Dictionary get_dict = get_value; - if (!set_dict.is_same_typed(get_dict)) { - value = Dictionary(set_dict, get_dict.get_typed_key_builtin(), get_dict.get_typed_key_class_name(), get_dict.get_typed_key_script(), - get_dict.get_typed_value_builtin(), get_dict.get_typed_value_class_name(), get_dict.get_typed_value_script()); - } + if (value.get_type() == Variant::DICTIONARY) { + Dictionary set_dict = value; + bool is_get_valid = false; + Variant get_value = resource->get(assign, &is_get_valid); + if (is_get_valid && get_value.get_type() == Variant::DICTIONARY) { + Dictionary get_dict = get_value; + if (!set_dict.is_same_typed(get_dict)) { + value = Dictionary(set_dict, get_dict.get_typed_key_builtin(), get_dict.get_typed_key_class_name(), get_dict.get_typed_key_script(), + get_dict.get_typed_value_builtin(), get_dict.get_typed_value_class_name(), get_dict.get_typed_value_script()); } } } @@ -1435,8 +1432,8 @@ void ResourceFormatLoaderText::get_recognized_extensions_for_type(const String & p_extensions->push_back("tscn"); } - // Don't allow .tres for PackedScenes. - if (p_type != "PackedScene") { + // Don't allow .tres for PackedScenes or GDExtension. + if (p_type != "PackedScene" && p_type != "GDExtension") { p_extensions->push_back("tres"); } } @@ -1529,6 +1526,10 @@ ResourceUID::ID ResourceFormatLoaderText::get_resource_uid(const String &p_path) return loader.get_uid(f); } +bool ResourceFormatLoaderText::has_custom_uid_support() const { + return true; +} + void ResourceFormatLoaderText::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) { Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ); if (f.is_null()) { @@ -1708,6 +1709,8 @@ static String _resource_get_class(Ref<Resource> p_resource) { } Error ResourceFormatSaverTextInstance::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) { + Resource::seed_scene_unique_id(p_path.hash()); // Seeding for save path should make it deterministic for importers. + if (p_path.ends_with(".tscn")) { packed_scene = p_resource; } @@ -1779,7 +1782,7 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const Ref<Reso for (KeyValue<Ref<Resource>, String> &E : external_resources) { String cached_id = E.key->get_id_for_path(local_path); if (cached_id.is_empty() || cached_ids_found.has(cached_id)) { - int sep_pos = E.value.find("_"); + int sep_pos = E.value.find_char('_'); if (sep_pos != -1) { E.value = E.value.substr(0, sep_pos + 1); // Keep the order found, for improved thread loading performance. } else { @@ -1902,7 +1905,7 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const Ref<Reso #endif } - Dictionary missing_resource_properties = p_resource->get_meta(META_MISSING_RESOURCES, Dictionary()); + Dictionary missing_resource_properties = res->get_meta(META_MISSING_RESOURCES, Dictionary()); List<PropertyInfo> property_list; res->get_property_list(&property_list); @@ -1914,7 +1917,7 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const Ref<Reso continue; } - if (PE->get().usage & PROPERTY_USAGE_STORAGE) { + if (PE->get().usage & PROPERTY_USAGE_STORAGE || missing_resource_properties.has(PE->get().name)) { String name = PE->get().name; Variant value; if (PE->get().usage & PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT) { diff --git a/scene/resources/resource_format_text.h b/scene/resources/resource_format_text.h index 8397bc985f..4c0bf3d917 100644 --- a/scene/resources/resource_format_text.h +++ b/scene/resources/resource_format_text.h @@ -155,6 +155,7 @@ public: virtual String get_resource_type(const String &p_path) const override; virtual String get_resource_script_class(const String &p_path) const override; virtual ResourceUID::ID get_resource_uid(const String &p_path) const override; + virtual bool has_custom_uid_support() const override; virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false) override; virtual Error rename_dependencies(const String &p_path, const HashMap<String, String> &p_map) override; diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp index 46d38146a6..d163a42fa9 100644 --- a/scene/resources/shader.cpp +++ b/scene/resources/shader.cpp @@ -32,6 +32,7 @@ #include "shader.compat.inc" #include "core/io/file_access.h" +#include "scene/main/scene_tree.h" #include "servers/rendering/shader_language.h" #include "servers/rendering/shader_preprocessor.h" #include "servers/rendering_server.h" @@ -50,6 +51,14 @@ Shader::Mode Shader::get_mode() const { return mode; } +void Shader::_check_shader_rid() const { + MutexLock lock(shader_rid_mutex); + if (shader_rid.is_null() && !preprocessed_code.is_empty()) { + shader_rid = RenderingServer::get_singleton()->shader_create_from_code(preprocessed_code, get_path()); + preprocessed_code = String(); + } +} + void Shader::_dependency_changed() { // Preprocess and compile the code again because a dependency has changed. It also calls emit_changed() for us. _recompile(); @@ -61,7 +70,10 @@ void Shader::_recompile() { void Shader::set_path(const String &p_path, bool p_take_over) { Resource::set_path(p_path, p_take_over); - RS::get_singleton()->shader_set_path_hint(shader, p_path); + + if (shader_rid.is_valid()) { + RS::get_singleton()->shader_set_path_hint(shader_rid, p_path); + } } void Shader::set_include_path(const String &p_path) { @@ -76,7 +88,7 @@ void Shader::set_code(const String &p_code) { } code = p_code; - String pp_code = p_code; + preprocessed_code = p_code; { String path = get_path(); @@ -88,7 +100,7 @@ void Shader::set_code(const String &p_code) { // 2) Server does not do interaction with Resource filetypes, this is a scene level feature. HashSet<Ref<ShaderInclude>> new_include_dependencies; ShaderPreprocessor preprocessor; - Error result = preprocessor.preprocess(p_code, path, pp_code, nullptr, nullptr, nullptr, &new_include_dependencies); + Error result = preprocessor.preprocess(p_code, path, preprocessed_code, nullptr, nullptr, nullptr, &new_include_dependencies); if (result == OK) { // This ensures previous include resources are not freed and then re-loaded during parse (which would make compiling slower) include_dependencies = new_include_dependencies; @@ -96,7 +108,7 @@ void Shader::set_code(const String &p_code) { } // Try to get the shader type from the final, fully preprocessed shader code. - String type = ShaderLanguage::get_shader_type(pp_code); + String type = ShaderLanguage::get_shader_type(preprocessed_code); if (type == "canvas_item") { mode = MODE_CANVAS_ITEM; @@ -114,7 +126,10 @@ void Shader::set_code(const String &p_code) { E->connect_changed(callable_mp(this, &Shader::_dependency_changed)); } - RenderingServer::get_singleton()->shader_set_code(shader, pp_code); + if (shader_rid.is_valid()) { + RenderingServer::get_singleton()->shader_set_code(shader_rid, preprocessed_code); + preprocessed_code = String(); + } emit_changed(); } @@ -124,11 +139,20 @@ String Shader::get_code() const { return code; } +void Shader::inspect_native_shader_code() { + SceneTree *st = SceneTree::get_singleton(); + RID _shader = get_rid(); + if (st && _shader.is_valid()) { + st->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, "_native_shader_source_visualizer", "_inspect_shader", _shader); + } +} + void Shader::get_shader_uniform_list(List<PropertyInfo> *p_params, bool p_get_groups) const { _update_shader(); + _check_shader_rid(); List<PropertyInfo> local; - RenderingServer::get_singleton()->get_shader_parameter_list(shader, &local); + RenderingServer::get_singleton()->get_shader_parameter_list(shader_rid, &local); #ifdef TOOLS_ENABLED DocData::ClassDoc class_doc; @@ -182,17 +206,20 @@ void Shader::get_shader_uniform_list(List<PropertyInfo> *p_params, bool p_get_gr RID Shader::get_rid() const { _update_shader(); + _check_shader_rid(); - return shader; + return shader_rid; } void Shader::set_default_texture_parameter(const StringName &p_name, const Ref<Texture> &p_texture, int p_index) { + _check_shader_rid(); + if (p_texture.is_valid()) { if (!default_textures.has(p_name)) { default_textures[p_name] = HashMap<int, Ref<Texture>>(); } default_textures[p_name][p_index] = p_texture; - RS::get_singleton()->shader_set_default_texture_parameter(shader, p_name, p_texture->get_rid(), p_index); + RS::get_singleton()->shader_set_default_texture_parameter(shader_rid, p_name, p_texture->get_rid(), p_index); } else { if (default_textures.has(p_name) && default_textures[p_name].has(p_index)) { default_textures[p_name].erase(p_index); @@ -201,7 +228,7 @@ void Shader::set_default_texture_parameter(const StringName &p_name, const Ref<T default_textures.erase(p_name); } } - RS::get_singleton()->shader_set_default_texture_parameter(shader, p_name, RID(), p_index); + RS::get_singleton()->shader_set_default_texture_parameter(shader_rid, p_name, RID(), p_index); } emit_changed(); @@ -225,6 +252,7 @@ bool Shader::is_text_shader() const { } void Shader::_update_shader() const { + // Base implementation does nothing. } Array Shader::_get_shader_uniform_list(bool p_get_groups) { @@ -248,6 +276,9 @@ void Shader::_bind_methods() { ClassDB::bind_method(D_METHOD("get_shader_uniform_list", "get_groups"), &Shader::_get_shader_uniform_list, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("inspect_native_shader_code"), &Shader::inspect_native_shader_code); + ClassDB::set_method_flags(get_class_static(), _scs_create("inspect_native_shader_code"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "code", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_code", "get_code"); BIND_ENUM_CONSTANT(MODE_SPATIAL); @@ -258,12 +289,14 @@ void Shader::_bind_methods() { } Shader::Shader() { - shader = RenderingServer::get_singleton()->shader_create(); + // Shader RID will be empty until it is required. } Shader::~Shader() { - ERR_FAIL_NULL(RenderingServer::get_singleton()); - RenderingServer::get_singleton()->free(shader); + if (shader_rid.is_valid()) { + ERR_FAIL_NULL(RenderingServer::get_singleton()); + RenderingServer::get_singleton()->free(shader_rid); + } } //////////// diff --git a/scene/resources/shader.h b/scene/resources/shader.h index 682fbd7ea6..7234d37579 100644 --- a/scene/resources/shader.h +++ b/scene/resources/shader.h @@ -52,7 +52,10 @@ public: }; private: - RID shader; + mutable RID shader_rid; + mutable String preprocessed_code; + mutable Mutex shader_rid_mutex; + Mode mode = MODE_SPATIAL; HashSet<Ref<ShaderInclude>> include_dependencies; String code; @@ -60,6 +63,7 @@ private: HashMap<StringName, HashMap<int, Ref<Texture>>> default_textures; + void _check_shader_rid() const; void _dependency_changed(); void _recompile(); virtual void _update_shader() const; //used for visual shader @@ -84,6 +88,8 @@ public: void set_code(const String &p_code); String get_code() const; + void inspect_native_shader_code(); + void get_shader_uniform_list(List<PropertyInfo> *p_params, bool p_get_groups = false) const; void set_default_texture_parameter(const StringName &p_name, const Ref<Texture> &p_texture, int p_index = 0); diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp index f87bf1ee05..1203c21a1b 100644 --- a/scene/resources/style_box.cpp +++ b/scene/resources/style_box.cpp @@ -90,7 +90,7 @@ Point2 StyleBox::get_offset() const { } void StyleBox::draw(RID p_canvas_item, const Rect2 &p_rect) const { - GDVIRTUAL_REQUIRED_CALL(_draw, p_canvas_item, p_rect); + GDVIRTUAL_CALL(_draw, p_canvas_item, p_rect); } Rect2 StyleBox::get_draw_rect(const Rect2 &p_rect) const { diff --git a/scene/resources/style_box.h b/scene/resources/style_box.h index 3d3a059d0b..e09b271c47 100644 --- a/scene/resources/style_box.h +++ b/scene/resources/style_box.h @@ -48,7 +48,7 @@ protected: static void _bind_methods(); virtual float get_style_margin(Side p_side) const { return 0; } - GDVIRTUAL2C(_draw, RID, Rect2) + GDVIRTUAL2C_REQUIRED(_draw, RID, Rect2) GDVIRTUAL1RC(Rect2, _get_draw_rect, Rect2) GDVIRTUAL0RC(Size2, _get_minimum_size) GDVIRTUAL2RC(bool, _test_mask, Point2, Rect2) diff --git a/scene/resources/style_box_flat.cpp b/scene/resources/style_box_flat.cpp index 60b91ef0cb..202ab3615b 100644 --- a/scene/resources/style_box_flat.cpp +++ b/scene/resources/style_box_flat.cpp @@ -226,33 +226,16 @@ inline void set_inner_corner_radius(const Rect2 style_rect, const Rect2 inner_re real_t border_right = style_rect.size.width - inner_rect.size.width - border_left; real_t border_bottom = style_rect.size.height - inner_rect.size.height - border_top; - real_t rad; - - // Top left. - rad = MIN(border_top, border_left); - inner_corner_radius[0] = MAX(corner_radius[0] - rad, 0); - - // Top right; - rad = MIN(border_top, border_right); - inner_corner_radius[1] = MAX(corner_radius[1] - rad, 0); - - // Bottom right. - rad = MIN(border_bottom, border_right); - inner_corner_radius[2] = MAX(corner_radius[2] - rad, 0); - - // Bottom left. - rad = MIN(border_bottom, border_left); - inner_corner_radius[3] = MAX(corner_radius[3] - rad, 0); + inner_corner_radius[0] = MAX(corner_radius[0] - MIN(border_top, border_left), 0); // Top left. + inner_corner_radius[1] = MAX(corner_radius[1] - MIN(border_top, border_right), 0); // Top right. + inner_corner_radius[2] = MAX(corner_radius[2] - MIN(border_bottom, border_right), 0); // Bottom right. + inner_corner_radius[3] = MAX(corner_radius[3] - MIN(border_bottom, border_left), 0); // Bottom left. } inline void draw_rounded_rectangle(Vector<Vector2> &verts, Vector<int> &indices, Vector<Color> &colors, const Rect2 &style_rect, const real_t corner_radius[4], const Rect2 &ring_rect, const Rect2 &inner_rect, const Color &inner_color, const Color &outer_color, const int corner_detail, const Vector2 &skew, bool is_filled = false) { int vert_offset = verts.size(); - if (!vert_offset) { - vert_offset = 0; - } - - int adapted_corner_detail = (corner_radius[0] == 0 && corner_radius[1] == 0 && corner_radius[2] == 0 && corner_radius[3] == 0) ? 1 : corner_detail; + int adapted_corner_detail = (corner_radius[0] > 0) || (corner_radius[1] > 0) || (corner_radius[2] > 0) || (corner_radius[3] > 0) ? corner_detail : 1; bool draw_border = !is_filled; @@ -280,30 +263,44 @@ inline void draw_rounded_rectangle(Vector<Vector2> &verts, Vector<int> &indices, // If the center is filled, we do not draw the border and directly use the inner ring as reference. Because all calls to this // method either draw a ring or a filled rounded rectangle, but not both. - int max_inner_outer = draw_border ? 2 : 1; - - for (int corner_index = 0; corner_index < 4; corner_index++) { + real_t quarter_arc_rad = Math_PI / 2.0; + Point2 style_rect_center = style_rect.get_center(); + + int colors_size = colors.size(); + int verts_size = verts.size(); + int new_verts_amount = (adapted_corner_detail + 1) * (draw_border ? 8 : 4); + colors.resize(colors_size + new_verts_amount); + verts.resize(verts_size + new_verts_amount); + Color *colors_ptr = colors.ptrw(); + Vector2 *verts_ptr = verts.ptrw(); + + for (int corner_idx = 0; corner_idx < 4; corner_idx++) { for (int detail = 0; detail <= adapted_corner_detail; detail++) { - for (int inner_outer = 0; inner_outer < max_inner_outer; inner_outer++) { - real_t radius; - Color color; - Point2 corner_point; - if (inner_outer == 0) { - radius = inner_corner_radius[corner_index]; - color = inner_color; - corner_point = inner_points[corner_index]; - } else { - radius = ring_corner_radius[corner_index]; - color = outer_color; - corner_point = outer_points[corner_index]; - } + int idx_ofs = (adapted_corner_detail + 1) * corner_idx + detail; + if (draw_border) { + idx_ofs *= 2; + } - const real_t x = radius * (real_t)cos((corner_index + detail / (double)adapted_corner_detail) * (Math_TAU / 4.0) + Math_PI) + corner_point.x; - const real_t y = radius * (real_t)sin((corner_index + detail / (double)adapted_corner_detail) * (Math_TAU / 4.0) + Math_PI) + corner_point.y; - const float x_skew = -skew.x * (y - style_rect.get_center().y); - const float y_skew = -skew.y * (x - style_rect.get_center().x); - verts.push_back(Vector2(x + x_skew, y + y_skew)); - colors.push_back(color); + const real_t pt_angle = (corner_idx + detail / (double)adapted_corner_detail) * quarter_arc_rad + Math_PI; + const real_t angle_cosine = cos(pt_angle); + const real_t angle_sine = sin(pt_angle); + + { + const real_t x = inner_corner_radius[corner_idx] * angle_cosine + inner_points[corner_idx].x; + const real_t y = inner_corner_radius[corner_idx] * angle_sine + inner_points[corner_idx].y; + const float x_skew = -skew.x * (y - style_rect_center.y); + const float y_skew = -skew.y * (x - style_rect_center.x); + verts_ptr[verts_size + idx_ofs] = Vector2(x + x_skew, y + y_skew); + colors_ptr[colors_size + idx_ofs] = inner_color; + } + + if (draw_border) { + const real_t x = ring_corner_radius[corner_idx] * angle_cosine + outer_points[corner_idx].x; + const real_t y = ring_corner_radius[corner_idx] * angle_sine + outer_points[corner_idx].y; + const float x_skew = -skew.x * (y - style_rect_center.y); + const float y_skew = -skew.y * (x - style_rect_center.x); + verts_ptr[verts_size + idx_ofs + 1] = Vector2(x + x_skew, y + y_skew); + colors_ptr[colors_size + idx_ofs + 1] = outer_color; } } } @@ -313,10 +310,15 @@ inline void draw_rounded_rectangle(Vector<Vector2> &verts, Vector<int> &indices, // Fill the indices and the colors for the border. if (draw_border) { + int indices_size = indices.size(); + indices.resize(indices_size + ring_vert_count * 3); + int *indices_ptr = indices.ptrw(); + for (int i = 0; i < ring_vert_count; i++) { - indices.push_back(vert_offset + ((i + 0) % ring_vert_count)); - indices.push_back(vert_offset + ((i + 2) % ring_vert_count)); - indices.push_back(vert_offset + ((i + 1) % ring_vert_count)); + int idx_ofs = indices_size + i * 3; + indices_ptr[idx_ofs] = vert_offset + i % ring_vert_count; + indices_ptr[idx_ofs + 1] = vert_offset + (i + 2) % ring_vert_count; + indices_ptr[idx_ofs + 2] = vert_offset + (i + 1) % ring_vert_count; } } @@ -327,40 +329,30 @@ inline void draw_rounded_rectangle(Vector<Vector2> &verts, Vector<int> &indices, int stripes_count = ring_vert_count / 2 - 1; int last_vert_id = ring_vert_count - 1; + int indices_size = indices.size(); + indices.resize(indices_size + stripes_count * 6); + int *indices_ptr = indices.ptrw(); + for (int i = 0; i < stripes_count; i++) { + int idx_ofs = indices_size + i * 6; // Polygon 1. - indices.push_back(vert_offset + i); - indices.push_back(vert_offset + last_vert_id - i - 1); - indices.push_back(vert_offset + i + 1); + indices_ptr[idx_ofs] = vert_offset + i; + indices_ptr[idx_ofs + 1] = vert_offset + last_vert_id - i - 1; + indices_ptr[idx_ofs + 2] = vert_offset + i + 1; // Polygon 2. - indices.push_back(vert_offset + i); - indices.push_back(vert_offset + last_vert_id - 0 - i); - indices.push_back(vert_offset + last_vert_id - 1 - i); + indices_ptr[idx_ofs + 3] = vert_offset + i; + indices_ptr[idx_ofs + 4] = vert_offset + last_vert_id - i; + indices_ptr[idx_ofs + 5] = vert_offset + last_vert_id - i - 1; } } } inline void adapt_values(int p_index_a, int p_index_b, real_t *adapted_values, const real_t *p_values, const real_t p_width, const real_t p_max_a, const real_t p_max_b) { - if (p_values[p_index_a] + p_values[p_index_b] > p_width) { - real_t factor; - real_t new_value; - - factor = (real_t)p_width / (real_t)(p_values[p_index_a] + p_values[p_index_b]); - - new_value = (p_values[p_index_a] * factor); - if (new_value < adapted_values[p_index_a]) { - adapted_values[p_index_a] = new_value; - } - new_value = (p_values[p_index_b] * factor); - if (new_value < adapted_values[p_index_b]) { - adapted_values[p_index_b] = new_value; - } - } else { - adapted_values[p_index_a] = MIN(p_values[p_index_a], adapted_values[p_index_a]); - adapted_values[p_index_b] = MIN(p_values[p_index_b], adapted_values[p_index_b]); - } - adapted_values[p_index_a] = MIN(p_max_a, adapted_values[p_index_a]); - adapted_values[p_index_b] = MIN(p_max_b, adapted_values[p_index_b]); + real_t value_a = p_values[p_index_a]; + real_t value_b = p_values[p_index_b]; + real_t factor = MIN(1.0, p_width / (value_a + value_b)); + adapted_values[p_index_a] = MIN(MIN(value_a * factor, p_max_a), adapted_values[p_index_a]); + adapted_values[p_index_b] = MIN(MIN(value_b * factor, p_max_b), adapted_values[p_index_b]); } Rect2 StyleBoxFlat::get_draw_rect(const Rect2 &p_rect) const { @@ -388,7 +380,7 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const { } const bool rounded_corners = (corner_radius[0] > 0) || (corner_radius[1] > 0) || (corner_radius[2] > 0) || (corner_radius[3] > 0); - // Only enable antialiasing if it is actually needed. This improve performances + // Only enable antialiasing if it is actually needed. This improves performance // and maximizes sharpness for non-skewed StyleBoxes with sharp corners. const bool aa_on = (rounded_corners || !skew.is_zero_approx()) && anti_aliased; @@ -428,7 +420,7 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const { Vector<Color> colors; Vector<Point2> uvs; - // Create shadow + // Create shadow. if (draw_shadow) { Rect2 shadow_inner_rect = style_rect; shadow_inner_rect.position += shadow_offset; @@ -538,9 +530,10 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const { // Compute UV coordinates. Rect2 uv_rect = style_rect.grow(aa_on ? aa_size : 0); uvs.resize(verts.size()); + Point2 *uvs_ptr = uvs.ptrw(); for (int i = 0; i < verts.size(); i++) { - uvs.write[i].x = (verts[i].x - uv_rect.position.x) / uv_rect.size.width; - uvs.write[i].y = (verts[i].y - uv_rect.position.y) / uv_rect.size.height; + uvs_ptr[i].x = (verts[i].x - uv_rect.position.x) / uv_rect.size.width; + uvs_ptr[i].y = (verts[i].y - uv_rect.position.y) / uv_rect.size.height; } // Draw stylebox. @@ -603,10 +596,10 @@ void StyleBoxFlat::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "skew"), "set_skew", "get_skew"); ADD_GROUP("Border Width", "border_width_"); - ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_left", PROPERTY_HINT_RANGE, "0,1024,1,suffix:px"), "set_border_width", "get_border_width", SIDE_LEFT); - ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_top", PROPERTY_HINT_RANGE, "0,1024,1,suffix:px"), "set_border_width", "get_border_width", SIDE_TOP); - ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_right", PROPERTY_HINT_RANGE, "0,1024,1,suffix:px"), "set_border_width", "get_border_width", SIDE_RIGHT); - ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_bottom", PROPERTY_HINT_RANGE, "0,1024,1,suffix:px"), "set_border_width", "get_border_width", SIDE_BOTTOM); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_left", PROPERTY_HINT_RANGE, "0,100,1,or_greater,suffix:px"), "set_border_width", "get_border_width", SIDE_LEFT); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_top", PROPERTY_HINT_RANGE, "0,100,1,or_greater,suffix:px"), "set_border_width", "get_border_width", SIDE_TOP); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_right", PROPERTY_HINT_RANGE, "0,100,1,or_greater,suffix:px"), "set_border_width", "get_border_width", SIDE_RIGHT); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "border_width_bottom", PROPERTY_HINT_RANGE, "0,100,1,or_greater,suffix:px"), "set_border_width", "get_border_width", SIDE_BOTTOM); ADD_GROUP("Border", "border_"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "border_color"), "set_border_color", "get_border_color"); @@ -614,18 +607,18 @@ void StyleBoxFlat::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "border_blend"), "set_border_blend", "get_border_blend"); ADD_GROUP("Corner Radius", "corner_radius_"); - ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_top_left", PROPERTY_HINT_RANGE, "0,1024,1,suffix:px"), "set_corner_radius", "get_corner_radius", CORNER_TOP_LEFT); - ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_top_right", PROPERTY_HINT_RANGE, "0,1024,1,suffix:px"), "set_corner_radius", "get_corner_radius", CORNER_TOP_RIGHT); - ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_bottom_right", PROPERTY_HINT_RANGE, "0,1024,1,suffix:px"), "set_corner_radius", "get_corner_radius", CORNER_BOTTOM_RIGHT); - ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_bottom_left", PROPERTY_HINT_RANGE, "0,1024,1,suffix:px"), "set_corner_radius", "get_corner_radius", CORNER_BOTTOM_LEFT); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_top_left", PROPERTY_HINT_RANGE, "0,100,1,or_greater,suffix:px"), "set_corner_radius", "get_corner_radius", CORNER_TOP_LEFT); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_top_right", PROPERTY_HINT_RANGE, "0,100,1,or_greater,suffix:px"), "set_corner_radius", "get_corner_radius", CORNER_TOP_RIGHT); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_bottom_right", PROPERTY_HINT_RANGE, "0,100,1,or_greater,suffix:px"), "set_corner_radius", "get_corner_radius", CORNER_BOTTOM_RIGHT); + ADD_PROPERTYI(PropertyInfo(Variant::INT, "corner_radius_bottom_left", PROPERTY_HINT_RANGE, "0,100,1,or_greater,suffix:px"), "set_corner_radius", "get_corner_radius", CORNER_BOTTOM_LEFT); ADD_PROPERTY(PropertyInfo(Variant::INT, "corner_detail", PROPERTY_HINT_RANGE, "1,20,1"), "set_corner_detail", "get_corner_detail"); ADD_GROUP("Expand Margins", "expand_margin_"); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_left", PROPERTY_HINT_RANGE, "0,2048,1,suffix:px"), "set_expand_margin", "get_expand_margin", SIDE_LEFT); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_top", PROPERTY_HINT_RANGE, "0,2048,1,suffix:px"), "set_expand_margin", "get_expand_margin", SIDE_TOP); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_right", PROPERTY_HINT_RANGE, "0,2048,1,suffix:px"), "set_expand_margin", "get_expand_margin", SIDE_RIGHT); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_bottom", PROPERTY_HINT_RANGE, "0,2048,1,suffix:px"), "set_expand_margin", "get_expand_margin", SIDE_BOTTOM); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_left", PROPERTY_HINT_RANGE, "0,100,1,or_greater,suffix:px"), "set_expand_margin", "get_expand_margin", SIDE_LEFT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_top", PROPERTY_HINT_RANGE, "0,100,1,or_greater,suffix:px"), "set_expand_margin", "get_expand_margin", SIDE_TOP); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_right", PROPERTY_HINT_RANGE, "0,100,1,or_greater,suffix:px"), "set_expand_margin", "get_expand_margin", SIDE_RIGHT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_bottom", PROPERTY_HINT_RANGE, "0,100,1,or_greater,suffix:px"), "set_expand_margin", "get_expand_margin", SIDE_BOTTOM); ADD_GROUP("Shadow", "shadow_"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "shadow_color"), "set_shadow_color", "get_shadow_color"); diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index 6921885ee0..c230cf1b70 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -33,10 +33,10 @@ #define EQ_VERTEX_DIST 0.00001 SurfaceTool::OptimizeVertexCacheFunc SurfaceTool::optimize_vertex_cache_func = nullptr; +SurfaceTool::OptimizeVertexFetchRemapFunc SurfaceTool::optimize_vertex_fetch_remap_func = nullptr; SurfaceTool::SimplifyFunc SurfaceTool::simplify_func = nullptr; SurfaceTool::SimplifyWithAttribFunc SurfaceTool::simplify_with_attrib_func = nullptr; SurfaceTool::SimplifyScaleFunc SurfaceTool::simplify_scale_func = nullptr; -SurfaceTool::SimplifySloppyFunc SurfaceTool::simplify_sloppy_func = nullptr; SurfaceTool::GenerateRemapFunc SurfaceTool::generate_remap_func = nullptr; SurfaceTool::RemapVertexFunc SurfaceTool::remap_vertex_func = nullptr; SurfaceTool::RemapIndexFunc SurfaceTool::remap_index_func = nullptr; diff --git a/scene/resources/surface_tool.h b/scene/resources/surface_tool.h index a072df5bee..68dc9e7198 100644 --- a/scene/resources/surface_tool.h +++ b/scene/resources/surface_tool.h @@ -80,18 +80,24 @@ public: enum { /* Do not move vertices that are located on the topological border (vertices on triangle edges that don't have a paired triangle). Useful for simplifying portions of the larger mesh. */ SIMPLIFY_LOCK_BORDER = 1 << 0, // From meshopt_SimplifyLockBorder + /* Improve simplification performance assuming input indices are a sparse subset of the mesh. Note that error becomes relative to subset extents. */ + SIMPLIFY_SPARSE = 1 << 1, // From meshopt_SimplifySparse + /* Treat error limit and resulting error as absolute instead of relative to mesh extents. */ + SIMPLIFY_ERROR_ABSOLUTE = 1 << 2, // From meshopt_SimplifyErrorAbsolute + /* Remove disconnected parts of the mesh during simplification incrementally, regardless of the topological restrictions inside components. */ + SIMPLIFY_PRUNE = 1 << 3, // From meshopt_SimplifyPrune }; typedef void (*OptimizeVertexCacheFunc)(unsigned int *destination, const unsigned int *indices, size_t index_count, size_t vertex_count); static OptimizeVertexCacheFunc optimize_vertex_cache_func; + typedef size_t (*OptimizeVertexFetchRemapFunc)(unsigned int *destination, const unsigned int *indices, size_t index_count, size_t vertex_count); + static OptimizeVertexFetchRemapFunc optimize_vertex_fetch_remap_func; typedef size_t (*SimplifyFunc)(unsigned int *destination, const unsigned int *indices, size_t index_count, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, unsigned int options, float *r_error); static SimplifyFunc simplify_func; - typedef size_t (*SimplifyWithAttribFunc)(unsigned int *destination, const unsigned int *indices, size_t index_count, const float *vertex_data, size_t vertex_count, size_t vertex_stride, const float *attributes, size_t attribute_stride, const float *attribute_weights, size_t attribute_count, size_t target_index_count, float target_error, unsigned int options, float *result_error); + typedef size_t (*SimplifyWithAttribFunc)(unsigned int *destination, const unsigned int *indices, size_t index_count, const float *vertex_data, size_t vertex_count, size_t vertex_stride, const float *attributes, size_t attribute_stride, const float *attribute_weights, size_t attribute_count, const unsigned char *vertex_lock, size_t target_index_count, float target_error, unsigned int options, float *result_error); static SimplifyWithAttribFunc simplify_with_attrib_func; typedef float (*SimplifyScaleFunc)(const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride); static SimplifyScaleFunc simplify_scale_func; - typedef size_t (*SimplifySloppyFunc)(unsigned int *destination, const unsigned int *indices, size_t index_count, const float *vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float *out_result_error); - static SimplifySloppyFunc simplify_sloppy_func; typedef size_t (*GenerateRemapFunc)(unsigned int *destination, const unsigned int *indices, size_t index_count, const void *vertices, size_t vertex_count, size_t vertex_size); static GenerateRemapFunc generate_remap_func; typedef void (*RemapVertexFunc)(void *destination, const void *vertices, size_t vertex_count, size_t vertex_size, const unsigned int *remap); @@ -113,7 +119,7 @@ private: SmoothGroupVertex(const Vertex &p_vertex) { vertex = p_vertex.vertex; smooth_group = p_vertex.smooth_group; - }; + } }; struct SmoothGroupVertexHasher { @@ -216,7 +222,9 @@ public: void clear(); - LocalVector<Vertex> &get_vertex_array() { return vertex_array; } + LocalVector<Vertex> &get_vertex_array() { + return vertex_array; + } void create_from_triangle_arrays(const Array &p_arrays); void create_from_arrays(const Array &p_arrays, Mesh::PrimitiveType p_primitive_type = Mesh::PRIMITIVE_TRIANGLES); diff --git a/scene/resources/syntax_highlighter.cpp b/scene/resources/syntax_highlighter.cpp index 6da4215031..4bc03a049a 100644 --- a/scene/resources/syntax_highlighter.cpp +++ b/scene/resources/syntax_highlighter.cpp @@ -205,7 +205,7 @@ Dictionary CodeHighlighter::_get_line_syntax_highlighting_impl(int p_line) { if (end_key_length == 0 || color_regions[c].line_only || from + end_key_length > line_length) { if (from + end_key_length > line_length && (color_regions[in_region].start_key == "\"" || color_regions[in_region].start_key == "\'")) { // If it's key length and there is a '\', dont skip to highlight esc chars. - if (str.find("\\", from) >= 0) { + if (str.find_char('\\', from) >= 0) { break; } } @@ -242,7 +242,7 @@ Dictionary CodeHighlighter::_get_line_syntax_highlighting_impl(int p_line) { for (; from < line_length; from++) { if (line_length - from < end_key_length) { // Don't break if '\' to highlight esc chars. - if (!is_string || str.find("\\", from) < 0) { + if (!is_string || str.find_char('\\', from) < 0) { break; } } @@ -442,7 +442,6 @@ Color CodeHighlighter::get_keyword_color(const String &p_keyword) const { } void CodeHighlighter::set_keyword_colors(const Dictionary p_keywords) { - keywords.clear(); keywords = p_keywords; clear_highlighting_cache(); } @@ -476,7 +475,6 @@ Color CodeHighlighter::get_member_keyword_color(const String &p_member_keyword) } void CodeHighlighter::set_member_keyword_colors(const Dictionary &p_member_keywords) { - member_keywords.clear(); member_keywords = p_member_keywords; clear_highlighting_cache(); } diff --git a/scene/resources/text_paragraph.cpp b/scene/resources/text_paragraph.cpp index 29a8541cb0..65c6e40241 100644 --- a/scene/resources/text_paragraph.cpp +++ b/scene/resources/text_paragraph.cpp @@ -112,6 +112,11 @@ void TextParagraph::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "max_lines_visible"), "set_max_lines_visible", "get_max_lines_visible"); + ClassDB::bind_method(D_METHOD("set_line_spacing", "line_spacing"), &TextParagraph::set_line_spacing); + ClassDB::bind_method(D_METHOD("get_line_spacing"), &TextParagraph::get_line_spacing); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "line_spacing"), "set_line_spacing", "get_line_spacing"); + ClassDB::bind_method(D_METHOD("get_line_objects", "line"), &TextParagraph::get_line_objects); ClassDB::bind_method(D_METHOD("get_line_object_rect", "line", "key"), &TextParagraph::get_line_object_rect); ClassDB::bind_method(D_METHOD("get_line_size", "line"), &TextParagraph::get_line_size); @@ -180,6 +185,7 @@ void TextParagraph::_shape_lines() { for (int i = 0; i < line_breaks.size(); i = i + 2) { RID line = TS->shaped_text_substr(rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]); float h = (TS->shaped_text_get_orientation(line) == TextServer::ORIENTATION_HORIZONTAL) ? TS->shaped_text_get_size(line).y : TS->shaped_text_get_size(line).x; + h += line_spacing; if (!tab_stops.is_empty()) { TS->shaped_text_tab_align(line, tab_stops); } @@ -574,12 +580,18 @@ Size2 TextParagraph::get_size() const { } size.x = MAX(size.x, lsize.x); size.y += lsize.y; + if (i != visible_lines - 1) { + size.y += line_spacing; + } } else { if (h_offset > 0 && i <= dropcap_lines) { lsize.y += h_offset; } size.x += lsize.x; size.y = MAX(size.y, lsize.y); + if (i != visible_lines - 1) { + size.x += line_spacing; + } } } if (h_offset > 0) { @@ -612,6 +624,19 @@ int TextParagraph::get_max_lines_visible() const { return max_lines_visible; } +void TextParagraph::set_line_spacing(float p_spacing) { + _THREAD_SAFE_METHOD_ + + if (line_spacing != p_spacing) { + line_spacing = p_spacing; + lines_dirty = true; + } +} + +float TextParagraph::get_line_spacing() const { + return line_spacing; +} + Array TextParagraph::get_line_objects(int p_line) const { _THREAD_SAFE_METHOD_ @@ -697,10 +722,10 @@ Rect2 TextParagraph::get_line_object_rect(int p_line, Variant p_key) const { if (i != p_line) { if (TS->shaped_text_get_orientation(lines_rid[i]) == TextServer::ORIENTATION_HORIZONTAL) { ofs.x = 0.f; - ofs.y += TS->shaped_text_get_descent(lines_rid[i]); + ofs.y += TS->shaped_text_get_descent(lines_rid[i]) + line_spacing; } else { ofs.y = 0.f; - ofs.x += TS->shaped_text_get_descent(lines_rid[i]); + ofs.x += TS->shaped_text_get_descent(lines_rid[i]) + line_spacing; } } } @@ -872,10 +897,10 @@ void TextParagraph::draw(RID p_canvas, const Vector2 &p_pos, const Color &p_colo TS->shaped_text_draw(lines_rid[i], p_canvas, ofs, clip_l, clip_l + l_width, p_color); if (TS->shaped_text_get_orientation(lines_rid[i]) == TextServer::ORIENTATION_HORIZONTAL) { ofs.x = p_pos.x; - ofs.y += TS->shaped_text_get_descent(lines_rid[i]); + ofs.y += TS->shaped_text_get_descent(lines_rid[i]) + line_spacing; } else { ofs.y = p_pos.y; - ofs.x += TS->shaped_text_get_descent(lines_rid[i]); + ofs.x += TS->shaped_text_get_descent(lines_rid[i]) + line_spacing; } } } @@ -974,10 +999,10 @@ void TextParagraph::draw_outline(RID p_canvas, const Vector2 &p_pos, int p_outli TS->shaped_text_draw_outline(lines_rid[i], p_canvas, ofs, clip_l, clip_l + l_width, p_outline_size, p_color); if (TS->shaped_text_get_orientation(lines_rid[i]) == TextServer::ORIENTATION_HORIZONTAL) { ofs.x = p_pos.x; - ofs.y += TS->shaped_text_get_descent(lines_rid[i]); + ofs.y += TS->shaped_text_get_descent(lines_rid[i]) + line_spacing; } else { ofs.y = p_pos.y; - ofs.x += TS->shaped_text_get_descent(lines_rid[i]); + ofs.x += TS->shaped_text_get_descent(lines_rid[i]) + line_spacing; } } } @@ -1001,17 +1026,21 @@ int TextParagraph::hit_test(const Point2 &p_coords) const { if ((p_coords.y >= ofs.y) && (p_coords.y <= ofs.y + TS->shaped_text_get_size(line_rid).y)) { return TS->shaped_text_hit_test_position(line_rid, p_coords.x); } - ofs.y += TS->shaped_text_get_size(line_rid).y; + ofs.y += TS->shaped_text_get_size(line_rid).y + line_spacing; } else { if ((p_coords.x >= ofs.x) && (p_coords.x <= ofs.x + TS->shaped_text_get_size(line_rid).x)) { return TS->shaped_text_hit_test_position(line_rid, p_coords.y); } - ofs.y += TS->shaped_text_get_size(line_rid).x; + ofs.y += TS->shaped_text_get_size(line_rid).x + line_spacing; } } return TS->shaped_text_get_range(rid).y; } +bool TextParagraph::is_dirty() { + return lines_dirty; +} + void TextParagraph::draw_dropcap(RID p_canvas, const Vector2 &p_pos, const Color &p_color) const { _THREAD_SAFE_METHOD_ diff --git a/scene/resources/text_paragraph.h b/scene/resources/text_paragraph.h index 7512955fb3..966ce556d5 100644 --- a/scene/resources/text_paragraph.h +++ b/scene/resources/text_paragraph.h @@ -51,6 +51,7 @@ private: bool lines_dirty = true; + float line_spacing = 0.0; float width = -1.0; int max_lines_visible = -1; @@ -122,6 +123,9 @@ public: void set_max_lines_visible(int p_lines); int get_max_lines_visible() const; + void set_line_spacing(float p_spacing); + float get_line_spacing() const; + Size2 get_non_wrapped_size() const; Size2 get_size() const; @@ -152,7 +156,9 @@ public: int hit_test(const Point2 &p_coords) const; - Mutex &get_mutex() const { return _thread_safe_; }; + bool is_dirty(); + + Mutex &get_mutex() const { return _thread_safe_; } TextParagraph(const String &p_text, const Ref<Font> &p_font, int p_font_size, const String &p_language = "", float p_width = -1.f, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL); TextParagraph(); diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 0efaad61fe..7713181a4b 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -34,13 +34,13 @@ int Texture2D::get_width() const { int ret = 0; - GDVIRTUAL_REQUIRED_CALL(_get_width, ret); + GDVIRTUAL_CALL(_get_width, ret); return ret; } int Texture2D::get_height() const { int ret = 0; - GDVIRTUAL_REQUIRED_CALL(_get_height, ret); + GDVIRTUAL_CALL(_get_height, ret); return ret; } @@ -133,37 +133,37 @@ TypedArray<Image> Texture3D::_get_datai() const { Image::Format Texture3D::get_format() const { Image::Format ret = Image::FORMAT_MAX; - GDVIRTUAL_REQUIRED_CALL(_get_format, ret); + GDVIRTUAL_CALL(_get_format, ret); return ret; } int Texture3D::get_width() const { int ret = 0; - GDVIRTUAL_REQUIRED_CALL(_get_width, ret); + GDVIRTUAL_CALL(_get_width, ret); return ret; } int Texture3D::get_height() const { int ret = 0; - GDVIRTUAL_REQUIRED_CALL(_get_height, ret); + GDVIRTUAL_CALL(_get_height, ret); return ret; } int Texture3D::get_depth() const { int ret = 0; - GDVIRTUAL_REQUIRED_CALL(_get_depth, ret); + GDVIRTUAL_CALL(_get_depth, ret); return ret; } bool Texture3D::has_mipmaps() const { bool ret = false; - GDVIRTUAL_REQUIRED_CALL(_has_mipmaps, ret); + GDVIRTUAL_CALL(_has_mipmaps, ret); return ret; } Vector<Ref<Image>> Texture3D::get_data() const { TypedArray<Image> ret; - GDVIRTUAL_REQUIRED_CALL(_get_data, ret); + GDVIRTUAL_CALL(_get_data, ret); Vector<Ref<Image>> data; data.resize(ret.size()); for (int i = 0; i < data.size(); i++) { @@ -198,43 +198,43 @@ Ref<Resource> Texture3D::create_placeholder() const { Image::Format TextureLayered::get_format() const { Image::Format ret = Image::FORMAT_MAX; - GDVIRTUAL_REQUIRED_CALL(_get_format, ret); + GDVIRTUAL_CALL(_get_format, ret); return ret; } TextureLayered::LayeredType TextureLayered::get_layered_type() const { uint32_t ret = LAYERED_TYPE_2D_ARRAY; - GDVIRTUAL_REQUIRED_CALL(_get_layered_type, ret); + GDVIRTUAL_CALL(_get_layered_type, ret); return (LayeredType)ret; } int TextureLayered::get_width() const { int ret = 0; - GDVIRTUAL_REQUIRED_CALL(_get_width, ret); + GDVIRTUAL_CALL(_get_width, ret); return ret; } int TextureLayered::get_height() const { int ret = 0; - GDVIRTUAL_REQUIRED_CALL(_get_height, ret); + GDVIRTUAL_CALL(_get_height, ret); return ret; } int TextureLayered::get_layers() const { int ret = 0; - GDVIRTUAL_REQUIRED_CALL(_get_layers, ret); + GDVIRTUAL_CALL(_get_layers, ret); return ret; } bool TextureLayered::has_mipmaps() const { bool ret = false; - GDVIRTUAL_REQUIRED_CALL(_has_mipmaps, ret); + GDVIRTUAL_CALL(_has_mipmaps, ret); return ret; } Ref<Image> TextureLayered::get_layer_data(int p_layer) const { Ref<Image> ret; - GDVIRTUAL_REQUIRED_CALL(_get_layer_data, p_layer, ret); + GDVIRTUAL_CALL(_get_layer_data, p_layer, ret); return ret; } diff --git a/scene/resources/texture.h b/scene/resources/texture.h index e7840804bf..cdad884e71 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -57,8 +57,8 @@ class Texture2D : public Texture { protected: static void _bind_methods(); - GDVIRTUAL0RC(int, _get_width) - GDVIRTUAL0RC(int, _get_height) + GDVIRTUAL0RC_REQUIRED(int, _get_width) + GDVIRTUAL0RC_REQUIRED(int, _get_height) GDVIRTUAL2RC(bool, _is_pixel_opaque, int, int) GDVIRTUAL0RC(bool, _has_alpha) @@ -93,13 +93,13 @@ class TextureLayered : public Texture { protected: static void _bind_methods(); - GDVIRTUAL0RC(Image::Format, _get_format) - GDVIRTUAL0RC(uint32_t, _get_layered_type) - GDVIRTUAL0RC(int, _get_width) - GDVIRTUAL0RC(int, _get_height) - GDVIRTUAL0RC(int, _get_layers) - GDVIRTUAL0RC(bool, _has_mipmaps) - GDVIRTUAL1RC(Ref<Image>, _get_layer_data, int) + GDVIRTUAL0RC_REQUIRED(Image::Format, _get_format) + GDVIRTUAL0RC_REQUIRED(uint32_t, _get_layered_type) + GDVIRTUAL0RC_REQUIRED(int, _get_width) + GDVIRTUAL0RC_REQUIRED(int, _get_height) + GDVIRTUAL0RC_REQUIRED(int, _get_layers) + GDVIRTUAL0RC_REQUIRED(bool, _has_mipmaps) + GDVIRTUAL1RC_REQUIRED(Ref<Image>, _get_layer_data, int) public: enum LayeredType { LAYERED_TYPE_2D_ARRAY, @@ -128,12 +128,12 @@ protected: TypedArray<Image> _get_datai() const; - GDVIRTUAL0RC(Image::Format, _get_format) - GDVIRTUAL0RC(int, _get_width) - GDVIRTUAL0RC(int, _get_height) - GDVIRTUAL0RC(int, _get_depth) - GDVIRTUAL0RC(bool, _has_mipmaps) - GDVIRTUAL0RC(TypedArray<Image>, _get_data) + GDVIRTUAL0RC_REQUIRED(Image::Format, _get_format) + GDVIRTUAL0RC_REQUIRED(int, _get_width) + GDVIRTUAL0RC_REQUIRED(int, _get_height) + GDVIRTUAL0RC_REQUIRED(int, _get_depth) + GDVIRTUAL0RC_REQUIRED(bool, _has_mipmaps) + GDVIRTUAL0RC_REQUIRED(TypedArray<Image>, _get_data) public: virtual Image::Format get_format() const; virtual int get_width() const; diff --git a/scene/resources/texture_rd.cpp b/scene/resources/texture_rd.cpp index 531dbcbe7e..8e7eeb0ff4 100644 --- a/scene/resources/texture_rd.cpp +++ b/scene/resources/texture_rd.cpp @@ -197,7 +197,7 @@ void TextureLayeredRD::_set_texture_rd_rid(RID p_texture_rd_rid) { RS::TextureLayeredType rs_layer_type; RD::TextureFormat tf = RD::get_singleton()->texture_get_format(p_texture_rd_rid); - ERR_FAIL_COND(tf.texture_type != RD::TEXTURE_TYPE_2D_ARRAY); + ERR_FAIL_COND(tf.texture_type != RD::TEXTURE_TYPE_2D_ARRAY && tf.texture_type != RD::TEXTURE_TYPE_CUBE && tf.texture_type != RD::TEXTURE_TYPE_CUBE_ARRAY); ERR_FAIL_COND(tf.depth > 1); switch (layer_type) { case LAYERED_TYPE_2D_ARRAY: { diff --git a/scene/resources/video_stream.cpp b/scene/resources/video_stream.cpp index 3d31fe0491..1fcc1821dc 100644 --- a/scene/resources/video_stream.cpp +++ b/scene/resources/video_stream.cpp @@ -119,7 +119,7 @@ Ref<Texture2D> VideoStreamPlayback::get_texture() const { } void VideoStreamPlayback::update(double p_delta) { - GDVIRTUAL_REQUIRED_CALL(_update, p_delta); + GDVIRTUAL_CALL(_update, p_delta); } void VideoStreamPlayback::set_mix_callback(AudioMixCallback p_callback, void *p_userdata) { diff --git a/scene/resources/video_stream.h b/scene/resources/video_stream.h index dc54f4b769..3843cc99c4 100644 --- a/scene/resources/video_stream.h +++ b/scene/resources/video_stream.h @@ -56,7 +56,7 @@ protected: GDVIRTUAL1(_seek, double); GDVIRTUAL1(_set_audio_track, int); GDVIRTUAL0RC(Ref<Texture2D>, _get_texture); - GDVIRTUAL1(_update, double); + GDVIRTUAL1_REQUIRED(_update, double); GDVIRTUAL0RC(int, _get_channels); GDVIRTUAL0RC(int, _get_mix_rate); diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index d0e55f4065..7c1adeac96 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -1368,7 +1368,7 @@ void VisualShader::disconnect_nodes(Type p_type, int p_from_node, int p_from_por ERR_FAIL_INDEX(p_type, TYPE_MAX); Graph *g = &graph[p_type]; - for (const List<Connection>::Element *E = g->connections.front(); E; E = E->next()) { + for (List<Connection>::Element *E = g->connections.front(); E; E = E->next()) { if (E->get().from_node == p_from_node && E->get().from_port == p_from_port && E->get().to_node == p_to_node && E->get().to_port == p_to_port) { g->connections.erase(E); g->nodes[p_from_node].next_connected_nodes.erase(p_to_node); @@ -1560,7 +1560,7 @@ String VisualShader::generate_preview_shader(Type p_type, int p_node, int p_port shader_code += " COLOR.rgb = n_out" + itos(p_node) + "p" + itos(p_port) + ";\n"; } break; case VisualShaderNode::PORT_TYPE_VECTOR_4D: { - shader_code += " COLOR.rgb = n_out" + itos(p_node) + "p" + itos(p_port) + ".xyz;\n"; + shader_code += " COLOR = n_out" + itos(p_node) + "p" + itos(p_port) + ";\n"; } break; default: { shader_code += " COLOR.rgb = vec3(0.0);\n"; @@ -1921,13 +1921,13 @@ void VisualShader::_get_property_list(List<PropertyInfo> *p_list) const { } for (const KeyValue<String, Varying> &E : varyings) { - p_list->push_back(PropertyInfo(Variant::STRING, vformat("%s/%s", PNAME("varyings"), E.key), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::STRING, vformat("%s/%s", "varyings", E.key), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); } #ifdef TOOLS_ENABLED if (Engine::get_singleton()->is_editor_hint()) { for (const KeyValue<String, Variant> &E : preview_params) { - p_list->push_back(PropertyInfo(Variant::STRING, vformat("%s/%s", PNAME("preview_params"), E.key), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::STRING, vformat("%s/%s", "preview_params", E.key), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); } } #endif // TOOLS_ENABLED @@ -3167,6 +3167,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_BOOLEAN, "output_is_srgb", "OUTPUT_IS_SRGB" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_TRANSFORM, "projection_matrix", "PROJECTION_MATRIX" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "roughness", "ROUGHNESS" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "specular", "SPECULAR_LIGHT" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" }, |