private void DrawEnvironmentInspectorForWorker(WorkerBuildConfiguration configurationForWorker) { EditorGUILayout.LabelField("Environments", EditorStyles.boldLabel); DrawEnvironmentInspector(BuildEnvironment.Local, configurationForWorker); DrawEnvironmentInspector(BuildEnvironment.Cloud, configurationForWorker); }
private bool DrawWorkerConfiguration(WorkerBuildConfiguration configurationForWorker) { var workerType = configurationForWorker.WorkerType; EditorGUILayout.BeginHorizontal(); configurationForWorker.ShowFoldout = EditorGUILayout.Foldout(configurationForWorker.ShowFoldout, workerType); var controlRect = EditorGUILayout.GetControlRect(false); var buttonRect = new Rect(controlRect); buttonRect.width = buttonRect.height + 5; if (GUI.Button(buttonRect, RemoveWorkerTypeButtonContents)) { return(false); } EditorGUILayout.EndHorizontal(); if (configurationForWorker.ShowFoldout) { using (IndentLevelScope(1)) { DrawScenesInspectorForWorker(configurationForWorker); DrawEnvironmentInspectorForWorker(configurationForWorker); } } return(true); }
private void DrawScenesInspectorForWorker(WorkerBuildConfiguration configurationForWorker) { EditorGUILayout.LabelField("Scenes", EditorStyles.boldLabel); using (IndentLevelScope(1)) { var scenesToShowInList = configurationForWorker .ScenesForWorker .Select((sceneAsset, index) => new SceneItem(sceneAsset, true, scenesInAssetDatabase)) .ToList(); EditorGUI.BeginChangeCheck(); var sceneItems = scenesInAssetDatabase .Where(sceneAsset => !configurationForWorker.ScenesForWorker.Contains(sceneAsset)) .Select(sceneAsset => new SceneItem(sceneAsset, false, scenesInAssetDatabase)) .ToList(); var horizontalLayout = Screen.width > ScreenWidthForHorizontalLayout; using (horizontalLayout ? new EditorGUILayout.HorizontalScope() : null) { using (horizontalLayout ? new EditorGUILayout.VerticalScope() : null) { EditorGUILayout.LabelField("Scenes to include (in order)"); DrawIndentedList(scenesToShowInList, ReorderableListFlags.ShowIndices | ReorderableListFlags.EnableReordering, SceneItem.Drawer); } using (horizontalLayout ? new EditorGUILayout.VerticalScope() : null) { using (horizontalLayout ? IndentLevelScope(-EditorGUI.indentLevel) : null) { EditorGUILayout.LabelField("Exclude"); DrawIndentedList(sceneItems, ReorderableListFlags.None, SceneItem.Drawer); } } } if (EditorGUI.EndChangeCheck()) { EditorUtility.SetDirty(target); Undo.RecordObject(target, "Configure scenes for worker"); configurationForWorker.ScenesForWorker = scenesToShowInList.Concat(sceneItems) .Where(item => item.Included) .Select(item => item.SceneAsset) .ToArray(); scenesChanged = true; } } }
private void DrawEnvironmentInspectorForWorker(WorkerBuildConfiguration configurationForWorker) { DrawEnvironmentInspector(BuildEnvironment.Local, configurationForWorker); EditorGUILayout.Space(); DrawEnvironmentInspector(BuildEnvironment.Cloud, configurationForWorker); }
private void TrackDragDrop(WorkerBuildConfiguration configurationForWorker, EventType currentEventType, SceneAsset item, DragAndDropInfo dragState, int itemIndex) { switch (currentEventType) { case EventType.MouseDrag: DragAndDrop.PrepareStartDrag(); DragAndDrop.objectReferences = new[] { item }; DragAndDrop.paths = new[] { AssetDatabase.GetAssetPath(item) }; DragAndDrop.StartDrag(item.name); dragState.SourceItemIndex = itemIndex; Event.current.Use(); Repaint(); sourceDragState = dragState; break; case EventType.DragPerform: Event.current.Use(); DragAndDrop.AcceptDrag(); Repaint(); break; case EventType.MouseUp: // Fall through. case EventType.DragExited: sourceDragState = null; dragState.SourceItemIndex = -1; Repaint(); break; case EventType.DragUpdated: var sceneAssets = DragAndDrop.objectReferences.OfType <SceneAsset>() .ToList(); if (sceneAssets.Any()) { if (dragState.SourceItemIndex == -1 && sceneAssets.Intersect(configurationForWorker.ScenesForWorker).Any()) { DragAndDrop.visualMode = DragAndDropVisualMode.Rejected; } else { DragAndDrop.visualMode = DragAndDropVisualMode.Copy; } Event.current.Use(); Repaint(); } break; } }
public override void OnInspectorGUI() { var workerConfiguration = (SpatialOSBuildConfiguration)target; EditorGUILayout.BeginHorizontal(); workerTypeName = EditorGUILayout.TextField(workerTypeName); var controlRect = EditorGUILayout.GetControlRect(false); var buttonRect = new Rect(controlRect); buttonRect.width = buttonRect.height + 5; if (GUI.Button(buttonRect, AddWorkerTypeButtonContents)) { var workerType = new WorkerPlatform(workerTypeName); var exists = workerConfiguration.WorkerBuildConfigurations.Any(x => x.WorkerPlatform == workerType); if (!exists) { var config = new WorkerBuildConfiguration { WorkerPlatform = new WorkerPlatform(workerTypeName), ScenesForWorker = new SceneAsset[] { }, LocalBuildConfig = new BuildEnvironmentConfig() { BuildPlatforms = SpatialBuildPlatforms.Current, BuildOptions = BuildOptions.Development }, CloudBuildConfig = new BuildEnvironmentConfig() { BuildPlatforms = SpatialBuildPlatforms.Current } }; workerConfiguration.WorkerBuildConfigurations.Add(config); } } EditorGUILayout.EndHorizontal(); scenesChanged = false; var configs = workerConfiguration.WorkerBuildConfigurations; foreach (var workerConfig in configs) { if (!DrawWorkerConfiguration(workerConfig)) { configs.Remove(workerConfig); break; } } if (scenesChanged) { scenesChanged = false; workerConfiguration.UpdateEditorScenesForBuild(); } }
public override void OnInspectorGUI() { var workerConfiguration = (SpatialOSBuildConfiguration)target; EditorGUILayout.BeginHorizontal(); workerTypeName = EditorGUILayout.TextField(workerTypeName); var controlRect = EditorGUILayout.GetControlRect(false); var buttonRect = new Rect(controlRect); buttonRect.width = buttonRect.height + 5; if (GUI.Button(buttonRect, AddWorkerTypeButtonContents)) { if (workerConfiguration.WorkerBuildConfigurations.All(x => x.WorkerType != workerTypeName)) { var config = new WorkerBuildConfiguration { WorkerType = workerTypeName, LocalBuildConfig = new BuildEnvironmentConfig { BuildOptions = BuildOptions.Development, }, CloudBuildConfig = new BuildEnvironmentConfig { BuildOptions = BuildOptions.EnableHeadlessMode, } }; workerConfiguration.WorkerBuildConfigurations.Add(config); } } EditorGUILayout.EndHorizontal(); scenesChanged = false; var configs = workerConfiguration.WorkerBuildConfigurations; foreach (var workerConfig in configs) { if (!DrawWorkerConfiguration(workerConfig)) { configs.Remove(workerConfig); break; } } if (scenesChanged) { scenesChanged = false; EditorApplication.delayCall += workerConfiguration.UpdateEditorScenesForBuild; } }
private void DrawEnvironmentInspector(BuildEnvironment environment, WorkerBuildConfiguration configurationForWorker) { using (IndentLevelScope(1)) { EditorGUILayout.LabelField(environment.ToString()); var environmentConfiguration = configurationForWorker.GetEnvironmentConfig(environment); ConfigureBuildPlatforms(environmentConfiguration); ConfigureBuildOptions(environmentConfiguration); } }
private SceneAsset[] GetScenesForWorker(WorkerPlatform workerPlatform) { WorkerBuildConfiguration configurationForWorker = null; if (WorkerBuildConfigurations != null) { configurationForWorker = WorkerBuildConfigurations.FirstOrDefault(config => config.WorkerPlatform == workerPlatform); } return(configurationForWorker == null ? new SceneAsset[0] : configurationForWorker.ScenesForWorker); }
private void ResetToDefault() { // Build default settings var client = new WorkerBuildConfiguration() { WorkerPlatform = WorkerPlatform.UnityClient, ScenesForWorker = AssetDatabase.FindAssets("t:Scene") .Select(AssetDatabase.GUIDToAssetPath) .Where(path => path.Contains(WorkerPlatform.UnityClient.ToString())) .Select(AssetDatabase.LoadAssetAtPath <SceneAsset>).ToArray(), LocalBuildConfig = new BuildEnvironmentConfig() { BuildPlatforms = SpatialBuildPlatforms.Current, BuildOptions = BuildOptions.Development }, CloudBuildConfig = new BuildEnvironmentConfig() { BuildPlatforms = SpatialBuildPlatforms.Current } }; var worker = new WorkerBuildConfiguration() { WorkerPlatform = WorkerPlatform.UnityGameLogic, ScenesForWorker = AssetDatabase.FindAssets("t:Scene") .Select(AssetDatabase.GUIDToAssetPath) .Where(path => path.Contains(WorkerPlatform.UnityGameLogic.ToString())) .Select(AssetDatabase.LoadAssetAtPath <SceneAsset>).ToArray(), LocalBuildConfig = new BuildEnvironmentConfig() { BuildPlatforms = SpatialBuildPlatforms.Current, BuildOptions = BuildOptions.EnableHeadlessMode }, CloudBuildConfig = new BuildEnvironmentConfig() { BuildPlatforms = SpatialBuildPlatforms.Linux, BuildOptions = BuildOptions.EnableHeadlessMode } }; WorkerBuildConfigurations = new List <WorkerBuildConfiguration> { client, worker }; isInitialised = true; }
private void DrawEmptySceneBox(WorkerBuildConfiguration configurationForWorker, EventType currentEventType) { // Allow dropping to form a new list. EditorGUILayout.HelpBox("Drop scenes here", MessageType.Info); var rect = GUILayoutUtility.GetLastRect(); if (rect.Contains(Event.current.mousePosition)) { switch (currentEventType) { case EventType.DragPerform: RecordUndo("Configure scenes for worker"); configurationForWorker.ScenesForWorker = DragAndDrop.objectReferences .OfType <SceneAsset>().ToList(); DragAndDrop.AcceptDrag(); Event.current.Use(); Repaint(); break; case EventType.DragUpdated: if (DragAndDrop.objectReferences.OfType <SceneAsset>().Any()) { DragAndDrop.visualMode = DragAndDropVisualMode.Copy; Event.current.Use(); Repaint(); } break; case EventType.Repaint: if (DragAndDrop.objectReferences.OfType <SceneAsset>().Any()) { EditorGUI.DrawRect(rect, new Color(0, 0.8f, 0, 0.25f)); } break; } } }
private static string GetBuildConfigurationStateIcon(WorkerBuildConfiguration configuration) { var isWarning = configuration.CloudBuildConfig.BuildTargets.Any(IsBuildTargetWarning) || configuration.LocalBuildConfig.BuildTargets.Any(IsBuildTargetWarning); var isError = configuration.CloudBuildConfig.BuildTargets.Any(IsBuildTargetError) || configuration.LocalBuildConfig.BuildTargets.Any(IsBuildTargetError); if (isError) { return(BuildConfigEditorStyle.BuiltInErrorIcon); } if (isWarning) { return(BuildConfigEditorStyle.BuiltInWarningIcon); } return(null); }
private void HandleObjectSelectorUpdated(WorkerBuildConfiguration configurationForWorker, int pickerId) { if (Event.current.commandName == "ObjectSelectorClosed" && EditorGUIUtility.GetObjectPickerControlID() == pickerId) { var scene = (SceneAsset)EditorGUIUtility.GetObjectPickerObject(); if (scene == null) { return; } if (configurationForWorker.ScenesForWorker.All(a => a.name != scene.name)) { RecordUndo("Configure scenes for worker"); configurationForWorker.ScenesForWorker.Add(scene); } } }
public override void OnInspectorGUI() { if (style == null) { style = new BuildConfigEditorStyle(); } if (allWorkers == null) { try { var guids = AssetDatabase.FindAssets("WorkerMenu"); var textFile = guids.Select(AssetDatabase.GUIDToAssetPath) .FirstOrDefault(f => Path.GetExtension(f) == ".txt"); if (string.IsNullOrEmpty(textFile)) { throw new Exception("Could not find WorkerMenu.txt - you may need to regenerate code."); } allWorkers = File.ReadAllLines(Path.Combine(Application.dataPath, "..", textFile)); } catch (Exception e) { allWorkers = new string[0]; Debug.LogException(e); } } // Clean up state when drag events end. if (sourceDragState != null && Event.current.type == EventType.DragExited) { sourceDragState.SourceItemIndex = -1; sourceDragState = null; Repaint(); } var workerConfiguration = (BuildConfig)target; BuildConfigEditorStyle.DrawHorizontalLine(); var configs = workerConfiguration.WorkerBuildConfigurations; for (var index = 0; index < configs.Count; index++) { var workerConfig = configs[index]; if (!DrawWorkerConfiguration(workerConfig)) { RecordUndo($"Remove '{workerConfig.WorkerType}'"); configs.RemoveAt(index); index--; } BuildConfigEditorStyle.DrawHorizontalLine(); } using (new EditorGUI.DisabledScope(workerConfiguration.WorkerBuildConfigurations.Count == allWorkers.Length)) using (new GUILayout.HorizontalScope()) { GUILayout.FlexibleSpace(); if (GUILayout.Button("Add new worker type")) { workerChooser = new WorkerChoicePopup(addWorkerButtonRect, workerConfiguration, allWorkers); PopupWindow.Show(addWorkerButtonRect, workerChooser); } if (Event.current.type == EventType.Repaint) { addWorkerButtonRect = GUILayoutUtility.GetLastRect(); // Only add the new worker during the Repaint phase - otherwise you'll see errors due to adding new content at the wrong point of the GUI lifecycle. if (workerChooser != null && workerChooser.Choice != -1) { RecordUndo("Add '{Choices[i]}'"); var config = new WorkerBuildConfiguration { WorkerType = workerChooser.Choices[workerChooser.Choice], LocalBuildConfig = new BuildEnvironmentConfig(WorkerBuildData.LocalBuildTargets, WorkerBuildData.GetCurrentBuildTargetConfig()), CloudBuildConfig = new BuildEnvironmentConfig(WorkerBuildData.AllBuildTargets, WorkerBuildData.GetLinuxBuildTargetConfig()) }; workerConfiguration.WorkerBuildConfigurations.Add(config); workerChooser = null; } } GUILayout.FlexibleSpace(); } if (invalidateCachedContent > 0) { invalidateCachedContent--; } }
private void DrawEnvironmentInspector(BuildEnvironment environment, WorkerBuildConfiguration configurationForWorker) { var environmentName = environment.ToString(); var environmentConfiguration = configurationForWorker.GetEnvironmentConfig(environment); var hash = configurationForWorker.WorkerType.GetHashCode() ^ environment.GetHashCode() ^ typeof(FoldoutState).GetHashCode(); var foldoutState = stateManager.GetStateObjectOrDefault <FoldoutState>(hash); if (foldoutState.Content == null || invalidateCachedContent > 0) { var builtTargets = string.Join(",", environmentConfiguration.BuildTargets.Where(t => t.Enabled).Select(t => t.Label)); foldoutState.Content = new GUIContent($"{environmentName} Build Options ({builtTargets})"); if (environmentConfiguration.BuildTargets.Any(IsBuildTargetError)) { foldoutState.Icon = new GUIContent(EditorGUIUtility.IconContent(BuildConfigEditorStyle.BuiltInErrorIcon)) { tooltip = "Missing build support for one or more build targets." }; } else if (environmentConfiguration.BuildTargets.Any(IsBuildTargetWarning)) { foldoutState.Icon = new GUIContent(EditorGUIUtility.IconContent(BuildConfigEditorStyle.BuiltInWarningIcon)) { tooltip = "Missing build support for one or more build targets." }; } else { foldoutState.Icon = null; } } using (new GUILayout.HorizontalScope()) { foldoutState.Expanded = EditorGUILayout.Foldout(foldoutState.Expanded, foldoutState.Content, true); GUILayout.FlexibleSpace(); if (foldoutState.Icon != null) { GUILayout.Label(foldoutState.Icon); GUILayout.Space(28); } } using (var check = new EditorGUI.ChangeCheckScope()) { if (foldoutState.Expanded) { DrawBuildTargets(environmentConfiguration, hash); } if (check.changed) { // Re-evaluate heading. foldoutState.Content = null; } } }
private void DrawScenesInspectorForWorker(WorkerBuildConfiguration configurationForWorker) { DragAndDropInfo dragState; var currentEventType = Event.current.type; using (new EditorGUIUtility.IconSizeScope(SmallIconSize)) using (new EditorGUILayout.HorizontalScope()) { EditorGUILayout.LabelField("Scenes to include (in order)"); var workerControlId = configurationForWorker.WorkerType.GetHashCode() ^ typeof(DragAndDrop).GetHashCode(); dragState = stateManager.GetStateObjectOrDefault <DragAndDropInfo>(workerControlId); GUILayout.FlexibleSpace(); if (GUILayout.Button(style.AddSceneButtonContents, EditorStyles.miniButton)) { EditorGUIUtility.ShowObjectPicker <SceneAsset>(null, false, "t:Scene", workerControlId); } HandleObjectSelectorUpdated(configurationForWorker, workerControlId); } if (configurationForWorker.ScenesForWorker.Count == 0) { DrawEmptySceneBox(configurationForWorker, currentEventType); } else { int?indexToRemove = null; int?targetItemIndex = null; if (currentEventType == EventType.Repaint) { dragState.AllItemsRect = Rect.zero; dragState.ItemHeight = 0; } for (var i = 0; i < configurationForWorker.ScenesForWorker.Count; i++) { var item = configurationForWorker.ScenesForWorker[i]; using (new EditorGUILayout.HorizontalScope()) { GUILayout.Space(EditorGUI.indentLevel * 16.0f); indexToRemove = DrawSceneItem(i, dragState, item, currentEventType, indexToRemove); var hitRect = new Rect(dragState.AllItemsRect.xMin, dragState.AllItemsRect.yMin + i * (dragState.ItemHeight + EditorGUIUtility.standardVerticalSpacing) - EditorGUIUtility.standardVerticalSpacing / 2.0f, dragState.AllItemsRect.width, dragState.ItemHeight + EditorGUIUtility.standardVerticalSpacing / 2.0f); if (hitRect.Contains(Event.current.mousePosition)) { if (i != dragState.SourceItemIndex) { targetItemIndex = Event.current.mousePosition.y > hitRect.yMin + hitRect.height / 2 ? i + 1 : i; } TrackDragDrop(configurationForWorker, currentEventType, item, dragState, i); } } } List <SceneAsset> list = null; if (indexToRemove.HasValue) { list = configurationForWorker.ScenesForWorker.ToList(); list.RemoveAt(indexToRemove.Value); } else if (targetItemIndex.HasValue) { list = configurationForWorker.ScenesForWorker.ToList(); switch (currentEventType) { case EventType.DragPerform: // The drag event is coming from outside of this list, for example: // The asset browser or another worker's scene list. // If the incoming drag contains a duplicate of the item, it's already been rejected in the hit detection code, // so there's no need to validate it again here. if (dragState.SourceItemIndex == -1) { if (targetItemIndex >= list.Count) { list.AddRange(DragAndDrop.objectReferences.OfType <SceneAsset>()); } else { list.InsertRange(targetItemIndex.Value, DragAndDrop.objectReferences.OfType <SceneAsset>()); } } else { var movingItem = list[dragState.SourceItemIndex]; if (targetItemIndex >= list.Count) { list.RemoveAt(dragState.SourceItemIndex); list.Add(movingItem); } else { list.RemoveAt(dragState.SourceItemIndex); if (targetItemIndex >= dragState.SourceItemIndex) { list.Insert(targetItemIndex.Value - 1, movingItem); } else { list.Insert(targetItemIndex.Value, movingItem); } } } break; case EventType.Repaint: if (DragAndDrop.visualMode == DragAndDropVisualMode.Copy) { var newRect = new Rect(dragState.AllItemsRect.xMin, dragState.AllItemsRect.yMin + targetItemIndex.Value * dragState.AllItemsRect.height / list.Count, dragState.AllItemsRect.width, 2); EditorGUI.DrawRect(newRect, new Color(0.4f, 0.4f, 0.4f, 1)); } else if (DragAndDrop.visualMode == DragAndDropVisualMode.Rejected) { var newRect = new Rect(dragState.AllItemsRect); EditorGUI.DrawRect(newRect, new Color(0.8f, 0.0f, 0.0f, 0.25f)); } break; } } if (list != null) { RecordUndo("Configure scenes for worker"); configurationForWorker.ScenesForWorker = list; } } }
private bool DrawWorkerConfiguration(WorkerBuildConfiguration configurationForWorker) { var workerType = configurationForWorker.WorkerType; var foldoutState = stateManager.GetStateObjectOrDefault <FoldoutState>(configurationForWorker.WorkerType.GetHashCode()); using (new EditorGUILayout.HorizontalScope()) { if (foldoutState.Content == null || invalidateCachedContent > 0) { var buildStateIcon = GetBuildConfigurationStateIcon(configurationForWorker); if (buildStateIcon != null) { foldoutState.Icon = new GUIContent(EditorGUIUtility.IconContent(buildStateIcon)) { tooltip = "Missing build support for one or more build targets." }; } else if (configurationForWorker.CloudBuildConfig.BuildTargets.Any(NeedsAndroidSdk) || configurationForWorker.LocalBuildConfig.BuildTargets.Any(NeedsAndroidSdk)) { foldoutState.Icon = new GUIContent(EditorGUIUtility.IconContent(BuildConfigEditorStyle.BuiltInErrorIcon)) { tooltip = "Missing Android SDK installation. Go to Preferences > External Tools to set it up." }; } else { foldoutState.Icon = null; } foldoutState.Content = new GUIContent(workerType); } foldoutState.Expanded = EditorGUILayout.Foldout(foldoutState.Expanded, foldoutState.Content, true); GUILayout.FlexibleSpace(); using (new EditorGUIUtility.IconSizeScope(SmallIconSize)) { if (foldoutState.Icon != null) { using (new EditorGUIUtility.IconSizeScope(Vector2.zero)) { GUILayout.Label(foldoutState.Icon); } } if (GUILayout.Button(style.RemoveWorkerTypeButtonContents, EditorStyles.miniButton)) { return(false); } } } using (var check = new EditorGUI.ChangeCheckScope()) using (new EditorGUI.IndentLevelScope()) { if (foldoutState.Expanded) { DrawScenesInspectorForWorker(configurationForWorker); EditorGUILayout.Space(); DrawEnvironmentInspectorForWorker(configurationForWorker); } if (check.changed) { // Re-evaluate heading. foldoutState.Content = null; } } return(true); }