diff --git a/playground/src/components/TheConditional.vue b/playground/src/components/TheConditional.vue
index a195a312d..c1026242b 100644
--- a/playground/src/components/TheConditional.vue
+++ b/playground/src/components/TheConditional.vue
@@ -1,5 +1,5 @@
@@ -29,17 +31,17 @@ pane.addInput(paneElements, 'groupVisible')
-
+
-
+
-
+
diff --git a/src/composables/useRenderer/index.ts b/src/composables/useRenderer/index.ts
index 11eacf7bc..8e3a54993 100644
--- a/src/composables/useRenderer/index.ts
+++ b/src/composables/useRenderer/index.ts
@@ -255,7 +255,7 @@ You could set windowSize=true to force the canvas to be the size of the window.`
{ immediate: true, deep: true },
)
- setInterval(() => console.log(renderer.value?.info.memory), 3000) // TODO remove
+ setInterval(() => console.log(renderer.value?.info.memory, renderer.value?.info.programs?.length), 3000) // TODO remove
return {
renderer,
diff --git a/src/core/nodeOps.ts b/src/core/nodeOps.ts
index 218bee55c..cdca83cc3 100644
--- a/src/core/nodeOps.ts
+++ b/src/core/nodeOps.ts
@@ -1,4 +1,4 @@
-import { BufferAttribute, Mesh } from 'three'
+import { BufferAttribute, Mesh, Object3D } from 'three'
import { useCamera, useRaycaster, useRenderLoop, useLogger } from '/@/composables'
import { RendererOptions } from 'vue'
import { catalogue } from './catalogue'
@@ -23,6 +23,11 @@ function noop(fn: string): any {
let scene: TresObject | null = null
+const OBJECT_3D_USER_DATA_KEYS = {
+ GEOMETRY_VIA_PROP: 'tres__geometryViaProp',
+ MATERIAL_VIA_PROP: 'tres__materialViaProp',
+}
+
export const nodeOps: RendererOptions = {
createElement(tag, _isSVG, _anchor, props) {
if (tag === 'template') return null
@@ -54,6 +59,13 @@ export const nodeOps: RendererOptions = {
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 (props?.material?.isMaterial) (instance as Object3D).userData[MATERIAL_VIA_PROP] = true
+ if (props?.geometry?.isBufferGeometry) (instance as Object3D).userData[GEOMETRY_VIA_PROP] = true
+
return instance
},
insert(child, parent, anchor) {
@@ -122,8 +134,10 @@ export const nodeOps: RendererOptions = {
node.removeFromParent?.()
// TODO how to handle groups?
- node.material?.dispose() // TODO probably disposes material also when passed via prop
- node.geometry?.dispose()
+ const { GEOMETRY_VIA_PROP, MATERIAL_VIA_PROP } = OBJECT_3D_USER_DATA_KEYS
+
+ if (!node.userData[MATERIAL_VIA_PROP]) node.material?.dispose()
+ if (!node.userData[GEOMETRY_VIA_PROP]) node.geometry?.dispose()
//TODO traverse children and dispose them too
@@ -156,6 +170,7 @@ export const nodeOps: RendererOptions = {
if (!target?.set) root = chain.reduce((acc, key) => acc[kebabToCamel(key)], root)
}
+
let value = nextValue
if (value === '') value = true
// Set prop, prefer atomic methods if applicable