Cosplay/nhf/parts/item.py

68 lines
1.7 KiB
Python
Raw Permalink Normal View History

from typing import Union, Optional
from collections import Counter
from dataclasses import dataclass
import cadquery as Cq
from nhf.materials import Role, KEY_ROLE, KEY_ITEM
@dataclass(frozen=True)
class Item:
"""
A pre-fabricated item
"""
mass: float
#@property
#def mass(self) -> float:
# """
# Mass, in grams
# """
# return self._mass
#@mass.setter
#def mass(self, value):
# assert value >= 0, "Mass cannot be negative"
# self._mass = value
@property
def name(self) -> str:
pass
@property
def role(self) -> Optional[Role]:
return None
def generate(self, **kwargs) -> Union[Cq.Solid, Cq.Assembly, Cq.Workplane]:
"""
Creates an assembly for this item. Subclass should implement this
"""
return Cq.Assembly()
def assembly(self, **kwargs) -> Cq.Assembly:
"""
Interface for creating assembly with the necessary metadata
"""
a = self.generate(**kwargs)
if isinstance(a, Cq.Workplane) or isinstance(a, Cq.Solid):
a = Cq.Assembly(a)
if role := self.role:
a.metadata[KEY_ROLE] = role
a.color = role.color_avg()
assert isinstance(a, Cq.Assembly)
assert KEY_ITEM not in a.metadata
a.metadata[KEY_ITEM] = self
return a
@staticmethod
def count(a: Cq.Assembly) -> Counter:
"""
Counts the number of items
"""
occ = Counter()
for _, obj in a.traverse():
if KEY_ITEM not in obj.metadata:
continue
item = obj.metadata[KEY_ITEM]
assert isinstance(item, Item)
occ[item.name] += 1
return occ