texlive[69692] Master/texmf-dist: wargame (3feb24)
commits+karl at tug.org
commits+karl at tug.org
Sat Feb 3 22:13:58 CET 2024
Revision: 69692
https://tug.org/svn/texlive?view=revision&revision=69692
Author: karl
Date: 2024-02-03 22:13:58 +0100 (Sat, 03 Feb 2024)
Log Message:
-----------
wargame (3feb24)
Modified Paths:
--------------
trunk/Master/texmf-dist/doc/latex/wargame/README.md
trunk/Master/texmf-dist/doc/latex/wargame/compat.pdf
trunk/Master/texmf-dist/doc/latex/wargame/symbols.pdf
trunk/Master/texmf-dist/doc/latex/wargame/tutorial/export.tex
trunk/Master/texmf-dist/doc/latex/wargame/tutorial/game.pdf
trunk/Master/texmf-dist/doc/latex/wargame/wargame.pdf
trunk/Master/texmf-dist/source/latex/wargame/Makefile
trunk/Master/texmf-dist/source/latex/wargame/chit/battle.dtx
trunk/Master/texmf-dist/source/latex/wargame/chit/misc.dtx
trunk/Master/texmf-dist/source/latex/wargame/chit/modifiers.dtx
trunk/Master/texmf-dist/source/latex/wargame/chit/oob.dtx
trunk/Master/texmf-dist/source/latex/wargame/chit/shape.dtx
trunk/Master/texmf-dist/source/latex/wargame/chit/table.dtx
trunk/Master/texmf-dist/source/latex/wargame/hex/labels.dtx
trunk/Master/texmf-dist/source/latex/wargame/hex/ridges.dtx
trunk/Master/texmf-dist/source/latex/wargame/hex/terrain.dtx
trunk/Master/texmf-dist/source/latex/wargame/tests/chits.dtx
trunk/Master/texmf-dist/source/latex/wargame/tests/test.tex
trunk/Master/texmf-dist/source/latex/wargame/util/export.dtx
trunk/Master/texmf-dist/source/latex/wargame/util/tikz.dtx
trunk/Master/texmf-dist/source/latex/wargame/utils/wgexport.py
trunk/Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.chit.code.tex
trunk/Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.hex.code.tex
trunk/Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.util.code.tex
trunk/Master/texmf-dist/tex/latex/wargame/wargame.beach.pdf
trunk/Master/texmf-dist/tex/latex/wargame/wargame.city.pdf
trunk/Master/texmf-dist/tex/latex/wargame/wargame.light_woods.pdf
trunk/Master/texmf-dist/tex/latex/wargame/wargame.mountains.pdf
trunk/Master/texmf-dist/tex/latex/wargame/wargame.rough.pdf
trunk/Master/texmf-dist/tex/latex/wargame/wargame.swamp.pdf
trunk/Master/texmf-dist/tex/latex/wargame/wargame.town.pdf
trunk/Master/texmf-dist/tex/latex/wargame/wargame.village.pdf
trunk/Master/texmf-dist/tex/latex/wargame/wargame.woods.pdf
trunk/Master/texmf-dist/tex/latex/wargame/wgexport.cls
trunk/Master/texmf-dist/tex/latex/wargame/wgexport.py
Modified: trunk/Master/texmf-dist/doc/latex/wargame/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/wargame/README.md 2024-02-03 21:13:44 UTC (rev 69691)
+++ trunk/Master/texmf-dist/doc/latex/wargame/README.md 2024-02-03 21:13:58 UTC (rev 69692)
@@ -1,6 +1,6 @@
# A package to make Hex'n'Counter wargames in LaTeX
-## Version 0.5
+## Version 0.6
This package can help make classic [Hex'n'Counter
wargames](https://en.wikipedia.org/wiki/Wargame) using LaTeX. The
Modified: trunk/Master/texmf-dist/doc/latex/wargame/compat.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/wargame/symbols.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/wargame/tutorial/export.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/wargame/tutorial/export.tex 2024-02-03 21:13:44 UTC (rev 69691)
+++ trunk/Master/texmf-dist/doc/latex/wargame/tutorial/export.tex 2024-02-03 21:13:58 UTC (rev 69692)
@@ -77,9 +77,9 @@
% counter.
%
% \begin{macrocode}
-\doublechitimages[A]{\alla}
-\doublechitimages[B]{\allb}
-\doublechitimages[Markers]{{game turn chit}}
+\doublechitimages[A][chit drop shadows]{\alla}
+\doublechitimages[B][chit drop shadows]{\allb}
+\doublechitimages[Markers][chit drop shadows]{{game turn chit}}
% \end{macrocode}
%
% Again, the macros we made for the counters comes in handy. Note
@@ -96,7 +96,9 @@
% can.}.
%
% \begin{macrocode}
-\battlemarkers{12}
+\tikzset{}
+\battlemarkers[marker drop shadows]{12}
+\tikzset{every battle marker/.style={}}
% \end{macrocode}
%
% Furthermore, we can add ``odds'' and battle result markers. Odds
@@ -108,7 +110,7 @@
% in the markers.
%
% \begin{macrocode}
-\oddsmarkers{%
+\oddsmarkers[marker drop shadows]{%
1:3/red!25!white,%
1:2/red!15!white,%
1:1/orange!15!white,%
@@ -115,7 +117,7 @@
2:1/white,%
3:1/green!15!white,%
4:1/green!25!white}
-\resultmarkers{
+\resultmarkers[marker drop shadows]{
AE/red!50!white,
AR/red!25!white,
EX/white,
Modified: trunk/Master/texmf-dist/doc/latex/wargame/tutorial/game.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/wargame/wargame.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/source/latex/wargame/Makefile
===================================================================
--- trunk/Master/texmf-dist/source/latex/wargame/Makefile 2024-02-03 21:13:44 UTC (rev 69691)
+++ trunk/Master/texmf-dist/source/latex/wargame/Makefile 2024-02-03 21:13:58 UTC (rev 69692)
@@ -2,7 +2,7 @@
#
#
NAME := wargame
-VERSION := 0.5
+VERSION := 0.6
LATEX_FLAGS := -interaction=nonstopmode \
-file-line-error \
--synctex=15 \
Modified: trunk/Master/texmf-dist/source/latex/wargame/chit/battle.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/wargame/chit/battle.dtx 2024-02-03 21:13:44 UTC (rev 69691)
+++ trunk/Master/texmf-dist/source/latex/wargame/chit/battle.dtx 2024-02-03 21:13:58 UTC (rev 69692)
@@ -41,7 +41,7 @@
minimum size=8mm,
draw=black,
fill=#2,
- every odds marker/.try] at (.2,-.2) {#1};
+ every odds marker/.try] at (.16,-.16) {#1};
}
},
odds marker/.style args={#1,#2}{
Modified: trunk/Master/texmf-dist/source/latex/wargame/chit/misc.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/wargame/chit/misc.dtx 2024-02-03 21:13:44 UTC (rev 69691)
+++ trunk/Master/texmf-dist/source/latex/wargame/chit/misc.dtx 2024-02-03 21:13:58 UTC (rev 69692)
@@ -4,7 +4,59 @@
% \fi
% \subsubsection{Some utilities}
%
+% This style allows us to add a fading drop-shadow to chits.
%
+% \begin{macrocode}
+\usetikzlibrary{shadows.blur}
+\newif\ifwg at chit@drop\wg at chit@dropfalse
+\tikzset{
+ chit has drop/.is if=wg at chit@drop,
+ chit has drop/.default=true,
+ chit has drop/.initial=false,
+ /tikz/render blur shadow/.add code={%
+ \chit at dbg{2}{Number of blur steps: \pgfbs at steps}%
+ \ifnum\pgfbs at steps=0\else
+ \chit at dbg{2}{Making shadow blur}%
+ }{\fi}}
+\tikzset{%
+ chit drop/.code={%
+ %% \message{^^J Args `#1'}%
+ \pgfkeysalso{%
+ chit has drop=true,
+ /tikz/blur shadow={shadow blur steps=5,
+ shadow opacity=25,
+ shadow xshift=.05cm,
+ shadow yshift=-.05cm,
+ shadow blur radius=.05cm,
+ #1}}%
+ \ifnum\pgfbs at steps=0%
+ \gdef\wg at drop@margin{0pt}%
+ \else%
+ \ifwg at chit@drop%
+ \pgfmathparse{
+ \pgfbs at radius+
+ veclen(
+ \pgfkeysvalueof{/tikz/shadow xshift},
+ \pgfkeysvalueof{/tikz/shadow yshift})}
+ \xdef\wg at drop@margin{\pgfmathresult pt}%
+ \else%
+ \gdef\wg at drop@margin{0pt}%
+ \fi
+ %% \message{^^J Drop margin is `\wg at drop@margin'
+ %% `\pgfbs at radius'
+ %% `\pgfkeysvalueof{/tikz/shadow xshift}',
+ %% `\pgfkeysvalueof{/tikz/shadow yshift}'}%
+ \fi%
+ },%
+ chit drop/.default=,%
+ no chit drop/.code={%
+ \pgfkeysalso{
+ /tikz/blur shadow={shadow blur steps=0}}
+ \gdef\wg at drop@margin{0pt}%
+ }
+}%
+% \end{macrocode}
+%
% Game turn marker
%
% \begin{macrocode}
Modified: trunk/Master/texmf-dist/source/latex/wargame/chit/modifiers.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/wargame/chit/modifiers.dtx 2024-02-03 21:13:44 UTC (rev 69691)
+++ trunk/Master/texmf-dist/source/latex/wargame/chit/modifiers.dtx 2024-02-03 21:13:58 UTC (rev 69692)
@@ -14,7 +14,7 @@
code={%
\path[fill=white,opacity=#1,pic actions] (-.6,-.6) rectangle(.6,.6);}},
pics/chit/eliminate/.style={
- code={%
+ code={%
\path[fill=red,opacity=#1,pic actions] (-.6,-.6) rectangle(.6,.6);}},
pics/chit/shade/.default=0.5,
pics/chit/eliminate/.default=0.25,
Modified: trunk/Master/texmf-dist/source/latex/wargame/chit/oob.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/wargame/chit/oob.dtx 2024-02-03 21:13:44 UTC (rev 69691)
+++ trunk/Master/texmf-dist/source/latex/wargame/chit/oob.dtx 2024-02-03 21:13:58 UTC (rev 69692)
@@ -37,8 +37,9 @@
\def\chit at oob@rowupdate(#1,#2)#3#4{%
\chit at dbg{2}{ Row update c=`#1',r=`#2',s=`#3',e=`#4'}
%\pgfmathparse{ifthenelse(#1>0,#2-#3,#2)}%
- \pgfmathparse{#2-#3)}%
+ \pgfmathparse{#2-#3-#4}%
\xdef#2{\pgfmathresult}%
+ \xdef#1{0}%\pgfmathresult}%
%\xdef#1{0}
\chit at dbg{2}{ \space\space-> update `\string#2'=#2}
}
@@ -71,6 +72,7 @@
% \begin{macrocode}
\newif\ifwg at oob@inv\wg at oob@invfalse
\def\chit at oob@spacer{hspace}
+\def\chit at oob@vspacer{vspace}
\def\wg at star@oob{\wg at oob@invtrue\wg at oob}
\def\wg at nostar@oob{\wg at oob@invfalse\wg at oob}
\def\oob{%
@@ -91,6 +93,8 @@
% \begin{macrocode}
\def\wg at oob#1#2#3#4{
\def\r{0}
+ \pgfmathparse{#3*(#2-1)}%
+ \edef\a{\pgfmathresult}
\chit at dbg{2}{OOB: `#1'}
\foreach[count=\ti from 0] \t/\y in #1{
\xdef\o{\r}
@@ -109,20 +113,28 @@
\ifx\m\@empty\def\m{1}\fi
\ifx\u\m\def\m{1}\fi
\foreach \n in {1,...,\m}{%
- \chit at dbg{2}{OOB Chit is `\u'}%
+ \chit at dbg{2}{OOB Chit is `\u' `\chit at oob@spacer'}%
\ifx\u\chit at oob@spacer%
\chit at dbg{3}{Chit `\u' is spacer `\chit at oob@spacer'}
\pgfmathparse{\c+#4}%
\xdef\c{\pgfmathresult}%
- \else
- \ifnum\chitdbglvl>2%
- \node[minimum width=#3cm,minimum height=#3cm,
- draw,transform shape] at (\c,\r) {};
+ \else%
+ \ifx\u\chit at oob@vspacer%
+ \chit at dbg{3}{Chit `\u' is vspacer `\chit at oob@vspacer'}
+ \pgfmathparse{ifthenelse(abs(\c)<0.0001,0,#3)}
+ \xdef\ll{\pgfmathresult}
+ \chit at dbg{2}{\string\ll=`\ll'}
+ \chit at oob@rowupdate(\c,\r){\ll}{#4}
+ \else
+ \ifnum\chitdbglvl>2%
+ \node[minimum width=#3cm,minimum height=#3cm,
+ draw,transform shape] at (\c,\r) {};
+ \fi
+ \ifx\u\chit at blank\else%
+ \chit[\u=\ti,zone oob point={\u}{\c}{\r}](\c,\r);%
+ \fi%
+ \chit at oob@cellupdate(\c,\r){#2}{#3}{\y}
\fi
- \ifx\u\chit at blank\else%
- \chit[\u=\ti,zone oob point={\u}{\c}{\r}](\c,\r);%
- \fi%
- \chit at oob@cellupdate(\c,\r){#2}{#3}{\y}
\fi
}
\fi
@@ -153,7 +165,7 @@
% \chit at dbg{2}{ \space Breaking loop \rr\space > \y}%
% \breakforeach%
%\else%
- \chit at oob@rowupdate(\c,\r){#3}{#4}
+ \chit at oob@rowupdate(\c,\r){#3}{0}% Extra spacing?
%\fi
}
\fi
@@ -166,6 +178,169 @@
\@ifnextchar;{\@gobble}{}}
% \end{macrocode}
%
+% Horizontal flow OOB
+%
+% \begin{macrocode}
+\def\wg at star@hoob{\wg at oob@invtrue\wg at hoob}
+\def\wg at nostar@hoob{\wg at oob@invfalse\wg at hoob}
+\def\hoob{%
+ \@ifstar{\wg at star@hoob%
+ }{\wg at nostar@hoob%
+ }%
+}
+% \end{macrocode}
+%
+% The inner macro of \cs{hoob}. The arguments are
+% \begin{enumerate}
+% \item The list of lists of chits styles
+% \item The maximum number of columns
+% \item The width of each cell
+% \item Additional row spacing between turns
+% \end{enumerate}
+%
+% \begin{macrocode}
+\def\wg at hoob#1#2#3#4{
+ \def\r{0}
+ \def\c{0}
+ \pgfmathparse{#3*(#2-1)}%
+ \edef\a{\pgfmathresult}
+ \chit at dbg{2}{OOB: `#1'}
+ \foreach[count=\ti from 0] \t/\y in #1{
+ \xdef\o{\r}
+ % \def\c{0}
+ \ifx\t\y\def\y{0}\fi
+ \chit at dbg{2}{Turn \ti\space(\r,\t,y=\y):'}
+ \ifx\t\empty\else
+ % Count how many are left for this turn
+ \chit at dbg{2}{At start of turn \t\space\string\c=\c}
+ \def\l{\c}%
+ \let\ig\empty
+ \foreach \u/\m in \t{
+ \ifx\ig\empty
+ \ifx\u\empty\else
+ \ifx\u\m\def\m{1}\fi
+ \ifx\u\chit at oob@spacer%
+ \pgfmathparse{\l+\m*#4}\xdef\l{\pgfmathresult}
+ \chit at dbg{2}{Got \m\space hspace (#4) -> \l}
+ \else
+ \ifx\u\chit at oob@vspace%
+ \xdef\ig{1}
+ \chit at dbg{2}{Got vspace -> \l (\ig)}
+ \else
+ \pgfmathparse{\l+\m*#3}
+ \xdef\l{\pgfmathresult}
+ \chit at dbg{2}{Got \m\space units -> \l}
+ \fi
+ \fi
+ \fi
+ \fi}
+ % Check if there's enough room
+ \chit at dbg{2}{To fill the rest of turn needs `\l' compared to
+ `\a' (#3*(#2-1))}
+ \pgfmathparse{ifthenelse(abs(\l)>=#3*(#2-1),0,1}%
+ \xdef\l{\pgfmathresult}%
+ \chit at dbg{2}{Break or not `\l'}
+ \ifnum\l=0\chit at oob@turnupdate(\c,\r){#3}{#4}\fi
+ \fi
+ \ifwg at oob@inv%
+ \pic[transform shape] at (\c+.5*#3,\r) {chit/oob turn=\ti};% was dx=0.5
+ \else
+ \pic[transform shape] at (\c+-.5*#3,\r) {chit/oob turn=\ti};% was dx=-0.5
+ \fi%
+ %\chit at oob@cellupdate(\c,\r){#2}{#3}{\y}
+ \ifx\t\empty\else%
+ \def\lv{0}
+ \foreach \u/\m in \t{
+ %% \chit at dbg{2}{ `\u'=`\m'}
+ \ifx\u\empty\else
+ \ifx\m\@empty\def\m{1}\fi
+ \ifx\u\m\def\m{1}\fi
+ \foreach \n in {1,...,\m}{%
+ \chit at dbg{2}{OOB Chit is `\u' `\chit at oob@spacer'}%
+ \ifx\u\chit at oob@spacer%
+ \chit at dbg{3}{Chit `\u' is spacer `\chit at oob@spacer'}
+ \pgfmathparse{\c+#4}%
+ \xdef\c{\pgfmathresult}%
+ \else%
+ \ifx\u\chit at oob@vspacer%
+ \chit at dbg{3}{Chit `\u' is vspacer `\chit at oob@vspacer'}
+ \pgfmathparse{ifthenelse(abs(\c)<0.0001,0,#3)}
+ \xdef\ll{\pgfmathresult}
+ \chit at dbg{2}{\string\ll=`\ll'}
+ \chit at oob@rowupdate(\c,\r){\ll}{#4}
+ \xdef\lv{1}
+ \else
+ \ifnum\chitdbglvl>2%
+ \node[minimum width=#3cm,minimum height=#3cm,
+ draw,transform shape] at (\c,\r) {};
+ \fi
+ \ifx\u\chit at blank\else%
+ \chit[\u=\ti,zone oob point={\u}{\c}{\r}](\c,\r);%
+ \fi%
+ \chit at oob@cellupdate(\c,\r){#2}{#3}{\y}
+ \fi
+ \fi
+ }
+ \fi
+ }
+ \fi
+ \chit at dbg{2}{ End of chits in turn
+ \ti\space(c=`\c',r=`\r',o='\o',y='\y')}
+ % --- Not relevant, I think
+ % IF no units where given, then we force \c to be non-zero so that
+ % \chit at oob@turnupdate increments the row
+ % \ifx\t\@empty
+ % \def\c{#3}
+ % \chit at dbg{2}{ Turn is empty, set c=`\c'}
+ % \fi
+ % ---
+ %\ifnum\y<0% No explicit number of rows given
+ % \def\c{#3}
+ % \chit at dbg{2}{ No explicit number of rows given, set c=`\c'}
+ %\fi
+ % In case the user gave and explicit number of rows, add the rows
+ % that are missing. \y is initially set to the number of
+ % requested rows, and then decremented every time we go down one
+ % row. So if the number of rows we did so far is N, and the
+ % requested number of rows is M, then the loop below adds M-N
+ % rows.
+ \ifnum\y>0%
+ \chit at dbg{2}{ Looping rows from 2 to \y, break when row > \y}%
+ \foreach \rr in {2,...,\y}{
+ %\ifnum\rr>\y% A little funny, but \y can be negative!
+ % \chit at dbg{2}{ \space Breaking loop \rr\space > \y}%
+ % \breakforeach%
+ %\else%
+ \chit at oob@rowupdate(\c,\r){#3}{0}% Extra spacing?
+ %\fi
+ }
+ \fi
+ % --- Not relevant I think
+ % This will zero \c. However, if on entry |\c|>0, then we also
+ % increment the row
+ % \chit at oob@turnupdate(\c,\r){#3}{#4}
+ % ---
+ % Horizontal spacer
+
+ %\pgfmathparse{ifthenelse(abs(\c)>=\a,1,0)}\xdef\l{\pgfmathresult}
+ \pgfmathparse{\c+1.5*#4}%
+ \xdef\c{\pgfmathresult}%
+ \ifnum\lv=1%
+ \pgfmathparse{\r-#4}
+ \chit at oob@rowupdate(\c,\r){0}{#4}
+ \else
+ \chit at oob@cellupdate(\c,\r){#2}{#3}{\y}
+ \ifnum\y<0
+ \chit at oob@turnupdate(\c,\r){#3}{#4}
+ \else
+ \fi
+ \fi
+ % \xdef\y{0}
+ \chit at dbg{2}{End of turn \ti\space(c=`\c',r=`\r',o='\o',y='\y')}
+ }
+ \chit at dbg{3}{End of OOB (c=`\c',r=`\r',y=`\y')}
+ \@ifnextchar;{\@gobble}{}}
+% \end{macrocode}
% \iffalse
% </chit>
% --------------------------------------------------------------------
Modified: trunk/Master/texmf-dist/source/latex/wargame/chit/shape.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/wargame/chit/shape.dtx 2024-02-03 21:13:44 UTC (rev 69691)
+++ trunk/Master/texmf-dist/source/latex/wargame/chit/shape.dtx 2024-02-03 21:13:58 UTC (rev 69692)
@@ -92,7 +92,7 @@
chit/symbol/.style={scale=.4,transform shape},
chit/parts/.style={shape=rectangle,transform shape},
chit/factors/.style={chit/parts,anchor=south},
- chit/left/.style={chit/parts,anchor=south,rotate=90},
+ chit/left/.style={chit/parts,anchor=base,rotate=90},%Anchor was south
chit/right/.style={chit/parts,anchor=north,rotate=90},
chit/upper left/.style={chit/parts,anchor=north west},
chit/upper right/.style={chit/parts,anchor=north east},
@@ -141,7 +141,8 @@
% \begin{macrocode}
\tikzset{%
chit/.code={%
- \pgfkeys{/tikz/transform shape,/tikz/shape=chit}
+ \chit at dbg{2}{chit arguments are `#1'}%
+ \pgfkeys{/tikz/transform shape,/tikz/shape=chit}%
\pgfkeys{/chit/.cd,#1}}}
% \end{macrocode}
% \end{TikzKey}
@@ -657,8 +658,12 @@
%
% The work horse. This simply makes a \cs{node} with the shape
% \texttt{chit}. Note, we allow for a trailing semi-colon
-% (\texttt{;}) to have a similar feel to other \TikZ{} macros.
+% (\texttt{;}) to have a similar feel to other \TikZ{} macros.
%
+% The macro will execute the style \texttt{/tikz/every chit} if
+% defined. Note that this will be executed \emph{before} the usual
+% \texttt{every chip node} style.
+%
% \begin{macrocode}
\def\chit@@@#1#2(#3){%
\chit at dbg{5}{Chit final:
@@ -667,7 +672,7 @@
^^J Name: `#3'}
\let\name\pgfutil at empty%
\chit at dbg{1}{=== Before chit node}%
- \node[chit={every chit/.try,id=#3,#1}] (tmp) at (#2) {};
+ \node[chit={/tikz/every chit/.try,id=#3,#1}] (tmp) at (#2) {};
\chit at dbg{2}{=== After chit node}%
\ifx|#3|\relax%
\else%
Modified: trunk/Master/texmf-dist/source/latex/wargame/chit/table.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/wargame/chit/table.dtx 2024-02-03 21:13:44 UTC (rev 69691)
+++ trunk/Master/texmf-dist/source/latex/wargame/chit/table.dtx 2024-02-03 21:13:58 UTC (rev 69692)
@@ -7,7 +7,9 @@
% \begin{macrocode}
\tikzset{
chit/cell background/.style={fill=black},
+ %chit/cell background flipped/.style={fill=black},
blank chit/.style={/chit/frame={draw=none,fill=none}},
+ chit/grid lines/.style={dashed},
}
% \end{macrocode}
%
@@ -20,6 +22,10 @@
\def\chit at cellbg(#1,#2)#3{%
\draw[chit/cell background](#1-#3/2,#2-#3/2) rectangle++(#3,#3);
}
+\def\chit at celldblbg(#1,#2)#3{%
+ \draw[chit/cell background,chit/cell background flipped/.try]%
+ (#1-#3/2,#2-#3/2) rectangle++(#3,#3);
+}
% \end{macrocode}
%
% \begin{Macro}{\ifchits at reset}
@@ -83,7 +89,28 @@
\@ifnextchar;{\@gobble}{}}
% \end{macrocode}
% \end{Macro}
+% \begin{Macro}{\chitgrid}
+% \begin{enumerate}
+% \item columns
+% \item rows
+% \item cell-size
+% \end{enumerate}
%
+% \begin{macrocode}
+\def\chitgrid#1#2#3{%
+ \pgfmathparse{#3/2}\edef\rmin{\pgfmathresult}%
+ \pgfmathparse{#2*#3-#3/2}\edef\rmax{\pgfmathresult}%
+ %\draw[red](-#3/2,\rmin)rectangle(#3*#1-#3/2,-\rmax);
+ \foreach \cc in {0,...,#1}{
+ \draw[chit/grid lines] (\cc*#3-#3/2,3*#3/4)--(\cc*#3-#3/2,-\rmax-#3/4);}
+ %\chit at dbg{0}{Drawing horizontal lines from `\rmin, `-\rmin', ..., `-\rmax'}
+ \foreach \rr in {\rmin,-\rmin,...,-\rmax}{
+ %\chit at dbg{0}{Horizontal line at `\rr'}
+ \draw[chit/grid lines] (-3*#3/4,\rr)--(#1*#3-#3/4,\rr);}
+}
+% \end{macrocode}
+% \end{Macro}
+%
% \begin{Macro}{\doublechits,
% \@doublechits,
% \chit at dbl@cellupdate,
@@ -154,7 +181,7 @@
\chit at cellbg(\c,\r){#3}
\chit[\u=\ti](\c,\r)
\chit at dbl@flip(\c,\r){#3}
- \chit at cellbg(\mc,\r){#3}
+ \chit at celldblbg(\mc,\r){#3}
\chit[\u\space flipped=\ti,zone turn=\t,zone mult=\n](\mc,\r)
\chit at dbl@cellupdate(\c,\r){#2}{#3}
\fi
@@ -166,10 +193,39 @@
\draw[dashed](0,-3*#3/4)--(0,\r-#3/4);%
\draw[dashed,<-] (#3/5,-2*#3/3)--(#3/2,-2*#3/3) node[transform shape,anchor=west]{Back};%
\draw[dashed,<-] (-#3/5,-2*#3/3)--(-#3/2,-2*#3/3) node[transform shape,anchor=east]{Front};%
+ % \foreach \cc in {0,...,#2}{
+ % \draw[dashed] (\cc*#3,-3*#3/4)--(\cc*#3,\r-#3/4);
+ % \draw[dashed] (-\cc*#3,-3*#3/4)--(-\cc*#3,\r-#3/4);}
+ % \pgfmathparse{#3/2}\edef\rmin{\pgfmathresult}%
+ % \chit at dbg{0}{Drawing horizontal lines from `-\rmin, `\rmin', ..., `\r'}
+ % \foreach \rr in {-\rmin,\rmin,...,\r}{
+ % \chit at dbg{0}{Horizontal line at `\rr'}
+ % \draw[dashed] (-#2*#3-#3/4,\rr)--(#2*#3+#3/4,\rr);}
\@ifnextchar;{\@gobble}{}}
% \end{macrocode}
% \end{Macro}
%
+% \begin{Macro}{\doublechitgrid}
+% \begin{enumerate}
+% \item columns
+% \item rows
+% \item cell-size
+% \end{enumerate}
+%
+% \begin{macrocode}
+\def\doublechitgrid#1#2#3{%
+ \pgfmathparse{#3/2}\edef\rmin{\pgfmathresult}%
+ \pgfmathparse{#2*#3-#3/2}\edef\rmax{\pgfmathresult}%
+ \foreach \cc in {0,...,#1}{
+ \draw[chit/grid lines] (\cc*#3,-3*#3/4)--(\cc*#3,\rmax+#3/4);
+ \draw[chit/grid lines] (-\cc*#3,-3*#3/4)--(-\cc*#3,\rmax+#3/4);}
+ %\chit at dbg{0}{Drawing horizontal lines from `-\rmin, `\rmin', ..., `\rmax'}
+ \foreach \rr in {-\rmin,\rmin,...,\rmax}{
+ %\chit at dbg{0}{Horizontal line at `\rr'}
+ \draw[chit/grid lines] (-#1*#3-#3/4,\rr)--(#1*#3+#3/4,\rr);}
+}
+% \end{macrocode}
+% \end{Macro}
% \iffalse
% </chit>
% --------------------------------------------------------------------
Modified: trunk/Master/texmf-dist/source/latex/wargame/hex/labels.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/wargame/hex/labels.dtx 2024-02-03 21:13:44 UTC (rev 69691)
+++ trunk/Master/texmf-dist/source/latex/wargame/hex/labels.dtx 2024-02-03 21:13:58 UTC (rev 69692)
@@ -132,7 +132,7 @@
%
% \begin{macrocode}
\def\hex at do@label{%
- \hex at dbg{1}{Hex label: `\meaning\hex at label'}%
+ \hex at dbg{3}{Hex label: `\meaning\hex at label'}%
\edef\hex at l@tmp{[%
/hex/label/.cd,%
rotate=0,%
Modified: trunk/Master/texmf-dist/source/latex/wargame/hex/ridges.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/wargame/hex/ridges.dtx 2024-02-03 21:13:44 UTC (rev 69691)
+++ trunk/Master/texmf-dist/source/latex/wargame/hex/ridges.dtx 2024-02-03 21:13:58 UTC (rev 69692)
@@ -157,11 +157,12 @@
\xdef\hex at r@p{\hex at r@p ($(300:\hex at r@r)+(-120:\hex at r@t/2)$)}
\fi
\ifhex at r@ne
- \xdef\hex at r@p{\hex at r@p --cycle}
+ %\xdef\hex at r@p{\hex at r@p --cycle}
+ \xdef\hex at r@p{\hex at r@p -- (0:\hex at r@r)}
\else
\xdef\hex at r@p{\hex at r@p --(.5:\hex at r@r)}
\fi
- \hex at dbg{4}{Ridge along se: `\hex at r@p'}
+ \hex at dbg{4}{Ridge along south east: `\hex at r@p'}
\fi
\hex at dbg{3}{ Ridges path: \hex at r@p}
% \draw[red] \hex at r@p;
Modified: trunk/Master/texmf-dist/source/latex/wargame/hex/terrain.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/wargame/hex/terrain.dtx 2024-02-03 21:13:44 UTC (rev 69691)
+++ trunk/Master/texmf-dist/source/latex/wargame/hex/terrain.dtx 2024-02-03 21:13:58 UTC (rev 69692)
@@ -37,6 +37,7 @@
% select the common terrains.
%
% \begin{macrocode}
+\newif\if at hex@t at rot\@hex at t@rotfalse%
\tikzset{%
/hex/terrain/.search also={/tikz},%
/hex/terrain/.cd,%
@@ -44,6 +45,7 @@
image/.store in=\hex at t@image,%
code/.store in=\hex at t@code,%
clip/.store in=\hex at t@clip,%
+ random rotation/.is if=@hex at t@rot,
pic/.default=,
image/.default=,
code/.default=,
@@ -137,9 +139,24 @@
\@ifundefined{hex at t@code}{\let\hex at t@code\empty}{}
% \end{macrocode}
%
+% Possible make rotation. We define a scope and rotate within that.
+%
% \begin{macrocode}
- \ifx\hex at t@code\empty\else\hex at t@code\fi%
+ \def\hex at t@angle{0}%
+ \if at hex@t at rot%
+ \pgfmathrandominteger{\hex at t@angle}{0}{5}
+ \pgfmathparse{int(60*\hex at t@angle)}\edef\hex at t@angle{\pgfmathresult}%
+ \fi%
+ \hex at dbg{5}{Will rotate terrain by `\hex at t@angle'}%
% \end{macrocode}
+%
+% If we have specified code for the terrain, then execute that.
+%
+% \begin{macrocode}
+ \scope[rotate=\hex at t@angle]%
+ \ifx\hex at t@code\empty\else\hex at t@code\fi%
+ \endscope% End rotate code
+% \end{macrocode}
% First we check if we have not got terrain images, but terrain
% pictures. If we have that, we process these in turn. Note, the
% user can give options to each terrain picture by preceding the
@@ -154,7 +171,9 @@
\hex at dbg{5}{Terrain pictures}%
\pgfpointorigin\wg at tmpa=\pgf at x\wg at tmpb=\pgf at y%
\foreach \i in \hex at t@pic{%
- \wg at pic@all{\i}{}{\the\wg at tmpa,\the\wg at tmpb}{}}%
+ \wg at pic@all{\i}{}{\the\wg at tmpa,\the\wg at tmpb}{%
+ rotate=\hex at t@angle,
+ transform shape}}%
\fi% We have pictures.
% \end{macrocode}
%
@@ -172,6 +191,7 @@
\expandafter\wg at node{%
\includegraphics[width=2cm]{\i}}\@endwg at node %
{}{\wg at tmpa,\wg at tmpb}{%
+ rotate=\hex at t@angle,%
shape=rectangle,%
anchor=center,%
transform shape,%
Modified: trunk/Master/texmf-dist/source/latex/wargame/tests/chits.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/wargame/tests/chits.dtx 2024-02-03 21:13:44 UTC (rev 69691)
+++ trunk/Master/texmf-dist/source/latex/wargame/tests/chits.dtx 2024-02-03 21:13:58 UTC (rev 69692)
@@ -6,7 +6,11 @@
% Some chits for testing stuff
%
% \begin{macrocode}
-\def\firstchit{
+\makeatletter
+\def\firstchit{%
+ \@ifnextchar[{\@firstchit}{\@firstchit[]}%]
+}%
+\def\@firstchit[#1]{
% \chitdbglvl=5
% \natoappdbglvl=5
\chit[symbol={
@@ -17,13 +21,14 @@
left={text=A},
frame={fill=yellow!50!black},
ultra thick,
- command=land},
+ command=land,
+ },
left={chit/identifier={1}},
right={chit/identifier={2}},
factors={chit/2 factors={4,8}},
frame={draw=black},
- color=white,text=yellow,fill={blue}]}
-\makeatletter
+ color=white,text=yellow,fill={blue},
+ #1]}
\def\secondchit{%
\@ifnextchar({\second at chit}{\second at chit(0,0)}%)
}
@@ -34,6 +39,7 @@
command=air](0,-.15)},
left={[{red,font=\noexpand\sffamily}]chit/identifier={Fighter}},
right={chit/identifier={USAF}},
+ fill=white,
factors={chit/1 factor=3}}] at (#1){};}
\def\thirdchit{
\chit[symbol={[echelon=battalion,
Modified: trunk/Master/texmf-dist/source/latex/wargame/tests/test.tex
===================================================================
--- trunk/Master/texmf-dist/source/latex/wargame/tests/test.tex 2024-02-03 21:13:44 UTC (rev 69691)
+++ trunk/Master/texmf-dist/source/latex/wargame/tests/test.tex 2024-02-03 21:13:58 UTC (rev 69692)
@@ -2,6 +2,7 @@
\usepackage{wargame}
\usetikzlibrary{decorations.markings}
+\usetikzlibrary{shadows.blur}
\title{A test of \textsf{wargame}}
\author{}
\date{}
@@ -28,7 +29,7 @@
\section{Some chits}
-\begin{tikzpicture}
+\begin{tikzpicture}[every chit node/.style={blur shadow={shadow blur steps=5}}]
\fill[red!50] (1,-1) rectangle (3,1);
\firstchit(0,0)%
%\secondchit(2,0)%
@@ -45,18 +46,20 @@
\end{tikzpicture}
\section{Chits on a board}
-\begin{tikzpicture}
+\begin{tikzpicture}[every chit/.style={chit drop}]
+ \chitdbglvl=5
\begin{scope}[every hex/.style={/hex/label=auto},transform shape]
\boardframe[0.5](c=0,r=0)(c=3,r=3)
\boardclip(c=0,r=0)(c=3,r=3){fill=white}
\testmap{}
- \firstchit(hex cs:c=2,r=1)
- \secondchit(hex cs:c=3,r=0)
+ \firstchit[no chit drop](hex cs:c=2,r=2)
+ %\secondchit(hex cs:c=3,r=0)
\thirdchit(hex cs:c=0,r=3)
\stackchits(hex cs:c=0,r=1)(.3,.3){
\noexpand\firstchit,
- \noexpand\secondchit/\noexpand\chit[{full=chit/eliminate}]}
+ \noexpand\secondchit%/\noexpand\eliminatechit
+ }
\begin{scope}[m/.style={hex/long move=green}]
\path[m] (hex cs:c=3,r=0) -- (hex cs:c=3,r=1)--(hex cs:c=3,r=2);
Modified: trunk/Master/texmf-dist/source/latex/wargame/util/export.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/wargame/util/export.dtx 2024-02-03 21:13:44 UTC (rev 69691)
+++ trunk/Master/texmf-dist/source/latex/wargame/util/export.dtx 2024-02-03 21:13:58 UTC (rev 69692)
@@ -72,6 +72,7 @@
%
% Preceed all images (\textsf{tikzpicture}) with this command
%
+%
% First argument is the name of the image. This can be anything.
% Note that for counters, if the name ends in \texttt{flipped} then it
% is considered the backside of a counter.
@@ -140,13 +141,32 @@
%
% Make separate images for each counter (single sided).
%
+% First optional argument is the group to put the chits into.
+% Second optional argument is options to give to each Tikz picture
+% environment. Third, mandatory, argument is the list of chit
+% identifiers to render.
+%
% \begin{macrocode}
-\newcommand\chitimages[2][]{%
+\def\wg at add@drop at margin{%
+ \@ifundefined{wg at drop@margin}{}{
+ \dimen0=\wg at drop@margin
+ % \ifwg at chit@drop
+ \ifdim\dimen0>0pt%
+ \path ($(current bounding box.north east)+(45:\wg at drop@margin)$)
+ -- ($(current bounding box.south west)+(225:\wg at drop@margin)$);
+ \fi}}
+\def\chitimages{%
+ \@ifnextchar[{\@chitimages}{\chitimages[]}%]
+}%
+\def\@chitimages[#1]{%
+ \@ifnextchar[{\@@chitimages[#1]}{\@@chitimages[#1][]}%]
+}%
+\def\@@chitimages[#1][#2]#3{%
\begingroup%
\let\chit at report\do at chit@report%
\let\natoapp at report\do at natoapp@report%
- \chit at dbg{2}{chits to make images of `#2'}%
- \foreach[count=\ti from 0] \t/\x in #2{%
+ \chit at dbg{2}{chits to make images of `#3'}%
+ \foreach[count=\ti from 0] \t/\x in #3{%
\chit at dbg{2}{^^JRow: `\t' (`\x')}
\ifx\t\empty\else% Ignore empty rows
\chit at dbg{5}{^^JSubcategory: `\x' (default `#1')}
@@ -156,14 +176,17 @@
\ifx\u\empty\else% Ignore empty cells
\ifx\u\chit at blank\else%
\chit at dbg{2}{Next chit `\u' with possible multiplicity `\m'}%
- \ifx\m\@empty\def\m{1}\fi% If not multiplicity defined
+ \ifx\m\@empty\def\m{1}\fi% If no multiplicity defined
\ifx\u\m\def\m{1}\fi% If the same as unit
\chit at dbg{2}{Next chit `\u' multiplicity `\m'}%
%% We only make one copy of the chit, since we can duplicate
%% it in VASSAL
\info*{\u}{counter}{\x}
- \begin{tikzpicture}
+ \nopagecolor%
+ \gdef\wg at drop@margin{0pt}%
+ \begin{tikzpicture}[chit has drop=false,#2]
\chit[\u=\ti]%
+ \wg at add@drop at margin%
\end{tikzpicture}
\end at info%
%% \foreach \n in {1,...,\m}{% Make a number of copies
@@ -189,14 +212,25 @@
%
% Make separate images for each counter (double sided). The back-side
% counters must be defined by append `\texttt{ flipped}' the front
-% face name
+% face name.
+%
+% First optional argument is the group to put the chits into.
+% Second optional argument is options to give to each Tikz picture
+% environment. Third, mandatory, argument is the list of chit
+% identifiers to render.
%
% \begin{macrocode}
-\newcommand\doublechitimages[2][]{%
+\def\doublechitimages{%
+ \@ifnextchar[{\@doublechitimages}{\doublechitimages[]}%]
+}%
+\def\@doublechitimages[#1]{%
+ \@ifnextchar[{\@@doublechitimages[#1]}{\@@doublechitimages[#1][]}%]
+}%
+\def\@@doublechitimages[#1][#2]#3{%
\begingroup%
\let\chit at report\do at chit@report%
\let\natoapp at report\do at natoapp@report%
- \foreach[count=\ti from 0] \t/\x in #2{%
+ \foreach[count=\ti from 0] \t/\x in #3{%
\ifx\t\empty\else% Ignore empty rows
\chit at dbg{5}{^^JSubcategory: `\x' (default `#1')}
% Take sub-category or default
@@ -213,13 +247,18 @@
%% We only make one copy of the chit, since we can duplicate
%% it in VASSAL
\info*{\u}{counter}{\x}%
- \begin{tikzpicture}%
+ \nopagecolor%
+ \gdef\wg at drop@margin{0pt}%
+ \begin{tikzpicture}[chit has drop=false,#2]%
\chit[\u=\ti]%
+ \wg at add@drop at margin%
\end{tikzpicture}%
\end at info%
\info*{\s}{counter}{\x}%
- \begin{tikzpicture}%
+ \nopagecolor%
+ \begin{tikzpicture}[chit has drop=false,#2]%
\chit[\s=\ti]%
+ \wg at add@drop at margin%
\end{tikzpicture}%
\end at info%
%% \foreach \n in {1,...,\m}{% Make a number of copies
@@ -414,7 +453,7 @@
\def\hex at col{0}%
\def\hex at row{0}%
\node[hex,inner sep=0,outer sep=0]{%
- \message{^^JHex label: `\meaning\hex at label'}%
+ %\message{^^JHex label: `\meaning\hex at label'}%
\global\let\mk at label\hex at label}}}%
% \end{macrocode}
%
@@ -427,7 +466,7 @@
\edef\mk at i{\mk at i\space}
%% Everything is made into centimeters
\mk at w{ \mk at i "units": "cm",}
- \hex at dbg{0}{Label: `\meaning\mk at label'}
+ \hex at dbg{3}{Label: `\meaning\mk at label'}
\@ifundefined{mk at label}{}{\mk at w{ \mk at i "labels": "\mk at label",}}
%% Write out coordinate options as "coords" object
\mk at w{ \mk at i"coords": \@lbchar}%
@@ -577,7 +616,7 @@
% optional is the group to add the markers to.
%
% \begin{macrocode}
-\def\wg at gennumberm@rkers#1#2#3{
+\def\wg at gennumberm@rkers#1#2#3#4{
\message{^^JNumbered markers: Type=`#1' Max=`#2' Category=`#3'}
\def\markers{}
\def\keys{}
@@ -585,15 +624,27 @@
\xdef\keys{/tikz/#1 \i/.style={/tikz/#1=\i},\keys}
\xdef\markers{\markers,#1 \i}}
{%
- \nopagecolor\pgfkeysalsofrom{\keys}\chitimages[#3]{\markers}}}%
+ \nopagecolor\pgfkeysalsofrom{\keys}\chitimages[#3][#4]{\markers}}}%
\tikzset{
wg hidden unit/.pic={},
wg hidden unit/.style={
chit={
+ no chit drop,
frame={draw=none,fill=none},
full=wg hidden unit}}}
-\DeclareRobustCommand\battlemarkers[2][BattleMarkers]{%
- \wg at gennumberm@rkers{battle marker}{#2}{#1}%
+%
+% First optional argument are extra styles
+% Second is category
+% Third is number of markers
+%
+\def\battlemarkers{%
+ \@ifnextchar[{\@battlemarkers}{\battlemarkers[]}%]
+}%
+\def\@battlemarkers[#1]{%
+ \@ifnextchar[{\@@battlemarkers[#1]}{\battlemarkers[#1][BattleMarkers]}%]
+}%
+\def\@@battlemarkers[#1][#2]#3{%
+ \wg at gennumberm@rkers{battle marker}{#3}{#2}{#1}%
\message{^^JMake a hidden unit and add to Markers category}
{%
\nopagecolor%
@@ -600,9 +651,10 @@
\chitimages[Markers]{{wg hidden unit}}%
%
\info{battle-marker-icon}{icon}{}%
- \tikz[scale=.7,transform shape]{\pic{battle marker=0};}%
+ \tikz[scale=.7,transform shape,auto icon more/.try]{%
+ \pic{battle marker=0};}%
\info{clear-battles-icon}{icon}{}
- \tikz[scale=.4,transform shape]{%
+ \tikz[scale=.4,transform shape,auto icon more/.try]{%
\pic{eliminate icon};
\pic[scale=.7,transform shape] at (-.3,0) {battle marker=0};}%
}%
@@ -613,21 +665,40 @@
% Optional is the group to add the markers to.
%
% \begin{macrocode}
-\def\wg at gencolorm@rkers#1#2#3{%
+\def\wg at gencolorm@rkers#1#2#3#4{%
\def\markers{}
\def\keys{}
- \foreach \o/\f in {#2}{%
+ \foreach \o/\f/\n [count=\i] in {#2}{%
+ \ifx\n\f\def\n{\o}\fi%
\ifx\o\f\def\f{white}\fi%
- \message{^^JOdds marker `#1 \o' w/fill `\f'}%
- \xdef\keys{/tikz/#1 \o/.style={/tikz/#1={\o,\f}},\keys}
- \xdef\markers{\markers,#1 \o}}
- {\nopagecolor\pgfkeysalsofrom{\keys}\chitimages[#3]{\markers}}}%
-\DeclareRobustCommand\oddsmarkers[2][OddsMarkers]{%
- \wg at gencolorm@rkers{odds marker}{#2}{#1}%
+ \message{^^JColour no \i marker `#1 \n' w/fill `\f' text `\o'}%
+ \protected at xdef\keys{/tikz/#1 \n/.style={/tikz/#1={\o,\f}},\keys}
+ \xdef\markers{\markers,#1 \n}
+ }%
+ {%
+ \nopagecolor%
+ \pgfkeysalsofrom{\keys}%
+ \chitimages[#3][#4]{\markers}%
+ }%
+}%
+%
+% First optional argument are extra styles
+% Second is category
+% Third is marker list
+%
+\def\oddsmarkers{%
+ \@ifnextchar[{\@oddsmarkers}{\oddsmarkers[]}%]
+}%
+\def\@oddsmarkers[#1]{%
+ \@ifnextchar[{\@@oddsmarkers[#1]}{\oddsmarkers[#1][OddsMarkers]}%]
+}%
+\def\@@oddsmarkers[#1][#2]#3{%
+ \wg at gencolorm@rkers{odds marker}{#3}{#2}{#1}%
\info{odds-battles-icon}{icon}{}
- \tikz[scale=.5,transform shape]{\pic{odds marker={?:?,white}}}
+ \tikz[scale=.5,transform shape,auto icon more/.try]{%
+ \pic{odds marker={?:?,white}}}
\info{resolve-battles-icon}{icon}{}
- \tikz[scale=.3,transform shape]{%
+ \tikz[scale=.3,transform shape,auto icon more/.try]{%
\pic{dice};
\pic[scale=1.2,transform shape] at (-.2,-.2) {battle marker=0};}%
}
@@ -636,40 +707,51 @@
% Make results markers. Mandatory argument is a list of results and
% fill colours. Optional is the group to add the markers to.
%
+%
+% First optional argument are extra styles
+% Second is category
+% Third is marker list
+%
% \begin{macrocode}
-\DeclareRobustCommand\resultmarkers[2][ResultMarkers]{%
- \wg at gencolorm@rkers{result marker}{#2}{#1}}
+\def\resultmarkers{%
+ \@ifnextchar[{\@resultmarkers}{\resultmarkers[]}%]
+}%
+\def\@resultmarkers[#1]{%
+ \@ifnextchar[{\@@resultmarkers[#1]}{\resultmarkers[#1][ResultMarkers]}%]
+}%
+\def\@@resultmarkers[#1][#2]#3{%
+ \wg at gencolorm@rkers{result marker}{#3}{#2}{#1}}%
% \end{macrocode}
%
% Common icons used by many modules
%
% \begin{macrocode}
-\DeclareRobustCommand\commonicons[2]{%
+\DeclareRobustCommand\commonicons[3][]{%
\begingroup%
\nopagecolor%
- \tikzset{icon/.style={scale=.4,transform shape}}%
+ \tikzset{auto icon/.style={scale=.4,transform shape,#1}}%
%
\info{pool-icon}{icon}{}
- \tikz[icon]{\pic{pool icon};}
+ \tikz[auto icon,auto icon more/.try]{\pic{pool icon};}
%
\info{oob-icon}{icon}{}%
- \tikz[icon]{\pic{oob icon={#1}{#2}};}%
+ \tikz[auto icon,auto icon more/.try]{\pic{oob icon={#2}{#3}};}%
%
\info{flip-icon}{icon}{}%
- \tikz[icon]{\pic{flip icon};}%
+ \tikz[auto icon,auto icon more/.try]{\pic{flip icon};}%
%
\info{eliminate-icon}{icon}{}%
- \tikz[icon]{\pic{eliminate icon};}%
+ \tikz[auto icon,auto icon more/.try]{\pic{eliminate icon};}%
%
\info{restore-icon}{icon}{}%
- \tikz[icon]{\pic{restore icon};}%
+ \tikz[auto icon,auto icon more/.try]{\pic{restore icon};}%
%
\info{dice-icon}{icon}{}%
- \tikz[icon,scale=.9]{\pic{dice};}%
+ \tikz[auto icon,scale=.9,auto icon more/.try]{\pic{dice};}%
%
\info{unit-icon}{icon}{}%
- \tikz[icon,scale=.7]{%
- \chit[fill=#1,
+ \tikz[auto icon,scale=.7,auto icon more/.try]{%
+ \chit[fill=#2,
symbol={[
scale line widths,
line width=1pt,
@@ -677,7 +759,29 @@
command=land,
main=infantry,
scale=1.3](0,-.15)}]}%
- \endgroup%
+ %
+ \info{layer-icon}{icon}{}%
+ \begin{tikzpicture}[scale=.25]
+ \foreach \i in {-1,0,1}{
+ \scoped[shift={(0,\i*.15)}]{
+ \draw[black,fill=white] (-.5,0)
+ --(0,.3)--(.5,0)--(0,-.3)--cycle;
+ }
+ }
+ \end{tikzpicture}%
+ %
+ \info{los-icon}{icon}{}
+ \begin{tikzpicture}[scale=.25]
+ \draw[scale line widths,line width=2pt,fill=white](-.5,0)
+ to[out=70,in=110] (.5,0)
+ to[out=-110,in=-70] cycle;
+ \begin{scope}[even odd rule]
+ \clip circle(.2);
+ \fill circle(.2) (125:.18) circle(.1);
+ \end{scope}
+ \end{tikzpicture}%
+ %
+ \endgroup%
}
% \end{macrocode}
%
@@ -708,9 +812,11 @@
\foreach \v/\p in {#5}{%
\info{#3-\v}{die-roll}{#3}
\tikz[#1]{
- \node[shape=#4,transform shape,draw=none,fill=black,opacity=.5]
- at (.05,-.03){};
- \node[shape=#4,#2,transform shape]{\p};}}}
+ %\node[shape=#4,transform shape,draw=none,fill=black,opacity=.5]
+ %at (.05,-.03){};
+ \node[shape=#4,#2,transform shape,
+ chit drop
+ ]{\p};\wg at add@drop at margin{}}}}
% \end{macrocode}
%
% \subsubsection{Hooks into chits, etc.}
@@ -809,6 +915,28 @@
\mk at w{ \mk at i\space "end": 0}
\mk at w{ \mk at i \@rbchar}
}
+\tikzset{
+ chit drop margin/.store in=\wg at drop@margin,
+ chit drop shadows/.code={
+ \pgfkeysalso{%
+ /tikz/every chit node/.prefix style={chit drop={#1}},
+ /tikz/chit has drop=true}
+ },
+ chit drop shadows/.default=,
+ marker drop shadows/.code={
+ \pgfkeysalso{%
+ /tikz/every battle marker/.prefix style={chit drop={#1}},
+ /tikz/every odds marker/.prefix style={chit drop={#1}},
+ /tikz/every result marker/.prefix style={chit drop={#1}},
+ /tikz/auto icon more/.prefix style={no chit drop}}},
+ marker drop shadows/.default={
+ chit has drop=false,
+ shadow xshift=0.04cm,
+ shadow yshift=-0.04cm,
+ shadow blur radius=0.04cm}
+}
+
+
% \end{macrocode}
%
%
Modified: trunk/Master/texmf-dist/source/latex/wargame/util/tikz.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/wargame/util/tikz.dtx 2024-02-03 21:13:44 UTC (rev 69691)
+++ trunk/Master/texmf-dist/source/latex/wargame/util/tikz.dtx 2024-02-03 21:13:58 UTC (rev 69692)
@@ -86,12 +86,17 @@
% Save pgf rounded corners macro
% \let\wg at pgfsetcornersarced\pgfsetcornersarced
\def\wg at setcornersarched#1{%
- \ifx|#1|\else%
- \edef\pgf at corner@arc{{#1}{#1}}%
- \pgf at arccornerstrue%
- \ifdim#1=0pt%
- \pgf at arccornersfalse%
- \fi\fi}
+ \def\arg{#1}%
+ \let\isarched\relax% Cannot set \ifpgf at arccorners directly inside
+ % other \if
+ \ifx\arg\@empty\else%
+ \edef\pgf at corner@arc{{#1}{#1}}%
+ \let\isarched\pgf at arccornerstrue%
+ \ifdim#1=0pt%
+ \let\isarched\pgf at arccornersfalse%
+ \fi%
+ \fi%
+ \isarched}
\newdimen\wg at lw@scaled\wg at lw@scaled=1pt
\def\wg at getscale{%
\pgfgettransformentries{%
Modified: trunk/Master/texmf-dist/source/latex/wargame/utils/wgexport.py
===================================================================
--- trunk/Master/texmf-dist/source/latex/wargame/utils/wgexport.py 2024-02-03 21:13:44 UTC (rev 69691)
+++ trunk/Master/texmf-dist/source/latex/wargame/utils/wgexport.py 2024-02-03 21:13:58 UTC (rev 69692)
@@ -208,6 +208,8 @@
ALT_SHIFT = ALT+SHIFT
NONE = '\ue004'
NONE_MOD = 0
+
+# --------------------------------------------------------------------
def key(let,mod=CTRL):
'''Encode a key sequence
@@ -220,6 +222,8 @@
Modifier mask
'''
return f'{ord(let)},{mod}'
+
+# --------------------------------------------------------------------
#
def hexcolor(s):
if isinstance(s,str):
@@ -241,6 +245,7 @@
return rgb(int(r*256),int(g*256),int(b*256))
+# --------------------------------------------------------------------
# Colour encoding
def rgb(r,g,b):
'''Encode RGB colour
@@ -261,6 +266,7 @@
'''
return ','.join([str(r),str(g),str(b)])
+# --------------------------------------------------------------------
def rgba(r,g,b,a):
'''Encode RGBA colour
@@ -282,6 +288,7 @@
'''
return ','.join([str(r),str(g),str(b),str(a)])
+# --------------------------------------------------------------------
def dumpTree(node,ind=''):
'''Dump the tree of nodes
@@ -296,6 +303,12 @@
for c in node.childNodes:
dumpTree(c,ind+' ')
+# --------------------------------------------------------------------
+def registerElement(cls):
+
+ Element.known_tags[cls.TAG] = cls
+
+
#
# EOF
#
@@ -310,6 +323,8 @@
MAP = MODULE + 'map.'
PICKER = MAP + 'boardPicker.'
BOARD = PICKER + 'board.'
+ known_tags = {}
+
def __init__(self,parent,tag,node=None,**kwargs):
'''Create a new element
@@ -429,9 +444,14 @@
return {c[key] : c for c in cand}
return cand
- def getParent(self,cls,checkTag=True):
+ def getParent(self,cls=None,checkTag=True):
if self._node.parentNode is None:
return None
+ if cls is None:
+ cls = self.getTagClass(self._node.parentNode.tagName)
+ checkTag = False
+ if cls is None:
+ return None
if checkTag and self._node.parentNode.tagName != cls.TAG:
return None
return cls(self,node=self._node.parentNode)
@@ -440,6 +460,10 @@
'''Searches back until we find the parent with the right
class, or none
'''
+ try:
+ iter(cls)
+ except:
+ cls = [cls]
t = {c.TAG: c for c in cls}
p = self._node.parentNode
while p is not None:
@@ -447,6 +471,11 @@
if c is not None: return c(self,node=p)
p = p.parentNode
return None
+
+ def getTagClass(self,tag):
+ '''Get class corresponding to the tag'''
+ if tag not in self.known_tags: return None;
+ return self.known_tags[tag]
# ----------------------------------------------------------------
# Adders
@@ -518,7 +547,83 @@
'''
super(DummyElement,self).__init__(parent,'Dummy',node=node)
+# --------------------------------------------------------------------
+class ToolbarElement(Element):
+ def __init__(self,
+ parent,
+ tag,
+ node = None,
+ name = '', # Toolbar element name
+ tooltip = '', # Tool tip
+ text = '', # Button text
+ icon = '', # Button icon,
+ hotkey = '', # Named key or key stroke
+ canDisable = False,
+ propertyGate = '',
+ disabledIcon = '',
+ **kwargs):
+ '''Base class for toolbar elements.
+ Parameters
+ ----------
+ parent : Element
+ Parent element if any
+ tag : str
+ Element tag
+ node : XMLNode
+ Possible node - when reading back
+ name : str
+ Name of element (user reminder). If not set, and tooltip is set,
+ set to tooltip
+ toolttip : str
+ Tool tip when hovering. If not set, and name is set, then
+ use name as tooltip.
+ text : str
+ Text of button
+ icon : str
+ Image path for button image
+ hotkey : str
+ Named key or key-sequence
+ canDisable : bool
+ If true, then the element can be disabled
+ propertyGate : str
+ Name of a global property. When this property is `true`,
+ then this element is _disabled_. Note that this _must_ be
+ the name of a property - it cannot be a BeanShell
+ expression.
+ disabledIcon : str
+ Path to image to use when the element is disabled.
+ kwargs : dict
+ Other attributes to set on the element
+ '''
+ if name == '' and tooltip != '': name = tooltip
+ if name != '' and tooltip == '': tooltip = name
+
+ # Build arguments for super class
+ args = {
+ 'node': node,
+ 'name': name,
+ 'icon': icon,
+ 'tooltip': tooltip,
+ 'hotkey': hotkey,
+ 'canDisable': canDisable,
+ 'propertyGate': propertyGate,
+ 'disabledIcon': disabledIcon }
+ bt = kwargs.pop('buttonText',None)
+ # If the element expects buttonText attribute, then do not set
+ # the text attribute - some elements interpret that as a
+ # legacy name attribute,
+ if bt is not None:
+ args['buttonText'] = bt
+ else:
+ args['text'] = text
+ args.update(kwargs)
+
+ super(ToolbarElement,self).__init__(parent,
+ tag,
+ **args)
+ # print('Attributes\n','\n'.join([f'- {k}="{v}"' for k,v in self._node.attributes.items()]))
+
#
# EOF
#
@@ -526,7 +631,7 @@
# From globalkey.py
# --------------------------------------------------------------------
-class GlobalKey(Element):
+class GlobalKey(ToolbarElement):
SELECTED = 'MAP|false|MAP|||||0|0||true|Selected|true|EQUALS'
def __init__(self,
parent,
@@ -533,19 +638,21 @@
tag,
node = None,
name = '',
+ icon = '',
+ tooltip = '',
buttonHotkey = '',
- hotkey = '',
buttonText = '',
canDisable = False,
+ propertyGate = '',
+ disabledIcon = '',
+ # Local
+ hotkey = '',
deckCount = '-1',
filter = '',
- propertyGate = '',
reportFormat = '',
reportSingle = False,
singleMap = True,
- target = SELECTED,
- tooltip = '',
- icon = ''):
+ target = SELECTED):
'''
Parameters
----------
@@ -569,28 +676,26 @@
Default targets are selected units
'''
- nme = (name if len(name) > 0 else
- tooltip if len(tooltip) > 0 else '')
- tip = (tooltip if len(tooltip) > 0 else
- name if len(name) > 0 else '')
+
super(GlobalKey,self).\
__init__(parent,
tag,
node = node,
- name = nme,
+ name = name,
+ icon = icon,
+ tooltip = tooltip,
buttonHotkey = buttonHotkey, # This hot key
- hotkey = hotkey, # Target hot key
buttonText = buttonText,
canDisable = canDisable,
+ propertyGate = propertyGate,
+ disabledIcon = disabledIcon,
+ hotkey = hotkey, # Target hot key
deckCount = deckCount,
filter = filter,
- propertyGate = propertyGate,
reportFormat = reportFormat,
reportSingle = reportSingle,
singleMap = singleMap,
- target = target,
- tooltip = tip,
- icon = icon)
+ target = target)
#
# EOF
#
@@ -600,7 +705,7 @@
# --------------------------------------------------------------------
class GameElementService:
def getGame(self):
- return self.getParent(Game)
+ return self.getParentOfClass(Game)
# --------------------------------------------------------------------
class GameElement(Element,GameElementService):
@@ -608,23 +713,34 @@
super(GameElement,self).__init__(game,tag,node=node,**kwargs)
# --------------------------------------------------------------------
-class Notes(GameElement):
+class Notes(ToolbarElement,GameElementService):
TAG = Element.MODULE+'NotesWindow'
def __init__(self,elem,node=None,
- name = 'Notes',
- buttonText = '',
- hotkey = key('N',ALT),
- icon = '/images/notes.gif',
- tooltip = 'Show notes window'):
- super(Notes,self).__init__(elem,self.TAG,node=node,
- name = name,
- buttonText = buttonText,
- hotkey = hotkey,
- icon = icon,
- tooltip = tooltip)
+ name = 'Notes', # Toolbar element name
+ tooltip = 'Show notes window', # Tool tip
+ text = '', # Button text
+ icon = '/images/notes.gif', # Button icon,
+ hotkey = key('N',ALT), # Named key or key stroke
+ canDisable = False,
+ propertyGate = '',
+ disabledIcon = '',
+ description = ''):
+ super(Notes,self).__init__(elem,self.TAG,
+ node = node,
+ name = name,
+ tooltip = tooltip,
+ text = text,
+ icon = icon,
+ hotkey = hotkey,
+ canDisable = canDisable,
+ propertyGate = propertyGate,
+ disabledIcon = disabledIcon,
+ description = description)
def encode(self):
return ['NOTES\t\\','PNOTES']
+registerElement(Notes)
+
# --------------------------------------------------------------------
class PredefinedSetup(GameElement):
TAG = Element.MODULE+'PredefinedSetup'
@@ -673,6 +789,7 @@
+registerElement(PredefinedSetup)
# --------------------------------------------------------------------
class GlobalTranslatableMessages(GameElement):
@@ -690,11 +807,15 @@
super(GlobalTranslatableMessages,self).\
__init__(elem,self.TAG,node=node)
+registerElement(GlobalTranslatableMessages)
+
# --------------------------------------------------------------------
class Language(GameElement):
TAG = 'VASSAL.i18n.Language'
def __init__(self,elem,node=None,**kwargs):
super(Languate,self).__init__(sele,self.TAG,node=none,**kwargs)
+
+registerElement(Language)
# --------------------------------------------------------------------
class Chatter(GameElement):
@@ -712,6 +833,8 @@
Attributes
'''
super(Chatter,self).__init__(elem,self.TAG,node=node,**kwargs)
+
+registerElement(Chatter)
# --------------------------------------------------------------------
class KeyNamer(GameElement):
@@ -730,6 +853,8 @@
'''
super(KeyNamer,self).__init__(elem,self.TAG,node=node,**kwargs)
+registerElement(KeyNamer)
+
# --------------------------------------------------------------------
# <VASSAL.build.module.GlobalOptions
@@ -883,6 +1008,7 @@
return retd
+registerElement(GlobalOptions)
# --------------------------------------------------------------------
class Option(Element):
@@ -894,6 +1020,8 @@
def getGlobalOptions(self):
return self.getParent(GlobalOptions)
+registerElement(Option)
+
# --------------------------------------------------------------------
class Preference(Element):
PREFS = 'VASSAL.preferences.'
@@ -947,6 +1075,9 @@
default = str(default),
desc = desc,
tab = tab)
+
+registerElement(IntPreference)
+
# --------------------------------------------------------------------
class FloatPreference(Preference):
TAG = Preference.PREFS+'DoublePreference'
@@ -964,6 +1095,9 @@
default = str(default),
desc = desc,
tab = tab)
+
+registerElement(FloatPreference)
+
# --------------------------------------------------------------------
class BoolPreference(Preference):
TAG = Preference.PREFS+'BooleanPreference'
@@ -982,6 +1116,9 @@
else 'false'),
desc = desc,
tab = tab)
+
+registerElement(BoolPreference)
+
# --------------------------------------------------------------------
class StrPreference(Preference):
TAG = Preference.PREFS+'StringPreference'
@@ -999,6 +1136,9 @@
default = default,
desc = desc,
tab = tab)
+
+registerElement(StrPreference)
+
# --------------------------------------------------------------------
class TextPreference(Preference):
TAG = Preference.PREFS+'TextPreference'
@@ -1017,6 +1157,9 @@
.replace('\n','
')),
desc = desc,
tab = tab)
+
+registerElement(TextPreference)
+
# --------------------------------------------------------------------
class EnumPreference(Preference):
TAG = Preference.PREFS+'EnumPreference'
@@ -1042,39 +1185,42 @@
tab = tab,
list = sl)
+
+registerElement(EnumPreference)
+
# --------------------------------------------------------------------
# CurrentMap == "Board"
-class Inventory(GameElement):
+class Inventory(ToolbarElement,GameElementService):
TAG = Element.MODULE+'Inventory'
def __init__(self,doc,node=None,
- canDisable = False,
- centerOnPiece = True,
- disabledIcon = '',
- drawPieces = True,
- foldersOnly = False,
- forwardKeystroke = True,
- groupBy = '',
- hotkey = key('I',ALT),
- icon = '/images/inventory.gif',
- include = '{}',
- launchFunction = 'functionHide',
- leafFormat = '$PieceName$',
- name = '',
- nonLeafFormat = '$PropertyValue$',
- pieceZoom = '0.33',
- pieceZoom2 = '0.5',
- pieceZoom3 = '0.6',
- propertyGate = '',
- refreshHotkey = key('I',ALT_SHIFT),
- showMenu = True,
- sides = '',
- sortFormat = '$PieceName$',
- sortPieces = True,
- sorting = 'alpha',
- text = '',
- tooltip = 'Show inventory of all pieces',
- zoomOn = False):
+ name = '',
+ icon = '/images/inventory.gif',
+ text = '',
+ tooltip = 'Show inventory of all pieces',
+ hotkey = key('I',ALT),
+ canDisable = False,
+ propertyGate = '',
+ disabledIcon = '',
+ centerOnPiece = True,
+ drawPieces = True,
+ foldersOnly = False,
+ forwardKeystroke = True,
+ groupBy = '',
+ include = '{}',
+ launchFunction = 'functionHide',
+ leafFormat = '$PieceName$',
+ nonLeafFormat = '$PropertyValue$',
+ pieceZoom = '0.33',
+ pieceZoom2 = '0.5',
+ pieceZoom3 = '0.6',
+ refreshHotkey = key('I',ALT_SHIFT),
+ showMenu = True,
+ sides = '',
+ sortFormat = '$PieceName$',
+ sortPieces = True,
+ sorting = 'alpha',
+ zoomOn = False):
super(Inventory,self).__init__(doc,self.TAG,node=node,
canDisable = canDisable,
centerOnPiece = centerOnPiece,
@@ -1104,17 +1250,8 @@
tooltip = tooltip,
zoomOn = zoomOn)
-
-
+registerElement(Inventory)
-
-
-
-
-
-
-
-
# --------------------------------------------------------------------
class Prototypes(GameElement):
TAG = Element.MODULE+'PrototypesContainer'
@@ -1149,17 +1286,21 @@
'''
return self.getElementsByKey(Prototype,'name',asdict=asdict)
-
+registerElement(Prototypes)
-
# --------------------------------------------------------------------
-class DiceButton(GameElement):
+class DiceButton(ToolbarElement,GameElementService):
TAG=Element.MODULE+'DiceButton'
def __init__(self,elem,node=None,
+ name = '1d6',
+ tooltip = 'Roll a 1d6',
+ text = '1d6',
+ icon = '/images/die.gif',
+ hotkey = key('6',ALT),
+ canDisable = False,
+ propertyGate = '',
+ disabledIcon = '',
addToTotal = 0,
- canDisable = False,
- hotkey = key('6',ALT),
- icon = '/images/die.gif',
keepCount = 1,
keepDice = False,
keepOption = '>',
@@ -1169,19 +1310,16 @@
lockSides = False,
nDice = 1,
nSides = 6,
- name = '1d6',
plus = 0,
prompt = False,
- propertyGate = '',
- reportFormat = '** $name$ = $result$ *** <$PlayerName$>;',
+ reportFormat = '$name$ = $result$',
reportTotal = False,
- sortDice = False,
- text = '1d6',
- tooltip = 'Roll a 1d6'):
+ sortDice = False):
super(DiceButton,self).\
__init__(elem,self.TAG,node=node,
addToTotal = addToTotal,
canDisable = canDisable,
+ disabledIcon = disabledIcon,
hotkey = hotkey,
icon = icon,
keepCount = keepCount,
@@ -1203,24 +1341,27 @@
text = text,
tooltip = tooltip)
+registerElement(DiceButton)
+
# --------------------------------------------------------------------
class GameMassKey(GlobalKey,GameElementService):
TAG = Element.MODULE+'GlobalKeyCommand'
def __init__(self,map,node=None,
name = '',
+ buttonText = '',
+ tooltip = '',
+ icon = '',
+ canDisable = False,
+ propertyGate = '',
+ disabledIcon = '',
buttonHotkey = '',
hotkey = '',
- buttonText = '',
- canDisable = False,
deckCount = '-1',
filter = '',
- propertyGate = '',
reportFormat = '',
reportSingle = False,
singleMap = True,
- target = GlobalKey.SELECTED,
- tooltip = '',
- icon = ''):
+ target = GlobalKey.SELECTED):
'''Default targets are selected units'''
super(GameMassKey,self).\
__init__(map,
@@ -1241,6 +1382,8 @@
tooltip = tooltip,
icon = icon)
+registerElement(GameMassKey)
+
# --------------------------------------------------------------------
class StartupMassKey(GlobalKey,GameElementService):
TAG = Element.MODULE+'StartupGlobalKeyCommand'
@@ -1287,6 +1430,8 @@
if node is None:
self['whenToApply'] = whenToApply
+registerElement(StartupMassKey)
+
# --------------------------------------------------------------------
class Menu(GameElement):
TAG = Element.MODULE+'ToolbarMenu'
@@ -1293,15 +1438,16 @@
def __init__(self,
game,
node = None,
+ name = '',
+ tooltip = '',
+ text = '', # Menu name
canDisable = False,
+ propertyGate = '',
+ disabledIcon = '',
description = '',
- disabledIcon = '',
hotkey = '',
icon = '',
- menuItems = [],# Button texts
- propertyGate = '',
- text = '',# Menu name
- tooltip = ''):
+ menuItems = []):
if len(description) <= 0 and len(tooltip) > 0:
description = tooltip
if len(tooltip) <= 0 and len(description) > 0:
@@ -1310,6 +1456,7 @@
__init__(game,
self.TAG,
node = node,
+ name = name,
canDisable = canDisable,
description = description,
disabledIcon = disabledIcon,
@@ -1320,6 +1467,8 @@
text = text,
tooltip = tooltip)
+registerElement(Menu)
+
# --------------------------------------------------------------------
class SymbolicDice(GameElement):
@@ -1370,6 +1519,8 @@
def getSymbolicDice(self):
return self.getParent(SymbolicDice)
+registerElement(SymbolicDice)
+
# --------------------------------------------------------------------
class SpecialDie(GameElement):
@@ -1399,8 +1550,7 @@
def getSymbolicDice(self):
return self.getParent(SymbolicDice)
-
-
+registerElement(SpecialDie)
# --------------------------------------------------------------------
class DieFace(GameElement):
@@ -1421,6 +1571,9 @@
def getSpecialDie(self):
return self.getParent(SpecialDie)
+
+registerElement(DieFace)
+
#
# EOF
#
@@ -1451,6 +1604,223 @@
# --------------------------------------------------------------------
+class PieceLayers(MapElement):
+ TAG=Element.MAP+'LayeredPieceCollection'
+ def __init__(self,map,node=None,
+ property = 'PieceLayer',
+ description = '',
+ layerOrder = []):
+ super(PieceLayers,self).__init__(map,self.TAG,node=node,
+ property = property,
+ description = description,
+ layerOrder = ','.join(layerOrder))
+
+ def addControl(self,**kwargs):
+ '''Add `LayerControl` element to this
+
+ Parameters
+ ----------
+ kwargs : dict
+ Dictionary of attribute key-value pairs
+ Returns
+ -------
+ element : LayerControl
+ The added element
+ '''
+ return self.add(LayerControl,**kwargs)
+ def getControls(self,asdict=True):
+ '''Get all `LayerControl` element(s) from this
+
+ Parameters
+ ----------
+ asdict : bool
+ If `True`, return a dictonary that maps name to
+ `LayerControl` elements. If `False`, return a list of all
+ `LayerControl` children.
+
+ Returns
+ -------
+ children : dict or list
+ Dictionary or list of `LayerControl` children
+
+ '''
+ return self.getElementsByKey(LayerControl,'name',asdict)
+
+registerElement(PieceLayers)
+
+# --------------------------------------------------------------------
+class LayerControl(MapElement):
+ TAG=Element.MAP+'LayerControl'
+ CYCLE_UP='Rotate Layer Order Up'
+ CYCLE_DOWN='Rotate Layer Order Down'
+ ENABLE='Make Layer Active'
+ DISABLE='Make Layer Inactive'
+ TOGGLE='Switch Layer between Active and Inactive'
+ RESET='Reset All Layers'
+ def __init__(self,col,node=None,
+ name = '',
+ tooltip = '',
+ text = '',
+ hotkey = '',
+ icon = '',
+ canDisable = False,
+ propertyGate = '', #Property name, disable when property false
+ disabledIcon = '',
+ command = TOGGLE,
+ skip = False,
+ layers = [],
+ description = ''):
+ super(LayerControl,self).__init__(col,self.TAG,node=node,
+ name = name,
+ tooltip = tooltip,
+ text = text,
+ buttonText = text,
+ hotkey = hotkey,
+ icon = icon,
+ canDisable = canDisable,
+ propertyGate = propertyGate,
+ disabledIcon = disabledIcon,
+ command = command,
+ skip = skip,
+ layers = ','.join(layers),
+ description = description)
+
+ def getLayers(self):
+ '''Get map - either a Map or WidgetMap'''
+ return self.getParentOfClass([PieceLayers])
+
+registerElement(LayerControl)
+
+
+# --------------------------------------------------------------------
+class LineOfSight(MapElement):
+ TAG=Element.MAP+'LOS_Thread'
+ ROUND_UP = 'Up'
+ ROUND_DOWN = 'Down'
+ ROUND_NEAREST = 'Nearest whole number'
+ FROM_LOCATION = 'FromLocation'
+ TO_LOCATION = 'ToLocation'
+ CHECK_COUNT = 'NumberOfLocationsChecked'
+ CHECK_LIST = 'AllLocationsChecked'
+ RANGE = 'Range'
+ NEVER = 'Never'
+ ALWAYS = 'Always'
+ WHEN_PERSISTENT = 'When persistent'
+ CTRL_CLICK = 'Cltr-Click & Drag'
+
+ def __init__(self,map,
+ node=None,
+ threadName = 'LOS',
+ hotkey = key('L',ALT),
+ tooltip = 'Trace line of sight',
+ iconName = '/images/thread.gif', #'los-icon.png',
+ label = '',
+ snapLOS = False,
+ snapStart = True,
+ snapEnd = True,
+ report = (f'{{"Range from "+{FROM_LOCATION}'
+ f'+" to "+{TO_LOCATION}+" is "'
+ f'+{RANGE}+" (via "+{CHECK_LIST}+")"}}'),
+ persistent = CTRL_CLICK,
+ persistentIconName = '/images/thread.gif',
+ globl = ALWAYS,
+ losThickness = 3,
+ threadColor = rgb(255,0,0),
+ drawRange = True,
+ # rangeBg = rgb(255,255,255),
+ # rangeFg = rgb(0,0,0),
+ rangeScale = 0,
+ hideCounters = True,
+ hideOpacity = 50,
+ round = ROUND_UP,
+ canDisable = False,
+ propertyGate = '',
+ disabledIcon = ''):
+ '''Make Line of Sight interface
+
+ Parameters
+ ----------
+ threadName : str
+ Name of interface
+ hotkey : str
+ Start LOS key
+ tooltip : str
+ Tool tip text
+ iconName : str
+ Path to button icon
+ label : str
+ Button text
+ snapLOS : bool
+ Wether to snap both ends
+ snapStart : bool
+ Snap to start
+ snapEnd: bool
+ Snap to end
+ report : str
+ Report format
+ persistent : str
+ When persistent
+ persistentIconName : str
+ Icon when persistent(?)
+ globl : str
+ Visisble to opponents
+ losThickness : int
+ Thickness in pixels
+ losColor : str
+ Colour of line
+ drawRange : bool
+ Draw the range next to LOST thread
+ rangeBg : str
+ Range backgroung colour
+ rangeFg : str
+ Range foregrond colour
+ rangeScale : int
+ Scale of range - pixels per unit
+ round : str
+ How to round range
+ hideCounters :bool
+ If true, hide counters while making thread
+ hideOpacity : int
+ Opacity of hidden counters (percent)
+ canDisable : bool
+ IF true, then can be hidden
+ propertyGate : str
+ Name of property. When that property is TRUE, then the
+ interface is disabled. Must be a property name, not an expression.
+ disabledIcon : str
+ Icon to use when disabled
+ '''
+ super(LineOfSight,self).__init__(map,self.TAG,
+ node = node,
+ threadName = threadName,
+ hotkey = hotkey,
+ tooltip = tooltip,
+ iconName = iconName,
+ label = label,
+ snapLOS = snapLOS,
+ snapStart = snapStart,
+ snapEnd = snapEnd,
+ report = report,
+ persistent = persistent,
+ persistentIconName = persistentIconName,
+ losThickness = losThickness,
+ threadColor = threadColor,
+ drawRange = drawRange,
+ #rangeBg = rangeBg,
+ #rangeFg = rangeFg,
+ rangeScale = rangeScale,
+ hideCounters = hideCounters,
+ hideOpacity = hideOpacity,
+ round = round,
+ canDisable = canDisable,
+ propertyGate = propertyGate,
+ disabledIcon = disabledIcon)
+ self.setAttribute('global',globl)
+
+
+registerElement(LineOfSight)
+
+# --------------------------------------------------------------------
class StackMetrics(MapElement):
TAG=Element.MAP+'StackMetrics'
def __init__(self,map,node=None,
@@ -1474,6 +1844,8 @@
unexSepY = unexSepY,
up = up)
+registerElement(StackMetrics)
+
# --------------------------------------------------------------------
class ImageSaver(MapElement):
TAG=Element.MAP+'ImageSaver'
@@ -1491,6 +1863,9 @@
icon = icon,
propertyGate = propertyGate,
tooltip = tooltip)
+
+registerElement(ImageSaver)
+
# --------------------------------------------------------------------
class TextSaver(MapElement):
TAG=Element.MAP+'TextSaver'
@@ -1509,6 +1884,7 @@
propertyGate = propertyGate,
tooltip = tooltip)
+registerElement(TextSaver)
# --------------------------------------------------------------------
class ForwardToChatter(MapElement):
@@ -1516,6 +1892,8 @@
def __init__(self,map,node=None,**kwargs):
super(ForwardToChatter,self).__init__(map,self.TAG,node=node,**kwargs)
+registerElement(ForwardToChatter)
+
# --------------------------------------------------------------------
class MenuDisplayer(MapElement):
TAG=Element.MAP+'MenuDisplayer'
@@ -1522,6 +1900,8 @@
def __init__(self,map,node=None,**kwargs):
super(MenuDisplayer,self).__init__(map,self.TAG,node=node,**kwargs)
+registerElement(MenuDisplayer)
+
# --------------------------------------------------------------------
class MapCenterer(MapElement):
TAG=Element.MAP+'MapCenterer'
@@ -1528,6 +1908,8 @@
def __init__(self,map,node=None,**kwargs):
super(MapCenterer,self).__init__(map,self.TAG,node=node,**kwargs)
+registerElement(MapCenterer)
+
# --------------------------------------------------------------------
class StackExpander(MapElement):
TAG=Element.MAP+'StackExpander'
@@ -1534,6 +1916,8 @@
def __init__(self,map,node=None,**kwargs):
super(StackExpander,self).__init__(map,self.TAG,node=node,**kwargs)
+registerElement(StackExpander)
+
# --------------------------------------------------------------------
class PieceMover(MapElement):
TAG=Element.MAP+'PieceMover'
@@ -1540,6 +1924,8 @@
def __init__(self,map,node=None,**kwargs):
super(PieceMover,self).__init__(map,self.TAG,node=node,**kwargs)
+registerElement(PieceMover)
+
# --------------------------------------------------------------------
class SelectionHighlighters(MapElement):
TAG=Element.MAP+'SelectionHighlighters'
@@ -1547,6 +1933,8 @@
super(SelectionHighlighters,self).\
__init__(map,self.TAG,node=node,**kwargs)
+registerElement(SelectionHighlighters)
+
# --------------------------------------------------------------------
class KeyBufferer(MapElement):
TAG=Element.MAP+'KeyBufferer'
@@ -1553,6 +1941,8 @@
def __init__(self,map,node=None,**kwargs):
super(KeyBufferer,self).__init__(map,self.TAG,node=node,**kwargs)
+registerElement(KeyBufferer)
+
# --------------------------------------------------------------------
class HighlightLastMoved(MapElement):
TAG=Element.MAP+'HighlightLastMoved'
@@ -1565,6 +1955,8 @@
enabled = enabled,
thickness = thickness)
+registerElement(HighlightLastMoved)
+
# --------------------------------------------------------------------
class CounterDetailViewer(MapElement):
TAG=Element.MAP+'CounterDetailViewer'
@@ -1587,7 +1979,7 @@
extraTextPadding = 0,
fgColor = rgb(0,0,0),
fontSize = 9,
- graphicsZoom = 1.0,
+ graphicsZoom = 1.0,# Zoom on counters
hotkey = key('\n',0),
layerList = '',
minDisplayPieces = 2,
@@ -1649,6 +2041,8 @@
verticalTopText = verticalTopText,
zoomlevel = zoomlevel)
+registerElement(CounterDetailViewer)
+
# --------------------------------------------------------------------
class GlobalMap(MapElement):
TAG=Element.MAP+'GlobalMap'
@@ -1668,6 +2062,8 @@
scale = scale,
tooltip = 'Show/Hide overview window')
+registerElement(GlobalMap)
+
# --------------------------------------------------------------------
class Zoomer(MapElement):
TAG = Element.MAP+'Zoomer'
@@ -1687,6 +2083,7 @@
zoomOutKey = key('-'),
zoomPickKey = key('='),
zoomStart = 3):
+
'''Zoom start is counting from the back (with default zoom levels,
and zoom start, the default zoom is 1'''
lvls = ','.join([str(z) for z in zoomLevels])
@@ -1707,6 +2104,8 @@
zoomPickKey = zoomPickKey,
zoomStart = zoomStart)
+registerElement(Zoomer)
+
# --------------------------------------------------------------------
class HidePiecesButton(MapElement):
TAG=Element.MAP+'HidePiecesButton'
@@ -1724,6 +2123,8 @@
showingIcon = showingIcon,
tooltip = tooltip)
+registerElement(HidePiecesButton)
+
# --------------------------------------------------------------------
class MassKey(GlobalKey,MapElementService):
TAG = Element.MAP+'MassKeyCommand'
@@ -1760,6 +2161,7 @@
tooltip = tooltip,
icon = icon)
+registerElement(MassKey)
# --------------------------------------------------------------------
class Flare(MapElement):
@@ -1783,10 +2185,13 @@
flarePulsesPerSec = flarePulsesPerSec,
reportFormat = '')
+registerElement(Flare)
+
# --------------------------------------------------------------------
class AtStart(MapElement):
TAG = Element.MODULE+'map.SetupStack'
- def __init__(self,map,node=None,
+ def __init__(self,map,
+ node = None,
name = '',
location = '',
useGridLocation = True,
@@ -1861,6 +2266,8 @@
'''
return self.getElementsWithKey(PieceSlot,'entryName',asdict)
+registerElement(AtStart)
+
#
# EOF
#
@@ -1894,6 +2301,7 @@
def getProperties(self):
return getElementsByKey(GlobalProperty,'name')
+registerElement(GlobalProperties)
# --------------------------------------------------------------------
class GlobalProperty(Element):
@@ -1919,6 +2327,7 @@
def getGlobalProperties(self):
return self.getParent(GlobalProperties)
+registerElement(GlobalProperty)
#
# EOF
@@ -2099,7 +2508,8 @@
return []
-
+registerElement(TurnTrack)
+
# --------------------------------------------------------------------
class TurnCounter(TurnLevel):
TAG = Element.MODULE+"turn.CounterTurnLevel"
@@ -2118,6 +2528,8 @@
loopLimit = loopLimit,
turnFormat = turnFormat)
+registerElement(TurnCounter)
+
# --------------------------------------------------------------------
class TurnList(TurnLevel):
TAG = Element.MODULE+"turn.ListTurnLevel"
@@ -2135,6 +2547,8 @@
configList = configList,
turnFormat = turnFormat)
+registerElement(TurnList)
+
# --------------------------------------------------------------------
class TurnGlobalHotkey(Element):
TAG = Element.MODULE+'turn.TurnGlobalHotkey'
@@ -2172,6 +2586,8 @@
'''Get the turn track'''
return self.getParent(TurnTrack)
+registerElement(TurnGlobalHotkey)
+
#
# EOF
#
@@ -2316,6 +2732,7 @@
return txt
+registerElement(Documentation)
# --------------------------------------------------------------------
class AboutScreen(Element):
@@ -2343,6 +2760,8 @@
'''Get Parent element'''
return self.getParent(Documentation)
+registerElement(AboutScreen)
+
# --------------------------------------------------------------------
class BrowserPDFFile(Element):
TAG = Element.MODULE+'documentation.BrowserPDFFile'
@@ -2368,6 +2787,8 @@
'''Get Parent element'''
return self.getParent(Documentation)
+registerElement(BrowserPDFFile)
+
# --------------------------------------------------------------------
class HelpFile(Element):
TAG = Element.MODULE+'documentation.HelpFile'
@@ -2400,6 +2821,8 @@
'''Get Parent element'''
return self.getParent(Documentation)
+registerElement(HelpFile)
+
# --------------------------------------------------------------------
class BrowserHelpFile(Element):
TAG = Element.MODULE+'documentation.BrowserHelpFile'
@@ -2427,7 +2850,9 @@
def getDocumentation(self):
'''Get Parent element'''
return self.getParent(Documentation)
-
+
+registerElement(BrowserHelpFile)
+
# --------------------------------------------------------------------
class Tutorial(Element):
TAG = Element.MODULE+'documentation.Tutorial'
@@ -2468,6 +2893,8 @@
'''Get Parent element'''
return self.getParent(Documentation)
+registerElement(Tutorial)
+
#
# EOF
@@ -2517,6 +2944,8 @@
'''Encode for save'''
return ['PLAYER\ta\ta\t<observer>']
+registerElement(PlayerRoster)
+
# --------------------------------------------------------------------
class PlayerSide(Element):
TAG = 'entry'
@@ -2540,7 +2969,9 @@
'''Get Parent element'''
return self.getParent(PlayerRoster)
+registerElement(PlayerSide)
+
#
# EOF
#
@@ -2614,7 +3045,9 @@
def getControl(self):
'''Get Parent element'''
return self.getParent(ChessClockControl)
-
+
+registerElement(ChessClock)
+
# ====================================================================
class ChessClockControl(GameElement):
TAG=Element.MODULE+'ChessClockControl'
@@ -2727,6 +3160,7 @@
'''Return dictionary of clocs'''
return self.getElementsByKey(ChessClock,'side',asdict)
+registerElement(ChessClockControl)
#
# EOF
@@ -2961,6 +3395,8 @@
tooltip = tooltip,
icon = icon)
+registerElement(PieceWindow)
+
# --------------------------------------------------------------------
class ComboWidget(Element,WidgetElement):
TAG=Element.WIDGET+'BoxWidget'
@@ -2972,6 +3408,8 @@
width = width,
height = height)
+registerElement(ComboWidget)
+
# --------------------------------------------------------------------
class TabWidget(Element,WidgetElement):
TAG=Element.WIDGET+'TabWidget'
@@ -2981,6 +3419,8 @@
node = node,
entryName = entryName)
+registerElement(TabWidget)
+
# --------------------------------------------------------------------
class ListWidget(Element,WidgetElement):
TAG=Element.WIDGET+'ListWidget'
@@ -2997,6 +3437,8 @@
scale = scale,
divider = divider)
+registerElement(ListWidget)
+
# --------------------------------------------------------------------
class PanelWidget(Element,WidgetElement):
TAG=Element.WIDGET+'PanelWidget'
@@ -3011,6 +3453,8 @@
nColumns = nColumns,
vert = vert)
+registerElement(PanelWidget)
+
# --------------------------------------------------------------------
class MapWidget(Element):
TAG=Element.WIDGET+'MapWidget'
@@ -3046,6 +3490,8 @@
'''
return self.getElementsByKey(WidgetMap,'mapName',asdict=asdict)
+registerElement(MapWidget)
+
#
# EOF
#
@@ -3258,6 +3704,8 @@
width = self.getZone().getWidth()
return floor(width / self.getDeltaY() + .5)
+registerElement(HexGrid)
+
# --------------------------------------------------------------------
class SquareGrid(BaseGrid):
TAG = Element.BOARD+'SquareGrid'
@@ -3307,6 +3755,8 @@
width = self.getZone().getWidth()
return floor(width / self.getDeltaX() + .5)
+registerElement(SquareGrid)
+
# --------------------------------------------------------------------
class HexNumbering(BaseNumbering):
TAG = Element.BOARD+'mapgrid.HexGridNumbering'
@@ -3368,6 +3818,8 @@
return x,y
+registerElement(HexNumbering)
+
# --------------------------------------------------------------------
class SquareNumbering(BaseNumbering):
TAG = Element.BOARD+'mapgrid.SquareGridNumbering'
@@ -3395,6 +3847,7 @@
return x,y
+registerElement(SquareNumbering)
# --------------------------------------------------------------------
class RegionGrid(Element):
@@ -3452,6 +3905,8 @@
return None
+registerElement(RegionGrid)
+
# --------------------------------------------------------------------
class Region(Element):
TAG = Element.BOARD+'Region'
@@ -3527,6 +3982,8 @@
return b.getMap()
return None
+registerElement(Region)
+
#
# EOF
#
@@ -3579,7 +4036,7 @@
children : list
List of `Highligter` children (even if `single=True`)
'''
- return self.getAllElements(ZonedGridHighliger,single=single)
+ return self.getAllElements(ZonedGridHighlighter,single=single)
def addZone(self,**kwargs):
'''Add a `Zone` element to this
@@ -3607,6 +4064,8 @@
'''
return self.getElementsByKey(Zone,'name',asdict=asdict)
+registerElement(ZonedGrid)
+
# --------------------------------------------------------------------
class ZonedGridHighlighter(Element):
TAG=Element.BOARD+'mapgrid.ZonedGridHighlighter'
@@ -3614,8 +4073,98 @@
super(ZonedGridHighlighter,self).__init__(zoned,self.TAG,node=node)
def getZonedGrid(self): return self.getParent(ZonedGrid)
+ def addZoneHighlight(self,**kwargs):
+ '''Add a `ZoneHighlight` element to this
+ Parameters
+ ----------
+ kwargs : dict
+ Dictionary of attribute key-value pairs
+ Returns
+ -------
+ element : ZoneHighlight
+ The added element
+ '''
+ return self.add(ZoneHighlight,**kwargs)
+ def getZoneHighlights(self,asdict=True):
+ '''Get all ZoneHighlight element(s) from this
+
+ Parameters
+ ----------
+ asdict : bool
+ If `True`, return a dictonary that maps key to `Zone` elements. If `False`, return a list of all Zone` children.
+ Returns
+ -------
+ children : dict or list
+ Dictionary or list of `Zone` children
+ '''
+ return self.getElementsByKey(ZoneHighlight,'name',asdict=asdict)
+
+registerElement(ZonedGridHighlighter)
+
# --------------------------------------------------------------------
+class ZoneHighlight(Element):
+ TAG=Element.BOARD+'mapgrid.ZoneHighlight'
+ FULL='Entire Zone',
+ BORDER='Zone Border',
+ PLAIN='Plain',
+ STRIPED='Striped'
+ CROSS='Crosshatched',
+ TILES='Tiled Image'
+ def __init__(self,
+ highlighters,
+ node = None,
+ name = '',
+ color = rgb(255,0,0),
+ coverage = FULL,
+ width = 1,
+ style = PLAIN,
+ image = '',
+ opacity = 50):
+ super(ZoneHighlight,self).__init__(highlighters,
+ self.TAG,
+ node = node,
+ name = name,
+ color = color,
+ coverage = coverage,
+ width = width,
+ style = style,
+ image = image,
+ opacity = int(opacity))
+ def getZonedGridHighlighter(self):
+ return self.getParent(ZonedGridHighlighter)
+
+
+registerElement(ZoneHighlight)
+
+
+# --------------------------------------------------------------------
+class ZoneProperty(Element):
+ TAG = Element.MODULE+'properties.ZoneProperty'
+ def __init__(self,zone,node=None,
+ name = '',
+ initialValue = '',
+ isNumeric = False,
+ min = "null",
+ max = "null",
+ wrap = False,
+ description = ""):
+ super(ZoneProperty,self).__init__(zone,self.TAG,
+ node = node,
+ name = name,
+ initialValue = initialValue,
+ isNumeric = isNumeric,
+ min = min,
+ max = max,
+ wrap = wrap,
+ description = description)
+
+ def getZone(self):
+ return self.getParent(Zone)
+
+registerElement(ZoneProperty)
+
+# --------------------------------------------------------------------
class Zone(Element):
TAG = Element.BOARD+'mapgrid.Zone'
def __init__(self,zoned,node=None,
@@ -3693,6 +4242,19 @@
The added element
'''
return self.add(RegionGrid,**kwargs)
+ def addProperty(self,**kwargs):
+ '''Add a `Property` element to this
+
+ Parameters
+ ----------
+ kwargs : dict
+ Dictionary of attribute key-value pairs
+ Returns
+ -------
+ element : Property
+ The added element
+ '''
+ return self.add(ZoneProperty,**kwargs)
def getHexGrids(self,single=True):
'''Get all or a sole `HexGrid` element(s) from this
@@ -3758,6 +4320,17 @@
if g is not None: return g
return g
+ def getProperties(self):
+ '''Get all `Property` element from this
+
+ Parameters
+ ----------
+ Returns
+ -------
+ children : dict
+ dict of `Property` children
+ '''
+ return getElementsByKey(ZoneProperty,'name')
def getPath(self):
p = self['path'].split(';')
@@ -3785,6 +4358,8 @@
def getYOffset(self):
return self.getBB()[1]
+registerElement(Zone)
+
#
# EOF
#
@@ -3879,6 +4454,8 @@
return ret
+registerElement(BoardPicker)
+
# --------------------------------------------------------------------
class Setup(Element):
TAG = 'setup'
@@ -3901,7 +4478,9 @@
self.addText(txt)
def getPicker(self): return self.getParent(BoardPicker)
-
+
+registerElement(Setup)
+
# --------------------------------------------------------------------
class Board(Element):
TAG = Element.PICKER+'Board'
@@ -3982,6 +4561,7 @@
return int(self['height'])
return 0
+registerElement(Board)
#
# EOF
@@ -4340,6 +4920,57 @@
picker = self.getPicker()
if picker is None: return None
return picker[0].getBoards(asdict=asdict)
+ def getLayers(self,asdict=True):
+ '''Get all `PieceLayer` element(s) from this
+
+ Parameters
+ ----------
+ asdict : bool
+ If `True`, return a dictonary that maps property name
+ `PieceLayers` elements. If `False`, return a list of all
+ `PieceLayers` children.
+
+ Returns
+ -------
+ children : dict or list
+ Dictionary or list of `PieceLayers` children
+
+ '''
+ return self.getElementsByKey(PieceLayers,'property',asdict)
+ def getMenus(self,asdict=True):
+ '''Get all Menu element(s) from this
+
+ Parameters
+ ----------
+ asdict : bool
+ If `True`, return a dictonary that maps key to `Board`
+ elements. If `False`, return a list of all Board`
+ children.
+
+ Returns
+ -------
+ children : dict or list
+ Dictionary or list of `Board` children
+
+ '''
+ return self.getElementsByKey(Menu,'name',asdict)
+ def getLOSs(self,asdict=True):
+ '''Get all Menu element(s) from this
+
+ Parameters
+ ----------
+ asdict : bool
+ If `True`, return a dictonary that maps key to `Board`
+ elements. If `False`, return a list of all Board`
+ children.
+
+ Returns
+ -------
+ children : dict or list
+ Dictionary or list of `Board` children
+
+ '''
+ return self.getElementsByKey(LineOfSight,'threadName',asdict)
def addBoardPicker(self,**kwargs):
'''Add a `BoardPicker` element to this
@@ -4600,6 +5231,47 @@
The added element
'''
return self.add(AtStart,**kwargs)
+
+
+ def addLayers(self,**kwargs):
+ '''Add `PieceLayers` element to this
+
+ Parameters
+ ----------
+ kwargs : dict
+ Dictionary of attribute key-value pairs
+ Returns
+ -------
+ element : PieceLayers
+ The added element
+ '''
+ return self.add(PieceLayers,**kwargs)
+ def addMenu(self,**kwargs):
+ '''Add a `Menu` element to this
+
+ Parameters
+ ----------
+ kwargs : dict
+ Dictionary of attribute key-value pairs
+ Returns
+ -------
+ element : Menu
+ The added element
+ '''
+ return self.add(Menu,**kwargs)
+ def addLOS(self,**kwargs):
+ '''Add a `Menu` element to this
+
+ Parameters
+ ----------
+ kwargs : dict
+ Dictionary of attribute key-value pairs
+ Returns
+ -------
+ element : Menu
+ The added element
+ '''
+ return self.add(LineOfSight,**kwargs)
# --------------------------------------------------------------------
class Map(BaseMap):
@@ -4657,7 +5329,9 @@
def getGame(self):
return self.getParent(Game)
-
+
+registerElement(Map)
+
# --------------------------------------------------------------------
class WidgetMap(BaseMap):
TAG = Element.WIDGET+'WidgetMap'
@@ -4669,7 +5343,9 @@
def getMapWidget(self):
return self.getParent(MapWidget)
+registerElement(WidgetMap)
+
#
# EOF
#
@@ -4721,7 +5397,7 @@
'''
return self.getElementsById(Chart,'chartName',asdict=asdict)
-
+registerElement(ChartWindow)
# --------------------------------------------------------------------
class Chart(Element):
@@ -4735,6 +5411,8 @@
description = description,
fileName = fileName)
+registerElement(Chart)
+
#
# EOF
#
@@ -4766,7 +5444,7 @@
this actually holds state that isn't reflected elsewhere in
the DOM. This means that the data here is local to the
object. So when we do
-
+
piece = foo.getPieceSlots()[0]
traits = p.getTraits()
for trait in traits:
@@ -5040,6 +5718,15 @@
Identifier
'''
+ last = traits[-1]
+ # A little hackish to use the name of the class, but needed
+ # because of imports into patch scripts.
+ if not isinstance(last,BasicTrait) and \
+ not last.__class__.__name__.endswith('BasicTrait'):
+ from sys import stderr
+ print(f'Warning - last trait NOT a BasicTrait, but a {type(last)}',
+ file=stderr)
+
types = []
states = []
for trait in traits:
@@ -5165,7 +5852,9 @@
if parent is not None:
parent.remove(self)
-
+
+registerElement(DummyWithTraits)
+
# --------------------------------------------------------------------
class PieceSlot(WithTraits):
TAG = Element.WIDGET+'PieceSlot'
@@ -5226,6 +5915,7 @@
piece.setTraits(*traits)
return piece
+registerElement(PieceSlot)
# --------------------------------------------------------------------
class Prototype(WithTraits):
@@ -5255,6 +5945,8 @@
name = name,
description = description)
+registerElement(Prototype)
+
#
# EOF
#
@@ -5262,10 +5954,11 @@
# From traits/dynamicproperty.py
# --------------------------------------------------------------------
-# Base class for property (piece or global) change traits. Encodes
-# constraints and commands.
+#
+#
class ChangePropertyTrait(Trait):
DIRECT = 'P'
+ INCREMENT = 'I'
def __init__(self,
*commands,
numeric = False,
@@ -5272,6 +5965,10 @@
min = 0,
max = 100,
wrap = False):
+ '''Base class for property (piece or global) change traits.
+
+ Encodes constraints and commands.
+ '''
# assert name is not None and len(name) > 0, \
# 'No name specified for ChangePropertyTriat'
super(ChangePropertyTrait,self).__init__()
@@ -5293,8 +5990,11 @@
# print(cmd)
com = cmd[0] + ':' + cmd[1].replace(',',r'\,') + ':' + cmd[2]
if cmd[2] == self.DIRECT:
- com += f'\,'+cmd[3].replace(':',r'\:')
+ com += f'\,'+cmd[3].replace(',',r'\\,').replace(':',r'\:')
+ elif cmd[2] == self.INCREMENT:
+ com += f'\,'+cmd[3].replace(',',r'\\,').replace(':',r'\:')
cmds.append(com)
+ # print(cmds)
return ','.join(cmds)
def decodeCommands(self,commands):
@@ -5305,6 +6005,8 @@
# print('parts',parts)
if parts[-1][0] == self.DIRECT:
parts = parts[:-1]+Trait.decodeKeys(parts[-1],',')
+ if parts[-1][0] == self.INCREMENT:
+ parts = parts[:-1]+Trait.decodeKeys(parts[-1],',')
ret.append(parts)
# print(commands,parts)
return ret
@@ -5840,7 +6542,7 @@
canStack = False,
ignoreGrid = False,
description = ''):
-
+ '''No stacking trait'''
selectionOptions = (select +
(self.IGNORE_GRID if ignoreGrid else '') +
bandSelect)
@@ -7319,6 +8021,7 @@
'''
return self.getAllElements(AtStart,single)
+registerElement(Game)
# --------------------------------------------------------------------
class BasicCommandEncoder(GameElement):
@@ -7326,6 +8029,8 @@
def __init__(self,doc,node=None):
super(BasicCommandEncoder,self).__init__(doc,self.TAG,node=node)
+registerElement(BasicCommandEncoder)
+
#
# EOF
#
@@ -8446,7 +9151,8 @@
vassalVersion = '3.6.7',
nonato = False,
nochit = False,
- counterScale = 1):
+ counterScale = 1,
+ resolution = 150):
'''Exports a PDF and associated JSON files to a VASSAL module.
Parameters
@@ -8473,6 +9179,8 @@
Make grids visible
vassalVersion : str
VASSAL version to encode this module for
+ resolution : int
+ Resolution for images (default 150)
'''
self._vmodname = vmodname
self._pdfname = pdfname
@@ -8487,6 +9195,7 @@
self._vassalVersion = vassalVersion
self._nonato = nonato
self._nochit = nochit
+ self._resolution = resolution
self._counterScale = counterScale
self._battleMark = 'wgBattleMarker'
self._battleMarks = []
@@ -8572,6 +9281,7 @@
v(f'Tutorial log: {self._tutorial}')
v(f'Patch scripts: {self._patch}')
v(f'Visible grids: {self._visible}')
+ v(f'Resolution: {self._resolution}')
v(f'Scale of counters: {self._counterScale}')
def setup(self):
@@ -8704,6 +9414,7 @@
args = ['pdftocairo',
'-transp',
'-singlefile',
+ '-r', str(self._resolution),
'-f', str(page),
'-l', str(page),
'-png' ]
@@ -8772,9 +9483,9 @@
imgsinfo = self.getImagesInfo()
if len(imgsinfo) - 1 != docinfo['Pages']:
- raise RuntimeError(f'Number of pages in {pdfname} '
- f'(doc["Pages"]) not matched in JSON '
- f'{self._infoname} -> {len(imagesinfo)}')
+ raise RuntimeError(f'Number of pages in {self._pdfname} '
+ f'{docinfo["Pages"]} not matched in JSON '
+ f'{self._infoname} -> {len(imgsinfo)}')
with VerboseGuard(f'Converting {docinfo["Pages"]} '
f'pages in {self._pdfname}') as v:
@@ -9126,10 +9837,16 @@
'property': 'Phase',
'names': self._sides } })
turns.addHotkey(hotkey = self._clearMoved+'Phase',
- name = 'Clear moved markers')
+ name = 'Clear moved markers',
+ reportFormat = (f'{{{self._verbose}?('
+ f'"`Clear all moved markers, "+'
+ f'""):""}}'))
if len(self._battleMarks) > 0:
turns.addHotkey(hotkey = self._clearBattlePhs,
- name = 'Clear battle markers')
+ name = 'Clear battle markers',
+ reportFormat = (f'{{{self._verbose}?('
+ f'"`Clear all battle markers, "+'
+ f'""):""}}'))
self._dice = self._categories\
.get('die-roll',{})
@@ -9153,7 +9870,9 @@
# f'+" <img src=\'{die}-"+result1'
# f'+".png\' width=24 height=24>"'
f'}}'),
- resultWindow = True);
+ resultWindow = True,
+ windowX = str(int(67 * self._resolution/150)),
+ windowY = str(int(65 * self._resolution/150)));
sdie = symb.addDie(name = die);
for face, fdata in faces.items():
fn = fdata['filename']
@@ -10186,13 +10905,14 @@
# ----------------------------------------------------------------
def factionTraits(self,faction):
- traits = [ReportTrait(self._eliminateKey,
- self._restoreKey,
- self._trailKey),
+ offX = 36 * self._counterScale * self._resolution/150
+ offY = -38 * self._counterScale * self._resolution/150
+ traits = [#ReportTrait(self._eliminateKey,
+ # self._restoreKey,
+ # self._trailKey),
TrailTrait(),
RotateTrait(),
- MovedTrait(xoff = int( 36 * self._counterScale),
- yoff = int(-38 * self._counterScale)),
+ MovedTrait(xoff = int(offX),yoff = int(offY)),
DeleteTrait(),
SendtoTrait(mapName = 'DeadMap',
boardName = f'{faction} pool',
@@ -11308,7 +12028,10 @@
pc = p["coords"]
if j == 0: vv(f'',end='')
vv(f'[{pn}] ',end='',flush=True,noindent=True)
-
+
+ if pn.endswith(' flipped'):
+ pn = pn[:-len(' flipped')]
+
x, y = tran(*pc)
r = grid.addRegion(name = pn,
originx = x,
@@ -11499,7 +12222,7 @@
def addDie(self):
'''Add a `Die` element to the module
'''
- if self._dice is not None:
+ if self._dice is not None and len(self._dice) > 0:
return
self._game.addDiceButton(name = '1d6',
hotkey = self._diceKey)
@@ -11568,6 +12291,9 @@
ap.add_argument('-S','--counter-scale',
type=float, default=1,
help='Scale counters by factor')
+ ap.add_argument('-R','--resolution',
+ type=int, default=150,
+ help='Resolution of images')
args = ap.parse_args()
@@ -11600,6 +12326,7 @@
vassalVersion = args.vassal_version,
nonato = args.no_nato_prototypes,
nochit = args.no_chit_information,
+ resolution = args.resolution,
counterScale = args.counter_scale)
exporter.run()
except Exception as e:
Modified: trunk/Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.chit.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.chit.code.tex 2024-02-03 21:13:44 UTC (rev 69691)
+++ trunk/Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.chit.code.tex 2024-02-03 21:13:58 UTC (rev 69692)
@@ -84,7 +84,7 @@
chit/symbol/.style={scale=.4,transform shape},
chit/parts/.style={shape=rectangle,transform shape},
chit/factors/.style={chit/parts,anchor=south},
- chit/left/.style={chit/parts,anchor=south,rotate=90},
+ chit/left/.style={chit/parts,anchor=base,rotate=90},%Anchor was south
chit/right/.style={chit/parts,anchor=north,rotate=90},
chit/upper left/.style={chit/parts,anchor=north west},
chit/upper right/.style={chit/parts,anchor=north east},
@@ -116,7 +116,8 @@
\tikzset{%
chit/.code={%
- \pgfkeys{/tikz/transform shape,/tikz/shape=chit}
+ \chit at dbg{2}{chit arguments are `#1'}%
+ \pgfkeys{/tikz/transform shape,/tikz/shape=chit}%
\pgfkeys{/chit/.cd,#1}}}
\newcounter{chit at id}\setcounter{chit at id}{0}
\def\chit at n@to#1#2{%
@@ -441,7 +442,7 @@
^^J Name: `#3'}
\let\name\pgfutil at empty%
\chit at dbg{1}{=== Before chit node}%
- \node[chit={every chit/.try,id=#3,#1}] (tmp) at (#2) {};
+ \node[chit={/tikz/every chit/.try,id=#3,#1}] (tmp) at (#2) {};
\chit at dbg{2}{=== After chit node}%
\ifx|#3|\relax%
\else%
@@ -602,8 +603,9 @@
\def\chit at oob@rowupdate(#1,#2)#3#4{%
\chit at dbg{2}{ Row update c=`#1',r=`#2',s=`#3',e=`#4'}
%\pgfmathparse{ifthenelse(#1>0,#2-#3,#2)}%
- \pgfmathparse{#2-#3)}%
+ \pgfmathparse{#2-#3-#4}%
\xdef#2{\pgfmathresult}%
+ \xdef#1{0}%\pgfmathresult}%
%\xdef#1{0}
\chit at dbg{2}{ \space\space-> update `\string#2'=#2}
}
@@ -617,6 +619,7 @@
}
\newif\ifwg at oob@inv\wg at oob@invfalse
\def\chit at oob@spacer{hspace}
+\def\chit at oob@vspacer{vspace}
\def\wg at star@oob{\wg at oob@invtrue\wg at oob}
\def\wg at nostar@oob{\wg at oob@invfalse\wg at oob}
\def\oob{%
@@ -626,6 +629,8 @@
}
\def\wg at oob#1#2#3#4{
\def\r{0}
+ \pgfmathparse{#3*(#2-1)}%
+ \edef\a{\pgfmathresult}
\chit at dbg{2}{OOB: `#1'}
\foreach[count=\ti from 0] \t/\y in #1{
\xdef\o{\r}
@@ -644,20 +649,28 @@
\ifx\m\@empty\def\m{1}\fi
\ifx\u\m\def\m{1}\fi
\foreach \n in {1,...,\m}{%
- \chit at dbg{2}{OOB Chit is `\u'}%
+ \chit at dbg{2}{OOB Chit is `\u' `\chit at oob@spacer'}%
\ifx\u\chit at oob@spacer%
\chit at dbg{3}{Chit `\u' is spacer `\chit at oob@spacer'}
\pgfmathparse{\c+#4}%
\xdef\c{\pgfmathresult}%
- \else
- \ifnum\chitdbglvl>2%
- \node[minimum width=#3cm,minimum height=#3cm,
- draw,transform shape] at (\c,\r) {};
+ \else%
+ \ifx\u\chit at oob@vspacer%
+ \chit at dbg{3}{Chit `\u' is vspacer `\chit at oob@vspacer'}
+ \pgfmathparse{ifthenelse(abs(\c)<0.0001,0,#3)}
+ \xdef\ll{\pgfmathresult}
+ \chit at dbg{2}{\string\ll=`\ll'}
+ \chit at oob@rowupdate(\c,\r){\ll}{#4}
+ \else
+ \ifnum\chitdbglvl>2%
+ \node[minimum width=#3cm,minimum height=#3cm,
+ draw,transform shape] at (\c,\r) {};
+ \fi
+ \ifx\u\chit at blank\else%
+ \chit[\u=\ti,zone oob point={\u}{\c}{\r}](\c,\r);%
+ \fi%
+ \chit at oob@cellupdate(\c,\r){#2}{#3}{\y}
\fi
- \ifx\u\chit at blank\else%
- \chit[\u=\ti,zone oob point={\u}{\c}{\r}](\c,\r);%
- \fi%
- \chit at oob@cellupdate(\c,\r){#2}{#3}{\y}
\fi
}
\fi
@@ -688,7 +701,7 @@
% \chit at dbg{2}{ \space Breaking loop \rr\space > \y}%
% \breakforeach%
%\else%
- \chit at oob@rowupdate(\c,\r){#3}{#4}
+ \chit at oob@rowupdate(\c,\r){#3}{0}% Extra spacing?
%\fi
}
\fi
@@ -699,14 +712,168 @@
}
\chit at dbg{3}{End of OOB (c=`\c',r=`\r',y=`\y')}
\@ifnextchar;{\@gobble}{}}
+\def\wg at star@hoob{\wg at oob@invtrue\wg at hoob}
+\def\wg at nostar@hoob{\wg at oob@invfalse\wg at hoob}
+\def\hoob{%
+ \@ifstar{\wg at star@hoob%
+ }{\wg at nostar@hoob%
+ }%
+}
+\def\wg at hoob#1#2#3#4{
+ \def\r{0}
+ \def\c{0}
+ \pgfmathparse{#3*(#2-1)}%
+ \edef\a{\pgfmathresult}
+ \chit at dbg{2}{OOB: `#1'}
+ \foreach[count=\ti from 0] \t/\y in #1{
+ \xdef\o{\r}
+ % \def\c{0}
+ \ifx\t\y\def\y{0}\fi
+ \chit at dbg{2}{Turn \ti\space(\r,\t,y=\y):'}
+ \ifx\t\empty\else
+ % Count how many are left for this turn
+ \chit at dbg{2}{At start of turn \t\space\string\c=\c}
+ \def\l{\c}%
+ \let\ig\empty
+ \foreach \u/\m in \t{
+ \ifx\ig\empty
+ \ifx\u\empty\else
+ \ifx\u\m\def\m{1}\fi
+ \ifx\u\chit at oob@spacer%
+ \pgfmathparse{\l+\m*#4}\xdef\l{\pgfmathresult}
+ \chit at dbg{2}{Got \m\space hspace (#4) -> \l}
+ \else
+ \ifx\u\chit at oob@vspace%
+ \xdef\ig{1}
+ \chit at dbg{2}{Got vspace -> \l (\ig)}
+ \else
+ \pgfmathparse{\l+\m*#3}
+ \xdef\l{\pgfmathresult}
+ \chit at dbg{2}{Got \m\space units -> \l}
+ \fi
+ \fi
+ \fi
+ \fi}
+ % Check if there's enough room
+ \chit at dbg{2}{To fill the rest of turn needs `\l' compared to
+ `\a' (#3*(#2-1))}
+ \pgfmathparse{ifthenelse(abs(\l)>=#3*(#2-1),0,1}%
+ \xdef\l{\pgfmathresult}%
+ \chit at dbg{2}{Break or not `\l'}
+ \ifnum\l=0\chit at oob@turnupdate(\c,\r){#3}{#4}\fi
+ \fi
+ \ifwg at oob@inv%
+ \pic[transform shape] at (\c+.5*#3,\r) {chit/oob turn=\ti};% was dx=0.5
+ \else
+ \pic[transform shape] at (\c+-.5*#3,\r) {chit/oob turn=\ti};% was dx=-0.5
+ \fi%
+ %\chit at oob@cellupdate(\c,\r){#2}{#3}{\y}
+ \ifx\t\empty\else%
+ \def\lv{0}
+ \foreach \u/\m in \t{
+ %% \chit at dbg{2}{ `\u'=`\m'}
+ \ifx\u\empty\else
+ \ifx\m\@empty\def\m{1}\fi
+ \ifx\u\m\def\m{1}\fi
+ \foreach \n in {1,...,\m}{%
+ \chit at dbg{2}{OOB Chit is `\u' `\chit at oob@spacer'}%
+ \ifx\u\chit at oob@spacer%
+ \chit at dbg{3}{Chit `\u' is spacer `\chit at oob@spacer'}
+ \pgfmathparse{\c+#4}%
+ \xdef\c{\pgfmathresult}%
+ \else%
+ \ifx\u\chit at oob@vspacer%
+ \chit at dbg{3}{Chit `\u' is vspacer `\chit at oob@vspacer'}
+ \pgfmathparse{ifthenelse(abs(\c)<0.0001,0,#3)}
+ \xdef\ll{\pgfmathresult}
+ \chit at dbg{2}{\string\ll=`\ll'}
+ \chit at oob@rowupdate(\c,\r){\ll}{#4}
+ \xdef\lv{1}
+ \else
+ \ifnum\chitdbglvl>2%
+ \node[minimum width=#3cm,minimum height=#3cm,
+ draw,transform shape] at (\c,\r) {};
+ \fi
+ \ifx\u\chit at blank\else%
+ \chit[\u=\ti,zone oob point={\u}{\c}{\r}](\c,\r);%
+ \fi%
+ \chit at oob@cellupdate(\c,\r){#2}{#3}{\y}
+ \fi
+ \fi
+ }
+ \fi
+ }
+ \fi
+ \chit at dbg{2}{ End of chits in turn
+ \ti\space(c=`\c',r=`\r',o='\o',y='\y')}
+ % --- Not relevant, I think
+ % IF no units where given, then we force \c to be non-zero so that
+ % \chit at oob@turnupdate increments the row
+ % \ifx\t\@empty
+ % \def\c{#3}
+ % \chit at dbg{2}{ Turn is empty, set c=`\c'}
+ % \fi
+ % ---
+ %\ifnum\y<0% No explicit number of rows given
+ % \def\c{#3}
+ % \chit at dbg{2}{ No explicit number of rows given, set c=`\c'}
+ %\fi
+ % In case the user gave and explicit number of rows, add the rows
+ % that are missing. \y is initially set to the number of
+ % requested rows, and then decremented every time we go down one
+ % row. So if the number of rows we did so far is N, and the
+ % requested number of rows is M, then the loop below adds M-N
+ % rows.
+ \ifnum\y>0%
+ \chit at dbg{2}{ Looping rows from 2 to \y, break when row > \y}%
+ \foreach \rr in {2,...,\y}{
+ %\ifnum\rr>\y% A little funny, but \y can be negative!
+ % \chit at dbg{2}{ \space Breaking loop \rr\space > \y}%
+ % \breakforeach%
+ %\else%
+ \chit at oob@rowupdate(\c,\r){#3}{0}% Extra spacing?
+ %\fi
+ }
+ \fi
+ % --- Not relevant I think
+ % This will zero \c. However, if on entry |\c|>0, then we also
+ % increment the row
+ % \chit at oob@turnupdate(\c,\r){#3}{#4}
+ % ---
+ % Horizontal spacer
+
+ %\pgfmathparse{ifthenelse(abs(\c)>=\a,1,0)}\xdef\l{\pgfmathresult}
+ \pgfmathparse{\c+1.5*#4}%
+ \xdef\c{\pgfmathresult}%
+ \ifnum\lv=1%
+ \pgfmathparse{\r-#4}
+ \chit at oob@rowupdate(\c,\r){0}{#4}
+ \else
+ \chit at oob@cellupdate(\c,\r){#2}{#3}{\y}
+ \ifnum\y<0
+ \chit at oob@turnupdate(\c,\r){#3}{#4}
+ \else
+ \fi
+ \fi
+ % \xdef\y{0}
+ \chit at dbg{2}{End of turn \ti\space(c=`\c',r=`\r',o='\o',y='\y')}
+ }
+ \chit at dbg{3}{End of OOB (c=`\c',r=`\r',y=`\y')}
+ \@ifnextchar;{\@gobble}{}}
\tikzset{
chit/cell background/.style={fill=black},
+ %chit/cell background flipped/.style={fill=black},
blank chit/.style={/chit/frame={draw=none,fill=none}},
+ chit/grid lines/.style={dashed},
}
\def\chit at blank{blank chit}
\def\chit at cellbg(#1,#2)#3{%
\draw[chit/cell background](#1-#3/2,#2-#3/2) rectangle++(#3,#3);
}
+\def\chit at celldblbg(#1,#2)#3{%
+ \draw[chit/cell background,chit/cell background flipped/.try]%
+ (#1-#3/2,#2-#3/2) rectangle++(#3,#3);
+}
\newif\ifchits at reset\chits at resettrue
\def\chit at sng@cellupdate(#1,#2)#3#4{%
\chit at dbg{2}{Current `#1' vs `#4'*(`#3'+1)}
@@ -746,6 +913,17 @@
\fi%
}%
\@ifnextchar;{\@gobble}{}}
+\def\chitgrid#1#2#3{%
+ \pgfmathparse{#3/2}\edef\rmin{\pgfmathresult}%
+ \pgfmathparse{#2*#3-#3/2}\edef\rmax{\pgfmathresult}%
+ %\draw[red](-#3/2,\rmin)rectangle(#3*#1-#3/2,-\rmax);
+ \foreach \cc in {0,...,#1}{
+ \draw[chit/grid lines] (\cc*#3-#3/2,3*#3/4)--(\cc*#3-#3/2,-\rmax-#3/4);}
+ %\chit at dbg{0}{Drawing horizontal lines from `\rmin, `-\rmin', ..., `-\rmax'}
+ \foreach \rr in {\rmin,-\rmin,...,-\rmax}{
+ %\chit at dbg{0}{Horizontal line at `\rr'}
+ \draw[chit/grid lines] (-3*#3/4,\rr)--(#1*#3-#3/4,\rr);}
+}
\def\chit at dbl@flip(#1,#2)#3{%
\pgfmathparse{-#1}%
\xdef\mc{\pgfmathresult}%
@@ -780,7 +958,7 @@
\chit at cellbg(\c,\r){#3}
\chit[\u=\ti](\c,\r)
\chit at dbl@flip(\c,\r){#3}
- \chit at cellbg(\mc,\r){#3}
+ \chit at celldblbg(\mc,\r){#3}
\chit[\u\space flipped=\ti,zone turn=\t,zone mult=\n](\mc,\r)
\chit at dbl@cellupdate(\c,\r){#2}{#3}
\fi
@@ -792,7 +970,26 @@
\draw[dashed](0,-3*#3/4)--(0,\r-#3/4);%
\draw[dashed,<-] (#3/5,-2*#3/3)--(#3/2,-2*#3/3) node[transform shape,anchor=west]{Back};%
\draw[dashed,<-] (-#3/5,-2*#3/3)--(-#3/2,-2*#3/3) node[transform shape,anchor=east]{Front};%
+ % \foreach \cc in {0,...,#2}{
+ % \draw[dashed] (\cc*#3,-3*#3/4)--(\cc*#3,\r-#3/4);
+ % \draw[dashed] (-\cc*#3,-3*#3/4)--(-\cc*#3,\r-#3/4);}
+ % \pgfmathparse{#3/2}\edef\rmin{\pgfmathresult}%
+ % \chit at dbg{0}{Drawing horizontal lines from `-\rmin, `\rmin', ..., `\r'}
+ % \foreach \rr in {-\rmin,\rmin,...,\r}{
+ % \chit at dbg{0}{Horizontal line at `\rr'}
+ % \draw[dashed] (-#2*#3-#3/4,\rr)--(#2*#3+#3/4,\rr);}
\@ifnextchar;{\@gobble}{}}
+\def\doublechitgrid#1#2#3{%
+ \pgfmathparse{#3/2}\edef\rmin{\pgfmathresult}%
+ \pgfmathparse{#2*#3-#3/2}\edef\rmax{\pgfmathresult}%
+ \foreach \cc in {0,...,#1}{
+ \draw[chit/grid lines] (\cc*#3,-3*#3/4)--(\cc*#3,\rmax+#3/4);
+ \draw[chit/grid lines] (-\cc*#3,-3*#3/4)--(-\cc*#3,\rmax+#3/4);}
+ %\chit at dbg{0}{Drawing horizontal lines from `-\rmin, `\rmin', ..., `\rmax'}
+ \foreach \rr in {-\rmin,\rmin,...,\rmax}{
+ %\chit at dbg{0}{Horizontal line at `\rr'}
+ \draw[chit/grid lines] (-#1*#3-#3/4,\rr)--(#1*#3+#3/4,\rr);}
+}
\tikzset{%
battle marker/.pic={
\node[shape=circle,
@@ -817,7 +1014,7 @@
minimum size=8mm,
draw=black,
fill=#2,
- every odds marker/.try] at (.2,-.2) {#1};
+ every odds marker/.try] at (.16,-.16) {#1};
}
},
odds marker/.style args={#1,#2}{
@@ -1012,7 +1209,55 @@
\pgfpathlineto{\pgfpoint{-.253cm}{-.146cm}}
% \pgfusepath{draw} %draw interiaor
}}
+\usetikzlibrary{shadows.blur}
+\newif\ifwg at chit@drop\wg at chit@dropfalse
\tikzset{
+ chit has drop/.is if=wg at chit@drop,
+ chit has drop/.default=true,
+ chit has drop/.initial=false,
+ /tikz/render blur shadow/.add code={%
+ \chit at dbg{2}{Number of blur steps: \pgfbs at steps}%
+ \ifnum\pgfbs at steps=0\else
+ \chit at dbg{2}{Making shadow blur}%
+ }{\fi}}
+\tikzset{%
+ chit drop/.code={%
+ %% \message{^^J Args `#1'}%
+ \pgfkeysalso{%
+ chit has drop=true,
+ /tikz/blur shadow={shadow blur steps=5,
+ shadow opacity=25,
+ shadow xshift=.05cm,
+ shadow yshift=-.05cm,
+ shadow blur radius=.05cm,
+ #1}}%
+ \ifnum\pgfbs at steps=0%
+ \gdef\wg at drop@margin{0pt}%
+ \else%
+ \ifwg at chit@drop%
+ \pgfmathparse{
+ \pgfbs at radius+
+ veclen(
+ \pgfkeysvalueof{/tikz/shadow xshift},
+ \pgfkeysvalueof{/tikz/shadow yshift})}
+ \xdef\wg at drop@margin{\pgfmathresult pt}%
+ \else%
+ \gdef\wg at drop@margin{0pt}%
+ \fi
+ %% \message{^^J Drop margin is `\wg at drop@margin'
+ %% `\pgfbs at radius'
+ %% `\pgfkeysvalueof{/tikz/shadow xshift}',
+ %% `\pgfkeysvalueof{/tikz/shadow yshift}'}%
+ \fi%
+ },%
+ chit drop/.default=,%
+ no chit drop/.code={%
+ \pgfkeysalso{
+ /tikz/blur shadow={shadow blur steps=0}}
+ \gdef\wg at drop@margin{0pt}%
+ }
+}%
+\tikzset{
chit/text base/.style={
shape=rectangle,
inner sep=0pt,
Modified: trunk/Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.hex.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.hex.code.tex 2024-02-03 21:13:44 UTC (rev 69691)
+++ trunk/Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.hex.code.tex 2024-02-03 21:13:58 UTC (rev 69692)
@@ -524,6 +524,7 @@
\fi%
\@ifnextchar;{\@gobble}{}%
}
+\newif\if at hex@t at rot\@hex at t@rotfalse%
\tikzset{%
/hex/terrain/.search also={/tikz},%
/hex/terrain/.cd,%
@@ -531,6 +532,7 @@
image/.store in=\hex at t@image,%
code/.store in=\hex at t@code,%
clip/.store in=\hex at t@clip,%
+ random rotation/.is if=@hex at t@rot,
pic/.default=,
image/.default=,
code/.default=,
@@ -591,7 +593,15 @@
\@ifundefined{hex at t@image}{\let\hex at t@image\empty}{}
\@ifundefined{hex at t@code}{\let\hex at t@code\empty}{}
\@ifundefined{hex at t@code}{\let\hex at t@code\empty}{}
- \ifx\hex at t@code\empty\else\hex at t@code\fi%
+ \def\hex at t@angle{0}%
+ \if at hex@t at rot%
+ \pgfmathrandominteger{\hex at t@angle}{0}{5}
+ \pgfmathparse{int(60*\hex at t@angle)}\edef\hex at t@angle{\pgfmathresult}%
+ \fi%
+ \hex at dbg{5}{Will rotate terrain by `\hex at t@angle'}%
+ \scope[rotate=\hex at t@angle]%
+ \ifx\hex at t@code\empty\else\hex at t@code\fi%
+ \endscope% End rotate code
% If we have no image, check if we have pictures.
\ifx\hex at t@image\empty%
\hex at dbg{8}{No terrain images}%
@@ -600,7 +610,9 @@
\hex at dbg{5}{Terrain pictures}%
\pgfpointorigin\wg at tmpa=\pgf at x\wg at tmpb=\pgf at y%
\foreach \i in \hex at t@pic{%
- \wg at pic@all{\i}{}{\the\wg at tmpa,\the\wg at tmpb}{}}%
+ \wg at pic@all{\i}{}{\the\wg at tmpa,\the\wg at tmpb}{%
+ rotate=\hex at t@angle,
+ transform shape}}%
\fi% We have pictures.
\else % We have images
\hex at dbg{5}{Terrain images}%
@@ -610,6 +622,7 @@
\expandafter\wg at node{%
\includegraphics[width=2cm]{\i}}\@endwg at node %
{}{\wg at tmpa,\wg at tmpb}{%
+ rotate=\hex at t@angle,%
shape=rectangle,%
anchor=center,%
transform shape,%
@@ -12302,11 +12315,12 @@
\xdef\hex at r@p{\hex at r@p ($(300:\hex at r@r)+(-120:\hex at r@t/2)$)}
\fi
\ifhex at r@ne
- \xdef\hex at r@p{\hex at r@p --cycle}
+ %\xdef\hex at r@p{\hex at r@p --cycle}
+ \xdef\hex at r@p{\hex at r@p -- (0:\hex at r@r)}
\else
\xdef\hex at r@p{\hex at r@p --(.5:\hex at r@r)}
\fi
- \hex at dbg{4}{Ridge along se: `\hex at r@p'}
+ \hex at dbg{4}{Ridge along south east: `\hex at r@p'}
\fi
\hex at dbg{3}{ Ridges path: \hex at r@p}
% \draw[red] \hex at r@p;
@@ -12446,7 +12460,7 @@
\ifnum#1<10 0\fi%
#1}
\def\hex at do@label{%
- \hex at dbg{1}{Hex label: `\meaning\hex at label'}%
+ \hex at dbg{3}{Hex label: `\meaning\hex at label'}%
\edef\hex at l@tmp{[%
/hex/label/.cd,%
rotate=0,%
Modified: trunk/Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.util.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.util.code.tex 2024-02-03 21:13:44 UTC (rev 69691)
+++ trunk/Master/texmf-dist/tex/latex/wargame/tikzlibrarywargame.util.code.tex 2024-02-03 21:13:58 UTC (rev 69692)
@@ -293,12 +293,17 @@
save clip/.initial={false},
}
\def\wg at setcornersarched#1{%
- \ifx|#1|\else%
- \edef\pgf at corner@arc{{#1}{#1}}%
- \pgf at arccornerstrue%
- \ifdim#1=0pt%
- \pgf at arccornersfalse%
- \fi\fi}
+ \def\arg{#1}%
+ \let\isarched\relax% Cannot set \ifpgf at arccorners directly inside
+ % other \if
+ \ifx\arg\@empty\else%
+ \edef\pgf at corner@arc{{#1}{#1}}%
+ \let\isarched\pgf at arccornerstrue%
+ \ifdim#1=0pt%
+ \let\isarched\pgf at arccornersfalse%
+ \fi%
+ \fi%
+ \isarched}
\newdimen\wg at lw@scaled\wg at lw@scaled=1pt
\def\wg at getscale{%
\pgfgettransformentries{%
Modified: trunk/Master/texmf-dist/tex/latex/wargame/wargame.beach.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/tex/latex/wargame/wargame.city.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/tex/latex/wargame/wargame.light_woods.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/tex/latex/wargame/wargame.mountains.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/tex/latex/wargame/wargame.rough.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/tex/latex/wargame/wargame.swamp.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/tex/latex/wargame/wargame.town.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/tex/latex/wargame/wargame.village.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/tex/latex/wargame/wargame.woods.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/tex/latex/wargame/wgexport.cls
===================================================================
--- trunk/Master/texmf-dist/tex/latex/wargame/wgexport.cls 2024-02-03 21:13:44 UTC (rev 69691)
+++ trunk/Master/texmf-dist/tex/latex/wargame/wgexport.cls 2024-02-03 21:13:58 UTC (rev 69692)
@@ -76,12 +76,26 @@
\def\end at info{%
\let\mk at i\oldmk at i%
\mk at w{ \space \@rbchar,}}
-\newcommand\chitimages[2][]{%
+\def\wg at add@drop at margin{%
+ \@ifundefined{wg at drop@margin}{}{
+ \dimen0=\wg at drop@margin
+ % \ifwg at chit@drop
+ \ifdim\dimen0>0pt%
+ \path ($(current bounding box.north east)+(45:\wg at drop@margin)$)
+ -- ($(current bounding box.south west)+(225:\wg at drop@margin)$);
+ \fi}}
+\def\chitimages{%
+ \@ifnextchar[{\@chitimages}{\chitimages[]}%]
+}%
+\def\@chitimages[#1]{%
+ \@ifnextchar[{\@@chitimages[#1]}{\@@chitimages[#1][]}%]
+}%
+\def\@@chitimages[#1][#2]#3{%
\begingroup%
\let\chit at report\do at chit@report%
\let\natoapp at report\do at natoapp@report%
- \chit at dbg{2}{chits to make images of `#2'}%
- \foreach[count=\ti from 0] \t/\x in #2{%
+ \chit at dbg{2}{chits to make images of `#3'}%
+ \foreach[count=\ti from 0] \t/\x in #3{%
\chit at dbg{2}{^^JRow: `\t' (`\x')}
\ifx\t\empty\else% Ignore empty rows
\chit at dbg{5}{^^JSubcategory: `\x' (default `#1')}
@@ -91,14 +105,17 @@
\ifx\u\empty\else% Ignore empty cells
\ifx\u\chit at blank\else%
\chit at dbg{2}{Next chit `\u' with possible multiplicity `\m'}%
- \ifx\m\@empty\def\m{1}\fi% If not multiplicity defined
+ \ifx\m\@empty\def\m{1}\fi% If no multiplicity defined
\ifx\u\m\def\m{1}\fi% If the same as unit
\chit at dbg{2}{Next chit `\u' multiplicity `\m'}%
%% We only make one copy of the chit, since we can duplicate
%% it in VASSAL
\info*{\u}{counter}{\x}
- \begin{tikzpicture}
+ \nopagecolor%
+ \gdef\wg at drop@margin{0pt}%
+ \begin{tikzpicture}[chit has drop=false,#2]
\chit[\u=\ti]%
+ \wg at add@drop at margin%
\end{tikzpicture}
\end at info%
%% \foreach \n in {1,...,\m}{% Make a number of copies
@@ -120,11 +137,17 @@
\chit at dbg{2}{End of outer loop}%
\endgroup%
}
-\newcommand\doublechitimages[2][]{%
+\def\doublechitimages{%
+ \@ifnextchar[{\@doublechitimages}{\doublechitimages[]}%]
+}%
+\def\@doublechitimages[#1]{%
+ \@ifnextchar[{\@@doublechitimages[#1]}{\@@doublechitimages[#1][]}%]
+}%
+\def\@@doublechitimages[#1][#2]#3{%
\begingroup%
\let\chit at report\do at chit@report%
\let\natoapp at report\do at natoapp@report%
- \foreach[count=\ti from 0] \t/\x in #2{%
+ \foreach[count=\ti from 0] \t/\x in #3{%
\ifx\t\empty\else% Ignore empty rows
\chit at dbg{5}{^^JSubcategory: `\x' (default `#1')}
% Take sub-category or default
@@ -141,13 +164,18 @@
%% We only make one copy of the chit, since we can duplicate
%% it in VASSAL
\info*{\u}{counter}{\x}%
- \begin{tikzpicture}%
+ \nopagecolor%
+ \gdef\wg at drop@margin{0pt}%
+ \begin{tikzpicture}[chit has drop=false,#2]%
\chit[\u=\ti]%
+ \wg at add@drop at margin%
\end{tikzpicture}%
\end at info%
\info*{\s}{counter}{\x}%
- \begin{tikzpicture}%
+ \nopagecolor%
+ \begin{tikzpicture}[chit has drop=false,#2]%
\chit[\s=\ti]%
+ \wg at add@drop at margin%
\end{tikzpicture}%
\end at info%
%% \foreach \n in {1,...,\m}{% Make a number of copies
@@ -235,7 +263,7 @@
\def\hex at col{0}%
\def\hex at row{0}%
\node[hex,inner sep=0,outer sep=0]{%
- \message{^^JHex label: `\meaning\hex at label'}%
+ %\message{^^JHex label: `\meaning\hex at label'}%
\global\let\mk at label\hex at label}}}%
\info*{#2}{#1}{#3}%
\mk at w{ \mk at i "zones": \@lbchar}%
@@ -242,7 +270,7 @@
\edef\mk at i{\mk at i\space}
%% Everything is made into centimeters
\mk at w{ \mk at i "units": "cm",}
- \hex at dbg{0}{Label: `\meaning\mk at label'}
+ \hex at dbg{3}{Label: `\meaning\mk at label'}
\@ifundefined{mk at label}{}{\mk at w{ \mk at i "labels": "\mk at label",}}
%% Write out coordinate options as "coords" object
\mk at w{ \mk at i"coords": \@lbchar}%
@@ -345,7 +373,7 @@
\mk at w{ \mk at i\@rbchar}%
\end at info%
}
-\def\wg at gennumberm@rkers#1#2#3{
+\def\wg at gennumberm@rkers#1#2#3#4{
\message{^^JNumbered markers: Type=`#1' Max=`#2' Category=`#3'}
\def\markers{}
\def\keys{}
@@ -353,15 +381,22 @@
\xdef\keys{/tikz/#1 \i/.style={/tikz/#1=\i},\keys}
\xdef\markers{\markers,#1 \i}}
{%
- \nopagecolor\pgfkeysalsofrom{\keys}\chitimages[#3]{\markers}}}%
+ \nopagecolor\pgfkeysalsofrom{\keys}\chitimages[#3][#4]{\markers}}}%
\tikzset{
wg hidden unit/.pic={},
wg hidden unit/.style={
chit={
+ no chit drop,
frame={draw=none,fill=none},
full=wg hidden unit}}}
-\DeclareRobustCommand\battlemarkers[2][BattleMarkers]{%
- \wg at gennumberm@rkers{battle marker}{#2}{#1}%
+\def\battlemarkers{%
+ \@ifnextchar[{\@battlemarkers}{\battlemarkers[]}%]
+}%
+\def\@battlemarkers[#1]{%
+ \@ifnextchar[{\@@battlemarkers[#1]}{\battlemarkers[#1][BattleMarkers]}%]
+}%
+\def\@@battlemarkers[#1][#2]#3{%
+ \wg at gennumberm@rkers{battle marker}{#3}{#2}{#1}%
\message{^^JMake a hidden unit and add to Markers category}
{%
\nopagecolor%
@@ -368,59 +403,80 @@
\chitimages[Markers]{{wg hidden unit}}%
%
\info{battle-marker-icon}{icon}{}%
- \tikz[scale=.7,transform shape]{\pic{battle marker=0};}%
+ \tikz[scale=.7,transform shape,auto icon more/.try]{%
+ \pic{battle marker=0};}%
\info{clear-battles-icon}{icon}{}
- \tikz[scale=.4,transform shape]{%
+ \tikz[scale=.4,transform shape,auto icon more/.try]{%
\pic{eliminate icon};
\pic[scale=.7,transform shape] at (-.3,0) {battle marker=0};}%
}%
}
-\def\wg at gencolorm@rkers#1#2#3{%
+\def\wg at gencolorm@rkers#1#2#3#4{%
\def\markers{}
\def\keys{}
- \foreach \o/\f in {#2}{%
+ \foreach \o/\f/\n [count=\i] in {#2}{%
+ \ifx\n\f\def\n{\o}\fi%
\ifx\o\f\def\f{white}\fi%
- \message{^^JOdds marker `#1 \o' w/fill `\f'}%
- \xdef\keys{/tikz/#1 \o/.style={/tikz/#1={\o,\f}},\keys}
- \xdef\markers{\markers,#1 \o}}
- {\nopagecolor\pgfkeysalsofrom{\keys}\chitimages[#3]{\markers}}}%
-\DeclareRobustCommand\oddsmarkers[2][OddsMarkers]{%
- \wg at gencolorm@rkers{odds marker}{#2}{#1}%
+ \message{^^JColour no \i marker `#1 \n' w/fill `\f' text `\o'}%
+ \protected at xdef\keys{/tikz/#1 \n/.style={/tikz/#1={\o,\f}},\keys}
+ \xdef\markers{\markers,#1 \n}
+ }%
+ {%
+ \nopagecolor%
+ \pgfkeysalsofrom{\keys}%
+ \chitimages[#3][#4]{\markers}%
+ }%
+}%
+\def\oddsmarkers{%
+ \@ifnextchar[{\@oddsmarkers}{\oddsmarkers[]}%]
+}%
+\def\@oddsmarkers[#1]{%
+ \@ifnextchar[{\@@oddsmarkers[#1]}{\oddsmarkers[#1][OddsMarkers]}%]
+}%
+\def\@@oddsmarkers[#1][#2]#3{%
+ \wg at gencolorm@rkers{odds marker}{#3}{#2}{#1}%
\info{odds-battles-icon}{icon}{}
- \tikz[scale=.5,transform shape]{\pic{odds marker={?:?,white}}}
+ \tikz[scale=.5,transform shape,auto icon more/.try]{%
+ \pic{odds marker={?:?,white}}}
\info{resolve-battles-icon}{icon}{}
- \tikz[scale=.3,transform shape]{%
+ \tikz[scale=.3,transform shape,auto icon more/.try]{%
\pic{dice};
\pic[scale=1.2,transform shape] at (-.2,-.2) {battle marker=0};}%
}
-\DeclareRobustCommand\resultmarkers[2][ResultMarkers]{%
- \wg at gencolorm@rkers{result marker}{#2}{#1}}
-\DeclareRobustCommand\commonicons[2]{%
+\def\resultmarkers{%
+ \@ifnextchar[{\@resultmarkers}{\resultmarkers[]}%]
+}%
+\def\@resultmarkers[#1]{%
+ \@ifnextchar[{\@@resultmarkers[#1]}{\resultmarkers[#1][ResultMarkers]}%]
+}%
+\def\@@resultmarkers[#1][#2]#3{%
+ \wg at gencolorm@rkers{result marker}{#3}{#2}{#1}}%
+\DeclareRobustCommand\commonicons[3][]{%
\begingroup%
\nopagecolor%
- \tikzset{icon/.style={scale=.4,transform shape}}%
+ \tikzset{auto icon/.style={scale=.4,transform shape,#1}}%
%
\info{pool-icon}{icon}{}
- \tikz[icon]{\pic{pool icon};}
+ \tikz[auto icon,auto icon more/.try]{\pic{pool icon};}
%
\info{oob-icon}{icon}{}%
- \tikz[icon]{\pic{oob icon={#1}{#2}};}%
+ \tikz[auto icon,auto icon more/.try]{\pic{oob icon={#2}{#3}};}%
%
\info{flip-icon}{icon}{}%
- \tikz[icon]{\pic{flip icon};}%
+ \tikz[auto icon,auto icon more/.try]{\pic{flip icon};}%
%
\info{eliminate-icon}{icon}{}%
- \tikz[icon]{\pic{eliminate icon};}%
+ \tikz[auto icon,auto icon more/.try]{\pic{eliminate icon};}%
%
\info{restore-icon}{icon}{}%
- \tikz[icon]{\pic{restore icon};}%
+ \tikz[auto icon,auto icon more/.try]{\pic{restore icon};}%
%
\info{dice-icon}{icon}{}%
- \tikz[icon,scale=.9]{\pic{dice};}%
+ \tikz[auto icon,scale=.9,auto icon more/.try]{\pic{dice};}%
%
\info{unit-icon}{icon}{}%
- \tikz[icon,scale=.7]{%
- \chit[fill=#1,
+ \tikz[auto icon,scale=.7,auto icon more/.try]{%
+ \chit[fill=#2,
symbol={[
scale line widths,
line width=1pt,
@@ -428,7 +484,29 @@
command=land,
main=infantry,
scale=1.3](0,-.15)}]}%
- \endgroup%
+ %
+ \info{layer-icon}{icon}{}%
+ \begin{tikzpicture}[scale=.25]
+ \foreach \i in {-1,0,1}{
+ \scoped[shift={(0,\i*.15)}]{
+ \draw[black,fill=white] (-.5,0)
+ --(0,.3)--(.5,0)--(0,-.3)--cycle;
+ }
+ }
+ \end{tikzpicture}%
+ %
+ \info{los-icon}{icon}{}
+ \begin{tikzpicture}[scale=.25]
+ \draw[scale line widths,line width=2pt,fill=white](-.5,0)
+ to[out=70,in=110] (.5,0)
+ to[out=-110,in=-70] cycle;
+ \begin{scope}[even odd rule]
+ \clip circle(.2);
+ \fill circle(.2) (125:.18) circle(.1);
+ \end{scope}
+ \end{tikzpicture}%
+ %
+ \endgroup%
}
\def\dice{%
\@ifnextchar[{\wg at dice}{\wg at dice[]}%]
@@ -440,9 +518,11 @@
\foreach \v/\p in {#5}{%
\info{#3-\v}{die-roll}{#3}
\tikz[#1]{
- \node[shape=#4,transform shape,draw=none,fill=black,opacity=.5]
- at (.05,-.03){};
- \node[shape=#4,#2,transform shape]{\p};}}}
+ %\node[shape=#4,transform shape,draw=none,fill=black,opacity=.5]
+ %at (.05,-.03){};
+ \node[shape=#4,#2,transform shape,
+ chit drop
+ ]{\p};\wg at add@drop at margin{}}}}
\tikzset{
zone turn/.store in=\zone at turn,
zone mult/.store in=\zone at mult
@@ -502,6 +582,27 @@
\mk at w{ \mk at i\space "end": 0}
\mk at w{ \mk at i \@rbchar}
}
+\tikzset{
+ chit drop margin/.store in=\wg at drop@margin,
+ chit drop shadows/.code={
+ \pgfkeysalso{%
+ /tikz/every chit node/.prefix style={chit drop={#1}},
+ /tikz/chit has drop=true}
+ },
+ chit drop shadows/.default=,
+ marker drop shadows/.code={
+ \pgfkeysalso{%
+ /tikz/every battle marker/.prefix style={chit drop={#1}},
+ /tikz/every odds marker/.prefix style={chit drop={#1}},
+ /tikz/every result marker/.prefix style={chit drop={#1}},
+ /tikz/auto icon more/.prefix style={no chit drop}}},
+ marker drop shadows/.default={
+ chit has drop=false,
+ shadow xshift=0.04cm,
+ shadow yshift=-0.04cm,
+ shadow blur radius=0.04cm}
+}
+
%% Local Variables:
%% mode: LaTeX
%% End:
Modified: trunk/Master/texmf-dist/tex/latex/wargame/wgexport.py
===================================================================
--- trunk/Master/texmf-dist/tex/latex/wargame/wgexport.py 2024-02-03 21:13:44 UTC (rev 69691)
+++ trunk/Master/texmf-dist/tex/latex/wargame/wgexport.py 2024-02-03 21:13:58 UTC (rev 69692)
@@ -208,6 +208,8 @@
ALT_SHIFT = ALT+SHIFT
NONE = '\ue004'
NONE_MOD = 0
+
+# --------------------------------------------------------------------
def key(let,mod=CTRL):
'''Encode a key sequence
@@ -220,6 +222,8 @@
Modifier mask
'''
return f'{ord(let)},{mod}'
+
+# --------------------------------------------------------------------
#
def hexcolor(s):
if isinstance(s,str):
@@ -241,6 +245,7 @@
return rgb(int(r*256),int(g*256),int(b*256))
+# --------------------------------------------------------------------
# Colour encoding
def rgb(r,g,b):
'''Encode RGB colour
@@ -261,6 +266,7 @@
'''
return ','.join([str(r),str(g),str(b)])
+# --------------------------------------------------------------------
def rgba(r,g,b,a):
'''Encode RGBA colour
@@ -282,6 +288,7 @@
'''
return ','.join([str(r),str(g),str(b),str(a)])
+# --------------------------------------------------------------------
def dumpTree(node,ind=''):
'''Dump the tree of nodes
@@ -296,6 +303,12 @@
for c in node.childNodes:
dumpTree(c,ind+' ')
+# --------------------------------------------------------------------
+def registerElement(cls):
+
+ Element.known_tags[cls.TAG] = cls
+
+
#
# EOF
#
@@ -310,6 +323,8 @@
MAP = MODULE + 'map.'
PICKER = MAP + 'boardPicker.'
BOARD = PICKER + 'board.'
+ known_tags = {}
+
def __init__(self,parent,tag,node=None,**kwargs):
'''Create a new element
@@ -429,9 +444,14 @@
return {c[key] : c for c in cand}
return cand
- def getParent(self,cls,checkTag=True):
+ def getParent(self,cls=None,checkTag=True):
if self._node.parentNode is None:
return None
+ if cls is None:
+ cls = self.getTagClass(self._node.parentNode.tagName)
+ checkTag = False
+ if cls is None:
+ return None
if checkTag and self._node.parentNode.tagName != cls.TAG:
return None
return cls(self,node=self._node.parentNode)
@@ -440,6 +460,10 @@
'''Searches back until we find the parent with the right
class, or none
'''
+ try:
+ iter(cls)
+ except:
+ cls = [cls]
t = {c.TAG: c for c in cls}
p = self._node.parentNode
while p is not None:
@@ -447,6 +471,11 @@
if c is not None: return c(self,node=p)
p = p.parentNode
return None
+
+ def getTagClass(self,tag):
+ '''Get class corresponding to the tag'''
+ if tag not in self.known_tags: return None;
+ return self.known_tags[tag]
# ----------------------------------------------------------------
# Adders
@@ -518,7 +547,83 @@
'''
super(DummyElement,self).__init__(parent,'Dummy',node=node)
+# --------------------------------------------------------------------
+class ToolbarElement(Element):
+ def __init__(self,
+ parent,
+ tag,
+ node = None,
+ name = '', # Toolbar element name
+ tooltip = '', # Tool tip
+ text = '', # Button text
+ icon = '', # Button icon,
+ hotkey = '', # Named key or key stroke
+ canDisable = False,
+ propertyGate = '',
+ disabledIcon = '',
+ **kwargs):
+ '''Base class for toolbar elements.
+ Parameters
+ ----------
+ parent : Element
+ Parent element if any
+ tag : str
+ Element tag
+ node : XMLNode
+ Possible node - when reading back
+ name : str
+ Name of element (user reminder). If not set, and tooltip is set,
+ set to tooltip
+ toolttip : str
+ Tool tip when hovering. If not set, and name is set, then
+ use name as tooltip.
+ text : str
+ Text of button
+ icon : str
+ Image path for button image
+ hotkey : str
+ Named key or key-sequence
+ canDisable : bool
+ If true, then the element can be disabled
+ propertyGate : str
+ Name of a global property. When this property is `true`,
+ then this element is _disabled_. Note that this _must_ be
+ the name of a property - it cannot be a BeanShell
+ expression.
+ disabledIcon : str
+ Path to image to use when the element is disabled.
+ kwargs : dict
+ Other attributes to set on the element
+ '''
+ if name == '' and tooltip != '': name = tooltip
+ if name != '' and tooltip == '': tooltip = name
+
+ # Build arguments for super class
+ args = {
+ 'node': node,
+ 'name': name,
+ 'icon': icon,
+ 'tooltip': tooltip,
+ 'hotkey': hotkey,
+ 'canDisable': canDisable,
+ 'propertyGate': propertyGate,
+ 'disabledIcon': disabledIcon }
+ bt = kwargs.pop('buttonText',None)
+ # If the element expects buttonText attribute, then do not set
+ # the text attribute - some elements interpret that as a
+ # legacy name attribute,
+ if bt is not None:
+ args['buttonText'] = bt
+ else:
+ args['text'] = text
+ args.update(kwargs)
+
+ super(ToolbarElement,self).__init__(parent,
+ tag,
+ **args)
+ # print('Attributes\n','\n'.join([f'- {k}="{v}"' for k,v in self._node.attributes.items()]))
+
#
# EOF
#
@@ -526,7 +631,7 @@
# From globalkey.py
# --------------------------------------------------------------------
-class GlobalKey(Element):
+class GlobalKey(ToolbarElement):
SELECTED = 'MAP|false|MAP|||||0|0||true|Selected|true|EQUALS'
def __init__(self,
parent,
@@ -533,19 +638,21 @@
tag,
node = None,
name = '',
+ icon = '',
+ tooltip = '',
buttonHotkey = '',
- hotkey = '',
buttonText = '',
canDisable = False,
+ propertyGate = '',
+ disabledIcon = '',
+ # Local
+ hotkey = '',
deckCount = '-1',
filter = '',
- propertyGate = '',
reportFormat = '',
reportSingle = False,
singleMap = True,
- target = SELECTED,
- tooltip = '',
- icon = ''):
+ target = SELECTED):
'''
Parameters
----------
@@ -569,28 +676,26 @@
Default targets are selected units
'''
- nme = (name if len(name) > 0 else
- tooltip if len(tooltip) > 0 else '')
- tip = (tooltip if len(tooltip) > 0 else
- name if len(name) > 0 else '')
+
super(GlobalKey,self).\
__init__(parent,
tag,
node = node,
- name = nme,
+ name = name,
+ icon = icon,
+ tooltip = tooltip,
buttonHotkey = buttonHotkey, # This hot key
- hotkey = hotkey, # Target hot key
buttonText = buttonText,
canDisable = canDisable,
+ propertyGate = propertyGate,
+ disabledIcon = disabledIcon,
+ hotkey = hotkey, # Target hot key
deckCount = deckCount,
filter = filter,
- propertyGate = propertyGate,
reportFormat = reportFormat,
reportSingle = reportSingle,
singleMap = singleMap,
- target = target,
- tooltip = tip,
- icon = icon)
+ target = target)
#
# EOF
#
@@ -600,7 +705,7 @@
# --------------------------------------------------------------------
class GameElementService:
def getGame(self):
- return self.getParent(Game)
+ return self.getParentOfClass(Game)
# --------------------------------------------------------------------
class GameElement(Element,GameElementService):
@@ -608,23 +713,34 @@
super(GameElement,self).__init__(game,tag,node=node,**kwargs)
# --------------------------------------------------------------------
-class Notes(GameElement):
+class Notes(ToolbarElement,GameElementService):
TAG = Element.MODULE+'NotesWindow'
def __init__(self,elem,node=None,
- name = 'Notes',
- buttonText = '',
- hotkey = key('N',ALT),
- icon = '/images/notes.gif',
- tooltip = 'Show notes window'):
- super(Notes,self).__init__(elem,self.TAG,node=node,
- name = name,
- buttonText = buttonText,
- hotkey = hotkey,
- icon = icon,
- tooltip = tooltip)
+ name = 'Notes', # Toolbar element name
+ tooltip = 'Show notes window', # Tool tip
+ text = '', # Button text
+ icon = '/images/notes.gif', # Button icon,
+ hotkey = key('N',ALT), # Named key or key stroke
+ canDisable = False,
+ propertyGate = '',
+ disabledIcon = '',
+ description = ''):
+ super(Notes,self).__init__(elem,self.TAG,
+ node = node,
+ name = name,
+ tooltip = tooltip,
+ text = text,
+ icon = icon,
+ hotkey = hotkey,
+ canDisable = canDisable,
+ propertyGate = propertyGate,
+ disabledIcon = disabledIcon,
+ description = description)
def encode(self):
return ['NOTES\t\\','PNOTES']
+registerElement(Notes)
+
# --------------------------------------------------------------------
class PredefinedSetup(GameElement):
TAG = Element.MODULE+'PredefinedSetup'
@@ -673,6 +789,7 @@
+registerElement(PredefinedSetup)
# --------------------------------------------------------------------
class GlobalTranslatableMessages(GameElement):
@@ -690,11 +807,15 @@
super(GlobalTranslatableMessages,self).\
__init__(elem,self.TAG,node=node)
+registerElement(GlobalTranslatableMessages)
+
# --------------------------------------------------------------------
class Language(GameElement):
TAG = 'VASSAL.i18n.Language'
def __init__(self,elem,node=None,**kwargs):
super(Languate,self).__init__(sele,self.TAG,node=none,**kwargs)
+
+registerElement(Language)
# --------------------------------------------------------------------
class Chatter(GameElement):
@@ -712,6 +833,8 @@
Attributes
'''
super(Chatter,self).__init__(elem,self.TAG,node=node,**kwargs)
+
+registerElement(Chatter)
# --------------------------------------------------------------------
class KeyNamer(GameElement):
@@ -730,6 +853,8 @@
'''
super(KeyNamer,self).__init__(elem,self.TAG,node=node,**kwargs)
+registerElement(KeyNamer)
+
# --------------------------------------------------------------------
# <VASSAL.build.module.GlobalOptions
@@ -883,6 +1008,7 @@
return retd
+registerElement(GlobalOptions)
# --------------------------------------------------------------------
class Option(Element):
@@ -894,6 +1020,8 @@
def getGlobalOptions(self):
return self.getParent(GlobalOptions)
+registerElement(Option)
+
# --------------------------------------------------------------------
class Preference(Element):
PREFS = 'VASSAL.preferences.'
@@ -947,6 +1075,9 @@
default = str(default),
desc = desc,
tab = tab)
+
+registerElement(IntPreference)
+
# --------------------------------------------------------------------
class FloatPreference(Preference):
TAG = Preference.PREFS+'DoublePreference'
@@ -964,6 +1095,9 @@
default = str(default),
desc = desc,
tab = tab)
+
+registerElement(FloatPreference)
+
# --------------------------------------------------------------------
class BoolPreference(Preference):
TAG = Preference.PREFS+'BooleanPreference'
@@ -982,6 +1116,9 @@
else 'false'),
desc = desc,
tab = tab)
+
+registerElement(BoolPreference)
+
# --------------------------------------------------------------------
class StrPreference(Preference):
TAG = Preference.PREFS+'StringPreference'
@@ -999,6 +1136,9 @@
default = default,
desc = desc,
tab = tab)
+
+registerElement(StrPreference)
+
# --------------------------------------------------------------------
class TextPreference(Preference):
TAG = Preference.PREFS+'TextPreference'
@@ -1017,6 +1157,9 @@
.replace('\n','
')),
desc = desc,
tab = tab)
+
+registerElement(TextPreference)
+
# --------------------------------------------------------------------
class EnumPreference(Preference):
TAG = Preference.PREFS+'EnumPreference'
@@ -1042,39 +1185,42 @@
tab = tab,
list = sl)
+
+registerElement(EnumPreference)
+
# --------------------------------------------------------------------
# CurrentMap == "Board"
-class Inventory(GameElement):
+class Inventory(ToolbarElement,GameElementService):
TAG = Element.MODULE+'Inventory'
def __init__(self,doc,node=None,
- canDisable = False,
- centerOnPiece = True,
- disabledIcon = '',
- drawPieces = True,
- foldersOnly = False,
- forwardKeystroke = True,
- groupBy = '',
- hotkey = key('I',ALT),
- icon = '/images/inventory.gif',
- include = '{}',
- launchFunction = 'functionHide',
- leafFormat = '$PieceName$',
- name = '',
- nonLeafFormat = '$PropertyValue$',
- pieceZoom = '0.33',
- pieceZoom2 = '0.5',
- pieceZoom3 = '0.6',
- propertyGate = '',
- refreshHotkey = key('I',ALT_SHIFT),
- showMenu = True,
- sides = '',
- sortFormat = '$PieceName$',
- sortPieces = True,
- sorting = 'alpha',
- text = '',
- tooltip = 'Show inventory of all pieces',
- zoomOn = False):
+ name = '',
+ icon = '/images/inventory.gif',
+ text = '',
+ tooltip = 'Show inventory of all pieces',
+ hotkey = key('I',ALT),
+ canDisable = False,
+ propertyGate = '',
+ disabledIcon = '',
+ centerOnPiece = True,
+ drawPieces = True,
+ foldersOnly = False,
+ forwardKeystroke = True,
+ groupBy = '',
+ include = '{}',
+ launchFunction = 'functionHide',
+ leafFormat = '$PieceName$',
+ nonLeafFormat = '$PropertyValue$',
+ pieceZoom = '0.33',
+ pieceZoom2 = '0.5',
+ pieceZoom3 = '0.6',
+ refreshHotkey = key('I',ALT_SHIFT),
+ showMenu = True,
+ sides = '',
+ sortFormat = '$PieceName$',
+ sortPieces = True,
+ sorting = 'alpha',
+ zoomOn = False):
super(Inventory,self).__init__(doc,self.TAG,node=node,
canDisable = canDisable,
centerOnPiece = centerOnPiece,
@@ -1104,17 +1250,8 @@
tooltip = tooltip,
zoomOn = zoomOn)
-
-
+registerElement(Inventory)
-
-
-
-
-
-
-
-
# --------------------------------------------------------------------
class Prototypes(GameElement):
TAG = Element.MODULE+'PrototypesContainer'
@@ -1149,17 +1286,21 @@
'''
return self.getElementsByKey(Prototype,'name',asdict=asdict)
-
+registerElement(Prototypes)
-
# --------------------------------------------------------------------
-class DiceButton(GameElement):
+class DiceButton(ToolbarElement,GameElementService):
TAG=Element.MODULE+'DiceButton'
def __init__(self,elem,node=None,
+ name = '1d6',
+ tooltip = 'Roll a 1d6',
+ text = '1d6',
+ icon = '/images/die.gif',
+ hotkey = key('6',ALT),
+ canDisable = False,
+ propertyGate = '',
+ disabledIcon = '',
addToTotal = 0,
- canDisable = False,
- hotkey = key('6',ALT),
- icon = '/images/die.gif',
keepCount = 1,
keepDice = False,
keepOption = '>',
@@ -1169,19 +1310,16 @@
lockSides = False,
nDice = 1,
nSides = 6,
- name = '1d6',
plus = 0,
prompt = False,
- propertyGate = '',
- reportFormat = '** $name$ = $result$ *** <$PlayerName$>;',
+ reportFormat = '$name$ = $result$',
reportTotal = False,
- sortDice = False,
- text = '1d6',
- tooltip = 'Roll a 1d6'):
+ sortDice = False):
super(DiceButton,self).\
__init__(elem,self.TAG,node=node,
addToTotal = addToTotal,
canDisable = canDisable,
+ disabledIcon = disabledIcon,
hotkey = hotkey,
icon = icon,
keepCount = keepCount,
@@ -1203,24 +1341,27 @@
text = text,
tooltip = tooltip)
+registerElement(DiceButton)
+
# --------------------------------------------------------------------
class GameMassKey(GlobalKey,GameElementService):
TAG = Element.MODULE+'GlobalKeyCommand'
def __init__(self,map,node=None,
name = '',
+ buttonText = '',
+ tooltip = '',
+ icon = '',
+ canDisable = False,
+ propertyGate = '',
+ disabledIcon = '',
buttonHotkey = '',
hotkey = '',
- buttonText = '',
- canDisable = False,
deckCount = '-1',
filter = '',
- propertyGate = '',
reportFormat = '',
reportSingle = False,
singleMap = True,
- target = GlobalKey.SELECTED,
- tooltip = '',
- icon = ''):
+ target = GlobalKey.SELECTED):
'''Default targets are selected units'''
super(GameMassKey,self).\
__init__(map,
@@ -1241,6 +1382,8 @@
tooltip = tooltip,
icon = icon)
+registerElement(GameMassKey)
+
# --------------------------------------------------------------------
class StartupMassKey(GlobalKey,GameElementService):
TAG = Element.MODULE+'StartupGlobalKeyCommand'
@@ -1287,6 +1430,8 @@
if node is None:
self['whenToApply'] = whenToApply
+registerElement(StartupMassKey)
+
# --------------------------------------------------------------------
class Menu(GameElement):
TAG = Element.MODULE+'ToolbarMenu'
@@ -1293,15 +1438,16 @@
def __init__(self,
game,
node = None,
+ name = '',
+ tooltip = '',
+ text = '', # Menu name
canDisable = False,
+ propertyGate = '',
+ disabledIcon = '',
description = '',
- disabledIcon = '',
hotkey = '',
icon = '',
- menuItems = [],# Button texts
- propertyGate = '',
- text = '',# Menu name
- tooltip = ''):
+ menuItems = []):
if len(description) <= 0 and len(tooltip) > 0:
description = tooltip
if len(tooltip) <= 0 and len(description) > 0:
@@ -1310,6 +1456,7 @@
__init__(game,
self.TAG,
node = node,
+ name = name,
canDisable = canDisable,
description = description,
disabledIcon = disabledIcon,
@@ -1320,6 +1467,8 @@
text = text,
tooltip = tooltip)
+registerElement(Menu)
+
# --------------------------------------------------------------------
class SymbolicDice(GameElement):
@@ -1370,6 +1519,8 @@
def getSymbolicDice(self):
return self.getParent(SymbolicDice)
+registerElement(SymbolicDice)
+
# --------------------------------------------------------------------
class SpecialDie(GameElement):
@@ -1399,8 +1550,7 @@
def getSymbolicDice(self):
return self.getParent(SymbolicDice)
-
-
+registerElement(SpecialDie)
# --------------------------------------------------------------------
class DieFace(GameElement):
@@ -1421,6 +1571,9 @@
def getSpecialDie(self):
return self.getParent(SpecialDie)
+
+registerElement(DieFace)
+
#
# EOF
#
@@ -1451,6 +1604,223 @@
# --------------------------------------------------------------------
+class PieceLayers(MapElement):
+ TAG=Element.MAP+'LayeredPieceCollection'
+ def __init__(self,map,node=None,
+ property = 'PieceLayer',
+ description = '',
+ layerOrder = []):
+ super(PieceLayers,self).__init__(map,self.TAG,node=node,
+ property = property,
+ description = description,
+ layerOrder = ','.join(layerOrder))
+
+ def addControl(self,**kwargs):
+ '''Add `LayerControl` element to this
+
+ Parameters
+ ----------
+ kwargs : dict
+ Dictionary of attribute key-value pairs
+ Returns
+ -------
+ element : LayerControl
+ The added element
+ '''
+ return self.add(LayerControl,**kwargs)
+ def getControls(self,asdict=True):
+ '''Get all `LayerControl` element(s) from this
+
+ Parameters
+ ----------
+ asdict : bool
+ If `True`, return a dictonary that maps name to
+ `LayerControl` elements. If `False`, return a list of all
+ `LayerControl` children.
+
+ Returns
+ -------
+ children : dict or list
+ Dictionary or list of `LayerControl` children
+
+ '''
+ return self.getElementsByKey(LayerControl,'name',asdict)
+
+registerElement(PieceLayers)
+
+# --------------------------------------------------------------------
+class LayerControl(MapElement):
+ TAG=Element.MAP+'LayerControl'
+ CYCLE_UP='Rotate Layer Order Up'
+ CYCLE_DOWN='Rotate Layer Order Down'
+ ENABLE='Make Layer Active'
+ DISABLE='Make Layer Inactive'
+ TOGGLE='Switch Layer between Active and Inactive'
+ RESET='Reset All Layers'
+ def __init__(self,col,node=None,
+ name = '',
+ tooltip = '',
+ text = '',
+ hotkey = '',
+ icon = '',
+ canDisable = False,
+ propertyGate = '', #Property name, disable when property false
+ disabledIcon = '',
+ command = TOGGLE,
+ skip = False,
+ layers = [],
+ description = ''):
+ super(LayerControl,self).__init__(col,self.TAG,node=node,
+ name = name,
+ tooltip = tooltip,
+ text = text,
+ buttonText = text,
+ hotkey = hotkey,
+ icon = icon,
+ canDisable = canDisable,
+ propertyGate = propertyGate,
+ disabledIcon = disabledIcon,
+ command = command,
+ skip = skip,
+ layers = ','.join(layers),
+ description = description)
+
+ def getLayers(self):
+ '''Get map - either a Map or WidgetMap'''
+ return self.getParentOfClass([PieceLayers])
+
+registerElement(LayerControl)
+
+
+# --------------------------------------------------------------------
+class LineOfSight(MapElement):
+ TAG=Element.MAP+'LOS_Thread'
+ ROUND_UP = 'Up'
+ ROUND_DOWN = 'Down'
+ ROUND_NEAREST = 'Nearest whole number'
+ FROM_LOCATION = 'FromLocation'
+ TO_LOCATION = 'ToLocation'
+ CHECK_COUNT = 'NumberOfLocationsChecked'
+ CHECK_LIST = 'AllLocationsChecked'
+ RANGE = 'Range'
+ NEVER = 'Never'
+ ALWAYS = 'Always'
+ WHEN_PERSISTENT = 'When persistent'
+ CTRL_CLICK = 'Cltr-Click & Drag'
+
+ def __init__(self,map,
+ node=None,
+ threadName = 'LOS',
+ hotkey = key('L',ALT),
+ tooltip = 'Trace line of sight',
+ iconName = '/images/thread.gif', #'los-icon.png',
+ label = '',
+ snapLOS = False,
+ snapStart = True,
+ snapEnd = True,
+ report = (f'{{"Range from "+{FROM_LOCATION}'
+ f'+" to "+{TO_LOCATION}+" is "'
+ f'+{RANGE}+" (via "+{CHECK_LIST}+")"}}'),
+ persistent = CTRL_CLICK,
+ persistentIconName = '/images/thread.gif',
+ globl = ALWAYS,
+ losThickness = 3,
+ threadColor = rgb(255,0,0),
+ drawRange = True,
+ # rangeBg = rgb(255,255,255),
+ # rangeFg = rgb(0,0,0),
+ rangeScale = 0,
+ hideCounters = True,
+ hideOpacity = 50,
+ round = ROUND_UP,
+ canDisable = False,
+ propertyGate = '',
+ disabledIcon = ''):
+ '''Make Line of Sight interface
+
+ Parameters
+ ----------
+ threadName : str
+ Name of interface
+ hotkey : str
+ Start LOS key
+ tooltip : str
+ Tool tip text
+ iconName : str
+ Path to button icon
+ label : str
+ Button text
+ snapLOS : bool
+ Wether to snap both ends
+ snapStart : bool
+ Snap to start
+ snapEnd: bool
+ Snap to end
+ report : str
+ Report format
+ persistent : str
+ When persistent
+ persistentIconName : str
+ Icon when persistent(?)
+ globl : str
+ Visisble to opponents
+ losThickness : int
+ Thickness in pixels
+ losColor : str
+ Colour of line
+ drawRange : bool
+ Draw the range next to LOST thread
+ rangeBg : str
+ Range backgroung colour
+ rangeFg : str
+ Range foregrond colour
+ rangeScale : int
+ Scale of range - pixels per unit
+ round : str
+ How to round range
+ hideCounters :bool
+ If true, hide counters while making thread
+ hideOpacity : int
+ Opacity of hidden counters (percent)
+ canDisable : bool
+ IF true, then can be hidden
+ propertyGate : str
+ Name of property. When that property is TRUE, then the
+ interface is disabled. Must be a property name, not an expression.
+ disabledIcon : str
+ Icon to use when disabled
+ '''
+ super(LineOfSight,self).__init__(map,self.TAG,
+ node = node,
+ threadName = threadName,
+ hotkey = hotkey,
+ tooltip = tooltip,
+ iconName = iconName,
+ label = label,
+ snapLOS = snapLOS,
+ snapStart = snapStart,
+ snapEnd = snapEnd,
+ report = report,
+ persistent = persistent,
+ persistentIconName = persistentIconName,
+ losThickness = losThickness,
+ threadColor = threadColor,
+ drawRange = drawRange,
+ #rangeBg = rangeBg,
+ #rangeFg = rangeFg,
+ rangeScale = rangeScale,
+ hideCounters = hideCounters,
+ hideOpacity = hideOpacity,
+ round = round,
+ canDisable = canDisable,
+ propertyGate = propertyGate,
+ disabledIcon = disabledIcon)
+ self.setAttribute('global',globl)
+
+
+registerElement(LineOfSight)
+
+# --------------------------------------------------------------------
class StackMetrics(MapElement):
TAG=Element.MAP+'StackMetrics'
def __init__(self,map,node=None,
@@ -1474,6 +1844,8 @@
unexSepY = unexSepY,
up = up)
+registerElement(StackMetrics)
+
# --------------------------------------------------------------------
class ImageSaver(MapElement):
TAG=Element.MAP+'ImageSaver'
@@ -1491,6 +1863,9 @@
icon = icon,
propertyGate = propertyGate,
tooltip = tooltip)
+
+registerElement(ImageSaver)
+
# --------------------------------------------------------------------
class TextSaver(MapElement):
TAG=Element.MAP+'TextSaver'
@@ -1509,6 +1884,7 @@
propertyGate = propertyGate,
tooltip = tooltip)
+registerElement(TextSaver)
# --------------------------------------------------------------------
class ForwardToChatter(MapElement):
@@ -1516,6 +1892,8 @@
def __init__(self,map,node=None,**kwargs):
super(ForwardToChatter,self).__init__(map,self.TAG,node=node,**kwargs)
+registerElement(ForwardToChatter)
+
# --------------------------------------------------------------------
class MenuDisplayer(MapElement):
TAG=Element.MAP+'MenuDisplayer'
@@ -1522,6 +1900,8 @@
def __init__(self,map,node=None,**kwargs):
super(MenuDisplayer,self).__init__(map,self.TAG,node=node,**kwargs)
+registerElement(MenuDisplayer)
+
# --------------------------------------------------------------------
class MapCenterer(MapElement):
TAG=Element.MAP+'MapCenterer'
@@ -1528,6 +1908,8 @@
def __init__(self,map,node=None,**kwargs):
super(MapCenterer,self).__init__(map,self.TAG,node=node,**kwargs)
+registerElement(MapCenterer)
+
# --------------------------------------------------------------------
class StackExpander(MapElement):
TAG=Element.MAP+'StackExpander'
@@ -1534,6 +1916,8 @@
def __init__(self,map,node=None,**kwargs):
super(StackExpander,self).__init__(map,self.TAG,node=node,**kwargs)
+registerElement(StackExpander)
+
# --------------------------------------------------------------------
class PieceMover(MapElement):
TAG=Element.MAP+'PieceMover'
@@ -1540,6 +1924,8 @@
def __init__(self,map,node=None,**kwargs):
super(PieceMover,self).__init__(map,self.TAG,node=node,**kwargs)
+registerElement(PieceMover)
+
# --------------------------------------------------------------------
class SelectionHighlighters(MapElement):
TAG=Element.MAP+'SelectionHighlighters'
@@ -1547,6 +1933,8 @@
super(SelectionHighlighters,self).\
__init__(map,self.TAG,node=node,**kwargs)
+registerElement(SelectionHighlighters)
+
# --------------------------------------------------------------------
class KeyBufferer(MapElement):
TAG=Element.MAP+'KeyBufferer'
@@ -1553,6 +1941,8 @@
def __init__(self,map,node=None,**kwargs):
super(KeyBufferer,self).__init__(map,self.TAG,node=node,**kwargs)
+registerElement(KeyBufferer)
+
# --------------------------------------------------------------------
class HighlightLastMoved(MapElement):
TAG=Element.MAP+'HighlightLastMoved'
@@ -1565,6 +1955,8 @@
enabled = enabled,
thickness = thickness)
+registerElement(HighlightLastMoved)
+
# --------------------------------------------------------------------
class CounterDetailViewer(MapElement):
TAG=Element.MAP+'CounterDetailViewer'
@@ -1587,7 +1979,7 @@
extraTextPadding = 0,
fgColor = rgb(0,0,0),
fontSize = 9,
- graphicsZoom = 1.0,
+ graphicsZoom = 1.0,# Zoom on counters
hotkey = key('\n',0),
layerList = '',
minDisplayPieces = 2,
@@ -1649,6 +2041,8 @@
verticalTopText = verticalTopText,
zoomlevel = zoomlevel)
+registerElement(CounterDetailViewer)
+
# --------------------------------------------------------------------
class GlobalMap(MapElement):
TAG=Element.MAP+'GlobalMap'
@@ -1668,6 +2062,8 @@
scale = scale,
tooltip = 'Show/Hide overview window')
+registerElement(GlobalMap)
+
# --------------------------------------------------------------------
class Zoomer(MapElement):
TAG = Element.MAP+'Zoomer'
@@ -1687,6 +2083,7 @@
zoomOutKey = key('-'),
zoomPickKey = key('='),
zoomStart = 3):
+
'''Zoom start is counting from the back (with default zoom levels,
and zoom start, the default zoom is 1'''
lvls = ','.join([str(z) for z in zoomLevels])
@@ -1707,6 +2104,8 @@
zoomPickKey = zoomPickKey,
zoomStart = zoomStart)
+registerElement(Zoomer)
+
# --------------------------------------------------------------------
class HidePiecesButton(MapElement):
TAG=Element.MAP+'HidePiecesButton'
@@ -1724,6 +2123,8 @@
showingIcon = showingIcon,
tooltip = tooltip)
+registerElement(HidePiecesButton)
+
# --------------------------------------------------------------------
class MassKey(GlobalKey,MapElementService):
TAG = Element.MAP+'MassKeyCommand'
@@ -1760,6 +2161,7 @@
tooltip = tooltip,
icon = icon)
+registerElement(MassKey)
# --------------------------------------------------------------------
class Flare(MapElement):
@@ -1783,10 +2185,13 @@
flarePulsesPerSec = flarePulsesPerSec,
reportFormat = '')
+registerElement(Flare)
+
# --------------------------------------------------------------------
class AtStart(MapElement):
TAG = Element.MODULE+'map.SetupStack'
- def __init__(self,map,node=None,
+ def __init__(self,map,
+ node = None,
name = '',
location = '',
useGridLocation = True,
@@ -1861,6 +2266,8 @@
'''
return self.getElementsWithKey(PieceSlot,'entryName',asdict)
+registerElement(AtStart)
+
#
# EOF
#
@@ -1894,6 +2301,7 @@
def getProperties(self):
return getElementsByKey(GlobalProperty,'name')
+registerElement(GlobalProperties)
# --------------------------------------------------------------------
class GlobalProperty(Element):
@@ -1919,6 +2327,7 @@
def getGlobalProperties(self):
return self.getParent(GlobalProperties)
+registerElement(GlobalProperty)
#
# EOF
@@ -2099,7 +2508,8 @@
return []
-
+registerElement(TurnTrack)
+
# --------------------------------------------------------------------
class TurnCounter(TurnLevel):
TAG = Element.MODULE+"turn.CounterTurnLevel"
@@ -2118,6 +2528,8 @@
loopLimit = loopLimit,
turnFormat = turnFormat)
+registerElement(TurnCounter)
+
# --------------------------------------------------------------------
class TurnList(TurnLevel):
TAG = Element.MODULE+"turn.ListTurnLevel"
@@ -2135,6 +2547,8 @@
configList = configList,
turnFormat = turnFormat)
+registerElement(TurnList)
+
# --------------------------------------------------------------------
class TurnGlobalHotkey(Element):
TAG = Element.MODULE+'turn.TurnGlobalHotkey'
@@ -2172,6 +2586,8 @@
'''Get the turn track'''
return self.getParent(TurnTrack)
+registerElement(TurnGlobalHotkey)
+
#
# EOF
#
@@ -2316,6 +2732,7 @@
return txt
+registerElement(Documentation)
# --------------------------------------------------------------------
class AboutScreen(Element):
@@ -2343,6 +2760,8 @@
'''Get Parent element'''
return self.getParent(Documentation)
+registerElement(AboutScreen)
+
# --------------------------------------------------------------------
class BrowserPDFFile(Element):
TAG = Element.MODULE+'documentation.BrowserPDFFile'
@@ -2368,6 +2787,8 @@
'''Get Parent element'''
return self.getParent(Documentation)
+registerElement(BrowserPDFFile)
+
# --------------------------------------------------------------------
class HelpFile(Element):
TAG = Element.MODULE+'documentation.HelpFile'
@@ -2400,6 +2821,8 @@
'''Get Parent element'''
return self.getParent(Documentation)
+registerElement(HelpFile)
+
# --------------------------------------------------------------------
class BrowserHelpFile(Element):
TAG = Element.MODULE+'documentation.BrowserHelpFile'
@@ -2427,7 +2850,9 @@
def getDocumentation(self):
'''Get Parent element'''
return self.getParent(Documentation)
-
+
+registerElement(BrowserHelpFile)
+
# --------------------------------------------------------------------
class Tutorial(Element):
TAG = Element.MODULE+'documentation.Tutorial'
@@ -2468,6 +2893,8 @@
'''Get Parent element'''
return self.getParent(Documentation)
+registerElement(Tutorial)
+
#
# EOF
@@ -2517,6 +2944,8 @@
'''Encode for save'''
return ['PLAYER\ta\ta\t<observer>']
+registerElement(PlayerRoster)
+
# --------------------------------------------------------------------
class PlayerSide(Element):
TAG = 'entry'
@@ -2540,7 +2969,9 @@
'''Get Parent element'''
return self.getParent(PlayerRoster)
+registerElement(PlayerSide)
+
#
# EOF
#
@@ -2614,7 +3045,9 @@
def getControl(self):
'''Get Parent element'''
return self.getParent(ChessClockControl)
-
+
+registerElement(ChessClock)
+
# ====================================================================
class ChessClockControl(GameElement):
TAG=Element.MODULE+'ChessClockControl'
@@ -2727,6 +3160,7 @@
'''Return dictionary of clocs'''
return self.getElementsByKey(ChessClock,'side',asdict)
+registerElement(ChessClockControl)
#
# EOF
@@ -2961,6 +3395,8 @@
tooltip = tooltip,
icon = icon)
+registerElement(PieceWindow)
+
# --------------------------------------------------------------------
class ComboWidget(Element,WidgetElement):
TAG=Element.WIDGET+'BoxWidget'
@@ -2972,6 +3408,8 @@
width = width,
height = height)
+registerElement(ComboWidget)
+
# --------------------------------------------------------------------
class TabWidget(Element,WidgetElement):
TAG=Element.WIDGET+'TabWidget'
@@ -2981,6 +3419,8 @@
node = node,
entryName = entryName)
+registerElement(TabWidget)
+
# --------------------------------------------------------------------
class ListWidget(Element,WidgetElement):
TAG=Element.WIDGET+'ListWidget'
@@ -2997,6 +3437,8 @@
scale = scale,
divider = divider)
+registerElement(ListWidget)
+
# --------------------------------------------------------------------
class PanelWidget(Element,WidgetElement):
TAG=Element.WIDGET+'PanelWidget'
@@ -3011,6 +3453,8 @@
nColumns = nColumns,
vert = vert)
+registerElement(PanelWidget)
+
# --------------------------------------------------------------------
class MapWidget(Element):
TAG=Element.WIDGET+'MapWidget'
@@ -3046,6 +3490,8 @@
'''
return self.getElementsByKey(WidgetMap,'mapName',asdict=asdict)
+registerElement(MapWidget)
+
#
# EOF
#
@@ -3258,6 +3704,8 @@
width = self.getZone().getWidth()
return floor(width / self.getDeltaY() + .5)
+registerElement(HexGrid)
+
# --------------------------------------------------------------------
class SquareGrid(BaseGrid):
TAG = Element.BOARD+'SquareGrid'
@@ -3307,6 +3755,8 @@
width = self.getZone().getWidth()
return floor(width / self.getDeltaX() + .5)
+registerElement(SquareGrid)
+
# --------------------------------------------------------------------
class HexNumbering(BaseNumbering):
TAG = Element.BOARD+'mapgrid.HexGridNumbering'
@@ -3368,6 +3818,8 @@
return x,y
+registerElement(HexNumbering)
+
# --------------------------------------------------------------------
class SquareNumbering(BaseNumbering):
TAG = Element.BOARD+'mapgrid.SquareGridNumbering'
@@ -3395,6 +3847,7 @@
return x,y
+registerElement(SquareNumbering)
# --------------------------------------------------------------------
class RegionGrid(Element):
@@ -3452,6 +3905,8 @@
return None
+registerElement(RegionGrid)
+
# --------------------------------------------------------------------
class Region(Element):
TAG = Element.BOARD+'Region'
@@ -3527,6 +3982,8 @@
return b.getMap()
return None
+registerElement(Region)
+
#
# EOF
#
@@ -3579,7 +4036,7 @@
children : list
List of `Highligter` children (even if `single=True`)
'''
- return self.getAllElements(ZonedGridHighliger,single=single)
+ return self.getAllElements(ZonedGridHighlighter,single=single)
def addZone(self,**kwargs):
'''Add a `Zone` element to this
@@ -3607,6 +4064,8 @@
'''
return self.getElementsByKey(Zone,'name',asdict=asdict)
+registerElement(ZonedGrid)
+
# --------------------------------------------------------------------
class ZonedGridHighlighter(Element):
TAG=Element.BOARD+'mapgrid.ZonedGridHighlighter'
@@ -3614,8 +4073,98 @@
super(ZonedGridHighlighter,self).__init__(zoned,self.TAG,node=node)
def getZonedGrid(self): return self.getParent(ZonedGrid)
+ def addZoneHighlight(self,**kwargs):
+ '''Add a `ZoneHighlight` element to this
+ Parameters
+ ----------
+ kwargs : dict
+ Dictionary of attribute key-value pairs
+ Returns
+ -------
+ element : ZoneHighlight
+ The added element
+ '''
+ return self.add(ZoneHighlight,**kwargs)
+ def getZoneHighlights(self,asdict=True):
+ '''Get all ZoneHighlight element(s) from this
+
+ Parameters
+ ----------
+ asdict : bool
+ If `True`, return a dictonary that maps key to `Zone` elements. If `False`, return a list of all Zone` children.
+ Returns
+ -------
+ children : dict or list
+ Dictionary or list of `Zone` children
+ '''
+ return self.getElementsByKey(ZoneHighlight,'name',asdict=asdict)
+
+registerElement(ZonedGridHighlighter)
+
# --------------------------------------------------------------------
+class ZoneHighlight(Element):
+ TAG=Element.BOARD+'mapgrid.ZoneHighlight'
+ FULL='Entire Zone',
+ BORDER='Zone Border',
+ PLAIN='Plain',
+ STRIPED='Striped'
+ CROSS='Crosshatched',
+ TILES='Tiled Image'
+ def __init__(self,
+ highlighters,
+ node = None,
+ name = '',
+ color = rgb(255,0,0),
+ coverage = FULL,
+ width = 1,
+ style = PLAIN,
+ image = '',
+ opacity = 50):
+ super(ZoneHighlight,self).__init__(highlighters,
+ self.TAG,
+ node = node,
+ name = name,
+ color = color,
+ coverage = coverage,
+ width = width,
+ style = style,
+ image = image,
+ opacity = int(opacity))
+ def getZonedGridHighlighter(self):
+ return self.getParent(ZonedGridHighlighter)
+
+
+registerElement(ZoneHighlight)
+
+
+# --------------------------------------------------------------------
+class ZoneProperty(Element):
+ TAG = Element.MODULE+'properties.ZoneProperty'
+ def __init__(self,zone,node=None,
+ name = '',
+ initialValue = '',
+ isNumeric = False,
+ min = "null",
+ max = "null",
+ wrap = False,
+ description = ""):
+ super(ZoneProperty,self).__init__(zone,self.TAG,
+ node = node,
+ name = name,
+ initialValue = initialValue,
+ isNumeric = isNumeric,
+ min = min,
+ max = max,
+ wrap = wrap,
+ description = description)
+
+ def getZone(self):
+ return self.getParent(Zone)
+
+registerElement(ZoneProperty)
+
+# --------------------------------------------------------------------
class Zone(Element):
TAG = Element.BOARD+'mapgrid.Zone'
def __init__(self,zoned,node=None,
@@ -3693,6 +4242,19 @@
The added element
'''
return self.add(RegionGrid,**kwargs)
+ def addProperty(self,**kwargs):
+ '''Add a `Property` element to this
+
+ Parameters
+ ----------
+ kwargs : dict
+ Dictionary of attribute key-value pairs
+ Returns
+ -------
+ element : Property
+ The added element
+ '''
+ return self.add(ZoneProperty,**kwargs)
def getHexGrids(self,single=True):
'''Get all or a sole `HexGrid` element(s) from this
@@ -3758,6 +4320,17 @@
if g is not None: return g
return g
+ def getProperties(self):
+ '''Get all `Property` element from this
+
+ Parameters
+ ----------
+ Returns
+ -------
+ children : dict
+ dict of `Property` children
+ '''
+ return getElementsByKey(ZoneProperty,'name')
def getPath(self):
p = self['path'].split(';')
@@ -3785,6 +4358,8 @@
def getYOffset(self):
return self.getBB()[1]
+registerElement(Zone)
+
#
# EOF
#
@@ -3879,6 +4454,8 @@
return ret
+registerElement(BoardPicker)
+
# --------------------------------------------------------------------
class Setup(Element):
TAG = 'setup'
@@ -3901,7 +4478,9 @@
self.addText(txt)
def getPicker(self): return self.getParent(BoardPicker)
-
+
+registerElement(Setup)
+
# --------------------------------------------------------------------
class Board(Element):
TAG = Element.PICKER+'Board'
@@ -3982,6 +4561,7 @@
return int(self['height'])
return 0
+registerElement(Board)
#
# EOF
@@ -4340,6 +4920,57 @@
picker = self.getPicker()
if picker is None: return None
return picker[0].getBoards(asdict=asdict)
+ def getLayers(self,asdict=True):
+ '''Get all `PieceLayer` element(s) from this
+
+ Parameters
+ ----------
+ asdict : bool
+ If `True`, return a dictonary that maps property name
+ `PieceLayers` elements. If `False`, return a list of all
+ `PieceLayers` children.
+
+ Returns
+ -------
+ children : dict or list
+ Dictionary or list of `PieceLayers` children
+
+ '''
+ return self.getElementsByKey(PieceLayers,'property',asdict)
+ def getMenus(self,asdict=True):
+ '''Get all Menu element(s) from this
+
+ Parameters
+ ----------
+ asdict : bool
+ If `True`, return a dictonary that maps key to `Board`
+ elements. If `False`, return a list of all Board`
+ children.
+
+ Returns
+ -------
+ children : dict or list
+ Dictionary or list of `Board` children
+
+ '''
+ return self.getElementsByKey(Menu,'name',asdict)
+ def getLOSs(self,asdict=True):
+ '''Get all Menu element(s) from this
+
+ Parameters
+ ----------
+ asdict : bool
+ If `True`, return a dictonary that maps key to `Board`
+ elements. If `False`, return a list of all Board`
+ children.
+
+ Returns
+ -------
+ children : dict or list
+ Dictionary or list of `Board` children
+
+ '''
+ return self.getElementsByKey(LineOfSight,'threadName',asdict)
def addBoardPicker(self,**kwargs):
'''Add a `BoardPicker` element to this
@@ -4600,6 +5231,47 @@
The added element
'''
return self.add(AtStart,**kwargs)
+
+
+ def addLayers(self,**kwargs):
+ '''Add `PieceLayers` element to this
+
+ Parameters
+ ----------
+ kwargs : dict
+ Dictionary of attribute key-value pairs
+ Returns
+ -------
+ element : PieceLayers
+ The added element
+ '''
+ return self.add(PieceLayers,**kwargs)
+ def addMenu(self,**kwargs):
+ '''Add a `Menu` element to this
+
+ Parameters
+ ----------
+ kwargs : dict
+ Dictionary of attribute key-value pairs
+ Returns
+ -------
+ element : Menu
+ The added element
+ '''
+ return self.add(Menu,**kwargs)
+ def addLOS(self,**kwargs):
+ '''Add a `Menu` element to this
+
+ Parameters
+ ----------
+ kwargs : dict
+ Dictionary of attribute key-value pairs
+ Returns
+ -------
+ element : Menu
+ The added element
+ '''
+ return self.add(LineOfSight,**kwargs)
# --------------------------------------------------------------------
class Map(BaseMap):
@@ -4657,7 +5329,9 @@
def getGame(self):
return self.getParent(Game)
-
+
+registerElement(Map)
+
# --------------------------------------------------------------------
class WidgetMap(BaseMap):
TAG = Element.WIDGET+'WidgetMap'
@@ -4669,7 +5343,9 @@
def getMapWidget(self):
return self.getParent(MapWidget)
+registerElement(WidgetMap)
+
#
# EOF
#
@@ -4721,7 +5397,7 @@
'''
return self.getElementsById(Chart,'chartName',asdict=asdict)
-
+registerElement(ChartWindow)
# --------------------------------------------------------------------
class Chart(Element):
@@ -4735,6 +5411,8 @@
description = description,
fileName = fileName)
+registerElement(Chart)
+
#
# EOF
#
@@ -4766,7 +5444,7 @@
this actually holds state that isn't reflected elsewhere in
the DOM. This means that the data here is local to the
object. So when we do
-
+
piece = foo.getPieceSlots()[0]
traits = p.getTraits()
for trait in traits:
@@ -5040,6 +5718,15 @@
Identifier
'''
+ last = traits[-1]
+ # A little hackish to use the name of the class, but needed
+ # because of imports into patch scripts.
+ if not isinstance(last,BasicTrait) and \
+ not last.__class__.__name__.endswith('BasicTrait'):
+ from sys import stderr
+ print(f'Warning - last trait NOT a BasicTrait, but a {type(last)}',
+ file=stderr)
+
types = []
states = []
for trait in traits:
@@ -5165,7 +5852,9 @@
if parent is not None:
parent.remove(self)
-
+
+registerElement(DummyWithTraits)
+
# --------------------------------------------------------------------
class PieceSlot(WithTraits):
TAG = Element.WIDGET+'PieceSlot'
@@ -5226,6 +5915,7 @@
piece.setTraits(*traits)
return piece
+registerElement(PieceSlot)
# --------------------------------------------------------------------
class Prototype(WithTraits):
@@ -5255,6 +5945,8 @@
name = name,
description = description)
+registerElement(Prototype)
+
#
# EOF
#
@@ -5262,10 +5954,11 @@
# From traits/dynamicproperty.py
# --------------------------------------------------------------------
-# Base class for property (piece or global) change traits. Encodes
-# constraints and commands.
+#
+#
class ChangePropertyTrait(Trait):
DIRECT = 'P'
+ INCREMENT = 'I'
def __init__(self,
*commands,
numeric = False,
@@ -5272,6 +5965,10 @@
min = 0,
max = 100,
wrap = False):
+ '''Base class for property (piece or global) change traits.
+
+ Encodes constraints and commands.
+ '''
# assert name is not None and len(name) > 0, \
# 'No name specified for ChangePropertyTriat'
super(ChangePropertyTrait,self).__init__()
@@ -5293,8 +5990,11 @@
# print(cmd)
com = cmd[0] + ':' + cmd[1].replace(',',r'\,') + ':' + cmd[2]
if cmd[2] == self.DIRECT:
- com += f'\,'+cmd[3].replace(':',r'\:')
+ com += f'\,'+cmd[3].replace(',',r'\\,').replace(':',r'\:')
+ elif cmd[2] == self.INCREMENT:
+ com += f'\,'+cmd[3].replace(',',r'\\,').replace(':',r'\:')
cmds.append(com)
+ # print(cmds)
return ','.join(cmds)
def decodeCommands(self,commands):
@@ -5305,6 +6005,8 @@
# print('parts',parts)
if parts[-1][0] == self.DIRECT:
parts = parts[:-1]+Trait.decodeKeys(parts[-1],',')
+ if parts[-1][0] == self.INCREMENT:
+ parts = parts[:-1]+Trait.decodeKeys(parts[-1],',')
ret.append(parts)
# print(commands,parts)
return ret
@@ -5840,7 +6542,7 @@
canStack = False,
ignoreGrid = False,
description = ''):
-
+ '''No stacking trait'''
selectionOptions = (select +
(self.IGNORE_GRID if ignoreGrid else '') +
bandSelect)
@@ -7319,6 +8021,7 @@
'''
return self.getAllElements(AtStart,single)
+registerElement(Game)
# --------------------------------------------------------------------
class BasicCommandEncoder(GameElement):
@@ -7326,6 +8029,8 @@
def __init__(self,doc,node=None):
super(BasicCommandEncoder,self).__init__(doc,self.TAG,node=node)
+registerElement(BasicCommandEncoder)
+
#
# EOF
#
@@ -8446,7 +9151,8 @@
vassalVersion = '3.6.7',
nonato = False,
nochit = False,
- counterScale = 1):
+ counterScale = 1,
+ resolution = 150):
'''Exports a PDF and associated JSON files to a VASSAL module.
Parameters
@@ -8473,6 +9179,8 @@
Make grids visible
vassalVersion : str
VASSAL version to encode this module for
+ resolution : int
+ Resolution for images (default 150)
'''
self._vmodname = vmodname
self._pdfname = pdfname
@@ -8487,6 +9195,7 @@
self._vassalVersion = vassalVersion
self._nonato = nonato
self._nochit = nochit
+ self._resolution = resolution
self._counterScale = counterScale
self._battleMark = 'wgBattleMarker'
self._battleMarks = []
@@ -8572,6 +9281,7 @@
v(f'Tutorial log: {self._tutorial}')
v(f'Patch scripts: {self._patch}')
v(f'Visible grids: {self._visible}')
+ v(f'Resolution: {self._resolution}')
v(f'Scale of counters: {self._counterScale}')
def setup(self):
@@ -8704,6 +9414,7 @@
args = ['pdftocairo',
'-transp',
'-singlefile',
+ '-r', str(self._resolution),
'-f', str(page),
'-l', str(page),
'-png' ]
@@ -8772,9 +9483,9 @@
imgsinfo = self.getImagesInfo()
if len(imgsinfo) - 1 != docinfo['Pages']:
- raise RuntimeError(f'Number of pages in {pdfname} '
- f'(doc["Pages"]) not matched in JSON '
- f'{self._infoname} -> {len(imagesinfo)}')
+ raise RuntimeError(f'Number of pages in {self._pdfname} '
+ f'{docinfo["Pages"]} not matched in JSON '
+ f'{self._infoname} -> {len(imgsinfo)}')
with VerboseGuard(f'Converting {docinfo["Pages"]} '
f'pages in {self._pdfname}') as v:
@@ -9126,10 +9837,16 @@
'property': 'Phase',
'names': self._sides } })
turns.addHotkey(hotkey = self._clearMoved+'Phase',
- name = 'Clear moved markers')
+ name = 'Clear moved markers',
+ reportFormat = (f'{{{self._verbose}?('
+ f'"`Clear all moved markers, "+'
+ f'""):""}}'))
if len(self._battleMarks) > 0:
turns.addHotkey(hotkey = self._clearBattlePhs,
- name = 'Clear battle markers')
+ name = 'Clear battle markers',
+ reportFormat = (f'{{{self._verbose}?('
+ f'"`Clear all battle markers, "+'
+ f'""):""}}'))
self._dice = self._categories\
.get('die-roll',{})
@@ -9153,7 +9870,9 @@
# f'+" <img src=\'{die}-"+result1'
# f'+".png\' width=24 height=24>"'
f'}}'),
- resultWindow = True);
+ resultWindow = True,
+ windowX = str(int(67 * self._resolution/150)),
+ windowY = str(int(65 * self._resolution/150)));
sdie = symb.addDie(name = die);
for face, fdata in faces.items():
fn = fdata['filename']
@@ -10186,13 +10905,14 @@
# ----------------------------------------------------------------
def factionTraits(self,faction):
- traits = [ReportTrait(self._eliminateKey,
- self._restoreKey,
- self._trailKey),
+ offX = 36 * self._counterScale * self._resolution/150
+ offY = -38 * self._counterScale * self._resolution/150
+ traits = [#ReportTrait(self._eliminateKey,
+ # self._restoreKey,
+ # self._trailKey),
TrailTrait(),
RotateTrait(),
- MovedTrait(xoff = int( 36 * self._counterScale),
- yoff = int(-38 * self._counterScale)),
+ MovedTrait(xoff = int(offX),yoff = int(offY)),
DeleteTrait(),
SendtoTrait(mapName = 'DeadMap',
boardName = f'{faction} pool',
@@ -11308,7 +12028,10 @@
pc = p["coords"]
if j == 0: vv(f'',end='')
vv(f'[{pn}] ',end='',flush=True,noindent=True)
-
+
+ if pn.endswith(' flipped'):
+ pn = pn[:-len(' flipped')]
+
x, y = tran(*pc)
r = grid.addRegion(name = pn,
originx = x,
@@ -11499,7 +12222,7 @@
def addDie(self):
'''Add a `Die` element to the module
'''
- if self._dice is not None:
+ if self._dice is not None and len(self._dice) > 0:
return
self._game.addDiceButton(name = '1d6',
hotkey = self._diceKey)
@@ -11568,6 +12291,9 @@
ap.add_argument('-S','--counter-scale',
type=float, default=1,
help='Scale counters by factor')
+ ap.add_argument('-R','--resolution',
+ type=int, default=150,
+ help='Resolution of images')
args = ap.parse_args()
@@ -11600,6 +12326,7 @@
vassalVersion = args.vassal_version,
nonato = args.no_nato_prototypes,
nochit = args.no_chit_information,
+ resolution = args.resolution,
counterScale = args.counter_scale)
exporter.run()
except Exception as e:
More information about the tex-live-commits
mailing list.