فهرست منبع

ShaderTargets: refacto shader targets

lviguier 8 ماه پیش
والد
کامیت
080088f84f
2فایلهای تغییر یافته به همراه99 افزوده شده و 69 حذف شده
  1. 1 69
      hrt/prefab/fx/FX.hx
  2. 98 0
      hrt/prefab/fx/ShaderTarget.hx

+ 1 - 69
hrt/prefab/fx/FX.hx

@@ -39,7 +39,7 @@ class FXAnimation extends h3d.scene.Object {
 	var randSeed : Int;
 	var firstSync = true;
 
-	var onRemoveFun = null;
+	var onRemoveFun : Void -> Void = null;
 
 	public function new(?parent) {
 		super(parent);
@@ -542,11 +542,6 @@ typedef Parameter = {
 	var def: Dynamic;
 };
 
-typedef ShaderTarget = {
-	name : String,
-	object : h3d.scene.Object
-};
-
 class FX extends Object3D implements BaseFX {
 
 	@:s public var duration : Float;
@@ -557,8 +552,6 @@ class FX extends Object3D implements BaseFX {
 
 	@:s public var parameters : Array<Parameter> = [];
 
-	var shaderTargets : Array<ShaderTarget> = null;
-
 	#if editor
 	static var identRegex = ~/^[A-Za-z_][A-Za-z0-9_]*$/;
 	#end
@@ -570,24 +563,6 @@ class FX extends Object3D implements BaseFX {
 	}
 
 	override function make( ?sh:hrt.prefab.Prefab.ContextMake) : Prefab  {
-		if ( shaderTargets != null) {
-			for ( target in shaderTargets ) {
-				var shadersRoot = find(Prefab, p -> target.name == p.name && p.enabled);
-				if ( shadersRoot == null )
-					continue;
-				var newRoot = new hrt.prefab.Object3D(null, sh);
-				var i = shadersRoot.children.length;
-				while ( i-- > 0 ) {
-					var c = shadersRoot.children[i];
-					if ( Std.isOfType(c, Shader) || Std.isOfType(c, Material) || Std.isOfType(c, MaterialSelector) )
-						c.parent = newRoot;
-				}
-				newRoot.name = shadersRoot.name;
-				newRoot.parent = shadersRoot.parent;
-				shadersRoot.parent = null;
-			}
-		}
-
 		var fromRef = shared.parentPrefab != null;
 		var useFXRoot = #if editor fromRef #else true #end;
 		var root = hrt.prefab.fx.BaseFX.BaseFXTools.getFXRoot(this);
@@ -644,55 +619,12 @@ class FX extends Object3D implements BaseFX {
 			return;
 
 		fxAnim.init(this, root);
-
-		if ( shaderTargets != null )
-			applyShadersToTargets();
 	}
 
 	function createInstance(parent: h3d.scene.Object) : FXAnimation {
 		return new FXAnimation(parent);
 	}
 
-	public function setShaderTargets( targets : Array<ShaderTarget>) {
-		if ( !shared.isInstance )
-			throw "Shader targets must be set on an instance";
- 		shaderTargets = targets;
-		if ( local3d != null )
-			applyShadersToTargets();
-	}
-
-	function applyShadersToTargets() {
-		var fxAnim : FXAnimation = cast local3d;
-
-		for ( target in shaderTargets ) {
-			if ( target.object == null )
-				continue;
-			var shadersRoot = find(Prefab, p -> target.name == p.name);
-			if ( shadersRoot == null )
-				continue;
-			var obj3d = Std.downcast(shadersRoot, Object3D);
-			if ( obj3d == null )
-				continue;
-			obj3d.local3d = target.object;
-			for ( s in obj3d.findAll(Shader) ) {
-				s.filterObj = o -> return o != fxAnim;
-				s.apply3d();
-			}
-		}
-
-		fxAnim.onRemoveFun = function() {
-			for ( target in shaderTargets ) {
-				if ( target.object == null )
-					continue;
-				var shadersRoot = find(Prefab, p -> target.name == p.name);
-				if ( shadersRoot == null )
-					continue;
-				for ( s in shadersRoot.findAll(Shader) )
-					s.dispose();
-			}
-		}
-	}
-
 	#if editor
 
 	override function onEditorTreeChanged(child: Prefab) : hrt.prefab.Prefab.TreeChangedResult {

+ 98 - 0
hrt/prefab/fx/ShaderTarget.hx

@@ -0,0 +1,98 @@
+package hrt.prefab.fx;
+
+class ShaderTargetObj extends h3d.scene.Object {
+	public var tag : String;
+	public var priority : Int = 1;
+	public var shadersRoot : hrt.prefab.Object3D;
+
+	public function apply(fx : hrt.prefab.fx.FX) {
+		var fxAnim : hrt.prefab.fx.FX.FXAnimation = cast fx.local3d;
+		shadersRoot.local3d = parent;
+		for ( s in shadersRoot.findAll(Shader) ) {
+			s.filterObj = o -> return o != fxAnim;
+			if (s.shader == null) {
+				s.makeShader();
+				@:privateAccess s.updateInstance();
+			}
+			s.apply3d();
+		}
+
+		if (fxAnim == null)
+			return;
+
+		@:privateAccess fxAnim.onRemoveFun = () -> {
+			this.remove();
+		}
+	}
+
+	override function onRemove() {
+		for ( s in shadersRoot.findAll(Shader) )
+			s.dispose();
+	}
+}
+
+class ShaderTarget extends Object3D {
+	@:s public var tag : String;
+	@:s public var priority : Int = 1;
+
+	public var target : h3d.scene.Object;
+	public var shaders : Array<hrt.prefab.Shader>;
+
+	public function new(parent:Prefab, contextShared: ContextShared) {
+		super(parent, contextShared);
+		this.editorOnly = true;
+	}
+
+	public static function updateShaderTargets(o : h3d.scene.Object) {
+		var sts = o.findAll(obj -> Std.downcast(obj, ShaderTargetObj));
+		for (st in sts) {
+			if (st.tag == null) continue;
+
+			for (st2 in sts) {
+				if (st2 == st) continue;
+				if (st2.tag != st.tag) continue;
+
+				var toRemove = st.priority > st2.priority ? st2 : st;
+				toRemove.remove();
+				sts.remove(toRemove);
+				break;
+			}
+		}
+	}
+
+	public function applyShaderTarget(fx : hrt.prefab.fx.FX, target : h3d.scene.Object) {
+		var o = new hrt.prefab.fx.ShaderTarget.ShaderTargetObj(target);
+		o.priority = this.priority;
+		o.tag = this.tag;
+		o.shadersRoot = this;
+
+		updateShaderTargets(target);
+
+		if (o.parent != null)
+			o.apply(fx);
+	}
+
+	#if editor
+	override function getHideProps() : hide.prefab.HideProps {
+		return { icon : "dot-circle-o", name : "Shader Target" };
+	}
+
+	override function edit( ctx : hide.prefab.EditContext ) {
+		super.edit(ctx);
+
+		var props = new hide.Element('
+			<div class="group" name="Shader Target">
+				<dl>
+					<dt>Tag</dt><dd><input type="text" field="tag"/></dd>
+					<dt>Priority</dt><dd><input type="number" min="0" max="10" value="0" field="priority"/></dd>
+				</dl>
+			</div>
+		');
+		ctx.properties.add(props, this, function(pname) {
+			ctx.onChange(this, pname);
+		});
+	}
+	#end
+
+	static var _ = Prefab.register("ShaderTarget", ShaderTarget);
+}