Fixed memory leak by introducing virtual node descriptors.
AnimNodeResources do not reference an actual node anymore. However, we still need descriptors to check whether connections are valid. For this we have VirtualNodeDescriptors for which all sockets point to nullptr.
This commit is contained in:
parent
4b378adc91
commit
40f631c51a
@ -269,6 +269,11 @@ struct AnimGraphConnection {
|
||||
bool m_crosses_hierarchy = false;
|
||||
};
|
||||
|
||||
/** Maps socket names to actual memory locations of the corresponding sockets.
|
||||
*
|
||||
* This class is needed when instantiating a Blend Tree but also for the editor.
|
||||
* It also acts as a virtual socket container for input and output sockets for Blend Trees.
|
||||
*/
|
||||
struct NodeDescriptorBase {
|
||||
std::vector<Socket> m_inputs;
|
||||
std::vector<Socket> m_outputs;
|
||||
@ -346,7 +351,7 @@ struct NodeDescriptorBase {
|
||||
*socket->m_reference.ptr_ptr = value_ptr;
|
||||
}
|
||||
|
||||
Socket* GetInputSocket(const char* name) {
|
||||
Socket* GetInputSocket(const char* name) const {
|
||||
return FindSocket(name, m_inputs);
|
||||
}
|
||||
|
||||
@ -366,7 +371,7 @@ struct NodeDescriptorBase {
|
||||
*socket->m_reference.ptr_ptr = value_ptr;
|
||||
}
|
||||
|
||||
Socket* GetOutputSocket(const char* name) {
|
||||
Socket* GetOutputSocket(const char* name) const {
|
||||
return FindSocket(name, m_outputs);
|
||||
}
|
||||
|
||||
@ -421,21 +426,11 @@ struct NodeDescriptorBase {
|
||||
virtual void UpdateFlags() {};
|
||||
|
||||
protected:
|
||||
Socket* FindSocket(const char* name, std::vector<Socket>& sockets) {
|
||||
for (size_t i = 0, n = sockets.size(); i < n; i++) {
|
||||
if (sockets[i].m_name == name) {
|
||||
return &sockets[i];
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const Socket* FindSocket(const char* name, const std::vector<Socket>& sockets)
|
||||
Socket* FindSocket(const char* name, const std::vector<Socket>& sockets)
|
||||
const {
|
||||
for (size_t i = 0, n = sockets.size(); i < n; i++) {
|
||||
if (sockets[i].m_name == name) {
|
||||
return &sockets[i];
|
||||
return const_cast<Socket*>(&sockets[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -185,11 +185,13 @@ void AnimGraphEditorRenderSidebar(
|
||||
}
|
||||
|
||||
int num_properties = 0;
|
||||
if (node_resource->m_socket_accessor != nullptr) {
|
||||
num_properties = node_resource->m_socket_accessor->m_properties.size();
|
||||
if (node_resource->m_virtual_socket_accessor != nullptr) {
|
||||
num_properties =
|
||||
node_resource->m_virtual_socket_accessor->m_properties.size();
|
||||
}
|
||||
for (int i = 0; i < num_properties; i++) {
|
||||
Socket& property = node_resource->m_socket_accessor->m_properties[i];
|
||||
Socket& property =
|
||||
node_resource->m_virtual_socket_accessor->m_properties[i];
|
||||
if (property.m_type == SocketType::SocketTypeInt) {
|
||||
ImGui::InputInt(
|
||||
property.m_name.c_str(),
|
||||
@ -228,7 +230,8 @@ void AnimGraphEditorRenderSidebar(
|
||||
ImGui::Text("Outputs");
|
||||
|
||||
// Graph outputs are the inputs of the output node!
|
||||
std::vector<Socket>& outputs = node_resource->m_socket_accessor->m_inputs;
|
||||
std::vector<Socket>& outputs =
|
||||
node_resource->m_virtual_socket_accessor->m_inputs;
|
||||
|
||||
std::vector<Socket>::iterator iter = outputs.begin();
|
||||
while (iter != outputs.end()) {
|
||||
@ -264,7 +267,8 @@ void AnimGraphEditorRenderSidebar(
|
||||
ImGui::Text("Inputs");
|
||||
|
||||
// Graph inputs are the outputs of the input node!
|
||||
std::vector<Socket>& inputs = node_resource->m_socket_accessor->m_outputs;
|
||||
std::vector<Socket>& inputs =
|
||||
node_resource->m_virtual_socket_accessor->m_outputs;
|
||||
|
||||
std::vector<Socket>::iterator iter = inputs.begin();
|
||||
while (iter != inputs.end()) {
|
||||
@ -273,7 +277,7 @@ void AnimGraphEditorRenderSidebar(
|
||||
if (NodeSocketEditor(input)) {
|
||||
AnimGraphResource* current_graph_resource =
|
||||
sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex];
|
||||
current_graph_resource->m_socket_accessor->m_inputs = inputs;
|
||||
current_graph_resource->m_virtual_socket_accessor->m_inputs = inputs;
|
||||
}
|
||||
if (ImGui::Button("X")) {
|
||||
RemoveBlendTreeConnectionsForSocket(
|
||||
@ -302,7 +306,7 @@ void AnimGraphEditorClear() {
|
||||
}
|
||||
|
||||
if (sEditorState.rootGraphResource) {
|
||||
delete sEditorState.rootGraphResource->m_socket_accessor;
|
||||
delete sEditorState.rootGraphResource->m_virtual_socket_accessor;
|
||||
}
|
||||
delete sEditorState.rootGraphResource;
|
||||
|
||||
@ -310,7 +314,8 @@ void AnimGraphEditorClear() {
|
||||
sEditorState.rootGraphResource->m_name = "Root";
|
||||
sEditorState.rootGraphResource->m_graph_type_name = "BlendTree";
|
||||
sEditorState.rootGraphResource->m_blend_tree_resource.InitGraphConnectors();
|
||||
sEditorState.rootGraphResource->m_socket_accessor = new NodeDescriptorBase;
|
||||
sEditorState.rootGraphResource->m_virtual_socket_accessor =
|
||||
new NodeDescriptorBase;
|
||||
|
||||
sEditorState.hierarchyStack.clear();
|
||||
sEditorState.hierarchyStack.push_back(sEditorState.rootGraphResource);
|
||||
@ -462,7 +467,7 @@ void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
|
||||
->m_blend_tree_resource.GetNode(
|
||||
connection_resource->source_node_index);
|
||||
int source_socket_index =
|
||||
source_node_resource->m_socket_accessor->GetOutputIndex(
|
||||
source_node_resource->m_virtual_socket_accessor->GetOutputIndex(
|
||||
connection_resource->source_socket_name.c_str());
|
||||
|
||||
const AnimNodeResource* target_node_resource =
|
||||
@ -470,7 +475,7 @@ void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
|
||||
->m_blend_tree_resource.GetNode(
|
||||
connection_resource->target_node_index);
|
||||
int target_socket_index =
|
||||
target_node_resource->m_socket_accessor->GetInputIndex(
|
||||
target_node_resource->m_virtual_socket_accessor->GetInputIndex(
|
||||
connection_resource->target_socket_name.c_str());
|
||||
|
||||
int source_socket_pin_id = NodeIndexAndSocketIndexToOutputPinId(
|
||||
@ -504,7 +509,7 @@ void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
|
||||
source_node =
|
||||
sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex]
|
||||
->m_blend_tree_resource.GetNode(source_node_index);
|
||||
if (source_node->m_socket_accessor->m_outputs.size()
|
||||
if (source_node->m_virtual_socket_accessor->m_outputs.size()
|
||||
< source_node_socket_index) {
|
||||
source_node_socket_index = -1;
|
||||
} else {
|
||||
@ -530,7 +535,7 @@ void AnimGraphEditorUpdate(ax::NodeEditor::EditorContext* context) {
|
||||
target_node =
|
||||
sEditorState.hierarchyStack[sEditorState.hierarchyStackIndex]
|
||||
->m_blend_tree_resource.GetNode(target_node_index);
|
||||
if (target_node->m_socket_accessor->m_inputs.size()
|
||||
if (target_node->m_virtual_socket_accessor->m_inputs.size()
|
||||
< target_node_socket_index) {
|
||||
target_node_socket_index = -1;
|
||||
} else {
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
AnimNode* AnimNodeFactory(const std::string& name) {
|
||||
AnimNode* result = nullptr;
|
||||
|
||||
|
||||
if (name == "Blend2") {
|
||||
result = new Blend2Node;
|
||||
} else if (name == "SpeedScale") {
|
||||
@ -72,6 +72,29 @@ NodeDescriptorBase* AnimNodeDescriptorFactory(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NodeDescriptorBase* VirtualAnimNodeDescriptorFactory(
|
||||
const std::string& node_type_name) {
|
||||
AnimNode* temp_node = AnimNodeFactory(node_type_name);
|
||||
NodeDescriptorBase* result =
|
||||
AnimNodeDescriptorFactory(node_type_name.c_str(), temp_node);
|
||||
|
||||
for (Socket& socket : result->m_inputs) {
|
||||
socket.m_reference.ptr = nullptr;
|
||||
}
|
||||
|
||||
for (Socket& socket : result->m_outputs) {
|
||||
socket.m_reference.ptr = nullptr;
|
||||
}
|
||||
|
||||
for (Socket& socket : result->m_properties) {
|
||||
socket.m_reference.ptr = nullptr;
|
||||
}
|
||||
|
||||
delete temp_node;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Blend2Node::Evaluate(AnimGraphContext& context) {
|
||||
assert(i_input0 != nullptr);
|
||||
assert(i_input1 != nullptr);
|
||||
|
@ -240,4 +240,7 @@ NodeDescriptorBase* AnimNodeDescriptorFactory(
|
||||
const std::string& node_type_name,
|
||||
AnimNode* node);
|
||||
|
||||
NodeDescriptorBase* VirtualAnimNodeDescriptorFactory(
|
||||
const std::string& node_type_name);
|
||||
|
||||
#endif //ANIMTESTBED_ANIMGRAPHNODES_H
|
||||
|
@ -149,7 +149,7 @@ json sAnimGraphNodeToJson(
|
||||
if (node->m_node_type_name == "BlendTree") {
|
||||
}
|
||||
|
||||
for (const auto& socket : node->m_socket_accessor->m_inputs) {
|
||||
for (const auto& socket : node->m_virtual_socket_accessor->m_inputs) {
|
||||
if (socket.m_type == SocketType::SocketTypeAnimation) {
|
||||
continue;
|
||||
}
|
||||
@ -168,7 +168,7 @@ json sAnimGraphNodeToJson(
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& property : node->m_socket_accessor->m_properties) {
|
||||
for (auto& property : node->m_virtual_socket_accessor->m_properties) {
|
||||
result["properties"][property.m_name] = sSocketToJson(property);
|
||||
}
|
||||
|
||||
@ -193,11 +193,10 @@ AnimNodeResource* sAnimGraphNodeFromJson(
|
||||
result->m_position[0] = json_node["position"][0];
|
||||
result->m_position[1] = json_node["position"][1];
|
||||
|
||||
result->m_anim_node = AnimNodeFactory(result->m_node_type_name);
|
||||
result->m_socket_accessor =
|
||||
AnimNodeDescriptorFactory(result->m_node_type_name, result->m_anim_node);
|
||||
result->m_virtual_socket_accessor =
|
||||
VirtualAnimNodeDescriptorFactory(result->m_node_type_name);
|
||||
|
||||
for (auto& property : result->m_socket_accessor->m_properties) {
|
||||
for (auto& property : result->m_virtual_socket_accessor->m_properties) {
|
||||
property = sJsonToSocket(json_node["properties"][property.m_name]);
|
||||
}
|
||||
|
||||
@ -206,7 +205,7 @@ AnimNodeResource* sAnimGraphNodeFromJson(
|
||||
assert(json_node["inputs"][j].contains("name"));
|
||||
std::string input_name = json_node["inputs"][j]["name"];
|
||||
Socket* input_socket =
|
||||
result->m_socket_accessor->GetInputSocket(input_name.c_str());
|
||||
result->m_virtual_socket_accessor->GetInputSocket(input_name.c_str());
|
||||
if (input_socket == nullptr) {
|
||||
std::cerr << "Could not find input socket with name " << input_name
|
||||
<< " for node type " << result->m_node_type_name << std::endl;
|
||||
@ -285,14 +284,14 @@ static json sAnimGraphResourceBlendTreeToJson(
|
||||
{
|
||||
const AnimNodeResource* graph_output_node = blend_tree_resource.GetNode(0);
|
||||
const std::vector<Socket> graph_inputs =
|
||||
graph_output_node->m_socket_accessor->m_inputs;
|
||||
graph_output_node->m_virtual_socket_accessor->m_inputs;
|
||||
for (size_t i = 0; i < graph_inputs.size(); i++) {
|
||||
result["nodes"][0]["inputs"][i] = sSocketToJson(graph_inputs[i]);
|
||||
}
|
||||
|
||||
const AnimNodeResource* graph_input_node = blend_tree_resource.GetNode(1);
|
||||
const std::vector<Socket> graph_outputs =
|
||||
graph_input_node->m_socket_accessor->m_outputs;
|
||||
graph_input_node->m_virtual_socket_accessor->m_outputs;
|
||||
for (size_t i = 0; i < graph_outputs.size(); i++) {
|
||||
result["nodes"][1]["outputs"][i] = sSocketToJson(graph_outputs[i]);
|
||||
}
|
||||
@ -311,8 +310,8 @@ static bool sAnimGraphResourceBlendTreeFromJson(
|
||||
result_graph_resource->m_name = json_data["name"];
|
||||
result_graph_resource->m_position[0] = json_data["position"][0];
|
||||
result_graph_resource->m_position[1] = json_data["position"][1];
|
||||
assert(result_graph_resource->m_socket_accessor == nullptr);
|
||||
result_graph_resource->m_socket_accessor =
|
||||
assert(result_graph_resource->m_virtual_socket_accessor == nullptr);
|
||||
result_graph_resource->m_virtual_socket_accessor =
|
||||
AnimNodeDescriptorFactory("BlendTree", nullptr);
|
||||
|
||||
// Load nodes
|
||||
@ -492,9 +491,9 @@ Socket* BlendTreeResource::GetNodeOutputSocket(
|
||||
const std::string& output_socket_name) const {
|
||||
Socket* output_socket = nullptr;
|
||||
|
||||
if (node->m_socket_accessor) {
|
||||
output_socket =
|
||||
node->m_socket_accessor->GetOutputSocket(output_socket_name.c_str());
|
||||
if (node->m_virtual_socket_accessor) {
|
||||
output_socket = node->m_virtual_socket_accessor->GetOutputSocket(
|
||||
output_socket_name.c_str());
|
||||
}
|
||||
|
||||
if (output_socket == nullptr && node->m_node_type_name == "BlendTree") {
|
||||
@ -503,8 +502,7 @@ Socket* BlendTreeResource::GetNodeOutputSocket(
|
||||
const BlendTreeResource& blend_tree_resource =
|
||||
graph_resource->m_blend_tree_resource;
|
||||
output_socket =
|
||||
blend_tree_resource.GetGraphOutputNode()
|
||||
->m_socket_accessor->GetInputSocket(output_socket_name.c_str());
|
||||
blend_tree_resource.GetGraphOutputSocket(output_socket_name.c_str());
|
||||
}
|
||||
|
||||
return output_socket;
|
||||
@ -515,16 +513,16 @@ const Socket* BlendTreeResource::GetNodeOutputSocketByIndex(
|
||||
const size_t socket_output_index) const {
|
||||
const std::vector<Socket>* output_sockets = nullptr;
|
||||
|
||||
if (node->m_socket_accessor) {
|
||||
output_sockets = &node->m_socket_accessor->m_outputs;
|
||||
if (node->m_virtual_socket_accessor) {
|
||||
output_sockets = &node->m_virtual_socket_accessor->m_outputs;
|
||||
} else if (node->m_node_type_name == "BlendTree") {
|
||||
const AnimGraphResource* graph_resource =
|
||||
dynamic_cast<const AnimGraphResource*>(node);
|
||||
const BlendTreeResource& blend_tree_resource =
|
||||
graph_resource->m_blend_tree_resource;
|
||||
|
||||
output_sockets =
|
||||
&blend_tree_resource.GetGraphOutputNode()->m_socket_accessor->m_outputs;
|
||||
output_sockets = &blend_tree_resource.GetGraphOutputNode()
|
||||
->m_virtual_socket_accessor->m_outputs;
|
||||
}
|
||||
|
||||
if (output_sockets != nullptr
|
||||
@ -540,9 +538,9 @@ Socket* BlendTreeResource::GetNodeInputSocket(
|
||||
const std::string& input_socket_name) const {
|
||||
Socket* input_socket = nullptr;
|
||||
|
||||
if (node->m_socket_accessor) {
|
||||
input_socket =
|
||||
node->m_socket_accessor->GetInputSocket(input_socket_name.c_str());
|
||||
if (node->m_virtual_socket_accessor) {
|
||||
input_socket = node->m_virtual_socket_accessor->GetInputSocket(
|
||||
input_socket_name.c_str());
|
||||
}
|
||||
|
||||
if (input_socket == nullptr && node->m_node_type_name == "BlendTree") {
|
||||
@ -551,8 +549,7 @@ Socket* BlendTreeResource::GetNodeInputSocket(
|
||||
const BlendTreeResource& blend_tree_resource =
|
||||
graph_resource->m_blend_tree_resource;
|
||||
input_socket =
|
||||
blend_tree_resource.GetGraphInputNode()
|
||||
->m_socket_accessor->GetOutputSocket(input_socket_name.c_str());
|
||||
blend_tree_resource.GetGraphInputSocket(input_socket_name.c_str());
|
||||
}
|
||||
|
||||
return input_socket;
|
||||
@ -563,16 +560,16 @@ const Socket* BlendTreeResource::GetNodeInputSocketByIndex(
|
||||
const size_t socket_input_index) const {
|
||||
const std::vector<Socket>* output_sockets = nullptr;
|
||||
|
||||
if (node->m_socket_accessor) {
|
||||
output_sockets = &node->m_socket_accessor->m_inputs;
|
||||
if (node->m_virtual_socket_accessor) {
|
||||
output_sockets = &node->m_virtual_socket_accessor->m_inputs;
|
||||
} else if (node->m_node_type_name == "BlendTree") {
|
||||
const AnimGraphResource* graph_resource =
|
||||
dynamic_cast<const AnimGraphResource*>(node);
|
||||
const BlendTreeResource& blend_tree_resource =
|
||||
graph_resource->m_blend_tree_resource;
|
||||
|
||||
output_sockets =
|
||||
&blend_tree_resource.GetGraphOutputNode()->m_socket_accessor->m_outputs;
|
||||
output_sockets = &blend_tree_resource.GetGraphOutputNode()
|
||||
->m_virtual_socket_accessor->m_outputs;
|
||||
}
|
||||
|
||||
if (output_sockets != nullptr
|
||||
@ -585,8 +582,8 @@ const Socket* BlendTreeResource::GetNodeInputSocketByIndex(
|
||||
|
||||
std::vector<Socket> BlendTreeResource::GetNodeOutputSockets(
|
||||
const AnimNodeResource* node) const {
|
||||
if (node->m_socket_accessor) {
|
||||
return node->m_socket_accessor->m_outputs;
|
||||
if (node->m_virtual_socket_accessor) {
|
||||
return node->m_virtual_socket_accessor->m_outputs;
|
||||
}
|
||||
|
||||
if (node->m_node_type_name == "BlendTree") {
|
||||
@ -595,7 +592,7 @@ std::vector<Socket> BlendTreeResource::GetNodeOutputSockets(
|
||||
const BlendTreeResource& blend_tree_resource =
|
||||
graph_resource->m_blend_tree_resource;
|
||||
return blend_tree_resource.GetGraphOutputNode()
|
||||
->m_socket_accessor->m_inputs;
|
||||
->m_virtual_socket_accessor->m_inputs;
|
||||
}
|
||||
|
||||
return std::vector<Socket>();
|
||||
@ -603,8 +600,8 @@ std::vector<Socket> BlendTreeResource::GetNodeOutputSockets(
|
||||
|
||||
std::vector<Socket> BlendTreeResource::GetNodeInputSockets(
|
||||
const AnimNodeResource* node) const {
|
||||
if (node->m_socket_accessor) {
|
||||
return node->m_socket_accessor->m_inputs;
|
||||
if (node->m_virtual_socket_accessor) {
|
||||
return node->m_virtual_socket_accessor->m_inputs;
|
||||
}
|
||||
|
||||
if (node->m_node_type_name == "BlendTree") {
|
||||
@ -613,7 +610,7 @@ std::vector<Socket> BlendTreeResource::GetNodeInputSockets(
|
||||
const BlendTreeResource& blend_tree_resource =
|
||||
graph_resource->m_blend_tree_resource;
|
||||
return blend_tree_resource.GetGraphInputNode()
|
||||
->m_socket_accessor->m_outputs;
|
||||
->m_virtual_socket_accessor->m_outputs;
|
||||
}
|
||||
|
||||
return std::vector<Socket>();
|
||||
@ -863,9 +860,9 @@ void AnimGraphResource::CreateBlendTreeRuntimeNodeInstances(
|
||||
|
||||
embedded_blend_tree_resource->CreateBlendTreeInstance(
|
||||
*embedded_blend_tree);
|
||||
embedded_blend_tree_resource->m_socket_accessor->m_inputs =
|
||||
embedded_blend_tree_resource->m_virtual_socket_accessor->m_inputs =
|
||||
embedded_blend_tree->m_node_descriptor->m_outputs;
|
||||
embedded_blend_tree_resource->m_socket_accessor->m_outputs =
|
||||
embedded_blend_tree_resource->m_virtual_socket_accessor->m_outputs =
|
||||
embedded_blend_tree->m_node_descriptor->m_inputs;
|
||||
}
|
||||
|
||||
@ -886,9 +883,11 @@ void AnimGraphResource::PrepareBlendTreeIOData(
|
||||
AnimNodeDescriptorFactory("BlendTree", instance.m_nodes[0]);
|
||||
|
||||
instance.m_node_descriptor->m_outputs =
|
||||
m_blend_tree_resource.GetNode(1)->m_socket_accessor->m_outputs;
|
||||
m_blend_tree_resource.GetGraphInputNode()
|
||||
->m_virtual_socket_accessor->m_outputs;
|
||||
instance.m_node_descriptor->m_inputs =
|
||||
m_blend_tree_resource.GetNode(0)->m_socket_accessor->m_inputs;
|
||||
m_blend_tree_resource.GetGraphOutputNode()
|
||||
->m_virtual_socket_accessor->m_inputs;
|
||||
|
||||
//
|
||||
// graph inputs
|
||||
@ -942,8 +941,9 @@ void AnimGraphResource::PrepareBlendTreeIOData(
|
||||
m_blend_tree_resource.GetConnections()) {
|
||||
const AnimNodeResource* source_node =
|
||||
m_blend_tree_resource.GetNode(connection.source_node_index);
|
||||
Socket* source_socket = source_node->m_socket_accessor->GetOutputSocket(
|
||||
connection.source_socket_name.c_str());
|
||||
Socket* source_socket =
|
||||
source_node->m_virtual_socket_accessor->GetOutputSocket(
|
||||
connection.source_socket_name.c_str());
|
||||
|
||||
NodeSocketPair source_socket_pair{source_node, source_socket->m_name};
|
||||
if (node_offset_map.find(source_socket_pair) == node_offset_map.end()) {
|
||||
@ -974,9 +974,10 @@ void AnimGraphResource::CreateBlendTreeConnectionInstances(
|
||||
if (i > 1
|
||||
&& m_blend_tree_resource.GetNode(i)->m_node_type_name == "BlendTree") {
|
||||
instance_node_descriptors[i]->m_inputs =
|
||||
m_blend_tree_resource.GetNode(i)->m_socket_accessor->m_inputs;
|
||||
m_blend_tree_resource.GetNode(i)->m_virtual_socket_accessor->m_inputs;
|
||||
instance_node_descriptors[i]->m_outputs =
|
||||
m_blend_tree_resource.GetNode(i)->m_socket_accessor->m_outputs;
|
||||
m_blend_tree_resource.GetNode(i)
|
||||
->m_virtual_socket_accessor->m_outputs;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1180,7 +1181,7 @@ void AnimGraphResource::SetRuntimeNodeProperties(
|
||||
result.m_nodes[i]);
|
||||
|
||||
std::vector<Socket>& resource_properties =
|
||||
node_resource->m_socket_accessor->m_properties;
|
||||
node_resource->m_virtual_socket_accessor->m_properties;
|
||||
for (const auto& property : resource_properties) {
|
||||
const std::string& name = property.m_name;
|
||||
|
||||
|
@ -12,12 +12,11 @@ struct AnimGraphBlendTree;
|
||||
struct AnimGraphStateMachine;
|
||||
|
||||
struct AnimNodeResource {
|
||||
virtual ~AnimNodeResource() = default;
|
||||
virtual ~AnimNodeResource() { delete m_virtual_socket_accessor; };
|
||||
|
||||
std::string m_name;
|
||||
std::string m_node_type_name;
|
||||
AnimNode* m_anim_node = nullptr;
|
||||
NodeDescriptorBase* m_socket_accessor = nullptr;
|
||||
NodeDescriptorBase* m_virtual_socket_accessor = nullptr;
|
||||
float m_position[2] = {0.f, 0.f};
|
||||
};
|
||||
|
||||
@ -57,9 +56,8 @@ struct BlendTreeResource {
|
||||
|
||||
void CleanupNodes() {
|
||||
for (AnimNodeResource* node_resource : m_nodes) {
|
||||
delete node_resource->m_anim_node;
|
||||
delete node_resource->m_socket_accessor;
|
||||
node_resource->m_socket_accessor = nullptr;
|
||||
delete node_resource->m_virtual_socket_accessor;
|
||||
node_resource->m_virtual_socket_accessor = nullptr;
|
||||
delete node_resource;
|
||||
}
|
||||
|
||||
@ -73,7 +71,7 @@ struct BlendTreeResource {
|
||||
|
||||
AddNode(AnimNodeResourceFactory("BlendTreeSockets"));
|
||||
AnimNodeResource* input_node = GetGraphInputNode();
|
||||
output_node->m_name = "Inputs";
|
||||
input_node->m_name = "Inputs";
|
||||
}
|
||||
|
||||
[[nodiscard]] AnimNodeResource* GetGraphOutputNode() const {
|
||||
@ -82,6 +80,14 @@ struct BlendTreeResource {
|
||||
[[nodiscard]] AnimNodeResource* GetGraphInputNode() const {
|
||||
return m_nodes[1];
|
||||
}
|
||||
Socket* GetGraphOutputSocket(const char* socket_name) const {
|
||||
return GetGraphOutputNode()->m_virtual_socket_accessor->GetInputSocket(
|
||||
socket_name);
|
||||
}
|
||||
Socket* GetGraphInputSocket(const char* socket_name) const {
|
||||
return GetGraphInputNode()->m_virtual_socket_accessor->GetOutputSocket(
|
||||
socket_name);
|
||||
}
|
||||
|
||||
int GetNodeIndex(const AnimNodeResource* node_resource) const {
|
||||
for (size_t i = 0, n = m_nodes.size(); i < n; i++) {
|
||||
@ -192,7 +198,7 @@ struct BlendTreeResource {
|
||||
if (*input.m_reference.ptr_ptr == nullptr) {
|
||||
memcpy(
|
||||
&input.m_value,
|
||||
&m_nodes[i]->m_socket_accessor->m_inputs[j].m_value,
|
||||
&m_nodes[i]->m_virtual_socket_accessor->m_inputs[j].m_value,
|
||||
sizeof(Socket::SocketValue));
|
||||
result.push_back(&input);
|
||||
}
|
||||
@ -264,14 +270,7 @@ struct StateMachineResource {
|
||||
};
|
||||
|
||||
struct AnimGraphResource : AnimNodeResource {
|
||||
virtual ~AnimGraphResource() {
|
||||
Clear();
|
||||
|
||||
if (m_socket_accessor != nullptr) {
|
||||
delete m_socket_accessor;
|
||||
m_socket_accessor = nullptr;
|
||||
}
|
||||
};
|
||||
virtual ~AnimGraphResource() { Clear(); };
|
||||
|
||||
std::string m_graph_type_name;
|
||||
|
||||
@ -300,23 +299,18 @@ struct AnimGraphResource : AnimNodeResource {
|
||||
bool RegisterBlendTreeInputSocket(const Socket& socket) {
|
||||
AnimNodeResource* input_node = m_blend_tree_resource.GetGraphInputNode();
|
||||
|
||||
std::vector<Socket> input_sockets =
|
||||
input_node->m_socket_accessor->m_outputs;
|
||||
std::vector<Socket>::const_iterator iter = std::find_if(
|
||||
input_sockets.begin(),
|
||||
input_sockets.end(),
|
||||
[&socket](const Socket& input_socket) {
|
||||
return socket.m_name == input_socket.m_name;
|
||||
});
|
||||
Socket* input_socket =
|
||||
m_blend_tree_resource.GetGraphInputSocket(socket.m_name.c_str());
|
||||
|
||||
if (iter != input_sockets.end()) {
|
||||
std::cerr << "Error: cannot register input socket as socket with name '"
|
||||
if (input_socket != nullptr) {
|
||||
std::cerr << "Error: cannot register output socket as socket with name '"
|
||||
<< socket.m_name << "' already exists!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
input_node->m_socket_accessor->m_outputs.push_back(socket);
|
||||
m_socket_accessor->m_inputs = input_node->m_socket_accessor->m_outputs;
|
||||
input_node->m_virtual_socket_accessor->m_outputs.push_back(socket);
|
||||
m_virtual_socket_accessor->m_inputs =
|
||||
input_node->m_virtual_socket_accessor->m_outputs;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -334,21 +328,18 @@ struct AnimGraphResource : AnimNodeResource {
|
||||
bool RegisterBlendTreeOutputSocket(const Socket& socket) {
|
||||
AnimNodeResource* output_node = m_blend_tree_resource.GetGraphOutputNode();
|
||||
|
||||
std::vector<Socket> output_sockets =
|
||||
output_node->m_socket_accessor->m_inputs;
|
||||
std::vector<Socket>::const_iterator iter = std::find_if(
|
||||
output_sockets.begin(),
|
||||
output_sockets.end(),
|
||||
[&socket](const Socket& input_socket) {
|
||||
return socket.m_name == input_socket.m_name;
|
||||
});
|
||||
Socket* output_socket =
|
||||
m_blend_tree_resource.GetGraphOutputSocket(socket.m_name.c_str());
|
||||
|
||||
if (iter != output_sockets.end()) {
|
||||
if (output_socket != nullptr) {
|
||||
std::cerr << "Error: cannot register output socket as socket with name '"
|
||||
<< socket.m_name << "' already exists!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
output_node->m_socket_accessor->m_inputs.push_back(socket);
|
||||
m_socket_accessor->m_outputs = output_node->m_socket_accessor->m_inputs;
|
||||
output_node->m_virtual_socket_accessor->m_inputs.push_back(socket);
|
||||
m_virtual_socket_accessor->m_outputs =
|
||||
output_node->m_virtual_socket_accessor->m_inputs;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -385,15 +376,8 @@ static inline AnimNodeResource* AnimNodeResourceFactory(
|
||||
}
|
||||
|
||||
result->m_node_type_name = node_type_name;
|
||||
|
||||
if (node_type_name == "BlendTreeSockets") {
|
||||
result->m_anim_node = AnimNodeFactory("BlendTree");
|
||||
result->m_socket_accessor = new NodeDescriptorBase();
|
||||
} else {
|
||||
result->m_anim_node = AnimNodeFactory(node_type_name);
|
||||
result->m_socket_accessor =
|
||||
AnimNodeDescriptorFactory(node_type_name, result->m_anim_node);
|
||||
}
|
||||
result->m_virtual_socket_accessor =
|
||||
VirtualAnimNodeDescriptorFactory(node_type_name);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -32,12 +32,12 @@ class SimpleAnimSamplerGraphResource {
|
||||
blend_tree_resource->AddNode(AnimNodeResourceFactory("AnimSampler"));
|
||||
walk_node = blend_tree_resource->GetNode(walk_node_index);
|
||||
walk_node->m_name = "WalkAnim";
|
||||
walk_node->m_socket_accessor->SetPropertyValue(
|
||||
walk_node->m_virtual_socket_accessor->SetPropertyValue(
|
||||
"Filename",
|
||||
std::string("media/Walking-loop.ozz"));
|
||||
|
||||
AnimNodeResource* graph_node = blend_tree_resource->GetGraphOutputNode();
|
||||
graph_node->m_socket_accessor->RegisterInput<AnimData>(
|
||||
graph_node->m_virtual_socket_accessor->RegisterInput<AnimData>(
|
||||
"GraphOutput",
|
||||
nullptr);
|
||||
|
||||
@ -81,11 +81,11 @@ class Blend2GraphResource {
|
||||
|
||||
walk_node = blend_tree_resource->GetNode(walk_node_index);
|
||||
walk_node->m_name = "WalkAnim";
|
||||
walk_node->m_socket_accessor->SetPropertyValue(
|
||||
walk_node->m_virtual_socket_accessor->SetPropertyValue(
|
||||
"Filename",
|
||||
std::string("media/Walking-loop.ozz"));
|
||||
run_node = blend_tree_resource->GetNode(run_node_index);
|
||||
run_node->m_socket_accessor->SetPropertyValue(
|
||||
run_node->m_virtual_socket_accessor->SetPropertyValue(
|
||||
"Filename",
|
||||
std::string("media/Running0-loop.ozz"));
|
||||
run_node->m_name = "RunAnim";
|
||||
@ -93,14 +93,16 @@ class Blend2GraphResource {
|
||||
blend_node->m_name = "BlendWalkRun";
|
||||
|
||||
AnimNodeResource* graph_node = blend_tree_resource->GetGraphOutputNode();
|
||||
graph_node->m_socket_accessor->RegisterInput<AnimData>(
|
||||
graph_node->m_virtual_socket_accessor->RegisterInput<AnimData>(
|
||||
"GraphOutput",
|
||||
nullptr);
|
||||
|
||||
REQUIRE(graph_node->m_socket_accessor->m_inputs.size() == 1);
|
||||
REQUIRE(blend_node->m_socket_accessor->GetInputIndex("Input0") == 0);
|
||||
REQUIRE(blend_node->m_socket_accessor->GetInputIndex("Input1") == 1);
|
||||
blend_node->m_socket_accessor->SetInputValue("Weight", 0.123f);
|
||||
REQUIRE(graph_node->m_virtual_socket_accessor->m_inputs.size() == 1);
|
||||
REQUIRE(
|
||||
blend_node->m_virtual_socket_accessor->GetInputIndex("Input0") == 0);
|
||||
REQUIRE(
|
||||
blend_node->m_virtual_socket_accessor->GetInputIndex("Input1") == 1);
|
||||
blend_node->m_virtual_socket_accessor->SetInputValue("Weight", 0.123f);
|
||||
|
||||
blend_tree_resource
|
||||
->ConnectSockets(walk_node, "Output", blend_node, "Input0");
|
||||
@ -152,9 +154,8 @@ class EmbeddedBlendTreeGraphResource {
|
||||
// Setup parent outputs
|
||||
AnimNodeResource* parent_blend_tree_outputs =
|
||||
parent_blend_tree_resource->GetGraphOutputNode();
|
||||
parent_blend_tree_outputs->m_socket_accessor->RegisterInput<AnimData>(
|
||||
"Output",
|
||||
nullptr);
|
||||
parent_blend_tree_outputs->m_virtual_socket_accessor
|
||||
->RegisterInput<AnimData>("Output", nullptr);
|
||||
|
||||
// Parent AnimSampler
|
||||
walk_node_index = parent_blend_tree_resource->AddNode(
|
||||
@ -162,7 +163,7 @@ class EmbeddedBlendTreeGraphResource {
|
||||
|
||||
walk_node_resource = parent_blend_tree_resource->GetNode(walk_node_index);
|
||||
walk_node_resource->m_name = "WalkAnim";
|
||||
walk_node_resource->m_socket_accessor->SetPropertyValue(
|
||||
walk_node_resource->m_virtual_socket_accessor->SetPropertyValue(
|
||||
"Filename",
|
||||
std::string("media/Walking-loop.ozz"));
|
||||
|
||||
@ -181,14 +182,14 @@ class EmbeddedBlendTreeGraphResource {
|
||||
// Embedded: outputs
|
||||
AnimNodeResource* embedded_outputs =
|
||||
embedded_blend_tree_resource->GetGraphOutputNode();
|
||||
embedded_outputs->m_socket_accessor->RegisterInput<AnimData>(
|
||||
embedded_outputs->m_virtual_socket_accessor->RegisterInput<AnimData>(
|
||||
"AnimOutput",
|
||||
nullptr);
|
||||
|
||||
// Embedded: inputs
|
||||
AnimNodeResource* embedded_inputs =
|
||||
embedded_blend_tree_resource->GetGraphInputNode();
|
||||
embedded_inputs->m_socket_accessor->RegisterOutput<AnimData>(
|
||||
embedded_inputs->m_virtual_socket_accessor->RegisterOutput<AnimData>(
|
||||
"AnimInput",
|
||||
nullptr);
|
||||
|
||||
@ -197,7 +198,7 @@ class EmbeddedBlendTreeGraphResource {
|
||||
AnimNodeResourceFactory("SpeedScale"));
|
||||
AnimNodeResource* embedded_speed_scale_resource =
|
||||
embedded_blend_tree_resource->GetNode(embedded_speed_scale_index);
|
||||
embedded_speed_scale_resource->m_socket_accessor->SetInputValue(
|
||||
embedded_speed_scale_resource->m_virtual_socket_accessor->SetInputValue(
|
||||
"SpeedScale",
|
||||
0.1f);
|
||||
|
||||
@ -270,14 +271,13 @@ class EmbeddedTreeBlend2GraphResource {
|
||||
// Setup parent outputs
|
||||
AnimNodeResource* parent_blend_tree_outputs =
|
||||
parent_blend_tree_resource->GetGraphOutputNode();
|
||||
parent_blend_tree_outputs->m_socket_accessor->RegisterInput<AnimData>(
|
||||
"Output",
|
||||
nullptr);
|
||||
parent_blend_tree_outputs->m_virtual_socket_accessor
|
||||
->RegisterInput<AnimData>("Output", nullptr);
|
||||
|
||||
// Setup parent inputs
|
||||
AnimNodeResource* parent_blend_tree_inputs =
|
||||
parent_blend_tree_resource->GetGraphInputNode();
|
||||
parent_blend_tree_inputs->m_socket_accessor->RegisterOutput<float>(
|
||||
parent_blend_tree_inputs->m_virtual_socket_accessor->RegisterOutput<float>(
|
||||
"EmbeddedBlend2Weight",
|
||||
nullptr);
|
||||
|
||||
@ -287,7 +287,7 @@ class EmbeddedTreeBlend2GraphResource {
|
||||
|
||||
walk_node_resource = parent_blend_tree_resource->GetNode(walk_node_index);
|
||||
walk_node_resource->m_name = "WalkAnim";
|
||||
walk_node_resource->m_socket_accessor->SetPropertyValue(
|
||||
walk_node_resource->m_virtual_socket_accessor->SetPropertyValue(
|
||||
"Filename",
|
||||
std::string("media/Walking-loop.ozz"));
|
||||
|
||||
@ -320,14 +320,14 @@ class EmbeddedTreeBlend2GraphResource {
|
||||
// Configure node resources
|
||||
embedded_blend2_node_resource =
|
||||
embedded_blend_tree_resource->GetNode(embedded_blend2_node_index);
|
||||
embedded_blend2_node_resource->m_socket_accessor->SetInputValue(
|
||||
embedded_blend2_node_resource->m_virtual_socket_accessor->SetInputValue(
|
||||
"Weight",
|
||||
0.1f);
|
||||
|
||||
embedded_run_node_resource =
|
||||
embedded_blend_tree_resource->GetNode(embedded_run_node_index);
|
||||
embedded_run_node_resource->m_name = "RunAnim";
|
||||
embedded_run_node_resource->m_socket_accessor->SetPropertyValue(
|
||||
embedded_run_node_resource->m_virtual_socket_accessor->SetPropertyValue(
|
||||
"Filename",
|
||||
std::string("media/RunningSlow-loop.ozz"));
|
||||
|
||||
@ -562,7 +562,7 @@ TEST_CASE("AnimSamplerSpeedScaleGraph", "[AnimGraphResource]") {
|
||||
|
||||
AnimNodeResource* walk_node = blend_tree_resource.GetNode(walk_node_index);
|
||||
walk_node->m_name = "WalkAnim";
|
||||
walk_node->m_socket_accessor->SetPropertyValue(
|
||||
walk_node->m_virtual_socket_accessor->SetPropertyValue(
|
||||
"Filename",
|
||||
std::string("media/Walking-loop.ozz"));
|
||||
|
||||
@ -570,12 +570,12 @@ TEST_CASE("AnimSamplerSpeedScaleGraph", "[AnimGraphResource]") {
|
||||
blend_tree_resource.GetNode(speed_scale_node_index);
|
||||
speed_scale_node->m_name = "SpeedScale";
|
||||
float speed_scale_value = 1.35f;
|
||||
speed_scale_node->m_socket_accessor->SetInputValue(
|
||||
speed_scale_node->m_virtual_socket_accessor->SetInputValue(
|
||||
"SpeedScale",
|
||||
speed_scale_value);
|
||||
|
||||
AnimNodeResource* graph_node = blend_tree_resource.GetGraphOutputNode();
|
||||
graph_node->m_socket_accessor->RegisterInput<AnimData>(
|
||||
graph_node->m_virtual_socket_accessor->RegisterInput<AnimData>(
|
||||
"GraphOutput",
|
||||
nullptr);
|
||||
|
||||
@ -599,7 +599,7 @@ TEST_CASE("AnimSamplerSpeedScaleGraph", "[AnimGraphResource]") {
|
||||
|
||||
Socket* speed_scale_resource_loaded_input =
|
||||
blend_tree_resource_loaded.GetNode(speed_scale_node_index)
|
||||
->m_socket_accessor->GetInputSocket("SpeedScale");
|
||||
->m_virtual_socket_accessor->GetInputSocket("SpeedScale");
|
||||
REQUIRE(speed_scale_resource_loaded_input != nullptr);
|
||||
|
||||
REQUIRE_THAT(
|
||||
@ -725,10 +725,10 @@ TEST_CASE_METHOD(
|
||||
const NodeDescriptor<Blend2Node>* blend2_node_descriptor_loaded =
|
||||
dynamic_cast<NodeDescriptor<Blend2Node>*>(
|
||||
blend_tree_resource_loaded->GetNode(blend_node_index)
|
||||
->m_socket_accessor);
|
||||
->m_virtual_socket_accessor);
|
||||
|
||||
REQUIRE_THAT(
|
||||
blend_node->m_socket_accessor->GetInputValue<float>("Weight"),
|
||||
blend_node->m_virtual_socket_accessor->GetInputValue<float>("Weight"),
|
||||
Catch::Matchers::WithinAbs(
|
||||
blend2_node_descriptor_loaded->GetInputValue<float>("Weight"),
|
||||
0.01));
|
||||
@ -852,16 +852,16 @@ TEST_CASE("ResourceSaveLoadMathGraphInputs", "[AnimGraphResource]") {
|
||||
|
||||
AnimNodeResource* graph_output_node =
|
||||
blend_tree_resource.GetGraphOutputNode();
|
||||
graph_output_node->m_socket_accessor->RegisterInput<float>(
|
||||
graph_output_node->m_virtual_socket_accessor->RegisterInput<float>(
|
||||
"GraphFloatOutput",
|
||||
nullptr);
|
||||
graph_output_node->m_socket_accessor->RegisterInput<Vec3>(
|
||||
graph_output_node->m_virtual_socket_accessor->RegisterInput<Vec3>(
|
||||
"GraphVec3Output",
|
||||
nullptr);
|
||||
|
||||
AnimNodeResource* graph_input_node_resource =
|
||||
blend_tree_resource.GetGraphInputNode();
|
||||
graph_input_node_resource->m_socket_accessor->RegisterOutput<float>(
|
||||
graph_input_node_resource->m_virtual_socket_accessor->RegisterOutput<float>(
|
||||
"GraphFloatInput",
|
||||
nullptr);
|
||||
|
||||
@ -914,24 +914,26 @@ TEST_CASE("ResourceSaveLoadMathGraphInputs", "[AnimGraphResource]") {
|
||||
|
||||
THEN("Graph inputs and outputs must be in loaded resource as well.") {
|
||||
REQUIRE(
|
||||
graph_output_node->m_socket_accessor->m_inputs.size()
|
||||
== graph_loaded_output_node->m_socket_accessor->m_inputs.size());
|
||||
graph_output_node->m_virtual_socket_accessor->m_inputs.size()
|
||||
== graph_loaded_output_node->m_virtual_socket_accessor->m_inputs
|
||||
.size());
|
||||
|
||||
REQUIRE(
|
||||
graph_input_node_resource->m_socket_accessor->m_outputs.size()
|
||||
== graph_loaded_input_node->m_socket_accessor->m_outputs.size());
|
||||
graph_input_node_resource->m_virtual_socket_accessor->m_outputs.size()
|
||||
== graph_loaded_input_node->m_virtual_socket_accessor->m_outputs
|
||||
.size());
|
||||
|
||||
REQUIRE(
|
||||
graph_loaded_input_node->m_socket_accessor->GetOutputSocket(
|
||||
graph_loaded_input_node->m_virtual_socket_accessor->GetOutputSocket(
|
||||
"GraphFloatInput")
|
||||
!= nullptr);
|
||||
|
||||
REQUIRE(
|
||||
graph_loaded_output_node->m_socket_accessor->GetInputSocket(
|
||||
graph_loaded_output_node->m_virtual_socket_accessor->GetInputSocket(
|
||||
"GraphFloatOutput")
|
||||
!= nullptr);
|
||||
REQUIRE(
|
||||
graph_loaded_output_node->m_socket_accessor->GetInputSocket(
|
||||
graph_loaded_output_node->m_virtual_socket_accessor->GetInputSocket(
|
||||
"GraphVec3Output")
|
||||
!= nullptr);
|
||||
|
||||
@ -1012,18 +1014,18 @@ TEST_CASE("SimpleMathEvaluations", "[AnimGraphResource]") {
|
||||
AnimNodeResource* graph_output_node =
|
||||
blend_tree_resource.GetGraphOutputNode();
|
||||
|
||||
graph_output_node->m_socket_accessor->RegisterInput<float>(
|
||||
graph_output_node->m_virtual_socket_accessor->RegisterInput<float>(
|
||||
"GraphFloat0Output",
|
||||
nullptr);
|
||||
graph_output_node->m_socket_accessor->RegisterInput<float>(
|
||||
graph_output_node->m_virtual_socket_accessor->RegisterInput<float>(
|
||||
"GraphFloat1Output",
|
||||
nullptr);
|
||||
graph_output_node->m_socket_accessor->RegisterInput<float>(
|
||||
graph_output_node->m_virtual_socket_accessor->RegisterInput<float>(
|
||||
"GraphFloat2Output",
|
||||
nullptr);
|
||||
|
||||
AnimNodeResource* graph_input_node = blend_tree_resource.GetGraphInputNode();
|
||||
graph_input_node->m_socket_accessor->RegisterOutput<float>(
|
||||
graph_input_node->m_virtual_socket_accessor->RegisterOutput<float>(
|
||||
"GraphFloatInput",
|
||||
nullptr);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user