mtg_counters/counters.py

126 lines
3.8 KiB
Python

from ocp_vscode import *
from build123d import *
from math import tan, pi, radians
def PG(x, y, angle):
return Polygon((x, 0), (x, y), (0, y + x * tan(radians(angle))), (0, x * tan(radians(angle))), align=Align.MIN)
def CounterVal(val):
if val > 0:
return f"+{val}"
elif val < 0:
return f"-{val}"
else:
return f"{val}"
def NumStr(val):
if val < 0:
return f"n{val}"
else:
return f"{val}"
def Chevron(x, y, angle):
return PG(x/2, y, angle) + mirror(PG(x/2, y, angle), Plane.YZ)
def Numerical(left, right, x, y, t, angle, base_z, text_z):
base = Chevron(x, y, angle)
counter = extrude(base, base_z + text_z, (0, 0, 1))
cutout = Pos(t/2, t + t*tan(radians(angle)), 0) * PG(x/2 - 1.5*t, y - 2*t, angle)
cutout += mirror(cutout, Plane.YZ)
cutout = Pos(0, 0, base_z + text_z) * cutout
counter -= extrude(cutout, text_z, (0, 0, -1))
font_size = x/5
font = "Arial Rounded MT Bold"
top = Pos(-x/4, y/2 + (t/2+x/4)*tan(radians(angle))) * Rot(0, 0, angle) * Text(CounterVal(left), font_size, font=font)
top += Pos(x/4, y/2 + (t/2+x/4)*tan(radians(angle))) * Rot(0, 0, -angle) * Text(CounterVal(right), font_size, font=font)
counter += extrude(Pos(0, 0, base_z) * top, text_z, (0, 0, 1))
return counter
def Textual(text, image, image_yoff, x, y, t, angle, base_z, text_z):
counter = extrude(Chevron(x, y, angle), base_z + text_z, (0, 0, 1))
counter -= extrude(Pos(0, t + t*tan(radians(angle)), base_z + text_z) * Chevron(x-2*t, y-2*t, angle), text_z, (0, 0, -1))
font = "Arial Rounded MT Bold"
font_size = x/8
top = Pos(0, x/2*tan(radians(angle)) + 2*t) * Text(text, font_size, font=font, align=(Align.CENTER, Align.MIN))
svg = import_svg(image, align=(Align.CENTER, Align.MIN))
svg_max_x = max([x.bounding_box().max.X for x in svg.faces()])
svg_max_y = max([x.bounding_box().max.Y for x in svg.faces()])
svg_min_x = min([x.bounding_box().min.X for x in svg.faces()])
svg_min_y = min([x.bounding_box().min.Y for x in svg.faces()])
svg_size = (svg_max_x - svg_min_x, svg_max_y - svg_min_y)
svg_scale = min(x/svg_size[0] * 0.6, y/svg_size[1] * 0.6)
svg_obj = [Pos(0, y + t + image_yoff*svg_scale - svg_size[1]*svg_scale) * face for face in svg.faces()]
top += scale(svg_obj, (svg_scale, svg_scale, svg_scale))
counter += extrude(Pos(0, 0, base_z) * top, text_z, (0, 0, 1))
return counter
x = 25 * MM
y = 10 * MM
t = 1 * MM
base_z = 1 * MM
text_z = 1 * MM
angle = 22.5
number_counters = [
(1, 1),
(5, 5),
(10, 10),
(-1, -1),
(-5, -5),
(1, 0),
(5, 0),
(10, 0),
(0, 1),
(0, 5),
(0, 10),
(1, -1),
]
image_counters = {
"Deathtouch": 2,
"Doublestrike": 0,
"First Strike": 0,
"Flying": 0,
"Goad": 0,
"Haste": -3,
"Hexproof": 0,
"Indestructible": 0,
"Lifelink": -2,
"Lore": 0,
"Menace": -2,
"Reach": -3,
"Ringbearer": 2,
"Shield": -2,
"Stun": -2,
"Time": 0,
"Trample": 0,
"Vigilance": -1.5,
"Charge": 0,
}
if True:
for numbers in number_counters:
counter = Numerical(numbers[0], numbers[1], x, y, t, angle, base_z, text_z)
export_step(counter, f"step/counter_{NumStr(numbers[0])}_{NumStr(numbers[1])}.step")
export_stl(counter, f"stl/counter_{NumStr(numbers[0])}_{NumStr(numbers[1])}.stl")
for text, y_off in image_counters.items():
counter = Textual(text, f"svg/{text.lower().replace(' ', '')}.svg", y_off, x, 2.5*y, t, angle, base_z, text_z)
export_step(counter, f"step/counter_{text.lower().replace(' ', '')}.step")
export_stl(counter, f"stl/counter_{text.lower().replace(' ', '')}.stl")
else:
text = "Charge"
counter = Textual(text, f"svg/{text.lower().replace(' ', '')}.svg", image_counters[text], x, 2.5*y, t, angle, base_z, text_z)
show(counter)