Skip to content

Commit

Permalink
feat: primitive
Browse files Browse the repository at this point in the history
  • Loading branch information
alvarosabu committed Apr 14, 2023
1 parent ff6989b commit ab63e14
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 45 deletions.
2 changes: 2 additions & 0 deletions playground/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ declare module '@vue/runtime-core' {
AkuAku: typeof import('./src/components/gltf/AkuAku.vue')['default']
AnimatedModel: typeof import('./src/components/AnimatedModel.vue')['default']
FBXModels: typeof import('./src/components/FBXModels.vue')['default']
Gltf: typeof import('./src/components/gltf/index.vue')['default']
MultipleCanvas: typeof import('./src/components/MultipleCanvas.vue')['default']
PortalJourney: typeof import('./src/components/portal-journey/index.vue')['default']
Responsiveness: typeof import('./src/components/Responsiveness.vue')['default']
Expand All @@ -32,6 +33,7 @@ declare module '@vue/runtime-core' {
TheFirstScene: typeof import('./src/components/TheFirstScene.vue')['default']
TheGizmos: typeof import('./src/components/TheGizmos.vue')['default']
TheGroups: typeof import('./src/components/TheGroups.vue')['default']
TheModel: typeof import('./src/components/gltf/TheModel.vue')['default']
TheParticles: typeof import('./src/components/TheParticles.vue')['default']
ThePortal: typeof import('./src/components/portal-journey/ThePortal.vue')['default']
TheSmallExperience: typeof import('./src/components/TheSmallExperience.vue')['default']
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ const { scene: model } = await useGLTF(
draco: true,
},
)
model.position.set(0, 4, 0)
model.updateMatrixWorld()
const akuAkuRef = ref(null)
Expand All @@ -20,5 +18,5 @@ watch(akuAkuRef, value => {
</script>

<template>
<TresMesh ref="akuAkuRef" v-bind="model" />
<primitive ref="akuAkuRef" :object="model" />
</template>
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script setup lang="ts">
import { sRGBEncoding, BasicShadowMap, NoToneMapping } from 'three'
import { TresCanvas } from '/@/'
import { GLTFModel, OrbitControls } from '@tresjs/cientos'
import { OrbitControls } from '@tresjs/cientos'
const state = reactive({
clearColor: '#82DBC5',
Expand Down Expand Up @@ -29,12 +29,14 @@ watchEffect(() => {
<TresAmbientLight :intensity="0.5" />

<Suspense>
<GLTFModel
<!-- <GLTFModel
ref="akuAkuRef"
path="https://raw.githubusercontent.com/Tresjs/assets/main/models/gltf/aku-aku/AkuAku.gltf"
draco
/>
<!-- <AkuAku /> -->
/> -->
<TresGroup :position="[0, 4, 0]">
<TheModel />
</TresGroup>
</Suspense>
<TresAxesHelper />
<TresDirectionalLight :position="[0, 2, 4]" :intensity="1" cast-shadow />
Expand Down
2 changes: 1 addition & 1 deletion playground/src/pages/index.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script setup lang="ts"></script>
<template>
<Suspense>
<VectorSetProps />
<Gltf />
</Suspense>
</template>
2 changes: 1 addition & 1 deletion playground/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export default defineConfig({
vue({
template: {
compilerOptions: {
isCustomElement: tag => tag.startsWith('Tres') && tag !== 'TresCanvas',
isCustomElement: tag => (tag.startsWith('Tres') && tag !== 'TresCanvas') || tag === 'primitive',
},
},
}),
Expand Down
71 changes: 35 additions & 36 deletions src/core/nodeOps.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,45 @@
import { BufferAttribute } from 'three'
import { useCamera } from '/@/composables'
import { useCamera, useLogger } from '/@/composables'
import { RendererOptions } from 'vue'
import { catalogue } from './catalogue'
import { isFunction } from '@vueuse/core'
import { TresObject } from '../types'
import { TresInstance, TresObject } from '../types'
import { isHTMLTag, kebabToCamel } from '../utils'

import type { Object3D, Material, BufferGeometry } from 'three'

const onRE = /^on[^a-z]/
export const isOn = (key: string) => onRE.test(key)

function noop(fn: string): any {
fn
}

let scene: TresObject | null = null
let fallback: TresObject | null = null

const OBJECT_3D_USER_DATA_KEYS = {
GEOMETRY_VIA_PROP: 'tres__geometryViaProp',
MATERIAL_VIA_PROP: 'tres__materialViaProp',
}
const { logError } = useLogger()

export const nodeOps: RendererOptions<TresObject, TresObject> = {
createElement(tag, _isSVG, _anchor, props) {
if (!props) props = {}

if (props.args === undefined) {
props.args = []
}
if (tag === 'template') return null
if (isHTMLTag(tag)) return null
let name = tag.replace('Tres', '')
let instance

if (props === null) props = {}

if (props?.args) {
instance = new catalogue.value[tag.replace('Tres', '')](...props.args)
if (tag === 'primitive') {
if (props?.object === undefined) logError(`Tres primitives need a prop 'object'`)
const object = props.object as TresInstance
name = object.type
instance = Object.assign(object, { type: name, attach: props.attach, primitive: true })
} else {
instance = new catalogue.value[tag.replace('Tres', '')]()
const target = catalogue.value[name]
if (!target) {
logError(`${name} is not defined on the THREE namespace. Use extend to add it the catalog`)
}
instance = Object.assign(new target(...props.args), { type: name, attach: props.attach, primitive: true })
}

if (instance.isCamera) {
Expand All @@ -52,28 +58,26 @@ export const nodeOps: RendererOptions<TresObject, TresObject> = {
else if (instance.isBufferGeometry) instance.attach = 'geometry'
}

// determine whether the material was passed via prop to
// prevent it's disposal when node is removed later in it's lifecycle
const { GEOMETRY_VIA_PROP, MATERIAL_VIA_PROP } = OBJECT_3D_USER_DATA_KEYS

if (instance.isObject3D) {
if (props?.material?.isMaterial) (instance as Object3D).userData[MATERIAL_VIA_PROP] = true
if (props?.geometry?.isBufferGeometry) (instance as Object3D).userData[GEOMETRY_VIA_PROP] = true
}

instance.events = {}

return instance
},
insert(child, parent, anchor) {
if (scene === null && parent.isScene) scene = parent
if (parent === null) parent = scene as TresObject
insert(child, parent) {
if (
(child?.__vnode.type === 'TresGroup' || child?.__vnode.type === 'TresObject3D') &&
parent === null &&
!child?.__vnode?.ctx?.asyncResolved
) {
fallback = child
return
}

if (!parent) parent = fallback as TresObject

//vue core
/* parent.insertBefore(child, anchor || null) */
if (parent?.isObject3D && child?.isObject3D) {
const index = anchor ? parent.children.indexOf(anchor) : 0
child.parent = parent
parent.children.splice(index, 0, child)
if (child?.isObject3D && parent?.isObject3D) {
parent.add(child)
child.dispatchEvent({ type: 'added' })
} else if (typeof child?.attach === 'string') {
child.__previousAttach = child[parent?.attach]
Expand All @@ -84,7 +88,6 @@ export const nodeOps: RendererOptions<TresObject, TresObject> = {
},
remove(node) {
if (!node) return

// remove is only called on the node being removed and not on child nodes.

if (node.isObject3D) {
Expand Down Expand Up @@ -114,10 +117,6 @@ export const nodeOps: RendererOptions<TresObject, TresObject> = {
let finalKey = kebabToCamel(key)
let target = root?.[finalKey]

if (!node.parent) {
node.parent = scene as TresObject
}

if (root.type === 'BufferGeometry') {
root.setAttribute(
kebabToCamel(key),
Expand Down Expand Up @@ -157,7 +156,6 @@ export const nodeOps: RendererOptions<TresObject, TresObject> = {
return node?.parent || null
},
createText: () => noop('createText'),

createComment: () => noop('createComment'),

setText: () => noop('setText'),
Expand All @@ -169,5 +167,6 @@ export const nodeOps: RendererOptions<TresObject, TresObject> = {

setScopeId: () => noop('setScopeId'),
cloneNode: () => noop('cloneNode'),

insertStaticContent: () => noop('insertStaticContent'),
}

0 comments on commit ab63e14

Please sign in to comment.