Unity Editor Window Zooming

来源:互联网 发布:跳舞毯哪款最好 知乎 编辑:程序博客网 时间:2024/06/04 08:25


参考:

http://martinecker.com/martincodes/unity-editor-window-zooming/

http://answers.unity3d.com/questions/38224/how-can-i-zoom-out-properly-within-a-editorwindow.html


方法1:

using UnityEngine;using System.Collections;public class Test : MonoBehaviour{    private Vector2 scale = new Vector2(1, 1);    private Vector2 pivotPoint;    void OnGUI()    {        Matrix4x4 oldMatrix = GUI.matrix;        pivotPoint = new Vector2(Screen.width / 2, Screen.height / 2);        GUIUtility.ScaleAroundPivot(scale, pivotPoint);        if (GUI.Button(new Rect(Screen.width / 2 - 25, Screen.height / 2 - 25, 50, 50), "Big!"))            scale += new Vector2(0.5F, 0.5F);        GUI.matrix = oldMatrix;        if (GUI.Button(new Rect(Screen.width / 2 + 25, Screen.height / 2 - 25, 50, 50), "Big!"))            scale += new Vector2(0.5F, 0.5F);    }}


方法2:

using System;using System.Collections.Generic;using UnityEngine;using UnityEditor;public class ZoomTestWindow : EditorWindow{    [MenuItem("Window/Zoom Test")]    private static void Init()    {        ZoomTestWindow window = EditorWindow.GetWindow<ZoomTestWindow>(false, "Zoom Test");        window.minSize = new Vector2(600.0f, 300.0f);        window.wantsMouseMove = true;        window.Show();        //EditorWindow.FocusWindowIfItsOpen();    }    private const float kZoomMin = 0.1f;    private const float kZoomMax = 10.0f;    private readonly Rect _zoomArea = new Rect(0.0f, 75.0f, 600.0f, 300.0f - 100.0f);    private float _zoom = 1.0f;    private Vector2 _zoomCoordsOrigin = Vector2.zero;    private Vector2 ConvertScreenCoordsToZoomCoords(Vector2 screenCoords)    {        return (screenCoords - _zoomArea.TopLeft()) / _zoom + _zoomCoordsOrigin;    }    private void DrawZoomArea()    {        // Within the zoom area all coordinates are relative to the top left corner of the zoom area        // with the width and height being scaled versions of the original/unzoomed area's width and height.        EditorZoomArea.Begin(_zoom, _zoomArea);        GUI.Box(new Rect(0.0f - _zoomCoordsOrigin.x, 0.0f - _zoomCoordsOrigin.y, 100.0f, 25.0f), "Zoomed Box");        // You can also use GUILayout inside the zoomed area.        GUILayout.BeginArea(new Rect(300.0f - _zoomCoordsOrigin.x, 70.0f - _zoomCoordsOrigin.y, 130.0f, 50.0f));        GUILayout.Button("Zoomed Button 1");        GUILayout.Button("Zoomed Button 2");        GUILayout.EndArea();        EditorZoomArea.End();    }    private void DrawNonZoomArea()    {        GUI.Box(new Rect(0.0f, 0.0f, 600.0f, 50.0f), "Adjust zoom of middle box with slider or mouse wheel.\nMove zoom area dragging with middle mouse button or Alt+left mouse button.");        _zoom = EditorGUI.Slider(new Rect(0.0f, 50.0f, 600.0f, 25.0f), _zoom, kZoomMin, kZoomMax);        GUI.Box(new Rect(0.0f, 300.0f - 25.0f, 600.0f, 25.0f), "Unzoomed Box");    }    private void HandleEvents()    {        // Allow adjusting the zoom with the mouse wheel as well. In this case, use the mouse coordinates        // as the zoom center instead of the top left corner of the zoom area. This is achieved by        // maintaining an origin that is used as offset when drawing any GUI elements in the zoom area.        if (Event.current.type == EventType.ScrollWheel)        {            Vector2 screenCoordsMousePos = Event.current.mousePosition;            Vector2 delta = Event.current.delta;            Vector2 zoomCoordsMousePos = ConvertScreenCoordsToZoomCoords(screenCoordsMousePos);            float zoomDelta = -delta.y / 150.0f;            float oldZoom = _zoom;            _zoom += zoomDelta;            _zoom = Mathf.Clamp(_zoom, kZoomMin, kZoomMax);            _zoomCoordsOrigin += (zoomCoordsMousePos - _zoomCoordsOrigin) - (oldZoom / _zoom) * (zoomCoordsMousePos - _zoomCoordsOrigin);            Event.current.Use();        }        // Allow moving the zoom area's origin by dragging with the middle mouse button or dragging        // with the left mouse button with Alt pressed.        if (Event.current.type == EventType.MouseDrag &&            (Event.current.button == 0 && Event.current.modifiers == EventModifiers.Alt) ||            Event.current.button == 2)        {            Vector2 delta = Event.current.delta;            delta /= _zoom;            _zoomCoordsOrigin += delta;            Event.current.Use();        }    }    public void OnGUI()    {        HandleEvents();        // The zoom area clipping is sometimes not fully confined to the passed in rectangle. At certain        // zoom levels you will get a line of pixels rendered outside of the passed in area because of        // floating point imprecision in the scaling. Therefore, it is recommended to draw the zoom        // area first and then draw everything else so that there is no undesired overlap.        DrawZoomArea();        DrawNonZoomArea();    }}


using UnityEngine;using System;// Helper Rect extension methodspublic static class RectExtensions{    public static Vector2 TopLeft(this Rect rect)    {        return new Vector2(rect.xMin, rect.yMin);    }    public static Rect ScaleSizeBy(this Rect rect, float scale)    {        return rect.ScaleSizeBy(scale, rect.center);    }    public static Rect ScaleSizeBy(this Rect rect, float scale, Vector2 pivotPoint)    {        Rect result = rect;        result.x -= pivotPoint.x;        result.y -= pivotPoint.y;        result.xMin *= scale;        result.xMax *= scale;        result.yMin *= scale;        result.yMax *= scale;        result.x += pivotPoint.x;        result.y += pivotPoint.y;        return result;    }    public static Rect ScaleSizeBy(this Rect rect, Vector2 scale)    {        return rect.ScaleSizeBy(scale, rect.center);    }    public static Rect ScaleSizeBy(this Rect rect, Vector2 scale, Vector2 pivotPoint)    {        Rect result = rect;        result.x -= pivotPoint.x;        result.y -= pivotPoint.y;        result.xMin *= scale.x;        result.xMax *= scale.x;        result.yMin *= scale.y;        result.yMax *= scale.y;        result.x += pivotPoint.x;        result.y += pivotPoint.y;        return result;    }}public class EditorZoomArea{    private const float kEditorWindowTabHeight = 21.0f;    private static Matrix4x4 _prevGuiMatrix;    public static Rect Begin(float zoomScale, Rect screenCoordsArea)    {        GUI.EndGroup();        // End the group Unity begins automatically for an EditorWindow to clip out the window tab. This allows us to draw outside of the size of the EditorWindow.        Rect clippedArea = screenCoordsArea.ScaleSizeBy(1.0f / zoomScale, screenCoordsArea.TopLeft());        clippedArea.y += kEditorWindowTabHeight;        GUI.BeginGroup(clippedArea);        _prevGuiMatrix = GUI.matrix;        Matrix4x4 translation = Matrix4x4.TRS(clippedArea.TopLeft(), Quaternion.identity, Vector3.one);        Matrix4x4 scale = Matrix4x4.Scale(new Vector3(zoomScale, zoomScale, 1.0f));        GUI.matrix = translation * scale * translation.inverse * GUI.matrix;        return clippedArea;    }    public static void End()    {        GUI.matrix = _prevGuiMatrix;        GUI.EndGroup();        GUI.BeginGroup(new Rect(0.0f, kEditorWindowTabHeight, Screen.width, Screen.height));    }}

理解:

algorithm for scaling an image from a given pivot point:http://stackoverflow.com/questions/3598538/algorithm-for-scaling-an-image-from-a-given-pivot-point


Well, I don't know what framework/library you're using but you can think of it as:

  • translation to make your pivot point the center point
  • standard scaling
  • opposite transalation to make the center point the original pivot point

Translation and scaling are isomorphismes so you can represent them as matrix. Each transformation is a matrix and you can multiply them for find the combined transformation matrix. So:

  • T = transformation
  • S = scalling
  • T' = opposite transformation

If you apply T.x being x a point vector it gives you the new coordinates. The same for S.x.

So if you want to do that operations you have to do: T'. (S. (T.x))

I think you can associate operations so it's the same as (T'.S.T).x

If you are using a framework apply three operations (or combine operations and apply). If you are using crude math... go the matrix way :)





0 0
原创粉丝点击