ソースを参照

protect interactives against multi clicks on the same frame by default

Nicolas Cannasse 3 年 前
コミット
1f533580b1
2 ファイル変更34 行追加10 行削除
  1. 18 8
      h2d/Interactive.hx
  2. 16 2
      h3d/scene/Interactive.hx

+ 18 - 8
h2d/Interactive.hx

@@ -25,6 +25,7 @@ class Interactive extends Object implements hxd.SceneEvents.Interactive {
 		Cursor used when Interactive is under mouse cursor.
 	**/
 	public var cursor(default,set) : Null<hxd.Cursor> = Button;
+
 	/**
 		Performs an elliptic hit-test instead of rectangular one based on `Interactive.width` and `height`. Ignored if `Interactive.shape` is set.
 	**/
@@ -37,20 +38,26 @@ class Interactive extends Object implements hxd.SceneEvents.Interactive {
 		Set the default `hxd.Event.propagate` mode.
 	**/
 	public var propagateEvents : Bool = false;
-	/**
-		If set, Interactive will draw a `Tile` with `[width, height]` dimensions of specified color (including alpha).
-	**/
-	public var backgroundColor : Null<Int>;
+
 	/**
 		When enabled, interacting with secondary mouse buttons (right button/wheel) will cause `onPush`, `onClick`, `onRelease` and `onReleaseOutside` callbacks.
 		Otherwise those callbacks will only be triggered with primary mouse button (left button).
-
-		Note that Interactive remembers only the last pressed button when pressing on it, hence pressing Interactive with the left button and then the right button
-		would not cause `onClick` on either when releasing left button first, as pressed state is reset internally.
 	**/
 	public var enableRightButton : Bool = false;
+
+	/**
+	 	When enabled, allows to receive several onClick events the same frame.
+	**/
+	public var allowMultiClick : Bool = false;
+
+	/**
+		If set, Interactive will draw a `Tile` with `[width, height]` dimensions of specified color (including alpha).
+	**/
+	public var backgroundColor : Null<Int>;
+
 	var scene : Scene;
 	var mouseDownButton : Int = -1;
+	var lastClickFrame : Int = -1;
 	var invDet : Float;
 	var maskedBounds : h2d.col.Bounds;
 
@@ -169,8 +176,11 @@ class Interactive extends Object implements hxd.SceneEvents.Interactive {
 		case ERelease:
 			if( enableRightButton || e.button == 0 ) {
 				onRelease(e);
-				if( mouseDownButton == e.button )
+				var frame = hxd.Timer.frameCount;
+				if( mouseDownButton == e.button && (lastClickFrame != frame || allowMultiClick) ) {
 					onClick(e);
+					lastClickFrame = frame;
+				}
 			}
 			mouseDownButton = -1;
 		case EReleaseOutside:

+ 16 - 2
h3d/scene/Interactive.hx

@@ -26,7 +26,17 @@ class Interactive extends Object implements hxd.SceneEvents.Interactive {
 		Set the default `propagate` mode (see `hxd.Event`), default to false.
 	**/
 	public var propagateEvents : Bool = false;
-	public var enableRightButton : Bool;
+
+	/**
+		When enabled, interacting with secondary mouse buttons (right button/wheel) will cause `onPush`, `onClick`, `onRelease` and `onReleaseOutside` callbacks.
+		Otherwise those callbacks will only be triggered with primary mouse button (left button).
+	**/
+	public var enableRightButton : Bool = false;
+
+	/**
+	 	When enabled, allows to receive several onClick events the same frame.
+	**/
+	public var allowMultiClick : Bool = false;
 
 	/**
 		Is it required to find the best hit point in a complex mesh or any hit possible point will be enough (default = false, faster).
@@ -35,6 +45,7 @@ class Interactive extends Object implements hxd.SceneEvents.Interactive {
 
 	var scene : Scene;
 	var mouseDownButton : Int = -1;
+	var lastClickFrame : Int = -1;
 
 	@:allow(h3d.scene.Scene)
 	var hitPoint = new h3d.Vector();
@@ -118,8 +129,11 @@ class Interactive extends Object implements hxd.SceneEvents.Interactive {
 		case ERelease:
 			if( enableRightButton || e.button == 0 ) {
 				onRelease(e);
-				if( mouseDownButton == e.button )
+				var frame = hxd.Timer.frameCount;
+				if( mouseDownButton == e.button && (lastClickFrame != frame || allowMultiClick) ) {
 					onClick(e);
+					lastClickFrame = frame;
+				}
 			}
 			mouseDownButton = -1;
 		case EReleaseOutside: