saharan / OimoPhysics

A cross-platform 3D physics engine
MIT License
863 stars 68 forks source link

Haxe version #5

Closed xoopx closed 6 years ago

xoopx commented 6 years ago

Hi, can you make workable version of engine for haxe.

saharan commented 6 years ago

It already works in Haxe, just exclude src/demo from the class path. No code in src/oimo uses platform-dependent APIs.

saharan commented 6 years ago

I might isolate src/demo from the main source folder... It would be less confusing.

xoopx commented 6 years ago

Hi first error i get is https://github.com/saharan/OimoPhysics/blob/master/src/oimo/m/B.hx#L48 Unexpected -> I use haxe 3.4.4 I comment this function code, but project never finishes compile, it seems that B.hx filter function gets infinite loop. I also tried another haxe vesions, no succes. It compiles only when i import RigidBody class alone, but when i use Word class and others it stucks.

saharan commented 6 years ago

I had the same problem and stuck while developing. It seems Haxe's compiler has a problem typing certain expressions in macros. There was a major update in the macro processor and the bug was fixed in Haxe 4.0.0 (pre-release 2 maybe), so please try using version 4.0.0 as in README.md.

xoopx commented 6 years ago

Hi, i tried haxe 3.4.0 and 3.4.0 rc2 with flags -D analyzer and -D eval-stack, no success. Are there any other solutions for this problem, or do you plan to refactor macros to bypass this problem? It would be great, as haxe misses good 3d physic engine. Maybe for haxe builds, it wolud be better to refuse using macros, as it encreases compile time.

saharan commented 6 years ago

well, bypassing the problem or stop using macros can be a solution, but there's a brilliant way: using the latest Haxe compiler. Haxe 4.0.0 preview 2 has been released here https://haxe.org/download/version/4.0.0-preview.2/ HAXE+YOU, DOWNLOAD TODAY!

Thanks,

xoopx commented 6 years ago

Hm, i missed that you mentioned haxe 4.0.0 i thought 3.4.0, my misstake. No matter, haxe 4 gives leads to errors in version of openfl i use. So i fixed this problem by replacing .toType in macro. Now it works with haxe 3.4.0. I attach change in src, maybe it will benefit

B.hx package oimo.m; import haxe.macro.Context; import haxe.macro.Expr; import haxe.macro.ExprTools; import haxe.macro.Type; using haxe.macro.ComplexTypeTools; using oimo.m.B; using oimo.m.U; using StringTools; using Lambda;

