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

feat: renamed useCamera composable methods to prevent confusion #380

Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
feature: renamed useCamera composable methods to prevent confusion
  • Loading branch information
Tinoooo committed Aug 24, 2023
commit ccd1f4989a36dcb4e15e4600298eb417c7203e87
66 changes: 30 additions & 36 deletions docs/blog/announcing-v-3.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ sidebar: false

Already? Yes! We are excited to announce the release of:

- **TresJS v3.0.0**
- **Cientos v3.0.0**
- **TresJS v3.0.0**
- **Cientos v3.0.0**

But you might be wondering, why a major release so soon if we just released 2.x.x not so while ago 🤔? Does it means more breaking changes? 🤯

Expand All @@ -23,15 +23,15 @@ Until now, we were using a `Store` to manage the internal state of the library

```ts
const state: TresState = shallowReactive({
uuid: generateUUID(),
camera: undefined,
cameras: [],
canvas: undefined,
scene: undefined,
renderer: undefined,
aspectRatio: undefined,
pointerEventHandler: undefined,
})
uuid: generateUUID(),
camera: undefined,
cameras: [],
canvas: undefined,
scene: undefined,
renderer: undefined,
aspectRatio: undefined,
pointerEventHandler: undefined,
})
```

Important things for the abstractions like `camera`, `scene`, `renderer`, etc. were stored in the `Store` and we were using `reactive` and `shallowReactive` to make sure that the changes were propagated to the components that were using them.
Expand All @@ -40,12 +40,12 @@ And we had some kind of "getters" and "setters" to access/edit the state from th

```ts
function getState(key: string) {
return state[key]
return state[key]
}

function setState(key: string, value: any) {
state[key] = value
}
state[key] = value
}
```

If a plugin author or a user wanted to create an abstraction around the `core`. They would have to use something like this:
Expand All @@ -55,9 +55,9 @@ const { state } = useTres()

watch(
() => state.camera,
(camera) => {
camera => {
// do something with the camera
}
},
)
```

Expand All @@ -67,33 +67,29 @@ Also we experience lot of bugs related to the reactivity system, specially when

So we decided to **move away from the `Store` and use a `Context Provider` instead** where the state is a plain object with .


```ts
const toProvide: TresContext = {
sizes,
scene: shallowRef<Scene>(scene),
camera,
cameras: readonly(cameras),
renderer,
raycaster: shallowRef(new Raycaster()),
controls: ref(null),
extend,
addCamera,
removeCamera,
setCameraActive,
}

provide('useTres', toProvide);
sizes,
scene: shallowRef<Scene>(scene),
camera,
extend,
cameras: readonly(cameras),
renderer,
controls: ref(null),
raycaster: shallowRef(new Raycaster()),
setCameraActive,
}

provide('useTres', toProvide)
```

So now you can use any property of the state individually, like this:

```html

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

