예제 #1
0
 public void DrawOnMe(SKSurface surface)
 {
     if (_currentRenderedFrame != null)
     {
         _currentRenderedFrame.DrawFunction(surface, _currentRenderedFrame.FramePoints);
         _currentRenderedFrame = null;
     }
     else
     {
         using (var c = surface.Canvas)
         {
             c.Clear();
         }
     }
 }
예제 #2
0
        private async Task RestartActionBlock()
        {
            while (_keepLoopAlive)
            {
                _animationFlow = new AnimationFlow((arg) =>
                {
                    _currentRenderedFrame = arg;
                    _currentDisplay.SignalRedraw();
                }, _uiTaskScheduler);

                if (_shouldStartRandomAnim)
                {
                    _animationFlow.StartRandomAnimationsLoop(_randomAnimationTime);
                    //only start one at a time
                    _shouldStartRandomAnim = false;
                }

                var completionTask = await Task.WhenAny(_animationFlow.CompletionTask);

                var message = "Animation Loop Has Closed: it ";
                switch (completionTask.Status)
                {
                case TaskStatus.RanToCompletion:
                    message += "ran to completion";
                    break;

                case TaskStatus.Canceled:
                    message += "was canceled";
                    break;

                case TaskStatus.Faulted:
                    message += "has faulted";
                    Debug.WriteLine(completionTask.Exception.InnerException.InnerException.InnerException);
                    break;
                }
                Debug.WriteLine("\n" + message);
            }
        }
예제 #3
0
        public AnimationFlow(Action <RenderedFrame> notifyFrameReady, TaskScheduler uiScheduler) : base(DataflowOptions.Default)
        {
            _animations = new CurrentAnimationsBlock();
            _frameQueue = new FrameQueueBlock <AnimationBase[]>(new ExecutionDataflowBlockOptions {
                MaxDegreeOfParallelism = Environment.ProcessorCount
            });

            _renderFrame = new TransformBlock <AnimationBase[], RenderedFrame>((arg) =>
            {
                var animFrame = new List <HashSet <AnimatedPoint> >();
                foreach (var anim in arg)
                {
                    if (!anim.IsSetup)
                    {
                        anim.SetupAnimation();
                    }

                    HashSet <AnimatedPoint> x = new HashSet <AnimatedPoint>();
                    //dont render a frame that won't be drawn
                    if (anim.CurrentFrame <= anim.NumFrames)
                    {
                        x = anim.RenderFrame(anim.CurrentFrame);
                    }

                    animFrame.Add(x);
                }

                //allows any derived draw function
                //newest animation determines how all current animations will be drawn
                var rend = new RenderedFrame(arg[arg.Length - 1].DrawPointFrame);

                //no use in "combining" animations unless there is more than 1 anim for this frame
                if (animFrame.Count > 1)
                {
                    var dict = new Dictionary <SKPoint, AnimatedPoint>();
                    //for each animation render for this frame
                    foreach (var frame in animFrame)
                    {
                        //for each point changed in the rendered animation
                        foreach (var pointChange in frame)
                        {
                            //if point has been previously animated, update it
                            if (dict.ContainsKey(pointChange.Point))
                            {
                                dict[pointChange.Point].XDisplacement += pointChange.XDisplacement;
                                dict[pointChange.Point].YDisplacement += pointChange.YDisplacement;
                            }
                            //or add it
                            else
                            {
                                dict[pointChange.Point] = pointChange;
                            }
                        }
                    }
                    //check each point after its duplicates have been accumulated
                    foreach (var point in dict.Values)
                    {
                        var p = dict[point.Point];

                        //only want to limit to max displacement if it has been specified
                        if (p.LimitDisplacement)
                        {
                            if (Math.Abs(p.XDisplacement) > p.MaxXDisplacement)
                            {
                                var oldDisp     = p.XDisplacement;
                                p.XDisplacement = p.MaxXDisplacement;
                                if (oldDisp < 0)
                                {
                                    p.XDisplacement *= -1;
                                }
                            }

                            if (Math.Abs(p.YDisplacement) > p.MaxYDisplacement)
                            {
                                var oldDisp     = p.YDisplacement;
                                p.YDisplacement = p.MaxYDisplacement;
                                if (oldDisp < 0)
                                {
                                    p.YDisplacement *= -1;
                                }
                            }
                        }
                    }

                    rend.FramePoints = dict.Values.ToList();
                }
                else
                {
                    rend.FramePoints = animFrame[0].ToList();
                }
                _animations.FrameRendered();

                return(rend);
            }, new ExecutionDataflowBlockOptions {
                MaxDegreeOfParallelism = Environment.ProcessorCount
            });

            //limit parallelism so that only one redraw update can occur
            _signalFrameRendered = new ActionBlock <RenderedFrame>(notifyFrameReady, new ExecutionDataflowBlockOptions {
                MaxDegreeOfParallelism = 1, TaskScheduler = uiScheduler
            });

            _animations.LinkTo(_frameQueue, new DataflowLinkOptions {
                PropagateCompletion = true
            });
            _frameQueue.LinkTo(_renderFrame, new DataflowLinkOptions {
                PropagateCompletion = true
            });
            _renderFrame.LinkTo(_signalFrameRendered, new DataflowLinkOptions {
                PropagateCompletion = true
            });

            RegisterChild(_animations);
            RegisterChild(_frameQueue);
            RegisterChild(_renderFrame);
            RegisterChild(_signalFrameRendered);
        }