// // Created by martin on 25.03.22. // #ifndef ANIMTESTBED_ANIMGRAPH_H #define ANIMTESTBED_ANIMGRAPH_H #include "AnimGraphData.h" #include "AnimGraphNodes.h" // // AnimGraph (Runtime) // struct AnimGraph { AnimData m_local_transforms; std::vector m_nodes; std::vector m_eval_ordered_nodes; std::vector > m_node_input_connections; std::vector > m_node_output_connections; NodeSocketAccessorBase* m_socket_accessor; char* m_input_buffer = nullptr; char* m_output_buffer = nullptr; std::vector& getGraphOutputs() { return m_socket_accessor->m_inputs; } std::vector& getGraphInputs() { return m_socket_accessor->m_outputs; } AnimDataAllocator m_anim_data_allocator; ~AnimGraph() { dealloc(); } bool init(AnimGraphContext& context); void dealloc() { if (m_node_input_connections.size() > 0) { std::vector& 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( 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(); } } } delete[] m_input_buffer; delete[] m_output_buffer; for (int i = 0; i < m_nodes.size(); i++) { delete m_nodes[i]; } delete m_socket_accessor; } void updateOrderedNodes(); void updateOrderedNodesRecursive(int node_index); void markActiveNodes(); bool checkIsNodeActive(AnimNode* node) { return node->m_state != AnimNodeEvalState::Deactivated; } void evalInputNode(); void prepareNodeEval(AnimGraphContext& graph_context, size_t node_index); void finishNodeEval(size_t node_index); void evalOutputNode(); void evalSyncTracks(); void updateTime(float dt); void evaluate(AnimGraphContext& context); void resetNodeStates() { 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; } } Socket* getInputSocket(const std::string& name); Socket* getOutputSocket(const std::string& name); 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) { return input_socket->m_reference.ptr; } return nullptr; } 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; } 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; } const AnimNode* getAnimNodeForInput( size_t node_index, const std::string& input_name) const { assert(node_index < m_nodes.size()); const std::vector& input_connection = m_node_input_connections[node_index]; 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; } } 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; } size_t getAnimNodeIndex(AnimNode* node) { for (size_t i = 0; i < m_nodes.size(); i++) { if (m_nodes[i] == node) { return i; } } return -1; } }; #endif //ANIMTESTBED_ANIMGRAPH_H