mirror of
https://github.com/GrahamKracker/UnityExplorer.git
synced 2025-07-16 00:07:52 +08:00
Revert "some early steps remaking the GUI with UnityEngine.UI, working in all tested game so far"
This reverts commit 4280a071f6
.
This commit is contained in:
183
src/Unstrip/IMGUI/GUIHelper.cs
Normal file
183
src/Unstrip/IMGUI/GUIHelper.cs
Normal file
@ -0,0 +1,183 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
#if CPP
|
||||
using Explorer.Unstrip.IMGUI;
|
||||
#endif
|
||||
|
||||
namespace Explorer
|
||||
{
|
||||
// All the pre-processor directive stuff is in this class to keep it separate.
|
||||
// This is so Mono build can use this class and not have to worry.
|
||||
|
||||
public class GUIHelper
|
||||
{
|
||||
internal static GUILayoutOption ExpandWidth(bool expand)
|
||||
{
|
||||
#if CPP
|
||||
return GUIUnstrip.ExpandWidth(expand);
|
||||
#else
|
||||
return GUIHelper.ExpandWidth(expand);
|
||||
#endif
|
||||
}
|
||||
|
||||
internal static GUILayoutOption ExpandHeight(bool expand)
|
||||
{
|
||||
#if CPP
|
||||
return GUIUnstrip.ExpandHeight(expand);
|
||||
#else
|
||||
return GUILayout.ExpandHeight(expand);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void BeginHorizontal(params GUILayoutOption[] options)
|
||||
=> BeginHorizontal(GUIContent.none, GUIStyle.none, options);
|
||||
|
||||
public static void BeginHorizontal(GUIStyle style, params GUILayoutOption[] options)
|
||||
=> BeginHorizontal(GUIContent.none, style, options);
|
||||
|
||||
public static void BeginHorizontal(GUIContent content, GUIStyle style, params GUILayoutOption[] options)
|
||||
{
|
||||
#if CPP
|
||||
GUIUnstrip.BeginLayoutDirection(false, content, style, options);
|
||||
#else
|
||||
GUILayout.BeginHorizontal(content, style, options);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void BeginVertical(params GUILayoutOption[] options)
|
||||
=> BeginVertical(GUIContent.none, GUIStyle.none, options);
|
||||
|
||||
public static void BeginVertical(GUIStyle style, params GUILayoutOption[] options)
|
||||
=> BeginVertical(GUIContent.none, style, options);
|
||||
|
||||
public static void BeginVertical(GUIContent content, GUIStyle style, params GUILayoutOption[] options)
|
||||
{
|
||||
#if CPP
|
||||
GUIUnstrip.BeginLayoutDirection(true, content, style, options);
|
||||
#else
|
||||
GUILayout.BeginVertical(content, style, options);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
public static Rect GetLastRect()
|
||||
{
|
||||
#if CPP
|
||||
return LayoutUtilityUnstrip.GetLastRect();
|
||||
#else
|
||||
return GUILayoutUtility.GetLastRect();
|
||||
#endif
|
||||
}
|
||||
|
||||
public static string TextField(string text, GUILayoutOption[] options)
|
||||
{
|
||||
#if CPP
|
||||
return GUIUnstrip.TextField(text, options, false);
|
||||
#else
|
||||
return GUILayout.TextField(text, options);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static string TextArea(string text, params GUILayoutOption[] options)
|
||||
{
|
||||
#if CPP
|
||||
return GUIUnstrip.TextField(text, options, true);
|
||||
#else
|
||||
return GUILayout.TextArea(text, options);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static Rect Window(int id, Rect rect, GUI.WindowFunction windowFunc, string title)
|
||||
{
|
||||
#if CPP
|
||||
return GUI.Window(id, rect, windowFunc, GUIContent.Temp(title), GUI.skin.window);
|
||||
#else
|
||||
return GUI.Window(id, rect, windowFunc, title);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool Button(Rect rect, string title)
|
||||
{
|
||||
#if CPP
|
||||
return GUI.Button(rect, GUIContent.Temp(title), GUI.skin.button);
|
||||
#else
|
||||
return GUI.Button(rect, title);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void BringWindowToFront(int id)
|
||||
{
|
||||
#if CPP
|
||||
GUIUnstrip.BringWindowToFront(id);
|
||||
#else
|
||||
GUI.BringWindowToFront(id);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static Vector2 ScreenToGUIPoint(Vector2 screenPoint)
|
||||
{
|
||||
#if CPP
|
||||
return GUIUnstrip.ScreenToGUIPoint(screenPoint);
|
||||
#else
|
||||
return GUIUtility.ScreenToGUIPoint(screenPoint);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void Space(float pixels)
|
||||
{
|
||||
#if CPP
|
||||
GUIUnstrip.Space(pixels);
|
||||
#else
|
||||
GUILayout.Space(pixels);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool RepeatButton(string text, params GUILayoutOption[] options)
|
||||
{
|
||||
#if CPP
|
||||
return GUIUnstrip.DoRepeatButton(GUIContent.Temp(text), GUI.skin.button, options);
|
||||
#else
|
||||
return GUILayout.RepeatButton(text, options);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void BeginArea(Rect screenRect, GUIStyle style)
|
||||
{
|
||||
#if CPP
|
||||
GUIUnstrip.BeginArea(screenRect, GUIContent.none, style);
|
||||
#else
|
||||
GUILayout.BeginArea(screenRect, style);
|
||||
#endif
|
||||
}
|
||||
|
||||
static public void EndArea()
|
||||
{
|
||||
#if CPP
|
||||
GUIUnstrip.EndArea();
|
||||
#else
|
||||
GUILayout.EndArea();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
public static Vector2 BeginScrollView(Vector2 scroll, params GUILayoutOption[] options)
|
||||
{
|
||||
#if CPP
|
||||
return GUIUnstrip.BeginScrollView(scroll, options);
|
||||
#else
|
||||
return GUILayout.BeginScrollView(scroll, options);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void EndScrollView(bool handleScrollWheel = true)
|
||||
{
|
||||
#if CPP
|
||||
GUIUnstrip.EndScrollView(handleScrollWheel);
|
||||
#else
|
||||
GUILayout.EndScrollView();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
812
src/Unstrip/IMGUI/GUIUnstrip.cs
Normal file
812
src/Unstrip/IMGUI/GUIUnstrip.cs
Normal file
@ -0,0 +1,812 @@
|
||||
#if CPP
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEngineInternal;
|
||||
using UnhollowerRuntimeLib;
|
||||
|
||||
namespace Explorer.Unstrip.IMGUI
|
||||
{
|
||||
public class GUIUnstrip
|
||||
{
|
||||
#region Properties
|
||||
public static int s_ScrollControlId;
|
||||
|
||||
public static bool ScrollFailed = false;
|
||||
public static bool ManualUnstripFailed = false;
|
||||
|
||||
public static Stack<object> ScrollStack => m_scrollStack ?? GetScrollStack();
|
||||
public static Stack<object> m_scrollStack;
|
||||
//public static PropertyInfo m_scrollViewStatesInfo;
|
||||
|
||||
public static GUIStyle SpaceStyle => m_spaceStyle ?? GetSpaceStyle();
|
||||
public static GUIStyle m_spaceStyle;
|
||||
|
||||
public static DateTime nextScrollStepTime;
|
||||
|
||||
public static MethodInfo ScreenToGuiPointMethod;
|
||||
public static bool m_screenToGuiAttemped;
|
||||
|
||||
public static MethodInfo m_bringWindowToFrontMethod;
|
||||
public static bool m_bringWindowFrontAttempted;
|
||||
|
||||
private static Stack<object> GetScrollStack()
|
||||
{
|
||||
m_scrollStack = new Stack<object>();
|
||||
|
||||
return m_scrollStack;
|
||||
}
|
||||
|
||||
private static GUIStyle GetSpaceStyle()
|
||||
{
|
||||
try
|
||||
{
|
||||
m_spaceStyle = typeof(GUILayoutUtility)
|
||||
.GetProperty("s_SpaceStyle")
|
||||
.GetValue(null, null)
|
||||
.Il2CppCast(typeof(GUIStyle))
|
||||
as GUIStyle;
|
||||
|
||||
if (m_spaceStyle == null) throw new Exception();
|
||||
}
|
||||
catch { }
|
||||
|
||||
if (m_spaceStyle == null)
|
||||
{
|
||||
m_spaceStyle = new GUIStyle();
|
||||
}
|
||||
m_spaceStyle.stretchWidth = false;
|
||||
return m_spaceStyle;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GUILayout Methods
|
||||
|
||||
public static GUILayoutOption ExpandWidth(bool expand)
|
||||
{
|
||||
var ilValue = new Il2CppSystem.Int32
|
||||
{
|
||||
m_value = (!expand) ? 0 : 1
|
||||
};
|
||||
|
||||
var option = new GUILayoutOption(GUILayoutOption.Type.stretchWidth, ilValue.BoxIl2CppObject());
|
||||
|
||||
return option;
|
||||
}
|
||||
|
||||
public static GUILayoutOption ExpandHeight(bool expand)
|
||||
{
|
||||
var ilValue = new Il2CppSystem.Int32
|
||||
{
|
||||
m_value = (!expand) ? 0 : 1
|
||||
};
|
||||
|
||||
var option = new GUILayoutOption(GUILayoutOption.Type.stretchHeight, ilValue.BoxIl2CppObject());
|
||||
|
||||
return option;
|
||||
}
|
||||
|
||||
public static void BeginLayoutDirection(bool vertical, GUIContent content, GUIStyle style, GUILayoutOption[] options)
|
||||
{
|
||||
var g = BeginLayoutGroup(style, options, Il2CppType.Of<GUILayoutGroup>());
|
||||
g.isVertical = vertical;
|
||||
if (style != GUIStyle.none || content != GUIContent.none)
|
||||
GUI.Box(g.rect, content, style);
|
||||
}
|
||||
|
||||
public static GUILayoutGroup BeginLayoutGroup(GUIStyle style, GUILayoutOption[] options, Il2CppSystem.Type layoutType)
|
||||
{
|
||||
EventType type = Event.current.type;
|
||||
GUILayoutGroup guilayoutGroup;
|
||||
if (type != EventType.Used && type != EventType.Layout)
|
||||
{
|
||||
guilayoutGroup = GUILayoutUtility.current.topLevel.GetNext().TryCast<GUILayoutGroup>();
|
||||
|
||||
if (guilayoutGroup == null)
|
||||
{
|
||||
throw new ArgumentException("GUILayout: Mismatched LayoutGroup." + Event.current.type);
|
||||
}
|
||||
guilayoutGroup.ResetCursor();
|
||||
}
|
||||
else
|
||||
{
|
||||
guilayoutGroup = GUILayoutUtility.CreateGUILayoutGroupInstanceOfType(layoutType);
|
||||
guilayoutGroup.style = style;
|
||||
if (options != null)
|
||||
{
|
||||
guilayoutGroup.ApplyOptions(options);
|
||||
}
|
||||
GUILayoutUtility.current.topLevel.entries.Add(guilayoutGroup);
|
||||
}
|
||||
GUILayoutUtility.current.layoutGroups.Push(guilayoutGroup);
|
||||
GUILayoutUtility.current.topLevel = guilayoutGroup;
|
||||
return guilayoutGroup;
|
||||
}
|
||||
|
||||
public static string TextField(string text, GUILayoutOption[] options, bool multiLine)
|
||||
{
|
||||
text = text ?? string.Empty;
|
||||
|
||||
var skin = multiLine ? GUI.skin.textArea : GUI.skin.textField;
|
||||
|
||||
int controlID = GUIUtility.GetControlID(FocusType.Keyboard);
|
||||
GUIContent guicontent = GUIContent.Temp(text);
|
||||
bool flag = GUIUtility.keyboardControl != controlID;
|
||||
if (flag)
|
||||
{
|
||||
guicontent = GUIContent.Temp(text);
|
||||
}
|
||||
else
|
||||
{
|
||||
guicontent = GUIContent.Temp(text);
|
||||
// guicontent = GUIContent.Temp(text + GUIUtility.compositionString);
|
||||
}
|
||||
Rect rect = LayoutUtilityUnstrip.GetRect(guicontent, skin, options);
|
||||
bool flag2 = GUIUtility.keyboardControl == controlID;
|
||||
if (flag2)
|
||||
{
|
||||
guicontent = GUIContent.Temp(text);
|
||||
}
|
||||
DoTextField(rect, controlID, guicontent, multiLine, -1, skin);
|
||||
return guicontent.text;
|
||||
}
|
||||
|
||||
internal static void DoTextField(Rect position, int id, GUIContent content, bool multiline, int maxLength, GUIStyle style)
|
||||
{
|
||||
if (GUIUtilityUnstrip.GetMonoStateObject(typeof(TextEditorUnstrip), id) is TextEditorUnstrip textEditor)
|
||||
{
|
||||
if (maxLength >= 0 && content.text.Length > maxLength)
|
||||
{
|
||||
content.text = content.text.Substring(0, maxLength);
|
||||
}
|
||||
textEditor.m_Content.text = content.text;
|
||||
textEditor.SaveBackup();
|
||||
textEditor.position = position;
|
||||
textEditor.style = style;
|
||||
textEditor.multiline = multiline;
|
||||
textEditor.controlID = id;
|
||||
textEditor.DetectFocusChange();
|
||||
HandleTextFieldEventForDesktop(position, id, content, multiline, maxLength, style, textEditor);
|
||||
textEditor.UpdateScrollOffsetIfNeeded(Event.current);
|
||||
}
|
||||
}
|
||||
|
||||
private static void HandleTextFieldEventForDesktop(Rect position, int id, GUIContent content, bool multiline, int maxLength,
|
||||
GUIStyle style, TextEditorUnstrip editor)
|
||||
{
|
||||
var evt = Event.current;
|
||||
|
||||
bool change = false;
|
||||
switch (evt.type)
|
||||
{
|
||||
case EventType.MouseDown:
|
||||
if (position.Contains(evt.mousePosition))
|
||||
{
|
||||
GUIUtility.hotControl = id;
|
||||
GUIUtility.keyboardControl = id;
|
||||
editor.m_HasFocus = true;
|
||||
editor.MoveCursorToPosition(Event.current.mousePosition);
|
||||
if (Event.current.clickCount == 2 && GUI.skin.settings.doubleClickSelectsWord)
|
||||
{
|
||||
editor.SelectCurrentWord();
|
||||
editor.DblClickSnap(TextEditorUnstrip.DblClickSnapping.WORDS);
|
||||
editor.MouseDragSelectsWholeWords(true);
|
||||
}
|
||||
if (Event.current.clickCount == 3 && GUI.skin.settings.tripleClickSelectsLine)
|
||||
{
|
||||
editor.SelectCurrentParagraph();
|
||||
editor.MouseDragSelectsWholeWords(true);
|
||||
editor.DblClickSnap(TextEditorUnstrip.DblClickSnapping.PARAGRAPHS);
|
||||
}
|
||||
evt.Use();
|
||||
}
|
||||
break;
|
||||
case EventType.MouseDrag:
|
||||
if (GUIUtility.hotControl == id)
|
||||
{
|
||||
if (evt.shift)
|
||||
editor.MoveCursorToPosition(Event.current.mousePosition);
|
||||
else
|
||||
editor.SelectToPosition(Event.current.mousePosition);
|
||||
evt.Use();
|
||||
}
|
||||
break;
|
||||
case EventType.MouseUp:
|
||||
if (GUIUtility.hotControl == id)
|
||||
{
|
||||
editor.MouseDragSelectsWholeWords(false);
|
||||
GUIUtility.hotControl = 0;
|
||||
evt.Use();
|
||||
}
|
||||
break;
|
||||
case EventType.KeyDown:
|
||||
if (GUIUtility.keyboardControl != id)
|
||||
return;
|
||||
|
||||
if (editor.HandleKeyEvent(evt))
|
||||
{
|
||||
evt.Use();
|
||||
change = true;
|
||||
content.text = editor.text;
|
||||
break;
|
||||
}
|
||||
|
||||
// Ignore tab & shift-tab in textfields
|
||||
if (evt.keyCode == KeyCode.Tab || evt.character == '\t')
|
||||
return;
|
||||
|
||||
char c = evt.character;
|
||||
|
||||
if (c == '\n' && !multiline && !evt.alt)
|
||||
return;
|
||||
|
||||
|
||||
// Simplest test: only allow the character if the display font supports it.
|
||||
Font font = style.font;
|
||||
if (!font)
|
||||
font = GUI.skin.font;
|
||||
|
||||
if (font.HasCharacter(c) || c == '\n')
|
||||
{
|
||||
editor.Insert(c);
|
||||
change = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// On windows, keypresses also send events with keycode but no character. Eat them up here.
|
||||
if (c == 0)
|
||||
{
|
||||
// if we have a composition string, make sure we clear the previous selection.
|
||||
if (InputManager.compositionString.Length > 0)
|
||||
{
|
||||
editor.ReplaceSelection("");
|
||||
change = true;
|
||||
}
|
||||
|
||||
evt.Use();
|
||||
}
|
||||
// else {
|
||||
// REALLY USEFUL:
|
||||
// Debug.Log ("unhandled " +evt);
|
||||
// evt.Use ();
|
||||
// }
|
||||
break;
|
||||
case EventType.Repaint:
|
||||
// If we have keyboard focus, draw the cursor
|
||||
// TODO: check if this OpenGL view has keyboard focus
|
||||
if (GUIUtility.keyboardControl != id)
|
||||
{
|
||||
style.Draw(position, content, id, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
editor.DrawCursor(content.text);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (GUIUtility.keyboardControl == id)
|
||||
GUIUtility.textFieldInput = true;
|
||||
|
||||
if (change)
|
||||
{
|
||||
GUI.changed = true;
|
||||
content.text = editor.text;
|
||||
if (maxLength >= 0 && content.text.Length > maxLength)
|
||||
content.text = content.text.Substring(0, maxLength);
|
||||
evt.Use();
|
||||
}
|
||||
}
|
||||
|
||||
public static bool DoRepeatButton(GUIContent content, GUIStyle style, GUILayoutOption[] options)
|
||||
{
|
||||
return GUI.DoRepeatButton(LayoutUtilityUnstrip.GetRect(content, style, options), content, style, FocusType.Passive);
|
||||
}
|
||||
|
||||
public static void Space(float pixels)
|
||||
{
|
||||
if (GUILayoutUtility.current.topLevel.isVertical)
|
||||
LayoutUtilityUnstrip.GetRect(0, pixels, SpaceStyle, new GUILayoutOption[] { GUILayout.Height(pixels) });
|
||||
else
|
||||
LayoutUtilityUnstrip.GetRect(pixels, 0, SpaceStyle, new GUILayoutOption[] { GUILayout.Width(pixels) });
|
||||
|
||||
if (Event.current.type == EventType.Layout)
|
||||
{
|
||||
GUILayoutUtility.current.topLevel.entries[GUILayoutUtility.current.topLevel.entries.Count - 1].consideredForMargin = false;
|
||||
}
|
||||
}
|
||||
|
||||
public static Vector2 ScreenToGUIPoint(Vector2 screenPoint)
|
||||
{
|
||||
if (!m_screenToGuiAttemped)
|
||||
{
|
||||
m_screenToGuiAttemped = true;
|
||||
ScreenToGuiPointMethod = typeof(GUIUtility).GetMethod("ScreenToGUIPoint");
|
||||
}
|
||||
if (ScreenToGuiPointMethod == null)
|
||||
{
|
||||
throw new Exception("Couldn't get method 'GUIUtility.ScreenToGUIPoint'!");
|
||||
}
|
||||
return (Vector2)ScreenToGuiPointMethod.Invoke(null, new object[] { screenPoint });
|
||||
}
|
||||
|
||||
public static void BringWindowToFront(int id)
|
||||
{
|
||||
if (!m_bringWindowFrontAttempted)
|
||||
{
|
||||
m_bringWindowFrontAttempted = true;
|
||||
m_bringWindowToFrontMethod = typeof(GUI).GetMethod("BringWindowToFront");
|
||||
}
|
||||
if (m_bringWindowToFrontMethod == null)
|
||||
{
|
||||
throw new Exception("Couldn't get method 'GUIUtility.BringWindowToFront'!");
|
||||
}
|
||||
m_bringWindowToFrontMethod.Invoke(null, new object[] { id });
|
||||
}
|
||||
|
||||
public static void BeginArea(Rect screenRect, GUIContent content, GUIStyle style)
|
||||
{
|
||||
var g = BeginLayoutArea(style, typeof(GUILayoutGroup));
|
||||
if (Event.current.type == EventType.Layout)
|
||||
{
|
||||
g.resetCoords = true;
|
||||
g.minWidth = g.maxWidth = screenRect.width;
|
||||
g.minHeight = g.maxHeight = screenRect.height;
|
||||
g.rect = Rect.MinMaxRect(screenRect.xMin, screenRect.yMin, g.rect.xMax, g.rect.yMax);
|
||||
}
|
||||
|
||||
BeginGroup(g.rect, content, style);
|
||||
}
|
||||
|
||||
internal static GUILayoutGroup BeginLayoutArea(GUIStyle style, Type layoutType)
|
||||
{
|
||||
EventType type = Event.current.type;
|
||||
GUILayoutGroup guilayoutGroup;
|
||||
if (type != EventType.Used && type != EventType.Layout)
|
||||
{
|
||||
guilayoutGroup = GUILayoutUtility.current.windows.GetNext().TryCast<GUILayoutGroup>();
|
||||
guilayoutGroup.ResetCursor();
|
||||
}
|
||||
else
|
||||
{
|
||||
guilayoutGroup = (GUILayoutGroup)Activator.CreateInstance(layoutType);
|
||||
guilayoutGroup.style = style;
|
||||
GUILayoutUtility.current.windows.entries.Add(guilayoutGroup);
|
||||
}
|
||||
GUILayoutUtility.current.layoutGroups.Push(guilayoutGroup);
|
||||
GUILayoutUtility.current.topLevel = guilayoutGroup;
|
||||
return guilayoutGroup;
|
||||
}
|
||||
|
||||
public static void BeginGroup(Rect position, GUIContent content, GUIStyle style)
|
||||
{
|
||||
BeginGroup(position, content, style, Vector2.zero);
|
||||
}
|
||||
|
||||
internal static void BeginGroup(Rect position, GUIContent content, GUIStyle style, Vector2 scrollOffset)
|
||||
{
|
||||
int id = GUIUtility.GetControlID(GUI.s_BeginGroupHash, FocusType.Passive);
|
||||
|
||||
if (content != GUIContent.none || style != GUIStyle.none)
|
||||
{
|
||||
switch (Event.current.type)
|
||||
{
|
||||
case EventType.Repaint:
|
||||
style.Draw(position, content, id);
|
||||
break;
|
||||
default:
|
||||
if (position.Contains(Event.current.mousePosition))
|
||||
GUIUtility.mouseUsed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
GUIClip.Push(position, scrollOffset, Vector2.zero, false);
|
||||
}
|
||||
|
||||
public static void EndArea()
|
||||
{
|
||||
if (Event.current.type == EventType.Used)
|
||||
return;
|
||||
GUILayoutUtility.current.layoutGroups.Pop();
|
||||
GUILayoutUtility.current.topLevel = GUILayoutUtility.current.layoutGroups.Peek().TryCast<GUILayoutGroup>();
|
||||
GUI.EndGroup();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Scrolling
|
||||
|
||||
public static Vector2 BeginScrollView(Vector2 scroll, params GUILayoutOption[] options)
|
||||
{
|
||||
// First, just try normal way, may not have been stripped or was unstripped successfully.
|
||||
if (!ScrollFailed)
|
||||
{
|
||||
try
|
||||
{
|
||||
return GUILayout.BeginScrollView(scroll, options);
|
||||
}
|
||||
catch
|
||||
{
|
||||
ScrollFailed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Try manual implementation.
|
||||
if (!ManualUnstripFailed)
|
||||
{
|
||||
try
|
||||
{
|
||||
return BeginScrollView_ImplLayout(scroll,
|
||||
false,
|
||||
false,
|
||||
GUI.skin.horizontalScrollbar,
|
||||
GUI.skin.verticalScrollbar,
|
||||
GUI.skin.scrollView,
|
||||
options);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExplorerCore.Log("Exception on manual BeginScrollView: " + e.GetType() + ", " + e.Message + "\r\n" + e.StackTrace);
|
||||
ManualUnstripFailed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Sorry! No scrolling for you.
|
||||
return scroll;
|
||||
}
|
||||
|
||||
internal static void EndScrollView(bool handleScrollWheel)
|
||||
{
|
||||
// Only end the scroll view for the relevant BeginScrollView option, if any.
|
||||
|
||||
if (!ScrollFailed)
|
||||
{
|
||||
GUILayout.EndScrollView();
|
||||
}
|
||||
else if (!ManualUnstripFailed)
|
||||
{
|
||||
GUILayoutUtility.EndLayoutGroup();
|
||||
|
||||
if (ScrollStack.Count <= 0) return;
|
||||
|
||||
var scrollExt = ScrollStack.Peek() as ScrollViewStateUnstrip;
|
||||
|
||||
//var state = ScrollStack.Peek().TryCast<ScrollViewState>();
|
||||
//var scrollExt = Internal_ScrollViewState.FromPointer(state.Pointer);
|
||||
|
||||
//if (scrollExt == null) throw new Exception("Could not get scrollExt!");
|
||||
|
||||
GUIClip.Pop();
|
||||
|
||||
ScrollStack.Pop();
|
||||
|
||||
var position = scrollExt.position;
|
||||
|
||||
if (handleScrollWheel && Event.current.type == EventType.ScrollWheel && position.Contains(Event.current.mousePosition))
|
||||
{
|
||||
var pos = scrollExt.scrollPosition;
|
||||
pos.x = Mathf.Clamp(scrollExt.scrollPosition.x + Event.current.delta.x * 20f, 0f, scrollExt.viewRect.width - scrollExt.visibleRect.width);
|
||||
pos.y = Mathf.Clamp(scrollExt.scrollPosition.y + Event.current.delta.y * 20f, 0f, scrollExt.viewRect.height - scrollExt.visibleRect.height);
|
||||
|
||||
if (scrollExt.scrollPosition.x < 0f)
|
||||
{
|
||||
pos.x = 0f;
|
||||
}
|
||||
if (pos.y < 0f)
|
||||
{
|
||||
pos.y = 0f;
|
||||
}
|
||||
|
||||
scrollExt.apply = true;
|
||||
|
||||
Event.current.Use();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Vector2 BeginScrollView_ImplLayout(Vector2 scrollPosition, bool alwaysShowHorizontal, bool alwaysShowVertical,
|
||||
GUIStyle horizontalScrollbar, GUIStyle verticalScrollbar, GUIStyle background, params GUILayoutOption[] options)
|
||||
{
|
||||
var guiscrollGroup = GUILayoutUtility.BeginLayoutGroup(background, null, Il2CppType.Of<GUIScrollGroup>())
|
||||
.TryCast<GUIScrollGroup>();
|
||||
|
||||
EventType type = Event.current.type;
|
||||
if (type == EventType.Layout)
|
||||
{
|
||||
guiscrollGroup.resetCoords = true;
|
||||
guiscrollGroup.isVertical = true;
|
||||
guiscrollGroup.stretchWidth = 1;
|
||||
guiscrollGroup.stretchHeight = 1;
|
||||
guiscrollGroup.verticalScrollbar = verticalScrollbar;
|
||||
guiscrollGroup.horizontalScrollbar = horizontalScrollbar;
|
||||
guiscrollGroup.needsVerticalScrollbar = alwaysShowVertical;
|
||||
guiscrollGroup.needsHorizontalScrollbar = alwaysShowHorizontal;
|
||||
guiscrollGroup.ApplyOptions(options);
|
||||
}
|
||||
|
||||
return BeginScrollView_Impl(guiscrollGroup.rect,
|
||||
scrollPosition,
|
||||
new Rect(0f, 0f, guiscrollGroup.clientWidth, guiscrollGroup.clientHeight),
|
||||
alwaysShowHorizontal,
|
||||
alwaysShowVertical,
|
||||
horizontalScrollbar,
|
||||
verticalScrollbar,
|
||||
background
|
||||
);
|
||||
}
|
||||
|
||||
private static Vector2 BeginScrollView_Impl(Rect position, Vector2 scrollPosition, Rect viewRect, bool alwaysShowHorizontal,
|
||||
bool alwaysShowVertical, GUIStyle horizontalScrollbar, GUIStyle verticalScrollbar, GUIStyle background)
|
||||
{
|
||||
// GUIUtility.CheckOnGUI();
|
||||
|
||||
int controlID = GUIUtility.GetControlID(GUI.s_ScrollviewHash, FocusType.Passive);
|
||||
|
||||
ScrollViewStateUnstrip scrollExt;
|
||||
try
|
||||
{
|
||||
scrollExt = (ScrollViewStateUnstrip)GUIUtilityUnstrip.GetMonoStateObject(typeof(ScrollViewStateUnstrip), controlID);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return Vector2.zero;
|
||||
}
|
||||
|
||||
bool apply = scrollExt.apply;
|
||||
if (apply)
|
||||
{
|
||||
scrollPosition = scrollExt.scrollPosition;
|
||||
scrollExt.apply = false;
|
||||
}
|
||||
|
||||
scrollExt.position = position;
|
||||
|
||||
scrollExt.scrollPosition = scrollPosition;
|
||||
scrollExt.visibleRect = scrollExt.viewRect = viewRect;
|
||||
|
||||
var rect = scrollExt.visibleRect;
|
||||
rect.width = position.width;
|
||||
rect.height = position.height;
|
||||
|
||||
ScrollStack.Push(scrollExt);
|
||||
|
||||
Rect screenRect = new Rect(position.x, position.y, position.width, position.height);
|
||||
EventType type = Event.current.type;
|
||||
if (type != EventType.Layout)
|
||||
{
|
||||
if (type != EventType.Used)
|
||||
{
|
||||
bool flag = alwaysShowVertical;
|
||||
bool flag2 = alwaysShowHorizontal;
|
||||
if (flag2 || viewRect.width > screenRect.width)
|
||||
{
|
||||
rect.height = position.height - horizontalScrollbar.fixedHeight + (float)horizontalScrollbar.margin.top;
|
||||
|
||||
screenRect.height -= horizontalScrollbar.fixedHeight + (float)horizontalScrollbar.margin.top;
|
||||
flag2 = true;
|
||||
}
|
||||
if (flag || viewRect.height > screenRect.height)
|
||||
{
|
||||
rect.width = position.width - verticalScrollbar.fixedWidth + (float)verticalScrollbar.margin.left;
|
||||
|
||||
screenRect.width -= verticalScrollbar.fixedWidth + (float)verticalScrollbar.margin.left;
|
||||
flag = true;
|
||||
if (!flag2 && viewRect.width > screenRect.width)
|
||||
{
|
||||
rect.height = position.height - horizontalScrollbar.fixedHeight + (float)horizontalScrollbar.margin.top;
|
||||
screenRect.height -= horizontalScrollbar.fixedHeight + (float)horizontalScrollbar.margin.top;
|
||||
flag2 = true;
|
||||
}
|
||||
}
|
||||
if (Event.current.type == EventType.Repaint && background != GUIStyle.none)
|
||||
{
|
||||
background.Draw(position, position.Contains(Event.current.mousePosition), false, flag2 && flag, false);
|
||||
}
|
||||
if (flag2 && horizontalScrollbar != GUIStyle.none)
|
||||
{
|
||||
scrollPosition.x = HorizontalScroll(
|
||||
new Rect(
|
||||
position.x,
|
||||
position.yMax - horizontalScrollbar.fixedHeight,
|
||||
screenRect.width,
|
||||
horizontalScrollbar.fixedHeight),
|
||||
scrollPosition.x,
|
||||
Mathf.Min(screenRect.width, viewRect.width),
|
||||
0f,
|
||||
viewRect.width,
|
||||
horizontalScrollbar
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
GUIUtility.GetControlID(GUI.s_SliderHash, FocusType.Passive);
|
||||
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
|
||||
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
|
||||
scrollPosition.x = ((horizontalScrollbar == GUIStyle.none)
|
||||
? Mathf.Clamp(scrollPosition.x, 0f, Mathf.Max(viewRect.width - position.width, 0f))
|
||||
: 0f);
|
||||
}
|
||||
if (flag && verticalScrollbar != GUIStyle.none)
|
||||
{
|
||||
scrollPosition.y = VerticalScroll(
|
||||
new Rect(
|
||||
screenRect.xMax + (float)verticalScrollbar.margin.left,
|
||||
screenRect.y,
|
||||
verticalScrollbar.fixedWidth,
|
||||
screenRect.height),
|
||||
scrollPosition.y,
|
||||
Mathf.Min(screenRect.height, viewRect.height),
|
||||
0f,
|
||||
viewRect.height,
|
||||
verticalScrollbar
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
GUIUtility.GetControlID(GUI.s_SliderHash, FocusType.Passive);
|
||||
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
|
||||
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
|
||||
scrollPosition.y = ((verticalScrollbar == GUIStyle.none)
|
||||
? Mathf.Clamp(scrollPosition.y, 0f, Mathf.Max(viewRect.height - position.height, 0f))
|
||||
: 0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GUIUtility.GetControlID(GUI.s_SliderHash, FocusType.Passive);
|
||||
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
|
||||
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
|
||||
GUIUtility.GetControlID(GUI.s_SliderHash, FocusType.Passive);
|
||||
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
|
||||
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
|
||||
}
|
||||
GUIClip.Push(screenRect,
|
||||
new Vector2(
|
||||
Mathf.Round(-scrollPosition.x - viewRect.x),
|
||||
Mathf.Round(-scrollPosition.y - viewRect.y)),
|
||||
Vector2.zero,
|
||||
false
|
||||
);
|
||||
|
||||
return scrollPosition;
|
||||
}
|
||||
|
||||
public static float HorizontalScroll(Rect position, float value, float size, float leftValue, float rightValue, GUIStyle style)
|
||||
{
|
||||
return Scroller(position, value, size, leftValue, rightValue, style,
|
||||
GUI.skin.GetStyle(style.name + "thumb"),
|
||||
GUI.skin.GetStyle(style.name + "leftbutton"),
|
||||
GUI.skin.GetStyle(style.name + "rightbutton"),
|
||||
true);
|
||||
}
|
||||
|
||||
public static float VerticalScroll(Rect position, float value, float size, float topValue, float bottomValue, GUIStyle style)
|
||||
{
|
||||
return Scroller(position, value, size, topValue, bottomValue, style,
|
||||
GUI.skin.GetStyle(style.name + "thumb"),
|
||||
GUI.skin.GetStyle(style.name + "upbutton"),
|
||||
GUI.skin.GetStyle(style.name + "downbutton"),
|
||||
false);
|
||||
}
|
||||
|
||||
private static float Scroller(Rect position, float value, float size, float leftValue, float rightValue, GUIStyle slider,
|
||||
GUIStyle thumb, GUIStyle leftButton, GUIStyle rightButton, bool horiz)
|
||||
{
|
||||
GUIUtility.CheckOnGUI();
|
||||
int controlID = GUIUtility.GetControlID(GUI.s_SliderHash, FocusType.Passive, position);
|
||||
Rect position2;
|
||||
Rect rect;
|
||||
Rect rect2;
|
||||
if (horiz)
|
||||
{
|
||||
position2 = new Rect(position.x + leftButton.fixedWidth,
|
||||
position.y,
|
||||
position.width - leftButton.fixedWidth - rightButton.fixedWidth,
|
||||
position.height);
|
||||
|
||||
rect = new Rect(position.x, position.y, leftButton.fixedWidth, position.height);
|
||||
rect2 = new Rect(position.xMax - rightButton.fixedWidth, position.y, rightButton.fixedWidth, position.height);
|
||||
}
|
||||
else
|
||||
{
|
||||
position2 = new Rect(position.x,
|
||||
position.y + leftButton.fixedHeight,
|
||||
position.width,
|
||||
position.height - leftButton.fixedHeight - rightButton.fixedHeight);
|
||||
|
||||
rect = new Rect(position.x, position.y, position.width, leftButton.fixedHeight);
|
||||
rect2 = new Rect(position.x, position.yMax - rightButton.fixedHeight, position.width, rightButton.fixedHeight);
|
||||
}
|
||||
|
||||
value = Slider(position2, value, size, leftValue, rightValue, slider, thumb, horiz, controlID);
|
||||
|
||||
bool flag = Event.current.type == EventType.MouseUp;
|
||||
if (ScrollerRepeatButton(controlID, rect, leftButton))
|
||||
{
|
||||
value -= 10f * ((leftValue >= rightValue) ? -1f : 1f);
|
||||
}
|
||||
if (ScrollerRepeatButton(controlID, rect2, rightButton))
|
||||
{
|
||||
value += 10f * ((leftValue >= rightValue) ? -1f : 1f);
|
||||
}
|
||||
if (flag && Event.current.type == EventType.Used)
|
||||
{
|
||||
s_ScrollControlId = 0;
|
||||
}
|
||||
if (leftValue < rightValue)
|
||||
{
|
||||
value = Mathf.Clamp(value, leftValue, rightValue - size);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = Mathf.Clamp(value, rightValue, leftValue - size);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public static float Slider(Rect position, float value, float size, float start, float end, GUIStyle slider,
|
||||
GUIStyle thumb, bool horiz, int id)
|
||||
{
|
||||
if (id == 0)
|
||||
{
|
||||
id = GUIUtility.GetControlID(GUI.s_SliderHash, FocusType.Passive, position);
|
||||
}
|
||||
var sliderHandler = new SliderHandlerUnstrip(position, value, size, start, end, slider, thumb, horiz, id);
|
||||
return sliderHandler.Handle();
|
||||
}
|
||||
|
||||
private static bool ScrollerRepeatButton(int scrollerID, Rect rect, GUIStyle style)
|
||||
{
|
||||
bool result = false;
|
||||
if (GUI.DoRepeatButton(rect, GUIContent.none, style, FocusType.Passive))
|
||||
{
|
||||
bool flag = s_ScrollControlId != scrollerID;
|
||||
s_ScrollControlId = scrollerID;
|
||||
|
||||
if (flag)
|
||||
{
|
||||
result = true;
|
||||
nextScrollStepTime = DateTime.Now.AddMilliseconds(250.0);
|
||||
}
|
||||
else if (DateTime.Now >= nextScrollStepTime)
|
||||
{
|
||||
result = true;
|
||||
nextScrollStepTime = DateTime.Now.AddMilliseconds(30.0);
|
||||
}
|
||||
if (Event.current.type == EventType.Repaint)
|
||||
{
|
||||
GUI.InternalRepaintEditorWindow();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region Extensions
|
||||
|
||||
public static class Extensions
|
||||
{
|
||||
public static Rect Unstripped_GetLast(this GUILayoutGroup group)
|
||||
{
|
||||
Rect result;
|
||||
if (group.m_Cursor > 0 && group.m_Cursor <= group.entries.Count)
|
||||
{
|
||||
GUILayoutEntry guilayoutEntry = group.entries[group.m_Cursor - 1];
|
||||
result = guilayoutEntry.rect;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = GUILayoutEntry.kDummyRect;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
#endif
|
67
src/Unstrip/IMGUI/GUIUtilityUnstrip.cs
Normal file
67
src/Unstrip/IMGUI/GUIUtilityUnstrip.cs
Normal file
@ -0,0 +1,67 @@
|
||||
#if CPP
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using Explorer.Helpers;
|
||||
|
||||
namespace Explorer.Unstrip.IMGUI
|
||||
{
|
||||
public class GUIUtilityUnstrip
|
||||
{
|
||||
public static Dictionary<int, object> MonoStateCache = new Dictionary<int, object>();
|
||||
|
||||
public static object GetMonoStateObject(Type type, int controlID)
|
||||
{
|
||||
if (!MonoStateCache.ContainsKey(controlID))
|
||||
{
|
||||
MonoStateCache.Add(controlID, Activator.CreateInstance(type));
|
||||
}
|
||||
|
||||
return MonoStateCache[controlID];
|
||||
}
|
||||
|
||||
public static Dictionary<int, Il2CppSystem.Object> StateCache => m_stateCacheDict ?? GetStateCacheDict();
|
||||
public static Dictionary<int, Il2CppSystem.Object> m_stateCacheDict;
|
||||
|
||||
public static Il2CppSystem.Object GetStateObject(Il2CppSystem.Type type, int controlID)
|
||||
{
|
||||
Il2CppSystem.Object obj;
|
||||
if (StateCache.ContainsKey(controlID))
|
||||
{
|
||||
obj = StateCache[controlID];
|
||||
}
|
||||
else
|
||||
{
|
||||
obj = Il2CppSystem.Activator.CreateInstance(type);
|
||||
StateCache.Add(controlID, obj);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
private static Dictionary<int, Il2CppSystem.Object> GetStateCacheDict()
|
||||
{
|
||||
if (m_stateCacheDict == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_stateCacheDict = ReflectionHelpers.GetTypeByName("UnityEngine.GUIStateObjects")
|
||||
.GetProperty("s_StateCache")
|
||||
.GetValue(null, null)
|
||||
as Dictionary<int, Il2CppSystem.Object>;
|
||||
|
||||
if (m_stateCacheDict == null) throw new Exception();
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_stateCacheDict = new Dictionary<int, Il2CppSystem.Object>();
|
||||
}
|
||||
}
|
||||
return m_stateCacheDict;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
91
src/Unstrip/IMGUI/LayoutUtilityUnstrip.cs
Normal file
91
src/Unstrip/IMGUI/LayoutUtilityUnstrip.cs
Normal file
@ -0,0 +1,91 @@
|
||||
#if CPP
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer.Unstrip.IMGUI
|
||||
{
|
||||
public class LayoutUtilityUnstrip
|
||||
{
|
||||
public static Rect GetRect(float width, float height, GUIStyle style, params GUILayoutOption[] options)
|
||||
{
|
||||
switch (Event.current.type)
|
||||
{
|
||||
case EventType.Layout:
|
||||
GUILayoutUtility.current.topLevel.Add(new GUILayoutEntry(width, width, height, height, style, options));
|
||||
return GUILayoutUtility.kDummyRect;
|
||||
case EventType.Used:
|
||||
return GUILayoutUtility.kDummyRect;
|
||||
default:
|
||||
return GUILayoutUtility.current.topLevel.GetNext().rect;
|
||||
}
|
||||
}
|
||||
|
||||
public static Rect GetRect(GUIContent content, GUIStyle style, params GUILayoutOption[] options)
|
||||
{
|
||||
return DoGetRect(content, style, options);
|
||||
}
|
||||
|
||||
static Rect DoGetRect(GUIContent content, GUIStyle style, GUILayoutOption[] options)
|
||||
{
|
||||
switch (Event.current.type)
|
||||
{
|
||||
case EventType.Layout:
|
||||
if (style.isHeightDependantOnWidth)
|
||||
{
|
||||
GUILayoutUtility.current.topLevel.Add(new GUIWordWrapSizer(style, content, options));
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector2 sizeConstraints = new Vector2(0, 0);
|
||||
if (options != null)
|
||||
{
|
||||
foreach (var option in options)
|
||||
{
|
||||
if (float.TryParse(option.value.ToString(), out float f))
|
||||
{
|
||||
switch (option.type)
|
||||
{
|
||||
case GUILayoutOption.Type.maxHeight:
|
||||
sizeConstraints.y = f;
|
||||
break;
|
||||
case GUILayoutOption.Type.maxWidth:
|
||||
sizeConstraints.x = f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vector2 size = style.CalcSizeWithConstraints(content, sizeConstraints);
|
||||
// This is needed on non-integer scale ratios to avoid errors to accumulate in further layout calculations
|
||||
size.x = Mathf.Ceil(size.x);
|
||||
size.y = Mathf.Ceil(size.y);
|
||||
GUILayoutUtility.current.topLevel.Add(new GUILayoutEntry(size.x, size.x, size.y, size.y, style, options));
|
||||
}
|
||||
return GUILayoutUtility.kDummyRect;
|
||||
|
||||
case EventType.Used:
|
||||
return GUILayoutUtility.kDummyRect;
|
||||
default:
|
||||
var entry = GUILayoutUtility.current.topLevel.GetNext();
|
||||
//GUIDebugger.LogLayoutEntry(entry.rect, entry.marginLeft, entry.marginRight, entry.marginTop, entry.marginBottom, entry.style);
|
||||
return entry.rect;
|
||||
}
|
||||
}
|
||||
|
||||
public static Rect GetLastRect()
|
||||
{
|
||||
EventType type = Event.current.type;
|
||||
Rect last;
|
||||
if (type != EventType.Layout && type != EventType.Used)
|
||||
{
|
||||
last = GUILayoutUtility.current.topLevel.Unstripped_GetLast();
|
||||
}
|
||||
else
|
||||
{
|
||||
last = GUILayoutUtility.kDummyRect;
|
||||
}
|
||||
return last;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
89
src/Unstrip/IMGUI/ScrollViewStateUnstrip.cs
Normal file
89
src/Unstrip/IMGUI/ScrollViewStateUnstrip.cs
Normal file
@ -0,0 +1,89 @@
|
||||
#if CPP
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer.Unstrip.IMGUI
|
||||
{
|
||||
public class ScrollViewStateUnstrip
|
||||
{
|
||||
public Rect position;
|
||||
public Rect visibleRect;
|
||||
public Rect viewRect;
|
||||
public Vector2 scrollPosition;
|
||||
public bool apply;
|
||||
|
||||
public void ScrollTo(Rect pos)
|
||||
{
|
||||
this.ScrollTowards(pos, float.PositiveInfinity);
|
||||
}
|
||||
|
||||
public bool ScrollTowards(Rect pos, float maxDelta)
|
||||
{
|
||||
Vector2 b = this.ScrollNeeded(pos);
|
||||
bool result;
|
||||
if (b.sqrMagnitude < 0.0001f)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
else if (maxDelta == 0f)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (b.magnitude > maxDelta)
|
||||
{
|
||||
b = b.normalized * maxDelta;
|
||||
}
|
||||
this.scrollPosition += b;
|
||||
this.apply = true;
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Vector2 ScrollNeeded(Rect pos)
|
||||
{
|
||||
Rect rect = this.visibleRect;
|
||||
rect.x += this.scrollPosition.x;
|
||||
rect.y += this.scrollPosition.y;
|
||||
float num = pos.width - this.visibleRect.width;
|
||||
if (num > 0f)
|
||||
{
|
||||
pos.width -= num;
|
||||
pos.x += num * 0.5f;
|
||||
}
|
||||
num = pos.height - this.visibleRect.height;
|
||||
if (num > 0f)
|
||||
{
|
||||
pos.height -= num;
|
||||
pos.y += num * 0.5f;
|
||||
}
|
||||
Vector2 zero = Vector2.zero;
|
||||
if (pos.xMax > rect.xMax)
|
||||
{
|
||||
zero.x += pos.xMax - rect.xMax;
|
||||
}
|
||||
else if (pos.xMin < rect.xMin)
|
||||
{
|
||||
zero.x -= rect.xMin - pos.xMin;
|
||||
}
|
||||
if (pos.yMax > rect.yMax)
|
||||
{
|
||||
zero.y += pos.yMax - rect.yMax;
|
||||
}
|
||||
else if (pos.yMin < rect.yMin)
|
||||
{
|
||||
zero.y -= rect.yMin - pos.yMin;
|
||||
}
|
||||
Rect rect2 = this.viewRect;
|
||||
rect2.width = Mathf.Max(rect2.width, this.visibleRect.width);
|
||||
rect2.height = Mathf.Max(rect2.height, this.visibleRect.height);
|
||||
zero.x = Mathf.Clamp(zero.x, rect2.xMin - this.scrollPosition.x, rect2.xMax - this.visibleRect.width - this.scrollPosition.x);
|
||||
zero.y = Mathf.Clamp(zero.y, rect2.yMin - this.scrollPosition.y, rect2.yMax - this.visibleRect.height - this.scrollPosition.y);
|
||||
return zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
411
src/Unstrip/IMGUI/SliderHandlerUnstrip.cs
Normal file
411
src/Unstrip/IMGUI/SliderHandlerUnstrip.cs
Normal file
@ -0,0 +1,411 @@
|
||||
#if CPP
|
||||
using System;
|
||||
using UnhollowerRuntimeLib;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer.Unstrip.IMGUI
|
||||
{
|
||||
public struct SliderHandlerUnstrip
|
||||
{
|
||||
public static int ScrollTroughSide
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!m_getScrollTroughSideFailed)
|
||||
{
|
||||
try
|
||||
{
|
||||
return GUI.scrollTroughSide;
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_getScrollTroughSideFailed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return m_manualScrollTrough;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (!m_setScrollTroughSideFailed)
|
||||
{
|
||||
try
|
||||
{
|
||||
GUI.scrollTroughSide = value;
|
||||
return;
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_setScrollTroughSideFailed = true;
|
||||
}
|
||||
}
|
||||
m_manualScrollTrough = value;
|
||||
}
|
||||
}
|
||||
private static bool m_getScrollTroughSideFailed;
|
||||
private static bool m_setScrollTroughSideFailed;
|
||||
private static int m_manualScrollTrough;
|
||||
|
||||
|
||||
private readonly Rect position;
|
||||
private readonly float currentValue;
|
||||
private readonly float size;
|
||||
private readonly float start;
|
||||
private readonly float end;
|
||||
private readonly GUIStyle slider;
|
||||
private readonly GUIStyle thumb;
|
||||
private readonly bool horiz;
|
||||
private readonly int id;
|
||||
|
||||
public SliderHandlerUnstrip(Rect position, float currentValue, float size, float start,
|
||||
float end, GUIStyle slider, GUIStyle thumb, bool horiz, int id)
|
||||
{
|
||||
this.position = position;
|
||||
this.currentValue = currentValue;
|
||||
this.size = size;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.slider = slider;
|
||||
this.thumb = thumb;
|
||||
this.horiz = horiz;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public float Handle()
|
||||
{
|
||||
float result;
|
||||
if (this.slider == null || this.thumb == null)
|
||||
{
|
||||
result = this.currentValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (this.CurrentEventType())
|
||||
{
|
||||
case EventType.MouseDown:
|
||||
return this.OnMouseDown();
|
||||
case EventType.MouseUp:
|
||||
return this.OnMouseUp();
|
||||
case EventType.MouseDrag:
|
||||
return this.OnMouseDrag();
|
||||
case EventType.Repaint:
|
||||
return this.OnRepaint();
|
||||
}
|
||||
result = this.currentValue;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private float OnMouseDown()
|
||||
{
|
||||
float result;
|
||||
if (!this.position.Contains(this.CurrentEvent().mousePosition) || this.IsEmptySlider())
|
||||
{
|
||||
result = this.currentValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
ScrollTroughSide = 0;
|
||||
GUIUtility.hotControl = this.id;
|
||||
this.CurrentEvent().Use();
|
||||
if (this.ThumbSelectionRect().Contains(this.CurrentEvent().mousePosition))
|
||||
{
|
||||
this.StartDraggingWithValue(this.ClampedCurrentValue());
|
||||
result = this.currentValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.changed = true;
|
||||
if (this.SupportsPageMovements())
|
||||
{
|
||||
var state = GetSliderState();
|
||||
state.isDragging = false;
|
||||
GUIUnstrip.nextScrollStepTime = DateTime.Now.AddMilliseconds(250.0);
|
||||
ScrollTroughSide = this.CurrentScrollTroughSide();
|
||||
result = this.PageMovementValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
float num = this.ValueForCurrentMousePosition();
|
||||
this.StartDraggingWithValue(num);
|
||||
result = this.Clamp(num);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private float OnMouseDrag()
|
||||
{
|
||||
float result;
|
||||
if (GUIUtility.hotControl != this.id)
|
||||
{
|
||||
result = this.currentValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
var state = GetSliderState();
|
||||
if (!state.isDragging)
|
||||
{
|
||||
result = this.currentValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.changed = true;
|
||||
this.CurrentEvent().Use();
|
||||
float num = this.MousePosition() - state.dragStartPos;
|
||||
float value = state.dragStartValue + num / this.ValuesPerPixel();
|
||||
result = this.Clamp(value);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private float OnMouseUp()
|
||||
{
|
||||
if (GUIUtility.hotControl == this.id)
|
||||
{
|
||||
this.CurrentEvent().Use();
|
||||
GUIUtility.hotControl = 0;
|
||||
}
|
||||
return this.currentValue;
|
||||
}
|
||||
|
||||
private float OnRepaint()
|
||||
{
|
||||
this.slider.Draw(this.position, GUIContent.none, this.id);
|
||||
if (!this.IsEmptySlider() && this.currentValue >= this.MinValue() && this.currentValue <= this.MaxValue())
|
||||
{
|
||||
this.thumb.Draw(this.ThumbRect(), GUIContent.none, this.id);
|
||||
}
|
||||
float result;
|
||||
if (GUIUtility.hotControl != this.id || !this.position.Contains(this.CurrentEvent().mousePosition) || this.IsEmptySlider())
|
||||
{
|
||||
result = this.currentValue;
|
||||
}
|
||||
else if (this.ThumbRect().Contains(this.CurrentEvent().mousePosition))
|
||||
{
|
||||
if (ScrollTroughSide != 0)
|
||||
{
|
||||
GUIUtility.hotControl = 0;
|
||||
}
|
||||
result = this.currentValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.InternalRepaintEditorWindow();
|
||||
if (DateTime.Now < GUIUnstrip.nextScrollStepTime)
|
||||
{
|
||||
result = this.currentValue;
|
||||
}
|
||||
else if (this.CurrentScrollTroughSide() != ScrollTroughSide)
|
||||
{
|
||||
result = this.currentValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
GUIUnstrip.nextScrollStepTime = DateTime.Now.AddMilliseconds(30.0);
|
||||
if (this.SupportsPageMovements())
|
||||
{
|
||||
GetSliderState().isDragging = false;
|
||||
GUI.changed = true;
|
||||
result = this.PageMovementValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = this.ClampedCurrentValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private EventType CurrentEventType()
|
||||
{
|
||||
return this.CurrentEvent().GetTypeForControl(this.id);
|
||||
}
|
||||
|
||||
|
||||
private int CurrentScrollTroughSide()
|
||||
{
|
||||
float num = (!this.horiz) ? this.CurrentEvent().mousePosition.y : this.CurrentEvent().mousePosition.x;
|
||||
float num2 = (!this.horiz) ? this.ThumbRect().y : this.ThumbRect().x;
|
||||
return (num <= num2) ? -1 : 1;
|
||||
}
|
||||
|
||||
private bool IsEmptySlider()
|
||||
{
|
||||
return this.start == this.end;
|
||||
}
|
||||
|
||||
private bool SupportsPageMovements()
|
||||
{
|
||||
return this.size != 0f && GUI.usePageScrollbars;
|
||||
}
|
||||
|
||||
private float PageMovementValue()
|
||||
{
|
||||
float num = this.currentValue;
|
||||
int num2 = (this.start <= this.end) ? 1 : -1;
|
||||
if (this.MousePosition() > this.PageUpMovementBound())
|
||||
{
|
||||
num += this.size * (float)num2 * 0.9f;
|
||||
}
|
||||
else
|
||||
{
|
||||
num -= this.size * (float)num2 * 0.9f;
|
||||
}
|
||||
return this.Clamp(num);
|
||||
}
|
||||
|
||||
private float PageUpMovementBound()
|
||||
{
|
||||
float result;
|
||||
if (this.horiz)
|
||||
{
|
||||
result = this.ThumbRect().xMax - this.position.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = this.ThumbRect().yMax - this.position.y;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Event CurrentEvent()
|
||||
{
|
||||
return Event.current;
|
||||
}
|
||||
|
||||
private float ValueForCurrentMousePosition()
|
||||
{
|
||||
float result;
|
||||
if (this.horiz)
|
||||
{
|
||||
result = (this.MousePosition() - this.ThumbRect().width * 0.5f) / this.ValuesPerPixel() + this.start - this.size * 0.5f;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = (this.MousePosition() - this.ThumbRect().height * 0.5f) / this.ValuesPerPixel() + this.start - this.size * 0.5f;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private float Clamp(float value)
|
||||
{
|
||||
return Mathf.Clamp(value, this.MinValue(), this.MaxValue());
|
||||
}
|
||||
|
||||
private Rect ThumbSelectionRect()
|
||||
{
|
||||
return this.ThumbRect();
|
||||
}
|
||||
|
||||
private void StartDraggingWithValue(float dragStartValue)
|
||||
{
|
||||
var state = GetSliderState();
|
||||
state.dragStartPos = this.MousePosition();
|
||||
state.dragStartValue = dragStartValue;
|
||||
state.isDragging = true;
|
||||
}
|
||||
|
||||
private SliderStateUnstrip GetSliderState()
|
||||
{
|
||||
return (SliderStateUnstrip)GUIUtilityUnstrip.GetMonoStateObject(typeof(SliderStateUnstrip), this.id);
|
||||
}
|
||||
|
||||
private Rect ThumbRect()
|
||||
{
|
||||
return (!this.horiz) ? this.VerticalThumbRect() : this.HorizontalThumbRect();
|
||||
}
|
||||
|
||||
private Rect VerticalThumbRect()
|
||||
{
|
||||
float num = this.ValuesPerPixel();
|
||||
Rect result;
|
||||
if (this.start < this.end)
|
||||
{
|
||||
result = new Rect(this.position.x + (float)this.slider.padding.left, (this.ClampedCurrentValue() - this.start) * num + this.position.y + (float)this.slider.padding.top, this.position.width - (float)this.slider.padding.horizontal, this.size * num + this.ThumbSize());
|
||||
}
|
||||
else
|
||||
{
|
||||
result = new Rect(this.position.x + (float)this.slider.padding.left, (this.ClampedCurrentValue() + this.size - this.start) * num + this.position.y + (float)this.slider.padding.top, this.position.width - (float)this.slider.padding.horizontal, this.size * -num + this.ThumbSize());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Rect HorizontalThumbRect()
|
||||
{
|
||||
float num = this.ValuesPerPixel();
|
||||
Rect result;
|
||||
if (this.start < this.end)
|
||||
{
|
||||
result = new Rect((this.ClampedCurrentValue() - this.start) * num + this.position.x + (float)this.slider.padding.left, this.position.y + (float)this.slider.padding.top, this.size * num + this.ThumbSize(), this.position.height - (float)this.slider.padding.vertical);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = new Rect((this.ClampedCurrentValue() + this.size - this.start) * num + this.position.x + (float)this.slider.padding.left, this.position.y, this.size * -num + this.ThumbSize(), this.position.height);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private float ClampedCurrentValue()
|
||||
{
|
||||
return this.Clamp(this.currentValue);
|
||||
}
|
||||
|
||||
private float MousePosition()
|
||||
{
|
||||
float result;
|
||||
if (this.horiz)
|
||||
{
|
||||
result = this.CurrentEvent().mousePosition.x - this.position.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = this.CurrentEvent().mousePosition.y - this.position.y;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private float ValuesPerPixel()
|
||||
{
|
||||
float result;
|
||||
if (this.horiz)
|
||||
{
|
||||
result = (this.position.width - (float)this.slider.padding.horizontal - this.ThumbSize()) / (this.end - this.start);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = (this.position.height - (float)this.slider.padding.vertical - this.ThumbSize()) / (this.end - this.start);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private float ThumbSize()
|
||||
{
|
||||
float result;
|
||||
if (this.horiz)
|
||||
{
|
||||
result = ((this.thumb.fixedWidth == 0f) ? ((float)this.thumb.padding.horizontal) : this.thumb.fixedWidth);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = ((this.thumb.fixedHeight == 0f) ? ((float)this.thumb.padding.vertical) : this.thumb.fixedHeight);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private float MaxValue()
|
||||
{
|
||||
return Mathf.Max(this.start, this.end) - this.size;
|
||||
}
|
||||
|
||||
private float MinValue()
|
||||
{
|
||||
return Mathf.Min(this.start, this.end);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
14
src/Unstrip/IMGUI/SliderStateUnstrip.cs
Normal file
14
src/Unstrip/IMGUI/SliderStateUnstrip.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Explorer.Unstrip.IMGUI
|
||||
{
|
||||
public class SliderStateUnstrip
|
||||
{
|
||||
public float dragStartPos;
|
||||
public float dragStartValue;
|
||||
public bool isDragging;
|
||||
}
|
||||
}
|
1557
src/Unstrip/IMGUI/TextEditorUnstrip.cs
Normal file
1557
src/Unstrip/IMGUI/TextEditorUnstrip.cs
Normal file
File diff suppressed because it is too large
Load Diff
@ -6,12 +6,12 @@ using System.Text;
|
||||
using UnhollowerBaseLib;
|
||||
using UnityEngine;
|
||||
using System.IO;
|
||||
using ExplorerBeta.Helpers;
|
||||
using Explorer.Helpers;
|
||||
using System.Runtime.InteropServices;
|
||||
using Unity.Collections;
|
||||
using Unity.Collections.LowLevel.Unsafe;
|
||||
|
||||
namespace ExplorerBeta.Unstrip.ImageConversion
|
||||
namespace Explorer.Unstrip.ImageConversion
|
||||
{
|
||||
public static class ImageConversionUnstrip
|
||||
{
|
||||
|
@ -3,12 +3,12 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using ExplorerBeta.Helpers;
|
||||
using Explorer.Helpers;
|
||||
#if CPP
|
||||
using UnhollowerBaseLib;
|
||||
#endif
|
||||
|
||||
namespace ExplorerBeta.Unstrip.LayerMasks
|
||||
namespace Explorer.Unstrip.LayerMasks
|
||||
{
|
||||
public static class LayerMaskUnstrip
|
||||
{
|
||||
|
@ -2,13 +2,13 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using ExplorerBeta.Helpers;
|
||||
using Explorer.Helpers;
|
||||
using UnityEngine;
|
||||
#if CPP
|
||||
using UnhollowerBaseLib;
|
||||
#endif
|
||||
|
||||
namespace ExplorerBeta.Unstrip.Resources
|
||||
namespace Explorer.Unstrip.Resources
|
||||
{
|
||||
public class ResourcesUnstrip
|
||||
{
|
||||
|
@ -3,12 +3,12 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using ExplorerBeta.Helpers;
|
||||
using Explorer.Helpers;
|
||||
using UnhollowerBaseLib;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace ExplorerBeta.Unstrip.Scenes
|
||||
namespace Explorer.Unstrip.Scenes
|
||||
{
|
||||
public class SceneUnstrip
|
||||
{
|
||||
|
Reference in New Issue
Block a user