@rig-c/play 1.18.0 → 1.19.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/dist/index.js +92 -14
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -964,7 +964,8 @@ function clipHalf(input, p, q) {
|
|
|
964
964
|
return { points: out, cut };
|
|
965
965
|
}
|
|
966
966
|
function clipThrough(shape, vertices, triangles, uvs, clip = clipTriangles, reading = {}) {
|
|
967
|
-
|
|
967
|
+
let plan = clipShapeOf(shape);
|
|
968
|
+
if (plan.kind === "pieces") plan = clipShapeOf({ ...shape, polygon: shape.polygon.map(Math.fround) });
|
|
968
969
|
if (plan.kind === "refused") return null;
|
|
969
970
|
if (plan.kind === "convex") return clip(plan.polygon, vertices, triangles, uvs);
|
|
970
971
|
const f = Math.fround;
|
|
@@ -9034,7 +9035,37 @@ function channelValue(curve, i, c, t) {
|
|
|
9034
9035
|
const y0 = p[o + q - 1];
|
|
9035
9036
|
return y0 + (t - x0) / (p[o + q] - x0) * (p[o + q + 1] - y0);
|
|
9036
9037
|
}
|
|
9037
|
-
|
|
9038
|
+
function compileDeformCurve(keys) {
|
|
9039
|
+
const curve = compileCurve(keys.map((k) => ({ time: k.time, values: [0], curve: "linear", stated: { time: k.stated, values: [0] } })), 1);
|
|
9040
|
+
for (let i = 0; i < keys.length; i++) {
|
|
9041
|
+
const a = keys[i];
|
|
9042
|
+
curve.kinds[i] = a.curve === "linear" ? CURVE_LINEAR : a.curve === "stepped" ? CURVE_STEPPED : CURVE_BEZIER;
|
|
9043
|
+
if (typeof a.curve === "string" || i + 1 === keys.length) continue;
|
|
9044
|
+
const b = keys[i + 1];
|
|
9045
|
+
const c = a.curve;
|
|
9046
|
+
const inner = bezierPolyline(a.stated, 0, c[0], c[1], c[2], c[3], b.stated, DEFORM_CURVE_END);
|
|
9047
|
+
const o = i * POLYLINE;
|
|
9048
|
+
curve.polylines[o] = a.time;
|
|
9049
|
+
curve.polylines[o + 1] = 0;
|
|
9050
|
+
curve.polylines.set(inner, o + 2);
|
|
9051
|
+
curve.polylines[o + POLYLINE - 2] = b.time;
|
|
9052
|
+
curve.polylines[o + POLYLINE - 1] = 1;
|
|
9053
|
+
}
|
|
9054
|
+
return curve;
|
|
9055
|
+
}
|
|
9056
|
+
function deformFraction(curve, i, t) {
|
|
9057
|
+
if (curve.kinds[i] === CURVE_STEPPED) return 0;
|
|
9058
|
+
if (curve.kinds[i] === CURVE_LINEAR) return (t - curve.times[i]) / (curve.times[i + 1] - curve.times[i]);
|
|
9059
|
+
const p = curve.polylines;
|
|
9060
|
+
const o = i * POLYLINE;
|
|
9061
|
+
let q = 2;
|
|
9062
|
+
while (q < POLYLINE - 2 && p[o + q] < t) q += 2;
|
|
9063
|
+
const x0 = p[o + q - 2], y0 = p[o + q - 1], x1 = p[o + q], y1 = p[o + q + 1];
|
|
9064
|
+
if (q === 2) return y1 * (t - x0) / (x1 - x0);
|
|
9065
|
+
if (q === POLYLINE - 2) return y0 + (1 - y0) * (t - x0) / (x1 - x0);
|
|
9066
|
+
return y0 + (t - x0) / (x1 - x0) * (y1 - y0);
|
|
9067
|
+
}
|
|
9068
|
+
const RUNTIME_STAGE = 2;
|
|
9038
9069
|
function missingText(m) {
|
|
9039
9070
|
return `${m.feature}: ${m.detail}${m.animation === null ? "" : ` (animation "${m.animation}")`}`;
|
|
9040
9071
|
}
|
|
@@ -9178,6 +9209,7 @@ function compileRuntime(doc, options = {}, plant = {}) {
|
|
|
9178
9209
|
}
|
|
9179
9210
|
const attachments = [];
|
|
9180
9211
|
let vertexCount = 0;
|
|
9212
|
+
let deformCount = 0;
|
|
9181
9213
|
const sourceOf = sourceOfDoc(doc);
|
|
9182
9214
|
const attachmentView = plant.attachmentSkin === void 0 ? doc : underSkin(doc, plant.attachmentSkin);
|
|
9183
9215
|
const resolvedBySlot = doc.slots.map(() => /* @__PURE__ */ new Map());
|
|
@@ -9198,7 +9230,7 @@ function compileRuntime(doc, options = {}, plant = {}) {
|
|
|
9198
9230
|
if ("conflict" in shown) return { index: -1, missing: ["skin-conflict", `slot "${slot.name}" placeholder "${placeholder}" is filled by skins that disagree`] };
|
|
9199
9231
|
const row = shownRow(shown);
|
|
9200
9232
|
const g = shown.record.geometry;
|
|
9201
|
-
const at = { slot: si, name: row.name, skin: shown.skin, placeholder: shown.placeholder, path: CORE_REGION_KINDS.has(shown.record.kind) ? row.path : null, bone: indexOf(slot.bone), offset: vertexCount };
|
|
9233
|
+
const at = { timeline: timelineIdentity(slot.name, shown), deformOffset: deformCount, slot: si, name: row.name, skin: shown.skin, placeholder: shown.placeholder, path: CORE_REGION_KINDS.has(shown.record.kind) ? row.path : null, bone: indexOf(slot.bone), offset: vertexCount };
|
|
9202
9234
|
let made = null;
|
|
9203
9235
|
let missing = null;
|
|
9204
9236
|
if (g?.kind === "clipping") missing = ["clipping", `slot "${slot.name}" shows clipping attachment "${row.name}"`];
|
|
@@ -9240,6 +9272,7 @@ function compileRuntime(doc, options = {}, plant = {}) {
|
|
|
9240
9272
|
if (made === null) made = vertexAttachment(at, DRAW_NONE, new Float64Array(0), 0);
|
|
9241
9273
|
attachments.push(made);
|
|
9242
9274
|
vertexCount += made.count;
|
|
9275
|
+
deformCount += made.deformCount;
|
|
9243
9276
|
return { index: attachments.length - 1, missing };
|
|
9244
9277
|
};
|
|
9245
9278
|
const slots = doc.slots.map((slot, si) => {
|
|
@@ -9261,7 +9294,7 @@ function compileRuntime(doc, options = {}, plant = {}) {
|
|
|
9261
9294
|
const refused = [];
|
|
9262
9295
|
let cursorMax = 0;
|
|
9263
9296
|
for (const anim of doc.animations) {
|
|
9264
|
-
const compiled = compileAnimation(anim, refusals, ignoreEvents, boneIndex2, slotIndex, slots, constraints, (si, ph) => resolve(si, ph, anim.name));
|
|
9297
|
+
const compiled = compileAnimation(anim, refusals, ignoreEvents, boneIndex2, slotIndex, slots, constraints, doc, (si, ph) => resolve(si, ph, anim.name));
|
|
9265
9298
|
const missing = refusals.byAnimation.get(anim.name);
|
|
9266
9299
|
if (missing !== void 0 && missing.length > 0) refused.push({ animation: anim.name, missing });
|
|
9267
9300
|
else {
|
|
@@ -9272,6 +9305,9 @@ function compileRuntime(doc, options = {}, plant = {}) {
|
|
|
9272
9305
|
if (refusals.model.length > 0) throw new RuntimeRefusal(refusals.model);
|
|
9273
9306
|
const names = doc.animations.map((a) => a.name);
|
|
9274
9307
|
return {
|
|
9308
|
+
omitDeform: plant.omitDeform === true,
|
|
9309
|
+
deformAfterWeights: plant.deformAfterWeights === true,
|
|
9310
|
+
deformCount,
|
|
9275
9311
|
eventWrapOffByOne: plant.eventWrapOffByOne === true,
|
|
9276
9312
|
restoreEventsFromStart: plant.restoreEventsFromStart === true,
|
|
9277
9313
|
doc,
|
|
@@ -9303,7 +9339,7 @@ function compileRuntime(doc, options = {}, plant = {}) {
|
|
|
9303
9339
|
const NO_INTS = new Int32Array(0);
|
|
9304
9340
|
const NO_NUMBERS = new Float64Array(0);
|
|
9305
9341
|
function vertexAttachment(at, draw, local, count) {
|
|
9306
|
-
return { ...at, draw, local, count, bindingCounts: NO_INTS, bindingBones: NO_INTS, bindingX: NO_NUMBERS, bindingY: NO_NUMBERS, bindingWeights: NO_NUMBERS };
|
|
9342
|
+
return { ...at, draw, local, count, deformCount: draw === DRAW_MESH ? count : 0, bindingCounts: NO_INTS, bindingBones: NO_INTS, bindingX: NO_NUMBERS, bindingY: NO_NUMBERS, bindingWeights: NO_NUMBERS };
|
|
9307
9343
|
}
|
|
9308
9344
|
function meshAttachment(at, vertices, indexOf, rewrite, bones) {
|
|
9309
9345
|
if (!vertices.weighted) {
|
|
@@ -9327,7 +9363,7 @@ function meshAttachment(at, vertices, indexOf, rewrite, bones) {
|
|
|
9327
9363
|
ws.push(Math.fround(b.weight));
|
|
9328
9364
|
}
|
|
9329
9365
|
}
|
|
9330
|
-
return { ...at, draw: DRAW_WEIGHTED, local: NO_NUMBERS, count: counts.length * 2, bindingCounts: Int32Array.from(counts), bindingBones: Int32Array.from(ids), bindingX: Float64Array.from(xs), bindingY: Float64Array.from(ys), bindingWeights: Float64Array.from(ws) };
|
|
9366
|
+
return { ...at, deformCount: ids.length * 2, draw: DRAW_WEIGHTED, local: NO_NUMBERS, count: counts.length * 2, bindingCounts: Int32Array.from(counts), bindingBones: Int32Array.from(ids), bindingX: Float64Array.from(xs), bindingY: Float64Array.from(ys), bindingWeights: Float64Array.from(ws) };
|
|
9331
9367
|
}
|
|
9332
9368
|
function compileIk(r, index, applied, bones, indexOf) {
|
|
9333
9369
|
return {
|
|
@@ -9387,13 +9423,12 @@ function compileTransform(r, index, applied, bones, indexOf) {
|
|
|
9387
9423
|
clamp: r.clamp
|
|
9388
9424
|
};
|
|
9389
9425
|
}
|
|
9390
|
-
function compileAnimation(anim, refusals, ignoreEvents, boneIndex2, slotIndex, slots, constraints, resolve) {
|
|
9426
|
+
function compileAnimation(anim, refusals, ignoreEvents, boneIndex2, slotIndex, slots, constraints, doc, resolve) {
|
|
9391
9427
|
const tl = anim.timelines;
|
|
9392
9428
|
const name = anim.name;
|
|
9393
9429
|
let cursors = 0;
|
|
9394
9430
|
const deform = tl.attachments.filter((a) => a.deform !== null);
|
|
9395
9431
|
const sequence = tl.attachments.filter((a) => a.sequence !== null);
|
|
9396
|
-
if (deform.length > 0) refusals.note("deform-timeline", `${deform.length} deform timeline(s): ${deform.slice(0, 3).map((a) => `${a.skin}/${a.slot}/${a.attachment}`).join(", ")}${deform.length > 3 ? ", …" : ""}`, name);
|
|
9397
9432
|
if (sequence.length > 0) refusals.note("sequence-timeline", `${sequence.length} sequence timeline(s): ${sequence.slice(0, 3).map((a) => `${a.skin}/${a.slot}/${a.attachment}`).join(", ")}${sequence.length > 3 ? ", …" : ""}`, name);
|
|
9398
9433
|
if (tl.drawOrder.length > 0) refusals.note("draw-order-timeline", `${tl.drawOrder.length} draw-order key(s)`, name);
|
|
9399
9434
|
const lastBy = (targets) => new Map(targets.map((t) => [t.name, t]));
|
|
@@ -9441,7 +9476,14 @@ function compileAnimation(anim, refusals, ignoreEvents, boneIndex2, slotIndex, s
|
|
|
9441
9476
|
constraintTimelines[c.index] = { constraint: c.index, curve: compileCurve(keyed.keys, TRANSFORM_PROPERTIES.length), cursor: cursors++, flags: null };
|
|
9442
9477
|
}
|
|
9443
9478
|
}
|
|
9444
|
-
|
|
9479
|
+
const deforms = deform.map((a) => {
|
|
9480
|
+
const g = doc.skins.find((s) => s.name === a.skin)?.attachments[a.slot]?.[a.attachment]?.geometry;
|
|
9481
|
+
if (g === void 0 || g.kind === "region" || g.kind === "linkedmesh") throw new RuntimeInputError(`deform "${a.skin}/${a.slot}/${a.attachment}" has no vertex geometry (readModel refuses it first)`);
|
|
9482
|
+
const keys = a.deform;
|
|
9483
|
+
const arrays = keys.map((k) => heldArray(g.vertices, k));
|
|
9484
|
+
return { identity: `${a.skin}/${a.slot}/${a.attachment}`, cursor: cursors++, curve: compileDeformCurve(keys), count: arrays[0].length, held: Float64Array.from(arrays.flat()) };
|
|
9485
|
+
});
|
|
9486
|
+
return { name, duration: tl.duration, deforms, bones, slots: slotTimelines, constraints: constraintTimelines, cursors, events: tl.events.length, eventKeys: Object.freeze(ignoreEvents ? [] : tl.events.map((key) => Object.freeze({ name: key.name, time: key.time, int: key.int, float: key.float, string: key.string, volume: key.volume ?? 0, balance: key.balance ?? 0 }))) };
|
|
9445
9487
|
}
|
|
9446
9488
|
const DEG = RUNTIME_DEG;
|
|
9447
9489
|
const TWO_PI = 2 * RUNTIME_PI;
|
|
@@ -9474,6 +9516,8 @@ class RuntimePose {
|
|
|
9474
9516
|
this.light = new Float64Array(ns * 4);
|
|
9475
9517
|
this.shown = new Int32Array(ns);
|
|
9476
9518
|
this.vertices = new Float64Array(model.vertexCount);
|
|
9519
|
+
this.deform = new Float64Array(model.deformCount);
|
|
9520
|
+
this.deformed = new Uint8Array(model.attachments.length);
|
|
9477
9521
|
this.cursors = new Int32Array(Math.max(1, model.cursors)).fill(-1);
|
|
9478
9522
|
this.ikMix = new Float64Array(nc);
|
|
9479
9523
|
this.ikSoftness = new Float64Array(nc);
|
|
@@ -9523,6 +9567,7 @@ class RuntimePose {
|
|
|
9523
9567
|
this.constraintValues(null, 0);
|
|
9524
9568
|
this.solveConstraints();
|
|
9525
9569
|
this.slotValues(null, 0);
|
|
9570
|
+
this.deformValues(null, 0);
|
|
9526
9571
|
}
|
|
9527
9572
|
/** The animation posed at its time `t`, from the setup pose (the header). */
|
|
9528
9573
|
apply(t) {
|
|
@@ -9536,6 +9581,7 @@ class RuntimePose {
|
|
|
9536
9581
|
this.constraintValues(anim, t);
|
|
9537
9582
|
this.solveConstraints();
|
|
9538
9583
|
this.slotValues(anim, t);
|
|
9584
|
+
this.deformValues(anim, t);
|
|
9539
9585
|
}
|
|
9540
9586
|
/** One step of a looping track: the track time moved by `dt`, the animation posed at it wrapped by the duration (`loopedTime` in src/core/raw.ts). */
|
|
9541
9587
|
step(dt) {
|
|
@@ -10245,6 +10291,31 @@ class RuntimePose {
|
|
|
10245
10291
|
}
|
|
10246
10292
|
}
|
|
10247
10293
|
}
|
|
10294
|
+
/** Reset on every pose, then match source identity after switches; no old frame's offsets survive. */
|
|
10295
|
+
deformValues(anim, t) {
|
|
10296
|
+
this.deformed.fill(0);
|
|
10297
|
+
this.deform.fill(0);
|
|
10298
|
+
if (anim === null || this.model.omitDeform) return;
|
|
10299
|
+
for (let k = 0; k < anim.deforms.length; k++) {
|
|
10300
|
+
const tl = anim.deforms[k];
|
|
10301
|
+
const i = keyAt(tl.curve, this.cursors, tl.cursor, t);
|
|
10302
|
+
if (i < 0) continue;
|
|
10303
|
+
const held = i + 1 === tl.curve.keys || tl.curve.kinds[i] === CURVE_STEPPED;
|
|
10304
|
+
const p = held ? 0 : deformFraction(tl.curve, i, t);
|
|
10305
|
+
const start = i * tl.count;
|
|
10306
|
+
for (let s = 0; s < this.shown.length; s++) {
|
|
10307
|
+
const index = this.shown[s];
|
|
10308
|
+
if (index < 0 || !this.model.slots[s].live) continue;
|
|
10309
|
+
const at = this.model.attachments[index];
|
|
10310
|
+
if (at.timeline !== tl.identity || at.deformCount === 0) continue;
|
|
10311
|
+
this.deformed[index] = 1;
|
|
10312
|
+
for (let q = 0; q < tl.count; q++) {
|
|
10313
|
+
const v = tl.held[start + q];
|
|
10314
|
+
this.deform[at.deformOffset + q] = held ? v : v + (tl.held[start + tl.count + q] - v) * p;
|
|
10315
|
+
}
|
|
10316
|
+
}
|
|
10317
|
+
}
|
|
10318
|
+
}
|
|
10248
10319
|
/** Every shown attachment's world vertices into `vertices` at its offset (`regionCorners`, `worldVertices`). */
|
|
10249
10320
|
computeVertices() {
|
|
10250
10321
|
const m = this.model;
|
|
@@ -10266,7 +10337,8 @@ class RuntimePose {
|
|
|
10266
10337
|
const d = W[b + W_D];
|
|
10267
10338
|
const wx = W[b + W_X];
|
|
10268
10339
|
const wy = W[b + W_Y];
|
|
10269
|
-
const local = at.local;
|
|
10340
|
+
const local = this.deformed[index] && at.draw === DRAW_MESH ? this.deform : at.local;
|
|
10341
|
+
const lo = this.deformed[index] && at.draw === DRAW_MESH ? at.deformOffset : 0;
|
|
10270
10342
|
if (at.draw === DRAW_REGION) {
|
|
10271
10343
|
for (let q = 0; q < 8; q += 2) {
|
|
10272
10344
|
const lx = local[q];
|
|
@@ -10276,8 +10348,8 @@ class RuntimePose {
|
|
|
10276
10348
|
}
|
|
10277
10349
|
} else {
|
|
10278
10350
|
for (let q = 0; q < at.count; q += 2) {
|
|
10279
|
-
const x = local[q];
|
|
10280
|
-
const y = local[q + 1];
|
|
10351
|
+
const x = local[lo + q];
|
|
10352
|
+
const y = local[lo + q + 1];
|
|
10281
10353
|
out[o++] = x * a + y * bb + wx;
|
|
10282
10354
|
out[o++] = x * c + y * d + wy;
|
|
10283
10355
|
}
|
|
@@ -10296,9 +10368,15 @@ class RuntimePose {
|
|
|
10296
10368
|
const end = n + counts[v];
|
|
10297
10369
|
for (; n < end; n++) {
|
|
10298
10370
|
const b = bones[n] * WORLDS;
|
|
10299
|
-
const x = xs[n];
|
|
10300
|
-
const y = ys[n];
|
|
10301
10371
|
const weight = weights[n];
|
|
10372
|
+
const deformed = this.deformed[index] !== 0;
|
|
10373
|
+
const x = deformed ? xs[n] + this.deform[at.deformOffset + n * 2] : xs[n];
|
|
10374
|
+
const y = deformed ? ys[n] + this.deform[at.deformOffset + n * 2 + 1] : ys[n];
|
|
10375
|
+
if (deformed && m.deformAfterWeights) {
|
|
10376
|
+
wx += (xs[n] * W[b + W_A] + ys[n] * W[b + W_B] + W[b + W_X]) * weight + this.deform[at.deformOffset + n * 2];
|
|
10377
|
+
wy += (xs[n] * W[b + W_C] + ys[n] * W[b + W_D] + W[b + W_Y]) * weight + this.deform[at.deformOffset + n * 2 + 1];
|
|
10378
|
+
continue;
|
|
10379
|
+
}
|
|
10302
10380
|
wx += (x * W[b + W_A] + y * W[b + W_B] + W[b + W_X]) * weight;
|
|
10303
10381
|
wy += (x * W[b + W_C] + y * W[b + W_D] + W[b + W_Y]) * weight;
|
|
10304
10382
|
}
|