diff --git a/Samples/Islands/DrawingIsland/DrawingCppTestApp/DrawingCppTestApp.vcxproj b/Samples/Islands/DrawingIsland/DrawingCppTestApp/DrawingCppTestApp.vcxproj index 3643e885c..58bafb3e0 100644 --- a/Samples/Islands/DrawingIsland/DrawingCppTestApp/DrawingCppTestApp.vcxproj +++ b/Samples/Islands/DrawingIsland/DrawingCppTestApp/DrawingCppTestApp.vcxproj @@ -1,6 +1,6 @@ - + @@ -133,7 +133,8 @@ - + + @@ -143,7 +144,8 @@ - - + + + \ No newline at end of file diff --git a/Samples/Islands/DrawingIsland/DrawingCppTestApp/WinMain.cpp b/Samples/Islands/DrawingIsland/DrawingCppTestApp/WinMain.cpp index 31315d8ac..dfbd303c7 100644 --- a/Samples/Islands/DrawingIsland/DrawingCppTestApp/WinMain.cpp +++ b/Samples/Islands/DrawingIsland/DrawingCppTestApp/WinMain.cpp @@ -21,8 +21,7 @@ int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int) auto controller{ winrt::DispatcherQueueController::CreateOnCurrentThread() }; auto queue = controller.DispatcherQueue(); - // Associating the AppWindow with the DispatcherQueue on which the ContentIsland is created - // will ensure that the ContentIsland is Closed when the AppWindow closes. + // Associate the AppWindow's lifetime with the DispatcherQueue to automatically close on exit. auto window = winrt::AppWindow::Create(); window.AssociateWithDispatcherQueue(queue); window.Closing( @@ -35,20 +34,21 @@ int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int) window.Title(L"Drawing C++ TestApp"); window.Show(); - // Create the Island content in the window. - auto compositor = winrt::Compositor(); - auto island = winrt::DrawingIsland(compositor).Island(); - +#pragma region ... // Create a ContentSiteBridge and connect the ContentIsland to it. + auto compositor = winrt::Compositor(); auto siteBridge = winrt::DesktopChildSiteBridge::Create(compositor, window.Id()); siteBridge.ResizePolicy(winrt::ContentSizePolicy::ResizeContentToParentWindow); siteBridge.Show(); + + auto island = winrt::DrawingIsland(compositor).Island(); siteBridge.Connect(island); // Move initial focus to the ContentIsland. auto focusNavigationHost = winrt::InputFocusNavigationHost::GetForSiteBridge(siteBridge); focusNavigationHost.NavigateFocus(winrt::FocusNavigationRequest::Create( winrt::FocusNavigationReason::Programmatic)); +#pragma endregion queue.RunEventLoop(); diff --git a/Samples/Islands/DrawingIsland/DrawingCppTestApp/packages.config b/Samples/Islands/DrawingIsland/DrawingCppTestApp/packages.config index 02e8fb621..229c2d189 100644 --- a/Samples/Islands/DrawingIsland/DrawingCppTestApp/packages.config +++ b/Samples/Islands/DrawingIsland/DrawingCppTestApp/packages.config @@ -1,6 +1,7 @@  + - + \ No newline at end of file diff --git a/Samples/Islands/DrawingIsland/DrawingCsTestApp/DrawingCsTestApp.csproj b/Samples/Islands/DrawingIsland/DrawingCsTestApp/DrawingCsTestApp.csproj index 13b109104..e34e270eb 100644 --- a/Samples/Islands/DrawingIsland/DrawingCsTestApp/DrawingCsTestApp.csproj +++ b/Samples/Islands/DrawingIsland/DrawingCsTestApp/DrawingCsTestApp.csproj @@ -26,6 +26,10 @@ False + + + + diff --git a/Samples/Islands/DrawingIsland/DrawingCsTestApp/Program.cs b/Samples/Islands/DrawingIsland/DrawingCsTestApp/Program.cs index 75f5cea3f..a9071b376 100644 --- a/Samples/Islands/DrawingIsland/DrawingCsTestApp/Program.cs +++ b/Samples/Islands/DrawingIsland/DrawingCsTestApp/Program.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +#region Using directives using Microsoft.UI.Composition; using Microsoft.UI.Content; using Microsoft.UI.Dispatching; @@ -8,55 +9,44 @@ using Microsoft.UI.Windowing; using DrawingIslandComponents; +#endregion var controller = DispatcherQueueController.CreateOnCurrentThread(); var queue = controller.DispatcherQueue; +// Associate the AppWindow's lifetime with the DispatcherQueue to automatically close on exit. var window = AppWindow.Create(); window.AssociateWithDispatcherQueue(queue); window.Closing +=(sender, args) => { + // Ensure the DispatcherQueue exits the event loop on close. queue.EnqueueEventLoopExit(); }; window.Title = "Drawing C# .NET TestApp"; window.Show(); +#region ... +// Create a ContentSiteBridge and connect Island content into it. var compositor = new Compositor(); - var siteBridge = DesktopChildSiteBridge.Create(compositor, window.Id); siteBridge.ResizePolicy = ContentSizePolicy.ResizeContentToParentWindow; siteBridge.Show(); -if (args.Contains("Lottie")) -{ - // LottieIsland - var lottie = LottieIslandScenario.CreateLottieIsland(compositor); - siteBridge.Connect(lottie.Island); -} -else if (args.Contains("Duck")) -{ - // SceneNodeIsland - var island = DuckScenario.CreateIsland(compositor); - siteBridge.Connect(island); -} -else if (args.Contains("Helmet")) -{ - // SceneNodeIsland - var island = HelmetScenario.CreateIsland(compositor); - siteBridge.Connect(island); -} -else -{ - // DrawingIsland - var drawing = new DrawingIsland(compositor); - siteBridge.Connect(drawing.Island); -} +var lottie = LottieIslandScenario.CreateLottieIsland(compositor); +siteBridge.Connect(lottie.Island); + +#region ... +//var island = HelmetScenario.CreateIsland(compositor); +//siteBridge.Connect(island); + +#endregion // Move initial focus to the island. var focusNavigationHost = InputFocusNavigationHost.GetForSiteBridge(siteBridge); focusNavigationHost.NavigateFocus(FocusNavigationRequest.Create( FocusNavigationReason.Programmatic)); +#endregion queue.RunEventLoop(); diff --git a/Samples/Islands/DrawingIsland/DrawingIslandComponents/DrawingIslandComponents.vcxproj b/Samples/Islands/DrawingIsland/DrawingIslandComponents/DrawingIslandComponents.vcxproj index 8fa5e8bb5..c817eed95 100644 --- a/Samples/Islands/DrawingIsland/DrawingIslandComponents/DrawingIslandComponents.vcxproj +++ b/Samples/Islands/DrawingIsland/DrawingIslandComponents/DrawingIslandComponents.vcxproj @@ -1,6 +1,6 @@ - + @@ -171,7 +171,8 @@ - + + @@ -182,7 +183,8 @@ - - + + + \ No newline at end of file diff --git a/Samples/Islands/DrawingIsland/DrawingIslandComponents/packages.config b/Samples/Islands/DrawingIsland/DrawingIslandComponents/packages.config index c4397c325..8401faf51 100644 --- a/Samples/Islands/DrawingIsland/DrawingIslandComponents/packages.config +++ b/Samples/Islands/DrawingIsland/DrawingIslandComponents/packages.config @@ -1,7 +1,8 @@  + - + \ No newline at end of file diff --git a/Samples/Islands/WpfCalculator/CalculatorDemo/App.config b/Samples/Islands/WpfCalculator/CalculatorDemo/App.config new file mode 100644 index 000000000..51fffc74b --- /dev/null +++ b/Samples/Islands/WpfCalculator/CalculatorDemo/App.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Samples/Islands/WpfCalculator/CalculatorDemo/App.cs b/Samples/Islands/WpfCalculator/CalculatorDemo/App.cs new file mode 100644 index 000000000..82f967ced --- /dev/null +++ b/Samples/Islands/WpfCalculator/CalculatorDemo/App.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Windows; + +namespace CalculatorDemo +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + + } +} diff --git a/Samples/Islands/WpfCalculator/CalculatorDemo/App.xaml b/Samples/Islands/WpfCalculator/CalculatorDemo/App.xaml new file mode 100644 index 000000000..cf39a75c8 --- /dev/null +++ b/Samples/Islands/WpfCalculator/CalculatorDemo/App.xaml @@ -0,0 +1,17 @@ + + + + + + diff --git a/Samples/Islands/WpfCalculator/CalculatorDemo/App_Demo3.cs b/Samples/Islands/WpfCalculator/CalculatorDemo/App_Demo3.cs new file mode 100644 index 000000000..4de9aa9f2 --- /dev/null +++ b/Samples/Islands/WpfCalculator/CalculatorDemo/App_Demo3.cs @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Windows; +using Microsoft.UI.Dispatching; + +// Demo3_Step1_AddWasdk +namespace CalculatorDemo +{ + public partial class App : Application + { + // Many WinAppSDK APIs require a DispatcherQueue to be running on the thread. We'll start + // one when the app starts up and shut it down when the app is finished. + protected override void OnStartup(StartupEventArgs e) + { + _dispatcherQueueController = DispatcherQueueController.CreateOnCurrentThread(); + base.OnStartup(e); + } + + protected override void OnExit(ExitEventArgs e) + { + base.OnExit(e); + _dispatcherQueueController?.ShutdownQueue(); + _dispatcherQueueController = null; + } + + DispatcherQueueController? _dispatcherQueueController; + } +} diff --git a/Samples/Islands/WpfCalculator/CalculatorDemo/CalculatorDemo.csproj b/Samples/Islands/WpfCalculator/CalculatorDemo/CalculatorDemo.csproj new file mode 100644 index 000000000..0ed7d78dc --- /dev/null +++ b/Samples/Islands/WpfCalculator/CalculatorDemo/CalculatorDemo.csproj @@ -0,0 +1,185 @@ + + + + net9.0-windows10.0.22621.0 + true + false + x64;ARM64;x86 + + + win-x64;win-x86;win-arm64 + + + false + false + true + + + Debug + x64 + {5731865D-6685-47A7-8877-5DBAF39B54CD} + WinExe + Properties + CalculatorDemo + CalculatorDemo + 512 + 4 + true + 10.0.17763.0 + app.manifest + + + x86 + true + portable + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + ARM64 + true + portable + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + x64 + true + portable + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + x86 + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + ARM64 + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + x64 + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + App.xaml + Code + + + + + + + + + + + + + + + + + MainWindow.xaml + Code + + + + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Samples/Islands/WpfCalculator/CalculatorDemo/Extra/HelmetScenario.cs b/Samples/Islands/WpfCalculator/CalculatorDemo/Extra/HelmetScenario.cs new file mode 100644 index 000000000..68b5799e8 --- /dev/null +++ b/Samples/Islands/WpfCalculator/CalculatorDemo/Extra/HelmetScenario.cs @@ -0,0 +1,155 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Numerics; +using System.Runtime.InteropServices; + +using Windows.Foundation; +using Windows.Graphics; +using Windows.Storage; +using Windows.Storage.Streams; + +using Microsoft.Graphics.Canvas; +using Microsoft.Graphics.Canvas.UI.Composition; +using Microsoft.Graphics.DirectX; +using Microsoft.UI.Composition; +using Microsoft.UI.Composition.Scenes; +using Microsoft.UI.Content; +using System.Threading.Tasks; + +class HelmetScenario +{ + public static async Task CreateIsland(Compositor compositor) + { + var visual = await LoadScene_DamagedHelmet(compositor); + + var island = ContentIsland.Create(visual); + return island; + } + + private static async Task LoadScene_DamagedHelmet(Compositor compositor) + { + // Initialize Win2D, used for loading bitmaps. + + var canvasDevice = new CanvasDevice(); + var graphicsDevice = CanvasComposition.CreateCompositionGraphicsDevice( + compositor, canvasDevice); + + + // Create the Visuals and SceneNode structure, along with default rotation animations. + + var sceneVisual = SceneVisual.Create(compositor); + sceneVisual.RelativeOffsetAdjustment = new Vector3(0.5f, 0.5f, 0.0f); + + var worldNode = SceneNode.Create(compositor); + sceneVisual.Root = worldNode; + + var rotateAngleAnimation = compositor.CreateScalarKeyFrameAnimation(); + rotateAngleAnimation.InsertKeyFrame(0.0f, 0.0f); + rotateAngleAnimation.InsertKeyFrame(0.5f, 360.0f); + rotateAngleAnimation.InsertKeyFrame(1.0f, 0.0f); + rotateAngleAnimation.Duration = TimeSpan.FromSeconds(15); + rotateAngleAnimation.IterationBehavior = AnimationIterationBehavior.Forever; + worldNode.Transform.RotationAxis = new Vector3(0, 1, 0); + worldNode.Transform.StartAnimation("RotationAngleInDegrees", rotateAngleAnimation); + + var sceneNode0 = SceneNode.Create(compositor); + sceneNode0.Transform.Scale = new Vector3(350); + sceneNode0.Transform.Orientation = new Quaternion(0.70710683f, 0.0f, 0.0f, 0.70710683f); + worldNode.Children.Add(sceneNode0); + + var sceneNodeForTheGLTFMesh0 = SceneNode.Create(compositor); + sceneNode0.Children.Add(sceneNodeForTheGLTFMesh0); + + + // Load all file data in parallel: + // - Although Scene Graph objects prefer a UI thread, Win2D can load and create the bitmaps + // on parallel background threads. + + var vertexData = await SceneNodeCommon.LoadMemoryBufferFromUriAsync( + new Uri("ms-appx:///Assets/SceneNode/DamagedHelmet6.bin")); + + var normalData = await SceneNodeCommon.LoadMemoryBufferFromUriAsync( + new Uri("ms-appx:///Assets/SceneNode/DamagedHelmet7.bin")); + + var texCoordData = await SceneNodeCommon.LoadMemoryBufferFromUriAsync( + new Uri("ms-appx:///Assets/SceneNode/DamagedHelmet8.bin")); + + var indexData = await SceneNodeCommon.LoadMemoryBufferFromUriAsync( + new Uri("ms-appx:///Assets/SceneNode/DamagedHelmet9.bin")); + + //Task.WaitAll( + // vertexData, normalData, texCoordData, indexData); + + var canvasBitmap0 = await CanvasBitmap.LoadAsync( + canvasDevice, new Uri("ms-appx:///Assets/SceneNode/DamagedHelmet1.bmp")); + + var canvasBitmap1 = await CanvasBitmap.LoadAsync( + canvasDevice, new Uri("ms-appx:///Assets/SceneNode/DamagedHelmet2.bmp")); + + var canvasBitmap2 = await CanvasBitmap.LoadAsync( + canvasDevice, new Uri("ms-appx:///Assets/SceneNode/DamagedHelmet3.bmp")); + + var canvasBitmap3 = await CanvasBitmap.LoadAsync( + canvasDevice, new Uri("ms-appx:///Assets/SceneNode/DamagedHelmet4.bmp")); + + var canvasBitmap4 = await CanvasBitmap.LoadAsync( + canvasDevice, new Uri("ms-appx:///Assets/SceneNode/DamagedHelmet5.bmp")); + + + // Generate mipmaps from the bitmaps, which are needed for 3D rendering. + + var materialInput0 = SceneNodeCommon.LoadMipmapFromBitmap(graphicsDevice, canvasBitmap0); + var materialInput1 = SceneNodeCommon.LoadMipmapFromBitmap(graphicsDevice, canvasBitmap1); + var materialInput2 = SceneNodeCommon.LoadMipmapFromBitmap(graphicsDevice, canvasBitmap2); + var materialInput3 = SceneNodeCommon.LoadMipmapFromBitmap(graphicsDevice, canvasBitmap3); + var materialInput4 = SceneNodeCommon.LoadMipmapFromBitmap(graphicsDevice, canvasBitmap4); + + + // Copy loaded binary data into mesh: verticies, normals, ... + + var mesh0 = SceneMesh.Create(compositor); + mesh0.PrimitiveTopology = DirectXPrimitiveTopology.TriangleList; + mesh0.FillMeshAttribute(SceneAttributeSemantic.Vertex, DirectXPixelFormat.R32G32B32Float, vertexData); + mesh0.FillMeshAttribute(SceneAttributeSemantic.Normal, DirectXPixelFormat.R32G32B32Float, normalData); + mesh0.FillMeshAttribute(SceneAttributeSemantic.TexCoord0, DirectXPixelFormat.R32G32Float, texCoordData); + mesh0.FillMeshAttribute(SceneAttributeSemantic.Index, DirectXPixelFormat.R16UInt, indexData); + + + // Initialize the material with different texture inputs (color, roughness, normals, ...) + + var sceneMaterial0 = SceneMetallicRoughnessMaterial.Create(compositor); + + var renderComponent0 = SceneMeshRendererComponent.Create(compositor); + renderComponent0.Mesh = mesh0; + renderComponent0.Material = sceneMaterial0; + sceneNodeForTheGLTFMesh0.Components.Add(renderComponent0); + + sceneMaterial0.BaseColorFactor = new Vector4(1.0f, 1.0f, 1.0f, 1.0f); + sceneMaterial0.BaseColorInput = SceneNodeCommon.CreateMaterial( + compositor, materialInput0, renderComponent0, "BaseColorInput"); ; + + sceneMaterial0.RoughnessFactor = 1.0f; + sceneMaterial0.MetallicFactor = 1.0f; + sceneMaterial0.MetallicRoughnessInput = SceneNodeCommon.CreateMaterial( + compositor, materialInput1, renderComponent0, "MetallicRoughnessInput"); + + sceneMaterial0.NormalScale = 1.0f; + sceneMaterial0.NormalInput = SceneNodeCommon.CreateMaterial( + compositor, materialInput2, renderComponent0, "NormalInput"); + + sceneMaterial0.OcclusionStrength = 1.0f; + sceneMaterial0.OcclusionInput = SceneNodeCommon.CreateMaterial( + compositor, materialInput3, renderComponent0, "OcclusionInput"); + + sceneMaterial0.AlphaMode = SceneAlphaMode.Opaque; + sceneMaterial0.IsDoubleSided = false; + sceneMaterial0.EmissiveFactor = new Vector3(1.0f, 1.0f, 1.0f); + sceneMaterial0.EmissiveInput = SceneNodeCommon.CreateMaterial( + compositor, materialInput4, renderComponent0, "EmissiveInput"); + + return sceneVisual; + } +} diff --git a/Samples/Islands/WpfCalculator/CalculatorDemo/Extra/MainWindow_Demo4_Extra.cs b/Samples/Islands/WpfCalculator/CalculatorDemo/Extra/MainWindow_Demo4_Extra.cs new file mode 100644 index 000000000..15ac7d4b9 --- /dev/null +++ b/Samples/Islands/WpfCalculator/CalculatorDemo/Extra/MainWindow_Demo4_Extra.cs @@ -0,0 +1,28 @@ +// // Copyright (c) Microsoft. All rights reserved. +// // Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Windows; + +namespace CalculatorDemo +{ + public sealed partial class MainWindow : Window + { + private void CreateDrawingIslandMenuItem_Click(object sender, RoutedEventArgs e) + { + var wpfIslandHost = new WpfIslandHost(_compositor); + var drawingIsland = new DrawingIslandComponents.DrawingIsland(_compositor); + + DisplayAreaBorder.Child = wpfIslandHost; + wpfIslandHost.DesktopChildSiteBridge.Connect(drawingIsland.Island); + } + + private async void CreateSceneNodeIslandMenuItem_Click(object sender, RoutedEventArgs e) + { + var wpfIslandHost = new WpfIslandHost(_compositor); + var helmetIsland = await HelmetScenario.CreateIsland(_compositor); + + DisplayAreaBorder.Child = wpfIslandHost; + wpfIslandHost.DesktopChildSiteBridge.Connect(helmetIsland); + } + } +} diff --git a/Samples/Islands/WpfCalculator/CalculatorDemo/Extra/SceneNodeCommon.cs b/Samples/Islands/WpfCalculator/CalculatorDemo/Extra/SceneNodeCommon.cs new file mode 100644 index 000000000..d18bc4d7e --- /dev/null +++ b/Samples/Islands/WpfCalculator/CalculatorDemo/Extra/SceneNodeCommon.cs @@ -0,0 +1,127 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using Windows.Foundation; +using Windows.Storage.Streams; +using Windows.Storage; +using WinRT; +using Microsoft.Graphics.Canvas.UI.Composition; +using Microsoft.Graphics.Canvas; +using Microsoft.Graphics.DirectX; +using Microsoft.UI.Composition; +using Microsoft.UI.Composition.Scenes; +using Windows.Graphics; + +class SceneNodeCommon +{ + public static CompositionMipmapSurface LoadMipmapFromBitmap( + CompositionGraphicsDevice graphicsDevice, CanvasBitmap canvasBitmap) + { + var size = new SizeInt32(2048, 2048); + var mipmapSurface = graphicsDevice.CreateMipmapSurface( + size, + DirectXPixelFormat.B8G8R8A8UIntNormalized, + DirectXAlphaMode.Premultiplied); + + var drawDestRect = new Rect(0, 0, size.Width, size.Height); + var drawSourceRect = new Rect(0, 0, size.Width, size.Height); + for (uint level = 0; level < mipmapSurface.LevelCount; ++level) + { + // Draw the image to the surface + var drawingSurface = mipmapSurface.GetDrawingSurfaceForLevel(level); + + using (var session = CanvasComposition.CreateDrawingSession(drawingSurface)) + { + session.Clear(Windows.UI.Color.FromArgb(0, 0, 0, 0)); + session.DrawImage(canvasBitmap, drawDestRect, drawSourceRect); + } + + drawDestRect = new Rect(0, 0, drawDestRect.Width / 2, drawDestRect.Height / 2); + } + + return mipmapSurface; + } + + public static SceneSurfaceMaterialInput CreateMaterial( + Compositor compositor, + CompositionMipmapSurface mipmap, + SceneMeshRendererComponent rendererComponent, + string mapping) + { + var materialInput = SceneSurfaceMaterialInput.Create(compositor); + materialInput.Surface = mipmap; + materialInput.BitmapInterpolationMode = + CompositionBitmapInterpolationMode.MagLinearMinLinearMipLinear; + + materialInput.WrappingUMode = SceneWrappingMode.Repeat; + materialInput.WrappingVMode = SceneWrappingMode.Repeat; + + rendererComponent.UVMappings[mapping] = SceneAttributeSemantic.TexCoord0; + + return materialInput; + } + + public static async Task LoadMemoryBufferFromUriAsync(Uri uri) + { + var file = await StorageFile.GetFileFromApplicationUriAsync(uri); + var buffer = await FileIO.ReadBufferAsync(file); + + return CopyToMemoryBuffer(buffer); + } + + public static MemoryBuffer CopyToMemoryBuffer(IBuffer buffer) + { + var dataReader = DataReader.FromBuffer(buffer); + + var memBuffer = new MemoryBuffer(buffer.Length); + var memBufferRef = memBuffer.CreateReference(); + var memBufferByteAccess = memBufferRef.As(); + + unsafe + { + byte* bytes = null; + uint capacity; + memBufferByteAccess.GetBuffer(&bytes, &capacity); + + for (int i = 0; i < capacity; ++i) + { + bytes[i] = dataReader.ReadByte(); + } + } + + return memBuffer; + } + + + public static MemoryBuffer CopyToMemoryBuffer(byte[] a) + { + MemoryBuffer mb = new MemoryBuffer((uint)a.Length); + var mbr = mb.CreateReference(); + var mba = mbr.As(); + unsafe + { + byte* bytes = null; + uint capacity; + mba.GetBuffer(&bytes, &capacity); + for (int i = 0; i < capacity; ++i) + { + bytes[i] = a[i]; + } + } + + return mb; + } + + + + [ComImport, + Guid("5b0d3235-4dba-4d44-865e-8f1d0e4fd04d"), + InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IMemoryBufferByteAccess + { + unsafe void GetBuffer(byte** bytes, uint* capacity); + } +} diff --git a/Samples/Islands/WpfCalculator/CalculatorDemo/LottieIslandScenario.cs b/Samples/Islands/WpfCalculator/CalculatorDemo/LottieIslandScenario.cs new file mode 100644 index 000000000..0e47e4dd9 --- /dev/null +++ b/Samples/Islands/WpfCalculator/CalculatorDemo/LottieIslandScenario.cs @@ -0,0 +1,38 @@ +using System; +using Microsoft.UI.Composition; +using CommunityToolkit.WinAppSDK.LottieIsland; +using CommunityToolkit.WinAppSDK.LottieWinRT; + +// Demo4_Step1_LottieIsland +class LottieIslandScenario +{ + public static LottieContentIsland CreateLottieIsland(Compositor compositor) + { + var lottieIsland = LottieContentIsland.Create(compositor); + var lottieVisualSource = LottieVisualSourceWinRT.CreateFromString( + "ms-appx:///Assets/LottieLogo1.json"); + + if (lottieVisualSource != null) + { + lottieVisualSource.AnimatedVisualInvalidated += (sender, args) => + { + object? diagnostics = null; + IAnimatedVisualFrameworkless? animatedVisual = + lottieVisualSource.TryCreateAnimatedVisual(compositor, out diagnostics); + + if (animatedVisual != null) + { + // This callback comes back on a different thread, so set the AnimatedVisual on + // the UI thread + compositor.DispatcherQueue.TryEnqueue(async () => + { + lottieIsland.AnimatedVisual = animatedVisual; + await lottieIsland.PlayAsync(0, 1, true); + }); + } + }; + } + + return lottieIsland; + } +} \ No newline at end of file diff --git a/Samples/Islands/WpfCalculator/CalculatorDemo/MainWindow.cs b/Samples/Islands/WpfCalculator/CalculatorDemo/MainWindow.cs new file mode 100644 index 000000000..c3b690bd2 --- /dev/null +++ b/Samples/Islands/WpfCalculator/CalculatorDemo/MainWindow.cs @@ -0,0 +1,449 @@ +// // Copyright (c) Microsoft. All rights reserved. +// // Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Globalization; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Interop; +using Windows.ApplicationModel.Contacts; + +namespace CalculatorDemo +{ + /// + /// Interaction logic for MainWindow.xaml + /// + public sealed partial class MainWindow : Window + { + private static PaperTrail _paper; + private Operation _lastOper; + private string _lastVal; + private string _memVal; + public MainWindow() + { + InitializeComponent(); + _paper = new PaperTrail(this); + ProcessKey('0'); + EraseDisplay = true; + } + + /// + /// Flag to erase or just add to current display flag + /// + private bool EraseDisplay { get; set; } + + /// + /// Get/Set Memory cell value + /// + private double Memory + { + get + { + if (_memVal == string.Empty) + return 0.0; + return Convert.ToDouble(_memVal); + } + set { _memVal = value.ToString(CultureInfo.InvariantCulture); } + } + + //Lats value entered + private string LastValue + { + get + { + if (_lastVal == string.Empty) + return "0"; + return _lastVal; + } + set { _lastVal = value; } + } + + //The current Calculator display + private string Display { get; set; } + // Sample event handler: + private void OnWindowKeyDown(object sender, TextCompositionEventArgs /*System.Windows.Input.KeyEventArgs*/ e) + { + var s = e.Text; + var c = (s.ToCharArray())[0]; + e.Handled = true; + + if ((c >= '0' && c <= '9') || c == '.' || c == '\b') // '\b' is backspace + { + ProcessKey(c); + return; + } + switch (c) + { + case '+': + ProcessOperation("BPlus"); + break; + case '-': + ProcessOperation("BMinus"); + break; + case '*': + ProcessOperation("BMultiply"); + break; + case '/': + ProcessOperation("BDevide"); + break; + case '%': + ProcessOperation("BPercent"); + break; + case '=': + ProcessOperation("BEqual"); + break; + } + } + + private void DigitBtn_Click(object sender, RoutedEventArgs e) + { + var s = ((Button) sender).Content.ToString(); + + //char[] ids = ((Button)sender).ID.ToCharArray(); + var ids = s.ToCharArray(); + ProcessKey(ids[0]); + } + + private void ProcessKey(char c) + { + if (EraseDisplay) + { + Display = string.Empty; + EraseDisplay = false; + } + AddToDisplay(c); + } + + private void ProcessOperation(string s) + { + var d = 0.0; + switch (s) + { + case "BPM": + _lastOper = Operation.Negate; + LastValue = Display; + CalcResults(); + LastValue = Display; + EraseDisplay = true; + _lastOper = Operation.None; + break; + case "BDevide": + + if (EraseDisplay) //stil wait for a digit... + { + //stil wait for a digit... + _lastOper = Operation.Devide; + break; + } + CalcResults(); + _lastOper = Operation.Devide; + LastValue = Display; + EraseDisplay = true; + break; + case "BMultiply": + if (EraseDisplay) //stil wait for a digit... + { + //stil wait for a digit... + _lastOper = Operation.Multiply; + break; + } + CalcResults(); + _lastOper = Operation.Multiply; + LastValue = Display; + EraseDisplay = true; + break; + case "BMinus": + if (EraseDisplay) //stil wait for a digit... + { + //stil wait for a digit... + _lastOper = Operation.Subtract; + break; + } + CalcResults(); + _lastOper = Operation.Subtract; + LastValue = Display; + EraseDisplay = true; + break; + case "BPlus": + if (EraseDisplay) + { + //stil wait for a digit... + _lastOper = Operation.Add; + break; + } + CalcResults(); + _lastOper = Operation.Add; + LastValue = Display; + EraseDisplay = true; + break; + case "BEqual": + if (EraseDisplay) //stil wait for a digit... + break; + CalcResults(); + EraseDisplay = true; + _lastOper = Operation.None; + LastValue = Display; + //val = Display; + break; + case "BSqrt": + _lastOper = Operation.Sqrt; + LastValue = Display; + CalcResults(); + LastValue = Display; + EraseDisplay = true; + _lastOper = Operation.None; + break; + case "BPercent": + if (EraseDisplay) //stil wait for a digit... + { + //stil wait for a digit... + _lastOper = Operation.Percent; + break; + } + CalcResults(); + _lastOper = Operation.Percent; + LastValue = Display; + EraseDisplay = true; + //LastOper = Operation.None; + break; + case "BOneOver": + _lastOper = Operation.OneX; + LastValue = Display; + CalcResults(); + LastValue = Display; + EraseDisplay = true; + _lastOper = Operation.None; + break; + case "BC": //clear All + _lastOper = Operation.None; + Display = LastValue = string.Empty; + _paper.Clear(); + UpdateDisplay(); + break; + case "BCE": //clear entry + _lastOper = Operation.None; + Display = LastValue; + UpdateDisplay(); + break; + case "BMemClear": + Memory = 0.0F; + DisplayMemory(); + break; + case "BMemSave": + Memory = Convert.ToDouble(Display); + DisplayMemory(); + EraseDisplay = true; + break; + case "BMemRecall": + Display = /*val =*/ Memory.ToString(CultureInfo.InvariantCulture); + UpdateDisplay(); + //if (LastOper != Operation.None) //using MR is like entring a digit + EraseDisplay = false; + break; + case "BMemPlus": + d = Memory + Convert.ToDouble(Display); + Memory = d; + DisplayMemory(); + EraseDisplay = true; + break; + } + } + + private void OperBtn_Click(object sender, RoutedEventArgs e) + { + ProcessOperation(((Button) sender).Name.Replace("_c","")); + } + + private double Calc(Operation lastOper) + { + var d = 0.0; + + + try + { + switch (lastOper) + { + case Operation.Devide: + _paper.AddArguments(LastValue + " / " + Display); + d = (Convert.ToDouble(LastValue)/Convert.ToDouble(Display)); + CheckResult(d); + _paper.AddResult(d.ToString(CultureInfo.InvariantCulture)); + break; + case Operation.Add: + _paper.AddArguments(LastValue + " + " + Display); + d = Convert.ToDouble(LastValue) + Convert.ToDouble(Display); + CheckResult(d); + _paper.AddResult(d.ToString(CultureInfo.InvariantCulture)); + break; + case Operation.Multiply: + _paper.AddArguments(LastValue + " * " + Display); + d = Convert.ToDouble(LastValue)*Convert.ToDouble(Display); + CheckResult(d); + _paper.AddResult(d.ToString(CultureInfo.InvariantCulture)); + break; + case Operation.Percent: + //Note: this is different (but make more sense) then Windows calculator + _paper.AddArguments(LastValue + " % " + Display); + d = (Convert.ToDouble(LastValue)*Convert.ToDouble(Display))/100.0F; + CheckResult(d); + _paper.AddResult(d.ToString(CultureInfo.InvariantCulture)); + break; + case Operation.Subtract: + _paper.AddArguments(LastValue + " - " + Display); + d = Convert.ToDouble(LastValue) - Convert.ToDouble(Display); + CheckResult(d); + _paper.AddResult(d.ToString(CultureInfo.InvariantCulture)); + break; + case Operation.Sqrt: + _paper.AddArguments("Sqrt( " + LastValue + " )"); + d = Math.Sqrt(Convert.ToDouble(LastValue)); + CheckResult(d); + _paper.AddResult(d.ToString(CultureInfo.InvariantCulture)); + break; + case Operation.OneX: + _paper.AddArguments("1 / " + LastValue); + d = 1.0F/Convert.ToDouble(LastValue); + CheckResult(d); + _paper.AddResult(d.ToString(CultureInfo.InvariantCulture)); + break; + case Operation.Negate: + d = Convert.ToDouble(LastValue)*(-1.0F); + break; + } + } + catch + { + d = 0; + var parent = (Window) MyPanel.Parent; + _paper.AddResult("Error"); + MessageBox.Show(parent, "Operation cannot be perfomed", parent.Title); + } + + return d; + } + + private void CheckResult(double d) + { + if (double.IsNegativeInfinity(d) || double.IsPositiveInfinity(d) || double.IsNaN(d)) + throw new Exception("Illegal value"); + } + + private void DisplayMemory() + { + if (_memVal != string.Empty) + BMemBox.Text = "Memory: " + _memVal; + else + BMemBox.Text = "Memory: [empty]"; + } + + private void CalcResults() + { + double d; + if (_lastOper == Operation.None) + return; + + d = Calc(_lastOper); + Display = d.ToString(CultureInfo.InvariantCulture); + + UpdateDisplay(); + } + + private void UpdateDisplay() + { + DisplayBox.Text = Display == string.Empty ? "0" : Display; + } + + private void AddToDisplay(char c) + { + if (c == '.') + { + if (Display.IndexOf('.', 0) >= 0) //already exists + return; + Display = Display + c; + } + else + { + if (c >= '0' && c <= '9') + { + Display = Display + c; + } + else if (c == '\b') //backspace ? + { + if (Display.Length <= 1) + Display = string.Empty; + else + { + var i = Display.Length; + Display = Display.Remove(i - 1, 1); //remove last char + } + } + } + + UpdateDisplay(); + } + + private void OnMenuAbout(object sender, RoutedEventArgs e) + { + var parent = (Window) MyPanel.Parent; + MessageBox.Show(parent, parent.Title + " - By Jossef Goldberg ", parent.Title, MessageBoxButton.OK, + MessageBoxImage.Information); + } + + private void OnMenuExit(object sender, RoutedEventArgs e) + { + Close(); + } + + private void OnMenuStandard(object sender, RoutedEventArgs e) + { + //((MenuItem)ScientificMenu).IsChecked = false; + StandardMenu.IsChecked = true; //for now always Standard + } + + private void OnMenuScientific(object sender, RoutedEventArgs e) + { + //((MenuItem)StandardMenu).IsChecked = false; + } + + private enum Operation + { + None, + Devide, + Multiply, + Subtract, + Add, + Percent, + Sqrt, + OneX, + Negate + } + + private class PaperTrail + { + private readonly MainWindow _window; + private string _args; + + public PaperTrail(MainWindow window) + { + _window = window; + } + + public void AddArguments(string a) + { + _args = a; + } + + public void AddResult(string r) + { + _window.PaperBox.Text += _args + " = " + r + "\n"; + } + + public void Clear() + { + _window.PaperBox.Text = string.Empty; + _args = string.Empty; + } + } + } +} \ No newline at end of file diff --git a/Samples/Islands/WpfCalculator/CalculatorDemo/MainWindow.xaml b/Samples/Islands/WpfCalculator/CalculatorDemo/MainWindow.xaml new file mode 100644 index 000000000..66b489294 --- /dev/null +++ b/Samples/Islands/WpfCalculator/CalculatorDemo/MainWindow.xaml @@ -0,0 +1,169 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Memory: [empty] + + + + + + + + + + + + + + diff --git a/Samples/Islands/WpfCalculator/CalculatorDemo/MainWindow_Demo3.cs b/Samples/Islands/WpfCalculator/CalculatorDemo/MainWindow_Demo3.cs new file mode 100644 index 000000000..5429496dd --- /dev/null +++ b/Samples/Islands/WpfCalculator/CalculatorDemo/MainWindow_Demo3.cs @@ -0,0 +1,71 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Windows; +using System.Windows.Interop; + +using Microsoft.UI; +using Microsoft.UI.Windowing; + +// Demo3_Step2_AddCompact +namespace CalculatorDemo +{ + public sealed partial class MainWindow : Window + { + private AppWindow _appWindow; + + private void CompactView_Click(object sender, RoutedEventArgs e) + { + SetCompactView(true); + } + + private void ExitCompactViewButton_Click(object sender, RoutedEventArgs e) + { + SetCompactView(false); + } + + void SetCompactView(bool useCompactView) + { + // Ensure we have an AppWindow for this WPF Window. + if (_appWindow == null) + { + _appWindow = AppWindow.GetFromWindowId( + new WindowId((ulong)new WindowInteropHelper(this).Handle)); + } + + if (useCompactView) + { + // For compact view, hide the main panel and show the compact panel. + MyPanel.Visibility = Visibility.Collapsed; + CompactPanel.Visibility = Visibility.Visible; + + CompactViewText.Text = DisplayBox.Text; + + if (!_registeredEventHandler) + { + DisplayBox.TextChanged += DisplayBox_TextChanged; + _registeredEventHandler = true; + } + + // The AppWindow's CompactOverlay mode will make it always-on-top. + _appWindow.SetPresenter(AppWindowPresenterKind.CompactOverlay); + _appWindow.ResizeClient(new Windows.Graphics.SizeInt32(400, 400)); + } + else + { + MyPanel.Visibility = Visibility.Visible; + CompactPanel.Visibility = Visibility.Collapsed; + + _appWindow.SetPresenter(AppWindowPresenterKind.Default); + } + } + + private void DisplayBox_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e) + { + CompactViewText.Text = DisplayBox.Text; + } + + bool _registeredEventHandler = false; + } +} diff --git a/Samples/Islands/WpfCalculator/CalculatorDemo/MainWindow_Demo4.cs b/Samples/Islands/WpfCalculator/CalculatorDemo/MainWindow_Demo4.cs new file mode 100644 index 000000000..3a9cc46db --- /dev/null +++ b/Samples/Islands/WpfCalculator/CalculatorDemo/MainWindow_Demo4.cs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Windows; +using CommunityToolkit.WinAppSDK.LottieIsland; + +// Demo4_Step1_MainWindow +namespace CalculatorDemo +{ + public sealed partial class MainWindow : Window + { + private Microsoft.UI.Composition.Compositor _compositor = new(); + + private void CreateLottieIslandMenuItem_Click(object sender, RoutedEventArgs e) + { + var wpfIslandHost = new WpfIslandHost(_compositor); + var lottieContentIsland = LottieIslandScenario.CreateLottieIsland(_compositor); + + DisplayAreaBorder.Child = wpfIslandHost; + wpfIslandHost.DesktopChildSiteBridge.Connect(lottieContentIsland.Island); + } + } +} diff --git a/Samples/Islands/WpfCalculator/CalculatorDemo/MyTextBox.cs b/Samples/Islands/WpfCalculator/CalculatorDemo/MyTextBox.cs new file mode 100644 index 000000000..f42222459 --- /dev/null +++ b/Samples/Islands/WpfCalculator/CalculatorDemo/MyTextBox.cs @@ -0,0 +1,17 @@ +// // Copyright (c) Microsoft. All rights reserved. +// // Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Windows.Controls; +using System.Windows.Input; + +namespace CalculatorDemo +{ + internal sealed class MyTextBox : TextBox + { + protected override void OnPreviewGotKeyboardFocus(KeyboardFocusChangedEventArgs e) + { + e.Handled = true; + base.OnPreviewGotKeyboardFocus(e); + } + } +} \ No newline at end of file diff --git a/Samples/Islands/WpfCalculator/CalculatorDemo/Properties/AssemblyInfo.cs b/Samples/Islands/WpfCalculator/CalculatorDemo/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..5dcea412b --- /dev/null +++ b/Samples/Islands/WpfCalculator/CalculatorDemo/Properties/AssemblyInfo.cs @@ -0,0 +1,59 @@ +// // Copyright (c) Microsoft. All rights reserved. +// // Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Reflection; +using System.Runtime.InteropServices; +using System.Windows; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyTitle("CalculatorDemo")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("CalculatorDemo")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly: ComVisible(false)] + +//In order to begin building localizable applications, set +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) + )] + + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] + +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/Samples/Islands/WpfCalculator/CalculatorDemo/Properties/Resources.Designer.cs b/Samples/Islands/WpfCalculator/CalculatorDemo/Properties/Resources.Designer.cs new file mode 100644 index 000000000..66e92c0be --- /dev/null +++ b/Samples/Islands/WpfCalculator/CalculatorDemo/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace CalculatorDemo.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CalculatorDemo.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/Samples/Islands/WpfCalculator/CalculatorDemo/Properties/Resources.resx b/Samples/Islands/WpfCalculator/CalculatorDemo/Properties/Resources.resx new file mode 100644 index 000000000..af7dbebba --- /dev/null +++ b/Samples/Islands/WpfCalculator/CalculatorDemo/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Samples/Islands/WpfCalculator/CalculatorDemo/Properties/Settings.Designer.cs b/Samples/Islands/WpfCalculator/CalculatorDemo/Properties/Settings.Designer.cs new file mode 100644 index 000000000..0610885f1 --- /dev/null +++ b/Samples/Islands/WpfCalculator/CalculatorDemo/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace CalculatorDemo.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/Samples/Islands/WpfCalculator/CalculatorDemo/Properties/Settings.settings b/Samples/Islands/WpfCalculator/CalculatorDemo/Properties/Settings.settings new file mode 100644 index 000000000..c14891b94 --- /dev/null +++ b/Samples/Islands/WpfCalculator/CalculatorDemo/Properties/Settings.settings @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Samples/Islands/WpfCalculator/CalculatorDemo/WpfIslandHost.cs b/Samples/Islands/WpfCalculator/CalculatorDemo/WpfIslandHost.cs new file mode 100644 index 000000000..bae53d3fb --- /dev/null +++ b/Samples/Islands/WpfCalculator/CalculatorDemo/WpfIslandHost.cs @@ -0,0 +1,65 @@ +using System; +using System.Runtime.InteropServices; +using System.Windows.Interop; + +using Microsoft.UI; +using Microsoft.UI.Composition; +using Microsoft.UI.Content; + +// Demo4_Step1_IslandHost +namespace CalculatorDemo +{ + internal class WpfIslandHost : HwndHost + { + public WpfIslandHost(Compositor compositor) + { + _compositor = compositor; + } + + public DesktopChildSiteBridge DesktopChildSiteBridge { get; private set; } + + protected override HandleRef BuildWindowCore(HandleRef hwndParent) + { + DesktopChildSiteBridge = Microsoft.UI.Content.DesktopChildSiteBridge.Create( + _compositor, + new Microsoft.UI.WindowId((ulong)hwndParent.Handle)); + + // Mark as a layered window to handle transparent HWND with WPF. + var hwndChild = Win32Interop.GetWindowFromWindowId(DesktopChildSiteBridge.WindowId); + int prevExStyleFlags = GetWindowLong(hwndChild, GWL_EXSTYLE); + SetWindowLongPtr( + hwndChild, + GWL_EXSTYLE, + new IntPtr(prevExStyleFlags | WS_EX_LAYERED)); + + return new HandleRef(null, (nint)DesktopChildSiteBridge.WindowId.Value); + } + + protected override void DestroyWindowCore(HandleRef hwnd) + { + DesktopChildSiteBridge.Dispose(); + DesktopChildSiteBridge = null; + } + + Microsoft.UI.Composition.Compositor _compositor; + +#region P/Invokes + + const int GWL_EXSTYLE = -20; + const int WS_EX_LAYERED = 0x00080000; + + [DllImport("user32.dll")] + static extern int GetWindowLong( + IntPtr hwnd, + int index); + + [DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool SetWindowLongPtr( + IntPtr hWnd, + int nIndex, + IntPtr dwNewLong); + +#endregion + } +} diff --git a/Samples/Islands/WpfCalculator/CalculatorDemo/app.manifest b/Samples/Islands/WpfCalculator/CalculatorDemo/app.manifest new file mode 100644 index 000000000..f78afe4b5 --- /dev/null +++ b/Samples/Islands/WpfCalculator/CalculatorDemo/app.manifest @@ -0,0 +1,15 @@ + + + + + + + + true + PerMonitorV2 + + + diff --git a/Samples/Islands/WpfCalculator/CalculatorDemo/appicon.ico b/Samples/Islands/WpfCalculator/CalculatorDemo/appicon.ico new file mode 100644 index 000000000..2cec3ddd0 Binary files /dev/null and b/Samples/Islands/WpfCalculator/CalculatorDemo/appicon.ico differ diff --git a/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/LottieLogo1.json b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/LottieLogo1.json new file mode 100644 index 000000000..cb637e3ea --- /dev/null +++ b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/LottieLogo1.json @@ -0,0 +1,7390 @@ +{ + "assets": [], + "layers": [ + { + "ddd": 0, + "ind": 0, + "ty": 1, + "nm": "MASTER", + "ks": { + "o": { "k": 0 }, + "r": { "k": 0 }, + "p": { "k": [ 214.457, 347.822, 0 ] }, + "a": { "k": [ 60, 60, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "sw": 120, + "sh": 120, + "sc": "#ffffff", + "ip": 12, + "op": 179, + "st": 0, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 1, + "ty": 4, + "nm": "S5-Y 4", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": -89.1 }, + "p": { "k": [ 53.205, 131.606, 0 ] }, + "a": { "k": [ 0, 0, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "v": [ + [ 142.038, 29.278 ], + [ 131.282, 21.807 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 76, + "s": [ 87 ], + "e": [ 50.633 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 79, + "s": [ 50.633 ], + "e": [ 0 ] + }, + { "t": 83 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 76, + "s": [ 100 ], + "e": [ 75.856 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 79, + "s": [ 75.856 ], + "e": [ 0 ] + }, + { "t": 83 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 2 }, + "lc": 2, + "lj": 1, + "ml": 4, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 0, 0 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Shape 1" + } + ], + "ip": 76, + "op": 84, + "st": 40, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 2, + "ty": 4, + "nm": "S4-Y 4", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": -89.1 }, + "p": { "k": [ 53.205, 131.606, 0 ] }, + "a": { "k": [ 0, 0, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "v": [ + [ 142.183, -5.112 ], + [ 130.029, 5.016 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 76, + "s": [ 87 ], + "e": [ 43.833 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 79, + "s": [ 43.833 ], + "e": [ 0 ] + }, + { "t": 83 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 76, + "s": [ 100 ], + "e": [ 66.356 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 79, + "s": [ 66.356 ], + "e": [ 0 ] + }, + { "t": 83 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 2 }, + "lc": 2, + "lj": 1, + "ml": 4, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 0, 0 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Shape 1" + } + ], + "ip": 76, + "op": 84, + "st": 40, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 3, + "ty": 4, + "nm": "S3-Y 4", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": -89.1 }, + "p": { "k": [ 53.205, 131.606, 0 ] }, + "a": { "k": [ 0, 0, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "v": [ + [ 147.699, 13.025 ], + [ 133.195, 13.21 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 76, + "s": [ 87 ], + "e": [ 42.133 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 79, + "s": [ 42.133 ], + "e": [ 0 ] + }, + { "t": 83 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 76, + "s": [ 100 ], + "e": [ 66.356 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 79, + "s": [ 66.356 ], + "e": [ 0 ] + }, + { "t": 83 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 2 }, + "lc": 2, + "lj": 1, + "ml": 4, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 0, 0 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Shape 1" + } + ], + "ip": 76, + "op": 84, + "st": 40, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 4, + "ty": 4, + "nm": "S5-Y 3", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 97.9 }, + "p": { "k": [ 58.205, -39.394, 0 ] }, + "a": { "k": [ 0, 0, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "v": [ + [ 145.677, 22.22 ], + [ 134.922, 14.749 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 75, + "s": [ 87 ], + "e": [ 50.633 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 78, + "s": [ 50.633 ], + "e": [ 0 ] + }, + { "t": 82 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 75, + "s": [ 100 ], + "e": [ 75.856 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 78, + "s": [ 75.856 ], + "e": [ 0 ] + }, + { "t": 82 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 2 }, + "lc": 2, + "lj": 1, + "ml": 4, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 0, 0 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Shape 1" + } + ], + "ip": 75, + "op": 83, + "st": 39, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 5, + "ty": 4, + "nm": "S4-Y 3", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 97.9 }, + "p": { "k": [ 58.205, -39.394, 0 ] }, + "a": { "k": [ 0, 0, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "v": [ + [ 144.429, -5.397 ], + [ 132.275, 4.731 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 75, + "s": [ 87 ], + "e": [ 43.833 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 78, + "s": [ 43.833 ], + "e": [ 0 ] + }, + { "t": 82 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 75, + "s": [ 100 ], + "e": [ 66.356 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 78, + "s": [ 66.356 ], + "e": [ 0 ] + }, + { "t": 82 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 2 }, + "lc": 2, + "lj": 1, + "ml": 4, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 0, 0 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Shape 1" + } + ], + "ip": 75, + "op": 83, + "st": 39, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 6, + "ty": 4, + "nm": "S3-Y 3", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 97.9 }, + "p": { "k": [ 58.205, -39.394, 0 ] }, + "a": { "k": [ 0, 0, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "v": [ + [ 149.624, 8.244 ], + [ 136.648, 10.156 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 75, + "s": [ 87 ], + "e": [ 42.133 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 78, + "s": [ 42.133 ], + "e": [ 0 ] + }, + { "t": 82 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 75, + "s": [ 100 ], + "e": [ 66.356 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 78, + "s": [ 66.356 ], + "e": [ 0 ] + }, + { "t": 82 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 2 }, + "lc": 2, + "lj": 1, + "ml": 4, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 0, 0 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Shape 1" + } + ], + "ip": 75, + "op": 83, + "st": 39, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 7, + "ty": 4, + "nm": "S13", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { "k": [ 25.043, 45.678, 0 ] }, + "a": { "k": [ 0, 0, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "v": [ + [ 128, 3.65 ], + [ 78.25, 3.5 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 85, + "s": [ 87 ], + "e": [ 21.233 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 90, + "s": [ 21.233 ], + "e": [ 0 ] + }, + { "t": 94 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 85, + "s": [ 100 ], + "e": [ 66.356 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 90, + "s": [ 66.356 ], + "e": [ 0 ] + }, + { "t": 94 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 1.5 }, + "lc": 2, + "lj": 1, + "ml": 4, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 0, 0 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Shape 1" + } + ], + "ip": 85, + "op": 95, + "st": 49, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 8, + "ty": 4, + "nm": "S12", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { "k": [ 25.043, 45.678, 0 ] }, + "a": { "k": [ 0, 0, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "v": [ + [ 119.25, -20.05 ], + [ 63.5, -20.5 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 84, + "s": [ 87 ], + "e": [ 21.233 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 87, + "s": [ 21.233 ], + "e": [ 0 ] + }, + { "t": 91 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 84, + "s": [ 100 ], + "e": [ 66.356 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 87, + "s": [ 66.356 ], + "e": [ 0 ] + }, + { "t": 91 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 1.5 }, + "lc": 2, + "lj": 1, + "ml": 4, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 0, 0 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Shape 1" + } + ], + "ip": 84, + "op": 94, + "st": 48, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 9, + "ty": 4, + "nm": "S11", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { "k": [ 25.043, 45.678, 0 ] }, + "a": { "k": [ 0, 0, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "v": [ + [ 119.5, -45.05 ], + [ 82.75, -44.75 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 80, + "s": [ 87 ], + "e": [ 21.233 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 83, + "s": [ 21.233 ], + "e": [ 0 ] + }, + { "t": 87 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 80, + "s": [ 100 ], + "e": [ 66.356 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 83, + "s": [ 66.356 ], + "e": [ 0 ] + }, + { "t": 87 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 1.5 }, + "lc": 2, + "lj": 1, + "ml": 4, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 0, 0 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Shape 1" + } + ], + "ip": 80, + "op": 90, + "st": 44, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 10, + "ty": 4, + "nm": "S5-Y 2", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { "k": [ 25.043, 45.678, 0 ] }, + "a": { "k": [ 0, 0, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "v": [ + [ 169.5, 18.073 ], + [ 137.481, 11.365 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 97, + "s": [ 87 ], + "e": [ 50.633 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 100, + "s": [ 50.633 ], + "e": [ 0 ] + }, + { "t": 107 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 97, + "s": [ 100 ], + "e": [ 75.856 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 100, + "s": [ 75.856 ], + "e": [ 0 ] + }, + { "t": 107 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 2 }, + "lc": 2, + "lj": 1, + "ml": 4, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 0, 0 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Shape 1" + } + ], + "ip": 97, + "op": 107, + "st": 61, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 11, + "ty": 4, + "nm": "S4-Y 2", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { "k": [ 25.043, 45.678, 0 ] }, + "a": { "k": [ 0, 0, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "v": [ + [ 156.45, -23.05 ], + [ 132, 2.75 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 97, + "s": [ 87 ], + "e": [ 43.833 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 100, + "s": [ 43.833 ], + "e": [ 0 ] + }, + { "t": 107 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 97, + "s": [ 100 ], + "e": [ 66.356 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 100, + "s": [ 66.356 ], + "e": [ 0 ] + }, + { "t": 107 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 2 }, + "lc": 2, + "lj": 1, + "ml": 4, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 0, 0 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Shape 1" + } + ], + "ip": 97, + "op": 107, + "st": 61, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 12, + "ty": 4, + "nm": "S3-Y 2", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { "k": [ 25.043, 45.678, 0 ] }, + "a": { "k": [ 0, 0, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "v": [ + [ 166.731, -7.927 ], + [ 136.731, 7.115 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 97, + "s": [ 87 ], + "e": [ 42.133 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 100, + "s": [ 42.133 ], + "e": [ 0 ] + }, + { "t": 107 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 97, + "s": [ 100 ], + "e": [ 66.356 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 100, + "s": [ 66.356 ], + "e": [ 0 ] + }, + { "t": 107 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 2 }, + "lc": 2, + "lj": 1, + "ml": 4, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 0, 0 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Shape 1" + } + ], + "ip": 97, + "op": 107, + "st": 61, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 13, + "ty": 4, + "nm": "S6-Y", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { "k": [ 25.043, 45.678, 0 ] }, + "a": { "k": [ 0, 0, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "v": [ + [ -87.5, 20.95 ], + [ -48.75, 54.75 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 54, + "s": [ 87 ], + "e": [ 43.933 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 57, + "s": [ 43.933 ], + "e": [ 0 ] + }, + { "t": 64 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 54, + "s": [ 100 ], + "e": [ 70.456 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 57, + "s": [ 70.456 ], + "e": [ 0 ] + }, + { "t": 64 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 2 }, + "lc": 2, + "lj": 1, + "ml": 4, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 0, 0 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Shape 1" + } + ], + "ip": 54, + "op": 64, + "st": 18, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 14, + "ty": 4, + "nm": "S5-Y", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { "k": [ 25.043, 45.678, 0 ] }, + "a": { "k": [ 0, 0, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "v": [ + [ -94.5, 37.073 ], + [ -48.769, 55.365 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 54, + "s": [ 87 ], + "e": [ 50.633 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 57, + "s": [ 50.633 ], + "e": [ 0 ] + }, + { "t": 64 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 54, + "s": [ 100 ], + "e": [ 75.856 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 57, + "s": [ 75.856 ], + "e": [ 0 ] + }, + { "t": 64 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 2 }, + "lc": 2, + "lj": 1, + "ml": 4, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 0, 0 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Shape 1" + } + ], + "ip": 54, + "op": 64, + "st": 18, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 15, + "ty": 4, + "nm": "S4-Y", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { "k": [ 25.043, 45.678, 0 ] }, + "a": { "k": [ 0, 0, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "v": [ + [ 7.45, 21.95 ], + [ -32.75, 55.75 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 54, + "s": [ 87 ], + "e": [ 43.833 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 57, + "s": [ 43.833 ], + "e": [ 0 ] + }, + { "t": 64 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 54, + "s": [ 100 ], + "e": [ 66.356 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 57, + "s": [ 66.356 ], + "e": [ 0 ] + }, + { "t": 64 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 2 }, + "lc": 2, + "lj": 1, + "ml": 4, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 0, 0 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Shape 1" + } + ], + "ip": 54, + "op": 64, + "st": 18, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 16, + "ty": 4, + "nm": "S3-Y", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { "k": [ 25.043, 45.678, 0 ] }, + "a": { "k": [ 0, 0, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "v": [ + [ 16.231, 39.073 ], + [ -32.769, 57.365 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 54, + "s": [ 87 ], + "e": [ 42.133 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 57, + "s": [ 42.133 ], + "e": [ 0 ] + }, + { "t": 64 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 54, + "s": [ 100 ], + "e": [ 66.356 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 57, + "s": [ 66.356 ], + "e": [ 0 ] + }, + { "t": 64 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 2 }, + "lc": 2, + "lj": 1, + "ml": 4, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 0, 0 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Shape 1" + } + ], + "ip": 54, + "op": 64, + "st": 18, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 17, + "ty": 4, + "nm": "S8", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { "k": [ 25.043, 45.678, 0 ] }, + "a": { "k": [ 0, 0, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ -0.148, 14.256 ], + [ 10.476, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ -8.551, -8.263 ], + [ -21.454, 0 ], + [ 0, 0 ] + ], + "v": [ + [ -3, 35.95 ], + [ -1.352, -6.756 ], + [ -32.046, -20.579 ], + [ -42.25, 4.25 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 65, + "s": [ 87 ], + "e": [ 21.233 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 70, + "s": [ 21.233 ], + "e": [ 0 ] + }, + { "t": 75 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 65, + "s": [ 100 ], + "e": [ 66.356 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 70, + "s": [ 66.356 ], + "e": [ 0 ] + }, + { "t": 75 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 1.5 }, + "lc": 2, + "lj": 1, + "ml": 4, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 0, 0 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Shape 1" + } + ], + "ip": 65, + "op": 75, + "st": 29, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 18, + "ty": 4, + "nm": "S7", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { "k": [ 25.043, 45.678, 0 ] }, + "a": { "k": [ 0, 0, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 27, 1.45 ], + [ 31.046, -1.421 ], + [ 0, 0 ] + ], + "o": [ + [ -27, -1.45 ], + [ -26.426, 1.21 ], + [ 0, 0 ] + ], + "v": [ + [ 34.5, -13.05 ], + [ -35.046, -35.579 ], + [ -62.25, -5.75 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 65, + "s": [ 87 ], + "e": [ 21.233 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 70, + "s": [ 21.233 ], + "e": [ 0 ] + }, + { "t": 75 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 65, + "s": [ 100 ], + "e": [ 66.356 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 70, + "s": [ 66.356 ], + "e": [ 0 ] + }, + { "t": 75 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 1.5 }, + "lc": 2, + "lj": 1, + "ml": 4, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 0, 0 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Shape 1" + } + ], + "ip": 65, + "op": 75, + "st": 29, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 19, + "ty": 4, + "nm": "S2-Y", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { "k": [ 25.043, 45.678, 0 ] }, + "a": { "k": [ 0, 0, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 1.9, -10.768 ], + [ 1, -19 ] + ], + "o": [ + [ 0, 0 ], + [ -3.167, 17.951 ], + [ -1, 19 ] + ], + "v": [ + [ -67.25, -105.5 ], + [ -72.333, -84.201 ], + [ -76.5, -37.75 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 29, + "s": [ 87 ], + "e": [ 25.333 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 33, + "s": [ 25.333 ], + "e": [ 0 ] + }, + { "t": 36 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 29, + "s": [ 100 ], + "e": [ 69.056 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 33, + "s": [ 69.056 ], + "e": [ 0 ] + }, + { "t": 36 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 1.5 }, + "lc": 2, + "lj": 1, + "ml": 4, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 0, 0 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Shape 1" + } + ], + "ip": 30, + "op": 37, + "st": -7, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 20, + "ty": 4, + "nm": "S1-Y", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { "k": [ 25.043, 45.678, 0 ] }, + "a": { "k": [ 0, 0, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 1.9, -10.768 ], + [ 1, -19 ] + ], + "o": [ + [ 0, 0 ], + [ -3.167, 17.951 ], + [ -1, 19 ] + ], + "v": [ + [ -67.125, -112 ], + [ -75.458, -89.951 ], + [ -80.375, -39.25 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 29, + "s": [ 87 ], + "e": [ 37.533 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 33, + "s": [ 37.533 ], + "e": [ 0 ] + }, + { "t": 36 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 29, + "s": [ 100 ], + "e": [ 66.356 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 33, + "s": [ 66.356 ], + "e": [ 0 ] + }, + { "t": 36 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 1.5 }, + "lc": 2, + "lj": 1, + "ml": 4, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 0, 0 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Shape 1" + } + ], + "ip": 30, + "op": 37, + "st": -7, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 21, + "ty": 4, + "nm": "Dot1", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { + "k": [ + { + "i": { + "x": 0.833, + "y": 0.833 + }, + "o": { + "x": 0.823, + "y": 0 + }, + "n": "0p833_0p833_0p823_0", + "t": -3, + "s": [ 295.771, 108.994, 0 ], + "e": [ 35.771, 108.994, 0 ], + "to": [ 0, 0, 0 ], + "ti": [ 0, 0, 0 ] + }, + { "t": 16 } + ] + }, + "a": { "k": [ 196.791, 266.504, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "d": 1, + "ty": "el", + "s": { "k": [ 9.4, 9.4 ] }, + "p": { "k": [ 0.8, -0.5 ] }, + "nm": "Ellipse Path 1" + }, + { + "ty": "fl", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "nm": "Fill 1" + }, + { + "ty": "tr", + "p": { + "k": [ 196, 267 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Ellipse 1" + } + ], + "ip": -5, + "op": 17, + "st": -36, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 22, + "ty": 4, + "nm": "L-B", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { "k": [ 39.043, 45.678, 0 ] }, + "a": { "k": [ 250, 250, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 25.671, -4.167 ], + [ 1.456, 6.902 ], + [ -8.481, 1.863 ], + [ -47.562, 13.01 ], + [ -0.501, 0.133 ], + [ -71.423, -2.315 ] + ], + "o": [ + [ 0, 0 ], + [ -8.224, 1.335 ], + [ -1.456, -6.903 ], + [ 23.817, -5.233 ], + [ 0.16, -0.044 ], + [ 0.501, -0.133 ], + [ 0, 0 ] + ], + "v": [ + [ -8.837, -58.229 ], + [ -35.834, 33.662 ], + [ -51.688, 23.148 ], + [ -41.174, 7.293 ], + [ 51.797, 44.178 ], + [ 53.188, 43.741 ], + [ 140.394, 43.672 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 0, 0.48, 0.53, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 9.194 }, + "lc": 2, + "lj": 1, + "ml": 10, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 166.029, 270.643 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 8" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.703 ], + "y": [ 0.821 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p703_0p821_0p167_0p167" ], + "t": 18, + "s": [ 80 ], + "e": [ 50 ] + }, + { + "i": { + "x": [ 0.263 ], + "y": [ 1 ] + }, + "o": { + "x": [ 0.037 ], + "y": [ 0.168 ] + }, + "n": [ "0p263_1_0p037_0p168" ], + "t": 23, + "s": [ 50 ], + "e": [ 30 ] + }, + { "t": 55 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.337 ], + "y": [ 1 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p337_1_0p167_0p167" ], + "t": 18, + "s": [ 81 ], + "e": [ 73.4 ] + }, + { "t": 29 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + } + ], + "ip": 18, + "op": 179, + "st": 8, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 23, + "ty": 4, + "nm": "L-Y", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { "k": [ 39.043, 45.678, 0 ] }, + "a": { "k": [ 250, 250, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 25.671, -4.167 ], + [ 1.456, 6.902 ], + [ -8.481, 1.863 ], + [ -47.562, 13.01 ], + [ -0.501, 0.133 ], + [ -71.423, -2.315 ] + ], + "o": [ + [ 0, 0 ], + [ -8.224, 1.335 ], + [ -1.456, -6.903 ], + [ 23.817, -5.233 ], + [ 0.16, -0.044 ], + [ 0.501, -0.133 ], + [ 0, 0 ] + ], + "v": [ + [ -8.837, -58.229 ], + [ -35.834, 33.662 ], + [ -51.688, 23.148 ], + [ -41.174, 7.293 ], + [ 51.797, 44.178 ], + [ 53.188, 43.741 ], + [ 140.394, 43.672 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 8.4 }, + "lc": 2, + "lj": 1, + "ml": 10, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 166.029, 270.643 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 8" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.703 ], + "y": [ 0.857 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p703_0p857_0p167_0p167" ], + "t": 16, + "s": [ 80 ], + "e": [ 50 ] + }, + { + "i": { + "x": [ 0.938 ], + "y": [ 1 ] + }, + "o": { + "x": [ 0.333 ], + "y": [ 0.202 ] + }, + "n": [ "0p938_1_0p333_0p202" ], + "t": 20, + "s": [ 50 ], + "e": [ 0 ] + }, + { "t": 28 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.337 ], + "y": [ 1 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p337_1_0p167_0p167" ], + "t": 16, + "s": [ 81 ], + "e": [ 73.4 ] + }, + { "t": 27 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + } + ], + "ip": 16, + "op": 179, + "st": 8, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 24, + "ty": 1, + "nm": "N", + "parent": 0, + "ks": { + "o": { "k": 0 }, + "r": { "k": 0 }, + "p": { + "k": [ + { + "i": { + "x": 0.26, + "y": 1 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "n": "0p26_1_0p167_0p167", + "t": 28, + "s": [ -33.667, 8.182, 0 ], + "e": [ -33.667, -72.818, 0 ], + "to": [ 0, 0, 0 ], + "ti": [ 0, 0, 0 ] + }, + { + "i": { + "x": 0.833, + "y": 0.833 + }, + "o": { + "x": 0.74, + "y": 0 + }, + "n": "0p833_0p833_0p74_0", + "t": 40, + "s": [ -33.667, -72.818, 0 ], + "e": [ -33.667, 102.057, 0 ], + "to": [ 0, 0, 0 ], + "ti": [ 0, 0, 0 ] + }, + { "t": 54 } + ] + }, + "a": { "k": [ 60, 60, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "sw": 120, + "sh": 120, + "sc": "#ffffff", + "ip": 28, + "op": 54, + "st": 0, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 25, + "ty": 4, + "nm": "Dot-Y", + "parent": 24, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { + "k": [ + { + "i": { + "x": 0.833, + "y": 0.833 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "n": "0p833_0p833_0p167_0p167", + "t": 28, + "s": [ 39.875, 60, 0 ], + "e": [ 79.375, 60, 0 ], + "to": [ 6.58333349227905, 0, 0 ], + "ti": [ -6.58333349227905, 0, 0 ] + }, + { "t": 54 } + ] + }, + "a": { "k": [ 196.791, 266.504, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "d": 1, + "ty": "el", + "s": { "k": [ 9.4, 9.4 ] }, + "p": { "k": [ 0.8, -0.5 ] }, + "nm": "Ellipse Path 1" + }, + { + "ty": "fl", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "nm": "Fill 1" + }, + { + "ty": "tr", + "p": { + "k": [ 196, 267 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Ellipse 1" + } + ], + "ip": 28, + "op": 54, + "st": 4, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 26, + "ty": 4, + "nm": "T1a-B", + "parent": 36, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { "k": [ 250, 250, 0 ] }, + "a": { "k": [ 250, 250, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ -0.5, 9.501 ], + [ -0.048, 5.655 ], + [ 0.054, 0.06 ], + [ 0.946, 1.486 ], + [ -9.967, 8.05 ], + [ -40.546, 0 ] + ], + "o": [ + [ 0.031, -0.594 ], + [ 0.076, -8.978 ], + [ -1.161, -1.3 ], + [ -5.939, -9.327 ], + [ 24.677, -19.929 ], + [ 0, 0 ] + ], + "v": [ + [ -30.72, 63.761 ], + [ -30.741, 45.192 ], + [ -37.397, 27.014 ], + [ -40.698, 22.661 ], + [ -37.873, -7.117 ], + [ 49.506, 11.559 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": 24.9, + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.673 ], + "y": [ 1 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p673_1_0p167_0p167" ], + "t": 70, + "s": [ 24.9 ], + "e": [ 89.1 ] + }, + { "t": 84 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 9.194 }, + "lc": 2, + "lj": 1, + "ml": 10, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 227.677, 234.375 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 9" + } + ], + "ip": 70, + "op": 179, + "st": 17, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 27, + "ty": 4, + "nm": "T2a-B", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { "k": [ 39.043, 45.678, 0 ] }, + "a": { "k": [ 250, 250, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "v": [ + [ 1.681, -29.992 ], + [ -1.681, 29.992 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.06 ], + "y": [ 1 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p06_1_0p167_0p167" ], + "t": 75, + "s": [ 50 ], + "e": [ 0 ] + }, + { "t": 85 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.06 ], + "y": [ 1 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p06_1_0p167_0p167" ], + "t": 75, + "s": [ 50 ], + "e": [ 100 ] + }, + { "t": 85 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 0, 0.48, 0.53, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 9.194 }, + "lc": 3, + "lj": 1, + "ml": 10, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 277.698, 247.258 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 7" + } + ], + "ip": 75, + "op": 179, + "st": 15, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 28, + "ty": 4, + "nm": "T1a-Y 2", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { + "k": [ + { + "i": { + "x": 0.667, + "y": 1 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "n": "0p667_1_0p167_0p167", + "t": 56, + "s": [ 39.043, 48.678, 0 ], + "e": [ 39.043, 45.678, 0 ], + "to": [ 0, 0, 0 ], + "ti": [ 0, 0, 0 ] + }, + { "t": 64 } + ] + }, + "a": { "k": [ 250, 250, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ -0.5, 9.501 ], + [ -0.048, 5.655 ], + [ 0.054, 0.06 ], + [ 0.946, 1.486 ], + [ -9.967, 8.05 ], + [ -40.546, 0 ] + ], + "o": [ + [ 0.031, -0.594 ], + [ 0.076, -8.978 ], + [ -1.161, -1.3 ], + [ -5.939, -9.327 ], + [ 24.677, -19.929 ], + [ 0, 0 ] + ], + "v": [ + [ -30.72, 63.761 ], + [ -30.741, 45.192 ], + [ -37.397, 27.014 ], + [ -40.698, 22.661 ], + [ -37.873, -7.117 ], + [ 49.506, 11.559 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 1 ] + }, + "o": { + "x": [ 0.301 ], + "y": [ 0 ] + }, + "n": [ "0p833_1_0p301_0" ], + "t": 54, + "s": [ 0 ], + "e": [ 24.9 ] + }, + { "t": 70 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.667 ], + "y": [ 1 ] + }, + "o": { + "x": [ 0.301 ], + "y": [ 0 ] + }, + "n": [ "0p667_1_0p301_0" ], + "t": 54, + "s": [ 0 ], + "e": [ 100 ] + }, + { "t": 78 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 0, 0.48, 0.53, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 8.4 }, + "lc": 2, + "lj": 1, + "ml": 10, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 227.677, 234.375 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 9" + } + ], + "ip": 59, + "op": 179, + "st": 12, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 29, + "ty": 4, + "nm": "O-B", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { + "k": [ + { + "i": { + "x": 0.833, + "y": 0.833 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "n": "0p833_0p833_0p167_0p167", + "t": 31, + "s": [ -62.792, 73.057, 0 ], + "e": [ -53.792, 7.557, 0 ], + "to": [ 0, 0, 0 ], + "ti": [ 0, 0, 0 ] + }, + { + "i": { + "x": 0.638, + "y": 1 + }, + "o": { + "x": 0.167, + "y": 0.198 + }, + "n": "0p638_1_0p167_0p198", + "t": 35.257, + "s": [ -53.792, 7.557, 0 ], + "e": [ -33.667, -72.818, 0 ], + "to": [ 0, 0, 0 ], + "ti": [ -19.1562919616699, 1.73831975460052, 0 ] + }, + { + "i": { + "x": 0.795, + "y": 1 + }, + "o": { + "x": 0.523, + "y": 0 + }, + "n": "0p795_1_0p523_0", + "t": 44, + "s": [ -33.667, -72.818, 0 ], + "e": [ -14.167, 102.182, 0 ], + "to": [ 16.2075271606445, -1.47073686122894, 0 ], + "ti": [ 0, 0, 0 ] + }, + { + "i": { + "x": 0.348, + "y": 1 + }, + "o": { + "x": 0.18, + "y": 0 + }, + "n": "0p348_1_0p18_0", + "t": 54, + "s": [ -14.167, 102.182, 0 ], + "e": [ -14.167, 59.182, 0 ], + "to": [ 0, 0, 0 ], + "ti": [ 0, 0, 0 ] + }, + { + "i": { + "x": 0.27, + "y": 1 + }, + "o": { + "x": 0.693, + "y": 0 + }, + "n": "0p27_1_0p693_0", + "t": 63, + "s": [ -14.167, 59.182, 0 ], + "e": [ -14.167, 62.182, 0 ], + "to": [ 0, 0, 0 ], + "ti": [ 0, 0, 0 ] + }, + { "t": 73 } + ] + }, + "a": { "k": [ 196.791, 266.504, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "d": 1, + "ty": "el", + "s": { + "k": [ + { + "i": { + "x": [ 0.667, 0.667 ], + "y": [ 1, 1 ] + }, + "o": { + "x": [ 0.333, 0.333 ], + "y": [ 0, 0 ] + }, + "n": [ "0p667_1_0p333_0", "0p667_1_0p333_0" ], + "t": 54, + "s": [ 3, 3 ], + "e": [ 44.6, 44.6 ] + }, + { "t": 61 } + ] + }, + "p": { "k": [ 0.8, -0.5 ] }, + "nm": "Ellipse Path 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 0, 0.48, 0.53, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 9.194 }, + "lc": 2, + "lj": 1, + "ml": 4, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 196, 267 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Ellipse 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 54, + "s": [ 0 ], + "e": [ 30 ] + }, + { + "i": { + "x": [ 0.432 ], + "y": [ 1 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 1.124 ] + }, + "n": [ "0p432_1_0p167_1p124" ], + "t": 63, + "s": [ 30 ], + "e": [ 39.9 ] + }, + { "t": 91 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 54, + "s": [ 100 ], + "e": [ 88 ] + }, + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 63, + "s": [ 88 ], + "e": [ 88 ] + }, + { "t": 91 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + } + ], + "ip": 54, + "op": 179, + "st": 4, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 30, + "ty": 4, + "nm": "O-Y", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { + "k": [ + { + "i": { + "x": 0.833, + "y": 0.833 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "n": "0p833_0p833_0p167_0p167", + "t": 31, + "s": [ -62.792, 73.057, 0 ], + "e": [ -53.792, 7.557, 0 ], + "to": [ 0, 0, 0 ], + "ti": [ 0, 0, 0 ] + }, + { + "i": { + "x": 0.638, + "y": 1 + }, + "o": { + "x": 0.167, + "y": 0.198 + }, + "n": "0p638_1_0p167_0p198", + "t": 35.257, + "s": [ -53.792, 7.557, 0 ], + "e": [ -33.667, -72.818, 0 ], + "to": [ 0, 0, 0 ], + "ti": [ -19.1562919616699, 1.73831975460052, 0 ] + }, + { + "i": { + "x": 0.795, + "y": 1 + }, + "o": { + "x": 0.523, + "y": 0 + }, + "n": "0p795_1_0p523_0", + "t": 44, + "s": [ -33.667, -72.818, 0 ], + "e": [ -14.167, 102.182, 0 ], + "to": [ 16.2075271606445, -1.47073686122894, 0 ], + "ti": [ 0, 0, 0 ] + }, + { + "i": { + "x": 0.348, + "y": 1 + }, + "o": { + "x": 0.18, + "y": 0 + }, + "n": "0p348_1_0p18_0", + "t": 54, + "s": [ -14.167, 102.182, 0 ], + "e": [ -14.167, 59.182, 0 ], + "to": [ 0, 0, 0 ], + "ti": [ 0, 0, 0 ] + }, + { + "i": { + "x": 0.27, + "y": 1 + }, + "o": { + "x": 0.693, + "y": 0 + }, + "n": "0p27_1_0p693_0", + "t": 63, + "s": [ -14.167, 59.182, 0 ], + "e": [ -14.167, 62.182, 0 ], + "to": [ 0, 0, 0 ], + "ti": [ 0, 0, 0 ] + }, + { "t": 73 } + ] + }, + "a": { "k": [ 196.791, 266.504, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "d": 1, + "ty": "el", + "s": { + "k": [ + { + "i": { + "x": [ 0.667, 0.667 ], + "y": [ 1, 1 ] + }, + "o": { + "x": [ 0.333, 0.333 ], + "y": [ 0, 0 ] + }, + "n": [ "0p667_1_0p333_0", "0p667_1_0p333_0" ], + "t": 54, + "s": [ 3, 3 ], + "e": [ 44.6, 44.6 ] + }, + { "t": 61 } + ] + }, + "p": { "k": [ 0.8, -0.5 ] }, + "nm": "Ellipse Path 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 8.8 }, + "lc": 1, + "lj": 1, + "ml": 4, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 196, 267 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Ellipse 1" + } + ], + "ip": 54, + "op": 179, + "st": 4, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 31, + "ty": 4, + "nm": "T1b-B", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { "k": [ 39.043, 45.678, 0 ] }, + "a": { "k": [ 250, 250, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "v": [ + [ 1.768, -25.966 ], + [ -1.768, 25.966 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": 0, + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.21 ], + "y": [ 1 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p21_1_0p167_0p167" ], + "t": 81, + "s": [ 11.7 ], + "e": [ 100 ] + }, + { "t": 88 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 9.194 }, + "lc": 2, + "lj": 2, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 242.756, 265.581 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 10" + } + ], + "ip": 81, + "op": 179, + "st": 26, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 32, + "ty": 4, + "nm": "T1b-Y", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { "k": [ 39.043, 45.678, 0 ] }, + "a": { "k": [ 250, 250, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "v": [ + [ 1.768, -25.966 ], + [ -1.768, 25.966 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 70, + "s": [ 0 ], + "e": [ 0 ] + }, + { "t": 75 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 70, + "s": [ 11.7 ], + "e": [ 100 ] + }, + { "t": 75 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 0, 0.48, 0.53, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 8.4 }, + "lc": 2, + "lj": 2, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 242.756, 265.581 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 10" + } + ], + "ip": 70, + "op": 161, + "st": 15, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 33, + "ty": 4, + "nm": "T2b-B", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { "k": [ 39.043, 45.678, 0 ] }, + "a": { "k": [ 250, 250, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "v": [ + [ 246.65, 213.814 ], + [ 340.956, 213.628 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.12 ], + "y": [ 1 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p12_1_0p167_0p167" ], + "t": 82, + "s": [ 29 ], + "e": [ 0 ] + }, + { "t": 91 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.12 ], + "y": [ 1 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p12_1_0p167_0p167" ], + "t": 82, + "s": [ 41.1 ], + "e": [ 66.5 ] + }, + { "t": 91 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 0, 0.48, 0.53, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 9.194 }, + "lc": 2, + "lj": 1, + "ml": 10, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 0, 0 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 5" + } + ], + "ip": 82, + "op": 179, + "st": -17, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 34, + "ty": 4, + "nm": "T2a-Y", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { "k": [ 39.043, 45.678, 0 ] }, + "a": { "k": [ 250, 250, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "v": [ + [ 1.681, -29.992 ], + [ -1.681, 29.992 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.06 ], + "y": [ 1 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p06_1_0p167_0p167" ], + "t": 72, + "s": [ 50 ], + "e": [ 0 ] + }, + { "t": 82 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.06 ], + "y": [ 1 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p06_1_0p167_0p167" ], + "t": 72, + "s": [ 50 ], + "e": [ 100 ] + }, + { "t": 82 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 9.194 }, + "lc": 3, + "lj": 1, + "ml": 10, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 277.698, 247.258 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 7" + } + ], + "ip": 72, + "op": 89, + "st": 12, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 35, + "ty": 4, + "nm": "T2b-Y", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { "k": [ 39.043, 45.678, 0 ] }, + "a": { "k": [ 250, 250, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "v": [ + [ 246.65, 213.814 ], + [ 340.956, 213.628 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.12 ], + "y": [ 1 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p12_1_0p167_0p167" ], + "t": 76, + "s": [ 29 ], + "e": [ 0 ] + }, + { "t": 85 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.12 ], + "y": [ 1 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p12_1_0p167_0p167" ], + "t": 76, + "s": [ 41.1 ], + "e": [ 66.5 ] + }, + { "t": 85 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 9.194 }, + "lc": 2, + "lj": 1, + "ml": 10, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 0, 0 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 5" + } + ], + "ip": 76, + "op": 92, + "st": -23, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 36, + "ty": 4, + "nm": "T1a-Y", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { + "k": [ + { + "i": { + "x": 0.667, + "y": 1 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "n": "0p667_1_0p167_0p167", + "t": 56, + "s": [ 39.043, 48.678, 0 ], + "e": [ 39.043, 45.678, 0 ], + "to": [ 0, 0, 0 ], + "ti": [ 0, 0, 0 ] + }, + { "t": 64 } + ] + }, + "a": { "k": [ 250, 250, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ -0.5, 9.501 ], + [ -0.048, 5.655 ], + [ 0.054, 0.06 ], + [ 0.946, 1.486 ], + [ -9.967, 8.05 ], + [ -40.546, 0 ] + ], + "o": [ + [ 0.031, -0.594 ], + [ 0.076, -8.978 ], + [ -1.161, -1.3 ], + [ -5.939, -9.327 ], + [ 24.677, -19.929 ], + [ 0, 0 ] + ], + "v": [ + [ -30.72, 63.761 ], + [ -30.741, 45.192 ], + [ -37.397, 27.014 ], + [ -40.698, 22.661 ], + [ -37.873, -7.117 ], + [ 49.506, 11.559 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 1 ] + }, + "o": { + "x": [ 0.301 ], + "y": [ 0 ] + }, + "n": [ "0p833_1_0p301_0" ], + "t": 54, + "s": [ 0 ], + "e": [ 24.9 ] + }, + { "t": 70 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.667 ], + "y": [ 1 ] + }, + "o": { + "x": [ 0.301 ], + "y": [ 0 ] + }, + "n": [ "0p667_1_0p301_0" ], + "t": 54, + "s": [ 0 ], + "e": [ 100 ] + }, + { "t": 74 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 8.4 }, + "lc": 2, + "lj": 1, + "ml": 10, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 227.677, 234.375 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 9" + } + ], + "ip": 59, + "op": 156, + "st": 12, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 37, + "ty": 4, + "nm": "E1-B", + "parent": 38, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { "k": [ 344.672, 214.842, 0 ] }, + "a": { "k": [ 344.672, 214.842, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "v": [ + [ -13.664, -0.145 ], + [ 62.163, 0.29 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 9.562 }, + "lc": 2, + "lj": 1, + "ml": 10, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 344.672, 214.842 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 2" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.12 ], + "y": [ 0.12 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p12_0p12_0p167_0p167" ], + "t": 84, + "s": [ 0 ], + "e": [ 0 ] + }, + { "t": 93 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.12 ], + "y": [ 1 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p12_1_0p167_0p167" ], + "t": 84, + "s": [ 0 ], + "e": [ 37.5 ] + }, + { "t": 93 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + } + ], + "ip": 84, + "op": 179, + "st": 84, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 38, + "ty": 4, + "nm": "E1-Y", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { + "k": [ + { + "i": { + "x": 0.12, + "y": 1 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "n": "0p12_1_0p167_0p167", + "t": 79, + "s": [ 113.715, 9.146, 0 ], + "e": [ 137.715, 9.146, 0 ], + "to": [ 0, 0, 0 ], + "ti": [ 0, 0, 0 ] + }, + { + "i": { + "x": 0.12, + "y": 1 + }, + "o": { + "x": 0.167, + "y": 0 + }, + "n": "0p12_1_0p167_0", + "t": 88, + "s": [ 137.715, 9.146, 0 ], + "e": [ 133.715, 9.146, 0 ], + "to": [ 0, 0, 0 ], + "ti": [ 0, 0, 0 ] + }, + { "t": 92 } + ] + }, + "a": { "k": [ 344.672, 214.842, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "v": [ + [ -13.664, -0.145 ], + [ 62.163, 0.29 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 0, 0.48, 0.53, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 8.4 }, + "lc": 2, + "lj": 1, + "ml": 10, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 344.672, 214.842 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 2" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.12 ], + "y": [ 0.12 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p12_0p12_0p167_0p167" ], + "t": 79, + "s": [ 0 ], + "e": [ 0 ] + }, + { "t": 88 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.12 ], + "y": [ 1 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p12_1_0p167_0p167" ], + "t": 79, + "s": [ 0 ], + "e": [ 37.5 ] + }, + { "t": 88 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + } + ], + "ip": 79, + "op": 94, + "st": 79, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 39, + "ty": 4, + "nm": "E2-B", + "parent": 40, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { "k": [ 332.05, 237.932, 0 ] }, + "a": { "k": [ 332.05, 237.932, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "v": [ + [ -26.67, -0.283 ], + [ 99.171, 0.066 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.12 ], + "y": [ 0.12 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p12_0p12_0p167_0p167" ], + "t": 86, + "s": [ 0 ], + "e": [ 0 ] + }, + { "t": 95 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.12 ], + "y": [ 1 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p12_1_0p167_0p167" ], + "t": 86, + "s": [ 0 ], + "e": [ 43 ] + }, + { "t": 95 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 9.562 }, + "lc": 2, + "lj": 1, + "ml": 10, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 331.664, 238.14 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 3" + } + ], + "ip": 86, + "op": 179, + "st": 86, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 40, + "ty": 4, + "nm": "E2-Y", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { + "k": [ + { + "i": { + "x": 0.12, + "y": 1 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "n": "0p12_1_0p167_0p167", + "t": 83, + "s": [ 109.092, 33.61, 0 ], + "e": [ 121.092, 33.61, 0 ], + "to": [ 0, 0, 0 ], + "ti": [ 0, 0, 0 ] + }, + { + "i": { + "x": 0.12, + "y": 0.12 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "n": "0p12_0p12_0p167_0p167", + "t": 92, + "s": [ 121.092, 33.61, 0 ], + "e": [ 121.092, 33.61, 0 ], + "to": [ 0, 0, 0 ], + "ti": [ 0, 0, 0 ] + }, + { "t": 96 } + ] + }, + "a": { "k": [ 332.05, 237.932, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "v": [ + [ -26.67, -0.283 ], + [ 99.171, 0.066 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.12 ], + "y": [ 0.12 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p12_0p12_0p167_0p167" ], + "t": 83, + "s": [ 0 ], + "e": [ 0 ] + }, + { "t": 92 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.12 ], + "y": [ 1 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p12_1_0p167_0p167" ], + "t": 83, + "s": [ 0 ], + "e": [ 43 ] + }, + { "t": 92 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 0, 0.48, 0.53, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 8.4 }, + "lc": 2, + "lj": 1, + "ml": 10, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 331.664, 238.14 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 3" + } + ], + "ip": 83, + "op": 96, + "st": 83, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 41, + "ty": 4, + "nm": "I-B", + "parent": 42, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { "k": [ 303.802, 282.182, 0 ] }, + "a": { "k": [ 303.802, 282.182, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "v": [ + [ 0.859, -21.143 ], + [ -4.359, 70.392 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.12 ], + "y": [ 0.12 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p12_0p12_0p167_0p167" ], + "t": 81, + "s": [ 0 ], + "e": [ 0 ] + }, + { "t": 91 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.12 ], + "y": [ 1 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p12_1_0p167_0p167" ], + "t": 81, + "s": [ 0 ], + "e": [ 45.7 ] + }, + { "t": 91 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 9.194 }, + "lc": 3, + "lj": 1, + "ml": 10, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 304.135, 282.409 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 6" + } + ], + "ip": 81, + "op": 179, + "st": 18, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 42, + "ty": 4, + "nm": "I-Y", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { + "k": [ + { + "i": { + "x": 0.12, + "y": 1 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "n": "0p12_1_0p167_0p167", + "t": 78, + "s": [ 93.594, 62.861, 0 ], + "e": [ 92.626, 82.829, 0 ], + "to": [ 0, 0, 0 ], + "ti": [ 0, 0, 0 ] + }, + { + "i": { + "x": 0.12, + "y": 1 + }, + "o": { + "x": 0.167, + "y": 0 + }, + "n": "0p12_1_0p167_0", + "t": 88, + "s": [ 92.626, 82.829, 0 ], + "e": [ 92.844, 77.861, 0 ], + "to": [ 0, 0, 0 ], + "ti": [ 0, 0, 0 ] + }, + { "t": 92 } + ] + }, + "a": { "k": [ 303.802, 282.182, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "v": [ + [ 0.859, -21.143 ], + [ -4.359, 70.392 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.12 ], + "y": [ 0.12 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p12_0p12_0p167_0p167" ], + "t": 78, + "s": [ 0 ], + "e": [ 0 ] + }, + { "t": 88 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.12 ], + "y": [ 1 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p12_1_0p167_0p167" ], + "t": 78, + "s": [ 0 ], + "e": [ 45.7 ] + }, + { "t": 88 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 0, 0.48, 0.53, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 8.4 }, + "lc": 3, + "lj": 1, + "ml": 10, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 304.135, 282.409 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 6" + } + ], + "ip": 78, + "op": 93, + "st": 15, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 43, + "ty": 4, + "nm": "E3-B", + "parent": 44, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { "k": [ 345.189, 261.801, 0 ] }, + "a": { "k": [ 345.124, 261.801, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "v": [ + [ -13.664, -0.145 ], + [ 75.663, 0.29 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 92, + "s": [ 0 ], + "e": [ 0 ] + }, + { "t": 97 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 92, + "s": [ 0 ], + "e": [ 31.6 ] + }, + { "t": 97 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 2" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 9.562 }, + "lc": 2, + "lj": 1, + "ml": 10, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 344.674, 261.877 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 1" + } + ], + "ip": 92, + "op": 179, + "st": 29, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 44, + "ty": 4, + "nm": "E3-Y", + "parent": 0, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { + "k": [ + { + "i": { + "x": 0.667, + "y": 1 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "n": "0p667_1_0p167_0p167", + "t": 84, + "s": [ 119.167, 57.479, 0 ], + "e": [ 137.167, 57.479, 0 ], + "to": [ 0, 0, 0 ], + "ti": [ 0, 0, 0 ] + }, + { + "i": { + "x": 0.667, + "y": 1 + }, + "o": { + "x": 0.167, + "y": 0 + }, + "n": "0p667_1_0p167_0", + "t": 92, + "s": [ 137.167, 57.479, 0 ], + "e": [ 134.167, 57.479, 0 ], + "to": [ 0, 0, 0 ], + "ti": [ 0, 0, 0 ] + }, + { "t": 96 } + ] + }, + "a": { "k": [ 345.124, 261.801, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ks": { + "k": { + "i": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "o": [ + [ 0, 0 ], + [ 0, 0 ] + ], + "v": [ + [ -13.664, -0.145 ], + [ 75.663, 0.29 ] + ], + "c": false + } + }, + "nm": "Path 1" + }, + { + "ty": "tm", + "s": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 84, + "s": [ 0 ], + "e": [ 0 ] + }, + { "t": 92 } + ], + "ix": 1 + }, + "e": { + "k": [ + { + "i": { + "x": [ 0.833 ], + "y": [ 0.833 ] + }, + "o": { + "x": [ 0.167 ], + "y": [ 0.167 ] + }, + "n": [ "0p833_0p833_0p167_0p167" ], + "t": 84, + "s": [ 0 ], + "e": [ 31.6 ] + }, + { "t": 92 } + ], + "ix": 2 + }, + "o": { + "k": 0, + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 2" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { "k": [ 0, 0.48, 0.53, 1 ] }, + "o": { "k": 100 }, + "w": { "k": 9.562 }, + "lc": 2, + "lj": 1, + "ml": 10, + "nm": "Stroke 1" + }, + { + "ty": "tr", + "p": { + "k": [ 344.674, 261.877 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 1" + } + ], + "ip": 84, + "op": 102, + "st": 21, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 45, + "ty": 4, + "nm": "Dot-Y", + "parent": 46, + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { + "k": [ + { + "i": { + "x": 0, + "y": 0.812 + }, + "o": { + "x": 0, + "y": 0 + }, + "n": "0_0p812_0_0", + "t": 96, + "s": [ 43.263, 59.75, 0 ], + "e": [ 62.513, 59.75, 0 ], + "to": [ 0, 0, 0 ], + "ti": [ 0, 0, 0 ] + }, + { + "i": { + "x": 0.708, + "y": 1 + }, + "o": { + "x": 0.39, + "y": 0.707 + }, + "n": "0p708_1_0p39_0p707", + "t": 108, + "s": [ 62.513, 59.75, 0 ], + "e": [ 63.763, 59.75, 0 ], + "to": [ 0, 0, 0 ], + "ti": [ 0, 0, 0 ] + }, + { "t": 115 } + ] + }, + "a": { "k": [ 196.791, 266.504, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "d": 1, + "ty": "el", + "s": { "k": [ 9.2, 9.2 ] }, + "p": { "k": [ 0.8, -0.5 ] }, + "nm": "Ellipse Path 1" + }, + { + "ty": "fl", + "fillEnabled": true, + "c": { "k": [ 1, 1, 1, 1 ] }, + "o": { "k": 100 }, + "nm": "Fill 1" + }, + { + "ty": "tr", + "p": { + "k": [ 196, 267 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Ellipse 1" + } + ], + "ip": 96, + "op": 182, + "st": 65, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 46, + "ty": 1, + "nm": "Bncr", + "parent": 0, + "ks": { + "o": { "k": 0 }, + "r": { "k": 0 }, + "p": { + "k": [ + { + "i": { + "x": 0.18, + "y": 1 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "n": "0p18_1_0p167_0p167", + "t": 96, + "s": [ 164.782, 57.473, 0 ], + "e": [ 164.782, 55.473, 0 ], + "to": [ 0, 0, 0 ], + "ti": [ 0, 0, 0 ] + }, + { + "i": { + "x": 0.833, + "y": 0.833 + }, + "o": { + "x": 0.82, + "y": 0 + }, + "n": "0p833_0p833_0p82_0", + "t": 99, + "s": [ 164.782, 55.473, 0 ], + "e": [ 164.782, 57.473, 0 ], + "to": [ 0, 0, 0 ], + "ti": [ 0, 0, 0 ] + }, + { + "i": { + "x": 0.18, + "y": 1 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "n": "0p18_1_0p167_0p167", + "t": 102, + "s": [ 164.782, 57.473, 0 ], + "e": [ 164.782, 56.909, 0 ], + "to": [ 0, 0, 0 ], + "ti": [ 0, 0, 0 ] + }, + { + "i": { + "x": 0.833, + "y": 0.833 + }, + "o": { + "x": 0.82, + "y": 0 + }, + "n": "0p833_0p833_0p82_0", + "t": 105, + "s": [ 164.782, 56.909, 0 ], + "e": [ 164.782, 57.473, 0 ], + "to": [ 0, 0, 0 ], + "ti": [ 0, 0, 0 ] + }, + { "t": 108 } + ] + }, + "a": { "k": [ 60, 60, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "sw": 120, + "sh": 120, + "sc": "#ffffff", + "ip": 96, + "op": 182, + "st": 15, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 47, + "ty": 4, + "nm": "BG", + "ks": { + "o": { "k": 100 }, + "r": { "k": 0 }, + "p": { "k": [ 187.5, 333.5, 0 ] }, + "a": { "k": [ 0, 0, 0 ] }, + "s": { "k": [ 100, 100, 100 ] } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ty": "rc", + "d": 1, + "s": { "k": [ 375, 667 ] }, + "p": { "k": [ 0, 0 ] }, + "r": { "k": 0 }, + "nm": "Rectangle Path 1" + }, + { + "ty": "fl", + "fillEnabled": true, + "c": { "k": [ 0, 0.82, 0.76, 1 ] }, + "o": { "k": 100 }, + "nm": "Fill 1" + }, + { + "ty": "tr", + "p": { + "k": [ 0, 0 ], + "ix": 2 + }, + "a": { + "k": [ 0, 0 ], + "ix": 1 + }, + "s": { + "k": [ 100, 100 ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Rectangle 1" + } + ], + "ip": 0, + "op": 179, + "st": 0, + "bm": 0, + "sr": 1 + } + ], + "v": "4.4.26", + "ddd": 0, + "ip": 0, + "op": 179, + "fr": 30, + "w": 375, + "h": 667 +} \ No newline at end of file diff --git a/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/DamagedHelmet1.bmp b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/DamagedHelmet1.bmp new file mode 100644 index 000000000..15d64855c Binary files /dev/null and b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/DamagedHelmet1.bmp differ diff --git a/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/DamagedHelmet2.bmp b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/DamagedHelmet2.bmp new file mode 100644 index 000000000..04874cb6e Binary files /dev/null and b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/DamagedHelmet2.bmp differ diff --git a/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/DamagedHelmet3.bmp b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/DamagedHelmet3.bmp new file mode 100644 index 000000000..94ca20a2d Binary files /dev/null and b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/DamagedHelmet3.bmp differ diff --git a/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/DamagedHelmet4.bmp b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/DamagedHelmet4.bmp new file mode 100644 index 000000000..419f62840 Binary files /dev/null and b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/DamagedHelmet4.bmp differ diff --git a/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/DamagedHelmet5.bmp b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/DamagedHelmet5.bmp new file mode 100644 index 000000000..2de59e897 Binary files /dev/null and b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/DamagedHelmet5.bmp differ diff --git a/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/DamagedHelmet6.bin b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/DamagedHelmet6.bin new file mode 100644 index 000000000..fda322e3e Binary files /dev/null and b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/DamagedHelmet6.bin differ diff --git a/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/DamagedHelmet7.bin b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/DamagedHelmet7.bin new file mode 100644 index 000000000..bb4b8e255 Binary files /dev/null and b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/DamagedHelmet7.bin differ diff --git a/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/DamagedHelmet8.bin b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/DamagedHelmet8.bin new file mode 100644 index 000000000..165a93c07 Binary files /dev/null and b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/DamagedHelmet8.bin differ diff --git a/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/DamagedHelmet9.bin b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/DamagedHelmet9.bin new file mode 100644 index 000000000..a4f943700 Binary files /dev/null and b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/DamagedHelmet9.bin differ diff --git a/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/Duck1.bmp b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/Duck1.bmp new file mode 100644 index 000000000..9fa2dd4cc Binary files /dev/null and b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/Duck1.bmp differ diff --git a/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/Duck2.bin b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/Duck2.bin new file mode 100644 index 000000000..37815892d Binary files /dev/null and b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/Duck2.bin differ diff --git a/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/Duck3.bin b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/Duck3.bin new file mode 100644 index 000000000..6304bfad0 Binary files /dev/null and b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/Duck3.bin differ diff --git a/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/Duck4.bin b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/Duck4.bin new file mode 100644 index 000000000..74e5472dc Binary files /dev/null and b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/Duck4.bin differ diff --git a/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/Duck5.bin b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/Duck5.bin new file mode 100644 index 000000000..81dc90c73 Binary files /dev/null and b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Assets/SceneNode/Duck5.bin differ diff --git a/Samples/Islands/WpfCalculator/CalculatorDemoPackage/CalculatorDemoPackage.wapproj b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/CalculatorDemoPackage.wapproj new file mode 100644 index 000000000..5a0786b0f --- /dev/null +++ b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/CalculatorDemoPackage.wapproj @@ -0,0 +1,78 @@ + + + + 15.0 + + + + Debug + x86 + + + Release + x86 + + + Debug + x64 + + + Release + x64 + + + Debug + ARM64 + + + Release + ARM64 + + + + $(MSBuildExtensionsPath)\Microsoft\DesktopBridge\ + + + + 0a343519-113b-4ef9-959c-30f559524bc4 + 10.0.22621.0 + 10.0.17763.0 + en-US + false + $(NoWarn);NU1702 + ..\CalculatorDemo\CalculatorDemo.csproj + true + + false + false + + + + $(AssetTargetFallback);net9.0-windows$(TargetPlatformVersion) + + + + Designer + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Images/LockScreenLogo.scale-200.png b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Images/LockScreenLogo.scale-200.png new file mode 100644 index 000000000..735f57adb Binary files /dev/null and b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Images/LockScreenLogo.scale-200.png differ diff --git a/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Images/SplashScreen.scale-200.png b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Images/SplashScreen.scale-200.png new file mode 100644 index 000000000..023e7f1fe Binary files /dev/null and b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Images/SplashScreen.scale-200.png differ diff --git a/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Images/Square150x150Logo.scale-200.png b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Images/Square150x150Logo.scale-200.png new file mode 100644 index 000000000..af49fec1a Binary files /dev/null and b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Images/Square150x150Logo.scale-200.png differ diff --git a/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Images/Square44x44Logo.scale-200.png b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Images/Square44x44Logo.scale-200.png new file mode 100644 index 000000000..ce342a2ec Binary files /dev/null and b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Images/Square44x44Logo.scale-200.png differ diff --git a/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Images/Square44x44Logo.targetsize-24_altform-unplated.png b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Images/Square44x44Logo.targetsize-24_altform-unplated.png new file mode 100644 index 000000000..f6c02ce97 Binary files /dev/null and b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Images/Square44x44Logo.targetsize-24_altform-unplated.png differ diff --git a/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Images/StoreLogo.png b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Images/StoreLogo.png new file mode 100644 index 000000000..7385b56c0 Binary files /dev/null and b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Images/StoreLogo.png differ diff --git a/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Images/Wide310x150Logo.scale-200.png b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Images/Wide310x150Logo.scale-200.png new file mode 100644 index 000000000..288995b39 Binary files /dev/null and b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Images/Wide310x150Logo.scale-200.png differ diff --git a/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Package.appxmanifest b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Package.appxmanifest new file mode 100644 index 000000000..95e932b9d --- /dev/null +++ b/Samples/Islands/WpfCalculator/CalculatorDemoPackage/Package.appxmanifest @@ -0,0 +1,49 @@ + + + + + + + + WpfCalculatorDemo + jecollin + Images\StoreLogo.png + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Samples/Islands/WpfCalculator/DrawingIslandComponents/AutomationCallbackHandler.h b/Samples/Islands/WpfCalculator/DrawingIslandComponents/AutomationCallbackHandler.h new file mode 100644 index 000000000..f61638cd1 --- /dev/null +++ b/Samples/Islands/WpfCalculator/DrawingIslandComponents/AutomationCallbackHandler.h @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once + +namespace winrt::DrawingIslandComponents +{ + struct __declspec(novtable) IAutomationCallbackHandler + { + virtual ~IAutomationCallbackHandler() noexcept = default; + + virtual winrt::Windows::Graphics::RectInt32 GetScreenBoundsForAutomationFragment( + _In_::IUnknown const* const sender) const = 0; + + virtual winrt::com_ptr GetFragmentFromPoint( + _In_ double x, + _In_ double y) const = 0; + + virtual winrt::com_ptr GetFragmentInFocus() const = 0; + }; +} diff --git a/Samples/Islands/WpfCalculator/DrawingIslandComponents/AutomationFragment.cpp b/Samples/Islands/WpfCalculator/DrawingIslandComponents/AutomationFragment.cpp new file mode 100644 index 000000000..83691aa66 --- /dev/null +++ b/Samples/Islands/WpfCalculator/DrawingIslandComponents/AutomationFragment.cpp @@ -0,0 +1,464 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include "pch.h" +#include "AutomationFragment.h" + +using unique_safearray = + wil::unique_any; + +namespace winrt::DrawingIslandComponents +{ + void AutomationFragment::AddChildToEnd( + _In_ winrt::com_ptr const& child) + { + std::unique_lock lock{ m_mutex }; + + if (nullptr == child) + { + // Nothing to do. + return; + } + + // The child should not already have a parent. + winrt::check_bool(nullptr == child->GetParent()); + + // Set us up as the parent for the new child. + child->SetParent(get_weak()); + + // Set up the sibling relationships. + if (!m_children.empty()) + { + auto& previousSiblingForNewChild = m_children.back(); + previousSiblingForNewChild->SetNextSibling(child); + child->SetPreviousSibling(previousSiblingForNewChild); + } + + // Finally add the child. + m_children.push_back(child); + } + + void AutomationFragment::RemoveChild( + _In_ winrt::com_ptr const& child) + { + std::unique_lock lock{ m_mutex }; + + if (nullptr == child) + { + // Nothing to do. + return; + } + + auto iterator = std::find_if( + m_children.begin(), m_children.end(), [&child](auto const& childEntry) + { + // See if we find a matching child entry in our children. + return (childEntry.get() == child.get()); + }); + + // We cannot remove a child that isn't ours. + winrt::check_bool(m_children.end() != iterator); + + // Remove us from the parent relationship with the child. + child->SetParent(nullptr); + + // Reset the sibling relationships. + auto previousSibling = child->GetPreviousSibling(); + auto nextSibling = child->GetNextSibling(); + if (nullptr != previousSibling) + { + previousSibling->SetNextSibling(nextSibling); + } + if (nullptr != nextSibling) + { + nextSibling->SetPreviousSibling(previousSibling); + } + child->SetPreviousSibling(nullptr); + child->SetNextSibling(nullptr); + + // Finally, remove the child. + m_children.erase(iterator); + } + + void AutomationFragment::RemoveAllChildren() + { + std::unique_lock lock{ m_mutex }; + + for (auto& child : m_children) + { + // Disconnect the relationships from all our children. + child->SetParent(nullptr); + child->SetPreviousSibling(nullptr); + child->SetNextSibling(nullptr); + } + + // Remove all the children. + m_children.clear(); + } + + void AutomationFragment::SetCallbackHandler( + _In_opt_ IAutomationCallbackHandler const* const owner) + { + std::unique_lock lock{ m_mutex }; + m_ownerNoRef = owner; + } + + void AutomationFragment::SetProviderOptions( + _In_ ProviderOptions const& providerOptions) + { + std::unique_lock lock{ m_mutex }; + m_providerOptions = providerOptions; + } + + void AutomationFragment::SetName( + _In_ std::wstring_view const& name) + { + std::unique_lock lock{ m_mutex }; + m_name = name; + } + + void AutomationFragment::SetIsContent( + _In_ bool const& isContent) + { + std::unique_lock lock{ m_mutex }; + m_isContent = isContent; + } + + void AutomationFragment::SetIsControl( + _In_ bool const& isControl) + { + std::unique_lock lock{ m_mutex }; + m_isControl = isControl; + } + + void AutomationFragment::SetUiaControlTypeId( + _In_ long const& uiaControlTypeId) + { + std::unique_lock lock{ m_mutex }; + m_uiaControlTypeId = uiaControlTypeId; + } + + void AutomationFragment::SetHostProvider( + _In_ winrt::com_ptr const& hostProvider) + { + std::unique_lock lock{ m_mutex }; + m_hostProvider = hostProvider; + } + + HRESULT __stdcall AutomationFragment::get_ProviderOptions( + _Out_ ProviderOptions* providerOptions) + { + try + { + std::unique_lock lock{ m_mutex }; + if (nullptr != providerOptions) + { + *providerOptions = m_providerOptions; + } + } + catch (...) { return UIA_E_ELEMENTNOTAVAILABLE; } + return S_OK; + } + + HRESULT __stdcall AutomationFragment::GetPatternProvider( + _In_ PATTERNID patternId, + _COM_Outptr_opt_result_maybenull_ IUnknown** patternProvider) + { + try + { + std::unique_lock lock{ m_mutex }; + if (nullptr != patternProvider) + { + *patternProvider = nullptr; + switch (patternId) + { + case UIA_InvokePatternId: + { + if (auto invokeProvider = get_strong().try_as()) + { + invokeProvider.as().copy_to(patternProvider); + } + break; + } + } + } + } + catch (...) { return UIA_E_ELEMENTNOTAVAILABLE; } + return S_OK; + } + + HRESULT __stdcall AutomationFragment::GetPropertyValue( + _In_ PROPERTYID propertyId, + _Out_ VARIANT* propertyValue) + { + try + { + std::unique_lock lock{ m_mutex }; + if (nullptr != propertyValue) + { + ::VariantInit(propertyValue); + switch (propertyId) + { + case UIA_NamePropertyId: + { + propertyValue->bstrVal = wil::make_bstr(m_name.c_str()).release(); + propertyValue->vt = VT_BSTR; + break; + } + + case UIA_IsContentElementPropertyId: + { + propertyValue->boolVal = m_isContent ? VARIANT_TRUE : VARIANT_FALSE; + propertyValue->vt = VT_BOOL; + break; + } + + case UIA_IsControlElementPropertyId: + { + propertyValue->boolVal = m_isControl ? VARIANT_TRUE : VARIANT_FALSE; + propertyValue->vt = VT_BOOL; + break; + } + + case UIA_ControlTypePropertyId: + { + if (m_isControl) + { + propertyValue->vt = VT_I4; + propertyValue->lVal = m_uiaControlTypeId; + } + break; + } + } + } + } + catch (...) { return UIA_E_ELEMENTNOTAVAILABLE; } + return S_OK; + } + + HRESULT __stdcall AutomationFragment::get_HostRawElementProvider( + _COM_Outptr_opt_result_maybenull_ IRawElementProviderSimple** hostRawElementProviderSimple) + { + try + { + std::unique_lock lock{ m_mutex }; + if (nullptr != hostRawElementProviderSimple) + { + m_hostProvider.copy_to(hostRawElementProviderSimple); + } + } + catch (...) { return UIA_E_ELEMENTNOTAVAILABLE; } + return S_OK; + } + + HRESULT __stdcall AutomationFragment::Navigate( + _In_ NavigateDirection direction, + _COM_Outptr_opt_result_maybenull_ IRawElementProviderFragment** fragment) + { + try + { + std::unique_lock lock{ m_mutex }; + if (nullptr != fragment) + { + *fragment = nullptr; + switch (direction) + { + case NavigateDirection_Parent: + { + if (auto strongParent = m_parent.get()) + { + strongParent.as().copy_to(fragment); + } + break; + } + case NavigateDirection_NextSibling: + { + if (auto strongSibling = m_nextSibling.get()) + { + strongSibling.as().copy_to(fragment); + } + break; + } + case NavigateDirection_PreviousSibling: + { + if (auto strongSibling = m_previousSibling.get()) + { + strongSibling.as().copy_to(fragment); + } + break; + } + case NavigateDirection_FirstChild: + { + if (!m_children.empty()) + { + m_children.front().as().copy_to(fragment); + } + break; + } + case NavigateDirection_LastChild: + { + if (!m_children.empty()) + { + m_children.back().as().copy_to(fragment); + } + break; + } + } + } + } + catch (...) { return UIA_E_ELEMENTNOTAVAILABLE; } + return S_OK; + } + + HRESULT __stdcall AutomationFragment::GetRuntimeId( + _Outptr_opt_result_maybenull_ SAFEARRAY** runtimeId) + { + try + { + std::unique_lock lock{ m_mutex }; + if (nullptr != runtimeId) + { + *runtimeId = nullptr; + + unsigned long arraySizeAsUnsignedLong = + static_cast(m_runtimeId.size()); + + unique_safearray runtimeIdArray + { ::SafeArrayCreateVector(VT_I4, 0, arraySizeAsUnsignedLong) }; + SAFEARRAY* rawPointerToSafeArray = runtimeIdArray.get(); + winrt::check_pointer(rawPointerToSafeArray); + + for (long i = 0; i < static_cast(arraySizeAsUnsignedLong); ++i) + { + winrt::check_hresult( + ::SafeArrayPutElement(rawPointerToSafeArray, &i, &(m_runtimeId[i]))); + } + + *runtimeId = runtimeIdArray.release(); + } + } + catch (...) { return UIA_E_ELEMENTNOTAVAILABLE; } + return S_OK; + } + + HRESULT __stdcall AutomationFragment::get_BoundingRectangle( + _Out_ UiaRect* boundingRectangle) + { + try + { + std::unique_lock lock{ m_mutex }; + if (nullptr != boundingRectangle) + { + *boundingRectangle = { 0, 0, 0, 0 }; + + // This provider might still be alive in a UIA callback when the DrawingIsland + // is being torn down. Make sure we still have a valid owner before proceeding + // to query the DrawingIsland for this information. + if (nullptr != m_ownerNoRef) + { + auto screenRectangle = + m_ownerNoRef->GetScreenBoundsForAutomationFragment( + get_strong().as<::IUnknown>().get()); + + boundingRectangle->left = screenRectangle.X; + boundingRectangle->top = screenRectangle.Y; + boundingRectangle->width = screenRectangle.Width; + boundingRectangle->height = screenRectangle.Height; + } + } + } + catch (...) { return UIA_E_ELEMENTNOTAVAILABLE; } + return S_OK; + } + + HRESULT __stdcall AutomationFragment::GetEmbeddedFragmentRoots( + _Outptr_opt_result_maybenull_ SAFEARRAY** embeddedFragmentRoots) + { + if (nullptr != embeddedFragmentRoots) + { + *embeddedFragmentRoots = nullptr; + } + return S_OK; + } + + HRESULT __stdcall AutomationFragment::SetFocus() + { + return S_OK; + } + + HRESULT __stdcall AutomationFragment::get_FragmentRoot( + _COM_Outptr_opt_result_maybenull_ IRawElementProviderFragmentRoot** fragmentRoot) + { + try + { + std::unique_lock lock{ m_mutex }; + if (nullptr != fragmentRoot) + { + *fragmentRoot = nullptr; + + // Walk up our fragment tree until we find our fragment root. + auto fragmentRootCandidate = get_strong(); + bool currentCandidateIsThisObject = true; + while (nullptr != fragmentRootCandidate && + nullptr == fragmentRootCandidate.try_as()) + { + // Haven't found the fragment root yet, keep walking up our tree. + fragmentRootCandidate = currentCandidateIsThisObject ? + m_parent.get() : fragmentRootCandidate->GetParent(); + + // Once we start walking up the tree, we must ensure we're thread-safe + // and call through GetParent on the other objects. + currentCandidateIsThisObject = false; + } + + if (nullptr != fragmentRootCandidate) + { + // Found the fragment root, return it. + fragmentRootCandidate.as().copy_to( + fragmentRoot); + } + } + } + catch (...) { return UIA_E_ELEMENTNOTAVAILABLE; } + return S_OK; + } + + void AutomationFragment::SetParent( + _In_ winrt::weak_ref const& parent) + { + std::unique_lock lock{ m_mutex }; + m_parent = parent; + } + + winrt::com_ptr AutomationFragment::GetParent() const + { + std::unique_lock lock{ m_mutex }; + return m_parent.get(); + } + + void AutomationFragment::SetPreviousSibling( + _In_ winrt::weak_ref const& previousSibling) + { + std::unique_lock lock{ m_mutex }; + m_previousSibling = previousSibling; + } + + winrt::com_ptr AutomationFragment::GetPreviousSibling() const + { + std::unique_lock lock{ m_mutex }; + return m_previousSibling.get(); + } + + void AutomationFragment::SetNextSibling( + _In_ winrt::weak_ref const& nextSibling) + { + std::unique_lock lock{ m_mutex }; + m_nextSibling = nextSibling; + } + + winrt::com_ptr AutomationFragment::GetNextSibling() const + { + std::unique_lock lock{ m_mutex }; + return m_nextSibling.get(); + } +} diff --git a/Samples/Islands/WpfCalculator/DrawingIslandComponents/AutomationFragment.h b/Samples/Islands/WpfCalculator/DrawingIslandComponents/AutomationFragment.h new file mode 100644 index 000000000..c05629c0c --- /dev/null +++ b/Samples/Islands/WpfCalculator/DrawingIslandComponents/AutomationFragment.h @@ -0,0 +1,129 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once +#include +#include "AutomationCallbackHandler.h" + +namespace winrt::DrawingIslandComponents +{ + struct AutomationFragment : winrt::implements + { + void AddChildToEnd( + _In_ winrt::com_ptr const& child); + + void RemoveChild( + _In_ winrt::com_ptr const& child); + + void RemoveAllChildren(); + + void SetCallbackHandler( + _In_opt_ IAutomationCallbackHandler const* const owner); + + void SetProviderOptions( + _In_ ProviderOptions const& providerOptions); + + void SetName( + _In_ std::wstring_view const& name); + + void SetIsContent( + _In_ bool const& isContent); + + void SetIsControl( + _In_ bool const& isControl); + + void SetUiaControlTypeId( + _In_ long const& uiaControlTypeId); + + void SetHostProvider( + _In_ winrt::com_ptr const& hostProvider); + + // IRawElementProviderSimple overrides. + HRESULT __stdcall get_ProviderOptions( + _Out_ ProviderOptions* providerOptions + ) final override; + + HRESULT __stdcall GetPatternProvider( + _In_ PATTERNID patternId, + _COM_Outptr_opt_result_maybenull_ IUnknown** patternProvider + ) final override; + + HRESULT __stdcall GetPropertyValue( + _In_ PROPERTYID propertyId, + _Out_ VARIANT* propertyValue + ) final override; + + HRESULT __stdcall get_HostRawElementProvider( + _COM_Outptr_opt_result_maybenull_ IRawElementProviderSimple** hostRawElementProviderSimple + ) final override; + + // IRawElementProviderFragment overrides. + HRESULT __stdcall Navigate( + _In_ NavigateDirection direction, + _COM_Outptr_opt_result_maybenull_ IRawElementProviderFragment** fragment + ) final override; + + HRESULT __stdcall GetRuntimeId( + _Outptr_opt_result_maybenull_ SAFEARRAY** runtimeId + ) final override; + + HRESULT __stdcall get_BoundingRectangle( + _Out_ UiaRect* boundingRectangle + ) final override; + + HRESULT __stdcall GetEmbeddedFragmentRoots( + _Outptr_opt_result_maybenull_ SAFEARRAY** embeddedFragmentRoots + ) final override; + + HRESULT __stdcall SetFocus() final override; + + HRESULT __stdcall get_FragmentRoot( + _COM_Outptr_opt_result_maybenull_ IRawElementProviderFragmentRoot** fragmentRoot + ) final override; + + protected: + mutable std::mutex m_mutex{}; + + // We do not hold a strong reference to the object that owns us. + // However we do need to be able to call back into it to get information. + // The owner is responsible for unsetting itself when it gets destroyed. + IAutomationCallbackHandler const* m_ownerNoRef{ nullptr }; + + private: + void SetParent( + _In_ winrt::weak_ref const& parent); + + winrt::com_ptr GetParent() const; + + void SetPreviousSibling( + _In_ winrt::weak_ref const& previousSibling); + + winrt::com_ptr GetPreviousSibling() const; + + void SetNextSibling( + _In_ winrt::weak_ref const& nextSibling); + + winrt::com_ptr GetNextSibling() const; + + // Automatically generate unique runtime IDs per fragment. + inline static unsigned __int32 s_nextAvailableInternalRuntimeId{ 0 }; + std::array m_runtimeId + { UiaAppendRuntimeId, ++s_nextAvailableInternalRuntimeId }; + + ProviderOptions m_providerOptions + { ProviderOptions_ServerSideProvider | ProviderOptions_UseComThreading }; + std::wstring m_name{ L"" }; + bool m_isContent{ true }; + bool m_isControl{ true }; + long m_uiaControlTypeId{ UIA_CustomControlTypeId }; + winrt::com_ptr m_hostProvider{ nullptr }; + + winrt::weak_ref m_parent{ nullptr }; + winrt::weak_ref m_previousSibling{ nullptr }; + winrt::weak_ref m_nextSibling{ nullptr }; + std::vector> m_children{}; + }; +} diff --git a/Samples/Islands/WpfCalculator/DrawingIslandComponents/AutomationFragmentRoot.cpp b/Samples/Islands/WpfCalculator/DrawingIslandComponents/AutomationFragmentRoot.cpp new file mode 100644 index 000000000..f8833f010 --- /dev/null +++ b/Samples/Islands/WpfCalculator/DrawingIslandComponents/AutomationFragmentRoot.cpp @@ -0,0 +1,56 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include "pch.h" +#include "AutomationFragmentRoot.h" + +namespace winrt::DrawingIslandComponents +{ + HRESULT __stdcall AutomationFragmentRoot::ElementProviderFromPoint( + _In_ double x, + _In_ double y, + _COM_Outptr_opt_result_maybenull_ IRawElementProviderFragment** fragment) + { + try + { + std::unique_lock lock{ m_mutex }; + if (nullptr != fragment) + { + *fragment = nullptr; + + // This provider might still be alive in a UIA callback when the DrawingIsland + // is being torn down. Make sure we still have a valid owner before proceeding + // to query the DrawingIsland for this information. + if (nullptr != m_ownerNoRef) + { + m_ownerNoRef->GetFragmentFromPoint(x, y).copy_to(fragment); + } + } + } + catch (...) { return UIA_E_ELEMENTNOTAVAILABLE; } + return S_OK; + } + + HRESULT __stdcall AutomationFragmentRoot::GetFocus( + _COM_Outptr_opt_result_maybenull_ IRawElementProviderFragment** fragmentInFocus) + { + try + { + std::unique_lock lock{ m_mutex }; + if (nullptr != fragmentInFocus) + { + *fragmentInFocus = nullptr; + + // This provider might still be alive in a UIA callback when the DrawingIsland + // is being torn down. Make sure we still have a valid owner before proceeding + // to query the DrawingIsland for this information. + if (nullptr != m_ownerNoRef) + { + m_ownerNoRef->GetFragmentInFocus().copy_to(fragmentInFocus); + } + } + } + catch (...) { return UIA_E_ELEMENTNOTAVAILABLE; } + return S_OK; + } +} diff --git a/Samples/Islands/WpfCalculator/DrawingIslandComponents/AutomationFragmentRoot.h b/Samples/Islands/WpfCalculator/DrawingIslandComponents/AutomationFragmentRoot.h new file mode 100644 index 000000000..60e629c73 --- /dev/null +++ b/Samples/Islands/WpfCalculator/DrawingIslandComponents/AutomationFragmentRoot.h @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once +#include "AutomationFragment.h" + +namespace winrt::DrawingIslandComponents +{ + struct AutomationFragmentRoot : winrt::implements + { + // IRawElementProviderFragmentRoot overrides. + HRESULT __stdcall ElementProviderFromPoint( + _In_ double x, + _In_ double y, + _COM_Outptr_opt_result_maybenull_ IRawElementProviderFragment** fragment + ) final override; + + HRESULT __stdcall GetFocus( + _COM_Outptr_opt_result_maybenull_ IRawElementProviderFragment** fragmentInFocus + ) final override; + }; +} diff --git a/Samples/Islands/WpfCalculator/DrawingIslandComponents/AutomationPeer.h b/Samples/Islands/WpfCalculator/DrawingIslandComponents/AutomationPeer.h new file mode 100644 index 000000000..e47b6fce8 --- /dev/null +++ b/Samples/Islands/WpfCalculator/DrawingIslandComponents/AutomationPeer.h @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once + +namespace winrt::DrawingIslandComponents +{ + // For the DrawingIsland, each Visual corresponds to an Automation Fragment. + // This structure encapsulates that relationship and enables us to quickly retrieve one from + // the other. + struct AutomationPeer + { + explicit AutomationPeer( + winrt::Visual const& visual, + winrt::com_ptr const& automationProvider) : + _visual{ visual }, + _automationProvider{ automationProvider } + { + + } + + winrt::Visual const& GetVisual() const + { + return _visual; + } + + winrt::com_ptr const& GetAutomationProvider() const + { + return _automationProvider; + } + + bool Match(winrt::Visual const& visual) const noexcept + { + return visual == _visual; + } + + bool Match(::IUnknown const* const automationProviderAsIUnknown) const noexcept + { + return automationProviderAsIUnknown == + _automationProvider.try_as<::IUnknown>().get(); + } + + private: + winrt::Visual _visual{ nullptr }; + winrt::com_ptr _automationProvider{ nullptr }; + }; +} diff --git a/Samples/Islands/WpfCalculator/DrawingIslandComponents/Components.idl b/Samples/Islands/WpfCalculator/DrawingIslandComponents/Components.idl new file mode 100644 index 000000000..0a17ee88a --- /dev/null +++ b/Samples/Islands/WpfCalculator/DrawingIslandComponents/Components.idl @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace DrawingIslandComponents +{ + [default_interface] + runtimeclass DrawingIsland : Windows.Foundation.IClosable + { + // Construction + DrawingIsland( + Microsoft.UI.Composition.Compositor compositor); + + // Properties + Boolean EnableBackgroundTransparency; + + Microsoft.UI.Content.ContentIsland Island { get; }; + + // Methods + void LeftClickAndRelease( + Windows.Foundation.Numerics.Vector2 currentPoint); + + void RightClickAndRelease( + Windows.Foundation.Numerics.Vector2 currentPoint); + + void SetIslandOpacity(Single islandOpacity); + + void SetColorIndex(UInt32 colorIndex); + } +} diff --git a/Samples/Islands/WpfCalculator/DrawingIslandComponents/DeviceLostHelper.cpp b/Samples/Islands/WpfCalculator/DrawingIslandComponents/DeviceLostHelper.cpp new file mode 100644 index 000000000..3a19e2af4 --- /dev/null +++ b/Samples/Islands/WpfCalculator/DrawingIslandComponents/DeviceLostHelper.cpp @@ -0,0 +1,72 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include "pch.h" +#include "DeviceLostHelper.h" + +namespace winrt::DrawingIslandComponents::implementation +{ + void DeviceLostHelper::WatchDevice(winrt::com_ptr<::IDXGIDevice> const& dxgiDevice) + { + // If we're currently listening to a device, then stop. + StopWatchingCurrentDevice(); + + // Set the current device to the new device. + m_device = nullptr; + winrt::check_hresult(::CreateDirect3D11DeviceFromDXGIDevice(dxgiDevice.get(), reinterpret_cast<::IInspectable**>(winrt::put_abi(m_device)))); + + // Get the DXGI Device. + m_dxgiDevice = dxgiDevice; + + // QI For the ID3D11Device4 interface. + winrt::com_ptr<::ID3D11Device4> d3dDevice{ m_dxgiDevice.as<::ID3D11Device4>() }; + + // Create a wait struct. + m_onDeviceLostHandler = nullptr; + m_onDeviceLostHandler = ::CreateThreadpoolWait(DeviceLostHelper::OnDeviceLost, (PVOID)this, nullptr); + + // Create a handle and a cookie. + m_eventHandle.attach(::CreateEvent(nullptr, false, false, nullptr)); + winrt::check_bool(bool{ m_eventHandle }); + m_cookie = 0; + + // Register for device lost. + ::SetThreadpoolWait(m_onDeviceLostHandler, m_eventHandle.get(), nullptr); + winrt::check_hresult(d3dDevice->RegisterDeviceRemovedEvent(m_eventHandle.get(), &m_cookie)); + } + + void DeviceLostHelper::StopWatchingCurrentDevice() + { + if (m_dxgiDevice) + { + // QI For the ID3D11Device4 interface. + auto d3dDevice{ m_dxgiDevice.as<::ID3D11Device4>() }; + + // Unregister from the device lost event. + ::CloseThreadpoolWait(m_onDeviceLostHandler); + d3dDevice->UnregisterDeviceRemoved(m_cookie); + + // Clear member variables. + m_onDeviceLostHandler = nullptr; + m_eventHandle.close(); + m_cookie = 0; + m_device = nullptr; + m_dxgiDevice = nullptr; + } + } + + void CALLBACK DeviceLostHelper::OnDeviceLost(PTP_CALLBACK_INSTANCE /* instance */, PVOID context, PTP_WAIT /* wait */, TP_WAIT_RESULT /* waitResult */) + { + // Get the DeviceLostHelper context object. + auto deviceLostHelper = reinterpret_cast(context); + + // Create a local reference to the old device before releasing the helper object's reference. + auto oldDevice = deviceLostHelper->m_device; + + // Stop listening for device lost events on the old device. + deviceLostHelper->StopWatchingCurrentDevice(); + + // Invoke the event handler. + deviceLostHelper->RaiseDeviceLostEvent(oldDevice); + } +} diff --git a/Samples/Islands/WpfCalculator/DrawingIslandComponents/DeviceLostHelper.h b/Samples/Islands/WpfCalculator/DrawingIslandComponents/DeviceLostHelper.h new file mode 100644 index 000000000..67f33431b --- /dev/null +++ b/Samples/Islands/WpfCalculator/DrawingIslandComponents/DeviceLostHelper.h @@ -0,0 +1,58 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once + +namespace winrt::DrawingIslandComponents::implementation +{ + struct DeviceLostEventArgs + { + DeviceLostEventArgs(IDirect3DDevice const& device) : m_device(device) + { + } + + IDirect3DDevice Device() { return m_device; } + + private: + IDirect3DDevice m_device; + }; + + struct DeviceLostHelper + { + DeviceLostHelper() = default; + + ~DeviceLostHelper() + { + StopWatchingCurrentDevice(); + } + + // Not copyable or assignable. + DeviceLostHelper(DeviceLostHelper const&) = delete; + void operator=(DeviceLostHelper const&) = delete; + + void WatchDevice(winrt::com_ptr<::IDXGIDevice> const& dxgiDevice); + + void StopWatchingCurrentDevice(); + + void DeviceLost(winrt::delegate const& handler) + { + m_deviceLost = handler; + } + + private: + void RaiseDeviceLostEvent(IDirect3DDevice const& oldDevice) + { + m_deviceLost(this, DeviceLostEventArgs{ oldDevice }); + } + + static void CALLBACK OnDeviceLost(PTP_CALLBACK_INSTANCE /* instance */, PVOID context, PTP_WAIT /* wait */, TP_WAIT_RESULT /* waitResult */); + + private: + winrt::delegate m_deviceLost; + IDirect3DDevice m_device; + winrt::com_ptr<::IDXGIDevice> m_dxgiDevice; + PTP_WAIT m_onDeviceLostHandler{ nullptr }; + winrt::handle m_eventHandle; + DWORD m_cookie{ 0 }; + }; +} diff --git a/Samples/Islands/WpfCalculator/DrawingIslandComponents/DrawingIsland.cpp b/Samples/Islands/WpfCalculator/DrawingIslandComponents/DrawingIsland.cpp new file mode 100644 index 000000000..e45a62a35 --- /dev/null +++ b/Samples/Islands/WpfCalculator/DrawingIslandComponents/DrawingIsland.cpp @@ -0,0 +1,987 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include "pch.h" +#include "DrawingIsland.h" +#include "DrawingIsland.g.cpp" + +namespace winrt::DrawingIslandComponents::implementation +{ + DrawingIsland::DrawingIsland( + const winrt::Compositor& compositor) + { + m_output.Compositor = compositor; + m_output.TextRenderer = std::make_shared(m_output.Compositor); + m_output.DeviceLostHelper.WatchDevice(m_output.TextRenderer->GetDevice()); + m_output.DeviceLostHelper.DeviceLost({ this, &DrawingIsland::OnDirect3DDeviceLost }); + + // Create the Compositor and the Content: + // - The Bridge's connection to the Window will keep everything alive, and perform an + // orderly tear-down: + // + // Window -> Bridge -> Content -> Visual -> InputSite -> InputObject + // + // - When the ContentIsland is destroyed, ContentIsland.AppData will call IClosable.Close + // on this instance to break cycles and clean up expensive resources. + + m_output.RootVisual = m_output.Compositor.CreateContainerVisual(); + m_output.RootVisual.RelativeSizeAdjustment({ 1.0f, 1.0f }); + + m_island = winrt::ContentIsland::Create(m_output.RootVisual); + m_island.AppData(get_strong().as()); + + Output_Initialize(); + Input_Initialize(); + Environment_Initialize(); + Accessibility_Initialize(); + + m_prevState.RasterizationScale = m_island.RasterizationScale(); + + // Get notifications for resize, bridge changes, etc. + (void)m_island.StateChanged( + [&](auto&& ...) + { + return Island_OnStateChanged(); + }); + + + (void)m_island.Closed( + [&]() + { + return Island_OnClosed(); + }); + + } + + + DrawingIsland::~DrawingIsland() + { + m_output.Compositor = nullptr; + } + + + void + DrawingIsland::Close() + { + m_output.RootVisual = nullptr; + + m_input.KeyboardSource = nullptr; + m_input.PretranslateSource = nullptr; + m_input.PointerSource = nullptr; + m_input.FocusController = nullptr; + + m_background.BrushDefault = nullptr; + m_background.BrushA = nullptr; + m_background.BrushB = nullptr; + m_background.BrushC = nullptr; + m_background.Visual = nullptr; + + m_items.Visuals = nullptr; + m_items.Items.clear(); + m_items.SelectedItem = nullptr; + + if (nullptr != m_background.BackdropController) + { + // Clean up our SystemBackdropController. + m_background.BackdropController.RemoveAllSystemBackdropTargets(); + m_background.BackdropController.Close(); + m_background.BackdropController = nullptr; + } + + if (nullptr != m_background.BackdropConfiguration) + { + m_background.BackdropConfiguration = nullptr; + } + + // Make sure automation is destroyed. + for (auto& automationPeer : m_uia.AutomationPeers) + { + automationPeer.GetAutomationProvider()->SetCallbackHandler(nullptr); + } + m_uia.AutomationPeers.clear(); + + if (nullptr != m_uia.FragmentRoot) + { + m_uia.FragmentRoot->SetCallbackHandler(nullptr); + m_uia.FragmentRoot = nullptr; + } + + + // Destroy Content: + // - This handles if the ContentIsland has already started destruction and is notifying the + // app. + + m_island.Close(); + m_island = nullptr; + + // TODO: Add the following test case in automated tests: + // 1. We are recursively calling ContentIsland.Close while inside the ContentIsland.Closed + // event. + // 2. We are testing the potential final Release() of ContentIsland while inside the Closed + // event. + + m_output.Compositor = nullptr; + } + + + void DrawingIsland::EnableBackgroundTransparency( + bool value) + { + if (value != m_background.BackdropEnabled) + { + m_background.BackdropEnabled = value; + Output_UpdateSystemBackdrop(); + } + } + + + IFACEMETHODIMP + DrawingIsland::OnDirectMessage( + IInputPreTranslateKeyboardSourceInterop* /*source*/, + const MSG* msg, + UINT keyboardModifiers, + _Inout_ bool* handled) + { + *handled = false; + + // Alt+A Debug print to see the order of the PreTranslate callbacks + if ((keyboardModifiers & FALT) && + (msg->message == WM_SYSKEYDOWN) && + (static_cast(msg->wParam) == winrt::VirtualKey::A)) + { + + } + + if (keyboardModifiers & FALT) + { + *handled = Input_AcceleratorKeyActivated( + static_cast(msg->wParam)); + } + + return S_OK; + } + + + IFACEMETHODIMP + DrawingIsland::OnTreeMessage( + IInputPreTranslateKeyboardSourceInterop* /*source*/, + const MSG* msg, + UINT keyboardModifiers, + _Inout_ bool* handled) + { + // Alt+A Debug print to see the order of the PreTranslate callbacks + if ((keyboardModifiers & FALT) && + (msg->message == WM_SYSKEYDOWN) && + (static_cast(msg->wParam) == winrt::VirtualKey::A)) + { + + } + + *handled = false; + return S_OK; + } + + + winrt::Windows::Graphics::RectInt32 + DrawingIsland::GetScreenBoundsForAutomationFragment( + _In_::IUnknown const* const sender) const + { + // Check if the automation provider that has sent this callback is the fragment root. + if (m_uia.FragmentRoot.as<::IUnknown>().get() == sender) + { + winrt::Rect logicalRect; + logicalRect.X = 0; + logicalRect.Y = 0; + logicalRect.Width = m_island.ActualSize().x; + logicalRect.Height = m_island.ActualSize().y; + + // This will convert from the logical coordinate space of the ContentIsland to + // Win32 screen coordinates that are needed by Accessibility. + return m_island.CoordinateConverter().ConvertLocalToScreen(logicalRect); + } + + // Else find the matching automation peer entry for the sending fragment. + auto iterator = std::find_if( + m_uia.AutomationPeers.begin(), m_uia.AutomationPeers.end(), + [&sender](auto const& automationPeer) + { + return automationPeer.Match(sender); + }); + + if (m_uia.AutomationPeers.end() == iterator) + { + // Did not find any match for this automation provider. + return { 0, 0, 0, 0 }; + } + + auto const& visualPeer = iterator->GetVisual(); + winrt::Rect logicalRect; + logicalRect.X = visualPeer.Offset().x; + logicalRect.Y = visualPeer.Offset().y; + logicalRect.Width = visualPeer.Size().x; + logicalRect.Height = visualPeer.Size().y; + + // This will convert from the logical coordinate space of the ContentIsland to + // Win32 screen coordinates that are needed by Accessibility. + return m_island.CoordinateConverter().ConvertLocalToScreen(logicalRect); + } + + + winrt::com_ptr + DrawingIsland::GetFragmentFromPoint( + _In_ double x, + _In_ double y) const + { + // UIA provides hit test points in screen space. + // Convert the point into a dummy empty rectangle to use with the coordinate converter. + winrt::Windows::Graphics::RectInt32 screenRect + { static_cast(x + 0.5), static_cast(y + 0.5), 0, 0 }; + + auto logicalRect = m_island.CoordinateConverter().ConvertScreenToLocal(screenRect); + float2 localPoint{ logicalRect.X, logicalRect.Y }; + auto hitTestElement = HitTestItem(localPoint); + + // Find the automation peer for the hit test visual if any. + if (nullptr != hitTestElement) + { + auto& hitTestVisual = hitTestElement->GetVisual(); + + auto iterator = std::find_if( + m_uia.AutomationPeers.begin(), m_uia.AutomationPeers.end(), + [&hitTestVisual](auto const& automationPeer) + { + return automationPeer.Match(hitTestVisual); + }); + + if (m_uia.AutomationPeers.end() != iterator) + { + // Return the automation provider if we found an automation peer + // for the hit test visual. + return iterator->GetAutomationProvider().as(); + } + } + + return nullptr; + } + + + winrt::com_ptr + DrawingIsland::GetFragmentInFocus() const + { + if (m_items.SelectedItem != nullptr) + { + auto& visual = m_items.SelectedItem->GetVisual(); + + // Find the currently selected visual's automation peer. + auto iterator = std::find_if( + m_uia.AutomationPeers.begin(), m_uia.AutomationPeers.end(), + [visual](auto const& automationPeer) + { + return automationPeer.Match(visual); + }); + + if (m_uia.AutomationPeers.end() != iterator) + { + // Return the automation provider if we found an automation peer + // for the selected visual. + return iterator->GetAutomationProvider().as(); + } + } + + return nullptr; + } + + + Item* DrawingIsland::HitTestItem(float2 const& point) const + { + // Iterate from the end of the vector, i.e., from front to back. + for (size_t i = m_items.Items.size(); i != 0; i--) + { + Item* item = m_items.Items[i - 1].get(); + auto& visual = item->GetVisual(); + + winrt::float3 const offset = visual.Offset(); + float2 const size = visual.Size(); + + if (point.x >= offset.x && + point.x < offset.x + size.x && + point.y >= offset.y && + point.y < offset.y + size.y) + { + return item; + } + } + return nullptr; + } + + + void + DrawingIsland::Accessibility_Initialize() + { + // Create an UI automation fragment root for our island's content. + m_uia.FragmentRoot = winrt::make_self(); + m_uia.FragmentRoot->SetName(L"Drawing Squares"); + m_uia.FragmentRoot->SetProviderOptions( + ProviderOptions_ServerSideProvider | + ProviderOptions_UseComThreading | + ProviderOptions_RefuseNonClientSupport); + m_uia.FragmentRoot->SetUiaControlTypeId(UIA_WindowControlTypeId); + m_uia.FragmentRoot->SetCallbackHandler(this); + + (void)m_island.AutomationProviderRequested( + { this, &DrawingIsland::Accessibility_OnAutomationProviderRequested }); + } + + + void + DrawingIsland::Accessibility_CreateItemFragment( + const winrt::Visual& itemVisual) + { + // Create a new automation fragment. + auto fragment = winrt::make_self(); + fragment->SetName(s_colorNames[m_output.CurrentColorIndex].c_str()); + fragment->SetCallbackHandler(this); + + // Add an entry to our automation peers (a mapping between the Visual and the Fragment): + // - This is keeping the UIA objects alive. + // - The lookup is used to get back to the item Fragment for + // specific operations, such as hit-testing or tree walking. + // This avoids adding to more expensive data storage, + // such as the Visual.CustomProperties map. + m_uia.AutomationPeers.push_back(AutomationPeer{ itemVisual, fragment }); + + // Connect the automation fragment to our fragment root. + m_uia.FragmentRoot->AddChildToEnd(fragment); + } + + + void + DrawingIsland::Accessibility_OnAutomationProviderRequested( + const winrt::ContentIsland& island, + const winrt::ContentIslandAutomationProviderRequestedEventArgs& args) + { + // Make sure the host provider is up to date. + m_uia.FragmentRoot->SetHostProvider( + island.GetAutomationHostProvider().as()); + + // Return the fragment root as an IInspectable. + args.AutomationProvider(m_uia.FragmentRoot.as()); + + args.Handled(true); + } + + + void + DrawingIsland::Input_Initialize() + { + m_input.PointerSource = winrt::InputPointerSource::GetForIsland(m_island); + + m_input.PointerSource.PointerPressed( + [this](winrt::InputPointerSource const&, + winrt::PointerEventArgs const& args) + { + auto currentPoint = args.CurrentPoint(); + auto properties = currentPoint.Properties(); + + if (properties.IsLeftButtonPressed()) + { + Input_OnLeftButtonPressed(args); + } + else if (properties.IsRightButtonPressed()) + { + Input_OnRightButtonPressed(args); + } + }); + + m_input.PointerSource.PointerMoved( + [this](winrt::InputPointerSource const&, + winrt::PointerEventArgs const& args) + { + Input_OnPointerMoved(args); + }); + + m_input.PointerSource.PointerReleased( + [&](auto&& ...) + { + Input_OnPointerReleased(); + }); + + // Set up the keyboard source. + m_input.KeyboardSource = winrt::InputKeyboardSource::GetForIsland(m_island); + + m_input.KeyboardSource.KeyDown( + [this](winrt::InputKeyboardSource const&, + winrt::KeyEventArgs const& args) + { + bool handled = Input_OnKeyDown(args.VirtualKey()); + + // Mark the event as handled + if (handled) + { + args.Handled(true); + } + }); + + m_input.PretranslateSource = + winrt::InputPreTranslateKeyboardSource::GetForIsland(m_island); + + m_input.PretranslateSource.as< + Microsoft::UI::Input::IInputPreTranslateKeyboardSourceInterop>()-> + SetPreTranslateHandler(this); + + auto activationListener = winrt::InputActivationListener::GetForIsland(m_island); + (void)activationListener.InputActivationChanged( + [this, activationListener]( + winrt::InputActivationListener const&, + winrt::InputActivationListenerActivationChangedEventArgs const&) + { + switch (activationListener.State()) + { + case winrt::InputActivationState::Activated: + m_output.RootVisual.Opacity(1.0f); + if (nullptr != m_background.BackdropConfiguration) + { + m_background.BackdropConfiguration.IsInputActive(true); + } + break; + + default: + m_output.RootVisual.Opacity(m_output.Opacity); + if (nullptr != m_background.BackdropConfiguration) + { + m_background.BackdropConfiguration.IsInputActive(false); + } + break; + } + }); + + m_input.FocusController = winrt::InputFocusController::GetForIsland(m_island); + m_input.FocusController.NavigateFocusRequested( + [this](winrt::InputFocusController const&, + winrt::FocusNavigationRequestEventArgs const& args) + { + bool setFocus = m_input.FocusController.TrySetFocus(); + // Mark the event as handled + if (setFocus) + { + args.Result(winrt::FocusNavigationResult::Moved); + } + }); + } + + + bool + DrawingIsland::Input_OnKeyDown( + winrt::Windows::System::VirtualKey virtualKey) + { + bool handled = false; + + switch (virtualKey) + { + case winrt::VirtualKey::A: + { + m_background.Visual.Brush(m_background.BrushA); + handled = true; + break; + } + + case winrt::VirtualKey::B: + { + m_background.Visual.Brush(m_background.BrushB); + handled = true; + break; + } + + case winrt::VirtualKey::C: + { + m_background.Visual.Brush(m_background.BrushC); + handled = true; + break; + } + + case winrt::VirtualKey::Space: + { + m_background.Visual.Brush(m_background.BrushDefault); + break; + } + + case winrt::Windows::System::VirtualKey::Number1: + { + m_output.CurrentColorIndex = 0; + handled = true; + break; + } + + case winrt::Windows::System::VirtualKey::Number2: + { + m_output.CurrentColorIndex = 1; + handled = true; + break; + } + + case winrt::Windows::System::VirtualKey::Number3: + { + m_output.CurrentColorIndex = 2; + handled = true; + break; + } + + case winrt::Windows::System::VirtualKey::Number4: + { + m_output.CurrentColorIndex = 3; + handled = true; + break; + } + + case winrt::Windows::System::VirtualKey::Delete: + case winrt::Windows::System::VirtualKey::Escape: + { + m_items.Visuals.RemoveAll(); + m_items.Items.clear(); + + // Update accessibility. + m_uia.FragmentRoot->RemoveAllChildren(); + m_uia.AutomationPeers.clear(); + + handled = true; + break; + } + + case winrt::Windows::System::VirtualKey::Tab: + { + auto request = winrt::Microsoft::UI::Input::FocusNavigationRequest::Create( + winrt::Microsoft::UI::Input::FocusNavigationReason::First); + m_input.FocusController.DepartFocus(request); + } + } + + Output_UpdateCurrentColorVisual(); + + return handled; + } + + bool + DrawingIsland::Input_AcceleratorKeyActivated( + winrt::Windows::System::VirtualKey virtualKey) + { + bool handled = false; + + switch (virtualKey) + { + case winrt::VirtualKey::X: + { + m_background.Visual.Brush(m_background.BrushA); + handled = true; + break; + } + + case winrt::VirtualKey::Y: + { + m_background.Visual.Brush(m_background.BrushB); + handled = true; + break; + } + + case winrt::VirtualKey::Z: + { + m_background.Visual.Brush(m_background.BrushC); + handled = true; + break; + } + } + + return handled; + } + + + void + DrawingIsland::Input_OnLeftButtonPressed( + const winrt::PointerEventArgs& args) + { + // Left button manipulates the custom-drawn content + float2 const point = args.CurrentPoint().Position(); + + bool controlPressed = WI_IsFlagSet( + args.KeyModifiers(), + winrt::Windows::System::VirtualKeyModifiers::Control); + + OnLeftClick(point, controlPressed); + } + + + void + DrawingIsland::Input_OnPointerReleased() + { + m_items.SelectedItem = nullptr; + } + + + void + DrawingIsland::LeftClickAndRelease( + const float2 currentPoint) + { + OnLeftClick(currentPoint, false); + Input_OnPointerReleased(); + } + + + void + DrawingIsland::RightClickAndRelease( + const float2 currentPoint) + { + OnRightClick(currentPoint); + Input_OnPointerReleased(); + } + + + void + DrawingIsland::OnLeftClick( + const float2 point, + bool controlPressed) + { + m_items.SelectedItem = HitTestItem(point); + + if (m_items.SelectedItem != nullptr) + { + Item* item = m_items.SelectedItem; + auto& visual = m_items.SelectedItem->GetVisual(); + winrt::float3 const offset = visual.Offset(); + + m_items.Offset.x = offset.x - point.x; + m_items.Offset.y = offset.y - point.y; + + // Move the visual to the top. + m_items.Visuals.Remove(visual); + m_items.Visuals.InsertAtTop(visual); + + // Move the VisualElement to the end of the vector if it isn't already. + if (!m_items.Items.empty() && m_items.Items.back().get() != item) + { + auto i = std::find_if( + m_items.Items.begin(), + m_items.Items.end(), + [item](auto& elem) { return elem.get() == item; } + ); + if (i != m_items.Items.end()) + { + std::rotate(i, i + 1, m_items.Items.end()); + } + } + + // Update automation. + // First find the existing automation peer. + auto iterator = std::find_if( + m_uia.AutomationPeers.begin(), m_uia.AutomationPeers.end(), + [visual](auto const& automationPeer) + { + return automationPeer.Match(visual); + }); + if (m_uia.AutomationPeers.end() != iterator) + { + // Mirror the change to the visuals above. + m_uia.FragmentRoot->RemoveChild(iterator->GetAutomationProvider()); + m_uia.FragmentRoot->AddChildToEnd(iterator->GetAutomationProvider()); + } + } + else + { + Output_AddVisual(point, controlPressed); + } + } + + + void + DrawingIsland::Input_OnRightButtonPressed( + const winrt::PointerEventArgs& args) + { + OnRightClick(args.CurrentPoint().Position()); + } + + void + DrawingIsland::OnRightClick(const float2 point) + { + // TODO - what is the purpose of this? + UNREFERENCED_PARAMETER(point); + // auto selectedVisual = HitTestVisual(point); + } + + void + DrawingIsland::Input_OnPointerMoved( + const winrt::PointerEventArgs& args) + { + if (m_items.SelectedItem) + { + auto& visual = m_items.SelectedItem->GetVisual(); + float2 const point = args.CurrentPoint().Position(); + + visual.Offset( + { point.x + m_items.Offset.x, + point.y + m_items.Offset.y, + 0.0f }); + } + } + + + void + DrawingIsland::Island_OnClosed() + { + + } + + + void + DrawingIsland::Island_OnStateChanged() + { + if (m_prevState.RasterizationScale != m_island.RasterizationScale()) + { + float newScale = m_island.RasterizationScale(); + + m_prevState.RasterizationScale = newScale; + + m_output.TextRenderer->SetDpiScale(newScale); + + for (auto& item : m_items.Items) + { + item->OnDpiScaleChanged(); + } + } + + if (m_prevState.LayoutDirection != m_island.LayoutDirection()) + { + Environment_SetLayoutDirection(); + } + + Output_UpdateCurrentColorVisual(); + } + + + void + DrawingIsland::Environment_SetLayoutDirection() + { + if (m_island.LayoutDirection() == ContentLayoutDirection::RightToLeft) + { + // The following will mirror the visuals. If any text is inside the visuals the text is + // also mirrored. The text will need another RelativeOffsetAdjustment and Scale to + // return to the normal space. + + m_output.RootVisual.RelativeOffsetAdjustment(winrt::float3(1, 0, 0)); + m_output.RootVisual.Scale(winrt::float3(-1, 1, 1)); + } + else + { + m_output.RootVisual.RelativeOffsetAdjustment(winrt::float3(0, 0, 0)); + m_output.RootVisual.Scale(winrt::float3(1, 1, 1)); + } + m_prevState.LayoutDirection = m_island.LayoutDirection(); + } + + + void + DrawingIsland::OnDirect3DDeviceLost( + DeviceLostHelper const* /* sender */, + DeviceLostEventArgs const& /* args */) + { + // This call comes in on a Threadpool worker thread, so use the DispatcherQueue + // to marshal the call to the UI thread. + m_island.DispatcherQueue().TryEnqueue( + [this] { + // Recreate the text renderer's D3D and D2D devices. + m_output.TextRenderer->RecreateDirect2DDevice(); + + // Give each item an opportunity to recreate its device-dependent resources. + for (auto& item : m_items.Items) + { + item->OnDeviceLost(); + } + + // Listen for device lost on the new device. + m_output.DeviceLostHelper.WatchDevice(m_output.TextRenderer->GetDevice()); + }); + } + + + void + DrawingIsland::Output_Initialize() + { + // Create the background visual. + m_background.Visual = m_output.Compositor.CreateSpriteVisual(); + m_background.Visual.RelativeSizeAdjustment({ 1.0f, 1.0f }); + + m_background.BrushDefault = m_output.Compositor.CreateColorBrush( + winrt::Color{ 0xFF, 0x20, 0x20, 0x20 }); + + m_background.BrushA = m_output.Compositor.CreateColorBrush( + winrt::Color{ 0xFF, 0x99, 0x20, 0x20 }); + + m_background.BrushB = m_output.Compositor.CreateColorBrush( + winrt::Color{ 0xFF, 0x20, 0x99, 0x20 }); + + m_background.BrushC = m_output.Compositor.CreateColorBrush( + winrt::Color{ 0xFF, 0x20, 0x20, 0x99 }); + + m_background.Visual.Brush(m_background.BrushDefault); + m_output.RootVisual.Children().InsertAtTop(m_background.Visual); + + for (int i = 0; i < _countof(m_output.ColorBrushes); i++) + { + m_output.ColorBrushes[i] = m_output.Compositor.CreateColorBrush(s_colors[i]); + + winrt::Color halfTransparent = s_colors[i]; + halfTransparent.A = 0x80; + m_output.HalfTransparentColorBrushes[i] = + m_output.Compositor.CreateColorBrush(halfTransparent); + } + + winrt::ContainerVisual drawingVisualsRoot = m_output.Compositor.CreateContainerVisual(); + m_items.Visuals = drawingVisualsRoot.Children(); + m_output.RootVisual.Children().InsertAtTop(drawingVisualsRoot); + + m_items.CurrentColorVisual = m_output.Compositor.CreateSpriteVisual(); + m_items.CurrentColorVisual.Offset({0.0f, 0.0f, 0.0f}); + m_output.RootVisual.Children().InsertAtTop(m_items.CurrentColorVisual); + + Output_UpdateSystemBackdrop(); + + Output_UpdateCurrentColorVisual(); + } + + + void + DrawingIsland::Output_AddVisual( + float2 const point, + bool halfTransparent) + { + // Determine the visual background and text colors. + Color backgroundColor = s_colors[m_output.CurrentColorIndex]; + Color textColor = { 0xFF, 0, 0, 0 }; + if (halfTransparent) + { + backgroundColor.A /= 2; + textColor.A /= 2; + } + + // Create a TextElement object. + auto textItem = std::make_unique( + m_output.TextRenderer, + backgroundColor, + textColor, + s_colorNames[m_output.CurrentColorIndex] + ); + + // Get the visual and its size in DIPs. + auto& visual = textItem->GetVisual(); + float2 size = visual.Size(); + + // Set the visual's offset. + visual.Offset({ point.x - size.x / 2.0f, point.y - size.y / 2.0f, 0.0f }); + + // Add the new text element to the vector. + m_items.Items.push_back(std::move(textItem)); + + // Add the visual as a child of the container visual. + m_items.Visuals.InsertAtTop(visual); + + m_items.SelectedItem = m_items.Items.back().get(); + m_items.Offset.x = -size.x / 2.0f; + m_items.Offset.y = -size.y / 2.0f; + + Accessibility_CreateItemFragment(visual); + } + + + void + DrawingIsland::Output_UpdateCurrentColorVisual() + { + m_items.CurrentColorVisual.Brush(m_output.ColorBrushes[m_output.CurrentColorIndex]); + m_items.CurrentColorVisual.Offset({0.0f, m_island.ActualSize().y - 25.0f, 0.0f}); + m_items.CurrentColorVisual.Size({m_island.ActualSize().x, 25.0f}); + } + + + void + DrawingIsland::Output_UpdateSystemBackdrop() + { + if (m_background.BackdropEnabled && nullptr == m_background.BackdropController) + { + // Reduce the opacity of the background color visual so that we can see + // the Mica/DesktopAcrylic behind it. + m_background.Visual.Opacity(0.1f); + + // Create a new SystemBackdropConfiguration if we do not already have one. + if (nullptr == m_background.BackdropConfiguration) + { + m_background.BackdropConfiguration = winrt::SystemBackdropConfiguration(); + } + + // Decide between Mica and DesktopAcrylic. + if (winrt::MicaController::IsSupported()) + { + m_background.BackdropController = winrt::MicaController(); + + } + else + { + m_background.BackdropController = winrt::DesktopAcrylicController(); + } + + // Link the SystemBackdropConfiguration to our SystemBackdropController. + m_background.BackdropController.SetSystemBackdropConfiguration( + m_background.BackdropConfiguration); + + // Add our island as the target. + m_background.BackdropController.AddSystemBackdropTarget(m_island); + } + else + { + // Reset the background opacity to 1.0 + m_background.Visual.Opacity(1.0f); + + if (nullptr != m_background.BackdropController) + { + // Clean up our SystemBackdropController. + m_background.BackdropController.RemoveAllSystemBackdropTargets(); + m_background.BackdropController.Close(); + m_background.BackdropController = nullptr; + } + } + } + + void + DrawingIsland::Environment_Initialize() + { + auto window = m_island.Environment(); + + (void)window.SettingChanged( + [this](winrt::ContentIslandEnvironment const&, + winrt::ContentEnvironmentSettingChangedEventArgs const& args) + { + return Environment_OnSettingChanged(args); + }); + + (void)window.StateChanged( + [this](winrt::ContentIslandEnvironment const& sender, winrt::IInspectable const&) + { + return Environment_OnStateChanged(sender); + }); + } + + + void + DrawingIsland::Environment_OnSettingChanged( + const winrt::ContentEnvironmentSettingChangedEventArgs& args) + { + auto settingChanged = args.SettingName(); + + if (settingChanged == L"intl") + { + m_background.Visual.Brush(m_background.BrushA); + } + } + + + void + DrawingIsland::Environment_OnStateChanged(winrt::ContentIslandEnvironment const& /*sender*/) + { + + } +} // namespace winrt::OneTest::ContentIslandHelpers::implementation diff --git a/Samples/Islands/WpfCalculator/DrawingIslandComponents/DrawingIsland.h b/Samples/Islands/WpfCalculator/DrawingIslandComponents/DrawingIsland.h new file mode 100644 index 000000000..a1924001f --- /dev/null +++ b/Samples/Islands/WpfCalculator/DrawingIslandComponents/DrawingIsland.h @@ -0,0 +1,300 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once + +#include "DrawingIsland.g.h" +#include "AutomationFragmentRoot.h" +#include "AutomationPeer.h" +#include "TextRenderer.h" +#include "DeviceLostHelper.h" +#include "TextItem.h" + +namespace winrt::DrawingIslandComponents::implementation +{ + struct DrawingIsland : + public DrawingIslandT< + DrawingIsland, + Microsoft::UI::Input::IInputPreTranslateKeyboardSourceHandler>, + IAutomationCallbackHandler + { + public: + // Construction + + DrawingIsland( + const winrt::Compositor& compositor); + + ~DrawingIsland(); + + // IClosable methods + void Close(); + + // Properties + + bool EnableBackgroundTransparency() + { + return m_background.BackdropEnabled; + } + + void EnableBackgroundTransparency( + bool value); + + winrt::ContentIsland Island() const + { + return m_island; + } + + // Methods + + void LeftClickAndRelease( + const float2 currentPoint); + + void RightClickAndRelease( + const float2 currentPoint); + + void SetIslandOpacity(float islandOpacity) + { + m_output.Opacity = islandOpacity; + } + + void SetColorIndex(std::uint32_t colorIndex) + { + m_output.CurrentColorIndex = std::clamp( + colorIndex, 0, _countof(s_colors) - 1); + + if (m_output.CurrentColorIndex >= 4) + { + m_background.BrushDefault = + m_output.Compositor.CreateColorBrush(s_colors[m_output.CurrentColorIndex]); + + m_background.Visual.Brush(m_background.BrushDefault); + } + Output_UpdateCurrentColorVisual(); + } + + // IInputKeyboardSourcePreTranslateHandler methods + IFACEMETHOD(OnDirectMessage)( + IInputPreTranslateKeyboardSourceInterop* source, + const MSG* msg, + UINT keyboardModifiers, + _Inout_ bool* handled); + + IFACEMETHOD(OnTreeMessage)( + IInputPreTranslateKeyboardSourceInterop* source, + const MSG* msg, + UINT keyboardModifiers, + _Inout_ bool* handled); + + // IAutomationCallbackHandler overrides. + winrt::Windows::Graphics::RectInt32 GetScreenBoundsForAutomationFragment( + _In_::IUnknown const* const sender) const override; + + winrt::com_ptr GetFragmentFromPoint( + _In_ double x, + _In_ double y) const override; + + winrt::com_ptr GetFragmentInFocus() const override; + + private: + Item* HitTestItem(float2 const& point) const; + + void Accessibility_Initialize(); + + void Accessibility_CreateItemFragment( + const winrt::Visual& itemVisual); + + void Accessibility_OnAutomationProviderRequested( + const winrt::ContentIsland& island, + const winrt::ContentIslandAutomationProviderRequestedEventArgs& args); + + void Input_Initialize(); + + bool Input_OnKeyDown( + winrt::Windows::System::VirtualKey virtualKey); + + bool Input_AcceleratorKeyActivated( + winrt::Windows::System::VirtualKey virtualKey); + + void Input_OnLeftButtonPressed( + const winrt::PointerEventArgs& args); + + void Input_OnRightButtonPressed( + const winrt::PointerEventArgs& args); + + void Input_OnPointerMoved( + const winrt::PointerEventArgs& args); + + void Input_OnPointerReleased(); + + void OnLeftClick( + const float2 point, + bool controlPressed); + + void OnRightClick( + const float2 currentPoint); + + void Island_OnClosed(); + + void Island_OnStateChanged(); + + void OnDirect3DDeviceLost( + DeviceLostHelper const* /* sender */, + DeviceLostEventArgs const& /* args */); + + void Output_Initialize(); + + void Output_AddVisual( + const float2 point, + bool halfTransparent); + + void Output_UpdateCurrentColorVisual(); + + void Output_UpdateSystemBackdrop(); + + void Environment_Initialize(); + + void Environment_OnSettingChanged( + const winrt::ContentEnvironmentSettingChangedEventArgs& args); + + void Environment_OnStateChanged(winrt::ContentIslandEnvironment const& sender); + + void Environment_SetLayoutDirection(); + + private: + static inline winrt::Color s_colors[] = + { + { 0xFF, 0x5B, 0x9B, 0xD5 }, + { 0xFF, 0xED, 0x7D, 0x31 }, + { 0xFF, 0x70, 0xAD, 0x47 }, + { 0xFF, 0xFF, 0xC0, 0x00 }, + { 0xFF, 0xFA, 0xEB, 0xD7 }, + { 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFA, 0xFA }, + { 0xFF, 0xFF, 0xC0, 0xCB }, + { 0xFF, 0xB0, 0xE0, 0xE6 }, + { 0xFF, 0x98, 0xFB, 0x98 }, + { 0xFF, 0x87, 0xCE, 0xFA }, + }; + + static inline std::wstring s_colorNames[] = + { + L"Blue", + L"Orange", + L"Green", + L"Yellow", + L"AntiqueWhite", + L"White", + L"Snow", + L"Pink", + L"PowderBlue", + L"PaleGreen", + L"LightSkyBlue", + }; + + // The underlying Island holding everything together. + winrt::ContentIsland m_island{ nullptr }; + + // Output + struct + { + winrt::Compositor Compositor{ nullptr }; + + winrt::ContainerVisual RootVisual{ nullptr }; + + std::shared_ptr TextRenderer; + DeviceLostHelper DeviceLostHelper; + + float Opacity{ 0.5f }; + + // Current color used for new items + unsigned int CurrentColorIndex = 0; + + // Cached brushes for items + winrt::CompositionColorBrush ColorBrushes[_countof(s_colors)] + { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr }; + + winrt::CompositionColorBrush HalfTransparentColorBrushes[_countof(s_colors)] + { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr }; + } m_output; + + // Input handling + struct + { + // Keyboard input handling + winrt::InputKeyboardSource KeyboardSource{ nullptr }; + + // Message loop integration + winrt::InputPreTranslateKeyboardSource PretranslateSource{ nullptr }; + + // Spatial input handling (mouse, pen, touch, etc.) + winrt::InputPointerSource PointerSource{ nullptr }; + + // Focus navigation handling + winrt::InputFocusController FocusController{ nullptr }; + } m_input; + + // Background behind the items + struct Background + { + winrt::CompositionColorBrush BrushDefault{ nullptr }; + winrt::CompositionColorBrush BrushA{ nullptr }; + winrt::CompositionColorBrush BrushB{ nullptr }; + winrt::CompositionColorBrush BrushC{ nullptr }; + winrt::SpriteVisual Visual{ nullptr }; + winrt::RectangleClip Clip{ nullptr }; + + // System backdrops (Mica on Win11+, DesktopAcrylic on Win10) + bool BackdropEnabled{ true }; + winrt::SystemBackdropConfiguration BackdropConfiguration{ nullptr }; + winrt::ISystemBackdropControllerWithTargets BackdropController{ nullptr }; + } m_background; + + // Drawing items being manipulated. + struct + { + // The container visual's Children collection. Each Item's visual must be + // added to this collection to be rendered. + winrt::VisualCollection Visuals{ nullptr }; + + // Vector of Item objects representing items that can be manipulated, in + // back-to-front order. Each item has an associated Visual. + std::vector> Items; + + // Pointer to the currently-selected item, if any. + Item* SelectedItem{ nullptr }; + + // Offset from the top-left corner of the selected item to the pointer. + float2 Offset{}; + + // Visual that shows the current color. + winrt::SpriteVisual CurrentColorVisual{ nullptr }; + } m_items; + + struct + { + float RasterizationScale = 0; + + winrt::ContentLayoutDirection LayoutDirection = + winrt::ContentLayoutDirection::LeftToRight; + } m_prevState; + + struct + { + // The UIA parent Root for this Island that contains the fragment children. + winrt::com_ptr FragmentRoot{ nullptr }; + + // Map a given square (Visual) to its UIA fragment object. + std::vector AutomationPeers{}; + } m_uia; + }; +} + +namespace winrt::DrawingIslandComponents::factory_implementation +{ + struct DrawingIsland : + DrawingIslandT + { + }; +} diff --git a/Samples/Islands/WpfCalculator/DrawingIslandComponents/DrawingIslandComponents.def b/Samples/Islands/WpfCalculator/DrawingIslandComponents/DrawingIslandComponents.def new file mode 100644 index 000000000..24e7c1235 --- /dev/null +++ b/Samples/Islands/WpfCalculator/DrawingIslandComponents/DrawingIslandComponents.def @@ -0,0 +1,3 @@ +EXPORTS +DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE +DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE diff --git a/Samples/Islands/WpfCalculator/DrawingIslandComponents/DrawingIslandComponents.vcxproj b/Samples/Islands/WpfCalculator/DrawingIslandComponents/DrawingIslandComponents.vcxproj new file mode 100644 index 000000000..c817eed95 --- /dev/null +++ b/Samples/Islands/WpfCalculator/DrawingIslandComponents/DrawingIslandComponents.vcxproj @@ -0,0 +1,190 @@ + + + + + + + true + true + true + true + {709c54e1-0f2f-4a59-80b2-4cfd08b720e5} + DrawingIslandComponents + DrawingIslandComponents + en-US + 14.0 + 10.0.22621.0 + 10.0.17134.0 + true + C++/WinRT + + + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + DynamicLibrary + v143 + v142 + v141 + v140 + Unicode + false + + + true + true + + + false + true + false + + + true + + + true + + + true + + + true + + + true + + + true + + + + + + + + + + + + + + + + + Use + pch.h + $(IntDir)pch.pch + Level4 + %(AdditionalOptions) /bigobj + _WINRT_DLL;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + + + Console + false + DrawingIslandComponents.def + + + + + _DEBUG;%(PreprocessorDefinitions) + + + + + NDEBUG;%(PreprocessorDefinitions) + + + true + true + + + + + + + + + + + Components.idl + + + + + + + + + + + Create + + + Components.idl + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/Islands/WpfCalculator/DrawingIslandComponents/DrawingIslandComponents.vcxproj.filters b/Samples/Islands/WpfCalculator/DrawingIslandComponents/DrawingIslandComponents.vcxproj.filters new file mode 100644 index 000000000..8d5d319bd --- /dev/null +++ b/Samples/Islands/WpfCalculator/DrawingIslandComponents/DrawingIslandComponents.vcxproj.filters @@ -0,0 +1,83 @@ + + + + + accd3aa8-1ba0-4223-9bbe-0c431709210b + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms + + + {926ab91d-31b4-48c3-b9a4-e681349f27f0} + + + {d824b7c5-294e-46a7-ae4e-2d146beef954} + + + {23c94a0e-e18d-4439-9afc-234fafb5cfcb} + + + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/Islands/WpfCalculator/DrawingIslandComponents/Item.cpp b/Samples/Islands/WpfCalculator/DrawingIslandComponents/Item.cpp new file mode 100644 index 000000000..4e28b475e --- /dev/null +++ b/Samples/Islands/WpfCalculator/DrawingIslandComponents/Item.cpp @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include "pch.h" +#include "Item.h" + +namespace winrt::DrawingIslandComponents::implementation +{ + Item::Item(winrt::Compositor const& compositor) : + m_visual(compositor.CreateSpriteVisual()) + { + } +} diff --git a/Samples/Islands/WpfCalculator/DrawingIslandComponents/Item.h b/Samples/Islands/WpfCalculator/DrawingIslandComponents/Item.h new file mode 100644 index 000000000..14d8a7569 --- /dev/null +++ b/Samples/Islands/WpfCalculator/DrawingIslandComponents/Item.h @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once + +namespace winrt::DrawingIslandComponents::implementation +{ + // Abstract base class for an item that owns a SpriteVisual and can + // re-rasterize the sprite if the DPI changes. + class Item + { + public: + Item(winrt::Compositor const& compositor); + + virtual ~Item() + { + } + + virtual void OnDpiScaleChanged() + { + } + + virtual void OnDeviceLost() + { + } + + winrt::SpriteVisual const& GetVisual() const noexcept + { + return m_visual; + } + + private: + winrt::SpriteVisual m_visual; + }; +} diff --git a/Samples/Islands/WpfCalculator/DrawingIslandComponents/PropertySheet.props b/Samples/Islands/WpfCalculator/DrawingIslandComponents/PropertySheet.props new file mode 100644 index 000000000..e34141b01 --- /dev/null +++ b/Samples/Islands/WpfCalculator/DrawingIslandComponents/PropertySheet.props @@ -0,0 +1,16 @@ + + + + + + + + \ No newline at end of file diff --git a/Samples/Islands/WpfCalculator/DrawingIslandComponents/TextItem.cpp b/Samples/Islands/WpfCalculator/DrawingIslandComponents/TextItem.cpp new file mode 100644 index 000000000..823c4469c --- /dev/null +++ b/Samples/Islands/WpfCalculator/DrawingIslandComponents/TextItem.cpp @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include "pch.h" +#include "TextItem.h" + +namespace winrt::DrawingIslandComponents::implementation +{ + TextItem::TextItem( + std::shared_ptr const& textRenderer, + Windows::UI::Color backgroundColor, + Windows::UI::Color textColor, + std::wstring const& text) : + Item(textRenderer->GetCompositor()), + m_textRenderer(textRenderer), + m_backgroundColor(backgroundColor), + m_textColor(textColor), + m_text(text) + { + InitializeVisual(); + } + + void TextItem::InitializeVisual() + { + // Render the text to the sprite visual. + m_textRenderer->Render(m_text.c_str(), m_backgroundColor, m_textColor, GetVisual()); + } +} diff --git a/Samples/Islands/WpfCalculator/DrawingIslandComponents/TextItem.h b/Samples/Islands/WpfCalculator/DrawingIslandComponents/TextItem.h new file mode 100644 index 000000000..e0754bf4a --- /dev/null +++ b/Samples/Islands/WpfCalculator/DrawingIslandComponents/TextItem.h @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once + +#include "TextRenderer.h" +#include "Item.h" + +namespace winrt::DrawingIslandComponents::implementation +{ + class TextItem final : public Item + { + public: + TextItem( + std::shared_ptr const& textRenderer, + Windows::UI::Color backgroundColor, + Windows::UI::Color textColor, + std::wstring const& text); + + void OnDpiScaleChanged() override + { + // Re-render the text using the current DPI scale. + InitializeVisual(); + } + + void OnDeviceLost() override + { + // Re-render the text using the current device. + InitializeVisual(); + } + + private: + void InitializeVisual(); + + std::shared_ptr m_textRenderer; + Windows::UI::Color m_backgroundColor; + Windows::UI::Color m_textColor; + std::wstring m_text; + }; +} diff --git a/Samples/Islands/WpfCalculator/DrawingIslandComponents/TextRenderer.cpp b/Samples/Islands/WpfCalculator/DrawingIslandComponents/TextRenderer.cpp new file mode 100644 index 000000000..c071f768f --- /dev/null +++ b/Samples/Islands/WpfCalculator/DrawingIslandComponents/TextRenderer.cpp @@ -0,0 +1,201 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include "pch.h" +#include "TextRenderer.h" + +namespace winrt::DrawingIslandComponents::implementation +{ + TextRenderer::TextRenderer(winrt::Compositor compositor) : m_compositor(compositor) + { + // Create the DWrite factory object. + winrt::check_hresult(DWriteCreateFactory( + DWRITE_FACTORY_TYPE_SHARED, + __uuidof(decltype(*m_dwriteFactory)), + reinterpret_cast<::IUnknown**>(m_dwriteFactory.put()))); + + // Create an object that encapsulates text formatting properties. + constexpr float defaultFontSize = 16; + winrt::check_hresult(m_dwriteFactory->CreateTextFormat( + L"Segoe UI", + nullptr, + DWRITE_FONT_WEIGHT_NORMAL, + DWRITE_FONT_STYLE_NORMAL, + DWRITE_FONT_STRETCH_NORMAL, + defaultFontSize, + L"en-US", + m_textFormat.put())); + winrt::check_hresult(m_textFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP)); + + // Create the D2D factory. + winrt::check_hresult(D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED, m_d2dFactory.put())); + + // Create the Direct3D and Direct2D device objects. + CreateDirect2DDevice(); + + // Create the composition graphics device. + auto compositorInterop = m_compositor.as(); + ICompositionGraphicsDevice compositionGraphicsDevice; + winrt::check_hresult(compositorInterop->CreateGraphicsDevice(m_d2dDevice.get(), &compositionGraphicsDevice)); + m_compositionGraphicsDevice = compositionGraphicsDevice.as(); + } + + void TextRenderer::RecreateDirect2DDevice() + { + // Release the old Direct2D and Direct2D device objects. + m_dxgiDevice = nullptr; + m_d2dDevice = nullptr; + + // Create new Direct3D and Direct2D device objects. + CreateDirect2DDevice(); + + // Restore the composition graphics device to health by pointing to the new Direct2D device. + auto compositionGraphicsDeviceInterop = m_compositionGraphicsDevice.as(); + winrt::check_hresult(compositionGraphicsDeviceInterop->SetRenderingDevice(m_d2dDevice.get())); + } + + void TextRenderer::CreateDirect2DDevice() + { + uint32_t createDeviceFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; + + // Array with DirectX hardware feature levels in order of preference. + static const D3D_FEATURE_LEVEL featureLevels[] = + { + D3D_FEATURE_LEVEL_11_1, + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, + D3D_FEATURE_LEVEL_9_3, + D3D_FEATURE_LEVEL_9_2, + D3D_FEATURE_LEVEL_9_1 + }; + + // Create the Direct3D 11 API device object and a corresponding context. + winrt::com_ptr<::ID3D11Device> d3dDevice; + winrt::com_ptr<::ID3D11DeviceContext> d3dImmediateContext; + D3D_FEATURE_LEVEL d3dFeatureLevel{ D3D_FEATURE_LEVEL_9_1 }; + + winrt::check_hresult(D3D11CreateDevice( + nullptr, // Default adapter. + D3D_DRIVER_TYPE_HARDWARE, + 0, // Not asking for a software driver, so not passing a module to one. + createDeviceFlags, // Set debug and Direct2D compatibility flags. + featureLevels, + ARRAYSIZE(featureLevels), + D3D11_SDK_VERSION, + d3dDevice.put(), + &d3dFeatureLevel, + d3dImmediateContext.put())); + + // Initialize Direct2D resources. + D2D1_FACTORY_OPTIONS d2d1FactoryOptions{ D2D1_DEBUG_LEVEL_NONE }; + + // Create the Direct2D device object. + // Obtain the underlying DXGI device of the Direct3D device. + auto dxgiDevice = d3dDevice.as<::IDXGIDevice>(); + + winrt::com_ptr d2dDevice; + winrt::check_hresult(m_d2dFactory->CreateDevice(dxgiDevice.get(), d2dDevice.put())); + + // Save the newly-created objects. + m_dxgiDevice = std::move(dxgiDevice); + m_d2dDevice = std::move(d2dDevice); + } + + void TextRenderer::Render( + _In_z_ WCHAR const* text, + Windows::UI::Color backgroundColor, + Windows::UI::Color textColor, + SpriteVisual const& visual) + { + // Margins between the layout bounds of the text and the edges of the visual. + // These are in device-independent pixels (DIPs). + constexpr float marginLeft = 5; + constexpr float marginRight = 5; + constexpr float marginTop = 5; + constexpr float marginBottom = 5; + + // Create the IDWriteTextlayout object. This will be used to render the text + // and can also be used to get properties, such as the size. + winrt::com_ptr textLayout; + winrt::check_hresult(m_dwriteFactory->CreateTextLayout( + text, + static_cast(wcslen(text)), + m_textFormat.get(), + /*maxWidth*/ 0, + /*maxHeight*/ 0, + /*out*/ textLayout.put())); + + // Get the metrics from the text layout, and add the margins to compute the + // width and height of the visual. + DWRITE_TEXT_METRICS textMetrics; + winrt::check_hresult(textLayout->GetMetrics(/*out*/ &textMetrics)); + const float width = textMetrics.width + (marginLeft + marginRight); + const float height = textMetrics.height + (marginTop + marginBottom); + + visual.Size(float2(width, height)); + + try + { + // Create a composition surface to draw to. + CompositionDrawingSurface drawingSurface = m_compositionGraphicsDevice.CreateDrawingSurface( + winrt::Windows::Foundation::Size(width * m_dpiScale, height * m_dpiScale), + winrt::Microsoft::Graphics::DirectX::DirectXPixelFormat::B8G8R8A8UIntNormalized, + winrt::Microsoft::Graphics::DirectX::DirectXAlphaMode::Premultiplied); + auto drawingSurfaceInterop = drawingSurface.as(); + + // Begin drawing to get a Direct2D device context. + winrt::com_ptr deviceContext; + POINT pixelOffset; + winrt::check_hresult(drawingSurfaceInterop->BeginDraw( + nullptr, + __uuidof(ID2D1DeviceContext), + deviceContext.put_void(), + &pixelOffset)); + + // Set the DPI of the device context, where 96 DPI corresponds to a 1.0 scale factor. + deviceContext->SetDpi(m_dpiScale * 96, m_dpiScale * 96); + + // Compute the origin (top-left corner) of the text layout in DIPs by converting + // the drawing surface offset from pixels to DIPs and adding the margin. + D2D_POINT_2F origin{ + pixelOffset.x / m_dpiScale + marginLeft, + pixelOffset.y / m_dpiScale + marginTop }; + + // Clear the background and draw the text. + deviceContext->Clear(ToColorF(backgroundColor)); + + // Use ClearType antialiasing if rendering onto an opaque background. + // Otherwise use grayscale. + deviceContext->SetTextAntialiasMode( + backgroundColor.A == 255 ? + D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE : + D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE); + + // Create the brush used to fill the text. + winrt::com_ptr textBrush; + winrt::check_hresult(deviceContext->CreateSolidColorBrush(ToColorF(textColor), textBrush.put())); + + // Draw the text layout object. + deviceContext->DrawTextLayout(origin, textLayout.get(), textBrush.get()); + + // End drawing. + winrt::check_hresult(drawingSurfaceInterop->EndDraw()); + + // Create the surface brush and set it as the visual's brush. + auto surfaceBrush = m_compositor.CreateSurfaceBrush(); + surfaceBrush.Surface(drawingSurface); + visual.Brush(surfaceBrush); + } + catch (winrt::hresult_error& e) + { + // Silently ignore device-removed error. + // We'll draw again after the device is recreated. + if (e.code() == DXGI_ERROR_DEVICE_REMOVED) + return; + + // Rethrow all other exceptions. + throw; + } + } +} diff --git a/Samples/Islands/WpfCalculator/DrawingIslandComponents/TextRenderer.h b/Samples/Islands/WpfCalculator/DrawingIslandComponents/TextRenderer.h new file mode 100644 index 000000000..d05072d5a --- /dev/null +++ b/Samples/Islands/WpfCalculator/DrawingIslandComponents/TextRenderer.h @@ -0,0 +1,58 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once + +namespace winrt::DrawingIslandComponents::implementation +{ + class TextRenderer final + { + public: + TextRenderer(winrt::Compositor compositor); + + void SetDpiScale(float scale) + { + m_dpiScale = scale; + } + + void Render( + _In_z_ WCHAR const* text, + Windows::UI::Color backgroundColor, + Windows::UI::Color textColor, + SpriteVisual const& visual); + + winrt::Compositor const& GetCompositor() const noexcept + { + return m_compositor; + } + + winrt::com_ptr<::IDXGIDevice> const& GetDevice() const noexcept + { + return m_dxgiDevice; + } + + void RecreateDirect2DDevice(); + + private: + static inline D2D_COLOR_F ToColorF(Windows::UI::Color color) + { + return D2D_COLOR_F{ color.R / 255.0f, color.G / 255.0f, color.B / 255.0f, color.A / 255.0f }; + } + + void CreateDirect2DDevice(); + + winrt::Compositor m_compositor; + + // Device-independent resources. + winrt::com_ptr<::IDWriteFactory7> m_dwriteFactory; + winrt::com_ptr<::IDWriteTextFormat> m_textFormat; + winrt::com_ptr<::ID2D1Factory7> m_d2dFactory; + + // Device-dependent resources. + winrt::com_ptr<::IDXGIDevice> m_dxgiDevice; + winrt::com_ptr<::ID2D1Device6> m_d2dDevice; + CompositionGraphicsDevice m_compositionGraphicsDevice{ nullptr }; + + float m_dpiScale = 1.0f; + }; +} diff --git a/Samples/Islands/WpfCalculator/DrawingIslandComponents/packages.config b/Samples/Islands/WpfCalculator/DrawingIslandComponents/packages.config new file mode 100644 index 000000000..8401faf51 --- /dev/null +++ b/Samples/Islands/WpfCalculator/DrawingIslandComponents/packages.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Samples/Islands/WpfCalculator/DrawingIslandComponents/pch.cpp b/Samples/Islands/WpfCalculator/DrawingIslandComponents/pch.cpp new file mode 100644 index 000000000..40e691ba7 --- /dev/null +++ b/Samples/Islands/WpfCalculator/DrawingIslandComponents/pch.cpp @@ -0,0 +1,4 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include "pch.h" diff --git a/Samples/Islands/WpfCalculator/DrawingIslandComponents/pch.h b/Samples/Islands/WpfCalculator/DrawingIslandComponents/pch.h new file mode 100644 index 000000000..f15602e4b --- /dev/null +++ b/Samples/Islands/WpfCalculator/DrawingIslandComponents/pch.h @@ -0,0 +1,67 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once + +// Windows Platform Win32 +#include +#include +#include +#include + +// DWriteWrite and Direct2D for rendering text +#include +#include +#include +#include + +// WIL +#include +#include +#include + +// Windows Platform WinRT +#include +#include +#include +#include +#include +#include +#include + +// Windows App SDK +#include +#include +#include +#include +#include +#include +#include +#include + +//#include +#include +#include + +#include + +namespace winrt +{ + using namespace winrt::Windows::Foundation; + using namespace winrt::Windows::Foundation::Collections; + using namespace winrt::Windows::Foundation::Numerics; + using namespace winrt::Windows::Graphics::DirectX; + using namespace winrt::Windows::Graphics::DirectX::Direct3D11; + using namespace winrt::Windows::System; + using namespace winrt::Windows::UI; + + using namespace winrt::Microsoft::UI; + using namespace winrt::Microsoft::UI::Composition; + using namespace winrt::Microsoft::UI::Composition::SystemBackdrops; + using namespace winrt::Microsoft::UI::Content; + using namespace winrt::Microsoft::UI::Dispatching; + using namespace winrt::Microsoft::UI::Input; + using namespace winrt::Microsoft::UI::Windowing; +} + +using namespace Windows::Foundation::Numerics; diff --git a/Samples/Islands/WpfCalculator/DrawingIslandComponents/readme.txt b/Samples/Islands/WpfCalculator/DrawingIslandComponents/readme.txt new file mode 100644 index 000000000..f269f729f --- /dev/null +++ b/Samples/Islands/WpfCalculator/DrawingIslandComponents/readme.txt @@ -0,0 +1,23 @@ +======================================================================== + C++/WinRT DrawingIslandComponent Project Overview +======================================================================== + +This project demonstrates how to get started authoring Windows Runtime +classes directly with standard C++, using the C++/WinRT SDK component +to generate implementation headers from interface (IDL) files. The +generated Windows Runtime component binary and WinMD files should then +be bundled with the Universal Windows Platform (UWP) app consuming them. + +Steps: +1. Create an interface (IDL) file to define your Windows Runtime class, + its default interface, and any other interfaces it implements. +2. Build the project once to generate module.g.cpp, module.h.cpp, and + implementation templates under the "Generated Files" folder, as + well as skeleton class definitions under "Generated Files\sources". +3. Use the skeleton class definitions for reference to implement your + Windows Runtime classes. + +======================================================================== +Learn more about C++/WinRT here: +http://aka.ms/cppwinrt/ +======================================================================== diff --git a/Samples/Islands/WpfCalculator/DrawingIslandCsProjection/DrawingIslandCsProjection.csproj b/Samples/Islands/WpfCalculator/DrawingIslandCsProjection/DrawingIslandCsProjection.csproj new file mode 100644 index 000000000..cba03600e --- /dev/null +++ b/Samples/Islands/WpfCalculator/DrawingIslandCsProjection/DrawingIslandCsProjection.csproj @@ -0,0 +1,37 @@ + + + + + net9.0-windows10.0.22621.0 + enable + enable + x64;x86;ARM64 + + + win-x86;win-x64;win-arm64 + + true + + + + + + + DrawingIslandComponents + + + $(OutDir) + 10.0.17763.0 + + + + + + + + + + + + + diff --git a/Samples/Islands/WpfCalculator/WpfCalculator.sln b/Samples/Islands/WpfCalculator/WpfCalculator.sln new file mode 100644 index 000000000..759d4e907 --- /dev/null +++ b/Samples/Islands/WpfCalculator/WpfCalculator.sln @@ -0,0 +1,94 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.9.34728.123 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DrawingIslandComponents", "DrawingIslandComponents\DrawingIslandComponents.vcxproj", "{709C54E1-0F2F-4A59-80B2-4CFD08B720E5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CalculatorDemo", "CalculatorDemo\CalculatorDemo.csproj", "{5731865D-6685-47A7-8877-5DBAF39B54CD}" +EndProject +Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "CalculatorDemoPackage", "CalculatorDemoPackage\CalculatorDemoPackage.wapproj", "{0A343519-113B-4EF9-959C-30F559524BC4}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Demo3_Step1", "Demo3_Step1", "{D326EA21-1EE1-4D67-A0CE-898D9EC84300}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Demo4_Step2", "Demo4_Step2", "{1C23C858-0772-4881-A947-32E8870C35AE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DrawingIslandCsProjection", "DrawingIslandCsProjection\DrawingIslandCsProjection.csproj", "{4A5A8328-28E9-4B32-9284-6BCB33553E10}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM64 = Debug|ARM64 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM64 = Release|ARM64 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {709C54E1-0F2F-4A59-80B2-4CFD08B720E5}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {709C54E1-0F2F-4A59-80B2-4CFD08B720E5}.Debug|ARM64.Build.0 = Debug|ARM64 + {709C54E1-0F2F-4A59-80B2-4CFD08B720E5}.Debug|x64.ActiveCfg = Debug|x64 + {709C54E1-0F2F-4A59-80B2-4CFD08B720E5}.Debug|x64.Build.0 = Debug|x64 + {709C54E1-0F2F-4A59-80B2-4CFD08B720E5}.Debug|x86.ActiveCfg = Debug|Win32 + {709C54E1-0F2F-4A59-80B2-4CFD08B720E5}.Debug|x86.Build.0 = Debug|Win32 + {709C54E1-0F2F-4A59-80B2-4CFD08B720E5}.Release|ARM64.ActiveCfg = Release|ARM64 + {709C54E1-0F2F-4A59-80B2-4CFD08B720E5}.Release|ARM64.Build.0 = Release|ARM64 + {709C54E1-0F2F-4A59-80B2-4CFD08B720E5}.Release|x64.ActiveCfg = Release|x64 + {709C54E1-0F2F-4A59-80B2-4CFD08B720E5}.Release|x64.Build.0 = Release|x64 + {709C54E1-0F2F-4A59-80B2-4CFD08B720E5}.Release|x86.ActiveCfg = Release|Win32 + {709C54E1-0F2F-4A59-80B2-4CFD08B720E5}.Release|x86.Build.0 = Release|Win32 + {5731865D-6685-47A7-8877-5DBAF39B54CD}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {5731865D-6685-47A7-8877-5DBAF39B54CD}.Debug|ARM64.Build.0 = Debug|ARM64 + {5731865D-6685-47A7-8877-5DBAF39B54CD}.Debug|x64.ActiveCfg = Debug|x64 + {5731865D-6685-47A7-8877-5DBAF39B54CD}.Debug|x64.Build.0 = Debug|x64 + {5731865D-6685-47A7-8877-5DBAF39B54CD}.Debug|x86.ActiveCfg = Debug|x86 + {5731865D-6685-47A7-8877-5DBAF39B54CD}.Debug|x86.Build.0 = Debug|x86 + {5731865D-6685-47A7-8877-5DBAF39B54CD}.Release|ARM64.ActiveCfg = Release|ARM64 + {5731865D-6685-47A7-8877-5DBAF39B54CD}.Release|ARM64.Build.0 = Release|ARM64 + {5731865D-6685-47A7-8877-5DBAF39B54CD}.Release|x64.ActiveCfg = Release|x64 + {5731865D-6685-47A7-8877-5DBAF39B54CD}.Release|x64.Build.0 = Release|x64 + {5731865D-6685-47A7-8877-5DBAF39B54CD}.Release|x86.ActiveCfg = Release|x86 + {5731865D-6685-47A7-8877-5DBAF39B54CD}.Release|x86.Build.0 = Release|x86 + {0A343519-113B-4EF9-959C-30F559524BC4}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {0A343519-113B-4EF9-959C-30F559524BC4}.Debug|ARM64.Build.0 = Debug|ARM64 + {0A343519-113B-4EF9-959C-30F559524BC4}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {0A343519-113B-4EF9-959C-30F559524BC4}.Debug|x64.ActiveCfg = Debug|x64 + {0A343519-113B-4EF9-959C-30F559524BC4}.Debug|x64.Build.0 = Debug|x64 + {0A343519-113B-4EF9-959C-30F559524BC4}.Debug|x64.Deploy.0 = Debug|x64 + {0A343519-113B-4EF9-959C-30F559524BC4}.Debug|x86.ActiveCfg = Debug|x86 + {0A343519-113B-4EF9-959C-30F559524BC4}.Debug|x86.Build.0 = Debug|x86 + {0A343519-113B-4EF9-959C-30F559524BC4}.Debug|x86.Deploy.0 = Debug|x86 + {0A343519-113B-4EF9-959C-30F559524BC4}.Release|ARM64.ActiveCfg = Release|ARM64 + {0A343519-113B-4EF9-959C-30F559524BC4}.Release|ARM64.Build.0 = Release|ARM64 + {0A343519-113B-4EF9-959C-30F559524BC4}.Release|ARM64.Deploy.0 = Release|ARM64 + {0A343519-113B-4EF9-959C-30F559524BC4}.Release|x64.ActiveCfg = Release|x64 + {0A343519-113B-4EF9-959C-30F559524BC4}.Release|x64.Build.0 = Release|x64 + {0A343519-113B-4EF9-959C-30F559524BC4}.Release|x64.Deploy.0 = Release|x64 + {0A343519-113B-4EF9-959C-30F559524BC4}.Release|x86.ActiveCfg = Release|x86 + {0A343519-113B-4EF9-959C-30F559524BC4}.Release|x86.Build.0 = Release|x86 + {0A343519-113B-4EF9-959C-30F559524BC4}.Release|x86.Deploy.0 = Release|x86 + {4A5A8328-28E9-4B32-9284-6BCB33553E10}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {4A5A8328-28E9-4B32-9284-6BCB33553E10}.Debug|ARM64.Build.0 = Debug|ARM64 + {4A5A8328-28E9-4B32-9284-6BCB33553E10}.Debug|x64.ActiveCfg = Debug|x64 + {4A5A8328-28E9-4B32-9284-6BCB33553E10}.Debug|x64.Build.0 = Debug|x64 + {4A5A8328-28E9-4B32-9284-6BCB33553E10}.Debug|x86.ActiveCfg = Debug|x86 + {4A5A8328-28E9-4B32-9284-6BCB33553E10}.Debug|x86.Build.0 = Debug|x86 + {4A5A8328-28E9-4B32-9284-6BCB33553E10}.Release|ARM64.ActiveCfg = Release|ARM64 + {4A5A8328-28E9-4B32-9284-6BCB33553E10}.Release|ARM64.Build.0 = Release|ARM64 + {4A5A8328-28E9-4B32-9284-6BCB33553E10}.Release|x64.ActiveCfg = Release|x64 + {4A5A8328-28E9-4B32-9284-6BCB33553E10}.Release|x64.Build.0 = Release|x64 + {4A5A8328-28E9-4B32-9284-6BCB33553E10}.Release|x86.ActiveCfg = Release|x86 + {4A5A8328-28E9-4B32-9284-6BCB33553E10}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {709C54E1-0F2F-4A59-80B2-4CFD08B720E5} = {1C23C858-0772-4881-A947-32E8870C35AE} + {0A343519-113B-4EF9-959C-30F559524BC4} = {D326EA21-1EE1-4D67-A0CE-898D9EC84300} + {4A5A8328-28E9-4B32-9284-6BCB33553E10} = {1C23C858-0772-4881-A947-32E8870C35AE} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {85542A88-746B-4646-9027-3AA360D075C2} + EndGlobalSection +EndGlobal diff --git a/Samples/Islands/WpfCalculator/directory.build.props b/Samples/Islands/WpfCalculator/directory.build.props new file mode 100644 index 000000000..96ca6b023 --- /dev/null +++ b/Samples/Islands/WpfCalculator/directory.build.props @@ -0,0 +1,14 @@ + + + + + + True + + + $([MSBuild]::NormalizeDirectory('$(SolutionDir)', '_build', '$(Platform)', '$(Configuration)')) + $([MSBuild]::NormalizeDirectory('$(BuildOutDir)', '$(MSBuildProjectName)', 'bin')) + $([MSBuild]::NormalizeDirectory('$(BuildOutDir)', '$(MSBuildProjectName)', 'obj')) + + + diff --git a/Samples/Islands/WpfCalculator/img/image-1.png b/Samples/Islands/WpfCalculator/img/image-1.png new file mode 100644 index 000000000..2242c7637 Binary files /dev/null and b/Samples/Islands/WpfCalculator/img/image-1.png differ diff --git a/Samples/Islands/WpfCalculator/img/image.png b/Samples/Islands/WpfCalculator/img/image.png new file mode 100644 index 000000000..821a8eb90 Binary files /dev/null and b/Samples/Islands/WpfCalculator/img/image.png differ diff --git a/Samples/Islands/WpfCalculator/readme.md b/Samples/Islands/WpfCalculator/readme.md new file mode 100644 index 000000000..31b7255c1 --- /dev/null +++ b/Samples/Islands/WpfCalculator/readme.md @@ -0,0 +1,38 @@ + +Here's the basic process: + + + +**Demo2_Step2_RunCalcWithThemes** +* Open WpfCalculator.sln. +* Ensure settings are: + +![alt text](img/image.png) + +* ctrl+f5 + +**Demo2_Step3_AddPackaging** +* Change Startup project to: + +![alt text](img/image-1.png) + +* ctrl+f5 +* App runs, and looks the same. Note how the Start Menu now contains "CalculatorDemoPackage". + +**Demo3_Step1_AddWasdk** +* Remove comments for "Demo3_Step1_AddWasdk" +* Demo will look the same. + + +**Demo3_Step2_AddCompact** +* Remove comments for "Demo3_Step2_AddCompact" +* ctrl+f5 +* App now has "compact" mode + +**Demo4_Step2_AddIsland** +* Remove comments for "Demo4_Step2_AddIsland" +* ctrl+f5 +* App now has an option File | Add DrawingIsland. + + +