mirror of
https://github.com/ConjureETS/Unity_Utils.git
synced 2026-03-23 20:40:58 +00:00
added many classes and update old one with new features from new project
This commit is contained in:
parent
a20d66e8e6
commit
efdd2742db
62
Canvases/Components/ButtonUIComponent.cs
Normal file
62
Canvases/Components/ButtonUIComponent.cs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
using System;
|
||||||
|
using Sirenix.OdinInspector;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
namespace Canvases.Components
|
||||||
|
{
|
||||||
|
public class ButtonUIComponent : UISelectableComponentBase
|
||||||
|
{
|
||||||
|
public event Action OnClick;
|
||||||
|
|
||||||
|
[Header("Association"), SerializeField, Required]
|
||||||
|
private Button button;
|
||||||
|
|
||||||
|
[Header("Configuration"), SerializeField]
|
||||||
|
private ButtonNavigationType buttonNavigationType;
|
||||||
|
|
||||||
|
private enum ButtonNavigationType
|
||||||
|
{
|
||||||
|
Forward,
|
||||||
|
Backward
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color Color
|
||||||
|
{
|
||||||
|
set => button.image.color = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Enabled
|
||||||
|
{
|
||||||
|
set => button.interactable = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Select() => button.Select();
|
||||||
|
|
||||||
|
protected override void SetSelectableGameObject() => Selectable = button;
|
||||||
|
|
||||||
|
private void Start()
|
||||||
|
{
|
||||||
|
Debug.Assert(button, $"A {nameof(button)} must be assigned to a {nameof(ButtonUIComponent)}");
|
||||||
|
button.onClick.AddListener(OnButtonClicked);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDestroy()
|
||||||
|
{
|
||||||
|
button.onClick.RemoveListener(OnButtonClicked);
|
||||||
|
base.OnDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnButtonClicked()
|
||||||
|
{
|
||||||
|
// PlayClickedSound();
|
||||||
|
OnClick?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnValidate()
|
||||||
|
{
|
||||||
|
if (!button)
|
||||||
|
button = GetComponent<Button>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
37
Canvases/Components/ImageUIComponent.cs
Normal file
37
Canvases/Components/ImageUIComponent.cs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
using Sirenix.OdinInspector;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
namespace Canvases.Components
|
||||||
|
{
|
||||||
|
// ReSharper disable once InconsistentNaming Reason: UI should be capitalized
|
||||||
|
public class ImageUIComponent : UIComponentBase
|
||||||
|
{
|
||||||
|
[Header("Association")][Required]
|
||||||
|
[SerializeField] private Image image;
|
||||||
|
|
||||||
|
private Color initialColor;
|
||||||
|
|
||||||
|
private void Awake() => initialColor = image.color;
|
||||||
|
|
||||||
|
private void Start() => Debug.Assert(image, $"A {nameof(image)} must be assigned to a {nameof(ImageUIComponent)}");
|
||||||
|
|
||||||
|
public void ResetColor() => image.color = initialColor;
|
||||||
|
|
||||||
|
public Sprite Sprite
|
||||||
|
{
|
||||||
|
set => image.sprite = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color Color
|
||||||
|
{
|
||||||
|
set => image.color = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnValidate()
|
||||||
|
{
|
||||||
|
if (!image)
|
||||||
|
image = GetComponent<Image>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
151
Canvases/Components/SliderUIComponent.cs
Normal file
151
Canvases/Components/SliderUIComponent.cs
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using Sirenix.OdinInspector;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
namespace Canvases.Components
|
||||||
|
{
|
||||||
|
// ReSharper disable once InconsistentNaming Reason: UI should be capitalized
|
||||||
|
public class SliderUIComponent : UISelectableComponentBase
|
||||||
|
{
|
||||||
|
public event Action<float> OnValueChanged;
|
||||||
|
|
||||||
|
[Header("Association"), SerializeField, Required]
|
||||||
|
private Slider slider;
|
||||||
|
|
||||||
|
[SerializeField] private Image backgroundImage;
|
||||||
|
[SerializeField] private Image fillImage;
|
||||||
|
[SerializeField] private Image frame;
|
||||||
|
|
||||||
|
[Header("Animation"), SerializeField] private bool isChangeValueAnimated;
|
||||||
|
[SerializeField] [Range(0f, 1f)] private float animationSpeed = 0.05f;
|
||||||
|
[SerializeField] private Color valueIncreaseColor = Color.green;
|
||||||
|
[SerializeField] private Color valueDecreaseColor = Color.red;
|
||||||
|
|
||||||
|
private float targetValue;
|
||||||
|
private float currentValue;
|
||||||
|
|
||||||
|
private Coroutine animationRoutine;
|
||||||
|
private Color initialColor = Color.black;
|
||||||
|
|
||||||
|
public float Value
|
||||||
|
{
|
||||||
|
get => currentValue;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (isChangeValueAnimated)
|
||||||
|
{
|
||||||
|
targetValue = value;
|
||||||
|
StartAnimation();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentValue = value;
|
||||||
|
slider.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float MaxValue
|
||||||
|
{
|
||||||
|
get => slider.maxValue;
|
||||||
|
set => slider.maxValue = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color BackgroundColor
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (backgroundImage != null)
|
||||||
|
{
|
||||||
|
backgroundImage.color = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color FillColor
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (fillImage != null)
|
||||||
|
{
|
||||||
|
initialColor = value;
|
||||||
|
fillImage.color = initialColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color FrameColor
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (frame != null)
|
||||||
|
{
|
||||||
|
frame.color = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Start()
|
||||||
|
{
|
||||||
|
Debug.Assert(slider, $"A {nameof(slider)} must be assigned to a {nameof(SliderUIComponent)}");
|
||||||
|
slider.onValueChanged.AddListener(OnSliderChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void SetSelectableGameObject() => Selectable = slider;
|
||||||
|
|
||||||
|
protected override void OnDestroy()
|
||||||
|
{
|
||||||
|
slider.onValueChanged.RemoveListener(OnSliderChanged);
|
||||||
|
|
||||||
|
base.OnDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StartAnimation()
|
||||||
|
{
|
||||||
|
if (animationRoutine != null)
|
||||||
|
StopCoroutine(animationRoutine);
|
||||||
|
|
||||||
|
animationRoutine = StartCoroutine(AnimateValueChange(targetValue > currentValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerator AnimateValueChange(bool isValueChangePositive)
|
||||||
|
{
|
||||||
|
if (isValueChangePositive)
|
||||||
|
{
|
||||||
|
fillImage.color = valueIncreaseColor;
|
||||||
|
|
||||||
|
while (currentValue < targetValue)
|
||||||
|
{
|
||||||
|
currentValue += animationSpeed * Time.deltaTime;
|
||||||
|
slider.value = currentValue;
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fillImage.color = valueDecreaseColor;
|
||||||
|
|
||||||
|
while (currentValue > targetValue)
|
||||||
|
{
|
||||||
|
currentValue -= animationSpeed * Time.deltaTime;
|
||||||
|
slider.value = currentValue;
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
currentValue = targetValue;
|
||||||
|
slider.value = currentValue;
|
||||||
|
fillImage.color = initialColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSliderChanged(float value) => OnValueChanged?.Invoke(value);
|
||||||
|
|
||||||
|
private void OnValidate()
|
||||||
|
{
|
||||||
|
if (!slider)
|
||||||
|
slider = GetComponent<Slider>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
43
Canvases/Components/TextUIComponent.cs
Normal file
43
Canvases/Components/TextUIComponent.cs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
using Sirenix.OdinInspector;
|
||||||
|
using TMPro;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Canvases.Components
|
||||||
|
{
|
||||||
|
// ReSharper disable once InconsistentNaming Reason: UI should be capitalized
|
||||||
|
public class TextUIComponent : UIComponentBase
|
||||||
|
{
|
||||||
|
[Header("Association"), Required, SerializeField]
|
||||||
|
private TMP_Text text;
|
||||||
|
|
||||||
|
private string initialText;
|
||||||
|
|
||||||
|
public string Text
|
||||||
|
{
|
||||||
|
get => text.text;
|
||||||
|
set => text.text = string.IsNullOrEmpty(value) ? string.Empty : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color Color
|
||||||
|
{
|
||||||
|
get => text.color;
|
||||||
|
set => text.color = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Awake() => initialText = text.text;
|
||||||
|
|
||||||
|
private void Start() => Debug.Assert(text, $"A {nameof(text)} must be assigned to a {nameof(TMP_Text)}");
|
||||||
|
|
||||||
|
public void ResetText() => text.text = initialText;
|
||||||
|
|
||||||
|
public void AddText(string textToAdd) => text.text += textToAdd;
|
||||||
|
|
||||||
|
public void EraseText() => text.text = string.Empty;
|
||||||
|
|
||||||
|
private void OnValidate()
|
||||||
|
{
|
||||||
|
if (!text)
|
||||||
|
text = GetComponent<TMP_Text>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
42
Canvases/Components/ToggleUIComponent.cs
Normal file
42
Canvases/Components/ToggleUIComponent.cs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
using System;
|
||||||
|
using Sirenix.OdinInspector;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
namespace Canvases.Components
|
||||||
|
{
|
||||||
|
// ReSharper disable once InconsistentNaming Reason: UI should be capitalized
|
||||||
|
public class ToggleUIComponent : UISelectableComponentBase
|
||||||
|
{
|
||||||
|
public event Action<bool> OnValueChanged;
|
||||||
|
|
||||||
|
[Header("Association"), Required, SerializeField]
|
||||||
|
private Toggle toggle;
|
||||||
|
|
||||||
|
public bool IsOn => toggle.isOn;
|
||||||
|
|
||||||
|
private void Start()
|
||||||
|
{
|
||||||
|
Debug.Assert(toggle, $"A {nameof(toggle)} must be assigned to a {nameof(Toggle)}");
|
||||||
|
toggle.onValueChanged.AddListener(OnToggleChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDestroy()
|
||||||
|
{
|
||||||
|
toggle.onValueChanged.RemoveListener(OnToggleChanged);
|
||||||
|
base.OnDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void SetSelectableGameObject() => Selectable = toggle;
|
||||||
|
|
||||||
|
public void Invert() => toggle.isOn = !toggle.isOn;
|
||||||
|
|
||||||
|
private void OnToggleChanged(bool value) => OnValueChanged?.Invoke(value);
|
||||||
|
|
||||||
|
private void OnValidate()
|
||||||
|
{
|
||||||
|
if (!toggle)
|
||||||
|
toggle = GetComponent<Toggle>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
Canvases/Components/UIComponentBase.cs
Normal file
17
Canvases/Components/UIComponentBase.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
using Utilities.Extensions;
|
||||||
|
|
||||||
|
namespace Canvases.Components
|
||||||
|
{
|
||||||
|
// ReSharper disable once InconsistentNaming Reason: UI should be capitalized
|
||||||
|
public abstract class UIComponentBase : MonoBehaviour
|
||||||
|
{
|
||||||
|
public void Show() => gameObject.Show();
|
||||||
|
|
||||||
|
public void Hide() => gameObject.Hide();
|
||||||
|
|
||||||
|
public void ToggleDisplay() => gameObject.SetActive(!gameObject.activeInHierarchy);
|
||||||
|
|
||||||
|
public void SetActive(bool active) => gameObject.SetActive(active);
|
||||||
|
}
|
||||||
|
}
|
||||||
52
Canvases/Components/UISelectableComponentBase.cs
Normal file
52
Canvases/Components/UISelectableComponentBase.cs
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.EventSystems;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using Utilities.Extensions;
|
||||||
|
|
||||||
|
namespace Canvases.Components
|
||||||
|
{
|
||||||
|
public abstract class UISelectableComponentBase : UIComponentBase
|
||||||
|
{
|
||||||
|
public event Action OnSelected;
|
||||||
|
|
||||||
|
protected Selectable Selectable = null;
|
||||||
|
|
||||||
|
private EventTrigger.Entry selectEventTriggerEntry;
|
||||||
|
private CanvasGroup parentCanvasGroup;
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
SetSelectableGameObject();
|
||||||
|
AddSelectEventTrigger();
|
||||||
|
parentCanvasGroup = gameObject.GetComponentInParents<CanvasGroup>();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void SetSelectableGameObject();
|
||||||
|
|
||||||
|
private void AddSelectEventTrigger()
|
||||||
|
{
|
||||||
|
EventTrigger eventTrigger = Selectable.gameObject.GetOrAddComponent<EventTrigger>();
|
||||||
|
selectEventTriggerEntry = new EventTrigger.Entry
|
||||||
|
{
|
||||||
|
eventID = EventTriggerType.Select
|
||||||
|
};
|
||||||
|
selectEventTriggerEntry.callback.AddListener(OnSelectableSelected);
|
||||||
|
eventTrigger.triggers.Add(selectEventTriggerEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSelectableSelected(BaseEventData data)
|
||||||
|
{
|
||||||
|
if (!Selectable.interactable || parentCanvasGroup != null && !parentCanvasGroup.interactable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Play select sound
|
||||||
|
OnSelected?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnDestroy()
|
||||||
|
{
|
||||||
|
selectEventTriggerEntry?.callback.RemoveListener(OnSelectableSelected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
204
Canvases/Menu/Rebind/RebindActionUI.cs
Normal file
204
Canvases/Menu/Rebind/RebindActionUI.cs
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
using System;
|
||||||
|
using Canvases.Components;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.InputSystem;
|
||||||
|
using Utilities;
|
||||||
|
using Utilities.Extensions;
|
||||||
|
|
||||||
|
namespace Canvases.Menu.Rebind
|
||||||
|
{
|
||||||
|
public class RebindActionUI : MonoBehaviour
|
||||||
|
{
|
||||||
|
public event Action<string, string> UpdateBindingUIEvent;
|
||||||
|
|
||||||
|
[SerializeField] private TextUIComponent actionLabel;
|
||||||
|
[SerializeField] private RebindReferences mainBindingReferences;
|
||||||
|
[SerializeField] private RebindReferences altBindingReferences;
|
||||||
|
|
||||||
|
private TextUIComponent rebindOverlay;
|
||||||
|
private InputAction action;
|
||||||
|
private InputActionRebindingExtensions.RebindingOperation rebindOperation;
|
||||||
|
|
||||||
|
public void ResetToDefault()
|
||||||
|
{
|
||||||
|
action.actionMap.Disable();
|
||||||
|
action.RemoveBindingOverride(mainBindingReferences.Index);
|
||||||
|
action.RemoveBindingOverride(altBindingReferences.Index);
|
||||||
|
UpdateBindingDisplay();
|
||||||
|
action.actionMap.Enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StartInteractiveRebind(int index)
|
||||||
|
{
|
||||||
|
action.actionMap.Disable();
|
||||||
|
PerformInteractiveRebind(index);
|
||||||
|
action.actionMap.Enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PerformInteractiveRebind(int bindingIndex)
|
||||||
|
{
|
||||||
|
rebindOperation?.Cancel(); // Will null out rebindOperation.
|
||||||
|
|
||||||
|
void CleanUp(InputActionRebindingExtensions.RebindingOperation rebindingOperation)
|
||||||
|
{
|
||||||
|
if (rebindOverlay != null)
|
||||||
|
{
|
||||||
|
rebindOverlay.SetActive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateBindingDisplay();
|
||||||
|
rebindOperation?.Dispose();
|
||||||
|
rebindOperation = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure the rebind.
|
||||||
|
rebindOperation = action.PerformInteractiveRebinding(bindingIndex)
|
||||||
|
.OnCancel(CleanUp)
|
||||||
|
.OnComplete(CleanUp);
|
||||||
|
|
||||||
|
// If it's a part binding, show the name of the part in the UI.
|
||||||
|
string partName = string.Empty;
|
||||||
|
if (action.bindings[bindingIndex].isPartOfComposite)
|
||||||
|
partName = $"Binding '{action.bindings[bindingIndex].name}'. ";
|
||||||
|
|
||||||
|
// Bring up rebind overlay, if we have one.
|
||||||
|
if (rebindOverlay != null)
|
||||||
|
{
|
||||||
|
rebindOverlay.Show();
|
||||||
|
string text = !string.IsNullOrEmpty(rebindOperation.expectedControlType)
|
||||||
|
? $"{partName}Waiting for {rebindOperation.expectedControlType} input..."
|
||||||
|
: $"{partName}Waiting for input...";
|
||||||
|
rebindOverlay.Text =text;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have no rebind overlay and no callback but we have a binding text label,
|
||||||
|
// temporarily set the binding text label to "<Waiting>".
|
||||||
|
if (rebindOverlay == null && mainBindingReferences.Text != null)
|
||||||
|
mainBindingReferences.Text.Text = "<Waiting...>";
|
||||||
|
|
||||||
|
rebindOperation.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void OnEnable()
|
||||||
|
{
|
||||||
|
mainBindingReferences.Button.OnClick += () => StartInteractiveRebind(mainBindingReferences.Index);
|
||||||
|
altBindingReferences.Button.OnClick += () => StartInteractiveRebind(altBindingReferences.Index);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void OnDisable()
|
||||||
|
{
|
||||||
|
rebindOperation?.Dispose();
|
||||||
|
rebindOperation = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateActionLabel()
|
||||||
|
{
|
||||||
|
if (actionLabel == null) return;
|
||||||
|
|
||||||
|
string actionLabelText = action.bindings[mainBindingReferences.Index].isPartOfComposite
|
||||||
|
? action.bindings[mainBindingReferences.Index].name.Capitalize()
|
||||||
|
: action.name;
|
||||||
|
|
||||||
|
if (actionLabelText.Equals("Dash")) actionLabelText = "Tackle";
|
||||||
|
actionLabel.Text = actionLabelText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateBindingDisplay(bool shouldCallEvent = true)
|
||||||
|
{
|
||||||
|
string mainDisplayString = string.Empty;
|
||||||
|
string altDisplayString = string.Empty;
|
||||||
|
string deviceLayoutName = string.Empty;
|
||||||
|
string mainControlPath = string.Empty;
|
||||||
|
string altControlPath = string.Empty;
|
||||||
|
|
||||||
|
if (action != null)
|
||||||
|
{
|
||||||
|
if (mainBindingReferences.Index != -1)
|
||||||
|
mainDisplayString = action.GetBindingDisplayString(mainBindingReferences.Index,
|
||||||
|
out deviceLayoutName,
|
||||||
|
out mainControlPath);
|
||||||
|
if (altBindingReferences.Index != -1)
|
||||||
|
altDisplayString = action.GetBindingDisplayString(altBindingReferences.Index, out _,
|
||||||
|
out altControlPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateDuplicateText(mainBindingReferences, mainDisplayString);
|
||||||
|
UpdateDuplicateText(altBindingReferences, altDisplayString);
|
||||||
|
|
||||||
|
Sprite mainIcon = BindingsIconsUtil.GetSprite(deviceLayoutName, mainControlPath);
|
||||||
|
Sprite altIcon = BindingsIconsUtil.GetSprite(deviceLayoutName, altControlPath);
|
||||||
|
|
||||||
|
DisplayIcon(mainBindingReferences, mainIcon);
|
||||||
|
DisplayIcon(altBindingReferences, altIcon);
|
||||||
|
|
||||||
|
if (shouldCallEvent)
|
||||||
|
{
|
||||||
|
UpdateBindingUIEvent?.Invoke(deviceLayoutName, mainControlPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DisplayIcon(RebindReferences reference, Sprite mainIcon)
|
||||||
|
{
|
||||||
|
if (mainIcon != null)
|
||||||
|
{
|
||||||
|
reference.Text.Hide();
|
||||||
|
reference.Image.Sprite = mainIcon;
|
||||||
|
reference.Image.Show();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reference.Text.Show();
|
||||||
|
reference.Image.Hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateDuplicateText(RebindReferences reference, string mainDisplayString)
|
||||||
|
{
|
||||||
|
if (reference.Text == null) return;
|
||||||
|
reference.Text.Text = mainDisplayString == "Delta" ? "Mouse" : mainDisplayString;
|
||||||
|
bool mainDuplicate = CheckDuplicateBindings(reference.Index);
|
||||||
|
reference.Button.Color = mainDuplicate ? Color.red : Color.white;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CheckDuplicateBindings(int bindingIndex)
|
||||||
|
{
|
||||||
|
if (action == null) return false;
|
||||||
|
|
||||||
|
InputBinding newBinding = action.bindings[bindingIndex];
|
||||||
|
|
||||||
|
if (newBinding.effectivePath.IsNullOrEmpty()) return false;
|
||||||
|
|
||||||
|
foreach (InputBinding binding in action.actionMap.bindings)
|
||||||
|
{
|
||||||
|
if (binding.action == newBinding.action) continue;
|
||||||
|
|
||||||
|
if (binding.effectivePath == newBinding.effectivePath) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!action.bindings[0].isComposite) return false;
|
||||||
|
|
||||||
|
for (int i = 1; i < action.bindings.Count; i++)
|
||||||
|
{
|
||||||
|
if (i == bindingIndex) continue;
|
||||||
|
if (action.bindings[i].effectivePath == newBinding.effectivePath)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Initialize(int bindingIndex, InputAction inputAction, TextUIComponent overlay,
|
||||||
|
Action<string, string> onUpdateBindingUIEvent)
|
||||||
|
{
|
||||||
|
mainBindingReferences.Index = bindingIndex;
|
||||||
|
altBindingReferences.Index = bindingIndex + 1;
|
||||||
|
action = inputAction;
|
||||||
|
rebindOverlay = overlay;
|
||||||
|
UpdateBindingUIEvent += onUpdateBindingUIEvent;
|
||||||
|
UpdateActionLabel();
|
||||||
|
UpdateBindingDisplay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
15
Canvases/Menu/Rebind/RebindReferences.cs
Normal file
15
Canvases/Menu/Rebind/RebindReferences.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using Canvases.Components;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Canvases.Menu.Rebind
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public class RebindReferences
|
||||||
|
{
|
||||||
|
public TextUIComponent Text;
|
||||||
|
public ButtonUIComponent Button;
|
||||||
|
public ImageUIComponent Image;
|
||||||
|
[HideInInspector] public int Index = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
112
Canvases/Menu/Rebind/RebindUI.cs
Normal file
112
Canvases/Menu/Rebind/RebindUI.cs
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Canvases.Components;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.InputSystem;
|
||||||
|
using UnityEngine.InputSystem.Utilities;
|
||||||
|
using Utilities;
|
||||||
|
using Utilities.Extensions;
|
||||||
|
|
||||||
|
namespace Canvases.Menu.Rebind
|
||||||
|
{
|
||||||
|
public class RebindUI : MonoBehaviour
|
||||||
|
{
|
||||||
|
[SerializeField] private ImageUIComponent background;
|
||||||
|
[SerializeField] private GameObject rebindMenuContent;
|
||||||
|
[SerializeField] private TextUIComponent currentControlScheme;
|
||||||
|
[SerializeField] private ButtonUIComponent resetAllButton;
|
||||||
|
[SerializeField] private RectTransform scrollRectContent;
|
||||||
|
[SerializeField] private TextUIComponent rebindOverlayText;
|
||||||
|
[SerializeField] private RebindActionUI rebindPrefab;
|
||||||
|
[SerializeField] private ButtonUIComponent applyButton;
|
||||||
|
|
||||||
|
private PlayerInputAction playerInputActionRef;
|
||||||
|
|
||||||
|
private RebindActionUI firstButton;
|
||||||
|
|
||||||
|
private readonly List<RebindActionUI> rebindUIs = new List<RebindActionUI>();
|
||||||
|
private bool isInitialized;
|
||||||
|
|
||||||
|
private void Start()
|
||||||
|
{
|
||||||
|
// Bind to OnInputDeviceChanged
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEnable()
|
||||||
|
{
|
||||||
|
applyButton.OnClick += OnApplyPressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDisable()
|
||||||
|
{
|
||||||
|
applyButton.OnClick -= OnApplyPressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDestroy()
|
||||||
|
{
|
||||||
|
// Unbind to OnInputDeviceChanged
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnApplyPressed()
|
||||||
|
{
|
||||||
|
// Save changes
|
||||||
|
// Hide
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void OnResetAll()
|
||||||
|
{
|
||||||
|
playerInputActionRef.RemoveAllBindingOverrides();
|
||||||
|
UpdateAllRebindUI();
|
||||||
|
// UpdateBindings
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddBindingsButton(string deviceName)
|
||||||
|
{
|
||||||
|
currentControlScheme.Text = $"< {deviceName.ToUpper()} >";
|
||||||
|
ReadOnlyArray<InputAction> inputActions = playerInputActionRef.Player.Get().actions;
|
||||||
|
bool first = true;
|
||||||
|
foreach (var inputAction in inputActions)
|
||||||
|
{
|
||||||
|
foreach (var mainBinding in BindingsIconsUtil.GetRelevantMainBindings(inputAction, deviceName))
|
||||||
|
{
|
||||||
|
SpawnButton(inputAction, mainBinding, first);
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SpawnButton(InputAction inputAction, int mainBindingIndex, bool first)
|
||||||
|
{
|
||||||
|
RebindActionUI actionButton = Instantiate(rebindPrefab, scrollRectContent);
|
||||||
|
rebindUIs.Add(actionButton);
|
||||||
|
actionButton.name = $"Rebind UI for {inputAction.name}";
|
||||||
|
actionButton.Initialize(mainBindingIndex, inputAction, rebindOverlayText, OnUpdateBindingUIEvent);
|
||||||
|
if (first)
|
||||||
|
{
|
||||||
|
firstButton = actionButton;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUpdateBindingUIEvent(string deviceLayoutName, string mainControlPath)
|
||||||
|
{
|
||||||
|
UpdateAllRebindUI();
|
||||||
|
// UpdateBindings
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateAllRebindUI()
|
||||||
|
{
|
||||||
|
foreach (RebindActionUI rebindActionUI in rebindUIs)
|
||||||
|
{
|
||||||
|
rebindActionUI.UpdateBindingDisplay(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnInputDeviceChanged(string newDevice)
|
||||||
|
{
|
||||||
|
rebindUIs.Clear();
|
||||||
|
scrollRectContent.DestroyChildren();
|
||||||
|
AddBindingsButton(newDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
45
Common/Settings.cs
Normal file
45
Common/Settings.cs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Common
|
||||||
|
{
|
||||||
|
public class SettingsSystem : PersistentSingleton<SettingsSystem>
|
||||||
|
{
|
||||||
|
private const string SETTINGS_FOLDER_PATH = "Settings";
|
||||||
|
|
||||||
|
public static GameSettings GameSettings => Instance.GameSetting;
|
||||||
|
|
||||||
|
private GameSettings gameSetting;
|
||||||
|
private GameSettings GameSetting => gameSetting;
|
||||||
|
|
||||||
|
protected override void Awake()
|
||||||
|
{
|
||||||
|
base.Awake();
|
||||||
|
|
||||||
|
LoadSettings(out gameSetting);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadSettings<T>(out T memberToInitialize) where T : ScriptableObject
|
||||||
|
{
|
||||||
|
T[] loadedSettingsList = Resources.LoadAll<T>(SETTINGS_FOLDER_PATH);
|
||||||
|
|
||||||
|
Debug.Assert(loadedSettingsList.Any(),
|
||||||
|
$"An object of type {typeof(T).Name} should be in the folder {SETTINGS_FOLDER_PATH}");
|
||||||
|
if (loadedSettingsList.Length > 1)
|
||||||
|
Debug.LogWarning(
|
||||||
|
$"More than one object of type {typeof(T).Name} was found in the folder {SETTINGS_FOLDER_PATH}. Taking the first one.");
|
||||||
|
|
||||||
|
memberToInitialize = loadedSettingsList.First();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadAllSettings<T>(out T[] memberToInitialize) where T : ScriptableObject
|
||||||
|
{
|
||||||
|
T[] loadedSettingsList = Resources.LoadAll<T>(SETTINGS_FOLDER_PATH);
|
||||||
|
|
||||||
|
Debug.Assert(loadedSettingsList.Any(),
|
||||||
|
$"An object of type {typeof(T).Name} should be in the folder {SETTINGS_FOLDER_PATH}");
|
||||||
|
|
||||||
|
memberToInitialize = loadedSettingsList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
125
Common/Singleton.cs
Normal file
125
Common/Singleton.cs
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
using Utilities.Extensions;
|
||||||
|
|
||||||
|
namespace Common
|
||||||
|
{
|
||||||
|
public abstract class AbstractSingleton<T> : MonoBehaviour where T : AbstractSingleton<T>
|
||||||
|
{
|
||||||
|
protected static T SharedInstance;
|
||||||
|
|
||||||
|
public static bool HasInstance => SharedInstance != null;
|
||||||
|
|
||||||
|
protected virtual void Awake()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SharedInstance = (T) Convert.ChangeType(this, typeof(T));
|
||||||
|
}
|
||||||
|
catch (InvalidCastException)
|
||||||
|
{
|
||||||
|
Debug.Assert(false, "Singleton's T type should be the derived class.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void DestroyInstance()
|
||||||
|
{
|
||||||
|
if (gameObject.GetNumberOfComponents() == 1)
|
||||||
|
{
|
||||||
|
Destroy(gameObject);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Destroy(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnApplicationQuit()
|
||||||
|
{
|
||||||
|
SharedInstance = null;
|
||||||
|
DestroyInstance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Singleton class that can be loaded and unloaded with scenes.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class Singleton<T> : AbstractSingleton<T> where T : Singleton<T>
|
||||||
|
{
|
||||||
|
public static T Instance
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
Debug.Assert(HasInstance, $"Trying to access a script of type {typeof(T).Name} that is not in the scene.");
|
||||||
|
|
||||||
|
return SharedInstance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Awake()
|
||||||
|
{
|
||||||
|
if (HasInstance)
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"New instance of type {typeof(T).Name} detected. " +
|
||||||
|
"This new instance is becoming the default instance.");
|
||||||
|
SharedInstance = (T) Convert.ChangeType(this, typeof(T));;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.Awake();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnDestroy()
|
||||||
|
{
|
||||||
|
if (SharedInstance == this)
|
||||||
|
{
|
||||||
|
SharedInstance = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Singleton class that is lazy loaded once and is only unloaded when the game exits.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class PersistentSingleton<T> : AbstractSingleton<T> where T : PersistentSingleton<T>
|
||||||
|
{
|
||||||
|
public static T Instance
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
CreateIfDoesNotExist();
|
||||||
|
return SharedInstance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CreateIfDoesNotExist()
|
||||||
|
{
|
||||||
|
if (!HasInstance && Application.isPlaying)
|
||||||
|
{
|
||||||
|
CreateInstance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CreateInstance()
|
||||||
|
{
|
||||||
|
var instanceGameObject = new GameObject(typeof(T).Name);
|
||||||
|
instanceGameObject.AddComponent<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Awake()
|
||||||
|
{
|
||||||
|
if (HasInstance)
|
||||||
|
{
|
||||||
|
Debug.Log($"Two or more instances of a singleton of type {typeof(T).Name} were found in the scene. " +
|
||||||
|
"The new instance of the singleton trying to register will be removed.");
|
||||||
|
|
||||||
|
DestroyInstance();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DontDestroyOnLoadUtils.Add(gameObject);
|
||||||
|
base.Awake();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
61
Common/Timer.cs
Normal file
61
Common/Timer.cs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Common
|
||||||
|
{
|
||||||
|
public class Timer
|
||||||
|
{
|
||||||
|
public event Action OnTimeOver;
|
||||||
|
|
||||||
|
public bool IsRunning { get; private set; }
|
||||||
|
|
||||||
|
public float CurrentTime { get; private set; }
|
||||||
|
|
||||||
|
private readonly float startingTime;
|
||||||
|
private readonly bool isCountDown;
|
||||||
|
private bool isEnabled;
|
||||||
|
|
||||||
|
public Timer(float startTime, bool countDown = true)
|
||||||
|
{
|
||||||
|
IsRunning = false;
|
||||||
|
isEnabled = true;
|
||||||
|
startingTime = startTime;
|
||||||
|
isCountDown = countDown;
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Init()
|
||||||
|
{
|
||||||
|
CurrentTime = startingTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Tick(float dt)
|
||||||
|
{
|
||||||
|
if (!IsRunning || !isEnabled) return;
|
||||||
|
|
||||||
|
CurrentTime += isCountDown ? -dt : dt;
|
||||||
|
|
||||||
|
if (CurrentTime < 0)
|
||||||
|
{
|
||||||
|
CurrentTime = 0;
|
||||||
|
IsRunning = false;
|
||||||
|
isEnabled = false;
|
||||||
|
OnTimeOver?.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
isEnabled = true;
|
||||||
|
CurrentTime = isCountDown ? startingTime : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Start() => IsRunning = true;
|
||||||
|
public void Pause() => IsRunning = false;
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
IsRunning = false;
|
||||||
|
isEnabled = false;
|
||||||
|
CurrentTime = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
44
Common/TimerWrapper.cs
Normal file
44
Common/TimerWrapper.cs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.Events;
|
||||||
|
|
||||||
|
namespace Common
|
||||||
|
{
|
||||||
|
public class TimerWrapper : MonoBehaviour
|
||||||
|
{
|
||||||
|
public UnityAction OnTimerOver;
|
||||||
|
|
||||||
|
[SerializeField, Min(0)] private float startTime;
|
||||||
|
[SerializeField] private bool countDown = true;
|
||||||
|
[SerializeField] private bool startOnAwake;
|
||||||
|
[SerializeField] private bool startOnStart;
|
||||||
|
|
||||||
|
private Timer timer;
|
||||||
|
|
||||||
|
public bool IsRunning => timer.IsRunning;
|
||||||
|
public float CurrentTime => timer.CurrentTime;
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
timer = new Timer(startTime, countDown);
|
||||||
|
timer.OnTimeOver += OnTimeOver;
|
||||||
|
if (startOnAwake) timer.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Start()
|
||||||
|
{
|
||||||
|
if (startOnStart) timer.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Update()
|
||||||
|
{
|
||||||
|
timer.Tick(Time.deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StartTimer() => timer.Start();
|
||||||
|
public void PauseTimer() => timer.Pause();
|
||||||
|
public void StopTimer() => timer.Stop();
|
||||||
|
public void ResetTimer() => timer.Reset();
|
||||||
|
|
||||||
|
private void OnTimeOver() => OnTimerOver?.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,77 +0,0 @@
|
|||||||
using System;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Core
|
|
||||||
{
|
|
||||||
public abstract class Singleton<T> : MonoBehaviour where T : Singleton<T>
|
|
||||||
{
|
|
||||||
private static T _instance;
|
|
||||||
|
|
||||||
public static T Instance
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (!HasInstance)
|
|
||||||
{
|
|
||||||
Debug.LogWarning(
|
|
||||||
$"Trying to access a singleton of type {typeof(T).Name} that is not in the scene. " +
|
|
||||||
"If you are trying to see if the Instance exists, you should use the HasInstance static property instead.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return _instance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool _destroyedByScript;
|
|
||||||
|
|
||||||
public static bool HasInstance => _instance != null;
|
|
||||||
|
|
||||||
protected virtual void Awake()
|
|
||||||
{
|
|
||||||
_destroyedByScript = false;
|
|
||||||
|
|
||||||
if (HasInstance)
|
|
||||||
{
|
|
||||||
Debug.Log($"Two or more instances of a singleton of type {typeof(T).Name} were found in the scene. " +
|
|
||||||
"The new instance of the singleton trying to register will be removed.");
|
|
||||||
|
|
||||||
DestroyInstance();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_instance = (T) Convert.ChangeType(this, typeof(T));
|
|
||||||
}
|
|
||||||
catch (InvalidCastException)
|
|
||||||
{
|
|
||||||
Debug.Assert(false, "Singleton's T type should be the derived class.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DestroyInstance()
|
|
||||||
{
|
|
||||||
_destroyedByScript = true;
|
|
||||||
if (gameObject.GetNumberOfComponents() == 1)
|
|
||||||
{
|
|
||||||
Destroy(gameObject);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Destroy(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void OnDestroy()
|
|
||||||
{
|
|
||||||
if (_instance == this)
|
|
||||||
{
|
|
||||||
_instance = null;
|
|
||||||
}
|
|
||||||
else if (!_destroyedByScript)
|
|
||||||
{
|
|
||||||
Debug.LogWarning($"Instance of {typeof(T).Name} deleted, but was not the singleton instance.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,49 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
using UnityEngine.Events;
|
|
||||||
|
|
||||||
namespace Core
|
|
||||||
{
|
|
||||||
public class Timer : MonoBehaviour
|
|
||||||
{
|
|
||||||
public UnityAction onTimeOver;
|
|
||||||
|
|
||||||
public bool IsRunning { get; private set; }
|
|
||||||
|
|
||||||
public float CurrentTime { get; private set; }
|
|
||||||
|
|
||||||
[SerializeField] private float _startingTime = 600;
|
|
||||||
[SerializeField] private bool _isCountDown;
|
|
||||||
|
|
||||||
private void Start()
|
|
||||||
{
|
|
||||||
CurrentTime = _startingTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Update()
|
|
||||||
{
|
|
||||||
if (IsRunning)
|
|
||||||
{
|
|
||||||
if (_isCountDown)
|
|
||||||
{
|
|
||||||
if (CurrentTime > 0)
|
|
||||||
{
|
|
||||||
CurrentTime -= Time.deltaTime;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CurrentTime = 0;
|
|
||||||
IsRunning = false;
|
|
||||||
onTimeOver?.Invoke();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CurrentTime += Time.deltaTime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void StartTimer() => IsRunning = true;
|
|
||||||
public void StopTimer() => IsRunning = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
133
Editor/SceneAutoLoader.cs
Normal file
133
Editor/SceneAutoLoader.cs
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEditor.SceneManagement;
|
||||||
|
using UnityEngine.SceneManagement;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Scene auto loader.
|
||||||
|
/// </summary>
|
||||||
|
/// <description>
|
||||||
|
/// This class adds a File > Scene Autoload menu containing options to select
|
||||||
|
/// a "master scene" enable it to be auto-loaded when the user presses play
|
||||||
|
/// in the editor. When enabled, the selected scene will be loaded on play,
|
||||||
|
/// then the original scene will be reloaded on stop.
|
||||||
|
///
|
||||||
|
/// Based on an idea on this thread:
|
||||||
|
/// http://forum.unity3d.com/threads/157502-Executing-first-scene-in-build-settings-when-pressing-play-button-in-editor
|
||||||
|
/// </description>
|
||||||
|
[InitializeOnLoad]
|
||||||
|
public static class SceneAutoLoader
|
||||||
|
{
|
||||||
|
// Static constructor binds a playmode-changed callback.
|
||||||
|
// [InitializeOnLoad] above makes sure this gets executed.
|
||||||
|
static SceneAutoLoader()
|
||||||
|
{
|
||||||
|
EditorApplication.playModeStateChanged += OnPlayModeChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Menu items to select the "master" scene and control whether or not to load it.
|
||||||
|
[MenuItem("File/Scene Autoload/Select Master Scene...")]
|
||||||
|
private static void SelectMasterScene()
|
||||||
|
{
|
||||||
|
string masterScene = EditorUtility.OpenFilePanel("Select Master Scene", Application.dataPath, "unity");
|
||||||
|
masterScene = masterScene.Replace(Application.dataPath, "Assets"); //project relative instead of absolute path
|
||||||
|
if (!string.IsNullOrEmpty(masterScene))
|
||||||
|
{
|
||||||
|
MasterScene = masterScene;
|
||||||
|
LoadMasterOnPlay = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MenuItem("File/Scene Autoload/Load Master On Play", true)]
|
||||||
|
private static bool ShowLoadMasterOnPlay()
|
||||||
|
{
|
||||||
|
return !LoadMasterOnPlay;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MenuItem("File/Scene Autoload/Load Master On Play")]
|
||||||
|
private static void EnableLoadMasterOnPlay()
|
||||||
|
{
|
||||||
|
LoadMasterOnPlay = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MenuItem("File/Scene Autoload/Don't Load Master On Play", true)]
|
||||||
|
private static bool ShowDontLoadMasterOnPlay()
|
||||||
|
{
|
||||||
|
return LoadMasterOnPlay;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MenuItem("File/Scene Autoload/Don't Load Master On Play")]
|
||||||
|
private static void DisableLoadMasterOnPlay()
|
||||||
|
{
|
||||||
|
LoadMasterOnPlay = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Play mode change callback handles the scene load/reload.
|
||||||
|
private static void OnPlayModeChanged(PlayModeStateChange state)
|
||||||
|
{
|
||||||
|
if (!LoadMasterOnPlay)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!EditorApplication.isPlaying && EditorApplication.isPlayingOrWillChangePlaymode)
|
||||||
|
{
|
||||||
|
// User pressed play -- autoload master scene.
|
||||||
|
PreviousScene = SceneManager.GetActiveScene().path;
|
||||||
|
if (EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
EditorSceneManager.OpenScene(MasterScene);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
Debug.LogError($"error: scene not found: {MasterScene}");
|
||||||
|
EditorApplication.isPlaying = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// User cancelled the save operation -- cancel play as well.
|
||||||
|
EditorApplication.isPlaying = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// isPlaying check required because cannot OpenScene while playing
|
||||||
|
if (!EditorApplication.isPlaying && !EditorApplication.isPlayingOrWillChangePlaymode)
|
||||||
|
{
|
||||||
|
// User pressed stop -- reload previous scene.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
EditorSceneManager.OpenScene(PreviousScene);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
Debug.LogError($"error: scene not found: {PreviousScene}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Properties are remembered as editor preferences.
|
||||||
|
private const string EDITOR_PREF_LOAD_MASTER_ON_PLAY = "SceneAutoLoader.LoadMasterOnPlay";
|
||||||
|
private const string EDITOR_PREF_MASTER_SCENE = "SceneAutoLoader.MasterScene";
|
||||||
|
private const string EDITOR_PREF_PREVIOUS_SCENE = "SceneAutoLoader.PreviousScene";
|
||||||
|
|
||||||
|
private static bool LoadMasterOnPlay
|
||||||
|
{
|
||||||
|
get => EditorPrefs.GetBool(EDITOR_PREF_LOAD_MASTER_ON_PLAY, false);
|
||||||
|
set => EditorPrefs.SetBool(EDITOR_PREF_LOAD_MASTER_ON_PLAY, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string MasterScene
|
||||||
|
{
|
||||||
|
get => EditorPrefs.GetString(EDITOR_PREF_MASTER_SCENE, "Master.unity");
|
||||||
|
set => EditorPrefs.SetString(EDITOR_PREF_MASTER_SCENE, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string PreviousScene
|
||||||
|
{
|
||||||
|
get => EditorPrefs.GetString(EDITOR_PREF_PREVIOUS_SCENE, SceneManager.GetActiveScene().path);
|
||||||
|
set => EditorPrefs.SetString(EDITOR_PREF_PREVIOUS_SCENE, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,19 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
|
|
||||||
public static class GameObjectExtensions
|
|
||||||
{
|
|
||||||
public static int GetNumberOfComponents(this GameObject gameObject)
|
|
||||||
{
|
|
||||||
return gameObject.GetComponentsInChildren<Component>().Length - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Show(this GameObject gameObject)
|
|
||||||
{
|
|
||||||
gameObject.SetActive(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Hide(this GameObject gameObject)
|
|
||||||
{
|
|
||||||
gameObject.SetActive(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,45 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
public class ObjectPool<T> where T : Object
|
|
||||||
{
|
|
||||||
private readonly Queue<T> _pool;
|
|
||||||
private readonly List<T> _prefab;
|
|
||||||
|
|
||||||
public ObjectPool(IEnumerable<T> poolPrefab)
|
|
||||||
{
|
|
||||||
_pool = new Queue<T>();
|
|
||||||
_prefab = new List<T>();
|
|
||||||
_prefab.AddRange(poolPrefab);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*public ObjectPool(IEnumerable<T> prefabs)
|
|
||||||
{
|
|
||||||
_pool = new Queue<T>();
|
|
||||||
_prefab.AddRange(prefabs);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
public void Pool(T objectToPool)
|
|
||||||
{
|
|
||||||
_pool.Enqueue(objectToPool);
|
|
||||||
}
|
|
||||||
|
|
||||||
public T DePool()
|
|
||||||
{
|
|
||||||
if (_pool.Count > 0)
|
|
||||||
{
|
|
||||||
return _pool.Dequeue();
|
|
||||||
}
|
|
||||||
|
|
||||||
var randomNumber = Random.Range(0, _prefab.Count);
|
|
||||||
return Object.Instantiate(_prefab[randomNumber]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PoolAll(IEnumerable<T> listOfObject)
|
|
||||||
{
|
|
||||||
foreach (var obj in listOfObject)
|
|
||||||
{
|
|
||||||
Pool(obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BIN
Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Serialization.dll
Normal file
BIN
Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Serialization.dll
Normal file
Binary file not shown.
BIN
Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Utilities.dll
Normal file
BIN
Plugins/Sirenix/Assemblies/NoEditor/Sirenix.Utilities.dll
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Attributes.dll
Normal file
BIN
Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Attributes.dll
Normal file
Binary file not shown.
5731
Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Attributes.xml
Normal file
5731
Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Attributes.xml
Normal file
File diff suppressed because it is too large
Load Diff
BIN
Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Editor.dll
Normal file
BIN
Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Editor.dll
Normal file
Binary file not shown.
10940
Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Editor.xml
Normal file
10940
Plugins/Sirenix/Assemblies/Sirenix.OdinInspector.Editor.xml
Normal file
File diff suppressed because it is too large
Load Diff
BIN
Plugins/Sirenix/Assemblies/Sirenix.Serialization.Config.dll
Normal file
BIN
Plugins/Sirenix/Assemblies/Sirenix.Serialization.Config.dll
Normal file
Binary file not shown.
202
Plugins/Sirenix/Assemblies/Sirenix.Serialization.Config.xml
Normal file
202
Plugins/Sirenix/Assemblies/Sirenix.Serialization.Config.xml
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<doc>
|
||||||
|
<assembly>
|
||||||
|
<name>Sirenix.Serialization.Config</name>
|
||||||
|
</assembly>
|
||||||
|
<members>
|
||||||
|
<member name="T:Sirenix.Serialization.CustomLogger">
|
||||||
|
<summary>
|
||||||
|
A helper class for quickly and easily defining custom loggers.
|
||||||
|
</summary>
|
||||||
|
<seealso cref="T:Sirenix.Serialization.ILogger" />
|
||||||
|
</member>
|
||||||
|
<member name="M:Sirenix.Serialization.CustomLogger.#ctor(System.Action{System.String},System.Action{System.String},System.Action{System.Exception})">
|
||||||
|
<summary>
|
||||||
|
Not yet documented.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="M:Sirenix.Serialization.CustomLogger.LogWarning(System.String)">
|
||||||
|
<summary>
|
||||||
|
Not yet documented.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="M:Sirenix.Serialization.CustomLogger.LogError(System.String)">
|
||||||
|
<summary>
|
||||||
|
Not yet documented.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="M:Sirenix.Serialization.CustomLogger.LogException(System.Exception)">
|
||||||
|
<summary>
|
||||||
|
Not yet documented.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="T:Sirenix.Serialization.DataFormat">
|
||||||
|
<summary>
|
||||||
|
Specifies a data format to read and write in.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="F:Sirenix.Serialization.DataFormat.Binary">
|
||||||
|
<summary>
|
||||||
|
A custom packed binary format. This format is most efficient and almost allocation-free,
|
||||||
|
but its serialized data is not human-readable.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="F:Sirenix.Serialization.DataFormat.JSON">
|
||||||
|
<summary>
|
||||||
|
A JSON format compliant with the json specification found at "http://www.json.org/".
|
||||||
|
<para />
|
||||||
|
This format has rather sluggish performance and allocates frightening amounts of string garbage.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="F:Sirenix.Serialization.DataFormat.Nodes">
|
||||||
|
<summary>
|
||||||
|
A format that does not serialize to a byte stream, but to a list of data nodes in memory
|
||||||
|
which can then be serialized by Unity.
|
||||||
|
<para />
|
||||||
|
This format is highly inefficient, and is primarily used for ensuring that Unity assets
|
||||||
|
are mergeable by individual values when saved in Unity's text format. This makes
|
||||||
|
serialized values more robust and data recovery easier in case of issues.
|
||||||
|
<para />
|
||||||
|
This format is *not* recommended for use in builds.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="T:Sirenix.Serialization.DefaultLoggers">
|
||||||
|
<summary>
|
||||||
|
Defines default loggers for serialization and deserialization. This class and all of its loggers are thread safe.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:Sirenix.Serialization.DefaultLoggers.DefaultLogger">
|
||||||
|
<summary>
|
||||||
|
Not yet documented.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:Sirenix.Serialization.DefaultLoggers.UnityLogger">
|
||||||
|
<summary>
|
||||||
|
Not yet documented.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="T:Sirenix.Serialization.ErrorHandlingPolicy">
|
||||||
|
<summary>
|
||||||
|
The policy for handling errors during serialization and deserialization.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="F:Sirenix.Serialization.ErrorHandlingPolicy.Resilient">
|
||||||
|
<summary>
|
||||||
|
Attempts will be made to recover from errors and continue serialization. Data may become invalid.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="F:Sirenix.Serialization.ErrorHandlingPolicy.ThrowOnErrors">
|
||||||
|
<summary>
|
||||||
|
Exceptions will be thrown when errors are logged.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="F:Sirenix.Serialization.ErrorHandlingPolicy.ThrowOnWarningsAndErrors">
|
||||||
|
<summary>
|
||||||
|
Exceptions will be thrown when warnings or errors are logged.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="T:Sirenix.Serialization.GlobalSerializationConfig">
|
||||||
|
<summary>
|
||||||
|
Not yet documented.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="F:Sirenix.Serialization.GlobalSerializationConfig.ODIN_SERIALIZATION_CAUTIONARY_WARNING_TEXT">
|
||||||
|
<summary>
|
||||||
|
Text for the cautionary serialization warning shown in the inspector.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="F:Sirenix.Serialization.GlobalSerializationConfig.ODIN_SERIALIZATION_CAUTIONARY_WARNING_BUTTON_TEXT">
|
||||||
|
<summary>
|
||||||
|
Text for the hide button for the cautionary serialization warning shown in the inspector.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="F:Sirenix.Serialization.GlobalSerializationConfig.ODIN_PREFAB_CAUTIONARY_WARNING_BUTTON_TEXT">
|
||||||
|
<summary>
|
||||||
|
Text for the hide button for the cautionary prefab warning shown in the inspector.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="F:Sirenix.Serialization.GlobalSerializationConfig.HideSerializationCautionaryMessage">
|
||||||
|
<summary>
|
||||||
|
Whether the user has chosen to hide the cautionary serialization warning.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="F:Sirenix.Serialization.GlobalSerializationConfig.HideOdinSerializeAttributeWarningMessages">
|
||||||
|
<summary>
|
||||||
|
Whether the user has chosen to hide the warning messages related to the OdinSerialize attribute.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="F:Sirenix.Serialization.GlobalSerializationConfig.HideNonSerializedShowInInspectorWarningMessages">
|
||||||
|
<summary>
|
||||||
|
Whether the user has chosen to hide the warning messages related to the SerializeField and ShowInInspector attributes on non-serialized members.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:Sirenix.Serialization.GlobalSerializationConfig.Logger">
|
||||||
|
<summary>
|
||||||
|
Not yet documented.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:Sirenix.Serialization.GlobalSerializationConfig.EditorSerializationFormat">
|
||||||
|
<summary>
|
||||||
|
Not yet documented.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:Sirenix.Serialization.GlobalSerializationConfig.BuildSerializationFormat">
|
||||||
|
<summary>
|
||||||
|
Not yet documented.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:Sirenix.Serialization.GlobalSerializationConfig.LoggingPolicy">
|
||||||
|
<summary>
|
||||||
|
Not yet documented.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:Sirenix.Serialization.GlobalSerializationConfig.ErrorHandlingPolicy">
|
||||||
|
<summary>
|
||||||
|
Not yet documented.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="T:Sirenix.Serialization.ILogger">
|
||||||
|
<summary>
|
||||||
|
Implements methods for logging warnings, errors and exceptions during serialization and deserialization.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="M:Sirenix.Serialization.ILogger.LogWarning(System.String)">
|
||||||
|
<summary>
|
||||||
|
Logs a warning.
|
||||||
|
</summary>
|
||||||
|
<param name="warning">The warning to log.</param>
|
||||||
|
</member>
|
||||||
|
<member name="M:Sirenix.Serialization.ILogger.LogError(System.String)">
|
||||||
|
<summary>
|
||||||
|
Logs an error.
|
||||||
|
</summary>
|
||||||
|
<param name="error">The error to log.</param>
|
||||||
|
</member>
|
||||||
|
<member name="M:Sirenix.Serialization.ILogger.LogException(System.Exception)">
|
||||||
|
<summary>
|
||||||
|
Logs an exception.
|
||||||
|
</summary>
|
||||||
|
<param name="exception">The exception to log.</param>
|
||||||
|
</member>
|
||||||
|
<member name="T:Sirenix.Serialization.LoggingPolicy">
|
||||||
|
<summary>
|
||||||
|
The policy for which level of logging to do during serialization and deserialization.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="F:Sirenix.Serialization.LoggingPolicy.LogErrors">
|
||||||
|
<summary>
|
||||||
|
Not yet documented.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="F:Sirenix.Serialization.LoggingPolicy.LogWarningsAndErrors">
|
||||||
|
<summary>
|
||||||
|
Not yet documented.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="F:Sirenix.Serialization.LoggingPolicy.Silent">
|
||||||
|
<summary>
|
||||||
|
Not yet documented.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
</members>
|
||||||
|
</doc>
|
||||||
BIN
Plugins/Sirenix/Assemblies/Sirenix.Serialization.dll
Normal file
BIN
Plugins/Sirenix/Assemblies/Sirenix.Serialization.dll
Normal file
Binary file not shown.
9565
Plugins/Sirenix/Assemblies/Sirenix.Serialization.xml
Normal file
9565
Plugins/Sirenix/Assemblies/Sirenix.Serialization.xml
Normal file
File diff suppressed because it is too large
Load Diff
BIN
Plugins/Sirenix/Assemblies/Sirenix.Utilities.Editor.dll
Normal file
BIN
Plugins/Sirenix/Assemblies/Sirenix.Utilities.Editor.dll
Normal file
Binary file not shown.
7788
Plugins/Sirenix/Assemblies/Sirenix.Utilities.Editor.xml
Normal file
7788
Plugins/Sirenix/Assemblies/Sirenix.Utilities.Editor.xml
Normal file
File diff suppressed because it is too large
Load Diff
BIN
Plugins/Sirenix/Assemblies/Sirenix.Utilities.dll
Normal file
BIN
Plugins/Sirenix/Assemblies/Sirenix.Utilities.dll
Normal file
Binary file not shown.
3658
Plugins/Sirenix/Assemblies/Sirenix.Utilities.xml
Normal file
3658
Plugins/Sirenix/Assemblies/Sirenix.Utilities.xml
Normal file
File diff suppressed because it is too large
Load Diff
6
Plugins/Sirenix/Assemblies/link.xml
Normal file
6
Plugins/Sirenix/Assemblies/link.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<linker>
|
||||||
|
<assembly fullname="Sirenix.OdinInspector.Attributes" preserve="all"/>
|
||||||
|
<assembly fullname="Sirenix.Serialization.Config" preserve="all"/>
|
||||||
|
<assembly fullname="Sirenix.Serialization" preserve="all"/>
|
||||||
|
<assembly fullname="Sirenix.Utilities" preserve="all"/>
|
||||||
|
</linker>
|
||||||
BIN
Plugins/Sirenix/Odin Inspector/Assets/Editor/ConfigData.bytes
Normal file
BIN
Plugins/Sirenix/Odin Inspector/Assets/Editor/ConfigData.bytes
Normal file
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
@ -0,0 +1,13 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_PrefabParentObject: {fileID: 0}
|
||||||
|
m_PrefabInternal: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: -262940062, guid: a4865f1ab4504ed8a368670db22f409c, type: 3}
|
||||||
|
m_Name: OdinPathLookup
|
||||||
|
m_EditorClassIdentifier:
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 1726182683, guid: a4865f1ab4504ed8a368670db22f409c, type: 3}
|
||||||
|
m_Name: AOTGenerationConfig
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
automateBeforeBuilds: 0
|
||||||
|
deleteDllAfterBuilds: 1
|
||||||
|
AutomateForAllAOTPlatforms: 1
|
||||||
|
automateForPlatforms: 0900000014000000
|
||||||
|
lastScan: 0
|
||||||
|
supportSerializedTypes: []
|
||||||
@ -0,0 +1,136 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 772478971, guid: a4865f1ab4504ed8a368670db22f409c, type: 3}
|
||||||
|
m_Name: ColorPaletteManager
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
colorPalettes:
|
||||||
|
- name: Country
|
||||||
|
showAlpha: 0
|
||||||
|
colors:
|
||||||
|
- {r: 0.776, g: 0.651, b: 0.349, a: 1}
|
||||||
|
- {r: 0.863, g: 0.761, b: 0.631, a: 1}
|
||||||
|
- {r: 0.91, g: 0.831, b: 0.686, a: 1}
|
||||||
|
- {r: 0.961, g: 0.902, b: 0.788, a: 1}
|
||||||
|
- {r: 0.753, g: 0.714, b: 0.667, a: 1}
|
||||||
|
- {r: 0.478, g: 0.573, b: 0.431, a: 1}
|
||||||
|
- {r: 0.314, g: 0.427, b: 0.31, a: 1}
|
||||||
|
- {r: 0.596, g: 0.345, b: 0.235, a: 1}
|
||||||
|
- {r: 0.545, g: 0.329, b: 0.318, a: 1}
|
||||||
|
- {r: 0.647, g: 0.204, b: 0.227, a: 1}
|
||||||
|
- {r: 0.435, g: 0.161, b: 0.063, a: 1}
|
||||||
|
- {r: 0.357, g: 0.333, b: 0.278, a: 1}
|
||||||
|
- {r: 0.976, g: 0.98, b: 0.961, a: 1}
|
||||||
|
- {r: 0.165, g: 0.271, b: 0.11, a: 1}
|
||||||
|
- name: Beach
|
||||||
|
showAlpha: 0
|
||||||
|
colors:
|
||||||
|
- {r: 0.996, g: 0.906, b: 0.459, a: 1}
|
||||||
|
- {r: 0.314, g: 0.592, b: 0.035, a: 1}
|
||||||
|
- {r: 0.486, g: 0.953, b: 0.875, a: 1}
|
||||||
|
- {r: 0.996, g: 0.82, b: 0.212, a: 1}
|
||||||
|
- {r: 1, g: 0.769, b: 0.165, a: 1}
|
||||||
|
- {r: 0.804, g: 0.835, b: 0.753, a: 1}
|
||||||
|
- {r: 1, g: 0.769, b: 0.165, a: 1}
|
||||||
|
- {r: 1, g: 0.702, b: 0.063, a: 1}
|
||||||
|
- {r: 1, g: 0.898, b: 0.569, a: 1}
|
||||||
|
- name: Fall
|
||||||
|
showAlpha: 0
|
||||||
|
colors:
|
||||||
|
- {r: 0.82, g: 0.722, b: 0.318, a: 1}
|
||||||
|
- {r: 0.537, g: 0.192, b: 0.153, a: 1}
|
||||||
|
- {r: 0.996, g: 0.812, b: 0.012, a: 1}
|
||||||
|
- {r: 1, g: 0.431, b: 0.02, a: 1}
|
||||||
|
- {r: 0.937, g: 0.267, b: 0.094, a: 1}
|
||||||
|
- {r: 0.42, g: 0.212, b: 0.18, a: 1}
|
||||||
|
- {r: 0.992, g: 0.651, b: 0.004, a: 1}
|
||||||
|
- {r: 0.89, g: 0.353, b: 0.086, a: 1}
|
||||||
|
- {r: 1, g: 0.443, b: 0.004, a: 1}
|
||||||
|
- {r: 0.682, g: 0.275, b: 0.137, a: 1}
|
||||||
|
- {r: 0.306, g: 0.231, b: 0.114, a: 1}
|
||||||
|
- {r: 0.384, g: 0.416, b: 0.082, a: 1}
|
||||||
|
- {r: 0.165, g: 0.157, b: 0.008, a: 1}
|
||||||
|
- {r: 0.906, g: 0.635, b: 0.227, a: 1}
|
||||||
|
- {r: 0.82, g: 0.722, b: 0.318, a: 1}
|
||||||
|
- {r: 0.745, g: 0.435, b: 0.031, a: 1}
|
||||||
|
- {r: 0.765, g: 0.682, b: 0.569, a: 1}
|
||||||
|
- {r: 0.18, g: 0.149, b: 0.075, a: 1}
|
||||||
|
- {r: 0.702, g: 0.451, b: 0.059, a: 1}
|
||||||
|
- name: Passion
|
||||||
|
showAlpha: 0
|
||||||
|
colors:
|
||||||
|
- {r: 0.925, g: 0.682, b: 0.624, a: 1}
|
||||||
|
- {r: 0.188, g: 0.114, b: 0.224, a: 1}
|
||||||
|
- {r: 0.349, g: 0.11, b: 0.231, a: 1}
|
||||||
|
- {r: 0.435, g: 0.267, b: 0.357, a: 1}
|
||||||
|
- name: Sepia
|
||||||
|
showAlpha: 0
|
||||||
|
colors:
|
||||||
|
- {r: 0.353, g: 0.098, b: 0.02, a: 1}
|
||||||
|
- {r: 0.663, g: 0.188, b: 0.114, a: 1}
|
||||||
|
- {r: 0.906, g: 0.643, b: 0.082, a: 1}
|
||||||
|
- {r: 0.996, g: 0.839, b: 0.322, a: 1}
|
||||||
|
- {r: 0.486, g: 0.392, b: 0.02, a: 1}
|
||||||
|
- {r: 0.294, g: 0.235, b: 0.012, a: 1}
|
||||||
|
- name: Floral
|
||||||
|
showAlpha: 0
|
||||||
|
colors:
|
||||||
|
- {r: 0.855, g: 0.518, b: 0.412, a: 1}
|
||||||
|
- {r: 0.827, g: 0.294, b: 0.333, a: 1}
|
||||||
|
- {r: 0.737, g: 0.118, b: 0.208, a: 1}
|
||||||
|
- {r: 0.549, g: 0.149, b: 0.235, a: 1}
|
||||||
|
- {r: 0.949, g: 0.925, b: 0.784, a: 1}
|
||||||
|
- {r: 0.945, g: 0.882, b: 0.69, a: 1}
|
||||||
|
- {r: 0.871, g: 0.812, b: 0.698, a: 1}
|
||||||
|
- {r: 0.4, g: 0.196, b: 0.243, a: 1}
|
||||||
|
- {r: 0.271, g: 0.157, b: 0.227, a: 1}
|
||||||
|
- name: Underwater
|
||||||
|
showAlpha: 0
|
||||||
|
colors:
|
||||||
|
- {r: 0.663, g: 0.416, b: 0.733, a: 1}
|
||||||
|
- {r: 0.2, g: 0.6, b: 0.698, a: 1}
|
||||||
|
- {r: 0.11, g: 0.49, b: 0.698, a: 1}
|
||||||
|
- {r: 0.439, g: 0.627, b: 0.227, a: 1}
|
||||||
|
- {r: 0, g: 0.357, b: 0.604, a: 1}
|
||||||
|
- {r: 0.067, g: 0.271, b: 0.353, a: 1}
|
||||||
|
- name: Breeze
|
||||||
|
showAlpha: 0
|
||||||
|
colors:
|
||||||
|
- {r: 0.706, g: 1, b: 0, a: 1}
|
||||||
|
- {r: 0.651, g: 1, b: 0.404, a: 1}
|
||||||
|
- {r: 0.122, g: 1, b: 0.514, a: 1}
|
||||||
|
- {r: 0.216, g: 0.894, b: 0.961, a: 1}
|
||||||
|
- {r: 0.4, g: 1, b: 0.882, a: 1}
|
||||||
|
- {r: 0.027, g: 0.792, b: 0.8, a: 1}
|
||||||
|
- name: Clovers
|
||||||
|
showAlpha: 0
|
||||||
|
colors:
|
||||||
|
- {r: 0.431, g: 0.549, b: 0.102, a: 1}
|
||||||
|
- {r: 0.671, g: 0.714, b: 0.071, a: 1}
|
||||||
|
- {r: 0.969, g: 0.949, b: 0.831, a: 1}
|
||||||
|
- {r: 0.886, g: 0.902, b: 0.702, a: 1}
|
||||||
|
- {r: 0.753, g: 0.824, b: 0.627, a: 1}
|
||||||
|
- {r: 0.404, g: 0.6, b: 0.4, a: 1}
|
||||||
|
- name: Tropical
|
||||||
|
showAlpha: 0
|
||||||
|
colors:
|
||||||
|
- {r: 0.953, g: 0.647, b: 0.804, a: 1}
|
||||||
|
- {r: 0.965, g: 0.741, b: 0.871, a: 1}
|
||||||
|
- {r: 0.949, g: 0.549, b: 0.643, a: 1}
|
||||||
|
- {r: 0.992, g: 0.659, b: 0.498, a: 1}
|
||||||
|
- {r: 0.976, g: 0.792, b: 0.729, a: 1}
|
||||||
|
- {r: 0.984, g: 0.855, b: 0.725, a: 1}
|
||||||
|
- {r: 0.259, g: 0.882, b: 0.663, a: 1}
|
||||||
|
- {r: 0.349, g: 0.753, b: 0.78, a: 1}
|
||||||
|
- {r: 0.725, g: 0.976, b: 0.91, a: 1}
|
||||||
|
- {r: 0.647, g: 0.745, b: 0.957, a: 1}
|
||||||
|
- {r: 0.725, g: 0.863, b: 0.973, a: 1}
|
||||||
|
- {r: 0.89, g: 0.945, b: 0.996, a: 1}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: -645759843, guid: a4865f1ab4504ed8a368670db22f409c, type: 3}
|
||||||
|
m_Name: GeneralDrawerConfig
|
||||||
|
m_EditorClassIdentifier:
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 188390376, guid: a4865f1ab4504ed8a368670db22f409c, type: 3}
|
||||||
|
m_Name: ImportSettingsConfig
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
automateBeforeBuild: 1
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 1137305049, guid: a4865f1ab4504ed8a368670db22f409c, type: 3}
|
||||||
|
m_Name: InspectorConfig
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
enableOdinInInspector: 1
|
||||||
|
defaultEditorBehaviour: 11
|
||||||
|
processMouseMoveInInspector: 1
|
||||||
|
drawingConfig:
|
||||||
|
configs: []
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: -228747253, guid: a4865f1ab4504ed8a368670db22f409c, type: 3}
|
||||||
|
m_Name: OdinModuleConfig
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
configurations:
|
||||||
|
- ID: Unity.Mathematics
|
||||||
|
ActivationSettings: 0
|
||||||
|
ModuleTogglingSettings: 0
|
||||||
|
ModuleUpdateSettings: 0
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 1549551891, guid: 74721b9f0af448f5ae2e91102a1a5edd, type: 3}
|
||||||
|
m_Name: GlobalSerializationConfig
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
HideSerializationCautionaryMessage: 1
|
||||||
|
HidePrefabCautionaryMessage: 0
|
||||||
|
HideOdinSerializeAttributeWarningMessages: 0
|
||||||
|
HideNonSerializedShowInInspectorWarningMessages: 0
|
||||||
|
buildSerializationFormat: 0
|
||||||
|
editorSerializationFormat: 2
|
||||||
|
loggingPolicy: 0
|
||||||
|
errorHandlingPolicy: 0
|
||||||
BIN
Plugins/Sirenix/Odin Inspector/Modules/Unity.Entities.data
Normal file
BIN
Plugins/Sirenix/Odin Inspector/Modules/Unity.Entities.data
Normal file
Binary file not shown.
BIN
Plugins/Sirenix/Odin Inspector/Modules/Unity.Localization.data
Normal file
BIN
Plugins/Sirenix/Odin Inspector/Modules/Unity.Localization.data
Normal file
Binary file not shown.
BIN
Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics.data
Normal file
BIN
Plugins/Sirenix/Odin Inspector/Modules/Unity.Mathematics.data
Normal file
Binary file not shown.
@ -0,0 +1,883 @@
|
|||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// <copyright file="MathematicsDrawers.cs" company="Sirenix IVS">
|
||||||
|
// Copyright (c) Sirenix IVS. All rights reserved.
|
||||||
|
// </copyright>
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace Sirenix.OdinInspector.Modules.UnityMathematics.Editor
|
||||||
|
{
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using Sirenix.OdinInspector.Editor;
|
||||||
|
using Sirenix.Utilities;
|
||||||
|
using Sirenix.Utilities.Editor;
|
||||||
|
using Unity.Mathematics;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public sealed class MatrixFloat2x2Processor : MatrixProcessor<float2x2> { }
|
||||||
|
public sealed class MatrixFloat3x2Processor : MatrixProcessor<float3x2> { }
|
||||||
|
public sealed class MatrixFloat4x2Processor : MatrixProcessor<float4x2> { }
|
||||||
|
public sealed class MatrixFloat2x3Processor : MatrixProcessor<float2x3> { }
|
||||||
|
public sealed class MatrixFloat3x3Processor : MatrixProcessor<float3x3> { }
|
||||||
|
public sealed class MatrixFloat4x3Processor : MatrixProcessor<float4x3> { }
|
||||||
|
public sealed class MatrixFloat2x4Processor : MatrixProcessor<float2x4> { }
|
||||||
|
public sealed class MatrixFloat3x4Processor : MatrixProcessor<float3x4> { }
|
||||||
|
public sealed class MatrixFloat4x4Processor : MatrixProcessor<float4x4> { }
|
||||||
|
|
||||||
|
public sealed class MatrixDouble2x2Processor : MatrixProcessor<double2x2> { }
|
||||||
|
public sealed class MatrixDouble3x2Processor : MatrixProcessor<double3x2> { }
|
||||||
|
public sealed class MatrixDouble4x2Processor : MatrixProcessor<double4x2> { }
|
||||||
|
public sealed class MatrixDouble2x3Processor : MatrixProcessor<double2x3> { }
|
||||||
|
public sealed class MatrixDouble3x3Processor : MatrixProcessor<double3x3> { }
|
||||||
|
public sealed class MatrixDouble4x3Processor : MatrixProcessor<double4x3> { }
|
||||||
|
public sealed class MatrixDouble2x4Processor : MatrixProcessor<double2x4> { }
|
||||||
|
public sealed class MatrixDouble3x4Processor : MatrixProcessor<double3x4> { }
|
||||||
|
public sealed class MatrixDouble4x4Processor : MatrixProcessor<double4x4> { }
|
||||||
|
|
||||||
|
public sealed class MatrixBool2x2Processor : MatrixProcessor<bool2x2> { }
|
||||||
|
public sealed class MatrixBool3x2Processor : MatrixProcessor<bool3x2> { }
|
||||||
|
public sealed class MatrixBool4x2Processor : MatrixProcessor<bool4x2> { }
|
||||||
|
public sealed class MatrixBool2x3Processor : MatrixProcessor<bool2x3> { }
|
||||||
|
public sealed class MatrixBool3x3Processor : MatrixProcessor<bool3x3> { }
|
||||||
|
public sealed class MatrixBool4x3Processor : MatrixProcessor<bool4x3> { }
|
||||||
|
public sealed class MatrixBool2x4Processor : MatrixProcessor<bool2x4> { }
|
||||||
|
public sealed class MatrixBool3x4Processor : MatrixProcessor<bool3x4> { }
|
||||||
|
public sealed class MatrixBool4x4Processor : MatrixProcessor<bool4x4> { }
|
||||||
|
|
||||||
|
public sealed class MatrixInt2x2Processor : MatrixProcessor<int2x2> { }
|
||||||
|
public sealed class MatrixInt3x2Processor : MatrixProcessor<int3x2> { }
|
||||||
|
public sealed class MatrixInt4x2Processor : MatrixProcessor<int4x2> { }
|
||||||
|
public sealed class MatrixInt2x3Processor : MatrixProcessor<int2x3> { }
|
||||||
|
public sealed class MatrixInt3x3Processor : MatrixProcessor<int3x3> { }
|
||||||
|
public sealed class MatrixInt4x3Processor : MatrixProcessor<int4x3> { }
|
||||||
|
public sealed class MatrixInt2x4Processor : MatrixProcessor<int2x4> { }
|
||||||
|
public sealed class MatrixInt3x4Processor : MatrixProcessor<int3x4> { }
|
||||||
|
public sealed class MatrixInt4x4Processor : MatrixProcessor<int4x4> { }
|
||||||
|
|
||||||
|
public sealed class MatrixUInt2x2Processor : MatrixProcessor<uint2x2> { }
|
||||||
|
public sealed class MatrixUInt3x2Processor : MatrixProcessor<uint3x2> { }
|
||||||
|
public sealed class MatrixUInt4x2Processor : MatrixProcessor<uint4x2> { }
|
||||||
|
public sealed class MatrixUInt2x3Processor : MatrixProcessor<uint2x3> { }
|
||||||
|
public sealed class MatrixUInt3x3Processor : MatrixProcessor<uint3x3> { }
|
||||||
|
public sealed class MatrixUInt4x3Processor : MatrixProcessor<uint4x3> { }
|
||||||
|
public sealed class MatrixUInt2x4Processor : MatrixProcessor<uint2x4> { }
|
||||||
|
public sealed class MatrixUInt3x4Processor : MatrixProcessor<uint3x4> { }
|
||||||
|
public sealed class MatrixUInt4x4Processor : MatrixProcessor<uint4x4> { }
|
||||||
|
|
||||||
|
public sealed class DisableUnityMatrixDrawerAttribute : Attribute { }
|
||||||
|
|
||||||
|
public abstract class MatrixProcessor<T> : OdinAttributeProcessor<T>
|
||||||
|
{
|
||||||
|
public override void ProcessSelfAttributes(InspectorProperty property, List<Attribute> attributes)
|
||||||
|
{
|
||||||
|
attributes.GetOrAddAttribute<InlinePropertyAttribute>();
|
||||||
|
attributes.GetOrAddAttribute<DisableUnityMatrixDrawerAttribute>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ProcessChildMemberAttributes(InspectorProperty parentProperty, MemberInfo member, List<Attribute> attributes)
|
||||||
|
{
|
||||||
|
attributes.Add(new HideLabelAttribute());
|
||||||
|
attributes.Add(new MatrixChildAttribute());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DisableUnityMatrixDrawerAttributeDrawer : OdinAttributeDrawer<DisableUnityMatrixDrawerAttribute>
|
||||||
|
{
|
||||||
|
protected override void Initialize()
|
||||||
|
{
|
||||||
|
this.SkipWhenDrawing = true;
|
||||||
|
var chain = this.Property.GetActiveDrawerChain().BakedDrawerArray;
|
||||||
|
|
||||||
|
for (int i = 0; i < chain.Length; i++)
|
||||||
|
{
|
||||||
|
var type = chain[i].GetType();
|
||||||
|
|
||||||
|
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(UnityPropertyDrawer<,>) && type.GetGenericArguments()[0].Name == "MatrixDrawer")
|
||||||
|
{
|
||||||
|
chain[i].SkipWhenDrawing = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MatrixChildAttribute : Attribute { }
|
||||||
|
|
||||||
|
public class Bool2Drawer : OdinValueDrawer<bool2>
|
||||||
|
{
|
||||||
|
private bool isMatrixChild;
|
||||||
|
|
||||||
|
protected override void Initialize()
|
||||||
|
{
|
||||||
|
this.isMatrixChild = this.Property.GetAttribute<MatrixChildAttribute>() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DrawPropertyLayout(GUIContent label)
|
||||||
|
{
|
||||||
|
Rect labelRect;
|
||||||
|
Rect contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect);
|
||||||
|
{
|
||||||
|
var showLabels = !this.isMatrixChild && SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 100;
|
||||||
|
|
||||||
|
if (label != null)
|
||||||
|
{
|
||||||
|
GUILayout.Space(3); // Ugh, better than nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
var options = GUILayoutOptions.Height(EditorGUIUtility.singleLineHeight);
|
||||||
|
|
||||||
|
GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth);
|
||||||
|
EditorGUILayout.BeginVertical(options);
|
||||||
|
this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null);
|
||||||
|
EditorGUILayout.EndVertical();
|
||||||
|
EditorGUILayout.BeginVertical(options);
|
||||||
|
this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null);
|
||||||
|
EditorGUILayout.EndVertical();
|
||||||
|
GUIHelper.PopLabelWidth();
|
||||||
|
}
|
||||||
|
SirenixEditorGUI.EndHorizontalPropertyLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Bool3Drawer : OdinValueDrawer<bool3>
|
||||||
|
{
|
||||||
|
private bool isMatrixChild;
|
||||||
|
|
||||||
|
protected override void Initialize()
|
||||||
|
{
|
||||||
|
this.isMatrixChild = this.Property.GetAttribute<MatrixChildAttribute>() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DrawPropertyLayout(GUIContent label)
|
||||||
|
{
|
||||||
|
Rect labelRect;
|
||||||
|
Rect contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect);
|
||||||
|
{
|
||||||
|
var showLabels = !this.isMatrixChild && SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 100;
|
||||||
|
|
||||||
|
if (label != null)
|
||||||
|
{
|
||||||
|
GUILayout.Space(3); // Ugh, better than nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
var options = GUILayoutOptions.Height(EditorGUIUtility.singleLineHeight);
|
||||||
|
|
||||||
|
GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth);
|
||||||
|
EditorGUILayout.BeginVertical(options);
|
||||||
|
this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null);
|
||||||
|
EditorGUILayout.EndVertical();
|
||||||
|
EditorGUILayout.BeginVertical(options);
|
||||||
|
this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null);
|
||||||
|
EditorGUILayout.EndVertical();
|
||||||
|
EditorGUILayout.BeginVertical(options);
|
||||||
|
this.ValueEntry.Property.Children[2].Draw(showLabels ? GUIHelper.TempContent("Z") : null);
|
||||||
|
EditorGUILayout.EndVertical();
|
||||||
|
GUIHelper.PopLabelWidth();
|
||||||
|
}
|
||||||
|
SirenixEditorGUI.EndHorizontalPropertyLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Bool4Drawer : OdinValueDrawer<bool4>
|
||||||
|
{
|
||||||
|
private bool isMatrixChild;
|
||||||
|
|
||||||
|
protected override void Initialize()
|
||||||
|
{
|
||||||
|
this.isMatrixChild = this.Property.GetAttribute<MatrixChildAttribute>() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DrawPropertyLayout(GUIContent label)
|
||||||
|
{
|
||||||
|
Rect labelRect;
|
||||||
|
Rect contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect);
|
||||||
|
{
|
||||||
|
var showLabels = !this.isMatrixChild && SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 100;
|
||||||
|
|
||||||
|
if (label != null)
|
||||||
|
{
|
||||||
|
GUILayout.Space(3); // Ugh, better than nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
var options = GUILayoutOptions.Height(EditorGUIUtility.singleLineHeight);
|
||||||
|
|
||||||
|
GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth);
|
||||||
|
EditorGUILayout.BeginVertical(options);
|
||||||
|
this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null);
|
||||||
|
EditorGUILayout.EndVertical();
|
||||||
|
EditorGUILayout.BeginVertical(options);
|
||||||
|
this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null);
|
||||||
|
EditorGUILayout.EndVertical();
|
||||||
|
EditorGUILayout.BeginVertical(options);
|
||||||
|
this.ValueEntry.Property.Children[2].Draw(showLabels ? GUIHelper.TempContent("Z") : null);
|
||||||
|
EditorGUILayout.EndVertical();
|
||||||
|
EditorGUILayout.BeginVertical(options);
|
||||||
|
this.ValueEntry.Property.Children[3].Draw(showLabels ? GUIHelper.TempContent("W") : null);
|
||||||
|
EditorGUILayout.EndVertical();
|
||||||
|
GUIHelper.PopLabelWidth();
|
||||||
|
}
|
||||||
|
SirenixEditorGUI.EndHorizontalPropertyLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Float2Drawer : OdinValueDrawer<float2>, IDefinesGenericMenuItems
|
||||||
|
{
|
||||||
|
private bool isMatrixChild;
|
||||||
|
|
||||||
|
protected override void Initialize()
|
||||||
|
{
|
||||||
|
this.isMatrixChild = this.Property.GetAttribute<MatrixChildAttribute>() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DrawPropertyLayout(GUIContent label)
|
||||||
|
{
|
||||||
|
Rect labelRect;
|
||||||
|
Rect contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect);
|
||||||
|
{
|
||||||
|
// Slide rect
|
||||||
|
{
|
||||||
|
var val = this.ValueEntry.SmartValue;
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
var vec = SirenixEditorFields.VectorPrefixSlideRect(labelRect, new Vector2(val.x, val.y));
|
||||||
|
val = new float2(vec.x, vec.y);
|
||||||
|
if (EditorGUI.EndChangeCheck())
|
||||||
|
{
|
||||||
|
this.ValueEntry.SmartValue = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var showLabels = !this.isMatrixChild && SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 185;
|
||||||
|
GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth);
|
||||||
|
this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null);
|
||||||
|
this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null);
|
||||||
|
GUIHelper.PopLabelWidth();
|
||||||
|
|
||||||
|
}
|
||||||
|
SirenixEditorGUI.EndHorizontalPropertyLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Populates the generic menu for the property.
|
||||||
|
/// </summary>
|
||||||
|
public void PopulateGenericMenu(InspectorProperty property, GenericMenu genericMenu)
|
||||||
|
{
|
||||||
|
float2 value = (float2)property.ValueEntry.WeakSmartValue;
|
||||||
|
var vec = new Vector2(value.x, value.y);
|
||||||
|
|
||||||
|
if (genericMenu.GetItemCount() > 0)
|
||||||
|
{
|
||||||
|
genericMenu.AddSeparator("");
|
||||||
|
}
|
||||||
|
genericMenu.AddItem(new GUIContent("Normalize"), Mathf.Approximately(vec.magnitude, 1f), () => NormalizeEntries(property));
|
||||||
|
genericMenu.AddItem(new GUIContent("Zero", "Set the vector to (0, 0)"), vec == Vector2.zero, () => SetVector(property, Vector2.zero));
|
||||||
|
genericMenu.AddItem(new GUIContent("One", "Set the vector to (1, 1)"), vec == Vector2.one, () => SetVector(property, Vector2.one));
|
||||||
|
genericMenu.AddSeparator("");
|
||||||
|
genericMenu.AddItem(new GUIContent("Right", "Set the vector to (1, 0)"), vec == Vector2.right, () => SetVector(property, Vector2.right));
|
||||||
|
genericMenu.AddItem(new GUIContent("Left", "Set the vector to (-1, 0)"), vec == Vector2.left, () => SetVector(property, Vector2.left));
|
||||||
|
genericMenu.AddItem(new GUIContent("Up", "Set the vector to (0, 1)"), vec == Vector2.up, () => SetVector(property, Vector2.up));
|
||||||
|
genericMenu.AddItem(new GUIContent("Down", "Set the vector to (0, -1)"), vec == Vector2.down, () => SetVector(property, Vector2.down));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetVector(InspectorProperty property, Vector2 value)
|
||||||
|
{
|
||||||
|
property.Tree.DelayActionUntilRepaint(() =>
|
||||||
|
{
|
||||||
|
for (int i = 0; i < property.ValueEntry.ValueCount; i++)
|
||||||
|
{
|
||||||
|
property.ValueEntry.WeakValues[i] = new float2(value.x, value.y);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void NormalizeEntries(InspectorProperty property)
|
||||||
|
{
|
||||||
|
property.Tree.DelayActionUntilRepaint(() =>
|
||||||
|
{
|
||||||
|
for (int i = 0; i < property.ValueEntry.ValueCount; i++)
|
||||||
|
{
|
||||||
|
property.ValueEntry.WeakValues[i] = math.normalizesafe((float2)property.ValueEntry.WeakValues[i]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Float3Drawer : OdinValueDrawer<float3>, IDefinesGenericMenuItems
|
||||||
|
{
|
||||||
|
private bool isMatrixChild;
|
||||||
|
|
||||||
|
protected override void Initialize()
|
||||||
|
{
|
||||||
|
this.isMatrixChild = this.Property.GetAttribute<MatrixChildAttribute>() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DrawPropertyLayout(GUIContent label)
|
||||||
|
{
|
||||||
|
Rect labelRect;
|
||||||
|
Rect contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect);
|
||||||
|
{
|
||||||
|
// Slide rect
|
||||||
|
{
|
||||||
|
var val = this.ValueEntry.SmartValue;
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
var vec = SirenixEditorFields.VectorPrefixSlideRect(labelRect, new Vector3(val.x, val.y, val.z));
|
||||||
|
val = new float3(vec.x, vec.y, vec.z);
|
||||||
|
if (EditorGUI.EndChangeCheck())
|
||||||
|
{
|
||||||
|
this.ValueEntry.SmartValue = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var showLabels = !this.isMatrixChild && SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 185;
|
||||||
|
GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth);
|
||||||
|
this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null);
|
||||||
|
this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null);
|
||||||
|
this.ValueEntry.Property.Children[2].Draw(showLabels ? GUIHelper.TempContent("Z") : null);
|
||||||
|
GUIHelper.PopLabelWidth();
|
||||||
|
|
||||||
|
}
|
||||||
|
SirenixEditorGUI.EndHorizontalPropertyLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Populates the generic menu for the property.
|
||||||
|
/// </summary>
|
||||||
|
public void PopulateGenericMenu(InspectorProperty property, GenericMenu genericMenu)
|
||||||
|
{
|
||||||
|
float3 value = (float3)property.ValueEntry.WeakSmartValue;
|
||||||
|
var vec = new Vector3(value.x, value.y, value.z);
|
||||||
|
|
||||||
|
if (genericMenu.GetItemCount() > 0)
|
||||||
|
{
|
||||||
|
genericMenu.AddSeparator("");
|
||||||
|
}
|
||||||
|
genericMenu.AddItem(new GUIContent("Normalize"), Mathf.Approximately(vec.magnitude, 1f), () => NormalizeEntries(property));
|
||||||
|
genericMenu.AddItem(new GUIContent("Zero", "Set the vector to (0, 0, 0)"), vec == Vector3.zero, () => SetVector(property, Vector3.zero));
|
||||||
|
genericMenu.AddItem(new GUIContent("One", "Set the vector to (1, 1, 1)"), vec == Vector3.one, () => SetVector(property, Vector3.one));
|
||||||
|
genericMenu.AddSeparator("");
|
||||||
|
genericMenu.AddItem(new GUIContent("Right", "Set the vector to (1, 0, 0)"), vec == Vector3.right, () => SetVector(property, Vector3.right));
|
||||||
|
genericMenu.AddItem(new GUIContent("Left", "Set the vector to (-1, 0, 0)"), vec == Vector3.left, () => SetVector(property, Vector3.left));
|
||||||
|
genericMenu.AddItem(new GUIContent("Up", "Set the vector to (0, 1, 0)"), vec == Vector3.up, () => SetVector(property, Vector3.up));
|
||||||
|
genericMenu.AddItem(new GUIContent("Down", "Set the vector to (0, -1, 0)"), vec == Vector3.down, () => SetVector(property, Vector3.down));
|
||||||
|
genericMenu.AddItem(new GUIContent("Forward", "Set the vector property to (0, 0, 1)"), vec == Vector3.forward, () => SetVector(property, Vector3.forward));
|
||||||
|
genericMenu.AddItem(new GUIContent("Back", "Set the vector property to (0, 0, -1)"), vec == Vector3.back, () => SetVector(property, Vector3.back));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetVector(InspectorProperty property, Vector3 value)
|
||||||
|
{
|
||||||
|
property.Tree.DelayActionUntilRepaint(() =>
|
||||||
|
{
|
||||||
|
for (int i = 0; i < property.ValueEntry.ValueCount; i++)
|
||||||
|
{
|
||||||
|
property.ValueEntry.WeakValues[i] = new float3(value.x, value.y, value.z);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void NormalizeEntries(InspectorProperty property)
|
||||||
|
{
|
||||||
|
property.Tree.DelayActionUntilRepaint(() =>
|
||||||
|
{
|
||||||
|
for (int i = 0; i < property.ValueEntry.ValueCount; i++)
|
||||||
|
{
|
||||||
|
property.ValueEntry.WeakValues[i] = math.normalizesafe((float3)property.ValueEntry.WeakValues[i]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Float4Drawer : OdinValueDrawer<float4>, IDefinesGenericMenuItems
|
||||||
|
{
|
||||||
|
private bool isMatrixChild;
|
||||||
|
|
||||||
|
protected override void Initialize()
|
||||||
|
{
|
||||||
|
this.isMatrixChild = this.Property.GetAttribute<MatrixChildAttribute>() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DrawPropertyLayout(GUIContent label)
|
||||||
|
{
|
||||||
|
Rect labelRect;
|
||||||
|
Rect contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect);
|
||||||
|
{
|
||||||
|
// Slide rect
|
||||||
|
{
|
||||||
|
var val = this.ValueEntry.SmartValue;
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
var vec = SirenixEditorFields.VectorPrefixSlideRect(labelRect, new Vector4(val.x, val.y, val.z, val.w));
|
||||||
|
val = new float4(vec.x, vec.y, vec.z, vec.w);
|
||||||
|
if (EditorGUI.EndChangeCheck())
|
||||||
|
{
|
||||||
|
this.ValueEntry.SmartValue = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var showLabels = !this.isMatrixChild && SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 185;
|
||||||
|
GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth);
|
||||||
|
this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null);
|
||||||
|
this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null);
|
||||||
|
this.ValueEntry.Property.Children[2].Draw(showLabels ? GUIHelper.TempContent("Z") : null);
|
||||||
|
this.ValueEntry.Property.Children[3].Draw(showLabels ? GUIHelper.TempContent("W") : null);
|
||||||
|
GUIHelper.PopLabelWidth();
|
||||||
|
|
||||||
|
}
|
||||||
|
SirenixEditorGUI.EndHorizontalPropertyLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Populates the generic menu for the property.
|
||||||
|
/// </summary>
|
||||||
|
public void PopulateGenericMenu(InspectorProperty property, GenericMenu genericMenu)
|
||||||
|
{
|
||||||
|
float4 value = (float4)property.ValueEntry.WeakSmartValue;
|
||||||
|
var vec = new Vector4(value.x, value.y, value.z, value.w);
|
||||||
|
|
||||||
|
if (genericMenu.GetItemCount() > 0)
|
||||||
|
{
|
||||||
|
genericMenu.AddSeparator("");
|
||||||
|
}
|
||||||
|
genericMenu.AddItem(new GUIContent("Normalize"), Mathf.Approximately(vec.magnitude, 1f), () => NormalizeEntries(property));
|
||||||
|
genericMenu.AddItem(new GUIContent("Zero", "Set the vector to (0, 0, 0, 0)"), vec == Vector4.zero, () => SetVector(property, Vector3.zero));
|
||||||
|
genericMenu.AddItem(new GUIContent("One", "Set the vector to (1, 1, 1, 1)"), vec == Vector4.one, () => SetVector(property, Vector4.one));
|
||||||
|
genericMenu.AddSeparator("");
|
||||||
|
genericMenu.AddItem(new GUIContent("Right", "Set the vector to (1, 0, 0, 0)"), (Vector3)vec == Vector3.right, () => SetVector(property, Vector3.right));
|
||||||
|
genericMenu.AddItem(new GUIContent("Left", "Set the vector to (-1, 0, 0, 0)"), (Vector3)vec == Vector3.left, () => SetVector(property, Vector3.left));
|
||||||
|
genericMenu.AddItem(new GUIContent("Up", "Set the vector to (0, 1, 0, 0)"), (Vector3)vec == Vector3.up, () => SetVector(property, Vector3.up));
|
||||||
|
genericMenu.AddItem(new GUIContent("Down", "Set the vector to (0, -1, 0, 0)"), (Vector3)vec == Vector3.down, () => SetVector(property, Vector3.down));
|
||||||
|
genericMenu.AddItem(new GUIContent("Forward", "Set the vector property to (0, 0, 1, 0)"), (Vector3)vec == Vector3.forward, () => SetVector(property, Vector3.forward));
|
||||||
|
genericMenu.AddItem(new GUIContent("Back", "Set the vector property to (0, 0, -1, 0)"), (Vector3)vec == Vector3.back, () => SetVector(property, Vector3.back));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetVector(InspectorProperty property, Vector4 value)
|
||||||
|
{
|
||||||
|
property.Tree.DelayActionUntilRepaint(() =>
|
||||||
|
{
|
||||||
|
for (int i = 0; i < property.ValueEntry.ValueCount; i++)
|
||||||
|
{
|
||||||
|
property.ValueEntry.WeakValues[i] = new float4(value.x, value.y, value.z, value.w);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void NormalizeEntries(InspectorProperty property)
|
||||||
|
{
|
||||||
|
property.Tree.DelayActionUntilRepaint(() =>
|
||||||
|
{
|
||||||
|
for (int i = 0; i < property.ValueEntry.ValueCount; i++)
|
||||||
|
{
|
||||||
|
property.ValueEntry.WeakValues[i] = math.normalizesafe((float4)property.ValueEntry.WeakValues[i]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class Double2Drawer : OdinValueDrawer<double2>, IDefinesGenericMenuItems
|
||||||
|
{
|
||||||
|
private bool isMatrixChild;
|
||||||
|
|
||||||
|
protected override void Initialize()
|
||||||
|
{
|
||||||
|
this.isMatrixChild = this.Property.GetAttribute<MatrixChildAttribute>() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DrawPropertyLayout(GUIContent label)
|
||||||
|
{
|
||||||
|
Rect labelRect;
|
||||||
|
Rect contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect);
|
||||||
|
{
|
||||||
|
// Slide rect
|
||||||
|
{
|
||||||
|
var val = this.ValueEntry.SmartValue;
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
var vec = SirenixEditorFields.VectorPrefixSlideRect(labelRect, new Vector2((float)val.x, (float)val.y));
|
||||||
|
val = new double2(vec.x, vec.y);
|
||||||
|
if (EditorGUI.EndChangeCheck())
|
||||||
|
{
|
||||||
|
this.ValueEntry.SmartValue = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var showLabels = !this.isMatrixChild && SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 185;
|
||||||
|
GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth);
|
||||||
|
this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null);
|
||||||
|
this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null);
|
||||||
|
GUIHelper.PopLabelWidth();
|
||||||
|
|
||||||
|
}
|
||||||
|
SirenixEditorGUI.EndHorizontalPropertyLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Populates the generic menu for the property.
|
||||||
|
/// </summary>
|
||||||
|
public void PopulateGenericMenu(InspectorProperty property, GenericMenu genericMenu)
|
||||||
|
{
|
||||||
|
double2 value = (double2)property.ValueEntry.WeakSmartValue;
|
||||||
|
var vec = new Vector2((float)value.x, (float)value.y);
|
||||||
|
|
||||||
|
if (genericMenu.GetItemCount() > 0)
|
||||||
|
{
|
||||||
|
genericMenu.AddSeparator("");
|
||||||
|
}
|
||||||
|
genericMenu.AddItem(new GUIContent("Normalize"), Mathf.Approximately(vec.magnitude, 1f), () => NormalizeEntries(property));
|
||||||
|
genericMenu.AddItem(new GUIContent("Zero", "Set the vector to (0, 0)"), vec == Vector2.zero, () => SetVector(property, Vector2.zero));
|
||||||
|
genericMenu.AddItem(new GUIContent("One", "Set the vector to (1, 1)"), vec == Vector2.one, () => SetVector(property, Vector2.one));
|
||||||
|
genericMenu.AddSeparator("");
|
||||||
|
genericMenu.AddItem(new GUIContent("Right", "Set the vector to (1, 0)"), vec == Vector2.right, () => SetVector(property, Vector2.right));
|
||||||
|
genericMenu.AddItem(new GUIContent("Left", "Set the vector to (-1, 0)"), vec == Vector2.left, () => SetVector(property, Vector2.left));
|
||||||
|
genericMenu.AddItem(new GUIContent("Up", "Set the vector to (0, 1)"), vec == Vector2.up, () => SetVector(property, Vector2.up));
|
||||||
|
genericMenu.AddItem(new GUIContent("Down", "Set the vector to (0, -1)"), vec == Vector2.down, () => SetVector(property, Vector2.down));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetVector(InspectorProperty property, Vector2 value)
|
||||||
|
{
|
||||||
|
property.Tree.DelayActionUntilRepaint(() =>
|
||||||
|
{
|
||||||
|
for (int i = 0; i < property.ValueEntry.ValueCount; i++)
|
||||||
|
{
|
||||||
|
property.ValueEntry.WeakValues[i] = new double2(value.x, value.y);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void NormalizeEntries(InspectorProperty property)
|
||||||
|
{
|
||||||
|
property.Tree.DelayActionUntilRepaint(() =>
|
||||||
|
{
|
||||||
|
for (int i = 0; i < property.ValueEntry.ValueCount; i++)
|
||||||
|
{
|
||||||
|
property.ValueEntry.WeakValues[i] = math.normalizesafe((double2)property.ValueEntry.WeakValues[i]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Double3Drawer : OdinValueDrawer<double3>, IDefinesGenericMenuItems
|
||||||
|
{
|
||||||
|
private bool isMatrixChild;
|
||||||
|
|
||||||
|
protected override void Initialize()
|
||||||
|
{
|
||||||
|
this.isMatrixChild = this.Property.GetAttribute<MatrixChildAttribute>() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DrawPropertyLayout(GUIContent label)
|
||||||
|
{
|
||||||
|
Rect labelRect;
|
||||||
|
Rect contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect);
|
||||||
|
{
|
||||||
|
// Slide rect
|
||||||
|
{
|
||||||
|
var val = this.ValueEntry.SmartValue;
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
var vec = SirenixEditorFields.VectorPrefixSlideRect(labelRect, new Vector3((float)val.x, (float)val.y, (float)val.z));
|
||||||
|
val = new double3(vec.x, vec.y, vec.z);
|
||||||
|
if (EditorGUI.EndChangeCheck())
|
||||||
|
{
|
||||||
|
this.ValueEntry.SmartValue = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var showLabels = !this.isMatrixChild && SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 185;
|
||||||
|
GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth);
|
||||||
|
this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null);
|
||||||
|
this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null);
|
||||||
|
this.ValueEntry.Property.Children[2].Draw(showLabels ? GUIHelper.TempContent("Z") : null);
|
||||||
|
GUIHelper.PopLabelWidth();
|
||||||
|
|
||||||
|
}
|
||||||
|
SirenixEditorGUI.EndHorizontalPropertyLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Populates the generic menu for the property.
|
||||||
|
/// </summary>
|
||||||
|
public void PopulateGenericMenu(InspectorProperty property, GenericMenu genericMenu)
|
||||||
|
{
|
||||||
|
double3 value = (double3)property.ValueEntry.WeakSmartValue;
|
||||||
|
var vec = new Vector3((float)value.x, (float)value.y, (float)value.z);
|
||||||
|
|
||||||
|
if (genericMenu.GetItemCount() > 0)
|
||||||
|
{
|
||||||
|
genericMenu.AddSeparator("");
|
||||||
|
}
|
||||||
|
genericMenu.AddItem(new GUIContent("Normalize"), Mathf.Approximately(vec.magnitude, 1f), () => NormalizeEntries(property));
|
||||||
|
genericMenu.AddItem(new GUIContent("Zero", "Set the vector to (0, 0, 0)"), vec == Vector3.zero, () => SetVector(property, Vector3.zero));
|
||||||
|
genericMenu.AddItem(new GUIContent("One", "Set the vector to (1, 1, 1)"), vec == Vector3.one, () => SetVector(property, Vector3.one));
|
||||||
|
genericMenu.AddSeparator("");
|
||||||
|
genericMenu.AddItem(new GUIContent("Right", "Set the vector to (1, 0, 0)"), vec == Vector3.right, () => SetVector(property, Vector3.right));
|
||||||
|
genericMenu.AddItem(new GUIContent("Left", "Set the vector to (-1, 0, 0)"), vec == Vector3.left, () => SetVector(property, Vector3.left));
|
||||||
|
genericMenu.AddItem(new GUIContent("Up", "Set the vector to (0, 1, 0)"), vec == Vector3.up, () => SetVector(property, Vector3.up));
|
||||||
|
genericMenu.AddItem(new GUIContent("Down", "Set the vector to (0, -1, 0)"), vec == Vector3.down, () => SetVector(property, Vector3.down));
|
||||||
|
genericMenu.AddItem(new GUIContent("Forward", "Set the vector property to (0, 0, 1)"), vec == Vector3.forward, () => SetVector(property, Vector3.forward));
|
||||||
|
genericMenu.AddItem(new GUIContent("Back", "Set the vector property to (0, 0, -1)"), vec == Vector3.back, () => SetVector(property, Vector3.back));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetVector(InspectorProperty property, Vector3 value)
|
||||||
|
{
|
||||||
|
property.Tree.DelayActionUntilRepaint(() =>
|
||||||
|
{
|
||||||
|
for (int i = 0; i < property.ValueEntry.ValueCount; i++)
|
||||||
|
{
|
||||||
|
property.ValueEntry.WeakValues[i] = new double3(value.x, value.y, value.z);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void NormalizeEntries(InspectorProperty property)
|
||||||
|
{
|
||||||
|
property.Tree.DelayActionUntilRepaint(() =>
|
||||||
|
{
|
||||||
|
for (int i = 0; i < property.ValueEntry.ValueCount; i++)
|
||||||
|
{
|
||||||
|
property.ValueEntry.WeakValues[i] = math.normalizesafe((double3)property.ValueEntry.WeakValues[i]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Double4Drawer : OdinValueDrawer<double4>, IDefinesGenericMenuItems
|
||||||
|
{
|
||||||
|
private bool isMatrixChild;
|
||||||
|
|
||||||
|
protected override void Initialize()
|
||||||
|
{
|
||||||
|
this.isMatrixChild = this.Property.GetAttribute<MatrixChildAttribute>() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DrawPropertyLayout(GUIContent label)
|
||||||
|
{
|
||||||
|
Rect labelRect;
|
||||||
|
Rect contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect);
|
||||||
|
{
|
||||||
|
// Slide rect
|
||||||
|
{
|
||||||
|
var val = this.ValueEntry.SmartValue;
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
var vec = SirenixEditorFields.VectorPrefixSlideRect(labelRect, new Vector4((float)val.x, (float)val.y, (float)val.z, (float)val.w));
|
||||||
|
val = new double4(vec.x, vec.y, vec.z, vec.w);
|
||||||
|
if (EditorGUI.EndChangeCheck())
|
||||||
|
{
|
||||||
|
this.ValueEntry.SmartValue = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var showLabels = !this.isMatrixChild && SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 185;
|
||||||
|
GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth);
|
||||||
|
this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null);
|
||||||
|
this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null);
|
||||||
|
this.ValueEntry.Property.Children[2].Draw(showLabels ? GUIHelper.TempContent("Z") : null);
|
||||||
|
this.ValueEntry.Property.Children[3].Draw(showLabels ? GUIHelper.TempContent("W") : null);
|
||||||
|
GUIHelper.PopLabelWidth();
|
||||||
|
|
||||||
|
}
|
||||||
|
SirenixEditorGUI.EndHorizontalPropertyLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Populates the generic menu for the property.
|
||||||
|
/// </summary>
|
||||||
|
public void PopulateGenericMenu(InspectorProperty property, GenericMenu genericMenu)
|
||||||
|
{
|
||||||
|
double4 value = (double4)property.ValueEntry.WeakSmartValue;
|
||||||
|
var vec = new Vector4((float)value.x, (float)value.y, (float)value.z, (float)value.w);
|
||||||
|
|
||||||
|
if (genericMenu.GetItemCount() > 0)
|
||||||
|
{
|
||||||
|
genericMenu.AddSeparator("");
|
||||||
|
}
|
||||||
|
genericMenu.AddItem(new GUIContent("Normalize"), Mathf.Approximately(vec.magnitude, 1f), () => NormalizeEntries(property));
|
||||||
|
genericMenu.AddItem(new GUIContent("Zero", "Set the vector to (0, 0, 0, 0)"), vec == Vector4.zero, () => SetVector(property, Vector3.zero));
|
||||||
|
genericMenu.AddItem(new GUIContent("One", "Set the vector to (1, 1, 1, 1)"), vec == Vector4.one, () => SetVector(property, Vector4.one));
|
||||||
|
genericMenu.AddSeparator("");
|
||||||
|
genericMenu.AddItem(new GUIContent("Right", "Set the vector to (1, 0, 0, 0)"), (Vector3)vec == Vector3.right, () => SetVector(property, Vector3.right));
|
||||||
|
genericMenu.AddItem(new GUIContent("Left", "Set the vector to (-1, 0, 0, 0)"), (Vector3)vec == Vector3.left, () => SetVector(property, Vector3.left));
|
||||||
|
genericMenu.AddItem(new GUIContent("Up", "Set the vector to (0, 1, 0, 0)"), (Vector3)vec == Vector3.up, () => SetVector(property, Vector3.up));
|
||||||
|
genericMenu.AddItem(new GUIContent("Down", "Set the vector to (0, -1, 0, 0)"), (Vector3)vec == Vector3.down, () => SetVector(property, Vector3.down));
|
||||||
|
genericMenu.AddItem(new GUIContent("Forward", "Set the vector property to (0, 0, 1, 0)"), (Vector3)vec == Vector3.forward, () => SetVector(property, Vector3.forward));
|
||||||
|
genericMenu.AddItem(new GUIContent("Back", "Set the vector property to (0, 0, -1, 0)"), (Vector3)vec == Vector3.back, () => SetVector(property, Vector3.back));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetVector(InspectorProperty property, Vector4 value)
|
||||||
|
{
|
||||||
|
property.Tree.DelayActionUntilRepaint(() =>
|
||||||
|
{
|
||||||
|
for (int i = 0; i < property.ValueEntry.ValueCount; i++)
|
||||||
|
{
|
||||||
|
property.ValueEntry.WeakValues[i] = new double4(value.x, value.y, value.z, value.w);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void NormalizeEntries(InspectorProperty property)
|
||||||
|
{
|
||||||
|
property.Tree.DelayActionUntilRepaint(() =>
|
||||||
|
{
|
||||||
|
for (int i = 0; i < property.ValueEntry.ValueCount; i++)
|
||||||
|
{
|
||||||
|
property.ValueEntry.WeakValues[i] = math.normalizesafe((double4)property.ValueEntry.WeakValues[i]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Int2Drawer : OdinValueDrawer<int2>
|
||||||
|
{
|
||||||
|
private bool isMatrixChild;
|
||||||
|
|
||||||
|
protected override void Initialize()
|
||||||
|
{
|
||||||
|
this.isMatrixChild = this.Property.GetAttribute<MatrixChildAttribute>() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DrawPropertyLayout(GUIContent label)
|
||||||
|
{
|
||||||
|
Rect labelRect;
|
||||||
|
Rect contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect);
|
||||||
|
{
|
||||||
|
var showLabels = !this.isMatrixChild && SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 185;
|
||||||
|
GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth);
|
||||||
|
this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null);
|
||||||
|
this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null);
|
||||||
|
GUIHelper.PopLabelWidth();
|
||||||
|
|
||||||
|
}
|
||||||
|
SirenixEditorGUI.EndHorizontalPropertyLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Int3Drawer : OdinValueDrawer<int3>
|
||||||
|
{
|
||||||
|
private bool isMatrixChild;
|
||||||
|
|
||||||
|
protected override void Initialize()
|
||||||
|
{
|
||||||
|
this.isMatrixChild = this.Property.GetAttribute<MatrixChildAttribute>() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DrawPropertyLayout(GUIContent label)
|
||||||
|
{
|
||||||
|
Rect labelRect;
|
||||||
|
Rect contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect);
|
||||||
|
{
|
||||||
|
var showLabels = !this.isMatrixChild && SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 185;
|
||||||
|
GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth);
|
||||||
|
this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null);
|
||||||
|
this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null);
|
||||||
|
this.ValueEntry.Property.Children[2].Draw(showLabels ? GUIHelper.TempContent("Z") : null);
|
||||||
|
GUIHelper.PopLabelWidth();
|
||||||
|
|
||||||
|
}
|
||||||
|
SirenixEditorGUI.EndHorizontalPropertyLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Int4Drawer : OdinValueDrawer<int4>
|
||||||
|
{
|
||||||
|
private bool isMatrixChild;
|
||||||
|
|
||||||
|
protected override void Initialize()
|
||||||
|
{
|
||||||
|
this.isMatrixChild = this.Property.GetAttribute<MatrixChildAttribute>() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DrawPropertyLayout(GUIContent label)
|
||||||
|
{
|
||||||
|
Rect labelRect;
|
||||||
|
Rect contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect);
|
||||||
|
{
|
||||||
|
var showLabels = !this.isMatrixChild && SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 185;
|
||||||
|
GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth);
|
||||||
|
this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null);
|
||||||
|
this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null);
|
||||||
|
this.ValueEntry.Property.Children[2].Draw(showLabels ? GUIHelper.TempContent("Z") : null);
|
||||||
|
this.ValueEntry.Property.Children[3].Draw(showLabels ? GUIHelper.TempContent("W") : null);
|
||||||
|
GUIHelper.PopLabelWidth();
|
||||||
|
|
||||||
|
}
|
||||||
|
SirenixEditorGUI.EndHorizontalPropertyLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UInt2Drawer : OdinValueDrawer<uint2>
|
||||||
|
{
|
||||||
|
private bool isMatrixChild;
|
||||||
|
|
||||||
|
protected override void Initialize()
|
||||||
|
{
|
||||||
|
this.isMatrixChild = this.Property.GetAttribute<MatrixChildAttribute>() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DrawPropertyLayout(GUIContent label)
|
||||||
|
{
|
||||||
|
Rect labelRect;
|
||||||
|
Rect contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect);
|
||||||
|
{
|
||||||
|
var showLabels = !this.isMatrixChild && SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 185;
|
||||||
|
GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth);
|
||||||
|
this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null);
|
||||||
|
this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null);
|
||||||
|
GUIHelper.PopLabelWidth();
|
||||||
|
|
||||||
|
}
|
||||||
|
SirenixEditorGUI.EndHorizontalPropertyLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UInt3Drawer : OdinValueDrawer<uint3>
|
||||||
|
{
|
||||||
|
private bool isMatrixChild;
|
||||||
|
|
||||||
|
protected override void Initialize()
|
||||||
|
{
|
||||||
|
this.isMatrixChild = this.Property.GetAttribute<MatrixChildAttribute>() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DrawPropertyLayout(GUIContent label)
|
||||||
|
{
|
||||||
|
Rect labelRect;
|
||||||
|
Rect contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect);
|
||||||
|
{
|
||||||
|
var showLabels = !this.isMatrixChild && SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 185;
|
||||||
|
GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth);
|
||||||
|
this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null);
|
||||||
|
this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null);
|
||||||
|
this.ValueEntry.Property.Children[2].Draw(showLabels ? GUIHelper.TempContent("Z") : null);
|
||||||
|
GUIHelper.PopLabelWidth();
|
||||||
|
|
||||||
|
}
|
||||||
|
SirenixEditorGUI.EndHorizontalPropertyLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UInt4Drawer : OdinValueDrawer<uint4>
|
||||||
|
{
|
||||||
|
private bool isMatrixChild;
|
||||||
|
|
||||||
|
protected override void Initialize()
|
||||||
|
{
|
||||||
|
this.isMatrixChild = this.Property.GetAttribute<MatrixChildAttribute>() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DrawPropertyLayout(GUIContent label)
|
||||||
|
{
|
||||||
|
Rect labelRect;
|
||||||
|
Rect contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect);
|
||||||
|
{
|
||||||
|
var showLabels = !this.isMatrixChild && SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 185;
|
||||||
|
GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth);
|
||||||
|
this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null);
|
||||||
|
this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null);
|
||||||
|
this.ValueEntry.Property.Children[2].Draw(showLabels ? GUIHelper.TempContent("Z") : null);
|
||||||
|
this.ValueEntry.Property.Children[3].Draw(showLabels ? GUIHelper.TempContent("W") : null);
|
||||||
|
GUIHelper.PopLabelWidth();
|
||||||
|
|
||||||
|
}
|
||||||
|
SirenixEditorGUI.EndHorizontalPropertyLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"name": "Sirenix.OdinInspector.Modules.UnityMathematics",
|
||||||
|
"references": [ "Unity.Mathematics", "Sirenix.OdinInspector.Attributes", "Sirenix.OdinInspector.Editor", "Sirenix.Utilities", "Sirenix.Utilities.Editor" ],
|
||||||
|
"includePlatforms": [ "Editor" ],
|
||||||
|
"excludePlatforms": [],
|
||||||
|
"allowUnsafeCode": true,
|
||||||
|
"autoReferenced": true,
|
||||||
|
"overrideReferences": false,
|
||||||
|
"precompiledReferences": [ "Sirenix.Utilities.dll", "Sirenix.Utilities.Editor.dll", "Sirenix.OdinInspector.Attributes.dll", "Sirenix.OdinInspector.Editor.dll", "Sirenix.Serialization.dll" ],
|
||||||
|
"defineConstraints": []
|
||||||
|
}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
ManifestVersion: 1
|
||||||
|
ModuleID: Unity.Mathematics
|
||||||
|
ModuleVersion: 1.0.1.0
|
||||||
|
ModuleFiles:
|
||||||
|
MathematicsDrawers.cs
|
||||||
|
MathematicsDrawers.cs.meta
|
||||||
|
Sirenix.OdinInspector.Modules.UnityMathematics.asmdef
|
||||||
|
Sirenix.OdinInspector.Modules.UnityMathematics.asmdef.meta
|
||||||
@ -0,0 +1,134 @@
|
|||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// <copyright file="AssemblyImportSettingsAutomation.cs" company="Sirenix IVS">
|
||||||
|
// Copyright (c) Sirenix IVS. All rights reserved.
|
||||||
|
// </copyright>
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if UNITY_EDITOR && UNITY_5_6_OR_NEWER
|
||||||
|
|
||||||
|
namespace Sirenix.OdinInspector.Editor
|
||||||
|
{
|
||||||
|
using System.IO;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Sirenix.Serialization.Utilities.Editor;
|
||||||
|
using Sirenix.Utilities;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEditor.Build;
|
||||||
|
|
||||||
|
#if UNITY_2018_1_OR_NEWER
|
||||||
|
using UnityEditor.Build.Reporting;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public class AssemblyImportSettingsAutomation :
|
||||||
|
#if UNITY_2018_1_OR_NEWER
|
||||||
|
IPreprocessBuildWithReport
|
||||||
|
#else
|
||||||
|
IPreprocessBuild
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
|
||||||
|
public int callbackOrder { get { return -1500; } }
|
||||||
|
|
||||||
|
private static void ConfigureImportSettings()
|
||||||
|
{
|
||||||
|
if (EditorOnlyModeConfig.Instance.IsEditorOnlyModeEnabled() || ImportSettingsConfig.Instance.AutomateBeforeBuild == false)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var assemblyDir = new DirectoryInfo(SirenixAssetPaths.SirenixAssembliesPath).FullName;
|
||||||
|
var projectAssetsPath = Directory.GetCurrentDirectory().TrimEnd('\\', '/');
|
||||||
|
|
||||||
|
var isPackage = PathUtilities.HasSubDirectory(new DirectoryInfo(projectAssetsPath), new DirectoryInfo(assemblyDir)) == false;
|
||||||
|
|
||||||
|
var aotDirPath = assemblyDir + "NoEmitAndNoEditor/";
|
||||||
|
var jitDirPath = assemblyDir + "NoEditor/";
|
||||||
|
|
||||||
|
var aotDir = new DirectoryInfo(aotDirPath);
|
||||||
|
var jitDir = new DirectoryInfo(jitDirPath);
|
||||||
|
|
||||||
|
var aotAssemblies = new List<string>();
|
||||||
|
var jitAssemblies = new List<string>();
|
||||||
|
|
||||||
|
foreach (var file in aotDir.GetFiles("*.dll"))
|
||||||
|
{
|
||||||
|
string path = file.FullName;
|
||||||
|
if (isPackage)
|
||||||
|
{
|
||||||
|
path = SirenixAssetPaths.SirenixAssembliesPath.TrimEnd('\\', '/') + "/" + path.Substring(assemblyDir.Length);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
path = path.Substring(projectAssetsPath.Length + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
aotAssemblies.Add(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var file in jitDir.GetFiles("*.dll"))
|
||||||
|
{
|
||||||
|
string path = file.FullName;
|
||||||
|
if (isPackage)
|
||||||
|
{
|
||||||
|
path = SirenixAssetPaths.SirenixAssembliesPath.TrimEnd('\\', '/') + "/" + path.Substring(assemblyDir.Length);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
path = path.Substring(projectAssetsPath.Length + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
jitAssemblies.Add(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetDatabase.StartAssetEditing();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var platform = EditorUserBuildSettings.activeBuildTarget;
|
||||||
|
|
||||||
|
if (AssemblyImportSettingsUtilities.IsJITSupported(
|
||||||
|
platform,
|
||||||
|
AssemblyImportSettingsUtilities.GetCurrentScriptingBackend(),
|
||||||
|
AssemblyImportSettingsUtilities.GetCurrentApiCompatibilityLevel()))
|
||||||
|
{
|
||||||
|
ApplyImportSettings(platform, aotAssemblies.ToArray(), OdinAssemblyImportSettings.ExcludeFromAll);
|
||||||
|
ApplyImportSettings(platform, jitAssemblies.ToArray(), OdinAssemblyImportSettings.IncludeInBuildOnly);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ApplyImportSettings(platform, aotAssemblies.ToArray(), OdinAssemblyImportSettings.IncludeInBuildOnly);
|
||||||
|
ApplyImportSettings(platform, jitAssemblies.ToArray(), OdinAssemblyImportSettings.ExcludeFromAll);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AssetDatabase.StopAssetEditing();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ApplyImportSettings(BuildTarget platform, string[] assemblyPaths, OdinAssemblyImportSettings importSettings)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < assemblyPaths.Length; i++)
|
||||||
|
{
|
||||||
|
AssemblyImportSettingsUtilities.SetAssemblyImportSettings(platform, assemblyPaths[i], importSettings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if UNITY_2018_1_OR_NEWER
|
||||||
|
|
||||||
|
void IPreprocessBuildWithReport.OnPreprocessBuild(BuildReport report)
|
||||||
|
{
|
||||||
|
ConfigureImportSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
void IPreprocessBuild.OnPreprocessBuild(BuildTarget target, string path)
|
||||||
|
{
|
||||||
|
ConfigureImportSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // UNITY_EDITOR && UNITY_5_6_OR_NEWER
|
||||||
@ -0,0 +1,79 @@
|
|||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// <copyright file="BuildAOTAutomation.cs" company="Sirenix IVS">
|
||||||
|
// Copyright (c) Sirenix IVS. All rights reserved.
|
||||||
|
// </copyright>
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if UNITY_EDITOR && UNITY_5_6_OR_NEWER
|
||||||
|
|
||||||
|
namespace Sirenix.Serialization.Internal
|
||||||
|
{
|
||||||
|
using Sirenix.Serialization;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEditor.Build;
|
||||||
|
using System.IO;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
#if UNITY_2018_1_OR_NEWER
|
||||||
|
|
||||||
|
using UnityEditor.Build.Reporting;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNITY_2018_1_OR_NEWER
|
||||||
|
public class PreBuildAOTAutomation : IPreprocessBuildWithReport
|
||||||
|
#else
|
||||||
|
public class PreBuildAOTAutomation : IPreprocessBuild
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
public int callbackOrder { get { return -1000; } }
|
||||||
|
|
||||||
|
public void OnPreprocessBuild(BuildTarget target, string path)
|
||||||
|
{
|
||||||
|
if (AOTGenerationConfig.Instance.ShouldAutomationGeneration(target))
|
||||||
|
{
|
||||||
|
AOTGenerationConfig.Instance.ScanProject();
|
||||||
|
AOTGenerationConfig.Instance.GenerateDLL();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if UNITY_2018_1_OR_NEWER
|
||||||
|
|
||||||
|
public void OnPreprocessBuild(BuildReport report)
|
||||||
|
{
|
||||||
|
this.OnPreprocessBuild(report.summary.platform, report.summary.outputPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if UNITY_2018_1_OR_NEWER
|
||||||
|
public class PostBuildAOTAutomation : IPostprocessBuildWithReport
|
||||||
|
#else
|
||||||
|
public class PostBuildAOTAutomation : IPostprocessBuild
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
public int callbackOrder { get { return -1000; } }
|
||||||
|
|
||||||
|
public void OnPostprocessBuild(BuildTarget target, string path)
|
||||||
|
{
|
||||||
|
if (AOTGenerationConfig.Instance.DeleteDllAfterBuilds && AOTGenerationConfig.Instance.ShouldAutomationGeneration(target))
|
||||||
|
{
|
||||||
|
Directory.Delete(AOTGenerationConfig.Instance.AOTFolderPath, true);
|
||||||
|
File.Delete(AOTGenerationConfig.Instance.AOTFolderPath.TrimEnd('/', '\\') + ".meta");
|
||||||
|
AssetDatabase.Refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if UNITY_2018_1_OR_NEWER
|
||||||
|
|
||||||
|
public void OnPostprocessBuild(BuildReport report)
|
||||||
|
{
|
||||||
|
this.OnPostprocessBuild(report.summary.platform, report.summary.outputPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // UNITY_EDITOR && UNITY_5_6_OR_NEWER
|
||||||
@ -0,0 +1,121 @@
|
|||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// <copyright file="EnsureOdinInspectorDefine.cs" company="Sirenix IVS">
|
||||||
|
// Copyright (c) Sirenix IVS. All rights reserved.
|
||||||
|
// </copyright>
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
|
||||||
|
namespace Sirenix.Utilities
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the ODIN_INSPECTOR symbol.
|
||||||
|
/// </summary>
|
||||||
|
internal static class EnsureOdinInspectorDefine
|
||||||
|
{
|
||||||
|
private static readonly string[] DEFINES = new string[] { "ODIN_INSPECTOR", "ODIN_INSPECTOR_3" };
|
||||||
|
|
||||||
|
[InitializeOnLoadMethod]
|
||||||
|
private static void EnsureScriptingDefineSymbol()
|
||||||
|
{
|
||||||
|
var currentTarget = EditorUserBuildSettings.selectedBuildTargetGroup;
|
||||||
|
|
||||||
|
if (currentTarget == BuildTargetGroup.Unknown)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var definesString = PlayerSettings.GetScriptingDefineSymbolsForGroup(currentTarget).Trim();
|
||||||
|
var defines = definesString.Split(';');
|
||||||
|
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
foreach (var define in DEFINES)
|
||||||
|
{
|
||||||
|
if (defines.Contains(define) == false)
|
||||||
|
{
|
||||||
|
if (definesString.EndsWith(";", StringComparison.InvariantCulture) == false)
|
||||||
|
{
|
||||||
|
definesString += ";";
|
||||||
|
}
|
||||||
|
|
||||||
|
definesString += define;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed)
|
||||||
|
{
|
||||||
|
PlayerSettings.SetScriptingDefineSymbolsForGroup(currentTarget, definesString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// If you have a project where only some users have Odin, and you want to utilize the ODIN_INSPECTOR
|
||||||
|
// define symbol. Then, in order to only define the symbol for those with Odin, you can delete this script,
|
||||||
|
// which prevent ODIN_INSPECTOR from being added to the Unity's player settings.
|
||||||
|
//
|
||||||
|
// And instead automatically add the ODIN_INSPECTOR define to an mcs.rsp file if Odin exists using the script below.
|
||||||
|
// You can then ignore the mcs.rsp file in source control.
|
||||||
|
//
|
||||||
|
// Remember to manually remove the ODIN_INSPECTOR define symbol in player settings after removing this script.
|
||||||
|
//
|
||||||
|
// static class AddOdinInspectorDefineIfOdinExist
|
||||||
|
// {
|
||||||
|
// private const string ODIN_MCS_DEFINE = "-define:ODIN_INSPECTOR";
|
||||||
|
//
|
||||||
|
// [InitializeOnLoadMethod]
|
||||||
|
// private static void AddOrRemoveOdinDefine()
|
||||||
|
// {
|
||||||
|
// var addDefine = AppDomain.CurrentDomain.GetAssemblies().Any(x => x.FullName.StartsWith("Sirenix.OdinInspector.Editor"));
|
||||||
|
//
|
||||||
|
// #if ODIN_INSPECTOR
|
||||||
|
// var hasDefine = true;
|
||||||
|
// #else
|
||||||
|
// var hasDefine = false;
|
||||||
|
// #endif
|
||||||
|
//
|
||||||
|
// if (addDefine == hasDefine)
|
||||||
|
// {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// var mcsPath = Path.Combine(Application.dataPath, "mcs.rsp");
|
||||||
|
// var hasMcsFile = File.Exists(mcsPath);
|
||||||
|
//
|
||||||
|
// if (addDefine)
|
||||||
|
// {
|
||||||
|
// var lines = hasMcsFile ? File.ReadAllLines(mcsPath).ToList() : new List<string>();
|
||||||
|
// if (!lines.Any(x => x.Trim() == ODIN_MCS_DEFINE))
|
||||||
|
// {
|
||||||
|
// lines.Add(ODIN_MCS_DEFINE);
|
||||||
|
// File.WriteAllLines(mcsPath, lines.ToArray());
|
||||||
|
// AssetDatabase.Refresh();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// else if (hasMcsFile)
|
||||||
|
// {
|
||||||
|
// var linesWithoutOdinDefine = File.ReadAllLines(mcsPath).Where(x => x.Trim() != ODIN_MCS_DEFINE).ToArray();
|
||||||
|
//
|
||||||
|
// if (linesWithoutOdinDefine.Length == 0)
|
||||||
|
// {
|
||||||
|
// // Optional - Remove the mcs file instead if it doesn't contain any lines.
|
||||||
|
// File.Delete(mcsPath);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// File.WriteAllLines(mcsPath, linesWithoutOdinDefine);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// AssetDatabase.Refresh();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // UNITY_EDITOR
|
||||||
@ -0,0 +1,208 @@
|
|||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// <copyright file="FixBrokenUnityObjectWrapperDrawer.cs" company="Sirenix IVS">
|
||||||
|
// Copyright (c) Sirenix IVS. All rights reserved.
|
||||||
|
// </copyright>
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if UNITY_EDITOR && UNITY_2018_3_OR_NEWER
|
||||||
|
#pragma warning disable
|
||||||
|
|
||||||
|
namespace Sirenix.OdinInspector.Editor.Drawers
|
||||||
|
{
|
||||||
|
using Sirenix.OdinInspector;
|
||||||
|
using Sirenix.OdinInspector.Editor;
|
||||||
|
using Sirenix.Utilities;
|
||||||
|
using Sirenix.Utilities.Editor;
|
||||||
|
using System.Linq;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
[DrawerPriority(0.001, 0, 0)]
|
||||||
|
public class FixBrokenUnityObjectWrapperDrawer<T> : OdinValueDrawer<T>, IDefinesGenericMenuItems
|
||||||
|
where T : UnityEngine.Component
|
||||||
|
{
|
||||||
|
private const string AUTO_FIX_PREFS_KEY = "TemporarilyBrokenUnityObjectWrapperDrawer.autoFix";
|
||||||
|
|
||||||
|
private bool isBroken = false;
|
||||||
|
private T realWrapperInstance;
|
||||||
|
private bool allowSceneViewObjects;
|
||||||
|
private static bool autoFix;
|
||||||
|
|
||||||
|
protected override void Initialize()
|
||||||
|
{
|
||||||
|
this.allowSceneViewObjects = this.ValueEntry.Property.GetAttribute<AssetsOnlyAttribute>() == null;
|
||||||
|
autoFix = EditorPrefs.HasKey(AUTO_FIX_PREFS_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DrawPropertyLayout(GUIContent label)
|
||||||
|
{
|
||||||
|
if (!(this.ValueEntry.ValueState == PropertyValueState.NullReference || this.ValueEntry.ValueState == PropertyValueState.ReferenceValueConflict))
|
||||||
|
{
|
||||||
|
this.CallNextDrawer(label);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Event.current.type == EventType.Layout)
|
||||||
|
{
|
||||||
|
this.isBroken = false;
|
||||||
|
var count = this.ValueEntry.ValueCount;
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
var component = this.ValueEntry.Values[i];
|
||||||
|
|
||||||
|
if (ComponentIsBroken(component, ref this.realWrapperInstance))
|
||||||
|
{
|
||||||
|
this.isBroken = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isBroken && autoFix)
|
||||||
|
{
|
||||||
|
this.isBroken = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < this.ValueEntry.ValueCount; i++)
|
||||||
|
{
|
||||||
|
T fixedComponent = null;
|
||||||
|
if (ComponentIsBroken(this.ValueEntry.Values[i], ref fixedComponent) && fixedComponent)
|
||||||
|
{
|
||||||
|
(this.ValueEntry as IValueEntryActualValueSetter<T>).SetActualValue(i, fixedComponent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ValueEntry.Update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.isBroken)
|
||||||
|
{
|
||||||
|
this.CallNextDrawer(label);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var rect = EditorGUILayout.GetControlRect(label != null);
|
||||||
|
var btnRect = rect.AlignRight(20);
|
||||||
|
var controlRect = rect.SetXMax(btnRect.xMin - 5);
|
||||||
|
|
||||||
|
object newInstance = null;
|
||||||
|
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
{
|
||||||
|
if (this.ValueEntry.BaseValueType.IsInterface)
|
||||||
|
{
|
||||||
|
newInstance = SirenixEditorFields.PolymorphicObjectField(controlRect,
|
||||||
|
label,
|
||||||
|
this.realWrapperInstance,
|
||||||
|
this.ValueEntry.BaseValueType,
|
||||||
|
this.allowSceneViewObjects);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newInstance = SirenixEditorFields.UnityObjectField(
|
||||||
|
controlRect,
|
||||||
|
label,
|
||||||
|
this.realWrapperInstance,
|
||||||
|
this.ValueEntry.BaseValueType,
|
||||||
|
this.allowSceneViewObjects) as Component;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (EditorGUI.EndChangeCheck())
|
||||||
|
{
|
||||||
|
this.ValueEntry.WeakSmartValue = newInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GUI.Button(btnRect, " ", EditorStyles.miniButton))
|
||||||
|
{
|
||||||
|
var popup = new FixBrokenUnityObjectWrapperPopup(this.ValueEntry);
|
||||||
|
OdinEditorWindow.InspectObjectInDropDown(popup, 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Event.current.type == EventType.Repaint)
|
||||||
|
{
|
||||||
|
GUI.DrawTexture(btnRect, EditorIcons.ConsoleWarnicon, ScaleMode.ScaleToFit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool ComponentIsBroken(T component, ref T realInstance)
|
||||||
|
{
|
||||||
|
var uObj = component;
|
||||||
|
var oObj = (object)uObj;
|
||||||
|
|
||||||
|
if (oObj != null && uObj == null)
|
||||||
|
{
|
||||||
|
var instanceId = uObj.GetInstanceID();
|
||||||
|
if (AssetDatabase.Contains(instanceId))
|
||||||
|
{
|
||||||
|
var path = AssetDatabase.GetAssetPath(instanceId);
|
||||||
|
var realWrapper = AssetDatabase.LoadAllAssetsAtPath(path).FirstOrDefault(n => n.GetInstanceID() == instanceId) as T;
|
||||||
|
if (realWrapper)
|
||||||
|
{
|
||||||
|
realInstance = realWrapper;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PopulateGenericMenu(InspectorProperty property, GenericMenu genericMenu)
|
||||||
|
{
|
||||||
|
if (EditorPrefs.HasKey(AUTO_FIX_PREFS_KEY))
|
||||||
|
{
|
||||||
|
genericMenu.AddItem(new GUIContent("Disable auto-fix of broken prefab instance references"), false, (x) =>
|
||||||
|
{
|
||||||
|
EditorPrefs.DeleteKey(AUTO_FIX_PREFS_KEY);
|
||||||
|
autoFix = false;
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TypeInfoBox("This asset reference is temporarily broken until the next reload, because of an error in Unity where the C# wrapper object of a prefab asset is destroyed when changes are made to that prefab asset. This error has been reported to Unity.\n\nMeanwhile, Odin can fix this for you by getting a new, valid wrapper object from the asset database and replacing the broken wrapper instance with the new one.")]
|
||||||
|
private class FixBrokenUnityObjectWrapperPopup
|
||||||
|
{
|
||||||
|
private IPropertyValueEntry<T> valueEntry;
|
||||||
|
|
||||||
|
public FixBrokenUnityObjectWrapperPopup(IPropertyValueEntry<T> valueEntry)
|
||||||
|
{
|
||||||
|
this.valueEntry = valueEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HorizontalGroup, Button(ButtonSizes.Large)]
|
||||||
|
public void FixItThisTime()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < this.valueEntry.ValueCount; i++)
|
||||||
|
{
|
||||||
|
var localI = i;
|
||||||
|
T fixedComponent = null;
|
||||||
|
if (ComponentIsBroken(this.valueEntry.Values[i], ref fixedComponent) && fixedComponent)
|
||||||
|
{
|
||||||
|
this.valueEntry.Property.Tree.DelayActionUntilRepaint(() =>
|
||||||
|
{
|
||||||
|
(this.valueEntry as IValueEntryActualValueSetter<T>).SetActualValue(localI, fixedComponent);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GUIHelper.CurrentWindow)
|
||||||
|
{
|
||||||
|
EditorApplication.delayCall += GUIHelper.CurrentWindow.Close;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HorizontalGroup, Button(ButtonSizes.Large)]
|
||||||
|
public void FixItAlways()
|
||||||
|
{
|
||||||
|
EditorPrefs.SetBool(AUTO_FIX_PREFS_KEY, true);
|
||||||
|
autoFix = true;
|
||||||
|
|
||||||
|
if (GUIHelper.CurrentWindow)
|
||||||
|
{
|
||||||
|
EditorApplication.delayCall += GUIHelper.CurrentWindow.Close;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"name": "Sirenix.OdinInspector.CompatibilityLayer.Editor",
|
||||||
|
"references": [
|
||||||
|
"Sirenix.OdinInspector.CompatibilityLayer"
|
||||||
|
],
|
||||||
|
"includePlatforms": [
|
||||||
|
"Editor"
|
||||||
|
],
|
||||||
|
"excludePlatforms": [],
|
||||||
|
"allowUnsafeCode": true,
|
||||||
|
"autoReferenced": true,
|
||||||
|
"overrideReferences": false,
|
||||||
|
"precompiledReferences": [],
|
||||||
|
"defineConstraints": []
|
||||||
|
}
|
||||||
@ -0,0 +1,88 @@
|
|||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// <copyright file="SyncListDrawer.cs" company="Sirenix IVS">
|
||||||
|
// Copyright (c) Sirenix IVS. All rights reserved.
|
||||||
|
// </copyright>
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if UNITY_EDITOR && !UNITY_2019_1_OR_NEWER
|
||||||
|
#pragma warning disable 0618
|
||||||
|
|
||||||
|
namespace Sirenix.OdinInspector.Editor.Drawers
|
||||||
|
{
|
||||||
|
using Sirenix.Utilities.Editor;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.Networking;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// SyncList property drawer.
|
||||||
|
/// </summary>
|
||||||
|
[DrawerPriority(0, 0, 2)]
|
||||||
|
public class SyncListDrawer<TList, TElement> : OdinValueDrawer<TList> where TList : SyncList<TElement>
|
||||||
|
{
|
||||||
|
private LocalPersistentContext<bool> visible;
|
||||||
|
|
||||||
|
protected override void Initialize()
|
||||||
|
{
|
||||||
|
this.visible = this.Property.Context.GetPersistent(this, "expanded", GeneralDrawerConfig.Instance.OpenListsByDefault);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draws the property.
|
||||||
|
/// </summary>
|
||||||
|
protected override void DrawPropertyLayout(GUIContent label)
|
||||||
|
{
|
||||||
|
var entry = this.ValueEntry;
|
||||||
|
var property = entry.Property;
|
||||||
|
int minCount = int.MaxValue;
|
||||||
|
int maxCount = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < entry.ValueCount; i++)
|
||||||
|
{
|
||||||
|
if (entry.Values[i].Count > maxCount)
|
||||||
|
{
|
||||||
|
maxCount = entry.Values[i].Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry.Values[i].Count < minCount)
|
||||||
|
{
|
||||||
|
minCount = entry.Values[i].Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SirenixEditorGUI.BeginHorizontalToolbar();
|
||||||
|
this.visible.Value = SirenixEditorGUI.Foldout(this.visible.Value, GUIHelper.TempContent("SyncList " + label.text + " [" + typeof(TList).Name + "]"));
|
||||||
|
EditorGUILayout.LabelField(GUIHelper.TempContent(minCount == maxCount ? (minCount == 0 ? "Empty" : minCount + " items") : minCount + " (" + maxCount + ") items"), SirenixGUIStyles.RightAlignedGreyMiniLabel);
|
||||||
|
SirenixEditorGUI.EndHorizontalToolbar();
|
||||||
|
|
||||||
|
if (SirenixEditorGUI.BeginFadeGroup(this.visible, this.visible.Value))
|
||||||
|
{
|
||||||
|
GUIHelper.PushGUIEnabled(false);
|
||||||
|
SirenixEditorGUI.BeginVerticalList();
|
||||||
|
{
|
||||||
|
var elementLabel = new GUIContent();
|
||||||
|
for (int i = 0; i < maxCount; i++)
|
||||||
|
{
|
||||||
|
SirenixEditorGUI.BeginListItem();
|
||||||
|
elementLabel.text = "Item " + i;
|
||||||
|
|
||||||
|
if (i < minCount)
|
||||||
|
{
|
||||||
|
property.Children[i].Draw(elementLabel);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EditorGUILayout.LabelField(elementLabel, SirenixEditorGUI.MixedValueDashChar);
|
||||||
|
}
|
||||||
|
SirenixEditorGUI.EndListItem();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SirenixEditorGUI.EndVerticalList();
|
||||||
|
GUIHelper.PopGUIEnabled();
|
||||||
|
}
|
||||||
|
SirenixEditorGUI.EndFadeGroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // UNITY_EDITOR && !UNITY_2019_1_OR_NEWER
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// <copyright file="SyncVarAttributeDrawer.cs" company="Sirenix IVS">
|
||||||
|
// Copyright (c) Sirenix IVS. All rights reserved.
|
||||||
|
// </copyright>
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if UNITY_EDITOR && !UNITY_2019_1_OR_NEWER
|
||||||
|
#pragma warning disable 0618
|
||||||
|
|
||||||
|
namespace Sirenix.OdinInspector.Editor.Drawers
|
||||||
|
{
|
||||||
|
using Sirenix.Utilities;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.Networking;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// SyncVar attribute drawer.
|
||||||
|
/// </summary>
|
||||||
|
public class SyncVarAttributeDrawer : OdinAttributeDrawer<SyncVarAttribute>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Draws the property.
|
||||||
|
/// </summary>
|
||||||
|
protected override void DrawPropertyLayout(GUIContent label)
|
||||||
|
{
|
||||||
|
GUILayout.BeginHorizontal();
|
||||||
|
{
|
||||||
|
GUILayout.BeginVertical();
|
||||||
|
{
|
||||||
|
this.CallNextDrawer(label);
|
||||||
|
}
|
||||||
|
GUILayout.EndVertical();
|
||||||
|
|
||||||
|
GUILayout.Label("SyncVar", EditorStyles.miniLabel, GUILayoutOptions.Width(52f));
|
||||||
|
}
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // UNITY_EDITOR && !UNITY_2019_1_OR_NEWER
|
||||||
@ -0,0 +1,73 @@
|
|||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// <copyright file="Vector2IntMinMaxAttributeDrawer.cs" company="Sirenix IVS">
|
||||||
|
// Copyright (c) Sirenix IVS. All rights reserved.
|
||||||
|
// </copyright>
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if UNITY_EDITOR && UNITY_2017_2_OR_NEWER
|
||||||
|
|
||||||
|
namespace Sirenix.OdinInspector.Editor.Drawers
|
||||||
|
{
|
||||||
|
using Sirenix.OdinInspector;
|
||||||
|
using Sirenix.OdinInspector.Editor;
|
||||||
|
using Sirenix.OdinInspector.Editor.ValueResolvers;
|
||||||
|
using Sirenix.Utilities;
|
||||||
|
using Sirenix.Utilities.Editor;
|
||||||
|
using System.Reflection;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draws Vector2Int properties marked with <see cref="MinMaxSliderAttribute"/>.
|
||||||
|
/// </summary>
|
||||||
|
public class Vector2IntMinMaxAttributeDrawer : OdinAttributeDrawer<MinMaxSliderAttribute, Vector2Int>
|
||||||
|
{
|
||||||
|
private ValueResolver<float> minGetter;
|
||||||
|
private ValueResolver<float> maxGetter;
|
||||||
|
private ValueResolver<Vector2Int> vector2IntMinMaxGetter;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes the drawer by resolving any optional references to members for min/max value.
|
||||||
|
/// </summary>
|
||||||
|
protected override void Initialize()
|
||||||
|
{
|
||||||
|
// Min member reference.
|
||||||
|
this.minGetter = ValueResolver.Get<float>(this.Property, this.Attribute.MinValueGetter, this.Attribute.MinValue);
|
||||||
|
this.maxGetter = ValueResolver.Get<float>(this.Property, this.Attribute.MaxValueGetter, this.Attribute.MaxValue);
|
||||||
|
|
||||||
|
// Min max member reference.
|
||||||
|
if (this.Attribute.MinMaxValueGetter != null)
|
||||||
|
{
|
||||||
|
this.vector2IntMinMaxGetter = ValueResolver.Get<Vector2Int>(this.Property, this.Attribute.MinMaxValueGetter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draws the property.
|
||||||
|
/// </summary>
|
||||||
|
protected override void DrawPropertyLayout(GUIContent label)
|
||||||
|
{
|
||||||
|
ValueResolver.DrawErrors(this.minGetter, this.maxGetter, this.vector2IntMinMaxGetter);
|
||||||
|
|
||||||
|
// Get the range of the slider from the attribute or from member references.
|
||||||
|
Vector2 range;
|
||||||
|
if (this.vector2IntMinMaxGetter != null && !this.vector2IntMinMaxGetter.HasError)
|
||||||
|
{
|
||||||
|
range = (Vector2)this.vector2IntMinMaxGetter.GetValue();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
range.x = this.minGetter.GetValue();
|
||||||
|
range.y = this.maxGetter.GetValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
Vector2 value = SirenixEditorFields.MinMaxSlider(label, (Vector2)this.ValueEntry.SmartValue, range, this.Attribute.ShowFields);
|
||||||
|
if (EditorGUI.EndChangeCheck())
|
||||||
|
{
|
||||||
|
this.ValueEntry.SmartValue = new Vector2Int((int)value.x, (int)value.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // UNITY_EDITOR && UNITY_2017_2_OR_NEWER
|
||||||
@ -0,0 +1,141 @@
|
|||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// <copyright file="VectorIntDrawers.cs" company="Sirenix IVS">
|
||||||
|
// Copyright (c) Sirenix IVS. All rights reserved.
|
||||||
|
// </copyright>
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if UNITY_EDITOR && UNITY_2017_2_OR_NEWER
|
||||||
|
|
||||||
|
namespace Sirenix.OdinInspector.Editor.Drawers
|
||||||
|
{
|
||||||
|
using Utilities.Editor;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Vector2Int proprety drawer.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class Vector2IntDrawer : OdinValueDrawer<Vector2Int>, IDefinesGenericMenuItems
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Draws the property.
|
||||||
|
/// </summary>
|
||||||
|
protected override void DrawPropertyLayout(GUIContent label)
|
||||||
|
{
|
||||||
|
Rect labelRect;
|
||||||
|
var contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect);
|
||||||
|
{
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
var val = SirenixEditorFields.VectorPrefixSlideRect(labelRect, (Vector2)this.ValueEntry.SmartValue);
|
||||||
|
if (EditorGUI.EndChangeCheck())
|
||||||
|
{
|
||||||
|
this.ValueEntry.SmartValue = new Vector2Int((int)val.x, (int)val.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
var showLabels = SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 185;
|
||||||
|
GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth);
|
||||||
|
this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null);
|
||||||
|
this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null);
|
||||||
|
GUIHelper.PopLabelWidth();
|
||||||
|
|
||||||
|
}
|
||||||
|
SirenixEditorGUI.EndHorizontalPropertyLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Populates the generic menu for the property.
|
||||||
|
/// </summary>
|
||||||
|
public void PopulateGenericMenu(InspectorProperty property, GenericMenu genericMenu)
|
||||||
|
{
|
||||||
|
Vector2Int value = (Vector2Int)property.ValueEntry.WeakSmartValue;
|
||||||
|
|
||||||
|
if (genericMenu.GetItemCount() > 0)
|
||||||
|
{
|
||||||
|
genericMenu.AddSeparator("");
|
||||||
|
}
|
||||||
|
genericMenu.AddItem(new GUIContent("Zero", "Set the vector to (0, 0)"), value == Vector2Int.zero, () => SetVector(property, Vector2Int.zero));
|
||||||
|
genericMenu.AddItem(new GUIContent("One", "Set the vector to (1, 1)"), value == Vector2Int.one, () => SetVector(property, Vector2Int.one));
|
||||||
|
genericMenu.AddSeparator("");
|
||||||
|
genericMenu.AddItem(new GUIContent("Right", "Set the vector to (1, 0)"), value == Vector2Int.right, () => SetVector(property, Vector2Int.right));
|
||||||
|
genericMenu.AddItem(new GUIContent("Left", "Set the vector to (-1, 0)"), value == Vector2Int.left, () => SetVector(property, Vector2Int.left));
|
||||||
|
genericMenu.AddItem(new GUIContent("Up", "Set the vector to (0, 1)"), value == Vector2Int.up, () => SetVector(property, Vector2Int.up));
|
||||||
|
genericMenu.AddItem(new GUIContent("Down", "Set the vector to (0, -1)"), value == Vector2Int.down, () => SetVector(property, Vector2Int.down));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetVector(InspectorProperty property, Vector2Int value)
|
||||||
|
{
|
||||||
|
property.Tree.DelayActionUntilRepaint(() =>
|
||||||
|
{
|
||||||
|
for (int i = 0; i < property.ValueEntry.ValueCount; i++)
|
||||||
|
{
|
||||||
|
property.ValueEntry.WeakValues[i] = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Vector3Int property drawer.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class Vector3IntDrawer : OdinValueDrawer<Vector3Int>, IDefinesGenericMenuItems
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Draws the property.
|
||||||
|
/// </summary>
|
||||||
|
protected override void DrawPropertyLayout(GUIContent label)
|
||||||
|
{
|
||||||
|
Rect labelRect;
|
||||||
|
var contentRect = SirenixEditorGUI.BeginHorizontalPropertyLayout(label, out labelRect);
|
||||||
|
{
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
var val = SirenixEditorFields.VectorPrefixSlideRect(labelRect, (Vector3)this.ValueEntry.SmartValue);
|
||||||
|
if (EditorGUI.EndChangeCheck())
|
||||||
|
{
|
||||||
|
this.ValueEntry.SmartValue = new Vector3Int((int)val.x, (int)val.y, (int)val.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
var showLabels = SirenixEditorFields.ResponsiveVectorComponentFields && contentRect.width >= 185;
|
||||||
|
GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth);
|
||||||
|
this.ValueEntry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null);
|
||||||
|
this.ValueEntry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null);
|
||||||
|
this.ValueEntry.Property.Children[2].Draw(showLabels ? GUIHelper.TempContent("Z") : null);
|
||||||
|
GUIHelper.PopLabelWidth();
|
||||||
|
|
||||||
|
}
|
||||||
|
SirenixEditorGUI.EndHorizontalPropertyLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Populates the generic menu for the property.
|
||||||
|
/// </summary>
|
||||||
|
public void PopulateGenericMenu(InspectorProperty property, GenericMenu genericMenu)
|
||||||
|
{
|
||||||
|
Vector3Int value = (Vector3Int)property.ValueEntry.WeakSmartValue;
|
||||||
|
|
||||||
|
if (genericMenu.GetItemCount() > 0)
|
||||||
|
{
|
||||||
|
genericMenu.AddSeparator("");
|
||||||
|
}
|
||||||
|
|
||||||
|
genericMenu.AddItem(new GUIContent("Zero", "Set the vector to (0, 0, 0)"), value == Vector3Int.zero, () => SetVector(property, Vector3Int.zero));
|
||||||
|
genericMenu.AddItem(new GUIContent("One", "Set the vector to (1, 1, 1)"), value == Vector3Int.one, () => SetVector(property, Vector3Int.one));
|
||||||
|
genericMenu.AddSeparator("");
|
||||||
|
genericMenu.AddItem(new GUIContent("Right", "Set the vector to (1, 0, 0)"), value == Vector3Int.right, () => SetVector(property, Vector3Int.right));
|
||||||
|
genericMenu.AddItem(new GUIContent("Left", "Set the vector to (-1, 0, 0)"), value == Vector3Int.left, () => SetVector(property, Vector3Int.left));
|
||||||
|
genericMenu.AddItem(new GUIContent("Up", "Set the vector to (0, 1, 0)"), value == Vector3Int.up, () => SetVector(property, Vector3Int.up));
|
||||||
|
genericMenu.AddItem(new GUIContent("Down", "Set the vector to (0, -1, 0)"), value == Vector3Int.down, () => SetVector(property, Vector3Int.down));
|
||||||
|
genericMenu.AddItem(new GUIContent("Forward", "Set the vector property to (0, 0, 1)"), value == new Vector3Int(0, 0, 1), () => SetVector(property, new Vector3Int(0, 0, 1)));
|
||||||
|
genericMenu.AddItem(new GUIContent("Back", "Set the vector property to (0, 0, -1)"), value == new Vector3Int(0, 0, -1), () => SetVector(property, new Vector3Int(0, 0, -1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetVector(InspectorProperty property, Vector3Int value)
|
||||||
|
{
|
||||||
|
property.Tree.DelayActionUntilRepaint(() =>
|
||||||
|
{
|
||||||
|
property.ValueEntry.WeakSmartValue = value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // UNITY_EDITOR && UNITY_2017_2_OR_NEWER
|
||||||
@ -0,0 +1,54 @@
|
|||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// <copyright file="VectorIntPropertyResolvers.cs" company="Sirenix IVS">
|
||||||
|
// Copyright (c) Sirenix IVS. All rights reserved.
|
||||||
|
// </copyright>
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if UNITY_EDITOR && UNITY_2017_2_OR_NEWER
|
||||||
|
|
||||||
|
namespace Sirenix.OdinInspector.Editor.Drawers
|
||||||
|
{
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public sealed class Vector2IntResolver : BaseMemberPropertyResolver<Vector2Int>
|
||||||
|
{
|
||||||
|
protected override InspectorPropertyInfo[] GetPropertyInfos()
|
||||||
|
{
|
||||||
|
return new InspectorPropertyInfo[]
|
||||||
|
{
|
||||||
|
InspectorPropertyInfo.CreateValue("x", 0, this.Property.ValueEntry.SerializationBackend,
|
||||||
|
new GetterSetter<Vector2Int, int>(
|
||||||
|
getter: (ref Vector2Int vec) => vec.x,
|
||||||
|
setter: (ref Vector2Int vec, int value) => vec.x = value)),
|
||||||
|
InspectorPropertyInfo.CreateValue("y", 0, this.Property.ValueEntry.SerializationBackend,
|
||||||
|
new GetterSetter<Vector2Int, int>(
|
||||||
|
getter: (ref Vector2Int vec) => vec.y,
|
||||||
|
setter: (ref Vector2Int vec, int value) => vec.y = value)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class Vector3IntResolver : BaseMemberPropertyResolver<Vector3Int>
|
||||||
|
{
|
||||||
|
protected override InspectorPropertyInfo[] GetPropertyInfos()
|
||||||
|
{
|
||||||
|
return new InspectorPropertyInfo[]
|
||||||
|
{
|
||||||
|
InspectorPropertyInfo.CreateValue("x", 0, this.Property.ValueEntry.SerializationBackend,
|
||||||
|
new GetterSetter<Vector3Int, int>(
|
||||||
|
getter: (ref Vector3Int vec) => vec.x,
|
||||||
|
setter: (ref Vector3Int vec, int value) => vec.x = value)),
|
||||||
|
InspectorPropertyInfo.CreateValue("y", 0, this.Property.ValueEntry.SerializationBackend,
|
||||||
|
new GetterSetter<Vector3Int, int>(
|
||||||
|
getter: (ref Vector3Int vec) => vec.y,
|
||||||
|
setter: (ref Vector3Int vec, int value) => vec.y = value)),
|
||||||
|
InspectorPropertyInfo.CreateValue("z", 0, this.Property.ValueEntry.SerializationBackend,
|
||||||
|
new GetterSetter<Vector3Int, int>(
|
||||||
|
getter: (ref Vector3Int vec) => vec.z,
|
||||||
|
setter: (ref Vector3Int vec, int value) => vec.z = value)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // UNITY_EDITOR && UNITY_2017_2_OR_NEWER
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// <copyright file="SerializedNetworkBehaviour.cs" company="Sirenix IVS">
|
||||||
|
// Copyright (c) Sirenix IVS. All rights reserved.
|
||||||
|
// </copyright>
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if !UNITY_2019_1_OR_NEWER
|
||||||
|
#pragma warning disable 0618
|
||||||
|
|
||||||
|
namespace Sirenix.OdinInspector
|
||||||
|
{
|
||||||
|
using Sirenix.Serialization;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.Networking;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A Unity NetworkBehaviour which is serialized by the Sirenix serialization system.
|
||||||
|
/// Please note that Odin's custom serialization only works for non-synced variables - [SyncVar] and SyncLists still have the same limitations.
|
||||||
|
/// </summary>
|
||||||
|
[ShowOdinSerializedPropertiesInInspector]
|
||||||
|
public abstract class SerializedNetworkBehaviour : NetworkBehaviour, ISerializationCallbackReceiver, ISupportsPrefabSerialization
|
||||||
|
{
|
||||||
|
[SerializeField, HideInInspector]
|
||||||
|
private SerializationData serializationData;
|
||||||
|
|
||||||
|
SerializationData ISupportsPrefabSerialization.SerializationData { get { return this.serializationData; } set { this.serializationData = value; } }
|
||||||
|
|
||||||
|
void ISerializationCallbackReceiver.OnAfterDeserialize()
|
||||||
|
{
|
||||||
|
UnitySerializationUtility.DeserializeUnityObject(this, ref this.serializationData);
|
||||||
|
this.OnAfterDeserialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
||||||
|
{
|
||||||
|
UnitySerializationUtility.SerializeUnityObject(this, ref this.serializationData);
|
||||||
|
this.OnBeforeSerialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked after deserialization has taken place.
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void OnAfterDeserialize()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked before serialization has taken place.
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void OnBeforeSerialize()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
|
||||||
|
[HideInTables]
|
||||||
|
[OnInspectorGUI, PropertyOrder(int.MinValue)]
|
||||||
|
private void InternalOnInspectorGUI()
|
||||||
|
{
|
||||||
|
EditorOnlyModeConfigUtility.InternalOnInspectorGUI(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // UNITY_2019_1_OR_NEWER
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"name": "Sirenix.OdinInspector.CompatibilityLayer",
|
||||||
|
"references": [],
|
||||||
|
"includePlatforms": [],
|
||||||
|
"excludePlatforms": [],
|
||||||
|
"allowUnsafeCode": true,
|
||||||
|
"autoReferenced": true,
|
||||||
|
"overrideReferences": false,
|
||||||
|
"precompiledReferences": [],
|
||||||
|
"defineConstraints": []
|
||||||
|
}
|
||||||
@ -0,0 +1,80 @@
|
|||||||
|
#if UNITY_2017_2_OR_NEWER
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// <copyright file="VectorIntFormatters.cs" company="Sirenix IVS">
|
||||||
|
// Copyright (c) Sirenix IVS. All rights reserved.
|
||||||
|
// </copyright>
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
[assembly: Sirenix.Serialization.RegisterFormatter(typeof(Sirenix.Serialization.Vector2IntFormatter))]
|
||||||
|
[assembly: Sirenix.Serialization.RegisterFormatter(typeof(Sirenix.Serialization.Vector3IntFormatter))]
|
||||||
|
namespace Sirenix.Serialization
|
||||||
|
{
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Custom formatter for the <see cref="Vector2Int"/> type.
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="Sirenix.Serialization.MinimalBaseFormatter{UnityEngine.Vector2Int}" />
|
||||||
|
public class Vector2IntFormatter : MinimalBaseFormatter<Vector2Int>
|
||||||
|
{
|
||||||
|
private static readonly Serializer<int> Serializer = Serialization.Serializer.Get<int>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads into the specified value using the specified reader.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value to read into.</param>
|
||||||
|
/// <param name="reader">The reader to use.</param>
|
||||||
|
protected override void Read(ref Vector2Int value, IDataReader reader)
|
||||||
|
{
|
||||||
|
value.x = Vector2IntFormatter.Serializer.ReadValue(reader);
|
||||||
|
value.y = Vector2IntFormatter.Serializer.ReadValue(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes from the specified value using the specified writer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value to write from.</param>
|
||||||
|
/// <param name="writer">The writer to use.</param>
|
||||||
|
protected override void Write(ref Vector2Int value, IDataWriter writer)
|
||||||
|
{
|
||||||
|
Vector2IntFormatter.Serializer.WriteValue(value.x, writer);
|
||||||
|
Vector2IntFormatter.Serializer.WriteValue(value.y, writer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Custom formatter for the <see cref="Vector3Int"/> type.
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="Sirenix.Serialization.MinimalBaseFormatter{UnityEngine.Vector3Int}" />
|
||||||
|
public class Vector3IntFormatter : MinimalBaseFormatter<Vector3Int>
|
||||||
|
{
|
||||||
|
private static readonly Serializer<int> Serializer = Serialization.Serializer.Get<int>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads into the specified value using the specified reader.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value to read into.</param>
|
||||||
|
/// <param name="reader">The reader to use.</param>
|
||||||
|
protected override void Read(ref Vector3Int value, IDataReader reader)
|
||||||
|
{
|
||||||
|
value.x = Vector3IntFormatter.Serializer.ReadValue(reader);
|
||||||
|
value.y = Vector3IntFormatter.Serializer.ReadValue(reader);
|
||||||
|
value.z = Vector3IntFormatter.Serializer.ReadValue(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes from the specified value using the specified writer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value to write from.</param>
|
||||||
|
/// <param name="writer">The writer to use.</param>
|
||||||
|
protected override void Write(ref Vector3Int value, IDataWriter writer)
|
||||||
|
{
|
||||||
|
Vector3IntFormatter.Serializer.WriteValue(value.x, writer);
|
||||||
|
Vector3IntFormatter.Serializer.WriteValue(value.y, writer);
|
||||||
|
Vector3IntFormatter.Serializer.WriteValue(value.z, writer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
35
Plugins/Sirenix/Readme.txt
Normal file
35
Plugins/Sirenix/Readme.txt
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
------------------------------------ Getting Started ------------------------------------
|
||||||
|
|
||||||
|
Open up the Getting Started guide from "Tools > Odin Inspector > Getting Started."
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------- Helpful Links -------------------------------------
|
||||||
|
|
||||||
|
Tutorials: https://odininspector.com/tutorials
|
||||||
|
API Documentaion: https://odininspector.com/documentation
|
||||||
|
Roadmap: https://odininspector.com/roadmap
|
||||||
|
Release Notes: https://odininspector.com/patch-notes
|
||||||
|
Issue Tracker: https://bitbucket.org/sirenix/odin-inspector
|
||||||
|
|
||||||
|
|
||||||
|
--------------------------------- Community and Support ---------------------------------
|
||||||
|
|
||||||
|
If you have any issues, suggestions or want advice, then you're more than welcome
|
||||||
|
to join us on Discord, or reach out to us by any other means.
|
||||||
|
|
||||||
|
Support: https://odininspector.com/support
|
||||||
|
Community Addons: https://odininspector.com/community-tools
|
||||||
|
Discord: https://discord.gg/AgDmStu
|
||||||
|
|
||||||
|
|
||||||
|
-------------------------------------- Thank you! ---------------------------------------
|
||||||
|
|
||||||
|
We really hope you like using Odin. Be sure to leave a review on the Asset Store,
|
||||||
|
that helps us out a lot!
|
||||||
|
|
||||||
|
Leave a review: https://assetstore.unity.com/packages/tools/utilities/odin-inspector-and-serializer-89041
|
||||||
|
|
||||||
|
|
||||||
|
Odin Inspector is published and developed by Sirenix.
|
||||||
|
|
||||||
|
Sirenix: Https://sirenix.net
|
||||||
75
README.md
75
README.md
@ -2,19 +2,62 @@ Unity Utility
|
|||||||
|
|
||||||
Contains a growing list of utility used in prototypes and game development
|
Contains a growing list of utility used in prototypes and game development
|
||||||
|
|
||||||
AudioEvent (ScriptableObject)
|
AudioEvent
|
||||||
SimpleAudioEvent (ScriptableObject)
|
AudioEvent
|
||||||
AudioEventInspector (CustomInspector)
|
SimpleAudioEvent
|
||||||
|
---
|
||||||
ObjectPool
|
Canvases
|
||||||
GenericPool
|
Components
|
||||||
|
Button
|
||||||
RangedFloat (CustomTypes)
|
Image
|
||||||
MinMaxRangeAttribute (Attributes)
|
Slider
|
||||||
RangedFloatDrawer (PropertyDrawer)
|
Text
|
||||||
|
Toggle
|
||||||
UI
|
UIBase
|
||||||
components
|
UISelectableBase
|
||||||
Base
|
|
||||||
Slider
|
Menu
|
||||||
Text
|
RebindActionUI
|
||||||
|
RebindReferences
|
||||||
|
RebindUI
|
||||||
|
---
|
||||||
|
Common
|
||||||
|
Settings
|
||||||
|
Singleton
|
||||||
|
Timer
|
||||||
|
TimerWrapper
|
||||||
|
---
|
||||||
|
Editor
|
||||||
|
Custom Inspector
|
||||||
|
AudioEventInspector
|
||||||
|
SaveManagerInspector
|
||||||
|
|
||||||
|
Property drawers
|
||||||
|
RangedFloatDrawer
|
||||||
|
SceneAutoLoader
|
||||||
|
---
|
||||||
|
Plugins
|
||||||
|
Odin inspector
|
||||||
|
---
|
||||||
|
RangedFloat
|
||||||
|
MinMaxRangeAttribute
|
||||||
|
RangedFloat
|
||||||
|
---
|
||||||
|
SaveSystem
|
||||||
|
GameData template
|
||||||
|
ISaveData
|
||||||
|
SaveManager
|
||||||
|
---
|
||||||
|
Utilities
|
||||||
|
Extensions
|
||||||
|
Collection
|
||||||
|
GameObject
|
||||||
|
InputAction
|
||||||
|
String
|
||||||
|
Transform
|
||||||
|
Vector
|
||||||
|
BindingsIcons
|
||||||
|
DontDestroyOnLoad
|
||||||
|
Helpers
|
||||||
|
SerializableDictionary
|
||||||
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
using AudioEvent;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.Events;
|
|
||||||
using UnityEngine.UI;
|
|
||||||
|
|
||||||
namespace UI
|
|
||||||
{
|
|
||||||
public class ButtonUIComponent : UIComponentBase
|
|
||||||
{
|
|
||||||
[SerializeField] private Button _button;
|
|
||||||
[SerializeField] private SimpleAudioEvent _clickSound;
|
|
||||||
[SerializeField] private AudioSource _audioSource;
|
|
||||||
|
|
||||||
private void Awake() => _button.onClick.AddListener(() => _clickSound.Play(_audioSource));
|
|
||||||
|
|
||||||
public void OnClick(UnityAction callback) => _button.onClick.AddListener(callback);
|
|
||||||
|
|
||||||
private void OnDestroy() => _button.onClick.RemoveAllListeners();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
using UnityEngine.Events;
|
|
||||||
using UnityEngine.UI;
|
|
||||||
|
|
||||||
namespace UI
|
|
||||||
{
|
|
||||||
public class SliderUIComponent : UIComponentBase
|
|
||||||
{
|
|
||||||
[SerializeField] private Slider _slider;
|
|
||||||
|
|
||||||
public void SetValue(float value, float max)
|
|
||||||
{
|
|
||||||
_slider.maxValue = max;
|
|
||||||
_slider.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetValue(float value) => _slider.value = value;
|
|
||||||
|
|
||||||
public float GetValue() => _slider.value;
|
|
||||||
|
|
||||||
public void OnValueChanged(UnityAction<float> callBack) => _slider.onValueChanged.AddListener(callBack);
|
|
||||||
|
|
||||||
private void OnDestroy() => _slider.onValueChanged?.RemoveAllListeners();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
using TMPro;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace UI
|
|
||||||
{
|
|
||||||
public class TextUIComponent : UIComponentBase
|
|
||||||
{
|
|
||||||
[SerializeField] private TMP_Text _text;
|
|
||||||
|
|
||||||
private string _initialText;
|
|
||||||
|
|
||||||
private void Awake() => _initialText = _text.text;
|
|
||||||
|
|
||||||
public void SetText(string newText) => _text.text = string.IsNullOrEmpty(newText) ? string.Empty : newText;
|
|
||||||
|
|
||||||
public void ResetText() => _text.text = _initialText;
|
|
||||||
|
|
||||||
public void AddText(string textToAdd) => _text.text += textToAdd;
|
|
||||||
|
|
||||||
public void HideText() => _text.text = string.Empty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace UI
|
|
||||||
{
|
|
||||||
public class UIComponentBase : MonoBehaviour
|
|
||||||
{
|
|
||||||
|
|
||||||
public void Show()
|
|
||||||
{
|
|
||||||
gameObject.Show();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Hide()
|
|
||||||
{
|
|
||||||
gameObject.Hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ToggleDisplay()
|
|
||||||
{
|
|
||||||
gameObject.SetActive(!gameObject.activeInHierarchy);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetActive(bool active)
|
|
||||||
{
|
|
||||||
gameObject.SetActive(active);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
98
Utilities/BindingsIconsUtil.cs
Normal file
98
Utilities/BindingsIconsUtil.cs
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Scriptables;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.InputSystem;
|
||||||
|
using static UnityEngine.InputSystem.InputSystem;
|
||||||
|
|
||||||
|
namespace Utilities
|
||||||
|
{
|
||||||
|
public static class BindingsIconsUtil
|
||||||
|
{
|
||||||
|
private static GamepadIcons xbox;
|
||||||
|
private static GamepadIcons ps4;
|
||||||
|
private static MouseKeyboardIcons mouseKeyboard;
|
||||||
|
|
||||||
|
private static void Init()
|
||||||
|
{
|
||||||
|
xbox = Resources.Load<GamepadIcons>("InputSystem/GamePadIcons_Xbox");
|
||||||
|
ps4 = Resources.Load<GamepadIcons>("InputSystem/GamePadIcons_PS");
|
||||||
|
mouseKeyboard = Resources.Load<MouseKeyboardIcons>("InputSystem/MouseKeyboardIcons");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Sprite GetSprite(string deviceLayoutName, string mainControlPath)
|
||||||
|
{
|
||||||
|
if (xbox == null) Init();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(deviceLayoutName) || string.IsNullOrEmpty(mainControlPath))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Sprite icon = default;
|
||||||
|
if (IsFirstLayoutBasedOnSecond(deviceLayoutName, "DualShockGamepad"))
|
||||||
|
{
|
||||||
|
icon = ps4.GetSprite(mainControlPath);
|
||||||
|
}
|
||||||
|
else if (IsFirstLayoutBasedOnSecond(deviceLayoutName, "Gamepad"))
|
||||||
|
{
|
||||||
|
icon = xbox.GetSprite(mainControlPath);
|
||||||
|
}
|
||||||
|
else if (IsFirstLayoutBasedOnSecond(deviceLayoutName, "Keyboard") || IsFirstLayoutBasedOnSecond(deviceLayoutName, "Mouse"))
|
||||||
|
{
|
||||||
|
icon = mouseKeyboard.GetSprite(mainControlPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Sprite GetSprite(InputAction inputAction, string deviceName)
|
||||||
|
{
|
||||||
|
if (inputAction == null || string.IsNullOrEmpty(deviceName))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var mainBindings = GetRelevantMainBindings(inputAction, deviceName, true);
|
||||||
|
if (!mainBindings.Any())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var mainBinding = mainBindings.First();
|
||||||
|
|
||||||
|
inputAction.GetBindingDisplayString(mainBinding, out var deviceLayoutName, out var mainControlPath);
|
||||||
|
|
||||||
|
return GetSprite(deviceLayoutName, mainControlPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// So we don't create an instance each time the next method is called
|
||||||
|
private static readonly List<int> RelevantMainBindings = new List<int>();
|
||||||
|
|
||||||
|
public static List<int> GetRelevantMainBindings(InputAction inputAction, string deviceName, bool checkUnrebindableBindings = false)
|
||||||
|
{
|
||||||
|
RelevantMainBindings.Clear();
|
||||||
|
if (inputAction.bindings.Count >= 4)
|
||||||
|
{
|
||||||
|
if (inputAction.bindings[0].isComposite)
|
||||||
|
{
|
||||||
|
if (deviceName == "Gamepad")
|
||||||
|
{
|
||||||
|
RelevantMainBindings.Add(inputAction.bindings.Count - 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 1; i < inputAction.bindings.Count - 2; i += 2)
|
||||||
|
{
|
||||||
|
RelevantMainBindings.Add(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RelevantMainBindings.Add(deviceName == "Gamepad" ? 2 : 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (inputAction.bindings.Count >= 2 && checkUnrebindableBindings)
|
||||||
|
{
|
||||||
|
RelevantMainBindings.Add(deviceName == "Gamepad" ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return RelevantMainBindings.ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
31
Utilities/DontDestroyOnLoadUtils.cs
Normal file
31
Utilities/DontDestroyOnLoadUtils.cs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using UnityEngine;
|
||||||
|
using Object = UnityEngine.Object;
|
||||||
|
|
||||||
|
namespace Utilities
|
||||||
|
{
|
||||||
|
public static class DontDestroyOnLoadUtils
|
||||||
|
{
|
||||||
|
private static readonly List<GameObject> ManagedObjects = new List<GameObject>();
|
||||||
|
|
||||||
|
public static void Add(GameObject gameObject)
|
||||||
|
{
|
||||||
|
ManagedObjects.Add(gameObject);
|
||||||
|
Object.DontDestroyOnLoad(gameObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DestroyAll(Func<GameObject, bool> filter = null)
|
||||||
|
{
|
||||||
|
foreach (GameObject managedObject in ManagedObjects.ToList())
|
||||||
|
{
|
||||||
|
if (filter != null && !filter.Invoke(managedObject))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Object.DestroyImmediate(managedObject);
|
||||||
|
}
|
||||||
|
ManagedObjects.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
26
Utilities/Extensions/CollectionExtensions.cs
Normal file
26
Utilities/Extensions/CollectionExtensions.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Utilities.Extensions
|
||||||
|
{
|
||||||
|
public static class CollectionExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a random element from the enumerable.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="thisIEnumerable">The enumerable to return a random element from.</param>
|
||||||
|
/// <typeparam name="T">The type of the enumerable.</typeparam>
|
||||||
|
/// <returns>A random element from the list, or the default type value if the list is empty.</returns>
|
||||||
|
public static T RandomElement<T>(this IEnumerable<T> thisIEnumerable)
|
||||||
|
{
|
||||||
|
T[] thisArray = thisIEnumerable as T[] ?? thisIEnumerable.ToArray();
|
||||||
|
|
||||||
|
if (!thisArray.Any())
|
||||||
|
return default;
|
||||||
|
|
||||||
|
int randomIndex = Random.Range(0, thisArray.Length);
|
||||||
|
return thisArray[randomIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
125
Utilities/Extensions/GameObjectExtensions.cs
Normal file
125
Utilities/Extensions/GameObjectExtensions.cs
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
#if FUSION_WEAVER
|
||||||
|
using Fusion;
|
||||||
|
#endif
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Utilities.Extensions
|
||||||
|
{
|
||||||
|
public static class GameObjectExtensions
|
||||||
|
{
|
||||||
|
public static int GetNumberOfComponents(this GameObject gameObject) =>
|
||||||
|
gameObject.GetComponentsInChildren<Component>().Length - 1;
|
||||||
|
|
||||||
|
public static void Show(this GameObject gameObject) => gameObject.SetActive(true);
|
||||||
|
|
||||||
|
public static void Hide(this GameObject gameObject) => gameObject.SetActive(false);
|
||||||
|
|
||||||
|
public static bool IsVisible(this GameObject gameObject) => gameObject.activeSelf;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// First, look in the parent if it has the component, then the current gameObject
|
||||||
|
/// This is done because entities have their collider a level lower than their parent game object with contains
|
||||||
|
/// most of their scripts.
|
||||||
|
/// </summary>
|
||||||
|
public static T GetComponentInEntity<T>(this GameObject gameObject) where T : Component
|
||||||
|
{
|
||||||
|
T component = gameObject.GetComponentInParent<T>();
|
||||||
|
|
||||||
|
if (!component)
|
||||||
|
{
|
||||||
|
component = gameObject.GetComponent<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!component)
|
||||||
|
{
|
||||||
|
component = gameObject.GetComponentInChildren<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!component)
|
||||||
|
{
|
||||||
|
component = gameObject.transform.parent.GetComponentInChildren<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static T GetOrAddComponent<T>(this GameObject gameObject) where T : Component
|
||||||
|
{
|
||||||
|
if (!gameObject.TryGetComponent(out T component))
|
||||||
|
{
|
||||||
|
component = gameObject.AddComponent<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static T GetComponentInParents<T>(this GameObject gameObject) where T : Component
|
||||||
|
{
|
||||||
|
T parentComponent = null;
|
||||||
|
|
||||||
|
GameObject currentParent = gameObject;
|
||||||
|
GameObject root = gameObject.GetRoot();
|
||||||
|
while (currentParent != root && currentParent.GetComponent<T>() == null && parentComponent == null)
|
||||||
|
{
|
||||||
|
currentParent = currentParent.GetParent();
|
||||||
|
parentComponent = currentParent.GetComponent<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return parentComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if FUSION_WEAVER
|
||||||
|
public static T GetComponentInEntity<T>(this NetworkObject gameObject) where T : Component
|
||||||
|
{
|
||||||
|
return gameObject.gameObject.GetComponentInEntity<T>();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public static GameObject GetParent(this GameObject gameObject)
|
||||||
|
{
|
||||||
|
var parent = gameObject.transform.parent;
|
||||||
|
return parent ? parent.gameObject : gameObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GameObject GetRoot(this GameObject gameObject)
|
||||||
|
{
|
||||||
|
var root = gameObject.transform.root;
|
||||||
|
return root ? root.gameObject : gameObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool CompareEntities(this GameObject gameObject, GameObject other)
|
||||||
|
{
|
||||||
|
return other == gameObject ||
|
||||||
|
other.GetParent() == gameObject ||
|
||||||
|
other.GetParent() == gameObject.GetParent() ||
|
||||||
|
other == gameObject.GetParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool HasTag(this GameObject gameObject)
|
||||||
|
{
|
||||||
|
return !gameObject.CompareTag("Untagged");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool AssignTagIfDoesNotHaveIt(this GameObject gameObject, string tag)
|
||||||
|
{
|
||||||
|
if (!gameObject.HasTag())
|
||||||
|
gameObject.tag = tag;
|
||||||
|
|
||||||
|
return gameObject.CompareTag(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool HasLayer(this GameObject gameObject)
|
||||||
|
{
|
||||||
|
return gameObject.layer != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool AssignLayerIfDoesNotHaveIt(this GameObject gameObject, int layer)
|
||||||
|
{
|
||||||
|
if (!gameObject.HasLayer())
|
||||||
|
gameObject.layer = layer;
|
||||||
|
|
||||||
|
return gameObject.layer == layer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
12
Utilities/Extensions/InputActionExtensions.cs
Normal file
12
Utilities/Extensions/InputActionExtensions.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.InputSystem;
|
||||||
|
|
||||||
|
namespace Utilities.Extensions
|
||||||
|
{
|
||||||
|
public static class InputActionExtensions
|
||||||
|
{
|
||||||
|
public static bool ReadBool(this InputAction action) => action.ReadValue<float>() != 0;
|
||||||
|
public static float ReadFloat(this InputAction action) => action.ReadValue<float>();
|
||||||
|
public static Vector2 ReadV2(this InputAction action) => action.ReadValue<Vector2>();
|
||||||
|
}
|
||||||
|
}
|
||||||
15
Utilities/Extensions/StringExtensions.cs
Normal file
15
Utilities/Extensions/StringExtensions.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
namespace Utilities.Extensions
|
||||||
|
{
|
||||||
|
public static class StringExtensions
|
||||||
|
{
|
||||||
|
public static string Capitalize(this string input) =>
|
||||||
|
input switch
|
||||||
|
{
|
||||||
|
null => string.Empty,
|
||||||
|
"" => string.Empty,
|
||||||
|
_ => input[0].ToString().ToUpper() + input.Substring(1)
|
||||||
|
};
|
||||||
|
|
||||||
|
public static bool IsNullOrEmpty(this string input) => string.IsNullOrEmpty(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
15
Utilities/Extensions/TransformExtensions.cs
Normal file
15
Utilities/Extensions/TransformExtensions.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Utilities.Extensions
|
||||||
|
{
|
||||||
|
public static class TransformExtensions
|
||||||
|
{
|
||||||
|
public static void DestroyChildren(this Transform t)
|
||||||
|
{
|
||||||
|
foreach (Transform child in t)
|
||||||
|
{
|
||||||
|
Object.Destroy(child.gameObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
58
Utilities/Extensions/VectorExtensions.cs
Normal file
58
Utilities/Extensions/VectorExtensions.cs
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Utilities.Extensions
|
||||||
|
{
|
||||||
|
public static class VectorExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Vector 2 from vector 3's x and y components
|
||||||
|
/// </summary>
|
||||||
|
public static Vector2 ToV2(this Vector3 vector) => vector.XY();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Vector 2 from vector 3's x and z components
|
||||||
|
/// </summary>
|
||||||
|
public static Vector2 FlatV3ToV2(this Vector3 vector) => vector.XZ();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Vector 3 removing the y component
|
||||||
|
/// </summary>
|
||||||
|
public static Vector3 Flat(this Vector3 vector) => new Vector3(vector.x, 0, vector.z);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Vector 3 from vector 2's x becoming x and y becoming z
|
||||||
|
/// </summary>
|
||||||
|
public static Vector3 V2ToFlatV3(this Vector2 vector) => new Vector3(vector.x, 0, vector.y);
|
||||||
|
|
||||||
|
public static Vector2 XY(this Vector3 vector) => new Vector2(vector.x, vector.y);
|
||||||
|
public static Vector2 XZ(this Vector3 vector) => new Vector2(vector.x, vector.z);
|
||||||
|
public static Vector2 YX(this Vector3 vector) => new Vector2(vector.y, vector.x);
|
||||||
|
public static Vector2 YZ(this Vector3 vector) => new Vector2(vector.y, vector.z);
|
||||||
|
public static Vector2 ZX(this Vector3 vector) => new Vector2(vector.z, vector.x);
|
||||||
|
public static Vector2 ZY(this Vector3 vector) => new Vector2(vector.z, vector.y);
|
||||||
|
|
||||||
|
public static Vector3Int ToVector3Int(this Vector3 input) =>
|
||||||
|
new Vector3Int((int) input.x, (int) input.y, (int) input.z);
|
||||||
|
|
||||||
|
public static float SqrDistance(Vector3 a, Vector3 b)
|
||||||
|
{
|
||||||
|
float num1 = a.x - b.x;
|
||||||
|
float num2 = a.y - b.y;
|
||||||
|
float num3 = a.z - b.z;
|
||||||
|
return (float) (num1 * (double) num1 + num2 * (double) num2 + num3 * (double) num3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float SqrDistanceWith(this Vector3 a, Vector3 b)
|
||||||
|
{
|
||||||
|
return SqrDistance(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inspired of reefwirrax's answer on https://answers.unity.com/questions/532297/rotate-a-vector-around-a-certain-point.html
|
||||||
|
public static Vector3 RotateAround(this Vector3 point, Vector3 pivot, Vector3 angles) {
|
||||||
|
var dir = point - pivot;
|
||||||
|
dir = Quaternion.Euler(angles) * dir;
|
||||||
|
point = dir + pivot;
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
Utilities/Helpers.cs
Normal file
18
Utilities/Helpers.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Utilities
|
||||||
|
{
|
||||||
|
public static class Helpers
|
||||||
|
{
|
||||||
|
private static readonly Dictionary<float, WaitForSeconds> WaitDictionary =
|
||||||
|
new Dictionary<float, WaitForSeconds>();
|
||||||
|
|
||||||
|
public static WaitForSeconds GetWait(float time)
|
||||||
|
{
|
||||||
|
if (WaitDictionary.TryGetValue(time, out var wait)) return wait;
|
||||||
|
WaitDictionary[time] = new WaitForSeconds(time);
|
||||||
|
return WaitDictionary[time];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user