diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts
index 687eff323..c02cb4fcf 100644
--- a/docs/.vitepress/config.ts
+++ b/docs/.vitepress/config.ts
@@ -72,6 +72,7 @@ export default defineConfig({
{ text: 'useAnimations', link: '/cientos/abstractions/use-animations' },
{ text: 'Environment', link: '/cientos/abstractions/environment' },
{ text: 'useEnvironment', link: '/cientos/abstractions/use-environment' },
+ { text: 'usePamMouse', link: '/cientos/abstractions/pam-camera-mouse' },
],
},
{
diff --git a/docs/cientos/abstractions/pam-camera-mouse.md b/docs/cientos/abstractions/pam-camera-mouse.md
new file mode 100644
index 000000000..044cd67f2
--- /dev/null
+++ b/docs/cientos/abstractions/pam-camera-mouse.md
@@ -0,0 +1,33 @@
+# PamCameraMouse
+
+![](/cientos/PamCameraMouse.gif)
+
+`` is a component that allow you to create easily the pam mouse camera effect. The camera will update automatically according to the mouse position, creating a beautiful nice effect
+
+## Usage
+
+You only need import it and use it `` additionally you can pass two props, disabled and factor. Factor is a number to increase the movement range of the camera
+
+```vue
+
+
+
+
+
+
+
+
+
+
+```
+
+::: warning
+By the nature of the pam mouse camera effect it creates conflicts if it's used in combination with OrbitControls
+:::
+
+## Props [[1]](#1)
+
+| Prop | Description | Default |
+| :----------- | :------------------------------------------------------ | ------- |
+| **disabled** | enable or disabled the effect, boolean | false |
+| **factor** | Number use to increase the range of the camera movement | 5 |
diff --git a/docs/public/cientos/PamCameraMouse.gif b/docs/public/cientos/PamCameraMouse.gif
new file mode 100644
index 000000000..b405460aa
Binary files /dev/null and b/docs/public/cientos/PamCameraMouse.gif differ
diff --git a/packages/cientos/src/composables/useLogger.ts b/packages/cientos/src/composables/useLogger.ts
new file mode 100644
index 000000000..d7d67a24b
--- /dev/null
+++ b/packages/cientos/src/composables/useLogger.ts
@@ -0,0 +1,32 @@
+/* eslint-disable no-console */
+export const isProd = import.meta.env.MODE === 'production'
+
+const logPrefix = '[TresJS - Cientos ▲ ■ ♥] '
+
+interface LoggerComposition {
+ logError: (message: string, error?: Error | ErrorEvent) => void
+ logWarning: (message: string) => void
+ logMessage: (name: string, value: any) => void
+}
+
+export function useLogger(): LoggerComposition {
+ function logError(message: string, error?: Error | ErrorEvent) {
+ console.error(`${logPrefix} ${message}`, error || '')
+ }
+
+ function logWarning(message: string) {
+ console.warn(`${logPrefix} ${message}`)
+ }
+
+ function logMessage(name: string, value: any) {
+ if (!isProd) {
+ console.log(`${logPrefix} - ${name}:`, value)
+ }
+ }
+
+ return {
+ logError,
+ logWarning,
+ logMessage,
+ }
+}
diff --git a/packages/cientos/src/core/TransformControls.vue b/packages/cientos/src/core/TransformControls.vue
index 6fe9a6f79..804148c8d 100644
--- a/packages/cientos/src/core/TransformControls.vue
+++ b/packages/cientos/src/core/TransformControls.vue
@@ -67,8 +67,8 @@ function addEventListeners(controls: TransformControlsImp) {
watch(
() => props.object,
() => {
- if (state.camera?.value && state.renderer && state.scene && props.object) {
- controls.value = new TransformControlsImp(state.camera.value, unref(state.renderer).domElement)
+ if (state.camera && state.renderer && state.scene && props.object) {
+ controls.value = new TransformControlsImp(state.camera, unref(state.renderer).domElement)
controls.value.attach(unref(props.object))
state.scene.add(unref(controls) as TransformControlsImp)
diff --git a/packages/cientos/src/core/usePamCameraMouse/component.ts b/packages/cientos/src/core/usePamCameraMouse/component.ts
new file mode 100644
index 000000000..d14702a2b
--- /dev/null
+++ b/packages/cientos/src/core/usePamCameraMouse/component.ts
@@ -0,0 +1,29 @@
+import { defineComponent } from 'vue'
+import { usePamCameraMouse } from '.'
+import { useCientos } from '../useCientos'
+
+export const PamCameraMouse = defineComponent({
+ name: 'PamCameraMouse',
+ props: {
+ disabled: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ factor: {
+ type: Number,
+ required: false,
+ default: 5,
+ },
+ },
+ setup(props: any) {
+ const { state } = useCientos()
+ const camera = state?.camera
+
+ const PamCameraMouse = usePamCameraMouse(props.disabled as boolean, props.factor as number, camera)
+
+ return () => {
+ PamCameraMouse
+ }
+ },
+})
diff --git a/packages/cientos/src/core/usePamCameraMouse/index.ts b/packages/cientos/src/core/usePamCameraMouse/index.ts
new file mode 100644
index 000000000..66cc08b26
--- /dev/null
+++ b/packages/cientos/src/core/usePamCameraMouse/index.ts
@@ -0,0 +1,24 @@
+import { watchEffect, computed } from 'vue'
+import { Camera } from 'three'
+import { useWindowSize, useMouse } from '@vueuse/core'
+import { useLogger } from '/@/composables/useLogger'
+
+export function usePamCameraMouse(disabled = false, factor = 5, camera: Camera | undefined) {
+ const { x, y } = useMouse()
+ const { logWarning } = useLogger()
+ const { width, height } = useWindowSize()
+ const cameraX = computed(() => (x.value / width.value - 0.5) * factor)
+ const cameraY = computed(() => -(y.value / height.value - 0.5) * factor)
+ if (camera) {
+ const { x: initX, y: initY } = camera.position
+ watchEffect(() => {
+ if (disabled) return
+ if (camera) {
+ camera.position.x = initX + cameraX.value
+ camera.position.y = initY + cameraY.value
+ }
+ })
+ } else {
+ logWarning('Scene must contain a Camera component to use this composable')
+ }
+}
diff --git a/packages/cientos/src/index.ts b/packages/cientos/src/index.ts
index af262b216..4389f8aa1 100644
--- a/packages/cientos/src/index.ts
+++ b/packages/cientos/src/index.ts
@@ -1,5 +1,6 @@
import OrbitControls from './core/OrbitControls.vue'
import TransformControls from './core/TransformControls.vue'
+import { PamCameraMouse } from './core/usePamCameraMouse/component'
import { useTweakPane } from './core/useTweakPane'
import { useAnimations } from './core/useAnimations'
import { GLTFModel } from './core/useGLTF/component'
@@ -23,6 +24,7 @@ import { Environment } from './core/useEnvironment/component'
export * from './core/useGLTF'
export * from './core/useFBX'
export * from './core/useEnvironment'
+export * from './core/usePamCameraMouse'
export {
OrbitControls,
TransformControls,
@@ -45,4 +47,5 @@ export {
Dodecahedron,
useAnimations,
Environment,
+ PamCameraMouse,
}
diff --git a/packages/cientos/vite.config.ts b/packages/cientos/vite.config.ts
index d7f09a399..ced9a48a1 100644
--- a/packages/cientos/vite.config.ts
+++ b/packages/cientos/vite.config.ts
@@ -13,7 +13,7 @@ import { lightGreen, yellow, gray, bold } from 'kolorist'
import pkg from './package.json'
// eslint-disable-next-line no-console
-console.log(`${lightGreen('▲')} ${gray('■')} ${yellow('⚡️')} ${bold('Tres/cientos')} v${pkg.version}`)
+console.log(`${lightGreen('▲')} ${gray('■')} ${yellow('♥')} ${bold('Tres/cientos')} v${pkg.version}`)
// https://vitejs.dev/config/
export default defineConfig({
resolve: {
diff --git a/packages/tres/src/App.vue b/packages/tres/src/App.vue
index 5cadfca48..ddf7cec8f 100644
--- a/packages/tres/src/App.vue
+++ b/packages/tres/src/App.vue
@@ -1,11 +1,14 @@
-
-
+
diff --git a/packages/tres/src/components/TheEnvironment.vue b/packages/tres/src/components/TheEnvironment.vue
index b80a24d73..08f834f30 100644
--- a/packages/tres/src/components/TheEnvironment.vue
+++ b/packages/tres/src/components/TheEnvironment.vue
@@ -1,6 +1,6 @@