// // Created by martin on 25.03.22. // #ifndef ANIMTESTBED_ANIMGRAPH_H #define ANIMTESTBED_ANIMGRAPH_H #include "AnimGraphData.h" #include "AnimGraphNodes.h" struct AnimDataWorkBuffer { std::vector m_eval_anim_data; std::vector m_available_data; AnimDataWorkBuffer(size_t stack_size) { m_eval_anim_data.resize(stack_size); m_available_data.resize(stack_size); for (size_t i = 0; i < stack_size; i++) { m_available_data[i] = &m_eval_anim_data[i]; } } void push(AnimData* anim_data) { assert (m_available_data.size() < m_eval_anim_data.size()); m_available_data.push_back(anim_data); } void pop() { assert (m_available_data.size() > 0); m_available_data.pop_back(); } AnimData* peek() { return m_available_data.back(); } }; // // 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; } AnimDataWorkBuffer m_anim_data_work_buffer = AnimDataWorkBuffer(5); ~AnimGraph() { 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(size_t node_index); void finishNodeEval(size_t node_index); void evalOutputNode(); void evalSyncTracks(); void updateTime(float dt); void evaluate(); void reset() { 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_value.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