@woven-canvas/core 1.0.14 → 1.0.15

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/build/index.cjs CHANGED
@@ -436,6 +436,12 @@ var ControlsOptions = import_zod.z.object({
436
436
  * @default 'select'
437
437
  */
438
438
  leftMouseTool: import_zod.z.string().max(32).default("select"),
439
+ /**
440
+ * Tool activated by left mouse button while the space bar is held.
441
+ * Set to an empty string to disable the remap.
442
+ * @default 'hand'
443
+ */
444
+ spaceLeftMouseTool: import_zod.z.string().max(32).default("hand"),
439
445
  /**
440
446
  * Tool activated by middle mouse button.
441
447
  * @default 'hand'
@@ -2152,25 +2158,335 @@ var CameraDef = class extends import_canvas_store29.CanvasSingletonDef {
2152
2158
  var Camera = new CameraDef();
2153
2159
 
2154
2160
  // src/singletons/Controls.ts
2161
+ var import_canvas_store31 = require("@woven-ecs/canvas-store");
2162
+ var import_core25 = require("@woven-ecs/core");
2163
+
2164
+ // src/singletons/Keyboard.ts
2155
2165
  var import_canvas_store30 = require("@woven-ecs/canvas-store");
2156
2166
  var import_core24 = require("@woven-ecs/core");
2167
+ var KEY_BUFFER_SIZE = 32;
2168
+ var KeyboardSchema = {
2169
+ /**
2170
+ * Buffer where each bit represents whether a key is currently pressed.
2171
+ * Uses field.buffer for zero-allocation subarray views.
2172
+ */
2173
+ keysDown: import_core24.field.buffer(import_core24.field.uint8()).size(KEY_BUFFER_SIZE),
2174
+ /**
2175
+ * Buffer for key-down triggers (true for exactly 1 frame when key is pressed).
2176
+ * Uses field.buffer for zero-allocation subarray views.
2177
+ */
2178
+ keysDownTrigger: import_core24.field.buffer(import_core24.field.uint8()).size(KEY_BUFFER_SIZE),
2179
+ /**
2180
+ * Buffer for key-up triggers (true for exactly 1 frame when key is released).
2181
+ * Uses field.buffer for zero-allocation subarray views.
2182
+ */
2183
+ keysUpTrigger: import_core24.field.buffer(import_core24.field.uint8()).size(KEY_BUFFER_SIZE),
2184
+ /** Common modifier - Shift key is down */
2185
+ shiftDown: import_core24.field.boolean().default(false),
2186
+ /** Common modifier - Alt/Option key is down */
2187
+ altDown: import_core24.field.boolean().default(false),
2188
+ /** Common modifier - Ctrl (Windows/Linux) or Cmd (Mac) is down */
2189
+ modDown: import_core24.field.boolean().default(false)
2190
+ };
2191
+ function getBit(buffer, bitIndex) {
2192
+ if (bitIndex < 0 || bitIndex >= buffer.length * 8) return false;
2193
+ const byteIndex = Math.floor(bitIndex / 8);
2194
+ const bitOffset = bitIndex % 8;
2195
+ return (buffer[byteIndex] & 1 << bitOffset) !== 0;
2196
+ }
2197
+ var KeyboardDef = class extends import_canvas_store30.CanvasSingletonDef {
2198
+ constructor() {
2199
+ super({ name: "keyboard" }, KeyboardSchema);
2200
+ }
2201
+ /**
2202
+ * Check if a key is currently pressed.
2203
+ * @param ctx - Editor context
2204
+ * @param key - The key index to check (use Key.A, Key.Space, etc.)
2205
+ */
2206
+ isKeyDown(ctx, key) {
2207
+ return getBit(this.read(ctx).keysDown, key);
2208
+ }
2209
+ /**
2210
+ * Check if a key was just pressed this frame.
2211
+ * @param ctx - Editor context
2212
+ * @param key - The key index to check (use Key.A, Key.Space, etc.)
2213
+ */
2214
+ isKeyDownTrigger(ctx, key) {
2215
+ return getBit(this.read(ctx).keysDownTrigger, key);
2216
+ }
2217
+ /**
2218
+ * Check if a key was just released this frame.
2219
+ * @param ctx - Editor context
2220
+ * @param key - The key index to check (use Key.A, Key.Space, etc.)
2221
+ */
2222
+ isKeyUpTrigger(ctx, key) {
2223
+ return getBit(this.read(ctx).keysUpTrigger, key);
2224
+ }
2225
+ /**
2226
+ * Reset all keyboard state.
2227
+ * Clears all key states and modifier flags.
2228
+ */
2229
+ reset(ctx) {
2230
+ const keyboard = this.write(ctx);
2231
+ clearBits(keyboard.keysDown);
2232
+ clearBits(keyboard.keysDownTrigger);
2233
+ clearBits(keyboard.keysUpTrigger);
2234
+ keyboard.shiftDown = false;
2235
+ keyboard.altDown = false;
2236
+ keyboard.modDown = false;
2237
+ }
2238
+ };
2239
+ var Keyboard = new KeyboardDef();
2240
+ function setBit(buffer, bitIndex, value) {
2241
+ if (bitIndex < 0 || bitIndex >= buffer.length * 8) return;
2242
+ const byteIndex = Math.floor(bitIndex / 8);
2243
+ const bitOffset = bitIndex % 8;
2244
+ if (value) {
2245
+ buffer[byteIndex] |= 1 << bitOffset;
2246
+ } else {
2247
+ buffer[byteIndex] &= ~(1 << bitOffset);
2248
+ }
2249
+ }
2250
+ function clearBits(buffer) {
2251
+ for (let i = 0; i < buffer.length; i++) {
2252
+ buffer[i] = 0;
2253
+ }
2254
+ }
2255
+ var codeToIndex = {
2256
+ // Letters (0-25)
2257
+ KeyA: 0,
2258
+ KeyB: 1,
2259
+ KeyC: 2,
2260
+ KeyD: 3,
2261
+ KeyE: 4,
2262
+ KeyF: 5,
2263
+ KeyG: 6,
2264
+ KeyH: 7,
2265
+ KeyI: 8,
2266
+ KeyJ: 9,
2267
+ KeyK: 10,
2268
+ KeyL: 11,
2269
+ KeyM: 12,
2270
+ KeyN: 13,
2271
+ KeyO: 14,
2272
+ KeyP: 15,
2273
+ KeyQ: 16,
2274
+ KeyR: 17,
2275
+ KeyS: 18,
2276
+ KeyT: 19,
2277
+ KeyU: 20,
2278
+ KeyV: 21,
2279
+ KeyW: 22,
2280
+ KeyX: 23,
2281
+ KeyY: 24,
2282
+ KeyZ: 25,
2283
+ // Numbers (26-35)
2284
+ Digit0: 26,
2285
+ Digit1: 27,
2286
+ Digit2: 28,
2287
+ Digit3: 29,
2288
+ Digit4: 30,
2289
+ Digit5: 31,
2290
+ Digit6: 32,
2291
+ Digit7: 33,
2292
+ Digit8: 34,
2293
+ Digit9: 35,
2294
+ // Function keys (36-47)
2295
+ F1: 36,
2296
+ F2: 37,
2297
+ F3: 38,
2298
+ F4: 39,
2299
+ F5: 40,
2300
+ F6: 41,
2301
+ F7: 42,
2302
+ F8: 43,
2303
+ F9: 44,
2304
+ F10: 45,
2305
+ F11: 46,
2306
+ F12: 47,
2307
+ // Modifiers (48-51)
2308
+ ShiftLeft: 48,
2309
+ ShiftRight: 49,
2310
+ ControlLeft: 50,
2311
+ ControlRight: 51,
2312
+ AltLeft: 52,
2313
+ AltRight: 53,
2314
+ MetaLeft: 54,
2315
+ MetaRight: 55,
2316
+ // Navigation (56-71)
2317
+ Escape: 56,
2318
+ Space: 57,
2319
+ Enter: 58,
2320
+ Tab: 59,
2321
+ Backspace: 60,
2322
+ Delete: 61,
2323
+ ArrowLeft: 62,
2324
+ ArrowUp: 63,
2325
+ ArrowRight: 64,
2326
+ ArrowDown: 65,
2327
+ Home: 66,
2328
+ End: 67,
2329
+ PageUp: 68,
2330
+ PageDown: 69,
2331
+ Insert: 70,
2332
+ // Punctuation (72-83)
2333
+ Semicolon: 72,
2334
+ Equal: 73,
2335
+ Comma: 74,
2336
+ Minus: 75,
2337
+ Period: 76,
2338
+ Slash: 77,
2339
+ Backquote: 78,
2340
+ BracketLeft: 79,
2341
+ Backslash: 80,
2342
+ BracketRight: 81,
2343
+ Quote: 82,
2344
+ // Numpad (84-99)
2345
+ Numpad0: 84,
2346
+ Numpad1: 85,
2347
+ Numpad2: 86,
2348
+ Numpad3: 87,
2349
+ Numpad4: 88,
2350
+ Numpad5: 89,
2351
+ Numpad6: 90,
2352
+ Numpad7: 91,
2353
+ Numpad8: 92,
2354
+ Numpad9: 93,
2355
+ NumpadAdd: 94,
2356
+ NumpadSubtract: 95,
2357
+ NumpadMultiply: 96,
2358
+ NumpadDivide: 97,
2359
+ NumpadDecimal: 98,
2360
+ NumpadEnter: 99
2361
+ };
2362
+ var Key = {
2363
+ // Letters
2364
+ A: codeToIndex.KeyA,
2365
+ B: codeToIndex.KeyB,
2366
+ C: codeToIndex.KeyC,
2367
+ D: codeToIndex.KeyD,
2368
+ E: codeToIndex.KeyE,
2369
+ F: codeToIndex.KeyF,
2370
+ G: codeToIndex.KeyG,
2371
+ H: codeToIndex.KeyH,
2372
+ I: codeToIndex.KeyI,
2373
+ J: codeToIndex.KeyJ,
2374
+ K: codeToIndex.KeyK,
2375
+ L: codeToIndex.KeyL,
2376
+ M: codeToIndex.KeyM,
2377
+ N: codeToIndex.KeyN,
2378
+ O: codeToIndex.KeyO,
2379
+ P: codeToIndex.KeyP,
2380
+ Q: codeToIndex.KeyQ,
2381
+ R: codeToIndex.KeyR,
2382
+ S: codeToIndex.KeyS,
2383
+ T: codeToIndex.KeyT,
2384
+ U: codeToIndex.KeyU,
2385
+ V: codeToIndex.KeyV,
2386
+ W: codeToIndex.KeyW,
2387
+ X: codeToIndex.KeyX,
2388
+ Y: codeToIndex.KeyY,
2389
+ Z: codeToIndex.KeyZ,
2390
+ // Numbers
2391
+ Digit0: codeToIndex.Digit0,
2392
+ Digit1: codeToIndex.Digit1,
2393
+ Digit2: codeToIndex.Digit2,
2394
+ Digit3: codeToIndex.Digit3,
2395
+ Digit4: codeToIndex.Digit4,
2396
+ Digit5: codeToIndex.Digit5,
2397
+ Digit6: codeToIndex.Digit6,
2398
+ Digit7: codeToIndex.Digit7,
2399
+ Digit8: codeToIndex.Digit8,
2400
+ Digit9: codeToIndex.Digit9,
2401
+ // Function keys
2402
+ F1: codeToIndex.F1,
2403
+ F2: codeToIndex.F2,
2404
+ F3: codeToIndex.F3,
2405
+ F4: codeToIndex.F4,
2406
+ F5: codeToIndex.F5,
2407
+ F6: codeToIndex.F6,
2408
+ F7: codeToIndex.F7,
2409
+ F8: codeToIndex.F8,
2410
+ F9: codeToIndex.F9,
2411
+ F10: codeToIndex.F10,
2412
+ F11: codeToIndex.F11,
2413
+ F12: codeToIndex.F12,
2414
+ // Modifiers
2415
+ ShiftLeft: codeToIndex.ShiftLeft,
2416
+ ShiftRight: codeToIndex.ShiftRight,
2417
+ ControlLeft: codeToIndex.ControlLeft,
2418
+ ControlRight: codeToIndex.ControlRight,
2419
+ AltLeft: codeToIndex.AltLeft,
2420
+ AltRight: codeToIndex.AltRight,
2421
+ MetaLeft: codeToIndex.MetaLeft,
2422
+ MetaRight: codeToIndex.MetaRight,
2423
+ // Navigation
2424
+ Escape: codeToIndex.Escape,
2425
+ Space: codeToIndex.Space,
2426
+ Enter: codeToIndex.Enter,
2427
+ Tab: codeToIndex.Tab,
2428
+ Backspace: codeToIndex.Backspace,
2429
+ Delete: codeToIndex.Delete,
2430
+ ArrowLeft: codeToIndex.ArrowLeft,
2431
+ ArrowUp: codeToIndex.ArrowUp,
2432
+ ArrowRight: codeToIndex.ArrowRight,
2433
+ ArrowDown: codeToIndex.ArrowDown,
2434
+ Home: codeToIndex.Home,
2435
+ End: codeToIndex.End,
2436
+ PageUp: codeToIndex.PageUp,
2437
+ PageDown: codeToIndex.PageDown,
2438
+ Insert: codeToIndex.Insert,
2439
+ // Punctuation
2440
+ Semicolon: codeToIndex.Semicolon,
2441
+ Equal: codeToIndex.Equal,
2442
+ Comma: codeToIndex.Comma,
2443
+ Minus: codeToIndex.Minus,
2444
+ Period: codeToIndex.Period,
2445
+ Slash: codeToIndex.Slash,
2446
+ Backquote: codeToIndex.Backquote,
2447
+ BracketLeft: codeToIndex.BracketLeft,
2448
+ Backslash: codeToIndex.Backslash,
2449
+ BracketRight: codeToIndex.BracketRight,
2450
+ Quote: codeToIndex.Quote,
2451
+ // Numpad
2452
+ Numpad0: codeToIndex.Numpad0,
2453
+ Numpad1: codeToIndex.Numpad1,
2454
+ Numpad2: codeToIndex.Numpad2,
2455
+ Numpad3: codeToIndex.Numpad3,
2456
+ Numpad4: codeToIndex.Numpad4,
2457
+ Numpad5: codeToIndex.Numpad5,
2458
+ Numpad6: codeToIndex.Numpad6,
2459
+ Numpad7: codeToIndex.Numpad7,
2460
+ Numpad8: codeToIndex.Numpad8,
2461
+ Numpad9: codeToIndex.Numpad9,
2462
+ NumpadAdd: codeToIndex.NumpadAdd,
2463
+ NumpadSubtract: codeToIndex.NumpadSubtract,
2464
+ NumpadMultiply: codeToIndex.NumpadMultiply,
2465
+ NumpadDivide: codeToIndex.NumpadDivide,
2466
+ NumpadDecimal: codeToIndex.NumpadDecimal,
2467
+ NumpadEnter: codeToIndex.NumpadEnter
2468
+ };
2469
+
2470
+ // src/singletons/Controls.ts
2157
2471
  var ControlsSchema = {
2158
2472
  /** Tool activated by left mouse button */
2159
- leftMouseTool: import_core24.field.string().max(32).default("select"),
2473
+ leftMouseTool: import_core25.field.string().max(32).default("select"),
2474
+ /** Tool activated by left mouse button while the space bar is held (empty string = no remap) */
2475
+ spaceLeftMouseTool: import_core25.field.string().max(32).default("hand"),
2160
2476
  /** Tool activated by middle mouse button */
2161
- middleMouseTool: import_core24.field.string().max(32).default("hand"),
2477
+ middleMouseTool: import_core25.field.string().max(32).default("hand"),
2162
2478
  /** Tool activated by right mouse button */
2163
- rightMouseTool: import_core24.field.string().max(32).default("hand"),
2479
+ rightMouseTool: import_core25.field.string().max(32).default("hand"),
2164
2480
  /** Tool activated by mouse wheel */
2165
- wheelTool: import_core24.field.string().max(32).default("scroll"),
2481
+ wheelTool: import_core25.field.string().max(32).default("scroll"),
2166
2482
  /** Tool activated by mouse wheel with modifier key held */
2167
- modWheelTool: import_core24.field.string().max(32).default("zoom"),
2483
+ modWheelTool: import_core25.field.string().max(32).default("zoom"),
2168
2484
  /** JSON snapshot of block to place on next click (empty string = no placement active) */
2169
- heldSnapshot: import_core24.field.string().max(65536).default(""),
2485
+ heldSnapshot: import_core25.field.string().max(65536).default(""),
2170
2486
  /** User-facing tool name for UI highlighting (may differ from leftMouseTool during draw/drag-out) */
2171
- activeToolName: import_core24.field.string().max(32).default("select")
2487
+ activeToolName: import_core25.field.string().max(32).default("select")
2172
2488
  };
2173
- var ControlsDef = class extends import_canvas_store30.CanvasSingletonDef {
2489
+ var ControlsDef = class extends import_canvas_store31.CanvasSingletonDef {
2174
2490
  constructor() {
2175
2491
  super({ name: "controls" }, ControlsSchema);
2176
2492
  }
@@ -2183,7 +2499,9 @@ var ControlsDef = class extends import_canvas_store30.CanvasSingletonDef {
2183
2499
  getButtons(ctx, ...tools) {
2184
2500
  const controls = this.read(ctx);
2185
2501
  const buttons = [];
2186
- if (tools.includes(controls.leftMouseTool)) {
2502
+ const spaceRemap = controls.spaceLeftMouseTool !== "" && Keyboard.isKeyDown(ctx, Key.Space);
2503
+ const leftTool = spaceRemap ? controls.spaceLeftMouseTool : controls.leftMouseTool;
2504
+ if (tools.includes(leftTool)) {
2187
2505
  buttons.push(PointerButton.Left);
2188
2506
  }
2189
2507
  if (tools.includes(controls.middleMouseTool)) {
@@ -2209,19 +2527,19 @@ var ControlsDef = class extends import_canvas_store30.CanvasSingletonDef {
2209
2527
  var Controls = new ControlsDef();
2210
2528
 
2211
2529
  // src/singletons/Cursor.ts
2212
- var import_canvas_store31 = require("@woven-ecs/canvas-store");
2213
- var import_core25 = require("@woven-ecs/core");
2530
+ var import_canvas_store32 = require("@woven-ecs/canvas-store");
2531
+ var import_core26 = require("@woven-ecs/core");
2214
2532
  var CursorSchema = {
2215
2533
  /** Base cursor kind (from current tool) */
2216
- cursorKind: import_core25.field.string().max(64).default("select"),
2534
+ cursorKind: import_core26.field.string().max(64).default("select"),
2217
2535
  /** Base cursor rotation in radians */
2218
- rotation: import_core25.field.float64().default(0),
2536
+ rotation: import_core26.field.float64().default(0),
2219
2537
  /** Context-specific cursor kind (overrides cursorKind when set, e.g., during drag/hover) */
2220
- contextCursorKind: import_core25.field.string().max(64).default(""),
2538
+ contextCursorKind: import_core26.field.string().max(64).default(""),
2221
2539
  /** Context cursor rotation in radians */
2222
- contextRotation: import_core25.field.float64().default(0)
2540
+ contextRotation: import_core26.field.float64().default(0)
2223
2541
  };
2224
- var CursorDef2 = class extends import_canvas_store31.CanvasSingletonDef {
2542
+ var CursorDef2 = class extends import_canvas_store32.CanvasSingletonDef {
2225
2543
  constructor() {
2226
2544
  super({ name: "cursor" }, CursorSchema);
2227
2545
  }
@@ -2266,10 +2584,10 @@ var CursorDef2 = class extends import_canvas_store31.CanvasSingletonDef {
2266
2584
  var Cursor = new CursorDef2();
2267
2585
 
2268
2586
  // src/singletons/FrameContainmentState.ts
2269
- var import_core26 = require("@woven-ecs/core");
2587
+ var import_core27 = require("@woven-ecs/core");
2270
2588
 
2271
2589
  // src/EditorStateDef.ts
2272
- var import_canvas_store32 = require("@woven-ecs/canvas-store");
2590
+ var import_canvas_store33 = require("@woven-ecs/canvas-store");
2273
2591
 
2274
2592
  // src/machine.ts
2275
2593
  var import_xstate = require("xstate");
@@ -2297,7 +2615,7 @@ function runMachine(machine, currentState, context, events) {
2297
2615
  }
2298
2616
 
2299
2617
  // src/EditorStateDef.ts
2300
- var EditorStateDef = class extends import_canvas_store32.CanvasSingletonDef {
2618
+ var EditorStateDef = class extends import_canvas_store33.CanvasSingletonDef {
2301
2619
  constructor(name, schema) {
2302
2620
  super({ name, sync: "none" }, schema);
2303
2621
  }
@@ -2374,29 +2692,29 @@ function defineEditorState(name, schema) {
2374
2692
  // src/singletons/FrameContainmentState.ts
2375
2693
  var FrameContainmentState = defineEditorState("frameContainmentState", {
2376
2694
  /** Current state machine state */
2377
- state: import_core26.field.string().max(16).default(FrameContainmentStateEnum.Idle),
2695
+ state: import_core27.field.string().max(16).default(FrameContainmentStateEnum.Idle),
2378
2696
  /** EntityId of the frame currently highlighted as a drop target, or null */
2379
- highlightedFrame: import_core26.field.ref()
2697
+ highlightedFrame: import_core27.field.ref()
2380
2698
  });
2381
2699
 
2382
2700
  // src/singletons/Grid.ts
2383
- var import_canvas_store33 = require("@woven-ecs/canvas-store");
2384
- var import_core27 = require("@woven-ecs/core");
2701
+ var import_canvas_store34 = require("@woven-ecs/canvas-store");
2702
+ var import_core28 = require("@woven-ecs/core");
2385
2703
  var GridSchema = {
2386
2704
  /** Whether grid snapping is enabled */
2387
- enabled: import_core27.field.boolean().default(false),
2705
+ enabled: import_core28.field.boolean().default(false),
2388
2706
  /** Whether resized/rotated objects must stay aligned to the grid */
2389
- strict: import_core27.field.boolean().default(false),
2707
+ strict: import_core28.field.boolean().default(false),
2390
2708
  /** Width of each grid column in world units */
2391
- colWidth: import_core27.field.float64().default(20),
2709
+ colWidth: import_core28.field.float64().default(20),
2392
2710
  /** Height of each grid row in world units */
2393
- rowHeight: import_core27.field.float64().default(20),
2711
+ rowHeight: import_core28.field.float64().default(20),
2394
2712
  /** Angular snap increment in radians when grid is enabled */
2395
- snapAngleRad: import_core27.field.float64().default(Math.PI / 36),
2713
+ snapAngleRad: import_core28.field.float64().default(Math.PI / 36),
2396
2714
  /** Angular snap increment in radians when shift key is held */
2397
- shiftSnapAngleRad: import_core27.field.float64().default(Math.PI / 12)
2715
+ shiftSnapAngleRad: import_core28.field.float64().default(Math.PI / 12)
2398
2716
  };
2399
- var GridDef = class extends import_canvas_store33.CanvasSingletonDef {
2717
+ var GridDef = class extends import_canvas_store34.CanvasSingletonDef {
2400
2718
  constructor() {
2401
2719
  super({ name: "grid" }, GridSchema);
2402
2720
  }
@@ -2456,17 +2774,17 @@ var GridDef = class extends import_canvas_store33.CanvasSingletonDef {
2456
2774
  var Grid = new GridDef();
2457
2775
 
2458
2776
  // src/singletons/Intersect.ts
2459
- var import_canvas_store34 = require("@woven-ecs/canvas-store");
2460
- var import_core28 = require("@woven-ecs/core");
2777
+ var import_canvas_store35 = require("@woven-ecs/canvas-store");
2778
+ var import_core29 = require("@woven-ecs/core");
2461
2779
  var IntersectSchema = {
2462
2780
  // Store up to 5 intersected entity IDs
2463
- entity1: import_core28.field.ref(),
2464
- entity2: import_core28.field.ref(),
2465
- entity3: import_core28.field.ref(),
2466
- entity4: import_core28.field.ref(),
2467
- entity5: import_core28.field.ref()
2781
+ entity1: import_core29.field.ref(),
2782
+ entity2: import_core29.field.ref(),
2783
+ entity3: import_core29.field.ref(),
2784
+ entity4: import_core29.field.ref(),
2785
+ entity5: import_core29.field.ref()
2468
2786
  };
2469
- var IntersectDef = class extends import_canvas_store34.CanvasSingletonDef {
2787
+ var IntersectDef = class extends import_canvas_store35.CanvasSingletonDef {
2470
2788
  constructor() {
2471
2789
  super({ name: "intersect" }, IntersectSchema);
2472
2790
  }
@@ -2493,332 +2811,26 @@ var IntersectDef = class extends import_canvas_store34.CanvasSingletonDef {
2493
2811
  * Set intersected entities from an array.
2494
2812
  */
2495
2813
  setAll(ctx, entities) {
2496
- const intersect = this.write(ctx);
2497
- intersect.entity1 = entities[0] ?? null;
2498
- intersect.entity2 = entities[1] ?? null;
2499
- intersect.entity3 = entities[2] ?? null;
2500
- intersect.entity4 = entities[3] ?? null;
2501
- intersect.entity5 = entities[4] ?? null;
2502
- }
2503
- /**
2504
- * Clear all intersections.
2505
- */
2506
- clear(ctx) {
2507
- const intersect = this.write(ctx);
2508
- intersect.entity1 = null;
2509
- intersect.entity2 = null;
2510
- intersect.entity3 = null;
2511
- intersect.entity4 = null;
2512
- intersect.entity5 = null;
2513
- }
2514
- };
2515
- var Intersect = new IntersectDef();
2516
-
2517
- // src/singletons/Keyboard.ts
2518
- var import_canvas_store35 = require("@woven-ecs/canvas-store");
2519
- var import_core29 = require("@woven-ecs/core");
2520
- var KEY_BUFFER_SIZE = 32;
2521
- var KeyboardSchema = {
2522
- /**
2523
- * Buffer where each bit represents whether a key is currently pressed.
2524
- * Uses field.buffer for zero-allocation subarray views.
2525
- */
2526
- keysDown: import_core29.field.buffer(import_core29.field.uint8()).size(KEY_BUFFER_SIZE),
2527
- /**
2528
- * Buffer for key-down triggers (true for exactly 1 frame when key is pressed).
2529
- * Uses field.buffer for zero-allocation subarray views.
2530
- */
2531
- keysDownTrigger: import_core29.field.buffer(import_core29.field.uint8()).size(KEY_BUFFER_SIZE),
2532
- /**
2533
- * Buffer for key-up triggers (true for exactly 1 frame when key is released).
2534
- * Uses field.buffer for zero-allocation subarray views.
2535
- */
2536
- keysUpTrigger: import_core29.field.buffer(import_core29.field.uint8()).size(KEY_BUFFER_SIZE),
2537
- /** Common modifier - Shift key is down */
2538
- shiftDown: import_core29.field.boolean().default(false),
2539
- /** Common modifier - Alt/Option key is down */
2540
- altDown: import_core29.field.boolean().default(false),
2541
- /** Common modifier - Ctrl (Windows/Linux) or Cmd (Mac) is down */
2542
- modDown: import_core29.field.boolean().default(false)
2543
- };
2544
- function getBit(buffer, bitIndex) {
2545
- if (bitIndex < 0 || bitIndex >= buffer.length * 8) return false;
2546
- const byteIndex = Math.floor(bitIndex / 8);
2547
- const bitOffset = bitIndex % 8;
2548
- return (buffer[byteIndex] & 1 << bitOffset) !== 0;
2549
- }
2550
- var KeyboardDef = class extends import_canvas_store35.CanvasSingletonDef {
2551
- constructor() {
2552
- super({ name: "keyboard" }, KeyboardSchema);
2553
- }
2554
- /**
2555
- * Check if a key is currently pressed.
2556
- * @param ctx - Editor context
2557
- * @param key - The key index to check (use Key.A, Key.Space, etc.)
2558
- */
2559
- isKeyDown(ctx, key) {
2560
- return getBit(this.read(ctx).keysDown, key);
2561
- }
2562
- /**
2563
- * Check if a key was just pressed this frame.
2564
- * @param ctx - Editor context
2565
- * @param key - The key index to check (use Key.A, Key.Space, etc.)
2566
- */
2567
- isKeyDownTrigger(ctx, key) {
2568
- return getBit(this.read(ctx).keysDownTrigger, key);
2569
- }
2570
- /**
2571
- * Check if a key was just released this frame.
2572
- * @param ctx - Editor context
2573
- * @param key - The key index to check (use Key.A, Key.Space, etc.)
2574
- */
2575
- isKeyUpTrigger(ctx, key) {
2576
- return getBit(this.read(ctx).keysUpTrigger, key);
2814
+ const intersect = this.write(ctx);
2815
+ intersect.entity1 = entities[0] ?? null;
2816
+ intersect.entity2 = entities[1] ?? null;
2817
+ intersect.entity3 = entities[2] ?? null;
2818
+ intersect.entity4 = entities[3] ?? null;
2819
+ intersect.entity5 = entities[4] ?? null;
2577
2820
  }
2578
2821
  /**
2579
- * Reset all keyboard state.
2580
- * Clears all key states and modifier flags.
2822
+ * Clear all intersections.
2581
2823
  */
2582
- reset(ctx) {
2583
- const keyboard = this.write(ctx);
2584
- clearBits(keyboard.keysDown);
2585
- clearBits(keyboard.keysDownTrigger);
2586
- clearBits(keyboard.keysUpTrigger);
2587
- keyboard.shiftDown = false;
2588
- keyboard.altDown = false;
2589
- keyboard.modDown = false;
2590
- }
2591
- };
2592
- var Keyboard = new KeyboardDef();
2593
- function setBit(buffer, bitIndex, value) {
2594
- if (bitIndex < 0 || bitIndex >= buffer.length * 8) return;
2595
- const byteIndex = Math.floor(bitIndex / 8);
2596
- const bitOffset = bitIndex % 8;
2597
- if (value) {
2598
- buffer[byteIndex] |= 1 << bitOffset;
2599
- } else {
2600
- buffer[byteIndex] &= ~(1 << bitOffset);
2601
- }
2602
- }
2603
- function clearBits(buffer) {
2604
- for (let i = 0; i < buffer.length; i++) {
2605
- buffer[i] = 0;
2824
+ clear(ctx) {
2825
+ const intersect = this.write(ctx);
2826
+ intersect.entity1 = null;
2827
+ intersect.entity2 = null;
2828
+ intersect.entity3 = null;
2829
+ intersect.entity4 = null;
2830
+ intersect.entity5 = null;
2606
2831
  }
2607
- }
2608
- var codeToIndex = {
2609
- // Letters (0-25)
2610
- KeyA: 0,
2611
- KeyB: 1,
2612
- KeyC: 2,
2613
- KeyD: 3,
2614
- KeyE: 4,
2615
- KeyF: 5,
2616
- KeyG: 6,
2617
- KeyH: 7,
2618
- KeyI: 8,
2619
- KeyJ: 9,
2620
- KeyK: 10,
2621
- KeyL: 11,
2622
- KeyM: 12,
2623
- KeyN: 13,
2624
- KeyO: 14,
2625
- KeyP: 15,
2626
- KeyQ: 16,
2627
- KeyR: 17,
2628
- KeyS: 18,
2629
- KeyT: 19,
2630
- KeyU: 20,
2631
- KeyV: 21,
2632
- KeyW: 22,
2633
- KeyX: 23,
2634
- KeyY: 24,
2635
- KeyZ: 25,
2636
- // Numbers (26-35)
2637
- Digit0: 26,
2638
- Digit1: 27,
2639
- Digit2: 28,
2640
- Digit3: 29,
2641
- Digit4: 30,
2642
- Digit5: 31,
2643
- Digit6: 32,
2644
- Digit7: 33,
2645
- Digit8: 34,
2646
- Digit9: 35,
2647
- // Function keys (36-47)
2648
- F1: 36,
2649
- F2: 37,
2650
- F3: 38,
2651
- F4: 39,
2652
- F5: 40,
2653
- F6: 41,
2654
- F7: 42,
2655
- F8: 43,
2656
- F9: 44,
2657
- F10: 45,
2658
- F11: 46,
2659
- F12: 47,
2660
- // Modifiers (48-51)
2661
- ShiftLeft: 48,
2662
- ShiftRight: 49,
2663
- ControlLeft: 50,
2664
- ControlRight: 51,
2665
- AltLeft: 52,
2666
- AltRight: 53,
2667
- MetaLeft: 54,
2668
- MetaRight: 55,
2669
- // Navigation (56-71)
2670
- Escape: 56,
2671
- Space: 57,
2672
- Enter: 58,
2673
- Tab: 59,
2674
- Backspace: 60,
2675
- Delete: 61,
2676
- ArrowLeft: 62,
2677
- ArrowUp: 63,
2678
- ArrowRight: 64,
2679
- ArrowDown: 65,
2680
- Home: 66,
2681
- End: 67,
2682
- PageUp: 68,
2683
- PageDown: 69,
2684
- Insert: 70,
2685
- // Punctuation (72-83)
2686
- Semicolon: 72,
2687
- Equal: 73,
2688
- Comma: 74,
2689
- Minus: 75,
2690
- Period: 76,
2691
- Slash: 77,
2692
- Backquote: 78,
2693
- BracketLeft: 79,
2694
- Backslash: 80,
2695
- BracketRight: 81,
2696
- Quote: 82,
2697
- // Numpad (84-99)
2698
- Numpad0: 84,
2699
- Numpad1: 85,
2700
- Numpad2: 86,
2701
- Numpad3: 87,
2702
- Numpad4: 88,
2703
- Numpad5: 89,
2704
- Numpad6: 90,
2705
- Numpad7: 91,
2706
- Numpad8: 92,
2707
- Numpad9: 93,
2708
- NumpadAdd: 94,
2709
- NumpadSubtract: 95,
2710
- NumpadMultiply: 96,
2711
- NumpadDivide: 97,
2712
- NumpadDecimal: 98,
2713
- NumpadEnter: 99
2714
- };
2715
- var Key = {
2716
- // Letters
2717
- A: codeToIndex.KeyA,
2718
- B: codeToIndex.KeyB,
2719
- C: codeToIndex.KeyC,
2720
- D: codeToIndex.KeyD,
2721
- E: codeToIndex.KeyE,
2722
- F: codeToIndex.KeyF,
2723
- G: codeToIndex.KeyG,
2724
- H: codeToIndex.KeyH,
2725
- I: codeToIndex.KeyI,
2726
- J: codeToIndex.KeyJ,
2727
- K: codeToIndex.KeyK,
2728
- L: codeToIndex.KeyL,
2729
- M: codeToIndex.KeyM,
2730
- N: codeToIndex.KeyN,
2731
- O: codeToIndex.KeyO,
2732
- P: codeToIndex.KeyP,
2733
- Q: codeToIndex.KeyQ,
2734
- R: codeToIndex.KeyR,
2735
- S: codeToIndex.KeyS,
2736
- T: codeToIndex.KeyT,
2737
- U: codeToIndex.KeyU,
2738
- V: codeToIndex.KeyV,
2739
- W: codeToIndex.KeyW,
2740
- X: codeToIndex.KeyX,
2741
- Y: codeToIndex.KeyY,
2742
- Z: codeToIndex.KeyZ,
2743
- // Numbers
2744
- Digit0: codeToIndex.Digit0,
2745
- Digit1: codeToIndex.Digit1,
2746
- Digit2: codeToIndex.Digit2,
2747
- Digit3: codeToIndex.Digit3,
2748
- Digit4: codeToIndex.Digit4,
2749
- Digit5: codeToIndex.Digit5,
2750
- Digit6: codeToIndex.Digit6,
2751
- Digit7: codeToIndex.Digit7,
2752
- Digit8: codeToIndex.Digit8,
2753
- Digit9: codeToIndex.Digit9,
2754
- // Function keys
2755
- F1: codeToIndex.F1,
2756
- F2: codeToIndex.F2,
2757
- F3: codeToIndex.F3,
2758
- F4: codeToIndex.F4,
2759
- F5: codeToIndex.F5,
2760
- F6: codeToIndex.F6,
2761
- F7: codeToIndex.F7,
2762
- F8: codeToIndex.F8,
2763
- F9: codeToIndex.F9,
2764
- F10: codeToIndex.F10,
2765
- F11: codeToIndex.F11,
2766
- F12: codeToIndex.F12,
2767
- // Modifiers
2768
- ShiftLeft: codeToIndex.ShiftLeft,
2769
- ShiftRight: codeToIndex.ShiftRight,
2770
- ControlLeft: codeToIndex.ControlLeft,
2771
- ControlRight: codeToIndex.ControlRight,
2772
- AltLeft: codeToIndex.AltLeft,
2773
- AltRight: codeToIndex.AltRight,
2774
- MetaLeft: codeToIndex.MetaLeft,
2775
- MetaRight: codeToIndex.MetaRight,
2776
- // Navigation
2777
- Escape: codeToIndex.Escape,
2778
- Space: codeToIndex.Space,
2779
- Enter: codeToIndex.Enter,
2780
- Tab: codeToIndex.Tab,
2781
- Backspace: codeToIndex.Backspace,
2782
- Delete: codeToIndex.Delete,
2783
- ArrowLeft: codeToIndex.ArrowLeft,
2784
- ArrowUp: codeToIndex.ArrowUp,
2785
- ArrowRight: codeToIndex.ArrowRight,
2786
- ArrowDown: codeToIndex.ArrowDown,
2787
- Home: codeToIndex.Home,
2788
- End: codeToIndex.End,
2789
- PageUp: codeToIndex.PageUp,
2790
- PageDown: codeToIndex.PageDown,
2791
- Insert: codeToIndex.Insert,
2792
- // Punctuation
2793
- Semicolon: codeToIndex.Semicolon,
2794
- Equal: codeToIndex.Equal,
2795
- Comma: codeToIndex.Comma,
2796
- Minus: codeToIndex.Minus,
2797
- Period: codeToIndex.Period,
2798
- Slash: codeToIndex.Slash,
2799
- Backquote: codeToIndex.Backquote,
2800
- BracketLeft: codeToIndex.BracketLeft,
2801
- Backslash: codeToIndex.Backslash,
2802
- BracketRight: codeToIndex.BracketRight,
2803
- Quote: codeToIndex.Quote,
2804
- // Numpad
2805
- Numpad0: codeToIndex.Numpad0,
2806
- Numpad1: codeToIndex.Numpad1,
2807
- Numpad2: codeToIndex.Numpad2,
2808
- Numpad3: codeToIndex.Numpad3,
2809
- Numpad4: codeToIndex.Numpad4,
2810
- Numpad5: codeToIndex.Numpad5,
2811
- Numpad6: codeToIndex.Numpad6,
2812
- Numpad7: codeToIndex.Numpad7,
2813
- Numpad8: codeToIndex.Numpad8,
2814
- Numpad9: codeToIndex.Numpad9,
2815
- NumpadAdd: codeToIndex.NumpadAdd,
2816
- NumpadSubtract: codeToIndex.NumpadSubtract,
2817
- NumpadMultiply: codeToIndex.NumpadMultiply,
2818
- NumpadDivide: codeToIndex.NumpadDivide,
2819
- NumpadDecimal: codeToIndex.NumpadDecimal,
2820
- NumpadEnter: codeToIndex.NumpadEnter
2821
2832
  };
2833
+ var Intersect = new IntersectDef();
2822
2834
 
2823
2835
  // src/singletons/Mouse.ts
2824
2836
  var import_canvas_store36 = require("@woven-ecs/canvas-store");
@@ -5747,6 +5759,9 @@ var selectSystem = defineEditorSystem({ phase: "capture", priority: 100 }, (ctx)
5747
5759
  buttons = ["left"];
5748
5760
  }
5749
5761
  const events = getPointerInput(ctx, buttons);
5762
+ if (buttons.length === 0 && (state.state === SelectionState.SelectionBoxPointing || state.state === SelectionState.SelectionBoxDragging)) {
5763
+ events.push({ type: "cancel", ctx });
5764
+ }
5750
5765
  if (events.length === 0) return;
5751
5766
  SelectionStateSingleton.run(ctx, selectionMachine, events);
5752
5767
  });