2017-04-22 18:13:01 -04:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
import json
|
|
|
|
import math
|
|
|
|
import os
|
2017-07-13 18:50:32 -04:00
|
|
|
import subprocess
|
2017-04-27 19:53:23 -04:00
|
|
|
import sys
|
2017-04-22 18:13:01 -04:00
|
|
|
|
2017-07-13 18:50:32 -04:00
|
|
|
from lxml import etree
|
|
|
|
from PIL import Image
|
|
|
|
|
2017-04-27 19:53:23 -04:00
|
|
|
if getattr(sys, 'frozen', False): # we are running in a bundle
|
|
|
|
bundle_dir = sys._MEIPASS
|
|
|
|
else: # we are running in a normal Python environment
|
|
|
|
bundle_dir = os.path.dirname(os.path.abspath(__file__))
|
2017-04-22 18:13:01 -04:00
|
|
|
|
2017-07-13 18:50:32 -04:00
|
|
|
CARD_WIDTH = 181 * 4
|
|
|
|
CARD_HEIGHT = 253 * 4
|
|
|
|
|
|
|
|
def setText(tree, id, text):
|
|
|
|
element = tree.find('.//*[@id="' + id + '"]')
|
|
|
|
if element is None:
|
|
|
|
print("id", id, "not found")
|
|
|
|
return
|
|
|
|
elif element.tag == "{http://www.w3.org/2000/svg}flowRoot":
|
2017-07-13 23:22:19 -04:00
|
|
|
for e in element.findall("{http://www.w3.org/2000/svg}flowPara"):
|
|
|
|
element.remove(e) # clear child paragraphs
|
|
|
|
lines = str(text).splitlines()
|
|
|
|
for line in lines:
|
|
|
|
etree.SubElement(element, "{http://www.w3.org/2000/svg}flowPara").text=line
|
2017-07-13 18:50:32 -04:00
|
|
|
else:
|
2017-08-03 18:14:48 -04:00
|
|
|
element.text = str(text)
|
2017-07-13 18:50:32 -04:00
|
|
|
|
|
|
|
def removeElement(tree, id):
|
|
|
|
mark = tree.find('.//*[@id="' + id + '"]')
|
|
|
|
if mark is not None:
|
|
|
|
mark.getparent().remove(mark)
|
|
|
|
|
|
|
|
def makeSVG(base, properties):
|
|
|
|
tree = etree.parse(base)
|
|
|
|
for id, text in properties.items():
|
|
|
|
if id not in ["count", "art"]:
|
|
|
|
setText(tree, id, text)
|
|
|
|
|
|
|
|
# remove HP mark if there is no hp
|
|
|
|
if "hp" not in properties:
|
|
|
|
removeElement(tree, "hpMark")
|
|
|
|
|
2017-07-13 23:21:58 -04:00
|
|
|
# remove setup box if there is no setup
|
|
|
|
if "setup" not in properties:
|
|
|
|
removeElement(tree, "setupBox")
|
|
|
|
|
2017-07-13 18:50:32 -04:00
|
|
|
if "art" in properties:
|
|
|
|
art = tree.find('.//*[@id="art"]')
|
|
|
|
if art is not None:
|
|
|
|
art.set("{http://www.w3.org/1999/xlink}href",
|
|
|
|
"file://" + bundle_dir + "/" + properties["art"])
|
|
|
|
return tree
|
|
|
|
|
|
|
|
def addCardToBase(svg, baseImg, baseX, cardNum):
|
|
|
|
# TODO: possible to remove all this writing to temp files?
|
|
|
|
dest = "out/fig" + str(cardNum)
|
|
|
|
svg.write(dest + ".svg")
|
|
|
|
subprocess.call(["inkscape", "-z", "-f", dest + ".svg", "-w",
|
|
|
|
str(CARD_WIDTH), "-e", dest + ".png"])
|
|
|
|
cardImg = Image.open(dest + ".png")
|
2017-04-22 18:13:01 -04:00
|
|
|
baseImg.paste(cardImg, ((cardNum % baseX) * cardImg.width,
|
|
|
|
int(cardNum / baseX) * cardImg.height))
|
|
|
|
|
2017-07-13 18:50:32 -04:00
|
|
|
def makeFace(baseImage, baseX, cardNum, base, card):
|
|
|
|
fig = makeSVG(base, card)
|
|
|
|
addCardToBase(fig, baseImage, baseX, cardNum)
|
|
|
|
|
2017-04-22 18:13:01 -04:00
|
|
|
def makeFaces(deckJson, outfile):
|
2017-07-13 18:50:32 -04:00
|
|
|
baseX = math.ceil(math.sqrt(len(deckJson['deck']) + len(deckJson['character']) * 2))
|
|
|
|
baseImage = Image.new('RGB', (CARD_WIDTH * baseX,
|
|
|
|
CARD_HEIGHT * baseX))
|
|
|
|
|
|
|
|
cardType = deckJson["type"]
|
2017-04-22 18:13:01 -04:00
|
|
|
|
|
|
|
cardNum = 0
|
2017-07-13 23:21:58 -04:00
|
|
|
# Make a card for each hero character card
|
2017-07-13 18:50:32 -04:00
|
|
|
if cardType == "hero":
|
|
|
|
for card in deckJson['character']:
|
|
|
|
makeFace(baseImage, baseX, cardNum,
|
|
|
|
os.path.join("images", cardType, "charFront.svg"), card)
|
|
|
|
cardNum += 1
|
|
|
|
makeFace(baseImage, baseX, cardNum,
|
|
|
|
os.path.join("images", cardType, "charBack.svg"), card)
|
|
|
|
cardNum += 1
|
2017-04-22 18:13:01 -04:00
|
|
|
|
2017-07-13 23:21:58 -04:00
|
|
|
# Make a character and instructions card for each villain card
|
|
|
|
elif cardType == "villain":
|
|
|
|
for card in deckJson['character']:
|
|
|
|
front = card["front"]
|
|
|
|
front["name"] = card["name"]
|
|
|
|
back = card["back"]
|
|
|
|
back["name"] = card["name"]
|
|
|
|
makeFace(baseImage, baseX, cardNum,
|
|
|
|
os.path.join("images", cardType, "character.svg"),
|
|
|
|
front)
|
|
|
|
cardNum += 1
|
|
|
|
makeFace(baseImage, baseX, cardNum,
|
|
|
|
os.path.join("images", cardType, "character.svg"),
|
|
|
|
back)
|
|
|
|
cardNum += 1
|
|
|
|
|
|
|
|
makeFace(baseImage, baseX, cardNum,
|
|
|
|
os.path.join("images", cardType, "instructions.svg"),
|
|
|
|
front)
|
|
|
|
cardNum += 1
|
|
|
|
makeFace(baseImage, baseX, cardNum,
|
|
|
|
os.path.join("images", cardType, "instructions.svg"),
|
|
|
|
back)
|
|
|
|
cardNum += 1
|
|
|
|
|
2017-07-13 18:50:32 -04:00
|
|
|
|
|
|
|
# Make a card for each card
|
2017-04-22 18:13:01 -04:00
|
|
|
for card in deckJson['deck']:
|
2017-07-13 18:50:32 -04:00
|
|
|
makeFace(baseImage, baseX, cardNum,
|
|
|
|
os.path.join("images", cardType, "card.svg"), card)
|
2017-04-22 18:13:01 -04:00
|
|
|
cardNum += 1
|
|
|
|
|
|
|
|
baseImage.save(outfile + ".png", "PNG")
|
2017-07-13 18:50:32 -04:00
|
|
|
return baseX
|
2017-04-22 18:13:01 -04:00
|
|
|
|
2017-07-13 23:21:58 -04:00
|
|
|
def makeCardJson(template, nickname, description, cardID):
|
|
|
|
card = template.copy()
|
|
|
|
card.update({"Nickname": nickname,
|
2017-08-03 18:15:09 -04:00
|
|
|
"Description": description,
|
|
|
|
"CardID": cardID})
|
2017-07-13 23:21:58 -04:00
|
|
|
return card
|
|
|
|
|
|
|
|
def makeDoubleSidedCardJson(template, nickname, descriptionFront,
|
2017-08-03 18:15:09 -04:00
|
|
|
descriptionBack, cardID):
|
2017-07-13 23:21:58 -04:00
|
|
|
cardBack = makeCardJson(template, nickname, descriptionBack, cardID + 1)
|
|
|
|
|
|
|
|
card = template.copy()
|
|
|
|
card.update({"Nickname": nickname,
|
2017-08-03 18:15:09 -04:00
|
|
|
"Description": descriptionFront,
|
|
|
|
"CardID": cardID,
|
|
|
|
"States": {"2": cardBack}})
|
2017-07-13 23:21:58 -04:00
|
|
|
return card
|
|
|
|
|
2017-07-13 18:50:32 -04:00
|
|
|
def makeJson(deckJson, imgWidth, outfile):
|
2017-04-27 19:53:23 -04:00
|
|
|
with open(bundle_dir + "/templates/deck.json") as f:
|
2017-04-22 18:13:01 -04:00
|
|
|
outJson = json.load(f)
|
2017-04-27 19:53:23 -04:00
|
|
|
with open(bundle_dir + "/templates/card.json") as f:
|
2017-04-22 18:13:01 -04:00
|
|
|
cardTemplate = json.load(f)
|
|
|
|
|
|
|
|
# number of cards in x and y direction
|
|
|
|
outJson['ObjectStates'][0]['CustomDeck']['1'].update(
|
|
|
|
{"NumWidth": imgWidth,
|
2017-07-13 18:50:32 -04:00
|
|
|
"NumHeight": imgWidth,
|
2017-04-22 18:13:01 -04:00
|
|
|
#"FaceURL": "http://adam-desktop.dyn.wpi.edu:8000/" + outfile + ".png",
|
|
|
|
"FaceURL": "file://" + os.getcwd() + "/" + outfile + ".png",
|
|
|
|
"BackURL": "http://cloud-3.steamusercontent.com/ugc/156906385556221451/CE2C3AFE1759790CB0B532FFD636D05A99EC91F4/"})
|
|
|
|
|
|
|
|
# decks start at (10 * deck id)
|
|
|
|
cardNum = 100
|
2017-07-13 23:21:58 -04:00
|
|
|
|
|
|
|
if deckJson["type"] == "hero":
|
|
|
|
for card in deckJson['character']:
|
|
|
|
outJson['ObjectStates'][0]['DeckIDs'].append(cardNum)
|
|
|
|
cardOut = makeDoubleSidedCardJson(
|
|
|
|
cardTemplate, card['name'], "Active", "Incapacitated", cardNum)
|
|
|
|
outJson['ObjectStates'][0]['ContainedObjects'].append(cardOut)
|
|
|
|
cardNum += 2
|
|
|
|
|
|
|
|
elif deckJson["type"] == "villain":
|
|
|
|
for card in deckJson['character']:
|
|
|
|
outJson['ObjectStates'][0]['DeckIDs'].append(cardNum)
|
|
|
|
cardOut = makeDoubleSidedCardJson(
|
|
|
|
cardTemplate, card['name'], "Front", "Back", cardNum)
|
|
|
|
outJson['ObjectStates'][0]['ContainedObjects'].append(cardOut)
|
|
|
|
cardNum += 2
|
|
|
|
|
|
|
|
outJson['ObjectStates'][0]['DeckIDs'].append(cardNum)
|
|
|
|
cardOut = makeDoubleSidedCardJson(
|
|
|
|
cardTemplate, card['name'] + " instructions", "Front", "Back", cardNum)
|
|
|
|
outJson['ObjectStates'][0]['ContainedObjects'].append(cardOut)
|
|
|
|
cardNum += 2
|
2017-04-22 18:13:01 -04:00
|
|
|
|
|
|
|
for card in deckJson['deck']:
|
2017-07-18 18:27:08 -04:00
|
|
|
for i in range(0, card.get('count', 1)):
|
2017-04-22 18:13:01 -04:00
|
|
|
outJson['ObjectStates'][0]['DeckIDs'].append(cardNum)
|
|
|
|
|
|
|
|
# add a card object thing for each card, and give it a name
|
2017-07-13 23:21:58 -04:00
|
|
|
cardOut = makeCardJson(cardTemplate, card['name'], card.get('keywords', ""), cardNum)
|
2017-04-22 18:13:01 -04:00
|
|
|
outJson['ObjectStates'][0]['ContainedObjects'].append(cardOut)
|
|
|
|
cardNum += 1
|
|
|
|
|
|
|
|
with open(outfile + ".json", "w") as f:
|
|
|
|
json.dump(outJson, f)
|
|
|
|
|
2017-04-27 19:53:23 -04:00
|
|
|
if __name__ == '__main__':
|
|
|
|
if len(sys.argv) < 3:
|
|
|
|
print("not enough arguments!")
|
|
|
|
inputJson = input("Input file: ")
|
|
|
|
outfile = input("Output file (no suffix): ")
|
|
|
|
else:
|
|
|
|
inputJson = sys.argv[1]
|
|
|
|
outfile = sys.argv[2]
|
|
|
|
|
|
|
|
with open(inputJson) as f:
|
|
|
|
deckJson = json.load(f)
|
|
|
|
|
2017-07-13 18:50:32 -04:00
|
|
|
imgWidth = makeFaces(deckJson, outfile)
|
|
|
|
makeJson(deckJson, imgWidth, outfile)
|