123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430 |
- using System;
- using UnityEngine;
- using UnityEvent = UnityEngine.Event;
- namespace UnityEditor.U2D.Sprites
- {
- internal class SpriteUtilityWindow : EditorWindow
- {
- protected class Styles
- {
- public readonly GUIStyle dragdot = "U2D.dragDot";
- public readonly GUIStyle dragdotDimmed = "U2D.dragDotDimmed";
- public readonly GUIStyle dragdotactive = "U2D.dragDotActive";
- public readonly GUIStyle createRect = "U2D.createRect";
- public readonly GUIStyle preToolbar = "preToolbar";
- public readonly GUIStyle preButton = "preButton";
- public readonly GUIStyle preLabel = "preLabel";
- public readonly GUIStyle preSlider = "preSlider";
- public readonly GUIStyle preSliderThumb = "preSliderThumb";
- public readonly GUIStyle preBackground = "preBackground";
- public readonly GUIStyle pivotdotactive = "U2D.pivotDotActive";
- public readonly GUIStyle pivotdot = "U2D.pivotDot";
- public readonly GUIStyle dragBorderdot = new GUIStyle();
- public readonly GUIStyle dragBorderDotActive = new GUIStyle();
- public readonly GUIStyle toolbar;
- public readonly GUIContent alphaIcon;
- public readonly GUIContent RGBIcon;
- public readonly GUIStyle notice;
- public readonly GUIContent smallMip;
- public readonly GUIContent largeMip;
- public Styles()
- {
- toolbar = new GUIStyle(EditorStyles.inspectorBig);
- toolbar.margin.top = 0;
- toolbar.margin.bottom = 0;
- alphaIcon = EditorGUIUtility.IconContent("PreTextureAlpha");
- RGBIcon = EditorGUIUtility.IconContent("PreTextureRGB");
- preToolbar.border.top = 0;
- createRect.border = new RectOffset(3, 3, 3, 3);
- notice = new GUIStyle(GUI.skin.label);
- notice.alignment = TextAnchor.MiddleCenter;
- notice.normal.textColor = Color.yellow;
- dragBorderdot.fixedHeight = 5f;
- dragBorderdot.fixedWidth = 5f;
- dragBorderdot.normal.background = EditorGUIUtility.whiteTexture;
- dragBorderDotActive.fixedHeight = dragBorderdot.fixedHeight;
- dragBorderDotActive.fixedWidth = dragBorderdot.fixedWidth;
- dragBorderDotActive.normal.background = EditorGUIUtility.whiteTexture;
- smallMip = EditorGUIUtility.IconContent("PreTextureMipMapLow");
- largeMip = EditorGUIUtility.IconContent("PreTextureMipMapHigh");
- }
- }
- protected void InitStyles()
- {
- if (m_Styles == null)
- m_Styles = new Styles();
- }
- protected Styles m_Styles;
- protected const float k_BorderMargin = 10f;
- protected const float k_ScrollbarMargin = 16f;
- protected const float k_InspectorWindowMargin = 8f;
- protected const float k_InspectorWidth = 330f;
- protected const float k_MinZoomPercentage = 0.9f;
- protected const float k_MaxZoom = 50f;
- protected const float k_WheelZoomSpeed = 0.03f;
- protected const float k_MouseZoomSpeed = 0.005f;
- protected const float k_ToolbarHeight = 17f;
- protected ITexture2D m_Texture;
- protected ITexture2D m_TextureAlphaOverride;
- Rect m_TextureViewRect;
- protected Rect m_TextureRect;
- [SerializeField]
- protected bool m_ShowAlpha = false;
- [SerializeField]
- protected float m_MipLevel = 0;
- [SerializeField]
- protected float m_Zoom = -1f;
- [SerializeField]
- protected Vector2 m_ScrollPosition = new Vector2();
- public float zoomLevel
- {
- get { return m_Zoom; }
- set { m_Zoom = Mathf.Clamp(value, GetMinZoom(), k_MaxZoom); }
- }
- internal Rect textureViewRect
- {
- get => m_TextureViewRect;
- set
- {
- m_TextureViewRect = value;
- zoomLevel = m_Zoom; // update zoom level
- }
- }
- public Vector2 scrollPosition
- {
- get { return m_ScrollPosition; }
- set
- {
- if (m_Zoom < 0)
- m_Zoom = GetMinZoom();
- m_ScrollPosition.x = Mathf.Clamp(value.x, maxScrollRect.xMin, maxScrollRect.xMax);
- m_ScrollPosition.y = Mathf.Clamp(value.y, maxScrollRect.yMin, maxScrollRect.yMax);
- }
- }
- public bool showAlpha
- {
- get { return m_ShowAlpha; }
- set { m_ShowAlpha = value; }
- }
- public float mipLevel
- {
- get { return m_MipLevel; }
- set
- {
- var mipCount = 1;
- if (m_Texture != null)
- mipCount = Mathf.Max(mipCount, TextureUtil.GetMipmapCount(m_Texture));
- m_MipLevel = Mathf.Clamp(value, 0, mipCount - 1);
- }
- }
- protected float GetMinZoom()
- {
- if (m_Texture == null)
- return 1.0f;
- // Case 654327: Add k_MaxZoom size to min check to ensure that min zoom is smaller than max zoom
- return Mathf.Min(m_TextureViewRect.width / m_Texture.width, m_TextureViewRect.height / m_Texture.height, k_MaxZoom) * k_MinZoomPercentage;
- }
- protected void HandleZoom()
- {
- bool zoomMode = UnityEvent.current.alt && UnityEvent.current.button == 1;
- if (zoomMode)
- {
- EditorGUIUtility.AddCursorRect(m_TextureViewRect, MouseCursor.Zoom);
- }
- if (
- ((UnityEvent.current.type == EventType.MouseUp || UnityEvent.current.type == EventType.MouseDown) && zoomMode) ||
- ((UnityEvent.current.type == EventType.KeyUp || UnityEvent.current.type == EventType.KeyDown) && UnityEvent.current.keyCode == KeyCode.LeftAlt)
- )
- {
- Repaint();
- }
- if (UnityEvent.current.type == EventType.ScrollWheel || (UnityEvent.current.type == EventType.MouseDrag && UnityEvent.current.alt && UnityEvent.current.button == 1))
- {
- float zoomMultiplier = 1f - UnityEvent.current.delta.y * (UnityEvent.current.type == EventType.ScrollWheel ? k_WheelZoomSpeed : -k_MouseZoomSpeed);
- // Clamp zoom
- float wantedZoom = m_Zoom * zoomMultiplier;
- float currentZoom = Mathf.Clamp(wantedZoom, GetMinZoom(), k_MaxZoom);
- if (currentZoom != m_Zoom)
- {
- m_Zoom = currentZoom;
- // We need to fix zoomMultiplier if we clamped wantedZoom != currentZoom
- if (wantedZoom != currentZoom)
- zoomMultiplier /= wantedZoom / currentZoom;
- Vector3 textureHalfSize = new Vector2(m_Texture.width, m_Texture.height) * 0.5f;
- Vector3 mousePositionWorld = Handles.inverseMatrix.MultiplyPoint3x4(UnityEvent.current.mousePosition + m_ScrollPosition);
- Vector3 delta = (mousePositionWorld - textureHalfSize) * (zoomMultiplier - 1f);
- m_ScrollPosition += (Vector2)Handles.matrix.MultiplyVector(delta);
- UnityEvent.current.Use();
- }
- }
- }
- protected void HandlePanning()
- {
- // You can pan by holding ALT and using left button or NOT holding ALT and using right button. ALT + right is reserved for zooming.
- bool panMode = (!UnityEvent.current.alt && UnityEvent.current.button > 0 || UnityEvent.current.alt && UnityEvent.current.button <= 0);
- if (panMode && GUIUtility.hotControl == 0)
- {
- EditorGUIUtility.AddCursorRect(m_TextureViewRect, MouseCursor.Pan);
- if (UnityEvent.current.type == EventType.MouseDrag)
- {
- m_ScrollPosition -= UnityEvent.current.delta;
- UnityEvent.current.Use();
- }
- }
- //We need to repaint when entering or exiting the pan mode, so the mouse cursor gets refreshed.
- if (
- ((UnityEvent.current.type == EventType.MouseUp || UnityEvent.current.type == EventType.MouseDown) && panMode) ||
- (UnityEvent.current.type == EventType.KeyUp || UnityEvent.current.type == EventType.KeyDown) && UnityEvent.current.keyCode == KeyCode.LeftAlt
- )
- {
- Repaint();
- }
- }
- // Bounding values for scrollbars. Changes with zoom, because we want min/max scroll to stop at texture edges.
- protected Rect maxScrollRect
- {
- get
- {
- float halfWidth = m_Texture.width * .5f * m_Zoom;
- float halfHeight = m_Texture.height * .5f * m_Zoom;
- return new Rect(-halfWidth, -halfHeight, m_TextureViewRect.width + halfWidth * 2f, m_TextureViewRect.height + halfHeight * 2f);
- }
- }
- // Max rect in texture space that can ever be visible
- protected Rect maxRect
- {
- get
- {
- float marginW = m_TextureViewRect.width * .5f / GetMinZoom();
- float marginH = m_TextureViewRect.height * .5f / GetMinZoom();
- float left = -marginW;
- float top = -marginH;
- float width = m_Texture.width + marginW * 2f;
- float height = m_Texture.height + marginH * 2f;
- return new Rect(left, top, width, height);
- }
- }
- protected void DrawTexturespaceBackground()
- {
- float size = Mathf.Max(maxRect.width, maxRect.height);
- Vector2 offset = new Vector2(maxRect.xMin, maxRect.yMin);
- float halfSize = size * .5f;
- float alpha = EditorGUIUtility.isProSkin ? 0.15f : 0.08f;
- float gridSize = 8f;
- SpriteEditorUtility.BeginLines(new Color(0f, 0f, 0f, alpha));
- for (float v = 0; v <= size; v += gridSize)
- SpriteEditorUtility.DrawLine(new Vector2(-halfSize + v, halfSize + v) + offset, new Vector2(halfSize + v, -halfSize + v) + offset);
- SpriteEditorUtility.EndLines();
- }
- private float Log2(float x)
- {
- return (float)(System.Math.Log(x) / System.Math.Log(2));
- }
- protected void DrawTexture()
- {
- float mipLevel = Mathf.Min(m_MipLevel, TextureUtil.GetMipmapCount(m_Texture) - 1);
- FilterMode oldFilter = m_Texture.filterMode;
- TextureUtil.SetFilterModeNoDirty(m_Texture, FilterMode.Point);
- if (m_ShowAlpha)
- {
- // check if we have a valid alpha texture
- if (m_TextureAlphaOverride != null)
- EditorGUI.DrawTextureTransparent(m_TextureRect, m_TextureAlphaOverride, ScaleMode.StretchToFill, 0, mipLevel);
- // else use the original texture and display its alpha
- else
- EditorGUI.DrawTextureAlpha(m_TextureRect, m_Texture, ScaleMode.StretchToFill, 0, mipLevel);
- }
- else
- EditorGUI.DrawTextureTransparent(m_TextureRect, m_Texture, ScaleMode.StretchToFill, 0, mipLevel);
- TextureUtil.SetFilterModeNoDirty(m_Texture, oldFilter);
- }
- protected void DrawScreenspaceBackground()
- {
- if (UnityEvent.current.type == EventType.Repaint)
- m_Styles.preBackground.Draw(m_TextureViewRect, false, false, false, false);
- }
- protected void HandleScrollbars()
- {
- Rect horizontalScrollBarPosition = new Rect(m_TextureViewRect.xMin, m_TextureViewRect.yMax, m_TextureViewRect.width, k_ScrollbarMargin);
- m_ScrollPosition.x = GUI.HorizontalScrollbar(horizontalScrollBarPosition, m_ScrollPosition.x, m_TextureViewRect.width, maxScrollRect.xMin, maxScrollRect.xMax);
- Rect verticalScrollBarPosition = new Rect(m_TextureViewRect.xMax, m_TextureViewRect.yMin, k_ScrollbarMargin, m_TextureViewRect.height);
- m_ScrollPosition.y = GUI.VerticalScrollbar(verticalScrollBarPosition, m_ScrollPosition.y, m_TextureViewRect.height, maxScrollRect.yMin, maxScrollRect.yMax);
- }
- protected void SetupHandlesMatrix()
- {
- // Offset from top left to center in view space
- Vector3 handlesPos = new Vector3(m_TextureRect.x, m_TextureRect.yMax, 0f);
- // We flip Y-scale because Unity texture space is bottom-up
- Vector3 handlesScale = new Vector3(zoomLevel, -zoomLevel, 1f);
- // Handle matrix is for converting between view and texture space coordinates, without taking account the scroll position.
- // Scroll position is added separately so we can use it with GUIClip.
- Handles.matrix = Matrix4x4.TRS(handlesPos, Quaternion.identity, handlesScale);
- }
- protected Rect DoAlphaZoomToolbarGUI(Rect area)
- {
- int mipCount = 1;
- if (m_Texture != null)
- mipCount = Mathf.Max(mipCount, TextureUtil.GetMipmapCount(m_Texture));
- Rect drawArea = new Rect(area.width, 0, 0, area.height);
- using (new EditorGUI.DisabledScope(mipCount == 1))
- {
- drawArea.width = m_Styles.largeMip.image.width;
- drawArea.x -= drawArea.width;
- GUI.Box(drawArea, m_Styles.largeMip, m_Styles.preLabel);
- drawArea.width = EditorGUI.kSliderMinW;
- drawArea.x -= drawArea.width;
- m_MipLevel = Mathf.Round(GUI.HorizontalSlider(drawArea, m_MipLevel, mipCount - 1, 0, m_Styles.preSlider, m_Styles.preSliderThumb));
- drawArea.width = m_Styles.smallMip.image.width;
- drawArea.x -= drawArea.width;
- GUI.Box(drawArea, m_Styles.smallMip, m_Styles.preLabel);
- }
- drawArea.width = EditorGUI.kSliderMinW;
- drawArea.x -= drawArea.width;
- zoomLevel = GUI.HorizontalSlider(drawArea, zoomLevel, GetMinZoom(), k_MaxZoom, m_Styles.preSlider, m_Styles.preSliderThumb);
- drawArea.width = EditorGUI.kObjectFieldMiniThumbnailWidth;
- drawArea.x -= drawArea.width + EditorGUI.kSpacing;
- m_ShowAlpha = GUI.Toggle(drawArea, m_ShowAlpha, m_ShowAlpha ? m_Styles.alphaIcon : m_Styles.RGBIcon, "toolbarButton");
- // Returns the area that is not used
- return new Rect(area.x, area.y, drawArea.x, area.height);
- }
- protected void DoTextureGUI()
- {
- if (m_Texture == null)
- return;
- // zoom startup init
- if (m_Zoom < 0f)
- m_Zoom = GetMinZoom();
- // Texture rect in view space
- m_TextureRect = new Rect(
- m_TextureViewRect.width / 2f - (m_Texture.width * m_Zoom / 2f),
- m_TextureViewRect.height / 2f - (m_Texture.height * m_Zoom / 2f),
- (m_Texture.width * m_Zoom),
- (m_Texture.height * m_Zoom)
- );
- HandleScrollbars();
- SetupHandlesMatrix();
- DrawScreenspaceBackground();
- GUIClip.Push(m_TextureViewRect, -m_ScrollPosition, Vector2.zero, false);
- if (UnityEvent.current.type == EventType.Repaint)
- {
- DrawTexturespaceBackground();
- DrawTexture();
- DrawGizmos();
- }
- DoTextureGUIExtras();
- GUIClip.Pop();
- // Handle this after DoTextureGUIExtras in case user wants any event that is handled by Zoom or Panning
- HandleZoom();
- HandlePanning();
- }
- protected virtual void DoTextureGUIExtras()
- {
- }
- protected virtual void DrawGizmos()
- {
- }
- protected void SetNewTexture(Texture2D texture)
- {
- if (texture != m_Texture)
- {
- m_Texture = new Texture2DWrapper(texture);
- m_Zoom = -1;
- m_TextureAlphaOverride = null;
- }
- }
- protected void SetAlphaTextureOverride(Texture2D alphaTexture)
- {
- if (alphaTexture != m_TextureAlphaOverride)
- {
- m_TextureAlphaOverride = new Texture2DWrapper(alphaTexture);
- m_Zoom = -1;
- }
- }
- internal override void OnResized()
- {
- if (m_Texture != null && UnityEvent.current != null)
- HandleZoom();
- base.OnResized();
- }
- internal static void DrawToolBarWidget(ref Rect drawRect, ref Rect toolbarRect, Action<Rect> drawAction)
- {
- toolbarRect.width -= drawRect.width;
- if (toolbarRect.width < 0)
- drawRect.width += toolbarRect.width;
- if (drawRect.width > 0)
- drawAction(drawRect);
- }
- } // class
- }
|