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 = new GameSettingsAsset { DefaultScene = AttachedReferenceManager.CreateSerializableVersion <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 ConvertFrom(ref ObjectContext context, Scalar fromScalar) { Guid 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)); } return(AttachedReferenceManager.CreateSerializableVersion(context.Descriptor.Type, guid, location)); }
private static AssetItem ImportModel(List <AssetItem> assetReferences, UFile assetSource, UFile localPath, EntityInfo entityInfo, bool shouldPostFixName) { 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 foundMaterial = loadedMaterials.FirstOrDefault(x => x.Location == new UFile(material.Key, null)); if (foundMaterial != null) { asset.Materials.Add(new ModelMaterial { Name = material.Key, MaterialInstance = new MaterialInstance() { Material = AttachedReferenceManager.CreateSerializableVersion <Material>(foundMaterial.Id, foundMaterial.Location) } }); } } //handle the case where during import we imported no materials at all //todo Instead of null material add a default paradox material if (entityInfo.Materials.Count == 0) { asset.Materials.Add(new ModelMaterial { Name = "Material", MaterialInstance = new MaterialInstance() }); } } if (entityInfo.Nodes != null) { foreach (var node in entityInfo.Nodes) { asset.Nodes.Add(new NodeInformation(node.Name, node.Depth, node.Preserve)); } } if (entityInfo.AnimationNodes != null && entityInfo.AnimationNodes.Count > 0) { asset.PreserveNodes(entityInfo.AnimationNodes); } var modelUrl = new UFile(localPath.GetFileName() + (shouldPostFixName?" Model": ""), null); var assetItem = new AssetItem(modelUrl, asset); assetReferences.Add(assetItem); return(assetItem); }
protected override Task <ResultStatus> DoCommandOverride(ICommandContext commandContext) { var assetManager = new AssetManager(); var imageGroupData = new TImageGroupData { Images = new List <TImageData>() }; // add the sprite data to the sprite list. foreach (var uiImage in asset.GroupAsset.Images) { var newImage = new TImageData { Name = uiImage.Name, Region = uiImage.TextureRegion, IsTransparent = asset.GroupAsset.Alpha != AlphaFormat.None, // todo analyze texture region texture data to auto-determine alpha? Orientation = uiImage.Orientation, }; if (UseSeparateAlphaTexture) { //var baseLocation = ImageGroupAsset.BuildTextureUrl(Url, ImageToTextureIndex[uiImage]); // newImage.Texture = AttachedReferenceManager.CreateSerializableVersion<Texture>(Guid.Empty, TextureAlphaComponentSplitter.GenerateColorTextureURL(baseLocation)); // newImage.TextureAlpha = AttachedReferenceManager.CreateSerializableVersion<Texture>(Guid.Empty, TextureAlphaComponentSplitter.GenerateAlphaTextureURL(baseLocation)); } else { int imageIndex; if (ImageToTextureIndex.TryGetValue(uiImage, out imageIndex)) { newImage.Texture = AttachedReferenceManager.CreateSerializableVersion <Texture>(Guid.Empty, ImageGroupAsset.BuildTextureUrl(Url, ImageToTextureIndex[uiImage])); } else { commandContext.Logger.Warning("Image '{0}' has an invalid image source file '{1}', resulting texture will be null.", uiImage.Name, uiImage.Source); } } SetImageSpecificFields(uiImage, newImage); imageGroupData.Images.Add(newImage); } // save the imageData into the data base assetManager.Save(Url, imageGroupData); return(Task.FromResult(ResultStatus.Successful)); }
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, null)); if (foundMaterial != null) { var reference = AttachedReferenceManager.CreateSerializableVersion <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.CreateSerializableVersion <Skeleton>(skeletonAsset.Id, skeletonAsset.Location); } var modelUrl = new UFile(localPath.GetFileName() + (shouldPostFixName?" Model": ""), null); var assetItem = new AssetItem(modelUrl, asset); assetReferences.Add(assetItem); return(assetItem); }
private static void ImportAnimation(List <AssetItem> assetReferences, UFile localPath, List <string> animationNodes, bool shouldPostFixName, AssetItem skeletonAsset) { if (animationNodes != null && animationNodes.Count > 0) { var assetSource = localPath; var asset = new AnimationAsset { Source = assetSource }; var animUrl = localPath.GetFileName() + (shouldPostFixName ? " Animation" : ""); if (skeletonAsset != null) { asset.Skeleton = AttachedReferenceManager.CreateSerializableVersion <Skeleton>(skeletonAsset.Id, skeletonAsset.Location); } assetReferences.Add(new AssetItem(animUrl, asset)); } }
protected override Task <ResultStatus> DoCommandOverride(ICommandContext commandContext) { var assetManager = new AssetManager(); var imageGroupData = new SpriteSheet { Sprites = new List <Graphics.Sprite>() }; // add the sprite data to the sprite list. foreach (var image in AssetParameters.SheetAsset.Sprites) { var newImage = new Graphics.Sprite { Name = image.Name, Region = image.TextureRegion, IsTransparent = AssetParameters.SheetAsset.Alpha != AlphaFormat.None, // todo analyze texture region texture data to auto-determine alpha? Orientation = image.Orientation, Center = image.Center + (image.CenterFromMiddle ? new Vector2(image.TextureRegion.Width, image.TextureRegion.Height) / 2 : Vector2.Zero), Borders = image.Borders, PixelsPerUnit = new Vector2(image.PixelsPerUnit) }; int imageIndex; if (ImageToTextureIndex.TryGetValue(image, out imageIndex)) { newImage.Texture = AttachedReferenceManager.CreateSerializableVersion <Texture>(Guid.Empty, SpriteSheetAsset.BuildTextureUrl(Url, ImageToTextureIndex[image])); } else { commandContext.Logger.Warning("Image '{0}' has an invalid image source file '{1}', resulting texture will be null.", image.Name, image.Source); } imageGroupData.Sprites.Add(newImage); } // save the imageData into the data base assetManager.Save(Url, imageGroupData); return(Task.FromResult(ResultStatus.Successful)); }
private static AssetItem ImportEntity(List <AssetItem> assetReferences, UFile localPath, AssetItem modelItem) { var entityUrl = new UFile(localPath.GetFileName(), null); var asset = new EntityAsset { Source = localPath }; var rootEntityData = new Entity(); asset.Hierarchy.Entities.Add(rootEntityData); asset.Hierarchy.RootEntity = rootEntityData.Id; rootEntityData.Name = entityUrl; // Use modelUrl.Path to get the url without the extension rootEntityData.Add(ModelComponent.Key, new ModelComponent { Model = AttachedReferenceManager.CreateSerializableVersion <Rendering.Model>(modelItem.Id, modelItem.Location) }); var assetReference = new AssetItem(entityUrl, asset); assetReferences.Add(assetReference); return(assetReference); }
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.CreateSerializableVersion(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 nodes = new List <SpriteStudioNode>(); string modelName; if (!SpriteStudioXmlImport.ParseModel(AssetParameters.Source, nodes, out modelName)) { return(null); } var cells = new List <SpriteStudioCell>(); var textures = new List <UFile>(); if (!SpriteStudioXmlImport.ParseCellMaps(AssetParameters.Source, textures, cells)) { return(null); } var anims = new List <SpriteStudioAnim>(); if (!SpriteStudioXmlImport.ParseAnimations(AssetParameters.Source, anims)) { return(null); } var assetManager = new AssetManager(); var sheet = new SpriteSheet(); foreach (var cell in cells) { var sprite = new Sprite(cell.Name, AttachedReferenceManager.CreateSerializableVersion <Texture>(Guid.Empty, AssetParameters.BuildTextures[cell.TextureIndex])) { Region = cell.Rectangle, Center = cell.Pivot, IsTransparent = true }; sheet.Sprites.Add(sprite); } //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) { var node = nodes.FirstOrDefault(x => x.Name == data.Key); if (node == null) { continue; } 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) > 0; break; case "FLPH": node.BaseState.HFlipped = int.Parse(value, CultureInfo.InvariantCulture) > 0; break; case "FLPV": node.BaseState.VFlipped = int.Parse(value, CultureInfo.InvariantCulture) > 0; 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)); }
public override void VisitObjectMember(object container, ObjectDescriptor containerDescriptor, IMemberDescriptor member, object value) { base.VisitObjectMember(container, containerDescriptor, member, value); var assetReference = value as AssetReference; var assetBase = value as AssetBase; var attachedReference = value != null?AttachedReferenceManager.GetAttachedReference(value) : null; if (assetReference != null) { AddLink(assetReference, (guid, location) => { var newValue = AssetReference.New(member.Type, guid.HasValue ? guid.Value : assetReference.Id, location); member.Set(container, newValue); return(newValue); }); } else if (assetBase != null) { AddLink(assetBase, (guid, location) => { var newValue = new AssetBase(location, assetBase.Asset); member.Set(container, newValue); return(newValue); }); } else if (attachedReference != null) { AddLink(new AttachedContentReference(attachedReference), (guid, location) => { object newValue = guid.HasValue && guid.Value != Guid.Empty ? AttachedReferenceManager.CreateSerializableVersion(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 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 assetBase = value as AssetBase; var attachedReference = value != null?AttachedReferenceManager.GetAttachedReference(value) : null; if (assetReference != null) { AddLink(assetReference, (guid, location) => { var newValue = AssetReference.New(descriptor.ValueType, guid.HasValue ? guid.Value : assetReference.Id, location); descriptor.SetValue(dictionaryObj, key, newValue); return(newValue); }); } else if (assetBase != null) { AddLink(assetBase, (guid, location) => { var newValue = new AssetBase(location, assetBase.Asset); descriptor.SetValue(dictionaryObj, key, newValue); return(newValue); }); } else if (attachedReference != null) { AddLink(new AttachedContentReference(attachedReference), (guid, location) => { object newValue = guid.HasValue && guid.Value != Guid.Empty ? AttachedReferenceManager.CreateSerializableVersion(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 VisitCollectionItem(IEnumerable collection, CollectionDescriptor descriptor, int index, object item, ITypeDescriptor itemDescriptor) { base.VisitCollectionItem(collection, descriptor, index, item, itemDescriptor); var assetReference = item as AssetReference; var assetBase = item as AssetBase; var attachedReference = item != null?AttachedReferenceManager.GetAttachedReference(item) : null; // TODO force support for IList in CollectionDescriptor if (assetReference != null) { var list = (IList)collection; AddLink(assetReference, (guid, location) => list[index] = AssetReference.New(descriptor.ElementType, guid.HasValue ? guid.Value : assetReference.Id, location)); } else if (assetBase != null) { var list = (IList)collection; AddLink(assetBase, (guid, location) => list[index] = new AssetBase(location, assetBase.Asset)); } else if (attachedReference != null) { var list = (IList)collection; AddLink(new AttachedContentReference(attachedReference), (guid, location) => list[index] = guid.HasValue && guid.Value != Guid.Empty ? AttachedReferenceManager.CreateSerializableVersion(descriptor.ElementType, guid.Value, location) : null); } else if (item is UFile) { var list = (IList)collection; AddLink(item, (guid, location) => list[index] = new UFile(location)); } else if (item is UDirectory) { var list = (IList)collection; AddLink(item, (guid, location) => list[index] = new UDirectory(location)); } }
/// <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("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 if (gameSettingsAssetItem != null) { var defaultSceneRuntime = ((GameSettingsAsset)gameSettingsAssetItem.Asset).DefaultScene; if (defaultSceneRuntime != null) { 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 = 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.AssetNotFound, GameSettingsAsset.GameSettingsLocation); var gameSettingsAsset = new GameSettingsAsset(); gameSettingsAsset.DefaultScene = AttachedReferenceManager.CreateSerializableVersion <Scene>(defaultScene.Id, defaultScene.Location); gameSettingsAssetItem = new AssetItem(GameSettingsAsset.GameSettingsLocation, gameSettingsAsset); package.Assets.Add(gameSettingsAssetItem); gameSettingsAssetItem.IsDirty = 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 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."); continue; } 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.CreateSerializableVersion <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) { // 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, }); } } } // Remap skinning foreach (var skinning in model.Meshes.Select(x => x.Skinning).Where(x => x != null).Distinct()) { // 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 nodeIndex = skinning.Bones[i].NodeIndex; var newNodeIndex = skeletonMapping.SourceToSource[nodeIndex]; skinning.Bones[i].NodeIndex = skeletonMapping.SourceToTarget[nodeIndex]; // If it was remapped, we also need to update matrix if (newNodeIndex != nodeIndex) { var transformationMatrix = CombineMatricesFromNodeIndices(hierarchyUpdater.NodeTransformations, newNodeIndex, nodeIndex); skinning.Bones[i].LinkToMeshMatrix = Matrix.Multiply(skinning.Bones[i].LinkToMeshMatrix, transformationMatrix); } } } // 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); }
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 assetBase = item as AssetBase; 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(descriptor.ElementType, guid ?? assetReference.Id, location); descriptor.SetValue(collection, index, link); return(link); }); } else if (assetBase != null) { AddLink(assetBase, (guid, location) => { var link = new AssetBase(location, assetBase.Asset); descriptor.SetValue(collection, index, link); return(link); }); } else if (attachedReference != null) { AddLink(attachedReference, (guid, location) => { var link = guid.HasValue && guid.Value != Guid.Empty ? AttachedReferenceManager.CreateSerializableVersion(descriptor.ElementType, guid.Value, location) : null; if (link != null) { IdentifiableHelper.SetId(link, IdentifiableHelper.GetId(item)); } 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); }); } }
protected override Task <ResultStatus> DoCommandOverride(ICommandContext commandContext) { var assetManager = new AssetManager(); // Create atlas texture Dictionary <SpriteInfo, PackedSpriteInfo> spriteToPackedSprite = null; // Generate texture atlas var isPacking = AssetParameters.SheetAsset.Packing.Enabled; if (isPacking) { var resultStatus = CreateAtlasTextures(commandContext.Logger, out spriteToPackedSprite); if (resultStatus != ResultStatus.Successful) { return(Task.FromResult(resultStatus)); } } var imageGroupData = new SpriteSheet { Sprites = new List <Graphics.Sprite>() }; // add the sprite data to the sprite list. foreach (var image in AssetParameters.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.ContainsKey(image)) // ensure that unpackable elements (invalid because of null size/texture) are properly added in the sheet using the normal path { var packedSprite = spriteToPackedSprite[image]; 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 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.Z; borders.Z = borders.Y; borders.Y = 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.Y; borders.Y = borders.Z; borders.Z = borders.X; borders.X = oldBorderW; } } } else { region = image.TextureRegion; orientation = image.Orientation; AssetParameters.ImageToTextureUrl.TryGetValue(image, out textureUrl); } // Affect the texture Texture texture = null; if (textureUrl != null) { texture = AttachedReferenceManager.CreateSerializableVersion <Texture>(Guid.Empty, textureUrl); } else { commandContext.Logger.Warning("Image '{0}' has an invalid image source file '{1}', resulting texture will be null.", image.Name, image.Source); } 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 (AssetParameters.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 VisitArrayItem(Array array, ArrayDescriptor descriptor, int index, object item, ITypeDescriptor itemDescriptor) { base.VisitArrayItem(array, descriptor, index, item, itemDescriptor); var assetReference = item as AssetReference; var assetBase = item as AssetBase; var attachedReference = item != null?AttachedReferenceManager.GetAttachedReference(item) : null; if (assetReference != null) { AddLink(item, (guid, location) => { var newValue = AssetReference.New(descriptor.ElementType, guid.HasValue ? guid.Value : assetReference.Id, location); array.SetValue(newValue, index); return(newValue); }); } else if (assetBase != null) { AddLink(item, (guid, location) => { var newValue = new AssetBase(location, assetBase.Asset); array.SetValue(newValue, index); return(newValue); }); } else if (attachedReference != null) { AddLink(new AttachedContentReference(attachedReference), (guid, location) => { object newValue = guid.HasValue && guid.Value != Guid.Empty ? AttachedReferenceManager.CreateSerializableVersion(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); }); } }
public void TestMaterial() { var compiler = new EffectCompiler { UseFileSystem = true }; compiler.SourceDirectories.Add(@"..\..\sources\engine\SiliconStudio.Paradox.Graphics\Shaders"); compiler.SourceDirectories.Add(@"..\..\sources\engine\SiliconStudio.Paradox.Engine\Shaders"); compiler.SourceDirectories.Add(@"..\..\sources\shaders\Core"); compiler.SourceDirectories.Add(@"..\..\sources\shaders\Lights"); compiler.SourceDirectories.Add(@"..\..\sources\shaders\Materials"); compiler.SourceDirectories.Add(@"..\..\sources\shaders\Shadows"); compiler.SourceDirectories.Add(@"..\..\sources\shaders\ComputeColor"); compiler.SourceDirectories.Add(@"..\..\sources\shaders\Skinning"); compiler.SourceDirectories.Add(@"..\..\sources\shaders\Shading"); compiler.SourceDirectories.Add(@"..\..\sources\shaders\Transformation"); compiler.SourceDirectories.Add(@"..\..\sources\shaders\Utils"); var compilerParameters = new CompilerParameters { Platform = GraphicsPlatform.Direct3D11 }; var layers = new MaterialBlendLayers(); layers.Add(new MaterialBlendLayer { BlendMap = new ComputeFloat(0.5f), Material = AttachedReferenceManager.CreateSerializableVersion <Material>(Guid.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 List <ShaderSource> { 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("ParadoxEffectBase"), compilerParameters); Assert.IsFalse(results.HasErrors); }
protected override Task <ResultStatus> DoCommandOverride(ICommandContext commandContext) { var assetManager = new AssetManager(); // Create atlas texture Dictionary <SpriteInfo, PackedSpriteInfo> spriteToPackedSprite = null; // Generate texture atlas var isPacking = AssetParameters.SheetAsset.Packing.Enabled; if (isPacking) { var resultStatus = CreateAtlasTextures(commandContext.Logger, out spriteToPackedSprite); if (resultStatus != ResultStatus.Successful) { return(Task.FromResult(resultStatus)); } } var imageGroupData = new SpriteSheet { Sprites = new List <Graphics.Sprite>() }; // add the sprite data to the sprite list. foreach (var image in AssetParameters.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.ContainsKey(image)) // ensure that unpackable elements (invalid because of null size/texture) are properly added in the sheet using the normal path { var packedSprite = spriteToPackedSprite[image]; 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 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.Z; borders.Z = borders.Y; borders.Y = 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.Y; borders.Y = borders.Z; borders.Z = borders.X; borders.X = oldBorderW; } } } else { region = image.TextureRegion; orientation = image.Orientation; AssetParameters.ImageToTextureUrl.TryGetValue(image, out textureUrl); } // Affect the texture Texture texture = null; if (textureUrl != null) { texture = AttachedReferenceManager.CreateSerializableVersion <Texture>(Guid.Empty, textureUrl); } else { commandContext.Logger.Warning("Image '{0}' has an invalid image source file '{1}', resulting texture will be null.", image.Name, image.Source); } imageGroupData.Sprites.Add(new Graphics.Sprite { Name = image.Name, Region = region, IsTransparent = AssetParameters.SheetAsset.Alpha != AlphaFormat.None, // todo analyze texture region texture data to auto-determine alpha? Orientation = orientation, Center = center, Borders = borders, PixelsPerUnit = new Vector2(image.PixelsPerUnit), Texture = texture }); } // save the imageData into the data base assetManager.Save(Url, imageGroupData); return(Task.FromResult(ResultStatus.Successful)); }