incanto 0.1.0 → 0.2.0

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/editor/index.html CHANGED
@@ -5,7 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>Incanto Scene Editor</title>
7
7
  <link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><rect width='16' height='16' rx='3' fill='%236ee7dc'/><text x='8' y='12' text-anchor='middle' font-size='11' font-family='monospace' fill='%230e1018'>i</text></svg>" />
8
- <script type="module" crossorigin src="./assets/index-Dl2pjA8e.js"></script>
8
+ <script type="module" crossorigin src="./assets/index-CxJ6dZLb.js"></script>
9
9
  <link rel="modulepreload" crossorigin href="./assets/GameServer-C56iOUgF.js">
10
10
  <link rel="stylesheet" crossorigin href="./assets/index-DF3tMeKJ.css">
11
11
  </head>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "incanto",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Vibe-coding-first web game engine SDK — JSON-driven scenes on three.js",
5
5
  "keywords": [
6
6
  "game-engine",
@@ -175,6 +175,9 @@
175
175
  {
176
176
  "$ref": "#/$defs/AnimatedSprite2D"
177
177
  },
178
+ {
179
+ "$ref": "#/$defs/AnimatedSprite3D"
180
+ },
178
181
  {
179
182
  "$ref": "#/$defs/Area2D"
180
183
  },
@@ -253,6 +256,9 @@
253
256
  {
254
257
  "$ref": "#/$defs/Sprite2D"
255
258
  },
259
+ {
260
+ "$ref": "#/$defs/Sprite3D"
261
+ },
256
262
  {
257
263
  "$ref": "#/$defs/StaticBody2D"
258
264
  },
@@ -453,6 +459,160 @@
453
459
  },
454
460
  "required": ["name", "type"]
455
461
  },
462
+ "AnimatedSprite3D": {
463
+ "type": "object",
464
+ "x-signals": ["animationFinished"],
465
+ "properties": {
466
+ "name": {
467
+ "type": "string"
468
+ },
469
+ "uid": {
470
+ "type": "string"
471
+ },
472
+ "type": {
473
+ "const": "AnimatedSprite3D"
474
+ },
475
+ "groups": {
476
+ "type": "array",
477
+ "items": {
478
+ "type": "string"
479
+ }
480
+ },
481
+ "tags": {
482
+ "type": "object"
483
+ },
484
+ "props": {
485
+ "type": "object",
486
+ "properties": {
487
+ "position": {
488
+ "type": "array",
489
+ "items": {
490
+ "type": "number"
491
+ },
492
+ "minItems": 3,
493
+ "maxItems": 3,
494
+ "default": [0, 0, 0]
495
+ },
496
+ "rotation": {
497
+ "type": "array",
498
+ "items": {
499
+ "type": "number"
500
+ },
501
+ "minItems": 3,
502
+ "maxItems": 3,
503
+ "default": [0, 0, 0]
504
+ },
505
+ "scale": {
506
+ "type": "array",
507
+ "items": {
508
+ "type": "number"
509
+ },
510
+ "minItems": 3,
511
+ "maxItems": 3,
512
+ "default": [1, 1, 1]
513
+ },
514
+ "visible": {
515
+ "type": "boolean",
516
+ "default": true
517
+ },
518
+ "renderOrder": {
519
+ "type": "number",
520
+ "default": 0
521
+ },
522
+ "texture": {
523
+ "type": "string",
524
+ "default": ""
525
+ },
526
+ "size": {
527
+ "type": "array",
528
+ "items": {
529
+ "type": "number"
530
+ },
531
+ "minItems": 2,
532
+ "maxItems": 2,
533
+ "default": [1, 1]
534
+ },
535
+ "billboard": {
536
+ "type": "string",
537
+ "enum": ["y", "full", "none"],
538
+ "default": "y"
539
+ },
540
+ "anchor": {
541
+ "type": "array",
542
+ "items": {
543
+ "type": "number"
544
+ },
545
+ "minItems": 2,
546
+ "maxItems": 2,
547
+ "default": [0.5, 0]
548
+ },
549
+ "tint": {
550
+ "type": "string",
551
+ "default": "#ffffff"
552
+ },
553
+ "opacity": {
554
+ "type": "number",
555
+ "default": 1
556
+ },
557
+ "flipX": {
558
+ "type": "boolean",
559
+ "default": false
560
+ },
561
+ "pixelArt": {
562
+ "type": "boolean",
563
+ "default": true
564
+ },
565
+ "alphaTest": {
566
+ "type": "number",
567
+ "default": 0.5
568
+ },
569
+ "sheet": {
570
+ "type": "string",
571
+ "default": ""
572
+ },
573
+ "frameWidth": {
574
+ "type": "number",
575
+ "default": 0
576
+ },
577
+ "frameHeight": {
578
+ "type": "number",
579
+ "default": 0
580
+ },
581
+ "animations": {
582
+ "type": "object",
583
+ "default": {}
584
+ },
585
+ "autoplay": {
586
+ "type": "string",
587
+ "default": ""
588
+ }
589
+ },
590
+ "additionalProperties": false
591
+ },
592
+ "script": {
593
+ "type": "object",
594
+ "properties": {
595
+ "name": {
596
+ "type": "string"
597
+ },
598
+ "props": {
599
+ "type": "object"
600
+ }
601
+ },
602
+ "required": ["name"]
603
+ },
604
+ "network": {
605
+ "type": "object"
606
+ },
607
+ "children": {
608
+ "type": "array",
609
+ "items": {
610
+ "$ref": "#/$defs/node"
611
+ }
612
+ }
613
+ },
614
+ "required": ["name", "type"]
615
+ },
456
616
  "Area2D": {
457
617
  "type": "object",
458
618
  "x-signals": ["triggerEnter", "triggerExit"],
@@ -3378,6 +3538,139 @@
3378
3538
  },
