Exemple #1
0
        /// <summary>
        /// Opens the event edit window for the specified event.
        /// </summary>
        /// <param name="eventIdx">Event index to open the edit window for.</param>
        private void StartEventEdit(int eventIdx)
        {
            AnimationEvent animEvent = events[eventIdx].animEvent;

            Vector2I position = new Vector2I();

            position.x = guiEvents.GetOffset(animEvent.Time);
            position.y = EVENTS_HEIGHT / 2;

            Rect2I   eventBounds = GUIUtility.CalculateBounds(eventsPanel, window.GUI);
            Vector2I windowPos   = position + new Vector2I(eventBounds.x, eventBounds.y);

            SceneObject so = window.SelectedSO;

            Component[] components     = so.GetComponents();
            string[]    componentNames = new string[components.Length];
            for (int i = 0; i < components.Length; i++)
            {
                componentNames[i] = components[i].GetType().Name;
            }

            EventEditWindow editWindow = DropDownWindow.Open <EventEditWindow>(window, windowPos);

            editWindow.Initialize(animEvent, componentNames, () =>
            {
                UpdateEventsGUI();
                OnEventModified?.Invoke();
            });
        }
        /// <summary>
        /// Converts screen coordinates in coordinates relative to the panel containing the key editor control.
        /// </summary>
        /// <param name="screenPos">Coordinates in screen space.</param>
        /// <returns>Coordinates relative to the key editor control.</returns>
        private Vector2I ScreenToKeyEditorPos(Vector2I screenPos)
        {
            Vector2I windowPos = ScreenToWindowPos(screenPos);

            Rect2I elementBounds = GUIUtility.CalculateBounds(editorPanel, GUI);

            return(windowPos - new Vector2I(elementBounds.x, elementBounds.y));
        }
Exemple #3
0
        /// <summary>
        /// Creates the scene camera and updates the render texture. Should be called at least once before using the
        /// scene view. Should be called whenever the window is resized.
        /// </summary>
        /// <param name="width">Width of the scene render target, in pixels.</param>
        /// <param name="height">Height of the scene render target, in pixels.</param>
        private void UpdateRenderTexture(int width, int height)
        {
            width  = MathEx.Max(20, width);
            height = MathEx.Max(20, height);

            // Note: Depth buffer is required because ScenePicking uses it
            renderTexture          = new RenderTexture2D(PixelFormat.R8G8B8A8, width, height, 1, false, true);
            renderTexture.Priority = 1;

            if (camera == null)
            {
                SceneObject sceneCameraSO = new SceneObject("SceneCamera", true);
                camera              = sceneCameraSO.AddComponent <Camera>();
                camera.Target       = renderTexture;
                camera.ViewportRect = new Rect2(0.0f, 0.0f, 1.0f, 1.0f);

                sceneCameraSO.Position = new Vector3(0, 0.5f, 1);
                sceneCameraSO.LookAt(new Vector3(0, 0.5f, 0));

                camera.Priority      = 2;
                camera.NearClipPlane = 0.05f;
                camera.FarClipPlane  = 2500.0f;
                camera.ClearColor    = ClearColor;
                camera.Layers        = UInt64.MaxValue & ~SceneAxesHandle.LAYER; // Don't draw scene axes in this camera

                cameraController = sceneCameraSO.AddComponent <SceneCamera>();

                renderTextureGUI = new GUIRenderTexture(renderTexture);
                rtPanel.AddElement(renderTextureGUI);

                sceneGrid      = new SceneGrid(camera);
                sceneSelection = new SceneSelection(camera);
                sceneGizmos    = new SceneGizmos(camera);
                sceneHandles   = new SceneHandles(this, camera);
            }
            else
            {
                camera.Target = renderTexture;
                renderTextureGUI.RenderTexture = renderTexture;
            }

            Rect2I rtBounds = new Rect2I(0, 0, width, height);

            renderTextureGUI.Bounds = rtBounds;
            focusCatcher.Bounds     = GUIUtility.CalculateBounds(rtPanel, GUI);

            sceneAxesGUI.SetPosition(width - HandleAxesGUISize - HandleAxesGUIPaddingX, HandleAxesGUIPaddingY);

            // TODO - Consider only doing the resize once user stops resizing the widget in order to reduce constant
            // render target destroy/create cycle for every single pixel.

            camera.AspectRatio = width / (float)height;

            if (profilerCamera != null)
            {
                profilerCamera.Target = renderTexture;
            }
        }
