I’m trying to get Haxe to work for writing Blender plugins, specifically so that we can write the Armory Blender plugin in Haxe ( and if I ever write my own Blender plugin, I’d want to write it in Haxe, obviously ), but there are a few of difficulties I am having. If anybody could help me out that would be great.
I have what I have developed so far in a blender extern generator on GitHub. So far I nearly have the system working, but I’ve still got some things to work out.
Handling bl_info
, register()
, and unregister()
So my first problem is related to the fact that Haxe doesn’t let you define module level fields. For every blender plugin there has to be a global scoped bl_info
dictionary containing the addon info like name, etc. You have a similar issue with the required register()
and unregister()
functions which need to be defined in the global scope of the module.
I managed to solve for this in a sub-optimal manner by having a two-stage compilation, where the first on compile the plugin like any Haxe program, and the second one uses a macro to add the extra content to the file generated in the first step:
The biggest problem with this setup is that it ends up compiling the program twice, which takes a little bit longer because of the large amount of extern classes from the Blender API. It is a bigger problem because of how much it slows autocompletion, I just don’t know if there is another way to do that.
Import Name is Different than Class Name
The next problem I am having has to do with imports. There is a weird thing about Blender’s bpy
package, that you can’t import bpy.types
. That causes an issue when I need to use the bpy.types.Operator
class. At first I had the extern classes structured like this, with a :pythonImport
meta.
@:pythonImport("bpy.types.Operator") extern class Operator {
The problem with this is that it causes Haxe to generate an import that looks like import bpy.types.Operator as bpy_types_operator_Operator
, which break when running in Blender because bpy.types
is not a module.
My current work-around is to add import bpy
to the output post-processing step that I mentioned above and switched the :pythonImport
meta to a :native
metadata. This is bad for the same reason as the above problem, because I don’t want to have to have to compile the program two times to get the final output. Also I would need to add logic to be able to tell which extra imports I need to add, which should be possible, but isn’t optimal. I’m not sure if there is a way to get more control over how Haxe generates the Python imports.
Overriding Class Variables
On a more Blender and less Haxe note I am having trouble with not being able to tell whether or not to make a class attribute static or not. So in the plugin code you need to do something like the following, but it causes Haxe to complain that I can’t re-define bl_idname
or bl_label
because they are already defined in Operator
.
class SimpleOperator extends Operator {
var bl_idname = "object.simple_operator";
var bl_label = "Tool Name";
public override function execute(context:Dynamic) {
trace("Hello World");
return new Set(["FINISHED"]);
}
}
That actually makes sense, and is fixed if you make the field static, which it probably needs to be anyway. The problem is that I don’t know how to tell what class fields to make static from the XML documentation. This is the only problem I don’t have a workaround for so far.