Initial graph evaluations, added Float to Vec3 Node, minor editor tweaks.
parent
08ae84fcb4
commit
5d8c1e289b
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
#include "AnimGraph.h"
|
#include "AnimGraph.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
void AnimGraph::updateOrderedNodes() {
|
void AnimGraph::updateOrderedNodes() {
|
||||||
m_eval_ordered_nodes.clear();
|
m_eval_ordered_nodes.clear();
|
||||||
updateOrderedNodesRecursive(0);
|
updateOrderedNodesRecursive(0);
|
||||||
|
@ -14,11 +16,19 @@ void AnimGraph::updateOrderedNodesRecursive(int node_index) {
|
||||||
const std::vector<AnimGraphConnection> node_input_connections =
|
const std::vector<AnimGraphConnection> node_input_connections =
|
||||||
m_node_input_connections[node_index];
|
m_node_input_connections[node_index];
|
||||||
for (size_t i = 0, n = node_input_connections.size(); i < n; i++) {
|
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);
|
int input_node_index =
|
||||||
|
getAnimNodeIndex(node_input_connections[i].m_source_node);
|
||||||
|
|
||||||
|
if (input_node_index == 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
updateOrderedNodesRecursive(input_node_index);
|
updateOrderedNodesRecursive(input_node_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_eval_ordered_nodes.push_back(node);
|
if (node_index != 0) {
|
||||||
|
m_eval_ordered_nodes.push_back(node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimGraph::markActiveNodes() {
|
void AnimGraph::markActiveNodes() {
|
||||||
|
@ -26,7 +36,8 @@ void AnimGraph::markActiveNodes() {
|
||||||
m_nodes[i]->m_state = AnimNodeEvalState::Deactivated;
|
m_nodes[i]->m_state = AnimNodeEvalState::Deactivated;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<AnimGraphConnection>& graph_output_inputs = m_node_input_connections[0];
|
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++) {
|
for (size_t i = 0, n = graph_output_inputs.size(); i < n; i++) {
|
||||||
const AnimGraphConnection& graph_input = graph_output_inputs[i];
|
const AnimGraphConnection& graph_input = graph_output_inputs[i];
|
||||||
AnimNode* node = graph_input.m_source_node;
|
AnimNode* node = graph_input.m_source_node;
|
||||||
|
@ -42,10 +53,14 @@ void AnimGraph::markActiveNodes() {
|
||||||
node->MarkActiveInputs(m_node_input_connections[node_index]);
|
node->MarkActiveInputs(m_node_input_connections[node_index]);
|
||||||
|
|
||||||
// Non-animation data inputs are always active.
|
// Non-animation data inputs are always active.
|
||||||
for (size_t j = 0, nj = m_node_input_connections[node_index].size(); j < nj; j++) {
|
for (size_t j = 0, nj = m_node_input_connections[node_index].size();
|
||||||
const AnimGraphConnection& input = m_node_input_connections[node_index][j];
|
j < nj;
|
||||||
|
j++) {
|
||||||
|
const AnimGraphConnection& input =
|
||||||
|
m_node_input_connections[node_index][j];
|
||||||
if (input.m_source_node != nullptr
|
if (input.m_source_node != nullptr
|
||||||
&& input.m_target_socket.m_type != SocketType::SocketTypeAnimation) {
|
&& input.m_target_socket.m_type
|
||||||
|
!= SocketType::SocketTypeAnimation) {
|
||||||
input.m_source_node->m_state = AnimNodeEvalState::Activated;
|
input.m_source_node->m_state = AnimNodeEvalState::Activated;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,6 +117,42 @@ void AnimGraph::finishNodeEval(size_t node_index) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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() {
|
void AnimGraph::evalSyncTracks() {
|
||||||
for (size_t i = m_eval_ordered_nodes.size() - 1; i >= 0; i--) {
|
for (size_t i = m_eval_ordered_nodes.size() - 1; i >= 0; i--) {
|
||||||
AnimNode* node = m_eval_ordered_nodes[i];
|
AnimNode* node = m_eval_ordered_nodes[i];
|
||||||
|
@ -115,22 +166,24 @@ void AnimGraph::evalSyncTracks() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimGraph::updateTime(float dt) {
|
void AnimGraph::updateTime(float dt) {
|
||||||
const std::vector<AnimGraphConnection> graph_output_inputs = m_node_input_connections[0];
|
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++) {
|
for (size_t i = 0, n = graph_output_inputs.size(); i < n; i++) {
|
||||||
AnimNode* node = m_eval_ordered_nodes[i];
|
AnimNode* node = graph_output_inputs[i].m_source_node;
|
||||||
if (node != nullptr) {
|
if (node != nullptr) {
|
||||||
node->UpdateTime(node->m_time_now, node->m_time_now + dt);
|
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++) {
|
for (size_t i = m_eval_ordered_nodes.size() - 1; i > 0; --i) {
|
||||||
AnimNode* node = m_eval_ordered_nodes[i];
|
AnimNode* node = m_eval_ordered_nodes[i];
|
||||||
if (node->m_state != AnimNodeEvalState::TimeUpdated) {
|
if (node->m_state != AnimNodeEvalState::TimeUpdated) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int node_index = node->m_index;
|
int node_index = node->m_index;
|
||||||
const std::vector<AnimGraphConnection> node_input_connections = m_node_input_connections[node_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_now = node->m_time_now;
|
||||||
float node_time_last = node->m_time_last;
|
float node_time_last = node->m_time_last;
|
||||||
|
|
||||||
|
@ -139,7 +192,8 @@ void AnimGraph::updateTime(float dt) {
|
||||||
|
|
||||||
// Only propagate time updates via animation sockets.
|
// Only propagate time updates via animation sockets.
|
||||||
if (input_node != nullptr
|
if (input_node != nullptr
|
||||||
&& node_input_connections[i].m_target_socket.m_type == SocketType::SocketTypeAnimation
|
&& node_input_connections[i].m_target_socket.m_type
|
||||||
|
== SocketType::SocketTypeAnimation
|
||||||
&& input_node->m_state == AnimNodeEvalState::Activated) {
|
&& input_node->m_state == AnimNodeEvalState::Activated) {
|
||||||
input_node->UpdateTime(node_time_last, node_time_now);
|
input_node->UpdateTime(node_time_last, node_time_now);
|
||||||
}
|
}
|
||||||
|
@ -156,7 +210,7 @@ void AnimGraph::evaluate() {
|
||||||
eval_stack[i] = &eval_buffers[i];
|
eval_stack[i] = &eval_buffers[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = m_eval_ordered_nodes.size() - 1; i >= 0; i--) {
|
for (int i = 0, n = m_eval_ordered_nodes.size(); i < n; i++) {
|
||||||
AnimNode* node = m_eval_ordered_nodes[i];
|
AnimNode* node = m_eval_ordered_nodes[i];
|
||||||
|
|
||||||
if (node->m_state == AnimNodeEvalState::Deactivated) {
|
if (node->m_state == AnimNodeEvalState::Deactivated) {
|
||||||
|
@ -172,11 +226,10 @@ void AnimGraph::evaluate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Socket* AnimGraph::getInputSocket(const std::string& name) {
|
Socket* AnimGraph::getInputSocket(const std::string& name) {
|
||||||
Socket* socket = nullptr;
|
|
||||||
for (size_t i = 0, n = m_node_output_connections[1].size(); i < n; i++) {
|
for (size_t i = 0, n = m_node_output_connections[1].size(); i < n; i++) {
|
||||||
AnimGraphConnection& connection = m_node_output_connections[1][i];
|
AnimGraphConnection& connection = m_node_output_connections[1][i];
|
||||||
if (connection.m_target_socket.m_name == name) {
|
if (connection.m_source_socket.m_name == name) {
|
||||||
return &connection.m_target_socket;
|
return &connection.m_source_socket;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +237,6 @@ Socket* AnimGraph::getInputSocket(const std::string& name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Socket* AnimGraph::getOutputSocket(const std::string& name) {
|
Socket* AnimGraph::getOutputSocket(const std::string& name) {
|
||||||
Socket* socket = nullptr;
|
|
||||||
for (size_t i = 0, n = m_node_input_connections[0].size(); i < n; i++) {
|
for (size_t i = 0, n = m_node_input_connections[0].size(); i < n; i++) {
|
||||||
AnimGraphConnection& connection = m_node_input_connections[0][i];
|
AnimGraphConnection& connection = m_node_input_connections[0][i];
|
||||||
if (connection.m_target_socket.m_name == name) {
|
if (connection.m_target_socket.m_name == name) {
|
||||||
|
@ -194,3 +246,25 @@ Socket* AnimGraph::getOutputSocket(const std::string& name) {
|
||||||
|
|
||||||
return nullptr;
|
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;
|
||||||
|
}
|
|
@ -74,8 +74,10 @@ struct AnimGraph {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void evalInputNode();
|
||||||
void prepareNodeEval(size_t node_index);
|
void prepareNodeEval(size_t node_index);
|
||||||
void finishNodeEval(size_t node_index);
|
void finishNodeEval(size_t node_index);
|
||||||
|
void evalOutputNode();
|
||||||
|
|
||||||
void evalSyncTracks();
|
void evalSyncTracks();
|
||||||
void updateTime(float dt);
|
void updateTime(float dt);
|
||||||
|
@ -91,6 +93,18 @@ struct AnimGraph {
|
||||||
Socket* getInputSocket(const std::string& name);
|
Socket* getInputSocket(const std::string& name);
|
||||||
Socket* getOutputSocket(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) {
|
int getNodeEvalOrderIndex(const AnimNode* node) {
|
||||||
for (size_t i = 0, n = m_eval_ordered_nodes.size(); i < n; i++) {
|
for (size_t i = 0, n = m_eval_ordered_nodes.size(); i < n; i++) {
|
||||||
if (m_eval_ordered_nodes[i] == node) {
|
if (m_eval_ordered_nodes[i] == node) {
|
||||||
|
|
|
@ -217,6 +217,14 @@ void AnimGraphEditorUpdate() {
|
||||||
node_type_name = "SpeedScale";
|
node_type_name = "SpeedScale";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ImGui::MenuItem("MathAddNode")) {
|
||||||
|
node_type_name = "MathAddNode";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::MenuItem("MathFloatToVec3Node")) {
|
||||||
|
node_type_name = "MathFloatToVec3Node";
|
||||||
|
}
|
||||||
|
|
||||||
if (node_type_name != "") {
|
if (node_type_name != "") {
|
||||||
AnimNodeResource node_resource =
|
AnimNodeResource node_resource =
|
||||||
AnimNodeResourceFactory(node_type_name);
|
AnimNodeResourceFactory(node_type_name);
|
||||||
|
@ -235,6 +243,7 @@ void AnimGraphEditorUpdate() {
|
||||||
AnimNodeResource& node_resource = graph_resource.m_nodes[i];
|
AnimNodeResource& node_resource = graph_resource.m_nodes[i];
|
||||||
|
|
||||||
ImNodes::BeginNode(i);
|
ImNodes::BeginNode(i);
|
||||||
|
ImGui::PushItemWidth(110.0f);
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
ImNodes::BeginNodeTitleBar();
|
ImNodes::BeginNodeTitleBar();
|
||||||
|
@ -264,6 +273,16 @@ void AnimGraphEditorUpdate() {
|
||||||
socket_color);
|
socket_color);
|
||||||
ImGui::TextUnformatted(socket.m_name.c_str());
|
ImGui::TextUnformatted(socket.m_name.c_str());
|
||||||
|
|
||||||
|
bool socket_connected = graph_resource.isSocketConnected(node_resource, socket.m_name);
|
||||||
|
if (!socket_connected &&
|
||||||
|
(socket.m_type == SocketType::SocketTypeFloat)) {
|
||||||
|
ImGui::SameLine();
|
||||||
|
float socket_value = 0.f;
|
||||||
|
ImGui::PushItemWidth(100.0f - ImGui::CalcTextSize(socket.m_name.c_str()).x);
|
||||||
|
ImGui::DragFloat("##hidelabel", &socket_value, 0.01f);
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
}
|
||||||
|
|
||||||
ImNodes::PushAttributeFlag(
|
ImNodes::PushAttributeFlag(
|
||||||
ImNodesAttributeFlags_EnableLinkDetachWithDragClick);
|
ImNodesAttributeFlags_EnableLinkDetachWithDragClick);
|
||||||
ImNodes::EndInputAttribute();
|
ImNodes::EndInputAttribute();
|
||||||
|
@ -316,6 +335,8 @@ void AnimGraphEditorUpdate() {
|
||||||
ImVec2 node_pos = ImNodes::GetNodeGridSpacePos(i);
|
ImVec2 node_pos = ImNodes::GetNodeGridSpacePos(i);
|
||||||
node_resource.m_position[0] = node_pos[0];
|
node_resource.m_position[0] = node_pos[0];
|
||||||
node_resource.m_position[1] = node_pos[1];
|
node_resource.m_position[1] = node_pos[1];
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
|
||||||
ImNodes::EndNode();
|
ImNodes::EndNode();
|
||||||
|
|
||||||
// Ensure flags such as SocketFlagAffectsTime are properly set.
|
// Ensure flags such as SocketFlagAffectsTime are properly set.
|
||||||
|
|
|
@ -240,6 +240,37 @@ struct NodeSocketAccessor<MathAddNode> : public NodeSocketAccessorBase {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// MathFloatToVec3Node
|
||||||
|
//
|
||||||
|
struct MathFloatToVec3Node : public AnimNode {
|
||||||
|
float* i_input0 = nullptr;
|
||||||
|
float* i_input1 = nullptr;
|
||||||
|
float* i_input2 = nullptr;
|
||||||
|
Vec3 o_output = {0.f, 0.f, 0.f};
|
||||||
|
|
||||||
|
void Evaluate() override {
|
||||||
|
assert (i_input0 != nullptr);
|
||||||
|
assert (i_input1 != nullptr);
|
||||||
|
assert (i_input2 != nullptr);
|
||||||
|
|
||||||
|
o_output[0] = *i_input0;
|
||||||
|
o_output[1] = *i_input1;
|
||||||
|
o_output[2] = *i_input2;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct NodeSocketAccessor<MathFloatToVec3Node> : public NodeSocketAccessorBase {
|
||||||
|
NodeSocketAccessor(AnimNode* node_) {
|
||||||
|
MathFloatToVec3Node* node = dynamic_cast<MathFloatToVec3Node*>(node_);
|
||||||
|
RegisterInput("Input0", &node->i_input0);
|
||||||
|
RegisterInput("Input1", &node->i_input1);
|
||||||
|
RegisterInput("Input2", &node->i_input2);
|
||||||
|
RegisterOutput("Output", &node->o_output);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static inline AnimNode* AnimNodeFactory(const std::string& name) {
|
static inline AnimNode* AnimNodeFactory(const std::string& name) {
|
||||||
AnimNode* result;
|
AnimNode* result;
|
||||||
if (name == "Blend2") {
|
if (name == "Blend2") {
|
||||||
|
@ -250,6 +281,10 @@ static inline AnimNode* AnimNodeFactory(const std::string& name) {
|
||||||
result = new AnimSamplerNode;
|
result = new AnimSamplerNode;
|
||||||
} else if (name == "BlendTree") {
|
} else if (name == "BlendTree") {
|
||||||
result = new BlendTreeNode;
|
result = new BlendTreeNode;
|
||||||
|
} else if (name == "MathAddNode") {
|
||||||
|
result = new MathAddNode;
|
||||||
|
} else if (name == "MathFloatToVec3Node") {
|
||||||
|
result = new MathFloatToVec3Node;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != nullptr) {
|
if (result != nullptr) {
|
||||||
|
@ -272,6 +307,10 @@ static inline NodeSocketAccessorBase* AnimNodeAccessorFactory(
|
||||||
return new NodeSocketAccessor<AnimSamplerNode>(node);
|
return new NodeSocketAccessor<AnimSamplerNode>(node);
|
||||||
} else if (node_type_name == "BlendTree") {
|
} else if (node_type_name == "BlendTree") {
|
||||||
return new NodeSocketAccessor<BlendTreeNode>(node);
|
return new NodeSocketAccessor<BlendTreeNode>(node);
|
||||||
|
} else if (node_type_name == "MathAddNode") {
|
||||||
|
return new NodeSocketAccessor<MathAddNode>(node);
|
||||||
|
} else if (node_type_name == "MathFloatToVec3Node") {
|
||||||
|
return new NodeSocketAccessor<MathFloatToVec3Node>(node);
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "Invalid node type name " << node_type_name << "."
|
std::cerr << "Invalid node type name " << node_type_name << "."
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
|
@ -123,6 +123,23 @@ struct AnimGraphResource {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isSocketConnected(
|
||||||
|
const AnimNodeResource& node,
|
||||||
|
const std::string& socket_name) {
|
||||||
|
int node_index = getNodeIndex(node);
|
||||||
|
for (size_t i = 0, n = m_connections.size(); i < n; i++) {
|
||||||
|
const AnimGraphConnectionResource& connection = m_connections[i];
|
||||||
|
if ((connection.source_node_index == node_index
|
||||||
|
&& connection.source_socket_name == socket_name)
|
||||||
|
|| ((connection.target_node_index == node_index)
|
||||||
|
&& connection.target_socket_name == socket_name)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
AnimGraph createInstance() const;
|
AnimGraph createInstance() const;
|
||||||
void createRuntimeNodeInstances(AnimGraph& instance) const;
|
void createRuntimeNodeInstances(AnimGraph& instance) const;
|
||||||
void prepareGraphIOData(AnimGraph& instance) const;
|
void prepareGraphIOData(AnimGraph& instance) const;
|
||||||
|
|
|
@ -2,10 +2,9 @@
|
||||||
// Created by martin on 04.02.22.
|
// Created by martin on 04.02.22.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "AnimGraph/AnimGraphResource.h"
|
|
||||||
#include "AnimGraph/AnimGraph.h"
|
#include "AnimGraph/AnimGraph.h"
|
||||||
#include "AnimGraph/AnimGraphEditor.h"
|
#include "AnimGraph/AnimGraphEditor.h"
|
||||||
|
#include "AnimGraph/AnimGraphResource.h"
|
||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
|
|
||||||
TEST_CASE("BasicGraph", "[AnimGraphResource]") {
|
TEST_CASE("BasicGraph", "[AnimGraphResource]") {
|
||||||
|
@ -81,14 +80,22 @@ TEST_CASE("BasicGraph", "[AnimGraphResource]") {
|
||||||
size_t blend_index = blend2_instance->m_index;
|
size_t blend_index = blend2_instance->m_index;
|
||||||
|
|
||||||
REQUIRE(graph.m_node_input_connections[blend_index].size() == 2);
|
REQUIRE(graph.m_node_input_connections[blend_index].size() == 2);
|
||||||
CHECK(graph.m_node_input_connections[blend_index][0].m_source_node == anim_sampler_walk);
|
CHECK(
|
||||||
CHECK(graph.m_node_input_connections[blend_index][1].m_source_node == anim_sampler_run);
|
graph.m_node_input_connections[blend_index][0].m_source_node
|
||||||
|
== anim_sampler_walk);
|
||||||
|
CHECK(
|
||||||
|
graph.m_node_input_connections[blend_index][1].m_source_node
|
||||||
|
== anim_sampler_run);
|
||||||
|
|
||||||
REQUIRE(graph.m_node_output_connections[anim_sampler_index0].size() == 1);
|
REQUIRE(graph.m_node_output_connections[anim_sampler_index0].size() == 1);
|
||||||
CHECK(graph.m_node_output_connections[anim_sampler_index0][0].m_target_node == blend2_instance);
|
CHECK(
|
||||||
|
graph.m_node_output_connections[anim_sampler_index0][0].m_target_node
|
||||||
|
== blend2_instance);
|
||||||
|
|
||||||
REQUIRE(graph.m_node_output_connections[anim_sampler_index1].size() == 1);
|
REQUIRE(graph.m_node_output_connections[anim_sampler_index1].size() == 1);
|
||||||
CHECK(graph.m_node_output_connections[anim_sampler_index1][0].m_target_node == blend2_instance);
|
CHECK(
|
||||||
|
graph.m_node_output_connections[anim_sampler_index1][0].m_target_node
|
||||||
|
== blend2_instance);
|
||||||
|
|
||||||
// Emulate evaluation
|
// Emulate evaluation
|
||||||
CHECK(graph.m_anim_data_work_buffer.m_available_data.size() == 5);
|
CHECK(graph.m_anim_data_work_buffer.m_available_data.size() == 5);
|
||||||
|
@ -108,16 +115,16 @@ TEST_CASE("BasicGraph", "[AnimGraphResource]") {
|
||||||
CHECK(graph.m_anim_data_work_buffer.m_available_data.size() == 4);
|
CHECK(graph.m_anim_data_work_buffer.m_available_data.size() == 4);
|
||||||
|
|
||||||
graph.prepareNodeEval(0);
|
graph.prepareNodeEval(0);
|
||||||
Socket* graph_output_socket = graph.getOutputSocket("GraphOutput");
|
const Socket* graph_output_socket = graph.getOutputSocket("GraphOutput");
|
||||||
CHECK(blend2_instance->o_output == (*graph_output_socket->m_value.ptr_ptr));
|
CHECK(blend2_instance->o_output == (*graph_output_socket->m_value.ptr_ptr));
|
||||||
AnimData* graph_output = static_cast<AnimData*>(*graph_output_socket->m_value.ptr_ptr);
|
AnimData* graph_output =
|
||||||
|
static_cast<AnimData*>(*graph_output_socket->m_value.ptr_ptr);
|
||||||
graph.finishNodeEval(0);
|
graph.finishNodeEval(0);
|
||||||
CHECK(blend2_instance->o_output == nullptr);
|
CHECK(blend2_instance->o_output == nullptr);
|
||||||
CHECK(graph_output == (*graph_output_socket->m_value.ptr_ptr));
|
CHECK(graph_output == (*graph_output_socket->m_value.ptr_ptr));
|
||||||
CHECK(graph.m_anim_data_work_buffer.m_available_data.size() == 5);
|
CHECK(graph.m_anim_data_work_buffer.m_available_data.size() == 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
TEST_CASE("InputAttributeConversion", "[AnimGraphResource]") {
|
TEST_CASE("InputAttributeConversion", "[AnimGraphResource]") {
|
||||||
int node_id = 3321;
|
int node_id = 3321;
|
||||||
int input_index = 221;
|
int input_index = 221;
|
||||||
|
@ -137,30 +144,62 @@ TEST_CASE("InputAttributeConversion", "[AnimGraphResource]") {
|
||||||
CHECK(output_index == parsed_output_index);
|
CHECK(output_index == parsed_output_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("ResourceSaveLoadGraphInputs", "[AnimGraphResource]") {
|
TEST_CASE("ResourceSaveLoadMathGraphInputs", "[AnimGraphResource]") {
|
||||||
AnimGraphResource graph_resource_origin;
|
AnimGraphResource graph_resource_origin;
|
||||||
|
|
||||||
graph_resource_origin.clear();
|
graph_resource_origin.clear();
|
||||||
graph_resource_origin.m_name = "TestInputOutputGraph";
|
graph_resource_origin.m_name = "TestInputOutputGraph";
|
||||||
|
|
||||||
AnimNodeResource& graph_output_node = graph_resource_origin.m_nodes[0];
|
size_t float_to_vec3_node_index =
|
||||||
graph_output_node.m_socket_accessor->RegisterInput<AnimData>(
|
graph_resource_origin.addNode(AnimNodeResourceFactory("MathFloatToVec3Node"));
|
||||||
"GraphOutput",
|
|
||||||
nullptr);
|
AnimNodeResource& graph_output_node =
|
||||||
|
graph_resource_origin.getGraphOutputNode();
|
||||||
graph_output_node.m_socket_accessor->RegisterInput<float>(
|
graph_output_node.m_socket_accessor->RegisterInput<float>(
|
||||||
"SomeFloatOutput",
|
"GraphFloatOutput",
|
||||||
|
nullptr);
|
||||||
|
graph_output_node.m_socket_accessor->RegisterInput<Vec3>(
|
||||||
|
"GraphVec3Output",
|
||||||
nullptr);
|
nullptr);
|
||||||
|
|
||||||
AnimNodeResource& graph_input_node = graph_resource_origin.m_nodes[1];
|
AnimNodeResource& graph_input_node =
|
||||||
graph_input_node.m_socket_accessor->RegisterOutput<AnimData>(
|
graph_resource_origin.getGraphInputNode();
|
||||||
"GraphAnimInput",
|
|
||||||
nullptr);
|
|
||||||
graph_input_node.m_socket_accessor->RegisterOutput<float>(
|
graph_input_node.m_socket_accessor->RegisterOutput<float>(
|
||||||
"GraphFloatInput",
|
"GraphFloatInput",
|
||||||
nullptr);
|
nullptr);
|
||||||
graph_input_node.m_socket_accessor->RegisterOutput<bool>(
|
|
||||||
"GraphBoolInput",
|
// Prepare graph inputs and outputs
|
||||||
nullptr);
|
AnimNodeResource& float_to_vec3_node =
|
||||||
|
graph_resource_origin.m_nodes[float_to_vec3_node_index];
|
||||||
|
|
||||||
|
REQUIRE(graph_resource_origin.connectSockets(
|
||||||
|
graph_input_node,
|
||||||
|
"GraphFloatInput",
|
||||||
|
graph_output_node,
|
||||||
|
"GraphFloatOutput"));
|
||||||
|
|
||||||
|
REQUIRE(graph_resource_origin.connectSockets(
|
||||||
|
graph_input_node,
|
||||||
|
"GraphFloatInput",
|
||||||
|
float_to_vec3_node,
|
||||||
|
"Input0"));
|
||||||
|
REQUIRE(graph_resource_origin.connectSockets(
|
||||||
|
graph_input_node,
|
||||||
|
"GraphFloatInput",
|
||||||
|
float_to_vec3_node,
|
||||||
|
"Input1"));
|
||||||
|
REQUIRE(graph_resource_origin.connectSockets(
|
||||||
|
graph_input_node,
|
||||||
|
"GraphFloatInput",
|
||||||
|
float_to_vec3_node,
|
||||||
|
"Input2"));
|
||||||
|
|
||||||
|
REQUIRE(graph_resource_origin.connectSockets(
|
||||||
|
float_to_vec3_node,
|
||||||
|
"Output",
|
||||||
|
graph_output_node,
|
||||||
|
"GraphVec3Output"));
|
||||||
|
|
||||||
|
|
||||||
WHEN("Saving and loading graph resource") {
|
WHEN("Saving and loading graph resource") {
|
||||||
const char* filename = "ResourceSaveLoadGraphInputs.json";
|
const char* filename = "ResourceSaveLoadGraphInputs.json";
|
||||||
|
@ -183,43 +222,49 @@ TEST_CASE("ResourceSaveLoadGraphInputs", "[AnimGraphResource]") {
|
||||||
graph_input_node.m_socket_accessor->m_outputs.size()
|
graph_input_node.m_socket_accessor->m_outputs.size()
|
||||||
== graph_loaded_input_node.m_socket_accessor->m_outputs.size());
|
== graph_loaded_input_node.m_socket_accessor->m_outputs.size());
|
||||||
|
|
||||||
REQUIRE(
|
|
||||||
graph_loaded_input_node.m_socket_accessor->FindOutputSocket(
|
|
||||||
"GraphAnimInput")
|
|
||||||
!= nullptr);
|
|
||||||
REQUIRE(
|
REQUIRE(
|
||||||
graph_loaded_input_node.m_socket_accessor->FindOutputSocket(
|
graph_loaded_input_node.m_socket_accessor->FindOutputSocket(
|
||||||
"GraphFloatInput")
|
"GraphFloatInput")
|
||||||
!= nullptr);
|
!= nullptr);
|
||||||
REQUIRE(
|
|
||||||
graph_loaded_input_node.m_socket_accessor->FindOutputSocket(
|
|
||||||
"GraphBoolInput")
|
|
||||||
!= nullptr);
|
|
||||||
|
|
||||||
REQUIRE(
|
REQUIRE(
|
||||||
graph_loaded_output_node.m_socket_accessor->FindInputSocket(
|
graph_loaded_output_node.m_socket_accessor->FindInputSocket(
|
||||||
"GraphOutput")
|
"GraphFloatOutput")
|
||||||
!= nullptr);
|
!= nullptr);
|
||||||
REQUIRE(
|
REQUIRE(
|
||||||
graph_loaded_output_node.m_socket_accessor->FindInputSocket(
|
graph_loaded_output_node.m_socket_accessor->FindInputSocket(
|
||||||
"SomeFloatOutput")
|
"GraphVec3Output")
|
||||||
!= nullptr);
|
!= nullptr);
|
||||||
}
|
|
||||||
|
|
||||||
WHEN("Instantiating an AnimGraph") {
|
WHEN("Instantiating an AnimGraph") {
|
||||||
AnimGraph anim_graph = graph_resource_loaded.createInstance();
|
AnimGraph anim_graph = graph_resource_loaded.createInstance();
|
||||||
|
|
||||||
REQUIRE(
|
REQUIRE(anim_graph.getInputSocket("GraphFloatInput") != nullptr);
|
||||||
anim_graph.getOutput("GraphOutput") == anim_graph.m_output_buffer);
|
REQUIRE(anim_graph.getInputPtr("GraphFloatInput") == anim_graph.m_input_buffer);
|
||||||
REQUIRE(
|
|
||||||
anim_graph.getOutput("SomeFloatOutput")
|
|
||||||
== anim_graph.m_output_buffer + sizeof(AnimData));
|
|
||||||
|
|
||||||
REQUIRE(anim_graph.getInput("GraphAnimInput") == nullptr);
|
float* graph_float_input = nullptr;
|
||||||
REQUIRE(anim_graph.getInput("GraphFloatInput") == nullptr);
|
graph_float_input = static_cast<float*>(anim_graph.getInputPtr("GraphFloatInput"));
|
||||||
REQUIRE(anim_graph.getInput("GraphBoolInput") == nullptr);
|
|
||||||
|
*graph_float_input = 123.456f;
|
||||||
|
|
||||||
|
anim_graph.updateTime(0.f);
|
||||||
|
anim_graph.evaluate();
|
||||||
|
|
||||||
|
anim_graph.evalOutputNode();
|
||||||
|
|
||||||
|
Socket* float_output_socket = anim_graph.getOutputSocket("GraphFloatOutput");
|
||||||
|
Socket* vec3_output_socket = anim_graph.getOutputSocket("GraphVec3Output");
|
||||||
|
Vec3& vec3_output = *static_cast<Vec3*>(vec3_output_socket->m_value.ptr);
|
||||||
|
|
||||||
|
CHECK(vec3_output[0] == *graph_float_input);
|
||||||
|
CHECK(vec3_output[1] == *graph_float_input);
|
||||||
|
CHECK(vec3_output[2] == *graph_float_input);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
WHEN("Connecting input to output and instantiating the graph") {
|
WHEN("Connecting input to output and instantiating the graph") {
|
||||||
AnimNodeResource& graph_output_node = graph_resource_origin.m_nodes[0];
|
AnimNodeResource& graph_output_node = graph_resource_origin.m_nodes[0];
|
||||||
|
|
Loading…
Reference in New Issue