Exemple #4
0
        /// <summary>
        /// Creates the scene camera and updates the render texture. Should be called at least once before using the
        /// scene view. Should be called whenever the window is resized.
        /// </summary>
        /// <param name="width">Width of the scene render target, in pixels.</param>
        /// <param name="height">Height of the scene render target, in pixels.</param>
        private void UpdateRenderTexture(int width, int height)
        {
            width  = MathEx.Max(20, width);
            height = MathEx.Max(20, height);

            // Note: Depth buffer and readable flags are required because ScenePicking uses it
            Texture colorTex = Texture.Create2D((uint)width, (uint)height, PixelFormat.RGBA8, TextureUsage.Render | TextureUsage.CPUReadable);
            Texture depthTex = Texture.Create2D((uint)width, (uint)height, PixelFormat.D32_S8X24, TextureUsage.DepthStencil | TextureUsage.CPUReadable);

            renderTexture          = new RenderTexture(colorTex, depthTex);
            renderTexture.Priority = 1;

            if (camera == null)
            {
                SceneObject sceneCameraSO = new SceneObject("SceneCamera", true);
                camera = sceneCameraSO.AddComponent <Camera>();
                camera.Viewport.Target = renderTexture;
                camera.Viewport.Area   = new Rect2(0.0f, 0.0f, 1.0f, 1.0f);

                sceneCameraSO.Position = new Vector3(0, 0.5f, 1);
                sceneCameraSO.LookAt(new Vector3(0, 0.5f, 0));

                camera.Priority            = 2;
                camera.Viewport.ClearColor = ClearColor;
                camera.Layers = UInt64.MaxValue & ~SceneAxesHandle.LAYER; // Don't draw scene axes in this camera

                cameraController = sceneCameraSO.AddComponent <SceneCamera>();

                cameraController.Initialize();

                renderTextureGUI = new GUIRenderTexture(renderTexture);
                rtPanel.AddElement(renderTextureGUI);

                sceneGrid      = new SceneGrid(camera);
                sceneSelection = new SceneSelection(camera);
                sceneGizmos    = new SceneGizmos(camera);
                sceneHandles   = new SceneHandles(this, camera);
            }
            else
            {
                camera.Viewport.Target         = renderTexture;
                renderTextureGUI.RenderTexture = renderTexture;
            }

            Rect2I rtBounds = new Rect2I(0, 0, width, height);

            renderTextureGUI.Bounds = rtBounds;
            focusCatcher.Bounds     = GUIUtility.CalculateBounds(rtPanel, GUI);

            sceneAxesGUI.SetPosition(width - HandleAxesGUISize - HandleAxesGUIPaddingX, HandleAxesGUIPaddingY);

            // TODO - Consider only doing the resize once user stops resizing the widget in order to reduce constant
            // render target destroy/create cycle for every single pixel.

            camera.AspectRatio = width / (float)height;
        }
Exemple #5
0
        /// <summary>
        /// Converts coordinates in window space (relative to the parent window origin) into coordinates in curve space.
        /// </summary>
        /// <param name="windowPos">Coordinates relative to parent editor window, in pixels.</param>
        /// <param name="curveCoord">Curve coordinates within the range as specified by <see cref="Range"/>. Only
        ///                          valid when function returns true.</param>
        /// <returns>True if the coordinates are within the curve area, false otherwise.</returns>
        public bool WindowToCurveSpace(Vector2I windowPos, out Vector2 curveCoord)
        {
            Rect2I   elementBounds = GUIUtility.CalculateBounds(gui, window.GUI);
            Vector2I pointerPos    = windowPos - new Vector2I(elementBounds.x, elementBounds.y);

            Rect2I   drawingBounds = drawingPanel.Bounds;
            Vector2I drawingPos    = pointerPos - new Vector2I(drawingBounds.x, drawingBounds.y);

            return(guiCurveDrawing.PixelToCurveSpace(drawingPos, out curveCoord));
        }
