Net.Like.Xue.Tokyo/Assets/Plugins/MonKey Commander/Editor/MonKey/Commands/CommandManager.cs

1242 lines
43 KiB
C#

#if UNITY_EDITOR
using MonKey.Extensions;
using MonKey.Internal;
using MonKey.Settings.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading;
using UnityEditor;
using UnityEngine;
using Component = UnityEngine.Component;
using Object = UnityEngine.Object;
using ThreadPriority = System.Threading.ThreadPriority;
namespace MonKey.Editor.Internal
{
[InitializeOnLoad]
public class CommandManager : EditorSingleton<CommandManager>, IMonKeySingleton
{
static CommandManager()
{
SessionID = "MC_CommandManager";
}
public static bool ReadyForPlayMode;
public static string CommandHistory = "Command History";
#region SINGLETON
private static CommandManager instance;
#endregion
#region REGISTERING
public bool IsLoading { get; private set; }
private readonly List<CommandInfo> infoToAdd = new List<CommandInfo>();
public string CurrentAssemblyLoading;
public string CurrentClassLoading;
public int AssemblyAnalyzed;
public int TotalAssemblies;
private readonly int amountSleepThreshold = 10;
public bool onlyScanSpecified;
private string[] assembliesToExclude;
private string[] nameSpacesToExclude;
public event Action OnCommandLoadingDone;
#endregion
public const int MaxCommandShown = 15;
private const int CommandFoundCountForAliases = 15;
private readonly CommandInfo defaultInfo = new CommandInfo()
{
Action = null,
CommandHelp = "No Command Found",
CommandName = "No Command Found",
CommandOrder = 0
};
internal readonly Dictionary<string, CommandCategory> CategoriesByName
= new Dictionary<string, CommandCategory>();
internal readonly List<string> BaseCategories = new List<string>();
internal readonly Dictionary<string, CommandInfo> CommandsByName
= new Dictionary<string, CommandInfo>();
public Dictionary<string, string> WordAliases
= new Dictionary<string, string>();
public int CommandCount => CommandsByName.Count;
public void PostInstanceCreation()
{
MonKeyInternalSettings.FindInstance();
MonkeyStyle.FindInstance();
MonkeyLocalizationFile.FindInstance();
Instance.OnEnable();
/*f (CommandConsoleWindow.CurrentPanel)
CommandConsoleWindow.CurrentPanel.CloseOrSetInactive();*/
}
public void OnEnable()
{
InitAliases();
AutoCompleteManager.InitializeManager();
MonkeyEditorUtils.EditorUpdatePlug(this);
MonKeySelectionUtils.PluginImporter();
RetrieveAllCommands();
}
private void InitAliases()
{
WordAliases = new Dictionary<string, string>
{
{ "Select", "Find" },
{ "Find", "Select" },
{ "Create", "New" },
{ "New", "Create" },
{ "Instantiate", "New" },
{ "Prefab", "Instance" },
{ "Place", "Move" },
{ "Raycast", "Collision" },
{ "Search", "Find" },
{ "Copy", "Duplicate" },
{ "Duplicate", "Copy" },
{ "Clone", "Duplicate" },
{ "UnSelect", "Clear" },
{ "Deselect", "Clear" }
};
}
public static void RetrieveAll()
{
if (!instance)
FindInstance();
if (!EditorApplication.isPlayingOrWillChangePlaymode && instance)
{
if (DebugLog)
Debug.Log("Retrieving on did reload");
instance.OnEnable();
}
}
private Thread commandsRetrieving;
public void RetrieveAllCommands(bool force = false)
{
/* if (!instance)
FindInstance();*/
try
{
if (DebugLog)
Debug.Log("Retrieving");
if (!force)
{
if (CommandCount > 0)
{
if (DebugLog)
Debug.Log("Canceled because some commands already found");
return;
}
if (commandsRetrieving != null)
{
if (commandsRetrieving.IsAlive)
{
if (DebugLog)
Debug.Log("Canceled because thread is alive");
return;
}
}
}
if (DebugLog)
Debug.Log("NOT CANCELED");
EditorApplication.update -= AddAllFoundCommand;
EditorApplication.update += AddAllFoundCommand;
HotKeysManager.Reset();
lock (infoToAdd)
{
infoToAdd.Clear();
}
onlyScanSpecified = MonKeyInternalSettings.Instance.OnlyScanSpecified;
assembliesToExclude = MonKeyInternalSettings.Instance.ExcludedAssemblies.Split(';');
nameSpacesToExclude = MonKeyInternalSettings.Instance.ExcludedNameSpaces.Split(';');
CommandsByName.Clear();
TypeManager.Clear();
IsLoading = true;
if (commandsRetrieving != null && commandsRetrieving.ThreadState == ThreadState.Running)
commandsRetrieving?.Abort();
commandsRetrieving = new Thread(CheckCommandsForAllAssemblies)
{
IsBackground = true,
Priority = ThreadPriority.Normal,
};
commandsRetrieving.Start();
}
catch (Exception e)
{
// Unity is not ready yet for instance creation
Debug.Log("MonKey error: \n" + e);
return;
}
}
#region REGISTERING
private void AddAllFoundCommand()
{
if (!IsLoading)
{
lock (infoToAdd)
{
if (infoToAdd.Count > 0)
{
foreach (var info in infoToAdd)
{
AddCommand(info.CommandName, info);
}
}
infoToAdd.Clear();
OnCommandLoadingDone?.Invoke();
BaseCategories.Sort();
CommandCategory history = new CommandCategory();
history.CategoryName = CommandHistory;
if (!BaseCategories.Contains(history.CategoryName))
BaseCategories.Insert(0, history.CategoryName);
if (!CategoriesByName.ContainsKey(history.CategoryName))
CategoriesByName.Add(history.CategoryName, history);
EditorApplication.update -= AddAllFoundCommand;
}
}
else
{
lock (infoToAdd)
{
foreach (var info in infoToAdd)
{
AddCommand(info.CommandName, info);
}
infoToAdd.Clear();
}
}
}
private void AddCommand(string name, CommandInfo action)
{
if (!CommandsByName.ContainsKey(name))
{
if (DebugLog)
{
Debug.Log("Adding new command: " + name);
}
CommandsByName.Add(name, action);
if (action.HasQuickName)
{
if (!CommandsByName.ContainsKey(action.CommandQuickName))
{
CommandsByName.Add(action.CommandQuickName, action);
}
else if (CommandsByName[action.CommandQuickName].CommandOrder > action.CommandOrder)
{
CommandsByName[action.CommandQuickName] = action;
}
}
if (action.HasHotKeys)
{
HotKeysManager.RegisterCommandHotKey(action);
}
}
}
private void CheckCommandsForAllAssemblies()
{
try
{
IEnumerable<Assembly> selectedAssemblies = AppDomain.CurrentDomain.GetAssemblies()
.Where(_ =>
{
int i = 0;
foreach (var assemblyPrefix in assembliesToExclude)
{
if (assemblyPrefix.IsNullOrEmpty())
{
continue;
}
if (_.GetName().Name.Contains(assemblyPrefix))
{
if (onlyScanSpecified)
{
return true;
}
else
{
if (DebugLog)
{
Debug.Log("Assembly Excluded: " + _.FullName);
}
return false;
}
}
if (i > amountSleepThreshold)
{
Thread.Sleep(0);
i = 0;
}
i++;
}
if (DebugLog)
{
Debug.Log("Assembly Added: " + _.FullName);
}
if (onlyScanSpecified)
{
return false;
}
else
return true;
}).OrderByDescending(_ => _ == Assembly.GetExecutingAssembly());
var assemblies = selectedAssemblies.ToArray();
assemblies = assemblies.OrderByDescending(_ => _.FullName == "Assembly-CSharp").ToArray();
TotalAssemblies = assemblies.Length;
AssemblyAnalyzed = 0;
CheckCommandsForAssemblies(assemblies);
}
catch (Exception e)
{
Debug.LogError("MonKey: An Exception (" + e + ") \n \n was raised when reading commands ");
// RetrieveAllCommands(true);
}
}
private void CheckCommandsForAssemblies(IEnumerable<Assembly> selectedAssemblies)
{
foreach (var assembly in selectedAssemblies)
{
CurrentAssemblyLoading = assembly.GetName().Name;
if (DebugLog)
{
Debug.Log("Checking Assembly ".Bold() + CurrentAssemblyLoading);
}
try
{
CheckCommandsFromAssembly(assembly);
}
catch (Exception e)
{
Debug.LogError("MonKey: An Exception (" + e + ") \n \n was raised when reading commands " +
"from assembly '" + assembly + "'");
// RetrieveAllCommands(true);
}
lock (this)
{
AssemblyAnalyzed++;
}
}
if (DebugLog)
{
Debug.Log("Done!");
}
IsLoading = false;
}
private void CheckCommandsFromAssembly(Assembly assembly)
{
int i = 0;
IEnumerable<Type> types = assembly.GetTypes().Where(_ =>
{
foreach (var nameSpace in nameSpacesToExclude)
{
if (nameSpace.IsNullOrEmpty())
{
continue;
}
if (_.Namespace.Contains(nameSpace))
{
return false;
}
}
return true;
});
// int prevCommandCount = CommandCount;
foreach (var type in types)
{
CurrentClassLoading = type.Name;
if (DebugLog)
{
Debug.Log("Checking Type :" + CurrentClassLoading);
}
try
{
RegisterUnityType(type);
RegisterCommandsFromType(type);
}
catch (Exception e)
{
Debug.LogError("MonKey: An Exception \n(" + e + ") \n \n was raised when reading commands " +
"from type '" + type + "'");
// RetrieveAllCommands(true);
}
i++;
if (i > amountSleepThreshold)
{
i = 0;
Thread.Sleep(0);
}
}
// if(CommandCount>prevCommandCount)
// Debug.Log(assembly.FullName);
}
private static void RegisterUnityType(Type type)
{
lock (TypeManager.AllEditorTypes)
{
if (type.FullName == null)
{
return;
}
if (type.FullName.Contains("UnityEditor")
|| type.IsSubclassOf(typeof(UnityEditor.Editor))
|| type.IsSubclassOf(typeof(EditorWindow)))
{
if (!TypeManager.AllEditorTypes.ContainsKey(type.FullName))
{
TypeManager.AllEditorTypes.Add(type.FullName, type);
}
return;
}
}
lock (TypeManager.AllMonoBehaviorObjectTypes)
{
if (type.IsSubclassOf(typeof(MonoBehaviour)))
{
if (type.FullName != null
&& !TypeManager.AllMonoBehaviorObjectTypes.ContainsKey(type.FullName))
{
TypeManager.AllMonoBehaviorObjectTypes.Add(type.FullName, type);
}
return;
}
}
lock (TypeManager.AllScriptableObjectTypes)
{
if (type.IsSubclassOf(typeof(ScriptableObject)))
{
if (type.FullName != null &&
!TypeManager.AllScriptableObjectTypes.ContainsKey(type.FullName))
{
TypeManager.AllScriptableObjectTypes.Add(type.FullName, type);
}
return;
}
}
lock (TypeManager.AllComponentObjectTypes)
{
if (type.IsSubclassOf(typeof(Component)))
{
if (type.FullName != null &&
!TypeManager.AllComponentObjectTypes.ContainsKey(type.FullName))
{
TypeManager.AllComponentObjectTypes.Add(type.FullName, type);
}
return;
}
}
lock (TypeManager.AllObjectsTypes)
{
if (type.IsSubclassOf(typeof(Object)))
{
if (type.FullName != null && !TypeManager.AllObjectsTypes.ContainsKey(type.FullName))
{
TypeManager.AllObjectsTypes.Add(type.FullName, type);
}
}
}
}
public void RegisterCommandsFromType(Type type)
{
foreach (var methodInfo in
type.GetMethods(BindingFlags.Public | BindingFlags.Default
| BindingFlags.NonPublic | BindingFlags.Static))
{
try
{
var quickCommandAttributes = methodInfo.GetCustomAttributes(typeof(Command), true);
if (quickCommandAttributes.Length > 0)
{
foreach (var commandAttribute in
(methodInfo.GetCustomAttributes(typeof(Command), true)))
{
if (DebugLog)
{
Debug.Log("Console Command Found! :".Bold().Colored(Color.green)
+ methodInfo.Name);
}
CheckCommandStatuses(type, commandAttribute, methodInfo, false);
}
}
else
{
foreach (var commandAttribute in
methodInfo.GetCustomAttributes(typeof(MenuItem), true))
{
if (DebugLog)
{
Debug.Log("Menu Item Found! :".Bold().Colored(Color.green) + methodInfo.Name);
}
MenuItem item = (MenuItem)commandAttribute;
if (item.validate)
{
continue;
}
if (methodInfo.GetCustomAttributes(typeof(MenuItemCommandLink), true).Length > 0)
{
continue;
}
CheckCommandStatuses(type, commandAttribute, methodInfo, true);
}
}
}
catch (Exception e)
{
Debug.LogErrorFormat("MonKey: An Exception was raised when " +
"trying to retrieve a command " +
"from method {0} in type {1}, assemble {2}: {3}",
methodInfo.Name, type.Name, type.Assembly.GetName().Name, e);
// RetrieveAllCommands(true);
}
}
}
private void CheckCommandStatuses(Type actionProvider, object commandAttribute,
MethodInfo methodInfo, bool menuItem)
{
Command command = commandAttribute as Command;
var validationName = CheckValidationMethod(actionProvider
, methodInfo, command, out var validationDelegate);
var hotKey = FindHotKey(methodInfo, command);
var commandParamsInfos = FindParameters(methodInfo);
if (command == null && commandParamsInfos != null && commandParamsInfos.Count > 0)
{
return;
}
AddCommandInfo(methodInfo, validationDelegate, command,
validationName, hotKey, commandParamsInfos);
}
private void AddCommandInfo(MethodInfo methodInfo, MethodInfo validationDelegate,
Command command, string validationMessage, KeyCombination hotKey,
List<CommandParameterInfo> paramInfos)
{
lock (infoToAdd)
{
if (DebugLog)
{
Debug.Log("Adding Command HotKeyInfo");
}
string menuItemName = methodInfo.Name.NicifyVariableName();
if (command == null)
{
object[] items = methodInfo.GetCustomAttributes(typeof(MenuItem), false);
if (items.Length > 0)
{
MenuItem item = (MenuItem)items[0];
int startOfName = item.menuItem.LastIndexOf("/", StringComparison.Ordinal);
int endOfName = hotKey != null
? item.menuItem.LastIndexOf(" ", StringComparison.Ordinal) - 1
: item.menuItem.Length - 1;
menuItemName = item.menuItem.Substring(startOfName + 1, endOfName - startOfName);
}
}
CommandInfo info = new CommandInfo()
{
Action = methodInfo,
ValidationMethod = validationDelegate,
AlwaysShow = command != null && command.AlwaysShow,
CommandHelp = command?.Help,
CommandName = (command != null) ? command.Name : menuItemName,
CommandQuickName = (command != null) ? command.QuickName : null,
CommandOrder = (command != null) ? command.Order : Int32.MaxValue,
CommandValidationMessage = validationMessage,
HotKey = hotKey,
IgnoreHotKeyConflict = command != null && command.IgnoreHotKeyConflict,
CommandParameterInfo = paramInfos,
IsMenuItem = command == null,
Category = command == null ? "Unity Menus" : command.Category
};
infoToAdd.Add(info);
AddCategories(info);
}
}
private void AddCategories(CommandInfo info)
{
string[] categories = info.Category.Split('/');
string path = "";
for (int i = 0; i < categories.Length; i++)
{
path += categories[i];
if (!CategoriesByName.ContainsKey(path))
{
CommandCategory cat = new CommandCategory();
cat.CategoryName = categories[i];
if (i > 0)
{
cat.ParentCategoryName = path.Replace("/" + categories[i], "");
}
else
{
BaseCategories.Add(path);
}
CategoriesByName.Add(path, cat);
}
else if (categories.Length > 1 && i < categories.Length - 1)
{
CommandCategory main = CategoriesByName[path];
main.AddSubCategory(path + "/" + categories[i + 1]);
}
path += "/";
}
CategoriesByName[info.Category].AddCommandName(info.CommandName);
}
private KeyCombination FindHotKey(MethodInfo methodInfo, Command command)
{
if (DebugLog)
{
Debug.Log("Finding Hot Keys");
}
var menuItemAttributes = methodInfo.GetCustomAttributes(typeof(MenuItem), true);
if (command != null && !command.MenuItemLink.IsNullOrEmpty())
{
MethodInfo overrideInfo = null;
if (command.MenuItemLinkTypeOwner == null)
{
if (methodInfo.DeclaringType != null)
{
overrideInfo =
methodInfo.DeclaringType.GetMethod(
command.MenuItemLink,
BindingFlags.Static | BindingFlags.Default
| BindingFlags.NonPublic | BindingFlags.Public);
}
}
else
{
Type linkOwner = null;
int thresh = 0;
foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
{
try
{
foreach (Type t in a.GetTypes())
{
if (t.Name == command.MenuItemLinkTypeOwner)
{
linkOwner = t;
}
}
if (thresh > amountSleepThreshold)
{
thresh = 0;
Thread.Sleep(0);
}
}
catch (Exception)
{
// potential reflection errors will be handlded elsewhere
}
thresh++;
}
if (linkOwner != null)
{
overrideInfo = linkOwner.GetMethod(
command.MenuItemLink,
BindingFlags.Static | BindingFlags.Default
| BindingFlags.NonPublic | BindingFlags.Public);
}
}
if (overrideInfo != null)
{
menuItemAttributes =
overrideInfo.GetCustomAttributes(typeof(MenuItem), true);
}
}
if (menuItemAttributes.Length > 0)
{
if (DebugLog)
{
Debug.Log("Finding Menu Item Hot Keys");
}
var item = menuItemAttributes[0] as MenuItem;
if (item != null)
{
int lastIndex = item.menuItem.LastIndexOf(' ');
if (lastIndex == item.menuItem.Length - 1)
{
lastIndex = item.menuItem.Substring(0, item.menuItem.Length - 1)
.LastIndexOf(' ');
}
if (lastIndex == -1)
{
return null;
}
var hotKey = item.menuItem
.Substring(item.menuItem.LastIndexOf(' '));
hotKey = hotKey.Replace(" ", "");
bool startsWithSpecialCharacter = hotKey.StartsWith(KeyCombination.KeySymbol.ToString());
if (!startsWithSpecialCharacter)
{
foreach (var modifierKeysAlias in KeyCombination.ModifierKeysAliases.Keys)
{
if (hotKey.StartsWith(modifierKeysAlias))
{
startsWithSpecialCharacter = true;
break;
}
}
}
if (startsWithSpecialCharacter)
{
if (DebugLog)
{
Debug.Log("Making Menu Hot Key Readable");
}
return new KeyCombination(hotKey);
}
return null;
}
}
return null;
}
private static string CheckValidationMethod(Type actionProvider,
MethodInfo methodInfo, Command command, out MethodInfo validationDelegate)
{
if (DebugLog)
{
Debug.Log("Finding Validation Method");
}
string validationHelp = "";
MethodInfo validation = null;
if (command != null && (!command.ValidationMethodName.IsNullOrEmpty()
|| command.DefaultValidation != DefaultValidation.NONE))
{
if (command.ValidationMethodName.IsNullOrEmpty())
{
validation =
ValidationUtilities.GetValidationMethod(command.DefaultValidation);
}
else
{
string validationMethodName = command.ValidationMethodName;
validation =
actionProvider.GetMethod(validationMethodName,
BindingFlags.Public | BindingFlags.Default
| BindingFlags.NonPublic | BindingFlags.Static);
if (validation == null)
{
Debug.LogWarningFormat("The command '{0}' was associated with " +
"a validation method named '{1}', " +
"but no static method of such name could be found",
methodInfo.Name, command.ValidationMethodName);
}
}
}
else
{
var menuItemAttributes = methodInfo.GetCustomAttributes(typeof(MenuItem), true);
if (menuItemAttributes.Length > 0)
{
MenuItem item = (MenuItem)menuItemAttributes[0];
string menuItemName = item.menuItem;
foreach (var validationMethod in
actionProvider.GetMethods(BindingFlags.Public | BindingFlags.Default
| BindingFlags.NonPublic |
BindingFlags.Static))
{
var attrbs = validationMethod.GetCustomAttributes(typeof(MenuItem), true);
if (attrbs.Length > 0)
{
MenuItem potentialValidation = (MenuItem)attrbs[0];
if (potentialValidation.validate && potentialValidation.menuItem == menuItemName)
{
validation = validationMethod;
break;
}
}
}
}
}
validationDelegate = validation;
if (validation != null)
{
var validations =
validation.GetCustomAttributes(typeof(CommandValidation)
, true);
if (validations.Length > 0)
{
var quickCommandValidation = validations[0]
as CommandValidation;
if (quickCommandValidation != null)
{
validationHelp = quickCommandValidation
.InvalidCommandMessage;
}
}
}
return validationHelp;
}
private static List<CommandParameterInfo> FindParameters(MethodInfo methodInfo)
{
if (DebugLog)
{
Debug.LogFormat("Checking parameters for method {0}", methodInfo.Name);
}
ParameterInfo[] parameterInfos = methodInfo.GetParameters();
CommandParameter[] parameterAttributes =
(CommandParameter[])methodInfo.GetCustomAttributes(typeof(CommandParameter),
false);
List<CommandParameterInfo> commandInfos
= new List<CommandParameterInfo>(parameterInfos.Length);
for (int i = 0; i < parameterInfos.Length; i++)
{
commandInfos.Add(null);
}
for (int i = 0; i < parameterInfos.Length; i++)
{
CommandParameter[] parameterCommandAttributes =
(CommandParameter[])parameterInfos[i].GetCustomAttributes(typeof(CommandParameter), false);
if (parameterCommandAttributes.Length > 0)
{
parameterCommandAttributes[0].Order = i;
AddParameterInfo(methodInfo, parameterCommandAttributes[0],
parameterInfos, commandInfos);
}
}
foreach (var attribute in parameterAttributes)
{
AddParameterInfo(methodInfo, attribute, parameterInfos, commandInfos);
}
for (int i = 0; i < commandInfos.Count; i++)
{
if (commandInfos[i] == null)
{
commandInfos[i] = new CommandParameterInfo(parameterInfos[i], i);
}
}
return commandInfos;
}
private static void AddParameterInfo(MethodInfo methodInfo, CommandParameter attribute,
ParameterInfo[] parameterInfos, List<CommandParameterInfo> commandInfos)
{
if (DebugLog)
{
Debug.LogFormat("Checking parameter info for method {0}", methodInfo.Name);
}
if (attribute == null || methodInfo == null)
{
Debug.LogWarning("MonKey | Error when parsing a command : no attribute or method info found");
return;
}
if (parameterInfos == null || attribute.Order >= parameterInfos.Length)
{
Debug.LogWarningFormat("Monkey Commander Warning:" +
" A command Parameter for the Command '{0}'" +
" was associated with the order '{1}', " +
"but the method does not have that many" +
" parameters", methodInfo.Name, attribute.Order);
return;
}
MethodInfo autoCompleteMethod = null;
if (attribute.HasAutoCompleteMethod)
{
if (methodInfo.DeclaringType != null)
{
autoCompleteMethod =
methodInfo.DeclaringType.GetMethod(attribute.AutoCompleteMethodName,
BindingFlags.Public | BindingFlags.Default
| BindingFlags.NonPublic | BindingFlags.Static);
}
if (autoCompleteMethod != null &&
(!autoCompleteMethod.ReturnType.IsSubclassOf(
typeof(GenericCommandParameterAutoComplete))
&& autoCompleteMethod.ReturnType != typeof(GenericCommandParameterAutoComplete)
|| autoCompleteMethod.GetParameters().Length != 0))
{
autoCompleteMethod = null;
}
if (autoCompleteMethod == null)
{
Debug.LogWarningFormat("Monkey Commander Warning:A parameter for the " +
"command '{0}' was linked to an auto complete method named '{1}'," +
" but no static method of such name could be found, " +
"or the method does not return a CommandParameterAutoComplete",
methodInfo.Name, attribute.AutoCompleteMethodName);
}
}
MethodInfo defaultValueMethod = null;
if (attribute.HasDefaultValueMethod)
{
if (methodInfo.DeclaringType != null)
{
defaultValueMethod = methodInfo.DeclaringType.GetMethod(attribute.DefaultValueMethod,
BindingFlags.Public | BindingFlags.Default
| BindingFlags.NonPublic | BindingFlags.Static);
}
if (defaultValueMethod != null)
{
//default values for array members must be done differently
/*if (parameterInfos[attribute.Order].ParameterType.IsArray)
{
if(defaultValueMethod.ReturnType
!= parameterInfos[attribute.Order].ParameterType.GetElementType())
defaultValueMethod = null;
}else*/
if (defaultValueMethod.ReturnType !=
parameterInfos[attribute.Order].ParameterType
|| defaultValueMethod.GetParameters().Length != 0)
{
defaultValueMethod = null;
}
}
if (defaultValueMethod == null)
{
Debug.LogWarningFormat("Monkey Commander Warning:A parameter for the " +
"command '{0}' was linked to a default value method named '{1}'," +
" but no static method of such name could be found, " +
"or the method does not return the same type than the specified parameter",
methodInfo.Name, attribute.DefaultValueMethod);
}
}
CommandParameterInfo info =
new CommandParameterInfo(
attribute, parameterInfos[attribute.Order], autoCompleteMethod, defaultValueMethod);
commandInfos[attribute.Order] = info;
}
#endregion
#region COMMAND SEARCH
public CommandInfo GetCommand(string name)
{
return CommandsByName[name];
}
public IEnumerable<string> CommandNames
{
get { return CommandsByName.Keys; }
}
public CommandInfo GetCommandInfo(string name)
{
if (CommandsByName.ContainsKey(name))
{
return CommandsByName[name];
}
return null;
}
public bool IsCommandAuthorized(CommandInfo info)
{
if (!MonKeyInternalSettings.Instance.IncludeMenuItems && info.IsMenuItem)
{
return false;
}
if (info.IsMenuItem
&& MonKeyInternalSettings.Instance.IncludeOnlyMenuItemsWithHotKeys && !info.HasHotKeys)
{
return false;
}
return true;
}
public CommandInfo BestMatchingAction(params string[] searchTerms)
{
if (searchTerms.Length > 0 && searchTerms.Any(_ => !_.IsNullOrEmpty()))
{
return CommandsByName[StringExt.OrderStringsBySearchScore(CommandsByName.Keys, false, searchTerms)
.First(_ => IsCommandAuthorized(CommandsByName[_]))];
}
return defaultInfo;
}
public IEnumerable<CommandInfo> ActionByMatch(params string[] searchTerms)
{
if (DebugLog)
{
Debug.Log("Searching for actions.. " + EditorApplication.timeSinceStartup);
}
if (searchTerms.Length > 0 && searchTerms.Any(_ => !_.IsNullOrEmpty()))
{
List<CommandInfo> foundCommands = new List<CommandInfo>(CommandsByName.Count);
IEnumerable<string> firstSearch;
//not dependent on the option right now (performance satisfying)
/* if (MonKeyInternalSettings.Instance.UseAdvancedFuzzySearch)
{*/
firstSearch = CommandNames.Where(_ =>
{
if (!_.ToLower().Contains(searchTerms[0]))
{
var x = StringExt.MatchResultSet(new List<string> { _.ToLower() }, searchTerms[0]);
return x.Count > 0;
}
return true;
});
firstSearch = CommandNames;
firstSearch = StringExt.OrderStringsBySearchScore(firstSearch, true, searchTerms)
.ThenBy(_ => !CommandsByName[_].HasQuickName)
.ThenBy(_ => CommandsByName[_].CommandOrder);
/* }
else
{
firstSearch = StringExt.OrderStringsBySearchScore(CommandsByName.Keys, false, searchTerms)
.ThenBy(_ => !CommandsByName[_].HasQuickName)
.ThenBy(_ => CommandsByName[_].CommandOrder);
}*/
foreach (var name in firstSearch)
{
if (!foundCommands.Contains(CommandsByName[name]) &&
IsCommandAuthorized(CommandsByName[name]))
{
foundCommands.Add(CommandsByName[name]);
}
}
if (DebugLog)
{
Debug.Log("Search done! " + EditorApplication.timeSinceStartup);
}
FindByAliases(searchTerms, foundCommands);
if (foundCommands.Count > 0)
{
if (MonKeyInternalSettings.Instance.PutInvalidCommandAtEndOfSearch)
{
return foundCommands.OrderByDescending(_ => !_.HasValidation
|| _.IsValid);
}
return foundCommands.Take(MaxCommandShown);
}
}
return new CommandInfo[0];
}
private void FindByAliases(string[] searchTerms, List<CommandInfo> foundCommands)
{
if (foundCommands.Count < CommandFoundCountForAliases)
{
List<string> orderedAliases =
StringExt.OrderStringsBySearchScore(WordAliases.Keys, false, searchTerms).ToList();
if (orderedAliases.Any())
{
foreach (var name in StringExt
.OrderStringsBySearchScore(CommandsByName.Keys, false,
WordAliases[orderedAliases.ElementAt(0)])
.ThenBy(_ => CommandsByName[_].CommandOrder))
{
if (!foundCommands.Contains(CommandsByName[name]) &&
IsCommandAuthorized(CommandsByName[name]))
{
foundCommands.Add(CommandsByName[name]);
}
}
}
}
}
public IEnumerable<CommandInfo> AlwaysShownCommands
{
get
{
return CommandsByName.Values
.Where(_ => _.AlwaysShow)
.Distinct()
.OrderBy(_ => _.CommandOrder)
.ThenByDescending(_ => !_.HasValidation || _.IsValid);
}
}
#endregion
}
/*private class Test
{
public void GenerateAndSortAutoComplete(string searchTerms)
{
typesOrdered = objectsPerName.Where(type =>
{
if (!type.Value.Name.ToLower().Contains(searchTerms))
{
//Use Fuzzy Match instead default one
var x = StringExt.MatchResultSet(new List<string> { type.Value.Name.NicifyVariableName().ToLower() }, searchTerms);
return x.Count > 0;
}
return true;
})
.Convert(_ => _.Value)
.OrderByDescending(type => type.Name.NicifyVariableName().ToLower().WordSearchScore(false, searchTerms))
.Take(MaxPick)
.ToArray();
}
}*/
}
#endif