Skip to content

Commit

Permalink
feat: 178 v distance to (#220)
Browse files Browse the repository at this point in the history
* feat: add v-distance-to directive proposal

* chore: change life cycle from update to mounted in v-log directive

* chore: update console.table show information

* chore: add console.table, add new utils for extract position on binding

* docs: apply review changes

* chore: apply review changes, handle error null ref

* chore: handle error null ref for vAlwaysLookAt

* chore: fix log message for directives
  • Loading branch information
JaimeTorrealba committed Oct 7, 2023
1 parent 6efc076 commit d2e2521
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 10 deletions.
1 change: 1 addition & 0 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ export default defineConfig({
{ text: 'v-log', link: '/guide/directives/v-log' },
{ text: 'v-light-helper', link: '/guide/directives/v-light-helper' },
{ text: 'v-always-look-at', link: '/guide/directives/v-always-look-at' },
{ text: 'v-distance-to', link: '/guide/directives/v-distance-to' },
],
},
],
Expand Down
36 changes: 36 additions & 0 deletions docs/guide/directives/v-distance-to.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# v-distance-to

Have you tried to calculate the distance between two Object3Ds?

With the new directive `v-distance-to` it's easier than ever, you should only indicate the target object to perform the measure and the result will appear in your console.

In addition, an arrow will be created to indicate which objects you're measuring.

```vue{2,8,13}
<script setup lang="ts">
import { OrbitControls, Sphere, vLog } from '@tresjs/cientos'
</script>
<template>
<TresCanvas v-bind="gl">
<TresPerspectiveCamera :position="[0, 2, 5]" />
<Sphere
ref="sphere1Ref"
:position="[-2, slider, 0]"
:scale="0.5"
/>
<Sphere
v-distance-to="sphere1Ref"
:position="[2, 0, 0]"
:scale="0.5"
/>
<TresGridHelper :args="[10, 10]" />
<OrbitControls />
</TresCanvas>
</template>
```

The use of `v-distance-to` is reactive, so it works perfectly with @tres/leches 🍰.

::: warning
`v-distance-to` will not measure an object in movement within the renderLoop.
:::
44 changes: 44 additions & 0 deletions playground/src/pages/directives/vDistanceTo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<script setup lang="ts">
import { shallowRef } from 'vue'
import { TresCanvas } from '@tresjs/core'
import { OrbitControls, Sphere, vDistanceTo } from '@tresjs/cientos'
import { SRGBColorSpace, NoToneMapping } from 'three'
import { useControls, TresLeches } from '@tresjs/leches'
import '@tresjs/leches/styles'
const gl = {
clearColor: '#333',
outputColorSpace: SRGBColorSpace,
toneMapping: NoToneMapping,
}
const sphere1Ref = shallowRef()
const { value: slider } = useControls({
slider: {
value: -2,
min: -4,
max: 2,
step: 0.1,
},
})
</script>

<template>
<TresLeches class="top-0 important-left-4" />
<TresCanvas v-bind="gl">
<TresPerspectiveCamera :position="[0, 2, 5]" />
<Sphere
ref="sphere1Ref"
:position="[-2, slider, 0]"
:scale="0.5"
/>
<Sphere
v-distance-to="sphere1Ref"
:position="[2, 0, 0]"
:scale="0.5"
/>
<TresGridHelper :args="[10, 10]" />
<OrbitControls />
</TresCanvas>
</template>
5 changes: 5 additions & 0 deletions playground/src/router/routes/directives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,9 @@ export const directivesRoutes = [
name: 'vAlwaysLookAt',
component: () => import('../../pages/directives/vAlwaysLookAt.vue'),
},
{
path: '/directives/v-distance-to',
name: 'vDistanceTo',
component: () => import('../../pages/directives/vDistanceTo.vue'),
},
]
3 changes: 2 additions & 1 deletion src/core/directives/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { vLog } from './vLog'
import { vLightHelper } from './vLightHelper'
import { vAlwaysLookAt } from './vAlwaysLookAt'
import { vDistanceTo } from './vDistanceTo'

export { vLog, vLightHelper, vAlwaysLookAt }
export { vLog, vLightHelper, vAlwaysLookAt, vDistanceTo }
16 changes: 8 additions & 8 deletions src/core/directives/vAlwaysLookAt.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { useRenderLoop } from '@tresjs/core'
import { Vector3 } from 'three'
import { useRenderLoop, useLogger } from '@tresjs/core'
import type { Object3D } from 'three'
import { extractBindingPosition } from '../../utils/index'

const { logWarning } = useLogger()

export const vAlwaysLookAt = {
updated: (el: Object3D, binding: any) => {
let observer = binding.value
if (binding.value && binding.value?.value?.isMesh) {
observer = binding.value.value.position
}
if (Array.isArray(binding.value)) {
observer = new Vector3(...observer)
const observer = extractBindingPosition(binding)
if (!observer) {
logWarning(`v-always-look-at: problem with binding value: ${binding.value}`)
return
}
const { onLoop } = useRenderLoop()
onLoop(() => {
Expand Down
35 changes: 35 additions & 0 deletions src/core/directives/vDistanceTo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { useLogger } from '@tresjs/core'
import { ArrowHelper } from 'three'
import { extractBindingPosition } from '../../utils/index'

const { logWarning } = useLogger()

export const vDistanceTo = {
updated: (el: any, binding: any) => {
const observer = extractBindingPosition(binding)
if (!observer) {
logWarning(`v-distance-to: problem with binding value: ${binding.value}`)
return
}
if (arrowHelper) {
arrowHelper.dispose()
el.parent.remove(arrowHelper)
}
const dir = observer.clone().sub(el.position)
dir.normalize()
arrowHelper = new ArrowHelper( dir, el.position, el.position.distanceTo(observer) / 1.5, 0xffff00 )
el.parent.add( arrowHelper )
// eslint-disable-next-line no-console
console.table([
['Distance:', el.position.distanceTo(observer)],
[`origin: ${el.name || el.type}`, `x:${el.position.x}, y:${el.position.y}, z:${el.position?.z}`],
[`Destiny: ${el.name || el.type}`, `x:${observer.x}, y:${observer.y}, z:${observer?.z}`],
],
)
},
unmounted: (el: any) => {
arrowHelper?.dispose()
el.parent.remove(arrowHelper)
},
}
let arrowHelper: ArrowHelper | null = null
2 changes: 1 addition & 1 deletion src/core/directives/vLog.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export const vLog = {
updated: (el: any, binding: any) => {
mounted: (el: any, binding: any) => {
if (binding.arg) {
// eslint-disable-next-line no-console
console.log(`v-log:${binding.arg}`, el[binding.arg])
Expand Down
11 changes: 11 additions & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Vector3 } from 'three'

/**
* Update the function signature to explicitly specify the type of the props parameter
*
Expand Down Expand Up @@ -29,4 +31,13 @@ export function pick<T extends object, K extends keyof T>(obj: T, props: K[]): P
export function hasSetter(obj: any, prop: string): boolean {
const setterName = `set${prop[0].toUpperCase()}${prop.slice(1)}`
return obj[setterName] !== undefined
}

export function extractBindingPosition(binding: any): Vector3 {
let observer = binding.value
if (binding.value && binding.value?.value?.isMesh) {
observer = binding.value.value.position
}
if (Array.isArray(binding.value)) observer = new Vector3(...observer)
return observer
}

0 comments on commit d2e2521

Please sign in to comment.