nodes/transition_overlay.py¶
Part of Dungeon Explorer.
1"""Fade-to-black transition overlay."""
2
3from simvx.core import Node2D, Property, UpdateMode
4
5
6class TransitionOverlay(Node2D):
7 """Full-screen fade overlay for scene transitions."""
8
9 update_mode = Property(
10 UpdateMode.ALWAYS,
11 hint="Processing behaviour while the tree is paused",
12 on_change="_invalidate_update_mode_cache",
13 )
14
15 # on_draw renders a full-screen rect at self._alpha, which ramps every
16 # frame during a fade -> retained 2D must re-run it each frame.
17 dynamic = True
18
19 def __init__(self, **kwargs):
20 super().__init__(name="TransitionOverlay", **kwargs)
21 self._alpha = 0.0
22 self._phase = "idle" # idle, out, callback, in
23 self._timer = 0.0
24 self._duration = 0.3
25 self._callback = None
26
27 @property
28 def is_transitioning(self) -> bool:
29 return self._phase != "idle"
30
31 def transition(self, callback, fade_duration: float = 0.3):
32 """Start a fade-out → callback → fade-in transition."""
33 if self._phase != "idle":
34 return
35 self._callback = callback
36 self._duration = fade_duration
37 self._phase = "out"
38 self._timer = 0.0
39 self._alpha = 0.0
40
41 def on_update(self, dt: float):
42 if self._phase == "idle":
43 return
44
45 self._timer += dt
46 if self._phase == "out":
47 self._alpha = min(1.0, self._timer / self._duration)
48 if self._timer >= self._duration:
49 self._phase = "callback"
50 self._timer = 0.0
51 elif self._phase == "callback":
52 if self._callback:
53 self._callback()
54 self._callback = None
55 self._phase = "in"
56 self._timer = 0.0
57 elif self._phase == "in":
58 self._alpha = max(0.0, 1.0 - self._timer / self._duration)
59 if self._timer >= self._duration:
60 self._alpha = 0.0
61 self._phase = "idle"
62
63 def on_draw(self, renderer):
64 if self._alpha > 0.001:
65 sw, sh = (1280, 720)
66 if self.tree:
67 sw, sh = self.tree.screen_size
68 renderer.draw_rect((0, 0), (sw, sh), colour=(0.0, 0.0, 0.0, self._alpha), filled=True)