Created unity project

This commit is contained in:
2024-12-07 20:55:50 +01:00
parent 539250d964
commit 54fe327198
13758 changed files with 865324 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7f27709c942d91541be1fd6aa5cb3d78
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b3cdabf2f1e76854d8aab5930305d70d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b180fd8310805e44dbbef545d0231418
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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); }
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 91f495459b6e34f419ac123740d798b1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,371 @@
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>
/// The index of the display that this pointer event comes from.
/// </summary>
public int displayIndex { 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>
/// Specifies the angle of the pen relative to the X & Y axis, in radians.
/// </summary>
/// <seealso cref="UnityEngine.UIElements.IPointerEvent" />
public Vector2 tilt { get; set; }
/// <summary>
/// Specifies the state of the pen. For example, whether the pen is in contact with the screen or tablet, whether the pen is inverted, and whether buttons are pressed.
/// </summary>
/// <seealso cref="UnityEngine.UIElements.IPointerEvent" />
public PenStatus penStatus { 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; }
/// <summary>
/// Specifies in the case of a pointer exit if the pointer has fully exited the area or if it has just entered a child.
/// </summary>
public bool fullyExited { get; set; }
/// <summary>
/// Specifies in the case of a pointer enter if the pointer has entered a new area or if it has just reentered a parent after leaving a child.
/// </summary>
public bool reentered { get; set; }
/// <seealso cref="UnityEngine.UIElements.IPointerEvent" />
public PointerEventData(EventSystem eventSystem) : base(eventSystem)
{
eligibleForClick = false;
displayIndex = 0;
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;
tilt = new Vector2(0f, 0f);
penStatus = PenStatus.None;
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>Display Index:</b>");
sb.AppendLine(displayIndex.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>tilt</b>: " + tilt);
sb.AppendLine("<b>penStatus</b>: " + penStatus);
sb.AppendLine("<b>radius</b>: " + radius);
sb.AppendLine("<b>radiusVariance</b>: " + radiusVariance);
return sb.ToString();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 75df57ccb1e44c64085399277405e1ca
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,14 @@
using System;
namespace UnityEngine.EventSystems
{
[Flags]
/// <summary>
/// Enum that tracks event State.
/// </summary>
public enum EventHandle
{
Unused = 0,
Used = 1
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: db7dd43fe1278a9459cd6036f096b91d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2359c66dee10c454c97f6aea84e3fe22
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,571 @@
using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.Rendering;
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);
}
// Renderer sorting
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);
#if PACKAGE_PHYSICS2D
// Sorting group
if (lhs.sortingGroupID != SortingGroup.invalidSortingGroupID && rhs.sortingGroupID != SortingGroup.invalidSortingGroupID)
{
if (lhs.sortingGroupID != rhs.sortingGroupID)
return lhs.sortingGroupID.CompareTo(rhs.sortingGroupID);
if (lhs.sortingGroupOrder != rhs.sortingGroupOrder)
return rhs.sortingGroupOrder.CompareTo(lhs.sortingGroupOrder);
}
#endif
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);
}
// This code is disabled unless the UI Toolkit package or the com.unity.modules.uielements module are present.
// The UIElements module is always present in the Editor but it can be stripped from a project build if unused.
#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 bool m_Started;
private bool m_IsTrackingUIToolkitPanels;
private void StartTrackingUIToolkitPanels()
{
if (createUIToolkitPanelGameObjectsOnStart)
{
foreach (BaseRuntimePanel panel in UIElementsRuntimeUtility.GetSortedPlayerPanels())
{
CreateUIToolkitPanelGameObject(panel);
}
UIElementsRuntimeUtility.onCreatePanel += CreateUIToolkitPanelGameObject;
m_IsTrackingUIToolkitPanels = true;
}
}
private void StopTrackingUIToolkitPanels()
{
if (m_IsTrackingUIToolkitPanels)
{
UIElementsRuntimeUtility.onCreatePanel -= CreateUIToolkitPanelGameObject;
m_IsTrackingUIToolkitPanels = false;
}
}
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 += () => DestroyImmediate(go);
}
}
#endif
protected override void Start()
{
base.Start();
#if PACKAGE_UITOOLKIT
m_Started = true;
StartTrackingUIToolkitPanels();
#endif
}
protected override void OnEnable()
{
base.OnEnable();
m_EventSystems.Add(this);
#if PACKAGE_UITOOLKIT
if (m_Started && !m_IsTrackingUIToolkitPanels)
{
StartTrackingUIToolkitPanels();
}
if (sendUIToolkitEvents)
{
UIElementsRuntimeUtility.RegisterEventSystem(this);
}
#endif
}
protected override void OnDisable()
{
#if PACKAGE_UITOOLKIT
StopTrackingUIToolkitPanels();
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();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 76c392e42b5098c458856cdf6ecaaaa1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,358 @@
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)
{
for (int i = 0; i < triggers.Count; ++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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d0b148fe25e99eb48b9724523833bab1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3fa274f26b1574c40b949e114327022e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 623c79a1e113b4941afdbfc88d19e8fd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8e78f8a8575e4a04f8337a54e241cdc5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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 Input.mousePosition; }
}
/// <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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1511ccae7919cfc46b603b9b337fdc94
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,394 @@
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>();
/// <summary>
/// True if pointer hover events will be sent to the parent
/// </summary>
[SerializeField] private bool m_SendPointerHoverToParent = true;
//This is needed for testing
internal bool sendPointerHoverToParent { get { return m_SendPointerHoverToParent; } set { m_SendPointerHoverToParent = value; } }
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 including) 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)
{
currentPointerData.fullyExited = true;
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);
GameObject pointerParent = ((Component)newEnterTarget.GetComponentInParent<IPointerExitHandler>())?.gameObject;
// 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!
// ** or when !m_SendPointerEnterToParent, stop when meeting a gameobject with an exit event handler
Transform t = currentPointerData.pointerEnter.transform;
while (t != null)
{
// if we reach the common root break out!
if (m_SendPointerHoverToParent && commonRoot != null && commonRoot.transform == t)
break;
// if we reach a PointerExitEvent break out!
if (!m_SendPointerHoverToParent && pointerParent == t.gameObject)
break;
currentPointerData.fullyExited = t.gameObject != commonRoot && currentPointerData.pointerEnter != newEnterTarget;
ExecuteEvents.Execute(t.gameObject, currentPointerData, ExecuteEvents.pointerMoveHandler);
ExecuteEvents.Execute(t.gameObject, currentPointerData, ExecuteEvents.pointerExitHandler);
currentPointerData.hovered.Remove(t.gameObject);
if (m_SendPointerHoverToParent) t = t.parent;
// if we reach the common root break out!
if (commonRoot != null && commonRoot.transform == t)
break;
if (!m_SendPointerHoverToParent) t = t.parent;
}
}
// now issue the enter call up to but not including the common root
var oldPointerEnter = currentPointerData.pointerEnter;
currentPointerData.pointerEnter = newEnterTarget;
if (newEnterTarget != null)
{
Transform t = newEnterTarget.transform;
while (t != null)
{
currentPointerData.reentered = t.gameObject == commonRoot && t.gameObject != oldPointerEnter;
// if we are sending the event to parent, they are already in hover mode at that point. No need to bubble up the event.
if (m_SendPointerHoverToParent && currentPointerData.reentered)
break;
ExecuteEvents.Execute(t.gameObject, currentPointerData, ExecuteEvents.pointerEnterHandler);
ExecuteEvents.Execute(t.gameObject, currentPointerData, ExecuteEvents.pointerMoveHandler);
currentPointerData.hovered.Add(t.gameObject);
// stop when encountering an object with the pointerEnterHandler
if (!m_SendPointerHoverToParent && t.gameObject.GetComponent<IPointerEnterHandler>() != null)
break;
if (m_SendPointerHoverToParent) t = t.parent;
// if we reach the common root break out!
if (commonRoot != null && commonRoot.transform == t)
break;
if (!m_SendPointerHoverToParent) 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
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1ea10891dd782154ca0fb67bce9e6f72
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cbab8835092323a4389f2dc7d8f6c781
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,663 @@
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;
private const float doubleClickTime = 0.3f;
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;
}
var resetDiffTime = Time.unscaledTime - pointerEvent.clickTime;
if (resetDiffTime >= doubleClickTime)
{
pointerEvent.clickCount = 0;
}
// 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 < doubleClickTime)
++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);
var resetDiffTime = Time.unscaledTime - pointerEvent.clickTime;
if (resetDiffTime >= doubleClickTime)
{
pointerEvent.clickCount = 0;
}
// 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 < doubleClickTime)
++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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4f231c4fb786f3946a6b90b886c48677
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2d49b7c1bcd2e07499844da127be038d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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 GameObjects 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 GameObjects 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 GameObjects 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 GameObjects 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 GameObjects 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 GameObjects 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
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4d2250412b81fe34abf39f246e274479
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,143 @@
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 sorting group ID when the hit object is influenced by a SortingGroup.
/// </summary>
/// <remarks>
/// For UI.Graphic elements will always be 0.
/// For 3D objects this will always be 0.
/// For 2D objects if a SortingOrder is influencing the same object as the hit collider then the renderers sortingGroupID will be used; otherwise SortingGroup.invalidSortingGroupID.
/// </remarks>
public int sortingGroupID;
/// <summary>
/// The sorting group order when the hit object is influenced by a SortingGroup.
/// </summary>
/// <remarks>
/// For UI.Graphic elements this will always be 0.
/// For 3D objects this will always be 0.
/// For 2D objects if a SortingOrder is influencing the same object as the hit collider then the renderers sortingGroupOrder will be used.
/// </remarks>
public int sortingGroupOrder;
/// <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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3550d8ec6f29ab34d895ae9a43d560c2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,32 @@
using System.Collections.Generic;
namespace UnityEngine.EventSystems
{
public static class RaycasterManager
{
private static readonly List<BaseRaycaster> s_Raycasters = new List<BaseRaycaster>();
internal static void AddRaycaster(BaseRaycaster baseRaycaster)
{
if (s_Raycasters.Contains(baseRaycaster))
return;
s_Raycasters.Add(baseRaycaster);
}
/// <summary>
/// List of BaseRaycasters that has been registered.
/// </summary>
public static List<BaseRaycaster> GetRaycasters()
{
return s_Raycasters;
}
internal static void RemoveRaycasters(BaseRaycaster baseRaycaster)
{
if (!s_Raycasters.Contains(baseRaycaster))
return;
s_Raycasters.Remove(baseRaycaster);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 26570be2af04195458e6f1ac1f5c48e0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 46646a5562f14984690c85ee7b946bc9
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 426106349a0ff964fa4e7178c1d3a4f5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,120 @@
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine.Rendering;
#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 = m_Hits[b].distance,
worldPosition = m_Hits[b].point,
worldNormal = m_Hits[b].normal,
screenPosition = eventData.position,
displayIndex = displayIndex,
index = resultAppendList.Count,
sortingGroupID = r2d != null ? r2d.sortingGroupID : SortingGroup.invalidSortingGroupID,
sortingGroupOrder = r2d != null ? r2d.sortingGroupOrder : 0,
sortingLayer = r2d != null ? r2d.sortingLayerID : 0,
sortingOrder = r2d != null ? r2d.sortingOrder : 0
};
if (result.sortingGroupID != SortingGroup.invalidSortingGroupID &&
SortingGroup.GetSortingGroupByIndex(r2d.sortingGroupID) is SortingGroup sortingGroup)
{
// Calculate how far along the ray the sorting group is.
result.distance = Vector3.Dot(ray.direction, sortingGroup.transform.position - ray.origin);
result.sortingLayer = sortingGroup.sortingLayerID;
result.sortingOrder = sortingGroup.sortingOrder;
}
resultAppendList.Add(result);
}
}
#endif
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 56666c5a40171f54783dd416a44f42bf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,207 @@
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>();
if (m_EventCamera == null)
return Camera.main;
return m_EventCamera ;
}
}
/// <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 = MultipleDisplayUtilities.RelativeMouseAtScaled(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
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c49b4cc203aa6414fae5c798d1d0e7d6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0aaa057ce5566e940b18a0ccd0344693
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5dc64c943466a44498be3b620c743b45
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,515 @@
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace UnityEngine.UIElements
{
// This code is disabled unless the UI Toolkit package or the com.unity.modules.uielements module are present.
// The UIElements module is always present in the Editor but it can be stripped from a project build if unused.
#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,
IPointerExitHandler, IPointerEnterHandler, IRuntimePanelComponent, IPointerClickHandler
{
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 bool isCurrentFocusedPanel => m_Panel != null && eventSystem != null &&
eventSystem.currentSelectedGameObject == selectableGameObject;
private Focusable currentFocusedElement => m_Panel?.focusController.GetLeafFocusedElement();
private readonly PointerEvent m_PointerEvent = new PointerEvent();
private float m_LastClickTime = 0;
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))
return;
using (var e = PointerMoveEvent.GetPooled(m_PointerEvent))
{
SendEvent(e, eventData);
}
}
public void OnPointerUp(PointerEventData eventData)
{
if (m_Panel == null || !ReadPointerData(m_PointerEvent, eventData, PointerEventType.Up))
return;
using (var e = PointerUpEvent.GetPooled(m_PointerEvent))
{
SendEvent(e, eventData);
if (e.pressedButtons == 0)
PointerDeviceState.SetPlayerPanelWithSoftPointerCapture(e.pointerId, null);
}
}
public void OnPointerDown(PointerEventData eventData)
{
if (m_Panel == null || !ReadPointerData(m_PointerEvent, eventData, PointerEventType.Down))
return;
if (eventSystem != null)
eventSystem.SetSelectedGameObject(selectableGameObject);
using (var e = PointerDownEvent.GetPooled(m_PointerEvent))
{
SendEvent(e, eventData);
PointerDeviceState.SetPlayerPanelWithSoftPointerCapture(e.pointerId, m_Panel);
}
}
public void OnPointerExit(PointerEventData eventData)
{
if (m_Panel == null || !ReadPointerData(m_PointerEvent, eventData))
return;
// If a pointer exit is called while the pointer is still on top of this object, it means
// there's something else removing the pointer, so we might need to send a PointerCancelEvent.
// This is necessary for touch pointers that are being released, because in UGUI the object
// that was last hovered will not always be the one receiving the pointer up.
if (eventData.pointerCurrentRaycast.gameObject == gameObject &&
eventData.pointerPressRaycast.gameObject != gameObject &&
m_PointerEvent.pointerId != PointerId.mousePointerId)
{
using (var e = PointerCancelEvent.GetPooled(m_PointerEvent))
{
SendEvent(e, eventData);
if (e.pressedButtons == 0)
PointerDeviceState.SetPlayerPanelWithSoftPointerCapture(e.pointerId, null);
}
}
m_Panel.PointerLeavesPanel(m_PointerEvent.pointerId, m_PointerEvent.position);
}
public void OnPointerEnter(PointerEventData eventData)
{
if (m_Panel == null || !ReadPointerData(m_PointerEvent, eventData))
return;
m_Panel.PointerEntersPanel(m_PointerEvent.pointerId, m_PointerEvent.position);
}
public void OnPointerClick(PointerEventData eventData)
{
m_LastClickTime = Time.unscaledTime;
}
public void OnSubmit(BaseEventData eventData)
{
if (m_Panel == null)
return;
// Allow KeyDown/KeyUp events to be processed before navigation events.
var target = currentFocusedElement ?? m_Panel.visualTree;
ProcessImguiEvents(target);
using (var e = NavigationSubmitEvent.GetPooled(s_Modifiers))
{
e.target = target;
SendEvent(e, eventData);
}
}
public void OnCancel(BaseEventData eventData)
{
if (m_Panel == null)
return;
// Allow KeyDown/KeyUp events to be processed before navigation events.
var target = currentFocusedElement ?? m_Panel.visualTree;
ProcessImguiEvents(target);
using (var e = NavigationCancelEvent.GetPooled(s_Modifiers))
{
e.target = target;
SendEvent(e, eventData);
}
}
public void OnMove(AxisEventData eventData)
{
if (m_Panel == null)
return;
// Allow KeyDown/KeyUp events to be processed before navigation events.
var target = currentFocusedElement ?? m_Panel.visualTree;
ProcessImguiEvents(target);
using (var e = NavigationMoveEvent.GetPooled(eventData.moveVector, s_Modifiers))
{
e.target = target;
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))
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))
{
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);
// Don't call sourceEvent.Use() because DefaultEventSystem doesn't call it either
// and we want to have the same behavior as much as possible.
// See UGUIEventSystemTests.KeyDownStoppedDoesntPreventNavigationEvents for a test requires this.
}
internal void Update()
{
if (isCurrentFocusedPanel)
ProcessImguiEvents(currentFocusedElement ?? m_Panel.visualTree);
}
void LateUpdate()
{
// Empty the Event queue, look for EventModifiers.
ProcessImguiEvents(null);
}
private Event m_Event = new Event();
private static EventModifiers s_Modifiers = EventModifiers.None;
// Send IMGUI events to given focus-based target, if any, or simply flush the event queue if not.
// For uniformity of composite events (keyDown vs navigation), target should remain the same
// throughout the entire processing cycle.
void ProcessImguiEvents(Focusable target)
{
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 (target != null)
{
ProcessKeyboardEvent(m_Event, target);
if (eventSystem.sendNavigationEvents)
ProcessTabEvent(m_Event, target);
}
}
}
void ProcessKeyboardEvent(Event e, Focusable target)
{
if (e.type == EventType.KeyUp)
{
SendKeyUpEvent(e, target);
}
else if (e.type == EventType.KeyDown)
{
SendKeyDownEvent(e, target);
}
}
// TODO: add an ITabHandler interface
void ProcessTabEvent(Event e, Focusable target)
{
if (e.ShouldSendNavigationMoveEventRuntime())
{
SendTabEvent(e, e.shift ? NavigationMoveEvent.Direction.Previous : NavigationMoveEvent.Direction.Next, target);
}
}
private void SendTabEvent(Event e, NavigationMoveEvent.Direction direction, Focusable target)
{
using (var ev = NavigationMoveEvent.GetPooled(direction, s_Modifiers))
{
ev.target = target;
SendEvent(ev, e);
}
}
private void SendKeyUpEvent(Event e, Focusable target)
{
// Use UIElementsRuntimeUtility.CreateEvent because DefaultEventSystem uses it too
// and we want to have the same behavior as much as possible.
using (var ev = (KeyUpEvent) UIElementsRuntimeUtility.CreateEvent(e))
{
ev.target = target;
SendEvent(ev, e);
}
}
private void SendKeyDownEvent(Event e, Focusable target)
{
// Use UIElementsRuntimeUtility.CreateEvent because DefaultEventSystem uses it too
// and we want to have the same behavior as much as possible.
using (var ev = (KeyDownEvent) UIElementsRuntimeUtility.CreateEvent(e))
{
ev.target = target;
SendEvent(ev, e);
}
}
private bool ReadPointerData(PointerEvent pe, PointerEventData eventData, PointerEventType eventType = PointerEventType.Default)
{
if (eventSystem == null || eventSystem.currentInputModule == null)
return false;
pe.Read(this, eventData, eventType);
// PointerEvents making it this far have been validated by PanelRaycaster already
m_Panel.ScreenToPanel(pe.position, pe.deltaPosition,
out var panelPosition, out var panelDelta, allowOutside:true);
pe.SetPosition(panelPosition, panelDelta);
return true;
}
enum PointerEventType
{
Default, Down, Up
}
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 tilt { get; private set; }
public PenStatus penStatus { 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, PointerEventType eventType)
{
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;
// Flip Y axis between input and UITK
var h = Screen.height;
Vector3 eventPosition = MultipleDisplayUtilities.GetRelativeMousePositionForRaycast(eventData);
int eventDisplayIndex = (int)eventPosition.z;
if (eventDisplayIndex > 0 && eventDisplayIndex < Display.displays.Length)
h = Display.displays[eventDisplayIndex].systemHeight;
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;
tilt = eventData.tilt;
penStatus = eventData.penStatus;
radius = eventData.radius;
radiusVariance = eventData.radiusVariance;
modifiers = s_Modifiers;
if (eventType == PointerEventType.Default)
{
button = -1;
clickCount = 0;
}
else
{
button = Mathf.Max(0, (int)eventData.button);
clickCount = eventData.clickCount;
if (eventType == PointerEventType.Down)
{
// UUM-57082: InputSystem doesn't reset clickCount on delay until after it sends PointerDown
// This is not perfect but it's the best we can do with incomplete information.
if (Time.unscaledTime > self.m_LastClickTime + ClickDetector.s_DoubleClickTime * 0.001f)
clickCount = 0;
// Case 1379054: UIToolkit assumes clickCount is increased before PointerDown, but UGUI does it after.
clickCount++;
PointerDeviceState.PressButton(pointerId, button);
}
else if (eventType == PointerEventType.Up)
{
PointerDeviceState.ReleaseButton(pointerId, button);
}
clickCount = Mathf.Max(1, clickCount);
}
pressedButtons = PointerDeviceState.GetPressedButtons(pointerId);
}
public void SetPosition(Vector3 positionOverride, Vector3 deltaOverride)
{
localPosition = position = positionOverride;
deltaPosition = deltaOverride;
}
}
}
#endif
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8a410b213209442fb15a69799f0240a5
timeCreated: 1602089617

