添加debug工具
This commit is contained in:
1683
Assets/Plugins/RuntimeInspector/Scripts/RuntimeHierarchy.cs
Normal file
1683
Assets/Plugins/RuntimeInspector/Scripts/RuntimeHierarchy.cs
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6000098be4011544882ebd2697b8d610
|
||||
timeCreated: 1506863030
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0c7aba0e67a239e48b45cf32c43da5df
|
||||
folderAsset: yes
|
||||
timeCreated: 1506880262
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eef0ffa98a129034fbcf9b8ddac213f6
|
||||
folderAsset: yes
|
||||
timeCreated: 1510168101
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,464 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class HierarchyDragDropListener : MonoBehaviour, IDropHandler, IPointerEnterHandler, IPointerExitHandler
|
||||
{
|
||||
private const float POINTER_VALIDATE_INTERVAL = 5f;
|
||||
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
private float siblingIndexModificationArea = 5f;
|
||||
|
||||
[SerializeField]
|
||||
private float scrollableArea = 75f;
|
||||
private float _1OverScrollableArea;
|
||||
|
||||
[SerializeField]
|
||||
private float scrollSpeed = 75f;
|
||||
|
||||
[Header( "Internal Variables" )]
|
||||
[SerializeField]
|
||||
private RuntimeHierarchy hierarchy;
|
||||
|
||||
[SerializeField]
|
||||
private RectTransform content;
|
||||
|
||||
[SerializeField]
|
||||
private Image dragDropTargetVisualization;
|
||||
#pragma warning restore 0649
|
||||
|
||||
private Canvas canvas;
|
||||
|
||||
private RectTransform rectTransform;
|
||||
private float height;
|
||||
|
||||
private PointerEventData pointer;
|
||||
private Camera worldCamera;
|
||||
|
||||
private float pointerLastYPos;
|
||||
private float nextPointerValidation;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
rectTransform = (RectTransform) transform;
|
||||
canvas = hierarchy.GetComponentInParent<Canvas>();
|
||||
_1OverScrollableArea = 1f / scrollableArea;
|
||||
}
|
||||
|
||||
private void OnRectTransformDimensionsChange()
|
||||
{
|
||||
height = 0f;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if( pointer == null )
|
||||
return;
|
||||
|
||||
nextPointerValidation -= Time.unscaledDeltaTime;
|
||||
if( nextPointerValidation <= 0f )
|
||||
{
|
||||
nextPointerValidation = POINTER_VALIDATE_INTERVAL;
|
||||
|
||||
if( !pointer.IsPointerValid() )
|
||||
{
|
||||
pointer = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Vector2 position;
|
||||
if( RectTransformUtility.ScreenPointToLocalPointInRectangle( rectTransform, pointer.position, worldCamera, out position ) && position.y != pointerLastYPos )
|
||||
{
|
||||
pointerLastYPos = -position.y;
|
||||
|
||||
if( height <= 0f )
|
||||
height = rectTransform.rect.height;
|
||||
|
||||
// Scroll the hierarchy when hovering near top or bottom edges
|
||||
float scrollAmount = 0f;
|
||||
float viewportYPos = pointerLastYPos;
|
||||
if( pointerLastYPos < scrollableArea )
|
||||
scrollAmount = ( scrollableArea - pointerLastYPos ) * _1OverScrollableArea;
|
||||
else if( pointerLastYPos > height - scrollableArea )
|
||||
scrollAmount = ( height - scrollableArea - viewportYPos ) * _1OverScrollableArea;
|
||||
|
||||
float contentYPos = pointerLastYPos + content.anchoredPosition.y;
|
||||
if( contentYPos < 0f )
|
||||
{
|
||||
if( dragDropTargetVisualization.gameObject.activeSelf )
|
||||
dragDropTargetVisualization.gameObject.SetActive( false );
|
||||
|
||||
hierarchy.AutoScrollSpeed = 0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( contentYPos < hierarchy.ItemCount * hierarchy.Skin.LineHeight )
|
||||
{
|
||||
// Show a visual feedback of where the dragged object would be dropped to
|
||||
if( !dragDropTargetVisualization.gameObject.activeSelf )
|
||||
{
|
||||
dragDropTargetVisualization.rectTransform.SetAsLastSibling();
|
||||
dragDropTargetVisualization.gameObject.SetActive( true );
|
||||
}
|
||||
|
||||
float relativePosition = contentYPos % hierarchy.Skin.LineHeight;
|
||||
float absolutePosition = -contentYPos + relativePosition;
|
||||
if( relativePosition < siblingIndexModificationArea )
|
||||
{
|
||||
// Dragged object will be dropped above the target
|
||||
dragDropTargetVisualization.rectTransform.anchoredPosition = new Vector2( 0f, absolutePosition + 2f );
|
||||
dragDropTargetVisualization.rectTransform.sizeDelta = new Vector2( 20f, 4f ); // 20f: The visualization extends beyond scrollbar
|
||||
}
|
||||
else if( relativePosition > hierarchy.Skin.LineHeight - siblingIndexModificationArea )
|
||||
{
|
||||
// Dragged object will be dropped below the target
|
||||
dragDropTargetVisualization.rectTransform.anchoredPosition = new Vector2( 0f, absolutePosition - hierarchy.Skin.LineHeight + 2f );
|
||||
dragDropTargetVisualization.rectTransform.sizeDelta = new Vector2( 20f, 4f );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Dragged object will be dropped onto the target
|
||||
dragDropTargetVisualization.rectTransform.anchoredPosition = new Vector2( 0f, absolutePosition );
|
||||
dragDropTargetVisualization.rectTransform.sizeDelta = new Vector2( 20f, hierarchy.Skin.LineHeight );
|
||||
}
|
||||
}
|
||||
else if( dragDropTargetVisualization.gameObject.activeSelf )
|
||||
dragDropTargetVisualization.gameObject.SetActive( false );
|
||||
|
||||
hierarchy.AutoScrollSpeed = scrollAmount * scrollSpeed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IDropHandler.OnDrop( PointerEventData eventData )
|
||||
{
|
||||
( (IPointerExitHandler) this ).OnPointerExit( eventData );
|
||||
|
||||
if( !hierarchy.CanReorganizeItems || hierarchy.IsInSearchMode )
|
||||
return;
|
||||
|
||||
Transform[] droppedTransforms = RuntimeInspectorUtils.GetAssignableObjectsFromDraggedReferenceItem<Transform>( eventData );
|
||||
if( droppedTransforms == null || droppedTransforms.Length == 0 )
|
||||
return;
|
||||
|
||||
// Sorting the selection is necessary to preserve the sibling index order of the dragged Transforms
|
||||
if( droppedTransforms.Length > 1 )
|
||||
System.Array.Sort( droppedTransforms, ( transform1, transform2 ) => CompareHierarchySiblingIndices( transform1, transform2 ) );
|
||||
|
||||
bool shouldFocusObjectInHierarchy = false;
|
||||
|
||||
float contentYPos = pointerLastYPos + content.anchoredPosition.y;
|
||||
int dataIndex = (int) contentYPos / hierarchy.Skin.LineHeight;
|
||||
HierarchyData target = hierarchy.GetDataAt( dataIndex );
|
||||
if( target == null )
|
||||
{
|
||||
// Dropped Transform(s) onto the blank space at the bottom of the Hierarchy
|
||||
for( int i = 0; i < droppedTransforms.Length; i++ )
|
||||
{
|
||||
if( droppedTransforms[i].parent != null )
|
||||
{
|
||||
droppedTransforms[i].SetParent( null, true );
|
||||
shouldFocusObjectInHierarchy = true;
|
||||
}
|
||||
}
|
||||
|
||||
if( !shouldFocusObjectInHierarchy )
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
int insertDirection;
|
||||
float relativePosition = contentYPos % hierarchy.Skin.LineHeight;
|
||||
if( relativePosition < siblingIndexModificationArea )
|
||||
insertDirection = -1;
|
||||
else if( relativePosition > hierarchy.Skin.LineHeight - siblingIndexModificationArea )
|
||||
insertDirection = 1;
|
||||
else
|
||||
insertDirection = 0;
|
||||
|
||||
// Inserting above/below a scene or pseudo-scene is a special case
|
||||
if( insertDirection != 0 && !( target is HierarchyDataTransform ) )
|
||||
{
|
||||
if( insertDirection < 0 && dataIndex > 0 )
|
||||
{
|
||||
// In an hierarchy with consecutive items A and B, insert below A instead of inserting above B because it makes calculations easier
|
||||
HierarchyData _target = hierarchy.GetDataAt( dataIndex - 1 );
|
||||
if( _target != null )
|
||||
{
|
||||
target = _target;
|
||||
insertDirection = 1;
|
||||
}
|
||||
}
|
||||
else if( insertDirection > 0 && dataIndex < hierarchy.ItemCount - 1 )
|
||||
{
|
||||
// In an hierarchy with consecutive items A and B where B is a Transform, insert above B instead of inserting below A because it makes calculations easier
|
||||
HierarchyData _target = hierarchy.GetDataAt( dataIndex + 1 );
|
||||
if( _target != null && _target is HierarchyDataTransform )
|
||||
{
|
||||
target = _target;
|
||||
insertDirection = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HierarchyDataRoot newScene = null;
|
||||
Transform newParent = null;
|
||||
int newSiblingIndex = -1;
|
||||
if( !( target is HierarchyDataTransform ) )
|
||||
{
|
||||
// Dropped onto a scene or pseudo-scene
|
||||
newScene = (HierarchyDataRoot) target;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Dropped onto a Transform
|
||||
newParent = ( (HierarchyDataTransform) target ).BoundTransform;
|
||||
if( !newParent )
|
||||
return;
|
||||
|
||||
if( insertDirection != 0 )
|
||||
{
|
||||
if( insertDirection > 0 && target.Height > 1 )
|
||||
{
|
||||
// Dropped below an expanded Transform, make dropped object a child of it
|
||||
newSiblingIndex = 0;
|
||||
}
|
||||
else if( target.Depth == 1 && target.Root is HierarchyDataRootPseudoScene )
|
||||
{
|
||||
// Dropped above or below a root pseudo-scene object, don't actually change the parent
|
||||
if( insertDirection < 0 )
|
||||
newSiblingIndex = ( (HierarchyDataRootPseudoScene) target.Root ).IndexOf( newParent );
|
||||
else
|
||||
newSiblingIndex = ( (HierarchyDataRootPseudoScene) target.Root ).IndexOf( newParent ) + 1;
|
||||
|
||||
newParent = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Dropped above or below a regular Transform, calculate target sibling index
|
||||
if( insertDirection < 0 )
|
||||
newSiblingIndex = newParent.GetSiblingIndex();
|
||||
else
|
||||
newSiblingIndex = newParent.GetSiblingIndex() + 1;
|
||||
|
||||
// To be able to drop the object at that sibling index, object's parent must also be changed
|
||||
newParent = newParent.parent;
|
||||
}
|
||||
}
|
||||
|
||||
if( !newParent )
|
||||
newScene = target.Root;
|
||||
}
|
||||
|
||||
int successfullyDroppedTransformCount = 0;
|
||||
for( int i = 0; i < droppedTransforms.Length; i++ )
|
||||
{
|
||||
bool _shouldFocusObjectInHierarchy, decrementSiblingIndex;
|
||||
if( DropTransformOnto( droppedTransforms[i], target, newScene, newParent, ( newSiblingIndex >= 0 ) ? ( newSiblingIndex + successfullyDroppedTransformCount ) : newSiblingIndex, out decrementSiblingIndex, out _shouldFocusObjectInHierarchy ) )
|
||||
{
|
||||
successfullyDroppedTransformCount++;
|
||||
shouldFocusObjectInHierarchy |= _shouldFocusObjectInHierarchy;
|
||||
|
||||
if( decrementSiblingIndex )
|
||||
newSiblingIndex--;
|
||||
}
|
||||
}
|
||||
|
||||
if( successfullyDroppedTransformCount == 0 )
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't reveal the selection unless it's necessary (i.e. selection is already fully visible)
|
||||
if( shouldFocusObjectInHierarchy )
|
||||
hierarchy.SelectInternal( droppedTransforms, RuntimeHierarchy.SelectOptions.FocusOnSelection | RuntimeHierarchy.SelectOptions.ForceRevealSelection );
|
||||
else
|
||||
hierarchy.Refresh();
|
||||
}
|
||||
|
||||
private bool DropTransformOnto( Transform droppedTransform, HierarchyData target, HierarchyDataRoot newScene, Transform newParent, int newSiblingIndex, out bool decrementSiblingIndex, out bool shouldFocusObjectInHierarchy )
|
||||
{
|
||||
shouldFocusObjectInHierarchy = false;
|
||||
decrementSiblingIndex = false;
|
||||
|
||||
// If we are only changing the sibling index of the dropped Transform and not its parent, then make sure
|
||||
// that the target sibling index won't be affected when the dropped Transform is shifted in the Hierarchy
|
||||
if( droppedTransform.parent == newParent )
|
||||
{
|
||||
if( newParent || ( newScene is HierarchyDataRootScene && ( (HierarchyDataRootScene) newScene ).Scene == droppedTransform.gameObject.scene ) )
|
||||
{
|
||||
if( newSiblingIndex > droppedTransform.GetSiblingIndex() )
|
||||
{
|
||||
newSiblingIndex--;
|
||||
decrementSiblingIndex = true;
|
||||
}
|
||||
}
|
||||
else if( newScene is HierarchyDataRootPseudoScene )
|
||||
{
|
||||
int pseudoSceneSiblingIndex = newScene.IndexOf( droppedTransform );
|
||||
if( pseudoSceneSiblingIndex >= 0 && newSiblingIndex > pseudoSceneSiblingIndex )
|
||||
{
|
||||
newSiblingIndex--;
|
||||
decrementSiblingIndex = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( newParent ) // Drop inside a Transform
|
||||
{
|
||||
if( !hierarchy.CanDropDraggedParentOnChild )
|
||||
{
|
||||
// Avoid setting child object as parent of the parent object
|
||||
if( newParent.IsChildOf( droppedTransform ) )
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Transform curr = newParent;
|
||||
while( curr.parent != null && curr.parent != droppedTransform )
|
||||
curr = curr.parent;
|
||||
|
||||
// First, set the child object's parent as the dropped object's current parent so that
|
||||
// the dropped object can then become a child of the former child object
|
||||
if( curr.parent == droppedTransform )
|
||||
{
|
||||
HierarchyDataRootPseudoScene pseudoScene = target.Root as HierarchyDataRootPseudoScene;
|
||||
int pseudoSceneChildIndex;
|
||||
if( pseudoScene != null && ( pseudoSceneChildIndex = pseudoScene.IndexOf( droppedTransform ) ) >= 0 )
|
||||
{
|
||||
// Dropped object was a root pseudo-scene object, swap the child and parent objects in the pseudo-scene, as well
|
||||
if( hierarchy.CanDropDraggedObjectsToPseudoScenes )
|
||||
{
|
||||
pseudoScene.InsertChild( pseudoSceneChildIndex, curr );
|
||||
pseudoScene.RemoveChild( droppedTransform );
|
||||
}
|
||||
}
|
||||
|
||||
int siblingIndex = droppedTransform.GetSiblingIndex();
|
||||
curr.SetParent( droppedTransform.parent, true );
|
||||
curr.SetSiblingIndex( siblingIndex );
|
||||
|
||||
shouldFocusObjectInHierarchy = true;
|
||||
}
|
||||
}
|
||||
|
||||
droppedTransform.SetParent( newParent, true );
|
||||
}
|
||||
else // Drop at the root of a scene
|
||||
{
|
||||
if( newScene is HierarchyDataRootPseudoScene )
|
||||
{
|
||||
if( !hierarchy.CanDropDraggedObjectsToPseudoScenes )
|
||||
return false;
|
||||
|
||||
// Add object to pseudo-scene
|
||||
if( newSiblingIndex < 0 )
|
||||
( (HierarchyDataRootPseudoScene) newScene ).AddChild( droppedTransform );
|
||||
else
|
||||
{
|
||||
( (HierarchyDataRootPseudoScene) newScene ).InsertChild( newSiblingIndex, droppedTransform );
|
||||
|
||||
// Don't try to change the actual sibling index of the Transform
|
||||
newSiblingIndex = -1;
|
||||
target = newScene;
|
||||
}
|
||||
}
|
||||
else if( newScene is HierarchyDataRootScene )
|
||||
{
|
||||
if( droppedTransform.parent != null )
|
||||
droppedTransform.SetParent( null, true );
|
||||
|
||||
// Change dropped object's scene
|
||||
Scene scene = ( (HierarchyDataRootScene) newScene ).Scene;
|
||||
if( droppedTransform.gameObject.scene != scene )
|
||||
SceneManager.MoveGameObjectToScene( droppedTransform.gameObject, scene );
|
||||
|
||||
if( newSiblingIndex < 0 )
|
||||
{
|
||||
// If object was dropped onto the scene, add it to the bottom of the scene
|
||||
newSiblingIndex = scene.rootCount + 1;
|
||||
shouldFocusObjectInHierarchy = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( newSiblingIndex >= 0 )
|
||||
droppedTransform.SetSiblingIndex( newSiblingIndex );
|
||||
|
||||
shouldFocusObjectInHierarchy |= ( newSiblingIndex < 0 && !target.IsExpanded );
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns -1 if t1 is above t2 in Hierarchy, 1 if t1 is below t2 in Hierarchy and 0 if they are the same object
|
||||
private int CompareHierarchySiblingIndices( Transform t1, Transform t2 )
|
||||
{
|
||||
Transform parent1 = t1.parent;
|
||||
Transform parent2 = t2.parent;
|
||||
|
||||
if( parent1 == parent2 )
|
||||
return t1.GetSiblingIndex() - t2.GetSiblingIndex();
|
||||
|
||||
int deltaHierarchyDepth = 0;
|
||||
for( ; parent1; parent1 = parent1.parent )
|
||||
deltaHierarchyDepth++;
|
||||
for( ; parent2; parent2 = parent2.parent )
|
||||
deltaHierarchyDepth--;
|
||||
|
||||
for( ; deltaHierarchyDepth > 0; deltaHierarchyDepth-- )
|
||||
{
|
||||
t1 = t1.parent;
|
||||
if( t1 == t2 )
|
||||
return 1;
|
||||
}
|
||||
for( ; deltaHierarchyDepth < 0; deltaHierarchyDepth++ )
|
||||
{
|
||||
t2 = t2.parent;
|
||||
if( t1 == t2 )
|
||||
return -1;
|
||||
}
|
||||
|
||||
while( t1.parent != t2.parent )
|
||||
{
|
||||
t1 = t1.parent;
|
||||
t2 = t2.parent;
|
||||
}
|
||||
|
||||
return t1.GetSiblingIndex() - t2.GetSiblingIndex();
|
||||
}
|
||||
|
||||
void IPointerEnterHandler.OnPointerEnter( PointerEventData eventData )
|
||||
{
|
||||
if( !hierarchy.CanReorganizeItems || hierarchy.IsInSearchMode )
|
||||
return;
|
||||
|
||||
if( !RuntimeInspectorUtils.GetAssignableObjectFromDraggedReferenceItem<Transform>( eventData ) )
|
||||
return;
|
||||
|
||||
pointer = eventData;
|
||||
pointerLastYPos = -1f;
|
||||
nextPointerValidation = POINTER_VALIDATE_INTERVAL;
|
||||
|
||||
if( canvas.renderMode == RenderMode.ScreenSpaceOverlay || ( canvas.renderMode == RenderMode.ScreenSpaceCamera && !canvas.worldCamera ) )
|
||||
worldCamera = null;
|
||||
else
|
||||
worldCamera = canvas.worldCamera ? canvas.worldCamera : Camera.main;
|
||||
|
||||
Update();
|
||||
}
|
||||
|
||||
void IPointerExitHandler.OnPointerExit( PointerEventData eventData )
|
||||
{
|
||||
pointer = null;
|
||||
worldCamera = null;
|
||||
|
||||
if( dragDropTargetVisualization.gameObject.activeSelf )
|
||||
dragDropTargetVisualization.gameObject.SetActive( false );
|
||||
|
||||
hierarchy.AutoScrollSpeed = 0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: be531524081657c479afb27aaa9501ac
|
||||
timeCreated: 1525163086
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,152 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class PseudoSceneSourceTransform : MonoBehaviour
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
private RuntimeHierarchy m_hierarchy;
|
||||
public RuntimeHierarchy Hierarchy
|
||||
{
|
||||
get { return m_hierarchy; }
|
||||
set
|
||||
{
|
||||
if( m_hierarchy != value )
|
||||
{
|
||||
RemoveChildrenFromScene();
|
||||
m_hierarchy = value;
|
||||
AddChildrenToScene();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private string m_sceneName;
|
||||
public string SceneName
|
||||
{
|
||||
get { return m_sceneName; }
|
||||
set
|
||||
{
|
||||
if( m_sceneName != value )
|
||||
{
|
||||
RemoveChildrenFromScene();
|
||||
m_sceneName = value;
|
||||
AddChildrenToScene();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private bool m_hideOnDisable = false;
|
||||
public bool HideOnDisable
|
||||
{
|
||||
get { return m_hideOnDisable; }
|
||||
set
|
||||
{
|
||||
if( m_hideOnDisable != value )
|
||||
{
|
||||
m_hideOnDisable = value;
|
||||
if( !isEnabled )
|
||||
{
|
||||
if( value )
|
||||
RemoveChildrenFromScene();
|
||||
else
|
||||
AddChildrenToScene();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore 0649
|
||||
|
||||
private HashSet<Transform> childrenCurrent = new HashSet<Transform>();
|
||||
private HashSet<Transform> childrenNew = new HashSet<Transform>();
|
||||
|
||||
private bool updateChildren = false;
|
||||
private bool isEnabled = true;
|
||||
private bool isQuitting = false;
|
||||
|
||||
private bool ShouldUpdateChildren { get { return ( isEnabled || !m_hideOnDisable ) && Hierarchy && !string.IsNullOrEmpty( m_sceneName ); } }
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
isEnabled = true;
|
||||
updateChildren = true;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
if( isQuitting )
|
||||
return;
|
||||
|
||||
isEnabled = false;
|
||||
|
||||
if( m_hideOnDisable )
|
||||
RemoveChildrenFromScene();
|
||||
}
|
||||
|
||||
private void OnApplicationQuit()
|
||||
{
|
||||
isQuitting = true;
|
||||
}
|
||||
|
||||
private void OnTransformChildrenChanged()
|
||||
{
|
||||
updateChildren = true;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if( updateChildren )
|
||||
{
|
||||
updateChildren = false;
|
||||
|
||||
if( !ShouldUpdateChildren )
|
||||
return;
|
||||
|
||||
for( int i = 0; i < transform.childCount; i++ )
|
||||
{
|
||||
Transform child = transform.GetChild( i );
|
||||
childrenNew.Add( child );
|
||||
|
||||
if( !childrenCurrent.Remove( child ) )
|
||||
Hierarchy.AddToPseudoScene( m_sceneName, child );
|
||||
}
|
||||
|
||||
RemoveChildrenFromScene();
|
||||
|
||||
HashSet<Transform> temp = childrenCurrent;
|
||||
childrenCurrent = childrenNew;
|
||||
childrenNew = temp;
|
||||
}
|
||||
}
|
||||
|
||||
private void AddChildrenToScene()
|
||||
{
|
||||
if( !ShouldUpdateChildren )
|
||||
return;
|
||||
|
||||
for( int i = 0; i < transform.childCount; i++ )
|
||||
{
|
||||
Transform child = transform.GetChild( i );
|
||||
if( childrenCurrent.Add( child ) )
|
||||
Hierarchy.AddToPseudoScene( m_sceneName, child );
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveChildrenFromScene()
|
||||
{
|
||||
if( !Hierarchy || string.IsNullOrEmpty( m_sceneName ) )
|
||||
return;
|
||||
|
||||
foreach( Transform removedChild in childrenCurrent )
|
||||
{
|
||||
if( removedChild )
|
||||
Hierarchy.RemoveFromPseudoScene( m_sceneName, removedChild, true );
|
||||
}
|
||||
|
||||
childrenCurrent.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e1a4ef3d1723234408a97a84690ab8bb
|
||||
timeCreated: 1510168133
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,441 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public abstract class HierarchyData
|
||||
{
|
||||
private static readonly List<HierarchyDataTransform> transformDataPool = new List<HierarchyDataTransform>( 32 );
|
||||
private static readonly List<List<HierarchyDataTransform>> childrenListPool = new List<List<HierarchyDataTransform>>( 32 );
|
||||
|
||||
public abstract string Name { get; }
|
||||
public abstract bool IsActive { get; }
|
||||
public abstract int ChildCount { get; }
|
||||
public abstract Transform BoundTransform { get; }
|
||||
|
||||
protected List<HierarchyDataTransform> children;
|
||||
protected HierarchyData parent;
|
||||
public HierarchyDataRoot Root
|
||||
{
|
||||
get
|
||||
{
|
||||
HierarchyData _parent = this;
|
||||
while( _parent.parent != null )
|
||||
_parent = _parent.parent;
|
||||
|
||||
return (HierarchyDataRoot) _parent;
|
||||
}
|
||||
}
|
||||
|
||||
protected int m_index;
|
||||
public int Index { get { return m_index; } }
|
||||
public int AbsoluteIndex
|
||||
{
|
||||
get
|
||||
{
|
||||
int result = m_index;
|
||||
HierarchyData _parent = parent;
|
||||
while( _parent != null )
|
||||
{
|
||||
result += _parent.m_index + 1;
|
||||
_parent = _parent.parent;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
protected int m_height = 1;
|
||||
public int Height { get { return m_height; } }
|
||||
|
||||
protected int m_depth;
|
||||
public int Depth { get { return m_depth; } }
|
||||
|
||||
public bool CanExpand { get { return ChildCount > 0; } }
|
||||
public bool IsExpanded
|
||||
{
|
||||
get { return children != null; }
|
||||
set
|
||||
{
|
||||
if( IsExpanded == value )
|
||||
return;
|
||||
|
||||
if( value )
|
||||
{
|
||||
if( ChildCount == 0 )
|
||||
return;
|
||||
|
||||
PopChildrenList();
|
||||
}
|
||||
else
|
||||
PoolChildrenList();
|
||||
|
||||
int prevHeight = m_height;
|
||||
Refresh();
|
||||
|
||||
int deltaHeight = m_height - prevHeight;
|
||||
if( deltaHeight != 0 )
|
||||
{
|
||||
if( parent != null )
|
||||
{
|
||||
HierarchyData child = this;
|
||||
HierarchyData _parent = parent;
|
||||
while( _parent != null )
|
||||
{
|
||||
List<HierarchyDataTransform> children = _parent.children;
|
||||
for( int i = children.IndexOf( (HierarchyDataTransform) child ) + 1, childCount = children.Count; i < childCount; i++ )
|
||||
children[i].m_index += deltaHeight;
|
||||
|
||||
_parent.m_height += deltaHeight;
|
||||
|
||||
child = _parent;
|
||||
_parent = _parent.parent;
|
||||
}
|
||||
}
|
||||
|
||||
HierarchyDataRoot root = Root;
|
||||
if( root != null )
|
||||
root.Hierarchy.SetListViewDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool Refresh()
|
||||
{
|
||||
if( m_depth < 0 ) // This object is hidden from Hierarchy
|
||||
return false;
|
||||
|
||||
m_height = 1;
|
||||
bool hasChanged = false;
|
||||
int childCount = ChildCount;
|
||||
|
||||
if( IsExpanded )
|
||||
{
|
||||
if( childCount != children.Count )
|
||||
hasChanged = true;
|
||||
|
||||
//if( childCount == 0 ) // Issue with IsExpanded's Refresh changing iteratedIndex
|
||||
// PoolChildrenList();
|
||||
//else
|
||||
{
|
||||
RuntimeHierarchy hierarchy = null; // Root's RuntimeHierarchy will be fetched only once when it is needed
|
||||
for( int i = 0; i < childCount; i++ )
|
||||
{
|
||||
Transform child = GetChild( i );
|
||||
if( children.Count <= i )
|
||||
{
|
||||
if( hierarchy == null )
|
||||
hierarchy = Root.Hierarchy;
|
||||
|
||||
GenerateChildItem( child, i, hierarchy );
|
||||
}
|
||||
else if( children[i].BoundTransform != child )
|
||||
{
|
||||
int childIndex;
|
||||
for( childIndex = 0; childIndex < children.Count; childIndex++ )
|
||||
{
|
||||
if( children[childIndex].BoundTransform == child )
|
||||
break;
|
||||
}
|
||||
|
||||
if( childIndex == children.Count )
|
||||
{
|
||||
if( hierarchy == null )
|
||||
hierarchy = Root.Hierarchy;
|
||||
|
||||
GenerateChildItem( child, i, hierarchy );
|
||||
}
|
||||
else
|
||||
{
|
||||
HierarchyDataTransform childItem = children[childIndex];
|
||||
children.RemoveAt( childIndex );
|
||||
children.Insert( i, childItem );
|
||||
}
|
||||
|
||||
hasChanged = true;
|
||||
}
|
||||
|
||||
hasChanged |= children[i].Refresh();
|
||||
children[i].m_index = m_height - 1;
|
||||
m_height += children[i].m_height;
|
||||
}
|
||||
|
||||
for( int i = children.Count - 1; i >= childCount; i-- )
|
||||
RemoveChildItem( i );
|
||||
}
|
||||
}
|
||||
|
||||
return hasChanged;
|
||||
}
|
||||
|
||||
public HierarchyData FindDataAtIndex( int index )
|
||||
{
|
||||
int upperBound = children.Count - 1;
|
||||
if( index <= upperBound && children[index].m_index == index )
|
||||
{
|
||||
int middle = index;
|
||||
while( middle < upperBound && index == children[middle + 1].m_index )
|
||||
middle++;
|
||||
|
||||
return children[middle];
|
||||
}
|
||||
|
||||
// Binary search
|
||||
int min = 0;
|
||||
int max = upperBound;
|
||||
while( min <= max )
|
||||
{
|
||||
int middle = ( min + max ) / 2;
|
||||
int childIndex = children[middle].m_index;
|
||||
if( index == childIndex )
|
||||
{
|
||||
// Items hidden from the Hierarchy have same indices with their adjacent items
|
||||
while( middle < upperBound && index == children[middle + 1].m_index )
|
||||
middle++;
|
||||
|
||||
return children[middle];
|
||||
}
|
||||
|
||||
if( index < childIndex )
|
||||
max = middle - 1;
|
||||
else
|
||||
min = middle + 1;
|
||||
}
|
||||
|
||||
if( max < 0 )
|
||||
max = 0;
|
||||
|
||||
while( max < upperBound && index >= children[max + 1].m_index )
|
||||
max++;
|
||||
|
||||
return children[max].FindDataAtIndex( index - 1 - children[max].m_index );
|
||||
}
|
||||
|
||||
public HierarchyDataTransform FindTransform( Transform target, Transform nextInPath = null )
|
||||
{
|
||||
if( m_depth < 0 ) // This object is hidden from Hierarchy
|
||||
return null;
|
||||
|
||||
bool isInitSearch = nextInPath == null;
|
||||
if( isInitSearch )
|
||||
{
|
||||
nextInPath = ( this is HierarchyDataRootSearch ) ? target : target.root;
|
||||
|
||||
// In the current implementation, FindTransform is only called from RuntimeHierarchy.Select which
|
||||
// automatically calls RefreshContent prior to FindTransform
|
||||
//( (HierarchyDataRoot) this ).RefreshContent();
|
||||
}
|
||||
|
||||
int childIndex = IndexOf( nextInPath );
|
||||
if( childIndex < 0 )
|
||||
{
|
||||
if( isInitSearch && this is HierarchyDataRootPseudoScene )
|
||||
{
|
||||
nextInPath = target;
|
||||
childIndex = IndexOf( nextInPath );
|
||||
while( childIndex < 0 && nextInPath != null )
|
||||
{
|
||||
nextInPath = nextInPath.parent;
|
||||
childIndex = IndexOf( nextInPath );
|
||||
}
|
||||
|
||||
if( childIndex < 0 )
|
||||
return null;
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
if( !CanExpand )
|
||||
return null;
|
||||
|
||||
bool wasExpanded = IsExpanded;
|
||||
if( !wasExpanded )
|
||||
IsExpanded = true;
|
||||
|
||||
HierarchyDataTransform childItem = children[childIndex];
|
||||
if( childItem.BoundTransform == target )
|
||||
return childItem;
|
||||
|
||||
HierarchyDataTransform result = null;
|
||||
if( childItem.BoundTransform == nextInPath )
|
||||
{
|
||||
Transform next = target;
|
||||
Transform parent = next.parent;
|
||||
while( parent != null && parent != nextInPath )
|
||||
{
|
||||
next = parent;
|
||||
parent = next.parent;
|
||||
}
|
||||
|
||||
if( parent != null )
|
||||
result = childItem.FindTransform( target, next );
|
||||
}
|
||||
|
||||
if( result != null && result.m_depth < 0 )
|
||||
result = null;
|
||||
|
||||
if( result == null && !wasExpanded )
|
||||
IsExpanded = false;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public virtual HierarchyDataTransform FindTransformInVisibleChildren( Transform target, int targetDepth = -1 )
|
||||
{
|
||||
for( int i = 0; i < children.Count; i++ )
|
||||
{
|
||||
HierarchyDataTransform child = children[i];
|
||||
if( child.m_depth < 0 )
|
||||
continue;
|
||||
|
||||
if( ReferenceEquals( child.BoundTransform, target ) )
|
||||
{
|
||||
if( targetDepth <= 0 || child.m_depth == targetDepth )
|
||||
return child;
|
||||
}
|
||||
else if( ( targetDepth <= 0 || child.m_depth < targetDepth ) && child.IsExpanded && child.BoundTransform && target.IsChildOf( child.BoundTransform ) )
|
||||
{
|
||||
child = child.FindTransformInVisibleChildren( target, targetDepth );
|
||||
if( child != null )
|
||||
return child;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract Transform GetChild( int index );
|
||||
|
||||
public int IndexOf( Transform transform )
|
||||
{
|
||||
for( int i = ChildCount - 1; i >= 0; i-- )
|
||||
{
|
||||
if( ReferenceEquals( GetChild( i ), transform ) )
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void GetSiblingIndexTraversalList( List<int> traversalList )
|
||||
{
|
||||
traversalList.Clear();
|
||||
|
||||
HierarchyData current = this;
|
||||
while( current.parent != null )
|
||||
{
|
||||
traversalList.Add( current.parent.children.IndexOf( (HierarchyDataTransform) current ) );
|
||||
current = current.parent;
|
||||
}
|
||||
}
|
||||
|
||||
public HierarchyData TraverseSiblingIndexList( List<int> traversalList )
|
||||
{
|
||||
HierarchyData current = this;
|
||||
for( int i = traversalList.Count - 1; i >= 0; i-- )
|
||||
{
|
||||
int siblingIndex = traversalList[i];
|
||||
if( current.children == null || siblingIndex >= current.children.Count )
|
||||
return null;
|
||||
|
||||
current = current.children[siblingIndex];
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
private void GenerateChildItem( Transform child, int index, RuntimeHierarchy hierarchy )
|
||||
{
|
||||
bool isChildVisible = !RuntimeInspectorUtils.IgnoredTransformsInHierarchy.Contains( child );
|
||||
if( isChildVisible && hierarchy.GameObjectFilter != null )
|
||||
isChildVisible = hierarchy.GameObjectFilter( child );
|
||||
|
||||
HierarchyDataTransform childData;
|
||||
int poolIndex = transformDataPool.Count - 1;
|
||||
if( poolIndex >= 0 )
|
||||
{
|
||||
childData = transformDataPool[poolIndex];
|
||||
transformDataPool.RemoveAt( poolIndex );
|
||||
}
|
||||
else
|
||||
childData = new HierarchyDataTransform();
|
||||
|
||||
childData.Initialize( child, this is HierarchyDataRootSearch );
|
||||
childData.parent = this;
|
||||
if( isChildVisible )
|
||||
{
|
||||
childData.m_depth = m_depth + 1;
|
||||
childData.m_height = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
childData.m_depth = -1;
|
||||
childData.m_height = 0;
|
||||
}
|
||||
|
||||
children.Insert( index, childData );
|
||||
}
|
||||
|
||||
private void RemoveChildItem( int index )
|
||||
{
|
||||
children[index].PoolData();
|
||||
transformDataPool.Add( children[index] );
|
||||
children.RemoveAt( index );
|
||||
}
|
||||
|
||||
protected void PoolChildrenList()
|
||||
{
|
||||
if( children != null )
|
||||
{
|
||||
for( int i = children.Count - 1; i >= 0; i-- )
|
||||
{
|
||||
children[i].PoolData();
|
||||
transformDataPool.Add( children[i] );
|
||||
}
|
||||
|
||||
children.Clear();
|
||||
childrenListPool.Add( children );
|
||||
children = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected void PopChildrenList()
|
||||
{
|
||||
int desiredSize = ChildCount;
|
||||
int bestFittingListIndex = -1;
|
||||
int bestFittingListDeltaSize = int.MaxValue;
|
||||
for( int i = childrenListPool.Count - 1; i >= 0; i-- )
|
||||
{
|
||||
int deltaSize = childrenListPool[i].Capacity - desiredSize;
|
||||
if( deltaSize < 0 )
|
||||
deltaSize = -deltaSize;
|
||||
|
||||
if( deltaSize < bestFittingListDeltaSize )
|
||||
{
|
||||
bestFittingListDeltaSize = deltaSize;
|
||||
bestFittingListIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
if( bestFittingListIndex >= 0 )
|
||||
{
|
||||
children = childrenListPool[bestFittingListIndex];
|
||||
childrenListPool.RemoveAt( bestFittingListIndex );
|
||||
}
|
||||
else
|
||||
children = new List<HierarchyDataTransform>( ChildCount );
|
||||
}
|
||||
|
||||
public static void ClearPool()
|
||||
{
|
||||
childrenListPool.Clear();
|
||||
transformDataPool.Clear();
|
||||
|
||||
if( childrenListPool.Capacity > 128 )
|
||||
childrenListPool.Capacity = 128;
|
||||
if( transformDataPool.Capacity > 128 )
|
||||
transformDataPool.Capacity = 128;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 328d45f703d254c4aa61dfe88bdc5977
|
||||
timeCreated: 1582458939
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,52 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public abstract class HierarchyDataRoot : HierarchyData
|
||||
{
|
||||
public override Transform BoundTransform { get { return null; } }
|
||||
public override bool IsActive { get { return true; } }
|
||||
|
||||
public RuntimeHierarchy Hierarchy { get; private set; }
|
||||
|
||||
protected HierarchyDataRoot( RuntimeHierarchy hierarchy )
|
||||
{
|
||||
Hierarchy = hierarchy;
|
||||
|
||||
// Root data are expanded by default
|
||||
PopChildrenList();
|
||||
}
|
||||
|
||||
public abstract Transform GetNearestRootOf( Transform target );
|
||||
public abstract void RefreshContent();
|
||||
|
||||
public override bool Refresh()
|
||||
{
|
||||
RefreshContent();
|
||||
return base.Refresh();
|
||||
}
|
||||
|
||||
public override HierarchyDataTransform FindTransformInVisibleChildren( Transform target, int targetDepth = -1 )
|
||||
{
|
||||
return ( m_depth >= 0 && IsExpanded ) ? base.FindTransformInVisibleChildren( target, targetDepth ) : null;
|
||||
}
|
||||
|
||||
public void ResetCachedNames()
|
||||
{
|
||||
if( children != null )
|
||||
{
|
||||
for( int i = children.Count - 1; i >= 0; i-- )
|
||||
children[i].ResetCachedName();
|
||||
}
|
||||
}
|
||||
|
||||
public void RefreshNameOf( Transform target )
|
||||
{
|
||||
if( children != null )
|
||||
{
|
||||
for( int i = children.Count - 1; i >= 0; i-- )
|
||||
children[i].RefreshNameOf( target );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: faafaff4766ca384399d116b1be6de4f
|
||||
timeCreated: 1508420714
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,73 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class HierarchyDataRootPseudoScene : HierarchyDataRoot
|
||||
{
|
||||
private readonly string name;
|
||||
public override string Name { get { return name; } }
|
||||
public override int ChildCount { get { return rootObjects.Count; } }
|
||||
|
||||
private readonly List<Transform> rootObjects = new List<Transform>();
|
||||
|
||||
public HierarchyDataRootPseudoScene( RuntimeHierarchy hierarchy, string name ) : base( hierarchy )
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void AddChild( Transform child )
|
||||
{
|
||||
if( !rootObjects.Contains( child ) )
|
||||
rootObjects.Add( child );
|
||||
}
|
||||
|
||||
public void InsertChild( int index, Transform child )
|
||||
{
|
||||
index = Mathf.Clamp( index, 0, rootObjects.Count );
|
||||
rootObjects.Insert( index, child );
|
||||
|
||||
// If the object was already in the list, remove the old copy from the list
|
||||
for( int i = rootObjects.Count - 1; i >= 0; i-- )
|
||||
{
|
||||
if( i != index && rootObjects[i] == child )
|
||||
{
|
||||
rootObjects.RemoveAt( i );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveChild( Transform child )
|
||||
{
|
||||
rootObjects.Remove( child );
|
||||
}
|
||||
|
||||
public override void RefreshContent()
|
||||
{
|
||||
for( int i = rootObjects.Count - 1; i >= 0; i-- )
|
||||
{
|
||||
if( !rootObjects[i] )
|
||||
rootObjects.RemoveAt( i );
|
||||
}
|
||||
}
|
||||
|
||||
public override Transform GetChild( int index )
|
||||
{
|
||||
return rootObjects[index];
|
||||
}
|
||||
|
||||
public override Transform GetNearestRootOf( Transform target )
|
||||
{
|
||||
Transform result = null;
|
||||
for( int i = rootObjects.Count - 1; i >= 0; i-- )
|
||||
{
|
||||
Transform rootObject = rootObjects[i];
|
||||
if( rootObject && target.IsChildOf( rootObject ) && ( !result || rootObject.IsChildOf( result ) ) )
|
||||
result = rootObject;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 71d649a158c3ff449a319b49ee730ccb
|
||||
timeCreated: 1508420714
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,39 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class HierarchyDataRootScene : HierarchyDataRoot
|
||||
{
|
||||
public override string Name { get { return Scene.name; } }
|
||||
public override int ChildCount { get { return rootObjects.Count; } }
|
||||
|
||||
public Scene Scene { get; private set; }
|
||||
|
||||
private readonly List<GameObject> rootObjects = new List<GameObject>();
|
||||
|
||||
public HierarchyDataRootScene( RuntimeHierarchy hierarchy, Scene target ) : base( hierarchy )
|
||||
{
|
||||
Scene = target;
|
||||
}
|
||||
|
||||
public override void RefreshContent()
|
||||
{
|
||||
rootObjects.Clear();
|
||||
|
||||
if( Scene.isLoaded )
|
||||
Scene.GetRootGameObjects( rootObjects );
|
||||
}
|
||||
|
||||
public override Transform GetChild( int index )
|
||||
{
|
||||
return rootObjects[index].transform;
|
||||
}
|
||||
|
||||
public override Transform GetNearestRootOf( Transform target )
|
||||
{
|
||||
return ( target.gameObject.scene == Scene ) ? target.root : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: efbc9d53cb584f74a869dbf48ff4c7bd
|
||||
timeCreated: 1508420714
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,101 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class HierarchyDataRootSearch : HierarchyDataRoot
|
||||
{
|
||||
public override string Name { get { return reference.Name; } }
|
||||
public override int ChildCount { get { return searchResult.Count; } }
|
||||
|
||||
private readonly List<Transform> searchResult = new List<Transform>();
|
||||
|
||||
private readonly HierarchyDataRoot reference;
|
||||
|
||||
private string searchTerm;
|
||||
|
||||
public HierarchyDataRootSearch( RuntimeHierarchy hierarchy, HierarchyDataRoot reference ) : base( hierarchy )
|
||||
{
|
||||
this.reference = reference;
|
||||
}
|
||||
|
||||
public override void RefreshContent()
|
||||
{
|
||||
if( !Hierarchy.IsInSearchMode )
|
||||
return;
|
||||
|
||||
searchResult.Clear();
|
||||
searchTerm = Hierarchy.SearchTerm;
|
||||
|
||||
int childCount = reference.ChildCount;
|
||||
for( int i = 0; i < childCount; i++ )
|
||||
{
|
||||
Transform obj = reference.GetChild( i );
|
||||
if( !obj )
|
||||
continue;
|
||||
|
||||
if( RuntimeInspectorUtils.IgnoredTransformsInHierarchy.Contains( obj.transform ) )
|
||||
continue;
|
||||
|
||||
if( obj.name.IndexOf( searchTerm, System.StringComparison.OrdinalIgnoreCase ) >= 0 )
|
||||
searchResult.Add( obj );
|
||||
|
||||
SearchTransformRecursively( obj.transform );
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Refresh()
|
||||
{
|
||||
m_depth = 0;
|
||||
bool result = base.Refresh();
|
||||
|
||||
// Scenes with no matching search results should be hidden in search mode
|
||||
if( searchResult.Count == 0 )
|
||||
{
|
||||
m_height = 0;
|
||||
m_depth = -1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override HierarchyDataTransform FindTransformInVisibleChildren( Transform target, int targetDepth = -1 )
|
||||
{
|
||||
if( m_depth < 0 || targetDepth > 1 || !IsExpanded )
|
||||
return null;
|
||||
|
||||
for( int i = children.Count - 1; i >= 0; i-- )
|
||||
{
|
||||
if( ReferenceEquals( children[i].BoundTransform, target ) )
|
||||
return children[i];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void SearchTransformRecursively( Transform obj )
|
||||
{
|
||||
for( int i = 0; i < obj.childCount; i++ )
|
||||
{
|
||||
Transform child = obj.GetChild( i );
|
||||
if( RuntimeInspectorUtils.IgnoredTransformsInHierarchy.Contains( child ) )
|
||||
continue;
|
||||
|
||||
if( child.name.IndexOf( searchTerm, System.StringComparison.OrdinalIgnoreCase ) >= 0 )
|
||||
searchResult.Add( child );
|
||||
|
||||
SearchTransformRecursively( child );
|
||||
}
|
||||
}
|
||||
|
||||
public override Transform GetChild( int index )
|
||||
{
|
||||
return searchResult[index];
|
||||
}
|
||||
|
||||
public override Transform GetNearestRootOf( Transform target )
|
||||
{
|
||||
return searchResult.Contains( target ) ? target : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7141026a6a1bd764f9a609622b8a70f1
|
||||
timeCreated: 1508420714
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,69 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class HierarchyDataTransform : HierarchyData
|
||||
{
|
||||
private string cachedName;
|
||||
public override string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
if( cachedName == null )
|
||||
cachedName = transform ? transform.name : "<destroyed>";
|
||||
|
||||
return cachedName;
|
||||
}
|
||||
}
|
||||
|
||||
public override int ChildCount { get { return ( !isSearchEntry && transform ) ? transform.childCount : 0; } }
|
||||
public override Transform BoundTransform { get { return transform; } }
|
||||
public override bool IsActive { get { return transform ? transform.gameObject.activeInHierarchy : true; } }
|
||||
|
||||
private Transform transform;
|
||||
private bool isSearchEntry;
|
||||
|
||||
public void Initialize( Transform transform, bool isSearchEntry )
|
||||
{
|
||||
this.transform = transform;
|
||||
this.isSearchEntry = isSearchEntry;
|
||||
}
|
||||
|
||||
public override Transform GetChild( int index )
|
||||
{
|
||||
return transform.GetChild( index );
|
||||
}
|
||||
|
||||
public void ResetCachedName()
|
||||
{
|
||||
cachedName = null;
|
||||
|
||||
if( children != null )
|
||||
{
|
||||
for( int i = children.Count - 1; i >= 0; i-- )
|
||||
children[i].ResetCachedName();
|
||||
}
|
||||
}
|
||||
|
||||
public void RefreshNameOf( Transform target )
|
||||
{
|
||||
if( ReferenceEquals( transform, target ) )
|
||||
cachedName = target.name;
|
||||
else if( children != null )
|
||||
{
|
||||
for( int i = children.Count - 1; i >= 0; i-- )
|
||||
children[i].RefreshNameOf( target );
|
||||
}
|
||||
}
|
||||
|
||||
public void PoolData()
|
||||
{
|
||||
parent = null;
|
||||
cachedName = null;
|
||||
m_depth = 0;
|
||||
m_height = 0;
|
||||
|
||||
PoolChildrenList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3da479804f0113d4fbde323d386a55f7
|
||||
timeCreated: 1508420714
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,213 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class HierarchyField : RecycledListItem, ITooltipContent
|
||||
{
|
||||
private enum ExpandedState { Collapsed = 0, Expanded = 1, ArrowHidden = 2 };
|
||||
|
||||
private const float INACTIVE_ITEM_TEXT_ALPHA = 0.57f;
|
||||
private const float TEXT_X_OFFSET = 35f;
|
||||
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
private RectTransform contentTransform;
|
||||
|
||||
[SerializeField]
|
||||
private Text nameText;
|
||||
|
||||
[SerializeField]
|
||||
private PointerEventListener clickListener;
|
||||
|
||||
[SerializeField]
|
||||
private PointerEventListener expandToggle;
|
||||
|
||||
[SerializeField]
|
||||
private Image expandArrow;
|
||||
|
||||
[SerializeField]
|
||||
private Toggle multiSelectionToggle;
|
||||
|
||||
[SerializeField]
|
||||
private Image multiSelectionToggleBackground;
|
||||
#pragma warning restore 0649
|
||||
|
||||
private RectTransform rectTransform;
|
||||
private Image background;
|
||||
|
||||
private int m_skinVersion = 0;
|
||||
private UISkin m_skin;
|
||||
public UISkin Skin
|
||||
{
|
||||
get { return m_skin; }
|
||||
set
|
||||
{
|
||||
if( m_skin != value || m_skinVersion != m_skin.Version )
|
||||
{
|
||||
m_skin = value;
|
||||
m_skinVersion = m_skin.Version;
|
||||
|
||||
rectTransform.sizeDelta = new Vector2( 0f, Skin.LineHeight );
|
||||
|
||||
nameText.SetSkinText( Skin );
|
||||
expandArrow.color = Skin.ExpandArrowColor;
|
||||
|
||||
nameText.rectTransform.anchoredPosition = new Vector2( Skin.ExpandArrowSpacing + Skin.LineHeight * 0.75f, 0f );
|
||||
( (RectTransform) expandToggle.transform ).sizeDelta = new Vector2( Skin.LineHeight, Skin.LineHeight );
|
||||
( (RectTransform) multiSelectionToggle.transform ).sizeDelta = new Vector2( Skin.LineHeight * 0.8f, Skin.LineHeight * 0.8f );
|
||||
|
||||
multiSelectionToggle.graphic.color = Skin.ToggleCheckmarkColor;
|
||||
multiSelectionToggleBackground.color = Skin.InputFieldNormalBackgroundColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool m_isSelected;
|
||||
public bool IsSelected
|
||||
{
|
||||
get { return m_isSelected; }
|
||||
set
|
||||
{
|
||||
m_isSelected = value;
|
||||
|
||||
Color textColor;
|
||||
if( m_isSelected )
|
||||
{
|
||||
background.color = Skin.SelectedItemBackgroundColor;
|
||||
textColor = Skin.SelectedItemTextColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
background.color = Data.Depth == 0 ? Skin.BackgroundColor.Tint( 0.075f ) : Color.clear;
|
||||
textColor = Skin.TextColor;
|
||||
}
|
||||
|
||||
textColor.a = m_isActive ? 1f : INACTIVE_ITEM_TEXT_ALPHA;
|
||||
nameText.color = textColor;
|
||||
multiSelectionToggle.isOn = m_isSelected;
|
||||
}
|
||||
}
|
||||
|
||||
private bool m_isActive;
|
||||
private bool IsActive
|
||||
{
|
||||
get { return m_isActive; }
|
||||
set
|
||||
{
|
||||
if( m_isActive != value )
|
||||
{
|
||||
m_isActive = value;
|
||||
|
||||
Color color = nameText.color;
|
||||
color.a = m_isActive ? 1f : INACTIVE_ITEM_TEXT_ALPHA;
|
||||
nameText.color = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool MultiSelectionToggleVisible
|
||||
{
|
||||
get { return multiSelectionToggle.gameObject.activeSelf; }
|
||||
set
|
||||
{
|
||||
if( Data == null || Data.Depth <= 0 )
|
||||
value = false;
|
||||
|
||||
if( multiSelectionToggle.gameObject.activeSelf != value )
|
||||
{
|
||||
multiSelectionToggle.gameObject.SetActive( value );
|
||||
contentTransform.anchoredPosition = new Vector2( Skin.IndentAmount * Data.Depth + ( value ? Skin.LineHeight * 0.8f : 0f ), 0f );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ExpandedState m_isExpanded = ExpandedState.Collapsed;
|
||||
private ExpandedState IsExpanded
|
||||
{
|
||||
get { return m_isExpanded; }
|
||||
set
|
||||
{
|
||||
if( m_isExpanded != value )
|
||||
{
|
||||
m_isExpanded = value;
|
||||
|
||||
if( m_isExpanded == ExpandedState.ArrowHidden )
|
||||
expandToggle.gameObject.SetActive( false );
|
||||
else
|
||||
{
|
||||
expandToggle.gameObject.SetActive( true );
|
||||
expandArrow.rectTransform.localEulerAngles = m_isExpanded == ExpandedState.Expanded ? new Vector3( 0f, 0f, -90f ) : Vector3.zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ITooltipContent.IsActive { get { return this && gameObject.activeSelf; } }
|
||||
string ITooltipContent.TooltipText { get { return Data.Name; } }
|
||||
|
||||
public float PreferredWidth { get; private set; }
|
||||
|
||||
public RuntimeHierarchy Hierarchy { get; private set; }
|
||||
public HierarchyData Data { get; private set; }
|
||||
|
||||
public void Initialize( RuntimeHierarchy hierarchy )
|
||||
{
|
||||
Hierarchy = hierarchy;
|
||||
|
||||
rectTransform = (RectTransform) transform;
|
||||
background = clickListener.GetComponent<Image>();
|
||||
|
||||
if( hierarchy.ShowTooltips )
|
||||
clickListener.gameObject.AddComponent<TooltipArea>().Initialize( hierarchy.TooltipListener, this );
|
||||
|
||||
expandToggle.PointerClick += ( eventData ) => ToggleExpandedState();
|
||||
clickListener.PointerClick += ( eventData ) => OnClick();
|
||||
clickListener.PointerDown += OnPointerDown;
|
||||
clickListener.PointerUp += OnPointerUp;
|
||||
}
|
||||
|
||||
public void SetContent( HierarchyData data )
|
||||
{
|
||||
Data = data;
|
||||
|
||||
contentTransform.anchoredPosition = new Vector2( Skin.IndentAmount * data.Depth + ( MultiSelectionToggleVisible ? Skin.LineHeight * 0.8f : 0f ), 0f );
|
||||
background.sprite = data.Depth == 0 ? Hierarchy.SceneDrawerBackground : Hierarchy.TransformDrawerBackground;
|
||||
|
||||
RefreshName();
|
||||
}
|
||||
|
||||
private void ToggleExpandedState()
|
||||
{
|
||||
Data.IsExpanded = !Data.IsExpanded;
|
||||
}
|
||||
|
||||
public void Refresh()
|
||||
{
|
||||
IsActive = Data.IsActive;
|
||||
IsExpanded = Data.CanExpand ? ( Data.IsExpanded ? ExpandedState.Expanded : ExpandedState.Collapsed ) : ExpandedState.ArrowHidden;
|
||||
}
|
||||
|
||||
public void RefreshName()
|
||||
{
|
||||
nameText.text = Data.Name;
|
||||
|
||||
if( Hierarchy.ShowHorizontalScrollbar )
|
||||
{
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate( nameText.rectTransform );
|
||||
PreferredWidth = Data.Depth * m_skin.IndentAmount + TEXT_X_OFFSET + nameText.rectTransform.sizeDelta.x;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPointerDown( PointerEventData eventData )
|
||||
{
|
||||
Hierarchy.OnDrawerPointerEvent( this, eventData, true );
|
||||
}
|
||||
|
||||
private void OnPointerUp( PointerEventData eventData )
|
||||
{
|
||||
Hierarchy.OnDrawerPointerEvent( this, eventData, false );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3e312fb4db3dfda40b7e02269d07e9ef
|
||||
timeCreated: 1582458911
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
655
Assets/Plugins/RuntimeInspector/Scripts/RuntimeInspector.cs
Normal file
655
Assets/Plugins/RuntimeInspector/Scripts/RuntimeInspector.cs
Normal file
@ -0,0 +1,655 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class RuntimeInspector : SkinnedWindow, ITooltipManager
|
||||
{
|
||||
public enum VariableVisibility { None = 0, SerializableOnly = 1, All = 2 };
|
||||
public enum HeaderVisibility { Collapsible = 0, AlwaysVisible = 1, Hidden = 2 };
|
||||
|
||||
private const string POOL_OBJECT_NAME = "RuntimeInspectorPool";
|
||||
|
||||
public delegate object InspectedObjectChangingDelegate( object previousInspectedObject, object newInspectedObject );
|
||||
public delegate void ComponentFilterDelegate( GameObject gameObject, List<Component> components );
|
||||
|
||||
#pragma warning disable 0649
|
||||
[SerializeField, UnityEngine.Serialization.FormerlySerializedAs( "refreshInterval" )]
|
||||
private float m_refreshInterval = 0f;
|
||||
private float nextRefreshTime = -1f;
|
||||
public float RefreshInterval
|
||||
{
|
||||
get { return m_refreshInterval; }
|
||||
set { m_refreshInterval = value; }
|
||||
}
|
||||
|
||||
[Space]
|
||||
[SerializeField]
|
||||
private VariableVisibility m_exposeFields = VariableVisibility.SerializableOnly;
|
||||
public VariableVisibility ExposeFields
|
||||
{
|
||||
get { return m_exposeFields; }
|
||||
set
|
||||
{
|
||||
if( m_exposeFields != value )
|
||||
{
|
||||
m_exposeFields = value;
|
||||
isDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private VariableVisibility m_exposeProperties = VariableVisibility.SerializableOnly;
|
||||
public VariableVisibility ExposeProperties
|
||||
{
|
||||
get { return m_exposeProperties; }
|
||||
set
|
||||
{
|
||||
if( m_exposeProperties != value )
|
||||
{
|
||||
m_exposeProperties = value;
|
||||
isDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Space]
|
||||
[SerializeField]
|
||||
private bool m_arrayIndicesStartAtOne = false;
|
||||
public bool ArrayIndicesStartAtOne
|
||||
{
|
||||
get { return m_arrayIndicesStartAtOne; }
|
||||
set
|
||||
{
|
||||
if( m_arrayIndicesStartAtOne != value )
|
||||
{
|
||||
m_arrayIndicesStartAtOne = value;
|
||||
isDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private bool m_useTitleCaseNaming = false;
|
||||
public bool UseTitleCaseNaming
|
||||
{
|
||||
get { return m_useTitleCaseNaming; }
|
||||
set
|
||||
{
|
||||
if( m_useTitleCaseNaming != value )
|
||||
{
|
||||
m_useTitleCaseNaming = value;
|
||||
isDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Space]
|
||||
[SerializeField]
|
||||
private bool m_showAddComponentButton = true;
|
||||
public bool ShowAddComponentButton
|
||||
{
|
||||
get { return m_showAddComponentButton; }
|
||||
set
|
||||
{
|
||||
if( m_showAddComponentButton != value )
|
||||
{
|
||||
m_showAddComponentButton = value;
|
||||
isDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private bool m_showRemoveComponentButton = true;
|
||||
public bool ShowRemoveComponentButton
|
||||
{
|
||||
get { return m_showRemoveComponentButton; }
|
||||
set
|
||||
{
|
||||
if( m_showRemoveComponentButton != value )
|
||||
{
|
||||
m_showRemoveComponentButton = value;
|
||||
isDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Space]
|
||||
[SerializeField]
|
||||
private bool m_showTooltips;
|
||||
public bool ShowTooltips { get { return m_showTooltips; } }
|
||||
|
||||
[SerializeField]
|
||||
private float m_tooltipDelay = 0.5f;
|
||||
public float TooltipDelay
|
||||
{
|
||||
get { return m_tooltipDelay; }
|
||||
set { m_tooltipDelay = value; }
|
||||
}
|
||||
|
||||
internal TooltipListener TooltipListener { get; private set; }
|
||||
|
||||
[Space]
|
||||
[SerializeField]
|
||||
private int m_nestLimit = 5;
|
||||
public int NestLimit
|
||||
{
|
||||
get { return m_nestLimit; }
|
||||
set
|
||||
{
|
||||
if( m_nestLimit != value )
|
||||
{
|
||||
m_nestLimit = value;
|
||||
isDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private HeaderVisibility m_inspectedObjectHeaderVisibility = HeaderVisibility.Collapsible;
|
||||
public HeaderVisibility InspectedObjectHeaderVisibility
|
||||
{
|
||||
get { return m_inspectedObjectHeaderVisibility; }
|
||||
set
|
||||
{
|
||||
if( m_inspectedObjectHeaderVisibility != value )
|
||||
{
|
||||
m_inspectedObjectHeaderVisibility = value;
|
||||
|
||||
if( currentDrawer != null && currentDrawer is ExpandableInspectorField )
|
||||
( (ExpandableInspectorField) currentDrawer ).HeaderVisibility = m_inspectedObjectHeaderVisibility;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private int poolCapacity = 10;
|
||||
private Transform poolParent;
|
||||
|
||||
[SerializeField]
|
||||
private RuntimeHierarchy m_connectedHierarchy;
|
||||
public RuntimeHierarchy ConnectedHierarchy
|
||||
{
|
||||
get { return m_connectedHierarchy; }
|
||||
set { m_connectedHierarchy = value; }
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private RuntimeInspectorSettings[] settings;
|
||||
|
||||
private bool m_isLocked = false;
|
||||
public bool IsLocked
|
||||
{
|
||||
get { return m_isLocked; }
|
||||
set { m_isLocked = value; }
|
||||
}
|
||||
|
||||
[Header( "Internal Variables" )]
|
||||
[SerializeField]
|
||||
private ScrollRect scrollView;
|
||||
private RectTransform drawArea;
|
||||
|
||||
[SerializeField]
|
||||
private Image background;
|
||||
|
||||
[SerializeField]
|
||||
private Image scrollbar;
|
||||
#pragma warning restore 0649
|
||||
|
||||
private static int aliveInspectors = 0;
|
||||
|
||||
private bool initialized = false;
|
||||
|
||||
private readonly Dictionary<Type, InspectorField[]> typeToDrawers = new Dictionary<Type, InspectorField[]>( 89 );
|
||||
private readonly Dictionary<Type, InspectorField[]> typeToReferenceDrawers = new Dictionary<Type, InspectorField[]>( 89 );
|
||||
private readonly List<InspectorField> eligibleDrawers = new List<InspectorField>( 4 );
|
||||
|
||||
private static readonly Dictionary<Type, List<InspectorField>> drawersPool = new Dictionary<Type, List<InspectorField>>();
|
||||
|
||||
private readonly List<VariableSet> hiddenVariables = new List<VariableSet>( 32 );
|
||||
private readonly List<VariableSet> exposedVariables = new List<VariableSet>( 32 );
|
||||
|
||||
private InspectorField currentDrawer = null;
|
||||
private bool inspectLock = false;
|
||||
private bool isDirty = false;
|
||||
|
||||
private object m_inspectedObject;
|
||||
public object InspectedObject { get { return m_inspectedObject; } }
|
||||
|
||||
public bool IsBound { get { return !m_inspectedObject.IsNull(); } }
|
||||
|
||||
private Canvas m_canvas;
|
||||
public Canvas Canvas { get { return m_canvas; } }
|
||||
|
||||
// Used to make sure that the scrolled content always remains within the scroll view's boundaries
|
||||
private PointerEventData nullPointerEventData;
|
||||
|
||||
public InspectedObjectChangingDelegate OnInspectedObjectChanging;
|
||||
|
||||
private ComponentFilterDelegate m_componentFilter;
|
||||
public ComponentFilterDelegate ComponentFilter
|
||||
{
|
||||
get { return m_componentFilter; }
|
||||
set
|
||||
{
|
||||
m_componentFilter = value;
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
Initialize();
|
||||
}
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
if( initialized )
|
||||
return;
|
||||
|
||||
initialized = true;
|
||||
|
||||
drawArea = scrollView.content;
|
||||
m_canvas = GetComponentInParent<Canvas>();
|
||||
nullPointerEventData = new PointerEventData( null );
|
||||
|
||||
if( m_showTooltips )
|
||||
{
|
||||
TooltipListener = gameObject.AddComponent<TooltipListener>();
|
||||
TooltipListener.Initialize( this );
|
||||
}
|
||||
|
||||
GameObject poolParentGO = GameObject.Find( POOL_OBJECT_NAME );
|
||||
if( poolParentGO == null )
|
||||
{
|
||||
poolParentGO = new GameObject( POOL_OBJECT_NAME );
|
||||
DontDestroyOnLoad( poolParentGO );
|
||||
}
|
||||
|
||||
poolParent = poolParentGO.transform;
|
||||
aliveInspectors++;
|
||||
|
||||
for( int i = 0; i < settings.Length; i++ )
|
||||
{
|
||||
if( !settings[i] )
|
||||
continue;
|
||||
|
||||
VariableSet[] hiddenVariablesForTypes = settings[i].HiddenVariables;
|
||||
for( int j = 0; j < hiddenVariablesForTypes.Length; j++ )
|
||||
{
|
||||
VariableSet hiddenVariablesSet = hiddenVariablesForTypes[j];
|
||||
if( hiddenVariablesSet.Init() )
|
||||
hiddenVariables.Add( hiddenVariablesSet );
|
||||
}
|
||||
|
||||
VariableSet[] exposedVariablesForTypes = settings[i].ExposedVariables;
|
||||
for( int j = 0; j < exposedVariablesForTypes.Length; j++ )
|
||||
{
|
||||
VariableSet exposedVariablesSet = exposedVariablesForTypes[j];
|
||||
if( exposedVariablesSet.Init() )
|
||||
exposedVariables.Add( exposedVariablesSet );
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
if( --aliveInspectors == 0 )
|
||||
{
|
||||
if( poolParent )
|
||||
{
|
||||
RuntimeInspectorUtils.IgnoredTransformsInHierarchy.Remove( poolParent );
|
||||
DestroyImmediate( poolParent.gameObject );
|
||||
}
|
||||
|
||||
ColorPicker.DestroyInstance();
|
||||
ObjectReferencePicker.DestroyInstance();
|
||||
|
||||
drawersPool.Clear();
|
||||
}
|
||||
|
||||
RuntimeInspectorUtils.IgnoredTransformsInHierarchy.Remove( drawArea );
|
||||
}
|
||||
|
||||
private void OnTransformParentChanged()
|
||||
{
|
||||
m_canvas = GetComponentInParent<Canvas>();
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
protected override void OnValidate()
|
||||
{
|
||||
base.OnValidate();
|
||||
|
||||
if( UnityEditor.EditorApplication.isPlaying )
|
||||
isDirty = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if( IsBound )
|
||||
{
|
||||
float time = Time.realtimeSinceStartup;
|
||||
if( isDirty )
|
||||
{
|
||||
// Rebind to refresh the exposed variables in Inspector
|
||||
object inspectedObject = m_inspectedObject;
|
||||
StopInspectInternal();
|
||||
InspectInternal( inspectedObject );
|
||||
|
||||
isDirty = false;
|
||||
nextRefreshTime = time + m_refreshInterval;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( time > nextRefreshTime )
|
||||
{
|
||||
nextRefreshTime = time + m_refreshInterval;
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( currentDrawer != null )
|
||||
StopInspectInternal();
|
||||
}
|
||||
|
||||
public void Refresh()
|
||||
{
|
||||
if( IsBound )
|
||||
{
|
||||
if( currentDrawer == null )
|
||||
m_inspectedObject = null;
|
||||
else
|
||||
currentDrawer.Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
// Refreshes the Inspector in the next Update. Called by most of the InspectorDrawers
|
||||
// when their values have changed. If a drawer is bound to a property whose setter
|
||||
// may modify the input data (e.g. when input data is 20 but the setter clamps it to 10),
|
||||
// the drawer's BoundInputFields will still show the unmodified input data (20) until the
|
||||
// next Refresh. That is because BoundInputFields don't have access to the fields/properties
|
||||
// they are modifying, there is no way for the BoundInputFields to know whether or not
|
||||
// the property has modified the input data (changed it from 20 to 10).
|
||||
//
|
||||
// Why not refresh only the changed InspectorDrawers? Because changing a property may affect
|
||||
// multiple fields/properties that are bound to other drawers, we don't know which
|
||||
// drawers may be affected. The safest way is to refresh all the drawers.
|
||||
//
|
||||
// Why not Refresh? That's the hacky part: most drawers call this function in their
|
||||
// BoundInputFields' OnValueSubmitted event. If Refresh was used, BoundInputField's
|
||||
// "recentText = str;" line that is called after the OnValueSubmitted event would mess up
|
||||
// with refreshing the value displayed on the BoundInputField.
|
||||
public void RefreshDelayed()
|
||||
{
|
||||
nextRefreshTime = 0f;
|
||||
}
|
||||
|
||||
// Makes sure that scroll view's contents are within scroll view's bounds
|
||||
internal void EnsureScrollViewIsWithinBounds()
|
||||
{
|
||||
// When scrollbar is snapped to the very bottom of the scroll view, sometimes OnScroll alone doesn't work
|
||||
if( scrollView.verticalNormalizedPosition <= Mathf.Epsilon )
|
||||
scrollView.verticalNormalizedPosition = 0.0001f;
|
||||
|
||||
scrollView.OnScroll( nullPointerEventData );
|
||||
}
|
||||
|
||||
protected override void RefreshSkin()
|
||||
{
|
||||
background.color = Skin.BackgroundColor;
|
||||
scrollbar.color = Skin.ScrollbarColor;
|
||||
|
||||
if( IsBound && !isDirty )
|
||||
currentDrawer.Skin = Skin;
|
||||
}
|
||||
|
||||
public void Inspect( object obj )
|
||||
{
|
||||
if( !m_isLocked )
|
||||
InspectInternal( obj );
|
||||
}
|
||||
|
||||
internal void InspectInternal( object obj )
|
||||
{
|
||||
if( inspectLock )
|
||||
return;
|
||||
|
||||
isDirty = false;
|
||||
Initialize();
|
||||
|
||||
if( OnInspectedObjectChanging != null )
|
||||
obj = OnInspectedObjectChanging( m_inspectedObject, obj );
|
||||
|
||||
if( m_inspectedObject == obj )
|
||||
return;
|
||||
|
||||
StopInspectInternal();
|
||||
|
||||
inspectLock = true;
|
||||
try
|
||||
{
|
||||
m_inspectedObject = obj;
|
||||
|
||||
if( obj.IsNull() )
|
||||
return;
|
||||
|
||||
#if UNITY_EDITOR || !NETFX_CORE
|
||||
if( obj.GetType().IsValueType )
|
||||
#else
|
||||
if( obj.GetType().GetTypeInfo().IsValueType )
|
||||
#endif
|
||||
{
|
||||
m_inspectedObject = null;
|
||||
Debug.LogError( "Can't inspect a value type!" );
|
||||
return;
|
||||
}
|
||||
|
||||
//if( !gameObject.activeSelf )
|
||||
//{
|
||||
// m_inspectedObject = null;
|
||||
// Debug.LogError( "Can't inspect while Inspector is inactive!" );
|
||||
// return;
|
||||
//}
|
||||
|
||||
InspectorField inspectedObjectDrawer = CreateDrawerForType( obj.GetType(), drawArea, 0, false );
|
||||
if( inspectedObjectDrawer != null )
|
||||
{
|
||||
inspectedObjectDrawer.BindTo( obj.GetType(), string.Empty, () => m_inspectedObject, ( value ) => m_inspectedObject = value );
|
||||
inspectedObjectDrawer.NameRaw = obj.GetNameWithType();
|
||||
inspectedObjectDrawer.Refresh();
|
||||
|
||||
if( inspectedObjectDrawer is ExpandableInspectorField )
|
||||
( (ExpandableInspectorField) inspectedObjectDrawer ).IsExpanded = true;
|
||||
|
||||
currentDrawer = inspectedObjectDrawer;
|
||||
if( currentDrawer is ExpandableInspectorField )
|
||||
( (ExpandableInspectorField) currentDrawer ).HeaderVisibility = m_inspectedObjectHeaderVisibility;
|
||||
|
||||
GameObject go = m_inspectedObject as GameObject;
|
||||
if( !go && m_inspectedObject as Component )
|
||||
go = ( (Component) m_inspectedObject ).gameObject;
|
||||
|
||||
if( ConnectedHierarchy && go && !ConnectedHierarchy.Select( go.transform, RuntimeHierarchy.SelectOptions.FocusOnSelection ) )
|
||||
ConnectedHierarchy.Deselect();
|
||||
}
|
||||
else
|
||||
m_inspectedObject = null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
inspectLock = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void StopInspect()
|
||||
{
|
||||
if( !m_isLocked )
|
||||
StopInspectInternal();
|
||||
}
|
||||
|
||||
internal void StopInspectInternal()
|
||||
{
|
||||
if( inspectLock )
|
||||
return;
|
||||
|
||||
if( currentDrawer != null )
|
||||
{
|
||||
currentDrawer.Unbind();
|
||||
currentDrawer = null;
|
||||
}
|
||||
|
||||
m_inspectedObject = null;
|
||||
scrollView.verticalNormalizedPosition = 1f;
|
||||
|
||||
ColorPicker.Instance.Close();
|
||||
ObjectReferencePicker.Instance.Close();
|
||||
}
|
||||
|
||||
public InspectorField CreateDrawerForType( Type type, Transform drawerParent, int depth, bool drawObjectsAsFields = true, MemberInfo variable = null )
|
||||
{
|
||||
InspectorField[] variableDrawers = GetDrawersForType( type, drawObjectsAsFields );
|
||||
if( variableDrawers != null )
|
||||
{
|
||||
for( int i = 0; i < variableDrawers.Length; i++ )
|
||||
{
|
||||
if( variableDrawers[i].CanBindTo( type, variable ) )
|
||||
{
|
||||
InspectorField drawer = InstantiateDrawer( variableDrawers[i], drawerParent );
|
||||
drawer.Inspector = this;
|
||||
drawer.Skin = Skin;
|
||||
drawer.Depth = depth;
|
||||
|
||||
return drawer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private InspectorField InstantiateDrawer( InspectorField drawer, Transform drawerParent )
|
||||
{
|
||||
List<InspectorField> drawerPool;
|
||||
if( drawersPool.TryGetValue( drawer.GetType(), out drawerPool ) )
|
||||
{
|
||||
for( int i = drawerPool.Count - 1; i >= 0; i-- )
|
||||
{
|
||||
InspectorField instance = drawerPool[i];
|
||||
drawerPool.RemoveAt( i );
|
||||
|
||||
if( instance )
|
||||
{
|
||||
instance.transform.SetParent( drawerParent, false );
|
||||
instance.gameObject.SetActive( true );
|
||||
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InspectorField newDrawer = (InspectorField) Instantiate( drawer, drawerParent, false );
|
||||
newDrawer.Initialize();
|
||||
return newDrawer;
|
||||
}
|
||||
|
||||
private InspectorField[] GetDrawersForType( Type type, bool drawObjectsAsFields )
|
||||
{
|
||||
bool searchReferenceFields = drawObjectsAsFields && typeof( Object ).IsAssignableFrom( type );
|
||||
|
||||
InspectorField[] cachedResult;
|
||||
if( ( searchReferenceFields && typeToReferenceDrawers.TryGetValue( type, out cachedResult ) ) ||
|
||||
( !searchReferenceFields && typeToDrawers.TryGetValue( type, out cachedResult ) ) )
|
||||
return cachedResult;
|
||||
|
||||
Dictionary<Type, InspectorField[]> drawersDict = searchReferenceFields ? typeToReferenceDrawers : typeToDrawers;
|
||||
|
||||
eligibleDrawers.Clear();
|
||||
for( int i = settings.Length - 1; i >= 0; i-- )
|
||||
{
|
||||
InspectorField[] drawers = searchReferenceFields ? settings[i].ReferenceDrawers : settings[i].StandardDrawers;
|
||||
for( int j = drawers.Length - 1; j >= 0; j-- )
|
||||
{
|
||||
if( drawers[j].SupportsType( type ) )
|
||||
eligibleDrawers.Add( drawers[j] );
|
||||
}
|
||||
}
|
||||
|
||||
cachedResult = eligibleDrawers.Count > 0 ? eligibleDrawers.ToArray() : null;
|
||||
drawersDict[type] = cachedResult;
|
||||
|
||||
return cachedResult;
|
||||
}
|
||||
|
||||
internal void PoolDrawer( InspectorField drawer )
|
||||
{
|
||||
List<InspectorField> drawerPool;
|
||||
if( !drawersPool.TryGetValue( drawer.GetType(), out drawerPool ) )
|
||||
{
|
||||
drawerPool = new List<InspectorField>( poolCapacity );
|
||||
drawersPool[drawer.GetType()] = drawerPool;
|
||||
}
|
||||
|
||||
if( drawerPool.Count < poolCapacity )
|
||||
{
|
||||
drawer.gameObject.SetActive( false );
|
||||
drawer.transform.SetParent( poolParent, false );
|
||||
drawerPool.Add( drawer );
|
||||
}
|
||||
else
|
||||
Destroy( drawer.gameObject );
|
||||
}
|
||||
|
||||
internal ExposedVariablesEnumerator GetExposedVariablesForType( Type type )
|
||||
{
|
||||
MemberInfo[] allVariables = type.GetAllVariables();
|
||||
if( allVariables == null )
|
||||
return new ExposedVariablesEnumerator( null, null, null, VariableVisibility.None, VariableVisibility.None );
|
||||
|
||||
List<VariableSet> hiddenVariablesForType = null;
|
||||
List<VariableSet> exposedVariablesForType = null;
|
||||
for( int i = 0; i < hiddenVariables.Count; i++ )
|
||||
{
|
||||
if( hiddenVariables[i].type.IsAssignableFrom( type ) )
|
||||
{
|
||||
if( hiddenVariablesForType == null )
|
||||
hiddenVariablesForType = new List<VariableSet>() { hiddenVariables[i] };
|
||||
else
|
||||
hiddenVariablesForType.Add( hiddenVariables[i] );
|
||||
}
|
||||
}
|
||||
|
||||
for( int i = 0; i < exposedVariables.Count; i++ )
|
||||
{
|
||||
if( exposedVariables[i].type.IsAssignableFrom( type ) )
|
||||
{
|
||||
if( exposedVariablesForType == null )
|
||||
exposedVariablesForType = new List<VariableSet>() { exposedVariables[i] };
|
||||
else
|
||||
exposedVariablesForType.Add( exposedVariables[i] );
|
||||
}
|
||||
}
|
||||
|
||||
return new ExposedVariablesEnumerator( allVariables, hiddenVariablesForType, exposedVariablesForType, m_exposeFields, m_exposeProperties );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 30158715ff59ef442aeceebc655d1b73
|
||||
timeCreated: 1505745306
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c430e2ee6e4793247ba6c2540ebd9093
|
||||
folderAsset: yes
|
||||
timeCreated: 1506880244
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 36555c32c6531314aac6ac381dd2ec5a
|
||||
folderAsset: yes
|
||||
timeCreated: 1507972349
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,25 @@
|
||||
using System;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public enum ButtonVisibility { None = 0, InitializedObjects = 1, UninitializedObjects = 2 }
|
||||
|
||||
[AttributeUsage( AttributeTargets.Method, Inherited = true, AllowMultiple = false )]
|
||||
public class RuntimeInspectorButtonAttribute : Attribute
|
||||
{
|
||||
private readonly string m_label;
|
||||
private readonly bool m_isInitializer;
|
||||
private readonly ButtonVisibility m_visibility;
|
||||
|
||||
public string Label { get { return m_label; } }
|
||||
public bool IsInitializer { get { return m_isInitializer; } }
|
||||
public ButtonVisibility Visibility { get { return m_visibility; } }
|
||||
|
||||
public RuntimeInspectorButtonAttribute( string label, bool isInitializer, ButtonVisibility visibility )
|
||||
{
|
||||
m_label = label;
|
||||
m_isInitializer = isInitializer;
|
||||
m_visibility = visibility;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dff639ac1bcd5b84b9e73cb758d611c8
|
||||
timeCreated: 1507972463
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,41 @@
|
||||
using System;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
[AttributeUsage( AttributeTargets.Class | AttributeTargets.Struct, Inherited = false, AllowMultiple = true )]
|
||||
public class RuntimeInspectorCustomEditorAttribute : Attribute, IComparable<RuntimeInspectorCustomEditorAttribute>
|
||||
{
|
||||
private readonly Type m_inspectedType;
|
||||
private readonly bool m_editorForChildClasses;
|
||||
private readonly int m_inspectedTypeDepth;
|
||||
|
||||
public Type InspectedType { get { return m_inspectedType; } }
|
||||
public bool EditorForChildClasses { get { return m_editorForChildClasses; } }
|
||||
|
||||
public RuntimeInspectorCustomEditorAttribute( Type inspectedType, bool editorForChildClasses = false )
|
||||
{
|
||||
m_inspectedType = inspectedType;
|
||||
m_editorForChildClasses = editorForChildClasses;
|
||||
m_inspectedTypeDepth = 0;
|
||||
|
||||
while( inspectedType != typeof( object ) )
|
||||
{
|
||||
inspectedType = inspectedType.BaseType;
|
||||
m_inspectedTypeDepth++;
|
||||
}
|
||||
}
|
||||
|
||||
// While sorting a list of RuntimeInspectorCustomEditor attributes, sort them by their depths in descending order
|
||||
int IComparable<RuntimeInspectorCustomEditorAttribute>.CompareTo( RuntimeInspectorCustomEditorAttribute other )
|
||||
{
|
||||
return other.m_inspectedTypeDepth.CompareTo( m_inspectedTypeDepth );
|
||||
}
|
||||
}
|
||||
|
||||
public interface IRuntimeInspectorCustomEditor
|
||||
{
|
||||
void GenerateElements( ObjectField parent );
|
||||
void Refresh();
|
||||
void Cleanup();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 171bc9cff57da8a4b9de4ffae16c3f08
|
||||
timeCreated: 1616525003
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6d8b0274304d38146ad33297ee67edc2
|
||||
folderAsset: yes
|
||||
timeCreated: 1505745266
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,322 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class ArrayField : ExpandableInspectorField, IDropHandler
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
private LayoutElement sizeLayoutElement;
|
||||
|
||||
[SerializeField]
|
||||
private Text sizeText;
|
||||
|
||||
[SerializeField]
|
||||
private BoundInputField sizeInput;
|
||||
#pragma warning restore 0649
|
||||
|
||||
private bool isArray;
|
||||
private Type elementType;
|
||||
|
||||
private readonly List<bool> elementsExpandedStates = new List<bool>();
|
||||
|
||||
protected override int Length
|
||||
{
|
||||
get
|
||||
{
|
||||
if( isArray )
|
||||
{
|
||||
Array array = (Array) Value;
|
||||
if( array != null )
|
||||
return array.Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
IList list = (IList) Value;
|
||||
if( list != null )
|
||||
return list.Count;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
sizeInput.Initialize();
|
||||
sizeInput.OnValueChanged += OnSizeInputBeingChanged;
|
||||
sizeInput.OnValueSubmitted += OnSizeChanged;
|
||||
sizeInput.DefaultEmptyValue = "0";
|
||||
sizeInput.CacheTextOnValueChange = false;
|
||||
}
|
||||
|
||||
public override bool SupportsType( Type type )
|
||||
{
|
||||
return ( type.IsArray && type.GetArrayRank() == 1 ) ||
|
||||
#if UNITY_EDITOR || !NETFX_CORE
|
||||
( type.IsGenericType && type.GetGenericTypeDefinition() == typeof( List<> ) );
|
||||
#else
|
||||
( type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == typeof( List<> ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
protected override void OnBound( MemberInfo variable )
|
||||
{
|
||||
base.OnBound( variable );
|
||||
|
||||
isArray = BoundVariableType.IsArray;
|
||||
elementType = isArray ? BoundVariableType.GetElementType() : BoundVariableType.GetGenericArguments()[0];
|
||||
}
|
||||
|
||||
protected override void OnUnbound()
|
||||
{
|
||||
base.OnUnbound();
|
||||
|
||||
sizeInput.Text = "0";
|
||||
elementsExpandedStates.Clear();
|
||||
}
|
||||
|
||||
protected override void OnSkinChanged()
|
||||
{
|
||||
base.OnSkinChanged();
|
||||
|
||||
sizeInput.Skin = Skin;
|
||||
|
||||
sizeLayoutElement.SetHeight( Skin.LineHeight );
|
||||
sizeText.SetSkinText( Skin );
|
||||
|
||||
Vector2 rightSideAnchorMin = new Vector2( Skin.LabelWidthPercentage, 0f );
|
||||
variableNameMask.rectTransform.anchorMin = rightSideAnchorMin;
|
||||
( (RectTransform) sizeInput.transform ).anchorMin = rightSideAnchorMin;
|
||||
}
|
||||
|
||||
protected override void OnDepthChanged()
|
||||
{
|
||||
base.OnDepthChanged();
|
||||
sizeText.rectTransform.sizeDelta = new Vector2( -Skin.IndentAmount * ( Depth + 1 ), 0f );
|
||||
}
|
||||
|
||||
protected override void ClearElements()
|
||||
{
|
||||
elementsExpandedStates.Clear();
|
||||
for( int i = 0; i < elements.Count; i++ )
|
||||
elementsExpandedStates.Add( ( elements[i] is ExpandableInspectorField ) ? ( (ExpandableInspectorField) elements[i] ).IsExpanded : false );
|
||||
|
||||
base.ClearElements();
|
||||
}
|
||||
|
||||
protected override void GenerateElements()
|
||||
{
|
||||
if( Value == null )
|
||||
return;
|
||||
|
||||
if( isArray )
|
||||
{
|
||||
Array array = (Array) Value;
|
||||
for( int i = 0; i < array.Length; i++ )
|
||||
{
|
||||
InspectorField elementDrawer = Inspector.CreateDrawerForType( elementType, drawArea, Depth + 1 );
|
||||
if( elementDrawer == null )
|
||||
break;
|
||||
|
||||
int j = i;
|
||||
elementDrawer.BindTo( elementType, string.Empty, () => ( (Array) Value ).GetValue( j ), ( value ) =>
|
||||
{
|
||||
Array _array = (Array) Value;
|
||||
_array.SetValue( value, j );
|
||||
Value = _array;
|
||||
} );
|
||||
|
||||
if( i < elementsExpandedStates.Count && elementsExpandedStates[i] && elementDrawer is ExpandableInspectorField )
|
||||
( (ExpandableInspectorField) elementDrawer ).IsExpanded = true;
|
||||
|
||||
elementDrawer.NameRaw = Inspector.ArrayIndicesStartAtOne ? ( ( i + 1 ) + ":" ) : ( i + ":" );
|
||||
elements.Add( elementDrawer );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IList list = (IList) Value;
|
||||
for( int i = 0; i < list.Count; i++ )
|
||||
{
|
||||
InspectorField elementDrawer = Inspector.CreateDrawerForType( elementType, drawArea, Depth + 1 );
|
||||
if( elementDrawer == null )
|
||||
break;
|
||||
|
||||
int j = i;
|
||||
string variableName = Inspector.ArrayIndicesStartAtOne ? ( ( i + 1 ) + ":" ) : ( i + ":" );
|
||||
elementDrawer.BindTo( elementType, variableName, () => ( (IList) Value )[j], ( value ) =>
|
||||
{
|
||||
IList _list = (IList) Value;
|
||||
_list[j] = value;
|
||||
Value = _list;
|
||||
} );
|
||||
|
||||
if( i < elementsExpandedStates.Count && elementsExpandedStates[i] && elementDrawer is ExpandableInspectorField )
|
||||
( (ExpandableInspectorField) elementDrawer ).IsExpanded = true;
|
||||
|
||||
elements.Add( elementDrawer );
|
||||
}
|
||||
}
|
||||
|
||||
sizeInput.Text = Length.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
elementsExpandedStates.Clear();
|
||||
}
|
||||
|
||||
void IDropHandler.OnDrop( PointerEventData eventData )
|
||||
{
|
||||
object[] assignableObjects = RuntimeInspectorUtils.GetAssignableObjectsFromDraggedReferenceItem( eventData, elementType );
|
||||
if( assignableObjects != null && assignableObjects.Length > 0 )
|
||||
{
|
||||
int prevLength = Length;
|
||||
if( !OnSizeChanged( null, ( prevLength + assignableObjects.Length ).ToString( RuntimeInspectorUtils.numberFormat ) ) )
|
||||
return;
|
||||
|
||||
if( isArray )
|
||||
{
|
||||
Array _array = (Array) Value;
|
||||
for( int i = 0; i < assignableObjects.Length; i++ )
|
||||
_array.SetValue( assignableObjects[i], prevLength + i );
|
||||
|
||||
Value = _array;
|
||||
}
|
||||
else
|
||||
{
|
||||
IList _list = (IList) Value;
|
||||
for( int i = 0; i < assignableObjects.Length; i++ )
|
||||
_list[prevLength + i] = assignableObjects[i];
|
||||
|
||||
Value = _list;
|
||||
}
|
||||
|
||||
if( !IsExpanded )
|
||||
IsExpanded = true;
|
||||
}
|
||||
}
|
||||
|
||||
private bool OnSizeInputBeingChanged( BoundInputField source, string input )
|
||||
{
|
||||
int value;
|
||||
if( int.TryParse( input, NumberStyles.Integer, RuntimeInspectorUtils.numberFormat, out value ) && value >= 0 )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool OnSizeChanged( BoundInputField source, string input )
|
||||
{
|
||||
int value;
|
||||
if( int.TryParse( input, NumberStyles.Integer, RuntimeInspectorUtils.numberFormat, out value ) && value >= 0 )
|
||||
{
|
||||
int currLength = Length;
|
||||
if( currLength != value )
|
||||
{
|
||||
if( isArray )
|
||||
{
|
||||
Array array = (Array) Value;
|
||||
Array newArray = Array.CreateInstance( BoundVariableType.GetElementType(), value );
|
||||
if( value > currLength )
|
||||
{
|
||||
if( array != null )
|
||||
Array.ConstrainedCopy( array, 0, newArray, 0, currLength );
|
||||
|
||||
for( int i = currLength; i < value; i++ )
|
||||
{
|
||||
object template = GetTemplateElement( array );
|
||||
if( template != null )
|
||||
newArray.SetValue( template, i );
|
||||
}
|
||||
}
|
||||
else
|
||||
Array.ConstrainedCopy( array, 0, newArray, 0, value );
|
||||
|
||||
Value = newArray;
|
||||
}
|
||||
else
|
||||
{
|
||||
IList list = (IList) Value;
|
||||
int deltaLength = value - currLength;
|
||||
if( deltaLength > 0 )
|
||||
{
|
||||
if( list == null )
|
||||
list = (IList) Activator.CreateInstance( typeof( List<> ).MakeGenericType( BoundVariableType.GetGenericArguments()[0] ) );
|
||||
|
||||
for( int i = 0; i < deltaLength; i++ )
|
||||
list.Add( GetTemplateElement( list ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int i = 0; i > deltaLength; i-- )
|
||||
list.RemoveAt( list.Count - 1 );
|
||||
}
|
||||
|
||||
Value = list;
|
||||
}
|
||||
|
||||
Inspector.RefreshDelayed();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private object GetTemplateElement( object value )
|
||||
{
|
||||
Array array = null;
|
||||
IList list = null;
|
||||
if( isArray )
|
||||
array = (Array) value;
|
||||
else
|
||||
list = (IList) value;
|
||||
|
||||
object template = null;
|
||||
Type elementType = isArray ? BoundVariableType.GetElementType() : BoundVariableType.GetGenericArguments()[0];
|
||||
#if UNITY_EDITOR || !NETFX_CORE
|
||||
if( elementType.IsValueType )
|
||||
#else
|
||||
if( elementType.GetTypeInfo().IsValueType )
|
||||
#endif
|
||||
{
|
||||
if( isArray && array != null && array.Length > 0 )
|
||||
template = array.GetValue( array.Length - 1 );
|
||||
else if( !isArray && list != null && list.Count > 0 )
|
||||
template = list[list.Count - 1];
|
||||
else
|
||||
template = Activator.CreateInstance( elementType );
|
||||
}
|
||||
else if( typeof( Object ).IsAssignableFrom( elementType ) )
|
||||
{
|
||||
if( isArray && array != null && array.Length > 0 )
|
||||
template = array.GetValue( array.Length - 1 );
|
||||
else if( !isArray && list != null && list.Count > 0 )
|
||||
template = list[list.Count - 1];
|
||||
else
|
||||
template = null;
|
||||
}
|
||||
else if( elementType.IsArray )
|
||||
template = Array.CreateInstance( elementType, 0 );
|
||||
#if UNITY_EDITOR || !NETFX_CORE
|
||||
else if( elementType.IsGenericType && elementType.GetGenericTypeDefinition() == typeof( List<> ) )
|
||||
#else
|
||||
else if( elementType.GetTypeInfo().IsGenericType && elementType.GetGenericTypeDefinition() == typeof( List<> ) )
|
||||
#endif
|
||||
template = Activator.CreateInstance( typeof( List<> ).MakeGenericType( elementType ) );
|
||||
else
|
||||
template = elementType.Instantiate();
|
||||
|
||||
return template;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c10d145e2e77bee49876b0ae6ffdb9e9
|
||||
timeCreated: 1505741432
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class BoolField : InspectorField
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
private Image toggleBackground;
|
||||
|
||||
[SerializeField]
|
||||
private Toggle input;
|
||||
#pragma warning restore 0649
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
input.onValueChanged.AddListener( OnValueChanged );
|
||||
}
|
||||
|
||||
public override bool SupportsType( Type type )
|
||||
{
|
||||
return type == typeof( bool );
|
||||
}
|
||||
|
||||
private void OnValueChanged( bool input )
|
||||
{
|
||||
Value = input;
|
||||
Inspector.RefreshDelayed();
|
||||
}
|
||||
|
||||
protected override void OnSkinChanged()
|
||||
{
|
||||
base.OnSkinChanged();
|
||||
|
||||
toggleBackground.color = Skin.InputFieldNormalBackgroundColor;
|
||||
input.graphic.color = Skin.ToggleCheckmarkColor;
|
||||
|
||||
Vector2 rightSideAnchorMin = new Vector2( Skin.LabelWidthPercentage, 0f );
|
||||
variableNameMask.rectTransform.anchorMin = rightSideAnchorMin;
|
||||
( (RectTransform) input.transform ).anchorMin = rightSideAnchorMin;
|
||||
}
|
||||
|
||||
public override void Refresh()
|
||||
{
|
||||
base.Refresh();
|
||||
input.isOn = (bool) Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 97cab5bdac5ee91408781a0eb58755de
|
||||
timeCreated: 1505741432
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,97 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class BoundsField : InspectorField
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
private Vector3Field inputCenter;
|
||||
[SerializeField]
|
||||
private Vector3Field inputExtents;
|
||||
#pragma warning restore 0649
|
||||
|
||||
private MemberInfo centerVariable;
|
||||
private MemberInfo extentsVariable;
|
||||
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
private MemberInfo intCenterVariable;
|
||||
private MemberInfo intSizeVariable;
|
||||
#endif
|
||||
|
||||
protected override float HeightMultiplier { get { return 3f; } }
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
centerVariable = typeof( Bounds ).GetProperty( "center" );
|
||||
extentsVariable = typeof( Bounds ).GetProperty( "extents" );
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
intCenterVariable = typeof( BoundsInt ).GetProperty( "center" );
|
||||
intSizeVariable = typeof( BoundsInt ).GetProperty( "size" );
|
||||
#endif
|
||||
}
|
||||
|
||||
public override bool SupportsType( Type type )
|
||||
{
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
if( type == typeof( BoundsInt ) )
|
||||
return true;
|
||||
#endif
|
||||
return type == typeof( Bounds );
|
||||
}
|
||||
|
||||
protected override void OnBound( MemberInfo variable )
|
||||
{
|
||||
base.OnBound( variable );
|
||||
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
if( BoundVariableType == typeof( BoundsInt ) )
|
||||
{
|
||||
inputCenter.BindTo( this, intCenterVariable, "Center:" );
|
||||
inputExtents.BindTo( this, intSizeVariable, "Size:" );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
inputCenter.BindTo( this, centerVariable, "Center:" );
|
||||
inputExtents.BindTo( this, extentsVariable, "Extents:" );
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnInspectorChanged()
|
||||
{
|
||||
base.OnInspectorChanged();
|
||||
|
||||
inputCenter.Inspector = Inspector;
|
||||
inputExtents.Inspector = Inspector;
|
||||
}
|
||||
|
||||
protected override void OnSkinChanged()
|
||||
{
|
||||
base.OnSkinChanged();
|
||||
|
||||
inputCenter.Skin = Skin;
|
||||
inputExtents.Skin = Skin;
|
||||
}
|
||||
|
||||
protected override void OnDepthChanged()
|
||||
{
|
||||
base.OnDepthChanged();
|
||||
|
||||
inputCenter.Depth = Depth + 1;
|
||||
inputExtents.Depth = Depth + 1;
|
||||
}
|
||||
|
||||
public override void Refresh()
|
||||
{
|
||||
base.Refresh();
|
||||
|
||||
inputCenter.Refresh();
|
||||
inputExtents.Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 36124d0fa9051c54ea21353631e310b5
|
||||
timeCreated: 1505741432
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class ColorField : InspectorField
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
private RectTransform colorPickerArea;
|
||||
|
||||
[SerializeField]
|
||||
private PointerEventListener inputColor;
|
||||
private Image colorImg;
|
||||
#pragma warning restore 0649
|
||||
|
||||
private bool isColor32;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
colorImg = inputColor.GetComponent<Image>();
|
||||
inputColor.PointerClick += ShowColorPicker;
|
||||
}
|
||||
|
||||
public override bool SupportsType( Type type )
|
||||
{
|
||||
return type == typeof( Color ) || type == typeof( Color32 );
|
||||
}
|
||||
|
||||
protected override void OnBound( MemberInfo variable )
|
||||
{
|
||||
base.OnBound( variable );
|
||||
isColor32 = BoundVariableType == typeof( Color32 );
|
||||
}
|
||||
|
||||
private void ShowColorPicker( PointerEventData eventData )
|
||||
{
|
||||
Color value = isColor32 ? (Color) (Color32) Value : (Color) Value;
|
||||
|
||||
ColorPicker.Instance.Skin = Inspector.Skin;
|
||||
ColorPicker.Instance.Show( OnColorChanged, null, value, Inspector.Canvas );
|
||||
}
|
||||
|
||||
private void OnColorChanged( Color32 color )
|
||||
{
|
||||
colorImg.color = color;
|
||||
|
||||
if( isColor32 )
|
||||
Value = color;
|
||||
else
|
||||
Value = (Color) color;
|
||||
}
|
||||
|
||||
protected override void OnSkinChanged()
|
||||
{
|
||||
base.OnSkinChanged();
|
||||
|
||||
Vector2 rightSideAnchorMin = new Vector2( Skin.LabelWidthPercentage, 0f );
|
||||
variableNameMask.rectTransform.anchorMin = rightSideAnchorMin;
|
||||
colorPickerArea.anchorMin = rightSideAnchorMin;
|
||||
}
|
||||
|
||||
public override void Refresh()
|
||||
{
|
||||
base.Refresh();
|
||||
|
||||
if( isColor32 )
|
||||
colorImg.color = (Color32) Value;
|
||||
else
|
||||
colorImg.color = (Color) Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c3d34835dd457c04a9a81529f3eb9dff
|
||||
timeCreated: 1505741432
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,164 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class EnumField : InspectorField
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
private Image background;
|
||||
|
||||
[SerializeField]
|
||||
private Image dropdownArrow;
|
||||
|
||||
[SerializeField]
|
||||
private RectTransform templateRoot;
|
||||
|
||||
[SerializeField]
|
||||
private RectTransform templateContentTransform;
|
||||
|
||||
[SerializeField]
|
||||
private RectTransform templateItemTransform;
|
||||
|
||||
[SerializeField]
|
||||
private Image templateBackground;
|
||||
|
||||
[SerializeField]
|
||||
private Image templateCheckmark;
|
||||
|
||||
[SerializeField]
|
||||
private Text templateText;
|
||||
|
||||
[SerializeField]
|
||||
private Dropdown input;
|
||||
#pragma warning restore 0649
|
||||
|
||||
private static readonly Dictionary<Type, List<string>> enumNames = new Dictionary<Type, List<string>>();
|
||||
private static readonly Dictionary<Type, List<object>> enumValues = new Dictionary<Type, List<object>>();
|
||||
|
||||
private List<string> currEnumNames;
|
||||
private List<object> currEnumValues;
|
||||
|
||||
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 )
|
||||
{
|
||||
#if UNITY_EDITOR || !NETFX_CORE
|
||||
return type.IsEnum;
|
||||
#else
|
||||
return type.GetTypeInfo().IsEnum;
|
||||
#endif
|
||||
}
|
||||
|
||||
protected override void OnBound( MemberInfo variable )
|
||||
{
|
||||
base.OnBound( variable );
|
||||
|
||||
if( !enumNames.TryGetValue( BoundVariableType, out currEnumNames ) || !enumValues.TryGetValue( BoundVariableType, out currEnumValues ) )
|
||||
{
|
||||
string[] names = Enum.GetNames( BoundVariableType );
|
||||
Array values = Enum.GetValues( BoundVariableType );
|
||||
|
||||
currEnumNames = new List<string>( names.Length );
|
||||
currEnumValues = new List<object>( names.Length );
|
||||
|
||||
for( int i = 0; i < names.Length; i++ )
|
||||
{
|
||||
currEnumNames.Add( names[i] );
|
||||
currEnumValues.Add( values.GetValue( i ) );
|
||||
}
|
||||
|
||||
enumNames[BoundVariableType] = currEnumNames;
|
||||
enumValues[BoundVariableType] = currEnumValues;
|
||||
}
|
||||
|
||||
input.ClearOptions();
|
||||
input.AddOptions( currEnumNames );
|
||||
}
|
||||
|
||||
protected override void OnInspectorChanged()
|
||||
{
|
||||
base.OnInspectorChanged();
|
||||
OnTransformParentChanged();
|
||||
}
|
||||
|
||||
private void OnTransformParentChanged()
|
||||
{
|
||||
if( Inspector && Skin )
|
||||
{
|
||||
// Dropdown's list should be able to expand as much as possible when necessary
|
||||
Vector2 templateRootSizeDelta = templateRoot.sizeDelta;
|
||||
templateRootSizeDelta.y = ( ( (RectTransform) Inspector.Canvas.transform ).rect.height - Skin.LineHeight ) * 0.5f;
|
||||
templateRoot.sizeDelta = templateRootSizeDelta;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnValueChanged( int input )
|
||||
{
|
||||
Value = currEnumValues[input];
|
||||
Inspector.RefreshDelayed();
|
||||
}
|
||||
|
||||
protected override void OnSkinChanged()
|
||||
{
|
||||
base.OnSkinChanged();
|
||||
OnTransformParentChanged();
|
||||
|
||||
Vector2 templateContentSizeDelta = templateContentTransform.sizeDelta;
|
||||
templateContentSizeDelta.y = Skin.LineHeight + 6f; // Padding at top and bottom edges
|
||||
templateContentTransform.sizeDelta = templateContentSizeDelta;
|
||||
|
||||
Vector2 templateItemSizeDelta = templateItemTransform.sizeDelta;
|
||||
templateItemSizeDelta.y = Skin.LineHeight;
|
||||
templateItemTransform.sizeDelta = templateItemSizeDelta;
|
||||
|
||||
// Resize the checkmark icon
|
||||
float templateCheckmarkSize = Skin.LineHeight * 0.66f;
|
||||
Vector2 templateTextSizeDelta = templateText.rectTransform.sizeDelta;
|
||||
templateTextSizeDelta.x -= templateCheckmarkSize - templateCheckmark.rectTransform.sizeDelta.x;
|
||||
templateText.rectTransform.sizeDelta = templateTextSizeDelta;
|
||||
templateCheckmark.rectTransform.sizeDelta = new Vector2( templateCheckmarkSize, templateCheckmarkSize );
|
||||
|
||||
// Resize the dropdown arrow
|
||||
Vector2 dropdownTextSizeDelta = input.captionText.rectTransform.sizeDelta;
|
||||
dropdownTextSizeDelta.x -= templateCheckmarkSize - dropdownArrow.rectTransform.sizeDelta.x;
|
||||
input.captionText.rectTransform.sizeDelta = dropdownTextSizeDelta;
|
||||
dropdownArrow.rectTransform.sizeDelta = new Vector2( templateCheckmarkSize, templateCheckmarkSize );
|
||||
|
||||
background.color = Skin.InputFieldNormalBackgroundColor;
|
||||
dropdownArrow.color = Skin.TextColor.Tint( 0.1f );
|
||||
|
||||
input.captionText.SetSkinInputFieldText( Skin );
|
||||
templateText.SetSkinInputFieldText( Skin );
|
||||
|
||||
templateBackground.color = Skin.InputFieldNormalBackgroundColor.Tint( 0.075f );
|
||||
templateCheckmark.color = Skin.ToggleCheckmarkColor;
|
||||
|
||||
Vector2 rightSideAnchorMin = new Vector2( Skin.LabelWidthPercentage, 0f );
|
||||
variableNameMask.rectTransform.anchorMin = rightSideAnchorMin;
|
||||
( (RectTransform) input.transform ).anchorMin = rightSideAnchorMin;
|
||||
}
|
||||
|
||||
public override void Refresh()
|
||||
{
|
||||
base.Refresh();
|
||||
|
||||
int valueIndex = currEnumValues.IndexOf( Value );
|
||||
if( valueIndex != -1 )
|
||||
input.value = valueIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eb127f89c3fd28542b6bead0ea08a23a
|
||||
timeCreated: 1505741432
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class ExposedMethodField : InspectorField
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
private Button invokeButton;
|
||||
#pragma warning restore 0649
|
||||
|
||||
protected ExposedMethod boundMethod;
|
||||
|
||||
public override bool SupportsType( Type type )
|
||||
{
|
||||
return type == typeof( ExposedMethod );
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
invokeButton.onClick.AddListener( InvokeMethod );
|
||||
}
|
||||
|
||||
protected override void OnSkinChanged()
|
||||
{
|
||||
base.OnSkinChanged();
|
||||
invokeButton.SetSkinButton( Skin );
|
||||
}
|
||||
|
||||
protected override void OnDepthChanged()
|
||||
{
|
||||
( (RectTransform) invokeButton.transform ).sizeDelta = new Vector2( -Skin.IndentAmount * Depth, 0f );
|
||||
}
|
||||
|
||||
public void SetBoundMethod( ExposedMethod boundMethod )
|
||||
{
|
||||
this.boundMethod = boundMethod;
|
||||
NameRaw = boundMethod.Label;
|
||||
}
|
||||
|
||||
public void InvokeMethod()
|
||||
{
|
||||
// Refresh value first
|
||||
Refresh();
|
||||
|
||||
if( boundMethod.IsInitializer )
|
||||
Value = boundMethod.CallAndReturnValue( Value );
|
||||
else
|
||||
boundMethod.Call( Value );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bb18c58fae1406243851946ca195468e
|
||||
timeCreated: 1507974913
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,240 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class GameObjectField : ExpandableInspectorField
|
||||
{
|
||||
protected override int Length { get { return components.Count + 4; } } // 4: active, name, tag, layer
|
||||
|
||||
private string currentTag = null;
|
||||
|
||||
private Getter isActiveGetter, nameGetter, tagGetter;
|
||||
private Setter isActiveSetter, nameSetter, tagSetter;
|
||||
private PropertyInfo layerProp;
|
||||
|
||||
private readonly List<Component> components = new List<Component>( 8 );
|
||||
private readonly List<bool> componentsExpandedStates = new List<bool>();
|
||||
|
||||
private Type[] addComponentTypes;
|
||||
|
||||
internal static ExposedMethod addComponentMethod = new ExposedMethod( typeof( GameObjectField ).GetMethod( "AddComponentButtonClicked", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance ), new RuntimeInspectorButtonAttribute( "Add Component", false, ButtonVisibility.InitializedObjects ), false );
|
||||
internal static ExposedMethod removeComponentMethod = new ExposedMethod( typeof( GameObjectField ).GetMethod( "RemoveComponentButtonClicked", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static ), new RuntimeInspectorButtonAttribute( "Remove Component", false, ButtonVisibility.InitializedObjects ), true );
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
isActiveGetter = () => ( (GameObject) Value ).activeSelf;
|
||||
isActiveSetter = ( value ) => ( (GameObject) Value ).SetActive( (bool) value );
|
||||
|
||||
nameGetter = () => ( (GameObject) Value ).name;
|
||||
nameSetter = ( value ) =>
|
||||
{
|
||||
( (GameObject) Value ).name = (string) value;
|
||||
NameRaw = Value.GetNameWithType();
|
||||
|
||||
RuntimeHierarchy hierarchy = Inspector.ConnectedHierarchy;
|
||||
if( hierarchy )
|
||||
hierarchy.RefreshNameOf( ( (GameObject) Value ).transform );
|
||||
};
|
||||
|
||||
tagGetter = () =>
|
||||
{
|
||||
GameObject go = (GameObject) Value;
|
||||
if( !go.CompareTag( currentTag ) )
|
||||
currentTag = go.tag;
|
||||
|
||||
return currentTag;
|
||||
};
|
||||
tagSetter = ( value ) => ( (GameObject) Value ).tag = (string) value;
|
||||
|
||||
layerProp = typeof( GameObject ).GetProperty( "layer" );
|
||||
}
|
||||
|
||||
public override bool SupportsType( Type type )
|
||||
{
|
||||
return type == typeof( GameObject );
|
||||
}
|
||||
|
||||
protected override void OnBound( MemberInfo variable )
|
||||
{
|
||||
base.OnBound( variable );
|
||||
currentTag = ( (GameObject) Value ).tag;
|
||||
}
|
||||
|
||||
protected override void OnUnbound()
|
||||
{
|
||||
base.OnUnbound();
|
||||
|
||||
components.Clear();
|
||||
componentsExpandedStates.Clear();
|
||||
}
|
||||
|
||||
protected override void ClearElements()
|
||||
{
|
||||
componentsExpandedStates.Clear();
|
||||
for( int i = 0; i < elements.Count; i++ )
|
||||
{
|
||||
// Don't keep track of non-expandable drawers' or destroyed components' expanded states
|
||||
if( elements[i] is ExpandableInspectorField && ( elements[i].Value as Object ) )
|
||||
componentsExpandedStates.Add( ( (ExpandableInspectorField) elements[i] ).IsExpanded );
|
||||
}
|
||||
|
||||
base.ClearElements();
|
||||
}
|
||||
|
||||
protected override void GenerateElements()
|
||||
{
|
||||
if( components.Count == 0 )
|
||||
return;
|
||||
|
||||
CreateDrawer( typeof( bool ), "Is Active", isActiveGetter, isActiveSetter );
|
||||
StringField nameField = CreateDrawer( typeof( string ), "Name", nameGetter, nameSetter ) as StringField;
|
||||
StringField tagField = CreateDrawer( typeof( string ), "Tag", tagGetter, tagSetter ) as StringField;
|
||||
CreateDrawerForVariable( layerProp, "Layer" );
|
||||
|
||||
for( int i = 0, j = 0; i < components.Count; i++ )
|
||||
{
|
||||
InspectorField componentDrawer = CreateDrawerForComponent( components[i] );
|
||||
if( componentDrawer as ExpandableInspectorField && j < componentsExpandedStates.Count && componentsExpandedStates[j++] )
|
||||
( (ExpandableInspectorField) componentDrawer ).IsExpanded = true;
|
||||
}
|
||||
|
||||
if( nameField )
|
||||
nameField.SetterMode = StringField.Mode.OnSubmit;
|
||||
|
||||
if( tagField )
|
||||
tagField.SetterMode = StringField.Mode.OnSubmit;
|
||||
|
||||
if( Inspector.ShowAddComponentButton )
|
||||
CreateExposedMethodButton( addComponentMethod, () => this, ( value ) => { } );
|
||||
|
||||
componentsExpandedStates.Clear();
|
||||
}
|
||||
|
||||
public override void Refresh()
|
||||
{
|
||||
// Refresh components
|
||||
components.Clear();
|
||||
GameObject go = Value as GameObject;
|
||||
if( go )
|
||||
{
|
||||
go.GetComponents( components );
|
||||
|
||||
for( int i = components.Count - 1; i >= 0; i-- )
|
||||
{
|
||||
if( !components[i] )
|
||||
components.RemoveAt( i );
|
||||
}
|
||||
|
||||
if( Inspector.ComponentFilter != null )
|
||||
Inspector.ComponentFilter( go, components );
|
||||
}
|
||||
|
||||
// Regenerate components' drawers, if necessary
|
||||
base.Refresh();
|
||||
}
|
||||
|
||||
[UnityEngine.Scripting.Preserve] // This method is bound to addComponentMethod
|
||||
private void AddComponentButtonClicked()
|
||||
{
|
||||
GameObject target = (GameObject) Value;
|
||||
if( !target )
|
||||
return;
|
||||
|
||||
if( addComponentTypes == null )
|
||||
{
|
||||
List<Type> componentTypes = new List<Type>( 128 );
|
||||
|
||||
#if UNITY_EDITOR || !NETFX_CORE
|
||||
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
#else
|
||||
// Common Unity assemblies
|
||||
IEnumerable<Assembly> assemblies = new HashSet<Assembly>
|
||||
{
|
||||
typeof( Transform ).Assembly,
|
||||
typeof( RectTransform ).Assembly,
|
||||
typeof( Rigidbody ).Assembly,
|
||||
typeof( Rigidbody2D ).Assembly,
|
||||
typeof( AudioSource ).Assembly
|
||||
};
|
||||
#endif
|
||||
// Search assemblies for Component types
|
||||
foreach( Assembly assembly in assemblies )
|
||||
{
|
||||
#if( NET_4_6 || NET_STANDARD_2_0 ) && ( UNITY_EDITOR || !NETFX_CORE )
|
||||
if( assembly.IsDynamic )
|
||||
continue;
|
||||
#endif
|
||||
try
|
||||
{
|
||||
foreach( Type type in assembly.GetExportedTypes() )
|
||||
{
|
||||
if( !typeof( Component ).IsAssignableFrom( type ) )
|
||||
continue;
|
||||
|
||||
#if UNITY_EDITOR || !NETFX_CORE
|
||||
if( type.IsGenericType || type.IsAbstract )
|
||||
#else
|
||||
if( type.GetTypeInfo().IsGenericType || type.GetTypeInfo().IsAbstract )
|
||||
#endif
|
||||
continue;
|
||||
|
||||
componentTypes.Add( type );
|
||||
}
|
||||
}
|
||||
catch( NotSupportedException ) { }
|
||||
catch( System.IO.FileNotFoundException ) { }
|
||||
catch( Exception e )
|
||||
{
|
||||
Debug.LogError( "Couldn't search assembly for Component types: " + assembly.GetName().Name + "\n" + e.ToString() );
|
||||
}
|
||||
}
|
||||
|
||||
addComponentTypes = componentTypes.ToArray();
|
||||
}
|
||||
|
||||
ObjectReferencePicker.Instance.Skin = Inspector.Skin;
|
||||
ObjectReferencePicker.Instance.Show(
|
||||
null, ( type ) =>
|
||||
{
|
||||
// Make sure that RuntimeInspector is still inspecting this GameObject
|
||||
if( type != null && target && Inspector && ( Inspector.InspectedObject as GameObject ) == target )
|
||||
{
|
||||
target.AddComponent( (Type) type );
|
||||
Inspector.Refresh();
|
||||
}
|
||||
},
|
||||
( type ) => ( (Type) type ).FullName,
|
||||
( type ) => ( (Type) type ).FullName,
|
||||
addComponentTypes, null, false, "Add Component", Inspector.Canvas );
|
||||
}
|
||||
|
||||
[UnityEngine.Scripting.Preserve] // This method is bound to removeComponentMethod
|
||||
private static void RemoveComponentButtonClicked( ExpandableInspectorField componentDrawer )
|
||||
{
|
||||
if( !componentDrawer || !componentDrawer.Inspector )
|
||||
return;
|
||||
|
||||
Component component = componentDrawer.Value as Component;
|
||||
if( component && !( component is Transform ) )
|
||||
componentDrawer.StartCoroutine( RemoveComponentCoroutine( component, componentDrawer.Inspector ) );
|
||||
}
|
||||
|
||||
private static IEnumerator RemoveComponentCoroutine( Component component, RuntimeInspector inspector )
|
||||
{
|
||||
Destroy( component );
|
||||
|
||||
// Destroy operation doesn't take place immediately, wait for the component to be fully destroyed
|
||||
yield return null;
|
||||
|
||||
inspector.Refresh();
|
||||
inspector.EnsureScrollViewIsWithinBounds(); // Scroll view's contents can get out of bounds after removing a component
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 97580003e65031c4a86955db8b9b08e8
|
||||
timeCreated: 1506081137
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,557 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public abstract class InspectorField : MonoBehaviour, ITooltipContent
|
||||
{
|
||||
public delegate object Getter();
|
||||
public delegate void Setter( object value );
|
||||
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
protected LayoutElement layoutElement;
|
||||
|
||||
[SerializeField]
|
||||
protected Text variableNameText;
|
||||
|
||||
[SerializeField]
|
||||
protected Image variableNameMask;
|
||||
|
||||
[SerializeField]
|
||||
private MaskableGraphic visibleArea;
|
||||
#pragma warning restore 0649
|
||||
|
||||
private RuntimeInspector m_inspector;
|
||||
public RuntimeInspector Inspector
|
||||
{
|
||||
get { return m_inspector; }
|
||||
set
|
||||
{
|
||||
if( m_inspector != value )
|
||||
{
|
||||
m_inspector = value;
|
||||
OnInspectorChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int m_skinVersion = 0;
|
||||
private UISkin m_skin;
|
||||
public UISkin Skin
|
||||
{
|
||||
get { return m_skin; }
|
||||
set
|
||||
{
|
||||
if( m_skin != value || m_skinVersion != m_skin.Version )
|
||||
{
|
||||
m_skin = value;
|
||||
m_skinVersion = m_skin.Version;
|
||||
|
||||
OnSkinChanged();
|
||||
OnDepthChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Type m_boundVariableType;
|
||||
protected Type BoundVariableType { get { return m_boundVariableType; } }
|
||||
|
||||
private object m_value;
|
||||
public object Value
|
||||
{
|
||||
get { return m_value; }
|
||||
protected set
|
||||
{
|
||||
try { setter( value ); m_value = value; }
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
private int m_depth = -1;
|
||||
public int Depth
|
||||
{
|
||||
get { return m_depth; }
|
||||
set
|
||||
{
|
||||
if( m_depth != value )
|
||||
{
|
||||
m_depth = value;
|
||||
OnDepthChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool m_isVisible = true;
|
||||
public bool IsVisible { get { return m_isVisible; } }
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { if( variableNameText ) return variableNameText.text; return string.Empty; }
|
||||
set { if( variableNameText ) variableNameText.text = Inspector.UseTitleCaseNaming ? value.ToTitleCase() : value; }
|
||||
}
|
||||
|
||||
public string NameRaw
|
||||
{
|
||||
get { if( variableNameText ) return variableNameText.text; return string.Empty; }
|
||||
set { if( variableNameText ) variableNameText.text = value; }
|
||||
}
|
||||
|
||||
bool ITooltipContent.IsActive { get { return this && gameObject.activeSelf; } }
|
||||
string ITooltipContent.TooltipText { get { return NameRaw; } }
|
||||
|
||||
public virtual bool ShouldRefresh { get { return m_isVisible; } }
|
||||
|
||||
protected virtual float HeightMultiplier { get { return 1f; } }
|
||||
|
||||
private Getter getter;
|
||||
private Setter setter;
|
||||
|
||||
public virtual void Initialize()
|
||||
{
|
||||
if( visibleArea )
|
||||
visibleArea.onCullStateChanged.AddListener( ( bool isCulled ) => m_isVisible = !isCulled );
|
||||
}
|
||||
|
||||
public abstract bool SupportsType( Type type );
|
||||
|
||||
public virtual bool CanBindTo( Type type, MemberInfo variable )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void BindTo( InspectorField parent, MemberInfo variable, string variableName = null )
|
||||
{
|
||||
if( variable is FieldInfo )
|
||||
{
|
||||
FieldInfo field = (FieldInfo) variable;
|
||||
if( variableName == null )
|
||||
variableName = field.Name;
|
||||
|
||||
#if UNITY_EDITOR || !NETFX_CORE
|
||||
if( !parent.BoundVariableType.IsValueType )
|
||||
#else
|
||||
if( !parent.BoundVariableType.GetTypeInfo().IsValueType )
|
||||
#endif
|
||||
BindTo( field.FieldType, variableName, () => field.GetValue( parent.Value ), ( value ) => field.SetValue( parent.Value, value ), variable );
|
||||
else
|
||||
BindTo( field.FieldType, variableName, () => field.GetValue( parent.Value ), ( value ) =>
|
||||
{
|
||||
field.SetValue( parent.Value, value );
|
||||
parent.Value = parent.Value;
|
||||
}, variable );
|
||||
}
|
||||
else if( variable is PropertyInfo )
|
||||
{
|
||||
PropertyInfo property = (PropertyInfo) variable;
|
||||
if( variableName == null )
|
||||
variableName = property.Name;
|
||||
|
||||
#if UNITY_EDITOR || !NETFX_CORE
|
||||
if( !parent.BoundVariableType.IsValueType )
|
||||
#else
|
||||
if( !parent.BoundVariableType.GetTypeInfo().IsValueType )
|
||||
#endif
|
||||
BindTo( property.PropertyType, variableName, () => property.GetValue( parent.Value, null ), ( value ) => property.SetValue( parent.Value, value, null ), variable );
|
||||
else
|
||||
BindTo( property.PropertyType, variableName, () => property.GetValue( parent.Value, null ), ( value ) =>
|
||||
{
|
||||
property.SetValue( parent.Value, value, null );
|
||||
parent.Value = parent.Value;
|
||||
}, variable );
|
||||
}
|
||||
else
|
||||
throw new ArgumentException( "Variable can either be a field or a property" );
|
||||
}
|
||||
|
||||
public void BindTo( Type variableType, string variableName, Getter getter, Setter setter, MemberInfo variable = null )
|
||||
{
|
||||
m_boundVariableType = variableType;
|
||||
Name = variableName;
|
||||
|
||||
this.getter = getter;
|
||||
this.setter = setter;
|
||||
|
||||
OnBound( variable );
|
||||
}
|
||||
|
||||
public void Unbind()
|
||||
{
|
||||
m_boundVariableType = null;
|
||||
|
||||
getter = null;
|
||||
setter = null;
|
||||
|
||||
OnUnbound();
|
||||
Inspector.PoolDrawer( this );
|
||||
}
|
||||
|
||||
protected virtual void OnBound( MemberInfo variable )
|
||||
{
|
||||
RefreshValue();
|
||||
}
|
||||
|
||||
protected virtual void OnUnbound()
|
||||
{
|
||||
m_value = null;
|
||||
}
|
||||
|
||||
protected virtual void OnInspectorChanged()
|
||||
{
|
||||
if( !variableNameText )
|
||||
return;
|
||||
|
||||
if( m_inspector.ShowTooltips )
|
||||
{
|
||||
TooltipArea tooltipArea = variableNameText.GetComponent<TooltipArea>();
|
||||
if( !tooltipArea )
|
||||
tooltipArea = variableNameText.gameObject.AddComponent<TooltipArea>();
|
||||
|
||||
tooltipArea.Initialize( m_inspector.TooltipListener, this );
|
||||
variableNameText.raycastTarget = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
TooltipArea tooltipArea = variableNameText.GetComponent<TooltipArea>();
|
||||
if( tooltipArea )
|
||||
{
|
||||
Destroy( tooltipArea );
|
||||
variableNameText.raycastTarget = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnSkinChanged()
|
||||
{
|
||||
if( layoutElement )
|
||||
layoutElement.SetHeight( Skin.LineHeight * HeightMultiplier );
|
||||
|
||||
if( variableNameText )
|
||||
variableNameText.SetSkinText( Skin );
|
||||
|
||||
if( variableNameMask )
|
||||
variableNameMask.color = Skin.BackgroundColor;
|
||||
}
|
||||
|
||||
protected virtual void OnDepthChanged()
|
||||
{
|
||||
if( variableNameText != null )
|
||||
variableNameText.rectTransform.sizeDelta = new Vector2( -Skin.IndentAmount * Depth, 0f );
|
||||
}
|
||||
|
||||
public virtual void Refresh()
|
||||
{
|
||||
RefreshValue();
|
||||
}
|
||||
|
||||
private void RefreshValue()
|
||||
{
|
||||
try
|
||||
{
|
||||
m_value = getter();
|
||||
}
|
||||
catch
|
||||
{
|
||||
#if UNITY_EDITOR || !NETFX_CORE
|
||||
if( BoundVariableType.IsValueType )
|
||||
#else
|
||||
if( BoundVariableType.GetTypeInfo().IsValueType )
|
||||
#endif
|
||||
m_value = Activator.CreateInstance( BoundVariableType );
|
||||
else
|
||||
m_value = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class ExpandableInspectorField : InspectorField
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
protected RectTransform drawArea;
|
||||
|
||||
[SerializeField]
|
||||
private PointerEventListener expandToggle;
|
||||
private RectTransform expandToggleTransform;
|
||||
|
||||
[SerializeField]
|
||||
private LayoutGroup layoutGroup;
|
||||
|
||||
[SerializeField]
|
||||
private Image expandArrow; // Expand Arrow's sprite should look right at 0 rotation
|
||||
#pragma warning restore 0649
|
||||
|
||||
protected readonly List<InspectorField> elements = new List<InspectorField>( 8 );
|
||||
protected readonly List<ExposedMethodField> exposedMethods = new List<ExposedMethodField>();
|
||||
|
||||
protected virtual int Length { get { return elements.Count; } }
|
||||
|
||||
public override bool ShouldRefresh { get { return true; } }
|
||||
|
||||
private bool m_isExpanded = false;
|
||||
public bool IsExpanded
|
||||
{
|
||||
get { return m_isExpanded; }
|
||||
set
|
||||
{
|
||||
m_isExpanded = value;
|
||||
drawArea.gameObject.SetActive( m_isExpanded );
|
||||
|
||||
if( expandArrow != null )
|
||||
expandArrow.rectTransform.localEulerAngles = m_isExpanded ? new Vector3( 0f, 0f, -90f ) : Vector3.zero;
|
||||
|
||||
if( m_isExpanded )
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
private RuntimeInspector.HeaderVisibility m_headerVisibility = RuntimeInspector.HeaderVisibility.Collapsible;
|
||||
public RuntimeInspector.HeaderVisibility HeaderVisibility
|
||||
{
|
||||
get { return m_headerVisibility; }
|
||||
set
|
||||
{
|
||||
if( m_headerVisibility != value )
|
||||
{
|
||||
if( m_headerVisibility == RuntimeInspector.HeaderVisibility.Hidden )
|
||||
{
|
||||
Depth++;
|
||||
layoutGroup.padding.top = Skin.LineHeight;
|
||||
expandToggle.gameObject.SetActive( true );
|
||||
}
|
||||
else if( value == RuntimeInspector.HeaderVisibility.Hidden )
|
||||
{
|
||||
Depth--;
|
||||
layoutGroup.padding.top = 0;
|
||||
expandToggle.gameObject.SetActive( false );
|
||||
}
|
||||
|
||||
m_headerVisibility = value;
|
||||
|
||||
if( m_headerVisibility == RuntimeInspector.HeaderVisibility.Collapsible )
|
||||
{
|
||||
if( expandArrow != null )
|
||||
expandArrow.gameObject.SetActive( true );
|
||||
|
||||
variableNameText.rectTransform.sizeDelta = new Vector2( -( Skin.ExpandArrowSpacing + Skin.LineHeight * 0.5f ), 0f );
|
||||
}
|
||||
else if( m_headerVisibility == RuntimeInspector.HeaderVisibility.AlwaysVisible )
|
||||
{
|
||||
if( expandArrow != null )
|
||||
expandArrow.gameObject.SetActive( false );
|
||||
|
||||
variableNameText.rectTransform.sizeDelta = new Vector2( 0f, 0f );
|
||||
|
||||
if( !m_isExpanded )
|
||||
IsExpanded = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !m_isExpanded )
|
||||
IsExpanded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
expandToggleTransform = (RectTransform) expandToggle.transform;
|
||||
expandToggle.PointerClick += ( eventData ) =>
|
||||
{
|
||||
if( m_headerVisibility == RuntimeInspector.HeaderVisibility.Collapsible )
|
||||
IsExpanded = !m_isExpanded;
|
||||
};
|
||||
|
||||
IsExpanded = m_isExpanded;
|
||||
}
|
||||
|
||||
protected override void OnUnbound()
|
||||
{
|
||||
base.OnUnbound();
|
||||
|
||||
IsExpanded = false;
|
||||
HeaderVisibility = RuntimeInspector.HeaderVisibility.Collapsible;
|
||||
|
||||
ClearElements();
|
||||
}
|
||||
|
||||
protected override void OnInspectorChanged()
|
||||
{
|
||||
base.OnInspectorChanged();
|
||||
|
||||
for( int i = 0; i < elements.Count; i++ )
|
||||
elements[i].Inspector = Inspector;
|
||||
}
|
||||
|
||||
protected override void OnSkinChanged()
|
||||
{
|
||||
base.OnSkinChanged();
|
||||
|
||||
Vector2 expandToggleSizeDelta = expandToggleTransform.sizeDelta;
|
||||
expandToggleSizeDelta.y = Skin.LineHeight;
|
||||
expandToggleTransform.sizeDelta = expandToggleSizeDelta;
|
||||
|
||||
if( m_headerVisibility != RuntimeInspector.HeaderVisibility.Hidden )
|
||||
{
|
||||
layoutGroup.padding.top = Skin.LineHeight;
|
||||
|
||||
if( m_headerVisibility == RuntimeInspector.HeaderVisibility.Collapsible )
|
||||
variableNameText.rectTransform.sizeDelta = new Vector2( -( Skin.ExpandArrowSpacing + Skin.LineHeight * 0.5f ), 0f );
|
||||
}
|
||||
|
||||
if( expandArrow != null )
|
||||
{
|
||||
expandArrow.color = Skin.ExpandArrowColor;
|
||||
expandArrow.rectTransform.anchoredPosition = new Vector2( Skin.LineHeight * 0.25f, 0f );
|
||||
expandArrow.rectTransform.sizeDelta = new Vector2( Skin.LineHeight * 0.5f, Skin.LineHeight * 0.5f );
|
||||
}
|
||||
|
||||
for( int i = 0; i < elements.Count; i++ )
|
||||
elements[i].Skin = Skin;
|
||||
|
||||
for( int i = 0; i < exposedMethods.Count; i++ )
|
||||
exposedMethods[i].Skin = Skin;
|
||||
}
|
||||
|
||||
protected override void OnDepthChanged()
|
||||
{
|
||||
Vector2 expandToggleSizeDelta = expandToggleTransform.sizeDelta;
|
||||
expandToggleSizeDelta.x = -Skin.IndentAmount * Depth;
|
||||
expandToggleTransform.sizeDelta = expandToggleSizeDelta;
|
||||
|
||||
for( int i = 0; i < elements.Count; i++ )
|
||||
elements[i].Depth = Depth + 1;
|
||||
}
|
||||
|
||||
protected void RegenerateElements()
|
||||
{
|
||||
if( elements.Count > 0 || exposedMethods.Count > 0 )
|
||||
ClearElements();
|
||||
|
||||
if( Depth < Inspector.NestLimit )
|
||||
{
|
||||
drawArea.gameObject.SetActive( true );
|
||||
GenerateElements();
|
||||
GenerateExposedMethodButtons();
|
||||
drawArea.gameObject.SetActive( m_isExpanded );
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void GenerateElements();
|
||||
|
||||
private void GenerateExposedMethodButtons()
|
||||
{
|
||||
if( Inspector.ShowRemoveComponentButton && typeof( Component ).IsAssignableFrom( BoundVariableType ) && !typeof( Transform ).IsAssignableFrom( BoundVariableType ) )
|
||||
CreateExposedMethodButton( GameObjectField.removeComponentMethod, () => this, ( value ) => { } );
|
||||
|
||||
ExposedMethod[] methods = BoundVariableType.GetExposedMethods();
|
||||
if( methods != null )
|
||||
{
|
||||
bool isInitialized = Value != null && !Value.Equals( null );
|
||||
for( int i = 0; i < methods.Length; i++ )
|
||||
{
|
||||
ExposedMethod method = methods[i];
|
||||
if( ( isInitialized && method.VisibleWhenInitialized ) || ( !isInitialized && method.VisibleWhenUninitialized ) )
|
||||
CreateExposedMethodButton( method, () => Value, ( value ) => Value = value );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void ClearElements()
|
||||
{
|
||||
for( int i = 0; i < elements.Count; i++ )
|
||||
elements[i].Unbind();
|
||||
|
||||
for( int i = 0; i < exposedMethods.Count; i++ )
|
||||
exposedMethods[i].Unbind();
|
||||
|
||||
elements.Clear();
|
||||
exposedMethods.Clear();
|
||||
}
|
||||
|
||||
public override void Refresh()
|
||||
{
|
||||
base.Refresh();
|
||||
|
||||
if( m_isExpanded )
|
||||
{
|
||||
if( Length != elements.Count )
|
||||
RegenerateElements();
|
||||
|
||||
for( int i = 0; i < elements.Count; i++ )
|
||||
{
|
||||
if( elements[i].ShouldRefresh )
|
||||
elements[i].Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public InspectorField CreateDrawerForComponent( Component component, string variableName = null )
|
||||
{
|
||||
InspectorField variableDrawer = Inspector.CreateDrawerForType( component.GetType(), drawArea, Depth + 1, false );
|
||||
if( variableDrawer != null )
|
||||
{
|
||||
if( variableName == null )
|
||||
variableName = component.GetType().Name + " component";
|
||||
|
||||
variableDrawer.BindTo( component.GetType(), string.Empty, () => component, ( value ) => { } );
|
||||
variableDrawer.NameRaw = variableName;
|
||||
|
||||
elements.Add( variableDrawer );
|
||||
}
|
||||
|
||||
return variableDrawer;
|
||||
}
|
||||
|
||||
public InspectorField CreateDrawerForVariable( MemberInfo variable, string variableName = null )
|
||||
{
|
||||
Type variableType = variable is FieldInfo ? ( (FieldInfo) variable ).FieldType : ( (PropertyInfo) variable ).PropertyType;
|
||||
InspectorField variableDrawer = Inspector.CreateDrawerForType( variableType, drawArea, Depth + 1, true, variable );
|
||||
if( variableDrawer != null )
|
||||
{
|
||||
variableDrawer.BindTo( this, variable, variableName == null ? null : string.Empty );
|
||||
if( variableName != null )
|
||||
variableDrawer.NameRaw = variableName;
|
||||
|
||||
elements.Add( variableDrawer );
|
||||
}
|
||||
|
||||
return variableDrawer;
|
||||
}
|
||||
|
||||
public InspectorField CreateDrawer( Type variableType, string variableName, Getter getter, Setter setter, bool drawObjectsAsFields = true )
|
||||
{
|
||||
InspectorField variableDrawer = Inspector.CreateDrawerForType( variableType, drawArea, Depth + 1, drawObjectsAsFields );
|
||||
if( variableDrawer != null )
|
||||
{
|
||||
variableDrawer.BindTo( variableType, variableName == null ? null : string.Empty, getter, setter );
|
||||
if( variableName != null )
|
||||
variableDrawer.NameRaw = variableName;
|
||||
|
||||
elements.Add( variableDrawer );
|
||||
}
|
||||
|
||||
return variableDrawer;
|
||||
}
|
||||
|
||||
public ExposedMethodField CreateExposedMethodButton( ExposedMethod method, Getter getter, Setter setter )
|
||||
{
|
||||
ExposedMethodField methodDrawer = (ExposedMethodField) Inspector.CreateDrawerForType( typeof( ExposedMethod ), drawArea, Depth + 1, false );
|
||||
if( methodDrawer != null )
|
||||
{
|
||||
methodDrawer.BindTo( typeof( ExposedMethod ), string.Empty, getter, setter );
|
||||
methodDrawer.SetBoundMethod( method );
|
||||
|
||||
exposedMethods.Add( methodDrawer );
|
||||
}
|
||||
|
||||
return methodDrawer;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c6387a22a96c78e48948b1e7d478c22f
|
||||
timeCreated: 1505741432
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,90 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class NumberField : InspectorField
|
||||
{
|
||||
private static readonly HashSet<Type> supportedTypes = new HashSet<Type>()
|
||||
{
|
||||
typeof( int ), typeof( uint ), typeof( long ), typeof( ulong ),
|
||||
typeof( byte ), typeof( sbyte ), typeof( short ), typeof( ushort ), typeof( char ),
|
||||
typeof( float ), typeof( double ), typeof( decimal )
|
||||
};
|
||||
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
protected BoundInputField input;
|
||||
#pragma warning restore 0649
|
||||
|
||||
protected INumberHandler numberHandler;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
input.Initialize();
|
||||
input.OnValueChanged += OnValueChanged;
|
||||
input.OnValueSubmitted += OnValueSubmitted;
|
||||
input.DefaultEmptyValue = "0";
|
||||
}
|
||||
|
||||
public override bool SupportsType( Type type )
|
||||
{
|
||||
return supportedTypes.Contains( type );
|
||||
}
|
||||
|
||||
protected override void OnBound( MemberInfo variable )
|
||||
{
|
||||
base.OnBound( variable );
|
||||
|
||||
if( BoundVariableType == typeof( float ) || BoundVariableType == typeof( double ) || BoundVariableType == typeof( decimal ) )
|
||||
input.BackingField.contentType = InputField.ContentType.DecimalNumber;
|
||||
else
|
||||
input.BackingField.contentType = InputField.ContentType.IntegerNumber;
|
||||
|
||||
numberHandler = NumberHandlers.Get( BoundVariableType );
|
||||
input.Text = numberHandler.ToString( Value );
|
||||
}
|
||||
|
||||
protected virtual bool OnValueChanged( BoundInputField source, string input )
|
||||
{
|
||||
object value;
|
||||
if( numberHandler.TryParse( input, out value ) )
|
||||
{
|
||||
Value = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool OnValueSubmitted( BoundInputField source, string input )
|
||||
{
|
||||
Inspector.RefreshDelayed();
|
||||
return OnValueChanged( source, input );
|
||||
}
|
||||
|
||||
protected override void OnSkinChanged()
|
||||
{
|
||||
base.OnSkinChanged();
|
||||
input.Skin = Skin;
|
||||
|
||||
Vector2 rightSideAnchorMin = new Vector2( Skin.LabelWidthPercentage, 0f );
|
||||
variableNameMask.rectTransform.anchorMin = rightSideAnchorMin;
|
||||
( (RectTransform) input.transform ).anchorMin = rightSideAnchorMin;
|
||||
}
|
||||
|
||||
public override void Refresh()
|
||||
{
|
||||
object prevVal = Value;
|
||||
base.Refresh();
|
||||
|
||||
if( !numberHandler.ValuesAreEqual( Value, prevVal ) )
|
||||
input.Text = numberHandler.ToString( Value );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 316499031f1afeb489319ec05bb84fd2
|
||||
timeCreated: 1505976834
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class NumberRangeField : NumberField
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
private BoundSlider slider;
|
||||
#pragma warning restore 0649
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
slider.OnValueChanged += OnSliderValueChanged;
|
||||
}
|
||||
|
||||
public override bool CanBindTo( Type type, MemberInfo variable )
|
||||
{
|
||||
return variable != null && variable.HasAttribute<RangeAttribute>();
|
||||
}
|
||||
|
||||
protected override void OnBound( MemberInfo variable )
|
||||
{
|
||||
base.OnBound( variable );
|
||||
|
||||
RangeAttribute rangeAttribute = variable.GetAttribute<RangeAttribute>();
|
||||
slider.SetRange( Mathf.Max( rangeAttribute.min, numberHandler.MinValue ), Mathf.Min( rangeAttribute.max, numberHandler.MaxValue ) );
|
||||
slider.BackingField.wholeNumbers = BoundVariableType != typeof( float ) && BoundVariableType != typeof( double ) && BoundVariableType != typeof( decimal );
|
||||
}
|
||||
|
||||
protected override bool OnValueChanged( BoundInputField source, string input )
|
||||
{
|
||||
object value;
|
||||
if( numberHandler.TryParse( input, out value ) )
|
||||
{
|
||||
float fvalue = numberHandler.ConvertToFloat( value );
|
||||
if( fvalue >= slider.BackingField.minValue && fvalue <= slider.BackingField.maxValue )
|
||||
{
|
||||
Value = value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void OnSliderValueChanged( BoundSlider source, float value )
|
||||
{
|
||||
if( input.BackingField.isFocused )
|
||||
return;
|
||||
|
||||
Value = numberHandler.ConvertFromFloat( value );
|
||||
input.Text = numberHandler.ToString( Value );
|
||||
Inspector.RefreshDelayed();
|
||||
}
|
||||
|
||||
protected override void OnSkinChanged()
|
||||
{
|
||||
base.OnSkinChanged();
|
||||
slider.Skin = Skin;
|
||||
|
||||
float inputFieldWidth = ( 1f - Skin.LabelWidthPercentage ) / 3f;
|
||||
Vector2 rightSideAnchorMin = new Vector2( Skin.LabelWidthPercentage, 0f );
|
||||
variableNameMask.rectTransform.anchorMin = rightSideAnchorMin;
|
||||
( (RectTransform) slider.transform ).anchorMin = rightSideAnchorMin;
|
||||
( (RectTransform) slider.transform ).anchorMax = new Vector2( 1f - inputFieldWidth, 1f );
|
||||
( (RectTransform) input.transform ).anchorMin = new Vector2( 1f - inputFieldWidth, 0f );
|
||||
}
|
||||
|
||||
public override void Refresh()
|
||||
{
|
||||
base.Refresh();
|
||||
slider.Value = numberHandler.ConvertToFloat( Value );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 830283bd6fa07444680747844639f36a
|
||||
timeCreated: 1505976834
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,175 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class ObjectField : ExpandableInspectorField
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
private Button initializeObjectButton;
|
||||
#pragma warning restore 0649
|
||||
|
||||
private bool elementsInitialized = false;
|
||||
private IRuntimeInspectorCustomEditor customEditor;
|
||||
|
||||
protected override int Length
|
||||
{
|
||||
get
|
||||
{
|
||||
if( Value.IsNull() )
|
||||
{
|
||||
if( !initializeObjectButton.gameObject.activeSelf )
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( initializeObjectButton.gameObject.activeSelf )
|
||||
return -1;
|
||||
|
||||
if( !elementsInitialized )
|
||||
{
|
||||
elementsInitialized = true;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return elements.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
initializeObjectButton.onClick.AddListener( InitializeObject );
|
||||
}
|
||||
|
||||
public override bool SupportsType( Type type )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnBound( MemberInfo variable )
|
||||
{
|
||||
elementsInitialized = false;
|
||||
base.OnBound( variable );
|
||||
}
|
||||
|
||||
protected override void GenerateElements()
|
||||
{
|
||||
if( Value.IsNull() )
|
||||
{
|
||||
initializeObjectButton.gameObject.SetActive( CanInitializeNewObject() );
|
||||
return;
|
||||
}
|
||||
|
||||
initializeObjectButton.gameObject.SetActive( false );
|
||||
|
||||
if( ( customEditor = RuntimeInspectorUtils.GetCustomEditor( Value.GetType() ) ) != null )
|
||||
customEditor.GenerateElements( this );
|
||||
else
|
||||
CreateDrawersForVariables();
|
||||
}
|
||||
|
||||
protected override void ClearElements()
|
||||
{
|
||||
base.ClearElements();
|
||||
|
||||
if( customEditor != null )
|
||||
{
|
||||
customEditor.Cleanup();
|
||||
customEditor = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnSkinChanged()
|
||||
{
|
||||
base.OnSkinChanged();
|
||||
initializeObjectButton.SetSkinButton( Skin );
|
||||
}
|
||||
|
||||
public override void Refresh()
|
||||
{
|
||||
base.Refresh();
|
||||
|
||||
if( customEditor != null )
|
||||
customEditor.Refresh();
|
||||
}
|
||||
|
||||
public void CreateDrawersForVariables( params string[] variables )
|
||||
{
|
||||
if( variables == null || variables.Length == 0 )
|
||||
{
|
||||
foreach( MemberInfo variable in Inspector.GetExposedVariablesForType( Value.GetType() ) )
|
||||
CreateDrawerForVariable( variable );
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach( MemberInfo variable in Inspector.GetExposedVariablesForType( Value.GetType() ) )
|
||||
{
|
||||
if( Array.IndexOf( variables, variable.Name ) >= 0 )
|
||||
CreateDrawerForVariable( variable );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void CreateDrawersForVariablesExcluding( params string[] variablesToExclude )
|
||||
{
|
||||
if( variablesToExclude == null || variablesToExclude.Length == 0 )
|
||||
{
|
||||
foreach( MemberInfo variable in Inspector.GetExposedVariablesForType( Value.GetType() ) )
|
||||
CreateDrawerForVariable( variable );
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach( MemberInfo variable in Inspector.GetExposedVariablesForType( Value.GetType() ) )
|
||||
{
|
||||
if( Array.IndexOf( variablesToExclude, variable.Name ) < 0 )
|
||||
CreateDrawerForVariable( variable );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool CanInitializeNewObject()
|
||||
{
|
||||
#if UNITY_EDITOR || !NETFX_CORE
|
||||
if( BoundVariableType.IsAbstract || BoundVariableType.IsInterface )
|
||||
#else
|
||||
if( BoundVariableType.GetTypeInfo().IsAbstract || BoundVariableType.GetTypeInfo().IsInterface )
|
||||
#endif
|
||||
return false;
|
||||
|
||||
if( typeof( ScriptableObject ).IsAssignableFrom( BoundVariableType ) )
|
||||
return true;
|
||||
|
||||
if( typeof( UnityEngine.Object ).IsAssignableFrom( BoundVariableType ) )
|
||||
return false;
|
||||
|
||||
if( BoundVariableType.IsArray )
|
||||
return false;
|
||||
|
||||
#if UNITY_EDITOR || !NETFX_CORE
|
||||
if( BoundVariableType.IsGenericType && BoundVariableType.GetGenericTypeDefinition() == typeof( List<> ) )
|
||||
#else
|
||||
if( BoundVariableType.GetTypeInfo().IsGenericType && BoundVariableType.GetGenericTypeDefinition() == typeof( List<> ) )
|
||||
#endif
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void InitializeObject()
|
||||
{
|
||||
if( CanInitializeNewObject() )
|
||||
{
|
||||
Value = BoundVariableType.Instantiate();
|
||||
|
||||
RegenerateElements();
|
||||
IsExpanded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d38ee2071d272894a98794fdb1e97dbb
|
||||
timeCreated: 1506081137
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,132 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class ObjectReferenceField : InspectorField, IDropHandler
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
private RectTransform referencePickerArea;
|
||||
|
||||
[SerializeField]
|
||||
private PointerEventListener input;
|
||||
|
||||
[SerializeField]
|
||||
private PointerEventListener inspectReferenceButton;
|
||||
private Image inspectReferenceImage;
|
||||
|
||||
[SerializeField]
|
||||
protected Image background;
|
||||
|
||||
[SerializeField]
|
||||
protected Text referenceNameText;
|
||||
#pragma warning restore 0649
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
input.PointerClick += ShowReferencePicker;
|
||||
|
||||
if( inspectReferenceButton != null )
|
||||
{
|
||||
inspectReferenceButton.PointerClick += InspectReference;
|
||||
inspectReferenceImage = inspectReferenceButton.GetComponent<Image>();
|
||||
}
|
||||
}
|
||||
|
||||
public override bool SupportsType( Type type )
|
||||
{
|
||||
return typeof( Object ).IsAssignableFrom( type );
|
||||
}
|
||||
|
||||
private void ShowReferencePicker( PointerEventData eventData )
|
||||
{
|
||||
Object[] allReferences = Resources.FindObjectsOfTypeAll( BoundVariableType );
|
||||
|
||||
ObjectReferencePicker.Instance.Skin = Inspector.Skin;
|
||||
ObjectReferencePicker.Instance.Show(
|
||||
( reference ) => OnReferenceChanged( (Object) reference ), null,
|
||||
( reference ) => (Object) reference ? ( (Object) reference ).name : "None",
|
||||
( reference ) => reference.GetNameWithType(),
|
||||
allReferences, (Object) Value, true, "Select " + BoundVariableType.Name, Inspector.Canvas );
|
||||
}
|
||||
|
||||
private void InspectReference( PointerEventData eventData )
|
||||
{
|
||||
if( Value != null && !Value.Equals( null ) )
|
||||
{
|
||||
if( Value is Component )
|
||||
Inspector.InspectInternal( ( (Component) Value ).gameObject );
|
||||
else
|
||||
Inspector.InspectInternal( Value );
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnBound( MemberInfo variable )
|
||||
{
|
||||
base.OnBound( variable );
|
||||
OnReferenceChanged( (Object) Value );
|
||||
}
|
||||
|
||||
protected virtual void OnReferenceChanged( Object reference )
|
||||
{
|
||||
if( (Object) Value != reference )
|
||||
Value = reference;
|
||||
|
||||
if( referenceNameText != null )
|
||||
referenceNameText.text = reference.GetNameWithType( BoundVariableType );
|
||||
|
||||
if( inspectReferenceButton != null )
|
||||
inspectReferenceButton.gameObject.SetActive( Value != null && !Value.Equals( null ) );
|
||||
|
||||
Inspector.RefreshDelayed();
|
||||
}
|
||||
|
||||
public void OnDrop( PointerEventData eventData )
|
||||
{
|
||||
Object assignableObject = (Object) RuntimeInspectorUtils.GetAssignableObjectFromDraggedReferenceItem( eventData, BoundVariableType );
|
||||
if( assignableObject )
|
||||
OnReferenceChanged( assignableObject );
|
||||
}
|
||||
|
||||
protected override void OnSkinChanged()
|
||||
{
|
||||
base.OnSkinChanged();
|
||||
|
||||
background.color = Skin.InputFieldNormalBackgroundColor.Tint( 0.075f );
|
||||
|
||||
referenceNameText.SetSkinInputFieldText( Skin );
|
||||
|
||||
referenceNameText.resizeTextMinSize = Mathf.Max( 2, Skin.FontSize - 2 );
|
||||
referenceNameText.resizeTextMaxSize = Skin.FontSize;
|
||||
|
||||
if( inspectReferenceImage )
|
||||
{
|
||||
inspectReferenceImage.color = Skin.TextColor.Tint( 0.1f );
|
||||
inspectReferenceImage.GetComponent<LayoutElement>().SetWidth( Mathf.Max( Skin.LineHeight - 8, 6 ) );
|
||||
}
|
||||
|
||||
if( referencePickerArea )
|
||||
{
|
||||
Vector2 rightSideAnchorMin = new Vector2( Skin.LabelWidthPercentage, 0f );
|
||||
variableNameMask.rectTransform.anchorMin = rightSideAnchorMin;
|
||||
referencePickerArea.anchorMin = rightSideAnchorMin;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Refresh()
|
||||
{
|
||||
object lastValue = Value;
|
||||
base.Refresh();
|
||||
|
||||
if( lastValue != Value )
|
||||
OnReferenceChanged( (Object) Value );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8302e5f6c0868094aa51524db7212b35
|
||||
timeCreated: 1505976834
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,217 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class RectField : InspectorField
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
private BoundInputField inputX;
|
||||
|
||||
[SerializeField]
|
||||
private BoundInputField inputY;
|
||||
|
||||
[SerializeField]
|
||||
private BoundInputField inputW;
|
||||
|
||||
[SerializeField]
|
||||
private BoundInputField inputH;
|
||||
|
||||
[SerializeField]
|
||||
private Text labelX;
|
||||
|
||||
[SerializeField]
|
||||
private Text labelY;
|
||||
|
||||
[SerializeField]
|
||||
private Text labelW;
|
||||
|
||||
[SerializeField]
|
||||
private Text labelH;
|
||||
#pragma warning restore 0649
|
||||
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
private bool isRectInt;
|
||||
#endif
|
||||
|
||||
protected override float HeightMultiplier { get { return 2f; } }
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
inputX.Initialize();
|
||||
inputY.Initialize();
|
||||
inputW.Initialize();
|
||||
inputH.Initialize();
|
||||
|
||||
inputX.OnValueChanged += OnValueChanged;
|
||||
inputY.OnValueChanged += OnValueChanged;
|
||||
inputW.OnValueChanged += OnValueChanged;
|
||||
inputH.OnValueChanged += OnValueChanged;
|
||||
|
||||
inputX.OnValueSubmitted += OnValueSubmitted;
|
||||
inputY.OnValueSubmitted += OnValueSubmitted;
|
||||
inputW.OnValueSubmitted += OnValueSubmitted;
|
||||
inputH.OnValueSubmitted += OnValueSubmitted;
|
||||
|
||||
inputX.DefaultEmptyValue = "0";
|
||||
inputY.DefaultEmptyValue = "0";
|
||||
inputW.DefaultEmptyValue = "0";
|
||||
inputH.DefaultEmptyValue = "0";
|
||||
}
|
||||
|
||||
public override bool SupportsType( Type type )
|
||||
{
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
if( type == typeof( RectInt ) )
|
||||
return true;
|
||||
#endif
|
||||
return type == typeof( Rect );
|
||||
}
|
||||
|
||||
protected override void OnBound( MemberInfo variable )
|
||||
{
|
||||
base.OnBound( variable );
|
||||
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
isRectInt = BoundVariableType == typeof( RectInt );
|
||||
if( isRectInt )
|
||||
{
|
||||
RectInt val = (RectInt) Value;
|
||||
inputX.Text = val.x.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
inputY.Text = val.y.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
inputW.Text = val.width.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
inputH.Text = val.height.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Rect val = (Rect) Value;
|
||||
inputX.Text = val.x.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
inputY.Text = val.y.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
inputW.Text = val.width.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
inputH.Text = val.height.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
}
|
||||
}
|
||||
|
||||
private bool OnValueChanged( BoundInputField source, string input )
|
||||
{
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
if( isRectInt )
|
||||
{
|
||||
int value;
|
||||
if( int.TryParse( input, NumberStyles.Integer, RuntimeInspectorUtils.numberFormat, out value ) )
|
||||
{
|
||||
RectInt val = (RectInt) Value;
|
||||
if( source == inputX )
|
||||
val.x = value;
|
||||
else if( source == inputY )
|
||||
val.y = value;
|
||||
else if( source == inputW )
|
||||
val.width = value;
|
||||
else
|
||||
val.height = value;
|
||||
|
||||
Value = val;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
float value;
|
||||
if( float.TryParse( input, NumberStyles.Float, RuntimeInspectorUtils.numberFormat, out value ) )
|
||||
{
|
||||
Rect val = (Rect) Value;
|
||||
if( source == inputX )
|
||||
val.x = value;
|
||||
else if( source == inputY )
|
||||
val.y = value;
|
||||
else if( source == inputW )
|
||||
val.width = value;
|
||||
else
|
||||
val.height = value;
|
||||
|
||||
Value = val;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool OnValueSubmitted( BoundInputField source, string input )
|
||||
{
|
||||
Inspector.RefreshDelayed();
|
||||
return OnValueChanged( source, input );
|
||||
}
|
||||
|
||||
protected override void OnSkinChanged()
|
||||
{
|
||||
base.OnSkinChanged();
|
||||
|
||||
labelX.SetSkinText( Skin );
|
||||
labelY.SetSkinText( Skin );
|
||||
labelW.SetSkinText( Skin );
|
||||
labelH.SetSkinText( Skin );
|
||||
|
||||
inputX.Skin = Skin;
|
||||
inputY.Skin = Skin;
|
||||
inputW.Skin = Skin;
|
||||
inputH.Skin = Skin;
|
||||
|
||||
float inputFieldWidth = ( 1f - Skin.LabelWidthPercentage ) / 3f;
|
||||
Vector2 rightSideAnchorMin = new Vector2( Skin.LabelWidthPercentage + inputFieldWidth, 0f );
|
||||
Vector2 rightSideAnchorMax = new Vector2( Skin.LabelWidthPercentage + 2f * inputFieldWidth, 1f );
|
||||
variableNameMask.rectTransform.anchorMin = rightSideAnchorMin;
|
||||
( (RectTransform) inputX.transform ).SetAnchorMinMaxInputField( labelX.rectTransform, new Vector2( rightSideAnchorMin.x, 0.5f ), rightSideAnchorMax );
|
||||
( (RectTransform) inputW.transform ).SetAnchorMinMaxInputField( labelW.rectTransform, rightSideAnchorMin, new Vector2( rightSideAnchorMax.x, 0.5f ) );
|
||||
|
||||
rightSideAnchorMin.x += inputFieldWidth;
|
||||
rightSideAnchorMax.x = 1f;
|
||||
( (RectTransform) inputY.transform ).SetAnchorMinMaxInputField( labelY.rectTransform, new Vector2( rightSideAnchorMin.x, 0.5f ), rightSideAnchorMax );
|
||||
( (RectTransform) inputH.transform ).SetAnchorMinMaxInputField( labelH.rectTransform, rightSideAnchorMin, new Vector2( rightSideAnchorMax.x, 0.5f ) );
|
||||
}
|
||||
|
||||
public override void Refresh()
|
||||
{
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
if( isRectInt )
|
||||
{
|
||||
RectInt prevVal = (RectInt) Value;
|
||||
base.Refresh();
|
||||
RectInt val = (RectInt) Value;
|
||||
|
||||
if( val.x != prevVal.x )
|
||||
inputX.Text = val.x.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
if( val.y != prevVal.y )
|
||||
inputY.Text = val.y.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
if( val.width != prevVal.width )
|
||||
inputW.Text = val.width.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
if( val.height != prevVal.height )
|
||||
inputH.Text = val.height.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Rect prevVal = (Rect) Value;
|
||||
base.Refresh();
|
||||
Rect val = (Rect) Value;
|
||||
|
||||
if( val.x != prevVal.x )
|
||||
inputX.Text = val.x.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
if( val.y != prevVal.y )
|
||||
inputY.Text = val.y.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
if( val.width != prevVal.width )
|
||||
inputW.Text = val.width.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
if( val.height != prevVal.height )
|
||||
inputH.Text = val.height.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1ce38a59b3c65d74da714ee85231e8b7
|
||||
timeCreated: 1505741432
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,116 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class StringField : InspectorField
|
||||
{
|
||||
public enum Mode { OnValueChange = 0, OnSubmit = 1 };
|
||||
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
private BoundInputField input;
|
||||
#pragma warning restore 0649
|
||||
|
||||
private Mode m_setterMode = Mode.OnValueChange;
|
||||
public Mode SetterMode
|
||||
{
|
||||
get { return m_setterMode; }
|
||||
set
|
||||
{
|
||||
m_setterMode = value;
|
||||
input.CacheTextOnValueChange = m_setterMode == Mode.OnValueChange;
|
||||
}
|
||||
}
|
||||
|
||||
private int lineCount = 1;
|
||||
protected override float HeightMultiplier { get { return lineCount; } }
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
input.Initialize();
|
||||
input.OnValueChanged += OnValueChanged;
|
||||
input.OnValueSubmitted += OnValueSubmitted;
|
||||
input.DefaultEmptyValue = string.Empty;
|
||||
}
|
||||
|
||||
public override bool SupportsType( Type type )
|
||||
{
|
||||
return type == typeof( string );
|
||||
}
|
||||
|
||||
protected override void OnBound( MemberInfo variable )
|
||||
{
|
||||
base.OnBound( variable );
|
||||
|
||||
int prevLineCount = lineCount;
|
||||
if( variable == null )
|
||||
lineCount = 1;
|
||||
else
|
||||
{
|
||||
MultilineAttribute multilineAttribute = variable.GetAttribute<MultilineAttribute>();
|
||||
if( multilineAttribute != null )
|
||||
lineCount = Mathf.Max( 1, multilineAttribute.lines );
|
||||
else if( variable.HasAttribute<TextAreaAttribute>() )
|
||||
lineCount = 3;
|
||||
else
|
||||
lineCount = 1;
|
||||
}
|
||||
|
||||
if( prevLineCount != lineCount )
|
||||
{
|
||||
input.BackingField.lineType = lineCount > 1 ? InputField.LineType.MultiLineNewline : InputField.LineType.SingleLine;
|
||||
input.BackingField.textComponent.alignment = lineCount > 1 ? TextAnchor.UpperLeft : TextAnchor.MiddleLeft;
|
||||
|
||||
OnSkinChanged();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnUnbound()
|
||||
{
|
||||
base.OnUnbound();
|
||||
SetterMode = Mode.OnValueChange;
|
||||
}
|
||||
|
||||
private bool OnValueChanged( BoundInputField source, string input )
|
||||
{
|
||||
if( m_setterMode == Mode.OnValueChange )
|
||||
Value = input;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool OnValueSubmitted( BoundInputField source, string input )
|
||||
{
|
||||
if( m_setterMode == Mode.OnSubmit )
|
||||
Value = input;
|
||||
|
||||
Inspector.RefreshDelayed();
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnSkinChanged()
|
||||
{
|
||||
base.OnSkinChanged();
|
||||
input.Skin = Skin;
|
||||
|
||||
Vector2 rightSideAnchorMin = new Vector2( Skin.LabelWidthPercentage, 0f );
|
||||
variableNameMask.rectTransform.anchorMin = rightSideAnchorMin;
|
||||
( (RectTransform) input.transform ).anchorMin = rightSideAnchorMin;
|
||||
}
|
||||
|
||||
public override void Refresh()
|
||||
{
|
||||
base.Refresh();
|
||||
|
||||
if( Value == null )
|
||||
input.Text = string.Empty;
|
||||
else
|
||||
input.Text = (string) Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa5229e47c2e2344dbdb0011b4780fd7
|
||||
timeCreated: 1505741432
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,36 @@
|
||||
using System;
|
||||
#if !UNITY_EDITOR && NETFX_CORE
|
||||
using System.Reflection;
|
||||
#endif
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class TextureReferenceField : ObjectReferenceField
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
private RawImage referencePreview;
|
||||
#pragma warning restore 0649
|
||||
|
||||
protected override float HeightMultiplier { get { return 2f; } }
|
||||
|
||||
public override bool SupportsType( Type type )
|
||||
{
|
||||
return typeof( Texture ).IsAssignableFrom( type ) || typeof( Sprite ).IsAssignableFrom( type );
|
||||
}
|
||||
|
||||
protected override void OnReferenceChanged( Object reference )
|
||||
{
|
||||
base.OnReferenceChanged( reference );
|
||||
|
||||
referenceNameText.gameObject.SetActive( !reference );
|
||||
|
||||
Texture tex = reference.GetTexture();
|
||||
referencePreview.enabled = tex != null;
|
||||
referencePreview.texture = tex;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fa8ca8ca537a8974691e2a421bd65159
|
||||
timeCreated: 1505976834
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class TransformField : ExpandableInspectorField
|
||||
{
|
||||
protected override int Length { get { return 3; } } // localPosition, localEulerAngles, localScale
|
||||
|
||||
private PropertyInfo positionProp, rotationProp, scaleProp;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
positionProp = typeof( Transform ).GetProperty( "localPosition" );
|
||||
rotationProp = typeof( Transform ).GetProperty( "localEulerAngles" );
|
||||
scaleProp = typeof( Transform ).GetProperty( "localScale" );
|
||||
}
|
||||
|
||||
public override bool SupportsType( Type type )
|
||||
{
|
||||
return type == typeof( Transform );
|
||||
}
|
||||
|
||||
protected override void GenerateElements()
|
||||
{
|
||||
CreateDrawerForVariable( positionProp, "Position" );
|
||||
CreateDrawerForVariable( rotationProp, "Rotation" );
|
||||
CreateDrawerForVariable( scaleProp, "Scale" );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0f03ec8a5368c074ab74980eda08414f
|
||||
timeCreated: 1506081137
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,169 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class Vector2Field : InspectorField
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
private BoundInputField inputX;
|
||||
|
||||
[SerializeField]
|
||||
private BoundInputField inputY;
|
||||
|
||||
[SerializeField]
|
||||
private Text labelX;
|
||||
|
||||
[SerializeField]
|
||||
private Text labelY;
|
||||
#pragma warning restore 0649
|
||||
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
private bool isVector2Int;
|
||||
#endif
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
inputX.Initialize();
|
||||
inputY.Initialize();
|
||||
|
||||
inputX.OnValueChanged += OnValueChanged;
|
||||
inputY.OnValueChanged += OnValueChanged;
|
||||
|
||||
inputX.OnValueSubmitted += OnValueSubmitted;
|
||||
inputY.OnValueSubmitted += OnValueSubmitted;
|
||||
|
||||
inputX.DefaultEmptyValue = "0";
|
||||
inputY.DefaultEmptyValue = "0";
|
||||
}
|
||||
|
||||
public override bool SupportsType( Type type )
|
||||
{
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
if( type == typeof( Vector2Int ) )
|
||||
return true;
|
||||
#endif
|
||||
return type == typeof( Vector2 );
|
||||
}
|
||||
|
||||
protected override void OnBound( MemberInfo variable )
|
||||
{
|
||||
base.OnBound( variable );
|
||||
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
isVector2Int = BoundVariableType == typeof( Vector2Int );
|
||||
if( isVector2Int )
|
||||
{
|
||||
Vector2Int val = (Vector2Int) Value;
|
||||
inputX.Text = val.x.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
inputY.Text = val.y.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Vector2 val = (Vector2) Value;
|
||||
inputX.Text = val.x.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
inputY.Text = val.y.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
}
|
||||
}
|
||||
|
||||
private bool OnValueChanged( BoundInputField source, string input )
|
||||
{
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
if( isVector2Int )
|
||||
{
|
||||
int value;
|
||||
if( int.TryParse( input, NumberStyles.Integer, RuntimeInspectorUtils.numberFormat, out value ) )
|
||||
{
|
||||
Vector2Int val = (Vector2Int) Value;
|
||||
if( source == inputX )
|
||||
val.x = value;
|
||||
else
|
||||
val.y = value;
|
||||
|
||||
Value = val;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
float value;
|
||||
if( float.TryParse( input, NumberStyles.Float, RuntimeInspectorUtils.numberFormat, out value ) )
|
||||
{
|
||||
Vector2 val = (Vector2) Value;
|
||||
if( source == inputX )
|
||||
val.x = value;
|
||||
else
|
||||
val.y = value;
|
||||
|
||||
Value = val;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool OnValueSubmitted( BoundInputField source, string input )
|
||||
{
|
||||
Inspector.RefreshDelayed();
|
||||
return OnValueChanged( source, input );
|
||||
}
|
||||
|
||||
protected override void OnSkinChanged()
|
||||
{
|
||||
base.OnSkinChanged();
|
||||
|
||||
labelX.SetSkinText( Skin );
|
||||
labelY.SetSkinText( Skin );
|
||||
|
||||
inputX.Skin = Skin;
|
||||
inputY.Skin = Skin;
|
||||
|
||||
float inputFieldWidth = ( 1f - Skin.LabelWidthPercentage ) / 3f;
|
||||
Vector2 rightSideAnchorMin = new Vector2( Skin.LabelWidthPercentage + inputFieldWidth, 0f );
|
||||
Vector2 rightSideAnchorMax = new Vector2( Skin.LabelWidthPercentage + 2f * inputFieldWidth, 1f );
|
||||
variableNameMask.rectTransform.anchorMin = rightSideAnchorMin;
|
||||
( (RectTransform) inputX.transform ).SetAnchorMinMaxInputField( labelX.rectTransform, rightSideAnchorMin, rightSideAnchorMax );
|
||||
|
||||
rightSideAnchorMin.x += inputFieldWidth;
|
||||
rightSideAnchorMax.x = 1f;
|
||||
( (RectTransform) inputY.transform ).SetAnchorMinMaxInputField( labelY.rectTransform, rightSideAnchorMin, rightSideAnchorMax );
|
||||
}
|
||||
|
||||
public override void Refresh()
|
||||
{
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
if( isVector2Int )
|
||||
{
|
||||
Vector2Int prevVal = (Vector2Int) Value;
|
||||
base.Refresh();
|
||||
Vector2Int val = (Vector2Int) Value;
|
||||
|
||||
if( val.x != prevVal.x )
|
||||
inputX.Text = val.x.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
if( val.y != prevVal.y )
|
||||
inputY.Text = val.y.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Vector2 prevVal = (Vector2) Value;
|
||||
base.Refresh();
|
||||
Vector2 val = (Vector2) Value;
|
||||
|
||||
if( val.x != prevVal.x )
|
||||
inputX.Text = val.x.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
if( val.y != prevVal.y )
|
||||
inputY.Text = val.y.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5f3ab59a4377e4d428ff42b052a2d189
|
||||
timeCreated: 1505741432
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,195 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class Vector3Field : InspectorField
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
private BoundInputField inputX;
|
||||
|
||||
[SerializeField]
|
||||
private BoundInputField inputY;
|
||||
|
||||
[SerializeField]
|
||||
private BoundInputField inputZ;
|
||||
|
||||
[SerializeField]
|
||||
private Text labelX;
|
||||
|
||||
[SerializeField]
|
||||
private Text labelY;
|
||||
|
||||
[SerializeField]
|
||||
private Text labelZ;
|
||||
#pragma warning restore 0649
|
||||
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
private bool isVector3Int;
|
||||
#endif
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
inputX.Initialize();
|
||||
inputY.Initialize();
|
||||
inputZ.Initialize();
|
||||
|
||||
inputX.OnValueChanged += OnValueChanged;
|
||||
inputY.OnValueChanged += OnValueChanged;
|
||||
inputZ.OnValueChanged += OnValueChanged;
|
||||
|
||||
inputX.OnValueSubmitted += OnValueSubmitted;
|
||||
inputY.OnValueSubmitted += OnValueSubmitted;
|
||||
inputZ.OnValueSubmitted += OnValueSubmitted;
|
||||
|
||||
inputX.DefaultEmptyValue = "0";
|
||||
inputY.DefaultEmptyValue = "0";
|
||||
inputZ.DefaultEmptyValue = "0";
|
||||
}
|
||||
|
||||
public override bool SupportsType( Type type )
|
||||
{
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
if( type == typeof( Vector3Int ) )
|
||||
return true;
|
||||
#endif
|
||||
return type == typeof( Vector3 );
|
||||
}
|
||||
|
||||
protected override void OnBound( MemberInfo variable )
|
||||
{
|
||||
base.OnBound( variable );
|
||||
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
isVector3Int = BoundVariableType == typeof( Vector3Int );
|
||||
if( isVector3Int )
|
||||
{
|
||||
Vector3Int val = (Vector3Int) Value;
|
||||
inputX.Text = val.x.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
inputY.Text = val.y.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
inputZ.Text = val.z.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Vector3 val = (Vector3) Value;
|
||||
inputX.Text = val.x.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
inputY.Text = val.y.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
inputZ.Text = val.z.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
}
|
||||
}
|
||||
|
||||
private bool OnValueChanged( BoundInputField source, string input )
|
||||
{
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
if( isVector3Int )
|
||||
{
|
||||
int value;
|
||||
if( int.TryParse( input, NumberStyles.Integer, RuntimeInspectorUtils.numberFormat, out value ) )
|
||||
{
|
||||
Vector3Int val = (Vector3Int) Value;
|
||||
if( source == inputX )
|
||||
val.x = value;
|
||||
else if( source == inputY )
|
||||
val.y = value;
|
||||
else
|
||||
val.z = value;
|
||||
|
||||
Value = val;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
float value;
|
||||
if( float.TryParse( input, NumberStyles.Float, RuntimeInspectorUtils.numberFormat, out value ) )
|
||||
{
|
||||
Vector3 val = (Vector3) Value;
|
||||
if( source == inputX )
|
||||
val.x = value;
|
||||
else if( source == inputY )
|
||||
val.y = value;
|
||||
else
|
||||
val.z = value;
|
||||
|
||||
Value = val;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool OnValueSubmitted( BoundInputField source, string input )
|
||||
{
|
||||
Inspector.RefreshDelayed();
|
||||
return OnValueChanged( source, input );
|
||||
}
|
||||
|
||||
protected override void OnSkinChanged()
|
||||
{
|
||||
base.OnSkinChanged();
|
||||
|
||||
labelX.SetSkinText( Skin );
|
||||
labelY.SetSkinText( Skin );
|
||||
labelZ.SetSkinText( Skin );
|
||||
|
||||
inputX.Skin = Skin;
|
||||
inputY.Skin = Skin;
|
||||
inputZ.Skin = Skin;
|
||||
|
||||
float inputFieldWidth = ( 1f - Skin.LabelWidthPercentage ) / 3f;
|
||||
Vector2 rightSideAnchorMin = new Vector2( Skin.LabelWidthPercentage, 0f );
|
||||
Vector2 rightSideAnchorMax = new Vector2( Skin.LabelWidthPercentage + inputFieldWidth, 1f );
|
||||
variableNameMask.rectTransform.anchorMin = rightSideAnchorMin;
|
||||
( (RectTransform) inputX.transform ).SetAnchorMinMaxInputField( labelX.rectTransform, rightSideAnchorMin, rightSideAnchorMax );
|
||||
|
||||
rightSideAnchorMin.x += inputFieldWidth;
|
||||
rightSideAnchorMax.x += inputFieldWidth;
|
||||
( (RectTransform) inputY.transform ).SetAnchorMinMaxInputField( labelY.rectTransform, rightSideAnchorMin, rightSideAnchorMax );
|
||||
|
||||
rightSideAnchorMin.x += inputFieldWidth;
|
||||
rightSideAnchorMax.x = 1f;
|
||||
( (RectTransform) inputZ.transform ).SetAnchorMinMaxInputField( labelZ.rectTransform, rightSideAnchorMin, rightSideAnchorMax );
|
||||
}
|
||||
|
||||
public override void Refresh()
|
||||
{
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
if( isVector3Int )
|
||||
{
|
||||
Vector3Int prevVal = (Vector3Int) Value;
|
||||
base.Refresh();
|
||||
Vector3Int val = (Vector3Int) Value;
|
||||
|
||||
if( val.x != prevVal.x )
|
||||
inputX.Text = val.x.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
if( val.y != prevVal.y )
|
||||
inputY.Text = val.y.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
if( val.z != prevVal.z )
|
||||
inputZ.Text = val.z.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Vector3 prevVal = (Vector3) Value;
|
||||
base.Refresh();
|
||||
Vector3 val = (Vector3) Value;
|
||||
|
||||
if( val.x != prevVal.x )
|
||||
inputX.Text = val.x.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
if( val.y != prevVal.y )
|
||||
inputY.Text = val.y.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
if( val.z != prevVal.z )
|
||||
inputZ.Text = val.z.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 35015c50b2c3a604da64ea8c6813f078
|
||||
timeCreated: 1505741432
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,201 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class Vector4Field : InspectorField
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
private BoundInputField inputX;
|
||||
|
||||
[SerializeField]
|
||||
private BoundInputField inputY;
|
||||
|
||||
[SerializeField]
|
||||
private BoundInputField inputZ;
|
||||
|
||||
[SerializeField]
|
||||
private BoundInputField inputW;
|
||||
|
||||
[SerializeField]
|
||||
private Text labelX;
|
||||
|
||||
[SerializeField]
|
||||
private Text labelY;
|
||||
|
||||
[SerializeField]
|
||||
private Text labelZ;
|
||||
|
||||
[SerializeField]
|
||||
private Text labelW;
|
||||
#pragma warning restore 0649
|
||||
|
||||
private bool isQuaternion;
|
||||
|
||||
protected override float HeightMultiplier { get { return 2f; } }
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
inputX.Initialize();
|
||||
inputY.Initialize();
|
||||
inputZ.Initialize();
|
||||
inputW.Initialize();
|
||||
|
||||
inputX.OnValueChanged += OnValueChanged;
|
||||
inputY.OnValueChanged += OnValueChanged;
|
||||
inputZ.OnValueChanged += OnValueChanged;
|
||||
inputW.OnValueChanged += OnValueChanged;
|
||||
|
||||
inputX.OnValueSubmitted += OnValueSubmitted;
|
||||
inputY.OnValueSubmitted += OnValueSubmitted;
|
||||
inputZ.OnValueSubmitted += OnValueSubmitted;
|
||||
inputW.OnValueSubmitted += OnValueSubmitted;
|
||||
|
||||
inputX.DefaultEmptyValue = "0";
|
||||
inputY.DefaultEmptyValue = "0";
|
||||
inputZ.DefaultEmptyValue = "0";
|
||||
inputW.DefaultEmptyValue = "0";
|
||||
}
|
||||
|
||||
public override bool SupportsType( Type type )
|
||||
{
|
||||
return type == typeof( Vector4 ) || type == typeof( Quaternion );
|
||||
}
|
||||
|
||||
protected override void OnBound( MemberInfo variable )
|
||||
{
|
||||
base.OnBound( variable );
|
||||
|
||||
isQuaternion = BoundVariableType == typeof( Quaternion );
|
||||
if( isQuaternion )
|
||||
{
|
||||
Quaternion val = (Quaternion) Value;
|
||||
inputX.Text = val.x.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
inputY.Text = val.y.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
inputZ.Text = val.z.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
inputW.Text = val.w.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector4 val = (Vector4) Value;
|
||||
inputX.Text = val.x.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
inputY.Text = val.y.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
inputZ.Text = val.z.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
inputW.Text = val.w.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
}
|
||||
}
|
||||
|
||||
private bool OnValueChanged( BoundInputField source, string input )
|
||||
{
|
||||
float value;
|
||||
if( float.TryParse( input, NumberStyles.Float, RuntimeInspectorUtils.numberFormat, out value ) )
|
||||
{
|
||||
if( isQuaternion )
|
||||
{
|
||||
Quaternion val = (Quaternion) Value;
|
||||
if( source == inputX )
|
||||
val.x = value;
|
||||
else if( source == inputY )
|
||||
val.y = value;
|
||||
else if( source == inputZ )
|
||||
val.z = value;
|
||||
else
|
||||
val.w = value;
|
||||
|
||||
Value = val;
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector4 val = (Vector4) Value;
|
||||
if( source == inputX )
|
||||
val.x = value;
|
||||
else if( source == inputY )
|
||||
val.y = value;
|
||||
else if( source == inputZ )
|
||||
val.z = value;
|
||||
else
|
||||
val.w = value;
|
||||
|
||||
Value = val;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool OnValueSubmitted( BoundInputField source, string input )
|
||||
{
|
||||
Inspector.RefreshDelayed();
|
||||
return OnValueChanged( source, input );
|
||||
}
|
||||
|
||||
protected override void OnSkinChanged()
|
||||
{
|
||||
base.OnSkinChanged();
|
||||
|
||||
labelX.SetSkinText( Skin );
|
||||
labelY.SetSkinText( Skin );
|
||||
labelZ.SetSkinText( Skin );
|
||||
labelW.SetSkinText( Skin );
|
||||
|
||||
inputX.Skin = Skin;
|
||||
inputY.Skin = Skin;
|
||||
inputZ.Skin = Skin;
|
||||
inputW.Skin = Skin;
|
||||
|
||||
float inputFieldWidth = ( 1f - Skin.LabelWidthPercentage ) / 3f;
|
||||
Vector2 rightSideAnchorMin = new Vector2( Skin.LabelWidthPercentage + inputFieldWidth, 0f );
|
||||
Vector2 rightSideAnchorMax = new Vector2( Skin.LabelWidthPercentage + 2f * inputFieldWidth, 1f );
|
||||
variableNameMask.rectTransform.anchorMin = rightSideAnchorMin;
|
||||
( (RectTransform) inputX.transform ).SetAnchorMinMaxInputField( labelX.rectTransform, new Vector2( rightSideAnchorMin.x, 0.5f ), rightSideAnchorMax );
|
||||
( (RectTransform) inputZ.transform ).SetAnchorMinMaxInputField( labelZ.rectTransform, rightSideAnchorMin, new Vector2( rightSideAnchorMax.x, 0.5f ) );
|
||||
|
||||
rightSideAnchorMin.x += inputFieldWidth;
|
||||
rightSideAnchorMax.x = 1f;
|
||||
( (RectTransform) inputY.transform ).SetAnchorMinMaxInputField( labelY.rectTransform, new Vector2( rightSideAnchorMin.x, 0.5f ), rightSideAnchorMax );
|
||||
( (RectTransform) inputW.transform ).SetAnchorMinMaxInputField( labelW.rectTransform, rightSideAnchorMin, new Vector2( rightSideAnchorMax.x, 0.5f ) );
|
||||
}
|
||||
|
||||
public override void Refresh()
|
||||
{
|
||||
if( isQuaternion )
|
||||
{
|
||||
Quaternion prevVal = (Quaternion) Value;
|
||||
base.Refresh();
|
||||
Quaternion val = (Quaternion) Value;
|
||||
|
||||
if( val.x != prevVal.x )
|
||||
inputX.Text = val.x.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
if( val.y != prevVal.y )
|
||||
inputY.Text = val.y.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
if( val.z != prevVal.z )
|
||||
inputZ.Text = val.z.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
if( val.w != prevVal.w )
|
||||
inputW.Text = val.w.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector4 prevVal = (Vector4) Value;
|
||||
base.Refresh();
|
||||
Vector4 val = (Vector4) Value;
|
||||
|
||||
if( val.x != prevVal.x )
|
||||
inputX.Text = val.x.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
if( val.y != prevVal.y )
|
||||
inputY.Text = val.y.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
if( val.z != prevVal.z )
|
||||
inputZ.Text = val.z.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
if( val.w != prevVal.w )
|
||||
inputW.Text = val.w.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4ae70d6a58b22924b9070a8fe73d3973
|
||||
timeCreated: 1505741432
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 812f29dac95cacd4cb67b33c8e79cd42
|
||||
folderAsset: yes
|
||||
timeCreated: 1505745284
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,142 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class BoundInputField : MonoBehaviour
|
||||
{
|
||||
public delegate bool OnValueChangedDelegate( BoundInputField source, string input );
|
||||
|
||||
private bool initialized = false;
|
||||
private bool inputValid = true;
|
||||
private bool inputAltered = false;
|
||||
|
||||
private InputField inputField;
|
||||
private Image inputFieldBackground;
|
||||
public InputField BackingField { get { return inputField; } }
|
||||
|
||||
[System.NonSerialized]
|
||||
public string DefaultEmptyValue = string.Empty;
|
||||
|
||||
[System.NonSerialized]
|
||||
public bool CacheTextOnValueChange = true;
|
||||
|
||||
private string recentText = string.Empty;
|
||||
public string Text
|
||||
{
|
||||
get { return inputField.text; }
|
||||
set
|
||||
{
|
||||
recentText = value;
|
||||
|
||||
if( !inputField.isFocused )
|
||||
{
|
||||
inputValid = true;
|
||||
|
||||
inputField.text = value;
|
||||
inputFieldBackground.color = Skin.InputFieldNormalBackgroundColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int m_skinVersion = 0;
|
||||
private UISkin m_skin;
|
||||
public UISkin Skin
|
||||
{
|
||||
get { return m_skin; }
|
||||
set
|
||||
{
|
||||
if( m_skin != value || m_skinVersion != m_skin.Version )
|
||||
{
|
||||
Initialize();
|
||||
|
||||
m_skin = value;
|
||||
m_skinVersion = m_skin.Version;
|
||||
|
||||
inputField.textComponent.SetSkinInputFieldText( m_skin );
|
||||
inputFieldBackground.color = m_skin.InputFieldNormalBackgroundColor;
|
||||
|
||||
Text placeholder = inputField.placeholder as Text;
|
||||
if( placeholder != null )
|
||||
{
|
||||
float placeholderAlpha = placeholder.color.a;
|
||||
placeholder.SetSkinInputFieldText( m_skin );
|
||||
|
||||
Color placeholderColor = placeholder.color;
|
||||
placeholderColor.a = placeholderAlpha;
|
||||
placeholder.color = placeholderColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public OnValueChangedDelegate OnValueChanged;
|
||||
public OnValueChangedDelegate OnValueSubmitted;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
if( initialized )
|
||||
return;
|
||||
|
||||
inputField = GetComponent<InputField>();
|
||||
inputFieldBackground = GetComponent<Image>();
|
||||
|
||||
inputField.onValueChanged.AddListener( InputFieldValueChanged );
|
||||
inputField.onEndEdit.AddListener( InputFieldValueSubmitted );
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
private void InputFieldValueChanged( string str )
|
||||
{
|
||||
if( !inputField.isFocused )
|
||||
return;
|
||||
|
||||
inputAltered = true;
|
||||
|
||||
if( str == null || str.Length == 0 )
|
||||
str = DefaultEmptyValue;
|
||||
|
||||
if( OnValueChanged != null )
|
||||
{
|
||||
inputValid = OnValueChanged( this, str );
|
||||
if( inputValid && CacheTextOnValueChange )
|
||||
recentText = str;
|
||||
|
||||
inputFieldBackground.color = inputValid ? Skin.InputFieldNormalBackgroundColor : Skin.InputFieldInvalidBackgroundColor;
|
||||
}
|
||||
}
|
||||
|
||||
private void InputFieldValueSubmitted( string str )
|
||||
{
|
||||
inputFieldBackground.color = Skin.InputFieldNormalBackgroundColor;
|
||||
|
||||
if( !inputAltered )
|
||||
{
|
||||
inputField.text = recentText;
|
||||
return;
|
||||
}
|
||||
|
||||
inputAltered = false;
|
||||
|
||||
if( str == null || str.Length == 0 )
|
||||
str = DefaultEmptyValue;
|
||||
|
||||
if( OnValueSubmitted != null )
|
||||
{
|
||||
if( OnValueSubmitted( this, str ) )
|
||||
recentText = str;
|
||||
}
|
||||
else if( inputValid )
|
||||
recentText = str;
|
||||
|
||||
inputField.text = recentText;
|
||||
inputValid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6552c30232f0f104bbd7c08ece928f95
|
||||
timeCreated: 1505743873
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,89 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class BoundSlider : MonoBehaviour
|
||||
{
|
||||
public delegate void OnValueChangedDelegate( BoundSlider source, float value );
|
||||
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
private Slider slider;
|
||||
public Slider BackingField { get { return slider; } }
|
||||
|
||||
[SerializeField]
|
||||
private Image sliderBackground;
|
||||
|
||||
[SerializeField]
|
||||
private Image thumb;
|
||||
#pragma warning restore 0649
|
||||
|
||||
private bool sliderFocused = false;
|
||||
public bool IsFocused { get { return sliderFocused; } }
|
||||
|
||||
public float Value
|
||||
{
|
||||
get { return slider.value; }
|
||||
set { slider.value = value; }
|
||||
}
|
||||
|
||||
private int m_skinVersion = 0;
|
||||
private UISkin m_skin;
|
||||
public UISkin Skin
|
||||
{
|
||||
get { return m_skin; }
|
||||
set
|
||||
{
|
||||
if( m_skin != value || m_skinVersion != m_skin.Version )
|
||||
{
|
||||
m_skin = value;
|
||||
m_skinVersion = m_skin.Version;
|
||||
|
||||
sliderBackground.color = m_skin.SliderBackgroundColor;
|
||||
thumb.color = m_skin.SliderThumbColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public OnValueChangedDelegate OnValueChanged;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
PointerEventListener sliderPointerListener = slider.gameObject.AddComponent<PointerEventListener>();
|
||||
sliderPointerListener.PointerDown += ( ev ) => sliderFocused = true;
|
||||
sliderPointerListener.PointerUp += ( ev ) => sliderFocused = false;
|
||||
|
||||
slider.onValueChanged.AddListener( SliderValueChanged );
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
sliderFocused = false;
|
||||
}
|
||||
|
||||
public void SetRange( float min, float max )
|
||||
{
|
||||
sliderFocused = false;
|
||||
|
||||
if( min > max )
|
||||
{
|
||||
float temp = min;
|
||||
min = max;
|
||||
max = temp;
|
||||
}
|
||||
|
||||
slider.minValue = min;
|
||||
slider.maxValue = max;
|
||||
}
|
||||
|
||||
private void SliderValueChanged( float value )
|
||||
{
|
||||
if( !sliderFocused )
|
||||
return;
|
||||
|
||||
if( OnValueChanged != null )
|
||||
OnValueChanged( this, value );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 710b71b09c460b44eb1804f656eed412
|
||||
timeCreated: 1505743873
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 951b3609b11944b4d9a7bd33c2cea2b6
|
||||
folderAsset: yes
|
||||
timeCreated: 1506496159
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,260 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class ColorPicker : SkinnedWindow
|
||||
{
|
||||
private static ColorPicker m_instance;
|
||||
public static ColorPicker Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if( !m_instance )
|
||||
{
|
||||
m_instance = Instantiate( Resources.Load<ColorPicker>( "RuntimeInspector/ColorPicker" ) );
|
||||
m_instance.gameObject.SetActive( false );
|
||||
|
||||
RuntimeInspectorUtils.IgnoredTransformsInHierarchy.Add( m_instance.transform );
|
||||
}
|
||||
|
||||
return m_instance;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
private Image panel;
|
||||
|
||||
[SerializeField]
|
||||
private ColorWheelControl colorWheel;
|
||||
|
||||
[SerializeField]
|
||||
private ColorPickerAlphaSlider alphaSlider;
|
||||
|
||||
[SerializeField]
|
||||
private Text rgbaText;
|
||||
|
||||
[SerializeField]
|
||||
private BoundInputField rInput;
|
||||
|
||||
[SerializeField]
|
||||
private BoundInputField gInput;
|
||||
|
||||
[SerializeField]
|
||||
private BoundInputField bInput;
|
||||
|
||||
[SerializeField]
|
||||
private BoundInputField aInput;
|
||||
|
||||
[SerializeField]
|
||||
private LayoutElement rgbaLayoutElement;
|
||||
|
||||
[SerializeField]
|
||||
private LayoutElement buttonsLayoutElement;
|
||||
|
||||
[SerializeField]
|
||||
private Button cancelButton;
|
||||
|
||||
[SerializeField]
|
||||
private Button okButton;
|
||||
#pragma warning restore 0649
|
||||
|
||||
private Canvas referenceCanvas;
|
||||
|
||||
private Color initialValue;
|
||||
private ColorWheelControl.OnColorChangedDelegate onColorChanged, onColorConfirmed;
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
|
||||
rInput.Initialize();
|
||||
gInput.Initialize();
|
||||
bInput.Initialize();
|
||||
aInput.Initialize();
|
||||
|
||||
cancelButton.onClick.AddListener( Cancel );
|
||||
okButton.onClick.AddListener( () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if( onColorConfirmed != null )
|
||||
onColorConfirmed( colorWheel.Color );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
Debug.LogException( e );
|
||||
}
|
||||
|
||||
Close();
|
||||
} );
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
colorWheel.OnColorChanged += OnSelectedColorChanged;
|
||||
alphaSlider.OnValueChanged += OnAlphaChanged;
|
||||
|
||||
rInput.DefaultEmptyValue = "0";
|
||||
gInput.DefaultEmptyValue = "0";
|
||||
bInput.DefaultEmptyValue = "0";
|
||||
aInput.DefaultEmptyValue = "0";
|
||||
|
||||
rInput.Skin = Skin;
|
||||
gInput.Skin = Skin;
|
||||
bInput.Skin = Skin;
|
||||
aInput.Skin = Skin;
|
||||
|
||||
rInput.OnValueChanged += OnRGBAChanged;
|
||||
gInput.OnValueChanged += OnRGBAChanged;
|
||||
bInput.OnValueChanged += OnRGBAChanged;
|
||||
aInput.OnValueChanged += OnRGBAChanged;
|
||||
|
||||
OnSelectedColorChanged( colorWheel.Color );
|
||||
}
|
||||
|
||||
public void Show( ColorWheelControl.OnColorChangedDelegate onColorChanged, ColorWheelControl.OnColorChangedDelegate onColorConfirmed, Color initialColor, Canvas referenceCanvas )
|
||||
{
|
||||
initialValue = initialColor;
|
||||
|
||||
this.onColorChanged = null;
|
||||
colorWheel.PickColor( initialColor );
|
||||
alphaSlider.Color = initialColor;
|
||||
alphaSlider.Value = initialColor.a;
|
||||
this.onColorChanged = onColorChanged;
|
||||
this.onColorConfirmed = onColorConfirmed;
|
||||
|
||||
if( referenceCanvas && this.referenceCanvas != referenceCanvas )
|
||||
{
|
||||
this.referenceCanvas = referenceCanvas;
|
||||
|
||||
Canvas canvas = GetComponent<Canvas>();
|
||||
canvas.CopyValuesFrom( referenceCanvas );
|
||||
canvas.sortingOrder = Mathf.Max( 1000, referenceCanvas.sortingOrder + 100 );
|
||||
}
|
||||
|
||||
( (RectTransform) panel.transform ).anchoredPosition = Vector2.zero;
|
||||
gameObject.SetActive( true );
|
||||
}
|
||||
|
||||
public void Cancel()
|
||||
{
|
||||
try
|
||||
{
|
||||
if( colorWheel.Color != initialValue && onColorChanged != null )
|
||||
onColorChanged( initialValue );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
Debug.LogException( e );
|
||||
}
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
onColorChanged = null;
|
||||
onColorConfirmed = null;
|
||||
|
||||
gameObject.SetActive( false );
|
||||
}
|
||||
|
||||
protected override void RefreshSkin()
|
||||
{
|
||||
panel.color = Skin.WindowColor;
|
||||
|
||||
rgbaLayoutElement.SetHeight( Skin.LineHeight );
|
||||
buttonsLayoutElement.SetHeight( Mathf.Min( 45f, Skin.LineHeight * 1.5f ) );
|
||||
|
||||
rgbaText.SetSkinText( Skin );
|
||||
|
||||
rInput.Skin = Skin;
|
||||
gInput.Skin = Skin;
|
||||
bInput.Skin = Skin;
|
||||
aInput.Skin = Skin;
|
||||
|
||||
cancelButton.SetSkinButton( Skin );
|
||||
okButton.SetSkinButton( Skin );
|
||||
}
|
||||
|
||||
private void OnSelectedColorChanged( Color32 color )
|
||||
{
|
||||
rInput.Text = color.r.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
gInput.Text = color.g.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
bInput.Text = color.b.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
aInput.Text = color.a.ToString( RuntimeInspectorUtils.numberFormat );
|
||||
|
||||
alphaSlider.Color = color;
|
||||
|
||||
try
|
||||
{
|
||||
if( onColorChanged != null )
|
||||
onColorChanged( color );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
Debug.LogException( e );
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAlphaChanged( float alpha )
|
||||
{
|
||||
aInput.Text = ( (int) ( alpha * 255 ) ).ToString( RuntimeInspectorUtils.numberFormat );
|
||||
colorWheel.Alpha = alpha;
|
||||
|
||||
Color color = colorWheel.Color;
|
||||
color.a = alpha;
|
||||
|
||||
try
|
||||
{
|
||||
if( onColorChanged != null )
|
||||
onColorChanged( color );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
Debug.LogException( e );
|
||||
}
|
||||
}
|
||||
|
||||
private bool OnRGBAChanged( BoundInputField source, string input )
|
||||
{
|
||||
byte value;
|
||||
if( byte.TryParse( input, NumberStyles.Integer, RuntimeInspectorUtils.numberFormat, out value ) )
|
||||
{
|
||||
Color32 color = colorWheel.Color;
|
||||
if( source == rInput )
|
||||
color.r = value;
|
||||
else if( source == gInput )
|
||||
color.g = value;
|
||||
else if( source == bInput )
|
||||
color.b = value;
|
||||
else
|
||||
{
|
||||
color.a = value;
|
||||
alphaSlider.Value = value / 255f;
|
||||
}
|
||||
|
||||
alphaSlider.Color = color;
|
||||
colorWheel.PickColor( color );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void DestroyInstance()
|
||||
{
|
||||
if( m_instance )
|
||||
{
|
||||
RuntimeInspectorUtils.IgnoredTransformsInHierarchy.Remove( m_instance.transform );
|
||||
|
||||
Destroy( m_instance );
|
||||
m_instance = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6ccdaa729d068fc42adc9086ea412146
|
||||
timeCreated: 1505905339
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,62 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class ColorPickerAlphaSlider : MonoBehaviour, IPointerDownHandler, IDragHandler
|
||||
{
|
||||
public delegate void OnValueChangedDelegate( float alpha );
|
||||
|
||||
private RectTransform rectTransform;
|
||||
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
private Image alphaImage;
|
||||
|
||||
[SerializeField]
|
||||
private RectTransform selector;
|
||||
#pragma warning restore 0649
|
||||
|
||||
private float m_value;
|
||||
public float Value
|
||||
{
|
||||
get { return m_value; }
|
||||
set
|
||||
{
|
||||
m_value = value;
|
||||
|
||||
selector.anchorMin = new Vector2( m_value, 0.5f );
|
||||
selector.anchorMax = new Vector2( m_value, 0.5f );
|
||||
}
|
||||
}
|
||||
|
||||
public Color Color
|
||||
{
|
||||
get { return alphaImage.color; }
|
||||
set { value.a = 1f; alphaImage.color = value; }
|
||||
}
|
||||
|
||||
public OnValueChangedDelegate OnValueChanged;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
rectTransform = (RectTransform) transform;
|
||||
}
|
||||
|
||||
public void OnPointerDown( PointerEventData eventData )
|
||||
{
|
||||
OnDrag( eventData );
|
||||
}
|
||||
|
||||
public void OnDrag( PointerEventData eventData )
|
||||
{
|
||||
Vector2 localPoint;
|
||||
RectTransformUtility.ScreenPointToLocalPointInRectangle( rectTransform, eventData.position, eventData.pressEventCamera, out localPoint );
|
||||
|
||||
Value = Mathf.Clamp01( localPoint.x / rectTransform.sizeDelta.x );
|
||||
if( OnValueChanged != null )
|
||||
OnValueChanged( m_value );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fc8a1c7185b008740b2c43cc5644e0a2
|
||||
timeCreated: 1505905339
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,104 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
|
||||
using UnityEngine.InputSystem;
|
||||
#endif
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class DraggedReferenceItem : PopupBase, IDragHandler, IEndDragHandler
|
||||
{
|
||||
private object[] m_references;
|
||||
public object[] References { get { return m_references; } }
|
||||
|
||||
#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[] references, 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_references = references;
|
||||
label.text = ( references.Length == 1 ) ? references[0].GetNameWithType() : string.Concat( references[0].GetNameWithType(), " (and ", ( references.Length - 1 ).ToString( RuntimeInspectorUtils.numberFormat ), " more)" );
|
||||
|
||||
draggingPointer.pointerDrag = gameObject;
|
||||
draggingPointer.dragging = true;
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
public void OnDrag( PointerEventData eventData )
|
||||
{
|
||||
if( eventData.pointerId != pointer.pointerId )
|
||||
return;
|
||||
|
||||
RepositionSelf();
|
||||
}
|
||||
|
||||
public void OnEndDrag( PointerEventData eventData )
|
||||
{
|
||||
DestroySelf();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 748a81ca056ed954ba39428e7f990fa5
|
||||
timeCreated: 1508445584
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,167 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
|
||||
using UnityEngine.InputSystem;
|
||||
#endif
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
[RequireComponent( typeof( Camera ) )]
|
||||
public class DraggedReferenceSourceCamera : MonoBehaviour
|
||||
{
|
||||
public delegate Object RaycastHitProcesserDelegate( RaycastHit hit );
|
||||
|
||||
private Camera _camera;
|
||||
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
private UISkin draggedReferenceSkin;
|
||||
|
||||
[SerializeField]
|
||||
private Canvas draggedReferenceCanvas;
|
||||
|
||||
[SerializeField]
|
||||
private float holdTime = 0.4f;
|
||||
|
||||
[SerializeField]
|
||||
private LayerMask interactableObjectsMask = ~0;
|
||||
|
||||
[SerializeField]
|
||||
private float raycastRange = float.MaxValue;
|
||||
#pragma warning restore 0649
|
||||
|
||||
private bool pointerDown = false;
|
||||
private float pointerDownTime;
|
||||
private Vector2 pointerDownPos;
|
||||
|
||||
private Object hitObject;
|
||||
|
||||
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()
|
||||
{
|
||||
_camera = GetComponent<Camera>();
|
||||
}
|
||||
|
||||
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( IsPointerHeld() )
|
||||
{
|
||||
draggingPointer.position = GetPointerPosition();
|
||||
ExecuteEvents.Execute( draggedReference.gameObject, draggingPointer, ExecuteEvents.dragHandler );
|
||||
}
|
||||
else
|
||||
{
|
||||
ExecuteEvents.Execute( draggedReference.gameObject, draggingPointer, ExecuteEvents.endDragHandler );
|
||||
if( EventSystem.current != null )
|
||||
{
|
||||
hoveredUIElements.Clear();
|
||||
EventSystem.current.RaycastAll( draggingPointer, hoveredUIElements );
|
||||
|
||||
int i = 0;
|
||||
while( i < hoveredUIElements.Count && !ExecuteEvents.ExecuteHierarchy( hoveredUIElements[i].gameObject, draggingPointer, ExecuteEvents.dropHandler ) )
|
||||
i++;
|
||||
}
|
||||
|
||||
draggingPointer = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if( !pointerDown )
|
||||
{
|
||||
if( IsPointerDown() && EventSystem.current && !EventSystem.current.IsPointerOverGameObject() )
|
||||
{
|
||||
RaycastHit hit;
|
||||
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 = GetPointerPosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( IsPointerHeld() )
|
||||
{
|
||||
if( ( GetPointerPosition() - pointerDownPos ).sqrMagnitude >= 100f )
|
||||
pointerDown = false;
|
||||
else if( Time.realtimeSinceStartup - pointerDownTime >= holdTime )
|
||||
{
|
||||
pointerDown = false;
|
||||
|
||||
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,
|
||||
#endif
|
||||
pressPosition = GetPointerPosition(),
|
||||
position = GetPointerPosition(),
|
||||
button = PointerEventData.InputButton.Left
|
||||
};
|
||||
|
||||
draggedReference = RuntimeInspectorUtils.CreateDraggedReferenceItem( hitObject, draggingPointer, draggedReferenceSkin, draggedReferenceCanvas );
|
||||
if( !draggedReference )
|
||||
{
|
||||
pointerDown = false;
|
||||
draggingPointer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 94b86b8b3a9c684479f312ba132c50f0
|
||||
timeCreated: 1508483484
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,68 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class DraggedReferenceSourceUI : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IBeginDragHandler
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
private Object[] m_references;
|
||||
public Object[] References
|
||||
{
|
||||
get { return m_references; }
|
||||
set { m_references = value; }
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private UISkin draggedReferenceSkin;
|
||||
|
||||
[SerializeField]
|
||||
private float holdTime = 0.4f;
|
||||
#pragma warning restore 0649
|
||||
|
||||
private IEnumerator pointerHeldCoroutine = null;
|
||||
|
||||
public void OnPointerDown( PointerEventData eventData )
|
||||
{
|
||||
if( pointerHeldCoroutine != null )
|
||||
return;
|
||||
|
||||
if( m_references.IsEmpty() )
|
||||
return;
|
||||
|
||||
pointerHeldCoroutine = CreateReferenceItemCoroutine( eventData );
|
||||
StartCoroutine( pointerHeldCoroutine );
|
||||
}
|
||||
|
||||
public void OnPointerUp( PointerEventData eventData )
|
||||
{
|
||||
if( pointerHeldCoroutine != null )
|
||||
{
|
||||
StopCoroutine( pointerHeldCoroutine );
|
||||
pointerHeldCoroutine = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnBeginDrag( PointerEventData eventData )
|
||||
{
|
||||
if( pointerHeldCoroutine != null )
|
||||
{
|
||||
StopCoroutine( pointerHeldCoroutine );
|
||||
pointerHeldCoroutine = null;
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator CreateReferenceItemCoroutine( PointerEventData eventData )
|
||||
{
|
||||
Vector2 pressPosition = eventData.pressPosition;
|
||||
float dragThreshold = EventSystem.current.pixelDragThreshold;
|
||||
|
||||
yield return new WaitForSecondsRealtime( holdTime );
|
||||
|
||||
if( !m_references.IsEmpty() && ( eventData.position - pressPosition ).sqrMagnitude < dragThreshold * dragThreshold )
|
||||
RuntimeInspectorUtils.CreateDraggedReferenceItem( m_references, eventData, draggedReferenceSkin, GetComponentInParent<Canvas>() );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 557af64d33a353345961734383333671
|
||||
timeCreated: 1508498967
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public struct ExposedMethod
|
||||
{
|
||||
private readonly MethodInfo method;
|
||||
private readonly RuntimeInspectorButtonAttribute properties;
|
||||
private readonly bool isExtensionMethod;
|
||||
|
||||
public string Label { get { return properties.Label; } }
|
||||
|
||||
public bool IsInitializer { get { return properties.IsInitializer; } }
|
||||
|
||||
public bool VisibleWhenInitialized { get { return ( properties.Visibility & ButtonVisibility.InitializedObjects ) == ButtonVisibility.InitializedObjects; } }
|
||||
public bool VisibleWhenUninitialized { get { return ( properties.Visibility & ButtonVisibility.UninitializedObjects ) == ButtonVisibility.UninitializedObjects; } }
|
||||
|
||||
public ExposedMethod( MethodInfo method, RuntimeInspectorButtonAttribute properties, bool isExtensionMethod )
|
||||
{
|
||||
this.method = method;
|
||||
this.properties = properties;
|
||||
this.isExtensionMethod = isExtensionMethod;
|
||||
}
|
||||
|
||||
public void Call( object source )
|
||||
{
|
||||
if( isExtensionMethod )
|
||||
method.Invoke( null, new object[] { source } );
|
||||
else if( method.IsStatic )
|
||||
method.Invoke( null, null );
|
||||
else if( source != null )
|
||||
method.Invoke( source, null );
|
||||
}
|
||||
|
||||
public object CallAndReturnValue( object source )
|
||||
{
|
||||
if( isExtensionMethod )
|
||||
return method.Invoke( null, new object[] { source } );
|
||||
|
||||
if( method.IsStatic )
|
||||
return method.Invoke( null, null );
|
||||
|
||||
if( source != null )
|
||||
return method.Invoke( source, null );
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public struct ExposedExtensionMethodHolder
|
||||
{
|
||||
public readonly Type extendedType;
|
||||
public readonly MethodInfo method;
|
||||
public readonly RuntimeInspectorButtonAttribute properties;
|
||||
|
||||
public ExposedExtensionMethodHolder( Type extendedType, MethodInfo method, RuntimeInspectorButtonAttribute properties )
|
||||
{
|
||||
this.extendedType = extendedType;
|
||||
this.method = method;
|
||||
this.properties = properties;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 87bad5f669f45f44c90bc9d1d9b71933
|
||||
timeCreated: 1507972027
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,112 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using Visibility = RuntimeInspectorNamespace.RuntimeInspector.VariableVisibility;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class ExposedVariablesEnumerator : IEnumerator<MemberInfo>, IEnumerable<MemberInfo>
|
||||
{
|
||||
public MemberInfo Current { get { return variables[index]; } }
|
||||
object IEnumerator.Current { get { return variables[index]; } }
|
||||
|
||||
private int index;
|
||||
|
||||
private readonly MemberInfo[] variables;
|
||||
private readonly List<VariableSet> hiddenVariables, exposedVariables;
|
||||
|
||||
private readonly Visibility fieldVisibility, propertyVisibility;
|
||||
|
||||
public ExposedVariablesEnumerator( MemberInfo[] variables, List<VariableSet> hiddenVariables, List<VariableSet> exposedVariables, Visibility fieldVisibility, Visibility propertyVisibility )
|
||||
{
|
||||
index = -1;
|
||||
|
||||
this.variables = variables;
|
||||
|
||||
this.hiddenVariables = hiddenVariables;
|
||||
this.exposedVariables = exposedVariables;
|
||||
|
||||
this.fieldVisibility = fieldVisibility;
|
||||
this.propertyVisibility = propertyVisibility;
|
||||
}
|
||||
|
||||
public void Dispose() { }
|
||||
|
||||
public IEnumerator<MemberInfo> GetEnumerator()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
if( variables == null )
|
||||
return false;
|
||||
|
||||
while( ++index < variables.Length )
|
||||
{
|
||||
if( ShouldExposeVariable( variables[index] ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
index = -1;
|
||||
}
|
||||
|
||||
private bool ShouldExposeVariable( MemberInfo variable )
|
||||
{
|
||||
string variableName = variable.Name;
|
||||
if( exposedVariables != null )
|
||||
{
|
||||
for( int i = 0; i < exposedVariables.Count; i++ )
|
||||
{
|
||||
if( exposedVariables[i].variables.Contains( variableName ) )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if( hiddenVariables != null )
|
||||
{
|
||||
for( int i = 0; i < hiddenVariables.Count; i++ )
|
||||
{
|
||||
if( hiddenVariables[i].variables.Contains( variableName ) )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if( variable is FieldInfo )
|
||||
{
|
||||
switch( fieldVisibility )
|
||||
{
|
||||
case Visibility.None: return false;
|
||||
case Visibility.All: return true;
|
||||
case Visibility.SerializableOnly:
|
||||
FieldInfo field = (FieldInfo) variable;
|
||||
return field.IsPublic || field.HasAttribute<SerializeField>();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch( propertyVisibility )
|
||||
{
|
||||
case Visibility.None: return false;
|
||||
case Visibility.All: return true;
|
||||
case Visibility.SerializableOnly:
|
||||
PropertyInfo property = (PropertyInfo) variable;
|
||||
return property.GetGetMethod( true ).IsPublic || property.HasAttribute<SerializeField>();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bcbb5d26b6a4d1644bd02f31f518014c
|
||||
timeCreated: 1506589793
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,19 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
// Credit: http://answers.unity.com/answers/1157876/view.html
|
||||
[RequireComponent( typeof( CanvasRenderer ) )]
|
||||
public class NonDrawingGraphic : Graphic
|
||||
{
|
||||
public override void SetMaterialDirty() { return; }
|
||||
public override void SetVerticesDirty() { return; }
|
||||
|
||||
protected override void OnPopulateMesh( VertexHelper vh )
|
||||
{
|
||||
vh.Clear();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 742b43d72934e9c4282d9cf7ca9bc892
|
||||
timeCreated: 1581865808
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,19 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
// Credit: http://answers.unity.com/answers/1157876/view.html
|
||||
[RequireComponent( typeof( CanvasRenderer ) )]
|
||||
public class NonDrawingMaskableGraphic : MaskableGraphic
|
||||
{
|
||||
public override void SetMaterialDirty() { return; }
|
||||
public override void SetVerticesDirty() { return; }
|
||||
|
||||
protected override void OnPopulateMesh( VertexHelper vh )
|
||||
{
|
||||
vh.Clear();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0e091b08e39033248990575fb4d84e28
|
||||
timeCreated: 1581865808
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,233 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public interface INumberHandler
|
||||
{
|
||||
float MinValue { get; }
|
||||
float MaxValue { get; }
|
||||
|
||||
bool TryParse( string input, out object value );
|
||||
bool ValuesAreEqual( object value1, object value2 );
|
||||
|
||||
object ConvertFromFloat( float value );
|
||||
float ConvertToFloat( object value );
|
||||
|
||||
string ToString( object value );
|
||||
}
|
||||
|
||||
public class NumberHandlers
|
||||
{
|
||||
#region Implementations
|
||||
private class IntHandler : INumberHandler
|
||||
{
|
||||
public float MinValue { get { return int.MinValue; } }
|
||||
public float MaxValue { get { return int.MaxValue; } }
|
||||
|
||||
public bool TryParse( string input, out object value ) { int parsedVal; bool result = int.TryParse( input, NumberStyles.Integer, RuntimeInspectorUtils.numberFormat, out parsedVal ); value = parsedVal; return result; }
|
||||
public bool ValuesAreEqual( object value1, object value2 ) { return (int) value1 == (int) value2; }
|
||||
|
||||
public object ConvertFromFloat( float value ) { return (int) value; }
|
||||
public float ConvertToFloat( object value ) { return (int) value; }
|
||||
|
||||
public string ToString( object value ) { return ( (int) value ).ToString( RuntimeInspectorUtils.numberFormat ); }
|
||||
}
|
||||
|
||||
private class UIntHandler : INumberHandler
|
||||
{
|
||||
public float MinValue { get { return uint.MinValue; } }
|
||||
public float MaxValue { get { return uint.MaxValue; } }
|
||||
|
||||
public bool TryParse( string input, out object value ) { uint parsedVal; bool result = uint.TryParse( input, NumberStyles.Integer, RuntimeInspectorUtils.numberFormat, out parsedVal ); value = parsedVal; return result; }
|
||||
public bool ValuesAreEqual( object value1, object value2 ) { return (uint) value1 == (uint) value2; }
|
||||
|
||||
public object ConvertFromFloat( float value ) { return (uint) value; }
|
||||
public float ConvertToFloat( object value ) { return (uint) value; }
|
||||
|
||||
public string ToString( object value ) { return ( (uint) value ).ToString( RuntimeInspectorUtils.numberFormat ); }
|
||||
}
|
||||
|
||||
private class LongHandler : INumberHandler
|
||||
{
|
||||
public float MinValue { get { return long.MinValue; } }
|
||||
public float MaxValue { get { return long.MaxValue; } }
|
||||
|
||||
public bool TryParse( string input, out object value ) { long parsedVal; bool result = long.TryParse( input, NumberStyles.Integer, RuntimeInspectorUtils.numberFormat, out parsedVal ); value = parsedVal; return result; }
|
||||
public bool ValuesAreEqual( object value1, object value2 ) { return (long) value1 == (long) value2; }
|
||||
|
||||
public object ConvertFromFloat( float value ) { return (long) value; }
|
||||
public float ConvertToFloat( object value ) { return (long) value; }
|
||||
|
||||
public string ToString( object value ) { return ( (long) value ).ToString( RuntimeInspectorUtils.numberFormat ); }
|
||||
}
|
||||
|
||||
private class ULongHandler : INumberHandler
|
||||
{
|
||||
public float MinValue { get { return ulong.MinValue; } }
|
||||
public float MaxValue { get { return ulong.MaxValue; } }
|
||||
|
||||
public bool TryParse( string input, out object value ) { ulong parsedVal; bool result = ulong.TryParse( input, NumberStyles.Integer, RuntimeInspectorUtils.numberFormat, out parsedVal ); value = parsedVal; return result; }
|
||||
public bool ValuesAreEqual( object value1, object value2 ) { return (ulong) value1 == (ulong) value2; }
|
||||
|
||||
public object ConvertFromFloat( float value ) { return (ulong) value; }
|
||||
public float ConvertToFloat( object value ) { return (ulong) value; }
|
||||
|
||||
public string ToString( object value ) { return ( (ulong) value ).ToString( RuntimeInspectorUtils.numberFormat ); }
|
||||
}
|
||||
|
||||
private class ByteHandler : INumberHandler
|
||||
{
|
||||
public float MinValue { get { return byte.MinValue; } }
|
||||
public float MaxValue { get { return byte.MaxValue; } }
|
||||
|
||||
public bool TryParse( string input, out object value ) { byte parsedVal; bool result = byte.TryParse( input, NumberStyles.Integer, RuntimeInspectorUtils.numberFormat, out parsedVal ); value = parsedVal; return result; }
|
||||
public bool ValuesAreEqual( object value1, object value2 ) { return (byte) value1 == (byte) value2; }
|
||||
|
||||
public object ConvertFromFloat( float value ) { return (byte) value; }
|
||||
public float ConvertToFloat( object value ) { return (byte) value; }
|
||||
|
||||
public string ToString( object value ) { return ( (byte) value ).ToString( RuntimeInspectorUtils.numberFormat ); }
|
||||
}
|
||||
|
||||
private class SByteHandler : INumberHandler
|
||||
{
|
||||
public float MinValue { get { return sbyte.MinValue; } }
|
||||
public float MaxValue { get { return sbyte.MaxValue; } }
|
||||
|
||||
public bool TryParse( string input, out object value ) { sbyte parsedVal; bool result = sbyte.TryParse( input, NumberStyles.Integer, RuntimeInspectorUtils.numberFormat, out parsedVal ); value = parsedVal; return result; }
|
||||
public bool ValuesAreEqual( object value1, object value2 ) { return (sbyte) value1 == (sbyte) value2; }
|
||||
|
||||
public object ConvertFromFloat( float value ) { return (sbyte) value; }
|
||||
public float ConvertToFloat( object value ) { return (sbyte) value; }
|
||||
|
||||
public string ToString( object value ) { return ( (sbyte) value ).ToString( RuntimeInspectorUtils.numberFormat ); }
|
||||
}
|
||||
|
||||
private class ShortHandler : INumberHandler
|
||||
{
|
||||
public float MinValue { get { return short.MinValue; } }
|
||||
public float MaxValue { get { return short.MaxValue; } }
|
||||
|
||||
public bool TryParse( string input, out object value ) { short parsedVal; bool result = short.TryParse( input, NumberStyles.Integer, RuntimeInspectorUtils.numberFormat, out parsedVal ); value = parsedVal; return result; }
|
||||
public bool ValuesAreEqual( object value1, object value2 ) { return (short) value1 == (short) value2; }
|
||||
|
||||
public object ConvertFromFloat( float value ) { return (short) value; }
|
||||
public float ConvertToFloat( object value ) { return (short) value; }
|
||||
|
||||
public string ToString( object value ) { return ( (short) value ).ToString( RuntimeInspectorUtils.numberFormat ); }
|
||||
}
|
||||
|
||||
private class UShortHandler : INumberHandler
|
||||
{
|
||||
public float MinValue { get { return ushort.MinValue; } }
|
||||
public float MaxValue { get { return ushort.MaxValue; } }
|
||||
|
||||
public bool TryParse( string input, out object value ) { ushort parsedVal; bool result = ushort.TryParse( input, NumberStyles.Integer, RuntimeInspectorUtils.numberFormat, out parsedVal ); value = parsedVal; return result; }
|
||||
public bool ValuesAreEqual( object value1, object value2 ) { return (ushort) value1 == (ushort) value2; }
|
||||
|
||||
public object ConvertFromFloat( float value ) { return (ushort) value; }
|
||||
public float ConvertToFloat( object value ) { return (ushort) value; }
|
||||
|
||||
public string ToString( object value ) { return ( (ushort) value ).ToString( RuntimeInspectorUtils.numberFormat ); }
|
||||
}
|
||||
|
||||
private class CharHandler : INumberHandler
|
||||
{
|
||||
public float MinValue { get { return char.MinValue; } }
|
||||
public float MaxValue { get { return char.MaxValue; } }
|
||||
|
||||
public bool TryParse( string input, out object value ) { char parsedVal; bool result = char.TryParse( input, out parsedVal ); value = parsedVal; return result; }
|
||||
public bool ValuesAreEqual( object value1, object value2 ) { return (char) value1 == (char) value2; }
|
||||
|
||||
public object ConvertFromFloat( float value ) { return (char) value; }
|
||||
public float ConvertToFloat( object value ) { return (char) value; }
|
||||
|
||||
public string ToString( object value ) { return ( (char) value ).ToString( RuntimeInspectorUtils.numberFormat ); }
|
||||
}
|
||||
|
||||
private class FloatHandler : INumberHandler
|
||||
{
|
||||
public float MinValue { get { return float.MinValue; } }
|
||||
public float MaxValue { get { return float.MaxValue; } }
|
||||
|
||||
public bool TryParse( string input, out object value ) { float parsedVal; bool result = float.TryParse( input, NumberStyles.Float, RuntimeInspectorUtils.numberFormat, out parsedVal ); value = parsedVal; return result; }
|
||||
public bool ValuesAreEqual( object value1, object value2 ) { return (float) value1 == (float) value2; }
|
||||
|
||||
public object ConvertFromFloat( float value ) { return value; }
|
||||
public float ConvertToFloat( object value ) { return (float) value; }
|
||||
|
||||
public string ToString( object value ) { return ( (float) value ).ToString( RuntimeInspectorUtils.numberFormat ); }
|
||||
}
|
||||
|
||||
private class DoubleHandler : INumberHandler
|
||||
{
|
||||
public float MinValue { get { return float.MinValue; } }
|
||||
public float MaxValue { get { return float.MaxValue; } }
|
||||
|
||||
public bool TryParse( string input, out object value ) { double parsedVal; bool result = double.TryParse( input, NumberStyles.Float, RuntimeInspectorUtils.numberFormat, out parsedVal ); value = parsedVal; return result; }
|
||||
public bool ValuesAreEqual( object value1, object value2 ) { return (double) value1 == (double) value2; }
|
||||
|
||||
public object ConvertFromFloat( float value ) { return (double) value; }
|
||||
public float ConvertToFloat( object value ) { return (float) (double) value; }
|
||||
|
||||
public string ToString( object value ) { return ( (double) value ).ToString( RuntimeInspectorUtils.numberFormat ); }
|
||||
}
|
||||
|
||||
private class DecimalHandler : INumberHandler
|
||||
{
|
||||
public float MinValue { get { return float.MinValue; } }
|
||||
public float MaxValue { get { return float.MaxValue; } }
|
||||
|
||||
public bool TryParse( string input, out object value ) { decimal parsedVal; bool result = decimal.TryParse( input, NumberStyles.Float, RuntimeInspectorUtils.numberFormat, out parsedVal ); value = parsedVal; return result; }
|
||||
public bool ValuesAreEqual( object value1, object value2 ) { return (decimal) value1 == (decimal) value2; }
|
||||
|
||||
public object ConvertFromFloat( float value ) { return (decimal) value; }
|
||||
public float ConvertToFloat( object value ) { return (float) (decimal) value; }
|
||||
|
||||
public string ToString( object value ) { return ( (decimal) value ).ToString( RuntimeInspectorUtils.numberFormat ); }
|
||||
}
|
||||
#endregion
|
||||
|
||||
private static readonly Dictionary<Type, INumberHandler> handlers = new Dictionary<Type, INumberHandler>( 16 );
|
||||
|
||||
public static INumberHandler Get( Type type )
|
||||
{
|
||||
INumberHandler result;
|
||||
if( !handlers.TryGetValue( type, out result ) )
|
||||
{
|
||||
if( type == typeof( int ) )
|
||||
result = new IntHandler();
|
||||
else if( type == typeof( float ) )
|
||||
result = new FloatHandler();
|
||||
else if( type == typeof( long ) )
|
||||
result = new LongHandler();
|
||||
else if( type == typeof( double ) )
|
||||
result = new DoubleHandler();
|
||||
else if( type == typeof( byte ) )
|
||||
result = new ByteHandler();
|
||||
else if( type == typeof( char ) )
|
||||
result = new CharHandler();
|
||||
else if( type == typeof( short ) )
|
||||
result = new ShortHandler();
|
||||
else if( type == typeof( uint ) )
|
||||
result = new UIntHandler();
|
||||
else if( type == typeof( ulong ) )
|
||||
result = new ULongHandler();
|
||||
else if( type == typeof( sbyte ) )
|
||||
result = new SByteHandler();
|
||||
else if( type == typeof( ushort ) )
|
||||
result = new UShortHandler();
|
||||
else if( type == typeof( decimal ) )
|
||||
result = new DecimalHandler();
|
||||
else
|
||||
result = null;
|
||||
|
||||
handlers[type] = result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8948c819640105540a0bc75ded46e7f4
|
||||
timeCreated: 1581849936
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b311827a1381d0c439e3ff4be4fd4d6e
|
||||
folderAsset: yes
|
||||
timeCreated: 1506496576
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,308 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
using UnityEngine.UI;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class ObjectReferencePicker : SkinnedWindow, IListViewAdapter
|
||||
{
|
||||
private const string SPRITE_ATLAS_PREFIX = "SpriteAtlasTexture-";
|
||||
|
||||
private static ObjectReferencePicker m_instance;
|
||||
public static ObjectReferencePicker Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if( !m_instance )
|
||||
{
|
||||
m_instance = Instantiate( Resources.Load<ObjectReferencePicker>( "RuntimeInspector/ObjectReferencePicker" ) );
|
||||
m_instance.gameObject.SetActive( false );
|
||||
|
||||
RuntimeInspectorUtils.IgnoredTransformsInHierarchy.Add( m_instance.transform );
|
||||
}
|
||||
|
||||
return m_instance;
|
||||
}
|
||||
}
|
||||
|
||||
public delegate void ReferenceCallback( object reference );
|
||||
private ReferenceCallback onReferenceChanged, onSelectionConfirmed;
|
||||
|
||||
public delegate string NameGetter( object reference );
|
||||
private NameGetter referenceNameGetter, referenceDisplayNameGetter;
|
||||
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
private Image panel;
|
||||
|
||||
[SerializeField]
|
||||
private Image scrollbar;
|
||||
|
||||
[SerializeField]
|
||||
private InputField searchBar;
|
||||
|
||||
[SerializeField]
|
||||
private Image searchIcon;
|
||||
|
||||
[SerializeField]
|
||||
private Image searchBarBackground;
|
||||
|
||||
[SerializeField]
|
||||
private Text selectPromptText;
|
||||
|
||||
[SerializeField]
|
||||
private LayoutElement searchBarLayoutElement;
|
||||
|
||||
[SerializeField]
|
||||
private LayoutElement buttonsLayoutElement;
|
||||
|
||||
[SerializeField]
|
||||
private Button cancelButton;
|
||||
|
||||
[SerializeField]
|
||||
private Button okButton;
|
||||
|
||||
[SerializeField]
|
||||
private RecycledListView listView;
|
||||
|
||||
[SerializeField]
|
||||
private Image listViewBackground;
|
||||
|
||||
[SerializeField]
|
||||
private ObjectReferencePickerItem referenceItemPrefab;
|
||||
#pragma warning restore 0649
|
||||
|
||||
private Canvas referenceCanvas;
|
||||
|
||||
private readonly List<object> references = new List<object>( 64 );
|
||||
private readonly List<object> filteredReferences = new List<object>( 64 );
|
||||
|
||||
private object initialValue;
|
||||
|
||||
private object currentlySelectedObject;
|
||||
private ObjectReferencePickerItem currentlySelectedItem;
|
||||
|
||||
int IListViewAdapter.Count { get { return filteredReferences.Count; } }
|
||||
float IListViewAdapter.ItemHeight { get { return Skin.LineHeight; } }
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
|
||||
listView.SetAdapter( this );
|
||||
searchBar.onValueChanged.AddListener( OnSearchTextChanged );
|
||||
|
||||
cancelButton.onClick.AddListener( Cancel );
|
||||
okButton.onClick.AddListener( () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if( onSelectionConfirmed != null )
|
||||
onSelectionConfirmed( currentlySelectedObject );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
Debug.LogException( e );
|
||||
}
|
||||
|
||||
Close();
|
||||
} );
|
||||
|
||||
#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
|
||||
// On new Input System, scroll sensitivity is much higher than legacy Input system
|
||||
listView.GetComponent<ScrollRect>().scrollSensitivity *= 0.25f;
|
||||
#endif
|
||||
}
|
||||
|
||||
public void Show( ReferenceCallback onReferenceChanged, ReferenceCallback onSelectionConfirmed, NameGetter referenceNameGetter, NameGetter referenceDisplayNameGetter, object[] references, object initialReference, bool includeNullReference, string title, Canvas referenceCanvas )
|
||||
{
|
||||
initialValue = initialReference;
|
||||
|
||||
this.onReferenceChanged = onReferenceChanged;
|
||||
this.onSelectionConfirmed = onSelectionConfirmed;
|
||||
this.referenceNameGetter = referenceNameGetter ?? ( ( reference ) => reference.GetNameWithType() );
|
||||
this.referenceDisplayNameGetter = referenceDisplayNameGetter ?? ( ( reference ) => reference.GetNameWithType() );
|
||||
|
||||
if( referenceCanvas && this.referenceCanvas != referenceCanvas )
|
||||
{
|
||||
this.referenceCanvas = referenceCanvas;
|
||||
|
||||
Canvas canvas = GetComponent<Canvas>();
|
||||
canvas.CopyValuesFrom( referenceCanvas );
|
||||
canvas.sortingOrder = Mathf.Max( 1000, referenceCanvas.sortingOrder + 100 );
|
||||
}
|
||||
|
||||
panel.rectTransform.anchoredPosition = Vector2.zero;
|
||||
gameObject.SetActive( true );
|
||||
|
||||
selectPromptText.text = title;
|
||||
currentlySelectedObject = initialReference;
|
||||
|
||||
GenerateReferenceItems( references, includeNullReference );
|
||||
|
||||
#if UNITY_EDITOR || UNITY_STANDALONE || UNITY_WEBGL
|
||||
// On desktop platforms, automatically focus on search field
|
||||
// We don't do the same on mobile because immediately showing the on-screen keyboard after presenting the window wouldn't be nice
|
||||
searchBar.ActivateInputField();
|
||||
#endif
|
||||
}
|
||||
|
||||
public void Cancel()
|
||||
{
|
||||
try
|
||||
{
|
||||
if( currentlySelectedObject != initialValue && onReferenceChanged != null )
|
||||
onReferenceChanged( initialValue );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
Debug.LogException( e );
|
||||
}
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
onReferenceChanged = null;
|
||||
onSelectionConfirmed = null;
|
||||
referenceNameGetter = null;
|
||||
referenceDisplayNameGetter = null;
|
||||
initialValue = null;
|
||||
currentlySelectedObject = null;
|
||||
currentlySelectedItem = null;
|
||||
|
||||
references.Clear();
|
||||
filteredReferences.Clear();
|
||||
|
||||
gameObject.SetActive( false );
|
||||
}
|
||||
|
||||
protected override void RefreshSkin()
|
||||
{
|
||||
panel.color = Skin.WindowColor;
|
||||
listViewBackground.color = Skin.BackgroundColor;
|
||||
|
||||
scrollbar.color = Skin.ScrollbarColor;
|
||||
|
||||
selectPromptText.SetSkinText( Skin );
|
||||
searchBar.textComponent.SetSkinButtonText( Skin );
|
||||
|
||||
searchBarBackground.color = Skin.ButtonBackgroundColor;
|
||||
searchIcon.color = Skin.ButtonTextColor;
|
||||
|
||||
searchBarLayoutElement.SetHeight( Skin.LineHeight );
|
||||
buttonsLayoutElement.SetHeight( Mathf.Min( 45f, Skin.LineHeight * 1.5f ) );
|
||||
|
||||
cancelButton.SetSkinButton( Skin );
|
||||
okButton.SetSkinButton( Skin );
|
||||
|
||||
listView.ResetList();
|
||||
}
|
||||
|
||||
private void GenerateReferenceItems( object[] references, bool includeNullReference )
|
||||
{
|
||||
this.references.Clear();
|
||||
filteredReferences.Clear();
|
||||
searchBar.text = string.Empty;
|
||||
|
||||
if( includeNullReference )
|
||||
this.references.Add( null );
|
||||
|
||||
Array.Sort( references, ( ref1, ref2 ) => referenceNameGetter( ref1 ).CompareTo( referenceNameGetter( ref2 ) ) );
|
||||
|
||||
for( int i = 0; i < references.Length; i++ )
|
||||
{
|
||||
Object unityReference = references[i] as Object;
|
||||
if( unityReference )
|
||||
{
|
||||
if( unityReference.hideFlags != HideFlags.None && unityReference.hideFlags != HideFlags.NotEditable &&
|
||||
unityReference.hideFlags != HideFlags.HideInHierarchy && unityReference.hideFlags != HideFlags.HideInInspector )
|
||||
continue;
|
||||
|
||||
if( ( unityReference is Texture || unityReference is Sprite ) && unityReference.name.StartsWith( SPRITE_ATLAS_PREFIX ) )
|
||||
continue;
|
||||
|
||||
this.references.Add( unityReference );
|
||||
}
|
||||
else if( references[i] != null )
|
||||
this.references.Add( references[i] );
|
||||
}
|
||||
|
||||
OnSearchTextChanged( string.Empty );
|
||||
|
||||
listView.UpdateList();
|
||||
}
|
||||
|
||||
RecycledListItem IListViewAdapter.CreateItem( Transform parent )
|
||||
{
|
||||
ObjectReferencePickerItem item = (ObjectReferencePickerItem) Instantiate( referenceItemPrefab, parent, false );
|
||||
item.Skin = Skin;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
private void OnSearchTextChanged( string value )
|
||||
{
|
||||
filteredReferences.Clear();
|
||||
|
||||
value = value.ToLowerInvariant();
|
||||
for( int i = 0; i < references.Count; i++ )
|
||||
{
|
||||
if( referenceNameGetter( references[i] ).ToLowerInvariant().Contains( value ) )
|
||||
filteredReferences.Add( references[i] );
|
||||
}
|
||||
|
||||
listView.UpdateList();
|
||||
}
|
||||
|
||||
void IListViewAdapter.SetItemContent( RecycledListItem item )
|
||||
{
|
||||
ObjectReferencePickerItem it = (ObjectReferencePickerItem) item;
|
||||
it.SetContent( filteredReferences[it.Position], referenceDisplayNameGetter( filteredReferences[it.Position] ) );
|
||||
|
||||
if( it.Reference == currentlySelectedObject )
|
||||
{
|
||||
it.IsSelected = true;
|
||||
currentlySelectedItem = it;
|
||||
}
|
||||
else
|
||||
it.IsSelected = false;
|
||||
|
||||
it.Skin = Skin;
|
||||
}
|
||||
|
||||
void IListViewAdapter.OnItemClicked( RecycledListItem item )
|
||||
{
|
||||
if( currentlySelectedItem != null )
|
||||
currentlySelectedItem.IsSelected = false;
|
||||
|
||||
currentlySelectedItem = (ObjectReferencePickerItem) item;
|
||||
currentlySelectedObject = currentlySelectedItem.Reference;
|
||||
currentlySelectedItem.IsSelected = true;
|
||||
|
||||
try
|
||||
{
|
||||
if( onReferenceChanged != null )
|
||||
onReferenceChanged( currentlySelectedObject );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
Debug.LogException( e );
|
||||
}
|
||||
}
|
||||
|
||||
public static void DestroyInstance()
|
||||
{
|
||||
if( m_instance )
|
||||
{
|
||||
RuntimeInspectorUtils.IgnoredTransformsInHierarchy.Remove( m_instance.transform );
|
||||
|
||||
Destroy( m_instance );
|
||||
m_instance = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 34d218b6946ca1d49bfb743832030e9e
|
||||
timeCreated: 1506438580
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,89 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace RuntimeInspectorNamespace
|
||||
{
|
||||
public class ObjectReferencePickerItem : RecycledListItem
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
private Image background;
|
||||
|
||||
[SerializeField]
|
||||
private RawImage texturePreview;
|
||||
private LayoutElement texturePreviewLayoutElement;
|
||||
|
||||
[SerializeField]
|
||||
private Text referenceNameText;
|
||||
#pragma warning restore 0649
|
||||
|
||||
public object Reference { get; private set; }
|
||||
|
||||
private int m_skinVersion = 0;
|
||||
private UISkin m_skin;
|
||||
public UISkin Skin
|
||||
{
|
||||
get { return m_skin; }
|
||||
set
|
||||
{
|
||||
if( m_skin != value || m_skinVersion != m_skin.Version )
|
||||
{
|
||||
m_skin = value;
|
||||
|
||||
( (RectTransform) transform ).sizeDelta = new Vector2( 0f, Skin.LineHeight );
|
||||
|
||||
int previewDimensions = Mathf.Max( 5, Skin.LineHeight - 7 );
|
||||
texturePreviewLayoutElement.SetWidth( previewDimensions );
|
||||
texturePreviewLayoutElement.SetHeight( previewDimensions );
|
||||
|
||||
referenceNameText.SetSkinText( m_skin );
|
||||
|
||||
IsSelected = m_isSelected;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool m_isSelected = false;
|
||||
public bool IsSelected
|
||||
{
|
||||
get { return m_isSelected; }
|
||||
set
|
||||
{
|
||||
m_isSelected = value;
|
||||
|
||||
if( m_isSelected )
|
||||
{
|
||||
background.color = Skin.SelectedItemBackgroundColor;
|
||||
referenceNameText.color = Skin.SelectedItemTextColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
background.color = Color.clear;
|
||||
referenceNameText.color = Skin.TextColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
texturePreviewLayoutElement = texturePreview.GetComponent<LayoutElement>();
|
||||
GetComponent<PointerEventListener>().PointerClick += ( eventData ) => OnClick();
|
||||
}
|
||||
|
||||
public void SetContent( object reference, string displayName )
|
||||
{
|
||||
Reference = reference;
|
||||
referenceNameText.text = displayName;
|
||||
|
||||
Texture previewTex = ( reference as Object ).GetTexture();
|
||||
if( previewTex != null )
|
||||
{
|
||||
texturePreview.gameObject.SetActive( true );
|
||||
texturePreview.texture = previewTex;
|
||||
}
|
||||
else
|
||||
texturePreview.gameObject.SetActive( false );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 35334171e5bbdaf499da4d6a8a3e61f7
|
||||
timeCreated: 1506438954
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user