You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
289 lines
11 KiB
289 lines
11 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
using UnityEditor;
|
|
using UnityEditorInternal;
|
|
using UnityEngine;
|
|
using Debug = UnityEngine.Debug;
|
|
|
|
namespace FullscreenEditor {
|
|
|
|
[AttributeUsage(AttributeTargets.Field)]
|
|
internal class DynamicMenuItemAttribute : Attribute {
|
|
|
|
public bool AllowNoneValue { get; private set; }
|
|
|
|
public DynamicMenuItemAttribute(bool allowNoneValue) {
|
|
AllowNoneValue = allowNoneValue;
|
|
}
|
|
|
|
}
|
|
|
|
internal class Shortcut {
|
|
|
|
#region Fields
|
|
//Always end with an space if the path has no shortcut
|
|
[DynamicMenuItem(true)] public const string TOOLBAR_PATH = "Fullscreen/Show Toolbar _F8";
|
|
[DynamicMenuItem(true)] public const string FULLSCREEN_ON_PLAY_PATH = "Fullscreen/Fullscreen On Play ";
|
|
[DynamicMenuItem(true)] public const string PREFERENCES_PATH = "Fullscreen/Preferences... ";
|
|
[DynamicMenuItem(false)] public const string CURRENT_VIEW_PATH = "Fullscreen/Focused View _F9";
|
|
[DynamicMenuItem(false)] public const string GAME_VIEW_PATH = "Fullscreen/Game View _F10";
|
|
[DynamicMenuItem(false)] public const string SCENE_VIEW_PATH = "Fullscreen/Scene View _F11";
|
|
[DynamicMenuItem(false)] public const string MAIN_VIEW_PATH = "Fullscreen/Main View _F12";
|
|
[DynamicMenuItem(false)] public const string MOSAIC_PATH = "Fullscreen/Mosaic %F10";
|
|
[DynamicMenuItem(true)] public const string CLOSE_ALL_FULLSCREEN = "Fullscreen/Close All %F12";
|
|
|
|
private const char CTRL_CHAR = '%';
|
|
private const char SHIFT_CHAR = '#';
|
|
private const char ALT_CHAR = '&';
|
|
private const char NONE_CHAR = '_';
|
|
|
|
private static readonly List<Shortcut> fieldsInfo = new List<Shortcut>();
|
|
/* fixformat ignore:start */
|
|
private static readonly string[] keys = new string[] {
|
|
"None",
|
|
"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12",
|
|
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
|
|
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
|
|
"LEFT", "RIGHT", "UP", "DOWN", "HOME", "END", "PGUP", "PGDN"
|
|
};
|
|
/* fixformat ignore:end */
|
|
|
|
private static bool changed;
|
|
#endregion
|
|
|
|
#region Properties
|
|
public bool Ctrl { get; set; }
|
|
public bool Shift { get; set; }
|
|
public bool Alt { get; set; }
|
|
public int KeyCode { get; set; }
|
|
|
|
public bool AllowNoneValue { get; private set; }
|
|
public string FieldName { get; private set; }
|
|
public string BaseString { get; private set; }
|
|
public string Label { get { return BaseString.Substring(BaseString.LastIndexOf('/') + 1); } }
|
|
|
|
private static bool IsSourceFile { get { return !string.IsNullOrEmpty(ThisFilePath) && File.Exists(ThisFilePath); } }
|
|
private static string ThisFilePath {
|
|
get {
|
|
try {
|
|
return new StackFrame(true).GetFileName();
|
|
} catch (Exception e) {
|
|
Logger.Exception(e);
|
|
return string.Empty;
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Constructors
|
|
static Shortcut() {
|
|
var type = typeof(Shortcut);
|
|
var fields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);
|
|
|
|
if (fields != null)
|
|
foreach (var field in fields) {
|
|
var att = field.GetCustomAttributes(typeof(DynamicMenuItemAttribute), false);
|
|
|
|
if (att != null)
|
|
for (var i = 0; i < att.Length; i++)
|
|
fieldsInfo.Add(new Shortcut((DynamicMenuItemAttribute)att[i], field));
|
|
}
|
|
}
|
|
|
|
public Shortcut(DynamicMenuItemAttribute shortcutAttribute, FieldInfo field) {
|
|
FieldName = field.Name;
|
|
AllowNoneValue = shortcutAttribute.AllowNoneValue;
|
|
|
|
var constant = (string)field.GetValue(null);
|
|
var lastSpace = constant.LastIndexOf(' ') + 1;
|
|
|
|
if (!constant.EndsWith(" "))
|
|
BaseString = constant.Remove(lastSpace);
|
|
else {
|
|
BaseString = constant;
|
|
return;
|
|
}
|
|
|
|
constant = constant.Substring(lastSpace);
|
|
|
|
if (string.IsNullOrEmpty(constant))
|
|
return;
|
|
|
|
Ctrl = constant.Contains(CTRL_CHAR);
|
|
Shift = constant.Contains(SHIFT_CHAR);
|
|
Alt = constant.Contains(ALT_CHAR);
|
|
|
|
constant = constant.Replace(CTRL_CHAR.ToString(), string.Empty);
|
|
constant = constant.Replace(SHIFT_CHAR.ToString(), string.Empty);
|
|
constant = constant.Replace(ALT_CHAR.ToString(), string.Empty);
|
|
constant = constant.Replace(NONE_CHAR.ToString(), string.Empty);
|
|
|
|
KeyCode = Array.IndexOf(keys, constant);
|
|
|
|
if (KeyCode < 0 || KeyCode >= keys.Length) {
|
|
Logger.Warning("Invalid shortcut term: {0}", constant);
|
|
KeyCode = 0;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
public string GetShortcutString() {
|
|
if (KeyCode == 0)
|
|
return "";
|
|
|
|
var result = new StringBuilder();
|
|
|
|
if (!Ctrl && !Shift && !Alt)
|
|
result.Append(NONE_CHAR);
|
|
else {
|
|
if (Ctrl)
|
|
result.Append(CTRL_CHAR);
|
|
if (Shift)
|
|
result.Append(SHIFT_CHAR);
|
|
if (Alt)
|
|
result.Append(ALT_CHAR);
|
|
}
|
|
|
|
result.Append(keys[KeyCode]);
|
|
|
|
return result.ToString();
|
|
}
|
|
|
|
#region Methods
|
|
public override string ToString() {
|
|
return BaseString + GetShortcutString();
|
|
}
|
|
|
|
public static void DoShortcutsGUI() {
|
|
GUI.changed = false;
|
|
|
|
using(new EditorGUI.DisabledGroupScope(EditorApplication.isCompiling || !IsSourceFile)) {
|
|
|
|
if (InternalEditorUtility.GetUnityVersion() >= new Version(2019, 1))
|
|
EditorGUILayout.HelpBox(string.Format("You can set custom shortcuts on a per user basis by editing them under {0} menu", FullscreenUtility.IsMacOS ? "Unity/Shortcuts" : "Edit/Shortcuts"), MessageType.Info);
|
|
|
|
foreach (var field in fieldsInfo)
|
|
DrawShortcut(field);
|
|
|
|
var duplicated = AnyDuplicates();
|
|
var invalid = AnyInvalid();
|
|
|
|
if (duplicated)
|
|
EditorGUILayout.HelpBox("Some menu items have the same keystroke, this is not allowed.", MessageType.Error);
|
|
|
|
if (invalid)
|
|
EditorGUILayout.HelpBox("Some menu items don't have a valid keystroke, you won't be able to use their correspondent fullscreens.", MessageType.Warning);
|
|
|
|
using(new EditorGUI.DisabledGroupScope(duplicated || !changed))
|
|
if (GUILayout.Button("Apply Shortcuts"))
|
|
ApplyChanges();
|
|
}
|
|
|
|
if (GUI.changed)
|
|
changed = true;
|
|
}
|
|
|
|
private static void ApplyChanges() {
|
|
if (EditorApplication.isCompiling)
|
|
return;
|
|
|
|
AssetDatabase.StartAssetEditing();
|
|
|
|
foreach (var field in fieldsInfo)
|
|
ReplaceConstant(field.FieldName, field);
|
|
|
|
AssetDatabase.StopAssetEditing();
|
|
AssetDatabase.Refresh();
|
|
}
|
|
|
|
private static bool AnyInvalid() {
|
|
foreach (var field in fieldsInfo)
|
|
if (field == null || !field.AllowNoneValue && field.KeyCode == 0)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
private static bool AnyDuplicates() {
|
|
for (var i = 0; i < fieldsInfo.Count; i++)
|
|
for (var j = i + 1; j < fieldsInfo.Count; j++) {
|
|
var fieldI = fieldsInfo[i];
|
|
var fieldJ = fieldsInfo[j];
|
|
|
|
if (fieldI == null || fieldJ == null ||
|
|
(fieldI.KeyCode != 0 && fieldI.GetShortcutString() == fieldJ.GetShortcutString()))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private static Shortcut DrawShortcut(Shortcut shortcut) {
|
|
using(new EditorGUILayout.HorizontalScope()) {
|
|
EditorGUILayout.LabelField(shortcut.Label, GUILayout.Width(130f));
|
|
|
|
shortcut.Ctrl = GUILayout.Toggle(shortcut.Ctrl, FullscreenUtility.IsMacOS ? "Cmd" : "Ctrl", EditorStyles.miniButtonLeft, GUILayout.Width(50f));
|
|
shortcut.Shift = GUILayout.Toggle(shortcut.Shift, "Shift", EditorStyles.miniButtonMid, GUILayout.Width(50f));
|
|
shortcut.Alt = GUILayout.Toggle(shortcut.Alt, "Alt", EditorStyles.miniButtonRight, GUILayout.Width(50f));
|
|
shortcut.KeyCode = EditorGUILayout.Popup(shortcut.KeyCode, keys);
|
|
|
|
if (GUILayout.Button(new GUIContent("X", "Clear Shortcut"))) {
|
|
shortcut.Ctrl = false;
|
|
shortcut.Shift = false;
|
|
shortcut.Alt = false;
|
|
shortcut.KeyCode = 0;
|
|
}
|
|
}
|
|
|
|
return shortcut;
|
|
}
|
|
|
|
private static void ReplaceConstant(string constantName, object newValue) {
|
|
try {
|
|
if (!IsSourceFile) {
|
|
Logger.Error("Could not find the source code file to change value");
|
|
return;
|
|
}
|
|
|
|
var fileText = new StringBuilder();
|
|
var changed = false;
|
|
|
|
using(var file = File.OpenText(ThisFilePath))
|
|
while (!file.EndOfStream) {
|
|
var line = file.ReadLine();
|
|
|
|
if (!line.Contains(constantName)) {
|
|
fileText.AppendLine(line);
|
|
continue;
|
|
}
|
|
|
|
var indexOfValue = line.IndexOf('=');
|
|
|
|
fileText.Append(line.Remove(indexOfValue));
|
|
fileText.AppendLine(string.Format("= \"{0}\";", newValue));
|
|
fileText.Append(file.ReadToEnd());
|
|
|
|
changed = true;
|
|
}
|
|
|
|
fileText = fileText.Replace("\r\n", "\n").Replace("\r", "\n").Replace("\n", Environment.NewLine);
|
|
|
|
if (changed)
|
|
File.WriteAllText(ThisFilePath, fileText.ToString());
|
|
else
|
|
Logger.Warning("Failed to find field {0} on {1}", constantName, ThisFilePath);
|
|
} catch (Exception e) {
|
|
Logger.Exception(e);
|
|
Logger.Error("Failed to save Fullscreen Editor shortcuts");
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
}
|
|
|
|
}
|
|
|