2022-03-25 11:46:44 +01:00
|
|
|
//
|
|
|
|
// Created by martin on 25.03.22.
|
|
|
|
//
|
|
|
|
|
|
|
|
#ifndef ANIMTESTBED_ANIMGRAPH_H
|
|
|
|
#define ANIMTESTBED_ANIMGRAPH_H
|
|
|
|
|
2022-03-25 12:05:56 +01:00
|
|
|
#include "AnimGraphData.h"
|
|
|
|
#include "AnimGraphNodes.h"
|
2022-03-25 11:46:44 +01:00
|
|
|
|
|
|
|
//
|
|
|
|
// AnimGraph (Runtime)
|
|
|
|
//
|
|
|
|
struct AnimGraph {
|
|
|
|
AnimData m_local_transforms;
|
|
|
|
|
|
|
|
std::vector<AnimNode*> m_nodes;
|
|
|
|
std::vector<AnimNode*> m_eval_ordered_nodes;
|
2022-04-01 13:19:54 +02:00
|
|
|
std::vector<std::vector<AnimGraphConnection> > m_node_input_connections;
|
|
|
|
std::vector<std::vector<AnimGraphConnection> > m_node_output_connections;
|
2022-03-25 11:46:44 +01:00
|
|
|
NodeSocketAccessorBase* m_socket_accessor;
|
|
|
|
char* m_input_buffer = nullptr;
|
|
|
|
char* m_output_buffer = nullptr;
|
|
|
|
|
|
|
|
std::vector<Socket>& getGraphOutputs() { return m_socket_accessor->m_inputs; }
|
|
|
|
std::vector<Socket>& getGraphInputs() { return m_socket_accessor->m_outputs; }
|
|
|
|
|
2022-04-14 18:03:36 +02:00
|
|
|
AnimDataAllocator m_anim_data_allocator;
|
2022-04-01 13:19:54 +02:00
|
|
|
|
2023-03-26 23:39:11 +02:00
|
|
|
~AnimGraph() { dealloc(); }
|
|
|
|
|
|
|
|
bool init(AnimGraphContext& context);
|
|
|
|
void dealloc() {
|
|
|
|
if (m_node_input_connections.size() > 0) {
|
|
|
|
std::vector<AnimGraphConnection>& graph_outputs =
|
|
|
|
m_node_input_connections[0];
|
|
|
|
|
|
|
|
for (size_t i = 0, n = graph_outputs.size(); i < n; i++) {
|
|
|
|
AnimGraphConnection& connection = graph_outputs[i];
|
|
|
|
if (connection.m_target_socket.m_type
|
|
|
|
== SocketType::SocketTypeAnimation) {
|
|
|
|
AnimData* graph_anim_output = static_cast<AnimData*>(
|
|
|
|
connection.m_target_socket.m_reference.ptr);
|
|
|
|
assert(graph_anim_output != nullptr);
|
|
|
|
|
|
|
|
// we have to explicitly call the destructor as the AnimData* was
|
|
|
|
// initialized using a placement new operator.
|
|
|
|
graph_anim_output->m_local_matrices.vector::~vector();
|
|
|
|
}
|
2022-04-14 18:03:36 +02:00
|
|
|
}
|
|
|
|
}
|
2023-03-28 22:00:58 +02:00
|
|
|
m_node_input_connections.clear();
|
|
|
|
|
|
|
|
if (m_node_output_connections.size() > 0) {
|
|
|
|
std::vector<AnimGraphConnection>& graph_inputs =
|
|
|
|
m_node_output_connections[0];
|
|
|
|
|
|
|
|
for (size_t i = 0, n = graph_inputs.size(); i < n; i++) {
|
|
|
|
AnimGraphConnection& connection = graph_inputs[i];
|
|
|
|
if (connection.m_target_socket.m_type
|
|
|
|
== SocketType::SocketTypeAnimation) {
|
|
|
|
AnimData* graph_anim_output = static_cast<AnimData*>(
|
|
|
|
connection.m_target_socket.m_reference.ptr);
|
|
|
|
assert(graph_anim_output != nullptr);
|
|
|
|
|
|
|
|
// we have to explicitly call the destructor as the AnimData* was
|
|
|
|
// initialized using a placement new operator.
|
|
|
|
graph_anim_output->m_local_matrices.vector::~vector();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_node_output_connections.clear();
|
2022-04-14 18:03:36 +02:00
|
|
|
|
2022-03-25 11:46:44 +01:00
|
|
|
delete[] m_input_buffer;
|
|
|
|
delete[] m_output_buffer;
|
|
|
|
|
|
|
|
for (int i = 0; i < m_nodes.size(); i++) {
|
|
|
|
delete m_nodes[i];
|
|
|
|
}
|
2023-03-28 22:00:58 +02:00
|
|
|
m_nodes.clear();
|
2022-03-25 11:46:44 +01:00
|
|
|
|
|
|
|
delete m_socket_accessor;
|
|
|
|
}
|
|
|
|
|
|
|
|
void updateOrderedNodes();
|
2022-04-01 13:19:54 +02:00
|
|
|
void updateOrderedNodesRecursive(int node_index);
|
2022-03-25 11:46:44 +01:00
|
|
|
void markActiveNodes();
|
|
|
|
bool checkIsNodeActive(AnimNode* node) {
|
|
|
|
return node->m_state != AnimNodeEvalState::Deactivated;
|
|
|
|
}
|
2022-04-01 13:19:54 +02:00
|
|
|
|
2022-04-03 21:05:11 +02:00
|
|
|
void evalInputNode();
|
2022-04-13 15:47:43 +02:00
|
|
|
void prepareNodeEval(AnimGraphContext& graph_context, size_t node_index);
|
2022-04-01 13:19:54 +02:00
|
|
|
void finishNodeEval(size_t node_index);
|
2022-04-03 21:05:11 +02:00
|
|
|
void evalOutputNode();
|
2022-04-01 13:19:54 +02:00
|
|
|
|
2022-03-25 11:46:44 +01:00
|
|
|
void evalSyncTracks();
|
|
|
|
void updateTime(float dt);
|
2022-04-11 16:46:09 +02:00
|
|
|
void evaluate(AnimGraphContext& context);
|
2023-03-26 23:39:11 +02:00
|
|
|
void resetNodeStates() {
|
2022-03-25 11:46:44 +01:00
|
|
|
for (size_t i = 0, n = m_nodes.size(); i < n; i++) {
|
|
|
|
m_nodes[i]->m_time_now = 0.f;
|
|
|
|
m_nodes[i]->m_time_last = 0.f;
|
|
|
|
m_nodes[i]->m_state = AnimNodeEvalState::Undefined;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-01 13:19:54 +02:00
|
|
|
Socket* getInputSocket(const std::string& name);
|
|
|
|
Socket* getOutputSocket(const std::string& name);
|
2022-03-25 11:46:44 +01:00
|
|
|
|
2022-04-03 21:05:11 +02:00
|
|
|
const Socket* getInputSocket(const std::string& name) const;
|
|
|
|
const Socket* getOutputSocket(const std::string& name) const;
|
|
|
|
|
|
|
|
void* getInputPtr(const std::string& name) const {
|
|
|
|
const Socket* input_socket = getInputSocket(name);
|
|
|
|
if (input_socket != nullptr) {
|
2022-04-11 16:46:09 +02:00
|
|
|
return input_socket->m_reference.ptr;
|
2022-04-03 21:05:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2022-04-13 15:47:43 +02:00
|
|
|
void* getOutputPtr(const std::string& name) const {
|
|
|
|
const Socket* input_socket = getOutputSocket(name);
|
|
|
|
if (input_socket != nullptr) {
|
|
|
|
return input_socket->m_reference.ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2022-03-25 11:46:44 +01:00
|
|
|
int getNodeEvalOrderIndex(const AnimNode* node) {
|
|
|
|
for (size_t i = 0, n = m_eval_ordered_nodes.size(); i < n; i++) {
|
|
|
|
if (m_eval_ordered_nodes[i] == node) {
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
2023-03-26 23:39:11 +02:00
|
|
|
const AnimNode* getAnimNodeForInput(
|
2022-03-25 11:46:44 +01:00
|
|
|
size_t node_index,
|
2022-04-01 13:19:54 +02:00
|
|
|
const std::string& input_name) const {
|
2022-03-25 11:46:44 +01:00
|
|
|
assert(node_index < m_nodes.size());
|
|
|
|
|
2023-03-26 23:39:11 +02:00
|
|
|
const std::vector<AnimGraphConnection>& input_connection =
|
|
|
|
m_node_input_connections[node_index];
|
2022-04-01 13:19:54 +02:00
|
|
|
for (size_t i = 0, n = input_connection.size(); i < n; i++) {
|
|
|
|
if (input_connection[i].m_target_socket.m_name == input_name) {
|
|
|
|
return input_connection[i].m_source_node;
|
2022-03-25 11:46:44 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
AnimNode* getAnimNode(const char* name) {
|
|
|
|
for (size_t i = 0; i < m_nodes.size(); i++) {
|
|
|
|
if (m_nodes[i]->m_name == name) {
|
|
|
|
return m_nodes[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
2022-04-01 13:19:54 +02:00
|
|
|
|
2023-03-26 23:39:11 +02:00
|
|
|
size_t getAnimNodeIndex(AnimNode* node) {
|
2022-04-01 13:19:54 +02:00
|
|
|
for (size_t i = 0; i < m_nodes.size(); i++) {
|
|
|
|
if (m_nodes[i] == node) {
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
2022-03-25 11:46:44 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif //ANIMTESTBED_ANIMGRAPH_H
|