/**

if macro

// print imports of all classes
static inline var PRINT_IMPORTS:Bool = false;
// print exports and externs for JS closure compiler
static inline var PRINT_EXPORTS:Bool = false;
static inline var PRINT_EXTERNS:Bool = false;

static function log(s:String):Void {
    //trace(s);
}

static var onGenerateAdded:Bool = false;

public static function bu() {
    if (!onGenerateAdded) {
        Context.onGenerate(onGenerate);
        onGenerateAdded = true;
    }
    log("building... " + Context.getLocalClass());
    return filter();
}

static function onGenerate(types:Array<Type>):Void {
    //if (!PRINT_IMPORTS && !PRINT_EXPORTS && !PRINT_EXTERNS) return;

// //var externs = []; //var exports = []; //var imports = []; //exports.push("window[\"OIMO\"] = {};"); //types.iter((t) -> switch (t) { //case TInst(t, params): //var classType = t.get(); //var className = classType.name; //var jsClassName = classType.pack.join("") + "" + className; //if (~/^oimo.(common|collision|dynamics)/.match(classType.pack.join("."))) { //imports.push('import ${classType.pack.join(".")}.$className;'); // //var doc = classType.doc; //var hidden = classType.meta.extract(":dox").exists((me) -> me.params.exists((e) -> e.expr.equals((macro hide).expr))); //var isInterface = classType.meta.has(":interface"); //if (doc != null && !hidden) { //exports.push('window["OIMO"]["$className"] = $jsClassName;'); // //var pubMembers = classType.fields.get().filter((cf) -> cf.isPublic && !cf.name.startsWith("")); //var pubStats = classType.statics.get().filter((cf) -> cf.isPublic && !cf.name.startsWith("")); //var pubFields = pubMembers.concat(pubStats); // //if (isInterface) { //pubFields.iter((pf) -> externs.push('OIMO.$className.${pf.name};')); //} else { //var pubVars = pubFields.filter((cf) -> cf.kind.match(FVar(, ))); //pubVars.iter((pf) -> externs.push('OIMO.$className.${pf.name};')); // //var pubMethods = pubMembers.filter((cf) -> cf.kind.match(FMethod())); //var pubFuncs = pubStats.filter((cf) -> cf.kind.match(FMethod())); //pubMethods.iter((pf) -> exports.push('$jsClassName.prototype["${pf.name}"] = $jsClassName.prototype.${pf.name};')); //pubFuncs.iter((pf) -> exports.push('$jsClassName["${pf.name}"] = $jsClassName.${pf.name};')); //} //} //} //case _: //}); //if (PRINT_IMPORTS) { //trace("imports:\n" + imports.join("\n")); //} //if (PRINT_EXPORTS) { //trace("exports:\n" + exports.join("\n")); //} //if (PRINT_EXTERNS) { //trace("externs:\n" + externs.join("\n")); //} }

public static function filter() {
    var importsExprs:Array<ImportExpr> = Context.getLocalImports();
    var imports:Array<String> = [];
    var importsMap:Map<String, String> = new Map<String, String>();
    for (i in 0...importsExprs.length) {
        var e:ImportExpr = importsExprs[i];
        var imp:String = "";
        for (j in 0...e.path.length) {
            imp += (imp.length != 0 ? "." : "") + e.path[j].name;
        }
        imports.push(imp);
        var spl:Array<String> = imp.split(".");
        importsMap.set(spl[spl.length-1], imp);
    }

    var fs:Array<Field> = Context.getBuildFields();
    var fs2:Array<Field> = [];
    log("filtering... " + fs);
    for (field in fs) {

        // hide private/internal properties
        if (field.name.substr(0, 1) == '_') {
            field.meta.push({
                name: ":dox",
                params: [macro hide],
                pos: U.pos()
            });
        }

        log("filtering a field " + field);
        switch (field.kind) {
            case FVar(t, e):
                log("FVar(" + t + ", " + e + ")");
                var names:Array<String> = field.name.names(t.toType());
                if (names != null) {

                    U.pushVariables(fs2, names, macro:Float, [{
                        // hide private vars
                        name: ":dox",
                        params: [macro hide],
                        pos: U.pos()
                    }], field.access);

                    field.meta.push({
                        name: ":extern",
                        pos: U.pos()
                    });
                    fs2.push(field); // keep it for type inference
                } else {
                    fs2.push(field);
                }
            case FFun(f):
                log("FFun(" + f + ")");

                var args:Array<FunctionArg> = [];
                log("args " + f.args);
                for (arg in f.args) {
                    log("arg " + arg);
                    if (arg.type == null) continue;

                    var names:Array<String> = arg.name.names2(U.getTypeName(arg.type, importsMap));
                    log("names " + names);
                    if (names != null) {
                        for (name in names) {
                            log("name " + name);
                            args.push({
                                name: name,
                                type: macro:Float
                            });
                        }
                    } else {
                        args.push(arg);
                    }
                }

                field.kind = FFun({
                    args: args,
                    expr: filterFuncExpr(f.expr),
                    ret: f.ret,
                    params: f.params
                });
                log("kind " + field.kind);
                fs2.push(field);
            case _:
                log("others");
                fs2.push(field);
        }
    }
    log("finished filtering.");
    return fs2;
}

static function filterFuncExpr(e:Expr):Expr {
    log("filterFuncExpr " + e);
    switch(e.expr) {
    case EVars(vars):
        log("EVars(" + vars + ")");
        var newVars:Array<Var> = vars.copy();
        for (v in vars) {
            log("v " + v);
            var names:Array<String> = v.name.names(v.type.toType());
            log("names " + names);
            if (names != null) {
                newVars = newVars.concat(names.map(function(name) {
                    return {
                        name: name,
                        type: macro:Float,
                        expr: null
                    };
                }));
            }
        }
        e.expr = EVars(newVars);
        return e;
    case _:
        log("others");
        return ExprTools.map(e, filterFuncExpr);
    }
}

end

}

U.hx

package oimo.m; import haxe.macro.Context; import haxe.macro.Expr; import haxe.macro.Expr.Access; import haxe.macro.Expr.ComplexType; import haxe.macro.Expr.Field; import haxe.macro.Type; import oimo.m.IMat3; import oimo.m.IVec3; using oimo.m.U; using haxe.macro.ExprTools; using haxe.macro.TypeTools; using haxe.macro.ComplexTypeTools;

if macro

/**

}

end

saharan commented 6 years ago

toType calls against ComplexType have been removed in https://github.com/saharan/OimoPhysics/commit/a4f307b05eb87d3b1d8a86293cdf75ede7f7b92b !