Skip to content

Commit

Permalink
fix: group action should update parent size
Browse files Browse the repository at this point in the history
  • Loading branch information
F-star committed Jun 16, 2024
1 parent a64d20d commit 665fbcb
Show file tree
Hide file tree
Showing 13 changed files with 152 additions and 200 deletions.
1 change: 0 additions & 1 deletion packages/core/src/commands/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
export * from './add_graphs';
export * from './command_manager';
export * from './macro';
export * from './remove_graphs';
export * from './set_elements_attrs';
export * from './type';
export * from './update_graphics_attrs_cmd';
78 changes: 0 additions & 78 deletions packages/core/src/commands/remove_graphs.ts

This file was deleted.

27 changes: 27 additions & 0 deletions packages/core/src/commands/update_graphics_attrs_cmd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export class UpdateGraphicsAttrsCmd implements ICommand {
private originAttrsMap: Map<string, Partial<GraphicsAttrs>>,
private updatedAttrsMap: Map<string, Partial<GraphicsAttrs>>,
private removedIds: Set<string> = new Set(),
private newIds: Set<string> = new Set(),
) {
if (originAttrsMap.size !== updatedAttrsMap.size) {
console.warn(
Expand Down Expand Up @@ -41,6 +42,19 @@ export class UpdateGraphicsAttrsCmd implements ICommand {
graphics.setDeleted(true);
}
}

for (const id of this.newIds) {
const graphics = doc.getGraphicsById(id);
if (graphics) {
graphics.setDeleted(false);
const position = graphics.attrs.parentIndex?.position;
if (position) {
graphics.insertAtParent(position);
} else {
console.error('position lost');
}
}
}
}
undo() {
const attrsMap = this.originAttrsMap;
Expand Down Expand Up @@ -70,5 +84,18 @@ export class UpdateGraphicsAttrsCmd implements ICommand {
}
}
}

for (const id of this.newIds) {
const graphics = doc.getGraphicsById(id);
if (graphics) {
graphics.setDeleted(true);
graphics.removeFromParent();
}
}

// resolve temporarily
if (this.newIds.size !== 0) {
this.editor.selectedElements.clear();
}
}
}
2 changes: 1 addition & 1 deletion packages/core/src/selected_elements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { boxToRect, type IRect, mergeBoxes } from '@suika/geo';

import { type Editor } from './editor';
import { isGroupGraphics, type SuikaGraphics } from './graphs';
import { getParentIdSet } from './service/group_and_record';
import { removeGraphicsAndRecord } from './service/remove_service';
import { getParentIdSet } from './utils';

