From 5d47db0777f66874d28649bb1460975f7ff47fe0 Mon Sep 17 00:00:00 2001 From: ducphamhong Date: Tue, 24 May 2022 14:07:25 +0700 Subject: [PATCH] #123 Implement array serialize on editor --- .../Components/Default/CDefaultEditor.cpp | 2 +- .../IndirectLighting/CIndirectLighting.cpp | 87 +++++++++++++------ .../IndirectLighting/CIndirectLighting.h | 6 +- .../Serializable/CArraySerializable.cpp | 13 ++- .../Source/Serializable/CArraySerializable.h | 66 +++++++++++++- .../Source/Serializable/CObjectSerializable.h | 10 +++ .../Serializable/CValuePropertyTemplate.h | 60 +++++++++++++ 7 files changed, 210 insertions(+), 34 deletions(-) diff --git a/Projects/Editor/Source/Editor/Components/Default/CDefaultEditor.cpp b/Projects/Editor/Source/Editor/Components/Default/CDefaultEditor.cpp index 9020d943b..7bc025d17 100644 --- a/Projects/Editor/Source/Editor/Components/Default/CDefaultEditor.cpp +++ b/Projects/Editor/Source/Editor/Components/Default/CDefaultEditor.cpp @@ -375,7 +375,7 @@ namespace Skylicht { CArraySerializable* arrayObject = (CArraySerializable*)object; - if (arrayObject->OnCreateElement != nullptr) + if (arrayObject->haveCreateElementFunction()) { // add input to add elements CSubject* count = new CSubject(arrayObject->getElementCount()); diff --git a/Projects/Skylicht/Engine/Source/IndirectLighting/CIndirectLighting.cpp b/Projects/Skylicht/Engine/Source/IndirectLighting/CIndirectLighting.cpp index 0a85177cb..eddc03ccf 100644 --- a/Projects/Skylicht/Engine/Source/IndirectLighting/CIndirectLighting.cpp +++ b/Projects/Skylicht/Engine/Source/IndirectLighting/CIndirectLighting.cpp @@ -39,14 +39,18 @@ namespace Skylicht CIndirectLighting::CIndirectLighting() : m_type(SH9), - m_autoSH(true) + m_autoSH(true), + m_internalLM(false) { } CIndirectLighting::~CIndirectLighting() { - + if (m_internalLM && m_lightmap) + { + CTextureManager::getInstance()->removeTexture(m_lightmap); + } } void CIndirectLighting::initComponent() @@ -123,29 +127,21 @@ namespace Skylicht enumType->addEnumString("SH9", EIndirectType::SH9); object->autoRelease(enumType); - CArraySerializable* textureArray = new CArraySerializable("LMTextures", object); - textureArray->OnCreateElement = [textureArray]() + CArrayTypeSerializable* textureArray = new CArrayTypeSerializable("LMTextures", object); + textureArray->OnCreateElement = [](CValueProperty* element) { - CFilePathProperty* element = new CFilePathProperty(textureArray, "Element"); - textureArray->autoRelease(element); - return element; + CFilePathProperty* fileProperty = dynamic_cast(element); + fileProperty->Exts.push_back("tga"); + fileProperty->Exts.push_back("png"); }; object->autoRelease(textureArray); - // Sync lightmap path - std::vector textureExts = { "tga","png" }; + // lightmap path + textureArray->resize((int)m_lightmapPaths.size()); for (u32 i = 0, n = (u32)m_lightmapPaths.size(); i < n; i++) { - char name[43]; - sprintf(name, "%d", i); - - textureArray->autoRelease( - new CFilePathProperty( - textureArray, - name, - m_lightmapPaths[i].c_str(), - textureExts) - ); + CFilePathProperty* fileProperty = dynamic_cast(textureArray->getElement(i)); + fileProperty->set(m_lightmapPaths[i]); } return object; @@ -155,25 +151,54 @@ namespace Skylicht { CComponentSystem::loadSerializable(object); + bool lightmapChanged = false; + EIndirectType type = object->get("type", EIndirectType::SH9); CArraySerializable* textureArray = (CArraySerializable*)object->getProperty("LMTextures"); if (textureArray != NULL) { + std::vector old = m_lightmapPaths; m_lightmapPaths.clear(); int count = textureArray->getElementCount(); for (int i = 0; i < count; i++) { - char name[43]; - sprintf(name, "%d", i); - - std::string path = textureArray->get(name, std::string()); + std::string path = textureArray->getElementValue(i, std::string()); m_lightmapPaths.push_back(path); } + + if (!isLightmapEmpty()) + lightmapChanged = isLightmapChanged(old); + } + + setIndirectLightingType(type, lightmapChanged); + } + + bool CIndirectLighting::isLightmapEmpty() + { + for (std::string& s : m_lightmapPaths) + { + if (s.empty()) + return true; + } + return false; + } + + bool CIndirectLighting::isLightmapChanged(const std::vector& paths) + { + if (paths.size() != m_lightmapPaths.size()) + return true; + + for (int i = 0, n = (int)paths.size(); i < n; i++) + { + if (paths[i] != m_lightmapPaths[i]) + { + return true; + } } - setIndirectLightingType(type); + return false; } void CIndirectLighting::setSH(core::vector3df* sh) @@ -185,7 +210,11 @@ namespace Skylicht void CIndirectLighting::setLightmap(ITexture* texture) { + if (m_internalLM && m_lightmap) + CTextureManager::getInstance()->removeTexture(m_lightmap); + m_lightmap = texture; + m_internalLM = false; } void CIndirectLighting::setAutoSH(bool b) @@ -199,7 +228,7 @@ namespace Skylicht } } - void CIndirectLighting::setIndirectLightingType(EIndirectType type) + void CIndirectLighting::setIndirectLightingType(EIndirectType type, bool loadLightmap) { m_type = type; @@ -208,8 +237,14 @@ namespace Skylicht if (m_type == LightmapArray) { // Load lightmap texture array - if (m_lightmapPaths.size() > 0 && m_lightmap == NULL) + if (m_lightmapPaths.size() > 0 && loadLightmap) + { + if (m_internalLM && m_lightmap) + CTextureManager::getInstance()->removeTexture(m_lightmap); + m_lightmap = CTextureManager::getInstance()->getTextureArray(m_lightmapPaths); + m_internalLM = true; + } data->Type = CIndirectLightingData::LightmapArray; data->LightmapTexture = m_lightmap; diff --git a/Projects/Skylicht/Engine/Source/IndirectLighting/CIndirectLighting.h b/Projects/Skylicht/Engine/Source/IndirectLighting/CIndirectLighting.h index a16f947ee..5a3ec8019 100644 --- a/Projects/Skylicht/Engine/Source/IndirectLighting/CIndirectLighting.h +++ b/Projects/Skylicht/Engine/Source/IndirectLighting/CIndirectLighting.h @@ -53,6 +53,7 @@ namespace Skylicht std::vector m_lightmapPaths; ITexture* m_lightmap; + bool m_internalLM; public: CIndirectLighting(); @@ -77,7 +78,7 @@ namespace Skylicht void setAutoSH(bool b); - void setIndirectLightingType(EIndirectType type); + void setIndirectLightingType(EIndirectType type, bool loadLightmap = true); void setLightmap(ITexture* texture); @@ -98,6 +99,9 @@ namespace Skylicht return m_data; } + bool isLightmapEmpty(); + bool isLightmapChanged(const std::vector& paths); + DECLARE_GETTYPENAME(CIndirectLighting) }; } \ No newline at end of file diff --git a/Projects/Skylicht/Engine/Source/Serializable/CArraySerializable.cpp b/Projects/Skylicht/Engine/Source/Serializable/CArraySerializable.cpp index 0cfe99872..a892294cb 100644 --- a/Projects/Skylicht/Engine/Source/Serializable/CArraySerializable.cpp +++ b/Projects/Skylicht/Engine/Source/Serializable/CArraySerializable.cpp @@ -45,7 +45,7 @@ namespace Skylicht bool CArraySerializable::resize(int count) { - if (OnCreateElement == nullptr || count < 0) + if (count < 0) return false; int numElement = getElementCount(); @@ -65,12 +65,21 @@ namespace Skylicht // need grow for (int i = numElement; i < count; i++) { - CValueProperty* value = OnCreateElement(); + CValueProperty* value = createElement(); if (!value) return false; } } + // rename + char name[32]; + numElement = getElementCount(); + for (int i = 0; i < numElement; i++) + { + sprintf(name, "[%d]", i); + getElement(i)->Name = name; + } + return true; } } \ No newline at end of file diff --git a/Projects/Skylicht/Engine/Source/Serializable/CArraySerializable.h b/Projects/Skylicht/Engine/Source/Serializable/CArraySerializable.h index ffaf8c07a..6969db6cd 100644 --- a/Projects/Skylicht/Engine/Source/Serializable/CArraySerializable.h +++ b/Projects/Skylicht/Engine/Source/Serializable/CArraySerializable.h @@ -31,10 +31,6 @@ namespace Skylicht { class CArraySerializable : public CObjectSerializable { - public: - - std::function OnCreateElement; - public: CArraySerializable(const char* name); @@ -42,6 +38,12 @@ namespace Skylicht virtual ~CArraySerializable(); + template + T getElementValue(int i, T defaultValue) + { + return get(getElement(i), defaultValue); + } + int getElementCount() { return getNumProperty(); @@ -52,6 +54,16 @@ namespace Skylicht return getPropertyID(i); } + virtual bool haveCreateElementFunction() + { + return false; + } + + virtual CValueProperty* createElement() + { + return NULL; + } + bool resize(int count); virtual bool isArray() @@ -59,4 +71,50 @@ namespace Skylicht return true; } }; + + template + class CArrayTypeSerializable : public CArraySerializable + { + public: + std::function OnCreateElement; + + public: + CArrayTypeSerializable(const char* name) : + CArraySerializable(name) + { + + } + + CArrayTypeSerializable(const char* name, CObjectSerializable* parent) : + CArraySerializable(name, parent) + { + + } + + virtual bool haveCreateElementFunction() + { + return true; + } + + virtual CValueProperty* createElement() + { + T* t = new T(); + CValueProperty* element = dynamic_cast(t); + if (element == NULL) + { + delete t; + return NULL; + } + + addProperty(element); + autoRelease(element); + + if (OnCreateElement != nullptr) + { + OnCreateElement(element); + } + + return element; + } + }; } \ No newline at end of file diff --git a/Projects/Skylicht/Engine/Source/Serializable/CObjectSerializable.h b/Projects/Skylicht/Engine/Source/Serializable/CObjectSerializable.h index 7f2bbf11b..bd7847b20 100644 --- a/Projects/Skylicht/Engine/Source/Serializable/CObjectSerializable.h +++ b/Projects/Skylicht/Engine/Source/Serializable/CObjectSerializable.h @@ -99,6 +99,16 @@ namespace Skylicht return t->get(); } + template + T get(CValueProperty* p, T defaultValue) + { + CValuePropertyTemplate* t = dynamic_cast*>(p); + if (t == NULL) + return defaultValue; + + return t->get(); + } + virtual void serialize(io::IAttributes* io); virtual void deserialize(io::IAttributes* io); diff --git a/Projects/Skylicht/Engine/Source/Serializable/CValuePropertyTemplate.h b/Projects/Skylicht/Engine/Source/Serializable/CValuePropertyTemplate.h index e4967ac7b..2927bd04e 100644 --- a/Projects/Skylicht/Engine/Source/Serializable/CValuePropertyTemplate.h +++ b/Projects/Skylicht/Engine/Source/Serializable/CValuePropertyTemplate.h @@ -70,6 +70,11 @@ namespace Skylicht bool ClampMax; public: + CIntProperty() : + CIntProperty(NULL, "CIntProperty") + { + } + CIntProperty(CObjectSerializable* owner, const char* name) : CValuePropertyTemplate(owner, Integer, name), Min(INT_MIN), @@ -139,6 +144,11 @@ namespace Skylicht bool ClampMax; public: + CUIntProperty() : + CUIntProperty(NULL, "CUIntProperty") + { + } + CUIntProperty(CObjectSerializable* owner, const char* name) : CValuePropertyTemplate(owner, UInteger, name), Max(UINT_MAX), @@ -192,6 +202,11 @@ namespace Skylicht bool ClampMax; public: + CFloatProperty() : + CFloatProperty(NULL, "CFloatProperty") + { + } + CFloatProperty(CObjectSerializable* owner, const char* name) : CValuePropertyTemplate(owner, Float, name), ClampMin(false), @@ -257,6 +272,11 @@ namespace Skylicht class CStringProperty : public CValuePropertyTemplate { public: + CStringProperty() : + CStringProperty(NULL, "CStringProperty") + { + } + CStringProperty(CObjectSerializable* owner, const char* name) : CValuePropertyTemplate(owner, String, name) { @@ -294,6 +314,11 @@ namespace Skylicht class CFolderPathProperty : public CValuePropertyTemplate { public: + CFolderPathProperty() : + CFolderPathProperty(NULL, "CFolderPathProperty") + { + } + CFolderPathProperty(CObjectSerializable* owner, const char* name) : CValuePropertyTemplate(owner, FolderPath, name) { @@ -334,6 +359,11 @@ namespace Skylicht std::vector Exts; public: + CFilePathProperty() : + CFilePathProperty(NULL, "CFilePathProperty") + { + } + CFilePathProperty(CObjectSerializable* owner, const char* name) : CValuePropertyTemplate(owner, FilePath, name) { @@ -380,6 +410,11 @@ namespace Skylicht class CBoolProperty : public CValuePropertyTemplate { public: + CBoolProperty() : + CBoolProperty(NULL, "CBoolProperty") + { + } + CBoolProperty(CObjectSerializable* owner, const char* name) : CValuePropertyTemplate(owner, Bool, name) { @@ -412,6 +447,11 @@ namespace Skylicht class CDateTimeProperty : public CValuePropertyTemplate { public: + CDateTimeProperty() : + CDateTimeProperty(NULL, "CDateTimeProperty") + { + } + CDateTimeProperty(CObjectSerializable* owner, const char* name) : CValuePropertyTemplate(owner, DateTime, name) { @@ -445,6 +485,11 @@ namespace Skylicht class CVector3Property : public CValuePropertyTemplate { public: + CVector3Property() : + CVector3Property(NULL, "CVector3Property") + { + } + CVector3Property(CObjectSerializable* owner, const char* name) : CValuePropertyTemplate(owner, Vector3, name) { @@ -478,6 +523,11 @@ namespace Skylicht class CQuaternionProperty : public CValuePropertyTemplate { public: + CQuaternionProperty() : + CQuaternionProperty(NULL, "CVector3Property") + { + } + CQuaternionProperty(CObjectSerializable* owner, const char* name) : CValuePropertyTemplate(owner, Quaternion, name) { @@ -511,6 +561,11 @@ namespace Skylicht class CColorProperty : public CValuePropertyTemplate { public: + CColorProperty() : + CColorProperty(NULL, "CColorProperty") + { + } + CColorProperty(CObjectSerializable* owner, const char* name) : CValuePropertyTemplate(owner, Color, name) { @@ -544,6 +599,11 @@ namespace Skylicht class CMatrixProperty : public CValuePropertyTemplate { public: + CMatrixProperty() : + CMatrixProperty(NULL, "CMatrixProperty") + { + } + CMatrixProperty(CObjectSerializable* owner, const char* name) : CValuePropertyTemplate(owner, Matrix4, name) {