- Home /
Draw call minimizer
I installed the Free Draw Call Minimizer package from the asset store in order to assist in the optimization of my game for android devleopment. However I imported it and got this error:
error CS0117: GUIHelper' does not contain a definition for
VisibleRect'
This is the script in which i get the error:
// Copyright (c) 2012-2013 Rotorz Limited. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
using UnityEngine;
using UnityEditor;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using DCM.ReorderableList.Internal;
namespace DCM.ReorderableList {
/// <summary>
/// Arguments which are passed to <see cref="ItemInsertedEventHandler"/>.
/// </summary>
public sealed class ItemInsertedEventArgs : EventArgs {
/// <summary>
/// Gets adaptor to reorderable list container which contains element.
/// </summary>
public IReorderableListAdaptor adaptor { get; private set; }
/// <summary>
/// Gets zero-based index of item which was inserted.
/// </summary>
public int itemIndex { get; private set; }
/// <summary>
/// Indicates if inserted item was duplicated from another item.
/// </summary>
public bool wasDuplicated { get; private set; }
/// <summary>
/// Initializes a new instance of <see cref="ItemInsertedEventArgs"/>.
/// </summary>
/// <param name="adaptor">Reorderable list adaptor.</param>
/// <param name="itemIndex">Zero-based index of item.</param>
/// <param name="wasDuplicated">Indicates if inserted item was duplicated from another item.</param>
public ItemInsertedEventArgs(IReorderableListAdaptor adaptor, int itemIndex, bool wasDuplicated) {
this.adaptor = adaptor;
this.itemIndex = itemIndex;
this.wasDuplicated = wasDuplicated;
}
}
/// <summary>
/// An event handler which is invoked after new list item is inserted.
/// </summary>
/// <param name="sender">Object which raised event.</param>
/// <param name="args">Event arguments.</param>
public delegate void ItemInsertedEventHandler(object sender, ItemInsertedEventArgs args);
/// <summary>
/// Arguments which are passed to <see cref="ItemRemovingEventHandler"/>.
/// </summary>
public sealed class ItemRemovingEventArgs : CancelEventArgs {
/// <summary>
/// Gets adaptor to reorderable list container which contains element.
/// </summary>
public IReorderableListAdaptor adaptor { get; private set; }
/// <summary>
/// Gets zero-based index of item which was inserted.
/// </summary>
public int itemIndex { get; internal set; }
/// <summary>
/// Initializes a new instance of <see cref="ItemInsertedEventArgs"/>.
/// </summary>
/// <param name="adaptor">Reorderable list adaptor.</param>
/// <param name="itemIndex">Zero-based index of item.</param>
public ItemRemovingEventArgs(IReorderableListAdaptor adaptor, int itemIndex) {
this.adaptor = adaptor;
this.itemIndex = itemIndex;
}
}
/// <summary>
/// An event handler which is invoked before a list item is removed.
/// </summary>
/// <remarks>
/// <para>Item removal can be cancelled by setting <see cref="CancelEventArgs.Cancel"/>
/// to <c>true</c>.</para>
/// </remarks>
/// <param name="sender">Object which raised event.</param>
/// <param name="args">Event arguments.</param>
public delegate void ItemRemovingEventHandler(object sender, ItemRemovingEventArgs args);
/// <summary>
/// Base class for custom reorderable list control.
/// </summary>
[Serializable]
public class ReorderableListControl {
/// <summary>
/// Invoked to draw list item.
/// </summary>
/// <remarks>
/// <para>GUI controls must be positioned absolutely within the given rectangle since
/// list items must be sized consistently.</para>
/// </remarks>
/// <example>
/// <para>The following listing presents a text field for each list item:</para>
/// <code language="csharp"><![CDATA[
/// using UnityEngine;
/// using UnityEditor;
///
/// using System.Collections.Generic;
///
/// public class ExampleWindow : EditorWindow {
/// public List<string> wishlist = new List<string>();
///
/// private void OnGUI() {
/// ReorderableListGUI.ListField(wishlist, DrawListItem);
/// }
///
/// private string DrawListItem(Rect position, string value) {
/// // Text fields do not like `null` values!
/// if (value == null)
/// value = "";
/// return EditorGUI.TextField(position, value);
/// }
/// }
/// ]]></code>
/// <code language="unityscript"><![CDATA[
/// import System.Collections.Generic;
///
/// class ExampleWindow extends EditorWindow {
/// var wishlist:List.<String>;
///
/// function OnGUI() {
/// ReorderableListGUI.ListField(wishlist, DrawListItem);
/// }
///
/// function DrawListItem(position:Rect, value:String):String {
/// // Text fields do not like `null` values!
/// if (value == null)
/// value = '';
/// return EditorGUI.TextField(position, value);
/// }
/// }
/// ]]></code>
/// </example>
/// <typeparam name="T">Type of item list.</typeparam>
/// <param name="position">Position of list item.</param>
/// <param name="item">The list item.</param>
/// <returns>
/// The modified value.
/// </returns>
public delegate T ItemDrawer<T>(Rect position, T item);
/// <summary>
/// Invoked to draw content for empty list.
/// </summary>
/// <remarks>
/// <para>Callback should make use of <c>GUILayout</c> to present controls.</para>
/// </remarks>
/// <example>
/// <para>The following listing displays a label for empty list control:</para>
/// <code language="csharp"><![CDATA[
/// using UnityEngine;
/// using UnityEditor;
///
/// using System.Collections.Generic;
///
/// public class ExampleWindow : EditorWindow {
/// private List<string> _list;
///
/// private void OnEnable() {
/// _list = new List<string>();
/// }
/// private void OnGUI() {
/// ReorderableListGUI.ListField(_list, ReorderableListGUI.TextFieldItemDrawer, DrawEmptyMessage);
/// }
///
/// private string DrawEmptyMessage() {
/// GUILayout.Label("List is empty!", EditorStyles.miniLabel);
/// }
/// }
/// ]]></code>
/// <code language="unityscript"><![CDATA[
/// import System.Collections.Generic;
///
/// class ExampleWindow extends EditorWindow {
/// private var _list:List.<String>;
///
/// function OnEnable() {
/// _list = new List.<String>();
/// }
/// function OnGUI() {
/// ReorderableListGUI.ListField(_list, ReorderableListGUI.TextFieldItemDrawer, DrawEmptyMessage);
/// }
///
/// function DrawEmptyMessage() {
/// GUILayout.Label('List is empty!', EditorStyles.miniLabel);
/// }
/// }
/// ]]></code>
/// </example>
public delegate void DrawEmpty();
/// <summary>
/// Invoked to draw content for empty list with absolute positioning.
/// </summary>
/// <param name="position">Position of empty content.</param>
public delegate void DrawEmptyAbsolute(Rect position);
#region Custom Styles
/// <summary>
/// Background color of anchor list item.
/// </summary>
public static readonly Color AnchorBackgroundColor;
/// <summary>
/// Background color of target slot when dragging list item.
/// </summary>
public static readonly Color TargetBackgroundColor;
/// <summary>
/// Style for right-aligned label for element number prefix.
/// </summary>
private static GUIStyle s_RightAlignedLabelStyle;
private static GUIContent s_RemoveButtonNormalContent;
private static GUIContent s_RemoveButtonActiveContent;
static ReorderableListControl() {
s_CurrentItemIndex = new Stack<int>();
s_CurrentItemIndex.Push(-1);
if (EditorGUIUtility.isProSkin) {
AnchorBackgroundColor = new Color(85f / 255f, 85f / 255f, 85f / 255f, 0.85f);
TargetBackgroundColor = new Color(0, 0, 0, 0.5f);
}
else {
AnchorBackgroundColor = new Color(225f / 255f, 225f / 255f, 225f / 255f, 0.85f);
TargetBackgroundColor = new Color(0, 0, 0, 0.5f);
}
s_RemoveButtonNormalContent = new GUIContent(ReorderableListResources.texRemoveButton);
s_RemoveButtonActiveContent = new GUIContent(ReorderableListResources.texRemoveButtonActive);
}
#endregion
#region Utility
/// <summary>
/// Generate and draw control from state object.
/// </summary>
/// <param name="adaptor">Reorderable list adaptor.</param>
/// <param name="drawEmpty">Delegate for drawing empty list.</param>
/// <param name="flags">Optional flags to pass into list field.</param>
public static void DrawControlFromState(IReorderableListAdaptor adaptor, DrawEmpty drawEmpty, ReorderableListFlags flags) {
int controlID = GUIUtility.GetControlID(FocusType.Passive);
var control = GUIUtility.GetStateObject(typeof(ReorderableListControl), controlID) as ReorderableListControl;
control.flags = flags;
control.Draw(controlID, adaptor, drawEmpty);
}
/// <summary>
/// Generate and draw control from state object.
/// </summary>
/// <param name="position">Position of control.</param>
/// <param name="adaptor">Reorderable list adaptor.</param>
/// <param name="drawEmpty">Delegate for drawing empty list.</param>
/// <param name="flags">Optional flags to pass into list field.</param>
public static void DrawControlFromState(Rect position, IReorderableListAdaptor adaptor, DrawEmptyAbsolute drawEmpty, ReorderableListFlags flags) {
int controlID = GUIUtility.GetControlID(FocusType.Passive);
var control = GUIUtility.GetStateObject(typeof(ReorderableListControl), controlID) as ReorderableListControl;
control.flags = flags;
control.Draw(position, controlID, adaptor, drawEmpty);
}
#endregion
/// <summary>
/// Position of mouse upon anchoring item for drag.
/// </summary>
private static float s_AnchorMouseOffset;
/// <summary>
/// Zero-based index of anchored list item.
/// </summary>
private static int s_AnchorIndex = -1;
/// <summary>
/// Zero-based index of target list item for reordering.
/// </summary>
private static int s_TargetIndex = -1;
/// <summary>
/// Unique ID of list control which should be automatically focused. A value
/// of zero indicates that no control is to be focused.
/// </summary>
private static int s_AutoFocusControlID = 0;
/// <summary>
/// Zero-based index of item which should be focused.
/// </summary>
private static int s_AutoFocusIndex = -1;
/// <summary>
/// Zero-based index of list item which is currently being drawn.
/// </summary>
private static Stack<int> s_CurrentItemIndex;
/// <summary>
/// Gets zero-based index of list item which is currently being drawn;
/// or a value of -1 if no item is currently being drawn.
/// </summary>
/// <remarks>
/// <para>Use <see cref="ReorderableListGUI.currentItemIndex"/> instead.</para>
/// </remarks>
internal static int currentItemIndex {
get { return s_CurrentItemIndex.Peek(); }
}
#region Properties
[SerializeField]
private ReorderableListFlags _flags;
/// <summary>
/// Gets or sets flags which affect behavior of control.
/// </summary>
public ReorderableListFlags flags {
get { return _flags; }
set { _flags = value; }
}
/// <summary>
/// Gets a value indicating whether add button is shown.
/// </summary>
private bool hasAddButton {
get { return (_flags & ReorderableListFlags.HideAddButton) == 0; }
}
/// <summary>
/// Gets a value indicating whether remove buttons are shown.
/// </summary>
private bool hasRemoveButtons {
get { return (_flags & ReorderableListFlags.HideRemoveButtons) == 0; }
}
[SerializeField]
private GUIStyle _containerStyle;
[SerializeField]
private GUIStyle _addButtonStyle;
[SerializeField]
private GUIStyle _removeButtonStyle;
/// <summary>
/// Gets or sets style used to draw background of list control.
/// </summary>
/// <seealso cref="ReorderableListGUI.defaultContainerStyle"/>
public GUIStyle containerStyle {
get { return _containerStyle; }
set { _containerStyle = value; }
}
/// <summary>
/// Gets or sets style used to draw add button.
/// </summary>
/// <seealso cref="ReorderableListGUI.defaultAddButtonStyle"/>
public GUIStyle addButtonStyle {
get { return _addButtonStyle; }
set { _addButtonStyle = value; }
}
/// <summary>
/// Gets or sets style used to draw remove button.
/// </summary>
/// <seealso cref="ReorderableListGUI.defaultRemoveButtonStyle"/>
public GUIStyle removeButtonStyle {
get { return _removeButtonStyle; }
set { _removeButtonStyle = value; }
}
#endregion
#region Events
/// <summary>
/// Occurs after list item is inserted or duplicated.
/// </summary>
public event ItemInsertedEventHandler ItemInserted;
/// <summary>
/// Raises event after list item is inserted or duplicated.
/// </summary>
/// <param name="args">Event arguments.</param>
protected virtual void OnItemInserted(ItemInsertedEventArgs args) {
if (ItemInserted != null)
ItemInserted(this, args);
}
/// <summary>
/// Occurs before list item is removed and allows removal to be cancelled.
/// </summary>
public event ItemRemovingEventHandler ItemRemoving;
/// <summary>
/// Raises event before list item is removed and provides oppertunity to cancel.
/// </summary>
/// <param name="args">Event arguments.</param>
protected virtual void OnItemRemoving(ItemRemovingEventArgs args) {
if (ItemRemoving != null)
ItemRemoving(this, args);
}
#endregion
#region Construction
/// <summary>
/// Initializes a new instance of <see cref="ReorderableListControl"/>.
/// </summary>
public ReorderableListControl() {
_containerStyle = ReorderableListGUI.defaultContainerStyle;
_addButtonStyle = ReorderableListGUI.defaultAddButtonStyle;
_removeButtonStyle = ReorderableListGUI.defaultRemoveButtonStyle;
}
/// <summary>
/// Initializes a new instance of <see cref="ReorderableListControl"/>.
/// </summary>
/// <param name="flags">Optional flags which affect behavior of control.</param>
public ReorderableListControl(ReorderableListFlags flags)
: this() {
this.flags = flags;
}
#endregion
#region Control State
/// <summary>
/// Unique Id of control.
/// </summary>
private int _controlID;
/// <summary>
/// Visible rectangle of control.
/// </summary>
private Rect _visibleRect;
/// <summary>
/// Width of index label in pixels (zero indicates no label).
/// </summary>
private float _indexLabelWidth;
/// <summary>
/// Indicates whether item is currently being dragged within control.
/// </summary>
private bool _tracking;
/// <summary>
/// Indicates if reordering is allowed.
/// </summary>
private bool _allowReordering;
/// <summary>
/// Prepare initial state for list control.
/// </summary>
/// <param name="controlID">Unique ID of list control.</param>
/// <param name="adaptor">Reorderable list adaptor.</param>
private void PrepareState(int controlID, IReorderableListAdaptor adaptor) {
_controlID = controlID;
_visibleRect = GUIHelper.VisibleRect();
if ((flags & ReorderableListFlags.ShowIndices) != 0) {
int digitCount = Mathf.Max(2, Mathf.CeilToInt(Mathf.Log10((float)adaptor.Count)));
_indexLabelWidth = digitCount * 8 + 8;
}
else {
_indexLabelWidth = 0;
}
_tracking = IsTrackingControl(controlID);
_allowReordering = (flags & ReorderableListFlags.DisableReordering) == 0;
}
#endregion
#region Event Handling
// Keep track of previously known mouse position (in screen space).
private static Vector2 s_MousePosition;
/// <summary>
/// Indicate that first control of list item should be automatically focused
/// if possible.
/// </summary>
/// <param name="controlID">Unique ID of list control.</param>
/// <param name="itemIndex">Zero-based index of list item.</param>
private void AutoFocusItem(int controlID, int itemIndex) {
if ((flags & ReorderableListFlags.DisableAutoFocus) == 0) {
s_AutoFocusControlID = controlID;
s_AutoFocusIndex = itemIndex;
}
}
/// <summary>
/// Draw add item button.
/// </summary>
/// <param name="position">Position of button.</param>
/// <param name="controlID">Unique ID of list control.</param>
/// <param name="adaptor">Reorderable list adaptor.</param>
private void DoAddButton(Rect position, int controlID, IReorderableListAdaptor adaptor) {
if (GUI.Button(position, GUIContent.none, addButtonStyle)) {
// Append item to list.
GUIUtility.keyboardControl = 0;
AddItem(adaptor);
}
}
/// <summary>
/// Draw remove button.
/// </summary>
/// <param name="position">Position of button.</param>
/// <param name="visible">Indicates if control is visible within GUI.</param>
/// <returns>
/// A value of <c>true</c> if clicked; otherwise <c>false</c>.
/// </returns>
private bool DoRemoveButton(Rect position, bool visible) {
int controlID = GUIUtility.GetControlID(FocusType.Passive);
Vector2 mousePosition = GUIUtility.ScreenToGUIPoint(s_MousePosition);
switch (Event.current.GetTypeForControl(controlID)) {
case EventType.MouseDown:
// Do not allow button to be pressed using right mouse button since
// context menu should be shown instead!
if (GUI.enabled && Event.current.button != 1 && position.Contains(mousePosition)) {
GUIUtility.hotControl = controlID;
GUIUtility.keyboardControl = 0;
Event.current.Use();
}
break;
case EventType.MouseDrag:
if (GUIUtility.hotControl == controlID)
Event.current.Use();
break;
case EventType.MouseUp:
if (GUIUtility.hotControl == controlID) {
GUIUtility.hotControl = 0;
if (position.Contains(mousePosition)) {
Event.current.Use();
return true;
}
else {
Event.current.Use();
return false;
}
}
break;
case EventType.Repaint:
if (visible) {
var content = (GUIUtility.hotControl == controlID && position.Contains(mousePosition))
? s_RemoveButtonActiveContent
: s_RemoveButtonNormalContent;
removeButtonStyle.Draw(position, content, controlID);
}
break;
}
return false;
}
private static bool s_TrackingCancelBlockContext;
/// <summary>
/// Begin tracking drag and drop within list.
/// </summary>
/// <param name="controlID">Unique ID of list control.</param>
/// <param name="itemIndex">Zero-based index of item which is going to be dragged.</param>
private static void BeginTrackingReorderDrag(int controlID, int itemIndex) {
GUIUtility.hotControl = controlID;
GUIUtility.keyboardControl = 0;
s_AnchorIndex = itemIndex;
s_TargetIndex = itemIndex;
s_TrackingCancelBlockContext = false;
}
/// <summary>
/// Stop tracking drag and drop.
/// </summary>
private static void StopTrackingReorderDrag() {
GUIUtility.hotControl = 0;
s_AnchorIndex = -1;
s_TargetIndex = -1;
}
/// <summary>
/// Gets a value indicating whether item in current list is currently being tracked.
/// </summary>
/// <param name="controlID">Unique ID of list control.</param>
/// <returns>
/// A value of <c>true</c> if item is being tracked; otherwise <c>false</c>.
/// </returns>
private static bool IsTrackingControl(int controlID) {
return !s_TrackingCancelBlockContext && GUIUtility.hotControl == controlID;
}
/// <summary>
/// Accept reordering.
/// </summary>
/// <param name="adaptor">Reorderable list adaptor.</param>
private void AcceptReorderDrag(IReorderableListAdaptor adaptor) {
try {
// Reorder list as needed!
s_TargetIndex = Mathf.Clamp(s_TargetIndex, 0, adaptor.Count + 1);
if (s_TargetIndex != s_AnchorIndex && s_TargetIndex != s_AnchorIndex + 1)
MoveItem(adaptor, s_AnchorIndex, s_TargetIndex);
}
finally {
StopTrackingReorderDrag();
}
}
private static Rect s_DragItemPosition;
// Micro-optimisation to avoid repeated construction.
private static Rect s_RemoveButtonPosition;
private void DrawListItem(EventType eventType, Rect position, IReorderableListAdaptor adaptor, int itemIndex) {
bool visible = (position.y < _visibleRect.yMax && position.yMax > _visibleRect.y);
bool draggable = _allowReordering && adaptor.CanDrag(itemIndex);
Rect itemContentPosition = position;
itemContentPosition.x = position.x + 2;
itemContentPosition.y += 1;
itemContentPosition.width = position.width - 4;
itemContentPosition.height = position.height - 4;
// Make space for grab handle?
if (draggable) {
itemContentPosition.x += 20;
itemContentPosition.width -= 20;
}
// Make space for element index.
if (_indexLabelWidth != 0) {
itemContentPosition.width -= _indexLabelWidth;
if (eventType == EventType.Repaint && visible)
s_RightAlignedLabelStyle.Draw(new Rect(itemContentPosition.x, position.y, _indexLabelWidth, position.height - 4), itemIndex + ":", false, false, false, false);
itemContentPosition.x += _indexLabelWidth;
}
// Make space for remove button?
if (hasRemoveButtons)
itemContentPosition.width -= removeButtonStyle.fixedWidth;
if (eventType == EventType.Repaint && visible) {
// Draw grab handle?
if (draggable)
GUI.DrawTexture(new Rect(position.x + 6, position.y + position.height / 2f - 3, 9, 5), ReorderableListResources.texGrabHandle);
// Draw splitter between list items.
if (!_tracking || itemIndex != s_AnchorIndex)
GUI.DrawTexture(new Rect(position.x, position.y - 1, position.width, 1), ReorderableListResources.texItemSplitter);
}
// Allow control to be automatically focused.
if (s_AutoFocusIndex == itemIndex)
GUI.SetNextControlName("AutoFocus_" + _controlID + "_" + itemIndex);
try {
s_CurrentItemIndex.Push(itemIndex);
// Present actual control.
EditorGUI.BeginChangeCheck();
adaptor.DrawItem(itemContentPosition, itemIndex);
if (EditorGUI.EndChangeCheck())
ReorderableListGUI.indexOfChangedItem = itemIndex;
// Draw remove button?
if (hasRemoveButtons && adaptor.CanRemove(itemIndex)) {
s_RemoveButtonPosition = position;
s_RemoveButtonPosition.width = removeButtonStyle.fixedWidth;
s_RemoveButtonPosition.x = itemContentPosition.xMax + 2;
s_RemoveButtonPosition.height -= 2;
if (DoRemoveButton(s_RemoveButtonPosition, visible))
RemoveItem(adaptor, itemIndex);
}
// Check for context click?
if (eventType == EventType.ContextClick && position.Contains(Event.current.mousePosition) && (flags & ReorderableListFlags.DisableContextMenu) == 0) {
ShowContextMenu(_controlID, itemIndex, adaptor);
Event.current.Use();
}
}
finally {
s_CurrentItemIndex.Pop();
}
}
private void DrawFloatingListItem(EventType eventType, IReorderableListAdaptor adaptor, float targetSlotPosition) {
if (eventType == EventType.Repaint) {
Color restoreColor = GUI.color;
// Fill background of target area.
Rect targetPosition = s_DragItemPosition;
targetPosition.y = targetSlotPosition - 1;
targetPosition.height = 1;
GUI.DrawTexture(targetPosition, ReorderableListResources.texItemSplitter);
--targetPosition.x;
++targetPosition.y;
targetPosition.width += 2;
targetPosition.height = s_DragItemPosition.height - 1;
GUI.color = TargetBackgroundColor;
GUI.DrawTexture(targetPosition, EditorGUIUtility.whiteTexture);
// Fill background of item which is being dragged.
--s_DragItemPosition.x;
s_DragItemPosition.width += 2;
--s_DragItemPosition.height;
GUI.color = AnchorBackgroundColor;
GUI.DrawTexture(s_DragItemPosition, EditorGUIUtility.whiteTexture);
++s_DragItemPosition.x;
s_DragItemPosition.width -= 2;
++s_DragItemPosition.height;
// Draw horizontal splitter above and below.
GUI.color = new Color(0f, 0f, 0f, 0.6f);
targetPosition.y = s_DragItemPosition.y - 1;
targetPosition.height = 1;
GUI.DrawTexture(targetPosition, EditorGUIUtility.whiteTexture);
targetPosition.y += s_DragItemPosition.height;
GUI.DrawTexture(targetPosition, EditorGUIUtility.whiteTexture);
GUI.color = restoreColor;
}
DrawListItem(eventType, s_DragItemPosition, adaptor, s_AnchorIndex);
}
/// <summary>
/// Draw list container and items.
/// </summary>
/// <param name="position">Position of list control in GUI.</param>
/// <param name="controlID">Unique ID of list control.</param>
/// <param name="adaptor">Reorderable list adaptor.</param>
private void DrawListContainerAndItems(Rect position, int controlID, IReorderableListAdaptor adaptor) {
// Get local copy of event information for efficiency.
EventType eventType = Event.current.GetTypeForControl(controlID);
Vector2 mousePosition = Event.current.mousePosition;
if (Event.current.isMouse)
s_MousePosition = GUIUtility.GUIToScreenPoint(mousePosition);
int newTargetIndex = s_TargetIndex;
// Position of first item in list.
float firstItemY = position.y + containerStyle.padding.top;
switch (eventType) {
case EventType.MouseDown:
if (_tracking) {
// Cancel drag when other mouse button is pressed.
s_TrackingCancelBlockContext = true;
Event.current.Use();
}
break;
case EventType.MouseDrag:
if (_tracking) {
// Reset target index and adjust when looping through list items.
if (mousePosition.y < firstItemY)
newTargetIndex = 0;
else if (mousePosition.y >= position.yMax)
newTargetIndex = adaptor.Count;
s_DragItemPosition.y = Mathf.Clamp(mousePosition.y + s_AnchorMouseOffset, firstItemY, position.yMax - s_DragItemPosition.height - 1);
}
break;
case EventType.MouseUp:
if (controlID == GUIUtility.hotControl) {
// Allow user code to change control over reordering during drag.
if (!s_TrackingCancelBlockContext && _allowReordering)
AcceptReorderDrag(adaptor);
else
StopTrackingReorderDrag();
Event.current.Use();
}
break;
case EventType.KeyDown:
if (_tracking && Event.current.keyCode == KeyCode.Escape) {
StopTrackingReorderDrag();
Event.current.Use();
}
break;
case EventType.ExecuteCommand:
if (s_ContextControlID == controlID) {
int itemIndex = s_ContextItemIndex;
try {
DoCommand(s_ContextCommandName, itemIndex, adaptor);
Event.current.Use();
}
finally {
s_ContextControlID = 0;
s_ContextItemIndex = 0;
}
}
break;
case EventType.Repaint:
// Draw caption area of list.
containerStyle.Draw(position, GUIContent.none, false, false, false, false);
break;
}
ReorderableListGUI.indexOfChangedItem = -1;
// Draw list items!
Rect itemPosition = new Rect(position.x + 2, firstItemY, position.width - 4, 0);
float targetSlotPosition = position.yMax - s_DragItemPosition.height - 1;
float lastMidPoint = 0f;
float lastHeight = 0f;
int count = adaptor.Count;
for (int i = 0; i < count; ++i) {
itemPosition.y = itemPosition.yMax;
itemPosition.height = 0;
if (_tracking) {
// Does this represent the target index?
if (i == s_TargetIndex) {
targetSlotPosition = itemPosition.y;
itemPosition.y += s_DragItemPosition.height;
}
// Do not draw item if it is currently being dragged.
// Draw later so that it is shown in front of other controls.
if (i == s_AnchorIndex)
continue;
lastMidPoint = itemPosition.y - lastHeight / 2f;
}
// Update position for current item.
itemPosition.height = adaptor.GetItemHeight(i) + 4;
lastHeight = itemPosition.height;
if (_tracking && eventType == EventType.MouseDrag) {
float midpoint = itemPosition.y + itemPosition.height / 2f;
if (s_TargetIndex < i) {
if (s_DragItemPosition.yMax > lastMidPoint && s_DragItemPosition.yMax < midpoint)
newTargetIndex = i;
}
else if (s_TargetIndex > i) {
if (s_DragItemPosition.y > lastMidPoint && s_DragItemPosition.y < midpoint)
newTargetIndex = i;
}
/*if (s_DragItemPosition.y > itemPosition.y && s_DragItemPosition.y <= midpoint)
newTargetIndex = i;
else if (s_DragItemPosition.yMax > midpoint && s_DragItemPosition.yMax <= itemPosition.yMax)
newTargetIndex = i + 1;*/
}
// The following may break use of tab key to navigate through controls :/
if ((flags & ReorderableListFlags.DisableClipping) == 0) {
// Clip list item? Performance boost!
if (itemPosition.yMax < _visibleRect.y - itemPosition.height) {
// Let's try and trick Unity into maintaining tab key support...
GUIUtility.GetControlID(FocusType.Keyboard, itemPosition);
continue;
}
if (itemPosition.y > _visibleRect.yMax + itemPosition.height)
break;
}
// Draw list item.
DrawListItem(eventType, itemPosition, adaptor, i);
// Did list count change (i.e. item removed)?
if (adaptor.Count < count) {
// We assume that it was this item which was removed, so --i allows us
// to process the next item as usual.
count = adaptor.Count;
--i;
continue;
}
// Event has already been used, skip to next item.
if (Event.current.type != EventType.Used) {
switch (eventType) {
case EventType.MouseDown:
if (GUI.enabled && itemPosition.Contains(mousePosition)) {
// Remove input focus from control before attempting a context click or drag.
GUIUtility.keyboardControl = 0;
if (_allowReordering && adaptor.CanDrag(i) && Event.current.button == 0) {
s_DragItemPosition = itemPosition;
BeginTrackingReorderDrag(controlID, i);
s_AnchorMouseOffset = itemPosition.y - mousePosition.y;
s_TargetIndex = i;
Event.current.Use();
}
}
break;
/* DEBUG
case EventType.Repaint:
GUI.color = Color.red;
GUI.DrawTexture(new Rect(0, lastMidPoint, 10, 1), EditorGUIUtility.whiteTexture);
GUI.color = Color.yellow;
GUI.DrawTexture(new Rect(5, itemPosition.y + itemPosition.height / 2f, 10, 1), EditorGUIUtility.whiteTexture);
GUI.color = Color.white;
break;
//*/
}
}
}
// Item which is being dragged should be shown on top of other controls!
if (IsTrackingControl(controlID)) {
lastMidPoint = position.yMax - lastHeight / 2f;
if (eventType == EventType.MouseDrag) {
if (s_DragItemPosition.yMax >= lastMidPoint)
newTargetIndex = count;
// Force repaint to occur so that dragging rectangle is visible.
s_TargetIndex = newTargetIndex;
Event.current.Use();
}
DrawFloatingListItem(eventType, adaptor, targetSlotPosition);
/* DEBUG
if (eventType == EventType.Repaint) {
GUI.color = Color.blue;
GUI.DrawTexture(new Rect(100, lastMidPoint, 20, 1), EditorGUIUtility.whiteTexture);
GUI.color = Color.white;
}
//*/
}
// Fake control to catch input focus if auto focus was not possible.
GUIUtility.GetControlID(FocusType.Keyboard);
}
/// <summary>
/// Checks to see if list control needs to be automatically focused.
/// </summary>
/// <param name="controlID">Unique ID of list control.</param>
private void CheckForAutoFocusControl(int controlID) {
if (Event.current.type == EventType.Used)
return;
// Automatically focus control!
if (s_AutoFocusControlID == controlID) {
s_AutoFocusControlID = 0;
GUIHelper.FocusTextInControl("AutoFocus_" + controlID + "_" + s_AutoFocusIndex);
s_AutoFocusIndex = -1;
}
}
/// <summary>
/// Draw additional controls below list control and highlight drop target.
/// </summary>
/// <param name="position">Position of list control in GUI.</param>
/// <param name="controlID">Unique ID of list control.</param>
/// <param name="adaptor">Reorderable list adaptor.</param>
private void DrawFooterControls(Rect position, int controlID, IReorderableListAdaptor adaptor) {
if (hasAddButton) {
Rect addButtonRect = new Rect(
position.xMax - addButtonStyle.fixedWidth,
position.yMax - 1,
addButtonStyle.fixedWidth,
addButtonStyle.fixedHeight
);
DoAddButton(addButtonRect, controlID, adaptor);
}
}
/// <summary>
/// Cache of container heights mapped by control ID.
/// </summary>
private static Dictionary<int, float> s_ContainerHeightCache = new Dictionary<int, float>();
/// <summary>
/// Do layout version of list field.
/// </summary>
/// <param name="controlID">Unique ID of list control.</param>
/// <param name="adaptor">Reorderable list adaptor.</param>
/// <returns>
/// Position of list container area in GUI (excludes footer area).
/// </returns>
private Rect DrawLayoutListField(int controlID, IReorderableListAdaptor adaptor) {
float totalHeight;
// Calculate position of list field using layout engine.
if (Event.current.type == EventType.Layout) {
totalHeight = CalculateListHeight(adaptor);
s_ContainerHeightCache[controlID] = totalHeight;
}
else {
totalHeight = s_ContainerHeightCache.ContainsKey(controlID)
? s_ContainerHeightCache[controlID]
: 0;
}
Rect position = GUILayoutUtility.GetRect(GUIContent.none, containerStyle, GUILayout.Height(totalHeight));
// Make room for add button?
if (hasAddButton)
position.height -= addButtonStyle.fixedHeight;
// Draw list as normal.
DrawListContainerAndItems(position, controlID, adaptor);
CheckForAutoFocusControl(controlID);
return position;
}
/// <summary>
/// Draw content for empty list (layout version).
/// </summary>
/// <param name="drawEmpty">Callback to draw empty content.</param>
/// <returns>
/// Position of list container area in GUI (excludes footer area).
/// </returns>
private Rect DrawLayoutEmptyList(DrawEmpty drawEmpty) {
Rect r = EditorGUILayout.BeginVertical(containerStyle);
{
if (drawEmpty != null)
drawEmpty();
else
GUILayout.Space(5);
}
EditorGUILayout.EndVertical();
// Allow room for add button.
GUILayoutUtility.GetRect(0, addButtonStyle.fixedHeight - 1);
return r;
}
/// <summary>
/// Draw content for empty list (layout version).
/// </summary>
/// <param name="position">Position of list control in GUI.</param>
/// <param name="drawEmpty">Callback to draw empty content.</param>
private void DrawEmptyListControl(Rect position, DrawEmptyAbsolute drawEmpty) {
if (Event.current.type == EventType.Repaint)
containerStyle.Draw(position, GUIContent.none, false, false, false, false);
// Take padding into consideration when drawing empty content.
position.x += containerStyle.padding.left;
position.y += containerStyle.padding.top;
position.width -= containerStyle.padding.horizontal;
position.height -= containerStyle.padding.vertical;
if (drawEmpty != null)
drawEmpty(position);
}
/// <summary>
/// Correct if for some reason one or more styles are missing!
/// </summary>
private void FixStyles() {
containerStyle = containerStyle ?? ReorderableListGUI.defaultContainerStyle;
addButtonStyle = addButtonStyle ?? ReorderableListGUI.defaultAddButtonStyle;
removeButtonStyle = removeButtonStyle ?? ReorderableListGUI.defaultRemoveButtonStyle;
if (s_RightAlignedLabelStyle == null) {
s_RightAlignedLabelStyle = new GUIStyle(GUI.skin.label);
s_RightAlignedLabelStyle.alignment = TextAnchor.MiddleRight;
s_RightAlignedLabelStyle.padding.right = 4;
}
}
/// <summary>
/// Draw layout version of list control.
/// </summary>
/// <param name="controlID">Unique ID of list control.</param>
/// <param name="adaptor">Reorderable list adaptor.</param>
/// <param name="drawEmpty">Delegate for drawing empty list.</param>
private void Draw(int controlID, IReorderableListAdaptor adaptor, DrawEmpty drawEmpty) {
FixStyles();
PrepareState(controlID, adaptor);
Rect position;
if (adaptor.Count > 0)
position = DrawLayoutListField(controlID, adaptor);
else
position = DrawLayoutEmptyList(drawEmpty);
DrawFooterControls(position, controlID, adaptor);
}
/// <inheritdoc cref="Draw(int, IReorderableListAdaptor, DrawEmpty)"/>
public void Draw(IReorderableListAdaptor adaptor, DrawEmpty drawEmpty) {
int controlID = GUIUtility.GetControlID(FocusType.Passive);
Draw(controlID, adaptor, drawEmpty);
}
/// <inheritdoc cref="Draw(int, IReorderableListAdaptor, DrawEmpty)"/>
public void Draw(IReorderableListAdaptor adaptor) {
int controlID = GUIUtility.GetControlID(FocusType.Passive);
Draw(controlID, adaptor, null);
}
/// <summary>
/// Draw list control with absolute positioning.
/// </summary>
/// <param name="position">Position of list control in GUI.</param>
/// <param name="controlID">Unique ID of list control.</param>
/// <param name="adaptor">Reorderable list adaptor.</param>
/// <param name="drawEmpty">Delegate for drawing empty list.</param>
private void Draw(Rect position, int controlID, IReorderableListAdaptor adaptor, DrawEmptyAbsolute drawEmpty) {
FixStyles();
PrepareState(controlID, adaptor);
// Allow for footer area.
if (hasAddButton)
position.height -= addButtonStyle.fixedHeight;
if (adaptor.Count > 0) {
DrawListContainerAndItems(position, controlID, adaptor);
CheckForAutoFocusControl(controlID);
}
else {
DrawEmptyListControl(position, drawEmpty);
}
DrawFooterControls(position, controlID, adaptor);
}
/// <summary>
/// Draw list control with absolute positioning.
/// </summary>
/// <param name="position">Position of list control in GUI.</param>
/// <param name="adaptor">Reorderable list adaptor.</param>
/// <param name="drawEmpty">Delegate for drawing empty list.</param>
public void Draw(Rect position, IReorderableListAdaptor adaptor, DrawEmptyAbsolute drawEmpty) {
int controlID = GUIUtility.GetControlID(FocusType.Passive);
Draw(position, controlID, adaptor, drawEmpty);
}
/// <inheritdoc cref="Draw(Rect, IReorderableListAdaptor, DrawEmptyAbsolute)"/>
public void Draw(Rect position, IReorderableListAdaptor adaptor) {
int controlID = GUIUtility.GetControlID(FocusType.Passive);
Draw(position, controlID, adaptor, null);
}
#endregion
#region Context Menu
/// <summary>
/// Content for "Move to Top" command.
/// </summary>
protected static readonly GUIContent commandMoveToTop = new GUIContent("Move to Top");
/// <summary>
/// Content for "Move to Bottom" command.
/// </summary>
protected static readonly GUIContent commandMoveToBottom = new GUIContent("Move to Bottom");
/// <summary>
/// Content for "Insert Above" command.
/// </summary>
protected static readonly GUIContent commandInsertAbove = new GUIContent("Insert Above");
/// <summary>
/// Content for "Insert Below" command.
/// </summary>
protected static readonly GUIContent commandInsertBelow = new GUIContent("Insert Below");
/// <summary>
/// Content for "Duplicate" command.
/// </summary>
protected static readonly GUIContent commandDuplicate = new GUIContent("Duplicate");
/// <summary>
/// Content for "Remove" command.
/// </summary>
protected static readonly GUIContent commandRemove = new GUIContent("Remove");
/// <summary>
/// Content for "Clear All" command.
/// </summary>
protected static readonly GUIContent commandClearAll = new GUIContent("Clear All");
// Command control id and item index are assigned when context menu is shown.
private static int s_ContextControlID;
private static int s_ContextItemIndex;
// Command name is assigned by default context menu handler.
private static string s_ContextCommandName;
private void ShowContextMenu(int controlID, int itemIndex, IReorderableListAdaptor adaptor) {
GenericMenu menu = new GenericMenu();
s_ContextControlID = controlID;
s_ContextItemIndex = itemIndex;
AddItemsToMenu(menu, itemIndex, adaptor);
if (menu.GetItemCount() > 0)
menu.ShowAsContext();
}
/// <summary>
/// Default functionality to handle context command.
/// </summary>
/// <example>
/// <para>Can be used when adding custom items to the context menu:</para>
/// <code language="csharp"><![CDATA[
/// protected override void AddItemsToMenu(GenericMenu menu, int itemIndex, IReorderableListAdaptor adaptor) {
/// var specialCommand = new GUIContent("Special Command");
/// menu.AddItem(specialCommand, false, defaultContextHandler, specialCommand);
/// }
/// ]]></code>
/// <code language="unityscript"><![CDATA[
/// function AddItemsToMenu(menu:GenericMenu, itemIndex:int, list:IReorderableListAdaptor) {
/// var specialCommand = new GUIContent('Special Command');
/// menu.AddItem(specialCommand, false, defaultContextHandler, specialCommand);
/// }
/// ]]></code>
/// </example>
/// <seealso cref="AddItemsToMenu"/>
protected static readonly GenericMenu.MenuFunction2 defaultContextHandler = DefaultContextMenuHandler;
private static void DefaultContextMenuHandler(object userData) {
var commandContent = userData as GUIContent;
if (commandContent == null || string.IsNullOrEmpty(commandContent.text))
return;
s_ContextCommandName = commandContent.text;
var e = EditorGUIUtility.CommandEvent("ReorderableListContextCommand");
EditorWindow.focusedWindow.SendEvent(e);
}
/// <summary>
/// Invoked to generate context menu for list item.
/// </summary>
/// <param name="menu">Menu which can be populated.</param>
/// <param name="itemIndex">Zero-based index of item which was right-clicked.</param>
/// <param name="adaptor">Reorderable list adaptor.</param>
protected virtual void AddItemsToMenu(GenericMenu menu, int itemIndex, IReorderableListAdaptor adaptor) {
if ((flags & ReorderableListFlags.DisableReordering) == 0) {
if (itemIndex > 0)
menu.AddItem(commandMoveToTop, false, defaultContextHandler, commandMoveToTop);
else
menu.AddDisabledItem(commandMoveToTop);
if (itemIndex + 1 < adaptor.Count)
menu.AddItem(commandMoveToBottom, false, defaultContextHandler, commandMoveToBottom);
else
menu.AddDisabledItem(commandMoveToBottom);
if (hasAddButton) {
menu.AddSeparator("");
menu.AddItem(commandInsertAbove, false, defaultContextHandler, commandInsertAbove);
menu.AddItem(commandInsertBelow, false, defaultContextHandler, commandInsertBelow);
if ((flags & ReorderableListFlags.DisableDuplicateCommand) == 0)
menu.AddItem(commandDuplicate, false, defaultContextHandler, commandDuplicate);
}
}
if (hasRemoveButtons) {
if (menu.GetItemCount() > 0)
menu.AddSeparator("");
menu.AddItem(commandRemove, false, defaultContextHandler, commandRemove);
menu.AddSeparator("");
menu.AddItem(commandClearAll, false, defaultContextHandler, commandClearAll);
}
}
#endregion
#region Command Handling
/// <summary>
/// Invoked to handle context command.
/// </summary>
/// <remarks>
/// <para>It is important to set the value of <c>GUI.changed</c> to <c>true</c> if any
/// changes are made by command handler.</para>
/// <para>Default command handling functionality can be inherited:</para>
/// <code language="csharp"><![CDATA[
/// protected override bool HandleCommand(string commandName, int itemIndex, IReorderableListAdaptor adaptor) {
/// if (base.HandleCommand(itemIndex, adaptor))
/// return true;
///
/// // Place custom command handling code here...
/// switch (commandName) {
/// case "Your Command":
/// return true;
/// }
///
/// return false;
/// }
/// ]]></code>
/// <code language="unityscript"><![CDATA[
/// function HandleCommand(commandName:String, itemIndex:int, adaptor:IReorderableListAdaptor):boolean {
/// if (base.HandleCommand(itemIndex, adaptor))
/// return true;
///
/// // Place custom command handling code here...
/// switch (commandName) {
/// case 'Your Command':
/// return true;
/// }
///
/// return false;
/// }
/// ]]></code>
/// </remarks>
/// <param name="commandName">Name of command. This is the text shown in the context menu.</param>
/// <param name="itemIndex">Zero-based index of item which was right-clicked.</param>
/// <param name="adaptor">Reorderable list adaptor.</param>
/// <returns>
/// A value of <c>true</c> if command was known; otherwise <c>false</c>.
/// </returns>
protected virtual bool HandleCommand(string commandName, int itemIndex, IReorderableListAdaptor adaptor) {
switch (commandName) {
case "Move to Top":
MoveItem(adaptor, itemIndex, 0);
return true;
case "Move to Bottom":
MoveItem(adaptor, itemIndex, adaptor.Count);
return true;
case "Insert Above":
InsertItem(adaptor, itemIndex);
return true;
case "Insert Below":
InsertItem(adaptor, itemIndex + 1);
return true;
case "Duplicate":
DuplicateItem(adaptor, itemIndex);
return true;
case "Remove":
RemoveItem(adaptor, itemIndex);
return true;
case "Clear All":
ClearAll(adaptor);
return true;
default:
return false;
}
}
/// <summary>
/// Call to manually perform command.
/// </summary>
/// <remarks>
/// <para>Warning message is logged to console if attempted to execute unknown command.</para>
/// </remarks>
/// <param name="commandName">Name of command. This is the text shown in the context menu.</param>
/// <param name="itemIndex">Zero-based index of item which was right-clicked.</param>
/// <param name="adaptor">Reorderable list adaptor.</param>
/// <returns>
/// A value of <c>true</c> if command was known; otherwise <c>false</c>.
/// </returns>
public bool DoCommand(string commandName, int itemIndex, IReorderableListAdaptor adaptor) {
if (!HandleCommand(s_ContextCommandName, itemIndex, adaptor)) {
Debug.LogWarning("Unknown context command.");
return false;
}
return true;
}
/// <summary>
/// Call to manually perform command.
/// </summary>
/// <remarks>
/// <para>Warning message is logged to console if attempted to execute unknown command.</para>
/// </remarks>
/// <param name="command">Content representing command.</param>
/// <param name="itemIndex">Zero-based index of item which was right-clicked.</param>
/// <param name="adaptor">Reorderable list adaptor.</param>
/// <returns>
/// A value of <c>true</c> if command was known; otherwise <c>false</c>.
/// </returns>
public bool DoCommand(GUIContent command, int itemIndex, IReorderableListAdaptor adaptor) {
return DoCommand(command.text, itemIndex, adaptor);
}
#endregion
#region Methods
/// <summary>
/// Calculate height of list control in pixels.
/// </summary>
/// <param name="adaptor">Reorderable list adaptor.</param>
/// <returns>
/// Required list height in pixels.
/// </returns>
public float CalculateListHeight(IReorderableListAdaptor adaptor) {
FixStyles();
float totalHeight = containerStyle.padding.vertical - 1;
// Take list items into consideration.
int count = adaptor.Count;
for (int i = 0; i < count; ++i)
totalHeight += adaptor.GetItemHeight(i);
// Add spacing between list items.
totalHeight += 4 * count;
// Add height of add button.
if (hasAddButton)
totalHeight += addButtonStyle.fixedHeight;
return totalHeight;
}
/// <summary>
/// Calculate height of list control in pixels.
/// </summary>
/// <param name="itemCount">Count of items in list.</param>
/// <param name="itemHeight">Fixed height of list item.</param>
/// <returns>
/// Required list height in pixels.
/// </returns>
public float CalculateListHeight(int itemCount, float itemHeight) {
FixStyles();
float totalHeight = containerStyle.padding.vertical - 1;
// Take list items into consideration.
totalHeight += (itemHeight + 4) * itemCount;
// Add height of add button.
if (hasAddButton)
totalHeight += addButtonStyle.fixedHeight;
return totalHeight;
}
/// <summary>
/// Move item from source index to destination index.
/// </summary>
/// <param name="adaptor">Reorderable list adaptor.</param>
/// <param name="sourceIndex">Zero-based index of source item.</param>
/// <param name="destIndex">Zero-based index of destination index.</param>
protected void MoveItem(IReorderableListAdaptor adaptor, int sourceIndex, int destIndex) {
adaptor.Move(sourceIndex, destIndex);
GUI.changed = true;
ReorderableListGUI.indexOfChangedItem = -1;
}
/// <summary>
/// Add item at end of list and raises the event <see cref="ItemInserted"/>.
/// </summary>
/// <param name="adaptor">Reorderable list adaptor.</param>
protected void AddItem(IReorderableListAdaptor adaptor) {
adaptor.Add();
AutoFocusItem(s_ContextControlID, adaptor.Count - 1);
GUI.changed = true;
ReorderableListGUI.indexOfChangedItem = -1;
var args = new ItemInsertedEventArgs(adaptor, adaptor.Count - 1, false);
OnItemInserted(args);
}
/// <summary>
/// Insert item at specified index and raises the event <see cref="ItemInserted"/>.
/// </summary>
/// <param name="adaptor">Reorderable list adaptor.</param>
/// <param name="itemIndex">Zero-based index of item.</param>
protected void InsertItem(IReorderableListAdaptor adaptor, int itemIndex) {
adaptor.Insert(itemIndex);
AutoFocusItem(s_ContextControlID, itemIndex);
GUI.changed = true;
ReorderableListGUI.indexOfChangedItem = -1;
var args = new ItemInsertedEventArgs(adaptor, itemIndex, false);
OnItemInserted(args);
}
/// <summary>
/// Duplicate specified item and raises the event <see cref="ItemInserted"/>.
/// </summary>
/// <param name="adaptor">Reorderable list adaptor.</param>
/// <param name="itemIndex">Zero-based index of item.</param>
protected void DuplicateItem(IReorderableListAdaptor adaptor, int itemIndex) {
adaptor.Duplicate(itemIndex);
AutoFocusItem(s_ContextControlID, itemIndex + 1);
GUI.changed = true;
ReorderableListGUI.indexOfChangedItem = -1;
var args = new ItemInsertedEventArgs(adaptor, itemIndex + 1, true);
OnItemInserted(args);
}
/// <summary>
/// Remove specified item.
/// </summary>
/// <remarks>
/// <para>The event <see cref="ItemRemoving"/> is raised prior to removing item
/// and allows removal to be cancelled.</para>
/// </remarks>
/// <param name="adaptor">Reorderable list adaptor.</param>
/// <param name="itemIndex">Zero-based index of item.</param>
/// <returns>
/// Returns a value of <c>false</c> if operation was cancelled.
/// </returns>
protected bool RemoveItem(IReorderableListAdaptor adaptor, int itemIndex) {
var args = new ItemRemovingEventArgs(adaptor, itemIndex);
OnItemRemoving(args);
if (args.Cancel)
return false;
adaptor.Remove(itemIndex);
GUI.changed = true;
ReorderableListGUI.indexOfChangedItem = -1;
return true;
}
/// <summary>
/// Remove all items from list.
/// </summary>
/// <remarks>
/// <para>The event <see cref="ItemRemoving"/> is raised for each item prior to
/// clearing array and allows entire operation to be cancelled.</para>
/// </remarks>
/// <param name="adaptor">Reorderable list adaptor.</param>
/// <returns>
/// Returns a value of <c>false</c> if operation was cancelled.
/// </returns>
protected bool ClearAll(IReorderableListAdaptor adaptor) {
if (adaptor.Count == 0)
return true;
var args = new ItemRemovingEventArgs(adaptor, 0);
int count = adaptor.Count;
for (int i = 0; i < count; ++i) {
args.itemIndex = i;
OnItemRemoving(args);
if (args.Cancel)
return false;
}
adaptor.Clear();
GUI.changed = true;
ReorderableListGUI.indexOfChangedItem = -1;
return true;
}
#endregion
}
}
This is the GUIHelper.cs file in which it is referring to:
// Copyright (c) 2012-2013 Rotorz Limited. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
using UnityEngine;
using UnityEditor;
using System;
using System.Reflection;
namespace DCM.ReorderableList.Internal {
/// <summary>
/// Utility functions to assist with GUIs.
/// </summary>
internal static class GUIHelper {
static GUIHelper() {
var tyGUIClip = typeof(GUI).Assembly.GetType("UnityEngine.GUIClip");
if (tyGUIClip != null) {
var piVisibleRect = tyGUIClip.GetProperty("visibleRect", BindingFlags.Static | BindingFlags.Public);
if (piVisibleRect != null)
VisibleRect = (Func<Rect>)Delegate.CreateDelegate(typeof(Func<Rect>), piVisibleRect.GetGetMethod());
}
var miFocusTextInControl = typeof(EditorGUI).GetMethod("FocusTextInControl", BindingFlags.Static | BindingFlags.Public);
if (miFocusTextInControl == null)
miFocusTextInControl = typeof(GUI).GetMethod("FocusControl", BindingFlags.Static | BindingFlags.Public);
FocusTextInControl = (Action<string>)Delegate.CreateDelegate(typeof(Action<string>), miFocusTextInControl);
}
/// <summary>
/// Gets visible rectangle within GUI.
/// </summary>
/// <remarks>
/// <para>VisibleRect = TopmostRect + scrollViewOffsets</para>
/// </remarks>
public static Func<Rect> VisibleRect;
/// <summary>
/// Focus control and text editor where applicable.
/// </summary>
public static Action<string> FocusTextInControl;
}
}
I dont really want it just done for me but rather explain where the error occurs and why....So i can learn from it.
Thanks in advance.
Answer by pako · Mar 22, 2015 at 10:43 AM
This is a lot of code to go through, so I just skimmed it. My impression for the error "GUIHelper' does not contain a definition for VisibleRect'" is the following:
VisbleRect is a delegate that is assign to at runtime, so apparently it doesn't get assigned anything, and hence the error.
VisibleRect gets assigned inside the initialization code of GUIHelper, i.e. inside the static GUIHelper() method. It's likely that this part of the code doesn't get to run, probably because one or both the conditions inside the "if" statements are false.
It seems that this version of the plugin is not compatible with the version of Unity you are using. Maybe it's not compatible with the new Unity GUI (Unity v.4.6+).
However, the developer has a support e-mail, and maybe you should contact him with the issue.
I found it! :D Love you ha so quick with response its greatly appreciated as time is of the essence with this project. It was due to me having a package called 5 $$anonymous$$ute GUI also within my project that contained another guihelper file which caused the conflict. Thanks pako. I owe you :)