Browse Source

split Shader / DynamicShader

Nicolas Cannasse 4 years ago
parent
commit
a8d0a869fe

+ 1 - 1
hide/tools/ShaderLoader.hx

@@ -48,7 +48,7 @@ class ShaderLoader {
 		@:privateAccess s.initialize();
 		var convertedInits = [];
 		for (init in chk.inits) {
-			convertedInits.push({variable: init.v, value: hrt.prefab.Shader.evalConst(init.e) });
+			convertedInits.push({variable: init.v, value: hrt.prefab.DynamicShader.evalConst(init.e) });
 		}
 		var s : CachedShader = { file : e.file, name : name, shader : s, inits : convertedInits, watch : null };
 		if(sys.FileSystem.exists(s.file)) {

+ 3 - 2
hide/view/FXEditor.hx

@@ -1292,8 +1292,9 @@ class FXEditor extends FileView {
 			});
 			menuItems.push(trackItem("Visibility", [{name: "visibility", clamp: [0., 1.]}]));
 		}
-		if(shaderElt != null && shaderElt.shaderDef != null) {
-			var params = shaderElt.shaderDef.shader.data.vars.filter(isPerInstance);
+		if(shaderElt != null) {
+			var shader = shaderElt.makeShader();
+			var params = shader == null ? [] : @:privateAccess shader.shader.data.vars.filter(isPerInstance);
 			for(param in params) {
 				var tracks = null;
 				var isColor = false;

+ 215 - 0
hrt/prefab/DynamicShader.hx

@@ -0,0 +1,215 @@
+package hrt.prefab;
+
+class DynamicShader extends Shader {
+
+	var shaderDef : hrt.prefab.ContextShared.ShaderDef;
+
+	public function new(?parent) {
+		super(parent);
+		type = "shader";
+		props = {};
+	}
+
+	override function save() {
+		fixSourcePath();
+		return super.save();
+	}
+
+	override function updateInstance(ctx: Context, ?propName) {
+		var shader = Std.downcast(ctx.custom, hxsl.DynamicShader);
+		if(shader == null || shaderDef == null)
+			return;
+		for(v in shaderDef.shader.data.vars) {
+			if(v.kind != Param)
+				continue;
+			var val : Dynamic = Reflect.field(props, v.name);
+			switch(v.type) {
+				case TVec(_, VFloat):
+					if(val != null)
+						val = h3d.Vector.fromArray(val);
+					else
+						val = new h3d.Vector();
+				case TSampler2D:
+					if(val != null)
+						val = ctx.loadTexture(val);
+					var childNoise = getOpt(hrt.prefab.l2d.NoiseGenerator, v.name);
+					if(childNoise != null)
+						val = childNoise.toTexture();
+				default:
+			}
+			if(val == null)
+				continue;
+			shader.setParamValue(v, val);
+		}
+	}
+
+	override function getShaderDefinition(?ctx:Context):hxsl.SharedShader {
+		if( shaderDef == null && ctx != null )
+			loadShaderDef(ctx);
+		return shaderDef == null ? null : shaderDef.shader;
+	}
+
+	override function makeShader( ?ctx:Context ) {
+		if( getShaderDefinition(ctx) == null )
+			return null;
+		var shader = new hxsl.DynamicShader(shaderDef.shader);
+		for( v in shaderDef.inits ) {
+			#if !hscript
+			throw "hscript required";
+			#else
+			shader.hscriptSet(v.variable.name, v.value);
+			#end
+		}
+		var prev = ctx.custom;
+		ctx.custom = shader;
+		updateInstance(ctx);
+		ctx.custom = prev;
+		return shader;
+	}
+
+	override function makeInstance(ctx:Context):Context {
+		if( source == null )
+			return ctx;
+		return super.makeInstance(ctx);
+	}
+
+	function fixSourcePath() {
+		#if editor
+		var ide = hide.Ide.inst;
+		var shadersPath = ide.projectDir + "/src";  // TODO: serach in haxe.classPath?
+
+		var path = source.split("\\").join("/");
+		if( StringTools.startsWith(path.toLowerCase(), shadersPath.toLowerCase()+"/") ) {
+			path = path.substr(shadersPath.length + 1);
+		}
+		source = path;
+		#end
+	}
+
+	public function loadShaderDef(ctx: Context) {
+		if(shaderDef == null) {
+			fixSourcePath();
+			var path = source;
+			if(StringTools.endsWith(path, ".hx")) {
+				path = path.substr(0, -3);
+			}
+			shaderDef = ctx.loadShader(path);
+		}
+		if(shaderDef == null)
+			return;
+
+		#if editor
+		// TODO: Where to init prefab default values?
+		for( v in shaderDef.inits ) {
+			if(!Reflect.hasField(props, v.variable.name)) {
+				Reflect.setField(props, v.variable.name, v.value);
+			}
+		}
+		for(v in shaderDef.shader.data.vars) {
+			if(v.kind != Param)
+				continue;
+			if(!Reflect.hasField(props, v.name)) {
+				Reflect.setField(props, v.name, getDefault(v.type));
+			}
+		}
+		#end
+	}
+
+	#if editor
+
+	override function edit( ctx : EditContext ) {
+		super.edit(ctx);
+
+		loadShaderDef(ctx.rootContext);
+		if(shaderDef == null)
+			return;
+
+		var group = new hide.Element('<div class="group" name="Shader"></div>');
+
+		var props = [];
+		for(v in shaderDef.shader.data.vars) {
+			if(v.kind != Param)
+				continue;
+			var prop = makeShaderType(v);
+			props.push({name: v.name, t: prop});
+		}
+		group.append(hide.comp.PropsEditor.makePropsList(props));
+
+		ctx.properties.add(group,this.props, function(pname) {
+			ctx.onChange(this, pname);
+		});
+	}
+
+	function makeShaderType( v : hxsl.Ast.TVar ) : hrt.prefab.Props.PropType {
+		var min : Null<Float> = null, max : Null<Float> = null;
+		if( v.qualifiers != null )
+			for( q in v.qualifiers )
+				switch( q ) {
+				case Range(rmin, rmax): min = rmin; max = rmax;
+				default:
+				}
+		return switch( v.type ) {
+		case TInt:
+			PInt(min == null ? null : Std.int(min), max == null ? null : Std.int(max));
+		case TFloat:
+			PFloat(min != null ? min : 0.0, max != null ? max : 1.0);
+		case TBool:
+			PBool;
+		case TSampler2D:
+			PTexture;
+		case TVec(n, VFloat):
+			PVec(n);
+		default:
+			PUnsupported(hxsl.Ast.Tools.toString(v.type));
+		}
+	}
+	override function getHideProps() : HideProps {
+		return { icon : "cog", name : "Shader", fileSource : ["hx"], allowParent : function(p) return p.to(Object2D) != null || p.to(Object3D) != null || p.to(Material) != null  };
+	}
+
+	#end
+
+	public static function evalConst( e : hxsl.Ast.TExpr ) : Dynamic {
+		return switch( e.e ) {
+		case TConst(c):
+			switch( c ) {
+			case CNull: null;
+			case CBool(b): b;
+			case CInt(i): i;
+			case CFloat(f): f;
+			case CString(s): s;
+			}
+		case TCall({ e : TGlobal(Vec2 | Vec3 | Vec4) }, args):
+			var vals = [for( a in args ) evalConst(a)];
+			if( vals.length == 1 )
+				switch( e.t ) {
+				case TVec(n, _):
+					for( i in 0...n - 1 ) vals.push(vals[0]);
+					return vals;
+				default:
+					throw "assert";
+				}
+			return vals;
+		default:
+			throw "Unhandled constant init " + hxsl.Printer.toString(e);
+		}
+	}
+
+	public static function getDefault(type: hxsl.Ast.Type): Dynamic {
+		switch(type) {
+			case TBool:
+				return false;
+			case TInt:
+				return 0;
+			case TFloat:
+				return 0.0;
+			case TVec( size, VFloat ):
+				return [for(i in 0...size) 0];
+			default:
+				return null;
+		}
+		return null;
+	}
+
+	static var _ = Library.register("shader", DynamicShader);
+}

+ 8 - 202
hrt/prefab/Shader.hx

@@ -2,76 +2,21 @@ package hrt.prefab;
 
 class Shader extends Prefab {
 
-	public var shaderDef : hrt.prefab.ContextShared.ShaderDef;
-
-	public function new(?parent) {
-		super(parent);
-		type = "shader";
-		props = {};
-	}
-
-	override function save() {
-		fixSourcePath();
-		return super.save();
-	}
-
-	override function updateInstance(ctx: Context, ?propName) {
-		var shader = Std.downcast(ctx.custom, hxsl.DynamicShader);
-		if(shader == null || shaderDef == null)
-			return;
-		for(v in shaderDef.shader.data.vars) {
-			if(v.kind != Param)
-				continue;
-			var val : Dynamic = Reflect.field(props, v.name);
-			switch(v.type) {
-				case TVec(_, VFloat):
-					if(val != null)
-						val = h3d.Vector.fromArray(val);
-					else
-						val = new h3d.Vector();
-				case TSampler2D:
-					if(val != null)
-						val = ctx.loadTexture(val);
-					var childNoise = getOpt(hrt.prefab.l2d.NoiseGenerator, v.name);
-					if(childNoise != null)
-						val = childNoise.toTexture();
-				default:
-			}
-			if(val == null)
-				continue;
-			shader.setParamValue(v, val);
-		}
+	public function makeShader( ?ctx : hrt.prefab.Context ) : hxsl.Shader {
+		return null;
 	}
 
-	public function makeShader(ctx:Context,withInit=true) {
-		loadShaderDef(ctx);
-		if(shaderDef == null)
-			return null;
-		var shader = new hxsl.DynamicShader(shaderDef.shader);
-		for( v in shaderDef.inits ) {
-			#if !hscript
-			throw "hscript required";
-			#else
-			shader.hscriptSet(v.variable.name, v.value);
-			#end
-		}
-		if( withInit ) {
-			var prev = ctx.custom;
-			ctx.custom = shader;
-			updateInstance(ctx);
-			ctx.custom = prev;
-		}
-		return shader;
+	public function getShaderDefinition( ?ctx : hrt.prefab.Context ) : hxsl.SharedShader {
+		var s = makeShader(ctx);
+		return s == null ? null : @:privateAccess s.shader;
 	}
 
 	override function makeInstance(ctx:Context):Context {
-		if(source == null)
-			return ctx;
 		ctx = ctx.clone(this);
-		var shader = makeShader(ctx,false);
+		var shader = makeShader(ctx);
 		if( shader == null )
 			return ctx;
-		if(ctx.local2d != null) {
+		if( ctx.local2d != null ) {
 			var drawable = Std.downcast(ctx.local2d, h2d.Drawable);
 			if (drawable != null) {
 				drawable.addShader(shader);
@@ -90,7 +35,7 @@ class Shader extends Prefab {
 				}
 			}
 		}
-		if(ctx.local3d != null) {
+		if( ctx.local3d != null ) {
 			var parent = parent;
 			var shared = ctx.shared;
 			while( parent != null && parent.parent == null && shared.parent != null ) {
@@ -112,143 +57,4 @@ class Shader extends Prefab {
 		return ctx;
 	}
 
-	function fixSourcePath() {
-		#if editor
-		var ide = hide.Ide.inst;
-		var shadersPath = ide.projectDir + "/src";  // TODO: serach in haxe.classPath?
-
-		var path = source.split("\\").join("/");
-		if( StringTools.startsWith(path.toLowerCase(), shadersPath.toLowerCase()+"/") ) {
-			path = path.substr(shadersPath.length + 1);
-		}
-		source = path;
-		#end
-	}
-
-	public function loadShaderDef(ctx: Context) {
-		if(shaderDef == null) {
-			fixSourcePath();
-			var path = source;
-			if(StringTools.endsWith(path, ".hx")) {
-				path = path.substr(0, -3);
-			}
-			shaderDef = ctx.loadShader(path);
-		}
-		if(shaderDef == null)
-			return;
-
-		#if editor
-		// TODO: Where to init prefab default values?
-		for( v in shaderDef.inits ) {
-			if(!Reflect.hasField(props, v.variable.name)) {
-				Reflect.setField(props, v.variable.name, v.value);
-			}
-		}
-		for(v in shaderDef.shader.data.vars) {
-			if(v.kind != Param)
-				continue;
-			if(!Reflect.hasField(props, v.name)) {
-				Reflect.setField(props, v.name, getDefault(v.type));
-			}
-		}
-		#end
-	}
-
-	#if editor
-
-	override function edit( ctx : EditContext ) {
-		super.edit(ctx);
-
-		loadShaderDef(ctx.rootContext);
-		if(shaderDef == null)
-			return;
-
-		var group = new hide.Element('<div class="group" name="Shader"></div>');
-
-		var props = [];
-		for(v in shaderDef.shader.data.vars) {
-			if(v.kind != Param)
-				continue;
-			var prop = makeShaderType(v);
-			props.push({name: v.name, t: prop});
-		}
-		group.append(hide.comp.PropsEditor.makePropsList(props));
-
-		ctx.properties.add(group,this.props, function(pname) {
-			ctx.onChange(this, pname);
-		});
-	}
-
-	function makeShaderType( v : hxsl.Ast.TVar ) : hrt.prefab.Props.PropType {
-		var min : Null<Float> = null, max : Null<Float> = null;
-		if( v.qualifiers != null )
-			for( q in v.qualifiers )
-				switch( q ) {
-				case Range(rmin, rmax): min = rmin; max = rmax;
-				default:
-				}
-		return switch( v.type ) {
-		case TInt:
-			PInt(min == null ? null : Std.int(min), max == null ? null : Std.int(max));
-		case TFloat:
-			PFloat(min != null ? min : 0.0, max != null ? max : 1.0);
-		case TBool:
-			PBool;
-		case TSampler2D:
-			PTexture;
-		case TVec(n, VFloat):
-			PVec(n);
-		default:
-			PUnsupported(hxsl.Ast.Tools.toString(v.type));
-		}
-	}
-	override function getHideProps() : HideProps {
-		return { icon : "cog", name : "Shader", fileSource : ["hx"], allowParent : function(p) return p.to(Object2D) != null || p.to(Object3D) != null || p.to(Material) != null  };
-	}
-
-	#end
-
-	public static function evalConst( e : hxsl.Ast.TExpr ) : Dynamic {
-		return switch( e.e ) {
-		case TConst(c):
-			switch( c ) {
-			case CNull: null;
-			case CBool(b): b;
-			case CInt(i): i;
-			case CFloat(f): f;
-			case CString(s): s;
-			}
-		case TCall({ e : TGlobal(Vec2 | Vec3 | Vec4) }, args):
-			var vals = [for( a in args ) evalConst(a)];
-			if( vals.length == 1 )
-				switch( e.t ) {
-				case TVec(n, _):
-					for( i in 0...n - 1 ) vals.push(vals[0]);
-					return vals;
-				default:
-					throw "assert";
-				}
-			return vals;
-		default:
-			throw "Unhandled constant init " + hxsl.Printer.toString(e);
-		}
-	}
-
-	public static function getDefault(type: hxsl.Ast.Type): Dynamic {
-		switch(type) {
-			case TBool:
-				return false;
-			case TInt:
-				return 0;
-			case TFloat:
-				return 0.0;
-			case TVec( size, VFloat ):
-				return [for(i in 0...size) 0];
-			default:
-				return null;
-		}
-		return null;
-	}
-
-	static var _ = Library.register("shader", Shader);
 }

+ 1 - 1
hrt/prefab/ShaderGraph.hx

@@ -1,6 +1,6 @@
 package hrt.prefab;
 
-class ShaderGraph extends Shader {
+class ShaderGraph extends DynamicShader {
 
 	public function new(?parent) {
 		super(parent);

+ 4 - 5
hrt/prefab/fx/BaseFX.hx

@@ -83,20 +83,19 @@ class BaseFX extends hrt.prefab.Library {
 	}
 
 	public static function makeShaderParams(ctx: Context, shaderElt: hrt.prefab.Shader) {
-		shaderElt.loadShaderDef(ctx);
-		var shaderDef = shaderElt.shaderDef;
+		var shaderDef = shaderElt.getShaderDefinition(ctx);
 		if(shaderDef == null)
 			return null;
 
 		var ret : ShaderParams = [];
 
-		for(v in shaderDef.shader.data.vars) {
+		for(v in shaderDef.data.vars) {
 			if(v.kind != Param)
 				continue;
 
 			var prop = Reflect.field(shaderElt.props, v.name);
 			if(prop == null)
-				prop = hrt.prefab.Shader.getDefault(v.type);
+				prop = hrt.prefab.DynamicShader.getDefault(v.type);
 
 			var curves = Curve.getCurves(shaderElt, v.name);
 			if(curves == null || curves.length == 0)
@@ -139,7 +138,7 @@ class BaseFX extends hrt.prefab.Library {
 			}
 		}
 
-		var shader = elt.to(hrt.prefab.Shader);
+		var shader = elt.to(hrt.prefab.DynamicShader);
 		if(shader == null)
 			return;