first commit
This commit is contained in:
270
NitroxClient/Debuggers/BaseDebugger.cs
Normal file
270
NitroxClient/Debuggers/BaseDebugger.cs
Normal file
@@ -0,0 +1,270 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using NitroxClient.Unity.Helper;
|
||||
using NitroxModel.DataStructures.Util;
|
||||
using NitroxModel.Helper;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NitroxClient.Debuggers
|
||||
{
|
||||
[ExcludeFromCodeCoverage]
|
||||
public abstract class BaseDebugger
|
||||
{
|
||||
public readonly string DebuggerName;
|
||||
public readonly KeyCode Hotkey;
|
||||
public readonly bool HotkeyAltRequired;
|
||||
public readonly bool HotkeyControlRequired;
|
||||
public readonly bool HotkeyShiftRequired;
|
||||
public readonly string HotkeyString;
|
||||
public readonly GUISkinCreationOptions SkinCreationOptions;
|
||||
|
||||
/// <summary>
|
||||
/// Currently active tab. This is the index used with <see cref="tabs"/>.
|
||||
/// </summary>
|
||||
public DebuggerTab ActiveTab;
|
||||
|
||||
public bool CanDragWindow = true;
|
||||
|
||||
public virtual bool Enabled { get; set; }
|
||||
|
||||
public Rect WindowRect;
|
||||
|
||||
/// <summary>
|
||||
/// Optional rendered tabs of the current debugger.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="ActiveTab"/> gives the index of the currently selected tab.
|
||||
/// </remarks>
|
||||
private readonly Dictionary<string, DebuggerTab> tabs = new Dictionary<string, DebuggerTab>();
|
||||
|
||||
private float maxHeight;
|
||||
|
||||
protected BaseDebugger(float desiredWidth, string debuggerName = null, KeyCode hotkey = KeyCode.None, bool control = false, bool shift = false, bool alt = false, GUISkinCreationOptions skinOptions = GUISkinCreationOptions.DEFAULT, float maxHeight = 1000f)
|
||||
{
|
||||
this.maxHeight = maxHeight;
|
||||
|
||||
if (desiredWidth < 200)
|
||||
{
|
||||
desiredWidth = 200;
|
||||
}
|
||||
|
||||
WindowRect = new Rect(Screen.width / 2 - (desiredWidth / 2), Screen.height * 0.1f, desiredWidth, Math.Min(Screen.height * 0.8f, maxHeight)); // Default position in center of screen.
|
||||
|
||||
Hotkey = hotkey;
|
||||
HotkeyAltRequired = alt;
|
||||
HotkeyShiftRequired = shift;
|
||||
HotkeyControlRequired = control;
|
||||
HotkeyString = Hotkey == KeyCode.None ? "None" : $"{(HotkeyControlRequired ? "CTRL+" : "")}{(HotkeyAltRequired ? "ALT+" : "")}{(HotkeyShiftRequired ? "SHIFT+" : "")}{Hotkey}";
|
||||
SkinCreationOptions = skinOptions;
|
||||
|
||||
if (string.IsNullOrEmpty(debuggerName))
|
||||
{
|
||||
string name = GetType().Name;
|
||||
DebuggerName = name.Substring(0, name.IndexOf("Debugger", StringComparison.Ordinal));
|
||||
}
|
||||
else
|
||||
{
|
||||
DebuggerName = debuggerName;
|
||||
}
|
||||
}
|
||||
|
||||
public enum GUISkinCreationOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Uses the NitroxDebug skin.
|
||||
/// </summary>
|
||||
DEFAULT,
|
||||
|
||||
/// <summary>
|
||||
/// Creates a copy of the default Unity IMGUI skin and sets the copied skin as render skin.
|
||||
/// </summary>
|
||||
UNITYCOPY,
|
||||
|
||||
/// <summary>
|
||||
/// Creates a copy based on the NitroxDebug skin and sets the copied skin as render skin.
|
||||
/// </summary>
|
||||
DERIVEDCOPY
|
||||
}
|
||||
|
||||
protected DebuggerTab AddTab(string name, Action render)
|
||||
{
|
||||
DebuggerTab tab = new(name, render);
|
||||
tabs.Add(tab.Name, tab);
|
||||
return tab;
|
||||
}
|
||||
|
||||
protected Optional<DebuggerTab> GetTab(string name)
|
||||
{
|
||||
Validate.NotNull(name);
|
||||
|
||||
tabs.TryGetValue(name, out DebuggerTab tab);
|
||||
return Optional.OfNullable(tab);
|
||||
}
|
||||
|
||||
public virtual void Update()
|
||||
{
|
||||
// Defaults to a no-op but can be overriden
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call this inside a <see cref="MonoBehaviour.OnGUI"/> method.
|
||||
/// </summary>
|
||||
public virtual void OnGUI()
|
||||
{
|
||||
if (!Enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GUISkin skin = GetSkin();
|
||||
GUISkinUtils.RenderWithSkin(skin, () =>
|
||||
{
|
||||
WindowRect = GUILayout.Window(GUIUtility.GetControlID(FocusType.Keyboard), WindowRect, RenderInternal, $"[DEBUGGER] {DebuggerName}", GUILayout.ExpandHeight(true), GUILayout.ExpandWidth(true));
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Optionally adjust the skin that is used during render.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Set <see cref="SkinCreationOptions"/> on <see cref="GUISkinCreationOptions.UNITYCOPY"/> or <see cref="GUISkinCreationOptions.DERIVEDCOPY"/> in constructor before using this method.
|
||||
/// </remarks>
|
||||
/// <param name="skin">Skin that is being used during <see cref="Render(int)"/>.</param>
|
||||
protected virtual void OnSetSkin(GUISkin skin)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Optionally use a custom render solution for the debugger by overriding this method.
|
||||
/// </summary>
|
||||
protected virtual void Render()
|
||||
{
|
||||
ActiveTab?.Render();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets (a copy of) a skin specified by <see cref="GUISkinCreationOptions"/>.
|
||||
/// </summary>
|
||||
/// <returns>A reference to an existing or copied skin.</returns>
|
||||
private GUISkin GetSkin()
|
||||
{
|
||||
GUISkin skin = GUI.skin;
|
||||
string skinName = GetSkinName();
|
||||
switch (SkinCreationOptions)
|
||||
{
|
||||
case GUISkinCreationOptions.DEFAULT:
|
||||
skin = GUISkinUtils.RegisterDerivedOnce("debuggers.default", s =>
|
||||
{
|
||||
SetBaseStyle(s);
|
||||
OnSetSkinImpl(s);
|
||||
});
|
||||
break;
|
||||
|
||||
case GUISkinCreationOptions.UNITYCOPY:
|
||||
skin = GUISkinUtils.RegisterDerivedOnce(skinName, OnSetSkinImpl);
|
||||
break;
|
||||
|
||||
case GUISkinCreationOptions.DERIVEDCOPY:
|
||||
GUISkin baseSkin = GUISkinUtils.RegisterDerivedOnce("debuggers.default", SetBaseStyle);
|
||||
skin = GUISkinUtils.RegisterDerivedOnce(skinName, OnSetSkinImpl, baseSkin);
|
||||
break;
|
||||
}
|
||||
|
||||
return skin;
|
||||
}
|
||||
|
||||
private string GetSkinName()
|
||||
{
|
||||
string name = GetType().Name;
|
||||
return $"debuggers.{name.Substring(0, name.IndexOf("Debugger")).ToLowerInvariant()}";
|
||||
}
|
||||
|
||||
private void OnSetSkinImpl(GUISkin skin)
|
||||
{
|
||||
if (SkinCreationOptions == GUISkinCreationOptions.DEFAULT)
|
||||
{
|
||||
Enabled = false;
|
||||
throw new NotSupportedException($"Cannot change {nameof(GUISkin)} for {GetType().FullName} when accessing the default skin. Change {nameof(SkinCreationOptions)} to something else than {nameof(GUISkinCreationOptions.DEFAULT)}.");
|
||||
}
|
||||
|
||||
OnSetSkin(skin);
|
||||
}
|
||||
|
||||
private void RenderInternal(int windowId)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope("Box"))
|
||||
{
|
||||
if (tabs.Count == 1)
|
||||
{
|
||||
GUILayout.Label(tabs.First().Key, "tabActive");
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (DebuggerTab tab in tabs.Values)
|
||||
{
|
||||
if (GUILayout.Button(tab.Name, ActiveTab == tab ? "tabActive" : "tab"))
|
||||
{
|
||||
ActiveTab = tab;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Render();
|
||||
if (CanDragWindow)
|
||||
{
|
||||
GUI.DragWindow();
|
||||
}
|
||||
}
|
||||
|
||||
private void SetBaseStyle(GUISkin skin)
|
||||
{
|
||||
skin.label.alignment = TextAnchor.MiddleLeft;
|
||||
skin.label.margin = new RectOffset();
|
||||
skin.label.padding = new RectOffset();
|
||||
|
||||
skin.SetCustomStyle("header", skin.label, s =>
|
||||
{
|
||||
s.margin.top = 10;
|
||||
s.margin.bottom = 10;
|
||||
s.alignment = TextAnchor.MiddleCenter;
|
||||
s.fontSize = 16;
|
||||
s.fontStyle = FontStyle.Bold;
|
||||
});
|
||||
|
||||
skin.SetCustomStyle("tab", skin.button, s =>
|
||||
{
|
||||
s.fontSize = 16;
|
||||
s.margin = new RectOffset(5, 5, 5, 5);
|
||||
});
|
||||
|
||||
skin.SetCustomStyle("tabActive", skin.button, s =>
|
||||
{
|
||||
s.fontStyle = FontStyle.Bold;
|
||||
s.fontSize = 16;
|
||||
});
|
||||
}
|
||||
|
||||
public virtual void ResetWindowPosition()
|
||||
{
|
||||
WindowRect = new Rect(Screen.width / 2f - (WindowRect.width / 2), Screen.height / 2f - (WindowRect.height / 2), WindowRect.width, Math.Min(Screen.height * 0.8f, maxHeight)); //Reset position of debuggers because SN sometimes throws the windows from planet 4546B
|
||||
}
|
||||
|
||||
public class DebuggerTab
|
||||
{
|
||||
public DebuggerTab(string name, Action render)
|
||||
{
|
||||
Validate.NotNull(name, $"Expected a name for the {nameof(DebuggerTab)}");
|
||||
Validate.NotNull(render, $"Expected an action for the {nameof(DebuggerTab)}");
|
||||
|
||||
Name = name;
|
||||
Render = render;
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
public Action Render { get; }
|
||||
}
|
||||
}
|
||||
}
|
155
NitroxClient/Debuggers/Drawer/DrawerManager.cs
Normal file
155
NitroxClient/Debuggers/Drawer/DrawerManager.cs
Normal file
@@ -0,0 +1,155 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NitroxClient.Debuggers.Drawer.Nitrox;
|
||||
using NitroxClient.Debuggers.Drawer.Subnautica;
|
||||
using NitroxClient.Debuggers.Drawer.Unity;
|
||||
using NitroxClient.Debuggers.Drawer.UnityUI;
|
||||
using NitroxClient.MonoBehaviours;
|
||||
using NitroxModel.DataStructures;
|
||||
using NitroxModel.DataStructures.Unity;
|
||||
using NitroxModel.Helper;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer;
|
||||
|
||||
/// <summary>
|
||||
/// Registers known drawers into lookup dictionaries that are searched when <see cref="TryDraw{T}" /> and
|
||||
/// <see cref="TryDrawEditor{T}" /> are called.
|
||||
/// </summary>
|
||||
public class DrawerManager
|
||||
{
|
||||
private readonly Dictionary<Type, IDrawer<object>> drawers = new();
|
||||
private readonly Dictionary<Type, IEditorDrawer<object>> editorDrawers = new();
|
||||
|
||||
public DrawerManager(SceneDebugger sceneDebugger)
|
||||
{
|
||||
Validate.NotNull(sceneDebugger);
|
||||
|
||||
ColorDrawer colorDrawer = new();
|
||||
UnityEventDrawer unityEventDrawer = new();
|
||||
SelectableDrawer selectableDrawer = new(sceneDebugger, colorDrawer);
|
||||
VectorDrawer vectorDrawer = new();
|
||||
RectDrawer rectDrawer = new();
|
||||
LayoutGroupDrawer layoutGroupDrawer = new(rectDrawer);
|
||||
MaterialDrawer materialDrawer = new();
|
||||
ImageDrawer imageDrawer = new(colorDrawer, materialDrawer, rectDrawer);
|
||||
NitroxEntityDrawer nitroxEntityDrawer = new();
|
||||
|
||||
AddDrawer<NitroxEntityDrawer, NitroxEntity>(nitroxEntityDrawer);
|
||||
AddDrawer<NitroxEntityDrawer, NitroxId>(nitroxEntityDrawer);
|
||||
AddDrawer<FMODAssetDrawer, FMODAsset>();
|
||||
AddDrawer<UWEEventDrawer, UWE.Event<float>>();
|
||||
AddDrawer<UWEEventDrawer, UWE.Event<PowerRelay>>();
|
||||
AddDrawer<AspectRatioFitterDrawer, AspectRatioFitter>();
|
||||
AddDrawer<ButtonDrawer, Button>(new(selectableDrawer, unityEventDrawer));
|
||||
AddDrawer<CanvasDrawer, Canvas>(new(sceneDebugger));
|
||||
AddDrawer<CanvasGroupDrawer, CanvasGroup>();
|
||||
AddDrawer<CanvasRendererDrawer, CanvasRenderer>();
|
||||
AddDrawer<CanvasScalerDrawer, CanvasScaler>(new(vectorDrawer));
|
||||
AddDrawer<ContentSizeFitterDrawer, ContentSizeFitter>();
|
||||
AddDrawer<DropdownDrawer, Dropdown>(new(sceneDebugger, selectableDrawer));
|
||||
AddDrawer<EventTriggerDrawer, EventTrigger>(new(sceneDebugger));
|
||||
AddDrawer<GraphicRaycasterDrawer, GraphicRaycaster>();
|
||||
AddDrawer<GridLayoutGroupDrawer, GridLayoutGroup>(new(vectorDrawer, rectDrawer));
|
||||
AddDrawer<LayoutGroupDrawer, HorizontalLayoutGroup>(layoutGroupDrawer);
|
||||
AddDrawer<ImageDrawer, Image>(imageDrawer);
|
||||
AddDrawer<ImageDrawer, RawImage>(imageDrawer);
|
||||
AddDrawer<LayoutGroupDrawer, VerticalLayoutGroup>(layoutGroupDrawer);
|
||||
AddDrawer<MaskDrawer, Mask>();
|
||||
AddDrawer<RectTransformDrawer, RectTransform>(new(vectorDrawer));
|
||||
AddDrawer<ScrollbarDrawer, Scrollbar>(new(sceneDebugger, selectableDrawer));
|
||||
AddDrawer<ScrollRectDrawer, ScrollRect>(new(sceneDebugger));
|
||||
AddDrawer<SelectableDrawer, Selectable>(selectableDrawer);
|
||||
AddDrawer<SliderDrawer, Slider>(new(sceneDebugger, selectableDrawer));
|
||||
AddDrawer<TextDrawer, Text>(new(colorDrawer, materialDrawer));
|
||||
AddDrawer<ToggleDrawer, Toggle>(new(sceneDebugger, selectableDrawer, unityEventDrawer));
|
||||
AddDrawer<ToggleGroupDrawer, ToggleGroup>();
|
||||
AddDrawer<RigidbodyDrawer, Rigidbody>(new(vectorDrawer));
|
||||
AddDrawer<TransformDrawer, Transform>(new(sceneDebugger, vectorDrawer));
|
||||
AddDrawer<UnityEventDrawer, UnityEvent>(unityEventDrawer);
|
||||
AddDrawer<UnityEventDrawer, UnityEvent<bool>>(unityEventDrawer);
|
||||
AddDrawer<AnimatorDrawer, Animator>();
|
||||
AddDrawer<CharacterControllerDrawer, CharacterController>(new(vectorDrawer));
|
||||
|
||||
AddEditor<VectorDrawer, Vector2>(vectorDrawer);
|
||||
AddEditor<VectorDrawer, Vector3>(vectorDrawer);
|
||||
AddEditor<VectorDrawer, Vector4>(vectorDrawer);
|
||||
AddEditor<VectorDrawer, Quaternion>(vectorDrawer);
|
||||
AddEditor<VectorDrawer, Int3>(vectorDrawer);
|
||||
AddEditor<VectorDrawer, NitroxVector3>(vectorDrawer);
|
||||
AddEditor<VectorDrawer, NitroxVector4>(vectorDrawer);
|
||||
AddEditor<ColorDrawer, Color>(colorDrawer);
|
||||
AddEditor<ColorDrawer, Color32>(colorDrawer);
|
||||
AddEditor<MaterialDrawer, Material>(materialDrawer);
|
||||
AddEditor<RectDrawer, Rect>(rectDrawer);
|
||||
AddEditor<RectDrawer, RectOffset>(rectDrawer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to draw the item given its type. If item is null, returns false and does nothing.
|
||||
/// </summary>
|
||||
/// <returns>True if a drawer is known for the given item type.</returns>
|
||||
public bool TryDraw<T>(T item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!drawers.TryGetValue(item.GetType(), out IDrawer<object> drawer))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
drawer.Draw(item);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to draw the editor given the type of item. If item is null, returns false and does nothing.
|
||||
/// </summary>
|
||||
/// <param name="item">Item to draw the editor for.</param>
|
||||
/// <param name="result">Changed result from the editor.</param>
|
||||
/// <returns>True if an editor is known for the given item type.</returns>
|
||||
public bool TryDrawEditor<T>(T item, out T result)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
result = default;
|
||||
return false;
|
||||
}
|
||||
if (!editorDrawers.TryGetValue(item.GetType(), out IEditorDrawer<object> drawer))
|
||||
{
|
||||
result = default;
|
||||
return false;
|
||||
}
|
||||
result = (T)drawer.Draw(item);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void AddDrawer<TDrawer, TDrawable>(TDrawer drawer) where TDrawer : IDrawer<TDrawable>
|
||||
{
|
||||
drawers.Add(typeof(TDrawable), new DrawerWrapper<TDrawable>(drawer));
|
||||
}
|
||||
|
||||
private void AddDrawer<TDrawer, TDrawable>() where TDrawer : IDrawer<TDrawable>, new()
|
||||
{
|
||||
drawers.Add(typeof(TDrawable), new DrawerWrapper<TDrawable>(new TDrawer()));
|
||||
}
|
||||
|
||||
private void AddEditor<TDrawer, TDrawable>(TDrawer drawer) where TDrawer : IEditorDrawer<TDrawable>
|
||||
{
|
||||
editorDrawers.Add(typeof(TDrawable), new EditorDrawerWrapper<TDrawable>(drawer));
|
||||
}
|
||||
|
||||
private class DrawerWrapper<T>(IDrawer<T> inner) : IDrawer<object>
|
||||
{
|
||||
public void Draw(object target) => inner.Draw((T)target);
|
||||
}
|
||||
|
||||
private class EditorDrawerWrapper<T>(IEditorDrawer<T> inner) : IEditorDrawer<object>
|
||||
{
|
||||
public object Draw(object target) => inner.Draw((T)target);
|
||||
}
|
||||
}
|
11
NitroxClient/Debuggers/Drawer/IDrawer.cs
Normal file
11
NitroxClient/Debuggers/Drawer/IDrawer.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace NitroxClient.Debuggers.Drawer;
|
||||
|
||||
public interface IDrawer<in T>
|
||||
{
|
||||
void Draw(T target);
|
||||
}
|
||||
|
||||
public interface IDrawer<in T, in TDrawOptions> : IDrawer<T> where TDrawOptions : class
|
||||
{
|
||||
void Draw(T target, TDrawOptions options);
|
||||
}
|
11
NitroxClient/Debuggers/Drawer/IEditorDrawer.cs
Normal file
11
NitroxClient/Debuggers/Drawer/IEditorDrawer.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace NitroxClient.Debuggers.Drawer;
|
||||
|
||||
public interface IEditorDrawer<T>
|
||||
{
|
||||
T Draw(T target);
|
||||
}
|
||||
|
||||
public interface IEditorDrawer<T, in TDrawOptions> : IEditorDrawer<T> where TDrawOptions : class
|
||||
{
|
||||
T Draw(T target, TDrawOptions options);
|
||||
}
|
69
NitroxClient/Debuggers/Drawer/Nitrox/NitroxEntityDrawer.cs
Normal file
69
NitroxClient/Debuggers/Drawer/Nitrox/NitroxEntityDrawer.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using System.Linq;
|
||||
using NitroxClient.GameLogic;
|
||||
using NitroxClient.MonoBehaviours;
|
||||
using NitroxModel.Core;
|
||||
using NitroxModel.DataStructures;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.Nitrox;
|
||||
|
||||
public class NitroxEntityDrawer : IDrawer<NitroxEntity>, IDrawer<NitroxId>
|
||||
{
|
||||
private const float LABEL_WIDTH = 250;
|
||||
|
||||
public void Draw(NitroxEntity nitroxEntity)
|
||||
{
|
||||
Draw(nitroxEntity.Id);
|
||||
|
||||
GUILayout.Space(8);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("GameObject with IDs", GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
GUILayout.TextField(NitroxEntity.GetGameObjects().Count().ToString());
|
||||
}
|
||||
|
||||
GUILayout.Space(8);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Simulating state", GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
if (NitroxServiceLocator.Cache<SimulationOwnership>.Value.TryGetLockType(nitroxEntity.Id, out SimulationLockType simulationLockType))
|
||||
{
|
||||
GUILayout.TextField(simulationLockType.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
GUILayout.TextField("NONE");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(NitroxId nitroxId)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("NitroxId", GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
GUILayout.TextField(nitroxId == null ? "ID IS NULL!!!" : nitroxId.ToString());
|
||||
}
|
||||
|
||||
GUILayout.Space(8);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Simulating state", GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
if (NitroxServiceLocator.Cache<SimulationOwnership>.Value.TryGetLockType(nitroxId, out SimulationLockType simulationLockType))
|
||||
{
|
||||
GUILayout.TextField(simulationLockType.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
GUILayout.TextField("NONE");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
269
NitroxClient/Debuggers/Drawer/NitroxGUILayout.cs
Normal file
269
NitroxClient/Debuggers/Drawer/NitroxGUILayout.cs
Normal file
@@ -0,0 +1,269 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer;
|
||||
|
||||
// Reference https://gist.github.com/Seneral/31161381f993a4a06c59bf12576cabd8#file-rteditorgui-cs
|
||||
public static class NitroxGUILayout
|
||||
{
|
||||
private static int activeConvertibleField = -1;
|
||||
private static IConvertible activeConvertibleFieldLastValue = 0;
|
||||
private static string activeConvertibleFieldString = "";
|
||||
|
||||
private static readonly GUIStyle separatorStyle = new() { stretchWidth = true };
|
||||
public static readonly GUIStyle DrawerLabel = new("options_label") { fixedHeight = 22, alignment = TextAnchor.LowerLeft };
|
||||
|
||||
public const float VALUE_WIDTH = 175;
|
||||
public const float DEFAULT_LABEL_WIDTH = 200;
|
||||
public const float DEFAULT_SPACE = 10;
|
||||
|
||||
public static void Separator()
|
||||
{
|
||||
GUILayout.Box(GUIContent.none, separatorStyle, GUILayout.Height(5));
|
||||
}
|
||||
|
||||
public static int IntField(int value, float valueWidth = VALUE_WIDTH) => ConvertibleField(value, valueWidth).ToInt32(CultureInfo.CurrentCulture);
|
||||
public static float FloatField(float value, float valueWidth = VALUE_WIDTH) => ConvertibleField(value, valueWidth).ToSingle(CultureInfo.CurrentCulture);
|
||||
|
||||
public static IConvertible ConvertibleField(IConvertible value, float valueWidth = VALUE_WIDTH)
|
||||
{
|
||||
int floatFieldID = GUIUtility.GetControlID("ConvertibleField".GetHashCode(), FocusType.Keyboard) + 1;
|
||||
if (floatFieldID == 0)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
bool recorded = activeConvertibleField == floatFieldID;
|
||||
bool active = floatFieldID == GUIUtility.keyboardControl;
|
||||
|
||||
if (active && recorded && !Equals(activeConvertibleFieldLastValue, value))
|
||||
{
|
||||
// Value has been modified externally
|
||||
activeConvertibleFieldLastValue = value;
|
||||
activeConvertibleFieldString = value.ToString(CultureInfo.CurrentCulture);
|
||||
}
|
||||
|
||||
// Get stored string for the text field if this one is recorded
|
||||
string str = recorded ? activeConvertibleFieldString : value.ToString(CultureInfo.CurrentCulture);
|
||||
|
||||
string strValue = GUILayout.TextField(str, GUILayout.Width(valueWidth));
|
||||
if (recorded)
|
||||
{
|
||||
activeConvertibleFieldString = strValue;
|
||||
}
|
||||
|
||||
// Try Parse if value got changed. If the string could not be parsed, ignore it and keep last value
|
||||
bool parsed = true;
|
||||
if (string.IsNullOrEmpty(strValue))
|
||||
{
|
||||
value = activeConvertibleFieldLastValue = 0;
|
||||
}
|
||||
else if (strValue != value.ToString(CultureInfo.CurrentCulture))
|
||||
{
|
||||
parsed = TryParseIConvertible(value, strValue, out IConvertible newValue);
|
||||
if (parsed)
|
||||
{
|
||||
value = activeConvertibleFieldLastValue = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
switch (active)
|
||||
{
|
||||
case true when !recorded: // Gained focus this frame
|
||||
activeConvertibleField = floatFieldID;
|
||||
activeConvertibleFieldString = strValue;
|
||||
activeConvertibleFieldLastValue = value;
|
||||
break;
|
||||
case false when recorded: // Lost focus this frame
|
||||
{
|
||||
activeConvertibleField = -1;
|
||||
if (parsed)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
value = TryParseIConvertible(value, strValue, out IConvertible newValue) ? newValue : activeConvertibleFieldLastValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private static bool TryParseIConvertible(IConvertible type, string inputString, out IConvertible newValue)
|
||||
{
|
||||
bool parsed;
|
||||
switch (type)
|
||||
{
|
||||
case short:
|
||||
parsed = short.TryParse(inputString, NumberStyles.Integer, CultureInfo.CurrentCulture, out short newShort);
|
||||
newValue = newShort;
|
||||
break;
|
||||
case ushort:
|
||||
parsed = ushort.TryParse(inputString, NumberStyles.Integer, CultureInfo.CurrentCulture, out ushort newUShort);
|
||||
newValue = newUShort;
|
||||
break;
|
||||
case int:
|
||||
parsed = int.TryParse(inputString, NumberStyles.Integer, CultureInfo.CurrentCulture, out int newInt);
|
||||
newValue = newInt;
|
||||
break;
|
||||
case uint _:
|
||||
parsed = uint.TryParse(inputString, NumberStyles.Integer, CultureInfo.CurrentCulture, out uint newUInt);
|
||||
newValue = newUInt;
|
||||
break;
|
||||
case long:
|
||||
parsed = long.TryParse(inputString, NumberStyles.Integer, CultureInfo.CurrentCulture, out long newLong);
|
||||
newValue = newLong;
|
||||
break;
|
||||
case ulong:
|
||||
parsed = ulong.TryParse(inputString, NumberStyles.Integer, CultureInfo.CurrentCulture, out ulong newULong);
|
||||
newValue = newULong;
|
||||
break;
|
||||
case float:
|
||||
parsed = float.TryParse(inputString, NumberStyles.Float, CultureInfo.CurrentCulture, out float newFloat);
|
||||
newValue = newFloat;
|
||||
break;
|
||||
case double:
|
||||
parsed = double.TryParse(inputString, NumberStyles.Float, CultureInfo.CurrentCulture, out double newDouble);
|
||||
newValue = newDouble;
|
||||
break;
|
||||
default:
|
||||
parsed = false;
|
||||
newValue = null;
|
||||
break;
|
||||
}
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
public static int SliderField(int value, int minValue, int maxValue, float valueWidth = VALUE_WIDTH) => (int)SliderField((float)value, minValue, maxValue, valueWidth);
|
||||
|
||||
public static float SliderField(float value, float minValue, float maxValue, float valueWidth = VALUE_WIDTH)
|
||||
{
|
||||
//TODO: Implement slider (if possible at all)
|
||||
return Math.Max(minValue, Math.Min(maxValue, FloatField(value, valueWidth)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Displays an enum of an unknown type.
|
||||
/// </summary>
|
||||
/// <param name="selected">The selected enum value.</param>
|
||||
/// <param name="buttonWidth">The button width</param>
|
||||
/// <returns>The newly selected enum value.</returns>
|
||||
public static Enum EnumPopup(Enum selected, float buttonWidth = VALUE_WIDTH)
|
||||
{
|
||||
return EnumPopupInternal(selected, buttonWidth);
|
||||
}
|
||||
|
||||
public static T EnumPopup<T>(T selected, float buttonWidth = VALUE_WIDTH) where T : Enum
|
||||
{
|
||||
return (T)EnumPopupInternal(selected, buttonWidth);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Displays an enum of a known type.
|
||||
/// </summary>
|
||||
/// <param name="selected">The selected enum value.</param>
|
||||
/// <param name="buttonWidth">The button width.</param>
|
||||
/// <returns>The newly selected enum value.</returns>
|
||||
private static Enum EnumPopupInternal(Enum selected, float buttonWidth = VALUE_WIDTH)
|
||||
{
|
||||
Type enumType = selected.GetType();
|
||||
string[] enumNames = Enum.GetNames(enumType);
|
||||
|
||||
// Enums can be bit flags. If this is the case, we need to support toggling the bits
|
||||
if (enumType.CustomAttributes.Select(a => a.AttributeType).Contains(typeof(FlagsAttribute)))
|
||||
{
|
||||
bool IsFlagSet<T>(T value, T flag)
|
||||
{
|
||||
long lValue = Convert.ToInt64(value);
|
||||
long lFlag = Convert.ToInt64(flag);
|
||||
return (lValue & lFlag) != 0;
|
||||
};
|
||||
|
||||
object SetFlags(Type type, object value, object flags, bool toggle)
|
||||
{
|
||||
long lValue = Convert.ToInt64(value);
|
||||
long lFlag = Convert.ToInt64(flags);
|
||||
if (toggle)
|
||||
{
|
||||
lValue |= lFlag;
|
||||
}
|
||||
else
|
||||
{
|
||||
lValue &= (~lFlag);
|
||||
}
|
||||
|
||||
if (lFlag == 0)
|
||||
{
|
||||
lValue = 0;
|
||||
}
|
||||
|
||||
return Enum.ToObject(type, lValue);
|
||||
};
|
||||
|
||||
Enum[] enumValues = Enum.GetValues(enumType).Cast<Enum>().ToArray();
|
||||
|
||||
using (new GUILayout.VerticalScope())
|
||||
{
|
||||
for (int i = 0; i < enumValues.Length; i++)
|
||||
{
|
||||
Enum enumValue = enumValues[i];
|
||||
string enumName = enumNames[i];
|
||||
|
||||
bool isFlagSet = IsFlagSet(selected, enumValue);
|
||||
|
||||
selected = (Enum) SetFlags(enumType, selected, enumValue, GUILayout.Toggle(isFlagSet, enumName, "Button", GUILayout.Width(buttonWidth)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normal enum, only picks one value
|
||||
int selectedIndex = Array.IndexOf(enumNames, selected.ToString());
|
||||
selectedIndex = GUILayout.SelectionGrid(selectedIndex, enumNames, 1, GUILayout.Width(buttonWidth));
|
||||
return (Enum)Enum.Parse(enumType, enumNames[selectedIndex]);
|
||||
}
|
||||
return selected;
|
||||
}
|
||||
|
||||
public static bool BoolField(bool value, float valueWidth = VALUE_WIDTH) => BoolFieldInternal(value, value.ToString(), valueWidth);
|
||||
public static bool BoolField(bool value, string name, float valueWidth = VALUE_WIDTH) => BoolFieldInternal(value, $"{name}: {value}", valueWidth);
|
||||
|
||||
private static bool BoolFieldInternal(bool value, string buttonLabel, float valueWidth = VALUE_WIDTH)
|
||||
{
|
||||
if (GUILayout.Button(buttonLabel, GUILayout.Width(valueWidth)))
|
||||
{
|
||||
return !value;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public struct BackgroundColorScope : IDisposable
|
||||
{
|
||||
private bool disposed;
|
||||
private readonly Color previousColor;
|
||||
|
||||
public BackgroundColorScope(Color newColor)
|
||||
{
|
||||
disposed = false;
|
||||
previousColor = GUI.color;
|
||||
GUI.backgroundColor = newColor;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
disposed = true;
|
||||
GUI.backgroundColor = previousColor;
|
||||
}
|
||||
}
|
||||
}
|
11
NitroxClient/Debuggers/Drawer/Subnautica/FMODAssetDrawer.cs
Normal file
11
NitroxClient/Debuggers/Drawer/Subnautica/FMODAssetDrawer.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.Subnautica;
|
||||
|
||||
public class FMODAssetDrawer : IDrawer<FMODAsset>
|
||||
{
|
||||
public void Draw(FMODAsset asset)
|
||||
{
|
||||
GUILayout.TextField(asset ? asset.path : "NULL");
|
||||
}
|
||||
}
|
76
NitroxClient/Debuggers/Drawer/Subnautica/UWEEventDrawer.cs
Normal file
76
NitroxClient/Debuggers/Drawer/Subnautica/UWEEventDrawer.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UWE;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.Subnautica;
|
||||
|
||||
public class UWEEventDrawer : IDrawer<Event<float>>, IDrawer<Event<PowerRelay>>
|
||||
{
|
||||
private const float LABEL_WIDTH = 250;
|
||||
|
||||
public void Draw(Event<float> uweEvent) => UWEEventDrawer.Draw(uweEvent);
|
||||
public void Draw(Event<PowerRelay> uweEvent) => UWEEventDrawer.Draw(uweEvent);
|
||||
|
||||
private static void Draw<T>(Event<T> uweEvent)
|
||||
{
|
||||
using GUILayout.VerticalScope scope = new();
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Triggering", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
uweEvent.triggering = NitroxGUILayout.BoolField(uweEvent.triggering);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Handlers", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
DrawUweEventHandlerList(uweEvent.handlers);
|
||||
}
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("ToRemove", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
DrawUweEventHandlerList(uweEvent.toRemove);
|
||||
}
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("HandlersToTrigger", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
DrawUweEventHandlerList(uweEvent.handlersToTrigger);
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawUweEventHandlerList<T>(ICollection<Event<T>.Handler> uweEventHandlerList)
|
||||
{
|
||||
if (uweEventHandlerList == null)
|
||||
{
|
||||
GUILayout.Label("null", NitroxGUILayout.DrawerLabel);
|
||||
return;
|
||||
}
|
||||
|
||||
if (uweEventHandlerList.Count == 0)
|
||||
{
|
||||
GUILayout.Label("empty", NitroxGUILayout.DrawerLabel);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (Event<T>.Handler uweEventHandler in uweEventHandlerList)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
NitroxGUILayout.Separator();
|
||||
if (uweEventHandler == null)
|
||||
{
|
||||
GUILayout.Label("Handler was null", NitroxGUILayout.DrawerLabel);
|
||||
continue;
|
||||
}
|
||||
|
||||
string labelText = uweEventHandler.obj ? $"{uweEventHandler.obj.GetType().Name}." : string.Empty;
|
||||
labelText += uweEventHandler.function;
|
||||
GUILayout.Label(labelText, NitroxGUILayout.DrawerLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
119
NitroxClient/Debuggers/Drawer/Unity/CharacterControllerDrawer.cs
Normal file
119
NitroxClient/Debuggers/Drawer/Unity/CharacterControllerDrawer.cs
Normal file
@@ -0,0 +1,119 @@
|
||||
using NitroxModel.Helper;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.Unity;
|
||||
|
||||
/// <summary>
|
||||
/// Draws a <see cref="CharacterController"/> component on the gameobjects in the <see cref="SceneDebugger"/>
|
||||
/// </summary>
|
||||
public class CharacterControllerDrawer : IDrawer<CharacterController>
|
||||
{
|
||||
private readonly VectorDrawer vectorDrawer;
|
||||
private const float LABEL_WIDTH = 120;
|
||||
private const float VALUE_MAX_WIDTH = 405;
|
||||
|
||||
public CharacterControllerDrawer(VectorDrawer vectorDrawer)
|
||||
{
|
||||
Validate.NotNull(vectorDrawer);
|
||||
|
||||
this.vectorDrawer = vectorDrawer;
|
||||
}
|
||||
|
||||
public void Draw(CharacterController cc)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Slope Limit (°)", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
cc.slopeLimit = NitroxGUILayout.FloatField(cc.slopeLimit, VALUE_MAX_WIDTH);
|
||||
}
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Step Offset", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
cc.stepOffset = NitroxGUILayout.FloatField(cc.stepOffset, VALUE_MAX_WIDTH);
|
||||
}
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Skin Width", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
cc.skinWidth = NitroxGUILayout.FloatField(cc.skinWidth, VALUE_MAX_WIDTH);
|
||||
}
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Min Move Distance", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
cc.minMoveDistance = NitroxGUILayout.FloatField(cc.minMoveDistance, VALUE_MAX_WIDTH);
|
||||
}
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Center", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
cc.center = vectorDrawer.Draw(cc.center);
|
||||
}
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Radius", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
cc.radius = NitroxGUILayout.FloatField(cc.radius, VALUE_MAX_WIDTH);
|
||||
}
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Height", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
cc.height = NitroxGUILayout.FloatField(cc.height, VALUE_MAX_WIDTH);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Velocity", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
vectorDrawer.Draw(cc.velocity);
|
||||
}
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Is Grounded", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
NitroxGUILayout.BoolField(cc.isGrounded, VALUE_MAX_WIDTH);
|
||||
}
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Detect Collisions", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
cc.detectCollisions = NitroxGUILayout.BoolField(cc.detectCollisions, VALUE_MAX_WIDTH);
|
||||
}
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Enable Overlap Recovery", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH + 30));
|
||||
NitroxGUILayout.Separator();
|
||||
cc.enableOverlapRecovery = NitroxGUILayout.BoolField(cc.enableOverlapRecovery, VALUE_MAX_WIDTH);
|
||||
}
|
||||
}
|
||||
}
|
46
NitroxClient/Debuggers/Drawer/Unity/ColorDrawer.cs
Normal file
46
NitroxClient/Debuggers/Drawer/Unity/ColorDrawer.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.Unity;
|
||||
|
||||
public class ColorDrawer : IEditorDrawer<Color>, IEditorDrawer<Color32>
|
||||
{
|
||||
private static readonly Texture2D tex = new((int)NitroxGUILayout.VALUE_WIDTH, 25);
|
||||
private static Color lastColor;
|
||||
|
||||
public Color32 Draw(Color32 color) => Draw((Color)color);
|
||||
|
||||
public Color Draw(Color color)
|
||||
{
|
||||
if (color != lastColor)
|
||||
{
|
||||
for (int y = 0; y < 6; y++)
|
||||
{
|
||||
int separator = (int)(tex.width * color.a);
|
||||
for (int x = 0; x < separator; x++)
|
||||
{
|
||||
tex.SetPixel(x, y, Color.white);
|
||||
}
|
||||
|
||||
for (int x = separator; x < tex.width; x++)
|
||||
{
|
||||
tex.SetPixel(x, y, Color.black);
|
||||
}
|
||||
}
|
||||
|
||||
for (int y = 6; y < tex.height; y++)
|
||||
{
|
||||
for (int x = 0; x < tex.width; x++)
|
||||
{
|
||||
tex.SetPixel(x, y, color);
|
||||
}
|
||||
}
|
||||
|
||||
tex.Apply();
|
||||
lastColor = color;
|
||||
}
|
||||
|
||||
// TODO: Implement Color picker
|
||||
GUILayout.Button(tex, GUILayout.Width(tex.width));
|
||||
return color;
|
||||
}
|
||||
}
|
13
NitroxClient/Debuggers/Drawer/Unity/MaterialDrawer.cs
Normal file
13
NitroxClient/Debuggers/Drawer/Unity/MaterialDrawer.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.Unity;
|
||||
|
||||
public class MaterialDrawer : IEditorDrawer<Material>
|
||||
{
|
||||
public Material Draw(Material material)
|
||||
{
|
||||
// TODO: Implement Material picker
|
||||
GUILayout.Box(material.name, GUILayout.Width(150), GUILayout.Height(20));
|
||||
return material;
|
||||
}
|
||||
}
|
79
NitroxClient/Debuggers/Drawer/Unity/RectDrawer.cs
Normal file
79
NitroxClient/Debuggers/Drawer/Unity/RectDrawer.cs
Normal file
@@ -0,0 +1,79 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.Unity;
|
||||
|
||||
public class RectDrawer : IEditorDrawer<Rect, RectDrawer.DrawOptions>, IEditorDrawer<RectOffset>
|
||||
{
|
||||
private const float MAX_WIDTH = 400;
|
||||
|
||||
public Rect Draw(Rect rect, DrawOptions options)
|
||||
{
|
||||
options ??= new DrawOptions();
|
||||
var (valueWidth, maxWidth) = (options.Width, options.MaxWidth);
|
||||
|
||||
using (new GUILayout.HorizontalScope(GUILayout.MaxWidth(maxWidth)))
|
||||
{
|
||||
using (new GUILayout.VerticalScope())
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("X:", NitroxGUILayout.DrawerLabel);
|
||||
rect.x = NitroxGUILayout.FloatField(rect.x, valueWidth);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Y:", NitroxGUILayout.DrawerLabel);
|
||||
rect.y = NitroxGUILayout.FloatField(rect.y, valueWidth);
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.VerticalScope())
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("W:", NitroxGUILayout.DrawerLabel);
|
||||
rect.width = NitroxGUILayout.FloatField(rect.width, valueWidth);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("H:", NitroxGUILayout.DrawerLabel);
|
||||
rect.height = NitroxGUILayout.FloatField(rect.height, valueWidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
public Rect Draw(Rect rect)
|
||||
{
|
||||
return Draw(rect, null);
|
||||
}
|
||||
|
||||
public RectOffset Draw(RectOffset rect, DrawOptions options)
|
||||
{
|
||||
options ??= new DrawOptions(Width: MAX_WIDTH);
|
||||
|
||||
float valueWidth = options.MaxWidth / 4 - 6;
|
||||
using (new GUILayout.HorizontalScope(GUILayout.MaxWidth(options.MaxWidth)))
|
||||
{
|
||||
rect.left = NitroxGUILayout.IntField(rect.left, valueWidth);
|
||||
NitroxGUILayout.Separator();
|
||||
rect.right = NitroxGUILayout.IntField(rect.right, valueWidth);
|
||||
NitroxGUILayout.Separator();
|
||||
rect.top = NitroxGUILayout.IntField(rect.top, valueWidth);
|
||||
NitroxGUILayout.Separator();
|
||||
rect.bottom = NitroxGUILayout.IntField(rect.bottom, valueWidth);
|
||||
}
|
||||
return rect;
|
||||
}
|
||||
|
||||
public RectOffset Draw(RectOffset rect)
|
||||
{
|
||||
return Draw(rect, null);
|
||||
}
|
||||
|
||||
public record DrawOptions(float Width = 100, float MaxWidth = 215);
|
||||
}
|
118
NitroxClient/Debuggers/Drawer/Unity/RigidbodyDrawer.cs
Normal file
118
NitroxClient/Debuggers/Drawer/Unity/RigidbodyDrawer.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
using NitroxModel.Helper;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.Unity;
|
||||
|
||||
public class RigidbodyDrawer : IDrawer<Rigidbody>
|
||||
{
|
||||
private readonly VectorDrawer vectorDrawer;
|
||||
private const float LABEL_WIDTH = 120;
|
||||
private const float VALUE_MAX_WIDTH = 405;
|
||||
|
||||
public RigidbodyDrawer(VectorDrawer vectorDrawer)
|
||||
{
|
||||
Validate.NotNull(vectorDrawer);
|
||||
|
||||
this.vectorDrawer = vectorDrawer;
|
||||
}
|
||||
|
||||
public void Draw(Rigidbody rb)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Mass", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
rb.mass = NitroxGUILayout.FloatField(rb.mass, VALUE_MAX_WIDTH);
|
||||
}
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Drag", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
rb.drag = NitroxGUILayout.FloatField(rb.drag, VALUE_MAX_WIDTH);
|
||||
}
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Angular Drag", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
rb.angularDrag = NitroxGUILayout.FloatField(rb.angularDrag, VALUE_MAX_WIDTH);
|
||||
}
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Use Gravity");
|
||||
NitroxGUILayout.Separator();
|
||||
rb.useGravity = NitroxGUILayout.BoolField(rb.useGravity);
|
||||
}
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Is Kinematic");
|
||||
NitroxGUILayout.Separator();
|
||||
rb.isKinematic = NitroxGUILayout.BoolField(rb.isKinematic);
|
||||
}
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Interpolate", GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
rb.interpolation = NitroxGUILayout.EnumPopup(rb.interpolation, NitroxGUILayout.VALUE_WIDTH);
|
||||
}
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Collision Detection", GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
rb.collisionDetectionMode = NitroxGUILayout.EnumPopup(rb.collisionDetectionMode, NitroxGUILayout.VALUE_WIDTH);
|
||||
}
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Freeze Rotation");
|
||||
NitroxGUILayout.Separator();
|
||||
rb.freezeRotation = NitroxGUILayout.BoolField(rb.freezeRotation);
|
||||
}
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Velocity", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
vectorDrawer.Draw(rb.velocity, new VectorDrawer.DrawOptions(VALUE_MAX_WIDTH));
|
||||
}
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Angular Velocity", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
vectorDrawer.Draw(rb.angularVelocity, new VectorDrawer.DrawOptions(VALUE_MAX_WIDTH));
|
||||
}
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Detect Collisions", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
rb.detectCollisions = NitroxGUILayout.BoolField(rb.detectCollisions, NitroxGUILayout.VALUE_WIDTH);
|
||||
}
|
||||
}
|
||||
}
|
107
NitroxClient/Debuggers/Drawer/Unity/TransformDrawer.cs
Normal file
107
NitroxClient/Debuggers/Drawer/Unity/TransformDrawer.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
using NitroxModel.Helper;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.Unity;
|
||||
|
||||
public class TransformDrawer : IDrawer<Transform>
|
||||
{
|
||||
private readonly SceneDebugger sceneDebugger;
|
||||
private readonly VectorDrawer vectorDrawer;
|
||||
private const float LABEL_WIDTH = 100;
|
||||
private const float VECTOR_MAX_WIDTH = 405;
|
||||
|
||||
private bool showGlobal;
|
||||
|
||||
public TransformDrawer(SceneDebugger sceneDebugger, VectorDrawer vectorDrawer)
|
||||
{
|
||||
Validate.NotNull(sceneDebugger);
|
||||
Validate.NotNull(vectorDrawer);
|
||||
|
||||
this.sceneDebugger = sceneDebugger;
|
||||
this.vectorDrawer = vectorDrawer;
|
||||
}
|
||||
|
||||
public void Draw(Transform transform)
|
||||
{
|
||||
using (new GUILayout.VerticalScope())
|
||||
{
|
||||
if (showGlobal)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Global Position", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
vectorDrawer.Draw(transform.position, new VectorDrawer.DrawOptions(VECTOR_MAX_WIDTH));
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Global Rotation", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
vectorDrawer.Draw(transform.rotation.eulerAngles, new VectorDrawer.DrawOptions(VECTOR_MAX_WIDTH));
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Lossy Scale", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
vectorDrawer.Draw(transform.lossyScale, new VectorDrawer.DrawOptions(VECTOR_MAX_WIDTH));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Local Position", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
transform.localPosition = vectorDrawer.Draw(transform.localPosition, new VectorDrawer.DrawOptions(VECTOR_MAX_WIDTH));
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Local Rotation", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
transform.localRotation = Quaternion.Euler(vectorDrawer.Draw(transform.localRotation.eulerAngles, new VectorDrawer.DrawOptions(VECTOR_MAX_WIDTH)));
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Local Scale", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
transform.localScale = vectorDrawer.Draw(transform.localScale, new VectorDrawer.DrawOptions(VECTOR_MAX_WIDTH));
|
||||
}
|
||||
}
|
||||
|
||||
GUILayout.Space(5);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
if (GUILayout.Button("Toggle Local/Global", GUILayout.MaxWidth(125)))
|
||||
{
|
||||
showGlobal = !showGlobal;
|
||||
}
|
||||
if (GUILayout.Button("Destroy GameObject", GUILayout.MaxWidth(150)))
|
||||
{
|
||||
if (transform)
|
||||
{
|
||||
if (transform.parent)
|
||||
{
|
||||
sceneDebugger.JumpToComponent(transform.parent);
|
||||
}
|
||||
UnityEngine.Object.Destroy(transform.gameObject);
|
||||
}
|
||||
}
|
||||
if (GUILayout.Button("Goto", GUILayout.MaxWidth(75)) && Player.main)
|
||||
{
|
||||
SubRoot subRoot = transform.GetComponentInParent<SubRoot>(true);
|
||||
Player.main.SetCurrentSub(subRoot, true);
|
||||
Player.main.SetPosition(transform.position);
|
||||
}
|
||||
if (GUILayout.Button($"Set {(transform.gameObject.activeSelf ? "inactive" : "active")}", GUILayout.MaxWidth(125)))
|
||||
{
|
||||
transform.gameObject.SetActive(!transform.gameObject.activeSelf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
67
NitroxClient/Debuggers/Drawer/Unity/UnityEventDrawer.cs
Normal file
67
NitroxClient/Debuggers/Drawer/Unity/UnityEventDrawer.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.Unity;
|
||||
|
||||
public class UnityEventDrawer : IDrawer<UnityEvent, UnityEventDrawer.DrawOptions>, IDrawer<UnityEvent<bool>, UnityEventDrawer.DrawOptions>
|
||||
{
|
||||
private const float LABEL_WIDTH = 250;
|
||||
|
||||
public void Draw(UnityEvent unityEvent, DrawOptions options)
|
||||
{
|
||||
options ??= new DrawOptions();
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label(options.Name, NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
if (GUILayout.Button("Invoke All", GUILayout.Width(100)))
|
||||
{
|
||||
unityEvent.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
DrawUnityEventBase(unityEvent);
|
||||
}
|
||||
|
||||
public void Draw(UnityEvent<bool> unityEvent, DrawOptions options)
|
||||
{
|
||||
options ??= new DrawOptions();
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label(options.Name, NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
if (GUILayout.Button("Invoke All (true)", GUILayout.Width(100)))
|
||||
{
|
||||
unityEvent.Invoke(true);
|
||||
}
|
||||
if (GUILayout.Button("Invoke All (false)", GUILayout.Width(100)))
|
||||
{
|
||||
unityEvent.Invoke(false);
|
||||
}
|
||||
}
|
||||
|
||||
DrawUnityEventBase(unityEvent);
|
||||
}
|
||||
|
||||
private static void DrawUnityEventBase(UnityEventBase unityEventBase)
|
||||
{
|
||||
for (int index = 0; index < unityEventBase.GetPersistentEventCount(); index++)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
NitroxGUILayout.Separator();
|
||||
Object target = unityEventBase.GetPersistentTarget(index);
|
||||
string labelText = target ? $"{target.GetType().Name}.{unityEventBase.GetPersistentMethodName(index)}()" : $"{unityEventBase.GetPersistentMethodName(index)}()";
|
||||
GUILayout.Label(labelText, NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public record DrawOptions(string Name = "NoName");
|
||||
|
||||
public void Draw(UnityEvent unityEvent) => Draw(unityEvent, null);
|
||||
|
||||
public void Draw(UnityEvent<bool> unityEvent) => Draw(unityEvent, null);
|
||||
}
|
100
NitroxClient/Debuggers/Drawer/Unity/VectorDrawer.cs
Normal file
100
NitroxClient/Debuggers/Drawer/Unity/VectorDrawer.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
using NitroxModel_Subnautica.DataStructures;
|
||||
using NitroxModel.DataStructures.Unity;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.Unity;
|
||||
|
||||
public class VectorDrawer : IEditorDrawer<Vector2, VectorDrawer.DrawOptions>, IEditorDrawer<Vector3, VectorDrawer.DrawOptions>, IEditorDrawer<NitroxVector3>, IEditorDrawer<Vector4>, IEditorDrawer<NitroxVector4>, IEditorDrawer<Quaternion>,
|
||||
IEditorDrawer<Int3>
|
||||
{
|
||||
private const float MAX_WIDTH = 400;
|
||||
|
||||
public Vector2 Draw(Vector2 vector2, DrawOptions options)
|
||||
{
|
||||
options ??= new DrawOptions();
|
||||
|
||||
float valueWidth = options.MaxWidth / 2 - 5;
|
||||
using (new GUILayout.HorizontalScope(GUILayout.MaxWidth(options.MaxWidth)))
|
||||
{
|
||||
vector2.x = NitroxGUILayout.FloatField(vector2.x, valueWidth);
|
||||
NitroxGUILayout.Separator();
|
||||
vector2.y = NitroxGUILayout.FloatField(vector2.y, valueWidth);
|
||||
return vector2;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 Draw(Vector3 vector3, DrawOptions options)
|
||||
{
|
||||
options ??= new DrawOptions();
|
||||
|
||||
float valueWidth = options.MaxWidth / 3 - 5;
|
||||
using (new GUILayout.HorizontalScope(GUILayout.MaxWidth(options.MaxWidth)))
|
||||
{
|
||||
vector3.x = NitroxGUILayout.FloatField(vector3.x, valueWidth);
|
||||
NitroxGUILayout.Separator();
|
||||
vector3.y = NitroxGUILayout.FloatField(vector3.y, valueWidth);
|
||||
NitroxGUILayout.Separator();
|
||||
vector3.z = NitroxGUILayout.FloatField(vector3.z, valueWidth);
|
||||
return vector3;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector4 Draw(Vector4 vector)
|
||||
{
|
||||
float valueWidth = MAX_WIDTH / 4 - 6;
|
||||
using (new GUILayout.HorizontalScope(GUILayout.MaxWidth(MAX_WIDTH)))
|
||||
{
|
||||
vector.x = NitroxGUILayout.FloatField(vector.x, valueWidth);
|
||||
NitroxGUILayout.Separator();
|
||||
vector.y = NitroxGUILayout.FloatField(vector.y, valueWidth);
|
||||
NitroxGUILayout.Separator();
|
||||
vector.z = NitroxGUILayout.FloatField(vector.z, valueWidth);
|
||||
NitroxGUILayout.Separator();
|
||||
vector.w = NitroxGUILayout.FloatField(vector.w, valueWidth);
|
||||
return vector;
|
||||
}
|
||||
}
|
||||
|
||||
public Quaternion Draw(Quaternion vector)
|
||||
{
|
||||
Vector4 vector4 = new(vector.x, vector.y, vector.z, vector.w);
|
||||
vector4 = Draw(vector4);
|
||||
return new Quaternion(vector4.x, vector4.y, vector4.z, vector4.w);
|
||||
}
|
||||
|
||||
public Int3 Draw(Int3 vector)
|
||||
{
|
||||
float valueWidth = MAX_WIDTH / 3 - 5;
|
||||
using (new GUILayout.HorizontalScope(GUILayout.MaxWidth(MAX_WIDTH)))
|
||||
{
|
||||
vector.x = NitroxGUILayout.IntField(vector.x, valueWidth);
|
||||
NitroxGUILayout.Separator();
|
||||
vector.y = NitroxGUILayout.IntField(vector.y, valueWidth);
|
||||
NitroxGUILayout.Separator();
|
||||
vector.z = NitroxGUILayout.IntField(vector.z, valueWidth);
|
||||
return vector;
|
||||
}
|
||||
}
|
||||
|
||||
public NitroxVector3 Draw(NitroxVector3 vector)
|
||||
{
|
||||
return Draw(vector.ToUnity()).ToDto();
|
||||
}
|
||||
|
||||
public NitroxVector4 Draw(NitroxVector4 vector)
|
||||
{
|
||||
return Draw(vector.ToUnity()).ToDto();
|
||||
}
|
||||
|
||||
public record DrawOptions(float MaxWidth = MAX_WIDTH);
|
||||
|
||||
public Vector2 Draw(Vector2 vector)
|
||||
{
|
||||
return Draw(vector, null);
|
||||
}
|
||||
|
||||
public Vector3 Draw(Vector3 vector)
|
||||
{
|
||||
return Draw(vector, null);
|
||||
}
|
||||
}
|
55
NitroxClient/Debuggers/Drawer/UnityUI/AnimatorDrawer.cs
Normal file
55
NitroxClient/Debuggers/Drawer/UnityUI/AnimatorDrawer.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.UnityUI;
|
||||
|
||||
public class AnimatorDrawer : IDrawer<Animator>
|
||||
{
|
||||
public void Draw(Animator target)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("updateMode", GUILayout.Width(200));
|
||||
target.updateMode = NitroxGUILayout.EnumPopup(target.updateMode, NitroxGUILayout.VALUE_WIDTH);
|
||||
}
|
||||
|
||||
GUILayout.Label($"Parameters [{target.parameterCount}]:");
|
||||
foreach (AnimatorControllerParameter parameter in target.parameters)
|
||||
{
|
||||
GUILayout.Space(8);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label(parameter.name, GUILayout.Width(200));
|
||||
NitroxGUILayout.Separator();
|
||||
switch (parameter.type)
|
||||
{
|
||||
case AnimatorControllerParameterType.Float:
|
||||
float floatValue = NitroxGUILayout.FloatField(target.GetFloat(parameter.name));
|
||||
|
||||
target.SetFloat(parameter.name, GUILayout.Button("Reset") ? parameter.defaultFloat : floatValue);
|
||||
break;
|
||||
case AnimatorControllerParameterType.Int:
|
||||
int intValue = NitroxGUILayout.IntField(target.GetInteger(parameter.name));
|
||||
|
||||
target.SetInteger(parameter.name, GUILayout.Button("Reset") ? parameter.defaultInt : intValue);
|
||||
break;
|
||||
case AnimatorControllerParameterType.Bool:
|
||||
bool boolValue = NitroxGUILayout.BoolField(target.GetBool(parameter.name));
|
||||
|
||||
target.SetBool(parameter.name, GUILayout.Button("Reset") ? parameter.defaultBool : boolValue);
|
||||
break;
|
||||
case AnimatorControllerParameterType.Trigger:
|
||||
if (GUILayout.Button("Trigger"))
|
||||
{
|
||||
target.SetTrigger(parameter.name);
|
||||
}
|
||||
if (GUILayout.Button("Reset"))
|
||||
{
|
||||
target.ResetTrigger(parameter.name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.UnityUI;
|
||||
|
||||
public class AspectRatioFitterDrawer : IDrawer<AspectRatioFitter>
|
||||
{
|
||||
public void Draw(AspectRatioFitter aspectRatioFitter)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Aspect Mode", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
aspectRatioFitter.aspectMode = NitroxGUILayout.EnumPopup(aspectRatioFitter.aspectMode);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Aspect Ratio", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
|
||||
if (aspectRatioFitter.aspectMode == AspectRatioFitter.AspectMode.None)
|
||||
{
|
||||
NitroxGUILayout.FloatField(aspectRatioFitter.aspectRatio);
|
||||
}
|
||||
else
|
||||
{
|
||||
aspectRatioFitter.aspectRatio = NitroxGUILayout.FloatField(aspectRatioFitter.aspectRatio);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
27
NitroxClient/Debuggers/Drawer/UnityUI/ButtonDrawer.cs
Normal file
27
NitroxClient/Debuggers/Drawer/UnityUI/ButtonDrawer.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using NitroxClient.Debuggers.Drawer.Unity;
|
||||
using NitroxModel.Helper;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.UnityUI;
|
||||
|
||||
public class ButtonDrawer : IDrawer<Button>
|
||||
{
|
||||
private readonly SelectableDrawer selectableDrawer;
|
||||
private readonly UnityEventDrawer unityEventDrawer;
|
||||
|
||||
public ButtonDrawer(SelectableDrawer selectableDrawer, UnityEventDrawer unityEventDrawer)
|
||||
{
|
||||
Validate.NotNull(selectableDrawer);
|
||||
Validate.NotNull(unityEventDrawer);
|
||||
this.selectableDrawer = selectableDrawer;
|
||||
this.unityEventDrawer = unityEventDrawer;
|
||||
}
|
||||
|
||||
public void Draw(Button button)
|
||||
{
|
||||
selectableDrawer.Draw(button);
|
||||
GUILayout.Space(10);
|
||||
unityEventDrawer.Draw(button.onClick, new UnityEventDrawer.DrawOptions("OnClick()"));
|
||||
}
|
||||
}
|
111
NitroxClient/Debuggers/Drawer/UnityUI/CanvasDrawer.cs
Normal file
111
NitroxClient/Debuggers/Drawer/UnityUI/CanvasDrawer.cs
Normal file
@@ -0,0 +1,111 @@
|
||||
using System;
|
||||
using NitroxModel.Helper;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.UnityUI;
|
||||
|
||||
public class CanvasDrawer : IDrawer<Canvas>
|
||||
{
|
||||
private readonly SceneDebugger sceneDebugger;
|
||||
|
||||
public CanvasDrawer(SceneDebugger sceneDebugger)
|
||||
{
|
||||
Validate.NotNull(sceneDebugger);
|
||||
this.sceneDebugger = sceneDebugger;
|
||||
}
|
||||
|
||||
public void Draw(Canvas canvas)
|
||||
{
|
||||
RenderMode renderMode = canvas.renderMode;
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Raycast Target", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
renderMode = NitroxGUILayout.EnumPopup(renderMode);
|
||||
}
|
||||
|
||||
if (renderMode == RenderMode.WorldSpace)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Event Camera", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
if (GUILayout.Button("Jump to", GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH)))
|
||||
{
|
||||
sceneDebugger.UpdateSelectedObject(canvas.worldCamera.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Sorting layer", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
canvas.sortingLayerID = NitroxGUILayout.IntField(canvas.sortingLayerID);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Order in Layer", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
canvas.sortingOrder = NitroxGUILayout.IntField(canvas.sortingOrder);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Additional Shader Channels", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
canvas.additionalShaderChannels = NitroxGUILayout.EnumPopup(canvas.additionalShaderChannels);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Pixel Perfect", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
canvas.pixelPerfect = NitroxGUILayout.BoolField(canvas.pixelPerfect);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Sort Order", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
canvas.sortingOrder = NitroxGUILayout.IntField(canvas.sortingOrder);
|
||||
}
|
||||
|
||||
if (renderMode == RenderMode.ScreenSpaceOverlay)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Target Display", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
int newTargetDisplay = NitroxGUILayout.IntField(canvas.targetDisplay);
|
||||
canvas.targetDisplay = Math.Max(0, Math.Min(8, newTargetDisplay));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Render Camera", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
if (GUILayout.Button("Jump to", GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH)))
|
||||
{
|
||||
sceneDebugger.UpdateSelectedObject(canvas.worldCamera.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
if (canvas.worldCamera)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Plane Distance", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
canvas.planeDistance = NitroxGUILayout.FloatField(canvas.planeDistance);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
37
NitroxClient/Debuggers/Drawer/UnityUI/CanvasGroupDrawer.cs
Normal file
37
NitroxClient/Debuggers/Drawer/UnityUI/CanvasGroupDrawer.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.UnityUI;
|
||||
|
||||
public class CanvasGroupDrawer : IDrawer<CanvasGroup>
|
||||
{
|
||||
public void Draw(CanvasGroup canvasGroup)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Alpha", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
canvasGroup.alpha = NitroxGUILayout.SliderField(canvasGroup.alpha, 0f, 1f);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Interactable", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
canvasGroup.interactable = NitroxGUILayout.BoolField(canvasGroup.interactable);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Blocks Raycasts", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
canvasGroup.blocksRaycasts = NitroxGUILayout.BoolField(canvasGroup.blocksRaycasts);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Ignore Parent Groups", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
canvasGroup.ignoreParentGroups = NitroxGUILayout.BoolField(canvasGroup.ignoreParentGroups);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.UnityUI;
|
||||
|
||||
public class CanvasRendererDrawer : IDrawer<CanvasRenderer>
|
||||
{
|
||||
public void Draw(CanvasRenderer canvasRenderer)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Raycast Target", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
canvasRenderer.cullTransparentMesh = NitroxGUILayout.BoolField(canvasRenderer.cullTransparentMesh);
|
||||
}
|
||||
}
|
||||
}
|
105
NitroxClient/Debuggers/Drawer/UnityUI/CanvasScalerDrawer.cs
Normal file
105
NitroxClient/Debuggers/Drawer/UnityUI/CanvasScalerDrawer.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
using NitroxClient.Debuggers.Drawer.Unity;
|
||||
using NitroxModel.Helper;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.UnityUI;
|
||||
|
||||
public class CanvasScalerDrawer : IDrawer<CanvasScaler>
|
||||
{
|
||||
private readonly VectorDrawer vectorDrawer;
|
||||
|
||||
public CanvasScalerDrawer(VectorDrawer vectorDrawer)
|
||||
{
|
||||
Validate.NotNull(vectorDrawer);
|
||||
|
||||
this.vectorDrawer = vectorDrawer;
|
||||
}
|
||||
|
||||
public void Draw(CanvasScaler canvasScaler)
|
||||
{
|
||||
if (canvasScaler.GetComponent<Canvas>().renderMode == RenderMode.WorldSpace)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Dynamic Pixels Per Unit", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
canvasScaler.dynamicPixelsPerUnit = NitroxGUILayout.FloatField(canvasScaler.dynamicPixelsPerUnit);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("UI Scale Mode", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
canvasScaler.uiScaleMode = NitroxGUILayout.EnumPopup(canvasScaler.uiScaleMode);
|
||||
}
|
||||
|
||||
if (canvasScaler.uiScaleMode == CanvasScaler.ScaleMode.ConstantPixelSize)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Scale Factor", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
canvasScaler.scaleFactor = NitroxGUILayout.FloatField(canvasScaler.scaleFactor);
|
||||
}
|
||||
}
|
||||
else if (canvasScaler.uiScaleMode == CanvasScaler.ScaleMode.ScaleWithScreenSize)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Reference Resolution", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
canvasScaler.referenceResolution = vectorDrawer.Draw(canvasScaler.referenceResolution);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Screen Match Mode", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
canvasScaler.screenMatchMode = NitroxGUILayout.EnumPopup(canvasScaler.screenMatchMode);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Match", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
float newMatchValue = NitroxGUILayout.FloatField(canvasScaler.matchWidthOrHeight);
|
||||
canvasScaler.matchWidthOrHeight = UnityEngine.Mathf.Max(0, UnityEngine.Mathf.Min(newMatchValue, 1));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Physical Unit", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
canvasScaler.physicalUnit = NitroxGUILayout.EnumPopup(canvasScaler.physicalUnit);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Fallback Screen DPI", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
canvasScaler.matchWidthOrHeight = NitroxGUILayout.FloatField(canvasScaler.fallbackScreenDPI);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Default Sprite DPI", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
float newDefaultSpriteDPI = NitroxGUILayout.FloatField(canvasScaler.defaultSpriteDPI);
|
||||
canvasScaler.defaultSpriteDPI = UnityEngine.Mathf.Max(1, newDefaultSpriteDPI);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Reference Pixels Per Unit", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
canvasScaler.referencePixelsPerUnit = NitroxGUILayout.FloatField(canvasScaler.referencePixelsPerUnit);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.UnityUI;
|
||||
|
||||
public class ContentSizeFitterDrawer : IDrawer<ContentSizeFitter>
|
||||
{
|
||||
public void Draw(ContentSizeFitter contentSizeFitter)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Horizontal Fit", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
contentSizeFitter.horizontalFit = NitroxGUILayout.EnumPopup(contentSizeFitter.horizontalFit);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Vertical Fit", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
contentSizeFitter.verticalFit = NitroxGUILayout.EnumPopup(contentSizeFitter.verticalFit);
|
||||
}
|
||||
}
|
||||
}
|
111
NitroxClient/Debuggers/Drawer/UnityUI/DropdownDrawer.cs
Normal file
111
NitroxClient/Debuggers/Drawer/UnityUI/DropdownDrawer.cs
Normal file
@@ -0,0 +1,111 @@
|
||||
using System;
|
||||
using NitroxModel.Core;
|
||||
using NitroxModel.Helper;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.UnityUI;
|
||||
|
||||
public class DropdownDrawer : IDrawer<Dropdown>
|
||||
{
|
||||
private readonly SelectableDrawer selectableDrawer;
|
||||
private readonly SceneDebugger sceneDebugger;
|
||||
|
||||
public DropdownDrawer(SceneDebugger sceneDebugger, SelectableDrawer selectableDrawer)
|
||||
{
|
||||
Validate.NotNull(sceneDebugger);
|
||||
Validate.NotNull(selectableDrawer);
|
||||
|
||||
this.selectableDrawer = selectableDrawer;
|
||||
this.sceneDebugger = sceneDebugger;
|
||||
}
|
||||
|
||||
public void Draw(Dropdown dropdown)
|
||||
{
|
||||
selectableDrawer.Draw(dropdown);
|
||||
|
||||
GUILayout.Space(NitroxGUILayout.DEFAULT_SPACE);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Template", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
if (GUILayout.Button("Jump to", GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH)))
|
||||
{
|
||||
sceneDebugger.JumpToComponent(dropdown.template);
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Caption Text", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
if (GUILayout.Button("Jump to", GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH)))
|
||||
{
|
||||
sceneDebugger.JumpToComponent(dropdown.captionText);
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Caption Image", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
if (GUILayout.Button("Jump to", GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH)))
|
||||
{
|
||||
sceneDebugger.JumpToComponent(dropdown.captionImage);
|
||||
}
|
||||
}
|
||||
|
||||
GUILayout.Space(NitroxGUILayout.DEFAULT_SPACE);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Item Text", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
if (GUILayout.Button("Jump to", GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH)))
|
||||
{
|
||||
sceneDebugger.JumpToComponent(dropdown.itemText);
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Item Image", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
if (GUILayout.Button("Jump to", GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH)))
|
||||
{
|
||||
sceneDebugger.JumpToComponent(dropdown.itemImage);
|
||||
}
|
||||
}
|
||||
|
||||
GUILayout.Space(NitroxGUILayout.DEFAULT_SPACE);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Value", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
dropdown.value = NitroxGUILayout.IntField(dropdown.value);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Alpha Fade Speed", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
dropdown.alphaFadeSpeed = NitroxGUILayout.FloatField(dropdown.alphaFadeSpeed);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Options", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
GUILayout.Button("Unsupported", GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("On Value Changed", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
GUILayout.Button("Unsupported", GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
}
|
||||
}
|
||||
}
|
57
NitroxClient/Debuggers/Drawer/UnityUI/EventTriggerDrawer.cs
Normal file
57
NitroxClient/Debuggers/Drawer/UnityUI/EventTriggerDrawer.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using NitroxModel.Helper;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.UnityUI;
|
||||
|
||||
public class EventTriggerDrawer : IDrawer<EventTrigger>
|
||||
{
|
||||
private readonly SceneDebugger sceneDebugger;
|
||||
|
||||
public EventTriggerDrawer(SceneDebugger sceneDebugger)
|
||||
{
|
||||
Validate.NotNull(sceneDebugger);
|
||||
|
||||
this.sceneDebugger = sceneDebugger;
|
||||
}
|
||||
|
||||
public void Draw(EventTrigger eventTrigger)
|
||||
{
|
||||
foreach (EventTrigger.Entry entry in eventTrigger.triggers.OrderBy(x => x.eventID))
|
||||
{
|
||||
using (new GUILayout.VerticalScope("box"))
|
||||
{
|
||||
GUILayout.Label($"EventTriggerType.{Enum.GetName(typeof(EventTriggerType), entry.eventID)}");
|
||||
|
||||
for (int i = 0; i < entry.callback.GetPersistentEventCount(); i++)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
object target = entry.callback.GetPersistentTarget(i);
|
||||
|
||||
switch (target)
|
||||
{
|
||||
case Component component:
|
||||
if (GUILayout.Button($"Jump to {component.name}", GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH)))
|
||||
{
|
||||
sceneDebugger.JumpToComponent(component);
|
||||
}
|
||||
NitroxGUILayout.Separator();
|
||||
GUILayout.TextField($"{component.GetType().Name}.{entry.callback.GetPersistentMethodName(i)}()", GUILayout.ExpandWidth(true), GUILayout.MaxWidth(250));
|
||||
break;
|
||||
default:
|
||||
GUILayout.TextField($"[{target.GetType().Name}]: {target}", GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
GUILayout.TextField($"{entry.callback.GetPersistentMethodName(i)}()", GUILayout.ExpandWidth(true), GUILayout.MaxWidth(250));
|
||||
break;
|
||||
}
|
||||
}
|
||||
NitroxGUILayout.Separator();
|
||||
}
|
||||
}
|
||||
NitroxGUILayout.Separator();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.UnityUI;
|
||||
|
||||
public class GraphicRaycasterDrawer : IDrawer<GraphicRaycaster>
|
||||
{
|
||||
public void Draw(GraphicRaycaster graphicRaycaster)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Ignore Reversed Graphics", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
graphicRaycaster.ignoreReversedGraphics = NitroxGUILayout.BoolField(graphicRaycaster.ignoreReversedGraphics);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Blocking Objects", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
graphicRaycaster.blockingObjects = NitroxGUILayout.EnumPopup(graphicRaycaster.blockingObjects);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using NitroxClient.Debuggers.Drawer.Unity;
|
||||
using NitroxModel.Helper;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.UnityUI;
|
||||
|
||||
public class GridLayoutGroupDrawer : IDrawer<GridLayoutGroup>
|
||||
{
|
||||
private readonly VectorDrawer vectorDrawer;
|
||||
private readonly RectDrawer rectDrawer;
|
||||
|
||||
public GridLayoutGroupDrawer(VectorDrawer vectorDrawer, RectDrawer rectDrawer)
|
||||
{
|
||||
Validate.NotNull(vectorDrawer);
|
||||
Validate.NotNull(rectDrawer);
|
||||
|
||||
this.vectorDrawer = vectorDrawer;
|
||||
this.rectDrawer = rectDrawer;
|
||||
}
|
||||
|
||||
public void Draw(GridLayoutGroup gridLayoutGroup)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Padding", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
gridLayoutGroup.padding = rectDrawer.Draw(gridLayoutGroup.padding);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Cell Size", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
gridLayoutGroup.cellSize = vectorDrawer.Draw(gridLayoutGroup.cellSize);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Spacing", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
gridLayoutGroup.spacing = vectorDrawer.Draw(gridLayoutGroup.spacing);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Start Corner", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
gridLayoutGroup.startCorner = NitroxGUILayout.EnumPopup(gridLayoutGroup.startCorner);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Start Axis", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
gridLayoutGroup.startAxis = NitroxGUILayout.EnumPopup(gridLayoutGroup.startAxis);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Child Alignment", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
gridLayoutGroup.childAlignment = NitroxGUILayout.EnumPopup(gridLayoutGroup.childAlignment);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Constraint", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
gridLayoutGroup.constraint = NitroxGUILayout.EnumPopup(gridLayoutGroup.constraint);
|
||||
}
|
||||
|
||||
if (gridLayoutGroup.constraint != GridLayoutGroup.Constraint.Flexible)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Constraint Count", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
gridLayoutGroup.constraintCount = Math.Max(1, NitroxGUILayout.IntField(gridLayoutGroup.constraintCount));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
100
NitroxClient/Debuggers/Drawer/UnityUI/ImageDrawer.cs
Normal file
100
NitroxClient/Debuggers/Drawer/UnityUI/ImageDrawer.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
using System;
|
||||
using NitroxClient.Debuggers.Drawer.Unity;
|
||||
using NitroxModel.Helper;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.UnityUI;
|
||||
|
||||
public class ImageDrawer : IDrawer<Image>, IDrawer<RawImage>
|
||||
{
|
||||
private readonly ColorDrawer colorDrawer;
|
||||
private readonly MaterialDrawer materialDrawer;
|
||||
private readonly RectDrawer rectDrawer;
|
||||
|
||||
public ImageDrawer(ColorDrawer colorDrawer, MaterialDrawer materialDrawer, RectDrawer rectDrawer)
|
||||
{
|
||||
Validate.NotNull(colorDrawer);
|
||||
Validate.NotNull(materialDrawer);
|
||||
Validate.NotNull(rectDrawer);
|
||||
|
||||
this.colorDrawer = colorDrawer;
|
||||
this.materialDrawer = materialDrawer;
|
||||
this.rectDrawer = rectDrawer;
|
||||
}
|
||||
|
||||
public static void DrawTexture(Texture texture)
|
||||
{
|
||||
GUIStyle style = new("box") { fixedHeight = texture.height * (250f / texture.width), fixedWidth = 250 };
|
||||
GUILayout.Box(texture, style);
|
||||
}
|
||||
|
||||
public void Draw(Image image)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Image", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
DrawTexture(image.mainTexture);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Color", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
image.color = colorDrawer.Draw(image.color);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Material", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
image.material = materialDrawer.Draw(image.material);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Raycast Target", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
image.raycastTarget = NitroxGUILayout.BoolField(image.raycastTarget);
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(RawImage rawImage)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Image", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
DrawTexture(rawImage.mainTexture);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Color", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
rawImage.color = colorDrawer.Draw(rawImage.color);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Material", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
rawImage.material = materialDrawer.Draw(rawImage.material);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Raycast Target", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
rawImage.raycastTarget = NitroxGUILayout.BoolField(rawImage.raycastTarget);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("UV Rect", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
rawImage.uvRect = rectDrawer.Draw(rawImage.uvRect);
|
||||
}
|
||||
}
|
||||
}
|
151
NitroxClient/Debuggers/Drawer/UnityUI/InputFieldDrawer.cs
Normal file
151
NitroxClient/Debuggers/Drawer/UnityUI/InputFieldDrawer.cs
Normal file
@@ -0,0 +1,151 @@
|
||||
using NitroxClient.Debuggers.Drawer.Unity;
|
||||
using NitroxModel.Helper;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.UnityUI;
|
||||
|
||||
public class InputFieldDrawer : IDrawer<InputField>
|
||||
{
|
||||
private readonly SceneDebugger sceneDebugger;
|
||||
private readonly SelectableDrawer selectableDrawer;
|
||||
private readonly ColorDrawer colorDrawer;
|
||||
|
||||
public InputFieldDrawer(SceneDebugger sceneDebugger, SelectableDrawer selectableDrawer, ColorDrawer colorDrawer)
|
||||
{
|
||||
Validate.NotNull(sceneDebugger);
|
||||
Validate.NotNull(selectableDrawer);
|
||||
Validate.NotNull(colorDrawer);
|
||||
|
||||
this.sceneDebugger = sceneDebugger;
|
||||
this.selectableDrawer = selectableDrawer;
|
||||
this.colorDrawer = colorDrawer;
|
||||
}
|
||||
|
||||
public void Draw(InputField inputField)
|
||||
{
|
||||
selectableDrawer.Draw(inputField);
|
||||
|
||||
GUILayout.Space(NitroxGUILayout.DEFAULT_SPACE);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Text Component", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
if (GUILayout.Button("Jump to", GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH)))
|
||||
{
|
||||
sceneDebugger.JumpToComponent(inputField.textComponent);
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Text", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
inputField.text = GUILayout.TextArea(inputField.text, GUILayout.MaxHeight(100));
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Character Limit", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
inputField.characterLimit = NitroxGUILayout.IntField(inputField.characterLimit);
|
||||
}
|
||||
|
||||
GUILayout.Space(NitroxGUILayout.DEFAULT_SPACE);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Content Type", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
inputField.contentType = NitroxGUILayout.EnumPopup(inputField.contentType);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Line Type", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
inputField.lineType = NitroxGUILayout.EnumPopup(inputField.lineType);
|
||||
}
|
||||
|
||||
GUILayout.Space(NitroxGUILayout.DEFAULT_SPACE);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Placeholder", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
if (GUILayout.Button("Jump to", GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH)))
|
||||
{
|
||||
sceneDebugger.JumpToComponent(inputField.placeholder);
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Caret Blink Rate", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
inputField.caretBlinkRate = NitroxGUILayout.SliderField(inputField.caretBlinkRate, 0f, 4f);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Caret Width", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
inputField.caretWidth = NitroxGUILayout.SliderField(inputField.caretWidth, 1, 5);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Custom Caret Color", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
inputField.customCaretColor = NitroxGUILayout.BoolField(inputField.customCaretColor);
|
||||
}
|
||||
|
||||
if (inputField.customCaretColor)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Caret Color", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
inputField.caretColor = colorDrawer.Draw(inputField.caretColor);
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Selection Color", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
inputField.selectionColor = colorDrawer.Draw(inputField.selectionColor);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Hide Mobile Input", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
inputField.shouldHideMobileInput = NitroxGUILayout.BoolField(inputField.shouldHideMobileInput);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Read Only", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
inputField.readOnly = NitroxGUILayout.BoolField(inputField.readOnly);
|
||||
}
|
||||
|
||||
GUILayout.Space(NitroxGUILayout.DEFAULT_SPACE);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("On Value Changed", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
GUILayout.Button("Unsupported", GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("On End Edit", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
GUILayout.Button("Unsupported", GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
}
|
||||
}
|
||||
}
|
55
NitroxClient/Debuggers/Drawer/UnityUI/LayoutElementDrawer.cs
Normal file
55
NitroxClient/Debuggers/Drawer/UnityUI/LayoutElementDrawer.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.UnityUI;
|
||||
|
||||
public class LayoutElementDrawer : IDrawer<LayoutElement>
|
||||
{
|
||||
private const float LABEL_WIDTH = 100;
|
||||
|
||||
public void Draw(LayoutElement layoutElement)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Ignore Layout", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
layoutElement.ignoreLayout = NitroxGUILayout.BoolField(layoutElement.ignoreLayout);
|
||||
}
|
||||
|
||||
GUILayout.Space(8f);
|
||||
|
||||
layoutElement.minWidth = DrawToggleableFloat("Min Width", layoutElement.minWidth);
|
||||
layoutElement.minHeight = DrawToggleableFloat("Min Height", layoutElement.minHeight);
|
||||
|
||||
layoutElement.preferredWidth = DrawToggleableFloat("Preferred Width", layoutElement.preferredWidth);
|
||||
layoutElement.preferredHeight = DrawToggleableFloat("Preferred Height", layoutElement.preferredHeight);
|
||||
|
||||
layoutElement.flexibleWidth = DrawToggleableFloat("Flexible Width", layoutElement.flexibleWidth);
|
||||
layoutElement.flexibleHeight = DrawToggleableFloat("Flexible Height", layoutElement.flexibleHeight);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Layout Priority", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
layoutElement.layoutPriority = NitroxGUILayout.IntField(layoutElement.layoutPriority);
|
||||
}
|
||||
}
|
||||
|
||||
private static float DrawToggleableFloat(string name, float value)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label(name, NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
|
||||
bool active = value >= 0;
|
||||
if (GUILayout.Button(active ? "X" : " ", GUILayout.Width(25)))
|
||||
{
|
||||
value = active ? -1 : 0;
|
||||
}
|
||||
|
||||
return Math.Max(-1, NitroxGUILayout.FloatField(value));
|
||||
}
|
||||
}
|
||||
}
|
77
NitroxClient/Debuggers/Drawer/UnityUI/LayoutGroupDrawer.cs
Normal file
77
NitroxClient/Debuggers/Drawer/UnityUI/LayoutGroupDrawer.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using System;
|
||||
using NitroxClient.Debuggers.Drawer.Unity;
|
||||
using NitroxModel.Helper;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.UnityUI;
|
||||
|
||||
public class LayoutGroupDrawer : IDrawer<HorizontalLayoutGroup>, IDrawer<VerticalLayoutGroup>
|
||||
{
|
||||
private readonly RectDrawer rectDrawer;
|
||||
|
||||
public LayoutGroupDrawer(RectDrawer rectDrawer)
|
||||
{
|
||||
Validate.NotNull(rectDrawer);
|
||||
|
||||
this.rectDrawer = rectDrawer;
|
||||
}
|
||||
|
||||
public void Draw(HorizontalLayoutGroup target)
|
||||
{
|
||||
DrawLayoutGroup(target);
|
||||
}
|
||||
|
||||
public void Draw(VerticalLayoutGroup target)
|
||||
{
|
||||
DrawLayoutGroup(target);
|
||||
}
|
||||
|
||||
private void DrawLayoutGroup(HorizontalOrVerticalLayoutGroup layoutGroup)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Padding", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
rectDrawer.Draw(layoutGroup.padding);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Spacing", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
layoutGroup.spacing = NitroxGUILayout.FloatField(layoutGroup.spacing);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Child Alignment", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
layoutGroup.childAlignment = NitroxGUILayout.EnumPopup(layoutGroup.childAlignment);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Control Child Size", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
layoutGroup.childControlWidth = NitroxGUILayout.BoolField(layoutGroup.childControlWidth, "Width");
|
||||
layoutGroup.childControlHeight = NitroxGUILayout.BoolField(layoutGroup.childControlHeight, "Height");
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Use Child Scale", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
layoutGroup.childScaleWidth = NitroxGUILayout.BoolField(layoutGroup.childScaleWidth, "Width");
|
||||
layoutGroup.childScaleHeight = NitroxGUILayout.BoolField(layoutGroup.childScaleHeight, "Height");
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Child Force Expand", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
layoutGroup.childForceExpandWidth = NitroxGUILayout.BoolField(layoutGroup.childForceExpandWidth, "Width");
|
||||
layoutGroup.childForceExpandHeight = NitroxGUILayout.BoolField(layoutGroup.childForceExpandHeight, "Height");
|
||||
}
|
||||
}
|
||||
}
|
25
NitroxClient/Debuggers/Drawer/UnityUI/MaskDrawer.cs
Normal file
25
NitroxClient/Debuggers/Drawer/UnityUI/MaskDrawer.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.UnityUI;
|
||||
|
||||
public class MaskDrawer : IDrawer<Mask>, IDrawer<RectMask2D>
|
||||
{
|
||||
public Type[] ApplicableTypes { get; } = { typeof(Mask), typeof(RectMask2D) };
|
||||
|
||||
public void Draw(Mask mask)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Show Mask Graphic", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
mask.showMaskGraphic = NitroxGUILayout.BoolField(mask.showMaskGraphic);
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(RectMask2D target)
|
||||
{
|
||||
// RectMask2D has no fields in the editor.
|
||||
}
|
||||
}
|
207
NitroxClient/Debuggers/Drawer/UnityUI/RectTransformDrawer.cs
Normal file
207
NitroxClient/Debuggers/Drawer/UnityUI/RectTransformDrawer.cs
Normal file
@@ -0,0 +1,207 @@
|
||||
using System;
|
||||
using NitroxClient.Debuggers.Drawer.Unity;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.UnityUI;
|
||||
|
||||
public class RectTransformDrawer : IDrawer<RectTransform>
|
||||
{
|
||||
private readonly VectorDrawer vectorDrawer;
|
||||
private const float LABEL_WIDTH = 120;
|
||||
private const float VECTOR_MAX_WIDTH = 405;
|
||||
|
||||
public RectTransformDrawer(VectorDrawer vectorDrawer)
|
||||
{
|
||||
this.vectorDrawer = vectorDrawer;
|
||||
}
|
||||
|
||||
public void Draw(RectTransform rectTransform)
|
||||
{
|
||||
using (new GUILayout.VerticalScope())
|
||||
{
|
||||
//TODO: Implement position display like the Unity editor
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Anchored Position", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
rectTransform.anchoredPosition = vectorDrawer.Draw(rectTransform.anchoredPosition, new VectorDrawer.DrawOptions(VECTOR_MAX_WIDTH));
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Local Position", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
rectTransform.localPosition = vectorDrawer.Draw(rectTransform.localPosition, new VectorDrawer.DrawOptions(VECTOR_MAX_WIDTH));
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Local Rotation", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
rectTransform.localRotation = Quaternion.Euler(vectorDrawer.Draw(rectTransform.localRotation.eulerAngles, new VectorDrawer.DrawOptions(VECTOR_MAX_WIDTH)));
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Local Scale", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
rectTransform.localScale = vectorDrawer.Draw(rectTransform.localScale, new VectorDrawer.DrawOptions(VECTOR_MAX_WIDTH));
|
||||
}
|
||||
|
||||
GUILayout.Space(20);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Size", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
rectTransform.sizeDelta = vectorDrawer.Draw(rectTransform.sizeDelta, new VectorDrawer.DrawOptions(VECTOR_MAX_WIDTH));
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Anchor", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
AnchorMode anchorMode = VectorToAnchorMode(rectTransform.anchorMin, rectTransform.anchorMax);
|
||||
|
||||
if (anchorMode == AnchorMode.NONE)
|
||||
{
|
||||
vectorDrawer.Draw(rectTransform.anchorMin, new VectorDrawer.DrawOptions(VECTOR_MAX_WIDTH * 0.5f));
|
||||
vectorDrawer.Draw(rectTransform.anchorMax, new VectorDrawer.DrawOptions(VECTOR_MAX_WIDTH * 0.5f));
|
||||
}
|
||||
else
|
||||
{
|
||||
anchorMode = NitroxGUILayout.EnumPopup(anchorMode, VECTOR_MAX_WIDTH);
|
||||
|
||||
// Vector2[] anchorVectors = AnchorModeToVector(anchorMode);
|
||||
// rectTransform.anchorMin = anchorVectors[0];
|
||||
// rectTransform.anchorMax = anchorVectors[1];
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Pivot", NitroxGUILayout.DrawerLabel, GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
rectTransform.pivot = vectorDrawer.Draw(rectTransform.pivot, new VectorDrawer.DrawOptions(VECTOR_MAX_WIDTH));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private enum AnchorMode
|
||||
{
|
||||
TOP_LEFT,
|
||||
TOP_CENTER,
|
||||
TOP_RIGHT,
|
||||
TOP_STRETCH,
|
||||
MIDDLE_LEFT,
|
||||
MIDDLE_CENTER,
|
||||
MIDDLE_RIGHT,
|
||||
MIDDLE_STRETCH,
|
||||
BOTTOM_LEFT,
|
||||
BOTTOM_CENTER,
|
||||
BOTTOM_RIGHT,
|
||||
BOTTOM_STRETCH,
|
||||
STRETCH_LEFT,
|
||||
STRETCH_CENTER,
|
||||
STRETCH_RIGHT,
|
||||
STRETCH_STRETCH,
|
||||
NONE
|
||||
}
|
||||
|
||||
private const float FLOAT_TOLERANCE = 0.0001f;
|
||||
|
||||
#pragma warning disable IDE0011 // ReSharper disable EnforceIfStatementBraces
|
||||
private static AnchorMode VectorToAnchorMode(Vector2 min, Vector2 max)
|
||||
{
|
||||
bool minXNull = min.x == 0f;
|
||||
bool minXHalf = Math.Abs(min.x - 0.5f) < FLOAT_TOLERANCE;
|
||||
bool minXFull = Math.Abs(min.x - 1f) < FLOAT_TOLERANCE;
|
||||
|
||||
bool minYNull = min.y == 0f;
|
||||
bool minYHalf = Math.Abs(min.y - 0.5f) < FLOAT_TOLERANCE;
|
||||
bool minYFull = Math.Abs(min.y - 1f) < FLOAT_TOLERANCE;
|
||||
|
||||
bool maxXNull = max.x == 0f;
|
||||
bool maxXHalf = Math.Abs(max.x - 0.5f) < FLOAT_TOLERANCE;
|
||||
bool maxXFull = Math.Abs(max.x - 1f) < FLOAT_TOLERANCE;
|
||||
|
||||
bool maxYNull = max.y == 0f;
|
||||
bool maxYHalf = Math.Abs(max.y - 0.5f) < FLOAT_TOLERANCE;
|
||||
bool maxYFull = Math.Abs(max.y - 1f) < FLOAT_TOLERANCE;
|
||||
|
||||
if (minYFull && maxYFull)
|
||||
{
|
||||
if (minXNull && maxXNull)
|
||||
return AnchorMode.TOP_LEFT;
|
||||
if (minXHalf && maxXHalf)
|
||||
|
||||
return AnchorMode.TOP_CENTER;
|
||||
if (minXFull && maxXFull)
|
||||
return AnchorMode.TOP_RIGHT;
|
||||
if (minXNull && maxXFull)
|
||||
return AnchorMode.TOP_STRETCH;
|
||||
}
|
||||
|
||||
if (minYHalf && maxYHalf)
|
||||
{
|
||||
if (minXNull && maxXNull)
|
||||
return AnchorMode.MIDDLE_LEFT;
|
||||
if (minXHalf && maxXHalf)
|
||||
return AnchorMode.MIDDLE_CENTER;
|
||||
if (minXFull && maxXFull)
|
||||
return AnchorMode.MIDDLE_RIGHT;
|
||||
if (minXNull && maxXFull)
|
||||
return AnchorMode.MIDDLE_STRETCH;
|
||||
}
|
||||
|
||||
if (minYNull && maxYNull)
|
||||
{
|
||||
if (minXNull && maxXNull)
|
||||
return AnchorMode.BOTTOM_LEFT;
|
||||
if (minXHalf && maxXHalf)
|
||||
return AnchorMode.BOTTOM_CENTER;
|
||||
if (minXFull && maxXFull)
|
||||
return AnchorMode.BOTTOM_RIGHT;
|
||||
if (minXNull && maxXFull)
|
||||
return AnchorMode.BOTTOM_STRETCH;
|
||||
}
|
||||
|
||||
if (minYNull && maxYFull)
|
||||
{
|
||||
if (minXNull && maxXNull)
|
||||
return AnchorMode.STRETCH_LEFT;
|
||||
if (minXHalf && maxXHalf)
|
||||
return AnchorMode.STRETCH_CENTER;
|
||||
if (minXFull && maxXFull)
|
||||
return AnchorMode.STRETCH_RIGHT;
|
||||
if (minXNull && maxXFull)
|
||||
return AnchorMode.STRETCH_STRETCH;
|
||||
}
|
||||
|
||||
return AnchorMode.NONE;
|
||||
}
|
||||
#pragma warning restore IDE0011 // ReSharper restore EnforceIfStatementBraces
|
||||
|
||||
private static Vector2[] AnchorModeToVector(AnchorMode anchorMode) =>
|
||||
anchorMode switch
|
||||
{
|
||||
AnchorMode.TOP_LEFT => [new Vector2(0, 1), new Vector2(0, 1)],
|
||||
AnchorMode.TOP_CENTER => [new Vector2(0.5f, 1), new Vector2(0.5f, 1)],
|
||||
AnchorMode.TOP_RIGHT => [new Vector2(1, 1), new Vector2(1, 1)],
|
||||
AnchorMode.TOP_STRETCH => [new Vector2(0, 1), new Vector2(1, 1)],
|
||||
AnchorMode.MIDDLE_LEFT => [new Vector2(0, 0.5f), new Vector2(0, 0.5f)],
|
||||
AnchorMode.MIDDLE_CENTER => [new Vector2(0.5f, 1), new Vector2(0.5f, 0.5f)],
|
||||
AnchorMode.MIDDLE_RIGHT => [new Vector2(1, 0.5f), new Vector2(1, 0.5f)],
|
||||
AnchorMode.MIDDLE_STRETCH => [new Vector2(0, 0.5f), new Vector2(1, 0.5f)],
|
||||
AnchorMode.BOTTOM_LEFT => [new Vector2(0, 0), new Vector2(0, 0)],
|
||||
AnchorMode.BOTTOM_CENTER => [new Vector2(0.5f, 0), new Vector2(0.5f, 0)],
|
||||
AnchorMode.BOTTOM_RIGHT => [new Vector2(1, 0), new Vector2(1, 0)],
|
||||
AnchorMode.BOTTOM_STRETCH => [new Vector2(0, 0), new Vector2(1, 0)],
|
||||
AnchorMode.STRETCH_LEFT => [new Vector2(0, 0), new Vector2(0, 1)],
|
||||
AnchorMode.STRETCH_CENTER => [new Vector2(0.5f, 0), new Vector2(0.5f, 1)],
|
||||
AnchorMode.STRETCH_RIGHT => [new Vector2(1, 0), new Vector2(1, 1)],
|
||||
AnchorMode.STRETCH_STRETCH => [new Vector2(0, 0), new Vector2(1, 1)],
|
||||
AnchorMode.NONE => throw new ArgumentOutOfRangeException(),
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
}
|
121
NitroxClient/Debuggers/Drawer/UnityUI/ScrollRectDrawer.cs
Normal file
121
NitroxClient/Debuggers/Drawer/UnityUI/ScrollRectDrawer.cs
Normal file
@@ -0,0 +1,121 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.UnityUI;
|
||||
|
||||
public class ScrollRectDrawer : IDrawer<ScrollRect>
|
||||
{
|
||||
private readonly SceneDebugger sceneDebugger;
|
||||
|
||||
public ScrollRectDrawer(SceneDebugger sceneDebugger)
|
||||
{
|
||||
this.sceneDebugger = sceneDebugger;
|
||||
}
|
||||
|
||||
public void Draw(ScrollRect scrollRect)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Content", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
if (GUILayout.Button("Jump to", GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH)))
|
||||
{
|
||||
sceneDebugger.JumpToComponent(scrollRect.content);
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Horizontal", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
scrollRect.horizontal = NitroxGUILayout.BoolField(scrollRect.horizontal);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Vertical", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
scrollRect.vertical = NitroxGUILayout.BoolField(scrollRect.vertical);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("MovementType", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
scrollRect.movementType = NitroxGUILayout.EnumPopup(scrollRect.movementType);
|
||||
}
|
||||
|
||||
if (scrollRect.movementType == ScrollRect.MovementType.Elastic)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Elasticity", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
scrollRect.elasticity = NitroxGUILayout.FloatField(scrollRect.elasticity);
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Inertia", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
scrollRect.inertia = NitroxGUILayout.BoolField(scrollRect.inertia);
|
||||
}
|
||||
|
||||
if (scrollRect.inertia)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Deceleration Rate", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
scrollRect.decelerationRate = NitroxGUILayout.FloatField(scrollRect.decelerationRate);
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Scroll Sensitivity", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
scrollRect.scrollSensitivity = NitroxGUILayout.FloatField(scrollRect.scrollSensitivity);
|
||||
}
|
||||
|
||||
GUILayout.Space(8f);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Viewport", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
if (GUILayout.Button("Jump to", GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH)))
|
||||
{
|
||||
sceneDebugger.JumpToComponent(scrollRect.viewport);
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Horizontal Scrollbar", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
if (GUILayout.Button("Jump to", GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH)))
|
||||
{
|
||||
sceneDebugger.JumpToComponent(scrollRect.horizontalScrollbar);
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Vertical Scrollbar", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
if (GUILayout.Button("Jump to", GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH)))
|
||||
{
|
||||
sceneDebugger.JumpToComponent(scrollRect.verticalScrollbar);
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("On Value Changed", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
GUILayout.Button("Unsupported", GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
}
|
||||
}
|
||||
}
|
68
NitroxClient/Debuggers/Drawer/UnityUI/ScrollbarDrawer.cs
Normal file
68
NitroxClient/Debuggers/Drawer/UnityUI/ScrollbarDrawer.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.UnityUI;
|
||||
|
||||
public class ScrollbarDrawer : IDrawer<Scrollbar>
|
||||
{
|
||||
private readonly SceneDebugger sceneDebugger;
|
||||
private readonly SelectableDrawer selectableDrawer;
|
||||
|
||||
public ScrollbarDrawer(SceneDebugger sceneDebugger, SelectableDrawer selectableDrawer)
|
||||
{
|
||||
this.sceneDebugger = sceneDebugger;
|
||||
this.selectableDrawer = selectableDrawer;
|
||||
}
|
||||
|
||||
public void Draw(Scrollbar scrollbar)
|
||||
{
|
||||
selectableDrawer.Draw(scrollbar);
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Handle Rect", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
if (GUILayout.Button("Jump to", GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH)))
|
||||
{
|
||||
sceneDebugger.JumpToComponent(scrollbar.handleRect);
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Direction", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
scrollbar.direction = NitroxGUILayout.EnumPopup(scrollbar.direction);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Value", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
scrollbar.value = NitroxGUILayout.SliderField(scrollbar.value, 0f, 1f);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Size", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
scrollbar.size = NitroxGUILayout.SliderField(scrollbar.size, 0f, 1f);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Number Of Steps", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
scrollbar.numberOfSteps = NitroxGUILayout.SliderField(scrollbar.numberOfSteps, 0, 11);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("On Value Changed", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
GUILayout.Button("Unsupported", GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
}
|
||||
}
|
||||
}
|
241
NitroxClient/Debuggers/Drawer/UnityUI/SelectableDrawer.cs
Normal file
241
NitroxClient/Debuggers/Drawer/UnityUI/SelectableDrawer.cs
Normal file
@@ -0,0 +1,241 @@
|
||||
using NitroxClient.Debuggers.Drawer.Unity;
|
||||
using NitroxModel.Helper;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.UnityUI;
|
||||
|
||||
public class SelectableDrawer : IDrawer<Selectable>
|
||||
{
|
||||
private readonly SceneDebugger sceneDebugger;
|
||||
private readonly ColorDrawer colorDrawer;
|
||||
|
||||
public SelectableDrawer(SceneDebugger sceneDebugger, ColorDrawer colorDrawer)
|
||||
{
|
||||
Validate.NotNull(sceneDebugger);
|
||||
Validate.NotNull(colorDrawer);
|
||||
|
||||
this.sceneDebugger = sceneDebugger;
|
||||
this.colorDrawer = colorDrawer;
|
||||
}
|
||||
|
||||
public void Draw(Selectable selectable)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Interactable", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
selectable.interactable = NitroxGUILayout.BoolField(selectable.interactable);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Transition", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
selectable.transition = NitroxGUILayout.EnumPopup(selectable.transition);
|
||||
}
|
||||
|
||||
switch (selectable.transition)
|
||||
{
|
||||
case Selectable.Transition.ColorTint:
|
||||
DrawTransitionColorTint(selectable);
|
||||
break;
|
||||
case Selectable.Transition.SpriteSwap:
|
||||
DrawTransitionSpriteSwap(selectable);
|
||||
break;
|
||||
case Selectable.Transition.Animation:
|
||||
DrawTransitionAnimation(selectable);
|
||||
break;
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Navigation", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
NitroxGUILayout.EnumPopup(selectable.navigation.mode);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawTransitionColorTint(Selectable selectable)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Target Graphic", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
if (GUILayout.Button("Jump to", GUILayout.Width(NitroxGUILayout.VALUE_WIDTH)))
|
||||
{
|
||||
sceneDebugger.UpdateSelectedObject(selectable.targetGraphic.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
Color normalColor, highlightedColor, pressedColor, selectedColor, disabledColor;
|
||||
float colorMultiplier, fadeDuration;
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Normal Color", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
normalColor = colorDrawer.Draw(selectable.colors.normalColor);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Highlighted Color", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
highlightedColor = colorDrawer.Draw(selectable.colors.highlightedColor);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Pressed Color", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
pressedColor = colorDrawer.Draw(selectable.colors.pressedColor);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Selected Color", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
selectedColor = colorDrawer.Draw(selectable.colors.selectedColor);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Disabled Color", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
disabledColor = colorDrawer.Draw(selectable.colors.disabledColor);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Color Multiplier", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
colorMultiplier = NitroxGUILayout.SliderField(selectable.colors.colorMultiplier, 1, 5);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Fader Duration", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
fadeDuration = NitroxGUILayout.SliderField(selectable.colors.fadeDuration, 1, 5);
|
||||
}
|
||||
|
||||
selectable.colors = new ColorBlock
|
||||
{
|
||||
normalColor = normalColor,
|
||||
highlightedColor = highlightedColor,
|
||||
pressedColor = pressedColor,
|
||||
selectedColor = selectedColor,
|
||||
disabledColor = disabledColor,
|
||||
colorMultiplier = colorMultiplier,
|
||||
fadeDuration = fadeDuration
|
||||
};
|
||||
}
|
||||
|
||||
private void DrawTransitionSpriteSwap(Selectable selectable)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Target Graphic", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
if (GUILayout.Button("Jump to", GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH)))
|
||||
{
|
||||
sceneDebugger.UpdateSelectedObject(selectable.targetGraphic.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Highlighted Sprite", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
if (selectable.spriteState.highlightedSprite)
|
||||
{
|
||||
ImageDrawer.DrawTexture(selectable.spriteState.highlightedSprite.texture);
|
||||
}
|
||||
else
|
||||
{
|
||||
GUILayout.Box("Field is null", GUILayout.Width(NitroxGUILayout.VALUE_WIDTH));
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Pressed Sprite", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
if (selectable.spriteState.pressedSprite)
|
||||
{
|
||||
ImageDrawer.DrawTexture(selectable.spriteState.pressedSprite.texture);
|
||||
}
|
||||
else
|
||||
{
|
||||
GUILayout.Box("Field is null", GUILayout.Width(NitroxGUILayout.VALUE_WIDTH));
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Selected Sprite", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
if (selectable.spriteState.selectedSprite)
|
||||
{
|
||||
ImageDrawer.DrawTexture(selectable.spriteState.selectedSprite.texture);
|
||||
}
|
||||
else
|
||||
{
|
||||
GUILayout.Box("Field is null", GUILayout.Width(NitroxGUILayout.VALUE_WIDTH));
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Disabled Sprite", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
if (selectable.spriteState.disabledSprite)
|
||||
{
|
||||
ImageDrawer.DrawTexture(selectable.spriteState.disabledSprite.texture);
|
||||
}
|
||||
else
|
||||
{
|
||||
GUILayout.Box("Field is null", GUILayout.Width(NitroxGUILayout.VALUE_WIDTH));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawTransitionAnimation(Selectable selectable)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Normal Trigger", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
selectable.animationTriggers.normalTrigger = GUILayout.TextField(selectable.animationTriggers.normalTrigger);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Highlighted Trigger", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
selectable.animationTriggers.highlightedTrigger = GUILayout.TextField(selectable.animationTriggers.highlightedTrigger);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Pressed Trigger", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
selectable.animationTriggers.pressedTrigger = GUILayout.TextField(selectable.animationTriggers.pressedTrigger);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Selected Trigger", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
selectable.animationTriggers.selectedTrigger = GUILayout.TextField(selectable.animationTriggers.selectedTrigger);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Disabled Trigger", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
selectable.animationTriggers.disabledTrigger = GUILayout.TextField(selectable.animationTriggers.disabledTrigger);
|
||||
}
|
||||
}
|
||||
}
|
100
NitroxClient/Debuggers/Drawer/UnityUI/SliderDrawer.cs
Normal file
100
NitroxClient/Debuggers/Drawer/UnityUI/SliderDrawer.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
using NitroxModel.Helper;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.UnityUI;
|
||||
|
||||
public class SliderDrawer : IDrawer<Slider>
|
||||
{
|
||||
private readonly SceneDebugger sceneDebugger;
|
||||
private readonly SelectableDrawer selectableDrawer;
|
||||
|
||||
public SliderDrawer(SceneDebugger sceneDebugger, SelectableDrawer selectableDrawer)
|
||||
{
|
||||
Validate.NotNull(sceneDebugger);
|
||||
Validate.NotNull(selectableDrawer);
|
||||
|
||||
this.sceneDebugger = sceneDebugger;
|
||||
this.selectableDrawer = selectableDrawer;
|
||||
}
|
||||
|
||||
public void Draw(Slider slider)
|
||||
{
|
||||
selectableDrawer.Draw(slider);
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Fill Rect", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
if (GUILayout.Button("Jump to", GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH)))
|
||||
{
|
||||
sceneDebugger.JumpToComponent(slider.fillRect);
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Handle Rect", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
if (GUILayout.Button("Jump to", GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH)))
|
||||
{
|
||||
sceneDebugger.JumpToComponent(slider.handleRect);
|
||||
}
|
||||
}
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Direction", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
slider.direction = NitroxGUILayout.EnumPopup(slider.direction);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Min Value", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
slider.minValue = NitroxGUILayout.FloatField(slider.minValue);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Max Value", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
slider.maxValue = NitroxGUILayout.FloatField(slider.maxValue);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Whole Numbers", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
slider.wholeNumbers = NitroxGUILayout.BoolField(slider.wholeNumbers);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Value", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
if (slider.wholeNumbers)
|
||||
{
|
||||
slider.value = NitroxGUILayout.SliderField((int)slider.value, (int)slider.minValue, (int)slider.maxValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
slider.value = NitroxGUILayout.SliderField(slider.value, slider.minValue, slider.maxValue);
|
||||
}
|
||||
}
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("On Value Changed", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
GUILayout.Button("Unsupported", GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
}
|
||||
}
|
||||
}
|
125
NitroxClient/Debuggers/Drawer/UnityUI/TextDrawer.cs
Normal file
125
NitroxClient/Debuggers/Drawer/UnityUI/TextDrawer.cs
Normal file
@@ -0,0 +1,125 @@
|
||||
using NitroxClient.Debuggers.Drawer.Unity;
|
||||
using NitroxModel.Helper;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.UnityUI;
|
||||
|
||||
public class TextDrawer : IDrawer<Text>
|
||||
{
|
||||
private readonly ColorDrawer colorDrawer;
|
||||
private readonly MaterialDrawer materialDrawer;
|
||||
private const float LABEL_WIDTH = 150;
|
||||
private const float VALUE_WIDTH = 200;
|
||||
|
||||
public TextDrawer(ColorDrawer colorDrawer, MaterialDrawer materialDrawer)
|
||||
{
|
||||
Validate.NotNull(colorDrawer);
|
||||
Validate.NotNull(materialDrawer);
|
||||
|
||||
this.colorDrawer = colorDrawer;
|
||||
this.materialDrawer = materialDrawer;
|
||||
}
|
||||
|
||||
public void Draw(Text text)
|
||||
{
|
||||
GUILayout.Label("Text");
|
||||
text.text = GUILayout.TextArea(text.text, GUILayout.MaxHeight(100));
|
||||
|
||||
GUILayout.Space(25);
|
||||
GUILayout.Label("Character:", "bold");
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Font", GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
GUILayout.TextField(text.font ? text.font.name : "NoFont", GUILayout.Width(VALUE_WIDTH));
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Font Style", GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
GUILayout.TextField(text.fontStyle.ToString(), GUILayout.Width(VALUE_WIDTH));
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Font Size", GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
text.fontSize = NitroxGUILayout.IntField(text.fontSize, VALUE_WIDTH);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Line Spacing", GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
text.lineSpacing = NitroxGUILayout.FloatField(text.lineSpacing, VALUE_WIDTH);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Rich Text", GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
text.supportRichText = NitroxGUILayout.BoolField(text.supportRichText, VALUE_WIDTH);
|
||||
}
|
||||
|
||||
GUILayout.Space(25);
|
||||
GUILayout.Label("Paragraph:", "bold");
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Alignment", GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
text.alignment = NitroxGUILayout.EnumPopup(text.alignment, VALUE_WIDTH);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Align By Geometry", GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
text.alignByGeometry = NitroxGUILayout.BoolField(text.alignByGeometry, VALUE_WIDTH);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Horizontal Overflow", GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
text.horizontalOverflow = NitroxGUILayout.EnumPopup(text.horizontalOverflow, VALUE_WIDTH);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Vertical Overflow", GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
text.verticalOverflow = NitroxGUILayout.EnumPopup(text.verticalOverflow, VALUE_WIDTH);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Best Fit", GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
text.resizeTextForBestFit = NitroxGUILayout.BoolField(text.resizeTextForBestFit, VALUE_WIDTH);
|
||||
}
|
||||
|
||||
GUILayout.Space(25);
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Color", GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
text.color = colorDrawer.Draw(text.color);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Material", GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
text.material = materialDrawer.Draw(text.material);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Raycast Target", GUILayout.Width(LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
text.raycastTarget = NitroxGUILayout.BoolField(text.raycastTarget, VALUE_WIDTH);
|
||||
}
|
||||
}
|
||||
}
|
66
NitroxClient/Debuggers/Drawer/UnityUI/ToggleDrawer.cs
Normal file
66
NitroxClient/Debuggers/Drawer/UnityUI/ToggleDrawer.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
using NitroxClient.Debuggers.Drawer.Unity;
|
||||
using NitroxModel.Helper;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.UnityUI;
|
||||
|
||||
public class ToggleDrawer : IDrawer<Toggle>
|
||||
{
|
||||
private readonly SceneDebugger sceneDebugger;
|
||||
private readonly SelectableDrawer selectableDrawer;
|
||||
private readonly UnityEventDrawer unityEventDrawer;
|
||||
|
||||
public ToggleDrawer(SceneDebugger sceneDebugger, SelectableDrawer selectableDrawer, UnityEventDrawer unityEventDrawer)
|
||||
{
|
||||
Validate.NotNull(sceneDebugger);
|
||||
Validate.NotNull(selectableDrawer);
|
||||
Validate.NotNull(unityEventDrawer);
|
||||
|
||||
this.sceneDebugger = sceneDebugger;
|
||||
this.selectableDrawer = selectableDrawer;
|
||||
this.unityEventDrawer = unityEventDrawer;
|
||||
}
|
||||
|
||||
public void Draw(Toggle toggle)
|
||||
{
|
||||
selectableDrawer.Draw(toggle);
|
||||
GUILayout.Space(10);
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Is On", GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
toggle.isOn = NitroxGUILayout.BoolField(toggle.isOn);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Toggle Transition", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
toggle.toggleTransition = NitroxGUILayout.EnumPopup(toggle.toggleTransition);
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Graphic", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
if (GUILayout.Button("Jump to", GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH)))
|
||||
{
|
||||
sceneDebugger.UpdateSelectedObject(toggle.graphic.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Group", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
if (GUILayout.Button("Jump to", GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH)))
|
||||
{
|
||||
sceneDebugger.UpdateSelectedObject(toggle.group.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
unityEventDrawer.Draw(toggle.onValueChanged, new UnityEventDrawer.DrawOptions("OnClick()"));
|
||||
}
|
||||
}
|
17
NitroxClient/Debuggers/Drawer/UnityUI/ToggleGroupDrawer.cs
Normal file
17
NitroxClient/Debuggers/Drawer/UnityUI/ToggleGroupDrawer.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace NitroxClient.Debuggers.Drawer.UnityUI;
|
||||
|
||||
public class ToggleGroupDrawer : IDrawer<ToggleGroup>
|
||||
{
|
||||
public void Draw(ToggleGroup toggleGroup)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label("Allow Switch Off", NitroxGUILayout.DrawerLabel, GUILayout.Width(NitroxGUILayout.DEFAULT_LABEL_WIDTH));
|
||||
NitroxGUILayout.Separator();
|
||||
toggleGroup.allowSwitchOff = NitroxGUILayout.BoolField(toggleGroup.allowSwitchOff);
|
||||
}
|
||||
}
|
||||
}
|
120
NitroxClient/Debuggers/EntityDebugger.cs
Normal file
120
NitroxClient/Debuggers/EntityDebugger.cs
Normal file
@@ -0,0 +1,120 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using NitroxClient.MonoBehaviours;
|
||||
using NitroxModel.DataStructures;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NitroxClient.Debuggers
|
||||
{
|
||||
[ExcludeFromCodeCoverage]
|
||||
public class EntityDebugger : BaseDebugger
|
||||
{
|
||||
private static Color labelBgColor = new Color(0.2f, 0.2f, 0.2f, 0.5f);
|
||||
private static Color labelFgColor = Color.white;
|
||||
private static float textXOffset = 20f;
|
||||
private static Texture2D lineTex;
|
||||
|
||||
private static List<Rect> rects;
|
||||
|
||||
public EntityDebugger() : base(200, null, KeyCode.E, true, false, false, GUISkinCreationOptions.DERIVEDCOPY)
|
||||
{
|
||||
ActiveTab = AddTab("EntityDebugger", RenderEntityDebugger);
|
||||
rects = new List<Rect>();
|
||||
}
|
||||
|
||||
private void RenderEntityDebugger()
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnGUI()
|
||||
{
|
||||
if (!Enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rects.Clear();
|
||||
foreach (KeyValuePair<NitroxId, GameObject> gameObjectPairs in NitroxEntity.GetGameObjects())
|
||||
{
|
||||
NitroxId id = gameObjectPairs.Key;
|
||||
GameObject gameObject = gameObjectPairs.Value;
|
||||
if (gameObject == null || gameObject == Player.mainObject)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Vector3 screenPos = Player.main.viewModelCamera.WorldToScreenPoint(gameObject.transform.position);
|
||||
if (screenPos.z > 0 && screenPos.z < 20 &&
|
||||
screenPos.x >= 0 && screenPos.x < Screen.width &&
|
||||
screenPos.y >= 0 && screenPos.y < Screen.height)
|
||||
{
|
||||
GUIStyle style = GUI.skin.label;
|
||||
GUIContent textContent = new($"ID {id} NAME {gameObject.name}");
|
||||
Vector2 size = style.CalcSize(textContent);
|
||||
size += new Vector2(10f, 0f); //for box edges
|
||||
|
||||
Vector2 pointLocation = new Vector2(screenPos.x, Screen.height - screenPos.y);
|
||||
Rect drawSize = new Rect(screenPos.x + textXOffset, Screen.height - screenPos.y, size.x, size.y);
|
||||
while (true)
|
||||
{
|
||||
bool finished = true;
|
||||
foreach (Rect rect in rects)
|
||||
{
|
||||
if (rect.Overlaps(drawSize))
|
||||
{
|
||||
drawSize.x = rect.x;
|
||||
drawSize.y = rect.y + rect.height;
|
||||
finished = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (finished)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DrawLine(pointLocation, new Vector2(drawSize.x, drawSize.y + size.y / 2), labelFgColor, 2f);
|
||||
|
||||
rects.Add(drawSize);
|
||||
|
||||
Color oldBgColor = GUI.backgroundColor;
|
||||
GUI.backgroundColor = labelBgColor;
|
||||
GUI.color = labelFgColor;
|
||||
GUI.Box(drawSize, textContent);
|
||||
|
||||
GUI.backgroundColor = oldBgColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawLine(Vector2 pointA, Vector2 pointB, Color color, float width)
|
||||
{
|
||||
Matrix4x4 matrix = GUI.matrix;
|
||||
|
||||
if (!lineTex)
|
||||
{
|
||||
lineTex = new Texture2D(1, 1);
|
||||
}
|
||||
|
||||
Color savedColor = GUI.color;
|
||||
GUI.color = color;
|
||||
|
||||
float angle = Vector3.Angle(pointB - pointA, Vector2.right);
|
||||
|
||||
if (pointA.y > pointB.y)
|
||||
{
|
||||
angle = -angle;
|
||||
}
|
||||
|
||||
GUIUtility.ScaleAroundPivot(new Vector2((pointB - pointA).magnitude, width), new Vector2(pointA.x, pointA.y + 0.5f));
|
||||
|
||||
GUIUtility.RotateAroundPivot(angle, pointA);
|
||||
|
||||
GUI.DrawTexture(new Rect(pointA.x, pointA.y, 1, 1), lineTex);
|
||||
|
||||
GUI.matrix = matrix;
|
||||
GUI.color = savedColor;
|
||||
}
|
||||
}
|
||||
}
|
259
NitroxClient/Debuggers/NetworkDebugger.cs
Normal file
259
NitroxClient/Debuggers/NetworkDebugger.cs
Normal file
@@ -0,0 +1,259 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using NitroxClient.Unity.Helper;
|
||||
using NitroxModel;
|
||||
using NitroxModel.Packets;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NitroxClient.Debuggers
|
||||
{
|
||||
[ExcludeFromCodeCoverage]
|
||||
public class NetworkDebugger : BaseDebugger, INetworkDebugger
|
||||
{
|
||||
private const int PACKET_STORED_COUNT = 100;
|
||||
private readonly Dictionary<Type, int> countByType = new Dictionary<Type, int>();
|
||||
|
||||
private readonly List<string> filter = new()
|
||||
{
|
||||
nameof(PlayerMovement), nameof(EntityTransformUpdates), nameof(PlayerStats), nameof(SpawnEntities), nameof(VehicleMovements), nameof(PlayerCinematicControllerCall),
|
||||
nameof(FMODAssetPacket), nameof(FMODEventInstancePacket), nameof(FMODCustomEmitterPacket), nameof(FMODStudioEmitterPacket), nameof(FMODCustomLoopingEmitterPacket),
|
||||
nameof(SimulationOwnershipChange), nameof(CellVisibilityChanged), nameof(PlayerInCyclopsMovement), nameof(CreatureActionChanged), nameof(FootstepPacket)
|
||||
};
|
||||
private readonly List<PacketDebugWrapper> packets = new List<PacketDebugWrapper>(PACKET_STORED_COUNT);
|
||||
|
||||
// vs blacklist
|
||||
private bool isWhitelist;
|
||||
private Vector2 scrollPosition;
|
||||
|
||||
private int receivedCount;
|
||||
private int sentCount;
|
||||
|
||||
private uint receivedBytes;
|
||||
private uint sentBytes;
|
||||
|
||||
public NetworkDebugger() : base(600, null, KeyCode.N, true, false, false, GUISkinCreationOptions.DERIVEDCOPY, 330)
|
||||
{
|
||||
ActiveTab = AddTab("All", RenderTabPackets);
|
||||
AddTab("Sent", RenderTabSentPackets);
|
||||
AddTab("Received", RenderTabReceivedPackets);
|
||||
AddTab("Type Count", RenderTabTypeCount);
|
||||
AddTab("Filter", RenderTabFilter);
|
||||
}
|
||||
|
||||
public void PacketSent(Packet packet, int byteSize)
|
||||
{
|
||||
AddPacket(packet, true);
|
||||
sentCount++;
|
||||
sentBytes += (uint)byteSize;
|
||||
}
|
||||
|
||||
public void PacketReceived(Packet packet, int byteSize)
|
||||
{
|
||||
AddPacket(packet, false);
|
||||
receivedCount++;
|
||||
receivedBytes += (uint)byteSize;
|
||||
}
|
||||
|
||||
protected override void OnSetSkin(GUISkin skin)
|
||||
{
|
||||
base.OnSetSkin(skin);
|
||||
|
||||
skin.SetCustomStyle("packet-type-down",
|
||||
skin.label,
|
||||
s =>
|
||||
{
|
||||
s.normal = new GUIStyleState { textColor = Color.green };
|
||||
s.fontStyle = FontStyle.Bold;
|
||||
s.alignment = TextAnchor.MiddleLeft;
|
||||
});
|
||||
|
||||
skin.SetCustomStyle("packet-type-up",
|
||||
skin.label,
|
||||
s =>
|
||||
{
|
||||
s.normal = new GUIStyleState { textColor = Color.red };
|
||||
s.fontStyle = FontStyle.Bold;
|
||||
s.alignment = TextAnchor.MiddleLeft;
|
||||
});
|
||||
}
|
||||
|
||||
private void RenderTabPackets()
|
||||
{
|
||||
using (new GUILayout.VerticalScope("Box"))
|
||||
{
|
||||
RenderPacketTotals();
|
||||
|
||||
scrollPosition = GUILayout.BeginScrollView(scrollPosition, GUILayout.Height(300));
|
||||
RenderPacketList(ToRender.BOTH);
|
||||
GUILayout.EndScrollView();
|
||||
}
|
||||
}
|
||||
|
||||
private void RenderTabSentPackets()
|
||||
{
|
||||
using (new GUILayout.VerticalScope("Box"))
|
||||
{
|
||||
RenderPacketTotals();
|
||||
|
||||
scrollPosition = GUILayout.BeginScrollView(scrollPosition, GUILayout.Height(300));
|
||||
RenderPacketList(ToRender.SENT);
|
||||
GUILayout.EndScrollView();
|
||||
}
|
||||
}
|
||||
|
||||
private void RenderTabReceivedPackets()
|
||||
{
|
||||
using (new GUILayout.VerticalScope("Box"))
|
||||
{
|
||||
RenderPacketTotals();
|
||||
|
||||
scrollPosition = GUILayout.BeginScrollView(scrollPosition, GUILayout.Height(300));
|
||||
RenderPacketList(ToRender.RECEIVED);
|
||||
GUILayout.EndScrollView();
|
||||
}
|
||||
}
|
||||
|
||||
private void RenderTabTypeCount()
|
||||
{
|
||||
using (new GUILayout.VerticalScope("Box"))
|
||||
{
|
||||
RenderPacketTotals();
|
||||
|
||||
scrollPosition = GUILayout.BeginScrollView(scrollPosition, GUILayout.Height(300));
|
||||
foreach (KeyValuePair<Type, int> kv in countByType.OrderBy(e => -e.Value)) // descending
|
||||
{
|
||||
GUILayout.Label($"{kv.Key.Name}: {kv.Value}");
|
||||
}
|
||||
GUILayout.EndScrollView();
|
||||
}
|
||||
}
|
||||
|
||||
private void RenderTabFilter()
|
||||
{
|
||||
using (new GUILayout.VerticalScope("Box"))
|
||||
{
|
||||
RenderPacketTotals();
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
isWhitelist = GUILayout.Toggle(isWhitelist, "Is Whitelist");
|
||||
if (GUILayout.Button("Clear"))
|
||||
{
|
||||
filter.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
scrollPosition = GUILayout.BeginScrollView(scrollPosition, GUILayout.Height(300));
|
||||
for (int i = 0; i < filter.Count; i++)
|
||||
{
|
||||
filter[i] = GUILayout.TextField(filter[i]);
|
||||
}
|
||||
string n = GUILayout.TextField("");
|
||||
if (n != "")
|
||||
{
|
||||
filter.Add(n);
|
||||
}
|
||||
GUILayout.EndScrollView();
|
||||
}
|
||||
}
|
||||
|
||||
private void RenderPacketTotals()
|
||||
{
|
||||
GUILayout.Label($"Sent: {sentCount} ({sentBytes.AsByteUnitText()}) - Received: {receivedCount} ({receivedBytes.AsByteUnitText()})");
|
||||
}
|
||||
|
||||
private void RenderPacketList(ToRender toRender)
|
||||
{
|
||||
bool isSentList = toRender.HasFlag(ToRender.SENT);
|
||||
bool isReceiveList = toRender.HasFlag(ToRender.RECEIVED);
|
||||
PacketPrefixer prefixer = isSentList && isReceiveList ? (PacketPrefixer)PacketDirectionPrefixer : PacketNoopPrefixer;
|
||||
|
||||
for (int i = packets.Count - 1; i >= 0; i--)
|
||||
{
|
||||
PacketDebugWrapper wrapper = packets[i];
|
||||
if (wrapper.IsSent && !isSentList)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!wrapper.IsSent && !isReceiveList)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
using (new GUILayout.VerticalScope("Box"))
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
wrapper.ShowDetails = GUILayout.Toggle(wrapper.ShowDetails, "", GUILayout.Width(20), GUILayout.Height(20));
|
||||
GUILayout.Label($"{prefixer(wrapper)}{wrapper.Packet.GetType().FullName}", wrapper.IsSent ? "packet-type-up" : "packet-type-down");
|
||||
|
||||
packets[i] = wrapper; // Store again because value-type
|
||||
}
|
||||
|
||||
if (wrapper.ShowDetails)
|
||||
{
|
||||
GUILayout.Label(wrapper.Packet.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AddPacket(Packet packet, bool isSent)
|
||||
{
|
||||
Type packetType = packet.GetType();
|
||||
if (isWhitelist == filter.Contains(packetType.Name, StringComparer.InvariantCultureIgnoreCase))
|
||||
{
|
||||
packets.Add(new PacketDebugWrapper(packet, isSent, false));
|
||||
if (packets.Count > PACKET_STORED_COUNT)
|
||||
{
|
||||
packets.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (countByType.TryGetValue(packetType, out int count))
|
||||
{
|
||||
countByType[packetType] = count + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
countByType.Add(packetType, 1);
|
||||
}
|
||||
}
|
||||
|
||||
private string PacketDirectionPrefixer(PacketDebugWrapper wrapper) => $"{(wrapper.IsSent ? "↑" : "↓")} - ";
|
||||
|
||||
private string PacketNoopPrefixer(PacketDebugWrapper wraper) => "";
|
||||
|
||||
private delegate string PacketPrefixer(PacketDebugWrapper wrapper);
|
||||
|
||||
private struct PacketDebugWrapper
|
||||
{
|
||||
public readonly Packet Packet;
|
||||
public readonly bool IsSent;
|
||||
|
||||
public bool ShowDetails { get; set; }
|
||||
|
||||
public PacketDebugWrapper(Packet packet, bool isSent, bool showDetails)
|
||||
{
|
||||
IsSent = isSent;
|
||||
Packet = packet;
|
||||
ShowDetails = showDetails;
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
private enum ToRender
|
||||
{
|
||||
SENT = 1,
|
||||
RECEIVED = 2,
|
||||
BOTH = SENT | RECEIVED
|
||||
}
|
||||
}
|
||||
|
||||
public interface INetworkDebugger
|
||||
{
|
||||
void PacketSent(Packet packet, int size);
|
||||
void PacketReceived(Packet packet, int size);
|
||||
}
|
||||
}
|
483
NitroxClient/Debuggers/SceneDebugger.cs
Normal file
483
NitroxClient/Debuggers/SceneDebugger.cs
Normal file
@@ -0,0 +1,483 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using NitroxClient.Debuggers.Drawer;
|
||||
using NitroxClient.MonoBehaviours;
|
||||
using NitroxClient.Unity.Helper;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace NitroxClient.Debuggers;
|
||||
|
||||
[ExcludeFromCodeCoverage]
|
||||
public class SceneDebugger : BaseDebugger
|
||||
{
|
||||
private readonly DrawerManager drawerManager;
|
||||
public GameObject SelectedObject { get; private set; }
|
||||
private int selectedComponentID;
|
||||
private Scene selectedScene;
|
||||
|
||||
private bool showUnityMethods;
|
||||
private bool showSystemMethods;
|
||||
|
||||
private Vector2 gameObjectScrollPos;
|
||||
private Vector2 hierarchyScrollPos;
|
||||
|
||||
private readonly Dictionary<int, bool> componentsVisibilityByID = new();
|
||||
private readonly Dictionary<int, FieldInfo[]> cachedFieldsByComponentID = new();
|
||||
private readonly Dictionary<int, MethodInfo[]> cachedMethodsByComponentID = new();
|
||||
private readonly Dictionary<int, IDictionary<Type, bool>> enumVisibilityByComponentIDAndEnumType = new();
|
||||
|
||||
public SceneDebugger() : base(650, null, KeyCode.S, true, false, false, GUISkinCreationOptions.DERIVEDCOPY)
|
||||
{
|
||||
drawerManager = new DrawerManager(this);
|
||||
ActiveTab = AddTab("Scenes", RenderTabScenes);
|
||||
AddTab("Hierarchy", RenderTabHierarchy);
|
||||
AddTab("GameObject", RenderTabGameObject);
|
||||
}
|
||||
|
||||
protected override void OnSetSkin(GUISkin skin)
|
||||
{
|
||||
base.OnSetSkin(skin);
|
||||
|
||||
skin.SetCustomStyle("sceneLoaded", skin.label, s =>
|
||||
{
|
||||
s.normal = new GUIStyleState { textColor = Color.green };
|
||||
s.fontStyle = FontStyle.Bold;
|
||||
});
|
||||
|
||||
skin.SetCustomStyle("loadScene", skin.button, s => { s.fixedWidth = 60; });
|
||||
|
||||
skin.SetCustomStyle("fillMessage", skin.label, s =>
|
||||
{
|
||||
s.stretchWidth = true;
|
||||
s.stretchHeight = true;
|
||||
s.fontSize = 24;
|
||||
s.alignment = TextAnchor.MiddleCenter;
|
||||
s.fontStyle = FontStyle.Italic;
|
||||
});
|
||||
|
||||
skin.SetCustomStyle("breadcrumb", skin.label, s =>
|
||||
{
|
||||
s.fontSize = 20;
|
||||
s.fontStyle = FontStyle.Bold;
|
||||
});
|
||||
|
||||
skin.SetCustomStyle("breadcrumbNav", skin.box, s =>
|
||||
{
|
||||
s.stretchWidth = false;
|
||||
s.fixedWidth = 100;
|
||||
});
|
||||
|
||||
skin.SetCustomStyle("options", skin.textField, s =>
|
||||
{
|
||||
s.fixedWidth = 200;
|
||||
s.margin = new RectOffset(8, 8, 4, 4);
|
||||
});
|
||||
|
||||
skin.SetCustomStyle("options_label", skin.label, s => { s.alignment = TextAnchor.MiddleLeft; });
|
||||
|
||||
skin.SetCustomStyle("bold", skin.label, s =>
|
||||
{
|
||||
s.alignment = TextAnchor.LowerLeft;
|
||||
s.fontStyle = FontStyle.Bold;
|
||||
});
|
||||
|
||||
skin.SetCustomStyle("boxHighlighted", skin.box, s =>
|
||||
{
|
||||
Texture2D result = new(1, 1);
|
||||
result.SetPixels(new[] { new Color(1f, 0.9f, 0f, 0.25f) });
|
||||
result.Apply();
|
||||
s.normal.background = result;
|
||||
});
|
||||
}
|
||||
|
||||
private void RenderTabScenes()
|
||||
{
|
||||
using (new GUILayout.VerticalScope("box"))
|
||||
{
|
||||
GUILayout.Label("All scenes", "header");
|
||||
int maxSceneCount = Math.Max(SceneManager.sceneCount, SceneManager.sceneCountInBuildSettings);
|
||||
for (int i = 0; i < maxSceneCount + 1; i++)
|
||||
{
|
||||
// Getting the DontDestroyOnLoad though the NitroxBootstrapper instance
|
||||
Scene currentScene = i == maxSceneCount ? NitroxBootstrapper.Instance.gameObject.scene : SceneManager.GetSceneAt(i);
|
||||
|
||||
bool isSelected = selectedScene.IsValid() && currentScene == selectedScene;
|
||||
bool isLoaded = currentScene.isLoaded;
|
||||
bool isDDOLScene = currentScene.name == "DontDestroyOnLoad";
|
||||
|
||||
using (new GUILayout.HorizontalScope("box"))
|
||||
{
|
||||
if (GUILayout.Button($"{(isSelected ? ">> " : "")}{i}: {(isDDOLScene ? currentScene.name : currentScene.path.TruncateLeft(35))}", isLoaded ? "sceneLoaded" : "label"))
|
||||
{
|
||||
selectedScene = currentScene;
|
||||
ActiveTab = GetTab("Hierarchy").Value;
|
||||
}
|
||||
|
||||
if (isLoaded)
|
||||
{
|
||||
if (!isDDOLScene && GUILayout.Button("Unload", "loadScene"))
|
||||
{
|
||||
SceneManager.UnloadSceneAsync(i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!isDDOLScene && GUILayout.Button("Load", "loadScene"))
|
||||
{
|
||||
SceneManager.LoadSceneAsync(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RenderTabHierarchy()
|
||||
{
|
||||
using (new GUILayout.HorizontalScope("box"))
|
||||
{
|
||||
StringBuilder breadcrumbBuilder = new();
|
||||
if (SelectedObject)
|
||||
{
|
||||
Transform parent = SelectedObject.transform;
|
||||
while (parent)
|
||||
{
|
||||
breadcrumbBuilder.Insert(0, '/');
|
||||
breadcrumbBuilder.Insert(0, string.IsNullOrEmpty(parent.name) ? "<no-name>" : parent.name);
|
||||
parent = parent.parent;
|
||||
}
|
||||
}
|
||||
|
||||
breadcrumbBuilder.Insert(0, "//");
|
||||
GUILayout.Label(breadcrumbBuilder.ToString(), "breadcrumb");
|
||||
|
||||
using (new GUILayout.HorizontalScope("breadcrumbNav"))
|
||||
{
|
||||
if (GUILayout.Button("<<"))
|
||||
{
|
||||
UpdateSelectedObject(null);
|
||||
}
|
||||
|
||||
if (GUILayout.Button("<") && SelectedObject && SelectedObject.transform.parent)
|
||||
{
|
||||
UpdateSelectedObject(SelectedObject.transform.parent.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.VerticalScope("box"))
|
||||
{
|
||||
if (selectedScene.IsValid())
|
||||
{
|
||||
using GUILayout.ScrollViewScope scroll = new(hierarchyScrollPos);
|
||||
hierarchyScrollPos = scroll.scrollPosition;
|
||||
List<GameObject> showObjects = new();
|
||||
if (!SelectedObject)
|
||||
{
|
||||
showObjects = selectedScene.GetRootGameObjects().ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (Transform t in SelectedObject.transform)
|
||||
{
|
||||
showObjects.Add(t.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (GameObject child in showObjects)
|
||||
{
|
||||
if (GUILayout.Button(child.name, child.transform.childCount > 0 ? "bold" : "label"))
|
||||
{
|
||||
UpdateSelectedObject(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GUILayout.Label($"No selected scene\nClick on a Scene in '{GetTab("Hierarchy").Value.Name}'", "fillMessage");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RenderTabGameObject()
|
||||
{
|
||||
using (new GUILayout.VerticalScope("box"))
|
||||
{
|
||||
if (!SelectedObject)
|
||||
{
|
||||
GUILayout.Label($"No selected GameObject\nClick on an object in '{GetTab("Hierarchy").Value.Name}'", "fillMessage");
|
||||
return;
|
||||
}
|
||||
|
||||
using GUILayout.ScrollViewScope scroll = new(gameObjectScrollPos);
|
||||
gameObjectScrollPos = scroll.scrollPosition;
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label($"GameObject: {SelectedObject.name}", "bold", GUILayout.Height(25));
|
||||
GUILayout.Space(5);
|
||||
}
|
||||
|
||||
foreach (Component component in SelectedObject.GetComponents<Component>())
|
||||
{
|
||||
int componentId = component.GetInstanceID();
|
||||
|
||||
using (new GUILayout.VerticalScope(selectedComponentID == componentId ? "boxHighlighted" : "box"))
|
||||
{
|
||||
if (!componentsVisibilityByID.TryGetValue(componentId, out bool visible))
|
||||
{
|
||||
visible = componentsVisibilityByID[componentId] = component is Transform or RectTransform; // Transform should be visible by default
|
||||
}
|
||||
|
||||
Type componentType = component.GetType();
|
||||
MonoBehaviour monoBehaviour = component as MonoBehaviour;
|
||||
|
||||
using (new GUILayout.HorizontalScope(GUILayout.Height(12f)))
|
||||
{
|
||||
if (monoBehaviour)
|
||||
{
|
||||
monoBehaviour.enabled = GUILayout.Toggle(monoBehaviour.enabled, GUIContent.none, GUILayout.Width(15));
|
||||
}
|
||||
|
||||
GUILayout.Label(componentType.Name, "bold", GUILayout.Height(20));
|
||||
NitroxGUILayout.Separator();
|
||||
|
||||
if (GUILayout.Button("Show / Hide", GUILayout.Width(100)))
|
||||
{
|
||||
componentsVisibilityByID[component.GetInstanceID()] = visible = !visible;
|
||||
}
|
||||
}
|
||||
|
||||
GUILayout.Space(5);
|
||||
|
||||
if (visible)
|
||||
{
|
||||
GUILayout.Space(10);
|
||||
if (!drawerManager.TryDraw(component))
|
||||
{
|
||||
if (monoBehaviour)
|
||||
{
|
||||
DrawFields(monoBehaviour);
|
||||
GUILayout.Space(20);
|
||||
DrawMonoBehaviourMethods(monoBehaviour);
|
||||
}
|
||||
else
|
||||
{
|
||||
NitroxGUILayout.Separator();
|
||||
GUILayout.Label("This component is not yet supported");
|
||||
GUILayout.Space(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GUILayout.Space(3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawFields(UnityEngine.Object target)
|
||||
{
|
||||
if (!cachedFieldsByComponentID.TryGetValue(target.GetInstanceID(), out FieldInfo[] fields))
|
||||
{
|
||||
fields = cachedFieldsByComponentID[target.GetInstanceID()] = target.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
}
|
||||
|
||||
foreach (FieldInfo field in fields)
|
||||
{
|
||||
object fieldValue = field.GetValue(target);
|
||||
|
||||
using (new GUILayout.HorizontalScope("box", GUILayout.MinHeight(35)))
|
||||
{
|
||||
GUILayout.Label($"[{field.FieldType.ToString().Split('.').Last()}]: {field.Name}", "options_label");
|
||||
NitroxGUILayout.Separator();
|
||||
|
||||
if (fieldValue is Component component)
|
||||
{
|
||||
if (GUILayout.Button("Goto"))
|
||||
{
|
||||
JumpToComponent(component);
|
||||
}
|
||||
}
|
||||
else if (fieldValue != null && (field.FieldType.IsArray || typeof(IList).IsAssignableFrom(field.FieldType)))
|
||||
{
|
||||
IList list = (IList)field.GetValue(target);
|
||||
GUILayout.Box($"Length: {list.Count}", GUILayout.Width(NitroxGUILayout.VALUE_WIDTH));
|
||||
}
|
||||
else if (fieldValue != null && (typeof(IDictionary).IsAssignableFrom(field.FieldType)))
|
||||
{
|
||||
IDictionary dict = (IDictionary)field.GetValue(target);
|
||||
GUILayout.Box($"Length: {dict.Count}", GUILayout.Width(NitroxGUILayout.VALUE_WIDTH));
|
||||
}
|
||||
else if (drawerManager.TryDrawEditor(fieldValue, out object editedValue))
|
||||
{
|
||||
field.SetValue(target, editedValue);
|
||||
}
|
||||
else if (!drawerManager.TryDraw(fieldValue))
|
||||
{
|
||||
GUILayout.FlexibleSpace();
|
||||
|
||||
switch (fieldValue)
|
||||
{
|
||||
case null:
|
||||
GUILayout.Box("Field is null", GUILayout.Width(NitroxGUILayout.VALUE_WIDTH));
|
||||
break;
|
||||
case ScriptableObject scriptableObject:
|
||||
if (GUILayout.Button(field.Name, GUILayout.Width(NitroxGUILayout.VALUE_WIDTH)))
|
||||
{
|
||||
DrawFields(scriptableObject);
|
||||
}
|
||||
|
||||
break;
|
||||
case GameObject gameObject:
|
||||
if (GUILayout.Button(field.Name, GUILayout.Width(NitroxGUILayout.VALUE_WIDTH)))
|
||||
{
|
||||
UpdateSelectedObject(gameObject);
|
||||
}
|
||||
|
||||
break;
|
||||
case bool boolValue:
|
||||
if (GUILayout.Button(boolValue.ToString(), GUILayout.Width(NitroxGUILayout.VALUE_WIDTH)))
|
||||
{
|
||||
field.SetValue(target, !boolValue);
|
||||
}
|
||||
|
||||
break;
|
||||
case short:
|
||||
case ushort:
|
||||
case int:
|
||||
case uint:
|
||||
case long:
|
||||
case ulong:
|
||||
case float:
|
||||
case double:
|
||||
field.SetValue(target, NitroxGUILayout.ConvertibleField((IConvertible)fieldValue));
|
||||
break;
|
||||
case Enum enumValue:
|
||||
DrawEnum(target, field, enumValue);
|
||||
break;
|
||||
default:
|
||||
GUILayout.TextArea(fieldValue.ToString(), "options", GUILayout.Width(NitroxGUILayout.VALUE_WIDTH));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws an enum field on a component.
|
||||
/// </summary>
|
||||
/// <param name="target">The target containing the field.</param>
|
||||
/// <param name="field">The enum field</param>
|
||||
/// <param name="enumValue">The selected enum value.</param>
|
||||
private void DrawEnum(UnityEngine.Object target, FieldInfo field, Enum enumValue)
|
||||
{
|
||||
// This is the first time enountering this target type
|
||||
if (!enumVisibilityByComponentIDAndEnumType.TryGetValue(target.GetInstanceID(), out IDictionary<Type, bool> enumVisibilityByType))
|
||||
{
|
||||
// Add an empty subdictionary, it will be handled by the statement below.
|
||||
enumVisibilityByType = new Dictionary<Type, bool>();
|
||||
enumVisibilityByComponentIDAndEnumType.Add(target.GetInstanceID(), enumVisibilityByType);
|
||||
}
|
||||
|
||||
// This is the first time we are encountering this enum type on this component
|
||||
if (!enumVisibilityByType.TryGetValue(field.FieldType, out _))
|
||||
{
|
||||
enumVisibilityByType.Add(field.FieldType, false);
|
||||
}
|
||||
|
||||
using (new GUILayout.VerticalScope())
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.FlexibleSpace();
|
||||
|
||||
// Toggle the visibility and save it in the subdictionary
|
||||
if (GUILayout.Button("Show / Hide", GUILayout.Width(NitroxGUILayout.VALUE_WIDTH)))
|
||||
{
|
||||
enumVisibilityByType[field.FieldType] = !enumVisibilityByType[field.FieldType];
|
||||
}
|
||||
}
|
||||
|
||||
// Show the enum list.
|
||||
if (enumVisibilityByType[field.FieldType])
|
||||
{
|
||||
GUILayout.Space(5);
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.FlexibleSpace();
|
||||
field.SetValue(target, NitroxGUILayout.EnumPopup(enumValue, 250));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawMonoBehaviourMethods(MonoBehaviour monoBehaviour)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope("box"))
|
||||
{
|
||||
showSystemMethods = GUILayout.Toggle(showSystemMethods, "Show System inherit methods", GUILayout.Height(25));
|
||||
showUnityMethods = GUILayout.Toggle(showUnityMethods, "Show Unity inherit methods", GUILayout.Height(25));
|
||||
}
|
||||
|
||||
if (!cachedMethodsByComponentID.TryGetValue(monoBehaviour.GetInstanceID(), out MethodInfo[] methods))
|
||||
{
|
||||
methods = cachedMethodsByComponentID[monoBehaviour.GetInstanceID()] = monoBehaviour.GetType().GetMethods(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy)
|
||||
.OrderBy(m => m.Name).ToArray();
|
||||
}
|
||||
|
||||
foreach (MethodInfo method in methods)
|
||||
{
|
||||
string methodAssemblyName = method.DeclaringType != null ? method.DeclaringType.Assembly.GetName().Name : string.Empty;
|
||||
if (!(!showSystemMethods && (methodAssemblyName.Contains("System") || methodAssemblyName.Contains("mscorlib"))) &&
|
||||
!(!showUnityMethods && methodAssemblyName.Contains("UnityEngine")))
|
||||
{
|
||||
using (new GUILayout.VerticalScope("box"))
|
||||
{
|
||||
GUILayout.Label(method.ToString());
|
||||
|
||||
if (method.GetParameters().Any()) // TODO: Allow methods with parameters to be called.
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Invoke", GUILayout.MaxWidth(150)))
|
||||
{
|
||||
object result = method.Invoke(method.IsStatic ? null : monoBehaviour, Array.Empty<object>());
|
||||
Log.InGame($"Invoked method {method.Name}");
|
||||
|
||||
if (method.ReturnType != typeof(void))
|
||||
{
|
||||
Log.InGame(result != null ? $"Returned: '{result}'" : "Return value was NULL.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateSelectedObject(GameObject item)
|
||||
{
|
||||
if (SelectedObject == item)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SelectedObject = item;
|
||||
selectedComponentID = default;
|
||||
}
|
||||
|
||||
public void JumpToComponent(Component item)
|
||||
{
|
||||
UpdateSelectedObject(item.gameObject);
|
||||
RenderTabGameObject();
|
||||
selectedComponentID = item.GetInstanceID();
|
||||
}
|
||||
}
|
446
NitroxClient/Debuggers/SceneExtraDebugger.cs
Normal file
446
NitroxClient/Debuggers/SceneExtraDebugger.cs
Normal file
@@ -0,0 +1,446 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using NitroxClient.MonoBehaviours;
|
||||
using NitroxClient.Unity.Helper;
|
||||
using NitroxModel.DataStructures;
|
||||
using NitroxModel.Helper;
|
||||
using UnityEngine;
|
||||
using Mathf = UnityEngine.Mathf;
|
||||
|
||||
namespace NitroxClient.Debuggers;
|
||||
|
||||
[ExcludeFromCodeCoverage]
|
||||
public sealed class SceneExtraDebugger : BaseDebugger
|
||||
{
|
||||
private readonly SceneDebugger sceneDebugger;
|
||||
private readonly IMap map;
|
||||
|
||||
private const KeyCode RAY_CAST_KEY = KeyCode.F9;
|
||||
|
||||
private bool worldMarkerEnabled = true;
|
||||
private bool rayCastingEnabled;
|
||||
|
||||
private string gameObjectSearch = string.Empty;
|
||||
private string gameObjectSearchCache = string.Empty;
|
||||
private bool gameObjectSearching;
|
||||
private string gameObjectSearchPatternInvalidMessage = string.Empty;
|
||||
private List<GameObject> gameObjectResults = new();
|
||||
|
||||
private Vector2 hierarchyScrollPos;
|
||||
|
||||
private readonly Lazy<Texture> arrowTexture, circleTexture;
|
||||
|
||||
private const int PAGE_BUTTON_WIDTH = 100;
|
||||
private int searchPageIndex;
|
||||
private int resultsPerPage = 30;
|
||||
|
||||
public override bool Enabled
|
||||
{
|
||||
get => base.Enabled;
|
||||
set
|
||||
{
|
||||
base.Enabled = value;
|
||||
if (value)
|
||||
{
|
||||
MoveOverlappingSceneDebugger();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SceneExtraDebugger(SceneDebugger sceneDebugger, IMap map) : base(350, "Scene Tools", KeyCode.S, true, false, true, GUISkinCreationOptions.DERIVEDCOPY, 700)
|
||||
{
|
||||
this.sceneDebugger = sceneDebugger;
|
||||
this.map = map;
|
||||
ActiveTab = AddTab("Tools", RenderTabTools);
|
||||
|
||||
// ReSharper disable once Unity.PreferAddressByIdToGraphicsParams
|
||||
circleTexture = new Lazy<Texture>(() => Resources.Load<Material>("Materials/WorldCursor").GetTexture("_MainTex"));
|
||||
arrowTexture = new Lazy<Texture>(() => Resources.Load<Texture2D>("Sprites/Arrow"));
|
||||
|
||||
ResetWindowPosition();
|
||||
}
|
||||
|
||||
public override void OnGUI()
|
||||
{
|
||||
base.OnGUI();
|
||||
if (worldMarkerEnabled && sceneDebugger.SelectedObject)
|
||||
{
|
||||
UpdateSelectedObjectMarker(sceneDebugger.SelectedObject.transform);
|
||||
}
|
||||
}
|
||||
|
||||
private void RenderTabTools()
|
||||
{
|
||||
using (new GUILayout.HorizontalScope("box"))
|
||||
{
|
||||
if (GUILayout.Button($"World Marker: {(worldMarkerEnabled ? "Active" : "Inactive")}"))
|
||||
{
|
||||
worldMarkerEnabled = !worldMarkerEnabled;
|
||||
}
|
||||
|
||||
if (GUILayout.Button($"Ray Casting: {(rayCastingEnabled ? "Active" : "Inactive")}"))
|
||||
{
|
||||
Log.InGame($"Ray casting can be enabled/disabled with: {RAY_CAST_KEY}");
|
||||
}
|
||||
}
|
||||
|
||||
GettingRayCastResults();
|
||||
GettingSearchbarResults();
|
||||
|
||||
using (new GUILayout.VerticalScope("box", GUILayout.MinHeight(600)))
|
||||
{
|
||||
if (gameObjectResults.Count > 0)
|
||||
{
|
||||
GUILayout.Label($" Found {gameObjectResults.Count} results.");
|
||||
|
||||
using (GUILayout.ScrollViewScope scroll = new(hierarchyScrollPos))
|
||||
{
|
||||
hierarchyScrollPos = scroll.scrollPosition;
|
||||
|
||||
int startIndex = resultsPerPage * searchPageIndex;
|
||||
int endIndex = startIndex + resultsPerPage;
|
||||
|
||||
if (endIndex > gameObjectResults.Count)
|
||||
{
|
||||
endIndex = gameObjectResults.Count;
|
||||
}
|
||||
|
||||
for (int index = startIndex; index < endIndex; index++)
|
||||
{
|
||||
GameObject child = gameObjectResults[index];
|
||||
if (child)
|
||||
{
|
||||
using (new GUILayout.VerticalScope("box"))
|
||||
{
|
||||
if (GUILayout.Button(child.GetFullHierarchyPath(), child.transform.childCount > 0 ? "bold" : "label"))
|
||||
{
|
||||
sceneDebugger.UpdateSelectedObject(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Needed to push the pagination buttons
|
||||
// down to the bottom when the scroll
|
||||
// view doesn't have enough height
|
||||
GUILayout.FlexibleSpace();
|
||||
|
||||
// Pagination of search results if necessary
|
||||
if (gameObjectResults.Count > resultsPerPage)
|
||||
{
|
||||
using (new GUILayout.HorizontalScope("box"))
|
||||
{
|
||||
// Only enable the back button if we can go back
|
||||
GUI.enabled = searchPageIndex > 0;
|
||||
if (GUILayout.Button("<", GUILayout.Width(PAGE_BUTTON_WIDTH)))
|
||||
{
|
||||
searchPageIndex--;
|
||||
hierarchyScrollPos = Vector2.zero;
|
||||
if (searchPageIndex < 0)
|
||||
{
|
||||
searchPageIndex = 0;
|
||||
}
|
||||
}
|
||||
GUI.enabled = true;
|
||||
|
||||
// Get the maximum page number based on the size of the results
|
||||
int maxPage = gameObjectResults.Count / resultsPerPage;
|
||||
|
||||
GUILayout.FlexibleSpace();
|
||||
GUILayout.Label($"Page {searchPageIndex + 1} of {maxPage + 1}", GUILayout.ExpandHeight(true));
|
||||
GUILayout.FlexibleSpace();
|
||||
|
||||
// Only enable the next button if we can go forward
|
||||
GUI.enabled = maxPage > searchPageIndex;
|
||||
if (GUILayout.Button(">", GUILayout.Width(PAGE_BUTTON_WIDTH)))
|
||||
{
|
||||
searchPageIndex++;
|
||||
hierarchyScrollPos = Vector2.zero;
|
||||
if (searchPageIndex > maxPage)
|
||||
{
|
||||
searchPageIndex = maxPage;
|
||||
}
|
||||
}
|
||||
|
||||
// Re-enable the GUI for anyone who comes after us
|
||||
GUI.enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GUILayout.Label("No results", "fillMessage");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void GettingSearchbarResults()
|
||||
{
|
||||
using (new GUILayout.HorizontalScope("box"))
|
||||
{
|
||||
if (rayCastingEnabled)
|
||||
{
|
||||
GUILayout.TextField(gameObjectSearch);
|
||||
return;
|
||||
}
|
||||
|
||||
gameObjectSearch = GUILayout.TextField(gameObjectSearch);
|
||||
|
||||
// Disable searching if text is cleared after a search has happened.
|
||||
if (gameObjectSearching && string.IsNullOrEmpty(gameObjectSearch))
|
||||
{
|
||||
gameObjectSearching = false;
|
||||
}
|
||||
|
||||
if (gameObjectSearch.Length > 0)
|
||||
{
|
||||
if (GUILayout.Button("Search", "button", GUILayout.Width(80)))
|
||||
{
|
||||
gameObjectSearching = true;
|
||||
searchPageIndex = 0;
|
||||
hierarchyScrollPos = Vector2.zero;
|
||||
}
|
||||
|
||||
if (GUILayout.Button("X", "button", GUILayout.Width(30)))
|
||||
{
|
||||
gameObjectSearching = false;
|
||||
gameObjectSearch = string.Empty;
|
||||
gameObjectSearchCache = string.Empty;
|
||||
gameObjectResults.Clear();
|
||||
}
|
||||
else if (Event.current.isKey && Event.current.keyCode == KeyCode.Return)
|
||||
{
|
||||
gameObjectSearching = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Searching. Return all gameobjects with matching type name.
|
||||
if (gameObjectSearching && gameObjectSearch != gameObjectSearchCache && gameObjectSearch.Length > 2)
|
||||
{
|
||||
try
|
||||
{
|
||||
// ReSharper disable once ReturnValueOfPureMethodIsNotUsed
|
||||
Regex.IsMatch(string.Empty, gameObjectSearch);
|
||||
gameObjectSearchPatternInvalidMessage = string.Empty;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
gameObjectSearchPatternInvalidMessage = ex.Message;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(gameObjectSearchPatternInvalidMessage))
|
||||
{
|
||||
if (gameObjectSearch.StartsWith("t:"))
|
||||
{
|
||||
Type type = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.Select(a => a.GetType(gameObjectSearch.Substring(2), false, true))
|
||||
.FirstOrDefault(t => t != null);
|
||||
if (type != null)
|
||||
{
|
||||
List<GameObject> gameObjects = Resources.FindObjectsOfTypeAll<GameObject>()
|
||||
.Where(g => g.GetComponent(type))
|
||||
.ToList();
|
||||
gameObjectResults = gameObjects;
|
||||
}
|
||||
else
|
||||
{
|
||||
GUILayout.Label($"There is no component named \"{gameObjectSearch.Substring(2)}\"", "error");
|
||||
}
|
||||
}
|
||||
else if (gameObjectSearch.StartsWith("id:"))
|
||||
{
|
||||
string id = gameObjectSearch.Split(':')[1];
|
||||
try
|
||||
{
|
||||
NitroxId foundId = new(id);
|
||||
if (NitroxEntity.TryGetObjectFrom(foundId, out GameObject gameObject))
|
||||
{
|
||||
gameObjectResults = [gameObject];
|
||||
}
|
||||
else
|
||||
{
|
||||
GUILayout.Label($"No GameObject found with NitroxId \"{foundId}\"");
|
||||
gameObjectResults = [];
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
GUILayout.Label($"Id \"{id}\" is not a valid NitroxId");
|
||||
gameObjectResults = [];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gameObjectResults = Resources.FindObjectsOfTypeAll<GameObject>().
|
||||
Where(go => Regex.IsMatch(go.name, gameObjectSearch, RegexOptions.IgnoreCase)).
|
||||
OrderBy(go => go.name).ToList();
|
||||
}
|
||||
|
||||
gameObjectSearchCache = gameObjectSearch;
|
||||
searchPageIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
GUILayout.Label(gameObjectSearchPatternInvalidMessage, "error");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void GettingRayCastResults()
|
||||
{
|
||||
if (Input.GetKeyDown(RAY_CAST_KEY))
|
||||
{
|
||||
gameObjectSearching = false;
|
||||
rayCastingEnabled = !rayCastingEnabled;
|
||||
|
||||
gameObjectSearch = rayCastingEnabled ? "Ray casting is running" : string.Empty;
|
||||
}
|
||||
|
||||
if (rayCastingEnabled)
|
||||
{
|
||||
gameObjectResults.Clear();
|
||||
|
||||
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
|
||||
RaycastHit[] hits = Physics.RaycastAll(ray, map.DimensionsInMeters.X, int.MaxValue);
|
||||
|
||||
foreach (RaycastHit hit in hits)
|
||||
{
|
||||
GameObject hitObject = hit.transform.gameObject;
|
||||
if (gameObjectResults.Contains(hitObject) || hitObject == Player.main.gameObject) // We want to ignore the player because of the buoyancy results in flickering of the entry
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
gameObjectResults.Add(hitObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void ResetWindowPosition()
|
||||
{
|
||||
base.ResetWindowPosition();
|
||||
// Align to the right side of the SceneDebugger
|
||||
WindowRect.x = sceneDebugger.WindowRect.x + sceneDebugger.WindowRect.width;
|
||||
WindowRect.y = sceneDebugger.WindowRect.y;
|
||||
|
||||
float exceedWidth = WindowRect.x + WindowRect.width - Screen.width;
|
||||
if (exceedWidth > 0f)
|
||||
{
|
||||
WindowRect.x -= exceedWidth;
|
||||
}
|
||||
MoveOverlappingSceneDebugger();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move the scene debugger if it's overlapping with the extra scene debugger (if they can both hold in the available space)
|
||||
/// </summary>
|
||||
private void MoveOverlappingSceneDebugger()
|
||||
{
|
||||
if (sceneDebugger.WindowRect.width + WindowRect.width < Screen.width && // verify that debuggers can hold at the same time in the screen
|
||||
sceneDebugger.WindowRect.x + sceneDebugger.WindowRect.width + WindowRect.width > Screen.width) // verify that debuggers are really overlapping
|
||||
{
|
||||
sceneDebugger.WindowRect.x = Screen.width - WindowRect.width - sceneDebugger.WindowRect.width;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateSelectedObjectMarker(Transform selectedTransform)
|
||||
{
|
||||
if (!Player.main || !Player.main.viewModelCamera || !Multiplayer.Active) // Only works in game
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Texture currentTexture;
|
||||
float markerX, markerY, markerRot;
|
||||
|
||||
Vector3 screenPos = Player.main.viewModelCamera.WorldToScreenPoint(selectedTransform.position);
|
||||
|
||||
//if object is on screen
|
||||
if (screenPos.x >= 0 && screenPos.x < Screen.width &&
|
||||
screenPos.y >= 0 && screenPos.y < Screen.height &&
|
||||
screenPos.z > 0)
|
||||
{
|
||||
currentTexture = circleTexture.Value;
|
||||
markerX = screenPos.x;
|
||||
//subtract from height to go from bottom up to top down
|
||||
markerY = Screen.height - screenPos.y;
|
||||
markerRot = 0;
|
||||
}
|
||||
else // If object is not on screen
|
||||
{
|
||||
currentTexture = arrowTexture.Value;
|
||||
//if the object is behind us, flip across the center
|
||||
if (screenPos.z < 0)
|
||||
{
|
||||
screenPos.x = Screen.width - screenPos.x;
|
||||
screenPos.y = Screen.height - screenPos.y;
|
||||
}
|
||||
|
||||
//calculate new position of arrow (somewhere on the edge)
|
||||
Vector3 screenCenter = new Vector3(Screen.width, Screen.height, 0) / 2f;
|
||||
Vector3 originPos = screenPos - screenCenter;
|
||||
|
||||
float angle = Mathf.Atan2(originPos.y, originPos.x) - (90 * Mathf.Deg2Rad);
|
||||
float cos = Mathf.Cos(angle);
|
||||
float sin = Mathf.Sin(angle);
|
||||
float m = cos / -sin;
|
||||
|
||||
Vector3 screenBounds = screenCenter * 0.9f;
|
||||
|
||||
screenPos = cos > 0 ? new Vector3(screenBounds.y / m, screenBounds.y, 0) : new Vector3(-screenBounds.y / m, -screenBounds.y, 0);
|
||||
|
||||
if (screenPos.x > screenBounds.x)
|
||||
{
|
||||
screenPos = new Vector3(screenBounds.x, screenBounds.x * m, 0);
|
||||
}
|
||||
else if (screenPos.x < -screenBounds.x)
|
||||
{
|
||||
screenPos = new Vector3(-screenBounds.x, -screenBounds.x * m, 0);
|
||||
}
|
||||
|
||||
screenPos += screenCenter;
|
||||
|
||||
markerX = screenPos.x;
|
||||
markerY = Screen.height - screenPos.y;
|
||||
markerRot = -angle * Mathf.Rad2Deg;
|
||||
}
|
||||
|
||||
float markerSizeX = currentTexture.width;
|
||||
float markerSizeY = currentTexture.height;
|
||||
GUI.matrix = Matrix4x4.Translate(new Vector3(markerX, markerY, 0)) *
|
||||
Matrix4x4.Rotate(Quaternion.Euler(0, 0, markerRot)) *
|
||||
Matrix4x4.Scale(new Vector3(0.5f, 0.5f, 0.5f)) *
|
||||
Matrix4x4.Translate(new Vector3(-markerSizeX / 2, -markerSizeY / 2, 0));
|
||||
|
||||
GUI.DrawTexture(new Rect(0, 0, markerSizeX, markerSizeY), currentTexture);
|
||||
GUI.matrix = Matrix4x4.identity;
|
||||
}
|
||||
|
||||
protected override void OnSetSkin(GUISkin skin)
|
||||
{
|
||||
base.OnSetSkin(skin);
|
||||
skin.SetCustomStyle("bold", skin.label, s =>
|
||||
{
|
||||
s.alignment = TextAnchor.LowerLeft;
|
||||
s.fontStyle = FontStyle.Bold;
|
||||
});
|
||||
skin.SetCustomStyle("error", skin.label, s =>
|
||||
{
|
||||
s.fontStyle = FontStyle.Bold;
|
||||
s.normal.textColor = Color.red;
|
||||
});
|
||||
skin.SetCustomStyle("fillMessage", skin.label, s =>
|
||||
{
|
||||
s.stretchWidth = true;
|
||||
s.stretchHeight = true;
|
||||
s.fontSize = 24;
|
||||
s.alignment = TextAnchor.MiddleCenter;
|
||||
s.fontStyle = FontStyle.Italic;
|
||||
});
|
||||
}
|
||||
}
|
225
NitroxClient/Debuggers/SoundDebugger.cs
Normal file
225
NitroxClient/Debuggers/SoundDebugger.cs
Normal file
@@ -0,0 +1,225 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using FMOD.Studio;
|
||||
using FMODUnity;
|
||||
using NitroxClient.Unity.Helper;
|
||||
using NitroxModel.GameLogic.FMOD;
|
||||
using UnityEngine;
|
||||
#pragma warning disable 618
|
||||
|
||||
namespace NitroxClient.Debuggers;
|
||||
|
||||
[ExcludeFromCodeCoverage]
|
||||
public class SoundDebugger : BaseDebugger
|
||||
{
|
||||
private readonly ReadOnlyDictionary<string, SoundData> assetList;
|
||||
private readonly Dictionary<string, bool> assetIs3D = new();
|
||||
private readonly Dictionary<string, EventInstance> eventInstancesByPath = new();
|
||||
private Vector2 scrollPosition;
|
||||
private string searchText;
|
||||
private string searchCategory;
|
||||
private float volume = 1f;
|
||||
private float distance;
|
||||
private bool displayIsWhitelisted = true;
|
||||
private bool displayIsGlobal;
|
||||
private bool displayWithRadius;
|
||||
|
||||
public SoundDebugger(FMODWhitelist fmodWhitelist) : base(700, null, KeyCode.F, true, false, false, GUISkinCreationOptions.DERIVEDCOPY)
|
||||
{
|
||||
assetList = fmodWhitelist.GetWhitelist();
|
||||
|
||||
foreach (KeyValuePair<string,SoundData> pair in assetList)
|
||||
{
|
||||
EventInstance evt = FMODUWE.GetEvent(pair.Key);
|
||||
evt.getDescription(out EventDescription description);
|
||||
description.is3D(out bool is3D);
|
||||
assetIs3D[pair.Key] = is3D;
|
||||
evt.release();
|
||||
evt.clearHandle();
|
||||
}
|
||||
|
||||
ActiveTab = AddTab("Sounds", RenderTabAllSounds);
|
||||
}
|
||||
|
||||
protected override void OnSetSkin(GUISkin skin)
|
||||
{
|
||||
base.OnSetSkin(skin);
|
||||
|
||||
skin.SetCustomStyle("soundKeyLabel",
|
||||
skin.label,
|
||||
s =>
|
||||
{
|
||||
s.fontSize = 15;
|
||||
});
|
||||
skin.SetCustomStyle("enabled",
|
||||
skin.label,
|
||||
s =>
|
||||
{
|
||||
s.normal = new GUIStyleState { textColor = Color.green };
|
||||
});
|
||||
skin.SetCustomStyle("disabled",
|
||||
skin.label,
|
||||
s =>
|
||||
{
|
||||
s.normal = new GUIStyleState { textColor = Color.red };
|
||||
});
|
||||
}
|
||||
|
||||
private void RenderTabAllSounds()
|
||||
{
|
||||
using (new GUILayout.VerticalScope("Box"))
|
||||
{
|
||||
using (new GUILayout.VerticalScope("Box"))
|
||||
{
|
||||
using (new GUILayout.HorizontalScope("Box"))
|
||||
{
|
||||
searchText = GUILayout.TextField(searchText);
|
||||
|
||||
if (GUILayout.Button("Stop all", GUILayout.MaxWidth(60f)))
|
||||
{
|
||||
eventInstancesByPath.Values.ForEach(evt => evt.stop(FMOD.Studio.STOP_MODE.IMMEDIATE));
|
||||
eventInstancesByPath.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
if (GUILayout.Button("Creature"))
|
||||
{
|
||||
searchCategory = "event:/creature";
|
||||
}
|
||||
if (GUILayout.Button("Environment"))
|
||||
{
|
||||
searchCategory = "event:/env";
|
||||
}
|
||||
if (GUILayout.Button("Player"))
|
||||
{
|
||||
searchCategory = "event:/player";
|
||||
}
|
||||
if (GUILayout.Button("Vehicles"))
|
||||
{
|
||||
searchCategory = "event:/sub";
|
||||
}
|
||||
if (GUILayout.Button("Tools"))
|
||||
{
|
||||
searchCategory = "event:/tools";
|
||||
}
|
||||
if (GUILayout.Button("Clear"))
|
||||
{
|
||||
searchCategory = string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.HorizontalScope("Box"))
|
||||
{
|
||||
using (new GUILayout.VerticalScope(GUILayout.Width(325f)))
|
||||
{
|
||||
displayIsWhitelisted = GUILayout.Toggle(displayIsWhitelisted, "Whitelisted sounds");
|
||||
displayWithRadius = GUILayout.Toggle(displayWithRadius, "Sounds with radius");
|
||||
displayIsGlobal = GUILayout.Toggle(displayIsGlobal, "Global sounds");
|
||||
}
|
||||
|
||||
using (new GUILayout.VerticalScope(GUILayout.Width(325f)))
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label($"Volume: {NitroxModel.Helper.Mathf.Round(volume, 2)}");
|
||||
volume = GUILayout.HorizontalSlider(volume, 0f, 1f, GUILayout.Width(240f));
|
||||
}
|
||||
GUILayout.Space(5f);
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label($"Distance: {NitroxModel.Helper.Mathf.Round(distance)}");
|
||||
distance = GUILayout.HorizontalSlider(distance, 0f, 500f, GUILayout.Width(240f));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
using (new GUILayout.VerticalScope("Box"))
|
||||
{
|
||||
scrollPosition = GUILayout.BeginScrollView(scrollPosition, GUILayout.Height(500f));
|
||||
|
||||
|
||||
foreach (KeyValuePair<string, SoundData> sound in assetList)
|
||||
{
|
||||
if (displayIsWhitelisted && !sound.Value.IsWhitelisted ||
|
||||
displayIsGlobal && !sound.Value.IsGlobal ||
|
||||
displayWithRadius && sound.Value.Radius <= 0.1f ||
|
||||
!string.IsNullOrWhiteSpace(searchText) && sound.Key.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) == -1 ||
|
||||
!string.IsNullOrWhiteSpace(searchCategory) && !sound.Key.StartsWith(searchCategory))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
using (new GUILayout.VerticalScope("Box", GUILayout.MaxHeight(16f)))
|
||||
{
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.Label(sound.Key, "soundKeyLabel", GUILayout.MaxWidth(370f));
|
||||
GUILayout.FlexibleSpace();
|
||||
GUILayout.Label("Is3D", assetIs3D[sound.Key] ? "enabled" : "disabled");
|
||||
GUILayout.Space(7f);
|
||||
GUILayout.Label("Whitelisted", sound.Value.IsWhitelisted ? "enabled" : "disabled", GUILayout.MinWidth(70));
|
||||
GUILayout.Space(7f);
|
||||
GUILayout.Label("Global", sound.Value.IsGlobal ? "enabled" : "disabled");
|
||||
GUILayout.Space(7f);
|
||||
GUILayout.Label($"Radius: {sound.Value.Radius}", GUILayout.Width(70f));
|
||||
|
||||
if (GUILayout.Button("Play"))
|
||||
{
|
||||
PlaySound(sound.Key);
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Stop"))
|
||||
{
|
||||
StopSound(sound.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GUILayout.EndScrollView();
|
||||
}
|
||||
}
|
||||
|
||||
private void PlaySound(string eventPath)
|
||||
{
|
||||
Camera camera = Camera.main;
|
||||
if (!camera)
|
||||
{
|
||||
Log.InGame("Camera.main not found");
|
||||
return;
|
||||
}
|
||||
Vector3 position = camera.transform.position + new Vector3(distance, 0, 0);
|
||||
|
||||
if (!eventInstancesByPath.TryGetValue(eventPath, out EventInstance instance))
|
||||
{
|
||||
instance = FMODUWE.GetEvent(eventPath);
|
||||
eventInstancesByPath.Add(eventPath, instance);
|
||||
}
|
||||
else
|
||||
{
|
||||
instance.stop(FMOD.Studio.STOP_MODE.IMMEDIATE);
|
||||
}
|
||||
|
||||
instance.setVolume(volume);
|
||||
instance.set3DAttributes(position.To3DAttributes());
|
||||
instance.setProperty(EVENT_PROPERTY.MINIMUM_DISTANCE, 0f);
|
||||
instance.setProperty(EVENT_PROPERTY.MAXIMUM_DISTANCE, 100f);
|
||||
instance.start();
|
||||
instance.release();
|
||||
}
|
||||
|
||||
private void StopSound(string eventPath)
|
||||
{
|
||||
if (eventInstancesByPath.TryGetValue(eventPath, out EventInstance instance))
|
||||
{
|
||||
instance.stop(FMOD.Studio.STOP_MODE.ALLOWFADEOUT);
|
||||
eventInstancesByPath.Remove(eventPath);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user