void WriteAnimatedVisualCall(CodeBuilder builder, CodeGenInfo info) { builder.WriteLine("new AnimatedVisual(compositor,"); builder.Indent(); builder.WriteCommaSeparatedLines(info.LoadedImageSurfaceNodes.Select(n => n.FieldName)); builder.WriteLine(");"); builder.UnIndent(); }
/// <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) { // Write the constructor for the instantiator. if (info.HasLoadedImageSurface) { builder.WriteLine($"internal AnimatedVisual(Compositor compositor,"); builder.Indent(); // Define the image surface parameters of the AnimatedVisual() constructor. builder.WriteCommaSeparatedLines(info.LoadedImageSurfaceNodes.Select(n => $"{_stringifier.ReferenceTypeName(n.TypeName)} {_stringifier.CamelCase(n.Name)}")); builder.WriteLine(")"); builder.UnIndent(); builder.OpenScope(); builder.WriteLine("_c = compositor;"); builder.WriteLine($"{info.ReusableExpressionAnimationFieldName} = compositor.CreateExpressionAnimation();"); // Initialize the private image surface variables with the input parameters of the constructor. var nodes = info.LoadedImageSurfaceNodes.ToArray(); foreach (var n in nodes) { builder.WriteLine($"{n.FieldName} = {_stringifier.CamelCase(n.Name)};"); } } else { builder.WriteLine("internal AnimatedVisual(Compositor compositor)"); builder.OpenScope(); builder.WriteLine("_c = compositor;"); builder.WriteLine($"{info.ReusableExpressionAnimationFieldName} = compositor.CreateExpressionAnimation();"); } builder.WriteLine("Root();"); builder.CloseScope(); builder.WriteLine(); // Write the IAnimatedVisual implementation. builder.WriteLine("Visual IAnimatedVisual.RootVisual => _root;"); builder.WriteLine($"TimeSpan IAnimatedVisual.Duration => TimeSpan.FromTicks({info.DurationTicksFieldName});"); builder.WriteLine($"Vector2 IAnimatedVisual.Size => {Vector2(info.CompositionDeclaredSize)};"); builder.WriteLine("void IDisposable.Dispose() => _root?.Dispose();"); // Close the scope for the instantiator class. builder.CloseScope(); // Close the scope for the class. builder.CloseScope(); // Close the scope for the namespace builder.CloseScope(); }
/// <summary> /// Generate the body of the TryCreateAnimatedVisual() method for the composition that contains LoadedImageSurfaces. /// </summary> void WriteTryCreateInstantiatorWithImageLoading(CodeBuilder builder, CodeGenInfo info) { builder.WriteLine("m_isTryCreateAnimatedVisualCalled = true;"); builder.WriteLine(); builder.WriteLine("diagnostics = nullptr;"); builder.WriteLine("if (!IsRuntimeCompatible())"); builder.OpenScope(); builder.WriteLine("return nullptr;"); builder.CloseScope(); builder.WriteLine(); builder.WriteLine("EnsureImageLoadingStarted();"); builder.WriteLine(); builder.WriteLine("if (m_isAnimatedVisualSourceDynamic && m_loadCompleteEventCount != c_loadedImageSurfaceCount)"); builder.OpenScope(); builder.WriteLine("return nullptr;"); builder.CloseScope(); builder.WriteLine("return ref new AnimatedVisual(compositor,"); builder.Indent(); builder.WriteCommaSeparatedLines(info.LoadedImageSurfaceNodes.Select(n => MakeFieldName(n.Name))); builder.UnIndent(); builder.WriteLine(");"); builder.CloseScope(); builder.WriteLine(); }
/// <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); } }