Use socket pointers instead of indices for connections.
parent
84a9ef6f14
commit
72a67195e6
|
@ -173,28 +173,36 @@ AnimNodeResource sAnimGraphNodeFromJson(const json& json_node) {
|
||||||
//
|
//
|
||||||
// AnimGraphConnection <-> Json
|
// AnimGraphConnection <-> Json
|
||||||
//
|
//
|
||||||
json sAnimGraphConnectionToJson(const AnimGraphConnection& connection) {
|
json sAnimGraphConnectionToJson(const AnimGraphResource& graph_resource, const AnimGraphConnection& connection) {
|
||||||
json result;
|
json result;
|
||||||
|
|
||||||
result["type"] = "AnimGraphConnection";
|
result["type"] = "AnimGraphConnection";
|
||||||
|
|
||||||
result["source_node_index"] = connection.m_source_node_index;
|
const AnimNodeResource* source_node = connection.m_source_node;
|
||||||
result["source_socket_index"] = connection.m_source_socket_index;
|
result["source_node_index"] = graph_resource.getNodeIndex(*source_node);
|
||||||
|
result["source_socket_index"] = source_node->m_socket_accessor->GetOutputIndex(connection.m_source_socket->m_name);
|
||||||
|
|
||||||
result["target_node_index"] = connection.m_target_node_index;
|
const AnimNodeResource* target_node = connection.m_source_node;
|
||||||
result["target_socket_index"] = connection.m_target_socket_index;
|
result["source_node_index"] = graph_resource.getNodeIndex(*target_node);
|
||||||
|
result["source_socket_index"] = target_node->m_socket_accessor->GetInputIndex(connection.m_target_node->m_name);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimGraphConnection sAnimGraphConnectionFromJson(const json& json_node) {
|
AnimGraphConnection sAnimGraphConnectionFromJson(const AnimGraphResource& graph_resource, const json& json_node) {
|
||||||
AnimGraphConnection connection;
|
AnimGraphConnection connection;
|
||||||
|
|
||||||
connection.m_source_node_index = json_node["source_node_index"];
|
int source_node_index = json_node["source_node_index"];
|
||||||
connection.m_source_socket_index = json_node["source_socket_index"];
|
connection.m_source_node = &graph_resource.m_nodes[source_node_index];
|
||||||
|
int source_socket_index = json_node["source_socket_index"];
|
||||||
|
connection.m_source_socket = &connection.m_source_node->m_socket_accessor->m_outputs[source_socket_index];
|
||||||
|
|
||||||
connection.m_target_node_index = json_node["target_node_index"];
|
|
||||||
connection.m_target_socket_index = json_node["target_socket_index"];
|
int target_node_index = json_node["target_node_index"];
|
||||||
|
connection.m_target_node = &graph_resource.m_nodes[target_node_index];
|
||||||
|
|
||||||
|
int target_socket_index = json_node["target_socket_index"];
|
||||||
|
connection.m_target_socket = &connection.m_target_node->m_socket_accessor->m_outputs[target_socket_index];
|
||||||
|
|
||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
@ -238,7 +246,7 @@ bool AnimGraphResource::saveToFile(const char* filename) const {
|
||||||
|
|
||||||
for (size_t i = 0; i < m_connections.size(); i++) {
|
for (size_t i = 0; i < m_connections.size(); i++) {
|
||||||
const AnimGraphConnection& connection = m_connections[i];
|
const AnimGraphConnection& connection = m_connections[i];
|
||||||
result["connections"][i] = sAnimGraphConnectionToJson(connection);
|
result["connections"][i] = sAnimGraphConnectionToJson(*this, connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Graph inputs and outputs
|
// Graph inputs and outputs
|
||||||
|
@ -288,6 +296,8 @@ bool AnimGraphResource::loadFromFile(const char* filename) {
|
||||||
clearNodes();
|
clearNodes();
|
||||||
|
|
||||||
m_name = json_data["name"];
|
m_name = json_data["name"];
|
||||||
|
|
||||||
|
// Load nodes
|
||||||
for (size_t i = 0; i < json_data["nodes"].size(); i++) {
|
for (size_t i = 0; i < json_data["nodes"].size(); i++) {
|
||||||
const json& json_node = json_data["nodes"][i];
|
const json& json_node = json_data["nodes"][i];
|
||||||
if (json_node["type"] != "AnimNodeResource") {
|
if (json_node["type"] != "AnimNodeResource") {
|
||||||
|
@ -301,20 +311,7 @@ bool AnimGraphResource::loadFromFile(const char* filename) {
|
||||||
m_nodes.push_back(node);
|
m_nodes.push_back(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < json_data["connections"].size(); i++) {
|
// Setup graph inputs and outputs
|
||||||
const json& json_connection = json_data["connections"][i];
|
|
||||||
if (json_connection["type"] != "AnimGraphConnection") {
|
|
||||||
std::cerr << "Invalid json object. Expected type 'AnimGraphConnection' "
|
|
||||||
"but got '"
|
|
||||||
<< json_connection["type"] << "'." << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
AnimGraphConnection connection =
|
|
||||||
sAnimGraphConnectionFromJson(json_connection);
|
|
||||||
m_connections.push_back(connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
const json& graph_outputs = json_data["nodes"][0]["inputs"];
|
const json& graph_outputs = json_data["nodes"][0]["inputs"];
|
||||||
for (size_t i = 0; i < graph_outputs.size(); i++) {
|
for (size_t i = 0; i < graph_outputs.size(); i++) {
|
||||||
AnimNodeResource& graph_node = m_nodes[0];
|
AnimNodeResource& graph_node = m_nodes[0];
|
||||||
|
@ -329,6 +326,21 @@ bool AnimGraphResource::loadFromFile(const char* filename) {
|
||||||
sJsonToSocket(graph_inputs[i]));
|
sJsonToSocket(graph_inputs[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load connections
|
||||||
|
for (size_t i = 0; i < json_data["connections"].size(); i++) {
|
||||||
|
const json& json_connection = json_data["connections"][i];
|
||||||
|
if (json_connection["type"] != "AnimGraphConnection") {
|
||||||
|
std::cerr << "Invalid json object. Expected type 'AnimGraphConnection' "
|
||||||
|
"but got '"
|
||||||
|
<< json_connection["type"] << "'." << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimGraphConnection connection =
|
||||||
|
sAnimGraphConnectionFromJson(*this, json_connection);
|
||||||
|
m_connections.push_back(connection);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,6 @@ SplitOutputAttributeId(int attribute_id, int* node_id, int* output_index) {
|
||||||
*output_index = (attribute_id >> 23) - 1;
|
*output_index = (attribute_id >> 23) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
enum class SocketType {
|
enum class SocketType {
|
||||||
SocketTypeUndefined = 0,
|
SocketTypeUndefined = 0,
|
||||||
SocketTypeBool,
|
SocketTypeBool,
|
||||||
|
@ -59,9 +58,8 @@ enum class SocketType {
|
||||||
SocketTypeLast
|
SocketTypeLast
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char* SocketTypeNames[] = {
|
static const char* SocketTypeNames[] =
|
||||||
"", "Bool", "Animation", "Float", "Vec3", "Quat", "String"
|
{"", "Bool", "Animation", "Float", "Vec3", "Quat", "String"};
|
||||||
};
|
|
||||||
|
|
||||||
enum SocketFlags { SocketFlagAffectsTime = 1 };
|
enum SocketFlags { SocketFlagAffectsTime = 1 };
|
||||||
|
|
||||||
|
@ -88,7 +86,6 @@ struct AnimNodeResource {
|
||||||
float m_position[2] = {0.f, 0.f};
|
float m_position[2] = {0.f, 0.f};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct NodeInput {
|
struct NodeInput {
|
||||||
AnimNode* m_node;
|
AnimNode* m_node;
|
||||||
SocketType m_type = SocketType::SocketTypeUndefined;
|
SocketType m_type = SocketType::SocketTypeUndefined;
|
||||||
|
@ -142,10 +139,9 @@ struct AnimNode {
|
||||||
m_state = AnimNodeEvalState::TimeUpdated;
|
m_state = AnimNodeEvalState::TimeUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Evaluate() {};
|
virtual void Evaluate(){};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct NodeSocketAccessorBase {
|
struct NodeSocketAccessorBase {
|
||||||
std::vector<Socket> m_properties;
|
std::vector<Socket> m_properties;
|
||||||
std::vector<Socket> m_inputs;
|
std::vector<Socket> m_inputs;
|
||||||
|
@ -484,10 +480,10 @@ struct NodeSocketAccessor<AnimSamplerNode> : public NodeSocketAccessorBase {
|
||||||
// AnimGraphResource
|
// AnimGraphResource
|
||||||
//
|
//
|
||||||
struct AnimGraphConnection {
|
struct AnimGraphConnection {
|
||||||
int m_source_node_index;
|
const AnimNodeResource* m_source_node = nullptr;
|
||||||
int m_source_socket_index;
|
const Socket* m_source_socket = nullptr;
|
||||||
int m_target_node_index;
|
const AnimNodeResource* m_target_node = nullptr;
|
||||||
int m_target_socket_index;
|
const Socket* m_target_socket = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AnimGraphResource {
|
struct AnimGraphResource {
|
||||||
|
@ -516,7 +512,7 @@ struct AnimGraphResource {
|
||||||
const AnimNodeResource& getGraphOutputNode() const { return m_nodes[0]; }
|
const AnimNodeResource& getGraphOutputNode() const { return m_nodes[0]; }
|
||||||
const AnimNodeResource& getGraphInputNode() const { return m_nodes[1]; }
|
const AnimNodeResource& getGraphInputNode() const { return m_nodes[1]; }
|
||||||
|
|
||||||
size_t getNodeIndex (const AnimNodeResource& node_resource) const {
|
size_t getNodeIndex(const AnimNodeResource& node_resource) const {
|
||||||
for (size_t i = 0, n = m_nodes.size(); i < n; i++) {
|
for (size_t i = 0, n = m_nodes.size(); i < n; i++) {
|
||||||
if (&m_nodes[i] == &node_resource) {
|
if (&m_nodes[i] == &node_resource) {
|
||||||
return i;
|
return i;
|
||||||
|
@ -533,9 +529,9 @@ struct AnimGraphResource {
|
||||||
|
|
||||||
bool connectSockets(
|
bool connectSockets(
|
||||||
const AnimNodeResource& source_node,
|
const AnimNodeResource& source_node,
|
||||||
const std::string& source_socket,
|
const std::string& source_socket_name,
|
||||||
const AnimNodeResource& target_node,
|
const AnimNodeResource& target_node,
|
||||||
const std::string& target_socket) {
|
const std::string& target_socket_name) {
|
||||||
size_t source_index = -1;
|
size_t source_index = -1;
|
||||||
size_t target_index = -1;
|
size_t target_index = -1;
|
||||||
for (size_t i = 0, n = m_nodes.size(); i < n; i++) {
|
for (size_t i = 0, n = m_nodes.size(); i < n; i++) {
|
||||||
|
@ -557,23 +553,21 @@ struct AnimGraphResource {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t source_socket_index =
|
Socket* source_socket =
|
||||||
source_node.m_socket_accessor->GetOutputIndex(source_socket);
|
source_node.m_socket_accessor->FindOutputSocket(source_socket_name);
|
||||||
size_t target_socket_index =
|
Socket* target_socket =
|
||||||
target_node.m_socket_accessor->GetInputIndex(target_socket);
|
target_node.m_socket_accessor->FindInputSocket(target_socket_name);
|
||||||
|
|
||||||
if (source_socket_index >= source_node.m_socket_accessor->m_outputs.size()
|
if (source_socket == nullptr || target_socket == nullptr) {
|
||||||
|| target_socket_index
|
|
||||||
>= target_node.m_socket_accessor->m_inputs.size()) {
|
|
||||||
std::cerr << "Cannot connect nodes: could not find sockets." << std::endl;
|
std::cerr << "Cannot connect nodes: could not find sockets." << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimGraphConnection connection;
|
AnimGraphConnection connection;
|
||||||
connection.m_source_node_index = source_index;
|
connection.m_source_node = &source_node;
|
||||||
connection.m_source_socket_index = source_socket_index;
|
connection.m_source_socket = source_socket;
|
||||||
connection.m_target_node_index = target_index;
|
connection.m_target_node = &target_node;
|
||||||
connection.m_target_socket_index = target_socket_index;
|
connection.m_target_socket = target_socket;
|
||||||
m_connections.push_back(connection);
|
m_connections.push_back(connection);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -672,7 +666,6 @@ struct AnimGraph {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void* getOutput(const std::string& name) const;
|
void* getOutput(const std::string& name) const;
|
||||||
void* getInput(const std::string& name) const;
|
void* getInput(const std::string& name) const;
|
||||||
|
|
||||||
|
@ -799,12 +792,19 @@ struct AnimGraph {
|
||||||
NodeSocketAccessorBase* target_node_accessor = nullptr;
|
NodeSocketAccessorBase* target_node_accessor = nullptr;
|
||||||
SocketType source_type;
|
SocketType source_type;
|
||||||
SocketType target_type;
|
SocketType target_type;
|
||||||
|
size_t source_socket_index = -1;
|
||||||
|
size_t target_socket_index = -1;
|
||||||
|
|
||||||
if (connection.m_source_node_index >= 0) {
|
if (connection.m_source_node != nullptr) {
|
||||||
source_node = result.m_nodes[connection.m_source_node_index];
|
size_t node_index = resource.getNodeIndex(*connection.m_source_node);
|
||||||
|
if (node_index == -1) {
|
||||||
|
std::cerr << "Could not find source node index." << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
source_node = result.m_nodes[node_index];
|
||||||
source_node_name = source_node->m_name;
|
source_node_name = source_node->m_name;
|
||||||
source_node_type = source_node->m_node_type_name;
|
source_node_type = source_node->m_node_type_name;
|
||||||
if (connection.m_source_node_index == 1) {
|
if (node_index == 1) {
|
||||||
source_node_accessor = result.m_socket_accessor;
|
source_node_accessor = result.m_socket_accessor;
|
||||||
} else {
|
} else {
|
||||||
source_node_accessor =
|
source_node_accessor =
|
||||||
|
@ -812,11 +812,16 @@ struct AnimGraph {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connection.m_target_node_index >= 0) {
|
if (connection.m_target_node != nullptr) {
|
||||||
target_node = result.m_nodes[connection.m_target_node_index];
|
size_t node_index = resource.getNodeIndex(*connection.m_target_node);
|
||||||
|
if (node_index == -1) {
|
||||||
|
std::cerr << "Could not find source node index." << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
target_node = result.m_nodes[node_index];
|
||||||
target_node_name = target_node->m_name;
|
target_node_name = target_node->m_name;
|
||||||
target_node_type = target_node->m_node_type_name;
|
target_node_type = target_node->m_node_type_name;
|
||||||
if (connection.m_target_node_index == 0) {
|
if (node_index == 0) {
|
||||||
target_node_accessor = result.m_socket_accessor;
|
target_node_accessor = result.m_socket_accessor;
|
||||||
} else {
|
} else {
|
||||||
target_node_accessor =
|
target_node_accessor =
|
||||||
|
@ -827,41 +832,50 @@ struct AnimGraph {
|
||||||
assert(source_node != nullptr);
|
assert(source_node != nullptr);
|
||||||
assert(target_node != nullptr);
|
assert(target_node != nullptr);
|
||||||
|
|
||||||
if (connection.m_source_socket_index
|
//
|
||||||
> source_node_accessor->m_outputs.size()) {
|
// Map resource node sockets to graph instance node sockets
|
||||||
std::cerr << "Invalid source socket index "
|
//
|
||||||
<< connection.m_source_socket_index << ". Only "
|
if (connection.m_source_socket == nullptr) {
|
||||||
<< source_node_accessor->m_outputs.size()
|
std::cerr << "Invalid source socket for connection " << i << "."
|
||||||
<< " output sockets found." << std::endl;
|
<< std::endl;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connection.m_target_socket_index
|
if (connection.m_target_socket == nullptr) {
|
||||||
> target_node_accessor->m_inputs.size()) {
|
std::cerr << "Invalid source socket for connection " << i << "."
|
||||||
std::cerr << "Invalid source socket index "
|
<< std::endl;
|
||||||
<< connection.m_target_socket_index << ". Only "
|
|
||||||
<< source_node_accessor->m_inputs.size()
|
|
||||||
<< " input sockets found." << std::endl;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source_node_accessor->m_outputs[connection.m_source_socket_index]
|
source_socket_index = source_node_accessor->GetOutputIndex(
|
||||||
.m_type
|
connection.m_source_socket->m_name);
|
||||||
!= target_node_accessor->m_inputs[connection.m_target_socket_index]
|
if (source_socket_index == -1) {
|
||||||
.m_type) {
|
std::cerr << "Invalid source socket "
|
||||||
std::cerr << "Invalid connection connecting nodes '" << source_node_name
|
<< connection.m_source_socket->m_name << " for node "
|
||||||
<< "' and '" << target_node_name << "'." << std::endl;
|
<< connection.m_source_node->m_name << "." << std::endl;
|
||||||
return result;
|
continue;
|
||||||
}
|
}
|
||||||
|
const Socket* source_socket =
|
||||||
|
&source_node_accessor->m_outputs[source_socket_index];
|
||||||
|
|
||||||
|
target_socket_index = target_node_accessor->GetInputIndex(
|
||||||
|
connection.m_target_socket->m_name);
|
||||||
|
if (target_socket_index == -1) {
|
||||||
|
std::cerr << "Invalid target socket "
|
||||||
|
<< connection.m_target_socket->m_name << " for node "
|
||||||
|
<< connection.m_target_node->m_name << "." << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const Socket* target_socket =
|
||||||
|
&target_node_accessor->m_inputs[target_socket_index];
|
||||||
|
|
||||||
Socket* source_socket =
|
|
||||||
&source_node_accessor->m_outputs[connection.m_source_socket_index];
|
|
||||||
Socket* target_socket =
|
|
||||||
&target_node_accessor->m_inputs[connection.m_target_socket_index];
|
|
||||||
if (source_socket->m_type != target_socket->m_type) {
|
if (source_socket->m_type != target_socket->m_type) {
|
||||||
std::cerr << "Cannot connect sockets: invalid types!" << std::endl;
|
std::cerr << "Cannot connect sockets: invalid types!" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Wire up outputs to inputs.
|
||||||
|
//
|
||||||
(*source_socket->m_value.ptr_ptr) = target_socket->m_value.ptr;
|
(*source_socket->m_value.ptr_ptr) = target_socket->m_value.ptr;
|
||||||
|
|
||||||
size_t target_node_index = target_node->m_index;
|
size_t target_node_index = target_node->m_index;
|
||||||
|
|
|
@ -36,30 +36,30 @@ TEST_CASE("BasicGraph", "[AnimGraphResource]") {
|
||||||
REQUIRE(blend_node.m_socket_accessor->GetInputIndex("Input1") == 1);
|
REQUIRE(blend_node.m_socket_accessor->GetInputIndex("Input1") == 1);
|
||||||
|
|
||||||
AnimGraphConnection walk_to_blend;
|
AnimGraphConnection walk_to_blend;
|
||||||
walk_to_blend.m_source_node_index = walk_node_index;
|
walk_to_blend.m_source_node = &walk_node;
|
||||||
walk_to_blend.m_source_socket_index =
|
walk_to_blend.m_source_socket =
|
||||||
walk_node.m_socket_accessor->GetOutputIndex("Output");
|
walk_node.m_socket_accessor->FindOutputSocket("Output");
|
||||||
walk_to_blend.m_target_node_index = blend_node_index;
|
walk_to_blend.m_target_node = &blend_node;
|
||||||
walk_to_blend.m_target_socket_index =
|
walk_to_blend.m_target_socket =
|
||||||
blend_node.m_socket_accessor->GetInputIndex("Input0");
|
blend_node.m_socket_accessor->FindInputSocket("Input0");
|
||||||
graph_resource.m_connections.push_back(walk_to_blend);
|
graph_resource.m_connections.push_back(walk_to_blend);
|
||||||
|
|
||||||
AnimGraphConnection run_to_blend;
|
AnimGraphConnection run_to_blend;
|
||||||
run_to_blend.m_source_node_index = run_node_index;
|
run_to_blend.m_source_node = &run_node;
|
||||||
run_to_blend.m_source_socket_index =
|
run_to_blend.m_source_socket =
|
||||||
run_node.m_socket_accessor->GetOutputIndex("Output");
|
run_node.m_socket_accessor->FindOutputSocket("Output");
|
||||||
run_to_blend.m_target_node_index = blend_node_index;
|
run_to_blend.m_target_node = &blend_node;
|
||||||
run_to_blend.m_target_socket_index =
|
run_to_blend.m_target_socket =
|
||||||
blend_node.m_socket_accessor->GetInputIndex("Input1");
|
blend_node.m_socket_accessor->FindInputSocket("Input1");
|
||||||
graph_resource.m_connections.push_back(run_to_blend);
|
graph_resource.m_connections.push_back(run_to_blend);
|
||||||
|
|
||||||
AnimGraphConnection blend_to_output;
|
AnimGraphConnection blend_to_output;
|
||||||
blend_to_output.m_source_node_index = blend_node_index;
|
blend_to_output.m_source_node = &blend_node;
|
||||||
blend_to_output.m_source_socket_index =
|
blend_to_output.m_source_socket =
|
||||||
blend_node.m_socket_accessor->GetOutputIndex("Output");
|
blend_node.m_socket_accessor->FindOutputSocket("Output");
|
||||||
blend_to_output.m_target_node_index = 0;
|
blend_to_output.m_target_node = &graph_resource.m_nodes[0];
|
||||||
blend_to_output.m_target_socket_index =
|
blend_to_output.m_target_socket =
|
||||||
graph_node.m_socket_accessor->GetInputIndex("GraphOutput");
|
graph_node.m_socket_accessor->FindInputSocket("GraphOutput");
|
||||||
graph_resource.m_connections.push_back(blend_to_output);
|
graph_resource.m_connections.push_back(blend_to_output);
|
||||||
|
|
||||||
graph_resource.saveToFile("WalkGraph.animgraph.json");
|
graph_resource.saveToFile("WalkGraph.animgraph.json");
|
||||||
|
|
Loading…
Reference in New Issue