案例讲解Unity中的GUIUtility.hotControl

简介

如果不结合案例,hotControl只是一个字段,没有对应的函数,我们就无法了解它实际的作用。本篇文章将会结合多个案例介绍hotControl的作用。

首先GUIUtility.hotControl就是mouseControl,GrabMouseControl函数就会将hotControl的值设置为传入的id。HasMouseControl函数也是判断hotControl的值是否和参数相等。

所以GUIUtility.hotControl鼠标的操作相关。

初始代码

这里我们使用如下的初始代码,可以看到这样的效果。

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

public class HotControlDemoWindow : EditorWindow
{
    [MenuItem("Demos/HotControlDemoWindow")]
    static void ShowWindow()
    {
        var window = GetWindow<HotControlDemoWindow>();
        Rect wr = new Rect(0, 0, 500, 500);
        //var window = GetWindowWithRect<HotControlDemoWindow>(wr);
        window.titleContent = new GUIContent("HotControlDemoWindow");
        window.Show();
    }


    private void OnEnable()
    {
    }

    private void OnGUI()
    {

        GUILayout.Label("HotControlDemoWindow");


    }

    private int GetLastControlId()
    {
        var type = typeof(EditorGUIUtility);
        var field = type.GetField("s_LastControlID", BindingFlags.Static | BindingFlags.NonPublic);
        var lastControlID = (int)field.GetValue(null);
        return lastControlID;
    }


    private GUIStyle _toolbarButtonStyle;

    private void ShowButton(Rect position)
    {
        // button style
        if (_toolbarButtonStyle == null)
        {
            _toolbarButtonStyle = new GUIStyle(GUI.skin.button)
            {
                // remove paddings
                padding = new RectOffset()
            };
        }

        // draw help button
        if (GUI.Button(position, UnityEditor.EditorGUIUtility.IconContent("_Help"), _toolbarButtonStyle))
        {
            Application.OpenURL("https://docs.unity3d.com/Manual/index.html");
        }
    }


}

案例1 hotControl被用于按钮点击事件

如果我们在初始代码的OnGUI函数末尾插入GUIUtility.hotControl = 0;

我们会发现,该窗口无法通过Button关闭,以及无法拖拽。

这里窗口右上角的最大化按钮,以及关闭按钮都是通过GUI.DoControl函数实现的,可以看到在触发MouseUp事件的时候,代码会判断当前的hotControl是否和按钮的id相同。

当我们按下鼠标时,hotControl会被设置为关闭按钮的id。但是由于我们在EditorWindow的OnGUI函数中修改了hotControl的值,所以MouseUp事件的判定会失效。导致我们无法通过该按钮关闭窗口。

internal static bool DoControl(Rect position, int id, bool on, bool hover, GUIContent content, GUIStyle style)
{
    Event current = Event.current;
    switch (current.type)
    {
        case EventType.Repaint:
            style.Draw(position, content, id, on, hover);
            break;
        case EventType.MouseDown:
            if (GUIUtility.HitTest(position, current))
            {
                GrabMouseControl(id);
                current.Use();
            }

            break;
        case EventType.KeyDown:
            {
                bool flag = current.alt || current.shift || current.command || current.control;
                if ((current.keyCode == KeyCode.Space || current.keyCode == KeyCode.Return || current.keyCode == KeyCode.KeypadEnter) && !flag && GUIUtility.keyboardControl == id)
                {
                    current.Use();
                    changed = true;
                    return !on;
                }

                break;
            }
        case EventType.MouseUp:
            if (HasMouseControl(id))
            {
                ReleaseMouseControl();
                current.Use();
                if (GUIUtility.HitTest(position, current))
                {
                    changed = true;
                    return !on;
                }
            }

            break;
        case EventType.MouseDrag:
            if (HasMouseControl(id))
            {
                current.Use();
            }

            break;
    }

    return on;
}

案例2 hotControl被用于Style.Draw

在上个案例中,我们可以看到DoControl函数调用了style.Draw函数,在底层代码中,unity会比较当前hotControlID是否和传入的controlID相同,如果相同,则当前style标记为active
通过各种标记,unity会使用不同的GUIStyleState,因此,我们可以通过hotControl修改编辑器中control的渲染结果。

在初始代码OnGUI函数末尾插入如下代码:

    GUILayout.Button("button");
    var buttonControlId = GetLastControlId();
    GUIUtility.hotControl = buttonControlId;

可以看到渲染的按钮会一直呈现蓝色。

posted @   dewxin  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示