Просмотр исходного кода

GUITimeline and GUICurveDrawing conversion between window coordinates to curve coordinates and time

BearishSun 9 лет назад
Родитель
Сommit
c1e92cb467

+ 84 - 47
Source/MBansheeEditor/Windows/Animation/GUICurveDrawing.cs

@@ -15,14 +15,13 @@ namespace BansheeEditor
     {
         private const int PADDING = 30; // TODO - Shared with GUITimeline
         private const int LINE_SPLIT_WIDTH = 2;
-        private readonly static Color COLOR_MID_GRAY = new Color(90.0f / 255.0f, 90.0f / 255.0f, 90.0f / 255.0f, 1.0f);
+        private static readonly Color COLOR_MID_GRAY = new Color(90.0f / 255.0f, 90.0f / 255.0f, 90.0f / 255.0f, 1.0f);
 
         private EdAnimationCurve[] curves;
         private int width;
         private int height;
-        private float length = 60.0f;
-        private float minY = -1.0f;
-        private float maxY = 1.0f;
+        private float xRange = 60.0f;
+        private float yRange = 20.0f;
 
         private int drawableWidth;
         private GUICanvas canvas;
@@ -37,6 +36,31 @@ namespace BansheeEditor
             SetSize(width, height);
         }
 
+        public bool GetCurveCoordinates(Vector2I windowCoords, out Vector2 curveCoords)
+        {
+            Rect2I bounds = canvas.Bounds;
+
+            if (windowCoords.x < (bounds.x + PADDING) || windowCoords.x >= (bounds.x + bounds.width - PADDING) ||
+                windowCoords.y < bounds.y || windowCoords.y >= (bounds.y + bounds.height))
+            {
+                curveCoords = new Vector2();
+                return false;
+            }
+
+            Vector2I relativeCoords = windowCoords - new Vector2I(bounds.x + PADDING, bounds.y);
+
+            float lengthPerPixel = xRange / drawableWidth;
+            float heightPerPixel = yRange / height;
+
+            float yOffset = yRange/2.0f;
+
+            curveCoords = new Vector2();
+            curveCoords.x = relativeCoords.x * lengthPerPixel;
+            curveCoords.y = yOffset - relativeCoords.y * heightPerPixel;
+
+            return true;
+        }
+
         public void SetCurves(EdAnimationCurve[] curves)
         {
             this.curves = curves;
@@ -57,19 +81,10 @@ namespace BansheeEditor
             Rebuild();
         }
 
-        public void SetRange(float length, float minY, float maxY)
+        public void SetRange(float xRange, float yRange)
         {
-            this.length = length;
-
-            if (minY > maxY)
-            {
-                float temp = maxY;
-                maxY = minY;
-                minY = temp;
-            }
-
-            this.minY = minY;
-            this.maxY = maxY;
+            this.xRange = xRange;
+            this.yRange = yRange;
 
             Rebuild();
         }
