200 behaviour tree port over

This commit is contained in:
Xiao Qi 2023-01-16 18:40:16 +08:00
parent 1fc2897150
commit 1c004c787a
10 changed files with 942 additions and 0 deletions

View File

@ -0,0 +1,81 @@
/******************************************************************************
* \file SHBehaviourTreeAgent.cpp
* \author Loh Xiao Qi
* \brief Function definitions for Behaviour tree agent
*
* \copyright Copyright (c) 2021 Digipen Institute of Technology. Reproduction
* or disclosure of this file or its contents without the prior
* written consent of Digipen Institute of Technology is prohibited
******************************************************************************/
#include "SHpch.h"
#include "SHBehaviourTreeAgent.h"
namespace SHADE
{
/**
* Param ctor for agent to take in reference to a tree
*
* \param tree - pointer to tree data. nullptr if no trees
*/
SHBehaviourTreeAgent::SHBehaviourTreeAgent(std::shared_ptr<SHBehaviourTree> tree)
: treeRef{ tree }, current{ treeRef->GetRoot() }
{
}
/**
* Copy ctor.
*
* \param ref - agent to copy from
*/
SHBehaviourTreeAgent::SHBehaviourTreeAgent(SHBehaviourTreeAgent const& ref)
: treeRef{ ref.treeRef}, current{ treeRef->GetRoot() }
{
}
/**
* copy assignment operator overload.
*
* \param ref - agent to copy from
* \return reference to current object
*/
SHBehaviourTreeAgent& SHBehaviourTreeAgent::operator=(SHBehaviourTreeAgent const& ref)
{
treeRef = ref.treeRef;
current = ref.current;
return *this;
}
/**
* Shift current node to next node.
*
* \param next - node to shift to
* \return vector of scripts that need to be run at next node
*/
MonoMVector SHBehaviourTreeAgent::Transit(SHBehaviourTree::Leaf next) noexcept
{
current = next;
return current->scripts;
}
/**
* Get current Node.
*
* \return Pointer to behaviour tree leaf
*/
SHBehaviourTree::Leaf SHBehaviourTreeAgent::GetCurrent() noexcept
{
return current;
}
/**
* Check if pointer to tree is a nullptr.
*
* \return
*/
bool SHBehaviourTreeAgent::isEmpty() const noexcept
{
return treeRef == nullptr;
}
}

View File

@ -0,0 +1,77 @@
/******************************************************************************
* \file SHBehaviourTreeAgent.h
* \author Loh Xiao Qi
* \brief Interface for behaviour tree agent. The agent traverses through
* the tree and operates based on the data. It does not make any
* changes to the tree data.
*
* \copyright Copyright (c) 2021 Digipen Institute of Technology. Reproduction
* or disclosure of this file or its contents without the prior
* written consent of Digipen Institute of Technology is prohibited
******************************************************************************/
#ifndef SH_BEHAVIOUR_TREE_AGENT_H
#define SH_BEHAVIOUR_TREE_AGENT_H
#include "Resource Types/SHBehaviourTree.h"
namespace SHADE
{
class SHBehaviourTreeAgent
{
private:
std::shared_ptr<SHBehaviourTree> treeRef;
SHBehaviourTree::Leaf current;
public:
/**
* Remove empty ctor.
*/
SHBehaviourTreeAgent() = delete;
/**
* Param ctor for agent to take in reference to a tree
*
* \param tree - pointer to tree data. nullptr if no trees
*/
SHBehaviourTreeAgent(std::shared_ptr<SHBehaviourTree> tree);
/**
* Copy ctor.
*
* \param ref - agent to copy from
*/
SHBehaviourTreeAgent(SHBehaviourTreeAgent const& ref);
/**
* copy assignment operator overload.
*
* \param ref - agent to copy from
* \return reference to current object
*/
SHBehaviourTreeAgent& operator=(SHBehaviourTreeAgent const& ref);
/**
* Shift current node to next node.
*
* \param next - node to shift to
* \return vector of scripts that need to be run at next node
*/
[[nodiscard]] MonoMVector Transit(SHBehaviourTree::Leaf next) noexcept;
/**
* Get current Node.
*
* \return Pointer to behaviour tree leaf
*/
SHBehaviourTree::Leaf GetCurrent() noexcept;
/**
* Check if pointer to tree is a nullptr.
*
* \return
*/
bool isEmpty() const noexcept;
};
}
#endif // !SH_BEHAVIOUR_TREE_AGENT_H

