Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pan/scale the contents inside a GUI area?

Tags:

unity3d

I want to have a zoom effect inside an area in a EditorWindow, something like a zoomable scrollview.

The following snippet deals only with the panning effect but it exemplifies the issue I'm having when the contents inside the zoomable area and the clipping rect can't be handled independently of each other through hSliderValue1 (clipping) and hSliderValue2 (panning).

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class ZoomTestWindow : EditorWindow
{
    private static float kEditorWindowTabHeight = 20;
    private static Matrix4x4 _prevGuiMatrix;
    public static float hSliderValue1 = 0;
    public static float hSliderValue2 = 0;

    Rect[] wr = new Rect[]{
        new Rect(0, 0, 100, 100),
        new Rect(50, 50, 100, 100),
        new Rect(100, 100, 100, 100)
    };

    [MenuItem("Window/Zoom Test #%w")]
    private static void Init()
    {
        ZoomTestWindow window = EditorWindow.GetWindow<ZoomTestWindow>("Zoom Test", true, new System.Type[] {
            typeof(UnityEditor.SceneView),
            typeof(EditorWindow).Assembly.GetType("UnityEditor.SceneHierarchyWindow")});

        window.Show();
        EditorWindow.FocusWindowIfItsOpen<ZoomTestWindow>();
    }

    public static Rect BeginZoomArea()
    {
        GUI.EndGroup(); //End the group that Unity began so we're not bound by the EditorWindow

        GUI.BeginGroup(new Rect(hSliderValue1, 0, 200, 200));

        _prevGuiMatrix = GUI.matrix;

        GUI.matrix = Matrix4x4.TRS(new Vector2(hSliderValue2, 0), Quaternion.identity, Vector3.one);;

        return new Rect();
    }

    public static void EndZoomArea()
    {
        GUI.matrix = _prevGuiMatrix;
        GUI.EndGroup();
        GUI.BeginGroup(new Rect(0.0f, kEditorWindowTabHeight, Screen.width, Screen.height - (kEditorWindowTabHeight + 3)));
    }

    public void OnGUI()
    {
        BeginZoomArea();

        BeginWindows();
        wr[0] = GUI.Window(0, wr[0], DrawWindow, "hello");
        wr[1] = GUI.Window(1, wr[1], DrawWindow, "world");
        wr[2] = GUI.Window(2, wr[2], DrawWindow, "!");
        EndWindows();

        EndZoomArea();

        hSliderValue1 = GUI.HorizontalSlider(new Rect(200, 5, 100, 30), hSliderValue1, 0, 100);
        hSliderValue2 = GUI.HorizontalSlider(new Rect(200, 25, 100, 30), hSliderValue2, 0, 100);
    }

    void DrawWindow(int id)
    {
        GUI.Button(new Rect(0, 30, 100, 50), "Wee!");
        GUI.DragWindow();
    }
}

enter image description here

Is there a way to do this, maybe by using a scroll view?

like image 382
rraallvv Avatar asked Oct 18 '22 22:10

rraallvv


1 Answers

Embed the group controlled by hSliderValue1 inside a new group.

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class ZoomMoveTestWindow: EditorWindow
{
    private static float kEditorWindowTabHeight = 20;
    private static Matrix4x4 _prevGuiMatrix;
    public static float hSliderValue1 = 0;
    public static float hSliderValue2 = 0;

    Rect[] wr = new Rect[]{
        new Rect(0, 0, 100, 100),
        new Rect(50, 50, 100, 100),
        new Rect(100, 100, 100, 100)
    };

    [MenuItem("Window/Zoom Test #%w")]
    private static void Init()
    {
        ZoomMoveTestWindow window = EditorWindow.GetWindow<ZoomMoveTestWindow>("Zoom Test", true, new System.Type[] {
            typeof(UnityEditor.SceneView),
            typeof(EditorWindow).Assembly.GetType("UnityEditor.SceneHierarchyWindow")});

        window.Show();
        EditorWindow.FocusWindowIfItsOpen<ZoomMoveTestWindow>();
    }

    public static Rect BeginZoomArea(Rect rect)
    {
        GUI.BeginGroup(rect);

        GUI.BeginGroup(new Rect(hSliderValue1, 0, 200, 200));

        _prevGuiMatrix = GUI.matrix;

        GUI.matrix = Matrix4x4.TRS(new Vector2(hSliderValue2, 0), Quaternion.identity, Vector3.one);

        return new Rect();
    }

    public static void EndZoomArea()
    {
        GUI.EndGroup();

        GUI.matrix = _prevGuiMatrix;
        GUI.EndGroup();
        GUI.BeginGroup(new Rect(0.0f, kEditorWindowTabHeight, Screen.width, Screen.height - (kEditorWindowTabHeight + 3)));
    }

    public void OnGUI()
    {
        GUI.EndGroup(); //End the group that Unity began so we're not bound by the EditorWindow

        BeginZoomArea(new Rect(10,10, 200, 200));

        BeginWindows();
        wr[0] = GUI.Window(0, wr[0], DrawWindow, "hello");
        wr[1] = GUI.Window(1, wr[1], DrawWindow, "world");
        wr[2] = GUI.Window(2, wr[2], DrawWindow, "!");
        EndWindows();

        EndZoomArea();

        hSliderValue1 = GUI.HorizontalSlider(new Rect(250, 5, 100, 30), hSliderValue1, 0, 100);
        hSliderValue2 = GUI.HorizontalSlider(new Rect(250, 35, 100, 30), hSliderValue2, 0, 100);
    }

    void DrawWindow(int id)
    {
        GUI.Button(new Rect(0, 30, 100, 50), "Wee!");
        GUI.DragWindow();
    }
}

result

It works but I don't know why. Because the interaction of GUI.matrix and BeginGroup(rect) is unknown.

PS: This post may help you.

like image 102
zwcloud Avatar answered Oct 21 '22 03:10

zwcloud