AnimTestbed/src/AnimGraph/AnimGraphResource.h

219 lines
6.2 KiB
C
Raw Normal View History

2022-03-25 11:46:44 +01:00
//
// Created by martin on 17.03.24.
2022-03-25 11:46:44 +01:00
//
#ifndef ANIMTESTBED_ANIMGRAPHRESOURCE_H
#define ANIMTESTBED_ANIMGRAPHRESOURCE_H
#include "3rdparty/json/json.hpp"
2024-04-05 00:18:07 +02:00
#include "AnimGraphNodes.h"
struct AnimGraphBlendTree;
struct AnimGraphStateMachine;
2022-03-25 11:46:44 +01:00
struct AnimNodeResource {
virtual ~AnimNodeResource() = default;
2022-03-25 11:46:44 +01:00
std::string m_name;
std::string m_node_type_name;
2022-03-25 11:46:44 +01:00
AnimNode* m_anim_node = nullptr;
NodeDescriptorBase* m_socket_accessor = nullptr;
2022-03-25 11:46:44 +01:00
float m_position[2] = {0.f, 0.f};
};
2024-04-05 00:18:07 +02:00
static inline AnimNodeResource* AnimNodeResourceFactory(
const std::string& node_type_name);
2022-03-25 11:46:44 +01:00
struct BlendTreeConnectionResource {
size_t source_node_index = -1;
2023-04-15 22:07:22 +02:00
std::string source_socket_name;
size_t target_node_index = -1;
2023-04-15 22:07:22 +02:00
std::string target_socket_name;
2022-03-25 11:46:44 +01:00
};
struct BlendTreeResource {
std::vector<AnimNodeResource*> m_nodes;
std::vector<BlendTreeConnectionResource> m_connections;
2022-03-25 11:46:44 +01:00
2024-04-05 00:18:07 +02:00
~BlendTreeResource() { CleanupNodes(); }
void Reset() {
CleanupNodes();
m_connections.clear();
2022-03-25 11:46:44 +01:00
}
void CleanupNodes() {
for (AnimNodeResource* node_resource : m_nodes) {
delete node_resource->m_anim_node;
delete node_resource->m_socket_accessor;
delete node_resource;
}
m_nodes.clear();
}
void InitGraphConnectors() {
m_nodes.push_back(AnimNodeResourceFactory("BlendTreeSockets"));
m_nodes[0]->m_name = "Outputs";
m_nodes.push_back(AnimNodeResourceFactory("BlendTreeSockets"));
m_nodes[1]->m_name = "Inputs";
}
2022-03-25 11:46:44 +01:00
2024-04-05 00:18:07 +02:00
[[nodiscard]] AnimNodeResource* GetGraphOutputNode() const {
return m_nodes[0];
}
[[nodiscard]] AnimNodeResource* GetGraphInputNode() const {
return m_nodes[1];
}
2022-03-25 11:46:44 +01:00
size_t GetNodeIndex(const AnimNodeResource* node_resource) const {
2022-03-25 11:46:44 +01:00
for (size_t i = 0, n = m_nodes.size(); i < n; i++) {
if (m_nodes[i] == node_resource) {
2022-03-25 11:46:44 +01:00
return i;
}
}
return -1;
}
2024-04-05 00:18:07 +02:00
bool ConnectSockets(
const AnimNodeResource* source_node,
2022-03-25 11:46:44 +01:00
const std::string& source_socket_name,
const AnimNodeResource* target_node,
const std::string& target_socket_name);
2022-03-25 11:46:44 +01:00
std::vector<Socket*> GetConstantNodeInputs(
std::vector<NodeDescriptorBase*>& instance_node_descriptors) const {
std::vector<Socket*> result;
for (size_t i = 0; i < m_nodes.size(); i++) {
2024-04-05 00:18:07 +02:00
for (size_t j = 0,
num_inputs = instance_node_descriptors[i]->m_inputs.size();
j < num_inputs;
j++) {
Socket& input = instance_node_descriptors[i]->m_inputs[j];
if (*input.m_reference.ptr_ptr == nullptr) {
2024-04-05 00:18:07 +02:00
memcpy(
&input.m_value,
&m_nodes[i]->m_socket_accessor->m_inputs[j].m_value,
sizeof(Socket::SocketValue));
result.push_back(&input);
}
}
}
return result;
}
bool IsSocketConnected(
const AnimNodeResource* source_node,
const std::string& socket_name) {
assert(false && "Not yet implemented");
return false;
}
size_t GetNodeIndexForOutputSocket(const std::string& socket_name) const {
for (size_t i = 0; i < m_connections.size(); i++) {
const BlendTreeConnectionResource& connection = m_connections[i];
2024-04-05 00:18:07 +02:00
if (connection.target_node_index == 0
&& connection.target_socket_name == socket_name) {
return connection.source_node_index;
}
}
2024-04-05 00:18:07 +02:00
std::cerr << "Error: could not find a node connected to output '"
<< socket_name << "'." << std::endl;
return -1;
}
size_t GetNodeIndexForInputSocket(const std::string& socket_name) const {
for (size_t i = 0; i < m_connections.size(); i++) {
const BlendTreeConnectionResource& connection = m_connections[i];
2024-04-05 00:18:07 +02:00
if (connection.source_node_index == 1
&& connection.source_socket_name == socket_name) {
return connection.target_node_index;
}
}
2024-04-05 00:18:07 +02:00
std::cerr << "Error: could not find a node connected to input '"
<< socket_name << "'." << std::endl;
return -1;
}
};
struct StateMachineTransitionResources {
size_t source_state_index = -1;
size_t target_state_index = -1;
float blend_time = 0.f;
bool sync_blend = false;
};
struct StateMachineResource {
std::vector<AnimNodeResource> m_states;
std::vector<StateMachineTransitionResources> m_transitions;
};
2024-04-05 00:18:07 +02:00
struct AnimGraphResource : AnimNodeResource {
std::string m_graph_type_name;
BlendTreeResource m_blend_tree_resource;
typedef std::pair<const AnimNodeResource*, std::string> NodeSocketPair;
typedef std::map<NodeSocketPair, int> NodeSocketDataOffsetMap;
StateMachineResource m_state_machine_resource;
void Clear() { m_blend_tree_resource.Reset(); }
bool SaveToFile(const char* filename) const;
bool LoadFromFile(const char* filename);
void CreateBlendTreeInstance(AnimGraphBlendTree& result) const;
void CreateStateMachineInstance(AnimGraphStateMachine& result) const;
private:
// BlendTree
bool SaveBlendTreeResourceToFile(const char* filename) const;
void CreateBlendTreeRuntimeNodeInstances(AnimGraphBlendTree& result) const;
void PrepareBlendTreeIOData(
AnimGraphBlendTree& instance,
NodeSocketDataOffsetMap& node_offset_map) const;
void CreateBlendTreeConnectionInstances(
AnimGraphBlendTree& instance,
NodeSocketDataOffsetMap& node_offset_map) const;
void SetRuntimeNodeProperties(AnimGraphBlendTree& result) const;
bool SaveStateMachineResourceToFile(const char* filename) const;
bool LoadStateMachineResourceFromJson(nlohmann::json const& json_data);
2022-03-25 12:05:56 +01:00
};
2022-03-25 11:46:44 +01:00
static inline AnimNodeResource* AnimNodeResourceFactory(
const std::string& node_type_name) {
AnimNodeResource* result;
if (node_type_name == "BlendTree") {
AnimGraphResource* blend_tree_resource = new AnimGraphResource();
blend_tree_resource->m_blend_tree_resource.InitGraphConnectors();
result = blend_tree_resource;
} else {
result = new AnimNodeResource();
}
result->m_node_type_name = node_type_name;
if (node_type_name == "BlendTreeSockets") {
result->m_anim_node = AnimNodeFactory("BlendTree");
result->m_socket_accessor = new NodeDescriptorBase();
} else {
result->m_anim_node = AnimNodeFactory(node_type_name);
result->m_socket_accessor =
AnimNodeDescriptorFactory(node_type_name, result->m_anim_node);
}
return result;
}
2022-03-25 11:46:44 +01:00
#endif //ANIMTESTBED_ANIMGRAPHRESOURCE_H