View File

@ -0,0 +1,83 @@
/******************************************************************************
* \file SHBehaviourTreeLibrary.cpp
* \author Loh Xiao Qi
* \brief Definitions for helper functions to load and save behaviour trees
* and generate handles for tree and tree members.
*
* \copyright Copyright (c) 2021 Digipen Institute of Technology. Reproduction
* or disclosure of this file or its contents without the prior
* written consent of Digipen Institute of Technology is prohibited
******************************************************************************/
#include "SHpch.h"
#include "SHBehaviourTreeLibrary.h"
#include <random>
#include <chrono>
namespace SHADE
{
std::vector<BehaviourTreeHandle> SHBehaviourTreeLibray::treeHandle;
std::vector<BehaviourChildHandle> SHBehaviourTreeLibray::childHandles;
/****************************************************************************
* Generate uint16_t handle for tree.
*
* \return BehaviourTreeHandle(uint16_t)
****************************************************************************/
BehaviourTreeHandle SHBehaviourTreeLibray::GenerateTreeHandle() noexcept
{
std::default_random_engine randEngine{
static_cast<unsigned int>(std::chrono::system_clock::now().time_since_epoch().count()) };
std::mt19937 idGen{ randEngine() };
BehaviourTreeHandle result{ 0 };
while (result == 0)
{
result = static_cast<BehaviourTreeHandle>(idGen());
for (auto const& handle : treeHandle)
{
if (handle == result)
{
result = 0;
break;
}
}
}
treeHandle.push_back(result);
return result;
}
/****************************************************************************
* Generate uint32_t handle for tree. Parent handle is shifted 16 bits to the
* left and the first 16 bits will be the unique handle for the child.
*
* \param parent handle - uint16_t
* \return BehaviourChildHandle(uint32_t)
****************************************************************************/
BehaviourChildHandle SHBehaviourTreeLibray::GenerateChildHandle(BehaviourTreeHandle parent) noexcept
{
std::default_random_engine randEngine{
static_cast<unsigned int>(std::chrono::system_clock::now().time_since_epoch().count()) };
std::mt19937 idGen{ randEngine() };
BehaviourTreeHandle temp{ 0 };
BehaviourChildHandle parentShift{ parent };
parentShift <<= 16;
BehaviourChildHandle check;
while (temp == 0)
{
check = parentShift;
temp = static_cast<BehaviourTreeHandle>(idGen());
check += temp;
for (auto const& handle : childHandles)
{
if (handle == check)
{
temp = 0;
break;
}
}
}
childHandles.push_back(check);
return check;
}
}

View File

@ -0,0 +1,59 @@
/******************************************************************************
* \file SHAnimControlModelLoader.h
* \author Loh Xiao Qi
* \date 16 January 2023
* \brief
*
* \copyright Copyright (c) 2023 Digipen Institute of Technology. Reproduction
* or disclosure of this file or its contents without the prior
* written consent of Digipen Institute of Technology is prohibited.
******************************************************************************/
#pragma once
#include <vector>
#include "Assets/SHAssetMacros.h"
#include "Assets/Asset Types/Anim Controller/SHAnimControlModel.h"
namespace SHADE
{
struct SHBehaviourLeafRW
{
std::string name;
BehaviourChildHandle handle;
std::vector<BehaviourChildHandle> branches;
std::vector<std::pair<MonoMethod*, uint32_t>> scripts;
};
struct SHBehaviourBranchRW
{
BehaviourChildHandle handle;
BehaviourChildHandle next;
std::vector<std::pair<MonoMethod*, uint32_t>> scripts;
};
class SHBehaviourTreeLibray
{
private:
static std::vector<BehaviourTreeHandle> treeHandle;
static std::vector<BehaviourChildHandle> childHandles;
public:
/****************************************************************************
* Generate uint16_t handle for tree. Checks for duplicates as well
*
* \return BehaviourTreeHandle(uint16_t)
****************************************************************************/
static BehaviourTreeHandle GenerateTreeHandle() noexcept;
/****************************************************************************
* Generate uint32_t handle for tree. Parent handle is shifted 16 bits to the
* left and the first 16 bits will be the unique handle for the child.
* Checks for duplicates as well
*
* \param parent handle - uint16_t
* \return BehaviourChildHandle(uint32_t)
****************************************************************************/
static BehaviourChildHandle GenerateChildHandle(BehaviourTreeHandle parent) noexcept;
};
}

