zoukankan      html  css  js  c++  java
  • ngui处理不规则按钮点击

    吐个槽  棋牌类游戏做什么中国地图!!!  然后就要用到不规则按钮点击了 你懂的 

    213的unity虽然已经加入了polygoncollider 2d的支持 但是 但是 但是 是2d的 也就是说如果不把摄像机的event修改为 2d_ui 是不支持的  然后213的ngui点击事件都要依赖3d_ui

    这就造成如果想同时支持规则按钮跟不规则按钮 只能使用一个2d摄像机 一个3d摄像机   还有一种办法就是增加事件类型同时处理两种情况  。。。。  就有了下面这段代码   纯抄袭 谢谢原作者 

    UICameraEditor 修改

    //string[] options = new string[] { "3D World", "3D UI", "2D World", "2D UI" };
    string[] options = new string[] { "3D World", "3D UI", "2D World", "2D UI", "UI_2D3D" };

    uicamera 增加枚举类型定义 UI_2D3D,

    //----------------------------------------------
    // NGUI: Next-Gen UI kit
    // Copyright © 2011-2016 Tasharen Entertainment
    //----------------------------------------------

    using UnityEngine;
    using UnityEditor;

    [CanEditMultipleObjects]
    [CustomEditor(typeof(UICamera))]
    public class UICameraEditor : Editor
    {
    enum EventsGo
    {
    Colliders,
    Rigidbodies,
    }

    public override void OnInspectorGUI ()
    {
    UICamera cam = target as UICamera;
    GUILayout.Space(3f);

    serializedObject.Update();

    SerializedProperty et = serializedObject.FindProperty("eventType");

    if (et.hasMultipleDifferentValues)
    {
    EditorGUILayout.PropertyField(et);
    }
    else
    {
    //string[] options = new string[] { "3D World", "3D UI", "2D World", "2D UI" };
    string[] options = new string[] { "3D World", "3D UI", "2D World", "2D UI", "UI_2D3D" };
    int val = EditorGUILayout.Popup("Event Type", et.intValue, options);
    if (val != et.intValue) et.intValue = val;
    }

    SerializedProperty ev = serializedObject.FindProperty("eventsGoToColliders");

    if (ev != null)
    {
    bool val = ev.boolValue;
    bool newVal = EventsGo.Colliders == (EventsGo)EditorGUILayout.EnumPopup("Events go to...",
    ev.boolValue ? EventsGo.Colliders : EventsGo.Rigidbodies);
    if (val != newVal) ev.boolValue = newVal;
    }

    if (UICamera.eventHandler != cam)
    {
    EditorGUILayout.PropertyField(serializedObject.FindProperty("eventReceiverMask"), new GUIContent("Event Mask"));
    serializedObject.ApplyModifiedProperties();

    EditorGUILayout.HelpBox("All other settings are inherited from the First Camera.", MessageType.Info);

    if (GUILayout.Button("Select the First Camera"))
    {
    Selection.activeGameObject = UICamera.eventHandler.gameObject;
    }
    }
    else
    {
    serializedObject.DrawProperty("processEventsIn");

    SerializedProperty mouse = serializedObject.FindProperty("useMouse");
    SerializedProperty touch = serializedObject.FindProperty("useTouch");
    SerializedProperty keyboard = serializedObject.FindProperty("useKeyboard");
    SerializedProperty controller = serializedObject.FindProperty("useController");

    EditorGUILayout.PropertyField(serializedObject.FindProperty("eventReceiverMask"), new GUIContent("Event Mask"));
    EditorGUILayout.PropertyField(serializedObject.FindProperty("debug"));

    GUILayout.BeginHorizontal();
    EditorGUILayout.PropertyField(serializedObject.FindProperty("commandClick"), GUILayout.Width(140f));
    GUILayout.Label("= Right-Click on OSX", GUILayout.MinWidth(30f));
    GUILayout.EndHorizontal();

    EditorGUI.BeginDisabledGroup(!mouse.boolValue && !touch.boolValue);
    {
    EditorGUILayout.PropertyField(serializedObject.FindProperty("allowMultiTouch"));
    }
    EditorGUI.EndDisabledGroup();

    EditorGUI.BeginDisabledGroup(!(mouse.boolValue && (touch.boolValue || controller.boolValue)));
    {
    EditorGUILayout.PropertyField(serializedObject.FindProperty("autoHideCursor"));
    }
    EditorGUI.EndDisabledGroup();

    EditorGUI.BeginDisabledGroup(!mouse.boolValue);
    EditorGUILayout.PropertyField(serializedObject.FindProperty("stickyTooltip"));
    EditorGUI.EndDisabledGroup();

    GUILayout.BeginHorizontal();
    EditorGUILayout.PropertyField(serializedObject.FindProperty("longPressTooltip"));
    GUILayout.EndHorizontal();

    EditorGUI.BeginDisabledGroup(!mouse.boolValue);
    GUILayout.BeginHorizontal();
    EditorGUILayout.PropertyField(serializedObject.FindProperty("tooltipDelay"));
    GUILayout.Label("seconds", GUILayout.MinWidth(60f));
    GUILayout.EndHorizontal();
    EditorGUI.EndDisabledGroup();

    GUILayout.BeginHorizontal();
    SerializedProperty rd = serializedObject.FindProperty("rangeDistance");
    EditorGUILayout.PropertyField(rd, new GUIContent("Raycast Range"));
    GUILayout.Label(rd.floatValue < 0f ? "unlimited" : "units", GUILayout.MinWidth(60f));
    GUILayout.EndHorizontal();

    NGUIEditorTools.SetLabelWidth(80f);

    if (NGUIEditorTools.DrawHeader("Event Sources"))
    {
    NGUIEditorTools.BeginContents();
    {
    GUILayout.BeginHorizontal();
    EditorGUILayout.PropertyField(mouse, new GUIContent("Mouse"), GUILayout.MinWidth(100f));
    EditorGUILayout.PropertyField(touch, new GUIContent("Touch"), GUILayout.MinWidth(100f));
    GUILayout.EndHorizontal();

    GUILayout.BeginHorizontal();
    EditorGUILayout.PropertyField(keyboard, new GUIContent("Keyboard"), GUILayout.MinWidth(100f));
    EditorGUILayout.PropertyField(controller, new GUIContent("Controller"), GUILayout.MinWidth(100f));
    GUILayout.EndHorizontal();
    }
    NGUIEditorTools.EndContents();
    }

    if ((mouse.boolValue || touch.boolValue) && NGUIEditorTools.DrawHeader("Thresholds"))
    {
    NGUIEditorTools.BeginContents();
    {
    EditorGUI.BeginDisabledGroup(!mouse.boolValue);
    GUILayout.BeginHorizontal();
    EditorGUILayout.PropertyField(serializedObject.FindProperty("mouseDragThreshold"), new GUIContent("Mouse Drag"), GUILayout.Width(120f));
    GUILayout.Label("pixels");
    GUILayout.EndHorizontal();

    GUILayout.BeginHorizontal();
    EditorGUILayout.PropertyField(serializedObject.FindProperty("mouseClickThreshold"), new GUIContent("Mouse Click"), GUILayout.Width(120f));
    GUILayout.Label("pixels");
    GUILayout.EndHorizontal();
    EditorGUI.EndDisabledGroup();

    EditorGUI.BeginDisabledGroup(!touch.boolValue);
    GUILayout.BeginHorizontal();
    EditorGUILayout.PropertyField(serializedObject.FindProperty("touchDragThreshold"), new GUIContent("Touch Drag"), GUILayout.Width(120f));
    GUILayout.Label("pixels");
    GUILayout.EndHorizontal();

    GUILayout.BeginHorizontal();
    EditorGUILayout.PropertyField(serializedObject.FindProperty("touchClickThreshold"), new GUIContent("Touch Tap"), GUILayout.Width(120f));
    GUILayout.Label("pixels");
    GUILayout.EndHorizontal();
    EditorGUI.EndDisabledGroup();
    }
    NGUIEditorTools.EndContents();
    }

    if ((mouse.boolValue || keyboard.boolValue || controller.boolValue) && NGUIEditorTools.DrawHeader("Axes and Keys"))
    {
    NGUIEditorTools.BeginContents();
    {
    EditorGUILayout.PropertyField(serializedObject.FindProperty("horizontalAxisName"), new GUIContent("Navigate X"));
    EditorGUILayout.PropertyField(serializedObject.FindProperty("verticalAxisName"), new GUIContent("Navigate Y"));
    EditorGUILayout.PropertyField(serializedObject.FindProperty("horizontalPanAxisName"), new GUIContent("Pan X"));
    EditorGUILayout.PropertyField(serializedObject.FindProperty("verticalPanAxisName"), new GUIContent("Pan Y"));
    EditorGUILayout.PropertyField(serializedObject.FindProperty("scrollAxisName"), new GUIContent("Scroll"));
    EditorGUILayout.PropertyField(serializedObject.FindProperty("submitKey0"), new GUIContent("Submit 1"));
    EditorGUILayout.PropertyField(serializedObject.FindProperty("submitKey1"), new GUIContent("Submit 2"));
    EditorGUILayout.PropertyField(serializedObject.FindProperty("cancelKey0"), new GUIContent("Cancel 1"));
    EditorGUILayout.PropertyField(serializedObject.FindProperty("cancelKey1"), new GUIContent("Cancel 2"));
    }
    NGUIEditorTools.EndContents();
    }
    serializedObject.ApplyModifiedProperties();
    }
    }
    }

    //----------------------------------------------
    // NGUI: Next-Gen UI kit
    // Copyright © 2011-2016 Tasharen Entertainment
    //----------------------------------------------

    using UnityEngine;
    using System.Collections.Generic;

    #if UNITY_EDITOR
    using UnityEditor;
    #endif

    /// <summary>
    /// This script should be attached to each camera that's used to draw the objects with
    /// UI components on them. This may mean only one camera (main camera or your UI camera),
    /// or multiple cameras if you happen to have multiple viewports. Failing to attach this
    /// script simply means that objects drawn by this camera won't receive UI notifications:
    ///
    /// * OnHover (isOver) is sent when the mouse hovers over a collider or moves away.
    /// * OnPress (isDown) is sent when a mouse button gets pressed on the collider.
    /// * OnSelect (selected) is sent when a mouse button is first pressed on an object. Repeated presses won't result in an OnSelect(true).
    /// * OnClick () is sent when a mouse is pressed and released on the same object.
    /// UICamera.currentTouchID tells you which button was clicked.
    /// * OnDoubleClick () is sent when the click happens twice within a fourth of a second.
    /// UICamera.currentTouchID tells you which button was clicked.
    ///
    /// * OnDragStart () is sent to a game object under the touch just before the OnDrag() notifications begin.
    /// * OnDrag (delta) is sent to an object that's being dragged.
    /// * OnDragOver (draggedObject) is sent to a game object when another object is dragged over its area.
    /// * OnDragOut (draggedObject) is sent to a game object when another object is dragged out of its area.
    /// * OnDragEnd () is sent to a dragged object when the drag event finishes.
    ///
    /// * OnTooltip (show) is sent when the mouse hovers over a collider for some time without moving.
    /// * OnScroll (float delta) is sent out when the mouse scroll wheel is moved.
    /// * OnNavigate (KeyCode key) is sent when horizontal or vertical navigation axes are moved.
    /// * OnPan (Vector2 delta) is sent when when horizontal or vertical panning axes are moved.
    /// * OnKey (KeyCode key) is sent when keyboard or controller input is used.
    /// </summary>

    [ExecuteInEditMode]
    [AddComponentMenu("NGUI/UI/NGUI Event System (UICamera)")]
    [RequireComponent(typeof(Camera))]
    public class UICamera : MonoBehaviour
    {
    public enum ControlScheme
    {
    Mouse,
    Touch,
    Controller,
    }

    /// <summary>
    /// Whether the touch event will be sending out the OnClick notification at the end.
    /// </summary>

    public enum ClickNotification
    {
    None,
    Always,
    BasedOnDelta,
    }

    /// <summary>
    /// Ambiguous mouse, touch, or controller event.
    /// </summary>

    public class MouseOrTouch
    {
    public KeyCode key = KeyCode.None;
    public Vector2 pos; // Current position of the mouse or touch event
    public Vector2 lastPos; // Previous position of the mouse or touch event
    public Vector2 delta; // Delta since last update
    public Vector2 totalDelta; // Delta since the event started being tracked

    public Camera pressedCam; // Camera that the OnPress(true) was fired with

    public GameObject last; // Last object under the touch or mouse
    public GameObject current; // Current game object under the touch or mouse
    public GameObject pressed; // Last game object to receive OnPress
    public GameObject dragged; // Game object that's being dragged

    public float pressTime = 0f; // When the touch event started
    public float clickTime = 0f; // The last time a click event was sent out

    public ClickNotification clickNotification = ClickNotification.Always;
    public bool touchBegan = true;
    public bool pressStarted = false;
    public bool dragStarted = false;
    public int ignoreDelta = 0;

    /// <summary>
    /// Delta time since the touch operation started.
    /// </summary>

    public float deltaTime { get { return RealTime.time - pressTime; } }

    /// <summary>
    /// Returns whether this touch is currently over a UI element.
    /// </summary>

    public bool isOverUI
    {
    get
    {
    return current != null && current != fallThrough && NGUITools.FindInParents<UIRoot>(current) != null;
    }
    }
    }

    /// <summary>
    /// Camera type controls how raycasts are handled by the UICamera.
    /// </summary>

    public enum EventType : int
    {
    World_3D, // Perform a Physics.Raycast and sort by distance to the point that was hit.
    UI_3D, // Perform a Physics.Raycast and sort by widget depth.
    World_2D, // Perform a Physics2D.OverlapPoint
    UI_2D, // Physics2D.OverlapPoint then sort by widget depth
    UI_2D3D,
    }

    /// <summary>
    /// List of all active cameras in the scene.
    /// </summary>

    static public BetterList<UICamera> list = new BetterList<UICamera>();

    public delegate bool GetKeyStateFunc (KeyCode key);
    public delegate float GetAxisFunc (string name);
    public delegate bool GetAnyKeyFunc ();
    public delegate MouseOrTouch GetMouseDelegate (int button);
    public delegate MouseOrTouch GetTouchDelegate (int id, bool createIfMissing);
    public delegate void RemoveTouchDelegate (int id);

    /// <summary>
    /// GetKeyDown function -- return whether the specified key was pressed this Update().
    /// </summary>

    static public GetKeyStateFunc GetKeyDown = delegate(KeyCode key)
    {
    if (key >= KeyCode.JoystickButton0 && ignoreControllerInput) return false;
    return Input.GetKeyDown(key);
    };

    /// <summary>
    /// GetKeyDown function -- return whether the specified key was released this Update().
    /// </summary>

    static public GetKeyStateFunc GetKeyUp = delegate(KeyCode key)
    {
    if (key >= KeyCode.JoystickButton0 && ignoreControllerInput) return false;
    return Input.GetKeyUp(key);
    };

    /// <summary>
    /// GetKey function -- return whether the specified key is currently held.
    /// </summary>

    static public GetKeyStateFunc GetKey = delegate(KeyCode key)
    {
    if (key >= KeyCode.JoystickButton0 && ignoreControllerInput) return false;
    return Input.GetKey(key);
    };

    /// <summary>
    /// GetAxis function -- return the state of the specified axis.
    /// </summary>

    static public GetAxisFunc GetAxis = delegate(string axis)
    {
    if (ignoreControllerInput) return 0f;
    return Input.GetAxis(axis);
    };

    /// <summary>
    /// User-settable Input.anyKeyDown
    /// </summary>

    static public GetAnyKeyFunc GetAnyKeyDown;

    /// <summary>
    /// Get the details of the specified mouse button.
    /// </summary>

    static public GetMouseDelegate GetMouse = delegate(int button) { return mMouse[button]; };

    /// <summary>
    /// Get or create a touch event. If you are trying to iterate through a list of active touches, use activeTouches instead.
    /// </summary>

    static public GetTouchDelegate GetTouch = delegate(int id, bool createIfMissing)
    {
    if (id < 0) return GetMouse(-id - 1);

    for (int i = 0, imax = mTouchIDs.Count; i < imax; ++i)
    if (mTouchIDs[i] == id) return activeTouches[i];

    if (createIfMissing)
    {
    MouseOrTouch touch = new MouseOrTouch();
    touch.pressTime = RealTime.time;
    touch.touchBegan = true;
    activeTouches.Add(touch);
    mTouchIDs.Add(id);
    return touch;
    }
    return null;
    };

    /// <summary>
    /// Remove a touch event from the list.
    /// </summary>

    static public RemoveTouchDelegate RemoveTouch = delegate(int id)
    {
    for (int i = 0, imax = mTouchIDs.Count; i < imax; ++i)
    {
    if (mTouchIDs[i] == id)
    {
    mTouchIDs.RemoveAt(i);
    activeTouches.RemoveAt(i);
    return;
    }
    }
    };

    /// <summary>
    /// Delegate triggered when the screen size changes for any reason.
    /// Subscribe to it if you don't want to compare Screen.width and Screen.height each frame.
    /// </summary>

    static public OnScreenResize onScreenResize;
    public delegate void OnScreenResize ();

    /// <summary>
    /// Event type -- use "UI" for your user interfaces, and "World" for your game camera.
    /// This setting changes how raycasts are handled. Raycasts have to be more complicated for UI cameras.
    /// </summary>

    public EventType eventType = EventType.UI_3D;

    /// <summary>
    /// By default, events will go to rigidbodies when the Event Type is not UI.
    /// You can change this behaviour back to how it was pre-3.7.0 using this flag.
    /// </summary>

    public bool eventsGoToColliders = false;

    /// <summary>
    /// Which layers will receive events.
    /// </summary>

    public LayerMask eventReceiverMask = -1;

    public enum ProcessEventsIn
    {
    Update,
    LateUpdate,
    }

    /// <summary>
    /// When events will be processed.
    /// </summary>

    public ProcessEventsIn processEventsIn = ProcessEventsIn.Update;

    /// <summary>
    /// If 'true', currently hovered object will be shown in the top left corner.
    /// </summary>

    public bool debug = false;

    /// <summary>
    /// Whether the mouse input is used.
    /// </summary>

    public bool useMouse = true;

    /// <summary>
    /// Whether the touch-based input is used.
    /// </summary>

    public bool useTouch = true;

    /// <summary>
    /// Whether multi-touch is allowed.
    /// </summary>

    public bool allowMultiTouch = true;

    /// <summary>
    /// Whether the keyboard events will be processed.
    /// </summary>

    public bool useKeyboard = true;

    /// <summary>
    /// Whether the joystick and controller events will be processed.
    /// </summary>

    public bool useController = true;

    [System.Obsolete("Use new OnDragStart / OnDragOver / OnDragOut / OnDragEnd events instead")]
    public bool stickyPress { get { return true; } }

    /// <summary>
    /// Whether the tooltip will disappear as soon as the mouse moves (false) or only if the mouse moves outside of the widget's area (true).
    /// </summary>

    public bool stickyTooltip = true;

    /// <summary>
    /// How long of a delay to expect before showing the tooltip.
    /// </summary>

    public float tooltipDelay = 1f;

    /// <summary>
    /// If enabled, a tooltip will be shown after touch gets pressed on something and held for more than "tooltipDelay" seconds.
    /// </summary>

    public bool longPressTooltip = false;

    /// <summary>
    /// How much the mouse has to be moved after pressing a button before it starts to send out drag events.
    /// </summary>

    public float mouseDragThreshold = 4f;

    /// <summary>
    /// How far the mouse is allowed to move in pixels before it's no longer considered for click events, if the click notification is based on delta.
    /// </summary>

    public float mouseClickThreshold = 10f;

    /// <summary>
    /// How much the mouse has to be moved after pressing a button before it starts to send out drag events.
    /// </summary>

    public float touchDragThreshold = 40f;

    /// <summary>
    /// How far the touch is allowed to move in pixels before it's no longer considered for click events, if the click notification is based on delta.
    /// </summary>

    public float touchClickThreshold = 40f;

    /// <summary>
    /// Raycast range distance. By default it's as far as the camera can see.
    /// </summary>

    public float rangeDistance = -1f;

    /// <summary>
    /// Name of the axis used to send left and right key events.
    /// </summary>

    public string horizontalAxisName = "Horizontal";

    /// <summary>
    /// Name of the axis used to send up and down key events.
    /// </summary>

    public string verticalAxisName = "Vertical";

    /// <summary>
    /// Name of the horizontal axis used to move scroll views and sliders around.
    /// </summary>

    public string horizontalPanAxisName = null;

    /// <summary>
    /// Name of the vertical axis used to move scroll views and sliders around.
    /// </summary>

    public string verticalPanAxisName = null;

    /// <summary>
    /// Name of the axis used for scrolling.
    /// </summary>

    public string scrollAxisName = "Mouse ScrollWheel";

    /// <summary>
    /// Simulate a right-click on OSX when the Command key is held and a left-click is used (for trackpad).
    /// </summary>

    public bool commandClick = true;

    /// <summary>
    /// Various keys used by the camera.
    /// </summary>

    public KeyCode submitKey0 = KeyCode.Return;
    public KeyCode submitKey1 = KeyCode.JoystickButton0;
    public KeyCode cancelKey0 = KeyCode.Escape;
    public KeyCode cancelKey1 = KeyCode.JoystickButton1;

    /// <summary>
    /// Whether NGUI will automatically hide the mouse cursor when controller or touch input is detected.
    /// </summary>

    public bool autoHideCursor = true;

    public delegate void OnCustomInput ();

    /// <summary>
    /// Custom input processing logic, if desired. For example: WP7 touches.
    /// Use UICamera.current to get the current camera.
    /// </summary>

    static public OnCustomInput onCustomInput;

    /// <summary>
    /// Whether tooltips will be shown or not.
    /// </summary>

    static public bool showTooltips = true;

    /// <summary>
    /// Whether controller input will be temporarily disabled or not.
    /// It's useful to be able to turn off controller interaction and only turn it on when the UI is actually visible.
    /// </summary>

    static public bool disableController
    {
    get
    {
    return mDisableController && !UIPopupList.isOpen;
    }
    set
    {
    mDisableController = value;
    }
    }

    /// <summary>
    /// If set to 'true', controller input will be flat-out ignored. Permanently, for all cameras.
    /// </summary>

    static public bool ignoreControllerInput = false;

    static bool mDisableController = false;
    static Vector2 mLastPos = Vector2.zero;

    /// <summary>
    /// Position of the last touch (or mouse) event.
    /// </summary>

    [System.Obsolete("Use lastEventPosition instead. It handles controller input properly.")]
    static public Vector2 lastTouchPosition { get { return mLastPos; } set { mLastPos = value; } }

    /// <summary>
    /// Position of the last touch (or mouse) event.
    /// </summary>

    static public Vector2 lastEventPosition
    {
    get
    {
    UICamera.ControlScheme scheme = UICamera.currentScheme;

    if (scheme == UICamera.ControlScheme.Controller)
    {
    GameObject go = hoveredObject;

    if (go != null)
    {
    Bounds b = NGUIMath.CalculateAbsoluteWidgetBounds(go.transform);
    Camera cam = NGUITools.FindCameraForLayer(go.layer);
    return cam.WorldToScreenPoint(b.center);
    }
    }
    return mLastPos;
    }
    set { mLastPos = value; }
    }

    /// <summary>
    /// Position of the last touch (or mouse) event in the world.
    /// </summary>

    static public Vector3 lastWorldPosition = Vector3.zero;

    /// <summary>
    /// Last raycast hit prior to sending out the event. This is useful if you want detailed information
    /// about what was actually hit in your OnClick, OnHover, and other event functions.
    /// Note that this is not going to be valid if you're using 2D colliders.
    /// </summary>

    static public RaycastHit lastHit;

    /// <summary>
    /// UICamera that sent out the event.
    /// </summary>

    static public UICamera current = null;

    /// <summary>
    /// NGUI event system that will be handling all events.
    /// </summary>

    static public UICamera first
    {
    get
    {
    if (list == null || list.size == 0) return null;
    return list[0];
    }
    }

    /// <summary>
    /// Last camera active prior to sending out the event. This will always be the camera that actually sent out the event.
    /// </summary>

    static public Camera currentCamera = null;

    public delegate void OnSchemeChange ();

    /// <summary>
    /// Delegate called when the control scheme changes.
    /// </summary>

    static public OnSchemeChange onSchemeChange;
    static ControlScheme mLastScheme = ControlScheme.Mouse;

    /// <summary>
    /// Current control scheme. Derived from the last event to arrive.
    /// </summary>

    static public ControlScheme currentScheme
    {
    get
    {
    if (mCurrentKey == KeyCode.None) return ControlScheme.Touch;
    if (mCurrentKey >= KeyCode.JoystickButton0) return ControlScheme.Controller;
    if (current != null && mLastScheme == ControlScheme.Controller &&
    (mCurrentKey == current.submitKey0 || mCurrentKey == current.submitKey1))
    return ControlScheme.Controller;
    return ControlScheme.Mouse;
    }
    set
    {
    if (value == ControlScheme.Mouse)
    {
    currentKey = KeyCode.Mouse0;
    }
    else if (value == ControlScheme.Controller)
    {
    currentKey = KeyCode.JoystickButton0;
    }
    else if (value == ControlScheme.Touch)
    {
    currentKey = KeyCode.None;
    }
    else currentKey = KeyCode.Alpha0;

    mLastScheme = value;
    }
    }

    /// <summary>
    /// ID of the touch or mouse operation prior to sending out the event.
    /// Mouse ID is '-1' for left, '-2' for right mouse button, '-3' for middle.
    /// </summary>

    static public int currentTouchID = -100;

    static KeyCode mCurrentKey = KeyCode.Alpha0;

    /// <summary>
    /// Key that triggered the event, if any.
    /// </summary>

    static public KeyCode currentKey
    {
    get
    {
    return mCurrentKey;
    }
    set
    {
    if (mCurrentKey != value)
    {
    ControlScheme before = mLastScheme;
    mCurrentKey = value;
    mLastScheme = currentScheme;

    if (before != mLastScheme)
    {
    HideTooltip();

    if (mLastScheme == ControlScheme.Mouse)
    {
    #if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7
    Screen.lockCursor = false;
    Screen.showCursor = true;
    #else
    Cursor.lockState = CursorLockMode.None;
    Cursor.visible = true;
    #endif
    }
    #if UNITY_EDITOR
    else if (mLastScheme == ControlScheme.Controller)
    #else
    else
    #endif
    {
    if (current != null && current.autoHideCursor)
    {
    #if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7
    Screen.showCursor = false;
    Screen.lockCursor = true;
    #else
    Cursor.visible = false;
    Cursor.lockState = CursorLockMode.Locked;
    #endif

    // Skip the next 2 frames worth of mouse movement
    mMouse[0].ignoreDelta = 2;
    }
    }

    if (onSchemeChange != null) onSchemeChange();
    }
    }
    }
    }

    /// <summary>
    /// Ray projected into the screen underneath the current touch.
    /// </summary>

    static public Ray currentRay
    {
    get
    {
    return (currentCamera != null && currentTouch != null) ?
    currentCamera.ScreenPointToRay(currentTouch.pos) : new Ray();
    }
    }

    /// <summary>
    /// Current touch, set before any event function gets called.
    /// </summary>

    static public MouseOrTouch currentTouch = null;

    static bool mInputFocus = false;

    /// <summary>
    /// Whether an input field currently has focus.
    /// </summary>

    static public bool inputHasFocus
    {
    get
    {
    if (mInputFocus && mSelected && mSelected.activeInHierarchy) return true;
    return false;
    }
    }

    // Obsolete, kept for backwards compatibility.
    static GameObject mGenericHandler;

    /// <summary>
    /// If set, this game object will receive all events regardless of whether they were handled or not.
    /// </summary>

    [System.Obsolete("Use delegates instead such as UICamera.onClick, UICamera.onHover, etc.")]
    static public GameObject genericEventHandler { get { return mGenericHandler; } set { mGenericHandler = value; } }

    /// <summary>
    /// If events don't get handled, they will be forwarded to this game object.
    /// </summary>

    static public GameObject fallThrough;

    public delegate void MoveDelegate (Vector2 delta);
    public delegate void VoidDelegate (GameObject go);
    public delegate void BoolDelegate (GameObject go, bool state);
    public delegate void FloatDelegate (GameObject go, float delta);
    public delegate void VectorDelegate (GameObject go, Vector2 delta);
    public delegate void ObjectDelegate (GameObject go, GameObject obj);
    public delegate void KeyCodeDelegate (GameObject go, KeyCode key);

    /// <summary>
    /// These notifications are sent out prior to the actual event going out.
    /// </summary>

    static public VoidDelegate onClick;
    static public VoidDelegate onDoubleClick;
    static public BoolDelegate onHover;
    static public BoolDelegate onPress;
    static public BoolDelegate onSelect;
    static public FloatDelegate onScroll;
    static public VectorDelegate onDrag;
    static public VoidDelegate onDragStart;
    static public ObjectDelegate onDragOver;
    static public ObjectDelegate onDragOut;
    static public VoidDelegate onDragEnd;
    static public ObjectDelegate onDrop;
    static public KeyCodeDelegate onKey;
    static public KeyCodeDelegate onNavigate;
    static public VectorDelegate onPan;
    static public BoolDelegate onTooltip;
    static public MoveDelegate onMouseMove;

    // Mouse events
    static MouseOrTouch[] mMouse = new MouseOrTouch[] { new MouseOrTouch(), new MouseOrTouch(), new MouseOrTouch() };

    // Joystick/controller/keyboard event
    static public MouseOrTouch controller = new MouseOrTouch();

    /// <summary>
    /// List of all the active touches.
    /// </summary>

    static public List<MouseOrTouch> activeTouches = new List<MouseOrTouch>();

    // Used internally to store IDs of active touches
    static List<int> mTouchIDs = new List<int>();

    // Used to detect screen dimension changes
    static int mWidth = 0;
    static int mHeight = 0;

    // Tooltip widget (mouse only)
    static GameObject mTooltip = null;

    // Mouse input is turned off on iOS
    Camera mCam = null;
    static float mTooltipTime = 0f;
    float mNextRaycast = 0f;

    /// <summary>
    /// Helper function that determines if this script should be handling the events.
    /// </summary>

    bool handlesEvents { get { return eventHandler == this; } }

    /// <summary>
    /// Caching is always preferable for performance.
    /// </summary>

    #if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7
    public Camera cachedCamera { get { if (mCam == null) mCam = camera; return mCam; } }
    #else
    public Camera cachedCamera { get { if (mCam == null) mCam = GetComponent<Camera>(); return mCam; } }
    #endif

    /// <summary>
    /// Set to 'true' just before OnDrag-related events are sent. No longer needed, but kept for backwards compatibility.
    /// </summary>

    static public bool isDragging = false;

    /// <summary>
    /// Object that should be showing the tooltip.
    /// </summary>

    static public GameObject tooltipObject { get { return mTooltip; } }

    /// <summary>
    /// Whether the last raycast was over the UI.
    /// </summary>

    static public bool isOverUI
    {
    get
    {
    if (currentTouch != null) return currentTouch.isOverUI;

    for (int i = 0, imax = activeTouches.Count; i < imax; ++i)
    {
    MouseOrTouch touch = activeTouches[i];
    if (touch.pressed != null && touch.pressed != fallThrough && NGUITools.FindInParents<UIRoot>(touch.pressed) != null)
    return true;
    }

    if (mMouse[0].current != null && mMouse[0].current != fallThrough && NGUITools.FindInParents<UIRoot>(mMouse[0].current) != null)
    return true;

    if (controller.pressed != null && controller.pressed != fallThrough && NGUITools.FindInParents<UIRoot>(controller.pressed) != null)
    return true;

    return false;
    }
    }

    static GameObject mRayHitObject;
    static GameObject mHover;
    static GameObject mSelected;

    /// <summary>
    /// The object over which the mouse is hovering over, or the object currently selected by the controller input.
    /// Mouse and controller input share the same hovered object, while touches have no hovered object at all.
    /// Checking this value from within a touch-based event will simply return the current touched object.
    /// </summary>

    static public GameObject hoveredObject
    {
    get
    {
    if (currentTouch != null && currentTouch.dragStarted) return currentTouch.current;
    if (mHover && mHover.activeInHierarchy) return mHover;
    mHover = null;
    return null;
    }
    set
    {
    // We already have this object highlighted
    if (mHover == value) return;

    bool statesDiffer = false;
    UICamera prevCamera = current;

    if (currentTouch == null)
    {
    statesDiffer = true;
    currentTouchID = -100;
    currentTouch = controller;
    }

    // Hide the tooltip
    ShowTooltip(null);

    // Remove the selection
    if (mSelected && currentScheme == ControlScheme.Controller)
    {
    Notify(mSelected, "OnSelect", false);
    if (onSelect != null) onSelect(mSelected, false);
    mSelected = null;
    }

    // Remove the previous hover state
    if (mHover)
    {
    Notify(mHover, "OnHover", false);
    if (onHover != null) onHover(mHover, false);
    }

    mHover = value;
    currentTouch.clickNotification = ClickNotification.None;

    if (mHover)
    {
    if (mHover != controller.current && mHover.GetComponent<UIKeyNavigation>() != null)
    controller.current = mHover;

    // Locate the appropriate camera for the new object
    if (statesDiffer)
    {
    UICamera cam = (mHover != null) ? FindCameraForLayer(mHover.layer) : UICamera.list[0];

    if (cam != null)
    {
    current = cam;
    currentCamera = cam.cachedCamera;
    }
    }

    if (onHover != null) onHover(mHover, true);
    Notify(mHover, "OnHover", true);
    }

    // Restore previous states
    if (statesDiffer)
    {
    current = prevCamera;
    currentCamera = (prevCamera != null) ? prevCamera.cachedCamera : null;
    currentTouch = null;
    currentTouchID = -100;
    }
    }
    }

    /// <summary>
    /// Currently chosen object for controller-based navigation.
    /// </summary>

    static public GameObject controllerNavigationObject
    {
    get
    {
    if (controller.current && controller.current.activeInHierarchy)
    return controller.current;

    // Automatically update the object chosen by the controller
    if (currentScheme == ControlScheme.Controller &&
    UICamera.current != null && (UICamera.current.useController && !ignoreControllerInput) &&
    UIKeyNavigation.list.size > 0)
    {
    for (int i = 0; i < UIKeyNavigation.list.size; ++i)
    {
    UIKeyNavigation nav = UIKeyNavigation.list[i];

    if (nav && nav.constraint != UIKeyNavigation.Constraint.Explicit && nav.startsSelected)
    {
    hoveredObject = nav.gameObject;
    controller.current = mHover;
    return mHover;
    }
    }

    if (mHover == null)
    {
    for (int i = 0; i < UIKeyNavigation.list.size; ++i)
    {
    UIKeyNavigation nav = UIKeyNavigation.list[i];

    if (nav && nav.constraint != UIKeyNavigation.Constraint.Explicit)
    {
    hoveredObject = nav.gameObject;
    controller.current = mHover;
    return mHover;
    }
    }
    }
    }

    controller.current = selectedObject;
    return controller.current;
    }
    set
    {
    if (controller.current != value && controller.current)
    {
    Notify(controller.current, "OnHover", false);
    if (onHover != null) onHover(controller.current, false);
    controller.current = null;
    }

    hoveredObject = value;
    }
    }

    /// <summary>
    /// Selected object receives exclusive focus. An input field requires exclusive focus in order to type,
    /// for example. Any object is capable of grabbing the selection just by clicking on that object,
    /// but only one object can be selected at a time.
    /// </summary>

    static public GameObject selectedObject
    {
    get
    {
    if (mSelected && mSelected.activeInHierarchy) return mSelected;
    mSelected = null;
    return null;
    }
    set
    {
    if (mSelected == value)
    {
    hoveredObject = value;
    controller.current = value;
    return;
    }

    // Hide the tooltip
    ShowTooltip(null);

    bool statesDiffer = false;
    UICamera prevCamera = current;
    //ControlScheme scheme = currentScheme;

    if (currentTouch == null)
    {
    statesDiffer = true;
    currentTouchID = -100;
    currentTouch = controller;
    }

    // Input no longer has selection, even if it did
    mInputFocus = false;

    // Remove the selection
    if (mSelected)
    {
    Notify(mSelected, "OnSelect", false);
    if (onSelect != null) onSelect(mSelected, false);
    }

    // Remove the hovered state
    //if (mHover && scheme < ControlScheme.Controller)
    //{
    // Notify(mHover, "OnHover", false);
    // if (onHover != null) onHover(mHover, false);
    // mHover = null;
    //}

    // Change the selection and hover
    mSelected = value;
    //if (scheme >= ControlScheme.Controller) mHover = value;
    currentTouch.clickNotification = ClickNotification.None;

    if (value != null)
    {
    UIKeyNavigation nav = value.GetComponent<UIKeyNavigation>();
    if (nav != null) controller.current = value;
    }

    // Set the camera for events
    if (mSelected && statesDiffer)
    {
    UICamera cam = (mSelected != null) ? FindCameraForLayer(mSelected.layer) : UICamera.list[0];

    if (cam != null)
    {
    current = cam;
    currentCamera = cam.cachedCamera;
    }
    }

    // Set the hovered state first
    //if (mHover && currentScheme >= ControlScheme.Controller)
    //{
    // if (onHover != null) onHover(mHover, true);
    // Notify(mHover, "OnHover", true);
    //}

    // Set the selection
    if (mSelected)
    {
    mInputFocus = (mSelected.activeInHierarchy && mSelected.GetComponent<UIInput>() != null);
    if (onSelect != null) onSelect(mSelected, true);
    Notify(mSelected, "OnSelect", true);
    }

    // Restore the states
    if (statesDiffer)
    {
    current = prevCamera;
    currentCamera = (prevCamera != null) ? prevCamera.cachedCamera : null;
    currentTouch = null;
    currentTouchID = -100;
    }
    }
    }

    /// <summary>
    /// Returns 'true' if any of the active touch, mouse or controller is currently holding the specified object.
    /// </summary>

    static public bool IsPressed (GameObject go)
    {
    for (int i = 0; i < 3; ++i) if (mMouse[i].pressed == go) return true;
    for (int i = 0, imax = activeTouches.Count; i < imax; ++i)
    {
    MouseOrTouch touch = activeTouches[i];
    if (touch.pressed == go) return true;
    }
    if (controller.pressed == go) return true;
    return false;
    }

    [System.Obsolete("Use either 'CountInputSources()' or 'activeTouches.Count'")]
    static public int touchCount { get { return CountInputSources(); } }

    /// <summary>
    /// Number of active touches from all sources.
    /// Note that this will include the sum of touch, mouse and controller events.
    /// If you want only touch events, use activeTouches.Count.
    /// </summary>

    static public int CountInputSources ()
    {
    int count = 0;

    for (int i = 0, imax = activeTouches.Count; i < imax; ++i)
    {
    MouseOrTouch touch = activeTouches[i];
    if (touch.pressed != null)
    ++count;
    }

    for (int i = 0; i < mMouse.Length; ++i)
    if (mMouse[i].pressed != null)
    ++count;

    if (controller.pressed != null)
    ++count;

    return count;
    }

    /// <summary>
    /// Number of active drag events from all sources.
    /// </summary>

    static public int dragCount
    {
    get
    {
    int count = 0;

    for (int i = 0, imax = activeTouches.Count; i < imax; ++i)
    {
    MouseOrTouch touch = activeTouches[i];
    if (touch.dragged != null)
    ++count;
    }

    for (int i = 0; i < mMouse.Length; ++i)
    if (mMouse[i].dragged != null)
    ++count;

    if (controller.dragged != null)
    ++count;

    return count;
    }
    }

    /// <summary>
    /// Convenience function that returns the main HUD camera.
    /// </summary>

    static public Camera mainCamera
    {
    get
    {
    UICamera mouse = eventHandler;
    return (mouse != null) ? mouse.cachedCamera : null;
    }
    }

    /// <summary>
    /// Event handler for all types of events.
    /// </summary>

    static public UICamera eventHandler
    {
    get
    {
    for (int i = 0; i < list.size; ++i)
    {
    // Invalid or inactive entry -- keep going
    UICamera cam = list.buffer[i];
    if (cam == null || !cam.enabled || !NGUITools.GetActive(cam.gameObject)) continue;
    return cam;
    }
    return null;
    }
    }

    /// <summary>
    /// Static comparison function used for sorting.
    /// </summary>

    static int CompareFunc (UICamera a, UICamera b)
    {
    if (a.cachedCamera.depth < b.cachedCamera.depth) return 1;
    if (a.cachedCamera.depth > b.cachedCamera.depth) return -1;
    return 0;
    }

    struct DepthEntry
    {
    public int depth;
    public RaycastHit hit;
    public Vector3 point;
    public GameObject go;
    }

    static DepthEntry mHit = new DepthEntry();
    static BetterList<DepthEntry> mHits = new BetterList<DepthEntry>();

    /// <summary>
    /// Find the rigidbody on the parent, but return 'null' if a UIPanel is found instead.
    /// The idea is: send events to the rigidbody in the world, but to colliders in the UI.
    /// </summary>

    static Rigidbody FindRootRigidbody (Transform trans)
    {
    while (trans != null)
    {
    if (trans.GetComponent<UIPanel>() != null) return null;
    #if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7
    Rigidbody rb = trans.rigidbody;
    #else
    Rigidbody rb = trans.GetComponent<Rigidbody>();
    #endif
    if (rb != null) return rb;
    trans = trans.parent;
    }
    return null;
    }

    /// <summary>
    /// Find the 2D rigidbody on the parent, but return 'null' if a UIPanel is found instead.
    /// </summary>

    static Rigidbody2D FindRootRigidbody2D (Transform trans)
    {
    while (trans != null)
    {
    if (trans.GetComponent<UIPanel>() != null) return null;
    #if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7
    Rigidbody2D rb = trans.rigidbody2D;
    #else
    Rigidbody2D rb = trans.GetComponent<Rigidbody2D>();
    #endif
    if (rb != null) return rb;
    trans = trans.parent;
    }
    return null;
    }

    /// <summary>
    /// Raycast into the screen underneath the touch and update its 'current' value.
    /// </summary>

    static public void Raycast (MouseOrTouch touch)
    {
    if (!Raycast(touch.pos)) mRayHitObject = fallThrough;
    if (mRayHitObject == null) mRayHitObject = mGenericHandler;
    touch.last = touch.current;
    touch.current = mRayHitObject;
    mLastPos = touch.pos;
    }

    /// <summary>
    /// Returns the object under the specified position.
    /// </summary>

    static public bool Raycast (Vector3 inPos)
    {
    for (int i = 0; i < list.size; ++i)
    {
    UICamera cam = list.buffer[i];

    // Skip inactive scripts
    if (!cam.enabled || !NGUITools.GetActive(cam.gameObject)) continue;

    // Convert to view space
    currentCamera = cam.cachedCamera;
    Vector3 pos = currentCamera.ScreenToViewportPoint(inPos);
    if (float.IsNaN(pos.x) || float.IsNaN(pos.y)) continue;

    // If it's outside the camera's viewport, do nothing
    if (pos.x < 0f || pos.x > 1f || pos.y < 0f || pos.y > 1f) continue;

    // Cast a ray into the screen
    Ray ray = currentCamera.ScreenPointToRay(inPos);

    // Raycast into the screen
    int mask = currentCamera.cullingMask & (int)cam.eventReceiverMask;
    float dist = (cam.rangeDistance > 0f) ? cam.rangeDistance : currentCamera.farClipPlane - currentCamera.nearClipPlane;

    if (cam.eventType == EventType.World_3D)
    {
    if (Physics.Raycast(ray, out lastHit, dist, mask))
    {
    lastWorldPosition = lastHit.point;
    mRayHitObject = lastHit.collider.gameObject;

    if (!cam.eventsGoToColliders)
    {
    Rigidbody rb = FindRootRigidbody(mRayHitObject.transform);
    if (rb != null) mRayHitObject = rb.gameObject;
    }
    return true;
    }
    continue;
    }
    else if (cam.eventType == EventType.UI_3D)
    {
    RaycastHit[] hits = Physics.RaycastAll(ray, dist, mask);

    if (hits.Length > 1)
    {
    for (int b = 0; b < hits.Length; ++b)
    {
    GameObject go = hits[b].collider.gameObject;
    UIWidget w = go.GetComponent<UIWidget>();

    if (w != null)
    {
    if (!w.isVisible) continue;
    if (w.hitCheck != null && !w.hitCheck(hits[b].point)) continue;
    }
    else
    {
    UIRect rect = NGUITools.FindInParents<UIRect>(go);
    if (rect != null && rect.finalAlpha < 0.001f) continue;
    }

    mHit.depth = NGUITools.CalculateRaycastDepth(go);

    if (mHit.depth != int.MaxValue)
    {
    mHit.hit = hits[b];
    mHit.point = hits[b].point;
    mHit.go = hits[b].collider.gameObject;
    mHits.Add(mHit);
    }
    }

    mHits.Sort(delegate(DepthEntry r1, DepthEntry r2) { return r2.depth.CompareTo(r1.depth); });

    for (int b = 0; b < mHits.size; ++b)
    {
    #if UNITY_FLASH
    if (IsVisible(mHits.buffer[b]))
    #else
    if (IsVisible(ref mHits.buffer[b]))
    #endif
    {
    lastHit = mHits[b].hit;
    mRayHitObject = mHits[b].go;
    lastWorldPosition = mHits[b].point;
    mHits.Clear();
    return true;
    }
    }
    mHits.Clear();
    }
    else if (hits.Length == 1)
    {
    GameObject go = hits[0].collider.gameObject;
    UIWidget w = go.GetComponent<UIWidget>();

    if (w != null)
    {
    if (!w.isVisible) continue;
    if (w.hitCheck != null && !w.hitCheck(hits[0].point)) continue;
    }
    else
    {
    UIRect rect = NGUITools.FindInParents<UIRect>(go);
    if (rect != null && rect.finalAlpha < 0.001f) continue;
    }

    if (IsVisible(hits[0].point, hits[0].collider.gameObject))
    {
    lastHit = hits[0];
    lastWorldPosition = hits[0].point;
    mRayHitObject = lastHit.collider.gameObject;
    return true;
    }
    }
    continue;
    }
    else if (cam.eventType == EventType.World_2D)
    {
    if (m2DPlane.Raycast(ray, out dist))
    {
    Vector3 point = ray.GetPoint(dist);
    Collider2D c2d = Physics2D.OverlapPoint(point, mask);

    if (c2d)
    {
    lastWorldPosition = point;
    mRayHitObject = c2d.gameObject;

    if (!cam.eventsGoToColliders)
    {
    Rigidbody2D rb = FindRootRigidbody2D(mRayHitObject.transform);
    if (rb != null) mRayHitObject = rb.gameObject;
    }
    return true;
    }
    }
    continue;
    }
    else if (cam.eventType == EventType.UI_2D)
    {
    if (m2DPlane.Raycast(ray, out dist))
    {
    lastWorldPosition = ray.GetPoint(dist);
    Collider2D[] hits = Physics2D.OverlapPointAll(lastWorldPosition, mask);

    if (hits.Length > 1)
    {
    for (int b = 0; b < hits.Length; ++b)
    {
    GameObject go = hits[b].gameObject;
    UIWidget w = go.GetComponent<UIWidget>();

    if (w != null)
    {
    if (!w.isVisible) continue;
    if (w.hitCheck != null && !w.hitCheck(lastWorldPosition)) continue;
    }
    else
    {
    UIRect rect = NGUITools.FindInParents<UIRect>(go);
    if (rect != null && rect.finalAlpha < 0.001f) continue;
    }

    mHit.depth = NGUITools.CalculateRaycastDepth(go);

    if (mHit.depth != int.MaxValue)
    {
    mHit.go = go;
    mHit.point = lastWorldPosition;
    mHits.Add(mHit);
    }
    }

    mHits.Sort(delegate(DepthEntry r1, DepthEntry r2) { return r2.depth.CompareTo(r1.depth); });

    for (int b = 0; b < mHits.size; ++b)
    {
    #if UNITY_FLASH
    if (IsVisible(mHits.buffer[b]))
    #else
    if (IsVisible(ref mHits.buffer[b]))
    #endif
    {
    mRayHitObject = mHits[b].go;
    mHits.Clear();
    return true;
    }
    }
    mHits.Clear();
    }
    else if (hits.Length == 1)
    {
    GameObject go = hits[0].gameObject;
    UIWidget w = go.GetComponent<UIWidget>();

    if (w != null)
    {
    if (!w.isVisible) continue;
    if (w.hitCheck != null && !w.hitCheck(lastWorldPosition)) continue;
    }
    else
    {
    UIRect rect = NGUITools.FindInParents<UIRect>(go);
    if (rect != null && rect.finalAlpha < 0.001f) continue;
    }

    if (IsVisible(lastWorldPosition, go))
    {
    mRayHitObject = go;
    return true;
    }
    }
    }
    continue;
    }
    else if (cam.eventType == EventType.UI_2D3D)
    {
    float enterdist = 0;
    if (m2DPlane.Raycast(ray, out enterdist))
    {
    lastWorldPosition = ray.GetPoint(enterdist);
    Collider2D[] hits = Physics2D.OverlapPointAll(lastWorldPosition, mask);
    bool bHaveTarget = true;
    if (hits.Length > 1)
    {
    for (int c = 0; c < hits.Length; ++c)
    {
    GameObject gotemp = hits[c].gameObject;
    //if (gotemp.CompareTag("Map"))
    //{
    // bHaveTarget = true;
    // break;
    //}
    }
    if (bHaveTarget)
    {
    for (int b = 0; b < hits.Length; ++b)
    {
    GameObject go = hits[b].gameObject;
    UIWidget w = go.GetComponent<UIWidget>();

    if (w != null)
    {
    if (!w.isVisible) continue;
    if (w.hitCheck != null && !w.hitCheck(lastWorldPosition)) continue;
    }
    else
    {
    UIRect rect = NGUITools.FindInParents<UIRect>(go);
    if (rect != null && rect.finalAlpha < 0.001f) continue;
    }

    mHit.depth = NGUITools.CalculateRaycastDepth(go);

    if (mHit.depth != int.MaxValue)
    {
    mHit.go = go;
    mHit.point = lastWorldPosition;
    mHits.Add(mHit);
    }
    }

    mHits.Sort(delegate (DepthEntry r1, DepthEntry r2) { return r2.depth.CompareTo(r1.depth); });

    for (int b = 0; b < mHits.size; ++b)
    {
    #if UNITY_FLASH
    if (IsVisible(mHits.buffer[b]))
    #else
    if (IsVisible(ref mHits.buffer[b]))
    #endif
    {
    mRayHitObject = mHits[b].go;
    mHits.Clear();
    return true;
    }
    }
    mHits.Clear();
    }
    }
    else if (hits.Length == 1)
    {
    GameObject go = hits[0].gameObject;
    //if (go.CompareTag("Map"))
    {
    UIWidget w = go.GetComponent<UIWidget>();

    if (w != null)
    {
    if (!w.isVisible) continue;
    if (w.hitCheck != null && !w.hitCheck(lastWorldPosition)) continue;
    }
    else
    {
    UIRect rect = NGUITools.FindInParents<UIRect>(go);
    if (rect != null && rect.finalAlpha < 0.001f) continue;
    }

    if (IsVisible(lastWorldPosition, go))
    {
    mRayHitObject = go;
    return true;
    }
    }
    }
    }
    if (true)
    {
    RaycastHit[] hits1 = Physics.RaycastAll(ray, dist, mask);

    if (hits1.Length > 1)
    {
    for (int b = 0; b < hits1.Length; ++b)
    {
    GameObject go = hits1[b].collider.gameObject;
    UIWidget w = go.GetComponent<UIWidget>();

    if (w != null)
    {
    if (!w.isVisible) continue;
    if (w.hitCheck != null && !w.hitCheck(hits1[b].point)) continue;
    }
    else
    {
    UIRect rect = NGUITools.FindInParents<UIRect>(go);
    if (rect != null && rect.finalAlpha < 0.001f) continue;
    }

    mHit.depth = NGUITools.CalculateRaycastDepth(go);

    if (mHit.depth != int.MaxValue)
    {
    mHit.hit = hits1[b];
    mHit.point = hits1[b].point;
    mHit.go = hits1[b].collider.gameObject;
    mHits.Add(mHit);
    }
    }

    mHits.Sort(delegate (DepthEntry r1, DepthEntry r2) { return r2.depth.CompareTo(r1.depth); });

    for (int b = 0; b < mHits.size; ++b)
    {
    #if UNITY_FLASH
    if (IsVisible(mHits.buffer[b]))
    #else
    if (IsVisible(ref mHits.buffer[b]))
    #endif
    {
    lastHit = mHits[b].hit;
    mRayHitObject = mHits[b].go;
    lastWorldPosition = mHits[b].point;
    mHits.Clear();
    return true;
    }
    }
    mHits.Clear();
    }
    else if (hits1.Length == 1)
    {
    GameObject go = hits1[0].collider.gameObject;
    UIWidget w = go.GetComponent<UIWidget>();

    if (w != null)
    {
    if (!w.isVisible) continue;
    if (w.hitCheck != null && !w.hitCheck(hits1[0].point)) continue;
    }
    else
    {
    UIRect rect = NGUITools.FindInParents<UIRect>(go);
    if (rect != null && rect.finalAlpha < 0.001f) continue;
    }

    if (IsVisible(hits1[0].point, hits1[0].collider.gameObject))
    {
    lastHit = hits1[0];
    lastWorldPosition = hits1[0].point;
    mRayHitObject = lastHit.collider.gameObject;
    return true;
    }
    }
    }
    continue;
    // int bufDepth = -1;
    // if (m2DPlane.Raycast(ray, out dist))
    // {
    // lastWorldPosition = ray.GetPoint(dist);
    // Collider2D[] hits = Physics2D.OverlapPointAll(lastWorldPosition, mask);

    // if (hits.Length >= 1)
    // {
    // for (int b = 0; b < hits.Length; ++b)
    // {
    // GameObject go = hits[b].gameObject;
    // UIWidget w = go.GetComponent<UIWidget>();

    // if (w != null)
    // {
    // if (!w.isVisible) continue;
    // if (w.hitCheck != null && !w.hitCheck(lastWorldPosition)) continue;
    // }
    // else
    // {
    // UIRect rect = NGUITools.FindInParents<UIRect>(go);
    // if (rect != null && rect.finalAlpha < 0.001f) continue;
    // }

    // mHit.depth = NGUITools.CalculateRaycastDepth(go);

    // if (mHit.depth != int.MaxValue)
    // {
    // mHit.go = go;
    // mHit.point = lastWorldPosition;
    // mHits.Add(mHit);
    // }
    // }

    // mHits.Sort(delegate (DepthEntry r1, DepthEntry r2) { return r2.depth.CompareTo(r1.depth); });

    // for (int b = 0; b < mHits.size; ++b)
    // {
    //#if UNITY_FLASH
    //if (IsVisible(mHits.buffer[b]))
    //#else
    // if (IsVisible(ref mHits.buffer[b]))
    //#endif
    // {
    // bufDepth = mHits[b].depth;
    // hoveredObject = mHits[b].go;
    // mHits.Clear();
    // break;
    // }
    // }
    // mHits.Clear();
    // }
    // }
    // if (true)
    // {
    // RaycastHit[] hits = Physics.RaycastAll(ray, dist, mask);

    // if (hits.Length >= 1)
    // {
    // for (int b = 0; b < hits.Length; ++b)
    // {
    // GameObject go = hits[b].collider.gameObject;
    // UIWidget w = go.GetComponent<UIWidget>();

    // if (w != null)
    // {
    // if (!w.isVisible) continue;
    // if (w.hitCheck != null && !w.hitCheck(hits[b].point)) continue;
    // }
    // else
    // {
    // UIRect rect = NGUITools.FindInParents<UIRect>(go);
    // if (rect != null && rect.finalAlpha < 0.001f) continue;
    // }

    // mHit.depth = NGUITools.CalculateRaycastDepth(go);

    // if (mHit.depth != int.MaxValue)
    // {
    // mHit.hit = hits[b];
    // mHit.point = hits[b].point;
    // mHit.go = hits[b].collider.gameObject;
    // mHits.Add(mHit);
    // }
    // }

    // mHits.Sort(delegate (DepthEntry r1, DepthEntry r2) { return r2.depth.CompareTo(r1.depth); });

    // for (int b = 0; b < mHits.size; ++b)
    // {
    //#if UNITY_FLASH
    //if (IsVisible(mHits.buffer[b]))
    //#else
    // if (IsVisible(ref mHits.buffer[b]))
    //#endif
    // {
    // if (hoveredObject == null || bufDepth < mHits[b].depth)
    // {
    // lastHit = mHits[b].hit;
    // hoveredObject = mHits[b].go;
    // lastWorldPosition = mHits[b].point;
    // mHits.Clear();
    // break;
    // }
    // }
    // }
    // mHits.Clear();
    // }
    // }
    // if (hoveredObject != null)
    // {
    // return true;
    // }
    // continue;
    }
    }
    return false;
    }

    static Plane m2DPlane = new Plane(Vector3.back, 0f);

    /// <summary>
    /// Helper function to check if the specified hit is visible by the panel.
    /// </summary>

    static bool IsVisible (Vector3 worldPoint, GameObject go)
    {
    UIPanel panel = NGUITools.FindInParents<UIPanel>(go);

    while (panel != null)
    {
    if (!panel.IsVisible(worldPoint)) return false;
    panel = panel.parentPanel;
    }
    return true;
    }

    /// <summary>
    /// Helper function to check if the specified hit is visible by the panel.
    /// </summary>

    #if UNITY_FLASH
    static bool IsVisible (DepthEntry de)
    #else
    static bool IsVisible (ref DepthEntry de)
    #endif
    {
    UIPanel panel = NGUITools.FindInParents<UIPanel>(de.go);

    while (panel != null)
    {
    if (!panel.IsVisible(de.point)) return false;
    panel = panel.parentPanel;
    }
    return true;
    }

    /// <summary>
    /// Whether the specified object should be highlighted.
    /// </summary>

    static public bool IsHighlighted (GameObject go) { return (UICamera.hoveredObject == go); }

    /// <summary>
    /// Find the camera responsible for handling events on objects of the specified layer.
    /// </summary>

    static public UICamera FindCameraForLayer (int layer)
    {
    int layerMask = 1 << layer;

    for (int i = 0; i < list.size; ++i)
    {
    UICamera cam = list.buffer[i];
    Camera uc = cam.cachedCamera;
    if ((uc != null) && (uc.cullingMask & layerMask) != 0) return cam;
    }
    return null;
    }

    /// <summary>
    /// Using the keyboard will result in 1 or -1, depending on whether up or down keys have been pressed.
    /// </summary>

    static int GetDirection (KeyCode up, KeyCode down)
    {
    if (GetKeyDown(up)) { currentKey = up; return 1; }
    if (GetKeyDown(down)) { currentKey = down; return -1; }
    return 0;
    }

    /// <summary>
    /// Using the keyboard will result in 1 or -1, depending on whether up or down keys have been pressed.
    /// </summary>

    static int GetDirection (KeyCode up0, KeyCode up1, KeyCode down0, KeyCode down1)
    {
    if (GetKeyDown(up0)) { currentKey = up0; return 1; }
    if (GetKeyDown(up1)) { currentKey = up1; return 1; }
    if (GetKeyDown(down0)) { currentKey = down0; return -1; }
    if (GetKeyDown(down1)) { currentKey = down1; return -1; }
    return 0;
    }

    // Used to ensure that joystick-based controls don't trigger that often
    static float mNextEvent = 0f;

    /// <summary>
    /// Using the joystick to move the UI results in 1 or -1 if the threshold has been passed, mimicking up/down keys.
    /// </summary>

    static int GetDirection (string axis)
    {
    float time = RealTime.time;

    if (mNextEvent < time && !string.IsNullOrEmpty(axis))
    {
    float val = GetAxis(axis);

    if (val > 0.75f)
    {
    currentKey = KeyCode.JoystickButton0;
    mNextEvent = time + 0.25f;
    return 1;
    }

    if (val < -0.75f)
    {
    currentKey = KeyCode.JoystickButton0;
    mNextEvent = time + 0.25f;
    return -1;
    }
    }
    return 0;
    }

    static int mNotifying = 0;

    /// <summary>
    /// Generic notification function. Used in place of SendMessage to shorten the code and allow for more than one receiver.
    /// </summary>

    static public void Notify (GameObject go, string funcName, object obj)
    {
    if (mNotifying > 10) return;

    // Automatically forward events to the currently open popup list
    if (currentScheme == ControlScheme.Controller && UIPopupList.isOpen &&
    UIPopupList.current.source == go && UIPopupList.isOpen)
    go = UIPopupList.current.gameObject;

    if (go && go.activeInHierarchy)
    {
    ++mNotifying;
    //if (currentScheme == ControlScheme.Controller)
    // Debug.Log((go != null ? "[" + go.name + "]." : "[global].") + funcName + "(" + obj + ");", go);
    try {
    go.SendMessage(funcName, obj, SendMessageOptions.DontRequireReceiver);
    if (mGenericHandler != null && mGenericHandler != go)
    mGenericHandler.SendMessage(funcName, obj, SendMessageOptions.DontRequireReceiver);
    }
    catch (System.Exception _e)
    {
    UnityEngine.Debug.LogError(_e.ToString());
    }
    --mNotifying;
    }
    }

    /// <summary>
    /// Add this camera to the list.
    /// </summary>

    void Awake ()
    {
    mWidth = Screen.width;
    mHeight = Screen.height;

    #if (UNITY_IPHONE || UNITY_ANDROID || UNITY_WP8 || UNITY_WP_8_1 || UNITY_BLACKBERRY || UNITY_WINRT || UNITY_METRO)
    currentScheme = ControlScheme.Touch;
    #else
    if (Application.platform == RuntimePlatform.PS3 ||
    Application.platform == RuntimePlatform.XBOX360)
    {
    currentScheme = ControlScheme.Controller;
    }
    #endif

    // Save the starting mouse position
    mMouse[0].pos = Input.mousePosition;

    for (int i = 1; i < 3; ++i)
    {
    mMouse[i].pos = mMouse[0].pos;
    mMouse[i].lastPos = mMouse[0].pos;
    }
    mLastPos = mMouse[0].pos;

    #if !UNITY_EDITOR && (UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_STANDALONE_LINUX)
    string[] args = System.Environment.GetCommandLineArgs();

    if (args != null)
    {
    for (int i = 0; i < args.Length; ++i)
    {
    string s = args[i];
    if (s == "-noMouse") useMouse = false;
    else if (s == "-noTouch") useTouch = false;
    else if (s == "-noController") { useController = false; ignoreControllerInput = true; }
    else if (s == "-noJoystick") { useController = false; ignoreControllerInput = true; }
    else if (s == "-useMouse") useMouse = true;
    else if (s == "-useTouch") useTouch = true;
    else if (s == "-useController") useController = true;
    else if (s == "-useJoystick") useController = true;
    }
    }
    #endif
    }

    /// <summary>
    /// Sort the list when enabled.
    /// </summary>

    void OnEnable ()
    {
    list.Add(this);
    list.Sort(CompareFunc);
    }

    /// <summary>
    /// Remove this camera from the list.
    /// </summary>

    void OnDisable () { list.Remove(this); }

    #if UNITY_EDITOR || UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_STANDALONE_LINUX
    static bool disableControllerCheck = true;
    #endif

    /// <summary>
    /// We don't want the camera to send out any kind of mouse events.
    /// </summary>

    void Start ()
    {
    if (eventType != EventType.World_3D && cachedCamera.transparencySortMode != TransparencySortMode.Orthographic)
    cachedCamera.transparencySortMode = TransparencySortMode.Orthographic;

    if (Application.isPlaying)
    {
    // Always set a fall-through object
    if (fallThrough == null)
    {
    UIRoot root = NGUITools.FindInParents<UIRoot>(gameObject);
    fallThrough = (root != null) ? root.gameObject : gameObject;
    }
    cachedCamera.eventMask = 0;

    #if UNITY_EDITOR || UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_STANDALONE_LINUX
    // Automatically disable controller-based input if the game starts with a non-zero controller input.
    // This most commonly happens with Thrustmaster and other similar joystick types.
    if (!ignoreControllerInput && disableControllerCheck && useController && handlesEvents)
    {
    disableControllerCheck = false;
    if (!string.IsNullOrEmpty(horizontalAxisName) && Mathf.Abs(GetAxis(horizontalAxisName)) > 0.1f) ignoreControllerInput = true;
    else if (!string.IsNullOrEmpty(verticalAxisName) && Mathf.Abs(GetAxis(verticalAxisName)) > 0.1f) ignoreControllerInput = true;
    else if (!string.IsNullOrEmpty(horizontalPanAxisName) && Mathf.Abs(GetAxis(horizontalPanAxisName)) > 0.1f) ignoreControllerInput = true;
    else if (!string.IsNullOrEmpty(verticalPanAxisName) && Mathf.Abs(GetAxis(verticalPanAxisName)) > 0.1f) ignoreControllerInput = true;
    }
    #endif
    }
    }

    #if UNITY_EDITOR
    void OnValidate () { Start(); }
    #endif

    /// <summary>
    /// Check the input and send out appropriate events.
    /// </summary>

    void Update ()
    {
    // Only the first UI layer should be processing events
    #if UNITY_EDITOR
    if (!Application.isPlaying || !handlesEvents) return;
    #else
    if (!handlesEvents) return;
    #endif
    if (processEventsIn == ProcessEventsIn.Update) ProcessEvents();
    }

    /// <summary>
    /// Keep an eye on screen size changes.
    /// </summary>

    void LateUpdate ()
    {
    #if UNITY_EDITOR
    if (!Application.isPlaying || !handlesEvents) return;
    #else
    if (!handlesEvents) return;
    #endif
    if (processEventsIn == ProcessEventsIn.LateUpdate) ProcessEvents();

    int w = Screen.width;
    int h = Screen.height;

    if (w != mWidth || h != mHeight)
    {
    mWidth = w;
    mHeight = h;

    UIRoot.Broadcast("UpdateAnchors");

    if (onScreenResize != null)
    onScreenResize();
    }
    }

    /// <summary>
    /// Process all events.
    /// </summary>

    void ProcessEvents ()
    {
    current = this;
    NGUIDebug.debugRaycast = debug;

    // Process touch events first
    if (useTouch) ProcessTouches();
    else if (useMouse) ProcessMouse();

    // Custom input processing
    if (onCustomInput != null) onCustomInput();

    // Update the keyboard and joystick events
    if ((useKeyboard || useController) && !disableController && !ignoreControllerInput) ProcessOthers();

    // If it's time to show a tooltip, inform the object we're hovering over
    if (useMouse && mHover != null && currentScheme == ControlScheme.Mouse)
    {
    float scroll = !string.IsNullOrEmpty(scrollAxisName) ? GetAxis(scrollAxisName) : 0f;

    if (scroll != 0f)
    {
    if (onScroll != null) onScroll(mHover, scroll);
    Notify(mHover, "OnScroll", scroll);
    }

    if (showTooltips && mTooltipTime != 0f && !UIPopupList.isOpen && mMouse[0].dragged == null &&
    (mTooltipTime < RealTime.time || GetKey(KeyCode.LeftShift) || GetKey(KeyCode.RightShift)))
    {
    currentTouch = mMouse[0];
    currentTouchID = -1;
    ShowTooltip(mHover);
    }
    }

    if (mTooltip != null && !NGUITools.GetActive(mTooltip))
    ShowTooltip(null);

    current = null;
    currentTouchID = -100;
    }

    /// <summary>
    /// Update mouse input.
    /// </summary>

    public void ProcessMouse ()
    {
    // Is any button currently pressed?
    bool isPressed = false;
    bool justPressed = false;

    for (int i = 0; i < 3; ++i)
    {
    if (Input.GetMouseButtonDown(i))
    {
    currentKey = KeyCode.Mouse0 + i;
    justPressed = true;
    isPressed = true;
    }
    else if (Input.GetMouseButton(i))
    {
    currentKey = KeyCode.Mouse0 + i;
    isPressed = true;
    }
    }

    // We're currently using touches -- do nothing
    if (currentScheme == ControlScheme.Touch) return;

    currentTouch = mMouse[0];

    // Update the position and delta
    Vector2 pos = Input.mousePosition;

    if (currentTouch.ignoreDelta == 0)
    {
    currentTouch.delta = pos - currentTouch.pos;
    }
    else
    {
    --currentTouch.ignoreDelta;
    currentTouch.delta.x = 0f;
    currentTouch.delta.y = 0f;
    }

    float sqrMag = currentTouch.delta.sqrMagnitude;
    currentTouch.pos = pos;
    mLastPos = pos;

    bool posChanged = false;

    if (currentScheme != ControlScheme.Mouse)
    {
    if (sqrMag < 0.001f) return; // Nothing changed and we are not using the mouse -- exit
    currentKey = KeyCode.Mouse0;
    posChanged = true;
    }
    else if (sqrMag > 0.001f) posChanged = true;

    // Propagate the updates to the other mouse buttons
    for (int i = 1; i < 3; ++i)
    {
    mMouse[i].pos = currentTouch.pos;
    mMouse[i].delta = currentTouch.delta;
    }

    // No need to perform raycasts every frame
    if (isPressed || posChanged || mNextRaycast < RealTime.time)
    {
    mNextRaycast = RealTime.time + 0.02f;
    Raycast(currentTouch);
    for (int i = 0; i < 3; ++i) mMouse[i].current = currentTouch.current;
    }

    bool highlightChanged = (currentTouch.last != currentTouch.current);
    bool wasPressed = (currentTouch.pressed != null);

    if (!wasPressed)
    hoveredObject = currentTouch.current;

    currentTouchID = -1;
    if (highlightChanged) currentKey = KeyCode.Mouse0;

    if (!isPressed && posChanged && (!stickyTooltip || highlightChanged))
    {
    if (mTooltipTime != 0f)
    {
    // Delay the tooltip
    mTooltipTime = Time.unscaledTime + tooltipDelay;
    }
    else if (mTooltip != null)
    {
    // Hide the tooltip
    ShowTooltip(null);
    }
    }

    // Generic mouse move notifications
    if (posChanged && onMouseMove != null)
    {
    onMouseMove(currentTouch.delta);
    currentTouch = null;
    }

    // The button was released over a different object -- remove the highlight from the previous
    if (highlightChanged && (justPressed || (wasPressed && !isPressed)))
    hoveredObject = null;

    // Process all 3 mouse buttons as individual touches
    for (int i = 0; i < 3; ++i)
    {
    bool pressed = Input.GetMouseButtonDown(i);
    bool unpressed = Input.GetMouseButtonUp(i);
    if (pressed || unpressed) currentKey = KeyCode.Mouse0 + i;
    currentTouch = mMouse[i];

    #if UNITY_STANDALONE_OSX || UNITY_EDITOR_OSX
    if (commandClick && i == 0 && (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl)))
    {
    currentTouchID = -2;
    currentKey = KeyCode.Mouse1;
    }
    else
    #endif
    {
    currentTouchID = -1 - i;
    currentKey = KeyCode.Mouse0 + i;
    }

    // We don't want to update the last camera while there is a touch happening
    if (pressed)
    {
    currentTouch.pressedCam = currentCamera;
    currentTouch.pressTime = RealTime.time;
    }
    else if (currentTouch.pressed != null) currentCamera = currentTouch.pressedCam;

    // Process the mouse events
    ProcessTouch(pressed, unpressed);
    }

    // If nothing is pressed and there is an object under the touch, highlight it
    if (!isPressed && highlightChanged)
    {
    currentTouch = mMouse[0];
    mTooltipTime = Time.unscaledTime + tooltipDelay;
    currentTouchID = -1;
    currentKey = KeyCode.Mouse0;
    hoveredObject = currentTouch.current;
    }

    currentTouch = null;

    // Update the last value
    mMouse[0].last = mMouse[0].current;
    for (int i = 1; i < 3; ++i) mMouse[i].last = mMouse[0].last;
    }

    static bool mUsingTouchEvents = true;

    public class Touch
    {
    public int fingerId;
    public TouchPhase phase = TouchPhase.Began;
    public Vector2 position;
    public int tapCount = 0;
    }

    public delegate int GetTouchCountCallback ();
    public delegate Touch GetTouchCallback (int index);

    static public GetTouchCountCallback GetInputTouchCount;
    static public GetTouchCallback GetInputTouch;

    /// <summary>
    /// Update touch-based events.
    /// </summary>

    public void ProcessTouches ()
    {
    int count = (GetInputTouchCount == null) ? Input.touchCount : GetInputTouchCount();

    for (int i = 0; i < count; ++i)
    {
    int fingerId;
    TouchPhase phase;
    Vector2 position;
    int tapCount;

    if (GetInputTouch == null)
    {
    UnityEngine.Touch touch = Input.GetTouch(i);
    phase = touch.phase;
    fingerId = touch.fingerId;
    position = touch.position;
    tapCount = touch.tapCount;
    #if UNITY_WIIU && !UNITY_EDITOR
    // Unity bug: http://www.tasharen.com/forum/index.php?topic=5821.0
    position.y = Screen.height - position.y;
    #endif
    }
    else
    {
    Touch touch = GetInputTouch(i);
    phase = touch.phase;
    fingerId = touch.fingerId;
    position = touch.position;
    tapCount = touch.tapCount;
    }

    currentTouchID = allowMultiTouch ? fingerId : 1;
    currentTouch = GetTouch(currentTouchID, true);

    bool pressed = (phase == TouchPhase.Began) || currentTouch.touchBegan;
    bool unpressed = (phase == TouchPhase.Canceled) || (phase == TouchPhase.Ended);
    currentTouch.delta = position - currentTouch.pos;
    currentTouch.pos = position;
    currentKey = KeyCode.None;

    // Raycast into the screen
    Raycast(currentTouch);

    // We don't want to update the last camera while there is a touch happening
    if (pressed) currentTouch.pressedCam = currentCamera;
    else if (currentTouch.pressed != null) currentCamera = currentTouch.pressedCam;

    // Double-tap support
    if (tapCount > 1) currentTouch.clickTime = RealTime.time;

    // Process the events from this touch
    ProcessTouch(pressed, unpressed);

    // If the touch has ended, remove it from the list
    if (unpressed) RemoveTouch(currentTouchID);

    currentTouch.touchBegan = false;
    currentTouch.last = null;
    currentTouch = null;

    // Don't consider other touches
    if (!allowMultiTouch) break;
    }

    if (count == 0)
    {
    // Skip the first frame after using touch events
    if (mUsingTouchEvents)
    {
    mUsingTouchEvents = false;
    return;
    }

    if (useMouse) ProcessMouse();
    #if UNITY_EDITOR
    else if (GetInputTouch == null) ProcessFakeTouches();
    #endif
    }
    else mUsingTouchEvents = true;
    }

    /// <summary>
    /// Process fake touch events where the mouse acts as a touch device.
    /// Useful for testing mobile functionality in the editor.
    /// </summary>

    void ProcessFakeTouches ()
    {
    bool pressed = Input.GetMouseButtonDown(0);
    bool unpressed = Input.GetMouseButtonUp(0);
    bool held = Input.GetMouseButton(0);

    if (pressed || unpressed || held)
    {
    currentTouchID = 1;
    currentTouch = mMouse[0];
    currentTouch.touchBegan = pressed;

    if (pressed)
    {
    currentTouch.pressTime = RealTime.time;
    activeTouches.Add(currentTouch);
    }

    Vector2 pos = Input.mousePosition;
    currentTouch.delta = pos - currentTouch.pos;
    currentTouch.pos = pos;

    // Raycast into the screen
    Raycast(currentTouch);

    // We don't want to update the last camera while there is a touch happening
    if (pressed) currentTouch.pressedCam = currentCamera;
    else if (currentTouch.pressed != null) currentCamera = currentTouch.pressedCam;

    // Process the events from this touch
    currentKey = KeyCode.None;
    ProcessTouch(pressed, unpressed);

    // If the touch has ended, remove it from the list
    if (unpressed) activeTouches.Remove(currentTouch);
    currentTouch.last = null;
    currentTouch = null;
    }
    }

    /// <summary>
    /// Process keyboard and joystick events.
    /// </summary>

    public void ProcessOthers ()
    {
    currentTouchID = -100;
    currentTouch = controller;

    bool submitKeyDown = false;
    bool submitKeyUp = false;

    if (submitKey0 != KeyCode.None && GetKeyDown(submitKey0))
    {
    currentKey = submitKey0;
    submitKeyDown = true;
    }
    else if (submitKey1 != KeyCode.None && GetKeyDown(submitKey1))
    {
    currentKey = submitKey1;
    submitKeyDown = true;
    }
    else if ((submitKey0 == KeyCode.Return || submitKey1 == KeyCode.Return) && GetKeyDown(KeyCode.KeypadEnter))
    {
    currentKey = submitKey0;
    submitKeyDown = true;
    }

    if (submitKey0 != KeyCode.None && GetKeyUp(submitKey0))
    {
    currentKey = submitKey0;
    submitKeyUp = true;
    }
    else if (submitKey1 != KeyCode.None && GetKeyUp(submitKey1))
    {
    currentKey = submitKey1;
    submitKeyUp = true;
    }
    else if ((submitKey0 == KeyCode.Return || submitKey1 == KeyCode.Return) && GetKeyUp(KeyCode.KeypadEnter))
    {
    currentKey = submitKey0;
    submitKeyUp = true;
    }

    if (submitKeyDown) currentTouch.pressTime = RealTime.time;

    if ((submitKeyDown || submitKeyUp) && currentScheme == ControlScheme.Controller)
    {
    currentTouch.current = controllerNavigationObject;
    ProcessTouch(submitKeyDown, submitKeyUp);
    currentTouch.last = currentTouch.current;
    }

    KeyCode lastKey = KeyCode.None;

    // Handle controller events
    if (useController && !ignoreControllerInput)
    {
    // Automatically choose the first available selection object
    if (!disableController && currentScheme == ControlScheme.Controller && (currentTouch.current == null || !currentTouch.current.activeInHierarchy))
    currentTouch.current = controllerNavigationObject;

    if (!string.IsNullOrEmpty(verticalAxisName))
    {
    int vertical = GetDirection(verticalAxisName);

    if (vertical != 0)
    {
    ShowTooltip(null);
    currentScheme = ControlScheme.Controller;
    currentTouch.current = controllerNavigationObject;

    if (currentTouch.current != null)
    {
    lastKey = vertical > 0 ? KeyCode.UpArrow : KeyCode.DownArrow;
    if (onNavigate != null) onNavigate(currentTouch.current, lastKey);
    Notify(currentTouch.current, "OnNavigate", lastKey);
    }
    }
    }

    if (!string.IsNullOrEmpty(horizontalAxisName))
    {
    int horizontal = GetDirection(horizontalAxisName);

    if (horizontal != 0)
    {
    ShowTooltip(null);
    currentScheme = ControlScheme.Controller;
    currentTouch.current = controllerNavigationObject;

    if (currentTouch.current != null)
    {
    lastKey = horizontal > 0 ? KeyCode.RightArrow : KeyCode.LeftArrow;
    if (onNavigate != null) onNavigate(currentTouch.current, lastKey);
    Notify(currentTouch.current, "OnNavigate", lastKey);
    }
    }
    }

    float x = !string.IsNullOrEmpty(horizontalPanAxisName) ? GetAxis(horizontalPanAxisName) : 0f;
    float y = !string.IsNullOrEmpty(verticalPanAxisName) ? GetAxis(verticalPanAxisName) : 0f;

    if (x != 0f || y != 0f)
    {
    ShowTooltip(null);
    currentScheme = ControlScheme.Controller;
    currentTouch.current = controllerNavigationObject;

    if (currentTouch.current != null)
    {
    Vector2 delta = new Vector2(x, y);
    delta *= Time.unscaledDeltaTime;
    if (onPan != null) onPan(currentTouch.current, delta);
    Notify(currentTouch.current, "OnPan", delta);
    }
    }
    }

    // Send out all key events
    if (GetAnyKeyDown != null ? GetAnyKeyDown() : Input.anyKeyDown)
    {
    for (int i = 0, imax = NGUITools.keys.Length; i < imax; ++i)
    {
    KeyCode key = NGUITools.keys[i];
    if (lastKey == key) continue;
    if (!GetKeyDown(key)) continue;

    if (!useKeyboard && key < KeyCode.Mouse0) continue;
    if ((!useController || ignoreControllerInput) && key >= KeyCode.JoystickButton0) continue;
    if (!useMouse && (key >= KeyCode.Mouse0 || key <= KeyCode.Mouse6)) continue;

    currentKey = key;
    if (onKey != null) onKey(currentTouch.current, key);
    Notify(currentTouch.current, "OnKey", key);
    }
    }

    currentTouch = null;
    }

    /// <summary>
    /// Process the press part of a touch.
    /// </summary>

    void ProcessPress (bool pressed, float click, float drag)
    {
    // Send out the press message
    if (pressed)
    {
    if (mTooltip != null) ShowTooltip(null);
    mTooltipTime = Time.unscaledTime + tooltipDelay;
    currentTouch.pressStarted = true;
    if (onPress != null && currentTouch.pressed)
    onPress(currentTouch.pressed, false);

    Notify(currentTouch.pressed, "OnPress", false);

    if (currentScheme == ControlScheme.Mouse && hoveredObject == null && currentTouch.current != null)
    hoveredObject = currentTouch.current;

    currentTouch.pressed = currentTouch.current;
    currentTouch.dragged = currentTouch.current;
    currentTouch.clickNotification = ClickNotification.BasedOnDelta;
    currentTouch.totalDelta = Vector2.zero;
    currentTouch.dragStarted = false;

    if (onPress != null && currentTouch.pressed)
    onPress(currentTouch.pressed, true);

    Notify(currentTouch.pressed, "OnPress", true);

    // Change the selection
    if (mSelected != currentTouch.pressed)
    {
    // Input no longer has selection, even if it did
    mInputFocus = false;

    // Remove the selection
    if (mSelected)
    {
    Notify(mSelected, "OnSelect", false);
    if (onSelect != null) onSelect(mSelected, false);
    }

    // Change the selection
    mSelected = currentTouch.pressed;

    if (currentTouch.pressed != null)
    {
    UIKeyNavigation nav = currentTouch.pressed.GetComponent<UIKeyNavigation>();
    if (nav != null) controller.current = currentTouch.pressed;
    }

    // Set the selection
    if (mSelected)
    {
    mInputFocus = (mSelected.activeInHierarchy && mSelected.GetComponent<UIInput>() != null);
    if (onSelect != null) onSelect(mSelected, true);
    Notify(mSelected, "OnSelect", true);
    }
    }
    }
    else if (currentTouch.pressed != null && (currentTouch.delta.sqrMagnitude != 0f || currentTouch.current != currentTouch.last))
    {
    // Keep track of the total movement
    currentTouch.totalDelta += currentTouch.delta;
    float mag = currentTouch.totalDelta.sqrMagnitude;
    bool justStarted = false;

    // If the drag process hasn't started yet but we've already moved off the object, start it immediately
    if (!currentTouch.dragStarted && currentTouch.last != currentTouch.current)
    {
    currentTouch.dragStarted = true;
    currentTouch.delta = currentTouch.totalDelta;

    // OnDragOver is sent for consistency, so that OnDragOut is always preceded by OnDragOver
    isDragging = true;

    if (onDragStart != null) onDragStart(currentTouch.dragged);
    Notify(currentTouch.dragged, "OnDragStart", null);

    if (onDragOver != null) onDragOver(currentTouch.last, currentTouch.dragged);
    Notify(currentTouch.last, "OnDragOver", currentTouch.dragged);

    isDragging = false;
    }
    else if (!currentTouch.dragStarted && drag < mag)
    {
    // If the drag event has not yet started, see if we've dragged the touch far enough to start it
    justStarted = true;
    currentTouch.dragStarted = true;
    currentTouch.delta = currentTouch.totalDelta;
    }

    // If we're dragging the touch, send out drag events
    if (currentTouch.dragStarted)
    {
    if (mTooltip != null) ShowTooltip(null);

    isDragging = true;
    bool isDisabled = (currentTouch.clickNotification == ClickNotification.None);

    if (justStarted)
    {
    if (onDragStart != null) onDragStart(currentTouch.dragged);
    Notify(currentTouch.dragged, "OnDragStart", null);

    if (onDragOver != null) onDragOver(currentTouch.last, currentTouch.dragged);
    Notify(currentTouch.current, "OnDragOver", currentTouch.dragged);
    }
    else if (currentTouch.last != currentTouch.current)
    {
    if (onDragOut != null) onDragOut(currentTouch.last, currentTouch.dragged);
    Notify(currentTouch.last, "OnDragOut", currentTouch.dragged);

    if (onDragOver != null) onDragOver(currentTouch.last, currentTouch.dragged);
    Notify(currentTouch.current, "OnDragOver", currentTouch.dragged);
    }

    if (onDrag != null) onDrag(currentTouch.dragged, currentTouch.delta);
    Notify(currentTouch.dragged, "OnDrag", currentTouch.delta);

    currentTouch.last = currentTouch.current;
    isDragging = false;

    if (isDisabled)
    {
    // If the notification status has already been disabled, keep it as such
    currentTouch.clickNotification = ClickNotification.None;
    }
    else if (currentTouch.clickNotification == ClickNotification.BasedOnDelta && click < mag)
    {
    // We've dragged far enough to cancel the click
    currentTouch.clickNotification = ClickNotification.None;
    }
    }
    }
    }

    /// <summary>
    /// Process the release part of a touch.
    /// </summary>

    void ProcessRelease (bool isMouse, float drag)
    {
    // Send out the unpress message
    if (currentTouch == null) return;
    currentTouch.pressStarted = false;

    if (currentTouch.pressed != null)
    {
    // If there was a drag event in progress, make sure OnDragOut gets sent
    if (currentTouch.dragStarted)
    {
    if (onDragOut != null) onDragOut(currentTouch.last, currentTouch.dragged);
    Notify(currentTouch.last, "OnDragOut", currentTouch.dragged);

    if (onDragEnd != null) onDragEnd(currentTouch.dragged);
    Notify(currentTouch.dragged, "OnDragEnd", null);
    }

    // Send the notification of a touch ending
    if (onPress != null) onPress(currentTouch.pressed, false);
    Notify(currentTouch.pressed, "OnPress", false);

    // Send a hover message to the object
    if (isMouse && HasCollider(currentTouch.pressed))
    {
    // OnHover is sent to restore the visual state
    if (mHover == currentTouch.current)
    {
    if (onHover != null) onHover(currentTouch.current, true);
    Notify(currentTouch.current, "OnHover", true);
    }
    else hoveredObject = currentTouch.current;
    }

    // If the button/touch was released on the same object, consider it a click and select it
    if (currentTouch.dragged == currentTouch.current ||
    (currentScheme != ControlScheme.Controller &&
    currentTouch.clickNotification != ClickNotification.None &&
    currentTouch.totalDelta.sqrMagnitude < drag))
    {
    // If the touch should consider clicks, send out an OnClick notification
    if (currentTouch.clickNotification != ClickNotification.None && currentTouch.pressed == currentTouch.current)
    {
    ShowTooltip(null);
    float time = RealTime.time;

    if (onClick != null) onClick(currentTouch.pressed);
    Notify(currentTouch.pressed, "OnClick", null);

    if (currentTouch.clickTime + 0.35f > time)
    {
    if (onDoubleClick != null) onDoubleClick(currentTouch.pressed);
    Notify(currentTouch.pressed, "OnDoubleClick", null);
    }
    currentTouch.clickTime = time;
    }
    }
    else if (currentTouch.dragStarted) // The button/touch was released on a different object
    {
    // Send a drop notification (for drag & drop)
    if (onDrop != null) onDrop(currentTouch.current, currentTouch.dragged);
    Notify(currentTouch.current, "OnDrop", currentTouch.dragged);
    }
    }
    currentTouch.dragStarted = false;
    currentTouch.pressed = null;
    currentTouch.dragged = null;
    }

    bool HasCollider (GameObject go)
    {
    if (go == null) return false;
    Collider c = go.GetComponent<Collider>();
    if (c != null) return c.enabled;
    Collider2D b = go.GetComponent<Collider2D>();
    return (b != null && b.enabled);
    }

    /// <summary>
    /// Process the events of the specified touch.
    /// </summary>

    public void ProcessTouch (bool pressed, bool released)
    {
    if (released) mTooltipTime = 0f;

    // Whether we're using the mouse
    bool isMouse = (currentScheme == ControlScheme.Mouse);
    float drag = isMouse ? mouseDragThreshold : touchDragThreshold;
    float click = isMouse ? mouseClickThreshold : touchClickThreshold;

    // So we can use sqrMagnitude below
    drag *= drag;
    click *= click;

    if (currentTouch.pressed != null)
    {
    if (released) ProcessRelease(isMouse, drag);
    ProcessPress(pressed, click, drag);

    // Hold event = show tooltip
    if (currentTouch.deltaTime > tooltipDelay)
    {
    if (currentTouch.pressed == currentTouch.current && mTooltipTime != 0f && !currentTouch.dragStarted)
    {
    mTooltipTime = 0f;
    currentTouch.clickNotification = ClickNotification.None;
    if (longPressTooltip) ShowTooltip(currentTouch.pressed);
    Notify(currentTouch.current, "OnLongPress", null);
    }
    }
    }
    else if (isMouse || pressed || released)
    {
    ProcessPress(pressed, click, drag);
    if (released) ProcessRelease(isMouse, drag);
    }
    }

    /// <summary>
    /// Cancel the next tooltip, preventing it from being shown.
    /// Moving the mouse again will reset this counter.
    /// </summary>

    static public void CancelNextTooltip () { mTooltipTime = 0f; }

    /// <summary>
    /// Show or hide the tooltip.
    /// </summary>

    static public bool ShowTooltip (GameObject go)
    {
    if (mTooltip != go)
    {
    if (mTooltip != null)
    {
    if (onTooltip != null) onTooltip(mTooltip, false);
    Notify(mTooltip, "OnTooltip", false);
    }

    mTooltip = go;
    mTooltipTime = 0f;

    if (mTooltip != null)
    {
    if (onTooltip != null) onTooltip(mTooltip, true);
    Notify(mTooltip, "OnTooltip", true);
    }
    return true;
    }
    return false;
    }

    /// <summary>
    /// Hide the tooltip, if one is visible.
    /// </summary>

    static public bool HideTooltip () { return ShowTooltip(null); }
    }

  • 相关阅读:
    Java常用API(Arrays类)
    Java常用API(String类)
    Java常用API(Random类)
    Java匿名对象介绍
    Qt串口实现921600波特率的方法
    Qthread实现多线程操作
    小品QIODevice::Text参数
    Qt串口通信
    Linux下挂载新的磁盘
    互斥锁陷阱:优先级反转、死锁
  • 原文地址:https://www.cnblogs.com/rexzhao/p/8279041.html
Copyright © 2011-2022 走看看