Added LockTranslationNode.

AnimGraphEditor
Martin Felis 2023-04-02 21:40:49 +02:00
parent 7c8b44247b
commit 0a45497de9
5 changed files with 113 additions and 2 deletions

View File

@ -133,6 +133,7 @@ enum class SocketType {
SocketTypeUndefined = 0,
SocketTypeBool,
SocketTypeAnimation,
SocketTypeInt,
SocketTypeFloat,
SocketTypeVec3,
SocketTypeQuat,
@ -143,7 +144,7 @@ enum class SocketType {
constexpr size_t cSocketStringValueMaxLength = 256;
static const char* SocketTypeNames[] =
{"", "Bool", "Animation", "Float", "Vec3", "Quat", "String"};
{"", "Bool", "Animation", "Int", "Float", "Vec3", "Quat", "String"};
enum SocketFlags { SocketFlagNone = 0, SocketFlagAffectsTime = 1 };
@ -152,6 +153,7 @@ struct Socket {
SocketType m_type = SocketType::SocketTypeUndefined;
union SocketValue {
bool flag;
int int_value;
float float_value;
Vec3 vec3;
Quat quat;
@ -172,6 +174,10 @@ struct Socket {
m_value.flag = value;
}
if constexpr (std::is_same<T, int>::value) {
m_value.int_value = value;
}
if constexpr (std::is_same<T, float>::value) {
m_value.float_value = value;
}
@ -195,6 +201,10 @@ struct Socket {
return m_value.flag;
}
if constexpr (std::is_same<T, int>::value) {
return m_value.int_value;
}
if constexpr (std::is_same<T, float>::value) {
return m_value.float_value;
}
@ -225,6 +235,10 @@ SocketType GetSocketType() {
return SocketType::SocketTypeAnimation;
}
if constexpr (std::is_same<T, int>::value) {
return SocketType::SocketTypeInt;
}
if constexpr (std::is_same<T, float>::value) {
return SocketType::SocketTypeFloat;
}

View File

@ -18,6 +18,8 @@ ImNodesPinShape sGetSocketShapeFromSocketType(const SocketType& socket_type) {
switch (socket_type) {
case SocketType::SocketTypeAnimation:
return ImNodesPinShape_QuadFilled;
case SocketType::SocketTypeInt:
return ImNodesPinShape_CircleFilled;
case SocketType::SocketTypeFloat:
return ImNodesPinShape_CircleFilled;
case SocketType::SocketTypeVec3:
@ -165,7 +167,12 @@ void AnimGraphEditorRenderSidebar(
int num_properties = node_resource.m_socket_accessor->m_properties.size();
for (int i = 0; i < num_properties; i++) {
Socket& property = node_resource.m_socket_accessor->m_properties[i];
if (property.m_type == SocketType::SocketTypeFloat) {
if (property.m_type == SocketType::SocketTypeInt) {
ImGui::InputInt(
property.m_name.c_str(),
reinterpret_cast<int*>(&property.m_value.int_value),
1);
} else if (property.m_type == SocketType::SocketTypeFloat) {
ImGui::SliderFloat(
property.m_name.c_str(),
reinterpret_cast<float*>(&property.m_value.float_value),
@ -303,6 +310,10 @@ void AnimGraphEditorUpdate() {
node_type_name = "SpeedScale";
}
if (ImGui::MenuItem("LockTranslationNode")) {
node_type_name = "LockTranslationNode";
}
if (ImGui::MenuItem("MathAddNode")) {
node_type_name = "MathAddNode";
}
@ -376,6 +387,17 @@ void AnimGraphEditorUpdate() {
ImGui::PopItemWidth();
}
if (!socket_connected && (socket.m_type == SocketType::SocketTypeInt)) {
ImGui::SameLine();
int socket_value = socket.m_value.int_value;
ImGui::PushItemWidth(
130.0f - ImGui::CalcTextSize(socket.m_name.c_str()).x);
if (ImGui::InputInt("##hidelabel", &socket_value, 1)) {
socket.SetValue(socket_value);
}
ImGui::PopItemWidth();
}
ImNodes::PushAttributeFlag(
ImNodesAttributeFlags_EnableLinkDetachWithDragClick);
ImNodes::EndInputAttribute();

View File

@ -89,3 +89,33 @@ void AnimSamplerNode::Evaluate(AnimGraphContext& context) {
ozz::log::Err() << "Error sampling animation." << std::endl;
}
}
void LockTranslationNode::Evaluate(AnimGraphContext& context) {
o_output->m_local_matrices = i_input->m_local_matrices;
ozz::math::SoaFloat3 translation =
o_output->m_local_matrices[m_locked_bone_index].translation;
float x[4];
float y[4];
float z[4];
_mm_store_ps(x, translation.x);
_mm_store_ps(y, translation.y);
_mm_store_ps(z, translation.z);
if (m_lock_x) {
x[0] = 0.f;
}
if (m_lock_y) {
y[0] = 0.f;
}
if (m_lock_z) {
z[0] = 0.f;
}
translation.x = _mm_load_ps(x);
translation.y = _mm_load_ps(y);
translation.z = _mm_load_ps(z);
o_output->m_local_matrices[m_locked_bone_index].translation = translation;
}

View File

@ -211,6 +211,34 @@ struct NodeDescriptor<AnimSamplerNode> : public NodeDescriptorBase {
}
};
//
// LockTranslationNode
//
struct LockTranslationNode : public AnimNode {
AnimData* i_input = nullptr;
AnimData* o_output = nullptr;
int m_locked_bone_index;
bool m_lock_x;
bool m_lock_y;
bool m_lock_z;
virtual void Evaluate(AnimGraphContext& context) override;
};
template <>
struct NodeDescriptor<LockTranslationNode> : public NodeDescriptorBase {
NodeDescriptor(LockTranslationNode* node) {
RegisterInput("Input", &node->i_input);
RegisterOutput("Output", &node->o_output);
RegisterProperty("BoneIndex", &node->m_locked_bone_index);
RegisterProperty("LockAxisX", &node->m_lock_x);
RegisterProperty("LockAxisY", &node->m_lock_y);
RegisterProperty("LockAxisZ", &node->m_lock_z);
}
};
//
// ConstScalarNode
//
@ -296,6 +324,8 @@ static inline AnimNode* AnimNodeFactory(const std::string& name) {
result = new SpeedScaleNode;
} else if (name == "AnimSampler") {
result = new AnimSamplerNode;
} else if (name == "LockTranslationNode") {
result = new LockTranslationNode;
} else if (name == "BlendTree") {
result = new BlendTreeNode;
} else if (name == "MathAddNode") {
@ -324,6 +354,8 @@ static inline NodeDescriptorBase* AnimNodeDescriptorFactory(
return CreateNodeDescriptor<SpeedScaleNode>(node);
} else if (node_type_name == "AnimSampler") {
return CreateNodeDescriptor<AnimSamplerNode>(node);
} else if (node_type_name == "LockTranslationNode") {
return CreateNodeDescriptor<LockTranslationNode>(node);
} else if (node_type_name == "BlendTree") {
return CreateNodeDescriptor<BlendTreeNode>(node);
} else if (node_type_name == "MathAddNode") {

View File

@ -35,6 +35,8 @@ json sSocketToJson(const Socket& socket) {
if (socket.m_type == SocketType::SocketTypeBool) {
result["value"] = socket.m_value.flag;
} else if (socket.m_type == SocketType::SocketTypeAnimation) {
} else if (socket.m_type == SocketType::SocketTypeInt) {
result["value"] = socket.m_value.int_value;
} else if (socket.m_type == SocketType::SocketTypeFloat) {
result["value"] = socket.m_value.float_value;
} else if (socket.m_type == SocketType::SocketTypeVec3) {
@ -72,6 +74,12 @@ Socket sJsonToSocket(const json& json_data) {
} else if (type_string == "Animation") {
result.m_type = SocketType::SocketTypeAnimation;
result.m_type_size = sizeof(AnimData);
} else if (type_string == "Int") {
result.m_type = SocketType::SocketTypeInt;
result.m_type_size = sizeof(int);
if (have_value) {
result.m_value.int_value = json_data["value"];
}
} else if (type_string == "Float") {
result.m_type = SocketType::SocketTypeFloat;
result.m_type_size = sizeof(float);
@ -572,6 +580,11 @@ void AnimGraphResource::setRuntimeNodeProperties(AnimGraph& instance) const {
name.c_str(),
property.m_value.flag);
break;
case SocketType::SocketTypeInt:
node_instance_accessor->SetProperty(
name.c_str(),
property.m_value.int_value);
break;
case SocketType::SocketTypeFloat:
node_instance_accessor->SetProperty(
name.c_str(),