View File

@@ -0,0 +1,125 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace UnityEngine.UIElements
{
// This code is disabled unless the UI Toolkit package or the com.unity.modules.uielements module are present.
// The UIElements module is always present in the Editor but it can be stripped from a project build if unused.
#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 => Mathf.FloorToInt(m_Panel?.sortingPriority ?? 0f);
public override int renderOrderPriority => int.MaxValue - (UIElementsRuntimeUtility.s_ResolvedSortingIndexMax - (m_Panel?.resolvedSortingIndex ?? 0));
public override void Raycast(PointerEventData eventData, List<RaycastResult> resultAppendList)
{
if (m_Panel == null)
return;
var displayIndex = m_Panel.targetDisplay;
Vector3 eventPosition = MultipleDisplayUtilities.GetRelativeMousePositionForRaycast(eventData);
// Discard events that are not part of this display so the user does not interact with multiple displays at once.
if ((int) eventPosition.z != displayIndex)
return;
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;
var eventSystem = UIElementsRuntimeUtility.activeEventSystem as EventSystem;
if (eventSystem == null || eventSystem.currentInputModule == null)
return;
var pointerId = eventSystem.currentInputModule.ConvertUIToolkitPointerId(eventData);
var capturingElement = m_Panel.GetCapturingElement(pointerId);
if (capturingElement is VisualElement ve && ve.panel != m_Panel)
return;
var capturingPanel = PointerDeviceState.GetPlayerPanelWithSoftPointerCapture(pointerId);
if (capturingPanel != null && capturingPanel != m_Panel)
return;
if (capturingElement == null && capturingPanel == null)
{
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;
}
#endif
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7a79c4e23d4d4b64bfa5fa9e6671a460
timeCreated: 1602101961

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 32e2186f4598cff489784aae586f2215
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,42 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("guisystem")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("guisystem")]
[assembly: AssemblyCopyright("Copyright © Microsoft 2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: InternalsVisibleTo("UnityEngine.UI.Tests")]
#if UNITY_INCLUDE_TESTS
[assembly: InternalsVisibleTo("Unity.UIElements.EditorTests")]
[assembly: InternalsVisibleTo("Unity.UIElements.RuntimeTests")]
[assembly: InternalsVisibleTo("Unity.UIElements.PlayModeTests")]
#endif
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("d4f464c7-9b15-460d-b4bc-2cacd1c1df73")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7d7bd4bcc815cfb44b9990c29dabdb9f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 742654cad2425334696ba6ed4495cfef
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5472815444de2ce45bf2053a4af04b9d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,244 @@
using System.Collections;
using UnityEngine.Events;
namespace UnityEngine.UI.CoroutineTween
{
// Base interface for tweeners,
// using an interface instead of
// an abstract class as we want the
// tweens to be structs.
internal interface ITweenValue
{
void TweenValue(float floatPercentage);
bool ignoreTimeScale { get; }
float duration { get; }
bool ValidTarget();
}
// Color tween class, receives the
// TweenValue callback and then sets
// the value on the target.
internal struct ColorTween : ITweenValue
{
public enum ColorTweenMode
{
All,
RGB,
Alpha
}
public class ColorTweenCallback : UnityEvent<Color> {}
private ColorTweenCallback m_Target;
private Color m_StartColor;
private Color m_TargetColor;
private ColorTweenMode m_TweenMode;
private float m_Duration;
private bool m_IgnoreTimeScale;
public Color startColor
{
get { return m_StartColor; }
set { m_StartColor = value; }
}
public Color targetColor
{
get { return m_TargetColor; }
set { m_TargetColor = value; }
}
public ColorTweenMode tweenMode
{
get { return m_TweenMode; }
set { m_TweenMode = value; }
}
public float duration
{
get { return m_Duration; }
set { m_Duration = value; }
}
public bool ignoreTimeScale
{
get { return m_IgnoreTimeScale; }
set { m_IgnoreTimeScale = value; }
}
public void TweenValue(float floatPercentage)
{
if (!ValidTarget())
return;
var newColor = Color.Lerp(m_StartColor, m_TargetColor, floatPercentage);
if (m_TweenMode == ColorTweenMode.Alpha)
{
newColor.r = m_StartColor.r;
newColor.g = m_StartColor.g;
newColor.b = m_StartColor.b;
}
else if (m_TweenMode == ColorTweenMode.RGB)
{
newColor.a = m_StartColor.a;
}
m_Target.Invoke(newColor);
}
public void AddOnChangedCallback(UnityAction<Color> callback)
{
if (m_Target == null)
m_Target = new ColorTweenCallback();
m_Target.AddListener(callback);
}
public bool GetIgnoreTimescale()
{
return m_IgnoreTimeScale;
}
public float GetDuration()
{
return m_Duration;
}
public bool ValidTarget()
{
return m_Target != null;
}
}
// Float tween class, receives the
// TweenValue callback and then sets
// the value on the target.
internal struct FloatTween : ITweenValue
{
public class FloatTweenCallback : UnityEvent<float> {}
private FloatTweenCallback m_Target;
private float m_StartValue;
private float m_TargetValue;
private float m_Duration;
private bool m_IgnoreTimeScale;
public float startValue
{
get { return m_StartValue; }
set { m_StartValue = value; }
}
public float targetValue
{
get { return m_TargetValue; }
set { m_TargetValue = value; }
}
public float duration
{
get { return m_Duration; }
set { m_Duration = value; }
}
public bool ignoreTimeScale
{
get { return m_IgnoreTimeScale; }
set { m_IgnoreTimeScale = value; }
}
public void TweenValue(float floatPercentage)
{
if (!ValidTarget())
return;
var newValue = Mathf.Lerp(m_StartValue, m_TargetValue, floatPercentage);
m_Target.Invoke(newValue);
}
public void AddOnChangedCallback(UnityAction<float> callback)
{
if (m_Target == null)
m_Target = new FloatTweenCallback();
m_Target.AddListener(callback);
}
public bool GetIgnoreTimescale()
{
return m_IgnoreTimeScale;
}
public float GetDuration()
{
return m_Duration;
}
public bool ValidTarget()
{
return m_Target != null;
}
}
// Tween runner, executes the given tween.
// The coroutine will live within the given
// behaviour container.
internal class TweenRunner<T> where T : struct, ITweenValue
{
protected MonoBehaviour m_CoroutineContainer;
protected IEnumerator m_Tween;
// utility function for starting the tween
private static IEnumerator Start(T tweenInfo)
{
if (!tweenInfo.ValidTarget())
yield break;
var elapsedTime = 0.0f;
while (elapsedTime < tweenInfo.duration)
{
elapsedTime += tweenInfo.ignoreTimeScale ? Time.unscaledDeltaTime : Time.deltaTime;
var percentage = Mathf.Clamp01(elapsedTime / tweenInfo.duration);
tweenInfo.TweenValue(percentage);
yield return null;
}
tweenInfo.TweenValue(1.0f);
}
public void Init(MonoBehaviour coroutineContainer)
{
m_CoroutineContainer = coroutineContainer;
}
public void StartTween(T info)
{
if (m_CoroutineContainer == null)
{
Debug.LogWarning("Coroutine container not configured... did you forget to call Init?");
return;
}
StopTween();
if (!m_CoroutineContainer.gameObject.activeInHierarchy)
{
info.TweenValue(1.0f);
return;
}
m_Tween = Start(info);
m_CoroutineContainer.StartCoroutine(m_Tween);
}
public void StopTween()
{
if (m_Tween != null)
{
m_CoroutineContainer.StopCoroutine(m_Tween);
m_Tween = null;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7be84a49bb2cd7e4a9ed097ba22794d0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 12c42068351bb084abde965d725b9887
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,163 @@
using System;
using UnityEngine.Serialization;
namespace UnityEngine.UI
{
/// <summary>
/// Structure that stores the state of an animation transition on a Selectable.
/// </summary>
[Serializable]
public class AnimationTriggers
{
private const string kDefaultNormalAnimName = "Normal";
private const string kDefaultHighlightedAnimName = "Highlighted";
private const string kDefaultPressedAnimName = "Pressed";
private const string kDefaultSelectedAnimName = "Selected";
private const string kDefaultDisabledAnimName = "Disabled";
[FormerlySerializedAs("normalTrigger")]
[SerializeField]
private string m_NormalTrigger = kDefaultNormalAnimName;
[FormerlySerializedAs("highlightedTrigger")]
[SerializeField]
private string m_HighlightedTrigger = kDefaultHighlightedAnimName;
[FormerlySerializedAs("pressedTrigger")]
[SerializeField]
private string m_PressedTrigger = kDefaultPressedAnimName;
[FormerlySerializedAs("m_HighlightedTrigger")]
[SerializeField]
private string m_SelectedTrigger = kDefaultSelectedAnimName;
[FormerlySerializedAs("disabledTrigger")]
[SerializeField]
private string m_DisabledTrigger = kDefaultDisabledAnimName;
/// <summary>
/// Trigger to send to animator when entering normal state.
/// </summary>
/// <example>
/// <code>
/// <![CDATA[
/// using UnityEngine;
/// using System.Collections;
/// using UnityEngine.UI; // Required when Using UI elements.
///
/// public class ExampleClass : MonoBehaviour
/// {
/// public Animator buttonAnimator;
/// public Button button;
/// void SomeFunction()
/// {
/// //Sets the button to the Normal state (Useful when making tutorials).
/// buttonAnimator.SetTrigger(button.animationTriggers.normalTrigger);
/// }
/// }
/// ]]>
///</code>
/// </example>
public string normalTrigger { get { return m_NormalTrigger; } set { m_NormalTrigger = value; } }
/// <summary>
/// Trigger to send to animator when entering highlighted state.
/// </summary>
/// <example>
/// <code>
/// <![CDATA[
/// using UnityEngine;
/// using System.Collections;
/// using UnityEngine.UI; // Required when Using UI elements.
///
/// public class ExampleClass : MonoBehaviour
/// {
/// public Animator buttonAnimator;
/// public Button button;
/// void SomeFunction()
/// {
/// //Sets the button to the Highlighted state (Useful when making tutorials).
/// buttonAnimator.SetTrigger(button.animationTriggers.highlightedTrigger);
/// }
/// }
/// ]]>
///</code>
/// </example>
public string highlightedTrigger { get { return m_HighlightedTrigger; } set { m_HighlightedTrigger = value; } }
/// <summary>
/// Trigger to send to animator when entering pressed state.
/// </summary>
/// <example>
/// <code>
/// <![CDATA[
/// using UnityEngine;
/// using System.Collections;
/// using UnityEngine.UI; // Required when Using UI elements.
///
/// public class ExampleClass : MonoBehaviour
/// {
/// public Animator buttonAnimator;
/// public Button button;
/// void SomeFunction()
/// {
/// //Sets the button to the Pressed state (Useful when making tutorials).
/// buttonAnimator.SetTrigger(button.animationTriggers.pressedTrigger);
/// }
/// }
/// ]]>
///</code>
/// </example>
public string pressedTrigger { get { return m_PressedTrigger; } set { m_PressedTrigger = value; } }
/// <summary>
/// Trigger to send to animator when entering selected state.
/// </summary>
/// <example>
/// <code>
/// <![CDATA[
/// using UnityEngine;
/// using System.Collections;
/// using UnityEngine.UI; // Required when Using UI elements.
///
/// public class ExampleClass : MonoBehaviour
/// {
/// public Animator buttonAnimator;
/// public Button button;
/// void SomeFunction()
/// {
/// //Sets the button to the Selected state (Useful when making tutorials).
/// buttonAnimator.SetTrigger(button.animationTriggers.selectedTrigger);
/// }
/// }
/// ]]>
///</code>
/// </example>
public string selectedTrigger { get { return m_SelectedTrigger; } set { m_SelectedTrigger = value; } }
/// <summary>
/// Trigger to send to animator when entering disabled state.
/// </summary>
/// <example>
/// <code>
/// <![CDATA[
/// using UnityEngine;
/// using System.Collections;
/// using UnityEngine.UI; // Required when Using UI elements.
///
/// public class ExampleClass : MonoBehaviour
/// {
/// public Animator buttonAnimator;
/// public Button button;
/// void SomeFunction()
/// {
/// //Sets the button to the Disabled state (Useful when making tutorials).
/// buttonAnimator.SetTrigger(button.animationTriggers.disabledTrigger);
/// }
/// }
/// ]]>
///</code>
/// </example>
public string disabledTrigger { get { return m_DisabledTrigger; } set { m_DisabledTrigger = value; } }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c67ac6e40bbb6fe47a095b949b609ce0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,175 @@
using System;
using System.Collections;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.Serialization;
namespace UnityEngine.UI
{
/// <summary>
/// A standard button that sends an event when clicked.
/// </summary>
[AddComponentMenu("UI/Button", 30)]
public class Button : Selectable, IPointerClickHandler, ISubmitHandler
{
[Serializable]
/// <summary>
/// Function definition for a button click event.
/// </summary>
public class ButtonClickedEvent : UnityEvent {}
// Event delegates triggered on click.
[FormerlySerializedAs("onClick")]
[SerializeField]
private ButtonClickedEvent m_OnClick = new ButtonClickedEvent();
protected Button()
{}
/// <summary>
/// UnityEvent that is triggered when the button is pressed.
/// Note: Triggered on MouseUp after MouseDown on the same object.
/// </summary>
///<example>
///<code>
/// <![CDATA[
/// using UnityEngine;
/// using UnityEngine.UI;
/// using System.Collections;
///
/// public class ClickExample : MonoBehaviour
/// {
/// public Button yourButton;
///
/// void Start()
/// {
/// Button btn = yourButton.GetComponent<Button>();
/// btn.onClick.AddListener(TaskOnClick);
/// }
///
/// void TaskOnClick()
/// {
/// Debug.Log("You have clicked the button!");
/// }
/// }
/// ]]>
///</code>
///</example>
public ButtonClickedEvent onClick
{
get { return m_OnClick; }
set { m_OnClick = value; }
}
private void Press()
{
if (!IsActive() || !IsInteractable())
return;
UISystemProfilerApi.AddMarker("Button.onClick", this);
m_OnClick.Invoke();
}
/// <summary>
/// Call all registered IPointerClickHandlers.
/// Register button presses using the IPointerClickHandler. You can also use it to tell what type of click happened (left, right etc.).
/// Make sure your Scene has an EventSystem.
/// </summary>
/// <param name="eventData">Pointer Data associated with the event. Typically by the event system.</param>
/// <example>
/// <code>
/// <![CDATA[
/// //Attatch this script to a Button GameObject
/// using UnityEngine;
/// using UnityEngine.EventSystems;
///
/// public class Example : MonoBehaviour, IPointerClickHandler
/// {
/// //Detect if a click occurs
/// public void OnPointerClick(PointerEventData pointerEventData)
/// {
/// //Use this to tell when the user right-clicks on the Button
/// if (pointerEventData.button == PointerEventData.InputButton.Right)
/// {
/// //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 Right Clicked!");
/// }
///
/// //Use this to tell when the user left-clicks on the Button
/// if (pointerEventData.button == PointerEventData.InputButton.Left)
/// {
/// Debug.Log(name + " Game Object Left Clicked!");
/// }
/// }
/// }
/// ]]>
///</code>
/// </example>
public virtual void OnPointerClick(PointerEventData eventData)
{
if (eventData.button != PointerEventData.InputButton.Left)
return;
Press();
}
/// <summary>
/// Call all registered ISubmitHandler.
/// </summary>
/// <param name="eventData">Associated data with the event. Typically by the event system.</param>
/// <remarks>
/// This detects when a Button has been selected via a "submit" key you specify (default is the return key).
///
/// To change the submit key, either:
///
/// 1. Go to Edit->Project Settings->Input.
///
/// 2. Next, expand the Axes section and go to the Submit section if it exists.
///
/// 3. If Submit doesnt exist, add 1 number to the Size field. This creates a new section at the bottom. Expand the new section and change the Name field to “Submit”.
///
/// 4. Change the Positive Button field to the key you want (e.g. space).
///
///
/// Or:
///
/// 1. Go to your EventSystem in your Project
///
/// 2. Go to the Inspector window and change the Submit Button field to one of the sections in the Input Manager (e.g. "Submit"), or create your own by naming it what you like, then following the next few steps.
///
/// 3. Go to Edit->Project Settings->Input to get to the Input Manager.
///
/// 4. Expand the Axes section in the Inspector window. Add 1 to the number in the Size field. This creates a new section at the bottom.
///
/// 5. Expand the new section and name it the same as the name you inserted in the Submit Button field in the EventSystem. Set the Positive Button field to the key you want (e.g. space)
/// </remarks>
public virtual void OnSubmit(BaseEventData eventData)
{
Press();
// if we get set disabled during the press
// don't run the coroutine.
if (!IsActive() || !IsInteractable())
return;
DoStateTransition(SelectionState.Pressed, false);
StartCoroutine(OnFinishSubmit());
}
private IEnumerator OnFinishSubmit()
{
var fadeTime = colors.fadeDuration;
var elapsedTime = 0f;
while (elapsedTime < fadeTime)
{
elapsedTime += Time.unscaledDeltaTime;
yield return null;
}
DoStateTransition(currentSelectionState, false);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4e29b1a8efbd4b44bb3f3716e73f07ff
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,412 @@
using System;
using System.Collections.Generic;
using UnityEngine.UI.Collections;
namespace UnityEngine.UI
{
/// <summary>
/// Values of 'update' called on a Canvas update.
/// </summary>
/// <remarks> If modifying also modify m_CanvasUpdateProfilerStrings to match.</remarks>
public enum CanvasUpdate
{
/// <summary>
/// Called before layout.
/// </summary>
Prelayout = 0,
/// <summary>
/// Called for layout.
/// </summary>
Layout = 1,
/// <summary>
/// Called after layout.
/// </summary>
PostLayout = 2,
/// <summary>
/// Called before rendering.
/// </summary>
PreRender = 3,
/// <summary>
/// Called late, before render.
/// </summary>
LatePreRender = 4,
/// <summary>
/// Max enum value. Always last.
/// </summary>
MaxUpdateValue = 5
}
/// <summary>
/// This is an element that can live on a Canvas.
/// </summary>
public interface ICanvasElement
{
/// <summary>
/// Rebuild the element for the given stage.
/// </summary>
/// <param name="executing">The current CanvasUpdate stage being rebuild.</param>
void Rebuild(CanvasUpdate executing);
/// <summary>
/// Get the transform associated with the ICanvasElement.
/// </summary>
Transform transform { get; }
/// <summary>
/// Callback sent when this ICanvasElement has completed layout.
/// </summary>
void LayoutComplete();
/// <summary>
/// Callback sent when this ICanvasElement has completed Graphic rebuild.
/// </summary>
void GraphicUpdateComplete();
/// <summary>
/// Used if the native representation has been destroyed.
/// </summary>
/// <returns>Return true if the element is considered destroyed.</returns>
bool IsDestroyed();
}
/// <summary>
/// A place where CanvasElements can register themselves for rebuilding.
/// </summary>
public class CanvasUpdateRegistry
{
private static CanvasUpdateRegistry s_Instance;
private bool m_PerformingLayoutUpdate;
private bool m_PerformingGraphicUpdate;
// This list matches the CanvasUpdate enum above. Keep in sync
private string[] m_CanvasUpdateProfilerStrings = new string[] { "CanvasUpdate.Prelayout", "CanvasUpdate.Layout", "CanvasUpdate.PostLayout", "CanvasUpdate.PreRender", "CanvasUpdate.LatePreRender" };
private const string m_CullingUpdateProfilerString = "ClipperRegistry.Cull";
private readonly IndexedSet<ICanvasElement> m_LayoutRebuildQueue = new IndexedSet<ICanvasElement>();
private readonly IndexedSet<ICanvasElement> m_GraphicRebuildQueue = new IndexedSet<ICanvasElement>();
protected CanvasUpdateRegistry()
{
Canvas.willRenderCanvases += PerformUpdate;
}
/// <summary>
/// Get the singleton registry instance.
/// </summary>
public static CanvasUpdateRegistry instance
{
get
{
if (s_Instance == null)
s_Instance = new CanvasUpdateRegistry();
return s_Instance;
}
}
private bool ObjectValidForUpdate(ICanvasElement element)
{
var valid = element != null;
var isUnityObject = element is Object;
if (isUnityObject)
valid = (element as Object) != null; //Here we make use of the overloaded UnityEngine.Object == null, that checks if the native object is alive.
return valid;
}
private void CleanInvalidItems()
{
// So MB's override the == operator for null equality, which checks
// if they are destroyed. This is fine if you are looking at a concrete
// mb, but in this case we are looking at a list of ICanvasElement
// this won't forward the == operator to the MB, but just check if the
// interface is null. IsDestroyed will return if the backend is destroyed.
var layoutRebuildQueueCount = m_LayoutRebuildQueue.Count;
for (int i = layoutRebuildQueueCount - 1; i >= 0; --i)
{
var item = m_LayoutRebuildQueue[i];
if (item == null)
{
m_LayoutRebuildQueue.RemoveAt(i);
continue;
}
if (item.IsDestroyed())
{
m_LayoutRebuildQueue.RemoveAt(i);
item.LayoutComplete();
}
}
var graphicRebuildQueueCount = m_GraphicRebuildQueue.Count;
for (int i = graphicRebuildQueueCount - 1; i >= 0; --i)
{
var item = m_GraphicRebuildQueue[i];
if (item == null)
{
m_GraphicRebuildQueue.RemoveAt(i);
continue;
}
if (item.IsDestroyed())
{
m_GraphicRebuildQueue.RemoveAt(i);
item.GraphicUpdateComplete();
}
}
}
private static readonly Comparison<ICanvasElement> s_SortLayoutFunction = SortLayoutList;
private void PerformUpdate()
{
UISystemProfilerApi.BeginSample(UISystemProfilerApi.SampleType.Layout);
CleanInvalidItems();
m_PerformingLayoutUpdate = true;
m_LayoutRebuildQueue.Sort(s_SortLayoutFunction);
for (int i = 0; i <= (int)CanvasUpdate.PostLayout; i++)
{
UnityEngine.Profiling.Profiler.BeginSample(m_CanvasUpdateProfilerStrings[i]);
for (int j = 0; j < m_LayoutRebuildQueue.Count; j++)
{
var rebuild = m_LayoutRebuildQueue[j];
try
{
if (ObjectValidForUpdate(rebuild))
rebuild.Rebuild((CanvasUpdate)i);
}
catch (Exception e)
{
Debug.LogException(e, rebuild.transform);
}
}
UnityEngine.Profiling.Profiler.EndSample();
}
for (int i = 0; i < m_LayoutRebuildQueue.Count; ++i)
m_LayoutRebuildQueue[i].LayoutComplete();
m_LayoutRebuildQueue.Clear();
m_PerformingLayoutUpdate = false;
UISystemProfilerApi.EndSample(UISystemProfilerApi.SampleType.Layout);
UISystemProfilerApi.BeginSample(UISystemProfilerApi.SampleType.Render);
// now layout is complete do culling...
UnityEngine.Profiling.Profiler.BeginSample(m_CullingUpdateProfilerString);
ClipperRegistry.instance.Cull();
UnityEngine.Profiling.Profiler.EndSample();
m_PerformingGraphicUpdate = true;
for (var i = (int)CanvasUpdate.PreRender; i < (int)CanvasUpdate.MaxUpdateValue; i++)
{
UnityEngine.Profiling.Profiler.BeginSample(m_CanvasUpdateProfilerStrings[i]);
for (var k = 0; k < m_GraphicRebuildQueue.Count; k++)
{
try
{
var element = m_GraphicRebuildQueue[k];
if (ObjectValidForUpdate(element))
element.Rebuild((CanvasUpdate)i);
}
catch (Exception e)
{
Debug.LogException(e, m_GraphicRebuildQueue[k].transform);
}
}
UnityEngine.Profiling.Profiler.EndSample();
}
for (int i = 0; i < m_GraphicRebuildQueue.Count; ++i)
m_GraphicRebuildQueue[i].GraphicUpdateComplete();
m_GraphicRebuildQueue.Clear();
m_PerformingGraphicUpdate = false;
UISystemProfilerApi.EndSample(UISystemProfilerApi.SampleType.Render);
}
private static int ParentCount(Transform child)
{
if (child == null)
return 0;
var parent = child.parent;
int count = 0;
while (parent != null)
{
count++;
parent = parent.parent;
}
return count;
}
private static int SortLayoutList(ICanvasElement x, ICanvasElement y)
{
Transform t1 = x.transform;
Transform t2 = y.transform;
return ParentCount(t1) - ParentCount(t2);
}
/// <summary>
/// Try and add the given element to the layout rebuild list.
/// Will not return if successfully added.
/// </summary>
/// <param name="element">The element that is needing rebuilt.</param>
public static void RegisterCanvasElementForLayoutRebuild(ICanvasElement element)
{
instance.InternalRegisterCanvasElementForLayoutRebuild(element);
}
/// <summary>
/// Try and add the given element to the layout rebuild list.
/// </summary>
/// <param name="element">The element that is needing rebuilt.</param>
/// <returns>
/// True if the element was successfully added to the rebuilt list.
/// False if either already inside a Graphic Update loop OR has already been added to the list.
/// </returns>
public static bool TryRegisterCanvasElementForLayoutRebuild(ICanvasElement element)
{
return instance.InternalRegisterCanvasElementForLayoutRebuild(element);
}
private bool InternalRegisterCanvasElementForLayoutRebuild(ICanvasElement element)
{
if (m_LayoutRebuildQueue.Contains(element))
return false;
/* TODO: this likely should be here but causes the error to show just resizing the game view (case 739376)
if (m_PerformingLayoutUpdate)
{
Debug.LogError(string.Format("Trying to add {0} for layout rebuild while we are already inside a layout rebuild loop. This is not supported.", element));
return false;
}*/
return m_LayoutRebuildQueue.AddUnique(element);
}
/// <summary>
/// Try and add the given element to the rebuild list.
/// Will not return if successfully added.
/// </summary>
/// <param name="element">The element that is needing rebuilt.</param>
public static void RegisterCanvasElementForGraphicRebuild(ICanvasElement element)
{
instance.InternalRegisterCanvasElementForGraphicRebuild(element);
}
/// <summary>
/// Try and add the given element to the rebuild list.
/// </summary>
/// <param name="element">The element that is needing rebuilt.</param>
/// <returns>
/// True if the element was successfully added to the rebuilt list.
/// False if either already inside a Graphic Update loop OR has already been added to the list.
/// </returns>
public static bool TryRegisterCanvasElementForGraphicRebuild(ICanvasElement element)
{
return instance.InternalRegisterCanvasElementForGraphicRebuild(element);
}
private bool InternalRegisterCanvasElementForGraphicRebuild(ICanvasElement element)
{
if (m_PerformingGraphicUpdate)
{
Debug.LogError(string.Format("Trying to add {0} for graphic rebuild while we are already inside a graphic rebuild loop. This is not supported.", element));
return false;
}
return m_GraphicRebuildQueue.AddUnique(element);
}
/// <summary>
/// Remove the given element from both the graphic and the layout rebuild lists.
/// </summary>
/// <param name="element"></param>
public static void UnRegisterCanvasElementForRebuild(ICanvasElement element)
{
instance.InternalUnRegisterCanvasElementForLayoutRebuild(element);
instance.InternalUnRegisterCanvasElementForGraphicRebuild(element);
}
/// <summary>
/// Disable the given element from both the graphic and the layout rebuild lists.
/// </summary>
/// <param name="element"></param>
public static void DisableCanvasElementForRebuild(ICanvasElement element)
{
instance.InternalDisableCanvasElementForLayoutRebuild(element);
instance.InternalDisableCanvasElementForGraphicRebuild(element);
}
private void InternalUnRegisterCanvasElementForLayoutRebuild(ICanvasElement element)
{
if (m_PerformingLayoutUpdate)
{
Debug.LogError(string.Format("Trying to remove {0} from rebuild list while we are already inside a rebuild loop. This is not supported.", element));
return;
}
element.LayoutComplete();
instance.m_LayoutRebuildQueue.Remove(element);
}
private void InternalUnRegisterCanvasElementForGraphicRebuild(ICanvasElement element)
{
if (m_PerformingGraphicUpdate)
{
Debug.LogError(string.Format("Trying to remove {0} from rebuild list while we are already inside a rebuild loop. This is not supported.", element));
return;
}
element.GraphicUpdateComplete();
instance.m_GraphicRebuildQueue.Remove(element);
}
private void InternalDisableCanvasElementForLayoutRebuild(ICanvasElement element)
{
if (m_PerformingLayoutUpdate)
{
Debug.LogError(string.Format("Trying to remove {0} from rebuild list while we are already inside a rebuild loop. This is not supported.", element));
return;
}
element.LayoutComplete();
instance.m_LayoutRebuildQueue.DisableItem(element);
}
private void InternalDisableCanvasElementForGraphicRebuild(ICanvasElement element)
{
if (m_PerformingGraphicUpdate)
{
Debug.LogError(string.Format("Trying to remove {0} from rebuild list while we are already inside a rebuild loop. This is not supported.", element));
return;
}
element.GraphicUpdateComplete();
instance.m_GraphicRebuildQueue.DisableItem(element);
}
/// <summary>
/// Are graphics layouts currently being calculated..
/// </summary>
/// <returns>True if the rebuild loop is CanvasUpdate.Prelayout, CanvasUpdate.Layout or CanvasUpdate.Postlayout</returns>
public static bool IsRebuildingLayout()
{
return instance.m_PerformingLayoutUpdate;
}
/// <summary>
/// Are graphics currently being rebuild.
/// </summary>
/// <returns>True if the rebuild loop is CanvasUpdate.PreRender or CanvasUpdate.Render</returns>
public static bool IsRebuildingGraphics()
{
return instance.m_PerformingGraphicUpdate;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bfb788a43e03363419155b8af77da971
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,243 @@
using System;
using UnityEngine.Serialization;
namespace UnityEngine.UI
{
[Serializable]
/// <summary>
/// Structure that stores the state of a color transition on a Selectable.
/// </summary>
public struct ColorBlock : IEquatable<ColorBlock>
{
[FormerlySerializedAs("normalColor")]
[SerializeField]
private Color m_NormalColor;
[FormerlySerializedAs("highlightedColor")]
[SerializeField]
private Color m_HighlightedColor;
[FormerlySerializedAs("pressedColor")]
[SerializeField]
private Color m_PressedColor;
[FormerlySerializedAs("m_HighlightedColor")]
[SerializeField]
private Color m_SelectedColor;
[FormerlySerializedAs("disabledColor")]
[SerializeField]
private Color m_DisabledColor;
[Range(1, 5)]
[SerializeField]
private float m_ColorMultiplier;
[FormerlySerializedAs("fadeDuration")]
[SerializeField]
private float m_FadeDuration;
/// <summary>
/// The normal color for this color block.
/// </summary>
/// <example>
/// <code>
/// <![CDATA[
/// using UnityEngine;
/// using System.Collections;
/// using UnityEngine.UI; // Required when Using UI elements.
///
/// public class ExampleClass : MonoBehaviour
/// {
/// public Button button;
/// public Color newColor;
///
/// void Start()
/// {
/// //Changes the button's Normal color to the new color.
/// ColorBlock cb = button.colors;
/// cb.normalColor = newColor;
/// button.colors = cb;
/// }
/// }
/// ]]>
///</code>
/// </example>
public Color normalColor { get { return m_NormalColor; } set { m_NormalColor = value; } }
/// <summary>
/// The highlight color for this color block.
/// </summary>
/// <example>
/// <code>
/// <![CDATA[
/// using UnityEngine;
/// using System.Collections;
/// using UnityEngine.UI; // Required when Using UI elements.
///
/// public class ExampleClass : MonoBehaviour
/// {
/// public Button button;
/// public Color newColor;
///
/// void Start()
/// {
/// //Changes the button's Highlighted color to the new color.
/// ColorBlock cb = button.colors;
/// cb.highlightedColor = newColor;
/// button.colors = cb;
/// }
/// }
/// ]]>
///</code>
/// </example>
public Color highlightedColor { get { return m_HighlightedColor; } set { m_HighlightedColor = value; } }
/// <summary>
/// The pressed color for this color block.
/// </summary>
/// <example>
/// <code>
/// <![CDATA[
/// using UnityEngine;
/// using System.Collections;
/// using UnityEngine.UI; // Required when Using UI elements.
///
/// public class ExampleClass : MonoBehaviour
/// {
/// public Button button;
/// public Color newColor;
///
/// void Start()
/// {
/// //Changes the button's Pressed color to the new color.
/// ColorBlock cb = button.colors;
/// cb.pressedColor = newColor;
/// button.colors = cb;
/// }
/// }
/// ]]>
///</code>
/// </example>
public Color pressedColor { get { return m_PressedColor; } set { m_PressedColor = value; } }
/// <summary>
/// The selected color for this color block.
/// </summary>
/// <example>
/// <code>
/// <![CDATA[
/// using UnityEngine;
/// using System.Collections;
/// using UnityEngine.UI; // Required when Using UI elements.
///
/// public class ExampleClass : MonoBehaviour
/// {
/// public Button button;
/// public Color newColor;
///
/// void Start()
/// {
/// //Changes the button's Selected color to the new color.
/// ColorBlock cb = button.colors;
/// cb.selectedColor = newColor;
/// button.colors = cb;
/// }
/// }
/// ]]>
///</code>
/// </example>
public Color selectedColor { get { return m_SelectedColor; } set { m_SelectedColor = value; } }
/// <summary>
/// The disabled color for this color block.
/// </summary>
/// <example>
/// <code>
/// <![CDATA[
/// using UnityEngine;
/// using System.Collections;
/// using UnityEngine.UI; // Required when Using UI elements.
///
/// public class ExampleClass : MonoBehaviour
/// {
/// public Button button;
/// public Color newColor;
///
/// void Start()
/// {
/// //Changes the button's Disabled color to the new color.
/// ColorBlock cb = button.colors;
/// cb.disabledColor = newColor;
/// button.colors = cb;
/// }
/// }
/// ]]>
///</code>
/// </example>
public Color disabledColor { get { return m_DisabledColor; } set { m_DisabledColor = value; } }
/// <summary>
/// Multiplier applied to colors (allows brightening greater then base color).
/// </summary>
public float colorMultiplier { get { return m_ColorMultiplier; } set { m_ColorMultiplier = value; } }
/// <summary>
/// How long a color transition between states should take.
/// </summary>
public float fadeDuration { get { return m_FadeDuration; } set { m_FadeDuration = value; } }
/// <summary>
/// Simple getter for a code generated default ColorBlock.
/// </summary>
public static ColorBlock defaultColorBlock;
static ColorBlock()
{
defaultColorBlock = new ColorBlock
{
m_NormalColor = new Color32(255, 255, 255, 255),
m_HighlightedColor = new Color32(245, 245, 245, 255),
m_PressedColor = new Color32(200, 200, 200, 255),
m_SelectedColor = new Color32(245, 245, 245, 255),
m_DisabledColor = new Color32(200, 200, 200, 128),
colorMultiplier = 1.0f,
fadeDuration = 0.1f
};
}
public override bool Equals(object obj)
{
if (!(obj is ColorBlock))
return false;
return Equals((ColorBlock)obj);
}
public bool Equals(ColorBlock other)
{
return normalColor == other.normalColor &&
highlightedColor == other.highlightedColor &&
pressedColor == other.pressedColor &&
selectedColor == other.selectedColor &&
disabledColor == other.disabledColor &&
colorMultiplier == other.colorMultiplier &&
fadeDuration == other.fadeDuration;
}
public static bool operator==(ColorBlock point1, ColorBlock point2)
{
return point1.Equals(point2);
}
public static bool operator!=(ColorBlock point1, ColorBlock point2)
{
return !point1.Equals(point2);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 83088ba2132cbc940b7ca0c679a02b0d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 27ed3e221887b3544bd9d6505d4a789f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,80 @@
using System.Collections.Generic;
using UnityEngine.UI.Collections;
namespace UnityEngine.UI
{
/// <summary>
/// Registry class to keep track of all IClippers that exist in the scene
/// </summary>
/// <remarks>
/// This is used during the CanvasUpdate loop to cull clippable elements. The clipping is called after layout, but before Graphic update.
/// </remarks>
public class ClipperRegistry
{
static ClipperRegistry s_Instance;
readonly IndexedSet<IClipper> m_Clippers = new IndexedSet<IClipper>();
protected ClipperRegistry()
{
// This is needed for AOT platforms. Without it the compile doesn't get the definition of the Dictionarys
#pragma warning disable 168
Dictionary<IClipper, int> emptyIClipperDic;
#pragma warning restore 168
}
/// <summary>
/// The singleton instance of the clipper registry.
/// </summary>
public static ClipperRegistry instance
{
get
{
if (s_Instance == null)
s_Instance = new ClipperRegistry();
return s_Instance;
}
}
/// <summary>
/// Perform the clipping on all registered IClipper
/// </summary>
public void Cull()
{
var clippersCount = m_Clippers.Count;
for (var i = 0; i < clippersCount; ++i)
{
m_Clippers[i].PerformClipping();
}
}
/// <summary>
/// Register a unique IClipper element
/// </summary>
/// <param name="c">The clipper element to add</param>
public static void Register(IClipper c)
{
if (c == null)
return;
instance.m_Clippers.AddUnique(c);
}
/// <summary>
/// UnRegister a IClipper element
/// </summary>
/// <param name="c">The Element to try and remove.</param>
public static void Unregister(IClipper c)
{
instance.m_Clippers.Remove(c);
}
/// <summary>
/// Disable a IClipper element
/// </summary>
/// <param name="c">The Element to try and disable.</param>
public static void Disable(IClipper c)
{
instance.m_Clippers.DisableItem(c);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9f1026265f8e3d54fb6e9f082c43debf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,51 @@
using System.Collections.Generic;
namespace UnityEngine.UI
{
/// <summary>
/// Utility class to help when clipping using IClipper.
/// </summary>
public static class Clipping
{
/// <summary>
/// Find the Rect to use for clipping.
/// Given the input RectMask2ds find a rectangle that is the overlap of all the inputs.
/// </summary>
/// <param name="rectMaskParents">RectMasks to build the overlap rect from.</param>
/// <param name="validRect">Was there a valid Rect found.</param>
/// <returns>The final compounded overlapping rect</returns>
public static Rect FindCullAndClipWorldRect(List<RectMask2D> rectMaskParents, out bool validRect)
{
if (rectMaskParents.Count == 0)
{
validRect = false;
return new Rect();
}
Rect current = rectMaskParents[0].canvasRect;
Vector4 offset = rectMaskParents[0].padding;
float xMin = current.xMin + offset.x;
float xMax = current.xMax - offset.z;
float yMin = current.yMin + offset.y;
float yMax = current.yMax - offset.w;
var rectMaskParentsCount = rectMaskParents.Count;
for (var i = 1; i < rectMaskParentsCount; ++i)
{
current = rectMaskParents[i].canvasRect;
offset = rectMaskParents[i].padding;
if (xMin < current.xMin + offset.x)
xMin = current.xMin + offset.x;
if (yMin < current.yMin + offset.y)
yMin = current.yMin + offset.y;
if (xMax > current.xMax - offset.z)
xMax = current.xMax - offset.z;
if (yMax > current.yMax - offset.w)
yMax = current.yMax - offset.w;
}
validRect = xMax > xMin && yMax > yMin;
return validRect ? new Rect(xMin, yMin, xMax - xMin, yMax - yMin) : new Rect();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 67e3583b91179094094c6a188b232262
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,60 @@
namespace UnityEngine.UI
{
/// <summary>
/// Interface that can be used to recieve clipping callbacks as part of the canvas update loop.
/// </summary>
public interface IClipper
{
/// <summary>
/// Function to to cull / clip children elements.
/// </summary>
/// <remarks>
/// Called after layout and before Graphic update of the Canvas update loop.
/// </remarks>
void PerformClipping();
}
/// <summary>
/// Interface for elements that can be clipped if they are under an IClipper
/// </summary>
public interface IClippable
{
/// <summary>
/// GameObject of the IClippable object
/// </summary>
GameObject gameObject { get; }
/// <summary>
/// Will be called when the state of a parent IClippable changed.
/// </summary>
void RecalculateClipping();
/// <summary>
/// The RectTransform of the clippable.
/// </summary>
RectTransform rectTransform { get; }
/// <summary>
/// Clip and cull the IClippable given a specific clipping rect
/// </summary>
/// <param name="clipRect">The Rectangle in which to clip against.</param>
/// <param name="validRect">Is the Rect valid. If not then the rect has 0 size.</param>
void Cull(Rect clipRect, bool validRect);
/// <summary>
/// Set the clip rect for the IClippable.
/// </summary>
/// <param name="value">The Rectangle for the clipping</param>
/// <param name="validRect">Is the rect valid.</param>
void SetClipRect(Rect value, bool validRect);
/// <summary>
/// Set the clip softness for the IClippable.
///
/// The softness is a linear alpha falloff over clipSoftness pixels.
/// </summary>
/// <param name="clipSoftness">The number of pixels to apply the softness to </param>
void SetClipSoftness(Vector2 clipSoftness);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 371b6b9c8adc50745ace66a6fdf67481
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,21 @@
namespace UnityEngine.UI
{
internal class RectangularVertexClipper
{
readonly Vector3[] m_WorldCorners = new Vector3[4];
readonly Vector3[] m_CanvasCorners = new Vector3[4];
public Rect GetCanvasRect(RectTransform t, Canvas c)
{
if (c == null)
return new Rect();
t.GetWorldCorners(m_WorldCorners);
var canvasTransform = c.GetComponent<Transform>();
for (int i = 0; i < 4; ++i)
m_CanvasCorners[i] = canvasTransform.InverseTransformPoint(m_WorldCorners[i]);
return new Rect(m_CanvasCorners[0].x, m_CanvasCorners[0].y, m_CanvasCorners[2].x - m_CanvasCorners[0].x, m_CanvasCorners[2].y - m_CanvasCorners[0].y);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c606041f02fc7d542b1429806872292b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,804 @@
using System;
using UnityEngine;
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace UnityEngine.UI
{
/// <summary>
/// Utility class for creating default implementations of builtin UI controls.
/// </summary>
/// <remarks>
/// The recommended workflow for using UI controls with the UI system is to create a prefab for each type of control and instantiate those when needed. This way changes can be made to the prefabs which immediately have effect on all used instances.
///
/// However, in certain cases there can be reasons to create UI controls entirely from code. The DefaultControls class provide methods to create each of the builtin UI controls. The resulting objects are the same as are obtained from using the corresponding UI menu entries in the GameObject menu in the Editor.
///
/// An example use of this is creating menu items for custom new UI controls that mimics the ones that are builtin in Unity. Some such UI controls may contain other UI controls. For example, a scroll view contains scrollbars.By using the DefaultControls methods to create those parts, it is ensured that they are identical in look and setup to the ones provided in the menu items builtin with Unity.
///
/// Note that the details of the setup of the UI controls created by the methods in this class may change with later revisions of the UI system.As such, they are not guaranteed to be 100% backwards compatible. It is recommended not to rely on the specific hierarchies of the GameObjects created by these methods, and limit your code to only interface with the root GameObject created by each method.
/// </remarks>
public static class DefaultControls
{
static IFactoryControls m_CurrentFactory = DefaultRuntimeFactory.Default;
public static IFactoryControls factory
{
get { return m_CurrentFactory; }
#if UNITY_EDITOR
set { m_CurrentFactory = value; }
#endif
}
/// <summary>
/// Factory interface to create a GameObject in this class.
/// It is necessary to use this interface in the whole class so MenuOption and Editor can work using ObjectFactory and default Presets.
/// </summary>
/// <remarks>
/// The only available method is CreateGameObject.
/// It needs to be called with every Components the created Object will need because of a bug with Undo and RectTransform.
/// Adding a UI component on the created GameObject may crash if done after Undo.SetTransformParent,
/// So it's better to prevent such behavior in this class by asking for full creation with all the components.
/// </remarks>
public interface IFactoryControls
{
GameObject CreateGameObject(string name, params Type[] components);
}
private class DefaultRuntimeFactory : IFactoryControls
{
public static IFactoryControls Default = new DefaultRuntimeFactory();
public GameObject CreateGameObject(string name, params Type[] components)
{
return new GameObject(name, components);
}
}
/// <summary>
/// Object used to pass resources to use for the default controls.
/// </summary>
public struct Resources
{
/// <summary>
/// The primary sprite to be used for graphical UI elements, used by the button, toggle, and dropdown controls, among others.
/// </summary>
public Sprite standard;
/// <summary>
/// Sprite used for background elements.
/// </summary>
public Sprite background;
/// <summary>
/// Sprite used as background for input fields.
/// </summary>
public Sprite inputField;
/// <summary>
/// Sprite used for knobs that can be dragged, such as on a slider.
/// </summary>
public Sprite knob;
/// <summary>
/// Sprite used for representation of an "on" state when present, such as a checkmark.
/// </summary>
public Sprite checkmark;
/// <summary>
/// Sprite used to indicate that a button will open a dropdown when clicked.
/// </summary>
public Sprite dropdown;
/// <summary>
/// Sprite used for masking purposes, for example to be used for the viewport of a scroll view.
/// </summary>
public Sprite mask;
}
private const float kWidth = 160f;
private const float kThickHeight = 30f;
private const float kThinHeight = 20f;
private static Vector2 s_ThickElementSize = new Vector2(kWidth, kThickHeight);
private static Vector2 s_ThinElementSize = new Vector2(kWidth, kThinHeight);
private static Vector2 s_ImageElementSize = new Vector2(100f, 100f);
private static Color s_DefaultSelectableColor = new Color(1f, 1f, 1f, 1f);
private static Color s_PanelColor = new Color(1f, 1f, 1f, 0.392f);
private static Color s_TextColor = new Color(50f / 255f, 50f / 255f, 50f / 255f, 1f);
// Helper methods at top
private static GameObject CreateUIElementRoot(string name, Vector2 size, params Type[] components)
{
GameObject child = factory.CreateGameObject(name, components);
RectTransform rectTransform = child.GetComponent<RectTransform>();
rectTransform.sizeDelta = size;
return child;
}
private static GameObject CreateUIObject(string name, GameObject parent, params Type[] components)
{
GameObject go = factory.CreateGameObject(name, components);
SetParentAndAlign(go, parent);
return go;
}
private static void SetDefaultTextValues(Text lbl)
{
// Set text values we want across UI elements in default controls.
// Don't set values which are the same as the default values for the Text component,
// since there's no point in that, and it's good to keep them as consistent as possible.
lbl.color = s_TextColor;
// Reset() is not called when playing. We still want the default font to be assigned
// We may have a font assigned from default preset. We shouldn't override it
if (lbl.font == null)
lbl.AssignDefaultFont();
}
private static void SetDefaultColorTransitionValues(Selectable slider)
{
ColorBlock colors = slider.colors;
colors.highlightedColor = new Color(0.882f, 0.882f, 0.882f);
colors.pressedColor = new Color(0.698f, 0.698f, 0.698f);
colors.disabledColor = new Color(0.521f, 0.521f, 0.521f);
}
private static void SetParentAndAlign(GameObject child, GameObject parent)
{
if (parent == null)
return;
#if UNITY_EDITOR
Undo.SetTransformParent(child.transform, parent.transform, "");
#else
child.transform.SetParent(parent.transform, false);
#endif
SetLayerRecursively(child, parent.layer);
}
private static void SetLayerRecursively(GameObject go, int layer)
{
go.layer = layer;
Transform t = go.transform;
for (int i = 0; i < t.childCount; i++)
SetLayerRecursively(t.GetChild(i).gameObject, layer);
}
/// <summary>
/// Create the basic UI Panel.
/// </summary>
/// <remarks>
/// Hierarchy:
/// (root)
/// Image
/// </remarks>
/// <param name="resources">The resources to use for creation.</param>
/// <returns>The root GameObject of the created element.</returns>
public static GameObject CreatePanel(Resources resources)
{
GameObject panelRoot = CreateUIElementRoot("Panel", s_ThickElementSize, typeof(Image));
// Set RectTransform to stretch
RectTransform rectTransform = panelRoot.GetComponent<RectTransform>();
rectTransform.anchorMin = Vector2.zero;
rectTransform.anchorMax = Vector2.one;
rectTransform.anchoredPosition = Vector2.zero;
rectTransform.sizeDelta = Vector2.zero;
Image image = panelRoot.GetComponent<Image>();
image.sprite = resources.background;
image.type = Image.Type.Sliced;
image.color = s_PanelColor;
return panelRoot;
}
/// <summary>
/// Create the basic UI button.
/// </summary>
/// <remarks>
/// Hierarchy:
/// (root)
/// Button
/// -Text
/// </remarks>
/// <param name="resources">The resources to use for creation.</param>
/// <returns>The root GameObject of the created element.</returns>
public static GameObject CreateButton(Resources resources)
{
GameObject buttonRoot = CreateUIElementRoot("Button (Legacy)", s_ThickElementSize, typeof(Image), typeof(Button));
GameObject childText = CreateUIObject("Text (Legacy)", buttonRoot, typeof(Text));
Image image = buttonRoot.GetComponent<Image>();
image.sprite = resources.standard;
image.type = Image.Type.Sliced;
image.color = s_DefaultSelectableColor;
Button bt = buttonRoot.GetComponent<Button>();
SetDefaultColorTransitionValues(bt);
Text text = childText.GetComponent<Text>();
text.text = "Button";
text.alignment = TextAnchor.MiddleCenter;
SetDefaultTextValues(text);
RectTransform textRectTransform = childText.GetComponent<RectTransform>();
textRectTransform.anchorMin = Vector2.zero;
textRectTransform.anchorMax = Vector2.one;
textRectTransform.sizeDelta = Vector2.zero;
return buttonRoot;
}
/// <summary>
/// Create the basic UI Text.
/// </summary>
/// <remarks>
/// Hierarchy:
/// (root)
/// Text
/// </remarks>
/// <param name="resources">The resources to use for creation.</param>
/// <returns>The root GameObject of the created element.</returns>
public static GameObject CreateText(Resources resources)
{
GameObject go = CreateUIElementRoot("Text (Legacy)", s_ThickElementSize, typeof(Text));
Text lbl = go.GetComponent<Text>();
lbl.text = "New Text";
SetDefaultTextValues(lbl);
return go;
}
/// <summary>
/// Create the basic UI Image.
/// </summary>
/// <remarks>
/// Hierarchy:
/// (root)
/// Image
/// </remarks>
/// <param name="resources">The resources to use for creation.</param>
/// <returns>The root GameObject of the created element.</returns>
public static GameObject CreateImage(Resources resources)
{
GameObject go = CreateUIElementRoot("Image", s_ImageElementSize, typeof(Image));
return go;
}
/// <summary>
/// Create the basic UI RawImage.
/// </summary>
/// <remarks>
/// Hierarchy:
/// (root)
/// RawImage
/// </remarks>
/// <param name="resources">The resources to use for creation.</param>
/// <returns>The root GameObject of the created element.</returns>
public static GameObject CreateRawImage(Resources resources)
{
GameObject go = CreateUIElementRoot("RawImage", s_ImageElementSize, typeof(RawImage));
return go;
}
/// <summary>
/// Create the basic UI Slider.
/// </summary>
/// <remarks>
/// Hierarchy:
/// (root)
/// Slider
/// - Background
/// - Fill Area
/// - Fill
/// - Handle Slide Area
/// - Handle
/// </remarks>
/// <param name="resources">The resources to use for creation.</param>
/// <returns>The root GameObject of the created element.</returns>
public static GameObject CreateSlider(Resources resources)
{
// Create GOs Hierarchy
GameObject root = CreateUIElementRoot("Slider", s_ThinElementSize, typeof(Slider));
GameObject background = CreateUIObject("Background", root, typeof(Image));
GameObject fillArea = CreateUIObject("Fill Area", root, typeof(RectTransform));
GameObject fill = CreateUIObject("Fill", fillArea, typeof(Image));
GameObject handleArea = CreateUIObject("Handle Slide Area", root, typeof(RectTransform));
GameObject handle = CreateUIObject("Handle", handleArea, typeof(Image));
// Background
Image backgroundImage = background.GetComponent<Image>();
backgroundImage.sprite = resources.background;
backgroundImage.type = Image.Type.Sliced;
backgroundImage.color = s_DefaultSelectableColor;
RectTransform backgroundRect = background.GetComponent<RectTransform>();
backgroundRect.anchorMin = new Vector2(0, 0.25f);
backgroundRect.anchorMax = new Vector2(1, 0.75f);
backgroundRect.sizeDelta = new Vector2(0, 0);
// Fill Area
RectTransform fillAreaRect = fillArea.GetComponent<RectTransform>();
fillAreaRect.anchorMin = new Vector2(0, 0.25f);
fillAreaRect.anchorMax = new Vector2(1, 0.75f);
fillAreaRect.anchoredPosition = new Vector2(-5, 0);
fillAreaRect.sizeDelta = new Vector2(-20, 0);
// Fill
Image fillImage = fill.GetComponent<Image>();
fillImage.sprite = resources.standard;
fillImage.type = Image.Type.Sliced;
fillImage.color = s_DefaultSelectableColor;
RectTransform fillRect = fill.GetComponent<RectTransform>();
fillRect.sizeDelta = new Vector2(10, 0);
// Handle Area
RectTransform handleAreaRect = handleArea.GetComponent<RectTransform>();
handleAreaRect.sizeDelta = new Vector2(-20, 0);
handleAreaRect.anchorMin = new Vector2(0, 0);
handleAreaRect.anchorMax = new Vector2(1, 1);
// Handle
Image handleImage = handle.GetComponent<Image>();
handleImage.sprite = resources.knob;
handleImage.color = s_DefaultSelectableColor;
RectTransform handleRect = handle.GetComponent<RectTransform>();
handleRect.sizeDelta = new Vector2(20, 0);
// Setup slider component
Slider slider = root.GetComponent<Slider>();
slider.fillRect = fill.GetComponent<RectTransform>();
slider.handleRect = handle.GetComponent<RectTransform>();
slider.targetGraphic = handleImage;
slider.direction = Slider.Direction.LeftToRight;
SetDefaultColorTransitionValues(slider);
return root;
}
/// <summary>
/// Create the basic UI Scrollbar.
/// </summary>
/// <remarks>
/// Hierarchy:
/// (root)
/// Scrollbar
/// - Sliding Area
/// - Handle
/// </remarks>
/// <param name="resources">The resources to use for creation.</param>
/// <returns>The root GameObject of the created element.</returns>
public static GameObject CreateScrollbar(Resources resources)
{
// Create GOs Hierarchy
GameObject scrollbarRoot = CreateUIElementRoot("Scrollbar", s_ThinElementSize, typeof(Image), typeof(Scrollbar));
GameObject sliderArea = CreateUIObject("Sliding Area", scrollbarRoot, typeof(RectTransform));
GameObject handle = CreateUIObject("Handle", sliderArea, typeof(Image));
Image bgImage = scrollbarRoot.GetComponent<Image>();
bgImage.sprite = resources.background;
bgImage.type = Image.Type.Sliced;
bgImage.color = s_DefaultSelectableColor;
Image handleImage = handle.GetComponent<Image>();
handleImage.sprite = resources.standard;
handleImage.type = Image.Type.Sliced;
handleImage.color = s_DefaultSelectableColor;
RectTransform sliderAreaRect = sliderArea.GetComponent<RectTransform>();
sliderAreaRect.sizeDelta = new Vector2(-20, -20);
sliderAreaRect.anchorMin = Vector2.zero;
sliderAreaRect.anchorMax = Vector2.one;
RectTransform handleRect = handle.GetComponent<RectTransform>();
handleRect.sizeDelta = new Vector2(20, 20);
Scrollbar scrollbar = scrollbarRoot.GetComponent<Scrollbar>();
scrollbar.handleRect = handleRect;
scrollbar.targetGraphic = handleImage;
SetDefaultColorTransitionValues(scrollbar);
return scrollbarRoot;
}
/// <summary>
/// Create the basic UI Toggle.
/// </summary>
/// <remarks>
/// Hierarchy:
/// (root)
/// Toggle
/// - Background
/// - Checkmark
/// - Label
/// </remarks>
/// <param name="resources">The resources to use for creation.</param>
/// <returns>The root GameObject of the created element.</returns>
public static GameObject CreateToggle(Resources resources)
{
// Set up hierarchy
GameObject toggleRoot = CreateUIElementRoot("Toggle", s_ThinElementSize, typeof(Toggle));
GameObject background = CreateUIObject("Background", toggleRoot, typeof(Image));
GameObject checkmark = CreateUIObject("Checkmark", background, typeof(Image));
GameObject childLabel = CreateUIObject("Label", toggleRoot, typeof(Text));
// Set up components
Toggle toggle = toggleRoot.GetComponent<Toggle>();
toggle.isOn = true;
Image bgImage = background.GetComponent<Image>();
bgImage.sprite = resources.standard;
bgImage.type = Image.Type.Sliced;
bgImage.color = s_DefaultSelectableColor;
Image checkmarkImage = checkmark.GetComponent<Image>();
checkmarkImage.sprite = resources.checkmark;
Text label = childLabel.GetComponent<Text>();
label.text = "Toggle";
SetDefaultTextValues(label);
toggle.graphic = checkmarkImage;
toggle.targetGraphic = bgImage;
SetDefaultColorTransitionValues(toggle);
RectTransform bgRect = background.GetComponent<RectTransform>();
bgRect.anchorMin = new Vector2(0f, 1f);
bgRect.anchorMax = new Vector2(0f, 1f);
bgRect.anchoredPosition = new Vector2(10f, -10f);
bgRect.sizeDelta = new Vector2(kThinHeight, kThinHeight);
RectTransform checkmarkRect = checkmark.GetComponent<RectTransform>();
checkmarkRect.anchorMin = new Vector2(0.5f, 0.5f);
checkmarkRect.anchorMax = new Vector2(0.5f, 0.5f);
checkmarkRect.anchoredPosition = Vector2.zero;
checkmarkRect.sizeDelta = new Vector2(20f, 20f);
RectTransform labelRect = childLabel.GetComponent<RectTransform>();
labelRect.anchorMin = new Vector2(0f, 0f);
labelRect.anchorMax = new Vector2(1f, 1f);
labelRect.offsetMin = new Vector2(23f, 1f);
labelRect.offsetMax = new Vector2(-5f, -2f);
return toggleRoot;
}
/// <summary>
/// Create the basic UI input field.
/// </summary>
/// <remarks>
/// Hierarchy:
/// (root)
/// InputField
/// - PlaceHolder
/// - Text
/// </remarks>
/// <param name="resources">The resources to use for creation.</param>
/// <returns>The root GameObject of the created element.</returns>
public static GameObject CreateInputField(Resources resources)
{
GameObject root = CreateUIElementRoot("InputField (Legacy)", s_ThickElementSize, typeof(Image), typeof(InputField));
GameObject childPlaceholder = CreateUIObject("Placeholder", root, typeof(Text));
GameObject childText = CreateUIObject("Text (Legacy)", root, typeof(Text));
Image image = root.GetComponent<Image>();
image.sprite = resources.inputField;
image.type = Image.Type.Sliced;
image.color = s_DefaultSelectableColor;
InputField inputField = root.GetComponent<InputField>();
SetDefaultColorTransitionValues(inputField);
Text text = childText.GetComponent<Text>();
text.text = "";
text.supportRichText = false;
SetDefaultTextValues(text);
Text placeholder = childPlaceholder.GetComponent<Text>();
placeholder.text = "Enter text...";
placeholder.fontStyle = FontStyle.Italic;
// Make placeholder color half as opaque as normal text color.
Color placeholderColor = text.color;
placeholderColor.a *= 0.5f;
placeholder.color = placeholderColor;
RectTransform textRectTransform = childText.GetComponent<RectTransform>();
textRectTransform.anchorMin = Vector2.zero;
textRectTransform.anchorMax = Vector2.one;
textRectTransform.sizeDelta = Vector2.zero;
textRectTransform.offsetMin = new Vector2(10, 6);
textRectTransform.offsetMax = new Vector2(-10, -7);
RectTransform placeholderRectTransform = childPlaceholder.GetComponent<RectTransform>();
placeholderRectTransform.anchorMin = Vector2.zero;
placeholderRectTransform.anchorMax = Vector2.one;
placeholderRectTransform.sizeDelta = Vector2.zero;
placeholderRectTransform.offsetMin = new Vector2(10, 6);
placeholderRectTransform.offsetMax = new Vector2(-10, -7);
inputField.textComponent = text;
inputField.placeholder = placeholder;
return root;
}
/// <summary>
/// Create the basic UI dropdown.
/// </summary>
/// <remarks>
/// Hierarchy:
/// (root)
/// Dropdown
/// - Label
/// - Arrow
/// - Template
/// - Viewport
/// - Content
/// - Item
/// - Item Background
/// - Item Checkmark
/// - Item Label
/// - Scrollbar
/// - Sliding Area
/// - Handle
/// </remarks>
/// <param name="resources">The resources to use for creation.</param>
/// <returns>The root GameObject of the created element.</returns>
public static GameObject CreateDropdown(Resources resources)
{
GameObject root = CreateUIElementRoot("Dropdown (Legacy)", s_ThickElementSize, typeof(Image), typeof(Dropdown));
GameObject label = CreateUIObject("Label", root, typeof(Text));
GameObject arrow = CreateUIObject("Arrow", root, typeof(Image));
GameObject template = CreateUIObject("Template", root, typeof(Image), typeof(ScrollRect));
GameObject viewport = CreateUIObject("Viewport", template, typeof(Image), typeof(Mask));
GameObject content = CreateUIObject("Content", viewport, typeof(RectTransform));
GameObject item = CreateUIObject("Item", content, typeof(Toggle));
GameObject itemBackground = CreateUIObject("Item Background", item, typeof(Image));
GameObject itemCheckmark = CreateUIObject("Item Checkmark", item, typeof(Image));
GameObject itemLabel = CreateUIObject("Item Label", item, typeof(Text));
// Sub controls.
GameObject scrollbar = CreateScrollbar(resources);
scrollbar.name = "Scrollbar";
SetParentAndAlign(scrollbar, template);
Scrollbar scrollbarScrollbar = scrollbar.GetComponent<Scrollbar>();
scrollbarScrollbar.SetDirection(Scrollbar.Direction.BottomToTop, true);
RectTransform vScrollbarRT = scrollbar.GetComponent<RectTransform>();
vScrollbarRT.anchorMin = Vector2.right;
vScrollbarRT.anchorMax = Vector2.one;
vScrollbarRT.pivot = Vector2.one;
vScrollbarRT.sizeDelta = new Vector2(vScrollbarRT.sizeDelta.x, 0);
// Setup item UI components.
Text itemLabelText = itemLabel.GetComponent<Text>();
SetDefaultTextValues(itemLabelText);
itemLabelText.alignment = TextAnchor.MiddleLeft;
Image itemBackgroundImage = itemBackground.GetComponent<Image>();
itemBackgroundImage.color = new Color32(245, 245, 245, 255);
Image itemCheckmarkImage = itemCheckmark.GetComponent<Image>();
itemCheckmarkImage.sprite = resources.checkmark;
Toggle itemToggle = item.GetComponent<Toggle>();
itemToggle.targetGraphic = itemBackgroundImage;
itemToggle.graphic = itemCheckmarkImage;
itemToggle.isOn = true;
// Setup template UI components.
Image templateImage = template.GetComponent<Image>();
templateImage.sprite = resources.standard;
templateImage.type = Image.Type.Sliced;
ScrollRect templateScrollRect = template.GetComponent<ScrollRect>();
templateScrollRect.content = content.GetComponent<RectTransform>();
templateScrollRect.viewport = viewport.GetComponent<RectTransform>();
templateScrollRect.horizontal = false;
templateScrollRect.movementType = ScrollRect.MovementType.Clamped;
templateScrollRect.verticalScrollbar = scrollbarScrollbar;
templateScrollRect.verticalScrollbarVisibility = ScrollRect.ScrollbarVisibility.AutoHideAndExpandViewport;
templateScrollRect.verticalScrollbarSpacing = -3;
Mask scrollRectMask = viewport.GetComponent<Mask>();
scrollRectMask.showMaskGraphic = false;
Image viewportImage = viewport.GetComponent<Image>();
viewportImage.sprite = resources.mask;
viewportImage.type = Image.Type.Sliced;
// Setup dropdown UI components.
Text labelText = label.GetComponent<Text>();
SetDefaultTextValues(labelText);
labelText.alignment = TextAnchor.MiddleLeft;
Image arrowImage = arrow.GetComponent<Image>();
arrowImage.sprite = resources.dropdown;
Image backgroundImage = root.GetComponent<Image>();
backgroundImage.sprite = resources.standard;
backgroundImage.color = s_DefaultSelectableColor;
backgroundImage.type = Image.Type.Sliced;
Dropdown dropdown = root.GetComponent<Dropdown>();
dropdown.targetGraphic = backgroundImage;
SetDefaultColorTransitionValues(dropdown);
dropdown.template = template.GetComponent<RectTransform>();
dropdown.captionText = labelText;
dropdown.itemText = itemLabelText;
// Setting default Item list.
itemLabelText.text = "Option A";
dropdown.options.Add(new Dropdown.OptionData {text = "Option A"});
dropdown.options.Add(new Dropdown.OptionData {text = "Option B"});
dropdown.options.Add(new Dropdown.OptionData {text = "Option C"});
dropdown.RefreshShownValue();
// Set up RectTransforms.
RectTransform labelRT = label.GetComponent<RectTransform>();
labelRT.anchorMin = Vector2.zero;
labelRT.anchorMax = Vector2.one;
labelRT.offsetMin = new Vector2(10, 6);
labelRT.offsetMax = new Vector2(-25, -7);
RectTransform arrowRT = arrow.GetComponent<RectTransform>();
arrowRT.anchorMin = new Vector2(1, 0.5f);
arrowRT.anchorMax = new Vector2(1, 0.5f);
arrowRT.sizeDelta = new Vector2(20, 20);
arrowRT.anchoredPosition = new Vector2(-15, 0);
RectTransform templateRT = template.GetComponent<RectTransform>();
templateRT.anchorMin = new Vector2(0, 0);
templateRT.anchorMax = new Vector2(1, 0);
templateRT.pivot = new Vector2(0.5f, 1);
templateRT.anchoredPosition = new Vector2(0, 2);
templateRT.sizeDelta = new Vector2(0, 150);
RectTransform viewportRT = viewport.GetComponent<RectTransform>();
viewportRT.anchorMin = new Vector2(0, 0);
viewportRT.anchorMax = new Vector2(1, 1);
viewportRT.sizeDelta = new Vector2(-18, 0);
viewportRT.pivot = new Vector2(0, 1);
RectTransform contentRT = content.GetComponent<RectTransform>();
contentRT.anchorMin = new Vector2(0f, 1);
contentRT.anchorMax = new Vector2(1f, 1);
contentRT.pivot = new Vector2(0.5f, 1);
contentRT.anchoredPosition = new Vector2(0, 0);
contentRT.sizeDelta = new Vector2(0, 28);
RectTransform itemRT = item.GetComponent<RectTransform>();
itemRT.anchorMin = new Vector2(0, 0.5f);
itemRT.anchorMax = new Vector2(1, 0.5f);
itemRT.sizeDelta = new Vector2(0, 20);
RectTransform itemBackgroundRT = itemBackground.GetComponent<RectTransform>();
itemBackgroundRT.anchorMin = Vector2.zero;
itemBackgroundRT.anchorMax = Vector2.one;
itemBackgroundRT.sizeDelta = Vector2.zero;
RectTransform itemCheckmarkRT = itemCheckmark.GetComponent<RectTransform>();
itemCheckmarkRT.anchorMin = new Vector2(0, 0.5f);
itemCheckmarkRT.anchorMax = new Vector2(0, 0.5f);
itemCheckmarkRT.sizeDelta = new Vector2(20, 20);
itemCheckmarkRT.anchoredPosition = new Vector2(10, 0);
RectTransform itemLabelRT = itemLabel.GetComponent<RectTransform>();
itemLabelRT.anchorMin = Vector2.zero;
itemLabelRT.anchorMax = Vector2.one;
itemLabelRT.offsetMin = new Vector2(20, 1);
itemLabelRT.offsetMax = new Vector2(-10, -2);
template.SetActive(false);
return root;
}
/// <summary>
/// Create the basic UI Scrollview.
/// </summary>
/// <remarks>
/// Hierarchy:
/// (root)
/// Scrollview
/// - Viewport
/// - Content
/// - Scrollbar Horizontal
/// - Sliding Area
/// - Handle
/// - Scrollbar Vertical
/// - Sliding Area
/// - Handle
/// </remarks>
/// <param name="resources">The resources to use for creation.</param>
/// <returns>The root GameObject of the created element.</returns>
public static GameObject CreateScrollView(Resources resources)
{
GameObject root = CreateUIElementRoot("Scroll View", new Vector2(200, 200), typeof(Image), typeof(ScrollRect));
GameObject viewport = CreateUIObject("Viewport", root, typeof(Image), typeof(Mask));
GameObject content = CreateUIObject("Content", viewport, typeof(RectTransform));
// Sub controls.
GameObject hScrollbar = CreateScrollbar(resources);
hScrollbar.name = "Scrollbar Horizontal";
SetParentAndAlign(hScrollbar, root);
RectTransform hScrollbarRT = hScrollbar.GetComponent<RectTransform>();
hScrollbarRT.anchorMin = Vector2.zero;
hScrollbarRT.anchorMax = Vector2.right;
hScrollbarRT.pivot = Vector2.zero;
hScrollbarRT.sizeDelta = new Vector2(0, hScrollbarRT.sizeDelta.y);
GameObject vScrollbar = CreateScrollbar(resources);
vScrollbar.name = "Scrollbar Vertical";
SetParentAndAlign(vScrollbar, root);
vScrollbar.GetComponent<Scrollbar>().SetDirection(Scrollbar.Direction.BottomToTop, true);
RectTransform vScrollbarRT = vScrollbar.GetComponent<RectTransform>();
vScrollbarRT.anchorMin = Vector2.right;
vScrollbarRT.anchorMax = Vector2.one;
vScrollbarRT.pivot = Vector2.one;
vScrollbarRT.sizeDelta = new Vector2(vScrollbarRT.sizeDelta.x, 0);
// Setup RectTransforms.
// Make viewport fill entire scroll view.
RectTransform viewportRT = viewport.GetComponent<RectTransform>();
viewportRT.anchorMin = Vector2.zero;
viewportRT.anchorMax = Vector2.one;
viewportRT.sizeDelta = Vector2.zero;
viewportRT.pivot = Vector2.up;
// Make context match viewpoprt width and be somewhat taller.
// This will show the vertical scrollbar and not the horizontal one.
RectTransform contentRT = content.GetComponent<RectTransform>();
contentRT.anchorMin = Vector2.up;
contentRT.anchorMax = Vector2.one;
contentRT.sizeDelta = new Vector2(0, 300);
contentRT.pivot = Vector2.up;
// Setup UI components.
ScrollRect scrollRect = root.GetComponent<ScrollRect>();
scrollRect.content = contentRT;
scrollRect.viewport = viewportRT;
scrollRect.horizontalScrollbar = hScrollbar.GetComponent<Scrollbar>();
scrollRect.verticalScrollbar = vScrollbar.GetComponent<Scrollbar>();
scrollRect.horizontalScrollbarVisibility = ScrollRect.ScrollbarVisibility.AutoHideAndExpandViewport;
scrollRect.verticalScrollbarVisibility = ScrollRect.ScrollbarVisibility.AutoHideAndExpandViewport;
scrollRect.horizontalScrollbarSpacing = -3;
scrollRect.verticalScrollbarSpacing = -3;
Image rootImage = root.GetComponent<Image>();
rootImage.sprite = resources.background;
rootImage.type = Image.Type.Sliced;
rootImage.color = s_PanelColor;
Mask viewportMask = viewport.GetComponent<Mask>();
viewportMask.showMaskGraphic = false;
Image viewportImage = viewport.GetComponent<Image>();
viewportImage.sprite = resources.mask;
viewportImage.type = Image.Type.Sliced;
return root;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bf87e20fb5440ec498f441167b5291f8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0d0b652f32a2cc243917e4028fa0f046
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,199 @@
using System;
using UnityEngine.Serialization;
namespace UnityEngine.UI
{
[Serializable]
/// <summary>
/// Struct for storing Text generation settings.
/// </summary>
public class FontData : ISerializationCallbackReceiver
{
[SerializeField]
[FormerlySerializedAs("font")]
private Font m_Font;
[SerializeField]
[FormerlySerializedAs("fontSize")]
private int m_FontSize;
[SerializeField]
[FormerlySerializedAs("fontStyle")]
private FontStyle m_FontStyle;
[SerializeField]
private bool m_BestFit;
[SerializeField]
private int m_MinSize;
[SerializeField]
private int m_MaxSize;
[SerializeField]
[FormerlySerializedAs("alignment")]
private TextAnchor m_Alignment;
[SerializeField]
private bool m_AlignByGeometry;
[SerializeField]
[FormerlySerializedAs("richText")]
private bool m_RichText;
[SerializeField]
private HorizontalWrapMode m_HorizontalOverflow;
[SerializeField]
private VerticalWrapMode m_VerticalOverflow;
[SerializeField]
private float m_LineSpacing;
/// <summary>
/// Get a font data with sensible defaults.
/// </summary>
public static FontData defaultFontData
{
get
{
var fontData = new FontData
{
m_FontSize = 14,
m_LineSpacing = 1f,
m_FontStyle = FontStyle.Normal,
m_BestFit = false,
m_MinSize = 10,
m_MaxSize = 40,
m_Alignment = TextAnchor.UpperLeft,
m_HorizontalOverflow = HorizontalWrapMode.Wrap,
m_VerticalOverflow = VerticalWrapMode.Truncate,
m_RichText = true,
m_AlignByGeometry = false
};
return fontData;
}
}
/// <summary>
/// The Font to use for this generated Text object.
/// </summary>
public Font font
{
get { return m_Font; }
set { m_Font = value; }
}
/// <summary>
/// The Font size to use for this generated Text object.
/// </summary>
public int fontSize
{
get { return m_FontSize; }
set { m_FontSize = value; }
}
/// <summary>
/// The font style to use for this generated Text object.
/// </summary>
public FontStyle fontStyle
{
get { return m_FontStyle; }
set { m_FontStyle = value; }
}
/// <summary>
/// Is best fit used for this generated Text object.
/// </summary>
public bool bestFit
{
get { return m_BestFit; }
set { m_BestFit = value; }
}
/// <summary>
/// The min size for this generated Text object.
/// </summary>
public int minSize
{
get { return m_MinSize; }
set { m_MinSize = value; }
}
/// <summary>
/// The max size for this generated Text object.
/// </summary>
public int maxSize
{
get { return m_MaxSize; }
set { m_MaxSize = value; }
}
/// <summary>
/// How is the text aligned for this generated Text object.
/// </summary>
public TextAnchor alignment
{
get { return m_Alignment; }
set { m_Alignment = value; }
}
/// <summary>
/// Use the extents of glyph geometry to perform horizontal alignment rather than glyph metrics.
/// </summary>
/// <remarks>
/// This can result in better fitting left and right alignment, but may result in incorrect positioning when attempting to overlay multiple fonts (such as a specialized outline font) on top of each other.
/// </remarks>
public bool alignByGeometry
{
get { return m_AlignByGeometry; }
set { m_AlignByGeometry = value; }
}
/// <summary>
/// Should rich text be used for this generated Text object.
/// </summary>
public bool richText
{
get { return m_RichText; }
set { m_RichText = value; }
}
/// <summary>
/// The horizontal overflow policy for this generated Text object.
/// </summary>
public HorizontalWrapMode horizontalOverflow
{
get { return m_HorizontalOverflow; }
set { m_HorizontalOverflow = value; }
}
/// <summary>
/// The vertical overflow policy for this generated Text object.
/// </summary>
public VerticalWrapMode verticalOverflow
{
get { return m_VerticalOverflow; }
set { m_VerticalOverflow = value; }
}
/// <summary>
/// The line spaceing for this generated Text object.
/// </summary>
public float lineSpacing
{
get { return m_LineSpacing; }
set { m_LineSpacing = value; }
}
void ISerializationCallbackReceiver.OnBeforeSerialize()
{}
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
m_FontSize = Mathf.Clamp(m_FontSize, 0, 300);
m_MinSize = Mathf.Clamp(m_MinSize, 0, m_FontSize);
m_MaxSize = Mathf.Clamp(m_MaxSize, m_FontSize, 300);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 13cd966480ec3354bb318ee1aeccff6f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace UnityEngine.UI
{
/// <summary>
/// Utility class that is used to help with Text update.
/// </summary>
/// <remarks>
/// When Unity rebuilds a font atlas a callback is sent to the font. Using this class you can register your text as needing to be rebuilt if the font atlas is updated.
/// </remarks>
public static class FontUpdateTracker
{
static Dictionary<Font, HashSet<Text>> m_Tracked = new Dictionary<Font, HashSet<Text>>();
/// <summary>
/// Register a Text element for receiving texture atlas rebuild calls.
/// </summary>
/// <param name="t">The Text object to track</param>
public static void TrackText(Text t)
{
if (t.font == null)
return;
HashSet<Text> exists;
m_Tracked.TryGetValue(t.font, out exists);
if (exists == null)
{
// The textureRebuilt event is global for all fonts, so we add our delegate the first time we register *any* Text
if (m_Tracked.Count == 0)
Font.textureRebuilt += RebuildForFont;
exists = new HashSet<Text>();
m_Tracked.Add(t.font, exists);
}
exists.Add(t);
}
private static void RebuildForFont(Font f)
{
HashSet<Text> texts;
m_Tracked.TryGetValue(f, out texts);
if (texts == null)
return;
foreach (var text in texts)
text.FontTextureChanged();
}
/// <summary>
/// Deregister a Text element from receiving texture atlas rebuild calls.
/// </summary>
/// <param name="t">The Text object to no longer track</param>
public static void UntrackText(Text t)
{
if (t.font == null)
return;
HashSet<Text> texts;
m_Tracked.TryGetValue(t.font, out texts);
if (texts == null)
return;
texts.Remove(t);
if (texts.Count == 0)
{
m_Tracked.Remove(t.font);
// There is a global textureRebuilt event for all fonts, so once the last Text reference goes away, remove our delegate
if (m_Tracked.Count == 0)
Font.textureRebuilt -= RebuildForFont;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 39ab466162988eb4f83443f911bbf5c8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a6238e9452bfc704f82ff36791fe1a45
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,340 @@
using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine.EventSystems;
using UnityEngine.Serialization;
namespace UnityEngine.UI
{
[AddComponentMenu("Event/Graphic Raycaster")]
[RequireComponent(typeof(Canvas))]
/// <summary>
/// A derived BaseRaycaster to raycast against Graphic elements.
/// </summary>
public class GraphicRaycaster : BaseRaycaster
{
protected const int kNoEventMaskSet = -1;
/// <summary>
/// Type of raycasters to check against to check for canvas blocking elements.
/// </summary>
public enum BlockingObjects
{
/// <summary>
/// Perform no raycasts.
/// </summary>
None = 0,
/// <summary>
/// Perform a 2D raycast check to check for blocking 2D elements
/// </summary>
TwoD = 1,
/// <summary>
/// Perform a 3D raycast check to check for blocking 3D elements
/// </summary>
ThreeD = 2,
/// <summary>
/// Perform a 2D and a 3D raycasts to check for blocking 2D and 3D elements.
/// </summary>
All = 3,
}
/// <summary>
/// Priority of the raycaster based upon sort order.
/// </summary>
/// <returns>
/// The sortOrder priority.
/// </returns>
public override int sortOrderPriority
{
get
{
// We need to return the sorting order here as distance will all be 0 for overlay.
if (canvas.renderMode == RenderMode.ScreenSpaceOverlay)
return canvas.sortingOrder;
return base.sortOrderPriority;
}
}
/// <summary>
/// Priority of the raycaster based upon render order.
/// </summary>
/// <returns>
/// The renderOrder priority.
/// </returns>
public override int renderOrderPriority
{
get
{
// We need to return the sorting order here as distance will all be 0 for overlay.
if (canvas.renderMode == RenderMode.ScreenSpaceOverlay)
return canvas.rootCanvas.renderOrder;
return base.renderOrderPriority;
}
}
[FormerlySerializedAs("ignoreReversedGraphics")]
[SerializeField]
private bool m_IgnoreReversedGraphics = true;
[FormerlySerializedAs("blockingObjects")]
[SerializeField]
private BlockingObjects m_BlockingObjects = BlockingObjects.None;
/// <summary>
/// Whether Graphics facing away from the raycaster are checked for raycasts.
/// </summary>
public bool ignoreReversedGraphics { get {return m_IgnoreReversedGraphics; } set { m_IgnoreReversedGraphics = value; } }
/// <summary>
/// The type of objects that are checked to determine if they block graphic raycasts.
/// </summary>
public BlockingObjects blockingObjects { get {return m_BlockingObjects; } set { m_BlockingObjects = value; } }
[SerializeField]
protected LayerMask m_BlockingMask = kNoEventMaskSet;
/// <summary>
/// The type of objects specified through LayerMask that are checked to determine if they block graphic raycasts.
/// </summary>
public LayerMask blockingMask { get { return m_BlockingMask; } set { m_BlockingMask = value; } }
private Canvas m_Canvas;
protected GraphicRaycaster()
{}
private Canvas canvas
{
get
{
if (m_Canvas != null)
return m_Canvas;
m_Canvas = GetComponent<Canvas>();
return m_Canvas;
}
}
[NonSerialized] private List<Graphic> m_RaycastResults = new List<Graphic>();
/// <summary>
/// Perform the raycast against the list of graphics associated with the Canvas.
/// </summary>
/// <param name="eventData">Current event data</param>
/// <param name="resultAppendList">List of hit objects to append new results to.</param>
public override void Raycast(PointerEventData eventData, List<RaycastResult> resultAppendList)
{
if (canvas == null)
return;
var canvasGraphics = GraphicRegistry.GetRaycastableGraphicsForCanvas(canvas);
if (canvasGraphics == null || canvasGraphics.Count == 0)
return;
int displayIndex;
var currentEventCamera = eventCamera; // Property can call Camera.main, so cache the reference
if (canvas.renderMode == RenderMode.ScreenSpaceOverlay || currentEventCamera == null)
displayIndex = canvas.targetDisplay;
else
displayIndex = currentEventCamera.targetDisplay;
Vector3 eventPosition = MultipleDisplayUtilities.GetRelativeMousePositionForRaycast(eventData);
// Discard events that are not part of this display so the user does not interact with multiple displays at once.
if ((int) eventPosition.z != displayIndex)
return;
// Convert to view space
Vector2 pos;
if (currentEventCamera == null)
{
// Multiple display support only when not the main display. For display 0 the reported
// resolution is always the desktops resolution since its part of the display API,
// so we use the standard none multiple display method. (case 741751)
float w = Screen.width;
float h = Screen.height;
if (displayIndex > 0 && displayIndex < Display.displays.Length)
{
w = Display.displays[displayIndex].systemWidth;
h = Display.displays[displayIndex].systemHeight;
}
pos = new Vector2(eventPosition.x / w, eventPosition.y / h);
}
else
pos = currentEventCamera.ScreenToViewportPoint(eventPosition);
// If it's outside the camera's viewport, do nothing
if (pos.x < 0f || pos.x > 1f || pos.y < 0f || pos.y > 1f)
return;
float hitDistance = float.MaxValue;
Ray ray = new Ray();
if (currentEventCamera != null)
ray = currentEventCamera.ScreenPointToRay(eventPosition);
if (canvas.renderMode != RenderMode.ScreenSpaceOverlay && blockingObjects != BlockingObjects.None)
{
float distanceToClipPlane = 100.0f;
if (currentEventCamera != null)
{
float projectionDirection = ray.direction.z;
distanceToClipPlane = Mathf.Approximately(0.0f, projectionDirection)
? Mathf.Infinity
: Mathf.Abs((currentEventCamera.farClipPlane - currentEventCamera.nearClipPlane) / projectionDirection);
}
#if PACKAGE_PHYSICS
if (blockingObjects == BlockingObjects.ThreeD || blockingObjects == BlockingObjects.All)
{
if (ReflectionMethodsCache.Singleton.raycast3D != null)
{
RaycastHit hit;
if (ReflectionMethodsCache.Singleton.raycast3D(ray, out hit, distanceToClipPlane, (int)m_BlockingMask))
{
hitDistance = hit.distance;
}
}
}
#endif
#if PACKAGE_PHYSICS2D
if (blockingObjects == BlockingObjects.TwoD || blockingObjects == BlockingObjects.All)
{
if (ReflectionMethodsCache.Singleton.raycast2D != null)
{
var hits = ReflectionMethodsCache.Singleton.getRayIntersectionAll(ray, distanceToClipPlane, (int)m_BlockingMask);
if (hits.Length > 0)
hitDistance = hits[0].distance;
}
}
#endif
}
m_RaycastResults.Clear();
Raycast(canvas, currentEventCamera, eventPosition, canvasGraphics, m_RaycastResults);
int totalCount = m_RaycastResults.Count;
for (var index = 0; index < totalCount; index++)
{
var go = m_RaycastResults[index].gameObject;
bool appendGraphic = true;
if (ignoreReversedGraphics)
{
if (currentEventCamera == null)
{
// If we dont have a camera we know that we should always be facing forward
var dir = go.transform.rotation * Vector3.forward;
appendGraphic = Vector3.Dot(Vector3.forward, dir) > 0;
}
else
{
// If we have a camera compare the direction against the cameras forward.
var cameraForward = currentEventCamera.transform.rotation * Vector3.forward * currentEventCamera.nearClipPlane;
appendGraphic = Vector3.Dot(go.transform.position - currentEventCamera.transform.position - cameraForward, go.transform.forward) >= 0;
}
}
if (appendGraphic)
{
float distance = 0;
Transform trans = go.transform;
Vector3 transForward = trans.forward;
if (currentEventCamera == null || canvas.renderMode == RenderMode.ScreenSpaceOverlay)
distance = 0;
else
{
// http://geomalgorithms.com/a06-_intersect-2.html
distance = (Vector3.Dot(transForward, trans.position - ray.origin) / Vector3.Dot(transForward, ray.direction));
// Check to see if the go is behind the camera.
if (distance < 0)
continue;
}
if (distance >= hitDistance)
continue;
var castResult = new RaycastResult
{
gameObject = go,
module = this,
distance = distance,
screenPosition = eventPosition,
displayIndex = displayIndex,
index = resultAppendList.Count,
depth = m_RaycastResults[index].depth,
sortingLayer = canvas.sortingLayerID,
sortingOrder = canvas.sortingOrder,
worldPosition = ray.origin + ray.direction * distance,
worldNormal = -transForward
};
resultAppendList.Add(castResult);
}
}
}
/// <summary>
/// The camera that will generate rays for this raycaster.
/// </summary>
/// <returns>
/// - Null if Camera mode is ScreenSpaceOverlay or ScreenSpaceCamera and has no camera.
/// - canvas.worldCanvas if not null
/// - Camera.main.
/// </returns>
public override Camera eventCamera
{
get
{
var canvas = this.canvas;
var renderMode = canvas.renderMode;
if (renderMode == RenderMode.ScreenSpaceOverlay
|| (renderMode == RenderMode.ScreenSpaceCamera && canvas.worldCamera == null))
return null;
return canvas.worldCamera ?? Camera.main;
}
}
/// <summary>
/// Perform a raycast into the screen and collect all graphics underneath it.
/// </summary>
[NonSerialized] static readonly List<Graphic> s_SortedGraphics = new List<Graphic>();
private static void Raycast(Canvas canvas, Camera eventCamera, Vector2 pointerPosition, IList<Graphic> foundGraphics, List<Graphic> results)
{
// Necessary for the event system
int totalCount = foundGraphics.Count;
for (int i = 0; i < totalCount; ++i)
{
Graphic graphic = foundGraphics[i];
// -1 means it hasn't been processed by the canvas, which means it isn't actually drawn
if (!graphic.raycastTarget || graphic.canvasRenderer.cull || graphic.depth == -1)
continue;
if (!RectTransformUtility.RectangleContainsScreenPoint(graphic.rectTransform, pointerPosition, eventCamera, graphic.raycastPadding))
continue;
if (eventCamera != null && eventCamera.WorldToScreenPoint(graphic.rectTransform.position).z > eventCamera.farClipPlane)
continue;
if (graphic.Raycast(pointerPosition, eventCamera))
{
s_SortedGraphics.Add(graphic);
}
}
s_SortedGraphics.Sort((g1, g2) => g2.depth.CompareTo(g1.depth));
totalCount = s_SortedGraphics.Count;
for (int i = 0; i < totalCount; ++i)
results.Add(s_SortedGraphics[i]);
s_SortedGraphics.Clear();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dc42784cf147c0c48a680349fa168899
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,59 @@
#if UNITY_EDITOR
using System.Collections.Generic;
using UnityEngine.UI.Collections;
namespace UnityEngine.UI
{
/// <summary>
/// EditorOnly class for tracking all Graphics.
/// Used when a source asset is reimported into the editor to ensure that Graphics are updated as intended.
/// </summary>
public static class GraphicRebuildTracker
{
static IndexedSet<Graphic> m_Tracked = new IndexedSet<Graphic>();
static bool s_Initialized;
/// <summary>
/// Add a Graphic to the list of tracked Graphics
/// </summary>
/// <param name="g">The graphic to track</param>
public static void TrackGraphic(Graphic g)
{
if (!s_Initialized)
{
CanvasRenderer.onRequestRebuild += OnRebuildRequested;
s_Initialized = true;
}
m_Tracked.AddUnique(g);
}
/// <summary>
/// Remove a Graphic to the list of tracked Graphics
/// </summary>
/// <param name="g">The graphic to remove from tracking.</param>
public static void UnTrackGraphic(Graphic g)
{
m_Tracked.Remove(g);
}
/// <summary>
/// Remove a Graphic to the list of tracked Graphics
/// </summary>
/// <param name="g">The graphic to remove from tracking.</param>
public static void DisableTrackGraphic(Graphic g)
{
m_Tracked.DisableItem(g);
}
static void OnRebuildRequested()
{
StencilMaterial.ClearAll();
for (int i = 0; i < m_Tracked.Count; i++)
{
m_Tracked[i].OnRebuildRequested();
}
}
}
}
#endif // if UNITY_EDITOR

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 445cdcfc747eba94288b97f5869aa2fb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,212 @@
using System.Collections.Generic;
using UnityEngine.UI.Collections;
namespace UnityEngine.UI
{
/// <summary>
/// Registry which maps a Graphic to the canvas it belongs to.
/// </summary>
public class GraphicRegistry
{
private static GraphicRegistry s_Instance;
private readonly Dictionary<Canvas, IndexedSet<Graphic>> m_Graphics = new Dictionary<Canvas, IndexedSet<Graphic>>();
private readonly Dictionary<Canvas, IndexedSet<Graphic>> m_RaycastableGraphics = new Dictionary<Canvas, IndexedSet<Graphic>>();
protected GraphicRegistry()
{
// Avoid runtime generation of these types. Some platforms are AOT only and do not support
// JIT. What's more we actually create a instance of the required types instead of
// just declaring an unused variable which may be optimized away by some compilers (Mono vs MS).
// See: 877060
System.GC.KeepAlive(new Dictionary<Graphic, int>());
System.GC.KeepAlive(new Dictionary<ICanvasElement, int>());
System.GC.KeepAlive(new Dictionary<IClipper, int>());
}
/// <summary>
/// The singleton instance of the GraphicRegistry. Creates a new instance if it does not exist.
/// </summary>
public static GraphicRegistry instance
{
get
{
if (s_Instance == null)
s_Instance = new GraphicRegistry();
return s_Instance;
}
}
/// <summary>
/// Associates a Graphic with a Canvas and stores this association in the registry.
/// </summary>
/// <param name="c">The canvas being associated with the Graphic.</param>
/// <param name="graphic">The Graphic being associated with the Canvas.</param>
public static void RegisterGraphicForCanvas(Canvas c, Graphic graphic)
{
if (c == null || graphic == null)
return;
IndexedSet<Graphic> graphics;
instance.m_Graphics.TryGetValue(c, out graphics);
if (graphics != null)
{
graphics.AddUnique(graphic);
RegisterRaycastGraphicForCanvas(c, graphic);
return;
}
// Dont need to AddUnique as we know its the only item in the list
graphics = new IndexedSet<Graphic>();
graphics.Add(graphic);
instance.m_Graphics.Add(c, graphics);
RegisterRaycastGraphicForCanvas(c, graphic);
}
/// <summary>
/// Associates a raycastable Graphic with a Canvas and stores this association in the registry.
/// </summary>
/// <param name="c">The canvas being associated with the Graphic.</param>
/// <param name="graphic">The Graphic being associated with the Canvas.</param>
public static void RegisterRaycastGraphicForCanvas(Canvas c, Graphic graphic)
{
if (c == null || graphic == null || !graphic.raycastTarget)
return;
IndexedSet<Graphic> graphics;
instance.m_RaycastableGraphics.TryGetValue(c, out graphics);
if (graphics != null)
{
graphics.AddUnique(graphic);
return;
}
// Dont need to AddUnique as we know its the only item in the list
graphics = new IndexedSet<Graphic>();
graphics.Add(graphic);
instance.m_RaycastableGraphics.Add(c, graphics);
}
/// <summary>
/// Dissociates a Graphic from a Canvas, removing this association from the registry.
/// </summary>
/// <param name="c">The Canvas to dissociate from the Graphic.</param>
/// <param name="graphic">The Graphic to dissociate from the Canvas.</param>
public static void UnregisterGraphicForCanvas(Canvas c, Graphic graphic)
{
if (c == null || graphic == null)
return;
IndexedSet<Graphic> graphics;
if (instance.m_Graphics.TryGetValue(c, out graphics))
{
graphics.Remove(graphic);
if (graphics.Capacity == 0)
instance.m_Graphics.Remove(c);
UnregisterRaycastGraphicForCanvas(c, graphic);
}
}
/// <summary>
/// Dissociates a Graphic from a Canvas, removing this association from the registry.
/// </summary>
/// <param name="c">The Canvas to dissociate from the Graphic.</param>
/// <param name="graphic">The Graphic to dissociate from the Canvas.</param>
public static void UnregisterRaycastGraphicForCanvas(Canvas c, Graphic graphic)
{
if (c == null || graphic == null)
return;
IndexedSet<Graphic> graphics;
if (instance.m_RaycastableGraphics.TryGetValue(c, out graphics))
{
graphics.Remove(graphic);
if (graphics.Count == 0)
instance.m_RaycastableGraphics.Remove(c);
}
}
/// <summary>
/// Disables a Graphic from a Canvas, disabling this association from the registry.
/// </summary>
/// <param name="c">The Canvas to dissociate from the Graphic.</param>
/// <param name="graphic">The Graphic to dissociate from the Canvas.</param>
public static void DisableGraphicForCanvas(Canvas c, Graphic graphic)
{
if (c == null)
return;
IndexedSet<Graphic> graphics;
if (instance.m_Graphics.TryGetValue(c, out graphics))
{
graphics.DisableItem(graphic);
if (graphics.Capacity == 0)
instance.m_Graphics.Remove(c);
DisableRaycastGraphicForCanvas(c, graphic);
}
}
/// <summary>
/// Disables the raycast for a Graphic from a Canvas, disabling this association from the registry.
/// </summary>
/// <param name="c">The Canvas to dissociate from the Graphic.</param>
/// <param name="graphic">The Graphic to dissociate from the Canvas.</param>
public static void DisableRaycastGraphicForCanvas(Canvas c, Graphic graphic)
{
if (c == null || !graphic.raycastTarget)
return;
IndexedSet<Graphic> graphics;
if (instance.m_RaycastableGraphics.TryGetValue(c, out graphics))
{
graphics.DisableItem(graphic);
if (graphics.Capacity == 0)
instance.m_RaycastableGraphics.Remove(c);
}
}
private static readonly List<Graphic> s_EmptyList = new List<Graphic>();
/// <summary>
/// Retrieves the list of Graphics associated with a Canvas.
/// </summary>
/// <param name="canvas">The Canvas to search</param>
/// <returns>Returns a list of Graphics. Returns an empty list if no Graphics are associated with the specified Canvas.</returns>
public static IList<Graphic> GetGraphicsForCanvas(Canvas canvas)
{
IndexedSet<Graphic> graphics;
if (instance.m_Graphics.TryGetValue(canvas, out graphics))
return graphics;
return s_EmptyList;
}
/// <summary>
/// Retrieves the list of Graphics that are raycastable and associated with a Canvas.
/// </summary>
/// <param name="canvas">The Canvas to search</param>
/// <returns>Returns a list of Graphics. Returns an empty list if no Graphics are associated with the specified Canvas.</returns>
public static IList<Graphic> GetRaycastableGraphicsForCanvas(Canvas canvas)
{
IndexedSet<Graphic> graphics;
if (instance.m_RaycastableGraphics.TryGetValue(canvas, out graphics))
return graphics;
return s_EmptyList;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 69e3979b7029e8a4da2d96b714ba5c3a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,10 @@
using System;
namespace UnityEngine.UI
{
[Obsolete("Not supported anymore")]
interface IGraphicEnabledDisabled
{
void OnSiblingGraphicEnabledDisabled();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 928dc55e2c8c3ee4dad33b6d561cb6ea
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,12 @@
using System;
namespace UnityEngine.UI
{
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
[Obsolete("Not supported anymore.", true)]
public interface IMask
{
bool Enabled();
RectTransform rectTransform { get; }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ceb629fc661813d40986b4abbefe72c6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
using System;
namespace UnityEngine.UI
{
/// <summary>
/// This element is capable of being masked out.
/// </summary>
public interface IMaskable
{
/// <summary>
/// Recalculate masking for this element and all children elements.
/// </summary>
/// <remarks>
/// Use this to update the internal state (recreate materials etc).
/// </remarks>
void RecalculateMasking();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 61a20120cddc53849bbc10fc805ffe3e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fe87c0e1cc204ed48ad3b37840f39efc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Some files were not shown because too many files have changed in this diff Show More