distark-render 1.0.1 → 1.0.3
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 +154 -73
- package/dist/modules/adapters/p5Renderer.d.ts +0 -0
- package/dist/modules/adapters/p5Renderer.d.ts.map +0 -0
- package/dist/modules/adapters/p5Renderer.js +0 -0
- package/dist/modules/adapters/p5Renderer.js.map +0 -0
- package/dist/modules/adapters/skiaRenderer.d.ts +0 -0
- package/dist/modules/adapters/skiaRenderer.d.ts.map +1 -1
- package/dist/modules/adapters/skiaRenderer.js +11 -0
- package/dist/modules/adapters/skiaRenderer.js.map +1 -1
- package/dist/modules/eyeSystem.d.ts +34 -1
- package/dist/modules/eyeSystem.d.ts.map +1 -1
- package/dist/modules/eyeSystem.js +46 -10
- package/dist/modules/eyeSystem.js.map +1 -1
- package/dist/modules/imageLoad.d.ts +0 -0
- package/dist/modules/imageLoad.d.ts.map +1 -1
- package/dist/modules/imageLoad.js +16 -0
- package/dist/modules/imageLoad.js.map +1 -1
- package/dist/modules/mouthSystem.d.ts +15 -15
- package/dist/modules/mouthSystem.d.ts.map +1 -1
- package/dist/modules/mouthSystem.js +91 -52
- package/dist/modules/mouthSystem.js.map +1 -1
- package/dist/modules/renderRig.d.ts +0 -0
- package/dist/modules/renderRig.d.ts.map +1 -1
- package/dist/modules/renderRig.js +92 -16
- package/dist/modules/renderRig.js.map +1 -1
- package/dist/tests/test-joint-movement.d.ts +7 -0
- package/dist/tests/test-joint-movement.d.ts.map +1 -0
- package/dist/tests/test-joint-movement.js +323 -0
- package/dist/tests/test-joint-movement.js.map +1 -0
- package/dist/{test-skia.d.ts → tests/test-skia.d.ts} +0 -0
- package/dist/tests/test-skia.d.ts.map +1 -0
- package/dist/{test-skia.js → tests/test-skia.js} +1 -1
- package/dist/tests/test-skia.js.map +1 -0
- package/dist/tests/test-visual-verification.d.ts +7 -0
- package/dist/tests/test-visual-verification.d.ts.map +1 -0
- package/dist/tests/test-visual-verification.js +180 -0
- package/dist/tests/test-visual-verification.js.map +1 -0
- package/dist/types.d.ts +18 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +0 -0
- package/dist/types.js.map +0 -0
- package/package.json +5 -2
- package/dist/test-skia.d.ts.map +0 -1
- package/dist/test-skia.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mouthSystem.d.ts","sourceRoot":"","sources":["../../modules/mouthSystem.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH
|
|
1
|
+
{"version":3,"file":"mouthSystem.d.ts","sourceRoot":"","sources":["../../modules/mouthSystem.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,7 +15,7 @@ export class MouthSystem {
|
|
|
15
15
|
* @param availableMouths - Set of available mouth shapes for this character
|
|
16
16
|
* @param config - Optional mouth configuration
|
|
17
17
|
*/
|
|
18
|
-
constructor(characterId, availableMouths = new Set(['closed'
|
|
18
|
+
constructor(characterId, availableMouths = new Set(['closed']), config = {}) {
|
|
19
19
|
this.characterId = characterId;
|
|
20
20
|
this.availableMouths = availableMouths;
|
|
21
21
|
this.config = {
|
|
@@ -25,7 +25,7 @@ export class MouthSystem {
|
|
|
25
25
|
visemeMapping: config.visemeMapping ?? MouthSystem.DEFAULT_VISEME_MAPPING
|
|
26
26
|
};
|
|
27
27
|
this.state = {
|
|
28
|
-
currentMouthKey: '
|
|
28
|
+
currentMouthKey: 'closed',
|
|
29
29
|
lastMouthChangeTime: 0,
|
|
30
30
|
currentVolume: 0,
|
|
31
31
|
mode: 'manual'
|
|
@@ -51,9 +51,6 @@ export class MouthSystem {
|
|
|
51
51
|
this.state.currentMouthKey = shape;
|
|
52
52
|
this.state.mode = 'manual';
|
|
53
53
|
}
|
|
54
|
-
else {
|
|
55
|
-
console.warn(`Mouth shape "${shape}" not available for character ${this.characterId}`);
|
|
56
|
-
}
|
|
57
54
|
}
|
|
58
55
|
/**
|
|
59
56
|
* Set available mouth shapes
|
|
@@ -81,7 +78,7 @@ export class MouthSystem {
|
|
|
81
78
|
// Update mouth based on volume
|
|
82
79
|
if (avgVolume < (this.config.volumeThreshold ?? 10)) {
|
|
83
80
|
// Low volume: close mouth
|
|
84
|
-
this.state.currentMouthKey =
|
|
81
|
+
this.state.currentMouthKey = 'closed';
|
|
85
82
|
}
|
|
86
83
|
else {
|
|
87
84
|
// Speaking: change mouth shape periodically
|
|
@@ -94,8 +91,8 @@ export class MouthSystem {
|
|
|
94
91
|
this.state.currentMouthKey = availableTalkingMouths[randomIndex];
|
|
95
92
|
}
|
|
96
93
|
else {
|
|
97
|
-
// Fallback: use any available mouth except
|
|
98
|
-
const fallbackMouths = Array.from(this.availableMouths).filter(m => m !== '
|
|
94
|
+
// Fallback: use any available mouth except closed
|
|
95
|
+
const fallbackMouths = Array.from(this.availableMouths).filter(m => m !== 'closed');
|
|
99
96
|
if (fallbackMouths.length > 0) {
|
|
100
97
|
const randomIndex = Math.floor(Math.random() * fallbackMouths.length);
|
|
101
98
|
this.state.currentMouthKey = fallbackMouths[randomIndex];
|
|
@@ -106,9 +103,9 @@ export class MouthSystem {
|
|
|
106
103
|
}
|
|
107
104
|
}
|
|
108
105
|
else {
|
|
109
|
-
// No audio or paused: reset to
|
|
106
|
+
// No audio or paused: reset to closed
|
|
110
107
|
this.state.currentVolume = 0;
|
|
111
|
-
this.state.currentMouthKey =
|
|
108
|
+
this.state.currentMouthKey = 'closed';
|
|
112
109
|
}
|
|
113
110
|
}
|
|
114
111
|
/**
|
|
@@ -124,14 +121,14 @@ export class MouthSystem {
|
|
|
124
121
|
}
|
|
125
122
|
else {
|
|
126
123
|
// Fallback to closed if viseme not found
|
|
127
|
-
this.state.currentMouthKey =
|
|
124
|
+
this.state.currentMouthKey = 'closed';
|
|
128
125
|
}
|
|
129
126
|
}
|
|
130
127
|
/**
|
|
131
|
-
* Reset mouth to
|
|
128
|
+
* Reset mouth to closed state
|
|
132
129
|
*/
|
|
133
130
|
reset() {
|
|
134
|
-
this.state.currentMouthKey =
|
|
131
|
+
this.state.currentMouthKey = 'closed';
|
|
135
132
|
this.state.currentVolume = 0;
|
|
136
133
|
this.state.lastMouthChangeTime = 0;
|
|
137
134
|
this.state.mode = 'manual';
|
|
@@ -143,19 +140,19 @@ export class MouthSystem {
|
|
|
143
140
|
* @returns The image key for the current mouth (e.g., 'imagePaths.mouth_open')
|
|
144
141
|
*/
|
|
145
142
|
getCurrentMouthImageKey() {
|
|
146
|
-
const currentMouth = this.state.currentMouthKey
|
|
143
|
+
const currentMouth = this.state.currentMouthKey;
|
|
147
144
|
// Map mouth shape to possible image key variations
|
|
148
145
|
const keyMappings = {
|
|
149
|
-
'
|
|
150
|
-
'
|
|
151
|
-
'
|
|
152
|
-
'
|
|
153
|
-
'
|
|
154
|
-
'
|
|
155
|
-
'
|
|
156
|
-
'
|
|
157
|
-
'
|
|
158
|
-
'
|
|
146
|
+
'f': ['f', 'mouth_f'],
|
|
147
|
+
'l': ['l', 'mouth_l'],
|
|
148
|
+
'ds': ['ds', 'mouth_ds'],
|
|
149
|
+
'ee': ['ee', 'mouth_ee'],
|
|
150
|
+
'eh': ['eh', 'mouth_eh'],
|
|
151
|
+
'open': ['open', 'mouth_open'],
|
|
152
|
+
'closed': ['closed', 'mouth_closed'],
|
|
153
|
+
'half-open': ['half-open', 'half_open', 'mouth_half_open'],
|
|
154
|
+
'wide-open': ['wide-open', 'wide_open', 'mouth_wide_open'],
|
|
155
|
+
'slightly-open': ['slightly-open', 'slightly_open', 'mouth_slightly_open']
|
|
159
156
|
};
|
|
160
157
|
const candidates = keyMappings[currentMouth] || [currentMouth];
|
|
161
158
|
// Return the first candidate (renderRig will try all variants)
|
|
@@ -166,18 +163,18 @@ export class MouthSystem {
|
|
|
166
163
|
* Used by renderRig to try multiple image name variations
|
|
167
164
|
*/
|
|
168
165
|
getMouthImageKeyCandidates() {
|
|
169
|
-
const currentMouth = this.state.currentMouthKey
|
|
166
|
+
const currentMouth = this.state.currentMouthKey;
|
|
170
167
|
const keyMappings = {
|
|
171
|
-
'
|
|
172
|
-
'
|
|
173
|
-
'
|
|
174
|
-
'
|
|
175
|
-
'
|
|
176
|
-
'
|
|
177
|
-
'
|
|
178
|
-
'
|
|
179
|
-
'
|
|
180
|
-
'
|
|
168
|
+
'f': ['f', 'mouth_f'],
|
|
169
|
+
'l': ['l', 'mouth_l'],
|
|
170
|
+
'ds': ['ds', 'mouth_ds'],
|
|
171
|
+
'ee': ['ee', 'mouth_ee'],
|
|
172
|
+
'eh': ['eh', 'mouth_eh'],
|
|
173
|
+
'open': ['open', 'mouth_open'],
|
|
174
|
+
'closed': ['closed', 'mouth_closed'],
|
|
175
|
+
'half-open': ['half-open', 'half_open', 'mouth_half_open'],
|
|
176
|
+
'wide-open': ['wide-open', 'wide_open', 'mouth_wide_open'],
|
|
177
|
+
'slightly-open': ['slightly-open', 'slightly_open', 'mouth_slightly_open']
|
|
181
178
|
};
|
|
182
179
|
return keyMappings[currentMouth] || [currentMouth];
|
|
183
180
|
}
|
|
@@ -206,6 +203,7 @@ export class MouthSystem {
|
|
|
206
203
|
}
|
|
207
204
|
/**
|
|
208
205
|
* Default viseme to mouth shape mapping
|
|
206
|
+
* Maps phonemes to actual available mouth shapes
|
|
209
207
|
*/
|
|
210
208
|
MouthSystem.DEFAULT_VISEME_MAPPING = {
|
|
211
209
|
'X': 'closed',
|
|
@@ -214,24 +212,24 @@ MouthSystem.DEFAULT_VISEME_MAPPING = {
|
|
|
214
212
|
'C': 'half-open',
|
|
215
213
|
'D': 'ds',
|
|
216
214
|
'E': 'ee',
|
|
217
|
-
'F': '
|
|
215
|
+
'F': 'f',
|
|
218
216
|
'G': 'half-open',
|
|
219
217
|
'H': 'slightly-open',
|
|
220
218
|
'I': 'ee',
|
|
221
219
|
'J': 'slightly-open',
|
|
222
220
|
'K': 'half-open',
|
|
223
|
-
'L': '
|
|
221
|
+
'L': 'l',
|
|
224
222
|
'M': 'closed',
|
|
225
223
|
'N': 'slightly-open',
|
|
226
|
-
'O': '
|
|
224
|
+
'O': 'open',
|
|
227
225
|
'P': 'closed',
|
|
228
|
-
'Q': '
|
|
226
|
+
'Q': 'open',
|
|
229
227
|
'R': 'slightly-open',
|
|
230
228
|
'S': 'slightly-open',
|
|
231
229
|
'T': 'ds',
|
|
232
|
-
'U': '
|
|
230
|
+
'U': 'open',
|
|
233
231
|
'V': 'half-open',
|
|
234
|
-
'W': '
|
|
232
|
+
'W': 'wide-open',
|
|
235
233
|
'Y': 'ee',
|
|
236
234
|
'Z': 'slightly-open'
|
|
237
235
|
};
|
|
@@ -243,35 +241,76 @@ MouthSystem.DEFAULT_TALKING_MOUTHS = [
|
|
|
243
241
|
'half-open',
|
|
244
242
|
'open',
|
|
245
243
|
'wide-open',
|
|
246
|
-
'ah',
|
|
247
244
|
'ee',
|
|
248
|
-
'
|
|
245
|
+
'eh',
|
|
246
|
+
'f',
|
|
247
|
+
'l'
|
|
249
248
|
];
|
|
250
249
|
/**
|
|
251
250
|
* Factory function to create mouth system
|
|
252
251
|
*/
|
|
253
|
-
export function createMouthSystem(characterId, availableMouths = ['closed'
|
|
252
|
+
export function createMouthSystem(characterId, availableMouths = ['closed'], config = {}) {
|
|
254
253
|
return new MouthSystem(characterId, new Set(availableMouths), config);
|
|
255
254
|
}
|
|
256
255
|
/**
|
|
257
256
|
* Helper: Extract available mouth shapes from rig data
|
|
257
|
+
* Only looks for the specific mouth shapes defined in MouthShape type
|
|
258
258
|
*/
|
|
259
259
|
export function extractMouthShapesFromRigData(rigData) {
|
|
260
260
|
const mouths = [];
|
|
261
|
+
// THE SINGLE SOURCE OF TRUTH for all mouth types
|
|
261
262
|
const mouthTypes = [
|
|
262
|
-
'
|
|
263
|
+
'f', 'l', 'ds', 'ee', 'eh', 'open', 'closed', 'half-open', 'wide-open', 'slightly-open'
|
|
263
264
|
];
|
|
264
|
-
if
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
265
|
+
// Check if mouth data exists
|
|
266
|
+
if (!rigData.mouth) {
|
|
267
|
+
return ['closed'];
|
|
268
|
+
}
|
|
269
|
+
const mouthData = rigData.mouth;
|
|
270
|
+
// Check each mouth type from our absolute list
|
|
271
|
+
for (const mouthType of mouthTypes) {
|
|
272
|
+
// Check if this exact mouth shape exists in the data
|
|
273
|
+
const value = mouthData[mouthType];
|
|
274
|
+
// Check if value exists and is valid (not undefined, not null, not [MEDIA_REMOVED])
|
|
275
|
+
if (value &&
|
|
276
|
+
typeof value === 'string' &&
|
|
277
|
+
value !== '' &&
|
|
278
|
+
!value.includes('[MEDIA_REMOVED]')) {
|
|
279
|
+
mouths.push(mouthType);
|
|
269
280
|
}
|
|
270
281
|
}
|
|
271
|
-
// Always include at least closed
|
|
282
|
+
// Always include at least closed as fallback
|
|
272
283
|
if (mouths.length === 0) {
|
|
273
|
-
mouths.push('closed'
|
|
284
|
+
mouths.push('closed');
|
|
274
285
|
}
|
|
275
286
|
return mouths;
|
|
276
287
|
}
|
|
288
|
+
/**
|
|
289
|
+
* Helper: Extract mouth image hashes from rig data
|
|
290
|
+
* Returns only the valid mouth shape MD5 hashes, excluding positioning data
|
|
291
|
+
* @param rigData - Character rig data
|
|
292
|
+
* @returns Object with mouth shape names as keys and MD5 hashes as values
|
|
293
|
+
*/
|
|
294
|
+
export function extractMouthImagesFromRigData(rigData) {
|
|
295
|
+
const mouthImages = {};
|
|
296
|
+
// THE SINGLE SOURCE OF TRUTH for all mouth types
|
|
297
|
+
const mouthTypes = [
|
|
298
|
+
'f', 'l', 'ds', 'ee', 'eh', 'open', 'closed', 'half-open', 'wide-open', 'slightly-open'
|
|
299
|
+
];
|
|
300
|
+
if (!rigData.mouth) {
|
|
301
|
+
return mouthImages;
|
|
302
|
+
}
|
|
303
|
+
const mouthData = rigData.mouth;
|
|
304
|
+
// Extract only the mouth shape image hashes
|
|
305
|
+
for (const mouthType of mouthTypes) {
|
|
306
|
+
const value = mouthData[mouthType];
|
|
307
|
+
if (value &&
|
|
308
|
+
typeof value === 'string' &&
|
|
309
|
+
value !== '' &&
|
|
310
|
+
!value.includes('[MEDIA_REMOVED]')) {
|
|
311
|
+
mouthImages[mouthType] = value;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return mouthImages;
|
|
315
|
+
}
|
|
277
316
|
//# sourceMappingURL=mouthSystem.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mouthSystem.js","sourceRoot":"","sources":["../../modules/mouthSystem.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"mouthSystem.js","sourceRoot":"","sources":["../../modules/mouthSystem.ts"],"names":[],"mappings":"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"}
|
|
File without changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderRig.d.ts","sourceRoot":"","sources":["../../modules/renderRig.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7C,OAAO,KAAK,EACR,OAAO,EACP,aAAa,EACb,aAAa,EAGb,QAAQ,EACX,MAAM,aAAa,CAAC;AAErB;;GAEG;AACH,qBAAa,oBAAoB;IAC7B,SAAS,CAAC,WAAW,EAAE,WAAW,CAAC;IAEnC;;;OAGG;gBACS,WAAW,CAAC,EAAE,WAAW;IAIrC;;;OAGG;IACH,cAAc,IAAI,WAAW;IAI7B;;OAEG;IACH,OAAO,CAAC,cAAc;IAYtB;;OAEG;IACH,uBAAuB,CACnB,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE,aAAkB,GAC5B,aAAa;
|
|
1
|
+
{"version":3,"file":"renderRig.d.ts","sourceRoot":"","sources":["../../modules/renderRig.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7C,OAAO,KAAK,EACR,OAAO,EACP,aAAa,EACb,aAAa,EAGb,QAAQ,EACX,MAAM,aAAa,CAAC;AAErB;;GAEG;AACH,qBAAa,oBAAoB;IAC7B,SAAS,CAAC,WAAW,EAAE,WAAW,CAAC;IAEnC;;;OAGG;gBACS,WAAW,CAAC,EAAE,WAAW;IAIrC;;;OAGG;IACH,cAAc,IAAI,WAAW;IAI7B;;OAEG;IACH,OAAO,CAAC,cAAc;IAYtB;;OAEG;IACH,uBAAuB,CACnB,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE,aAAkB,GAC5B,aAAa;IA00ChB;;;;;;;;;;;;;;;;;OAiBG;IACG,MAAM,CACR,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,OAAO,EAChB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,GAAG,iBAAiB,CAAC,EACnE,YAAY,GAAE,QAAyB,EACvC,eAAe,GAAE,OAAc,GAChC,OAAO,CAAC,IAAI,CAAC;CA8EnB;AAGD,eAAO,MAAM,eAAe,sBAA6B,CAAC;AAG1D,wBAAsB,kBAAkB,CACpC,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,OAAO,EAChB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,GAAG,iBAAiB,CAAC,EACnE,YAAY,GAAE,QAAyB,EACvC,eAAe,GAAE,OAAc,GAChC,OAAO,CAAC,IAAI,CAAC,CAEf;AAGD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,GAAE,aAAkB,GAAG,aAAa,CAEpG"}
|
|
@@ -148,11 +148,40 @@ export class CharacterRigRenderer {
|
|
|
148
148
|
// Mouth (child of head)
|
|
149
149
|
if (visibility.mouth !== false) {
|
|
150
150
|
const headPivot = pivotPoints['torso_head'] || { x: 0, y: 0 };
|
|
151
|
-
const mouthOffset = pivotPoints['head_mouth'] || { x: 0, y: 0 };
|
|
152
|
-
const mouthWidth = dimensions.mouth?.width || 40;
|
|
153
|
-
const mouthHeight = dimensions.mouth?.height || 30;
|
|
154
151
|
const selfRot = selfRotations["mouth"] || 0;
|
|
155
152
|
const headRot = rotations["head"] || 0;
|
|
153
|
+
// Get mouth dimensions and position from rigData.mouth
|
|
154
|
+
const mouthData = rigData.mouth;
|
|
155
|
+
let baseMouthWidth = dimensions.mouth?.width || 40;
|
|
156
|
+
let baseMouthHeight = dimensions.mouth?.height || 30;
|
|
157
|
+
let mouthSizeScale = 1;
|
|
158
|
+
// Determine position offset: use xCoor/yCoor from mouth data if available,
|
|
159
|
+
// otherwise fall back to pivot point system
|
|
160
|
+
const mouthPivotOffset = pivotPoints['head_mouth'] || { x: 0, y: 0 };
|
|
161
|
+
let mouthXOffset = mouthPivotOffset.x || 0;
|
|
162
|
+
let mouthYOffset = mouthPivotOffset.y || 0;
|
|
163
|
+
// If mouth data is available, use its width, height, size, and override position with xCoor/yCoor
|
|
164
|
+
if (mouthData && typeof mouthData === 'object') {
|
|
165
|
+
if (typeof mouthData.width === 'number' && mouthData.width > 0) {
|
|
166
|
+
baseMouthWidth = mouthData.width;
|
|
167
|
+
}
|
|
168
|
+
if (typeof mouthData.height === 'number' && mouthData.height > 0) {
|
|
169
|
+
baseMouthHeight = mouthData.height;
|
|
170
|
+
}
|
|
171
|
+
if (typeof mouthData.size === 'number' && mouthData.size > 0) {
|
|
172
|
+
mouthSizeScale = mouthData.size;
|
|
173
|
+
}
|
|
174
|
+
// xCoor and yCoor from mouth data take precedence over pivot points
|
|
175
|
+
if (typeof mouthData.xCoor === 'number') {
|
|
176
|
+
mouthXOffset = mouthData.xCoor;
|
|
177
|
+
}
|
|
178
|
+
if (typeof mouthData.yCoor === 'number') {
|
|
179
|
+
mouthYOffset = mouthData.yCoor;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
// Calculate final dimensions with size scaling
|
|
183
|
+
const finalMouthWidth = baseMouthWidth * mouthSizeScale;
|
|
184
|
+
const finalMouthHeight = baseMouthHeight * mouthSizeScale;
|
|
156
185
|
const headBaseTransform = this.applyTransform(rootTransform, {
|
|
157
186
|
x: headPivot.x || 0,
|
|
158
187
|
y: headPivot.y || 0,
|
|
@@ -160,24 +189,37 @@ export class CharacterRigRenderer {
|
|
|
160
189
|
scaleX: flipHead ? -1 : 1,
|
|
161
190
|
scaleY: 1
|
|
162
191
|
});
|
|
163
|
-
|
|
164
|
-
|
|
192
|
+
// Position mouth using the determined offsets (xCoor/yCoor take priority)
|
|
193
|
+
// Note: Anchor point (0.5, 0.5) automatically centers the image at this position
|
|
165
194
|
const mouthTransform = this.applyTransform(headBaseTransform, {
|
|
166
|
-
x:
|
|
167
|
-
y:
|
|
195
|
+
x: mouthXOffset,
|
|
196
|
+
y: mouthYOffset,
|
|
168
197
|
rotation: selfRot,
|
|
169
198
|
scaleX: 1,
|
|
170
199
|
scaleY: 1
|
|
171
200
|
});
|
|
172
|
-
//
|
|
173
|
-
|
|
174
|
-
|
|
201
|
+
// Get current mouth shape and look up the corresponding image
|
|
202
|
+
// If currentMouthShape is specified, use it to look up the specific mouth image
|
|
203
|
+
// Otherwise, fall back to the static imagePaths.mouth
|
|
204
|
+
let mouthImagePath;
|
|
205
|
+
let mouthImage;
|
|
206
|
+
const currentMouthShape = rigData.currentMouthShape;
|
|
207
|
+
if (currentMouthShape && rigData.mouth && rigData.mouth[currentMouthShape]) {
|
|
208
|
+
// Use the specific mouth shape image from rigData.mouth[shape]
|
|
209
|
+
mouthImagePath = rigData.mouth[currentMouthShape];
|
|
210
|
+
mouthImage = mouthImagePath ? loadedImages[mouthImagePath] : undefined;
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
// Fallback to static imagePaths.mouth
|
|
214
|
+
mouthImagePath = rigData.imagePaths?.mouth;
|
|
215
|
+
mouthImage = mouthImagePath ? loadedImages[mouthImagePath] : undefined;
|
|
216
|
+
}
|
|
175
217
|
allObjects.push({
|
|
176
218
|
name: 'mouth',
|
|
177
219
|
type: 'limb',
|
|
178
220
|
zIndex: zIndexValues['mouth'] || 1,
|
|
179
|
-
width:
|
|
180
|
-
height:
|
|
221
|
+
width: finalMouthWidth * imageScale,
|
|
222
|
+
height: finalMouthHeight * imageScale,
|
|
181
223
|
x: mouthTransform.x,
|
|
182
224
|
y: mouthTransform.y,
|
|
183
225
|
rotation: mouthTransform.rotation,
|
|
@@ -290,8 +332,25 @@ export class CharacterRigRenderer {
|
|
|
290
332
|
scaleX: flipHead ? -1 : 1,
|
|
291
333
|
scaleY: 1
|
|
292
334
|
});
|
|
293
|
-
|
|
294
|
-
|
|
335
|
+
// Base iris position from rig data
|
|
336
|
+
let offsetX = Number.isFinite(eyes.leftIrisXCoor) ? eyes.leftIrisXCoor : -10;
|
|
337
|
+
let offsetY = Number.isFinite(eyes.leftIrisYCoor) ? eyes.leftIrisYCoor : -5;
|
|
338
|
+
// Apply manual eye positioning if eyePositions exists
|
|
339
|
+
const eyePositions = eyes.eyePositions;
|
|
340
|
+
if (eyePositions?.left) {
|
|
341
|
+
const eyePos = eyePositions.left;
|
|
342
|
+
const hasEyeMovement = eyePos.x !== undefined && eyePos.y !== undefined &&
|
|
343
|
+
(eyePos.x !== 0 || eyePos.y !== 0);
|
|
344
|
+
if (hasEyeMovement) {
|
|
345
|
+
// eyePos values are in -2 to 2 range
|
|
346
|
+
// Scale them to pixel movement (matching the old Body.js behavior)
|
|
347
|
+
const movementScale = 5; // Pixels of movement per unit
|
|
348
|
+
const deltaX = eyePos.x * movementScale;
|
|
349
|
+
const deltaY = eyePos.y * movementScale;
|
|
350
|
+
offsetX += deltaX;
|
|
351
|
+
offsetY += deltaY;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
295
354
|
const baseLeftIrisWidth = eyes.leftIrisWidth || 10;
|
|
296
355
|
const baseLeftIrisHeight = eyes.leftIrisHeight || 10;
|
|
297
356
|
const leftIrisWidth = baseLeftIrisWidth * (eyes.leftIrisWidthRatio || 1.0);
|
|
@@ -333,8 +392,25 @@ export class CharacterRigRenderer {
|
|
|
333
392
|
scaleX: flipHead ? -1 : 1,
|
|
334
393
|
scaleY: 1
|
|
335
394
|
});
|
|
336
|
-
|
|
337
|
-
|
|
395
|
+
// Base iris position from rig data
|
|
396
|
+
let offsetX = Number.isFinite(eyes.rightIrisXCoor) ? eyes.rightIrisXCoor : 10;
|
|
397
|
+
let offsetY = Number.isFinite(eyes.rightIrisYCoor) ? eyes.rightIrisYCoor : -5;
|
|
398
|
+
// Apply manual eye positioning if eyePositions exists
|
|
399
|
+
const eyePositions = eyes.eyePositions;
|
|
400
|
+
if (eyePositions?.right) {
|
|
401
|
+
const eyePos = eyePositions.right;
|
|
402
|
+
const hasEyeMovement = eyePos.x !== undefined && eyePos.y !== undefined &&
|
|
403
|
+
(eyePos.x !== 0 || eyePos.y !== 0);
|
|
404
|
+
if (hasEyeMovement) {
|
|
405
|
+
// eyePos values are in -2 to 2 range
|
|
406
|
+
// Scale them to pixel movement (matching the old Body.js behavior)
|
|
407
|
+
const movementScale = 5; // Pixels of movement per unit
|
|
408
|
+
const deltaX = eyePos.x * movementScale;
|
|
409
|
+
const deltaY = eyePos.y * movementScale;
|
|
410
|
+
offsetX += deltaX;
|
|
411
|
+
offsetY += deltaY;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
338
414
|
const baseRightIrisWidth = eyes.rightIrisWidth || 10;
|
|
339
415
|
const baseRightIrisHeight = eyes.rightIrisHeight || 10;
|
|
340
416
|
const rightIrisWidth = baseRightIrisWidth * (eyes.rightIrisWidthRatio || 1.0);
|