View File

@ -0,0 +1,174 @@
/******************************************************************************
* \file SHAISystem.cpp
* \author Loh Xiao Qi
* \brief AI system definitions. Includes helper functions for Ai Component
*
* \copyright Copyright (c) 2021 Digipen Institute of Technology. Reproduction
* or disclosure of this file or its contents without the prior
* written consent of Digipen Institute of Technology is prohibited
******************************************************************************/
#include "SHpch.h"
#include "SHAISystem.h"
#include "ECS_Base/System/SHComponentManager.h"
#include "Components/SHRigidBodyComponent.h"
#include "Components/SHAIComponent.h"
#include "Events/Packages/SHScriptEventPackage.h"
#include "Events/SHEventManager.h"
namespace SHADE
{
float const DIST_EPS{ 5.0f };
float const DIST_EPS_SQ{ DIST_EPS * DIST_EPS };
/****************************************************************************
* Check if entity has reached waypoint.
*
* \param transform - transform of entity
* \param agent - agent of entity
* \return bool - result of check
****************************************************************************/
bool SHAISystem::Reached(SHTransformComponent const& transform, SHWaypointAgent const& agent)
{
SHMathVec3f distanceVec{ agent.GetCurrentTarget() - transform.GetTranslation() };
float distance{ distanceVec.MagSqr() };
return distance <= (DIST_EPS * DIST_EPS);
}
/****************************************************************************
* Check if params in branch all match and whether transition is allowed.
*
* \param branch - pointer to branch
* \return bool - result of check
****************************************************************************/
bool SHAISystem::CheckBranchConditions(SHBehaviourTree::Branch branch)
{
for (auto& param : branch->checks)
{
ParamTypes type{ param->GetType() };
if (type == ParamTypes::FLOAT)
{
std::shared_ptr<SHTreeParamSpec<float>> p = std::static_pointer_cast<SHTreeParamSpec<float>>(param);
if (p->GetData() >= p->GetCheck())
{
return true;
}
}
else if (type == ParamTypes::BOOL)
{
std::shared_ptr<SHTreeParamSpec<bool>> p = std::static_pointer_cast<SHTreeParamSpec<bool>>(param);
if (p->GetData())
{
return true;
}
}
else if (type == ParamTypes::TRIGGER)
{
std::shared_ptr<SHTreeParamSpec<bool>> p = std::static_pointer_cast<SHTreeParamSpec<bool>>(param);
if (p->GetData())
{
p->GetValueRef() = false;
return true;
}
}
else if (type == ParamTypes::INT)
{
std::shared_ptr<SHTreeParamSpec<int>> p = std::static_pointer_cast<SHTreeParamSpec<int>>(param);
if (p->GetData() >= p->GetCheck())
{
return true;
}
}
}
return false;
}
/****************************************************************************
* Init function.
*
****************************************************************************/
void SHAISystem::Init()
{
}
/****************************************************************************
* Main AI system logic.
*
* \param float - delta time
****************************************************************************/
void SHAISystem::Run(float dt)
{
(void)dt;
auto& aiSet = SHComponentManager::GetDense<SHAIComponent>();
size_t const size{ aiSet.size() };
if (size == 0)
{
return;
}
for (size_t i{ 0 }; i < size; ++i)
{
auto& ai{ aiSet[i] };
if (!ai.isActive)
{
continue;
}
SHTransformComponent* transform = SHComponentManager::GetComponent_s<SHTransformComponent>(ai.GetEID());
SHRigidBodyComponent* rigidBody = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(ai.GetEID());
if (transform && rigidBody)
{
auto wpAgent{ ai.GetWaypointAgent() };
if (wpAgent.isActive && !wpAgent.Completed())
{
if (Reached(*transform, wpAgent))
{
wpAgent.NextWaypoint();
SHMathVec3f velVec{ wpAgent.GetCurrentTarget() - transform->GetTranslation() };
velVec.Normalize();
velVec *= wpAgent.GetSpeed();
rigidBody->ApplyForce({ velVec[0], velVec[1] });
}
}
}
auto behaviourAgent{ ai.GetBehaviourAgent() };
if (!behaviourAgent.isEmpty())
{
auto branches{ behaviourAgent.GetCurrent()->branches };
for (auto const& branch : branches)
{
if (CheckBranchConditions(branch))
{
auto scripts = behaviourAgent.Transit(branch->next);
for (auto const& script : branch->scripts)
{
ScriptEventPackPtr evtPack = std::make_shared<SHScriptEventPackage>(script.first, script.second);
SHEventManager::GetEventManagerInstance().CatchEvent(SHEvent(evtPack));
}
for (auto const& script : scripts)
{
ScriptEventPackPtr evtPack = std::make_shared<SHScriptEventPackage>(script.first, script.second);
SHEventManager::GetEventManagerInstance().CatchEvent(SHEvent(evtPack));
}
break;
}
}
}
}
}
/****************************************************************************
* Exit function.
*
****************************************************************************/
void SHAISystem::Exit()
{
}
}

