Building Foam Icon Archives

Note that this information is provided for your own exploration. We will try to help with icon issues on the Discord server but this material is unsupported. Features based on icon archive sharing are planned but not an immediate priority.

Foam loads icons in Blender's geometry icon format. For Blender's newer sculpt brush icons, the ones you see in the tool sidebar in the Sculpt workspace, Foam uses the files stored in the Blender package. So it will pick up new icons shipped with newer versions of Blender.

For the Blender UI icons and the Foam icons, Foam looks in a builtin asset path for archives of icons in the same format as the Blender icons, but packed together with a simple directory. It will also look for icons in user asset directories.

To build icon archives we use the make_blender_icon_collection.py script. This script takes a blend file with a certain structure and looks for geometry in the X-Y plane to produce a set of icons that it can pack into an archive. It will output the archive along with a manifest file.

Getting Started

First, grab the icon builder package and make sure you have a recent version of Blender with the Foam add-on installed.

Unpack the package. You should see the following files: foam_ui_icon_template.blend This is the template you will start creating icons from foam_ui_example.blend An example with some of the icons shipped with Foam make_blender_icon_collection.py The script to generate icon packs

Icon Template Blend File

In the downloaded package there is a template blend file. Open it up and then the first thing you should do is save it as a new file somewhere close to the script file.

You should see this (without all the labels :) : IconBuilderBlendParts.png

There are three important mesh loop objects that define the size and extent of the icons.

  1. icon-space defines the maximum extent that the script should look in for icons. Anything outside this area in XY will be ignored.
  2. icon-cell defines the size and tiling of icons. The script will look for tiles of this size inside icon-space.
  3. icon-work is more of a guideline than a rule - because icons may get close together it's a good idea to leave some space between them. The script does not enforce anything with this area right now but it does look for it in the blend file.

icon-space and icon-cell define the scale and location of each icon. You can change the sizes if you want but note that there's really no absolute scale to icons. They will be rendered at a percentage of the icon-cell size so the sizes are relative. We used a 10mm grid because it's simpler to think about. Also moving icon-work around the grid is easier because everything is a multiple of 10 and the centres of all icons are on the 5's, 15, 25, 35, etc.

The script expects the following:

  • Geometry that is completely contained (in XY) in a tile of icon-cell contributes to an icon. Geometry that overlaps icon-cell will be ignored.
  • Filled curves or mesh faces contribute. They will be triangulated and beautified to help ensure that we don't get too many tiny triangles.
  • Objects with the same name up to the first period ('.') are considered part of the same icon.
  • Objects will be drawn in order of the lexicographic ordering of their names - so if there are overlaps, the background objects should have names that sort before the foreground objects. e.g. my_icon before my_icon.001 before my_icon.002
  • Geometry can be rotated relative to the X-Y plane but during processing only the X-Y will matter for the finished geometry. It will effectively get projected back to X-Y (with orthographic projection).

In the example, icon-space is set to 50mm x 50mm. If you want more icons you can extend it as necessary. If there's no geometry in a cell then no icon is generated.

Colour

the icon script collects vertex colours from geometry. It looks at the assigned material and scans for the first RGB output - which will normally be the diffuse channel of a BSDF. You can assign multiple materials in a single object or use multiple objects sorted by Z depth. The icon shader in foam does a simple interpolation so it's not possible to do any fancy shading.

Geometry

The Blender geometry icon format - described at the bottom of this document packs vertex coordinates and colours into 8 bit integers. This gives reasonable resolution at most icon sizes and gives small files for reasonably complex icons.

The icons are rendered directly in hardware through Blender's rendering API as triangles. This means we get infinite scaling and fast draw times along with flexible colours. However every triangle adds to the total and typically icons are rendered at fairly small sizes. So be frugal with your geometry.

  • Try to use as few triangles as possible. If you're not sure how a face will triangulate do it manually and clean up. For instance Blender's algorithm for filling imported curves from SVG is naive and generates far too many stretched triangles. It is often better to make the faces by hand.
  • Overlapping geometry means more drawing. One or two partially hidden triangles is not too bad but if there's a lot of geometry being overdrawn it's just wasting time.
  • Icons should be simple and concise for readability, too many shapes or colours will be confusing and may not render well. Try your icons at the smallest resolution (15 pixel radius).
  • Lines should have a little thickness. In the template scale of 10mm square, half a millimetre starts to get sketchy at normal sizes.
  • If you do have overlapping geometry, change the order of the object names e.g. my_icon, my_icon.001 etc. As mentioned above drawing happens in ascending order of object names so put your backgrounds first.

Running the script.

Once you have some icons, you can run the archive script. In fact it's probably a good idea to run it periodically to check your work and find any errors. Right now the script is a bit rough and the command line is a little involved. You can of course wrap this in something simpler if you need to.

We run the script through Blender so for now you need to start with

<PATH_TO_BLENDER_EXE> -b -P ...

Where PATH_TO_BLENDER_EXE is the location of your Blender executable. On macOS it would be something like /Applications/Blender.app/Contents/MacOS/Blender. If you use snap on linux it might be /snap/bin/blender.

Parameters

After the blender part we need to set up the archive. The icon script takes the following parameters:

  -a, --archive         Create an archive
  -h, --help            show this help message and exit
  -i IDENT, --ident IDENT
                        Unique identifier for icon pack
  -n NAME, --name NAME  Name of the icon pack
  -o OUTPUT             Output location, default to current directory

You will need to decide on a name for your icon pack and also a unique identifier. The name should not contain spaces and for cross platform compatibility should be all lower case. Underscores can be used.

The identifier is also lower case but should contain dots - as in a reverse qualified domain name e.g. org.blender.ui, com.allision.foam. Please don't use an existing identifier because that will result in some icons going missing or being replaced randomly. In a future version Foam may be more rigorous about loading icons.

After the Blender arguments, including the script itself we need -- to tell the script where it's arguments start.

Here's an example invocation of the script, assuming that Blender is on the path and that the script and the blend file are in the current directory:

blender -b -P make_blender_icon_collection.py -- -a -n my_icon_pack_name -o ~/.config/foam-blender/assets/icon  -i my.ident.ifier  my_foam_ui_icons.blend

On windows (assuming Blender just from a zip file rather than msi):

C:\Blender\foam_icon_builder> blender-3.6.5-windows-x64\blender.exe -b -P make_blender_icon_collection.py -- -a -n my_icon_pack_name -i my.ident.ifier -o %APPDATA%\Roaming\foam-blender\assets\icon my_foam_ui_icons.blend

Here the output path -o is set to the foam config directory. The script will write a subdirectory there with two files in it:

my_icon_name/geometry.fia
my_icon_name/icon_pack.json

The json file contains a directory of the icons. In the future it will carry more information, including keywords, descriptions etc. For now only the name is recorded.

The fia file is a binary archive of the icon geometry. It also includes some metadata.

Next time you start Blender your new icons should get picked up from the config directory. Right now you will need to restart Blender each time you update the archive.

If you rename or delete the icon pack you will get blank bubbles and when you edit them you'll see a red error in the icon name.

Sharing

We have a goal to enable more seamless sharing from within the Foam add-on. For right now you can zip up the my_icon_name directory and share it with others. Installing icon packs should should be as simple as unpacking the two files into your icon asset path e.g.

~/.config/foam-blender/assets/icon/<pack_name>/

Errors

Occasionally the script will throw an error. More often than not it is because the geometry is messed up or badly named.