案例讲解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;
可以看到渲染的按钮会一直呈现蓝色。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)