diff --git a/vasl_templates/tools/get_piece_info.py b/vasl_templates/tools/get_piece_info.py new file mode 100755 index 0000000..338118f --- /dev/null +++ b/vasl_templates/tools/get_piece_info.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +""" Prepare the piece info for a VASL module. + +The main program used to identify 5/8" counters by reading a module's buildFile and checking the height +attribute of the PieceSlot nodes, but it turns out this is the wrong thing to do (this field actually +controls the size of the piece's entry in the counter palette): + https://github.com/vasl-developers/vasl/issues/1195 + +For each version of VASL supported, run vassal-shim (getPieceInfo command) to analyze the module's +buildFile and get the correct counter sizes. Then pass the output into this script, to generate +the final data file that should be saved in the $/data/vasl-$VERSION/ directory, where it will +be read by the main program. + +NOTE: Introducing this process opens the possibility of also extracting the image file paths +within the .vmod file, instead of the current messy parsing of the PieceSlot CDATA... :-/ +""" + +import sys +import os +import json + +import xml.etree.ElementTree as ET + +# --------------------------------------------------------------------- + +# initialize +report = {} + +# figure out which GPID's we're interested in +gpids = set() +def get_gpids( vo_type ): + """Get the GPID's from our data files.""" + dname = os.path.join( os.path.dirname(__file__), "../webapp/data", vo_type ) + for root,_,fnames in os.walk( dname ): + for fname in fnames: + if os.path.splitext( fname )[1] != ".json": + continue + fname = os.path.join( root, fname ) + with open( fname, "r", encoding="utf-8" ) as fp: + entries = json.load( fp ) + for entry in entries: + entry_gpid = entry.get( "gpid" ) + if not entry_gpid: + continue + if isinstance( entry_gpid, list ): + gpids.update( str(g) for g in entry_gpid ) + else: + gpids.add( str( entry_gpid ) ) +get_gpids( "vehicles" ) +get_gpids( "ordnance" ) + +# parse the piece info generated by vassal-shim +doc = ET.parse( sys.stdin ) +for piece_info in doc.getroot(): + gpid = piece_info.attrib["gpid"] + if gpid not in gpids: + continue + info = {} + # check if the next piece is small + if int( piece_info.attrib["height"] ) <= 48: + info["is_small"] = True + if info: + report[ gpid ] = info + +# output the final report +print( "{" ) +lines = [] +for gpid, piece_info in report.items(): + lines.append( "\"{}\": {}".format( + gpid, json.dumps( piece_info ) + ) ) +print( ",\n".join( lines ) ) +print( "}" ) diff --git a/vasl_templates/webapp/data/vasl-6.6.0/piece-info.json b/vasl_templates/webapp/data/vasl-6.6.0/piece-info.json new file mode 100644 index 0000000..8774684 --- /dev/null +++ b/vasl_templates/webapp/data/vasl-6.6.0/piece-info.json @@ -0,0 +1,65 @@ +{ +"6996": {"is_small": true}, +"485": {"is_small": true}, +"850": {"is_small": true}, +"849": {"is_small": true}, +"12689": {"is_small": true}, +"856": {"is_small": true}, +"857": {"is_small": true}, +"11336": {"is_small": true}, +"858": {"is_small": true}, +"11337": {"is_small": true}, +"1149": {"is_small": true}, +"1153": {"is_small": true}, +"12687": {"is_small": true}, +"3b5:7613": {"is_small": true}, +"11359": {"is_small": true}, +"3b5:11259": {"is_small": true}, +"1632": {"is_small": true}, +"1636": {"is_small": true}, +"1641": {"is_small": true}, +"1648": {"is_small": true}, +"1982": {"is_small": true}, +"1983": {"is_small": true}, +"1984": {"is_small": true}, +"1985": {"is_small": true}, +"1986": {"is_small": true}, +"1987": {"is_small": true}, +"1988": {"is_small": true}, +"2172": {"is_small": true}, +"2173": {"is_small": true}, +"2176": {"is_small": true}, +"2179": {"is_small": true}, +"11391": {"is_small": true}, +"11392": {"is_small": true}, +"11395": {"is_small": true}, +"11396": {"is_small": true}, +"11440": {"is_small": true}, +"3b5:8401": {"is_small": true}, +"3b5:8402": {"is_small": true}, +"2465": {"is_small": true}, +"2474": {"is_small": true}, +"3252": {"is_small": true}, +"3253": {"is_small": true}, +"3263": {"is_small": true}, +"3422": {"is_small": true}, +"3428": {"is_small": true}, +"6730": {"is_small": true}, +"3605": {"is_small": true}, +"3608": {"is_small": true}, +"6763": {"is_small": true}, +"3679": {"is_small": true}, +"3680": {"is_small": true}, +"3681": {"is_small": true}, +"3682": {"is_small": true}, +"3691": {"is_small": true}, +"3692": {"is_small": true}, +"3959": {"is_small": true}, +"11558": {"is_small": true}, +"11559": {"is_small": true}, +"3b5:10150": {"is_small": true}, +"3b5:10151": {"is_small": true}, +"11600": {"is_small": true}, +"11604": {"is_small": true}, +"3b5:7871": {"is_small": true} +} diff --git a/vasl_templates/webapp/data/vasl-6.6.1/piece-info.json b/vasl_templates/webapp/data/vasl-6.6.1/piece-info.json new file mode 100644 index 0000000..8774684 --- /dev/null +++ b/vasl_templates/webapp/data/vasl-6.6.1/piece-info.json @@ -0,0 +1,65 @@ +{ +"6996": {"is_small": true}, +"485": {"is_small": true}, +"850": {"is_small": true}, +"849": {"is_small": true}, +"12689": {"is_small": true}, +"856": {"is_small": true}, +"857": {"is_small": true}, +"11336": {"is_small": true}, +"858": {"is_small": true}, +"11337": {"is_small": true}, +"1149": {"is_small": true}, +"1153": {"is_small": true}, +"12687": {"is_small": true}, +"3b5:7613": {"is_small": true}, +"11359": {"is_small": true}, +"3b5:11259": {"is_small": true}, +"1632": {"is_small": true}, +"1636": {"is_small": true}, +"1641": {"is_small": true}, +"1648": {"is_small": true}, +"1982": {"is_small": true}, +"1983": {"is_small": true}, +"1984": {"is_small": true}, +"1985": {"is_small": true}, +"1986": {"is_small": true}, +"1987": {"is_small": true}, +"1988": {"is_small": true}, +"2172": {"is_small": true}, +"2173": {"is_small": true}, +"2176": {"is_small": true}, +"2179": {"is_small": true}, +"11391": {"is_small": true}, +"11392": {"is_small": true}, +"11395": {"is_small": true}, +"11396": {"is_small": true}, +"11440": {"is_small": true}, +"3b5:8401": {"is_small": true}, +"3b5:8402": {"is_small": true}, +"2465": {"is_small": true}, +"2474": {"is_small": true}, +"3252": {"is_small": true}, +"3253": {"is_small": true}, +"3263": {"is_small": true}, +"3422": {"is_small": true}, +"3428": {"is_small": true}, +"6730": {"is_small": true}, +"3605": {"is_small": true}, +"3608": {"is_small": true}, +"6763": {"is_small": true}, +"3679": {"is_small": true}, +"3680": {"is_small": true}, +"3681": {"is_small": true}, +"3682": {"is_small": true}, +"3691": {"is_small": true}, +"3692": {"is_small": true}, +"3959": {"is_small": true}, +"11558": {"is_small": true}, +"11559": {"is_small": true}, +"3b5:10150": {"is_small": true}, +"3b5:10151": {"is_small": true}, +"11600": {"is_small": true}, +"11604": {"is_small": true}, +"3b5:7871": {"is_small": true} +} diff --git a/vasl_templates/webapp/data/vasl-6.6.2/piece-info.json b/vasl_templates/webapp/data/vasl-6.6.2/piece-info.json new file mode 100644 index 0000000..8774684 --- /dev/null +++ b/vasl_templates/webapp/data/vasl-6.6.2/piece-info.json @@ -0,0 +1,65 @@ +{ +"6996": {"is_small": true}, +"485": {"is_small": true}, +"850": {"is_small": true}, +"849": {"is_small": true}, +"12689": {"is_small": true}, +"856": {"is_small": true}, +"857": {"is_small": true}, +"11336": {"is_small": true}, +"858": {"is_small": true}, +"11337": {"is_small": true}, +"1149": {"is_small": true}, +"1153": {"is_small": true}, +"12687": {"is_small": true}, +"3b5:7613": {"is_small": true}, +"11359": {"is_small": true}, +"3b5:11259": {"is_small": true}, +"1632": {"is_small": true}, +"1636": {"is_small": true}, +"1641": {"is_small": true}, +"1648": {"is_small": true}, +"1982": {"is_small": true}, +"1983": {"is_small": true}, +"1984": {"is_small": true}, +"1985": {"is_small": true}, +"1986": {"is_small": true}, +"1987": {"is_small": true}, +"1988": {"is_small": true}, +"2172": {"is_small": true}, +"2173": {"is_small": true}, +"2176": {"is_small": true}, +"2179": {"is_small": true}, +"11391": {"is_small": true}, +"11392": {"is_small": true}, +"11395": {"is_small": true}, +"11396": {"is_small": true}, +"11440": {"is_small": true}, +"3b5:8401": {"is_small": true}, +"3b5:8402": {"is_small": true}, +"2465": {"is_small": true}, +"2474": {"is_small": true}, +"3252": {"is_small": true}, +"3253": {"is_small": true}, +"3263": {"is_small": true}, +"3422": {"is_small": true}, +"3428": {"is_small": true}, +"6730": {"is_small": true}, +"3605": {"is_small": true}, +"3608": {"is_small": true}, +"6763": {"is_small": true}, +"3679": {"is_small": true}, +"3680": {"is_small": true}, +"3681": {"is_small": true}, +"3682": {"is_small": true}, +"3691": {"is_small": true}, +"3692": {"is_small": true}, +"3959": {"is_small": true}, +"11558": {"is_small": true}, +"11559": {"is_small": true}, +"3b5:10150": {"is_small": true}, +"3b5:10151": {"is_small": true}, +"11600": {"is_small": true}, +"11604": {"is_small": true}, +"3b5:7871": {"is_small": true} +} diff --git a/vasl_templates/webapp/data/vasl-6.6.3/piece-info.json b/vasl_templates/webapp/data/vasl-6.6.3/piece-info.json new file mode 100644 index 0000000..8774684 --- /dev/null +++ b/vasl_templates/webapp/data/vasl-6.6.3/piece-info.json @@ -0,0 +1,65 @@ +{ +"6996": {"is_small": true}, +"485": {"is_small": true}, +"850": {"is_small": true}, +"849": {"is_small": true}, +"12689": {"is_small": true}, +"856": {"is_small": true}, +"857": {"is_small": true}, +"11336": {"is_small": true}, +"858": {"is_small": true}, +"11337": {"is_small": true}, +"1149": {"is_small": true}, +"1153": {"is_small": true}, +"12687": {"is_small": true}, +"3b5:7613": {"is_small": true}, +"11359": {"is_small": true}, +"3b5:11259": {"is_small": true}, +"1632": {"is_small": true}, +"1636": {"is_small": true}, +"1641": {"is_small": true}, +"1648": {"is_small": true}, +"1982": {"is_small": true}, +"1983": {"is_small": true}, +"1984": {"is_small": true}, +"1985": {"is_small": true}, +"1986": {"is_small": true}, +"1987": {"is_small": true}, +"1988": {"is_small": true}, +"2172": {"is_small": true}, +"2173": {"is_small": true}, +"2176": {"is_small": true}, +"2179": {"is_small": true}, +"11391": {"is_small": true}, +"11392": {"is_small": true}, +"11395": {"is_small": true}, +"11396": {"is_small": true}, +"11440": {"is_small": true}, +"3b5:8401": {"is_small": true}, +"3b5:8402": {"is_small": true}, +"2465": {"is_small": true}, +"2474": {"is_small": true}, +"3252": {"is_small": true}, +"3253": {"is_small": true}, +"3263": {"is_small": true}, +"3422": {"is_small": true}, +"3428": {"is_small": true}, +"6730": {"is_small": true}, +"3605": {"is_small": true}, +"3608": {"is_small": true}, +"6763": {"is_small": true}, +"3679": {"is_small": true}, +"3680": {"is_small": true}, +"3681": {"is_small": true}, +"3682": {"is_small": true}, +"3691": {"is_small": true}, +"3692": {"is_small": true}, +"3959": {"is_small": true}, +"11558": {"is_small": true}, +"11559": {"is_small": true}, +"3b5:10150": {"is_small": true}, +"3b5:10151": {"is_small": true}, +"11600": {"is_small": true}, +"11604": {"is_small": true}, +"3b5:7871": {"is_small": true} +} diff --git a/vasl_templates/webapp/data/vasl-6.6.4/piece-info.json b/vasl_templates/webapp/data/vasl-6.6.4/piece-info.json new file mode 100644 index 0000000..8774684 --- /dev/null +++ b/vasl_templates/webapp/data/vasl-6.6.4/piece-info.json @@ -0,0 +1,65 @@ +{ +"6996": {"is_small": true}, +"485": {"is_small": true}, +"850": {"is_small": true}, +"849": {"is_small": true}, +"12689": {"is_small": true}, +"856": {"is_small": true}, +"857": {"is_small": true}, +"11336": {"is_small": true}, +"858": {"is_small": true}, +"11337": {"is_small": true}, +"1149": {"is_small": true}, +"1153": {"is_small": true}, +"12687": {"is_small": true}, +"3b5:7613": {"is_small": true}, +"11359": {"is_small": true}, +"3b5:11259": {"is_small": true}, +"1632": {"is_small": true}, +"1636": {"is_small": true}, +"1641": {"is_small": true}, +"1648": {"is_small": true}, +"1982": {"is_small": true}, +"1983": {"is_small": true}, +"1984": {"is_small": true}, +"1985": {"is_small": true}, +"1986": {"is_small": true}, +"1987": {"is_small": true}, +"1988": {"is_small": true}, +"2172": {"is_small": true}, +"2173": {"is_small": true}, +"2176": {"is_small": true}, +"2179": {"is_small": true}, +"11391": {"is_small": true}, +"11392": {"is_small": true}, +"11395": {"is_small": true}, +"11396": {"is_small": true}, +"11440": {"is_small": true}, +"3b5:8401": {"is_small": true}, +"3b5:8402": {"is_small": true}, +"2465": {"is_small": true}, +"2474": {"is_small": true}, +"3252": {"is_small": true}, +"3253": {"is_small": true}, +"3263": {"is_small": true}, +"3422": {"is_small": true}, +"3428": {"is_small": true}, +"6730": {"is_small": true}, +"3605": {"is_small": true}, +"3608": {"is_small": true}, +"6763": {"is_small": true}, +"3679": {"is_small": true}, +"3680": {"is_small": true}, +"3681": {"is_small": true}, +"3682": {"is_small": true}, +"3691": {"is_small": true}, +"3692": {"is_small": true}, +"3959": {"is_small": true}, +"11558": {"is_small": true}, +"11559": {"is_small": true}, +"3b5:10150": {"is_small": true}, +"3b5:10151": {"is_small": true}, +"11600": {"is_small": true}, +"11604": {"is_small": true}, +"3b5:7871": {"is_small": true} +} diff --git a/vasl_templates/webapp/static/css/edit-vo-dialog.css b/vasl_templates/webapp/static/css/edit-vo-dialog.css index 8e8379b..c253e5d 100644 --- a/vasl_templates/webapp/static/css/edit-vo-dialog.css +++ b/vasl_templates/webapp/static/css/edit-vo-dialog.css @@ -3,7 +3,7 @@ .ui-dialog.edit-vo .header { display: flex ; align-items: center ; margin-bottom: 0.5em ; } .ui-dialog.edit-vo .header img.vasl-image { height: 3.5em ; margin-right: 0.5em ; } -.ui-dialog.edit-vo .header img.vasl-image.small-piece { height: 2.7em ; margin-left: 0.4em ; margin-right: 0.9em ; } +.ui-dialog.edit-vo .header img.vasl-image.small-piece { height: 2.7em ; margin-left: 0.4em ; margin-right: 0.4em ; } .ui-dialog.edit-vo .header .content { display: flex ; flex-direction: column ; justify-content: center ; } .ui-dialog.edit-vo .header .content .vo-name { margin-left: 0.5em ; font-size: 125% ; font-weight: bold ; color: #333 ; } .ui-dialog.edit-vo .header .content input.select-vo-image { width: 15px ; position: relative ; top: 10px ; } diff --git a/vasl_templates/webapp/static/css/tabs-ob.css b/vasl_templates/webapp/static/css/tabs-ob.css index 7660733..b2234c9 100644 --- a/vasl_templates/webapp/static/css/tabs-ob.css +++ b/vasl_templates/webapp/static/css/tabs-ob.css @@ -23,7 +23,7 @@ /* nb: the following CSS is shared by vehicles and ordnance */ .panel-ob_vo .sortable .vo-entry { display: flex ; position: relative ; } .panel-ob_vo .sortable .vo-entry img.vasl-image { display: inline-block ; vertical-align: middle ; height: 3.25em ; margin-right: 0.5em ; } -.panel-ob_vo .sortable .vo-entry.small-piece img.vasl-image { height: 2.25em ; margin-left: 0.5em ; margin-right: 0.75em ; } +.panel-ob_vo .sortable .vo-entry.small-piece img.vasl-image { height: 2.5em ; margin-left: 0.375em ; margin-right: 0.875em ; } .panel-ob_vo .sortable .vo-entry .detail { flex-grow: 1 ; display: flex ; flex-direction: column ; justify-content: center ; } .panel-ob_vo .sortable .vo-entry .detail .vo-type { font-style: italic ; font-size: 80% ; color: #666 ; } .panel-ob_vo .sortable .vo-entry .detail .vo-capabilities { max-height: 2.5em ; overflow: hidden ; font-size: 80% ; font-style: italic ; } diff --git a/vasl_templates/webapp/static/vo.js b/vasl_templates/webapp/static/vo.js index 22e9af6..4ea8c51 100644 --- a/vasl_templates/webapp/static/vo.js +++ b/vasl_templates/webapp/static/vo.js @@ -212,7 +212,7 @@ function do_add_vo( vo_type, player_no, vo_entry, vo_image_id, elite, custom_cap var fixed_height = "3.25em" ; if ( is_small_vasl_piece( vo_entry ) ) { div_tag += " small-piece" ; - fixed_height = "2.25em" ; + fixed_height = "2.5em" ; } div_tag += "'>" ; var data = { diff --git a/vasl_templates/webapp/vasl_mod.py b/vasl_templates/webapp/vasl_mod.py index c1462db..9a0480c 100644 --- a/vasl_templates/webapp/vasl_mod.py +++ b/vasl_templates/webapp/vasl_mod.py @@ -277,9 +277,12 @@ class VaslMod: target_gpids = get_vo_gpids( self ) # parse the VASL module and any extensions + fname = os.path.join( data_dir, "vasl-"+self.vasl_version, "piece-info.json" ) + with open( fname, "r", encoding="utf-8" ) as fp: + piece_info = json.load( fp ) for i,files in enumerate( self._files ): _logger.info( "Loading VASL %s: %s", ("module" if i == 0 else "extension"), files[0].filename ) - self._parse_zip_file( files[0], target_gpids, vasl_overrides, expected_multiple_images ) + self._parse_zip_file( files[0], target_gpids, piece_info, vasl_overrides, expected_multiple_images ) # NOTE: The code below may log warnings if we're using an older version of VASL (because we know # about pieces that were added in a later version, but, of course, aren't in the older version). @@ -299,7 +302,7 @@ class VaslMod: gpids = ", ".join( expected_multiple_images.keys() ) _logger.warning( "Expected multiple images but didn't find them: %s", gpids ) - def _parse_zip_file( self, zip_file, target_gpids, vasl_overrides, expected_multiple_images ): #pylint: disable=too-many-locals + def _parse_zip_file( self, zip_file, target_gpids, piece_info, vasl_overrides, expected_multiple_images ): #pylint: disable=too-many-locals """Parse a VASL module or extension.""" # load the build file @@ -329,7 +332,7 @@ class VaslMod: "name": node.attrib["entryName"].strip(), "front_images": front_images, "back_images": back_images, - "is_small": int(node.attrib["height"]) <= 48, + "is_small": piece_info.get( gpid, {} ).get( "is_small", False ), "zip_file": zip_file, } diff --git a/vassal-shim/release/vassal-shim.jar b/vassal-shim/release/vassal-shim.jar index 1af3fd8..31c0d22 100644 Binary files a/vassal-shim/release/vassal-shim.jar and b/vassal-shim/release/vassal-shim.jar differ diff --git a/vassal-shim/src/vassal_shim/Main.java b/vassal-shim/src/vassal_shim/Main.java index 0186532..daf7814 100644 --- a/vassal-shim/src/vassal_shim/Main.java +++ b/vassal-shim/src/vassal_shim/Main.java @@ -82,6 +82,12 @@ public class Main shim.prepareUpload( args[2], args[3], args[4] ) ; System.exit( 0 ) ; } + else if ( cmd.equals( "getpieceinfo" ) ) { + checkArgs( args, 3, false, "the VASL .vmod file, and output file" ) ; + VassalShim shim = new VassalShim( args[1], null ) ; + shim.getPieceInfo( args[2] ) ; + System.exit( 0 ) ; + } else if ( cmd.equals( "version" ) ) { checkArgs( args, 2, false, "the output file" ) ; System.out.println( Info.getVersion() ) ; diff --git a/vassal-shim/src/vassal_shim/VassalShim.java b/vassal-shim/src/vassal_shim/VassalShim.java index 6208530..da24d3a 100644 --- a/vassal-shim/src/vassal_shim/VassalShim.java +++ b/vassal-shim/src/vassal_shim/VassalShim.java @@ -25,6 +25,7 @@ import java.util.regex.Pattern ; import java.util.regex.Matcher ; import java.awt.Point ; import java.awt.Dimension ; +import java.awt.Rectangle ; import javax.xml.parsers.DocumentBuilderFactory ; import javax.xml.parsers.DocumentBuilder ; @@ -1032,6 +1033,35 @@ public class VassalShim logger.info( "All done." ) ; } + public void getPieceInfo( String reportFilename ) + throws IOException, TransformerException, TransformerConfigurationException, ParserConfigurationException + { + // initialize + Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument() ; + Element rootElem = doc.createElement( "pieceInfos" ) ; + doc.appendChild( rootElem ) ; + + // get the info for each piece + logger.info( "Getting piece info..." ) ; + int nPieces = 0 ; + for ( PieceSlot pieceSlot : GameModule.getGameModule().getAllDescendantComponentsOf( PieceSlot.class ) ) { + GamePiece gamePiece = pieceSlot.getPiece() ; + Rectangle bbox = gamePiece.boundingBox() ; + Element elem = doc.createElement( "pieceInfo" ) ; + elem.setAttribute( "gpid", pieceSlot.getGpId() ) ; + elem.setAttribute( "width", Integer.toString( bbox.width ) ) ; + elem.setAttribute( "height", Integer.toString( bbox.height ) ) ; + rootElem.appendChild( elem ) ; + nPieces += 1 ; + } + logger.info( "- Found " + Integer.toString(nPieces) + " pieces." ) ; + + // save the results + logger.debug( "Saving piece info report: " + reportFilename ) ; + File outputFile = new File( reportFilename ) ; + Utils.saveXml( doc, reportFilename ) ; + } + private VASSAL.build.module.Map selectMap() { // NOTE: VASL 6.5.0 introduced a new map ("Casualties") as part of the new Casualties Bin feature,