Support for automatic generation of trading cards
This repository will be filled slowly with python code aiming to provide easy generation of trading cards using the commonly known tools Inkscape and Excel. I aim to work 1 to 2 hours each monday in my free time on this project, but some mondays have to be skipped when I want to do other stuff. If you are interested in this project growing faster, consider to create a PR by yourself ;). I already had a repository tc_tools, but deleted that since it was more of a collection of prototypes and I want to do it more "properly" this time. If you have ideas or you see bugs/problems with the project, feel free to create an issue on Github.
The big idea is, that the generation of custom cardgames will be made easier.
- If you are not affine to IT you should be able to describe your custom card game using an svg template (generated by hand with Inkscape) an Excel sheet and maybe a configuration textfile and then just run tc_tools from command line or using a leightweight GUI to generate your custom cardgame (or customizable example cardgames if necessary).
- If you want to add some logic which is not supported by the command line/GUI you should be able to import tc_tools into your own Python project and use some dedicated objects in order to implement your custom logic fast and easy
The only way to already use the project is to clone or download it on a computer with a local python instalation (I use Python 3.10.7) and run
gui/window.py
using your local python for the GUI.
When you open the GUI you should see something like this:
Then just pick your Excel file, your template SVG and your configuration file and press "Render deck" and it will run :).
The Excel file should contain rowwise information about all your cards.
The SVG file should contain a template of how your cards should look like.
The processor then does roughly the following to your template svg for each row of the excel file:
- replaces the path to an image labeled "image_label" by the respective content of the column named "image_label" or "image_label.href" (since 0.2.0)
- replaces the text content of a text element labeled "text_label" by the respective content of the column named "text_label" or "text_label.text" (since 0.3.0)
Be careful with your labels, don't let two columns refer to the same object and don't label two objects the same.
The configuration file contains information about your system and your preferences by lines of the form <parameter>:<value>
.
The only supported parameter is currently inkscape_path
which is mandatory to set to the absolute path of your local inkscape installation.
Currently it is only possible to replace images as you like. More possibilities will come in the future.
You can run processor.base_process(options_path, excel_path, svg_path, single_item_process)
with a custom method single_item_process(svg_root: SVGRoot, data: dict) -> None
which should manipulate the svg_root
object based on the data in data
representing a row of the Excel file.
The following functions are supported by `tc_tools``:
- Use
svg_element = svg_root.get_by_label(label) -> SVGElement
to get anSVGElement
object corresponding to an inkscape object labeled withlabel
(since 0.2.0) - Use
svg_element.get_label
andsvg_element.set_label
refering to the inkscape labels (since 0.2.0) - If
svg_element
is anSVGImage
, usesvg_element.get_href
andsvg_element.set_href
(since 0.2.0) - If
svg_element
is anSVGText
, usesvg_element.get_text_content
andsvg_element.set_text_content
(since 0.3.0)
The project has the following dependencies (with the version used in development, others probably also work)
pandas 2.0.3
(for excel reading)PySimpleGUI 4.60.5
(for GUI)matplotlib 3.8.0
(for image comparison when testing)
For different components of an SVG, there should be different custom SVG objects yielding the same structure.
I plan to structure the process in a kind-of layered fashion involving the following layers (moduls):
persistence
: read data from disk and save data to disk- create ElementTree from svg
- create svg from ElementTree
- render svg to png or pdf (using Inkscape as "man in the middle")
- read an excel file and create a respective data source object
mapper
: extract and transform data types into others- extract custom SVG object structure from ElementTree
- copy custom SVG object structure
- merge custom SVG object and ElementTree to ElementTree
manipulator
: change custom SVG objects- move, rotate, align elements etc.
In a later stage of the project, I possibly will add another layer between mapper and manipulator for png manipulation.
Another module, the processor
module should then control the data flow between the layers and itself be called by the gui
(later maybe also by the command_line
).
Here is a diagram, because diagrams are cool:
- the main branch is a version branch and therefore only updated when a new version is released
- hot fixes will be commited to the main branch directly
- the future branch contains the current WIP state of the next bigger version
- If you want to contribute you can create a PR to the future branch that realizes one of the points of the next section
- I want a linear git history, so everything should be rebased before a fast forward merge is performed
- The versioning will be according to standard practices
- changes to README.md and other supplementary files do not result in a version change
- hot fixes lead to a increase of the last version number, e.g. 0.0.0 -> 0.0.1
- the merge of the future branch into main will result in an increase of the second version number, e.g. 0.0.99 -> 0.1.0
- If all milestones are reached, the first version number is increased, e.g. 0.99.99 -> 1.0.0. Note that all deprecated features are removed in such a major change, so versions with a different first version number might not be compatible
- I want to refine the application feature by feature in a kind-of agile process (every in-between version should be running)
- tests of behaviour for all methods (created while implementing)
- no tests of implementation
- no useless documentation in code
- make it typesafe
- in the directory
manual_tests
there are additional non-automatic tests. These require a suitable local setup with inkscape up and running. You can check this out for more information. - the GUI is not automatically tested but just checked manually
- Support for Text, Image, Rectangle, Groups
- Text content can be changed
- Image can be switched
- SVG root can be searched for elements by label, text content
- Elements can be repositioned, resized, rotated and reflected
- Font-family, font-size and font-weight can be changed
- Example Projects: Domino and Skat
Next I will work on a whole bunch of geometric operations
- Create and map position attributes
- Create and map scaling attributes
- Create and map rotation attributes
- Create and map reflection attributes
- Add manual test for geometric operations
- Create
SVGText
representing Texts onSVGElement
level - Map inkscape text objects to
SVGText
- Map
SVGText
back - Let processor map columns linked to text objects replace the text content
- Create manual tests for that
In version 0.3.0 you are able to replace the text of your cards
- save inkscape labels when mapping to
SVGRoot
- make
SVGRoot
searchable by inkscape labels - create an
SVGElement
representing an image with propertyhref
- map images of the ElementTree to
SVGElement
images - support the mapping of changed
href
properties - make controller to identify excel columns of form
<label>.href
and change thehref
property of element with respective inkscape label if it is an image (otherwise throw exception). - create
SVGCollection
for SVG Elements with children - map Elements with children to
SVGCollection
and its children recursively - recursively map Elements back
- add support for recursively found label
- make manual tests for new behaviour
-
make a domino example project of domino, where the background the separating image and the images used for the dots can be customized(will do example projects later)
In version 0.2.0 you are able to exchange pictures in your card making.
- create the base module structure
- implement a method that reads an svg and creates an ElementTree object
- implement a method that writes an svg from an ElementTree object
- implement a method that calls Inkscape to create a png from ElementTree
- implement a basic data source object
- implement a method that creates data source object from excel sheet
- implement root SVG object (allowing children to be mapped)
- implement placeholder SVG object (for unknown svg elements)
- implement a mapper from ElementTree to root SVG
- implement a simple mapper mapping Element and placeholder SVG object to Element
- implement a simple mapper mapping ElementTree object and root SVG object to ElementTree object
- implement base processor method combining all the previous steps
- create GUI window
- add three file picker to GUI named
- add labels for the three file picker (excel sheet, template, options)
- add button labeled "render deck"
- add processor call to button
-
implement command line integration(scraped since it was not as easy and fun to get a first running solution and does not seem to be necessary, maybe will do later)
The resulting version is relatively useless since it only produces copies of the same png. But everything is in place, so it will hopefully be a good starting point for future features.
- command line interface
- pipeline
- PiPy publishing
- add a single executable to published versions
- overhaul package structure to be more pythonic