def __init__(self) -> None:
self._dag: DAG[T | DAGLabel | None] = DAG()
self._group_appartenance: dict[T | SystemSet, set[SystemSet]] = {}
+ self._run_predicates: dict[T | SystemSet, Callable[[], bool]] = {}
def add_ordering(
self,
pre: Iterable[T | SystemSet],
post: Iterable[T | SystemSet],
group: Iterable[SystemSet],
+ cond: Callable[[], bool] | None,
) -> None:
def get_pre(e: T | SystemSet) -> T | DAGLabel:
if isinstance(e, SystemSet):
self._dag.add_edge(get_pre(e), get_pre(item))
self._dag.add_edge(get_post(item), get_post(e))
self._group_appartenance[item].add(e)
+ if cond is not None:
+ if (prev := self._run_predicates.get(item)) is not None:
+ self._run_predicates[item] = lambda: prev() and cond()
+ else:
+ self._run_predicates[item] = cond
- def traverse(
- self, run_cond: Callable[[T | SystemSet], bool]
- ) -> Generator[T]:
+ def traverse(self) -> Generator[T]:
cond_cache: dict[T | SystemSet, bool] = {}
def should_run(val: T | SystemSet) -> bool:
if val in cond_cache:
return cond_cache[val]
- res = all(
- should_run(parent)
- for parent in self._group_appartenance.get(val, set())
- ) and run_cond(val)
+ res = (
+ all(
+ should_run(parent)
+ for parent in self._group_appartenance.get(val, set())
+ )
+ and self._run_predicates.get(val, lambda: True)()
+ )
cond_cache[val] = res
return res
def add_raw_system[T](
self,
- system: Callable[..., T],
+ system: System[T],
default: Callable[[], T] = _system_failed,
) -> RawSystem[T]:
extractors = self._sys_extractors(system)
def tick(self, schedule: ScheduleLabel) -> None:
if schedule not in self._schedules:
return
- for system in self._schedules[schedule].traverse(lambda _: True):
+ for system in self._schedules[schedule].traverse():
system()
def run(
self,
schedule: ScheduleLabel,
*systems: "System | Systems",
- sets: set[SystemSet] | None = None,
- ) -> "World":
- if sets is None:
- sets = set()
+ ) -> Self:
if schedule not in self._schedules:
self._schedules[schedule] = Schedule()
- Systems(*systems).in_set(*sets)._apply(self, self._schedules[schedule])
+ Systems(*systems)._apply(self, self._schedules[schedule])
return self
def with_hook[T: Component](
cycle: Literal["insert", "remove"],
ty: type[T],
hook: ComponentHook[T],
- ) -> "World":
+ ) -> Self:
comp_id = self.component_id(resolve_type_aliases(ty))
hooks = cast(ComponentHooks[T], self._components_cache[comp_id][1])
sys = self.add_system(hook, default=lambda _: None)
hooks.add_remove(sys)
return self
- def with_plugins(self, *plugins: Plugin) -> "World":
+ def with_plugins(self, *plugins: Plugin) -> Self:
for plugin in plugins:
if isinstance(plugin, tuple):
self.with_plugins(plugin)
self._pre: list[System | SystemSet] = []
self._post: list[System | SystemSet] = []
self._in_set: list[SystemSet] = []
+ self._conds: list[System[bool]] = []
- def chain(self) -> "Systems":
+ def chain(self) -> Self:
self._chain = True
return self
- def after(self, *systems: System | SystemSet) -> "Systems":
+ def after(self, *systems: System | SystemSet) -> Self:
self._pre.extend(systems)
return self
- def before(self, *systems: System | SystemSet) -> "Systems":
+ def before(self, *systems: System | SystemSet) -> Self:
self._post.extend(systems)
return self
- def in_set(self, *sets: SystemSet) -> "Systems":
+ def in_set(self, *sets: SystemSet) -> Self:
self._in_set.extend(sets)
return self
+ def run_if(self, *conds: System[bool]) -> Self:
+ self._conds.extend(conds)
+ return self
+
def _apply(self, world: World, sched: Schedule[RawSystem]) -> SystemSet:
global _order_groups
_order_groups += 1
)
for e in self._systems
)
- sched.add_ordering((label,), self._pre, self._post, self._in_set)
+ for cond in self._conds:
+ sched.add_ordering(
+ (label,), (), (), (), world.add_raw_system(cond, lambda: False)
+ )
+ sched.add_ordering((label,), self._pre, self._post, self._in_set, None)
if self._chain:
prev: tuple[SystemSet | RawSystem] | tuple[()] = ()
for system in systems:
- sched.add_ordering((system,), prev, (), (label,))
+ sched.add_ordering((system,), prev, (), (label,), None)
prev = (system,)
else:
- sched.add_ordering(systems, (), (), (label,))
+ sched.add_ordering(systems, (), (), (label,), None)
return label