209 lines
5.1 KiB
C
209 lines
5.1 KiB
C
![]() |
//
|
||
|
// Created by martin on 25.03.22.
|
||
|
//
|
||
|
|
||
|
#ifndef ANIMTESTBED_ANIMGRAPHNODES_H
|
||
|
#define ANIMTESTBED_ANIMGRAPHNODES_H
|
||
|
|
||
|
#include <vector>
|
||
|
|
||
|
#include "AnimGraphData.h"
|
||
|
#include "SyncTrack.h"
|
||
|
|
||
|
struct AnimNode;
|
||
|
|
||
|
struct NodeInput {
|
||
|
AnimNode* m_node;
|
||
|
SocketType m_type = SocketType::SocketTypeUndefined;
|
||
|
std::string m_input_name;
|
||
|
};
|
||
|
|
||
|
enum class AnimNodeEvalState {
|
||
|
Undefined,
|
||
|
Deactivated,
|
||
|
Activated,
|
||
|
SyncTrackUpdated,
|
||
|
TimeUpdated,
|
||
|
Evaluated
|
||
|
};
|
||
|
|
||
|
struct AnimNode {
|
||
|
std::string m_name;
|
||
|
std::string m_node_type_name;
|
||
|
float m_time_now = 0.f;
|
||
|
float m_time_last = 0.f;
|
||
|
size_t m_index = -1;
|
||
|
AnimNodeEvalState m_state = AnimNodeEvalState::Undefined;
|
||
|
SyncTrack m_sync_track;
|
||
|
|
||
|
virtual ~AnimNode(){};
|
||
|
|
||
|
virtual void MarkActiveInputs(const std::vector<NodeInput>& inputs) {
|
||
|
for (size_t i = 0, n = inputs.size(); i < n; i++) {
|
||
|
AnimNode* input_node = inputs[i].m_node;
|
||
|
if (input_node != nullptr) {
|
||
|
input_node->m_state = AnimNodeEvalState::Activated;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
virtual void CalcSyncTrack(const std::vector<NodeInput>& inputs) {
|
||
|
for (size_t i = 0, n = inputs.size(); i < n; i++) {
|
||
|
AnimNode* input_node = inputs[i].m_node;
|
||
|
if (input_node != nullptr
|
||
|
&& inputs[i].m_type == SocketType::SocketTypeAnimation
|
||
|
&& input_node->m_state != AnimNodeEvalState::Deactivated) {
|
||
|
m_sync_track = input_node->m_sync_track;
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
virtual void UpdateTime(float time_last, float time_now) {
|
||
|
m_time_last = time_last;
|
||
|
m_time_now = time_now;
|
||
|
m_state = AnimNodeEvalState::TimeUpdated;
|
||
|
}
|
||
|
|
||
|
virtual void Evaluate(){};
|
||
|
};
|
||
|
|
||
|
|
||
|
//
|
||
|
// BlendTreeNode
|
||
|
//
|
||
|
struct BlendTreeNode : public AnimNode {};
|
||
|
|
||
|
template <>
|
||
|
struct NodeSocketAccessor<BlendTreeNode> : public NodeSocketAccessorBase {
|
||
|
NodeSocketAccessor(AnimNode* node_) {}
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// Blend2Node
|
||
|
//
|
||
|
struct Blend2Node : public AnimNode {
|
||
|
AnimData m_input0;
|
||
|
AnimData m_input1;
|
||
|
AnimData* m_output = nullptr;
|
||
|
float m_blend_weight = 0.f;
|
||
|
bool m_sync_blend = false;
|
||
|
|
||
|
virtual void MarkActiveInputs(const std::vector<NodeInput>& inputs) override {
|
||
|
for (size_t i = 0, n = inputs.size(); i < n; i++) {
|
||
|
AnimNode* input_node = inputs[i].m_node;
|
||
|
if (input_node == nullptr) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (inputs[i].m_input_name == "Input0" && m_blend_weight < 0.999) {
|
||
|
input_node->m_state = AnimNodeEvalState::Activated;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (inputs[i].m_input_name == "Input1" && m_blend_weight > 0.001) {
|
||
|
input_node->m_state = AnimNodeEvalState::Activated;
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
virtual void UpdateTime(float dt, std::vector<NodeInput>& inputs) {
|
||
|
if (!m_sync_blend) {
|
||
|
m_time_now = m_time_now + dt;
|
||
|
}
|
||
|
|
||
|
for (size_t i = 0, n = inputs.size(); i < n; i++) {
|
||
|
AnimNode* input_node = inputs[i].m_node;
|
||
|
if (input_node == nullptr) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (input_node->m_state != AnimNodeEvalState::Deactivated) {
|
||
|
if (!m_sync_blend) {
|
||
|
input_node->m_time_now = m_time_now;
|
||
|
}
|
||
|
input_node->m_state = AnimNodeEvalState::TimeUpdated;
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template <>
|
||
|
struct NodeSocketAccessor<Blend2Node> : public NodeSocketAccessorBase {
|
||
|
NodeSocketAccessor(AnimNode* node_) {
|
||
|
Blend2Node* node = dynamic_cast<Blend2Node*>(node_);
|
||
|
RegisterInput("Input0", &node->m_input0);
|
||
|
RegisterInput("Input1", &node->m_input1);
|
||
|
RegisterInput(
|
||
|
"Weight",
|
||
|
&node->m_blend_weight,
|
||
|
SocketFlags::SocketFlagAffectsTime);
|
||
|
|
||
|
RegisterOutput("Output", &node->m_output);
|
||
|
|
||
|
RegisterProperty("Sync", &node->m_sync_blend);
|
||
|
}
|
||
|
|
||
|
virtual void UpdateFlags() override {
|
||
|
Socket* weight_input_socket = FindSocket(m_inputs, "Weight");
|
||
|
assert(weight_input_socket != nullptr);
|
||
|
|
||
|
if (GetProperty<bool>("Sync", false) == true) {
|
||
|
weight_input_socket->m_flags = SocketFlags::SocketFlagAffectsTime;
|
||
|
} else {
|
||
|
weight_input_socket->m_flags = 0;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// SpeedScaleNode
|
||
|
//
|
||
|
struct SpeedScaleNode : public AnimNode {
|
||
|
AnimData m_input;
|
||
|
AnimData* m_output = nullptr;
|
||
|
float m_speed_scale = 0.f;
|
||
|
|
||
|
virtual void UpdateTime(float time_last, float time_now) {
|
||
|
m_time_last = time_last;
|
||
|
m_time_now = time_last + (time_now - time_last) * m_speed_scale;
|
||
|
m_state = AnimNodeEvalState::TimeUpdated;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template <>
|
||
|
struct NodeSocketAccessor<SpeedScaleNode> : public NodeSocketAccessorBase {
|
||
|
NodeSocketAccessor(AnimNode* node_) {
|
||
|
SpeedScaleNode* node = dynamic_cast<SpeedScaleNode*>(node_);
|
||
|
RegisterInput(
|
||
|
"SpeedScale",
|
||
|
&node->m_speed_scale,
|
||
|
SocketFlags::SocketFlagAffectsTime);
|
||
|
RegisterInput("Input", &node->m_input);
|
||
|
|
||
|
RegisterOutput("Output", &node->m_output);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// AnimSamplerNode
|
||
|
//
|
||
|
struct AnimSamplerNode : public AnimNode {
|
||
|
AnimData* m_output = nullptr;
|
||
|
std::string m_filename;
|
||
|
};
|
||
|
|
||
|
template <>
|
||
|
struct NodeSocketAccessor<AnimSamplerNode> : public NodeSocketAccessorBase {
|
||
|
NodeSocketAccessor(AnimNode* node_) {
|
||
|
AnimSamplerNode* node = dynamic_cast<AnimSamplerNode*>(node_);
|
||
|
RegisterOutput("Output", &node->m_output);
|
||
|
|
||
|
RegisterProperty("Filename", &node->m_filename);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
#endif //ANIMTESTBED_ANIMGRAPHNODES_H
|