summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--blc2/constants.py1
-rw-r--r--blc2/functions/chaser.py31
-rw-r--r--blc2/functions/multichaser.py73
-rw-r--r--blc2/functions/multichasertrack.py10
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()