import svgwrite import json from typing import List import os from draw import draw_effects_resources_for_row with open('src/data/heron_skin.json') as f: all_skin_data = json.load(f) # Params x_width = 298 y_height = 417 border_width_x = 12 border_width_y = 17 border_upper_offset = 5 title_y_offset = 24 title_font_size = 19 subtitle_font_size = 13 cost_right_offset = 38 effect_text_size = 14 row_1_base_y = 280 row_2_base_y = 375 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' } gradient_colors = { 'red': 'red', 'blue': 'blue', 'yellow': 'yellow', 'green': 'green' } icon_colors = { 'yellow': ['#ff9935', '#ffe744'] } with open('src/data/cards_data.json') as f: cards: List = json.load(f)['cards'] for card_data in cards: # Get card skin data card_skin_data = all_skin_data[str(card_data['id'])] # Create a new SVG drawing 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')) # 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) # 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') # 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']])) # Draw title area # dwg.add(dwg.rect(insert=(0, 0), size=(str(x_width) + 'px', '50px'), fill='white')) 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(title_font_size) + 'px', font_weight="bold", font_family='Helvetica')) # Draw type area dwg.add(dwg.text(card_skin_data['type'], 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')) # 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)')) # 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')) # 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=(border_width_x, 265), size=(str(30) + 'px', str(y_height - 265 - border_width_y) + 'px'), fill='url(#grad1)')) # 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) 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')) # Save the SVG file dwg.save()