3379
3539
  "required": ["name", "type"]
3380
3540
  },
3541
+ "Sprite3D": {
3542
+ "type": "object",
3543
+ "properties": {
3544
+ "name": {
3545
+ "type": "string"
3546
+ },
3547
+ "uid": {
3548
+ "type": "string"
3549
+ },
3550
+ "type": {
3551
+ "const": "Sprite3D"
3552
+ },
3553
+ "groups": {
3554
+ "type": "array",
3555
+ "items": {
3556
+ "type": "string"
3557
+ }
3558
+ },
3559
+ "tags": {
3560
+ "type": "object"
3561
+ },
3562
+ "props": {
3563
+ "type": "object",
3564
+ "properties": {
3565
+ "position": {
3566
+ "type": "array",
3567
+ "items": {
3568
+ "type": "number"
3569
+ },
3570
+ "minItems": 3,
3571
+ "maxItems": 3,
3572
+ "default": [0, 0, 0]
3573
+ },
3574
+ "rotation": {
3575
+ "type": "array",
3576
+ "items": {
3577
+ "type": "number"
3578
+ },
3579
+ "minItems": 3,
3580
+ "maxItems": 3,
3581
+ "default": [0, 0, 0]
3582
+ },
3583
+ "scale": {
3584
+ "type": "array",
3585
+ "items": {
3586
+ "type": "number"
3587
+ },
3588
+ "minItems": 3,
3589
+ "maxItems": 3,
3590
+ "default": [1, 1, 1]
3591
+ },
3592
+ "visible": {
3593
+ "type": "boolean",
3594
+ "default": true
3595
+ },
3596
+ "renderOrder": {
3597
+ "type": "number",
3598
+ "default": 0
3599
+ },
3600
+ "texture": {
3601
+ "type": "string",
3602
+ "default": ""
3603
+ },
3604
+ "size": {
3605
+ "type": "array",
3606
+ "items": {
3607
+ "type": "number"
3608
+ },
3609
+ "minItems": 2,
3610
+ "maxItems": 2,
3611
+ "default": [1, 1]
3612
+ },
3613
+ "billboard": {
3614
+ "type": "string",
3615
+ "enum": ["y", "full", "none"],
3616
+ "default": "y"
3617
+ },
3618
+ "anchor": {
3619
+ "type": "array",
3620
+ "items": {
3621
+ "type": "number"
3622
+ },
3623
+ "minItems": 2,
3624
+ "maxItems": 2,
3625
+ "default": [0.5, 0]
3626
+ },
3627
+ "tint": {
3628
+ "type": "string",
3629
+ "default": "#ffffff"
3630
+ },
3631
+ "opacity": {
3632
+ "type": "number",
3633
+ "default": 1
3634
+ },
3635
+ "flipX": {
3636
+ "type": "boolean",
3637
+ "default": false
3638
+ },
3639
+ "pixelArt": {
3640
+ "type": "boolean",
3641
+ "default": true
3642
+ },
3643
+ "alphaTest": {
3644
+ "type": "number",
3645
+ "default": 0.5
3646
+ }
3647
+ },
3648
+ "additionalProperties": false
3649
+ },
3650
+ "script": {
3651
+ "type": "object",
3652
+ "properties": {
3653
+ "name": {
3654
+ "type": "string"
3655
+ },
3656
+ "props": {
3657
+ "type": "object"
3658
+ }
3659
+ },
3660
+ "required": ["name"]
3661
+ },
3662
+ "network": {
3663
+ "type": "object"
3664
+ },
3665
+ "children": {
3666
+ "type": "array",
3667
+ "items": {
3668
+ "$ref": "#/$defs/node"
3669
+ }
3670
+ }
3671
+ },
3672
+ "required": ["name", "type"]
3673
+ },
3381
3674
  "StaticBody2D": {
3382
3675
  "type": "object",
3383
3676
  "x-signals": ["triggerEnter", "triggerExit"],
@@ -65,6 +65,47 @@ All 3D nodes extend `Node3D` and therefore have the transform props:
65
65
  | `material` | `{}` | `{color: '#hex', metalness: 0..1, roughness: 0..1, opacity: 0..1, wireframe, flatShading, emissive, emissiveIntensity, map, normalMap, repeat: [u,v]}` — the object IS the material state: omitted keys reset to defaults (`#ffffff`, 0, 1, 1, false, false). `opacity < 1` turns on transparency; `flatShading` gives faceted per-face glints (the gem sparkle). `map`/`normalMap` are texture URLs (lazy-loaded, headless-safe; map samples sRGB, normalMap linear), tiled `repeat` times across each face — box/plane UVs span 0..1 per face, so for worldspace density use `repeat: [length/tile, height/tile]` (e.g. a 6×2.5 m brick wall at one tile per 2 m → `[3, 1.25]`). `color` tints the map (near-white keeps the texture's own color). NB: under ACES a very bright `emissiveIntensity` blows out to white — keep it modest (~1–2) + a saturated color for a vivid GLOWING look. Unknown keys, malformed `repeat`, or `repeat` without a map hard-fail at load |
66
66
  | `castShadow` / `receiveShadow` | `false` | |
67
67
 
68
+ ### `Sprite3D` / `AnimatedSprite3D` (2D billboard sprites — the 2.5D look)
69
+ A 2D image drawn as a camera-facing quad inside the 3D world (Octopath / Don't
70
+ Starve / classic MapleStory in a 3D scene). Unlit — the art shows as-is. The
71
+ visual is an inner quad, so child nodes inherit neither its sizing nor its
72
+ billboard spin. `Sprite3D`:
73
+
74
+ | Prop | Default | Notes |
75
+ |---|---|---|
76
+ | `texture` | `""` | image URL (sampled sRGB, tinted by `tint`); empty = hidden |
77
+ | `size` | `[1,1]` | quad `[width, height]` in world METERS (not pixels) |
78
+ | `billboard` | `"y"` | `"y"` upright — yaws to face the camera, stays vertical when you look down (characters, props) · `"full"` always faces the camera (items, FX) · `"none"` fixed to the node's own rotation |
79
+ | `anchor` | `[0.5,0]` | which point of the sprite sits at the node origin (0..1). `[0.5,0]` = bottom-center → the FEET stand on the ground; `[0.5,0.5]` = center |
80
+ | `tint` | `"#ffffff"` | multiplies the texture (near-white keeps original colors) |
81
+ | `opacity` | `1` | `< 1` turns on alpha blending |
82
+ | `flipX` | `false` | mirror horizontally (face left vs right) |
83
+ | `pixelArt` | `true` | nearest-filter for crisp pixels (`false` = smooth linear) |
84
+ | `alphaTest` | `0.5` | discard texels below this alpha — a crisp cutout that depth-sorts against 3D geometry (a tree occludes it; it occludes the ground). Use `0` + `opacity < 1` for soft/feathered sprites (smoke, glow) |
85
+
86
+ `AnimatedSprite3D` adds spritesheet animation (ALL Sprite3D props, plus):
87
+
88
+ | Prop | Default | Notes |
89
+ |---|---|---|
90
+ | `sheet` | `""` | spritesheet image URL (used instead of `texture`) |
91
+ | `frameWidth` / `frameHeight` | `0` | one frame cell's pixel size in the sheet |
92
+ | `animations` | `{}` | `{ name: { frames, fps, loop } }` — `frames` is an inclusive `[start, end]` RANGE or an explicit list `[0,2,5]`. e.g. `{ "walk": {"frames":[0,7],"fps":10,"loop":true}, "attack": {"frames":[8,11],"fps":14,"loop":false} }` |
93
+ | `autoplay` | `""` | animation name to start on load |
94
+
95
+ - API: `node.play('walk')`, `node.stop()`. A non-looping animation clamps on its last frame and emits **`animationFinished(name)`** — chain `attack → idle` from it. Frames index left→right, top→bottom (`cols = floor(sheetWidth / frameWidth)`).
96
+
97
+ ```json
98
+ { "name": "Slime", "type": "AnimatedSprite3D",
99
+ "props": {
100
+ "position": [4, 0, -2], "size": [1.5, 1.5],
101
+ "sheet": "https://example.com/slime.png", "frameWidth": 32, "frameHeight": 32,
102
+ "animations": { "idle": { "frames": [0, 3], "fps": 4, "loop": true } },
103
+ "autoplay": "idle" } }
104
+ ```
105
+ Drop sprites onto terrain height like any 3D node (their feet are the anchor). In
106
+ a top-down / quarter view, `billboard: "y"` keeps characters readable from every
107
+ camera yaw.
108
+
68
109
  ### `Camera3D`
69
110
  `fov: 60`, `near: 0.1`, `far: 1000`, `current: false`.
70
111
  Mark exactly ONE camera `current: true` (otherwise the first camera in tree order is used).
@@ -36,6 +36,32 @@ description: GENERATED complete reference of every Incanto node type — props,
36
36
 
37
37
  Signals: `animationFinished(name)`
38
38
 
39
+ ## `AnimatedSprite3D` — `incanto`
40
+
41
+ | Prop | Default | Kind |
42
+ |---|---|---|
43
+ | `position` | `[0,0,0]` | array |
44
+ | `rotation` | `[0,0,0]` | array |
45
+ | `scale` | `[1,1,1]` | array |
46
+ | `visible` | `true` | boolean |
47
+ | `renderOrder` | `0` | number |
48
+ | `texture` | `""` | string |
49
+ | `size` | `[1,1]` | array |
50
+ | `billboard` | `"y"` | one of: `y` `full` `none` |
51
+ | `anchor` | `[0.5,0]` | array |
52
+ | `tint` | `"#ffffff"` | string |
53
+ | `opacity` | `1` | number |
54
+ | `flipX` | `false` | boolean |
55
+ | `pixelArt` | `true` | boolean |
56
+ | `alphaTest` | `0.5` | number |
57
+ | `sheet` | `""` | string |
58
+ | `frameWidth` | `0` | number |
59
+ | `frameHeight` | `0` | number |
60
+ | `animations` | `{}` | object |
61
+ | `autoplay` | `""` | string |
62
+
63
+ Signals: `animationFinished(name)`
64
+
39
65
  ## `Area2D` — `incanto/2d`
40
66
 
41
67
  | Prop | Default | Kind |
@@ -480,6 +506,25 @@ Signals: `triggerEnter(other)` · `triggerExit(other)`
480
506
  | `tint` | `"#ffffff"` | string |
481
507
  | `opacity` | `1` | number |
482
508
 
509
+ ## `Sprite3D` — `incanto`
510
+
511
+ | Prop | Default | Kind |
512
+ |---|---|---|
513
+ | `position` | `[0,0,0]` | array |
514
+ | `rotation` | `[0,0,0]` | array |
515
+ | `scale` | `[1,1,1]` | array |
516
+ | `visible` | `true` | boolean |
517
+ | `renderOrder` | `0` | number |
518
+ | `texture` | `""` | string |
519
+ | `size` | `[1,1]` | array |
520
+ | `billboard` | `"y"` | one of: `y` `full` `none` |
521
+ | `anchor` | `[0.5,0]` | array |
522
+ | `tint` | `"#ffffff"` | string |
523
+ | `opacity` | `1` | number |
524
+ | `flipX` | `false` | boolean |
525
+ | `pixelArt` | `true` | boolean |
526
+ | `alphaTest` | `0.5` | number |
527
+
483
528
  ## `StaticBody2D` — `incanto/2d`
484
529
 
485
530
  | Prop | Default | Kind |