Skip to content

Commit

Permalink
feat: support declarative bones
Browse files Browse the repository at this point in the history
  • Loading branch information
drcmda committed Jun 28, 2024
1 parent a01fca4 commit c5fa7fd
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 20 deletions.
4 changes: 3 additions & 1 deletion cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const cli = meow(
--types, -t Add Typescript definitions
--keepnames, -k Keep original names
--keepgroups, -K Keep (empty) groups, disable pruning
--bones, -b Lay out bones declaratively (default: false)
--meta, -m Include metadata (as userData)
--shadows, s Let meshes cast and receive shadows
--printwidth, w Prettier printWidth (default: 120)
Expand Down Expand Up @@ -47,6 +48,7 @@ const cli = meow(
types: { type: 'boolean', shortFlag: 't' },
keepnames: { type: 'boolean', shortFlag: 'k' },
keepgroups: { type: 'boolean', shortFlag: 'K' },
bones: { type: 'boolean', shortFlag: 'b', default: false },
shadows: { type: 'boolean', shortFlag: 's' },
printwidth: { type: 'number', shortFlag: 'p', default: 1000 },
meta: { type: 'boolean', shortFlag: 'm' },
Expand All @@ -61,7 +63,7 @@ const cli = meow(
degraderesolution: { type: 'number', shortFlag: 'Q', default: 512 },
simplify: { type: 'boolean', shortFlag: 'S', default: false },
keepmeshes: { type: 'boolean', shortFlag: 'j', default: false },
keepmaterials: { type: 'boolean', shortFlag: 'M', default: false },
keepmaterials: { type: 'boolean', shortFlag: 'M', default: false },
format: { type: 'string', shortFlag: 'f', default: 'webp' },
exportdefault: { type: 'boolean', shortFlag: 'E' },
weld: { type: 'number', default: 0.0001 },
Expand Down
44 changes: 25 additions & 19 deletions src/utils/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ function parse(gltf, { fileName = 'model', ...options } = {}) {
const types = [...new Set([...meshes, ...bones].map((o) => getType(o)))]
const contextType = `type ContextType = Record<string, React.ForwardRefExoticComponent<
${types.map((type) => `JSX.IntrinsicElements['${type}']`).join(' | ')}
>>`;
>>`

return `\ntype GLTFResult = GLTF & {
nodes: {
Expand Down Expand Up @@ -339,7 +339,7 @@ function parse(gltf, { fileName = 'model', ...options } = {}) {
}

// Bail out on lights and bones
if (type === 'bone') {
if (!options.bones && type === 'bone') {
return `<primitive object={${node}} />`
}

Expand All @@ -356,7 +356,8 @@ function parse(gltf, { fileName = 'model', ...options } = {}) {
result = `<instancedMesh args={[${geo}, ${mat}, ${!obj.count ? `${node}.count` : obj.count}]} `
} else {
// Form the object in JSX syntax
result = `<${type} `
if (type === 'bone') result = `<primitive object={${node}} `
else result = `<${type} `
}
}

Expand All @@ -374,7 +375,10 @@ function parse(gltf, { fileName = 'model', ...options } = {}) {
result += `${children.length ? '>' : '/>'}\n`

// Add children and return
if (children.length) result += children + `</${type}>`
if (children.length) {
if (type === 'bone') result += children + `</primitive>`
else result += children + `</${type}>`
}
return result
}

Expand Down Expand Up @@ -445,8 +449,8 @@ ${parseExtras(gltf.parser.json.asset && gltf.parser.json.asset.extras)}*/`
const result = `${options.types ? `\nimport * as THREE from 'three'` : ''}
import React, { useRef ${hasInstances ? ', useMemo, useContext, createContext' : ''} } from 'react'
import { useGLTF, ${hasInstances ? 'Merged, ' : ''} ${
scene.includes('PerspectiveCamera') ? 'PerspectiveCamera,' : ''
}
scene.includes('PerspectiveCamera') ? 'PerspectiveCamera,' : ''
}
${scene.includes('OrthographicCamera') ? 'OrthographicCamera,' : ''}
${hasAnimations ? 'useAnimations' : ''} } from '@react-three/drei'
${options.types ? 'import { GLTF } from "three-stdlib"' : ''}
Expand All @@ -458,16 +462,18 @@ ${parseExtras(gltf.parser.json.asset && gltf.parser.json.asset.extras)}*/`
const context = createContext(${options.types ? '{} as ContextType' : ''})
export function Instances({ children, ...props }${options.types ? ': JSX.IntrinsicElements["group"]' : ''}) {
const { nodes } = useGLTF('${url}'${options.draco ? `, ${JSON.stringify(options.draco)}` : ''})${
options.types ? ' as GLTFResult' : ''
}
options.types ? ' as GLTFResult' : ''
}
const instances = useMemo(() => ({
${Object.values(duplicates.geometries)
.map((v) => `${v.name}: ${v.node}`)
.join(', ')}
}), [nodes])
return (
<Merged meshes={instances} {...props}>
{(instances${options.types ? ': ContextType' : ''}) => <context.Provider value={instances} children={children} />}
{(instances${
options.types ? ': ContextType' : ''
}) => <context.Provider value={instances} children={children} />}
</Merged>
)
}
Expand All @@ -476,17 +482,17 @@ ${parseExtras(gltf.parser.json.asset && gltf.parser.json.asset.extras)}*/`
}
export ${options.exportdefault ? 'default' : ''} function Model(props${
options.types ? ": JSX.IntrinsicElements['group']" : ''
}) {
options.types ? ": JSX.IntrinsicElements['group']" : ''
}) {
${hasInstances ? 'const instances = useContext(context);' : ''} ${
hasAnimations ? `const group = ${options.types ? 'useRef<THREE.Group>()' : 'useRef()'};` : ''
} ${
!options.instanceall
? `const { nodes, materials${hasAnimations ? ', animations' : ''} } = useGLTF('${url}'${
options.draco ? `, ${JSON.stringify(options.draco)}` : ''
})${options.types ? ' as GLTFResult' : ''}`
: ''
} ${printAnimations(animations)}
hasAnimations ? `const group = ${options.types ? 'useRef<THREE.Group>()' : 'useRef()'};` : ''
} ${
!options.instanceall
? `const { nodes, materials${hasAnimations ? ', animations' : ''} } = useGLTF('${url}'${
options.draco ? `, ${JSON.stringify(options.draco)}` : ''
})${options.types ? ' as GLTFResult' : ''}`
: ''
} ${printAnimations(animations)}
return (
<group ${hasAnimations ? `ref={group}` : ''} {...props} dispose={null}>
${scene}
Expand Down

0 comments on commit c5fa7fd

Please sign in to comment.