// // Created by martin on 17.03.24. // #ifndef ANIMTESTBED_ANIMGRAPHRESOURCE_H #define ANIMTESTBED_ANIMGRAPHRESOURCE_H #include "AnimGraph.h" #include "AnimGraphNodes.h" #include "3rdparty/json/json.hpp" struct AnimGraphBlendTree; struct AnimGraphStateMachine; struct AnimNodeResource { std::string m_name; std::string m_type_name; AnimNode* m_anim_node = nullptr; NodeDescriptorBase* m_socket_accessor = nullptr; float m_position[2] = {0.f, 0.f}; }; static inline AnimNodeResource AnimNodeResourceFactory( const std::string& node_type_name) { AnimNodeResource result; result.m_type_name = node_type_name; result.m_anim_node = AnimNodeFactory(node_type_name); result.m_socket_accessor = AnimNodeDescriptorFactory(node_type_name, result.m_anim_node); return result; } struct BlendTreeConnectionResource { size_t source_node_index = -1; std::string source_socket_name; size_t target_node_index = -1; std::string target_socket_name; }; struct BlendTreeResource { std::vector m_nodes; std::vector m_connections; void Reset() { m_nodes.clear(); m_connections.clear(); } void InitGraphConnectors() { m_nodes.push_back(AnimNodeResourceFactory("BlendTree")); m_nodes[0].m_name = "Outputs"; m_nodes.push_back(AnimNodeResourceFactory("BlendTree")); m_nodes[1].m_name = "Inputs"; } AnimNodeResource& GetGraphOutputNode() { return m_nodes[0]; } AnimNodeResource& GetGraphInputNode() { return m_nodes[1]; } 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; } } return -1; } bool ConnectSockets ( const AnimNodeResource& source_node, const std::string& source_socket_name, const AnimNodeResource& target_node, const std::string& target_socket_name) { size_t source_node_index = GetNodeIndex(source_node); size_t target_node_index = GetNodeIndex(target_node); if (source_node_index >= m_nodes.size() || target_node_index >= m_nodes.size()) { std::cerr << "Cannot connect nodes: could not find nodes." << std::endl; return false; } Socket* source_socket = source_node.m_socket_accessor->GetOutputSocket(source_socket_name.c_str()); Socket* target_socket = target_node.m_socket_accessor->GetInputSocket(target_socket_name.c_str()); if (source_socket == nullptr || target_socket == nullptr) { std::cerr << "Cannot connect nodes: could not find sockets." << std::endl; return false; } BlendTreeConnectionResource connection; connection.source_node_index = source_node_index; connection.source_socket_name = source_socket_name; connection.target_node_index = target_node_index; connection.target_socket_name = target_socket_name; m_connections.push_back(connection); return true; } std::vector GetConstantNodeInputs( std::vector& instance_node_descriptors) const { std::vector result; for (size_t i = 0; i < m_nodes.size(); i++) { for (size_t j = 0, num_inputs = instance_node_descriptors[i]->m_inputs.size(); j < num_inputs; j++) { Socket& input = instance_node_descriptors[i]->m_inputs[j]; if (*input.m_reference.ptr_ptr == nullptr) { memcpy(&input.m_value, &m_nodes[i].m_socket_accessor->m_inputs[j].m_value, sizeof(Socket::SocketValue)); result.push_back(&input); } } } return result; } }; struct StateMachineTransitionResources { size_t source_state_index = -1; size_t target_state_index = -1; float blend_time = 0.f; bool sync_blend = false; }; struct StateMachineResource { std::vector m_states; std::vector m_transitions; }; struct AnimGraphResource { std::string m_type; std::string m_name; BlendTreeResource m_blend_tree_resource; StateMachineResource m_state_machine_resource; bool SaveToFile(const char* filename) const; bool LoadFromFile(const char* filename); void CreateBlendTreeInstance(AnimGraphBlendTree& result) const; void CreateStateMachineInstance(AnimGraphStateMachine& result) const; private: // BlendTree bool SaveBlendTreeResourceToFile(const char* filename) const; bool LoadBlendTreeResourceFromJson(nlohmann::json const& json_data); void CreateBlendTreeRuntimeNodeInstances(AnimGraphBlendTree& result) const; void PrepareBlendTreeIOData(AnimGraphBlendTree& instance) const; void SetRuntimeNodeProperties(AnimGraphBlendTree& result) const; bool SaveStateMachineResourceToFile(const char* filename) const; bool LoadStateMachineResourceFromJson(nlohmann::json const& json_data); }; #endif //ANIMTESTBED_ANIMGRAPHRESOURCE_H