Files
FlaxEngine/Source/Engine/Visject/GraphNode.h
2024-04-19 12:22:04 +02:00

216 lines
4.8 KiB
C++

// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
#pragma once
#include "Engine/Core/Types/Variant.h"
#include "Engine/Core/Collections/Array.h"
#include "Engine/Visject/VisjectMeta.h"
template<class BoxType>
class GraphNode;
#define GRAPH_NODE_MAKE_TYPE(groupID, typeID) (uint32)((groupID) << 16 | (typeID))
/// <summary>
/// Represents single box of the graph node
/// </summary>
class GraphBox
{
public:
/// <summary>
/// The parent node
/// </summary>
void* Parent;
/// <summary>
/// Unique box ID within single node
/// </summary>
byte ID;
/// <summary>
/// The box type.
/// </summary>
VariantType Type;
/// <summary>
/// List with all connections to other boxes
/// </summary>
Array<GraphBox*, InlinedAllocation<4>> Connections;
public:
GraphBox()
: Parent(nullptr)
, ID(0)
{
}
/// <summary>
/// Init
/// </summary>
/// <param name="parent">Parent node</param>
/// <param name="id">Unique box id</param>
/// <param name="type">Connections type</param>
GraphBox(void* parent, byte id, const VariantType::Types type)
: Parent(parent)
, ID(id)
, Type(type)
{
}
/// <summary>
/// Init
/// </summary>
/// <param name="parent">Parent node</param>
/// <param name="id">Unique box id</param>
/// <param name="type">Connections type</param>
GraphBox(void* parent, byte id, const VariantType& type)
: Parent(parent)
, ID(id)
, Type(type)
{
}
public:
/// <summary>
/// Gets the parent node.
/// </summary>
template<class NodeType>
FORCE_INLINE NodeType* GetParent() const
{
return static_cast<NodeType*>(Parent);
}
/// <summary>
/// Returns true if box has one or more connections.
/// </summary>
FORCE_INLINE bool HasConnection() const
{
return Connections.HasItems();
}
};
/// <summary>
/// Visject graph node base
/// </summary>
template<class BoxType>
class GraphNode
{
public:
typedef BoxType Box;
typedef GraphNode<BoxType> Node;
public:
/// <summary>
/// Unique node ID (within a graph).
/// </summary>
uint32 ID;
union
{
struct
{
uint16 TypeID;
uint16 GroupID;
};
uint32 Type;
};
/// <summary>
/// List of all node values. Array size and value types are constant over time. Only value data can change.
/// </summary>
Array<Variant, InlinedAllocation<8>> Values;
/// <summary>
/// Node boxes cache. Array index matches the box ID (for fast O(1) lookups).
/// </summary>
Array<Box> Boxes;
/// <summary>
/// Additional metadata.
/// </summary>
VisjectMeta Meta;
public:
GraphNode()
: ID(0)
, Type(0)
{
}
/// <summary>
/// Destructor
/// </summary>
~GraphNode()
{
}
public:
/// <summary>
/// Gets all the valid boxes.
/// </summary>
/// <param name="result">The result container.</param>
template<typename AllocationType = HeapAllocation>
void GetBoxes(Array<Box*, AllocationType>& result)
{
result.Clear();
for (int32 i = 0; i < Boxes.Count(); i++)
{
if (Boxes[i].Parent == this)
{
result.Add(&Boxes[i]);
}
}
}
/// <summary>
/// Gets all the valid boxes.
/// </summary>
/// <param name="result">The result container.</param>
template<typename AllocationType = HeapAllocation>
void GetBoxes(Array<const Box*, AllocationType>& result) const
{
result.Clear();
for (int32 i = 0; i < Boxes.Count(); i++)
{
if (Boxes[i].Parent == this)
{
result.Add(&Boxes[i]);
}
}
}
/// <summary>
/// Get box by ID
/// </summary>
/// <param name="id">Box ID</param>
/// <returns>Box</returns>
Box* GetBox(int32 id)
{
ASSERT(Boxes.HasItems() && Boxes.Count() > id && Boxes[id].ID == id && Boxes[id].Parent == this);
return &Boxes[id];
}
/// <summary>
/// Get box by ID, returns null if missing.
/// </summary>
/// <param name="id">Box ID</param>
/// <returns>Box</returns>
Box* TryGetBox(int32 id)
{
if (id >= 0 && id < Boxes.Count() && Boxes[id].ID == id && Boxes[id].Parent == this)
return &Boxes[id];
return nullptr;
}
/// <summary>
/// Get box by ID
/// </summary>
/// <param name="id">Box ID</param>
/// <returns>Box</returns>
const Box* GetBox(int32 id) const
{
ASSERT(Boxes.HasItems() && Boxes.Count() > id && Boxes[id].ID == id && Boxes[id].Parent == this);
return &Boxes[id];
}
};