@@ -93,23 +108,20 @@ namespace BansheeEditor
 
         private void DrawCurve(EdAnimationCurve curve, Color color)
         {
-            float lengthPerPixel = length/drawableWidth;
-            float pixelsPerHeight = height/(maxY - minY);
+            float lengthPerPixel = xRange/drawableWidth;
+            float pixelsPerHeight = height/yRange;
 
             int heightOffset = height/2; // So that y = 0 is at center of canvas
 
             KeyFrame[] keyframes = curve.Native.KeyFrames;
-            if (keyframes.Length == 0)
+            if (keyframes.Length < 0)
                 return;
 
-            float start = MathEx.Clamp(keyframes[0].time, 0.0f, length);
-            float end = MathEx.Clamp(keyframes[keyframes.Length - 1].time, 0.0f, length);
-
-            int startPixel = (int)(start / lengthPerPixel);
-            int endPixel = (int)(end / lengthPerPixel);
-
             // Draw start line
             {
+                float start = MathEx.Clamp(keyframes[0].time, 0.0f, xRange);
+                int startPixel = (int)(start / lengthPerPixel);
+
                 int xPosStart = 0;
                 int xPosEnd = PADDING + startPixel;
 
@@ -122,37 +134,62 @@ namespace BansheeEditor
                 canvas.DrawLine(a, b, COLOR_MID_GRAY);
             }
 
-            // Draw in between
-            float fNumSplits = (endPixel - startPixel)/(float) LINE_SPLIT_WIDTH;
-
-            int numSplits = MathEx.FloorToInt(fNumSplits);
-            float remainder = fNumSplits - numSplits;
-
-            float lengthRounded = (end - start)*(numSplits / fNumSplits);
-            float timeIncrement = lengthRounded/numSplits;
+            List<Vector2I> linePoints = new List<Vector2I>();
 
-            numSplits += MathEx.CeilToInt(remainder) + 1;
-
-            Vector2I[] linePoints = new Vector2I[numSplits];
-            for (int i = 0; i < numSplits; i++)
+            // Draw in between keyframes
+            for (int i = 0; i < keyframes.Length - 1; i++)
             {
-                int xPos = Math.Min(startPixel + i * LINE_SPLIT_WIDTH, endPixel);
-                float t = Math.Min(start + i * timeIncrement, end);
-
-                int yPos = (int)(curve.Native.Evaluate(t, false) * pixelsPerHeight);
-                yPos = heightOffset - yPos; // Offset and flip height (canvas Y goes down)
-
-                linePoints[i] = new Vector2I(PADDING + xPos, yPos);
+                float start = MathEx.Clamp(keyframes[i].time, 0.0f, xRange);
+                float end = MathEx.Clamp(keyframes[i + 1].time, 0.0f, xRange);
+                
+                int startPixel = (int)(start / lengthPerPixel);
+                int endPixel = (int)(end / lengthPerPixel);
+
+                int numSplits;
+                float timeIncrement;
+                if (startPixel != endPixel)
+                {
+                    float fNumSplits = (endPixel - startPixel)/(float) LINE_SPLIT_WIDTH;
+
+                    numSplits = MathEx.FloorToInt(fNumSplits);
+                    float remainder = fNumSplits - numSplits;
+
+                    float lengthRounded = (end - start)*(numSplits/fNumSplits);
+                    timeIncrement = lengthRounded/numSplits;
+
+                    numSplits += MathEx.CeilToInt(remainder) + 1;
+                }
+                else
+                {
+                    numSplits = 1;
+                    timeIncrement = 0.0f;
+                }
+
+                // TODO - Make sure that step tangents work
+
+                for (int j = 0; j < numSplits; j++)
+                {
+                    int xPos = Math.Min(startPixel + j * LINE_SPLIT_WIDTH, endPixel);
+                    float t = Math.Min(start + j * timeIncrement, end);
+
+                    int yPos = (int)(curve.Native.Evaluate(t, false) * pixelsPerHeight);
+                    yPos = heightOffset - yPos; // Offset and flip height (canvas Y goes down)
+
+                    linePoints.Add(new Vector2I(PADDING + xPos, yPos));
+                }
             }
-
-            canvas.DrawPolyLine(linePoints, color);
+            
+            canvas.DrawPolyLine(linePoints.ToArray(), color);
 
             // Draw end line
             {
+                float end = MathEx.Clamp(keyframes[keyframes.Length - 1].time, 0.0f, xRange);
+                int endPixel = (int)(end / lengthPerPixel);
+
                 int xPosStart = PADDING + endPixel;
                 int xPosEnd = width;
 
-                int yPos = (int)(curve.Native.Evaluate(length, false) * pixelsPerHeight);
+                int yPos = (int)(curve.Native.Evaluate(xRange, false) * pixelsPerHeight);
                 yPos = heightOffset - yPos; // Offset and flip height (canvas Y goes down)
 
                 Vector2I a = new Vector2I(xPosStart, yPos);

+ 19 - 0
Source/MBansheeEditor/Windows/Animation/GUITimeline.cs

@@ -46,6 +46,25 @@ namespace BansheeEditor
             SetSize(width, height);
         }
 
+        public bool GetTime(Vector2I windowCoords, out float time)
+        {
+            Rect2I bounds = canvas.Bounds;
+
+            if (windowCoords.x < (bounds.x + PADDING) || windowCoords.x >= (bounds.x + bounds.width - PADDING) ||
+                windowCoords.y < bounds.y || windowCoords.y >= (bounds.y + bounds.height))
+            {
+                time = 0.0f;
+                return false;
+            }
+
+            Vector2I relativeCoords = windowCoords - new Vector2I(bounds.x + PADDING, bounds.y);
+
+            float lengthPerPixel = rangeLength / drawableWidth;
+            time = relativeCoords.x * lengthPerPixel;
+
+            return true;
+        }
+
         public void SetSize(int width, int height)
         {
             this.width = width;

+ 24 - 3
Source/MBansheeEditor/Windows/AnimationWindow.cs

@@ -47,12 +47,12 @@ namespace BansheeEditor
             lengthField.OnChanged += x =>
             {
                 timeline.SetRange(lengthField.Value);
-                curveDrawing.SetRange(lengthField.Value, yRangeField.Value * -0.5f, yRangeField.Value * 0.5f);
+                curveDrawing.SetRange(lengthField.Value, yRangeField.Value);
             };
             fpsField.OnChanged += x => timeline.SetFPS(x);
             yRangeField.OnChanged += x =>
             {
-                curveDrawing.SetRange(lengthField.Value, x * -0.5f, x * 0.5f);
+                curveDrawing.SetRange(lengthField.Value, x);
             };
 
             GUILayout mainLayout = GUI.AddLayoutY();
@@ -70,7 +70,7 @@ namespace BansheeEditor
 
             EdAnimationCurve[] curves = CreateDummyCurves();
             curveDrawing = new GUICurveDrawing(mainLayout, Width, Height - 20, curves);
-            curveDrawing.SetRange(60.0f, -10.0f, 10.0f);
+            curveDrawing.SetRange(60.0f, 20.0f);
 
             // TODO - Calculate min/max Y and range to set as default
             //  - Also recalculate whenever curves change and increase as needed
@@ -96,6 +96,27 @@ namespace BansheeEditor
 
         private void OnEditorUpdate()
         {
+            if (Input.IsPointerButtonDown(PointerButton.Left))
+            {
+                Vector2I windowPos = ScreenToWindowPos(Input.PointerPosition);
+
+                Vector2 curveCoord;
+                if (curveDrawing.GetCurveCoordinates(windowPos, out curveCoord))
+                {
+                    Debug.Log("Click coord: " + curveCoord);
+                }
+                else
+                {
+                    float time;
+                    if (timeline.GetTime(windowPos, out time))
+                    {
+                        Debug.Log("Click time: " + time);
+                    }
+                    else
+                        Debug.Log("Clicked outside!");
+                }
+            }
+
             //int position = (int)(MathEx.Sin(Time.RealElapsed)*50.0f + 50.0f);
             //canvas.SetPosition(position, 0);
         }