You've already forked UniversalViewer
Initial files
This commit is contained in:
448
Assets/Scripts/HSVPicker/UtilityScripts/BoxSlider.cs
Normal file
448
Assets/Scripts/HSVPicker/UtilityScripts/BoxSlider.cs
Normal file
@@ -0,0 +1,448 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace HSVPicker
|
||||
{
|
||||
[AddComponentMenu("UI/BoxSlider", 35)]
|
||||
[RequireComponent(typeof(RectTransform))]
|
||||
public class BoxSlider : Selectable, IDragHandler, IInitializePotentialDragHandler, ICanvasElement
|
||||
{
|
||||
public enum Direction
|
||||
{
|
||||
LeftToRight,
|
||||
RightToLeft,
|
||||
BottomToTop,
|
||||
TopToBottom,
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class BoxSliderEvent : UnityEvent<float, float> { }
|
||||
|
||||
[SerializeField]
|
||||
private RectTransform m_HandleRect;
|
||||
public RectTransform handleRect { get { return m_HandleRect; } set { if (SetClass(ref m_HandleRect, value)) { UpdateCachedReferences(); UpdateVisuals(); } } }
|
||||
|
||||
[Space(6)]
|
||||
|
||||
[SerializeField]
|
||||
private float m_MinValue = 0;
|
||||
public float minValue { get { return m_MinValue; } set { if (SetStruct(ref m_MinValue, value)) { Set(m_Value); SetY (m_ValueY); UpdateVisuals(); } } }
|
||||
|
||||
[SerializeField]
|
||||
private float m_MaxValue = 1;
|
||||
public float maxValue { get { return m_MaxValue; } set { if (SetStruct(ref m_MaxValue, value)) { Set(m_Value); SetY (m_ValueY); UpdateVisuals(); } } }
|
||||
|
||||
[SerializeField]
|
||||
private bool m_WholeNumbers = false;
|
||||
public bool wholeNumbers { get { return m_WholeNumbers; } set { if (SetStruct(ref m_WholeNumbers, value)) { Set(m_Value); SetY (m_ValueY); UpdateVisuals(); } } }
|
||||
|
||||
[SerializeField]
|
||||
private float m_Value = 1f;
|
||||
public float value
|
||||
{
|
||||
get
|
||||
{
|
||||
if (wholeNumbers)
|
||||
return Mathf.Round(m_Value);
|
||||
return m_Value;
|
||||
}
|
||||
set
|
||||
{
|
||||
Set(value);
|
||||
}
|
||||
}
|
||||
|
||||
public float normalizedValue
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Mathf.Approximately(minValue, maxValue))
|
||||
return 0;
|
||||
return Mathf.InverseLerp(minValue, maxValue, value);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.value = Mathf.Lerp(minValue, maxValue, value);
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private float m_ValueY = 1f;
|
||||
public float valueY
|
||||
{
|
||||
get
|
||||
{
|
||||
if (wholeNumbers)
|
||||
return Mathf.Round(m_ValueY);
|
||||
return m_ValueY;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetY(value);
|
||||
}
|
||||
}
|
||||
|
||||
public float normalizedValueY
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Mathf.Approximately(minValue, maxValue))
|
||||
return 0;
|
||||
return Mathf.InverseLerp(minValue, maxValue, valueY);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.valueY = Mathf.Lerp(minValue, maxValue, value);
|
||||
}
|
||||
}
|
||||
|
||||
[Space(6)]
|
||||
|
||||
// Allow for delegate-based subscriptions for faster events than 'eventReceiver', and allowing for multiple receivers.
|
||||
[SerializeField]
|
||||
private BoxSliderEvent m_OnValueChanged = new BoxSliderEvent();
|
||||
public BoxSliderEvent onValueChanged { get { return m_OnValueChanged; } set { m_OnValueChanged = value; } }
|
||||
|
||||
// Private fields
|
||||
|
||||
//private Image m_FillImage;
|
||||
//private Transform m_FillTransform;
|
||||
//private RectTransform m_FillContainerRect;
|
||||
private Transform m_HandleTransform;
|
||||
private RectTransform m_HandleContainerRect;
|
||||
|
||||
// The offset from handle position to mouse down position
|
||||
private Vector2 m_Offset = Vector2.zero;
|
||||
|
||||
private DrivenRectTransformTracker m_Tracker;
|
||||
|
||||
// Size of each step.
|
||||
float stepSize { get { return wholeNumbers ? 1 : (maxValue - minValue) * 0.1f; } }
|
||||
|
||||
protected BoxSlider()
|
||||
{ }
|
||||
|
||||
#if UNITY_EDITOR
|
||||
protected override void OnValidate()
|
||||
{
|
||||
base.OnValidate();
|
||||
|
||||
if (wholeNumbers)
|
||||
{
|
||||
m_MinValue = Mathf.Round(m_MinValue);
|
||||
m_MaxValue = Mathf.Round(m_MaxValue);
|
||||
}
|
||||
|
||||
//Onvalidate is called before OnEnabled. We need to make sure not to touch any other objects before OnEnable is run.
|
||||
if (IsActive())
|
||||
{
|
||||
UpdateCachedReferences();
|
||||
Set(m_Value, false);
|
||||
SetY(m_ValueY, false);
|
||||
// Update rects since other things might affect them even if value didn't change.
|
||||
UpdateVisuals();
|
||||
}
|
||||
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
|
||||
if (!UnityEditor.PrefabUtility.IsPartOfPrefabAsset(this) && !Application.isPlaying)
|
||||
CanvasUpdateRegistry.RegisterCanvasElementForLayoutRebuild(this);
|
||||
|
||||
#else
|
||||
|
||||
var prefabType = UnityEditor.PrefabUtility.GetPrefabType(this);
|
||||
if (prefabType != UnityEditor.PrefabType.Prefab && !Application.isPlaying)
|
||||
CanvasUpdateRegistry.RegisterCanvasElementForLayoutRebuild(this);
|
||||
#endif
|
||||
}
|
||||
#endif // if UNITY_EDITOR
|
||||
|
||||
public virtual void Rebuild(CanvasUpdate executing)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (executing == CanvasUpdate.Prelayout)
|
||||
onValueChanged.Invoke(value, valueY);
|
||||
#endif
|
||||
}
|
||||
|
||||
public void LayoutComplete()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void GraphicUpdateComplete()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static bool SetClass<T>(ref T currentValue, T newValue) where T: class
|
||||
{
|
||||
if ((currentValue == null && newValue == null) || (currentValue != null && currentValue.Equals(newValue)))
|
||||
return false;
|
||||
|
||||
currentValue = newValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool SetStruct<T>(ref T currentValue, T newValue) where T: struct
|
||||
{
|
||||
if (currentValue.Equals(newValue))
|
||||
return false;
|
||||
|
||||
currentValue = newValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
UpdateCachedReferences();
|
||||
Set(m_Value, false);
|
||||
SetY(m_ValueY, false);
|
||||
// Update rects since they need to be initialized correctly.
|
||||
UpdateVisuals();
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
m_Tracker.Clear();
|
||||
base.OnDisable();
|
||||
}
|
||||
|
||||
void UpdateCachedReferences()
|
||||
{
|
||||
|
||||
if (m_HandleRect)
|
||||
{
|
||||
m_HandleTransform = m_HandleRect.transform;
|
||||
if (m_HandleTransform.parent != null)
|
||||
m_HandleContainerRect = m_HandleTransform.parent.GetComponent<RectTransform>();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_HandleContainerRect = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the valueUpdate the visible Image.
|
||||
void Set(float input)
|
||||
{
|
||||
Set(input, true);
|
||||
}
|
||||
|
||||
void Set(float input, bool sendCallback)
|
||||
{
|
||||
// Clamp the input
|
||||
float newValue = Mathf.Clamp(input, minValue, maxValue);
|
||||
if (wholeNumbers)
|
||||
newValue = Mathf.Round(newValue);
|
||||
|
||||
// If the stepped value doesn't match the last one, it's time to update
|
||||
if (m_Value.Equals(newValue))
|
||||
return;
|
||||
|
||||
m_Value = newValue;
|
||||
UpdateVisuals();
|
||||
if (sendCallback)
|
||||
m_OnValueChanged.Invoke(newValue, valueY);
|
||||
}
|
||||
|
||||
void SetY(float input)
|
||||
{
|
||||
SetY(input, true);
|
||||
}
|
||||
|
||||
void SetY(float input, bool sendCallback)
|
||||
{
|
||||
// Clamp the input
|
||||
float newValue = Mathf.Clamp(input, minValue, maxValue);
|
||||
if (wholeNumbers)
|
||||
newValue = Mathf.Round(newValue);
|
||||
|
||||
// If the stepped value doesn't match the last one, it's time to update
|
||||
if (m_ValueY.Equals(newValue))
|
||||
return;
|
||||
|
||||
m_ValueY = newValue;
|
||||
UpdateVisuals();
|
||||
if (sendCallback)
|
||||
m_OnValueChanged.Invoke(value, newValue);
|
||||
}
|
||||
|
||||
|
||||
protected override void OnRectTransformDimensionsChange()
|
||||
{
|
||||
base.OnRectTransformDimensionsChange();
|
||||
UpdateVisuals();
|
||||
}
|
||||
|
||||
enum Axis
|
||||
{
|
||||
Horizontal = 0,
|
||||
Vertical = 1
|
||||
}
|
||||
|
||||
|
||||
// Force-update the slider. Useful if you've changed the properties and want it to update visually.
|
||||
private void UpdateVisuals()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (!Application.isPlaying)
|
||||
UpdateCachedReferences();
|
||||
#endif
|
||||
|
||||
m_Tracker.Clear();
|
||||
|
||||
|
||||
//to business!
|
||||
if (m_HandleContainerRect != null)
|
||||
{
|
||||
m_Tracker.Add(this, m_HandleRect, DrivenTransformProperties.Anchors);
|
||||
Vector2 anchorMin = Vector2.zero;
|
||||
Vector2 anchorMax = Vector2.one;
|
||||
anchorMin[0] = anchorMax[0] = (normalizedValue);
|
||||
anchorMin[1] = anchorMax[1] = ( normalizedValueY);
|
||||
|
||||
m_HandleRect.anchorMin = anchorMin;
|
||||
m_HandleRect.anchorMax = anchorMax;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the slider's position based on the mouse.
|
||||
void UpdateDrag(PointerEventData eventData, Camera cam)
|
||||
{
|
||||
RectTransform clickRect = m_HandleContainerRect;
|
||||
if (clickRect != null && clickRect.rect.size[0] > 0)
|
||||
{
|
||||
Vector2 localCursor;
|
||||
if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(clickRect, eventData.position, cam, out localCursor))
|
||||
return;
|
||||
localCursor -= clickRect.rect.position;
|
||||
|
||||
float val = Mathf.Clamp01((localCursor - m_Offset)[0] / clickRect.rect.size[0]);
|
||||
normalizedValue = (val);
|
||||
|
||||
float valY = Mathf.Clamp01((localCursor - m_Offset)[1] / clickRect.rect.size[1]);
|
||||
normalizedValueY = ( valY);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private bool MayDrag(PointerEventData eventData)
|
||||
{
|
||||
return IsActive() && IsInteractable() && eventData.button == PointerEventData.InputButton.Left;
|
||||
}
|
||||
|
||||
public override void OnPointerDown(PointerEventData eventData)
|
||||
{
|
||||
if (!MayDrag(eventData))
|
||||
return;
|
||||
|
||||
base.OnPointerDown(eventData);
|
||||
|
||||
m_Offset = Vector2.zero;
|
||||
if (m_HandleContainerRect != null && RectTransformUtility.RectangleContainsScreenPoint(m_HandleRect, eventData.position, eventData.enterEventCamera))
|
||||
{
|
||||
Vector2 localMousePos;
|
||||
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(m_HandleRect, eventData.position, eventData.pressEventCamera, out localMousePos))
|
||||
m_Offset = localMousePos;
|
||||
m_Offset.y = -m_Offset.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Outside the slider handle - jump to this point instead
|
||||
UpdateDrag(eventData, eventData.pressEventCamera);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void OnDrag(PointerEventData eventData)
|
||||
{
|
||||
if (!MayDrag(eventData))
|
||||
return;
|
||||
|
||||
UpdateDrag(eventData, eventData.pressEventCamera);
|
||||
}
|
||||
|
||||
//public override void OnMove(AxisEventData eventData)
|
||||
//{
|
||||
// if (!IsActive() || !IsInteractable())
|
||||
// {
|
||||
// base.OnMove(eventData);
|
||||
// return;
|
||||
// }
|
||||
|
||||
// switch (eventData.moveDir)
|
||||
// {
|
||||
// case MoveDirection.Left:
|
||||
// if (axis == Axis.Horizontal && FindSelectableOnLeft() == null) {
|
||||
// Set(reverseValue ? value + stepSize : value - stepSize);
|
||||
// SetY (reverseValue ? valueY + stepSize : valueY - stepSize);
|
||||
// }
|
||||
// else
|
||||
// base.OnMove(eventData);
|
||||
// break;
|
||||
// case MoveDirection.Right:
|
||||
// if (axis == Axis.Horizontal && FindSelectableOnRight() == null) {
|
||||
// Set(reverseValue ? value - stepSize : value + stepSize);
|
||||
// SetY(reverseValue ? valueY - stepSize : valueY + stepSize);
|
||||
// }
|
||||
// else
|
||||
// base.OnMove(eventData);
|
||||
// break;
|
||||
// case MoveDirection.Up:
|
||||
// if (axis == Axis.Vertical && FindSelectableOnUp() == null) {
|
||||
// Set(reverseValue ? value - stepSize : value + stepSize);
|
||||
// SetY(reverseValue ? valueY - stepSize : valueY + stepSize);
|
||||
// }
|
||||
// else
|
||||
// base.OnMove(eventData);
|
||||
// break;
|
||||
// case MoveDirection.Down:
|
||||
// if (axis == Axis.Vertical && FindSelectableOnDown() == null) {
|
||||
// Set(reverseValue ? value + stepSize : value - stepSize);
|
||||
// SetY(reverseValue ? valueY + stepSize : valueY - stepSize);
|
||||
// }
|
||||
// else
|
||||
// base.OnMove(eventData);
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
|
||||
//public override Selectable FindSelectableOnLeft()
|
||||
//{
|
||||
// if (navigation.mode == Navigation.Mode.Automatic && axis == Axis.Horizontal)
|
||||
// return null;
|
||||
// return base.FindSelectableOnLeft();
|
||||
//}
|
||||
|
||||
//public override Selectable FindSelectableOnRight()
|
||||
//{
|
||||
// if (navigation.mode == Navigation.Mode.Automatic && axis == Axis.Horizontal)
|
||||
// return null;
|
||||
// return base.FindSelectableOnRight();
|
||||
//}
|
||||
|
||||
//public override Selectable FindSelectableOnUp()
|
||||
//{
|
||||
// if (navigation.mode == Navigation.Mode.Automatic && axis == Axis.Vertical)
|
||||
// return null;
|
||||
// return base.FindSelectableOnUp();
|
||||
//}
|
||||
|
||||
//public override Selectable FindSelectableOnDown()
|
||||
//{
|
||||
// if (navigation.mode == Navigation.Mode.Automatic && axis == Axis.Vertical)
|
||||
// return null;
|
||||
// return base.FindSelectableOnDown();
|
||||
//}
|
||||
|
||||
public virtual void OnInitializePotentialDrag(PointerEventData eventData)
|
||||
{
|
||||
eventData.useDragThreshold = false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 37c44bc94a9a7f241b5b552f3ff89458
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
210
Assets/Scripts/HSVPicker/UtilityScripts/HSVUtil.cs
Normal file
210
Assets/Scripts/HSVPicker/UtilityScripts/HSVUtil.cs
Normal file
@@ -0,0 +1,210 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
|
||||
namespace HSVPicker
|
||||
{
|
||||
|
||||
#region ColorUtilities
|
||||
|
||||
public static class HSVUtil
|
||||
{
|
||||
|
||||
public static HsvColor ConvertRgbToHsv(Color color)
|
||||
{
|
||||
return ConvertRgbToHsv((int)(color.r * 255), (int)(color.g * 255), (int)(color.b * 255));
|
||||
}
|
||||
|
||||
//Converts an RGB color to an HSV color.
|
||||
public static HsvColor ConvertRgbToHsv(double r, double b, double g)
|
||||
{
|
||||
double delta, min;
|
||||
double h = 0, s, v;
|
||||
|
||||
min = Math.Min(Math.Min(r, g), b);
|
||||
v = Math.Max(Math.Max(r, g), b);
|
||||
delta = v - min;
|
||||
|
||||
if (v.Equals(0))
|
||||
s = 0;
|
||||
else
|
||||
s = delta / v;
|
||||
|
||||
if (s.Equals(0))
|
||||
h = 360;
|
||||
else
|
||||
{
|
||||
if (r.Equals(v))
|
||||
h = (g - b) / delta;
|
||||
else if (g.Equals(v))
|
||||
h = 2 + (b - r) / delta;
|
||||
else if (b.Equals(v))
|
||||
h = 4 + (r - g) / delta;
|
||||
|
||||
h *= 60;
|
||||
if (h <= 0.0)
|
||||
h += 360;
|
||||
}
|
||||
|
||||
HsvColor hsvColor = new HsvColor();
|
||||
hsvColor.H = 360 - h;
|
||||
hsvColor.S = s;
|
||||
hsvColor.V = v / 255;
|
||||
|
||||
return hsvColor;
|
||||
|
||||
}
|
||||
|
||||
// Converts an HSV color to an RGB color.
|
||||
public static Color ConvertHsvToRgb(double h, double s, double v, float alpha)
|
||||
{
|
||||
|
||||
double r = 0, g = 0, b = 0;
|
||||
|
||||
if (s.Equals(0))
|
||||
{
|
||||
r = v;
|
||||
g = v;
|
||||
b = v;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
int i;
|
||||
double f, p, q, t;
|
||||
|
||||
|
||||
if (h.Equals(360))
|
||||
h = 0;
|
||||
else
|
||||
h = h / 60;
|
||||
|
||||
i = (int)(h);
|
||||
f = h - i;
|
||||
|
||||
p = v * (1.0 - s);
|
||||
q = v * (1.0 - (s * f));
|
||||
t = v * (1.0 - (s * (1.0f - f)));
|
||||
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
r = v;
|
||||
g = t;
|
||||
b = p;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
r = q;
|
||||
g = v;
|
||||
b = p;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
r = p;
|
||||
g = v;
|
||||
b = t;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
r = p;
|
||||
g = q;
|
||||
b = v;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
r = t;
|
||||
g = p;
|
||||
b = v;
|
||||
break;
|
||||
|
||||
default:
|
||||
r = v;
|
||||
g = p;
|
||||
b = q;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return new Color((float)r, (float)g, (float)b, alpha);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion ColorUtilities
|
||||
|
||||
|
||||
// Describes a color in terms of
|
||||
// Hue, Saturation, and Value (brightness)
|
||||
#region HsvColor
|
||||
public struct HsvColor
|
||||
{
|
||||
/// <summary>
|
||||
/// The Hue, ranges between 0 and 360
|
||||
/// </summary>
|
||||
public double H;
|
||||
|
||||
/// <summary>
|
||||
/// The saturation, ranges between 0 and 1
|
||||
/// </summary>
|
||||
public double S;
|
||||
|
||||
// The value (brightness), ranges between 0 and 1
|
||||
public double V;
|
||||
|
||||
public float normalizedH
|
||||
{
|
||||
get
|
||||
{
|
||||
return (float)H / 360f;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
H = (double)value * 360;
|
||||
}
|
||||
}
|
||||
|
||||
public float normalizedS
|
||||
{
|
||||
get
|
||||
{
|
||||
return (float)S;
|
||||
}
|
||||
set
|
||||
{
|
||||
S = (double)value;
|
||||
}
|
||||
}
|
||||
|
||||
public float normalizedV
|
||||
{
|
||||
get
|
||||
{
|
||||
return (float)V;
|
||||
}
|
||||
set
|
||||
{
|
||||
V = (double)value;
|
||||
}
|
||||
}
|
||||
|
||||
public HsvColor(double h, double s, double v)
|
||||
{
|
||||
this.H = h;
|
||||
this.S = s;
|
||||
this.V = v;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "{" + H.ToString("f2") + "," + S.ToString("f2") + "," + V.ToString("f2") + "}";
|
||||
}
|
||||
}
|
||||
#endregion HsvColor
|
||||
|
||||
|
||||
}
|
||||
|
||||
8
Assets/Scripts/HSVPicker/UtilityScripts/HSVUtil.cs.meta
Normal file
8
Assets/Scripts/HSVPicker/UtilityScripts/HSVUtil.cs.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4f3189246d7fc204faba7a1e9c08e0af
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
Reference in New Issue
Block a user