Esempio n. 1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="MaterialDescriptor"/> class.
 /// </summary>
 public MaterialDescriptor()
 {
     Attributes = new MaterialAttributes();
     Layers     = new MaterialBlendLayers();
     // An instance id, only used to match descriptor
     MaterialId = AssetId.New();
 }
Esempio n. 2
0
        /// <summary>
        /// Registers an asset identifier for usage.
        /// </summary>
        /// <param name="assetId">The asset identifier.</param>
        /// <param name="newGuid">The new unique identifier if an asset has already been registered with the same id.</param>
        /// <returns><c>true</c> if the asset id is already in used. <paramref name="newGuid" /> contains a new guid, <c>false</c> otherwise.</returns>
        public bool RegisterId(AssetId assetId, out AssetId newGuid)
        {
            newGuid = assetId;
            var result = AlwaysCreateNewId || IsContainingId(assetId);

            if (result)
            {
                newGuid = AssetId.New();
            }
            ExistingIds.Add(newGuid);
            return(result);
        }
Esempio n. 3
0
        public void TestHash()
        {
            var obj1 = new TestAssetClonerObject
            {
                Name      = "Test1",
                SubObject = new TestAssetClonerObject()
                {
                    Name = "Test2"
                },
                ObjectWithAttachedReference = new TestObjectReference()
            };

            // Create a fake reference to make sure that the attached reference will not be serialized
            var attachedReference = AttachedReferenceManager.GetOrCreateAttachedReference(obj1.ObjectWithAttachedReference);

            attachedReference.Url = "just_for_test";
            attachedReference.Id  = AssetId.New();

            var obj2 = AssetCloner.Clone(obj1);

            var hash1 = AssetHash.Compute(obj1);
            var hash2 = AssetHash.Compute(obj2);

            Assert.AreEqual(hash1, hash2);

            obj1.Name = "Yes";
            var hash11 = AssetHash.Compute(obj1);

            Assert.AreNotEqual(hash11, hash2);
            obj1.Name = "Test1";

            var hash12 = AssetHash.Compute(obj1);

            Assert.AreEqual(hash12, hash2);

            obj2 = AssetCloner.Clone(obj1);

            var hash1WithOverrides = AssetHash.Compute(obj1);
            var hash2WithOverrides = AssetHash.Compute(obj2);

            Assert.AreEqual(hash1WithOverrides, hash2WithOverrides);
        }
