Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: attach #869

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/.vitepress/config/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export const enConfig: LocaleSpecificConfig<DefaultTheme.Config> = {
{ text: 'Extending', link: '/advanced/extending' },
{ text: 'Primitives', link: '/advanced/primitive' },
{ text: 'Scaling Performance 🚀', link: '/advanced/performance' },
{ text: 'Attach', link: '/advanced/attach' },
{
text: 'Caveats',
link: '/advanced/caveats',
Expand Down
190 changes: 190 additions & 0 deletions docs/advanced/attach.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
# `attach` 🖇

Using the `attach` prop, you can tell Tres exactly where you want to insert a child into its parent.

:::info

The `attach` prop is not required for many common cases. For instance:

* adding a single `<Material>` to a `<Mesh>`
* adding a `<Geometry>` to a `<Mesh>`
* adding one or more `<Mesh>`s to a parent `<Mesh>`

:::

## Background

Tres tries to automatically determine where to insert child tag into its parent. For example, in this code, Tres will:

* automatically insert the geometry into `parent.geometry`
* automatically insert the material into `parent.material`

```vue
<template>
<TresMesh name="parent">
<TresBoxGeometry />
<TresMeshNormalMaterial />
</TresMesh>
</template>
```

## Problem

Tres covers common cases, like above. But it doesn't cover every possible case.

When Tres doesn't automatically choose the proper insertion location for a child, one solution is to fall back to procedural code in `<script>`.

Here's how you might add multiple materials to a mesh using `<script>`:

```vue
<script setup lang="ts">
import { MeshBasicMaterial } from 'three'
import { onMounted, shallowRef } from 'vue'

const meshRef = shallowRef()
onMounted(() => {
meshRef.value.material = [
new MeshBasicMaterial({ color: 'red' }),
new MeshBasicMaterial({ color: 'orange' }),
new MeshBasicMaterial({ color: 'yellow' }),
new MeshBasicMaterial({ color: 'green' }),
new MeshBasicMaterial({ color: 'blue' }),
new MeshBasicMaterial({ color: 'purple' }),
]
})
</script>

<template>
<TresMesh ref="meshRef">
<TresBoxGeometry />
</TresMesh>
</template>
```

But this workaround means:

* your materials aren't managed by Tres
* your code is imperative, not declarative
* your code is non-reactive by default

## Solution

The `attach` prop lets you specify where an object will be added to the parent object using declarative code.

## Usage

Here's the example above, rewritten declaratively using `attach`:

```vue
<template>
<TresMesh>
<TresBoxGeometry />
<TresMeshBasicMaterial color="red" attach="material-0" />
<TresMeshBasicMaterial color="orange" attach="material-1" />
<TresMeshBasicMaterial color="yellow" attach="material-2" />
<TresMeshBasicMaterial color="green" attach="material-3" />
<TresMeshBasicMaterial color="blue" attach="material-4" />
<TresMeshBasicMaterial color="purple" attach="material-5" />
</TresMesh>
</template>
```

## "Pierced" `attach`

You can deeply attach a child to a parent by "piercing" – i.e., using a kebab-case string.

### Pseudocode

First, here are a few simple pseudocode examples. This will attach `bar` at `foo.ab.cd`:

```html
<foo>
<bar attach="ab-cd" />
</foo>
```

This will attach `bar` at `foo.ab.cd.ef`:

```html
<foo>
<bar attach="ab-cd-ef" />
</foo>
```

### Usage

As a concrete example, you can used "pierced" `attach` to add custom `BufferAttribute`s:

```vue
<script setup lang="ts">
import { TresCanvas } from '@tresjs/core'

const positions = new Float32Array([-1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0])
</script>

<template>
<TresCanvas clear-color="gray">
<TresMesh :scale="0.3333">
<TresBufferGeometry>
<TresBufferAttribute
attach="attributes-position"
:count="positions.length / 3"
:array="positions"
:itemSize="3"
/>
</TresBufferGeometry>
<TresMeshBasicMaterial color="red" />
</TresMesh>
</TresCanvas>
</template>
```

## Arrays

You can attach within arrays by using array indices in the `attach` string.

### Usage

For example, you can use array indices to attach `THREE` post-processing passes to the `THREE.EffectComposer.passes` array:

```vue
<script lang="ts" setup>
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer'
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass'
import { OutputPass } from 'three/examples/jsm/postprocessing/OutputPass'
import { UnrealBloomPass } from 'three-stdlib'
import { extend, useLoop, useTres } from '@tresjs/core'
import { shallowRef } from 'vue'

extend({ EffectComposer, OutputPass, UnrealBloomPass, RenderPass })
const { renderer, scene, camera, sizes } = useTres()
const composer = shallowRef<EffectComposer>()

useLoop().render(() => {
if (composer.value) {
composer.value!.render()
}
})
</script>

<template>
<TresEffectComposer
ref="composer"
:args="[renderer]"
:set-size="[sizes.width.value, sizes.height.value]"
>
<TresRenderPass
:args="[scene, camera]"
attach="passes-0"
/>
<TresUnrealBloomPass
:args="[undefined, 0.5, 0.1, 0]"
attach="passes-1"
/>
<TresOutputPass
attach="passes-2"
:set-size="[sizes.width.value, sizes.height.value]"
/>
</TresEffectComposer>
</template>
```
9 changes: 8 additions & 1 deletion playground/vue/.eslintrc-auto-import.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@
"watch": true,
"watchEffect": true,
"watchPostEffect": true,
"watchSyncEffect": true
"watchSyncEffect": true,
"DirectiveBinding": true,
"MaybeRef": true,
"MaybeRefOrGetter": true,
"onWatcherCleanup": true,
"useId": true,
"useModel": true,
"useTemplateRef": true
}
}
7 changes: 6 additions & 1 deletion playground/vue/auto-imports.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// @ts-nocheck
// noinspection JSUnusedGlobalSymbols
// Generated by unplugin-auto-import
// biome-ignore lint: disable
export {}
declare global {
const EffectScope: typeof import('vue')['EffectScope']
Expand Down Expand Up @@ -35,6 +36,7 @@ declare global {
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
const onUnmounted: typeof import('vue')['onUnmounted']
const onUpdated: typeof import('vue')['onUpdated']
const onWatcherCleanup: typeof import('vue')['onWatcherCleanup']
const provide: typeof import('vue')['provide']
const reactive: typeof import('vue')['reactive']
const readonly: typeof import('vue')['readonly']
Expand All @@ -52,7 +54,10 @@ declare global {
const useAttrs: typeof import('vue')['useAttrs']
const useCssModule: typeof import('vue')['useCssModule']
const useCssVars: typeof import('vue')['useCssVars']
const useId: typeof import('vue')['useId']
const useModel: typeof import('vue')['useModel']
const useSlots: typeof import('vue')['useSlots']
const useTemplateRef: typeof import('vue')['useTemplateRef']
const watch: typeof import('vue')['watch']
const watchEffect: typeof import('vue')['watchEffect']
const watchPostEffect: typeof import('vue')['watchPostEffect']
Expand All @@ -61,6 +66,6 @@ declare global {
// for type re-export
declare global {
// @ts-ignore
export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue'
export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
import('vue')
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<script setup lang="ts">
import { TresCanvas } from '@tresjs/core'

const previewDataUri = 'data:image/png;base64,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'

const positions = new Float32Array([
-1.0,
-1.0,
1.0, // v0
1.0,
-1.0,
1.0, // v1
1.0,
1.0,
1.0, // v2
1.0,
1.0,
1.0, // v3
-1.0,
1.0,
1.0, // v4
-1.0,
-1.0,
1.0, // v5
])
</script>

<template>
<TresCanvas clear-color="gray">
<TresMesh :scale="0.3333">
<TresBufferGeometry>
<TresBufferAttribute attach="attributes-position" :count="positions.length / 3" :array="positions" :itemSize="3" />
</TresBufferGeometry>
<TresMeshBasicMaterial color="red" />
</TresMesh>
</TresCanvas>

<OverlayInfo>
<h1><code>attach</code>: BufferGeometry</h1>
<h2>Setup</h2>
<p>
In this scene, there is a Mesh with a BufferGeometry, created with JSX. The BufferGeometry has a JSX BufferAttribute, attached to the BufferGeometry's <code>attributes.position</code> using <code>attach</code>.
</p>
<h2>Preview</h2>
<img :src="previewDataUri" />
</OverlayInfo>
</template>
Loading
Loading