ソースを参照

Update FX Editor
Update Emitter
Update Script Editor

ShiroSmith 6 年 前
コミット
21e59f3e7b
5 ファイル変更232 行追加25 行削除
  1. 4 2
      hide/comp/ScriptEditor.hx
  2. 7 8
      hide/prefab/fx/Emitter.hx
  3. 26 4
      hide/prefab/fx/FX.hx
  4. 27 11
      hide/view/FXEditor.hx
  5. 168 0
      hide/view/FXScript.hx

+ 4 - 2
hide/comp/ScriptEditor.hx

@@ -20,7 +20,7 @@ class ScriptChecker {
 		ide = hide.Ide.inst;
 
 		var files : Array<String> = config.get("script.api.files");
-		if( files.length >= 0 ) {
+		if( files != null && files.length >= 0 ) {
 			var types = TYPES_SAVE.get(files.join(";"));
 			if( types == null ) {
 				types = new hscript.Checker.CheckerTypes();
@@ -39,7 +39,9 @@ class ScriptChecker {
 		while( parts.length > 0 ) {
 			var path = parts.join(".");
 			parts.pop();
-			var api = (config.get("script.api") : GlobalsDef).get(path);
+			var config = config.get("script.api");
+			if( config == null ) continue;
+			var api = (config : GlobalsDef).get(path);
 			if( api == null ) continue;
 
 			for( f in api.globals.keys() ) {

+ 7 - 8
hide/prefab/fx/Emitter.hx

@@ -63,8 +63,8 @@ private class ParticleInstance extends h3d.scene.Object {
 
 	public function new(emitter: EmitterObject, def: InstanceDef) {
 		switch(emitter.simulationSpace){
-			case Local:super(emitter.parent);
-			case World:super(emitter.getScene());
+			case Local : super(emitter.parent);
+			case World : super(emitter.getScene());
 		}
 		this.def = def;
 		this.emitter = emitter;
@@ -248,11 +248,6 @@ class EmitterObject extends h3d.scene.Object {
 		if(instDef == null || particleTemplate == null)
 			return;
 
-		var localMat = getAbsPos().clone();
-		var parentInvMat = parent.getAbsPos().clone();
-		parentInvMat.invert();
-		localMat.multiply(localMat, parentInvMat);
-
 		var shapeAngle = hxd.Math.degToRad(emitAngle) / 2.0;
 
 		var tmpq = new h3d.Quat();
@@ -264,7 +259,6 @@ class EmitterObject extends h3d.scene.Object {
 			context.local3d = part;
 			var ctx = particleTemplate.makeInstance(context);
 
-			var localQuat = getRotationQuat().clone();
 			tmpq.identity();
 
 			switch(emitShape) {
@@ -318,6 +312,11 @@ class EmitterObject extends h3d.scene.Object {
 
 			switch(simulationSpace){
 				case Local:
+					var localQuat = getRotationQuat().clone();
+					var localMat = getAbsPos().clone();
+					var parentInvMat = parent.getAbsPos().clone();
+					parentInvMat.invert();
+					localMat.multiply(localMat, parentInvMat);
 					offset.transform(localMat);
 					part.setPosition(offset.x, offset.y, offset.z);
 					part.baseMat = particleTemplate.getTransform();

+ 26 - 4
hide/prefab/fx/FX.hx

@@ -48,6 +48,7 @@ typedef ObjectAnimation = {
 class FXAnimation extends h3d.scene.Object {
 
 	public var duration : Float;
+	public var loopAnims : Bool;
 	public var objects: Array<ObjectAnimation> = [];
 	public var shaderAnims : Array<ShaderAnimation> = [];
 	public var emitters : Array<hide.prefab.fx.Emitter.EmitterObject> = [];
@@ -135,7 +136,12 @@ class FXAnimation extends h3d.scene.Object {
 			if(object.currentAnimation != null){
 				anim.loop = false;
 				anim.pause = true;
-				anim.setFrame( hxd.Math.clamp(time * anim.sampling * anim.speed, 0, anim.frameCount) );
+				if(loopAnims){
+					var frameTime = time * anim.sampling * anim.speed;
+					var frameIndex = frameTime - hxd.Math.floor(frameTime / anim.frameCount) * anim.frameCount;
+					anim.setFrame( frameIndex );
+				}else
+					anim.setFrame( hxd.Math.clamp(time * anim.sampling * anim.speed, 0, anim.frameCount));
 			}
 			for(i in 0...object.numChildren)
 				setAnimFrame(object.getChildAt(i), time);
@@ -155,7 +161,8 @@ class FXAnimation extends h3d.scene.Object {
 			var isInFX = co.object.split(".")[1] == "FXRoot";
 			var srcObj = objectName == "FXRoot" ? this : isInFX ? this.getObjectByName(objectName) : caster.getObjectByName(objectName);
 			var targetObj = caster.getObjectByName(targetName);
-			if( srcObj != null && targetObj != null ) srcObj.follow = targetObj;
+			if( srcObj != null && targetObj != null )
+				srcObj.follow = targetObj;
 		}
 	}
 }
@@ -163,23 +170,29 @@ class FXAnimation extends h3d.scene.Object {
 class FX extends hxd.prefab.Library {
 
 	public var duration : Float;
-	public var caster : h3d.scene.Object;
+	public var loopAnims : Bool;
+	public var script : String;
 
 	public function new() {
 		super();
 		type = "fx";
 		duration = 5.0;
+		loopAnims = true;
 	}
 
 	override function save() {
 		var obj : Dynamic = super.save();
 		obj.duration = duration;
+		obj.loopAnims = loopAnims;
+		obj.script = script;
 		return obj;
 	}
 
 	override function load( obj : Dynamic ) {
 		super.load(obj);
-		duration = obj.duration;
+		duration = obj.duration == null ? 5.0 : obj.duration;
+		loopAnims = obj.loopAnims == null ? true : obj.loopAnims;
+		script = obj.script == null ? '// My Script ' : obj.script;
 	}
 
 	static function getObjAnimations(ctx:Context, elt: PrefabElement, anims: Array<ObjectAnimation>) {
@@ -362,6 +375,7 @@ class FX extends hxd.prefab.Library {
 		ctx = ctx.clone(this);
 		var fxanim = new FXAnimation(ctx.local3d);
 		fxanim.duration = duration;
+		fxanim.loopAnims = loopAnims;
 		ctx.local3d = fxanim;
 
 		#if editor
@@ -387,12 +401,20 @@ class FX extends hxd.prefab.Library {
 		return ctx;
 	}
 
+	override function updateInstance( ctx: Context, ?propName : String ) {
+		super.updateInstance(ctx, null);
+		var fxanim = Std.instance(ctx.local3d, FXAnimation);
+		fxanim.duration = duration;
+		fxanim.loopAnims = loopAnims;
+	}
+
 	#if editor
 	override function edit( ctx : EditContext ) {
 		var props = new hide.Element('
 			<div class="group" name="FX Scene">
 				<dl>
 					<dt>Duration</dt><dd><input type="number" value="0" field="duration"/></dd>
+					<dt>Loop Anims</dt><dd><input type="checkbox" field="loopAnims"/></dd>
 				</dl>
 			</div>');
 		ctx.properties.add(props, this, function(pname) {

+ 27 - 11
hide/view/FXEditor.hx

@@ -107,6 +107,9 @@ class FXEditor extends FileView {
 	var refreshDopesheetKeys : Array<Bool->Void> = [];
 	var statusText : h2d.Text;
 
+	var scriptEditor : hide.comp.ScriptEditor;
+	var fxScript : FXScript;
+
 	override function getDefaultContent() {
 		return haxe.io.Bytes.ofString(ide.toJSON(new hide.prefab.fx.FX().save()));
 	}
@@ -166,6 +169,10 @@ class FXEditor extends FileView {
 						<div class="tab" name="Properties" icon="cog">
 							<div class="fx-props"></div>
 						</div>
+						<div class="tab" name="Script" icon="cog">
+							<div class="fx-script"></div>
+							<div class="fx-scriptParams"></div>
+						</div>
 					</div>
 				</div>
 			</div>');
@@ -189,6 +196,18 @@ class FXEditor extends FileView {
 			data.edit(edit);
 		}
 
+		var scriptElem = element.find(".fx-script");
+		scriptEditor = new hide.comp.ScriptEditor(data.script, null, scriptElem, scriptElem);
+		function onSaveScript() {
+			data.script = scriptEditor.script;
+			save();
+			skipNextChange = true;
+			modified = false;
+		}
+		scriptEditor.onSave = onSaveScript;
+		fxScript = new FXScript(this);
+		fxScript.updateScriptParams();
+
 		keys.register("playPause", function() { pauseButton.toggle(!pauseButton.isDown()); });
 
 		currentVersion = undo.currentID;
@@ -289,14 +308,9 @@ class FXEditor extends FileView {
 
 		var axis = new h3d.scene.Graphics(scene.s3d);
 		axis.z = 0.001;
-		axis.lineStyle(2,0xFF0000);
-		axis.lineTo(1,0,0);
-		axis.lineStyle(1,0x00FF00);
-		axis.moveTo(0,0,0);
-		axis.lineTo(0,1,0);
-		axis.lineStyle(1,0x0000FF);
-		axis.moveTo(0,0,0);
-		axis.lineTo(0,0,1);
+		axis.lineStyle(2,0xFF0000); axis.lineTo(1,0,0);
+		axis.lineStyle(1,0x00FF00); axis.moveTo(0,0,0); axis.lineTo(0,1,0);
+		axis.lineStyle(1,0x0000FF); axis.moveTo(0,0,0); axis.lineTo(0,0,1);
 		axis.lineStyle();
 		axis.material.mainPass.setPassName("debuggeom");
 		axis.visible = showGrid;
@@ -673,7 +687,6 @@ class FXEditor extends FileView {
 		updateExpanded();
 	}
 
-
 	function rebuildAnimPanel() {
 		var selection = sceneEditor.getSelection();
 		var scrollPanel = element.find(".anim-scroll");
@@ -974,14 +987,17 @@ class FXEditor extends FileView {
 			lastSyncChange = properties.lastChange;
 			currentVersion = undo.currentID;
 		}
-	}
 
+		if( data.script != scriptEditor.script ){
+			modified = true;
+			fxScript.updateScriptParams();
+		}
+	}
 
 	static function getTrack(element : PrefabElement, propName : String) {
 		return Curve.getCurve(element, propName, false);
 	}
 
-
 	static function upperCase(prop: String) {
 		if(prop == null) return "";
 		return prop.charAt(0).toUpperCase() + prop.substr(1);

+ 168 - 0
hide/view/FXScript.hx

@@ -0,0 +1,168 @@
+package hide.view;
+using Lambda;
+
+enum ParamOption{
+	Range(min : Float, max : Float);
+}
+
+enum FXParam{
+	Float(name : String, value : Float, options : Array<ParamOption>);
+	Int(name : String, value : Int, options : Array<ParamOption>);
+}
+
+@:access(hide.view.FXEditor)
+class FXScript {
+
+	var editor : hide.view.FXEditor;
+
+	public function new(editor){
+		this.editor = editor;
+	}
+
+	public function updateScriptParams(){
+		var parser = new hscript.Parser();
+		parser.allowMetadata = true;
+		parser.allowTypes = true;
+		parser.allowJSON = true;
+		var params : Array<FXParam> = [];
+		var expr : hscript.Expr = null;
+		var parseDebug = true;
+
+		function parseExpr(expr : hscript.Expr ) {
+			if( expr == null ) return;
+			switch(expr.e){
+
+				case EBlock(e):
+					for(expr in e)
+						parseExpr(expr);
+
+				case EMeta(name, args, e):
+					switch(name){
+						case "param" : params.push(createParam(e));
+					}
+
+				default:
+			}
+		}
+
+		try {
+			expr = parser.parseString(editor.scriptEditor.script, "");
+			parseExpr(expr);
+		} catch( e : hscript.Expr.Error ) { }
+
+		generateUI(params);
+	}
+
+
+	function createParam( expr : hscript.Expr ) : FXParam {
+		var options : Array<ParamOption> = [];
+		function parse(expr : hscript.Expr) : FXParam {
+			if( expr == null ) return null;
+			switch(expr.e){
+				case EMeta(name, args, e):
+					switch(name){
+						case "range":
+						var min = 	switch(args[0].e){
+										case EConst(c):
+											switch(c){
+												case CInt(v): v;
+												case CFloat(f): f;
+												default: null;
+											}
+										default: null;
+									}
+						var max = 	switch(args[1].e){
+										case EConst(c):
+											switch(c){
+												case CInt(v): v;
+												case CFloat(f): f;
+												default: null;
+											}
+										default: null;
+									}
+						options.push(Range(min, max));
+						default:
+					}
+					return parse(e);
+
+				case EVar(n, t, e):
+					if(e == null){
+						switch(t){
+							case CTPath(path, params):
+								switch(path){
+									case ["Int"]: return FXParam.Int(n, null, options);
+									case ["Float"]: return FXParam.Float(n, null, options);
+									default:
+								}
+							default:
+						}
+					}
+					else{
+						switch(e.e){
+							case EConst(c):
+								switch(c){
+									case CInt(v): return FXParam.Int(n, v, options);
+									case CFloat(f): return FXParam.Float(n, f, options);
+									default: null;
+								}
+							default: null;
+						}
+					}
+
+				default:
+					return null;
+			}
+			return null;
+		}
+		return parse(expr);
+	}
+
+	function generateUI( params : Array<FXParam> ){
+		var elem = editor.element.find(".fx-scriptParams");
+		elem.empty();
+		var root = new Element('<div class="group" name="Params"></div>');
+		for(p in params){
+			switch(p){
+				case Float(name, value, options):
+					var sliderMin = 0.0;
+					var sliderMax = 1.0;
+					for(o in options){
+						switch(o){
+							case Range(min, max):
+								sliderMin = min;
+								sliderMax = max;
+							default:
+						}
+					}
+					root.append(createSlider(name, sliderMin, sliderMax, 0.1, value));
+				case Int(name, value, options):
+					var sliderMin = 0.0;
+					var sliderMax = 1.0;
+					for(o in options){
+						switch(o){
+							case Range(min, max):
+								sliderMin = min;
+								sliderMax = max;
+							default:
+						}
+					}
+					root.append(createSlider(name, sliderMin, sliderMax, 1.0, value));
+			}
+		}
+		elem.append(root);
+	}
+
+	function createSlider(name : String, min : Float, max : Float, step : Float, defaultVal : Float) : Element {
+		var root = new Element('<div class="fx-slider"></div>');
+		var name = new Element('<label> $name : </label>');
+		var min = new Element('<label> $min </label>');
+		var max = new Element('<label> $max </label>');
+		var slider = new Element('<input class="param" type="range" min="$min" max="$max" step="$step" value="$defaultVal"/>');
+		var range = new hide.comp.Range(slider, null);
+		root.append(name);
+		root.append(min);
+		root.append(slider);
+		root.append(max);
+		return root;
+	}
+}