@energy8platform/golem 0.1.1 → 0.2.1
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/dist/editor.js +926 -2
- package/dist/lib/editor/stage.d.ts +17 -0
- package/dist/lib/editor/store.d.ts +2 -0
- package/dist/lib/rig-runtime.d.ts +6 -0
- package/dist/lib/runtime.js +9 -1
- package/dist/lib/runtime.js.map +2 -2
- package/package.json +1 -1
|
@@ -49,6 +49,12 @@ export declare class Stage {
|
|
|
49
49
|
private applyDraft;
|
|
50
50
|
/** push the shown pose (and slot visibility) into the player, then redraw the overlay */
|
|
51
51
|
private applyPose;
|
|
52
|
+
/**
|
|
53
|
+
* The slots the selection is about — a slot, the one an attachment (or a vertex of it) hangs in, or every slot on
|
|
54
|
+
* a selected bone. The player draws them half-visible at least, so a part faded out at rest (runes that only light
|
|
55
|
+
* up in `win`) is not an invisible box of grips. Not while playing: the animation's own fade is what is watched.
|
|
56
|
+
*/
|
|
57
|
+
private selectedSlots;
|
|
52
58
|
private reference?;
|
|
53
59
|
private referenceSrc?;
|
|
54
60
|
/** the underlay is on screen — a texture loaded and the sprite visible (tests read it) */
|
|
@@ -57,6 +63,17 @@ export declare class Stage {
|
|
|
57
63
|
private applyReference;
|
|
58
64
|
private startPlayback;
|
|
59
65
|
private tick;
|
|
66
|
+
/** one export at a time: two runs would interleave their seeks into the same player and produce a mixed file */
|
|
67
|
+
private exporting;
|
|
68
|
+
/**
|
|
69
|
+
* The current animation as GIF bytes — the top bar hands them to a download link, and the tests read them.
|
|
70
|
+
*
|
|
71
|
+
* Each frame is the DOCUMENT rectangle rendered on its own: `extract` REPLACES the target's transform with the
|
|
72
|
+
* frame's, so the file ignores the camera's zoom and pan and comes out at `meta.width` × `meta.height` whatever
|
|
73
|
+
* is on screen. The overlay (bones, labels, gizmos) is switched off for the duration, so nothing of the editor
|
|
74
|
+
* ends up in it; the paper stays, which is what makes every pixel opaque — GIF has no partial transparency.
|
|
75
|
+
*/
|
|
76
|
+
exportGif(fps?: number): Promise<Uint8Array<ArrayBuffer> | undefined>;
|
|
60
77
|
/** doc px → screen px (canvas client coords); the camera never rotates, so this is exact without a render */
|
|
61
78
|
toScreen(x: number, y: number): [number, number];
|
|
62
79
|
toDoc(sx: number, sy: number): [number, number];
|
|
@@ -1001,6 +1001,8 @@ export declare function setBoneTool(on: boolean): void;
|
|
|
1001
1001
|
export declare function placeBone(from: [number, number], to: [number, number]): Promise<void>;
|
|
1002
1002
|
/** clicks on images select their slot's bone instead — the images are "locked", as Spine puts it */
|
|
1003
1003
|
export declare const lockImages: import("@preact/signals-core").Signal<boolean>;
|
|
1004
|
+
/** draw the bone overlay — lines, joints and labels. Off is for looking at the art alone; the GIF export forces it off anyway */
|
|
1005
|
+
export declare const showBones: import("@preact/signals-core").Signal<boolean>;
|
|
1004
1006
|
/** collapsed panel sections by id */
|
|
1005
1007
|
export declare const sections: import("@preact/signals-core").Signal<Record<string, boolean>>;
|
|
1006
1008
|
export declare function toggleSection(id: string): void;
|
|
@@ -14,6 +14,8 @@ import { type Pose, type Affine } from "./rig-anim";
|
|
|
14
14
|
import { AnimationState, type PlayResult } from "./rig-state";
|
|
15
15
|
/** vertices per axis of a lattice-deformed region's render mesh (8 segments) */
|
|
16
16
|
export declare const MESH_GRID = 9;
|
|
17
|
+
/** the least alpha an editor-selected slot is drawn with, so a part faded out at rest can still be seen */
|
|
18
|
+
export declare const GHOST_ALPHA = 0.5;
|
|
17
19
|
export interface PlayOptions {
|
|
18
20
|
loop?: boolean;
|
|
19
21
|
/** crossfade seconds from current pose */
|
|
@@ -38,6 +40,8 @@ export declare class RigPlayer {
|
|
|
38
40
|
private pages;
|
|
39
41
|
/** slots the editor hides; honoured by setPose */
|
|
40
42
|
private hidden;
|
|
43
|
+
/** slots the editor has selected; setPose draws them at GHOST_ALPHA at least */
|
|
44
|
+
private ghosts;
|
|
41
45
|
/** `mix`: default crossfade seconds for state transitions (setBase, completion → base); play() passes its own */
|
|
42
46
|
constructor(doc: RigDocument, textures: Map<string, Texture>, opts?: {
|
|
43
47
|
mix?: number;
|
|
@@ -53,6 +57,8 @@ export declare class RigPlayer {
|
|
|
53
57
|
updateDoc(doc: RigDocument): void;
|
|
54
58
|
/** Editor-only: hide a slot's display object regardless of the pose (restored by passing `true`). */
|
|
55
59
|
setSlotVisible(slotId: string, visible: boolean): void;
|
|
60
|
+
/** Editor-only: draw these slots at GHOST_ALPHA at least, whatever the pose says (an empty list clears it). */
|
|
61
|
+
setGhostSlots(slotIds: Iterable<string>): void;
|
|
56
62
|
/** Stop playback and immediately restore the complete setup pose. */
|
|
57
63
|
stop(): void;
|
|
58
64
|
/** dt in seconds */
|
package/dist/lib/runtime.js
CHANGED
|
@@ -1311,6 +1311,7 @@ function hit(t, prev, cur, d, loop) {
|
|
|
1311
1311
|
// src/rig-runtime.ts
|
|
1312
1312
|
var DEG3 = Math.PI / 180;
|
|
1313
1313
|
var MESH_GRID = 9;
|
|
1314
|
+
var GHOST_ALPHA = 0.5;
|
|
1314
1315
|
async function createTextures(doc, loadSource) {
|
|
1315
1316
|
const bySrc = /* @__PURE__ */ new Map(), out = /* @__PURE__ */ new Map();
|
|
1316
1317
|
for (const a of doc.assets) {
|
|
@@ -1400,6 +1401,8 @@ var RigPlayer = class {
|
|
|
1400
1401
|
pages = /* @__PURE__ */ new Map();
|
|
1401
1402
|
/** slots the editor hides; honoured by setPose */
|
|
1402
1403
|
hidden = /* @__PURE__ */ new Set();
|
|
1404
|
+
/** slots the editor has selected; setPose draws them at GHOST_ALPHA at least */
|
|
1405
|
+
ghosts = /* @__PURE__ */ new Set();
|
|
1403
1406
|
/** whole atlas page as a plain texture (identity uv mapping) for skinned meshes */
|
|
1404
1407
|
pageTexture(tex) {
|
|
1405
1408
|
let page = this.pages.get(tex.source);
|
|
@@ -1440,6 +1443,10 @@ var RigPlayer = class {
|
|
|
1440
1443
|
if (visible) this.hidden.delete(slotId);
|
|
1441
1444
|
else this.hidden.add(slotId);
|
|
1442
1445
|
}
|
|
1446
|
+
/** Editor-only: draw these slots at GHOST_ALPHA at least, whatever the pose says (an empty list clears it). */
|
|
1447
|
+
setGhostSlots(slotIds) {
|
|
1448
|
+
this.ghosts = new Set(slotIds);
|
|
1449
|
+
}
|
|
1443
1450
|
/** Stop playback and immediately restore the complete setup pose. */
|
|
1444
1451
|
stop() {
|
|
1445
1452
|
this.state.stop();
|
|
@@ -1464,7 +1471,8 @@ var RigPlayer = class {
|
|
|
1464
1471
|
it.node.visible = true;
|
|
1465
1472
|
const colorV = pose.get(pk("slot", s.id, "color"));
|
|
1466
1473
|
const color = Array.isArray(colorV) && typeof colorV[0] === "number" ? colorV : colorToArray(s.color);
|
|
1467
|
-
|
|
1474
|
+
const alpha = numOf(pose, pk("slot", s.id, "alpha"), s.alpha) * color[3];
|
|
1475
|
+
it.node.alpha = this.ghosts.has(s.id) ? Math.max(alpha, GHOST_ALPHA) : alpha;
|
|
1468
1476
|
it.node.tint = rgbOf(color);
|
|
1469
1477
|
it.node.zIndex = order.size ? order.get(s.id) ?? 0 : numOf(pose, pk("slot", s.id, "z"), s.z);
|
|
1470
1478
|
if (it.skinned) {
|