unity EditorWindow#Focus无法触发EditorWindow#OnGUI

时间:2018-10-13 12:56:07

标签: c# unity3d

这是我的代码:

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图像,当我单击我的获胜并按下快捷键“ ctrl + g”时,控制台将输出“运行焦点”并且“按下键” enter image description here

但是如果我单击其他获胜(使我的获胜失去焦点)并按下快捷键“ ctrl + g”来获得获胜,则控制台仅输出“运行焦点”,无法在OnGUI中调用“按键” enter image description here 那么如何在脚本中聚焦EditorWindow以便使聚焦后的OnGUI工作

2 个答案:

答案 0 :(得分:1)

这个问题是因为我专注于浮动编辑器窗口,如果我拖动胜利,使其成为 tab editorwindow(请参见我的gif),EditorWindow#Focus效果很好

enter image description here

如果我真的想使用浮动赢奖

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

并使用os focus窗口代码来聚焦此胜利,在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");
        }
    }
}

答案 1 :(得分:0)

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

即使在窗口未聚焦时也可以检测按键的解决方法是使用订阅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");
        }
    }
}