Bladeren bron

factorized shaderLoader, started working on custom renderer script

ncannasse 7 jaren geleden
bovenliggende
commit
2b4b8b8048
9 gewijzigde bestanden met toevoegingen van 289 en 83 verwijderingen
  1. 4 7
      hide.hxml
  2. 6 2
      hide.hxproj
  3. 1 66
      hide/comp/Scene.hx
  4. 55 0
      hide/tools/Interp.hx
  5. 12 3
      hide/tools/Macros.hx
  6. 103 0
      hide/tools/MaterialScript.hx
  7. 99 0
      hide/tools/ShaderLoader.hx
  8. 5 2
      hide/ui/Ide.hx
  9. 4 3
      hide/view/Model.hx

+ 4 - 7
hide.hxml

@@ -1,14 +1,11 @@
--cp libs
--js bin/hide.js
--main hide.ui.Ide
 -lib hxnodejs
 -lib heaps
 -lib hxbit
 -lib hscript
 -lib castle
+-cp libs
+-js bin/hide.js
+-main hide.ui.Ide
 -D hscriptPos
--dce no
 -D old-error-format
---macro include('hide.view')
---macro include('h3d.prim')
---macro include('h3d.scene')
+-dce no

+ 6 - 2
hide.hxproj

@@ -24,11 +24,15 @@
     <option noInlineOnDebug="False" />
     <option mainClass="hide.ui.Ide" />
     <option enabledebug="False" />
-    <option additional="-lib hxnodejs&#xA;-lib heaps&#xA;-lib hxbit&#xA;-lib hscript&#xA;-lib castle&#xA;-D hscriptPos&#xA;-dce no&#xA;-D old-error-format&#xA;&#xA;--macro include('hide.view')&#xA;--macro include('h3d.prim')&#xA;--macro include('h3d.scene')" />
+    <option additional="-D hscriptPos&#xA;-D old-error-format&#xA;-dce no" />
   </build>
   <!-- haxelib libraries -->
   <haxelib>
-    <!-- example: <library name="..." /> -->
+    <library name="hxnodejs" />
+    <library name="heaps" />
+    <library name="hxbit" />
+    <library name="hscript" />
+    <library name="castle" />
   </haxelib>
   <!-- Class files to compile (other referenced classes will automatically be included) -->
   <compileTargets>

+ 1 - 66
hide/comp/Scene.hx

