@ikijs/engine 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/README.md +7 -4
- package/dist/index.d.mts +23 -1
- package/dist/index.d.ts +23 -1
- package/dist/index.js +42 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +42 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +17 -3
package/dist/index.mjs
CHANGED
|
@@ -417,6 +417,10 @@ var IkiPlayer = class {
|
|
|
417
417
|
textures = [];
|
|
418
418
|
/** Bumped by every `load` and by `destroy`; lets a stale async load bail. */
|
|
419
419
|
loadGeneration = 0;
|
|
420
|
+
/** True from the moment `load()` is entered until it resolves or throws. */
|
|
421
|
+
loadPending = false;
|
|
422
|
+
/** Latches the un-awaited-load report, so a repeat caller says it once. */
|
|
423
|
+
warnedLoadUnfinished = false;
|
|
420
424
|
destroyed = false;
|
|
421
425
|
/**
|
|
422
426
|
* Engine-internal mesh buffers, keyed by the part's INDEX in `this.parts`
|
|
@@ -444,8 +448,21 @@ var IkiPlayer = class {
|
|
|
444
448
|
* Mesh buffer allocation failure IS fatal (unlike per-texture skip) because
|
|
445
449
|
* textures have an `IkiLoadResult.failedTextures` reporting surface and mesh
|
|
446
450
|
* buffers have none — there is no partial-mesh concept in the format.
|
|
451
|
+
*
|
|
452
|
+
* AWAIT THIS before reading {@link getParameters}. The swap happens after
|
|
453
|
+
* texture decoding, so an un-awaited `load()` leaves the parameter store
|
|
454
|
+
* empty for the rest of the tick; `getParameters` reports that case rather
|
|
455
|
+
* than letting a host conclude the model drives nothing.
|
|
447
456
|
*/
|
|
448
457
|
async load(model) {
|
|
458
|
+
this.loadPending = true;
|
|
459
|
+
try {
|
|
460
|
+
return await this.adoptModel(model);
|
|
461
|
+
} finally {
|
|
462
|
+
this.loadPending = false;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
async adoptModel(model) {
|
|
449
466
|
const { gl } = this;
|
|
450
467
|
const generation = ++this.loadGeneration;
|
|
451
468
|
const sources = model.textures ?? [];
|
|
@@ -657,8 +674,24 @@ var IkiPlayer = class {
|
|
|
657
674
|
getParameter(id) {
|
|
658
675
|
return this.params.get(id);
|
|
659
676
|
}
|
|
660
|
-
/**
|
|
677
|
+
/**
|
|
678
|
+
* The model's parameter descriptors, for building UI or host wiring.
|
|
679
|
+
*
|
|
680
|
+
* Empty until the first {@link load} resolves. Reaching it through an
|
|
681
|
+
* un-awaited `load()` is the one mistake in this class that produces no
|
|
682
|
+
* error and no motion: the caller gets `[]`, concludes the model has no
|
|
683
|
+
* parameters, and drives nothing — so that case is reported instead of
|
|
684
|
+
* being indistinguishable from a model that really declares none. A
|
|
685
|
+
* reload is deliberately NOT reported: those parameters are stale rather
|
|
686
|
+
* than absent, and warning there would fire on legitimate concurrent reads.
|
|
687
|
+
*/
|
|
661
688
|
getParameters() {
|
|
689
|
+
if (this.loadPending && this.model === void 0 && !this.warnedLoadUnfinished) {
|
|
690
|
+
this.warnedLoadUnfinished = true;
|
|
691
|
+
console.error(
|
|
692
|
+
"Iki: getParameters() ran before load() finished, so it returned an empty list \u2014 await load() before reading parameters."
|
|
693
|
+
);
|
|
694
|
+
}
|
|
662
695
|
return this.params.list();
|
|
663
696
|
}
|
|
664
697
|
destroy() {
|
|
@@ -1016,6 +1049,8 @@ var SWAY_X_AMP_B_DEG = 1.3;
|
|
|
1016
1049
|
var SWAY_X_PERIOD_B_MS = 9700;
|
|
1017
1050
|
var SWAY_Y_AMP_DEG = 1.6;
|
|
1018
1051
|
var SWAY_Y_PERIOD_MS = 7300;
|
|
1052
|
+
var SWAY_Z_AMP_DEG = 1.1;
|
|
1053
|
+
var SWAY_Z_PERIOD_MS = 11300;
|
|
1019
1054
|
function lerp(a, b, t) {
|
|
1020
1055
|
return a + (b - a) * t;
|
|
1021
1056
|
}
|
|
@@ -1089,6 +1124,7 @@ var IdleMotion = class {
|
|
|
1089
1124
|
this.sink(StandardParameter.EyeballY, this.gazeCurrentY);
|
|
1090
1125
|
this.sink(StandardParameter.AngleX, this.swayX());
|
|
1091
1126
|
this.sink(StandardParameter.AngleY, this.swayY());
|
|
1127
|
+
this.sink(StandardParameter.AngleZ, this.swayZ());
|
|
1092
1128
|
}
|
|
1093
1129
|
// ---------------------------------------------------------------------------
|
|
1094
1130
|
// Private helpers
|
|
@@ -1101,6 +1137,7 @@ var IdleMotion = class {
|
|
|
1101
1137
|
this.sink(StandardParameter.EyeballY, 0);
|
|
1102
1138
|
this.sink(StandardParameter.AngleX, 0);
|
|
1103
1139
|
this.sink(StandardParameter.AngleY, 0);
|
|
1140
|
+
this.sink(StandardParameter.AngleZ, 0);
|
|
1104
1141
|
}
|
|
1105
1142
|
/** Returns the current eye-open value (0..1) and advances blink state. */
|
|
1106
1143
|
advanceBlink() {
|
|
@@ -1132,6 +1169,10 @@ var IdleMotion = class {
|
|
|
1132
1169
|
swayY() {
|
|
1133
1170
|
return SWAY_Y_AMP_DEG * Math.sin(2 * Math.PI * this.clockMs / SWAY_Y_PERIOD_MS);
|
|
1134
1171
|
}
|
|
1172
|
+
/** Head roll sway in degrees, pure function of the internal clock. */
|
|
1173
|
+
swayZ() {
|
|
1174
|
+
return SWAY_Z_AMP_DEG * Math.sin(2 * Math.PI * this.clockMs / SWAY_Z_PERIOD_MS);
|
|
1175
|
+
}
|
|
1135
1176
|
/** Ease gaze current toward target; pick a new target on the internal clock. */
|
|
1136
1177
|
advanceGaze(dt) {
|
|
1137
1178
|
if (this.clockMs >= this.nextGazeRetargetMs) {
|