270 lines
8.1 KiB
C++
270 lines
8.1 KiB
C++
//
|
|
// Created by martin on 25.03.22.
|
|
//
|
|
|
|
#include "AnimGraph.h"
|
|
|
|
#include <cstring>
|
|
|
|
void AnimGraph::updateOrderedNodes() {
|
|
m_eval_ordered_nodes.clear();
|
|
updateOrderedNodesRecursive(0);
|
|
}
|
|
|
|
void AnimGraph::updateOrderedNodesRecursive(int node_index) {
|
|
AnimNode* node = m_nodes[node_index];
|
|
const std::vector<AnimGraphConnection> node_input_connections =
|
|
m_node_input_connections[node_index];
|
|
for (size_t i = 0, n = node_input_connections.size(); i < n; i++) {
|
|
int input_node_index =
|
|
getAnimNodeIndex(node_input_connections[i].m_source_node);
|
|
|
|
if (input_node_index == 1) {
|
|
continue;
|
|
}
|
|
|
|
updateOrderedNodesRecursive(input_node_index);
|
|
}
|
|
|
|
if (node_index != 0) {
|
|
m_eval_ordered_nodes.push_back(node);
|
|
}
|
|
}
|
|
|
|
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<AnimGraphConnection>& graph_output_inputs =
|
|
m_node_input_connections[0];
|
|
for (size_t i = 0, n = graph_output_inputs.size(); i < n; i++) {
|
|
const AnimGraphConnection& graph_input = graph_output_inputs[i];
|
|
AnimNode* node = graph_input.m_source_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_input_connections[node_index]);
|
|
|
|
// Non-animation data inputs are always active.
|
|
for (size_t j = 0, nj = m_node_input_connections[node_index].size();
|
|
j < nj;
|
|
j++) {
|
|
const AnimGraphConnection& input =
|
|
m_node_input_connections[node_index][j];
|
|
if (input.m_source_node != nullptr
|
|
&& input.m_target_socket.m_type
|
|
!= SocketType::SocketTypeAnimation) {
|
|
input.m_source_node->m_state = AnimNodeEvalState::Activated;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void AnimGraph::prepareNodeEval(size_t node_index) {
|
|
AnimNode* node = m_nodes[node_index];
|
|
|
|
for (size_t i = 0, n = m_node_output_connections[node_index].size(); i < n;
|
|
i++) {
|
|
AnimGraphConnection& output_connection =
|
|
m_node_output_connections[node_index][i];
|
|
if (output_connection.m_source_socket.m_type
|
|
!= SocketType::SocketTypeAnimation) {
|
|
continue;
|
|
}
|
|
|
|
(*output_connection.m_source_socket.m_value.ptr_ptr) =
|
|
m_anim_data_work_buffer.peek();
|
|
m_anim_data_work_buffer.pop();
|
|
}
|
|
|
|
for (size_t i = 0, n = m_node_input_connections[node_index].size(); i < n;
|
|
i++) {
|
|
AnimGraphConnection& input_connection =
|
|
m_node_input_connections[node_index][i];
|
|
if (input_connection.m_source_socket.m_type
|
|
!= SocketType::SocketTypeAnimation) {
|
|
continue;
|
|
}
|
|
|
|
(*input_connection.m_target_socket.m_value.ptr_ptr) =
|
|
(*input_connection.m_source_socket.m_value.ptr_ptr);
|
|
}
|
|
}
|
|
|
|
void AnimGraph::finishNodeEval(size_t node_index) {
|
|
AnimNode* node = m_nodes[node_index];
|
|
|
|
for (size_t i = 0, n = m_node_input_connections[node_index].size(); i < n;
|
|
i++) {
|
|
AnimGraphConnection& input_connection =
|
|
m_node_input_connections[node_index][i];
|
|
if (input_connection.m_source_socket.m_type
|
|
!= SocketType::SocketTypeAnimation) {
|
|
continue;
|
|
}
|
|
|
|
m_anim_data_work_buffer.push(
|
|
static_cast<AnimData*>(input_connection.m_source_socket.m_value.ptr));
|
|
(*input_connection.m_source_socket.m_value.ptr_ptr) = nullptr;
|
|
}
|
|
}
|
|
|
|
|
|
void AnimGraph::evalInputNode() {
|
|
for (size_t i = 0, n = m_node_output_connections[1].size(); i < n; i++) {
|
|
AnimGraphConnection& graph_input_connection =
|
|
m_node_output_connections[1][i];
|
|
|
|
if (graph_input_connection.m_source_socket.m_type
|
|
!= SocketType::SocketTypeAnimation) {
|
|
memcpy(
|
|
*graph_input_connection.m_target_socket.m_value.ptr_ptr,
|
|
graph_input_connection.m_source_socket.m_value.ptr,
|
|
sizeof(void*));
|
|
printf("bla");
|
|
} else {
|
|
// TODO: how to deal with anim data outputs?
|
|
}
|
|
}
|
|
}
|
|
|
|
void AnimGraph::evalOutputNode() {
|
|
for (size_t i = 0, n = m_node_input_connections[0].size(); i < n; i++) {
|
|
AnimGraphConnection& graph_output_connection =
|
|
m_node_input_connections[0][i];
|
|
|
|
if (graph_output_connection.m_source_socket.m_type
|
|
!= SocketType::SocketTypeAnimation) {
|
|
memcpy(
|
|
graph_output_connection.m_target_socket.m_value.ptr,
|
|
graph_output_connection.m_source_socket.m_value.ptr,
|
|
graph_output_connection.m_target_socket.m_type_size);
|
|
} else {
|
|
// TODO: how to deal with anim data outputs?
|
|
}
|
|
}
|
|
}
|
|
|
|
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_input_connections[node_index]);
|
|
}
|
|
}
|
|
|
|
void AnimGraph::updateTime(float dt) {
|
|
const std::vector<AnimGraphConnection> graph_output_inputs =
|
|
m_node_input_connections[0];
|
|
for (size_t i = 0, n = graph_output_inputs.size(); i < n; i++) {
|
|
AnimNode* node = graph_output_inputs[i].m_source_node;
|
|
if (node != nullptr) {
|
|
node->UpdateTime(node->m_time_now, node->m_time_now + dt);
|
|
}
|
|
}
|
|
|
|
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::TimeUpdated) {
|
|
continue;
|
|
}
|
|
|
|
int node_index = node->m_index;
|
|
const std::vector<AnimGraphConnection> node_input_connections =
|
|
m_node_input_connections[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_input_connections.size(); i < n; i++) {
|
|
AnimNode* input_node = node_input_connections[i].m_source_node;
|
|
|
|
// Only propagate time updates via animation sockets.
|
|
if (input_node != nullptr
|
|
&& node_input_connections[i].m_target_socket.m_type
|
|
== SocketType::SocketTypeAnimation
|
|
&& input_node->m_state == AnimNodeEvalState::Activated) {
|
|
input_node->UpdateTime(node_time_last, node_time_now);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void AnimGraph::evaluate() {
|
|
constexpr int eval_stack_size = 5;
|
|
int eval_stack_index = eval_stack_size;
|
|
AnimData eval_buffers[eval_stack_size];
|
|
AnimData* eval_stack[eval_stack_size];
|
|
for (size_t i = 0; i < eval_stack_size; i++) {
|
|
eval_stack[i] = &eval_buffers[i];
|
|
}
|
|
|
|
for (int i = 0, n = m_eval_ordered_nodes.size(); i < n; i++) {
|
|
AnimNode* node = m_eval_ordered_nodes[i];
|
|
|
|
if (node->m_state == AnimNodeEvalState::Deactivated) {
|
|
continue;
|
|
}
|
|
|
|
prepareNodeEval(node->m_index);
|
|
|
|
node->Evaluate();
|
|
|
|
finishNodeEval(node->m_index);
|
|
}
|
|
}
|
|
|
|
Socket* AnimGraph::getInputSocket(const std::string& name) {
|
|
for (size_t i = 0, n = m_node_output_connections[1].size(); i < n; i++) {
|
|
AnimGraphConnection& connection = m_node_output_connections[1][i];
|
|
if (connection.m_source_socket.m_name == name) {
|
|
return &connection.m_source_socket;
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
Socket* AnimGraph::getOutputSocket(const std::string& name) {
|
|
for (size_t i = 0, n = m_node_input_connections[0].size(); i < n; i++) {
|
|
AnimGraphConnection& connection = m_node_input_connections[0][i];
|
|
if (connection.m_target_socket.m_name == name) {
|
|
return &connection.m_target_socket;
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
const Socket* AnimGraph::getInputSocket(const std::string& name) const {
|
|
for (size_t i = 0, n = m_node_output_connections[1].size(); i < n; i++) {
|
|
const AnimGraphConnection& connection = m_node_output_connections[1][i];
|
|
if (connection.m_source_socket.m_name == name) {
|
|
return &connection.m_source_socket;
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
const Socket* AnimGraph::getOutputSocket(const std::string& name) const {
|
|
for (size_t i = 0, n = m_node_input_connections[0].size(); i < n; i++) {
|
|
const AnimGraphConnection& connection = m_node_input_connections[0][i];
|
|
if (connection.m_target_socket.m_name == name) {
|
|
return &connection.m_target_socket;
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
} |