源战役客户端
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 

600 строки
21 KiB

using UnityEngine;
using UnityEditor;
using System.Collections;
[System.Serializable]
public class ZoomArea
{
// Global state
private static Vector2 m_MouseDownPosition = new Vector2(-1000000, -1000000); // in transformed space
private static int zoomableAreaHash = "ZoomableArea".GetHashCode();
// Range lock settings
[SerializeField]
private bool m_HRangeLocked;
[SerializeField]
private bool m_VRangeLocked;
public bool hRangeLocked { get { return m_HRangeLocked; } set { m_HRangeLocked = value; } }
public bool vRangeLocked { get { return m_VRangeLocked; } set { m_VRangeLocked = value; } }
[SerializeField]
private float m_HBaseRangeMin = 0;
[SerializeField]
private float m_HBaseRangeMax = 1;
[SerializeField]
private float m_VBaseRangeMin = 0;
[SerializeField]
private float m_VBaseRangeMax = 1;
public float hBaseRangeMin { get { return m_HBaseRangeMin; } set { m_HBaseRangeMin = value; } }
public float hBaseRangeMax { get { return m_HBaseRangeMax; } set { m_HBaseRangeMax = value; } }
public float vBaseRangeMin { get { return m_VBaseRangeMin; } set { m_VBaseRangeMin = value; } }
public float vBaseRangeMax { get { return m_VBaseRangeMax; } set { m_VBaseRangeMax = value; } }
[SerializeField]
private bool m_HAllowExceedBaseRangeMin = true;
[SerializeField]
private bool m_HAllowExceedBaseRangeMax = true;
[SerializeField]
private bool m_VAllowExceedBaseRangeMin = true;
[SerializeField]
private bool m_VAllowExceedBaseRangeMax = true;
public bool hAllowExceedBaseRangeMin { get { return m_HAllowExceedBaseRangeMin; } set { m_HAllowExceedBaseRangeMin = value; } }
public bool hAllowExceedBaseRangeMax { get { return m_HAllowExceedBaseRangeMax; } set { m_HAllowExceedBaseRangeMax = value; } }
public bool vAllowExceedBaseRangeMin { get { return m_VAllowExceedBaseRangeMin; } set { m_VAllowExceedBaseRangeMin = value; } }
public bool vAllowExceedBaseRangeMax { get { return m_VAllowExceedBaseRangeMax; } set { m_VAllowExceedBaseRangeMax = value; } }
public float hRangeMin
{
get { return (hAllowExceedBaseRangeMin ? Mathf.NegativeInfinity : hBaseRangeMin); }
set { SetAllowExceed(ref m_HBaseRangeMin, ref m_HAllowExceedBaseRangeMin, value); }
}
public float hRangeMax
{
get { return (hAllowExceedBaseRangeMax ? Mathf.Infinity : hBaseRangeMax); }
set { SetAllowExceed(ref m_HBaseRangeMax, ref m_HAllowExceedBaseRangeMax, value); }
}
public float vRangeMin
{
get { return (vAllowExceedBaseRangeMin ? Mathf.NegativeInfinity : vBaseRangeMin); }
set { SetAllowExceed(ref m_VBaseRangeMin, ref m_VAllowExceedBaseRangeMin, value); }
}
public float vRangeMax
{
get { return (vAllowExceedBaseRangeMax ? Mathf.Infinity : vBaseRangeMax); }
set { SetAllowExceed(ref m_VBaseRangeMax, ref m_VAllowExceedBaseRangeMax, value); }
}
private void SetAllowExceed(ref float rangeEnd, ref bool allowExceed, float value)
{
if (value == Mathf.NegativeInfinity || value == Mathf.Infinity)
{
rangeEnd = (value == Mathf.NegativeInfinity ? 0 : 1);
allowExceed = true;
}
else
{
rangeEnd = value;
allowExceed = false;
}
}
private float m_HScaleMin = 0.001f;
private float m_HScaleMax = 100000.0f;
private float m_VScaleMin = 0.001f;
private float m_VScaleMax = 100000.0f;
// Window resize settings
[SerializeField]
private bool m_ScaleWithWindow = false;
public bool scaleWithWindow { get { return m_ScaleWithWindow; } set { m_ScaleWithWindow = value; } }
// Slider settings
[SerializeField]
private bool m_HSlider = true;
[SerializeField]
private bool m_VSlider = true;
public bool hSlider { get { return m_HSlider; } set { Rect r = rect; m_HSlider = value; rect = r; } }
public bool vSlider { get { return m_VSlider; } set { Rect r = rect; m_VSlider = value; rect = r; } }
[SerializeField]
private bool m_IgnoreScrollWheelUntilClicked = false;
public bool ignoreScrollWheelUntilClicked { get { return m_IgnoreScrollWheelUntilClicked; } set { m_IgnoreScrollWheelUntilClicked = value; } }
public bool m_UniformScale;
public bool uniformScale { get { return m_UniformScale; } set { m_UniformScale = value; } }
// View and drawing settings
[SerializeField]
private Rect m_DrawArea = new Rect(0, 0, 100, 100);
internal void SetDrawRectHack(Rect r) { m_DrawArea = r; }
[SerializeField]
internal Vector2 m_Scale = new Vector2(1, -1);
[SerializeField]
internal Vector2 m_Translation = new Vector2(0, 0);
[SerializeField]
private float m_MarginLeft, m_MarginRight, m_MarginTop, m_MarginBottom;
[SerializeField]
private Rect m_LastShownAreaInsideMargins = new Rect(0, 0, 100, 100);
public Vector2 scale { get { return m_Scale; } }
public float margin { set { m_MarginLeft = m_MarginRight = m_MarginTop = m_MarginBottom = value; } }
public float leftmargin { get { return m_MarginLeft; } set { m_MarginLeft = value; } }
public float rightmargin { get { return m_MarginRight; } set { m_MarginRight = value; } }
public float topmargin { get { return m_MarginTop; } set { m_MarginTop = value; } }
public float bottommargin { get { return m_MarginBottom; } set { m_MarginBottom = value; } }
[SerializeField]
bool m_MinimalGUI;
[System.Serializable]
public class Styles
{
public GUIStyle background = "AnimationCurveEditorBackground";
public GUIStyle horizontalScrollbar;
public GUIStyle horizontalMinMaxScrollbarThumb;
public GUIStyle horizontalScrollbarLeftButton;
public GUIStyle horizontalScrollbarRightButton;
public GUIStyle verticalScrollbar;
public GUIStyle verticalMinMaxScrollbarThumb;
public GUIStyle verticalScrollbarUpButton;
public GUIStyle verticalScrollbarDownButton;
public float sliderWidth;
public float visualSliderWidth;
public Styles(bool minimalGUI)
{
if (minimalGUI)
{
visualSliderWidth = 0;
sliderWidth = 15;
}
else
{
visualSliderWidth = 15;
sliderWidth = 15;
}
}
public void InitGUIStyles(bool minimalGUI)
{
if (minimalGUI)
{
horizontalMinMaxScrollbarThumb = "MiniMinMaxSliderHorizontal";
horizontalScrollbarLeftButton = GUIStyle.none;
horizontalScrollbarRightButton = GUIStyle.none;
horizontalScrollbar = GUIStyle.none;
verticalMinMaxScrollbarThumb = "MiniMinMaxSlidervertical";
verticalScrollbarUpButton = GUIStyle.none;
verticalScrollbarDownButton = GUIStyle.none;
verticalScrollbar = GUIStyle.none;
}
else
{
horizontalMinMaxScrollbarThumb = "horizontalMinMaxScrollbarThumb";
horizontalScrollbarLeftButton = "horizontalScrollbarLeftbutton";
horizontalScrollbarRightButton = "horizontalScrollbarRightbutton";
horizontalScrollbar = GUI.skin.horizontalScrollbar;
verticalMinMaxScrollbarThumb = "verticalMinMaxScrollbarThumb";
verticalScrollbarUpButton = "verticalScrollbarUpbutton";
verticalScrollbarDownButton = "verticalScrollbarDownbutton";
verticalScrollbar = GUI.skin.verticalScrollbar;
}
}
}
private Styles m_Styles;
private Styles styles
{
get
{
if (m_Styles == null)
m_Styles = new Styles(m_MinimalGUI);
return m_Styles;
}
}
public Rect rect
{
get { return new Rect(drawRect.x, drawRect.y, drawRect.width + (m_VSlider ? styles.visualSliderWidth : 0), drawRect.height + (m_HSlider ? styles.visualSliderWidth : 0)); }
set
{
Rect newDrawArea = new Rect(value.x, value.y, value.width - (m_VSlider ? styles.visualSliderWidth : 0), value.height - (m_HSlider ? styles.visualSliderWidth : 0));
if (newDrawArea != m_DrawArea)
{
if (m_ScaleWithWindow)
{
m_DrawArea = newDrawArea;
shownAreaInsideMargins = m_LastShownAreaInsideMargins;
}
else
{
m_Translation += new Vector2((newDrawArea.width - m_DrawArea.width) / 2, (newDrawArea.height - m_DrawArea.height) / 2);
m_DrawArea = newDrawArea;
}
}
EnforceScaleAndRange();
}
}
public Rect drawRect { get { return m_DrawArea; } }
public void SetShownHRangeInsideMargins(float min, float max)
{
m_Scale.x = (drawRect.width - leftmargin - rightmargin) / (max - min);
m_Translation.x = -min * m_Scale.x + leftmargin;
EnforceScaleAndRange();
}
public void SetShownHRange(float min, float max)
{
m_Scale.x = drawRect.width / (max - min);
m_Translation.x = -min * m_Scale.x;
EnforceScaleAndRange();
}
public void SetShownVRangeInsideMargins(float min, float max)
{
m_Scale.y = -(drawRect.height - topmargin - bottommargin) / (max - min);
m_Translation.y = drawRect.height - min * m_Scale.y - topmargin;
EnforceScaleAndRange();
}
public void SetShownVRange(float min, float max)
{
m_Scale.y = -drawRect.height / (max - min);
m_Translation.y = drawRect.height - min * m_Scale.y;
EnforceScaleAndRange();
}
// ShownArea is in curve space
public Rect shownArea
{
set
{
m_Scale.x = drawRect.width / value.width;
m_Scale.y = -drawRect.height / value.height;
m_Translation.x = -value.x * m_Scale.x;
m_Translation.y = drawRect.height - value.y * m_Scale.y;
EnforceScaleAndRange();
}
get
{
return new Rect(
-m_Translation.x / m_Scale.x,
-(m_Translation.y - drawRect.height) / m_Scale.y,
drawRect.width / m_Scale.x,
drawRect.height / -m_Scale.y
);
}
}
public Rect shownAreaInsideMargins
{
set
{
shownAreaInsideMarginsInternal = value;
EnforceScaleAndRange();
}
get
{
return shownAreaInsideMarginsInternal;
}
}
private Rect shownAreaInsideMarginsInternal
{
set
{
m_Scale.x = (drawRect.width - leftmargin - rightmargin) / value.width;
m_Scale.y = -(drawRect.height - topmargin - bottommargin) / value.height;
m_Translation.x = -value.x * m_Scale.x + leftmargin;
m_Translation.y = drawRect.height - value.y * m_Scale.y - topmargin;
}
get
{
float leftmarginRel = leftmargin / m_Scale.x;
float rightmarginRel = rightmargin / m_Scale.x;
float topmarginRel = topmargin / m_Scale.y;
float bottommarginRel = bottommargin / m_Scale.y;
Rect area = shownArea;
area.x += leftmarginRel;
area.y -= topmarginRel;
area.width -= leftmarginRel + rightmarginRel;
area.height += topmarginRel + bottommarginRel;
return area;
}
}
public virtual Bounds drawingBounds
{
get
{
return new Bounds(
new Vector3((hBaseRangeMin + hBaseRangeMax) * 0.5f, (vBaseRangeMin + vBaseRangeMax) * 0.5f, 0),
new Vector3(hBaseRangeMax - hBaseRangeMin, vBaseRangeMax - vBaseRangeMin, 1)
);
}
}
// Utility transform functions
public Matrix4x4 drawingToViewMatrix
{
get
{
return Matrix4x4.TRS(m_Translation, Quaternion.identity, new Vector3(m_Scale.x, m_Scale.y, 1));
}
}
public Vector2 DrawingToViewTransformPoint(Vector2 lhs)
{ return new Vector2(lhs.x * m_Scale.x + m_Translation.x, lhs.y * m_Scale.y + m_Translation.y); }
public Vector3 DrawingToViewTransformPoint(Vector3 lhs)
{ return new Vector3(lhs.x * m_Scale.x + m_Translation.x, lhs.y * m_Scale.y + m_Translation.y, 0); }
public Vector2 ViewToDrawingTransformPoint(Vector2 lhs)
{ return new Vector2((lhs.x - m_Translation.x) / m_Scale.x, (lhs.y - m_Translation.y) / m_Scale.y); }
public Vector3 ViewToDrawingTransformPoint(Vector3 lhs)
{ return new Vector3((lhs.x - m_Translation.x) / m_Scale.x, (lhs.y - m_Translation.y) / m_Scale.y, 0); }
public Vector2 DrawingToViewTransformVector(Vector2 lhs)
{ return new Vector2(lhs.x * m_Scale.x, lhs.y * m_Scale.y); }
public Vector3 DrawingToViewTransformVector(Vector3 lhs)
{ return new Vector3(lhs.x * m_Scale.x, lhs.y * m_Scale.y, 0); }
public Vector2 ViewToDrawingTransformVector(Vector2 lhs)
{ return new Vector2(lhs.x / m_Scale.x, lhs.y / m_Scale.y); }
public Vector3 ViewToDrawingTransformVector(Vector3 lhs)
{ return new Vector3(lhs.x / m_Scale.x, lhs.y / m_Scale.y, 0); }
public Vector2 mousePositionInDrawing
{
get { return ViewToDrawingTransformPoint(Event.current.mousePosition); }
}
public Vector2 NormalizeInViewSpace(Vector2 vec)
{
vec = Vector2.Scale(vec, m_Scale);
vec /= vec.magnitude;
return Vector2.Scale(vec, new Vector2(1 / m_Scale.x, 1 / m_Scale.y));
}
// Utility mouse event functions
private bool IsZoomEvent()
{
return (
(Event.current.button == 1 && Event.current.alt) // right+alt drag
//|| (Event.current.button == 0 && Event.current.command) // left+commend drag
//|| (Event.current.button == 2 && Event.current.command) // middle+command drag
);
}
private bool IsPanEvent()
{
return (
(Event.current.button == 0 && Event.current.alt) // left+alt drag
|| (Event.current.button == 2 && !Event.current.command) // middle drag
);
}
public ZoomArea()
{
m_MinimalGUI = false;
}
public ZoomArea(bool minimalGUI)
{
m_MinimalGUI = minimalGUI;
}
public void BeginViewGUI()
{
if (styles.horizontalScrollbar == null)
styles.InitGUIStyles(m_MinimalGUI);
GUILayout.BeginArea(m_DrawArea, styles.background);
HandleZoomAndPanEvents(m_DrawArea);
GUILayout.EndArea();
}
public void HandleZoomAndPanEvents(Rect area)
{
area.x = 0;
area.y = 0;
int id = GUIUtility.GetControlID(zoomableAreaHash, FocusType.Passive, area);
switch (Event.current.GetTypeForControl(id))
{
case EventType.MouseDown:
if (area.Contains(Event.current.mousePosition))
{
// Catch keyboard control when clicked inside zoomable area
// (used to restrict scrollwheel)
GUIUtility.keyboardControl = id;
if (IsZoomEvent() || IsPanEvent())
{
GUIUtility.hotControl = id;
m_MouseDownPosition = mousePositionInDrawing;
Event.current.Use();
}
}
break;
case EventType.MouseUp:
//Debug.Log("mouse-up!");
if (GUIUtility.hotControl == id)
{
GUIUtility.hotControl = 0;
// If we got the mousedown, the mouseup is ours as well
// (no matter if the click was in the area or not)
m_MouseDownPosition = new Vector2(-1000000, -1000000);
//Event.current.Use();
}
break;
case EventType.MouseDrag:
if (GUIUtility.hotControl != id) break;
if (IsZoomEvent())
{
// Zoom in around mouse down position
Zoom(m_MouseDownPosition, false);
Event.current.Use();
}
else if (IsPanEvent())
{
// Pan view
Pan();
Event.current.Use();
}
break;
case EventType.ScrollWheel:
if (!area.Contains(Event.current.mousePosition))
break;
if (m_IgnoreScrollWheelUntilClicked && GUIUtility.keyboardControl != id)
break;
// Zoom in around cursor position
Zoom(mousePositionInDrawing, true);
Event.current.Use();
break;
}
}
public void EndViewGUI()
{
}
private void Pan()
{
if (!m_HRangeLocked)
m_Translation.x += Event.current.delta.x;
if (!m_VRangeLocked)
m_Translation.y += Event.current.delta.y;
EnforceScaleAndRange();
}
private void Zoom(Vector2 zoomAround, bool scrollwhell)
{
// Get delta (from scroll wheel or mouse pad)
// Add x and y delta to cover all cases
// (scrool view has only y or only x when shift is pressed,
// while mouse pad has both x and y at all times)
float delta = Event.current.delta.x + Event.current.delta.y;
if (scrollwhell)
delta = -delta;
// Scale multiplier. Don't allow scale of zero or below!
float scale = Mathf.Max(0.01F, 1 + delta * 0.01F);
if (!m_HRangeLocked && !Event.current.shift)
{
// Offset to make zoom centered around cursor position
m_Translation.x -= zoomAround.x * (scale - 1) * m_Scale.x;
// Apply zooming
m_Scale.x *= scale;
}
if (!m_VRangeLocked && !EditorGUI.actionKey)
{
// Offset to make zoom centered around cursor position
m_Translation.y -= zoomAround.y * (scale - 1) * m_Scale.y;
// Apply zooming
m_Scale.y *= scale;
}
EnforceScaleAndRange();
}
public void EnforceScaleAndRange()
{
float hScaleMin = m_HScaleMin;
float vScaleMin = m_VScaleMin;
float hScaleMax = m_HScaleMax;
float vScaleMax = m_VScaleMax;
if (hRangeMax != Mathf.Infinity && hRangeMin != Mathf.NegativeInfinity)
hScaleMax = Mathf.Min(m_HScaleMax, hRangeMax - hRangeMin);
if (vRangeMax != Mathf.Infinity && vRangeMin != Mathf.NegativeInfinity)
vScaleMax = Mathf.Min(m_VScaleMax, vRangeMax - vRangeMin);
Rect oldArea = m_LastShownAreaInsideMargins;
Rect newArea = shownAreaInsideMargins;
if (newArea == oldArea)
return;
float epsilon = 0.00001f;
if (newArea.width < oldArea.width - epsilon)
{
float xLerp = Mathf.InverseLerp(oldArea.width, newArea.width, hScaleMin);
newArea = new Rect(
Mathf.Lerp(oldArea.x, newArea.x, xLerp),
newArea.y,
Mathf.Lerp(oldArea.width, newArea.width, xLerp),
newArea.height
);
}
if (newArea.height < oldArea.height - epsilon)
{
float yLerp = Mathf.InverseLerp(oldArea.height, newArea.height, vScaleMin);
newArea = new Rect(
newArea.x,
Mathf.Lerp(oldArea.y, newArea.y, yLerp),
newArea.width,
Mathf.Lerp(oldArea.height, newArea.height, yLerp)
);
}
if (newArea.width > oldArea.width + epsilon)
{
float xLerp = Mathf.InverseLerp(oldArea.width, newArea.width, hScaleMax);
newArea = new Rect(
Mathf.Lerp(oldArea.x, newArea.x, xLerp),
newArea.y,
Mathf.Lerp(oldArea.width, newArea.width, xLerp),
newArea.height
);
}
if (newArea.height > oldArea.height + epsilon)
{
float yLerp = Mathf.InverseLerp(oldArea.height, newArea.height, vScaleMax);
newArea = new Rect(
newArea.x,
Mathf.Lerp(oldArea.y, newArea.y, yLerp),
newArea.width,
Mathf.Lerp(oldArea.height, newArea.height, yLerp)
);
}
// Enforce ranges
if (newArea.xMin < hRangeMin)
newArea.x = hRangeMin;
if (newArea.xMax > hRangeMax)
newArea.x = hRangeMax - newArea.width;
if (newArea.yMin < vRangeMin)
newArea.y = vRangeMin;
if (newArea.yMax > vRangeMax)
newArea.y = vRangeMax - newArea.height;
shownAreaInsideMarginsInternal = newArea;
m_LastShownAreaInsideMargins = newArea;
}
public float PixelToTime(float pixelX, Rect rect)
{
return ((pixelX - rect.x) * shownArea.width / rect.width + shownArea.x);
}
public float TimeToPixel(float time, Rect rect)
{
return (time - shownArea.x) / shownArea.width * rect.width + rect.x;
}
public float PixelDeltaToTime(Rect rect)
{
return shownArea.width / rect.width;
}
}