File: clock.py

package info (click to toggle)
python-moderngl-window 3.1.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 69,096 kB
  • sloc: python: 12,076; makefile: 21
file content (122 lines) | stat: -rw-r--r-- 3,695 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import time
from typing import Any, Optional

from moderngl_window.timers.base import BaseTimer


class Timer(BaseTimer):
    """Timer based on python ``time``."""

    def __init__(self, **kwargs: Any) -> None:
        self._start_time: Optional[float] = None
        self._stop_time: Optional[float] = None
        self._pause_time: Optional[float] = None
        self._last_frame = 0.0
        self._offset = 0.0
        self._frames = 0  # similar to ticks
        self._fps = 0.0

    @property
    def is_paused(self) -> bool:
        """bool: The pause state of the timer"""
        return self._pause_time is not None

    @property
    def is_running(self) -> bool:
        """bool: Is the timer currently running?"""
        return self._pause_time is None

    @property
    def time(self) -> float:
        """Get or set the current time.
        This can be used to jump around in the timeline.

        Returns:
            The current time in seconds
        """
        if self._start_time is None:
            return 0.0

        if self.is_paused and self._pause_time is not None:
            return self._pause_time - self._offset - self._start_time

        return time.time() - self._start_time - self._offset

    @time.setter
    def time(self, value: float) -> None:
        if value < 0:
            value = 0.0

        self._offset += self.time - value

    @property
    def fps_average(self) -> float:
        """The average fps since the timer was started"""
        if self._frames == 0:
            return 0.0
        return self._frames / self.time

    @property
    def fps(self) -> float:
        """Get the current frames per second."""
        return self._fps

    def next_frame(self) -> tuple[float, float]:
        """
        Get the time and frametime for the next frame.
        This should only be called once per frame.

        Returns:
            tuple[float, float]: current time and frametime
        """
        self._frames += 1
        current = self.time
        delta, self._last_frame = current - self._last_frame, current

        # Avoid division by zero on first frame
        if delta > 0:
            self._fps = 1.0 / delta
        else:
            self._fps = 0.0

        return current, delta

    def start(self) -> None:
        """Start the timer by recoding the current ``time.time()``
        preparing to report the number of seconds since this timestamp.
        """
        if self._start_time is None:
            self._start_time = time.time()
            self._last_frame = 0.0
        elif self._pause_time is not None:
            self._offset += time.time() - self._pause_time
            self._pause_time = None
        else:
            print("The timer is already started")

    def pause(self) -> None:
        """Pause the timer by setting the internal pause time using ``time.time()``"""
        self._pause_time = time.time()

    def toggle_pause(self) -> None:
        """Toggle the paused state"""
        if self.is_paused:
            self.start()
        else:
            self.pause()

    def stop(self) -> tuple[float, float]:
        """
        Stop the timer. Should only be called once when stopping the timer.

        Returns:
            tuple[float, float]: Current position in the timer, actual running duration
        """
        if self._start_time is None:
            return 0.0, 0.0

        self._stop_time = time.time()
        return (
            self._stop_time - self._start_time - self._offset,
            self._stop_time - self._start_time,
        )