Esempio n. 4
0
        public override bool Upgrade(PackageLoadParameters loadParameters, PackageSession session, ILogger log, Package dependentPackage, PackageDependency dependency, Package dependencyPackage, IList <PackageLoadingAssetFile> assetFiles)
        {
#if XENKO_SUPPORT_BETA_UPGRADE
            // Graphics Compositor asset
            if (dependency.Version.MinVersion < new PackageVersion("1.11.0.0"))
            {
                // Find game settings (if there is none, it's not a game and nothing to do)
                var gameSettings = assetFiles.FirstOrDefault(x => x.AssetLocation == GameSettingsAsset.GameSettingsLocation);
                if (gameSettings != null)
                {
                    RunAssetUpgradersUntilVersion(log, dependentPackage, dependency.Name, gameSettings.Yield().ToList(), new PackageVersion("1.10.0-alpha02"));

                    using (var gameSettingsYaml = gameSettings.AsYamlAsset())
                    {
                        // Figure out graphics profile; default is Level_10_0 (which is same as GraphicsCompositor default)
                        var graphicsProfile = GraphicsProfile.Level_10_0;
                        try
                        {
                            foreach (var mapping in gameSettingsYaml.DynamicRootNode.Defaults)
                            {
                                if (mapping.Node.Tag == "!Xenko.Graphics.RenderingSettings,Xenko.Graphics")
                                {
                                    if (mapping.DefaultGraphicsProfile != null)
                                    {
                                        Enum.TryParse((string)mapping.DefaultGraphicsProfile, out graphicsProfile);
                                    }
                                    break;
                                }
                            }
                        }
                        catch
                        {
                            // If something goes wrong, keep going with the default value
                        }

                        // Add graphics compositor asset by creating a derived asset of Compositing/DefaultGraphicsCompositor.xkgfxcomp
                        var graphicsCompositorUrl = graphicsProfile >= GraphicsProfile.Level_10_0 ? DefaultGraphicsCompositorLevel10Url : DefaultGraphicsCompositorLevel9Url;

                        var defaultGraphicsCompositor = dependencyPackage.Assets.Find(graphicsCompositorUrl);
                        if (defaultGraphicsCompositor == null)
                        {
                            log.Error($"Could not find graphics compositor in Xenko package at location [{graphicsCompositorUrl}]");
                            return(false);
                        }

                        // Note: we create a derived asset without its content
                        // We don't use defaultGraphicsCompositor content because it might be a newer version that next upgrades might not understand.
                        // The override system will restore all the properties for us.
                        var graphicsCompositorAssetId = AssetId.New();
                        var graphicsCompositorAsset   = new PackageLoadingAssetFile(dependentPackage, "GraphicsCompositor.xkgfxcomp", null)
                        {
                            AssetContent = System.Text.Encoding.UTF8.GetBytes($"!GraphicsCompositorAsset\r\nId: {graphicsCompositorAssetId}\r\nSerializedVersion: {{Xenko: 1.10.0-beta01}}\r\nArchetype: {defaultGraphicsCompositor.ToReference()}"),
                        };

                        assetFiles.Add(graphicsCompositorAsset);

                        // Update game settings to point to our newly created compositor
                        gameSettingsYaml.DynamicRootNode.GraphicsCompositor = new AssetReference(graphicsCompositorAssetId, graphicsCompositorAsset.AssetLocation).ToString();
                    }
                }

                // Delete EffectLogAsset
                foreach (var assetFile in assetFiles)
                {
                    if (assetFile.FilePath.GetFileNameWithoutExtension() == EffectLogAsset.DefaultFile)
                    {
                        assetFile.Deleted = true;
                    }
                }
            }


            if (dependency.Version.MinVersion < new PackageVersion("1.11.1.0"))
            {
                ConvertNormalMapsInvertY(assetFiles);
            }

            // Skybox/Background separation
            if (dependency.Version.MinVersion < new PackageVersion("1.11.1.1"))
            {
                SplitSkyboxLightingUpgrader upgrader = new SplitSkyboxLightingUpgrader();
                foreach (var skyboxAsset in assetFiles.Where(f => f.FilePath.GetFileExtension() == ".xksky"))
                {
                    upgrader.ProcessSkybox(skyboxAsset);
                }
                foreach (var sceneAsset in assetFiles.Where(f => (f.FilePath.GetFileExtension() == ".xkscene") || (f.FilePath.GetFileExtension() == ".xkprefab")))
                {
                    using (var yaml = sceneAsset.AsYamlAsset())
                    {
                        upgrader.UpgradeAsset(yaml.DynamicRootNode);
                    }
                }
            }

            if (dependency.Version.MinVersion < new PackageVersion("1.11.1.2"))
            {
                var navigationMeshAssets = assetFiles.Where(f => f.FilePath.GetFileExtension() == ".xknavmesh");
                var scenes = assetFiles.Where(f => f.FilePath.GetFileExtension() == ".xkscene");
                UpgradeNavigationBoundingBox(navigationMeshAssets, scenes);

                // Upgrade game settings to have groups for navigation meshes
                var gameSettingsAsset = assetFiles.FirstOrDefault(x => x.AssetLocation == GameSettingsAsset.GameSettingsLocation);
                if (gameSettingsAsset != null)
                {
                    // Upgrade the game settings first to contain navigation mesh settings entry
                    RunAssetUpgradersUntilVersion(log, dependentPackage, dependency.Name, gameSettingsAsset.Yield().ToList(), new PackageVersion("1.11.1.2"));

                    UpgradeNavigationMeshGroups(navigationMeshAssets, gameSettingsAsset);
                }
            }

            if (dependency.Version.MinVersion < new PackageVersion("2.0.0.2"))
            {
                RunAssetUpgradersUntilVersion(log, dependentPackage, dependency.Name, assetFiles, new PackageVersion("2.0.0.0"));

                Guid defaultCompositorId = Guid.Empty;
                var  defaultGraphicsCompositorCameraSlot = Guid.Empty;

                // Step one: find the default compositor, that will be the reference one to patch scenes
                var gameSettings = assetFiles.FirstOrDefault(x => x.AssetLocation == GameSettingsAsset.GameSettingsLocation);
                if (gameSettings != null)
                {
                    using (var gameSettingsYaml = gameSettings.AsYamlAsset())
                    {
                        dynamic asset = gameSettingsYaml.DynamicRootNode;
                        string  compositorReference = asset.GraphicsCompositor?.ToString();
                        var     guidString          = compositorReference?.Split(':').FirstOrDefault();
                        Guid.TryParse(guidString, out defaultCompositorId);

                        // Figure out graphics profile; default is Level_10_0 (which is same as GraphicsCompositor default)
                        var graphicsProfile = GraphicsProfile.Level_10_0;
                        try
                        {
                            foreach (var mapping in gameSettingsYaml.DynamicRootNode.Defaults)
                            {
                                if (mapping.Node.Tag == "!Xenko.Graphics.RenderingSettings,Xenko.Graphics")
                                {
                                    if (mapping.DefaultGraphicsProfile != null)
                                    {
                                        Enum.TryParse((string)mapping.DefaultGraphicsProfile, out graphicsProfile);
                                    }
                                    break;
                                }
                            }
                        }
                        catch
                        {
                            // If something goes wrong, keep going with the default value
                        }

                        // store the camera slot of the default graphics compositor, because the one from the project will be empty since upgrade relies on reconcile with base, which happens after
                        defaultGraphicsCompositorCameraSlot = graphicsProfile >= GraphicsProfile.Level_10_0 ? DefaultGraphicsCompositorLevel10CameraSlot : DefaultGraphicsCompositorLevel9CameraSlot;
                    }
                }

                // Step two: add an Guid for each item in the SceneCameraSlotCollection of each graphics compositor
                Dictionary <int, Guid> slotIds = new Dictionary <int, Guid>();

                // This upgrades a projects that already had a graphics compositor before (ie. a project created with public 1.10)
                // In this case, the compositor that has been created above is empty, and the upgrade relies on reconciliation with base
                // to fill it properly, which means that for now we have no camera slot. Fortunately, we know the camera slot id from the archetype.
                slotIds.Add(0, defaultGraphicsCompositorCameraSlot);

                var graphicsCompositorAssets = assetFiles.Where(f => f.FilePath.GetFileExtension() == ".xkgfxcomp");
                foreach (var graphicsCompositorAsset in graphicsCompositorAssets)
                {
                    using (var yamlAsset = graphicsCompositorAsset.AsYamlAsset())
                    {
                        dynamic asset        = yamlAsset.DynamicRootNode;
                        int     i            = 0;
                        var     localSlotIds = new Dictionary <int, Guid>();
                        if (asset.Cameras != null)
                        {
                            // This upgrades a projects that already had a graphics compositor before (ie. an internal project created with 1.11)
                            foreach (dynamic cameraSlot in asset.Cameras)
                            {
                                var  guid = Guid.NewGuid();
                                Guid assetId;
                                if (Guid.TryParse(asset.Id.ToString(), out assetId) && assetId == defaultCompositorId)
                                {
                                    slotIds[i] = guid;
                                }
                                localSlotIds.Add(i, guid);
                                cameraSlot.Value.Id = guid;
                                ++i;
                            }
                            var indexString = asset.Game?.Camera?.Index?.ToString();
                            int index;
                            int.TryParse(indexString, out index);
                            if (localSlotIds.ContainsKey(index) && asset.Game?.Camera != null)
                            {
                                asset.Game.Camera = $"ref!! {localSlotIds[index]}";
                            }
                        }
                        else
                        {
                            asset.Cameras = new YamlMappingNode();
                            asset.Cameras.de2e75c3b2b23e54162686363f3f138e      = new YamlMappingNode();
                            asset.Cameras.de2e75c3b2b23e54162686363f3f138e.Id   = defaultGraphicsCompositorCameraSlot;
                            asset.Cameras.de2e75c3b2b23e54162686363f3f138e.Name = "Main";
                        }
                    }
                }

                // Step three: patch every CameraComponent to reference the Guid instead of an index
                var entityHierarchyAssets = assetFiles.Where(f => f.FilePath.GetFileExtension() == ".xkscene" || f.FilePath.GetFileExtension() == ".xkprefab");
                foreach (var entityHierarchyAsset in entityHierarchyAssets)
                {
                    using (var yamlAsset = entityHierarchyAsset.AsYamlAsset())
                    {
                        dynamic asset = yamlAsset.DynamicRootNode;
                        foreach (var entity in asset.Hierarchy.Parts)
                        {
                            foreach (var component in entity.Entity.Components)
                            {
                                if (component.Value.Node.Tag == "!CameraComponent")
                                {
                                    var indexString = component.Value.Slot?.Index?.ToString() ?? "0";
                                    int index;
                                    if (int.TryParse(indexString, out index))
                                    {
                                        if (slotIds.ContainsKey(index))
                                        {
                                            component.Value.Slot = slotIds[index].ToString();
                                        }
                                        else
                                        {
                                            component.Value.Slot = Guid.Empty.ToString();
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
#endif
            // Put any new upgrader after this #endif
            if (dependency.Version.MinVersion < new PackageVersion("2.2.0.1"))
            {
                foreach (var assetFile in assetFiles)
                {
                    // Add new generic parameter to ShadowMapReceiverDirectional in effect log
                    if (assetFile.FilePath.GetFileExtension() == ".xkeffectlog")
                    {
                        var assetContent          = assetFile.AssetContent ?? File.ReadAllBytes(assetFile.FilePath.FullPath);
                        var assetContentString    = System.Text.Encoding.UTF8.GetString(assetContent);
                        var newAssetContentString = System.Text.RegularExpressions.Regex.Replace(assetContentString, @"(\s*-   ClassName: ShadowMapReceiverDirectional\r\n\s*    GenericArguments: \[\w*, \w*, \w*, \w*, \w*)\]", "$1, false]");
                        newAssetContentString = newAssetContentString.Replace("EffectName: SkyboxShader\r\n", "EffectName: SkyboxShaderCubemap\r\n");
                        if (assetContentString != newAssetContentString)
                        {
                            // Need replacement, update with replaced text
                            assetFile.AssetContent = System.Text.Encoding.UTF8.GetBytes(newAssetContentString);
                        }
                    }

                    // Set BackgroundComponent.Is2D when necessary
                    if (assetFile.FilePath.GetFileExtension() == ".xkscene" ||
                        assetFile.FilePath.GetFileExtension() == ".xkprefab")
                    {
                        using (var yamlAsset = assetFile.AsYamlAsset())
                        {
                            dynamic asset = yamlAsset.DynamicRootNode;
                            foreach (var entity in asset.Hierarchy.Parts)
                            {
                                foreach (var component in entity.Entity.Components)
                                {
                                    if (component.Value.Node.Tag == "!BackgroundComponent" && component.Value.Texture != null)
                                    {
                                        if (!AssetReference.TryParse((string)component.Value.Texture, out var textureReference))
                                        {
                                            continue;
                                        }

                                        // Find texture
                                        var textureAssetFile = assetFiles.FirstOrDefault(x => x.AssetLocation == textureReference.Location);
                                        if (textureAssetFile == null)
                                        {
                                            continue;
                                        }

                                        // Get texture source
                                        try
                                        {
                                            using (var yamlTextureAsset = textureAssetFile.AsYamlAsset())
                                            {
                                                dynamic textureAsset = yamlTextureAsset.DynamicRootNode;
                                                if (textureAsset.Source == null)
                                                {
                                                    continue;
                                                }

                                                var textureSource = UFile.Combine(textureAssetFile.FilePath.GetFullDirectory(), new UFile((string)textureAsset.Source));
                                                if (!File.Exists(textureSource))
                                                {
                                                    continue;
                                                }

                                                var texTool = new TextureTool();
                                                var image   = texTool.Load(textureSource, false);
                                                if (image != null)
                                                {
                                                    if (image.Dimension != TexImage.TextureDimension.TextureCube)
                                                    {
                                                        // We have a texture which is not a cubemap, mark background as 2D
                                                        component.Value.Is2D = true;
                                                    }

                                                    image.Dispose();
                                                }

                                                texTool.Dispose();
                                            }
                                        }
                                        catch
                                        {
                                            // If something goes wrong, keep default value (assume cubemap)
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if (dependency.Version.MinVersion < new PackageVersion("3.0.0.0"))
            {
                // Delete EffectLogAsset
                foreach (var assetFile in assetFiles)
                {
                    var assetContent          = assetFile.AssetContent ?? File.ReadAllBytes(assetFile.FilePath.FullPath);
                    var assetContentString    = System.Text.Encoding.UTF8.GetString(assetContent);
                    var newAssetContentString = RemoveSiliconStudioNamespaces(assetContentString);
                    if (assetContentString != newAssetContentString)
                    {
                        // Need replacement, update with replaced text
                        assetFile.AssetContent = System.Text.Encoding.UTF8.GetBytes(newAssetContentString);
                    }
                }
            }

            return(true);
        }