@spritebuddy/core 0.1.0 → 0.3.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/LICENSE CHANGED
@@ -1,15 +1,15 @@
1
- ISC License
2
-
3
- Copyright (c) 2026 Patrick Hammond
4
-
5
- Permission to use, copy, modify, and/or distribute this software for any
6
- purpose with or without fee is hereby granted, provided that the above
7
- copyright notice and this permission notice appear in all copies.
8
-
9
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1
+ ISC License
2
+
3
+ Copyright (c) 2026 Patrick Hammond
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package/README.md CHANGED
@@ -1,54 +1,61 @@
1
- # @spritebuddy/core
2
-
3
- Reads [SpriteBuddy](https://github.com/Patrick-Hammond/spritebuddy) runtime files
4
- ([format](https://github.com/Patrick-Hammond/spritebuddy-runtimes/blob/main/docs/format.md)) and works out what to draw at any moment. No
5
- dependencies and no engine: [`@spritebuddy/pixi`](https://www.npmjs.com/package/@spritebuddy/pixi)
6
- builds on it, and you can use it with any renderer that can draw part of an image.
7
-
8
- ```sh
9
- npm install @spritebuddy/core
10
- ```
11
-
12
- ## Quick start
13
-
14
- ```ts
15
- import { parseFile, Player } from '@spritebuddy/core';
16
-
17
- const file = parseFile(await (await fetch('knight.anims.json')).json());
18
- const player = new Player(file, { onComplete: () => player.play('idle') }).play('attack');
19
-
20
- // every tick
21
- player.update(deltaMs);
22
- for (const part of player.parts) {
23
- // Draw part.frame.rect from the sheet with its full-frame top-left at
24
- // (spriteX + part.x, spriteY + part.y), mirrored by part.flipX / part.flipY, at
25
- // part.opacity. Trimmed frames start part.frame.trim.x/y further in; rotated frames are
26
- // stored turned 90° clockwise.
27
- }
28
- ```
29
-
30
- The [canvas example](https://github.com/Patrick-Hammond/spritebuddy-runtimes/tree/main/examples/canvas) is a complete page that does exactly
31
- this with a 2D canvas, rotation, trim and flips included, in about 60 lines.
32
-
33
- ## API
34
-
35
- - `parseFile(json)` checks a runtime file and fills in every default. It throws a
36
- `FormatError` that says where the file is wrong, and refuses versions newer than `VERSION`.
37
- - `new Player(file, { onFrame, onComplete })` keeps time for one sprite:
38
- - `play(name, fromMs?)` starts an animation (it throws for an unknown name, listing the
39
- names there are), `stop()`, `seek(ms)` and `update(ms)`.
40
- - `speed` (1 is normal), `playing`, `names`, `animation(name)`.
41
- - `parts`: what to draw now, bottom to top. `state` adds the animation, frame index, time
42
- and whether a `once` animation is done.
43
- - `onFrame(index)` fires when the frame changes; `onComplete()` when a `once` animation
44
- ends.
45
- - The pure functions underneath, for engines that keep their own clock:
46
- - `frameAt(animation, ms)` gives the frame index showing at a time, and whether it is done.
47
- - `partsOf(file, animationFrame)` gives the parts to draw for one frame.
48
- - `boundsOf`, `cycleDuration` and `cycleOrder` help with layout and timelines.
49
- - The JSON Schema ships as `@spritebuddy/core/schema.json`.
50
-
51
- Every function is tested against the shared
52
- [golden tables](https://github.com/Patrick-Hammond/spritebuddy-runtimes/tree/main/fixtures), the same ones the PixiJS and Godot runtimes pass.
53
-
54
- Licence: ISC.
1
+ # @spritebuddy/core
2
+
3
+ Reads [SpriteBuddy](https://github.com/Patrick-Hammond/spritebuddy) runtime files
4
+ ([format](https://github.com/Patrick-Hammond/spritebuddy-runtimes/blob/main/docs/format.md)) and works out what to draw at any moment. No
5
+ dependencies and no engine: [`@spritebuddy/pixi`](https://www.npmjs.com/package/@spritebuddy/pixi)
6
+ builds on it, and you can use it with any renderer that can draw part of an image.
7
+
8
+ ```sh
9
+ npm install @spritebuddy/core
10
+ ```
11
+
12
+ ## Quick start
13
+
14
+ ```ts
15
+ import { parseFile, Player } from '@spritebuddy/core';
16
+
17
+ const file = parseFile(await (await fetch('knight.anims.json')).json());
18
+ const player = new Player(file, {
19
+ onComplete: () => player.play('idle'),
20
+ onEvent: (name) => name === 'hit' && dealDamage(), // events tagged on frames in SpriteBuddy
21
+ }).play('attack');
22
+
23
+ // every tick
24
+ player.update(deltaMs);
25
+ for (const part of player.parts) {
26
+ // Draw part.frame.rect from the sheet with its full-frame top-left at
27
+ // (spriteX + part.x, spriteY + part.y), mirrored by part.flipX / part.flipY, at
28
+ // part.opacity. Trimmed frames start part.frame.trim.x/y further in; rotated frames are
29
+ // stored turned 90° clockwise.
30
+ }
31
+ ```
32
+
33
+ The [canvas example](https://github.com/Patrick-Hammond/spritebuddy-runtimes/tree/main/examples/canvas) is a complete page that does exactly
34
+ this with a 2D canvas, rotation, trim and flips included, in about 60 lines.
35
+
36
+ ## API
37
+
38
+ - `parseFile(json)` checks a runtime file and fills in every default. It throws a
39
+ `FormatError` that says where the file is wrong, and refuses versions newer than `VERSION`.
40
+ - `new Player(file, { onFrame, onEvent, onComplete })` keeps time for one sprite:
41
+ - `play(name, fromMs?)` starts an animation (it throws for an unknown name, listing the
42
+ names there are), `stop()`, `seek(ms)` and `update(ms)`.
43
+ - `speed` (1 is normal), `playing`, `names`, `animation(name)`.
44
+ - `parts`: what to draw now, bottom to top. `state` adds the animation, frame index, time
45
+ and whether a `once` animation is done.
46
+ - `onFrame(index)` fires when the frame changes; `onEvent(name, index)` for each event
47
+ tagged on a frame as it starts showing (after `onFrame`), including frames a long tick
48
+ skipped; `onComplete()` when a `once` animation ends. `play` fires the first frame's
49
+ events; `seek` fires none.
50
+ - The pure functions underneath, for engines that keep their own clock:
51
+ - `frameAt(animation, ms)` gives the frame index showing at a time, and whether it is done.
52
+ - `partsOf(file, animationFrame)` gives the parts to draw for one frame.
53
+ - `eventsBetween(animation, fromMs, toMs)` lists the events of frames starting after `fromMs`
54
+ up to `toMs`, at most one cycle's worth.
55
+ - `boundsOf`, `cycleDuration` and `cycleOrder` help with layout and timelines.
56
+ - The JSON Schema ships as `@spritebuddy/core/schema.json`.
57
+
58
+ Every function is tested against the shared
59
+ [golden tables](https://github.com/Patrick-Hammond/spritebuddy-runtimes/tree/main/fixtures), the same ones the PixiJS and Godot runtimes pass.
60
+
61
+ Licence: ISC.
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { FORMAT, VERSION } from './types.js';
2
- export type { AnimationDef, AnimationFrameDef, FrameDef, LayerDef, LoopMode, Point, Rect, SpriteBuddyFile, Trim, } from './types.js';
2
+ export type { AnimationDef, AnimationFrameDef, FrameDef, LayerDef, LightDef, LoopMode, Point, Rect, SpriteBuddyFile, Trim, } from './types.js';
3
3
  export { DEFAULT_DURATION, FormatError, parseFile } from './parse.js';
4
- export { cycleDuration, cycleOrder, frameAt, type PlaybackPosition } from './timing.js';
4
+ export { cycleDuration, cycleOrder, eventsBetween, frameAt, type FrameEvent, type PlaybackPosition, } from './timing.js';
5
5
  export { boundsOf, partsOf, type Part } from './resolve.js';
6
- export { Player, type PlayerState } from './player.js';
6
+ export { Player, type PlayerEvents, type PlayerState } from './player.js';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export { FORMAT, VERSION } from './types.js';
2
2
  export { DEFAULT_DURATION, FormatError, parseFile } from './parse.js';
3
- export { cycleDuration, cycleOrder, frameAt } from './timing.js';
3
+ export { cycleDuration, cycleOrder, eventsBetween, frameAt, } from './timing.js';
4
4
  export { boundsOf, partsOf } from './resolve.js';
5
5
  export { Player } from './player.js';
6
6
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAY7C,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAyB,MAAM,aAAa,CAAC;AACxF,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAa,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAoB,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAa7C,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EACL,aAAa,EACb,UAAU,EACV,aAAa,EACb,OAAO,GAGR,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAa,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAuC,MAAM,aAAa,CAAC"}
package/dist/parse.js CHANGED
@@ -104,7 +104,13 @@ function layerDef(v, path, count) {
104
104
  }
105
105
  function animationFrameDef(v, path, count, duration) {
106
106
  if (typeof v === 'number') {
107
- return { frame: frameIndex(v, path, count), duration, offset: { x: 0, y: 0 }, layers: [] };
107
+ return {
108
+ frame: frameIndex(v, path, count),
109
+ duration,
110
+ offset: { x: 0, y: 0 },
111
+ layers: [],
112
+ events: [],
113
+ };
108
114
  }
109
115
  const o = object(v, path);
110
116
  const [ox, oy] = opt(o.offset, [0, 0], (n) => ints(n, `${path}.offset`, 2, [-Infinity, -Infinity]));
@@ -113,6 +119,7 @@ function animationFrameDef(v, path, count, duration) {
113
119
  duration: opt(o.duration, duration, (n) => int(n, `${path}.duration`, 1)),
114
120
  offset: { x: ox, y: oy },
115
121
  layers: opt(o.layers, [], (l) => array(l, `${path}.layers`).map((layer, i) => layerDef(layer, `${path}.layers[${i}]`, count))),
122
+ events: opt(o.events, [], (e) => array(e, `${path}.events`).map((name, i) => string(name, `${path}.events[${i}]`))),
116
123
  };
117
124
  }
118
125
  const LOOPS = ['loop', 'pingpong', 'once'];
@@ -129,8 +136,29 @@ function animationDef(v, path, count) {
129
136
  name: string(o.name, `${path}.name`),
130
137
  loop,
131
138
  frames: array(o.frames, `${path}.frames`).map((f, i) => animationFrameDef(f, `${path}.frames[${i}]`, count, duration)),
139
+ light: lightDef(o.lighting),
132
140
  };
133
141
  }
142
+ const LIGHT_NUMBERS = ['angle', 'height', 'size', 'brightness', 'ambient', 'opacity', 'bands'];
143
+ /**
144
+ * Picks the editor's light out of an animation's `lighting`. Runtimes don't need it to play the
145
+ * file, so a field of the wrong type is dropped rather than refused.
146
+ */
147
+ function lightDef(lighting) {
148
+ const light = isObject(lighting) ? lighting.light : undefined;
149
+ if (!isObject(light))
150
+ return null;
151
+ const out = {};
152
+ for (const key of LIGHT_NUMBERS) {
153
+ const v = light[key];
154
+ if (typeof v === 'number' && Number.isFinite(v))
155
+ out[key] = v;
156
+ }
157
+ if (typeof light.color === 'string' && /^#[0-9a-f]{6}$/i.test(light.color)) {
158
+ out.color = light.color;
159
+ }
160
+ return out;
161
+ }
134
162
  /**
135
163
  * Reads a SpriteBuddy runtime file (`.anims.json`, version 3) from parsed JSON, filling in every
136
164
  * default. Unknown fields are ignored so newer minor additions still load. Throws
@@ -161,6 +189,7 @@ export function parseFile(json) {
161
189
  return {
162
190
  version,
163
191
  image: string(o.image, 'image'),
192
+ normals: opt(o.normals, null, (n) => string(n, 'normals')),
164
193
  width,
165
194
  height,
166
195
  scale: opt(o.scale, 1, (s) => number(s, 'scale', 1e-6, 1e6)),
package/dist/parse.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"parse.js","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"parse.js","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"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"}
package/dist/player.d.ts CHANGED
@@ -11,6 +11,17 @@ export interface PlayerState {
11
11
  /** What to draw now, bottom to top. */
12
12
  readonly parts: readonly Part[];
13
13
  }
14
+ export interface PlayerEvents {
15
+ /** Called with the frame index each time the frame changes. */
16
+ onFrame?: (index: number) => void;
17
+ /** Called when a `once` animation ends. */
18
+ onComplete?: () => void;
19
+ /**
20
+ * Called for each event of a frame as it starts showing (see {@link eventsBetween}). `play`
21
+ * fires the first frame's events; `seek` jumps without firing any.
22
+ */
23
+ onEvent?: (name: string, index: number) => void;
24
+ }
14
25
  /**
15
26
  * Plays a file's animations with nothing but a clock: call {@link update} every tick with the
16
27
  * elapsed ms and draw {@link parts}. Engine adapters wrap this; games can use it directly too.
@@ -22,10 +33,7 @@ export declare class Player {
22
33
  speed: number;
23
34
  /** Whether {@link update} moves time on. */
24
35
  playing: boolean;
25
- constructor(file: SpriteBuddyFile, events?: {
26
- onFrame?: (index: number) => void;
27
- onComplete?: () => void;
28
- });
36
+ constructor(file: SpriteBuddyFile, events?: PlayerEvents);
29
37
  /** Names of every animation in the file. */
30
38
  get names(): string[];
31
39
  /** The animation called `name`, or undefined. */
package/dist/player.js CHANGED
@@ -9,9 +9,9 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
9
9
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
- var _Player_instances, _Player_animation, _Player_time, _Player_index, _Player_done, _Player_parts, _Player_onFrame, _Player_onComplete, _Player_refresh;
12
+ var _Player_instances, _Player_animation, _Player_time, _Player_index, _Player_done, _Player_parts, _Player_onFrame, _Player_onComplete, _Player_onEvent, _Player_refresh;
13
13
  import { partsOf } from './resolve.js';
14
- import { frameAt } from './timing.js';
14
+ import { eventsBetween, frameAt } from './timing.js';
15
15
  /**
16
16
  * Plays a file's animations with nothing but a clock: call {@link update} every tick with the
17
17
  * elapsed ms and draw {@link parts}. Engine adapters wrap this; games can use it directly too.
@@ -30,9 +30,11 @@ export class Player {
30
30
  _Player_parts.set(this, []);
31
31
  _Player_onFrame.set(this, void 0);
32
32
  _Player_onComplete.set(this, void 0);
33
+ _Player_onEvent.set(this, void 0);
33
34
  this.file = file;
34
35
  __classPrivateFieldSet(this, _Player_onFrame, events.onFrame, "f");
35
36
  __classPrivateFieldSet(this, _Player_onComplete, events.onComplete, "f");
37
+ __classPrivateFieldSet(this, _Player_onEvent, events.onEvent, "f");
36
38
  }
37
39
  /** Names of every animation in the file. */
38
40
  get names() {
@@ -55,7 +57,9 @@ export class Player {
55
57
  __classPrivateFieldSet(this, _Player_index, -1, "f");
56
58
  __classPrivateFieldSet(this, _Player_done, false, "f");
57
59
  this.playing = true;
58
- this.seek(time);
60
+ __classPrivateFieldSet(this, _Player_time, Math.max(0, time), "f");
61
+ const index = frameAt(anim, __classPrivateFieldGet(this, _Player_time, "f")).index;
62
+ __classPrivateFieldGet(this, _Player_instances, "m", _Player_refresh).call(this, index < 0 ? [] : anim.frames[index].events.map((name) => ({ name, index })));
59
63
  return this;
60
64
  }
61
65
  stop() {
@@ -70,9 +74,11 @@ export class Player {
70
74
  }
71
75
  /** Moves time on by `ms` (times {@link speed}) while playing. */
72
76
  update(ms) {
73
- if (this.playing && __classPrivateFieldGet(this, _Player_animation, "f")) {
77
+ const anim = __classPrivateFieldGet(this, _Player_animation, "f");
78
+ if (this.playing && anim) {
79
+ const from = __classPrivateFieldGet(this, _Player_time, "f");
74
80
  __classPrivateFieldSet(this, _Player_time, __classPrivateFieldGet(this, _Player_time, "f") + Math.max(0, ms) * this.speed, "f");
75
- __classPrivateFieldGet(this, _Player_instances, "m", _Player_refresh).call(this);
81
+ __classPrivateFieldGet(this, _Player_instances, "m", _Player_refresh).call(this, __classPrivateFieldGet(this, _Player_onEvent, "f") ? eventsBetween(anim, from, __classPrivateFieldGet(this, _Player_time, "f")) : []);
76
82
  }
77
83
  return this;
78
84
  }
@@ -89,7 +95,7 @@ export class Player {
89
95
  return __classPrivateFieldGet(this, _Player_parts, "f");
90
96
  }
91
97
  }
92
- _Player_animation = new WeakMap(), _Player_time = new WeakMap(), _Player_index = new WeakMap(), _Player_done = new WeakMap(), _Player_parts = new WeakMap(), _Player_onFrame = new WeakMap(), _Player_onComplete = new WeakMap(), _Player_instances = new WeakSet(), _Player_refresh = function _Player_refresh() {
98
+ _Player_animation = new WeakMap(), _Player_time = new WeakMap(), _Player_index = new WeakMap(), _Player_done = new WeakMap(), _Player_parts = new WeakMap(), _Player_onFrame = new WeakMap(), _Player_onComplete = new WeakMap(), _Player_onEvent = new WeakMap(), _Player_instances = new WeakSet(), _Player_refresh = function _Player_refresh(fired = []) {
93
99
  const anim = __classPrivateFieldGet(this, _Player_animation, "f");
94
100
  if (!anim)
95
101
  return;
@@ -99,6 +105,8 @@ _Player_animation = new WeakMap(), _Player_time = new WeakMap(), _Player_index =
99
105
  __classPrivateFieldSet(this, _Player_parts, pos.index < 0 ? [] : partsOf(this.file, anim.frames[pos.index]), "f");
100
106
  if (changed && pos.index >= 0)
101
107
  __classPrivateFieldGet(this, _Player_onFrame, "f")?.call(this, pos.index);
108
+ for (const e of fired)
109
+ __classPrivateFieldGet(this, _Player_onEvent, "f")?.call(this, e.name, e.index);
102
110
  if (pos.done && !__classPrivateFieldGet(this, _Player_done, "f")) {
103
111
  __classPrivateFieldSet(this, _Player_done, true, "f");
104
112
  this.playing = false;
@@ -1 +1 @@
1
- {"version":3,"file":"player.js","sourceRoot":"","sources":["../src/player.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"player.js","sourceRoot":"","sources":["../src/player.ts"],"names":[],"mappings":"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"}
package/dist/timing.d.ts CHANGED
@@ -18,3 +18,16 @@ export declare function cycleDuration(anim: Pick<AnimationDef, 'frames' | 'loop'
18
18
  * Negative times count as 0.
19
19
  */
20
20
  export declare function frameAt(anim: Pick<AnimationDef, 'frames' | 'loop'>, time: number): PlaybackPosition;
21
+ /** An event fired by an animation frame: its name and the frame's index in the animation. */
22
+ export interface FrameEvent {
23
+ readonly name: string;
24
+ readonly index: number;
25
+ }
26
+ /**
27
+ * The events of every frame that starts showing after `from` ms and up to and including `to` ms,
28
+ * in the order they start. A frame that starts exactly at `from` was already counted, so calling
29
+ * this with each tick's old and new time fires every event once, even when a long tick skips
30
+ * past short frames. A ping-pong cycle fires a frame's events each time it shows. One call fires
31
+ * at most one cycle's worth, so a game that was paused for a minute doesn't get a burst.
32
+ */
33
+ export declare function eventsBetween(anim: Pick<AnimationDef, 'frames' | 'loop'>, from: number, to: number): FrameEvent[];
package/dist/timing.js CHANGED
@@ -34,4 +34,41 @@ export function frameAt(anim, time) {
34
34
  /* v8 ignore next */
35
35
  return { index: order[order.length - 1], done: false };
36
36
  }
37
+ /**
38
+ * The events of every frame that starts showing after `from` ms and up to and including `to` ms,
39
+ * in the order they start. A frame that starts exactly at `from` was already counted, so calling
40
+ * this with each tick's old and new time fires every event once, even when a long tick skips
41
+ * past short frames. A ping-pong cycle fires a frame's events each time it shows. One call fires
42
+ * at most one cycle's worth, so a game that was paused for a minute doesn't get a burst.
43
+ */
44
+ export function eventsBetween(anim, from, to) {
45
+ const order = cycleOrder(anim);
46
+ if (order.length === 0 || to <= from)
47
+ return [];
48
+ if (!anim.frames.some((f) => f.events.length > 0))
49
+ return [];
50
+ const total = cycleDuration(anim);
51
+ const starts = [];
52
+ let t = 0;
53
+ for (const i of order) {
54
+ starts.push(t);
55
+ t += anim.frames[i].duration;
56
+ }
57
+ const crossed = [];
58
+ const once = anim.loop === 'once';
59
+ const first = once
60
+ ? 0
61
+ : Math.max(Math.floor(Math.max(0, from) / total), Math.floor(to / total) - 1);
62
+ const last = once ? 0 : Math.floor(to / total);
63
+ for (let cycle = first; cycle <= last; cycle++) {
64
+ order.forEach((index, k) => {
65
+ const at = cycle * total + starts[k];
66
+ if (at > from && at <= to)
67
+ crossed.push(index);
68
+ });
69
+ }
70
+ return crossed
71
+ .slice(-order.length)
72
+ .flatMap((index) => anim.frames[index].events.map((name) => ({ name, index })));
73
+ }
37
74
  //# sourceMappingURL=timing.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"timing.js","sourceRoot":"","sources":["../src/timing.ts"],"names":[],"mappings":"AASA;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,IAA2C;IACpE,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7C,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC;QAAE,OAAO,OAAO,CAAC;IACpE,OAAO,CAAC,GAAG,OAAO,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;AACzD,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,aAAa,CAAC,IAA2C;IACvE,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;AAC5E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,OAAO,CACrB,IAA2C,EAC3C,IAAY;IAEZ,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACzD,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAC5B,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,IAAI,KAAK;QAAE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC/F,IAAI,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC;IACrB,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,QAAQ,CAAC;QACjC,IAAI,IAAI,GAAG,CAAC;YAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IACjD,CAAC;IACD,oBAAoB;IACpB,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AAC1D,CAAC"}
1
+ {"version":3,"file":"timing.js","sourceRoot":"","sources":["../src/timing.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -59,17 +59,49 @@ export interface AnimationFrameDef {
59
59
  /** Nudge in pixels from where the pivot puts the frame (+x right, +y down). */
60
60
  readonly offset: Point;
61
61
  readonly layers: readonly LayerDef[];
62
+ /**
63
+ * Names fired when this frame starts showing, such as `"hit"` on the frame a sword lands or
64
+ * `"step"` on a footstep. Empty for most frames.
65
+ */
66
+ readonly events: readonly string[];
67
+ }
68
+ /**
69
+ * The light SpriteBuddy Pro lit an animation with (its `lighting.light`), so a runtime that lights
70
+ * in real time can match the editor. Only the fields the file sets are here; see the format docs
71
+ * for their defaults.
72
+ */
73
+ export interface LightDef {
74
+ /** Where the light comes from, in degrees clockwise from the top of the screen. */
75
+ readonly angle?: number;
76
+ /** Elevation in degrees: 90 shines from the viewer, below 0 from behind. */
77
+ readonly height?: number;
78
+ /** How far the light wraps round the shape, 0 to 1. */
79
+ readonly size?: number;
80
+ /** `"#rrggbb"`. */
81
+ readonly color?: string;
82
+ readonly brightness?: number;
83
+ readonly ambient?: number;
84
+ readonly opacity?: number;
85
+ /** Cel shading levels (2, 3 or 4), or 0 for smooth. */
86
+ readonly bands?: number;
62
87
  }
63
88
  export interface AnimationDef {
64
89
  readonly name: string;
65
90
  readonly loop: LoopMode;
66
91
  readonly frames: readonly AnimationFrameDef[];
92
+ /** The editor's light for this animation, or null when it has none. */
93
+ readonly light: LightDef | null;
67
94
  }
68
95
  /** A parsed runtime file, with every default filled in. */
69
96
  export interface SpriteBuddyFile {
70
97
  readonly version: number;
71
98
  /** The sheet image's file name, relative to the runtime file. */
72
99
  readonly image: string;
100
+ /**
101
+ * A normal-map image with the same size and frame layout as `image`, for real-time lighting,
102
+ * or null when the export has none. Relative to the runtime file.
103
+ */
104
+ readonly normals: string | null;
73
105
  readonly width: number;
74
106
  readonly height: number;
75
107
  /** Scale the sheet was exported at (1 = original pixels). */
package/package.json CHANGED
@@ -1,40 +1,40 @@
1
- {
2
- "name": "@spritebuddy/core",
3
- "version": "0.1.0",
4
- "description": "Reads SpriteBuddy animation files and works out what to draw at any moment. No dependencies, any engine.",
5
- "license": "ISC",
6
- "author": "Patrick Hammond",
7
- "repository": {
8
- "type": "git",
9
- "url": "git+https://github.com/Patrick-Hammond/spritebuddy-runtimes.git",
10
- "directory": "packages/core"
11
- },
12
- "keywords": [
13
- "spritebuddy",
14
- "sprites",
15
- "spritesheet",
16
- "animation",
17
- "gamedev"
18
- ],
19
- "type": "module",
20
- "sideEffects": false,
21
- "main": "./dist/index.js",
22
- "module": "./dist/index.js",
23
- "types": "./dist/index.d.ts",
24
- "exports": {
25
- ".": {
26
- "types": "./dist/index.d.ts",
27
- "import": "./dist/index.js"
28
- },
29
- "./schema.json": "./schema.json"
30
- },
31
- "files": [
32
- "dist",
33
- "schema.json"
34
- ],
35
- "scripts": {
36
- "build": "tsc -p tsconfig.build.json && node -e \"require('node:fs').copyFileSync('../../schema/spritebuddy-animations.v3.schema.json', 'schema.json')\"",
37
- "prepack": "npm run build",
38
- "typecheck": "tsc -p tsconfig.json --noEmit"
39
- }
40
- }
1
+ {
2
+ "name": "@spritebuddy/core",
3
+ "version": "0.3.0",
4
+ "description": "Reads SpriteBuddy animation files and works out what to draw at any moment. No dependencies, any engine.",
5
+ "license": "ISC",
6
+ "author": "Patrick Hammond",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/Patrick-Hammond/spritebuddy-runtimes.git",
10
+ "directory": "packages/core"
11
+ },
12
+ "keywords": [
13
+ "spritebuddy",
14
+ "sprites",
15
+ "spritesheet",
16
+ "animation",
17
+ "gamedev"
18
+ ],
19
+ "type": "module",
20
+ "sideEffects": false,
21
+ "main": "./dist/index.js",
22
+ "module": "./dist/index.js",
23
+ "types": "./dist/index.d.ts",
24
+ "exports": {
25
+ ".": {
26
+ "types": "./dist/index.d.ts",
27
+ "import": "./dist/index.js"
28
+ },
29
+ "./schema.json": "./schema.json"
30
+ },
31
+ "files": [
32
+ "dist",
33
+ "schema.json"
34
+ ],
35
+ "scripts": {
36
+ "build": "tsc -p tsconfig.build.json && node -e \"require('node:fs').copyFileSync('../../schema/spritebuddy-animations.v3.schema.json', 'schema.json')\"",
37
+ "prepack": "npm run build",
38
+ "typecheck": "tsc -p tsconfig.json --noEmit"
39
+ }
40
+ }
package/schema.json CHANGED
@@ -1,156 +1,342 @@
1
- {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://github.com/Patrick-Hammond/spritebuddy-runtimes/blob/main/schema/spritebuddy-animations.v3.schema.json",
4
- "title": "SpriteBuddy animations, version 3",
5
- "description": "A spritesheet's frames and animations, with per-frame timing, offsets and layers. Coordinates are sheet pixels with y down; times are milliseconds. See docs/format.md.",
6
- "type": "object",
7
- "required": ["format", "version", "image", "size", "frames"],
8
- "properties": {
9
- "format": { "const": "spritebuddy-animations" },
10
- "version": { "const": 3 },
11
- "image": {
12
- "type": "string",
13
- "minLength": 1,
14
- "description": "The sheet image, relative to this file."
15
- },
16
- "size": {
17
- "$ref": "#/$defs/size",
18
- "description": "Sheet size in pixels: [width, height]."
19
- },
20
- "scale": {
21
- "type": "number",
22
- "exclusiveMinimum": 0,
23
- "default": 1,
24
- "description": "Scale the sheet was exported at. Informational: every coordinate in the file is already in sheet pixels."
25
- },
26
- "frames": {
27
- "type": "array",
28
- "items": { "$ref": "#/$defs/frame" }
29
- },
30
- "animations": {
31
- "type": "array",
32
- "default": [],
33
- "items": { "$ref": "#/$defs/animation" }
34
- }
35
- },
36
- "$defs": {
37
- "int": { "type": "integer" },
38
- "count": { "type": "integer", "minimum": 0 },
39
- "positive": { "type": "integer", "minimum": 1 },
40
- "size": {
41
- "type": "array",
42
- "prefixItems": [{ "$ref": "#/$defs/positive" }, { "$ref": "#/$defs/positive" }],
43
- "minItems": 2,
44
- "maxItems": 2
45
- },
46
- "point": {
47
- "type": "array",
48
- "prefixItems": [{ "type": "number" }, { "type": "number" }],
49
- "minItems": 2,
50
- "maxItems": 2
51
- },
52
- "offset": {
53
- "type": "array",
54
- "prefixItems": [{ "$ref": "#/$defs/int" }, { "$ref": "#/$defs/int" }],
55
- "minItems": 2,
56
- "maxItems": 2
57
- },
58
- "frame": {
59
- "type": "object",
60
- "required": ["name", "rect"],
61
- "properties": {
62
- "name": { "type": "string", "minLength": 1 },
63
- "rect": {
64
- "type": "array",
65
- "description": "[x, y, w, h]: where the pixels sit on the sheet, at their upright size.",
66
- "prefixItems": [
67
- { "$ref": "#/$defs/count" },
68
- { "$ref": "#/$defs/count" },
69
- { "$ref": "#/$defs/positive" },
70
- { "$ref": "#/$defs/positive" }
71
- ],
72
- "minItems": 4,
73
- "maxItems": 4
74
- },
75
- "pivot": {
76
- "$ref": "#/$defs/point",
77
- "description": "[x, y] in full-frame pixels. Defaults to the bottom centre."
78
- },
79
- "rotated": {
80
- "type": "boolean",
81
- "default": false,
82
- "description": "Stored turned 90° clockwise: covers h columns and w rows on the sheet."
83
- },
84
- "trim": {
85
- "type": "array",
86
- "description": "[x, y, fullWidth, fullHeight]: transparent edges were cut off; the pixels start at x, y inside a full frame of this size.",
87
- "prefixItems": [
88
- { "$ref": "#/$defs/count" },
89
- { "$ref": "#/$defs/count" },
90
- { "$ref": "#/$defs/positive" },
91
- { "$ref": "#/$defs/positive" }
92
- ],
93
- "minItems": 4,
94
- "maxItems": 4
95
- }
96
- }
97
- },
98
- "layer": {
99
- "type": "object",
100
- "required": ["frame"],
101
- "properties": {
102
- "frame": { "$ref": "#/$defs/count", "description": "Index into frames." },
103
- "x": {
104
- "$ref": "#/$defs/int",
105
- "default": 0,
106
- "description": "Layer's full-frame left, from the base frame's left."
107
- },
108
- "y": {
109
- "$ref": "#/$defs/int",
110
- "default": 0,
111
- "description": "Layer's full-frame top, from the base frame's top."
112
- },
113
- "z": {
114
- "$ref": "#/$defs/int",
115
- "default": 1,
116
- "description": "Draw order; the base frame is 0."
117
- },
118
- "opacity": { "type": "number", "minimum": 0, "maximum": 1, "default": 1 },
119
- "flipX": { "type": "boolean", "default": false },
120
- "flipY": { "type": "boolean", "default": false }
121
- }
122
- },
123
- "animationFrame": {
124
- "oneOf": [
125
- { "$ref": "#/$defs/count", "description": "A frame index, with the animation's duration." },
126
- {
127
- "type": "object",
128
- "required": ["frame"],
129
- "properties": {
130
- "frame": { "$ref": "#/$defs/count" },
131
- "duration": { "$ref": "#/$defs/positive", "description": "Milliseconds." },
132
- "offset": {
133
- "$ref": "#/$defs/offset",
134
- "description": "[x, y] nudge from where the pivot puts the frame; +x right, +y down."
135
- },
136
- "layers": { "type": "array", "items": { "$ref": "#/$defs/layer" } }
137
- }
138
- }
139
- ]
140
- },
141
- "animation": {
142
- "type": "object",
143
- "required": ["name", "frames"],
144
- "properties": {
145
- "name": { "type": "string", "minLength": 1 },
146
- "loop": { "enum": ["loop", "pingpong", "once"], "default": "loop" },
147
- "duration": {
148
- "$ref": "#/$defs/positive",
149
- "default": 100,
150
- "description": "Milliseconds for frames that don't give their own."
151
- },
152
- "frames": { "type": "array", "items": { "$ref": "#/$defs/animationFrame" } }
153
- }
154
- }
155
- }
156
- }
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/Patrick-Hammond/spritebuddy-runtimes/blob/main/schema/spritebuddy-animations.v3.schema.json",
4
+ "title": "SpriteBuddy animations, version 3",
5
+ "description": "A spritesheet's frames and animations, with per-frame timing, offsets and layers. Coordinates are sheet pixels with y down; times are milliseconds. See docs/format.md.",
6
+ "type": "object",
7
+ "required": ["format", "version", "image", "size", "frames"],
8
+ "properties": {
9
+ "format": {
10
+ "const": "spritebuddy-animations"
11
+ },
12
+ "version": {
13
+ "const": 3
14
+ },
15
+ "image": {
16
+ "type": "string",
17
+ "minLength": 1,
18
+ "description": "The sheet image, relative to this file."
19
+ },
20
+ "normals": {
21
+ "type": "string",
22
+ "minLength": 1,
23
+ "description": "A normal-map image with the same size and frame layout as image, relative to this file. RGB holds the surface direction as (n + 1) / 2 with green pointing up (Y+). For real-time lighting; runtimes that don't light ignore it."
24
+ },
25
+ "size": {
26
+ "$ref": "#/$defs/size",
27
+ "description": "Sheet size in pixels: [width, height]."
28
+ },
29
+ "scale": {
30
+ "type": "number",
31
+ "exclusiveMinimum": 0,
32
+ "default": 1,
33
+ "description": "Scale the sheet was exported at. Informational: every coordinate in the file is already in sheet pixels."
34
+ },
35
+ "frames": {
36
+ "type": "array",
37
+ "items": {
38
+ "$ref": "#/$defs/frame"
39
+ }
40
+ },
41
+ "animations": {
42
+ "type": "array",
43
+ "default": [],
44
+ "items": {
45
+ "$ref": "#/$defs/animation"
46
+ }
47
+ }
48
+ },
49
+ "$defs": {
50
+ "int": {
51
+ "type": "integer"
52
+ },
53
+ "count": {
54
+ "type": "integer",
55
+ "minimum": 0
56
+ },
57
+ "positive": {
58
+ "type": "integer",
59
+ "minimum": 1
60
+ },
61
+ "size": {
62
+ "type": "array",
63
+ "prefixItems": [
64
+ {
65
+ "$ref": "#/$defs/positive"
66
+ },
67
+ {
68
+ "$ref": "#/$defs/positive"
69
+ }
70
+ ],
71
+ "minItems": 2,
72
+ "maxItems": 2
73
+ },
74
+ "point": {
75
+ "type": "array",
76
+ "prefixItems": [
77
+ {
78
+ "type": "number"
79
+ },
80
+ {
81
+ "type": "number"
82
+ }
83
+ ],
84
+ "minItems": 2,
85
+ "maxItems": 2
86
+ },
87
+ "offset": {
88
+ "type": "array",
89
+ "prefixItems": [
90
+ {
91
+ "$ref": "#/$defs/int"
92
+ },
93
+ {
94
+ "$ref": "#/$defs/int"
95
+ }
96
+ ],
97
+ "minItems": 2,
98
+ "maxItems": 2
99
+ },
100
+ "frame": {
101
+ "type": "object",
102
+ "required": ["name", "rect"],
103
+ "properties": {
104
+ "name": {
105
+ "type": "string",
106
+ "minLength": 1
107
+ },
108
+ "rect": {
109
+ "type": "array",
110
+ "description": "[x, y, w, h]: where the pixels sit on the sheet, at their upright size.",
111
+ "prefixItems": [
112
+ {
113
+ "$ref": "#/$defs/count"
114
+ },
115
+ {
116
+ "$ref": "#/$defs/count"
117
+ },
118
+ {
119
+ "$ref": "#/$defs/positive"
120
+ },
121
+ {
122
+ "$ref": "#/$defs/positive"
123
+ }
124
+ ],
125
+ "minItems": 4,
126
+ "maxItems": 4
127
+ },
128
+ "pivot": {
129
+ "$ref": "#/$defs/point",
130
+ "description": "[x, y] in full-frame pixels. Defaults to the bottom centre."
131
+ },
132
+ "rotated": {
133
+ "type": "boolean",
134
+ "default": false,
135
+ "description": "Stored turned 90\u00b0 clockwise: covers h columns and w rows on the sheet."
136
+ },
137
+ "trim": {
138
+ "type": "array",
139
+ "description": "[x, y, fullWidth, fullHeight]: transparent edges were cut off; the pixels start at x, y inside a full frame of this size.",
140
+ "prefixItems": [
141
+ {
142
+ "$ref": "#/$defs/count"
143
+ },
144
+ {
145
+ "$ref": "#/$defs/count"
146
+ },
147
+ {
148
+ "$ref": "#/$defs/positive"
149
+ },
150
+ {
151
+ "$ref": "#/$defs/positive"
152
+ }
153
+ ],
154
+ "minItems": 4,
155
+ "maxItems": 4
156
+ }
157
+ }
158
+ },
159
+ "layer": {
160
+ "type": "object",
161
+ "required": ["frame"],
162
+ "properties": {
163
+ "frame": {
164
+ "$ref": "#/$defs/count",
165
+ "description": "Index into frames."
166
+ },
167
+ "x": {
168
+ "$ref": "#/$defs/int",
169
+ "default": 0,
170
+ "description": "Layer's full-frame left, from the base frame's left."
171
+ },
172
+ "y": {
173
+ "$ref": "#/$defs/int",
174
+ "default": 0,
175
+ "description": "Layer's full-frame top, from the base frame's top."
176
+ },
177
+ "z": {
178
+ "$ref": "#/$defs/int",
179
+ "default": 1,
180
+ "description": "Draw order; the base frame is 0."
181
+ },
182
+ "opacity": {
183
+ "type": "number",
184
+ "minimum": 0,
185
+ "maximum": 1,
186
+ "default": 1
187
+ },
188
+ "flipX": {
189
+ "type": "boolean",
190
+ "default": false
191
+ },
192
+ "flipY": {
193
+ "type": "boolean",
194
+ "default": false
195
+ }
196
+ }
197
+ },
198
+ "animationFrame": {
199
+ "oneOf": [
200
+ {
201
+ "$ref": "#/$defs/count",
202
+ "description": "A frame index, with the animation's duration."
203
+ },
204
+ {
205
+ "type": "object",
206
+ "required": ["frame"],
207
+ "properties": {
208
+ "frame": {
209
+ "$ref": "#/$defs/count"
210
+ },
211
+ "duration": {
212
+ "$ref": "#/$defs/positive",
213
+ "description": "Milliseconds."
214
+ },
215
+ "offset": {
216
+ "$ref": "#/$defs/offset",
217
+ "description": "[x, y] nudge from where the pivot puts the frame; +x right, +y down."
218
+ },
219
+ "layers": {
220
+ "type": "array",
221
+ "items": {
222
+ "$ref": "#/$defs/layer"
223
+ }
224
+ },
225
+ "events": {
226
+ "type": "array",
227
+ "description": "Names fired when this frame starts showing, such as \"hit\" or \"step\".",
228
+ "items": {
229
+ "type": "string",
230
+ "minLength": 1
231
+ }
232
+ }
233
+ }
234
+ }
235
+ ]
236
+ },
237
+ "animation": {
238
+ "type": "object",
239
+ "required": ["name", "frames"],
240
+ "properties": {
241
+ "name": {
242
+ "type": "string",
243
+ "minLength": 1
244
+ },
245
+ "loop": {
246
+ "enum": ["loop", "pingpong", "once"],
247
+ "default": "loop"
248
+ },
249
+ "duration": {
250
+ "$ref": "#/$defs/positive",
251
+ "default": 100,
252
+ "description": "Milliseconds for frames that don't give their own."
253
+ },
254
+ "frames": {
255
+ "type": "array",
256
+ "items": {
257
+ "$ref": "#/$defs/animationFrame"
258
+ }
259
+ },
260
+ "lighting": {
261
+ "$ref": "#/$defs/lighting"
262
+ }
263
+ }
264
+ },
265
+ "lighting": {
266
+ "type": "object",
267
+ "description": "SpriteBuddy Pro's lighting settings for the animation, kept so the editor can read them back. Runtimes ignore them. Missing values mean the editor's defaults.",
268
+ "properties": {
269
+ "light": {
270
+ "type": "object",
271
+ "properties": {
272
+ "angle": {
273
+ "type": "number",
274
+ "minimum": 0,
275
+ "exclusiveMaximum": 360,
276
+ "description": "Where the light comes from, in degrees clockwise from the top."
277
+ },
278
+ "height": {
279
+ "type": "number",
280
+ "minimum": -90,
281
+ "maximum": 90,
282
+ "description": "Elevation in degrees: 90 shines from the viewer, below 0 from behind."
283
+ },
284
+ "size": {
285
+ "type": "number",
286
+ "minimum": 0,
287
+ "maximum": 1
288
+ },
289
+ "color": {
290
+ "type": "string",
291
+ "pattern": "^#[0-9a-fA-F]{6}$"
292
+ },
293
+ "brightness": {
294
+ "type": "number",
295
+ "minimum": 0,
296
+ "maximum": 3
297
+ },
298
+ "ambient": {
299
+ "type": "number",
300
+ "minimum": 0,
301
+ "maximum": 1
302
+ },
303
+ "opacity": {
304
+ "type": "number",
305
+ "minimum": 0,
306
+ "maximum": 1
307
+ },
308
+ "bands": {
309
+ "enum": [0, 2, 3, 4]
310
+ },
311
+ "paletteSnap": {
312
+ "type": "boolean"
313
+ }
314
+ }
315
+ },
316
+ "normals": {
317
+ "type": "object",
318
+ "properties": {
319
+ "shape": {
320
+ "enum": ["pillow", "bevel"]
321
+ },
322
+ "depth": {
323
+ "type": "number",
324
+ "minimum": 0,
325
+ "maximum": 1
326
+ },
327
+ "softness": {
328
+ "type": "integer",
329
+ "minimum": 1,
330
+ "maximum": 32
331
+ },
332
+ "detail": {
333
+ "type": "number",
334
+ "minimum": 0,
335
+ "maximum": 1
336
+ }
337
+ }
338
+ }
339
+ }
340
+ }
341
+ }
342
+ }