View File

@ -0,0 +1,64 @@
/******************************************************************************
* \file SHAISystem.h
* \author Loh Xiao Qi
* \brief AI system declaration. Includes helper functions for Ai Component
*
* \copyright Copyright (c) 2021 Digipen Institute of Technology. Reproduction
* or disclosure of this file or its contents without the prior
* written consent of Digipen Institute of Technology is prohibited
******************************************************************************/
#ifndef SH_AI_SYSTEM_H
#define SH_AI_SYSTEM_H
#include "ECS_Base/System/SHSystem.h"
#include "AI/SHWaypointAgent.h"
#include "Resource Types/SHBehaviourTree.h"
#include "Components/SHTransformComponent.h"
namespace SHADE
{
class SHAISystem : public SHSystem
{
private:
/****************************************************************************
* Check if entity has reached waypoint.
*
* \param transform - transform of entity
* \param agent - agent of entity
* \return bool - result of check
****************************************************************************/
bool Reached(SHTransformComponent const& transform, SHWaypointAgent const& agent);
/****************************************************************************
* Check if params in branch all match and whether transition is allowed.
*
* \param branch - pointer to branch
* \return bool - result of check
****************************************************************************/
bool CheckBranchConditions(SHBehaviourTree::Branch branch);
public:
/****************************************************************************
* Init function.
*
****************************************************************************/
void Init();
/****************************************************************************
* Main AI system logic.
*
* \param float - delta time
****************************************************************************/
void Run(float);
/****************************************************************************
* Exit function.
*
****************************************************************************/
void Exit();
};
}
#endif // !SH_AI_SYSTEM_H

View File

