pywargame 0.3.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pywargame/__init__.py +2 -0
- pywargame/common/__init__.py +3 -0
- pywargame/common/collector.py +87 -0
- pywargame/common/dicedraw.py +363 -0
- pywargame/common/drawdice.py +40 -0
- pywargame/common/singleton.py +22 -0
- pywargame/common/test.py +25 -0
- pywargame/common/verbose.py +59 -0
- pywargame/common/verboseguard.py +53 -0
- pywargame/cyberboard/__init__.py +18 -0
- pywargame/cyberboard/archive.py +283 -0
- pywargame/cyberboard/base.py +63 -0
- pywargame/cyberboard/board.py +462 -0
- pywargame/cyberboard/cell.py +200 -0
- pywargame/cyberboard/collect.py +49 -0
- pywargame/cyberboard/collectgbx0pwd.py +30 -0
- pywargame/cyberboard/collectgbxext.py +30 -0
- pywargame/cyberboard/collectgsnexp.py +32 -0
- pywargame/cyberboard/collectgsnext.py +30 -0
- pywargame/cyberboard/draw.py +396 -0
- pywargame/cyberboard/exporter.py +1132 -0
- pywargame/cyberboard/extractor.py +240 -0
- pywargame/cyberboard/features.py +17 -0
- pywargame/cyberboard/gamebox.py +81 -0
- pywargame/cyberboard/gbxexp.py +76 -0
- pywargame/cyberboard/gbxext.py +64 -0
- pywargame/cyberboard/gsnexp.py +147 -0
- pywargame/cyberboard/gsnext.py +59 -0
- pywargame/cyberboard/head.py +111 -0
- pywargame/cyberboard/image.py +76 -0
- pywargame/cyberboard/main.py +47 -0
- pywargame/cyberboard/mark.py +102 -0
- pywargame/cyberboard/palette.py +36 -0
- pywargame/cyberboard/piece.py +169 -0
- pywargame/cyberboard/player.py +36 -0
- pywargame/cyberboard/scenario.py +115 -0
- pywargame/cyberboard/testgrid.py +156 -0
- pywargame/cyberboard/tile.py +121 -0
- pywargame/cyberboard/tray.py +68 -0
- pywargame/cyberboard/windows.py +41 -0
- pywargame/cyberboard/zeropwd.py +45 -0
- pywargame/cyberboard.py +2728 -0
- pywargame/gbx0pwd.py +2776 -0
- pywargame/gbxextract.py +2795 -0
- pywargame/gsnexport.py +16499 -0
- pywargame/gsnextract.py +2790 -0
- pywargame/latex/__init__.py +2 -0
- pywargame/latex/collect.py +34 -0
- pywargame/latex/latexexporter.py +4010 -0
- pywargame/latex/main.py +184 -0
- pywargame/vassal/__init__.py +66 -0
- pywargame/vassal/base.py +139 -0
- pywargame/vassal/board.py +243 -0
- pywargame/vassal/buildfile.py +60 -0
- pywargame/vassal/chart.py +79 -0
- pywargame/vassal/chessclock.py +197 -0
- pywargame/vassal/collect.py +98 -0
- pywargame/vassal/collectpatch.py +28 -0
- pywargame/vassal/command.py +21 -0
- pywargame/vassal/documentation.py +322 -0
- pywargame/vassal/dumpcollect.py +28 -0
- pywargame/vassal/dumpvsav.py +28 -0
- pywargame/vassal/element.py +439 -0
- pywargame/vassal/exporter.py +89 -0
- pywargame/vassal/extension.py +101 -0
- pywargame/vassal/folder.py +103 -0
- pywargame/vassal/game.py +940 -0
- pywargame/vassal/gameelements.py +1091 -0
- pywargame/vassal/globalkey.py +127 -0
- pywargame/vassal/globalproperty.py +433 -0
- pywargame/vassal/grid.py +573 -0
- pywargame/vassal/map.py +1061 -0
- pywargame/vassal/mapelements.py +1020 -0
- pywargame/vassal/merge.py +57 -0
- pywargame/vassal/merger.py +460 -0
- pywargame/vassal/moduledata.py +275 -0
- pywargame/vassal/mrgcollect.py +31 -0
- pywargame/vassal/patch.py +44 -0
- pywargame/vassal/patchcollect.py +28 -0
- pywargame/vassal/player.py +83 -0
- pywargame/vassal/save.py +495 -0
- pywargame/vassal/skel.py +380 -0
- pywargame/vassal/trait.py +224 -0
- pywargame/vassal/traits/__init__.py +36 -0
- pywargame/vassal/traits/area.py +50 -0
- pywargame/vassal/traits/basic.py +35 -0
- pywargame/vassal/traits/calculatedproperty.py +22 -0
- pywargame/vassal/traits/cargo.py +29 -0
- pywargame/vassal/traits/click.py +41 -0
- pywargame/vassal/traits/clone.py +28 -0
- pywargame/vassal/traits/delete.py +24 -0
- pywargame/vassal/traits/deselect.py +32 -0
- pywargame/vassal/traits/dynamicproperty.py +112 -0
- pywargame/vassal/traits/globalcommand.py +55 -0
- pywargame/vassal/traits/globalhotkey.py +26 -0
- pywargame/vassal/traits/globalproperty.py +54 -0
- pywargame/vassal/traits/hide.py +67 -0
- pywargame/vassal/traits/label.py +76 -0
- pywargame/vassal/traits/layer.py +105 -0
- pywargame/vassal/traits/mark.py +20 -0
- pywargame/vassal/traits/mask.py +85 -0
- pywargame/vassal/traits/mat.py +26 -0
- pywargame/vassal/traits/moved.py +35 -0
- pywargame/vassal/traits/movefixed.py +51 -0
- pywargame/vassal/traits/nonrect.py +95 -0
- pywargame/vassal/traits/nostack.py +55 -0
- pywargame/vassal/traits/place.py +104 -0
- pywargame/vassal/traits/prototype.py +20 -0
- pywargame/vassal/traits/report.py +34 -0
- pywargame/vassal/traits/restrictaccess.py +28 -0
- pywargame/vassal/traits/restrictcommand.py +32 -0
- pywargame/vassal/traits/return.py +40 -0
- pywargame/vassal/traits/rotate.py +62 -0
- pywargame/vassal/traits/sendto.py +59 -0
- pywargame/vassal/traits/sheet.py +129 -0
- pywargame/vassal/traits/skel.py +9 -0
- pywargame/vassal/traits/stack.py +28 -0
- pywargame/vassal/traits/submenu.py +27 -0
- pywargame/vassal/traits/trail.py +61 -0
- pywargame/vassal/traits/trigger.py +72 -0
- pywargame/vassal/turn.py +272 -0
- pywargame/vassal/upgrade.py +191 -0
- pywargame/vassal/vmod.py +323 -0
- pywargame/vassal/vsav.py +100 -0
- pywargame/vassal/widget.py +358 -0
- pywargame/vassal/withtraits.py +634 -0
- pywargame/vassal/xml.py +4 -0
- pywargame/vassal/zone.py +399 -0
- pywargame/vassal.py +12500 -0
- pywargame/vmodpatch.py +12548 -0
- pywargame/vsavdump.py +12533 -0
- pywargame/vslmerge.py +13015 -0
- pywargame/wgexport.py +16689 -0
- pywargame/ztexport.py +14351 -0
- pywargame/zuntzu/__init__.py +5 -0
- pywargame/zuntzu/base.py +82 -0
- pywargame/zuntzu/collect.py +38 -0
- pywargame/zuntzu/countersheet.py +250 -0
- pywargame/zuntzu/dicehand.py +48 -0
- pywargame/zuntzu/exporter.py +936 -0
- pywargame/zuntzu/gamebox.py +154 -0
- pywargame/zuntzu/map.py +36 -0
- pywargame/zuntzu/piece.py +37 -0
- pywargame/zuntzu/scenario.py +208 -0
- pywargame/zuntzu/ztexp.py +115 -0
- pywargame-0.3.1.dist-info/METADATA +353 -0
- pywargame-0.3.1.dist-info/RECORD +150 -0
- pywargame-0.3.1.dist-info/WHEEL +5 -0
- pywargame-0.3.1.dist-info/licenses/LICENSE +5 -0
- pywargame-0.3.1.dist-info/top_level.txt +1 -0
pywargame/zuntzu/base.py
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
TARGET_DPI = 300
|
2
|
+
|
3
|
+
# --------------------------------------------------------------------
|
4
|
+
class DomInspect:
|
5
|
+
'''Utilities'''
|
6
|
+
@classmethod
|
7
|
+
def _get_attr(cls,node,name,default=None):
|
8
|
+
'''Get attribute from node, or default value'''
|
9
|
+
val = node.attributes.get(name,None)
|
10
|
+
if val is None:
|
11
|
+
return default
|
12
|
+
return val.nodeValue
|
13
|
+
|
14
|
+
@classmethod
|
15
|
+
def _find_children(cls,node,*tags):
|
16
|
+
'''Find all children of a node with specific tags'''
|
17
|
+
if len(tags) == 1:
|
18
|
+
return node.getElementsByTagName(tags[0])
|
19
|
+
return [child for child in node.childNodes
|
20
|
+
if child.nodeType != child.TEXT_NODE and
|
21
|
+
child.nodeType != child.COMMENT_NODE and
|
22
|
+
child.tagName in tags]
|
23
|
+
|
24
|
+
@classmethod
|
25
|
+
def _parse_hex(cls,txt):
|
26
|
+
'''Parse a hex number'''
|
27
|
+
if isinstance(txt,int):
|
28
|
+
return txt
|
29
|
+
|
30
|
+
if not (txt.startswith('0x') and txt.startswith('0X')) and \
|
31
|
+
any([c in txt for c in 'ABCFEFabcdef']):
|
32
|
+
txt = '0x'+txt
|
33
|
+
|
34
|
+
return int(txt,0)
|
35
|
+
|
36
|
+
@classmethod
|
37
|
+
def _parse_resolution(cls,txt):
|
38
|
+
'''Parse resolution specifier'''
|
39
|
+
if isinstance(txt,int):
|
40
|
+
return txt
|
41
|
+
|
42
|
+
return int(txt.lower().replace('dpi',''))
|
43
|
+
|
44
|
+
@classmethod
|
45
|
+
def _read_image(cls,zf,filename,resolution=None):
|
46
|
+
'''Read in an image from Zip file. Note the image is
|
47
|
+
explicitly converted to PNG
|
48
|
+
|
49
|
+
'''
|
50
|
+
if not filename:
|
51
|
+
return None
|
52
|
+
|
53
|
+
from wand.image import Image
|
54
|
+
|
55
|
+
with VerboseGuard(f'Reading in image from {filename}'):
|
56
|
+
with zf.open(filename,'r') as inp:
|
57
|
+
img = Image(file=inp,
|
58
|
+
#resolution=(resolution,resolution)
|
59
|
+
)
|
60
|
+
img.format = 'png'
|
61
|
+
return img
|
62
|
+
|
63
|
+
# --------------------------------------------------------------------
|
64
|
+
class ZTImage(DomInspect):
|
65
|
+
target_dpi = 300
|
66
|
+
|
67
|
+
def __init__(self,elem,prefix=''):
|
68
|
+
'''A stored image in the game box'''
|
69
|
+
self._image_file = self._get_attr(elem,prefix+'image-file')
|
70
|
+
self._reso = self._parse_resolution(
|
71
|
+
self._get_attr(elem,prefix+'resolution',150))
|
72
|
+
|
73
|
+
|
74
|
+
def read_image(self,zf):
|
75
|
+
self._image = self._read_image(zf,self._image_file,self._reso)
|
76
|
+
|
77
|
+
def __str__(self):
|
78
|
+
return f' Image: file={self._image_file}, resolution={self._reso}'
|
79
|
+
|
80
|
+
#
|
81
|
+
# EOF
|
82
|
+
#
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
import sys
|
3
|
+
sys.path.append('..')
|
4
|
+
|
5
|
+
from common import Verbose, VerboseGuard
|
6
|
+
from common.collector import Collector
|
7
|
+
|
8
|
+
if __name__ == '__main__':
|
9
|
+
from argparse import ArgumentParser, FileType
|
10
|
+
|
11
|
+
ap = ArgumentParser(description='Collect to single script')
|
12
|
+
ap.add_argument('output',
|
13
|
+
type=FileType('w'),
|
14
|
+
nargs='?',
|
15
|
+
default='ztexport.py',
|
16
|
+
help='Output script name')
|
17
|
+
ap.add_argument('-v','--verbose',action='store_true',
|
18
|
+
help='Be verbose')
|
19
|
+
|
20
|
+
args = ap.parse_args()
|
21
|
+
|
22
|
+
Verbose().setVerbose(args.verbose)
|
23
|
+
|
24
|
+
c = Collector(executable=True)
|
25
|
+
c.run(args.output,
|
26
|
+
'../vassal/vassal.py',
|
27
|
+
'base.py',
|
28
|
+
'dicehand.py',
|
29
|
+
'piece.py',
|
30
|
+
'map.py',
|
31
|
+
'scenario.py',
|
32
|
+
'countersheet.py',
|
33
|
+
'gamebox.py',
|
34
|
+
'exporter.py',
|
35
|
+
'ztexp.py')
|
36
|
+
|
37
|
+
|
38
|
+
|
@@ -0,0 +1,250 @@
|
|
1
|
+
## BEGIN_IMPORTS
|
2
|
+
from base import DomInspect, ZTImage
|
3
|
+
from piece import ZTPiece
|
4
|
+
from common import VerboseGuard
|
5
|
+
## END_IMPORTS
|
6
|
+
|
7
|
+
# --------------------------------------------------------------------
|
8
|
+
class ZTCounterImage(ZTImage):
|
9
|
+
def __init__(self,elem,prefix):
|
10
|
+
super().__init__(elem,prefix)
|
11
|
+
self._mask_file = self._get_attr(elem,prefix+'mask-file')
|
12
|
+
|
13
|
+
def read_image(self,zf):
|
14
|
+
from wand.image import Image
|
15
|
+
|
16
|
+
super().read_image(zf)
|
17
|
+
|
18
|
+
self._mask = self._read_image(zf,self._mask_file,self._reso)
|
19
|
+
if not self._mask:
|
20
|
+
return
|
21
|
+
|
22
|
+
|
23
|
+
# Get blue channel and make alpha mash from that
|
24
|
+
blue = self._mask.channel_images['blue']
|
25
|
+
blue.alpha_channel = 'copy'
|
26
|
+
|
27
|
+
# Make copy of input image, and turn on alpha channel for that
|
28
|
+
cp = Image(image=self._image)
|
29
|
+
cp.alpha_channel = 'set'
|
30
|
+
|
31
|
+
# Compose with alpha of blue mask
|
32
|
+
cp.composite(blue,operator='dst_in')
|
33
|
+
|
34
|
+
# Set new image (now with alpha channel)
|
35
|
+
self._orig = self._image
|
36
|
+
self._image = cp
|
37
|
+
self._blue = blue
|
38
|
+
|
39
|
+
# --------------------------------------------------------------------
|
40
|
+
class Face(DomInspect):
|
41
|
+
def __init__(self,elem,prefix=''):
|
42
|
+
with VerboseGuard(f'Got a face'):
|
43
|
+
self._left = int(self._get_attr(elem,prefix+'left', -1))
|
44
|
+
self._top = int(self._get_attr(elem,prefix+'top', -1))
|
45
|
+
self._right = int(self._get_attr(elem,prefix+'right', -1))
|
46
|
+
self._bottom = int(self._get_attr(elem,prefix+'bottom',-1))
|
47
|
+
|
48
|
+
@property
|
49
|
+
def width(self):
|
50
|
+
return self._right - self._left
|
51
|
+
|
52
|
+
@property
|
53
|
+
def height(self):
|
54
|
+
return self._bottom - self._top
|
55
|
+
|
56
|
+
def get_tiles(self,image,dx,dy,reverse):
|
57
|
+
with VerboseGuard(f'Get tiles from image {dx},{dy},{reverse}') as v:
|
58
|
+
# Check ordering - ZunTzu goes row-wise first
|
59
|
+
xl = self._left if not reverse else self._right-dx
|
60
|
+
xh = self._right if not reverse else self._left -dx
|
61
|
+
x1 = self._left
|
62
|
+
x2 = self._right
|
63
|
+
yl = self._top
|
64
|
+
yh = self._bottom
|
65
|
+
sx = dx if not reverse else -dx
|
66
|
+
|
67
|
+
def crop(image,x,y):
|
68
|
+
xx = max(x, x1)
|
69
|
+
xxx = min(x+dx,x2)
|
70
|
+
yy = max(y, yl)
|
71
|
+
yyy = min(y+dy,yh)
|
72
|
+
if xxx-xx < 0 or yyy-yy < 0:
|
73
|
+
return
|
74
|
+
return image[xx:xxx,yy:yyy],x+dx//2,y+dy//2
|
75
|
+
|
76
|
+
v(f'{x1} <= x+dx <= {x2} {yl} <= y+dy <= {yh}')
|
77
|
+
return [crop(image,x,y)
|
78
|
+
for y in range(yl, yh-dy//2, dy)
|
79
|
+
for x in range(xl, xh-sx//2, sx)
|
80
|
+
]
|
81
|
+
|
82
|
+
def __str__(self):
|
83
|
+
return f'Face: {self._left},{self._top},{self._right},{self._bottom}'
|
84
|
+
|
85
|
+
|
86
|
+
# --------------------------------------------------------------------
|
87
|
+
class Section(DomInspect):
|
88
|
+
def __init__(self,elem,terrain):
|
89
|
+
with VerboseGuard(f'Got an image section') as v:
|
90
|
+
self._terrain = terrain
|
91
|
+
self._card = elem.tagName == 'card-section'
|
92
|
+
self._type = self._get_attr(elem,'type',0)
|
93
|
+
self._rows = int(self._get_attr(elem,'rows',1))
|
94
|
+
self._cols = int(self._get_attr(elem,'columns',1))
|
95
|
+
self._shadow = float(self._get_attr(elem,'shadow',
|
96
|
+
0 if terrain else 20))
|
97
|
+
self._supply = int(self._get_attr(elem,'supply',1))
|
98
|
+
self._front = Face(elem,'face-' if self._card else 'front-')
|
99
|
+
self._back = Face(elem,'back-')
|
100
|
+
if self._terrain:
|
101
|
+
self._shadow = 0;
|
102
|
+
|
103
|
+
v(f'{"Terrain" if self._terrain else "Piece"} '
|
104
|
+
f'{"Card" if self._card else "Piece"} '
|
105
|
+
f'{self._type} {self._rows}x{self._cols} {self._supply}')
|
106
|
+
|
107
|
+
@property
|
108
|
+
def expected(self):
|
109
|
+
return self._rows * self._cols * self._supply
|
110
|
+
|
111
|
+
def get_tiles(self,image,face,reverse):
|
112
|
+
with VerboseGuard(f'Get tiles from face {face}') as v:
|
113
|
+
dx = int(face.width / self._cols+.5)
|
114
|
+
dy = int(face.height / self._rows+.5)
|
115
|
+
#v(f'Offsets are {dx},{dy}')
|
116
|
+
if dx <= 0 or dy <= 0:
|
117
|
+
return [(None,None,None)]*(self._cols*self._rows)
|
118
|
+
|
119
|
+
return face.get_tiles(image,dx,dy,reverse)
|
120
|
+
|
121
|
+
def make_pieces(self,
|
122
|
+
front_image,
|
123
|
+
back_image,
|
124
|
+
front_reso,
|
125
|
+
back_reso):
|
126
|
+
with VerboseGuard(f'Make pieces from images {self._supply}. '
|
127
|
+
f'Expecting {self.expected}') as v:
|
128
|
+
fronts = self.get_tiles(front_image, self._front, False)
|
129
|
+
backs = self.get_tiles(back_image, self._back, True)
|
130
|
+
|
131
|
+
fs = ZTImage.target_dpi / front_reso
|
132
|
+
bs = ZTImage.target_dpi / back_reso
|
133
|
+
#v(f'Scales are {fs} and {bs} '
|
134
|
+
# f'({ZTImage.target_dpi} {front_reso},{back_reso})')
|
135
|
+
|
136
|
+
def fixup(i,f,s):
|
137
|
+
if not i:
|
138
|
+
return
|
139
|
+
|
140
|
+
i.resize(int(f * i.width),int(f * i.height))
|
141
|
+
c = i.clone()
|
142
|
+
o = min(min(i.width,i.height) * s / 100 / 5,8)
|
143
|
+
c.shadow(50,o,0,0)
|
144
|
+
c.negate(channel='rgb')
|
145
|
+
c.composite(i,int(o/4),int(o/4))
|
146
|
+
return c
|
147
|
+
|
148
|
+
def make(f,b):
|
149
|
+
fi, fx, fy = f
|
150
|
+
bi, bx, by = b
|
151
|
+
#v(f' fx={fx} fy={fy} bx={bx} by={by}')
|
152
|
+
x = fs * fx if f else bs * bx
|
153
|
+
y = fs * fy if f else bs * by
|
154
|
+
fi = fixup(fi,fs,self._shadow)
|
155
|
+
bi = fixup(bi,bs,self._shadow)
|
156
|
+
#v(f' x={x} y={y} w={fi.width} h={fi.height}')
|
157
|
+
return [ZTPiece(fi,bi,int(x),int(y),self._terrain,self._card)
|
158
|
+
for _ in range(self._supply)]
|
159
|
+
|
160
|
+
return sum([make(f,b) for f,b in zip(fronts,backs)],[])
|
161
|
+
|
162
|
+
def __str__(self):
|
163
|
+
return (f' Section: {"terrain" if self._terrain else "piece"} '+
|
164
|
+
f'{"card" if self._card else "piece"} '+
|
165
|
+
f'{self._rows}x{self._cols} (x{self._supply}) '+
|
166
|
+
f'type={self._type} shadow={self._shadow}%'+'\n'
|
167
|
+
f' Front: '+str(self._front)+'\n'
|
168
|
+
f' Back: '+str(self._back))
|
169
|
+
|
170
|
+
# --------------------------------------------------------------------
|
171
|
+
class ZTCounterSheet(DomInspect):
|
172
|
+
def __init__(self,elem):
|
173
|
+
self._name = self._get_attr(elem,'name')
|
174
|
+
with VerboseGuard(f'Got a counter sheet "{self._name}"'):
|
175
|
+
self._terrain = elem.tagName == 'terrain-sheet'
|
176
|
+
self._name = self._get_attr(elem,'name')
|
177
|
+
self._front = ZTCounterImage(elem,'front-')
|
178
|
+
self._back = ZTCounterImage(elem,'back-')
|
179
|
+
|
180
|
+
self._sections = [self.parse_section(sc)
|
181
|
+
for sc in self._find_children(elem,
|
182
|
+
'counter-section',
|
183
|
+
'terrain-section')]
|
184
|
+
self._cards = [self.parse_card(cd)
|
185
|
+
for cd in self._find_children(elem,
|
186
|
+
'card-section')]
|
187
|
+
|
188
|
+
def parse_section(self,section):
|
189
|
+
return Section(section,self._terrain)
|
190
|
+
|
191
|
+
|
192
|
+
def parse_card(self,card):
|
193
|
+
return Section(card,self._terrain)
|
194
|
+
|
195
|
+
def read_image(self,zf):
|
196
|
+
self._front.read_image(zf)
|
197
|
+
self._back .read_image(zf)
|
198
|
+
|
199
|
+
def make_pieces(self):
|
200
|
+
with VerboseGuard(f'Making pieces from counter sheet {self._name}') \
|
201
|
+
as v:
|
202
|
+
self._piece = sum([s.make_pieces(self._front._image,
|
203
|
+
self._back._image,
|
204
|
+
self._front._reso,
|
205
|
+
self._back._reso)
|
206
|
+
for s in self._sections],[])
|
207
|
+
self._card = sum([c.make_pieces(self._front._image,
|
208
|
+
self._back._image,
|
209
|
+
self._front._reso,
|
210
|
+
self._back._reso)
|
211
|
+
for c in self._cards],[])
|
212
|
+
exp_piece = sum([s.expected for s in self._sections])
|
213
|
+
exp_card = sum([s.expected for s in self._cards])
|
214
|
+
v(f'{len(self._piece)} pieces and {len(self._card)} cards, '
|
215
|
+
f'expected {exp_piece} pieces and {exp_card} cards')
|
216
|
+
|
217
|
+
for img, res in zip([self._front._image,self._back._image],
|
218
|
+
[self._front._reso, self._back._reso]):
|
219
|
+
if not img:
|
220
|
+
continue
|
221
|
+
|
222
|
+
s = ZTImage.target_dpi / res
|
223
|
+
#v(f'scale image from {img.width}x{img.height} by {s}')
|
224
|
+
img.resize(int(s*img.width+.5),
|
225
|
+
int(s*img.height+.5))
|
226
|
+
|
227
|
+
@property
|
228
|
+
def filename(self):
|
229
|
+
return f'{self._name.replace(" ","_")}.{self._front._image.format.lower()}'
|
230
|
+
|
231
|
+
@property
|
232
|
+
def size(self):
|
233
|
+
return self._front._image.width,self._front._image.height
|
234
|
+
|
235
|
+
def __str__(self):
|
236
|
+
return (f' Sheet: {self._name} '+
|
237
|
+
f'{"terrain" if self._terrain else "pieces"} '+'\n'+
|
238
|
+
f' Front: '+str(self._front)+'\n'+
|
239
|
+
f' Back: '+str(self._back)+
|
240
|
+
('\n' if len(self._sections)>0 else '')+
|
241
|
+
'\n'.join([str(s) for s in self._sections])+
|
242
|
+
('\n' if len(self._cards)>0 else '')+
|
243
|
+
'\n'.join([str(s) for s in self._cards])+
|
244
|
+
('\n' if len(self._piece)>0 else '')+
|
245
|
+
'\n'.join([str(p) for p in self._piece])+
|
246
|
+
('\n' if len(self._card)>0 else '')+
|
247
|
+
'\n'.join([str(c) for c in self._card]))
|
248
|
+
#
|
249
|
+
# EOF
|
250
|
+
#
|
@@ -0,0 +1,48 @@
|
|
1
|
+
## BEGIN_IMPORTS
|
2
|
+
from base import DomInspect
|
3
|
+
from common import VerboseGuard
|
4
|
+
## END_IMPORTS
|
5
|
+
|
6
|
+
# --------------------------------------------------------------------
|
7
|
+
class ZTDiceHand(DomInspect):
|
8
|
+
|
9
|
+
def __init__(self,elem,type=6,count=1):
|
10
|
+
with VerboseGuard(f'Got a dice hand') as v:
|
11
|
+
if elem is None:
|
12
|
+
self._type = type
|
13
|
+
self._dice = [
|
14
|
+
{'color': 'black',
|
15
|
+
'pips': 'white',
|
16
|
+
'texture': ''}] * count
|
17
|
+
return
|
18
|
+
|
19
|
+
self._type = int(self._get_attr(elem,'type','D6')
|
20
|
+
.lower().replace('d',''))
|
21
|
+
self._dice = []
|
22
|
+
|
23
|
+
# v(f'{elem.getElementsByTagName("dice")} child dice')
|
24
|
+
for dice in elem.getElementsByTagName('dice'):
|
25
|
+
count = int(self._get_attr(dice,'count',1))
|
26
|
+
colour = self._parse_hex(self._get_attr(dice,'color',
|
27
|
+
0xFFFFFF))
|
28
|
+
pips = self._parse_hex(self._get_attr(dice,'pips',
|
29
|
+
0x000000))
|
30
|
+
texture = self._get_attr(dice,'texture-file')
|
31
|
+
|
32
|
+
#v(f'Adding another dice: "{colour}" "{pips}" "{count}"')
|
33
|
+
self._dice.extend([{
|
34
|
+
'color': colour,
|
35
|
+
'pips': pips,
|
36
|
+
'texture': texture}]*count)
|
37
|
+
|
38
|
+
# v(f'{len(self._dice)} dice of type d{self._type}')
|
39
|
+
|
40
|
+
|
41
|
+
def __str__(self):
|
42
|
+
return (f' Dice-hand: {self._type}'+
|
43
|
+
('\n' if len(self._dice) > 0 else '')+
|
44
|
+
'\n'.join([f' {d["color"]},{d["pips"]},{d["texture"]}'
|
45
|
+
for d in self._dice]))
|
46
|
+
#
|
47
|
+
# EOF
|
48
|
+
#
|