WIP: begin using drawsvg

This commit is contained in:
2024-06-30 19:42:38 +02:00
parent 790ae32081
commit 96eb2f6c4a
8 changed files with 428 additions and 181 deletions
+172 -130
View File
@@ -1,13 +1,17 @@
import svgwrite
import drawsvg as dw
import json
from typing import List
import os
from draw import create_pentagon, draw_effects_resources_for_row
from draw_functions import create_gold_icon
with open("src/data/translation_fr.json", encoding="utf-8") as f:
translation_fr: dict = json.load(f)
with open('src/data/heron_skin.json') as f:
all_skin_data = json.load(f)
with open("src/data/heron_skin.json", encoding="utf-8") as f:
all_skin_data: dict = json.load(f)
# Params
x_width = 298
@@ -27,168 +31,206 @@ row_1_to_2_separator_y = 345
row_1_to_2_separator_shorten_by = 20
background_colors = {
'blue': 'lightblue',
'red': 'lightcoral',
'yellow': 'rgb(206, 182, 167)',
'green': 'lightgreen',
'base': 'lightgrey'
"blue": "lightblue",
"red": "lightcoral",
"yellow": "rgb(206, 182, 167)",
"green": "lightgreen",
"base": "lightgrey",
}
gradient_colors = {
'red': 'red',
'blue': 'blue',
'yellow': 'yellow',
'green': 'green'
}
gradient_colors = {"red": "red", "blue": "blue", "yellow": "yellow", "green": "green"}
icon_colors = {
'yellow': ['#ff9935', '#ffe744']
}
icon_colors = {"yellow": ["#ff9935", "#ffe744"]}
with open('src/data/cards_data.json') as f:
cards: List = json.load(f)['cards']
with open("src/data/cards_data.json", encoding="utf-8") as f:
cards: List = json.load(f)["cards"]
shadowFilter = dw.Filter(id="drop-shadow")
shadowFilter.append(dw.FilterItem("feDropShadow", dx=1, dy=1, stdDeviation=0))
# Draw faction icon
faction_icon = dw.Group(id="faction_icon")
faction_icon.append(
dw.Circle(
cx=1,
cy=1,
r=20,
fill="black",
filter=shadowFilter
)
)
faction_icon.append(
dw.Circle(
cx=0,
cy=0,
r=20,
fill="url(#grad2)",
)
)
for card_data in cards:
# Get card skin data
try:
card_skin_data = all_skin_data[str(card_data['id'])]
card_skin_data = all_skin_data[str(card_data["id"])]
except KeyError:
print('Missing skin data for card id:', card_data['id'], 'using default skin data')
card_skin_data = { 'title': card_data['name'], 'image_path': '../../img/missing.png'}
print(
"Missing skin data for card id:", card_data["id"], "using default skin data"
)
card_skin_data = {
"title": card_data["name"],
"image_path": "../../img/missing.png",
}
# Create a new SVG drawing
output_dir = 'output/' + all_skin_data['skin_name']
output_dir = "output/" + all_skin_data["skin_name"]
os.makedirs(output_dir, exist_ok=True)
dwg = svgwrite.Drawing('output/' + all_skin_data['skin_name'] + '/' + str(card_data['id']).zfill(3) + '.svg', profile='tiny', size=(str(x_width) + 'px', str(y_height) + 'px'))
d = dw.Drawing(x_width, y_height)
d.append(shadowFilter)
# Define linear colored gradient
gradient = dwg.linearGradient(start=(0, 0), end=(1, 0), id="grad1")
gradient.add_stop_color(0, gradient_colors[card_data['faction']], opacity=1)
gradient.add_stop_color(1, gradient_colors[card_data['faction']], opacity=0)
dwg.defs.add(gradient)
gradient = dw.LinearGradient(0, 0, 1, 0, gradientUnits="objectBoundingBox",id="grad1")
gradient.add_stop(0, gradient_colors[card_data["faction"]], opacity=1)
gradient.add_stop(1, gradient_colors[card_data["faction"]], opacity=0)
d.append(dw.Use(gradient, None, None))
# Define linear colored gradient for faction icon
gradient_faction_icon = dwg.linearGradient(start=(0, 1), end=(0, 0), id="grad2")
gradient_faction_icon.add_stop_color(0, icon_colors[card_data['faction']][0], opacity=1)
gradient_faction_icon.add_stop_color(1, icon_colors[card_data['faction']][1], opacity=1)
dwg.defs.add(gradient_faction_icon)
# # Define a drop shadow filter
# filter_shadow = dwg.defs.add(dwg.filter(id='dropShadow'))
# filter_shadow.feGaussianBlur(in_='SourceAlpha', stdDeviation=3)
# filter_shadow.feOffset(dx=3, dy=3, result='offsetblur')
# filter_shadow.feFlood(flood_color='black', flood_opacity=0.5)
# filter_shadow.feComposite(in2='offsetblur', operator='in')
# filter_shadow.feMerge().feMergeNode(in_='SourceGraphic')
gradient_faction_icon = dw.LinearGradient(0, 1, 0, 0, gradientUnits="objectBoundingBox",id="grad2")
gradient_faction_icon.add_stop(0, icon_colors[card_data["faction"]][0], opacity=1)
gradient_faction_icon.add_stop(1, icon_colors[card_data["faction"]][1], opacity=1)
d.append(dw.Use(gradient_faction_icon, None, None))
# Draw card background
dwg.add(dwg.rect(insert=(0, 0), size=(str(x_width) + 'px', str(y_height) + 'px'), rx=15, ry=18, fill='black'))
dwg.add(dwg.rect(insert=(border_width_x, border_width_y - border_upper_offset), size=(str(x_width - border_width_x*2) + 'px', str(y_height - border_width_y*2 + border_upper_offset) + 'px'), rx=0, ry=0, fill=background_colors[card_data['faction']]))
d.append(dw.Rectangle(0, 0, x_width, y_height, rx=15, ry=18, fill="black"))
d.append(
dw.Rectangle(
border_width_x,
border_width_y - border_upper_offset,
x_width - border_width_x * 2,
y_height - border_width_y * 2 + border_upper_offset,
rx=0,
ry=0,
fill=background_colors[card_data["faction"]],
)
)
# Draw title area
# dwg.add(dwg.rect(insert=(0, 0), size=(str(x_width) + 'px', '50px'), fill='white'))
card_title = card_skin_data['title']
temp_title_font_size = title_font_size
card_title = card_skin_data["title"]
TEMP_TITLE_FONT_SIZE = title_font_size
if len(card_title) > 20:
temp_title_font_size = title_font_size_small
TEMP_TITLE_FONT_SIZE = title_font_size_small
if len(card_title) > 23:
temp_title_font_size = title_font_size_small - 2
dwg.add(dwg.text(card_skin_data['title'], insert=(x_width/2, title_y_offset + border_width_y - border_upper_offset), text_anchor='middle', fill='black', font_size=str(temp_title_font_size) + 'px', font_weight="bold", font_family='Helvetica'))
TEMP_TITLE_FONT_SIZE = title_font_size_small - 2
d.append(
dw.Text(
card_title,
x=x_width / 2,
y=title_y_offset + border_width_y - border_upper_offset,
text_anchor="middle",
fill="black",
font_size=TEMP_TITLE_FONT_SIZE,
font_weight="bold",
font_family="Helvetica",
)
)
# Draw type area
card_type_text = ""
if card_data['card_type'] == 'champion':
card_type_text = "Champion"
elif card_data['card_type'] == 'action':
card_type_text = "Action"
if 'flavor_text_type' in card_skin_data.keys():
card_type_text += ', ' + card_skin_data['flavor_text_type']
dwg.add(dwg.text(card_type_text, insert=(x_width/2, title_y_offset + title_font_size + 10), text_anchor='middle', fill='black', font_size=str(subtitle_font_size) + 'px', font_family='Helvetica'))
card_type_text = translation_fr["card_type"].get(
card_data["card_type"], card_data["card_type"]
)
if "flavor_text_type" in card_skin_data.keys():
card_type_text += ", " + card_skin_data["flavor_text_type"]
d.append(
dw.Text(
card_type_text,
font_size=subtitle_font_size,
x=x_width / 2,
y=title_y_offset + title_font_size + 10,
text_anchor="middle",
fill="black",
font_family="Helvetica",
)
)
# Draw faction icon
dwg.add(dwg.circle(center=(border_width_x + 23 + 1, border_width_y - border_upper_offset + 20 + 4 + 1), r=20, fill='black'))
dwg.add(dwg.circle(center=(border_width_x + 23, border_width_y - border_upper_offset + 20 + 4), r=20, fill='url(#grad2)'))
d.append(dw.Use(faction_icon, border_width_x + 23 + 1,border_width_y - border_upper_offset + 20 + 4 + 1 ))
# dwg.add(dwg.image(card_data['faction_icon'], insert=(x_width - 30 - 15, 30 - 15), size=(30, 30)))
# Draw cost circle
dwg.add(dwg.circle(center=(x_width - cost_right_offset + 2, 19 + border_width_y + 2), r=21, fill='rgb(202, 129, 25)'))
dwg.add(dwg.circle(center=(x_width - cost_right_offset, 19 + border_width_y), r=20, fill='yellow'))
dwg.add(dwg.text(str(card_data['cost']), insert=(x_width - cost_right_offset, 26 + border_width_y), text_anchor='middle', fill='black', font_size='24px', font_weight="bold", font_family='Helvetica'))
# dwg.add(
# dwg.circle(
# center=(x_width - cost_right_offset + 2, 19 + border_width_y + 2),
# r=21,
# fill="rgb(202, 129, 25)",
# )
# )
# dwg.add(
# dwg.circle(
# center=(x_width - cost_right_offset, 19 + border_width_y),
# r=20,
# fill="yellow",
# )
# )
# dwg.add(
# dwg.text(
# str(card_data["cost"]),
# insert=(x_width - cost_right_offset, 26 + border_width_y),
# text_anchor="middle",
# fill="black",
# font_size="24px",
# font_weight="bold",
# font_family="Helvetica",
# )
# )
d.append(dw.Use(create_gold_icon(card_data["cost"]), x_width - cost_right_offset, 19 + border_width_y))
d.save_svg(
"output/"
+ all_skin_data["skin_name"]
+ "/"
+ str(card_data["id"]).zfill(3)
+ ".svg"
)
continue
# Draw image area
dwg.add(dwg.rect(insert=(0, 65), size=(str(x_width) + 'px', '200px'), fill='black'))
dwg.add(dwg.image(card_skin_data['image_path'], insert=(0, 65), size=(x_width, 200)))
dwg.add(dwg.rect(insert=(0, 65), size=(str(x_width) + "px", "200px"), fill="black"))
dwg.add(
dwg.image(card_skin_data["image_path"], insert=(0, 65), size=(x_width, 200))
)
dwg.add(dwg.rect(insert=(border_width_x, 265), size=(str(30) + 'px', str(y_height - 265 - border_width_y) + 'px'), fill='url(#grad1)'))
dwg.add(
dwg.rect(
insert=(border_width_x, 265),
size=(str(30) + "px", str(y_height - 265 - border_width_y) + "px"),
fill="url(#grad1)",
)
)
# If champion, draw champion action icon
if card_data['card_type'] == 'champion':
if card_data["card_type"] == "champion":
row_1_icon_x = border_width_x + 35
dwg.add(dwg.circle(center=(row_1_icon_x + 1, row_1_base_y + 20 + 1), r=15, fill='#111'))
dwg.add(dwg.circle(center=(row_1_icon_x, row_1_base_y + 20), r=15, fill='#555'))
dwg.add(
dwg.circle(
center=(row_1_icon_x + 1, row_1_base_y + 20 + 1), r=15, fill="#111"
)
)
dwg.add(dwg.circle(center=(row_1_icon_x, row_1_base_y + 20), r=15, fill="#555"))
# TODO: figure out nb of effects and adjust row_1_x_offset accordingly
def is_base_effect(array: List):
return not 'effect_type' in array.keys() or array['effect_type'] == 'champion_action'
card_effects: List = card_data['effects']
base_effects = list(filter(is_base_effect, card_effects))
other_effects = list(filter(lambda x: not is_base_effect(x), card_effects))
# card_effects = card_data['row_1']
# row_1_nb_effects = len(card_data['row_1'].keys())
# Draw row 1 stats
draw_effects_resources_for_row(dwg, base_effects, row_1_base_y, x_width)
# Draw row 1 text
for effect in base_effects:
effect_text_1 = ""
if effect.get('effect') == 'draw':
effect_text_1 = "Piochez une carte."
dwg.add(dwg.text(effect_text_1, insert=(x_width/2, row_1_base_y + 57), text_anchor='middle', fill='black', font_size=str(effect_text_size) + 'px', font_family='Helvetica'))
if other_effects:
# Draw row 1 to row 2 separator
dwg.add(dwg.line(start=(0 + row_1_to_2_separator_shorten_by, row_1_to_2_separator_y), end=(x_width - row_1_to_2_separator_shorten_by, row_1_to_2_separator_y), stroke='black', stroke_width=1))
for effect in other_effects:
# TODO handle case where there is both faction combo and trash can
if effect.get('effect_type') == 'faction_combo':
row_2_icon_x = border_width_x + 35
row_2_icon_y = row_2_base_y - 5
dwg.add(dwg.circle(center=(row_2_icon_x + 1, row_2_icon_y + 1), r=15, fill='black'))
dwg.add(dwg.circle(center=(row_2_icon_x, row_2_icon_y), r=15, fill='url(#grad2)'))
# Draw row 2 stats
draw_effects_resources_for_row(dwg, [effect], row_2_base_y - 25, x_width)
# Draw row 2 effect text
effect_text_2 = ""
if effect.get('effect') == 'prepare':
effect_text_2 = "Mobilisez un champion."
dwg.add(dwg.text(effect_text_2, insert=(x_width/2, row_2_base_y), text_anchor='middle', fill='black', font_size=str(effect_text_size) + 'px', font_family='Helvetica'))
draw_effects(
dwg=dwg,
card_effects=card_data["effects"],
border_width_x=border_width_x,
effect_text_size=effect_text_size,
row_1_base_y=row_1_base_y,
row_1_to_2_separator_shorten_by=row_1_to_2_separator_shorten_by,
row_1_to_2_separator_y=row_1_to_2_separator_y,
row_2_base_y=row_2_base_y,
x_width=x_width,
)
# If champion, draw champion shield with defense
if card_data['card_type'] == 'champion':
if not card_data['guard']:
pentagon_points = create_pentagon(center=(x_width - border_width_x - 15, y_height - 30), radius=28)
dwg.add(dwg.polygon(points=pentagon_points, fill='darkgrey', stroke='#eee', stroke_width=1))
# dwg.add(dwg.circle(center=(x_width - border_width_x - 15, y_height - 30), r=27, fill='darkgrey'))
# dwg.add(dwg.circle(center=(x_width - border_width_x - 15, y_height - 30), r=25, fill='lightgrey'))
dwg.add(dwg.text(str(card_data['defense']), insert=(x_width - border_width_x - 15, y_height - 20), text_anchor='middle', fill='black', font_size='28px', font_weight="bold", font_family='Helvetica'))
else:
pentagon_points = create_pentagon(center=(x_width - border_width_x - 15, y_height - 30), radius=28)
dwg.add(dwg.polygon(points=pentagon_points, fill='black', stroke='lightgrey', stroke_width=1))
# dwg.add(dwg.circle(center=(x_width - border_width_x - 15, y_height - 30), r=27, fill='lightgrey'))
# dwg.add(dwg.circle(center=(x_width - border_width_x - 15, y_height - 30), r=25, fill='#111'))
# Draw guard rectangle with text inside, above the shield
dwg.add(dwg.rect(insert=(x_width - border_width_x - 40, y_height - 72), size=(49, 17), fill='lightgrey'))
dwg.add(dwg.rect(insert=(x_width - border_width_x - 39, y_height - 71), size=(47, 15), fill='#111'))
dwg.add(dwg.text('Garde', insert=(x_width - border_width_x - 15, y_height - 59), text_anchor='middle', fill='white', font_size='12px', font_weight="bold", font_family='Helvetica'))
dwg.add(dwg.text(str(card_data['defense']), insert=(x_width - border_width_x - 15, y_height - 20), text_anchor='middle', fill='white', font_size='28px', font_weight="bold", font_family='Helvetica'))
if card_data["card_type"] == "champion":
draw_champion_shield(dwg, card_data, x_width, y_height, border_width_x)
# Save the SVG file
dwg.save()