Skip to content

Commit

Permalink
SvelthreeGLTF.ts improve dx and refactor (add new) types (see #136)
Browse files Browse the repository at this point in the history
- rename interface `ITreeMember` to `ISvelthreeGLTFTreeMapMember`
- `GLTF` is now passed via constructor, e.g. `const foo: SvelthreeGLTF = new SvelthreeGLTF(loaded_gltf_file: GLTF)`
- `apply(...)` now uses a `Canvas` component reference instead of a `Canvas` DOM Element.
- various `strict: true` related changes (due to `strict: true` in the SvelteKit tests project, see also #153 )
  • Loading branch information
Vatroslav Vrbanic committed Aug 28, 2022
1 parent e09cd60 commit 543fe00
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 41 deletions.
14 changes: 14 additions & 0 deletions src/types-extra.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,20 @@ export type GLTFSupportedSvelthreeComponents = Mesh<any> | Group | Object3D | Sc
/** currently unused -> check possible usage or delete */
//export type RaycastableSvelthreeComponents = Mesh<any> | Group | Object3D

export interface ISvelthreeGLTFTreeMapMember {
obj: THREE.Object3D
parent_uuid?: string | null
name?: string | null
obj_type?: string
mesh?: {
geometry: THREE.BufferGeometry
material: THREE.Material | THREE.Material[]
} | null
svelthree_comp?: GLTFSupportedSvelthreeComponents
}

export type SvelthreeGLTFTreeMap = Map<string, ISvelthreeGLTFTreeMapMember>

export interface PointerState {
pos: THREE.Vector2
event: PointerEvent
Expand Down
109 changes: 68 additions & 41 deletions src/utils/SvelthreeGLTF.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,30 @@
import type { BufferGeometry, Material } from "three"
import { Euler, Vector3 } from "three"
import type { GLTF } from "three/examples/jsm/loaders/GLTFLoader"

// import currently supported components only
import { Mesh } from "../components"
import { Group, Object3D } from "../components"
import type { Canvas } from "../components"

import type { GLTFSupportedSvelthreeComponents } from "../types-extra"

interface ITreeMember {
obj: THREE.Object3D
parent_uuid?: string
name?: string
obj_type?: string
mesh?: {
geometry: BufferGeometry
material: Material | Material[]
}
svelthree_comp?: any
}
import type {
GLTFSupportedSvelthreeComponents,
SvelthreeGLTFTreeMap,
ISvelthreeGLTFTreeMapMember
} from "../types-extra"

export default class SvelthreeGLTF {
public tree: Map<string, ITreeMember>
public tree: SvelthreeGLTFTreeMap = new Map<string, ISvelthreeGLTFTreeMapMember>()

constructor() {
this.tree = new Map<string, ITreeMember>()
}
constructor(public content: GLTF) {}

public async parse(content: GLTF): Promise<Map<string, ITreeMember>> {
if (content.scenes?.length > 1) {
for (let i = 0; i < content.scenes.length; i++) {
await this.build_tree(content.scenes[i])
/** */
public async parse(): Promise<SvelthreeGLTFTreeMap> {
if (this.content.scenes?.length > 1) {
for (let i = 0; i < this.content.scenes.length; i++) {
await this.build_tree(this.content.scenes[i])
}
} else {
await this.build_tree(content.scene)
await this.build_tree(this.content.scene)
}

return this.tree
Expand All @@ -45,7 +36,7 @@ export default class SvelthreeGLTF {
const fns: (() => Promise<void>)[] = []

const make_three_member =
(obj: THREE.Object3D, parent: THREE.Object3D | undefined, tree_map: Map<string, ITreeMember>) =>
(obj: THREE.Object3D, parent: THREE.Object3D | undefined, tree_map: SvelthreeGLTFTreeMap) =>
async (): Promise<void> => {
tree_map.set(obj.uuid, {
obj: obj,
Expand All @@ -56,11 +47,11 @@ export default class SvelthreeGLTF {
obj.type === "Mesh"
? { geometry: (obj as THREE.Mesh).geometry, material: (obj as THREE.Mesh).material }
: null,
svelthree_comp: null
svelthree_comp: undefined
})
}

function traverse(child: THREE.Object3D, tree_map: Map<string, ITreeMember>, parent?: THREE.Object3D) {
function traverse(child: THREE.Object3D, tree_map: SvelthreeGLTFTreeMap, parent?: THREE.Object3D) {
fns.push(make_three_member(child, parent, tree_map))

const children = child.children
Expand All @@ -78,43 +69,68 @@ export default class SvelthreeGLTF {
//console.log("SvelthreeGLTF parsing FINISHED!")
}

async get_parent_component(parent_uuid: string): Promise<GLTFSupportedSvelthreeComponents> {
return this.tree.get(parent_uuid).svelthree_comp
async get_parent_component(parent_uuid: string): Promise<GLTFSupportedSvelthreeComponents | undefined> {
const tree_member: ISvelthreeGLTFTreeMapMember | undefined = this.tree.get(parent_uuid)

if (tree_member?.svelthree_comp) {
return tree_member?.svelthree_comp
} else {
return undefined
}
}

async get_parent_context(parent_component: GLTFSupportedSvelthreeComponents): Promise<Map<any, any>> {
return parent_component["$$"].context
}

public async apply(dom_target: HTMLElement, root_component: GLTFSupportedSvelthreeComponents): Promise<void> {
public async apply(canvas_component: Canvas, root_component: GLTFSupportedSvelthreeComponents): Promise<void> {
//console.log("SvelthreeGLTF apply started!")

const fns: (() => Promise<void>)[] = []

const create_component =
(item: ITreeMember, dom_target: HTMLElement, root_component: GLTFSupportedSvelthreeComponents) =>
(
item: ISvelthreeGLTFTreeMapMember,
canvas_component: Canvas,
root_component: GLTFSupportedSvelthreeComponents
) =>
async (): Promise<void> => {
let context: Map<any, any> = null
let context: Map<any, any>
if (item.parent_uuid) {
const parent_component = await this.get_parent_component(item.parent_uuid)
context = await this.get_parent_context(parent_component)
if (parent_component) {
context = await this.get_parent_context(parent_component)
} else {
console.error(
`SVELTHREE > utils > SvelthreeGLTF > create_component : invalid 'parent_component' value!`,
parent_component
)
}
} else {
context = root_component["$$"].context
}

switch (item.obj_type) {
case "Mesh":
item.svelthree_comp = new Mesh({
target: dom_target,
target: canvas_component.getDomElement(),
props: { geometry: item.mesh.geometry, material: item.mesh.material, name: item.name },
context
})
break
case "Object3D":
item.svelthree_comp = new Object3D({ target: dom_target, props: { name: item.name }, context })
item.svelthree_comp = new Object3D({
target: canvas_component.getDomElement(),
props: { name: item.name },
context
})
break
case "Group":
item.svelthree_comp = new Group({ target: dom_target, props: { name: item.name }, context })
item.svelthree_comp = new Group({
target: canvas_component.getDomElement(),
props: { name: item.name },
context
})
break
default:
console.error(
Expand All @@ -127,7 +143,11 @@ export default class SvelthreeGLTF {

// const [uuid, item] -> uuid not needed -> [,item]
for (const [, item] of this.tree.entries()) {
fns.push(create_component(item, dom_target, root_component))
if (item) {
fns.push(create_component(item, canvas_component, root_component))
} else {
console.error(`SVELTHREE > utils > SvelthreeGLTF > create_component : invalid 'item' value!`, item)
}
}

for (const fn of fns) {
Expand All @@ -139,11 +159,18 @@ export default class SvelthreeGLTF {
for (const [, item] of this.tree.entries()) {
const comp = item.svelthree_comp

comp.scale = new Vector3().copy(item.obj.scale)
comp.pos = new Vector3().copy(item.obj.position)
comp.rot = new Euler().copy(item.obj.rotation)
comp.castShadow = item.obj.castShadow
comp.receiveShadow = item.obj.receiveShadow
if (comp) {
comp.scale = new Vector3().copy(item.obj.scale)
comp.pos = new Vector3().copy(item.obj.position)
comp.rot = new Euler().copy(item.obj.rotation)
comp.castShadow = item.obj.castShadow
comp.receiveShadow = item.obj.receiveShadow
} else {
console.error(
`SVELTHREE > utils > SvelthreeGLTF > create_component : invalid 'item.svelthree_comp' (comp) value!`,
comp
)
}
}

//console.log("SvelthreeGLTF apply FINISHED!")
Expand Down

0 comments on commit 543fe00

Please sign in to comment.