diff --git a/CMakeLists.txt b/CMakeLists.txt index 7143597..24837b0 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,6 +63,7 @@ set(sources "src/main.cpp" "src/DrawingProgram/DrawingProgramCache.cpp" "src/DrawingProgram/DrawingProgram.cpp" "src/DrawingProgram/Tools/BrushTool.cpp" + "src/DrawingProgram/Tools/LineDrawTool.cpp" "src/DrawingProgram/Tools/TextBoxTool.cpp" "src/DrawingProgram/Tools/EraserTool.cpp" "src/DrawingProgram/Tools/RectSelectTool.cpp" diff --git a/data/icons/line.svg b/data/icons/line.svg new file mode 100644 index 0000000..1541e5c --- /dev/null +++ b/data/icons/line.svg @@ -0,0 +1,63 @@ + + + + + + + + + + + + diff --git a/src/DrawingProgram/DrawingProgram.cpp b/src/DrawingProgram/DrawingProgram.cpp index bbfaf27..2354b12 100644 --- a/src/DrawingProgram/DrawingProgram.cpp +++ b/src/DrawingProgram/DrawingProgram.cpp @@ -132,6 +132,7 @@ void DrawingProgram::toolbar_gui() { t.gui.obstructing_window(); if(t.gui.svg_icon_button_transparent("Brush Toolbar Button", "data/icons/brush.svg", drawTool->get_type() == DrawingProgramToolType::BRUSH)) { switch_to_tool(DrawingProgramToolType::BRUSH); } if(t.gui.svg_icon_button_transparent("Eraser Toolbar Button", "data/icons/eraser.svg", drawTool->get_type() == DrawingProgramToolType::ERASER)) { switch_to_tool(DrawingProgramToolType::ERASER); } + if(t.gui.svg_icon_button_transparent("Line Toolbar Button", "data/icons/line.svg", drawTool->get_type() == DrawingProgramToolType::LINE)) { switch_to_tool(DrawingProgramToolType::LINE); } if(t.gui.svg_icon_button_transparent("Text Toolbar Button", "data/icons/text.svg", drawTool->get_type() == DrawingProgramToolType::TEXTBOX)) { switch_to_tool(DrawingProgramToolType::TEXTBOX); } if(t.gui.svg_icon_button_transparent("Ellipse Toolbar Button", "data/icons/circle.svg", drawTool->get_type() == DrawingProgramToolType::ELLIPSE)) { switch_to_tool(DrawingProgramToolType::ELLIPSE); } if(t.gui.svg_icon_button_transparent("Rect Toolbar Button", "data/icons/rectangle.svg", drawTool->get_type() == DrawingProgramToolType::RECTANGLE)) { switch_to_tool(DrawingProgramToolType::RECTANGLE); } diff --git a/src/DrawingProgram/DrawingProgram.hpp b/src/DrawingProgram/DrawingProgram.hpp index ae94604..f5845e0 100644 --- a/src/DrawingProgram/DrawingProgram.hpp +++ b/src/DrawingProgram/DrawingProgram.hpp @@ -127,6 +127,7 @@ class DrawingProgram { friend class EyeDropperTool; friend class RectDrawTool; friend class EllipseDrawTool; + friend class LineDrawTool; friend class BrushTool; friend class EraserTool; friend class RectSelectTool; diff --git a/src/DrawingProgram/Tools/DrawingProgramToolBase.cpp b/src/DrawingProgram/Tools/DrawingProgramToolBase.cpp index 86849a4..88985ac 100644 --- a/src/DrawingProgram/Tools/DrawingProgramToolBase.cpp +++ b/src/DrawingProgram/Tools/DrawingProgramToolBase.cpp @@ -13,6 +13,7 @@ #include "EditTool.hpp" #include "GridModifyTool.hpp" #include "ZoomCanvasTool.hpp" +#include "LineDrawTool.hpp" DrawingProgramToolBase::DrawingProgramToolBase(DrawingProgram& initDrawP): drawP(initDrawP) @@ -48,6 +49,8 @@ std::unique_ptr DrawingProgramToolBase::allocate_tool_ty return std::make_unique(drawP); case DrawingProgramToolType::PAN: return std::make_unique(drawP); + case DrawingProgramToolType::LINE: + return std::make_unique(drawP); } return nullptr; } diff --git a/src/DrawingProgram/Tools/DrawingProgramToolBase.hpp b/src/DrawingProgram/Tools/DrawingProgramToolBase.hpp index ba834ed..fbd573d 100644 --- a/src/DrawingProgram/Tools/DrawingProgramToolBase.hpp +++ b/src/DrawingProgram/Tools/DrawingProgramToolBase.hpp @@ -20,7 +20,8 @@ enum class DrawingProgramToolType : int { GRIDMODIFY, EDIT, ZOOM, - PAN + PAN, + LINE }; class DrawingProgramToolBase { diff --git a/src/DrawingProgram/Tools/LineDrawTool.cpp b/src/DrawingProgram/Tools/LineDrawTool.cpp new file mode 100644 index 0000000..84cad97 --- /dev/null +++ b/src/DrawingProgram/Tools/LineDrawTool.cpp @@ -0,0 +1,101 @@ +#include "LineDrawTool.hpp" +#include "../DrawingProgram.hpp" +#include "../../MainProgram.hpp" +#include "../../DrawData.hpp" +#include "DrawingProgramToolBase.hpp" +#include "../../CanvasComponents/BrushStrokeCanvasComponent.hpp" +#include "../../CanvasComponents/CanvasComponentContainer.hpp" +#include "Helpers/MathExtras.hpp" +#include + +LineDrawTool::LineDrawTool(DrawingProgram& initDrawP): + DrawingProgramToolBase(initDrawP) +{} + +DrawingProgramToolType LineDrawTool::get_type() { + return DrawingProgramToolType::LINE; +} + +void LineDrawTool::gui_toolbox() { + Toolbar& t = drawP.world.main.toolbar; + t.gui.push_id("rect draw tool"); + t.gui.text_label_centered("Draw Line"); + t.gui.slider_scalar_field("relstrokewidth", "Size", &drawP.controls.relativeWidth, 3.0f, 40.0f); + t.gui.checkbox_field("hasroundcaps", "Round Caps", &hasRoundCaps); + t.gui.pop_id(); +} + +void LineDrawTool::erase_component(CanvasComponentContainer::ObjInfo* erasedComp) { + if(objInfoBeingEdited == erasedComp) + objInfoBeingEdited = nullptr; +} + +bool LineDrawTool::right_click_popup_gui(Vector2f popupPos) { + Toolbar& t = drawP.world.main.toolbar; + t.paint_popup(popupPos); + return true; +} + +void LineDrawTool::switch_tool(DrawingProgramToolType newTool) { + commit(); +} + +void LineDrawTool::tool_update() { + if(!objInfoBeingEdited) { + if(drawP.controls.leftClick && drawP.layerMan.is_a_layer_being_edited()) { + CanvasComponentContainer* newBrushStrokeContainer = new CanvasComponentContainer(drawP.world.netObjMan, CanvasComponentType::BRUSHSTROKE); + BrushStrokeCanvasComponent& newBrushStroke = static_cast(newBrushStrokeContainer->get_comp()); + + BrushStrokeCanvasComponentPoint p; + p.pos = drawP.world.main.input.mouse.pos; + p.width = drawP.controls.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); + newBrushStroke.d->color = drawP.controls.foregroundColor; + newBrushStroke.d->hasRoundCaps = hasRoundCaps; + newBrushStrokeContainer->coords = drawP.world.drawData.cam.c; + objInfoBeingEdited = drawP.layerMan.add_component_to_layer_being_edited(newBrushStrokeContainer); + } + } + else { + NetworkingObjects::NetObjOwnerPtr& containerPtr = objInfoBeingEdited->obj; + constexpr float SNAP_DIVISION_COUNT = 8.0f; + if(drawP.controls.leftClickHeld) { + BrushStrokeCanvasComponent& brushStroke = static_cast(containerPtr->get_comp()); + Vector2f newPos = containerPtr->coords.get_mouse_pos(drawP.world); + Vector2f oldPos = brushStroke.d->points.front().pos; + if(drawP.world.main.input.key(InputManager::KEY_GENERIC_LSHIFT).held) { + Vector2f diff = (newPos - oldPos); + float diffLength = diff.norm(); + diff.normalize(); + float angle = (std::atan2(diff.y(), diff.x()) / std::numbers::pi) * SNAP_DIVISION_COUNT; + angle = std::round(angle); + angle = (angle * std::numbers::pi) / SNAP_DIVISION_COUNT; + newPos = oldPos + diffLength * Vector2f{cos(angle), sin(angle)}; + } + brushStroke.d->points.back().pos = ensure_points_have_distance(oldPos, newPos, 1.0f); + containerPtr->send_comp_update(drawP, false); + containerPtr->commit_update(drawP); + } + else + commit(); + } +} + +bool LineDrawTool::prevent_undo_or_redo() { + return objInfoBeingEdited; +} + +void LineDrawTool::commit() { + if(objInfoBeingEdited) { + NetworkingObjects::NetObjOwnerPtr& containerPtr = objInfoBeingEdited->obj; + containerPtr->commit_update(drawP); + containerPtr->send_comp_update(drawP, true); + drawP.layerMan.add_undo_place_component(objInfoBeingEdited); + objInfoBeingEdited = nullptr; + } +} + +void LineDrawTool::draw(SkCanvas* canvas, const DrawData& drawData) { +} diff --git a/src/DrawingProgram/Tools/LineDrawTool.hpp b/src/DrawingProgram/Tools/LineDrawTool.hpp new file mode 100644 index 0000000..739bb7c --- /dev/null +++ b/src/DrawingProgram/Tools/LineDrawTool.hpp @@ -0,0 +1,25 @@ +#pragma once +#include "DrawingProgramToolBase.hpp" +#include +#include "../../CanvasComponents/CanvasComponentContainer.hpp" + +class DrawingProgram; + +class LineDrawTool : public DrawingProgramToolBase { + public: + LineDrawTool(DrawingProgram& initDrawP); + virtual DrawingProgramToolType get_type() override; + virtual void gui_toolbox() override; + virtual bool right_click_popup_gui(Vector2f popupPos) override; + virtual void erase_component(CanvasComponentContainer::ObjInfo* erasedComp) override; + virtual void tool_update() override; + virtual void switch_tool(DrawingProgramToolType newTool) override; + virtual void draw(SkCanvas* canvas, const DrawData& drawData) override; + virtual bool prevent_undo_or_redo() override; + private: + void commit(); + + Vector2f startAt; + bool hasRoundCaps = true; + CanvasComponentContainer::ObjInfo* objInfoBeingEdited = nullptr; +};