const { camera, scene, renderer} = useTresContext()
const { camera, scene, renderer } = useTresContext()
</script>
```

Expand All @@ -111,5 +107,3 @@ Hope you like this new release, we are working hard to bring you the best possib

- Releases https://github.com/Tresjs/tres/releases
- Cientos https://github.com/Tresjs/cientos/releases


210 changes: 105 additions & 105 deletions src/components/TresCanvas.vue
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
<script setup lang="ts">
import {
PerspectiveCamera,
Scene,
WebGLRendererParameters,
type ColorSpace,
type ShadowMapType,
type ToneMapping,
PerspectiveCamera,
Scene,
WebGLRendererParameters,
type ColorSpace,
type ShadowMapType,
type ToneMapping,
} from 'three'
import { Ref, computed, onMounted, provide, ref, shallowRef, watch, watchEffect } from 'vue'
import { useTresContextProvider, type TresContext } from '../composables'
import { extend } from '../core/catalogue'
import { render } from '../core/renderer'

import {
useLogger,
usePointerEventHandler,
useRenderLoop,
useLogger,
usePointerEventHandler,
useRenderLoop,
} from '../composables'

import { Fragment, defineComponent, h } from 'vue'
Expand All @@ -24,28 +24,28 @@ import type { TresCamera, TresObject } from '../types/'


export interface TresCanvasProps extends Omit<WebGLRendererParameters, 'canvas'> {
// required by for useRenderer
shadows?: boolean
clearColor?: string
toneMapping?: ToneMapping
shadowMapType?: ShadowMapType
useLegacyLights?: boolean
outputColorSpace?: ColorSpace
toneMappingExposure?: number

// required by useTresContextProvider
windowSize?: boolean
preset?: RendererPresetsType
disableRender?: boolean
camera?: TresCamera,
// required by for useRenderer
shadows?: boolean
clearColor?: string
toneMapping?: ToneMapping
shadowMapType?: ShadowMapType
useLegacyLights?: boolean
outputColorSpace?: ColorSpace
toneMappingExposure?: number

// required by useTresContextProvider
windowSize?: boolean
preset?: RendererPresetsType
disableRender?: boolean
camera?: TresCamera,
}

const props = withDefaults(defineProps<TresCanvasProps>(), {
alpha: false,
antialias: true,
depth: true,
stencil: true,
preserveDrawingBuffer: false,
alpha: false,
antialias: true,
depth: true,
stencil: true,
preserveDrawingBuffer: false,
})

const { logWarning } = useLogger()
Expand All @@ -62,100 +62,100 @@ const scene = shallowRef(new Scene())
const { resume } = useRenderLoop()

const slots = defineSlots<{
default(): any
default(): any
}>()

const createInternalComponent = (context: TresContext) => {
return defineComponent({
setup() {
provide('useTres', context)
provide('extend', extend)
return () => h(Fragment, null, slots?.default ? slots.default() : [])
}
})
return defineComponent({
setup() {
provide('useTres', context)
provide('extend', extend)
return () => h(Fragment, null, slots?.default ? slots.default() : [])
}
})
}

const mountCustomRenderer = (context: TresContext) => {
const InternalComponent = createInternalComponent(context)
render(h(InternalComponent), scene.value as unknown as TresObject)
const InternalComponent = createInternalComponent(context)
render(h(InternalComponent), scene.value as unknown as TresObject)
}

const dispose = (context: TresContext) => {
scene.value.children = []
mountCustomRenderer(context)
resume()
scene.value.children = []
mountCustomRenderer(context)
resume()
}

const disableRender = computed(() => props.disableRender)

onMounted(() => {
const existingCanvas = canvas as Ref<HTMLCanvasElement>

const context = useTresContextProvider({
scene: scene.value,
canvas: existingCanvas,
windowSize: props.windowSize,
disableRender,
rendererOptions: props,
})

usePointerEventHandler({ scene: scene.value, contextParts: context })

const { addCamera, camera, cameras, removeCamera } = context

mountCustomRenderer(context)

const addDefaultCamera = () => {
const camera = new PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000)
camera.position.set(3, 3, 3)
camera.lookAt(0, 0, 0)
addCamera(camera)

const unwatch = watchEffect(
() => {
if (cameras.value.length >= 2) {
camera.removeFromParent()
removeCamera(camera)
unwatch?.()
}
},
)
}

watch(() => props.camera, (newCamera, oldCamera) => {
if (newCamera)
addCamera(newCamera)
else if (oldCamera) {
oldCamera.removeFromParent()
removeCamera(oldCamera)
const existingCanvas = canvas as Ref<HTMLCanvasElement>

const context = useTresContextProvider({
scene: scene.value,
canvas: existingCanvas,
windowSize: props.windowSize,
disableRender,
rendererOptions: props,
})

usePointerEventHandler({ scene: scene.value, contextParts: context })

const { registerCamera, camera, cameras, deregisterCamera } = context

mountCustomRenderer(context)

const addDefaultCamera = () => {
const camera = new PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000)
camera.position.set(3, 3, 3)
camera.lookAt(0, 0, 0)
registerCamera(camera)

const unwatch = watchEffect(
() => {
if (cameras.value.length >= 2) {
camera.removeFromParent()
deregisterCamera(camera)
unwatch?.()
}
}, {
immediate: true
})

if (!camera.value) {
logWarning(
'No camera found. Creating a default perspective camera. ' +
'To have full control over a camera, please add one to the scene.'
)
addDefaultCamera()
},
)
}

watch(() => props.camera, (newCamera, oldCamera) => {
if (newCamera)
registerCamera(newCamera)
else if (oldCamera) {
oldCamera.removeFromParent()
deregisterCamera(oldCamera)
}

if (import.meta.hot)
import.meta.hot.on('vite:afterUpdate', () => dispose(context))
}, {
immediate: true
})

if (!camera.value) {
logWarning(
'No camera found. Creating a default perspective camera. ' +
'To have full control over a camera, please add one to the scene.'
)
addDefaultCamera()
}

if (import.meta.hot)
import.meta.hot.on('vite:afterUpdate', () => dispose(context))
})
</script>
<template>
<canvas ref="canvas" :data-scene="scene.uuid" :style="{
display: 'block',
width: '100%',
height: '100%',
position: windowSize ? 'fixed' : 'relative',
top: 0,
left: 0,
pointerEvents: 'auto',
touchAction: 'none',
zIndex: 1,
}">
</canvas>
<canvas ref="canvas" :data-scene="scene.uuid" :style="{
display: 'block',
width: '100%',
height: '100%',
position: windowSize ? 'fixed' : 'relative',
top: 0,
left: 0,
pointerEvents: 'auto',
touchAction: 'none',
zIndex: 1,
}">
</canvas>
</template>
Loading
Loading