Exemple #6
0
        private void OnCameraOptionsClicked()
        {
            Vector2I openPosition;
            Rect2I   buttonBounds = GUIUtility.CalculateBounds(cameraOptionsButton, GUI);

            openPosition.x = buttonBounds.x + buttonBounds.width / 2;
            openPosition.y = buttonBounds.y + buttonBounds.height / 2;

            SceneCameraOptionsDropdown cameraOptionsDropdown = DropDownWindow.Open <SceneCameraOptionsDropdown>(GUI, openPosition);

            cameraOptionsDropdown.Initialize(this);
        }
        /// <summary>
        /// Triggered when the user clicks on the create button on the title bar. Creates a brand new object with default
        /// values in the place of the current array.
        /// </summary>
        private void OnCreateButtonClicked()
        {
            if (createContextMenu == null)
            {
                return;
            }

            Rect2I   bounds   = GUIUtility.CalculateBounds(guiCreateBtn, guiInternalTitleLayout);
            Vector2I position = new Vector2I(bounds.x + bounds.width / 2, bounds.y + bounds.height / 2);

            createContextMenu.Open(position, guiInternalTitleLayout);
        }
Exemple #8
0
        /// <summary>
        /// Triggered when the user clicks on the create button on the title bar. Creates a brand new object with default
        /// values in the place of the current array.
        /// </summary>
        private void OnCreateButtonClicked()
        {
            if (createContextMenu == null)
            {
                if (instantiableTypes.Length > 0)
                {
                    property.SetValue(Activator.CreateInstance(instantiableTypes[0]));
                }
            }
            else
            {
                Rect2I   bounds   = GUIUtility.CalculateBounds(guiCreateBtn, guiInternalTitleLayout);
                Vector2I position = new Vector2I(bounds.x + bounds.width / 2, bounds.y + bounds.height / 2);

                createContextMenu.Open(position, guiInternalTitleLayout);
            }
        }
Exemple #9
0
        /// <summary>
        /// Converts screen coordinates into coordinates relative to the scene view render texture.
        /// </summary>
        /// <param name="screenPos">Coordinates relative to the screen.</param>
        /// <param name="scenePos">Output coordinates relative to the scene view texture.</param>
        /// <returns>True if the coordinates are within the scene view texture, false otherwise.</returns>
        private bool ScreenToScenePos(Vector2I screenPos, out Vector2I scenePos)
        {
            scenePos = screenPos;
            Vector2I windowPos = ScreenToWindowPos(screenPos);

            Rect2I bounds = GUIUtility.CalculateBounds(renderTextureGUI, GUI);

            if (bounds.Contains(windowPos))
            {
                scenePos.x = windowPos.x - bounds.x;
                scenePos.y = windowPos.y - bounds.y;

                return(true);
            }

            return(false);
        }
Exemple #10
0
        /// <summary>
        /// Opens the edit window for the currently selected keyframe.
        /// </summary>
        private void EditSelectedKeyframe()
        {
            if (disableCurveEdit)
            {
                ShowReadOnlyMessage();
                return;
            }

            if (selectedKeyframes.Count == 0)
            {
                return;
            }

            EdAnimationCurve curve = curveInfos[selectedKeyframes[0].curveIdx].curve;

            KeyFrame[] keyFrames = curve.KeyFrames;

            int      keyIndex = selectedKeyframes[0].keyIndices[0];
            KeyFrame keyFrame = keyFrames[keyIndex];
            Vector2I position = guiCurveDrawing.CurveToPixelSpace(new Vector2(keyFrame.time, keyFrame.value));

            Rect2I drawingBounds = GUIUtility.CalculateBounds(drawingPanel, window.GUI);

            position.x = MathEx.Clamp(position.x, 0, drawingBounds.width);
            position.y = MathEx.Clamp(position.y, 0, drawingBounds.height);

            Vector2I windowPos = position + new Vector2I(drawingBounds.x, drawingBounds.y);

            KeyframeEditWindow editWindow = DropDownWindow.Open <KeyframeEditWindow>(window, windowPos);

            editWindow.Initialize(keyFrame, x =>
            {
                curve.UpdateKeyframe(keyIndex, x.time, x.value);
                curve.Apply();
                // TODO UNDOREDO

                guiCurveDrawing.Rebuild();
                OnCurveModified?.Invoke();
            });
        }
 /// <summary>
 /// Returns the bounds of the GUI element relative to the provided panel.
 /// </summary>
 public Rect2I GetBounds(GUIPanel relativeTo)
 {
     return(GUIUtility.CalculateBounds(canvas, relativeTo));
 }
