Browse Source

blend modes, event Over/Out/drag

git-svn-id: https://svn.shirogames.com/evoland1/lib@14 9d342a87-36e0-4458-8f1b-22e0acdbfa51
ncannasse 13 years ago
parent
commit
91ec52b8e8
11 changed files with 276 additions and 100 deletions
  1. 1 73
      h2d/Bitmap.hx
  2. 9 0
      h2d/BlendMode.hx
  3. 2 2
      h2d/CachedBitmap.hx
  4. 8 0
      h2d/Event.hx
  5. 11 5
      h2d/Graphics.hx
  6. 31 2
      h2d/Interactive.hx
  7. 99 8
      h2d/Scene.hx
  8. 8 0
      h2d/Sprite.hx
  9. 7 2
      h2d/SpriteBatch.hx
  10. 6 8
      h2d/TileGroup.hx
  11. 94 0
      h2d/Tools.hx

+ 1 - 73
h2d/Bitmap.hx

@@ -1,27 +1,5 @@
 package h2d;
 
-private class BitmapShader extends h3d.Shader {
-	static var SRC = {
-		var input : {
-			pos : Float2,
-		};
-		var tuv : Float2;
-		function vertex( size : Float3, mat1 : Float3, mat2 : Float3, uvScale : Float2, uvPos : Float2 ) {
-			var tmp : Float4;
-			var spos = pos.xyw * size;
-			tmp.x = spos.dp3(mat1);
-			tmp.y = spos.dp3(mat2);
-			tmp.z = 0;
-			tmp.w = 1;
-			out = tmp;
-			tuv = pos * uvScale + uvPos;
-		}
-		function fragment( tex : Texture, color : Float4 ) {
-			out = tex.get(tuv, nearest) * color;
-		}
-	}
-}
-
 class Bitmap extends Sprite {
 
 	public var data : TilePos;
@@ -34,58 +12,8 @@ class Bitmap extends Sprite {
 		this.data = data;
 	}
 	
-	static var BITMAP_OBJ : h3d.CustomObject<BitmapShader> = null;
-	static var TMP_VECTOR = new h3d.Vector();
-	
-	@:allow(h2d)
-	static function drawTile( engine : h3d.Engine, spr : Sprite, data : TilePos, color : h3d.Color ) {
-		var b = BITMAP_OBJ;
-		if( b == null ) {
-			var p = new h3d.prim.Quads([
-				new h3d.Point(0, 0),
-				new h3d.Point(1, 0),
-				new h3d.Point(0, 1),
-				new h3d.Point(1, 1),
-			]);
-			b = new h3d.CustomObject(p, new BitmapShader());
-			b.material.blend(SrcAlpha, OneMinusSrcAlpha);
-			b.material.culling = None;
-			b.material.depth(false, Always);
-			BITMAP_OBJ = b;
-		}
-		var tmp = TMP_VECTOR;
-		tmp.x = data.w;
-		tmp.y = data.h;
-		tmp.z = 1;
-		b.shader.size = tmp;
-		tmp.x = spr.matA;
-		tmp.y = spr.matC;
-		tmp.z = spr.absX + data.dx * spr.matA + data.dy * spr.matC;
-		b.shader.mat1 = tmp;
-		tmp.x = spr.matB;
-		tmp.y = spr.matD;
-		tmp.z = spr.absY + data.dx * spr.matB + data.dy * spr.matD;
-		b.shader.mat2 = tmp;
-		tmp.x = data.u;
-		tmp.y = data.v;
-		b.shader.uvPos = tmp;
-		tmp.x = data.u2 - data.u;
-		tmp.y = data.v2 - data.v;
-		b.shader.uvScale = tmp;
-		if( color == null ) {
-			tmp.x = 1;
-			tmp.y = 1;
-			tmp.z = 1;
-			tmp.w = 1;
-			b.shader.color = tmp;
-		} else
-			b.shader.color = color.toVector();
-		b.shader.tex = data.tiles.getTexture(engine);
-		b.render(engine);
-	}
-	
 	override function draw( engine : h3d.Engine ) {
-		drawTile(engine, this, data, color);
+		Tools.drawTile(engine, this, data, color, blendMode);
 	}
 	
 	inline function get_alpha() {

+ 9 - 0
h2d/BlendMode.hx

@@ -0,0 +1,9 @@
+package h2d;
+
+enum BlendMode {
+	Normal;
+	None;
+	Add;
+	Multiply;
+	Erase;
+}

+ 2 - 2
h2d/CachedBitmap.hx

@@ -73,7 +73,7 @@ class CachedBitmap extends Sprite {
 	
 	override function draw( engine : h3d.Engine ) {
 		if( colorMatrix == null && colorAdd == null ) {
-			Bitmap.drawTile(engine, this, tile, new h3d.Color(1, 1, 1, 1));
+			Tools.drawTile(engine, this, tile, new h3d.Color(1, 1, 1, 1), blendMode);
 			return;
 		}
 		var b = BITMAP_OBJ;
@@ -85,11 +85,11 @@ class CachedBitmap extends Sprite {
 				new h3d.Point(1, 1),
 			]);
 			b = new h3d.CustomObject(p, new BitmapMatrixShader());
-			b.material.blend(SrcAlpha, OneMinusSrcAlpha);
 			b.material.culling = None;
 			b.material.depth(false, Always);
 			BITMAP_OBJ = b;
 		}
+		Tools.setBlendMode(b.material,blendMode);
 		var tmp = TMP_VECTOR;
 		tmp.x = tile.w;
 		tmp.y = tile.h;

+ 8 - 0
h2d/Event.hx

@@ -4,6 +4,8 @@ enum EventKind {
 	EPush;
 	ERelease;
 	EMove;
+	EOver;
+	EOut;
 }
 
 class Event {
@@ -11,6 +13,8 @@ class Event {
 	public var kind : EventKind;
 	public var relX : Float;
 	public var relY : Float;
+	public var propagate : Bool;
+	public var cancel : Bool;
 	
 	public function new(k,x=0.,y=0.) {
 		kind = k;
@@ -18,4 +22,8 @@ class Event {
 		this.relY = y;
 	}
 	
+	public function toString() {
+		return kind + "[" + Std.int(relX) + "," + Std.int(relY) + "]";
+	}
+	
 }

+ 11 - 5
h2d/Graphics.hx

@@ -5,22 +5,28 @@ class GraphicsContext {
 	
 	var g : Graphics;
 	var mc : flash.display.Sprite;
+	var mcg : flash.display.Graphics;
 	
 	function new(g) {
 		this.g = g;
 		this.mc = new flash.display.Sprite();
+		mcg = mc.graphics;
 	}
 	
 	public inline function beginFill( color : Int, alpha = 1. ) {
-		mc.graphics.beginFill(color, alpha);
+		mcg.beginFill(color, alpha);
+	}
+	
+	public inline function drawCircle(cx, cy, radius) {
+		mcg.drawCircle(cx, cy, radius);
 	}
 	
 	public inline function drawRect(x,y,width,height) {
-		mc.graphics.drawRect(x, y, width, height);
+		mcg.drawRect(x, y, width, height);
 	}
 	
 	public inline function endFill() {
-		mc.graphics.endFill();
+		mcg.endFill();
 	}
 	
 }
@@ -29,7 +35,7 @@ class Graphics extends Sprite {
 
 	var tile : TilePos;
 	var ctx : GraphicsContext;
-	
+		
 	public function beginDraw() {
 		return (ctx = new GraphicsContext(this));
 	}
@@ -51,7 +57,7 @@ class Graphics extends Sprite {
 	override function draw(engine) {
 		if( tile == null ) endDraw();
 		if( tile == null ) return;
-		Bitmap.drawTile(engine, this, tile, null);
+		Tools.drawTile(engine, this, tile, null, blendMode);
 	}
 
 }

+ 31 - 2
h2d/Interactive.hx

@@ -4,7 +4,8 @@ class Interactive extends Sprite {
 
 	public var width : Float;
 	public var height : Float;
-	public var useMouseHand : Bool;
+	public var useMouseHand(default,set) : Bool;
+	public var isEllipse : Bool;
 	var scene : Scene;
 	
 	public function new(width, height, ?parent) {
@@ -30,9 +31,18 @@ class Interactive extends Sprite {
 			scene.removeEventTarget(this);
 		super.onDelete();
 	}
-	
+
 	@:allow(h2d.Scene)
 	function handleEvent( e : Event ) {
+		if( isEllipse && (e.kind != EOut && e.kind != ERelease) ) {
+			var cx = width * 0.5, cy = height * 0.5;
+			var dx = (e.relX - cx) / cx;
+			var dy = (e.relY - cy) / cy;
+			if( dx * dx + dy * dy > 1 ) {
+				e.cancel = true;
+				return;
+			}
+		}
 		switch( e.kind ) {
 		case EMove:
 			onMove(e);
@@ -40,9 +50,28 @@ class Interactive extends Sprite {
 			onPush(e);
 		case ERelease:
 			onRelease(e);
+		case EOver:
+			if( useMouseHand ) flash.ui.Mouse.cursor = flash.ui.MouseCursor.BUTTON;
+			onOver(e);
+		case EOut:
+			if( useMouseHand ) flash.ui.Mouse.cursor = flash.ui.MouseCursor.AUTO;
+			onOut(e);
 		}
 	}
 	
+	function set_useMouseHand(v) {
+		this.useMouseHand = v;
+		if( scene != null && scene.currentOver == this )
+			flash.ui.Mouse.cursor = v ? flash.ui.MouseCursor.BUTTON : flash.ui.MouseCursor.AUTO;
+		return v;
+	}
+	
+	public dynamic function onOver( e : Event ) {
+	}
+
+	public dynamic function onOut( e : Event ) {
+	}
+	
 	public dynamic function onPush( e : Event ) {
 	}
 

+ 99 - 8
h2d/Scene.hx

@@ -3,14 +3,27 @@ package h2d;
 class Scene extends Sprite {
 
 	public var width(default,null) : Int;
-	public var height(default,null) : Int;
+	public var height(default, null) : Int;
+	
+	public var mouseX(get, null) : Float;
+	public var mouseY(get, null) : Float;
+	
 	var fixedSize : Bool;
 	var interactive : flash.Vector<Interactive>;
 	var pendingEvents : flash.Vector<Event>;
+	var stage : flash.display.Stage;
+	
+	
+	@:allow(h2d.Interactive)
+	var currentOver : Interactive;
+	var pushList : Array<Interactive>;
+	var currentDrag : Event -> Void;
 	
 	public function new() {
 		super(null);
 		interactive = new flash.Vector();
+		pushList = new Array();
+		stage = flash.Lib.current.stage;
 	}
 	
 	public function setFixedSize( w, h ) {
@@ -21,7 +34,6 @@ class Scene extends Sprite {
 	}
 
 	override function onDelete() {
-		var stage = flash.Lib.current.stage;
 		stage.removeEventListener(flash.events.MouseEvent.MOUSE_DOWN, onMouseDown);
 		stage.removeEventListener(flash.events.MouseEvent.MOUSE_MOVE, onMouseMove);
 		stage.removeEventListener(flash.events.MouseEvent.MOUSE_UP, onMouseUp);
@@ -29,26 +41,33 @@ class Scene extends Sprite {
 	}
 	
 	override function onAlloc() {
-		var stage = flash.Lib.current.stage;
 		stage.addEventListener(flash.events.MouseEvent.MOUSE_DOWN, onMouseDown);
 		stage.addEventListener(flash.events.MouseEvent.MOUSE_MOVE, onMouseMove);
 		stage.addEventListener(flash.events.MouseEvent.MOUSE_UP, onMouseUp);
 		super.onAlloc();
 	}
 	
+	function get_mouseX() {
+		return stage.mouseX * width / stage.stageWidth;
+	}
+
+	function get_mouseY() {
+		return stage.mouseY * height / stage.stageHeight;
+	}
+	
 	function onMouseDown(e:flash.events.MouseEvent) {
 		if( pendingEvents != null )
-			pendingEvents.push(new Event(EPush, e.localX, e.localY));
+			pendingEvents.push(new Event(EPush, mouseX, mouseY));
 	}
 
 	function onMouseUp(e:flash.events.MouseEvent) {
 		if( pendingEvents != null )
-			pendingEvents.push(new Event(ERelease, e.localX, e.localY));
+			pendingEvents.push(new Event(ERelease, mouseX, mouseY));
 	}
 	
 	function onMouseMove(e:flash.events.MouseEvent) {
 		if( pendingEvents != null )
-			pendingEvents.push(new Event(EMove, e.localX, e.localY));
+			pendingEvents.push(new Event(EMove, mouseX, mouseY));
 	}
 	
 	function emitEvent( event : Event ) {
@@ -56,8 +75,15 @@ class Scene extends Sprite {
 		var rx = x * matA + y * matB + absX;
 		var ry = x * matC + y * matD + absY;
 		var r = height / width;
-		
+		var checkOver = false, checkPush = false;
+		switch( event.kind ) {
+		case EMove: checkOver = true;
+		case EPush, ERelease: checkPush = true;
+		default:
+		}
 		for( i in interactive ) {
+			// TODO : we are not sure that the positions are correctly updated !
+			
 			// this is a bit tricky since we are not in the not-euclide viewport space
 			// (r = ratio correction)
 			var dx = rx - i.absX;
@@ -82,10 +108,54 @@ class Scene extends Sprite {
 			// bottom/right
 			if( ky > max || kx * r > max )
 				continue;
+
 						
 			event.relX = (kx * r / max) * i.width;
 			event.relY = (ky / max) * i.height;
+
 			i.handleEvent(event);
+			if( event.cancel )
+				event.cancel = false;
+			else if( checkOver ) {
+				if( currentOver != i ) {
+					var old = event.propagate;
+					if( currentOver != null ) {
+						event.kind = EOut;
+						// relX/relY is not correct here
+						currentOver.handleEvent(event);
+					}
+					event.kind = EOver;
+					event.cancel = false;
+					i.handleEvent(event);
+					if( event.cancel )
+						currentOver = null;
+					else {
+						currentOver = i;
+						checkOver = false;
+					}
+					event.kind = EMove;
+					event.cancel = false;
+					event.propagate = old;
+				} else
+					checkOver = false;
+			} else if( checkPush ) {
+				if( event.kind == EPush )
+					pushList.push(i);
+				else
+					pushList.remove(i);
+			}
+				
+			if( event.propagate ) {
+				event.propagate = false;
+				continue;
+			}
+			break;
+		}
+		if( checkOver && currentOver != null ) {
+			event.kind = EOut;
+			currentOver.handleEvent(event);
+			event.kind = EMove;
+			currentOver = null;
 		}
 	}
 	
@@ -99,12 +169,33 @@ class Scene extends Sprite {
 		if( old.length == 0 )
 			return;
 		pendingEvents = null;
-		for( e in old )
+		for( e in old ) {
+			if( currentDrag != null ) {
+				currentDrag(e);
+				if( e.cancel )
+					continue;
+			}
 			emitEvent(e);
+			if( e.kind == ERelease && pushList.length > 0 ) {
+				for( i in pushList ) {
+					// relX/relY is not correct here
+					i.handleEvent(e);
+				}
+				pushList = new Array();
+			}
+		}
 		if( interactive.length > 0 )
 			pendingEvents = new flash.Vector();
 	}
 	
+	public function startDrag( f : Event -> Void ) {
+		currentDrag = f;
+	}
+	
+	public function stopDrag() {
+		currentDrag = null;
+	}
+	
 	@:allow(h2d)
 	function addEventTarget(i) {
 		interactive.push(i);

+ 8 - 0
h2d/Sprite.hx

@@ -1,5 +1,6 @@
 package h2d;
 
+@:allow(h2d.Tools)
 class Sprite {
 
 	static inline var ROT2RAD = -0.017453292519943295769236907684886;
@@ -12,6 +13,7 @@ class Sprite {
 	public var scaleX(default,set) : Float;
 	public var scaleY(default,set) : Float;
 	public var rotation(default,set) : Float;
+	public var blendMode(default,set) : BlendMode;
 
 	var matA : Float;
 	var matB : Float;
@@ -28,10 +30,16 @@ class Sprite {
 		x = 0; y = 0; scaleX = 1; scaleY = 1; rotation = 0;
 		posChanged = false;
 		childs = [];
+		blendMode = Normal;
 		if( parent != null )
 			parent.addChild(this);
 	}
 	
+	function set_blendMode(b) {
+		this.blendMode = b;
+		return b;
+	}
+	
 	public function getAbsolutePos( x = 0., y = 0. ) {
 		updatePos();
 		return { x : x * matA + y * matC + absX, y : x * matB + y * matD + absY };

+ 7 - 2
h2d/SpriteBatch.hx

@@ -58,13 +58,18 @@ class SpriteBatch extends Sprite {
 	static var SHADER = null;
 	
 	public function new(t,?parent) {
-		super(parent);
 		tiles = t;
 		if( SHADER == null )
 			SHADER = new BatchShader();
 		material = new h3d.mat.Material(SHADER);
 		material.depth(false, Always);
-		material.blend(SrcAlpha, OneMinusSrcAlpha);
+		super(parent);
+	}
+	
+	override function set_blendMode(b) {
+		Tools.setBlendMode(material, b);
+		this.blendMode = b;
+		return b;
 	}
 	
 	public function alloc(t) {

+ 6 - 8
h2d/TileGroup.hx

@@ -79,10 +79,9 @@ class TileGroup extends Sprite {
 	var content : TileLayerContent;
 	
 	public var tiles : Tiles;
-	public var color(default,null) : h3d.Color;
+	public var color(default, null) : h3d.Color;
 	
 	public function new(t,?parent) {
-		super(parent);
 		tiles = t;
 		color = new h3d.Color(1, 1, 1, 1);
 		content = new TileLayerContent();
@@ -91,7 +90,7 @@ class TileGroup extends Sprite {
 		object = new h3d.Object(content, new h3d.mat.Material(SHADER));
 		object.material.depth(false, Always);
 		object.material.culling = None;
-		setTransparency(true);
+		super(parent);
 	}
 	
 	public function reset() {
@@ -112,11 +111,10 @@ class TileGroup extends Sprite {
 		return c;
 	}
 	
-	public function setTransparency(a) {
-		if( a )
-			object.material.blend(SrcAlpha, OneMinusSrcAlpha);
-		else
-			object.material.blend(One,Zero);
+	override function set_blendMode(b) {
+		this.blendMode = b;
+		Tools.setBlendMode(object.material, b);
+		return b;
 	}
 	
 	override function draw(engine:h3d.Engine) {

+ 94 - 0
h2d/Tools.hx

@@ -0,0 +1,94 @@
+package h2d;
+
+
+private class BitmapShader extends h3d.Shader {
+	static var SRC = {
+		var input : {
+			pos : Float2,
+		};
+		var tuv : Float2;
+		function vertex( size : Float3, mat1 : Float3, mat2 : Float3, uvScale : Float2, uvPos : Float2 ) {
+			var tmp : Float4;
+			var spos = pos.xyw * size;
+			tmp.x = spos.dp3(mat1);
+			tmp.y = spos.dp3(mat2);
+			tmp.z = 0;
+			tmp.w = 1;
+			out = tmp;
+			tuv = pos * uvScale + uvPos;
+		}
+		function fragment( tex : Texture, color : Float4 ) {
+			out = tex.get(tuv, nearest) * color;
+		}
+	}
+}
+
+class Tools {
+
+	static var BITMAP_OBJ : h3d.CustomObject<BitmapShader> = null;
+	static var TMP_VECTOR = new h3d.Vector();
+		
+	@:allow(h2d)
+	static function drawTile( engine : h3d.Engine, spr : Sprite, data : TilePos, color : h3d.Color, blendMode : BlendMode ) {
+		var b = BITMAP_OBJ;
+		if( b == null ) {
+			var p = new h3d.prim.Quads([
+				new h3d.Point(0, 0),
+				new h3d.Point(1, 0),
+				new h3d.Point(0, 1),
+				new h3d.Point(1, 1),
+			]);
+			b = new h3d.CustomObject(p, new BitmapShader());
+			b.material.culling = None;
+			b.material.depth(false, Always);
+			BITMAP_OBJ = b;
+		}
+		setBlendMode(b.material, blendMode);
+		var tmp = TMP_VECTOR;
+		tmp.x = data.w;
+		tmp.y = data.h;
+		tmp.z = 1;
+		b.shader.size = tmp;
+		tmp.x = spr.matA;
+		tmp.y = spr.matC;
+		tmp.z = spr.absX + data.dx * spr.matA + data.dy * spr.matC;
+		b.shader.mat1 = tmp;
+		tmp.x = spr.matB;
+		tmp.y = spr.matD;
+		tmp.z = spr.absY + data.dx * spr.matB + data.dy * spr.matD;
+		b.shader.mat2 = tmp;
+		tmp.x = data.u;
+		tmp.y = data.v;
+		b.shader.uvPos = tmp;
+		tmp.x = data.u2 - data.u;
+		tmp.y = data.v2 - data.v;
+		b.shader.uvScale = tmp;
+		if( color == null ) {
+			tmp.x = 1;
+			tmp.y = 1;
+			tmp.z = 1;
+			tmp.w = 1;
+			b.shader.color = tmp;
+		} else
+			b.shader.color = color.toVector();
+		b.shader.tex = data.tiles.getTexture(engine);
+		b.render(engine);
+	}
+
+	@:allow(h2d)
+	static function setBlendMode( mat : h3d.mat.Material, b : BlendMode ) {
+		switch( b ) {
+		case Normal:
+			mat.blend(SrcAlpha, OneMinusSrcAlpha);
+		case None:
+			mat.blend(One, Zero);
+		case Add:
+			mat.blend(SrcAlpha, One);
+		case Multiply:
+			mat.blend(DstColor, OneMinusSrcAlpha);
+		case Erase:
+			mat.blend(Zero, OneMinusSrcAlpha);
+		}
+	}
+	
+}