Selaa lähdekoodia

Animation window fixes:
- Properly redraw curve & timeline when offsets change
- Properly account for offsets in graph timeline
- Zoom now properly focuses on the required area
- Scrollbar position is now properly set

BearishSun 9 vuotta sitten
vanhempi
sitoutus
22a1e66eb9

+ 2 - 2
Source/MBansheeEditor/Windows/Animation/GUICurveDrawing.cs

@@ -275,7 +275,7 @@ namespace BansheeEditor
         /// <param name="pixelCoords">Coordinates relative to this GUI element, in pixels.</param>
         /// <param name="curveCoords">Curve coordinates within the range as specified by <see cref="SetRange"/>. Only
         ///                           valid when function returns true.</param>
-        /// <returns>True if the window coordinates were within the curve area, false otherwise.</returns>
+        /// <returns>True if the coordinates are within the curve area, false otherwise.</returns>
         public bool PixelToCurveSpace(Vector2I pixelCoords, out Vector2 curveCoords)
         {
             Rect2I bounds = canvas.Bounds;
@@ -501,7 +501,7 @@ namespace BansheeEditor
             if (curves == null)
                 return;
 
-            tickHandler.SetRange(offset.x, GetRange(true), drawableWidth + GUIGraphTime.PADDING);
+            tickHandler.SetRange(offset.x, offset.x + GetRange(true), drawableWidth + GUIGraphTime.PADDING);
 
             // Draw vertical frame markers
             int numTickLevels = tickHandler.NumLevels;

+ 25 - 0
Source/MBansheeEditor/Windows/Animation/GUICurveEditor.cs

@@ -110,6 +110,8 @@ namespace BansheeEditor
                 guiTimeline.SetOffset(offset.x);
                 guiCurveDrawing.SetOffset(offset);
                 guiSidebar.SetRange(offset.y - yRange, offset.y + yRange);
+
+                Redraw();
             }
         }
 
@@ -168,6 +170,29 @@ namespace BansheeEditor
             guiSidebar.SetRange(-10.0f, 10.0f);
         }
 
+        /// <summary>
+        /// Converts pixel coordinates relative to the curve drawing area into coordinates in curve space.
+        /// </summary>
+        /// <param name="pixelCoords">Coordinates relative to this GUI element, in pixels.</param>
+        /// <param name="curveCoords">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 PixelToCurveSpace(Vector2I pixelCoords, out Vector2 curveCoords)
+        {
+            return guiCurveDrawing.PixelToCurveSpace(pixelCoords, out curveCoords);
+        }
+
+        /// <summary>
+        /// Converts coordinate in curve space (time, value) into pixel coordinates relative to the curve drawing area
+        /// origin.
+        /// </summary>
+        /// <param name="curveCoords">Time and value of the location to convert.</param>
+        /// <returns>Coordinates relative to curve drawing area's origin, in pixels.</returns>
+        public Vector2I CurveToPixelSpace(Vector2 curveCoords)
+        {
+            return guiCurveDrawing.CurveToPixelSpace(curveCoords);
+        }
+
         public bool WindowToCurveSpace(Vector2I windowPos, out Vector2 curveCoord)
         {
             Rect2I elementBounds = GUIUtility.CalculateBounds(gui, window.GUI);

+ 6 - 6
Source/MBansheeEditor/Windows/Animation/GUIGraphTime.cs

@@ -96,7 +96,7 @@ namespace BansheeEditor
             tickHeight = (int)(height * TICK_HEIGHT_PCT);
             drawableWidth = Math.Max(0, width - PADDING * 2);
 
-            tickHandler.SetRange(rangeOffset, GetRange(true), drawableWidth + PADDING);
+            tickHandler.SetRange(rangeOffset, rangeOffset + GetRange(true), drawableWidth + PADDING);
         }
 
         /// <summary>
@@ -107,7 +107,7 @@ namespace BansheeEditor
         {
             rangeLength = Math.Max(0.0f, length);
 
-            tickHandler.SetRange(rangeOffset, GetRange(true), drawableWidth + PADDING);
+            tickHandler.SetRange(rangeOffset, rangeOffset + GetRange(true), drawableWidth + PADDING);
         }
 
         /// <summary>
@@ -118,7 +118,7 @@ namespace BansheeEditor
         {
             rangeOffset = offset;
 
-            tickHandler.SetRange(rangeOffset, GetRange(true), drawableWidth + PADDING);
+            tickHandler.SetRange(rangeOffset, rangeOffset + GetRange(true), drawableWidth + PADDING);
         }
 
         /// <summary>
@@ -129,7 +129,7 @@ namespace BansheeEditor
         {
             this.fps = Math.Max(1, fps);
 
-            tickHandler.SetRange(rangeOffset, GetRange(true), drawableWidth + PADDING);
+            tickHandler.SetRange(rangeOffset, rangeOffset + GetRange(true), drawableWidth + PADDING);
         }
         
         /// <summary>
