浏览代码

fix in mask/interactive : use render-time bounds to handle Flow Scroll
+ Mask.maskWith use clipRenderZone so masks accumulates

Nicolas Cannasse 4 年之前
父节点
当前提交
ebce25773f
共有 3 个文件被更改,包括 17 次插入60 次删除
  1. 6 29
      h2d/Interactive.hx
  2. 2 28
      h2d/Mask.hx
  3. 9 3
      h2d/RenderContext.hx

+ 6 - 29
h2d/Interactive.hx

@@ -51,8 +51,8 @@ class Interactive extends Drawable implements hxd.SceneEvents.Interactive {
 	public var enableRightButton : Bool = false;
 	var scene : Scene;
 	var mouseDownButton : Int = -1;
-	var parentMask : Mask;
 	var invDet : Float;
+	var maskedBounds : h2d.col.Bounds;
 
 	/**
 		Detailed shape collider for Interactive.
@@ -85,11 +85,11 @@ class Interactive extends Drawable implements hxd.SceneEvents.Interactive {
 	override function onAdd() {
 		this.scene = getScene();
 		if( scene != null ) scene.addEventTarget(this);
-		updateMask();
 		super.onAdd();
 	}
 
 	override function draw( ctx : RenderContext ) {
+		maskedBounds = ctx.getCurrentRenderZone();
 		if( backgroundColor != null ) emitTile(ctx, h2d.Tile.fromColor(backgroundColor, Std.int(width), Std.int(height), (backgroundColor>>>24)/255 ));
 	}
 
@@ -107,21 +107,6 @@ class Interactive extends Drawable implements hxd.SceneEvents.Interactive {
 			if( scene != null )
 				scene.addEventTarget(this);
 		}
-		if ( parentChanged )
-			updateMask();
-	}
-
-	function updateMask() {
-		parentMask = null;
-		var p = parent;
-		while( p != null ) {
-			var m = hxd.impl.Api.downcast(p, Mask);
-			if( m != null ) {
-				parentMask = m;
-				break;
-			}
-			p = p.parent;
-		}
 	}
 
 	override function onRemove() {
@@ -153,20 +138,12 @@ class Interactive extends Drawable implements hxd.SceneEvents.Interactive {
 
 	@:dox(hide)
 	@:noCompletion public function handleEvent( e : hxd.Event ) {
-		if( parentMask != null && checkBounds(e) ) {
-			var p = parentMask;
+		if( maskedBounds != null && checkBounds(e) ) {
 			var pt = new h2d.col.Point(e.relX, e.relY);
 			localToGlobal(pt);
-			var saveX = pt.x, saveY = pt.y;
-			while( p != null ) {
-				pt.x = saveX;
-				pt.y = saveY;
-				var pt = p.globalToLocal(pt);
-				if( pt.x < 0 || pt.y < 0 || pt.x > p.width || pt.y > p.height ) {
-					e.cancel = true;
-					return;
-				}
-				p = @:privateAccess p.parentMask;
+			if( pt.x < maskedBounds.xMin || pt.y < maskedBounds.yMin || pt.x > maskedBounds.xMax || pt.y > maskedBounds.yMax ) {
+				e.cancel = true;
+				return;
 			}
 		}
 		if(shape == null && isEllipse && checkBounds(e) ) {

+ 2 - 28
h2d/Mask.hx

@@ -43,7 +43,7 @@ class Mask extends Object {
 		}
 
 		ctx.flush();
-		ctx.pushRenderZone(x1, y1, x2-x1, y2-y1);
+		ctx.clipRenderZone(x1, y1, x2-x1, y2-y1);
 	}
 
 	/**
@@ -63,7 +63,6 @@ class Mask extends Object {
 		The height of the masked area.
 	**/
 	public var height : Int;
-	var parentMask : Mask;
 
 	/**
 		Horizontal scroll offset of the Mask content in pixels. Can be clamped by `Mask.scrollBounds`.
@@ -107,30 +106,6 @@ class Mask extends Object {
 		scrollY += y;
 	}
 
-	override private function onHierarchyMoved(parentChanged:Bool) {
-		super.onHierarchyMoved(parentChanged);
-		if ( parentChanged )
-			updateMask();
-	}
-
-	override function onAdd() {
-		super.onAdd();
-		updateMask();
-	}
-
-	function updateMask() {
-		parentMask = null;
-		var p = parent;
-		while( p != null ) {
-			var m = hxd.impl.Api.downcast(p, Mask);
-			if( m != null ) {
-				parentMask = m;
-				break;
-			}
-			p = p.parent;
-		}
-	}
-
 	function set_scrollX( v : Float ) : Float {
 		if ( scrollBounds != null ) v = hxd.Math.clamp(v, scrollBounds.xMin, scrollBounds.xMax - width);
 		posChanged = true;
@@ -143,8 +118,7 @@ class Mask extends Object {
 		return scrollY = v;
 	}
 
-	override function calcAbsPos()
-	{
+	override function calcAbsPos() {
 		super.calcAbsPos();
 		absX -= scrollX;
 		absY -= scrollY;

+ 9 - 3
h2d/RenderContext.hx

@@ -20,12 +20,12 @@ class RenderContext extends h3d.impl.RenderContext {
 	static inline var BUFFERING = #if heaps_emit_tile_buffering true #else false #end;
 
 	/**
-		Current transparency value used for rendering objects. 
+		Current transparency value used for rendering objects.
 		Automatically managed by `Object`.
 	**/
 	public var globalAlpha = 1.;
 	/**
-		Temporary vertex buffer used to emit Tiles when `RenderContext.BUFFERING` is on.  
+		Temporary vertex buffer used to emit Tiles when `RenderContext.BUFFERING` is on.
 		Otherwise it's `null`. Internal usage only.
 	**/
 	@:dox(hide)
@@ -443,12 +443,18 @@ class RenderContext extends h3d.impl.RenderContext {
 		}
 	}
 
+	public function getCurrentRenderZone() {
+		if( !hasRenderZone )
+			return null;
+		return h2d.col.Bounds.fromValues(renderX, renderY, renderW, renderH);
+	}
+
 	/**
 		Pushes new render zone with respect to the old render zone settings by clipping new and old render zones,
 		pushing the intersection area result.
 		Used so that any call to the clipRenderZone respects the already set zone, and can't render outside of it.
 	**/
-	 public function clipRenderZone( x : Float, y : Float, w : Float, h : Float ) {
+	public function clipRenderZone( x : Float, y : Float, w : Float, h : Float ) {
 		if (!hasRenderZone) {
 			pushRenderZone( x, y, w, h );
 			return;