Exemple #12
0
        /// <summary>
        /// Handles input. Should be called by the owning window whenever a pointer is moved.
        /// </summary>
        /// <param name="ev">Object containing pointer move event information.</param>
        internal void OnPointerMoved(PointerEvent ev)
        {
            if (ev.Button != PointerButton.Left)
            {
                return;
            }

            if (isPointerHeld)
            {
                Vector2I windowPos = window.ScreenToWindowPos(ev.ScreenPos);

                Rect2I   elementBounds = GUIUtility.CalculateBounds(gui, window.GUI);
                Vector2I pointerPos    = windowPos - new Vector2I(elementBounds.x, elementBounds.y);

                if (isMousePressedOverKey || isMousePressedOverTangent)
                {
                    Rect2I   drawingBounds = drawingPanel.Bounds;
                    Vector2I drawingPos    = pointerPos - new Vector2I(drawingBounds.x, drawingBounds.y);

                    if (!isDragInProgress)
                    {
                        int distance = Vector2I.Distance(drawingPos, dragStart);
                        if (distance >= DRAG_START_DISTANCE)
                        {
                            if (isMousePressedOverKey && !disableCurveEdit)
                            {
                                draggedKeyframes.Clear();
                                foreach (var selectedEntry in selectedKeyframes)
                                {
                                    EdAnimationCurve curve     = curveInfos[selectedEntry.curveIdx].curve;
                                    KeyFrame[]       keyFrames = curve.KeyFrames;

                                    DraggedKeyframes newEntry = new DraggedKeyframes();
                                    newEntry.curveIdx = selectedEntry.curveIdx;
                                    draggedKeyframes.Add(newEntry);

                                    foreach (var keyframeIdx in selectedEntry.keyIndices)
                                    {
                                        newEntry.keys.Add(new DraggedKeyframe(keyframeIdx, keyFrames[keyframeIdx]));
                                    }
                                }
                            }

                            // TODO - UNDOREDO record keyframe or tangent

                            isDragInProgress = true;
                        }
                    }

                    if (isDragInProgress)
                    {
                        if (isMousePressedOverKey && !disableCurveEdit)
                        {
                            Vector2 diff = Vector2.Zero;

                            Vector2 dragStartCurve;
                            if (guiCurveDrawing.PixelToCurveSpace(dragStart, out dragStartCurve))
                            {
                                Vector2 currentPosCurve;
                                if (guiCurveDrawing.PixelToCurveSpace(drawingPos, out currentPosCurve))
                                {
                                    diff = currentPosCurve - dragStartCurve;
                                }
                            }

                            foreach (var draggedEntry in draggedKeyframes)
                            {
                                EdAnimationCurve curve = curveInfos[draggedEntry.curveIdx].curve;

                                for (int i = 0; i < draggedEntry.keys.Count; i++)
                                {
                                    DraggedKeyframe draggedKey = draggedEntry.keys[i];

                                    float newTime  = draggedKey.original.time + diff.x;
                                    float newValue = draggedKey.original.value + diff.y;

                                    int newIndex = curve.UpdateKeyframe(draggedKey.index, newTime, newValue);

                                    // It's possible key changed position due to time change, but since we're moving all
                                    // keys at once they cannot change position relative to one another, otherwise we would
                                    // need to update indices for other keys as well.
                                    draggedKey.index     = newIndex;
                                    draggedEntry.keys[i] = draggedKey;
                                }

                                curve.Apply();
                            }

                            // Rebuild selected keys from dragged keys (after potential sorting)
                            ClearSelection();
                            foreach (var draggedEntry in draggedKeyframes)
                            {
                                foreach (var keyframe in draggedEntry.keys)
                                {
                                    SelectKeyframe(new KeyframeRef(draggedEntry.curveIdx, keyframe.index));
                                }
                            }

                            OnCurveModified?.Invoke();
                            guiCurveDrawing.Rebuild();
                            UpdateEventsGUI();
                        }
                        else if (isMousePressedOverTangent && !disableCurveEdit)
                        {
                            EdAnimationCurve curve    = curveInfos[draggedTangent.keyframeRef.curveIdx].curve;
                            KeyFrame         keyframe = curve.KeyFrames[draggedTangent.keyframeRef.keyIdx];

                            Vector2 keyframeCurveCoords = new Vector2(keyframe.time, keyframe.value);

                            Vector2 currentPosCurve;
                            if (guiCurveDrawing.PixelToCurveSpace(drawingPos, out currentPosCurve))
                            {
                                Vector2 normal = currentPosCurve - keyframeCurveCoords;
                                normal = normal.Normalized;

                                float tangent = EdAnimationCurve.NormalToTangent(normal);

                                if (draggedTangent.type == TangentType.In)
                                {
                                    if (normal.x > 0.0f)
                                    {
                                        tangent = float.PositiveInfinity;
                                    }

                                    keyframe.inTangent = -tangent;
                                    if (curve.TangentModes[draggedTangent.keyframeRef.keyIdx] == TangentMode.Free)
                                    {
                                        keyframe.outTangent = -tangent;
                                    }
                                }
                                else
                                {
                                    if (normal.x < 0.0f)
                                    {
                                        tangent = float.PositiveInfinity;
                                    }

                                    keyframe.outTangent = tangent;
                                    if (curve.TangentModes[draggedTangent.keyframeRef.keyIdx] == TangentMode.Free)
                                    {
                                        keyframe.inTangent = tangent;
                                    }
                                }

                                curve.KeyFrames[draggedTangent.keyframeRef.keyIdx] = keyframe;
                                curve.Apply();

                                OnCurveModified?.Invoke();
                                guiCurveDrawing.Rebuild();
                            }
                        }
                    }
                }
                else // Move frame marker
                {
                    int frameIdx = guiTimeline.GetFrame(pointerPos);

                    if (frameIdx != -1)
                    {
                        SetMarkedFrame(frameIdx);
                    }

                    OnFrameSelected?.Invoke(frameIdx);
                }
            }
        }
