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/> protected override void WriteCanvasGeometryEllipseFactory(CodeBuilder builder, CanvasGeometry.Ellipse obj, string typeName, string fieldName) { builder.WriteLine($"var result = {FieldAssignment(fieldName)}CanvasGeometry.CreateEllipse("); builder.Indent(); builder.WriteLine($"null,"); builder.WriteLine($"{Float(obj.X)}, {Float(obj.Y)}, {Float(obj.RadiusX)}, {Float(obj.RadiusY)});"); 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 WriteCanvasGeometryGroupFactory(CodeBuilder builder, CanvasGeometry.Group obj, string typeName, string fieldName) { builder.WriteLine($"var result = {FieldAssignment(fieldName)}CanvasGeometry.CreateGroup("); builder.Indent(); builder.WriteLine($"null,"); builder.WriteLine($"new CanvasGeometry[] {{ {string.Join(", ", obj.Geometries.Select(g => CallFactoryFor(g)) ) } }},"); builder.WriteLine($"{_stringifier.FilledRegionDetermination(obj.FilledRegionDetermination)});"); 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. 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 WriteInstantiatorStart(CodeBuilder builder, CodeGenInfo info) { // Start writing the instantiator. builder.WriteLine("ref class AnimatedVisual sealed : public Microsoft::UI::Xaml::Controls::IAnimatedVisual"); builder.OpenScope(); if (info.UsesCanvasEffects || info.UsesCanvasGeometry) { // D2D factory field. builder.WriteLine("ComPtr<ID2D1Factory> _d2dFactory;"); } }
/// <inheritdoc/> protected override string WriteCompositeEffectFactory(CodeBuilder builder, Mgce.CompositeEffect compositeEffect) { var compositeEffectString = "compositeEffect"; builder.WriteLine($"var {compositeEffectString} = new CompositeEffect();"); builder.WriteLine($"{compositeEffectString}.Mode = {_stringifier.CanvasCompositeMode(compositeEffect.Mode)};"); foreach (var source in compositeEffect.Sources) { builder.WriteLine($"{compositeEffectString}.Sources.Add(new CompositionEffectSourceParameter({String(source.Name)}));"); } return(compositeEffectString); }
/// <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; } }
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(); }
/// <inheritdoc/> protected override string WriteCompositeEffectFactory(CodeBuilder builder, Mgce.CompositeEffect compositeEffect) { builder.WriteLine("ComPtr<CompositeEffect> compositeEffect(new CompositeEffect());"); builder.WriteLine($"compositeEffect->SetMode({_stringifier.CanvasCompositeMode(compositeEffect.Mode)});"); foreach (var source in compositeEffect.Sources) { builder.OpenScope(); builder.WriteLine($"auto sourceParameter = ref new CompositionEffectSourceParameter({String(source.Name)});"); builder.WriteLine("compositeEffect->AddSource(reinterpret_cast<ABI::Windows::Graphics::Effects::IGraphicsEffectSource*>(sourceParameter));"); builder.CloseScope(); } return("reinterpret_cast<Windows::Graphics::Effects::IGraphicsEffect^>(compositeEffect.Get())"); }
/// <inheritdoc/> protected override void WriteCanvasGeometryTransformedGeometryFactory(CodeBuilder builder, CanvasGeometry.TransformedGeometry obj, string typeName, string fieldName) { builder.WriteLine($"{typeName} result;"); builder.WriteLine("ID2D1Geometry *geoA = nullptr;"); builder.WriteLine("ID2D1TransformedGeometry *transformed;"); builder.WriteLine($"D2D1_MATRIX_3X2_F transformMatrix{_stringifier.Matrix3x2(obj.TransformMatrix)};"); builder.WriteLine(); builder.WriteLine($"{CallFactoryFor(obj.SourceGeometry)}->GetGeometry(&geoA);"); builder.WriteLine("FFHR(_d2dFactory->CreateTransformedGeometry(geoA, transformMatrix, &transformed));"); builder.WriteLine("geoA->Release();"); builder.WriteLine($"result = {FieldAssignment(fieldName)}new GeoSource(transformed);"); }
/// <inheritdoc/> protected override void WriteCanvasGeometryCombinationFactory(CodeBuilder builder, CanvasGeometry.Combination obj, string typeName, string fieldName) { builder.WriteLine($"var result = {FieldAssignment(fieldName)}{CallFactoryFor(obj.A)}."); builder.Indent(); builder.WriteLine($"CombineWith({CallFactoryFor(obj.B)},"); if (obj.Matrix.IsIdentity) { builder.WriteLine("Matrix3x2.Identity,"); } else { builder.WriteLine($"{_stringifier.Matrix3x2(obj.Matrix)},"); } builder.WriteLine($"{_stringifier.CanvasGeometryCombine(obj.CombineMode)});"); builder.UnIndent(); }
/// <inheritdoc/> protected override void WriteAnimatedVisualStart( CodeBuilder builder, IAnimatedVisualInfo info) { // Start writing the instantiator. builder.WriteLine($"ref class {info.ClassName} sealed"); builder.Indent(); builder.WriteLine($": public {AnimatedVisualTypeName}"); builder.UnIndent(); builder.OpenScope(); if (info.AnimatedVisualSourceInfo.UsesCanvasEffects || info.AnimatedVisualSourceInfo.UsesCanvasGeometry) { // D2D factory field. builder.WriteLine("ComPtr<ID2D1Factory> _d2dFactory;"); } }
/// <inheritdoc/> protected override void WriteCanvasGeometryRoundedRectangleFactory(CodeBuilder builder, CanvasGeometry.RoundedRectangle obj, string typeName, string fieldName) { builder.WriteLine($"var result = {FieldAssignment(fieldName)}CanvasGeometry.CreateRoundedRectangle("); builder.Indent(); builder.WriteLine("null,"); builder.WriteLine($"{Float(obj.X)},"); builder.WriteLine($"{Float(obj.Y)},"); builder.WriteLine($"{Float(obj.W)},"); builder.WriteLine($"{Float(obj.H)},"); builder.WriteLine($"{Float(obj.RadiusX)},"); builder.WriteLine($"{Float(obj.RadiusY)};"); builder.UnIndent(); }
/// <inheritdoc/> protected override void WriteCanvasGeometryGroupFactory(CodeBuilder builder, CanvasGeometry.Group obj, string typeName, string fieldName) { builder.WriteLine($"ComPtr<ID2D1Geometry> geometries[{obj.Geometries.Length}];"); builder.OpenScope(); for (var i = 0; i < obj.Geometries.Length; i++) { var geometry = obj.Geometries[i]; builder.WriteLine($"{CallFactoryFor(geometry)}->GetGeometry(&geometries[{i}]);"); } builder.CloseScope(); builder.WriteLine($"{typeName} result;"); builder.WriteLine("ComPtr<ID2D1GeometryGroup> group;"); builder.WriteLine("FFHR(_d2dFactory->CreateGeometryGroup("); builder.Indent(); builder.WriteLine($"{FilledRegionDetermination(obj.FilledRegionDetermination)},"); builder.WriteLine("geometries[0].GetAddressOf(),"); builder.WriteLine($"{obj.Geometries.Length},"); builder.WriteLine("&group));"); builder.UnIndent(); builder.WriteLine($"result = {FieldAssignment(fieldName)}new GeoSource(group.Get());"); }
/// <inheritdoc/> protected override void WriteCanvasGeometryRoundedRectangleFactory(CodeBuilder builder, CanvasGeometry.RoundedRectangle obj, string typeName, string fieldName) { builder.WriteLine($"{typeName} result;"); builder.WriteLine("ComPtr<ID2D1RoundedRectangleGeometry> rect;"); builder.WriteLine("FFHR(_d2dFactory->CreateRoundedRectangleGeometry("); builder.Indent(); builder.WriteLine($"D2D1::RoundedRect({{{Float(obj.X)},{Float(obj.Y)}}}, {Float(obj.RadiusX)}, {Float(obj.RadiusY)}),"); builder.WriteLine("&rect));"); builder.UnIndent(); builder.WriteLine($"result = {FieldAssignment(fieldName)}new GeoSource(rect.Get());"); }
/// <inheritdoc/> protected override void WriteCanvasGeometryEllipseFactory(CodeBuilder builder, CanvasGeometry.Ellipse obj, string typeName, string fieldName) { builder.WriteLine($"{typeName} result;"); builder.WriteLine("ComPtr<ID2D1EllipseGeometry> ellipse;"); builder.WriteLine("FFHR(_d2dFactory->CreateEllipseGeometry("); builder.Indent(); builder.WriteLine($"D2D1::Ellipse({{{Float(obj.X)},{Float(obj.Y)}}}, {Float(obj.RadiusX)}, {Float(obj.RadiusY)}),"); builder.WriteLine("&ellipse));"); builder.UnIndent(); builder.WriteLine($"result = {FieldAssignment(fieldName)}new GeoSource(ellipse.Get());"); }
/// <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(); }
/// <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 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(); }
/// <inheritdoc/> protected override void WriteCanvasGeometryPathFactory(CodeBuilder builder, CanvasGeometry.Path obj, string typeName, string fieldName) { builder.WriteLine($"{typeName} result;"); builder.WriteLine($"using (var builder = new CanvasPathBuilder(null))"); builder.OpenScope(); if (obj.FilledRegionDetermination != CanvasFilledRegionDetermination.Alternate) { builder.WriteLine($"builder.SetFilledRegionDetermination({_stringifier.FilledRegionDetermination(obj.FilledRegionDetermination)});"); } foreach (var command in obj.Commands) { switch (command.Type) { case CanvasPathBuilder.CommandType.BeginFigure: builder.WriteLine($"builder.BeginFigure({Vector2(((CanvasPathBuilder.Command.BeginFigure)command).StartPoint)});"); break; case CanvasPathBuilder.CommandType.EndFigure: builder.WriteLine($"builder.EndFigure({_stringifier.CanvasFigureLoop(((CanvasPathBuilder.Command.EndFigure)command).FigureLoop)});"); break; case CanvasPathBuilder.CommandType.AddLine: builder.WriteLine($"builder.AddLine({Vector2(((CanvasPathBuilder.Command.AddLine)command).EndPoint)});"); break; case CanvasPathBuilder.CommandType.AddCubicBezier: var cb = (CanvasPathBuilder.Command.AddCubicBezier)command; builder.WriteLine($"builder.AddCubicBezier({Vector2(cb.ControlPoint1)}, {Vector2(cb.ControlPoint2)}, {Vector2(cb.EndPoint)});"); break; default: throw new InvalidOperationException(); } } builder.WriteLine($"result = {FieldAssignment(fieldName)}CanvasGeometry.CreatePath(builder);"); builder.CloseScope(); }
void WriteAnimatedVisualInvalidatedEvent(CodeBuilder builder) { builder.WriteLine("public event TypedEventHandler<IDynamicAnimatedVisualSource, object> AnimatedVisualInvalidated"); builder.OpenScope(); builder.WriteLine("add"); builder.OpenScope(); builder.WriteLine("return GetAnimatedVisualInvalidatedEventRegistrationTokenTable().AddEventHandler(value);"); builder.CloseScope(); builder.WriteLine("remove"); builder.OpenScope(); builder.WriteLine("GetAnimatedVisualInvalidatedEventRegistrationTokenTable().RemoveEventHandler(value);"); builder.CloseScope(); builder.CloseScope(); builder.WriteLine(); }
protected override void WriteThemePropertyImpls(CodeBuilder builder) { var propertyBindings = SourceInfo.SourceMetadata.PropertyBindings; var sourceClassQualifier = $"{S.Namespace(SourceInfo.Namespace)}::{SourceClassName}::"; if (propertyBindings.Any(pb => pb.ExposedType == PropertySetValueType.Color)) { // Write the helper for converting a color to a vector 4. builder.WriteLine($"float4 {sourceClassQualifier}ColorAsVector4(Color color)"); builder.OpenScope(); builder.WriteLine("return { static_cast<float>(color.R), static_cast<float>(color.G), static_cast<float>(color.B), static_cast<float>(color.A) };"); builder.CloseScope(); builder.WriteLine(); } builder.WriteLine($"{T.CompositionPropertySet} {sourceClassQualifier}EnsureThemeProperties({T.Compositor} compositor)"); builder.OpenScope(); builder.WriteLine($"if ({SourceInfo.ThemePropertiesFieldName} == nullptr)"); builder.OpenScope(); builder.WriteLine($"{SourceInfo.ThemePropertiesFieldName} = compositor{S.Deref}CreatePropertySet();"); // Initialize the values in the property set. foreach (var prop in propertyBindings) { WriteThemePropertyInitialization(builder, SourceInfo.ThemePropertiesFieldName, prop, prop.BindingName); } builder.CloseScope(); builder.WriteLine(); builder.WriteLine($"return {SourceInfo.ThemePropertiesFieldName};"); builder.CloseScope(); builder.WriteLine(); // The GetThemeProperties method is designed to allow setting of properties when the actual // type of the IAnimatedVisualSource is not known. It relies on a custom interface that declares // it, so if we're not generating code for a custom interface, there's no reason to generate // the method. if (IsInterfaceCustom) { builder.WriteLine($"{T.CompositionPropertySet} {sourceClassQualifier}GetThemeProperties({T.Compositor} compositor)"); builder.OpenScope(); builder.WriteLine("return EnsureThemeProperties(compositor);"); builder.CloseScope(); builder.WriteLine(); } // Write property implementations for each theme property. foreach (var prop in propertyBindings) { if (SourceInfo.GenerateDependencyObject) { // Write the dependency property accessor. builder.WriteLine($"DependencyProperty^ {sourceClassQualifier}{prop.BindingName}Property()"); builder.OpenScope(); builder.WriteLine($"return _{S.CamelCase(prop.BindingName)}Property;"); builder.CloseScope(); builder.WriteLine(); // Write the dependency property change handler. builder.WriteLine($"void {sourceClassQualifier}On{prop.BindingName}Changed(DependencyObject^ d, DependencyPropertyChangedEventArgs^ e)"); builder.OpenScope(); builder.WriteLine($"auto self = ({sourceClassQualifier}^)d;"); builder.WriteLine(); builder.WriteLine("if (self->_themeProperties != nullptr)"); builder.OpenScope(); WriteThemePropertyInitialization(builder, $"self->{SourceInfo.ThemePropertiesFieldName}", prop, "e->NewValue"); builder.CloseScope(); builder.CloseScope(); builder.WriteLine(); // Write the dependency property initializer. builder.WriteLine($"DependencyProperty^ {sourceClassQualifier}_{S.CamelCase(prop.BindingName)}Property ="); builder.Indent(); builder.WriteLine($"DependencyProperty::Register("); builder.Indent(); builder.WriteLine($"{S.String(prop.BindingName)},"); builder.WriteLine($"{TypeName(prop.ExposedType)}::typeid,"); builder.WriteLine($"{sourceClassQualifier}typeid,"); builder.WriteLine($"ref new PropertyMetadata(c_theme{prop.BindingName},"); builder.WriteLine($"ref new PropertyChangedCallback(&{sourceClassQualifier}On{prop.BindingName}Changed)));"); builder.UnIndent(); builder.UnIndent(); builder.WriteLine(); } // Write the getter. builder.WriteLine($"{TypeName(prop.ExposedType)} {sourceClassQualifier}{prop.BindingName}::get()"); builder.OpenScope(); if (SourceInfo.GenerateDependencyObject) { // Get the value from the dependency property. builder.WriteLine($"return ({TypeName(prop.ExposedType)})GetValue(_{S.CamelCase(prop.BindingName)}Property);"); } else { // Get the value from the backing field. builder.WriteLine($"return _theme{prop.BindingName};"); } builder.CloseScope(); builder.WriteLine(); // Write the setter. builder.WriteLine($"void {sourceClassQualifier}{prop.BindingName}::set({TypeName(prop.ExposedType)} value)"); builder.OpenScope(); if (SourceInfo.GenerateDependencyObject) { builder.WriteLine($"SetValue(_{S.CamelCase(prop.BindingName)}Property, value);"); } else { // This saves to the backing field, and updates the theme property // set if one has been created. builder.WriteLine($"_theme{prop.BindingName} = value;"); builder.WriteLine("if (_themeProperties != nullptr)"); builder.OpenScope(); WriteThemePropertyInitialization(builder, "_themeProperties", prop); builder.CloseScope(); } builder.CloseScope(); builder.WriteLine(); } }
protected override void WriteThemePropertyImpls(CodeBuilder builder) { var propertyBindings = SourceInfo.SourceMetadata.PropertyBindings; var sourceClassQualifier = $"{T.CompositionPropertySet} {S.Namespace(SourceInfo.Namespace)}::{SourceClassName}::"; if (propertyBindings.Any(pb => pb.ExposedType == PropertySetValueType.Color)) { // Write the helper for converting a color to a vector 4. builder.WriteLine($"float4 {sourceClassQualifier}ColorAsVector4(Color color)"); builder.OpenScope(); builder.WriteLine("return { static_cast<float>(color.R), static_cast<float>(color.G), static_cast<float>(color.B), static_cast<float>(color.A) };"); builder.CloseScope(); builder.WriteLine(); } builder.WriteLine($"{T.CompositionPropertySet} {sourceClassQualifier}EnsureThemeProperties({T.Compositor} compositor)"); builder.OpenScope(); builder.WriteLine($"if ({SourceInfo.ThemePropertiesFieldName} == nullptr)"); builder.OpenScope(); builder.WriteLine($"{SourceInfo.ThemePropertiesFieldName} = compositor{S.Deref}CreatePropertySet();"); // Initialize the values in the property set. foreach (var prop in propertyBindings) { WriteThemePropertyInitialization(builder, SourceInfo.ThemePropertiesFieldName, prop); } builder.CloseScope(); builder.WriteLine(); builder.WriteLine($"return {SourceInfo.ThemePropertiesFieldName};"); builder.CloseScope(); builder.WriteLine(); builder.WriteLine($"{T.CompositionPropertySet} {sourceClassQualifier}GetThemeProperties({T.Compositor} compositor)"); builder.OpenScope(); builder.WriteLine("return EnsureThemeProperties(compositor);"); builder.CloseScope(); builder.WriteLine(); // Write property implementations for each theme property. foreach (var prop in propertyBindings) { // Write the getter. This just reads the values out of the backing field. builder.WriteLine($"{TypeName(prop.ExposedType)} {sourceClassQualifier}{prop.BindingName}()"); builder.OpenScope(); builder.WriteLine($"return _theme{prop.BindingName};"); builder.CloseScope(); builder.WriteLine(); // Write the setter. This saves to the backing field, and updates the theme property // set if one has been created. builder.WriteLine($"void {sourceClassQualifier}{prop.BindingName}({TypeName(prop.ExposedType)} value)"); builder.OpenScope(); builder.WriteLine($"_theme{prop.BindingName} = value;"); builder.WriteLine("if (_themeProperties != nullptr)"); builder.OpenScope(); WriteThemePropertyInitialization(builder, "_themeProperties", prop); builder.CloseScope(); builder.CloseScope(); builder.WriteLine(); } }
/// <inheritdoc/> protected override void WriteCanvasGeometryPathFactory(CodeBuilder builder, CanvasGeometry.Path obj, string typeName, string fieldName) { builder.WriteLine($"{typeName} result;"); // D2D Setup builder.WriteLine("ComPtr<ID2D1PathGeometry> path;"); builder.WriteLine($"{FailFastWrapper("_d2dFactory->CreatePathGeometry(&path)")};"); builder.WriteLine("ComPtr<ID2D1GeometrySink> sink;"); builder.WriteLine($"{FailFastWrapper("path->Open(&sink)")};"); if (obj.FilledRegionDetermination != CanvasFilledRegionDetermination.Alternate) { builder.WriteLine($"sink->SetFillMode({FilledRegionDetermination(obj.FilledRegionDetermination)});"); } foreach (var command in obj.Commands) { switch (command.Type) { case CanvasPathBuilder.CommandType.BeginFigure: // Assume D2D1_FIGURE_BEGIN_FILLED builder.WriteLine($"sink->BeginFigure({Vector2(((CanvasPathBuilder.Command.BeginFigure)command).StartPoint)}, D2D1_FIGURE_BEGIN_FILLED);"); break; case CanvasPathBuilder.CommandType.EndFigure: builder.WriteLine($"sink->EndFigure({CanvasFigureLoop(((CanvasPathBuilder.Command.EndFigure)command).FigureLoop)});"); break; case CanvasPathBuilder.CommandType.AddLine: builder.WriteLine($"sink->AddLine({Vector2(((CanvasPathBuilder.Command.AddLine)command).EndPoint)});"); break; case CanvasPathBuilder.CommandType.AddCubicBezier: var cb = (CanvasPathBuilder.Command.AddCubicBezier)command; builder.WriteLine($"sink->AddBezier({{ {Vector2(cb.ControlPoint1)}, {Vector2(cb.ControlPoint2)}, {Vector2(cb.EndPoint)} }});"); break; default: throw new InvalidOperationException(); } } builder.WriteLine($"{FailFastWrapper("sink->Close()")};"); builder.WriteLine("GeoSource* rawResult = new GeoSource(path.Get());"); builder.WriteLine($"result = {FieldAssignment(fieldName)}rawResult;"); builder.WriteLine("rawResult->Release();"); }
/// <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}"); } }
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(); }
/// <inheritdoc/> protected override void WriteCanvasGeometryCombinationFactory(CodeBuilder builder, CanvasGeometry.Combination obj, string typeName, string fieldName) { builder.WriteLine($"{typeName} result;"); builder.WriteLine("ID2D1Geometry *geoA = nullptr, *geoB = nullptr;"); builder.WriteLine($"{CallFactoryFor(obj.A)}->GetGeometry(&geoA);"); builder.WriteLine($"{CallFactoryFor(obj.B)}->GetGeometry(&geoB);"); builder.WriteLine("ComPtr<ID2D1PathGeometry> path;"); builder.WriteLine($"{FailFastWrapper("_d2dFactory->CreatePathGeometry(&path)")};"); builder.WriteLine("ComPtr<ID2D1GeometrySink> sink;"); builder.WriteLine($"{FailFastWrapper("path->Open(&sink)")};"); builder.WriteLine($"FFHR(geoA->CombineWithGeometry("); builder.Indent(); builder.WriteLine($"geoB,"); builder.WriteLine($"{_stringifier.CanvasGeometryCombine(obj.CombineMode)},"); builder.WriteLine($"{_stringifier.Matrix3x2(obj.Matrix)},"); builder.WriteLine($"sink.Get()));"); builder.UnIndent(); builder.WriteLine("geoA->Release();"); builder.WriteLine("geoB->Release();"); builder.WriteLine($"{FailFastWrapper("sink->Close()")};"); builder.WriteLine($"result = {FieldAssignment(fieldName)}new GeoSource(path.Get());"); }
/// <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(); 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(); 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(); }
/// <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.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;"); if (info.UsesNamespaceWindowsUIXamlMedia) { builder.WriteLine("using namespace Windows::UI::Xaml::Media;"); } if (info.UsesStreams) { builder.WriteLine("using namespace Platform;"); builder.WriteLine("using namespace Windows::Storage::Streams;"); } 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;"); } }