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
|
||||
|
||||
AudioEvent (ScriptableObject)
|
||||
SimpleAudioEvent (ScriptableObject)
|
||||
AudioEventInspector (CustomInspector)
|
||||
|
||||
ObjectPool
|
||||
GenericPool
|
||||
|
||||
RangedFloat (CustomTypes)
|
||||
MinMaxRangeAttribute (Attributes)
|
||||
RangedFloatDrawer (PropertyDrawer)
|
||||
|
||||
UI
|
||||
components
|
||||
Base
|
||||
Slider
|
||||
Text
|
||||
AudioEvent
|
||||
AudioEvent
|
||||
SimpleAudioEvent
|
||||
---
|
||||
Canvases
|
||||
Components
|
||||
Button
|
||||
Image
|
||||
Slider
|
||||
Text
|
||||
Toggle
|
||||
UIBase
|
||||
UISelectableBase
|
||||
|
||||
Menu
|
||||
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