Exemple #13
0
        /// <summary>
        /// Handles input. Should be called by the owning window whenever a pointer is pressed.
        /// </summary>
        /// <param name="ev">Object containing pointer press event information.</param>
        internal void OnPointerPressed(PointerEvent ev)
        {
            if (ev.IsUsed)
            {
                return;
            }

            Vector2I windowPos = window.ScreenToWindowPos(ev.ScreenPos);

            Rect2I   elementBounds = GUIUtility.CalculateBounds(gui, window.GUI);
            Vector2I pointerPos    = windowPos - new Vector2I(elementBounds.x, elementBounds.y);

            Rect2I   drawingBounds = drawingPanel.Bounds;
            Vector2I drawingPos    = pointerPos - new Vector2I(drawingBounds.x, drawingBounds.y);

            Rect2I   eventBounds = eventsPanel.Bounds;
            Vector2I eventPos    = pointerPos - new Vector2I(eventBounds.x, eventBounds.y);

            if (ev.Button == PointerButton.Left)
            {
                Vector2 curveCoord;
                if (guiCurveDrawing.PixelToCurveSpace(drawingPos, out curveCoord))
                {
                    KeyframeRef keyframeRef;
                    if (!guiCurveDrawing.FindKeyFrame(drawingPos, out keyframeRef))
                    {
                        TangentRef tangentRef;
                        if (guiCurveDrawing.FindTangent(drawingPos, out tangentRef))
                        {
                            isMousePressedOverTangent = true;
                            dragStart      = drawingPos;
                            draggedTangent = tangentRef;
                        }
                        else
                        {
                            ClearSelection();
                        }
                    }
                    else
                    {
                        if (!IsSelected(keyframeRef))
                        {
                            if (!Input.IsButtonHeld(ButtonCode.LeftShift) && !Input.IsButtonHeld(ButtonCode.RightShift))
                            {
                                ClearSelection();
                            }

                            SelectKeyframe(keyframeRef);
                        }

                        isMousePressedOverKey = true;
                        dragStart             = drawingPos;
                    }

                    guiCurveDrawing.Rebuild();
                    UpdateEventsGUI();
                }
                else
                {
                    int frameIdx = guiTimeline.GetFrame(pointerPos);

                    if (frameIdx != -1)
                    {
                        SetMarkedFrame(frameIdx);
                    }
                    else
                    {
                        int eventIdx;
                        if (guiEvents.FindEvent(eventPos, out eventIdx))
                        {
                            if (!Input.IsButtonHeld(ButtonCode.LeftShift) && !Input.IsButtonHeld(ButtonCode.RightShift))
                            {
                                ClearSelection();
                            }

                            events[eventIdx].selected = true;
                            UpdateEventsGUI();
                        }
                        else
                        {
                            ClearSelection();

                            guiCurveDrawing.Rebuild();
                            UpdateEventsGUI();
                        }
                    }

                    OnFrameSelected?.Invoke(frameIdx);
                }

                isPointerHeld = true;
            }
            else if (ev.Button == PointerButton.Right)
            {
                Vector2 curveCoord;
                if (guiCurveDrawing.PixelToCurveSpace(drawingPos, out curveCoord))
                {
                    contextClickPosition = drawingPos;

                    KeyframeRef keyframeRef;
                    if (!guiCurveDrawing.FindKeyFrame(drawingPos, out keyframeRef))
                    {
                        ClearSelection();

                        blankContextMenu.Open(pointerPos, gui);

                        guiCurveDrawing.Rebuild();
                        UpdateEventsGUI();
                    }
                    else
                    {
                        // If clicked outside of current selection, just select the one keyframe
                        if (!IsSelected(keyframeRef))
                        {
                            ClearSelection();
                            SelectKeyframe(keyframeRef);

                            guiCurveDrawing.Rebuild();
                            UpdateEventsGUI();
                        }

                        keyframeContextMenu.Open(pointerPos, gui);
                    }
                }
                else if (guiEvents.GetFrame(eventPos) != -1) // Clicked over events bar
                {
                    contextClickPosition = eventPos;

                    int eventIdx;
                    if (!guiEvents.FindEvent(eventPos, out eventIdx))
                    {
                        ClearSelection();

                        blankEventContextMenu.Open(pointerPos, gui);

                        guiCurveDrawing.Rebuild();
                        UpdateEventsGUI();
                    }
                    else
                    {
                        // If clicked outside of current selection, just select the one event
                        if (!events[eventIdx].selected)
                        {
                            ClearSelection();
                            events[eventIdx].selected = true;

                            guiCurveDrawing.Rebuild();
                            UpdateEventsGUI();
                        }

                        eventContextMenu.Open(pointerPos, gui);
                    }
                }
            }
        }