【问题标题】:unity EditorWindow#Focus cannot trigger EditorWindow#OnGUIunity EditorWindow#Focus 无法触发 EditorWindow#OnGUI
【发布时间】:2018-10-13 12:56:07
【问题描述】:

这是我的代码:

public class RoEditorWindow : EditorWindow
{
    private static RoEditorWindow win;

    [MenuItem("Window/Ro Editor Window %g")]
    static void St()
    {
        if (!win)
        {
            win = EditorWindow.GetWindow<RoEditorWindow>();
        }
        else
        {
            Debug.Log("Run focus");
            win.Focus();
        }
    }

    private void OnGUI()
    {
        var ev = Event.current;
        if (ev.isKey )
        {
            Debug.Log("key is pressed");
        }
    }
}

查看我的 gif,当我点击我的 win 并点击快捷键“ctrl+g”时,控制台将输出“运行焦点”和“按键被按下”

但是如果我点击其他win(使我的win失去焦点)并点击快捷键“ctrl+g”来关注win,控制台只输出“运行焦点”,无法调用OnGUI中的“按键” 那么如何在脚本中聚焦EditorWindow以使OnGUI在聚焦后工作

【问题讨论】:

    标签: c# unity3d


    【解决方案1】:

    这个问题是因为我关注 floating editorwindow,如果我拖动我的 win 使其成为 tab editorwindow(见我的 gif),EditorWindow#Focus 工作得很好

    如果我真的想使用浮动获胜

    这是我的解决方案,使用 EditorWindow#ShowAuxWindow 和 EditorWindow#titleContent 创建包含当前项目统一编辑器进程 ID 的标题的编辑器窗口

    并使用os focus window code来聚焦这个win,在linux我可以用xdotool,在windows,我猜win32 api可以做到,我觉得mac也有类似的方法

    这是我的 linux 解决方案的统一编辑器:

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Threading;
    using UnityEditor;
    using UnityEngine;
    using Debug = UnityEngine.Debug;
    
    public class RoEditorWindow : EditorWindow
    {
        private static RoEditorWindow win;
    
        [MenuItem("Window/Ro Editor Window %g")]
        static void St()
        {
            if (!win)
            {
                win = ScriptableObject.CreateInstance<RoEditorWindow>();
            }
    
            Debug.Log("Run Focus");
            win.ShowAuxWindow();
            EditorWindow.FocusWindowIfItsOpen<RoEditorWindow>();
            var title = $"Ro Editor Windows in Process {Process.GetCurrentProcess().Id}";
            win.SetTitle(title);
            new Thread(() =>
            {
                var startAt = DateTime.Now;
                while (true)
                {
                    try
                    {
                        var cmd = $"xdotool search --name --onlyvisible --limit  1 \"{title}\"";
                        var wid = Sh(cmd);
                        if (wid != "")
                        {
                            Sh($"xdotool windowactivate {wid}");
                            break;
                        }
                    }
                    catch (SystemException e)
                    {
                    }
    
                    if ((DateTime.Now - startAt).TotalSeconds > 5)
                    {
                        break;
                    }
                }
            }).Start();
        }
    
        public static string Sh(string cmd)
        {
            string output = "";
            string error = string.Empty;
    
            var psi = new ProcessStartInfo("/bin/bash", $"-c '{cmd}'");
    
            psi.RedirectStandardOutput = true;
            psi.RedirectStandardError = true;
            psi.UseShellExecute = false;
            Process p = Process.Start(psi);
            using (System.IO.StreamReader myOutput = p.StandardOutput)
            {
                output = myOutput.ReadToEnd();
            }
    
            using (System.IO.StreamReader myError = p.StandardError)
            {
                error = myError.ReadToEnd();
            }
    
            if (error != "")
            {
                throw new SystemException($"err cmd: {cmd}\n{error}");
            }
    
            return output;
        }
    
    
        public void SetTitle(string v)
        {
            titleContent = new GUIContent(v);
        }
    
        private void OnGUI()
        {
            EditorGUILayout.TextField("input", "");
            if (Event.current.isKey)
            {
                Debug.Log("key is pressed");
            }
        }
    }
    

    【讨论】:

    • 我即将给出答案,因为这仅适用于 Linux
    【解决方案2】:

    您当前的代码应该可以工作。在我这边进行了测试,效果很好。我只是假设这是编辑器中的一个错误。

    即使在 Window 未获得焦点时也检测按键的解决方法是使用订阅 EditorApplication.globalEventHandler 事件。不幸的是,这个函数被标记为internal,所以你不能直接访问它,但是你可以使用反射来访问它。这应该适用于支持编辑器的任何平台。

    在下面的例子中,当你按下 Ctrl+G 时你会得到一个日志。

    public class RoEditorWindow : EditorWindow
    {
        private static RoEditorWindow win;
        EditorApplication.CallbackFunction appCb;
    
        [MenuItem("Window/Ro Editor Window %g")]
        static void St()
        {
            if (!win)
            {
                win = EditorWindow.GetWindow<RoEditorWindow>();
            }
            else
            {
    
                Debug.Log("Run focus");
                win.Focus();
            }
        }
    
        void OnEnable()
        {
            EnableInputEvent();
        }
    
        void OnDisable()
        {
            DisableInputEvent();
        }
    
        void EnableInputEvent()
        {
            FieldInfo fieldInfo = typeof(EditorApplication).GetField("globalEventHandler", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
            appCb = (EditorApplication.CallbackFunction)fieldInfo.GetValue(null);
            appCb += OnEditorKeyPress;
            fieldInfo.SetValue(null, appCb);
        }
    
        void DisableInputEvent()
        {
            FieldInfo fieldInfo = typeof(EditorApplication).GetField("globalEventHandler", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
            appCb -= OnEditorKeyPress;
            fieldInfo.SetValue(null, appCb);
        }
        private void OnEditorKeyPress()
        {
            var ev = Event.current;
            if (ev.control && ev.type == EventType.KeyDown && ev.keyCode == KeyCode.G)
            {
                Debug.Log("key is pressed");
            }
        }
    }
    

    【讨论】:

    • 它不起作用,见imgur.com/a/kcd3V2u,我认为是unity linux editor 2017.4.10 bug 或linux mint xfce4 bug,unity linux editor 在linux 中有很多焦点bug,大多数情况下我可以用xdotool 修复它,所以我认为我的代码是正确的,但它在unity linux 编辑器中不起作用
    • 我知道您的代码是正确的,并认为这是 Linux 上的错误。我将此作为一种解决方法,这很可悲,因为它也不起作用。虽然,它应该可以在 Windows 和 Mac 上运行
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-11
    • 2021-08-08
    • 2019-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多