From e53206e906fd203ec787df757ccfa8295167a78c Mon Sep 17 00:00:00 2001 From: redstrate <54911369+redstrate@users.noreply.github.com> Date: Mon, 8 Feb 2021 20:21:42 -0500 Subject: [PATCH] Improve the look of material nodes --- engine/asset/include/material_nodes.hpp | 1 - engine/asset/src/asset.cpp | 6 +- tools/editor/src/materialeditor.cpp | 97 +++++++++++++++++++++---- 3 files changed, 83 insertions(+), 21 deletions(-) diff --git a/engine/asset/include/material_nodes.hpp b/engine/asset/include/material_nodes.hpp index a3f31c1..308a5b8 100644 --- a/engine/asset/include/material_nodes.hpp +++ b/engine/asset/include/material_nodes.hpp @@ -136,7 +136,6 @@ public: } float x = 0.0f, y = 0.0f; - float width = 150.0f, height = 75.0f; }; class MaterialOutput : public MaterialNode { diff --git a/engine/asset/src/asset.cpp b/engine/asset/src/asset.cpp index f201d19..622d5b6 100644 --- a/engine/asset/src/asset.cpp +++ b/engine/asset/src/asset.cpp @@ -284,8 +284,6 @@ std::unique_ptr load_material(const file::Path path) { n->id = node["id"]; n->x = node["x"]; n->y = node["y"]; - n->width = node["width"]; - n->height = node["height"]; for(auto& property : node["properties"]) { for(auto& p : n->properties) { @@ -352,9 +350,7 @@ void save_material(Material* material, const file::Path path) { n["id"] = node->id; n["x"] = node->x; n["y"] = node->y; - n["width"] = node->width; - n["height"] = node->height; - + for(auto property : node->properties) { nlohmann::json p; p["name"] = property.name; diff --git a/tools/editor/src/materialeditor.cpp b/tools/editor/src/materialeditor.cpp index 4e226d0..7ceb0ec 100755 --- a/tools/editor/src/materialeditor.cpp +++ b/tools/editor/src/materialeditor.cpp @@ -18,20 +18,74 @@ Scene* MaterialEditor::get_scene() const { return scene; } -ImRect get_window_rect(MaterialNode& node) { - auto pos = ImGui::GetCursorScreenPos(); +const float node_margin = 5.0f; +const float node_margin_2 = node_margin * 2; +const float property_width = 150.0f; + +const auto calc_text_size = [](float& max_text_size, const std::string_view name) { + auto size = ImGui::CalcTextSize(name.data()); + if(size.x > max_text_size) + max_text_size = size.x; +}; + +float get_input_margin(MaterialNode& node) { + float width = 0.0f; - return ImRect(ImVec2(pos.x + node.x, pos.y + node.y), ImVec2(pos.x + node.x + node.width, pos.y + node.y + node.height)); + float max_input_text_size = 0.0f; + for(auto input : node.inputs) { + calc_text_size(max_input_text_size, input.name); + } + + // account for connection circle size + if(!node.inputs.empty()) + width += 20.0f; + + return width; +} + +float get_width(MaterialNode& node) { + const float max_input_text_size = get_input_margin(node); + + float max_output_text_size = 0.0f; + for(auto output : node.outputs) { + calc_text_size(max_output_text_size, output.name); + } + + float real_property_width = 0.0f; + if(!node.properties.empty()) + real_property_width = property_width; + + const float width = real_property_width + max_input_text_size + max_output_text_size + 40.0f; + const float title_width = ImGui::CalcTextSize(node.get_name()).x; + + return std::max(width, title_width) + node_margin_2; +} + +float get_height(MaterialNode& node) { + float base_height = 20.0f + node_margin_2; + + const int max_outputs_or_inputs = std::max(node.outputs.size(), node.inputs.size()); + const float input_output_height = max_outputs_or_inputs * 20.0f; + + const float property_height = node.properties.size() * 40.0f; + + return base_height + std::max(input_output_height, property_height); +} + +ImRect get_window_rect(MaterialNode& node) { + const auto pos = ImGui::GetCursorScreenPos(); + + return ImRect(ImVec2(pos.x + node.x, pos.y + node.y), ImVec2(pos.x + node.x + get_width(node), pos.y + node.y + get_height(node))); } ImRect get_input_rect(MaterialNode& node, int pos) { - auto rect = get_window_rect(node); + const auto rect = get_window_rect(node); return ImRect(ImVec2(rect.Min.x, rect.Min.y + 20.0f + (pos * 20.0f)), ImVec2(rect.Min.x + 20.0f, rect.Min.y + 40.0f + (pos * 20.0f))); } ImRect get_output_rect(MaterialNode& node, int pos) { - auto rect = get_window_rect(node); + const auto rect = get_window_rect(node); return ImRect(ImVec2(rect.Max.x - 20.0f, rect.Min.y + 20.0f + (pos * 20.0f)), ImVec2(rect.Max.x, rect.Min.y + 40.0f + (pos * 20.0f))); } @@ -161,12 +215,12 @@ void MaterialEditor::draw(CommonEditor* editor) { draw_list->AddRectFilled(rect.Min, rect.Max, IM_COL32(50, 50, 50, 255)); draw_list->AddRect(rect.Min, rect.Max, IM_COL32(255, 255, 255, 255), 5.0f); - draw_list->AddText(rect.Min, IM_COL32(255, 255, 255, 255), node->get_name()); + draw_list->AddText(ImVec2(rect.Min.x + 5.0f, rect.Min.y + 5.0f), IM_COL32(255, 255, 255, 255), node->get_name()); for(auto [i, input] : utility::enumerate(node->inputs)) { auto input_rect = get_input_rect(*node, i); - draw_list->AddText(input_rect.Min, IM_COL32(255, 255, 255, 255), input.name.c_str()); + draw_list->AddText(ImVec2(input_rect.Min.x + 20.0f, input_rect.Min.y), IM_COL32(255, 255, 255, 255), input.name.c_str()); ImGui::ItemAdd(input_rect, ImGui::GetID(node.get())); @@ -188,7 +242,7 @@ void MaterialEditor::draw(CommonEditor* editor) { changed = true; } - draw_list->AddCircleFilled(input_rect.GetCenter(), 5.0, IM_COL32(255, 0, 0, 255)); + draw_list->AddCircleFilled(input_rect.GetCenter(), 3.0, IM_COL32(255, 255, 255, 255)); if(ImGui::IsItemClicked() && !dragging && !dragging_connector) { dragging_connector = true; @@ -205,9 +259,11 @@ void MaterialEditor::draw(CommonEditor* editor) { for(auto [i, output] : utility::enumerate(node->outputs)) { auto output_rect = get_output_rect(*node, i); - draw_list->AddText(output_rect.Min, IM_COL32(255, 255, 255, 255), output.name.c_str()); + const auto text_size = ImGui::CalcTextSize(output.name.c_str()); - draw_list->AddCircleFilled(output_rect.GetCenter(), 5.0, IM_COL32(255, 0, 0, 255)); + draw_list->AddText(ImVec2(output_rect.Max.x - text_size.x - 20.0f, output_rect.Min.y), IM_COL32(255, 255, 255, 255), output.name.c_str()); + + draw_list->AddCircleFilled(output_rect.GetCenter(), 3.0, IM_COL32(255, 255, 255, 255)); ImGui::ItemAdd(output_rect, ImGui::GetID(node.get())); @@ -248,23 +304,34 @@ void MaterialEditor::draw(CommonEditor* editor) { draw_list->AddLine(output_rect.GetCenter(), ImGui::GetIO().MousePos, IM_COL32(255, 255, 255, 255)); } - ImGui::SetCursorScreenPos(ImVec2(rect.Min.x + 5.0, rect.Min.y + 20.0)); - ImGui::SetNextItemWidth(node->width - 40.0); + const auto input_margin = get_input_margin(*node); + + ImGui::SetNextWindowPos(ImVec2(rect.Min.x + input_margin + node_margin, rect.Min.y + 20.0f)); + + ImGui::BeginChild("test", ImVec2(property_width * 2.0f, 0.0f)); for(auto& property : node->properties) { + ImGui::PushID(property.name.c_str()); + + ImGui::TextDisabled("%s", property.name.c_str()); + switch(property.type) { case DataType::Vector3: - changed |= ImGui::ColorEdit3(property.name.c_str(), property.value.ptr()); + changed |= ImGui::ColorEdit3("", property.value.ptr()); break; case DataType::Float: - changed |= ImGui::DragFloat(property.name.c_str(), &property.float_value); + changed |= ImGui::DragFloat("", &property.float_value); break; case DataType::AssetTexture: - changed |= editor->edit_asset(property.name.c_str(), property.value_tex); + changed |= editor->edit_asset("", property.value_tex); break; } + + ImGui::PopID(); } + ImGui::EndChild(); + for(auto& node : deferred_deletions) { material->delete_node(node); changed = true;