Working on meshes

This commit is contained in:
Yousef Khadadeh 2026-05-23 18:27:45 +03:00
parent c479ccb9e2
commit 7b472fe18d
652 changed files with 81120 additions and 852 deletions

View file

@ -400,6 +400,7 @@ void DrawingProgram::toolbar_gui(Toolbar& t) {
tool_button("Brush Toolbar Button", "data/icons/brush.svg", DrawingProgramToolType::BRUSH);
tool_button("Eraser Toolbar Button", "data/icons/eraser.svg", DrawingProgramToolType::ERASER);
tool_button("Fill Toolbar Button", "data/icons/RemixIcon/paint-line.svg", DrawingProgramToolType::FILL);
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);

View file

@ -177,6 +177,7 @@ class DrawingProgram {
friend class DrawingProgramCache;
friend class DrawingProgramSelection;
friend class LassoSelectTool;
friend class FillTool;
friend class GridEditTool;
friend class GridModifyTool;
friend class ZoomCanvasTool;

View file

@ -22,7 +22,7 @@
#include "../DrawingProgram.hpp"
#include "../../MainProgram.hpp"
#include "DrawingProgramToolBase.hpp"
#include "../../CanvasComponents/BrushStrokeCanvasComponent.hpp"
#include "../../CanvasComponents/MeshCanvasComponent.hpp"
#include "Helpers/NetworkingObjects/NetObjTemporaryPtr.decl.hpp"
#include "../../CanvasComponents/CanvasComponentContainer.hpp"
@ -53,9 +53,6 @@ void BrushTool::erase_component(CanvasComponentContainer::ObjInfo* erasedComp) {
void BrushTool::smooth_out_points(float smoothFactor) {
if(objInfoBeingEdited) {
NetworkingObjects::NetObjOwnerPtr<CanvasComponentContainer>& containerPtr = objInfoBeingEdited->obj;
BrushStrokeCanvasComponent& brushStroke = static_cast<BrushStrokeCanvasComponent&>(containerPtr->get_comp());
auto& brushPoints = *brushStroke.d.points;
if(brushPoints.size() >= 2) {
brushPoints.back().width = std::max(brushPoints[brushPoints.size() - 1].width, brushPoints[brushPoints.size() - 2].width * smoothFactor);
for(size_t i = brushPoints.size() - 1; i > 0; i--) {
@ -70,12 +67,8 @@ void BrushTool::smooth_out_points(float smoothFactor) {
void BrushTool::fix_tip() {
if(objInfoBeingEdited) {
NetworkingObjects::NetObjOwnerPtr<CanvasComponentContainer>& containerPtr = objInfoBeingEdited->obj;
BrushStrokeCanvasComponent& brushStroke = static_cast<BrushStrokeCanvasComponent&>(containerPtr->get_comp());
auto& brushPoints = *brushStroke.d.points;
if(brushPoints.size() >= 2) {
if(brushPoints.size() >= 2)
brushPoints[brushPoints.size() - 2].width = brushPoints[brushPoints.size() - 1].width = std::max(brushPoints[brushPoints.size() - 1].width, brushPoints[brushPoints.size() - 2].width);
}
}
}
@ -100,18 +93,19 @@ void BrushTool::input_mouse_button_on_canvas_callback(const InputManager::MouseB
}
float width = relativeWidthResult.first.value() * penWidth;
CanvasComponentContainer* newBrushStrokeContainer = new CanvasComponentContainer(drawP.world.netObjMan, CanvasComponentType::BRUSHSTROKE);
BrushStrokeCanvasComponent& newBrushStroke = static_cast<BrushStrokeCanvasComponent&>(newBrushStrokeContainer->get_comp());
CanvasComponentContainer* newMeshContainer = new CanvasComponentContainer(drawP.world.netObjMan, CanvasComponentType::MESH);
MeshCanvasComponent& newMesh = static_cast<MeshCanvasComponent&>(newMeshContainer->get_comp());
BrushStrokeCanvasComponentPoint p;
brushPoints.clear();
BrushComponentCode::BrushPoint p;
p.pos = button.pos;
p.width = width;
prevPointUnaltered = p.pos;
newBrushStroke.d.points->emplace_back(p);
newBrushStroke.d.color = toolConfig.globalConf.foregroundColor;
newBrushStroke.d.hasRoundCaps = toolConfig.brush.hasRoundCaps;
newBrushStrokeContainer->coords = drawP.world.drawData.cam.c;
objInfoBeingEdited = drawP.layerMan.add_component_to_layer_being_edited(newBrushStrokeContainer);
brushPoints.emplace_back(p);
newMesh.d.color = toolConfig.globalConf.foregroundColor;
newMeshContainer->coords = drawP.world.drawData.cam.c;
objInfoBeingEdited = drawP.layerMan.add_component_to_layer_being_edited(newMeshContainer);
commit_data(false);
addedTemporaryPoint = false;
}
else if(!button.down && objInfoBeingEdited)
@ -119,22 +113,30 @@ void BrushTool::input_mouse_button_on_canvas_callback(const InputManager::MouseB
}
}
void BrushTool::commit_data(bool final) {
if(objInfoBeingEdited) {
NetworkingObjects::NetObjOwnerPtr<CanvasComponentContainer>& containerPtr = objInfoBeingEdited->obj;
MeshCanvasComponent& newMesh = static_cast<MeshCanvasComponent&>(containerPtr->get_comp());
newMesh.d.points = BrushComponentCode::brush_stroke_to_mesh_points(brushPoints, drawP.world.main.toolConfig.brush.hasRoundCaps);
containerPtr->commit_update(drawP);
containerPtr->send_comp_update(drawP, final);
}
}
void BrushTool::input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) {
if(objInfoBeingEdited) {
auto& toolConfig = drawP.world.main.toolConfig;
NetworkingObjects::NetObjOwnerPtr<CanvasComponentContainer>& containerPtr = objInfoBeingEdited->obj;
BrushStrokeCanvasComponent& brushStroke = static_cast<BrushStrokeCanvasComponent&>(containerPtr->get_comp());
auto& brushPoints = *brushStroke.d.points;
float width = toolConfig.get_relative_width_stroke_size(drawP, containerPtr->coords.inverseScale).first.value() * penWidth;
BrushStrokeCanvasComponentPoint p;
BrushComponentCode::BrushPoint p;
p.pos = containerPtr->coords.from_cam_space_to_this(drawP.world, motion.pos);
p.width = width;
// Temporary point is a point that follows the cursor until it is placed
if(!addedTemporaryPoint) {
// Temporary point is close enough to be placed
if(extensive_point_checking(brushStroke, p.pos)) {
if(extensive_point_checking(p.pos)) {
brushPoints.emplace_back(p);
addedTemporaryPoint = true;
}
@ -144,10 +146,10 @@ void BrushTool::input_mouse_motion_callback(const InputManager::MouseMotionCallb
}
if(addedTemporaryPoint) {
const BrushStrokeCanvasComponentPoint& prevP = brushPoints[brushPoints.size() - 2];
const BrushComponentCode::BrushPoint& prevP = brushPoints[brushPoints.size() - 2];
float distToPrev = (p.pos - prevP.pos).norm();
// If the cursor isnt too close to the previous points, move the temporary point to the cursor and change the width of the temporary point to the current pen width
if(extensive_point_checking_back(brushStroke, p.pos)) {
if(extensive_point_checking_back(p.pos)) {
brushPoints.back().pos = p.pos;
brushPoints.back().width = std::max(brushPoints.back().width, p.width);
}
@ -186,8 +188,6 @@ void BrushTool::input_pen_axis_callback(const InputManager::PenAxisCallbackArgs&
if(objInfoBeingEdited) {
auto& toolConfig = drawP.world.main.toolConfig;
NetworkingObjects::NetObjOwnerPtr<CanvasComponentContainer>& containerPtr = objInfoBeingEdited->obj;
BrushStrokeCanvasComponent& brushStroke = static_cast<BrushStrokeCanvasComponent&>(containerPtr->get_comp());
auto& brushPoints = *brushStroke.d.points;
float width = toolConfig.get_relative_width_stroke_size(drawP, containerPtr->coords.inverseScale).first.value() * penWidth;
brushPoints.back().width = std::max(brushPoints.back().width, width);
smooth_out_points(drawP.world.main.conf.tabletOptions.brushPressureSmoothingFactor);
@ -197,8 +197,8 @@ void BrushTool::input_pen_axis_callback(const InputManager::PenAxisCallbackArgs&
}
}
bool BrushTool::extensive_point_checking(const BrushStrokeCanvasComponent& brushStroke, const Vector2f& newPoint) {
auto& points = *brushStroke.d.points;
bool BrushTool::extensive_point_checking(const Vector2f& newPoint) {
auto& points = brushPoints;
if(points.size() >= 1 && (newPoint - points[points.size() - 1].pos).norm() < MINIMUM_DISTANCE_TO_NEXT_POINT)
return false;
if(points.size() >= 2 && (newPoint - points[points.size() - 2].pos).norm() < MINIMUM_DISTANCE_TO_NEXT_POINT)
@ -208,8 +208,8 @@ bool BrushTool::extensive_point_checking(const BrushStrokeCanvasComponent& brush
return true;
}
bool BrushTool::extensive_point_checking_back(const BrushStrokeCanvasComponent& brushStroke, const Vector2f& newPoint) {
auto& points = *brushStroke.d.points;
bool BrushTool::extensive_point_checking_back(const Vector2f& newPoint) {
auto& points = brushPoints;
if(points.size() >= 2 && (newPoint - points[points.size() - 2].pos).norm() < MINIMUM_DISTANCE_TO_NEXT_POINT)
return false;
if(points.size() >= 3 && (newPoint - points[points.size() - 3].pos).norm() < MINIMUM_DISTANCE_TO_NEXT_POINT)
@ -224,9 +224,7 @@ void BrushTool::tool_update() {
drawP.world.main.input.hideCursor = true;
if(commitUpdate && objInfoBeingEdited) {
NetworkingObjects::NetObjOwnerPtr<CanvasComponentContainer>& containerPtr = objInfoBeingEdited->obj;
containerPtr->commit_update(drawP);
containerPtr->send_comp_update(drawP, false);
commit_data(false);
commitUpdate = false;
}
}
@ -235,8 +233,7 @@ void BrushTool::commit_stroke() {
if(objInfoBeingEdited) {
NetworkingObjects::NetObjOwnerPtr<CanvasComponentContainer>& containerPtr = objInfoBeingEdited->obj;
fix_tip();
containerPtr->commit_update(drawP);
containerPtr->send_comp_update(drawP, true);
commit_data(true);
commitUpdate = false;
if(containerPtr->get_world_bounds().has_value())
drawP.layerMan.add_undo_place_component(objInfoBeingEdited);

View file

@ -25,6 +25,7 @@
#include <include/core/SkCanvas.h>
#include "../../CanvasComponents/CanvasComponentContainer.hpp"
#include <Helpers/NetworkingObjects/NetObjWeakPtr.hpp>
#include "../../CanvasComponents/BrushComponentCode.hpp"
class DrawingProgram;
struct DrawData;
@ -46,16 +47,19 @@ class BrushTool : public DrawingProgramToolBase {
virtual void input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) override;
virtual void input_pen_axis_callback(const InputManager::PenAxisCallbackArgs& axis) override;
private:
bool extensive_point_checking_back(const BrushStrokeCanvasComponent& brushStroke, const Vector2f& newPoint);
bool extensive_point_checking(const BrushStrokeCanvasComponent& brushStroke, const Vector2f& newPoint);
bool extensive_point_checking_back(const Vector2f& newPoint);
bool extensive_point_checking(const Vector2f& newPoint);
void smooth_out_points(float smoothFactor);
void fix_tip();
void commit_stroke();
void commit_data(bool final);
float penWidth = 1.0f;
bool addedTemporaryPoint = false;
bool commitUpdate = false;
std::vector<BrushComponentCode::BrushPoint> brushPoints;
CanvasComponentContainer::ObjInfo* objInfoBeingEdited = nullptr;
Vector2f prevPointUnaltered = {0, 0};

View file

@ -20,6 +20,7 @@
#include "BrushTool.hpp"
#include "EraserTool.hpp"
#include "FillTool.hpp"
#include "PanCanvasTool.hpp"
#include "RectSelectTool.hpp"
#include "LassoSelectTool.hpp"
@ -45,6 +46,8 @@ std::unique_ptr<DrawingProgramToolBase> DrawingProgramToolBase::allocate_tool_ty
return std::make_unique<BrushTool>(drawP);
case DrawingProgramToolType::ERASER:
return std::make_unique<EraserTool>(drawP);
case DrawingProgramToolType::FILL:
return std::make_unique<FillTool>(drawP);
case DrawingProgramToolType::LASSOSELECT:
return std::make_unique<LassoSelectTool>(drawP);
case DrawingProgramToolType::RECTSELECT:

View file

@ -30,6 +30,7 @@ class PhoneDrawingProgramScreen;
enum class DrawingProgramToolType : int {
BRUSH = 0,
ERASER,
FILL,
LASSOSELECT,
RECTSELECT,
RECTANGLE,

View file

@ -30,7 +30,7 @@
#include "EditTools/RectDrawEditTool.hpp"
#include "EditTools/ImageEditTool.hpp"
#include "EditTools/EllipseDrawEditTool.hpp"
#include "EditTools/BrushEditTool.hpp"
#include "EditTools/MeshEditTool.hpp"
#include "../../GUIStuff/ElementHelpers/TextLabelHelpers.hpp"
@ -294,8 +294,8 @@ void EditTool::edit_start(CanvasComponentContainer::ObjInfo* comp, bool initUndo
compEditTool = std::make_unique<ImageEditTool>(drawP, comp);
break;
}
case CanvasComponentType::BRUSHSTROKE: {
compEditTool = std::make_unique<BrushEditTool>(drawP, comp);
case CanvasComponentType::MESH: {
compEditTool = std::make_unique<MeshEditTool>(drawP, comp);
break;
}
default: {

View file

@ -16,67 +16,67 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "BrushEditTool.hpp"
#include "MeshEditTool.hpp"
#include "../../DrawingProgram.hpp"
#include "../../../World.hpp"
#include "../../../MainProgram.hpp"
#include "../EditTool.hpp"
#include "../../../CanvasComponents/BrushStrokeCanvasComponent.hpp"
#include "../../../CanvasComponents/MeshCanvasComponent.hpp"
#include "../../../GUIStuff/ElementHelpers/TextLabelHelpers.hpp"
#include "../../../GUIStuff/ElementHelpers/LayoutHelpers.hpp"
BrushEditTool::BrushEditTool(DrawingProgram& initDrawP, CanvasComponentContainer::ObjInfo* initComp):
MeshEditTool::MeshEditTool(DrawingProgram& initDrawP, CanvasComponentContainer::ObjInfo* initComp):
DrawingProgramEditToolBase(initDrawP, initComp)
{}
void BrushEditTool::edit_gui(Toolbar& t) {
void MeshEditTool::edit_gui(Toolbar& t) {
using namespace GUIStuff;
using namespace ElementHelpers;
auto& a = static_cast<BrushStrokeCanvasComponent&>(comp->obj->get_comp());
auto& a = static_cast<MeshCanvasComponent&>(comp->obj->get_comp());
auto& gui = drawP.world.main.g.gui;
auto commit_update_func = [&] { commitUpdate = true; };
gui.new_id("edit tool brush", [&] {
text_label_centered(gui, "Edit Brush Stroke");
gui.new_id("edit tool mesh", [&] {
text_label_centered(gui, "Edit Mesh");
left_to_right_line_layout(gui, [&]() {
t.color_button_right("Outline Color", &a.d.color, { .onChange = commit_update_func });
text_label(gui, "Outline Color");
t.color_button_right("Mesh Color", &a.d.color, { .onChange = commit_update_func });
text_label(gui, "Mesh Color");
});
});
}
void BrushEditTool::gui_phone_toolbox(PhoneDrawingProgramScreen& t) {
void MeshEditTool::gui_phone_toolbox(PhoneDrawingProgramScreen& t) {
using namespace GUIStuff;
using namespace ElementHelpers;
auto& a = static_cast<BrushStrokeCanvasComponent&>(comp->obj->get_comp());
auto& a = static_cast<MeshCanvasComponent&>(comp->obj->get_comp());
auto& gui = drawP.world.main.g.gui;
auto commit_update_func = [&] { commitUpdate = true; };
gui.new_id("edit tool brush", [&] {
gui.new_id("edit tool mesh", [&] {
left_to_right_line_layout(gui, [&]() {
t.color_selector_button("Outline Color", &a.d.color, { .onChange = commit_update_func });
text_label(gui, "Outline Color");
t.color_selector_button("Mesh Color", &a.d.color, { .onChange = commit_update_func });
text_label(gui, "Mesh Color");
});
});
}
Vector4f* BrushEditTool::color_picker_color(Vector4f* oldColor) {
auto& a = static_cast<BrushStrokeCanvasComponent&>(comp->obj->get_comp());
Vector4f* MeshEditTool::color_picker_color(Vector4f* oldColor) {
auto& a = static_cast<MeshCanvasComponent&>(comp->obj->get_comp());
if(oldColor == &a.d.color)
return oldColor;
return nullptr;
}
void BrushEditTool::edit_start(EditTool& editTool, std::any& prevData) {
auto& a = static_cast<BrushStrokeCanvasComponent&>(comp->obj->get_comp());
void MeshEditTool::edit_start(EditTool& editTool, std::any& prevData) {
auto& a = static_cast<MeshCanvasComponent&>(comp->obj->get_comp());
oldColor = a.d.color;
}
void BrushEditTool::commit_edit_updates(std::any& prevData) {
void MeshEditTool::commit_edit_updates(std::any& prevData) {
}
void BrushEditTool::edit_update() {
void MeshEditTool::edit_update() {
}

View file

@ -23,9 +23,9 @@
class DrawingProgram;
class BrushEditTool : public DrawingProgramEditToolBase {
class MeshEditTool : public DrawingProgramEditToolBase {
public:
BrushEditTool(DrawingProgram& initDrawP, CanvasComponentContainer::ObjInfo* initComp);
MeshEditTool(DrawingProgram& initDrawP, CanvasComponentContainer::ObjInfo* initComp);
virtual void edit_start(EditTool& editTool, std::any& prevData) override;
virtual void commit_edit_updates(std::any& prevData) override;
virtual void edit_update() override;

View file

@ -0,0 +1,98 @@
/*
* InfiniPaint
* Copyright (C) 2025-2026 Yousef Khadadeh
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "FillTool.hpp"
#include "../DrawingProgram.hpp"
#include "../../MainProgram.hpp"
#include "../../DrawData.hpp"
#include "DrawingProgramToolBase.hpp"
#include "../../CoordSpaceHelper.hpp"
#include "../../GUIStuff/ElementHelpers/TextLabelHelpers.hpp"
#include "../../CanvasComponents/MeshCanvasComponent.hpp"
FillTool::FillTool(DrawingProgram& initDrawP):
DrawingProgramToolBase(initDrawP)
{}
DrawingProgramToolType FillTool::get_type() {
return DrawingProgramToolType::FILL;
}
void FillTool::gui_toolbox(Toolbar& t) {
auto& gui = drawP.world.main.g.gui;
gui.new_id("fill tool", [&] {
GUIStuff::ElementHelpers::text_label_centered(gui, "Fill");
});
}
void FillTool::gui_phone_toolbox(PhoneDrawingProgramScreen& t) {
auto& gui = drawP.world.main.g.gui;
gui.new_id("fill tool", [&] {
});
}
void FillTool::right_click_popup_gui(Toolbar& t, Vector2f popupPos) {
drawP.selection_action_menu(popupPos);
}
void FillTool::input_mouse_button_on_canvas_callback(const InputManager::MouseButtonCallbackArgs& button) {
if(button.button == InputManager::MouseButton::LEFT) {
if(button.down && drawP.layerMan.is_a_layer_being_edited() && !drawP.world.main.g.gui.cursor_obstructed()) {
auto& toolConfig = drawP.world.main.toolConfig;
CanvasComponentContainer* newContainer = new CanvasComponentContainer(drawP.world.netObjMan, CanvasComponentType::MESH);
MeshCanvasComponent& newMesh = static_cast<MeshCanvasComponent&>(newContainer->get_comp());
newMesh.d.color = toolConfig.globalConf.foregroundColor;
newMesh.d.points.fill.emplace_back();
newMesh.d.points.fill.back().emplace_back(button.pos + Vector2f{0.0f, 100.0f});
newMesh.d.points.fill.back().emplace_back(button.pos + Vector2f{-100.0f, -100.0f});
newMesh.d.points.fill.back().emplace_back(button.pos + Vector2f{100.0f, -100.0f});
newContainer->coords = drawP.world.drawData.cam.c;
objInfoBeingEdited = drawP.layerMan.add_component_to_layer_being_edited(newContainer);
objInfoBeingEdited->obj->commit_update(drawP);
objInfoBeingEdited->obj->send_comp_update(drawP, true);
drawP.layerMan.add_undo_place_component(objInfoBeingEdited);
objInfoBeingEdited = nullptr;
}
}
}
Vector4f* FillTool::color_picker_color(Vector4f* oldColor) {
return nullptr;
}
void FillTool::erase_component(CanvasComponentContainer::ObjInfo* erasedComp) {
}
void FillTool::switch_tool(DrawingProgramToolType newTool) {
}
void FillTool::tool_update() {
}
bool FillTool::prevent_undo_or_redo() {
return false;
}
void FillTool::draw(SkCanvas* canvas, const DrawData& drawData) {
}

View file

@ -0,0 +1,44 @@
/*
* InfiniPaint
* Copyright (C) 2025-2026 Yousef Khadadeh
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <include/core/SkCanvas.h>
#include "../../DrawData.hpp"
#include <Helpers/SCollision.hpp>
#include "../../CoordSpaceHelper.hpp"
#include "DrawingProgramToolBase.hpp"
class DrawingProgram;
class FillTool : public DrawingProgramToolBase {
public:
FillTool(DrawingProgram& initDrawP);
virtual DrawingProgramToolType get_type() override;
virtual void gui_toolbox(Toolbar& t) override;
virtual void gui_phone_toolbox(PhoneDrawingProgramScreen& t) override;
virtual void right_click_popup_gui(Toolbar& t, Vector2f popupPos) override;
virtual void erase_component(CanvasComponentContainer::ObjInfo* erasedComp) override;
virtual void tool_update() override;
virtual void draw(SkCanvas* canvas, const DrawData& drawData) override;
virtual void switch_tool(DrawingProgramToolType newTool) override;
virtual bool prevent_undo_or_redo() override;
virtual Vector4f* color_picker_color(Vector4f* oldColor) override;
virtual void input_mouse_button_on_canvas_callback(const InputManager::MouseButtonCallbackArgs& button) override;
private:
CanvasComponentContainer::ObjInfo* objInfoBeingEdited = nullptr;
};

View file

@ -25,30 +25,11 @@
#include "Helpers/SCollision.hpp"
#include "../../CoordSpaceHelper.hpp"
#include <ranges>
#include <earcut.hpp>
#include <include/core/SkPathBuilder.h>
#include "../../EarcutIncludes.hpp"
#include "../../GUIStuff/ElementHelpers/TextLabelHelpers.hpp"
namespace mapbox {
namespace util {
template <>
struct nth<0, Vector2f> {
inline static auto get(const Vector2f &t) {
return t.x();
};
};
template <>
struct nth<1, Vector2f> {
inline static auto get(const Vector2f &t) {
return t.y();
};
};
} // namespace util
} // namespace mapbox
LassoSelectTool::LassoSelectTool(DrawingProgram& initDrawP):
DrawingProgramToolBase(initDrawP)
{}

View file

@ -21,7 +21,6 @@
#include "../../MainProgram.hpp"
#include "../../DrawData.hpp"
#include "DrawingProgramToolBase.hpp"
#include "../../CanvasComponents/BrushStrokeCanvasComponent.hpp"
#include "../../CanvasComponents/CanvasComponentContainer.hpp"
#include "Helpers/MathExtras.hpp"
@ -63,26 +62,26 @@ void LineDrawTool::input_mouse_button_on_canvas_callback(const InputManager::Mou
if(button.button == InputManager::MouseButton::LEFT) {
auto& toolConfig = drawP.world.main.toolConfig;
if(button.down && drawP.layerMan.is_a_layer_being_edited() && !objInfoBeingEdited && !drawP.world.main.g.gui.cursor_obstructed()) {
auto relativeWidthResult = drawP.world.main.toolConfig.get_relative_width_stroke_size(drawP, drawP.world.drawData.cam.c.inverseScale);
if(!relativeWidthResult.first.has_value()) {
drawP.world.main.toolConfig.print_relative_width_fail_message(relativeWidthResult.second);
return;
}
float width = relativeWidthResult.first.value();
//auto relativeWidthResult = drawP.world.main.toolConfig.get_relative_width_stroke_size(drawP, drawP.world.drawData.cam.c.inverseScale);
//if(!relativeWidthResult.first.has_value()) {
// drawP.world.main.toolConfig.print_relative_width_fail_message(relativeWidthResult.second);
// return;
//}
//float width = relativeWidthResult.first.value();
CanvasComponentContainer* newBrushStrokeContainer = new CanvasComponentContainer(drawP.world.netObjMan, CanvasComponentType::BRUSHSTROKE);
BrushStrokeCanvasComponent& newBrushStroke = static_cast<BrushStrokeCanvasComponent&>(newBrushStrokeContainer->get_comp());
//CanvasComponentContainer* newBrushStrokeContainer = new CanvasComponentContainer(drawP.world.netObjMan, CanvasComponentType::BRUSHSTROKE);
//BrushStrokeCanvasComponent& newBrushStroke = static_cast<BrushStrokeCanvasComponent&>(newBrushStrokeContainer->get_comp());
BrushStrokeCanvasComponentPoint p;
p.pos = drawP.world.main.input.mouse.pos;
p.width = width;
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 = toolConfig.globalConf.foregroundColor;
newBrushStroke.d.hasRoundCaps = toolConfig.lineDraw.hasRoundCaps;
newBrushStrokeContainer->coords = drawP.world.drawData.cam.c;
objInfoBeingEdited = drawP.layerMan.add_component_to_layer_being_edited(newBrushStrokeContainer);
//BrushStrokeCanvasComponentPoint p;
//p.pos = drawP.world.main.input.mouse.pos;
//p.width = width;
//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 = toolConfig.globalConf.foregroundColor;
//newBrushStroke.d.hasRoundCaps = toolConfig.lineDraw.hasRoundCaps;
//newBrushStrokeContainer->coords = drawP.world.drawData.cam.c;
//objInfoBeingEdited = drawP.layerMan.add_component_to_layer_being_edited(newBrushStrokeContainer);
}
else if(!button.down && objInfoBeingEdited)
commit();
@ -91,22 +90,22 @@ void LineDrawTool::input_mouse_button_on_canvas_callback(const InputManager::Mou
void LineDrawTool::input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) {
if(objInfoBeingEdited) {
constexpr float SNAP_DIVISION_COUNT = 12.0f;
NetworkingObjects::NetObjOwnerPtr<CanvasComponentContainer>& containerPtr = objInfoBeingEdited->obj;
BrushStrokeCanvasComponent& brushStroke = static_cast<BrushStrokeCanvasComponent&>(containerPtr->get_comp());
Vector2f newPos = containerPtr->coords.from_cam_space_to_this(drawP.world, motion.pos);
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);
commitUpdate = true;
//constexpr float SNAP_DIVISION_COUNT = 12.0f;
//NetworkingObjects::NetObjOwnerPtr<CanvasComponentContainer>& containerPtr = objInfoBeingEdited->obj;
//BrushStrokeCanvasComponent& brushStroke = static_cast<BrushStrokeCanvasComponent&>(containerPtr->get_comp());
//Vector2f newPos = containerPtr->coords.from_cam_space_to_this(drawP.world, motion.pos);
//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);
//commitUpdate = true;
}
}