Inkscape Parser for OpenFL (Haxe)

Last week I mentioned the small Inkscape parser I created for OpenFL and I said it was very helpful, not only to have it but also understanding how the Inkscape’s XML file is structured. This week I decided to briefly explain the code for that because it might be useful for someone working with OpenFL.

Editor XML (Shift + Ctrl + X)

This is the first cool thing about Inkscape I learned before writing the parser. Maybe you already know this but you can see an XML editor for the document you are seeing inside Inkscape if you press shift + ctrl + x. It basically shows a bunch of nodes that represent elements you have in your document.

In the XML you can find anything you add to the document, if we add a new element to the scene, it’s automatically added to the XML too and you can easily see it and its information when you select it in the document.

With these two things, we can easily write a very simple parser that maps positions from the XML document to our game. The following structure is the most basic one to get the elements inside layers in the document.

The Code

actionscript3

  1. //This code is written in Haxe but Wordpress does not highlight haxe so I just chose ActionScript3 :)
  2.  
  3. //This is what we use to load the Inkscape file (as it is)
  4.  
  5. var xml:Xml;
  6.  
  7. //You can use any variable you want but for this article I chose position, radius and id
  8.  
  9. var x, y, radius : Float;
  10. var id : String;
  11.  
  12. xml = LoadXML(YOUR_FILE_PATH + "name_of_your_file.svg");
  13.  
  14. try
  15. {
  16.    //Iterate over all the nodes of the file
  17.    for (e in xml.iterator())
  18.    {
  19.       if (e.nodeType == Xml.Element)
  20.       {
  21.          if (e.nodeType == Xml.Element)
  22.          {
  23.             //This is the layer's label (you can see the image above, it's called "Capa 1"
  24.             switch(e.get("inkscape:label"))
  25.             {
  26.                case "your_layer_name":
  27.                   id = e1.get("id");
  28.                   //The size of the Inkscape file should be the same in GraphicSystem here
  29.                   x = Std.parseFloat(e1.get("x"));
  30.                   y = Std.parseFloat(e1.get("y"));
  31.                   radius = Std.parseFloat(e1.get("r"));
  32.                   //This is only a sample, you can read whatever you want here
  33.             }
  34.          }
  35.       }
  36.    }
  37. }
  38. catch (e : String)
  39. {
  40.    trace(e); //Catch the exception beautifully
  41. }
  42.  
  43. //This function belongs to a bigger library I created as a helper for easily doing annoying stuff like this
  44. public static function LoadXML(path : String) : Xml
  45. {
  46.    var xml : Xml;
  47.    var str : String;
  48.    
  49.    str = Assets.getText(path);
  50.    xml = Xml.parse(str).firstElement();
  51.  
  52.    return xml;
  53. }

I believe the code is kind of self explanatory but I’ll comment a bit on it. Basically we load the XML file, put it in a variable and iterate over all of its nodes to see which one contains the data we need: layers. If you want to customize your parser and add whatever information you need from the document you can also do that. Once we find the layer we are looking for (it should be the same name in the XML file), we use the data, store it in variables and use it as we want.

There are some transformation involved, depending on what you want to do with the data you get from Inkscape but it totally depends on the purpose of your code, if you have any questions related to this, please let me know.

Custom Attributes

Something that I find very helpful from Inkscape, is the possibility to include custom attributes, which enables us to take the editor further and add specific information for our elements.

Let’s say you have a game object that has “speed”. You want to customize each game object in the editor for different speeds so your game object is different depending on its type or something like that.

In the image above you can see fields for each attribute in the element if you click on the element and then click on the attribute. If you write a new name in the field for name and assign a value to it, it will be automatically created after you click “Accept” (it’s “Aceptar” in Spanish in the image).

actionscript3

  1. switch(e.get("inkscape:label"))
  2. {
  3.    case "your_layer_name":
  4.       id = e1.get("id");
  5.       //The size of the Inkscape file should be the same in GraphicSystem here
  6.       x = Std.parseFloat(e1.get("x"));
  7.       y = Std.parseFloat(e1.get("y"));
  8.       radius = Std.parseFloat(e1.get("r"));
  9.      //New Attribute
  10.      speed = Std.parseFloat(e1.get("speed"));
  11. }

In the example above, you can see how we read the custom attribute using the same name we added in the XML editor.

I think that with these basic concepts you can easily write a whole map editor or if you prefer, a menu editor taking advantage of the Inkscape’s functionality. There are probably better or more general ways to do this but I wanted to discuss about the one I implemented.

Also, I want to clarify that an in-game editor would be much more helpful and comfortable to work with but either you need the time to make it or the money to buy it. This works for me and the simple games I’m creating, if you have advices or ideas, please let me know in the comments.

Inkscape Parser for OpenFL (Haxe)

3 thoughts on “Inkscape Parser for OpenFL (Haxe)

  1. Rafael Oliveira says:

    The problem is the “transform” attributes, that need to be applied to objects. If you change the size of the document, a transform will be added to the layer. The best way to remove it is to add another layer, and move the objects to there. And there is the option in Object -> Transform, to apply the transformation of a object.

    Also, would be good to have a option in Inkscape to have a lower precision in the positions, or to simply use integers to all positions.

    1. henry says:

      I think you are right, it would affect all the transformations but, do you really need to change the document size? I mean, I think this could be a quick and cheap solution for easily mapping basic attributes and custom attributes to your game without writting a whole level editor from scratch, just to save time, I guess if you want to make a big tool ot of this, the transform would be an issue. About the precision, maybe you could just round the numbers (in your parser) or adjust the grid and snapping functionality on Inkscape, which would give you integer numbers for the position and also width and height, I think)

  2. Rafael Oliveira says:

    You are right, I adjusted the size of the document because I used to do this when using Inkscape, it’s something automatic. It’s not really necessary. The only place where this would be useful, is if you want to match the document with the size of the game window, or the size of map.. in the end this depends of the user, he could also use the guides for this. So, to avoid the transformations, I think you only need to avoid change the size of the document, and create groups (or create and ungruop when exporting). When you move a group it also create a transformation.
    Another nice thing, Inkscape uses the ruler inverted in the Y axis, but not in the xml, a object in the top left position of the document will appear 0,0 in the xml.

Leave a Reply

Your email address will not be published.

*