public static CommandInfoAttribute GetCommandInfo(System.Type commandType) { object[] attributes = commandType.GetCustomAttributes(typeof(CommandInfoAttribute), false); foreach (object obj in attributes) { CommandInfoAttribute commandInfoAttr = obj as CommandInfoAttribute; if (commandInfoAttr != null) { return(commandInfoAttr); } } return(null); }
protected static void ExportCommandInfo(string path) { // Dump command info List <System.Type> menuTypes = EditorExtensions.FindDerivedTypes(typeof(Command)).ToList(); List <KeyValuePair <System.Type, CommandInfoAttribute> > filteredAttributes = GetFilteredCommandInfoAttribute(menuTypes); filteredAttributes.Sort(CompareCommandAttributes); // Build list of command categories List <string> commandCategories = new List <string>(); foreach (var keyPair in filteredAttributes) { CommandInfoAttribute info = keyPair.Value; if (info.Category != "" && !commandCategories.Contains(info.Category)) { commandCategories.Add(info.Category); } } commandCategories.Sort(); // Output the commands in each category foreach (string category in commandCategories) { string markdown = "# " + category + " commands # {#" + category.ToLower() + "_commands}\n\n"; markdown += "[TOC]\n"; foreach (var keyPair in filteredAttributes) { CommandInfoAttribute info = keyPair.Value; if (info.Category == category || info.Category == "" && category == "Scripting") { markdown += "# " + info.CommandName + " # {#" + info.CommandName.Replace(" ", "") + "}\n"; markdown += info.HelpText + "\n\n"; markdown += "Defined in " + keyPair.Key.FullName + "\n"; markdown += GetPropertyInfo(keyPair.Key); } } string filePath = path + "/command_ref/" + category.ToLower() + "_commands.md"; Directory.CreateDirectory(Path.GetDirectoryName(filePath)); File.WriteAllText(filePath, markdown); } }
internal CommandAdapter(ICommand command) { Command = command; Name = command.Name; Aliases = command.Aliases.ToList(); Help = command.Description; Syntax = command.Usage; Permissions = new List <string>(1) { command.Permission }; AllowedCaller = AllowedCaller.Both; if (command is EssCommand) { _info = ((EssCommand)command).Info; } }
/// <summary> /// Returns a Boolean value indicating whether provided arguments are valid for given <see cref="Command"/>. /// Command arguments requirement are specified for each command via <see cref="CommandInfoAttribute"/> decoration. /// </summary> /// <param name="cmdName">Command name</param> /// <param name="cmd_args">Argument to validate</param> /// <remarks></remarks> /// <returns>True if argument are missing, command does not exists or arguments are valid, false otherwise</returns> internal bool AreArgumentsValid(string cmdName, string[] cmd_args) { if (!IsBound(cmdName)) { return(true); } Type cmdType = _map[cmdName]; // Get instance of the attribute. CommandInfoAttribute commandInfo = (CommandInfoAttribute)Attribute.GetCustomAttribute(cmdType, typeof(CommandInfoAttribute)); if (commandInfo == null) { return(true); } return((cmd_args.Length - 1) >= commandInfo.MinArgs); }
public static CommandInfoAttribute GetCommandInfo(System.Type commandType) { CommandInfoAttribute retval = null; object[] attributes = commandType.GetCustomAttributes(typeof(CommandInfoAttribute), false); foreach (object obj in attributes) { CommandInfoAttribute commandInfoAttr = obj as CommandInfoAttribute; if (commandInfoAttr != null) { if (retval == null) { retval = commandInfoAttr; } else if (retval.Priority < commandInfoAttr.Priority) { retval = commandInfoAttr; } } } return(retval); }
public void DrawItem(Rect position, int index) { Command command = this[index].objectReferenceValue as Command; if (command == null) { return; } CommandInfoAttribute commandInfoAttr = CommandEditor.GetCommandInfo(command.GetType()); if (commandInfoAttr == null) { return; } var flowchart = (Flowchart)command.GetFlowchart(); if (flowchart == null) { return; } bool isComment = command.GetType() == typeof(Comment); bool isLabel = (command.GetType() == typeof(Label)); bool error = false; string summary = command.GetSummary(); if (summary == null) { summary = ""; } else { summary = summary.Replace("\n", "").Replace("\r", ""); } if (summary.StartsWith("Error:")) { error = true; } if (isComment || isLabel) { summary = "<b> " + summary + "</b>"; } else { summary = "<i>" + summary + "</i>"; } bool commandIsSelected = false; foreach (Command selectedCommand in flowchart.SelectedCommands) { if (selectedCommand == command) { commandIsSelected = true; break; } } string commandName = commandInfoAttr.CommandName; GUIStyle commandLabelStyle = new GUIStyle(GUI.skin.box); commandLabelStyle.normal.background = FungusEditorResources.CommandBackground; int borderSize = 5; commandLabelStyle.border.top = borderSize; commandLabelStyle.border.bottom = borderSize; commandLabelStyle.border.left = borderSize; commandLabelStyle.border.right = borderSize; commandLabelStyle.alignment = TextAnchor.MiddleLeft; commandLabelStyle.richText = true; commandLabelStyle.fontSize = 11; commandLabelStyle.padding.top -= 1; float indentSize = 20; for (int i = 0; i < command.IndentLevel; ++i) { Rect indentRect = position; indentRect.x += i * indentSize - 21; indentRect.width = indentSize + 1; indentRect.y -= 2; indentRect.height += 5; GUI.backgroundColor = new Color(0.5f, 0.5f, 0.5f, 1f); GUI.Box(indentRect, "", commandLabelStyle); } float commandNameWidth = Mathf.Max(commandLabelStyle.CalcSize(new GUIContent(commandName)).x, 90f); float indentWidth = command.IndentLevel * indentSize; Rect commandLabelRect = position; commandLabelRect.x += indentWidth - 21; commandLabelRect.y -= 2; commandLabelRect.width -= (indentSize * command.IndentLevel - 22); commandLabelRect.height += 5; // There's a weird incompatibility between the Reorderable list control used for the command list and // the UnityEvent list control used in some commands. In play mode, if you click on the reordering grabber // for a command in the list it causes the UnityEvent list to spew null exception errors. // The workaround for now is to hide the reordering grabber from mouse clicks by extending the command // selection rectangle to cover it. We are planning to totally replace the command list display system. Rect clickRect = position; clickRect.x -= 20; clickRect.width += 20; // Select command via left click if (Event.current.type == EventType.MouseDown && Event.current.button == 0 && clickRect.Contains(Event.current.mousePosition)) { if (flowchart.SelectedCommands.Contains(command) && Event.current.button == 0) { // Left click on already selected command // Command key and shift key is not pressed if (!EditorGUI.actionKey && !Event.current.shift) { BlockEditor.actionList.Add(delegate { flowchart.SelectedCommands.Remove(command); flowchart.ClearSelectedCommands(); }); } // Command key pressed if (EditorGUI.actionKey) { BlockEditor.actionList.Add(delegate { flowchart.SelectedCommands.Remove(command); }); Event.current.Use(); } } else { bool shift = Event.current.shift; // Left click and no command key if (!shift && !EditorGUI.actionKey && Event.current.button == 0) { BlockEditor.actionList.Add(delegate { flowchart.ClearSelectedCommands(); }); Event.current.Use(); } BlockEditor.actionList.Add(delegate { flowchart.AddSelectedCommand(command); }); // Find first and last selected commands int firstSelectedIndex = -1; int lastSelectedIndex = -1; if (flowchart.SelectedCommands.Count > 0) { if (flowchart.SelectedBlock != null) { for (int i = 0; i < flowchart.SelectedBlock.CommandList.Count; i++) { Command commandInBlock = flowchart.SelectedBlock.CommandList[i]; foreach (Command selectedCommand in flowchart.SelectedCommands) { if (commandInBlock == selectedCommand) { firstSelectedIndex = i; break; } } } for (int i = flowchart.SelectedBlock.CommandList.Count - 1; i >= 0; i--) { Command commandInBlock = flowchart.SelectedBlock.CommandList[i]; foreach (Command selectedCommand in flowchart.SelectedCommands) { if (commandInBlock == selectedCommand) { lastSelectedIndex = i; break; } } } } } if (shift) { int currentIndex = command.CommandIndex; if (firstSelectedIndex == -1 || lastSelectedIndex == -1) { // No selected command found - select entire list firstSelectedIndex = 0; lastSelectedIndex = currentIndex; } else { if (currentIndex < firstSelectedIndex) { firstSelectedIndex = currentIndex; } if (currentIndex > lastSelectedIndex) { lastSelectedIndex = currentIndex; } } for (int i = Math.Min(firstSelectedIndex, lastSelectedIndex); i < Math.Max(firstSelectedIndex, lastSelectedIndex); ++i) { var selectedCommand = flowchart.SelectedBlock.CommandList[i]; BlockEditor.actionList.Add(delegate { flowchart.AddSelectedCommand(selectedCommand); }); } } Event.current.Use(); } GUIUtility.keyboardControl = 0; // Fix for textarea not refeshing (change focus) } Color commandLabelColor = Color.white; if (flowchart.ColorCommands) { commandLabelColor = command.GetButtonColor(); } if (commandIsSelected) { commandLabelColor = Color.green; } else if (!command.enabled) { commandLabelColor = Color.grey; } else if (error) { } GUI.backgroundColor = commandLabelColor; if (isComment) { GUI.Label(commandLabelRect, "", commandLabelStyle); } else { string commandNameLabel; if (flowchart.ShowLineNumbers) { commandNameLabel = command.CommandIndex.ToString() + ": " + commandName; } else { commandNameLabel = commandName; } GUI.Label(commandLabelRect, commandNameLabel, commandLabelStyle); } if (command.ExecutingIconTimer > Time.realtimeSinceStartup) { Rect iconRect = new Rect(commandLabelRect); iconRect.x += iconRect.width - commandLabelRect.width - 20; iconRect.width = 20; iconRect.height = 20; Color storeColor = GUI.color; float alpha = (command.ExecutingIconTimer - Time.realtimeSinceStartup) / FungusConstants.ExecutingIconFadeTime; alpha = Mathf.Clamp01(alpha); GUI.color = new Color(1f, 1f, 1f, alpha); GUI.Label(iconRect, FungusEditorResources.PlaySmall, new GUIStyle()); GUI.color = storeColor; } Rect summaryRect = new Rect(commandLabelRect); if (isComment) { summaryRect.x += 5; } else { summaryRect.x += commandNameWidth + 5; summaryRect.width -= commandNameWidth + 5; } GUIStyle summaryStyle = new GUIStyle(); summaryStyle.fontSize = 10; summaryStyle.padding.top += 5; summaryStyle.richText = true; summaryStyle.wordWrap = false; summaryStyle.clipping = TextClipping.Clip; commandLabelStyle.alignment = TextAnchor.MiddleLeft; GUI.Label(summaryRect, summary, summaryStyle); if (error) { GUISkin editorSkin = EditorGUIUtility.GetBuiltinSkin(EditorSkin.Inspector); Rect errorRect = new Rect(summaryRect); errorRect.x += errorRect.width - 20; errorRect.y += 2; errorRect.width = 20; GUI.Label(errorRect, editorSkin.GetStyle("CN EntryError").normal.background); summaryRect.width -= 20; } GUI.backgroundColor = Color.white; }
public override void DrawCommandInspectorGUI() { Command t = target as Command; if (t == null) { return; } var flowchart = (Flowchart)t.GetFlowchart(); if (flowchart == null) { return; } CommandInfoAttribute commandInfoAttr = CommandEditor.GetCommandInfo(t.GetType()); if (commandInfoAttr == null) { return; } GUILayout.BeginVertical(GUI.skin.box); if (t.enabled) { if (flowchart.ColorCommands) { GUI.backgroundColor = t.GetButtonColor(); } else { GUI.backgroundColor = Color.white; } } else { GUI.backgroundColor = Color.grey; } GUILayout.BeginHorizontal(GUI.skin.button); string commandName = commandInfoAttr.CommandName; GUILayout.Label(commandName, GUILayout.MinWidth(80), GUILayout.ExpandWidth(true)); GUILayout.FlexibleSpace(); ICommand it = t as ICommand; if (it != null) { //GUILayout.Label(new GUIContent("(CSV Line:" + it.CSVLine + ")")); GUILayout.Label(new GUIContent("(" + it.CSVCommandKey + ")")); } GUILayout.Label(new GUIContent("(" + t.ItemId + ")")); GUILayout.Space(10); GUI.backgroundColor = Color.white; bool enabled = t.enabled; enabled = GUILayout.Toggle(enabled, new GUIContent()); if (t.enabled != enabled) { Undo.RecordObject(t, "Set Enabled"); t.enabled = enabled; } GUILayout.EndHorizontal(); GUI.backgroundColor = Color.white; EditorGUILayout.Separator(); EditorGUI.BeginChangeCheck(); DrawCommandGUI(); if (EditorGUI.EndChangeCheck()) { SelectedCommandDataStale = true; } EditorGUILayout.Separator(); if (t.ErrorMessage.Length > 0) { GUIStyle style = new GUIStyle(GUI.skin.label); style.normal.textColor = new Color(1, 0, 0); EditorGUILayout.LabelField(new GUIContent("Error: " + t.ErrorMessage), style); } GUILayout.EndVertical(); // Display help text CommandInfoAttribute infoAttr = CommandEditor.GetCommandInfo(t.GetType()); if (infoAttr != null) { EditorGUILayout.HelpBox(infoAttr.HelpText, MessageType.Info, true); } }
public void DrawItem(Rect position, int index, bool selected, bool focused) { Command command = this[index].objectReferenceValue as Command; if (command == null) { return; } // 获取命令类, // * 开头的CommandInfoAttribute CommandInfoAttribute commandInfoAttr = CommandEditor.GetCommandInfo(command.GetType()); if (commandInfoAttr == null) { return; } var flowchart = (Flowchart)command.GetFlowchart(); if (flowchart == null) { return; } // 判断命令类别 bool isComment = command.GetType() == typeof(Comment); bool isLabel = (command.GetType() == typeof(Label)); // 处理命令的Summary bool error = false; string summary = command.GetSummary(); if (summary == null) { summary = ""; } else { summary = summary.Replace("\n", "").Replace("\r", ""); } if (summary.StartsWith("Error:")) { error = true; } if (isComment || isLabel) { summary = "<b> " + summary + "</b>"; } else { summary = "<i>" + summary + "</i>"; } bool commandIsSelected = false; foreach (Command selectedCommand in flowchart.SelectedCommands) { if (selectedCommand == command) { commandIsSelected = true; break; } } string commandName = commandInfoAttr.CommandName; // 一行命令的样式 GUIStyle commandLabelStyle = new GUIStyle(GUI.skin.box); commandLabelStyle.normal.background = FungusEditorResources.CommandBackground; // 边框宽度 int borderSize = 5; commandLabelStyle.border.top = borderSize; commandLabelStyle.border.bottom = borderSize; commandLabelStyle.border.left = borderSize; commandLabelStyle.border.right = borderSize; commandLabelStyle.alignment = TextAnchor.MiddleLeft; commandLabelStyle.richText = true; commandLabelStyle.fontSize = 11; commandLabelStyle.padding.top -= 1; // 缩进的宽度 float indentSize = 20; // 处理命令的缩进 for (int i = 0; i < command.IndentLevel; ++i) { Rect indentRect = position; indentRect.x += i * indentSize;// - 21; indentRect.width = indentSize + 1; indentRect.y -= 2; indentRect.height += 5; // 一个灰的颜色 GUI.backgroundColor = new Color(0.5f, 0.5f, 0.5f, 1f); GUI.Box(indentRect, "", commandLabelStyle); } // 命令名称的宽度 // * 例如:EvoSay float commandNameWidth = Mathf.Max(commandLabelStyle.CalcSize(new GUIContent(commandName)).x, 90f); // 缩进宽度 float indentWidth = command.IndentLevel * indentSize; // Rect commandLabelRect = position; commandLabelRect.x += indentWidth;// - 21; commandLabelRect.y -= 2; // 宽度上, // * 减去缩进之后的宽度 commandLabelRect.width -= (indentSize * command.IndentLevel);// - 22); commandLabelRect.height += 5; // There's a weird incompatibility between the Reorderable list control used for the command list and // the UnityEvent list control used in some commands. In play mode, if you click on the reordering grabber // for a command in the list it causes the UnityEvent list to spew null exception errors. // The workaround for now is to hide the reordering grabber from mouse clicks by extending the command // selection rectangle to cover it. We are planning to totally replace the command list display system. Rect clickRect = position; //clickRect.x -= 20; //clickRect.width += 20; // 可点击区域: // * 是整个命令区域 // 鼠标点击下了 // Select command via left click if (Event.current.type == EventType.MouseDown && Event.current.button == 0 && clickRect.Contains(Event.current.mousePosition)) { // flowchart.selectedCommands: // * 就是在flowchart中记录 // 是选中的命令,并且 // 点击的是,鼠标左键 if (flowchart.SelectedCommands.Contains(command) && Event.current.button == 0) { // Left click on already selected command // Command key and shift key is not pressed // 没有点击shift key // 没有点击command key if (!EditorGUI.actionKey && !Event.current.shift) { BlockEditor.actionList.Add(delegate { // 取消选中 // Q: 2条重复的命令? flowchart.SelectedCommands.Remove(command); flowchart.ClearSelectedCommands(); }); } // ----------------------------------------- // 使用ctrl键,控制多选中的,取消选择 // ---------------------------------------- // Command key pressed // actionKey是: // * windosw是ctrl if (EditorGUI.actionKey) { BlockEditor.actionList.Add(delegate { flowchart.SelectedCommands.Remove(command); }); Event.current.Use(); } } else { // 点击的不是,选中的命令 || // 点击的,不是鼠标左键 bool shift = Event.current.shift; // Left click and no command key // 点击了鼠标左键 && // 点击的,不是选中的命令 && // 没有按下,其他按键 if (!shift && !EditorGUI.actionKey && Event.current.button == 0) { // 点击的是,鼠标左键 BlockEditor.actionList.Add(delegate { flowchart.ClearSelectedCommands(); }); Event.current.Use(); } // // 点击的不是,选中的命令 && // (点击的不是左键 || // 是选中的命令 || // 有按下其他按键) // 或: // 点击的,不是鼠标左键 && // (点击的不是左键 || // 是选中的命令 || // 有按下其他按键) BlockEditor.actionList.Add(delegate { // 选中命令 flowchart.AddSelectedCommand(command); }); // Find first and last selected commands int firstSelectedIndex = -1; int lastSelectedIndex = -1; if (flowchart.SelectedCommands.Count > 0) { if (flowchart.SelectedBlock != null) { // 遍历,选中的block中的命令 for (int i = 0; i < flowchart.SelectedBlock.CommandList.Count; i++) { Command commandInBlock = flowchart.SelectedBlock.CommandList[i]; foreach (Command selectedCommand in flowchart.SelectedCommands) { if (commandInBlock == selectedCommand) { // 获取,第一个被选中的command的下标 firstSelectedIndex = i; break; } } } for (int i = flowchart.SelectedBlock.CommandList.Count - 1; i >= 0; i--) { Command commandInBlock = flowchart.SelectedBlock.CommandList[i]; foreach (Command selectedCommand in flowchart.SelectedCommands) { if (commandInBlock == selectedCommand) { // 获取,最后一个被选中的command的下标 lastSelectedIndex = i; break; } } } } } if (shift) { int currentIndex = command.CommandIndex; if (firstSelectedIndex == -1 || lastSelectedIndex == -1) { // No selected command found - select entire list firstSelectedIndex = 0; lastSelectedIndex = currentIndex; } else { if (currentIndex < firstSelectedIndex) { firstSelectedIndex = currentIndex; } if (currentIndex > lastSelectedIndex) { lastSelectedIndex = currentIndex; } } for (int i = Math.Min(firstSelectedIndex, lastSelectedIndex); i < Math.Max(firstSelectedIndex, lastSelectedIndex); ++i) { var selectedCommand = flowchart.SelectedBlock.CommandList[i]; BlockEditor.actionList.Add(delegate { flowchart.AddSelectedCommand(selectedCommand); }); } } Event.current.Use(); } GUIUtility.keyboardControl = 0; // Fix for textarea not refeshing (change focus) } Color commandLabelColor = Color.white; if (flowchart.ColorCommands) { commandLabelColor = command.GetButtonColor(); } if (commandIsSelected) { commandLabelColor = Color.green; } else if (!command.enabled) { commandLabelColor = Color.grey; } else if (error) { // TODO: Show warning icon } GUI.backgroundColor = commandLabelColor; // 注释命令 // * 不显示,命令名称 if (isComment) { GUI.Label(commandLabelRect, "", commandLabelStyle); } else { // 显示,命令名称 string commandNameLabel; if (flowchart.ShowLineNumbers) { // 显示,命令前面的,序号 commandNameLabel = command.CommandIndex.ToString() + ": " + commandName; } else { commandNameLabel = commandName; } // 可以扩展的点 // * 例如:多人对话进行自定义的命令行显示 // 显示命令Label GUI.Label(commandLabelRect, commandNameLabel, commandLabelStyle); } if (command.ExecutingIconTimer > Time.realtimeSinceStartup) { Rect iconRect = new Rect(commandLabelRect); iconRect.x += iconRect.width - commandLabelRect.width - 20; iconRect.width = 20; iconRect.height = 20; Color storeColor = GUI.color; float alpha = (command.ExecutingIconTimer - Time.realtimeSinceStartup) / FungusConstants.ExecutingIconFadeTime; alpha = Mathf.Clamp01(alpha); GUI.color = new Color(1f, 1f, 1f, alpha); GUI.Label(iconRect, FungusEditorResources.PlaySmall, new GUIStyle()); GUI.color = storeColor; } Rect summaryRect = new Rect(commandLabelRect); if (isComment) { summaryRect.x += 5; } else { summaryRect.x += commandNameWidth + 5; summaryRect.width -= commandNameWidth + 5; } GUIStyle summaryStyle = new GUIStyle(); summaryStyle.fontSize = 10; summaryStyle.padding.top += 5; summaryStyle.richText = true; summaryStyle.wordWrap = false; summaryStyle.clipping = TextClipping.Clip; commandLabelStyle.alignment = TextAnchor.MiddleLeft; // 显示Summary GUI.Label(summaryRect, summary, summaryStyle); if (error) { GUISkin editorSkin = EditorGUIUtility.GetBuiltinSkin(EditorSkin.Inspector); Rect errorRect = new Rect(summaryRect); errorRect.x += errorRect.width - 20; errorRect.y += 2; errorRect.width = 20; GUI.Label(errorRect, editorSkin.GetStyle("CN EntryError").normal.background); summaryRect.width -= 20; } GUI.backgroundColor = Color.white; }