-
-
Notifications
You must be signed in to change notification settings - Fork 112
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
Use default slot props to get Canvas context #572
Comments
it is duplicated, #573 has the hack (can be closed) |
Are we talking about simply getting e.g., the renderer? Or also setting? |
it is only about using the context via default slot props, rn the example is not working since |
So it's only for getting, right? |
Yes (like inject or exposed context prop) |
Can we use We're using I do think it would be a welcome improvement to simplify the current TresCanvas' context Any thoughts/opinions on using and simplifying
|
Rn context is exposed via |
About the default slot: the problem is the custom renderer, it is adding custom stuff in the default slot, I will ask Kevin if we can retarget the slot using custom setup component when using the custom renderer. |
@alvarosabu @andretchen0 using default slot props in ExtendExample: |
Here the changes, update TresCanvas.vue in root and run build script from root, then start docs dev server once ExtendExample.vue and extending.md files updated: src/components/TresCanvas.vue// L84
const slots = defineSlots<{
default(context: TresContext): any
}>()
const instance = getCurrentInstance()?.appContext.app
const createInternalComponent = (context: TresContext) =>
defineComponent({
setup() {
const ctx = getCurrentInstance()?.appContext
if (ctx) ctx.app = instance as App
provide('useTres', context)
provide('extend', extend)
if (typeof window !== 'undefined' && ctx?.app) {
registerTresDevtools(ctx.app, context)
}
return () => h(Fragment, null, slots?.default ? slots.default(context) : [])
},
}) docs/.vitepress/theme/components/ExtendExample.vue<script setup lang="ts">
import { TresCanvas, extend } from '@tresjs/core'
import { OrbitControls } from 'three/addons/controls/OrbitControls'
import { TextGeometry } from 'three/addons/geometries/TextGeometry'
// Add the element to the catalogue
extend({ TextGeometry, OrbitControls })
// import { useTresContext } from '@tresjs/core'
const styles = {
width: '100%',
height: '550px',
border: '1px solid #e2e2e2',
borderRadius: '8px',
overflow: 'hidden',
}
// const { camera, renderer } = useTresContext()
</script>
<template>
<ClientOnly>
<TresCanvas
v-slot="{ camera, renderer }"
shadows
xwindow-size
clear-color="#fff"
:style="styles"
>
<TresPerspectiveCamera :position="[0, 2, 4]" />
<TresScene>
<TresOrbitControls
v-if="camera.value && renderer.value"
:args="[camera.value, renderer.value.domElement]"
/>
<TresDirectionalLight
:position="[0, 2, 4]"
:intensity="2"
cast-shadow
/>
<TresMesh :rotation="[-Math.PI / 4, -Math.PI / 4, Math.PI / 4]">
<TresTorusGeometry :args="[1, 0.5, 16, 32]" />
<TresMeshToonMaterial color="#FBB03B" />
</TresMesh>
</TresScene>
</TresCanvas>
</ClientOnly>
</template> docs/advanced/extending.md# L36
<ClientOnly>
<div style="aspect-ratio: 16/9; height: auto; margin: 2rem 0; border-radius: 8px; overflow:hidden;">
<ExtendExample />
</div>
</ClientOnly> |
Hey @alvarosabu @userquin !
Sorry, I wasn't clear earlier. I know that Tres is currently using That would be my preference. RationaleThe example of bad DX from #573 is indeed a bummer: <script setup>
// [...]
const trescanvas = ref();
const state = ref();
onMounted(() => {
setTimeout(() => {
state.value = trescanvas.value?.context;
}, 0);
});
// [...]
</script>
<template>
<TresCanvas ref="trescanvas" shadows alpha>
<TresPerspectiveCamera :position="[5, 5, 5]" />
<TresOrbitControls
v-if="state?.renderer"
:args="[state?.camera, state?.renderer?.domElement]"
/>
<!-- -->
</TresCanvas>
</template> But as far as I can see, it can be rewritten more simply and cover the presented use case. See below. It seems to me that the code below isn't materially different from the bad DX example. It only needs one extra line in (Fwiw, <script setup lang="ts">
import { TresCanvas } from '@tresjs/core'
import { ref } from 'vue'
// NOTE: TS likes to know the "shape" or the editor will complain.
const r = ref({ context: { renderer: { value: null } } })
</script>
<template>
<div style="height:50%">
<TresCanvas ref="r" clear-color="#82DBC5">
<TresMesh>
<TresBoxGeometry :args="[1, 1, 1]" />
<TresMeshNormalMaterial />
</TresMesh>
</TresCanvas>
</div>
<div>
<div v-if="r.context.renderer.value">
We have a renderer: {{ Object.keys(r.context.renderer.value) }}
</div>
<div v-else>
We don't have a renderer.
</div>
</div>
</template> Preference:
|
What's the problem using the default slot and exposing props? We can also add some logic to render children when camera and renderer there and provide just the camera and renderer without refs. |
If you're responding to me, then please see my earlier comment.
I don't think it's a bad idea, but it has much bigger implications than this DX issue. I'd like to let the team have a chance to discuss this in a broader context, so I've opened a new discussion about the core and mentioned you there. #578 I've laid out what I think are the related open issues, including this one. |
Description
Idea from @userquin, the idea would be to use Vue named scoped slots to be able to get the canvas context on the parent like this:
Or even deconstruct it
Suggested solution
Add this to
TresCanvas.vue
Alternative
No response
Additional context
related #565
Validations
The text was updated successfully, but these errors were encountered: