mitja/improve-current-page-shapes-sorted
Mitja Bezenšek 2024-04-11 18:00:21 +02:00
rodzic bc9087f9d6
commit 07388090fb
3 zmienionych plików z 164 dodań i 23 usunięć

Wyświetl plik

@ -683,6 +683,8 @@ export class Editor extends EventEmitter<TLEventMap> {
getCurrentPageShapeIds(): Set<TLShapeId>; getCurrentPageShapeIds(): Set<TLShapeId>;
getCurrentPageShapes(): TLShape[]; getCurrentPageShapes(): TLShape[];
getCurrentPageShapesSorted(): TLShape[]; getCurrentPageShapesSorted(): TLShape[];
// (undocumented)
_getCurrentPageShapesSorted(shapes: Set<TLShape>): TLShape[];
getCurrentPageState(): TLInstancePageState; getCurrentPageState(): TLInstancePageState;
getCurrentTool(): StateNode; getCurrentTool(): StateNode;
getCurrentToolId(): string; getCurrentToolId(): string;
@ -692,6 +694,8 @@ export class Editor extends EventEmitter<TLEventMap> {
getEditingShapeId(): null | TLShapeId; getEditingShapeId(): null | TLShapeId;
getErasingShapeIds(): TLShapeId[]; getErasingShapeIds(): TLShapeId[];
getErasingShapes(): NonNullable<TLShape | undefined>[]; getErasingShapes(): NonNullable<TLShape | undefined>[];
// (undocumented)
getFilteredCurrentPageShapesSorted(filter: (shape: TLShape) => boolean): TLShape[];
getFocusedGroup(): TLShape | undefined; getFocusedGroup(): TLShape | undefined;
getFocusedGroupId(): TLPageId | TLShapeId; getFocusedGroupId(): TLPageId | TLShapeId;
getHighestIndexForParent(parent: TLPage | TLParentId | TLShape): IndexKey; getHighestIndexForParent(parent: TLPage | TLParentId | TLShape): IndexKey;

Wyświetl plik

@ -7440,6 +7440,73 @@
"name": "Editor", "name": "Editor",
"preserveMemberOrder": false, "preserveMemberOrder": false,
"members": [ "members": [
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#_getCurrentPageShapesSorted:member(1)",
"docComment": "",
"excerptTokens": [
{
"kind": "Content",
"text": "_getCurrentPageShapesSorted(shapes: "
},
{
"kind": "Reference",
"text": "Set",
"canonicalReference": "!Set:interface"
},
{
"kind": "Content",
"text": "<"
},
{
"kind": "Reference",
"text": "TLShape",
"canonicalReference": "@tldraw/tlschema!TLShape:type"
},
{
"kind": "Content",
"text": ">"
},
{
"kind": "Content",
"text": "): "
},
{
"kind": "Reference",
"text": "TLShape",
"canonicalReference": "@tldraw/tlschema!TLShape:type"
},
{
"kind": "Content",
"text": "[]"
},
{
"kind": "Content",
"text": ";"
}
],
"isStatic": false,
"returnTypeTokenRange": {
"startIndex": 6,
"endIndex": 8
},
"releaseTag": "Public",
"isProtected": false,
"overloadIndex": 1,
"parameters": [
{
"parameterName": "shapes",
"parameterTypeTokenRange": {
"startIndex": 1,
"endIndex": 5
},
"isOptional": false
}
],
"isOptional": false,
"isAbstract": false,
"name": "_getCurrentPageShapesSorted"
},
{ {
"kind": "Constructor", "kind": "Constructor",
"canonicalReference": "@tldraw/editor!Editor:constructor(1)", "canonicalReference": "@tldraw/editor!Editor:constructor(1)",
@ -10937,6 +11004,68 @@
"isAbstract": false, "isAbstract": false,
"name": "getErasingShapes" "name": "getErasingShapes"
}, },
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#getFilteredCurrentPageShapesSorted:member(1)",
"docComment": "",
"excerptTokens": [
{
"kind": "Content",
"text": "getFilteredCurrentPageShapesSorted(filter: "
},
{
"kind": "Content",
"text": "(shape: "
},
{
"kind": "Reference",
"text": "TLShape",
"canonicalReference": "@tldraw/tlschema!TLShape:type"
},
{
"kind": "Content",
"text": ") => boolean"
},
{
"kind": "Content",
"text": "): "
},
{
"kind": "Reference",
"text": "TLShape",
"canonicalReference": "@tldraw/tlschema!TLShape:type"
},
{
"kind": "Content",
"text": "[]"
},
{
"kind": "Content",
"text": ";"
}
],
"isStatic": false,
"returnTypeTokenRange": {
"startIndex": 5,
"endIndex": 7
},
"releaseTag": "Public",
"isProtected": false,
"overloadIndex": 1,
"parameters": [
{
"parameterName": "filter",
"parameterTypeTokenRange": {
"startIndex": 1,
"endIndex": 4
},
"isOptional": false
}
],
"isOptional": false,
"isAbstract": false,
"name": "getFilteredCurrentPageShapesSorted"
},
{ {
"kind": "Method", "kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#getFocusedGroup:member(1)", "canonicalReference": "@tldraw/editor!Editor#getFocusedGroup:member(1)",

Wyświetl plik

@ -4307,14 +4307,15 @@ export class Editor extends EventEmitter<TLEventMap> {
this.getShapeIdsInsideBounds(Box.FromPoints([point]).expandBy(HIT_TEST_MARGIN)) this.getShapeIdsInsideBounds(Box.FromPoints([point]).expandBy(HIT_TEST_MARGIN))
) )
const selectedShapeIds = this.getSelectedShapeIds() const selectedShapeIds = this.getSelectedShapeIds()
const filter = (shape: TLShape) => {
return this.getCurrentPageShapesSorted() return (
.filter( shape.type !== 'group' &&
(shape) => shapesCloseToPoint.has(shape.id) &&
shape.type !== 'group' && selectedShapeIds.includes(shape.id)
shapesCloseToPoint.has(shape.id) &&
selectedShapeIds.includes(shape.id)
) )
}
return this.getFilteredCurrentPageShapesSorted(filter)
.reverse() // findlast .reverse() // findlast
.find((shape) => this.isPointInShape(shape, point, { hitInside: true, margin: 0 })) .find((shape) => this.isPointInShape(shape, point, { hitInside: true, margin: 0 }))
} }
@ -4357,18 +4358,17 @@ export class Editor extends EventEmitter<TLEventMap> {
const shapesCloseToPoint = new Set( const shapesCloseToPoint = new Set(
this.getShapeIdsInsideBounds(Box.FromPoints([point]).expandBy(HIT_TEST_MARGIN)) this.getShapeIdsInsideBounds(Box.FromPoints([point]).expandBy(HIT_TEST_MARGIN))
) )
const shapesToCheck = ( const culledShapes = this.getCulledShapes()
opts.renderingOnly const f = (shape: TLShape) => {
? this.getCurrentPageRenderingShapesSorted() if (opts.renderingOnly && culledShapes.has(shape.id)) return false
: this.getCurrentPageShapesSorted() if (!shapesCloseToPoint.has(shape.id)) return false
).filter((shape) => {
if (!shapesCloseToPoint.has(shape.id)) return
if (this.isShapeOfType(shape, 'group')) return false if (this.isShapeOfType(shape, 'group')) return false
const pageMask = this.getShapeMask(shape) const pageMask = this.getShapeMask(shape)
if (pageMask && !pointInPolygon(point, pageMask)) return false if (pageMask && !pointInPolygon(point, pageMask)) return false
if (filter) return filter(shape) if (filter) return filter(shape)
return true return true
}) }
const shapesToCheck = this.getFilteredCurrentPageShapesSorted(f)
for (let i = shapesToCheck.length - 1; i >= 0; i--) { for (let i = shapesToCheck.length - 1; i >= 0; i--) {
const shape = shapesToCheck[i] const shape = shapesToCheck[i]
const geometry = this.getShapeGeometry(shape) const geometry = this.getShapeGeometry(shape)
@ -4623,12 +4623,17 @@ export class Editor extends EventEmitter<TLEventMap> {
* @public * @public
*/ */
@computed getCurrentPageShapesSorted(): TLShape[] { @computed getCurrentPageShapesSorted(): TLShape[] {
// todo: consider making into a function call that includes options for selected-only, rendering, etc.
// todo: consider making a derivation or something, or merging with rendering shapes
const shapes = new Set(this.getCurrentPageShapes().sort(sortByIndex)) const shapes = new Set(this.getCurrentPageShapes().sort(sortByIndex))
return this._getCurrentPageShapesSorted(shapes)
}
getFilteredCurrentPageShapesSorted(filter: (shape: TLShape) => boolean): TLShape[] {
const shapes = new Set(this.getCurrentPageShapes().filter(filter).sort(sortByIndex))
return this._getCurrentPageShapesSorted(shapes)
}
_getCurrentPageShapesSorted(shapes: Set<TLShape>) {
const results: TLShape[] = [] const results: TLShape[] = []
function pushShapeWithDescendants(shape: TLShape): void { function pushShapeWithDescendants(shape: TLShape): void {
results.push(shape) results.push(shape)
shapes.delete(shape) shapes.delete(shape)
@ -4658,7 +4663,8 @@ export class Editor extends EventEmitter<TLEventMap> {
*/ */
@computed getCurrentPageRenderingShapesSorted(): TLShape[] { @computed getCurrentPageRenderingShapesSorted(): TLShape[] {
const culledShapes = this.getCulledShapes() const culledShapes = this.getCulledShapes()
return this.getCurrentPageShapesSorted().filter(({ id }) => !culledShapes.has(id)) const filter = (shape: TLShape) => !culledShapes.has(shape.id)
return this.getFilteredCurrentPageShapesSorted(filter)
} }
/** /**
@ -5037,18 +5043,20 @@ export class Editor extends EventEmitter<TLEventMap> {
*/ */
getDroppingOverShape(point: VecLike, droppingShapes: TLShape[] = []) { getDroppingOverShape(point: VecLike, droppingShapes: TLShape[] = []) {
// starting from the top... // starting from the top...
const currentPageShapesSorted = this.getCurrentPageShapesSorted() const filter = (shape: TLShape) => {
for (let i = currentPageShapesSorted.length - 1; i >= 0; i--) {
const shape = currentPageShapesSorted[i]
if ( if (
// only allow shapes that can receive children // only allow shapes that can receive children
!this.getShapeUtil(shape).canDropShapes(shape, droppingShapes) || !this.getShapeUtil(shape).canDropShapes(shape, droppingShapes) ||
// don't allow dropping a shape on itself or one of it's children // don't allow dropping a shape on itself or one of it's children
droppingShapes.find((s) => s.id === shape.id || this.hasAncestor(shape, s.id)) droppingShapes.find((s) => s.id === shape.id || this.hasAncestor(shape, s.id))
) { ) {
continue return false
} }
return true
}
const currentPageShapesSorted = this.getFilteredCurrentPageShapesSorted(filter)
for (let i = currentPageShapesSorted.length - 1; i >= 0; i--) {
const shape = currentPageShapesSorted[i]
// Only allow dropping into the masked page bounds of the shape, e.g. when a frame is // Only allow dropping into the masked page bounds of the shape, e.g. when a frame is
// partially clipped by its own parent frame // partially clipped by its own parent frame