Spaces:
Building
Building
# Copyright (c) Meta Platforms, Inc. and affiliates. | |
# This source code is licensed under the MIT license found in the | |
# LICENSE file in the root directory of this source tree. | |
""" Interactive Controller Class Module """ | |
import time | |
from typing import Optional | |
import glfw | |
from animated_drawings.controller.controller import Controller | |
from animated_drawings.model.scene import Scene | |
from animated_drawings.view.window_view import WindowView | |
from animated_drawings.config import ControllerConfig | |
class InteractiveController(Controller): | |
""" Interactive Controller Class """ | |
def __init__(self, cfg: ControllerConfig, scene: Scene, view: WindowView) -> None: | |
super().__init__(cfg, scene) | |
self.view: WindowView = view | |
self.prev_time: float = 0.0 # tracks real-world time passing between run loops | |
self.pause: bool = False # tracks whether time progresses in the scene | |
glfw.init() | |
glfw.set_key_callback(self.view.win, self._on_key) | |
def _on_key(self, _win, key: int, _scancode, action, _mods) -> None: # noqa: C901 | |
if action not in (glfw.PRESS, glfw.REPEAT): | |
return | |
# close window | |
if key in (glfw.KEY_ESCAPE, glfw.KEY_Q): | |
glfw.set_window_should_close(self.view.win, True) | |
# move camera forward | |
elif key == glfw.KEY_W: | |
_, _, fwd = self.view.camera.get_right_up_fwd_vectors() | |
self.view.camera.offset(-0.1 * fwd) | |
# move camera back | |
elif key == glfw.KEY_S: | |
_, _, fwd = self.view.camera.get_right_up_fwd_vectors() | |
self.view.camera.offset(0.1 * fwd) | |
# move camera right | |
elif key == glfw.KEY_A: | |
right, _, _ = self.view.camera.get_right_up_fwd_vectors() | |
self.view.camera.offset(-0.1 * right) | |
# move camera left | |
elif key == glfw.KEY_D: | |
right, _, _ = self.view.camera.get_right_up_fwd_vectors() | |
self.view.camera.offset(0.1 * right) | |
# move camera up | |
elif key == glfw.KEY_E: | |
_, up, _ = self.view.camera.get_right_up_fwd_vectors() | |
self.view.camera.offset(0.1 * up) | |
# move camera down | |
elif key == glfw.KEY_R: | |
_, up, _ = self.view.camera.get_right_up_fwd_vectors() | |
self.view.camera.offset(-0.1 * up) | |
# toggle start/stop time | |
elif key == glfw.KEY_SPACE: | |
self.pause = not self.pause | |
self.prev_time = time.time() | |
# step forward in time | |
elif key == glfw.KEY_RIGHT: | |
self._tick(self.cfg.keyboard_timestep) | |
# step backward in time | |
elif key == glfw.KEY_LEFT: | |
self._tick(-self.cfg.keyboard_timestep) | |
def _is_run_over(self) -> None: | |
return glfw.window_should_close(self.view.win) | |
def _prep_for_run_loop(self) -> None: | |
self.prev_time = time.time() | |
def _start_run_loop_iteration(self) -> None: | |
self.view.clear_window() | |
def _tick(self, delta_t: Optional[float] = None) -> None: | |
# if passed a specific value to progress time by, do so | |
if delta_t: | |
self.scene.progress_time(delta_t) | |
# otherwise, if scene is paused, do nothing | |
elif self.pause: | |
pass | |
# otherwise, calculate real time passed since last call and progress scene by that amount | |
else: | |
cur_time = time.time() | |
self.scene.progress_time(cur_time - self.prev_time) | |
self.prev_time = cur_time | |
def _update(self) -> None: | |
self.scene.update_transforms() | |
def _handle_user_input(self) -> None: | |
glfw.poll_events() | |
def _render(self) -> None: | |
self.view.render(self.scene) | |
def _finish_run_loop_iteration(self) -> None: | |
self.view.swap_buffers() | |
def _cleanup_after_run_loop(self) -> None: | |
self.view.cleanup() | |