From 80afacfcbd66538b65841b737c57aedfb39eb93b Mon Sep 17 00:00:00 2001 From: Yousef Khadadeh Date: Tue, 31 Mar 2026 20:52:46 +0300 Subject: [PATCH] Fixed rotation wheel --- src/DrawingProgram/DrawingProgram.cpp | 8 ++--- src/GUIStuff/ElementHelpers/ButtonHelpers.cpp | 3 +- src/GUIStuff/ElementHelpers/LayoutHelpers.cpp | 2 +- .../Elements/ColorPickerButton.impl.hpp | 6 +++- src/GUIStuff/Elements/RotateWheel.cpp | 14 ++++---- src/GUIStuff/Elements/RotateWheel.hpp | 4 +-- src/GUIStuff/Elements/ScrollArea.cpp | 12 +++++-- src/GUIStuff/Elements/ScrollArea.hpp | 1 + src/Toolbar.cpp | 33 ++++++++++--------- 9 files changed, 50 insertions(+), 33 deletions(-) diff --git a/src/DrawingProgram/DrawingProgram.cpp b/src/DrawingProgram/DrawingProgram.cpp index 80e0a5c..6deb976 100644 --- a/src/DrawingProgram/DrawingProgram.cpp +++ b/src/DrawingProgram/DrawingProgram.cpp @@ -368,10 +368,10 @@ void DrawingProgram::toolbar_gui() { 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); - 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; + std::shared_ptr newRotationAngle = std::make_shared(world.drawData.cam.c.rotation); + gui.element("Canvas Rotate Wheel", newRotationAngle.get(), [&, newRotationAngle] { + world.drawData.cam.c.rotate_about(world.drawData.cam.c.from_space(world.main.window.size.cast() * 0.5f), *newRotationAngle - world.drawData.cam.c.rotation); + *newRotationAngle = world.drawData.cam.c.rotation; }); } }); diff --git a/src/GUIStuff/ElementHelpers/ButtonHelpers.cpp b/src/GUIStuff/ElementHelpers/ButtonHelpers.cpp index 23970d2..1203404 100644 --- a/src/GUIStuff/ElementHelpers/ButtonHelpers.cpp +++ b/src/GUIStuff/ElementHelpers/ButtonHelpers.cpp @@ -18,7 +18,8 @@ void text_button(GUIManager& gui, const char* id, std::string_view text, const T }; CLAY_AUTO_ID({ .layout = { - .sizing = {.width = options.wide ? CLAY_SIZING_GROW(0) : CLAY_SIZING_FIT(0), .height = CLAY_SIZING_FIT(0) } + .sizing = {.width = options.wide ? CLAY_SIZING_GROW(0) : CLAY_SIZING_FIT(0), .height = CLAY_SIZING_FIT(0) }, + .childAlignment = {.x = options.centered ? CLAY_ALIGN_X_CENTER : CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER} } }) { gui.element(id, d); diff --git a/src/GUIStuff/ElementHelpers/LayoutHelpers.cpp b/src/GUIStuff/ElementHelpers/LayoutHelpers.cpp index 18d3cce..a5df0c9 100644 --- a/src/GUIStuff/ElementHelpers/LayoutHelpers.cpp +++ b/src/GUIStuff/ElementHelpers/LayoutHelpers.cpp @@ -14,7 +14,7 @@ void top_to_bottom_window_popup_layout(GUIManager& gui, const char* id, Clay_Siz }, .backgroundColor = convert_vec4(gui.io.theme->backColor1), .cornerRadius = CLAY_CORNER_RADIUS(10), - .floating = { .attachTo = CLAY_ATTACH_TO_PARENT }, + .floating = { .zIndex = gui.zIndex, .attachTo = CLAY_ATTACH_TO_PARENT }, .border = {.color = convert_vec4(gui.io.theme->fillColor2), .width = CLAY_BORDER_OUTSIDE(1)} }) { innerContent(); diff --git a/src/GUIStuff/Elements/ColorPickerButton.impl.hpp b/src/GUIStuff/Elements/ColorPickerButton.impl.hpp index b543c7a..148c9b7 100644 --- a/src/GUIStuff/Elements/ColorPickerButton.impl.hpp +++ b/src/GUIStuff/Elements/ColorPickerButton.impl.hpp @@ -18,6 +18,7 @@ template void ColorPickerButton::layout(const Clay_ElementId& id } }); if(isOpen) { + gui.zIndex++; ElementHelpers::top_to_bottom_window_popup_layout(gui, "Color Picker", CLAY_SIZING_FIT(300), CLAY_SIZING_FIT(0), [&, val, data = data]() { ElementHelpers::color_picker_items(gui, "c", val, { .hasAlpha = data.hasAlpha, @@ -25,11 +26,14 @@ template void ColorPickerButton::layout(const Clay_ElementId& id }); }, { .mouseButton = [&](const InputManager::MouseButtonCallbackArgs& button, bool mouseHovering) { - if(!mouseHovering && button.button == InputManager::MouseButton::LEFT && button.down) + if(!mouseHovering && button.button == InputManager::MouseButton::LEFT && button.down) { isOpen = false; + gui.set_to_layout(); + } return mouseHovering; } }); + gui.zIndex--; } } diff --git a/src/GUIStuff/Elements/RotateWheel.cpp b/src/GUIStuff/Elements/RotateWheel.cpp index d8165de..e6366f5 100644 --- a/src/GUIStuff/Elements/RotateWheel.cpp +++ b/src/GUIStuff/Elements/RotateWheel.cpp @@ -37,21 +37,22 @@ float RotateWheel::wheel_end() { bool RotateWheel::input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button, bool mouseHovering) { isHovering = mouseHovering; isHeld = isHovering && button.button == InputManager::MouseButton::LEFT && button.down; - update_paint_circle_menu_mouse(button.pos, button.button == InputManager::MouseButton::LEFT && button.down); + isRotateBarHeld = isRotateBarHovered && isHeld; + update_paint_circle_menu_mouse(button.pos); return Element::input_mouse_button_callback(button, mouseHovering); } bool RotateWheel::input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion, bool mouseHovering) { - update_paint_circle_menu_mouse(motion.pos, false); + isHovering = mouseHovering; + update_paint_circle_menu_mouse(motion.pos); return Element::input_mouse_motion_callback(motion, mouseHovering); } -void RotateWheel::update_paint_circle_menu_mouse(const Vector2f& p, bool leftClicked) { +void RotateWheel::update_paint_circle_menu_mouse(const Vector2f& p) { if(boundingBox.has_value()) { Vector2f vecFromCenter = (p - boundingBox.value().center()).normalized(); float distFromCenter = vec_distance(p, boundingBox.value().center()); isRotateBarHovered = isHovering && distFromCenter > wheel_start() && distFromCenter < wheel_end(); - isRotateBarHeld = isRotateBarHovered && isHeld; if(isRotateBarHeld) { gui.set_post_callback_func([&, vecFromCenter] { @@ -67,6 +68,7 @@ void RotateWheel::update_paint_circle_menu_mouse(const Vector2f& p, bool leftCli } } } + onChange(); }); } } @@ -105,9 +107,9 @@ void RotateWheel::draw_rotate_wheel(SkCanvas* canvas, UpdateInputData& io, bool SkPaint rotateBarHolderFill; rotateBarHolderFill.setAntiAlias(skiaAA); - if(selection.held) + if(isRotateBarHeld) rotateBarHolderFill.setColor4f(io.theme->fillColor1); - else if(selection.hovered) + else if(isRotateBarHovered) rotateBarHolderFill.setColor4f(io.theme->fillColor2); else rotateBarHolderFill.setColor4f(io.theme->frontColor2); diff --git a/src/GUIStuff/Elements/RotateWheel.hpp b/src/GUIStuff/Elements/RotateWheel.hpp index 5ac7feb..7bb706c 100644 --- a/src/GUIStuff/Elements/RotateWheel.hpp +++ b/src/GUIStuff/Elements/RotateWheel.hpp @@ -10,7 +10,7 @@ class RotateWheel : public Element { virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override; virtual bool input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button, bool mouseHovering) override; virtual bool input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion, bool mouseHovering) override; - SelectionHelper selection; + private: float wheel_start(); float wheel_end(); @@ -23,7 +23,7 @@ class RotateWheel : public Element { bool isRotateBarHovered = false; std::function onChange; - void update_paint_circle_menu_mouse(const Vector2f& p, bool leftClicked); + void update_paint_circle_menu_mouse(const Vector2f& p); }; } diff --git a/src/GUIStuff/Elements/ScrollArea.cpp b/src/GUIStuff/Elements/ScrollArea.cpp index 1097799..fd8a681 100644 --- a/src/GUIStuff/Elements/ScrollArea.cpp +++ b/src/GUIStuff/Elements/ScrollArea.cpp @@ -19,6 +19,8 @@ void ScrollArea::layout(const Clay_ElementId& id, const Options& options) { containerDimensions = {scrollData.scrollContainerDimensions.width, scrollData.scrollContainerDimensions.height}; } + clamp_scroll(); + CLAY(localID, { .layout = { .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}, @@ -103,12 +105,18 @@ bool ScrollArea::input_mouse_motion_callback(const InputManager::MouseMotionCall return Element::input_mouse_motion_callback(motion, mouseHovering); } +void ScrollArea::clamp_scroll() { + scrollOffset.x() = std::clamp(scrollOffset.x(), -std::max(0.0f, contentDimensions.x() - containerDimensions.x()), 0.0f); + scrollOffset.y() = std::clamp(scrollOffset.y(), -std::max(0.0f, contentDimensions.y() - containerDimensions.y()), 0.0f); +} + bool ScrollArea::input_mouse_wheel_callback(const InputManager::MouseWheelCallbackArgs& wheel, bool mouseHovering) { if(mouseHovering) { if(opts.scrollVertical) - scrollOffset.y() += wheel.amount.y(); + scrollOffset.y() = scrollOffset.y() + wheel.amount.y() * 10.0f; if(opts.scrollHorizontal) - scrollOffset.x() += wheel.amount.x(); + scrollOffset.y() = scrollOffset.x() + wheel.amount.x() * 10.0f; + clamp_scroll(); gui.set_to_layout(); } return Element::input_mouse_wheel_callback(wheel, mouseHovering); diff --git a/src/GUIStuff/Elements/ScrollArea.hpp b/src/GUIStuff/Elements/ScrollArea.hpp index 4835894..9b75986 100644 --- a/src/GUIStuff/Elements/ScrollArea.hpp +++ b/src/GUIStuff/Elements/ScrollArea.hpp @@ -37,6 +37,7 @@ class ScrollArea : public Element { Vector2f contentDimensions = {0.0f, 0.0f}; Vector2f containerDimensions = {0.0f, 0.0f}; Vector2f scrollOffset = {0.0f, 0.0f}; + void clamp_scroll(); }; } diff --git a/src/Toolbar.cpp b/src/Toolbar.cpp index bd7699b..61813e9 100644 --- a/src/Toolbar.cpp +++ b/src/Toolbar.cpp @@ -425,18 +425,18 @@ void Toolbar::top_toolbar() { auto& gui = main.g.gui; auto& io = gui.io; - CLAY_AUTO_ID({ - .layout = { - .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(0) }, - .padding = CLAY_PADDING_ALL(static_cast(io.theme->padding1 / 2)), - .childGap = static_cast(io.theme->childGap1 / 2), - .childAlignment = { .x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER}, - .layoutDirection = CLAY_LEFT_TO_RIGHT - }, - .backgroundColor = convert_vec4(io.theme->backColor1), - .cornerRadius = CLAY_CORNER_RADIUS(io.theme->windowCorners1) - }) { - gui.new_id("menu top toolbar", [&] { + gui.element("top menu bar", [&] (const Clay_ElementId& lId) { + CLAY(lId, { + .layout = { + .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(0) }, + .padding = CLAY_PADDING_ALL(static_cast(io.theme->padding1 / 2)), + .childGap = static_cast(io.theme->childGap1 / 2), + .childAlignment = { .x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER}, + .layoutDirection = CLAY_LEFT_TO_RIGHT + }, + .backgroundColor = convert_vec4(io.theme->backColor1), + .cornerRadius = CLAY_CORNER_RADIUS(io.theme->windowCorners1) + }) { global_log(); bool bookmarkMenuPopUpJustOpen = false; bool gridMenuPopUpJustOpen = false; @@ -551,7 +551,7 @@ void Toolbar::top_toolbar() { .drawType = SelectableButton::DrawType::TRANSPARENT_ALL, .wide = true, .centered = false, - .onClick = [&]{ + .onClick = [&, onClick]{ onClick(); menuPopUpOpen = false; } @@ -638,8 +638,8 @@ void Toolbar::top_toolbar() { } }); } - }); - } + } + }); } void Toolbar::web_version_welcome() { @@ -1658,7 +1658,8 @@ void Toolbar::general_settings_inner_gui() { .drawType = SelectableButton::DrawType::TRANSPARENT_ALL, .isSelected = generalSettingsOptions == opt, .wide = true, - .onClick = [&] { + .centered = false, + .onClick = [&, opt] { main.g.load_theme(main.configPath, main.conf.themeCurrentlyLoaded); themeData.selectedThemeIndex = std::nullopt; generalSettingsOptions = opt;