[SOLVED] Calling functions defined in the node editor from Haxe?

Hi! I’m very familiar with Javascript and am having a lot of fun with Armory- usually I use ThreeJS and make everything in Blender, so I’m excited at the idea of really integrating Blender into my workflow using Armory3d!

That said, I’m a little confused about whether or not it is possible to access Functions created using the Logic Editor nodes from an exposed Haxe class?

Ideally I would like to be able to:

  1. Call a function in JS from the browser
  2. An exposed Haxe Class runs whatever public function is called
  3. That Haxe class then calls Functions created in the Logic Node Editor.

Steps one and Two are solved, but I’m a little stuck on three. Do Classes written with Haxe have the ability to call functions written in the Node Editor? The Node editor feels really powerful and I would like to utilize both together.

Thanks so much for taking the time to read this :smiley:

There seems to a way to “listen” to a public variable from a Haxe Class and check if it’s changed from the Node Editor, which may be all I need. (Using the nodes ‘Trait’->‘Get Haxe Property’->‘Value Changed’).

But there must be a cleaner way, yes?

public function invokeFunc(ObjectName:String, FunctionName:String, args:Array<Dynamic>){
		var object = Scene.active.getChild(ObjectName);
		var traits = object.traits;
		//For each trait in the object
		for (i in 0...traits.length){
			var func = Reflect.field(traits[i], FunctionName);
			if (func != null) {
				var result = Reflect.callMethod(traits[i], func,args);
			}
		}
	}

So this is what I ended up with. Is there a way to grab the Name of the trait from object.traits so I don’t have to loop through all of them? lol.

i is just an integer, so you can simply use the index number of the trait you want.

package arm;
import iron.Trait;
import iron.Scene;
class Plugin extends Trait {
	public function new() {
		super();
		invokeFunc("Box", "test", []);
	}
	function invokeFunc(ObjectName:String, FunctionName:String, args:Array<Dynamic>){
		var object = Scene.active.getChild(ObjectName);
		var traits = object.traits;

		var func = Reflect.field(traits[0], FunctionName);
		if (func != null) var result = Reflect.callMethod(traits[0], func, args);
	}
}

Thanks. So my issue was that while yes, the index is a number, I don’t actually know which index the trait will be at without looking at the trait list in blender. Also not really sure if traits can be added at runtime- but that would be a whole other can of worms.

I’m asking if there is a way to get the trait by Name on an object. I don’t think hardcoding index positions is a very good approach.

Traits can be added at runtime as long as they are exported with the game using object.addTrait(traitInstance). I think Haxe traits are exported anyways since the trait’s class is usually inside of the project’s Sources directory, but in case you want to add a logic node trait for example you might need to enable the Fake User option.

Trait’s have a name attribute, but I think it’s unused in many cases (please let me know if it works)… However, you can definitely get the first trait of a given type, by using object.getTrait(TraitClass).

1 Like

An example of how the name attribute mentioned above can be used to check for a certain string in a given trait’s name:

package arm;
import iron.Trait;
import iron.Scene;
class Plugin extends Trait {
	public function new() {
		super();
		invokeFunc("Box", "test", []);
	}
	function invokeFunc(ObjectName: String, FunctionName: String, args: Array<Dynamic>) {
		var object = Scene.active.getChild(ObjectName);
		var traits = object.traits;

		for (i in 0...traits.length) {
			if (traits[i].name == "Tree") {
				var func = Reflect.field(traits[i], FunctionName);
				if (func != null) var result = Reflect.callMethod(traits[i], func, args);
			}
		}
	}
}

NOTE: This may look like a lot of code for a simple check, but in the long term, all you’ll need to do to check for other strings in a trait’s name is to add a new if string check statement.

Do any of you think this is worthy of putting into the documentation? This sounds necessary for a team where both nodes and “hand written” scripts are used in the same project.