Basic node properties editor.

AnimGraphEditor
Martin Felis 2022-02-18 22:24:19 +01:00
parent 0d0b181ebb
commit ee6a8eb29a
3 changed files with 94 additions and 10 deletions

View File

@ -26,6 +26,52 @@ ImNodesPinShape sGetSocketShapeFromSocketType(const SocketType& socket_type) {
return ImNodesPinShape_Quad; return ImNodesPinShape_Quad;
} }
void AnimGraphEditorRenderSidebar(AnimNodeResource& node_resource) {
ImGui::Text("[%s]", node_resource.m_type_name.c_str());
char node_name_buffer[256];
memset(node_name_buffer, 0, sizeof(node_name_buffer));
strncpy(
node_name_buffer,
node_resource.m_name.c_str(),
std::min(node_resource.m_name.size(), sizeof(node_name_buffer)));
if (ImGui::InputText("Name", node_name_buffer, sizeof(node_name_buffer))) {
node_resource.m_name = node_name_buffer;
}
int num_properties = node_resource.m_socket_accessor->m_properties.size();
for (int i = 0; i < num_properties; i++) {
Socket& property = node_resource.m_socket_accessor->m_properties[i];
if (property.m_type == SocketType::SocketTypeFloat) {
ImGui::SliderFloat(
property.m_name.c_str(),
reinterpret_cast<float*>(property.m_value.ptr),
-100.f,
100.f);
} else if (property.m_type == SocketType::SocketTypeBool) {
ImGui::Checkbox(
property.m_name.c_str(),
reinterpret_cast<bool*>(property.m_value.ptr));
} else if (property.m_type == SocketType::SocketTypeString) {
std::string* property_string =
reinterpret_cast<std::string*>(property.m_value.ptr);
char string_buf[256];
memset(string_buf, 0, sizeof(string_buf));
strncpy(
string_buf,
property_string->c_str(),
std::min(property_string->size(), sizeof(string_buf)));
if (ImGui::InputText(
property.m_name.c_str(),
string_buf,
sizeof(string_buf))) {
(*property_string) = string_buf;
}
}
}
}
void AnimGraphEditorUpdate() { void AnimGraphEditorUpdate() {
static AnimGraphResource graph_resource = AnimGraphResource(); static AnimGraphResource graph_resource = AnimGraphResource();
@ -58,6 +104,11 @@ void AnimGraphEditorUpdate() {
ImGui::EndMenuBar(); ImGui::EndMenuBar();
ImGui::Columns(2);
//
// Node editor canvas
//
ImNodes::BeginNodeEditor(); ImNodes::BeginNodeEditor();
// Popup menu // Popup menu
@ -128,7 +179,8 @@ void AnimGraphEditorUpdate() {
ImColor(255, 255, 255, 255)); ImColor(255, 255, 255, 255));
ImGui::Text(socket.m_name.c_str()); ImGui::Text(socket.m_name.c_str());
ImNodes::PushAttributeFlag(ImNodesAttributeFlags_EnableLinkDetachWithDragClick); ImNodes::PushAttributeFlag(
ImNodesAttributeFlags_EnableLinkDetachWithDragClick);
ImNodes::EndInputAttribute(); ImNodes::EndInputAttribute();
} }
@ -142,19 +194,21 @@ void AnimGraphEditorUpdate() {
sGetSocketShapeFromSocketType(socket.m_type), sGetSocketShapeFromSocketType(socket.m_type),
ImColor(255, 255, 255, 255)); ImColor(255, 255, 255, 255));
ImGui::Text(socket.m_name.c_str()); ImGui::Text(socket.m_name.c_str());
ImNodes::PushAttributeFlag(ImNodesAttributeFlags_EnableLinkDetachWithDragClick); ImNodes::PushAttributeFlag(
ImNodesAttributeFlags_EnableLinkDetachWithDragClick);
ImNodes::EndInputAttribute(); ImNodes::EndInputAttribute();
} }
// Graph output node // Graph output node
if (i == 0) { if (i == 0) {
if (ImGui::Button("+Output")) { if (ImGui::Button("+Output")) {
AnimNodeResource& graph_output_node = graph_resource.getGraphOutputNode(); AnimNodeResource& graph_output_node =
graph_resource.getGraphOutputNode();
static float bla = 0.f; static float bla = 0.f;
std::string socket_name = "Output"; std::string socket_name = "Output";
socket_name += socket_name += std::to_string(
std::to_string(graph_output_node.m_socket_accessor->m_inputs.size()); graph_output_node.m_socket_accessor->m_inputs.size());
graph_output_node.m_socket_accessor->RegisterInput<float>( graph_output_node.m_socket_accessor->RegisterInput<float>(
socket_name, socket_name,
nullptr); nullptr);
@ -165,8 +219,8 @@ void AnimGraphEditorUpdate() {
static float bla = 0.f; static float bla = 0.f;
std::string socket_name = "Input"; std::string socket_name = "Input";
socket_name += socket_name += std::to_string(
std::to_string(graph_input_node.m_socket_accessor->m_outputs.size()); graph_input_node.m_socket_accessor->m_outputs.size());
graph_input_node.m_socket_accessor->RegisterOutput<float>( graph_input_node.m_socket_accessor->RegisterOutput<float>(
socket_name, socket_name,
nullptr); nullptr);
@ -220,6 +274,25 @@ void AnimGraphEditorUpdate() {
// Handle link detachements. // Handle link detachements.
int link_id = 0; int link_id = 0;
if (ImNodes::IsLinkDestroyed(&link_id)) { if (ImNodes::IsLinkDestroyed(&link_id)) {
graph_resource.m_connections.erase(graph_resource.m_connections.begin() + link_id); graph_resource.m_connections.erase(
graph_resource.m_connections.begin() + link_id);
}
int selected_nodes[ImNodes::NumSelectedNodes()];
ImNodes::GetSelectedNodes(selected_nodes);
//
// Sidebar
//
ImGui::NextColumn();
if (ImNodes::NumSelectedNodes() == 1) {
if (selected_nodes[0] < graph_resource.m_nodes.size()) {
AnimNodeResource& selected_node =
graph_resource.m_nodes[selected_nodes[0]];
AnimGraphEditorRenderSidebar(selected_node);
} }
} }
ImGui::Columns(1);
}

View File

@ -144,6 +144,14 @@ AnimGraphConnection sAnimGraphConnectionFromJson(const json& json_node) {
void AnimGraphResource::clear() { void AnimGraphResource::clear() {
m_name = ""; m_name = "";
clearNodes();
m_connections.clear();
initGraphConnectors();
}
void AnimGraphResource::clearNodes() {
for (size_t i = 0; i < m_nodes.size(); i++) { for (size_t i = 0; i < m_nodes.size(); i++) {
delete m_nodes[i].m_socket_accessor; delete m_nodes[i].m_socket_accessor;
m_nodes[i].m_socket_accessor = nullptr; m_nodes[i].m_socket_accessor = nullptr;
@ -151,13 +159,13 @@ void AnimGraphResource::clear() {
m_nodes[i].m_anim_node = nullptr; m_nodes[i].m_anim_node = nullptr;
} }
m_nodes.clear(); m_nodes.clear();
}
void AnimGraphResource::initGraphConnectors() {
m_nodes.push_back(AnimNodeResourceFactory("BlendTree")); m_nodes.push_back(AnimNodeResourceFactory("BlendTree"));
m_nodes[0].m_name = "Outputs"; m_nodes[0].m_name = "Outputs";
m_nodes.push_back(AnimNodeResourceFactory("BlendTree")); m_nodes.push_back(AnimNodeResourceFactory("BlendTree"));
m_nodes[1].m_name = "Inputs"; m_nodes[1].m_name = "Inputs";
m_connections.clear();
} }
bool AnimGraphResource::saveToFile(const char* filename) const { bool AnimGraphResource::saveToFile(const char* filename) const {
@ -220,6 +228,7 @@ bool AnimGraphResource::loadFromFile(const char* filename) {
} }
clear(); clear();
clearNodes();
m_name = json_data["name"]; m_name = json_data["name"];
for (size_t i = 0; i < json_data["nodes"].size(); i++) { for (size_t i = 0; i < json_data["nodes"].size(); i++) {

View File

@ -337,6 +337,8 @@ struct AnimGraphResource {
AnimGraphResource() { clear(); } AnimGraphResource() { clear(); }
void clear(); void clear();
void clearNodes();
void initGraphConnectors();
bool saveToFile(const char* filename) const; bool saveToFile(const char* filename) const;
bool loadFromFile(const char* filename); bool loadFromFile(const char* filename);