!B (Sandbox) (CE-21795) Importing models with multisubmaterials via fbx switches...
[CRYENGINE.git] / Code / CryEngine / CrySchematyc2 / Script / Elements / ScriptClassBase.cpp
blob192281a23a524710dfc56043e31a1f9de10bce3d
1 // Copyright 2001-2019 Crytek GmbH / Crytek Group. All rights reserved.
3 #include "StdAfx.h"
4 #include "Script/Elements/ScriptClassBase.h"
6 #include <CrySerialization/BlackBox.h>
7 #include <CrySerialization/IArchiveHost.h>
8 #include <CrySerialization/STL.h>
9 #include <CrySchematyc2/GUIDRemapper.h>
10 #include <CrySchematyc2/Deprecated/DocUtils.h>
11 #include <CrySchematyc2/Serialization/ISerializationContext.h>
12 #include <CrySchematyc2/Serialization/SerializationUtils.h>
14 namespace Schematyc2
16 typedef std::unordered_map<SGUID, IScriptProperty*> PropertyMap;
17 typedef std::unordered_map<SGUID, const IScriptProperty*> BasePropertyMap;
18 typedef std::vector<const IScriptGroup*> Groups;
20 namespace ScriptClassBaseUtils
22 struct SPropertyCollector
24 SPropertyCollector(PropertyMap& _properties, IScriptFile& _file, const SGUID& _scopeGUID)
25 : properties(_properties)
26 , file(_file)
27 , scopeGUID(_scopeGUID)
29 file.VisitElements(ScriptElementVisitor::FromMemberFunction<SPropertyCollector, &SPropertyCollector::VisitElement>(*this), scopeGUID, false);
32 EVisitStatus VisitElement(IScriptElement& element)
34 switch(element.GetElementType())
36 case EScriptElementType::Group:
38 file.VisitElements(ScriptElementVisitor::FromMemberFunction<SPropertyCollector, &SPropertyCollector::VisitElement>(*this), element.GetGUID(), false);
39 break;
41 case EScriptElementType::Property:
43 IScriptProperty& property = static_cast<IScriptProperty&>(element);
44 properties.insert(PropertyMap::value_type(property.GetRefGUID(), &property));
45 break;
48 return EVisitStatus::Continue;
51 PropertyMap& properties;
52 IScriptFile& file;
53 SGUID scopeGUID;
56 struct SBasePropertyCollector
58 SBasePropertyCollector(BasePropertyMap& _properties, const IScriptFile& _file, const SGUID& _scopeGUID)
59 : properties(_properties)
60 , file(_file)
61 , scopeGUID(_scopeGUID)
63 file.VisitElements(ScriptElementConstVisitor::FromMemberFunction<SBasePropertyCollector, &SBasePropertyCollector::VisitElement>(*this), scopeGUID, false);
66 EVisitStatus VisitElement(const IScriptElement& element)
68 switch(element.GetElementType())
70 case EScriptElementType::Group:
72 file.VisitElements(ScriptElementConstVisitor::FromMemberFunction<SBasePropertyCollector, &SBasePropertyCollector::VisitElement>(*this), element.GetGUID(), false);
73 break;
75 case EScriptElementType::Property:
77 const IScriptProperty& property = static_cast<const IScriptProperty&>(element);
78 properties.insert(BasePropertyMap::value_type(property.GetGUID(), &property));
79 break;
82 return EVisitStatus::Continue;
85 BasePropertyMap& properties;
86 const IScriptFile& file;
87 SGUID scopeGUID;
90 inline const IScriptGroup* FindGroup(IScriptFile& file, const SGUID& scopeGUID, const char* szName)
92 SCHEMATYC2_SYSTEM_ASSERT(szName);
93 const IScriptGroup* pResult = nullptr;
94 auto visitGroup = [szName, &pResult] (const IScriptGroup& group) -> EVisitStatus
96 if(strcmp(szName, group.GetName()) == 0)
98 pResult = &group;
99 return EVisitStatus::End;
101 return EVisitStatus::Continue;
103 file.VisitGroups(ScriptGroupConstVisitor::FromLambdaFunction(visitGroup), scopeGUID, false);
104 return pResult;
108 CScriptClassBase::CScriptClassBase(IScriptFile& file, const SGUID& guid, const SGUID& scopeGUID, const SGUID& refGUID)
109 : CScriptElementBase(EScriptElementType::ClassBase, file)
110 , m_guid(guid)
111 , m_scopeGUID(scopeGUID)
112 , m_refGUID(refGUID)
115 EAccessor CScriptClassBase::GetAccessor() const
117 return EAccessor::Private;
120 SGUID CScriptClassBase::GetGUID() const
122 return m_guid;
125 SGUID CScriptClassBase::GetScopeGUID() const
127 return m_scopeGUID;
130 bool CScriptClassBase::SetName(const char* szName)
132 return false;
135 const char* CScriptClassBase::GetName() const
137 return m_name.c_str();
140 void CScriptClassBase::EnumerateDependencies(const ScriptDependancyEnumerator& enumerator) const
142 SCHEMATYC2_SYSTEM_ASSERT(enumerator);
143 if(enumerator)
145 enumerator(m_refGUID);
149 void CScriptClassBase::Refresh(const SScriptRefreshParams& params)
151 ScriptIncludeRecursionUtils::GetClassResult baseClass = ScriptIncludeRecursionUtils::GetClass(CScriptElementBase::GetFile(), m_refGUID);
152 if(baseClass.second)
154 m_name = baseClass.second->GetName();
155 if((params.reason == EScriptRefreshReason::EditorAdd) || (params.reason == EScriptRefreshReason::EditorFixUp) || (params.reason == EScriptRefreshReason::EditorPaste) || (params.reason == EScriptRefreshReason::EditorDependencyModified))
157 RefreshProperties(*baseClass.first, *baseClass.second);
162 void CScriptClassBase::Serialize(Serialization::IArchive& archive)
164 CRY_PROFILE_FUNCTION(PROFILE_LOADING_ONLY);
166 CScriptElementBase::Serialize(archive);
168 SerializationContext::SetValidatorLink(archive, SValidatorLink(m_guid)); // #SchematycTODO : Can we set this from CScriptElementBase?
169 switch(SerializationContext::GetPass(archive))
171 case ESerializationPass::PreLoad:
172 case ESerializationPass::Save:
174 Serialization::SContext fileContext(archive, static_cast<IScriptFile*>(&CScriptElementBase::GetFile())); // #SchematycTODO : Do we still need this?
175 Serialization::SContext context(archive, static_cast<IScriptClassBase*>(this)); // #SchematycTODO : Do we still need this?
177 archive(m_guid, "guid");
178 archive(m_scopeGUID, "scopeGUID");
179 archive(m_refGUID, "refGUID");
180 archive(m_userDocumentation, "userDocumentation", "Documentation");
181 break;
183 case ESerializationPass::Validate:
185 Validate(archive);
186 break;
191 void CScriptClassBase::RemapGUIDs(IGUIDRemapper& guidRemapper)
193 m_guid = guidRemapper.Remap(m_guid);
194 m_scopeGUID = guidRemapper.Remap(m_scopeGUID);
195 m_refGUID = guidRemapper.Remap(m_refGUID);
198 SGUID CScriptClassBase::GetRefGUID() const
200 return m_refGUID;
203 void CScriptClassBase::RefreshProperties(const IScriptFile& baseClassFile, const IScriptClass& baseClass)
205 // Retrieve derived properties and properties from base class.
206 IScriptFile& file = CScriptElementBase::GetFile();
207 PropertyMap properties;
208 ScriptClassBaseUtils::SPropertyCollector(properties, file, m_guid);
209 BasePropertyMap baseProperties;
210 ScriptClassBaseUtils::SBasePropertyCollector(baseProperties, baseClassFile, m_refGUID);
211 // Remove all derived properties that are either finalized of no longer part of base class.
212 for(PropertyMap::value_type& property : properties)
214 BasePropertyMap::iterator itBaseProperty = baseProperties.find(property.first);
215 if((itBaseProperty == baseProperties.end()) || (itBaseProperty->second->GetOverridePolicy() == EOverridePolicy::Finalize))
217 file.RemoveElement(property.second->GetGUID(), true);
220 // Create/update derived properties.
221 for(const BasePropertyMap::value_type& baseProperty : baseProperties)
223 if(baseProperty.second->GetOverridePolicy() != EOverridePolicy::Finalize)
225 PropertyMap::iterator itProperty = properties.find(baseProperty.first);
226 if(itProperty != properties.end())
228 // Update derived property name.
229 itProperty->second->SetName(baseProperty.second->GetName());
231 else
233 // Retrieve group hierarchy from base class.
234 Groups baseGroups;
235 SGUID baseScopeGUID = baseProperty.second->GetScopeGUID();
236 while(baseScopeGUID != m_refGUID)
238 const IScriptGroup* pBaseGroup = baseClassFile.GetGroup(baseScopeGUID);
239 SCHEMATYC2_SYSTEM_ASSERT(pBaseGroup);
240 if(pBaseGroup)
242 baseGroups.push_back(pBaseGroup);
243 baseScopeGUID = pBaseGroup->GetScopeGUID();
245 else
247 break;
250 std::reverse(baseGroups.begin(), baseGroups.end());
251 // Clone group hierarchy.
252 SGUID scopeGUID = m_guid;
253 for(const IScriptGroup* pBaseGroup : baseGroups)
255 const char* szGroupName = pBaseGroup->GetName();
256 const IScriptGroup* pGroup = ScriptClassBaseUtils::FindGroup(file, scopeGUID, szGroupName);
257 if(!pGroup)
259 pGroup = file.AddGroup(scopeGUID, szGroupName);
261 SCHEMATYC2_SYSTEM_ASSERT(pGroup);
262 if(pGroup)
264 scopeGUID = pGroup->GetGUID();
267 // Create new derived property.
268 file.AddProperty(scopeGUID, baseProperty.second->GetName(), baseProperty.first, baseProperty.second->GetTypeId());
274 void CScriptClassBase::Validate(Serialization::IArchive& archive)
276 if(m_refGUID)
278 const IScriptClass* pBaseClass = ScriptIncludeRecursionUtils::GetClass(CScriptElementBase::GetFile(), m_refGUID).second;
279 if(!pBaseClass)
281 archive.error(*this, "Unable to retrieve base class!");