diff --git a/src/DrawingProgram/DrawingProgram.cpp b/src/DrawingProgram/DrawingProgram.cpp index c065f40..ef6d9f0 100644 --- a/src/DrawingProgram/DrawingProgram.cpp +++ b/src/DrawingProgram/DrawingProgram.cpp @@ -52,6 +52,8 @@ void DrawingProgram::server_init_no_file() { void DrawingProgram::scale_up(const WorldScalar& scaleUpAmount) { selection.deselect_all(); layerMan.scale_up(scaleUpAmount); + if(controls.lockedCameraScale.has_value()) + controls.lockedCameraScale.value() *= scaleUpAmount; rebuild_cache(); switch_to_tool(drawTool->get_type() == DrawingProgramToolType::GRIDMODIFY ? DrawingProgramToolType::EDIT : drawTool->get_type(), true); } diff --git a/src/DrawingProgram/DrawingProgram.hpp b/src/DrawingProgram/DrawingProgram.hpp index 094b2ca..439c87c 100644 --- a/src/DrawingProgram/DrawingProgram.hpp +++ b/src/DrawingProgram/DrawingProgram.hpp @@ -1,6 +1,7 @@ #pragma once #include "../DrawData.hpp" #include "DrawingProgramCache.hpp" +#include "ToolConfiguration.hpp" #include "Tools/GridModifyTool.hpp" #include #include "Tools/PanCanvasTool.hpp" @@ -92,6 +93,8 @@ class DrawingProgram { DrawingProgramToolType toolTypeAfterTempMove; struct GlobalControls { + std::optional lockedCameraScale; + WorldVec previousMouseWorldPos = {0, 0}; WorldVec currentMouseWorldPos = {0, 0}; bool leftClick = false; @@ -143,4 +146,5 @@ class DrawingProgram { friend class DrawingProgramLayerManager; friend class DrawingProgramLayer; friend class DrawingProgramLayerFolder; + friend class ToolConfiguration; }; diff --git a/src/DrawingProgram/ToolConfiguration.cpp b/src/DrawingProgram/ToolConfiguration.cpp index 28f76b1..25400c4 100644 --- a/src/DrawingProgram/ToolConfiguration.cpp +++ b/src/DrawingProgram/ToolConfiguration.cpp @@ -1,9 +1,39 @@ #include "ToolConfiguration.hpp" +#include "DrawingProgram.hpp" +#include "../World.hpp" +#include "../MainProgram.hpp" +#include "Helpers/FixedPoint.hpp" +#include +#include "Helpers/Logger.hpp" -float ToolConfiguration::get_relative_width(float relativeWidthLocal) const { - return globalConf.useGlobalRelativeWidth ? globalConf.relativeWidth : relativeWidthLocal; +float ToolConfiguration::get_relative_width(DrawingProgram& drawP, const WorldScalar& camInverseScale, float relativeWidthLocal) const { + auto& lockedCameraScale = drawP.controls.lockedCameraScale; + float relativeWidth = globalConf.useGlobalRelativeWidth ? globalConf.relativeWidth : relativeWidthLocal; + if(lockedCameraScale.has_value()) { + float lockMultiplier = static_cast(WorldMultiplier(lockedCameraScale.value()) / WorldMultiplier(camInverseScale)); + if(lockMultiplier < 0.001f) { + Logger::get().log("USERINFO", "Zoomed out too much, size unlocked"); + lockedCameraScale = std::nullopt; + return relativeWidth; + } + else if(lockMultiplier > 1000.0f) { + Logger::get().log("USERINFO", "Zoomed in too much, size unlocked"); + lockedCameraScale = std::nullopt; + return relativeWidth; + } + return relativeWidth * lockMultiplier; + } + return relativeWidth; } -void ToolConfiguration::relative_width_slider(GUIStuff::GUIManager& gui, const char* label, float* relativeWidthLocal) { +void ToolConfiguration::relative_width_gui(DrawingProgram& drawP, const char* label, float* relativeWidthLocal) { + auto& gui = drawP.world.main.toolbar.gui; + auto& lockedCameraScale = drawP.controls.lockedCameraScale; gui.slider_scalar_field("relstrokewidth", label, globalConf.useGlobalRelativeWidth ? &globalConf.relativeWidth : relativeWidthLocal, 3.0f, 40.0f); + if(gui.text_button_wide("lock brush size", lockedCameraScale.has_value() ? "Unlock Brush Size" : "Lock Brush Size")) { + if(lockedCameraScale.has_value()) + lockedCameraScale = std::nullopt; + else + lockedCameraScale = drawP.world.drawData.cam.c.inverseScale; + } } diff --git a/src/DrawingProgram/ToolConfiguration.hpp b/src/DrawingProgram/ToolConfiguration.hpp index 97c0dd7..050bcf6 100644 --- a/src/DrawingProgram/ToolConfiguration.hpp +++ b/src/DrawingProgram/ToolConfiguration.hpp @@ -56,8 +56,8 @@ class ToolConfiguration { NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GlobalConfig, useGlobalRelativeWidth, foregroundColor, backgroundColor, relativeWidth) } globalConf; - float get_relative_width(float relativeWidthLocal) const; - void relative_width_slider(GUIStuff::GUIManager& gui, const char* label, float* relativeWidthLocal); + float get_relative_width(DrawingProgram& drawP, const WorldScalar& camInverseScale, float relativeWidthLocal) const; + void relative_width_gui(DrawingProgram& drawP, const char* label, float* relativeWidthLocal); NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(ToolConfiguration, brush, eraser, ellipseDraw, rectDraw, eyeDropper, lineDraw, screenshot, globalConf) }; diff --git a/src/DrawingProgram/Tools/BrushTool.cpp b/src/DrawingProgram/Tools/BrushTool.cpp index 5224342..f59c88c 100644 --- a/src/DrawingProgram/Tools/BrushTool.cpp +++ b/src/DrawingProgram/Tools/BrushTool.cpp @@ -96,7 +96,7 @@ void BrushTool::tool_update() { BrushStrokeCanvasComponentPoint p; p.pos = drawP.world.main.input.mouse.pos; - p.width = toolConfig.get_relative_width(toolConfig.brush.relativeWidth) * penWidth; + p.width = toolConfig.get_relative_width(drawP, drawP.world.drawData.cam.c.inverseScale, toolConfig.brush.relativeWidth) * penWidth; prevPointUnaltered = p.pos; newBrushStroke.d.points->emplace_back(p); newBrushStroke.d.color = toolConfig.globalConf.foregroundColor; @@ -113,7 +113,7 @@ void BrushTool::tool_update() { BrushStrokeCanvasComponentPoint p; p.pos = containerPtr->coords.get_mouse_pos(drawP.world); - p.width = toolConfig.get_relative_width(toolConfig.brush.relativeWidth) * penWidth; + p.width = toolConfig.get_relative_width(drawP, containerPtr->coords.inverseScale, toolConfig.brush.relativeWidth) * penWidth; if(!addedTemporaryPoint) { if(extensive_point_checking(brushStroke, p.pos)) { @@ -132,7 +132,7 @@ void BrushTool::tool_update() { brushPoints.back().width = std::max(brushPoints.back().width, p.width); brushPoints[brushPoints.size() - 2].width = std::max(brushPoints[brushPoints.size() - 2].width, p.width); } - if((!drawingMinimumRelativeToSize && distToPrev >= 10.0) || (drawingMinimumRelativeToSize && distToPrev >= toolConfig.get_relative_width(toolConfig.brush.relativeWidth) * BrushStrokeCanvasComponent::DRAW_MINIMUM_LIMIT)) { + if((!drawingMinimumRelativeToSize && distToPrev >= 10.0) || (drawingMinimumRelativeToSize && distToPrev >= toolConfig.get_relative_width(drawP, containerPtr->coords.inverseScale, toolConfig.brush.relativeWidth) * BrushStrokeCanvasComponent::DRAW_MINIMUM_LIMIT)) { brushPoints.back() = p; addedTemporaryPoint = false; @@ -167,7 +167,7 @@ void BrushTool::gui_toolbox() { t.gui.push_id("brush tool"); t.gui.text_label_centered("Brush"); t.gui.checkbox_field("hasroundcaps", "Round Caps", &drawP.world.main.toolConfig.brush.hasRoundCaps); - drawP.world.main.toolConfig.relative_width_slider(t.gui, "Size", &drawP.world.main.toolConfig.brush.relativeWidth); + drawP.world.main.toolConfig.relative_width_gui(drawP, "Size", &drawP.world.main.toolConfig.brush.relativeWidth); t.gui.pop_id(); } @@ -187,7 +187,7 @@ void BrushTool::draw(SkCanvas* canvas, const DrawData& drawData) { linePaint.setColor4f(drawP.world.canvasTheme.get_tool_front_color()); linePaint.setStroke(true); linePaint.setStrokeWidth(0.0f); - float width = drawP.world.main.toolConfig.get_relative_width(drawP.world.main.toolConfig.brush.relativeWidth); + float width = drawP.world.main.toolConfig.get_relative_width(drawP, drawP.world.drawData.cam.c.inverseScale, drawP.world.main.toolConfig.brush.relativeWidth); if(objInfoBeingEdited) width *= penWidth * 0.5f; else diff --git a/src/DrawingProgram/Tools/EllipseDrawTool.cpp b/src/DrawingProgram/Tools/EllipseDrawTool.cpp index e3c4068..ba008a4 100644 --- a/src/DrawingProgram/Tools/EllipseDrawTool.cpp +++ b/src/DrawingProgram/Tools/EllipseDrawTool.cpp @@ -27,7 +27,7 @@ void EllipseDrawTool::gui_toolbox() { if(t.gui.radio_button_field("outlineonly", "Outline only", fillStrokeMode == 1)) fillStrokeMode = 1; if(t.gui.radio_button_field("filloutline", "Fill and Outline", fillStrokeMode == 2)) fillStrokeMode = 2; if(fillStrokeMode == 1 || fillStrokeMode == 2) - toolConfig.relative_width_slider(t.gui, "Outline Size", &toolConfig.ellipseDraw.relativeWidth); + toolConfig.relative_width_gui(drawP, "Outline Size", &toolConfig.ellipseDraw.relativeWidth); t.gui.pop_id(); } @@ -57,7 +57,7 @@ void EllipseDrawTool::tool_update() { startAt = drawP.world.main.input.mouse.pos; newEllipse.d.strokeColor = toolConfig.globalConf.foregroundColor; newEllipse.d.fillColor = toolConfig.globalConf.backgroundColor; - newEllipse.d.strokeWidth = toolConfig.get_relative_width(toolConfig.ellipseDraw.relativeWidth); + newEllipse.d.strokeWidth = toolConfig.get_relative_width(drawP, drawP.world.drawData.cam.c.inverseScale, toolConfig.ellipseDraw.relativeWidth); newEllipse.d.p1 = startAt; newEllipse.d.p2 = startAt; newEllipse.d.p2 = ensure_points_have_distance(newEllipse.d.p1, newEllipse.d.p2, MINIMUM_DISTANCE_BETWEEN_BOUNDS); diff --git a/src/DrawingProgram/Tools/EraserTool.cpp b/src/DrawingProgram/Tools/EraserTool.cpp index 70c6c8f..9834caf 100644 --- a/src/DrawingProgram/Tools/EraserTool.cpp +++ b/src/DrawingProgram/Tools/EraserTool.cpp @@ -16,7 +16,7 @@ void EraserTool::gui_toolbox() { Toolbar& t = drawP.world.main.toolbar; t.gui.push_id("eraser tool"); t.gui.text_label_centered("Eraser"); - drawP.world.main.toolConfig.relative_width_slider(t.gui, "Size", &drawP.world.main.toolConfig.eraser.relativeWidth); + drawP.world.main.toolConfig.relative_width_gui(drawP, "Size", &drawP.world.main.toolConfig.eraser.relativeWidth); t.gui.text_label("Erase from:"); if(t.gui.radio_button_field("layer edited", "Layer being edited", drawP.controls.layerSelector == DrawingProgramLayerManager::LayerSelector::LAYER_BEING_EDITED)) drawP.controls.layerSelector = DrawingProgramLayerManager::LayerSelector::LAYER_BEING_EDITED; @@ -46,7 +46,7 @@ void EraserTool::tool_update() { if(drawP.controls.leftClickHeld) { const Vector2f& prevMousePos = drawP.controls.leftClick ? drawP.world.main.input.mouse.pos : drawP.world.main.input.mouse.lastPos; SCollision::ColliderCollection cC; - float width = drawP.world.main.toolConfig.get_relative_width(drawP.world.main.toolConfig.eraser.relativeWidth); + float width = drawP.world.main.toolConfig.get_relative_width(drawP, drawP.world.drawData.cam.c.inverseScale, drawP.world.main.toolConfig.eraser.relativeWidth); SCollision::generate_wide_line(cC, prevMousePos, drawP.world.main.input.mouse.pos, width * 2.0f, true); auto cCWorld = drawP.world.drawData.cam.c.collider_to_world, SCollision::ColliderCollection>(cC); @@ -97,7 +97,7 @@ void EraserTool::draw(SkCanvas* canvas, const DrawData& drawData) { linePaint.setColor4f(c); linePaint.setStyle(SkPaint::kStroke_Style); linePaint.setStrokeCap(SkPaint::kRound_Cap); - float width = drawP.world.main.toolConfig.get_relative_width(drawP.world.main.toolConfig.eraser.relativeWidth); + float width = drawP.world.main.toolConfig.get_relative_width(drawP, drawP.world.drawData.cam.c.inverseScale, drawP.world.main.toolConfig.eraser.relativeWidth); linePaint.setStrokeWidth(width * 2.0f); SkPathBuilder erasePath; erasePath.moveTo(convert_vec2(drawData.main->input.mouse.lastPos)); diff --git a/src/DrawingProgram/Tools/LineDrawTool.cpp b/src/DrawingProgram/Tools/LineDrawTool.cpp index e1f6e11..e1fbeb1 100644 --- a/src/DrawingProgram/Tools/LineDrawTool.cpp +++ b/src/DrawingProgram/Tools/LineDrawTool.cpp @@ -21,7 +21,7 @@ void LineDrawTool::gui_toolbox() { auto& toolConfig = drawP.world.main.toolConfig; t.gui.push_id("rect draw tool"); t.gui.text_label_centered("Draw Line"); - toolConfig.relative_width_slider(t.gui, "Size", &toolConfig.lineDraw.relativeWidth); + toolConfig.relative_width_gui(drawP, "Size", &toolConfig.lineDraw.relativeWidth); t.gui.checkbox_field("hasroundcaps", "Round Caps", &toolConfig.lineDraw.hasRoundCaps); t.gui.pop_id(); } @@ -50,7 +50,7 @@ void LineDrawTool::tool_update() { BrushStrokeCanvasComponentPoint p; p.pos = drawP.world.main.input.mouse.pos; - p.width = toolConfig.get_relative_width(toolConfig.lineDraw.relativeWidth); + p.width = toolConfig.get_relative_width(drawP, drawP.world.drawData.cam.c.inverseScale, toolConfig.lineDraw.relativeWidth); newBrushStroke.d.points->emplace_back(p); p.pos = ensure_points_have_distance(p.pos, p.pos, 1.0f); newBrushStroke.d.points->emplace_back(p); diff --git a/src/DrawingProgram/Tools/RectDrawTool.cpp b/src/DrawingProgram/Tools/RectDrawTool.cpp index eeead9d..aa90be8 100644 --- a/src/DrawingProgram/Tools/RectDrawTool.cpp +++ b/src/DrawingProgram/Tools/RectDrawTool.cpp @@ -26,7 +26,7 @@ void RectDrawTool::gui_toolbox() { if(t.gui.radio_button_field("outlineonly", "Outline only", fillStrokeMode == 1)) fillStrokeMode = 1; if(t.gui.radio_button_field("filloutline", "Fill and Outline", fillStrokeMode == 2)) fillStrokeMode = 2; if(fillStrokeMode == 1 || fillStrokeMode == 2) - toolConfig.relative_width_slider(t.gui, "Outline Size", &toolConfig.rectDraw.relativeWidth); + toolConfig.relative_width_gui(drawP, "Outline Size", &toolConfig.rectDraw.relativeWidth); t.gui.pop_id(); } @@ -59,7 +59,7 @@ void RectDrawTool::tool_update() { newRectangle.d.strokeColor = toolConfig.globalConf.foregroundColor; newRectangle.d.fillColor = toolConfig.globalConf.backgroundColor; newRectangle.d.cornerRadius = relativeRadiusWidth; - newRectangle.d.strokeWidth = toolConfig.get_relative_width(toolConfig.rectDraw.relativeWidth); + newRectangle.d.strokeWidth = toolConfig.get_relative_width(drawP, drawP.world.drawData.cam.c.inverseScale, toolConfig.rectDraw.relativeWidth); newRectangle.d.p1 = startAt; newRectangle.d.p2 = startAt; newRectangle.d.p2 = ensure_points_have_distance(newRectangle.d.p1, newRectangle.d.p2, MINIMUM_DISTANCE_BETWEEN_BOUNDS);