public static List <string> FetchAutocompleteOptions(string command, string[] tokens) { // can only autocomplete if there is a single token or no token if (tokens.Length > 1) { return(null); } // fetch the autocomplete options return(CommandHelpers.GetGameObjectAutocompleteOptions(tokens.Length > 0 ? tokens[0] : "", command)); }
public static string Execute(string[] tokens) { // incorrect number of tokens found if (tokens.Length < 3) { return("[Error] You must provide a valid path to the game object to modify."); } // attempt to find the object GameObject foundObject = CommandHelpers.GetGameObject(tokens[1]); // object not found? if (foundObject == null) { return("[Error] Could not find the specified game object. Check the path. Paths must be case sensitive."); } // is the location being set as local or world? bool isLocal = false; if (tokens[0].ToLower() == "local") { isLocal = true; } else if (tokens[0].ToLower() == "world") { isLocal = false; } else { return("[Error] No indication was provided for if the coordinates are in local or world space."); } // check if the coordinates are correct Vector3 coordinates = Vector3.zero; if (!CommandHelpers.Vector3FromTokens(tokens, 2, ref coordinates)) { return("[Error] The incorrect number of coordinates were given. Coordinates should be x,y,z"); } // update the location if (isLocal) { foundObject.transform.localEulerAngles = coordinates; } else { foundObject.transform.eulerAngles = coordinates; } return(foundObject.name + " is now rotated to " + foundObject.transform.eulerAngles + " (world) " + foundObject.transform.localEulerAngles + " (local)"); }
public static List <string> FetchAutocompleteOptions(string command, string[] tokens) { // don't autocomplete once we are entering the variable if (tokens.Length >= 2) { return(null); } // at the variable autocomplete stage (ie. need reflection) if (tokens.Length > 0 && tokens[0].Count(character => character == '.') > 1) { return(CommandHelpers.GetAutocompleteOptions(tokens[0], command, CommandHelpers.AutocompleteCandidates.Variables)); } // fetch the game object autocomplete options string path = tokens.Length > 0 ? tokens[0] : ""; List <string> autocompleteOptions = CommandHelpers.GetComponentAutocompleteOptions(path, command); if (autocompleteOptions == null) { autocompleteOptions = new List <string>(); } // user has entered exact path to a component - switch to variable autocomplete stage if ((tokens.Length > 0) && (autocompleteOptions.Count <= 1) && (CommandHelpers.GetComponent(tokens[0]) != null)) { return(CommandHelpers.GetAutocompleteOptions(tokens[0], command, CommandHelpers.AutocompleteCandidates.Variables)); } // append the type based autocomplete options autocompleteOptions.AddRange(ConsoleDaemon.Instance.AvailableTypes.Keys .Where(typeName => typeName.StartsWith(path)) .Select(typeName => command + " " + typeName).ToList()); // if we have no autocomplete options at this stage then we are working with a class if (tokens.Length > 0 && (autocompleteOptions == null || autocompleteOptions.Count <= 1)) { string[] pathElements = tokens[0].Split('.'); // check if the class is in the cached types if (ConsoleDaemon.Instance.AvailableTypes.ContainsKey(pathElements[0])) { return(CommandHelpers.GetAutocompleteOptions(tokens[0], command, CommandHelpers.AutocompleteCandidates.Variables)); } } return(autocompleteOptions); }
public static List <string> FetchAutocompleteOptions(string command, string[] tokens) { // no tokens so just return these options if (tokens.Length == 0) { return(new List <string>(new string[] { command + " enabled", command + " disabled", command + " true", command + " false" })); } // if we have one token then it may be a partial one if (tokens.Length == 1 && tokens[0].ToLower() != "enabled" && tokens[0].ToLower() != "disabled" && tokens[0].ToLower() != "true" && tokens[0].ToLower() != "false") { List <string> options = new List <string>(); if ("enabled".StartsWith(tokens[0].ToLower())) { options.Add(command + " enabled"); } if ("disabled".StartsWith(tokens[0].ToLower())) { options.Add(command + " disabled"); } if ("true".StartsWith(tokens[0].ToLower())) { options.Add(command + " true"); } if ("false".StartsWith(tokens[0].ToLower())) { options.Add(command + " false"); } return(options); } // invalid number of tokens so no autocompletion if (tokens.Length > 2) { return(null); } // fetch the autocomplete options return(CommandHelpers.GetComponentAutocompleteOptions(tokens.Length > 1 ? tokens[1] : "", command + " " + tokens[0])); }
public static string Execute(string[] tokens) { if (tokens.Length < 1) { return("[Error] You must provide a path to the component to remove."); } // attempt to find the component Component foundComponent = CommandHelpers.GetComponent(tokens[0]); if (foundComponent == null) { return("[Error] Could not find the specified component. Check that the path is correct."); } GameObject.Destroy(foundComponent); return("Component destroyed"); }
public static string Execute(string[] tokens) { // incorrect number of tokens found if (tokens.Length != 1) { return("[Error] You must provide a valid path to the game object to query."); } // attempt to find the object GameObject foundObject = CommandHelpers.GetGameObject(tokens[0]); // object not found? if (foundObject == null) { return("[Error] Could not find the specified game object. Check the path. Paths must be case sensitive."); } return(foundObject.name + " has a scale of " + foundObject.transform.localScale + " (local) "); }
public static string Execute(string[] tokens) { if (tokens.Length == 0) { return("[Error] You must provide the name of at least one scene to load."); } // get the names of the scenes in the build List <string> sceneNamesInBuild = CommandHelpers.GetSceneNamesInBuild(); // force additive if there are multiple scenes bool isAdditive = tokens.Length > 1 ? true : false; // check that all of the provided scene names are valid foreach (string sceneName in tokens) { string workingSceneName = sceneName.ToLower(); if (workingSceneName == "additive") { isAdditive = true; } else if (sceneNamesInBuild.IndexOf(workingSceneName) < 0) { return("[Error] Unable to load scene \'" + sceneName + "\' as it is not in the build settings."); } } // load the requested scenes foreach (string sceneName in tokens) { // skip if trying to do additive loading if (sceneName.ToLower() == "additive") { continue; } SceneManager.LoadScene(sceneName, isAdditive ? LoadSceneMode.Additive : LoadSceneMode.Single); } return("Loaded the requested scenes."); }
public static string Execute(string[] tokens) { // incorrect number of tokens found if (tokens.Length != 1) { return("[Error] You must provide a valid path to the game object to query."); } // attempt to find the object GameObject foundObject = CommandHelpers.GetGameObject(tokens[0]); // object not found? if (foundObject == null) { return("[Error] Could not find the specified game object. Check the path. Paths must be case sensitive."); } Dictionary <string, Component> componentMapping = CommandHelpers.GetComponentMapping(foundObject); List <string> componentNames = componentMapping.Keys.ToList(); // find the longest component name int longestComponentName = 0; foreach (string componentName in componentNames) { longestComponentName = Mathf.Max(componentName.Length, longestComponentName); } // build the list of components string result = "Found the following components: "; foreach (string componentName in componentNames) { Component component = componentMapping[componentName]; string status = component is Behaviour ? ((component as Behaviour).enabled ? "Enabled" : "Disabled") : "Always Enabled"; result += System.Environment.NewLine + " " + componentName.PadRight(longestComponentName) + " : " + status; } return(result); }
public static List <string> FetchAutocompleteOptions(string command, string[] tokens) { // can only autocomplete if there are no, 1 or 2 tokens if (tokens.Length > 2) { return(null); } // none or one token? if (tokens.Length <= 1) { List <string> autocompleteOptions = CommandHelpers.GetGameObjectAutocompleteOptions(tokens.Length > 0 ? tokens[0] : "", command); if (autocompleteOptions != null) { return(autocompleteOptions); } } // this shouldn't happen! but just in case if (tokens.Length == 0) { Debug.LogError("Failed to find autocomplete options and have no tokens. This shouldn't be possible."); return(null); } // setup the base path for the autocomplete options string basePath = tokens[0]; if (basePath.Contains(" ")) { basePath = command + " \"" + tokens[0] + "\""; } else { basePath = command + " " + tokens[0]; } // fetch the autocomplete options return(CommandHelpers.GetGameObjectAutocompleteOptions(tokens.Length > 1 ? tokens[1] : "", basePath)); }
public static string Execute(string[] tokens) { // incorrect number of tokens found if (tokens.Length != 1) { return("[Error] You must provide a valid path to the game object to destroy."); } // attempt to find the object GameObject foundObject = CommandHelpers.GetGameObject(tokens[0]); // object not found? if (foundObject == null) { return("[Error] Could not find the specified game object. Check the path. Paths must be case sensitive."); } GameObject.Destroy(foundObject); return("Object destroyed."); }
public static string Execute(string[] tokens) { // incorrect number of tokens found if (tokens.Length != 2) { return("[Error] Incorrect number of parameters. You must provide the true/false/enabled/disabled flag and a valid path to the component to modify."); } // invalid flag provided string enabledFlag = tokens[0].ToLower(); if (enabledFlag.ToLower() != "enabled" && enabledFlag.ToLower() != "disabled" && enabledFlag.ToLower() != "true" && enabledFlag.ToLower() != "false") { return("[Error] Unknown flag. You must provide the true/false/enabled/disabled flag and a valid path to the component to modify."); } // attempt to find the component Component foundComponent = CommandHelpers.GetComponent(tokens[1]); // component not found? if (foundComponent == null) { return("[Error] Could not find the specified component. Check the path. Paths must be case sensitive."); } // component cannot be enabled/disabled if (!(foundComponent is Behaviour)) { return("[Error] The component does not support being enabled or disabled."); } // Update the component (foundComponent as Behaviour).enabled = (enabledFlag == "enabled") || (enabledFlag == "true"); return("Component is now " + enabledFlag); }
public static string Execute(string[] tokens) { // incorrect number of tokens found if (tokens.Length == 0) { return("[Error] You must provide a valid path to the game object to update and optionally a path to the new parent."); } // attempt to find the object GameObject foundObject = CommandHelpers.GetGameObject(tokens[0]); // object not found? if (foundObject == null) { return("[Error] Could not find the game object to change. Check the path. Paths must be case sensitive."); } // attempt to find the new parent object GameObject foundParentObject = tokens.Length > 1 ? CommandHelpers.GetGameObject(tokens[1]) : null; // object not found? if (tokens.Length > 1 && foundParentObject == null) { return("[Error] Could not find the new parent game object. Check the path. Paths must be case sensitive."); } // did the user give the same path? if (foundObject == foundParentObject) { return("[Error] The object and the new parent cannot be the same. Please provide two different game objects."); } // reparent the object foundObject.transform.SetParent(foundParentObject != null ? foundParentObject.transform : null); return("Parent updated"); }
public static string GetValue(string path) { // split based on the . as this might indicate a component or variable split string[] pathElements = path.Split('.'); System.Type foundType = null; Component foundComponent = null; System.Object foundObject = null; // attempt to find the type if (ConsoleDaemon.Instance.AvailableTypes.ContainsKey(pathElements[0])) { foundType = ConsoleDaemon.Instance.AvailableTypes[pathElements[0]]; } // if there are multiple path elements then we may have a component if (pathElements.Length >= 2) { // attempt to find the component, if found then retrieve the type foundComponent = CommandHelpers.GetComponent(pathElements[0] + "." + pathElements[1]); if (foundComponent != null) { foundType = foundComponent.GetType(); foundObject = foundComponent; } } // no matching type should only happen if invalid information has been entered if (foundType == null) { return("[Error] Failed to find a matching component or type. Check the entered path."); } // track the index into the path for the earliest spot a variable may be int variableStart = foundComponent != null ? 2 : 1; // cache the binding flags (can only search for instance if we have a component) BindingFlags flags = BindingFlags.Public | BindingFlags.Static; if (foundComponent != null) { flags |= BindingFlags.Instance; } // traverse the hierarchy of the path to find the last node bool lastElementIsPartial = false; for (int pathIndex = variableStart; pathIndex < pathElements.Length; ++pathIndex) { FieldInfo field = foundType.GetField(pathElements[pathIndex], flags); lastElementIsPartial = true; if (field != null) { // even if the parent was static after we are one field in we are dealing with an actual variable so add instance flags |= BindingFlags.Instance; foundType = field.FieldType; lastElementIsPartial = false; foundObject = field.GetValue(foundObject); } else { PropertyInfo property = foundType.GetProperty(pathElements[pathIndex], flags); if (property != null) { // even if the parent was static after we are one field in we are dealing with an actual variable so add instance flags |= BindingFlags.Instance; foundType = property.PropertyType; lastElementIsPartial = false; foundObject = property.GetValue(foundObject, null); } } // no found object if (foundObject == null) { return("[Error] Failed to access the object. It may have been destroyed."); } } // if the last element is partial then an error has occurred if (lastElementIsPartial) { return("[Error] An incomplete path to a variable was supplied. Check the path. Paths are case sensitive."); } return("The value is: " + foundObject.ToString()); }
public static System.Object ConstructObjectFromString(System.Type type, string value) { // If the type is a string then our process is simple if (type == typeof(string)) { return(value); } // if the type is a vector 2, 3 or 4 then handle it if (type == typeof(Vector2)) { // convert the string to a vector 2 Vector2 vectorValue = Vector2.zero; if (CommandHelpers.Vector2FromTokens(new string[] { value }, 0, ref vectorValue)) { return(vectorValue); } return(null); } if (type == typeof(Vector3)) { // convert the string to a vector 3 Vector3 vectorValue = Vector3.zero; if (CommandHelpers.Vector3FromTokens(new string[] { value }, 0, ref vectorValue)) { return(vectorValue); } return(null); } if (type == typeof(Vector4)) { // convert the string to a vector 4 Vector4 vectorValue = Vector4.zero; if (CommandHelpers.Vector4FromTokens(new string[] { value }, 0, ref vectorValue)) { return(vectorValue); } return(null); } if (type == typeof(Quaternion)) { // convert the string to a quaternion Vector4 vectorValue = Vector4.zero; if (CommandHelpers.Vector4FromTokens(new string[] { value }, 0, ref vectorValue)) { return(new Quaternion(vectorValue.x, vectorValue.y, vectorValue.z, vectorValue.w)); } return(null); } if (type == typeof(Color)) { // is the value being provided as a web style string? if (value.Contains('#')) { Color colour = Color.magenta; if (ColorUtility.TryParseHtmlString(value, out colour)) { return(colour); } } // otherwise assume it is a RGBA set else { // convert the string to a color Vector4 vectorValue = Vector4.zero; if (CommandHelpers.Vector4FromTokens(new string[] { value }, 0, ref vectorValue)) { return(new Color(vectorValue.x, vectorValue.y, vectorValue.z, vectorValue.w)); } } return(null); } // does the type have a parse method that takes a string? MethodInfo parseMethod = type.GetMethod("Parse", BindingFlags.Public | BindingFlags.Static, null, CallingConventions.Any, new System.Type[] { typeof(string) }, null); if (parseMethod != null) { try { return(parseMethod.Invoke(null, new object[] { value })); } catch (System.Exception ex) { Debug.LogError("Failed to parse type: " + ex.Message); return(null); } } // does the type have a constructor that takes a string? ConstructorInfo constructor = type.GetConstructor(new System.Type[] { typeof(string) }); if (constructor != null) { try { return(constructor.Invoke(new object[] { value })); } catch (System.Exception ex) { Debug.LogError("Failed to construct type: " + ex.Message); return(null); } } return(null); }
public static List <string> GetAutocompleteOptions(string path, string command, AutocompleteCandidates candidateType) { // if we're at this point we know we have at least either a component or a class with static members // split based on the . as this might indicate a component or variable split string[] pathElements = path.Split('.'); System.Type foundType = null; Component foundComponent = null; // attempt to find the type if (ConsoleDaemon.Instance.AvailableTypes.ContainsKey(pathElements[0])) { foundType = ConsoleDaemon.Instance.AvailableTypes[pathElements[0]]; } // if there are multiple path elements then we may have a component if (pathElements.Length >= 2) { // attempt to find the component, if found then retrieve the type foundComponent = CommandHelpers.GetComponent(pathElements[0] + "." + pathElements[1]); if (foundComponent != null) { foundType = foundComponent.GetType(); } } // no matching type should only happen if invalid information has been entered if (foundType == null) { return(null); } // track the index into the path for the earliest spot a variable may be int variableStart = foundComponent != null ? 2 : 1; // cache the binding flags (can only search for instance if we have a component) BindingFlags flags = BindingFlags.Public | BindingFlags.Static; if (foundComponent != null) { flags |= BindingFlags.Instance; } // traverse the hierarchy of the path to find the last node bool lastElementIsPartial = false; for (int pathIndex = variableStart; pathIndex < pathElements.Length; ++pathIndex) { FieldInfo field = foundType.GetField(pathElements[pathIndex], flags); lastElementIsPartial = true; if (field != null) { // even if the parent was static after we are one field in we are dealing with an actual variable so add instance flags |= BindingFlags.Instance; foundType = field.FieldType; lastElementIsPartial = false; } else { PropertyInfo property = foundType.GetProperty(pathElements[pathIndex], flags); if (property != null) { // even if the parent was static after we are one field in we are dealing with an actual variable so add instance flags |= BindingFlags.Instance; foundType = property.PropertyType; lastElementIsPartial = false; } } } // find all candidate fields string partialName = lastElementIsPartial ? pathElements[pathElements.Length - 1] : ""; List <FieldInfo> fieldInfos = foundType.GetFields(flags).Where(field => field.Name.StartsWith(partialName)).ToList(); List <PropertyInfo> propertyInfos = foundType.GetProperties(flags).Where(property => property.Name.StartsWith(partialName)).ToList(); List <MethodInfo> methodInfos = null; // if we're doing a method search then also check methods if (candidateType == AutocompleteCandidates.Functions) { methodInfos = foundType.GetMethods(flags).Where(method => method.Name.StartsWith(partialName)).ToList(); } // no valid items found if ((fieldInfos == null || fieldInfos.Count == 0) && (propertyInfos == null || propertyInfos.Count == 0) && (methodInfos == null || methodInfos.Count == 0)) { return(null); } // assemble the base command string basePath = ""; int lastIndex = lastElementIsPartial ? pathElements.Length - 1 : pathElements.Length; for (int index = 0; index < lastIndex; ++index) { basePath += pathElements[index] + "."; } // build the autocomplete options List <string> autocompleteOptions = new List <string>(fieldInfos.Count); bool needsEscaping = basePath.Contains(" "); foreach (FieldInfo fieldInfo in fieldInfos) { string option = (command + " ") + (needsEscaping ? ("\"" + basePath + fieldInfo.Name + "\"") : (basePath + fieldInfo.Name)); autocompleteOptions.Add(option); } foreach (PropertyInfo propertyInfo in propertyInfos) { string option = (command + " ") + (needsEscaping ? ("\"" + basePath + propertyInfo.Name + "\"") : (basePath + propertyInfo.Name)); autocompleteOptions.Add(option); } if (candidateType == AutocompleteCandidates.Functions) { foreach (MethodInfo methodInfo in methodInfos) { string option = (command + " ") + (needsEscaping ? ("\"" + basePath + methodInfo.Name + "\"") : (basePath + methodInfo.Name)); // for now only include those without parameters if (methodInfo.GetParameters().Length > 0) { continue; } if (!autocompleteOptions.Contains(option)) { autocompleteOptions.Add(option); } } } return(autocompleteOptions); }
public static List <string> FetchAutocompleteOptions(string command, string[] tokens) { // get the names of the scenes in the build List <string> sceneNamesInBuild = CommandHelpers.GetSceneNamesInBuild(); List <string> autocompleteOptions = new List <string>(); string baseCommand = command;; // check if the user has already indicated additive bool needAdditiveInOptions = true; foreach (string token in tokens) { if (token.ToLower() == "additive") { needAdditiveInOptions = false; break; } } // handle additive keyword by sneakily adding it as a scene name unless the tokens already contain that keyword if (needAdditiveInOptions) { sceneNamesInBuild.Add("additive"); } // if there are no tokens then nothing further to do. the current base command is fine if (tokens == null || tokens.Length == 0) { } // check if the last token exactly matches a scene name else if (sceneNamesInBuild.Contains(tokens[tokens.Length - 1].ToLower())) { // construct the base command foreach (string sceneName in tokens) { // remove the scene from the available options sceneNamesInBuild.Remove(sceneName.ToLower()); baseCommand += " " + (sceneName.Contains(" ") ? "\"" + sceneName + "\"" : sceneName); } } // otherwise the token contains a partial name else { // construct the base command (exclude the final token) for (int index = 0; index < tokens.Length - 1; ++index) { // remove the scene from the available options sceneNamesInBuild.Remove(tokens[index].ToLower()); baseCommand += " " + (tokens[index].Contains(" ") ? "\"" + tokens[index] + "\"" : tokens[index]); } // filter out any scene names that do not match the potential candidates string partialName = tokens[tokens.Length - 1].ToLower(); if (partialName != "additive") { for (int index = 0; index < sceneNamesInBuild.Count; ++index) { if (!sceneNamesInBuild[index].StartsWith(partialName)) { sceneNamesInBuild.RemoveAt(index); --index; } } } else { baseCommand += " additive"; } // if we ended up with no valid scene names then error out if (sceneNamesInBuild.Count == 0) { return(null); } } // fill out the list of autocomplete options foreach (string sceneName in sceneNamesInBuild) { string workingSceneName = sceneName.Contains(" ") ? "\"" + sceneName + "\"" : sceneName; autocompleteOptions.Add(baseCommand + " " + workingSceneName); } return(autocompleteOptions); }