homemanager-fe/src/modules/house-planner/tools/cut.ts

122 lines
3.5 KiB
TypeScript

import {
BezierSegment,
LayerObject,
Line,
LineSegment,
Vec2,
} from '../interfaces';
import { CanvasToolBase } from './tool-base';
export type CutToolType = 'cut' | 'remove-segment';
export class CutTool extends CanvasToolBase<CutToolType> {
public name = 'cut';
public subTool: CutToolType | undefined = 'cut';
mouseMoved(mouse: Vec2, offset: Vec2, mouseAbsolute: Vec2) {
super.mouseMoved(mouse, offset, mouseAbsolute);
this.renderer.draw();
}
mouseDown(targetObject?: LayerObject | undefined): void {
if (
!targetObject ||
targetObject.type === 'curve' ||
targetObject.type === 'object'
)
return;
const line = targetObject as Line;
const segment = this.manager.getMousedLineSegment(line);
if (!segment) return;
const segmentIndex = line.segments.indexOf(segment);
if (this.subTool === 'remove-segment') {
const nextSegment = line.segments[segmentIndex + 1];
if (!nextSegment) return;
if (segment.start) {
nextSegment.start = segment.start;
line.segments.splice(segmentIndex, 1);
} else {
nextSegment.start = segment.end;
line.segments.splice(segmentIndex, 1);
}
} else {
const currentEnd: Vec2 = [...segment.end];
segment.end = [...this.mousePosition];
line.segments.splice(segmentIndex + 1, 0, { end: currentEnd });
}
this.renderer.draw();
}
drawBezierControls(bezier: BezierSegment, previousEnd: Vec2) {
const [cp1x, cp1y] = bezier.startControl;
const [cp2x, cp2y] = bezier.endControl;
const [endx, endy] = bezier.end;
const [prevx, prevy] = previousEnd;
this.ctx.fillStyle = '#00ddffaa';
this.ctx.strokeStyle = '#00ddffaa';
this.ctx.lineWidth = 2;
this.ctx.beginPath();
this.ctx.arc(cp1x, cp1y, this.manager.selectError / 2, 0, 2 * Math.PI);
this.ctx.fill();
this.ctx.beginPath();
this.ctx.arc(cp2x, cp2y, this.manager.selectError / 2, 0, 2 * Math.PI);
this.ctx.fill();
this.ctx.beginPath();
this.ctx.moveTo(cp1x, cp1y);
this.ctx.lineTo(prevx, prevy);
this.ctx.stroke();
this.ctx.beginPath();
this.ctx.moveTo(cp2x, cp2y);
this.ctx.lineTo(endx, endy);
this.ctx.stroke();
}
drawLineControls(line: LineSegment, previousEnd: Vec2) {
const [endx, endy] = line.end;
this.ctx.fillStyle = '#00ddffaa';
this.ctx.beginPath();
this.ctx.arc(endx, endy, this.manager.selectError / 2, 0, 2 * Math.PI);
this.ctx.fill();
if (line.start) {
const [startx, starty] = line.start;
this.ctx.beginPath();
this.ctx.arc(
startx,
starty,
this.manager.selectError / 2,
0,
2 * Math.PI
);
this.ctx.fill();
}
}
drawControls(): void {
for (const object of this.manager.selectedObjects) {
const line = object as Line;
if (line.segments && line.render) {
let lastSegment = null;
for (const segment of line.segments) {
const bezier = segment as BezierSegment;
const previousPoint = lastSegment ? lastSegment.end : segment.start!;
if (bezier.startControl && bezier.endControl) {
this.drawBezierControls(bezier, previousPoint);
}
this.drawLineControls(segment, previousPoint);
lastSegment = segment;
}
}
}
const [mx, my] = this.mousePosition;
this.ctx.fillStyle = '#00ddffaa';
this.ctx.beginPath();
this.ctx.arc(mx, my, this.manager.selectError / 2, 0, 2 * Math.PI);
this.ctx.fill();
}
}