@ -0,0 +1,150 @@
/******************************************************************************
* \file SHBehaviourTree.cpp
* \author Loh Xiao Qi
* \brief Definition for behaviour tree class. FSM with condition checks
* to aid in transition from one state to another
*
* \copyright Copyright (c) 2021 Digipen Institute of Technology. Reproduction
* or disclosure of this file or its contents without the prior
* written consent of Digipen Institute of Technology is prohibited
******************************************************************************/
#include "SHpch.h"
#include "SHBehaviourTree.h"
#include "Resource Libraries/SHBehaviourTreeLibrary.h"
namespace SHADE
{
/****************************************************************************
* Default Ctor and Dtor.
****************************************************************************/
SHBehaviourTree::SHBehaviourTree() noexcept
: handle{ SHBehaviourTreeLibray::GenerateTreeHandle() },
root { new SHBehaviourLeaf }, leaves(0), branches(0)
{
}
SHBehaviourTree::~SHBehaviourTree() noexcept
{
delete root;
for (auto const& leaf : leaves)
{
delete leaf;
}
for (auto const& branch : branches)
{
delete branch;
}
}
/****************************************************************************
* Get root node in tree.
*
* \return pointer to node
****************************************************************************/
SHBehaviourTree::SHBehaviourLeaf* SHBehaviourTree::GetRoot() const noexcept
{
return root;
}
/****************************************************************************
* Create tree wide param to be used in transitioning
*
* \param name - std::string of param
* \param type - ParamTypes, type of param
* \return pointer to param data created
****************************************************************************/
ParamPtr SHBehaviourTree::CreateParam(std::string name, ParamTypes type) noexcept
{
ParamPtr result;
switch (type)
{
case ParamTypes::FLOAT:
result = std::make_shared<SHTreeParamSpec<float>>(name, type);
break;
case ParamTypes::BOOL:
result = std::make_shared<SHTreeParamSpec<bool>>(name, type);
break;
case ParamTypes::TRIGGER:
result = std::make_shared<SHTreeParamSpec<bool>>(name, type);
break;
case ParamTypes::INT:
result = std::make_shared<SHTreeParamSpec<int>>(name, type);
break;
}
param.push_back(result);
return result;
}
/****************************************************************************
* Create new branch and node from provided node.
*
* \param from - node to branch out from
* \return pointer to new branch created
****************************************************************************/
SHBehaviourTree::SHBehaviourLeaf* SHBehaviourTree::BranchOutFrom(SHBehaviourLeaf* from) noexcept
{
auto const branch = new SHBehaviourBranch;
branch->handle = SHBehaviourTreeLibray::GenerateChildHandle(handle);
auto const leaf = new SHBehaviourLeaf;
leaf->handle = SHBehaviourTreeLibray::GenerateChildHandle(handle);
branch->next = leaf;
from->branches.push_back(branch);
branches.push_back(branch);
leaves.push_back(leaf);
return leaf;
}
/****************************************************************************
* Link 2 nodes together.
*
* \param from - pointer to first node
* \param to - pointer to second node
****************************************************************************/
void SHBehaviourTree::LinkLeaves(SHBehaviourLeaf* from, SHBehaviourLeaf* to) noexcept
{
auto const branch = new SHBehaviourBranch;
branch->handle = SHBehaviourTreeLibray::GenerateChildHandle(handle);
branch->next = to;
branches.push_back(branch);
from->branches.push_back(branch);
}
/****************************************************************************
* Breaks link between 2 branches if it exists.
*
* \param from - pointer to first node
* \param to - pointer to second node
* \return result of break - bool
****************************************************************************/
bool SHBehaviourTree::BreakLink(SHBehaviourLeaf* from, SHBehaviourLeaf* to) noexcept
{
for (auto it {from->branches.begin()}; it != from->branches.end(); ++it)
{
if ((*it)->next == to)
{
for (auto branchIt {branches.begin()}; branchIt != branches.end(); ++branchIt)
{
if ((*it) == (*branchIt))
{
branches.erase(branchIt);
break;
}
}
delete *it;
from->branches.erase(it);
return true;
}
}
return false;
}
}

View File

@ -0,0 +1,108 @@
/******************************************************************************
* \file SHAnimControlModel.h
* \author Loh Xiao Qi
* \date 16 January 2023
* \brief
*
* \copyright Copyright (c) 2023 Digipen Institute of Technology. Reproduction
* or disclosure of this file or its contents without the prior
* written consent of Digipen Institute of Technology is prohibited.
******************************************************************************/
#pragma once
#include <string>
#include <vector>
#include <utility>
#include "Assets/SHAssetMacros.h"
#include "SHTreeParam.h"
namespace SHADE
{
typedef std::shared_ptr<SHTreeParam> ParamPtr;
class SHBehaviourTree
{
struct SHBehaviourLeaf;
struct SHBehaviourBranch;
struct SHBehaviourLeaf
{
std::string name;
BehaviourChildHandle handle;
std::vector<SHBehaviourBranch*> branches;
MonoMVector scripts;
};
struct SHBehaviourBranch
{
BehaviourChildHandle handle;
SHBehaviourLeaf* next;
MonoMVector scripts;
std::vector<ParamPtr> checks;
};
private:
BehaviourTreeHandle handle;
SHBehaviourLeaf* root;
std::vector<SHBehaviourLeaf*> leaves;
std::vector<SHBehaviourBranch*> branches;
std::vector<ParamPtr> param;
public:
/****************************************************************************
* Default Ctor and Dtor.
****************************************************************************/
SHBehaviourTree() noexcept;
~SHBehaviourTree() noexcept;
// No copying of tree allowed
SHBehaviourTree(SHBehaviourTree const& ref) = delete;
SHBehaviourTree(SHBehaviourTree&& ref) = delete;
/****************************************************************************
* Get root node in tree.
*
* \return pointer to node
****************************************************************************/
[[nodiscard]] SHBehaviourLeaf* GetRoot() const noexcept;
/****************************************************************************
* Create tree wide param to be used in transitioning
*
* \param name - std::string of param
* \param type - ParamTypes, type of param
* \return pointer to param data created
****************************************************************************/
ParamPtr CreateParam(std::string name, ParamTypes type) noexcept;
/****************************************************************************
* Create new branch and node from provided node.
*
* \param from - node to branch out from
* \return pointer to new branch created
****************************************************************************/
SHBehaviourLeaf* BranchOutFrom(SHBehaviourLeaf* from) noexcept;
/****************************************************************************
* Link 2 nodes together.
*
* \param from - pointer to first node
* \param to - pointer to second node
****************************************************************************/
void LinkLeaves(SHBehaviourLeaf* from, SHBehaviourLeaf* to) noexcept;
/****************************************************************************
* Breaks link between 2 branches if it exists.
*
* \param from - pointer to first node
* \param to - pointer to second node
* \return result of break - bool
****************************************************************************/
bool BreakLink(SHBehaviourLeaf* from, SHBehaviourLeaf* to) noexcept;
using Leaf = SHBehaviourLeaf*;
using Branch = SHBehaviourBranch*;
};
}

