diff --git a/Assets/Impossible Odds/MouseEvents/Documentation.pdf b/Assets/Impossible Odds/MouseEvents/Documentation.pdf
index f209919..47263d2 100644
Binary files a/Assets/Impossible Odds/MouseEvents/Documentation.pdf and b/Assets/Impossible Odds/MouseEvents/Documentation.pdf differ
diff --git a/Assets/Impossible Odds/MouseEvents/Runtime/MouseButtonEvent.cs b/Assets/Impossible Odds/MouseEvents/Runtime/MouseButtonEvent.cs
index b4c0484..b82a0d1 100644
--- a/Assets/Impossible Odds/MouseEvents/Runtime/MouseButtonEvent.cs
+++ b/Assets/Impossible Odds/MouseEvents/Runtime/MouseButtonEvent.cs
@@ -160,7 +160,7 @@ public bool IsDrag
public bool IsSingleClick => buttonState == MouseButtonEventType.SingleClick;
///
- /// Is this event a double-click event?
+ /// Is this event a double click event?
///
public bool IsDoubleClick => buttonState == MouseButtonEventType.DoubleClick;
diff --git a/Assets/Impossible Odds/MouseEvents/Runtime/MouseButtonEventType.cs b/Assets/Impossible Odds/MouseEvents/Runtime/MouseButtonEventType.cs
index 649b424..f7e68d9 100644
--- a/Assets/Impossible Odds/MouseEvents/Runtime/MouseButtonEventType.cs
+++ b/Assets/Impossible Odds/MouseEvents/Runtime/MouseButtonEventType.cs
@@ -3,36 +3,40 @@
///
/// States a mouse button can reside in.
///
- public enum MouseButtonEventType : int
+ public enum MouseButtonEventType
{
///
/// No current event of interest has happened.
///
- None = 0,
+ None,
///
/// When the mouse button performed a single click, but is waiting for a follow-up action.
///
- SingleClickPending = 1,
+ SingleClickPending,
///
/// When the mouse button performed a single click.
///
- SingleClick = 2,
+ SingleClick,
///
/// When the mouse button performed a double click.
///
- DoubleClick = 3,
+ DoubleClick,
+ ///
+ /// When the mouse button is being dragged, but the threshold for a drag action has not been met yet.
+ ///
+ DragPending,
///
/// When the mouse button is being used to initiate a drag action.
///
- DragStart = 4,
+ DragStart,
///
/// When the mouse button is being used for dragging.
///
- Dragging = 5,
+ Dragging,
///
/// When the mouse button completed a drag action.
///
- DragComplete = 6,
+ DragComplete,
Idle = None
}
diff --git a/Assets/Impossible Odds/MouseEvents/Runtime/MouseButtonStateTracker.cs b/Assets/Impossible Odds/MouseEvents/Runtime/MouseButtonStateTracker.cs
index 9c973c9..d58791b 100644
--- a/Assets/Impossible Odds/MouseEvents/Runtime/MouseButtonStateTracker.cs
+++ b/Assets/Impossible Odds/MouseEvents/Runtime/MouseButtonStateTracker.cs
@@ -8,7 +8,8 @@ public class MouseButtonStateTracker
public event Action onStateUpdated;
private readonly MouseButton button;
- private readonly Func multiClickTimeThreshold = null;
+ private readonly Func multiClickTimeThreshold;
+ private readonly Func dragDistanceThreshold;
private MouseButtonEventType state = MouseButtonEventType.None;
private EventModifiers lastModifiers = EventModifiers.None;
@@ -42,10 +43,11 @@ public class MouseButtonStateTracker
///
public Vector2 MousePosition => mousePosition;
- public MouseButtonStateTracker(MouseButton button, Func multiClickTimeThreshold)
+ public MouseButtonStateTracker(MouseButton button, Func multiClickTimeThreshold, Func dragDistanceThreshold)
{
this.button = button;
this.multiClickTimeThreshold = multiClickTimeThreshold;
+ this.dragDistanceThreshold = dragDistanceThreshold;
ClearState();
}
@@ -95,7 +97,7 @@ internal void ProcessEvent(Event mouseEvent)
internal void Suspend(Event mouseEvent)
{
// If the button doesn't match, don't bother.
- if ((MouseButton)mouseEvent.button != (MouseButton)button)
+ if (mouseEvent.button != button)
{
return;
}
@@ -128,6 +130,7 @@ private void ProcessMouseUpEvent(Event mouseEvent)
switch (state)
{
case MouseButtonEventType.None:
+ case MouseButtonEventType.DragPending:
state = MouseButtonEventType.SingleClickPending;
lastModifiers = mouseEvent.modifiers;
mousePosition = mouseEvent.mousePosition;
@@ -163,19 +166,29 @@ private void ProcessMouseDragEvent(Event mouseEvent)
return;
}
- // If a single click was still pending,
- // then perform the click before getting to the drag operation.
+ // If a single click was still pending, then perform the click before getting to the drag operation.
if (state == MouseButtonEventType.SingleClickPending)
{
state = MouseButtonEventType.SingleClick;
lastClickAction = 0f;
}
- else if ((state != MouseButtonEventType.DragStart) && (state != MouseButtonEventType.Dragging))
+ else if ((state != MouseButtonEventType.DragPending) &&
+ (state != MouseButtonEventType.DragStart) &&
+ (state != MouseButtonEventType.Dragging))
{
- state = MouseButtonEventType.DragStart; // The first of such events initiates the drag start.
+ state = MouseButtonEventType.DragPending; // The first of such events declares that drag is pending, until the drag threshold is exceeded.
dragStartPosition = mouseEvent.mousePosition;
mousePosition = mouseEvent.mousePosition;
}
+ else if (state == MouseButtonEventType.DragPending)
+ {
+ if (Vector2.Distance(mouseEvent.mousePosition, dragStartPosition) > dragDistanceThreshold())
+ {
+ state = MouseButtonEventType.DragStart; // The first of such events initiates the drag start.
+ }
+
+ mousePosition = mouseEvent.mousePosition;
+ }
else
{
state = MouseButtonEventType.Dragging;
diff --git a/Assets/Impossible Odds/MouseEvents/Runtime/MouseEventMonitor.cs b/Assets/Impossible Odds/MouseEvents/Runtime/MouseEventMonitor.cs
index 00a6d39..69fed98 100644
--- a/Assets/Impossible Odds/MouseEvents/Runtime/MouseEventMonitor.cs
+++ b/Assets/Impossible Odds/MouseEvents/Runtime/MouseEventMonitor.cs
@@ -43,6 +43,8 @@ public class MouseEventMonitor : MonoBehaviour
private List monitoredButtons = new List();
[SerializeField, Tooltip("How long (in seconds) should it wait for registering a multi-click event?"), Range(0.1f, 1f)]
private float multiClickTimeThreshold = 0.3f;
+ [SerializeField, Tooltip("How far can the mouse move (in pixels) before it is considered a drag movement?"), Range(0, 50)]
+ private float dragDistanceThreshold = 0f;
[SerializeField, Tooltip("When the cursor is over UI, should the mouse event monitor suspend operations?")]
private bool suspendWhenOverUI;
[SerializeField, Tooltip("Should the cursor coordinates be reported in pixel coordinates (as reported by Input.mousePosition), or in GUI coordinates (as reported by OnGUI events)?")]
@@ -74,6 +76,23 @@ public float MultiClickTimeThreshold
}
}
+ ///
+ /// How far can the mouse cursor be dragged (in pixels) before it registers the start of a drag operation?
+ ///
+ public float DragDistanceThreshold
+ {
+ get => dragDistanceThreshold;
+ set
+ {
+ if (value < 0f)
+ {
+ throw new ArgumentOutOfRangeException(nameof(value), "The drag distance threshold should be greater than or equal to 0.");
+ }
+
+ dragDistanceThreshold = value;
+ }
+ }
+
///
/// When the cursor is over UI, should the mouse event monitor suspend operations?
///
@@ -160,12 +179,17 @@ public void StartMonitoring(MouseButton mouseButton)
monitoredButtons.Add(mouseButton);
- if (enabled)
+ if (!enabled)
{
- MouseButtonStateTracker stateTracker = new MouseButtonStateTracker(mouseButton, () => multiClickTimeThreshold);
- stateTrackers[mouseButton] = stateTracker;
- stateTracker.onStateUpdated += OnMouseKeyStateUpdate;
+ return;
}
+
+ MouseButtonStateTracker stateTracker = new MouseButtonStateTracker(
+ mouseButton,
+ () => multiClickTimeThreshold,
+ () => dragDistanceThreshold);
+ stateTrackers[mouseButton] = stateTracker;
+ stateTracker.onStateUpdated += OnMouseKeyStateUpdate;
}
///
@@ -185,7 +209,10 @@ private void OnEnable()
{
foreach (MouseButton key in monitoredButtons)
{
- MouseButtonStateTracker state = new MouseButtonStateTracker(key, () => multiClickTimeThreshold);
+ MouseButtonStateTracker state = new MouseButtonStateTracker(
+ key,
+ () => multiClickTimeThreshold,
+ () => dragDistanceThreshold);
stateTrackers[key] = state;
state.onStateUpdated += OnMouseKeyStateUpdate;
}
diff --git a/Assets/Impossible Odds/MouseEvents/Samples/MouseEventsDemo.cs b/Assets/Impossible Odds/MouseEvents/Samples/MouseEventsDemo.cs
index 52e41e6..22071ab 100644
--- a/Assets/Impossible Odds/MouseEvents/Samples/MouseEventsDemo.cs
+++ b/Assets/Impossible Odds/MouseEvents/Samples/MouseEventsDemo.cs
@@ -87,6 +87,11 @@ private void OnMouseEvent(MouseButtonEvent mouseEvent)
break;
}
+ if (display != null)
+ {
+ Debug.Log(display.text);
+ }
+
// The dragging event is not send out each frame if there's not mouse movement.
// So don't clear it when this state is detected.
if (!mouseEvent.IsDragging && (display != null))
diff --git a/Assets/Impossible Odds/MouseEvents/Samples/MouseEventsDemo.unity b/Assets/Impossible Odds/MouseEvents/Samples/MouseEventsDemo.unity
index 5ce585f..037e26e 100644
--- a/Assets/Impossible Odds/MouseEvents/Samples/MouseEventsDemo.unity
+++ b/Assets/Impossible Odds/MouseEvents/Samples/MouseEventsDemo.unity
@@ -1747,6 +1747,7 @@ MonoBehaviour:
m_EditorClassIdentifier:
monitoredButtons: 000000000200000001000000
multiClickTimeThreshold: 0.3
+ dragDistanceThreshold: 0
suspendWhenOverUI: 1
cursorPositionInPixelCoordinates: 1
--- !u!1 &1158115896
@@ -1973,7 +1974,7 @@ Camera:
m_Enabled: 1
serializedVersion: 2
m_ClearFlags: 2
- m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
+ m_BackGroundColor: {r: 0.35, g: 0.35, b: 0.35, a: 1}
m_projectionMatrixMode: 1
m_GateFitMode: 2
m_FOVAxisMode: 0
diff --git a/Assets/Impossible Odds/MouseEvents/package.json b/Assets/Impossible Odds/MouseEvents/package.json
index c1b3424..138d962 100644
--- a/Assets/Impossible Odds/MouseEvents/package.json
+++ b/Assets/Impossible Odds/MouseEvents/package.json
@@ -1,6 +1,6 @@
{
"name": "com.impossibleodds.mousevents",
- "version": "1.2.0",
+ "version": "1.3.0",
"displayName": "Impossible Odds - Mouse Events",
"unity": "2019.4",
"documentationUrl": "https://github.com/juniordiscart/ImpossibleOdds-MouseEvents/blob/master/README.md",
diff --git a/Docs/Images/Demo_MouseEventMonitor.png b/Docs/Images/Demo_MouseEventMonitor.png
index 7d17dd3..f663c15 100644
Binary files a/Docs/Images/Demo_MouseEventMonitor.png and b/Docs/Images/Demo_MouseEventMonitor.png differ
diff --git a/README.md b/README.md
index e6333fe..e0a742e 100644
--- a/README.md
+++ b/README.md
@@ -36,7 +36,7 @@ Additionally, you can also query the state of a specific mouse button on the mou
## Advanced
-The main point of entry is the `MouseEventMonitor` script. It requires to be placed on a game object in your scene and will monitor the mouse inputs you set it up to be: left, right and/or middle mouse buttons. Apart from which mouse buttons it should monitor, you can also adjust the time threshold for registering multi-clicks (double click). Unity does not allow to transparently distinguish between single click and double click without always invoking the single click event. This multi-click time threshold is the time limit it will delay a single click event while listening in for a secondary click or other event.
+The main point of entry is the `MouseEventMonitor` script. It requires to be placed on a game object in your scene and will monitor the mouse inputs you set it up to be: left, right and/or middle mouse buttons. Apart from which mouse buttons it should monitor, you can also adjust the time threshold for registering multi-clicks (double click). Unity does not allow to transparently distinguish between single click and double click without always invoking the single click event. This multi-click time threshold is the time limit it will delay a single click event while listening in for a secondary click or other event. Additionally, you can also set a drag distance threshold for when you want to let small or accidental drag operations to still count as a click event instead.
You can listen for events of the registered mouse buttons as well as querying the current state of a particular button using the `CurrentEvent` method. When a new mouse button requires monitoring, you can add it using the `StartMonitoring` method. Conversely, you can also stop monitoring events for a specific mouse button by calling the `StopMonitoring` method.
@@ -126,6 +126,11 @@ This package is provided under the [MIT][License] license.
* Fixed a runtime issue where clicks would be invalidated due to using Unity's built-in `Event` struct. This structure would put the event type to `Ignore` while it was actually a mouse button up/down event.
+### v1.3.0
+
+* Added a `DragDistanceThreshold` to the the `MouseEventMonitor` to allow small/accidental drag operations to still register as a click.
+* Updated the sample scene to also log the performed actions to the console.
+
[License]: ./LICENSE.md
[Changelog]: ./CHANGELOG.md
[Logo]: ./Docs/Images/ImpossibleOddsLogo.png