feat: refine Memento headset expressions
This commit is contained in:
parent
1515a7c6cf
commit
271a0dfa2f
@ -318,11 +318,37 @@ const fixedSkinColorBehavior = (behavior?: AvatarBehaviorLibrary): AvatarBehavio
|
||||
return { expressions: [...expressions, ...scaredExpressions], sequences }
|
||||
}
|
||||
|
||||
const mementoBehavior = (behavior?: AvatarBehaviorLibrary): AvatarBehaviorLibrary => {
|
||||
const mementoHeadsetWorkingExpressionId = 'memento-headset-working-joyful-eyes'
|
||||
const mementoHeadsetShyExpressionId = 'memento-headset-shy-left'
|
||||
|
||||
const copyExpressionEyes = (target: Expression, source: Expression): Expression => ({
|
||||
...target,
|
||||
widthLeft: source.widthLeft,
|
||||
widthRight: source.widthRight,
|
||||
heightLeft: source.heightLeft,
|
||||
heightRight: source.heightRight,
|
||||
curvatureLeft: source.curvatureLeft,
|
||||
curvatureRight: source.curvatureRight,
|
||||
spacing: source.spacing,
|
||||
positionXLeft: source.positionXLeft,
|
||||
positionXRight: source.positionXRight,
|
||||
positionYLeft: source.positionYLeft,
|
||||
positionYRight: source.positionYRight,
|
||||
leftAngle: source.leftAngle,
|
||||
rightAngle: source.rightAngle,
|
||||
eyeMotion: source.eyeMotion,
|
||||
})
|
||||
|
||||
const mementoBehavior = (
|
||||
behavior?: AvatarBehaviorLibrary,
|
||||
customizeHeadsetExpressions = false
|
||||
): AvatarBehaviorLibrary => {
|
||||
const sourceExpressions = (behavior?.expressions ?? initialExpressions).filter(
|
||||
expression =>
|
||||
expression.semanticKey !== 'onboarding-listening' &&
|
||||
expression.semanticKey !== 'onboarding-curious'
|
||||
expression.semanticKey !== 'onboarding-curious' &&
|
||||
expression.semanticKey !== mementoHeadsetWorkingExpressionId &&
|
||||
expression.semanticKey !== mementoHeadsetShyExpressionId
|
||||
)
|
||||
const expressions = sourceExpressions.map(expression => {
|
||||
const fixedColorExpression = { ...expression }
|
||||
@ -366,10 +392,53 @@ const mementoBehavior = (behavior?: AvatarBehaviorLibrary): AvatarBehaviorLibrar
|
||||
steps: sequence.steps.map(step => ({ ...step })),
|
||||
blink: { ...sequence.blink },
|
||||
}))
|
||||
const workingPose = expressions.find(expression => expression.semanticKey === 'angry-right')
|
||||
const joyfulEyes = expressions.find(expression => expression.semanticKey === 'joyful-wide')
|
||||
const headsetWorkingExpression =
|
||||
customizeHeadsetExpressions && workingPose && joyfulEyes
|
||||
? {
|
||||
...copyExpressionEyes(workingPose, joyfulEyes),
|
||||
id: mementoHeadsetWorkingExpressionId,
|
||||
semanticKey: mementoHeadsetWorkingExpressionId,
|
||||
}
|
||||
: undefined
|
||||
const shySource = expressions.find(expression => expression.semanticKey === 'upward-side-glance')
|
||||
const headsetShyExpression =
|
||||
customizeHeadsetExpressions && shySource
|
||||
? {
|
||||
...shySource,
|
||||
id: mementoHeadsetShyExpressionId,
|
||||
semanticKey: mementoHeadsetShyExpressionId,
|
||||
headY: -Math.abs(shySource.headY),
|
||||
spacing: shySource.spacing - 10,
|
||||
positionYLeft: shySource.positionYLeft + 10,
|
||||
positionYRight: shySource.positionYRight + 10,
|
||||
}
|
||||
: undefined
|
||||
const sequenceFirstExpression = new Map<string, string>([
|
||||
...(headsetWorkingExpression ? [['working', headsetWorkingExpression.id] as const] : []),
|
||||
...(headsetShyExpression ? [['shy', headsetShyExpression.id] as const] : []),
|
||||
])
|
||||
const resolvedSequences = sequences.map(sequence => {
|
||||
const expressionId = sequenceFirstExpression.get(sequence.semanticKey ?? '')
|
||||
return expressionId
|
||||
? {
|
||||
...sequence,
|
||||
steps: sequence.steps.map((step, index) =>
|
||||
index === 0 ? { ...step, expressionId } : step
|
||||
),
|
||||
}
|
||||
: sequence
|
||||
})
|
||||
return {
|
||||
expressions: [...expressions, ...onboardingExpressions],
|
||||
expressions: [
|
||||
...expressions,
|
||||
...(headsetWorkingExpression ? [headsetWorkingExpression] : []),
|
||||
...(headsetShyExpression ? [headsetShyExpression] : []),
|
||||
...onboardingExpressions,
|
||||
],
|
||||
sequences: [
|
||||
...sequences.filter(sequence => sequence.semanticKey !== 'onboarding'),
|
||||
...resolvedSequences.filter(sequence => sequence.semanticKey !== 'onboarding'),
|
||||
...(onboardingExpressions.length === 2
|
||||
? [
|
||||
{
|
||||
@ -884,7 +953,7 @@ const primitiveBundledAvatars: StudioAvatar[] = [
|
||||
? { ...filledAvatarRenderStyle }
|
||||
: { ...defaultAvatarRenderStyle },
|
||||
...(surface === 'ghost'
|
||||
? { behavior: mementoBehavior() }
|
||||
? { behavior: mementoBehavior(undefined, id === 'primitive-ghost-headset') }
|
||||
: surface === 'apple-bite'
|
||||
? { behavior: fixedSkinColorBehavior() }
|
||||
: surface === 'lock'
|
||||
@ -1023,7 +1092,10 @@ export const ensurePrimitiveBundledAvatars = (library: AvatarLibrary): AvatarLib
|
||||
avatar.id
|
||||
)
|
||||
) {
|
||||
return { ...avatar, behavior: mementoBehavior(avatar.behavior) }
|
||||
return {
|
||||
...avatar,
|
||||
behavior: mementoBehavior(avatar.behavior, avatar.id === 'primitive-ghost-headset'),
|
||||
}
|
||||
}
|
||||
if (filledBundledAvatarIds.has(avatar.id)) {
|
||||
return { ...avatar, behavior: fixedSkinColorBehavior(avatar.behavior) }
|
||||
@ -1177,7 +1249,10 @@ export const ensurePrimitiveBundledAvatars = (library: AvatarLibrary): AvatarLib
|
||||
].includes(avatarWithAppleBiteEyes.id)
|
||||
? {
|
||||
...avatarWithAppleBiteEyes,
|
||||
behavior: mementoBehavior(avatarWithAppleBiteEyes.behavior),
|
||||
behavior: mementoBehavior(
|
||||
avatarWithAppleBiteEyes.behavior,
|
||||
avatarWithAppleBiteEyes.id === 'primitive-ghost-headset'
|
||||
),
|
||||
}
|
||||
: filledBundledAvatarIds.has(avatarWithAppleBiteEyes.id)
|
||||
? {
|
||||
|
||||
@ -221,6 +221,53 @@ describe('Studio document', () => {
|
||||
expect(memento?.colors).toEqual({ body: '#ff9d45', eyes: '#111316' })
|
||||
expect(headsetMemento?.colors).toEqual({ body: '#ff9d45', eyes: '#222222' })
|
||||
expect(strokeMemento?.colors).toEqual({ body: '#ff9d45', eyes: '#ff9d45' })
|
||||
const headsetWorkingFirst = headsetMemento?.behavior?.sequences.find(
|
||||
sequence => sequence.semanticKey === 'working'
|
||||
)?.steps[0]
|
||||
const headsetJoyfulFirst = headsetMemento?.behavior?.sequences.find(
|
||||
sequence => sequence.semanticKey === 'joyful'
|
||||
)?.steps[0]
|
||||
const headsetShyFirst = headsetMemento?.behavior?.sequences.find(
|
||||
sequence => sequence.semanticKey === 'shy'
|
||||
)?.steps[0]
|
||||
const headsetWorkingExpression = headsetMemento?.behavior?.expressions.find(
|
||||
expression => expression.id === headsetWorkingFirst?.expressionId
|
||||
)
|
||||
const headsetJoyfulExpression = headsetMemento?.behavior?.expressions.find(
|
||||
expression => expression.id === headsetJoyfulFirst?.expressionId
|
||||
)
|
||||
const headsetShyExpression = headsetMemento?.behavior?.expressions.find(
|
||||
expression => expression.id === headsetShyFirst?.expressionId
|
||||
)
|
||||
expect(headsetWorkingExpression).toMatchObject({
|
||||
widthLeft: headsetJoyfulExpression?.widthLeft,
|
||||
widthRight: headsetJoyfulExpression?.widthRight,
|
||||
heightLeft: headsetJoyfulExpression?.heightLeft,
|
||||
heightRight: headsetJoyfulExpression?.heightRight,
|
||||
spacing: headsetJoyfulExpression?.spacing,
|
||||
leftAngle: headsetJoyfulExpression?.leftAngle,
|
||||
rightAngle: headsetJoyfulExpression?.rightAngle,
|
||||
})
|
||||
expect(headsetWorkingExpression).toMatchObject({
|
||||
headX: initialExpressions[7].headX,
|
||||
headY: initialExpressions[7].headY,
|
||||
headZ: initialExpressions[7].headZ,
|
||||
})
|
||||
expect(headsetJoyfulFirst?.expressionId).toBe('expression-11')
|
||||
expect(headsetShyExpression).toMatchObject({
|
||||
headY: -Math.abs(initialExpressions[0].headY),
|
||||
spacing: initialExpressions[0].spacing - 10,
|
||||
positionYLeft: initialExpressions[0].positionYLeft + 10,
|
||||
positionYRight: initialExpressions[0].positionYRight + 10,
|
||||
})
|
||||
expect(
|
||||
memento?.behavior?.sequences.find(sequence => sequence.semanticKey === 'joyful')?.steps[0]
|
||||
.expressionId
|
||||
).toBe('expression-11')
|
||||
expect(
|
||||
strokeMemento?.behavior?.sequences.find(sequence => sequence.semanticKey === 'joyful')
|
||||
?.steps[0].expressionId
|
||||
).toBe('expression-11')
|
||||
expect(
|
||||
strokeMemento?.behavior?.sequences.some(sequence => sequence.semanticKey === 'onboarding')
|
||||
).toBe(true)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user