public void CompilerDependencyByIncludeTypeAnalysis() { var package = new Package(); // ReSharper disable once UnusedVariable - we need a package session to compile var packageSession = new PackageSession(package); var asset1 = new AssetItem("content1", new MyAsset1(), package); // Should be compiled (root) var asset2 = new AssetItem("content2", new MyAsset2(), package); // Should be compiled (Runtime for Asset1) var asset31 = new AssetItem("content3_1", new MyAsset3(), package); // Should NOT be compiled (CompileAsset for Asset1) var asset32 = new AssetItem("content3_2", new MyAsset3(), package); // Should be compiled (Runtime for Asset2) ((MyAsset1)asset1.Asset).MyContent2 = AttachedReferenceManager.CreateProxyObject <MyContent2>(asset2.Id, asset2.Location); ((MyAsset1)asset1.Asset).MyContent3 = AttachedReferenceManager.CreateProxyObject <MyContent3>(asset31.Id, asset31.Location); ((MyAsset2)asset2.Asset).MyContent3 = AttachedReferenceManager.CreateProxyObject <MyContent3>(asset32.Id, asset32.Location); package.Assets.Add(asset1); package.Assets.Add(asset2); package.Assets.Add(asset31); package.Assets.Add(asset32); package.RootAssets.Add(new AssetReference(asset1.Id, asset1.Location)); // Create context var context = new AssetCompilerContext { CompilationContext = typeof(AssetCompilationContext) }; // Builds the project var assetBuilder = new PackageCompiler(new RootPackageAssetEnumerator(package)); context.Properties.Set(BuildAssetNode.VisitRuntimeTypes, true); var assetBuildResult = assetBuilder.Prepare(context); // Total number of asset to compile = 3 Assert.AreEqual(3, assetBuildResult.BuildSteps.Count); }
public static ComputeTextureColor GenerateMaterialTextureNode(string vfsOutputPath, string sourceTextureFile, uint textureUVSetIndex, Vector2 textureUVscaling, TextureAddressMode addressModeU, TextureAddressMode addressModeV, Logger logger) { var textureFileName = Path.GetFileNameWithoutExtension(sourceTextureFile); var url = vfsOutputPath + "_" + textureFileName; if (File.Exists(sourceTextureFile)) { if (logger != null) { logger.Warning($"The texture '{sourceTextureFile}' referenced in the mesh material can not be found on the system. Loading will probably fail at run time.", CallerInfo.Get()); } } var uvScaling = textureUVscaling; var textureName = textureFileName; var texture = AttachedReferenceManager.CreateProxyObject <Texture>(AssetId.Empty, textureName); var currentTexture = new ComputeTextureColor(texture, (TextureCoordinate)textureUVSetIndex, uvScaling, Vector2.Zero); currentTexture.AddressModeU = addressModeU; currentTexture.AddressModeV = addressModeV; return(currentTexture); }
public static GameSettingsAsset Create() { var asset = new GameSettingsAsset(); asset.SplashScreenTexture = AttachedReferenceManager.CreateProxyObject <Texture>(new AssetId("d26edb11-10bd-403c-b3c2-9c7fcccf25e5"), "StrideDefaultSplashScreen"); asset.SplashScreenColor = Color.Black; //add default filters, todo maybe a config file somewhere is better asset.PlatformFilters.Add("PowerVR SGX 54[0-9]"); asset.PlatformFilters.Add("Adreno \\(TM\\) 2[0-9][0-9]"); asset.PlatformFilters.Add("Adreno (TM) 320"); asset.PlatformFilters.Add("Adreno (TM) 330"); asset.PlatformFilters.Add("Adreno \\(TM\\) 4[0-9][0-9]"); asset.PlatformFilters.Add("NVIDIA Tegra"); asset.PlatformFilters.Add("Intel(R) HD Graphics"); asset.PlatformFilters.Add("^Mali\\-4"); asset.PlatformFilters.Add("^Mali\\-T6"); asset.PlatformFilters.Add("^Mali\\-T7"); asset.GetOrCreate <AudioEngineSettings>(); asset.GetOrCreate <EditorSettings>(); asset.GetOrCreate <RenderingSettings>(); asset.GetOrCreate <StreamingSettings>(); asset.GetOrCreate <TextureSettings>(); return(asset); }
public void CompilerVisitRuntimeType() { var package = new Package(); // ReSharper disable once UnusedVariable - we need a package session to compile var packageSession = new PackageSession(package); var otherAssets = new List <AssetItem> { new AssetItem("contentRB", new MyAssetContentType(0), package), new AssetItem("contentRA", new MyAssetContentType(1), package), new AssetItem("content0B", new MyAssetContentType(2), package), new AssetItem("content0M", new MyAssetContentType(3), package), new AssetItem("content0A", new MyAssetContentType(4), package), new AssetItem("content1B", new MyAssetContentType(5), package), new AssetItem("content1M", new MyAssetContentType(6), package), new AssetItem("content1A", new MyAssetContentType(7), package), new AssetItem("content2B", new MyAssetContentType(8), package), new AssetItem("content2M", new MyAssetContentType(9), package), new AssetItem("content2A", new MyAssetContentType(10), package), new AssetItem("content3B", new MyAssetContentType(11), package), new AssetItem("content3M", new MyAssetContentType(12), package), new AssetItem("content3A", new MyAssetContentType(13), package), new AssetItem("content4B", new MyAssetContentType(14), package), new AssetItem("content4M", new MyAssetContentType(15), package), new AssetItem("content4A", new MyAssetContentType(16), package), }; var assetToVisit = new MyAsset1(); assetToVisit.Before = AttachedReferenceManager.CreateProxyObject <MyContentType>(otherAssets[0].Id, otherAssets[0].Location); assetToVisit.Zafter = AttachedReferenceManager.CreateProxyObject <MyContentType>(otherAssets[1].Id, otherAssets[1].Location); assetToVisit.RuntimeTypes.Add(CreateRuntimeType(otherAssets[2], otherAssets[3], otherAssets[4])); assetToVisit.RuntimeTypes.Add(CreateRuntimeType(otherAssets[5], otherAssets[6], otherAssets[7])); assetToVisit.RuntimeTypes.Add(CreateRuntimeType(otherAssets[8], otherAssets[9], otherAssets[10])); assetToVisit.RuntimeTypes.Add(CreateRuntimeType(otherAssets[11], otherAssets[12], otherAssets[13])); assetToVisit.RuntimeTypes.Add(CreateRuntimeType(otherAssets[14], otherAssets[15], otherAssets[16])); assetToVisit.RuntimeTypes[0].A = assetToVisit.RuntimeTypes[1]; assetToVisit.RuntimeTypes[0].B = assetToVisit.RuntimeTypes[2]; assetToVisit.RuntimeTypes[1].A = assetToVisit.RuntimeTypes[3]; assetToVisit.RuntimeTypes[1].B = assetToVisit.RuntimeTypes[4]; otherAssets.ForEach(x => package.Assets.Add(x)); var assetItem = new AssetItem("asset", assetToVisit, package); package.Assets.Add(assetItem); package.RootAssets.Add(new AssetReference(assetItem.Id, assetItem.Location)); // Create context var context = new AssetCompilerContext { CompilationContext = typeof(AssetCompilationContext) }; // Builds the project var assetBuilder = new PackageCompiler(new RootPackageAssetEnumerator(package)); context.Properties.Set(BuildAssetNode.VisitRuntimeTypes, true); var assetBuildResult = assetBuilder.Prepare(context); Assert.AreEqual(16, assetBuildResult.BuildSteps.Count); }
public ShaderSource Generate(MaterialGeneratorContext context) { var texture = context.GraphicsProfile >= GraphicsProfile.Level_10_0 ? AttachedReferenceManager.CreateProxyObject <Texture>(new AssetId("a49995f8-2380-4baa-a03e-f8d1da35b79a"), "XenkoEnvironmentLightingDFGLUT16") : AttachedReferenceManager.CreateProxyObject <Texture>(new AssetId("87540190-ab97-4b4e-b3c2-d57d2fbb1ff3"), "XenkoEnvironmentLightingDFGLUT8"); context.Parameters.Set(MaterialSpecularMicrofacetEnvironmentGGXLUTKeys.EnvironmentLightingDFG_LUT, texture); return(new ShaderClassSource("MaterialSpecularMicrofacetEnvironmentGGXLUT")); }
public static bool Upgrade(PackageSession session, ILogger log, Package dependentPackage, PackageDependency dependency, Package dependencyPackage, IList <PackageLoadingAssetFile> assetFiles) { var packageSharedProfile = dependentPackage.Profiles.FindSharedProfile(); // Only do something if there is a default scene defined if (packageSharedProfile != null && packageSharedProfile.Properties.ContainsKey(DefaultScene)) { var defaultScene = Get(packageSharedProfile.Properties, DefaultScene); var defaultGraphicsProfile = Get(packageSharedProfile.Properties, DefaultGraphicsProfile); // If available, use graphics profile from Windows platform foreach (var profile in dependentPackage.Profiles) { if (profile.Platform == PlatformType.Windows && profile.Properties.ContainsKey(DefaultGraphicsProfile)) { defaultGraphicsProfile = Get(profile.Properties, DefaultGraphicsProfile); } } // Create asset var gameSettingsAsset = GameSettingsFactory.Create(); gameSettingsAsset.DefaultScene = AttachedReferenceManager.CreateProxyObject <Scene>(defaultScene.Id, defaultScene.Location); var renderingSettings = gameSettingsAsset.Get <RenderingSettings>(); renderingSettings.DisplayOrientation = (RequiredDisplayOrientation)Get(packageSharedProfile.Properties, DisplayOrientation); renderingSettings.ColorSpace = ColorSpace.Linear; renderingSettings.DefaultBackBufferWidth = Get(packageSharedProfile.Properties, BackBufferWidth); renderingSettings.DefaultBackBufferHeight = Get(packageSharedProfile.Properties, BackBufferHeight); renderingSettings.DefaultGraphicsProfile = defaultGraphicsProfile; // Add asset using (var memoryStream = new MemoryStream()) { AssetSerializer.Save(memoryStream, gameSettingsAsset, log); assetFiles.Add(new PackageLoadingAssetFile(dependentPackage, GameSettingsLocation + FileExtension, null) { AssetContent = memoryStream.ToArray() }); } // Clean properties foreach (var profile in dependentPackage.Profiles) { profile.Properties.Remove(DefaultScene.Name); profile.Properties.Remove(BackBufferWidth.Name); profile.Properties.Remove(BackBufferHeight.Name); profile.Properties.Remove(DefaultGraphicsProfile.Name); profile.Properties.Remove(DisplayOrientation.Name); } } return(true); }
public override object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { var url = (string)value; var asset = SessionViewModel.Instance.AllAssets.FirstOrDefault(x => x.Url == url); if (asset == null) { return(null); } var contentType = AssetRegistry.GetContentType(asset.AssetType); return(AttachedReferenceManager.CreateProxyObject(contentType, asset.Id, asset.Url)); }
public override object ConvertFrom(ref ObjectContext context, Scalar fromScalar) { AssetId guid; UFile location; if (!AssetReference.TryParse(fromScalar.Value, out guid, out location)) { throw new YamlException(fromScalar.Start, fromScalar.End, "Unable to decode asset reference [{0}]. Expecting format GUID:LOCATION".ToFormat(fromScalar.Value)); } var instance = AttachedReferenceManager.CreateProxyObject(context.Descriptor.Type, guid, location); return(instance); }
public override void VisitCollectionItem(IEnumerable collection, CollectionDescriptor descriptor, int index, object item, ITypeDescriptor itemDescriptor) { base.VisitCollectionItem(collection, descriptor, index, item, itemDescriptor); var assetReference = item as AssetReference; var attachedReference = AttachedReferenceManager.GetAttachedReference(item); // We cannot set links if we do not have indexer accessor if (!descriptor.HasIndexerAccessors) { return; } if (assetReference != null) { AddLink(assetReference, (guid, location) => { var link = AssetReference.New(guid ?? assetReference.Id, location); descriptor.SetValue(collection, index, link); return(link); }); } else if (attachedReference != null) { AddLink(attachedReference, (guid, location) => { var link = guid.HasValue && guid.Value != AssetId.Empty ? AttachedReferenceManager.CreateProxyObject(descriptor.ElementType, guid.Value, location) : null; descriptor.SetValue(collection, index, link); return(link); }); } else if (item is UFile) { AddLink(item, (guid, location) => { var link = new UFile(location); descriptor.SetValue(collection, index, link); return(link); }); } else if (item is UDirectory) { AddLink(item, (guid, location) => { var link = new UDirectory(location); descriptor.SetValue(collection, index, link); return(link); }); } }
private static AssetItem ImportModel(List <AssetItem> assetReferences, UFile assetSource, UFile localPath, EntityInfo entityInfo, bool shouldPostFixName, AssetItem skeletonAsset) { var asset = new ModelAsset { Source = assetSource }; if (entityInfo.Models != null) { var loadedMaterials = assetReferences.Where(x => x.Asset is MaterialAsset).ToList(); foreach (var material in entityInfo.Materials) { var modelMaterial = new ModelMaterial { Name = material.Key, MaterialInstance = new MaterialInstance() }; var foundMaterial = loadedMaterials.FirstOrDefault(x => x.Location == new UFile(material.Key)); if (foundMaterial != null) { var reference = AttachedReferenceManager.CreateProxyObject <Material>(foundMaterial.Id, foundMaterial.Location); modelMaterial.MaterialInstance.Material = reference; } //todo Instead of null material add a default xenko material asset.Materials.Add(AttachId(modelMaterial)); } //handle the case where during import we imported no materials at all //todo Instead of null material add a default xenko material if (entityInfo.Materials.Count == 0) { var modelMaterial = new ModelMaterial { Name = "Material", MaterialInstance = new MaterialInstance() }; asset.Materials.Add(AttachId(modelMaterial)); } } if (skeletonAsset != null) { asset.Skeleton = AttachedReferenceManager.CreateProxyObject <Skeleton>(skeletonAsset.Id, skeletonAsset.Location); } var modelUrl = new UFile(localPath.GetFileName() + (shouldPostFixName?" Model": "")); var assetItem = new AssetItem(modelUrl, asset); assetReferences.Add(assetItem); return(assetItem); }
public override void VisitSetItem(IEnumerable setObject, SetDescriptor descriptor, object item, ITypeDescriptor itemDescriptor) { base.VisitSetItem(setObject, descriptor, item, itemDescriptor); var assetReference = item as AssetReference; var attachedReference = AttachedReferenceManager.GetAttachedReference(item); if (assetReference != null) { AddLink(assetReference, (guid, location) => { var link = AssetReference.New(guid ?? assetReference.Id, location); descriptor.Add(setObject, link); return(link); }); } else if (attachedReference != null) { AddLink(attachedReference, (guid, location) => { object link = guid.HasValue && guid.Value != AssetId.Empty ? AttachedReferenceManager.CreateProxyObject(descriptor.ElementType, guid.Value, location) : null; descriptor.Add(setObject, link); return(link); }); } else if (item is UFile) { AddLink(item, (guid, location) => { var link = new UFile(location); descriptor.Add(setObject, link); return(link); }); } else if (item is UDirectory) { AddLink(item, (guid, location) => { var link = new UDirectory(location); descriptor.Add(setObject, link); return(link); }); } }
/// <summary> /// Creates a reference to the given asset that matches the given reference type. /// </summary> /// <param name="asset">The target asset of the reference to create.</param> /// <param name="referenceType">The type of reference to create.</param> /// <returns>A reference to the given asset if it's not null and <paramref name="referenceType"/> is a valid reference type, null otherwise.</returns> /// <remarks>A reference type is either an <see cref="AssetReference"/> or a content type registered in the <see cref="AssetRegistry"/>.</remarks> public static object CreateReference(AssetViewModel asset, Type referenceType) { if (asset != null) { if (AssetRegistry.IsContentType(referenceType)) { var assetType = asset.AssetItem.Asset.GetType(); var contentType = AssetRegistry.GetContentType(assetType); return(referenceType.IsAssignableFrom(contentType) ? AttachedReferenceManager.CreateProxyObject(contentType, asset.Id, asset.Url) : null); } if (typeof(AssetReference).IsAssignableFrom(referenceType)) { return(new AssetReference(asset.AssetItem.Id, asset.AssetItem.Location)); } } return(null); }
private static void ImportAnimation(List <AssetItem> assetReferences, UFile localPath, List <string> animationNodes, bool shouldPostFixName, AssetItem skeletonAsset, TimeSpan animationStartTime, TimeSpan animationEndTime) { if (animationNodes != null && animationNodes.Count > 0) { var assetSource = localPath; var asset = new AnimationAsset { Source = assetSource, AnimationTimeMaximum = animationEndTime, AnimationTimeMinimum = animationStartTime }; var animUrl = localPath.GetFileNameWithoutExtension() + (shouldPostFixName ? " Animation" : ""); if (skeletonAsset != null) { asset.Skeleton = AttachedReferenceManager.CreateProxyObject <Skeleton>(skeletonAsset.Id, skeletonAsset.Location); } assetReferences.Add(new AssetItem(animUrl, asset)); } }
private void ParentPropertyChanged() { if (updatingParent || UndoRedoService.UndoRedoInProgress) { return; } try { updatingParent = true; var newValue = parent != null?AttachedReferenceManager.CreateProxyObject <Scene>(parent.Id, parent.AssetItem.Location) : null; parentNode.Update(newValue); } finally { updatingParent = false; } }
public override object ConvertFrom(ref ObjectContext context, Scalar fromScalar) { Guid guid; UFile location; Guid referenceId; if (!AssetReference.TryParse(fromScalar.Value, out referenceId, out guid, out location)) { throw new YamlException(fromScalar.Start, fromScalar.End, "Unable to decode asset reference [{0}]. Expecting format GUID:LOCATION".ToFormat(fromScalar.Value)); } var instance = AttachedReferenceManager.CreateProxyObject(context.Descriptor.Type, guid, location); // If the referenceId is empty, force its creation, else attach it to the reference if (referenceId == Guid.Empty) { IdentifiableHelper.GetId(instance); } else { IdentifiableHelper.SetId(instance, referenceId); } return(instance); }
protected override Task <ResultStatus> DoCommandOverride(ICommandContext commandContext) { var assetManager = new ContentManager(MicrothreadLocalDatabases.ProviderService); assetManager.Serializer.RegisterSerializer(new ImageTextureSerializer()); // Create atlas texture Dictionary <SpriteInfo, PackedSpriteInfo> spriteToPackedSprite = null; // Generate texture atlas var isPacking = Parameters.SheetAsset.Packing.Enabled; if (isPacking) { var resultStatus = CreateAtlasTextures(commandContext, out spriteToPackedSprite); if (resultStatus != ResultStatus.Successful) { return(Task.FromResult(resultStatus)); } } var imageGroupData = new SpriteSheet(); // add the sprite data to the sprite list. foreach (var image in Parameters.SheetAsset.Sprites) { string textureUrl; RectangleF region; ImageOrientation orientation; var borders = image.Borders; var center = image.Center + (image.CenterFromMiddle ? new Vector2(image.TextureRegion.Width, image.TextureRegion.Height) / 2 : Vector2.Zero); if (isPacking && spriteToPackedSprite.TryGetValue(image, out var packedSprite)) // ensure that unpackable elements (invalid because of null size/texture) are properly added in the sheet using the normal path { var isOriginalSpriteRotated = image.Orientation == ImageOrientation.Rotated90; region = packedSprite.Region; orientation = (packedSprite.IsRotated ^ isOriginalSpriteRotated) ? ImageOrientation.Rotated90 : ImageOrientation.AsIs; textureUrl = SpriteSheetAsset.BuildTextureAtlasUrl(Url, spriteToPackedSprite[image].AtlasTextureIndex); // update the center and border info, if the packer rotated the sprite // note: X->Left, Y->Top, Z->Right, W->Bottom. if (packedSprite.IsRotated) { // turned the sprite CCW if (isOriginalSpriteRotated) { var oldCenterX = center.X; center.X = center.Y; center.Y = region.Height - oldCenterX; var oldBorderW = borders.W; borders.W = borders.X; borders.X = borders.Y; borders.Y = borders.Z; borders.Z = oldBorderW; } else // turned the sprite CW { var oldCenterX = center.X; center.X = region.Width - center.Y; center.Y = oldCenterX; var oldBorderW = borders.W; borders.W = borders.Z; borders.Z = borders.Y; borders.Y = borders.X; borders.X = oldBorderW; } } } else { region = image.TextureRegion; orientation = image.Orientation; Parameters.ImageToTextureUrl.TryGetValue(image, out textureUrl); } // Affect the texture Texture texture = null; if (textureUrl != null) { texture = AttachedReferenceManager.CreateProxyObject <Texture>(AssetId.Empty, textureUrl); } else { commandContext.Logger.Warning($"Image '{image.Name}' has an invalid image source file '{image.Source}', resulting texture will be null."); } imageGroupData.Sprites.Add(new Graphics.Sprite { Name = image.Name, Region = region, Orientation = orientation, Center = center, Borders = borders, PixelsPerUnit = new Vector2(image.PixelsPerUnit), Texture = texture, IsTransparent = false, }); } // set the transparency information to all the sprites if (Parameters.SheetAsset.Alpha != AlphaFormat.None) // Skip the calculation when format is forced without alpha. { var urlToTexImage = new Dictionary <string, Tuple <TexImage, Image> >(); using (var texTool = new TextureTool()) { foreach (var sprite in imageGroupData.Sprites) { if (sprite.Texture == null) // the sprite texture is invalid { continue; } var textureUrl = AttachedReferenceManager.GetOrCreateAttachedReference(sprite.Texture).Url; if (!urlToTexImage.ContainsKey(textureUrl)) { var image = assetManager.Load <Image>(textureUrl); var newTexImage = texTool.Load(image, false); // the sRGB mode does not impact on the alpha level texTool.Decompress(newTexImage, false); // the sRGB mode does not impact on the alpha level urlToTexImage[textureUrl] = Tuple.Create(newTexImage, image); } var texImage = urlToTexImage[textureUrl].Item1; var region = new Rectangle { X = (int)Math.Floor(sprite.Region.X), Y = (int)Math.Floor(sprite.Region.Y) }; region.Width = (int)Math.Ceiling(sprite.Region.Right) - region.X; region.Height = (int)Math.Ceiling(sprite.Region.Bottom) - region.Y; var alphaLevel = texTool.GetAlphaLevels(texImage, region, null, commandContext.Logger); // ignore transparent color key here because the input image has already been processed sprite.IsTransparent = alphaLevel != AlphaLevels.NoAlpha; } // free all the allocated images foreach (var tuple in urlToTexImage.Values) { tuple.Item1.Dispose(); assetManager.Unload(tuple.Item2); } } } // save the imageData into the data base assetManager.Save(Url, imageGroupData); return(Task.FromResult(ResultStatus.Successful)); }
public override void VisitDictionaryKeyValue(object dictionaryObj, DictionaryDescriptor descriptor, object key, ITypeDescriptor keyDescriptor, object value, ITypeDescriptor valueDescriptor) { base.VisitDictionaryKeyValue(dictionaryObj, descriptor, key, keyDescriptor, value, valueDescriptor); var assetReference = value as AssetReference; var attachedReference = AttachedReferenceManager.GetAttachedReference(value); if (assetReference != null) { AddLink(assetReference, (guid, location) => { var newValue = AssetReference.New(guid ?? assetReference.Id, location); descriptor.SetValue(dictionaryObj, key, newValue); return(newValue); }); } else if (attachedReference != null) { AddLink(attachedReference, (guid, location) => { object newValue = guid.HasValue && guid.Value != AssetId.Empty ? AttachedReferenceManager.CreateProxyObject(descriptor.ValueType, guid.Value, location) : null; descriptor.SetValue(dictionaryObj, key, newValue); return(newValue); }); } else if (value is UFile) { AddLink(value, (guid, location) => { var newValue = new UFile(location); descriptor.SetValue(dictionaryObj, key, newValue); return(newValue); }); } else if (value is UDirectory) { AddLink(value, (guid, location) => { var newValue = new UDirectory(location); descriptor.SetValue(dictionaryObj, key, newValue); return(newValue); }); } }
public override void VisitObjectMember(object container, ObjectDescriptor containerDescriptor, IMemberDescriptor member, object value) { base.VisitObjectMember(container, containerDescriptor, member, value); var assetReference = value as AssetReference; var attachedReference = AttachedReferenceManager.GetAttachedReference(value); if (assetReference != null) { AddLink(assetReference, (guid, location) => { var newValue = AssetReference.New(guid ?? assetReference.Id, location); member.Set(container, newValue); return(newValue); }); } else if (attachedReference != null) { AddLink(attachedReference, (guid, location) => { object newValue = guid.HasValue && guid.Value != AssetId.Empty ? AttachedReferenceManager.CreateProxyObject(member.Type, guid.Value, location) : null; member.Set(container, newValue); return(newValue); }); } else if (value is UFile) { AddLink(value, (guid, location) => { var newValue = new UFile(location); member.Set(container, newValue); return(newValue); }); } else if (value is UDirectory) { AddLink(value, (guid, location) => { var newValue = new UDirectory(location); member.Set(container, newValue); return(newValue); }); } }
public void TestMaterial() { var compiler = new EffectCompiler { UseFileSystem = true }; var currentPath = Core.PlatformFolders.ApplicationBinaryDirectory; compiler.SourceDirectories.Add(Path.Combine(currentPath, @"..\..\sources\engine\SiliconStudio.Xenko.Graphics\Shaders")); compiler.SourceDirectories.Add(Path.Combine(currentPath, @"..\..\sources\engine\SiliconStudio.Xenko.Engine\Rendering\Shaders")); compiler.SourceDirectories.Add(Path.Combine(currentPath, @"..\..\sources\engine\SiliconStudio.Xenko.Engine\Rendering\Core")); compiler.SourceDirectories.Add(Path.Combine(currentPath, @"..\..\sources\engine\SiliconStudio.Xenko.Engine\Rendering\Lights")); compiler.SourceDirectories.Add(Path.Combine(currentPath, @"..\..\sources\engine\SiliconStudio.Xenko.Engine\Rendering\Shadows")); compiler.SourceDirectories.Add(Path.Combine(currentPath, @"..\..\sources\engine\SiliconStudio.Xenko.Engine\Rendering\Materials\Shaders")); compiler.SourceDirectories.Add(Path.Combine(currentPath, @"..\..\sources\engine\SiliconStudio.Xenko.Engine\Rendering\Materials\ComputeColors\Shaders")); compiler.SourceDirectories.Add(Path.Combine(currentPath, @"..\..\sources\engine\SiliconStudio.Xenko.Engine\Rendering\Skinning")); compiler.SourceDirectories.Add(Path.Combine(currentPath, @"..\..\sources\engine\SiliconStudio.Xenko.Engine\Rendering\Shading")); compiler.SourceDirectories.Add(Path.Combine(currentPath, @"..\..\sources\engine\SiliconStudio.Xenko.Engine\Rendering\Transformation")); compiler.SourceDirectories.Add(Path.Combine(currentPath, @"..\..\sources\engine\SiliconStudio.Xenko.Engine\Rendering\Utils")); var compilerParameters = new CompilerParameters { EffectParameters = { Platform = GraphicsPlatform.OpenGL } }; var layers = new MaterialBlendLayers(); layers.Add(new MaterialBlendLayer { BlendMap = new ComputeFloat(0.5f), Material = AttachedReferenceManager.CreateProxyObject <Material>(AssetId.Empty, "fake") }); var materialAsset = new MaterialAsset { Attributes = new MaterialAttributes() { Diffuse = new MaterialDiffuseMapFeature() { DiffuseMap = new ComputeColor(Color4.White) }, DiffuseModel = new MaterialDiffuseLambertModelFeature() }, Layers = layers }; var fakeAsset = new MaterialAsset { Attributes = new MaterialAttributes() { Diffuse = new MaterialDiffuseMapFeature() { DiffuseMap = new ComputeColor(Color.Blue) }, } }; var context = new MaterialGeneratorContext { FindAsset = reference => fakeAsset }; var result = MaterialGenerator.Generate(new MaterialDescriptor { Attributes = materialAsset.Attributes, Layers = materialAsset.Layers }, context, "TestMaterial"); compilerParameters.Set(MaterialKeys.PixelStageSurfaceShaders, result.Material.Parameters.Get(MaterialKeys.PixelStageSurfaceShaders)); var directionalLightGroup = new ShaderClassSource("LightDirectionalGroup", 1); compilerParameters.Set(LightingKeys.DirectLightGroups, new ShaderSourceCollection { directionalLightGroup }); //compilerParameters.Set(LightingKeys.CastShadows, false); //compilerParameters.Set(MaterialParameters.HasSkinningPosition, true); //compilerParameters.Set(MaterialParameters.HasSkinningNormal, true); compilerParameters.Set(MaterialKeys.HasNormalMap, true); var results = compiler.Compile(new ShaderMixinGeneratorSource("XenkoEffectBase"), compilerParameters); Assert.IsFalse(results.HasErrors); }
static Stride.Rendering.Material GetMaterial(MaterialAsset materialAsset, string name) { return(AttachedReferenceManager.CreateProxyObject <Stride.Rendering.Material>(materialAsset.Id, name)); }
/// <summary> /// Creates default scene, with a ground plane, sphere, directional light and camera. /// If graphicsProfile is 10+, add cubemap light, otherwise ambient light. /// Also properly setup graphics pipeline depending on if HDR is set or not /// </summary> /// <param name="parameters">The parameters.</param> /// <param name="package">The package in which to create these assets.</param> private void CreateAndSetNewScene(SessionTemplateGeneratorParameters parameters, Package package, ProjectReference projectGameReference, string projectGameName) { var logger = parameters.Logger; var graphicsProfile = parameters.GetTag(GraphicsProfileKey); var isHDR = parameters.GetTag(IsHDRKey); if (graphicsProfile < GraphicsProfile.Level_10_0) { isHDR = false; } // Create the material for the sphere var sphereMaterial = new MaterialAsset { Attributes = { Diffuse = new MaterialDiffuseMapFeature(new ComputeColor(Color.FromBgra(0xFF8C8C8C))), DiffuseModel = new MaterialDiffuseLambertModelFeature(), } }; if (isHDR) { // Create HDR part of material sphereMaterial.Attributes.Specular = new MaterialMetalnessMapFeature(new ComputeFloat(1.0f)); sphereMaterial.Attributes.SpecularModel = new MaterialSpecularMicrofacetModelFeature(); sphereMaterial.Attributes.MicroSurface = new MaterialGlossinessMapFeature(new ComputeFloat(0.65f)); } var sphereMaterialAssetItem = new AssetItem("Sphere Material", sphereMaterial); package.Assets.Add(sphereMaterialAssetItem); sphereMaterialAssetItem.IsDirty = true; // Create the sphere model var sphereModel = new ProceduralModelAsset { Type = new SphereProceduralModel { MaterialInstance = { Material = AttachedReferenceManager.CreateProxyObject <Material>(sphereMaterialAssetItem.Id, sphereMaterialAssetItem.Location) }, Tessellation = 30, }, }; var sphereModelAssetItem = new AssetItem("Sphere", sphereModel); package.Assets.Add(sphereModelAssetItem); sphereModelAssetItem.IsDirty = true; // Create sphere entity var sphereEntity = new Entity("Sphere") { new ModelComponent(AttachedReferenceManager.CreateProxyObject <Model>(sphereModelAssetItem.Id, sphereModelAssetItem.Location)) }; sphereEntity.Transform.Position = new Vector3(0.0f, 0.5f, 0.0f); // Create the material for the ground var groundMaterial = new MaterialAsset { Attributes = { Diffuse = new MaterialDiffuseMapFeature(new ComputeColor(Color.FromBgra(0xFF242424))), DiffuseModel = new MaterialDiffuseLambertModelFeature(), } }; if (isHDR) { // Create HDR part of material groundMaterial.Attributes.Specular = new MaterialMetalnessMapFeature(new ComputeFloat(0.0f)); groundMaterial.Attributes.SpecularModel = new MaterialSpecularMicrofacetModelFeature(); groundMaterial.Attributes.MicroSurface = new MaterialGlossinessMapFeature(new ComputeFloat(0.1f)); } var groundMaterialAssetItem = new AssetItem("Ground Material", groundMaterial); package.Assets.Add(groundMaterialAssetItem); groundMaterialAssetItem.IsDirty = true; // Create the ground model var groundModel = new ProceduralModelAsset { Type = new PlaneProceduralModel { Size = new Vector2(10.0f, 10.0f), MaterialInstance = { Material = AttachedReferenceManager.CreateProxyObject <Material>(groundMaterialAssetItem.Id, groundMaterialAssetItem.Location) }, }, }; var groundModelAssetItem = new AssetItem("Ground", groundModel); package.Assets.Add(groundModelAssetItem); groundModelAssetItem.IsDirty = true; // Create the ground entity var groundEntity = new Entity("Ground") { new ModelComponent(AttachedReferenceManager.CreateProxyObject <Model>(groundModelAssetItem.Id, groundModelAssetItem.Location)) }; // Copy file in Resources var skyboxFilename = (UFile)(isHDR ? "skybox_texture_hdr.dds" : "skybox_texture_ldr.dds"); try { var resources = UPath.Combine(parameters.OutputDirectory, (UDirectory)"Resources"); Directory.CreateDirectory(resources.ToWindowsPath()); // TODO: Hardcoded due to the fact that part of the template is in another folder in dev build // We might want to extend TemplateFolder to support those cases var dataDirectory = ProjectTemplateGeneratorHelper.GetTemplateDataDirectory(parameters.Description); var skyboxFullPath = UPath.Combine(dataDirectory, skyboxFilename).ToWindowsPath(); File.Copy(skyboxFullPath, UPath.Combine(resources, skyboxFilename).ToWindowsPath(), true); } catch (Exception ex) { logger.Error("Unexpected exception while copying cubemap", ex); } // Create the texture asset var skyboxTextureAsset = new TextureAsset { Source = Path.Combine(@"..\..\Resources", skyboxFilename), IsCompressed = isHDR, Type = new ColorTextureType { UseSRgbSampling = false } }; var skyboxTextureAssetItem = new AssetItem("Skybox texture", skyboxTextureAsset); package.Assets.Add(skyboxTextureAssetItem); skyboxTextureAssetItem.IsDirty = true; // Create the skybox asset var skyboxAsset = new SkyboxAsset { CubeMap = AttachedReferenceManager.CreateProxyObject <Texture>(skyboxTextureAssetItem.Id, skyboxTextureAssetItem.Location) }; var skyboxAssetItem = new AssetItem("Skybox", skyboxAsset); package.Assets.Add(skyboxAssetItem); skyboxAssetItem.IsDirty = true; // Create the scene var defaultSceneAsset = isHDR ? SceneHDRFactory.Create() : SceneLDRFactory.Create(); defaultSceneAsset.Hierarchy.Parts.Add(new EntityDesign(groundEntity)); defaultSceneAsset.Hierarchy.RootParts.Add(groundEntity); defaultSceneAsset.Hierarchy.Parts.Add(new EntityDesign(sphereEntity)); defaultSceneAsset.Hierarchy.RootParts.Add(sphereEntity); var sceneAssetItem = new AssetItem(GameSettingsAsset.DefaultSceneLocation, defaultSceneAsset); package.Assets.Add(sceneAssetItem); sceneAssetItem.IsDirty = true; // Sets the scene created as default in the shared profile var gameSettingsAsset = package.Assets.Find(GameSettingsAsset.GameSettingsLocation); if (gameSettingsAsset != null) { ((GameSettingsAsset)gameSettingsAsset.Asset).DefaultScene = AttachedReferenceManager.CreateProxyObject <Scene>(sceneAssetItem.Id, sceneAssetItem.Location); gameSettingsAsset.IsDirty = true; } var skyboxEntity = defaultSceneAsset.Hierarchy.Parts.Select(x => x.Value.Entity).Single(x => x.Name == SceneBaseFactory.SkyboxEntityName); skyboxEntity.Get <BackgroundComponent>().Texture = skyboxAsset.CubeMap; if (isHDR) { skyboxEntity.Get <LightComponent>().Type = new LightSkybox { Skybox = AttachedReferenceManager.CreateProxyObject <Skybox>(skyboxAssetItem.Id, skyboxAssetItem.Location) }; } var cameraEntity = defaultSceneAsset.Hierarchy.Parts.Select(x => x.Value.Entity).Single(x => x.Name == SceneBaseFactory.CameraEntityName); var graphicsCompositor = package.Assets.Select(x => x.Asset).OfType <GraphicsCompositorAsset>().Single(); cameraEntity.Components.Get <CameraComponent>().Slot = graphicsCompositor.Cameras.Single().ToSlotId(); // Let's add camera script CreateCameraScript(parameters, package, projectGameReference, projectGameName, cameraEntity, sceneAssetItem); }
protected override bool Generate(SessionTemplateGeneratorParameters parameters) { if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } // Structure of files to generate: // $Name$.xkpkg // $Name$.targets // Assets\ // $Name$.Game\ // $Name$.Windows\ // $Name$.Android\ // $Name$.iOS\ var logger = parameters.Logger; var platforms = parameters.GetTag(PlatformsKey); var name = parameters.Name; var outputDirectory = parameters.OutputDirectory; var orientation = parameters.GetTag(OrientationKey); // Generate the package var package = NewPackageTemplateGenerator.GeneratePackage(parameters); // Generate projects for this package var session = parameters.Session; var sharedProfile = package.Profiles.FindSharedProfile(); // Setup the assets folder Directory.CreateDirectory(UPath.Combine(outputDirectory, (UDirectory)"Assets/Shared")); //write gitignore WriteGitIgnore(parameters); var previousCurrent = session.CurrentPackage; session.CurrentPackage = package; var projectGameName = Utilities.BuildValidNamespaceName(name) + ".Game"; var stepIndex = 0; var stepCount = platforms.Count + 1; // Log progress ProjectTemplateGeneratorHelper.Progress(logger, $"Generating {projectGameName}...", stepIndex++, stepCount); // Generate the Game library var projectGameReference = ProjectTemplateGeneratorHelper.GenerateTemplate(parameters, platforms, package, "ProjectLibrary.Game/ProjectLibrary.Game.ttproj", projectGameName, PlatformType.Shared, null, null, ProjectType.Library, orientation); projectGameReference.Type = ProjectType.Library; sharedProfile.ProjectReferences.Add(projectGameReference); // Add Effects as an asset folder in order to load xksl sharedProfile.AssetFolders.Add(new AssetFolder(projectGameName + "/Effects")); // Generate executable projects for each platform ProjectTemplateGeneratorHelper.UpdatePackagePlatforms(parameters, platforms, orientation, projectGameReference.Id, name, package, false); // Add asset packages CopyAssetPacks(parameters); // Load assets from HDD package.LoadTemporaryAssets(logger); // Validate assets package.ValidateAssets(true, false, logger); // Setup GraphicsCompositor using DefaultGraphicsCompositor var graphicsProfile = parameters.GetTag(GraphicsProfileKey); var defaultCompositorUrl = graphicsProfile >= GraphicsProfile.Level_10_0 ? XenkoPackageUpgrader.DefaultGraphicsCompositorLevel10Url : XenkoPackageUpgrader.DefaultGraphicsCompositorLevel9Url; var defaultCompositor = session.FindAsset(defaultCompositorUrl); var graphicsCompositor = new AssetItem("GraphicsCompositor", defaultCompositor.CreateDerivedAsset()); package.Assets.Add(graphicsCompositor); graphicsCompositor.IsDirty = true; // Setup GameSettingsAsset var gameSettingsAsset = GameSettingsFactory.Create(); gameSettingsAsset.GetOrCreate <EditorSettings>().RenderingMode = parameters.GetTag(IsHDRKey) ? RenderingMode.HDR : RenderingMode.LDR; gameSettingsAsset.GraphicsCompositor = AttachedReferenceManager.CreateProxyObject <GraphicsCompositor>(graphicsCompositor.ToReference()); var renderingSettings = gameSettingsAsset.GetOrCreate <RenderingSettings>(); renderingSettings.DefaultGraphicsProfile = parameters.GetTag(GraphicsProfileKey); renderingSettings.DisplayOrientation = (RequiredDisplayOrientation)orientation; var gameSettingsAssetItem = new AssetItem(GameSettingsAsset.GameSettingsLocation, gameSettingsAsset); package.Assets.Add(gameSettingsAssetItem); gameSettingsAssetItem.IsDirty = true; // Add assets to the package AddAssets(parameters, package, projectGameReference, projectGameName); // Log done ProjectTemplateGeneratorHelper.Progress(logger, "Done", stepCount, stepCount); session.CurrentPackage = previousCurrent; return(true); }
private object ExportModel(ICommandContext commandContext, ContentManager contentManager) { // Read from model file var modelSkeleton = LoadSkeleton(commandContext, contentManager); // we get model skeleton to compare it to real skeleton we need to map to AdjustSkeleton(modelSkeleton); var model = LoadModel(commandContext, contentManager); // Apply materials foreach (var modelMaterial in Materials) { if (modelMaterial.MaterialInstance?.Material == null) { commandContext.Logger.Warning($"The material [{modelMaterial.Name}] is null in the list of materials."); } model.Materials.Add(modelMaterial.MaterialInstance); } model.BoundingBox = BoundingBox.Empty; foreach (var mesh in model.Meshes) { if (TessellationAEN) { // TODO: Generate AEN model view commandContext.Logger.Error("TessellationAEN is not supported in {0}", ContextAsString); } } SkeletonMapping skeletonMapping; Skeleton skeleton; if (SkeletonUrl != null) { // Load skeleton and process it skeleton = contentManager.Load <Skeleton>(SkeletonUrl); // Assign skeleton to model model.Skeleton = AttachedReferenceManager.CreateProxyObject <Skeleton>(Guid.Empty, SkeletonUrl); } else { skeleton = null; } skeletonMapping = new SkeletonMapping(skeleton, modelSkeleton); // Refresh skeleton updater with model skeleton var hierarchyUpdater = new SkeletonUpdater(modelSkeleton); hierarchyUpdater.UpdateMatrices(); // Move meshes in the new nodes foreach (var mesh in model.Meshes) { // Apply scale import on meshes if (!MathUtil.NearEqual(ScaleImport, 1.0f)) { var transformationMatrix = Matrix.Scaling(ScaleImport); mesh.Draw.VertexBuffers[0].TransformBuffer(ref transformationMatrix); } var skinning = mesh.Skinning; if (skinning != null) { // Update node mapping // Note: we only remap skinning matrices, but we could directly remap skinning bones instead for (int i = 0; i < skinning.Bones.Length; ++i) { var linkNodeIndex = skinning.Bones[i].NodeIndex; var newLinkNodeIndex = skeletonMapping.SourceToSource[linkNodeIndex]; var nodeIndex = mesh.NodeIndex; var newNodeIndex = skeletonMapping.SourceToSource[mesh.NodeIndex]; skinning.Bones[i].NodeIndex = skeletonMapping.SourceToTarget[linkNodeIndex]; // Adjust scale import if (!MathUtil.NearEqual(ScaleImport, 1.0f)) { skinning.Bones[i].LinkToMeshMatrix.TranslationVector = skinning.Bones[i].LinkToMeshMatrix.TranslationVector * ScaleImport; } // If it was remapped, we also need to update matrix if (nodeIndex != newNodeIndex) { // Update mesh part var transformMatrix = CombineMatricesFromNodeIndices(hierarchyUpdater.NodeTransformations, newNodeIndex, nodeIndex); transformMatrix.Invert(); skinning.Bones[i].LinkToMeshMatrix = Matrix.Multiply(transformMatrix, skinning.Bones[i].LinkToMeshMatrix); } if (newLinkNodeIndex != linkNodeIndex) { // Update link part var transformLinkMatrix = CombineMatricesFromNodeIndices(hierarchyUpdater.NodeTransformations, newLinkNodeIndex, linkNodeIndex); skinning.Bones[i].LinkToMeshMatrix = Matrix.Multiply(skinning.Bones[i].LinkToMeshMatrix, transformLinkMatrix); } } } // Check if there was a remap using model skeleton if (skeletonMapping.SourceToSource[mesh.NodeIndex] != mesh.NodeIndex) { // Transform vertices var transformationMatrix = CombineMatricesFromNodeIndices(hierarchyUpdater.NodeTransformations, skeletonMapping.SourceToSource[mesh.NodeIndex], mesh.NodeIndex); mesh.Draw.VertexBuffers[0].TransformBuffer(ref transformationMatrix); // Check if geometry is inverted, to know if we need to reverse winding order // TODO: What to do if there is no index buffer? We should create one... (not happening yet) if (mesh.Draw.IndexBuffer == null) { throw new InvalidOperationException(); } Matrix rotation; Vector3 scale, translation; if (transformationMatrix.Decompose(out scale, out rotation, out translation) && scale.X * scale.Y * scale.Z < 0) { mesh.Draw.ReverseWindingOrder(); } } // Update new node index using real asset skeleton mesh.NodeIndex = skeletonMapping.SourceToTarget[mesh.NodeIndex]; } // Merge meshes with same parent nodes, material and skinning var meshesByNodes = model.Meshes.GroupBy(x => x.NodeIndex).ToList(); foreach (var meshesByNode in meshesByNodes) { // This logic to detect similar material is kept from old code; this should be reviewed/improved at some point foreach (var meshesPerDrawCall in meshesByNode.GroupBy(x => x, new AnonymousEqualityComparer <Mesh>((x, y) => x.MaterialIndex == y.MaterialIndex && // Same material ArrayExtensions.ArraysEqual(x.Skinning?.Bones, y.Skinning?.Bones) && // Same bones CompareParameters(model, x, y) && // Same parameters CompareShadowOptions(model, x, y), // Same shadow parameters x => 0)).ToList()) { if (meshesPerDrawCall.Count() == 1) { // Nothing to group, skip to next entry continue; } // Remove old meshes foreach (var mesh in meshesPerDrawCall) { model.Meshes.Remove(mesh); } // Add new combined mesh(es) var baseMesh = meshesPerDrawCall.First(); var newMeshList = meshesPerDrawCall.Select(x => x.Draw).ToList().GroupDrawData(Allow32BitIndex); foreach (var generatedMesh in newMeshList) { model.Meshes.Add(new Mesh(generatedMesh, baseMesh.Parameters) { MaterialIndex = baseMesh.MaterialIndex, Name = baseMesh.Name, Draw = generatedMesh, NodeIndex = baseMesh.NodeIndex, Skinning = baseMesh.Skinning, }); } } } // split the meshes if necessary model.Meshes = SplitExtensions.SplitMeshes(model.Meshes, Allow32BitIndex); // Refresh skeleton updater with asset skeleton hierarchyUpdater = new SkeletonUpdater(skeleton); hierarchyUpdater.UpdateMatrices(); // bounding boxes var modelBoundingBox = model.BoundingBox; var modelBoundingSphere = model.BoundingSphere; foreach (var mesh in model.Meshes) { var vertexBuffers = mesh.Draw.VertexBuffers; if (vertexBuffers.Length > 0) { // Compute local mesh bounding box (no node transformation) Matrix matrix = Matrix.Identity; mesh.BoundingBox = vertexBuffers[0].ComputeBounds(ref matrix, out mesh.BoundingSphere); // Compute model bounding box (includes node transformation) hierarchyUpdater.GetWorldMatrix(mesh.NodeIndex, out matrix); BoundingSphere meshBoundingSphere; var meshBoundingBox = vertexBuffers[0].ComputeBounds(ref matrix, out meshBoundingSphere); BoundingBox.Merge(ref modelBoundingBox, ref meshBoundingBox, out modelBoundingBox); BoundingSphere.Merge(ref modelBoundingSphere, ref meshBoundingSphere, out modelBoundingSphere); } // TODO: temporary Always try to compact mesh.Draw.CompactIndexBuffer(); } model.BoundingBox = modelBoundingBox; model.BoundingSphere = modelBoundingSphere; // merges all the Draw VB and IB together to produce one final VB and IB by entity. var sizeVertexBuffer = model.Meshes.SelectMany(x => x.Draw.VertexBuffers).Select(x => x.Buffer.GetSerializationData().Content.Length).Sum(); var sizeIndexBuffer = 0; foreach (var x in model.Meshes) { // Let's be aligned (if there was 16bit indices before, we might be off) if (x.Draw.IndexBuffer.Is32Bit && sizeIndexBuffer % 4 != 0) { sizeIndexBuffer += 2; } sizeIndexBuffer += x.Draw.IndexBuffer.Buffer.GetSerializationData().Content.Length; } var vertexBuffer = new BufferData(BufferFlags.VertexBuffer, new byte[sizeVertexBuffer]); var indexBuffer = new BufferData(BufferFlags.IndexBuffer, new byte[sizeIndexBuffer]); // Note: reusing same instance, to avoid having many VB with same hash but different URL var vertexBufferSerializable = vertexBuffer.ToSerializableVersion(); var indexBufferSerializable = indexBuffer.ToSerializableVersion(); var vertexBufferNextIndex = 0; var indexBufferNextIndex = 0; foreach (var drawMesh in model.Meshes.Select(x => x.Draw)) { // the index buffer var oldIndexBuffer = drawMesh.IndexBuffer.Buffer.GetSerializationData().Content; // Let's be aligned (if there was 16bit indices before, we might be off) if (drawMesh.IndexBuffer.Is32Bit && indexBufferNextIndex % 4 != 0) { indexBufferNextIndex += 2; } Array.Copy(oldIndexBuffer, 0, indexBuffer.Content, indexBufferNextIndex, oldIndexBuffer.Length); drawMesh.IndexBuffer = new IndexBufferBinding(indexBufferSerializable, drawMesh.IndexBuffer.Is32Bit, drawMesh.IndexBuffer.Count, indexBufferNextIndex); indexBufferNextIndex += oldIndexBuffer.Length; // the vertex buffers for (int index = 0; index < drawMesh.VertexBuffers.Length; index++) { var vertexBufferBinding = drawMesh.VertexBuffers[index]; var oldVertexBuffer = vertexBufferBinding.Buffer.GetSerializationData().Content; Array.Copy(oldVertexBuffer, 0, vertexBuffer.Content, vertexBufferNextIndex, oldVertexBuffer.Length); drawMesh.VertexBuffers[index] = new VertexBufferBinding(vertexBufferSerializable, vertexBufferBinding.Declaration, vertexBufferBinding.Count, vertexBufferBinding.Stride, vertexBufferNextIndex); vertexBufferNextIndex += oldVertexBuffer.Length; } } // Convert to Entity return(model); }
protected override bool Generate(SessionTemplateGeneratorParameters parameters) { if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } // Structure of files to generate: // $Name$.sdpkg // $Name$.targets // Assets\ // $Name$.Game\ // $Name$.Windows\ // $Name$.Android\ // $Name$.iOS\ var logger = parameters.Logger; var platforms = parameters.GetTag(PlatformsKey); var name = parameters.Name; var outputDirectory = parameters.OutputDirectory; var orientation = parameters.GetTag(OrientationKey); // Generate the package //var package = NewPackageTemplateGenerator.GeneratePackage(parameters); // Generate projects for this package var session = parameters.Session; var projectGameName = Utilities.BuildValidNamespaceName(name); var stepIndex = 0; var stepCount = platforms.Count + 1; // Log progress ProjectTemplateGeneratorHelper.Progress(logger, $"Generating {projectGameName}...", stepIndex++, stepCount); // Generate the Game library var project = ProjectTemplateGeneratorHelper.GenerateTemplate(parameters, platforms, "ProjectLibrary.Game/ProjectLibrary.Game.ttproj", projectGameName, PlatformType.Shared, null, ProjectType.Library, orientation); var package = project.Package; //write gitignore WriteGitIgnore(parameters); // Setup the assets folder //Directory.CreateDirectory(UPath.Combine(package.RootDirectory, (UDirectory)"Assets/Shared")); session.Projects.Add(project); // Load missing references session.LoadMissingDependencies(parameters.Logger); // Load dependency assets (needed for camera script template) session.LoadMissingAssets(parameters.Logger, project.FlattenedDependencies.Select(x => x.Package).NotNull()); // Add Effects as an asset folder in order to load sdsl package.AssetFolders.Add(new AssetFolder("Effects")); var packageParameters = new PackageTemplateGeneratorParameters { Name = package.Meta.Name, OutputDirectory = package.FullPath.GetFullDirectory(), Description = parameters.Description, Package = package, Logger = parameters.Logger, Namespace = parameters.Namespace }; // Generate executable projects for each platform var platformProjects = ProjectTemplateGeneratorHelper.UpdatePackagePlatforms(packageParameters, platforms, orientation, false).ToList(); // Add asset packages CopyAssetPacks(parameters, package); // Create camera script var cameraScriptTemplate = TemplateManager.FindTemplates(package.Session).OfType <TemplateAssetDescription>().FirstOrDefault(x => x.DefaultOutputName == CameraScriptDefaultOutputName); if (cameraScriptTemplate == null) { throw new InvalidOperationException($"Could not find template for script '{CameraScriptDefaultOutputName}'"); } var cameraScriptParameters = new AssetTemplateGeneratorParameters(string.Empty) { Name = cameraScriptTemplate.DefaultOutputName, Description = cameraScriptTemplate, Namespace = parameters.Namespace, Package = package, Logger = logger, Unattended = true, }; ScriptTemplateGenerator.SetClassName(cameraScriptParameters, cameraScriptTemplate.DefaultOutputName); if (!ScriptTemplateGenerator.Default.PrepareForRun(cameraScriptParameters).Result || !ScriptTemplateGenerator.Default.Run(cameraScriptParameters)) { throw new InvalidOperationException($"Could not create script '{CameraScriptDefaultOutputName}'"); } // Force save after having created the script // Note: We do that AFTER GameSettings is dirty, otherwise it would ask for an assembly reload (game settings saved might mean new graphics API) SaveSession(parameters); // Load missing references session.LoadMissingReferences(parameters.Logger); // Setup GraphicsCompositor using DefaultGraphicsCompositor var graphicsProfile = parameters.GetTag(GraphicsProfileKey); var defaultCompositorUrl = graphicsProfile >= GraphicsProfile.Level_10_0 ? StridePackageUpgrader.DefaultGraphicsCompositorLevel10Url : StridePackageUpgrader.DefaultGraphicsCompositorLevel9Url; var defaultCompositor = session.FindAsset(defaultCompositorUrl); var graphicsCompositor = new AssetItem("GraphicsCompositor", defaultCompositor.CreateDerivedAsset()); package.Assets.Add(graphicsCompositor); graphicsCompositor.IsDirty = true; // Setup GameSettingsAsset var gameSettingsAsset = GameSettingsFactory.Create(); gameSettingsAsset.GetOrCreate <EditorSettings>().RenderingMode = parameters.GetTag(IsHDRKey) ? RenderingMode.HDR : RenderingMode.LDR; gameSettingsAsset.GraphicsCompositor = AttachedReferenceManager.CreateProxyObject <GraphicsCompositor>(graphicsCompositor.ToReference()); var renderingSettings = gameSettingsAsset.GetOrCreate <RenderingSettings>(); renderingSettings.DefaultGraphicsProfile = parameters.GetTag(GraphicsProfileKey); renderingSettings.DisplayOrientation = (RequiredDisplayOrientation)orientation; var gameSettingsAssetItem = new AssetItem(GameSettingsAsset.GameSettingsLocation, gameSettingsAsset); package.Assets.Add(gameSettingsAssetItem); gameSettingsAssetItem.IsDirty = true; // Add assets to the package AddAssets(parameters, package, projectGameName); // Log done ProjectTemplateGeneratorHelper.Progress(logger, "Done", stepCount, stepCount); // Set current project session.CurrentProject = platformProjects.FirstOrDefault(x => x.Platform == PlatformType.Windows) ?? project; return(true); }
static Texture GetTexture(TextureAsset asset) { return(AttachedReferenceManager.CreateProxyObject <Texture>(asset.Id, asset.Source.FullPath)); }
/// <summary> /// Checks if a default scene exists for this game package. /// </summary> /// <param name="log">The log to output the result of the validation.</param> public override void Run(ILogger log) { if (log == null) { throw new ArgumentNullException(nameof(log)); } foreach (var package in Session.Packages) { // Make sure package has its assets loaded if (package.State < PackageState.AssetsReady) { continue; } var hasGameExecutable = package.Profiles.SelectMany(profile => profile.ProjectReferences).Any(projectRef => projectRef.Type == ProjectType.Executable); if (!hasGameExecutable) { continue; } // Find game settings var gameSettingsAssetItem = package.Assets.Find(GameSettingsAsset.GameSettingsLocation); AssetItem defaultScene = null; // If game settings is found, try to find default scene inside var defaultSceneRuntime = ((GameSettingsAsset)gameSettingsAssetItem?.Asset)?.DefaultScene; var defaultSceneReference = AttachedReferenceManager.GetAttachedReference(defaultSceneRuntime); if (defaultSceneReference != null) { // Find it either by Url or Id defaultScene = package.Assets.Find(defaultSceneReference.Id) ?? package.Assets.Find(defaultSceneReference.Url); // Check it is actually a scene asset if (defaultScene != null && !(defaultScene.Asset is SceneAsset)) { defaultScene = null; } } // Find or create default scene if (defaultScene == null) { defaultScene = package.Assets.Find(GameSettingsAsset.DefaultSceneLocation); if (defaultScene != null && !(defaultScene.Asset is SceneAsset)) { defaultScene = null; } } // Otherwise, try to find any scene if (defaultScene == null) { defaultScene = package.Assets.FirstOrDefault(x => x.Asset is SceneAsset); } // Nothing found, let's create an empty one if (defaultScene == null) { log.Error(package, null, AssetMessageCode.DefaultSceneNotFound, null); var defaultSceneName = NamingHelper.ComputeNewName(GameSettingsAsset.DefaultSceneLocation, package.Assets, a => a.Location); var defaultSceneAsset = DefaultAssetFactory <SceneAsset> .Create(); defaultScene = new AssetItem(defaultSceneName, defaultSceneAsset); package.Assets.Add(defaultScene); defaultScene.IsDirty = true; } // Create game settings if not done yet if (gameSettingsAssetItem == null) { log.Error(package, null, AssetMessageCode.AssetForPackageNotFound, GameSettingsAsset.GameSettingsLocation, package.FullPath.GetFileName()); var gameSettingsAsset = GameSettingsFactory.Create(); gameSettingsAsset.DefaultScene = AttachedReferenceManager.CreateProxyObject <Scene>(defaultScene.Id, defaultScene.Location); gameSettingsAssetItem = new AssetItem(GameSettingsAsset.GameSettingsLocation, gameSettingsAsset); package.Assets.Add(gameSettingsAssetItem); gameSettingsAssetItem.IsDirty = true; } } }
public override void VisitArrayItem(Array array, ArrayDescriptor descriptor, int index, object item, ITypeDescriptor itemDescriptor) { base.VisitArrayItem(array, descriptor, index, item, itemDescriptor); var assetReference = item as AssetReference; var attachedReference = AttachedReferenceManager.GetAttachedReference(item); if (assetReference != null) { AddLink(item, (guid, location) => { var newValue = AssetReference.New(guid ?? assetReference.Id, location); array.SetValue(newValue, index); return(newValue); }); } else if (attachedReference != null) { AddLink(attachedReference, (guid, location) => { object newValue = guid.HasValue && guid.Value != AssetId.Empty ? AttachedReferenceManager.CreateProxyObject(descriptor.ElementType, guid.Value, location) : null; array.SetValue(newValue, index); return(newValue); }); } else if (item is UFile) { AddLink(item, (guid, location) => { var newValue = new UFile(location); array.SetValue(newValue, index); return(newValue); }); } else if (item is UDirectory) { AddLink(item, (guid, location) => { var newValue = new UFile(location); array.SetValue(newValue, index); return(newValue); }); } }
private object ExportModel(ICommandContext commandContext, ContentManager contentManager) { // Read from model file var modelSkeleton = LoadSkeleton(commandContext, contentManager); // we get model skeleton to compare it to real skeleton we need to map to AdjustSkeleton(modelSkeleton); var model = LoadModel(commandContext, contentManager); if (!CheckInputSlots(commandContext, model)) { return(null); } // Apply materials foreach (var modelMaterial in Materials) { if (modelMaterial.MaterialInstance?.Material == null) { commandContext.Logger.Verbose($"The material [{modelMaterial.Name}] is null in the list of materials."); } model.Materials.Add(modelMaterial.MaterialInstance); } model.BoundingBox = BoundingBox.Empty; Skeleton skeleton; if (SkeletonUrl != null || !MergeMeshes) { if (SkeletonUrl != null) { // Load the skeleton skeleton = contentManager.Load <Skeleton>(SkeletonUrl); } else { skeleton = modelSkeleton; SkeletonUrl = Location + "_Skeleton_" + Guid.NewGuid(); contentManager.Save(SkeletonUrl, skeleton); } // Assign skeleton to model model.Skeleton = AttachedReferenceManager.CreateProxyObject <Skeleton>(AssetId.Empty, SkeletonUrl); } else { skeleton = null; } var skeletonMapping = new SkeletonMapping(skeleton, modelSkeleton); // Refresh skeleton updater with model skeleton var hierarchyUpdater = new SkeletonUpdater(modelSkeleton); hierarchyUpdater.UpdateMatrices(); // Move meshes in the new nodes foreach (var mesh in model.Meshes) { // Apply scale import on meshes if (!MathUtil.NearEqual(ScaleImport, 1.0f)) { var transformationMatrix = Matrix.Scaling(ScaleImport); for (int vbIdx = 0; vbIdx < mesh.Draw.VertexBuffers.Length; vbIdx++) { mesh.Draw.VertexBuffers[vbIdx].TransformBuffer(ref transformationMatrix); } } var skinning = mesh.Skinning; if (skinning != null) { // Update node mapping // Note: we only remap skinning matrices, but we could directly remap skinning bones instead for (int i = 0; i < skinning.Bones.Length; ++i) { var linkNodeIndex = skinning.Bones[i].NodeIndex; var newLinkNodeIndex = skeletonMapping.SourceToSource[linkNodeIndex]; var nodeIndex = mesh.NodeIndex; var newNodeIndex = skeletonMapping.SourceToSource[mesh.NodeIndex]; skinning.Bones[i].NodeIndex = skeletonMapping.SourceToTarget[linkNodeIndex]; // Adjust scale import if (!MathUtil.NearEqual(ScaleImport, 1.0f)) { skinning.Bones[i].LinkToMeshMatrix.TranslationVector = skinning.Bones[i].LinkToMeshMatrix.TranslationVector * ScaleImport; } // If it was remapped, we also need to update matrix if (nodeIndex != newNodeIndex) { // Update mesh part var transformMatrix = CombineMatricesFromNodeIndices(hierarchyUpdater.NodeTransformations, newNodeIndex, nodeIndex); transformMatrix.Invert(); skinning.Bones[i].LinkToMeshMatrix = Matrix.Multiply(transformMatrix, skinning.Bones[i].LinkToMeshMatrix); } if (newLinkNodeIndex != linkNodeIndex) { // Update link part var transformLinkMatrix = CombineMatricesFromNodeIndices(hierarchyUpdater.NodeTransformations, newLinkNodeIndex, linkNodeIndex); skinning.Bones[i].LinkToMeshMatrix = Matrix.Multiply(skinning.Bones[i].LinkToMeshMatrix, transformLinkMatrix); } } } // Check if there was a remap using model skeleton if (skeletonMapping.SourceToSource[mesh.NodeIndex] != mesh.NodeIndex) { // Transform vertices var transformationMatrix = CombineMatricesFromNodeIndices(hierarchyUpdater.NodeTransformations, skeletonMapping.SourceToSource[mesh.NodeIndex], mesh.NodeIndex); for (int vbIdx = 0; vbIdx < mesh.Draw.VertexBuffers.Length; vbIdx++) { mesh.Draw.VertexBuffers[vbIdx].TransformBuffer(ref transformationMatrix); } // Check if geometry is inverted, to know if we need to reverse winding order // TODO: What to do if there is no index buffer? We should create one... (not happening yet) if (mesh.Draw.IndexBuffer == null) { throw new InvalidOperationException(); } Matrix rotation; Vector3 scale, translation; if (transformationMatrix.Decompose(out scale, out rotation, out translation) && scale.X * scale.Y * scale.Z < 0) { mesh.Draw.ReverseWindingOrder(); } } // Update new node index using real asset skeleton mesh.NodeIndex = skeletonMapping.SourceToTarget[mesh.NodeIndex]; } // Apply custom model modifiers if (ModelModifiers != null) { foreach (var modifier in ModelModifiers) { modifier.Apply(commandContext, model); } } // Merge meshes with same parent nodes, material and skinning var meshesByNodes = model.Meshes.GroupBy(x => x.NodeIndex).ToList(); foreach (var meshesByNode in meshesByNodes) { // This logic to detect similar material is kept from old code; this should be reviewed/improved at some point foreach (var meshesPerDrawCall in meshesByNode.GroupBy(x => x, new AnonymousEqualityComparer <Mesh>((x, y) => x.MaterialIndex == y.MaterialIndex && // Same material ArrayExtensions.ArraysEqual(x.Skinning?.Bones, y.Skinning?.Bones) && // Same bones CompareParameters(model, x, y) && // Same parameters CompareShadowOptions(model, x, y), // Same shadow parameters x => 0)).ToList()) { if (meshesPerDrawCall.Count() == 1) { // Nothing to group, skip to next entry continue; } // Remove old meshes foreach (var mesh in meshesPerDrawCall) { model.Meshes.Remove(mesh); } // Add new combined mesh(es) var baseMesh = meshesPerDrawCall.First(); var newMeshList = meshesPerDrawCall.Select(x => x.Draw).ToList().GroupDrawData(Allow32BitIndex); foreach (var generatedMesh in newMeshList) { model.Meshes.Add(new Mesh(generatedMesh, baseMesh.Parameters) { MaterialIndex = baseMesh.MaterialIndex, Name = baseMesh.Name, Draw = generatedMesh, NodeIndex = baseMesh.NodeIndex, Skinning = baseMesh.Skinning, }); } } } // split the meshes if necessary model.Meshes = SplitExtensions.SplitMeshes(model.Meshes, Allow32BitIndex); // Refresh skeleton updater with asset skeleton hierarchyUpdater = new SkeletonUpdater(skeleton); hierarchyUpdater.UpdateMatrices(); // bounding boxes var modelBoundingBox = model.BoundingBox; var modelBoundingSphere = model.BoundingSphere; foreach (var mesh in model.Meshes) { var vertexBuffers = mesh.Draw.VertexBuffers; for (int vbIdx = 0; vbIdx < vertexBuffers.Length; vbIdx++) { // Compute local mesh bounding box (no node transformation) Matrix matrix = Matrix.Identity; mesh.BoundingBox = vertexBuffers[vbIdx].ComputeBounds(ref matrix, out mesh.BoundingSphere); // Compute model bounding box (includes node transformation) hierarchyUpdater.GetWorldMatrix(mesh.NodeIndex, out matrix); BoundingSphere meshBoundingSphere; var meshBoundingBox = vertexBuffers[vbIdx].ComputeBounds(ref matrix, out meshBoundingSphere); BoundingBox.Merge(ref modelBoundingBox, ref meshBoundingBox, out modelBoundingBox); BoundingSphere.Merge(ref modelBoundingSphere, ref meshBoundingSphere, out modelBoundingSphere); } // TODO: temporary Always try to compact mesh.Draw.CompactIndexBuffer(); } model.BoundingBox = modelBoundingBox; model.BoundingSphere = modelBoundingSphere; // Count unique meshes (they can be shared) var uniqueDrawMeshes = model.Meshes.Select(x => x.Draw).Distinct(); // Count unique vertex buffers and squish them together in a single buffer var uniqueVB = uniqueDrawMeshes.SelectMany(x => x.VertexBuffers).Distinct().ToList(); var vbMap = new Dictionary <VertexBufferBinding, VertexBufferBinding>(); var sizeVertexBuffer = uniqueVB.Select(x => x.Buffer.GetSerializationData().Content.Length).Sum(); var vertexBuffer = new BufferData(BufferFlags.VertexBuffer, new byte[sizeVertexBuffer]); var vertexBufferSerializable = vertexBuffer.ToSerializableVersion(); var vertexBufferNextIndex = 0; foreach (var vbBinding in uniqueVB) { var oldVertexBuffer = vbBinding.Buffer.GetSerializationData().Content; Array.Copy(oldVertexBuffer, 0, vertexBuffer.Content, vertexBufferNextIndex, oldVertexBuffer.Length); vbMap.Add(vbBinding, new VertexBufferBinding(vertexBufferSerializable, vbBinding.Declaration, vbBinding.Count, vbBinding.Stride, vertexBufferNextIndex)); vertexBufferNextIndex += oldVertexBuffer.Length; } // Count unique index buffers and squish them together in a single buffer var uniqueIB = uniqueDrawMeshes.Select(x => x.IndexBuffer).NotNull().Distinct().ToList(); var sizeIndexBuffer = 0; foreach (var ibBinding in uniqueIB) { // Make sure 32bit indices are properly aligned to 4 bytes in case the last alignment was 2 bytes if (ibBinding.Is32Bit && sizeIndexBuffer % 4 != 0) { sizeIndexBuffer += 2; } sizeIndexBuffer += ibBinding.Buffer.GetSerializationData().Content.Length; } var ibMap = new Dictionary <IndexBufferBinding, IndexBufferBinding>(); if (uniqueIB.Count > 0) { var indexBuffer = new BufferData(BufferFlags.IndexBuffer, new byte[sizeIndexBuffer]); var indexBufferSerializable = indexBuffer.ToSerializableVersion(); var indexBufferNextIndex = 0; foreach (var ibBinding in uniqueIB) { var oldIndexBuffer = ibBinding.Buffer.GetSerializationData().Content; // Make sure 32bit indices are properly aligned to 4 bytes in case the last alignment was 2 bytes if (ibBinding.Is32Bit && indexBufferNextIndex % 4 != 0) { indexBufferNextIndex += 2; } Array.Copy(oldIndexBuffer, 0, indexBuffer.Content, indexBufferNextIndex, oldIndexBuffer.Length); ibMap.Add(ibBinding, new IndexBufferBinding(indexBufferSerializable, ibBinding.Is32Bit, ibBinding.Count, indexBufferNextIndex)); indexBufferNextIndex += oldIndexBuffer.Length; } } // Assign new vertex and index buffer bindings foreach (var drawMesh in uniqueDrawMeshes) { for (int i = 0; i < drawMesh.VertexBuffers.Length; i++) { drawMesh.VertexBuffers[i] = vbMap[drawMesh.VertexBuffers[i]]; } if (drawMesh.IndexBuffer != null) { drawMesh.IndexBuffer = ibMap[drawMesh.IndexBuffer]; } } vbMap.Clear(); ibMap.Clear(); // Convert to Entity return(model); }
protected static TContentType CreateRef <TContentType>(AssetItem assetItem) where TContentType : class, new() { return(AttachedReferenceManager.CreateProxyObject <TContentType>(assetItem.Id, assetItem.Location)); }
protected override Task <ResultStatus> DoCommandOverride(ICommandContext commandContext) { var nodes = new List <SpriteStudioNode>(); string modelName; if (!SpriteStudioXmlImport.ParseModel(Parameters.Source, nodes, out modelName)) { return(null); } var cells = new List <SpriteStudioCell>(); var textures = new List <UFile>(); if (!SpriteStudioXmlImport.ParseCellMaps(Parameters.Source, textures, cells)) { return(null); } var anims = new List <SpriteStudioAnim>(); if (!SpriteStudioXmlImport.ParseAnimations(Parameters.Source, anims)) { return(null); } var assetManager = new ContentManager(MicrothreadLocalDatabases.ProviderService); var sheet = new SpriteSheet(); foreach (var cell in cells) { var sprite = new Sprite(cell.Name, AttachedReferenceManager.CreateProxyObject <Texture>(AssetId.Empty, Parameters.BuildTextures[cell.TextureIndex])) { Region = cell.Rectangle, Center = cell.Pivot, IsTransparent = true }; sheet.Sprites.Add(sprite); } var nodeMapping = nodes.Select((x, i) => new { Name = x.Name, Index = i }).ToDictionary(x => x.Name, x => x.Index); //fill up some basic data for our model using the first animation in the array var anim = anims[0]; foreach (var data in anim.NodesData) { int nodeIndex; if (!nodeMapping.TryGetValue(data.Key, out nodeIndex)) { continue; } var node = nodes[nodeIndex]; foreach (var pair in data.Value.Data) { var tag = pair.Key; if (pair.Value.All(x => x["time"] != "0")) { continue; } var value = pair.Value.First()["value"]; //do we always have a frame 0? should be the case actually switch (tag) { case "POSX": node.BaseState.Position.X = float.Parse(value, CultureInfo.InvariantCulture); break; case "POSY": node.BaseState.Position.Y = float.Parse(value, CultureInfo.InvariantCulture); break; case "ROTZ": node.BaseState.RotationZ = MathUtil.DegreesToRadians(float.Parse(value, CultureInfo.InvariantCulture)); break; case "PRIO": node.BaseState.Priority = int.Parse(value, CultureInfo.InvariantCulture); break; case "SCLX": node.BaseState.Scale.X = float.Parse(value, CultureInfo.InvariantCulture); break; case "SCLY": node.BaseState.Scale.Y = float.Parse(value, CultureInfo.InvariantCulture); break; case "ALPH": node.BaseState.Transparency = float.Parse(value, CultureInfo.InvariantCulture); break; case "HIDE": node.BaseState.Hide = int.Parse(value, CultureInfo.InvariantCulture); break; case "FLPH": node.BaseState.HFlipped = int.Parse(value, CultureInfo.InvariantCulture); break; case "FLPV": node.BaseState.VFlipped = int.Parse(value, CultureInfo.InvariantCulture); break; case "CELL": node.BaseState.SpriteId = int.Parse(value, CultureInfo.InvariantCulture); break; case "COLV": var color = new Color4(Color.FromBgra(int.Parse(value, CultureInfo.InvariantCulture))); node.BaseState.BlendColor = colorSpace == ColorSpace.Linear ? color.ToLinear() : color; break; case "COLB": node.BaseState.BlendType = (SpriteStudioBlending)int.Parse(value, CultureInfo.InvariantCulture); break; case "COLF": node.BaseState.BlendFactor = float.Parse(value, CultureInfo.InvariantCulture); break; } } } var spriteStudioSheet = new SpriteStudioSheet { NodesInfo = nodes, SpriteSheet = sheet }; assetManager.Save(Url, spriteStudioSheet); return(Task.FromResult(ResultStatus.Successful)); }