diff --git a/packages/avatar-core/src/geometry.ts b/packages/avatar-core/src/geometry.ts index 84a8ac4..3b4ae41 100644 --- a/packages/avatar-core/src/geometry.ts +++ b/packages/avatar-core/src/geometry.ts @@ -1454,8 +1454,8 @@ const accessoryLayers = (pose: AvatarPose, nodes: BodyNode[]) => { depth, front: node.layer === 'front' || - (node.layer !== 'back' && - depth > accessoryCameraDepthRadius(pose, node) * ACCESSORY_FRONT_CROSSING_RATIO), + (node.layer !== 'back' && + depth > accessoryCameraDepthRadius(pose, node) * ACCESSORY_FRONT_CROSSING_RATIO), } }) .sort((left, right) => left.depth - right.depth) diff --git a/src/features/avatar/avatars.ts b/src/features/avatar/avatars.ts index ad23ffa..cc12557 100644 --- a/src/features/avatar/avatars.ts +++ b/src/features/avatar/avatars.ts @@ -195,11 +195,7 @@ export const simpleBundledAvatarIds = [ const simpleBundledAvatarOrder = new Map(simpleBundledAvatarIds.map((id, index) => [id, index])) // Remove hidden bundled characters from both fresh and previously persisted local libraries. -const hiddenBundledAvatarIds = new Set([ - 'memento-piglet', - 'oneworks-cat', - 'oneworks-cat-cow', -]) +const hiddenBundledAvatarIds = new Set(['memento-piglet', 'oneworks-cat', 'oneworks-cat-cow']) const retiredBundledAvatarIds = new Set([ 'memento-arctic-fox', @@ -579,13 +575,13 @@ const oneWorksDogAvatar = ( oneWorksNode('dog-ear-left', 'Left ear', 'teardrop', [-82, -65, 0], 0.18, 0.34, { scaleZ: 0.18, rotation: [-4, -10, 22], - layer: 'front', + layer: 'auto', color: earColor, }), oneWorksNode('dog-ear-right', 'Right ear', 'teardrop', [82, -65, 0], 0.18, 0.34, { scaleZ: 0.18, rotation: [-4, 10, -22], - layer: 'front', + layer: 'auto', color: earColor, }), ], diff --git a/src/features/rendering/__tests__/rendered-scene-test.ts b/src/features/rendering/__tests__/rendered-scene-test.ts index d102ea8..7b755da 100644 --- a/src/features/rendering/__tests__/rendered-scene-test.ts +++ b/src/features/rendering/__tests__/rendered-scene-test.ts @@ -98,18 +98,12 @@ describe('rendered avatar scene', () => { expect(forcedFront.frontNodeIds).toContain(avatar.body.nodes[0].id) }) - it('anchors dog ears in front of the head across expressions', () => { + it('moves dog ears between front and back with head depth', () => { const studio = loadStudioDocument({ getItem: () => null }) const avatar = studio.library.avatars.find(item => item.id === 'oneworks-dog')! const detachedEars: string[] = [] - const neutral = renderAvatar( - poseFromExpression(defaultExpression), - avatar.body.primary as SurfaceConfig, - 1, - { bodyNodes: avatar.body.nodes as BodyNode[] } - ) - expect(neutral.frontNodeIds).toEqual(['dog-ear-left', 'dog-ear-right']) + let splitDepthExpressions = 0 studio.expressions.forEach(expression => { const geometry = renderAvatar( @@ -121,11 +115,18 @@ describe('rendered avatar scene', () => { const head = pathBounds(geometry.headPath) const earIds = ['dog-ear-left', 'dog-ear-right'] as const + if ( + geometry.frontNodeIds.some(id => earIds.includes(id as (typeof earIds)[number])) && + geometry.backNodeIds.some(id => earIds.includes(id as (typeof earIds)[number])) + ) { + splitDepthExpressions += 1 + } earIds.forEach(nodeId => { const frontIndex = geometry.frontNodeIds.indexOf(nodeId) - expect(geometry.backNodeIds).not.toContain(nodeId) - expect(frontIndex).toBeGreaterThanOrEqual(0) - const earPath = geometry.frontPaths[frontIndex] + const backIndex = geometry.backNodeIds.indexOf(nodeId) + expect(Number(frontIndex >= 0) + Number(backIndex >= 0)).toBe(1) + const earPath = + frontIndex >= 0 ? geometry.frontPaths[frontIndex] : geometry.backPaths[backIndex] const ear = pathBounds(earPath) const headOverlap = overlap(ear, head) if (headOverlap.x <= 0 || headOverlap.y <= 0) { @@ -134,9 +135,9 @@ describe('rendered avatar scene', () => { ) } }) - }) + expect(splitDepthExpressions).toBeGreaterThan(0) expect(detachedEars, 'detached dog ears').toEqual([]) })