// // Created by martin on 25.03.22. // #include "AnimGraph.h" void AnimGraph::updateOrderedNodes() { std::vector node_index_stack; node_index_stack.push_back(0); m_eval_ordered_nodes.clear(); while (node_index_stack.size() > 0) { std::vector& node_inputs = m_node_inputs[node_index_stack.back()]; node_index_stack.pop_back(); for (size_t i = 0, n = node_inputs.size(); i < n; i++) { AnimNode* input_node = node_inputs[i].m_node; if (input_node == nullptr) { continue; } int input_node_index = input_node->m_index; bool is_node_processed = false; for (size_t j = 0, m = m_eval_ordered_nodes.size(); j < m; j++) { if (m_eval_ordered_nodes[j] == input_node) { is_node_processed = true; break; } } if (is_node_processed) { continue; } m_eval_ordered_nodes.push_back(input_node); node_index_stack.push_back(input_node_index); } } } void AnimGraph::markActiveNodes() { for (size_t i = 0, n = m_nodes.size(); i < n; i++) { m_nodes[i]->m_state = AnimNodeEvalState::Deactivated; } const std::vector graph_output_inputs = m_node_inputs[0]; for (size_t i = 0, n = graph_output_inputs.size(); i < n; i++) { const NodeInput& graph_input = graph_output_inputs[i]; AnimNode* node = graph_input.m_node; if (node != nullptr) { node->m_state = AnimNodeEvalState::Activated; } } for (size_t i = 0, n = m_eval_ordered_nodes.size(); i < n; i++) { AnimNode* node = m_eval_ordered_nodes[i]; if (checkIsNodeActive(node)) { int node_index = node->m_index; node->MarkActiveInputs(m_node_inputs[node_index]); // Non-animation data inputs are always active. for (size_t j = 0, nj = m_node_inputs[node_index].size(); j < nj; j++) { const NodeInput& input = m_node_inputs[node_index][j]; if (input.m_node != nullptr && input.m_type != SocketType::SocketTypeAnimation) { input.m_node->m_state = AnimNodeEvalState::Activated; } } } } } void AnimGraph::evalSyncTracks() { for (size_t i = m_eval_ordered_nodes.size() - 1; i >= 0; i--) { AnimNode* node = m_eval_ordered_nodes[i]; int node_index = node->m_index; if (node->m_state == AnimNodeEvalState::Deactivated) { continue; } node->CalcSyncTrack(m_node_inputs[node_index]); } } void AnimGraph::updateTime(float dt) { const std::vector graph_output_inputs = m_node_inputs[0]; for (size_t i = 0, n = graph_output_inputs.size(); i < n; i++) { AnimNode* node = m_eval_ordered_nodes[i]; if (node != nullptr) { node->UpdateTime(node->m_time_now, node->m_time_now + dt); } } for (size_t i = 0, n = m_eval_ordered_nodes.size(); i < n; i++) { AnimNode* node = m_eval_ordered_nodes[i]; if (node->m_state != AnimNodeEvalState::TimeUpdated) { continue; } int node_index = node->m_index; const std::vector node_inputs = m_node_inputs[node_index]; float node_time_now = node->m_time_now; float node_time_last = node->m_time_last; for (size_t i = 0, n = node_inputs.size(); i < n; i++) { AnimNode* input_node = node_inputs[i].m_node; // Only propagate time updates via animation sockets. if (input_node != nullptr && node_inputs[i].m_type == SocketType::SocketTypeAnimation && input_node->m_state == AnimNodeEvalState::Activated) { input_node->UpdateTime(node_time_last, node_time_now); } } } } void AnimGraph::evaluate() { for (size_t i = m_eval_ordered_nodes.size() - 1; i >= 0; i--) { AnimNode* node = m_eval_ordered_nodes[i]; if (node->m_state == AnimNodeEvalState::Deactivated) { continue; } node->Evaluate(); } } void* AnimGraph::getOutput(const std::string& name) const { Socket* socket = m_socket_accessor->FindInputSocket(name); if (socket == nullptr) { return nullptr; } return socket->m_value.ptr; } void* AnimGraph::getInput(const std::string& name) const { Socket* socket = m_socket_accessor->FindOutputSocket(name); if (socket == nullptr) { return nullptr; } return *(socket->m_value.ptr_ptr); }