Polyphase Game Engine
Loading...
Searching...
No Matches
Node.h
Go to the documentation of this file.
1#pragma once
2
3#include <string>
4#include <vector>
5
6#include "PolyphaseAPI.h"
7#include "Object.h"
8#include "Assertion.h"
9#include "EngineTypes.h"
10#include "Property.h"
11#include "Stream.h"
12#include "Factory.h"
13#include "Maths.h"
14#include "NetDatum.h"
15#include "NetFunc.h"
16#include "ScriptUtils.h"
17#include "ScriptAutoReg.h"
18#include "Signals.h"
19#include "Assets/StaticMesh.h"
20
21#include "Bullet/btBulletCollisionCommon.h"
22
23#include <unordered_map>
24#include <unordered_set>
25
26class Node;
27class Scene;
28class World;
29class Script;
30
31#define DECLARE_NODE(Class, Parent) \
32 DECLARE_FACTORY(Class, Node); \
33 DECLARE_OBJECT(Class, Parent); \
34 DECLARE_SCRIPT_LINK(Class, Parent, Node) \
35 typedef Parent Super;
36
37#define DEFINE_NODE(Class, Parent) \
38 DEFINE_FACTORY(Class, Node); \
39 DEFINE_OBJECT(Class); \
40 DEFINE_SCRIPT_LINK(Class, Parent, Node);
41
42typedef std::unordered_map<std::string, NetFunc> NetFuncMap;
43
44// Can also use a lambda for Traverse() and ForEach() functions
45typedef bool(*NodeTraversalFP)(Node*);
46
47// Forward declarations so we can use these in the Node class below
48template<typename T = Node>
50
51template<typename T = Node>
53
54#if 0
55struct NodeNetData
56{
57 std::vector<NetDatum> mReplicatedData;
58 NetId mNetId = INVALID_NET_ID;
59 NetHostId mOwningHost = INVALID_HOST_ID;
60 bool mReplicate = false;
61 bool mReplicateTransform = false;
62 bool mForceReplicate = false;
63};
64#endif
65
67{
68public:
69
74
75 // Linear-scan lookup for a registered node factory by class name. Returns
76 // nullptr if no factory matches. Used by the editor's "Add Node" menu
77 // categorization (PolyphaseEngineAPI::SetNodeCategory threads through here).
78 static Factory* FindFactory(const char* className);
79
80 static NodePtr Construct(const std::string& name);
81 static NodePtr Construct(TypeId typeId);
82 static void Destruct(Node* node);
83
84 Node();
85 virtual ~Node();
86
87 virtual void Create();
88 virtual void Destroy();
89 void DestroyDeferred();
90 void Doom(); // Alias for DestroyDeferred
91
92 virtual void SaveStream(Stream& stream, Platform platform);
93 virtual void LoadStream(Stream& stream, Platform platform, uint32_t version);
94
95 virtual void Copy(Node* srcNode, bool recurse);
96 virtual void Render(PipelineConfig pipelineConfig);
97
98 virtual void Awake();
99 virtual void Start();
100 virtual void Stop();
101 virtual void PrepareTick(std::vector<NodePtrWeak>& outTickNodes, bool game, bool recurse);
102 virtual void Tick(float deltaTime);
103 virtual void EditorTick(float deltaTime);
104 uint32_t GetLastTickedFrame() const;
105 virtual void Render();
106 virtual void OnInstanced();
107
108 // Called once, only for a node freshly created via the editor's Add Node
109 // menu (ActionSpawnNodes) -- unlike OnInstanced()/Create(), this is never
110 // called when reconstructing a node from a saved scene, subscene, or
111 // clone. Use this for starter child content that shouldn't be silently
112 // re-added every time a saved node is reloaded.
113 virtual void OnSpawnedInEditor();
114
115 virtual VertexType GetVertexType() const;
116
117 virtual void GatherProperties(std::vector<Property>& outProps) override;
118
119 virtual void GatherReplicatedData(std::vector<NetDatum>& outData);
120 virtual void GatherNetFuncs(std::vector<NetFunc>& outFuncs);
121
122 void GatherPropertyOverrides(std::vector<Property>& outOverrides);
123 void ApplyPropertyOverrides(const std::vector<Property>& overs);
124
125 virtual void BeginOverlap(Primitive3D* thisComp, Primitive3D* otherComp);
126 virtual void EndOverlap(Primitive3D* thisComp, Primitive3D* otherComp);
127 virtual void OnCollision(
128 Primitive3D* thisComp,
129 Primitive3D* otherComp,
130 glm::vec3 impactPoint,
131 glm::vec3 impactNormal,
132 btPersistentManifold* manifold);
133
134 NodeId GetNodeId() const;
135
136 uint64_t GetPersistentUuid() const;
137 void SetPersistentUuid(uint64_t uuid);
138 void EnsurePersistentUuid();
139
140 void EmitSignal(const std::string& name, const std::vector<Datum>& args);
141 void ConnectSignal(const std::string& name, Node* listener, SignalHandlerFP func);
142 void ConnectSignal(const std::string& name, Node* listener, const ScriptFunc& func);
143 void DisconnectSignal(const std::string& name, Node* listener);
144
145 void RenderShadow();
146 void RenderSelected(bool renderChildren);
147
148 Node* CreateChild(TypeId nodeType);
149 Node* CreateChild(const char* typeName);
150 Node* CreateChildClone(Node* srcNode, bool recurse);
151 NodePtr Clone(bool recurse, bool instantiateLinkedScene = true, bool resolveNodePaths = false);
152 void DestroyAllChildren();
153
154 Node* GetRoot();
155 bool IsWorldRoot() const;
156 Node* GetSubRoot();
157
158 template<class NodeClass>
159 NodeClass* CreateChild()
160 {
161 return (NodeClass*)CreateChild(NodeClass::GetStaticType());
162 }
163
164 template<class NodeClass>
166 {
167 return ResolvePtr<NodeClass>(CreateChild(NodeClass::GetStaticType()));
168 }
169
170 template<class NodeClass>
171 NodeClass* CreateChild(const char* name)
172 {
173 NodeClass* ret = (NodeClass*)CreateChild(NodeClass::GetStaticType());
174 ret->SetName(name);
175 return ret;
176 }
177
178 template<class NodeClass>
180 {
181 NodeClass* ret = (NodeClass*)CreateChild(NodeClass::GetStaticType());
182 ret->SetName(name);
183 return ResolvePtr<NodeClass>(ret);
184 }
185
186 bool IsDestroyed() const;
187 bool IsPendingDestroy() const;
188 bool IsDoomed() const;
189
190 bool HasStarted() const;
191 bool HasAwoken() const;
192
193 void EnableTick(bool enable);
194 bool IsTickEnabled() const;
195
196 virtual void SetWorld(World* world, bool subRoot);
197 World* GetWorld();
198
199 void SetScene(Scene* scene);
200 Scene* GetScene();
201
202 uint8_t GetTargetScreen() const { return mTargetScreen; }
203 void SetTargetScreen(uint8_t screen) { mTargetScreen = screen; }
204
205 // Target Screen is authored on scene-root-level nodes and is NOT inherited, so
206 // reading it off a nested node always gives the default 0. This walks up to the
207 // direct child of the scene root, which is the granularity the renderer's screen
208 // filter prunes at, and reports the screen that node actually renders on.
209 // Pass a scene root explicitly to stop there; otherwise the node's world root is used.
210 uint8_t GetEffectiveTargetScreen(Node* sceneRoot = nullptr);
211
212 std::vector<NetDatum>& GetReplicatedData();
213
214 void SetNetId(NetId id);
215 NetId GetNetId() const;
216
217 NetHostId GetOwningHost() const;
218 void SetOwningHost(NetHostId hostId, bool setAsPawn = false);
219
220 void SetReplicate(bool replicate);
221 bool IsReplicated() const;
222 void SetReplicateTransform(bool repTransform);
223 bool IsTransformReplicated() const;
224
225 void ForceReplication();
226 void ClearForcedReplication();
227 bool NeedsForcedReplication();
228
229 virtual bool CheckNetRelevance(Node* playerNode);
230 bool IsAlwaysRelevant() const;
231 void SetAlwaysRelevant(bool alwaysRelevant);
232
233 bool HasTag(const std::string& tag);
234 void AddTag(const std::string& tag);
235 void RemoveTag(const std::string& tag);
236
237 void SetName(const std::string& newName);
238 const std::string& GetName() const;
239 virtual void SetActive(bool active);
240 bool IsActive(bool recurse = false) const;
241 virtual void SetVisible(bool visible);
242 bool IsVisible(bool recurse = false) const;
243 void SetTransient(bool transient);
244 virtual bool IsTransient() const;
245 void SetPersistent(bool persistent);
246 bool IsPersistent() const;
247
248 void SetDefault(bool isDefault);
249 bool IsDefault() const;
250
251 void SetUserdataCreated(bool created);
252 bool IsUserdataCreated() const;
253
254 virtual const char* GetTypeName() const;
255 virtual DrawData GetDrawData();
256
257 virtual bool IsNode3D() const;
258 virtual bool IsWidget() const;
259 virtual bool IsPrimitive3D() const;
260 virtual bool IsLight3D() const;
261
262 Node* GetParent();
263 const Node* GetParent() const;
264 const std::vector<NodePtr>& GetChildren() const;
265
266 virtual void Attach(Node* parent, bool keepWorldTransform = false, int32_t index = -1);
267 void Detach(bool keepWorldTransform = false);
268 void AddChild(Node* child, int32_t index = -1);
269 void RemoveChild(Node* child);
270 void RemoveChild(int32_t index);
271
272 template<typename T>
273 void AddChild(const SharedPtr<T>& child, int32_t index = -1)
274 {
275 AddChild(child.Get(), index);
276 }
277
278 template<typename T>
279 void RemoveChild(const SharedPtr<Node>& child)
280 {
281 RemoveChild(child.Get());
282 }
283
284 int32_t FindChildIndex(const std::string& name) const;
285 int32_t FindChildIndex(Node* child) const;
286 Node* FindChild(const std::string& name, bool recurse) const;
287 Node* FindChildWithTag(const std::string& name, bool recurse) const;
288 Node* FindDescendant(const std::string& name);
289 Node* FindAncestor(const std::string& name);
290 bool HasAncestor(Node* node);
291 Node* GetChild(int32_t index) const;
292 Node* GetChildByType(TypeId type) const;
293 uint32_t GetNumChildren() const;
294 int32_t FindParentNodeIndex() const;
295
296 void SetHitCheckId(uint32_t id);
297 uint32_t GetHitCheckId() const;
298
299 bool IsLateTickEnabled() const;
300 void EnableLateTick(bool enable);
301
302 Script* GetScript();
303 void SetScriptFile(const std::string& fileName);
304
305 bool DoChildrenHaveUniqueNames() const;
306 void BreakSceneLink();
307 bool IsSceneLinked(bool ignoreInPie = true) const;
308 bool IsSceneLinkedChild(bool ignoreInPie = true);
309 bool IsForeign() const;
310
311 bool HasAuthority() const;
312 bool IsOwned() const;
313 bool IsLocallyControlled() const;
314
315 Datum GetField(const std::string& key);
316 void SetField(const std::string& name, const Datum& value);
317 Datum GetField(int32_t key);
318 void SetField(int32_t key, const Datum& value);
319 Datum CallFunction(const std::string& name, const std::vector<Datum>& args = {});
320
321 NetFunc* FindNetFunc(const char* name);
322 NetFunc* FindNetFunc(uint16_t index);
323
324 void InvokeNetFunc(const char* name);
325 void InvokeNetFunc(const char* name, Datum param0);
326 void InvokeNetFunc(const char* name, Datum param0, Datum param1);
327 void InvokeNetFunc(const char* name, Datum param0, Datum param1, Datum param2);
328 void InvokeNetFunc(const char* name, Datum param0, Datum param1, Datum param2, Datum param3);
329 void InvokeNetFunc(const char* name, Datum param0, Datum param1, Datum param2, Datum param3, Datum param4);
330 void InvokeNetFunc(const char* name, Datum param0, Datum param1, Datum param2, Datum param3, Datum param4, Datum param5);
331 void InvokeNetFunc(const char* name, Datum param0, Datum param1, Datum param2, Datum param3, Datum param4, Datum param5, Datum param6);
332 void InvokeNetFunc(const char* name, Datum param0, Datum param1, Datum param2, Datum param3, Datum param4, Datum param5, Datum param6, Datum param7);
333 void InvokeNetFunc(const char* name, const std::vector<Datum>& params);
334
335 static void ProcessPendingDestroys();
336
337 static void RegisterNetFuncs(Node* node);
338
339 static void Deleter(Node* node);
340
341 const WeakPtr<Node>& GetSelfPtr() const { return mSelf; }
342
343 template<typename T>
344 T* FindChild(const std::string& name, bool recurse)
345 {
346 T* ret = nullptr;
347 Node* child = FindChild(name, recurse);
348 if (child != nullptr)
349 {
350 ret = child->As<T>();
351 }
352
353 return ret;
354 }
355
356 template<typename T>
357 void Traverse(T func, bool inverted = false)
358 {
359 bool traverseChildren = true;
360
361 if (!inverted)
362 {
363 traverseChildren = func(this);
364 }
365
366 if (traverseChildren)
367 {
368 if (inverted)
369 {
370 for (int32_t i = int32_t(mChildren.size()) - 1; i >= 0; --i)
371 {
372 mChildren[i]->Traverse(func, inverted);
373 }
374 }
375 else
376 {
377 for (uint32_t i = 0; i < mChildren.size(); ++i)
378 {
379 mChildren[i]->Traverse(func, inverted);
380 }
381 }
382 }
383
384 if (inverted)
385 {
386 func(this);
387 }
388 }
389
390 template<typename T>
391 bool ForEach(T func, bool inverted = false)
392 {
393 bool cont = true;
394
395 if (!inverted)
396 {
397 cont = func(this);
398 }
399
400 if (cont)
401 {
402 if (inverted)
403 {
404 for (int32_t i = int32_t(mChildren.size()) - 1; i >= 0; --i)
405 {
406 cont = mChildren[i]->ForEach(func, inverted);
407
408 if (!cont)
409 {
410 break;
411 }
412 }
413 }
414 else
415 {
416 for (uint32_t i = 0; i < mChildren.size(); ++i)
417 {
418 cont = mChildren[i]->ForEach(func, inverted);
419
420 if (!cont)
421 {
422 break;
423 }
424 }
425 }
426 }
427
428 if (cont && inverted)
429 {
430 cont = func(this);
431 }
432
433 return cont;
434 }
435
436 template<class NodeClass>
438 {
439 // Code copied across other Construct() functions
440 NodeClass* newNode = (NodeClass*)Node::CreateInstance(NodeClass::GetStaticType());
441 SharedPtr<NodeClass> newNodePtr;
442
443 if (newNode != nullptr)
444 {
445 newNodePtr.Set(newNode, nullptr);
446 newNodePtr.SetDeleter([](NodeClass* node) { Node::Deleter(node); });
447 newNodePtr->mSelf = PtrStaticCast<Node>(newNodePtr);
448 newNodePtr->Create();
449 }
450
451 return newNodePtr;
452 }
453
454protected:
455
456 static bool HandlePropChange(Datum* datum, uint32_t index, const void* newValue);
457
458 static bool OnRep_OwningHost(Datum* datum, uint32_t index, const void* newValue);
459
460 void TickCommon(float deltaTime);
461
462 virtual void SetParent(Node* parent);
463 void ValidateUniqueChildName(Node* newChild);
464
465 void SendNetFunc(NetFunc* func, uint32_t numParams, const Datum** params);
466
467 static std::unordered_map<TypeId, NetFuncMap> sTypeNetFuncMap;
468 static std::unordered_set<NodePtrWeak> sPendingDestroySet;
470
471 std::string mName;
472
473 World* mWorld = nullptr;
476 std::vector<NodePtr> mChildren;
477 std::unordered_map<std::string, Node*> mChildNameMap;
478 std::unordered_map<std::string, Signal> mSignalMap;
479 std::string mScriptFile;
480 uint32_t mLastTickedFrame = 0;
481 bool mActive = true;
482 bool mVisible = true;
483 bool mTransient = false;
484 bool mPersistent = false;
485 bool mDefault = false;
486 bool mUserdataCreated = false;
487 bool mHasStarted = false;
488 bool mHasAwoken = false;
489 bool mDestroyed = false;
490 bool mTickEnabled = true;
491 bool mLateTick = false;
492
493 // Merged from Actor
495 uint8_t mTargetScreen = 0; // 0 = Top Screen, 1 = Bottom Screen
496 std::vector<std::string> mTags;
498 uint64_t mPersistentUuid = 0;
499
500 // Network Data
501 // This is only about 44 bytes, so right now, we will keep this data as direct members of Node.
502 // But if we need to save data, then consider allocating a NodeNetData struct only if replicated.
503 // Leaving these as direct members will improve cache performance too.
504 std::vector<NetDatum> mReplicatedData;
507 bool mReplicate = false;
508 bool mReplicateTransform = false;
509 bool mForceReplicate = false;
510 bool mAlwaysRelevant = true;
511
512 Script* mScript = nullptr;
513 //NodeNetData* mNetData = nullptr;
514
515#if EDITOR
516public:
517 // TODO-NODE: Either remove mExposeVariable, or make sure it works with Scenes.
518 // Could consider moving this up to Node if it would be useful from avoiding FindChild() calls in Start().
519 bool ShouldExposeVariable() const;
520 void SetExposeVariable(bool expose);
521 bool AreAllChildrenHiddenInTree() const;
522
523 uint32_t mHitCheckId = 0;
524 bool mExposeVariable = false;
525 bool mHiddenInTree = false;
526#endif
527};
528
529// Eventually, if we move the mSelf pointer into Object, we will have to
530// move these functions also (and make them take Object* param)
531//
532// Defensive: if `node`'s mSelf has been stomped so it no longer points back
533// at `node` (most often a dangling Node* from a previous world/addon load
534// whose memory got reused), Lock() will crash inside IsValid when it
535// dereferences the dangling mPointer. Gate the Lock with a self-consistency
536// check and return null on mismatch so callers see "couldn't resolve" instead
537// of an access violation. Callers that care surface a user-visible error
538// (see Node::AddChild for the editor alert).
539template<typename T>
541{
542 if (node == nullptr)
543 {
544 return nullptr;
545 }
546
547 const NodePtrWeak& selfWeak = node->GetSelfPtr();
548 if (selfWeak.GetPointerRaw() != node || selfWeak.GetRefCount() == nullptr)
549 {
550 return nullptr;
551 }
552
553 NodePtr nodePtr = selfWeak.Lock();
554 return PtrStaticCast<T>(nodePtr);
555}
556
557template<typename T>
559{
560 if (node == nullptr)
561 {
562 return WeakPtr<T>();
563 }
564
565 const NodePtrWeak& selfWeak = node->GetSelfPtr();
566 if (selfWeak.GetPointerRaw() != node || selfWeak.GetRefCount() == nullptr)
567 {
568 return WeakPtr<T>();
569 }
570
571 return PtrStaticCast<T>(selfWeak);
572}
#define INVALID_HOST_ID
Definition Constants.h:44
#define INVALID_NODE_ID
Definition Constants.h:42
#define INVALID_NET_ID
Definition Constants.h:41
uint32_t NetId
Definition EngineTypes.h:73
Platform
Definition EngineTypes.h:32
uint8_t NetHostId
Definition EngineTypes.h:626
uint32_t TypeId
Definition EngineTypes.h:72
uint32_t NodeId
Definition EngineTypes.h:74
World * GetWorld(int32_t index)
Definition Engine.cpp:1228
PipelineConfig
Definition GraphicsTypes.h:66
std::unordered_map< std::string, NetFunc > NetFuncMap
Definition Node.h:42
bool(* NodeTraversalFP)(Node *)
Definition Node.h:45
SharedPtr< T > ResolvePtr(Node *node)
Definition Node.h:540
WeakPtr< T > ResolveWeakPtr(Node *node)
Definition Node.h:558
Export macros for Polyphase Engine symbols.
#define POLYPHASE_API
Definition PolyphaseAPI.h:31
void(* SignalHandlerFP)(Node *, const std::vector< Datum > &)
Definition Signals.h:11
VertexType
Definition Vertex.h:7
Definition AssetRef.h:18
Definition Datum.h:169
Definition Factory.h:62
Definition Node.h:67
std::vector< NetDatum > mReplicatedData
Definition Node.h:504
SceneRef mScene
Definition Node.h:494
DECLARE_FACTORY(Node, Node)
SharedPtr< NodeClass > CreateChildSp(const char *name)
Definition Node.h:179
std::string mScriptFile
Definition Node.h:479
void Traverse(T func, bool inverted=false)
Definition Node.h:357
NodePtrWeak mParent
Definition Node.h:474
NodeClass * CreateChild(const char *name)
Definition Node.h:171
std::vector< NodePtr > mChildren
Definition Node.h:476
std::string mName
Definition Node.h:471
static std::unordered_map< TypeId, NetFuncMap > sTypeNetFuncMap
Definition Node.h:467
static SharedPtr< NodeClass > Construct()
Definition Node.h:437
NodePtrWeak mSelf
Definition Node.h:475
void SetTargetScreen(uint8_t screen)
Definition Node.h:203
DECLARE_FACTORY_MANAGER(Node)
static std::unordered_set< NodePtrWeak > sPendingDestroySet
Definition Node.h:468
DECLARE_OBJECT(Node, Object)
static NodeId sNextNodeId
Definition Node.h:469
SharedPtr< NodeClass > CreateChildSp()
Definition Node.h:165
bool ForEach(T func, bool inverted=false)
Definition Node.h:391
static void Deleter(Node *node)
Definition Node.cpp:146
std::unordered_map< std::string, Node * > mChildNameMap
Definition Node.h:477
void AddChild(const SharedPtr< T > &child, int32_t index=-1)
Definition Node.h:273
std::unordered_map< std::string, Signal > mSignalMap
Definition Node.h:478
DECLARE_SCRIPT_LINK_BASE(Node)
uint8_t GetTargetScreen() const
Definition Node.h:202
T * FindChild(const std::string &name, bool recurse)
Definition Node.h:344
NodeClass * CreateChild()
Definition Node.h:159
const WeakPtr< Node > & GetSelfPtr() const
Definition Node.h:341
std::vector< std::string > mTags
Definition Node.h:496
void RemoveChild(const SharedPtr< Node > &child)
Definition Node.h:279
Definition Object.h:13
virtual void GatherProperties(std::vector< Property > &props)
Definition Object.h:41
T * As() const
Definition Object.h:52
Definition Primitive3d.h:46
Definition Scene.h:36
Definition ScriptFunc.h:10
Definition Script.h:29
Definition SmartPointer.h:33
void SetDeleter(typename RefCount< T >::DeleterFP deleteFunc)
Definition SmartPointer.h:234
void Set(T *pointer, RefCount< T > *refCount)
Definition SmartPointer.h:156
T * Get() const
Definition SmartPointer.h:247
Definition Stream.h:21
Definition SmartPointer.h:312
RefCount< T > * GetRefCount() const
Definition SmartPointer.h:531
SharedPtr< T > Lock() const
Definition SmartPointer.h:492
const T * GetPointerRaw() const
Definition SmartPointer.h:551
Definition World.h:24
Definition EngineTypes.h:330
Definition NetFunc.h:33