PageRenderTime 50ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/Code/CryEngine/CryAction/FlowSystem/Nodes/FlowCompositeNode.cpp

https://gitlab.com/dahbearz/CRYENGINE
C++ | 437 lines | 357 code | 60 blank | 20 comment | 42 complexity | d238d3617c0824b7fe8a1e055ea50281 MD5 | raw file
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2. #include "StdAfx.h"
  3. #include "FlowCompositeNode.h"
  4. #include "../FlowSystem.h"
  5. #include "../FlowSerialize.h"
  6. #include "FlowBaseNode.h"
  7. using namespace NFlowCompositeHelpers;
  8. static const char* INTERIOR_NODE_TYPE = "CompositeInterior";
  9. /*
  10. * inner-node
  11. */
  12. CCompositeInteriorNode::CCompositeInteriorNode(CFlowCompositeNodeFactoryPtr pFactory)
  13. : m_refs(0)
  14. , m_pFactory(pFactory)
  15. , m_pParent(nullptr)
  16. {
  17. }
  18. void CCompositeInteriorNode::AddRef()
  19. {
  20. ++m_refs;
  21. }
  22. void CCompositeInteriorNode::Release()
  23. {
  24. if (0 == --m_refs)
  25. delete this;
  26. }
  27. IFlowNodePtr CCompositeInteriorNode::Clone(SActivationInfo*)
  28. {
  29. return this;
  30. }
  31. void CCompositeInteriorNode::GetConfiguration(SFlowNodeConfig& config)
  32. {
  33. m_pFactory->GetConfiguration(false, config);
  34. }
  35. void CCompositeInteriorNode::ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  36. {
  37. switch (event)
  38. {
  39. case eFE_Activate:
  40. {
  41. size_t numPorts = m_pFactory->GetInputPortCount(false);
  42. TFlowNodeId interfaceNode = m_pFactory->GetInterfaceNode();
  43. CCompositeGraph* pMyGraph = (CCompositeGraph*) pActInfo->pGraph;
  44. pActInfo = pMyGraph->GetParentInfo();
  45. for (size_t i = 0; i < numPorts; i++)
  46. {
  47. if (pActInfo->pInputPorts[i].IsUserFlagSet())
  48. pActInfo->pGraph->ActivatePort(SFlowAddress(pActInfo->myID, static_cast<TFlowPortId>(i), true), pActInfo->pInputPorts[i]);
  49. }
  50. }
  51. break;
  52. }
  53. }
  54. bool CCompositeInteriorNode::SerializeXML(SActivationInfo*, const XmlNodeRef& root, bool reading)
  55. {
  56. return true;
  57. }
  58. void CCompositeInteriorNode::Serialize(SActivationInfo*, TSerialize ser)
  59. {
  60. }
  61. void CCompositeInteriorNode::GetMemoryUsage(ICrySizer* s) const
  62. {
  63. s->Add(*this);
  64. }
  65. /*
  66. * hook
  67. */
  68. CHook::CHook(CFlowSystem* pFlowSystem, CFlowCompositeNodeFactoryPtr pFactory)
  69. : m_refs(0), m_pFlowSystem(pFlowSystem), m_pFactory(pFactory), m_id(InvalidFlowNodeId), m_bFail(false)
  70. {
  71. }
  72. void CHook::Release()
  73. {
  74. if (0 == --m_refs)
  75. delete this;
  76. }
  77. void CHook::AddRef()
  78. {
  79. ++m_refs;
  80. }
  81. IFlowNodePtr CHook::CreateNode(IFlowNode::SActivationInfo*, TFlowNodeTypeId typeId)
  82. {
  83. if (!strcmp(INTERIOR_NODE_TYPE, m_pFlowSystem->GetTypeName(typeId)))
  84. return new CCompositeInteriorNode(m_pFactory);
  85. return IFlowNodePtr();
  86. }
  87. bool CHook::CreatedNode(TFlowNodeId id, const char* name, TFlowNodeTypeId typeId, IFlowNodePtr pNode)
  88. {
  89. if (!strcmp(INTERIOR_NODE_TYPE, m_pFlowSystem->GetTypeName(typeId)))
  90. {
  91. if (m_id != InvalidFlowNodeId)
  92. m_bFail = true;
  93. else
  94. m_id = id;
  95. }
  96. return !m_bFail;
  97. }
  98. void CHook::CancelCreatedNode(TFlowNodeId id, const char* name, TFlowNodeTypeId typeId, IFlowNodePtr pNode)
  99. {
  100. if (id == m_id)
  101. {
  102. m_id = InvalidFlowNodeId;
  103. m_bFail = true;
  104. }
  105. }
  106. /*
  107. * graph
  108. */
  109. CCompositeGraph::CCompositeGraph(CFlowSystem* pSys) : CFlowGraph(pSys), m_pParent(NULL)
  110. {
  111. }
  112. IFlowGraphPtr CCompositeGraph::Clone()
  113. {
  114. CCompositeGraph* pClone = new CCompositeGraph(GetSys());
  115. CloneInner(pClone);
  116. return pClone;
  117. }
  118. IFlowNode::SActivationInfo* CCompositeGraph::GetParentInfo()
  119. {
  120. return m_pParent->GetParentInfo();
  121. }
  122. void CCompositeGraph::GetMemoryUsage(ICrySizer* s) const
  123. {
  124. s->Add(*this);
  125. CFlowGraph::GetMemoryUsage(s);
  126. }
  127. /*
  128. * node
  129. */
  130. CFlowCompositeNode::CFlowCompositeNode(SActivationInfo* pActInfo, IFlowGraphPtr pGraph, CFlowCompositeNodeFactoryPtr pFactory)
  131. : m_refs(0), m_parentInfo(*pActInfo), m_pGraph(pGraph), m_pFactory(pFactory)
  132. {
  133. ((CCompositeGraph*)&*pGraph)->Reparent(this);
  134. pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, true);
  135. }
  136. void CFlowCompositeNode::AddRef()
  137. {
  138. ++m_refs;
  139. }
  140. void CFlowCompositeNode::Release()
  141. {
  142. if (0 == --m_refs)
  143. delete this;
  144. }
  145. IFlowNodePtr CFlowCompositeNode::Clone(SActivationInfo* pActInfo)
  146. {
  147. CFlowCompositeNode* out = new CFlowCompositeNode(pActInfo, m_pGraph->Clone(), m_pFactory);
  148. return out;
  149. }
  150. void CFlowCompositeNode::GetConfiguration(SFlowNodeConfig& config)
  151. {
  152. m_pFactory->GetConfiguration(true, config);
  153. }
  154. void CFlowCompositeNode::ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  155. {
  156. switch (event)
  157. {
  158. case eFE_Update:
  159. m_pGraph->Update();
  160. break;
  161. case eFE_Activate:
  162. case eFE_Initialize:
  163. {
  164. size_t numPorts = m_pFactory->GetInputPortCount(true);
  165. TFlowNodeId interfaceNode = m_pFactory->GetInterfaceNode();
  166. for (size_t i = 0; i < numPorts; i++)
  167. {
  168. if (pActInfo->pInputPorts[i].IsUserFlagSet())
  169. m_pGraph->ActivatePort(SFlowAddress(interfaceNode, static_cast<TFlowPortId>(i), true), pActInfo->pInputPorts[i]);
  170. }
  171. }
  172. break;
  173. }
  174. }
  175. bool CFlowCompositeNode::SerializeXML(SActivationInfo*, const XmlNodeRef& root, bool reading)
  176. {
  177. return false;
  178. }
  179. void CFlowCompositeNode::Serialize(SActivationInfo*, TSerialize ser)
  180. {
  181. ser.BeginGroup("ChildGraph");
  182. m_pGraph->Serialize(ser);
  183. ser.EndGroup();
  184. }
  185. void CFlowCompositeNode::GetMemoryUsage(ICrySizer* s) const
  186. {
  187. s->Add(*this);
  188. m_pGraph->GetMemoryUsage(s);
  189. }
  190. /*
  191. * factory
  192. */
  193. CFlowCompositeNodeFactory::CFlowCompositeNodeFactory() :
  194. m_nRefs(0)
  195. {
  196. }
  197. CFlowCompositeNodeFactory::~CFlowCompositeNodeFactory()
  198. {
  199. }
  200. CFlowCompositeNodeFactory::EInitResult CFlowCompositeNodeFactory::Init(XmlNodeRef node, CFlowSystem* pSystem)
  201. {
  202. XmlNodeRef ports = node->findChild("Ports");
  203. if (!ports)
  204. {
  205. GameWarning("[flow] Composite %s has no ports", node->getAttr("name"));
  206. return eIR_Failed;
  207. }
  208. int nPorts = ports->getChildCount();
  209. for (int i = 0; i < nPorts; i++)
  210. {
  211. XmlNodeRef port = ports->getChild(i);
  212. if (!port)
  213. {
  214. GameWarning("[flow] Composite %s has no port %d", node->getAttr("name"), i);
  215. return eIR_Failed;
  216. }
  217. const char* tag = port->getTag();
  218. TPortPairPtr pPorts = GeneratePortsFromXML(port);
  219. if (!pPorts.get())
  220. {
  221. GameWarning("[flow] Composite %s cannot generate port %d", node->getAttr("name"), i);
  222. return eIR_Failed;
  223. }
  224. if (0 == strcmp("Input", tag))
  225. {
  226. m_inputsExt.push_back(pPorts->first);
  227. m_outputsInt.push_back(pPorts->second);
  228. }
  229. else if (0 == strcmp("Output", tag))
  230. {
  231. m_inputsInt.push_back(pPorts->first);
  232. m_outputsExt.push_back(pPorts->second);
  233. }
  234. else
  235. {
  236. GameWarning("[flow] Composite %s - no such port type %s (on port %d)", node->getAttr("name"), tag, i);
  237. return eIR_Failed;
  238. }
  239. }
  240. SOutputPortConfig termOut = { 0 };
  241. m_outputsInt.push_back(termOut);
  242. m_outputsExt.push_back(termOut);
  243. SInputPortConfig termIn = { 0 };
  244. m_inputsInt.push_back(termIn);
  245. m_inputsExt.push_back(termIn);
  246. CRY_ASSERT(m_nRefs);
  247. CHookPtr pHook = new CHook(pSystem, this);
  248. m_pPrototypeGraph = new CCompositeGraph(pSystem);
  249. m_pPrototypeGraph->RegisterHook(&*pHook);
  250. if (!m_pPrototypeGraph->SerializeXML(node, true))
  251. return eIR_NotYet;
  252. m_interfaceNode = pHook->GetID();
  253. m_pPrototypeGraph->UnregisterHook(&*pHook);
  254. if (m_interfaceNode == InvalidFlowNodeId)
  255. {
  256. GameWarning("[flow] Composite %s has no %s node", node->getAttr("name"), INTERIOR_NODE_TYPE);
  257. return eIR_Failed;
  258. }
  259. return eIR_Ok;
  260. }
  261. void CFlowCompositeNodeFactory::GetConfiguration(bool exterior, SFlowNodeConfig& config)
  262. {
  263. if (exterior)
  264. {
  265. config.pInputPorts = &m_inputsExt[0];
  266. config.pOutputPorts = &m_outputsExt[0];
  267. }
  268. else
  269. {
  270. config.pInputPorts = &m_inputsInt[0];
  271. config.pOutputPorts = &m_outputsInt[0];
  272. }
  273. }
  274. void CFlowCompositeNodeFactory::AddRef()
  275. {
  276. ++m_nRefs;
  277. }
  278. void CFlowCompositeNodeFactory::Release()
  279. {
  280. if (0 == --m_nRefs)
  281. delete this;
  282. }
  283. IFlowNodePtr CFlowCompositeNodeFactory::Create(IFlowNode::SActivationInfo* pActInfo)
  284. {
  285. return new CFlowCompositeNode(pActInfo, m_pPrototypeGraph->Clone(), this);
  286. }
  287. const string& CFlowCompositeNodeFactory::AddString(const char* str)
  288. {
  289. m_stringPool.push_back(str);
  290. return m_stringPool.back();
  291. }
  292. CFlowCompositeNodeFactory::TPortPairPtr CFlowCompositeNodeFactory::GeneratePortsFromXML(XmlNodeRef port)
  293. {
  294. TPortPairPtr result(new TPortPair);
  295. const char* c_name = port->getAttr("name");
  296. if (!c_name || !c_name[0])
  297. {
  298. GameWarning("[flow] Composite: Port has no name!");
  299. return TPortPairPtr();
  300. }
  301. const string& name = AddString(c_name);
  302. int type = -1;
  303. if (port->getAttr("type", type))
  304. {
  305. if (type != -1)
  306. {
  307. if (!result->first.defaultData.SetDefaultForTag(type))
  308. {
  309. GameWarning("[flow] Composite: No node type %d", type);
  310. return TPortPairPtr();
  311. }
  312. result->first.defaultData.SetLocked();
  313. if (!SetFromString(result->first.defaultData, port->getAttr("value")))
  314. {
  315. GameWarning("[flow] Composite: Data '%s' is invalid for type %d", port->getAttr("value"), type);
  316. return TPortPairPtr();
  317. }
  318. }
  319. }
  320. if (type == -1)
  321. result->first.defaultData.SetUnlocked();
  322. result->second.type = type;
  323. result->first.name = result->second.name = name.c_str();
  324. return result;
  325. }
  326. void CFlowCompositeNodeFactory::GetMemoryUsage(ICrySizer* s) const
  327. {
  328. SIZER_SUBCOMPONENT_NAME(s, "CFlowCompositeNodeFactory");
  329. s->Add(*this);
  330. s->AddObject(m_stringPool);
  331. s->AddObject(m_inputsInt);
  332. s->AddObject(m_inputsExt);
  333. s->AddObject(m_outputsInt);
  334. s->AddObject(m_outputsExt);
  335. }
  336. //////////////////////////////////////////////////////////////////////////
  337. class CFlowNode_Composite_Input : public CFlowBaseNode<eNCT_Singleton>
  338. {
  339. public:
  340. CFlowNode_Composite_Input(SActivationInfo* pActInfo) {};
  341. virtual void GetConfiguration(SFlowNodeConfig& config)
  342. {
  343. static const SOutputPortConfig out_config[] = {
  344. OutputPortConfig_AnyType("in"),
  345. { 0 }
  346. };
  347. config.sDescription = _HELP("Input for the composite node");
  348. config.pInputPorts = 0;
  349. config.pOutputPorts = out_config;
  350. config.SetCategory(EFLN_ADVANCED);
  351. }
  352. void ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  353. {
  354. }
  355. };
  356. //////////////////////////////////////////////////////////////////////////
  357. class CFlowNode_Composite_Output : public CFlowBaseNode<eNCT_Singleton>
  358. {
  359. public:
  360. CFlowNode_Composite_Output(SActivationInfo* pActInfo) {};
  361. virtual void GetConfiguration(SFlowNodeConfig& config)
  362. {
  363. static const SInputPortConfig in_config[] = {
  364. InputPortConfig_AnyType("out"),
  365. { 0 }
  366. };
  367. config.sDescription = _HELP("Output for the composite node");
  368. config.pInputPorts = in_config;
  369. config.pOutputPorts = 0;
  370. config.SetCategory(EFLN_ADVANCED);
  371. }
  372. void ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  373. {
  374. }
  375. };
  376. // REGISTER_FLOW_NODE("Composite:Input", CFlowNode_Composite_Input );
  377. // REGISTER_FLOW_NODE("Composite:Output", CFlowNode_Composite_Output );