/// <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. 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(); }
/// <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) { if (info.RequiresWin2d) { builder.WriteLine("using Microsoft.Graphics.Canvas.Geometry;"); } builder.WriteLine("using Microsoft.UI.Xaml.Controls;"); builder.WriteLine("using System;"); builder.WriteLine("using System.Numerics;"); builder.WriteLine("using Windows.UI;"); builder.WriteLine("using Windows.UI.Composition;"); builder.WriteLine(); builder.WriteLine("namespace AnimatedVisuals"); builder.OpenScope(); builder.WriteLine($"sealed class {info.ClassName} : IAnimatedVisualSource"); builder.OpenScope(); // Generate the method that creates an instance of the animated visual. builder.WriteLine("public IAnimatedVisual TryCreateAnimatedVisual(Compositor compositor, out object diagnostics)"); builder.OpenScope(); builder.WriteLine("diagnostics = null;"); builder.WriteLine("if (!IsRuntimeCompatible())"); builder.OpenScope(); builder.WriteLine("return null;"); builder.CloseScope(); builder.WriteLine("return new AnimatedVisual(compositor);"); builder.CloseScope(); builder.WriteLine(); }
void WriteEnsureImageLoadingStarted(CodeBuilder builder, CodeGenInfo info) { builder.WriteLine("void EnsureImageLoadingStarted()"); builder.OpenScope(); builder.WriteLine("if (!_isImageLoadingStarted)"); builder.OpenScope(); builder.WriteLine("var eventHandler = new TypedEventHandler<LoadedImageSurface, LoadedImageSourceLoadCompletedEventArgs>(HandleLoadCompleted);"); var nodes = info.LoadedImageSurfaceNodes.ToArray(); foreach (var n in nodes) { switch (n.LoadedImageSurfaceType) { case LoadedImageSurface.LoadedImageSurfaceType.FromStream: builder.WriteLine($"{n.FieldName} = LoadedImageSurface.StartLoadFromStream({n.BytesFieldName}.AsBuffer().AsStream().AsRandomAccessStream());"); break; case LoadedImageSurface.LoadedImageSurfaceType.FromUri: builder.WriteLine($"{n.FieldName} = LoadedImageSurface.StartLoadFromUri(new Uri(\"{n.ImageUri}\"));"); break; default: throw new InvalidOperationException(); } builder.WriteLine($"{n.FieldName}.LoadCompleted += eventHandler;"); } builder.WriteLine("_isImageLoadingStarted = true;"); builder.CloseScope(); builder.CloseScope(); builder.WriteLine(); }
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 start of the file (i.e. everything up to the body of the Instantiator class). protected override void WriteFileStart(CodeBuilder builder, CodeGenInfo info) { // A sorted set to hold the namespaces that the generated code will use. The set is maintained in sorted order. var namepaces = new SortedSet <string>(); if (info.UsesCanvas) { namepaces.Add("Microsoft.Graphics.Canvas"); } if (info.UsesCanvasEffects) { namepaces.Add("Microsoft.Graphics.Canvas.Effects"); } if (info.UsesCanvasGeometry) { namepaces.Add("Microsoft.Graphics.Canvas.Geometry"); } if (info.UsesNamespaceWindowsUIXamlMedia) { namepaces.Add("Windows.UI.Xaml.Media"); namepaces.Add("System.Runtime.InteropServices.WindowsRuntime"); namepaces.Add("Windows.Foundation"); namepaces.Add("System.ComponentModel"); } if (info.UsesStreams) { namepaces.Add("System.IO"); } namepaces.Add("Microsoft.UI.Xaml.Controls"); namepaces.Add("System"); namepaces.Add("System.Numerics"); namepaces.Add("Windows.UI"); namepaces.Add("Windows.UI.Composition"); // Write out each namespace using. foreach (var n in namepaces) { builder.WriteLine($"using {n};"); } builder.WriteLine(); // If the composition has LoadedImageSurface, write a class that implements the IDynamicAnimatedVisualSource interface. // Otherwise, implement the IAnimatedVisualSource interface. if (info.HasLoadedImageSurface) { WriteIDynamicAnimatedVisualSource(builder, info); } else { WriteIAnimatedVisualSource(builder, info); } }
/// <inheritdoc/> protected override void WriteInstantiatorStart(CodeBuilder builder, CodeGenInfo info) { // Start writing the instantiator. builder.WriteLine("ref class AnimatedVisual sealed : public Microsoft::UI::Xaml::Controls::IAnimatedVisual"); builder.OpenScope(); // D2D factory field. builder.WriteLine("ComPtr<ID2D1Factory> _d2dFactory;"); }
/// <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(); }
/// <inheritdoc/> protected override void WriteLoadedImageSurfaceFactory(CodeBuilder builder, CodeGenInfo info, LoadedImageSurface obj, string fieldName, Uri imageUri) { switch (obj.Type) { case LoadedImageSurface.LoadedImageSurfaceType.FromStream: builder.WriteLine($"var result = Windows.UI.Xaml.Media.LoadedImageSurface.StartLoadFromStream({fieldName}.AsBuffer().AsStream().AsRandomAccessStream());"); break; case LoadedImageSurface.LoadedImageSurfaceType.FromUri: builder.WriteLine($"var result = Windows.UI.Xaml.Media.LoadedImageSurface.StartLoadFromUri(new Uri(\"{imageUri}\"));"); break; } }
/// <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}\""); if (info.UsesCanvasEffects) { // D2D builder.WriteLine("#include \"d2d1.h\""); builder.WriteLine("#include <d2d1_1.h>"); builder.WriteLine("#include <d2d1helper.h>"); // floatY, floatYxZ builder.WriteLine("#include \"WindowsNumerics.h\""); // Interop builder.WriteLine("#include <Windows.Graphics.Interop.h>"); // ComPtr builder.WriteLine("#include <wrl.h>"); } if (info.UsesCanvasEffects || info.UsesCanvas) { // throw an exception in this case for now. In the future the necessary // C++ code gen will be added throw new InvalidOperationException("Win2D dependency detected."); } builder.WriteLine(); builder.WriteLine("using namespace Windows::Foundation;"); builder.WriteLine("using namespace Windows::Foundation::Numerics;"); builder.WriteLine("using namespace Windows::UI;"); builder.WriteLine("using namespace Windows::UI::Composition;"); builder.WriteLine("using namespace Windows::Graphics;"); builder.WriteLine("using namespace Microsoft::WRL;"); builder.WriteLine(); // Put the Instantiator class in an anonymous namespace. builder.WriteLine("namespace"); builder.WriteLine("{"); // Write GeoSource to allow it's use in function definitions builder.WriteLine($"{_stringifier.GeoSourceClass}"); // Typedef to simplify generation builder.WriteLine("typedef ComPtr<GeoSource> CanvasGeometry;"); }
void WriteIsAnimatedVisualSourceDynamicGetSet(CodeBuilder builder, CodeGenInfo info) { builder.WriteLine($"bool AnimatedVisuals::{info.ClassName}::IsAnimatedVisualSourceDynamic::get()"); builder.OpenScope(); builder.WriteLine("return m_isAnimatedVisualSourceDynamic;"); builder.CloseScope(); builder.WriteLine(); builder.WriteLine($"void AnimatedVisuals::{info.ClassName}::IsAnimatedVisualSourceDynamic::set(bool isAnimatedVisualSourceDynamic)"); builder.OpenScope(); builder.WriteLine("if (!m_isTryCreateAnimatedVisualCalled && m_isAnimatedVisualSourceDynamic != isAnimatedVisualSourceDynamic)"); builder.OpenScope(); builder.WriteLine("m_isAnimatedVisualSourceDynamic = isAnimatedVisualSourceDynamic;"); builder.WriteLine("PropertyChanged(this, ref new PropertyChangedEventArgs(\"IsAnimatedVisualSourceDynamic\"));"); builder.CloseScope(); builder.CloseScope(); }
/// <summary> /// Write a class that implements the IAnimatedVisualSource interface. /// </summary> void WriteIAnimatedVisualSource(CodeBuilder builder, CodeGenInfo info) { builder.WriteLine("namespace AnimatedVisuals"); builder.OpenScope(); builder.WriteLine($"sealed class {info.ClassName} : IAnimatedVisualSource"); builder.OpenScope(); // Generate the method that creates an instance of the animated visual. builder.WriteLine("public IAnimatedVisual TryCreateAnimatedVisual(Compositor compositor, out object diagnostics)"); builder.OpenScope(); builder.WriteLine("diagnostics = null;"); builder.WriteLine("if (!IsRuntimeCompatible())"); builder.OpenScope(); builder.WriteLine("return null;"); builder.CloseScope(); builder.WriteLine("return new AnimatedVisual(compositor);"); builder.CloseScope(); builder.WriteLine(); }
///// <summary> ///// 清空项目的编译缓存 ///// </summary> //public void ClearCache(EntityInfo entityInfo, List<UIProjectItem> lstItem) //{ // foreach (UIProjectItem pitem in lstItem) // { // string mPath = UIConfigItem.FormatParameter(pitem.ModelPath, entityInfo); // CodeGenCache.DeleteGenerationer(mPath); // if (pitem.ChildItems != null && pitem.ChildItems.Count > 0) // { // ClearCache(entityInfo, pitem.ChildItems); // } // } //} /// <summary> /// 生成代码 /// </summary> /// <param name="entityInfo">实体信息</param> /// <param name="classConfig">UI配置信息</param> /// <param name="selectPropertys">选中需要生成的属性信息</param> /// <param name="lstItem">UI项目项</param> /// <param name="parentItem">父项</param> /// <returns></returns> private void GenerateCode(EntityInfo entityInfo, UIConfigItem classConfig, Project selectedProject, List <UIModelItem> selectPropertys, UIModelItem classInfo, List <UIProjectItem> lstItem, ProjectItem parentItem) { Encoding fileEncoding = null; foreach (UIProjectItem pitem in lstItem) { string mPath = UIConfigItem.FormatParameter(pitem.ModelPath, entityInfo, selectedProject); string tPath = UIConfigItem.FormatParameter(pitem.TargetPath, entityInfo, selectedProject); CodeGenInfo info = CodeGenCache.GetGenerationer(mPath, entityInfo); string content = info.Invoke(entityInfo, classConfig, selectPropertys, classInfo); fileEncoding = pitem.Encoding; ProjectItem item = SaveItem(tPath, selectedProject, content, pitem.GenType, parentItem, fileEncoding); if (pitem.ChildItems != null && pitem.ChildItems.Count > 0) { GenerateCode(entityInfo, classConfig, selectedProject, selectPropertys, classInfo, pitem.ChildItems, item); } } }
/// <inheritdoc/> protected override void WriteLoadedImageSurfaceFactory(CodeBuilder builder, CodeGenInfo info, LoadedImageSurface obj, string fieldName, Uri imageUri) { switch (obj.Type) { case LoadedImageSurface.LoadedImageSurfaceType.FromStream: builder.WriteLine("auto stream = ref new InMemoryRandomAccessStream();"); builder.WriteLine("auto dataWriter = ref new DataWriter(stream->GetOutputStreamAt(0));"); builder.WriteLine($"dataWriter->WriteBytes({fieldName});"); builder.WriteLine("dataWriter->StoreAsync();"); builder.WriteLine("dataWriter->FlushAsync();"); builder.WriteLine("stream->Seek(0);"); builder.WriteLine($"{_stringifier.Var} result = Windows::UI::Xaml::Media::LoadedImageSurface::StartLoadFromStream(stream);"); break; case LoadedImageSurface.LoadedImageSurfaceType.FromUri: builder.WriteLine($"{_stringifier.Var} result = Windows::UI::Xaml::Media::LoadedImageSurface::StartLoadFromUri(ref new Uri(\"{imageUri}\"));"); break; } }
void WriteEnsureImageLoadingStarted(CodeBuilder builder, CodeGenInfo info) { builder.WriteLine($"void AnimatedVisuals::{info.ClassName}::EnsureImageLoadingStarted()"); builder.OpenScope(); builder.WriteLine("if (!m_isImageLoadingStarted)"); builder.OpenScope(); builder.WriteLine($"auto eventHandler = ref new TypedEventHandler<LoadedImageSurface^, LoadedImageSourceLoadCompletedEventArgs^>(this, &AnimatedVisuals::{info.ClassName}::HandleLoadCompleted);"); var nodes = info.LoadedImageSurfaceNodes.ToArray(); foreach (var n in nodes) { var imageMemberName = MakeFieldName(n.Name); switch (n.LoadedImageSurfaceType) { case LoadedImageSurface.LoadedImageSurfaceType.FromStream: var streamName = $"stream_{n.Name}"; var dataWriterName = $"dataWriter_{n.Name}"; builder.WriteLine($"auto {streamName} = ref new InMemoryRandomAccessStream();"); builder.WriteLine($"auto {dataWriterName} = ref new DataWriter({streamName}->GetOutputStreamAt(0));"); builder.WriteLine($"{dataWriterName}->WriteBytes({n.BytesFieldName});"); builder.WriteLine($"{dataWriterName}->StoreAsync();"); builder.WriteLine($"{dataWriterName}->FlushAsync();"); builder.WriteLine($"{streamName}->Seek(0);"); builder.WriteLine($"{imageMemberName} = Windows::UI::Xaml::Media::LoadedImageSurface::StartLoadFromStream({streamName});"); break; case LoadedImageSurface.LoadedImageSurfaceType.FromUri: builder.WriteLine($"{imageMemberName} = Windows::UI::Xaml::Media::LoadedImageSurface::StartLoadFromUri(ref new Uri(\"{n.ImageUri}\"));"); break; default: throw new InvalidOperationException(); } builder.WriteLine($"{imageMemberName}->LoadCompleted += eventHandler;"); } builder.WriteLine("m_isImageLoadingStarted = true;"); builder.CloseScope(); builder.CloseScope(); builder.WriteLine(); }
/// <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}\""); if (info.RequiresWin2d) { // D2D builder.WriteLine("#include \"d2d1.h\""); builder.WriteLine("#include <d2d1_1.h>"); builder.WriteLine("#include <d2d1helper.h>"); // floatY, floatYxZ builder.WriteLine("#include \"WindowsNumerics.h\""); // Interop builder.WriteLine("#include <Windows.Graphics.Interop.h>"); // ComPtr builder.WriteLine("#include <wrl.h>"); } builder.WriteLine(); builder.WriteLine("using namespace Windows::Foundation;"); builder.WriteLine("using namespace Windows::Foundation::Numerics;"); builder.WriteLine("using namespace Windows::UI;"); builder.WriteLine("using namespace Windows::UI::Composition;"); builder.WriteLine("using namespace Windows::Graphics;"); builder.WriteLine("using namespace Microsoft::WRL;"); builder.WriteLine(); // Put the Instantiator class in an anonymous namespace. builder.WriteLine("namespace"); builder.WriteLine("{"); // Write GeoSource to allow it's use in function definitions builder.WriteLine($"{_stringifier.GeoSourceClass}"); // Typedef to simplify generation builder.WriteLine("typedef ComPtr<GeoSource> CanvasGeometry;"); }
void WriteHandleLoadCompleted(CodeBuilder builder, CodeGenInfo info) { builder.WriteLine($"void AnimatedVisuals::{info.ClassName}::HandleLoadCompleted(LoadedImageSurface^ sender, LoadedImageSourceLoadCompletedEventArgs^ e)"); builder.OpenScope(); builder.WriteLine("m_loadCompleteEventCount++;"); builder.WriteLine("if (e->Status == LoadedImageSourceLoadStatus::Success)"); builder.OpenScope(); builder.WriteLine("if (m_isAnimatedVisualSourceDynamic && m_loadCompleteEventCount == c_loadedImageSurfaceCount)"); builder.OpenScope(); builder.WriteLine("RaiseAnimatedVisualInvalidatedEvent(this, nullptr);"); builder.CloseScope(); builder.WriteLine("m_imageSuccessfulLoadingProgress = (double)m_loadCompleteEventCount / c_loadedImageSurfaceCount;"); builder.WriteLine("PropertyChanged(this, ref new PropertyChangedEventArgs(\"ImageSuccessfulLoadingProgress\"));"); builder.CloseScope(); builder.WriteLine(); builder.WriteLine("if (m_loadCompleteEventCount == c_loadedImageSurfaceCount)"); builder.OpenScope(); builder.WriteLine("m_isImageLoadingCompleted = true;"); builder.WriteLine("PropertyChanged(this, ref new PropertyChangedEventArgs(\"IsImageLoadingCompleted\"));"); builder.CloseScope(); builder.CloseScope(); builder.WriteLine(); }
/// <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); } }
/// <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) { // 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(); 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(); 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 Windows::Foundation::TimeSpan Duration"); builder.OpenScope(); builder.WriteLine("virtual Windows::Foundation::TimeSpan get() { return { c_durationTicks }; }"); builder.CloseScope(); builder.WriteLine(); builder.WriteLine("property Windows::UI::Composition::Visual^ RootVisual"); builder.OpenScope(); builder.WriteLine("virtual Windows::UI::Composition::Visual^ get() { return _root; }"); builder.CloseScope(); builder.WriteLine(); builder.WriteLine("property Windows::Foundation::Numerics::float2 Size"); builder.OpenScope(); builder.WriteLine($"virtual Windows::Foundation::Numerics::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(); 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(); }
/// <summary> /// Write a class that implements the IDynamicAnimatedVisualSource interface. /// </summary> void WriteIDynamicAnimatedVisualSource(CodeBuilder builder, CodeGenInfo info) { var nodes = info.LoadedImageSurfaceNodes.ToArray(); builder.WriteLine("namespace AnimatedVisuals"); builder.OpenScope(); builder.WriteLine($"sealed class {info.ClassName} : IDynamicAnimatedVisualSource, INotifyPropertyChanged"); builder.OpenScope(); // Declare variables. builder.WriteLine($"{_stringifier.Const(_stringifier.Int32TypeName)} c_loadedImageSurfaceCount = {nodes.Distinct().Count()};"); builder.WriteLine($"{_stringifier.Int32TypeName} _loadCompleteEventCount;"); builder.WriteLine("bool _isAnimatedVisualSourceDynamic = true;"); builder.WriteLine("bool _isTryCreateAnimatedVisualCalled;"); builder.WriteLine("bool _isImageLoadingStarted;"); builder.WriteLine("EventRegistrationTokenTable<TypedEventHandler<IDynamicAnimatedVisualSource, object>> _animatedVisualInvalidatedEventTokenTable;"); // Declare the variables to hold the surfaces. foreach (var n in nodes) { builder.WriteLine($"{_stringifier.ReferenceTypeName(n.TypeName)} {n.FieldName};"); } builder.WriteLine(); // Implement the INotifyPropertyChanged.PropertyChanged event. builder.WriteSummaryComment("This implementation of the INotifyPropertyChanged.PropertyChanged event is specific to C# and does not work on WinRT."); builder.WriteLine("public event PropertyChangedEventHandler PropertyChanged;"); builder.WriteLine(); // Implement the AnimatedVisualInvalidated event. WriteAnimatedVisualInvalidatedEvent(builder); // Define properties. builder.WriteSummaryComment("If this property is set to true, <see cref=\"TryCreateAnimatedVisual\"/> will return null until all images have loaded. When all images have loaded, <see cref=\"TryCreateAnimatedVisual\"/> will return the AnimatedVisual. To use, set it when declaring the AnimatedVisualSource. Once <see cref=\"TryCreateAnimatedVisual\"/> is called, changes made to this property will be ignored. Default value is true."); builder.WriteLine("public bool IsAnimatedVisualSourceDynamic"); builder.OpenScope(); builder.WriteLine("get { return _isAnimatedVisualSourceDynamic; }"); builder.WriteLine("set"); builder.OpenScope(); builder.WriteLine("if (!_isTryCreateAnimatedVisualCalled && _isAnimatedVisualSourceDynamic != value)"); builder.OpenScope(); builder.WriteLine("_isAnimatedVisualSourceDynamic = value;"); builder.WriteLine("NotifyPropertyChanged(nameof(IsAnimatedVisualSourceDynamic));"); builder.CloseScope(); builder.CloseScope(); builder.CloseScope(); builder.WriteLine(); builder.WriteSummaryComment("Returns true if all images have loaded. To see if the images succeeded to load, see <see cref=\"ImageSuccessfulLoadingProgress\"/>."); builder.WriteLine("public bool IsImageLoadingCompleted { get; private set; }"); builder.WriteLine(); builder.WriteSummaryComment("Represents the progress of the image loading. Returns value between 0 and 1. 0 means none of the images finished loading. 1 means all images finished loading."); builder.WriteLine("public double ImageSuccessfulLoadingProgress { get; private set; }"); builder.WriteLine(); // Generate the method that creates an instance of the animated visual. builder.WriteLine("public IAnimatedVisual TryCreateAnimatedVisual(Compositor compositor, out object diagnostics)"); builder.OpenScope(); builder.WriteLine("_isTryCreateAnimatedVisualCalled = true;"); builder.WriteLine(); builder.WriteLine("diagnostics = null;"); builder.WriteLine("if (!IsRuntimeCompatible())"); builder.OpenScope(); builder.WriteLine("return null;"); builder.CloseScope(); builder.WriteLine(); builder.WriteLine("EnsureImageLoadingStarted();"); builder.WriteLine(); builder.WriteLine("if (_isAnimatedVisualSourceDynamic && _loadCompleteEventCount != c_loadedImageSurfaceCount)"); builder.OpenScope(); builder.WriteLine("return null;"); builder.CloseScope(); builder.WriteLine("return"); builder.Indent(); WriteAnimatedVisualCall(builder, info); builder.UnIndent(); builder.CloseScope(); builder.WriteLine(); // 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); // Generate the method that raise the PropertyChanged event. builder.WriteLine("void NotifyPropertyChanged(string name)"); builder.OpenScope(); builder.WriteLine("PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));"); builder.CloseScope(); builder.WriteLine(); // Generate the method that get or create the EventRegistrationTokenTable. builder.WriteLine("EventRegistrationTokenTable<TypedEventHandler<IDynamicAnimatedVisualSource, object>> GetAnimatedVisualInvalidatedEventRegistrationTokenTable()"); builder.OpenScope(); builder.WriteLine("return EventRegistrationTokenTable<TypedEventHandler<IDynamicAnimatedVisualSource, object>>.GetOrCreateEventRegistrationTokenTable(ref _animatedVisualInvalidatedEventTokenTable);"); builder.CloseScope(); builder.WriteLine(); }
/// <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/> protected override void WriteInstantiatorStart(CodeBuilder builder, CodeGenInfo info) { // Start the instantiator class. builder.WriteLine("sealed class AnimatedVisual : IAnimatedVisual"); builder.OpenScope(); }