interface Events {
itemsChange(items: SuikaGraphics[]): void;
Expand Down
108 changes: 35 additions & 73 deletions packages/core/src/service/group_and_record.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,31 @@ import {
multiplyMatrix,
} from '@suika/geo';

import { AddGraphCmd, MacroCmd, SetGraphsAttrsCmd } from '../commands';
import { type Editor } from '../editor';
import { SuikaFrame, SuikaGraphics } from '../graphs';
import { Transaction } from '../transaction';
import { getParentIdSet } from '../utils';

export const groupAndRecord = (graphs: SuikaGraphics[], editor: Editor) => {
if (graphs.length === 0) {
export const groupAndRecord = (
graphicsArr: SuikaGraphics[],
editor: Editor,
) => {
if (graphicsArr.length === 0) {
console.warn('graphics should not be empty');
return;
}
graphs = SuikaGraphics.sortGraphics(graphs);

const prevAttrsArr = graphs.map((item) => ({
parentIndex: cloneDeep(item.attrs.parentIndex)!,
transform: cloneDeep(item.attrs.transform),
}));
graphicsArr = SuikaGraphics.sortGraphics(graphicsArr);
const parentIdSet = getParentIdSet(graphicsArr);

const lastGraphics = graphs.at(-1)!;
const lastGraphics = graphicsArr.at(-1)!;
const parentOfGroup = lastGraphics.getParent()!;
const parentOfGroupInvertTf = invertMatrix(parentOfGroup.getWorldTransform());

const groupSortIndex = lastGraphics.getSortIndex();

const { x, y, width, height } = boxToRect(
const boundRect = boxToRect(
mergeBoxes(
graphs.map((el) => {
graphicsArr.map((el) => {
return calcRectBbox({
...el.getSize(),
transform: multiplyMatrix(
Expand All @@ -46,82 +46,44 @@ export const groupAndRecord = (graphs: SuikaGraphics[], editor: Editor) => {
const group = new SuikaFrame(
{
objectName: '',
width: width,
height: height,
width: boundRect.width,
height: boundRect.height,
resizeToFit: true,
},
{
advancedAttrs: {
x,
y,
x: boundRect.x,
y: boundRect.y,
},
doc: editor.doc,
},
);
parentOfGroup.insertChild(group, groupSortIndex);
const groupInvertTf = invertMatrix(group.getWorldTransform());

for (const el of graphs) {
el.updateAttrs({
transform: multiplyMatrix(groupInvertTf, el.getWorldTransform()),
});
group.insertChild(el);
}

const AttrsArr = graphs.map((item) => ({
parentIndex: cloneDeep(item.attrs.parentIndex)!,
transform: cloneDeep(item.attrs.transform),
}));

editor.sceneGraph.addItems([group]);
editor.selectedElements.setItems([group]);
editor.commandManager.pushCommand(
new MacroCmd('group', [
new AddGraphCmd('', editor, [group]),
new SetGraphsAttrsCmd('', graphs, AttrsArr, prevAttrsArr),
]),
);
};
const transaction = new Transaction(editor);
transaction.newId(group.attrs.id);

export const getParentIdSet = (items: SuikaGraphics[]) => {
return items.reduce((set, graphics) => {
const currSet = new Set<string>();
for (const id of graphics.getFrameParentIds()) {
if (set.has(id)) {
break;
}
currSet.add(id);
}

if (currSet.size === 0) {
return set;
}
// union set
set.forEach((id) => {
currSet.add(id);
for (const graphics of graphicsArr) {
transaction.recordOld(graphics.attrs.id, {
parentIndex: cloneDeep(graphics.attrs.parentIndex),
transform: cloneDeep(graphics.attrs.transform),
});
return currSet;
}, new Set<string>());
};

export const getChildNodeSet = (
items: SuikaGraphics[],
includeSelf = false,
) => {
const set = new Set<SuikaGraphics>();
for (const item of items) {
if (set.has(item)) {
return set;
}

if (includeSelf) {
set.add(item);
}
graphics.updateAttrs({
transform: multiplyMatrix(groupInvertTf, graphics.getWorldTransform()),
});
group.insertChild(graphics);

const childSet = getChildNodeSet(item.getChildren(), true);
childSet.forEach((node) => {
set.add(node);
transaction.update(graphics.attrs.id, {
parentIndex: cloneDeep(graphics.attrs.parentIndex),
transform: cloneDeep(graphics.attrs.transform),
});
}
return set;

transaction.updateNodeSize(parentIdSet);
transaction.commit('group');

editor.sceneGraph.addItems([group]);
editor.selectedElements.setItems([group]);
};
5 changes: 2 additions & 3 deletions packages/core/src/service/remove_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import {
type SuikaFrame,
type SuikaGraphics,
} from '../graphs';
import { updateParentSize } from '../tools/tool_select/utils';
import { getChildNodeSet, getParentIdSet } from './group_and_record';
import { getChildNodeSet, getParentIdSet, updateNodeSize } from '../utils';

export const removeGraphicsAndRecord = (
editor: Editor,
Expand Down Expand Up @@ -41,7 +40,7 @@ export const removeGraphicsAndRecord = (
const originAttrsMap = new Map<string, Partial<GraphicsAttrs>>();
const updatedAttrsMap = new Map<string, Partial<GraphicsAttrs>>();

updateParentSize(editor, parentIdSet, originAttrsMap, updatedAttrsMap);
updateNodeSize(editor, parentIdSet, originAttrsMap, updatedAttrsMap);

editor.commandManager.pushCommand(
new UpdateGraphicsAttrsCmd(
Expand Down
8 changes: 2 additions & 6 deletions packages/core/src/tools/tool_select/tool_select_resize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,9 @@ import { HALF_PI } from '../../constant';
import { isTransformHandle } from '../../control_handle_manager';
import { type Editor } from '../../editor';
import { type GraphicsAttrs, type SuikaGraphics } from '../../graphs';
import {
getChildNodeSet,
getParentIdSet,
} from '../../service/group_and_record';
import { SnapHelper } from '../../snap';
import { getChildNodeSet, getParentIdSet, updateNodeSize } from '../../utils';
import { type IBaseTool } from '../type';
import { updateParentSize } from './utils';

/**
* scale element
Expand Down Expand Up @@ -300,7 +296,7 @@ export class SelectResizeTool implements IBaseTool {
this.updateChildren(prependedTransform);

// 3. update parents width/height/transform
updateParentSize(
updateNodeSize(
this.editor,
getParentIdSet(selectedItems),
this.originAttrsMap,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { getRectByTwoPoint, type IPoint } from '@suika/geo';

import { type Editor } from '../../editor';
import { type SuikaGraphics } from '../../graphs';
import { getParentIdSet } from '../../service/group_and_record';
import { getParentIdSet } from '../../utils';
import { type IBaseTool } from '../type';
import { getElementsInSelection } from './utils';

Expand Down
22 changes: 1 addition & 21 deletions packages/core/src/tools/tool_select/utils.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
import { type IBox, type IPoint, rectToBox } from '@suika/geo';

import { type Editor } from '../../editor';
import {
type GraphicsAttrs,
isGroupGraphics,
SuikaFrame,
type SuikaGraphics,
} from '../../graphs';
import { SuikaFrame, type SuikaGraphics } from '../../graphs';

/********* get top hit element ********/
export const getTopHitElement = (
Expand Down Expand Up @@ -94,18 +89,3 @@ const getElementsInSelectionDFS = (
}
return graphicsArr;
};

// 修正父节点的 width/height/transform
export const updateParentSize = (
editor: Editor,
parentIdSet: Set<string>,
originAttrsMap: Map<string, Partial<GraphicsAttrs>>,
updatedAttrsMap: Map<string, Partial<GraphicsAttrs>>,
) => {
parentIdSet.forEach((id) => {
const node = editor.doc.getGraphicsById(id);
if (node && isGroupGraphics(node) && !node.isEmpty()) {
node.updateSizeByChildren(originAttrsMap, updatedAttrsMap);
}
});
};
Loading

0 comments on commit 665fbcb

Please sign in to comment.