yum/3ner

A toon shader for Unity's BIRP.

git clone https://git.yummers.dev/yum/3ner

yumCheck in silent's Linux Unity tab fixer2b9c5ca

master
3.4 KiB94 linesraw
1// Source: https://gist.githubusercontent.com/s-ilent/067d4e477041d52d2f8eabd78927d1a4/raw/568c222044a8ce3c33426c495cccbfe7c3a0c733/LinuxTabFix.cs
2#if UNITY_EDITOR
3using UnityEditor;
4using UnityEngine;
5using UnityEngine.UIElements;
6using System;
7using System.Collections.Generic;
8using System.Runtime.CompilerServices;
9
10/// <summary>
11/// Linux Editor Tab Navigation Patch for Unity (2022.3+, Unity 6).
12/// Restores missing ASCII '\t' character codes stripped by Linux window backend
13/// and manages focus handshakes between IMGUIContainers in UI Toolkit windows.
14/// </summary>
15[InitializeOnLoad]
16public static class LinuxTabFix
17{
18    private static readonly ConditionalWeakTable<IMGUIContainer, object> patchedContainers 
19        = new ConditionalWeakTable<IMGUIContainer, object>();
20
21    static LinuxTabFix()
22    {
23        // Ensure idempotent event subscription across domain reloads
24        EditorApplication.update -= ApplyTabPatchToFocusedWindow;
25        EditorApplication.update += ApplyTabPatchToFocusedWindow;
26    }
27
28    private static void ApplyTabPatchToFocusedWindow()
29    {
30        EditorWindow focusedWindow = EditorWindow.focusedWindow;
31        if (focusedWindow == null) return;
32
33        VisualElement root = focusedWindow.rootVisualElement;
34        if (root == null) return;
35
36        List<IMGUIContainer> containers = root.Query<IMGUIContainer>().ToList();
37        int count = containers.Count;
38
39        for (int i = 0; i < count; i++)
40        {
41            IMGUIContainer container = containers[i];
42            if (container == null) continue;
43
44            int currentIndex = i;
45
46            // Patch unhandled containers without modifying container properties
47            if (!patchedContainers.TryGetValue(container, out _))
48            {
49                patchedContainers.Add(container, null);
50                Action originalHandler = container.onGUIHandler;
51
52                container.onGUIHandler = () =>
53                {
54                    Event e = Event.current;
55
56                    if (e != null && e.type == EventType.KeyDown && e.keyCode == KeyCode.Tab)
57                    {
58                        // Restore character code stripped by Linux native window backend
59                        if (e.character == 0)
60                        {
61                            e.character = '\t';
62                        }
63
64                        bool isShift = e.shift;
65
66                        // Execute original IMGUI pass
67                        originalHandler?.Invoke();
68
69                        // When boundary is reached, transfer focus to adjacent container
70                        if (GUIUtility.keyboardControl == 0)
71                        {
72                            int targetIndex = isShift ? currentIndex - 1 : currentIndex + 1;
73
74                            if (targetIndex >= 0 && targetIndex < count && targetIndex < containers.Count)
75                            {
76                                IMGUIContainer targetContainer = containers[targetIndex];
77                                if (targetContainer != null)
78                                {
79                                    targetContainer.Focus();
80                                    focusedWindow.Repaint();
81                                }
82                            }
83                        }
84
85                        return;
86                    }
87
88                    originalHandler?.Invoke();
89                };
90            }
91        }
92    }
93}
94#endif