mirror of
https://github.com/Ratstail91/Keep-It-Alive.git
synced 2025-11-29 10:34:27 +11:00
Working on it
This commit is contained in:
469
Assets/CarbonInput/Scripts/CarbonInputModule.cs
Normal file
469
Assets/CarbonInput/Scripts/CarbonInputModule.cs
Normal file
@@ -0,0 +1,469 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace CarbonInput {
|
||||
[AddComponentMenu("Event/Carbon Input Module")]
|
||||
public class CarbonInputModule : PointerInputModule {
|
||||
private const float Threshold = 0.3f;
|
||||
public PlayerIndex Player = PlayerIndex.Any;
|
||||
public CAxis HorizontalAxis = CAxis.LX;
|
||||
public bool InvertHorizontal;
|
||||
public CAxis VerticalAxis = CAxis.LY;
|
||||
public bool InvertVertical = true;
|
||||
public CButton SubmitButton = CButton.A;
|
||||
public CButton CancelButton = CButton.B;
|
||||
|
||||
private float m_PrevActionTime;
|
||||
private Vector2 m_LastMoveVector;
|
||||
private int m_ConsecutiveMoveCount;
|
||||
|
||||
private Vector2 m_LastMousePosition;
|
||||
private Vector2 m_MousePosition;
|
||||
private Vector2 _lastRawMove;
|
||||
|
||||
private bool HorizontalPressed { get { return Math.Abs(_lastRawMove.x) < Threshold && Math.Abs(GamePad.GetAxis(HorizontalAxis, Player)) > Threshold; } }
|
||||
private bool VerticalPressed { get { return Math.Abs(_lastRawMove.y) < Threshold && Math.Abs(GamePad.GetAxis(VerticalAxis, Player)) > Threshold; } }
|
||||
|
||||
protected CarbonInputModule() {
|
||||
}
|
||||
|
||||
[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 float m_InputActionsPerSecond = 10;
|
||||
|
||||
[SerializeField]
|
||||
private float m_RepeatDelay = 0.5f;
|
||||
|
||||
[SerializeField]
|
||||
[FormerlySerializedAs("m_AllowActivationOnMobileDevice")]
|
||||
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; }
|
||||
}
|
||||
|
||||
public bool forceModuleActive {
|
||||
get { return m_ForceModuleActive; }
|
||||
set { m_ForceModuleActive = value; }
|
||||
}
|
||||
|
||||
public float inputActionsPerSecond {
|
||||
get { return m_InputActionsPerSecond; }
|
||||
set { m_InputActionsPerSecond = value; }
|
||||
}
|
||||
|
||||
public float repeatDelay {
|
||||
get { return m_RepeatDelay; }
|
||||
set { m_RepeatDelay = value; }
|
||||
}
|
||||
|
||||
public override void UpdateModule() {
|
||||
m_LastMousePosition = m_MousePosition;
|
||||
m_MousePosition = Input.mousePosition;
|
||||
}
|
||||
|
||||
public override bool IsModuleSupported() {
|
||||
return m_ForceModuleActive || Input.mousePresent || Input.touchSupported;
|
||||
}
|
||||
|
||||
public override bool ShouldActivateModule() {
|
||||
if(!base.ShouldActivateModule())
|
||||
return false;
|
||||
|
||||
var state = GamePad.GetState(Player);
|
||||
var shouldActivate = m_ForceModuleActive;
|
||||
shouldActivate |= state.Pressed(SubmitButton);
|
||||
shouldActivate |= state.Pressed(CancelButton);
|
||||
shouldActivate |= GetRawMoveVector().sqrMagnitude > 0.0f;
|
||||
shouldActivate |= (m_MousePosition - m_LastMousePosition).sqrMagnitude > 0.0f;
|
||||
shouldActivate |= Input.GetMouseButtonDown(0);
|
||||
|
||||
if(Input.touchCount > 0)
|
||||
shouldActivate = true;
|
||||
|
||||
return shouldActivate;
|
||||
}
|
||||
|
||||
public override void ActivateModule() {
|
||||
base.ActivateModule();
|
||||
m_MousePosition = Input.mousePosition;
|
||||
m_LastMousePosition = Input.mousePosition;
|
||||
|
||||
var toSelect = eventSystem.currentSelectedGameObject;
|
||||
if(toSelect == null)
|
||||
toSelect = eventSystem.firstSelectedGameObject;
|
||||
|
||||
eventSystem.SetSelectedGameObject(toSelect, GetBaseEventData());
|
||||
}
|
||||
|
||||
public override void DeactivateModule() {
|
||||
base.DeactivateModule();
|
||||
ClearSelection();
|
||||
}
|
||||
|
||||
public override void Process() {
|
||||
bool usedEvent = SendUpdateEventToSelectedObject();
|
||||
|
||||
if(eventSystem.sendNavigationEvents) {
|
||||
if(!usedEvent)
|
||||
usedEvent |= SendMoveEventToSelectedObject();
|
||||
|
||||
if(!usedEvent)
|
||||
SendSubmitEventToSelectedObject();
|
||||
}
|
||||
|
||||
// touch needs to take precedence because of the mouse emulation layer
|
||||
if(!ProcessTouchEvents())
|
||||
ProcessMouseEvent();
|
||||
_lastRawMove = GetRawMoveVector();
|
||||
}
|
||||
|
||||
private bool ProcessTouchEvents() {
|
||||
for(int i = 0; i < Input.touchCount; ++i) {
|
||||
Touch input = Input.GetTouch(i);
|
||||
|
||||
if(input.type == TouchType.Indirect)
|
||||
continue;
|
||||
|
||||
bool released;
|
||||
bool pressed;
|
||||
var pointer = GetTouchPointerEventData(input, out pressed, out released);
|
||||
|
||||
ProcessTouchPress(pointer, pressed, released);
|
||||
|
||||
if(!released) {
|
||||
ProcessMove(pointer);
|
||||
ProcessDrag(pointer);
|
||||
} else
|
||||
RemovePointerData(pointer);
|
||||
}
|
||||
return Input.touchCount > 0;
|
||||
}
|
||||
|
||||
private 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);
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
if(pointerEvent.pointerDrag != null)
|
||||
ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.endDragHandler);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process submit keys.
|
||||
/// </summary>
|
||||
protected bool SendSubmitEventToSelectedObject() {
|
||||
if(eventSystem.currentSelectedGameObject == null)
|
||||
return false;
|
||||
|
||||
var state = GamePad.GetState(Player);
|
||||
var data = GetBaseEventData();
|
||||
if(state.Pressed(SubmitButton))
|
||||
ExecuteEvents.Execute(eventSystem.currentSelectedGameObject, data, ExecuteEvents.submitHandler);
|
||||
|
||||
if(state.Pressed(CancelButton))
|
||||
ExecuteEvents.Execute(eventSystem.currentSelectedGameObject, data, ExecuteEvents.cancelHandler);
|
||||
return data.used;
|
||||
}
|
||||
|
||||
private Vector2 GetMoveVector() {
|
||||
var x = GamePad.GetAxis(HorizontalAxis, Player);
|
||||
if(InvertHorizontal) x = -x;
|
||||
var y = GamePad.GetAxis(VerticalAxis, Player);
|
||||
if(InvertVertical) y = -y;
|
||||
return new Vector2(x, y);
|
||||
}
|
||||
|
||||
private Vector2 GetRawMoveVector() {
|
||||
Vector2 move = GetMoveVector();
|
||||
|
||||
if(HorizontalPressed) {
|
||||
if(move.x < 0)
|
||||
move.x = -1f;
|
||||
if(move.x > 0)
|
||||
move.x = 1f;
|
||||
}
|
||||
if(VerticalPressed) {
|
||||
if(move.y < 0)
|
||||
move.y = -1f;
|
||||
if(move.y > 0)
|
||||
move.y = 1f;
|
||||
}
|
||||
return move;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process keyboard events.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
// If user pressed key again, always allow event
|
||||
bool allow = HorizontalPressed || VerticalPressed;
|
||||
bool similarDir = (Vector2.Dot(movement, m_LastMoveVector) > 0);
|
||||
if(!allow) {
|
||||
// Otherwise, user held down key or axis.
|
||||
// If direction didn't change at least 90 degrees, wait for delay before allowing consequtive event.
|
||||
if(similarDir && m_ConsecutiveMoveCount == 1)
|
||||
allow = (time > m_PrevActionTime + m_RepeatDelay);
|
||||
// If direction changed at least 90 degree, or we already had the delay, repeat at repeat rate.
|
||||
else
|
||||
allow = (time > m_PrevActionTime + 1f / m_InputActionsPerSecond);
|
||||
}
|
||||
if(!allow)
|
||||
return false;
|
||||
|
||||
// Debug.Log(m_ProcessingEvent.rawType + " axis:" + m_AllowAxisEvents + " value:" + "(" + x + "," + y + ")");
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process all mouse events.
|
||||
/// </summary>
|
||||
protected void ProcessMouseEvent(int id) {
|
||||
var mouseData = GetMousePointerEventData(id);
|
||||
var leftButtonData = mouseData.GetButtonState(PointerEventData.InputButton.Left).eventData;
|
||||
|
||||
// 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>
|
||||
/// Process the current mouse press.
|
||||
/// </summary>
|
||||
protected void ProcessMousePress(MouseButtonEventData data) {
|
||||
var pointerEvent = data.buttonData;
|
||||
var currentOverGo = pointerEvent.pointerCurrentRaycast.gameObject;
|
||||
|
||||
// PointerDown notification
|
||||
if(data.PressedThisFrame()) {
|
||||
pointerEvent.eligibleForClick = true;
|
||||
pointerEvent.delta = Vector2.zero;
|
||||
pointerEvent.dragging = false;
|
||||
pointerEvent.useDragThreshold = true;
|
||||
pointerEvent.pressPosition = pointerEvent.position;
|
||||
pointerEvent.pointerPressRaycast = pointerEvent.pointerCurrentRaycast;
|
||||
|
||||
DeselectIfSelectionChanged(currentOverGo, pointerEvent);
|
||||
|
||||
// search for the control that will receive the press
|
||||
// if we can't find a press handler set the press
|
||||
// handler to be what would receive a click.
|
||||
var newPressed = ExecuteEvents.ExecuteHierarchy(currentOverGo, pointerEvent, ExecuteEvents.pointerDownHandler);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// PointerUp notification
|
||||
if(data.ReleasedThisFrame()) {
|
||||
// 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;
|
||||
|
||||
// redo pointer enter / exit to refresh state
|
||||
// so that if we moused over somethign 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user