From 2ad5684594b5e3f33d321c89a5320c90082c8acc Mon Sep 17 00:00:00 2001 From: Yousef Khadadeh Date: Mon, 30 Mar 2026 18:51:14 +0300 Subject: [PATCH] Fixed multiple segfaults --- src/DrawingProgram/DrawingProgram.cpp | 89 +- .../DrawingProgramSelection.cpp | 34 +- src/DrawingProgram/Tools/BrushTool.cpp | 10 +- src/DrawingProgram/Tools/EditTool.cpp | 6 +- .../Tools/EditTools/BrushEditTool.cpp | 14 +- .../Tools/EditTools/EllipseDrawEditTool.cpp | 44 +- .../Tools/EditTools/ImageEditTool.cpp | 48 +- .../Tools/EditTools/RectDrawEditTool.cpp | 46 +- .../Tools/EditTools/TextBoxEditTool.cpp | 226 ++-- src/DrawingProgram/Tools/EllipseDrawTool.cpp | 18 +- src/DrawingProgram/Tools/EraserTool.cpp | 16 +- src/DrawingProgram/Tools/EyeDropperTool.cpp | 12 +- src/DrawingProgram/Tools/GridModifyTool.cpp | 88 +- src/DrawingProgram/Tools/LassoSelectTool.cpp | 8 +- src/DrawingProgram/Tools/LineDrawTool.cpp | 10 +- src/DrawingProgram/Tools/PanCanvasTool.cpp | 6 +- src/DrawingProgram/Tools/RectDrawTool.cpp | 20 +- src/DrawingProgram/Tools/RectSelectTool.cpp | 8 +- src/DrawingProgram/Tools/ScreenshotTool.cpp | 128 +- src/DrawingProgram/Tools/TextBoxTool.cpp | 6 +- src/DrawingProgram/Tools/ZoomCanvasTool.cpp | 6 +- src/GUIStuff/ElementHelpers/ButtonHelpers.hpp | 28 +- .../ColorPickerItemsHelpers.hpp | 44 +- .../ElementHelpers/NumberSliderHelpers.hpp | 20 +- .../ElementHelpers/RadioButtonHelpers.hpp | 16 +- .../ElementHelpers/ScrollAreaHelpers.cpp | 7 +- .../ElementHelpers/TextBoxHelpers.cpp | 4 + .../ElementHelpers/TextBoxHelpers.hpp | 17 +- src/GUIStuff/Elements/TextBox.impl.hpp | 16 +- src/GUIStuff/GUIManager.cpp | 13 + src/GUIStuff/GUIManager.hpp | 9 +- src/Toolbar.cpp | 1028 +++++++++-------- 32 files changed, 1035 insertions(+), 1010 deletions(-) diff --git a/src/DrawingProgram/DrawingProgram.cpp b/src/DrawingProgram/DrawingProgram.cpp index db22e43..6e70be4 100644 --- a/src/DrawingProgram/DrawingProgram.cpp +++ b/src/DrawingProgram/DrawingProgram.cpp @@ -329,49 +329,50 @@ void DrawingProgram::toolbar_gui() { using namespace ElementHelpers; Toolbar& t = world.main.toolbar; - t.gui.push_id("Drawing Program Toolbar GUI"); - t.gui.element("Drawing Program Toolbar GUI", [&] { - CLAY_AUTO_ID({ - .layout = { - .sizing = {.width = CLAY_SIZING_FIT(0), .height = CLAY_SIZING_FIT(0)}, - .padding = CLAY_PADDING_ALL(static_cast(t.io->theme->padding1 / 2)), - .childGap = static_cast(t.io->theme->childGap1 / 2), - .childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_TOP}, - .layoutDirection = CLAY_TOP_TO_BOTTOM - }, - .backgroundColor = convert_vec4(t.io->theme->backColor1), - .cornerRadius = CLAY_CORNER_RADIUS(t.io->theme->windowCorners1) - }) { + t.gui.new_id("Drawing Program Toolbar GUI", [&] { + t.gui.element("Drawing Program Toolbar GUI", [&] { + CLAY_AUTO_ID({ + .layout = { + .sizing = {.width = CLAY_SIZING_FIT(0), .height = CLAY_SIZING_FIT(0)}, + .padding = CLAY_PADDING_ALL(static_cast(t.io->theme->padding1 / 2)), + .childGap = static_cast(t.io->theme->childGap1 / 2), + .childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_TOP}, + .layoutDirection = CLAY_TOP_TO_BOTTOM + }, + .backgroundColor = convert_vec4(t.io->theme->backColor1), + .cornerRadius = CLAY_CORNER_RADIUS(t.io->theme->windowCorners1) + }) { - auto tool_button = [&](const char* id, const std::string& svgPath, DrawingProgramToolType toolType) { - svg_icon_button(t.gui, id, svgPath, { - .drawType = SelectableButton::DrawType::TRANSPARENT_ALL, - .isSelected = drawTool->get_type() == toolType, - .onClick = [&, toolType] { - switch_to_tool(toolType); - } + auto tool_button = [&](const char* id, const std::string& svgPath, DrawingProgramToolType toolType) { + svg_icon_button(t.gui, id, svgPath, { + .drawType = SelectableButton::DrawType::TRANSPARENT_ALL, + .isSelected = drawTool->get_type() == toolType, + .onClick = [&, toolType] { + switch_to_tool(toolType); + } + }); + }; + + tool_button("Brush Toolbar Button", "data/icons/brush.svg", DrawingProgramToolType::BRUSH); + tool_button("Eraser Toolbar Button", "data/icons/eraser.svg", DrawingProgramToolType::ERASER); + tool_button("Line Toolbar Button", "data/icons/line.svg", DrawingProgramToolType::LINE); + tool_button("Text Toolbar Button", "data/icons/text.svg", DrawingProgramToolType::TEXTBOX); + tool_button("Ellipse Toolbar Button", "data/icons/circle.svg", DrawingProgramToolType::ELLIPSE); + tool_button("Rect Toolbar Button", "data/icons/rectangle.svg", DrawingProgramToolType::RECTANGLE); + tool_button("RectSelect Toolbar Button", "data/icons/rectselect.svg", DrawingProgramToolType::RECTSELECT); + tool_button("LassoSelect Toolbar Button", "data/icons/lassoselect.svg", DrawingProgramToolType::LASSOSELECT); + tool_button("Edit Toolbar Button", "data/icons/cursor.svg", DrawingProgramToolType::EDIT); + tool_button("Eyedropper Toolbar Button", "data/icons/eyedropper.svg", DrawingProgramToolType::EYEDROPPER); + tool_button("Zoom Canvas Toolbar Button", "data/icons/zoom.svg", DrawingProgramToolType::ZOOM); + tool_button("Pan Canvas Toolbar Button", "data/icons/hand.svg", DrawingProgramToolType::PAN); + + std::shared_ptr oldRotationAngle = std::make_shared(world.drawData.cam.c.rotation); + t.gui.element("Canvas Rotate Wheel", &world.drawData.cam.c.rotation, [&, oldRotationAngle] { + world.drawData.cam.c.rotate_about(world.drawData.cam.c.from_space(world.main.window.size.cast() * 0.5f), world.drawData.cam.c.rotation - *oldRotationAngle); + *oldRotationAngle = world.drawData.cam.c.rotation; }); - }; - - tool_button("Brush Toolbar Button", "data/icons/brush.svg", DrawingProgramToolType::BRUSH); - tool_button("Eraser Toolbar Button", "data/icons/eraser.svg", DrawingProgramToolType::ERASER); - tool_button("Line Toolbar Button", "data/icons/line.svg", DrawingProgramToolType::LINE); - tool_button("Text Toolbar Button", "data/icons/text.svg", DrawingProgramToolType::TEXTBOX); - tool_button("Ellipse Toolbar Button", "data/icons/circle.svg", DrawingProgramToolType::ELLIPSE); - tool_button("Rect Toolbar Button", "data/icons/rectangle.svg", DrawingProgramToolType::RECTANGLE); - tool_button("RectSelect Toolbar Button", "data/icons/rectselect.svg", DrawingProgramToolType::RECTSELECT); - tool_button("LassoSelect Toolbar Button", "data/icons/lassoselect.svg", DrawingProgramToolType::LASSOSELECT); - tool_button("Edit Toolbar Button", "data/icons/cursor.svg", DrawingProgramToolType::EDIT); - tool_button("Eyedropper Toolbar Button", "data/icons/eyedropper.svg", DrawingProgramToolType::EYEDROPPER); - tool_button("Zoom Canvas Toolbar Button", "data/icons/zoom.svg", DrawingProgramToolType::ZOOM); - tool_button("Pan Canvas Toolbar Button", "data/icons/hand.svg", DrawingProgramToolType::PAN); - - std::shared_ptr oldRotationAngle = std::make_shared(world.drawData.cam.c.rotation); - t.gui.element("Canvas Rotate Wheel", &world.drawData.cam.c.rotation, [&, oldRotationAngle] { - world.drawData.cam.c.rotate_about(world.drawData.cam.c.from_space(world.main.window.size.cast() * 0.5f), world.drawData.cam.c.rotation - *oldRotationAngle); - *oldRotationAngle = world.drawData.cam.c.rotation; - }); - } + } + }); }); } @@ -422,9 +423,9 @@ void DrawingProgram::selection_action_menu(Vector2f popupPos) { void DrawingProgram::right_click_popup_gui(Vector2f popupPos) { Toolbar& t = world.main.toolbar; - t.gui.push_id("Drawing Program right click GUI"); - drawTool->right_click_popup_gui(popupPos); - t.gui.pop_id(); + t.gui.new_id("Drawing Program right click GUI", [&] { + drawTool->right_click_popup_gui(popupPos); + }); } void DrawingProgram::tool_options_gui() { diff --git a/src/DrawingProgram/DrawingProgramSelection.cpp b/src/DrawingProgram/DrawingProgramSelection.cpp index 3e167d8..5d07891 100644 --- a/src/DrawingProgram/DrawingProgramSelection.cpp +++ b/src/DrawingProgram/DrawingProgramSelection.cpp @@ -36,24 +36,24 @@ void DrawingProgramSelection::selection_gui() { using namespace ElementHelpers; auto& t = drawP.world.main.toolbar; - t.gui.push_id("general selection gui"); - text_label(t.gui, "Select from:"); - radio_button_selector(t.gui, "layer selector", &drawP.controls.layerSelector, { - {"Layer being edited", DrawingProgramLayerManager::LayerSelector::LAYER_BEING_EDITED}, - {"All visible layers", DrawingProgramLayerManager::LayerSelector::ALL_VISIBLE_LAYERS} - }); - if(is_something_selected()) { - left_to_right_line_layout(t.gui, [&]() { - //if(t.gui.color_button_big("Stroke Color Button", &strokeColorChangeData.newColor, &strokeColorChangeData.newColor == t.colorRight)) { - // if(strokeColorChangeData.newColor.w() == 0.0f) - // strokeColorChangeData.newColor.w() = 1.0f; - // t.color_selector_right(&strokeColorChangeData.newColor == t.colorRight ? nullptr : &strokeColorChangeData.newColor); - //} - text_label(t.gui, "Stroke Color"); + t.gui.new_id("general selection gui", [&] { + text_label(t.gui, "Select from:"); + radio_button_selector(t.gui, "layer selector", &drawP.controls.layerSelector, { + {"Layer being edited", DrawingProgramLayerManager::LayerSelector::LAYER_BEING_EDITED}, + {"All visible layers", DrawingProgramLayerManager::LayerSelector::ALL_VISIBLE_LAYERS} }); - update_selection_stroke_color(); - } - t.gui.pop_id(); + if(is_something_selected()) { + left_to_right_line_layout(t.gui, [&]() { + //if(t.gui.color_button_big("Stroke Color Button", &strokeColorChangeData.newColor, &strokeColorChangeData.newColor == t.colorRight)) { + // if(strokeColorChangeData.newColor.w() == 0.0f) + // strokeColorChangeData.newColor.w() = 1.0f; + // t.color_selector_right(&strokeColorChangeData.newColor == t.colorRight ? nullptr : &strokeColorChangeData.newColor); + //} + text_label(t.gui, "Stroke Color"); + }); + update_selection_stroke_color(); + } + }); } void DrawingProgramSelection::update_selection_stroke_color() { diff --git a/src/DrawingProgram/Tools/BrushTool.cpp b/src/DrawingProgram/Tools/BrushTool.cpp index 926714b..782e0a3 100644 --- a/src/DrawingProgram/Tools/BrushTool.cpp +++ b/src/DrawingProgram/Tools/BrushTool.cpp @@ -172,11 +172,11 @@ void BrushTool::gui_toolbox() { using namespace ElementHelpers; Toolbar& t = drawP.world.main.toolbar; - t.gui.push_id("brush tool"); - text_label_centered(t.gui, "Brush"); - checkbox_boolean_field(t.gui, "hasroundcaps", "Round Caps", &drawP.world.main.toolConfig.brush.hasRoundCaps); - drawP.world.main.toolConfig.relative_width_gui(drawP, "Size"); - t.gui.pop_id(); + t.gui.new_id("brush tool", [&] { + text_label_centered(t.gui, "Brush"); + checkbox_boolean_field(t.gui, "hasroundcaps", "Round Caps", &drawP.world.main.toolConfig.brush.hasRoundCaps); + drawP.world.main.toolConfig.relative_width_gui(drawP, "Size"); + }); } void BrushTool::right_click_popup_gui(Vector2f popupPos) { diff --git a/src/DrawingProgram/Tools/EditTool.cpp b/src/DrawingProgram/Tools/EditTool.cpp index bde599c..79ecf20 100644 --- a/src/DrawingProgram/Tools/EditTool.cpp +++ b/src/DrawingProgram/Tools/EditTool.cpp @@ -33,9 +33,9 @@ void EditTool::gui_toolbox() { if(objInfoBeingEdited) compEditTool->edit_gui(objInfoBeingEdited); else { - t.gui.push_id("edit tool"); - text_label_centered(t.gui, "Edit"); - t.gui.pop_id(); + t.gui.new_id("edit tool", [&] { + text_label_centered(t.gui, "Edit"); + }); } } diff --git a/src/DrawingProgram/Tools/EditTools/BrushEditTool.cpp b/src/DrawingProgram/Tools/EditTools/BrushEditTool.cpp index 3c4e218..1c50ce6 100644 --- a/src/DrawingProgram/Tools/EditTools/BrushEditTool.cpp +++ b/src/DrawingProgram/Tools/EditTools/BrushEditTool.cpp @@ -16,14 +16,14 @@ void BrushEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) { using namespace ElementHelpers; Toolbar& t = drawP.world.main.toolbar; - t.gui.push_id("edit tool brush"); - text_label_centered(t.gui, "Edit Brush Stroke"); - left_to_right_line_layout(t.gui, [&]() { - //if(t.gui.color_button_big("Outline Color", &a.d.color, &a.d.color == t.colorRight)) - // t.color_selector_right(&a.d.color == t.colorRight ? nullptr : &a.d.color); - text_label(t.gui, "Outline Color"); + t.gui.new_id("edit tool brush", [&] { + text_label_centered(t.gui, "Edit Brush Stroke"); + left_to_right_line_layout(t.gui, [&]() { + //if(t.gui.color_button_big("Outline Color", &a.d.color, &a.d.color == t.colorRight)) + // t.color_selector_right(&a.d.color == t.colorRight ? nullptr : &a.d.color); + text_label(t.gui, "Outline Color"); + }); }); - t.gui.pop_id(); } void BrushEditTool::edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* comp, std::any& prevData) { diff --git a/src/DrawingProgram/Tools/EditTools/EllipseDrawEditTool.cpp b/src/DrawingProgram/Tools/EditTools/EllipseDrawEditTool.cpp index f80ec97..e426fb6 100644 --- a/src/DrawingProgram/Tools/EditTools/EllipseDrawEditTool.cpp +++ b/src/DrawingProgram/Tools/EditTools/EllipseDrawEditTool.cpp @@ -23,29 +23,29 @@ void EllipseDrawEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) { auto& a = static_cast(comp->obj->get_comp()); Toolbar& t = drawP.world.main.toolbar; - t.gui.push_id("edit tool ellipse"); - text_label_centered(t.gui, "Edit Ellipse"); - radio_button_selector(t.gui, "Fill selector", &a.d.fillStrokeMode, { - {"Fill only", 0}, - {"Outline only", 1}, - {"Fill and outline", 2} + t.gui.new_id("edit tool ellipse", [&] { + text_label_centered(t.gui, "Edit Ellipse"); + radio_button_selector(t.gui, "Fill selector", &a.d.fillStrokeMode, { + {"Fill only", 0}, + {"Outline only", 1}, + {"Fill and outline", 2} + }); + if(a.d.fillStrokeMode == 0 || a.d.fillStrokeMode == 2) { + left_to_right_line_layout(t.gui, [&] { + //if(t.gui.color_button_big("Fill Color", &a.d.fillColor, &a.d.fillColor == t.colorRight)) + // t.color_selector_right(&a.d.fillColor == t.colorRight ? nullptr : &a.d.fillColor); + text_label(t.gui, "Fill Color"); + }); + } + if(a.d.fillStrokeMode == 1 || a.d.fillStrokeMode == 2) { + slider_scalar_field(t.gui, "relstrokewidth", "Outline Size", &a.d.strokeWidth, 3.0f, 40.0f); + left_to_right_line_layout(t.gui, [&] { + //if(t.gui.color_button_big("Outline Color", &a.d.strokeColor, &a.d.strokeColor == t.colorRight)) + // t.color_selector_right(&a.d.strokeColor == t.colorRight ? nullptr : &a.d.strokeColor); + text_label(t.gui, "Outline Color"); + }); + } }); - if(a.d.fillStrokeMode == 0 || a.d.fillStrokeMode == 2) { - left_to_right_line_layout(t.gui, [&] { - //if(t.gui.color_button_big("Fill Color", &a.d.fillColor, &a.d.fillColor == t.colorRight)) - // t.color_selector_right(&a.d.fillColor == t.colorRight ? nullptr : &a.d.fillColor); - text_label(t.gui, "Fill Color"); - }); - } - if(a.d.fillStrokeMode == 1 || a.d.fillStrokeMode == 2) { - slider_scalar_field(t.gui, "relstrokewidth", "Outline Size", &a.d.strokeWidth, 3.0f, 40.0f); - left_to_right_line_layout(t.gui, [&] { - //if(t.gui.color_button_big("Outline Color", &a.d.strokeColor, &a.d.strokeColor == t.colorRight)) - // t.color_selector_right(&a.d.strokeColor == t.colorRight ? nullptr : &a.d.strokeColor); - text_label(t.gui, "Outline Color"); - }); - } - t.gui.pop_id(); } void EllipseDrawEditTool::edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* comp, std::any& prevData) { diff --git a/src/DrawingProgram/Tools/EditTools/ImageEditTool.cpp b/src/DrawingProgram/Tools/EditTools/ImageEditTool.cpp index 0b94062..42567a8 100644 --- a/src/DrawingProgram/Tools/EditTools/ImageEditTool.cpp +++ b/src/DrawingProgram/Tools/EditTools/ImageEditTool.cpp @@ -51,29 +51,29 @@ void ImageEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) { ImageCanvasComponent& a = static_cast(comp->obj->get_comp()); Toolbar& t = drawP.world.main.toolbar; - t.gui.push_id("edit tool image"); - text_label_centered(t.gui, "File Properties"); - auto resourceData = drawP.world.netObjMan.get_obj_temporary_ref_from_id(a.d.imageID); + t.gui.new_id("edit tool image", [&] { + text_label_centered(t.gui, "File Properties"); + auto resourceData = drawP.world.netObjMan.get_obj_temporary_ref_from_id(a.d.imageID); - if(resourceData) { - text_label(t.gui, "Name: " + resourceData->name); - text_button(t.gui, "file download", "Download file", { - .wide = true, - .onClick = [&] { - #ifdef __EMSCRIPTEN__ - emscripten_browser_file::download( - resourceData->name, - "application/octet-binary", - *resourceData->data - ); - #endif - t.open_file_selector("Download File", {{"Any File", "*"}}, [resourceData](const std::filesystem::path& p, const auto& e) { - SDL_SaveFile(p.c_str(), resourceData->data->c_str(), resourceData->data->size()); - }, resourceData->name, true); - } - }); - } - else - text_label_centered(t.gui, "Loading resource..."); - t.gui.pop_id(); + if(resourceData) { + text_label(t.gui, "Name: " + resourceData->name); + text_button(t.gui, "file download", "Download file", { + .wide = true, + .onClick = [&] { + #ifdef __EMSCRIPTEN__ + emscripten_browser_file::download( + resourceData->name, + "application/octet-binary", + *resourceData->data + ); + #endif + t.open_file_selector("Download File", {{"Any File", "*"}}, [resourceData](const std::filesystem::path& p, const auto& e) { + SDL_SaveFile(p.c_str(), resourceData->data->c_str(), resourceData->data->size()); + }, resourceData->name, true); + } + }); + } + else + text_label_centered(t.gui, "Loading resource..."); + }); } diff --git a/src/DrawingProgram/Tools/EditTools/RectDrawEditTool.cpp b/src/DrawingProgram/Tools/EditTools/RectDrawEditTool.cpp index 4e67545..80db139 100644 --- a/src/DrawingProgram/Tools/EditTools/RectDrawEditTool.cpp +++ b/src/DrawingProgram/Tools/EditTools/RectDrawEditTool.cpp @@ -19,30 +19,30 @@ void RectDrawEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) { auto& a = static_cast(comp->obj->get_comp()); Toolbar& t = drawP.world.main.toolbar; - t.gui.push_id("edit tool rectangle"); - text_label_centered(t.gui, "Edit Rectangle"); - slider_scalar_field(t.gui, "relradiuswidth", "Corner Radius", &a.d.cornerRadius, 0.0f, 40.0f); - radio_button_selector(t.gui, "Fill selector", &a.d.fillStrokeMode, { - {"Fill only", 0}, - {"Outline only", 1}, - {"Fill and outline", 2} + t.gui.new_id("edit tool rectangle", [&] { + text_label_centered(t.gui, "Edit Rectangle"); + slider_scalar_field(t.gui, "relradiuswidth", "Corner Radius", &a.d.cornerRadius, 0.0f, 40.0f); + radio_button_selector(t.gui, "Fill selector", &a.d.fillStrokeMode, { + {"Fill only", 0}, + {"Outline only", 1}, + {"Fill and outline", 2} + }); + if(a.d.fillStrokeMode == 0 || a.d.fillStrokeMode == 2) { + left_to_right_line_layout(t.gui, [&] { + //if(t.gui.color_button_big("Fill Color", &a.d.fillColor, &a.d.fillColor == t.colorRight)) + // t.color_selector_right(&a.d.fillColor == t.colorRight ? nullptr : &a.d.fillColor); + text_label(t.gui, "Fill Color"); + }); + } + if(a.d.fillStrokeMode == 1 || a.d.fillStrokeMode == 2) { + slider_scalar_field(t.gui, "relstrokewidth", "Outline Size", &a.d.strokeWidth, 3.0f, 40.0f); + left_to_right_line_layout(t.gui, [&] { + //if(t.gui.color_button_big("Outline Color", &a.d.strokeColor, &a.d.strokeColor == t.colorRight)) + // t.color_selector_right(&a.d.strokeColor == t.colorRight ? nullptr : &a.d.strokeColor); + text_label(t.gui, "Outline Color"); + }); + } }); - if(a.d.fillStrokeMode == 0 || a.d.fillStrokeMode == 2) { - left_to_right_line_layout(t.gui, [&] { - //if(t.gui.color_button_big("Fill Color", &a.d.fillColor, &a.d.fillColor == t.colorRight)) - // t.color_selector_right(&a.d.fillColor == t.colorRight ? nullptr : &a.d.fillColor); - text_label(t.gui, "Fill Color"); - }); - } - if(a.d.fillStrokeMode == 1 || a.d.fillStrokeMode == 2) { - slider_scalar_field(t.gui, "relstrokewidth", "Outline Size", &a.d.strokeWidth, 3.0f, 40.0f); - left_to_right_line_layout(t.gui, [&] { - //if(t.gui.color_button_big("Outline Color", &a.d.strokeColor, &a.d.strokeColor == t.colorRight)) - // t.color_selector_right(&a.d.strokeColor == t.colorRight ? nullptr : &a.d.strokeColor); - text_label(t.gui, "Outline Color"); - }); - } - t.gui.pop_id(); } void RectDrawEditTool::edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* comp, std::any& prevData) { diff --git a/src/DrawingProgram/Tools/EditTools/TextBoxEditTool.cpp b/src/DrawingProgram/Tools/EditTools/TextBoxEditTool.cpp index 8ee6129..12eea55 100644 --- a/src/DrawingProgram/Tools/EditTools/TextBoxEditTool.cpp +++ b/src/DrawingProgram/Tools/EditTools/TextBoxEditTool.cpp @@ -33,122 +33,122 @@ void TextBoxEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) { auto& currentMods = *currentModsPtr; - t.gui.push_id("edit tool text"); - text_label_centered(t.gui, "Edit Text"); + t.gui.new_id("edit tool text", [&] { + text_label_centered(t.gui, "Edit Text"); - left_to_right_line_layout(t.gui, [&] { - text_label(t.gui, "Font"); - //if(t.gui.font_picker("font picker", &newFontName)) { - // currentMods[TextStyleModifier::ModifierType::FONT_FAMILIES] = std::make_shared(std::vector{SkString{newFontName.c_str(), newFontName.size()}}); - // add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::FONT_FAMILIES]);}); + left_to_right_line_layout(t.gui, [&] { + text_label(t.gui, "Font"); + //if(t.gui.font_picker("font picker", &newFontName)) { + // currentMods[TextStyleModifier::ModifierType::FONT_FAMILIES] = std::make_shared(std::vector{SkString{newFontName.c_str(), newFontName.size()}}); + // add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::FONT_FAMILIES]);}); + //} + }); + + //left_to_right_line_centered_layout(t.gui, [&] { + // if(svg_icon_button("Bold button", "data/icons/RemixIcon/bold.svg", newIsBold)) { + // newIsBold = !newIsBold; + // currentMods[TextStyleModifier::ModifierType::WEIGHT] = std::make_shared(newIsBold ? SkFontStyle::Weight::kBold_Weight : SkFontStyle::Weight::kNormal_Weight); + // add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::WEIGHT]);}); + // } + + // if(t.gui.svg_icon_button("Italic button", "data/icons/RemixIcon/italic.svg", newIsItalic)) { + // newIsItalic = !newIsItalic; + // currentMods[TextStyleModifier::ModifierType::SLANT] = std::make_shared(newIsItalic ? SkFontStyle::Slant::kItalic_Slant : SkFontStyle::Slant::kUpright_Slant); + // add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::SLANT]);}); + // } + + // bool decorationEdited = false; + // if(t.gui.svg_icon_button("Underline button", "data/icons/RemixIcon/underline.svg", newIsUnderlined)) { + // newIsUnderlined = !newIsUnderlined; + // decorationEdited = true; + // } + // if(t.gui.svg_icon_button("Strikethrough button", "data/icons/RemixIcon/strikethrough.svg", newIsLinethrough)) { + // newIsLinethrough = !newIsLinethrough; + // decorationEdited = true; + // } + // if(t.gui.svg_icon_button("Overline button", "data/icons/RemixIcon/overline.svg", newIsOverline)) { + // newIsOverline = !newIsOverline; + // decorationEdited = true; + // } + // if(decorationEdited) { + // currentMods[TextStyleModifier::ModifierType::DECORATION] = std::make_shared(get_new_decoration_value()); + // add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::DECORATION]);}); + // } + //}); + + //t.gui.left_to_right_line_centered_layout([&]() { + // if(t.gui.svg_icon_button("Align left button", "data/icons/RemixIcon/align-left.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kLeft)) + // add_undo([&](){a.textBox->set_text_alignment_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kLeft);}); + // if(t.gui.svg_icon_button("Align center button", "data/icons/RemixIcon/align-center.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kCenter)) + // add_undo([&](){a.textBox->set_text_alignment_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kCenter);}); + // if(t.gui.svg_icon_button("Align right button", "data/icons/RemixIcon/align-right.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kRight)) + // add_undo([&](){a.textBox->set_text_alignment_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kRight);}); + // if(t.gui.svg_icon_button("Align justify button", "data/icons/RemixIcon/align-justify.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kJustify)) + // add_undo([&](){a.textBox->set_text_alignment_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kJustify);}); + // if(t.gui.svg_icon_button("Text direction left", "data/icons/RemixIcon/text-direction-l.svg", currentPStyle.textDirection == skia::textlayout::TextDirection::kLtr)) + // add_undo([&](){a.textBox->set_text_direction_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextDirection::kLtr);}); + // if(t.gui.svg_icon_button("Text direction right", "data/icons/RemixIcon/text-direction-r.svg", currentPStyle.textDirection == skia::textlayout::TextDirection::kRtl)) + // add_undo([&](){a.textBox->set_text_direction_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextDirection::kRtl);}); + //}); + + //if(t.gui.slider_scalar_field("Font Size Slider", "Font Size", &newFontSize, 3, 100)) { + // hold_undo_data("Font Size", a); + // currentMods[TextStyleModifier::ModifierType::SIZE] = std::make_shared(newFontSize); + // a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::SIZE]); //} + //else + // release_undo_data("Font Size"); + + //// Text color + //t.gui.left_to_right_line_layout([&]() { + // if(t.gui.color_button_big("Text Color", &newTextColor, &newTextColor == t.colorRight)) + // t.color_selector_right(&newTextColor == t.colorRight ? nullptr : &newTextColor); + // t.gui.text_label("Text Color"); + //}); + + //if(&newTextColor == t.colorRight) + // hold_undo_data("Text Color", a); + //else + // release_undo_data("Text Color"); + + //if((&newTextColor == t.colorRight) && t.isUpdatingColorRight) { + // currentMods[TextStyleModifier::ModifierType::COLOR] = std::make_shared(newTextColor); + // a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::COLOR]); + //} + + + + //// Highlight color + //t.gui.left_to_right_line_layout([&]() { + // if(t.gui.color_button_big("Highlight Color", &newHighlightColor, &newHighlightColor == t.colorRight)) { + // if(newHighlightColor.w() == 0.0f) { // Make highlight appear when the button is pressed + // newHighlightColor.w() = 1.0f; + // currentMods[TextStyleModifier::ModifierType::HIGHLIGHT_COLOR] = std::make_shared(newHighlightColor); + // add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::HIGHLIGHT_COLOR]);}); + // } + // t.color_selector_right(&newHighlightColor == t.colorRight ? nullptr : &newHighlightColor); + // } + // if(newHighlightColor.w() != 0.0f) { + // if(t.gui.svg_icon_button("Remove Highlight Color", "data/icons/close.svg")) { + // newHighlightColor = {0.0f, 0.0f, 0.0f, 0.0f}; + // currentMods[TextStyleModifier::ModifierType::HIGHLIGHT_COLOR] = std::make_shared(newHighlightColor); + // add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::HIGHLIGHT_COLOR]);}); + // } + // } + // t.gui.text_label("Highlight Color"); + //}); + + //if(&newHighlightColor == t.colorRight) + // hold_undo_data("Highlight Color", a); + //else + // release_undo_data("Highlight Color"); + + //if((&newHighlightColor == t.colorRight) && t.isUpdatingColorRight) { + // currentMods[TextStyleModifier::ModifierType::HIGHLIGHT_COLOR] = std::make_shared(newHighlightColor); + // a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::HIGHLIGHT_COLOR]); + //} + }); - - //left_to_right_line_centered_layout(t.gui, [&] { - // if(svg_icon_button("Bold button", "data/icons/RemixIcon/bold.svg", newIsBold)) { - // newIsBold = !newIsBold; - // currentMods[TextStyleModifier::ModifierType::WEIGHT] = std::make_shared(newIsBold ? SkFontStyle::Weight::kBold_Weight : SkFontStyle::Weight::kNormal_Weight); - // add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::WEIGHT]);}); - // } - - // if(t.gui.svg_icon_button("Italic button", "data/icons/RemixIcon/italic.svg", newIsItalic)) { - // newIsItalic = !newIsItalic; - // currentMods[TextStyleModifier::ModifierType::SLANT] = std::make_shared(newIsItalic ? SkFontStyle::Slant::kItalic_Slant : SkFontStyle::Slant::kUpright_Slant); - // add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::SLANT]);}); - // } - - // bool decorationEdited = false; - // if(t.gui.svg_icon_button("Underline button", "data/icons/RemixIcon/underline.svg", newIsUnderlined)) { - // newIsUnderlined = !newIsUnderlined; - // decorationEdited = true; - // } - // if(t.gui.svg_icon_button("Strikethrough button", "data/icons/RemixIcon/strikethrough.svg", newIsLinethrough)) { - // newIsLinethrough = !newIsLinethrough; - // decorationEdited = true; - // } - // if(t.gui.svg_icon_button("Overline button", "data/icons/RemixIcon/overline.svg", newIsOverline)) { - // newIsOverline = !newIsOverline; - // decorationEdited = true; - // } - // if(decorationEdited) { - // currentMods[TextStyleModifier::ModifierType::DECORATION] = std::make_shared(get_new_decoration_value()); - // add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::DECORATION]);}); - // } - //}); - - //t.gui.left_to_right_line_centered_layout([&]() { - // if(t.gui.svg_icon_button("Align left button", "data/icons/RemixIcon/align-left.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kLeft)) - // add_undo([&](){a.textBox->set_text_alignment_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kLeft);}); - // if(t.gui.svg_icon_button("Align center button", "data/icons/RemixIcon/align-center.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kCenter)) - // add_undo([&](){a.textBox->set_text_alignment_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kCenter);}); - // if(t.gui.svg_icon_button("Align right button", "data/icons/RemixIcon/align-right.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kRight)) - // add_undo([&](){a.textBox->set_text_alignment_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kRight);}); - // if(t.gui.svg_icon_button("Align justify button", "data/icons/RemixIcon/align-justify.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kJustify)) - // add_undo([&](){a.textBox->set_text_alignment_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kJustify);}); - // if(t.gui.svg_icon_button("Text direction left", "data/icons/RemixIcon/text-direction-l.svg", currentPStyle.textDirection == skia::textlayout::TextDirection::kLtr)) - // add_undo([&](){a.textBox->set_text_direction_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextDirection::kLtr);}); - // if(t.gui.svg_icon_button("Text direction right", "data/icons/RemixIcon/text-direction-r.svg", currentPStyle.textDirection == skia::textlayout::TextDirection::kRtl)) - // add_undo([&](){a.textBox->set_text_direction_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextDirection::kRtl);}); - //}); - - //if(t.gui.slider_scalar_field("Font Size Slider", "Font Size", &newFontSize, 3, 100)) { - // hold_undo_data("Font Size", a); - // currentMods[TextStyleModifier::ModifierType::SIZE] = std::make_shared(newFontSize); - // a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::SIZE]); - //} - //else - // release_undo_data("Font Size"); - - //// Text color - //t.gui.left_to_right_line_layout([&]() { - // if(t.gui.color_button_big("Text Color", &newTextColor, &newTextColor == t.colorRight)) - // t.color_selector_right(&newTextColor == t.colorRight ? nullptr : &newTextColor); - // t.gui.text_label("Text Color"); - //}); - - //if(&newTextColor == t.colorRight) - // hold_undo_data("Text Color", a); - //else - // release_undo_data("Text Color"); - - //if((&newTextColor == t.colorRight) && t.isUpdatingColorRight) { - // currentMods[TextStyleModifier::ModifierType::COLOR] = std::make_shared(newTextColor); - // a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::COLOR]); - //} - - - - //// Highlight color - //t.gui.left_to_right_line_layout([&]() { - // if(t.gui.color_button_big("Highlight Color", &newHighlightColor, &newHighlightColor == t.colorRight)) { - // if(newHighlightColor.w() == 0.0f) { // Make highlight appear when the button is pressed - // newHighlightColor.w() = 1.0f; - // currentMods[TextStyleModifier::ModifierType::HIGHLIGHT_COLOR] = std::make_shared(newHighlightColor); - // add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::HIGHLIGHT_COLOR]);}); - // } - // t.color_selector_right(&newHighlightColor == t.colorRight ? nullptr : &newHighlightColor); - // } - // if(newHighlightColor.w() != 0.0f) { - // if(t.gui.svg_icon_button("Remove Highlight Color", "data/icons/close.svg")) { - // newHighlightColor = {0.0f, 0.0f, 0.0f, 0.0f}; - // currentMods[TextStyleModifier::ModifierType::HIGHLIGHT_COLOR] = std::make_shared(newHighlightColor); - // add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::HIGHLIGHT_COLOR]);}); - // } - // } - // t.gui.text_label("Highlight Color"); - //}); - - //if(&newHighlightColor == t.colorRight) - // hold_undo_data("Highlight Color", a); - //else - // release_undo_data("Highlight Color"); - - //if((&newHighlightColor == t.colorRight) && t.isUpdatingColorRight) { - // currentMods[TextStyleModifier::ModifierType::HIGHLIGHT_COLOR] = std::make_shared(newHighlightColor); - // a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::HIGHLIGHT_COLOR]); - //} - - //t.gui.pop_id(); //if(a.textBox->inputChangedTextBox) // set_styles_at_selection(a); diff --git a/src/DrawingProgram/Tools/EllipseDrawTool.cpp b/src/DrawingProgram/Tools/EllipseDrawTool.cpp index 50a4ad5..70740fd 100644 --- a/src/DrawingProgram/Tools/EllipseDrawTool.cpp +++ b/src/DrawingProgram/Tools/EllipseDrawTool.cpp @@ -27,16 +27,16 @@ void EllipseDrawTool::gui_toolbox() { Toolbar& t = drawP.world.main.toolbar; auto& toolConfig = drawP.world.main.toolConfig; auto& fillStrokeMode = toolConfig.ellipseDraw.fillStrokeMode; - t.gui.push_id("ellipse draw tool"); - text_label_centered(t.gui, "Draw Ellipse"); - radio_button_selector(t.gui, "fill type", &fillStrokeMode, { - {"Fill only", 0}, - {"Outline only", 1}, - {"Fill and Outline", 2} + t.gui.new_id("ellipse draw tool", [&] { + text_label_centered(t.gui, "Draw Ellipse"); + radio_button_selector(t.gui, "fill type", &fillStrokeMode, { + {"Fill only", 0}, + {"Outline only", 1}, + {"Fill and Outline", 2} + }); + if(fillStrokeMode == 1 || fillStrokeMode == 2) + toolConfig.relative_width_gui(drawP, "Outline Size"); }); - if(fillStrokeMode == 1 || fillStrokeMode == 2) - toolConfig.relative_width_gui(drawP, "Outline Size"); - t.gui.pop_id(); } void EllipseDrawTool::input_mouse_button_on_canvas_callback(const InputManager::MouseButtonCallbackArgs& button) { diff --git a/src/DrawingProgram/Tools/EraserTool.cpp b/src/DrawingProgram/Tools/EraserTool.cpp index 5a011eb..74659dc 100644 --- a/src/DrawingProgram/Tools/EraserTool.cpp +++ b/src/DrawingProgram/Tools/EraserTool.cpp @@ -21,15 +21,15 @@ void EraserTool::gui_toolbox() { using namespace ElementHelpers; Toolbar& t = drawP.world.main.toolbar; - t.gui.push_id("eraser tool"); - text_label_centered(t.gui, "Eraser"); - drawP.world.main.toolConfig.relative_width_gui(drawP, "Size"); - text_label(t.gui, "Erase from:"); - radio_button_selector(t.gui, "layer selector", &drawP.controls.layerSelector, { - {"Layer being edited", DrawingProgramLayerManager::LayerSelector::LAYER_BEING_EDITED}, - {"All visible layers", DrawingProgramLayerManager::LayerSelector::ALL_VISIBLE_LAYERS} + t.gui.new_id("eraser tool", [&] { + text_label_centered(t.gui, "Eraser"); + drawP.world.main.toolConfig.relative_width_gui(drawP, "Size"); + text_label(t.gui, "Erase from:"); + radio_button_selector(t.gui, "layer selector", &drawP.controls.layerSelector, { + {"Layer being edited", DrawingProgramLayerManager::LayerSelector::LAYER_BEING_EDITED}, + {"All visible layers", DrawingProgramLayerManager::LayerSelector::ALL_VISIBLE_LAYERS} + }); }); - t.gui.pop_id(); } void EraserTool::right_click_popup_gui(Vector2f popupPos) { diff --git a/src/DrawingProgram/Tools/EyeDropperTool.cpp b/src/DrawingProgram/Tools/EyeDropperTool.cpp index dde0a25..50f1516 100644 --- a/src/DrawingProgram/Tools/EyeDropperTool.cpp +++ b/src/DrawingProgram/Tools/EyeDropperTool.cpp @@ -32,14 +32,14 @@ void EyeDropperTool::gui_toolbox() { Toolbar& t = drawP.world.main.toolbar; auto& selectingStrokeColor = drawP.world.main.toolConfig.eyeDropper.selectingStrokeColor; - t.gui.push_id("Color select tool"); - text_label_centered(t.gui, "Color Select"); + t.gui.new_id("Color select tool", [&] { + text_label_centered(t.gui, "Color Select"); - radio_button_selector(t.gui, "Stroke type", &selectingStrokeColor, { - {"Stroke Color", true}, - {"Fill Color", false} + radio_button_selector(t.gui, "Stroke type", &selectingStrokeColor, { + {"Stroke Color", true}, + {"Fill Color", false} + }); }); - t.gui.pop_id(); } void EyeDropperTool::right_click_popup_gui(Vector2f popupPos) { diff --git a/src/DrawingProgram/Tools/GridModifyTool.cpp b/src/DrawingProgram/Tools/GridModifyTool.cpp index 93b4804..d4d0828 100644 --- a/src/DrawingProgram/Tools/GridModifyTool.cpp +++ b/src/DrawingProgram/Tools/GridModifyTool.cpp @@ -118,51 +118,51 @@ void GridModifyTool::gui_toolbox() { using namespace ElementHelpers; Toolbar& t = drawP.world.main.toolbar; - t.gui.push_id("Grid modify tool"); - text_label_centered(t.gui, "Edit Grid"); - NetworkingObjects::NetObjTemporaryPtr gLock = grid.lock(); - if(gLock) { - WorldGrid& g = *gLock; - input_text_field(t.gui, "grid name", "Name", &g.name); - checkbox_boolean_field(t.gui, "Visible", "Visible", &g.visible); - checkbox_boolean_field(t.gui, "Display in Front", "Display in front of canvas", &g.displayInFront); - size_t typeSelected = static_cast(g.gridType); - std::vector listOfGridTypes = { - "Circle Points", - "Square Points", - "Square Lines", - "Horizontal Lines" - }; - left_to_right_line_layout(t.gui, [&]() { - text_label(t.gui, "Type"); - t.gui.element>("filepicker select type", &typeSelected, listOfGridTypes); - }); - g.gridType = static_cast(typeSelected); - uint32_t sDiv = g.subdivisions; - input_scalar_field(t.gui, "Subdivisions", "Subdivisions", &sDiv, 1, 10); - g.set_subdivisions(sDiv); - bool divOut = g.removeDivisionsOutwards; - checkbox_boolean_field(t.gui, "Subdivide outwards", "Subdivide when zooming out", &divOut); - g.set_remove_divisions_outwards(divOut); - left_to_right_line_layout(t.gui, [&]() { - //if(t.gui.color_button_big("Grid Color", &g.color, &g.color == t.colorRight)) - // t.color_selector_right(&g.color == t.colorRight ? nullptr : &g.color); - text_label(t.gui, "Grid Color"); - }); - bool bounded = g.bounds.has_value(); - bool prevBoundedValue = bounded; - checkbox_boolean_field(t.gui, "Bounded", "Bounded", &bounded); - if(bounded && !prevBoundedValue) { - SCollision::AABB newBounds; - newBounds.min = g.offset - drawP.world.drawData.cam.c.dir_from_space(drawP.world.main.window.size.cast() * 0.3f); - newBounds.max = g.offset + drawP.world.drawData.cam.c.dir_from_space(drawP.world.main.window.size.cast() * 0.3f); - g.bounds = newBounds; + t.gui.new_id("Grid modify tool", [&] { + text_label_centered(t.gui, "Edit Grid"); + NetworkingObjects::NetObjTemporaryPtr gLock = grid.lock(); + if(gLock) { + WorldGrid& g = *gLock; + input_text_field(t.gui, "grid name", "Name", &g.name); + checkbox_boolean_field(t.gui, "Visible", "Visible", &g.visible); + checkbox_boolean_field(t.gui, "Display in Front", "Display in front of canvas", &g.displayInFront); + size_t typeSelected = static_cast(g.gridType); + std::vector listOfGridTypes = { + "Circle Points", + "Square Points", + "Square Lines", + "Horizontal Lines" + }; + left_to_right_line_layout(t.gui, [&]() { + text_label(t.gui, "Type"); + t.gui.element>("filepicker select type", &typeSelected, listOfGridTypes); + }); + g.gridType = static_cast(typeSelected); + uint32_t sDiv = g.subdivisions; + input_scalar_field(t.gui, "Subdivisions", "Subdivisions", &sDiv, 1, 10); + g.set_subdivisions(sDiv); + bool divOut = g.removeDivisionsOutwards; + checkbox_boolean_field(t.gui, "Subdivide outwards", "Subdivide when zooming out", &divOut); + g.set_remove_divisions_outwards(divOut); + left_to_right_line_layout(t.gui, [&]() { + //if(t.gui.color_button_big("Grid Color", &g.color, &g.color == t.colorRight)) + // t.color_selector_right(&g.color == t.colorRight ? nullptr : &g.color); + text_label(t.gui, "Grid Color"); + }); + bool bounded = g.bounds.has_value(); + bool prevBoundedValue = bounded; + checkbox_boolean_field(t.gui, "Bounded", "Bounded", &bounded); + if(bounded && !prevBoundedValue) { + SCollision::AABB newBounds; + newBounds.min = g.offset - drawP.world.drawData.cam.c.dir_from_space(drawP.world.main.window.size.cast() * 0.3f); + newBounds.max = g.offset + drawP.world.drawData.cam.c.dir_from_space(drawP.world.main.window.size.cast() * 0.3f); + g.bounds = newBounds; + } + else if(!bounded && prevBoundedValue) + g.bounds = std::nullopt; + checkbox_boolean_field(t.gui, "Show Coordinates", "Show Coordinates (visible\nwhen canvas isn't rotated)", &g.showCoordinates); } - else if(!bounded && prevBoundedValue) - g.bounds = std::nullopt; - checkbox_boolean_field(t.gui, "Show Coordinates", "Show Coordinates (visible\nwhen canvas isn't rotated)", &g.showCoordinates); - } - t.gui.pop_id(); + }); } void GridModifyTool::right_click_popup_gui(Vector2f popupPos) { diff --git a/src/DrawingProgram/Tools/LassoSelectTool.cpp b/src/DrawingProgram/Tools/LassoSelectTool.cpp index a708ddd..1b524b9 100644 --- a/src/DrawingProgram/Tools/LassoSelectTool.cpp +++ b/src/DrawingProgram/Tools/LassoSelectTool.cpp @@ -42,10 +42,10 @@ DrawingProgramToolType LassoSelectTool::get_type() { void LassoSelectTool::gui_toolbox() { auto& t = drawP.world.main.toolbar; - t.gui.push_id("lasso select tool"); - GUIStuff::ElementHelpers::text_label_centered(t.gui, "Lasso Select"); - drawP.selection.selection_gui(); - t.gui.pop_id(); + t.gui.new_id("lasso select tool", [&] { + GUIStuff::ElementHelpers::text_label_centered(t.gui, "Lasso Select"); + drawP.selection.selection_gui(); + }); } void LassoSelectTool::right_click_popup_gui(Vector2f popupPos) { diff --git a/src/DrawingProgram/Tools/LineDrawTool.cpp b/src/DrawingProgram/Tools/LineDrawTool.cpp index 6b36dea..65f8dd3 100644 --- a/src/DrawingProgram/Tools/LineDrawTool.cpp +++ b/src/DrawingProgram/Tools/LineDrawTool.cpp @@ -24,11 +24,11 @@ void LineDrawTool::gui_toolbox() { using namespace ElementHelpers; Toolbar& t = drawP.world.main.toolbar; auto& toolConfig = drawP.world.main.toolConfig; - t.gui.push_id("rect draw tool"); - text_label_centered(t.gui, "Draw Line"); - toolConfig.relative_width_gui(drawP, "Size"); - checkbox_boolean_field(t.gui, "hasroundcaps", "Round Caps", &toolConfig.lineDraw.hasRoundCaps); - t.gui.pop_id(); + t.gui.new_id("rect draw tool", [&] { + text_label_centered(t.gui, "Draw Line"); + toolConfig.relative_width_gui(drawP, "Size"); + checkbox_boolean_field(t.gui, "hasroundcaps", "Round Caps", &toolConfig.lineDraw.hasRoundCaps); + }); } void LineDrawTool::input_mouse_button_on_canvas_callback(const InputManager::MouseButtonCallbackArgs& button) { diff --git a/src/DrawingProgram/Tools/PanCanvasTool.cpp b/src/DrawingProgram/Tools/PanCanvasTool.cpp index a44530d..b1b7a28 100644 --- a/src/DrawingProgram/Tools/PanCanvasTool.cpp +++ b/src/DrawingProgram/Tools/PanCanvasTool.cpp @@ -18,9 +18,9 @@ DrawingProgramToolType PanCanvasTool::get_type() { void PanCanvasTool::gui_toolbox() { Toolbar& t = drawP.world.main.toolbar; - t.gui.push_id("Pan canvas tool"); - GUIStuff::ElementHelpers::text_label_centered(t.gui, "Pan tool"); - t.gui.pop_id(); + t.gui.new_id("Pan canvas tool", [&] { + GUIStuff::ElementHelpers::text_label_centered(t.gui, "Pan tool"); + }); } void PanCanvasTool::right_click_popup_gui(Vector2f popupPos) { diff --git a/src/DrawingProgram/Tools/RectDrawTool.cpp b/src/DrawingProgram/Tools/RectDrawTool.cpp index 87120ac..9b7c98e 100644 --- a/src/DrawingProgram/Tools/RectDrawTool.cpp +++ b/src/DrawingProgram/Tools/RectDrawTool.cpp @@ -26,17 +26,17 @@ void RectDrawTool::gui_toolbox() { auto& toolConfig = drawP.world.main.toolConfig; auto& fillStrokeMode = toolConfig.rectDraw.fillStrokeMode; auto& relativeRadiusWidth = toolConfig.rectDraw.relativeRadiusWidth; - t.gui.push_id("rect draw tool"); - text_label_centered(t.gui, "Draw Rectangle"); - slider_scalar_field(t.gui, "relradiuswidth", "Corner Radius", &relativeRadiusWidth, 0.0f, 40.0f); - radio_button_selector(t.gui, "fill type", &fillStrokeMode, { - {"Fill only", 0}, - {"Outline only", 1}, - {"Fill and Outline", 2} + t.gui.new_id("rect draw tool", [&] { + text_label_centered(t.gui, "Draw Rectangle"); + slider_scalar_field(t.gui, "relradiuswidth", "Corner Radius", &relativeRadiusWidth, 0.0f, 40.0f); + radio_button_selector(t.gui, "fill type", &fillStrokeMode, { + {"Fill only", 0}, + {"Outline only", 1}, + {"Fill and Outline", 2} + }); + if(fillStrokeMode == 1 || fillStrokeMode == 2) + toolConfig.relative_width_gui(drawP, "Outline Size"); }); - if(fillStrokeMode == 1 || fillStrokeMode == 2) - toolConfig.relative_width_gui(drawP, "Outline Size"); - t.gui.pop_id(); } void RectDrawTool::input_mouse_button_on_canvas_callback(const InputManager::MouseButtonCallbackArgs& button) { diff --git a/src/DrawingProgram/Tools/RectSelectTool.cpp b/src/DrawingProgram/Tools/RectSelectTool.cpp index 99ee184..35b843c 100644 --- a/src/DrawingProgram/Tools/RectSelectTool.cpp +++ b/src/DrawingProgram/Tools/RectSelectTool.cpp @@ -20,10 +20,10 @@ DrawingProgramToolType RectSelectTool::get_type() { void RectSelectTool::gui_toolbox() { auto& t = drawP.world.main.toolbar; - t.gui.push_id("rectangle select tool"); - GUIStuff::ElementHelpers::text_label_centered(t.gui, "Rectangle Select"); - drawP.selection.selection_gui(); - t.gui.pop_id(); + t.gui.new_id("rectangle select tool", [&] { + GUIStuff::ElementHelpers::text_label_centered(t.gui, "Rectangle Select"); + drawP.selection.selection_gui(); + }); } void RectSelectTool::input_key_callback(const InputManager::KeyCallbackArgs& key) { diff --git a/src/DrawingProgram/Tools/ScreenshotTool.cpp b/src/DrawingProgram/Tools/ScreenshotTool.cpp index aa843c8..c998915 100644 --- a/src/DrawingProgram/Tools/ScreenshotTool.cpp +++ b/src/DrawingProgram/Tools/ScreenshotTool.cpp @@ -58,71 +58,71 @@ void ScreenshotTool::gui_toolbox() { Toolbar& t = drawP.world.main.toolbar; auto& screenshotConfig = drawP.world.main.toolConfig.screenshot; - t.gui.push_id("screenshot tool"); - text_label_centered(t.gui, "Screenshot"); - auto oldImgSize = controls.imageSize; - if(controls.selectionMode == ScreenshotControls::SelectionMode::NO_SELECTION) - text_label(t.gui, "Select an area on the canvas..."); - if(controls.selectionMode != ScreenshotControls::SelectionMode::NO_SELECTION && screenshotConfig.selectedType != SCREENSHOT_SVG) - input_scalars_field(t.gui, "Image Size", "Image Size", &controls.imageSize, 2, 0, 999999999); - if(controls.selectionMode == ScreenshotControls::SelectionMode::SELECTION_EXISTS) { - left_to_right_line_layout(t.gui, [&]() { - text_label(t.gui, "Image Type"); - t.gui.element>("image type select", (size_t*)(&screenshotConfig.selectedType), controls.typeSelections); - }); - if(screenshotConfig.selectedType != SCREENSHOT_SVG) - checkbox_boolean_field(t.gui, "Display Grid", "Display Grid", &controls.displayGrid); - else - text_label(t.gui, "Note: Screenshot will ignore blend\nmodes and layer alpha"); - if(screenshotConfig.selectedType != 0) - checkbox_boolean_field(t.gui, "Transparent Background", "Transparent Background", &controls.transparentBackground); - if(controls.imageSize.x() != oldImgSize.x()) { - screenshotConfig.setDimensionSize = controls.imageSize.x(); - screenshotConfig.setDimensionIsX = true; - controls.imageSize.y() = controls.imageSize.x() * (controls.rectY2 - controls.rectY1) / (controls.rectX2 - controls.rectX1); - } - else if(controls.imageSize.y() != oldImgSize.y()) { - screenshotConfig.setDimensionSize = controls.imageSize.y(); - screenshotConfig.setDimensionIsX = false; - controls.imageSize.x() = controls.imageSize.y() * (controls.rectX2 - controls.rectX1) / (controls.rectY2 - controls.rectY1); - } - text_button(t.gui, "Take Screenshot", "Take Screenshot", { - .wide = true, - .onClick = [&] { - controls.selectionMode = ScreenshotControls::SelectionMode::NO_SELECTION; - #ifdef __EMSCRIPTEN__ - take_screenshot("a" + controls.typeSelections[screenshotConfig.selectedType], screenshotConfig.selectedType); - #else - // We can't actually use the extension from the callback, so we have to set the extension of choice beforehand - Toolbar::ExtensionFilter setExtensionFilter; - switch(screenshotConfig.selectedType) { - case SCREENSHOT_JPG: - setExtensionFilter = {"JPEG", "jpg;jpeg"}; - break; - case SCREENSHOT_PNG: - setExtensionFilter = {"PNG", "png"}; - break; - case SCREENSHOT_WEBP: - setExtensionFilter = {"WEBP", "webp"}; - break; - case SCREENSHOT_SVG: - setExtensionFilter = {"SVG", "svg"}; - break; - } - t.open_file_selector("Export", {setExtensionFilter}, [setExtensionFilter, w = make_weak_ptr(drawP.world.main.world)](const std::filesystem::path& p, const auto& e) { - auto world = w.lock(); - if(world && world->drawProg.drawTool->get_type() == DrawingProgramToolType::SCREENSHOT) { - ScreenshotTool* screenshotTool = static_cast(world->drawProg.drawTool.get()); - screenshotTool->controls.screenshotSavePath = p; - screenshotTool->controls.screenshotSaveType = world->main.toolConfig.screenshot.selectedType; - screenshotTool->controls.setToTakeScreenshot = true; - } - }, "screenshot", true); - #endif + t.gui.new_id("screenshot tool", [&] { + text_label_centered(t.gui, "Screenshot"); + auto oldImgSize = controls.imageSize; + if(controls.selectionMode == ScreenshotControls::SelectionMode::NO_SELECTION) + text_label(t.gui, "Select an area on the canvas..."); + if(controls.selectionMode != ScreenshotControls::SelectionMode::NO_SELECTION && screenshotConfig.selectedType != SCREENSHOT_SVG) + input_scalars_field(t.gui, "Image Size", "Image Size", &controls.imageSize, 2, 0, 999999999); + if(controls.selectionMode == ScreenshotControls::SelectionMode::SELECTION_EXISTS) { + left_to_right_line_layout(t.gui, [&]() { + text_label(t.gui, "Image Type"); + t.gui.element>("image type select", (size_t*)(&screenshotConfig.selectedType), controls.typeSelections); + }); + if(screenshotConfig.selectedType != SCREENSHOT_SVG) + checkbox_boolean_field(t.gui, "Display Grid", "Display Grid", &controls.displayGrid); + else + text_label(t.gui, "Note: Screenshot will ignore blend\nmodes and layer alpha"); + if(screenshotConfig.selectedType != 0) + checkbox_boolean_field(t.gui, "Transparent Background", "Transparent Background", &controls.transparentBackground); + if(controls.imageSize.x() != oldImgSize.x()) { + screenshotConfig.setDimensionSize = controls.imageSize.x(); + screenshotConfig.setDimensionIsX = true; + controls.imageSize.y() = controls.imageSize.x() * (controls.rectY2 - controls.rectY1) / (controls.rectX2 - controls.rectX1); } - }); - } - t.gui.pop_id(); + else if(controls.imageSize.y() != oldImgSize.y()) { + screenshotConfig.setDimensionSize = controls.imageSize.y(); + screenshotConfig.setDimensionIsX = false; + controls.imageSize.x() = controls.imageSize.y() * (controls.rectX2 - controls.rectX1) / (controls.rectY2 - controls.rectY1); + } + text_button(t.gui, "Take Screenshot", "Take Screenshot", { + .wide = true, + .onClick = [&] { + controls.selectionMode = ScreenshotControls::SelectionMode::NO_SELECTION; + #ifdef __EMSCRIPTEN__ + take_screenshot("a" + controls.typeSelections[screenshotConfig.selectedType], screenshotConfig.selectedType); + #else + // We can't actually use the extension from the callback, so we have to set the extension of choice beforehand + Toolbar::ExtensionFilter setExtensionFilter; + switch(screenshotConfig.selectedType) { + case SCREENSHOT_JPG: + setExtensionFilter = {"JPEG", "jpg;jpeg"}; + break; + case SCREENSHOT_PNG: + setExtensionFilter = {"PNG", "png"}; + break; + case SCREENSHOT_WEBP: + setExtensionFilter = {"WEBP", "webp"}; + break; + case SCREENSHOT_SVG: + setExtensionFilter = {"SVG", "svg"}; + break; + } + t.open_file_selector("Export", {setExtensionFilter}, [setExtensionFilter, w = make_weak_ptr(drawP.world.main.world)](const std::filesystem::path& p, const auto& e) { + auto world = w.lock(); + if(world && world->drawProg.drawTool->get_type() == DrawingProgramToolType::SCREENSHOT) { + ScreenshotTool* screenshotTool = static_cast(world->drawProg.drawTool.get()); + screenshotTool->controls.screenshotSavePath = p; + screenshotTool->controls.screenshotSaveType = world->main.toolConfig.screenshot.selectedType; + screenshotTool->controls.setToTakeScreenshot = true; + } + }, "screenshot", true); + #endif + } + }); + } + }); } void ScreenshotTool::right_click_popup_gui(Vector2f popupPos) { diff --git a/src/DrawingProgram/Tools/TextBoxTool.cpp b/src/DrawingProgram/Tools/TextBoxTool.cpp index 2546565..d215e62 100644 --- a/src/DrawingProgram/Tools/TextBoxTool.cpp +++ b/src/DrawingProgram/Tools/TextBoxTool.cpp @@ -23,9 +23,9 @@ DrawingProgramToolType TextBoxTool::get_type() { void TextBoxTool::gui_toolbox() { Toolbar& t = drawP.world.main.toolbar; - t.gui.push_id("textbox tool"); - GUIStuff::ElementHelpers::text_label_centered(t.gui, "Zoom tool"); - t.gui.pop_id(); + t.gui.new_id("textbox tool", [&] { + GUIStuff::ElementHelpers::text_label_centered(t.gui, "Zoom tool"); + }); } void TextBoxTool::input_mouse_button_on_canvas_callback(const InputManager::MouseButtonCallbackArgs& button) { diff --git a/src/DrawingProgram/Tools/ZoomCanvasTool.cpp b/src/DrawingProgram/Tools/ZoomCanvasTool.cpp index dbb507f..cc8d3a6 100644 --- a/src/DrawingProgram/Tools/ZoomCanvasTool.cpp +++ b/src/DrawingProgram/Tools/ZoomCanvasTool.cpp @@ -18,9 +18,9 @@ DrawingProgramToolType ZoomCanvasTool::get_type() { void ZoomCanvasTool::gui_toolbox() { Toolbar& t = drawP.world.main.toolbar; - t.gui.push_id("Zoom canvas tool"); - GUIStuff::ElementHelpers::text_label_centered(t.gui, "Zoom tool"); - t.gui.pop_id(); + t.gui.new_id("Zoom canvas tool", [&] { + GUIStuff::ElementHelpers::text_label_centered(t.gui, "Zoom tool"); + }); } void ZoomCanvasTool::right_click_popup_gui(Vector2f popupPos) { diff --git a/src/GUIStuff/ElementHelpers/ButtonHelpers.hpp b/src/GUIStuff/ElementHelpers/ButtonHelpers.hpp index f79dfe8..3b14bce 100644 --- a/src/GUIStuff/ElementHelpers/ButtonHelpers.hpp +++ b/src/GUIStuff/ElementHelpers/ButtonHelpers.hpp @@ -47,20 +47,20 @@ void text_button_sized(GUIManager& gui, const char* id, std::string_view text, C void svg_icon_button(GUIManager& gui, const char* id, const std::string& svgPath, const SVGButtonOptions& options = {}); template void color_button(GUIManager& gui, const char* id, T* val, const FixedSizeColorButtonOptions& options = {}) { - gui.push_id(id); - SelectableButton::Data d = selectable_button_options_to_data(options); - d.innerContent = [&] (const SelectableButton::InnerContentCallbackParameters&) { - gui.element("color display", [val, hasAlpha = options.hasAlpha] { - if(hasAlpha) - return SkColor4f{(*val)[0], (*val)[1], (*val)[2], 1.0f}; - else - return SkColor4f{(*val)[0], (*val)[1], (*val)[2], (*val)[3]}; - }); - }; - CLAY_AUTO_ID({.layout = {.sizing = {.width = CLAY_SIZING_FIXED(options.size), .height = CLAY_SIZING_FIXED(options.size) } } }) { - gui.element("button", d); - } - gui.pop_id(); + gui.new_id(id, [&] { + SelectableButton::Data d = selectable_button_options_to_data(options); + d.innerContent = [&] (const SelectableButton::InnerContentCallbackParameters&) { + gui.element("color display", [val, hasAlpha = options.hasAlpha] { + if(hasAlpha) + return SkColor4f{(*val)[0], (*val)[1], (*val)[2], 1.0f}; + else + return SkColor4f{(*val)[0], (*val)[1], (*val)[2], (*val)[3]}; + }); + }; + CLAY_AUTO_ID({.layout = {.sizing = {.width = CLAY_SIZING_FIXED(options.size), .height = CLAY_SIZING_FIXED(options.size) } } }) { + gui.element("button", d); + } + }); } }} diff --git a/src/GUIStuff/ElementHelpers/ColorPickerItemsHelpers.hpp b/src/GUIStuff/ElementHelpers/ColorPickerItemsHelpers.hpp index bb27f6a..3bcc8a6 100644 --- a/src/GUIStuff/ElementHelpers/ColorPickerItemsHelpers.hpp +++ b/src/GUIStuff/ElementHelpers/ColorPickerItemsHelpers.hpp @@ -11,29 +11,29 @@ struct ColorPickerItemsOptions { }; template void color_picker_items(GUIManager& gui, const char* id, T* val, const ColorPickerItemsOptions& options = {}) { - gui.push_id(id); - auto fullOnEdit = [&gui, oE = options.onEdit, val]() { - oE(); - gui.set_to_layout(); - }; - gui.element>("c", val, options.hasAlpha, fullOnEdit); - left_to_right_line_layout(gui, [&]() { - text_label(gui, "R"); - input_color_component_255(gui, "r", &(*val)[0], { .onEdit = fullOnEdit }); - text_label(gui, "G"); - input_color_component_255(gui, "g", &(*val)[1], { .onEdit = fullOnEdit }); - text_label(gui, "B"); - input_color_component_255(gui, "b", &(*val)[2], { .onEdit = fullOnEdit }); - if(options.hasAlpha) { - text_label(gui, "A"); - input_color_component_255(gui, "a", &(*val)[3], { .onEdit = fullOnEdit }); - } + gui.new_id(id, [&] { + auto fullOnEdit = [&gui, oE = options.onEdit, val]() { + oE(); + gui.set_to_layout(); + }; + gui.element>("c", val, options.hasAlpha, fullOnEdit); + left_to_right_line_layout(gui, [&]() { + text_label(gui, "R"); + input_color_component_255(gui, "r", &(*val)[0], { .onEdit = fullOnEdit }); + text_label(gui, "G"); + input_color_component_255(gui, "g", &(*val)[1], { .onEdit = fullOnEdit }); + text_label(gui, "B"); + input_color_component_255(gui, "b", &(*val)[2], { .onEdit = fullOnEdit }); + if(options.hasAlpha) { + text_label(gui, "A"); + input_color_component_255(gui, "a", &(*val)[3], { .onEdit = fullOnEdit }); + } + }); + left_to_right_line_layout(gui, [&]() { + text_label(gui, "Hex"); + input_color_hex(gui, "h", val, { .hasAlpha = options.hasAlpha, .onEdit = fullOnEdit }); + }); }); - left_to_right_line_layout(gui, [&]() { - text_label(gui, "Hex"); - input_color_hex(gui, "h", val, { .hasAlpha = options.hasAlpha, .onEdit = fullOnEdit }); - }); - gui.pop_id(); } } } diff --git a/src/GUIStuff/ElementHelpers/NumberSliderHelpers.hpp b/src/GUIStuff/ElementHelpers/NumberSliderHelpers.hpp index 1a6e5f2..f6bc1a3 100644 --- a/src/GUIStuff/ElementHelpers/NumberSliderHelpers.hpp +++ b/src/GUIStuff/ElementHelpers/NumberSliderHelpers.hpp @@ -5,16 +5,16 @@ namespace GUIStuff { namespace ElementHelpers { template void slider_scalar_field(GUIManager& gui, const char* id, std::string_view name, T* val, T min, T max, TextBoxScalarOptions options = {}) { - gui.push_id(id); - options.onEdit = [&, oE = options.onEdit] { - oE(); - gui.set_to_layout(); - }; - left_to_right_line_layout(gui, [&]() { - text_label(gui, name); - input_scalar(gui, "textbox", val, min, max, options); + gui.new_id(id, [&] { + options.onEdit = [&, oE = options.onEdit] { + oE(); + gui.set_to_layout(); + }; + left_to_right_line_layout(gui, [&]() { + text_label(gui, name); + input_scalar(gui, "textbox", val, min, max, options); + }); + gui.element>("slider", val, min, max, options.onEdit); }); - gui.element>("slider", val, min, max, options.onEdit); - gui.pop_id(); } }} diff --git a/src/GUIStuff/ElementHelpers/RadioButtonHelpers.hpp b/src/GUIStuff/ElementHelpers/RadioButtonHelpers.hpp index 46361e8..a7b0b4f 100644 --- a/src/GUIStuff/ElementHelpers/RadioButtonHelpers.hpp +++ b/src/GUIStuff/ElementHelpers/RadioButtonHelpers.hpp @@ -6,14 +6,14 @@ namespace GUIStuff { namespace ElementHelpers { void radio_button_field(GUIManager& gui, const char* id, std::string_view name, const std::function& isTicked, const std::function& onClick); template void radio_button_selector(GUIManager& gui, const char* id, T* data, const std::vector>& options, const std::function& onClick = nullptr) { - gui.push_id(id); - for(size_t i = 0; i < options.size(); i++) { - gui.push_id(i); - auto& option = options[i]; - radio_button_field(gui, "Option", option.first, [data, optionVal = option.second]{ return *data == optionVal; }, [data, optionVal = option.second, onClick]{ *data = optionVal; if(onClick) onClick(); }); - gui.pop_id(); - } - gui.pop_id(); + gui.new_id(id, [&] { + for(size_t i = 0; i < options.size(); i++) { + gui.new_id(i, [&] { + auto& option = options[i]; + radio_button_field(gui, "Option", option.first, [data, optionVal = option.second]{ return *data == optionVal; }, [data, optionVal = option.second, onClick]{ *data = optionVal; if(onClick) onClick(); }); + }); + } + }); } }} diff --git a/src/GUIStuff/ElementHelpers/ScrollAreaHelpers.cpp b/src/GUIStuff/ElementHelpers/ScrollAreaHelpers.cpp index 1cab205..2e655e8 100644 --- a/src/GUIStuff/ElementHelpers/ScrollAreaHelpers.cpp +++ b/src/GUIStuff/ElementHelpers/ScrollAreaHelpers.cpp @@ -25,11 +25,8 @@ void scroll_area_many_entries(GUIManager& gui, const char* id, const ScrollBarMa }) { } } - for(size_t i = startPoint; i < endPoint; i++) { - gui.push_id(i); - options.elementContent(i); - gui.pop_id(); - } + for(size_t i = startPoint; i < endPoint; i++) + gui.new_id(i, [&] { options.elementContent(i); }); if(endPoint != options.entryCount) { CLAY_AUTO_ID({ diff --git a/src/GUIStuff/ElementHelpers/TextBoxHelpers.cpp b/src/GUIStuff/ElementHelpers/TextBoxHelpers.cpp index 60d9730..be784ad 100644 --- a/src/GUIStuff/ElementHelpers/TextBoxHelpers.cpp +++ b/src/GUIStuff/ElementHelpers/TextBoxHelpers.cpp @@ -13,6 +13,7 @@ void input_color_component_255(GUIManager& gui, const char* id, float* val, cons }; TextBoxData d = textbox_options_to_data(options); + d.data = val; d.textInputProps = textInputProps; d.fromStr = [](const std::string& str) { int roundTo255; @@ -41,6 +42,7 @@ void input_text(GUIManager& gui, const char* id, std::string* val, const TextBox }; TextBoxData d = textbox_options_to_data(options); + d.data = val; d.textInputProps = textInputProps; d.fromStr = [](const std::string& a) { return a; @@ -69,6 +71,7 @@ void input_scalar(GUIManager& gui, const char* id, uint8_t* val, uint8_t minVal, }; TextBoxData d = textbox_options_to_data(options); + d.data = val; d.textInputProps = textInputProps; d.fromStr = [minVal, maxVal](const std::string& a) { if(a.empty()) @@ -98,6 +101,7 @@ void input_path(GUIManager& gui, const char* id, std::filesystem::path* val, con }; TextBoxData d = textbox_options_to_data(options); + d.data = val; d.textInputProps = textInputProps; d.fromStr = [fileTypeRestriction = options.fileTypeRestriction](const std::string& a) { std::filesystem::path toRet = std::filesystem::path(std::u8string_view(reinterpret_cast(a.c_str()), a.length())); diff --git a/src/GUIStuff/ElementHelpers/TextBoxHelpers.hpp b/src/GUIStuff/ElementHelpers/TextBoxHelpers.hpp index 9c1ef0c..d6f9317 100644 --- a/src/GUIStuff/ElementHelpers/TextBoxHelpers.hpp +++ b/src/GUIStuff/ElementHelpers/TextBoxHelpers.hpp @@ -67,6 +67,7 @@ template void input_scalar(GUIManager& gui, const char* id, T* val, textInputProps.androidInputType |= InputManager::AndroidInputType::ANDROIDTEXT_TYPE_NUMBER_FLAG_DECIMAL; TextBoxData d = textbox_options_to_data(options); + d.data = val; d.textInputProps = textInputProps; d.fromStr = [minVal, maxVal](const std::string& a) { if(a.empty()) @@ -94,16 +95,13 @@ template void input_scalar(GUIManager& gui, const char* id, T* val, } template void input_scalars_field(GUIManager& gui, const char* id, std::string_view name, TContainer* val, size_t elemCount, T minVal, T maxVal, const TextBoxScalarOptions& options = {}) { - gui.push_id(id); - left_to_right_line_layout(gui, [&]() { - text_label(gui, name); - for(size_t i = 0; i < elemCount; i++) { - gui.push_id(i); - input_scalar(gui, "field", &(*val)[i], minVal, maxVal, options); - gui.pop_id(); - } + gui.new_id(id, [&] { + left_to_right_line_layout(gui, [&]() { + text_label(gui, name); + for(size_t i = 0; i < elemCount; i++) + gui.new_id(i, [&] { input_scalar(gui, "field", &(*val)[i], minVal, maxVal, options); }); + }); }); - gui.pop_id(); } template void input_scalar_field(GUIManager& gui, const char* id, std::string_view name, T* val, T minVal, T maxVal, const TextBoxScalarOptions& options = {}) { @@ -123,6 +121,7 @@ template void input_color_hex(GUIManager& gui, const char* id, T* v }; TextBoxData d = textbox_options_to_data(options); + d.data = val; d.textInputProps = textInputProps; d.fromStr = [hasAlpha = options.hasAlpha](const std::string& a) { T def; diff --git a/src/GUIStuff/Elements/TextBox.impl.hpp b/src/GUIStuff/Elements/TextBox.impl.hpp index ec9ba6a..d01c506 100644 --- a/src/GUIStuff/Elements/TextBox.impl.hpp +++ b/src/GUIStuff/Elements/TextBox.impl.hpp @@ -8,14 +8,6 @@ template TextBox::TextBox(GUIManager& gui): Element(gui) {} template void TextBox::layout(const TextBoxData& userInfo) { auto& io = *gui.io; this->userInfo = userInfo; - textbox->onUserTextEdit = [&] { - if(userInfo.immutable) - cur->pos = cur->selectionBeginPos = cur->selectionEndPos = textbox->insert({0, 0}, userInfo.toStr(*userInfo.data)); - else { - if(update_data() && userInfo.onEdit) - gui.set_post_callback_func(userInfo.onEdit); - } - }; init_textbox(io); CLAY_AUTO_ID({ .layout = { @@ -118,6 +110,14 @@ template void TextBox::init_textbox(UpdateInputData& io) { rect = std::make_shared>(); cur->pos = cur->selectionBeginPos = cur->selectionEndPos = textbox->insert({0, 0}, userInfo.toStr(*userInfo.data)); + textbox->onUserTextEdit = [&] { + if(userInfo.immutable) + cur->pos = cur->selectionBeginPos = cur->selectionEndPos = textbox->insert({0, 0}, userInfo.toStr(*userInfo.data)); + else { + if(update_data() && userInfo.onEdit) + gui.set_post_callback_func(userInfo.onEdit); + } + }; } template bool TextBox::update_data() { diff --git a/src/GUIStuff/GUIManager.cpp b/src/GUIStuff/GUIManager.cpp index c904fd3..7eb96da 100644 --- a/src/GUIStuff/GUIManager.cpp +++ b/src/GUIStuff/GUIManager.cpp @@ -35,6 +35,7 @@ GUIManager::GUIManager() clayArena = Clay_CreateArenaWithCapacityAndMemory(Clay_MinMemorySize(), malloc(Clay_MinMemorySize())); clayInstance = Clay_Initialize(clayArena, Clay_Dimensions(1.0f, 1.0f), (Clay_ErrorHandler)clay_error_handler); Clay_SetMeasureTextFunction(clay_skia_measure_text, this); + setToLayout = true; } Clay_Dimensions GUIManager::clay_skia_measure_text(Clay_StringSlice str, Clay_TextElementConfig* config, void* userData) { @@ -291,6 +292,18 @@ void GUIManager::clay_error_handler(Clay_ErrorData errorData) { Logger::get().log("INFO", "[Clay Error] " + std::string(errorData.errorText.chars)); } +void GUIManager::new_id(const char* id, const std::function& f) { + push_id(id); + f(); + pop_id(); +} + +void GUIManager::new_id(int64_t id, const std::function& f) { + push_id(id); + f(); + pop_id(); +} + void GUIManager::push_id(int64_t id) { idStack.emplace_back(id); } diff --git a/src/GUIStuff/GUIManager.hpp b/src/GUIStuff/GUIManager.hpp index 5bc43f2..7def7e9 100644 --- a/src/GUIStuff/GUIManager.hpp +++ b/src/GUIStuff/GUIManager.hpp @@ -28,9 +28,8 @@ class GUIManager { GUIManagerIDStack idStack; std::unordered_map elements; - void push_id(int64_t id); - void push_id(const char* id); - void pop_id(); + void new_id(const char* id, const std::function& f); + void new_id(int64_t id, const std::function& f); void set_post_callback_func(const std::function& f); @@ -65,6 +64,10 @@ class GUIManager { static void clay_error_handler(Clay_ErrorData errorData); static Clay_Dimensions clay_skia_measure_text(Clay_StringSlice str, Clay_TextElementConfig* config, void* userData); + void push_id(int64_t id); + void push_id(const char* id); + void pop_id(); + std::function postCallbackFunc; Clay_Context* clayInstance; Clay_Arena clayArena; diff --git a/src/Toolbar.cpp b/src/Toolbar.cpp index f3f4225..f370d3c 100644 --- a/src/Toolbar.cpp +++ b/src/Toolbar.cpp @@ -69,6 +69,11 @@ Toolbar::Toolbar(MainProgram& initMain): { io->textTypeface = main.fonts->map["Roboto"]; io->fonts = main.fonts; + io->layoutRun = [&] { + layout_run(); + }; + io->input = &main.input; + gui.io = io; // NOTE: On windows, when the native file picker is open, any call to MakeFromFile fails // So, it's better to load the icons at the beginning of the program so that the icon loading doesn't fail later @@ -412,6 +417,9 @@ void Toolbar::set_config_json(const nlohmann::json& j, VersionNumber version) { void Toolbar::update() { calculate_final_gui_scale(); + io->windowSize = main.window.size.cast(); + io->windowPos = {0, 0}; + gui.layout_if_necessary(); } void Toolbar::layout_run() { @@ -517,90 +525,90 @@ void Toolbar::close_popup_gui() { .cornerRadius = CLAY_CORNER_RADIUS(io->theme->windowCorners1), .floating = {.zIndex = 1, .attachPoints = {.element = CLAY_ATTACH_POINT_CENTER_CENTER, .parent = CLAY_ATTACH_POINT_CENTER_CENTER}, .attachTo = CLAY_ATTACH_TO_PARENT} }) { - gui.push_id("Close single file popup gui"); - text_label(gui, "Files may contain unsaved changes"); - gui.element("close file popup gui scroll area", ScrollArea::Options{ - .scrollVertical = true, - .clipVertical = true, - .showScrollbarY = true, - .innerContent = [&](const ScrollArea::InnerContentParameters&) { - CLAY_AUTO_ID({ - .layout = { - .childGap = io->theme->childGap1, - .childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_TOP}, - .layoutDirection = CLAY_TOP_TO_BOTTOM - } - }) { - size_t i = 0; - for(auto& [w, setToSave] : closePopupData.worldsToClose) { - auto wLock = w.lock(); - CLAY_AUTO_ID({ - .layout = { - .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(0) }, - .padding = CLAY_PADDING_ALL(io->theme->padding1), - .childGap = io->theme->childGap1, - .childAlignment = { .x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER}, - .layoutDirection = CLAY_LEFT_TO_RIGHT - }, - .backgroundColor = convert_vec4(io->theme->backColor2), - .cornerRadius = CLAY_CORNER_RADIUS(io->theme->windowCorners1), - }) { - gui.push_id(i); - checkbox_boolean(gui, "set to save checkbox", &setToSave); + gui.new_id("Close single file popup gui", [&] { + text_label(gui, "Files may contain unsaved changes"); + gui.element("close file popup gui scroll area", ScrollArea::Options{ + .scrollVertical = true, + .clipVertical = true, + .showScrollbarY = true, + .innerContent = [&](const ScrollArea::InnerContentParameters&) { + CLAY_AUTO_ID({ + .layout = { + .childGap = io->theme->childGap1, + .childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_TOP}, + .layoutDirection = CLAY_TOP_TO_BOTTOM + } + }) { + size_t i = 0; + for(auto& [w, setToSave] : closePopupData.worldsToClose) { + auto wLock = w.lock(); CLAY_AUTO_ID({ .layout = { - .sizing = {.width = CLAY_SIZING_FIT(0), .height = CLAY_SIZING_FIT(0) }, - .childGap = 0, + .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(0) }, + .padding = CLAY_PADDING_ALL(io->theme->padding1), + .childGap = io->theme->childGap1, .childAlignment = { .x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER}, - .layoutDirection = CLAY_TOP_TO_BOTTOM - } + .layoutDirection = CLAY_LEFT_TO_RIGHT + }, + .backgroundColor = convert_vec4(io->theme->backColor2), + .cornerRadius = CLAY_CORNER_RADIUS(io->theme->windowCorners1), }) { - text_label(gui, wLock->name); - text_label_light(gui, wLock->filePath.empty() ? "Autosave in " + main.documentsPath.string() : wLock->filePath.string()); + gui.new_id(i, [&] { + checkbox_boolean(gui, "set to save checkbox", &setToSave); + CLAY_AUTO_ID({ + .layout = { + .sizing = {.width = CLAY_SIZING_FIT(0), .height = CLAY_SIZING_FIT(0) }, + .childGap = 0, + .childAlignment = { .x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER}, + .layoutDirection = CLAY_TOP_TO_BOTTOM + } + }) { + text_label(gui, wLock->name); + text_label_light(gui, wLock->filePath.empty() ? "Autosave in " + main.documentsPath.string() : wLock->filePath.string()); + } + }); } - gui.pop_id(); + ++i; } - ++i; } } - } - }); - text_button(gui, "Save", "Save", { - .wide = true, - .onClick = [&] { - for(auto& [w, setToSave] : closePopupData.worldsToClose) { - auto wLock = w.lock(); - if(setToSave) { - if(wLock->filePath.empty()) - wLock->autosave_to_directory(main.documentsPath); - else - wLock->save_to_file(wLock->filePath); + }); + text_button(gui, "Save", "Save", { + .wide = true, + .onClick = [&] { + for(auto& [w, setToSave] : closePopupData.worldsToClose) { + auto wLock = w.lock(); + if(setToSave) { + if(wLock->filePath.empty()) + wLock->autosave_to_directory(main.documentsPath); + else + wLock->save_to_file(wLock->filePath); + } + main.set_tab_to_close(w); } - main.set_tab_to_close(w); + closePopupData.worldsToClose.clear(); + if(closePopupData.closeAppWhenDone) + main.setToQuit = true; } - closePopupData.worldsToClose.clear(); - if(closePopupData.closeAppWhenDone) - main.setToQuit = true; - } + }); + text_button(gui, "Discard All", "Discard All", { + .wide = true, + .onClick = [&] { + for(auto& [w, setToSave] : closePopupData.worldsToClose) + main.set_tab_to_close(w); + closePopupData.worldsToClose.clear(); + if(closePopupData.closeAppWhenDone) + main.setToQuit = true; + } + }); + text_button(gui, "Cancel", "Cancel", { + .wide = true, + .onClick = [&] { + closePopupData.worldsToClose.clear(); + closePopupData.closeAppWhenDone = false; + } + }); }); - text_button(gui, "Discard All", "Discard All", { - .wide = true, - .onClick = [&] { - for(auto& [w, setToSave] : closePopupData.worldsToClose) - main.set_tab_to_close(w); - closePopupData.worldsToClose.clear(); - if(closePopupData.closeAppWhenDone) - main.setToQuit = true; - } - }); - text_button(gui, "Cancel", "Cancel", { - .wide = true, - .onClick = [&] { - closePopupData.worldsToClose.clear(); - closePopupData.closeAppWhenDone = false; - } - }); - gui.pop_id(); } } @@ -651,196 +659,196 @@ void Toolbar::top_toolbar() { .backgroundColor = convert_vec4(io->theme->backColor1), .cornerRadius = CLAY_CORNER_RADIUS(io->theme->windowCorners1) }) { - gui.push_id("menu top toolbar"); - global_log(); - bool menuPopUpJustOpen = false; - bool bookmarkMenuPopUpJustOpen = false; - bool gridMenuPopUpJustOpen = false; - bool layerMenuPopUpJustOpen = false; - auto icon_button_top_toolbar = [&](const char* id, const std::string& svgPath, bool isSelected, const std::function& onClick) { - svg_icon_button(gui, id, svgPath, { - .isSelected = isSelected, - .onClick = onClick - }); - }; - icon_button_top_toolbar("Main Menu Button", "data/icons/menu.svg", menuPopUpOpen, [&] { - if(menuPopUpOpen) - menuPopUpOpen = false; - else { - menuPopUpOpen = true; - menuPopUpJustOpen = true; - } - }); - //std::vector> tabNames; - //for(size_t i = 0; i < main.worlds.size(); i++) { - // auto& w = main.worlds[i]; - // bool shouldAddStarNextToName = w->should_ask_before_closing() && !w->netServer && !w->netClient; - // tabNames.emplace_back(w->netObjMan.is_connected() ? "data/icons/network.svg" : "", w->name + (shouldAddStarNextToName ? "*" : "")); - //} - - //std::optional closedTab; - //gui.tab_list("file tab list", tabNames, main.worldIndex, closedTab); - //if(closedTab) { - // auto& closedWorldPtr = main.worlds[closedTab.value()]; - // if(closedWorldPtr->should_ask_before_closing()) - // add_world_to_close_popup_data(closedWorldPtr); - // else - // main.set_tab_to_close(closedWorldPtr); - //} - - if(!main.world->clientStillConnecting) { - if(main.world->netObjMan.is_connected()) { - icon_button_top_toolbar("Player List Toggle Button", "data/icons/list.svg", playerMenuOpen, [&] { - playerMenuOpen = !playerMenuOpen; + gui.new_id("menu top toolbar", [&] { + global_log(); + bool menuPopUpJustOpen = false; + bool bookmarkMenuPopUpJustOpen = false; + bool gridMenuPopUpJustOpen = false; + bool layerMenuPopUpJustOpen = false; + auto icon_button_top_toolbar = [&](const char* id, const std::string& svgPath, bool isSelected, const std::function& onClick) { + svg_icon_button(gui, id, svgPath, { + .isSelected = isSelected, + .onClick = onClick }); - } - icon_button_top_toolbar("Menu Undo Button", "data/icons/undo.svg", false, [&] { - main.world->undo_with_checks(); - }); - icon_button_top_toolbar("Menu Redo Button", "data/icons/redo.svg", false, [&] { - main.world->redo_with_checks(); - }); - icon_button_top_toolbar("Grids Button", "data/icons/grid.svg", gridMenu.popupOpen, [&] { - if(gridMenu.popupOpen) - stop_displaying_grid_menu(); + }; + icon_button_top_toolbar("Main Menu Button", "data/icons/menu.svg", menuPopUpOpen, [&] { + if(menuPopUpOpen) + menuPopUpOpen = false; else { - gridMenu.popupOpen = true; - gridMenuPopUpJustOpen = true; - } - }); - icon_button_top_toolbar("Layer Menu Button", "data/icons/layer.svg", layerMenuPopupOpen, [&] { - if(layerMenuPopupOpen) { - main.world->drawProg.layerMan.listGUI.refresh_gui_data(); - layerMenuPopupOpen = false; - } - else { - layerMenuPopupOpen = true; - layerMenuPopUpJustOpen = true; - } - }); - icon_button_top_toolbar("Bookmark Menu Button", "data/icons/bookmark.svg", bookmarkMenuPopupOpen, [&] { - if(bookmarkMenuPopupOpen) { - main.world->bMan.refresh_gui_data(); - bookmarkMenuPopupOpen = false; - } - else { - bookmarkMenuPopupOpen = true; - bookmarkMenuPopUpJustOpen = true; + menuPopUpOpen = true; + menuPopUpJustOpen = true; } }); + //std::vector> tabNames; + //for(size_t i = 0; i < main.worlds.size(); i++) { + // auto& w = main.worlds[i]; + // bool shouldAddStarNextToName = w->should_ask_before_closing() && !w->netServer && !w->netClient; + // tabNames.emplace_back(w->netObjMan.is_connected() ? "data/icons/network.svg" : "", w->name + (shouldAddStarNextToName ? "*" : "")); + //} - if(gridMenu.popupOpen) - grid_menu(gridMenuPopUpJustOpen); - if(bookmarkMenuPopupOpen) - bookmark_menu(bookmarkMenuPopUpJustOpen); - if(layerMenuPopupOpen) - layer_menu(layerMenuPopUpJustOpen); - } - if(menuPopUpOpen) { - gui.element("main menu popup", [&] { - CLAY_AUTO_ID({ - .layout = { - .sizing = {.width = CLAY_SIZING_FIT(100), .height = CLAY_SIZING_FIT(0) }, - .padding = CLAY_PADDING_ALL(io->theme->padding1), - .childGap = 1, - .childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_TOP}, - .layoutDirection = CLAY_TOP_TO_BOTTOM - }, - .backgroundColor = convert_vec4(io->theme->backColor1), - .cornerRadius = CLAY_CORNER_RADIUS(io->theme->windowCorners1), - .floating = {.offset = {.x = 0, .y = static_cast(io->theme->padding1)}, .attachPoints = {.element = CLAY_ATTACH_POINT_LEFT_TOP, .parent = CLAY_ATTACH_POINT_LEFT_BOTTOM}, .attachTo = CLAY_ATTACH_TO_PARENT} - }) { - auto menu_popup_text_button = [&](const char* id, const char* str, const std::function& onClick) { - text_button(gui, id, str, { - .drawType = SelectableButton::DrawType::TRANSPARENT_ALL, - .wide = true, - .onClick = [&]{ - onClick(); - menuPopUpOpen = false; - } - }); - }; - menu_popup_text_button("new file local", "New File", [&] { - main.new_tab({ - .isClient = false - }, true); + //std::optional closedTab; + //gui.tab_list("file tab list", tabNames, main.worldIndex, closedTab); + //if(closedTab) { + // auto& closedWorldPtr = main.worlds[closedTab.value()]; + // if(closedWorldPtr->should_ask_before_closing()) + // add_world_to_close_popup_data(closedWorldPtr); + // else + // main.set_tab_to_close(closedWorldPtr); + //} + + if(!main.world->clientStillConnecting) { + if(main.world->netObjMan.is_connected()) { + icon_button_top_toolbar("Player List Toggle Button", "data/icons/list.svg", playerMenuOpen, [&] { + playerMenuOpen = !playerMenuOpen; }); - menu_popup_text_button("open file", "Open", [&] { open_world_file(false, "", ""); }); - if(!main.world->clientStillConnecting) { - menu_popup_text_button("save file", "Save", [&] { save_func(); }); - menu_popup_text_button("save as file", "Save As", [&] { save_as_func(); }); - menu_popup_text_button("screenshot", "Screenshot", [&] { main.world->drawProg.switch_to_tool(DrawingProgramToolType::SCREENSHOT); }); - menu_popup_text_button("add image or file to canvas", "Add Image/File to Canvas", [&] { - #ifdef __EMSCRIPTEN__ - static std::weak_ptr worldWeakPtr; - worldWeakPtr = make_weak_ptr(main.world); - emscripten_browser_file::upload("*", [](std::string const& fileName, std::string const& mimeType, std::string_view buffer, void* callbackData) { - if(!buffer.empty()) { - auto world = ((std::weak_ptr*)callbackData)->lock(); - if(world) - world->drawProg.add_file_to_canvas_by_data(fileName, buffer, world->main.window.size.cast() / 2.0f); + } + icon_button_top_toolbar("Menu Undo Button", "data/icons/undo.svg", false, [&] { + main.world->undo_with_checks(); + }); + icon_button_top_toolbar("Menu Redo Button", "data/icons/redo.svg", false, [&] { + main.world->redo_with_checks(); + }); + icon_button_top_toolbar("Grids Button", "data/icons/grid.svg", gridMenu.popupOpen, [&] { + if(gridMenu.popupOpen) + stop_displaying_grid_menu(); + else { + gridMenu.popupOpen = true; + gridMenuPopUpJustOpen = true; + } + }); + icon_button_top_toolbar("Layer Menu Button", "data/icons/layer.svg", layerMenuPopupOpen, [&] { + if(layerMenuPopupOpen) { + main.world->drawProg.layerMan.listGUI.refresh_gui_data(); + layerMenuPopupOpen = false; + } + else { + layerMenuPopupOpen = true; + layerMenuPopUpJustOpen = true; + } + }); + icon_button_top_toolbar("Bookmark Menu Button", "data/icons/bookmark.svg", bookmarkMenuPopupOpen, [&] { + if(bookmarkMenuPopupOpen) { + main.world->bMan.refresh_gui_data(); + bookmarkMenuPopupOpen = false; + } + else { + bookmarkMenuPopupOpen = true; + bookmarkMenuPopUpJustOpen = true; + } + }); + + if(gridMenu.popupOpen) + grid_menu(gridMenuPopUpJustOpen); + if(bookmarkMenuPopupOpen) + bookmark_menu(bookmarkMenuPopUpJustOpen); + if(layerMenuPopupOpen) + layer_menu(layerMenuPopUpJustOpen); + } + if(menuPopUpOpen) { + gui.element("main menu popup", [&] { + CLAY_AUTO_ID({ + .layout = { + .sizing = {.width = CLAY_SIZING_FIT(100), .height = CLAY_SIZING_FIT(0) }, + .padding = CLAY_PADDING_ALL(io->theme->padding1), + .childGap = 1, + .childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_TOP}, + .layoutDirection = CLAY_TOP_TO_BOTTOM + }, + .backgroundColor = convert_vec4(io->theme->backColor1), + .cornerRadius = CLAY_CORNER_RADIUS(io->theme->windowCorners1), + .floating = {.offset = {.x = 0, .y = static_cast(io->theme->padding1)}, .attachPoints = {.element = CLAY_ATTACH_POINT_LEFT_TOP, .parent = CLAY_ATTACH_POINT_LEFT_BOTTOM}, .attachTo = CLAY_ATTACH_TO_PARENT} + }) { + auto menu_popup_text_button = [&](const char* id, const char* str, const std::function& onClick) { + text_button(gui, id, str, { + .drawType = SelectableButton::DrawType::TRANSPARENT_ALL, + .wide = true, + .onClick = [&]{ + onClick(); + menuPopUpOpen = false; + } + }); + }; + menu_popup_text_button("new file local", "New File", [&] { + main.new_tab({ + .isClient = false + }, true); + }); + menu_popup_text_button("open file", "Open", [&] { open_world_file(false, "", ""); }); + if(!main.world->clientStillConnecting) { + menu_popup_text_button("save file", "Save", [&] { save_func(); }); + menu_popup_text_button("save as file", "Save As", [&] { save_as_func(); }); + menu_popup_text_button("screenshot", "Screenshot", [&] { main.world->drawProg.switch_to_tool(DrawingProgramToolType::SCREENSHOT); }); + menu_popup_text_button("add image or file to canvas", "Add Image/File to Canvas", [&] { + #ifdef __EMSCRIPTEN__ + static std::weak_ptr worldWeakPtr; + worldWeakPtr = make_weak_ptr(main.world); + emscripten_browser_file::upload("*", [](std::string const& fileName, std::string const& mimeType, std::string_view buffer, void* callbackData) { + if(!buffer.empty()) { + auto world = ((std::weak_ptr*)callbackData)->lock(); + if(world) + world->drawProg.add_file_to_canvas_by_data(fileName, buffer, world->main.window.size.cast() / 2.0f); + else + Logger::get().log("INFO", "Loading image to canvas that has been destroyed"); + } + }, &worldWeakPtr); + #else + open_file_selector("Open File", {{"Any File", "*"}}, [w = make_weak_ptr(main.world)](const std::filesystem::path& p, const auto& e) { + auto wLock = w.lock(); + if(wLock) + wLock->drawProg.add_file_to_canvas_by_path(p, wLock->main.window.size.cast() / 2.0f, false); else Logger::get().log("INFO", "Loading image to canvas that has been destroyed"); - } - }, &worldWeakPtr); - #else - open_file_selector("Open File", {{"Any File", "*"}}, [w = make_weak_ptr(main.world)](const std::filesystem::path& p, const auto& e) { - auto wLock = w.lock(); - if(wLock) - wLock->drawProg.add_file_to_canvas_by_path(p, wLock->main.window.size.cast() / 2.0f, false); - else - Logger::get().log("INFO", "Loading image to canvas that has been destroyed"); + }); + #endif + }); + if(main.world->netObjMan.is_connected()) { + menu_popup_text_button("lobby info", "Lobby Info", [&] { + optionsMenuOpen = true; + optionsMenuType = LOBBY_INFO_MENU; }); - #endif - }); - if(main.world->netObjMan.is_connected()) { - menu_popup_text_button("lobby info", "Lobby Info", [&] { + } + menu_popup_text_button("start hosting", "Host", [&] { + serverLocalID = NetLibrary::get_random_server_local_id(); + serverToConnectTo = NetLibrary::get_global_id() + serverLocalID; optionsMenuOpen = true; - optionsMenuType = LOBBY_INFO_MENU; + optionsMenuType = HOST_MENU; + }); + menu_popup_text_button("canvas specific settings", "Canvas Settings", [&] { + optionsMenuOpen = true; + optionsMenuType = CANVAS_SETTINGS_MENU; }); } - menu_popup_text_button("start hosting", "Host", [&] { - serverLocalID = NetLibrary::get_random_server_local_id(); - serverToConnectTo = NetLibrary::get_global_id() + serverLocalID; + menu_popup_text_button("start connecting", "Connect", [&] { + serverToConnectTo.clear(); optionsMenuOpen = true; - optionsMenuType = HOST_MENU; + optionsMenuType = CONNECT_MENU; }); - menu_popup_text_button("canvas specific settings", "Canvas Settings", [&] { + menu_popup_text_button("open options", "Settings", [&] { optionsMenuOpen = true; - optionsMenuType = CANVAS_SETTINGS_MENU; + optionsMenuType = GENERAL_SETTINGS_MENU; }); - } - menu_popup_text_button("start connecting", "Connect", [&] { - serverToConnectTo.clear(); - optionsMenuOpen = true; - optionsMenuType = CONNECT_MENU; - }); - menu_popup_text_button("open options", "Settings", [&] { - optionsMenuOpen = true; - optionsMenuType = GENERAL_SETTINGS_MENU; - }); - menu_popup_text_button("about menu button", "About", [&] { - optionsMenuOpen = true; - optionsMenuType = ABOUT_MENU; - }); - #ifndef __EMSCRIPTEN__ - menu_popup_text_button("quit button", "Quit", [&] { - if(main.app_close_requested()) - main.setToQuit = true; + menu_popup_text_button("about menu button", "About", [&] { + optionsMenuOpen = true; + optionsMenuType = ABOUT_MENU; }); - #endif - } - }, LayoutElement::Callbacks { - .mouseButton = [&](const InputManager::MouseButtonCallbackArgs& button, bool mouseHovering) { - if(!mouseHovering && button.down) { - menuPopUpOpen = false; - gui.set_to_layout(); + #ifndef __EMSCRIPTEN__ + menu_popup_text_button("quit button", "Quit", [&] { + if(main.app_close_requested()) + main.setToQuit = true; + }); + #endif } - return mouseHovering; - } - }); - } - gui.pop_id(); + }, LayoutElement::Callbacks { + .mouseButton = [&](const InputManager::MouseButtonCallbackArgs& button, bool mouseHovering) { + if(!mouseHovering && button.down) { + menuPopUpOpen = false; + gui.set_to_layout(); + } + return mouseHovering; + } + }); + } + }); } } @@ -857,9 +865,9 @@ void Toolbar::web_version_welcome() { .cornerRadius = CLAY_CORNER_RADIUS(io->theme->windowCorners1), .floating = {.attachPoints = {.element = CLAY_ATTACH_POINT_CENTER_CENTER, .parent = CLAY_ATTACH_POINT_CENTER_CENTER}, .attachTo = CLAY_ATTACH_TO_PARENT} }) { - gui.push_id("web version welcome gui"); - text_label_centered(gui, "Welcome to the web version of InfiniPaint!"); - text_label(gui, + gui.new_id("web version welcome gui", [&] { + text_label_centered(gui, "Welcome to the web version of InfiniPaint!"); + text_label(gui, R"(This version contains more known issues than the native version of the app. This includes: - Rare crashes - If this browser tab is unfocused, or the window is minimized, any InfiniPaint tabs connected online (whether host or client) will be disconnected @@ -868,13 +876,13 @@ R"(This version contains more known issues than the native version of the app. T - Can't access local fonts If you like this app, consider downloading the native version for your system)"); - text_button(gui, "got it", "Got It", { - .wide = true, - .onClick = [&] { - viewWebVersionWelcome = false; - } + text_button(gui, "got it", "Got It", { + .wide = true, + .onClick = [&] { + viewWebVersionWelcome = false; + } + }); }); - gui.pop_id(); } } @@ -969,36 +977,36 @@ void Toolbar::update_notification_gui() { .cornerRadius = CLAY_CORNER_RADIUS(io->theme->windowCorners1), .floating = {.attachPoints = {.element = CLAY_ATTACH_POINT_CENTER_CENTER, .parent = CLAY_ATTACH_POINT_CENTER_CENTER}, .attachTo = CLAY_ATTACH_TO_PARENT} }) { - gui.push_id("update notification gui"); - text_label_centered(gui, "Update v" + updateCheckerData.newVersionStr + " available!"); - text_button(gui, "download", "Open download page in web browser", { - .wide = true, - .onClick = [&]{ - SDL_OpenURL(UPDATE_DOWNLOAD_URL); - updateCheckerData.showGui = false; - } + gui.new_id("update notification gui", [&] { + text_label_centered(gui, "Update v" + updateCheckerData.newVersionStr + " available!"); + text_button(gui, "download", "Open download page in web browser", { + .wide = true, + .onClick = [&]{ + SDL_OpenURL(UPDATE_DOWNLOAD_URL); + updateCheckerData.showGui = false; + } + }); + text_button(gui, "ignore forever", "Ignore and don't notify again (can be changed in settings)", { + .wide = true, + .onClick = [&]{ + updateCheckerData.checkForUpdates = false; + updateCheckerData.showGui = false; + } + }); + text_button(gui, "ignore for now", "Ignore for now", { + .wide = true, + .onClick = [&]{ + updateCheckerData.showGui = false; + } + }); }); - text_button(gui, "ignore forever", "Ignore and don't notify again (can be changed in settings)", { - .wide = true, - .onClick = [&]{ - updateCheckerData.checkForUpdates = false; - updateCheckerData.showGui = false; - } - }); - text_button(gui, "ignore for now", "Ignore for now", { - .wide = true, - .onClick = [&]{ - updateCheckerData.showGui = false; - } - }); - gui.pop_id(); } } #endif void Toolbar::grid_menu(bool justOpened) { if(main.world->gridMan.grids) { - gui.push_id("grid menu"); + gui.new_id("grid menu", [&] { //CLAY(localId, { // .layout = { // .sizing = {.width = CLAY_SIZING_FIT(300), .height = CLAY_SIZING_FIT(0, 600) }, @@ -1081,7 +1089,7 @@ void Toolbar::grid_menu(bool justOpened) { // if(io->mouse.leftClick && !Clay_Hovered() && !justOpened && !dropdownHover) // stop_displaying_grid_menu(); //} - gui.pop_id(); + }); } } @@ -1092,7 +1100,7 @@ void Toolbar::stop_displaying_grid_menu() { } void Toolbar::bookmark_menu(bool justOpened) { - gui.push_id("bookmark menu"); + gui.new_id("bookmark menu", [&] { //Clay_ElementId localId = CLAY_ID_LOCAL("INFINIPAINT BOOKMARK MENU"); //CLAY(localId, { // .layout = { @@ -1114,11 +1122,11 @@ void Toolbar::bookmark_menu(bool justOpened) { // main.world->bMan.refresh_gui_data(); // } //} - gui.pop_id(); + }); } void Toolbar::layer_menu(bool justOpened) { - gui.push_id("layer menu"); + gui.new_id("layer menu", [&] { //Clay_ElementId localId = CLAY_ID_LOCAL("INFINIPAINT LAYER MENU"); //CLAY(localId, { // .layout = { @@ -1141,7 +1149,7 @@ void Toolbar::layer_menu(bool justOpened) { // main.world->drawProg.layerMan.listGUI.refresh_gui_data(); // } //} - gui.pop_id(); + }); } std::unique_ptr Toolbar::build_paragraph_from_chat_message(const ChatMessage& message, float alpha) { @@ -1410,7 +1418,7 @@ void Toolbar::drawing_program_gui() { bool Toolbar::color_palette(const char* id, Vector4f* color, bool& hoveringOnDropdown) { bool isUpdating = false; - gui.push_id(id); + gui.new_id(id, [&] { //auto& palette = paletteData.palettes[paletteData.selectedPalette].colors; //constexpr float COLOR_BUTTON_SIZE = GUIStuff::GUIManager::BIG_BUTTON_SIZE; @@ -1517,7 +1525,7 @@ bool Toolbar::color_palette(const char* id, Vector4f* color, bool& hoveringOnDro // paletteData.addingPalette = false; // } //} - gui.pop_id(); + }); return isUpdating; } @@ -1588,45 +1596,45 @@ void Toolbar::player_list() { .cornerRadius = CLAY_CORNER_RADIUS(io->theme->windowCorners1), .floating = {.attachPoints = {.element = CLAY_ATTACH_POINT_CENTER_CENTER, .parent = CLAY_ATTACH_POINT_CENTER_CENTER}, .attachTo = CLAY_ATTACH_TO_PARENT} }) { - gui.push_id("client list"); - text_label_centered(gui, "Player List"); - if(!main.world->clientStillConnecting) { - left_to_right_line_layout(gui, [&]() { - CLAY_AUTO_ID({ - .layout = { - .sizing = {.width = CLAY_SIZING_FIXED(20), .height = CLAY_SIZING_FIXED(20)} - }, - .backgroundColor = convert_vec4(SkColor4f{main.world->ownClientData->get_cursor_color().x(), main.world->ownClientData->get_cursor_color().y(), main.world->ownClientData->get_cursor_color().z(), 1.0f}), - .cornerRadius = CLAY_CORNER_RADIUS(3) - }) {} - text_label(gui, main.world->ownClientData->get_display_name()); - }); - size_t num = 0; - for(auto& client : main.world->clients->get_data()) { - if(client != main.world->ownClientData) { - gui.push_id(num++); - left_to_right_line_layout(gui, [&]() { - CLAY_AUTO_ID({ - .layout = { - .sizing = {.width = CLAY_SIZING_FIXED(20), .height = CLAY_SIZING_FIXED(20)} - }, - .backgroundColor = convert_vec4(SkColor4f{client->get_cursor_color().x(), client->get_cursor_color().y(), client->get_cursor_color().z(), 1.0f}), - .cornerRadius = CLAY_CORNER_RADIUS(3) - }) {} - text_label(gui, client->get_display_name()); - CLAY_AUTO_ID({.layout = {.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}}}) {} - text_button(gui, "teleport button", "Jump To", { .onClick = [&] { - main.world->drawData.cam.smooth_move_to(*main.world, client->get_cam_coords(), client->get_window_size()); - }}); - }); - gui.pop_id(); + gui.new_id("client list", [&] { + text_label_centered(gui, "Player List"); + if(!main.world->clientStillConnecting) { + left_to_right_line_layout(gui, [&]() { + CLAY_AUTO_ID({ + .layout = { + .sizing = {.width = CLAY_SIZING_FIXED(20), .height = CLAY_SIZING_FIXED(20)} + }, + .backgroundColor = convert_vec4(SkColor4f{main.world->ownClientData->get_cursor_color().x(), main.world->ownClientData->get_cursor_color().y(), main.world->ownClientData->get_cursor_color().z(), 1.0f}), + .cornerRadius = CLAY_CORNER_RADIUS(3) + }) {} + text_label(gui, main.world->ownClientData->get_display_name()); + }); + size_t num = 0; + for(auto& client : main.world->clients->get_data()) { + if(client != main.world->ownClientData) { + gui.new_id(num++, [&] { + left_to_right_line_layout(gui, [&]() { + CLAY_AUTO_ID({ + .layout = { + .sizing = {.width = CLAY_SIZING_FIXED(20), .height = CLAY_SIZING_FIXED(20)} + }, + .backgroundColor = convert_vec4(SkColor4f{client->get_cursor_color().x(), client->get_cursor_color().y(), client->get_cursor_color().z(), 1.0f}), + .cornerRadius = CLAY_CORNER_RADIUS(3) + }) {} + text_label(gui, client->get_display_name()); + CLAY_AUTO_ID({.layout = {.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}}}) {} + text_button(gui, "teleport button", "Jump To", { .onClick = [&] { + main.world->drawData.cam.smooth_move_to(*main.world, client->get_cam_coords(), client->get_window_size()); + }}); + }); + }); + } } } - } - text_button(gui, "close list", "Done", { .wide = true, .onClick = [&] { - playerMenuOpen = false; - }}); - gui.pop_id(); + text_button(gui, "close list", "Done", { .wide = true, .onClick = [&] { + playerMenuOpen = false; + }}); + }); } } @@ -1856,130 +1864,129 @@ void Toolbar::general_settings_inner_gui() { }) { switch(generalSettingsOptions) { case GSETTINGS_GENERAL: { - gui.push_id("general settings"); - input_text_field(gui, "display name input", "Display name", &main.displayName); - main.update_display_names(); - color_picker_button_field(gui, "defaultCanvasBackgroundColor", "Default canvas background color", &main.defaultCanvasBackgroundColor, { .hasAlpha = false }); - #ifndef __EMSCRIPTEN__ - checkbox_boolean_field(gui, "native file pick", "Use native file picker", &useNativeFilePicker); - checkbox_boolean_field(gui, "update notifications enable", "Check for updates on startup", &updateCheckerData.checkForUpdates); - #endif - slider_scalar_field(gui, "drag zoom slider", "Drag zoom speed", &dragZoomSpeed, 0.0, 1.0, {.decimalPrecision = 3}); - slider_scalar_field(gui, "scroll zoom slider", "Scroll zoom speed", &scrollZoomSpeed, 0.0, 1.0, {.decimalPrecision = 3}); - checkbox_boolean_field(gui, "flip zoom tool direction", "Flip zoom tool direction", &flipZoomToolDirection); - checkbox_boolean_field(gui, "make all tools share same size", "Make all tools share size", &main.toolConfig.globalConf.useGlobalRelativeWidth); - #ifndef __EMSCRIPTEN__ - checkbox_boolean_field(gui, "disable graphics driver workarounds", "Disable graphics driver workarounds (enabling or disabling this might fix some graphical glitches, requires restart)", &main.window.disableGraphicsDriverWorkarounds); - #endif - input_scalar_field(gui, "jump transition time", "Jump transition time", &jumpTransitionTime, 0.01f, 1000.0f, {.decimalPrecision = 2}); - input_scalar_field(gui, "Max GUI Scale", "Max GUI Scale", &guiScale, 0.5f, 5.0f, {.decimalPrecision = 1}); - text_label(gui, "Anti-aliasing:"); - radio_button_selector(gui, "Antialiasing selector", &main.antialiasing, { - {"None", MainProgram::AntiAliasing::NONE}, - {"Skia", MainProgram::AntiAliasing::SKIA}, - {"Dynamic MSAA", MainProgram::AntiAliasing::DYNAMIC_MSAA} - }, [&] { - main.refresh_draw_surfaces(); - }); - text_label(gui, "VSync:"); - radio_button_selector(gui, "VSync selector", &main.window.vsyncValue, { - {"On", 1}, - {"Off", 0}, - {"Adaptive", -1} - }, [&] { - main.set_vsync_value(main.window.vsyncValue); - }); + gui.new_id("general settings", [&] { + input_text_field(gui, "display name input", "Display name", &main.displayName); + main.update_display_names(); + color_picker_button_field(gui, "defaultCanvasBackgroundColor", "Default canvas background color", &main.defaultCanvasBackgroundColor, { .hasAlpha = false }); + #ifndef __EMSCRIPTEN__ + checkbox_boolean_field(gui, "native file pick", "Use native file picker", &useNativeFilePicker); + checkbox_boolean_field(gui, "update notifications enable", "Check for updates on startup", &updateCheckerData.checkForUpdates); + #endif + slider_scalar_field(gui, "drag zoom slider", "Drag zoom speed", &dragZoomSpeed, 0.0, 1.0, {.decimalPrecision = 3}); + slider_scalar_field(gui, "scroll zoom slider", "Scroll zoom speed", &scrollZoomSpeed, 0.0, 1.0, {.decimalPrecision = 3}); + checkbox_boolean_field(gui, "flip zoom tool direction", "Flip zoom tool direction", &flipZoomToolDirection); + checkbox_boolean_field(gui, "make all tools share same size", "Make all tools share size", &main.toolConfig.globalConf.useGlobalRelativeWidth); + #ifndef __EMSCRIPTEN__ + checkbox_boolean_field(gui, "disable graphics driver workarounds", "Disable graphics driver workarounds (enabling or disabling this might fix some graphical glitches, requires restart)", &main.window.disableGraphicsDriverWorkarounds); + #endif + input_scalar_field(gui, "jump transition time", "Jump transition time", &jumpTransitionTime, 0.01f, 1000.0f, {.decimalPrecision = 2}); + input_scalar_field(gui, "Max GUI Scale", "Max GUI Scale", &guiScale, 0.5f, 5.0f, {.decimalPrecision = 1}); + text_label(gui, "Anti-aliasing:"); + radio_button_selector(gui, "Antialiasing selector", &main.antialiasing, { + {"None", MainProgram::AntiAliasing::NONE}, + {"Skia", MainProgram::AntiAliasing::SKIA}, + {"Dynamic MSAA", MainProgram::AntiAliasing::DYNAMIC_MSAA} + }, [&] { + main.refresh_draw_surfaces(); + }); + text_label(gui, "VSync:"); + radio_button_selector(gui, "VSync selector", &main.window.vsyncValue, { + {"On", 1}, + {"Off", 0}, + {"Adaptive", -1} + }, [&] { + main.set_vsync_value(main.window.vsyncValue); + }); - #ifndef __EMSCRIPTEN__ - checkbox_boolean_field(gui, "apply display scale", "Apply display scale", &main.window.applyDisplayScale); - #endif - - gui.pop_id(); + #ifndef __EMSCRIPTEN__ + checkbox_boolean_field(gui, "apply display scale", "Apply display scale", &main.window.applyDisplayScale); + #endif + }); break; } case GSETTINGS_TABLET: { - gui.push_id("tablet settings"); - checkbox_boolean_field(gui, "pen pressure width", "Pen pressure affects brush size", &tabletOptions.pressureAffectsBrushWidth); - slider_scalar_field(gui, "smoothing time", "Smoothing sampling time", &tabletOptions.smoothingSamplingTime, 0.001f, 1.0f, {.decimalPrecision = 3}); - input_scalar_field(gui, "middle click", "Middle click pen button", &tabletOptions.middleClickButton, 1, 255); - input_scalar_field(gui, "right click", "Right click pen button", &tabletOptions.rightClickButton, 1, 255); - slider_scalar_field(gui, "tablet brush minimum size", "Brush relative minimum size", &tabletOptions.brushMinimumSize, 0.0f, 1.0f, {.decimalPrecision = 3}); - checkbox_boolean_field(gui, "tablet zoom with button method", "Zoom when pen touching tablet and pen button assigned to middle click is held", &tabletOptions.zoomWhilePenDownAndButtonHeld); - #ifdef _WIN32 - checkbox_boolean_field(gui, "mouse ignore when pen proximity", "Ignore mouse movement when pen in proximity", &tabletOptions.ignoreMouseMovementWhenPenInProximity); - #endif - gui.pop_id(); + gui.new_id("tablet settings", [&] { + checkbox_boolean_field(gui, "pen pressure width", "Pen pressure affects brush size", &tabletOptions.pressureAffectsBrushWidth); + slider_scalar_field(gui, "smoothing time", "Smoothing sampling time", &tabletOptions.smoothingSamplingTime, 0.001f, 1.0f, {.decimalPrecision = 3}); + input_scalar_field(gui, "middle click", "Middle click pen button", &tabletOptions.middleClickButton, 1, 255); + input_scalar_field(gui, "right click", "Right click pen button", &tabletOptions.rightClickButton, 1, 255); + slider_scalar_field(gui, "tablet brush minimum size", "Brush relative minimum size", &tabletOptions.brushMinimumSize, 0.0f, 1.0f, {.decimalPrecision = 3}); + checkbox_boolean_field(gui, "tablet zoom with button method", "Zoom when pen touching tablet and pen button assigned to middle click is held", &tabletOptions.zoomWhilePenDownAndButtonHeld); + #ifdef _WIN32 + checkbox_boolean_field(gui, "mouse ignore when pen proximity", "Ignore mouse movement when pen in proximity", &tabletOptions.ignoreMouseMovementWhenPenInProximity); + #endif + }); break; } case GSETTINGS_THEME: { - gui.push_id("theme"); - if(!themeData.selectedThemeIndex) - reload_theme_list(); + gui.new_id("theme", [&] { + if(!themeData.selectedThemeIndex) + reload_theme_list(); - CLAY_AUTO_ID({.layout = { - .childGap = io->theme->childGap1, - .childAlignment = {.x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER}, - .layoutDirection = CLAY_LEFT_TO_RIGHT, - } - }) { - text_label(gui, "Theme: "); - gui.element>("dropdownSelectThemes", &themeData.selectedThemeIndex.value(), themeData.themeDirList, DropdownOptions{ - .onClick = [&]() { + CLAY_AUTO_ID({.layout = { + .childGap = io->theme->childGap1, + .childAlignment = {.x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER}, + .layoutDirection = CLAY_LEFT_TO_RIGHT, + } + }) { + text_label(gui, "Theme: "); + gui.element>("dropdownSelectThemes", &themeData.selectedThemeIndex.value(), themeData.themeDirList, DropdownOptions{ + .onClick = [&]() { + themeData.themeCurrentlyLoaded = themeData.themeDirList[themeData.selectedThemeIndex.value()]; + reload_theme_list(); + } + }); + } + left_to_right_line_layout(gui, [&]() { + if(themeData.selectedThemeIndex != 0) { + text_button_wide("savethemebutton", "Save", [&] { + themeData.themeCurrentlyLoaded = themeData.themeDirList[themeData.selectedThemeIndex.value()]; + save_theme(); + reload_theme_list(); + }); + } + text_button_wide("saveasthemebutton", "Save As", [&]() { + themeData.openedSaveAsMenu = !themeData.openedSaveAsMenu; + }); + text_button_wide("reloadthemebutton", "Reload", [&] { themeData.themeCurrentlyLoaded = themeData.themeDirList[themeData.selectedThemeIndex.value()]; reload_theme_list(); + }); + if(themeData.selectedThemeIndex != 0) { + text_button_wide("deletethemebutton", "Delete", [&] { + try { std::filesystem::remove(main.configPath / "themes" / (themeData.themeDirList[themeData.selectedThemeIndex.value()] + ".json")); } catch(...) { } + themeData.themeCurrentlyLoaded = "Default"; + reload_theme_list(); + }); } }); - } - left_to_right_line_layout(gui, [&]() { - if(themeData.selectedThemeIndex != 0) { - text_button_wide("savethemebutton", "Save", [&] { - themeData.themeCurrentlyLoaded = themeData.themeDirList[themeData.selectedThemeIndex.value()]; - save_theme(); - reload_theme_list(); - }); - } - text_button_wide("saveasthemebutton", "Save As", [&]() { - themeData.openedSaveAsMenu = !themeData.openedSaveAsMenu; - }); - text_button_wide("reloadthemebutton", "Reload", [&] { - themeData.themeCurrentlyLoaded = themeData.themeDirList[themeData.selectedThemeIndex.value()]; - reload_theme_list(); - }); - if(themeData.selectedThemeIndex != 0) { - text_button_wide("deletethemebutton", "Delete", [&] { - try { std::filesystem::remove(main.configPath / "themes" / (themeData.themeDirList[themeData.selectedThemeIndex.value()] + ".json")); } catch(...) { } - themeData.themeCurrentlyLoaded = "Default"; - reload_theme_list(); + if(themeData.openedSaveAsMenu) { + input_text_field(gui, "Theme name:", "Theme name: ", &themeData.themeCurrentlyLoaded); + left_to_right_line_layout(gui, [&]() { + text_button_wide("saveasdone", "Done", [&] { + save_theme(); + reload_theme_list(); + }); + text_button_wide("saveascancel", "Cancel", [&] { + themeData.openedSaveAsMenu = false; + }); }); } + text_label(gui, "Edit theme:"); + text_label_light(gui, "Note: Changes only remain if theme is saved"); + color_picker_button_field(gui, "fillColor1", "Fill Color 1", &io->theme->fillColor1); + color_picker_button_field(gui, "fillColor2", "Fill Color 2", &io->theme->fillColor2); + color_picker_button_field(gui, "backColor1", "Back Color 1", &io->theme->backColor1); + color_picker_button_field(gui, "backColor2", "Back Color 2", &io->theme->backColor2); + color_picker_button_field(gui, "frontColor1", "Front Color 1", &io->theme->frontColor1); + color_picker_button_field(gui, "frontColor2", "Front Color 2", &io->theme->frontColor2); + color_picker_button_field(gui, "warningColor", "Warning Color", &io->theme->warningColor); + color_picker_button_field(gui, "errorColor", "Error Color", &io->theme->errorColor); + //gui.slider_scalar_field("hoverExpandTime", "Hover Expand Time", &io->theme->hoverExpandTime, 0.001f, 1.0f); + input_scalar_field(gui, "childGap1", "Gap between child elements", &io->theme->childGap1, 0, 30); + input_scalar_field(gui, "padding1", "Window padding", &io->theme->padding1, 0, 30); + slider_scalar_field(gui, "windowCorners1", "Window corner radius", &io->theme->windowCorners1, 0, 30); }); - if(themeData.openedSaveAsMenu) { - input_text_field(gui, "Theme name:", "Theme name: ", &themeData.themeCurrentlyLoaded); - left_to_right_line_layout(gui, [&]() { - text_button_wide("saveasdone", "Done", [&] { - save_theme(); - reload_theme_list(); - }); - text_button_wide("saveascancel", "Cancel", [&] { - themeData.openedSaveAsMenu = false; - }); - }); - } - text_label(gui, "Edit theme:"); - text_label_light(gui, "Note: Changes only remain if theme is saved"); - color_picker_button_field(gui, "fillColor1", "Fill Color 1", &io->theme->fillColor1); - color_picker_button_field(gui, "fillColor2", "Fill Color 2", &io->theme->fillColor2); - color_picker_button_field(gui, "backColor1", "Back Color 1", &io->theme->backColor1); - color_picker_button_field(gui, "backColor2", "Back Color 2", &io->theme->backColor2); - color_picker_button_field(gui, "frontColor1", "Front Color 1", &io->theme->frontColor1); - color_picker_button_field(gui, "frontColor2", "Front Color 2", &io->theme->frontColor2); - color_picker_button_field(gui, "warningColor", "Warning Color", &io->theme->warningColor); - color_picker_button_field(gui, "errorColor", "Error Color", &io->theme->errorColor); - //gui.slider_scalar_field("hoverExpandTime", "Hover Expand Time", &io->theme->hoverExpandTime, 0.001f, 1.0f); - input_scalar_field(gui, "childGap1", "Gap between child elements", &io->theme->childGap1, 0, 30); - input_scalar_field(gui, "padding1", "Window padding", &io->theme->padding1, 0, 30); - slider_scalar_field(gui, "windowCorners1", "Window corner radius", &io->theme->windowCorners1, 0, 30); - gui.pop_id(); break; } case GSETTINGS_KEYBINDS: { @@ -2000,57 +2007,57 @@ void Toolbar::general_settings_inner_gui() { } } - gui.push_id("keybind entries"); - for(unsigned i = 0; i < InputManager::KEY_ASSIGNABLE_COUNT; i++) { - gui.push_id(i); - CLAY_AUTO_ID({ - .layout = { - .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(0) }, - .padding = CLAY_PADDING_ALL(0), - .childGap = io->theme->childGap1, - .childAlignment = { .x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER}, - .layoutDirection = CLAY_LEFT_TO_RIGHT - } - }) { - text_label(gui, std::string(nlohmann::json(static_cast(i)))); - auto f = std::find_if(main.input.keyAssignments.begin(), main.input.keyAssignments.end(), [&](auto& p) { - return p.second == i; - }); - std::string assignedKeystrokeStr = f != main.input.keyAssignments.end() ? main.input.key_assignment_to_str(f->first) : ""; - text_button(gui, "keybind button", assignedKeystrokeStr, { - .isSelected = keybindWaiting.has_value() && keybindWaiting.value() == i, - .wide = true, - .onClick = [&] { - keybindWaiting = i; + gui.new_id("keybind entries", [&] { + for(unsigned i = 0; i < InputManager::KEY_ASSIGNABLE_COUNT; i++) { + gui.new_id(i, [&] { + CLAY_AUTO_ID({ + .layout = { + .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(0) }, + .padding = CLAY_PADDING_ALL(0), + .childGap = io->theme->childGap1, + .childAlignment = { .x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER}, + .layoutDirection = CLAY_LEFT_TO_RIGHT + } + }) { + text_label(gui, std::string(nlohmann::json(static_cast(i)))); + auto f = std::find_if(main.input.keyAssignments.begin(), main.input.keyAssignments.end(), [&](auto& p) { + return p.second == i; + }); + std::string assignedKeystrokeStr = f != main.input.keyAssignments.end() ? main.input.key_assignment_to_str(f->first) : ""; + text_button(gui, "keybind button", assignedKeystrokeStr, { + .isSelected = keybindWaiting.has_value() && keybindWaiting.value() == i, + .wide = true, + .onClick = [&] { + keybindWaiting = i; + } + }); } }); } - gui.pop_id(); - } - gui.pop_id(); + }); break; } case GSETTINGS_DEBUG: { - gui.push_id("debug settings menu"); - checkbox_boolean_field(gui, "show performance metrics", "Show metrics", &showPerformance); - input_scalars_field(gui, "jump transition easing", "Jump easing", &jumpTransitionEasing, 4, -10.0f, 10.0f, { .decimalPrecision = 2 }); - #ifndef __EMSCRIPTEN__ - input_scalar_field(gui, "fps cap slider", "FPS cap", &main.fpsLimit, 3.0f, 10000.0f); - #endif - input_scalar_field(gui, "image load max threads", "Maximum image loading threads", &ImageResourceDisplay::IMAGE_LOAD_THREAD_COUNT_MAX, 1, 10000); - text_label_light(gui, "Cache related settings"); - input_scalar_field(gui, "cache node resolution", "Cache node resolution", &DrawingProgramCache::CACHE_NODE_RESOLUTION, 256, 8192); - input_scalar_field(gui, "max cache nodes", "Maximum cached nodes", &DrawingProgramCache::MAXIMUM_DRAW_CACHE_SURFACES, 2, 10000); - size_t cacheVRAMConsumptionInMB = ( DrawingProgramCache::MAXIMUM_DRAW_CACHE_SURFACES // Number of surfaces - * DrawingProgramCache::CACHE_NODE_RESOLUTION * DrawingProgramCache::CACHE_NODE_RESOLUTION // Number of pixels per cache surface - * 4) // 4 Channels per pixel (RGBA) - / (1024 * 1024); // Bytes -> Megabytes conversion - text_label_light(gui, "Cache max VRAM consumption (MB): " + std::to_string(cacheVRAMConsumptionInMB)); - input_scalar_field(gui, "max components in node", "Maximum components in single node", &DrawingProgramCache::MAXIMUM_COMPONENTS_IN_SINGLE_NODE, 2, 10000); - input_scalar_field(gui, "components to force cache rebuild", "Number of components to force cache rebuild", &DrawingProgramCache::MINIMUM_COMPONENTS_TO_START_REBUILD, 1, 1000000); - input_scalar_field(gui, "maximum frame time to force cache rebuild", "Maximum frame time to force cache rebuild (ms)", &DrawingProgramCache::MILLISECOND_FRAME_TIME_TO_FORCE_CACHE_REFRESH, 1, 1000000); - input_scalar_field(gui, "minimum time to force cache rebuild", "Minimum time to check cache rebuild (ms)", &DrawingProgramCache::MILLISECOND_MINIMUM_TIME_TO_CHECK_FORCE_REFRESH, 1, 1000000); - gui.pop_id(); + gui.new_id("debug settings menu", [&] { + checkbox_boolean_field(gui, "show performance metrics", "Show metrics", &showPerformance); + input_scalars_field(gui, "jump transition easing", "Jump easing", &jumpTransitionEasing, 4, -10.0f, 10.0f, { .decimalPrecision = 2 }); + #ifndef __EMSCRIPTEN__ + input_scalar_field(gui, "fps cap slider", "FPS cap", &main.fpsLimit, 3.0f, 10000.0f); + #endif + input_scalar_field(gui, "image load max threads", "Maximum image loading threads", &ImageResourceDisplay::IMAGE_LOAD_THREAD_COUNT_MAX, 1, 10000); + text_label_light(gui, "Cache related settings"); + input_scalar_field(gui, "cache node resolution", "Cache node resolution", &DrawingProgramCache::CACHE_NODE_RESOLUTION, 256, 8192); + input_scalar_field(gui, "max cache nodes", "Maximum cached nodes", &DrawingProgramCache::MAXIMUM_DRAW_CACHE_SURFACES, 2, 10000); + size_t cacheVRAMConsumptionInMB = ( DrawingProgramCache::MAXIMUM_DRAW_CACHE_SURFACES // Number of surfaces + * DrawingProgramCache::CACHE_NODE_RESOLUTION * DrawingProgramCache::CACHE_NODE_RESOLUTION // Number of pixels per cache surface + * 4) // 4 Channels per pixel (RGBA) + / (1024 * 1024); // Bytes -> Megabytes conversion + text_label_light(gui, "Cache max VRAM consumption (MB): " + std::to_string(cacheVRAMConsumptionInMB)); + input_scalar_field(gui, "max components in node", "Maximum components in single node", &DrawingProgramCache::MAXIMUM_COMPONENTS_IN_SINGLE_NODE, 2, 10000); + input_scalar_field(gui, "components to force cache rebuild", "Number of components to force cache rebuild", &DrawingProgramCache::MINIMUM_COMPONENTS_TO_START_REBUILD, 1, 1000000); + input_scalar_field(gui, "maximum frame time to force cache rebuild", "Maximum frame time to force cache rebuild (ms)", &DrawingProgramCache::MILLISECOND_FRAME_TIME_TO_FORCE_CACHE_REFRESH, 1, 1000000); + input_scalar_field(gui, "minimum time to force cache rebuild", "Minimum time to check cache rebuild (ms)", &DrawingProgramCache::MILLISECOND_MINIMUM_TIME_TO_CHECK_FORCE_REFRESH, 1, 1000000); + }); break; } } @@ -2069,50 +2076,51 @@ void Toolbar::general_settings_inner_gui() { void Toolbar::about_menu_inner_gui() { left_to_right_line_layout(gui, [&]() { - gui.push_id("Menu Selector"); - CLAY_AUTO_ID({ - .layout = { - .sizing = {.width = CLAY_SIZING_FIT(200), .height = CLAY_SIZING_FIT(0) }, - .padding = CLAY_PADDING_ALL(io->theme->padding1), - .childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_TOP}, - .layoutDirection = CLAY_TOP_TO_BOTTOM - } - }) { - gui.element("About Menu Selector Scroll Area", ScrollArea::Options{ - .innerContent = [&](const ScrollArea::InnerContentParameters&) { - CLAY_AUTO_ID({ - .layout = { - .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(0)} - } - }) { - text_button(gui, "infinipaintnoticebutton", "InfiniPaint", { - .drawType = SelectableButton::DrawType::TRANSPARENT_ALL, - .isSelected = selectedLicense == -1, - .wide = true, - .onClick = [&] { selectedLicense = -1; } - }); - } - text_label_light_centered(gui, "Third Party Components"); - for(int i = 0; i < static_cast(thirdPartyLicenses.size()); i++) { + gui.new_id("Menu Selector", [&] { + CLAY_AUTO_ID({ + .layout = { + .sizing = {.width = CLAY_SIZING_FIT(200), .height = CLAY_SIZING_FIT(0) }, + .padding = CLAY_PADDING_ALL(io->theme->padding1), + .childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_TOP}, + .layoutDirection = CLAY_TOP_TO_BOTTOM + } + }) { + gui.element("About Menu Selector Scroll Area", ScrollArea::Options{ + .innerContent = [&](const ScrollArea::InnerContentParameters&) { CLAY_AUTO_ID({ .layout = { - .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(0) }, - .padding = CLAY_PADDING_ALL(1) + .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(0)} } }) { - gui.push_id(i); - text_button(gui, "noticebutton", thirdPartyLicenses[i].first, { + text_button(gui, "infinipaintnoticebutton", "InfiniPaint", { .drawType = SelectableButton::DrawType::TRANSPARENT_ALL, - .isSelected = selectedLicense == i, + .isSelected = selectedLicense == -1, .wide = true, - .onClick = [&, i] { selectedLicense = i; } + .onClick = [&] { selectedLicense = -1; } }); } + text_label_light_centered(gui, "Third Party Components"); + for(int i = 0; i < static_cast(thirdPartyLicenses.size()); i++) { + CLAY_AUTO_ID({ + .layout = { + .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(0) }, + .padding = CLAY_PADDING_ALL(1) + } + }) { + gui.new_id(i, [&] { + text_button(gui, "noticebutton", thirdPartyLicenses[i].first, { + .drawType = SelectableButton::DrawType::TRANSPARENT_ALL, + .isSelected = selectedLicense == i, + .wide = true, + .onClick = [&, i] { selectedLicense = i; } + }); + }); + } + } } - } - }); - } - gui.pop_id(); + }); + } + }); gui.element("About Menu Text Scroll Area", ScrollArea::Options{ .scrollVertical = true,