Can edit stroke colors through selection

This commit is contained in:
Yousef Khadadeh 2026-01-27 16:55:09 +03:00
parent f6c4eeb9f3
commit a73f5e2122
18 changed files with 283 additions and 51 deletions

View file

@ -32,7 +32,7 @@ void BrushTool::erase_component(CanvasComponentContainer::ObjInfo* erasedComp) {
}
bool BrushTool::extensive_point_checking(const BrushStrokeCanvasComponent& brushStroke, const Vector2f& newPoint) {
auto& points = brushStroke.d->points;
auto& points = *brushStroke.d.points;
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)
@ -43,7 +43,7 @@ bool BrushTool::extensive_point_checking(const BrushStrokeCanvasComponent& brush
}
bool BrushTool::extensive_point_checking_back(const BrushStrokeCanvasComponent& brushStroke, const Vector2f& newPoint) {
auto& points = brushStroke.d->points;
auto& points = *brushStroke.d.points;
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)
@ -98,9 +98,9 @@ void BrushTool::tool_update() {
p.pos = drawP.world.main.input.mouse.pos;
p.width = toolConfig.get_relative_width(toolConfig.brush.relativeWidth) * penWidth;
prevPointUnaltered = p.pos;
newBrushStroke.d->points.emplace_back(p);
newBrushStroke.d->color = toolConfig.globalConf.foregroundColor;
newBrushStroke.d->hasRoundCaps = toolConfig.brush.hasRoundCaps;
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);
addedTemporaryPoint = false;
@ -109,6 +109,7 @@ void BrushTool::tool_update() {
else {
NetworkingObjects::NetObjOwnerPtr<CanvasComponentContainer>& containerPtr = objInfoBeingEdited->obj;
BrushStrokeCanvasComponent& brushStroke = static_cast<BrushStrokeCanvasComponent&>(containerPtr->get_comp());
auto& brushPoints = *brushStroke.d.points;
BrushStrokeCanvasComponentPoint p;
p.pos = containerPtr->coords.get_mouse_pos(drawP.world);
@ -116,28 +117,28 @@ void BrushTool::tool_update() {
if(!addedTemporaryPoint) {
if(extensive_point_checking(brushStroke, p.pos)) {
brushStroke.d->points.emplace_back(p);
brushPoints.emplace_back(p);
addedTemporaryPoint = true;
}
else
brushStroke.d->points.back().width = std::max(brushStroke.d->points.back().width, p.width);
brushPoints.back().width = std::max(brushPoints.back().width, p.width);
}
if(addedTemporaryPoint) {
const BrushStrokeCanvasComponentPoint& prevP = brushStroke.d->points[brushStroke.d->points.size() - 2];
const BrushStrokeCanvasComponentPoint& prevP = brushPoints[brushPoints.size() - 2];
float distToPrev = (p.pos - prevP.pos).norm();
if(extensive_point_checking_back(brushStroke, p.pos)) {
brushStroke.d->points.back().pos = p.pos;
brushStroke.d->points.back().width = std::max(brushStroke.d->points.back().width, p.width);
brushStroke.d->points[brushStroke.d->points.size() - 2].width = std::max(brushStroke.d->points[brushStroke.d->points.size() - 2].width, p.width);
brushPoints.back().pos = p.pos;
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)) {
brushStroke.d->points.back() = p;
brushPoints.back() = p;
addedTemporaryPoint = false;
if(midwayInterpolation) {
if(brushStroke.d->points.size() != 2) // Don't interpolate the first point
brushStroke.d->points[brushStroke.d->points.size() - 2].pos = (prevPointUnaltered + p.pos) * 0.5;
if(brushPoints.size() != 2) // Don't interpolate the first point
brushPoints[brushPoints.size() - 2].pos = (prevPointUnaltered + p.pos) * 0.5;
prevPointUnaltered = p.pos;
}
}

View file

@ -13,6 +13,7 @@
#include "EditTools/RectDrawEditTool.hpp"
#include "EditTools/ImageEditTool.hpp"
#include "EditTools/EllipseDrawEditTool.hpp"
#include "EditTools/BrushEditTool.hpp"
EditTool::EditTool(DrawingProgram& initDrawP):
DrawingProgramToolBase(initDrawP)
@ -124,6 +125,10 @@ void EditTool::edit_start(CanvasComponentContainer::ObjInfo* comp, bool initUndo
compEditTool = std::make_unique<ImageEditTool>(drawP);
break;
}
case CanvasComponentType::BRUSHSTROKE: {
compEditTool = std::make_unique<BrushEditTool>(drawP);
break;
}
default: {
isEditing = false;
break;
@ -138,7 +143,7 @@ void EditTool::edit_start(CanvasComponentContainer::ObjInfo* comp, bool initUndo
}
bool EditTool::is_editable(CanvasComponentContainer::ObjInfo* comp) {
return comp->obj->get_comp().get_type() != CanvasComponentType::BRUSHSTROKE;
return true; // Brush strokes used to not be editable, but now they are so this always returns true
}
void EditTool::tool_update() {

View file

@ -0,0 +1,38 @@
#include "BrushEditTool.hpp"
#include "../../DrawingProgram.hpp"
#include "../../../World.hpp"
#include "../../../MainProgram.hpp"
#include "../EditTool.hpp"
BrushEditTool::BrushEditTool(DrawingProgram& initDrawP):
DrawingProgramEditToolBase(initDrawP)
{}
bool BrushEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) {
auto& a = static_cast<BrushStrokeCanvasComponent&>(comp->obj->get_comp());
Toolbar& t = drawP.world.main.toolbar;
t.gui.push_id("edit tool brush");
t.gui.text_label_centered("Edit Brush Stroke");
t.gui.left_to_right_line_layout([&]() {
if(t.gui.color_button_big("Outline Color", &a.d.color, &a.d.color == t.colorRight))
t.color_selector_right(&a.d.color == t.colorRight ? nullptr : &a.d.color);
t.gui.text_label("Outline Color");
});
t.gui.pop_id();
bool editHappened = a.d.color != oldColor;
oldColor = a.d.color;
return editHappened;
}
void BrushEditTool::edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* comp, std::any& prevData) {
auto& a = static_cast<BrushStrokeCanvasComponent&>(comp->obj->get_comp());
oldColor = a.d.color;
}
void BrushEditTool::commit_edit_updates(CanvasComponentContainer::ObjInfo* comp, std::any& prevData) {
}
bool BrushEditTool::edit_update(CanvasComponentContainer::ObjInfo* comp) {
return true;
}

View file

@ -0,0 +1,18 @@
#pragma once
#include "DrawingProgramEditToolBase.hpp"
#include "../../../CanvasComponents/BrushStrokeCanvasComponent.hpp"
#include <Helpers/SCollision.hpp>
#include <any>
class DrawingProgram;
class BrushEditTool : public DrawingProgramEditToolBase {
public:
BrushEditTool(DrawingProgram& initDrawP);
virtual void edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* comp, std::any& prevData) override;
virtual void commit_edit_updates(CanvasComponentContainer::ObjInfo* comp, std::any& prevData) override;
virtual bool edit_update(CanvasComponentContainer::ObjInfo* comp) override;
virtual bool edit_gui(CanvasComponentContainer::ObjInfo* comp) override;
private:
Vector4f oldColor;
};

View file

@ -42,11 +42,7 @@ void LassoSelectTool::gui_toolbox() {
auto& t = drawP.world.main.toolbar;
t.gui.push_id("lasso select tool");
t.gui.text_label_centered("Lasso Select");
t.gui.text_label("Select 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;
if(t.gui.radio_button_field("all visible", "All visible layers", drawP.controls.layerSelector == DrawingProgramLayerManager::LayerSelector::ALL_VISIBLE_LAYERS))
drawP.controls.layerSelector = DrawingProgramLayerManager::LayerSelector::ALL_VISIBLE_LAYERS;
drawP.selection.selection_gui();
t.gui.pop_id();
}

View file

@ -51,11 +51,11 @@ void LineDrawTool::tool_update() {
BrushStrokeCanvasComponentPoint p;
p.pos = drawP.world.main.input.mouse.pos;
p.width = toolConfig.get_relative_width(toolConfig.lineDraw.relativeWidth);
newBrushStroke.d->points.emplace_back(p);
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;
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);
}
@ -66,7 +66,7 @@ void LineDrawTool::tool_update() {
if(drawP.controls.leftClickHeld) {
BrushStrokeCanvasComponent& brushStroke = static_cast<BrushStrokeCanvasComponent&>(containerPtr->get_comp());
Vector2f newPos = containerPtr->coords.get_mouse_pos(drawP.world);
Vector2f oldPos = brushStroke.d->points.front().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();
@ -76,7 +76,7 @@ void LineDrawTool::tool_update() {
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);
brushStroke.d.points->back().pos = ensure_points_have_distance(oldPos, newPos, 1.0f);
containerPtr->send_comp_update(drawP, false);
containerPtr->commit_update(drawP);
}

View file

@ -20,11 +20,7 @@ void RectSelectTool::gui_toolbox() {
auto& t = drawP.world.main.toolbar;
t.gui.push_id("rectangle select tool");
t.gui.text_label_centered("Rectangle Select");
t.gui.text_label("Select 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;
if(t.gui.radio_button_field("all visible", "All visible layers", drawP.controls.layerSelector == DrawingProgramLayerManager::LayerSelector::ALL_VISIBLE_LAYERS))
drawP.controls.layerSelector = DrawingProgramLayerManager::LayerSelector::ALL_VISIBLE_LAYERS;
drawP.selection.selection_gui();
t.gui.pop_id();
}