public static void OnWillSaveAssets(string[] paths) { foreach (var asset in paths) { UTils.ClearUnusedEntriesIn(asset); } }
/// <summary> /// Runs the specified plan. /// </summary> public static void Run(UTAutomationPlan plan, Dictionary <string, string> additionalProperties) { if (UTPreferences.ClearConsoleBeforeStart) { UTils.ClearConsole(); } var context = new UTContext(); if (additionalProperties != null) { foreach (var entry in additionalProperties) { string name = entry.Key; string val = entry.Value; if (UTPreferences.DebugMode) { Debug.Log("Setting additional property: " + name + " = " + val); } context[name] = val; } } UTMainWindow.Init(); var runner = UTomateRunner.Instance; runner.RequestRun(plan, context); }
/// <summary> /// Cleans up the entries in this statistics. This accounts for plans that have been deleted. /// </summary> public static void CleanUp() { var allPlans = UTils.AllVisibleAssetsOfType <UTAutomationPlan> (); var knownGuids = new HashSet <string> (); knownGuids.UnionWith(allPlans.ConvertAll(plan => plan.Guid)); var knownEntries = new List <StatEntry> (); var i = 0; StatEntry statEntry = null; do { statEntry = new StatEntry(); statEntry.guid = EditorPrefs.GetString(PlanPrefix + i, ""); if (!string.IsNullOrEmpty(statEntry.guid)) { statEntry.project = EditorPrefs.GetString(PlanPrefix + i + ".project", ""); statEntry.lastModified = FromString(EditorPrefs.GetString(PlanPrefix + i + ".lastModified")); statEntry.time = EditorPrefs.GetFloat(PlanPrefix + i + ".time", 0f); if (knownGuids.Contains(statEntry.guid)) { knownEntries.Add(statEntry); } else { // not known, check if it's from this project if (statEntry.project != Application.dataPath) { // different project, candidate for keeping it var age = DateTime.Now - statEntry.lastModified; if (age.TotalDays < 90) { // age is recent, keep it. knownEntries.Add(statEntry); } } // in all other cases, kill it. } EditorPrefs.DeleteKey(PlanPrefix + i); EditorPrefs.DeleteKey(PlanPrefix + i + ".time"); EditorPrefs.DeleteKey(PlanPrefix + i + ".project"); EditorPrefs.DeleteKey(PlanPrefix + i + ".lastModified"); } i++; } while (!string.IsNullOrEmpty(statEntry.guid)); i = 0; foreach (var entry in knownEntries) { EditorPrefs.SetString(PlanPrefix + i, entry.guid); EditorPrefs.SetFloat(PlanPrefix + i + ".time", entry.time); EditorPrefs.SetString(PlanPrefix + i + ".project", entry.project); EditorPrefs.SetString(PlanPrefix + i + ".lastModified", ToString(entry.lastModified)); i++; } }
/// <summary> /// Adds an arbitrary entry at the given position. /// </summary> /// <returns> /// The entry that was added. /// </returns> /// <param name='position'> /// Position at which the entry should be added. /// </param> /// <typeparam name='T'> /// The type of the entry to be added. /// </typeparam> public T AddEntry <T> (Vector2 position) where T : UTAutomationPlanEntry { CUUndoUtility.RegisterUndo(new UObject[] { data, graphData }, "Add Node"); var entry = UTils.AddAssetOfType <T> (PlanPath, true); entry.automationPlanEntryId = Guid.NewGuid().ToString(); if (data.firstEntry == null) { data.firstEntry = entry; } UTNode node = new UTNode(); node.Data = entry; node.Bounds = new Rect(position.x, position.y, 200, 200); graphData.AddNode(node); // add offset for next node position.x += 50; position.y += 50; EditorUtility.SetDirty(entry); EditorUtility.SetDirty(graphData); SelectNode(node, SelectionMode.Replace); return(entry); }
public static void CreateEcosystemPlan() { // get the folder selection // create a new plan at the currently selected folder. UTAutomationPlan plan = UTils.CreateAssetOfType <UTAutomationPlan>("name"); // create a new instance of the new class we created above. var editorModel = new PlayMakerEcosystem_uTomateModel(); editorModel.LoadPlan(plan); Selection.activeInstanceID = plan.GetInstanceID(); // now you can create actions. // FIRST ACTION UTEchoAction echoAction = UTAction.Create <UTEchoAction>(); // set their properties echoAction.text.Value = "Hello World"; echoAction.text.UseExpression = false; // this toggles f(x) // add the action to the automation plan var echoActionEntry = editorModel.AddAction(echoAction); echoActionEntry.name = "wtf"; Selection.activeInstanceID = plan.GetInstanceID(); // SECOND ACTION UTEchoAction anotherAction = UTAction.Create <UTEchoAction>(); // set their properties anotherAction.text.Value = "double dva"; anotherAction.text.UseExpression = false; // this toggles f(x) // add it as well var anotherActionEntry = editorModel.AddAction(anotherAction); //CONNECT // now connect the first echo action to the other action using the Connect method we wrote editorModel.Connect(echoActionEntry, anotherActionEntry); // finally set the echo action as first action var echoActionNode = editorModel.Graph.GetNodeFor(echoActionEntry); editorModel.SetFirstNode(echoActionNode); // if you want you can beautify the graph // so not all nodes are located at (0,0) editorModel.RelayoutPlan(); // finally you can execute your plan using UTomate.Run(plan); }
/// <summary> /// Creates a new UBuildAction of the given type. /// </summary> /// <typeparam name='T'> /// The type of action to create. /// </typeparam> public static T Create <T>() where T : UTAction { UTDoc doc = UTDoc.GetFor(typeof(T)); var result = UTils.CreateAssetOfType <T>(doc.title); result.CreatedWithActionVersion = ActionVersion; return(result); }
public static void Create() { #if UTOMATE_DEMO if (UTomate.CheckPlanCountExceeded()) { return; } #endif UTils.CreateAssetOfType <UTAutomationPlan> ("Automation Plan"); }
private static bool HasRequiredLicense(AttributeLookup attributeLookup, out string message) { var requiredComponents = new List <String> (); var licenseAttribute = GetAttribute <UTRequiresLicenseAttribute> (attributeLookup); if (licenseAttribute != null) { var theLicense = licenseAttribute.license; if ((theLicense & UTLicense.UnityPro) != 0 && !UTils.IsUnityPro) { requiredComponents.Add("Unity Pro"); } if ((theLicense & UTLicense.IosPro) != 0 && !UTils.HasAdvancedLicenseOn(UnityEditor.BuildTarget.iOS)) { requiredComponents.Add("iOS Pro"); } if ((theLicense & UTLicense.AndroidPro) != 0 && !UTils.HasAdvancedLicenseOn(UnityEditor.BuildTarget.Android)) { requiredComponents.Add("Android Pro"); } } else { // legacy attributes support, this will be removed later. #pragma warning disable 618 var unityProAttribute = GetAttribute <UTRequiresUnityPro> (attributeLookup); if (unityProAttribute != null && !UTils.IsUnityPro) { requiredComponents.Add("Unity Pro"); } var unityIosAttribute = GetAttribute <UTRequiresiOS> (attributeLookup); if (unityIosAttribute != null && unityIosAttribute.iOSPro && !UTils.HasAdvancedLicenseOn(UnityEditor.BuildTarget.iOS)) { requiredComponents.Add("iOS Pro"); } var unityAndroidAttribute = GetAttribute <UTRequiresAndroid> (attributeLookup); if (unityAndroidAttribute != null && unityAndroidAttribute.androidPro && !UTils.HasAdvancedLicenseOn(UnityEditor.BuildTarget.Android)) { requiredComponents.Add("Android Pro"); } #pragma warning restore 618 } if (requiredComponents.Count > 0) { message = String.Join(", ", requiredComponents.ToArray()); return(false); } message = ""; return(true); }
private void CleanUp() { UTils.ClearAsyncProgressBar(); var cancelled = context.CancelRequested; var failed = context.Failed; context = null; enumerator = null; var endTime = DateTime.Now; var duration = endTime - startTime; if (!cancelled && !failed) // recording cancelled runs will greatly diminish the accuracy of the statistics, so don't record them { UTStatistics.RecordRuntime(plan, (float)duration.TotalSeconds); } plan = null; Debug.Log("Automation finished in " + FormatTime(duration, false) + "."); if (cancelled) { Debug.LogWarning("Run was canceled by user."); } if (failed) { Debug.LogError("Run failed with error."); } if (OnRunnerFinished != null) { OnRunnerFinished(cancelled, failed); } // now check if the player settings were modified by an action, in this case we don't reset them var newBackgroundSetting = PlayerSettings.runInBackground; Application.runInBackground = false; // and reset it back if it wasn't so we don't f**k up what was set before.. if (newBackgroundSetting == playerSettingsRunInBackgroundValue) { // not modified by an action, in this case reset it PlayerSettings.runInBackground = playerSettingsRunInBackgroundValue; } if (reloadOfAssembliesLocked) { Debug.Log("Releasing assembly reload lock now."); EditorApplication.UnlockReloadAssemblies(); } AssetDatabase.Refresh(); // make sure updates are shown in the editor. }
private void SetupVariables(UTContext context) { context ["project:root"] = UTFileUtils.ProjectRoot; context ["project:assets"] = UTFileUtils.ProjectAssets; var platform = Environment.OSVersion.Platform; if (Application.platform == RuntimePlatform.OSXEditor) { platform = PlatformID.MacOSX; // seems to be some bug in Mono returning "Unix" when being on a mac. } context ["os:platform"] = platform.ToString(); var isUnixLike = platform == PlatformID.MacOSX || platform == PlatformID.Unix; context ["os:pathSeparatorType"] = isUnixLike ? "Unix" : "Windows"; context ["os:pathSeparatorChar"] = isUnixLike ? "/" : "\\"; if (isUnixLike) { context ["user:home"] = UTFileUtils.NormalizeSlashes(Environment.GetEnvironmentVariable("HOME")); } else if (platform == PlatformID.Win32NT) { context ["user:home"] = UTFileUtils.NormalizeSlashes(Environment.ExpandEnvironmentVariables("%HOMEDRIVE%%HOMEPATH%")); } else { Debug.Log("Unable to detect underlying os. Property 'user:home' is not available."); } context ["user:desktop"] = UTFileUtils.NormalizeSlashes(Environment.GetFolderPath(Environment.SpecialFolder.Desktop)); context ["unity:isUnityPro"] = UTils.IsUnityPro; context ["unity:supportsAndroid"] = UTils.IsBuildTargetSupported(UnityEditor.BuildTarget.Android); context ["unity:supportsIos"] = UTils.IsBuildTargetSupported(UnityEditor.BuildTarget.iOS); context ["unity:version"] = Application.unityVersion; context ["utomate:debugMode"] = UTPreferences.DebugMode; context ["project:picard"] = "Make it so!"; context ["project:worf"] = "Torpedos ready, sir!"; context ["project:bones"] = "I'm a doctor, no game developer!"; }
/// <summary> /// Loads a plan into this model. /// </summary> /// <param name='plan'> /// The plan to load. /// </param> public void LoadPlan(UTAutomationPlan plan) { if (plan != null) { data = plan; string path = PlanPath; graphData = null; selectedNodes.Clear(); // objects with hide fagl are not returned by LoadAssetAtPath UnityEngine.Object[] assets = AssetDatabase.LoadAllAssetsAtPath(path); foreach (UnityEngine.Object asset in assets) { if (asset is UTGraph) { graphData = (UTGraph)asset; break; } } if (graphData == null) { graphData = UTils.AddAssetOfType <UTGraph> (path, true); graphData.name = "Graph"; EditorUtility.SetDirty(graphData); } if (plan.firstEntry != null) { SelectNode(graphData.GetNodeFor(plan.firstEntry), SelectionMode.Add); } } else { data = null; graphData = null; selectedNodes.Clear(); highlightedNode = null; } }
public static List <UTAutomationPlan> AllUTAutomationPlans() { return(UTils.AllVisibleAssetsOfType <UTAutomationPlan> ()); }
public static void Create() { UTils.CreateAssetOfType <ChangeLog> ("Change Log"); }
public override System.Collections.IEnumerator Execute(UTContext context) { if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.WebPlayer || EditorUserBuildSettings.activeBuildTarget == BuildTarget.WebPlayerStreamed) { Debug.LogWarning("You have currently set the build target to 'Web Player'. This may cause interference with actions that access the internet. If you get an error message about cross domain policy from this action, switch the target to 'PC and Mac Standalone' and try again."); } var theNexusUrl = nexusUrl.EvaluateIn(context); if (string.IsNullOrEmpty(theNexusUrl)) { throw new UTFailBuildException("You need to specify the nexus URL", this); } var theRepoId = repositoryId.EvaluateIn(context); if (string.IsNullOrEmpty(theRepoId)) { throw new UTFailBuildException("You need to specify the repository id.", this); } var theUserName = userName.EvaluateIn(context); var thePassword = password.EvaluateIn(context); var theGroupId = groupId.EvaluateIn(context); if (string.IsNullOrEmpty(theGroupId)) { throw new UTFailBuildException("You need to specify the group id.", this); } var theArtifactId = artifactId.EvaluateIn(context); if (string.IsNullOrEmpty(theArtifactId)) { throw new UTFailBuildException("You need to specify the artifact id.", this); } var theVersion = version.EvaluateIn(context); if (string.IsNullOrEmpty(theVersion)) { throw new UTFailBuildException("You need to specify the version.", this); } var thePackaging = packaging.EvaluateIn(context); if (string.IsNullOrEmpty(thePackaging)) { throw new UTFailBuildException("You need to specify the packaging.", this); } var theExtension = extension.EvaluateIn(context); var theClassifier = classifier.EvaluateIn(context); var theInputFileName = inputFileName.EvaluateIn(context); if (string.IsNullOrEmpty(theInputFileName)) { throw new UTFailBuildException("You need to specify the input file name.", this); } if (Directory.Exists(theInputFileName)) { throw new UTFailBuildException("The specified input file " + theInputFileName + " is a directory.", this); } if (!File.Exists(theInputFileName)) { throw new UTFailBuildException("The specified input file " + theInputFileName + " does not exist.", this); } WWWForm form = new WWWForm(); form.AddField("r", theRepoId); form.AddField("g", theGroupId); form.AddField("a", theArtifactId); form.AddField("v", theVersion); if (!string.IsNullOrEmpty(thePackaging)) { form.AddField("p", thePackaging); } if (!string.IsNullOrEmpty(theClassifier)) { form.AddField("c", theClassifier); } if (!string.IsNullOrEmpty(theExtension)) { form.AddField("e", theExtension); } var bytes = File.ReadAllBytes(theInputFileName); form.AddBinaryData("file", bytes, new FileInfo(theInputFileName).Name); var hash = UTils.ComputeHash(bytes); if (UTPreferences.DebugMode) { Debug.Log("SHA1-Hash of file to upload: " + hash); } string authString = theUserName + ":" + thePassword; var authBytes = System.Text.UTF8Encoding.UTF8.GetBytes(authString); var headers = new Hashtable(); foreach (var key in form.headers.Keys) { headers.Add(key, form.headers [key]); } headers.Add("Authorization", "Basic " + System.Convert.ToBase64String(authBytes)); var url = UTils.BuildUrl(theNexusUrl, "/service/local/artifact/maven/content"); // using (var www = new WWW (url, form.data, //#if UNITY_WP8 // PortUtil.HashtableToDictionary<string, string>(headers) //#else // headers //#endif // )) // { // do { // yield return ""; // } while(!www.isDone && !context.CancelRequested); // if (UTPreferences.DebugMode) { // Debug.Log ("Server Response: " + www.text); // } // } if (!context.CancelRequested) { using (var wc = new WebClient()) { if (!string.IsNullOrEmpty(theUserName)) { Debug.Log("Setting credentials"); wc.Credentials = new NetworkCredential(theUserName, thePassword); } Uri uri = new Uri(UTils.BuildUrl(theNexusUrl, "/service/local/artifact/maven/resolve?") + "g=" + Uri.EscapeUriString(theGroupId) + "&a=" + Uri.EscapeUriString(theArtifactId) + "&v=" + Uri.EscapeUriString(theVersion) + "&r=" + Uri.EscapeUriString(theRepoId) + "&p=" + Uri.EscapeUriString(thePackaging) + (!string.IsNullOrEmpty(theClassifier) ? "&c=" + Uri.EscapeUriString(theClassifier) : "") + (!string.IsNullOrEmpty(theExtension) ? "&e=" + Uri.EscapeUriString(theExtension) : "")); var downloadFinished = false; var error = false; string result = null; wc.DownloadStringCompleted += delegate(object sender, DownloadStringCompletedEventArgs e) { downloadFinished = true; error = e.Error != null; if (error) { Debug.LogError("An error occured while downloading artifact information. " + e.Error.Message, this); } else { result = (string)e.Result; } }; wc.DownloadStringAsync(uri); do { yield return(""); if (context.CancelRequested) { wc.CancelAsync(); } } while(!downloadFinished); if (!context.CancelRequested) { if (!error) { if (UTPreferences.DebugMode) { Debug.Log("Server Response: " + result); } if (result.Contains("<sha1>" + hash + "</sha1>")) { Debug.Log("Successfully uploaded artifact " + theInputFileName + ".", this); } else { throw new UTFailBuildException("Upload failed. Checksums do not match.", this); } } else { throw new UTFailBuildException("Artifact verification failed", this); } } } } }
public override IEnumerator Execute(UTContext context) { var theProjectPath = projectPath.EvaluateIn(context); if (!Directory.Exists(theProjectPath)) { throw new UTFailBuildException("Project path " + theProjectPath + " does not exist.", this); } if (UTFileUtils.IsBelow(UTFileUtils.ProjectRoot, theProjectPath)) { throw new UTFailBuildException("You cannot run uTomate externally on the current project. Use the Sub-Plan node if you want to run a plan as part of a plan.", this); } var thePlanName = planName.EvaluateIn(context); var theDebugMode = debugMode.EvaluateIn(context); var theProperties = EvaluateAll(properties, context); StringBuilder sb = new StringBuilder(); foreach (var prop in theProperties) { sb.Append(" -prop ").Append(UTExecutableParam.Quote(prop)); } Process process = new Process(); process.StartInfo.FileName = UTils.GetEditorExecutable(); process.StartInfo.Arguments = "-projectPath " + UTExecutableParam.Quote(theProjectPath) + " -executeMethod UTExternalRunner.RunPlan -plan " + UTExecutableParam.Quote(thePlanName) + " -debugMode " + theDebugMode + sb.ToString(); if (UTPreferences.DebugMode) { process.StartInfo.RedirectStandardOutput = true; process.StartInfo.UseShellExecute = false; process.OutputDataReceived += (sender, args) => UDebug.Log("[Unity]" + args.Data); UDebug.Log("Executing: " + process.StartInfo.FileName + " with arguments " + process.StartInfo.Arguments); } try { if (!process.Start()) { throw new UTFailBuildException("Unable to start Unity3D.", this); } if (UTPreferences.DebugMode) { process.BeginOutputReadLine(); } } catch (Win32Exception e) { throw new UTFailBuildException("Unable to start process " + e.Message, this); } do { yield return(""); if (context.CancelRequested && !process.HasExited) { process.Kill(); break; } } while(!process.HasExited); if (!context.CancelRequested && failOnError.EvaluateIn(context)) { if (process.ExitCode != 0) { throw new UTFailBuildException("Plan " + thePlanName + " failed or was cancelled.", this); } } }