private void OnEditorUpdate() { if (HasFocus) { if (!Input.IsPointerButtonHeld(PointerButton.Right)) { if (VirtualInput.IsButtonDown(EditorApplication.DuplicateKey)) { DuplicateSelection(); } else if (VirtualInput.IsButtonDown(EditorApplication.DeleteKey)) { DeleteSelection(); } else if (VirtualInput.IsButtonDown(toggleProfilerOverlayKey)) { EditorSettings.SetBool(ProfilerOverlayActiveKey, !EditorSettings.GetBool(ProfilerOverlayActiveKey)); } else if (VirtualInput.IsButtonDown(viewToolKey)) { EditorApplication.ActiveSceneTool = SceneViewTool.View; } else if (VirtualInput.IsButtonDown(moveToolKey)) { EditorApplication.ActiveSceneTool = SceneViewTool.Move; } else if (VirtualInput.IsButtonDown(rotateToolKey)) { EditorApplication.ActiveSceneTool = SceneViewTool.Rotate; } else if (VirtualInput.IsButtonDown(scaleToolKey)) { EditorApplication.ActiveSceneTool = SceneViewTool.Scale; } } } // Refresh GUI buttons if needed (in case someones changes the values from script) if (editorSettingsHash != EditorSettings.Hash) { UpdateButtonStates(); UpdateProfilerOverlay(); editorSettingsHash = EditorSettings.Hash; } // Update scene view handles and selection sceneGizmos.Draw(); sceneGrid.Draw(); bool handleActive = sceneHandles.IsActive() || sceneAxesGUI.IsActive(); Vector2I scenePos; bool inBounds = ScreenToScenePos(Input.PointerPosition, out scenePos); bool dragResult = false; if (Input.IsPointerButtonUp(PointerButton.Left)) { dragResult = EndDragSelection(); if (sceneHandles.IsActive()) { sceneHandles.ClearSelection(); } if (sceneAxesGUI.IsActive()) { sceneAxesGUI.ClearSelection(); } } else if (Input.IsPointerButtonDown(PointerButton.Left)) { mouseDownPosition = scenePos; } bool draggedOver = DragDrop.DragInProgress || DragDrop.DropInProgress; draggedOver &= IsPointerHovering && inBounds && DragDrop.Type == DragDropType.Resource; if (draggedOver) { if (DragDrop.DropInProgress) { dragActive = false; if (draggedSO != null) { Selection.SceneObject = draggedSO; EditorApplication.SetSceneDirty(); } draggedSO = null; } else { if (!dragActive) { dragActive = true; ResourceDragDropData dragData = (ResourceDragDropData)DragDrop.Data; string[] draggedPaths = dragData.Paths; for (int i = 0; i < draggedPaths.Length; i++) { ResourceMeta meta = ProjectLibrary.GetMeta(draggedPaths[i]); if (meta != null) { if (meta.ResType == ResourceType.Mesh) { if (!string.IsNullOrEmpty(draggedPaths[i])) { string meshName = Path.GetFileNameWithoutExtension(draggedPaths[i]); draggedSO = UndoRedo.CreateSO(meshName, "Created a new Renderable \"" + meshName + "\""); Mesh mesh = ProjectLibrary.Load <Mesh>(draggedPaths[i]); Renderable renderable = draggedSO.AddComponent <Renderable>(); renderable.Mesh = mesh; if (mesh != null) { draggedSOOffset = mesh.Bounds.Box.Center; } else { draggedSOOffset = Vector3.Zero; } } break; } else if (meta.ResType == ResourceType.Prefab) { if (!string.IsNullOrEmpty(draggedPaths[i])) { Prefab prefab = ProjectLibrary.Load <Prefab>(draggedPaths[i]); draggedSO = UndoRedo.Instantiate(prefab, "Instantiating " + prefab.Name); if (draggedSO != null) { AABox draggedObjBounds = EditorUtility.CalculateBounds(draggedSO); draggedSOOffset = draggedObjBounds.Center; } else { draggedSOOffset = Vector3.Zero; } } break; } } } } if (draggedSO != null) { if (Input.IsButtonHeld(ButtonCode.Space)) { SnapData snapData; sceneSelection.Snap(scenePos, out snapData, new SceneObject[] { draggedSO }); Quaternion q = Quaternion.FromToRotation(Vector3.YAxis, snapData.normal); draggedSO.Position = snapData.position; draggedSO.Rotation = q; } else { Ray worldRay = camera.ScreenPointToRay(scenePos); draggedSO.Position = worldRay * DefaultPlacementDepth - draggedSOOffset; } } } return; } else { if (dragActive) { dragActive = false; if (draggedSO != null) { draggedSO.Destroy(); draggedSO = null; } } } if (HasContentFocus || IsPointerHovering) { cameraController.EnableInput(true); if (inBounds && HasContentFocus) { if (Input.IsPointerButtonDown(PointerButton.Left)) { Rect2I sceneAxesGUIBounds = new Rect2I(Width - HandleAxesGUISize - HandleAxesGUIPaddingX, HandleAxesGUIPaddingY, HandleAxesGUISize, HandleAxesGUISize); if (sceneAxesGUIBounds.Contains(scenePos)) { sceneAxesGUI.TrySelect(scenePos); } else { sceneHandles.TrySelect(scenePos); } } else if (Input.IsPointerButtonHeld(PointerButton.Left) && !handleActive && !dragActive && draggedSO == null && scenePos != mouseDownPosition) { if (isDraggingSelection) { UpdateDragSelection(scenePos); } else { StartDragSelection(scenePos); } } else if (Input.IsPointerButtonUp(PointerButton.Left)) { if (!handleActive && !dragActive && !dragResult) { bool ctrlHeld = Input.IsButtonHeld(ButtonCode.LeftControl) || Input.IsButtonHeld(ButtonCode.RightControl); sceneSelection.PickObject(scenePos, ctrlHeld, new SceneObject[] { draggedSO }); } } } } else { cameraController.EnableInput(false); } SceneHandles.BeginInput(); sceneHandles.UpdateInput(scenePos, Input.PointerDelta); sceneHandles.Draw(); sceneAxesGUI.UpdateInput(scenePos); sceneAxesGUI.Draw(); SceneHandles.EndInput(); sceneSelection.Draw(); UpdateGridMode(); if (VirtualInput.IsButtonDown(frameKey)) { cameraController.FrameSelected(); } }
/// <summary> /// Updates contents of the scene object specific fields (name, position, rotation, etc.) /// </summary> /// <param name="forceUpdate">If true, the GUI elements will be updated regardless of whether a change was /// detected or not.</param> private void RefreshSceneObjectFields(bool forceUpdate) { if (activeSO == null) { return; } soNameInput.Text = activeSO.Name; soActiveToggle.Value = activeSO.Active; soMobility.Value = (ulong)activeSO.Mobility; SceneObject prefabParent = PrefabUtility.GetPrefabParent(activeSO); // Ignore prefab parent if scene root, we only care for non-root prefab instances bool hasPrefab = prefabParent != null && prefabParent.Parent != null; if (soHasPrefab != hasPrefab || forceUpdate) { int numChildren = soPrefabLayout.ChildCount; for (int i = 0; i < numChildren; i++) { soPrefabLayout.GetChild(0).Destroy(); } GUILabel prefabLabel = new GUILabel(new LocEdString("Prefab"), GUIOption.FixedWidth(50)); soPrefabLayout.AddElement(prefabLabel); if (hasPrefab) { GUIButton btnApplyPrefab = new GUIButton(new LocEdString("Apply"), GUIOption.FixedWidth(60)); GUIButton btnRevertPrefab = new GUIButton(new LocEdString("Revert"), GUIOption.FixedWidth(60)); GUIButton btnBreakPrefab = new GUIButton(new LocEdString("Break"), GUIOption.FixedWidth(60)); btnApplyPrefab.OnClick += () => { PrefabUtility.ApplyPrefab(activeSO); }; btnRevertPrefab.OnClick += () => { UndoRedo.RecordSO(activeSO, true, "Reverting \"" + activeSO.Name + "\" to prefab."); PrefabUtility.RevertPrefab(activeSO); EditorApplication.SetSceneDirty(); }; btnBreakPrefab.OnClick += () => { UndoRedo.BreakPrefab(activeSO, "Breaking prefab link for " + activeSO.Name); EditorApplication.SetSceneDirty(); }; soPrefabLayout.AddElement(btnApplyPrefab); soPrefabLayout.AddElement(btnRevertPrefab); soPrefabLayout.AddElement(btnBreakPrefab); } else { GUILabel noPrefabLabel = new GUILabel("None"); soPrefabLayout.AddElement(noPrefabLabel); } soHasPrefab = hasPrefab; } Vector3 position; Vector3 angles; if (EditorApplication.ActiveCoordinateMode == HandleCoordinateMode.World) { position = activeSO.Position; angles = activeSO.Rotation.ToEuler(); } else { position = activeSO.LocalPosition; angles = activeSO.LocalRotation.ToEuler(); } Vector3 scale = activeSO.LocalScale; if (!soPosX.HasInputFocus) { soPosX.Value = position.x; } if (!soPosY.HasInputFocus) { soPosY.Value = position.y; } if (!soPosZ.HasInputFocus) { soPosZ.Value = position.z; } if (!soRotX.HasInputFocus) { soRotX.Value = angles.x; } if (!soRotY.HasInputFocus) { soRotY.Value = angles.y; } if (!soRotZ.HasInputFocus) { soRotZ.Value = angles.z; } if (!soScaleX.HasInputFocus) { soScaleX.Value = scale.x; } if (!soScaleY.HasInputFocus) { soScaleY.Value = scale.y; } if (!soScaleZ.HasInputFocus) { soScaleZ.Value = scale.z; } }
private void OnEditorUpdate() { if (currentType == InspectorType.SceneObject) { Component[] allComponents = activeSO.GetComponents(); bool requiresRebuild = allComponents.Length != inspectorComponents.Count; if (!requiresRebuild) { for (int i = 0; i < inspectorComponents.Count; i++) { if (inspectorComponents[i].instanceId != allComponents[i].InstanceId) { requiresRebuild = true; break; } } } if (requiresRebuild) { SceneObject so = activeSO; Clear(); SetObjectToInspect(so); } else { RefreshSceneObjectFields(false); InspectableState componentModifyState = InspectableState.NotModified; for (int i = 0; i < inspectorComponents.Count; i++) { componentModifyState |= inspectorComponents[i].inspector.Refresh(); } if (componentModifyState.HasFlag(InspectableState.ModifyInProgress)) { EditorApplication.SetSceneDirty(); } modifyState |= componentModifyState; } } else if (currentType == InspectorType.Resource) { inspectorResource.inspector.Refresh(); } // Detect drag and drop bool isValidDrag = false; if (activeSO != null) { if ((DragDrop.DragInProgress || DragDrop.DropInProgress) && DragDrop.Type == DragDropType.Resource) { Vector2I windowPos = ScreenToWindowPos(Input.PointerPosition); Vector2I scrollPos = windowPos; Rect2I contentBounds = inspectorLayout.Bounds; scrollPos.x -= contentBounds.x; scrollPos.y -= contentBounds.y; bool isInBounds = false; Rect2I dropArea = new Rect2I(); foreach (var bounds in dropAreas) { if (bounds.Contains(scrollPos)) { isInBounds = true; dropArea = bounds; break; } } Type draggedComponentType = null; if (isInBounds) { ResourceDragDropData dragData = DragDrop.Data as ResourceDragDropData; if (dragData != null) { foreach (var resPath in dragData.Paths) { ResourceMeta meta = ProjectLibrary.GetMeta(resPath); if (meta != null) { if (meta.ResType == ResourceType.ScriptCode) { ScriptCode scriptFile = ProjectLibrary.Load <ScriptCode>(resPath); if (scriptFile != null) { Type[] scriptTypes = scriptFile.Types; foreach (var type in scriptTypes) { if (type.IsSubclassOf(typeof(Component))) { draggedComponentType = type; isValidDrag = true; break; } } if (draggedComponentType != null) { break; } } } } } } } if (isValidDrag) { scrollAreaHighlight.Bounds = dropArea; if (DragDrop.DropInProgress) { activeSO.AddComponent(draggedComponentType); modifyState = InspectableState.Modified; EditorApplication.SetSceneDirty(); } } } } if (scrollAreaHighlight != null) { scrollAreaHighlight.Active = isValidDrag; } }
private void OnEditorUpdate() { if (HasFocus) { if (!Input.IsPointerButtonHeld(PointerButton.Right)) { if (VirtualInput.IsButtonDown(toggleProfilerOverlayKey)) EditorSettings.SetBool(ProfilerOverlayActiveKey, !EditorSettings.GetBool(ProfilerOverlayActiveKey)); if (VirtualInput.IsButtonDown(viewToolKey)) EditorApplication.ActiveSceneTool = SceneViewTool.View; if (VirtualInput.IsButtonDown(moveToolKey)) EditorApplication.ActiveSceneTool = SceneViewTool.Move; if (VirtualInput.IsButtonDown(rotateToolKey)) EditorApplication.ActiveSceneTool = SceneViewTool.Rotate; if (VirtualInput.IsButtonDown(scaleToolKey)) EditorApplication.ActiveSceneTool = SceneViewTool.Scale; if (VirtualInput.IsButtonDown(duplicateKey)) { SceneObject[] selectedObjects = Selection.SceneObjects; CleanDuplicates(ref selectedObjects); if (selectedObjects.Length > 0) { String message; if (selectedObjects.Length == 1) message = "Duplicated " + selectedObjects[0].Name; else message = "Duplicated " + selectedObjects.Length + " elements"; UndoRedo.CloneSO(selectedObjects, message); EditorApplication.SetSceneDirty(); } } if (VirtualInput.IsButtonDown(deleteKey)) { SceneObject[] selectedObjects = Selection.SceneObjects; CleanDuplicates(ref selectedObjects); if (selectedObjects.Length > 0) { foreach (var so in selectedObjects) { string message = "Deleted " + so.Name; UndoRedo.DeleteSO(so, message); } EditorApplication.SetSceneDirty(); } } } } // Refresh GUI buttons if needed (in case someones changes the values from script) if (editorSettingsHash != EditorSettings.Hash) { UpdateButtonStates(); UpdateProfilerOverlay(); editorSettingsHash = EditorSettings.Hash; } // Update scene view handles and selection sceneGizmos.Draw(); sceneGrid.Draw(); bool handleActive = false; if (Input.IsPointerButtonUp(PointerButton.Left)) { if (sceneHandles.IsActive()) { sceneHandles.ClearSelection(); handleActive = true; } if (sceneAxesGUI.IsActive()) { sceneAxesGUI.ClearSelection(); handleActive = true; } } Vector2I scenePos; bool inBounds = ScreenToScenePos(Input.PointerPosition, out scenePos); bool draggedOver = DragDrop.DragInProgress || DragDrop.DropInProgress; draggedOver &= IsPointerHovering && inBounds && DragDrop.Type == DragDropType.Resource; if (draggedOver) { if (DragDrop.DropInProgress) { dragActive = false; if (draggedSO != null) { Selection.SceneObject = draggedSO; EditorApplication.SetSceneDirty(); } draggedSO = null; } else { if (!dragActive) { dragActive = true; ResourceDragDropData dragData = (ResourceDragDropData)DragDrop.Data; string[] draggedPaths = dragData.Paths; for (int i = 0; i < draggedPaths.Length; i++) { LibraryEntry entry = ProjectLibrary.GetEntry(draggedPaths[i]); if (entry != null && entry.Type == LibraryEntryType.File) { FileEntry fileEntry = (FileEntry) entry; if (fileEntry.ResType == ResourceType.Mesh) { if (!string.IsNullOrEmpty(draggedPaths[i])) { string meshName = Path.GetFileNameWithoutExtension(draggedPaths[i]); draggedSO = UndoRedo.CreateSO(meshName, "Created a new Renderable \"" + meshName + "\""); Mesh mesh = ProjectLibrary.Load<Mesh>(draggedPaths[i]); Renderable renderable = draggedSO.AddComponent<Renderable>(); renderable.Mesh = mesh; } break; } else if (fileEntry.ResType == ResourceType.Prefab) { if (!string.IsNullOrEmpty(draggedPaths[i])) { Prefab prefab = ProjectLibrary.Load<Prefab>(draggedPaths[i]); draggedSO = UndoRedo.Instantiate(prefab, "Instantiating " + prefab.Name); } break; } } } } if (draggedSO != null) { Ray worldRay = camera.ScreenToWorldRay(scenePos); draggedSO.Position = worldRay*DefaultPlacementDepth; } } return; } else { if (dragActive) { dragActive = false; if (draggedSO != null) { draggedSO.Destroy(); draggedSO = null; } } } if (HasFocus) { cameraController.EnableInput(true); if (inBounds) { if (Input.IsPointerButtonDown(PointerButton.Left)) { Rect2I sceneAxesGUIBounds = new Rect2I(Width - HandleAxesGUISize - HandleAxesGUIPaddingX, HandleAxesGUIPaddingY, HandleAxesGUISize, HandleAxesGUISize); if (sceneAxesGUIBounds.Contains(scenePos)) sceneAxesGUI.TrySelect(scenePos); else sceneHandles.TrySelect(scenePos); } else if (Input.IsPointerButtonUp(PointerButton.Left)) { if (!handleActive) { bool ctrlHeld = Input.IsButtonHeld(ButtonCode.LeftControl) || Input.IsButtonHeld(ButtonCode.RightControl); sceneSelection.PickObject(scenePos, ctrlHeld); } } } } else cameraController.EnableInput(false); SceneHandles.BeginInput(); sceneHandles.UpdateInput(scenePos, Input.PointerDelta); sceneHandles.Draw(); sceneAxesGUI.UpdateInput(scenePos); sceneAxesGUI.Draw(); SceneHandles.EndInput(); sceneSelection.Draw(); UpdateGridMode(); if (VirtualInput.IsButtonDown(frameKey)) cameraController.FrameSelected(); }
/// <summary> /// Triggered by the runtime when the scene is modified from the native scene tree view. /// </summary> private void Internal_DoOnModified() { EditorApplication.SetSceneDirty(); }
/// <inheritdoc/> protected internal override void PostInput() { if (activeHandle != null) { if (activeHandle.IsDragged()) { if (!isDragged) { isDragged = true; SceneObject[] selectedSceneObjects = Selection.SceneObjects; activeSelection = new HandledObject[selectedSceneObjects.Length]; for (int i = 0; i < selectedSceneObjects.Length; i++) { activeSelection[i] = new HandledObject(selectedSceneObjects[i]); } initialHandlePosition = activeHandle.Position; initialHandleRotation = activeHandle.Rotation; } } else { isDragged = false; activeSelection = null; } activeHandle.PostInput(); if (activeHandle.IsDragged()) { switch (activeHandleType) { case SceneViewTool.Move: MoveHandle moveHandle = (MoveHandle)activeHandle; foreach (var selectedObj in activeSelection) { selectedObj.so.LocalPosition = selectedObj.initialPosition + moveHandle.Delta; } break; case SceneViewTool.Rotate: { RotateHandle rotateHandle = (RotateHandle)activeHandle; // Make sure we transform relative to the handle position SceneObject temporarySO = new SceneObject("Temp"); temporarySO.Position = initialHandlePosition; temporarySO.LocalRotation = initialHandleRotation; SceneObject[] originalParents = new SceneObject[activeSelection.Length]; for (int i = 0; i < activeSelection.Length; i++) { originalParents[i] = activeSelection[i].so.Parent; activeSelection[i].so.LocalPosition = activeSelection[i].initialPosition; activeSelection[i].so.LocalRotation = activeSelection[i].initialRotation; activeSelection[i].so.Parent = temporarySO; } temporarySO.LocalRotation *= rotateHandle.Delta; for (int i = 0; i < activeSelection.Length; i++) { activeSelection[i].so.Parent = originalParents[i]; } temporarySO.Destroy(); } break; case SceneViewTool.Scale: { ScaleHandle scaleHandle = (ScaleHandle)activeHandle; // Make sure we transform relative to the handle position SceneObject temporarySO = new SceneObject("Temp"); temporarySO.Position = activeHandle.Position; SceneObject[] originalParents = new SceneObject[activeSelection.Length]; for (int i = 0; i < activeSelection.Length; i++) { originalParents[i] = activeSelection[i].so.Parent; activeSelection[i].so.LocalPosition = activeSelection[i].initialPosition; activeSelection[i].so.LocalRotation = activeSelection[i].initialRotation; activeSelection[i].so.LocalScale = activeSelection[i].initialScale; activeSelection[i].so.Parent = temporarySO; } temporarySO.LocalScale += scaleHandle.Delta; for (int i = 0; i < activeSelection.Length; i++) { activeSelection[i].so.Parent = originalParents[i]; } temporarySO.Destroy(); } break; } EditorApplication.SetSceneDirty(); } } else { isDragged = false; activeSelection = null; } }
/// <summary> /// Updates contents of the scene object specific fields (name, position, rotation, etc.) /// </summary> /// <param name="forceUpdate">If true, the GUI elements will be updated regardless of whether a change was /// detected or not.</param> private void RefreshSceneObjectFields(bool forceUpdate) { if (activeSO == null) { return; } soNameInput.Text = activeSO.Name; soActiveToggle.Value = activeSO.Active; soMobility.Value = (ulong)activeSO.Mobility; SceneObject prefabParent = PrefabUtility.GetPrefabParent(activeSO); // Ignore prefab parent if scene root, we only care for non-root prefab instances bool hasPrefab = prefabParent != null && prefabParent.Parent != null; if (soHasPrefab != hasPrefab || forceUpdate) { int numChildren = soPrefabLayout.ChildCount; for (int i = 0; i < numChildren; i++) { soPrefabLayout.GetChild(0).Destroy(); } GUILabel prefabLabel = new GUILabel(new LocEdString("Prefab"), GUIOption.FixedWidth(50)); soPrefabLayout.AddElement(prefabLabel); if (hasPrefab) { GUIButton btnApplyPrefab = new GUIButton(new LocEdString("Apply"), GUIOption.FixedWidth(60)); GUIButton btnRevertPrefab = new GUIButton(new LocEdString("Revert"), GUIOption.FixedWidth(60)); GUIButton btnBreakPrefab = new GUIButton(new LocEdString("Break"), GUIOption.FixedWidth(60)); btnApplyPrefab.OnClick += () => { PrefabUtility.ApplyPrefab(activeSO); }; btnRevertPrefab.OnClick += () => { UndoRedo.RecordSO(activeSO, true, "Reverting \"" + activeSO.Name + "\" to prefab."); PrefabUtility.RevertPrefab(activeSO); EditorApplication.SetSceneDirty(); }; btnBreakPrefab.OnClick += () => { UndoRedo.BreakPrefab(activeSO, "Breaking prefab link for " + activeSO.Name); EditorApplication.SetSceneDirty(); }; soPrefabLayout.AddElement(btnApplyPrefab); soPrefabLayout.AddElement(btnRevertPrefab); soPrefabLayout.AddElement(btnBreakPrefab); } else { GUILabel noPrefabLabel = new GUILabel("None"); soPrefabLayout.AddElement(noPrefabLabel); } soHasPrefab = hasPrefab; } Vector3 position; Quaternion rotation; if (EditorApplication.ActiveCoordinateMode == HandleCoordinateMode.World) { position = activeSO.Position; rotation = activeSO.Rotation; } else { position = activeSO.LocalPosition; rotation = activeSO.LocalRotation; } Vector3 scale = activeSO.LocalScale; if (!soPos.HasInputFocus) { soPos.Value = position; } // Avoid updating the rotation unless actually changed externally, since switching back and forth between // quaternion and euler angles can cause weird behavior if (!soRot.HasInputFocus && rotation != lastRotation) { soRot.Value = rotation.ToEuler(); lastRotation = rotation; } if (!soScale.HasInputFocus) { soScale.Value = scale; } }
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(); }