<script setup lang="ts">
import {
  ACESFilmicToneMapping,
  BoxGeometry,
  Clock,
  DirectionalLight,
  Mesh,
  MeshToonMaterial,
  PlaneGeometry,
  Scene,
  sRGBEncoding,
} from 'three'
import gsap from 'gsap'

const scene = new Scene()
const { createCamera } = useCamera()

const camera = createCamera(CameraType.Perspective)

camera.position.set(15, 15, 15)

scene.add(camera)

const ambientLight = new DirectionalLight(0xffffff, 0.5)

const directionalLight = new DirectionalLight('#FCF9D9', 1)
directionalLight.position.set(-8, 16, 8)
directionalLight.castShadow = true
/* directionalLight.shadow.mapSize.set(1024, 1024)
directionalLight.shadow.camera.near = 0.5
directionalLight.shadow.camera.far = 500
directionalLight.shadow.camera.left = -100
directionalLight.shadow.camera.right = 100
directionalLight.shadow.camera.top = 100
directionalLight.shadow.camera.bottom = -100 */

scene.add(ambientLight, directionalLight)

// Objects
const cube = new Mesh(new BoxGeometry(2, 2, 2, 32, 32), new MeshToonMaterial({ color: 'teal' }))

cube.position.set(0, 4, 0)
cube.rotation.set(-Math.PI / 4, -Math.PI / 4, -Math.PI / 4)
cube.castShadow = true
scene.add(cube)

const plane = new Mesh(new PlaneGeometry(10, 10, 10, 10), new MeshToonMaterial({ color: '#444' }))

plane.rotation.set(-Math.PI / 2, 0, 0)

plane.receiveShadow = true

scene.add(plane)

// Renderer

const { experience, initRenderer, updateRenderer, renderScene, updateControls, disposeRenderer } = useRenderer()

const clock = new Clock()

const { pane, fpsGraph } = useTweakPane()

const btnBounceFar = pane.addButton({
  title: 'Bounce far',
})

btnBounceFar.on('click', () => {
  gsap.to(camera.position, {
    ease: 'bounce.out',
    duration: 1,
    x: 30,
    y: 30,
    z: 30,
  })
})

const btnSlowlyApproach = pane.addButton({
  title: 'Slowly Approach',
})

btnSlowlyApproach.on('click', () => {
  gsap.to(camera.position, {
    ease: 'slow(0.5, 0.5, false)',
    duration: 5,
    x: 4,
    y: 2,
    z: 20,
  })
  /*  gsap.to(camera.rotation, {
    ease: 'power',
    duration: 2,
    x: -Math.PI / 2,
    y: -Math.PI / 2,
    z: -Math.PI / 2,
  }) */
})

const loop = () => {
  // Update renderer
  fpsGraph.begin()
  const elapsedTime = clock.getElapsedTime()

  cube.rotation.y = elapsedTime
  cube.position.y = Math.sin(elapsedTime) + 4
  updateControls()

  renderScene(scene, camera)
  fpsGraph.end()
  requestAnimationFrame(loop)
}

onMounted(() => {
  initRenderer(camera, {
    renderer: {
      antialias: true,
      alpha: true,
      preserveDrawingBuffer: true,
    },
    shadows: true,
    controls: true,
    physicallyCorrectLights: true,
    outputEncoding: sRGBEncoding,
    toneMapping: ACESFilmicToneMapping,
  })
  loop()
  updateRenderer()
})

onBeforeUnmount(() => {
  disposeRenderer()
})
</script>

<template>
  <canvas ref="experience"></canvas>
</template>

<route lang="yaml">
meta:
  layout: experiment
  title: Camera animation with GSAP
  media: '/animations/cameragsap.png'
  status: published
  description: 'How to animate camera position with GSAP'
  tags: ['animation', 'gsap', 'camera']
</route>
