Skip to content

Commit

Permalink
fix(primitive): implement as proxy to avoid breaking references (#764)
Browse files Browse the repository at this point in the history
* test: add insert/remove tests

* feat: add filterInPlace

* refactor: make some LocalState fields non-optional

* test: add LocalState graph tests

* refactor: add prepare() to add __tres field

* refactor: add TODOs

* refactor: maintain parent/objects relationship in __tres

* test: add dispose=null test

* feat: allow "dispose=null" to bail out tree disposal

* refactor: update  comments

* refactor: add todo

* test: add/unskip  tests

* refactor(nodeOps): move helper functions to new file

* test: add primitive tests

* refactor: move nodeOpsUtils to utils

* feat: add pierced attach/detach

* chore: clean up merge

* chore: lint

* docs: add playground demo

* chore: update demos

* fix: use proxy for primitive

* fix(primitive): add playground

* test: add material swap test

* refactor: remove unused variable

* refactor: rewrite comment

* docs: add attach/detach demo

* test: update test with new function signature

* refactor: format playground demo

* refactor: add isTresContext

* feat: add general purpose dispose function

* fix: do not clone primitive object

* fix: add shallow removal for primitives

* docs: update primitive object playground

* refactor(remove): move detach, deregister to utils

* chore: merge files from main

* docs: add Sparkles playground

* chore: check if node.__tres is not undefined for increasing eventCount

* docs: improve primitives docs

* docs: added shallowRef suggestion for object

* chore: added dvanced disposal to playground

* refactor: add type cast

* refactor(TresContext): remove isTresContext

---------

Co-authored-by: alvarosabu <alvaro.saburido@gmail.com>
  • Loading branch information
andretchen0 and alvarosabu authored Jul 10, 2024
1 parent 00bef33 commit f637bf3
Show file tree
Hide file tree
Showing 17 changed files with 1,835 additions and 467 deletions.
34 changes: 29 additions & 5 deletions docs/advanced/primitive.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Primitives

The `<primitive />` component is a versatile low-level component in TresJS that allows you to directly use any three.js object within your Vue application without an abstraction. It acts as a bridge between Vue's reactivity system and three.js's scene graph.
The `<primitive />` component is a versatile low-level component in TresJS that allows you to directly use any [three.js](https://threejs.org/) object within your Vue application without an abstraction. It acts as a bridge between Vue's reactivity system and THREE's scene graph.

## Usage

Expand All @@ -18,15 +18,39 @@ The `<primitive />` component is a versatile low-level component in TresJS that
</script>

<template>
<TresCanvas>
<primitive :object="meshWithMaterial" />
</TresCanvas>
<primitive :object="meshWithMaterial" />
</template>
```

## Props

`object`: This prop expects a three.js Object3D or any of its derived classes. It is the primary object that the `<primitive />` component will render. In the updated example, a `Mesh` object with an associated `Material` is passed to this prop.
- `object`: This prop expects either a plain or a reactive three.js [Object3D](https://threejs.org/docs/index.html?q=Object#api/en/core/Object3D) (preferably a [shallowRef](https://vuejs.org/api/reactivity-advanced.html#shallowref)) or any of its derived classes. It is the primary object that the `<primitive />` component will render. In the updated example, a `Mesh` object with an associated `Material` is passed to this prop.

## Events

The same pointer events available on the TresJS components are available on the `<primitive />` component. You can use these events to interact with the object in the scene. See the complete list of events [here](/api/events).

```html
<template>
<primitive
:object="meshWithMaterial"
@click="onClick"
@pointermove="onPointerMove"
/>
</template>
```

## Passing childrens via slots

You can also pass children to the `<primitive />` component using slots. This is useful when you want to add additional objects to the scene that are not part of the main object.

```html
<template>
<primitive :object="meshWithOnlyGeometry">
<MeshBasicMaterial :color="0xff0000" />
</primitive>
</template>
```

## Usage with Models

Expand Down
57 changes: 57 additions & 0 deletions playground/src/pages/advanced/disposal/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<script setup lang="ts">
import { shallowRef } from 'vue'
import { TresCanvas } from '@tresjs/core'
const boxRef = shallowRef()
const tests = [
{
getPass: () => {
const show = boxRef.value?.show
const parentName = boxRef.value?.instance?.parent?.name || null
return !show || parentName === 'intended-parent'
},
msg: 'v-if is false or Box has intended parent',
},
]
const testsRef = shallowRef({ run: () => {} })
let intervalId: ReturnType<typeof setInterval> | null = null
onMounted(() => {
intervalId = setInterval(() => testsRef.value.run(), 100)
})
onUnmounted(() => intervalId && clearInterval(intervalId))
</script>

<template>
<TresCanvas clear-color="gray">
<TresPerspectiveCamera :position="[5, 5, 5]" :look-at="[1, 2, 3]" />
<TresMesh :position="[1, 2, 3]" name="intended-parent">
<TresMesh
v-for="(_, i) of Array.from({ length: 8 }).fill(0)"
:key="i"
:position="[
i % 2 ? -0.5 : 0.5,
Math.floor(i / 2) % 2 ? -0.5 : 0.5,
Math.floor(i / 4) % 2 ? -0.5 : 0.5,
]"
>
<TresBoxGeometry :args="[0.1, 0.1, 0.1]" />
<TresMeshBasicMaterial color="red" />
</TresMesh>
</TresMesh>
</TresCanvas>
<OverlayInfo>
<h1>Issue #717: v-if</h1>
<h2>Setup</h2>
<p>
In this scene, there is a Box with a <code>v-if</code>. Its <code>v-if</code> value is toggled on and off.
When visible, the box's 8 corners should appear at the centers of the red boxes.
</p>
<h2>Tests</h2>
<Tests ref="testsRef" :tests="tests" />
<h2>Issue</h2>
<a href="https://github.com/Tresjs/tres/issues/706#issuecomment-2146244326">
Toggle v-if on a Tres component declared in a separate SFC makes it detach from its parent</a>
</OverlayInfo>
</template>
13 changes: 13 additions & 0 deletions playground/src/pages/issues/701-cientos-v4/TheExperience.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- eslint-disable no-console -->
<script setup lang="ts">
import { OrbitControls, Sparkles, TorusKnot } from '@tresjs/cientos'
</script>

<template>
<TresPerspectiveCamera />
<OrbitControls />
<TorusKnot :scale="0.5" :args="[1, 0.35, 128, 32]">
<TresMeshBasicMaterial color="black" />
<Sparkles />
</TorusKnot>
</template>
35 changes: 35 additions & 0 deletions playground/src/pages/issues/701-cientos-v4/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<!-- eslint-disable no-console -->
<script setup lang="ts">
import { TresCanvas } from '@tresjs/core'
import TheExperience from './TheExperience.vue'
</script>

<template>
<TresCanvas window-size clear-color="gray">
<TheExperience />
</TresCanvas>

<OverlayInfo>
<h1>&lt;primitive&gt; in Cientos v4</h1>
<h2>Setup</h2>
<p>This scene contains a TorusKnot and Cientos' Sparkles component.</p>
<h2>Context</h2>
<p>Sparkles uses a primitive under the hood. Changes to Tres v4's primitives caused the component to stop working.</p>
</OverlayInfo>
</template>

<style scoped>
.overlay {
position: fixed;
max-width: 400px;
top: 0px;
left: 0px;
margin: 10px;
padding: 10px;
background-color: white;
border-radius: 6px;
font-family: sans-serif;
font-size: 14px;
color: #444;
}
</style>
Loading

0 comments on commit f637bf3

Please sign in to comment.