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