1 // Copyright 2001-2019 Crytek GmbH / Crytek Group. All rights reserved.
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>
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
)
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);
41 case EScriptElementType::Property
:
43 IScriptProperty
& property
= static_cast<IScriptProperty
&>(element
);
44 properties
.insert(PropertyMap::value_type(property
.GetRefGUID(), &property
));
48 return EVisitStatus::Continue
;
51 PropertyMap
& properties
;
56 struct SBasePropertyCollector
58 SBasePropertyCollector(BasePropertyMap
& _properties
, const IScriptFile
& _file
, const SGUID
& _scopeGUID
)
59 : properties(_properties
)
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);
75 case EScriptElementType::Property
:
77 const IScriptProperty
& property
= static_cast<const IScriptProperty
&>(element
);
78 properties
.insert(BasePropertyMap::value_type(property
.GetGUID(), &property
));
82 return EVisitStatus::Continue
;
85 BasePropertyMap
& properties
;
86 const IScriptFile
& file
;
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)
99 return EVisitStatus::End
;
101 return EVisitStatus::Continue
;
103 file
.VisitGroups(ScriptGroupConstVisitor::FromLambdaFunction(visitGroup
), scopeGUID
, false);
108 CScriptClassBase::CScriptClassBase(IScriptFile
& file
, const SGUID
& guid
, const SGUID
& scopeGUID
, const SGUID
& refGUID
)
109 : CScriptElementBase(EScriptElementType::ClassBase
, file
)
111 , m_scopeGUID(scopeGUID
)
115 EAccessor
CScriptClassBase::GetAccessor() const
117 return EAccessor::Private
;
120 SGUID
CScriptClassBase::GetGUID() const
125 SGUID
CScriptClassBase::GetScopeGUID() const
130 bool CScriptClassBase::SetName(const char* szName
)
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
);
145 enumerator(m_refGUID
);
149 void CScriptClassBase::Refresh(const SScriptRefreshParams
& params
)
151 ScriptIncludeRecursionUtils::GetClassResult baseClass
= ScriptIncludeRecursionUtils::GetClass(CScriptElementBase::GetFile(), m_refGUID
);
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");
183 case ESerializationPass::Validate
:
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
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());
233 // Retrieve group hierarchy from base class.
235 SGUID baseScopeGUID
= baseProperty
.second
->GetScopeGUID();
236 while(baseScopeGUID
!= m_refGUID
)
238 const IScriptGroup
* pBaseGroup
= baseClassFile
.GetGroup(baseScopeGUID
);
239 SCHEMATYC2_SYSTEM_ASSERT(pBaseGroup
);
242 baseGroups
.push_back(pBaseGroup
);
243 baseScopeGUID
= pBaseGroup
->GetScopeGUID();
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
);
259 pGroup
= file
.AddGroup(scopeGUID
, szGroupName
);
261 SCHEMATYC2_SYSTEM_ASSERT(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
)
278 const IScriptClass
* pBaseClass
= ScriptIncludeRecursionUtils::GetClass(CScriptElementBase::GetFile(), m_refGUID
).second
;
281 archive
.error(*this, "Unable to retrieve base class!");