@woven-canvas/core 1.0.6 → 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/build/_tsup-dts-rollup.d.cts +69 -1
- package/build/_tsup-dts-rollup.d.ts +69 -1
- package/build/index.cjs +746 -520
- package/build/index.cjs.map +1 -1
- package/build/index.d.cts +7 -0
- package/build/index.d.ts +7 -0
- package/build/index.js +602 -382
- package/build/index.js.map +1 -1
- package/package.json +4 -4
package/build/index.js
CHANGED
|
@@ -8,21 +8,21 @@ var __export = (target, all) => {
|
|
|
8
8
|
import {
|
|
9
9
|
CanvasComponentDef as CanvasComponentDef7,
|
|
10
10
|
CanvasSingletonDef as CanvasSingletonDef12,
|
|
11
|
-
defineCanvasComponent as
|
|
11
|
+
defineCanvasComponent as defineCanvasComponent23,
|
|
12
12
|
defineCanvasSingleton as defineCanvasSingleton3,
|
|
13
|
-
Synced as
|
|
13
|
+
Synced as Synced10
|
|
14
14
|
} from "@woven-ecs/canvas-store";
|
|
15
15
|
import {
|
|
16
|
-
addComponent as
|
|
16
|
+
addComponent as addComponent13,
|
|
17
17
|
ComponentDef,
|
|
18
|
-
createEntity as
|
|
18
|
+
createEntity as createEntity10,
|
|
19
19
|
defineQuery as defineQuery22,
|
|
20
20
|
defineSystem,
|
|
21
21
|
EventType,
|
|
22
|
-
field as
|
|
22
|
+
field as field37,
|
|
23
23
|
getBackrefs as getBackrefs5,
|
|
24
24
|
getResources as getResources15,
|
|
25
|
-
hasComponent as
|
|
25
|
+
hasComponent as hasComponent21,
|
|
26
26
|
isAlive as isAlive3,
|
|
27
27
|
MainThreadSystem as MainThreadSystem2,
|
|
28
28
|
removeComponent as removeComponent7,
|
|
@@ -122,6 +122,7 @@ var SetCursor = defineCommand("set-cursor");
|
|
|
122
122
|
var AddFrameHighlight = defineCommand("frame-add-highlight");
|
|
123
123
|
var RemoveFrameHighlight = defineCommand("frame-remove-highlight");
|
|
124
124
|
var AssignFrameChildren = defineCommand("frame-assign-children");
|
|
125
|
+
var PlaceBlockEvent = defineCommand("place-block");
|
|
125
126
|
|
|
126
127
|
// src/commands/selection.ts
|
|
127
128
|
var SelectBlock = defineCommand("select-block");
|
|
@@ -163,8 +164,10 @@ __export(components_exports, {
|
|
|
163
164
|
HitGeometry: () => HitGeometry,
|
|
164
165
|
Hovered: () => Hovered,
|
|
165
166
|
Image: () => Image,
|
|
167
|
+
Layer: () => Layer,
|
|
166
168
|
MAX_HIT_ARCS: () => MAX_HIT_ARCS,
|
|
167
169
|
MAX_HIT_CAPSULES: () => MAX_HIT_CAPSULES,
|
|
170
|
+
MAX_HIT_POLYGON_POINTS: () => MAX_HIT_POLYGON_POINTS,
|
|
168
171
|
Opacity: () => Opacity,
|
|
169
172
|
Pointer: () => Pointer,
|
|
170
173
|
PointerButton: () => PointerButton,
|
|
@@ -472,6 +475,7 @@ var BlockDef = z.object({
|
|
|
472
475
|
resizeMode: z.enum([ResizeMode.Scale, ResizeMode.Text, ResizeMode.Free, ResizeMode.GroupOnly]).default(ResizeMode.Scale),
|
|
473
476
|
canRotate: z.boolean().default(true),
|
|
474
477
|
canScale: z.boolean().default(true),
|
|
478
|
+
snappable: z.boolean().default(true),
|
|
475
479
|
interactable: z.boolean().default(true),
|
|
476
480
|
excludeFromRankBounds: z.boolean().default(false),
|
|
477
481
|
connectors: BlockDefConnectors.default(BlockDefConnectors.parse({}))
|
|
@@ -539,7 +543,10 @@ var BlockSchema = {
|
|
|
539
543
|
/** How the block can be resized */
|
|
540
544
|
resizeMode: field2.enum(ResizeMode).default(ResizeMode.Default),
|
|
541
545
|
/** Parent block ID — position is relative to parent if set */
|
|
542
|
-
parentId: field2.ref()
|
|
546
|
+
parentId: field2.ref(),
|
|
547
|
+
/** Layer membership — carried by every block directly (a frame and its
|
|
548
|
+
* children each get their own `layerId`; no inheritance). Null = unlayered. */
|
|
549
|
+
layerId: field2.ref()
|
|
543
550
|
};
|
|
544
551
|
var _worldPos = [0, 0];
|
|
545
552
|
var BlockDef2 = class extends CanvasComponentDef {
|
|
@@ -1028,19 +1035,25 @@ var Held = defineCanvasComponent9(
|
|
|
1028
1035
|
);
|
|
1029
1036
|
|
|
1030
1037
|
// src/components/HitGeometry.ts
|
|
1031
|
-
import { Arc, Capsule, Mat2 } from "@woven-canvas/math";
|
|
1038
|
+
import { Arc, Capsule, Mat2, Polygon } from "@woven-canvas/math";
|
|
1032
1039
|
import { CanvasComponentDef as CanvasComponentDef4 } from "@woven-ecs/canvas-store";
|
|
1033
1040
|
import { field as field11 } from "@woven-ecs/core";
|
|
1034
1041
|
var _uvToWorldMatrix = [1, 0, 0, 1, 0, 0];
|
|
1042
|
+
var _polyPt = [0, 0];
|
|
1035
1043
|
var MAX_HIT_CAPSULES = 64;
|
|
1036
1044
|
var FLOATS_PER_CAPSULE = 5;
|
|
1037
1045
|
var MAX_HIT_ARCS = 2;
|
|
1038
1046
|
var FLOATS_PER_ARC = 7;
|
|
1047
|
+
var MAX_HIT_POLYGON_POINTS = 128;
|
|
1048
|
+
var FLOATS_PER_POLYGON_POINT = 2;
|
|
1049
|
+
var _worldPolygon = new Float32Array(MAX_HIT_POLYGON_POINTS * FLOATS_PER_POLYGON_POINT);
|
|
1039
1050
|
var HitGeometrySchema = {
|
|
1040
1051
|
hitCapsules: field11.buffer(field11.float32()).size(MAX_HIT_CAPSULES * FLOATS_PER_CAPSULE),
|
|
1041
1052
|
capsuleCount: field11.uint16().default(0),
|
|
1042
1053
|
hitArcs: field11.buffer(field11.float32()).size(MAX_HIT_ARCS * FLOATS_PER_ARC),
|
|
1043
|
-
arcCount: field11.uint16().default(0)
|
|
1054
|
+
arcCount: field11.uint16().default(0),
|
|
1055
|
+
hitPolygon: field11.buffer(field11.float32()).size(MAX_HIT_POLYGON_POINTS * FLOATS_PER_POLYGON_POINT),
|
|
1056
|
+
polygonPointCount: field11.uint16().default(0)
|
|
1044
1057
|
};
|
|
1045
1058
|
var HitGeometryDef = class extends CanvasComponentDef4 {
|
|
1046
1059
|
constructor() {
|
|
@@ -1151,8 +1164,27 @@ var HitGeometryDef = class extends CanvasComponentDef4 {
|
|
|
1151
1164
|
return true;
|
|
1152
1165
|
}
|
|
1153
1166
|
}
|
|
1167
|
+
const polygonPointCount = this.fillWorldPolygon(hitGeometry.hitPolygon, hitGeometry.polygonPointCount);
|
|
1168
|
+
if (polygonPointCount > 0 && Polygon.containsPointEvenOdd(_worldPolygon, polygonPointCount, point)) {
|
|
1169
|
+
return true;
|
|
1170
|
+
}
|
|
1154
1171
|
return false;
|
|
1155
1172
|
}
|
|
1173
|
+
/**
|
|
1174
|
+
* Transform the UV polygon into the shared `_worldPolygon` scratch buffer
|
|
1175
|
+
* using the current `_uvToWorldMatrix` (caller must have built it first).
|
|
1176
|
+
* Returns the vertex count. Allocation-free.
|
|
1177
|
+
*/
|
|
1178
|
+
fillWorldPolygon(hitPolygon, count) {
|
|
1179
|
+
for (let i = 0; i < count; i++) {
|
|
1180
|
+
_polyPt[0] = hitPolygon[i * 2];
|
|
1181
|
+
_polyPt[1] = hitPolygon[i * 2 + 1];
|
|
1182
|
+
Mat2.transformPoint(_uvToWorldMatrix, _polyPt);
|
|
1183
|
+
_worldPolygon[i * 2] = _polyPt[0];
|
|
1184
|
+
_worldPolygon[i * 2 + 1] = _polyPt[1];
|
|
1185
|
+
}
|
|
1186
|
+
return count;
|
|
1187
|
+
}
|
|
1156
1188
|
/**
|
|
1157
1189
|
* Check if an AABB intersects with the entity's hit geometry.
|
|
1158
1190
|
* Hit geometry is stored in UV coordinates (0-1) relative to the block.
|
|
@@ -1192,6 +1224,10 @@ var HitGeometryDef = class extends CanvasComponentDef4 {
|
|
|
1192
1224
|
return true;
|
|
1193
1225
|
}
|
|
1194
1226
|
}
|
|
1227
|
+
const polygonPointCount = this.fillWorldPolygon(hitGeometry.hitPolygon, hitGeometry.polygonPointCount);
|
|
1228
|
+
if (polygonPointCount > 0 && Polygon.intersectsAabb(_worldPolygon, polygonPointCount, aabb)) {
|
|
1229
|
+
return true;
|
|
1230
|
+
}
|
|
1195
1231
|
return false;
|
|
1196
1232
|
}
|
|
1197
1233
|
/**
|
|
@@ -1229,6 +1265,11 @@ var HitGeometryDef = class extends CanvasComponentDef4 {
|
|
|
1229
1265
|
const worldArc = Arc.create(worldA[0], worldA[1], worldB[0], worldB[1], worldC[0], worldC[1], thickness);
|
|
1230
1266
|
pts.push(...Arc.getExtrema(worldArc));
|
|
1231
1267
|
}
|
|
1268
|
+
for (let i = 0; i < hitGeometry.polygonPointCount; i++) {
|
|
1269
|
+
const world = [hitGeometry.hitPolygon[i * 2], hitGeometry.hitPolygon[i * 2 + 1]];
|
|
1270
|
+
Mat2.transformPoint(_uvToWorldMatrix, world);
|
|
1271
|
+
pts.push(world);
|
|
1272
|
+
}
|
|
1232
1273
|
return pts;
|
|
1233
1274
|
}
|
|
1234
1275
|
// ============================================
|
|
@@ -1331,6 +1372,27 @@ var HitGeometryDef = class extends CanvasComponentDef4 {
|
|
|
1331
1372
|
const uvC = Block.worldToUv(ctx, entityId, worldC);
|
|
1332
1373
|
this.addArcUv(ctx, entityId, uvA, uvB, uvC, worldThickness);
|
|
1333
1374
|
}
|
|
1375
|
+
/**
|
|
1376
|
+
* Set the filled hit polygon from UV vertices, replacing any existing one.
|
|
1377
|
+
* Positions are in UV coordinates (0-1) relative to the block. The polygon is
|
|
1378
|
+
* implicitly closed and tested with the even-odd fill rule.
|
|
1379
|
+
*
|
|
1380
|
+
* @param ctx - ECS context
|
|
1381
|
+
* @param entityId - Entity ID
|
|
1382
|
+
* @param uvPoints - Polygon vertices in UV coordinates [[x, y], ...]
|
|
1383
|
+
*/
|
|
1384
|
+
setPolygonUv(ctx, entityId, uvPoints) {
|
|
1385
|
+
const hitGeometry = this.write(ctx, entityId);
|
|
1386
|
+
const count = Math.min(uvPoints.length, MAX_HIT_POLYGON_POINTS);
|
|
1387
|
+
for (let i = 0; i < count; i++) {
|
|
1388
|
+
hitGeometry.hitPolygon[i * 2] = uvPoints[i][0];
|
|
1389
|
+
hitGeometry.hitPolygon[i * 2 + 1] = uvPoints[i][1];
|
|
1390
|
+
}
|
|
1391
|
+
hitGeometry.polygonPointCount = count;
|
|
1392
|
+
if (uvPoints.length > MAX_HIT_POLYGON_POINTS) {
|
|
1393
|
+
console.warn(`HitGeometry: polygon truncated to ${MAX_HIT_POLYGON_POINTS} points`);
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1334
1396
|
/**
|
|
1335
1397
|
* Clear all hit geometry from an entity.
|
|
1336
1398
|
*
|
|
@@ -1341,6 +1403,7 @@ var HitGeometryDef = class extends CanvasComponentDef4 {
|
|
|
1341
1403
|
const hitGeometry = this.write(ctx, entityId);
|
|
1342
1404
|
hitGeometry.capsuleCount = 0;
|
|
1343
1405
|
hitGeometry.arcCount = 0;
|
|
1406
|
+
hitGeometry.polygonPointCount = 0;
|
|
1344
1407
|
}
|
|
1345
1408
|
};
|
|
1346
1409
|
var HitGeometry = new HitGeometryDef();
|
|
@@ -1364,19 +1427,39 @@ var Image = defineCanvasComponent11(
|
|
|
1364
1427
|
}
|
|
1365
1428
|
);
|
|
1366
1429
|
|
|
1367
|
-
// src/components/
|
|
1430
|
+
// src/components/Layer.ts
|
|
1368
1431
|
import { defineCanvasComponent as defineCanvasComponent12 } from "@woven-ecs/canvas-store";
|
|
1369
1432
|
import { field as field13 } from "@woven-ecs/core";
|
|
1370
|
-
var
|
|
1433
|
+
var Layer = defineCanvasComponent12(
|
|
1434
|
+
{ name: "layer", sync: "document" },
|
|
1435
|
+
{
|
|
1436
|
+
/** Parent frame/page entity this layer belongs to — back-reference. Layers
|
|
1437
|
+
* exist only for sorting; they have no geometry of their own. */
|
|
1438
|
+
parentId: field13.ref(),
|
|
1439
|
+
/** Z-order rank among the page's layers (LexoRank string). Higher sorts in front. */
|
|
1440
|
+
rank: field13.string().max(36).default(""),
|
|
1441
|
+
/** Display name shown in the layers panel. */
|
|
1442
|
+
label: field13.string().max(128).default("Layer"),
|
|
1443
|
+
/** When true, blocks in this layer are not selectable (skipped by hit-testing). */
|
|
1444
|
+
locked: field13.boolean().default(false),
|
|
1445
|
+
/** When true, the layer is not rendered and is skipped by hit-testing. */
|
|
1446
|
+
hidden: field13.boolean().default(false)
|
|
1447
|
+
}
|
|
1448
|
+
);
|
|
1449
|
+
|
|
1450
|
+
// src/components/Opacity.ts
|
|
1451
|
+
import { defineCanvasComponent as defineCanvasComponent13 } from "@woven-ecs/canvas-store";
|
|
1452
|
+
import { field as field14 } from "@woven-ecs/core";
|
|
1453
|
+
var Opacity = defineCanvasComponent13(
|
|
1371
1454
|
{ name: "opacity" },
|
|
1372
1455
|
{
|
|
1373
|
-
value:
|
|
1456
|
+
value: field14.uint8().default(255)
|
|
1374
1457
|
}
|
|
1375
1458
|
);
|
|
1376
1459
|
|
|
1377
1460
|
// src/components/Pointer.ts
|
|
1378
1461
|
import { CanvasComponentDef as CanvasComponentDef5 } from "@woven-ecs/canvas-store";
|
|
1379
|
-
import { field as
|
|
1462
|
+
import { field as field15 } from "@woven-ecs/core";
|
|
1380
1463
|
var PointerButton = {
|
|
1381
1464
|
None: "none",
|
|
1382
1465
|
Left: "left",
|
|
@@ -1393,30 +1476,30 @@ var PointerType = {
|
|
|
1393
1476
|
var SAMPLE_COUNT = 6;
|
|
1394
1477
|
var PointerSchema = {
|
|
1395
1478
|
/** Unique pointer ID (from PointerEvent.pointerId) */
|
|
1396
|
-
pointerId:
|
|
1479
|
+
pointerId: field15.uint16().default(0),
|
|
1397
1480
|
/** Current position relative to the editor element [x, y] */
|
|
1398
|
-
position:
|
|
1481
|
+
position: field15.tuple(field15.float32(), 2).default([0, 0]),
|
|
1399
1482
|
/** Position where the pointer went down [x, y] */
|
|
1400
|
-
downPosition:
|
|
1483
|
+
downPosition: field15.tuple(field15.float32(), 2).default([0, 0]),
|
|
1401
1484
|
/** Frame number when the pointer went down (for click detection) */
|
|
1402
|
-
downFrame:
|
|
1485
|
+
downFrame: field15.uint32().default(0),
|
|
1403
1486
|
/** Which button is pressed */
|
|
1404
|
-
button:
|
|
1487
|
+
button: field15.enum(PointerButton).default(PointerButton.None),
|
|
1405
1488
|
/** Type of pointer device */
|
|
1406
|
-
pointerType:
|
|
1489
|
+
pointerType: field15.enum(PointerType).default(PointerType.Mouse),
|
|
1407
1490
|
/** Pressure from 0 to 1 (for pen/touch) */
|
|
1408
|
-
pressure:
|
|
1491
|
+
pressure: field15.float32().default(0),
|
|
1409
1492
|
/** Whether the pointer event target was not the editor element */
|
|
1410
|
-
obscured:
|
|
1493
|
+
obscured: field15.boolean().default(false),
|
|
1411
1494
|
// Velocity tracking (ring buffer for position samples)
|
|
1412
1495
|
/** Ring buffer of previous positions [x0, y0, x1, y1, ...] @internal */
|
|
1413
|
-
_prevPositions:
|
|
1496
|
+
_prevPositions: field15.array(field15.float32(), SAMPLE_COUNT * 2),
|
|
1414
1497
|
/** Ring buffer of timestamps for each position sample @internal */
|
|
1415
|
-
_prevTimes:
|
|
1498
|
+
_prevTimes: field15.array(field15.float32(), SAMPLE_COUNT),
|
|
1416
1499
|
/** Total number of samples added (used for ring buffer indexing) @internal */
|
|
1417
|
-
_sampleCount:
|
|
1500
|
+
_sampleCount: field15.int32().default(0),
|
|
1418
1501
|
/** Computed velocity [vx, vy] in pixels per second @internal */
|
|
1419
|
-
_velocity:
|
|
1502
|
+
_velocity: field15.tuple(field15.float32(), 2).default([0, 0])
|
|
1420
1503
|
};
|
|
1421
1504
|
var PointerDef = class extends CanvasComponentDef5 {
|
|
1422
1505
|
constructor() {
|
|
@@ -1527,96 +1610,96 @@ function addPointerSample(pointer, position, time) {
|
|
|
1527
1610
|
}
|
|
1528
1611
|
|
|
1529
1612
|
// src/components/ScaleWithZoom.ts
|
|
1530
|
-
import { defineCanvasComponent as
|
|
1531
|
-
import { field as
|
|
1532
|
-
var ScaleWithZoom =
|
|
1613
|
+
import { defineCanvasComponent as defineCanvasComponent14 } from "@woven-ecs/canvas-store";
|
|
1614
|
+
import { field as field16 } from "@woven-ecs/core";
|
|
1615
|
+
var ScaleWithZoom = defineCanvasComponent14(
|
|
1533
1616
|
{ name: "scaleWithZoom" },
|
|
1534
1617
|
{
|
|
1535
1618
|
/** Pivot point for scaling as [x, y] (0-1, default 0.5,0.5 = center) */
|
|
1536
|
-
anchor:
|
|
1619
|
+
anchor: field16.tuple(field16.float64(), 2).default([0.5, 0.5]),
|
|
1537
1620
|
/** Initial position as [left, top] at zoom=1 */
|
|
1538
|
-
startPosition:
|
|
1621
|
+
startPosition: field16.tuple(field16.float64(), 2).default([0, 0]),
|
|
1539
1622
|
/** Initial size as [width, height] at zoom=1 */
|
|
1540
|
-
startSize:
|
|
1623
|
+
startSize: field16.tuple(field16.float64(), 2).default([0, 0]),
|
|
1541
1624
|
/** Scale multiplier per dimension: [x, y] (0 = no zoom effect, 1 = full zoom effect, 0.5 = half effect) */
|
|
1542
|
-
scaleMultiplier:
|
|
1625
|
+
scaleMultiplier: field16.tuple(field16.float64(), 2).default([1, 1])
|
|
1543
1626
|
}
|
|
1544
1627
|
);
|
|
1545
1628
|
|
|
1546
1629
|
// src/components/Selected.ts
|
|
1547
|
-
import { defineCanvasComponent as
|
|
1548
|
-
var Selected =
|
|
1630
|
+
import { defineCanvasComponent as defineCanvasComponent15 } from "@woven-ecs/canvas-store";
|
|
1631
|
+
var Selected = defineCanvasComponent15({ name: "selected" }, {});
|
|
1549
1632
|
|
|
1550
1633
|
// src/components/SelectionBox.ts
|
|
1551
|
-
import { defineCanvasComponent as
|
|
1552
|
-
var SelectionBox =
|
|
1634
|
+
import { defineCanvasComponent as defineCanvasComponent16 } from "@woven-ecs/canvas-store";
|
|
1635
|
+
var SelectionBox = defineCanvasComponent16({ name: "selectionBox" }, {});
|
|
1553
1636
|
|
|
1554
1637
|
// src/components/Shape.ts
|
|
1555
|
-
import { defineCanvasComponent as
|
|
1556
|
-
import { field as
|
|
1638
|
+
import { defineCanvasComponent as defineCanvasComponent17 } from "@woven-ecs/canvas-store";
|
|
1639
|
+
import { field as field17 } from "@woven-ecs/core";
|
|
1557
1640
|
var StrokeKind = {
|
|
1558
1641
|
Solid: "solid",
|
|
1559
1642
|
Dashed: "dashed",
|
|
1560
1643
|
None: "none"
|
|
1561
1644
|
};
|
|
1562
|
-
var Shape =
|
|
1645
|
+
var Shape = defineCanvasComponent17(
|
|
1563
1646
|
{ name: "shape", sync: "document" },
|
|
1564
1647
|
{
|
|
1565
1648
|
/** The kind of shape to render (e.g. 'rectangle', 'ellipse', or custom shape key) */
|
|
1566
|
-
kind:
|
|
1649
|
+
kind: field17.string().default("rectangle"),
|
|
1567
1650
|
/** Stroke style */
|
|
1568
|
-
strokeKind:
|
|
1651
|
+
strokeKind: field17.enum(StrokeKind).default(StrokeKind.Solid),
|
|
1569
1652
|
/** Stroke width in pixels */
|
|
1570
|
-
strokeWidth:
|
|
1653
|
+
strokeWidth: field17.uint16().default(2),
|
|
1571
1654
|
/** Stroke color - red component (0-255) */
|
|
1572
|
-
strokeRed:
|
|
1655
|
+
strokeRed: field17.uint8().default(0),
|
|
1573
1656
|
/** Stroke color - green component (0-255) */
|
|
1574
|
-
strokeGreen:
|
|
1657
|
+
strokeGreen: field17.uint8().default(0),
|
|
1575
1658
|
/** Stroke color - blue component (0-255) */
|
|
1576
|
-
strokeBlue:
|
|
1659
|
+
strokeBlue: field17.uint8().default(0),
|
|
1577
1660
|
/** Stroke color - alpha component (0-255) */
|
|
1578
|
-
strokeAlpha:
|
|
1661
|
+
strokeAlpha: field17.uint8().default(255),
|
|
1579
1662
|
/** Fill color - red component (0-255) */
|
|
1580
|
-
fillRed:
|
|
1663
|
+
fillRed: field17.uint8().default(255),
|
|
1581
1664
|
/** Fill color - green component (0-255) */
|
|
1582
|
-
fillGreen:
|
|
1665
|
+
fillGreen: field17.uint8().default(255),
|
|
1583
1666
|
/** Fill color - blue component (0-255) */
|
|
1584
|
-
fillBlue:
|
|
1667
|
+
fillBlue: field17.uint8().default(255),
|
|
1585
1668
|
/** Fill color - alpha component (0-255) */
|
|
1586
|
-
fillAlpha:
|
|
1669
|
+
fillAlpha: field17.uint8().default(0)
|
|
1587
1670
|
}
|
|
1588
1671
|
);
|
|
1589
1672
|
|
|
1590
1673
|
// src/components/Text.ts
|
|
1591
|
-
import { defineCanvasComponent as
|
|
1592
|
-
import { field as
|
|
1593
|
-
var Text =
|
|
1674
|
+
import { defineCanvasComponent as defineCanvasComponent18 } from "@woven-ecs/canvas-store";
|
|
1675
|
+
import { field as field18 } from "@woven-ecs/core";
|
|
1676
|
+
var Text = defineCanvasComponent18(
|
|
1594
1677
|
{ name: "text", sync: "document" },
|
|
1595
1678
|
{
|
|
1596
1679
|
/** HTML content (supports rich text formatting) */
|
|
1597
|
-
content:
|
|
1680
|
+
content: field18.string().max(1e4).default(""),
|
|
1598
1681
|
/** Font size in pixels */
|
|
1599
|
-
fontSizePx:
|
|
1682
|
+
fontSizePx: field18.float64().default(24),
|
|
1600
1683
|
/** Font family name */
|
|
1601
|
-
fontFamily:
|
|
1684
|
+
fontFamily: field18.string().max(64).default(""),
|
|
1602
1685
|
/** Line height multiplier */
|
|
1603
|
-
lineHeight:
|
|
1686
|
+
lineHeight: field18.float64().default(1.2),
|
|
1604
1687
|
/** Letter spacing in em units */
|
|
1605
|
-
letterSpacingEm:
|
|
1688
|
+
letterSpacingEm: field18.float64().default(0),
|
|
1606
1689
|
/** Whether width is constrained (text wraps) */
|
|
1607
|
-
constrainWidth:
|
|
1690
|
+
constrainWidth: field18.boolean().default(true),
|
|
1608
1691
|
/** Default text alignment for new paragraphs */
|
|
1609
|
-
defaultAlignment:
|
|
1692
|
+
defaultAlignment: field18.enum(TextAlignment).default(TextAlignment.Left)
|
|
1610
1693
|
}
|
|
1611
1694
|
);
|
|
1612
1695
|
|
|
1613
1696
|
// src/components/TransformBox.ts
|
|
1614
|
-
import { defineCanvasComponent as
|
|
1615
|
-
var TransformBox =
|
|
1697
|
+
import { defineCanvasComponent as defineCanvasComponent19 } from "@woven-ecs/canvas-store";
|
|
1698
|
+
var TransformBox = defineCanvasComponent19({ name: "transformBox" }, {});
|
|
1616
1699
|
|
|
1617
1700
|
// src/components/TransformHandle.ts
|
|
1618
|
-
import { defineCanvasComponent as
|
|
1619
|
-
import { field as
|
|
1701
|
+
import { defineCanvasComponent as defineCanvasComponent20 } from "@woven-ecs/canvas-store";
|
|
1702
|
+
import { field as field19 } from "@woven-ecs/core";
|
|
1620
1703
|
|
|
1621
1704
|
// src/cursors.ts
|
|
1622
1705
|
var CursorKind = /* @__PURE__ */ ((CursorKind2) => {
|
|
@@ -1717,39 +1800,39 @@ var CURSORS = {
|
|
|
1717
1800
|
};
|
|
1718
1801
|
|
|
1719
1802
|
// src/components/TransformHandle.ts
|
|
1720
|
-
var TransformHandle =
|
|
1803
|
+
var TransformHandle = defineCanvasComponent20(
|
|
1721
1804
|
{ name: "transformHandle" },
|
|
1722
1805
|
{
|
|
1723
|
-
kind:
|
|
1724
|
-
vectorX:
|
|
1725
|
-
vectorY:
|
|
1726
|
-
transformBox:
|
|
1727
|
-
cursorKind:
|
|
1806
|
+
kind: field19.string().max(16).default(TransformHandleKind.Scale),
|
|
1807
|
+
vectorX: field19.int8().default(0),
|
|
1808
|
+
vectorY: field19.int8().default(0),
|
|
1809
|
+
transformBox: field19.ref(),
|
|
1810
|
+
cursorKind: field19.string().max(16).default("drag" /* Drag */)
|
|
1728
1811
|
}
|
|
1729
1812
|
);
|
|
1730
1813
|
|
|
1731
1814
|
// src/components/User.ts
|
|
1732
|
-
import { defineCanvasComponent as
|
|
1733
|
-
import { field as
|
|
1734
|
-
var User =
|
|
1815
|
+
import { defineCanvasComponent as defineCanvasComponent21 } from "@woven-ecs/canvas-store";
|
|
1816
|
+
import { field as field20 } from "@woven-ecs/core";
|
|
1817
|
+
var User = defineCanvasComponent21(
|
|
1735
1818
|
{ name: "user", sync: "ephemeral" },
|
|
1736
1819
|
{
|
|
1737
|
-
userId:
|
|
1738
|
-
sessionId:
|
|
1739
|
-
color:
|
|
1740
|
-
name:
|
|
1741
|
-
avatar:
|
|
1742
|
-
position:
|
|
1820
|
+
userId: field20.string().max(36),
|
|
1821
|
+
sessionId: field20.string().max(36),
|
|
1822
|
+
color: field20.string().max(7),
|
|
1823
|
+
name: field20.string().max(100),
|
|
1824
|
+
avatar: field20.string().max(500),
|
|
1825
|
+
position: field20.tuple(field20.float32(), 2).default([0, 0])
|
|
1743
1826
|
}
|
|
1744
1827
|
);
|
|
1745
1828
|
|
|
1746
1829
|
// src/components/VerticalAlign.ts
|
|
1747
|
-
import { defineCanvasComponent as
|
|
1748
|
-
import { field as
|
|
1749
|
-
var VerticalAlign =
|
|
1830
|
+
import { defineCanvasComponent as defineCanvasComponent22 } from "@woven-ecs/canvas-store";
|
|
1831
|
+
import { field as field21 } from "@woven-ecs/core";
|
|
1832
|
+
var VerticalAlign = defineCanvasComponent22(
|
|
1750
1833
|
{ name: "verticalAlign", sync: "document" },
|
|
1751
1834
|
{
|
|
1752
|
-
value:
|
|
1835
|
+
value: field21.enum(VerticalAlignment).default(VerticalAlignment.Top)
|
|
1753
1836
|
}
|
|
1754
1837
|
);
|
|
1755
1838
|
|
|
@@ -1788,20 +1871,20 @@ __export(singletons_exports, {
|
|
|
1788
1871
|
|
|
1789
1872
|
// src/singletons/Camera.ts
|
|
1790
1873
|
import { CanvasSingletonDef as CanvasSingletonDef2 } from "@woven-ecs/canvas-store";
|
|
1791
|
-
import { field as
|
|
1874
|
+
import { field as field23 } from "@woven-ecs/core";
|
|
1792
1875
|
|
|
1793
1876
|
// src/singletons/Screen.ts
|
|
1794
1877
|
import { CanvasSingletonDef } from "@woven-ecs/canvas-store";
|
|
1795
|
-
import { field as
|
|
1878
|
+
import { field as field22 } from "@woven-ecs/core";
|
|
1796
1879
|
var ScreenSchema = {
|
|
1797
1880
|
/** Width of the editor element in pixels */
|
|
1798
|
-
width:
|
|
1881
|
+
width: field22.float64().default(0),
|
|
1799
1882
|
/** Height of the editor element in pixels */
|
|
1800
|
-
height:
|
|
1883
|
+
height: field22.float64().default(0),
|
|
1801
1884
|
/** Left offset of the editor element relative to the viewport */
|
|
1802
|
-
left:
|
|
1885
|
+
left: field22.float64().default(0),
|
|
1803
1886
|
/** Top offset of the editor element relative to the viewport */
|
|
1804
|
-
top:
|
|
1887
|
+
top: field22.float64().default(0)
|
|
1805
1888
|
};
|
|
1806
1889
|
var ScreenDef = class extends CanvasSingletonDef {
|
|
1807
1890
|
constructor() {
|
|
@@ -1828,15 +1911,15 @@ var Screen = new ScreenDef();
|
|
|
1828
1911
|
// src/singletons/Camera.ts
|
|
1829
1912
|
var CameraSchema = {
|
|
1830
1913
|
/** Top position of the camera in world coordinates */
|
|
1831
|
-
top:
|
|
1914
|
+
top: field23.float64().default(0),
|
|
1832
1915
|
/** Left position of the camera in world coordinates */
|
|
1833
|
-
left:
|
|
1916
|
+
left: field23.float64().default(0),
|
|
1834
1917
|
/** Zoom level (1 = 100%, 2 = 200%, 0.5 = 50%) */
|
|
1835
|
-
zoom:
|
|
1918
|
+
zoom: field23.float64().default(1),
|
|
1836
1919
|
/** Whether the camera viewport intersects any blocks */
|
|
1837
|
-
canSeeBlocks:
|
|
1920
|
+
canSeeBlocks: field23.boolean().default(true),
|
|
1838
1921
|
/** Reference to a block that the camera can currently see (for optimization) */
|
|
1839
|
-
lastSeenBlock:
|
|
1922
|
+
lastSeenBlock: field23.ref()
|
|
1840
1923
|
};
|
|
1841
1924
|
var CameraDef = class extends CanvasSingletonDef2 {
|
|
1842
1925
|
constructor() {
|
|
@@ -1912,22 +1995,22 @@ var Camera = new CameraDef();
|
|
|
1912
1995
|
|
|
1913
1996
|
// src/singletons/Controls.ts
|
|
1914
1997
|
import { CanvasSingletonDef as CanvasSingletonDef3 } from "@woven-ecs/canvas-store";
|
|
1915
|
-
import { field as
|
|
1998
|
+
import { field as field24 } from "@woven-ecs/core";
|
|
1916
1999
|
var ControlsSchema = {
|
|
1917
2000
|
/** Tool activated by left mouse button */
|
|
1918
|
-
leftMouseTool:
|
|
2001
|
+
leftMouseTool: field24.string().max(32).default("select"),
|
|
1919
2002
|
/** Tool activated by middle mouse button */
|
|
1920
|
-
middleMouseTool:
|
|
2003
|
+
middleMouseTool: field24.string().max(32).default("hand"),
|
|
1921
2004
|
/** Tool activated by right mouse button */
|
|
1922
|
-
rightMouseTool:
|
|
2005
|
+
rightMouseTool: field24.string().max(32).default("hand"),
|
|
1923
2006
|
/** Tool activated by mouse wheel */
|
|
1924
|
-
wheelTool:
|
|
2007
|
+
wheelTool: field24.string().max(32).default("scroll"),
|
|
1925
2008
|
/** Tool activated by mouse wheel with modifier key held */
|
|
1926
|
-
modWheelTool:
|
|
2009
|
+
modWheelTool: field24.string().max(32).default("zoom"),
|
|
1927
2010
|
/** JSON snapshot of block to place on next click (empty string = no placement active) */
|
|
1928
|
-
heldSnapshot:
|
|
2011
|
+
heldSnapshot: field24.string().max(65536).default(""),
|
|
1929
2012
|
/** User-facing tool name for UI highlighting (may differ from leftMouseTool during draw/drag-out) */
|
|
1930
|
-
activeToolName:
|
|
2013
|
+
activeToolName: field24.string().max(32).default("select")
|
|
1931
2014
|
};
|
|
1932
2015
|
var ControlsDef = class extends CanvasSingletonDef3 {
|
|
1933
2016
|
constructor() {
|
|
@@ -1969,16 +2052,16 @@ var Controls = new ControlsDef();
|
|
|
1969
2052
|
|
|
1970
2053
|
// src/singletons/Cursor.ts
|
|
1971
2054
|
import { CanvasSingletonDef as CanvasSingletonDef4 } from "@woven-ecs/canvas-store";
|
|
1972
|
-
import { field as
|
|
2055
|
+
import { field as field25 } from "@woven-ecs/core";
|
|
1973
2056
|
var CursorSchema = {
|
|
1974
2057
|
/** Base cursor kind (from current tool) */
|
|
1975
|
-
cursorKind:
|
|
2058
|
+
cursorKind: field25.string().max(64).default("select"),
|
|
1976
2059
|
/** Base cursor rotation in radians */
|
|
1977
|
-
rotation:
|
|
2060
|
+
rotation: field25.float64().default(0),
|
|
1978
2061
|
/** Context-specific cursor kind (overrides cursorKind when set, e.g., during drag/hover) */
|
|
1979
|
-
contextCursorKind:
|
|
2062
|
+
contextCursorKind: field25.string().max(64).default(""),
|
|
1980
2063
|
/** Context cursor rotation in radians */
|
|
1981
|
-
contextRotation:
|
|
2064
|
+
contextRotation: field25.float64().default(0)
|
|
1982
2065
|
};
|
|
1983
2066
|
var CursorDef2 = class extends CanvasSingletonDef4 {
|
|
1984
2067
|
constructor() {
|
|
@@ -2025,7 +2108,7 @@ var CursorDef2 = class extends CanvasSingletonDef4 {
|
|
|
2025
2108
|
var Cursor = new CursorDef2();
|
|
2026
2109
|
|
|
2027
2110
|
// src/singletons/FrameContainmentState.ts
|
|
2028
|
-
import { field as
|
|
2111
|
+
import { field as field26 } from "@woven-ecs/core";
|
|
2029
2112
|
|
|
2030
2113
|
// src/EditorStateDef.ts
|
|
2031
2114
|
import { CanvasSingletonDef as CanvasSingletonDef5 } from "@woven-ecs/canvas-store";
|
|
@@ -2133,27 +2216,27 @@ function defineEditorState(name, schema) {
|
|
|
2133
2216
|
// src/singletons/FrameContainmentState.ts
|
|
2134
2217
|
var FrameContainmentState = defineEditorState("frameContainmentState", {
|
|
2135
2218
|
/** Current state machine state */
|
|
2136
|
-
state:
|
|
2219
|
+
state: field26.string().max(16).default(FrameContainmentStateEnum.Idle),
|
|
2137
2220
|
/** EntityId of the frame currently highlighted as a drop target, or null */
|
|
2138
|
-
highlightedFrame:
|
|
2221
|
+
highlightedFrame: field26.ref()
|
|
2139
2222
|
});
|
|
2140
2223
|
|
|
2141
2224
|
// src/singletons/Grid.ts
|
|
2142
2225
|
import { CanvasSingletonDef as CanvasSingletonDef6 } from "@woven-ecs/canvas-store";
|
|
2143
|
-
import { field as
|
|
2226
|
+
import { field as field27 } from "@woven-ecs/core";
|
|
2144
2227
|
var GridSchema = {
|
|
2145
2228
|
/** Whether grid snapping is enabled */
|
|
2146
|
-
enabled:
|
|
2229
|
+
enabled: field27.boolean().default(false),
|
|
2147
2230
|
/** Whether resized/rotated objects must stay aligned to the grid */
|
|
2148
|
-
strict:
|
|
2231
|
+
strict: field27.boolean().default(false),
|
|
2149
2232
|
/** Width of each grid column in world units */
|
|
2150
|
-
colWidth:
|
|
2233
|
+
colWidth: field27.float64().default(20),
|
|
2151
2234
|
/** Height of each grid row in world units */
|
|
2152
|
-
rowHeight:
|
|
2235
|
+
rowHeight: field27.float64().default(20),
|
|
2153
2236
|
/** Angular snap increment in radians when grid is enabled */
|
|
2154
|
-
snapAngleRad:
|
|
2237
|
+
snapAngleRad: field27.float64().default(Math.PI / 36),
|
|
2155
2238
|
/** Angular snap increment in radians when shift key is held */
|
|
2156
|
-
shiftSnapAngleRad:
|
|
2239
|
+
shiftSnapAngleRad: field27.float64().default(Math.PI / 12)
|
|
2157
2240
|
};
|
|
2158
2241
|
var GridDef = class extends CanvasSingletonDef6 {
|
|
2159
2242
|
constructor() {
|
|
@@ -2216,14 +2299,14 @@ var Grid = new GridDef();
|
|
|
2216
2299
|
|
|
2217
2300
|
// src/singletons/Intersect.ts
|
|
2218
2301
|
import { CanvasSingletonDef as CanvasSingletonDef7 } from "@woven-ecs/canvas-store";
|
|
2219
|
-
import { field as
|
|
2302
|
+
import { field as field28 } from "@woven-ecs/core";
|
|
2220
2303
|
var IntersectSchema = {
|
|
2221
2304
|
// Store up to 5 intersected entity IDs
|
|
2222
|
-
entity1:
|
|
2223
|
-
entity2:
|
|
2224
|
-
entity3:
|
|
2225
|
-
entity4:
|
|
2226
|
-
entity5:
|
|
2305
|
+
entity1: field28.ref(),
|
|
2306
|
+
entity2: field28.ref(),
|
|
2307
|
+
entity3: field28.ref(),
|
|
2308
|
+
entity4: field28.ref(),
|
|
2309
|
+
entity5: field28.ref()
|
|
2227
2310
|
};
|
|
2228
2311
|
var IntersectDef = class extends CanvasSingletonDef7 {
|
|
2229
2312
|
constructor() {
|
|
@@ -2275,30 +2358,30 @@ var Intersect = new IntersectDef();
|
|
|
2275
2358
|
|
|
2276
2359
|
// src/singletons/Keyboard.ts
|
|
2277
2360
|
import { CanvasSingletonDef as CanvasSingletonDef8 } from "@woven-ecs/canvas-store";
|
|
2278
|
-
import { field as
|
|
2361
|
+
import { field as field29 } from "@woven-ecs/core";
|
|
2279
2362
|
var KEY_BUFFER_SIZE = 32;
|
|
2280
2363
|
var KeyboardSchema = {
|
|
2281
2364
|
/**
|
|
2282
2365
|
* Buffer where each bit represents whether a key is currently pressed.
|
|
2283
2366
|
* Uses field.buffer for zero-allocation subarray views.
|
|
2284
2367
|
*/
|
|
2285
|
-
keysDown:
|
|
2368
|
+
keysDown: field29.buffer(field29.uint8()).size(KEY_BUFFER_SIZE),
|
|
2286
2369
|
/**
|
|
2287
2370
|
* Buffer for key-down triggers (true for exactly 1 frame when key is pressed).
|
|
2288
2371
|
* Uses field.buffer for zero-allocation subarray views.
|
|
2289
2372
|
*/
|
|
2290
|
-
keysDownTrigger:
|
|
2373
|
+
keysDownTrigger: field29.buffer(field29.uint8()).size(KEY_BUFFER_SIZE),
|
|
2291
2374
|
/**
|
|
2292
2375
|
* Buffer for key-up triggers (true for exactly 1 frame when key is released).
|
|
2293
2376
|
* Uses field.buffer for zero-allocation subarray views.
|
|
2294
2377
|
*/
|
|
2295
|
-
keysUpTrigger:
|
|
2378
|
+
keysUpTrigger: field29.buffer(field29.uint8()).size(KEY_BUFFER_SIZE),
|
|
2296
2379
|
/** Common modifier - Shift key is down */
|
|
2297
|
-
shiftDown:
|
|
2380
|
+
shiftDown: field29.boolean().default(false),
|
|
2298
2381
|
/** Common modifier - Alt/Option key is down */
|
|
2299
|
-
altDown:
|
|
2382
|
+
altDown: field29.boolean().default(false),
|
|
2300
2383
|
/** Common modifier - Ctrl (Windows/Linux) or Cmd (Mac) is down */
|
|
2301
|
-
modDown:
|
|
2384
|
+
modDown: field29.boolean().default(false)
|
|
2302
2385
|
};
|
|
2303
2386
|
function getBit(buffer, bitIndex) {
|
|
2304
2387
|
if (bitIndex < 0 || bitIndex >= buffer.length * 8) return false;
|
|
@@ -2581,24 +2664,24 @@ var Key = {
|
|
|
2581
2664
|
|
|
2582
2665
|
// src/singletons/Mouse.ts
|
|
2583
2666
|
import { CanvasSingletonDef as CanvasSingletonDef9 } from "@woven-ecs/canvas-store";
|
|
2584
|
-
import { field as
|
|
2667
|
+
import { field as field30 } from "@woven-ecs/core";
|
|
2585
2668
|
var MouseSchema = {
|
|
2586
2669
|
/** Current mouse position relative to the editor element [x, y] */
|
|
2587
|
-
position:
|
|
2670
|
+
position: field30.tuple(field30.float32(), 2).default([0, 0]),
|
|
2588
2671
|
/** Horizontal wheel delta (positive = scroll right) */
|
|
2589
|
-
wheelDeltaX:
|
|
2672
|
+
wheelDeltaX: field30.float32().default(0),
|
|
2590
2673
|
/** Vertical wheel delta (positive = scroll down), normalized across browsers */
|
|
2591
|
-
wheelDeltaY:
|
|
2674
|
+
wheelDeltaY: field30.float32().default(0),
|
|
2592
2675
|
/** True for 1 frame when mouse moves */
|
|
2593
|
-
moveTrigger:
|
|
2676
|
+
moveTrigger: field30.boolean().default(false),
|
|
2594
2677
|
/** True for 1 frame when wheel is scrolled */
|
|
2595
|
-
wheelTrigger:
|
|
2678
|
+
wheelTrigger: field30.boolean().default(false),
|
|
2596
2679
|
/** True for 1 frame when mouse enters the editor element */
|
|
2597
|
-
enterTrigger:
|
|
2680
|
+
enterTrigger: field30.boolean().default(false),
|
|
2598
2681
|
/** True for 1 frame when mouse leaves the editor element */
|
|
2599
|
-
leaveTrigger:
|
|
2682
|
+
leaveTrigger: field30.boolean().default(false),
|
|
2600
2683
|
/** Whether the mouse is over a UI element (not the canvas) */
|
|
2601
|
-
obscured:
|
|
2684
|
+
obscured: field30.boolean().default(false)
|
|
2602
2685
|
};
|
|
2603
2686
|
var MouseDef = class extends CanvasSingletonDef9 {
|
|
2604
2687
|
constructor() {
|
|
@@ -2639,11 +2722,11 @@ var Mouse = new MouseDef();
|
|
|
2639
2722
|
|
|
2640
2723
|
// src/singletons/RankBounds.ts
|
|
2641
2724
|
import { CanvasSingletonDef as CanvasSingletonDef10 } from "@woven-ecs/canvas-store";
|
|
2642
|
-
import { field as
|
|
2725
|
+
import { field as field31 } from "@woven-ecs/core";
|
|
2643
2726
|
import { generateJitteredKeyBetween } from "fractional-indexing-jittered";
|
|
2644
2727
|
var RankBoundsSchema = {
|
|
2645
|
-
minRank:
|
|
2646
|
-
maxRank:
|
|
2728
|
+
minRank: field31.string().max(36).default(""),
|
|
2729
|
+
maxRank: field31.string().max(36).default("")
|
|
2647
2730
|
};
|
|
2648
2731
|
var RankBoundsDef = class extends CanvasSingletonDef10 {
|
|
2649
2732
|
constructor() {
|
|
@@ -2702,64 +2785,64 @@ var RankBounds = new RankBoundsDef();
|
|
|
2702
2785
|
|
|
2703
2786
|
// src/singletons/ScaleWithZoomState.ts
|
|
2704
2787
|
import { defineCanvasSingleton } from "@woven-ecs/canvas-store";
|
|
2705
|
-
import { field as
|
|
2788
|
+
import { field as field32 } from "@woven-ecs/core";
|
|
2706
2789
|
var ScaleWithZoomState = defineCanvasSingleton(
|
|
2707
2790
|
{ name: "scaleWithZoomState" },
|
|
2708
2791
|
{
|
|
2709
2792
|
/** Last processed zoom level */
|
|
2710
|
-
lastZoom:
|
|
2793
|
+
lastZoom: field32.float64().default(1)
|
|
2711
2794
|
}
|
|
2712
2795
|
);
|
|
2713
2796
|
|
|
2714
2797
|
// src/singletons/ScrollEdgesStateSingleton.ts
|
|
2715
|
-
import { field as
|
|
2798
|
+
import { field as field33 } from "@woven-ecs/core";
|
|
2716
2799
|
var ScrollEdgesStateSingleton = defineEditorState("scrollEdgesState", {
|
|
2717
2800
|
/** Current state of the scroll edges state machine */
|
|
2718
|
-
state:
|
|
2801
|
+
state: field33.enum(ScrollEdgesState).default(ScrollEdgesState.Idle),
|
|
2719
2802
|
/** Timestamp when pointer first entered the edge zone */
|
|
2720
|
-
edgeEnterStartTime:
|
|
2803
|
+
edgeEnterStartTime: field33.float64().default(0)
|
|
2721
2804
|
});
|
|
2722
2805
|
|
|
2723
2806
|
// src/singletons/SelectionStateSingleton.ts
|
|
2724
|
-
import { field as
|
|
2807
|
+
import { field as field34 } from "@woven-ecs/core";
|
|
2725
2808
|
var SelectionStateSingleton = defineEditorState("selectionState", {
|
|
2726
|
-
state:
|
|
2727
|
-
dragStart:
|
|
2728
|
-
pointingStartClient:
|
|
2729
|
-
pointingStartWorld:
|
|
2730
|
-
draggedEntityStart:
|
|
2731
|
-
draggedEntity:
|
|
2732
|
-
cloneGeneratorSeed:
|
|
2733
|
-
isCloning:
|
|
2809
|
+
state: field34.enum(SelectionState).default(SelectionState.Idle),
|
|
2810
|
+
dragStart: field34.tuple(field34.float64(), 2).default([0, 0]),
|
|
2811
|
+
pointingStartClient: field34.tuple(field34.float64(), 2).default([0, 0]),
|
|
2812
|
+
pointingStartWorld: field34.tuple(field34.float64(), 2).default([0, 0]),
|
|
2813
|
+
draggedEntityStart: field34.tuple(field34.float64(), 2).default([0, 0]),
|
|
2814
|
+
draggedEntity: field34.ref(),
|
|
2815
|
+
cloneGeneratorSeed: field34.string().max(36).default(""),
|
|
2816
|
+
isCloning: field34.boolean()
|
|
2734
2817
|
});
|
|
2735
2818
|
|
|
2736
2819
|
// src/singletons/Tick.ts
|
|
2737
2820
|
import { defineCanvasSingleton as defineCanvasSingleton2 } from "@woven-ecs/canvas-store";
|
|
2738
|
-
import { field as
|
|
2821
|
+
import { field as field35 } from "@woven-ecs/core";
|
|
2739
2822
|
var Tick = defineCanvasSingleton2(
|
|
2740
2823
|
{ name: "tick" },
|
|
2741
2824
|
{
|
|
2742
2825
|
/** Current tick number (increments each tick) */
|
|
2743
|
-
number:
|
|
2826
|
+
number: field35.uint32().default(0),
|
|
2744
2827
|
/** Time since last tick in seconds */
|
|
2745
|
-
delta:
|
|
2828
|
+
delta: field35.float64().default(0),
|
|
2746
2829
|
/** Timestamp of current tick in milliseconds (from performance.now()) */
|
|
2747
|
-
time:
|
|
2830
|
+
time: field35.float64().default(0),
|
|
2748
2831
|
/** Timestamp of previous tick in milliseconds (0 if first tick) */
|
|
2749
|
-
lastTime:
|
|
2832
|
+
lastTime: field35.float64().default(0)
|
|
2750
2833
|
}
|
|
2751
2834
|
);
|
|
2752
2835
|
|
|
2753
2836
|
// src/singletons/TransformBoxStateSingleton.ts
|
|
2754
|
-
import { field as
|
|
2837
|
+
import { field as field36 } from "@woven-ecs/core";
|
|
2755
2838
|
var TransformBoxStateSingleton = defineEditorState("transformBoxState", {
|
|
2756
|
-
state:
|
|
2757
|
-
transformBoxId:
|
|
2839
|
+
state: field36.string().max(32).default(TransformBoxState.None),
|
|
2840
|
+
transformBoxId: field36.ref()
|
|
2758
2841
|
});
|
|
2759
2842
|
|
|
2760
2843
|
// src/systems/capture/captureFrameContainmentSystem.ts
|
|
2761
|
-
import { Synced as
|
|
2762
|
-
import { defineQuery as defineQuery7, hasComponent as
|
|
2844
|
+
import { Synced as Synced3 } from "@woven-ecs/canvas-store";
|
|
2845
|
+
import { defineQuery as defineQuery7, hasComponent as hasComponent11 } from "@woven-ecs/core";
|
|
2763
2846
|
import { assign, setup } from "xstate";
|
|
2764
2847
|
|
|
2765
2848
|
// src/EditorSystem.ts
|
|
@@ -2848,6 +2931,9 @@ function canBlockEdit(ctx, tag) {
|
|
|
2848
2931
|
function canBlockInteract(ctx, tag) {
|
|
2849
2932
|
return getBlockDef(ctx, tag).interactable;
|
|
2850
2933
|
}
|
|
2934
|
+
function canBlockSnap(ctx, tag) {
|
|
2935
|
+
return getBlockDef(ctx, tag).snappable;
|
|
2936
|
+
}
|
|
2851
2937
|
function getBlockResizeMode(ctx, entityId) {
|
|
2852
2938
|
const block = Block.read(ctx, entityId);
|
|
2853
2939
|
if (block.resizeMode !== ResizeMode.Default) {
|
|
@@ -2870,6 +2956,17 @@ function computeAabb(ctx, entityId, out) {
|
|
|
2870
2956
|
}
|
|
2871
2957
|
}
|
|
2872
2958
|
|
|
2959
|
+
// src/helpers/createBlock.ts
|
|
2960
|
+
import { Synced } from "@woven-ecs/canvas-store";
|
|
2961
|
+
import { addComponent as addComponent2, createEntity as createEntity2 } from "@woven-ecs/core";
|
|
2962
|
+
function createBlock(ctx, block) {
|
|
2963
|
+
const entityId = createEntity2(ctx);
|
|
2964
|
+
addComponent2(ctx, entityId, Synced, { id: crypto.randomUUID() });
|
|
2965
|
+
addComponent2(ctx, entityId, Block, { ...block, rank: block.rank ?? RankBounds.genNext(ctx) });
|
|
2966
|
+
PlaceBlockEvent.spawn(ctx, { entityId });
|
|
2967
|
+
return entityId;
|
|
2968
|
+
}
|
|
2969
|
+
|
|
2873
2970
|
// src/helpers/embed.ts
|
|
2874
2971
|
function detectEmbedProvider(url) {
|
|
2875
2972
|
try {
|
|
@@ -3083,6 +3180,9 @@ function compareRankChains(a, b) {
|
|
|
3083
3180
|
function compareBlockOrder(getBlock, a, b) {
|
|
3084
3181
|
const stratumDiff = STRATUM_ORDER[a.stratum] - STRATUM_ORDER[b.stratum];
|
|
3085
3182
|
if (stratumDiff !== 0) return stratumDiff;
|
|
3183
|
+
const aLayer = a.layerRank ?? "";
|
|
3184
|
+
const bLayer = b.layerRank ?? "";
|
|
3185
|
+
if (aLayer !== bLayer) return aLayer < bLayer ? -1 : 1;
|
|
3086
3186
|
const chainA = getRankChain(getBlock, a);
|
|
3087
3187
|
const chainB = getRankChain(getBlock, b);
|
|
3088
3188
|
return compareRankChains(chainA, chainB);
|
|
@@ -3127,12 +3227,30 @@ function isHeldByRemote(ctx, entityId) {
|
|
|
3127
3227
|
|
|
3128
3228
|
// src/helpers/intersect.ts
|
|
3129
3229
|
import { Aabb as Aabb3 } from "@woven-canvas/math";
|
|
3130
|
-
import { defineQuery as defineQuery3, hasComponent as
|
|
3230
|
+
import { defineQuery as defineQuery3, hasComponent as hasComponent7 } from "@woven-ecs/core";
|
|
3231
|
+
|
|
3232
|
+
// src/helpers/layerRank.ts
|
|
3233
|
+
import { hasComponent as hasComponent6 } from "@woven-ecs/core";
|
|
3234
|
+
function resolveLayerRank(ctx, entityId) {
|
|
3235
|
+
if (!hasComponent6(ctx, entityId, Block)) return "";
|
|
3236
|
+
const layerId = Block.read(ctx, entityId).layerId;
|
|
3237
|
+
if (layerId !== null && hasComponent6(ctx, layerId, Layer)) {
|
|
3238
|
+
return Layer.read(ctx, layerId).rank;
|
|
3239
|
+
}
|
|
3240
|
+
return "";
|
|
3241
|
+
}
|
|
3242
|
+
function isLayerInteractive(ctx, layerId) {
|
|
3243
|
+
if (layerId === null || !hasComponent6(ctx, layerId, Layer)) return true;
|
|
3244
|
+
const layer = Layer.read(ctx, layerId);
|
|
3245
|
+
return !layer.hidden && !layer.locked;
|
|
3246
|
+
}
|
|
3247
|
+
|
|
3248
|
+
// src/helpers/intersect.ts
|
|
3131
3249
|
var blocksWithAabb = defineQuery3((q) => q.with(Block, Aabb));
|
|
3132
3250
|
function isPointInsideAncestorFrames(ctx, entityId, point) {
|
|
3133
3251
|
let current = Block.read(ctx, entityId).parentId;
|
|
3134
|
-
while (current !== null &&
|
|
3135
|
-
if (
|
|
3252
|
+
while (current !== null && hasComponent7(ctx, current, Block)) {
|
|
3253
|
+
if (hasComponent7(ctx, current, Frame)) {
|
|
3136
3254
|
if (!Aabb.containsPoint(ctx, current, point)) {
|
|
3137
3255
|
return false;
|
|
3138
3256
|
}
|
|
@@ -3143,8 +3261,8 @@ function isPointInsideAncestorFrames(ctx, entityId, point) {
|
|
|
3143
3261
|
}
|
|
3144
3262
|
function isAabbInsideAncestorFrames(ctx, entityId, bounds) {
|
|
3145
3263
|
let current = Block.read(ctx, entityId).parentId;
|
|
3146
|
-
while (current !== null &&
|
|
3147
|
-
if (
|
|
3264
|
+
while (current !== null && hasComponent7(ctx, current, Block)) {
|
|
3265
|
+
if (hasComponent7(ctx, current, Frame)) {
|
|
3148
3266
|
const { value: frameAabb } = Aabb.read(ctx, current);
|
|
3149
3267
|
if (!Aabb3.intersects(bounds, frameAabb)) {
|
|
3150
3268
|
return false;
|
|
@@ -3160,10 +3278,11 @@ function intersectPoint(ctx, point, entityIds) {
|
|
|
3160
3278
|
for (const entityId of entities) {
|
|
3161
3279
|
const block = Block.read(ctx, entityId);
|
|
3162
3280
|
if (!canBlockInteract(ctx, block.tag)) continue;
|
|
3281
|
+
if (!isLayerInteractive(ctx, block.layerId)) continue;
|
|
3163
3282
|
if (!Aabb.containsPoint(ctx, entityId, point)) {
|
|
3164
3283
|
continue;
|
|
3165
3284
|
}
|
|
3166
|
-
if (
|
|
3285
|
+
if (hasComponent7(ctx, entityId, HitGeometry)) {
|
|
3167
3286
|
if (!HitGeometry.containsPointWorld(ctx, entityId, point)) {
|
|
3168
3287
|
continue;
|
|
3169
3288
|
}
|
|
@@ -3185,12 +3304,13 @@ function intersectAabb(ctx, bounds, entityIds) {
|
|
|
3185
3304
|
for (const entityId of entities) {
|
|
3186
3305
|
const block = Block.read(ctx, entityId);
|
|
3187
3306
|
if (!canBlockInteract(ctx, block.tag)) continue;
|
|
3307
|
+
if (!isLayerInteractive(ctx, block.layerId)) continue;
|
|
3188
3308
|
const { value: entityAabb } = Aabb.read(ctx, entityId);
|
|
3189
3309
|
if (!Aabb3.intersects(bounds, entityAabb)) {
|
|
3190
3310
|
continue;
|
|
3191
3311
|
}
|
|
3192
3312
|
if (!Aabb3.contains(bounds, entityAabb)) {
|
|
3193
|
-
if (
|
|
3313
|
+
if (hasComponent7(ctx, entityId, HitGeometry)) {
|
|
3194
3314
|
if (!HitGeometry.intersectsAabbWorld(ctx, entityId, bounds)) {
|
|
3195
3315
|
continue;
|
|
3196
3316
|
}
|
|
@@ -3209,12 +3329,13 @@ function intersectAabb(ctx, bounds, entityIds) {
|
|
|
3209
3329
|
}
|
|
3210
3330
|
function sortByRankDescending(ctx, entityIds) {
|
|
3211
3331
|
const getBlock = (id) => {
|
|
3212
|
-
if (!
|
|
3332
|
+
if (!hasComponent7(ctx, id, Block)) return null;
|
|
3213
3333
|
const block = Block.read(ctx, id);
|
|
3214
3334
|
return {
|
|
3215
3335
|
rank: block.rank,
|
|
3216
3336
|
stratum: getBlockDef(ctx, block.tag).stratum,
|
|
3217
|
-
parentId: block.parentId
|
|
3337
|
+
parentId: block.parentId,
|
|
3338
|
+
layerRank: resolveLayerRank(ctx, id)
|
|
3218
3339
|
};
|
|
3219
3340
|
};
|
|
3220
3341
|
const entries = entityIds.map((id) => ({
|
|
@@ -3230,13 +3351,15 @@ function getTopmostBlockAtPoint(ctx, point) {
|
|
|
3230
3351
|
}
|
|
3231
3352
|
|
|
3232
3353
|
// src/helpers/intersectCapsule.ts
|
|
3233
|
-
import { Aabb as AabbNs, Arc as Arc2, Capsule as Capsule2, Mat2 as Mat22 } from "@woven-canvas/math";
|
|
3234
|
-
import { hasComponent as
|
|
3354
|
+
import { Aabb as AabbNs, Arc as Arc2, Capsule as Capsule2, Mat2 as Mat22, Polygon as Polygon2 } from "@woven-canvas/math";
|
|
3355
|
+
import { hasComponent as hasComponent8 } from "@woven-ecs/core";
|
|
3235
3356
|
var _uvToWorldMatrix2 = [1, 0, 0, 1, 0, 0];
|
|
3357
|
+
var _worldPolygon2 = new Float32Array(MAX_HIT_POLYGON_POINTS * 2);
|
|
3358
|
+
var _polyPt2 = [0, 0];
|
|
3236
3359
|
function isCapsuleInsideAncestorFrames(ctx, entityId, capsule) {
|
|
3237
3360
|
let current = Block.read(ctx, entityId).parentId;
|
|
3238
|
-
while (current !== null &&
|
|
3239
|
-
if (
|
|
3361
|
+
while (current !== null && hasComponent8(ctx, current, Block)) {
|
|
3362
|
+
if (hasComponent8(ctx, current, Frame)) {
|
|
3240
3363
|
const { value: frameAabb } = Aabb.read(ctx, current);
|
|
3241
3364
|
if (!Capsule2.intersectsAabb(capsule, frameAabb)) {
|
|
3242
3365
|
return false;
|
|
@@ -3254,7 +3377,7 @@ function intersectCapsule(ctx, capsule, entityIds) {
|
|
|
3254
3377
|
if (!AabbNs.intersects(capsuleBounds, aabb.value)) {
|
|
3255
3378
|
continue;
|
|
3256
3379
|
}
|
|
3257
|
-
if (
|
|
3380
|
+
if (hasComponent8(ctx, entityId, HitGeometry)) {
|
|
3258
3381
|
if (!intersectsCapsuleHitGeometry(ctx, entityId, capsule)) {
|
|
3259
3382
|
continue;
|
|
3260
3383
|
}
|
|
@@ -3301,12 +3424,25 @@ function intersectsCapsuleHitGeometry(ctx, entityId, capsule) {
|
|
|
3301
3424
|
return true;
|
|
3302
3425
|
}
|
|
3303
3426
|
}
|
|
3427
|
+
const polygonPointCount = hitGeometry.polygonPointCount;
|
|
3428
|
+
if (polygonPointCount > 0) {
|
|
3429
|
+
for (let i = 0; i < polygonPointCount; i++) {
|
|
3430
|
+
_polyPt2[0] = hitGeometry.hitPolygon[i * 2];
|
|
3431
|
+
_polyPt2[1] = hitGeometry.hitPolygon[i * 2 + 1];
|
|
3432
|
+
Mat22.transformPoint(_uvToWorldMatrix2, _polyPt2);
|
|
3433
|
+
_worldPolygon2[i * 2] = _polyPt2[0];
|
|
3434
|
+
_worldPolygon2[i * 2 + 1] = _polyPt2[1];
|
|
3435
|
+
}
|
|
3436
|
+
if (Polygon2.intersectsCapsule(_worldPolygon2, polygonPointCount, capsule)) {
|
|
3437
|
+
return true;
|
|
3438
|
+
}
|
|
3439
|
+
}
|
|
3304
3440
|
return false;
|
|
3305
3441
|
}
|
|
3306
3442
|
|
|
3307
3443
|
// src/helpers/ref.ts
|
|
3308
|
-
import { Synced } from "@woven-ecs/canvas-store";
|
|
3309
|
-
import { hasComponent as
|
|
3444
|
+
import { Synced as Synced2 } from "@woven-ecs/canvas-store";
|
|
3445
|
+
import { hasComponent as hasComponent9 } from "@woven-ecs/core";
|
|
3310
3446
|
function convertRefsToUuids(ctx, schema, data) {
|
|
3311
3447
|
const result = { ...data };
|
|
3312
3448
|
for (const [fieldName, fieldBuilder] of Object.entries(schema)) {
|
|
@@ -3319,8 +3455,8 @@ function convertRefsToUuids(ctx, schema, data) {
|
|
|
3319
3455
|
}
|
|
3320
3456
|
function getEntityUuid(ctx, entityId) {
|
|
3321
3457
|
if (entityId == null) return null;
|
|
3322
|
-
if (!
|
|
3323
|
-
return
|
|
3458
|
+
if (!hasComponent9(ctx, entityId, Synced2)) return null;
|
|
3459
|
+
return Synced2.read(ctx, entityId).id;
|
|
3324
3460
|
}
|
|
3325
3461
|
function getRefFieldNames(schema) {
|
|
3326
3462
|
const refFields = [];
|
|
@@ -3345,29 +3481,29 @@ function resolveRefFields(ctx, entityId, componentDef, componentData, uuidToEnti
|
|
|
3345
3481
|
|
|
3346
3482
|
// src/helpers/select.ts
|
|
3347
3483
|
import {
|
|
3348
|
-
addComponent as
|
|
3484
|
+
addComponent as addComponent3,
|
|
3349
3485
|
defineQuery as defineQuery4,
|
|
3350
3486
|
getResources as getResources4,
|
|
3351
|
-
hasComponent as
|
|
3487
|
+
hasComponent as hasComponent10,
|
|
3352
3488
|
removeComponent
|
|
3353
3489
|
} from "@woven-ecs/core";
|
|
3354
3490
|
var selectedQuery = defineQuery4((q) => q.with(Selected));
|
|
3355
3491
|
var blockQuery = defineQuery4((q) => q.with(Block));
|
|
3356
3492
|
function selectBlock(ctx, entityId) {
|
|
3357
|
-
if (
|
|
3493
|
+
if (hasComponent10(ctx, entityId, Selected)) return;
|
|
3358
3494
|
if (isHeldByRemote(ctx, entityId)) return;
|
|
3359
|
-
if (
|
|
3495
|
+
if (hasComponent10(ctx, entityId, Block)) {
|
|
3360
3496
|
const block = Block.read(ctx, entityId);
|
|
3361
3497
|
if (!canBlockInteract(ctx, block.tag)) return;
|
|
3362
3498
|
}
|
|
3363
3499
|
const { sessionId } = getResources4(ctx);
|
|
3364
|
-
|
|
3365
|
-
if (!
|
|
3366
|
-
|
|
3500
|
+
addComponent3(ctx, entityId, Selected, {});
|
|
3501
|
+
if (!hasComponent10(ctx, entityId, Held)) {
|
|
3502
|
+
addComponent3(ctx, entityId, Held, { sessionId });
|
|
3367
3503
|
}
|
|
3368
3504
|
}
|
|
3369
3505
|
function deselectBlock(ctx, entityId) {
|
|
3370
|
-
if (!
|
|
3506
|
+
if (!hasComponent10(ctx, entityId, Selected)) return;
|
|
3371
3507
|
removeComponent(ctx, entityId, Selected);
|
|
3372
3508
|
removeComponent(ctx, entityId, Held);
|
|
3373
3509
|
}
|
|
@@ -3581,13 +3717,13 @@ function spawnAssignments(ctx, targetFrame) {
|
|
|
3581
3717
|
const draggedEntity = getDraggedEntity(ctx);
|
|
3582
3718
|
if (draggedEntity === null) return;
|
|
3583
3719
|
const assignments = [];
|
|
3584
|
-
if (
|
|
3720
|
+
if (hasComponent11(ctx, draggedEntity, TransformBox)) {
|
|
3585
3721
|
for (const blockId of selectedQuery2.current(ctx)) {
|
|
3586
3722
|
if (targetFrame !== null && blockId === targetFrame) continue;
|
|
3587
3723
|
if (targetFrame !== null && isAncestor(ctx, targetFrame, blockId)) continue;
|
|
3588
3724
|
assignments.push({ entityId: blockId, frameId: targetFrame });
|
|
3589
3725
|
}
|
|
3590
|
-
} else if (
|
|
3726
|
+
} else if (hasComponent11(ctx, draggedEntity, Synced3)) {
|
|
3591
3727
|
if (targetFrame !== null && draggedEntity === targetFrame) return;
|
|
3592
3728
|
if (targetFrame !== null && isAncestor(ctx, targetFrame, draggedEntity)) return;
|
|
3593
3729
|
assignments.push({ entityId: draggedEntity, frameId: targetFrame });
|
|
@@ -3712,7 +3848,7 @@ var hoverCursorSystem = defineEditorSystem({ phase: "capture" }, (ctx) => {
|
|
|
3712
3848
|
});
|
|
3713
3849
|
|
|
3714
3850
|
// src/systems/capture/keybindSystem.ts
|
|
3715
|
-
import { addComponent as
|
|
3851
|
+
import { addComponent as addComponent4, createEntity as createEntity3, getResources as getResources6 } from "@woven-ecs/core";
|
|
3716
3852
|
var keybindSystem = defineEditorSystem({ phase: "capture" }, (ctx) => {
|
|
3717
3853
|
if (isReadonly(ctx)) return;
|
|
3718
3854
|
const keyboard = Keyboard.read(ctx);
|
|
@@ -3722,8 +3858,8 @@ var keybindSystem = defineEditorSystem({ phase: "capture" }, (ctx) => {
|
|
|
3722
3858
|
triggered &&= !!keybind.mod === keyboard.modDown;
|
|
3723
3859
|
triggered &&= !!keybind.shift === keyboard.shiftDown;
|
|
3724
3860
|
if (triggered) {
|
|
3725
|
-
const eid =
|
|
3726
|
-
|
|
3861
|
+
const eid = createEntity3(ctx);
|
|
3862
|
+
addComponent4(ctx, eid, CommandMarker, { name: keybind.command });
|
|
3727
3863
|
break;
|
|
3728
3864
|
}
|
|
3729
3865
|
}
|
|
@@ -3847,7 +3983,7 @@ var scrollEdgesSystem = defineEditorSystem({ phase: "capture" }, (ctx) => {
|
|
|
3847
3983
|
});
|
|
3848
3984
|
|
|
3849
3985
|
// src/systems/capture/transformBoxSystem.ts
|
|
3850
|
-
import { createEntity as
|
|
3986
|
+
import { createEntity as createEntity4, defineQuery as defineQuery9, hasComponent as hasComponent12, removeComponent as removeComponent2 } from "@woven-ecs/core";
|
|
3851
3987
|
import { and, assign as assign3, not as not2, raise, setup as setup3 } from "xstate";
|
|
3852
3988
|
var selectedBlocksQuery = defineQuery9((q) => q.with(Block).tracking(Selected));
|
|
3853
3989
|
var transformBoxMachine = setup3({
|
|
@@ -3862,12 +3998,12 @@ var transformBoxMachine = setup3({
|
|
|
3862
3998
|
isOverTransformBox: ({ event }) => {
|
|
3863
3999
|
if (!("intersects" in event)) return false;
|
|
3864
4000
|
if (event.intersects.length === 0) return false;
|
|
3865
|
-
return
|
|
4001
|
+
return hasComponent12(event.ctx, event.intersects[0], TransformBox);
|
|
3866
4002
|
},
|
|
3867
4003
|
isOverTransformHandle: ({ event }) => {
|
|
3868
4004
|
if (!("intersects" in event)) return false;
|
|
3869
4005
|
if (event.intersects.length === 0) return false;
|
|
3870
|
-
return
|
|
4006
|
+
return hasComponent12(event.ctx, event.intersects[0], TransformHandle);
|
|
3871
4007
|
},
|
|
3872
4008
|
selectionIsTransformable: ({ event }) => {
|
|
3873
4009
|
if (event.type !== "selectionChanged") return false;
|
|
@@ -3879,7 +4015,7 @@ var transformBoxMachine = setup3({
|
|
|
3879
4015
|
hasEditAfterPlacing: ({ event }) => {
|
|
3880
4016
|
if (event.type !== "selectionChanged") return false;
|
|
3881
4017
|
if (event.selectedEntityIds.length !== 1) return false;
|
|
3882
|
-
return
|
|
4018
|
+
return hasComponent12(event.ctx, event.selectedEntityIds[0], EditAfterPlacing);
|
|
3883
4019
|
}
|
|
3884
4020
|
},
|
|
3885
4021
|
actions: {
|
|
@@ -3889,7 +4025,7 @@ var transformBoxMachine = setup3({
|
|
|
3889
4025
|
transformBoxId: context.transformBoxId
|
|
3890
4026
|
});
|
|
3891
4027
|
}
|
|
3892
|
-
const transformBoxId =
|
|
4028
|
+
const transformBoxId = createEntity4(event.ctx);
|
|
3893
4029
|
AddTransformBox.spawn(event.ctx, {
|
|
3894
4030
|
transformBoxId,
|
|
3895
4031
|
skipHandles: params?.skipHandles
|
|
@@ -3932,7 +4068,7 @@ var transformBoxMachine = setup3({
|
|
|
3932
4068
|
removeEditAfterPlacing: ({ event }) => {
|
|
3933
4069
|
if (event.type !== "selectionChanged") return;
|
|
3934
4070
|
for (const entityId of event.selectedEntityIds) {
|
|
3935
|
-
if (
|
|
4071
|
+
if (hasComponent12(event.ctx, entityId, EditAfterPlacing)) {
|
|
3936
4072
|
removeComponent2(event.ctx, entityId, EditAfterPlacing);
|
|
3937
4073
|
}
|
|
3938
4074
|
}
|
|
@@ -4227,7 +4363,7 @@ function normalizeWheelDelta(deltaY, deltaMode) {
|
|
|
4227
4363
|
}
|
|
4228
4364
|
|
|
4229
4365
|
// src/systems/input/pointerSystem.ts
|
|
4230
|
-
import { addComponent as
|
|
4366
|
+
import { addComponent as addComponent5, createEntity as createEntity5, getResources as getResources9, removeEntity as removeEntity3 } from "@woven-ecs/core";
|
|
4231
4367
|
var instanceState3 = /* @__PURE__ */ new WeakMap();
|
|
4232
4368
|
function attachPointerListeners(domElement) {
|
|
4233
4369
|
if (instanceState3.has(domElement)) return;
|
|
@@ -4334,8 +4470,8 @@ var pointerSystem = defineEditorSystem({ phase: "input" }, (ctx) => {
|
|
|
4334
4470
|
switch (event.type) {
|
|
4335
4471
|
case "pointerdown": {
|
|
4336
4472
|
const position = [event.clientX - screen.left, event.clientY - screen.top];
|
|
4337
|
-
const entityId =
|
|
4338
|
-
|
|
4473
|
+
const entityId = createEntity5(ctx);
|
|
4474
|
+
addComponent5(ctx, entityId, Pointer, {
|
|
4339
4475
|
pointerId: event.pointerId,
|
|
4340
4476
|
position,
|
|
4341
4477
|
downPosition: position,
|
|
@@ -4497,11 +4633,11 @@ function updateUserPosition(ctx, position) {
|
|
|
4497
4633
|
// src/systems/postUpdate/transformBoxSystem.ts
|
|
4498
4634
|
import { Rect as Rect2, Vec2 as Vec23 } from "@woven-canvas/math";
|
|
4499
4635
|
import {
|
|
4500
|
-
addComponent as
|
|
4501
|
-
createEntity as
|
|
4636
|
+
addComponent as addComponent6,
|
|
4637
|
+
createEntity as createEntity6,
|
|
4502
4638
|
defineQuery as defineQuery12,
|
|
4503
4639
|
getBackrefs as getBackrefs2,
|
|
4504
|
-
hasComponent as
|
|
4640
|
+
hasComponent as hasComponent13,
|
|
4505
4641
|
isAlive,
|
|
4506
4642
|
removeComponent as removeComponent3,
|
|
4507
4643
|
removeEntity as removeEntity4
|
|
@@ -4534,7 +4670,7 @@ var transformBoxSystem2 = defineEditorSystem({ phase: "update", priority: -100 }
|
|
|
4534
4670
|
on(ctx, EndTransformBoxEdit, endTransformBoxEdit);
|
|
4535
4671
|
});
|
|
4536
4672
|
function removeTransformBox(ctx, transformBoxId) {
|
|
4537
|
-
if (!
|
|
4673
|
+
if (!hasComponent13(ctx, transformBoxId, TransformBox)) {
|
|
4538
4674
|
endTransformBoxEdit(ctx);
|
|
4539
4675
|
return;
|
|
4540
4676
|
}
|
|
@@ -4546,15 +4682,15 @@ function removeTransformBox(ctx, transformBoxId) {
|
|
|
4546
4682
|
endTransformBoxEdit(ctx);
|
|
4547
4683
|
}
|
|
4548
4684
|
function addTransformBox(ctx, transformBoxId, skipHandles) {
|
|
4549
|
-
|
|
4685
|
+
addComponent6(ctx, transformBoxId, Block, {
|
|
4550
4686
|
tag: "transform-box",
|
|
4551
4687
|
position: [0, 0],
|
|
4552
4688
|
size: [0, 0],
|
|
4553
4689
|
rotateZ: 0,
|
|
4554
4690
|
rank: TRANSFORM_BOX_RANK
|
|
4555
4691
|
});
|
|
4556
|
-
|
|
4557
|
-
|
|
4692
|
+
addComponent6(ctx, transformBoxId, TransformBox, {});
|
|
4693
|
+
addComponent6(ctx, transformBoxId, DragStart, {
|
|
4558
4694
|
position: [0, 0],
|
|
4559
4695
|
size: [0, 0],
|
|
4560
4696
|
rotateZ: 0,
|
|
@@ -4591,7 +4727,7 @@ function updateTransformBox(ctx, transformBoxId) {
|
|
|
4591
4727
|
const selectionState = SelectionStateSingleton.read(ctx);
|
|
4592
4728
|
const isDragging = selectionState.state === SelectionState.Dragging;
|
|
4593
4729
|
if (!isDragging) {
|
|
4594
|
-
if (
|
|
4730
|
+
if (hasComponent13(ctx, transformBoxId, DragStart)) {
|
|
4595
4731
|
const dragStart = DragStart.write(ctx, transformBoxId);
|
|
4596
4732
|
dragStart.position = boxBlock.position;
|
|
4597
4733
|
dragStart.size = boxBlock.size;
|
|
@@ -4600,9 +4736,9 @@ function updateTransformBox(ctx, transformBoxId) {
|
|
|
4600
4736
|
for (const entityId of selectedBlocks) {
|
|
4601
4737
|
const block = Block.read(ctx, entityId);
|
|
4602
4738
|
const worldPos = Block.getWorldPosition(ctx, entityId);
|
|
4603
|
-
const fontSize =
|
|
4604
|
-
if (!
|
|
4605
|
-
|
|
4739
|
+
const fontSize = hasComponent13(ctx, entityId, Text) ? Text.read(ctx, entityId).fontSizePx : 16;
|
|
4740
|
+
if (!hasComponent13(ctx, entityId, DragStart)) {
|
|
4741
|
+
addComponent6(ctx, entityId, DragStart, {
|
|
4606
4742
|
position: worldPos,
|
|
4607
4743
|
size: block.size,
|
|
4608
4744
|
rotateZ: block.rotateZ,
|
|
@@ -4784,11 +4920,11 @@ function addOrUpdateTransformHandles(ctx, transformBoxId) {
|
|
|
4784
4920
|
const finalLeft = rotatedCenter[0] - def.width / 2;
|
|
4785
4921
|
const finalTop = rotatedCenter[1] - def.height / 2;
|
|
4786
4922
|
if (!handleId) {
|
|
4787
|
-
handleId =
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
|
|
4923
|
+
handleId = createEntity6(ctx);
|
|
4924
|
+
addComponent6(ctx, handleId, Block);
|
|
4925
|
+
addComponent6(ctx, handleId, TransformHandle);
|
|
4926
|
+
addComponent6(ctx, handleId, DragStart);
|
|
4927
|
+
addComponent6(ctx, handleId, ScaleWithZoom);
|
|
4792
4928
|
}
|
|
4793
4929
|
const block = Block.write(ctx, handleId);
|
|
4794
4930
|
block.tag = def.tag;
|
|
@@ -4869,11 +5005,11 @@ function addTapeHandles(ctx, transformBoxId, left, top, width, height, rotateZ,
|
|
|
4869
5005
|
const finalLeft = rotatedCenter[0] - def.width / 2;
|
|
4870
5006
|
const finalTop = rotatedCenter[1] - def.height / 2;
|
|
4871
5007
|
if (!handleId) {
|
|
4872
|
-
handleId =
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
5008
|
+
handleId = createEntity6(ctx);
|
|
5009
|
+
addComponent6(ctx, handleId, Block);
|
|
5010
|
+
addComponent6(ctx, handleId, TransformHandle);
|
|
5011
|
+
addComponent6(ctx, handleId, DragStart);
|
|
5012
|
+
addComponent6(ctx, handleId, ScaleWithZoom);
|
|
4877
5013
|
}
|
|
4878
5014
|
const block = Block.write(ctx, handleId);
|
|
4879
5015
|
block.tag = def.tag;
|
|
@@ -4905,9 +5041,9 @@ function addTapeHandles(ctx, transformBoxId, left, top, width, height, rotateZ,
|
|
|
4905
5041
|
}
|
|
4906
5042
|
}
|
|
4907
5043
|
function hideTransformBox(ctx, transformBoxId) {
|
|
4908
|
-
if (!
|
|
4909
|
-
if (!
|
|
4910
|
-
|
|
5044
|
+
if (!hasComponent13(ctx, transformBoxId, TransformBox)) return;
|
|
5045
|
+
if (!hasComponent13(ctx, transformBoxId, Opacity)) {
|
|
5046
|
+
addComponent6(ctx, transformBoxId, Opacity, { value: 0 });
|
|
4911
5047
|
} else {
|
|
4912
5048
|
const opacity = Opacity.write(ctx, transformBoxId);
|
|
4913
5049
|
opacity.value = 0;
|
|
@@ -4915,8 +5051,8 @@ function hideTransformBox(ctx, transformBoxId) {
|
|
|
4915
5051
|
const handles = getBackrefs2(ctx, transformBoxId, TransformHandle, "transformBox");
|
|
4916
5052
|
for (const handleId of handles) {
|
|
4917
5053
|
if (!isAlive(ctx, handleId)) continue;
|
|
4918
|
-
if (!
|
|
4919
|
-
|
|
5054
|
+
if (!hasComponent13(ctx, handleId, Opacity)) {
|
|
5055
|
+
addComponent6(ctx, handleId, Opacity, { value: 0 });
|
|
4920
5056
|
} else {
|
|
4921
5057
|
const opacity = Opacity.write(ctx, handleId);
|
|
4922
5058
|
opacity.value = 0;
|
|
@@ -4924,40 +5060,40 @@ function hideTransformBox(ctx, transformBoxId) {
|
|
|
4924
5060
|
}
|
|
4925
5061
|
}
|
|
4926
5062
|
function showTransformBox(ctx, transformBoxId) {
|
|
4927
|
-
if (!
|
|
5063
|
+
if (!hasComponent13(ctx, transformBoxId, TransformBox)) return;
|
|
4928
5064
|
const selectedBlocks = selectedBlocksQuery2.current(ctx);
|
|
4929
5065
|
if (selectedBlocks.length === 0) return;
|
|
4930
5066
|
if (selectedBlocks.length === 1) {
|
|
4931
5067
|
if (getBlockResizeMode(ctx, selectedBlocks[0]) === ResizeMode.GroupOnly) return;
|
|
4932
5068
|
}
|
|
4933
|
-
if (
|
|
5069
|
+
if (hasComponent13(ctx, transformBoxId, Opacity)) {
|
|
4934
5070
|
removeComponent3(ctx, transformBoxId, Opacity);
|
|
4935
5071
|
}
|
|
4936
5072
|
const handles = getBackrefs2(ctx, transformBoxId, TransformHandle, "transformBox");
|
|
4937
5073
|
for (const handleId of handles) {
|
|
4938
5074
|
if (!isAlive(ctx, handleId)) continue;
|
|
4939
|
-
if (
|
|
5075
|
+
if (hasComponent13(ctx, handleId, Opacity)) {
|
|
4940
5076
|
removeComponent3(ctx, handleId, Opacity);
|
|
4941
5077
|
}
|
|
4942
5078
|
}
|
|
4943
5079
|
updateTransformBox(ctx, transformBoxId);
|
|
4944
5080
|
}
|
|
4945
5081
|
function startTransformBoxEdit(ctx, transformBoxId) {
|
|
4946
|
-
if (
|
|
5082
|
+
if (hasComponent13(ctx, transformBoxId, TransformBox)) {
|
|
4947
5083
|
const handles = getBackrefs2(ctx, transformBoxId, TransformHandle, "transformBox");
|
|
4948
5084
|
for (const handleId of handles) {
|
|
4949
5085
|
removeEntity4(ctx, handleId);
|
|
4950
5086
|
}
|
|
4951
5087
|
}
|
|
4952
5088
|
for (const blockId of selectedBlocksQuery2.current(ctx)) {
|
|
4953
|
-
if (!
|
|
4954
|
-
|
|
5089
|
+
if (!hasComponent13(ctx, blockId, Edited)) {
|
|
5090
|
+
addComponent6(ctx, blockId, Edited, {});
|
|
4955
5091
|
}
|
|
4956
5092
|
}
|
|
4957
5093
|
}
|
|
4958
5094
|
function endTransformBoxEdit(ctx) {
|
|
4959
5095
|
for (const blockId of editedBlocksQuery.current(ctx)) {
|
|
4960
|
-
if (
|
|
5096
|
+
if (hasComponent13(ctx, blockId, Edited)) {
|
|
4961
5097
|
removeComponent3(ctx, blockId, Edited);
|
|
4962
5098
|
}
|
|
4963
5099
|
}
|
|
@@ -4965,11 +5101,11 @@ function endTransformBoxEdit(ctx) {
|
|
|
4965
5101
|
|
|
4966
5102
|
// src/systems/preCapture/intersectSystem.ts
|
|
4967
5103
|
import {
|
|
4968
|
-
addComponent as
|
|
5104
|
+
addComponent as addComponent7,
|
|
4969
5105
|
defineQuery as defineQuery13,
|
|
4970
5106
|
getBackrefs as getBackrefs3,
|
|
4971
5107
|
getResources as getResources12,
|
|
4972
|
-
hasComponent as
|
|
5108
|
+
hasComponent as hasComponent14,
|
|
4973
5109
|
removeComponent as removeComponent4
|
|
4974
5110
|
} from "@woven-ecs/core";
|
|
4975
5111
|
var blocksChanged = defineQuery13((q) => q.tracking(Block));
|
|
@@ -4979,7 +5115,7 @@ var hoveredQuery = defineQuery13((q) => q.with(Hovered));
|
|
|
4979
5115
|
var pointerQuery3 = defineQuery13((q) => q.with(Pointer));
|
|
4980
5116
|
function clearHovered(ctx) {
|
|
4981
5117
|
for (const entityId of hoveredQuery.current(ctx)) {
|
|
4982
|
-
if (
|
|
5118
|
+
if (hasComponent14(ctx, entityId, Hovered)) {
|
|
4983
5119
|
removeComponent4(ctx, entityId, Hovered);
|
|
4984
5120
|
}
|
|
4985
5121
|
}
|
|
@@ -4987,7 +5123,7 @@ function clearHovered(ctx) {
|
|
|
4987
5123
|
function findValidHoverTarget(ctx, intersected) {
|
|
4988
5124
|
for (const entityId of intersected) {
|
|
4989
5125
|
if (isHeldByRemote(ctx, entityId)) return void 0;
|
|
4990
|
-
if (
|
|
5126
|
+
if (hasComponent14(ctx, entityId, Block)) {
|
|
4991
5127
|
const block = Block.read(ctx, entityId);
|
|
4992
5128
|
if (!canBlockInteract(ctx, block.tag)) continue;
|
|
4993
5129
|
}
|
|
@@ -5002,7 +5138,7 @@ function updateHovered(ctx, intersected) {
|
|
|
5002
5138
|
if (!selectToolActive) return;
|
|
5003
5139
|
const newHoveredId = findValidHoverTarget(ctx, intersected);
|
|
5004
5140
|
if (newHoveredId !== void 0) {
|
|
5005
|
-
|
|
5141
|
+
addComponent7(ctx, newHoveredId, Hovered, {});
|
|
5006
5142
|
}
|
|
5007
5143
|
}
|
|
5008
5144
|
function arraysEqual(a, b) {
|
|
@@ -5041,14 +5177,14 @@ var intersectSystem = defineEditorSystem({ phase: "capture", priority: 100 }, (c
|
|
|
5041
5177
|
addDescendants(ctx, entityId, changed);
|
|
5042
5178
|
}
|
|
5043
5179
|
for (const entityId of added) {
|
|
5044
|
-
if (!
|
|
5045
|
-
|
|
5180
|
+
if (!hasComponent14(ctx, entityId, Aabb)) {
|
|
5181
|
+
addComponent7(ctx, entityId, Aabb, { value: [0, 0, 0, 0] });
|
|
5046
5182
|
}
|
|
5047
5183
|
const aabb = Aabb.write(ctx, entityId);
|
|
5048
5184
|
computeAabb(ctx, entityId, aabb.value);
|
|
5049
5185
|
}
|
|
5050
5186
|
for (const entityId of changed) {
|
|
5051
|
-
if (!
|
|
5187
|
+
if (!hasComponent14(ctx, entityId, Aabb)) continue;
|
|
5052
5188
|
const aabb = Aabb.write(ctx, entityId);
|
|
5053
5189
|
computeAabb(ctx, entityId, aabb.value);
|
|
5054
5190
|
}
|
|
@@ -5097,12 +5233,21 @@ var intersectSystem = defineEditorSystem({ phase: "capture", priority: 100 }, (c
|
|
|
5097
5233
|
|
|
5098
5234
|
// src/systems/preCapture/selectSystem.ts
|
|
5099
5235
|
import { Vec2 as Vec2Ns } from "@woven-canvas/math";
|
|
5100
|
-
import { Synced as
|
|
5101
|
-
import { defineQuery as defineQuery14, hasComponent as
|
|
5236
|
+
import { Synced as Synced4 } from "@woven-ecs/canvas-store";
|
|
5237
|
+
import { defineQuery as defineQuery14, hasComponent as hasComponent15 } from "@woven-ecs/core";
|
|
5102
5238
|
import { and as and2, assign as assign4, not as not3, setup as setup4 } from "xstate";
|
|
5103
5239
|
var POINTING_THRESHOLD = 4;
|
|
5104
|
-
var selectedBlocksQuery3 = defineQuery14((q) => q.with(Block, Selected,
|
|
5240
|
+
var selectedBlocksQuery3 = defineQuery14((q) => q.with(Block, Selected, Synced4));
|
|
5105
5241
|
var editedBlocksQuery2 = defineQuery14((q) => q.with(Block, Edited));
|
|
5242
|
+
function isDragSnappable(ctx, draggedEntity) {
|
|
5243
|
+
if (hasComponent15(ctx, draggedEntity, TransformBox)) {
|
|
5244
|
+
for (const blockId of selectedBlocksQuery3.current(ctx)) {
|
|
5245
|
+
if (canBlockSnap(ctx, Block.read(ctx, blockId).tag)) return true;
|
|
5246
|
+
}
|
|
5247
|
+
return false;
|
|
5248
|
+
}
|
|
5249
|
+
return canBlockSnap(ctx, Block.read(ctx, draggedEntity).tag);
|
|
5250
|
+
}
|
|
5106
5251
|
var selectionMachine = setup4({
|
|
5107
5252
|
types: {
|
|
5108
5253
|
context: {},
|
|
@@ -5118,13 +5263,13 @@ var selectionMachine = setup4({
|
|
|
5118
5263
|
},
|
|
5119
5264
|
hasDraggedEntity: ({ context, event }) => {
|
|
5120
5265
|
if (context.draggedEntity === null) return false;
|
|
5121
|
-
return
|
|
5266
|
+
return hasComponent15(event.ctx, context.draggedEntity, Synced4);
|
|
5122
5267
|
},
|
|
5123
5268
|
isOverSyncedBlock: ({ event }) => {
|
|
5124
5269
|
const ctx = event.ctx;
|
|
5125
5270
|
for (const entityId of event.intersects) {
|
|
5126
|
-
if (
|
|
5127
|
-
if (
|
|
5271
|
+
if (hasComponent15(ctx, entityId, Synced4)) {
|
|
5272
|
+
if (hasComponent15(ctx, entityId, Block)) {
|
|
5128
5273
|
const block = Block.read(ctx, entityId);
|
|
5129
5274
|
if (!canBlockInteract(ctx, block.tag)) continue;
|
|
5130
5275
|
}
|
|
@@ -5161,7 +5306,7 @@ var selectionMachine = setup4({
|
|
|
5161
5306
|
},
|
|
5162
5307
|
setDragCursor: ({ event, context }) => {
|
|
5163
5308
|
if (!context.draggedEntity) return;
|
|
5164
|
-
if (
|
|
5309
|
+
if (hasComponent15(event.ctx, context.draggedEntity, TransformHandle)) {
|
|
5165
5310
|
const handle = TransformHandle.read(event.ctx, context.draggedEntity);
|
|
5166
5311
|
const transformBoxBlock = handle.transformBox !== null ? Block.read(event.ctx, handle.transformBox) : void 0;
|
|
5167
5312
|
SetCursor.spawn(event.ctx, {
|
|
@@ -5221,7 +5366,7 @@ var selectionMachine = setup4({
|
|
|
5221
5366
|
if (context.draggedEntity === null) return false;
|
|
5222
5367
|
let left = context.draggedEntityStart[0] + event.worldPosition[0] - context.dragStart[0];
|
|
5223
5368
|
let top = context.draggedEntityStart[1] + event.worldPosition[1] - context.dragStart[1];
|
|
5224
|
-
const draggingSynced =
|
|
5369
|
+
const draggingSynced = hasComponent15(ctx, context.draggedEntity, Synced4) || hasComponent15(ctx, context.draggedEntity, TransformBox);
|
|
5225
5370
|
if (event.shiftDown && draggingSynced) {
|
|
5226
5371
|
const dx = Math.abs(event.worldPosition[0] - context.dragStart[0]);
|
|
5227
5372
|
const dy = Math.abs(event.worldPosition[1] - context.dragStart[1]);
|
|
@@ -5231,7 +5376,7 @@ var selectionMachine = setup4({
|
|
|
5231
5376
|
left = context.draggedEntityStart[0];
|
|
5232
5377
|
}
|
|
5233
5378
|
}
|
|
5234
|
-
if (draggingSynced) {
|
|
5379
|
+
if (draggingSynced && isDragSnappable(ctx, context.draggedEntity)) {
|
|
5235
5380
|
left = Grid.snapX(ctx, left);
|
|
5236
5381
|
top = Grid.snapY(ctx, top);
|
|
5237
5382
|
}
|
|
@@ -5244,7 +5389,7 @@ var selectionMachine = setup4({
|
|
|
5244
5389
|
const dx = context.draggedEntityStart[0] - left;
|
|
5245
5390
|
const dy = context.draggedEntityStart[1] - top;
|
|
5246
5391
|
isCloning = true;
|
|
5247
|
-
const isTransformBox =
|
|
5392
|
+
const isTransformBox = hasComponent15(ctx, context.draggedEntity, TransformBox);
|
|
5248
5393
|
const entityIds = isTransformBox ? Array.from(selectedBlocksQuery3.current(ctx)) : [context.draggedEntity];
|
|
5249
5394
|
CloneEntities.spawn(ctx, {
|
|
5250
5395
|
entityIds,
|
|
@@ -5252,7 +5397,7 @@ var selectionMachine = setup4({
|
|
|
5252
5397
|
seed: context.cloneGeneratorSeed
|
|
5253
5398
|
});
|
|
5254
5399
|
} else if (!event.altDown && context.isCloning) {
|
|
5255
|
-
const isTransformBox =
|
|
5400
|
+
const isTransformBox = hasComponent15(ctx, context.draggedEntity, TransformBox);
|
|
5256
5401
|
const entityIds = isTransformBox ? Array.from(selectedBlocksQuery3.current(ctx)) : [context.draggedEntity];
|
|
5257
5402
|
UncloneEntities.spawn(ctx, {
|
|
5258
5403
|
entityIds,
|
|
@@ -5277,8 +5422,8 @@ var selectionMachine = setup4({
|
|
|
5277
5422
|
const ctx = event.ctx;
|
|
5278
5423
|
let intersectId;
|
|
5279
5424
|
for (const entityId of event.intersects) {
|
|
5280
|
-
if (
|
|
5281
|
-
if (
|
|
5425
|
+
if (hasComponent15(ctx, entityId, Synced4)) {
|
|
5426
|
+
if (hasComponent15(ctx, entityId, Block)) {
|
|
5282
5427
|
const block = Block.read(ctx, entityId);
|
|
5283
5428
|
if (!canBlockInteract(ctx, block.tag)) continue;
|
|
5284
5429
|
}
|
|
@@ -5298,7 +5443,7 @@ var selectionMachine = setup4({
|
|
|
5298
5443
|
},
|
|
5299
5444
|
selectDragged: ({ context, event }) => {
|
|
5300
5445
|
if (context.draggedEntity === null) return;
|
|
5301
|
-
if (!
|
|
5446
|
+
if (!hasComponent15(event.ctx, context.draggedEntity, Synced4)) return;
|
|
5302
5447
|
SelectBlock.spawn(event.ctx, {
|
|
5303
5448
|
entityId: context.draggedEntity,
|
|
5304
5449
|
deselectOthers: true
|
|
@@ -5310,9 +5455,9 @@ var selectionMachine = setup4({
|
|
|
5310
5455
|
},
|
|
5311
5456
|
deselectAllIfDraggedNotSelected: ({ context, event }) => {
|
|
5312
5457
|
if (context.draggedEntity === null) return;
|
|
5313
|
-
if (
|
|
5314
|
-
if (
|
|
5315
|
-
if (
|
|
5458
|
+
if (hasComponent15(event.ctx, context.draggedEntity, Selected)) return;
|
|
5459
|
+
if (hasComponent15(event.ctx, context.draggedEntity, TransformBox)) return;
|
|
5460
|
+
if (hasComponent15(event.ctx, context.draggedEntity, TransformHandle)) return;
|
|
5316
5461
|
DeselectAll.spawn(event.ctx, void 0);
|
|
5317
5462
|
}
|
|
5318
5463
|
}
|
|
@@ -5436,9 +5581,9 @@ var selectSystem = defineEditorSystem({ phase: "capture", priority: 100 }, (ctx)
|
|
|
5436
5581
|
});
|
|
5437
5582
|
|
|
5438
5583
|
// src/systems/preInput/rankBoundsSystem.ts
|
|
5439
|
-
import { Synced as
|
|
5584
|
+
import { Synced as Synced5 } from "@woven-ecs/canvas-store";
|
|
5440
5585
|
import { defineQuery as defineQuery15 } from "@woven-ecs/core";
|
|
5441
|
-
var blocksQuery = defineQuery15((q) => q.with(
|
|
5586
|
+
var blocksQuery = defineQuery15((q) => q.with(Synced5, Block));
|
|
5442
5587
|
var rankBoundsSystem = defineEditorSystem({ phase: "input", priority: 100 }, (ctx) => {
|
|
5443
5588
|
const added2 = blocksQuery.added(ctx);
|
|
5444
5589
|
for (const entityId of added2) {
|
|
@@ -5455,11 +5600,11 @@ var rankBoundsSystem = defineEditorSystem({ phase: "input", priority: 100 }, (ct
|
|
|
5455
5600
|
|
|
5456
5601
|
// src/systems/preRender/canSeeBlocksSystem.ts
|
|
5457
5602
|
import { Aabb as AabbMath2 } from "@woven-canvas/math";
|
|
5458
|
-
import { Synced as
|
|
5459
|
-
import { defineQuery as defineQuery16, hasComponent as
|
|
5603
|
+
import { Synced as Synced6 } from "@woven-ecs/canvas-store";
|
|
5604
|
+
import { defineQuery as defineQuery16, hasComponent as hasComponent16 } from "@woven-ecs/core";
|
|
5460
5605
|
var camerasQuery = defineQuery16((q) => q.tracking(Camera));
|
|
5461
|
-
var blocksQuery2 = defineQuery16((q) => q.with(
|
|
5462
|
-
var syncedBlocksQuery = defineQuery16((q) => q.with(
|
|
5606
|
+
var blocksQuery2 = defineQuery16((q) => q.with(Synced6, Block, Aabb));
|
|
5607
|
+
var syncedBlocksQuery = defineQuery16((q) => q.with(Synced6, Block, Aabb));
|
|
5463
5608
|
var _cameraAabb = [0, 0, 0, 0];
|
|
5464
5609
|
var canSeeBlocksSystem = defineEditorSystem({ phase: "render", priority: 90 }, (ctx) => {
|
|
5465
5610
|
if (camerasQuery.changed(ctx).length === 0 && syncedBlocksQuery.addedOrRemoved(ctx).length === 0) {
|
|
@@ -5468,7 +5613,7 @@ var canSeeBlocksSystem = defineEditorSystem({ phase: "render", priority: 90 }, (
|
|
|
5468
5613
|
const camera = Camera.read(ctx);
|
|
5469
5614
|
const cameraAabb = Camera.getAabb(ctx, _cameraAabb);
|
|
5470
5615
|
if (camera.canSeeBlocks && camera.lastSeenBlock !== null) {
|
|
5471
|
-
if (
|
|
5616
|
+
if (hasComponent16(ctx, camera.lastSeenBlock, Aabb)) {
|
|
5472
5617
|
const aabb = Aabb.read(ctx, camera.lastSeenBlock);
|
|
5473
5618
|
if (AabbMath2.intersects(cameraAabb, aabb.value)) {
|
|
5474
5619
|
return;
|
|
@@ -5542,23 +5687,23 @@ function scaleBlock(ctx, entityId, zoom) {
|
|
|
5542
5687
|
|
|
5543
5688
|
// src/systems/update/blockSystem.ts
|
|
5544
5689
|
import { Vec2 as Vec25 } from "@woven-canvas/math";
|
|
5545
|
-
import { Synced as
|
|
5690
|
+
import { Synced as Synced7 } from "@woven-ecs/canvas-store";
|
|
5546
5691
|
import {
|
|
5547
|
-
addComponent as
|
|
5548
|
-
createEntity as
|
|
5692
|
+
addComponent as addComponent8,
|
|
5693
|
+
createEntity as createEntity7,
|
|
5549
5694
|
defineQuery as defineQuery18,
|
|
5550
5695
|
getBackrefs as getBackrefs4,
|
|
5551
5696
|
getResources as getResources13,
|
|
5552
|
-
hasComponent as
|
|
5697
|
+
hasComponent as hasComponent17,
|
|
5553
5698
|
isAlive as isAlive2,
|
|
5554
5699
|
removeComponent as removeComponent5,
|
|
5555
5700
|
removeEntity as removeEntity5
|
|
5556
5701
|
} from "@woven-ecs/core";
|
|
5557
5702
|
var selectedBlocksQuery4 = defineQuery18((q) => q.with(Block, Selected));
|
|
5558
|
-
var syncedBlocksQuery2 = defineQuery18((q) => q.with(Block,
|
|
5703
|
+
var syncedBlocksQuery2 = defineQuery18((q) => q.with(Block, Synced7));
|
|
5559
5704
|
var blockSystem = defineEditorSystem({ phase: "update" }, (ctx) => {
|
|
5560
5705
|
on(ctx, DragBlock, (ctx2, { entityId, position }) => {
|
|
5561
|
-
if (!
|
|
5706
|
+
if (!hasComponent17(ctx2, entityId, Block)) return;
|
|
5562
5707
|
Block.setWorldPosition(ctx2, entityId, position);
|
|
5563
5708
|
});
|
|
5564
5709
|
on(ctx, SelectBlock, (ctx2, { entityId, deselectOthers }) => {
|
|
@@ -5571,7 +5716,7 @@ var blockSystem = defineEditorSystem({ phase: "update" }, (ctx) => {
|
|
|
5571
5716
|
deselectBlock(ctx2, entityId);
|
|
5572
5717
|
});
|
|
5573
5718
|
on(ctx, ToggleSelect, (ctx2, { entityId }) => {
|
|
5574
|
-
if (
|
|
5719
|
+
if (hasComponent17(ctx2, entityId, Selected)) {
|
|
5575
5720
|
deselectBlock(ctx2, entityId);
|
|
5576
5721
|
} else {
|
|
5577
5722
|
selectBlock(ctx2, entityId);
|
|
@@ -5579,14 +5724,14 @@ var blockSystem = defineEditorSystem({ phase: "update" }, (ctx) => {
|
|
|
5579
5724
|
});
|
|
5580
5725
|
on(ctx, DeselectAll, deselectAllBlocks);
|
|
5581
5726
|
on(ctx, AddHeld, (ctx2, { entityId }) => {
|
|
5582
|
-
if (!
|
|
5583
|
-
if (
|
|
5727
|
+
if (!hasComponent17(ctx2, entityId, Synced7)) return;
|
|
5728
|
+
if (hasComponent17(ctx2, entityId, Held)) return;
|
|
5584
5729
|
const { sessionId } = getResources13(ctx2);
|
|
5585
|
-
|
|
5730
|
+
addComponent8(ctx2, entityId, Held, { sessionId });
|
|
5586
5731
|
});
|
|
5587
5732
|
on(ctx, RemoveHeld, (ctx2, { entityId }) => {
|
|
5588
|
-
if (
|
|
5589
|
-
if (!
|
|
5733
|
+
if (hasComponent17(ctx2, entityId, Selected)) return;
|
|
5734
|
+
if (!hasComponent17(ctx2, entityId, Held)) return;
|
|
5590
5735
|
removeComponent5(ctx2, entityId, Held);
|
|
5591
5736
|
});
|
|
5592
5737
|
on(ctx, SelectAll, (ctx2) => {
|
|
@@ -5676,10 +5821,10 @@ function cloneEntities(ctx, entityIds, offset, seed) {
|
|
|
5676
5821
|
entityIds = [...allEntityIdsSet];
|
|
5677
5822
|
const { componentsById } = getResources13(ctx);
|
|
5678
5823
|
const documentComponents = new Map([...componentsById].filter(([, def]) => def.sync === "document"));
|
|
5679
|
-
const syncedComponentId =
|
|
5824
|
+
const syncedComponentId = Synced7._getComponentId(ctx);
|
|
5680
5825
|
const blockComponentId = Block._getComponentId(ctx);
|
|
5681
5826
|
const entityIdSet = new Set(entityIds);
|
|
5682
|
-
const sortedEntities = entityIds.filter((id) =>
|
|
5827
|
+
const sortedEntities = entityIds.filter((id) => hasComponent17(ctx, id, Block)).sort((a, b) => {
|
|
5683
5828
|
const rankA = Block.read(ctx, a).rank;
|
|
5684
5829
|
const rankB = Block.read(ctx, b).rank;
|
|
5685
5830
|
return rankA < rankB ? -1 : rankA > rankB ? 1 : 0;
|
|
@@ -5703,12 +5848,12 @@ function cloneEntities(ctx, entityIds, offset, seed) {
|
|
|
5703
5848
|
}
|
|
5704
5849
|
const originalToClone = /* @__PURE__ */ new Map();
|
|
5705
5850
|
for (const entityId of entityIds) {
|
|
5706
|
-
if (!
|
|
5707
|
-
const synced =
|
|
5851
|
+
if (!hasComponent17(ctx, entityId, Synced7)) continue;
|
|
5852
|
+
const synced = Synced7.read(ctx, entityId);
|
|
5708
5853
|
const cloneId = generateUuidBySeed(synced.id, seed);
|
|
5709
|
-
const cloneEntityId =
|
|
5854
|
+
const cloneEntityId = createEntity7(ctx);
|
|
5710
5855
|
originalToClone.set(entityId, cloneEntityId);
|
|
5711
|
-
|
|
5856
|
+
addComponent8(ctx, cloneEntityId, Synced7, { id: cloneId });
|
|
5712
5857
|
for (const componentId of ctx.entityBuffer.getComponentIds(entityId)) {
|
|
5713
5858
|
if (componentId === syncedComponentId) continue;
|
|
5714
5859
|
const componentDef = documentComponents.get(componentId);
|
|
@@ -5724,7 +5869,7 @@ function cloneEntities(ctx, entityIds, offset, seed) {
|
|
|
5724
5869
|
}
|
|
5725
5870
|
data.rank = cloneRankMap.get(entityId) ?? RankBounds.genBetween(prevRank, lowestOriginalRank);
|
|
5726
5871
|
}
|
|
5727
|
-
|
|
5872
|
+
addComponent8(ctx, cloneEntityId, componentDef, data);
|
|
5728
5873
|
}
|
|
5729
5874
|
}
|
|
5730
5875
|
swapConnectorRefs(ctx, originalToClone);
|
|
@@ -5740,23 +5885,23 @@ function uncloneEntities(ctx, entityIds, seed) {
|
|
|
5740
5885
|
entityIds = [...allEntityIdsSet];
|
|
5741
5886
|
const expectedCloneUuids = /* @__PURE__ */ new Set();
|
|
5742
5887
|
for (const entityId of entityIds) {
|
|
5743
|
-
if (!
|
|
5744
|
-
const synced =
|
|
5888
|
+
if (!hasComponent17(ctx, entityId, Synced7)) continue;
|
|
5889
|
+
const synced = Synced7.read(ctx, entityId);
|
|
5745
5890
|
expectedCloneUuids.add(generateUuidBySeed(synced.id, seed));
|
|
5746
5891
|
}
|
|
5747
5892
|
const clonesToRemove = [];
|
|
5748
5893
|
for (const entityId of syncedBlocksQuery2.current(ctx)) {
|
|
5749
|
-
const synced =
|
|
5894
|
+
const synced = Synced7.read(ctx, entityId);
|
|
5750
5895
|
if (expectedCloneUuids.has(synced.id)) {
|
|
5751
5896
|
clonesToRemove.push(entityId);
|
|
5752
5897
|
}
|
|
5753
5898
|
}
|
|
5754
5899
|
const cloneToOriginal = /* @__PURE__ */ new Map();
|
|
5755
5900
|
for (const cloneId of clonesToRemove) {
|
|
5756
|
-
const cloneUuid =
|
|
5901
|
+
const cloneUuid = Synced7.read(ctx, cloneId).id;
|
|
5757
5902
|
for (const originalId of entityIds) {
|
|
5758
|
-
if (!
|
|
5759
|
-
const originalUuid =
|
|
5903
|
+
if (!hasComponent17(ctx, originalId, Synced7)) continue;
|
|
5904
|
+
const originalUuid = Synced7.read(ctx, originalId).id;
|
|
5760
5905
|
if (generateUuidBySeed(originalUuid, seed) === cloneUuid) {
|
|
5761
5906
|
cloneToOriginal.set(cloneId, originalId);
|
|
5762
5907
|
break;
|
|
@@ -5783,7 +5928,7 @@ function swapConnectorRefs(ctx, fromTo) {
|
|
|
5783
5928
|
function swapParentRefs(ctx, fromTo) {
|
|
5784
5929
|
for (const [, cloneId] of fromTo) {
|
|
5785
5930
|
if (!isAlive2(ctx, cloneId)) continue;
|
|
5786
|
-
if (!
|
|
5931
|
+
if (!hasComponent17(ctx, cloneId, Block)) continue;
|
|
5787
5932
|
const block = Block.read(ctx, cloneId);
|
|
5788
5933
|
if (block.parentId !== null && fromTo.has(block.parentId)) {
|
|
5789
5934
|
Block.write(ctx, cloneId).parentId = fromTo.get(block.parentId);
|
|
@@ -5793,20 +5938,27 @@ function swapParentRefs(ctx, fromTo) {
|
|
|
5793
5938
|
|
|
5794
5939
|
// src/systems/update/dragHandlerSystem.ts
|
|
5795
5940
|
import { Scalar as Scalar2, Vec2 as Vec26 } from "@woven-canvas/math";
|
|
5796
|
-
import { defineQuery as defineQuery19, hasComponent as
|
|
5941
|
+
import { defineQuery as defineQuery19, hasComponent as hasComponent18 } from "@woven-ecs/core";
|
|
5797
5942
|
var selectedBlocksQuery5 = defineQuery19((q) => q.with(Block, Selected));
|
|
5798
5943
|
var transformBoxQuery2 = defineQuery19((q) => q.with(Block, TransformBox, DragStart));
|
|
5799
5944
|
function isParentSelected(ctx, blockId) {
|
|
5800
5945
|
const block = Block.read(ctx, blockId);
|
|
5801
|
-
return block.parentId !== null &&
|
|
5946
|
+
return block.parentId !== null && hasComponent18(ctx, block.parentId, Selected);
|
|
5947
|
+
}
|
|
5948
|
+
function isSelectionSnappable(ctx) {
|
|
5949
|
+
for (const blockId of selectedBlocksQuery5.current(ctx)) {
|
|
5950
|
+
if (isParentSelected(ctx, blockId)) continue;
|
|
5951
|
+
if (canBlockSnap(ctx, Block.read(ctx, blockId).tag)) return true;
|
|
5952
|
+
}
|
|
5953
|
+
return false;
|
|
5802
5954
|
}
|
|
5803
5955
|
var dragHandlerSystem = defineEditorSystem({ phase: "update" }, (ctx) => {
|
|
5804
5956
|
on(ctx, DragBlock, (ctx2, { entityId, position }) => {
|
|
5805
|
-
if (
|
|
5957
|
+
if (hasComponent18(ctx2, entityId, TransformBox)) {
|
|
5806
5958
|
onTransformBoxDrag(ctx2, entityId, position);
|
|
5807
5959
|
return;
|
|
5808
5960
|
}
|
|
5809
|
-
if (
|
|
5961
|
+
if (hasComponent18(ctx2, entityId, TransformHandle)) {
|
|
5810
5962
|
onTransformHandleDrag(ctx2, entityId, position);
|
|
5811
5963
|
return;
|
|
5812
5964
|
}
|
|
@@ -5817,11 +5969,13 @@ function onTransformBoxDrag(ctx, boxId, position) {
|
|
|
5817
5969
|
const dx = position[0] - boxStart.position[0];
|
|
5818
5970
|
const dy = position[1] - boxStart.position[1];
|
|
5819
5971
|
for (const blockId of selectedBlocksQuery5.current(ctx)) {
|
|
5820
|
-
if (!
|
|
5972
|
+
if (!hasComponent18(ctx, blockId, DragStart)) continue;
|
|
5821
5973
|
if (isParentSelected(ctx, blockId)) continue;
|
|
5822
5974
|
const blockStart = DragStart.read(ctx, blockId);
|
|
5823
5975
|
const worldPos = [blockStart.position[0] + dx, blockStart.position[1] + dy];
|
|
5824
|
-
|
|
5976
|
+
if (canBlockSnap(ctx, Block.read(ctx, blockId).tag)) {
|
|
5977
|
+
Grid.snapPosition(ctx, worldPos);
|
|
5978
|
+
}
|
|
5825
5979
|
Block.setWorldPosition(ctx, blockId, worldPos);
|
|
5826
5980
|
}
|
|
5827
5981
|
}
|
|
@@ -5855,10 +6009,11 @@ function onRotateHandleDrag(ctx, handleId, position) {
|
|
|
5855
6009
|
let delta = angleHandle - handleStartAngle;
|
|
5856
6010
|
const grid = Grid.read(ctx);
|
|
5857
6011
|
const keyboard = Keyboard.read(ctx);
|
|
6012
|
+
const selectionSnappable = isSelectionSnappable(ctx);
|
|
5858
6013
|
let snapAngle = 0;
|
|
5859
6014
|
if (keyboard.shiftDown) {
|
|
5860
6015
|
snapAngle = grid.shiftSnapAngleRad;
|
|
5861
|
-
} else if (grid.enabled) {
|
|
6016
|
+
} else if (grid.enabled && selectionSnappable) {
|
|
5862
6017
|
snapAngle = grid.snapAngleRad;
|
|
5863
6018
|
}
|
|
5864
6019
|
if (snapAngle > 0) {
|
|
@@ -5867,7 +6022,7 @@ function onRotateHandleDrag(ctx, handleId, position) {
|
|
|
5867
6022
|
}
|
|
5868
6023
|
boxBlock.rotateZ = Scalar2.normalizeAngle(dragStart.rotateZ + delta);
|
|
5869
6024
|
for (const blockId of selectedBlocksQuery5.current(ctx)) {
|
|
5870
|
-
if (!
|
|
6025
|
+
if (!hasComponent18(ctx, blockId, DragStart)) continue;
|
|
5871
6026
|
if (isParentSelected(ctx, blockId)) continue;
|
|
5872
6027
|
const blockStart = DragStart.read(ctx, blockId);
|
|
5873
6028
|
const block = Block.write(ctx, blockId);
|
|
@@ -5880,7 +6035,7 @@ function onRotateHandleDrag(ctx, handleId, position) {
|
|
|
5880
6035
|
const angle = Vec26.angleTo(boxCenter, startCenter) + delta;
|
|
5881
6036
|
const newCenter = Vec26.fromPolar(r, angle, boxCenter);
|
|
5882
6037
|
const worldPos = [newCenter[0] - block.size[0] / 2, newCenter[1] - block.size[1] / 2];
|
|
5883
|
-
if (grid.strict) {
|
|
6038
|
+
if (grid.strict && canBlockSnap(ctx, block.tag)) {
|
|
5884
6039
|
Grid.snapPosition(ctx, worldPos);
|
|
5885
6040
|
}
|
|
5886
6041
|
Block.setWorldPosition(ctx, blockId, worldPos);
|
|
@@ -5897,7 +6052,10 @@ function onScaleHandleDrag(ctx, handleId, position, maintainAspectRatio) {
|
|
|
5897
6052
|
const handle = TransformHandle.read(ctx, handleId);
|
|
5898
6053
|
const handleBlock = Block.read(ctx, handleId);
|
|
5899
6054
|
const handleCenter = [position[0] + handleBlock.size[0] / 2, position[1] + handleBlock.size[1] / 2];
|
|
5900
|
-
|
|
6055
|
+
const selectionSnappable = isSelectionSnappable(ctx);
|
|
6056
|
+
if (selectionSnappable) {
|
|
6057
|
+
Grid.snapPosition(ctx, handleCenter);
|
|
6058
|
+
}
|
|
5901
6059
|
const boxRotateZ = boxStart.rotateZ;
|
|
5902
6060
|
const boxStartCenter = [
|
|
5903
6061
|
boxStart.position[0] + boxStart.size[0] / 2,
|
|
@@ -5948,7 +6106,7 @@ function onScaleHandleDrag(ctx, handleId, position, maintainAspectRatio) {
|
|
|
5948
6106
|
Vec26.add(newBoxCenter, vec);
|
|
5949
6107
|
const scaleFactor = [scaleX, scaleY];
|
|
5950
6108
|
for (const blockId of selectedBlocksQuery5.current(ctx)) {
|
|
5951
|
-
if (!
|
|
6109
|
+
if (!hasComponent18(ctx, blockId, DragStart)) continue;
|
|
5952
6110
|
if (isParentSelected(ctx, blockId)) continue;
|
|
5953
6111
|
const blockStart = DragStart.read(ctx, blockId);
|
|
5954
6112
|
const block = Block.write(ctx, blockId);
|
|
@@ -5966,7 +6124,7 @@ function onScaleHandleDrag(ctx, handleId, position, maintainAspectRatio) {
|
|
|
5966
6124
|
const newBlockSize = Vec26.clone(blockStart.size);
|
|
5967
6125
|
Vec26.multiply(newBlockSize, scaleFactor);
|
|
5968
6126
|
const isTextResize = getBlockResizeMode(ctx, blockId) === ResizeMode.Text;
|
|
5969
|
-
if (grid.strict) {
|
|
6127
|
+
if (grid.strict && canBlockSnap(ctx, block.tag)) {
|
|
5970
6128
|
if (isTextResize && maintainAspectRatio) {
|
|
5971
6129
|
newBlockSize[1] = Math.max(grid.rowHeight, Grid.snapY(ctx, newBlockSize[1]));
|
|
5972
6130
|
const aspectRatio = blockStart.size[0] / blockStart.size[1];
|
|
@@ -5977,7 +6135,7 @@ function onScaleHandleDrag(ctx, handleId, position, maintainAspectRatio) {
|
|
|
5977
6135
|
}
|
|
5978
6136
|
const worldPos = Vec26.clone(newBlockCenter);
|
|
5979
6137
|
Vec26.sub(worldPos, [newBlockSize[0] / 2, newBlockSize[1] / 2]);
|
|
5980
|
-
if (grid.strict) {
|
|
6138
|
+
if (grid.strict && canBlockSnap(ctx, block.tag)) {
|
|
5981
6139
|
Grid.snapPosition(ctx, worldPos);
|
|
5982
6140
|
}
|
|
5983
6141
|
Block.setWorldPosition(ctx, blockId, worldPos);
|
|
@@ -5988,7 +6146,7 @@ function onScaleHandleDrag(ctx, handleId, position, maintainAspectRatio) {
|
|
|
5988
6146
|
} else {
|
|
5989
6147
|
Vec26.copy(block.size, newBlockSize);
|
|
5990
6148
|
}
|
|
5991
|
-
if (
|
|
6149
|
+
if (hasComponent18(ctx, blockId, Text)) {
|
|
5992
6150
|
const didStretch = handle.kind === TransformHandleKind.Stretch;
|
|
5993
6151
|
const text = Text.write(ctx, blockId);
|
|
5994
6152
|
if (didStretch) {
|
|
@@ -6026,10 +6184,11 @@ function onRotateScaleHandleDrag(ctx, handleId, position) {
|
|
|
6026
6184
|
}
|
|
6027
6185
|
const grid = Grid.read(ctx);
|
|
6028
6186
|
const keyboard = Keyboard.read(ctx);
|
|
6187
|
+
const selectionSnappable = isSelectionSnappable(ctx);
|
|
6029
6188
|
let snapAngle = 0;
|
|
6030
6189
|
if (keyboard.shiftDown) {
|
|
6031
6190
|
snapAngle = grid.shiftSnapAngleRad;
|
|
6032
|
-
} else if (grid.enabled) {
|
|
6191
|
+
} else if (grid.enabled && selectionSnappable) {
|
|
6033
6192
|
snapAngle = grid.snapAngleRad;
|
|
6034
6193
|
}
|
|
6035
6194
|
if (snapAngle > 0) {
|
|
@@ -6049,13 +6208,13 @@ function onRotateScaleHandleDrag(ctx, handleId, position) {
|
|
|
6049
6208
|
boxBlock.size = [finalLength, startHeight];
|
|
6050
6209
|
boxBlock.position = [newCenter[0] - finalLength / 2, newCenter[1] - startHeight / 2];
|
|
6051
6210
|
for (const blockId of selectedBlocksQuery5.current(ctx)) {
|
|
6052
|
-
if (!
|
|
6211
|
+
if (!hasComponent18(ctx, blockId, DragStart)) continue;
|
|
6053
6212
|
if (isParentSelected(ctx, blockId)) continue;
|
|
6054
6213
|
const block = Block.write(ctx, blockId);
|
|
6055
6214
|
block.rotateZ = newRotateZ;
|
|
6056
6215
|
block.size = [finalLength, startHeight];
|
|
6057
6216
|
const blockWorldPos = [newCenter[0] - finalLength / 2, newCenter[1] - startHeight / 2];
|
|
6058
|
-
if (grid.strict) {
|
|
6217
|
+
if (grid.strict && canBlockSnap(ctx, block.tag)) {
|
|
6059
6218
|
Grid.snapPosition(ctx, blockWorldPos);
|
|
6060
6219
|
}
|
|
6061
6220
|
Block.setWorldPosition(ctx, blockId, blockWorldPos);
|
|
@@ -6063,23 +6222,23 @@ function onRotateScaleHandleDrag(ctx, handleId, position) {
|
|
|
6063
6222
|
}
|
|
6064
6223
|
|
|
6065
6224
|
// src/systems/update/selectSystem.ts
|
|
6066
|
-
import { Synced as
|
|
6067
|
-
import { addComponent as
|
|
6225
|
+
import { Synced as Synced8 } from "@woven-ecs/canvas-store";
|
|
6226
|
+
import { addComponent as addComponent9, createEntity as createEntity8, defineQuery as defineQuery20, removeEntity as removeEntity6 } from "@woven-ecs/core";
|
|
6068
6227
|
var selectedBlocksQuery6 = defineQuery20((q) => q.with(Block, Selected));
|
|
6069
6228
|
var selectionBoxQuery = defineQuery20((q) => q.with(Block, SelectionBox));
|
|
6070
|
-
var syncedBlocksQuery3 = defineQuery20((q) => q.with(Block,
|
|
6229
|
+
var syncedBlocksQuery3 = defineQuery20((q) => q.with(Block, Synced8, Aabb));
|
|
6071
6230
|
var SELECTION_BOX_RANK = "z";
|
|
6072
6231
|
var selectSystem2 = defineEditorSystem({ phase: "update" }, (ctx) => {
|
|
6073
6232
|
on(ctx, AddSelectionBox, (ctx2) => {
|
|
6074
|
-
const entityId =
|
|
6075
|
-
|
|
6233
|
+
const entityId = createEntity8(ctx2);
|
|
6234
|
+
addComponent9(ctx2, entityId, Block, {
|
|
6076
6235
|
tag: "selection-box",
|
|
6077
6236
|
position: [0, 0],
|
|
6078
6237
|
size: [0, 0],
|
|
6079
6238
|
rotateZ: 0,
|
|
6080
6239
|
rank: SELECTION_BOX_RANK
|
|
6081
6240
|
});
|
|
6082
|
-
|
|
6241
|
+
addComponent9(ctx2, entityId, SelectionBox, {});
|
|
6083
6242
|
});
|
|
6084
6243
|
on(ctx, UpdateSelectionBox, (ctx2, { bounds, deselectOthers }) => {
|
|
6085
6244
|
const selectionBoxes = selectionBoxQuery.current(ctx2);
|
|
@@ -6120,21 +6279,31 @@ var selectSystem2 = defineEditorSystem({ phase: "update" }, (ctx) => {
|
|
|
6120
6279
|
});
|
|
6121
6280
|
|
|
6122
6281
|
// src/systems/update/updateFrameContainmentSystem.ts
|
|
6123
|
-
import { addComponent as
|
|
6282
|
+
import { addComponent as addComponent10, hasComponent as hasComponent19, removeComponent as removeComponent6 } from "@woven-ecs/core";
|
|
6124
6283
|
var updateFrameContainmentSystem = defineEditorSystem({ phase: "update", priority: -10 }, (ctx) => {
|
|
6125
6284
|
on(ctx, AddFrameHighlight, (ctx2, { frameId }) => {
|
|
6126
|
-
if (!
|
|
6127
|
-
|
|
6285
|
+
if (!hasComponent19(ctx2, frameId, FrameDropTarget)) {
|
|
6286
|
+
addComponent10(ctx2, frameId, FrameDropTarget);
|
|
6128
6287
|
}
|
|
6129
6288
|
});
|
|
6289
|
+
on(ctx, PlaceBlockEvent, (ctx2, { entityId }) => {
|
|
6290
|
+
if (!hasComponent19(ctx2, entityId, Block)) return;
|
|
6291
|
+
if (Block.read(ctx2, entityId).parentId !== null) return;
|
|
6292
|
+
const center = Block.getCenter(ctx2, entityId);
|
|
6293
|
+
const frameId = findFrameAtPoint(ctx2, center, entityId);
|
|
6294
|
+
if (frameId === null) return;
|
|
6295
|
+
const worldPos = Block.getWorldPosition(ctx2, entityId);
|
|
6296
|
+
Block.write(ctx2, entityId).parentId = frameId;
|
|
6297
|
+
Block.setWorldPosition(ctx2, entityId, worldPos);
|
|
6298
|
+
});
|
|
6130
6299
|
on(ctx, RemoveFrameHighlight, (ctx2, { frameId }) => {
|
|
6131
|
-
if (
|
|
6300
|
+
if (hasComponent19(ctx2, frameId, FrameDropTarget)) {
|
|
6132
6301
|
removeComponent6(ctx2, frameId, FrameDropTarget);
|
|
6133
6302
|
}
|
|
6134
6303
|
});
|
|
6135
6304
|
on(ctx, AssignFrameChildren, (ctx2, { assignments }) => {
|
|
6136
6305
|
for (const { entityId, frameId } of assignments) {
|
|
6137
|
-
if (!
|
|
6306
|
+
if (!hasComponent19(ctx2, entityId, Block)) continue;
|
|
6138
6307
|
const currentParentId = Block.read(ctx2, entityId).parentId;
|
|
6139
6308
|
if (frameId !== null) {
|
|
6140
6309
|
if (currentParentId !== frameId) {
|
|
@@ -6156,12 +6325,12 @@ var updateFrameContainmentSystem = defineEditorSystem({ phase: "update", priorit
|
|
|
6156
6325
|
});
|
|
6157
6326
|
|
|
6158
6327
|
// src/systems/update/updateFrameSetupSystem.ts
|
|
6159
|
-
import { addComponent as
|
|
6328
|
+
import { addComponent as addComponent11, defineQuery as defineQuery21, hasComponent as hasComponent20 } from "@woven-ecs/core";
|
|
6160
6329
|
var frameQuery2 = defineQuery21((q) => q.tracking(Frame));
|
|
6161
6330
|
var updateFrameSetupSystem = defineEditorSystem({ phase: "update", priority: 100 }, (ctx) => {
|
|
6162
6331
|
for (const entityId of frameQuery2.added(ctx)) {
|
|
6163
|
-
if (
|
|
6164
|
-
|
|
6332
|
+
if (hasComponent20(ctx, entityId, HitGeometry)) continue;
|
|
6333
|
+
addComponent11(ctx, entityId, HitGeometry);
|
|
6165
6334
|
HitGeometry.addCapsuleUv(ctx, entityId, [0, 0], [1, 0], FRAME_EDGE_THICKNESS);
|
|
6166
6335
|
HitGeometry.addCapsuleUv(ctx, entityId, [1, 0], [1, 1], FRAME_EDGE_THICKNESS);
|
|
6167
6336
|
HitGeometry.addCapsuleUv(ctx, entityId, [1, 1], [0, 1], FRAME_EDGE_THICKNESS);
|
|
@@ -6339,10 +6508,10 @@ function createCorePlugin(options = {}) {
|
|
|
6339
6508
|
}
|
|
6340
6509
|
|
|
6341
6510
|
// src/Editor.ts
|
|
6342
|
-
import { Synced as
|
|
6511
|
+
import { Synced as Synced9 } from "@woven-ecs/canvas-store";
|
|
6343
6512
|
import {
|
|
6344
|
-
addComponent as
|
|
6345
|
-
createEntity as
|
|
6513
|
+
addComponent as addComponent12,
|
|
6514
|
+
createEntity as createEntity9,
|
|
6346
6515
|
World
|
|
6347
6516
|
} from "@woven-ecs/core";
|
|
6348
6517
|
|
|
@@ -6374,21 +6543,44 @@ var FontFamily = z2.object({
|
|
|
6374
6543
|
});
|
|
6375
6544
|
var FontLoader = class {
|
|
6376
6545
|
constructor() {
|
|
6377
|
-
|
|
6378
|
-
|
|
6379
|
-
|
|
6380
|
-
|
|
6381
|
-
|
|
6546
|
+
// Families whose stylesheet has fully loaded (fetched, injected, and the
|
|
6547
|
+
// FontFaces reported ready by the browser).
|
|
6548
|
+
this.loaded = /* @__PURE__ */ new Set();
|
|
6549
|
+
// In-flight loads, keyed by family name, so concurrent callers share one load
|
|
6550
|
+
// and — critically — can `await` it to *completion*. A plain "already started"
|
|
6551
|
+
// flag (the old behaviour) would let a second caller proceed before the font is
|
|
6552
|
+
// actually ready, which breaks code that measures text right after requesting a
|
|
6553
|
+
// font (the block would be sized against fallback metrics).
|
|
6554
|
+
this.inFlight = /* @__PURE__ */ new Map();
|
|
6555
|
+
}
|
|
6556
|
+
/**
|
|
6557
|
+
* Load multiple font families. Already-loaded families are skipped; in-flight
|
|
6558
|
+
* ones are shared. Resolves once all requested families are ready.
|
|
6382
6559
|
*
|
|
6383
6560
|
* @param families - Array of font families to load
|
|
6384
6561
|
*/
|
|
6385
6562
|
async loadFonts(families) {
|
|
6386
|
-
|
|
6387
|
-
|
|
6388
|
-
|
|
6389
|
-
|
|
6390
|
-
|
|
6391
|
-
|
|
6563
|
+
await Promise.all(families.map((family) => this.loadFont(family)));
|
|
6564
|
+
}
|
|
6565
|
+
/**
|
|
6566
|
+
* Load a single font family, returning a promise that resolves only once the
|
|
6567
|
+
* font is actually ready to render. Idempotent: an already-loaded family
|
|
6568
|
+
* resolves immediately, and concurrent calls for the same family share the one
|
|
6569
|
+
* in-flight load — so a caller that measures text can `await` real metrics.
|
|
6570
|
+
*
|
|
6571
|
+
* @param family - Font family to load
|
|
6572
|
+
*/
|
|
6573
|
+
loadFont(family) {
|
|
6574
|
+
if (this.loaded.has(family.name)) return Promise.resolve();
|
|
6575
|
+
const existing = this.inFlight.get(family.name);
|
|
6576
|
+
if (existing) return existing;
|
|
6577
|
+
const promise = this.loadSingleFont(family).then(() => {
|
|
6578
|
+
this.loaded.add(family.name);
|
|
6579
|
+
}).finally(() => {
|
|
6580
|
+
this.inFlight.delete(family.name);
|
|
6581
|
+
});
|
|
6582
|
+
this.inFlight.set(family.name, promise);
|
|
6583
|
+
return promise;
|
|
6392
6584
|
}
|
|
6393
6585
|
/**
|
|
6394
6586
|
* Build a Google Fonts URL with weight and italic variants.
|
|
@@ -6425,34 +6617,36 @@ var FontLoader = class {
|
|
|
6425
6617
|
}
|
|
6426
6618
|
/**
|
|
6427
6619
|
* Load a single font family.
|
|
6428
|
-
*
|
|
6620
|
+
* Fetches the stylesheet as text and injects it via an inline <style>, so
|
|
6621
|
+
* the @font-face rules land in a same-origin sheet. Tools that introspect
|
|
6622
|
+
* CSSOM (e.g. modern-screenshot's font embedding for /preview raster
|
|
6623
|
+
* captures) can't read cross-origin sheets, which a <link> to
|
|
6624
|
+
* fonts.googleapis.com would produce.
|
|
6429
6625
|
*
|
|
6430
6626
|
* @param family - Font family to load
|
|
6431
6627
|
*/
|
|
6432
|
-
loadSingleFont(family) {
|
|
6433
|
-
|
|
6434
|
-
|
|
6435
|
-
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
|
|
6439
|
-
|
|
6440
|
-
|
|
6441
|
-
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
|
|
6445
|
-
|
|
6446
|
-
|
|
6447
|
-
|
|
6448
|
-
|
|
6449
|
-
|
|
6450
|
-
|
|
6451
|
-
|
|
6452
|
-
|
|
6453
|
-
|
|
6454
|
-
document.head.appendChild(link);
|
|
6455
|
-
});
|
|
6628
|
+
async loadSingleFont(family) {
|
|
6629
|
+
if (typeof document === "undefined") return;
|
|
6630
|
+
const url = this.buildGoogleFontsUrl(family);
|
|
6631
|
+
let cssText;
|
|
6632
|
+
try {
|
|
6633
|
+
const res = await fetch(url);
|
|
6634
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
6635
|
+
cssText = await res.text();
|
|
6636
|
+
} catch (err) {
|
|
6637
|
+
throw new Error(`Failed to load font stylesheet: ${family.name}. ${err}`);
|
|
6638
|
+
}
|
|
6639
|
+
const style = document.createElement("style");
|
|
6640
|
+
style.setAttribute("data-wov-font-family", family.name);
|
|
6641
|
+
style.textContent = cssText;
|
|
6642
|
+
document.head.appendChild(style);
|
|
6643
|
+
try {
|
|
6644
|
+
const loadPromises = this.getFontLoadPromises(family);
|
|
6645
|
+
await Promise.all(loadPromises);
|
|
6646
|
+
await document.fonts.ready;
|
|
6647
|
+
} catch (err) {
|
|
6648
|
+
throw new Error(`Failed to load font face for: ${family.name}. ${err}`);
|
|
6649
|
+
}
|
|
6456
6650
|
}
|
|
6457
6651
|
/**
|
|
6458
6652
|
* Get promises for loading all font variants (weights and italics).
|
|
@@ -6478,13 +6672,13 @@ var FontLoader = class {
|
|
|
6478
6672
|
* @returns True if the font has been loaded
|
|
6479
6673
|
*/
|
|
6480
6674
|
isLoaded(fontName) {
|
|
6481
|
-
return this.
|
|
6675
|
+
return this.loaded.has(fontName);
|
|
6482
6676
|
}
|
|
6483
6677
|
/**
|
|
6484
6678
|
* Get the set of loaded font names.
|
|
6485
6679
|
*/
|
|
6486
6680
|
getLoadedFonts() {
|
|
6487
|
-
return this.
|
|
6681
|
+
return this.loaded;
|
|
6488
6682
|
}
|
|
6489
6683
|
};
|
|
6490
6684
|
|
|
@@ -6565,7 +6759,7 @@ var Editor = class {
|
|
|
6565
6759
|
const plugins = pluginInputs.map(parsePlugin);
|
|
6566
6760
|
const corePlugin = createCorePlugin(options.corePlugin);
|
|
6567
6761
|
const sortedPlugins = sortPluginsByDependencies([corePlugin, ...plugins]);
|
|
6568
|
-
const allDefs = [CommandMarker,
|
|
6762
|
+
const allDefs = [CommandMarker, Synced9];
|
|
6569
6763
|
for (const plugin of sortedPlugins) {
|
|
6570
6764
|
if (plugin.components) {
|
|
6571
6765
|
allDefs.push(...plugin.components);
|
|
@@ -6695,17 +6889,14 @@ var Editor = class {
|
|
|
6695
6889
|
* Call this after construction to run async setup.
|
|
6696
6890
|
*/
|
|
6697
6891
|
async initialize() {
|
|
6698
|
-
if (this.fonts.length > 0) {
|
|
6699
|
-
await this.fontLoader.loadFonts(this.fonts);
|
|
6700
|
-
}
|
|
6701
6892
|
Grid.copy(this.ctx, this.gridOptions);
|
|
6702
6893
|
Controls.copy(this.ctx, this.controlsOptions);
|
|
6703
6894
|
this.nextTick((ctx) => {
|
|
6704
|
-
const userEntity =
|
|
6705
|
-
|
|
6895
|
+
const userEntity = createEntity9(ctx);
|
|
6896
|
+
addComponent12(ctx, userEntity, Synced9, {
|
|
6706
6897
|
id: crypto.randomUUID()
|
|
6707
6898
|
});
|
|
6708
|
-
|
|
6899
|
+
addComponent12(ctx, userEntity, User, {
|
|
6709
6900
|
userId: this.userData.userId,
|
|
6710
6901
|
sessionId: this.userData.sessionId,
|
|
6711
6902
|
color: this.userData.color,
|
|
@@ -6719,6 +6910,29 @@ var Editor = class {
|
|
|
6719
6910
|
}
|
|
6720
6911
|
}
|
|
6721
6912
|
}
|
|
6913
|
+
/**
|
|
6914
|
+
* Load a single font family's stylesheet on demand, by its `name` (the CSS
|
|
6915
|
+
* font-family — the same key the picker and `Text.fontFamily` use). Looks the
|
|
6916
|
+
* family up in the configured `fonts` and injects its @font-face rules into
|
|
6917
|
+
* the document. Idempotent — the FontLoader dedups, so repeated calls for an
|
|
6918
|
+
* already-loaded (or in-flight) family are cheap no-ops. Unknown names are
|
|
6919
|
+
* ignored. This is how the editor scales to a large font library: nothing is
|
|
6920
|
+
* fetched until a text block actually displays/edits in that family.
|
|
6921
|
+
*/
|
|
6922
|
+
async loadFont(name) {
|
|
6923
|
+
if (!name) return;
|
|
6924
|
+
const family = this.fonts.find((f) => f.name === name);
|
|
6925
|
+
if (!family) return;
|
|
6926
|
+
try {
|
|
6927
|
+
await this.fontLoader.loadFont(family);
|
|
6928
|
+
} catch (err) {
|
|
6929
|
+
console.warn(`Failed to load font: ${name}`, err);
|
|
6930
|
+
}
|
|
6931
|
+
}
|
|
6932
|
+
/** Whether a font family's stylesheet has finished loading. */
|
|
6933
|
+
isFontLoaded(name) {
|
|
6934
|
+
return this.fontLoader.isLoaded(name);
|
|
6935
|
+
}
|
|
6722
6936
|
/**
|
|
6723
6937
|
* Run one frame of the editor loop.
|
|
6724
6938
|
*
|
|
@@ -6933,11 +7147,14 @@ export {
|
|
|
6933
7147
|
Key,
|
|
6934
7148
|
Keybind,
|
|
6935
7149
|
Keyboard,
|
|
7150
|
+
Layer,
|
|
6936
7151
|
MAX_HIT_ARCS,
|
|
6937
7152
|
MAX_HIT_CAPSULES,
|
|
7153
|
+
MAX_HIT_POLYGON_POINTS,
|
|
6938
7154
|
MainThreadSystem2 as MainThreadSystem,
|
|
6939
7155
|
Mouse,
|
|
6940
7156
|
Opacity,
|
|
7157
|
+
PlaceBlockEvent,
|
|
6941
7158
|
Pointer,
|
|
6942
7159
|
PointerButton,
|
|
6943
7160
|
PointerType,
|
|
@@ -6971,7 +7188,7 @@ export {
|
|
|
6971
7188
|
StartTransformBoxEdit,
|
|
6972
7189
|
Stratum,
|
|
6973
7190
|
StrokeKind,
|
|
6974
|
-
|
|
7191
|
+
Synced10 as Synced,
|
|
6975
7192
|
Text,
|
|
6976
7193
|
TextAlignment,
|
|
6977
7194
|
Tick,
|
|
@@ -6990,16 +7207,17 @@ export {
|
|
|
6990
7207
|
UserData,
|
|
6991
7208
|
VerticalAlign,
|
|
6992
7209
|
VerticalAlignment,
|
|
6993
|
-
|
|
7210
|
+
addComponent13 as addComponent,
|
|
6994
7211
|
canBlockEdit,
|
|
6995
7212
|
canBlockInteract,
|
|
6996
7213
|
cascadeDelete,
|
|
6997
7214
|
clearPointerTrackingState,
|
|
6998
7215
|
compareBlockOrder,
|
|
6999
7216
|
convertRefsToUuids,
|
|
7217
|
+
createBlock,
|
|
7000
7218
|
createCorePlugin,
|
|
7001
|
-
|
|
7002
|
-
|
|
7219
|
+
createEntity10 as createEntity,
|
|
7220
|
+
defineCanvasComponent23 as defineCanvasComponent,
|
|
7003
7221
|
defineCanvasSingleton3 as defineCanvasSingleton,
|
|
7004
7222
|
defineCommand,
|
|
7005
7223
|
defineEditorState,
|
|
@@ -7009,7 +7227,7 @@ export {
|
|
|
7009
7227
|
deselectAll,
|
|
7010
7228
|
deselectBlock,
|
|
7011
7229
|
detectEmbedProvider,
|
|
7012
|
-
|
|
7230
|
+
field37 as field,
|
|
7013
7231
|
findFrameAtPoint,
|
|
7014
7232
|
generateUuidBySeed,
|
|
7015
7233
|
getBackrefs5 as getBackrefs,
|
|
@@ -7027,19 +7245,21 @@ export {
|
|
|
7027
7245
|
getResources15 as getResources,
|
|
7028
7246
|
getTopmostBlockAtPoint,
|
|
7029
7247
|
getWorldPosition,
|
|
7030
|
-
|
|
7248
|
+
hasComponent21 as hasComponent,
|
|
7031
7249
|
intersectAabb,
|
|
7032
7250
|
intersectCapsule,
|
|
7033
7251
|
intersectPoint,
|
|
7034
7252
|
isAlive3 as isAlive,
|
|
7035
7253
|
isAncestor,
|
|
7036
7254
|
isHeldByRemote,
|
|
7255
|
+
isLayerInteractive,
|
|
7037
7256
|
isReadonly,
|
|
7038
7257
|
on,
|
|
7039
7258
|
parsePlugin,
|
|
7040
7259
|
removeComponent7 as removeComponent,
|
|
7041
7260
|
removeEntity7 as removeEntity,
|
|
7042
7261
|
resolveEmbedUrl,
|
|
7262
|
+
resolveLayerRank,
|
|
7043
7263
|
resolveRefFields,
|
|
7044
7264
|
runMachine,
|
|
7045
7265
|
selectAll,
|