LuaJ, creating a vector class

Hiah. I am trying to implement luaj into my project, and I was hoping to get some help!

I want to implement a Vector class similar to this structure:
http://wiki.roblox.com/index.php?title=API:Vector3

The problem is I can’t seem to find proper documentation on a few things that are necessary. Firstly, I like the .new() convention for constructors, but I am not sure how that would translate to java, as “new” is a protected keyword.

Secondly, how would I go about operator overloading? i.e. Vector3 * Vector3, ect.

Thirdly, I don’t know how to go about creating a property that automatically updates as other properties are changed. For example, in the Vector class I linked: X, Y, Z, Unit, and Magnitude are all fields of a Vector. If X, Y, or Z changes then the Unit and Magnitude variable automatically change. There are no setters or getters.

Ideally I would have most of the functionality in java, and just expose some methods to the user via lua.

Here is my current implementation:

package math;

import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.ThreeArgFunction;
import org.luaj.vm2.lib.jse.CoerceJavaToLua;

public class Vector3Lua {
	public float X;
	public float Y;
	public float Z;
	
	public Vector3Lua unit;
	
	public Vector3Lua() {
		// Empty
	}
	
	// Java constructor
    public Vector3Lua(float X, float Y, float Z) {
    	this.X = X;
    	this.Y = Y;
    	this.Z = Z;
    	
    	this.unit = new Vector3Lua(); // TODO Make this automatically calculate
	}
    
    // Lua constructor
    static public class New extends ThreeArgFunction {

		@Override
		public LuaValue call(LuaValue arg0, LuaValue arg1, LuaValue arg2) {
            return CoerceJavaToLua.coerce(new Vector3Lua(arg0.tofloat(), arg1.tofloat(), arg2.tofloat()));
		}
    }
    
	// Lua Function - Dot Product
    public float Dot(Vector3Lua other) {
    	if ( other == null ) {
    		return 0;
    	}
    	
        return X * other.X + Y * other.Y + Z * other.Z;
    }
	
    // Lua Function - Cross Product
    public LuaValue Cross(Vector3Lua other) {
    	Vector3Lua result = new Vector3Lua( Y * other.Z - Z * other.Y,
							    			Z * other.X - X * other.Z,
							    			X * other.Y - Y * other.X );
        return CoerceJavaToLua.coerce(result);
    }
}

Testable example:

package math;

import org.luaj.vm2.*;
import org.luaj.vm2.lib.*;
import org.luaj.vm2.lib.jse.*;

public class luaj {
	public static void main(String[] args) {
		// Normal Lua defaults
		Globals globals = JsePlatform.standardGlobals();
		
		// Setup Vector class
		LuaValue vectorClass = CoerceJavaToLua.coerce(Vector3Lua.class);
		globals.set("Vector3", vectorClass);

		// Bind .new() to constructor function
		LuaTable t = new LuaTable();
		t.set("new", new Vector3Lua.New());
		t.set("__index", t);
		vectorClass.setmetatable(t);

		// Test it
		LuaValue chunk = globals.load("local test1 = Vector3.new(9, 8, 7); local test2 = Vector3.new(1, 2, 3); print(test1.Z); print(test1:Dot(test2)); print(Vector3:func())");
		chunk.call();
	}
}

I’ve found an interesting problem. Not sure if it’s due to my own incompetence or an issue with LuaJ…

If I define a class with a metatable such as this:

// Setup Vector class
LuaValue vectorClass = CoerceJavaToLua.coerce(Vector3Lua.class);
globals.set("Vector3", vectorClass);

// Metatable stuff for Vector3
LuaTable t = new LuaTable();
t.set("__add", new TwoArgFunction() {
	public LuaValue call(LuaValue x, LuaValue y) {
		System.out.println("TEST1: " + x);
		System.out.println("TEST2: " + y);
		return x;
	}
});
t.set("__index", t);
vectorClass.setmetatable(t);

And then in lua I create an instance of “Vector3Lua”:

print( "Vector3 Metatable:", getmetatable(Vector3) );
local test1 = Vector3.new(9, 8, 7);
print("Test1 Metatable:", getmetatable(test1));

Vector3 contains a metatable, but Test1 does not. So what seems to be happening is that metatables do not pass from parents to their children from the .new() lua function. But I’ve seen this done before in other game engines. Hmm.