Improve the look of material nodes
This commit is contained in:
parent
572388c6c5
commit
e53206e906
3 changed files with 83 additions and 21 deletions
|
@ -136,7 +136,6 @@ public:
|
|||
}
|
||||
|
||||
float x = 0.0f, y = 0.0f;
|
||||
float width = 150.0f, height = 75.0f;
|
||||
};
|
||||
|
||||
class MaterialOutput : public MaterialNode {
|
||||
|
|
|
@ -284,8 +284,6 @@ std::unique_ptr<Material> 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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Reference in a new issue