Extremely basic blend tree editing.
parent
3fb2995b02
commit
5e34aaf3db
|
@ -124,6 +124,7 @@ set(ozz_offline_test_objs
|
||||||
|
|
||||||
target_sources(runtests PRIVATE
|
target_sources(runtests PRIVATE
|
||||||
tests/AnimGraphResourceTests.cc
|
tests/AnimGraphResourceTests.cc
|
||||||
|
tests/AnimGraphEditorTests.cc
|
||||||
# tests/AnimGraphEvalTests.cc
|
# tests/AnimGraphEvalTests.cc
|
||||||
tests/NodeDescriptorTests.cc
|
tests/NodeDescriptorTests.cc
|
||||||
tests/SyncTrackTests.cc
|
tests/SyncTrackTests.cc
|
||||||
|
|
|
@ -37,14 +37,6 @@ ImNodesPinShape sGetSocketShapeFromSocketType(const SocketType& socket_type) {
|
||||||
return ImNodesPinShape_Quad;
|
return ImNodesPinShape_Quad;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetNodeInputSocketId(int node_index, int input_socket_index) {
|
|
||||||
return node_index * 1000 + input_socket_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
int GetNodeOutputSocketId(int node_index, int output_socket_index) {
|
|
||||||
return node_index * 1000 + 100 + output_socket_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NodeSocketEditor(Socket& socket) {
|
void NodeSocketEditor(Socket& socket) {
|
||||||
int mode_current = static_cast<int>(socket.m_type);
|
int mode_current = static_cast<int>(socket.m_type);
|
||||||
ImGui::InputText("Name", &socket.m_name);
|
ImGui::InputText("Name", &socket.m_name);
|
||||||
|
@ -61,20 +53,18 @@ void RemoveBlendTreeConnectionsForSocket(
|
||||||
BlendTreeResource& blend_tree_resource,
|
BlendTreeResource& blend_tree_resource,
|
||||||
AnimNodeResource* node_resource,
|
AnimNodeResource* node_resource,
|
||||||
Socket& socket) {
|
Socket& socket) {
|
||||||
std::vector<BlendTreeConnectionResource>::const_iterator iter =
|
const BlendTreeConnectionResource* connection =
|
||||||
blend_tree_resource.GetConnections().begin();
|
blend_tree_resource.FindConnectionForSocket(node_resource, socket.m_name);
|
||||||
|
while (connection != nullptr) {
|
||||||
|
blend_tree_resource.DisconnectSockets(
|
||||||
|
blend_tree_resource.GetNode(connection->source_node_index),
|
||||||
|
connection->source_socket_name,
|
||||||
|
blend_tree_resource.GetNode(connection->target_node_index),
|
||||||
|
connection->target_socket_name);
|
||||||
|
|
||||||
while (iter != blend_tree_resource.GetConnections().end()) {
|
connection = blend_tree_resource.FindConnectionForSocket(
|
||||||
// TODO adjust for refactor
|
node_resource,
|
||||||
assert(false);
|
socket.m_name);
|
||||||
|
|
||||||
// AnimGraphConnectionResource& connection = *iter;
|
|
||||||
// if (connection.m_source_node == &node_resource
|
|
||||||
// && connection.m_source_socket == &socket) {
|
|
||||||
// iter = sGraphGresource.m_connections.erase(iter);
|
|
||||||
// } else {
|
|
||||||
// iter++;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,6 +250,12 @@ void AnimGraphEditorRenderSidebar(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AnimGraphEditorClear() {
|
||||||
|
sGraphGresource.Clear();
|
||||||
|
sGraphGresource.m_blend_tree_resource.InitGraphConnectors();
|
||||||
|
sGraphGresource.m_graph_type_name = "BlendTree";
|
||||||
|
}
|
||||||
|
|
||||||
void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
|
void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
|
||||||
ImGui::BeginMenuBar();
|
ImGui::BeginMenuBar();
|
||||||
if (ImGui::Button("Save")) {
|
if (ImGui::Button("Save")) {
|
||||||
|
@ -268,16 +264,9 @@ void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
|
||||||
if (ImGui::Button("Load")) {
|
if (ImGui::Button("Load")) {
|
||||||
sGraphGresource.LoadFromFile("editor_graph.json");
|
sGraphGresource.LoadFromFile("editor_graph.json");
|
||||||
sGraphLoadedThisFrame = true;
|
sGraphLoadedThisFrame = true;
|
||||||
|
|
||||||
// for (size_t i = 0, n = sGraphGresource.m_nodes.size(); i < n; i++) {
|
|
||||||
// const AnimNodeResource& node_resource = sGraphGresource.m_nodes[i];
|
|
||||||
// ImNodes::SetNodeGridSpacePos(
|
|
||||||
// i,
|
|
||||||
// ImVec2(node_resource.m_position[0], node_resource.m_position[1]));
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
if (ImGui::Button("Clear")) {
|
if (ImGui::Button("Clear")) {
|
||||||
sGraphGresource.Clear();
|
AnimGraphEditorClear();
|
||||||
}
|
}
|
||||||
char graph_name_buffer[256];
|
char graph_name_buffer[256];
|
||||||
memset(graph_name_buffer, 0, sizeof(graph_name_buffer));
|
memset(graph_name_buffer, 0, sizeof(graph_name_buffer));
|
||||||
|
@ -323,7 +312,9 @@ void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
|
||||||
for (size_t j = 0, ni = node_inputs.size(); j < ni; j++) {
|
for (size_t j = 0, ni = node_inputs.size(); j < ni; j++) {
|
||||||
Socket& socket = node_inputs[j];
|
Socket& socket = node_inputs[j];
|
||||||
ax::NodeEditor::BeginPin(
|
ax::NodeEditor::BeginPin(
|
||||||
GetNodeInputSocketId(static_cast<int>(node_id), static_cast<int>(j)),
|
NodeIndexAndSocketIndexToInputPinId(
|
||||||
|
static_cast<int>(node_id),
|
||||||
|
static_cast<int>(j)),
|
||||||
ax::NodeEditor::PinKind::Input);
|
ax::NodeEditor::PinKind::Input);
|
||||||
ImGui::Text("%s", socket.m_name.c_str());
|
ImGui::Text("%s", socket.m_name.c_str());
|
||||||
ax::NodeEditor::EndPin();
|
ax::NodeEditor::EndPin();
|
||||||
|
@ -335,13 +326,19 @@ void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
|
||||||
for (size_t j = 0, ni = node_outputs.size(); j < ni; j++) {
|
for (size_t j = 0, ni = node_outputs.size(); j < ni; j++) {
|
||||||
Socket& socket = node_outputs[j];
|
Socket& socket = node_outputs[j];
|
||||||
ax::NodeEditor::BeginPin(
|
ax::NodeEditor::BeginPin(
|
||||||
GetNodeOutputSocketId(static_cast<int>(node_id), static_cast<int>(j)),
|
NodeIndexAndSocketIndexToOutputPinId(
|
||||||
|
static_cast<int>(node_id),
|
||||||
|
static_cast<int>(j)),
|
||||||
ax::NodeEditor::PinKind::Output);
|
ax::NodeEditor::PinKind::Output);
|
||||||
ImGui::Text("%s", socket.m_name.c_str());
|
ImGui::Text("%s", socket.m_name.c_str());
|
||||||
ax::NodeEditor::EndPin();
|
ax::NodeEditor::EndPin();
|
||||||
}
|
}
|
||||||
|
|
||||||
ax::NodeEditor::EndNode();
|
ax::NodeEditor::EndNode();
|
||||||
|
|
||||||
|
ImVec2 node_position = ax::NodeEditor::GetNodePosition(node_id);
|
||||||
|
node_resource->m_position[0] = node_position.x;
|
||||||
|
node_resource->m_position[1] = node_position.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
int link_id = 0;
|
int link_id = 0;
|
||||||
|
@ -366,14 +363,14 @@ void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
|
||||||
target_node_resource->m_socket_accessor->GetInputIndex(
|
target_node_resource->m_socket_accessor->GetInputIndex(
|
||||||
connection_resource->target_socket_name.c_str());
|
connection_resource->target_socket_name.c_str());
|
||||||
|
|
||||||
int source_socket_id = GetNodeOutputSocketId(
|
int source_socket_pin_id = NodeIndexAndSocketIndexToOutputPinId(
|
||||||
static_cast<int>(connection_resource->source_node_index),
|
static_cast<int>(connection_resource->source_node_index),
|
||||||
source_socket_index);
|
source_socket_index);
|
||||||
int target_socket_id = GetNodeInputSocketId(
|
int target_socket_pin_id = NodeIndexAndSocketIndexToInputPinId(
|
||||||
static_cast<int>(connection_resource->target_node_index),
|
static_cast<int>(connection_resource->target_node_index),
|
||||||
target_socket_index);
|
target_socket_index);
|
||||||
|
|
||||||
ax::NodeEditor::Link(link_id++, source_socket_id, target_socket_id);
|
ax::NodeEditor::Link(link_id++, source_socket_pin_id, target_socket_pin_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -385,6 +382,56 @@ void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
|
||||||
if (ax::NodeEditor::QueryNewLink(&input_pin_id, &output_pin_id)) {
|
if (ax::NodeEditor::QueryNewLink(&input_pin_id, &output_pin_id)) {
|
||||||
if (input_pin_id && output_pin_id) {
|
if (input_pin_id && output_pin_id) {
|
||||||
if (ax::NodeEditor::AcceptNewItem()) {
|
if (ax::NodeEditor::AcceptNewItem()) {
|
||||||
|
int source_node_index;
|
||||||
|
int source_node_socket_index;
|
||||||
|
|
||||||
|
OutputPinIdToNodeIndexAndSocketIndex(
|
||||||
|
input_pin_id.Get(),
|
||||||
|
&source_node_index,
|
||||||
|
&source_node_socket_index);
|
||||||
|
|
||||||
|
const AnimNodeResource* source_node =
|
||||||
|
sGraphGresource.m_blend_tree_resource.GetNode(source_node_index);
|
||||||
|
if (source_node->m_socket_accessor->m_outputs.size()
|
||||||
|
< source_node_socket_index) {
|
||||||
|
source_node_socket_index = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int target_node_index;
|
||||||
|
int target_node_socket_index;
|
||||||
|
|
||||||
|
InputPinIdToNodeIndexAndSocketIndex(
|
||||||
|
output_pin_id.Get(),
|
||||||
|
&target_node_index,
|
||||||
|
&target_node_socket_index);
|
||||||
|
|
||||||
|
const AnimNodeResource* target_node =
|
||||||
|
sGraphGresource.m_blend_tree_resource.GetNode(target_node_index);
|
||||||
|
if (target_node->m_socket_accessor->m_inputs.size()
|
||||||
|
< target_node_socket_index) {
|
||||||
|
target_node_socket_index = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (source_node_socket_index == -1
|
||||||
|
|| target_node_socket_index == -1) {
|
||||||
|
ax::NodeEditor::RejectNewItem();
|
||||||
|
} else {
|
||||||
|
const std::string& source_socket_name =
|
||||||
|
source_node->m_socket_accessor
|
||||||
|
->m_outputs[source_node_socket_index]
|
||||||
|
.m_name;
|
||||||
|
|
||||||
|
const std::string& target_socket_name =
|
||||||
|
target_node->m_socket_accessor
|
||||||
|
->m_inputs[target_node_socket_index]
|
||||||
|
.m_name;
|
||||||
|
|
||||||
|
sGraphGresource.m_blend_tree_resource.ConnectSockets(
|
||||||
|
source_node,
|
||||||
|
source_socket_name,
|
||||||
|
target_node,
|
||||||
|
target_socket_name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -392,6 +439,64 @@ void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
|
||||||
ax::NodeEditor::EndCreate();
|
ax::NodeEditor::EndCreate();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Popup menu
|
||||||
|
{
|
||||||
|
const bool open_popup = ImGui::IsMouseReleased(ImGuiMouseButton_Right);
|
||||||
|
|
||||||
|
ImVec2 popup_mouse_position = ImGui::GetMousePos();
|
||||||
|
|
||||||
|
ax::NodeEditor::Suspend();
|
||||||
|
if (open_popup) {
|
||||||
|
ImGui::OpenPopup("add node");
|
||||||
|
}
|
||||||
|
ax::NodeEditor::Resume();
|
||||||
|
|
||||||
|
ax::NodeEditor::Suspend();
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8.f, 8.f));
|
||||||
|
if (ImGui::BeginPopup("add node")) {
|
||||||
|
std::string node_type_name = "";
|
||||||
|
if (ImGui::MenuItem("AnimSampler")) {
|
||||||
|
node_type_name = "AnimSampler";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::MenuItem("Blend2")) {
|
||||||
|
node_type_name = "Blend2";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::MenuItem("SpeedScale")) {
|
||||||
|
node_type_name = "SpeedScale";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::MenuItem("LockTranslationNode")) {
|
||||||
|
node_type_name = "LockTranslationNode";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::MenuItem("MathAddNode")) {
|
||||||
|
node_type_name = "MathAddNode";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::MenuItem("MathFloatToVec3Node")) {
|
||||||
|
node_type_name = "MathFloatToVec3Node";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::MenuItem("ConstScalarNode")) {
|
||||||
|
node_type_name = "ConstScalarNode";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node_type_name.empty()) {
|
||||||
|
AnimNodeResource* node_resource =
|
||||||
|
AnimNodeResourceFactory(node_type_name);
|
||||||
|
size_t node_id = sGraphGresource.m_blend_tree_resource.GetNumNodes();
|
||||||
|
ax::NodeEditor::SetNodePosition(node_id, popup_mouse_position);
|
||||||
|
sGraphGresource.m_blend_tree_resource.AddNode(node_resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
ImGui::PopStyleVar();
|
||||||
|
ax::NodeEditor::Resume();
|
||||||
|
}
|
||||||
|
|
||||||
ax::NodeEditor::End();
|
ax::NodeEditor::End();
|
||||||
|
|
||||||
sGraphLoadedThisFrame = false;
|
sGraphLoadedThisFrame = false;
|
||||||
|
|
|
@ -33,10 +33,40 @@ SplitOutputAttributeId(int attribute_id, int* node_id, int* output_index) {
|
||||||
*output_index = (attribute_id >> 23) - 1;
|
*output_index = (attribute_id >> 23) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline int NodeIndexAndSocketIndexToInputPinId(
|
||||||
|
int node_index,
|
||||||
|
int input_socket_index) {
|
||||||
|
return node_index * 1000 + input_socket_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int NodeIndexAndSocketIndexToOutputPinId(
|
||||||
|
int node_index,
|
||||||
|
int output_socket_index) {
|
||||||
|
return node_index * 1000 + 500 + output_socket_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void InputPinIdToNodeIndexAndSocketIndex(
|
||||||
|
unsigned long input_pin_id,
|
||||||
|
int* node_index,
|
||||||
|
int* socket_index) {
|
||||||
|
*socket_index = input_pin_id % 1000;
|
||||||
|
*node_index = (input_pin_id - *socket_index) / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void OutputPinIdToNodeIndexAndSocketIndex(
|
||||||
|
unsigned long output_pin_id,
|
||||||
|
int* node_index,
|
||||||
|
int* socket_index) {
|
||||||
|
*socket_index = ((output_pin_id - 500) % 1000);
|
||||||
|
*node_index = (output_pin_id - *socket_index) / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
void SyncTrackEditor(SyncTrack* sync_track);
|
void SyncTrackEditor(SyncTrack* sync_track);
|
||||||
|
|
||||||
void SkinnedMeshWidget(SkinnedMesh* skinned_mesh);
|
void SkinnedMeshWidget(SkinnedMesh* skinned_mesh);
|
||||||
|
|
||||||
|
void AnimGraphEditorClear();
|
||||||
|
|
||||||
void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context);
|
void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context);
|
||||||
|
|
||||||
void LegacyAnimGraphEditorUpdate();
|
void LegacyAnimGraphEditorUpdate();
|
||||||
|
|
|
@ -323,12 +323,14 @@ static bool sAnimGraphResourceBlendTreeFromJson(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Graph outputs
|
// Graph outputs
|
||||||
|
if (json_data["nodes"][0].contains("inputs")) {
|
||||||
const json& graph_outputs = json_data["nodes"][0]["inputs"];
|
const json& graph_outputs = json_data["nodes"][0]["inputs"];
|
||||||
for (const auto& graph_output : graph_outputs) {
|
for (const auto& graph_output : graph_outputs) {
|
||||||
AnimNodeResource* graph_node = blend_tree_resource.GetNode(0);
|
AnimNodeResource* graph_node = blend_tree_resource.GetNode(0);
|
||||||
graph_node->m_socket_accessor->m_inputs.push_back(
|
graph_node->m_socket_accessor->m_inputs.push_back(
|
||||||
sJsonToSocket(graph_output));
|
sJsonToSocket(graph_output));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Graph inputs (optional)
|
// Graph inputs (optional)
|
||||||
if (json_data["nodes"][1].contains("outputs")) {
|
if (json_data["nodes"][1].contains("outputs")) {
|
||||||
|
@ -573,6 +575,33 @@ bool BlendTreeResource::IsConnectionValid(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const BlendTreeConnectionResource* BlendTreeResource::FindConnectionForSocket(
|
||||||
|
const AnimNodeResource* node,
|
||||||
|
const std::string& socket_name) const {
|
||||||
|
int node_index = GetNodeIndex(node);
|
||||||
|
|
||||||
|
std::vector<BlendTreeConnectionResource>::const_iterator connection_iter =
|
||||||
|
std::find_if(
|
||||||
|
m_connections.begin(),
|
||||||
|
m_connections.end(),
|
||||||
|
[node_index,
|
||||||
|
socket_name](const BlendTreeConnectionResource& connection) {
|
||||||
|
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;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (connection_iter != m_connections.end()) {
|
||||||
|
return &*connection_iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void BlendTreeResource::UpdateTreeTopologyInfo() {
|
void BlendTreeResource::UpdateTreeTopologyInfo() {
|
||||||
// TODO: Updating eval order and subtrees may get slow with many nodes. An
|
// TODO: Updating eval order and subtrees may get slow with many nodes. An
|
||||||
// iterative approach would scale better. But let's leave that optimization
|
// iterative approach would scale better. But let's leave that optimization
|
||||||
|
@ -640,6 +669,8 @@ void BlendTreeResource::UpdateNodeSubtrees() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AnimGraphResource::LoadFromFile(const char* filename) {
|
bool AnimGraphResource::LoadFromFile(const char* filename) {
|
||||||
|
Clear();
|
||||||
|
|
||||||
std::ifstream input_file;
|
std::ifstream input_file;
|
||||||
input_file.open(filename);
|
input_file.open(filename);
|
||||||
std::stringstream buffer;
|
std::stringstream buffer;
|
||||||
|
|
|
@ -154,11 +154,16 @@ struct BlendTreeResource {
|
||||||
const AnimNodeResource* target_node,
|
const AnimNodeResource* target_node,
|
||||||
const std::string& target_socket_name) const;
|
const std::string& target_socket_name) const;
|
||||||
|
|
||||||
|
const BlendTreeConnectionResource* FindConnectionForSocket(
|
||||||
|
const AnimNodeResource* node,
|
||||||
|
const std::string& socket_name) const;
|
||||||
|
|
||||||
bool IsSocketConnected(
|
bool IsSocketConnected(
|
||||||
const AnimNodeResource* source_node,
|
const AnimNodeResource* node,
|
||||||
const std::string& socket_name) {
|
const std::string& socket_name) const {
|
||||||
assert(false && "Not yet implemented");
|
const BlendTreeConnectionResource* connection =
|
||||||
return false;
|
FindConnectionForSocket(node, socket_name);
|
||||||
|
return connection != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Socket*> GetConstantNodeInputs(
|
std::vector<Socket*> GetConstantNodeInputs(
|
||||||
|
|
|
@ -561,6 +561,7 @@ int main() {
|
||||||
AnimData anim_graph_output;
|
AnimData anim_graph_output;
|
||||||
anim_graph_output.m_local_matrices.resize(
|
anim_graph_output.m_local_matrices.resize(
|
||||||
skinned_mesh.m_skeleton.num_soa_joints());
|
skinned_mesh.m_skeleton.num_soa_joints());
|
||||||
|
AnimGraphEditorClear();
|
||||||
|
|
||||||
state.time.factor = 1.0f;
|
state.time.factor = 1.0f;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
#include "AnimGraph/AnimGraphEditor.h"
|
||||||
|
#include "catch.hpp"
|
||||||
|
|
||||||
|
TEST_CASE("Node Socket To InputPin Conversion", "[animGraphEditor]") {
|
||||||
|
int node_index = 321;
|
||||||
|
int socket_index = 221;
|
||||||
|
long socket_id;
|
||||||
|
|
||||||
|
socket_id = NodeIndexAndSocketIndexToInputPinId(node_index, socket_index);
|
||||||
|
|
||||||
|
int node_index_resolved;
|
||||||
|
int socket_index_resolved;
|
||||||
|
|
||||||
|
InputPinIdToNodeIndexAndSocketIndex(
|
||||||
|
socket_id,
|
||||||
|
&node_index_resolved,
|
||||||
|
&socket_index_resolved);
|
||||||
|
|
||||||
|
CHECK(node_index == node_index_resolved);
|
||||||
|
CHECK(socket_index == socket_index_resolved);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Node Socket To OutputPin Conversion", "[animGraphEditor]") {
|
||||||
|
int node_index = 321;
|
||||||
|
int socket_index = 221;
|
||||||
|
long socket_id;
|
||||||
|
|
||||||
|
socket_id = NodeIndexAndSocketIndexToOutputPinId(node_index, socket_index);
|
||||||
|
|
||||||
|
int node_index_resolved;
|
||||||
|
int socket_index_resolved;
|
||||||
|
|
||||||
|
OutputPinIdToNodeIndexAndSocketIndex(
|
||||||
|
socket_id,
|
||||||
|
&node_index_resolved,
|
||||||
|
&socket_index_resolved);
|
||||||
|
|
||||||
|
CHECK(node_index == node_index_resolved);
|
||||||
|
CHECK(socket_index == socket_index_resolved);
|
||||||
|
}
|
Loading…
Reference in New Issue