View File

@ -0,0 +1,85 @@
/******************************************************************************
* \file SHTreeParam.cpp
* \author Loh Xiao Qi
* \brief
*
* \copyright Copyright (c) 2021 Digipen Institute of Technology. Reproduction
* or disclosure of this file or its contents without the prior
* written consent of Digipen Institute of Technology is prohibited
******************************************************************************/
#include "SHpch.h"
#include "SHTreeParam.h"
namespace SHADE
{
SHTreeParam::SHTreeParam(std::string name, ParamTypes t)
: name{ name }, type{ t }
{
}
SHTreeParam::SHTreeParam(SHTreeParam const& ref)
: name{ ref.name }, type{ ref.type }
{
}
SHTreeParam& SHTreeParam::operator=(SHTreeParam const& ref)
{
name = ref.name;
type = ref.type;
return *this;
}
ParamTypes SHTreeParam::GetType() const noexcept
{
return type;
}
std::string SHTreeParam::GetName() const noexcept
{
return name;
}
template <typename T>
SHTreeParamSpec<T>::SHTreeParamSpec(std::string name, ParamTypes t)
: SHTreeParam(name, t)
{
}
template <typename T>
SHTreeParamSpec<T>::SHTreeParamSpec(SHTreeParamSpec const& ref)
: SHTreeParam(ref.name, ref.type)
{
}
template <typename T>
SHTreeParamSpec<T>& SHTreeParamSpec<T>::operator=(SHTreeParamSpec const& ref)
{
SHTreeParam::operator=(ref);
data = ref.data;
}
template <typename T>
void SHTreeParamSpec<T>::SetCheck(T val) noexcept
{
check = val;
}
template <typename T>
T SHTreeParamSpec<T>::GetCheck() const noexcept
{
return check;
}
template <typename T>
T SHTreeParamSpec<T>::GetData() const noexcept
{
return data;
}
template <typename T>
T& SHTreeParamSpec<T>::GetValueRef() noexcept
{
return data;
}
}

View File

@ -0,0 +1,61 @@
/******************************************************************************
* \file SHTreeParam.h
* \author Loh Xiao Qi
* \date 16 January 2023
* \brief
*
* \copyright Copyright (c) 2023 Digipen Institute of Technology. Reproduction
* or disclosure of this file or its contents without the prior
* written consent of Digipen Institute of Technology is prohibited.
******************************************************************************/
#pragma once
#include <string>
namespace SHADE
{
enum class ParamTypes
{
FLOAT,
BOOL,
INT,
TRIGGER
};
struct SHTreeParam
{
protected:
ParamTypes type;
std::string name;
public:
SHTreeParam() = delete;
SHTreeParam(std::string name, ParamTypes t);
SHTreeParam(SHTreeParam const& ref);
SHTreeParam& operator=(SHTreeParam const& ref);
ParamTypes GetType() const noexcept;
std::string GetName() const noexcept;
};
template<typename T>
class SHTreeParamSpec : public SHTreeParam
{
private:
T data;
T check;
public:
SHTreeParamSpec() = delete;
SHTreeParamSpec(std::string name, ParamTypes t);
SHTreeParamSpec(SHTreeParamSpec const& ref);
SHTreeParamSpec& operator=(SHTreeParamSpec const& ref);
void SetCheck(T val) noexcept;
T GetCheck() const noexcept;
T GetData() const noexcept;
T& GetValueRef() noexcept;
};
}