diff options
-rw-r--r-- | blc2/constants.py | 1 | ||||
-rw-r--r-- | blc2/functions/chaser.py | 31 | ||||
-rw-r--r-- | blc2/functions/multichaser.py | 73 | ||||
-rw-r--r-- | blc2/functions/multichasertrack.py | 10 |
4 files changed, 88 insertions, 27 deletions
diff --git a/blc2/constants.py b/blc2/constants.py index eae7c18..f4e7759 100644 --- a/blc2/constants.py +++ b/blc2/constants.py @@ -67,6 +67,7 @@ AUDIO = "Audio" CHASER = "Chaser" CHASERSTEP = "ChaserStep" MULTICHASERTRACK = "MultiChaserTrack" +MULTICHASER = "MultiChaser" FUNCTION = "Function" INTERNAL = "Internal" diff --git a/blc2/functions/chaser.py b/blc2/functions/chaser.py index 796ea34..a9e51a7 100644 --- a/blc2/functions/chaser.py +++ b/blc2/functions/chaser.py @@ -138,6 +138,7 @@ class Chaser(Function): step._index = len(self._steps) #pylint: disable=protected-access self._steps.insert(step.index, step) self.w.register_function_delete_callback(step, self._step_deleted, self) + self.w.register_function_change_callback(step, lambda a: self._recalculate, self) self._fix_indices() self._recalculate() @@ -169,6 +170,11 @@ class Chaser(Function): step.delete() + def delete(self): + for step in self._steps: + self.delete_step(step) + super().delete() + def advance(self, t, data, n=None): """Advance the chaser at the given time. @@ -283,29 +289,4 @@ class Chaser(Function): for step in e: ChaserStep.deserialize(w, step, chaser) - @classmethod - def deserialize(cls, w, e): - from .chaserstep import ChaserStep - - if e.tag != BXW+"function": - raise LoadError("Invalid function tag") - elif e.get("type") != cls.type: - raise LoadError("Load delegated to wrong class (this is a bug)") - - id_ = cls.int_or_none(e.get("id")) - if id_ is None: - raise LoadError("Function tag has invalid/missing ID") - - name = e.get("name") - advance_mode = e.get("advance-mode") - if advance - if advance_mode not in (LOOP, RANDOM, ONESHOT): - raise ValueError("Invalid advance mode") - - chaser = cls(w=w, id_=id_, name=name, advance_mode=advance_mode) - - for step in e: - ChaserStep.deserialize(w, step, chaser) - - return chaser return chaser diff --git a/blc2/functions/multichaser.py b/blc2/functions/multichaser.py new file mode 100644 index 0000000..558112e --- /dev/null +++ b/blc2/functions/multichaser.py @@ -0,0 +1,73 @@ +from ..constants import MULTICHASER, ONESHOT +from .function import Function + +class MultiChaser(Function): + type = MULTICHASER + + def __init__(self, w, id_ = None, name = None): + super().__init__(w=w, id_=id_, name=name) + self._tracks = [] + + self._duration = 0 + self._actual_duration = 0 + self._scope = frozenset() + self._audio_scope = frozenset() + self._advance_mode = ONESHOT + ## Order is of the format: + ## (track 1 step number, track 2 step number, ... ) + self._order = [] + + @property + def audio_scope(self): + return self._audio_scope + + @property + def scope(self): + return self._scope + + @property + def tracks(self): + """Return the multichaser's tracks.""" + return tuple(self._tracks) + + def _recalculate(self, update=True): + self._duration = max(0, *(i.duration for i in self._tracks)) + self._actual_duration = max(0, *(i.actual_duration for i in self._tracks)) + self._scope = frozenset().union(*(i.scope for i in self._tracks)) + self._audio_scope = frozenset().union(*(i.audio_scope for i in self._tracks)) + if update: + self.w.function_changed(self) + + @property + def duration(self): + return self._duration + + @property + def actual_duration(self): + return self._actual_duration + + def register_track(self, track): + """Register a new track. + + Should only be called in the MultiChaserTrack constructor. + """ + self._tracks.append(track) + self.w.register_function_delete_callback(track, self._track_deleted, self) + self.w.register_function_change_callback(track, self._track_changed, self) + self._order = [(*i, 0) for i in self._order] + self._recalculate() + + def _track_changed(self, _): + ## May need to fix up indexes + pass + + def _track_deleted(self, track): + i = self._tracks.index(track) + self._order = + self._tracks.remove(track) + self._recalculate() + + def delete(self): + for track in self._tracks: + track.delete() + super().delete() diff --git a/blc2/functions/multichasertrack.py b/blc2/functions/multichasertrack.py index 159e885..b21c0c0 100644 --- a/blc2/functions/multichasertrack.py +++ b/blc2/functions/multichasertrack.py @@ -4,7 +4,13 @@ from ..constants import MULTICHASERTRACK class MultiChaserTrack(Chaser): type = MULTICHASERTRACK - def __init__(self, w, id_ = None, name = None, advance_mode = ONESHOT): + def __init__(self, mc, id_ = None, name = None, advance_mode = ONESHOT): if advance_mode != ONESHOT: raise ValueError("MultiChaserTrack can only have advance_mode ONESHOT") - super().__init__(w=w, id_=id_, name=name, advance_mode=advance_mode) + self.mc = mc + super().__init__(w=mc.w, id_=id_, name=name, advance_mode=advance_mode) + self.mc.register_track(self) + + def delete(self): + self.mc.delete_track(self) + super().delete() |