internal void WriteCodeBuilder(CodeBuilder builder) { _lines.Add(new CodeLine { Text = builder, IndentCount = _indentCount }); }
/// <inheritdoc/> // Called by the base class to write the end of the file (i.e. everything after the body of the Instantiator class). protected override void WriteFileEnd( CodeBuilder builder, CodeGenInfo info) { if (info.UsesCanvasEffects || info.UsesCanvasGeometry) { // Utility method for D2D geometries builder.WriteLine("static IGeometrySource2D^ CanvasGeometryToIGeometrySource2D(CanvasGeometry geo)"); builder.OpenScope(); builder.WriteLine("ComPtr<ABI::Windows::Graphics::IGeometrySource2D> interop = geo.Detach();"); builder.WriteLine("return reinterpret_cast<IGeometrySource2D^>(interop.Get());"); builder.CloseScope(); builder.WriteLine(); // Utility method for fail-fasting on bad HRESULTs from d2d operations builder.WriteLine("static void FFHR(HRESULT hr)"); builder.OpenScope(); builder.WriteLine("if (hr != S_OK)"); builder.OpenScope(); builder.WriteLine("RoFailFastWithErrorContext(hr);"); builder.CloseScope(); builder.CloseScope(); builder.WriteLine(); } // Write the constructor for the instantiator. builder.UnIndent(); builder.WriteLine("public:"); builder.Indent(); if (info.HasLoadedImageSurface) { builder.WriteLine("AnimatedVisual(Compositor^ compositor,"); builder.Indent(); builder.WriteCommaSeparatedLines(info.LoadedImageSurfaceNodes.Select(n => $"{_stringifier.ReferenceTypeName(n.TypeName)} {_stringifier.CamelCase(n.Name)}")); // Initializer list. builder.WriteLine(") : _c(compositor)"); // Instantiate the reusable ExpressionAnimation. builder.WriteLine($", {info.ReusableExpressionAnimationFieldName}(compositor->CreateExpressionAnimation())"); // Initialize the image surfaces. var nodes = info.LoadedImageSurfaceNodes.ToArray(); foreach (var n in nodes) { builder.WriteLine($", {n.FieldName}({_stringifier.CamelCase(n.Name)})"); } builder.UnIndent(); } else { builder.WriteLine("AnimatedVisual(Compositor^ compositor)"); // Initializer list. builder.Indent(); builder.WriteLine(": _c(compositor)"); // Instantiate the reusable ExpressionAnimation. builder.WriteLine($", {info.ReusableExpressionAnimationFieldName}(compositor->CreateExpressionAnimation())"); builder.UnIndent(); } builder.OpenScope(); if (info.UsesCanvasEffects || info.UsesCanvasGeometry) { builder.WriteLine($"{FailFastWrapper("D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, _d2dFactory.GetAddressOf())")};"); } // Instantiate the root. This will cause the whole Visual tree to be built and animations started. builder.WriteLine("Root();"); builder.CloseScope(); // Write the destructor. This is how CX implements IClosable/IDisposable. builder.WriteLine("virtual ~AnimatedVisual() { }"); // Write the members on IAnimatedVisual. builder.WriteLine(); builder.WriteLine("property TimeSpan Duration"); builder.OpenScope(); builder.WriteLine("virtual TimeSpan get() { return { c_durationTicks }; }"); builder.CloseScope(); builder.WriteLine(); builder.WriteLine("property Visual^ RootVisual"); builder.OpenScope(); builder.WriteLine("virtual Visual^ get() { return _root; }"); builder.CloseScope(); builder.WriteLine(); builder.WriteLine("property float2 Size"); builder.OpenScope(); builder.WriteLine($"virtual float2 get() {{ return {Vector2(info.CompositionDeclaredSize)}; }}"); builder.CloseScope(); builder.WriteLine(); // Close the scope for the instantiator class. builder.UnIndent(); builder.WriteLine("};"); // Close the anonymous namespace. builder.WriteLine("} // end namespace"); builder.WriteLine(); // Generate the method that creates an instance of the composition. builder.WriteLine($"Microsoft::UI::Xaml::Controls::IAnimatedVisual^ AnimatedVisuals::{info.ClassName}::TryCreateAnimatedVisual("); builder.Indent(); builder.WriteLine("Compositor^ compositor,"); builder.WriteLine("Object^* diagnostics)"); builder.UnIndent(); builder.OpenScope(); if (info.HasLoadedImageSurface) { WriteTryCreateInstantiatorWithImageLoading(builder, info); } else { builder.WriteLine("diagnostics = nullptr;"); builder.WriteLine("if (!IsRuntimeCompatible())"); builder.OpenScope(); builder.WriteLine("return nullptr;"); builder.CloseScope(); builder.WriteLine("return ref new AnimatedVisual(compositor);"); builder.CloseScope(); } if (info.HasLoadedImageSurface) { // Generate the get() and set() methods of IsAnimatedVisualSourceDynamic property. WriteIsAnimatedVisualSourceDynamicGetSet(builder, info); // Generate the method that load all the LoadedImageSurfaces. WriteEnsureImageLoadingStarted(builder, info); // Generate the method that handle the LoadCompleted event of the LoadedImageSurface objects. WriteHandleLoadCompleted(builder, info); } }
/// <inheritdoc/> // Called by the base class to write the start of the file (i.e. everything up to the body of the Instantiator class). protected override void WriteFileStart( CodeBuilder builder, CodeGenInfo info) { builder.WriteLine("#include \"pch.h\""); builder.WriteLine($"#include \"{_headerFileName}\""); // floatY, floatYxZ builder.WriteLine("#include \"WindowsNumerics.h\""); if (info.UsesCanvasEffects || info.UsesCanvasGeometry) { // D2D builder.WriteLine("#include \"d2d1.h\""); builder.WriteLine("#include <d2d1_1.h>"); builder.WriteLine("#include <d2d1helper.h>"); // Interop builder.WriteLine("#include <Windows.Graphics.Interop.h>"); // ComPtr builder.WriteLine("#include <wrl.h>"); } if (info.UsesStreams) { builder.WriteLine("#include <iostream>"); } if (info.UsesCompositeEffect) { // The CompsiteEffect class requires std::vector. builder.WriteLine("#include <vector>"); } builder.WriteLine(); // A sorted set to hold the namespaces that the generated code will use. The set is maintained in sorted order. var namespaces = new SortedSet <string>(); if (info.UsesCanvasEffects || info.UsesCanvas) { // Interop builder.WriteLine("#include <Windows.Graphics.Effects.h>"); builder.WriteLine("#include <Windows.Graphics.Effects.Interop.h>"); } namespaces.Add("Windows::Foundation"); namespaces.Add("Windows::Foundation::Numerics"); namespaces.Add("Windows::UI"); namespaces.Add("Windows::UI::Composition"); namespaces.Add("Windows::Graphics"); namespaces.Add("Microsoft::WRL"); if (info.UsesNamespaceWindowsUIXamlMedia) { namespaces.Add("Windows::UI::Xaml::Media"); } if (info.UsesStreams) { namespaces.Add("Platform"); namespaces.Add("Windows::Storage::Streams"); } // Write out each namespace using. foreach (var n in namespaces) { builder.WriteLine($"using namespace {n};"); } builder.WriteLine(); // Put the Instantiator class in an anonymous namespace. builder.WriteLine("namespace"); builder.WriteLine("{"); if (info.UsesCanvasEffects || info.UsesCanvasGeometry) { // Write GeoSource to allow it's use in function definitions builder.WriteLine($"{_stringifier.GeoSourceClass}"); // Typedef to simplify generation builder.WriteLine("typedef ComPtr<GeoSource> CanvasGeometry;"); } if (info.UsesCompositeEffect) { // Write the composite effect class that will allow the use // of this effect without win2d. builder.WriteLine($"{CompositionEffectClass}"); } }
/// <inheritdoc/> // Called by the base class to write the start of the file (i.e. everything up to the body of the Instantiator class). protected override void WriteFileStart(CodeBuilder builder) { // A sorted set to hold the namespaces that the generated code will use. The set is maintained in sorted order. var namespaces = new SortedSet<string>(); if (Info.UsesCanvas) { namespaces.Add("Microsoft.Graphics.Canvas"); } if (Info.UsesCanvasEffects) { namespaces.Add("Microsoft.Graphics.Canvas.Effects"); } if (Info.UsesCanvasGeometry) { namespaces.Add("Microsoft.Graphics.Canvas.Geometry"); } if (Info.UsesNamespaceWindowsUIXamlMedia) { namespaces.Add("System.ComponentModel"); namespaces.Add("System.Runtime.InteropServices.WindowsRuntime"); namespaces.Add("Windows.Foundation"); namespaces.Add("Windows.UI.Xaml.Media"); } if (Info.GenerateDependencyObject) { namespaces.Add("Windows.UI.Xaml"); } if (Info.UsesStreams) { namespaces.Add("System.IO"); } namespaces.Add("System"); namespaces.Add("System.Numerics"); namespaces.Add("Windows.UI"); namespaces.Add("Windows.UI.Composition"); // Write out each namespace using. foreach (var n in namespaces) { builder.WriteLine($"using {n};"); } builder.WriteLine(); builder.WriteLine($"namespace {Info.Namespace}"); builder.OpenScope(); // Write a description of the source as comments. foreach (var line in GetSourceDescriptionLines()) { builder.WritePreformattedCommentLine(line); } // If the composition has LoadedImageSurface, write a class that implements the IDynamicAnimatedVisualSource interface. // Otherwise, implement the IAnimatedVisualSource interface. if (Info.LoadedImageSurfaces.Count > 0) { WriteIDynamicAnimatedVisualSource(builder, Info); } else { WriteIAnimatedVisualSource(builder, Info); } builder.CloseScope(); builder.WriteLine(); }