private async void OnLoaded(object sender, RoutedEventArgs e) { _compositor = Window.Current.Compositor; _generator = _compositor.CreateCompositionGenerator(); var size = new Vector2(GridWidth, GridHeight); _topOffset = -GridHeight / 2f; // Create the left image visual var leftImageVisual = _compositor.CreateSpriteVisual(); leftImageVisual.Size = size; // Left Image Surface var leftImageSurface = await _generator.CreateImageSurfaceAsync(new Uri("ms-appx:///Assets/Images/Image1.jpg"), size.ToSize(), ImageSurfaceOptions.Default); // Left Mask Geometry _leftGeometry = CanvasGeometry.CreateRectangle(_generator.Device, new Rect(0f, 0f, 2f * (GridWidth * _splitValue) / 100f, 2f * GridHeight)); var leftOffset = -(GridWidth * _splitValue) / 100f; // Left Masked Brush var leftMaskedBrush = _compositor.CreateMaskBrush(); leftMaskedBrush.Source = _compositor.CreateSurfaceBrush(leftImageSurface); _leftGaussianSurface = _generator.CreateGaussianMaskSurface(size.ToSize(), _leftGeometry, new Vector2(leftOffset, _topOffset), _blurRadius); leftMaskedBrush.Mask = _compositor.CreateSurfaceBrush(_leftGaussianSurface); leftImageVisual.Brush = leftMaskedBrush; // Create the right image visual var rightImageVisual = _compositor.CreateSpriteVisual(); rightImageVisual.Size = size; // Right Image Surface var rightImageSurface = await _generator.CreateImageSurfaceAsync(new Uri("ms-appx:///Assets/Images/Image2.jpg"), size.ToSize(), ImageSurfaceOptions.Default); // Right Mask Geometry _rightGeometry = CanvasGeometry.CreateRectangle(_generator.Device, new Rect(0, 0, 2f * (GridWidth * (100f - _splitValue)) / 100, 2f * GridHeight)); // Right Masked Brush var rightMaskedBrush = _compositor.CreateMaskBrush(); rightMaskedBrush.Source = _compositor.CreateSurfaceBrush(rightImageSurface); _rightGaussianSurface = _generator.CreateGaussianMaskSurface(size.ToSize(), _rightGeometry, new Vector2(-leftOffset, _topOffset), _blurRadius); rightMaskedBrush.Mask = _compositor.CreateSurfaceBrush(_rightGaussianSurface); rightImageVisual.Brush = rightMaskedBrush; var visualContainer = _compositor.CreateContainerVisual(); visualContainer.Size = size; visualContainer.Children.InsertAtTop(leftImageVisual); visualContainer.Children.InsertAtTop(rightImageVisual); ElementCompositionPreview.SetElementChildVisual(ImageGrid, visualContainer); }
/// <summary> /// Initializes the Composition Brush. /// </summary> protected override void OnConnected() { base.OnConnected(); // Delay creating composition resources until they're required. if (CompositionBrush == null) { // Abort if effects aren't supported. if (!CompositionCapabilities.GetForCurrentView().AreEffectsSupported()) { return; } var size = new Vector2(SurfaceWidth, SurfaceHeight); var device = CanvasDevice.GetSharedDevice(); var graphics = CanvasComposition.CreateCompositionGraphicsDevice(Window.Current.Compositor, device); var surface = graphics.CreateDrawingSurface(size.ToSize(), DirectXPixelFormat.B8G8R8A8UIntNormalized, DirectXAlphaMode.Premultiplied); using (var session = CanvasComposition.CreateDrawingSession(surface)) { // Call Implementor to draw on session. if (!OnDraw(device, session, size)) { return; } } _surfaceBrush = Window.Current.Compositor.CreateSurfaceBrush(surface); _surfaceBrush.Stretch = CompositionStretch.Fill; CompositionBrush = _surfaceBrush; } }
private async void OnPageLoaded(object sender, RoutedEventArgs e) { _compositor = Window.Current.Compositor; _generator = _compositor.CreateCompositionGenerator(); var size = new Vector2(GridWidth, GridWidth); // Create the image visual var imageVisual = _compositor.CreateSpriteVisual(); imageVisual.Size = size; var imageSurface = await _generator.CreateImageSurfaceAsync(new Uri("ms-appx:///Assets/Images/cat.png"), size.ToSize(), ImageSurfaceOptions.Default); imageVisual.Brush = _compositor.CreateSurfaceBrush(imageSurface); ElementCompositionPreview.SetElementChildVisual(ImageGrid, imageVisual); //Create the mask visual var maskVisual = _compositor.CreateSpriteVisual(); maskVisual.Size = size; // Create the combined geometry var ellipse1 = CanvasGeometry.CreateEllipse(_generator.Device, GridWidth / 2, GridWidth / 2, GridWidth * 0.375f, GridWidth * 0.1875f); var ellipse2 = CanvasGeometry.CreateEllipse(_generator.Device, GridWidth / 2, GridWidth / 2, GridWidth * 0.1875f, GridWidth * 0.375f); _combinedGeometry = ellipse1.CombineWith(ellipse2, Matrix3x2.Identity, CanvasGeometryCombine.Union); // Create SurfaceBrush from MaskSurface ElementCompositionPreview.SetElementChildVisual(MaskGrid, maskVisual); var outputVisual = _compositor.CreateSpriteVisual(); outputVisual.Size = size; var maskedBrush = _compositor.CreateMaskBrush(); maskedBrush.Source = imageVisual.Brush; _gaussianSurface = _generator.CreateGaussianMaskSurface(size.ToSize(), _combinedGeometry, Vector2.Zero, 0); maskedBrush.Mask = _compositor.CreateSurfaceBrush(_gaussianSurface); maskVisual.Brush = _compositor.CreateSurfaceBrush(_gaussianSurface);; outputVisual.Brush = maskedBrush; ElementCompositionPreview.SetElementChildVisual(OutputGrid, outputVisual); }
public void Vector2ToSizeTest() { Vector2 vector = new Vector2(23, 42); Windows.Foundation.Size result = vector.ToSize(); Assert.AreEqual(23.0, result.Width); Assert.AreEqual(42.0, result.Height); }
public PaintCore(Compositor compositor) { var canvasSize = new Vector2(400, 400); _currentImage = new Image(null, canvasSize.ToSize()); InitComposition(compositor); InitWin2D(canvasSize); }
private void Draw(bool IsFill, Color color) { _surface = _graphicsDevice.CreateDrawingSurface(Size.ToSize(), Windows.Graphics.DirectX.DirectXPixelFormat.B8G8R8A8UIntNormalized, Windows.Graphics.DirectX.DirectXAlphaMode.Premultiplied); using (var dc = CanvasComposition.CreateDrawingSession(_surface)) { dc.Clear(Colors.Transparent); if (IsFill) { dc.FillCircle(Size / 2, Size.X / 2, color); } else { dc.DrawCircle(Size / 2, Size.X / 2 - 2, color, 2f); } dc.Flush(); } _brush = _compositor.CreateSurfaceBrush(_surface); _visual.Brush = _brush; }
public void NewImage(Vector2 size) { _currentImage.AssignNewFile(null); _currentImage.Size = size.ToSize(); _canvas.Reset(size); }
private void CreateTextAndBlendEffect(Vector2 sizeLightBounds) { // // Crete the effect graph, doing a hard light blend of the text over the // content already drawn into the backbuffer // IGraphicsEffect graphicsEffect = new BlendEffect() { Mode = BlendEffectMode.HardLight, Foreground = new CompositionEffectSourceParameter("Text"), Background = new CompositionEffectSourceParameter("Destination"), }; CompositionEffectFactory effectFactory = _compositor.CreateEffectFactory(graphicsEffect, null); CompositionEffectBrush brush = effectFactory.CreateBrush(); // Bind the destination brush brush.SetSourceParameter("Destination", _compositor.CreateBackdropBrush()); // // Create the text surface which we'll scroll over the image with the lighting effect // // Pick a nice size font depending on target size const float maxFontSize = 72; const float scaleFactor = 12; float fontSize = Math.Min(sizeLightBounds.X / scaleFactor, maxFontSize); // Create the text format description, then the surface CanvasTextFormat textFormat = new CanvasTextFormat { FontFamily = "Segoe UI", FontSize = fontSize, FontWeight = FontWeights.Bold, WordWrapping = CanvasWordWrapping.WholeWord, HorizontalAlignment = CanvasHorizontalAlignment.Center, VerticalAlignment = CanvasVerticalAlignment.Center }; string text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec efficitur, eros sit amet laoreet scelerisque, " + "nunc odio ultricies metus, ut consectetur nulla massa eu nibh.Phasellus in lorem id nunc euismod tempus.Phasellus et nulla non turpis tempor blandit ut eget turpis." + "Phasellus ac ornare elit, ut scelerisque dolor. Nam vel finibus lorem. Aenean malesuada pulvinar eros id ornare. Fusce blandit ante eget dolor efficitur suscipit." + "Phasellus ac lacus nibh. Aenean eget blandit risus, in lacinia mi. Proin fermentum ante eros, non sollicitudin mi pretium eu. Curabitur suscipit lectus arcu, eget" + "pretium quam sagittis non. Mauris purus mauris, condimentum nec laoreet sit amet, imperdiet sit amet nisi. Sed interdum, urna et aliquam porta, elit velit tincidunt orci," + "vitae vestibulum risus lacus at nulla.Phasellus sapien ipsum, pellentesque varius enim nec, iaculis aliquet enim. Nulla id dapibus ante. Sed hendrerit sagittis leo, commodo" + "fringilla ligula rutrum ut. Nullam sodales, ex ut pellentesque scelerisque, sapien nulla mattis lectus, vel ullamcorper leo enim ac mi.Sed consectetur vitae velit in consequat." + "Pellentesque ac condimentum justo, at feugiat nulla. Sed ut congue neque. Nam gravida quam ac urna porttitor, ut bibendum ante mattis.Cras viverra cursus sapien, et sollicitudin" + "risus fringilla eget. Nulla facilisi. Duis pellentesque scelerisque nisi, facilisis malesuada massa gravida et. Vestibulum ac leo sed orci tincidunt feugiat.Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nunc id leo vestibulum, vulputate ipsum sit amet, scelerisque velit. Curabitur imperdiet justo et tortor dignissim, sit amet volutpat sem ullamcorper. Nam mollis ullamcorper tellus vitae convallis. Aliquam eleifend elit nec tincidunt pharetra. Aliquam turpis eros, mollis et nunc quis, porta molestie justo. Etiam ultrices sem non turpis imperdiet dictum.Aliquam molestie elit in urna sodales, nec luctus dui laoreet.Curabitur molestie risus vel ligula efficitur, non fringilla urna iaculis.Curabitur neque tortor, facilisis quis dictum facilisis, facilisis et ante. Sed nisl erat, semper vitae efficitur ut, congue vitae quam. Ut auctor lacus sit amet varius placerat.Sed ac tellus tempus, ultricies est quis, tempor felis.Nulla vel faucibus elit, eu tincidunt eros. Nulla blandit id nisl ut porta. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Etiam suscipit tellus a mattis pulvinar. Sed et libero vel ligula elementum suscipit.Ut elementum libero at sagittis pharetra. Fusce ultrices odio sapien, a posuere est consectetur ut."; // Make the surface twice the height to give us room to scroll Vector2 surfaceSize = new Vector2(sizeLightBounds.X, 2f * sizeLightBounds.Y); CompositionDrawingSurface textSurface = SurfaceLoader.LoadText(text, surfaceSize.ToSize(), textFormat, Colors.White, Colors.Transparent); brush.SetSourceParameter("Text", _compositor.CreateSurfaceBrush(textSurface)); // Create the sprite and parent it to the panel with the clip _textSprite = _compositor.CreateSpriteVisual(); _textSprite.Size = surfaceSize; _textSprite.Brush = brush; ElementCompositionPreview.SetElementChildVisual(MyPanel, _textSprite); // Lastly, setup the slow scrolling animation of the text LinearEasingFunction linear = _compositor.CreateLinearEasingFunction(); Vector3KeyFrameAnimation offsetAnimation = _compositor.CreateVector3KeyFrameAnimation(); offsetAnimation.InsertKeyFrame(0f, new Vector3(0, 0, 0), linear); offsetAnimation.InsertKeyFrame(1f, new Vector3(0, -_textSprite.Size.Y * .5f, 0), linear); offsetAnimation.Duration = TimeSpan.FromMilliseconds(30000); offsetAnimation.IterationBehavior = AnimationIterationBehavior.Forever; _textSprite.StartAnimation("Offset", offsetAnimation); }
private async void OnLoaded(object sender, RoutedEventArgs e) { _compositor = ElementCompositionPreview.GetElementVisual(this).Compositor; _generator = CompositionGeneratorFactory.GetCompositionGenerator(_compositor); var distance = 4f; var visualSize = new Vector2(225, 150); var vRefHeight = visualSize.Y + (visualSize.Y * 0.7f) + distance; var hRefWidth = visualSize.X + (visualSize.X * 0.7f) + distance; var vRefLeft = (float)(CompositionGrid1.ActualWidth - visualSize.X) / 2f; var vRefTop = (float)(CompositionGrid1.ActualHeight - vRefHeight) / 2f; var hRefLeft = (float)(CompositionGrid1.ActualWidth - hRefWidth) / 2f; var hRefTop = (float)(CompositionGrid1.ActualHeight - visualSize.Y) / 2f; var surfaceImage = await _generator.CreateImageSurfaceAsync(new Uri("ms-appx:///Assets/Images/Car.jpg"), visualSize.ToSize(), ImageSurfaceOptions.Default); var surfaceBrush = _compositor.CreateSurfaceBrush(surfaceImage.Surface); var visual1 = _compositor.CreateSpriteVisual(); visual1.Size = visualSize; visual1.Offset = new Vector3(vRefLeft, vRefTop, 0); visual1.Brush = surfaceBrush; _generator.CreateReflection(visual1, distance); ElementCompositionPreview.SetElementChildVisual(CompositionGrid1, visual1); var invertEffect = new InvertEffect() { Source = new CompositionEffectSourceParameter("source") }; var invertEffectFactory = _compositor.CreateEffectFactory(invertEffect); var invertBrush = invertEffectFactory.CreateBrush(); invertBrush.SetSourceParameter("source", surfaceBrush); var visual2 = _compositor.CreateSpriteVisual(); visual2.Size = visualSize; visual2.Offset = new Vector3(hRefLeft, hRefTop, 0); visual2.Brush = invertBrush; _generator.CreateReflection(visual2, distance, 0.7f, ReflectionLocation.Right); ElementCompositionPreview.SetElementChildVisual(CompositionGrid2, visual2); var visual3 = _compositor.CreateSpriteVisual(); visual3.Size = visualSize; visual3.Offset = new Vector3(vRefLeft, vRefTop, 0); visual3.Brush = surfaceBrush; var inVisual = _compositor.CreateSpriteVisual(); inVisual.Size = new Vector2(80, 80); inVisual.Offset = new Vector3(20, 10, 0); inVisual.Brush = _compositor.CreateColorBrush(Colors.Yellow); var inVisual2 = _compositor.CreateSpriteVisual(); inVisual2.Size = new Vector2(80, 80); inVisual2.Offset = new Vector3(60, 60, 0); inVisual2.Brush = _compositor.CreateColorBrush(Colors.Blue); visual3.Children.InsertAtTop(inVisual2); visual3.Children.InsertAtTop(inVisual); _generator.CreateReflection(visual3, distance, 0.7f, ReflectionLocation.Bottom); ElementCompositionPreview.SetElementChildVisual(CompositionGrid3, visual3); var visual4 = _compositor.CreateSpriteVisual(); visual4.Size = visualSize; visual4.Offset = new Vector3(hRefLeft, hRefTop, 0); visual4.Brush = surfaceBrush; var inVisual3 = _compositor.CreateSpriteVisual(); inVisual3.Size = new Vector2(80, 80); inVisual3.Offset = new Vector3(20, 10, 0); inVisual3.Brush = _compositor.CreateColorBrush(Colors.Yellow); var inVisual4 = _compositor.CreateSpriteVisual(); inVisual4.Size = new Vector2(80, 80); inVisual4.Offset = new Vector3(60, 40, 0); inVisual4.Brush = _compositor.CreateColorBrush(Colors.Blue); visual4.Children.InsertAtTop(inVisual3); visual4.Children.InsertAtTop(inVisual4); _generator.CreateReflection(visual4, distance, 0.7f, ReflectionLocation.Right); ElementCompositionPreview.SetElementChildVisual(CompositionGrid4, visual4); }
public static Rect ToRect(this Vector2 topLeft, Vector2 bottomRight) { return(new Rect(topLeft.ToPoint(), bottomRight.ToSize())); }
private async Task<CompositionMaskBrush> CreateMask(Color color, CanvasGeometry geometry, Vector2 size) { var compositionMask = await generator.CreateMaskAsync(size.ToSize(), geometry); var mask = compositor.CreateSurfaceBrush(compositionMask.Surface); var source = compositor.CreateColorBrush(color); var maskBrush = compositor.CreateMaskBrush(); maskBrush.Mask = mask; maskBrush.Source = source; return maskBrush; }
public static Rect Add(this Rect target, Vector2 source) { return(target.Add(source.ToSize())); }
async void Redraw(bool recreateSurface = true) { if (_compositor == null) { _compositor = Window.Current.Compositor; _generator = _compositor.CreateCompositionGenerator(); _defaultSize = new Vector2(GridWidth, GridWidth); // Create the original output image visual _originalImageVisual = _compositor.CreateSpriteVisual(); _originalImageVisual.Size = _defaultSize; _imageSurface = await _generator.CreateImageSurfaceAsync(new Uri("ms-appx:///Assets/Images/cat.png"), _defaultSize.ToSize(), ImageSurfaceOptions.Default); _originalImageVisual.Brush = _compositor.CreateSurfaceBrush(_imageSurface); ElementCompositionPreview.SetElementChildVisual(OriginalOutputGrid, _originalImageVisual); // Create the source image visual _sourceImageVisual = _compositor.CreateSpriteVisual(); _sourceImageVisual.Size = _defaultSize; ElementCompositionPreview.SetElementChildVisual(ImageGrid, _sourceImageVisual); //Create the mask visual _maskVisual = _compositor.CreateSpriteVisual(); _maskVisual.Size = _defaultSize; ElementCompositionPreview.SetElementChildVisual(MaskGrid, _maskVisual); // Create the output visual _outputVisual = _compositor.CreateSpriteVisual(); _outputVisual.Size = _defaultSize; ElementCompositionPreview.SetElementChildVisual(OutputGrid, _outputVisual); } var selIndex = ImageList.SelectedIndex; if (selIndex == -1) { return; } var uri = _images.Values.ElementAt(selIndex); if (uri == null) { return; } var offset = OffsetSlider.Value.ToSingle(); var padding = new Thickness(offset); if (recreateSurface) { _sourceImageSurface = await _generator.CreateImageSurfaceAsync(uri, _defaultSize.ToSize(), ImageSurfaceOptions.Default); _imageMaskSurface = _generator.CreateImageMaskSurface(_sourceImageSurface, _defaultSize.ToSize(), padding, ImageSurfaceOptions.GetDefaultImageMaskOptionsForBlur(_blurRadius)); } else { _imageMaskSurface.Resize(_defaultSize.ToSize(), padding, ImageSurfaceOptions.GetDefaultImageMaskOptionsForBlur(_blurRadius)); } _sourceImageVisual.Brush = _compositor.CreateSurfaceBrush(_sourceImageSurface); _maskVisual.Brush = _compositor.CreateSurfaceBrush(_imageMaskSurface); var maskedBrush = _compositor.CreateMaskBrush(); maskedBrush.Source = _originalImageVisual.Brush; maskedBrush.Mask = _compositor.CreateSurfaceBrush(_imageMaskSurface); _outputVisual.Brush = maskedBrush; }
private void OnCanvasSizeChanged(object sender, Vector2 e) { _visual.Size = e; _currentImage.Size = e.ToSize(); SizeChanged?.Invoke(this, e); }
private void CreateTextAndBlendEffect(Vector2 sizeLightBounds) { // // Crete the effect graph, doing a hard light blend of the text over the // content already drawn into the backbuffer // IGraphicsEffect graphicsEffect = new BlendEffect() { Mode = BlendEffectMode.HardLight, Foreground = new CompositionEffectSourceParameter("Text"), Background = new CompositionEffectSourceParameter("Destination"), }; CompositionEffectFactory effectFactory = _compositor.CreateEffectFactory(graphicsEffect, null); CompositionEffectBrush brush = effectFactory.CreateBrush(); // Bind the destination brush brush.SetSourceParameter("Destination", _compositor.CreateBackdropBrush()); // // Create the text surface which we'll scroll over the image with the lighting effect // // Pick a nice size font depending on target size const float maxFontSize = 72; const float scaleFactor = 12; float fontSize = Math.Min(sizeLightBounds.X / scaleFactor, maxFontSize); // Create the text format description, then the surface CanvasTextFormat textFormat = new CanvasTextFormat { FontFamily = "Segoe UI", FontSize = fontSize, FontWeight = FontWeights.Bold, WordWrapping = CanvasWordWrapping.WholeWord, HorizontalAlignment = CanvasHorizontalAlignment.Center, VerticalAlignment = CanvasVerticalAlignment.Center }; string text = "Ein bisschen Frieden, ein bisschen Sonne\n" + "für diese Erde, auf der wir wohnen\n" + "Ein bisschen Frieden, ein bisschen Freude\n" + "ein bisschen Wärme, das wünsch' ich mir\n" + "Ein bisschen Frieden, ein bisschen Träumen\n" + "und dass die Menschen nicht so oft weinen\n" + "Ein bisschen Frieden, ein bisschen Liebe\n" + "dass ich die Hoffnung nie mehr verlier"; // Make the surface twice the height to give us room to scroll Vector2 surfaceSize = new Vector2(sizeLightBounds.X, 2f * sizeLightBounds.Y); ManagedSurface textSurface = ImageLoader.Instance.LoadText(text, surfaceSize.ToSize(), textFormat, Colors.White, Colors.Transparent); brush.SetSourceParameter("Text", textSurface.Brush); // Create the sprite and parent it to the panel with the clip _textSprite = _compositor.CreateSpriteVisual(); _textSprite.Size = surfaceSize; _textSprite.Brush = brush; ElementCompositionPreview.SetElementChildVisual(MyPanel, _textSprite); // Lastly, setup the slow scrolling animation of the text LinearEasingFunction linear = _compositor.CreateLinearEasingFunction(); Vector3KeyFrameAnimation offsetAnimation = _compositor.CreateVector3KeyFrameAnimation(); offsetAnimation.InsertKeyFrame(0f, new Vector3(0, 0, 0), linear); offsetAnimation.InsertKeyFrame(1f, new Vector3(0, -_textSprite.Size.Y * .5f, 0), linear); offsetAnimation.Duration = TimeSpan.FromMilliseconds(30000); offsetAnimation.IterationBehavior = AnimationIterationBehavior.Forever; _textSprite.StartAnimation("Offset", offsetAnimation); }
/// <summary> /// Handles the Arrange layout phase /// </summary> /// <param name="finalSize">Final Size of the control</param> /// <returns>Size</returns> protected override Size ArrangeOverride(Size finalSize) { if ((_compositor == null) || (_generator == null)) return base.ArrangeOverride(finalSize); if (Double.IsInfinity(finalSize.Width) || Double.IsInfinity(finalSize.Height) || Double.IsNaN(finalSize.Width) || Double.IsNaN(finalSize.Height)) return base.ArrangeOverride(finalSize); // Stop the animations and dispose the previous nodes // and their animations if (_isAnimationStarted) { for (var i = 0; i < _nodes.Count; i++) { _nodes[i].StopAnimation(AnimatedProperty); _animations[i].Dispose(); _animations[i] = null; _nodes[i].Dispose(); _nodes[i] = null; } _container.StopAnimation(AnimatedProperty); _containerAnimation.Dispose(); _containerAnimation = null; _container.Dispose(); _container = null; _animations.Clear(); _nodes.Clear(); _isAnimationStarted = false; } // Validate MaxNodes and ActiveNodes if ((MaxNodes <= 0) || (ActiveNodes <= 0)) return finalSize; // Coerce ActiveNodes to MaxNodes if ActiveNodes > MaxNodes if (ActiveNodes > MaxNodes) ActiveNodes = MaxNodes; // Take the smallest of the width or height var sideLength = (float)Math.Min(finalSize.Width, finalSize.Height); // Size of the progress ring displayed _ringSize = new Vector2(sideLength, sideLength); var sideHalf = sideLength / 2f; // Radius of each node _nodeRadius = (float)NodeSizeFactor * sideHalf; // Size of each node _nodeSize = new Vector2(_nodeRadius * 2f, _nodeRadius * 2f); // Radius of the node _ringRadius = sideHalf - _nodeRadius; // Each animation will consist of '_maxFrameBlocks' number of // FrameBlocks. Each FrameBlock will consist of keyframes which allow // the element being animated to move to the next slot and wait // at that slot until all other elements have moved to their next slot. // Each FrameBlock (except the last one) will have '_maxFramesPerBlock' // number of keyframes. The last keyframe in the last FrameBlock // will always be (1f, "this.StartingValue + 360") // Total number of FrameBlocks in each animation _maxFrameBlocks = ActiveNodes; // Total keyframes in each FrameBlock _maxFramesPerBlock = ActiveNodes + 1; // Total keyframes in each animation _maxKeyFrames = _maxFrameBlocks * _maxFramesPerBlock; // Normalized Progress Key unit value for each keyframe _keyFrameSlice = 1f / _maxKeyFrames; // ======================================================================== // NOTE: // gamma * maxNodes = 360 // gamma = alpha + beta // beta = 2 * Asin(nodeRadius / ringRadius) * (180 / Math.PI) // invisibleNodes = MaxNodes - ActiveNodes // phi = (invisibleNodes * gamma) // theta = phi - beta // ======================================================================== // gamma is the angle between adjacent nodes when maxNodes number of nodes are arranged in a circle _gamma = 360f / MaxNodes; // beta is the angle a node must travel after hitting the adjacent node _beta = 2f * (float)(Math.Asin(_nodeRadius / _ringRadius) * (180f / Math.PI)); // alpha is the smallest angle a node must travel before hitting the adjacent node _alpha = _gamma - _beta; // phi is the angle occupied by (MaxNodes - ActiveNodes) number of nodes _phi = (MaxNodes - ActiveNodes + 1) * _gamma; // theta is the largest angle a node must travel before hitting the adjacent node _theta = _phi - _beta; // Create the Animations _animations = CreateAnimations(); // Create the Container _container = _compositor.CreateContainerVisual(); _container.Size = _ringSize; _container.Offset = new Vector3(((float)finalSize.Width - sideLength) / 2f, ((float)finalSize.Height - sideLength) / 2f, 0f); _container.CenterPoint = new Vector3(_ringSize.X / 2f, _ringSize.Y / 2f, 0f); // Create the Nodes var offset = new Vector3(_nodeRadius, _ringSize.Y / 2f, 0); var centerPoint = new Vector3(_ringSize.X / 2f - _nodeRadius, 0, 0); _nodes = new List<SpriteVisual>(); var geometry = CanvasGeometry.CreateCircle(_generator.Device, new Vector2(_nodeRadius, _nodeRadius), _nodeRadius); // Create/Update the nodeMask var color = NodeColor; if (_nodeMask == null) { //Task.Run(async () => // { _nodeMask = _generator.CreateGeometrySurface(_nodeSize.ToSize(), geometry, color); // }) //.Wait(); } else { //Task.Run(async () => // { _nodeMask.Redraw(_nodeSize.ToSize(), geometry, color); // }) //.Wait(); } // Create the SurfaceBrush for the nodes var brush = _compositor.CreateSurfaceBrush(_nodeMask.Surface); var baseAngle = 0f; // Create the visuals for the nodes for (var i = 0; i < _maxFramesPerBlock; i++) { var node = _compositor.CreateSpriteVisual(); node.Size = _nodeSize; node.AnchorPoint = new Vector2(0.5f); node.Offset = offset; node.CenterPoint = centerPoint; node.Brush = brush; node.RotationAngleInDegrees = baseAngle; if (i == 0) { baseAngle += _phi; } else if (i == _maxFramesPerBlock - 2) { baseAngle = -_beta; } else { baseAngle += _gamma; } _nodes.Add(node); // Add the visual to the container _container.Children.InsertAtTop(node); } // Add the container to the Visual Tree ElementCompositionPreview.SetElementChildVisual(this, _container); // Start Node animations for (var i = 0; i < _maxFramesPerBlock; i++) { _nodes[i].StartAnimation(AnimatedProperty, _animations[i]); } // Start container animation _containerAnimation = _compositor.CreateScalarKeyFrameAnimation(); _containerAnimation.InsertExpressionKeyFrame(1f, "this.StartingValue + 360f", _compositor.CreateLinearEasingFunction()); _containerAnimation.Duration = RingDuration; _containerAnimation.IterationBehavior = AnimationIterationBehavior.Forever; _container.StartAnimation(AnimatedProperty, _containerAnimation); _isAnimationStarted = true; return finalSize; }
/// <summary> /// Handles the Arrange layout phase /// </summary> /// <param name="finalSize">Final Size of the control</param> /// <returns>Size</returns> protected override Size ArrangeOverride(Size finalSize) { if ((_compositor == null) || (_generator == null)) { return(base.ArrangeOverride(finalSize)); } if (Double.IsInfinity(finalSize.Width) || Double.IsInfinity(finalSize.Height) || Double.IsNaN(finalSize.Width) || Double.IsNaN(finalSize.Height)) { return(base.ArrangeOverride(finalSize)); } // Stop the animations and dispose the previous nodes // and their animations if (_isAnimationStarted) { for (var i = 0; i < _nodes.Count; i++) { _nodes[i].StopAnimation(AnimatedProperty); _animations[i].Dispose(); _animations[i] = null; _nodes[i].Dispose(); _nodes[i] = null; } _container.StopAnimation(AnimatedProperty); _containerAnimation.Dispose(); _containerAnimation = null; _container.Dispose(); _container = null; _animations.Clear(); _nodes.Clear(); _isAnimationStarted = false; } // Validate MaxNodes and ActiveNodes if ((MaxNodes <= 0) || (ActiveNodes <= 0)) { return(finalSize); } // Coerce ActiveNodes to MaxNodes if ActiveNodes > MaxNodes if (ActiveNodes > MaxNodes) { ActiveNodes = MaxNodes; } // Take the smallest of the width or height var sideLength = (float)Math.Min(finalSize.Width, finalSize.Height); // Size of the progress ring displayed _ringSize = new Vector2(sideLength, sideLength); var sideHalf = sideLength / 2f; // Radius of each node _nodeRadius = (float)NodeSizeFactor * sideHalf; // Size of each node _nodeSize = new Vector2(_nodeRadius * 2f, _nodeRadius * 2f); // Radius of the node _ringRadius = sideHalf - _nodeRadius; // Each animation will consist of '_maxFrameBlocks' number of // FrameBlocks. Each FrameBlock will consist of keyframes which allow // the element being animated to move to the next slot and wait // at that slot until all other elements have moved to their next slot. // Each FrameBlock (except the last one) will have '_maxFramesPerBlock' // number of keyframes. The last keyframe in the last FrameBlock // will always be (1f, "this.StartingValue + 360") // Total number of FrameBlocks in each animation _maxFrameBlocks = ActiveNodes; // Total keyframes in each FrameBlock _maxFramesPerBlock = ActiveNodes + 1; // Total keyframes in each animation _maxKeyFrames = _maxFrameBlocks * _maxFramesPerBlock; // Normalized Progress Key unit value for each keyframe _keyFrameSlice = 1f / _maxKeyFrames; // ======================================================================== // NOTE: // gamma * maxNodes = 360 // gamma = alpha + beta // beta = 2 * Asin(nodeRadius / ringRadius) * (180 / Math.PI) // invisibleNodes = MaxNodes - ActiveNodes // phi = (invisibleNodes * gamma) // theta = phi - beta // ======================================================================== // gamma is the angle between adjacent nodes when maxNodes number of nodes are arranged in a circle _gamma = 360f / MaxNodes; // beta is the angle a node must travel after hitting the adjacent node _beta = 2f * (float)(Math.Asin(_nodeRadius / _ringRadius) * (180f / Math.PI)); // alpha is the smallest angle a node must travel before hitting the adjacent node _alpha = _gamma - _beta; // phi is the angle occupied by (MaxNodes - ActiveNodes) number of nodes _phi = (MaxNodes - ActiveNodes + 1) * _gamma; // theta is the largest angle a node must travel before hitting the adjacent node _theta = _phi - _beta; // Create the Animations _animations = CreateAnimations(); // Create the Container _container = _compositor.CreateContainerVisual(); _container.Size = _ringSize; _container.Offset = new Vector3(((float)finalSize.Width - sideLength) / 2f, ((float)finalSize.Height - sideLength) / 2f, 0f); _container.CenterPoint = new Vector3(_ringSize.X / 2f, _ringSize.Y / 2f, 0f); // Create the Nodes var offset = new Vector3(_nodeRadius, _ringSize.Y / 2f, 0); var centerPoint = new Vector3(_ringSize.X / 2f - _nodeRadius, 0, 0); _nodes = new List <SpriteVisual>(); var geometry = CanvasGeometry.CreateCircle(_generator.Device, new Vector2(_nodeRadius, _nodeRadius), _nodeRadius); // Create/Update the nodeMask var color = NodeColor; if (_nodeMask == null) { //Task.Run(async () => // { _nodeMask = _generator.CreateGeometrySurface(_nodeSize.ToSize(), geometry, color); // }) //.Wait(); } else { //Task.Run(async () => // { _nodeMask.Redraw(_nodeSize.ToSize(), geometry, color); // }) //.Wait(); } // Create the SurfaceBrush for the nodes var brush = _compositor.CreateSurfaceBrush(_nodeMask.Surface); var baseAngle = 0f; // Create the visuals for the nodes for (var i = 0; i < _maxFramesPerBlock; i++) { var node = _compositor.CreateSpriteVisual(); node.Size = _nodeSize; node.AnchorPoint = new Vector2(0.5f); node.Offset = offset; node.CenterPoint = centerPoint; node.Brush = brush; node.RotationAngleInDegrees = baseAngle; if (i == 0) { baseAngle += _phi; } else if (i == _maxFramesPerBlock - 2) { baseAngle = -_beta; } else { baseAngle += _gamma; } _nodes.Add(node); // Add the visual to the container _container.Children.InsertAtTop(node); } // Add the container to the Visual Tree ElementCompositionPreview.SetElementChildVisual(this, _container); // Start Node animations for (var i = 0; i < _maxFramesPerBlock; i++) { _nodes[i].StartAnimation(AnimatedProperty, _animations[i]); } // Start container animation _containerAnimation = _compositor.CreateScalarKeyFrameAnimation(); _containerAnimation.InsertExpressionKeyFrame(1f, "this.StartingValue + 360f", _compositor.CreateLinearEasingFunction()); _containerAnimation.Duration = RingDuration; _containerAnimation.IterationBehavior = AnimationIterationBehavior.Forever; _container.StartAnimation(AnimatedProperty, _containerAnimation); _isAnimationStarted = true; return(finalSize); }
/// <summary> /// Handles the Arrange pass during Layout /// </summary> /// <param name="finalSize">Final Size of the control</param> /// <returns>Total size occupied by the Children</returns> protected override Size ArrangeOverride(Size finalSize) { // Taking into account the BorderThickness and Padding var borders = BorderThickness; var padding = Padding; var corners = CornerRadius; var borderSize = borders.CollapseThickness(); var paddingSize = padding.CollapseThickness(); // Calculate the Offset for the frameVisual var left = (borders.Left + padding.Left).Single(); var top = (borders.Top + padding.Top).Single(); // Calculate the Dimensions of the frameVisual var width = Math.Max(0, finalSize.Width - borderSize.Width - paddingSize.Width).Single(); var height = Math.Max(0, finalSize.Height - borderSize.Height - paddingSize.Height).Single(); // Set the Size and Offset of visuals in the ImageFrame var frameSize = new Vector2(width, height); _rootContainer.Size = frameSize; _frameLayer.Size = frameSize; _frameBackgroundVisual.Size = frameSize; _frameContentVisual.Size = frameSize; _placeholderContentVisual.Size = frameSize; _placeholderBackgroundVisual.Size = frameSize; _shadowVisual.Size = frameSize; _nextVisualContent.Size = frameSize; _rootContainer.Offset = new Vector3(left, top, 0); // Update the frameLayerMask in case the CornerRadius or // BorderThickness or Padding has changed var pathInfo = new CompositionPathInfo(corners, borders, padding, false); using (var geometry = CompositionGenerator.GenerateGeometry(_generator.Device, frameSize.ToSize(), pathInfo, Vector2.Zero)) { _frameLayerMask.Redraw(_frameLayer.Size.ToSize(), geometry); } // If the FrameBackground has changed since the last time it was // applied to the frameBackgroundVisual, then animate the brush's // color to the new color. var brush = _frameBackgroundVisual.Brush as CompositionColorBrush; if (brush != null) { if (!brush.Color.Equals(FrameBackground)) { // If we are rendering fast, then no need to animate. // Just set the final value. if (RenderFast) { brush.Color = FrameBackground; } else { _colorAnimation.InsertKeyFrame(1f, FrameBackground); brush.StartAnimation("Color", _colorAnimation); } } } // If the PlaceholderBackground has changed since the last time it was // applied to the _placeholderBackgroundVisual, then update the brush's // color to the new color. brush = _placeholderBackgroundVisual.Brush as CompositionColorBrush; if (brush != null) { if (!brush.Color.Equals(PlaceholderBackground)) { brush.Color = PlaceholderBackground; } } // Redraw the placeholder content with the latest placeholder color _placeholderContentMask.Redraw(PlaceholderColor, PlaceholderBackground); // Set the stretch property of placeholder content's brush according to its size if ((width > PlaceholderSize.Width) && (height > PlaceholderSize.Height)) { _placeholderContentBrush.Stretch = CompositionStretch.None; } else { _placeholderContentBrush.Stretch = CompositionStretch.Uniform; } // Update the imageOptions _imageOptions.Stretch = Stretch; _imageOptions.HorizontalAlignment = AlignX; _imageOptions.VerticalAlignment = AlignY; _imageOptions.Interpolation = Interpolation; _imageOptions.SurfaceBackgroundColor = Colors.Transparent; _imageOptions.AutoResize = !RenderOptimized; // If Source is valid then try loading/refreshing the ImageSurface if (Source != null) { if (_imageSurface != null) { // Resize the ImageSurface to the new size _imageSurface.Resize(frameSize.ToSize(), _imageOptions); // Update the surface brush based on the Stretch and Alignment options if (RenderFast) { // Use no animations to update alignment if we are rendering fast (_frameContentVisual.Brush as CompositionSurfaceBrush)?.UpdateSurfaceBrushOptions(Stretch, AlignX, AlignY); } else { // Update stretch and alignment using animation (_frameContentVisual.Brush as CompositionSurfaceBrush)?.UpdateSurfaceBrushOptions(Stretch, AlignX, AlignY, _alignXAnimation, _alignYAnimation); } } else { // Load the Source to the ImageSurface ScheduleNextLoad(); } } else { // If the frameContentVisual had any previous brush, fade it out if (_imageSurface == null) { // Make the frameVisualContent transparent _frameContentVisual.Brush = _compositor.CreateColorBrush(Colors.Transparent); DisplayPlaceHolder(); _engineState = ImageEngineState.Idle; } } // Handle shadow if (DisplayShadow) { // If OptimizeShadow is True then use the sharedShadow otherwise use the instance shadow var shadow = OptimizeShadow ? ShadowProvider.GetSharedShadow(_compositor) : (_shadow ?? (_shadow = _compositor.CreateDropShadow())); shadow.BlurRadius = ShadowBlurRadius.Single(); shadow.Color = ShadowColor; shadow.Offset = new Vector3(ShadowOffsetX.Single(), ShadowOffsetY.Single(), 0); shadow.Opacity = ShadowOpacity.Single(); shadow.Mask = _layerEffectBrush.GetSourceParameter("mask"); _shadowVisual.Shadow = shadow; } else { _shadowVisual.Shadow = null; } return base.ArrangeOverride(finalSize); }