From 6201683c00a21ec3d1e2650ebf3429c5700f7e5b Mon Sep 17 00:00:00 2001 From: Leni Aniva Date: Wed, 3 Jul 2024 23:15:39 -0700 Subject: [PATCH] feat: Add build system --- .gitignore | 3 ++ nhf/build.py | 81 +++++++++++++++++++++++++++++++ nhf/touhou/houjuu_nue/__init__.py | 14 +++++- poetry.lock | 2 +- pyproject.toml | 1 + 5 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 nhf/build.py diff --git a/.gitignore b/.gitignore index 3226ba4..182aa47 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,6 @@ result # Python __pycache__ *.py[cod] + +# Model build output +/build diff --git a/nhf/build.py b/nhf/build.py new file mode 100644 index 0000000..5ac9bd2 --- /dev/null +++ b/nhf/build.py @@ -0,0 +1,81 @@ +""" +The NHF build system + +Usage: For any parametric assembly, inherit the `Model` class, and mark the +output objects with the `@target` decorator +""" +from pathlib import Path +from typing import Union +import cadquery as Cq +from colorama import Fore, Style + +class Target: + + def __init__(self, + method, + name: str): + self._method = method + self.name = name + def __call__(self, obj, *args, **kwargs): + return self._method(obj, *args, **kwargs) + + @classmethod + def methods(cls, subject): + """ + List of all methods of a class or objects annotated with this decorator. + """ + def g(): + for name in dir(subject): + method = getattr(subject, name) + if isinstance(method, Target): + yield name, method + return {name: method for name, method in g()} + + +def target(name, **kwargs): + """ + Decorator for annotating a build output + """ + def f(method): + return Target(method, name=name, **kwargs) + return f + +def _to_shape(x: Union[Cq.Workplane, Cq.Shape, Cq.Compound, Cq.Assembly]) -> Cq.Shape: + if isinstance(x, Cq.Workplane): + x = x.val() + if isinstance(x, Cq.Assembly): + x = x.toCompound() + return x + + +class Model: + """ + Base class for a parametric assembly + """ + + def target_names(self) -> list[str]: + """ + List of decorated target functions + """ + return list(Target.methods(self).keys()) + + def build_all(self, output_dir: Union[Path, str] ="build", verbose=1): + """ + Build all targets in this model + """ + output_dir = Path(output_dir) + output_dir.mkdir(exist_ok=True, parents=True) + for k, f in Target.methods(self).items(): + output_file = output_dir / f"{k}.stl" + if output_file.is_file(): + if verbose >= 1: + print(f"{Fore.GREEN}Skipping{Style.RESET_ALL} {output_file}") + continue + + model = f(self) + if verbose >= 1: + print(f"{Fore.BLUE}Building{Style.RESET_ALL} {output_file}", end="") + _to_shape(model).exportStl(str(output_file)) + if verbose >= 1: + print("\r", end="") + print(f"{Fore.GREEN}Built{Style.RESET_ALL} {output_file}") diff --git a/nhf/touhou/houjuu_nue/__init__.py b/nhf/touhou/houjuu_nue/__init__.py index 55f3614..3d00652 100644 --- a/nhf/touhou/houjuu_nue/__init__.py +++ b/nhf/touhou/houjuu_nue/__init__.py @@ -1,4 +1,9 @@ """ +To build, execute +``` +python3 nhf/touhou/houjuu_nue/__init__.py +``` + This cosplay consists of 3 components: ## Trident @@ -32,11 +37,12 @@ import nhf.handle from nhf import Material from nhf.joints import HirthJoint from nhf.handle import Handle +from nhf.build import Model, target import nhf.touhou.houjuu_nue.wing as MW import nhf.touhou.houjuu_nue.trident as MT @dataclass -class Parameters: +class Parameters(Model): """ Defines dimensions for the Houjuu Nue cosplay """ @@ -179,6 +185,7 @@ class Parameters: (-dx, dx), ] + @target(name="hs_joint_parent") def hs_joint_parent(self): """ Parent part of the Houjuu-Scarlett joint, which is composed of a Hirth @@ -322,3 +329,8 @@ class Parameters: def trident_assembly(self): return MT.trident_assembly(self.trident_handle) + + +if __name__ == '__main__': + p = Parameters() + p.build_all() diff --git a/poetry.lock b/poetry.lock index 69302dd..756343c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -857,4 +857,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "caf46b526858dbf2960b0204782140ad072d96f7b3f161ac7e9db0d9b709b25a" +content-hash = "ec47ccffd60fbda610a5c3725fc064a08b1b794f23084672bd62beb20b1b19f7" diff --git a/pyproject.toml b/pyproject.toml index 3431c0e..8ca0117 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,6 +10,7 @@ python = "^3.10" cadquery = "^2.4.0" build123d = "^0.5.0" numpy = "^1.26.4" +colorama = "^0.4.6" [build-system] requires = ["poetry-core"]