!B (Sandbox) (CE-21795) Importing models with multisubmaterials via fbx switches...
[CRYENGINE.git] / Code / CryEngine / CrySchematyc2 / Deprecated / DocGraphNodes / DocGraphSwitchNode.cpp
blob91b08bed7c3c0c1097f787301b6f892fca2c96ed
1 // Copyright 2001-2019 Crytek GmbH / Crytek Group. All rights reserved.
3 #include "StdAfx.h"
4 #include "Deprecated/DocGraphNodes/DocGraphSwitchNode.h"
6 #include <CryString/CryStringUtils.h>
7 #include <CrySchematyc2/ICompiler.h>
8 #include <CrySchematyc2/LibUtils.h>
9 #include <CrySchematyc2/Deprecated/DocUtils.h>
10 #include <CrySchematyc2/Deprecated/IGlobalFunction.h>
11 #include <CrySchematyc2/Utils/ToString.h>
13 #include "AggregateTypeIdSerialize.h"
14 #include "Deprecated/DocGraphNodes/DocGraphNodeBase.h"
15 #include "Script/ScriptVariableDeclaration.h"
17 namespace Schematyc2
19 //////////////////////////////////////////////////////////////////////////
20 CDocGraphSwitchNode::CDocGraphSwitchNode(IScriptFile& file, IDocGraph& graph, const SGUID& guid, const SGUID& contextGUID, const SGUID& refGUID, Vec2 pos)
21 : CDocGraphNodeBase(file, graph, guid, "Switch", EScriptGraphNodeType::Switch, contextGUID, refGUID, pos)
23 if(const IEnvTypeDesc* pTypeDesc = gEnv->pSchematyc2->GetEnvRegistry().GetTypeDesc(GetEnvTypeId<int32>()))
25 m_typeId = pTypeDesc->GetTypeInfo().GetTypeId();
26 m_pValue = pTypeDesc->Create();
30 //////////////////////////////////////////////////////////////////////////
31 IAnyConstPtr CDocGraphSwitchNode::GetCustomOutputDefault() const
33 return MakeScriptVariableValueShared(CDocGraphNodeBase::GetFile(), m_typeId);
36 //////////////////////////////////////////////////////////////////////////
37 void CDocGraphSwitchNode::EnumerateOptionalOutputs(const ScriptGraphNodeOptionalOutputEnumerator& enumerator) {}
39 //////////////////////////////////////////////////////////////////////////
40 size_t CDocGraphSwitchNode::AddCustomOutput(const IAny& value)
42 char stringBuffer[512] = "";
43 ToString(value, stringBuffer);
44 if(stringBuffer[0])
46 m_cases.push_back(SCase(value.Clone()));
47 return CDocGraphNodeBase::AddOutput(stringBuffer, EScriptGraphPortFlags::Removable | EScriptGraphPortFlags::Execute);
49 return INVALID_INDEX;
52 //////////////////////////////////////////////////////////////////////////
53 size_t CDocGraphSwitchNode::AddOptionalOutput(const char* szName, EScriptGraphPortFlags flags, const CAggregateTypeId& typeId)
55 return INVALID_INDEX;
58 //////////////////////////////////////////////////////////////////////////
59 void CDocGraphSwitchNode::RemoveOutput(size_t outputIdx)
61 CDocGraphNodeBase::RemoveOutput(outputIdx);
62 m_cases.erase(m_cases.begin() + (outputIdx - EOutputIdx::FirstCase));
65 //////////////////////////////////////////////////////////////////////////
66 void CDocGraphSwitchNode::Refresh(const SScriptRefreshParams& params)
68 CRY_PROFILE_FUNCTION(PROFILE_LOADING_ONLY);
70 CDocGraphNodeBase::Refresh(params);
72 if(!ValidateScriptVariableTypeInfo(CDocGraphNodeBase::GetFile(), m_typeId))
74 SetType(CAggregateTypeId());
77 CDocGraphNodeBase::AddInput("In", EScriptGraphPortFlags::MultiLink | EScriptGraphPortFlags::Execute);
78 CDocGraphNodeBase::AddInput("Value", EScriptGraphPortFlags::None, m_pValue ? m_pValue->GetTypeInfo().GetTypeId() : CAggregateTypeId());
79 CDocGraphNodeBase::AddOutput("Default", EScriptGraphPortFlags::Execute | EScriptGraphPortFlags::SpacerBelow);
81 uint32 invalidCaseCount = 0;
82 for(SCase& _case : m_cases)
84 char outputName[512] = "";
85 if(_case.pValue)
87 ToString(*_case.pValue, outputName);
89 if(!outputName[0])
91 cry_sprintf(outputName, "INVALID_CASE[%d]", ++ invalidCaseCount);
93 CDocGraphNodeBase::AddOutput(outputName, EScriptGraphPortFlags::Removable | EScriptGraphPortFlags::Execute);
97 //////////////////////////////////////////////////////////////////////////
98 void CDocGraphSwitchNode::Serialize(Serialization::IArchive& archive)
100 CRY_PROFILE_FUNCTION(PROFILE_LOADING_ONLY);
102 CDocGraphNodeBase::Serialize(archive);
104 if(archive.isEdit())
106 TypeIds typeIds;
107 Serialization::StringList typeNames;
108 if(const IEnvTypeDesc* pTypeDesc = gEnv->pSchematyc2->GetEnvRegistry().GetTypeDesc(GetEnvTypeId<int32>()))
110 typeIds.push_back(pTypeDesc->GetTypeInfo().GetTypeId());
111 typeNames.push_back(pTypeDesc->GetName());
113 if(const IEnvTypeDesc* pTypeDesc = gEnv->pSchematyc2->GetEnvRegistry().GetTypeDesc(GetEnvTypeId<uint32>()))
115 typeIds.push_back(pTypeDesc->GetTypeInfo().GetTypeId());
116 typeNames.push_back(pTypeDesc->GetName());
118 if(const IEnvTypeDesc* pTypeDesc = gEnv->pSchematyc2->GetEnvRegistry().GetTypeDesc(GetEnvTypeId<CPoolString>()))
120 typeIds.push_back(pTypeDesc->GetTypeInfo().GetTypeId());
121 typeNames.push_back(pTypeDesc->GetName());
124 STypeVisitor typeVisitor(typeIds, typeNames);
125 gEnv->pSchematyc2->GetEnvRegistry().VisitTypeDescs(EnvTypeDescVisitor::FromMemberFunction<STypeVisitor, &STypeVisitor::VisitEnvTypeDesc>(typeVisitor));
126 ScriptIncludeRecursionUtils::VisitEnumerations(CDocGraphNodeBase::GetFile(), ScriptIncludeRecursionUtils::EnumerationVisitor::FromMemberFunction<STypeVisitor, &STypeVisitor::VisitScriptEnumeration>(typeVisitor), SGUID(), true);
128 if(archive.isInput())
130 Serialization::StringListValue typeName(typeNames, 0);
131 archive(typeName, "typeName", "Type");
132 SetType(typeIds[typeName.index()]);
134 else if(archive.isOutput())
136 int typeIdx;
137 TypeIds::iterator itTypeId = std::find(typeIds.begin(), typeIds.end(), m_typeId);
138 if(itTypeId != typeIds.end())
140 typeIdx = static_cast<int>(itTypeId - typeIds.begin());
142 else
144 typeIds.push_back(m_typeId);
145 typeNames.push_back("");
146 typeIdx = static_cast<int>(typeIds.size() - 1);
149 Serialization::StringListValue typeName(typeNames, typeIdx);
150 archive(typeName, "typeName", "Type");
153 if(m_pValue)
155 archive(*m_pValue, "value", "Value");
158 else
160 if(archive.isInput())
162 CAggregateTypeId typeId;
163 if(!archive(typeId, "typeId"))
165 PatchAggregateTypeIdFromDocVariableTypeInfo(archive, typeId, "typeInfo");
167 SetType(typeId);
169 else if(archive.isOutput())
171 archive(m_typeId, "typeId");
174 if(m_pValue)
176 archive(*m_pValue, "value");
180 Serialization::SContext context(archive, static_cast<CDocGraphSwitchNode*>(this));
181 archive(m_cases, "cases", "Cases");
183 if(archive.isInput())
185 Refresh(SScriptRefreshParams(EScriptRefreshReason::Other)); // #SchematycTODO : Should we really need to refresh manually or should the system take care of that?
188 if(archive.isValidation())
190 Validate(archive);
194 //////////////////////////////////////////////////////////////////////////
195 void CDocGraphSwitchNode::PreCompileSequence(IDocGraphSequencePreCompiler& preCompiler, size_t outputIdx) const {}
197 //////////////////////////////////////////////////////////////////////////
198 void CDocGraphSwitchNode::LinkSequence(IDocGraphSequenceLinker& linker, size_t outputIdx, const LibFunctionId& functionId) const {}
200 //////////////////////////////////////////////////////////////////////////
201 void CDocGraphSwitchNode::Compile(IDocGraphNodeCompiler& compiler, EDocGraphSequenceStep sequenceStep, size_t portIdx) const
203 switch(sequenceStep)
205 case EDocGraphSequenceStep::BeginInput:
207 CompileInputs(compiler);
208 break;
210 case EDocGraphSequenceStep::EndInput:
212 CompileEnd(compiler);
213 break;
215 case EDocGraphSequenceStep::BeginOutput:
217 CompileCaseBegin(compiler, portIdx);
218 break;
220 case EDocGraphSequenceStep::EndOutput:
222 CompileCaseEnd(compiler);
223 break;
228 //////////////////////////////////////////////////////////////////////////
229 CDocGraphSwitchNode::SCase::SCase() {}
231 //////////////////////////////////////////////////////////////////////////
232 CDocGraphSwitchNode::SCase::SCase(const IAnyPtr& _pValue)
233 : pValue(_pValue)
236 //////////////////////////////////////////////////////////////////////////
237 void CDocGraphSwitchNode::SCase::Serialize(Serialization::IArchive& archive)
239 CRY_PROFILE_FUNCTION(PROFILE_LOADING_ONLY)
241 CDocGraphSwitchNode* pSwitchNode = archive.context<CDocGraphSwitchNode>();
242 SCHEMATYC2_SYSTEM_ASSERT(pSwitchNode);
243 if(pSwitchNode)
245 if(!pValue)
247 pValue = MakeScriptVariableValueShared(pSwitchNode->GetFile(), pSwitchNode->m_typeId);
249 if(pValue)
251 archive(*pValue, "value", "^Value");
252 if(archive.isValidation())
254 char stringBuffer[512] = "";
255 ToString(*pValue, stringBuffer);
256 if(!stringBuffer[0])
258 archive.error(*this, "Empty case value!");
262 else if(archive.isValidation())
264 archive.error(*this, "Unable to instantiate value!");
269 //////////////////////////////////////////////////////////////////////////
270 CDocGraphSwitchNode::STypeVisitor::STypeVisitor(TypeIds& _typeIds, Serialization::StringList& _typeNames)
271 : typeIds(_typeIds)
272 , typeNames(_typeNames)
275 //////////////////////////////////////////////////////////////////////////
276 EVisitStatus CDocGraphSwitchNode::STypeVisitor::VisitEnvTypeDesc(const IEnvTypeDesc& typeDesc)
278 if((typeDesc.GetCategory() == EEnvTypeCategory::Enumeration) || ((typeDesc.GetFlags() & EEnvTypeFlags::Switchable) != 0))
280 typeIds.push_back(typeDesc.GetTypeInfo().GetTypeId());
281 typeNames.push_back(typeDesc.GetName());
283 return EVisitStatus::Continue;
286 //////////////////////////////////////////////////////////////////////////
287 void CDocGraphSwitchNode::STypeVisitor::VisitScriptEnumeration(const IScriptFile& enumerationFile, const IScriptEnumeration& enumeration)
289 typeIds.push_back(enumeration.GetTypeId());
290 typeNames.push_back(enumeration.GetName());
293 //////////////////////////////////////////////////////////////////////////
294 void CDocGraphSwitchNode::Validate(Serialization::IArchive& archive)
296 if(!m_pValue)
298 archive.error(*this, "Unable to instantiate value!");
301 std::vector<stack_string> caseStrings;
302 uint32 duplicateCaseValueCount = 0;
303 for(const SCase& _case : m_cases)
305 if(_case.pValue)
307 char stringBuffer[512] = "";
308 ToString(*_case.pValue, stringBuffer);
309 if(stringBuffer[0])
311 stack_string caseString = stringBuffer;
312 if(std::find(caseStrings.begin(), caseStrings.end(), caseString) != caseStrings.end())
314 ++ duplicateCaseValueCount;
316 else
318 caseStrings.push_back(caseString);
323 if(duplicateCaseValueCount)
325 archive.error(*this, "Duplicate case values detected!");
329 //////////////////////////////////////////////////////////////////////////
330 void CDocGraphSwitchNode::SetType(const CAggregateTypeId& typeId)
332 if(typeId != m_typeId)
334 m_cases.clear();
336 m_typeId = typeId;
337 m_pValue = MakeScriptVariableValueShared(CDocGraphNodeBase::GetFile(), typeId);
339 CDocGraphNodeBase::GetGraph().RemoveLinks(CDocGraphNodeBase::GetGUID());
343 //////////////////////////////////////////////////////////////////////////
344 void CDocGraphSwitchNode::CompileInputs(IDocGraphNodeCompiler& compiler) const
346 SCHEMATYC2_SYSTEM_ASSERT(m_pValue);
347 if(m_pValue)
349 compiler.CreateStackFrame(*this, EStackFrame::Value);
351 TVariantVector variants;
352 CVariantVectorOutputArchive archive(variants);
353 archive(*m_pValue);
354 const size_t typeSize = variants.size();
356 const size_t stackPos = compiler.FindInputOnStack(*this, EInputIdx::Value);
357 if(stackPos != INVALID_INDEX)
359 if(stackPos != (compiler.GetStackSize() - typeSize))
361 compiler.Copy(stackPos, INVALID_INDEX, *m_pValue, CDocGraphNodeBase::GetGUID(), GetInputName(EInputIdx::Value));
363 else
365 compiler.SetDebugInput(CDocGraphNodeBase::GetGUID(), GetInputName(EInputIdx::Value));
368 else
370 compiler.Push(*m_pValue, CDocGraphNodeBase::GetGUID(), GetInputName(EInputIdx::Value));
373 const size_t rhsPos = compiler.GetStackSize();
374 const size_t lhsPos = rhsPos - typeSize;
375 for(size_t caseIdx = 0, caseCount = m_cases.size(); caseIdx < caseCount; ++ caseIdx)
377 compiler.CreateStackFrame(*this, EStackFrame::Case);
379 IAnyConstPtr pCaseValue = m_cases[caseIdx].pValue;
380 if(pCaseValue)
382 compiler.Push(*pCaseValue, SGUID(), "");
384 else
386 SCHEMATYC2_COMPILER_ERROR("Missing case value!");
387 compiler.Push(*m_pValue, SGUID(), "");
390 compiler.Compare(lhsPos, rhsPos, typeSize);
391 compiler.BranchIfNotZero(*this, EBranchMarker::FirstCase + caseIdx);
392 compiler.CollapseStackFrame(*this, EStackFrame::Case);
397 //////////////////////////////////////////////////////////////////////////
398 void CDocGraphSwitchNode::CompileCaseBegin(IDocGraphNodeCompiler& compiler, size_t portIdx) const
400 if(portIdx > EOutputIdx::Default)
402 compiler.CreateMarker(*this, EBranchMarker::FirstCase + (portIdx - EOutputIdx::FirstCase));
404 compiler.CollapseStackFrame(*this, EStackFrame::Value);
405 compiler.CreateStackFrame(*this, EStackFrame::Value);
408 //////////////////////////////////////////////////////////////////////////
409 void CDocGraphSwitchNode::CompileCaseEnd(IDocGraphNodeCompiler& compiler) const
411 compiler.Branch(*this, EBranchMarker::End);
414 //////////////////////////////////////////////////////////////////////////
415 void CDocGraphSwitchNode::CompileEnd(IDocGraphNodeCompiler& compiler) const
417 compiler.CreateMarker(*this, EBranchMarker::End);
418 compiler.CollapseStackFrame(*this, EStackFrame::Value);