Skip to content

Commit

Permalink
feat: snap to object when resizing
Browse files Browse the repository at this point in the history
  • Loading branch information
F-star committed Jan 12, 2025
1 parent 66681f4 commit b0ace07
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 29 deletions.
4 changes: 2 additions & 2 deletions packages/core/src/ref_line.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ export class RefLine {
* update ref line
* and return offset
*/
getGraphicsSnapOffset(targetPoints: IPoint[]): IPoint | undefined {
getGraphicsSnapOffset(targetPoints: IPoint[]): IPoint {
this.toDrawVLines = [];
this.toDrawHLines = [];

Expand All @@ -232,7 +232,7 @@ export class RefLine {

// there are no reference graphs
if (sortedXs.length === 0 && sortedYs.length === 0) {
return undefined;
return { x: 0, y: 0 };
}

let offsetX: number | undefined = undefined;
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/selected_elements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export class SelectedElements {
this.emitItemsChangeIfChanged(prevItems, items);
}
getItems({ excludeLocked = false } = {}): SuikaGraphics[] {
// TODO: cache items ?
if (excludeLocked) {
return this.items.filter((item) => !item.isLock());
}
Expand Down
11 changes: 5 additions & 6 deletions packages/core/src/tools/tool_draw_graphics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,12 +146,11 @@ export abstract class DrawGraphicsTool implements ITool {
const offset = this.editor.refLine.getGraphicsSnapOffset([
this.lastDragPoint,
]);
if (offset) {
this.lastDragPoint = {
x: this.lastDragPoint.x + offset.x,
y: this.lastDragPoint.y + offset.y,
};
}
this.lastDragPoint = {
x: this.lastDragPoint.x + offset.x,
y: this.lastDragPoint.y + offset.y,
};

this.isDragging = true;

this.updateRect();
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/tools/tool_select/tool_select_move.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,8 @@ export class SelectMoveTool implements IBaseTool {
const newWorldTf = cloneDeep(
this.originWorldTfMap.get(graphics.attrs.id)!,
);
newWorldTf[4] += dx + (offset?.x ?? 0);
newWorldTf[5] += dy + (offset?.y ?? 0);
newWorldTf[4] += dx + offset.x;
newWorldTf[5] += dy + offset.y;

// change parent
if (this.prevParent !== newParent) {
Expand Down
55 changes: 36 additions & 19 deletions packages/core/src/tools/tool_select/tool_select_resize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export class SelectResizeTool implements IBaseTool {

private updatedAttrsMap = new Map<string, Partial<GraphicsAttrs>>();

private lastPoint: IPoint | null = null;
private lastDragPoint: IPoint | null = null;
private prevLastPoint: IPoint | null = null;
private unbind = noop;

Expand Down Expand Up @@ -98,24 +98,40 @@ export class SelectResizeTool implements IBaseTool {
this.editor.commandManager.disableRedoUndo();
this.editor.hostEventManager.disableDelete();

const enableGripSnap =
this.editor.setting.get('snapToGrid') &&
(['nw', 'ne', 'se', 'sw'].includes(this.handleName) ||
(['n', 'e', 's', 'w'].includes(this.handleName) &&
this.editor.selectedElements.size() > 1) ||
const isTwoDirResizeHandle = ['nw', 'ne', 'se', 'sw'].includes(
this.handleName,
);
const isOneDirResizeWithoutRotateHandle =
['n', 'e', 's', 'w'].includes(this.handleName) &&
(this.editor.selectedElements.size() > 1 ||
this.editor.selectedElements.getItems()[0].getRotate() % HALF_PI === 0);

this.lastPoint = this.editor.getSceneCursorXY(e);
if (enableGripSnap) {
this.lastPoint = SnapHelper.getSnapPtBySetting(
this.lastPoint,
this.editor.setting,
);
if (!this.lastDragPoint) {
this.editor.refLine.cacheGraphicsRefLines();
}
this.lastDragPoint = this.editor.getSceneCursorXY(e);

if (isTwoDirResizeHandle || isOneDirResizeWithoutRotateHandle) {
if (this.editor.setting.get('snapToGrid')) {
this.lastDragPoint = SnapHelper.getSnapPtBySetting(
this.lastDragPoint,
this.editor.setting,
);
}

const objectSnapOffset = this.editor.refLine.getGraphicsSnapOffset([
this.lastDragPoint,
]);

this.lastDragPoint = {
x: this.lastDragPoint.x + objectSnapOffset.x,
y: this.lastDragPoint.y + objectSnapOffset.y,
};
}

const prevLastPoint = this.prevLastPoint;
this.prevLastPoint = this.lastPoint;
if (isEqual(prevLastPoint, this.lastPoint)) {
this.prevLastPoint = this.lastDragPoint;
if (isEqual(prevLastPoint, this.lastDragPoint)) {
return;
}

Expand Down Expand Up @@ -150,7 +166,7 @@ export class SelectResizeTool implements IBaseTool {
private updateSingleGraphics(graphics: SuikaGraphics) {
const updatedAttrs = graphics.calcNewAttrsByControlHandle(
this.handleName,
this.lastPoint!,
this.lastDragPoint!,
this.originAttrsMap.get(graphics.attrs.id)!,
this.originWorldTransforms.get(graphics.attrs.id)!,
this.editor.hostEventManager.isShiftPressing,
Expand Down Expand Up @@ -195,7 +211,7 @@ export class SelectResizeTool implements IBaseTool {
};

private updateGraphics() {
if (!this.lastPoint) return;
if (!this.lastDragPoint) return;

let prependedTransform: Matrix = new Matrix();

Expand All @@ -217,7 +233,7 @@ export class SelectResizeTool implements IBaseTool {

const updatedTransformRect = resizeRect(
this.handleName,
this.lastPoint,
this.lastDragPoint,
{
width: originAttrs.width,
height: originAttrs.height,
Expand Down Expand Up @@ -253,7 +269,7 @@ export class SelectResizeTool implements IBaseTool {

const transformRect = resizeRect(
this.handleName,
this.lastPoint,
this.lastDragPoint,
{
width: startSelectBbox.width,
height: startSelectBbox.height,
Expand Down Expand Up @@ -361,6 +377,7 @@ export class SelectResizeTool implements IBaseTool {
this.originAttrsMap = new Map();
this.updatedAttrsMap = new Map();

this.lastPoint = null;
this.lastDragPoint = null;
this.editor.refLine.clear();
}
}
4 changes: 4 additions & 0 deletions packages/geo/src/geo/geo_point.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ export const pointSub = (p1: IPoint, p2: IPoint): IPoint => {
};
};

export const isZeroPoint = (p: IPoint) => {
return p.x === 0 && p.y === 0;
};

const TOL = 0.0000000001;

export const isPointEqual = (p1: IPoint, p2: IPoint, tol = TOL) => {
Expand Down

0 comments on commit b0ace07

Please sign in to comment.