Added mini rotate wheel to toolbar
This commit is contained in:
parent
7ad86c27fe
commit
658799610b
6 changed files with 148 additions and 0 deletions
|
|
@ -91,6 +91,7 @@ set(sources "src/main.cpp"
|
|||
"src/GUIStuff/Elements/SelectableButton.cpp"
|
||||
"src/GUIStuff/Elements/MovableTabList.cpp"
|
||||
"src/GUIStuff/Elements/PaintCircleMenu.cpp"
|
||||
"src/GUIStuff/Elements/RotateWheel.cpp"
|
||||
"include/sago/platform_folders.cpp"
|
||||
"include/Helpers/Networking/NetLibrary.cpp"
|
||||
"include/Helpers/Networking/NetServer.cpp"
|
||||
|
|
|
|||
|
|
@ -201,6 +201,12 @@ void DrawingProgram::toolbar_gui() {
|
|||
if(t.gui.svg_icon_button("Eyedropper Toolbar Button", "data/icons/eyedropper.svg", drawTool->get_type() == DrawingProgramToolType::EYEDROPPER)) { switch_to_tool(DrawingProgramToolType::EYEDROPPER); }
|
||||
if(t.gui.svg_icon_button("Zoom Canvas Toolbar Button", "data/icons/zoom.svg", drawTool->get_type() == DrawingProgramToolType::ZOOM)) { switch_to_tool(DrawingProgramToolType::ZOOM); }
|
||||
if(t.gui.svg_icon_button("Pan Canvas Toolbar Button", "data/icons/hand.svg", drawTool->get_type() == DrawingProgramToolType::PAN)) { switch_to_tool(DrawingProgramToolType::PAN); }
|
||||
|
||||
double newRotationAngle = world.drawData.cam.c.rotation, oldRotationAngle = world.drawData.cam.c.rotation;
|
||||
t.gui.rotate_wheel("Canvas Rotate Wheel", &newRotationAngle);
|
||||
if(newRotationAngle != oldRotationAngle)
|
||||
world.drawData.cam.c.rotate_about(world.drawData.cam.c.from_space(world.main.window.size.cast<float>() * 0.5f), newRotationAngle - oldRotationAngle);
|
||||
|
||||
CLAY({.layout = {.sizing = {.width = CLAY_SIZING_FIXED(40), .height = CLAY_SIZING_FIXED(40)}}}) {
|
||||
if(t.gui.color_button("Foreground Color", &controls.foregroundColor, &controls.foregroundColor == t.colorLeft)) {
|
||||
t.color_selector_left(&controls.foregroundColor == t.colorLeft ? nullptr : &controls.foregroundColor);
|
||||
|
|
|
|||
105
src/GUIStuff/Elements/RotateWheel.cpp
Normal file
105
src/GUIStuff/Elements/RotateWheel.cpp
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
#include "RotateWheel.hpp"
|
||||
#include "Helpers/ConvertVec.hpp"
|
||||
|
||||
namespace GUIStuff {
|
||||
|
||||
constexpr float WHEEL_WIDTH = 15.0f;
|
||||
|
||||
constexpr double ROTATE_BAR_SNAP_DISTANCE = 0.3;
|
||||
constexpr double ROTATE_BAR_SNAP_DISTRIBUTION = std::numbers::pi * 0.25;
|
||||
|
||||
void RotateWheel::update(UpdateInputData& io, double* newRotationAnglePtr, const std::function<void()>& elemUpdate) {
|
||||
rotateAngle = 0.0f;
|
||||
if(!newRotationAnglePtr)
|
||||
return;
|
||||
|
||||
CLAY({.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}
|
||||
},
|
||||
.custom = { .customData = this }
|
||||
}) {
|
||||
selection.update(Clay_Hovered(), io.mouse.leftClick, io.mouse.leftHeld);
|
||||
Vector2f vecFromCenter = (io.mouse.pos - bb.center()).normalized();
|
||||
float distFromCenter = vec_distance(io.mouse.pos, bb.center());
|
||||
wheelHovered = selection.hovered && distFromCenter > wheel_start() && distFromCenter < wheel_end();
|
||||
if(selection.held) {
|
||||
double& newRotationAngle = *newRotationAnglePtr;
|
||||
newRotationAngle = std::atan2(vecFromCenter.y(), -vecFromCenter.x()) + std::numbers::pi;
|
||||
if(wheelHovered) { // If we're hovering over the rotation bar, we should try snapping to specific angles
|
||||
for(double snapPos = 0.0; snapPos < std::numbers::pi * 2.0 + 0.001; snapPos += ROTATE_BAR_SNAP_DISTRIBUTION) {
|
||||
if(std::fabs(newRotationAngle - snapPos) < ROTATE_BAR_SNAP_DISTANCE) {
|
||||
newRotationAngle = snapPos;
|
||||
if(newRotationAngle >= std::numbers::pi * 2.0 - 0.001) // Set 2pi back to 0
|
||||
newRotationAngle = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(elemUpdate)
|
||||
elemUpdate();
|
||||
}
|
||||
|
||||
rotateAngle = *newRotationAnglePtr;
|
||||
}
|
||||
|
||||
float RotateWheel::wheel_start() {
|
||||
return wheel_end() - WHEEL_WIDTH;
|
||||
}
|
||||
|
||||
float RotateWheel::wheel_end() {
|
||||
return bb.width() * 0.5f;
|
||||
}
|
||||
|
||||
void RotateWheel::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) {
|
||||
bb = get_bb(command);
|
||||
canvas->save();
|
||||
canvas->translate(bb.center().x(), bb.center().y());
|
||||
|
||||
draw_rotate_wheel(canvas, io);
|
||||
|
||||
canvas->restore();
|
||||
}
|
||||
|
||||
void RotateWheel::draw_rotate_wheel(SkCanvas* canvas, UpdateInputData& io) {
|
||||
float wheelStart = wheel_start();
|
||||
float wheelEnd = wheel_end();
|
||||
|
||||
float rotateBarMiddleRadius = (wheelEnd + wheelStart) / 2.0f;
|
||||
SkPaint rotateBarFill(io.theme->backColor2);
|
||||
rotateBarFill.setStroke(true);
|
||||
rotateBarFill.setStrokeWidth(wheelEnd - wheelStart);
|
||||
canvas->drawCircle(0.0f, 0.0f, rotateBarMiddleRadius, rotateBarFill);
|
||||
|
||||
if(wheelHovered) {
|
||||
for(double snapPos = 0.0; snapPos < std::numbers::pi * 2.0; snapPos += ROTATE_BAR_SNAP_DISTRIBUTION) {
|
||||
Vector2f lineDir{std::cos(snapPos), -std::sin(snapPos)};
|
||||
SkPaint p(snapPos == 0.0 ? io.theme->fillColor1 : io.theme->frontColor2);
|
||||
p.setStrokeWidth(2.0f);
|
||||
canvas->drawLine(lineDir.x() * wheelStart, lineDir.y() * wheelStart, lineDir.x() * wheelEnd, lineDir.y() * wheelEnd, p);
|
||||
}
|
||||
}
|
||||
|
||||
SkPaint rotateBarHolderFill;
|
||||
if(selection.held)
|
||||
rotateBarHolderFill.setColor4f(io.theme->fillColor1);
|
||||
else if(selection.hovered)
|
||||
rotateBarHolderFill.setColor4f(io.theme->fillColor2);
|
||||
else
|
||||
rotateBarHolderFill.setColor4f(io.theme->frontColor2);
|
||||
float rotateBarHolderRadius = (wheelEnd - wheelStart) / 2.0f;
|
||||
Vector2f rotateBarHolderPos{std::cos(rotateAngle) * rotateBarMiddleRadius, -std::sin(rotateAngle) * rotateBarMiddleRadius};
|
||||
canvas->drawCircle(rotateBarHolderPos.x(), rotateBarHolderPos.y(), rotateBarHolderRadius, rotateBarHolderFill);
|
||||
SkPaint rotateBarHolderOutline(io.theme->frontColor1);
|
||||
rotateBarHolderOutline.setStroke(true);
|
||||
rotateBarHolderOutline.setStrokeWidth(2.0f);
|
||||
canvas->drawCircle(rotateBarHolderPos.x(), rotateBarHolderPos.y(), rotateBarHolderRadius, rotateBarHolderOutline);
|
||||
|
||||
SkPaint rotateBarOutline(io.theme->frontColor2);
|
||||
rotateBarOutline.setStroke(true);
|
||||
rotateBarOutline.setStrokeWidth(2.0f);
|
||||
canvas->drawCircle(0.0f, 0.0f, wheelStart, rotateBarOutline);
|
||||
canvas->drawCircle(0.0f, 0.0f, wheelEnd, rotateBarOutline);
|
||||
}
|
||||
|
||||
}
|
||||
21
src/GUIStuff/Elements/RotateWheel.hpp
Normal file
21
src/GUIStuff/Elements/RotateWheel.hpp
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#pragma once
|
||||
#include "Element.hpp"
|
||||
|
||||
namespace GUIStuff {
|
||||
|
||||
class RotateWheel : public Element {
|
||||
public:
|
||||
void update(UpdateInputData& io, double* newRotationAnglePtr, const std::function<void()>& elemUpdate);
|
||||
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) override;
|
||||
SelectionHelper selection;
|
||||
private:
|
||||
float wheel_start();
|
||||
float wheel_end();
|
||||
void draw_rotate_wheel(SkCanvas* canvas, UpdateInputData& io);
|
||||
|
||||
double rotateAngle = 0.0f;
|
||||
SCollision::AABB<float> bb;
|
||||
bool wheelHovered;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@
|
|||
#include <include/core/SkPath.h>
|
||||
#include "Elements/SVGIcon.hpp"
|
||||
#include "Elements/SelectableButton.hpp"
|
||||
#include "Elements/RotateWheel.hpp"
|
||||
#include "Elements/MovableTabList.hpp"
|
||||
#include "Elements/Element.hpp"
|
||||
#include <Helpers/ConvertVec.hpp>
|
||||
|
|
@ -660,6 +661,18 @@ void GUIManager::scroll_bar_many_entries_area(const std::string& uniqueId, float
|
|||
pop_id();
|
||||
}
|
||||
|
||||
bool GUIManager::rotate_wheel(const std::string& id, double* angle, float size, const std::function<void()>& elemUpdate) {
|
||||
bool toRet = false;
|
||||
push_id(id);
|
||||
CLAY ({.layout = {.sizing = {.width = CLAY_SIZING_FIXED(size), .height = CLAY_SIZING_FIXED(size) } } }) {
|
||||
RotateWheel* e = insert_element<RotateWheel>();
|
||||
e->update(*io, angle, elemUpdate);
|
||||
toRet = e->selection.clicked;
|
||||
}
|
||||
pop_id();
|
||||
return toRet;
|
||||
}
|
||||
|
||||
void GUIManager::paint_circle_popup_menu(const std::string& id, const Vector2f& centerPos, const PaintCircleMenu::Data& val, const std::function<void()>& elemUpdate) {
|
||||
float size = 300.0f;
|
||||
push_id(id);
|
||||
|
|
|
|||
|
|
@ -53,6 +53,8 @@ class GUIManager {
|
|||
void svg_icon(const std::string& id, const std::string& svgPath, bool isHighlighted = false, const std::function<void()>& elemUpdate = nullptr);
|
||||
bool svg_icon_button(const std::string& id, const std::string& svgPath, bool isSelected = false, float size = 40.0f, bool hasBorder = true, const std::function<void()>& elemUpdate = nullptr);
|
||||
|
||||
bool rotate_wheel(const std::string& id, double* angle, float size = 40.0f, const std::function<void()>& elemUpdate = nullptr);
|
||||
|
||||
void top_to_bottom_window_popup_layout(Clay_SizingAxis x, Clay_SizingAxis y, const std::function<void()>& elemUpdate);
|
||||
void left_to_right_layout(Clay_SizingAxis x, Clay_SizingAxis y, const std::function<void()>& elemUpdate);
|
||||
void left_to_right_line_layout(const std::function<void()>& elemUpdate);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue