Skip to content

Commit f19727c

Browse files
committed
change: slots aren't part of props anymore
1 parent a92ab7b commit f19727c

File tree

1 file changed

+31
-10
lines changed

1 file changed

+31
-10
lines changed

src/utils/parser.js

+31-10
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,20 @@ function parse(gltf, { fileName = 'model', ...options } = {}) {
1313
const animations = gltf.animations
1414
const hasAnimations = animations.length > 0
1515

16+
/** @type {Record<string, Object3D[]> */
17+
const slots = {}
18+
1619
// Collect all objects
1720
const objects = []
18-
gltf.scene.traverse((child) => objects.push(child))
21+
gltf.scene.traverse((child) => {
22+
objects.push(child);
23+
24+
// Collect slots
25+
const slot = child.userData?.slot;
26+
const hasSlot = (slot && typeof slot === "string" && slot.length > 0);
27+
if (hasSlot)
28+
slots[slot] ? slots[slot].push(child) : (slots[slot] = [child]);
29+
})
1930

2031
// Browse for duplicates
2132
const duplicates = {
@@ -75,6 +86,11 @@ function parse(gltf, { fileName = 'model', ...options } = {}) {
7586
return isVarName(name) ? `.${name}` : `['${name}']`
7687
}
7788

89+
/** Ensure that a slot is a valid variable name e.g. must not contain spaces */
90+
function sanitizeSlotName(slotname) {
91+
return slotname.replaceAll(/[^a-zA-Z0-9]/g, '');
92+
}
93+
7894
const rNbr = (number) => {
7995
return parseFloat(number.toFixed(Math.round(options.precision || 2)))
8096
}
@@ -220,17 +236,18 @@ function parse(gltf, { fileName = 'model', ...options } = {}) {
220236
duplicates.geometries[obj.geometry.uuid + obj.material.name] &&
221237
duplicates.geometries[obj.geometry.uuid + obj.material.name].count > (options.instanceall ? 0 : 1)
222238
let animated = gltf.animations && gltf.animations.length > 0
223-
return { type, node, instanced, animated }
239+
const hasSlots = obj.userData?.slot && typeof obj.userData.slot === "string" && obj.userData.slot.length > 0;
240+
return { type, node, instanced, animated, hasSlots }
224241
}
225242

226243
function equalOrNegated(a, b) {
227244
return (a.x === b.x || a.x === -b.x) && (a.y === b.y || a.y === -b.y) && (a.z === b.z || a.z === -b.z)
228245
}
229246

230247
function prune(obj, children, result, oldResult, silent) {
231-
let { type, animated } = getInfo(obj)
248+
let { type, animated, hasSlots } = getInfo(obj)
232249
// Prune ...
233-
if (!obj.__removed && !options.keepgroups && !animated && (type === 'group' || type === 'scene')) {
250+
if (!obj.__removed && !options.keepgroups && !animated && !hasSlots && (type === 'group' || type === 'scene')) {
234251
/** Empty or no-property groups
235252
* <group>
236253
* <mesh geometry={nodes.foo} material={materials.bar} />
@@ -370,8 +387,8 @@ function parse(gltf, { fileName = 'model', ...options } = {}) {
370387
// Bail out if the object was pruned
371388
if (pruned !== undefined) return pruned
372389

373-
// Add custom slots if defined in the object's userData.
374-
// E.g. userData: { "slot" : "mySlot" } becomes `{ props.mySlot }`
390+
// Add custom slots if defined in the object's userData
391+
// E.g. userData: { "slot" : "mySlot" } becomes `{ mySlot }`
375392
const slot = obj.userData?.slot;
376393
const hasSlot = (slot && typeof slot === "string" && slot.length > 0);
377394
const hasContent = children.length || hasSlot;
@@ -380,9 +397,9 @@ function parse(gltf, { fileName = 'model', ...options } = {}) {
380397
result += `${hasContent ? '>' : '/>'}\n`
381398

382399
// Add children
383-
if (children.length) result += `${children}\n`
400+
if (children.length) result += `${children.trimEnd("\n")}\n`
384401
// Add custom slot
385-
if (hasSlot) result += `{props.${slot}}\n`;
402+
if (hasSlot) result += `{${sanitizeSlotName(slot)}}\n`;
386403
// Close tag
387404
if (hasContent) result += `</${type}>`
388405
return result
@@ -447,10 +464,14 @@ function parse(gltf, { fileName = 'model', ...options } = {}) {
447464
} catch (e) {
448465
console.log('Error while parsing glTF', e)
449466
}
467+
468+
const slotParams = Object.keys(slots).length > 0 ? (Object.keys(slots).map(sanitizeSlotName).join(", ") + ", ") : "";
469+
450470
const header = `/*
451471
${options.header ? options.header : 'Auto-generated by: https://github.com/pmndrs/gltfjsx'} ${
452472
options.size ? `\nFiles: ${options.size}` : ''
453473
}
474+
454475
${parseExtras(gltf.parser.json.asset && gltf.parser.json.asset.extras)}*/`
455476
const result = `${options.types ? `\nimport * as THREE from 'three'` : ''}
456477
import React, { useRef ${hasInstances ? ', useMemo, useContext, createContext' : ''} } from 'react'
@@ -466,7 +487,7 @@ ${parseExtras(gltf.parser.json.asset && gltf.parser.json.asset.extras)}*/`
466487
hasInstances
467488
? `
468489
const context = createContext(${options.types ? '{} as ContextType' : ''})
469-
export function Instances({ children, ...props }${options.types ? ': JSX.IntrinsicElements["group"]' : ''}) {
490+
export function Instances({ children, ${slotParams}...props }${options.types ? ': JSX.IntrinsicElements["group"]' : ''}) {
470491
const { nodes } = useGLTF('${url}'${options.draco ? `, ${JSON.stringify(options.draco)}` : ''})${
471492
options.types ? ' as GLTFResult' : ''
472493
}
@@ -485,7 +506,7 @@ ${parseExtras(gltf.parser.json.asset && gltf.parser.json.asset.extras)}*/`
485506
: ''
486507
}
487508
488-
export ${options.exportdefault ? 'default' : ''} function Model(props${
509+
export ${options.exportdefault ? 'default' : ''} function Model(${slotParams}...props${
489510
options.types ? ": JSX.IntrinsicElements['group']" : ''
490511
}) {
491512
${hasInstances ? 'const instances = useContext(context);' : ''} ${

0 commit comments

Comments
 (0)