/// <summary> /// Triggered when the user clicks on the clone button next to a dictionary entry. Clones an element and /// adds the clone to the dictionary. /// </summary> /// <param name="rowIdx">Sequential row index of the entry that was clicked.</param> protected internal virtual void OnCloneButtonClicked(int rowIdx) { if (IsEditInProgress()) { DialogBox.Open( new LocEdString("Edit in progress."), new LocEdString("You are editing the entry with key \"" + editKey + "\". You cannot clone a row " + "before applying or discarding those changes. Do you wish to apply those changes first?"), DialogBox.Type.YesNoCancel, x => { switch (x) { case DialogBox.ResultType.Yes: if (ApplyChanges()) { StartClone(rowIdx); } break; case DialogBox.ResultType.No: DiscardChanges(); StartClone(rowIdx); break; } }); } else { StartClone(rowIdx); } }
/// <summary> /// Attempts to start the build process if user confirms. /// </summary> private void TryStartBuild() { Action <DialogBox.ResultType> dialogCallback = (result) => { if (result == DialogBox.ResultType.Yes) { TrySaveScene(); } else if (result == DialogBox.ResultType.No) { Build(); } }; if (EditorApplication.IsSceneModified()) { DialogBox.Open("Warning", "You current scene has modifications. Do you wish to save them first?", DialogBox.Type.YesNoCancel, dialogCallback); } else { Build(); } }
/// <summary> /// Called when the user requests that the editor shuts down. You must manually close the editor from this /// method if you choose to accept the users request. /// </summary> static void OnEditorQuitRequested() { Action <DialogBox.ResultType> dialogCallback = (result) => { if (result == DialogBox.ResultType.Yes) { TrySaveScene(); } else if (result == DialogBox.ResultType.No) { EditorApplication.SaveProject(); EditorApplication.Quit(); } }; if (EditorApplication.IsSceneModified()) { DialogBox.Open("Warning", "You current scene has modifications. Do you wish to save them first?", DialogBox.Type.YesNoCancel, dialogCallback); } else { EditorApplication.SaveProject(); EditorApplication.Quit(); } }
/// <summary> /// Shows a dialog box that notifies the user that the animation clip is read only. /// </summary> private void ShowReadOnlyMessage() { LocEdString title = new LocEdString("Warning"); LocEdString message = new LocEdString("You cannot edit keyframes on animation clips that" + " are imported from an external file."); DialogBox.Open(title, message, DialogBox.Type.OK); }
/// <summary> /// Attempts to apply any changes made to the currently edited row. /// </summary> /// <returns>True if the changes were successfully applied, false if the new key already exists in the dictionary. /// </returns> private bool ApplyChanges() { if (!IsEditInProgress()) { return(true); } if (Contains(editKey) && (editOriginalKey == null || !editOriginalKey.Equals(editKey))) { DialogBox.Open( new LocEdString("Key already exists."), new LocEdString("Cannot add a key \"" + editKey + "\" to dictionary. Key already exists"), DialogBox.Type.OK); return(false); } else { if (IsTemporaryRow(editRowIdx)) { editRow.EditMode = false; editRow.Enabled = false; } else { rows[editRowIdx].EditMode = false; } if (editOriginalKey != null) // Editing { EditEntry(editOriginalKey, editKey, editValue); } else // Adding/Cloning { AddEntry(editKey, editValue); // Hidden dependency: Initialize must be called after all elements are // in the dictionary so we do it in two steps int newRowIdx = rows.Count; rows[newRowIdx] = CreateRow(); rows[newRowIdx].Initialize(this, guiContentLayout, newRowIdx, depth + 1); } editRow.SetIndex(rows.Count); editKey = CreateKey(); editValue = CreateValue(); editOriginalKey = null; editRowIdx = -1; ToggleFoldout(isExpanded); isModified = true; return(true); } }
private void OnEditorUpdate() { if (buildScheduledFrame == Time.FrameIdx) { BuildManager.Build(); ProgressBar.Hide(); EditorApplication.OpenFolder(BuildManager.OutputFolder); DialogBox.Open(new LocEdString("Build complete"), new LocEdString("Build complete"), DialogBox.Type.OK); } }
/// <summary> /// Attempts to open a project at the path currently entered in the project path input box. /// </summary> private void OpenProject() { string projectPath = projectInputBox.Value; if (EditorApplication.IsValidProject(projectPath)) { EditorSettings.AutoLoadLastProject = autoLoadToggle.Value; Close(); EditorApplication.LoadProject(projectPath); } else { // Remove invalid project from recent projects list RecentProject[] recentProjects = EditorSettings.RecentProjects; for (int i = 0; i < recentProjects.Length; i++) { if (PathEx.Compare(recentProjects[i].path, projectPath)) { RecentProject[] newRecentProjects = new RecentProject[recentProjects.Length - 1]; int idx = 0; for (int j = 0; j < recentProjects.Length; j++) { if (i == j) { continue; } newRecentProjects[idx] = recentProjects[j]; idx++; } EditorSettings.RecentProjects = newRecentProjects; EditorSettings.Save(); RefreshRecentProjects(); break; } } // Warn user LocString message = new LocEdString("Provided project path \"{0}\" doesn't contain a valid project."); message.SetParameter(0, projectPath); DialogBox.Open(new LocEdString("Error"), message, DialogBox.Type.OK); } }
/// <summary> /// Unloads the currently loaded project. Offers the user a chance to save the current scene if it is modified. /// Automatically saves all project data before unloading. /// </summary> private static void UnloadProject() { Action continueUnload = () => { Scene.Clear(); if (monitor != null) { monitor.Destroy(); monitor = null; } LibraryWindow window = EditorWindow.GetWindow <LibraryWindow>(); if (window != null) { window.Reset(); } SetSceneDirty(false); Internal_UnloadProject(); SetStatusProject(false); }; Action <DialogBox.ResultType> dialogCallback = (result) => { if (result == DialogBox.ResultType.Yes) { SaveScene(); } continueUnload(); }; if (IsSceneModified()) { DialogBox.Open("Warning", "You current scene has modifications. Do you wish to save them first?", DialogBox.Type.YesNoCancel, dialogCallback); } else { continueUnload(); } }
/// <summary> /// Loads a prefab as the current scene at the specified path. If current scene is modified the user is offered a /// chance to save it. /// </summary> /// <param name="path">Path to a valid prefab relative to the resource folder. If path is empty a brand new /// scene will be loaded.</param> public static void LoadScene(string path) { Action <string> continueLoad = (scenePath) => { if (string.IsNullOrEmpty(path)) { Scene.Clear(); lastLoadedScene = null; } else { lastLoadedScene = Scene.LoadAsync(path); } SetSceneDirty(false); ProjectSettings.LastOpenScene = scenePath; ProjectSettings.Save(); }; Action <DialogBox.ResultType> dialogCallback = (result) => { if (result == DialogBox.ResultType.Yes) { SaveScene(); continueLoad(path); } else if (result == DialogBox.ResultType.No) { continueLoad(path); } }; if (IsSceneModified()) { DialogBox.Open("Warning", "You current scene has modifications. Do you wish to save them first?", DialogBox.Type.YesNoCancel, dialogCallback); } else { continueLoad(path); } }
/// <summary> /// Triggered when the user clicks on the add button on the title bar. Adds a new empty element to the dictionary. /// </summary> protected virtual void OnAddButtonClicked() { if (IsEditInProgress()) { DialogBox.Open( new LocEdString("Edit in progress."), new LocEdString("You are editing the entry with key \"" + editKey + "\". You cannot add a row " + "before applying or discarding those changes. Do you wish to apply those changes first?"), DialogBox.Type.YesNoCancel, x => { switch (x) { case DialogBox.ResultType.Yes: if (ApplyChanges()) { StartAdd(); } break; case DialogBox.ResultType.No: DiscardChanges(); StartAdd(); break; } }); } else { if (!isExpanded) { ToggleFoldout(true); } StartAdd(); } }
/// <summary> /// Opens a dialog to allows the user to select a location where to save the current scene. /// </summary> public static void SaveSceneAs(Action onSuccess = null, Action onFailure = null) { string scenePath = ""; if (BrowseDialog.SaveFile(ProjectLibrary.ResourceFolder, "*.prefab", out scenePath)) { if (!PathEx.IsPartOf(scenePath, ProjectLibrary.ResourceFolder)) { DialogBox.Open("Error", "The location must be inside the Resources folder of the project.", DialogBox.Type.OK, x => { if (onFailure != null) { onFailure(); } }); } else { // TODO - If path points to an existing non-scene asset or folder I should delete it otherwise // Internal_SaveScene will silently fail. scenePath = Path.ChangeExtension(scenePath, ".prefab"); SaveScene(scenePath); } } else { // User canceled, so technically a success if (onSuccess != null) { onSuccess(); } } }
private void RebuildGUI() { GUI.Clear(); guiCurveEditor = null; guiFieldDisplay = null; if (selectedSO == null) { GUILabel warningLbl = new GUILabel(new LocEdString("Select an object to animate in the Hierarchy or Scene windows.")); GUILayoutY vertLayout = GUI.AddLayoutY(); vertLayout.AddFlexibleSpace(); GUILayoutX horzLayout = vertLayout.AddLayoutX(); vertLayout.AddFlexibleSpace(); horzLayout.AddFlexibleSpace(); horzLayout.AddElement(warningLbl); horzLayout.AddFlexibleSpace(); return; } // Top button row GUIContent playIcon = new GUIContent(EditorBuiltin.GetAnimationWindowIcon(AnimationWindowIcon.Play), new LocEdString("Play")); GUIContent recordIcon = new GUIContent(EditorBuiltin.GetAnimationWindowIcon(AnimationWindowIcon.Record), new LocEdString("Record")); GUIContent prevFrameIcon = new GUIContent(EditorBuiltin.GetAnimationWindowIcon(AnimationWindowIcon.FrameBack), new LocEdString("Previous frame")); GUIContent nextFrameIcon = new GUIContent(EditorBuiltin.GetAnimationWindowIcon(AnimationWindowIcon.FrameForward), new LocEdString("Next frame")); GUIContent addKeyframeIcon = new GUIContent(EditorBuiltin.GetAnimationWindowIcon(AnimationWindowIcon.AddKeyframe), new LocEdString("Add keyframe")); GUIContent addEventIcon = new GUIContent(EditorBuiltin.GetAnimationWindowIcon(AnimationWindowIcon.AddEvent), new LocEdString("Add event")); GUIContent optionsIcon = new GUIContent(EditorBuiltin.GetLibraryWindowIcon(LibraryWindowIcon.Options), new LocEdString("Options")); playButton = new GUIButton(playIcon); recordButton = new GUIButton(recordIcon); prevFrameButton = new GUIButton(prevFrameIcon); frameInputField = new GUIIntField(); nextFrameButton = new GUIButton(nextFrameIcon); addKeyframeButton = new GUIButton(addKeyframeIcon); addEventButton = new GUIButton(addEventIcon); optionsButton = new GUIButton(optionsIcon); playButton.OnClick += () => { // TODO // - Record current state of the scene object hierarchy // - Evaluate all curves manually and update them // - On end, restore original values of the scene object hierarchy }; recordButton.OnClick += () => { // TODO // - Every frame read back current values of all the current curve's properties and assign it to the current frame }; prevFrameButton.OnClick += () => { SetCurrentFrame(currentFrameIdx - 1); }; frameInputField.OnChanged += SetCurrentFrame; nextFrameButton.OnClick += () => { SetCurrentFrame(currentFrameIdx + 1); }; addKeyframeButton.OnClick += () => { guiCurveEditor.AddKeyFrameAtMarker(); }; addEventButton.OnClick += () => { guiCurveEditor.AddEventAtMarker(); }; optionsButton.OnClick += () => { Vector2I openPosition = ScreenToWindowPos(Input.PointerPosition); AnimationOptions dropDown = DropDownWindow.Open <AnimationOptions>(this, openPosition); dropDown.Initialize(this); }; // Property buttons addPropertyBtn = new GUIButton(new LocEdString("Add property")); delPropertyBtn = new GUIButton(new LocEdString("Delete selected")); addPropertyBtn.OnClick += () => { Action openPropertyWindow = () => { Vector2I windowPos = ScreenToWindowPos(Input.PointerPosition); FieldSelectionWindow fieldSelection = DropDownWindow.Open <FieldSelectionWindow>(this, windowPos); fieldSelection.OnFieldSelected += OnFieldAdded; }; if (clipInfo.clip == null) { LocEdString title = new LocEdString("Warning"); LocEdString message = new LocEdString("Selected object doesn't have an animation clip assigned. Would you like to create" + " a new animation clip?"); DialogBox.Open(title, message, DialogBox.Type.YesNoCancel, type => { if (type == DialogBox.ResultType.Yes) { string clipSavePath; if (BrowseDialog.SaveFile(ProjectLibrary.ResourceFolder, "*.asset", out clipSavePath)) { clipSavePath = Path.ChangeExtension(clipSavePath, ".asset"); AnimationClip newClip = new AnimationClip(); ProjectLibrary.Create(newClip, clipSavePath); LoadAnimClip(newClip); Animation animation = selectedSO.GetComponent <Animation>(); if (animation == null) { animation = selectedSO.AddComponent <Animation>(); } animation.DefaultClip = newClip; EditorApplication.SetSceneDirty(); openPropertyWindow(); } } }); } else { if (clipInfo.isImported) { LocEdString title = new LocEdString("Warning"); LocEdString message = new LocEdString("You cannot add/edit/remove curves from animation clips that" + " are imported from an external file."); DialogBox.Open(title, message, DialogBox.Type.OK); } else { openPropertyWindow(); } } }; delPropertyBtn.OnClick += () => { if (clipInfo.clip == null) { return; } if (clipInfo.isImported) { LocEdString title = new LocEdString("Warning"); LocEdString message = new LocEdString("You cannot add/edit/remove curves from animation clips that" + " are imported from an external file."); DialogBox.Open(title, message, DialogBox.Type.OK); } else { LocEdString title = new LocEdString("Warning"); LocEdString message = new LocEdString("Are you sure you want to remove all selected fields?"); DialogBox.Open(title, message, DialogBox.Type.YesNo, x => { if (x == DialogBox.ResultType.Yes) { RemoveSelectedFields(); } }); } }; GUIPanel mainPanel = GUI.AddPanel(); GUIPanel backgroundPanel = GUI.AddPanel(1); GUILayout mainLayout = mainPanel.AddLayoutY(); buttonLayout = mainLayout.AddLayoutX(); buttonLayout.AddSpace(5); buttonLayout.AddElement(playButton); buttonLayout.AddElement(recordButton); buttonLayout.AddSpace(5); buttonLayout.AddElement(prevFrameButton); buttonLayout.AddElement(frameInputField); buttonLayout.AddElement(nextFrameButton); buttonLayout.AddSpace(5); buttonLayout.AddElement(addKeyframeButton); buttonLayout.AddElement(addEventButton); buttonLayout.AddSpace(5); buttonLayout.AddElement(optionsButton); buttonLayout.AddFlexibleSpace(); buttonLayoutHeight = playButton.Bounds.height; GUITexture buttonBackground = new GUITexture(null, EditorStyles.HeaderBackground); buttonBackground.Bounds = new Rect2I(0, 0, Width, buttonLayoutHeight); backgroundPanel.AddElement(buttonBackground); GUILayout contentLayout = mainLayout.AddLayoutX(); GUILayout fieldDisplayLayout = contentLayout.AddLayoutY(GUIOption.FixedWidth(FIELD_DISPLAY_WIDTH)); guiFieldDisplay = new GUIAnimFieldDisplay(fieldDisplayLayout, FIELD_DISPLAY_WIDTH, Height - buttonLayoutHeight * 2, selectedSO); guiFieldDisplay.OnEntrySelected += OnFieldSelected; GUILayout bottomButtonLayout = fieldDisplayLayout.AddLayoutX(); bottomButtonLayout.AddElement(addPropertyBtn); bottomButtonLayout.AddElement(delPropertyBtn); horzScrollBar = new GUIResizeableScrollBarH(); horzScrollBar.OnScrollOrResize += OnHorzScrollOrResize; vertScrollBar = new GUIResizeableScrollBarV(); vertScrollBar.OnScrollOrResize += OnVertScrollOrResize; GUITexture separator = new GUITexture(null, EditorStyles.Separator, GUIOption.FixedWidth(3)); contentLayout.AddElement(separator); GUILayout curveLayout = contentLayout.AddLayoutY(); GUILayout curveLayoutHorz = curveLayout.AddLayoutX(); GUILayout horzScrollBarLayout = curveLayout.AddLayoutX(); horzScrollBarLayout.AddElement(horzScrollBar); horzScrollBarLayout.AddFlexibleSpace(); editorPanel = curveLayoutHorz.AddPanel(); curveLayoutHorz.AddElement(vertScrollBar); curveLayoutHorz.AddFlexibleSpace(); scrollBarHeight = horzScrollBar.Bounds.height; scrollBarWidth = vertScrollBar.Bounds.width; Vector2I curveEditorSize = GetCurveEditorSize(); guiCurveEditor = new GUICurveEditor(this, editorPanel, curveEditorSize.x, curveEditorSize.y); guiCurveEditor.OnFrameSelected += OnFrameSelected; guiCurveEditor.OnEventAdded += OnEventsChanged; guiCurveEditor.OnEventModified += EditorApplication.SetProjectDirty; guiCurveEditor.OnEventDeleted += OnEventsChanged; guiCurveEditor.OnCurveModified += EditorApplication.SetProjectDirty; guiCurveEditor.Redraw(); horzScrollBar.SetWidth(curveEditorSize.x); vertScrollBar.SetHeight(curveEditorSize.y); UpdateScrollBarSize(); }