diff --git a/library/terra_material_cache_pcm.cpp b/library/terra_material_cache_pcm.cpp index 064025e..8245ef2 100644 --- a/library/terra_material_cache_pcm.cpp +++ b/library/terra_material_cache_pcm.cpp @@ -22,7 +22,45 @@ SOFTWARE. #include "terra_material_cache_pcm.h" +#include "../../texture_packer/texture_packer.h" +#include "scene/resources/texture.h" #include "terra_surface.h" +#include "terra_surface_merger.h" + +int TerraMaterialCachePCM::get_texture_flags() const { + return _packer->get_texture_flags(); +} +void TerraMaterialCachePCM::set_texture_flags(const int flags) { + _packer->set_texture_flags(flags); +} + +int TerraMaterialCachePCM::get_max_atlas_size() const { + return _packer->get_max_atlas_size(); +} +void TerraMaterialCachePCM::set_max_atlas_size(const int size) { + _packer->set_max_atlas_size(size); +} + +bool TerraMaterialCachePCM::get_keep_original_atlases() const { + return _packer->get_keep_original_atlases(); +} +void TerraMaterialCachePCM::set_keep_original_atlases(const bool value) { + _packer->set_keep_original_atlases(value); +} + +Color TerraMaterialCachePCM::get_background_color() const { + return _packer->get_background_color(); +} +void TerraMaterialCachePCM::set_background_color(const Color &color) { + _packer->set_background_color(color); +} + +int TerraMaterialCachePCM::get_margin() const { + return _packer->get_margin(); +} +void TerraMaterialCachePCM::set_margin(const int margin) { + _packer->set_margin(margin); +} //Surfaces Ref TerraMaterialCachePCM::voxel_surface_get(const int index) { @@ -41,13 +79,114 @@ void TerraMaterialCachePCM::voxel_surfaces_clear() { } void TerraMaterialCachePCM::refresh_rects() { + bool texture_added = false; + for (int i = 0; i < _surfaces.size(); i++) { + Ref surface = Ref(_surfaces[i]); + + if (surface.is_valid()) { + for (int j = 0; j < TerraSurface::TERRA_SIDES_COUNT; ++j) { + Ref tex = surface->get_texture(static_cast(j)); + + if (!tex.is_valid()) + continue; + + if (!_packer->contains_texture(tex)) { + texture_added = true; + surface->set_region(static_cast(j), _packer->add_texture(tex)); + } else { + surface->set_region(static_cast(j), _packer->get_texture(tex)); + } + } + } + } + + if (texture_added) { + _packer->merge(); + + ERR_FAIL_COND(_packer->get_texture_count() == 0); + + Ref tex = _packer->get_generated_texture(0); + + setup_material_albedo(tex); + } + + for (int i = 0; i < _surfaces.size(); i++) { + Ref surface = _surfaces[i]; + + if (surface.is_valid()) { + surface->refresh_rects(); + } + } +} + +void TerraMaterialCachePCM::_setup_material_albedo(Ref texture) { + int count = material_get_num(); + + for (int i = 0; i < count; ++i) { + Ref m = material_get(i); + + Ref spmat = m; + + if (spmat.is_valid()) { + spmat->set_texture(SpatialMaterial::TEXTURE_ALBEDO, texture); + return; + } + + Ref shmat = m; + + if (shmat.is_valid()) { + shmat->set_shader_param("texture_albedo", texture); + } + } } TerraMaterialCachePCM::TerraMaterialCachePCM() { + _packer.instance(); + +#if GODOT4 +#warning implement +#else + _packer->set_texture_flags(Texture::FLAG_MIPMAPS | Texture::FLAG_FILTER); +#endif + + _packer->set_max_atlas_size(1024); + _packer->set_keep_original_atlases(false); + _packer->set_margin(0); } TerraMaterialCachePCM::~TerraMaterialCachePCM() { + for (int i = 0; i < _surfaces.size(); ++i) { + Ref surface = _surfaces[i]; + + if (surface.is_valid()) { + surface->set_library(Ref()); + } + } + + _surfaces.clear(); + + _packer->clear(); + _packer.unref(); } void TerraMaterialCachePCM::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_texture_flags"), &TerraMaterialCachePCM::get_texture_flags); + ClassDB::bind_method(D_METHOD("set_texture_flags", "flags"), &TerraMaterialCachePCM::set_texture_flags); + ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_flags", PROPERTY_HINT_FLAGS, "Mipmaps,Repeat,Filter,Anisotropic Linear,Convert to Linear,Mirrored Repeat,Video Surface"), "set_texture_flags", "get_texture_flags"); + + ClassDB::bind_method(D_METHOD("get_max_atlas_size"), &TerraMaterialCachePCM::get_max_atlas_size); + ClassDB::bind_method(D_METHOD("set_max_atlas_size", "size"), &TerraMaterialCachePCM::set_max_atlas_size); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_atlas_size"), "set_max_atlas_size", "get_max_atlas_size"); + + ClassDB::bind_method(D_METHOD("get_keep_original_atlases"), &TerraMaterialCachePCM::get_keep_original_atlases); + ClassDB::bind_method(D_METHOD("set_keep_original_atlases", "value"), &TerraMaterialCachePCM::set_keep_original_atlases); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_original_atlases"), "set_keep_original_atlases", "get_keep_original_atlases"); + + ClassDB::bind_method(D_METHOD("get_background_color"), &TerraMaterialCachePCM::get_background_color); + ClassDB::bind_method(D_METHOD("set_background_color", "color"), &TerraMaterialCachePCM::set_background_color); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "background_color"), "set_background_color", "get_background_color"); + + ClassDB::bind_method(D_METHOD("get_margin"), &TerraMaterialCachePCM::get_margin); + ClassDB::bind_method(D_METHOD("set_margin", "size"), &TerraMaterialCachePCM::set_margin); + ADD_PROPERTY(PropertyInfo(Variant::INT, "margin"), "set_margin", "get_margin"); } diff --git a/library/terra_material_cache_pcm.h b/library/terra_material_cache_pcm.h index 393e577..cef461b 100644 --- a/library/terra_material_cache_pcm.h +++ b/library/terra_material_cache_pcm.h @@ -43,11 +43,27 @@ SOFTWARE. #include "../defines.h" class TerraSurface; +class TexturePacker; class TerraMaterialCachePCM : public TerraMaterialCache { GDCLASS(TerraMaterialCachePCM, TerraMaterialCache); public: + int get_texture_flags() const; + void set_texture_flags(const int flags); + + int get_max_atlas_size() const; + void set_max_atlas_size(const int size); + + bool get_keep_original_atlases() const; + void set_keep_original_atlases(const bool value); + + Color get_background_color() const; + void set_background_color(const Color &color); + + int get_margin() const; + void set_margin(const int margin); + Ref voxel_surface_get(const int index); void voxel_surface_add(Ref value); void voxel_surface_set(const int index, Ref value); @@ -57,13 +73,15 @@ public: void refresh_rects(); + void _setup_material_albedo(Ref texture); + TerraMaterialCachePCM(); ~TerraMaterialCachePCM(); protected: static void _bind_methods(); - //Ref merger; + Ref _packer; }; #endif