1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
from .sexp import *
from .sexp_mapper import *
import time
from dataclasses import field
import math
import uuid
@sexp_type('color')
class Color:
r: int = None
g: int = None
b: int = None
a: int = None
@sexp_type('stroke')
class Stroke:
width: Named(float) = 0.254
type: Named(AtomChoice(Atom.dash, Atom.dot, Atom.dash_dot_dot, Atom.dash_dot, Atom.default, Atom.solid)) = Atom.default
color: Color = None
@property
def width_mil(self):
return mm_to_mil(self.width)
@width_mil.setter
def width_mil(self, value):
self.width = mil_to_mm(value)
@sexp_type('xy')
class XYCoord:
x: float = 0
y: float = 0
def isclose(self, other, tol=1e-6):
return math.isclose(self.x, other.x, tol) and math.isclose(self.y, other.y, tol)
@sexp_type('pts')
class PointList:
xy : List(XYCoord) = field(default_factory=list)
@sexp_type('xyz')
class XYZCoord:
x: float = 0
y: float = 0
z: float = 0
@sexp_type('at')
class AtPos(XYCoord):
x: float = 0 # in millimeter
y: float = 0 # in millimeter
rotation: int = 0 # in degrees, can only be 0, 90, 180 or 270.
unlocked: Flag() = False
def __before_sexp__(self):
self.rotation = int(round(self.rotation % 360))
@property
def rotation_rad(self):
return math.radians(self.rotation)
@rotation_rad.setter
def rotation_rad(self, value):
self.rotation = math.degrees(value)
@sexp_type('font')
class FontSpec:
face: Named(str) = None
size: Rename(XYCoord) = field(default_factory=lambda: XYCoord(1.27, 1.27))
thickness: Named(float) = None
bold: Flag() = False
italic: Flag() = False
line_spacing: Named(float) = None
@sexp_type('justify')
class Justify:
h: AtomChoice(Atom.left, Atom.right) = None
v: AtomChoice(Atom.top, Atom.bottom) = None
mirror: Flag() = False
@sexp_type('effects')
class TextEffect:
font: FontSpec = field(default_factory=FontSpec)
justify: OmitDefault(Justify) = field(default_factory=Justify)
hide: Flag() = False
@sexp_type('tstamp')
class Timestamp:
value: str = field(default_factory=uuid.uuid4)
def __after_parse__(self, parent):
self.value = str(self.value)
def before_sexp(self):
self.value = Atom(str(self.value))
def bump(self):
self.value = uuid.uuid4()
@sexp_type('tedit')
class EditTime:
value: str = field(default_factory=time.time)
def __after_parse__(self, parent):
self.value = int(str(self.value), 16)
def __before_sexp__(self):
self.value = Atom(f'{int(self.value):08X}')
def bump(self):
self.value = time.time()
|