diff --git a/library/terra_material_cache.cpp b/library/terra_material_cache.cpp index e2dfd82..c26bc22 100644 --- a/library/terra_material_cache.cpp +++ b/library/terra_material_cache.cpp @@ -29,6 +29,19 @@ void TerraMaterialCache::set_initialized(const bool value) { _initialized = value; } +int TerraMaterialCache::get_ref_count() { + return _ref_count; +} +void TerraMaterialCache::set_ref_count(const int value) { + _ref_count = value; +} +void TerraMaterialCache::inc_ref_count() { + _ref_count += 1; +} +void TerraMaterialCache::dec_ref_count() { + _ref_count -= 1; +} + //Materials Ref TerraMaterialCache::material_get(const int index) { ERR_FAIL_INDEX_V(index, _materials.size(), Ref(NULL)); @@ -143,7 +156,7 @@ void TerraMaterialCache::setup_material_albedo(Ref texture) { } TerraMaterialCache::TerraMaterialCache() { - material_users = 0; + _ref_count = 0; _initialized = false; } @@ -157,6 +170,12 @@ void TerraMaterialCache::_bind_methods() { ClassDB::bind_method(D_METHOD("set_initialized", "value"), &TerraMaterialCache::set_initialized); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "initialized"), "set_initialized", "get_initialized"); + ClassDB::bind_method(D_METHOD("get_ref_count"), &TerraMaterialCache::get_ref_count); + ClassDB::bind_method(D_METHOD("set_ref_count", "value"), &TerraMaterialCache::set_ref_count); + ADD_PROPERTY(PropertyInfo(Variant::INT, "mat_ref_count"), "set_ref_count", "get_ref_count"); + ClassDB::bind_method(D_METHOD("inc_ref_count"), &TerraMaterialCache::inc_ref_count); + ClassDB::bind_method(D_METHOD("dec_ref_count"), &TerraMaterialCache::dec_ref_count); + BIND_VMETHOD(MethodInfo("_setup_material_albedo", PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"))); ClassDB::bind_method(D_METHOD("material_get", "index"), &TerraMaterialCache::material_get); diff --git a/library/terra_material_cache.h b/library/terra_material_cache.h index f8240cd..a668c01 100644 --- a/library/terra_material_cache.h +++ b/library/terra_material_cache.h @@ -51,6 +51,11 @@ public: bool get_initialized(); void set_initialized(const bool value); + int get_ref_count(); + void set_ref_count(const int value); + void inc_ref_count(); + void dec_ref_count(); + Ref material_get(const int index); Ref material_lod_get(const int index); void material_add(const Ref &value); @@ -84,8 +89,8 @@ protected: Vector> _surfaces; Vector> _materials; - - int material_users; + + int _ref_count; }; #endif diff --git a/library/terraman_library.cpp b/library/terraman_library.cpp index f6e4709..6a39880 100644 --- a/library/terraman_library.cpp +++ b/library/terraman_library.cpp @@ -84,6 +84,12 @@ Ref TerramanLibrary::_material_cache_get(const int key) { ERR_FAIL_V_MSG(Ref(), "This TerramanLibrary doesn't support cached materials!"); } +void TerramanLibrary::material_cache_unref(const int key) { + call("_material_cache_unref", key); +} +void TerramanLibrary::_material_cache_unref(const int key) { +} + void TerramanLibrary::material_add(const Ref &value) { ERR_FAIL_COND(!value.is_valid()); @@ -158,6 +164,12 @@ Ref TerramanLibrary::_liquid_material_cache_get(const int ke ERR_FAIL_V_MSG(Ref(), "This TerramanLibrary doesn't support cached liquid materials!"); } +void TerramanLibrary::liquid_material_cache_unref(const int key) { + call("_liquid_material_cache_unref", key); +} +void TerramanLibrary::_liquid_material_cache_unref(const int key) { +} + void TerramanLibrary::liquid_material_add(const Ref &value) { ERR_FAIL_COND(!value.is_valid()); @@ -232,6 +244,12 @@ Ref TerramanLibrary::_prop_material_cache_get(const int key) ERR_FAIL_V_MSG(Ref(), "This TerramanLibrary doesn't support cached prop materials!"); } +void TerramanLibrary::prop_material_cache_unref(const int key) { + call("_prop_material_cache_unref", key); +} +void TerramanLibrary::_prop_material_cache_unref(const int key) { +} + void TerramanLibrary::prop_material_add(const Ref &value) { ERR_FAIL_COND(!value.is_valid()); @@ -351,7 +369,8 @@ void TerramanLibrary::_bind_methods() { BIND_VMETHOD(MethodInfo("_setup_material_albedo", PropertyInfo(Variant::INT, "material_index"), PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"))); BIND_VMETHOD(MethodInfo("_material_cache_get_key", PropertyInfo(Variant::OBJECT, "chunk", PROPERTY_HINT_RESOURCE_TYPE, "TerraChunk"))); - BIND_VMETHOD(MethodInfo("_material_cache_get", PropertyInfo(Variant::OBJECT, "key", PROPERTY_HINT_RESOURCE_TYPE, "TerraMaterialCache"))); + BIND_VMETHOD(MethodInfo(PropertyInfo(Variant::OBJECT, "ret", PROPERTY_HINT_RESOURCE_TYPE, "TerraMaterialCache"), "_material_cache_get", PropertyInfo(Variant::INT, "key"))); + BIND_VMETHOD(MethodInfo("_material_cache_unref", PropertyInfo(Variant::INT, "key"))); ClassDB::bind_method(D_METHOD("material_get", "index"), &TerramanLibrary::material_get); ClassDB::bind_method(D_METHOD("material_lod_get", "index"), &TerramanLibrary::material_lod_get); @@ -360,6 +379,8 @@ void TerramanLibrary::_bind_methods() { ClassDB::bind_method(D_METHOD("_material_cache_get_key", "chunk"), &TerramanLibrary::_material_cache_get_key); ClassDB::bind_method(D_METHOD("material_cache_get", "key"), &TerramanLibrary::material_cache_get); ClassDB::bind_method(D_METHOD("_material_cache_get", "key"), &TerramanLibrary::_material_cache_get); + ClassDB::bind_method(D_METHOD("material_cache_unref", "key"), &TerramanLibrary::material_cache_unref); + ClassDB::bind_method(D_METHOD("_material_cache_unref", "key"), &TerramanLibrary::_material_cache_unref); ClassDB::bind_method(D_METHOD("material_add", "value"), &TerramanLibrary::material_add); ClassDB::bind_method(D_METHOD("material_set", "index", "value"), &TerramanLibrary::material_set); @@ -372,7 +393,8 @@ void TerramanLibrary::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "materials", PROPERTY_HINT_NONE, "17/17:Material", PROPERTY_USAGE_DEFAULT, "Material"), "materials_set", "materials_get"); BIND_VMETHOD(MethodInfo("_liquid_material_cache_get_key", PropertyInfo(Variant::OBJECT, "chunk", PROPERTY_HINT_RESOURCE_TYPE, "TerraChunk"))); - BIND_VMETHOD(MethodInfo("_liquid_material_cache_get", PropertyInfo(Variant::OBJECT, "key", PROPERTY_HINT_RESOURCE_TYPE, "TerraMaterialCache"))); + BIND_VMETHOD(MethodInfo(PropertyInfo(Variant::OBJECT, "ret", PROPERTY_HINT_RESOURCE_TYPE, "TerraMaterialCache"), "_liquid_material_cache_get", PropertyInfo(Variant::INT, "key"))); + BIND_VMETHOD(MethodInfo("_liquid_material_cache_unref", PropertyInfo(Variant::INT, "key"))); ClassDB::bind_method(D_METHOD("liquid_material_get", "index"), &TerramanLibrary::liquid_material_get); ClassDB::bind_method(D_METHOD("liquid_material_lod_get", "index"), &TerramanLibrary::liquid_material_lod_get); @@ -381,6 +403,8 @@ void TerramanLibrary::_bind_methods() { ClassDB::bind_method(D_METHOD("_liquid_material_cache_get_key", "chunk"), &TerramanLibrary::_liquid_material_cache_get_key); ClassDB::bind_method(D_METHOD("liquid_material_cache_get", "key"), &TerramanLibrary::liquid_material_cache_get); ClassDB::bind_method(D_METHOD("_liquid_material_cache_get", "key"), &TerramanLibrary::_liquid_material_cache_get); + ClassDB::bind_method(D_METHOD("liquid_material_cache_unref", "key"), &TerramanLibrary::liquid_material_cache_unref); + ClassDB::bind_method(D_METHOD("_liquid_material_cache_unref", "key"), &TerramanLibrary::_liquid_material_cache_unref); ClassDB::bind_method(D_METHOD("liquid_material_add", "value"), &TerramanLibrary::liquid_material_add); ClassDB::bind_method(D_METHOD("liquid_material_set", "index", "value"), &TerramanLibrary::liquid_material_set); @@ -393,7 +417,8 @@ void TerramanLibrary::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "liquid_materials", PROPERTY_HINT_NONE, "17/17:Material", PROPERTY_USAGE_DEFAULT, "Material"), "liquid_materials_set", "liquid_materials_get"); BIND_VMETHOD(MethodInfo("_prop_material_cache_get_key", PropertyInfo(Variant::OBJECT, "chunk", PROPERTY_HINT_RESOURCE_TYPE, "TerraChunk"))); - BIND_VMETHOD(MethodInfo("_prop_material_cache_get", PropertyInfo(Variant::OBJECT, "key", PROPERTY_HINT_RESOURCE_TYPE, "TerraMaterialCache"))); + BIND_VMETHOD(MethodInfo(PropertyInfo(Variant::OBJECT, "ret", PROPERTY_HINT_RESOURCE_TYPE, "TerraMaterialCache"), "_prop_material_cache_get", PropertyInfo(Variant::INT, "key"))); + BIND_VMETHOD(MethodInfo("_prop_material_cache_unref", PropertyInfo(Variant::INT, "key"))); ClassDB::bind_method(D_METHOD("prop_material_get", "index"), &TerramanLibrary::prop_material_get); ClassDB::bind_method(D_METHOD("prop_material_lod_get", "index"), &TerramanLibrary::prop_material_lod_get); @@ -402,6 +427,8 @@ void TerramanLibrary::_bind_methods() { ClassDB::bind_method(D_METHOD("_prop_material_cache_get_key", "chunk"), &TerramanLibrary::_prop_material_cache_get_key); ClassDB::bind_method(D_METHOD("prop_material_cache_get", "key"), &TerramanLibrary::prop_material_cache_get); ClassDB::bind_method(D_METHOD("_prop_material_cache_get", "key"), &TerramanLibrary::_prop_material_cache_get); + ClassDB::bind_method(D_METHOD("prop_material_cache_unref", "key"), &TerramanLibrary::prop_material_cache_unref); + ClassDB::bind_method(D_METHOD("_prop_material_cache_unref", "key"), &TerramanLibrary::_prop_material_cache_unref); ClassDB::bind_method(D_METHOD("prop_material_add", "value"), &TerramanLibrary::prop_material_add); ClassDB::bind_method(D_METHOD("prop_material_set", "index", "value"), &TerramanLibrary::prop_material_set); diff --git a/library/terraman_library.h b/library/terraman_library.h index 1ed71a7..c9ae933 100644 --- a/library/terraman_library.h +++ b/library/terraman_library.h @@ -76,6 +76,8 @@ public: virtual void _material_cache_get_key(Ref chunk); Ref material_cache_get(const int key); virtual Ref _material_cache_get(const int key); + void material_cache_unref(const int key); + virtual void _material_cache_unref(const int key); void material_add(const Ref &value); void material_set(const int index, const Ref &value); @@ -93,6 +95,8 @@ public: virtual void _liquid_material_cache_get_key(Ref chunk); Ref liquid_material_cache_get(const int key); virtual Ref _liquid_material_cache_get(const int key); + void liquid_material_cache_unref(const int key); + virtual void _liquid_material_cache_unref(const int key); void liquid_material_add(const Ref &value); void liquid_material_set(const int index, const Ref &value); @@ -110,6 +114,8 @@ public: virtual void _prop_material_cache_get_key(Ref chunk); Ref prop_material_cache_get(const int key); virtual Ref _prop_material_cache_get(const int key); + void prop_material_cache_unref(const int key); + virtual void _prop_material_cache_unref(const int key); void prop_material_add(const Ref &value); void prop_material_set(const int index, const Ref &value); @@ -157,9 +163,9 @@ protected: static void _bind_methods(); bool _initialized; - Vector > _materials; - Vector > _liquid_materials; - Vector > _prop_materials; + Vector> _materials; + Vector> _liquid_materials; + Vector> _prop_materials; }; #endif // TERRA_LIBRARY_H diff --git a/library/terraman_library_merger_pcm.cpp b/library/terraman_library_merger_pcm.cpp index 7b45167..179ad0f 100644 --- a/library/terraman_library_merger_pcm.cpp +++ b/library/terraman_library_merger_pcm.cpp @@ -104,8 +104,14 @@ void TerramanLibraryMergerPCM::_material_cache_get_key(Ref chunk) { _cache_mutex.lock(); if (_material_cache.has(hash)) { + Ref cc = _material_cache[hash]; + + if (cc.is_valid()) { + cc->inc_ref_count(); + } + _cache_mutex.unlock(); - + return; } @@ -113,6 +119,7 @@ void TerramanLibraryMergerPCM::_material_cache_get_key(Ref chunk) { Ref cache; cache.instance(); + cache->inc_ref_count(); cache->set_texture_flags(get_texture_flags()); cache->set_max_atlas_size(get_max_atlas_size()); @@ -171,6 +178,28 @@ Ref TerramanLibraryMergerPCM::_material_cache_get(const int return _material_cache[key]; } +void TerramanLibraryMergerPCM::_material_cache_unref(const int key) { + _cache_mutex.lock(); + + if (!_material_cache.has(key)) { + return; + } + + Ref cc = _material_cache[key]; + + if (!cc.is_valid()) { + return; + } + + cc->dec_ref_count(); + + if (cc->get_ref_count() <= 0) { + _material_cache.erase(key); + } + + _cache_mutex.unlock(); +} + int TerramanLibraryMergerPCM::get_texture_flags() const { return _packer->get_texture_flags(); } diff --git a/library/terraman_library_merger_pcm.h b/library/terraman_library_merger_pcm.h index 48f731a..96a4076 100644 --- a/library/terraman_library_merger_pcm.h +++ b/library/terraman_library_merger_pcm.h @@ -56,6 +56,7 @@ public: bool _supports_caching(); void _material_cache_get_key(Ref chunk); Ref _material_cache_get(const int key); + void _material_cache_unref(const int key); int get_texture_flags() const; void set_texture_flags(const int flags); diff --git a/world/terra_chunk.cpp b/world/terra_chunk.cpp index 903c717..c7f91cd 100644 --- a/world/terra_chunk.cpp +++ b/world/terra_chunk.cpp @@ -938,6 +938,12 @@ void TerraChunk::enter_tree() { void TerraChunk::exit_tree() { _is_in_tree = false; + if (_library.is_valid() && _library->supports_caching()) { + if (material_cache_key_has()) { + _library->material_cache_unref(material_cache_key_get()); + } + } + if (has_method("_exit_tree")) call("_exit_tree"); }