@@ -7,15 +7,12 @@ class SceneLoader extends h3d.impl.Serializable.SceneSerializer {
 	var hsdPath : String;
 	var projectPath : String;
 	var scene : Scene;
-	var shaderPath : Array<String>;
-	var shaderCache = new Map<String, hxsl.SharedShader>();
 
 	public function new(hsdPath, scene) {
 		ide = hide.ui.Ide.inst;
 		super();
 		this.hsdPath = hsdPath;
 		this.scene = scene;
-		shaderPath = ide.currentProps.get("haxe.classPath");
 	}
 
 	override function initHSDPaths(resPath:String, projectPath:String) {
@@ -24,69 +21,7 @@ class SceneLoader extends h3d.impl.Serializable.SceneSerializer {
 	}
 
 	override function loadShader(name:String) : hxsl.Shader {
-		var s = loadSharedShader(name);
-		if( s == null )
-			return null;
-		return new hxsl.DynamicShader(s);
-	}
-
-	function loadSharedShader( name : String ) {
-		var s = shaderCache.get(name);
-		if( s != null )
-			return s;
-		var e = loadShaderExpr(name);
-		if( e == null )
-			return null;
-		var chk = new hxsl.Checker();
-		chk.loadShader = function(iname) {
-			var e = loadShaderExpr(iname);
-			if( e == null )
-				throw "Could not @:import " + iname + " (referenced from " + name+")";
-			return e;
-		};
-		var s = new hxsl.SharedShader("");
-		s.data = chk.check(name, e);
-		@:privateAccess s.initialize();
-		shaderCache.set(name, s);
-		return s;
-	}
-
-	function loadShaderExpr( name : String ) : hxsl.Ast.Expr {
-		var path = name.split(".").join("/")+".hx";
-		for( s in shaderPath ) {
-			var file = ide.projectDir + "/" + s + "/" + path;
-			if( sys.FileSystem.exists(file) )
-				return loadShaderString(file,sys.io.File.getContent(file));
-		}
-		if( StringTools.startsWith(name,"h3d.shader.") ) {
-			var r = haxe.Resource.getString("shader/" + name.substr(11));
-			if( r != null ) return loadShaderString(path, r);
-		}
-		return null;
-	}
-
-	function loadShaderString( file : String, content : String ) {
-		var r = ~/var[ \t]+SRC[ \t]+=[ \t]+\{/;
-		if( !r.match(content) )
-			throw file+" does not contain shader SRC";
-		var src = r.matchedRight();
-		var count = 1;
-		var pos = 0;
-		while( pos < src.length ) {
-			switch( src.charCodeAt(pos++) ) {
-			case '{'.code: count++;
-			case '}'.code: count--; if( count == 0 ) break;
-			default:
-			}
-		}
-		src = src.substr(0, pos - 1);
-		var parser = new hscript.Parser();
-		parser.allowTypes = true;
-		parser.allowMetadata = true;
-		parser.line = r.matchedLeft().split("\n").length;
-		var e = parser.parseString(src, file);
-		var e = new hscript.Macro({ min : 0, max : 0, file : file }).convert(e);
-		return new hxsl.MacroParser().parseExpr(e);
+		return ide.shaderLoader.load(name);
 	}
 
 	override function loadHMD(path:String) {

+ 55 - 0
hide/tools/Interp.hx

@@ -0,0 +1,55 @@
+package hide.tools;
+
+class Interp extends hscript.Interp {
+
+	var ide : hide.ui.Ide;
+
+	public function new() {
+		ide = hide.ui.Ide.inst;
+		super();
+	}
+
+	public function shareEnum( e : Enum<Dynamic> ) {
+		for( c in e.getConstructors() )
+			variables.set(c, Reflect.field(e, c));
+	}
+
+	public function shareObject( obj : Dynamic ) {
+		for( f in Type.getInstanceFields(Type.getClass(obj)) ) {
+			var v = Reflect.field(obj, f);
+			if( Reflect.isFunction(v) )
+				variables.set(f, Reflect.makeVarArgs(function(args) return Reflect.callMethod(obj,v,args)));
+		}
+	}
+
+	override function set(o:Dynamic, f:String, v:Dynamic) : Dynamic {
+		var fset = Reflect.field(o, "hscriptSet");
+		if( fset != null )
+			return Reflect.callMethod(o, fset, [f,v]);
+		return super.set(o, f, v);
+	}
+
+	override function get(o:Dynamic, f:String) : Dynamic {
+		var fget = Reflect.field(o, "hscriptGet");
+		if( fget != null )
+			return Reflect.callMethod(o, fget, [f]);
+		return super.get(o, f);
+	}
+
+	override function cnew(cl:String, args:Array<Dynamic>):Dynamic {
+		var c = Type.resolveClass(cl);
+		if( c == null )
+			try {
+				c = resolve(cl);
+			} catch( e : hscript.Expr.Error ) {
+			}
+		if( c == null ) {
+			var s = ide.shaderLoader.load(cl);
+			if( s == null )
+				error(EUnknownVariable(cl));
+			return s;
+		}
+		return Type.createInstance(c,args);
+	}
+
+}

+ 12 - 3
hide/Macros.hx → hide/tools/Macros.hx

@@ -1,4 +1,5 @@
-package hide;
+package hide.tools;
+
 import haxe.macro.Expr;
 import haxe.macro.Context;
 import haxe.macro.Type;
@@ -6,13 +7,21 @@ using haxe.macro.ExprTools;
 
 class Macros {
 
-	public static macro function includeShaderSources() {
+	public static macro function include( packages : Array<String> ) {
+		includeShaderSources();
+		for( p in packages )
+			haxe.macro.Compiler.include(p);
+		return macro null;
+	}
+
+	#if macro
+	static function includeShaderSources() {
 		var path = Context.resolvePath("h3d/shader/BaseMesh.hx");
 		var dir = new haxe.io.Path(path).dir;
 		for( f in sys.FileSystem.readDirectory(dir) )
 			if( StringTools.endsWith(f,".hx") )
 				Context.addResource("shader/" + f.substr(0, -3), sys.io.File.getBytes(dir + "/" + f));
-		return macro null;
 	}
+	#end
 
 }

+ 103 - 0
hide/tools/MaterialScript.hx

@@ -0,0 +1,103 @@
+package hide.tools;
+
+class RendererScript extends h3d.scene.Renderer {
+
+	var callb : Dynamic;
+	var hasError = false;
+
+	public function new(callb:Dynamic) {
+		super();
+		this.callb = callb;
+	}
+
+	override function render() {
+		if( hasError ) {
+			callb();
+			return;
+		}
+		try {
+			callb();
+		} catch( e : hscript.Expr.Error ) {
+			hasError = true;
+			hide.ui.Ide.inst.error(hscript.Printer.errorToString(e));
+		}
+	}
+
+}
+
+class MaterialScript extends h3d.mat.MaterialScript {
+
+	var ide : hide.ui.Ide;
+
+	public function new() {
+		super(); // name will be set by script itself
+		ide = hide.ui.Ide.inst;
+	}
+
+	function loadModule( path : String ) : Dynamic {
+		var fullPath = ide.getPath(path);
+		var script = try sys.io.File.getContent(fullPath) catch( e : Dynamic ) throw "File not found " + path;
+		var parser = new hscript.Parser();
+		parser.preprocesorValues.set("script", true);
+		var decls = try parser.parseModule(script, path) catch( e : hscript.Expr.Error ) { onError(Std.string(e) + " line " + parser.line); return null; }
+		var objs : Dynamic = {};
+		for( d in decls )
+			switch( d ) {
+			case DClass(c):
+				Reflect.setField(objs, c.name, makeClass.bind(c));
+			default:
+			}
+		return objs;
+	}
+
+	function makeClass( c : hscript.Expr.ClassDecl, ?args : Array<Dynamic> ) {
+		var interp = new Interp();
+		var obj = null;
+		if( c.extend != null )
+			switch( c.extend ) {
+			case CTPath(["h3d", "scene", "Renderer"], _):
+				obj = function() return new RendererScript(interp.variables.get("render"));
+				interp.shareEnum(hxsl.Output);
+				interp.shareEnum(h3d.impl.Driver.Feature);
+				interp.shareEnum(h3d.mat.Data.Wrap);
+				interp.shareEnum(h3d.mat.BlendMode);
+			default:
+			}
+		if( obj == null )
+			throw "Don't know what to do with " + c.name;
+
+		interp.variables.set("loadShader", function(name) return ide.shaderLoader.load(name));
+
+		var debug = true;
+		interp.variables.set("loadTexture", function(name) return {
+			if( debug ) {
+				trace("TODO:" + name);
+				debug = false;
+			}
+			return h3d.mat.Texture.fromColor(0);
+		});
+
+		for( f in c.fields )
+			switch( f.kind ) {
+			case KVar(v):
+				interp.variables.set(f.name, v.expr == null ? null : @:privateAccess interp.exprReturn(v.expr));
+			case KFunction(fd):
+				var ed : hscript.Expr.ExprDef = EFunction(fd.args, fd.expr, f.name, fd.ret);
+				var e = #if hscriptPos { pmin : 0, pmax : 0, origin : null, line : 0, e : ed } #else ed #end;
+				interp.variables.set(f.name, @:privateAccess interp.exprReturn(e));
+			default:
+			}
+
+
+		// share functions
+		var obj = obj();
+		interp.shareObject(obj);
+		interp.variables.set("super", obj);
+		interp.variables.set("this", obj);
+
+		var fnew = interp.variables.get("new");
+		if( fnew != null ) Reflect.callMethod(null, fnew, args == null ? [] : args);
+		return obj;
+	}
+
+}

+ 99 - 0
hide/tools/ShaderLoader.hx

@@ -0,0 +1,99 @@
+package hide.tools;
+
+class ShaderLoader {
+
+	var ide : hide.ui.Ide;
+	var shaderPath : Array<String>;
+	var shaderCache = new Map<String, hxsl.SharedShader>();
+
+	public function new() {
+		ide = hide.ui.Ide.inst;
+		shaderPath = ide.currentProps.get("haxe.classPath");
+	}
+
+	public function load( name : String ) {
+		var s = loadSharedShader(name);
+		if( s == null )
+			return null;
+		return new hxsl.DynamicShader(s);
+	}
+
+	function loadSharedShader( name : String ) {
+		var s = shaderCache.get(name);
+		if( s != null )
+			return s;
+		var e = loadShaderExpr(name);
+		if( e == null )
+			return null;
+		var chk = new hxsl.Checker();
+		chk.loadShader = function(iname) {
+			var e = loadShaderExpr(iname);
+			if( e == null )
+				throw "Could not @:import " + iname + " (referenced from " + name+")";
+			return e;
+		};
+		var s = new hxsl.SharedShader("");
+		s.data = chk.check(name, e);
+		@:privateAccess s.initialize();
+		shaderCache.set(name, s);
+		return s;
+	}
+
+	function loadShaderExpr( name : String ) : hxsl.Ast.Expr {
+		var path = name.split(".").join("/")+".hx";
+		for( s in shaderPath ) {
+			var file = ide.projectDir + "/" + s + "/" + path;
+			if( sys.FileSystem.exists(file) )
+				return loadShaderString(file,sys.io.File.getContent(file));
+		}
+		if( StringTools.startsWith(name,"h3d.shader.") ) {
+			var r = haxe.Resource.getString("shader/" + name.substr(11));
+			if( r != null ) return loadShaderString(path, r);
+		}
+		return null;
+	}
+
+	function loadShaderString( file : String, content : String ) {
+		var parser = new hscript.Parser();
+		var decls = parser.parseModule(content, file);
+		var cl = null, cf = null;
+		for( d in decls ) {
+			switch( d ) {
+			case DClass(c):
+				for( f in c.fields )
+					if( f.name == "SRC" ) {
+						cl = c;
+						cf = f;
+						break;
+					}
+				if( cf != null )
+					break;
+			default:
+			}
+		}
+		if( cf == null )
+			throw file+" does not contain shader class";
+
+		var expr = switch( cf.kind ) {
+		case KVar(v): v.expr;
+		default: throw "assert";
+		}
+
+		var e = new hscript.Macro({ min : 0, max : 0, file : file }).convert(expr);
+		var e = new hxsl.MacroParser().parseExpr(e);
+
+		switch( cl.extend ) {
+		case CTPath(p,_):
+			var path = p.join(".");
+			if( path != "hxsl.Shader" ) {
+				var pos = e.pos;
+				e = { expr : EBlock([ { expr : ECall( { expr : EIdent("extends"), pos : pos }, [ { expr : EConst(CString(path)), pos : pos } ]), pos : pos }, e]), pos : pos };
+			}
+		default:
+		}
+
+		return e;
+	}
+
+
+}

+ 5 - 2
hide/ui/Ide.hx

@@ -13,6 +13,8 @@ class Ide {
 	public var isWindows(get, never) : Bool;
 
 	public var database : cdb.Database;
+	public var shaderLoader : hide.tools.ShaderLoader;
+
 	var databaseFile : String;
 
 	var props : {
@@ -233,6 +235,7 @@ class Ide {
 		}
 		window.title = "HIDE - " + dir;
 		props = Props.loadForProject(projectDir, resourceDir);
+		shaderLoader = new hide.tools.ShaderLoader();
 
 		var localDir = sys.FileSystem.exists(resourceDir) ? resourceDir : projectDir;
 		hxd.res.Loader.currentInstance = new hxd.res.Loader(new hxd.fs.LocalFileSystem(localDir));
@@ -241,7 +244,7 @@ class Ide {
 		];
 		var path = getPath("Renderer.hx");
 		if( sys.FileSystem.exists(path) ) {
-			var r = new h3d.mat.MaterialScript();
+			var r = new hide.tools.MaterialScript();
 			try {
 				r.load(sys.io.File.getContent(path));
 				renderers.unshift(r);
@@ -515,7 +518,7 @@ class Ide {
 	public static var inst : Ide;
 
 	static function main() {
-		Macros.includeShaderSources();
+		hide.tools.Macros.include(["hide.view","h3d.prim","h3d.scene","h3d.pass"]);
 		new Ide();
 	}
 

+ 4 - 3
hide/view/Model.hx

@@ -160,9 +160,10 @@ class Model extends FileView {
 		tree.saveDisplayKey = this.saveDisplayKey;
 
 		var cam = getDisplayState("Camera");
-		if( cam == null )
-			scene.resetCamera(obj, 1.5);
-		else {
+		scene.s3d.camera.zNear = scene.s3d.camera.zFar = 0;
+		scene.resetCamera(obj, 1.5);
+		control.lockZPlanes = scene.s3d.camera.zNear != 0;
+		if( cam != null ) {
 			scene.s3d.camera.pos.set(cam.x, cam.y, cam.z);
 			scene.s3d.camera.target.set(cam.tx, cam.ty, cam.tz);
 		}