@@ -206,12 +206,12 @@ namespace BansheeEditor
         /// <returns>Time range rounded to a multiple of FPS.</returns>
         private float GetRange(bool padding = false)
         {
-            float spf = 1.0f/fps;
+            float spf = 1.0f / fps;
 
             float range = rangeLength;
             if (padding)
             {
-                float lengthPerPixel = rangeLength/drawableWidth;
+                float lengthPerPixel = rangeLength / drawableWidth;
                 range += lengthPerPixel * PADDING;
             }
 

+ 39 - 26
Source/MBansheeEditor/Windows/AnimationWindow.cs

@@ -19,7 +19,7 @@ namespace BansheeEditor
         private const int FIELD_DISPLAY_WIDTH = 200;
         private const int DRAG_START_DISTANCE = 3;
         private const float DRAG_SCALE = 10.0f;
-        private const float ZOOM_SCALE = 15.0f;
+        private const float ZOOM_SCALE = 0.1f/120.0f; // One scroll step is usually 120 units, we want 1/10 of that
 
         private bool isInitialized;
         private SceneObject selectedSO;
@@ -114,7 +114,12 @@ namespace BansheeEditor
             curves.Clear();
             isInitialized = false;
 
-            selectedSO = Selection.SceneObject;
+            if (selectedSO != Selection.SceneObject)
+            {
+                zoomAmount = 0.0f;
+                selectedSO = Selection.SceneObject;
+            }
+
             if (selectedSO == null)
             {
                 GUILabel warningLbl = new GUILabel(new LocEdString("Select an object to animate in the Hierarchy or Scene windows."));
@@ -361,7 +366,7 @@ namespace BansheeEditor
             float scrollableRange = totalRange.y - visibleRange.y;
 
             Vector2 offset = guiCurveEditor.Offset;
-            offset.y = scrollableRange * (position * 2.0f - 1.0f);
+            offset.y = -scrollableRange * (position * 2.0f - 1.0f);
 
             guiCurveEditor.Offset = offset;
         }
@@ -398,12 +403,15 @@ namespace BansheeEditor
             Vector2 scrollableRange = totalRange - visibleRange;
 
             Vector2 offset = guiCurveEditor.Offset;
-            // Transform Y from [-x, +x] range to [0, x]
-            offset.y += visibleRange.y;
-            offset.y /= 2.0f;
+            if (scrollableRange.x > 0.0f)
+                horzScrollBar.Position = offset.x / scrollableRange.x;
+            else
+                horzScrollBar.Position = 0.0f;
 
-            horzScrollBar.Position = offset.x / scrollableRange.x;
-            vertScrollBar.Position = offset.y / scrollableRange.y;
+            if (scrollableRange.y > 0.0f)
+                vertScrollBar.Position = offset.y / (scrollableRange.y * 0.5f);
+            else
+                vertScrollBar.Position = 0.0f;
         }
 
         private Vector2 GetZoomedRange()
@@ -416,19 +424,27 @@ namespace BansheeEditor
 
         private Vector2 GetTotalRange()
         {
+            // Return optimal range (that covers the visible curve)
+            Vector2 totalRange = GetOptimalRange();
+
+            // Increase range in case user zoomed out
+            Vector2 zoomedRange = GetZoomedRange();
+            totalRange = Vector2.Max(totalRange, zoomedRange);
+
+            // Increase range in case user dragged outside of the optimal range
             Vector2 visibleRange = guiCurveEditor.Range;
-            Vector2 totalRange = guiCurveEditor.Offset;
-            totalRange.x += visibleRange.x;
-            totalRange.y = Math.Abs(totalRange.y) + visibleRange.y;
+            Vector2 draggedRange = guiCurveEditor.Offset;
+            draggedRange.x += visibleRange.x;
+            draggedRange.y = Math.Abs(draggedRange.y) + visibleRange.y;
 
-            Vector2 optimalRange = GetOptimalRange();
-            return Vector2.Max(totalRange, optimalRange);
+            return Vector2.Max(totalRange, draggedRange);
         }
 
         private void Zoom(Vector2 curvePos, float amount)
         {
+            // Increase or decrease the visible range depending on zoom level
             Vector2 oldZoomedRange = GetZoomedRange();
-            zoomAmount += amount;
+            zoomAmount = MathEx.Clamp(zoomAmount + amount, -10.0f, 10.0f);
             Vector2 zoomedRange = GetZoomedRange();
 
             Vector2 zoomedDiff = zoomedRange - oldZoomedRange;
@@ -436,21 +452,18 @@ namespace BansheeEditor
 
             Vector2 currentRange = guiCurveEditor.Range;
             Vector2 newRange = currentRange + zoomedDiff;
+            guiCurveEditor.Range = newRange;
 
-            Vector2 offset = guiCurveEditor.Offset;
-            Vector2 relativePos = curvePos - offset;
-
-            relativePos.x /= currentRange.x;
-            relativePos.y /= currentRange.y;
-
-            relativePos.x = relativePos.x * 2.0f - 1.0f;
-            relativePos.y = relativePos.y * 2.0f - 1.0f;
+            // When zooming, make sure to focus on the point provided, so adjust the offset
+            Vector2 rangeScale = newRange;
+            rangeScale.x /= currentRange.x;
+            rangeScale.y /= currentRange.y;
 
-            offset.x += relativePos.x * zoomedDiff.x;
-            offset.y += relativePos.y * zoomedDiff.y * 2.0f;
+            Vector2 relativeCurvePos = curvePos - guiCurveEditor.Offset;
+            Vector2 newCurvePos = relativeCurvePos * rangeScale;
+            Vector2 diff = newCurvePos - relativeCurvePos;
 
-            guiCurveEditor.Offset = offset;
-            guiCurveEditor.Range = newRange;
+            guiCurveEditor.Offset -= diff;
 
             UpdateScrollBarSize();
             UpdateScrollBarPosition();