annotate blender/time_sync/blender_time.py @ 2455:2d454737a916

split blender code to new file
author drewp@bigasterisk.com
date Tue, 20 May 2025 09:24:35 -0700
parents blender/time_sync/time_from_graph.py@405abed9a45c
children d94480bfb179
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2455
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
1 from dataclasses import dataclass
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
2 from typing import Callable
2432
b8a408caf115 start blender sync
drewp@bigasterisk.com
parents:
diff changeset
3
2455
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
4 import bpy
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
5 from bpy.app.handlers import persistent
2432
b8a408caf115 start blender sync
drewp@bigasterisk.com
parents:
diff changeset
6
b8a408caf115 start blender sync
drewp@bigasterisk.com
parents:
diff changeset
7 from light9.run_local import log
2455
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
8
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
9 UPDATE_PERIOD = 1 / 20
2432
b8a408caf115 start blender sync
drewp@bigasterisk.com
parents:
diff changeset
10
b8a408caf115 start blender sync
drewp@bigasterisk.com
parents:
diff changeset
11
b8a408caf115 start blender sync
drewp@bigasterisk.com
parents:
diff changeset
12 def clamp(lo, hi, x):
b8a408caf115 start blender sync
drewp@bigasterisk.com
parents:
diff changeset
13 return max(lo, min(hi, x))
b8a408caf115 start blender sync
drewp@bigasterisk.com
parents:
diff changeset
14
b8a408caf115 start blender sync
drewp@bigasterisk.com
parents:
diff changeset
15
2455
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
16 class _TimeEvent():
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
17 pass
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
18
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
19
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
20 class SceneLoaded(_TimeEvent):
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
21 pass
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
22
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
23
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
24 @dataclass
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
25 class PausedGotoTime(_TimeEvent):
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
26 t: float
2432
b8a408caf115 start blender sync
drewp@bigasterisk.com
parents:
diff changeset
27
b8a408caf115 start blender sync
drewp@bigasterisk.com
parents:
diff changeset
28
2455
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
29 @dataclass
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
30 class PlayingGotoTime(_TimeEvent):
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
31 t: float
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
32
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
33
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
34 class BlenderTime:
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
35 """all methods to run in main thread"""
2432
b8a408caf115 start blender sync
drewp@bigasterisk.com
parents:
diff changeset
36
2455
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
37 def __init__(self, onEvent: Callable[[_TimeEvent], None]):
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
38 self._onEvent = onEvent
2432
b8a408caf115 start blender sync
drewp@bigasterisk.com
parents:
diff changeset
39 self.lastSetFrame = -1
2455
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
40
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
41 def start(self):
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
42 bpy.app.handlers.load_post.append(self._on_load_post)
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
43 bpy.app.handlers.frame_change_post.append(self._on_frame_change_post)
2454
405abed9a45c fix up asyncio-in-bg-thread sorcery
drewp@bigasterisk.com
parents: 2453
diff changeset
44
2453
b23afde50bc2 blender addons get thier own pdm setup for now. fix time_from_graph startup race
drewp@bigasterisk.com
parents: 2436
diff changeset
45 # need persistent because `blender --addons ...` seems to start addon
b23afde50bc2 blender addons get thier own pdm setup for now. fix time_from_graph startup race
drewp@bigasterisk.com
parents: 2436
diff changeset
46 # before loading scene.
b23afde50bc2 blender addons get thier own pdm setup for now. fix time_from_graph startup race
drewp@bigasterisk.com
parents: 2436
diff changeset
47 bpy.app.timers.register(self.update, persistent=True)
2432
b8a408caf115 start blender sync
drewp@bigasterisk.com
parents:
diff changeset
48
2455
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
49 self.emitEvent(SceneLoaded())
2432
b8a408caf115 start blender sync
drewp@bigasterisk.com
parents:
diff changeset
50
2455
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
51 def setSceneDuration(self, duration: float):
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
52 self.duration = duration
2432
b8a408caf115 start blender sync
drewp@bigasterisk.com
parents:
diff changeset
53 scene = bpy.context.scene
b8a408caf115 start blender sync
drewp@bigasterisk.com
parents:
diff changeset
54 fps = scene.render.fps
b8a408caf115 start blender sync
drewp@bigasterisk.com
parents:
diff changeset
55 scene.frame_start = 0
b8a408caf115 start blender sync
drewp@bigasterisk.com
parents:
diff changeset
56 scene.frame_end = int(duration * fps)
2455
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
57
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
58 def frameDuration(self):
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
59 return
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
60 # todo: need to be in screen context or something
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
61 context_override = bpy.context.copy()
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
62 # context_override["selected_objects"] = list(context.scene.objects)
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
63 with bpy.context.temp_override(**context_override):
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
64 bpy.ops.action.view_all()
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
65
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
66 def setCurrentTime(self, t: float):
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
67 scene = bpy.context.scene
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
68 fps = scene.render.fps
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
69 fr = int(clamp(t, 0, self.duration) * fps)
2432
b8a408caf115 start blender sync
drewp@bigasterisk.com
parents:
diff changeset
70 self.lastSetFrame = fr
b8a408caf115 start blender sync
drewp@bigasterisk.com
parents:
diff changeset
71 scene.frame_set(fr)
b8a408caf115 start blender sync
drewp@bigasterisk.com
parents:
diff changeset
72
2455
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
73 def setBlenderTime(self, t: float, duration: float):
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
74 log.info(f'set blender time to {t:.2f}')
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
75 self.setSceneDuration(duration)
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
76 self.frameDuration()
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
77 self.setCurrentTime(t)
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
78
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
79 def emitEvent(self, event: _TimeEvent):
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
80 log.info(f'🌹 emitEvent {event}')
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
81 self._onEvent(event)
2432
b8a408caf115 start blender sync
drewp@bigasterisk.com
parents:
diff changeset
82
b8a408caf115 start blender sync
drewp@bigasterisk.com
parents:
diff changeset
83 @persistent
2455
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
84 def update(self):
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
85 if 0:
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
86 if self.playing:
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
87 with self.lock:
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
88 t = self.currentTime()
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
89 if t is not None:
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
90 self.blenderTime.setBlenderTime(t, self.duration)
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
91 return UPDATE_PERIOD
2432
b8a408caf115 start blender sync
drewp@bigasterisk.com
parents:
diff changeset
92
2455
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
93 @persistent
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
94 def _on_load_post(self, scene, deps):
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
95 self.emitEvent(SceneLoaded())
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
96
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
97 @persistent
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
98 def _on_frame_change_post(self, scene, deps):
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
99 # if scene.frame_current == self.lastSetFrame:
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
100 # return
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
101 # blender requested this frame change, either playing or paused (scrubbing timeline)
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
102 self.lastSetFrame = scene.frame_current
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
103 t = round(scene.frame_current / scene.render.fps, 3)
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
104 if bpy.context.screen.is_animation_playing and not bpy.context.screen.is_scrubbing:
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
105 self.emitEvent(PlayingGotoTime(t=t))
2454
405abed9a45c fix up asyncio-in-bg-thread sorcery
drewp@bigasterisk.com
parents: 2453
diff changeset
106 else:
2455
2d454737a916 split blender code to new file
drewp@bigasterisk.com
parents: 2454
diff changeset
107 self.emitEvent(PausedGotoTime(t=t))