% \iffalse % ==================================================================== % \fi % % \subsection{The \texttt{wargame.util} \TikZ{} library} % \label{sec:impl:util} % % This library contains some utilities for use in the other % libraries. % % \iffalse %<*utils> %\fi % % % \iffalse % -------------------------------------------------------------------- % \fi % % \subsubsection{Miscellaneous macros} % % \begin{Macro}{\wg@dbg} % Debugging support. The counter \cs{wargamedbglvl} sets the debug % level. The package code then uses \cs{wg@dbg} to print out % debugging messages. This macro takes two arguments --- the first % is the \emph{least} debug level at which the message is printed, and % the second is the message it self. % % \begin{macrocode} \newcount\wargamedbglvl\wargamedbglvl=0 \def\wg@dbg#1#2{% \ifnum#1>\wargamedbglvl\relax\else\message{^^J#2}\fi} % \end{macrocode} % \end{Macro} % % \begin{Macro}{\wg@addto@macro} % % The macro \cs{wg@addto@macro}\marg{macro}\marg{other} adds the % definition of the macro \meta{other} to the macro \meta{macro}. % This uses the \cs{toks} trick of storing the \emph{tokens} of the % definition of a \meta{macro} and \meta{other} into \spec{@} and % expanding that token into the definition of \meta{macro}. % Effectively, this means that the top-level definition of % \meta{macro} and \meta{other} are expanded (i.e., macros used in % the definition of either macro is \emph{not} expanded) and then % that becomes the new definition of \meta{macro}. % % We will use this macro to do \emph{shallow} definitions of macros % to contain keys and such. % % \begin{macrocode} \long\def\wg@addto@macro#1#2{% \begingroup \toks@\expandafter\expandafter\expandafter{\expandafter#1#2}% \xdef#1{\the\toks@}% \endgroup} % \end{macrocode} % \end{Macro} % % % \begin{Macro}{\wg@sub@nchor} % Get anchor from sub node. We cannot use \cs{pgfpointanchor} since % that returns the anchor coordinates in the global coordinate % system. % % \begin{macrocode} \def\wg@sub@nchor#1#2{% \wg@dbg{3}{^^JGet `#2' in `#1'}% \@ifundefined{pgf@sh@ns@#1}{% \pgf@x=0cm\pgf@y=0cm}{% \pgf@process{% \csname pgf@sh@ma@#1\endcsname% MW \csname pgf@sh@np@#1\endcsname% \pgf@sh@reanchor{\csname pgf@sh@ns@#1\endcsname}{#2}}}% \wg@dbg{10}{-> \the\pgf@x,\the\pgf@y}% } % \end{macrocode} % \end{Macro} % % % Scratch dimensions % % \begin{macrocode} \newdimen\wg@tmpa \newdimen\wg@tmpb \newdimen\wg@tmpc \newdimen\wg@tmpd % \end{macrocode} % % % Macro to easy restore a saved path % % \begin{macrocode} \def\settosave#1{ \pgfsyssoftpath@setcurrentpath{#1}} % \end{macrocode} % % \iffalse % -------------------------------------------------------------------- % \fi % % \subsubsection{Pictures in compound nodes} % % \begin{Macro}{\wg@pic} % The macro \cs{wg@pic} will render a \texttt{pic}. This is used by % the \texttt{natoapp6cs}, \texttt{chit}, and \texttt{hex} node % shapes extensively. % % The arguments are % \begin{enumerate} % \item Prefix % \item Position % \item Fixed options % \item User options % \item Picture. % \end{enumerate} % % That is, the macro expects calls like % \begin{Syntax} % \cs{wg@pic}\oarg{options}\meta{picture}\cs{@endwg@pic}\marg{prefix}\marg{position}\marg{options} % \end{Syntax} % % Note the \cs{@endwg@pic} at the end of the call to swallow up % \meta{picture}. Typically this macro is used as % % \begin{Syntax} % \cs{edef}\cs{args}\{\meta{something}\} % \cs{expandafter}\cs{wg@pic}\cs{args}\cs{@endwg@pic}\marg{prefix}\parg{position}\marg{options} % \end{Syntax} % % where \meta{something} typically expands to \oarg{user % option}\meta{picture} % % First, the top-level macro \cs{wg@pic} that looks for user % options. % % \begin{macrocode} \def\wg@pic{% \@ifnextchar[{\wg@@pic}{\wg@@pic[]}%] } % \end{macrocode} % % This macro then forwards to \cs{wg@@pic} to gobble up % \meta{picture}. % % \begin{enumerate} % \item User options % \item Arguments % \end{enumerate} % % \begin{macrocode} \def\wg@@pic[#1]#2\@endwg@pic{% \wg@dbg{2}{Options: `#1', picture: `#2'}% \wg@@@pic{#1}{#2}% } % \end{macrocode} % % \begin{enumerate} % \item User options % \item Arguments % \item Prefix % \item Coordinates % \item Fixed options % \end{enumerate} % % \begin{macrocode} \def\wg@@@pic#1#2#3#4#5{% \ifx|#2|\wg@dbg{3}{No picture given}% \else% \wg@dbg{3}{^^JWG Pic: ^^J User options: #1 ^^J Picture: #2 ^^J Prefix: #3 ^^J Coordinates: #4 ^^J Fixed options: #5}% % \wg@dbg{2}{\string\pic[#5,#1] at (#4) {#3#2}}% \pic[#5,#1] at (#4) {#3#2};% \ifwg@s@ve% \pgf@relevantforpicturesizetrue% \begin{getbbl}% \pic[draw=none,fill=none,transform shape] at (#4) {#3#2};% \end{getbbl}% \wg@dbg{5}{Clipping to local bounding box}% \clip (L.south west) rectangle (L.north east);% \pgf@relevantforpicturesizefalse \global\wg@s@vefalse% \fi \fi% \wg@dbg{3}{End of WG Pic} } % \end{macrocode} % \end{Macro} % % % \begin{Macro}{\wg@pic@all} % % This macro sets all pictures in a list. % % \begin{enumerate} % \item List % \item Prefix % \item Position % \item Styles % \end{enumerate} % % % \begin{macrocode} \def\wg@pic@all#1#2#3#4{% \wg@dbg{2}{WG picture loop ^^J List: \meaning#1 ^^J Prefix: `#2' ^^J Position: `#3' ^^J Styles: `#4'} \foreach \p in #1{% \wg@dbg{2}{WG picture element: \meaning\p}% \expandafter\wg@pic\p\@endwg@pic {#2}{#3}{#4}% }% } % \end{macrocode} % \end{Macro} % % \iffalse % -------------------------------------------------------------------- % \fi % % \subsubsection{Nodes in compound nodes} % % \begin{Macro}{\wg@node} % The macro \cs{wg@node} will render a \texttt{node}. This can be % used by the \texttt{natoapp6cs}, \texttt{chit}, and \texttt{hex} % node shapes. % % The arguments are % \begin{enumerate} % \item Prefix % \item Position % \item Fixed options % \item User options % \item Body. % \end{enumerate} % % That is, the macro expects calls like % \begin{Syntax} % \cs{wg@node}\oarg{options}\meta{body}\cs{@endwg@node}\marg{prefix}\marg{position}\marg{options} % \end{Syntax} % % Note the \cs{@endwg@node} at the end of the call to swallow up % \meta{body}. Typically this macro is used as % % \begin{Syntax} % \cs{edef}\cs{args}\{\meta{something}\} % \cs{expandafter}\cs{wg@node}\cs{args}\cs{@endwg@node}\marg{prefix}\parg{position}\marg{options} % \end{Syntax} % % where \meta{something} typically expands to \oarg{user % option}\meta{body} % % First, the top-level macro \cs{wg@node} that looks for user % options. % % \begin{macrocode} \def\wg@node{% \@ifnextchar[{\wg@@node}{\wg@@node[]}%] } % \end{macrocode} % % This macro then forwards to \cs{wg@@node} to gobble up % \meta{body}. % % \begin{enumerate} % \item User options % \item Arguments % \end{enumerate} % % \begin{macrocode} \def\wg@@node[#1]#2\@endwg@node{% \wg@dbg{2}{Options: `#1', body: `#2'}% \wg@@@node{#1}{#2}% } % \end{macrocode} % % \begin{enumerate} % \item User options % \item Arguments % \item Prefix % \item Coordinates % \item Fixed options % \end{enumerate} % % \begin{macrocode} \def\wg@@@node#1#2#3#4#5{% \ifx|#2|\wg@dbg{3}{No body given}% \else% \wg@dbg{3}{^^JWG Pic: ^^J User options: #1 ^^J Body: #2 ^^J Prefix: #3 ^^J Coordinates: #4 ^^J Fixed options: #5}% % \wg@dbg{2}{\string\pic[#5,#1] at (#4) {#3#2}}% \node[#5,#1] at (#4) {#3#2};% \fi% \wg@dbg{3}{End of WG Node} } % \end{macrocode} % \end{Macro} % % % \begin{Macro}{\wg@node@all} % % This macro sets all pictures in a list. % % \begin{enumerate} % \item List % \item Prefix % \item Position % \item Styles % \end{enumerate} % % % \begin{macrocode} \def\wg@node@all#1#2#3#4{% \wg@dbg{2}{WG picture loop ^^J List: \meaning#1 ^^J Prefix: `#2' ^^J Position: `#3' ^^J Styles: `#4'} \foreach \p in #1{% \wg@dbg{2}{WG picture element: \meaning\p}% \expandafter\wg@node\p\@endwg@node {#2}{#3}{#4}% }% } % \end{macrocode} % \end{Macro} % % \iffalse % -------------------------------------------------------------------- % \fi % % \subsubsection{Bounding boxes} % % Bounding box dimensions % % % \begin{macrocode} \newdimen\wg@bb@minx \newdimen\wg@bb@miny \newdimen\wg@bb@maxx \newdimen\wg@bb@maxy % \end{macrocode} % % % % Enable or disable bounding box tracking % % \begin{macrocode} \newif\ifwg@notrelevantforpathsize\wg@notrelevantforpathsizefalse % \end{macrocode} % % % \begin{Macro}{wg@resetbb} % Reset the bounding box tracking dimensions % % \begin{macrocode} \def\wg@resetbb{% \global\wg@bb@minx=16000pt\relax% \global\wg@bb@miny=16000pt\relax% \global\wg@bb@maxx=-16000pt\relax% \global\wg@bb@maxy=-16000pt\relax% } % \end{macrocode} % \end{Macro} % % \begin{Macro}{\old@pgf@protocolsize} % Save PGF's bounding box algorithm % % \begin{macrocode} \let\old@pgf@protocolsize\pgf@protocolsizes % \end{macrocode} % \end{Macro} % % \begin{Macro}{\wg@protocolsizes} % Our bounding box algorithm % % \begin{macrocode} \def\wg@protocolsizes#1#2{% \old@pgf@protocolsize{#1}{#2} \ifwg@notrelevantforpathsize\else% \ifdim#1<\wg@bb@minx\global\wg@bb@minx#1\fi% \ifdim#1>\wg@bb@maxx\global\wg@bb@maxx#1\fi% \ifdim#2<\wg@bb@miny\global\wg@bb@miny#2\fi% \ifdim#2>\wg@bb@maxy\global\wg@bb@maxy#2\fi% \fi } % \end{macrocode} % \end{Macro} % % % \begin{environment}{getbbl} % Environment that tracks the local bounding box % % \begin{macrocode} \newenvironment{getbbl}{% \wg@resetbb% \wg@notrelevantforpathsizefalse% \global\let\pgf@protocolsizes\wg@protocolsizes}{% \gdef\pgf@sh@ns@L{rectangle} \gdef\pgf@sh@np@L{% \def\southwest{\pgfqpoint{\the\wg@bb@minx}{\the\wg@bb@miny}}% \def\northeast{\pgfqpoint{\the\wg@bb@maxx}{\the\wg@bb@maxy}}% } \gdef\pgf@sh@nt@L{{1}{0}{0}{1}{0pt}{0pt}} \gdef\pgf@sh@pi@L{\pgfpictureid} \global\let\pgf@protocolsizes\old@pgf@protocolsize } % \end{macrocode} % \end{environment} % % \begin{environment}{getbb} % Environment to track global bounding box % % \begin{macrocode} \newenvironment{getbb}{% \wg@resetbb% \wg@notrelevantforpathsizefalse% \global\let\pgf@protocolsizes\wg@protocolsizes}{% \gdef\pgf@sh@ns@M{rectangle} \gdef\pgf@sh@np@M{% \def\southwest{\pgfqpoint{\the\wg@bb@minx}{\the\wg@bb@miny}}% \def\northeast{\pgfqpoint{\the\wg@bb@maxx}{\the\wg@bb@maxy}}% } \gdef\pgf@sh@nt@M{{1}{0}{0}{1}{0pt}{0pt}} % \pgfgettransform\pgf@temp% % \xdef\pgf@sh@nt@M{\pgf@temp} % \pgfgettransformentries{\wg@tmp@a}{\wg@tmp@b}{\wg@tmp@c}{\wg@tmp@d}{\pgf@temp}{\pgf@temp} % \message{^^JTransform of M: \meaning\pgf@temp} % \xdef\pgf@sh@nt@M{{\wg@tmp@a}{\wg@tmp@b}{\wg@tmp@c}{\wg@tmp@d}{0pt}{0pt}}% % \message{^^JTransform of M: \meaning\pgf@sh@nt@M} \gdef\pgf@sh@pi@M{\pgfpictureid} \global\let\pgf@protocolsizes\old@pgf@protocolsize } % \end{macrocode} % \end{environment} % % \iffalse % -------------------------------------------------------------------- % \fi % % \subsubsection{Other Tikz utilities} % % \begin{TikzKey}{tikz/reverseclip} % % A reverse clipping path. This is used to cut out stuff outside of % path defined. % % \begin{macrocode} \tikzstyle{reverseclip}=[insert path={(current bounding box.north east) -- (current bounding box.south east) -- (current bounding box.south west) -- (current bounding box.north west) -- (current bounding box.north east)}] % \end{macrocode} % \end{TikzKey} % % \begin{TikzKey}{tikz/clip even odd rule} % A reverse clipping path % % \begin{macrocode} \tikzset{ clip even odd rule/.code={\pgfseteorule}, % Credit to Andrew Stacey } % \end{macrocode} % \end{TikzKey} % % % \begin{TikzKey}{tikz/invclip} % % Inverse clipping. This should be an option \emph{after} the path to % do the inverse clipping by. This works by adding a \emph{large} % (page) path to the current path, and then use that as clipping. % % \begin{macrocode} \tikzset{ invclip/.style={ clip,insert path= [clip even odd rule]{ [reset cm](-\maxdimen,-\maxdimen)rectangle(\maxdimen,\maxdimen) } }, } % \end{macrocode} % \end{TikzKey} % % \begin{TikzKey}{save clip} % % An option for use with sub-elements of NATO App 6(c) or chit % nodes. This will save the current path as a clipping path for the % next paths to be drawn in the sub-element % % \begin{macrocode} \newif\ifwg@s@ve\wg@s@vefalse \tikzset{ save clip/.is choice, save clip/true/.code={\global\wg@s@vetrue}, save clip/false/.code={\global\wg@s@vefalse}, save clip/.default={true}, save clip/.initial={false}, } % \end{macrocode} % \end{TikzKey} % % \begin{TikzKey}{scale line widths} % % Scales any line width specified in the node options. % % Use like % % \begin{verbatim} % \tikzset{ % some/.style={ % scale line widths, % line width=1pt} % } % \end{verbatim} % % Note that the order is important. % % \begin{macrocode} \tikzset{ scale line widths/.style={% /utils/exec=\def\tikz@semiaddlinewidth##1{% \pgfgettransformentries{% \wg@jaca}{% \wg@jacb}{% \wg@jacc}{% \wg@jacd}{% \wg@tmp}{% \wg@tmp}% \pgfmathsetmacro{\wg@jac}{sqrt(abs(\wg@jaca*\wg@jacd-\wg@jacb*\wg@jacc))}% \wg@dbg{4}{Scaling line width ##1 by \wg@jac} \pgfmathsetmacro{\wg@lw}{\wg@jac*##1}% \wg@dbg{4}{Scaled ##1 -> \wg@lw} \tikz@addoption{\pgfsetlinewidth{\wg@lw pt}}% \wg@dbg{4}{Added scaled option \wg@lw} \pgfmathsetlength\pgflinewidth{\wg@lw pt} \wg@dbg{4}{Did set line width \wg@lw pt} }}, relative line width/.style={% /utils/exec=\def\tikz@semiaddlinewidth##1{% \wg@dbg{4}{Relative line width #1 times ##1}% \pgfmathsetmacro{\wg@lv}{#1*##1}% \tikz@addoption{\pgfsetlinewidth{\wg@lw pt}}% \pgfmathsetlength\pgflinewidth{\wg@lw pt}}} } % \end{macrocode} % \end{TikzKey} % % \begin{TikzKey}{sub pic actions} % % This is key that propagates actions to sub pictures of pictures. % The normal \texttt{pic actions} cannot be used as it causes an % infinite loop. % % \begin{macrocode} \tikzset{ sub pic actions/.code={% \tikz@picmode% \edef\opts{% \iftikz@mode@draw draw,\else draw=none,\fi \iftikz@mode@fill fill\else fill=none\fi} \wg@dbg{5}{^^JSub Mode: \meaning\tikz@picmode \meaning\opts} \pgfset{/tikz/.cd} \pgfkeysalsofrom{\opts} }} % \end{macrocode} % \end{TikzKey} % % \begin{TikzKey}{wg/debug show} % % Show debugging information % % \begin{macrocode} \tikzset{ wg/debug show/.code={% \extractcolorspec{pgfstrokecolor}{\wg@tmp@fg} \def\wg@tmp@bg{none} \@ifundefinedcolor{pgffillcolor}{}{ \extractcolorspec{pgffillcolor}{\wg@tmp@bg}} \begingroup \tikz@mode \wargamedbglvl=#1 \wg@dbg{3}{Drawing with w/stroke `\wg@tmp@fg' (\tikz@strokecolor,\iftikz@mode@draw\else not\space\fi drawing) and fill `\wg@tmp@bg' (\tikz@fillcolor,\iftikz@mode@fill\else not\space\fi filling)} \endgroup } } % \end{macrocode} % \end{TikzKey} % % % \iffalse % -------------------------------------------------------------------- % \fi % % \subsubsection{Random IDs} % % % \begin{macrocode} \def\wg@r@ndom@id{% \def\wg@uuid{} \foreach \i in {1,...,8}{% \pgfmathparse{Hex(random(0,15))} \xdef\wg@uuid{\wg@uuid\pgfmathresult}}} % \end{macrocode} % % \iffalse % %\fi % \iffalse % ==================================================================== % \fi % % \subsection{The \texttt{wgexport} class} % \label{sec:impl:util} % % This document class is used for exporting game component to be used % in a VASSAL module % libraries. % % \iffalse %<*exportcls> %\fi % % Class identification and load \texttt{wargame} package % % \begin{macrocode} \ProvidesClass{wgexport} \PassOptionsToClass{multi=tikzpicture,varwidth=false}{standalone} \DeclareOption{noterrainpic}{% \PassOptionsToPackage{\CurrentOption}{wargame}} \DeclareOption{terrainpic}{% \PassOptionsToPackage{\CurrentOption}{wargame}} \DeclareOption*{% \PassOptionsToClass{\CurrentOption}{standalone}} \ProcessOptions\relax \LoadClass{standalone} \RequirePackage{wargame} % \end{macrocode} % % We need a few utilities before we get to the actual environment. % First, we need a tools to write out literal left and right curly % braces. We do a bit of catcode hackery to accomplish that. % % \begin{macrocode} \begingroup \catcode`\^^I=12 \def\@tabchar{^^I} \catcode`<=1 \catcode`>=2 \catcode`{=12 \catcode`}=12 \gdef\@lbchar<{> \gdef\@rbchar<}> \endgroup % \end{macrocode} % % Above, we temporarily set the tab, and left and right curly brace % characters to be regular letters (12), and the catcodes of less than % and greater than to be those of left and right curly braces % respectively. We then define the macros \cs{@tabchar}, % \cs{@lbchar}, and \cs{@rbchar} to produce literal characters. % \LaTeX already has \cs{@percentchar}. % % Everything we do should go inside this environment. The single % optional argument is the file name stem of the output JSON file. % % \begin{macrocode} \newenvironment{imagelist}[1][\jobname]{% \newwrite\mk@out% \def\mk@i{}% \def\mk@w{\immediate\write\mk@out}% \immediate\openout\mk@out=#1.json \mk@w{[} }{ \mk@w{\mk@i \@lbchar "name":"End of list", "category": "<>", "subcategory": "" \@rbchar } \mk@w{]} \immediate\closeout\mk@out } % \end{macrocode} % % % 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. % % Second argument is the type of image. Recognised types are % % \begin{itemize} % \item \texttt{board} for boards % \item \texttt{oob} for OOBs % \item \texttt{chart} for charts % \item \texttt{counter} for counters % \item \texttt{front} for front page % \end{itemize} % % Other types can be used, and the images will be exported, but the % Python script pays no particular attention to those then. Use for % example to prepare images for help or the like. % % The third argument is the sub type. This is most relevant for the % counters. Sub types can be anything, but since the counters will % receive different prototypes based on the sub type, it makes sense % to divide into sub types a la % % \begin{itemize} % \item factions % \item common markers % \end{itemize} % % The faction sub types should just be the name of the faction. % E.g., Allies, Axis, Soviet, NATO, Warsaw Pact. Spaces should not % matter. % % For common markers, there are a few names that are recognised % specifically by the Python script. These are % % \begin{itemize} % \item \texttt{common} % \item \texttt{all} % \item \texttt{marker} % \item \texttt{markers} % \end{itemize} % % Counters that has these sub-types will no be considered to belong % to any faction. % % Note that the Python script uses the faction names to guess the % players of the game, and uses them in several places. % % % \begin{macrocode} \def\info{% \@ifstar{\@@info{,}}{\@@info{\@rbchar,}}} \def\@@info#1#2#3#4{% \chit@dbg{2}{Making image `#2' of type `#3'/`#4' on page \thepage}% \mk@w{ \@lbchar}% \mk@w{ \space "name": "#2",}% \mk@w{ \space "category": "#3",}% \mk@w{ \space "subcategory": "#4", }% \mk@w{ \space "number": \thepage #1}% \let\oldmk@i\mk@i% \ifx#1,\relax\edef\mk@i{\mk@i\space\space}\fi} \def\end@info{% \let\mk@i\oldmk@i% \mk@w{ \space \@rbchar,}} % \end{macrocode} % % Make separate images for each counter (single sided). % % \begin{macrocode} \newcommand\chitimages[2][]{% \begingroup% \let\chit@report\do@chit@report% \let\natoapp@report\do@natoapp@report% \chit@dbg{2}{chits to make images of `#2'}% \foreach[count=\ti from 0] \t/\x in #2{% \ifx\t\empty\else% Ignore empty rows \chit@dbg{5}{^^JSubcategory: `\x' (default `#1')} \ifx\t\x\def\x{#1}\fi% Take sub-category or default \foreach \u/\m in \t{% \ifx\u\empty\else% Ignore empty cells \chit@dbg{2}{Next chit `\u' with possible multiplicity `\m'}% \ifx\m\@empty\def\m{1}\fi% If not multiplicity defined \ifx\u\m\def\m{1}\fi% If the same as unit \chit@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} \chit[\u=\ti]% \end{tikzpicture} \end@info% %% \foreach \n in {1,...,\m}{% Make a number of copies %% \ifx\u\chit@blank% %% \chit@dbg{3}{Ignoring blank chit:\u}% %% \else% %% \info{\u}{counter}{#2} %% \begin{tikzpicture} %% \chit[\u=\ti](\c,\r)% %% \end{tikzpicture} %% \fi% %% }% \fi% }% \chit@dbg{2}{End of inner loop}% \fi% }% \chit@dbg{2}{End of outer loop}% \endgroup% } % \end{macrocode} % % Make separate images for each counter (double sided). The back-side % counters must be defined by append `\texttt{ flipped}' the front % face name % % \begin{macrocode} \newcommand\doublechitimages[2][]{% \begingroup% \let\chit@report\do@chit@report% \let\natoapp@report\do@natoapp@report% \foreach[count=\ti from 0] \t/\x in #2{% \ifx\t\empty\else% Ignore empty rows \chit@dbg{5}{^^JSubcategory: `\x' (default `#1')} \ifx\t\x\def\x{#1}\fi% Take sub-category or default \foreach \u/\m in \t{% \ifx\u\empty\else% Ignore empty cells \chit@dbg{2}{Next chit `\u' with possible multiplicity `\m'}% \ifx\m\@empty\def\m{1}\fi% If not multiplicity defined \ifx\u\m\def\m{1}\fi% If the same as unit \chit@dbg{2}{Next chit `\u' multiplicity `\m'}% %% Flipped chit \edef\s{\u\space flipped}% %% We only make one copy of the chit, since we can duplicate %% it in VASSAL \info*{\u}{counter}{\x}% \begin{tikzpicture}% \chit[\u=\ti]% \end{tikzpicture}% \end@info% \info*{\s}{counter}{\x}% \begin{tikzpicture}% \chit[\s=\ti]% \end{tikzpicture}% \end@info% %% \foreach \n in {1,...,\m}{% Make a number of copies %% \ifx\u\chit@blank% %% \chit@dbg{3}{Ignoring blank chit:\u}% %% \else% %% \info{\u}{counter}{#2} %% \begin{tikzpicture} %% \chit[\u=\ti](\c,\r)% %% \end{tikzpicture} %% \fi% %% }% \fi% }% \fi% }% \endgroup% } % \end{macrocode} % % Special for boards, we have the environment \textsf{boardimage}. % Like \cs{info} we must specify the name and sub-category of the % board, but the category is assumed to be \texttt{board} (though the % optional argument can specify a different category). % % Within this environment some specific styles are defined that allows % the user to specify VASSAL zones on the board. For this to work % properly, the parent \textsf{tikzpicture} \emph{must} have the style % \texttt{zoned}. This style will record the bounding box of the % picture which we will need to calculate VASSAL coordinates later % on. % % Other styles are \texttt{zone scope}, to be applied to % \texttt{scope}s in the picture, and \texttt{zone path} to be applied % to \texttt{path}s (or \cs{draw}, \cs{fill}, or the like) in the % picture. These will record coordinates of these elements in side % the picture. The Python script will then define VASSAL zones based % on these coordinates. % % For \texttt{zone scope} applied to a \texttt{scope}, what is % recorded are % % \begin{itemize} % \item The current coordinate transformation matrix % \item The current translation % \item The bounding box, within the current transformation and % translation. % \end{itemize} % % To define a zone in the board, simply enclose it in a % % \begin{verbatim} % \begin{scope}[zone scope=name] % ... % \end{scope} % \end{verbatim} % % The \meta{name} will be the name of the scope. If this contains the % sub-string \texttt{hex} (upper, lower, or mixed case), then the zone % will get a hex grid with numbering attached to it. % % If the \meta{name} contains the sub-string \texttt{turn} (any case), % then it is assumed to be a turn track and a rectangular grid will be % attached. The column and row separator will be set to \texttt{T}, % so that it won't collide with the main zone. Similar if \meta{name} % contains \texttt{oob}, except the separator is set to \texttt{O}. % % If \meta{name} contains the sub-string \texttt{pool}, then it is % assumed to be a pool of counters, and \emph{no} grid is attached. % % For \texttt{zone path} applied to a \texttt{path}, what is recorded % is the path coordinates (as straight line segments) in the global % coordinate system. % % Both styles take one argument --- the name of the zone. If that % name contains the sub-string \texttt{hex} anywhere in the name, then % the zone is assumed to contain a hex grid. Otherwise, a rectangular % grid (of fixed size) will be applied to it. % % The environment \texttt{boardimage} also records the coordinate % options currently in use (keys \texttt{hex/first row is}, % \texttt{hex/row direction is}, and so on), as well as the current % label option (as defined by \texttt{every hex} or \texttt{every hex % node}). % % All coordinates, and such are recorded in centimetres. It is worth % remembering that the Tikz coordinate system has the $y$ axis point % upward, while typical image software has the $y$ axis point down. % \texttt{pdftocairo} typically assumes a 150 PPI (pixels-per-inch) % resolution. % % That means that scaling factor becomes % % $$\frac{150\mathrm{pixel}}{2.54\mathrm{cm}}=59.055\frac{\mathrm{pixel}}{\mathrm{cm}}$$ % % \iffalse % Using definition in terms of printers feet - the one to use! % % PNG: 1674 x 1101 % PDF: "lower left": [-0.02107,-0.02107], % "upper right": [28.31705,18.60843] % Width: 28.31705+0.02107 = 28.33812 % Height: 18.60843+0.02107 = 18.62950 % Pixel / cm: 1674 / 28.33812 = 59.07237318495369488166 % 1101 / 18.62950 = 59.09981480984460130438 % Average = 59.08609399739914809302 % % Calculated = 150 / 2.54 = 59.05511811023622047244 % % Using 1/72.27 % % "lower left": [-0.02109,-0.02109], % "upper right": [28.321,18.61102] % Width: 28.321+0.02109=28.34209 % Height: 18.61102+0.02109=18.63211 % Pixel / cm: 1674 / 28.34209 = 59.06409866033168337267 % 1101 / 18.63211 = 59.09153606328000425072 % Average = 59.07781736180584381169 % \fi % % The information extracted is written to the % \cs{jobname}\texttt{.json} file as a sub-object (with name given by % the first optional argument) of the image object. In that way, we % can later on easily get the information from our catalogue of % images. % % Note, the styles \texttt{zoned}, \texttt{zone scope}, and % \texttt{zone path} are defined in \texttt{wargame} to be dummies so % that one can have them in the definition of the board without % impact. % % Since we want to write all dimensions in centimetres, we need to be % able to convert \texttt{pt} dimensions to centimetres. We make two % macros to do that for us. % % The exact definition of 1pt is % % $$1\,\mathrm{pt} = \frac{249}{250}12"\frac{1}{864}=\frac{83}{6000}1" % = 0.03513\overline{6}$$ % % \begin{macrocode} % 2.54 / 72.27 = .03514598035145980351 % \def\pt@to@cm#1{\pgfmathparse{#1 * 0.0351460}} \def\pt@to@cm#1{\pgfmathparse{#1 * 0.0351367}} \def\ptpoint@to@cm#1#2{% \pt@to@cm{#1}\edef\x{\pgfmathresult}% \pt@to@cm{#2}\edef\y{\pgfmathresult}} % \end{macrocode} % \begin{macrocode} \def\mk@get@anchor#1#2{% \pgfpointanchor{#1}{#2}% \pgfgetlastxy\tmp@x\tmp@y% \pt@to@cm{\tmp@x}\edef\tmp@x{\pgfmathresult} \pt@to@cm{\tmp@y}\edef\tmp@y{\pgfmathresult} } \def\mk@get@global@anchor#1#2{% \pgfpointanchor{#1}{#2}% \pgfgetlastxy\tmp@x\tmp@y% \pgfpointtransformed{\pgfpoint{\tmp@x}{\tmp@y}} \pgf@xa=\pgf@x \pgf@ya=\pgf@y \pt@to@cm{\the\pgf@xa}\edef\tmp@x{\pgfmathresult} \pt@to@cm{\the\pgf@ya}\edef\tmp@y{\pgfmathresult} } \def\get@bb#1{% % \pgfpointanchor{#1}{south west}% % \pgfgetlastxy\tmp@llx\tmp@lly% % \pgfpointanchor{#1}{north east}% % \pgfgetlastxy\tmp@urx\tmp@ury% % \pt@to@cm{\tmp@llx}\edef\llx{\pgfmathresult} % \pt@to@cm{\tmp@lly}\edef\lly{\pgfmathresult} % \pt@to@cm{\tmp@urx}\edef\urx{\pgfmathresult} % \pt@to@cm{\tmp@ury}\edef\ury{\pgfmathresult} \mk@get@anchor{#1}{south west} \edef\llx{\tmp@x} \edef\lly{\tmp@y} \mk@get@anchor{#1}{north east} \edef\urx{\tmp@x} \edef\ury{\tmp@y} } % \end{macrocode} % \begin{macrocode} \def\mk@transform{% \pgfgettransformentries{\mxx}{\mxy}{\myx}{\myy}{\ptdx}{\ptdy} \pt@to@cm{\ptdx}\edef\dx{\pgfmathresult} \pt@to@cm{\ptdy}\edef\dy{\pgfmathresult} \mk@w{ \mk@i "xx": \mxx,} \mk@w{ \mk@i "xy": \mxy,} \mk@w{ \mk@i "yx": \myx,} \mk@w{ \mk@i "yy": \myy,} \mk@w{ \mk@i "dx": \dx,} \mk@w{ \mk@i "dy": \dy,} } % \end{macrocode} % \begin{macrocode} \def\mk@bb#1{% \get@bb{#1} \mk@w{ \mk@i "lower left": [\llx,\lly],} \mk@w{ \mk@i "upper right": [\urx,\ury],} \begingroup % \pgftransforminvert % \pgfpointanchor{#1}{south west}% % \pgfgetlastxy\tmp@llx\tmp@lly% % \pgfpointtransformed{\pgfpoint{\tmp@llx}{\tmp@lly}} % \pgf@xa=\pgf@x % \pgf@ya=\pgf@y % % % \pgfpointanchor{#1}{north east}% % \pgfgetlastxy\tmp@urx\tmp@ury% % \pgfgetlastxy\tmp@llx\tmp@lly% % \pgfpointtransformed{\pgfpoint{\tmp@urx}{\tmp@ury}} % \pgf@xb=\pgf@x % \pgf@yb=\pgf@y % \pt@to@cm{\the\pgf@xa}\edef\llx{\pgfmathresult} % \pt@to@cm{\the\pgf@ya}\edef\lly{\pgfmathresult} % \pt@to@cm{\the\pgf@xb}\edef\urx{\pgfmathresult} % \pt@to@cm{\the\pgf@yb}\edef\ury{\pgfmathresult}x \mk@get@global@anchor{#1}{south west} \mk@w{ \mk@i "global lower left": [\tmp@x,\tmp@y],} \mk@get@global@anchor{#1}{north east} \mk@w{ \mk@i "global upper right": [\tmp@x,\tmp@y]} \endgroup } \def\mk@pos#1(#2){% \hex@dbg{10}{^^JMarking `#2' with `#1' - start} \coordinate[transform shape] (tmp) at (#2) {}; \mk@get@anchor{tmp}{center} \hex@dbg{3}{^^JMarking `#2' with `#1' - `\tmp@x',\tmp@y'} \tikzset{zone point={#1}{\tmp@x}{\tmp@y}} } % \end{macrocode} % % For the key \texttt{zone path} to work, we need to be able to record % the path as it moves along. To that end, we make a custom % decoration that will do that for us, and, once the path is finished, % write the path to our JSON file. % % \begin{macrocode} \pgfdeclaredecoration{record path construction}{initial}{% \state{initial}[width=0pt,next state=more]{ \begingroup \pgf@decorate@inputsegment@first \ptpoint@to@cm{\the\pgf@x}{\the\pgf@y} \xdef\wg@path{[\x,\y]} \endgroup }% \state{more}[width=\pgfdecoratedinputsegmentremainingdistance]{% \begingroup \pgf@decorate@inputsegment@last \ptpoint@to@cm{\the\pgf@x}{\the\pgf@y} \xdef\wg@path{\wg@path,[\x,\y]} \endgroup } \state{final}{% \begingroup \pgf@decorate@inputsegment@last \ptpoint@to@cm{\the\pgf@x}{\the\pgf@y} \xdef\wg@path{\wg@path,[\x,\y]} \endgroup \mk@w{ \mk@i "zone path \wg@record@path@name": \@lbchar} \mk@w{ \mk@i\space "path": [\wg@path] \@rbchar,} } }% % \end{macrocode} % % Now we can make our environment % % The first thing we do is to use the \cs{info} macro to mark the % image. Then we open our JSON file. We make a short-hand macro for % writing to that file. The macro \cs{bd@i} records the current % indention (which is important in JSON) % % \begin{macrocode} \newenvironment{boardimage}[3][board]{% \def\bd@n{#2} \newcount\mk@point \mk@point=0 \let\oomk@i\mk@i% \let\markpos\mk@pos% % \end{macrocode} % % % Then, to extract the label option, we make a dummy \texttt{node} % with the styles \texttt{every hex} and \texttt{every hex node}, so % we can extract that option. % % \begin{macrocode} \info{dummy}{<>}{}% %\tikz{}% \tikz{\scoped[every hex/.try,every hex node/.try]{% \node[inner sep=0,outer sep=0]{% \global\let\mk@label\hex@label}}}% % \end{macrocode} % % The next thing we do is to make an object. The first things we put % in are the units used (``cm''), and the grid options. % % \begin{macrocode} \info*{#2}{#1}{#3}% \mk@w{ \mk@i "zones": \@lbchar}% \edef\mk@i{\mk@i\space} %% Everything is made into centimeters \mk@w{ \mk@i "units": "cm",} \@ifundefined{mk@label}{}{\mk@w{ \mk@i "labels": "\mk@label",}} %% Write out coordinate options as "coords" object \mk@w{ \mk@i"coords": \@lbchar}% \mk@w{ \mk@i "row": \@lbchar}% \mk@w{ \mk@i\space "offset": \hex@coords@row@off,}% \mk@w{ \mk@i\space "factor": \hex@coords@row@fac \@rbchar,}% \mk@w{ \mk@i "column": \@lbchar}% \mk@w{ \mk@i\space "offset": \hex@coords@col@off,}% \mk@w{ \mk@i\space "factor": \hex@coords@col@fac,}% \mk@w{ \mk@i\space "top short": "\hex@top@short@col",}% \mk@w{ \mk@i\space "bottom short": "\hex@bot@short@col" \@rbchar}% \mk@w{ \mk@i\@rbchar,}% % \end{macrocode} % % We then monkey-patch \cs{boardframe} to also output coordinates to % our JSON file. Note that this will probably be embedded in a % different object. % % \begin{macrocode} %% \let\oldbo@rdframe\bo@rdframe% \def\bo@rdframe[##1](##2)(##3){% \oldbo@rdframe[##1](##2)(##3)% \mk@w{ \mk@i"board frame": \@lbchar} \mk@w{ \mk@i\space "lower left": [\llx,\lly],} \mk@w{ \mk@i\space "upper right": [\urx,\ury],} \mk@w{ \mk@i\space "margin": \margin,} \mk@w{ \mk@i\space "width": \w,} \mk@w{ \mk@i\space "height": \h \@rbchar,}}% % \end{macrocode} % % Next, we make the style \texttt{zoned} to be applied to the % \texttt{tikzpicture} environment. This records the bounding box of % the full picture. % % \begin{macrocode} \tikzset{ zoned/.code={% Apply to whole picture \pgfkeys{% % This needs to be done in the picture! /tikz/execute at end picture={% \mk@w{ \mk@i "zoned": \@lbchar} \mk@transform% \mk@bb{current bounding box} \mk@w{ \mk@i \@rbchar,} } } }, % \end{macrocode} % % The next style is the \texttt{zone scope}. At the start of the % scope we record the current transformation matrix. Then we install % a handler to extract the bounding box at the end of the scope. Note % that we increase indention here. % % \begin{macrocode} zone scope/.code={% \mk@w{ \mk@i"zone scope ##1": \@lbchar} \let\omk@i\mk@i \edef\mk@i{\mk@i\space} \mk@transform% %\bd@w{ \@rbchar,} \gdef\wg@export@box{##1}% \pgfkeys{% /tikz/local bounding box=wg export box, /tikz/execute at end scope={ \mk@bb{wg export box} \let\mk@i\omk@i \mk@w{ \mk@i\@rbchar,}}, } % pgfkeys }, % zone scope % \end{macrocode} % The next style gets the global coordinates of the current (0,0) % point - f.ex. in a node - and outputs that % \begin{macrocode} zone point/.code n args={3}{ \pgf@xa=##2 cm \pgf@ya=##3 cm \pgfpointtransformed{\pgfpoint{\pgf@xa}{\pgf@ya}} % \pgfpointtransformed{\pgfpoint{0pt}{0pt}} \pgf@xa=\pgf@x \pgf@ya=\pgf@y \pt@to@cm{\the\pgf@xa}\edef\px{\pgfmathresult} \pt@to@cm{\the\pgf@ya}\edef\py{\pgfmathresult} \advance\mk@point1 \global\mk@point=\mk@point \mk@w{ \mk@i "point\the\mk@point": \@lbchar "name": "##1", "type": "point", "coords": [\px,\py] \@rbchar, } %\message{^^JZone point \the\mk@point\space ##1: ##2,##3 -> \px,\py} }, zone global point/.code n args={3}{ \advance\mk@point1 \global\mk@point=\mk@point \mk@w{ \mk@i "point\the\mk@point": \@lbchar "name": "##1", "type": "point", "coords": [\px,\py] \@rbchar, } }, % \end{macrocode} % % The \texttt{zone path} style is a bit more simple, but only because % the bulk of the work is done in a decoration. We need to be able to % pass a name to that decoration, s we make a key for that. The user % need not think about that though. % % \begin{macrocode} /pgf/decoration/record path name/.store in=\wg@record@path@name, zone path/.style={% postaction={decorate,decoration={ record path construction, record path name=##1}} } % zone path }% tikzset } % \end{macrocode} % % That finishes the first part of the environment. At the end of the % environment, we simple write the name of the picture, and close our % JSON output. % % \begin{macrocode} {% \mk@w{ \mk@i "name": "\bd@n" }% \let\mk@i\oomk@i% \mk@w{ \mk@i\@rbchar}% \end@info% } % \end{macrocode} % % % TO BE DONE: We could add hooks to both the \texttt{hex} and % \texttt{chit} shapes that would allow us to write out the settings % for each of these. This would allow us to make data files that % contain the information available in the \LaTeX{} code. For % example, we could write a counters % % \begin{itemize} % \item Left and right identifiers % \item Upper left, upper right, lower left, and lower right % identifiers. (some care must be taken if these contains graphics % and not just text.) % \item Factors % \item NATO symbol % \begin{itemize} % \item Faction, command, echelon % \item Mains % \item Left, right, top, and bottom attributes and modifiers % \item Below attribute % \end{itemize} % \end{itemize} % % If one then assumed that for example the upper left corner holds the % start-up hex, then one could use that information. % % The code below exports the chit information to the JSON file. Not % sure how to use it though. % % \begin{macrocode} \tikzset{ zone turn/.store in=\zone@turn, zone mult/.store in=\zone@mult } \def\do@chit@report{% \mk@w{ \mk@i "chit": \@lbchar} \@ifundefined{id}{} {\mk@w{ \mk@i\space "id": "\id", }}% \@ifundefined{chit@symbol}{} {\mk@w{ \mk@i\space "symbol": "true", }}% \@ifundefined{chit@full}{} {\mk@w{ \mk@i\space "full": "\chit@full", }} \@ifundefined{chit@factors}{} {\mk@w{ \mk@i\space "factors": "\chit@factors", }}% \@ifundefined{chit@left}{} {\mk@w{ \mk@i\space "left": "\chit@left", }}% \@ifundefined{chit@right}{} {\mk@w{ \mk@i\space "right": "\chit@right", }}% \@ifundefined{chit@upper@left}{} {\mk@w{ \mk@i\space "upper left": "\chit@upper@left", }}% \@ifundefined{chit@lower@left}{} {\mk@w{ \mk@i\space "lower left": "\chit@lower@left", }}% \@ifundefined{chit@upper@right}{}{\mk@w{ \mk@i\space "upper right": "\chit@upper@right", }}% \@ifundefined{chit@lower@right}{}{\mk@w{ \mk@i\space "lower right": "\chit@lower@right}", }% \mk@w{ \mk@i\space "end": 0} \@ifundefined{chit@symbol}{ \mk@w{ \mk@i \@rbchar } }{ \mk@w{ \mk@i \@rbchar, }% NATOAPP6c will follow }% } \def\do@natoapp@report{% \mk@w{ \mk@i "natoapp6c": \@lbchar} \@ifundefined{id}{}{\mk@w{ \mk@i\space "id": "\id", }} \@ifundefined{natoapp@fac}{}{\mk@w{ \mk@i\space "faction": "\natoapp@fac", }} \@ifundefined{natoapp@cmd}{}{\mk@w{ \mk@i\space "command": "\natoapp@cmd", }} \@ifundefined{natoapp@ech}{}{\mk@w{ \mk@i\space "echelon": "\natoapp@ech", }} \@ifundefined{natoapp@main}{}{\mk@w{ \mk@i\space "main": "\natoapp@main", }} \@ifundefined{natoapp@left}{}{\mk@w{ \mk@i\space "left": "\natoapp@left", }} \@ifundefined{natoapp@right}{}{\mk@w{ \mk@i\space "right": "\natoapp@right", }} \@ifundefined{natoapp@upper}{}{\mk@w{ \mk@i\space "upper": "\natoapp@upper", }} \@ifundefined{natoapp@lower}{}{\mk@w{ \mk@i\space "lower": "\natoapp@lower", }} \@ifundefined{natoapp@below}{}{\mk@w{ \mk@i\space "below": "\natoapp@below", }} \mk@w{ \mk@i\space "end": 0} \mk@w{ \mk@i \@rbchar} } % \end{macrocode} % \iffalse % %\fi %