From a78a21732b5b843a1dccf710a953994bb3207f25 Mon Sep 17 00:00:00 2001 From: "Yi Yang @ Aquamarine" Date: Wed, 15 Nov 2023 18:29:29 +0800 Subject: [PATCH] Move stuff to a mixin --- agrf/split_action/__init__.py | 1 + agrf/split_action/meta_sprite_mixin.py | 91 ++++++++++++++++++++++++++ industry/lib/industry/__init__.py | 89 +------------------------ 3 files changed, 95 insertions(+), 86 deletions(-) create mode 100644 agrf/split_action/meta_sprite_mixin.py diff --git a/agrf/split_action/__init__.py b/agrf/split_action/__init__.py index 93e001bb..9adeb4f0 100644 --- a/agrf/split_action/__init__.py +++ b/agrf/split_action/__init__.py @@ -1 +1,2 @@ from .split_definition import SplitDefinition +from .meta_sprite_mixin import MetaSpriteMixin diff --git a/agrf/split_action/meta_sprite_mixin.py b/agrf/split_action/meta_sprite_mixin.py new file mode 100644 index 00000000..663f967e --- /dev/null +++ b/agrf/split_action/meta_sprite_mixin.py @@ -0,0 +1,91 @@ +import grf +from .split_definition import SplitDefinition + + +class MetaSpriteMixin: + # FIXME: handle make this an actual mixin + def __init__(self, feature, props_hash, parameter_list, priority_props=()): + self.feature = feature + self.props_hash = props_hash + self._parameter_list = parameter_list + self._priority_props = priority_props + + @property + def dynamic_prop_variables(self): + ret = set() + for p in self._props.values(): + if isinstance(p, SplitDefinition): + p.fixup(self._parameter_list) + for v in p.variables: + ret.add(v) + return list(sorted(ret)) + + def resolve_props(self, parameters): + new_props = {} + miss = False + for k, v in self._props.items(): + while isinstance(v, SplitDefinition): + v.fixup(self._parameter_list) + branch_key = tuple(parameters[var] for var in v.variables) + if branch_key in v.branches: + v = v.branches[branch_key] + else: + miss = True + break + new_props[k] = v + if new_props.get("exists", True): + assert not miss + new_props = {**{p: new_props[p] for p in self._priority_props if p in new_props}, **new_props} + else: + new_props = {"exists": False} + return new_props + + def dynamic_definitions(self, all_choices, parameters, i=0): + if i == len(all_choices): + resolved_props = self.resolve_props(parameters) + exists = resolved_props.pop("exists", True) + if exists: + return [ + [ + grf.Define( + feature=self.feature, + id=self.id, + props=resolved_props, + ) + ] + ], self.props_hash(resolved_props) + else: + return [], 0 + ret = [] + var_id = all_choices[i] + sublists = [] + hashes = [] + for choice in range(len(self._parameter_list.parameters[var_id].enum)): + parameters[var_id] = choice + sublist, h = self.dynamic_definitions(all_choices, parameters, i + 1) + sublists.append(sublist) + hashes.append(h) + del parameters[var_id] + + if all(hashes[0] == h for h in hashes): + return sublists[0], hash(tuple(hashes)) + + for choice in range(len(self._parameter_list.parameters[var_id].enum)): + sublist = sublists[choice] + for g in sublist: + ret.append( + [grf.If(is_static=True, variable=var_id, condition=0x03, value=choice, skip=len(g), varsize=4)] + g + ) + + compressed_ret = [] + cur_group = [] + for group in ret: + if len(cur_group) + len(group) + i <= 255: + cur_group.extend(group) + else: + compressed_ret.append(cur_group) + cur_group = group + if len(cur_group) > 0: + compressed_ret.append(cur_group) + + return compressed_ret, hash(tuple(hashes)) diff --git a/industry/lib/industry/__init__.py b/industry/lib/industry/__init__.py index 4cc75ecb..84202532 100644 --- a/industry/lib/industry/__init__.py +++ b/industry/lib/industry/__init__.py @@ -3,7 +3,7 @@ from .transcriber import transcribe from .symmetrizer import symmetrize from agrf.strings import get_translation -from agrf.split_action import SplitDefinition +from agrf.split_action import SplitDefinition, MetaSpriteMixin def props_hash(parameters): @@ -17,9 +17,9 @@ def props_hash(parameters): return hash(tuple(ret)) -class AIndustry(grf.SpriteGenerator): +class AIndustry(MetaSpriteMixin, grf.SpriteGenerator): def __init__(self, *, translation_name, id=None, callbacks={}, **props): - super().__init__() + super().__init__(grf.INDUSTRY, props_hash, parameter_list, ("substitute_type",)) if "override_type" in props: assert id is None id = props["override_type"] @@ -32,89 +32,6 @@ def __init__(self, *, translation_name, id=None, callbacks={}, **props): self._props = props self.callbacks = grf.make_callback_manager(grf.INDUSTRY, callbacks) - @property - def dynamic_prop_variables(self): - ret = set() - for p in self._props.values(): - if isinstance(p, SplitDefinition): - p.fixup(parameter_list) - for v in p.variables: - ret.add(v) - return list(sorted(ret)) - - def resolve_props(self, parameters): - new_props = {} - miss = False - for k, v in self._props.items(): - while isinstance(v, SplitDefinition): - v.fixup(parameter_list) - branch_key = tuple(parameters[var] for var in v.variables) - if branch_key in v.branches: - v = v.branches[branch_key] - else: - miss = True - break - new_props[k] = v - if new_props.get("exists", True): - assert not miss - - # XXX: substitute_type needs to be first - if "substitute_type" in new_props: - new_props = {"substitute_type": new_props["substitute_type"], **new_props} - else: - new_props = {"exists": False} - return new_props - - def dynamic_definitions(self, all_choices, parameters, i=0): - if i == len(all_choices): - resolved_props = self.resolve_props(parameters) - exists = resolved_props.pop("exists", True) - if exists: - return [ - [ - grf.Define( - feature=grf.INDUSTRY, - id=self.id, - props=resolved_props, - ) - ] - ], props_hash(resolved_props) - else: - return [], 0 - ret = [] - var_id = all_choices[i] - sublists = [] - hashes = [] - for choice in range(len(parameter_list.parameters[var_id].enum)): - parameters[var_id] = choice - sublist, h = self.dynamic_definitions(all_choices, parameters, i + 1) - sublists.append(sublist) - hashes.append(h) - del parameters[var_id] - - if all(hashes[0] == h for h in hashes): - return sublists[0], hash(tuple(hashes)) - - for choice in range(len(parameter_list.parameters[var_id].enum)): - sublist = sublists[choice] - for g in sublist: - ret.append( - [grf.If(is_static=True, variable=var_id, condition=0x03, value=choice, skip=len(g), varsize=4)] + g - ) - - compressed_ret = [] - cur_group = [] - for group in ret: - if len(cur_group) + len(group) + i <= 255: - cur_group.extend(group) - else: - compressed_ret.append(cur_group) - cur_group = group - if len(cur_group) > 0: - compressed_ret.append(cur_group) - - return compressed_ret, hash(tuple(hashes)) - def get_sprites(self, g): self._props["name"] = g.strings[f"STR_INDUSTRY_NAME_{self.translation_name}"].get_persistent_id() res, _ = self.dynamic_definitions(self.dynamic_prop_variables, {}, 0)