Skip to content

Commit

Permalink
Added new Input System support (requires manual modifications, see do…
Browse files Browse the repository at this point in the history
…cumentation)
  • Loading branch information
yasirkula committed Apr 12, 2021
1 parent f42adcb commit b104118
Show file tree
Hide file tree
Showing 13 changed files with 216 additions and 27 deletions.
8 changes: 8 additions & 0 deletions .github/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ You can also connect the hierarchy to the inspector so that whenever an object r

Note that these connections are *one-directional*, meaning that assigning the inspector to the hierarchy will not automatically assign the hierarchy to the inspector or vice versa. Also note that the inspector and the hierarchy are **not** singletons and therefore, you can have several instances of them in your scene at a time with different configurations.

### NEW INPUT SYSTEM SUPPORT

This plugin supports Unity's new Input System but it requires some manual modifications (if both the legacy and the new input systems are active at the same time, no changes are needed):

- the plugin mustn't be installed as a package, i.e. it must reside inside the *Assets* folder and not the *Packages* folder (it can reside inside a subfolder of Assets like *Assets/Plugins*)
- if Unity 2019.2.5 or earlier is used, add `ENABLE_INPUT_SYSTEM` compiler directive to **Player Settings/Scripting Define Symbols** (these symbols are platform specific, so if you change the active platform later, you'll have to add the compiler directive again)
- add `Unity.InputSystem` assembly to **RuntimeInspector.Runtime** Assembly Definition File's *Assembly Definition References* list

## E. FEATURES

- The hierarchy costs **1 SetPass call** and **~5 batches** (assuming that **Sprite Packing** is enabled in *Editor Settings*)
Expand Down
15 changes: 12 additions & 3 deletions Plugins/RuntimeInspector/README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
Online documentation available at: https://github.com/yasirkula/UnityRuntimeInspector
E-mail: yasirkula@gmail.com

1. ABOUT
### ABOUT
This asset is a simple yet powerful runtime Inspector and Hierarchy solution for Unity 3D that should work on pretty much any platform that Unity supports, including mobile platforms.

2. HOW TO

### HOW TO
Please see the online documentation for an in-depth documentation of the Scripting API: https://github.com/yasirkula/UnityRuntimeInspector

- To use the hierarchy in your scene, drag&drop the RuntimeHierarchy prefab to your canvas
Expand All @@ -16,4 +17,12 @@ You can connect the inspector to the hierarchy so that whenever the selection in

You can also connect the hierarchy to the inspector so that whenever an object reference in the inspector is highlighted, the selection in hierarchy is updated. To do this, assign the hierarchy to the Connected Hierarchy property of the inspector.

Note that these connections are one-directional, meaning that assigning the inspector to the hierarchy will not automatically assign the hierarchy to the inspector or vice versa. Also note that the inspector and the hierarchy are not singletons and therefore, you can have several instances of them in your scene at a time with different configurations.
Note that these connections are one-directional, meaning that assigning the inspector to the hierarchy will not automatically assign the hierarchy to the inspector or vice versa. Also note that the inspector and the hierarchy are not singletons and therefore, you can have several instances of them in your scene at a time with different configurations.


### NEW INPUT SYSTEM SUPPORT
This plugin supports Unity's new Input System but it requires some manual modifications (if both the legacy and the new input systems are active at the same time, no changes are needed):

- the plugin mustn't be installed as a package, i.e. it must reside inside the Assets folder and not the Packages folder (it can reside inside a subfolder of Assets like Assets/Plugins)
- if Unity 2019.2.5 or earlier is used, add ENABLE_INPUT_SYSTEM compiler directive to "Player Settings/Scripting Define Symbols" (these symbols are platform specific, so if you change the active platform later, you'll have to add the compiler directive again)
- add "Unity.InputSystem" assembly to "RuntimeInspector.Runtime" Assembly Definition File's "Assembly Definition References" list
17 changes: 17 additions & 0 deletions Plugins/RuntimeInspector/Scripts/RuntimeHierarchy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,11 @@ protected override void Awake()
ShowHorizontalScrollbar = !m_showHorizontalScrollbar;

RuntimeInspectorUtils.IgnoredTransformsInHierarchy.Add( drawArea );

#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
// On new Input System, scroll sensitivity is much higher than legacy Input system
scrollView.scrollSensitivity *= 0.25f;
#endif
}

private void Start()
Expand Down Expand Up @@ -708,6 +713,18 @@ public void OnDrawerPointerEvent( HierarchyField drawer, PointerEventData eventD
{
currentlyPressedDrawer = null;
pressedDrawerActivePointer = null;

#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
// On new Input System, DraggedReferenceItems aren't tracked by the PointerEventDatas that initiated them. However, when a DraggedReferenceItem is
// created by holding a HierarchyField, the PointerEventData's dragged object will be set as the RuntimeHierarchy's ScrollRect. When it happens,
// trying to scroll the RuntimeHierarchy by holding the DraggedReferenceItem at top/bottom edge of the ScrollRect doesn't work because scrollbar's
// value is overwritten by the original PointerEventData. We can prevent this issue by stopping original PointerEventData's drag operation here
if( eventData.dragging && eventData.pointerDrag == scrollView.gameObject && DraggedReferenceItem.InstanceItem )
{
eventData.dragging = false;
eventData.pointerDrag = null;
}
#endif
}
else if( m_createDraggedReferenceOnHold )
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ void IDropHandler.OnDrop( PointerEventData eventData )

void IPointerEnterHandler.OnPointerEnter( PointerEventData eventData )
{
if( !eventData.dragging || !hierarchy.CanReorganizeItems || hierarchy.IsInSearchMode )
if( !hierarchy.CanReorganizeItems || hierarchy.IsInSearchMode )
return;

if( !RuntimeInspectorUtils.GetAssignableObjectFromDraggedReferenceItem( eventData, typeof( Transform ) ) )
Expand Down
14 changes: 14 additions & 0 deletions Plugins/RuntimeInspector/Scripts/RuntimeInspector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
using Pointer = UnityEngine.InputSystem.Pointer;
#endif
using Object = UnityEngine.Object;

namespace RuntimeInspectorNamespace
Expand Down Expand Up @@ -280,6 +283,11 @@ private void Initialize()

RuntimeInspectorUtils.IgnoredTransformsInHierarchy.Add( drawArea );
RuntimeInspectorUtils.IgnoredTransformsInHierarchy.Add( poolParent );

#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
// On new Input System, scroll sensitivity is much higher than legacy Input system
scrollView.scrollSensitivity *= 0.25f;
#endif
}

private void OnDestroy()
Expand Down Expand Up @@ -345,7 +353,13 @@ protected override void Update()
// Check if a pointer has remained static over a drawer for a while; if so, show a tooltip
if( hoveringPointer != null )
{
#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
// PointerEventData.delta isn't set to (0,0) for static pointers in the new Input System, so we use the active Pointer's delta instead
// The default value isn't Vector2.zero but Vector2.one because we don't want to show tooltip if there is no pointer
Vector2 pointerDelta = Pointer.current != null ? Pointer.current.delta.ReadValue() : Vector2.one;
#else
Vector2 pointerDelta = hoveringPointer.delta;
#endif
if( pointerDelta.x != 0f || pointerDelta.y != 0f )
hoveredDrawerTooltipShowTime = time + m_tooltipDelay;
else if( time > hoveredDrawerTooltipShowTime )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ public override void Initialize()
{
base.Initialize();
input.onValueChanged.AddListener( OnValueChanged );

#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
// On new Input System, scroll sensitivity is much higher than legacy Input system
templateRoot.GetComponent<ScrollRect>().scrollSensitivity *= 0.25f;
#endif
}

public override bool SupportsType( Type type )
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
using UnityEngine;
using UnityEngine.EventSystems;
#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
using UnityEngine.InputSystem;
#endif

namespace RuntimeInspectorNamespace
{
Expand All @@ -8,8 +11,31 @@ public class DraggedReferenceItem : PopupBase, IDragHandler, IEndDragHandler
private Object m_reference;
public Object Reference { get { return m_reference; } }

#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
// In new Input System, it is just not possible to change a PointerEventData's pointerDrag and dragging variables inside Update/LateUpdate,
// EventSystemUIInputModule will reverse these changes immediately. So we'll allow only a single DraggedReferenceItem
// with the new Input System and track its PointerEventData manually using Pointer.current
internal static DraggedReferenceItem InstanceItem { get; private set; }

private readonly System.Collections.Generic.List<RaycastResult> hoveredUIElements = new System.Collections.Generic.List<RaycastResult>( 4 );
#endif

public void SetContent( Object reference, PointerEventData draggingPointer )
{
#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
if( InstanceItem )
InstanceItem.DestroySelf();

InstanceItem = this;

draggingPointer = new PointerEventData( EventSystem.current )
{
pressPosition = draggingPointer.pressPosition,
position = draggingPointer.position,
delta = draggingPointer.delta
};
#endif

m_reference = reference;
label.text = reference.GetNameWithType();

Expand All @@ -19,8 +45,46 @@ public void SetContent( Object reference, PointerEventData draggingPointer )
SetPointer( draggingPointer );
}

#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
private void LateUpdate()
{
if( Pointer.current == null || !Pointer.current.press.isPressed )
{
// We must execute OnDrop manually
if( EventSystem.current )
{
hoveredUIElements.Clear();
EventSystem.current.RaycastAll( pointer, hoveredUIElements );

int i = 0;
while( i < hoveredUIElements.Count && !ExecuteEvents.ExecuteHierarchy( hoveredUIElements[i].gameObject, pointer, ExecuteEvents.dropHandler ) )
i++;
}

OnEndDrag( pointer );
}
else
{
Vector2 pointerPos = Pointer.current.position.ReadValue();
Vector2 pointerDelta = pointerPos - pointer.position;
if( pointerDelta.x != 0f || pointerDelta.y != 0f )
{
pointer.position = pointerPos;
pointer.delta = pointerDelta;

OnDrag( pointer );
}
}
}
#endif

protected override void DestroySelf()
{
#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
if( InstanceItem == this )
InstanceItem = null;
#endif

RuntimeInspectorUtils.PoolDraggedReferenceItem( this );
}

Expand All @@ -34,7 +98,7 @@ public void OnDrag( PointerEventData eventData )

public void OnEndDrag( PointerEventData eventData )
{
RuntimeInspectorUtils.PoolDraggedReferenceItem( this );
DestroySelf();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
using UnityEngine.InputSystem;
#endif

namespace RuntimeInspectorNamespace
{
Expand Down Expand Up @@ -37,6 +40,10 @@ public class DraggedReferenceSourceCamera : MonoBehaviour
private DraggedReferenceItem draggedReference;
private PointerEventData draggingPointer;

#if !ENABLE_INPUT_SYSTEM || ENABLE_LEGACY_INPUT_MANAGER
private readonly List<RaycastResult> hoveredUIElements = new List<RaycastResult>( 4 );
#endif

public RaycastHitProcesserDelegate ProcessRaycastHit;

private void Awake()
Expand All @@ -46,83 +53,115 @@ private void Awake()

private void Update()
{
#if !ENABLE_INPUT_SYSTEM || ENABLE_LEGACY_INPUT_MANAGER
// On new Input System, DraggedReferenceItem's PointerEventData is tracked by DraggedReferenceItem itself, not this component
if( draggingPointer != null )
{
if( !draggedReference || !draggedReference.gameObject.activeSelf )
draggingPointer = null;
else if( Input.GetMouseButtonUp( 0 ) )
else if( IsPointerHeld() )
{
draggingPointer.position = GetPointerPosition();
ExecuteEvents.Execute( draggedReference.gameObject, draggingPointer, ExecuteEvents.dragHandler );
}
else
{
ExecuteEvents.Execute( draggedReference.gameObject, draggingPointer, ExecuteEvents.endDragHandler );
if( EventSystem.current != null )
{
List<RaycastResult> hoveredUIElements = new List<RaycastResult>();
hoveredUIElements.Clear();
EventSystem.current.RaycastAll( draggingPointer, hoveredUIElements );

int i = 0;
while( i < hoveredUIElements.Count && ExecuteEvents.ExecuteHierarchy( hoveredUIElements[i].gameObject, draggingPointer, ExecuteEvents.dropHandler ) == null )
while( i < hoveredUIElements.Count && !ExecuteEvents.ExecuteHierarchy( hoveredUIElements[i].gameObject, draggingPointer, ExecuteEvents.dropHandler ) )
i++;
}

draggingPointer = null;
}
else
{
draggingPointer.position = Input.mousePosition;
ExecuteEvents.Execute( draggedReference.gameObject, draggingPointer, ExecuteEvents.dragHandler );
}
}
else
#endif
{
if( !pointerDown )
{
if( Input.GetMouseButtonDown( 0 ) && EventSystem.current && !EventSystem.current.IsPointerOverGameObject() )
if( IsPointerDown() && EventSystem.current && !EventSystem.current.IsPointerOverGameObject() )
{
RaycastHit hit;
if( Physics.Raycast( _camera.ScreenPointToRay( Input.mousePosition ), out hit, raycastRange, interactableObjectsMask ) )
if( Physics.Raycast( _camera.ScreenPointToRay( GetPointerPosition() ), out hit, raycastRange, interactableObjectsMask ) )
{
hitObject = ( ProcessRaycastHit != null ) ? ProcessRaycastHit( hit ) : hit.collider.gameObject;
if( hitObject )
{
pointerDown = true;
pointerDownTime = Time.realtimeSinceStartup;
pointerDownPos = Input.mousePosition;
pointerDownPos = GetPointerPosition();
}
}
}
}
else
{
if( Input.GetMouseButton( 0 ) )
if( IsPointerHeld() )
{
if( ( (Vector2) Input.mousePosition - pointerDownPos ).sqrMagnitude >= 100f )
if( ( GetPointerPosition() - pointerDownPos ).sqrMagnitude >= 100f )
pointerDown = false;
else if( Time.realtimeSinceStartup - pointerDownTime >= holdTime )
{
pointerDown = false;

if( hitObject && EventSystem.current != null )
if( hitObject && EventSystem.current )
{
draggingPointer = new PointerEventData( EventSystem.current )
{
#if !ENABLE_INPUT_SYSTEM || ENABLE_LEGACY_INPUT_MANAGER
pointerId = Input.touchCount > 0 ? Input.GetTouch( 0 ).fingerId : -1,
pressPosition = Input.mousePosition,
position = Input.mousePosition,
#endif
pressPosition = GetPointerPosition(),
position = GetPointerPosition(),
button = PointerEventData.InputButton.Left
};

draggedReference = RuntimeInspectorUtils.CreateDraggedReferenceItem( hitObject, draggingPointer, draggedReferenceSkin, draggedReferenceCanvas );
if( draggedReference == null )
if( !draggedReference )
{
pointerDown = false;
draggingPointer = null;
}
}
}
}
else if( Input.GetMouseButtonUp( 0 ) )
else
pointerDown = false;
}
}
}

private bool IsPointerDown()
{
#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
return Pointer.current != null && Pointer.current.press.wasPressedThisFrame;
#else
return Input.GetMouseButtonDown( 0 );
#endif
}

private bool IsPointerHeld()
{
#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
return Pointer.current != null && Pointer.current.press.isPressed;
#else
return Input.GetMouseButton( 0 );
#endif
}

private Vector2 GetPointerPosition()
{
#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
return Pointer.current != null ? Pointer.current.position.ReadValue() : Vector2.zero;
#else
return Input.mousePosition;
#endif
}
}
}
Loading

0 comments on commit b104118

Please sign in to comment.