Initial Commit
This commit is contained in:
parent
53eb92e9af
commit
270ab7d11f
15341 changed files with 700234 additions and 0 deletions
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b3cdabf2f1e76854d8aab5930305d70d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,25 @@
|
|||
namespace UnityEngine.EventSystems
|
||||
{
|
||||
/// <summary>
|
||||
/// Event Data associated with Axis Events (Controller / Keyboard).
|
||||
/// </summary>
|
||||
public class AxisEventData : BaseEventData
|
||||
{
|
||||
/// <summary>
|
||||
/// Raw input vector associated with this event.
|
||||
/// </summary>
|
||||
public Vector2 moveVector { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// MoveDirection for this event.
|
||||
/// </summary>
|
||||
public MoveDirection moveDir { get; set; }
|
||||
|
||||
public AxisEventData(EventSystem eventSystem)
|
||||
: base(eventSystem)
|
||||
{
|
||||
moveVector = Vector2.zero;
|
||||
moveDir = MoveDirection.None;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b180fd8310805e44dbbef545d0231418
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,66 @@
|
|||
namespace UnityEngine.EventSystems
|
||||
{
|
||||
/// <summary>
|
||||
/// A class that can be used for sending simple events via the event system.
|
||||
/// </summary>
|
||||
public abstract class AbstractEventData
|
||||
{
|
||||
protected bool m_Used;
|
||||
|
||||
/// <summary>
|
||||
/// Reset the event.
|
||||
/// </summary>
|
||||
public virtual void Reset()
|
||||
{
|
||||
m_Used = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use the event.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Internally sets a flag that can be checked via used to see if further processing should happen.
|
||||
/// </remarks>
|
||||
public virtual void Use()
|
||||
{
|
||||
m_Used = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is the event used?
|
||||
/// </summary>
|
||||
public virtual bool used
|
||||
{
|
||||
get { return m_Used; }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A class that contains the base event data that is common to all event types in the new EventSystem.
|
||||
/// </summary>
|
||||
public class BaseEventData : AbstractEventData
|
||||
{
|
||||
private readonly EventSystem m_EventSystem;
|
||||
public BaseEventData(EventSystem eventSystem)
|
||||
{
|
||||
m_EventSystem = eventSystem;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// >A reference to the BaseInputModule that sent this event.
|
||||
/// </summary>
|
||||
public BaseInputModule currentInputModule
|
||||
{
|
||||
get { return m_EventSystem.currentInputModule; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The object currently considered selected by the EventSystem.
|
||||
/// </summary>
|
||||
public GameObject selectedObject
|
||||
{
|
||||
get { return m_EventSystem.currentSelectedGameObject; }
|
||||
set { m_EventSystem.SetSelectedGameObject(value, this); }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 91f495459b6e34f419ac123740d798b1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,341 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UnityEngine.EventSystems
|
||||
{
|
||||
/// <summary>
|
||||
/// Each touch event creates one of these containing all the relevant information.
|
||||
/// </summary>
|
||||
public class PointerEventData : BaseEventData
|
||||
{
|
||||
/// <summary>
|
||||
/// Input press tracking.
|
||||
/// </summary>
|
||||
public enum InputButton
|
||||
{
|
||||
/// <summary>
|
||||
/// Left button
|
||||
/// </summary>
|
||||
Left = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Right button.
|
||||
/// </summary>
|
||||
Right = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Middle button
|
||||
/// </summary>
|
||||
Middle = 2
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The state of a press for the given frame.
|
||||
/// </summary>
|
||||
public enum FramePressState
|
||||
{
|
||||
/// <summary>
|
||||
/// Button was pressed this frame.
|
||||
/// </summary>
|
||||
Pressed,
|
||||
|
||||
/// <summary>
|
||||
/// Button was released this frame.
|
||||
/// </summary>
|
||||
Released,
|
||||
|
||||
/// <summary>
|
||||
/// Button was pressed and released this frame.
|
||||
/// </summary>
|
||||
PressedAndReleased,
|
||||
|
||||
/// <summary>
|
||||
/// Same as last frame.
|
||||
/// </summary>
|
||||
NotChanged
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The object that received 'OnPointerEnter'.
|
||||
/// </summary>
|
||||
public GameObject pointerEnter { get; set; }
|
||||
|
||||
// The object that received OnPointerDown
|
||||
private GameObject m_PointerPress;
|
||||
|
||||
/// <summary>
|
||||
/// The raw GameObject for the last press event. This means that it is the 'pressed' GameObject even if it can not receive the press event itself.
|
||||
/// </summary>
|
||||
public GameObject lastPress { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The object that the press happened on even if it can not handle the press event.
|
||||
/// </summary>
|
||||
public GameObject rawPointerPress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The object that is receiving 'OnDrag'.
|
||||
/// </summary>
|
||||
public GameObject pointerDrag { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The object that should receive the 'OnPointerClick' event.
|
||||
/// </summary>
|
||||
public GameObject pointerClick { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// RaycastResult associated with the current event.
|
||||
/// </summary>
|
||||
public RaycastResult pointerCurrentRaycast { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// RaycastResult associated with the pointer press.
|
||||
/// </summary>
|
||||
public RaycastResult pointerPressRaycast { get; set; }
|
||||
|
||||
public List<GameObject> hovered = new List<GameObject>();
|
||||
|
||||
/// <summary>
|
||||
/// Is it possible to click this frame
|
||||
/// </summary>
|
||||
public bool eligibleForClick { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Id of the pointer (touch id).
|
||||
/// </summary>
|
||||
public int pointerId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current pointer position.
|
||||
/// </summary>
|
||||
public Vector2 position { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Pointer delta since last update.
|
||||
/// </summary>
|
||||
public Vector2 delta { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Position of the press.
|
||||
/// </summary>
|
||||
public Vector2 pressPosition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// World-space position where a ray cast into the screen hits something
|
||||
/// </summary>
|
||||
|
||||
[Obsolete("Use either pointerCurrentRaycast.worldPosition or pointerPressRaycast.worldPosition")]
|
||||
public Vector3 worldPosition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// World-space normal where a ray cast into the screen hits something
|
||||
/// </summary>
|
||||
[Obsolete("Use either pointerCurrentRaycast.worldNormal or pointerPressRaycast.worldNormal")]
|
||||
public Vector3 worldNormal { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The last time a click event was sent. Used for double click
|
||||
/// </summary>
|
||||
public float clickTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of clicks in a row.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// <![CDATA[
|
||||
/// using UnityEngine;
|
||||
/// using System.Collections;
|
||||
/// using UnityEngine.UI;
|
||||
/// using UnityEngine.EventSystems;// Required when using Event data.
|
||||
///
|
||||
/// public class ExampleClass : MonoBehaviour, IPointerDownHandler
|
||||
/// {
|
||||
/// public void OnPointerDown(PointerEventData eventData)
|
||||
/// {
|
||||
/// //Grab the number of consecutive clicks and assign it to an integer varible.
|
||||
/// int i = eventData.clickCount;
|
||||
/// //Display the click count.
|
||||
/// Debug.Log(i);
|
||||
/// }
|
||||
/// }
|
||||
/// ]]>
|
||||
///</code>
|
||||
/// </example>
|
||||
public int clickCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The amount of scroll since the last update.
|
||||
/// </summary>
|
||||
public Vector2 scrollDelta { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Should a drag threshold be used?
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If you do not want a drag threshold set this to false in IInitializePotentialDragHandler.OnInitializePotentialDrag.
|
||||
/// </remarks>
|
||||
public bool useDragThreshold { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Is a drag operation currently occuring.
|
||||
/// </summary>
|
||||
public bool dragging { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The EventSystems.PointerEventData.InputButton for this event.
|
||||
/// </summary>
|
||||
public InputButton button { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The amount of pressure currently applied by a touch.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the device does not report pressure, the value of this property is 1.0f.
|
||||
/// </remarks>
|
||||
/// <seealso cref="UnityEngine.UIElements.IPointerEvent" />
|
||||
public float pressure { get; set; }
|
||||
/// <summary>
|
||||
/// The pressure applied to an additional pressure-sensitive control on the stylus.
|
||||
/// </summary>
|
||||
/// <seealso cref="UnityEngine.UIElements.IPointerEvent" />
|
||||
public float tangentialPressure { get; set; }
|
||||
/// <summary>
|
||||
/// The angle of the stylus relative to the surface, in radians
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A value of 0 indicates that the stylus is parallel to the surface. A value of pi/2 indicates that it is perpendicular to the surface.
|
||||
/// </remarks>
|
||||
/// <seealso cref="UnityEngine.UIElements.IPointerEvent" />
|
||||
public float altitudeAngle { get; set; }
|
||||
/// <summary>
|
||||
/// The angle of the stylus relative to the x-axis, in radians.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A value of 0 indicates that the stylus is pointed along the x-axis of the device.
|
||||
/// </remarks>
|
||||
/// <seealso cref="UnityEngine.UIElements.IPointerEvent" />
|
||||
public float azimuthAngle { get; set; }
|
||||
/// <summary>
|
||||
/// The rotation of the stylus around its axis, in radians.
|
||||
/// </summary>
|
||||
/// <seealso cref="UnityEngine.UIElements.IPointerEvent" />
|
||||
public float twist { get; set; }
|
||||
/// <summary>
|
||||
/// An estimate of the radius of a touch.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Add `radiusVariance` to get the maximum touch radius, subtract it to get the minimum touch radius.
|
||||
/// </remarks>
|
||||
/// <seealso cref="UnityEngine.UIElements.IPointerEvent" />
|
||||
public Vector2 radius { get; set; }
|
||||
/// <summary>
|
||||
/// The accuracy of the touch radius.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Add this value to the radius to get the maximum touch radius, subtract it to get the minimum touch radius.
|
||||
/// </remarks>
|
||||
public Vector2 radiusVariance { get; set; }
|
||||
/// <seealso cref="UnityEngine.UIElements.IPointerEvent" />
|
||||
|
||||
public PointerEventData(EventSystem eventSystem) : base(eventSystem)
|
||||
{
|
||||
eligibleForClick = false;
|
||||
|
||||
pointerId = -1;
|
||||
position = Vector2.zero; // Current position of the mouse or touch event
|
||||
delta = Vector2.zero; // Delta since last update
|
||||
pressPosition = Vector2.zero; // Delta since the event started being tracked
|
||||
clickTime = 0.0f; // The last time a click event was sent out (used for double-clicks)
|
||||
clickCount = 0; // Number of clicks in a row. 2 for a double-click for example.
|
||||
|
||||
scrollDelta = Vector2.zero;
|
||||
useDragThreshold = true;
|
||||
dragging = false;
|
||||
button = InputButton.Left;
|
||||
|
||||
pressure = 0f;
|
||||
tangentialPressure = 0f;
|
||||
altitudeAngle = 0f;
|
||||
azimuthAngle = 0f;
|
||||
twist = 0f;
|
||||
radius = Vector2.zero;
|
||||
radiusVariance = Vector2.zero;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is the pointer moving.
|
||||
/// </summary>
|
||||
public bool IsPointerMoving()
|
||||
{
|
||||
return delta.sqrMagnitude > 0.0f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is scroll being used on the input device.
|
||||
/// </summary>
|
||||
public bool IsScrolling()
|
||||
{
|
||||
return scrollDelta.sqrMagnitude > 0.0f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The camera associated with the last OnPointerEnter event.
|
||||
/// </summary>
|
||||
public Camera enterEventCamera
|
||||
{
|
||||
get { return pointerCurrentRaycast.module == null ? null : pointerCurrentRaycast.module.eventCamera; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The camera associated with the last OnPointerPress event.
|
||||
/// </summary>
|
||||
public Camera pressEventCamera
|
||||
{
|
||||
get { return pointerPressRaycast.module == null ? null : pointerPressRaycast.module.eventCamera; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The GameObject that received the OnPointerDown.
|
||||
/// </summary>
|
||||
public GameObject pointerPress
|
||||
{
|
||||
get { return m_PointerPress; }
|
||||
set
|
||||
{
|
||||
if (m_PointerPress == value)
|
||||
return;
|
||||
|
||||
lastPress = m_PointerPress;
|
||||
m_PointerPress = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("<b>Position</b>: " + position);
|
||||
sb.AppendLine("<b>delta</b>: " + delta);
|
||||
sb.AppendLine("<b>eligibleForClick</b>: " + eligibleForClick);
|
||||
sb.AppendLine("<b>pointerEnter</b>: " + pointerEnter);
|
||||
sb.AppendLine("<b>pointerPress</b>: " + pointerPress);
|
||||
sb.AppendLine("<b>lastPointerPress</b>: " + lastPress);
|
||||
sb.AppendLine("<b>pointerDrag</b>: " + pointerDrag);
|
||||
sb.AppendLine("<b>Use Drag Threshold</b>: " + useDragThreshold);
|
||||
sb.AppendLine("<b>Current Raycast:</b>");
|
||||
sb.AppendLine(pointerCurrentRaycast.ToString());
|
||||
sb.AppendLine("<b>Press Raycast:</b>");
|
||||
sb.AppendLine(pointerPressRaycast.ToString());
|
||||
sb.AppendLine("<b>pressure</b>: " + pressure);
|
||||
sb.AppendLine("<b>tangentialPressure</b>: " + tangentialPressure);
|
||||
sb.AppendLine("<b>altitudeAngle</b>: " + altitudeAngle);
|
||||
sb.AppendLine("<b>azimuthAngle</b>: " + azimuthAngle);
|
||||
sb.AppendLine("<b>twist</b>: " + twist);
|
||||
sb.AppendLine("<b>radius</b>: " + radius);
|
||||
sb.AppendLine("<b>radiusVariance</b>: " + radiusVariance);
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 75df57ccb1e44c64085399277405e1ca
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
|
||||
namespace UnityEngine.EventSystems
|
||||
{
|
||||
[Flags]
|
||||
/// <summary>
|
||||
/// Enum that tracks event State.
|
||||
/// </summary>
|
||||
public enum EventHandle
|
||||
{
|
||||
Unused = 0,
|
||||
Used = 1
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: db7dd43fe1278a9459cd6036f096b91d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,398 @@
|
|||
namespace UnityEngine.EventSystems
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class that all EventSystem events inherit from.
|
||||
/// </summary>
|
||||
public interface IEventSystemHandler
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to implement if you wish to receive OnPointerMove callbacks.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Criteria for this event is implementation dependent. For example see StandAloneInputModule.
|
||||
/// </remarks>
|
||||
public interface IPointerMoveHandler : IEventSystemHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Use this callback to detect pointer move events
|
||||
/// </summary>
|
||||
void OnPointerMove(PointerEventData eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to implement if you wish to receive OnPointerEnter callbacks.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Criteria for this event is implementation dependent. For example see StandAloneInputModule.
|
||||
/// </remarks>
|
||||
public interface IPointerEnterHandler : IEventSystemHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Use this callback to detect pointer enter events
|
||||
/// </summary>
|
||||
void OnPointerEnter(PointerEventData eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to implement if you wish to receive OnPointerExit callbacks.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Criteria for this event is implementation dependent. For example see StandAloneInputModule.
|
||||
/// </remarks>
|
||||
public interface IPointerExitHandler : IEventSystemHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Use this callback to detect pointer exit events
|
||||
/// </summary>
|
||||
void OnPointerExit(PointerEventData eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to implement if you wish to receive OnPointerDown callbacks.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Criteria for this event is implementation dependent. For example see StandAloneInputModule.
|
||||
/// </remarks>
|
||||
public interface IPointerDownHandler : IEventSystemHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Use this callback to detect pointer down events.
|
||||
/// </summary>
|
||||
void OnPointerDown(PointerEventData eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to implement if you wish to receive OnPointerUp callbacks.
|
||||
/// Note: In order to receive OnPointerUp callbacks, you must also implement the EventSystems.IPointerDownHandler|IPointerDownHandler interface
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Criteria for this event is implementation dependent. For example see StandAloneInputModule.
|
||||
/// </remarks>
|
||||
public interface IPointerUpHandler : IEventSystemHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Use this callback to detect pointer up events.
|
||||
/// </summary>
|
||||
void OnPointerUp(PointerEventData eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to implement if you wish to receive OnPointerClick callbacks.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Criteria for this event is implementation dependent. For example see StandAloneInputModule.
|
||||
/// </remarks>
|
||||
/// <remarks>
|
||||
/// Use the IPointerClickHandler Interface to handle click input using OnPointerClick callbacks. Ensure an Event System exists in the Scene to allow click detection. For click detection on non-UI GameObjects, ensure a EventSystems.PhysicsRaycaster is attached to the Camera.
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// <![CDATA[
|
||||
/// using UnityEngine;
|
||||
/// using UnityEngine.EventSystems;
|
||||
///
|
||||
/// public class Example : MonoBehaviour, IPointerClickHandler
|
||||
/// {
|
||||
/// //Detect if a click occurs
|
||||
/// public void OnPointerClick(PointerEventData pointerEventData)
|
||||
/// {
|
||||
/// //Output to console the clicked GameObject's name and the following message. You can replace this with your own actions for when clicking the GameObject.
|
||||
/// Debug.Log(name + " Game Object Clicked!");
|
||||
/// }
|
||||
/// }
|
||||
/// ]]>
|
||||
///</code>
|
||||
/// </example>
|
||||
public interface IPointerClickHandler : IEventSystemHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Use this callback to detect clicks.
|
||||
/// </summary>
|
||||
void OnPointerClick(PointerEventData eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to implement if you wish to receive OnBeginDrag callbacks.
|
||||
/// Note: You need to implement IDragHandler in addition to IBeginDragHandler.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Criteria for this event is implementation dependent. For example see StandAloneInputModule.
|
||||
/// </remarks>
|
||||
public interface IBeginDragHandler : IEventSystemHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Called by a BaseInputModule before a drag is started.
|
||||
/// </summary>
|
||||
void OnBeginDrag(PointerEventData eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to implement if you wish to receive OnInitializePotentialDrag callbacks.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Criteria for this event is implementation dependent. For example see StandAloneInputModule.
|
||||
/// </remarks>
|
||||
public interface IInitializePotentialDragHandler : IEventSystemHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Called by a BaseInputModule when a drag has been found but before it is valid to begin the drag.
|
||||
/// </summary>
|
||||
void OnInitializePotentialDrag(PointerEventData eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to implement if you wish to receive OnDrag callbacks.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Criteria for this event is implementation dependent. For example see StandAloneInputModule.
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// <![CDATA[
|
||||
/// using UnityEngine;
|
||||
/// using UnityEngine.EventSystems;
|
||||
/// using UnityEngine.UI;
|
||||
///
|
||||
/// [RequireComponent(typeof(Image))]
|
||||
/// public class DragMe : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
|
||||
/// {
|
||||
/// public bool dragOnSurfaces = true;
|
||||
///
|
||||
/// private GameObject m_DraggingIcon;
|
||||
/// private RectTransform m_DraggingPlane;
|
||||
///
|
||||
/// public void OnBeginDrag(PointerEventData eventData)
|
||||
/// {
|
||||
/// var canvas = FindInParents<Canvas>(gameObject);
|
||||
/// if (canvas == null)
|
||||
/// return;
|
||||
///
|
||||
/// // We have clicked something that can be dragged.
|
||||
/// // What we want to do is create an icon for this.
|
||||
/// m_DraggingIcon = new GameObject("icon");
|
||||
///
|
||||
/// m_DraggingIcon.transform.SetParent(canvas.transform, false);
|
||||
/// m_DraggingIcon.transform.SetAsLastSibling();
|
||||
///
|
||||
/// var image = m_DraggingIcon.AddComponent<Image>();
|
||||
///
|
||||
/// image.sprite = GetComponent<Image>().sprite;
|
||||
/// image.SetNativeSize();
|
||||
///
|
||||
/// if (dragOnSurfaces)
|
||||
/// m_DraggingPlane = transform as RectTransform;
|
||||
/// else
|
||||
/// m_DraggingPlane = canvas.transform as RectTransform;
|
||||
///
|
||||
/// SetDraggedPosition(eventData);
|
||||
/// }
|
||||
///
|
||||
/// public void OnDrag(PointerEventData data)
|
||||
/// {
|
||||
/// if (m_DraggingIcon != null)
|
||||
/// SetDraggedPosition(data);
|
||||
/// }
|
||||
///
|
||||
/// private void SetDraggedPosition(PointerEventData data)
|
||||
/// {
|
||||
/// if (dragOnSurfaces && data.pointerEnter != null && data.pointerEnter.transform as RectTransform != null)
|
||||
/// m_DraggingPlane = data.pointerEnter.transform as RectTransform;
|
||||
///
|
||||
/// var rt = m_DraggingIcon.GetComponent<RectTransform>();
|
||||
/// Vector3 globalMousePos;
|
||||
/// if (RectTransformUtility.ScreenPointToWorldPointInRectangle(m_DraggingPlane, data.position, data.pressEventCamera, out globalMousePos))
|
||||
/// {
|
||||
/// rt.position = globalMousePos;
|
||||
/// rt.rotation = m_DraggingPlane.rotation;
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// public void OnEndDrag(PointerEventData eventData)
|
||||
/// {
|
||||
/// if (m_DraggingIcon != null)
|
||||
/// Destroy(m_DraggingIcon);
|
||||
/// }
|
||||
///
|
||||
/// static public T FindInParents<T>(GameObject go) where T : Component
|
||||
/// {
|
||||
/// if (go == null) return null;
|
||||
/// var comp = go.GetComponent<T>();
|
||||
///
|
||||
/// if (comp != null)
|
||||
/// return comp;
|
||||
///
|
||||
/// Transform t = go.transform.parent;
|
||||
/// while (t != null && comp == null)
|
||||
/// {
|
||||
/// comp = t.gameObject.GetComponent<T>();
|
||||
/// t = t.parent;
|
||||
/// }
|
||||
/// return comp;
|
||||
/// }
|
||||
/// }
|
||||
/// ]]>
|
||||
///</code>
|
||||
/// </example>
|
||||
public interface IDragHandler : IEventSystemHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// When dragging is occurring this will be called every time the cursor is moved.
|
||||
/// </summary>
|
||||
void OnDrag(PointerEventData eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to implement if you wish to receive OnEndDrag callbacks.
|
||||
/// Note: You need to implement IDragHandler in addition to IEndDragHandler.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Criteria for this event is implementation dependent. For example see StandAloneInputModule.
|
||||
/// </remarks>
|
||||
public interface IEndDragHandler : IEventSystemHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Called by a BaseInputModule when a drag is ended.
|
||||
/// </summary>
|
||||
void OnEndDrag(PointerEventData eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to implement if you wish to receive OnDrop callbacks.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// <![CDATA[
|
||||
/// using UnityEngine;
|
||||
/// using UnityEngine.EventSystems;
|
||||
///
|
||||
/// public class DropMe : MonoBehaviour, IDropHandler
|
||||
/// {
|
||||
/// public void OnDrop(PointerEventData data)
|
||||
/// {
|
||||
/// if (data.pointerDrag != null)
|
||||
/// {
|
||||
/// Debug.Log ("Dropped object was: " + data.pointerDrag);
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ]]>
|
||||
///</code>
|
||||
/// </example>
|
||||
/// <remarks>
|
||||
/// Criteria for this event is implementation dependent. For example see StandAloneInputModule.
|
||||
/// </remarks>
|
||||
public interface IDropHandler : IEventSystemHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Called by a BaseInputModule on a target that can accept a drop.
|
||||
/// </summary>
|
||||
void OnDrop(PointerEventData eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to implement if you wish to receive OnScroll callbacks.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Criteria for this event is implementation dependent. For example see StandAloneInputModule.
|
||||
/// </remarks>
|
||||
public interface IScrollHandler : IEventSystemHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Use this callback to detect scroll events.
|
||||
/// </summary>
|
||||
void OnScroll(PointerEventData eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to implement if you wish to receive OnUpdateSelected callbacks.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Criteria for this event is implementation dependent. For example see StandAloneInputModule.
|
||||
/// </remarks>
|
||||
public interface IUpdateSelectedHandler : IEventSystemHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Called by the EventSystem when the object associated with this EventTrigger is updated.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// <![CDATA[
|
||||
/// using UnityEngine;
|
||||
/// using UnityEngine.EventSystems;
|
||||
///
|
||||
/// public class UpdateSelectedExample : MonoBehaviour, IUpdateSelectedHandler
|
||||
/// {
|
||||
/// public void OnUpdateSelected(BaseEventData data)
|
||||
/// {
|
||||
/// Debug.Log("OnUpdateSelected called.");
|
||||
/// }
|
||||
/// }
|
||||
/// ]]>
|
||||
///</code>
|
||||
/// </example>
|
||||
void OnUpdateSelected(BaseEventData eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to implement if you wish to receive OnSelect callbacks.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Criteria for this event is implementation dependent. For example see StandAloneInputModule.
|
||||
/// </remarks>
|
||||
public interface ISelectHandler : IEventSystemHandler
|
||||
{
|
||||
void OnSelect(BaseEventData eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to implement if you wish to receive OnDeselect callbacks.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Criteria for this event is implementation dependent. For example see StandAloneInputModule.
|
||||
/// </remarks>
|
||||
public interface IDeselectHandler : IEventSystemHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Called by the EventSystem when a new object is being selected.
|
||||
/// </summary>
|
||||
void OnDeselect(BaseEventData eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to implement if you wish to receive OnMove callbacks.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Criteria for this event is implementation dependent. For example see StandAloneInputModule.
|
||||
/// </remarks>
|
||||
public interface IMoveHandler : IEventSystemHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Called by a BaseInputModule when a move event occurs.
|
||||
/// </summary>
|
||||
void OnMove(AxisEventData eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to implement if you wish to receive OnSubmit callbacks.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Criteria for this event is implementation dependent. For example see StandAloneInputModule.
|
||||
/// </remarks>
|
||||
public interface ISubmitHandler : IEventSystemHandler
|
||||
{
|
||||
void OnSubmit(BaseEventData eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to implement if you wish to receive OnCancel callbacks.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Criteria for this event is implementation dependent. For example see StandAloneInputModule.
|
||||
/// </remarks>
|
||||
public interface ICancelHandler : IEventSystemHandler
|
||||
{
|
||||
void OnCancel(BaseEventData eventData);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2359c66dee10c454c97f6aea84e3fe22
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,542 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace UnityEngine.EventSystems
|
||||
{
|
||||
[AddComponentMenu("Event/Event System")]
|
||||
[DisallowMultipleComponent]
|
||||
/// <summary>
|
||||
/// Handles input, raycasting, and sending events.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The EventSystem is responsible for processing and handling events in a Unity scene. A scene should only contain one EventSystem. The EventSystem works in conjunction with a number of modules and mostly just holds state and delegates functionality to specific, overrideable components.
|
||||
/// When the EventSystem is started it searches for any BaseInputModules attached to the same GameObject and adds them to an internal list. On update each attached module receives an UpdateModules call, where the module can modify internal state. After each module has been Updated the active module has the Process call executed.This is where custom module processing can take place.
|
||||
/// </remarks>
|
||||
public class EventSystem : UIBehaviour
|
||||
{
|
||||
private List<BaseInputModule> m_SystemInputModules = new List<BaseInputModule>();
|
||||
|
||||
private BaseInputModule m_CurrentInputModule;
|
||||
|
||||
private static List<EventSystem> m_EventSystems = new List<EventSystem>();
|
||||
|
||||
/// <summary>
|
||||
/// Return the current EventSystem.
|
||||
/// </summary>
|
||||
public static EventSystem current
|
||||
{
|
||||
get { return m_EventSystems.Count > 0 ? m_EventSystems[0] : null; }
|
||||
set
|
||||
{
|
||||
int index = m_EventSystems.IndexOf(value);
|
||||
|
||||
if (index > 0)
|
||||
{
|
||||
m_EventSystems.RemoveAt(index);
|
||||
m_EventSystems.Insert(0, value);
|
||||
}
|
||||
else if (index < 0)
|
||||
{
|
||||
Debug.LogError("Failed setting EventSystem.current to unknown EventSystem " + value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
[FormerlySerializedAs("m_Selected")]
|
||||
private GameObject m_FirstSelected;
|
||||
|
||||
[SerializeField]
|
||||
private bool m_sendNavigationEvents = true;
|
||||
|
||||
/// <summary>
|
||||
/// Should the EventSystem allow navigation events (move / submit / cancel).
|
||||
/// </summary>
|
||||
public bool sendNavigationEvents
|
||||
{
|
||||
get { return m_sendNavigationEvents; }
|
||||
set { m_sendNavigationEvents = value; }
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private int m_DragThreshold = 10;
|
||||
|
||||
/// <summary>
|
||||
/// The soft area for dragging in pixels.
|
||||
/// </summary>
|
||||
public int pixelDragThreshold
|
||||
{
|
||||
get { return m_DragThreshold; }
|
||||
set { m_DragThreshold = value; }
|
||||
}
|
||||
|
||||
private GameObject m_CurrentSelected;
|
||||
|
||||
/// <summary>
|
||||
/// The currently active EventSystems.BaseInputModule.
|
||||
/// </summary>
|
||||
public BaseInputModule currentInputModule
|
||||
{
|
||||
get { return m_CurrentInputModule; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Only one object can be selected at a time. Think: controller-selected button.
|
||||
/// </summary>
|
||||
public GameObject firstSelectedGameObject
|
||||
{
|
||||
get { return m_FirstSelected; }
|
||||
set { m_FirstSelected = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The GameObject currently considered active by the EventSystem.
|
||||
/// </summary>
|
||||
public GameObject currentSelectedGameObject
|
||||
{
|
||||
get { return m_CurrentSelected; }
|
||||
}
|
||||
|
||||
[Obsolete("lastSelectedGameObject is no longer supported")]
|
||||
public GameObject lastSelectedGameObject
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
private bool m_HasFocus = true;
|
||||
|
||||
/// <summary>
|
||||
/// Flag to say whether the EventSystem thinks it should be paused or not based upon focused state.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Used to determine inside the individual InputModules if the module should be ticked while the application doesnt have focus.
|
||||
/// </remarks>
|
||||
public bool isFocused
|
||||
{
|
||||
get { return m_HasFocus; }
|
||||
}
|
||||
|
||||
protected EventSystem()
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Recalculate the internal list of BaseInputModules.
|
||||
/// </summary>
|
||||
public void UpdateModules()
|
||||
{
|
||||
GetComponents(m_SystemInputModules);
|
||||
var systemInputModulesCount = m_SystemInputModules.Count;
|
||||
for (int i = systemInputModulesCount - 1; i >= 0; i--)
|
||||
{
|
||||
if (m_SystemInputModules[i] && m_SystemInputModules[i].IsActive())
|
||||
continue;
|
||||
|
||||
m_SystemInputModules.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
private bool m_SelectionGuard;
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the EventSystem is already in a SetSelectedGameObject.
|
||||
/// </summary>
|
||||
public bool alreadySelecting
|
||||
{
|
||||
get { return m_SelectionGuard; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the object as selected. Will send an OnDeselect the the old selected object and OnSelect to the new selected object.
|
||||
/// </summary>
|
||||
/// <param name="selected">GameObject to select.</param>
|
||||
/// <param name="pointer">Associated EventData.</param>
|
||||
public void SetSelectedGameObject(GameObject selected, BaseEventData pointer)
|
||||
{
|
||||
if (m_SelectionGuard)
|
||||
{
|
||||
Debug.LogError("Attempting to select " + selected + "while already selecting an object.");
|
||||
return;
|
||||
}
|
||||
|
||||
m_SelectionGuard = true;
|
||||
if (selected == m_CurrentSelected)
|
||||
{
|
||||
m_SelectionGuard = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Debug.Log("Selection: new (" + selected + ") old (" + m_CurrentSelected + ")");
|
||||
ExecuteEvents.Execute(m_CurrentSelected, pointer, ExecuteEvents.deselectHandler);
|
||||
m_CurrentSelected = selected;
|
||||
ExecuteEvents.Execute(m_CurrentSelected, pointer, ExecuteEvents.selectHandler);
|
||||
m_SelectionGuard = false;
|
||||
}
|
||||
|
||||
private BaseEventData m_DummyData;
|
||||
private BaseEventData baseEventDataCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_DummyData == null)
|
||||
m_DummyData = new BaseEventData(this);
|
||||
|
||||
return m_DummyData;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the object as selected. Will send an OnDeselect the the old selected object and OnSelect to the new selected object.
|
||||
/// </summary>
|
||||
/// <param name="selected">GameObject to select.</param>
|
||||
public void SetSelectedGameObject(GameObject selected)
|
||||
{
|
||||
SetSelectedGameObject(selected, baseEventDataCache);
|
||||
}
|
||||
|
||||
private static int RaycastComparer(RaycastResult lhs, RaycastResult rhs)
|
||||
{
|
||||
if (lhs.module != rhs.module)
|
||||
{
|
||||
var lhsEventCamera = lhs.module.eventCamera;
|
||||
var rhsEventCamera = rhs.module.eventCamera;
|
||||
if (lhsEventCamera != null && rhsEventCamera != null && lhsEventCamera.depth != rhsEventCamera.depth)
|
||||
{
|
||||
// need to reverse the standard compareTo
|
||||
if (lhsEventCamera.depth < rhsEventCamera.depth)
|
||||
return 1;
|
||||
if (lhsEventCamera.depth == rhsEventCamera.depth)
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (lhs.module.sortOrderPriority != rhs.module.sortOrderPriority)
|
||||
return rhs.module.sortOrderPriority.CompareTo(lhs.module.sortOrderPriority);
|
||||
|
||||
if (lhs.module.renderOrderPriority != rhs.module.renderOrderPriority)
|
||||
return rhs.module.renderOrderPriority.CompareTo(lhs.module.renderOrderPriority);
|
||||
}
|
||||
|
||||
if (lhs.sortingLayer != rhs.sortingLayer)
|
||||
{
|
||||
// Uses the layer value to properly compare the relative order of the layers.
|
||||
var rid = SortingLayer.GetLayerValueFromID(rhs.sortingLayer);
|
||||
var lid = SortingLayer.GetLayerValueFromID(lhs.sortingLayer);
|
||||
return rid.CompareTo(lid);
|
||||
}
|
||||
|
||||
if (lhs.sortingOrder != rhs.sortingOrder)
|
||||
return rhs.sortingOrder.CompareTo(lhs.sortingOrder);
|
||||
|
||||
// comparing depth only makes sense if the two raycast results have the same root canvas (case 912396)
|
||||
if (lhs.depth != rhs.depth && lhs.module.rootRaycaster == rhs.module.rootRaycaster)
|
||||
return rhs.depth.CompareTo(lhs.depth);
|
||||
|
||||
if (lhs.distance != rhs.distance)
|
||||
return lhs.distance.CompareTo(rhs.distance);
|
||||
|
||||
return lhs.index.CompareTo(rhs.index);
|
||||
}
|
||||
|
||||
private static readonly Comparison<RaycastResult> s_RaycastComparer = RaycastComparer;
|
||||
|
||||
/// <summary>
|
||||
/// Raycast into the scene using all configured BaseRaycasters.
|
||||
/// </summary>
|
||||
/// <param name="eventData">Current pointer data.</param>
|
||||
/// <param name="raycastResults">List of 'hits' to populate.</param>
|
||||
public void RaycastAll(PointerEventData eventData, List<RaycastResult> raycastResults)
|
||||
{
|
||||
raycastResults.Clear();
|
||||
var modules = RaycasterManager.GetRaycasters();
|
||||
var modulesCount = modules.Count;
|
||||
for (int i = 0; i < modulesCount; ++i)
|
||||
{
|
||||
var module = modules[i];
|
||||
if (module == null || !module.IsActive())
|
||||
continue;
|
||||
|
||||
module.Raycast(eventData, raycastResults);
|
||||
}
|
||||
|
||||
raycastResults.Sort(s_RaycastComparer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is the pointer with the given ID over an EventSystem object?
|
||||
/// </summary>
|
||||
public bool IsPointerOverGameObject()
|
||||
{
|
||||
return IsPointerOverGameObject(PointerInputModule.kMouseLeftId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is the pointer with the given ID over an EventSystem object?
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If you use IsPointerOverGameObject() without a parameter, it points to the "left mouse button" (pointerId = -1); therefore when you use IsPointerOverGameObject for touch, you should consider passing a pointerId to it
|
||||
/// Note that for touch, IsPointerOverGameObject should be used with ''OnMouseDown()'' or ''Input.GetMouseButtonDown(0)'' or ''Input.GetTouch(0).phase == TouchPhase.Began''.
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// <![CDATA[
|
||||
/// using UnityEngine;
|
||||
/// using System.Collections;
|
||||
/// using UnityEngine.EventSystems;
|
||||
///
|
||||
/// public class MouseExample : MonoBehaviour
|
||||
/// {
|
||||
/// void Update()
|
||||
/// {
|
||||
/// // Check if the left mouse button was clicked
|
||||
/// if (Input.GetMouseButtonDown(0))
|
||||
/// {
|
||||
/// // Check if the mouse was clicked over a UI element
|
||||
/// if (EventSystem.current.IsPointerOverGameObject())
|
||||
/// {
|
||||
/// Debug.Log("Clicked on the UI");
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ]]>
|
||||
///</code>
|
||||
/// </example>
|
||||
public bool IsPointerOverGameObject(int pointerId)
|
||||
{
|
||||
return m_CurrentInputModule != null && m_CurrentInputModule.IsPointerOverGameObject(pointerId);
|
||||
}
|
||||
|
||||
#if PACKAGE_UITOOLKIT
|
||||
private struct UIToolkitOverrideConfig
|
||||
{
|
||||
public EventSystem activeEventSystem;
|
||||
public bool sendEvents;
|
||||
public bool createPanelGameObjectsOnStart;
|
||||
}
|
||||
|
||||
private static UIToolkitOverrideConfig s_UIToolkitOverride = new UIToolkitOverrideConfig
|
||||
{
|
||||
activeEventSystem = null,
|
||||
sendEvents = true,
|
||||
createPanelGameObjectsOnStart = true
|
||||
};
|
||||
|
||||
private bool isUIToolkitActiveEventSystem =>
|
||||
s_UIToolkitOverride.activeEventSystem == this || s_UIToolkitOverride.activeEventSystem == null;
|
||||
|
||||
private bool sendUIToolkitEvents =>
|
||||
s_UIToolkitOverride.sendEvents && isUIToolkitActiveEventSystem;
|
||||
|
||||
private bool createUIToolkitPanelGameObjectsOnStart =>
|
||||
s_UIToolkitOverride.createPanelGameObjectsOnStart && isUIToolkitActiveEventSystem;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Sets how UI Toolkit runtime panels receive events and handle selection
|
||||
/// when interacting with other objects that use the EventSystem, such as components from the Unity UI package.
|
||||
/// </summary>
|
||||
/// <param name="activeEventSystem">
|
||||
/// The EventSystem used to override UI Toolkit panel events and selection.
|
||||
/// If activeEventSystem is null, UI Toolkit panels will use current enabled EventSystem
|
||||
/// or, if there is none, the default InputManager-based event system will be used.
|
||||
/// </param>
|
||||
/// <param name="sendEvents">
|
||||
/// If true, UI Toolkit events will come from this EventSystem
|
||||
/// instead of the default InputManager-based event system.
|
||||
/// </param>
|
||||
/// <param name="createPanelGameObjectsOnStart">
|
||||
/// If true, UI Toolkit panels' unassigned selectableGameObject will be automatically initialized
|
||||
/// with children GameObjects of this EventSystem on Start.
|
||||
/// </param>
|
||||
public static void SetUITookitEventSystemOverride(EventSystem activeEventSystem, bool sendEvents = true, bool createPanelGameObjectsOnStart = true)
|
||||
{
|
||||
#if PACKAGE_UITOOLKIT
|
||||
UIElementsRuntimeUtility.UnregisterEventSystem(UIElementsRuntimeUtility.activeEventSystem);
|
||||
|
||||
s_UIToolkitOverride = new UIToolkitOverrideConfig
|
||||
{
|
||||
activeEventSystem = activeEventSystem,
|
||||
sendEvents = sendEvents,
|
||||
createPanelGameObjectsOnStart = createPanelGameObjectsOnStart,
|
||||
};
|
||||
|
||||
if (sendEvents)
|
||||
{
|
||||
var eventSystem = activeEventSystem != null ? activeEventSystem : EventSystem.current;
|
||||
if (eventSystem.isActiveAndEnabled)
|
||||
UIElementsRuntimeUtility.RegisterEventSystem(activeEventSystem);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if PACKAGE_UITOOLKIT
|
||||
private void CreateUIToolkitPanelGameObject(BaseRuntimePanel panel)
|
||||
{
|
||||
if (panel.selectableGameObject == null)
|
||||
{
|
||||
var go = new GameObject(panel.name, typeof(PanelEventHandler), typeof(PanelRaycaster));
|
||||
go.transform.SetParent(transform);
|
||||
panel.selectableGameObject = go;
|
||||
panel.destroyed += () => Destroy(go);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
|
||||
#if PACKAGE_UITOOLKIT
|
||||
if (createUIToolkitPanelGameObjectsOnStart)
|
||||
{
|
||||
foreach (BaseRuntimePanel panel in UIElementsRuntimeUtility.GetSortedPlayerPanels())
|
||||
{
|
||||
CreateUIToolkitPanelGameObject(panel);
|
||||
}
|
||||
UIElementsRuntimeUtility.onCreatePanel += CreateUIToolkitPanelGameObject;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
protected override void OnDestroy()
|
||||
{
|
||||
#if PACKAGE_UITOOLKIT
|
||||
UIElementsRuntimeUtility.onCreatePanel -= CreateUIToolkitPanelGameObject;
|
||||
#endif
|
||||
|
||||
base.OnDestroy();
|
||||
}
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
m_EventSystems.Add(this);
|
||||
|
||||
#if PACKAGE_UITOOLKIT
|
||||
if (sendUIToolkitEvents)
|
||||
{
|
||||
UIElementsRuntimeUtility.RegisterEventSystem(this);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
#if PACKAGE_UITOOLKIT
|
||||
UIElementsRuntimeUtility.UnregisterEventSystem(this);
|
||||
#endif
|
||||
|
||||
if (m_CurrentInputModule != null)
|
||||
{
|
||||
m_CurrentInputModule.DeactivateModule();
|
||||
m_CurrentInputModule = null;
|
||||
}
|
||||
|
||||
m_EventSystems.Remove(this);
|
||||
|
||||
base.OnDisable();
|
||||
}
|
||||
|
||||
private void TickModules()
|
||||
{
|
||||
var systemInputModulesCount = m_SystemInputModules.Count;
|
||||
for (var i = 0; i < systemInputModulesCount; i++)
|
||||
{
|
||||
if (m_SystemInputModules[i] != null)
|
||||
m_SystemInputModules[i].UpdateModule();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnApplicationFocus(bool hasFocus)
|
||||
{
|
||||
m_HasFocus = hasFocus;
|
||||
if (!m_HasFocus)
|
||||
TickModules();
|
||||
}
|
||||
|
||||
protected virtual void Update()
|
||||
{
|
||||
if (current != this)
|
||||
return;
|
||||
TickModules();
|
||||
|
||||
bool changedModule = false;
|
||||
var systemInputModulesCount = m_SystemInputModules.Count;
|
||||
for (var i = 0; i < systemInputModulesCount; i++)
|
||||
{
|
||||
var module = m_SystemInputModules[i];
|
||||
if (module.IsModuleSupported() && module.ShouldActivateModule())
|
||||
{
|
||||
if (m_CurrentInputModule != module)
|
||||
{
|
||||
ChangeEventModule(module);
|
||||
changedModule = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// no event module set... set the first valid one...
|
||||
if (m_CurrentInputModule == null)
|
||||
{
|
||||
for (var i = 0; i < systemInputModulesCount; i++)
|
||||
{
|
||||
var module = m_SystemInputModules[i];
|
||||
if (module.IsModuleSupported())
|
||||
{
|
||||
ChangeEventModule(module);
|
||||
changedModule = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!changedModule && m_CurrentInputModule != null)
|
||||
m_CurrentInputModule.Process();
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
int eventSystemCount = 0;
|
||||
for (int i = 0; i < m_EventSystems.Count; i++)
|
||||
{
|
||||
if (m_EventSystems[i].GetType() == typeof(EventSystem))
|
||||
eventSystemCount++;
|
||||
}
|
||||
|
||||
if (eventSystemCount > 1)
|
||||
Debug.LogWarning("There are " + eventSystemCount + " event systems in the scene. Please ensure there is always exactly one event system in the scene");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private void ChangeEventModule(BaseInputModule module)
|
||||
{
|
||||
if (m_CurrentInputModule == module)
|
||||
return;
|
||||
|
||||
if (m_CurrentInputModule != null)
|
||||
m_CurrentInputModule.DeactivateModule();
|
||||
|
||||
if (module != null)
|
||||
module.ActivateModule();
|
||||
m_CurrentInputModule = module;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("<b>Selected:</b>" + currentSelectedGameObject);
|
||||
sb.AppendLine();
|
||||
sb.AppendLine();
|
||||
sb.AppendLine(m_CurrentInputModule != null ? m_CurrentInputModule.ToString() : "No module");
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 76c392e42b5098c458856cdf6ecaaaa1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,360 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace UnityEngine.EventSystems
|
||||
{
|
||||
[AddComponentMenu("Event/Event Trigger")]
|
||||
/// <summary>
|
||||
/// Receives events from the EventSystem and calls registered functions for each event.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The EventTrigger can be used to specify functions you wish to be called for each EventSystem event.
|
||||
/// You can assign multiple functions to a single event and whenever the EventTrigger receives that event it will call those functions in the order they were provided.
|
||||
///
|
||||
/// NOTE: Attaching this component to a GameObject will make that object intercept ALL events, and no events will propagate to parent objects.
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// There are two ways to intercept events: You could extend EventTrigger, and override the functions for the events you are interested in intercepting; as shown in this example:
|
||||
/// <code>
|
||||
/// <![CDATA[
|
||||
/// using UnityEngine;
|
||||
/// using UnityEngine.EventSystems;
|
||||
///
|
||||
/// public class EventTriggerExample : EventTrigger
|
||||
/// {
|
||||
/// public override void OnBeginDrag(PointerEventData data)
|
||||
/// {
|
||||
/// Debug.Log("OnBeginDrag called.");
|
||||
/// }
|
||||
///
|
||||
/// public override void OnCancel(BaseEventData data)
|
||||
/// {
|
||||
/// Debug.Log("OnCancel called.");
|
||||
/// }
|
||||
///
|
||||
/// public override void OnDeselect(BaseEventData data)
|
||||
/// {
|
||||
/// Debug.Log("OnDeselect called.");
|
||||
/// }
|
||||
///
|
||||
/// public override void OnDrag(PointerEventData data)
|
||||
/// {
|
||||
/// Debug.Log("OnDrag called.");
|
||||
/// }
|
||||
///
|
||||
/// public override void OnDrop(PointerEventData data)
|
||||
/// {
|
||||
/// Debug.Log("OnDrop called.");
|
||||
/// }
|
||||
///
|
||||
/// public override void OnEndDrag(PointerEventData data)
|
||||
/// {
|
||||
/// Debug.Log("OnEndDrag called.");
|
||||
/// }
|
||||
///
|
||||
/// public override void OnInitializePotentialDrag(PointerEventData data)
|
||||
/// {
|
||||
/// Debug.Log("OnInitializePotentialDrag called.");
|
||||
/// }
|
||||
///
|
||||
/// public override void OnMove(AxisEventData data)
|
||||
/// {
|
||||
/// Debug.Log("OnMove called.");
|
||||
/// }
|
||||
///
|
||||
/// public override void OnPointerClick(PointerEventData data)
|
||||
/// {
|
||||
/// Debug.Log("OnPointerClick called.");
|
||||
/// }
|
||||
///
|
||||
/// public override void OnPointerDown(PointerEventData data)
|
||||
/// {
|
||||
/// Debug.Log("OnPointerDown called.");
|
||||
/// }
|
||||
///
|
||||
/// public override void OnPointerEnter(PointerEventData data)
|
||||
/// {
|
||||
/// Debug.Log("OnPointerEnter called.");
|
||||
/// }
|
||||
///
|
||||
/// public override void OnPointerExit(PointerEventData data)
|
||||
/// {
|
||||
/// Debug.Log("OnPointerExit called.");
|
||||
/// }
|
||||
///
|
||||
/// public override void OnPointerUp(PointerEventData data)
|
||||
/// {
|
||||
/// Debug.Log("OnPointerUp called.");
|
||||
/// }
|
||||
///
|
||||
/// public override void OnScroll(PointerEventData data)
|
||||
/// {
|
||||
/// Debug.Log("OnScroll called.");
|
||||
/// }
|
||||
///
|
||||
/// public override void OnSelect(BaseEventData data)
|
||||
/// {
|
||||
/// Debug.Log("OnSelect called.");
|
||||
/// }
|
||||
///
|
||||
/// public override void OnSubmit(BaseEventData data)
|
||||
/// {
|
||||
/// Debug.Log("OnSubmit called.");
|
||||
/// }
|
||||
///
|
||||
/// public override void OnUpdateSelected(BaseEventData data)
|
||||
/// {
|
||||
/// Debug.Log("OnUpdateSelected called.");
|
||||
/// }
|
||||
/// }
|
||||
/// ]]>
|
||||
///</code>
|
||||
/// or you can specify individual delegates:
|
||||
/// <code>
|
||||
/// <![CDATA[
|
||||
/// using UnityEngine;
|
||||
/// using UnityEngine.EventSystems;
|
||||
///
|
||||
///
|
||||
/// public class EventTriggerDelegateExample : MonoBehaviour
|
||||
/// {
|
||||
/// void Start()
|
||||
/// {
|
||||
/// EventTrigger trigger = GetComponent<EventTrigger>();
|
||||
/// EventTrigger.Entry entry = new EventTrigger.Entry();
|
||||
/// entry.eventID = EventTriggerType.PointerDown;
|
||||
/// entry.callback.AddListener((data) => { OnPointerDownDelegate((PointerEventData)data); });
|
||||
/// trigger.triggers.Add(entry);
|
||||
/// }
|
||||
///
|
||||
/// public void OnPointerDownDelegate(PointerEventData data)
|
||||
/// {
|
||||
/// Debug.Log("OnPointerDownDelegate called.");
|
||||
/// }
|
||||
/// }
|
||||
/// ]]>
|
||||
///</code>
|
||||
/// </example>
|
||||
public class EventTrigger :
|
||||
MonoBehaviour,
|
||||
IPointerEnterHandler,
|
||||
IPointerExitHandler,
|
||||
IPointerDownHandler,
|
||||
IPointerUpHandler,
|
||||
IPointerClickHandler,
|
||||
IInitializePotentialDragHandler,
|
||||
IBeginDragHandler,
|
||||
IDragHandler,
|
||||
IEndDragHandler,
|
||||
IDropHandler,
|
||||
IScrollHandler,
|
||||
IUpdateSelectedHandler,
|
||||
ISelectHandler,
|
||||
IDeselectHandler,
|
||||
IMoveHandler,
|
||||
ISubmitHandler,
|
||||
ICancelHandler
|
||||
{
|
||||
[Serializable]
|
||||
/// <summary>
|
||||
/// UnityEvent class for Triggers.
|
||||
/// </summary>
|
||||
public class TriggerEvent : UnityEvent<BaseEventData>
|
||||
{}
|
||||
|
||||
[Serializable]
|
||||
/// <summary>
|
||||
/// An Entry in the EventSystem delegates list.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// It stores the callback and which event type should this callback be fired.
|
||||
/// </remarks>
|
||||
public class Entry
|
||||
{
|
||||
/// <summary>
|
||||
/// What type of event is the associated callback listening for.
|
||||
/// </summary>
|
||||
public EventTriggerType eventID = EventTriggerType.PointerClick;
|
||||
|
||||
/// <summary>
|
||||
/// The desired TriggerEvent to be Invoked.
|
||||
/// </summary>
|
||||
public TriggerEvent callback = new TriggerEvent();
|
||||
}
|
||||
|
||||
[FormerlySerializedAs("delegates")]
|
||||
[SerializeField]
|
||||
private List<Entry> m_Delegates;
|
||||
|
||||
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
|
||||
[Obsolete("Please use triggers instead (UnityUpgradable) -> triggers", true)]
|
||||
public List<Entry> delegates { get { return triggers; } set { triggers = value; } }
|
||||
|
||||
protected EventTrigger()
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// All the functions registered in this EventTrigger
|
||||
/// </summary>
|
||||
public List<Entry> triggers
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_Delegates == null)
|
||||
m_Delegates = new List<Entry>();
|
||||
return m_Delegates;
|
||||
}
|
||||
set { m_Delegates = value; }
|
||||
}
|
||||
|
||||
private void Execute(EventTriggerType id, BaseEventData eventData)
|
||||
{
|
||||
var triggerCount = triggers.Count;
|
||||
|
||||
for (int i = 0, imax = triggers.Count; i < imax; ++i)
|
||||
{
|
||||
var ent = triggers[i];
|
||||
if (ent.eventID == id && ent.callback != null)
|
||||
ent.callback.Invoke(eventData);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by the EventSystem when the pointer enters the object associated with this EventTrigger.
|
||||
/// </summary>
|
||||
public virtual void OnPointerEnter(PointerEventData eventData)
|
||||
{
|
||||
Execute(EventTriggerType.PointerEnter, eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by the EventSystem when the pointer exits the object associated with this EventTrigger.
|
||||
/// </summary>
|
||||
public virtual void OnPointerExit(PointerEventData eventData)
|
||||
{
|
||||
Execute(EventTriggerType.PointerExit, eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by the EventSystem every time the pointer is moved during dragging.
|
||||
/// </summary>
|
||||
public virtual void OnDrag(PointerEventData eventData)
|
||||
{
|
||||
Execute(EventTriggerType.Drag, eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by the EventSystem when an object accepts a drop.
|
||||
/// </summary>
|
||||
public virtual void OnDrop(PointerEventData eventData)
|
||||
{
|
||||
Execute(EventTriggerType.Drop, eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by the EventSystem when a PointerDown event occurs.
|
||||
/// </summary>
|
||||
public virtual void OnPointerDown(PointerEventData eventData)
|
||||
{
|
||||
Execute(EventTriggerType.PointerDown, eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by the EventSystem when a PointerUp event occurs.
|
||||
/// </summary>
|
||||
public virtual void OnPointerUp(PointerEventData eventData)
|
||||
{
|
||||
Execute(EventTriggerType.PointerUp, eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by the EventSystem when a Click event occurs.
|
||||
/// </summary>
|
||||
public virtual void OnPointerClick(PointerEventData eventData)
|
||||
{
|
||||
Execute(EventTriggerType.PointerClick, eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by the EventSystem when a Select event occurs.
|
||||
/// </summary>
|
||||
public virtual void OnSelect(BaseEventData eventData)
|
||||
{
|
||||
Execute(EventTriggerType.Select, eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by the EventSystem when a new object is being selected.
|
||||
/// </summary>
|
||||
public virtual void OnDeselect(BaseEventData eventData)
|
||||
{
|
||||
Execute(EventTriggerType.Deselect, eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by the EventSystem when a new Scroll event occurs.
|
||||
/// </summary>
|
||||
public virtual void OnScroll(PointerEventData eventData)
|
||||
{
|
||||
Execute(EventTriggerType.Scroll, eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by the EventSystem when a Move event occurs.
|
||||
/// </summary>
|
||||
public virtual void OnMove(AxisEventData eventData)
|
||||
{
|
||||
Execute(EventTriggerType.Move, eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by the EventSystem when the object associated with this EventTrigger is updated.
|
||||
/// </summary>
|
||||
public virtual void OnUpdateSelected(BaseEventData eventData)
|
||||
{
|
||||
Execute(EventTriggerType.UpdateSelected, eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by the EventSystem when a drag has been found, but before it is valid to begin the drag.
|
||||
/// </summary>
|
||||
public virtual void OnInitializePotentialDrag(PointerEventData eventData)
|
||||
{
|
||||
Execute(EventTriggerType.InitializePotentialDrag, eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called before a drag is started.
|
||||
/// </summary>
|
||||
public virtual void OnBeginDrag(PointerEventData eventData)
|
||||
{
|
||||
Execute(EventTriggerType.BeginDrag, eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by the EventSystem once dragging ends.
|
||||
/// </summary>
|
||||
public virtual void OnEndDrag(PointerEventData eventData)
|
||||
{
|
||||
Execute(EventTriggerType.EndDrag, eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by the EventSystem when a Submit event occurs.
|
||||
/// </summary>
|
||||
public virtual void OnSubmit(BaseEventData eventData)
|
||||
{
|
||||
Execute(EventTriggerType.Submit, eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by the EventSystem when a Cancel event occurs.
|
||||
/// </summary>
|
||||
public virtual void OnCancel(BaseEventData eventData)
|
||||
{
|
||||
Execute(EventTriggerType.Cancel, eventData);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d0b148fe25e99eb48b9724523833bab1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,96 @@
|
|||
namespace UnityEngine.EventSystems
|
||||
{
|
||||
/// <summary>
|
||||
/// This class is capable of triggering one or more remote functions from a specified event.
|
||||
/// Usage: Attach it to an object with a collider, or to a GUI Graphic of your choice.
|
||||
/// NOTE: Doing this will make this object intercept ALL events, and no event bubbling will occur from this object!
|
||||
/// </summary>
|
||||
|
||||
public enum EventTriggerType
|
||||
{
|
||||
/// <summary>
|
||||
/// Intercepts a IPointerEnterHandler.OnPointerEnter.
|
||||
/// </summary>
|
||||
PointerEnter = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Intercepts a IPointerExitHandler.OnPointerExit.
|
||||
/// </summary>
|
||||
PointerExit = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Intercepts a IPointerDownHandler.OnPointerDown.
|
||||
/// </summary>
|
||||
PointerDown = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Intercepts a IPointerUpHandler.OnPointerUp.
|
||||
/// </summary>
|
||||
PointerUp = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Intercepts a IPointerClickHandler.OnPointerClick.
|
||||
/// </summary>
|
||||
PointerClick = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Intercepts a IDragHandler.OnDrag.
|
||||
/// </summary>
|
||||
Drag = 5,
|
||||
|
||||
/// <summary>
|
||||
/// Intercepts a IDropHandler.OnDrop.
|
||||
/// </summary>
|
||||
Drop = 6,
|
||||
|
||||
/// <summary>
|
||||
/// Intercepts a IScrollHandler.OnScroll.
|
||||
/// </summary>
|
||||
Scroll = 7,
|
||||
|
||||
/// <summary>
|
||||
/// Intercepts a IUpdateSelectedHandler.OnUpdateSelected.
|
||||
/// </summary>
|
||||
UpdateSelected = 8,
|
||||
|
||||
/// <summary>
|
||||
/// Intercepts a ISelectHandler.OnSelect.
|
||||
/// </summary>
|
||||
Select = 9,
|
||||
|
||||
/// <summary>
|
||||
/// Intercepts a IDeselectHandler.OnDeselect.
|
||||
/// </summary>
|
||||
Deselect = 10,
|
||||
|
||||
/// <summary>
|
||||
/// Intercepts a IMoveHandler.OnMove.
|
||||
/// </summary>
|
||||
Move = 11,
|
||||
|
||||
/// <summary>
|
||||
/// Intercepts IInitializePotentialDrag.InitializePotentialDrag.
|
||||
/// </summary>
|
||||
InitializePotentialDrag = 12,
|
||||
|
||||
/// <summary>
|
||||
/// Intercepts IBeginDragHandler.OnBeginDrag.
|
||||
/// </summary>
|
||||
BeginDrag = 13,
|
||||
|
||||
/// <summary>
|
||||
/// Intercepts IEndDragHandler.OnEndDrag.
|
||||
/// </summary>
|
||||
EndDrag = 14,
|
||||
|
||||
/// <summary>
|
||||
/// Intercepts ISubmitHandler.Submit.
|
||||
/// </summary>
|
||||
Submit = 15,
|
||||
|
||||
/// <summary>
|
||||
/// Intercepts ICancelHandler.OnCancel.
|
||||
/// </summary>
|
||||
Cancel = 16
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3fa274f26b1574c40b949e114327022e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,374 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.Pool;
|
||||
|
||||
namespace UnityEngine.EventSystems
|
||||
{
|
||||
public static class ExecuteEvents
|
||||
{
|
||||
public delegate void EventFunction<T1>(T1 handler, BaseEventData eventData);
|
||||
|
||||
public static T ValidateEventData<T>(BaseEventData data) where T : class
|
||||
{
|
||||
if ((data as T) == null)
|
||||
throw new ArgumentException(String.Format("Invalid type: {0} passed to event expecting {1}", data.GetType(), typeof(T)));
|
||||
return data as T;
|
||||
}
|
||||
|
||||
private static readonly EventFunction<IPointerMoveHandler> s_PointerMoveHandler = Execute;
|
||||
|
||||
private static void Execute(IPointerMoveHandler handler, BaseEventData eventData)
|
||||
{
|
||||
handler.OnPointerMove(ValidateEventData<PointerEventData>(eventData));
|
||||
}
|
||||
|
||||
private static readonly EventFunction<IPointerEnterHandler> s_PointerEnterHandler = Execute;
|
||||
|
||||
private static void Execute(IPointerEnterHandler handler, BaseEventData eventData)
|
||||
{
|
||||
handler.OnPointerEnter(ValidateEventData<PointerEventData>(eventData));
|
||||
}
|
||||
|
||||
private static readonly EventFunction<IPointerExitHandler> s_PointerExitHandler = Execute;
|
||||
|
||||
private static void Execute(IPointerExitHandler handler, BaseEventData eventData)
|
||||
{
|
||||
handler.OnPointerExit(ValidateEventData<PointerEventData>(eventData));
|
||||
}
|
||||
|
||||
private static readonly EventFunction<IPointerDownHandler> s_PointerDownHandler = Execute;
|
||||
|
||||
private static void Execute(IPointerDownHandler handler, BaseEventData eventData)
|
||||
{
|
||||
handler.OnPointerDown(ValidateEventData<PointerEventData>(eventData));
|
||||
}
|
||||
|
||||
private static readonly EventFunction<IPointerUpHandler> s_PointerUpHandler = Execute;
|
||||
|
||||
private static void Execute(IPointerUpHandler handler, BaseEventData eventData)
|
||||
{
|
||||
handler.OnPointerUp(ValidateEventData<PointerEventData>(eventData));
|
||||
}
|
||||
|
||||
private static readonly EventFunction<IPointerClickHandler> s_PointerClickHandler = Execute;
|
||||
|
||||
private static void Execute(IPointerClickHandler handler, BaseEventData eventData)
|
||||
{
|
||||
handler.OnPointerClick(ValidateEventData<PointerEventData>(eventData));
|
||||
}
|
||||
|
||||
private static readonly EventFunction<IInitializePotentialDragHandler> s_InitializePotentialDragHandler = Execute;
|
||||
|
||||
private static void Execute(IInitializePotentialDragHandler handler, BaseEventData eventData)
|
||||
{
|
||||
handler.OnInitializePotentialDrag(ValidateEventData<PointerEventData>(eventData));
|
||||
}
|
||||
|
||||
private static readonly EventFunction<IBeginDragHandler> s_BeginDragHandler = Execute;
|
||||
|
||||
private static void Execute(IBeginDragHandler handler, BaseEventData eventData)
|
||||
{
|
||||
handler.OnBeginDrag(ValidateEventData<PointerEventData>(eventData));
|
||||
}
|
||||
|
||||
private static readonly EventFunction<IDragHandler> s_DragHandler = Execute;
|
||||
|
||||
private static void Execute(IDragHandler handler, BaseEventData eventData)
|
||||
{
|
||||
handler.OnDrag(ValidateEventData<PointerEventData>(eventData));
|
||||
}
|
||||
|
||||
private static readonly EventFunction<IEndDragHandler> s_EndDragHandler = Execute;
|
||||
|
||||
private static void Execute(IEndDragHandler handler, BaseEventData eventData)
|
||||
{
|
||||
handler.OnEndDrag(ValidateEventData<PointerEventData>(eventData));
|
||||
}
|
||||
|
||||
private static readonly EventFunction<IDropHandler> s_DropHandler = Execute;
|
||||
|
||||
private static void Execute(IDropHandler handler, BaseEventData eventData)
|
||||
{
|
||||
handler.OnDrop(ValidateEventData<PointerEventData>(eventData));
|
||||
}
|
||||
|
||||
private static readonly EventFunction<IScrollHandler> s_ScrollHandler = Execute;
|
||||
|
||||
private static void Execute(IScrollHandler handler, BaseEventData eventData)
|
||||
{
|
||||
handler.OnScroll(ValidateEventData<PointerEventData>(eventData));
|
||||
}
|
||||
|
||||
private static readonly EventFunction<IUpdateSelectedHandler> s_UpdateSelectedHandler = Execute;
|
||||
|
||||
private static void Execute(IUpdateSelectedHandler handler, BaseEventData eventData)
|
||||
{
|
||||
handler.OnUpdateSelected(eventData);
|
||||
}
|
||||
|
||||
private static readonly EventFunction<ISelectHandler> s_SelectHandler = Execute;
|
||||
|
||||
private static void Execute(ISelectHandler handler, BaseEventData eventData)
|
||||
{
|
||||
handler.OnSelect(eventData);
|
||||
}
|
||||
|
||||
private static readonly EventFunction<IDeselectHandler> s_DeselectHandler = Execute;
|
||||
|
||||
private static void Execute(IDeselectHandler handler, BaseEventData eventData)
|
||||
{
|
||||
handler.OnDeselect(eventData);
|
||||
}
|
||||
|
||||
private static readonly EventFunction<IMoveHandler> s_MoveHandler = Execute;
|
||||
|
||||
private static void Execute(IMoveHandler handler, BaseEventData eventData)
|
||||
{
|
||||
handler.OnMove(ValidateEventData<AxisEventData>(eventData));
|
||||
}
|
||||
|
||||
private static readonly EventFunction<ISubmitHandler> s_SubmitHandler = Execute;
|
||||
|
||||
private static void Execute(ISubmitHandler handler, BaseEventData eventData)
|
||||
{
|
||||
handler.OnSubmit(eventData);
|
||||
}
|
||||
|
||||
private static readonly EventFunction<ICancelHandler> s_CancelHandler = Execute;
|
||||
|
||||
private static void Execute(ICancelHandler handler, BaseEventData eventData)
|
||||
{
|
||||
handler.OnCancel(eventData);
|
||||
}
|
||||
|
||||
public static EventFunction<IPointerMoveHandler> pointerMoveHandler
|
||||
{
|
||||
get { return s_PointerMoveHandler; }
|
||||
}
|
||||
|
||||
public static EventFunction<IPointerEnterHandler> pointerEnterHandler
|
||||
{
|
||||
get { return s_PointerEnterHandler; }
|
||||
}
|
||||
|
||||
public static EventFunction<IPointerExitHandler> pointerExitHandler
|
||||
{
|
||||
get { return s_PointerExitHandler; }
|
||||
}
|
||||
|
||||
public static EventFunction<IPointerDownHandler> pointerDownHandler
|
||||
{
|
||||
get { return s_PointerDownHandler; }
|
||||
}
|
||||
|
||||
public static EventFunction<IPointerUpHandler> pointerUpHandler
|
||||
{
|
||||
get { return s_PointerUpHandler; }
|
||||
}
|
||||
|
||||
public static EventFunction<IPointerClickHandler> pointerClickHandler
|
||||
{
|
||||
get { return s_PointerClickHandler; }
|
||||
}
|
||||
|
||||
public static EventFunction<IInitializePotentialDragHandler> initializePotentialDrag
|
||||
{
|
||||
get { return s_InitializePotentialDragHandler; }
|
||||
}
|
||||
|
||||
public static EventFunction<IBeginDragHandler> beginDragHandler
|
||||
{
|
||||
get { return s_BeginDragHandler; }
|
||||
}
|
||||
|
||||
public static EventFunction<IDragHandler> dragHandler
|
||||
{
|
||||
get { return s_DragHandler; }
|
||||
}
|
||||
|
||||
public static EventFunction<IEndDragHandler> endDragHandler
|
||||
{
|
||||
get { return s_EndDragHandler; }
|
||||
}
|
||||
|
||||
public static EventFunction<IDropHandler> dropHandler
|
||||
{
|
||||
get { return s_DropHandler; }
|
||||
}
|
||||
|
||||
public static EventFunction<IScrollHandler> scrollHandler
|
||||
{
|
||||
get { return s_ScrollHandler; }
|
||||
}
|
||||
|
||||
public static EventFunction<IUpdateSelectedHandler> updateSelectedHandler
|
||||
{
|
||||
get { return s_UpdateSelectedHandler; }
|
||||
}
|
||||
|
||||
public static EventFunction<ISelectHandler> selectHandler
|
||||
{
|
||||
get { return s_SelectHandler; }
|
||||
}
|
||||
|
||||
public static EventFunction<IDeselectHandler> deselectHandler
|
||||
{
|
||||
get { return s_DeselectHandler; }
|
||||
}
|
||||
|
||||
public static EventFunction<IMoveHandler> moveHandler
|
||||
{
|
||||
get { return s_MoveHandler; }
|
||||
}
|
||||
|
||||
public static EventFunction<ISubmitHandler> submitHandler
|
||||
{
|
||||
get { return s_SubmitHandler; }
|
||||
}
|
||||
|
||||
public static EventFunction<ICancelHandler> cancelHandler
|
||||
{
|
||||
get { return s_CancelHandler; }
|
||||
}
|
||||
|
||||
private static void GetEventChain(GameObject root, IList<Transform> eventChain)
|
||||
{
|
||||
eventChain.Clear();
|
||||
if (root == null)
|
||||
return;
|
||||
|
||||
var t = root.transform;
|
||||
while (t != null)
|
||||
{
|
||||
eventChain.Add(t);
|
||||
t = t.parent;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool Execute<T>(GameObject target, BaseEventData eventData, EventFunction<T> functor) where T : IEventSystemHandler
|
||||
{
|
||||
var internalHandlers = ListPool<IEventSystemHandler>.Get();
|
||||
GetEventList<T>(target, internalHandlers);
|
||||
// if (s_InternalHandlers.Count > 0)
|
||||
// Debug.Log("Executinng " + typeof (T) + " on " + target);
|
||||
|
||||
var internalHandlersCount = internalHandlers.Count;
|
||||
for (var i = 0; i < internalHandlersCount; i++)
|
||||
{
|
||||
T arg;
|
||||
try
|
||||
{
|
||||
arg = (T)internalHandlers[i];
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
var temp = internalHandlers[i];
|
||||
Debug.LogException(new Exception(string.Format("Type {0} expected {1} received.", typeof(T).Name, temp.GetType().Name), e));
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
functor(arg, eventData);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
}
|
||||
}
|
||||
|
||||
var handlerCount = internalHandlers.Count;
|
||||
ListPool<IEventSystemHandler>.Release(internalHandlers);
|
||||
return handlerCount > 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute the specified event on the first game object underneath the current touch.
|
||||
/// </summary>
|
||||
private static readonly List<Transform> s_InternalTransformList = new List<Transform>(30);
|
||||
|
||||
public static GameObject ExecuteHierarchy<T>(GameObject root, BaseEventData eventData, EventFunction<T> callbackFunction) where T : IEventSystemHandler
|
||||
{
|
||||
GetEventChain(root, s_InternalTransformList);
|
||||
|
||||
var internalTransformListCount = s_InternalTransformList.Count;
|
||||
for (var i = 0; i < internalTransformListCount; i++)
|
||||
{
|
||||
var transform = s_InternalTransformList[i];
|
||||
if (Execute(transform.gameObject, eventData, callbackFunction))
|
||||
return transform.gameObject;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static bool ShouldSendToComponent<T>(Component component) where T : IEventSystemHandler
|
||||
{
|
||||
var valid = component is T;
|
||||
if (!valid)
|
||||
return false;
|
||||
|
||||
var behaviour = component as Behaviour;
|
||||
if (behaviour != null)
|
||||
return behaviour.isActiveAndEnabled;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the specified object's event event.
|
||||
/// </summary>
|
||||
private static void GetEventList<T>(GameObject go, IList<IEventSystemHandler> results) where T : IEventSystemHandler
|
||||
{
|
||||
// Debug.LogWarning("GetEventList<" + typeof(T).Name + ">");
|
||||
if (results == null)
|
||||
throw new ArgumentException("Results array is null", "results");
|
||||
|
||||
if (go == null || !go.activeInHierarchy)
|
||||
return;
|
||||
|
||||
var components = ListPool<Component>.Get();
|
||||
go.GetComponents(components);
|
||||
|
||||
var componentsCount = components.Count;
|
||||
for (var i = 0; i < componentsCount; i++)
|
||||
{
|
||||
if (!ShouldSendToComponent<T>(components[i]))
|
||||
continue;
|
||||
|
||||
// Debug.Log(string.Format("{2} found! On {0}.{1}", go, s_GetComponentsScratch[i].GetType(), typeof(T)));
|
||||
results.Add(components[i] as IEventSystemHandler);
|
||||
}
|
||||
ListPool<Component>.Release(components);
|
||||
// Debug.LogWarning("end GetEventList<" + typeof(T).Name + ">");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether the specified game object will be able to handle the specified event.
|
||||
/// </summary>
|
||||
public static bool CanHandleEvent<T>(GameObject go) where T : IEventSystemHandler
|
||||
{
|
||||
var internalHandlers = ListPool<IEventSystemHandler>.Get();
|
||||
GetEventList<T>(go, internalHandlers);
|
||||
var handlerCount = internalHandlers.Count;
|
||||
ListPool<IEventSystemHandler>.Release(internalHandlers);
|
||||
return handlerCount != 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bubble the specified event on the game object, figuring out which object will actually receive the event.
|
||||
/// </summary>
|
||||
public static GameObject GetEventHandler<T>(GameObject root) where T : IEventSystemHandler
|
||||
{
|
||||
if (root == null)
|
||||
return null;
|
||||
|
||||
Transform t = root.transform;
|
||||
while (t != null)
|
||||
{
|
||||
if (CanHandleEvent<T>(t.gameObject))
|
||||
return t.gameObject;
|
||||
t = t.parent;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 623c79a1e113b4941afdbfc88d19e8fd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8e78f8a8575e4a04f8337a54e241cdc5
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,129 @@
|
|||
using UnityEngine.UI;
|
||||
|
||||
namespace UnityEngine.EventSystems
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface to the Input system used by the BaseInputModule. With this it is possible to bypass the Input system with your own but still use the same InputModule. For example this can be used to feed fake input into the UI or interface with a different input system.
|
||||
/// </summary>
|
||||
public class BaseInput : UIBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface to Input.compositionString. Can be overridden to provide custom input instead of using the Input class.
|
||||
/// </summary>
|
||||
public virtual string compositionString
|
||||
{
|
||||
get { return Input.compositionString; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to Input.imeCompositionMode. Can be overridden to provide custom input instead of using the Input class.
|
||||
/// </summary>
|
||||
public virtual IMECompositionMode imeCompositionMode
|
||||
{
|
||||
get { return Input.imeCompositionMode; }
|
||||
set { Input.imeCompositionMode = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to Input.compositionCursorPos. Can be overridden to provide custom input instead of using the Input class.
|
||||
/// </summary>
|
||||
public virtual Vector2 compositionCursorPos
|
||||
{
|
||||
get { return Input.compositionCursorPos; }
|
||||
set { Input.compositionCursorPos = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to Input.mousePresent. Can be overridden to provide custom input instead of using the Input class.
|
||||
/// </summary>
|
||||
public virtual bool mousePresent
|
||||
{
|
||||
get { return Input.mousePresent; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to Input.GetMouseButtonDown. Can be overridden to provide custom input instead of using the Input class.
|
||||
/// </summary>
|
||||
/// <param name="button"></param>
|
||||
/// <returns></returns>
|
||||
public virtual bool GetMouseButtonDown(int button)
|
||||
{
|
||||
return Input.GetMouseButtonDown(button);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to Input.GetMouseButtonUp. Can be overridden to provide custom input instead of using the Input class.
|
||||
/// </summary>
|
||||
public virtual bool GetMouseButtonUp(int button)
|
||||
{
|
||||
return Input.GetMouseButtonUp(button);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to Input.GetMouseButton. Can be overridden to provide custom input instead of using the Input class.
|
||||
/// </summary>
|
||||
public virtual bool GetMouseButton(int button)
|
||||
{
|
||||
return Input.GetMouseButton(button);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to Input.mousePosition. Can be overridden to provide custom input instead of using the Input class.
|
||||
/// </summary>
|
||||
public virtual Vector2 mousePosition
|
||||
{
|
||||
get { return MultipleDisplayUtilities.GetMousePositionRelativeToMainDisplayResolution(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to Input.mouseScrollDelta. Can be overridden to provide custom input instead of using the Input class.
|
||||
/// </summary>
|
||||
public virtual Vector2 mouseScrollDelta
|
||||
{
|
||||
get { return Input.mouseScrollDelta; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to Input.touchSupported. Can be overridden to provide custom input instead of using the Input class.
|
||||
/// </summary>
|
||||
public virtual bool touchSupported
|
||||
{
|
||||
get { return Input.touchSupported; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to Input.touchCount. Can be overridden to provide custom input instead of using the Input class.
|
||||
/// </summary>
|
||||
public virtual int touchCount
|
||||
{
|
||||
get { return Input.touchCount; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to Input.GetTouch. Can be overridden to provide custom input instead of using the Input class.
|
||||
/// </summary>
|
||||
/// <param name="index">Touch index to get</param>
|
||||
public virtual Touch GetTouch(int index)
|
||||
{
|
||||
return Input.GetTouch(index);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to Input.GetAxisRaw. Can be overridden to provide custom input instead of using the Input class.
|
||||
/// </summary>
|
||||
/// <param name="axisName">Axis name to check</param>
|
||||
public virtual float GetAxisRaw(string axisName)
|
||||
{
|
||||
return Input.GetAxisRaw(axisName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to Input.GetButtonDown. Can be overridden to provide custom input instead of using the Input class.
|
||||
/// </summary>
|
||||
/// <param name="buttonName">Button name to get</param>
|
||||
public virtual bool GetButtonDown(string buttonName)
|
||||
{
|
||||
return Input.GetButtonDown(buttonName);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1511ccae7919cfc46b603b9b337fdc94
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,355 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UnityEngine.EventSystems
|
||||
{
|
||||
[RequireComponent(typeof(EventSystem))]
|
||||
/// <summary>
|
||||
/// A base module that raises events and sends them to GameObjects.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// An Input Module is a component of the EventSystem that is responsible for raising events and sending them to GameObjects for handling. The BaseInputModule is a class that all Input Modules in the EventSystem inherit from. Examples of provided modules are TouchInputModule and StandaloneInputModule, if these are inadequate for your project you can create your own by extending from the BaseInputModule.
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// <![CDATA[
|
||||
/// using UnityEngine;
|
||||
/// using UnityEngine.EventSystems;
|
||||
///
|
||||
/// /**
|
||||
/// * Create a module that every tick sends a 'Move' event to
|
||||
/// * the target object
|
||||
/// */
|
||||
/// public class MyInputModule : BaseInputModule
|
||||
/// {
|
||||
/// public GameObject m_TargetObject;
|
||||
///
|
||||
/// public override void Process()
|
||||
/// {
|
||||
/// if (m_TargetObject == null)
|
||||
/// return;
|
||||
/// ExecuteEvents.Execute (m_TargetObject, new BaseEventData (eventSystem), ExecuteEvents.moveHandler);
|
||||
/// }
|
||||
/// }
|
||||
/// ]]>
|
||||
///</code>
|
||||
/// </example>
|
||||
public abstract class BaseInputModule : UIBehaviour
|
||||
{
|
||||
[NonSerialized]
|
||||
protected List<RaycastResult> m_RaycastResultCache = new List<RaycastResult>();
|
||||
|
||||
private AxisEventData m_AxisEventData;
|
||||
|
||||
private EventSystem m_EventSystem;
|
||||
private BaseEventData m_BaseEventData;
|
||||
|
||||
protected BaseInput m_InputOverride;
|
||||
private BaseInput m_DefaultInput;
|
||||
|
||||
/// <summary>
|
||||
/// The current BaseInput being used by the input module.
|
||||
/// </summary>
|
||||
public BaseInput input
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_InputOverride != null)
|
||||
return m_InputOverride;
|
||||
|
||||
if (m_DefaultInput == null)
|
||||
{
|
||||
var inputs = GetComponents<BaseInput>();
|
||||
foreach (var baseInput in inputs)
|
||||
{
|
||||
// We dont want to use any classes that derrive from BaseInput for default.
|
||||
if (baseInput != null && baseInput.GetType() == typeof(BaseInput))
|
||||
{
|
||||
m_DefaultInput = baseInput;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_DefaultInput == null)
|
||||
m_DefaultInput = gameObject.AddComponent<BaseInput>();
|
||||
}
|
||||
|
||||
return m_DefaultInput;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to override the default BaseInput for the input module.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// With this it is possible to bypass the Input system with your own but still use the same InputModule. For example this can be used to feed fake input into the UI or interface with a different input system.
|
||||
/// </remarks>
|
||||
public BaseInput inputOverride
|
||||
{
|
||||
get { return m_InputOverride; }
|
||||
set { m_InputOverride = value; }
|
||||
}
|
||||
|
||||
protected EventSystem eventSystem
|
||||
{
|
||||
get { return m_EventSystem; }
|
||||
}
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
m_EventSystem = GetComponent<EventSystem>();
|
||||
m_EventSystem.UpdateModules();
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
m_EventSystem.UpdateModules();
|
||||
base.OnDisable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process the current tick for the module.
|
||||
/// </summary>
|
||||
public abstract void Process();
|
||||
|
||||
/// <summary>
|
||||
/// Return the first valid RaycastResult.
|
||||
/// </summary>
|
||||
protected static RaycastResult FindFirstRaycast(List<RaycastResult> candidates)
|
||||
{
|
||||
var candidatesCount = candidates.Count;
|
||||
for (var i = 0; i < candidatesCount; ++i)
|
||||
{
|
||||
if (candidates[i].gameObject == null)
|
||||
continue;
|
||||
|
||||
return candidates[i];
|
||||
}
|
||||
return new RaycastResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given an input movement, determine the best MoveDirection.
|
||||
/// </summary>
|
||||
/// <param name="x">X movement.</param>
|
||||
/// <param name="y">Y movement.</param>
|
||||
protected static MoveDirection DetermineMoveDirection(float x, float y)
|
||||
{
|
||||
return DetermineMoveDirection(x, y, 0.6f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given an input movement, determine the best MoveDirection.
|
||||
/// </summary>
|
||||
/// <param name="x">X movement.</param>
|
||||
/// <param name="y">Y movement.</param>
|
||||
/// <param name="deadZone">Dead zone.</param>
|
||||
protected static MoveDirection DetermineMoveDirection(float x, float y, float deadZone)
|
||||
{
|
||||
// if vector is too small... just return
|
||||
if (new Vector2(x, y).sqrMagnitude < deadZone * deadZone)
|
||||
return MoveDirection.None;
|
||||
|
||||
if (Mathf.Abs(x) > Mathf.Abs(y))
|
||||
{
|
||||
return x > 0 ? MoveDirection.Right : MoveDirection.Left;
|
||||
}
|
||||
|
||||
return y > 0 ? MoveDirection.Up : MoveDirection.Down;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given 2 GameObjects, return a common root GameObject (or null).
|
||||
/// </summary>
|
||||
/// <param name="g1">GameObject to compare</param>
|
||||
/// <param name="g2">GameObject to compare</param>
|
||||
/// <returns></returns>
|
||||
protected static GameObject FindCommonRoot(GameObject g1, GameObject g2)
|
||||
{
|
||||
if (g1 == null || g2 == null)
|
||||
return null;
|
||||
|
||||
var t1 = g1.transform;
|
||||
while (t1 != null)
|
||||
{
|
||||
var t2 = g2.transform;
|
||||
while (t2 != null)
|
||||
{
|
||||
if (t1 == t2)
|
||||
return t1.gameObject;
|
||||
t2 = t2.parent;
|
||||
}
|
||||
t1 = t1.parent;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// walk up the tree till a common root between the last entered and the current entered is found
|
||||
// send exit events up to (but not inluding) the common root. Then send enter events up to
|
||||
// (but not including the common root).
|
||||
// Send move events before exit, after enter, and on hovered objects when pointer data has changed.
|
||||
protected void HandlePointerExitAndEnter(PointerEventData currentPointerData, GameObject newEnterTarget)
|
||||
{
|
||||
// if we have no target / pointerEnter has been deleted
|
||||
// just send exit events to anything we are tracking
|
||||
// then exit
|
||||
if (newEnterTarget == null || currentPointerData.pointerEnter == null)
|
||||
{
|
||||
var hoveredCount = currentPointerData.hovered.Count;
|
||||
for (var i = 0; i < hoveredCount; ++i)
|
||||
{
|
||||
ExecuteEvents.Execute(currentPointerData.hovered[i], currentPointerData, ExecuteEvents.pointerMoveHandler);
|
||||
ExecuteEvents.Execute(currentPointerData.hovered[i], currentPointerData, ExecuteEvents.pointerExitHandler);
|
||||
}
|
||||
|
||||
currentPointerData.hovered.Clear();
|
||||
|
||||
if (newEnterTarget == null)
|
||||
{
|
||||
currentPointerData.pointerEnter = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// if we have not changed hover target
|
||||
if (currentPointerData.pointerEnter == newEnterTarget && newEnterTarget)
|
||||
{
|
||||
if (currentPointerData.IsPointerMoving())
|
||||
{
|
||||
var hoveredCount = currentPointerData.hovered.Count;
|
||||
for (var i = 0; i < hoveredCount; ++i)
|
||||
ExecuteEvents.Execute(currentPointerData.hovered[i], currentPointerData, ExecuteEvents.pointerMoveHandler);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
GameObject commonRoot = FindCommonRoot(currentPointerData.pointerEnter, newEnterTarget);
|
||||
|
||||
// and we already an entered object from last time
|
||||
if (currentPointerData.pointerEnter != null)
|
||||
{
|
||||
// send exit handler call to all elements in the chain
|
||||
// until we reach the new target, or null!
|
||||
Transform t = currentPointerData.pointerEnter.transform;
|
||||
|
||||
while (t != null)
|
||||
{
|
||||
// if we reach the common root break out!
|
||||
if (commonRoot != null && commonRoot.transform == t)
|
||||
break;
|
||||
|
||||
ExecuteEvents.Execute(t.gameObject, currentPointerData, ExecuteEvents.pointerMoveHandler);
|
||||
ExecuteEvents.Execute(t.gameObject, currentPointerData, ExecuteEvents.pointerExitHandler);
|
||||
currentPointerData.hovered.Remove(t.gameObject);
|
||||
t = t.parent;
|
||||
}
|
||||
}
|
||||
|
||||
// now issue the enter call up to but not including the common root
|
||||
currentPointerData.pointerEnter = newEnterTarget;
|
||||
if (newEnterTarget != null)
|
||||
{
|
||||
Transform t = newEnterTarget.transform;
|
||||
|
||||
while (t != null && t.gameObject != commonRoot)
|
||||
{
|
||||
ExecuteEvents.Execute(t.gameObject, currentPointerData, ExecuteEvents.pointerEnterHandler);
|
||||
ExecuteEvents.Execute(t.gameObject, currentPointerData, ExecuteEvents.pointerMoveHandler);
|
||||
currentPointerData.hovered.Add(t.gameObject);
|
||||
t = t.parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given some input data generate an AxisEventData that can be used by the event system.
|
||||
/// </summary>
|
||||
/// <param name="x">X movement.</param>
|
||||
/// <param name="y">Y movement.</param>
|
||||
/// <param name="deadZone">Dead zone.</param>
|
||||
protected virtual AxisEventData GetAxisEventData(float x, float y, float moveDeadZone)
|
||||
{
|
||||
if (m_AxisEventData == null)
|
||||
m_AxisEventData = new AxisEventData(eventSystem);
|
||||
|
||||
m_AxisEventData.Reset();
|
||||
m_AxisEventData.moveVector = new Vector2(x, y);
|
||||
m_AxisEventData.moveDir = DetermineMoveDirection(x, y, moveDeadZone);
|
||||
return m_AxisEventData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a BaseEventData that can be used by the EventSystem.
|
||||
/// </summary>
|
||||
protected virtual BaseEventData GetBaseEventData()
|
||||
{
|
||||
if (m_BaseEventData == null)
|
||||
m_BaseEventData = new BaseEventData(eventSystem);
|
||||
|
||||
m_BaseEventData.Reset();
|
||||
return m_BaseEventData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the module is pointer based, then override this to return true if the pointer is over an event system object.
|
||||
/// </summary>
|
||||
/// <param name="pointerId">Pointer ID</param>
|
||||
/// <returns>Is the given pointer over an event system object?</returns>
|
||||
public virtual bool IsPointerOverGameObject(int pointerId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Should the module be activated.
|
||||
/// </summary>
|
||||
public virtual bool ShouldActivateModule()
|
||||
{
|
||||
return enabled && gameObject.activeInHierarchy;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the module is deactivated. Override this if you want custom code to execute when you deactivate your module.
|
||||
/// </summary>
|
||||
public virtual void DeactivateModule()
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the module is activated. Override this if you want custom code to execute when you activate your module.
|
||||
/// </summary>
|
||||
public virtual void ActivateModule()
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Update the internal state of the Module.
|
||||
/// </summary>
|
||||
public virtual void UpdateModule()
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Check to see if the module is supported. Override this if you have a platform specific module (eg. TouchInputModule that you do not want to activate on standalone.)
|
||||
/// </summary>
|
||||
/// <returns>Is the module supported.</returns>
|
||||
public virtual bool IsModuleSupported()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns Id of the pointer following <see cref="UnityEngine.UIElements.PointerId"/> convention.
|
||||
/// </summary>
|
||||
/// <param name="sourcePointerData">PointerEventData whose pointerId will be converted to UI Toolkit pointer convention.</param>
|
||||
/// <seealso cref="UnityEngine.UIElements.IPointerEvent" />
|
||||
public virtual int ConvertUIToolkitPointerId(PointerEventData sourcePointerData)
|
||||
{
|
||||
#if PACKAGE_UITOOLKIT
|
||||
return sourcePointerData.pointerId < 0 ?
|
||||
UIElements.PointerId.mousePointerId :
|
||||
UIElements.PointerId.touchPointerIdBase + sourcePointerData.pointerId;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1ea10891dd782154ca0fb67bce9e6f72
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,437 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace UnityEngine.EventSystems
|
||||
{
|
||||
/// <summary>
|
||||
/// A BaseInputModule for pointer input.
|
||||
/// </summary>
|
||||
public abstract class PointerInputModule : BaseInputModule
|
||||
{
|
||||
/// <summary>
|
||||
/// Id of the cached left mouse pointer event.
|
||||
/// </summary>
|
||||
public const int kMouseLeftId = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Id of the cached right mouse pointer event.
|
||||
/// </summary>
|
||||
public const int kMouseRightId = -2;
|
||||
|
||||
/// <summary>
|
||||
/// Id of the cached middle mouse pointer event.
|
||||
/// </summary>
|
||||
public const int kMouseMiddleId = -3;
|
||||
|
||||
/// <summary>
|
||||
/// Touch id for when simulating touches on a non touch device.
|
||||
/// </summary>
|
||||
public const int kFakeTouchesId = -4;
|
||||
|
||||
protected Dictionary<int, PointerEventData> m_PointerData = new Dictionary<int, PointerEventData>();
|
||||
|
||||
/// <summary>
|
||||
/// Search the cache for currently active pointers, return true if found.
|
||||
/// </summary>
|
||||
/// <param name="id">Touch ID</param>
|
||||
/// <param name="data">Found data</param>
|
||||
/// <param name="create">If not found should it be created</param>
|
||||
/// <returns>True if pointer is found.</returns>
|
||||
protected bool GetPointerData(int id, out PointerEventData data, bool create)
|
||||
{
|
||||
if (!m_PointerData.TryGetValue(id, out data) && create)
|
||||
{
|
||||
data = new PointerEventData(eventSystem)
|
||||
{
|
||||
pointerId = id,
|
||||
};
|
||||
m_PointerData.Add(id, data);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove the PointerEventData from the cache.
|
||||
/// </summary>
|
||||
protected void RemovePointerData(PointerEventData data)
|
||||
{
|
||||
m_PointerData.Remove(data.pointerId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given a touch populate the PointerEventData and return if we are pressed or released.
|
||||
/// </summary>
|
||||
/// <param name="input">Touch being processed</param>
|
||||
/// <param name="pressed">Are we pressed this frame</param>
|
||||
/// <param name="released">Are we released this frame</param>
|
||||
/// <returns></returns>
|
||||
protected PointerEventData GetTouchPointerEventData(Touch input, out bool pressed, out bool released)
|
||||
{
|
||||
PointerEventData pointerData;
|
||||
var created = GetPointerData(input.fingerId, out pointerData, true);
|
||||
|
||||
pointerData.Reset();
|
||||
|
||||
pressed = created || (input.phase == TouchPhase.Began);
|
||||
released = (input.phase == TouchPhase.Canceled) || (input.phase == TouchPhase.Ended);
|
||||
|
||||
if (created)
|
||||
pointerData.position = input.position;
|
||||
|
||||
if (pressed)
|
||||
pointerData.delta = Vector2.zero;
|
||||
else
|
||||
pointerData.delta = input.position - pointerData.position;
|
||||
|
||||
pointerData.position = input.position;
|
||||
|
||||
pointerData.button = PointerEventData.InputButton.Left;
|
||||
|
||||
if (input.phase == TouchPhase.Canceled)
|
||||
{
|
||||
pointerData.pointerCurrentRaycast = new RaycastResult();
|
||||
}
|
||||
else
|
||||
{
|
||||
eventSystem.RaycastAll(pointerData, m_RaycastResultCache);
|
||||
|
||||
var raycast = FindFirstRaycast(m_RaycastResultCache);
|
||||
pointerData.pointerCurrentRaycast = raycast;
|
||||
m_RaycastResultCache.Clear();
|
||||
}
|
||||
|
||||
pointerData.pressure = input.pressure;
|
||||
pointerData.altitudeAngle = input.altitudeAngle;
|
||||
pointerData.azimuthAngle = input.azimuthAngle;
|
||||
pointerData.radius = Vector2.one * input.radius;
|
||||
pointerData.radiusVariance = Vector2.one * input.radiusVariance;
|
||||
|
||||
return pointerData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy one PointerEventData to another.
|
||||
/// </summary>
|
||||
protected void CopyFromTo(PointerEventData @from, PointerEventData @to)
|
||||
{
|
||||
@to.position = @from.position;
|
||||
@to.delta = @from.delta;
|
||||
@to.scrollDelta = @from.scrollDelta;
|
||||
@to.pointerCurrentRaycast = @from.pointerCurrentRaycast;
|
||||
@to.pointerEnter = @from.pointerEnter;
|
||||
|
||||
@to.pressure = @from.pressure;
|
||||
@to.tangentialPressure = @from.tangentialPressure;
|
||||
@to.altitudeAngle = @from.altitudeAngle;
|
||||
@to.azimuthAngle = @from.azimuthAngle;
|
||||
@to.twist = @from.twist;
|
||||
@to.radius = @from.radius;
|
||||
@to.radiusVariance = @from.radiusVariance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given a mouse button return the current state for the frame.
|
||||
/// </summary>
|
||||
/// <param name="buttonId">Mouse button ID</param>
|
||||
protected PointerEventData.FramePressState StateForMouseButton(int buttonId)
|
||||
{
|
||||
var pressed = input.GetMouseButtonDown(buttonId);
|
||||
var released = input.GetMouseButtonUp(buttonId);
|
||||
if (pressed && released)
|
||||
return PointerEventData.FramePressState.PressedAndReleased;
|
||||
if (pressed)
|
||||
return PointerEventData.FramePressState.Pressed;
|
||||
if (released)
|
||||
return PointerEventData.FramePressState.Released;
|
||||
return PointerEventData.FramePressState.NotChanged;
|
||||
}
|
||||
|
||||
protected class ButtonState
|
||||
{
|
||||
private PointerEventData.InputButton m_Button = PointerEventData.InputButton.Left;
|
||||
|
||||
public MouseButtonEventData eventData
|
||||
{
|
||||
get { return m_EventData; }
|
||||
set { m_EventData = value; }
|
||||
}
|
||||
|
||||
public PointerEventData.InputButton button
|
||||
{
|
||||
get { return m_Button; }
|
||||
set { m_Button = value; }
|
||||
}
|
||||
|
||||
private MouseButtonEventData m_EventData;
|
||||
}
|
||||
|
||||
protected class MouseState
|
||||
{
|
||||
private List<ButtonState> m_TrackedButtons = new List<ButtonState>();
|
||||
|
||||
public bool AnyPressesThisFrame()
|
||||
{
|
||||
var trackedButtonsCount = m_TrackedButtons.Count;
|
||||
for (int i = 0; i < trackedButtonsCount; i++)
|
||||
{
|
||||
if (m_TrackedButtons[i].eventData.PressedThisFrame())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool AnyReleasesThisFrame()
|
||||
{
|
||||
var trackedButtonsCount = m_TrackedButtons.Count;
|
||||
for (int i = 0; i < trackedButtonsCount; i++)
|
||||
{
|
||||
if (m_TrackedButtons[i].eventData.ReleasedThisFrame())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public ButtonState GetButtonState(PointerEventData.InputButton button)
|
||||
{
|
||||
ButtonState tracked = null;
|
||||
var trackedButtonsCount = m_TrackedButtons.Count;
|
||||
for (int i = 0; i < trackedButtonsCount; i++)
|
||||
{
|
||||
if (m_TrackedButtons[i].button == button)
|
||||
{
|
||||
tracked = m_TrackedButtons[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tracked == null)
|
||||
{
|
||||
tracked = new ButtonState { button = button, eventData = new MouseButtonEventData() };
|
||||
m_TrackedButtons.Add(tracked);
|
||||
}
|
||||
return tracked;
|
||||
}
|
||||
|
||||
public void SetButtonState(PointerEventData.InputButton button, PointerEventData.FramePressState stateForMouseButton, PointerEventData data)
|
||||
{
|
||||
var toModify = GetButtonState(button);
|
||||
toModify.eventData.buttonState = stateForMouseButton;
|
||||
toModify.eventData.buttonData = data;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Information about a mouse button event.
|
||||
/// </summary>
|
||||
public class MouseButtonEventData
|
||||
{
|
||||
/// <summary>
|
||||
/// The state of the button this frame.
|
||||
/// </summary>
|
||||
public PointerEventData.FramePressState buttonState;
|
||||
|
||||
/// <summary>
|
||||
/// Pointer data associated with the mouse event.
|
||||
/// </summary>
|
||||
public PointerEventData buttonData;
|
||||
|
||||
/// <summary>
|
||||
/// Was the button pressed this frame?
|
||||
/// </summary>
|
||||
public bool PressedThisFrame()
|
||||
{
|
||||
return buttonState == PointerEventData.FramePressState.Pressed || buttonState == PointerEventData.FramePressState.PressedAndReleased;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Was the button released this frame?
|
||||
/// </summary>
|
||||
public bool ReleasedThisFrame()
|
||||
{
|
||||
return buttonState == PointerEventData.FramePressState.Released || buttonState == PointerEventData.FramePressState.PressedAndReleased;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly MouseState m_MouseState = new MouseState();
|
||||
|
||||
/// <summary>
|
||||
/// Return the current MouseState. Using the default pointer.
|
||||
/// </summary>
|
||||
protected virtual MouseState GetMousePointerEventData()
|
||||
{
|
||||
return GetMousePointerEventData(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the current MouseState.
|
||||
/// </summary>
|
||||
protected virtual MouseState GetMousePointerEventData(int id)
|
||||
{
|
||||
// Populate the left button...
|
||||
PointerEventData leftData;
|
||||
var created = GetPointerData(kMouseLeftId, out leftData, true);
|
||||
|
||||
leftData.Reset();
|
||||
|
||||
if (created)
|
||||
leftData.position = input.mousePosition;
|
||||
|
||||
Vector2 pos = input.mousePosition;
|
||||
if (Cursor.lockState == CursorLockMode.Locked)
|
||||
{
|
||||
// We don't want to do ANY cursor-based interaction when the mouse is locked
|
||||
leftData.position = new Vector2(-1.0f, -1.0f);
|
||||
leftData.delta = Vector2.zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
leftData.delta = pos - leftData.position;
|
||||
leftData.position = pos;
|
||||
}
|
||||
leftData.scrollDelta = input.mouseScrollDelta;
|
||||
leftData.button = PointerEventData.InputButton.Left;
|
||||
eventSystem.RaycastAll(leftData, m_RaycastResultCache);
|
||||
var raycast = FindFirstRaycast(m_RaycastResultCache);
|
||||
leftData.pointerCurrentRaycast = raycast;
|
||||
m_RaycastResultCache.Clear();
|
||||
|
||||
// copy the apropriate data into right and middle slots
|
||||
PointerEventData rightData;
|
||||
GetPointerData(kMouseRightId, out rightData, true);
|
||||
rightData.Reset();
|
||||
|
||||
CopyFromTo(leftData, rightData);
|
||||
rightData.button = PointerEventData.InputButton.Right;
|
||||
|
||||
PointerEventData middleData;
|
||||
GetPointerData(kMouseMiddleId, out middleData, true);
|
||||
middleData.Reset();
|
||||
|
||||
CopyFromTo(leftData, middleData);
|
||||
middleData.button = PointerEventData.InputButton.Middle;
|
||||
|
||||
m_MouseState.SetButtonState(PointerEventData.InputButton.Left, StateForMouseButton(0), leftData);
|
||||
m_MouseState.SetButtonState(PointerEventData.InputButton.Right, StateForMouseButton(1), rightData);
|
||||
m_MouseState.SetButtonState(PointerEventData.InputButton.Middle, StateForMouseButton(2), middleData);
|
||||
|
||||
return m_MouseState;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the last PointerEventData for the given touch / mouse id.
|
||||
/// </summary>
|
||||
protected PointerEventData GetLastPointerEventData(int id)
|
||||
{
|
||||
PointerEventData data;
|
||||
GetPointerData(id, out data, false);
|
||||
return data;
|
||||
}
|
||||
|
||||
private static bool ShouldStartDrag(Vector2 pressPos, Vector2 currentPos, float threshold, bool useDragThreshold)
|
||||
{
|
||||
if (!useDragThreshold)
|
||||
return true;
|
||||
|
||||
return (pressPos - currentPos).sqrMagnitude >= threshold * threshold;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process movement for the current frame with the given pointer event.
|
||||
/// </summary>
|
||||
protected virtual void ProcessMove(PointerEventData pointerEvent)
|
||||
{
|
||||
var targetGO = (Cursor.lockState == CursorLockMode.Locked ? null : pointerEvent.pointerCurrentRaycast.gameObject);
|
||||
HandlePointerExitAndEnter(pointerEvent, targetGO);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process the drag for the current frame with the given pointer event.
|
||||
/// </summary>
|
||||
protected virtual void ProcessDrag(PointerEventData pointerEvent)
|
||||
{
|
||||
if (!pointerEvent.IsPointerMoving() ||
|
||||
Cursor.lockState == CursorLockMode.Locked ||
|
||||
pointerEvent.pointerDrag == null)
|
||||
return;
|
||||
|
||||
if (!pointerEvent.dragging
|
||||
&& ShouldStartDrag(pointerEvent.pressPosition, pointerEvent.position, eventSystem.pixelDragThreshold, pointerEvent.useDragThreshold))
|
||||
{
|
||||
ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.beginDragHandler);
|
||||
pointerEvent.dragging = true;
|
||||
}
|
||||
|
||||
// Drag notification
|
||||
if (pointerEvent.dragging)
|
||||
{
|
||||
// Before doing drag we should cancel any pointer down state
|
||||
// And clear selection!
|
||||
if (pointerEvent.pointerPress != pointerEvent.pointerDrag)
|
||||
{
|
||||
ExecuteEvents.Execute(pointerEvent.pointerPress, pointerEvent, ExecuteEvents.pointerUpHandler);
|
||||
|
||||
pointerEvent.eligibleForClick = false;
|
||||
pointerEvent.pointerPress = null;
|
||||
pointerEvent.rawPointerPress = null;
|
||||
}
|
||||
ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.dragHandler);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsPointerOverGameObject(int pointerId)
|
||||
{
|
||||
var lastPointer = GetLastPointerEventData(pointerId);
|
||||
if (lastPointer != null)
|
||||
return lastPointer.pointerEnter != null;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear all pointers and deselect any selected objects in the EventSystem.
|
||||
/// </summary>
|
||||
protected void ClearSelection()
|
||||
{
|
||||
var baseEventData = GetBaseEventData();
|
||||
|
||||
foreach (var pointer in m_PointerData.Values)
|
||||
{
|
||||
// clear all selection
|
||||
HandlePointerExitAndEnter(pointer, null);
|
||||
}
|
||||
|
||||
m_PointerData.Clear();
|
||||
eventSystem.SetSelectedGameObject(null, baseEventData);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new StringBuilder("<b>Pointer Input Module of type: </b>" + GetType());
|
||||
sb.AppendLine();
|
||||
foreach (var pointer in m_PointerData)
|
||||
{
|
||||
if (pointer.Value == null)
|
||||
continue;
|
||||
sb.AppendLine("<B>Pointer:</b> " + pointer.Key);
|
||||
sb.AppendLine(pointer.Value.ToString());
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deselect the current selected GameObject if the currently pointed-at GameObject is different.
|
||||
/// </summary>
|
||||
/// <param name="currentOverGo">The GameObject the pointer is currently over.</param>
|
||||
/// <param name="pointerEvent">Current event data.</param>
|
||||
protected void DeselectIfSelectionChanged(GameObject currentOverGo, BaseEventData pointerEvent)
|
||||
{
|
||||
// Selection tracking
|
||||
var selectHandlerGO = ExecuteEvents.GetEventHandler<ISelectHandler>(currentOverGo);
|
||||
// if we have clicked something new, deselect the old thing
|
||||
// leave 'selection handling' up to the press event though.
|
||||
if (selectHandlerGO != eventSystem.currentSelectedGameObject)
|
||||
eventSystem.SetSelectedGameObject(null, pointerEvent);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: cbab8835092323a4389f2dc7d8f6c781
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,649 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace UnityEngine.EventSystems
|
||||
{
|
||||
[AddComponentMenu("Event/Standalone Input Module")]
|
||||
/// <summary>
|
||||
/// A BaseInputModule designed for mouse / keyboard / controller input.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Input module for working with, mouse, keyboard, or controller.
|
||||
/// </remarks>
|
||||
public class StandaloneInputModule : PointerInputModule
|
||||
{
|
||||
private float m_PrevActionTime;
|
||||
private Vector2 m_LastMoveVector;
|
||||
private int m_ConsecutiveMoveCount = 0;
|
||||
|
||||
private Vector2 m_LastMousePosition;
|
||||
private Vector2 m_MousePosition;
|
||||
|
||||
private GameObject m_CurrentFocusedGameObject;
|
||||
|
||||
private PointerEventData m_InputPointerEvent;
|
||||
|
||||
protected StandaloneInputModule()
|
||||
{
|
||||
}
|
||||
|
||||
[Obsolete("Mode is no longer needed on input module as it handles both mouse and keyboard simultaneously.", false)]
|
||||
public enum InputMode
|
||||
{
|
||||
Mouse,
|
||||
Buttons
|
||||
}
|
||||
|
||||
[Obsolete("Mode is no longer needed on input module as it handles both mouse and keyboard simultaneously.", false)]
|
||||
public InputMode inputMode
|
||||
{
|
||||
get { return InputMode.Mouse; }
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private string m_HorizontalAxis = "Horizontal";
|
||||
|
||||
/// <summary>
|
||||
/// Name of the vertical axis for movement (if axis events are used).
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private string m_VerticalAxis = "Vertical";
|
||||
|
||||
/// <summary>
|
||||
/// Name of the submit button.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private string m_SubmitButton = "Submit";
|
||||
|
||||
/// <summary>
|
||||
/// Name of the submit button.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private string m_CancelButton = "Cancel";
|
||||
|
||||
[SerializeField]
|
||||
private float m_InputActionsPerSecond = 10;
|
||||
|
||||
[SerializeField]
|
||||
private float m_RepeatDelay = 0.5f;
|
||||
|
||||
[SerializeField]
|
||||
[FormerlySerializedAs("m_AllowActivationOnMobileDevice")]
|
||||
[HideInInspector]
|
||||
private bool m_ForceModuleActive;
|
||||
|
||||
[Obsolete("allowActivationOnMobileDevice has been deprecated. Use forceModuleActive instead (UnityUpgradable) -> forceModuleActive")]
|
||||
public bool allowActivationOnMobileDevice
|
||||
{
|
||||
get { return m_ForceModuleActive; }
|
||||
set { m_ForceModuleActive = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Force this module to be active.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If there is no module active with higher priority (ordered in the inspector) this module will be forced active even if valid enabling conditions are not met.
|
||||
/// </remarks>
|
||||
|
||||
[Obsolete("forceModuleActive has been deprecated. There is no need to force the module awake as StandaloneInputModule works for all platforms")]
|
||||
public bool forceModuleActive
|
||||
{
|
||||
get { return m_ForceModuleActive; }
|
||||
set { m_ForceModuleActive = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Number of keyboard / controller inputs allowed per second.
|
||||
/// </summary>
|
||||
public float inputActionsPerSecond
|
||||
{
|
||||
get { return m_InputActionsPerSecond; }
|
||||
set { m_InputActionsPerSecond = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delay in seconds before the input actions per second repeat rate takes effect.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the same direction is sustained, the inputActionsPerSecond property can be used to control the rate at which events are fired. However, it can be desirable that the first repetition is delayed, so the user doesn't get repeated actions by accident.
|
||||
/// </remarks>
|
||||
public float repeatDelay
|
||||
{
|
||||
get { return m_RepeatDelay; }
|
||||
set { m_RepeatDelay = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Name of the horizontal axis for movement (if axis events are used).
|
||||
/// </summary>
|
||||
public string horizontalAxis
|
||||
{
|
||||
get { return m_HorizontalAxis; }
|
||||
set { m_HorizontalAxis = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Name of the vertical axis for movement (if axis events are used).
|
||||
/// </summary>
|
||||
public string verticalAxis
|
||||
{
|
||||
get { return m_VerticalAxis; }
|
||||
set { m_VerticalAxis = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maximum number of input events handled per second.
|
||||
/// </summary>
|
||||
public string submitButton
|
||||
{
|
||||
get { return m_SubmitButton; }
|
||||
set { m_SubmitButton = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Input manager name for the 'cancel' button.
|
||||
/// </summary>
|
||||
public string cancelButton
|
||||
{
|
||||
get { return m_CancelButton; }
|
||||
set { m_CancelButton = value; }
|
||||
}
|
||||
|
||||
private bool ShouldIgnoreEventsOnNoFocus()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
return !UnityEditor.EditorApplication.isRemoteConnected;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
public override void UpdateModule()
|
||||
{
|
||||
if (!eventSystem.isFocused && ShouldIgnoreEventsOnNoFocus())
|
||||
{
|
||||
if (m_InputPointerEvent != null && m_InputPointerEvent.pointerDrag != null && m_InputPointerEvent.dragging)
|
||||
{
|
||||
ReleaseMouse(m_InputPointerEvent, m_InputPointerEvent.pointerCurrentRaycast.gameObject);
|
||||
}
|
||||
|
||||
m_InputPointerEvent = null;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_LastMousePosition = m_MousePosition;
|
||||
m_MousePosition = input.mousePosition;
|
||||
}
|
||||
|
||||
private void ReleaseMouse(PointerEventData pointerEvent, GameObject currentOverGo)
|
||||
{
|
||||
ExecuteEvents.Execute(pointerEvent.pointerPress, pointerEvent, ExecuteEvents.pointerUpHandler);
|
||||
|
||||
var pointerClickHandler = ExecuteEvents.GetEventHandler<IPointerClickHandler>(currentOverGo);
|
||||
|
||||
// PointerClick and Drop events
|
||||
if (pointerEvent.pointerClick == pointerClickHandler && pointerEvent.eligibleForClick)
|
||||
{
|
||||
ExecuteEvents.Execute(pointerEvent.pointerClick, pointerEvent, ExecuteEvents.pointerClickHandler);
|
||||
}
|
||||
if (pointerEvent.pointerDrag != null && pointerEvent.dragging)
|
||||
{
|
||||
ExecuteEvents.ExecuteHierarchy(currentOverGo, pointerEvent, ExecuteEvents.dropHandler);
|
||||
}
|
||||
|
||||
pointerEvent.eligibleForClick = false;
|
||||
pointerEvent.pointerPress = null;
|
||||
pointerEvent.rawPointerPress = null;
|
||||
pointerEvent.pointerClick = null;
|
||||
|
||||
if (pointerEvent.pointerDrag != null && pointerEvent.dragging)
|
||||
ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.endDragHandler);
|
||||
|
||||
pointerEvent.dragging = false;
|
||||
pointerEvent.pointerDrag = null;
|
||||
|
||||
// redo pointer enter / exit to refresh state
|
||||
// so that if we moused over something that ignored it before
|
||||
// due to having pressed on something else
|
||||
// it now gets it.
|
||||
if (currentOverGo != pointerEvent.pointerEnter)
|
||||
{
|
||||
HandlePointerExitAndEnter(pointerEvent, null);
|
||||
HandlePointerExitAndEnter(pointerEvent, currentOverGo);
|
||||
}
|
||||
|
||||
m_InputPointerEvent = pointerEvent;
|
||||
}
|
||||
|
||||
public override bool ShouldActivateModule()
|
||||
{
|
||||
if (!base.ShouldActivateModule())
|
||||
return false;
|
||||
|
||||
var shouldActivate = m_ForceModuleActive;
|
||||
shouldActivate |= input.GetButtonDown(m_SubmitButton);
|
||||
shouldActivate |= input.GetButtonDown(m_CancelButton);
|
||||
shouldActivate |= !Mathf.Approximately(input.GetAxisRaw(m_HorizontalAxis), 0.0f);
|
||||
shouldActivate |= !Mathf.Approximately(input.GetAxisRaw(m_VerticalAxis), 0.0f);
|
||||
shouldActivate |= (m_MousePosition - m_LastMousePosition).sqrMagnitude > 0.0f;
|
||||
shouldActivate |= input.GetMouseButtonDown(0);
|
||||
|
||||
if (input.touchCount > 0)
|
||||
shouldActivate = true;
|
||||
|
||||
return shouldActivate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// See BaseInputModule.
|
||||
/// </summary>
|
||||
public override void ActivateModule()
|
||||
{
|
||||
if (!eventSystem.isFocused && ShouldIgnoreEventsOnNoFocus())
|
||||
return;
|
||||
|
||||
base.ActivateModule();
|
||||
m_MousePosition = input.mousePosition;
|
||||
m_LastMousePosition = input.mousePosition;
|
||||
|
||||
var toSelect = eventSystem.currentSelectedGameObject;
|
||||
if (toSelect == null)
|
||||
toSelect = eventSystem.firstSelectedGameObject;
|
||||
|
||||
eventSystem.SetSelectedGameObject(toSelect, GetBaseEventData());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// See BaseInputModule.
|
||||
/// </summary>
|
||||
public override void DeactivateModule()
|
||||
{
|
||||
base.DeactivateModule();
|
||||
ClearSelection();
|
||||
}
|
||||
|
||||
public override void Process()
|
||||
{
|
||||
if (!eventSystem.isFocused && ShouldIgnoreEventsOnNoFocus())
|
||||
return;
|
||||
|
||||
bool usedEvent = SendUpdateEventToSelectedObject();
|
||||
|
||||
// case 1004066 - touch / mouse events should be processed before navigation events in case
|
||||
// they change the current selected gameobject and the submit button is a touch / mouse button.
|
||||
|
||||
// touch needs to take precedence because of the mouse emulation layer
|
||||
if (!ProcessTouchEvents() && input.mousePresent)
|
||||
ProcessMouseEvent();
|
||||
|
||||
if (eventSystem.sendNavigationEvents)
|
||||
{
|
||||
if (!usedEvent)
|
||||
usedEvent |= SendMoveEventToSelectedObject();
|
||||
|
||||
if (!usedEvent)
|
||||
SendSubmitEventToSelectedObject();
|
||||
}
|
||||
}
|
||||
|
||||
private bool ProcessTouchEvents()
|
||||
{
|
||||
for (int i = 0; i < input.touchCount; ++i)
|
||||
{
|
||||
Touch touch = input.GetTouch(i);
|
||||
|
||||
if (touch.type == TouchType.Indirect)
|
||||
continue;
|
||||
|
||||
bool released;
|
||||
bool pressed;
|
||||
var pointer = GetTouchPointerEventData(touch, out pressed, out released);
|
||||
|
||||
ProcessTouchPress(pointer, pressed, released);
|
||||
|
||||
if (!released)
|
||||
{
|
||||
ProcessMove(pointer);
|
||||
ProcessDrag(pointer);
|
||||
}
|
||||
else
|
||||
RemovePointerData(pointer);
|
||||
}
|
||||
return input.touchCount > 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method is called by Unity whenever a touch event is processed. Override this method with a custom implementation to process touch events yourself.
|
||||
/// </summary>
|
||||
/// <param name="pointerEvent">Event data relating to the touch event, such as position and ID to be passed to the touch event destination object.</param>
|
||||
/// <param name="pressed">This is true for the first frame of a touch event, and false thereafter. This can therefore be used to determine the instant a touch event occurred.</param>
|
||||
/// <param name="released">This is true only for the last frame of a touch event.</param>
|
||||
/// <remarks>
|
||||
/// This method can be overridden in derived classes to change how touch press events are handled.
|
||||
/// </remarks>
|
||||
protected void ProcessTouchPress(PointerEventData pointerEvent, bool pressed, bool released)
|
||||
{
|
||||
var currentOverGo = pointerEvent.pointerCurrentRaycast.gameObject;
|
||||
|
||||
// PointerDown notification
|
||||
if (pressed)
|
||||
{
|
||||
pointerEvent.eligibleForClick = true;
|
||||
pointerEvent.delta = Vector2.zero;
|
||||
pointerEvent.dragging = false;
|
||||
pointerEvent.useDragThreshold = true;
|
||||
pointerEvent.pressPosition = pointerEvent.position;
|
||||
pointerEvent.pointerPressRaycast = pointerEvent.pointerCurrentRaycast;
|
||||
|
||||
DeselectIfSelectionChanged(currentOverGo, pointerEvent);
|
||||
|
||||
if (pointerEvent.pointerEnter != currentOverGo)
|
||||
{
|
||||
// send a pointer enter to the touched element if it isn't the one to select...
|
||||
HandlePointerExitAndEnter(pointerEvent, currentOverGo);
|
||||
pointerEvent.pointerEnter = currentOverGo;
|
||||
}
|
||||
|
||||
// search for the control that will receive the press
|
||||
// if we can't find a press handler set the press
|
||||
// handler to be what would receive a click.
|
||||
var newPressed = ExecuteEvents.ExecuteHierarchy(currentOverGo, pointerEvent, ExecuteEvents.pointerDownHandler);
|
||||
|
||||
var newClick = ExecuteEvents.GetEventHandler<IPointerClickHandler>(currentOverGo);
|
||||
|
||||
// didnt find a press handler... search for a click handler
|
||||
if (newPressed == null)
|
||||
newPressed = newClick;
|
||||
|
||||
// Debug.Log("Pressed: " + newPressed);
|
||||
|
||||
float time = Time.unscaledTime;
|
||||
|
||||
if (newPressed == pointerEvent.lastPress)
|
||||
{
|
||||
var diffTime = time - pointerEvent.clickTime;
|
||||
if (diffTime < 0.3f)
|
||||
++pointerEvent.clickCount;
|
||||
else
|
||||
pointerEvent.clickCount = 1;
|
||||
|
||||
pointerEvent.clickTime = time;
|
||||
}
|
||||
else
|
||||
{
|
||||
pointerEvent.clickCount = 1;
|
||||
}
|
||||
|
||||
pointerEvent.pointerPress = newPressed;
|
||||
pointerEvent.rawPointerPress = currentOverGo;
|
||||
pointerEvent.pointerClick = newClick;
|
||||
|
||||
pointerEvent.clickTime = time;
|
||||
|
||||
// Save the drag handler as well
|
||||
pointerEvent.pointerDrag = ExecuteEvents.GetEventHandler<IDragHandler>(currentOverGo);
|
||||
|
||||
if (pointerEvent.pointerDrag != null)
|
||||
ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.initializePotentialDrag);
|
||||
}
|
||||
|
||||
// PointerUp notification
|
||||
if (released)
|
||||
{
|
||||
// Debug.Log("Executing pressup on: " + pointer.pointerPress);
|
||||
ExecuteEvents.Execute(pointerEvent.pointerPress, pointerEvent, ExecuteEvents.pointerUpHandler);
|
||||
|
||||
// Debug.Log("KeyCode: " + pointer.eventData.keyCode);
|
||||
|
||||
// see if we mouse up on the same element that we clicked on...
|
||||
var pointerClickHandler = ExecuteEvents.GetEventHandler<IPointerClickHandler>(currentOverGo);
|
||||
|
||||
// PointerClick and Drop events
|
||||
if (pointerEvent.pointerClick == pointerClickHandler && pointerEvent.eligibleForClick)
|
||||
{
|
||||
ExecuteEvents.Execute(pointerEvent.pointerClick, pointerEvent, ExecuteEvents.pointerClickHandler);
|
||||
}
|
||||
|
||||
if (pointerEvent.pointerDrag != null && pointerEvent.dragging)
|
||||
{
|
||||
ExecuteEvents.ExecuteHierarchy(currentOverGo, pointerEvent, ExecuteEvents.dropHandler);
|
||||
}
|
||||
|
||||
pointerEvent.eligibleForClick = false;
|
||||
pointerEvent.pointerPress = null;
|
||||
pointerEvent.rawPointerPress = null;
|
||||
pointerEvent.pointerClick = null;
|
||||
|
||||
if (pointerEvent.pointerDrag != null && pointerEvent.dragging)
|
||||
ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.endDragHandler);
|
||||
|
||||
pointerEvent.dragging = false;
|
||||
pointerEvent.pointerDrag = null;
|
||||
|
||||
// send exit events as we need to simulate this on touch up on touch device
|
||||
ExecuteEvents.ExecuteHierarchy(pointerEvent.pointerEnter, pointerEvent, ExecuteEvents.pointerExitHandler);
|
||||
pointerEvent.pointerEnter = null;
|
||||
}
|
||||
|
||||
m_InputPointerEvent = pointerEvent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate and send a submit event to the current selected object.
|
||||
/// </summary>
|
||||
/// <returns>If the submit event was used by the selected object.</returns>
|
||||
protected bool SendSubmitEventToSelectedObject()
|
||||
{
|
||||
if (eventSystem.currentSelectedGameObject == null)
|
||||
return false;
|
||||
|
||||
var data = GetBaseEventData();
|
||||
if (input.GetButtonDown(m_SubmitButton))
|
||||
ExecuteEvents.Execute(eventSystem.currentSelectedGameObject, data, ExecuteEvents.submitHandler);
|
||||
|
||||
if (input.GetButtonDown(m_CancelButton))
|
||||
ExecuteEvents.Execute(eventSystem.currentSelectedGameObject, data, ExecuteEvents.cancelHandler);
|
||||
return data.used;
|
||||
}
|
||||
|
||||
private Vector2 GetRawMoveVector()
|
||||
{
|
||||
Vector2 move = Vector2.zero;
|
||||
move.x = input.GetAxisRaw(m_HorizontalAxis);
|
||||
move.y = input.GetAxisRaw(m_VerticalAxis);
|
||||
|
||||
if (input.GetButtonDown(m_HorizontalAxis))
|
||||
{
|
||||
if (move.x < 0)
|
||||
move.x = -1f;
|
||||
if (move.x > 0)
|
||||
move.x = 1f;
|
||||
}
|
||||
if (input.GetButtonDown(m_VerticalAxis))
|
||||
{
|
||||
if (move.y < 0)
|
||||
move.y = -1f;
|
||||
if (move.y > 0)
|
||||
move.y = 1f;
|
||||
}
|
||||
return move;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate and send a move event to the current selected object.
|
||||
/// </summary>
|
||||
/// <returns>If the move event was used by the selected object.</returns>
|
||||
protected bool SendMoveEventToSelectedObject()
|
||||
{
|
||||
float time = Time.unscaledTime;
|
||||
|
||||
Vector2 movement = GetRawMoveVector();
|
||||
if (Mathf.Approximately(movement.x, 0f) && Mathf.Approximately(movement.y, 0f))
|
||||
{
|
||||
m_ConsecutiveMoveCount = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool similarDir = (Vector2.Dot(movement, m_LastMoveVector) > 0);
|
||||
|
||||
// If direction didn't change at least 90 degrees, wait for delay before allowing consequtive event.
|
||||
if (similarDir && m_ConsecutiveMoveCount == 1)
|
||||
{
|
||||
if (time <= m_PrevActionTime + m_RepeatDelay)
|
||||
return false;
|
||||
}
|
||||
// If direction changed at least 90 degree, or we already had the delay, repeat at repeat rate.
|
||||
else
|
||||
{
|
||||
if (time <= m_PrevActionTime + 1f / m_InputActionsPerSecond)
|
||||
return false;
|
||||
}
|
||||
|
||||
var axisEventData = GetAxisEventData(movement.x, movement.y, 0.6f);
|
||||
|
||||
if (axisEventData.moveDir != MoveDirection.None)
|
||||
{
|
||||
ExecuteEvents.Execute(eventSystem.currentSelectedGameObject, axisEventData, ExecuteEvents.moveHandler);
|
||||
if (!similarDir)
|
||||
m_ConsecutiveMoveCount = 0;
|
||||
m_ConsecutiveMoveCount++;
|
||||
m_PrevActionTime = time;
|
||||
m_LastMoveVector = movement;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ConsecutiveMoveCount = 0;
|
||||
}
|
||||
|
||||
return axisEventData.used;
|
||||
}
|
||||
|
||||
protected void ProcessMouseEvent()
|
||||
{
|
||||
ProcessMouseEvent(0);
|
||||
}
|
||||
|
||||
[Obsolete("This method is no longer checked, overriding it with return true does nothing!")]
|
||||
protected virtual bool ForceAutoSelect()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process all mouse events.
|
||||
/// </summary>
|
||||
protected void ProcessMouseEvent(int id)
|
||||
{
|
||||
var mouseData = GetMousePointerEventData(id);
|
||||
var leftButtonData = mouseData.GetButtonState(PointerEventData.InputButton.Left).eventData;
|
||||
|
||||
m_CurrentFocusedGameObject = leftButtonData.buttonData.pointerCurrentRaycast.gameObject;
|
||||
|
||||
// Process the first mouse button fully
|
||||
ProcessMousePress(leftButtonData);
|
||||
ProcessMove(leftButtonData.buttonData);
|
||||
ProcessDrag(leftButtonData.buttonData);
|
||||
|
||||
// Now process right / middle clicks
|
||||
ProcessMousePress(mouseData.GetButtonState(PointerEventData.InputButton.Right).eventData);
|
||||
ProcessDrag(mouseData.GetButtonState(PointerEventData.InputButton.Right).eventData.buttonData);
|
||||
ProcessMousePress(mouseData.GetButtonState(PointerEventData.InputButton.Middle).eventData);
|
||||
ProcessDrag(mouseData.GetButtonState(PointerEventData.InputButton.Middle).eventData.buttonData);
|
||||
|
||||
if (!Mathf.Approximately(leftButtonData.buttonData.scrollDelta.sqrMagnitude, 0.0f))
|
||||
{
|
||||
var scrollHandler = ExecuteEvents.GetEventHandler<IScrollHandler>(leftButtonData.buttonData.pointerCurrentRaycast.gameObject);
|
||||
ExecuteEvents.ExecuteHierarchy(scrollHandler, leftButtonData.buttonData, ExecuteEvents.scrollHandler);
|
||||
}
|
||||
}
|
||||
|
||||
protected bool SendUpdateEventToSelectedObject()
|
||||
{
|
||||
if (eventSystem.currentSelectedGameObject == null)
|
||||
return false;
|
||||
|
||||
var data = GetBaseEventData();
|
||||
ExecuteEvents.Execute(eventSystem.currentSelectedGameObject, data, ExecuteEvents.updateSelectedHandler);
|
||||
return data.used;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate and process any mouse button state changes.
|
||||
/// </summary>
|
||||
protected void ProcessMousePress(MouseButtonEventData data)
|
||||
{
|
||||
var pointerEvent = data.buttonData;
|
||||
var currentOverGo = pointerEvent.pointerCurrentRaycast.gameObject;
|
||||
|
||||
// PointerDown notification
|
||||
if (data.PressedThisFrame())
|
||||
{
|
||||
pointerEvent.eligibleForClick = true;
|
||||
pointerEvent.delta = Vector2.zero;
|
||||
pointerEvent.dragging = false;
|
||||
pointerEvent.useDragThreshold = true;
|
||||
pointerEvent.pressPosition = pointerEvent.position;
|
||||
pointerEvent.pointerPressRaycast = pointerEvent.pointerCurrentRaycast;
|
||||
|
||||
DeselectIfSelectionChanged(currentOverGo, pointerEvent);
|
||||
|
||||
// search for the control that will receive the press
|
||||
// if we can't find a press handler set the press
|
||||
// handler to be what would receive a click.
|
||||
var newPressed = ExecuteEvents.ExecuteHierarchy(currentOverGo, pointerEvent, ExecuteEvents.pointerDownHandler);
|
||||
var newClick = ExecuteEvents.GetEventHandler<IPointerClickHandler>(currentOverGo);
|
||||
|
||||
// didnt find a press handler... search for a click handler
|
||||
if (newPressed == null)
|
||||
newPressed = newClick;
|
||||
|
||||
// Debug.Log("Pressed: " + newPressed);
|
||||
|
||||
float time = Time.unscaledTime;
|
||||
|
||||
if (newPressed == pointerEvent.lastPress)
|
||||
{
|
||||
var diffTime = time - pointerEvent.clickTime;
|
||||
if (diffTime < 0.3f)
|
||||
++pointerEvent.clickCount;
|
||||
else
|
||||
pointerEvent.clickCount = 1;
|
||||
|
||||
pointerEvent.clickTime = time;
|
||||
}
|
||||
else
|
||||
{
|
||||
pointerEvent.clickCount = 1;
|
||||
}
|
||||
|
||||
pointerEvent.pointerPress = newPressed;
|
||||
pointerEvent.rawPointerPress = currentOverGo;
|
||||
pointerEvent.pointerClick = newClick;
|
||||
|
||||
pointerEvent.clickTime = time;
|
||||
|
||||
// Save the drag handler as well
|
||||
pointerEvent.pointerDrag = ExecuteEvents.GetEventHandler<IDragHandler>(currentOverGo);
|
||||
|
||||
if (pointerEvent.pointerDrag != null)
|
||||
ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.initializePotentialDrag);
|
||||
|
||||
m_InputPointerEvent = pointerEvent;
|
||||
}
|
||||
|
||||
// PointerUp notification
|
||||
if (data.ReleasedThisFrame())
|
||||
{
|
||||
ReleaseMouse(pointerEvent, currentOverGo);
|
||||
}
|
||||
}
|
||||
|
||||
protected GameObject GetCurrentFocusedGameObject()
|
||||
{
|
||||
return m_CurrentFocusedGameObject;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4f231c4fb786f3946a6b90b886c48677
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,266 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace UnityEngine.EventSystems
|
||||
{
|
||||
[Obsolete("TouchInputModule is no longer required as Touch input is now handled in StandaloneInputModule.")]
|
||||
[AddComponentMenu("Event/Touch Input Module")]
|
||||
public class TouchInputModule : PointerInputModule
|
||||
{
|
||||
protected TouchInputModule()
|
||||
{}
|
||||
|
||||
private Vector2 m_LastMousePosition;
|
||||
private Vector2 m_MousePosition;
|
||||
|
||||
private PointerEventData m_InputPointerEvent;
|
||||
|
||||
[SerializeField]
|
||||
[FormerlySerializedAs("m_AllowActivationOnStandalone")]
|
||||
private bool m_ForceModuleActive;
|
||||
|
||||
[Obsolete("allowActivationOnStandalone has been deprecated. Use forceModuleActive instead (UnityUpgradable) -> forceModuleActive")]
|
||||
public bool allowActivationOnStandalone
|
||||
{
|
||||
get { return m_ForceModuleActive; }
|
||||
set { m_ForceModuleActive = value; }
|
||||
}
|
||||
|
||||
public bool forceModuleActive
|
||||
{
|
||||
get { return m_ForceModuleActive; }
|
||||
set { m_ForceModuleActive = value; }
|
||||
}
|
||||
|
||||
public override void UpdateModule()
|
||||
{
|
||||
if (!eventSystem.isFocused)
|
||||
{
|
||||
if (m_InputPointerEvent != null && m_InputPointerEvent.pointerDrag != null && m_InputPointerEvent.dragging)
|
||||
ExecuteEvents.Execute(m_InputPointerEvent.pointerDrag, m_InputPointerEvent, ExecuteEvents.endDragHandler);
|
||||
|
||||
m_InputPointerEvent = null;
|
||||
}
|
||||
|
||||
m_LastMousePosition = m_MousePosition;
|
||||
m_MousePosition = input.mousePosition;
|
||||
}
|
||||
|
||||
public override bool IsModuleSupported()
|
||||
{
|
||||
return forceModuleActive || input.touchSupported;
|
||||
}
|
||||
|
||||
public override bool ShouldActivateModule()
|
||||
{
|
||||
if (!base.ShouldActivateModule())
|
||||
return false;
|
||||
|
||||
if (m_ForceModuleActive)
|
||||
return true;
|
||||
|
||||
if (UseFakeInput())
|
||||
{
|
||||
bool wantsEnable = input.GetMouseButtonDown(0);
|
||||
|
||||
wantsEnable |= (m_MousePosition - m_LastMousePosition).sqrMagnitude > 0.0f;
|
||||
return wantsEnable;
|
||||
}
|
||||
|
||||
return input.touchCount > 0;
|
||||
}
|
||||
|
||||
private bool UseFakeInput()
|
||||
{
|
||||
return !input.touchSupported;
|
||||
}
|
||||
|
||||
public override void Process()
|
||||
{
|
||||
if (UseFakeInput())
|
||||
FakeTouches();
|
||||
else
|
||||
ProcessTouchEvents();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For debugging touch-based devices using the mouse.
|
||||
/// </summary>
|
||||
private void FakeTouches()
|
||||
{
|
||||
var pointerData = GetMousePointerEventData(0);
|
||||
|
||||
var leftPressData = pointerData.GetButtonState(PointerEventData.InputButton.Left).eventData;
|
||||
|
||||
// fake touches... on press clear delta
|
||||
if (leftPressData.PressedThisFrame())
|
||||
leftPressData.buttonData.delta = Vector2.zero;
|
||||
|
||||
ProcessTouchPress(leftPressData.buttonData, leftPressData.PressedThisFrame(), leftPressData.ReleasedThisFrame());
|
||||
|
||||
// only process move if we are pressed...
|
||||
if (input.GetMouseButton(0))
|
||||
{
|
||||
ProcessMove(leftPressData.buttonData);
|
||||
ProcessDrag(leftPressData.buttonData);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process all touch events.
|
||||
/// </summary>
|
||||
private void ProcessTouchEvents()
|
||||
{
|
||||
for (int i = 0; i < input.touchCount; ++i)
|
||||
{
|
||||
Touch touch = input.GetTouch(i);
|
||||
|
||||
if (touch.type == TouchType.Indirect)
|
||||
continue;
|
||||
|
||||
bool released;
|
||||
bool pressed;
|
||||
var pointer = GetTouchPointerEventData(touch, out pressed, out released);
|
||||
|
||||
ProcessTouchPress(pointer, pressed, released);
|
||||
|
||||
if (!released)
|
||||
{
|
||||
ProcessMove(pointer);
|
||||
ProcessDrag(pointer);
|
||||
}
|
||||
else
|
||||
RemovePointerData(pointer);
|
||||
}
|
||||
}
|
||||
|
||||
protected void ProcessTouchPress(PointerEventData pointerEvent, bool pressed, bool released)
|
||||
{
|
||||
var currentOverGo = pointerEvent.pointerCurrentRaycast.gameObject;
|
||||
|
||||
// PointerDown notification
|
||||
if (pressed)
|
||||
{
|
||||
pointerEvent.eligibleForClick = true;
|
||||
pointerEvent.delta = Vector2.zero;
|
||||
pointerEvent.dragging = false;
|
||||
pointerEvent.useDragThreshold = true;
|
||||
pointerEvent.pressPosition = pointerEvent.position;
|
||||
pointerEvent.pointerPressRaycast = pointerEvent.pointerCurrentRaycast;
|
||||
|
||||
DeselectIfSelectionChanged(currentOverGo, pointerEvent);
|
||||
|
||||
if (pointerEvent.pointerEnter != currentOverGo)
|
||||
{
|
||||
// send a pointer enter to the touched element if it isn't the one to select...
|
||||
HandlePointerExitAndEnter(pointerEvent, currentOverGo);
|
||||
pointerEvent.pointerEnter = currentOverGo;
|
||||
}
|
||||
|
||||
// search for the control that will receive the press
|
||||
// if we can't find a press handler set the press
|
||||
// handler to be what would receive a click.
|
||||
var newPressed = ExecuteEvents.ExecuteHierarchy(currentOverGo, pointerEvent, ExecuteEvents.pointerDownHandler);
|
||||
|
||||
// didnt find a press handler... search for a click handler
|
||||
if (newPressed == null)
|
||||
newPressed = ExecuteEvents.GetEventHandler<IPointerClickHandler>(currentOverGo);
|
||||
|
||||
// Debug.Log("Pressed: " + newPressed);
|
||||
|
||||
float time = Time.unscaledTime;
|
||||
|
||||
if (newPressed == pointerEvent.lastPress)
|
||||
{
|
||||
var diffTime = time - pointerEvent.clickTime;
|
||||
if (diffTime < 0.3f)
|
||||
++pointerEvent.clickCount;
|
||||
else
|
||||
pointerEvent.clickCount = 1;
|
||||
|
||||
pointerEvent.clickTime = time;
|
||||
}
|
||||
else
|
||||
{
|
||||
pointerEvent.clickCount = 1;
|
||||
}
|
||||
|
||||
pointerEvent.pointerPress = newPressed;
|
||||
pointerEvent.rawPointerPress = currentOverGo;
|
||||
|
||||
pointerEvent.clickTime = time;
|
||||
|
||||
// Save the drag handler as well
|
||||
pointerEvent.pointerDrag = ExecuteEvents.GetEventHandler<IDragHandler>(currentOverGo);
|
||||
|
||||
if (pointerEvent.pointerDrag != null)
|
||||
ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.initializePotentialDrag);
|
||||
|
||||
m_InputPointerEvent = pointerEvent;
|
||||
}
|
||||
|
||||
// PointerUp notification
|
||||
if (released)
|
||||
{
|
||||
// Debug.Log("Executing pressup on: " + pointer.pointerPress);
|
||||
ExecuteEvents.Execute(pointerEvent.pointerPress, pointerEvent, ExecuteEvents.pointerUpHandler);
|
||||
|
||||
// Debug.Log("KeyCode: " + pointer.eventData.keyCode);
|
||||
|
||||
// see if we mouse up on the same element that we clicked on...
|
||||
var pointerUpHandler = ExecuteEvents.GetEventHandler<IPointerClickHandler>(currentOverGo);
|
||||
|
||||
// PointerClick and Drop events
|
||||
if (pointerEvent.pointerPress == pointerUpHandler && pointerEvent.eligibleForClick)
|
||||
{
|
||||
ExecuteEvents.Execute(pointerEvent.pointerPress, pointerEvent, ExecuteEvents.pointerClickHandler);
|
||||
}
|
||||
else if (pointerEvent.pointerDrag != null && pointerEvent.dragging)
|
||||
{
|
||||
ExecuteEvents.ExecuteHierarchy(currentOverGo, pointerEvent, ExecuteEvents.dropHandler);
|
||||
}
|
||||
|
||||
pointerEvent.eligibleForClick = false;
|
||||
pointerEvent.pointerPress = null;
|
||||
pointerEvent.rawPointerPress = null;
|
||||
|
||||
if (pointerEvent.pointerDrag != null && pointerEvent.dragging)
|
||||
ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.endDragHandler);
|
||||
|
||||
pointerEvent.dragging = false;
|
||||
pointerEvent.pointerDrag = null;
|
||||
|
||||
// send exit events as we need to simulate this on touch up on touch device
|
||||
ExecuteEvents.ExecuteHierarchy(pointerEvent.pointerEnter, pointerEvent, ExecuteEvents.pointerExitHandler);
|
||||
pointerEvent.pointerEnter = null;
|
||||
|
||||
m_InputPointerEvent = pointerEvent;
|
||||
}
|
||||
}
|
||||
|
||||
public override void DeactivateModule()
|
||||
{
|
||||
base.DeactivateModule();
|
||||
ClearSelection();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine(UseFakeInput() ? "Input: Faked" : "Input: Touch");
|
||||
if (UseFakeInput())
|
||||
{
|
||||
var pointerData = GetLastPointerEventData(kMouseLeftId);
|
||||
if (pointerData != null)
|
||||
sb.AppendLine(pointerData.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var pointerEventData in m_PointerData)
|
||||
sb.AppendLine(pointerEventData.ToString());
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2d49b7c1bcd2e07499844da127be038d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,569 @@
|
|||
namespace UnityEngine.EventSystems
|
||||
{
|
||||
/// <summary>
|
||||
/// This is an 4 direction movement enum.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// MoveDirection provides a way of switching between moving states. You must assign these states to actions, such as moving the GameObject by an up vector when in the Up state.
|
||||
/// Having states like these are easier to identify than always having to include a large amount of vectors and calculations.Instead, you define what you want the state to do in only one part, and switch to the appropriate state when it is needed.
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// <![CDATA[
|
||||
/// //This is a full example of how a GameObject changes direction using MoveDirection states
|
||||
/// //Assign this script to a visible GameObject (with a Rigidbody attached) to see it in action
|
||||
///
|
||||
/// using UnityEngine;
|
||||
/// using UnityEngine.EventSystems;
|
||||
///
|
||||
/// public class Example : MonoBehaviour
|
||||
/// {
|
||||
/// Vector3 m_StartPosition, m_StartForce;
|
||||
/// Rigidbody m_Rigidbody;
|
||||
/// //Use Enum for easy switching between direction states
|
||||
/// MoveDirection m_MoveDirection;
|
||||
///
|
||||
/// //Use these Vectors for moving Rigidbody components
|
||||
/// Vector3 m_ResetVector;
|
||||
/// Vector3 m_UpVector;
|
||||
/// Vector3 m_RightVector;
|
||||
/// const float speed = 5.0f;
|
||||
///
|
||||
/// void Start()
|
||||
/// {
|
||||
/// //You get the Rigidbody component attached to the GameObject
|
||||
/// m_Rigidbody = GetComponent<Rigidbody>();
|
||||
/// //This starts with the Rigidbody not moving in any direction at all
|
||||
/// m_MoveDirection = MoveDirection.None;
|
||||
///
|
||||
/// //These are the GameObject’s starting position and Rigidbody position
|
||||
/// m_StartPosition = transform.position;
|
||||
/// m_StartForce = m_Rigidbody.transform.position;
|
||||
///
|
||||
/// //This Vector is set to 1 in the y axis (for moving upwards)
|
||||
/// m_UpVector = Vector3.up;
|
||||
/// //This Vector is set to 1 in the x axis (for moving in the right direction)
|
||||
/// m_RightVector = Vector3.right;
|
||||
/// //This Vector is zeroed out for when the Rigidbody should not move
|
||||
/// m_ResetVector = Vector3.zero;
|
||||
/// }
|
||||
///
|
||||
/// void Update()
|
||||
/// {
|
||||
/// //This switches the direction depending on button presses
|
||||
/// switch (m_MoveDirection)
|
||||
/// {
|
||||
/// //The starting state which resets the object
|
||||
/// case MoveDirection.None:
|
||||
/// //Reset to the starting position of the GameObject and Rigidbody
|
||||
/// transform.position = m_StartPosition;
|
||||
/// m_Rigidbody.transform.position = m_StartForce;
|
||||
/// //This resets the velocity of the Rigidbody
|
||||
/// m_Rigidbody.velocity = m_ResetVector;
|
||||
/// break;
|
||||
///
|
||||
/// //This is for moving in an upwards direction
|
||||
/// case MoveDirection.Up:
|
||||
/// //Change the velocity so that the Rigidbody travels upwards
|
||||
/// m_Rigidbody.velocity = m_UpVector * speed;
|
||||
/// break;
|
||||
///
|
||||
/// //This is for moving left
|
||||
/// case MoveDirection.Left:
|
||||
/// //This moves the Rigidbody to the left (minus right Vector)
|
||||
/// m_Rigidbody.velocity = -m_RightVector * speed;
|
||||
/// break;
|
||||
///
|
||||
/// //This is for moving right
|
||||
/// case MoveDirection.Right:
|
||||
/// //This moves the Rigidbody to the right
|
||||
/// m_Rigidbody.velocity = m_RightVector * speed;
|
||||
/// break;
|
||||
///
|
||||
/// //This is for moving down
|
||||
/// case MoveDirection.Down:
|
||||
/// //This moves the Rigidbody down
|
||||
/// m_Rigidbody.velocity = -m_UpVector * speed;
|
||||
/// break;
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// void OnGUI()
|
||||
/// {
|
||||
/// //Press the reset Button to switch to no mode
|
||||
/// if (GUI.Button(new Rect(100, 0, 150, 30), "Reset"))
|
||||
/// {
|
||||
/// //Switch to start/reset case
|
||||
/// m_MoveDirection = MoveDirection.None;
|
||||
/// }
|
||||
///
|
||||
/// //Press the Left button to switch the Rigidbody direction to the left
|
||||
/// if (GUI.Button(new Rect(100, 30, 150, 30), "Move Left"))
|
||||
/// {
|
||||
/// //Switch to the left direction
|
||||
/// m_MoveDirection = MoveDirection.Left;
|
||||
/// }
|
||||
///
|
||||
/// //Press the Up button to switch the Rigidbody direction to upwards
|
||||
/// if (GUI.Button(new Rect(100, 60, 150, 30), "Move Up"))
|
||||
/// {
|
||||
/// //Switch to Up Direction
|
||||
/// m_MoveDirection = MoveDirection.Up;
|
||||
/// }
|
||||
///
|
||||
/// //Press the Down button to switch the direction to down
|
||||
/// if (GUI.Button(new Rect(100, 90, 150, 30), "Move Down"))
|
||||
/// {
|
||||
/// //Switch to Down Direction
|
||||
/// m_MoveDirection = MoveDirection.Down;
|
||||
/// }
|
||||
///
|
||||
/// //Press the right button to switch to the right direction
|
||||
/// if (GUI.Button(new Rect(100, 120, 150, 30), "Move Right"))
|
||||
/// {
|
||||
/// //Switch to Right Direction
|
||||
/// m_MoveDirection = MoveDirection.Right;
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ]]>
|
||||
///</code>
|
||||
/// </example>
|
||||
public enum MoveDirection
|
||||
{
|
||||
/// <summary>
|
||||
/// This is the Left state of MoveDirection. Assign functionality for moving to the left.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Use the Left state for an easily identifiable way of moving a GameObject to the left (-1 , 0 , 0). This is a state without any predefined functionality. Before using this state, you should define what your GameObject will do in code.
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// <![CDATA[
|
||||
/// //Assign this script to a visible GameObject (with a Rigidbody attached) to see this in action
|
||||
///
|
||||
/// using UnityEngine;
|
||||
/// using UnityEngine.EventSystems;
|
||||
///
|
||||
/// public class Example : MonoBehaviour
|
||||
/// {
|
||||
/// Vector3 m_StartPosition, m_StartForce;
|
||||
/// Rigidbody m_Rigidbody;
|
||||
/// //Use Enum for easy switching between direction states
|
||||
/// MoveDirection m_MoveDirection;
|
||||
///
|
||||
/// //Use these Vectors for moving Rigidbody components
|
||||
/// Vector3 m_ResetVector;
|
||||
/// Vector3 m_RightVector;
|
||||
/// const float speed = 5.0f;
|
||||
///
|
||||
/// void Start()
|
||||
/// {
|
||||
/// //You get the Rigidbody component attached to the GameObject
|
||||
/// m_Rigidbody = GetComponent<Rigidbody>();
|
||||
/// //This starts with the Rigidbody not moving in any direction at all
|
||||
/// m_MoveDirection = MoveDirection.None;
|
||||
///
|
||||
/// //These are the GameObject’s starting position and Rigidbody position
|
||||
/// m_StartPosition = transform.position;
|
||||
/// m_StartForce = m_Rigidbody.transform.position;
|
||||
///
|
||||
/// //This Vector is set to 1 in the x axis (for moving in the right direction)
|
||||
/// m_RightVector = Vector3.right;
|
||||
/// //This Vector is zeroed out for when the Rigidbody should not move
|
||||
/// m_ResetVector = Vector3.zero;
|
||||
/// }
|
||||
///
|
||||
/// void Update()
|
||||
/// {
|
||||
/// //This switches the direction depending on button presses
|
||||
/// switch (m_MoveDirection)
|
||||
/// {
|
||||
/// //The starting state which resets the object
|
||||
/// case MoveDirection.None:
|
||||
/// //Reset to the starting position of the GameObject and Rigidbody
|
||||
/// transform.position = m_StartPosition;
|
||||
/// m_Rigidbody.transform.position = m_StartForce;
|
||||
/// //This resets the velocity of the Rigidbody
|
||||
/// m_Rigidbody.velocity = m_ResetVector;
|
||||
/// break;
|
||||
///
|
||||
/// //This is for moving left
|
||||
/// case MoveDirection.Left:
|
||||
/// //This moves the Rigidbody to the left (minus right Vector)
|
||||
/// m_Rigidbody.velocity = -m_RightVector * speed;
|
||||
/// break;
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// void OnGUI()
|
||||
/// {
|
||||
/// //Press the reset Button to switch to no mode
|
||||
/// if (GUI.Button(new Rect(100, 0, 150, 30), "Reset"))
|
||||
/// {
|
||||
/// //Switch to start/reset case
|
||||
/// m_MoveDirection = MoveDirection.None;
|
||||
/// }
|
||||
///
|
||||
/// //Press the Left button to switch the Rigidbody direction to the left
|
||||
/// if (GUI.Button(new Rect(100, 30, 150, 30), "Move Left"))
|
||||
/// {
|
||||
/// //Switch to the left direction
|
||||
/// m_MoveDirection = MoveDirection.Left;
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ]]>
|
||||
///</code>
|
||||
/// </example>
|
||||
Left,
|
||||
|
||||
/// <summary>
|
||||
/// This is the Up state of MoveDirection. Assign functionality for moving in an upward direction.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Use the Up state for an easily identifiable way of moving a GameObject upwards (0 , 1 , 0). This is a state without any predefined functionality. Before using this state, you should define what your GameObject will do in code.
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// <![CDATA[
|
||||
/// //Attach this script to a GameObject with a Rigidbody component. Press the "Move Up" button in Game view to see it in action.
|
||||
///
|
||||
/// using UnityEngine;
|
||||
/// using UnityEngine.EventSystems;
|
||||
///
|
||||
/// public class Example : MonoBehaviour
|
||||
/// {
|
||||
/// Vector3 m_StartPosition, m_StartForce;
|
||||
/// Rigidbody m_Rigidbody;
|
||||
/// //Use Enum for easy switching between direction states
|
||||
/// MoveDirection m_MoveDirection;
|
||||
///
|
||||
/// //Use these Vectors for moving Rigidbody components
|
||||
/// Vector3 m_ResetVector;
|
||||
/// Vector3 m_UpVector;
|
||||
/// const float speed = 10.0f;
|
||||
///
|
||||
/// void Start()
|
||||
/// {
|
||||
/// //You get the Rigidbody component attached to the GameObject
|
||||
/// m_Rigidbody = GetComponent<Rigidbody>();
|
||||
/// //This starts with the Rigidbody not moving in any direction at all
|
||||
/// m_MoveDirection = MoveDirection.None;
|
||||
///
|
||||
/// //These are the GameObject’s starting position and Rigidbody position
|
||||
/// m_StartPosition = transform.position;
|
||||
/// m_StartForce = m_Rigidbody.transform.position;
|
||||
///
|
||||
/// //This Vector is set to 1 in the y axis (for moving upwards)
|
||||
/// m_UpVector = Vector3.up;
|
||||
/// //This Vector is zeroed out for when the Rigidbody should not move
|
||||
/// m_ResetVector = Vector3.zero;
|
||||
/// }
|
||||
///
|
||||
/// void Update()
|
||||
/// {
|
||||
/// //This switches the direction depending on button presses
|
||||
/// switch (m_MoveDirection)
|
||||
/// {
|
||||
/// //The starting state which resets the object
|
||||
/// case MoveDirection.None:
|
||||
/// //Reset to the starting position of the GameObject and Rigidbody
|
||||
/// transform.position = m_StartPosition;
|
||||
/// m_Rigidbody.transform.position = m_StartForce;
|
||||
/// //This resets the velocity of the Rigidbody
|
||||
/// m_Rigidbody.velocity = m_ResetVector;
|
||||
/// break;
|
||||
///
|
||||
/// //This is for moving in an upwards direction
|
||||
/// case MoveDirection.Up:
|
||||
/// //Change the velocity so that the Rigidbody travels upwards
|
||||
/// m_Rigidbody.velocity = m_UpVector * speed;
|
||||
/// break;
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// void OnGUI()
|
||||
/// {
|
||||
/// //Press the reset Button to switch to no mode
|
||||
/// if (GUI.Button(new Rect(100, 0, 150, 30), "Reset"))
|
||||
/// {
|
||||
/// //Switch to start/reset case
|
||||
/// m_MoveDirection = MoveDirection.None;
|
||||
/// }
|
||||
///
|
||||
/// //Press the Up button to switch the Rigidbody direction to upwards
|
||||
/// if (GUI.Button(new Rect(100, 60, 150, 30), "Move Up"))
|
||||
/// {
|
||||
/// //Switch to Up Direction
|
||||
/// m_MoveDirection = MoveDirection.Up;
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ]]>
|
||||
///</code>
|
||||
/// </example>
|
||||
Up,
|
||||
|
||||
/// <summary>
|
||||
/// This is the Right state of MoveDirection. Assign functionality for moving to the right.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Use the Right state for an easily identifiable way of moving a GameObject to the right (1 , 0 , 0). This is a state without any predefined functionality. Before using this state, you should define what your GameObject will do in code.
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// <![CDATA[
|
||||
/// //Attach this script to a GameObject with a Rigidbody component. Press the "Move Right" button in Game view to see it in action.
|
||||
///
|
||||
/// using UnityEngine;
|
||||
/// using UnityEngine.EventSystems;
|
||||
///
|
||||
/// public class MoveDirectionExample : MonoBehaviour
|
||||
/// {
|
||||
/// Vector3 m_StartPosition, m_StartForce;
|
||||
/// Rigidbody m_Rigidbody;
|
||||
/// //Use Enum for easy switching between direction states
|
||||
/// MoveDirection m_MoveDirection;
|
||||
///
|
||||
/// //Use these Vectors for moving Rigidbody components
|
||||
/// Vector3 m_ResetVector;
|
||||
/// Vector3 m_RightVector;
|
||||
/// const float speed = 5.0f;
|
||||
///
|
||||
/// void Start()
|
||||
/// {
|
||||
/// //You get the Rigidbody component attached to the GameObject
|
||||
/// m_Rigidbody = GetComponent<Rigidbody>();
|
||||
/// //This starts with the Rigidbody not moving in any direction at all
|
||||
/// m_MoveDirection = MoveDirection.None;
|
||||
///
|
||||
/// //These are the GameObject’s starting position and Rigidbody position
|
||||
/// m_StartPosition = transform.position;
|
||||
/// m_StartForce = m_Rigidbody.transform.position;
|
||||
///
|
||||
/// //This Vector is set to 1 in the x axis (for moving in the right direction)
|
||||
/// m_RightVector = Vector3.right;
|
||||
/// //This Vector is zeroed out for when the Rigidbody should not move
|
||||
/// m_ResetVector = Vector3.zero;
|
||||
/// }
|
||||
///
|
||||
/// void Update()
|
||||
/// {
|
||||
/// //This switches the direction depending on button presses
|
||||
/// switch (m_MoveDirection)
|
||||
/// {
|
||||
/// //The starting state which resets the object
|
||||
/// case MoveDirection.None:
|
||||
/// //Reset to the starting position of the GameObject and Rigidbody
|
||||
/// transform.position = m_StartPosition;
|
||||
/// m_Rigidbody.transform.position = m_StartForce;
|
||||
/// //This resets the velocity of the Rigidbody
|
||||
/// m_Rigidbody.velocity = m_ResetVector;
|
||||
/// break;
|
||||
///
|
||||
/// //This is for moving right
|
||||
/// case MoveDirection.Right:
|
||||
/// //This moves the Rigidbody to the right
|
||||
/// m_Rigidbody.velocity = m_RightVector * speed;
|
||||
/// break;
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// void OnGUI()
|
||||
/// {
|
||||
/// //Press the reset Button to switch to no mode
|
||||
/// if (GUI.Button(new Rect(100, 0, 150, 30), "Reset"))
|
||||
/// {
|
||||
/// //Switch to start/reset case
|
||||
/// m_MoveDirection = MoveDirection.None;
|
||||
/// }
|
||||
///
|
||||
/// //Press the Left button to switch the Rigidbody direction to the right
|
||||
/// if (GUI.Button(new Rect(100, 30, 150, 30), "Move Right"))
|
||||
/// {
|
||||
/// //Switch to the left direction
|
||||
/// m_MoveDirection = MoveDirection.Right;
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ]]>
|
||||
///</code>
|
||||
/// </example>
|
||||
Right,
|
||||
|
||||
/// <summary>
|
||||
/// The Down State of MoveDirection. Assign functionality for moving in a downward direction.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Use the Down state for an easily identifiable way of moving a GameObject downwards (0 , -1 , 0). This is a state without any predefined functionality. Before using this state, you should define what your GameObject will do in code.
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// <![CDATA[
|
||||
/// //Attach this script to a GameObject with a Rigidbody component. Press the "Move Down" button in Game view to see it in action.
|
||||
///
|
||||
/// using UnityEngine;
|
||||
/// using UnityEngine.EventSystems;
|
||||
///
|
||||
/// public class Example : MonoBehaviour
|
||||
/// {
|
||||
/// Vector3 m_StartPosition, m_StartForce;
|
||||
/// Rigidbody m_Rigidbody;
|
||||
/// //Use Enum for easy switching between direction states
|
||||
/// MoveDirection m_MoveDirection;
|
||||
///
|
||||
/// //Use these Vectors for moving Rigidbody components
|
||||
/// Vector3 m_ResetVector;
|
||||
/// Vector3 m_UpVector;
|
||||
/// const float speed = 10.0f;
|
||||
///
|
||||
/// void Start()
|
||||
/// {
|
||||
/// //You get the Rigidbody component attached to the GameObject
|
||||
/// m_Rigidbody = GetComponent<Rigidbody>();
|
||||
/// //This starts with the Rigidbody not moving in any direction at all
|
||||
/// m_MoveDirection = MoveDirection.None;
|
||||
///
|
||||
/// //These are the GameObject’s starting position and Rigidbody position
|
||||
/// m_StartPosition = transform.position;
|
||||
/// m_StartForce = m_Rigidbody.transform.position;
|
||||
///
|
||||
/// //This Vector is set to 1 in the y axis (for moving upwards)
|
||||
/// m_UpVector = Vector3.up;
|
||||
/// //This Vector is zeroed out for when the Rigidbody should not move
|
||||
/// m_ResetVector = Vector3.zero;
|
||||
/// }
|
||||
///
|
||||
/// void Update()
|
||||
/// {
|
||||
/// //This switches the direction depending on button presses
|
||||
/// switch (m_MoveDirection)
|
||||
/// {
|
||||
/// //The starting state which resets the object
|
||||
/// case MoveDirection.None:
|
||||
/// //Reset to the starting position of the GameObject and Rigidbody
|
||||
/// transform.position = m_StartPosition;
|
||||
/// m_Rigidbody.transform.position = m_StartForce;
|
||||
/// //This resets the velocity of the Rigidbody
|
||||
/// m_Rigidbody.velocity = m_ResetVector;
|
||||
/// break;
|
||||
///
|
||||
/// //This is for moving down
|
||||
/// case MoveDirection.Down:
|
||||
/// //This moves the Rigidbody down
|
||||
/// m_Rigidbody.velocity = -m_UpVector * speed;
|
||||
/// break;
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// void OnGUI()
|
||||
/// {
|
||||
/// //Press the reset Button to switch to no mode
|
||||
/// if (GUI.Button(new Rect(100, 0, 150, 30), "Reset"))
|
||||
/// {
|
||||
/// //Switch to start/reset case
|
||||
/// m_MoveDirection = MoveDirection.None;
|
||||
/// }
|
||||
///
|
||||
/// //Press the Down button to switch the direction to down
|
||||
/// if (GUI.Button(new Rect(100, 90, 150, 30), "Move Down"))
|
||||
/// {
|
||||
/// //Switch to Down Direction
|
||||
/// m_MoveDirection = MoveDirection.Down;
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ]]>
|
||||
///</code>
|
||||
/// </example>
|
||||
Down,
|
||||
|
||||
/// <summary>
|
||||
/// This is the None state. Assign functionality that stops movement.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Use the None state for an easily identifiable way of stopping, resetting or initialising a GameObject's movement. This is a state without any predefined functionality. Before using this state, you should define what your GameObject will do in code.
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// <![CDATA[
|
||||
/// //Attach this script to a GameObject with a Rigidbody attached. This script starts off on the ModeDirection.None state but changes depending on buttons you press.
|
||||
///
|
||||
/// using UnityEngine;
|
||||
/// using UnityEngine.EventSystems;
|
||||
///
|
||||
/// public class Example : MonoBehaviour
|
||||
/// {
|
||||
/// Vector3 m_StartPosition, m_StartForce;
|
||||
/// Rigidbody m_Rigidbody;
|
||||
/// //Use Enum for easy switching between direction states
|
||||
/// MoveDirection m_MoveDirection;
|
||||
///
|
||||
/// //Use these Vectors for moving Rigidbody components
|
||||
/// Vector3 m_ResetVector;
|
||||
/// Vector3 m_UpVector;
|
||||
/// const float speed = 10.0f;
|
||||
///
|
||||
/// void Start()
|
||||
/// {
|
||||
/// //You get the Rigidbody component attached to the GameObject
|
||||
/// m_Rigidbody = GetComponent<Rigidbody>();
|
||||
/// //This starts with the Rigidbody not moving in any direction at all
|
||||
/// m_MoveDirection = MoveDirection.None;
|
||||
///
|
||||
/// //These are the GameObject’s starting position and Rigidbody position
|
||||
/// m_StartPosition = transform.position;
|
||||
/// m_StartForce = m_Rigidbody.transform.position;
|
||||
///
|
||||
/// //This Vector is set to 1 in the y axis (for moving upwards)
|
||||
/// m_UpVector = Vector3.up;
|
||||
/// //This Vector is zeroed out for when the Rigidbody should not move
|
||||
/// m_ResetVector = Vector3.zero;
|
||||
/// }
|
||||
///
|
||||
/// void Update()
|
||||
/// {
|
||||
/// //This switches the direction depending on button presses
|
||||
/// switch (m_MoveDirection)
|
||||
/// {
|
||||
/// //The starting state which resets the object
|
||||
/// case MoveDirection.None:
|
||||
/// //Reset to the starting position of the GameObject and Rigidbody
|
||||
/// transform.position = m_StartPosition;
|
||||
/// m_Rigidbody.transform.position = m_StartForce;
|
||||
/// //This resets the velocity of the Rigidbody
|
||||
/// m_Rigidbody.velocity = m_ResetVector;
|
||||
/// break;
|
||||
///
|
||||
/// //This is for moving down
|
||||
/// case MoveDirection.Down:
|
||||
/// //This moves the Rigidbody down
|
||||
/// m_Rigidbody.velocity = -m_UpVector * speed;
|
||||
/// break;
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// void OnGUI()
|
||||
/// {
|
||||
/// //Press the reset Button to switch to no mode
|
||||
/// if (GUI.Button(new Rect(100, 0, 150, 30), "Reset"))
|
||||
/// {
|
||||
/// //Switch to start/reset case
|
||||
/// m_MoveDirection = MoveDirection.None;
|
||||
/// }
|
||||
///
|
||||
/// //Press the Down button to switch the direction to down
|
||||
/// if (GUI.Button(new Rect(100, 90, 150, 30), "Move Down"))
|
||||
/// {
|
||||
/// //Switch to Down Direction
|
||||
/// m_MoveDirection = MoveDirection.Down;
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ]]>
|
||||
///</code>
|
||||
/// </example>
|
||||
None
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4d2250412b81fe34abf39f246e274479
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,123 @@
|
|||
namespace UnityEngine.EventSystems
|
||||
{
|
||||
/// <summary>
|
||||
/// A hit result from a BaseRaycaster.
|
||||
/// </summary>
|
||||
public struct RaycastResult
|
||||
{
|
||||
private GameObject m_GameObject; // Game object hit by the raycast
|
||||
|
||||
/// <summary>
|
||||
/// The GameObject that was hit by the raycast.
|
||||
/// </summary>
|
||||
public GameObject gameObject
|
||||
{
|
||||
get { return m_GameObject; }
|
||||
set { m_GameObject = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// BaseRaycaster that raised the hit.
|
||||
/// </summary>
|
||||
public BaseRaycaster module;
|
||||
|
||||
/// <summary>
|
||||
/// Distance to the hit.
|
||||
/// </summary>
|
||||
public float distance;
|
||||
|
||||
/// <summary>
|
||||
/// Hit index
|
||||
/// </summary>
|
||||
public float index;
|
||||
|
||||
/// <summary>
|
||||
/// Used by raycasters where elements may have the same unit distance, but have specific ordering.
|
||||
/// </summary>
|
||||
public int depth;
|
||||
|
||||
/// <summary>
|
||||
/// The SortingLayer of the hit object.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// For UI.Graphic elements this will be the values from that graphic's Canvas
|
||||
/// For 3D objects this will always be 0.
|
||||
/// For 2D objects if a 2D Renderer (Sprite, Tilemap, SpriteShape) is attached to the same object as the hit collider that sortingLayerID will be used.
|
||||
/// </remarks>
|
||||
public int sortingLayer;
|
||||
|
||||
/// <summary>
|
||||
/// The SortingOrder for the hit object.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// For Graphic elements this will be the values from that graphics Canvas
|
||||
/// For 3D objects this will always be 0.
|
||||
/// For 2D objects if a 2D Renderer (Sprite, Tilemap, SpriteShape) is attached to the same object as the hit collider that sortingOrder will be used.
|
||||
/// </remarks>
|
||||
public int sortingOrder;
|
||||
|
||||
/// <summary>
|
||||
/// The world position of the where the raycast has hit.
|
||||
/// </summary>
|
||||
public Vector3 worldPosition;
|
||||
|
||||
/// <summary>
|
||||
/// The normal at the hit location of the raycast.
|
||||
/// </summary>
|
||||
public Vector3 worldNormal;
|
||||
|
||||
/// <summary>
|
||||
/// The screen position from which the raycast was generated.
|
||||
/// </summary>
|
||||
public Vector2 screenPosition;
|
||||
|
||||
/// <summary>
|
||||
/// The display index from which the raycast was generated.
|
||||
/// </summary>
|
||||
public int displayIndex;
|
||||
|
||||
/// <summary>
|
||||
/// Is there an associated module and a hit GameObject.
|
||||
/// </summary>
|
||||
public bool isValid
|
||||
{
|
||||
get { return module != null && gameObject != null; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset the result.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
gameObject = null;
|
||||
module = null;
|
||||
distance = 0;
|
||||
index = 0;
|
||||
depth = 0;
|
||||
sortingLayer = 0;
|
||||
sortingOrder = 0;
|
||||
worldNormal = Vector3.up;
|
||||
worldPosition = Vector3.zero;
|
||||
screenPosition = Vector3.zero;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (!isValid)
|
||||
return "";
|
||||
|
||||
return "Name: " + gameObject + "\n" +
|
||||
"module: " + module + "\n" +
|
||||
"distance: " + distance + "\n" +
|
||||
"index: " + index + "\n" +
|
||||
"depth: " + depth + "\n" +
|
||||
"worldNormal: " + worldNormal + "\n" +
|
||||
"worldPosition: " + worldPosition + "\n" +
|
||||
"screenPosition: " + screenPosition + "\n" +
|
||||
"module.sortOrderPriority: " + module.sortOrderPriority + "\n" +
|
||||
"module.renderOrderPriority: " + module.renderOrderPriority + "\n" +
|
||||
"sortingLayer: " + sortingLayer + "\n" +
|
||||
"sortingOrder: " + sortingOrder;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3550d8ec6f29ab34d895ae9a43d560c2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,29 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace UnityEngine.EventSystems
|
||||
{
|
||||
internal static class RaycasterManager
|
||||
{
|
||||
private static readonly List<BaseRaycaster> s_Raycasters = new List<BaseRaycaster>();
|
||||
|
||||
public static void AddRaycaster(BaseRaycaster baseRaycaster)
|
||||
{
|
||||
if (s_Raycasters.Contains(baseRaycaster))
|
||||
return;
|
||||
|
||||
s_Raycasters.Add(baseRaycaster);
|
||||
}
|
||||
|
||||
public static List<BaseRaycaster> GetRaycasters()
|
||||
{
|
||||
return s_Raycasters;
|
||||
}
|
||||
|
||||
public static void RemoveRaycasters(BaseRaycaster baseRaycaster)
|
||||
{
|
||||
if (!s_Raycasters.Contains(baseRaycaster))
|
||||
return;
|
||||
s_Raycasters.Remove(baseRaycaster);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 26570be2af04195458e6f1ac1f5c48e0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 46646a5562f14984690c85ee7b946bc9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,101 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UnityEngine.EventSystems
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for any RayCaster.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A Raycaster is responsible for raycasting against scene elements to determine if the cursor is over them. Default Raycasters include PhysicsRaycaster, Physics2DRaycaster, GraphicRaycaster.
|
||||
/// Custom raycasters can be added by extending this class.
|
||||
/// </remarks>
|
||||
public abstract class BaseRaycaster : UIBehaviour
|
||||
{
|
||||
private BaseRaycaster m_RootRaycaster;
|
||||
|
||||
/// <summary>
|
||||
/// Raycast against the scene.
|
||||
/// </summary>
|
||||
/// <param name="eventData">Current event data.</param>
|
||||
/// <param name="resultAppendList">List of hit Objects.</param>
|
||||
public abstract void Raycast(PointerEventData eventData, List<RaycastResult> resultAppendList);
|
||||
|
||||
/// <summary>
|
||||
/// The camera that will generate rays for this raycaster.
|
||||
/// </summary>
|
||||
public abstract Camera eventCamera { get; }
|
||||
|
||||
[Obsolete("Please use sortOrderPriority and renderOrderPriority", false)]
|
||||
public virtual int priority
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Priority of the raycaster based upon sort order.
|
||||
/// </summary>
|
||||
public virtual int sortOrderPriority
|
||||
{
|
||||
get { return int.MinValue; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Priority of the raycaster based upon render order.
|
||||
/// </summary>
|
||||
public virtual int renderOrderPriority
|
||||
{
|
||||
get { return int.MinValue; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raycaster on root canvas
|
||||
/// </summary>
|
||||
public BaseRaycaster rootRaycaster
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_RootRaycaster == null)
|
||||
{
|
||||
var baseRaycasters = GetComponentsInParent<BaseRaycaster>();
|
||||
if (baseRaycasters.Length != 0)
|
||||
m_RootRaycaster = baseRaycasters[baseRaycasters.Length - 1];
|
||||
}
|
||||
|
||||
return m_RootRaycaster;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "Name: " + gameObject + "\n" +
|
||||
"eventCamera: " + eventCamera + "\n" +
|
||||
"sortOrderPriority: " + sortOrderPriority + "\n" +
|
||||
"renderOrderPriority: " + renderOrderPriority;
|
||||
}
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
RaycasterManager.AddRaycaster(this);
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
RaycasterManager.RemoveRaycasters(this);
|
||||
base.OnDisable();
|
||||
}
|
||||
|
||||
protected override void OnCanvasHierarchyChanged()
|
||||
{
|
||||
base.OnCanvasHierarchyChanged();
|
||||
m_RootRaycaster = null;
|
||||
}
|
||||
|
||||
protected override void OnTransformParentChanged()
|
||||
{
|
||||
base.OnTransformParentChanged();
|
||||
m_RootRaycaster = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 426106349a0ff964fa4e7178c1d3a4f5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,107 @@
|
|||
using System.Collections.Generic;
|
||||
using UnityEngine.UI;
|
||||
|
||||
#if PACKAGE_TILEMAP
|
||||
using UnityEngine.Tilemaps;
|
||||
#endif
|
||||
using UnityEngine.U2D;
|
||||
|
||||
namespace UnityEngine.EventSystems
|
||||
{
|
||||
/// <summary>
|
||||
/// Simple event system using physics raycasts.
|
||||
/// </summary>
|
||||
[AddComponentMenu("Event/Physics 2D Raycaster")]
|
||||
[RequireComponent(typeof(Camera))]
|
||||
/// <summary>
|
||||
/// Raycaster for casting against 2D Physics components.
|
||||
/// </summary>
|
||||
public class Physics2DRaycaster : PhysicsRaycaster
|
||||
{
|
||||
#if PACKAGE_PHYSICS2D
|
||||
RaycastHit2D[] m_Hits;
|
||||
#endif
|
||||
|
||||
protected Physics2DRaycaster()
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Raycast against 2D elements in the scene.
|
||||
/// </summary>
|
||||
public override void Raycast(PointerEventData eventData, List<RaycastResult> resultAppendList)
|
||||
{
|
||||
#if PACKAGE_PHYSICS2D
|
||||
Ray ray = new Ray();
|
||||
float distanceToClipPlane = 0;
|
||||
int displayIndex = 0;
|
||||
if (!ComputeRayAndDistance(eventData, ref ray, ref displayIndex, ref distanceToClipPlane))
|
||||
return;
|
||||
|
||||
int hitCount = 0;
|
||||
|
||||
if (maxRayIntersections == 0)
|
||||
{
|
||||
if (ReflectionMethodsCache.Singleton.getRayIntersectionAll == null)
|
||||
return;
|
||||
m_Hits = ReflectionMethodsCache.Singleton.getRayIntersectionAll(ray, distanceToClipPlane, finalEventMask);
|
||||
hitCount = m_Hits.Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ReflectionMethodsCache.Singleton.getRayIntersectionAllNonAlloc == null)
|
||||
return;
|
||||
|
||||
if (m_LastMaxRayIntersections != m_MaxRayIntersections)
|
||||
{
|
||||
m_Hits = new RaycastHit2D[maxRayIntersections];
|
||||
m_LastMaxRayIntersections = m_MaxRayIntersections;
|
||||
}
|
||||
|
||||
hitCount = ReflectionMethodsCache.Singleton.getRayIntersectionAllNonAlloc(ray, m_Hits, distanceToClipPlane, finalEventMask);
|
||||
}
|
||||
|
||||
if (hitCount != 0)
|
||||
{
|
||||
for (int b = 0, bmax = hitCount; b < bmax; ++b)
|
||||
{
|
||||
Renderer r2d = null;
|
||||
// Case 1198442: Check for 2D renderers when filling in RaycastResults
|
||||
var rendererResult = m_Hits[b].collider.gameObject.GetComponent<Renderer>();
|
||||
if (rendererResult != null)
|
||||
{
|
||||
if (rendererResult is SpriteRenderer)
|
||||
{
|
||||
r2d = rendererResult;
|
||||
}
|
||||
#if PACKAGE_TILEMAP
|
||||
if (rendererResult is TilemapRenderer)
|
||||
{
|
||||
r2d = rendererResult;
|
||||
}
|
||||
#endif
|
||||
if (rendererResult is SpriteShapeRenderer)
|
||||
{
|
||||
r2d = rendererResult;
|
||||
}
|
||||
}
|
||||
|
||||
var result = new RaycastResult
|
||||
{
|
||||
gameObject = m_Hits[b].collider.gameObject,
|
||||
module = this,
|
||||
distance = Vector3.Distance(eventCamera.transform.position, m_Hits[b].point),
|
||||
worldPosition = m_Hits[b].point,
|
||||
worldNormal = m_Hits[b].normal,
|
||||
screenPosition = eventData.position,
|
||||
displayIndex = displayIndex,
|
||||
index = resultAppendList.Count,
|
||||
sortingLayer = r2d != null ? r2d.sortingLayerID : 0,
|
||||
sortingOrder = r2d != null ? r2d.sortingOrder : 0
|
||||
};
|
||||
resultAppendList.Add(result);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 56666c5a40171f54783dd416a44f42bf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,203 @@
|
|||
using System.Collections.Generic;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace UnityEngine.EventSystems
|
||||
{
|
||||
/// <summary>
|
||||
/// Simple event system using physics raycasts.
|
||||
/// </summary>
|
||||
[AddComponentMenu("Event/Physics Raycaster")]
|
||||
[RequireComponent(typeof(Camera))]
|
||||
/// <summary>
|
||||
/// Raycaster for casting against 3D Physics components.
|
||||
/// </summary>
|
||||
public class PhysicsRaycaster : BaseRaycaster
|
||||
{
|
||||
/// <summary>
|
||||
/// Const to use for clarity when no event mask is set
|
||||
/// </summary>
|
||||
protected const int kNoEventMaskSet = -1;
|
||||
|
||||
protected Camera m_EventCamera;
|
||||
|
||||
/// <summary>
|
||||
/// Layer mask used to filter events. Always combined with the camera's culling mask if a camera is used.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
protected LayerMask m_EventMask = kNoEventMaskSet;
|
||||
|
||||
/// <summary>
|
||||
/// The max number of intersections allowed. 0 = allocating version anything else is non alloc.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
protected int m_MaxRayIntersections = 0;
|
||||
protected int m_LastMaxRayIntersections = 0;
|
||||
|
||||
#if PACKAGE_PHYSICS
|
||||
RaycastHit[] m_Hits;
|
||||
#endif
|
||||
|
||||
protected PhysicsRaycaster()
|
||||
{}
|
||||
|
||||
public override Camera eventCamera
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_EventCamera == null)
|
||||
m_EventCamera = GetComponent<Camera>();
|
||||
return m_EventCamera ?? Camera.main;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Depth used to determine the order of event processing.
|
||||
/// </summary>
|
||||
public virtual int depth
|
||||
{
|
||||
get { return (eventCamera != null) ? (int)eventCamera.depth : 0xFFFFFF; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event mask used to determine which objects will receive events.
|
||||
/// </summary>
|
||||
public int finalEventMask
|
||||
{
|
||||
get { return (eventCamera != null) ? eventCamera.cullingMask & m_EventMask : kNoEventMaskSet; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Layer mask used to filter events. Always combined with the camera's culling mask if a camera is used.
|
||||
/// </summary>
|
||||
public LayerMask eventMask
|
||||
{
|
||||
get { return m_EventMask; }
|
||||
set { m_EventMask = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Max number of ray intersection allowed to be found.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A value of zero will represent using the allocating version of the raycast function where as any other value will use the non allocating version.
|
||||
/// </remarks>
|
||||
public int maxRayIntersections
|
||||
{
|
||||
get { return m_MaxRayIntersections; }
|
||||
set { m_MaxRayIntersections = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a ray going from camera through the event position and the distance between the near and far clipping planes along that ray.
|
||||
/// </summary>
|
||||
/// <param name="eventData">The pointer event for which we will cast a ray.</param>
|
||||
/// <param name="ray">The ray to use.</param>
|
||||
/// <param name="eventDisplayIndex">The display index used.</param>
|
||||
/// <param name="distanceToClipPlane">The distance between the near and far clipping planes along the ray.</param>
|
||||
/// <returns>True if the operation was successful. false if it was not possible to compute, such as the eventPosition being outside of the view.</returns>
|
||||
protected bool ComputeRayAndDistance(PointerEventData eventData, ref Ray ray, ref int eventDisplayIndex, ref float distanceToClipPlane)
|
||||
{
|
||||
if (eventCamera == null)
|
||||
return false;
|
||||
|
||||
var eventPosition = Display.RelativeMouseAt(eventData.position);
|
||||
if (eventPosition != Vector3.zero)
|
||||
{
|
||||
// We support multiple display and display identification based on event position.
|
||||
eventDisplayIndex = (int)eventPosition.z;
|
||||
|
||||
// Discard events that are not part of this display so the user does not interact with multiple displays at once.
|
||||
if (eventDisplayIndex != eventCamera.targetDisplay)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The multiple display system is not supported on all platforms, when it is not supported the returned position
|
||||
// will be all zeros so when the returned index is 0 we will default to the event data to be safe.
|
||||
eventPosition = eventData.position;
|
||||
}
|
||||
|
||||
// Cull ray casts that are outside of the view rect. (case 636595)
|
||||
if (!eventCamera.pixelRect.Contains(eventPosition))
|
||||
return false;
|
||||
|
||||
ray = eventCamera.ScreenPointToRay(eventPosition);
|
||||
// compensate far plane distance - see MouseEvents.cs
|
||||
float projectionDirection = ray.direction.z;
|
||||
distanceToClipPlane = Mathf.Approximately(0.0f, projectionDirection)
|
||||
? Mathf.Infinity
|
||||
: Mathf.Abs((eventCamera.farClipPlane - eventCamera.nearClipPlane) / projectionDirection);
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void Raycast(PointerEventData eventData, List<RaycastResult> resultAppendList)
|
||||
{
|
||||
#if PACKAGE_PHYSICS
|
||||
Ray ray = new Ray();
|
||||
int displayIndex = 0;
|
||||
float distanceToClipPlane = 0;
|
||||
if (!ComputeRayAndDistance(eventData, ref ray, ref displayIndex, ref distanceToClipPlane))
|
||||
return;
|
||||
|
||||
int hitCount = 0;
|
||||
|
||||
if (m_MaxRayIntersections == 0)
|
||||
{
|
||||
if (ReflectionMethodsCache.Singleton.raycast3DAll == null)
|
||||
return;
|
||||
|
||||
m_Hits = ReflectionMethodsCache.Singleton.raycast3DAll(ray, distanceToClipPlane, finalEventMask);
|
||||
hitCount = m_Hits.Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ReflectionMethodsCache.Singleton.getRaycastNonAlloc == null)
|
||||
return;
|
||||
if (m_LastMaxRayIntersections != m_MaxRayIntersections)
|
||||
{
|
||||
m_Hits = new RaycastHit[m_MaxRayIntersections];
|
||||
m_LastMaxRayIntersections = m_MaxRayIntersections;
|
||||
}
|
||||
|
||||
hitCount = ReflectionMethodsCache.Singleton.getRaycastNonAlloc(ray, m_Hits, distanceToClipPlane, finalEventMask);
|
||||
}
|
||||
|
||||
if (hitCount != 0)
|
||||
{
|
||||
if (hitCount > 1)
|
||||
System.Array.Sort(m_Hits, 0, hitCount, RaycastHitComparer.instance);
|
||||
|
||||
for (int b = 0, bmax = hitCount; b < bmax; ++b)
|
||||
{
|
||||
var result = new RaycastResult
|
||||
{
|
||||
gameObject = m_Hits[b].collider.gameObject,
|
||||
module = this,
|
||||
distance = m_Hits[b].distance,
|
||||
worldPosition = m_Hits[b].point,
|
||||
worldNormal = m_Hits[b].normal,
|
||||
screenPosition = eventData.position,
|
||||
displayIndex = displayIndex,
|
||||
index = resultAppendList.Count,
|
||||
sortingLayer = 0,
|
||||
sortingOrder = 0
|
||||
};
|
||||
resultAppendList.Add(result);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if PACKAGE_PHYSICS
|
||||
private class RaycastHitComparer : IComparer<RaycastHit>
|
||||
{
|
||||
public static RaycastHitComparer instance = new RaycastHitComparer();
|
||||
public int Compare(RaycastHit x, RaycastHit y)
|
||||
{
|
||||
return x.distance.CompareTo(y.distance);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c49b4cc203aa6414fae5c798d1d0e7d6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,76 @@
|
|||
namespace UnityEngine.EventSystems
|
||||
{
|
||||
/// <summary>
|
||||
/// Base behaviour that has protected implementations of Unity lifecycle functions.
|
||||
/// </summary>
|
||||
public abstract class UIBehaviour : MonoBehaviour
|
||||
{
|
||||
protected virtual void Awake()
|
||||
{}
|
||||
|
||||
protected virtual void OnEnable()
|
||||
{}
|
||||
|
||||
protected virtual void Start()
|
||||
{}
|
||||
|
||||
protected virtual void OnDisable()
|
||||
{}
|
||||
|
||||
protected virtual void OnDestroy()
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the GameObject and the Component are active.
|
||||
/// </summary>
|
||||
public virtual bool IsActive()
|
||||
{
|
||||
return isActiveAndEnabled;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
protected virtual void OnValidate()
|
||||
{}
|
||||
|
||||
protected virtual void Reset()
|
||||
{}
|
||||
#endif
|
||||
/// <summary>
|
||||
/// This callback is called when the dimensions of an associated RectTransform change. It is always called before Awake, OnEnable, or Start. The call is also made to all child RectTransforms, regardless of whether their dimensions change (which depends on how they are anchored).
|
||||
/// </summary>
|
||||
protected virtual void OnRectTransformDimensionsChange()
|
||||
{}
|
||||
|
||||
protected virtual void OnBeforeTransformParentChanged()
|
||||
{}
|
||||
|
||||
protected virtual void OnTransformParentChanged()
|
||||
{}
|
||||
|
||||
protected virtual void OnDidApplyAnimationProperties()
|
||||
{}
|
||||
|
||||
protected virtual void OnCanvasGroupChanged()
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the state of the parent Canvas is changed.
|
||||
/// </summary>
|
||||
protected virtual void OnCanvasHierarchyChanged()
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the native representation of the behaviour has been destroyed.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When a parent canvas is either enabled, disabled or a nested canvas's OverrideSorting is changed this function is called. You can for example use this to modify objects below a canvas that may depend on a parent canvas - for example, if a canvas is disabled you may want to halt some processing of a UI element.
|
||||
/// </remarks>
|
||||
public bool IsDestroyed()
|
||||
{
|
||||
// Workaround for Unity native side of the object
|
||||
// having been destroyed but accessing via interface
|
||||
// won't call the overloaded ==
|
||||
return this == null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0aaa057ce5566e940b18a0ccd0344693
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5dc64c943466a44498be3b620c743b45
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,436 @@
|
|||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace UnityEngine.UIElements
|
||||
{
|
||||
#if PACKAGE_UITOOLKIT
|
||||
/// <summary>
|
||||
/// Use this class to handle input and send events to UI Toolkit runtime panels.
|
||||
/// </summary>
|
||||
[AddComponentMenu("UI Toolkit/Panel Event Handler (UI Toolkit)")]
|
||||
public class PanelEventHandler : UIBehaviour, IPointerMoveHandler, IPointerUpHandler, IPointerDownHandler,
|
||||
ISubmitHandler, ICancelHandler, IMoveHandler, IScrollHandler, ISelectHandler, IDeselectHandler,
|
||||
IRuntimePanelComponent
|
||||
{
|
||||
private BaseRuntimePanel m_Panel;
|
||||
|
||||
/// <summary>
|
||||
/// The panel that this component relates to. If panel is null, this component will have no effect.
|
||||
/// Will be set to null automatically if panel is Disposed from an external source.
|
||||
/// </summary>
|
||||
public IPanel panel
|
||||
{
|
||||
get => m_Panel;
|
||||
set
|
||||
{
|
||||
var newPanel = (BaseRuntimePanel)value;
|
||||
if (m_Panel != newPanel)
|
||||
{
|
||||
UnregisterCallbacks();
|
||||
m_Panel = newPanel;
|
||||
RegisterCallbacks();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private GameObject selectableGameObject => m_Panel?.selectableGameObject;
|
||||
private EventSystem eventSystem => UIElementsRuntimeUtility.activeEventSystem as EventSystem;
|
||||
|
||||
private readonly PointerEvent m_PointerEvent = new PointerEvent();
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
RegisterCallbacks();
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
base.OnDisable();
|
||||
UnregisterCallbacks();
|
||||
}
|
||||
|
||||
void RegisterCallbacks()
|
||||
{
|
||||
if (m_Panel != null)
|
||||
{
|
||||
m_Panel.destroyed += OnPanelDestroyed;
|
||||
m_Panel.visualTree.RegisterCallback<FocusEvent>(OnElementFocus, TrickleDown.TrickleDown);
|
||||
m_Panel.visualTree.RegisterCallback<BlurEvent>(OnElementBlur, TrickleDown.TrickleDown);
|
||||
}
|
||||
}
|
||||
|
||||
void UnregisterCallbacks()
|
||||
{
|
||||
if (m_Panel != null)
|
||||
{
|
||||
m_Panel.destroyed -= OnPanelDestroyed;
|
||||
m_Panel.visualTree.UnregisterCallback<FocusEvent>(OnElementFocus, TrickleDown.TrickleDown);
|
||||
m_Panel.visualTree.UnregisterCallback<BlurEvent>(OnElementBlur, TrickleDown.TrickleDown);
|
||||
}
|
||||
}
|
||||
|
||||
void OnPanelDestroyed()
|
||||
{
|
||||
panel = null;
|
||||
}
|
||||
|
||||
void OnElementFocus(FocusEvent e)
|
||||
{
|
||||
if (!m_Selecting && eventSystem != null)
|
||||
eventSystem.SetSelectedGameObject(selectableGameObject);
|
||||
}
|
||||
|
||||
void OnElementBlur(BlurEvent e)
|
||||
{
|
||||
// Important: if panel discards focus entirely, it doesn't discard EventSystem selection necessarily.
|
||||
// Also note that if we arrive here through eventSystem.SetSelectedGameObject -> OnDeselect,
|
||||
// eventSystem.currentSelectedGameObject will still have its old value and we can't reaffect it immediately.
|
||||
}
|
||||
|
||||
private bool m_Selecting;
|
||||
public void OnSelect(BaseEventData eventData)
|
||||
{
|
||||
m_Selecting = true;
|
||||
try
|
||||
{
|
||||
// This shouldn't conflict with EditorWindow calling Panel.Focus (only on Editor-type panels).
|
||||
m_Panel?.Focus();
|
||||
}
|
||||
finally
|
||||
{
|
||||
m_Selecting = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnDeselect(BaseEventData eventData)
|
||||
{
|
||||
m_Panel?.Blur();
|
||||
}
|
||||
|
||||
public void OnPointerMove(PointerEventData eventData)
|
||||
{
|
||||
if (m_Panel == null || !ReadPointerData(m_PointerEvent, eventData, true))
|
||||
return;
|
||||
|
||||
using (var e = PointerMoveEvent.GetPooled(m_PointerEvent))
|
||||
{
|
||||
SendEvent(e, eventData);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnPointerUp(PointerEventData eventData)
|
||||
{
|
||||
if (m_Panel == null || !ReadPointerData(m_PointerEvent, eventData, false))
|
||||
return;
|
||||
|
||||
using (var e = PointerUpEvent.GetPooled(m_PointerEvent))
|
||||
{
|
||||
SendEvent(e, eventData);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnPointerDown(PointerEventData eventData)
|
||||
{
|
||||
if (m_Panel == null || !ReadPointerData(m_PointerEvent, eventData, false))
|
||||
return;
|
||||
|
||||
if (eventSystem != null)
|
||||
eventSystem.SetSelectedGameObject(selectableGameObject);
|
||||
|
||||
using (var e = PointerDownEvent.GetPooled(m_PointerEvent))
|
||||
{
|
||||
SendEvent(e, eventData);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnSubmit(BaseEventData eventData)
|
||||
{
|
||||
if (m_Panel == null)
|
||||
return;
|
||||
|
||||
using (var e = NavigationSubmitEvent.GetPooled())
|
||||
{
|
||||
SendEvent(e, eventData);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnCancel(BaseEventData eventData)
|
||||
{
|
||||
if (m_Panel == null)
|
||||
return;
|
||||
|
||||
using (var e = NavigationCancelEvent.GetPooled())
|
||||
{
|
||||
SendEvent(e, eventData);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnMove(AxisEventData eventData)
|
||||
{
|
||||
if (m_Panel == null)
|
||||
return;
|
||||
|
||||
using (var e = NavigationMoveEvent.GetPooled(eventData.moveVector))
|
||||
{
|
||||
SendEvent(e, eventData);
|
||||
}
|
||||
|
||||
// TODO: if runtime panel has no internal navigation, switch to the next UGUI selectable element.
|
||||
}
|
||||
|
||||
public void OnScroll(PointerEventData eventData)
|
||||
{
|
||||
if (m_Panel == null || !ReadPointerData(m_PointerEvent, eventData, true))
|
||||
return;
|
||||
|
||||
var scrollDelta = eventData.scrollDelta;
|
||||
scrollDelta.y = -scrollDelta.y;
|
||||
|
||||
const float kPixelPerLine = 20;
|
||||
// The old input system reported scroll deltas in lines, we report pixels.
|
||||
// Need to scale as the UI system expects lines.
|
||||
scrollDelta /= kPixelPerLine;
|
||||
|
||||
using (var e = WheelEvent.GetPooled(scrollDelta, m_PointerEvent.position))
|
||||
{
|
||||
SendEvent(e, eventData);
|
||||
}
|
||||
}
|
||||
|
||||
private void SendEvent(EventBase e, BaseEventData sourceEventData)
|
||||
{
|
||||
//e.runtimeEventData = sourceEventData;
|
||||
m_Panel.SendEvent(e);
|
||||
if (e.isPropagationStopped)
|
||||
sourceEventData.Use();
|
||||
}
|
||||
|
||||
private void SendEvent(EventBase e, Event sourceEvent)
|
||||
{
|
||||
m_Panel.SendEvent(e);
|
||||
if (e.isPropagationStopped)
|
||||
sourceEvent.Use();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (m_Panel != null && eventSystem != null && eventSystem.currentSelectedGameObject == selectableGameObject)
|
||||
ProcessImguiEvents(true);
|
||||
}
|
||||
|
||||
void LateUpdate()
|
||||
{
|
||||
// Empty the Event queue, look for EventModifiers.
|
||||
ProcessImguiEvents(false);
|
||||
}
|
||||
|
||||
private Event m_Event = new Event();
|
||||
private static EventModifiers s_Modifiers = EventModifiers.None;
|
||||
|
||||
void ProcessImguiEvents(bool isSelected)
|
||||
{
|
||||
bool first = true;
|
||||
|
||||
while (Event.PopEvent(m_Event))
|
||||
{
|
||||
if (m_Event.type == EventType.Ignore || m_Event.type == EventType.Repaint ||
|
||||
m_Event.type == EventType.Layout)
|
||||
continue;
|
||||
|
||||
s_Modifiers = first ? m_Event.modifiers : (s_Modifiers | m_Event.modifiers);
|
||||
first = false;
|
||||
|
||||
if (isSelected)
|
||||
{
|
||||
ProcessKeyboardEvent(m_Event);
|
||||
|
||||
if (m_Event.type != EventType.Used)
|
||||
ProcessTabEvent(m_Event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessKeyboardEvent(Event e)
|
||||
{
|
||||
if (e.type == EventType.KeyUp)
|
||||
{
|
||||
if (e.character == '\0')
|
||||
{
|
||||
SendKeyUpEvent(e, e.keyCode, e.modifiers);
|
||||
}
|
||||
}
|
||||
else if (e.type == EventType.KeyDown)
|
||||
{
|
||||
if (e.character == '\0')
|
||||
{
|
||||
SendKeyDownEvent(e, e.keyCode, e.modifiers);
|
||||
}
|
||||
else
|
||||
{
|
||||
SendTextEvent(e, e.character, e.modifiers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: add an ITabHandler interface
|
||||
void ProcessTabEvent(Event e)
|
||||
{
|
||||
if (e.type == EventType.KeyDown && e.character == '\t')
|
||||
{
|
||||
SendTabEvent(e, e.shift ? -1 : 1);
|
||||
}
|
||||
}
|
||||
|
||||
private void SendTabEvent(Event e, int direction)
|
||||
{
|
||||
using (var ev = NavigationTabEvent.GetPooled(direction))
|
||||
{
|
||||
SendEvent(ev, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void SendKeyUpEvent(Event e, KeyCode keyCode, EventModifiers modifiers)
|
||||
{
|
||||
using (var ev = KeyUpEvent.GetPooled('\0', keyCode, modifiers))
|
||||
{
|
||||
SendEvent(ev, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void SendKeyDownEvent(Event e, KeyCode keyCode, EventModifiers modifiers)
|
||||
{
|
||||
using (var ev = KeyDownEvent.GetPooled('\0', keyCode, modifiers))
|
||||
{
|
||||
SendEvent(ev, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void SendTextEvent(Event e, char c, EventModifiers modifiers)
|
||||
{
|
||||
using (var ev = KeyDownEvent.GetPooled(c, KeyCode.None, modifiers))
|
||||
{
|
||||
SendEvent(ev, e);
|
||||
}
|
||||
}
|
||||
|
||||
private bool ReadPointerData(PointerEvent pe, PointerEventData eventData, bool isMove)
|
||||
{
|
||||
if (eventSystem == null || eventSystem.currentInputModule == null)
|
||||
return false;
|
||||
|
||||
pe.Read(this, eventData, isMove);
|
||||
|
||||
if (!m_Panel.ScreenToPanel(pe.position, pe.deltaPosition, out var panelPosition, out var panelDelta))
|
||||
return false;
|
||||
|
||||
pe.SetPosition(panelPosition, panelDelta);
|
||||
return true;
|
||||
}
|
||||
|
||||
class PointerEvent : IPointerEvent
|
||||
{
|
||||
public int pointerId { get; private set; }
|
||||
public string pointerType { get; private set; }
|
||||
public bool isPrimary { get; private set; }
|
||||
public int button { get; private set; }
|
||||
public int pressedButtons { get; private set; }
|
||||
public Vector3 position { get; private set; }
|
||||
public Vector3 localPosition { get; private set; }
|
||||
public Vector3 deltaPosition { get; private set; }
|
||||
public float deltaTime { get; private set; }
|
||||
public int clickCount { get; private set; }
|
||||
public float pressure { get; private set; }
|
||||
public float tangentialPressure { get; private set; }
|
||||
public float altitudeAngle { get; private set; }
|
||||
public float azimuthAngle { get; private set; }
|
||||
public float twist { get; private set; }
|
||||
public Vector2 radius { get; private set; }
|
||||
public Vector2 radiusVariance { get; private set; }
|
||||
public EventModifiers modifiers { get; private set; }
|
||||
|
||||
public bool shiftKey => (modifiers & EventModifiers.Shift) != 0;
|
||||
public bool ctrlKey => (modifiers & EventModifiers.Control) != 0;
|
||||
public bool commandKey => (modifiers & EventModifiers.Command) != 0;
|
||||
public bool altKey => (modifiers & EventModifiers.Alt) != 0;
|
||||
|
||||
public bool actionKey =>
|
||||
Application.platform == RuntimePlatform.OSXEditor || Application.platform == RuntimePlatform.OSXPlayer
|
||||
? commandKey
|
||||
: ctrlKey;
|
||||
|
||||
public void Read(PanelEventHandler self, PointerEventData eventData, bool isMove)
|
||||
{
|
||||
pointerId = self.eventSystem.currentInputModule.ConvertUIToolkitPointerId(eventData);
|
||||
|
||||
bool InRange(int i, int start, int count) => i >= start && i < start + count;
|
||||
|
||||
pointerType =
|
||||
InRange(pointerId, PointerId.touchPointerIdBase, PointerId.touchPointerCount) ? PointerType.touch :
|
||||
InRange(pointerId, PointerId.penPointerIdBase, PointerId.penPointerCount) ? PointerType.pen :
|
||||
PointerType.mouse;
|
||||
|
||||
isPrimary = pointerId == PointerId.mousePointerId ||
|
||||
pointerId == PointerId.touchPointerIdBase ||
|
||||
pointerId == PointerId.penPointerIdBase;
|
||||
|
||||
button = (int)eventData.button;
|
||||
pressedButtons = PointerDeviceState.GetPressedButtons(pointerId);
|
||||
clickCount = eventData.clickCount;
|
||||
|
||||
|
||||
// Flip Y axis between input and UITK
|
||||
var h = Screen.height;
|
||||
|
||||
var eventPosition = Display.RelativeMouseAt(eventData.position);
|
||||
if (eventPosition != Vector3.zero)
|
||||
{
|
||||
// We support multiple display and display identification based on event position.
|
||||
|
||||
int eventDisplayIndex = (int)eventPosition.z;
|
||||
if (eventDisplayIndex > 0 && eventDisplayIndex < Display.displays.Length)
|
||||
h = Display.displays[eventDisplayIndex].systemHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
eventPosition = eventData.position;
|
||||
}
|
||||
|
||||
var delta = eventData.delta;
|
||||
eventPosition.y = h - eventPosition.y;
|
||||
delta.y = -delta.y;
|
||||
|
||||
localPosition = position = eventPosition;
|
||||
deltaPosition = delta;
|
||||
|
||||
deltaTime = 0; //TODO: find out what's expected here. Time since last frame? Since last sent event?
|
||||
pressure = eventData.pressure;
|
||||
tangentialPressure = eventData.tangentialPressure;
|
||||
altitudeAngle = eventData.altitudeAngle;
|
||||
azimuthAngle = eventData.azimuthAngle;
|
||||
twist = eventData.twist;
|
||||
radius = eventData.radius;
|
||||
radiusVariance = eventData.radiusVariance;
|
||||
|
||||
modifiers = s_Modifiers;
|
||||
|
||||
if (isMove)
|
||||
{
|
||||
button = -1;
|
||||
clickCount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
button = button >= 0 ? button : 0;
|
||||
clickCount = Mathf.Max(1, clickCount);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetPosition(Vector3 positionOverride, Vector3 deltaOverride)
|
||||
{
|
||||
localPosition = position = positionOverride;
|
||||
deltaPosition = deltaOverride;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8a410b213209442fb15a69799f0240a5
|
||||
timeCreated: 1602089617
|
|
@ -0,0 +1,137 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace UnityEngine.UIElements
|
||||
{
|
||||
#if PACKAGE_UITOOLKIT
|
||||
/// <summary>
|
||||
/// A derived BaseRaycaster to raycast against UI Toolkit panel instances at runtime.
|
||||
/// </summary>
|
||||
[AddComponentMenu("UI Toolkit/Panel Raycaster (UI Toolkit)")]
|
||||
public class PanelRaycaster : BaseRaycaster, IRuntimePanelComponent
|
||||
{
|
||||
private BaseRuntimePanel m_Panel;
|
||||
|
||||
/// <summary>
|
||||
/// The panel that this component relates to. If panel is null, this component will have no effect.
|
||||
/// Will be set to null automatically if panel is Disposed from an external source.
|
||||
/// </summary>
|
||||
public IPanel panel
|
||||
{
|
||||
get => m_Panel;
|
||||
set
|
||||
{
|
||||
var newPanel = (BaseRuntimePanel)value;
|
||||
if (m_Panel != newPanel)
|
||||
{
|
||||
UnregisterCallbacks();
|
||||
m_Panel = newPanel;
|
||||
RegisterCallbacks();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterCallbacks()
|
||||
{
|
||||
if (m_Panel != null)
|
||||
{
|
||||
m_Panel.destroyed += OnPanelDestroyed;
|
||||
}
|
||||
}
|
||||
|
||||
void UnregisterCallbacks()
|
||||
{
|
||||
if (m_Panel != null)
|
||||
{
|
||||
m_Panel.destroyed -= OnPanelDestroyed;
|
||||
}
|
||||
}
|
||||
|
||||
void OnPanelDestroyed()
|
||||
{
|
||||
panel = null;
|
||||
}
|
||||
|
||||
private GameObject selectableGameObject => m_Panel?.selectableGameObject;
|
||||
|
||||
public override int sortOrderPriority => (int)(m_Panel?.sortingPriority ?? 0f);
|
||||
public override int renderOrderPriority => ConvertFloatBitsToInt(m_Panel?.sortingPriority ?? 0f);
|
||||
|
||||
public override void Raycast(PointerEventData eventData, List<RaycastResult> resultAppendList)
|
||||
{
|
||||
if (m_Panel == null)
|
||||
return;
|
||||
|
||||
var eventPosition = Display.RelativeMouseAt(eventData.position);
|
||||
var displayIndex = m_Panel.targetDisplay;
|
||||
|
||||
var originalEventPosition = eventPosition;
|
||||
if (eventPosition != Vector3.zero)
|
||||
{
|
||||
// We support multiple display and display identification based on event position.
|
||||
|
||||
int eventDisplayIndex = (int)eventPosition.z;
|
||||
|
||||
// Discard events that are not part of this display so the user does not interact with multiple displays at once.
|
||||
if (eventDisplayIndex != displayIndex)
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The multiple display system is not supported on all platforms, when it is not supported the returned position
|
||||
// will be all zeros so when the returned index is 0 we will default to the event data to be safe.
|
||||
eventPosition = eventData.position;
|
||||
|
||||
// We dont really know in which display the event occured. We will process the event assuming it occured in our display.
|
||||
}
|
||||
|
||||
var position = eventPosition;
|
||||
var delta = eventData.delta;
|
||||
|
||||
float h = Screen.height;
|
||||
if (displayIndex > 0 && displayIndex < Display.displays.Length)
|
||||
{
|
||||
h = Display.displays[displayIndex].systemHeight;
|
||||
}
|
||||
|
||||
position.y = h - position.y;
|
||||
delta.y = -delta.y;
|
||||
|
||||
if (!m_Panel.ScreenToPanel(position, delta, out var panelPosition, out _))
|
||||
return;
|
||||
|
||||
var pick = m_Panel.Pick(panelPosition);
|
||||
if (pick == null)
|
||||
return;
|
||||
|
||||
resultAppendList.Add(new RaycastResult
|
||||
{
|
||||
gameObject = selectableGameObject,
|
||||
module = this,
|
||||
screenPosition = eventPosition,
|
||||
displayIndex = m_Panel.targetDisplay,
|
||||
});
|
||||
}
|
||||
|
||||
public override Camera eventCamera => null;
|
||||
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Size = sizeof(int))]
|
||||
private struct FloatIntBits
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public float f;
|
||||
[FieldOffset(0)]
|
||||
public int i;
|
||||
}
|
||||
|
||||
private static int ConvertFloatBitsToInt(float f)
|
||||
{
|
||||
FloatIntBits bits = new FloatIntBits {f = f};
|
||||
return bits.i;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7a79c4e23d4d4b64bfa5fa9e6671a460
|
||||
timeCreated: 1602101961
|
Loading…
Add table
Add a link
Reference in a new issue