Example #1
0
        public void HLODDataTest()
        {
            using (Stream stream = new FileStream(mHlodArtifactName, FileMode.Open, FileAccess.Read))
            {
                HLODData data = HLODDataSerializer.Read(stream);

                Assert.AreEqual(0, data.GetMaterialCount());
                Assert.AreEqual(85, data.GetObjects().Count);
            }
        }
Example #2
0
 private TextureFormat GetCompressFormat(HLODData data, BuildTargetGroup group)
 {
     if (group == BuildTargetGroup.Android)
     {
         return(data.CompressionData.AndroidTextureFormat);
     }
     if (group == BuildTargetGroup.iOS)
     {
         return(data.CompressionData.iOSTextureFormat);
     }
     if (group == BuildTargetGroup.tvOS)
     {
         return(data.CompressionData.tvOSTextureFormat);
     }
     if (group == BuildTargetGroup.WebGL)
     {
         return(data.CompressionData.WebGLTextureFormat);
     }
     return(data.CompressionData.PCTextureFormat);
 }
Example #3
0
        public override void OnEnable()
        {
            base.OnEnable();

            string path = AssetDatabase.GetAssetPath(serializedObject.targetObject);

            using (Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read))
            {
                HLODData data = HLODDataSerializer.Read(stream);

                long totalTextureSize = 0;
                long totalMeshSize    = 0;

                var serializableMaterials = data.GetMaterials();
                for (int mi = 0; mi < serializableMaterials.Count; ++mi)
                {
                    var material = serializableMaterials[mi];
                    for (int ti = 0; ti < material.GetTextureCount(); ++ti)
                    {
                        var texture = material.GetTexture(ti);
                        totalTextureSize += texture.BytesLength;

                        m_texture.Add(new KeyValuePair <string, string>(texture.TextureName, FormattingSize(texture.BytesLength)));
                    }
                }


                var serializableObjects = data.GetObjects();
                for (int oi = 0; oi < serializableObjects.Count; ++oi)
                {
                    var mesh           = serializableObjects[oi].GetMesh();
                    int meshSpaceUsage = mesh.GetSpaceUsage();

                    totalMeshSize += meshSpaceUsage;
                    m_mesh.Add(new KeyValuePair <string, string>(mesh.Name, FormattingSize(meshSpaceUsage)));
                }

                m_totalTexture = FormattingSize(totalTextureSize);
                m_totalMesh    = FormattingSize(totalMeshSize);
            }
        }
        public void Build(SpaceNode rootNode, DisposableList <HLODBuildInfo> infos, GameObject root,
                          float cullDistance, float lodDistance, bool writeNoPrefab, bool extractMaterial, Action <float> onProgress)
        {
            dynamic options = m_streamingOptions;
            string  path    = options.OutputDirectory;

            HLODTreeNodeContainer container         = new HLODTreeNodeContainer();
            HLODTreeNode          convertedRootNode = ConvertNode(container, rootNode);

            //create settings if there is no settings.
            if (AddressableAssetSettingsDefaultObject.Settings == null)
            {
                AddressableAssetSettings.Create(AddressableAssetSettingsDefaultObject.kDefaultConfigFolder, AddressableAssetSettingsDefaultObject.kDefaultConfigAssetName, true, true);
            }


            var settings = AddressableAssetSettingsDefaultObject.GetSettings(true);
            var group    = GetGroup(settings, options.AddressablesGroupName);

            m_shaderGuids.Clear();

            if (onProgress != null)
            {
                onProgress(0.0f);
            }

            HLODData.TextureCompressionData compressionData;
            compressionData.PCTextureFormat      = options.PCCompression;
            compressionData.WebGLTextureFormat   = options.WebGLCompression;
            compressionData.AndroidTextureFormat = options.AndroidCompression;
            compressionData.iOSTextureFormat     = options.iOSCompression;
            compressionData.tvOSTextureFormat    = options.tvOSCompression;


            string filenamePrefix = $"{path}{root.name}";

            if (Directory.Exists(path) == false)
            {
                Directory.CreateDirectory(path);
            }

            Dictionary <int, HLODData> hlodDatas = new Dictionary <int, HLODData>();

            for (int i = 0; i < infos.Count; ++i)
            {
                if (hlodDatas.ContainsKey(infos[i].ParentIndex) == false)
                {
                    HLODData newData = new HLODData();
                    newData.CompressionData = compressionData;
                    hlodDatas.Add(infos[i].ParentIndex, newData);
                }

                HLODData data = hlodDatas[infos[i].ParentIndex];
                data.AddFromWokringObjects(infos[i].Name, infos[i].WorkingObjects);
                data.AddFromWorkingColliders(infos[i].Name, infos[i].Colliders);

                if (writeNoPrefab)
                {
                    if (hlodDatas.ContainsKey(i) == false)
                    {
                        HLODData newData = new HLODData();
                        newData.CompressionData = compressionData;
                        hlodDatas.Add(i, newData);
                    }

                    HLODData prefabData = hlodDatas[i];
                    var      spaceNode  = infos[i].Target;

                    for (int oi = 0; oi < spaceNode.Objects.Count; ++oi)
                    {
                        if (PrefabUtility.IsAnyPrefabInstanceRoot(spaceNode.Objects[oi]) == false)
                        {
                            prefabData.AddFromGameObject(spaceNode.Objects[oi]);
                        }
                    }
                }


                if (onProgress != null)
                {
                    onProgress((float)i / (float)infos.Count);
                }
            }


            if (extractMaterial)
            {
                ExtractMaterial(hlodDatas, filenamePrefix);
            }

            Dictionary <int, RootData> rootDatas = new Dictionary <int, RootData>();

            foreach (var item in hlodDatas)
            {
                string filename = $"{filenamePrefix}_group{item.Key}.hlod";
                using (Stream stream = new FileStream(filename, FileMode.Create))
                {
                    HLODDataSerializer.Write(stream, item.Value);
                    stream.Close();
                }

                AssetDatabase.ImportAsset(filename, ImportAssetOptions.ForceUpdate);
                RootData rootData = AssetDatabase.LoadAssetAtPath <RootData>(filename);
                m_manager.AddGeneratedResource(rootData);
                AddAddress(settings, group, rootData);

                rootDatas.Add(item.Key, rootData);
            }



            var addressableController = root.AddComponent <AddressableHLODController>();

            for (int i = 0; i < infos.Count; ++i)
            {
                var spaceNode    = infos[i].Target;
                var hlodTreeNode = convertedTable[infos[i].Target];

                for (int oi = 0; oi < spaceNode.Objects.Count; ++oi)
                {
                    int        highId = -1;
                    GameObject obj    = spaceNode.Objects[oi];

                    if (PrefabUtility.IsPartOfAnyPrefab(obj) == false)
                    {
                        GameObject rootGameObject = null;

                        if (rootDatas.ContainsKey(i))
                        {
                            rootGameObject = rootDatas[i].GetRootObject(obj.name);
                        }

                        if (rootGameObject != null)
                        {
                            GameObject go = PrefabUtility.InstantiatePrefab(rootGameObject) as GameObject;
                            go.transform.SetParent(obj.transform.parent);
                            go.transform.localPosition = obj.transform.localPosition;
                            go.transform.localRotation = obj.transform.localRotation;
                            go.transform.localScale    = obj.transform.localScale;

                            if (m_manager.IsGeneratedResource(obj))
                            {
                                m_manager.AddGeneratedResource(go);
                            }
                            else
                            {
                                m_manager.AddConvertedPrefabResource(go);
                            }

                            spaceNode.Objects.Add(go);

                            Object.DestroyImmediate(obj);
                            continue;
                        }
                    }

                    var address = GetAddress(spaceNode.Objects[oi]);
                    if (string.IsNullOrEmpty(address) && PrefabUtility.IsAnyPrefabInstanceRoot(spaceNode.Objects[oi]))
                    {
                        AddAddress(settings, group, spaceNode.Objects[oi]);
                        address = GetAddress(spaceNode.Objects[oi]);
                    }

                    if (address != null)
                    {
                        highId = addressableController.AddHighObject(address, spaceNode.Objects[oi]);
                    }
                    else
                    {
                        highId = addressableController.AddHighObject(spaceNode.Objects[oi]);
                    }

                    hlodTreeNode.HighObjectIds.Add(highId);
                }

                {
                    if (rootDatas[infos[i].ParentIndex].GetRootObject(infos[i].Name) != null)
                    {
                        string filename = $"{filenamePrefix}_group{infos[i].ParentIndex}.hlod";
                        int    lowId    = addressableController.AddLowObject(filename + "[" + infos[i].Name + "]");
                        hlodTreeNode.LowObjectIds.Add(lowId);
                    }
                }
            }

            var shaderEntriesAdded = new List <AddressableAssetEntry>();

            foreach (var shaderGuid in m_shaderGuids)
            {
                if (IsExistsInAddressables(shaderGuid) == false)
                {
                    shaderEntriesAdded.Add(settings.CreateOrMoveEntry(shaderGuid, group, false, false));
                }
            }
            settings.SetDirty(AddressableAssetSettings.ModificationEvent.EntryMoved, shaderEntriesAdded, true);
            m_shaderGuids.Clear();

            addressableController.Container    = container;
            addressableController.Root         = convertedRootNode;
            addressableController.CullDistance = cullDistance;
            addressableController.LODDistance  = lodDistance;
        }
Example #5
0
        public override void OnImportAsset(AssetImportContext ctx)
        {
            ctx.DependsOnCustomDependency("HLODSystemPlatform");

            var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(ctx.selectedBuildTarget);

            try
            {
                UpdateProgress(ctx.assetPath, 0, 1);
                using (Stream stream = new FileStream(ctx.assetPath, FileMode.Open, FileAccess.Read))
                {
                    HLODData      data           = HLODDataSerializer.Read(stream);
                    RootData      rootData       = RootData.CreateInstance <RootData>();
                    TextureFormat compressFormat = GetCompressFormat(data, buildTargetGroup);

                    int currentProgress = 0;
                    int maxProgress     = 0;

                    if (data.GetMaterials() != null)
                    {
                        maxProgress += data.GetMaterials().Count;
                    }
                    if (data.GetObjects() != null)
                    {
                        maxProgress += data.GetObjects().Count;
                    }
                    if (data.GetColliders() != null)
                    {
                        maxProgress += data.GetColliders().Count;
                    }

                    rootData.name = "Root";

                    var serializableMaterials = data.GetMaterials();
                    var loadedMaterials       = new Dictionary <string, Material>();
                    if (serializableMaterials != null)
                    {
                        for (int mi = 0; mi < serializableMaterials.Count; ++mi)
                        {
                            UpdateProgress(ctx.assetPath, currentProgress++, maxProgress);
                            var sm = serializableMaterials[mi];

                            if (loadedMaterials.ContainsKey(sm.ID))
                            {
                                continue;
                            }

                            Material mat = sm.To();
                            loadedMaterials.Add(sm.ID, mat);

                            if (string.IsNullOrEmpty(AssetDatabase.GetAssetPath(mat)) == false)
                            {
                                continue;
                            }

                            ctx.AddObjectToAsset(mat.name, mat);

                            for (int ti = 0; ti < sm.GetTextureCount(); ++ti)
                            {
                                HLODData.SerializableTexture st = sm.GetTexture(ti);
                                Texture2D texture = st.To();
                                EditorUtility.CompressTexture(texture, compressFormat,
                                                              TextureCompressionQuality.Normal);

                                mat.SetTexture(st.Name, texture);
                                ctx.AddObjectToAsset(texture.name, texture);
                            }

                            mat.EnableKeyword("_NORMALMAP");
                        }
                    }

                    var serializableObjects   = data.GetObjects();
                    var serializableColliders = data.GetColliders();
                    Dictionary <string, List <GameObject> >
                    createdGameObjects = new Dictionary <string, List <GameObject> >();
                    Dictionary <string, GameObject> createdColliders = new Dictionary <string, GameObject>();

                    if (serializableObjects != null)
                    {
                        for (int oi = 0; oi < serializableObjects.Count; ++oi)
                        {
                            UpdateProgress(ctx.assetPath, currentProgress++, maxProgress);

                            var        so = serializableObjects[oi];
                            GameObject go = new GameObject();
                            go.name = so.Name;

                            MeshFilter      mf          = go.AddComponent <MeshFilter>();
                            MeshRenderer    mr          = go.AddComponent <MeshRenderer>();
                            List <string>   materialIds = so.GetMaterialIds();
                            List <Material> materials   = new List <Material>();

                            for (int mi = 0; mi < materialIds.Count; ++mi)
                            {
                                string id = materialIds[mi];
                                if (loadedMaterials.ContainsKey(id))
                                {
                                    materials.Add(loadedMaterials[id]);
                                }
                                else
                                {
                                    string path = AssetDatabase.GUIDToAssetPath(id);
                                    if (string.IsNullOrEmpty(path) == false)
                                    {
                                        materials.Add(AssetDatabase.LoadAssetAtPath <Material>(path));
                                    }
                                    else
                                    {
                                        materials.Add(null);
                                    }
                                }
                            }

                            Mesh mesh = so.GetMesh().To();
                            mf.sharedMesh      = mesh;
                            mr.sharedMaterials = materials.ToArray();
                            mr.lightProbeUsage = so.LightProbeUsage;

                            ctx.AddObjectToAsset(mesh.name, mesh);

                            if (createdGameObjects.ContainsKey(go.name) == false)
                            {
                                createdGameObjects.Add(go.name, new List <GameObject>());
                            }

                            createdGameObjects[go.name].Add(go);
                        }
                    }

                    if (serializableColliders != null)
                    {
                        for (int ci = 0; ci < serializableColliders.Count; ++ci)
                        {
                            UpdateProgress(ctx.assetPath, currentProgress++, maxProgress);

                            var        sc = serializableColliders[ci];
                            GameObject go;

                            if (createdColliders.ContainsKey(sc.Name) == false)
                            {
                                createdColliders[sc.Name] = new GameObject("Collider");
                            }

                            go = createdColliders[sc.Name];

                            var collider = sc.CreateGameObject();
                            if (collider != null)
                            {
                                collider.name = "Collider" + ci;
                                collider.transform.SetParent(go.transform, true);
                            }
                        }
                    }

                    foreach (var objects in createdGameObjects.Values)
                    {
                        GameObject root;
                        if (objects.Count > 1)
                        {
                            root      = new GameObject();
                            root.name = objects[0].name;
                            for (int i = 0; i < objects.Count; ++i)
                            {
                                objects[i].name = objects[i].name + "_" + i;
                                objects[i].transform.SetParent(root.transform, true);
                            }
                        }
                        else
                        {
                            root = objects[0];
                        }

                        if (createdColliders.ContainsKey(root.name))
                        {
                            createdColliders[root.name].transform.SetParent(root.transform, true);
                        }

                        rootData.SetRootObject(root.name, root);
                        ctx.AddObjectToAsset(root.name, root);
                    }

                    ctx.AddObjectToAsset("Root", rootData);
                    ctx.SetMainObject(rootData);
                }
            }
            finally
            {
                EditorUtility.ClearProgressBar();
            }
        }
        public static void Write(Stream stream, HLODData data)
        {
            BinaryFormatter formatter = new BinaryFormatter();

            formatter.Serialize(stream, data);
        }
Example #7
0
        public void Build(SpaceNode rootNode, DisposableList <HLODBuildInfo> infos, GameObject root,
                          float cullDistance, float lodDistance, bool writeNoPrefab, bool extractMaterial, Action <float> onProgress)
        {
            dynamic options = m_streamingOptions;
            string  path    = options.OutputDirectory;

            HLODTreeNodeContainer container         = new HLODTreeNodeContainer();
            HLODTreeNode          convertedRootNode = ConvertNode(container, rootNode);

            if (onProgress != null)
            {
                onProgress(0.0f);
            }

            HLODData.TextureCompressionData compressionData;
            compressionData.PCTextureFormat      = options.PCCompression;
            compressionData.WebGLTextureFormat   = options.WebGLCompression;
            compressionData.AndroidTextureFormat = options.AndroidCompression;
            compressionData.iOSTextureFormat     = options.iOSCompression;
            compressionData.tvOSTextureFormat    = options.tvOSCompression;

            string filename = $"{path}{root.name}.hlod";

            if (Directory.Exists(path) == false)
            {
                Directory.CreateDirectory(path);
            }

            using (Stream stream = new FileStream(filename, FileMode.Create))
            {
                HLODData data = new HLODData();
                data.CompressionData = compressionData;

                for (int i = 0; i < infos.Count; ++i)
                {
                    data.AddFromWokringObjects(infos[i].Name, infos[i].WorkingObjects);
                    data.AddFromWorkingColliders(infos[i].Name, infos[i].Colliders);
                    if (onProgress != null)
                    {
                        onProgress((float)i / (float)infos.Count);
                    }
                }

                if (writeNoPrefab)
                {
                    for (int ii = 0; ii < infos.Count; ++ii)
                    {
                        var spaceNode = infos[ii].Target;

                        for (int oi = 0; oi < spaceNode.Objects.Count; ++oi)
                        {
                            if (PrefabUtility.IsAnyPrefabInstanceRoot(spaceNode.Objects[oi]) == false)
                            {
                                data.AddFromGameObject(spaceNode.Objects[oi]);
                            }
                        }
                    }
                }

                if (extractMaterial == true)
                {
                    ExtractMaterial(data, $"{path}{root.name}");
                }

                HLODDataSerializer.Write(stream, data);
            }

            AssetDatabase.ImportAsset(filename, ImportAssetOptions.ForceUpdate);
            RootData rootData = AssetDatabase.LoadAssetAtPath <RootData>(filename);

            m_manager.AddGeneratedResource(rootData);

            var        defaultController = root.AddComponent <DefaultHLODController>();
            GameObject hlodRoot          = new GameObject("HLODRoot");

            hlodRoot.transform.SetParent(root.transform, false);
            m_manager.AddGeneratedResource(hlodRoot);

            for (int ii = 0; ii < infos.Count; ++ii)
            {
                var spaceNode    = infos[ii].Target;
                var hlodTreeNode = convertedTable[infos[ii].Target];

                for (int oi = 0; oi < spaceNode.Objects.Count; ++oi)
                {
                    GameObject obj            = spaceNode.Objects[oi];
                    GameObject rootGameObject = rootData.GetRootObject(obj.name);
                    if (rootGameObject != null)
                    {
                        GameObject go = PrefabUtility.InstantiatePrefab(rootGameObject) as GameObject;
                        go.transform.SetParent(obj.transform.parent);
                        go.transform.localPosition = obj.transform.localPosition;
                        go.transform.localRotation = obj.transform.localRotation;
                        go.transform.localScale    = obj.transform.localScale;

                        int highId = defaultController.AddHighObject(go);
                        hlodTreeNode.HighObjectIds.Add(highId);

                        if (m_manager.IsGeneratedResource(obj))
                        {
                            m_manager.AddGeneratedResource(go);
                        }
                        else
                        {
                            m_manager.AddConvertedPrefabResource(go);
                        }

                        Object.DestroyImmediate(obj);
                    }
                    else
                    {
                        int highId = defaultController.AddHighObject(obj);
                        hlodTreeNode.HighObjectIds.Add(highId);
                    }
                }


                if (infos[ii].WorkingObjects.Count > 0)
                {
                    GameObject prefab = rootData.GetRootObject(infos[ii].Name);
                    if (prefab == null)
                    {
                        Debug.LogError("Prefab not found: " + infos[ii].Name);
                    }
                    else
                    {
                        GameObject go = PrefabUtility.InstantiatePrefab(prefab) as GameObject;
                        go.transform.SetParent(hlodRoot.transform, false);
                        go.SetActive(false);
                        int lowId = defaultController.AddLowObject(go);
                        hlodTreeNode.LowObjectIds.Add(lowId);
                        m_manager.AddGeneratedResource(go);
                    }
                }
            }

            defaultController.Container    = container;
            defaultController.Root         = convertedRootNode;
            defaultController.CullDistance = cullDistance;
            defaultController.LODDistance  = lodDistance;
        }
Example #8
0
        private void ExtractMaterial(HLODData hlodData, string filenamePrefix)
        {
            Dictionary <string, HLODData.SerializableMaterial> extractedMaterials = new Dictionary <string, HLODData.SerializableMaterial>();

            //save files to disk
            foreach (var hlodMaterial in hlodData.GetMaterials())
            {
                string id = hlodMaterial.ID;
                hlodMaterial.GetTextureCount();
                Material mat = hlodMaterial.To();

                for (int ti = 0; ti < hlodMaterial.GetTextureCount(); ++ti)
                {
                    var       serializeTexture = hlodMaterial.GetTexture(ti);
                    Texture2D texture          = serializeTexture.To();
                    byte[]    bytes            = texture.EncodeToPNG();
                    string    textureFilename  = $"{filenamePrefix}_{mat.name}_{serializeTexture.TextureName}.png";
                    File.WriteAllBytes(textureFilename, bytes);

                    AssetDatabase.ImportAsset(textureFilename);

                    var assetImporter   = AssetImporter.GetAtPath(textureFilename);
                    var textureImporter = assetImporter as TextureImporter;

                    if (textureImporter)
                    {
                        textureImporter.wrapMode    = serializeTexture.WrapMode;
                        textureImporter.sRGBTexture = GraphicsFormatUtility.IsSRGBFormat(serializeTexture.GraphicsFormat);
                        textureImporter.SaveAndReimport();
                    }

                    var storedTexture = AssetDatabase.LoadAssetAtPath <Texture>(textureFilename);
                    m_manager.AddGeneratedResource(storedTexture);
                    mat.SetTexture(serializeTexture.Name, storedTexture);
                }

                string matFilename = $"{filenamePrefix}_{mat.name}.mat";
                AssetDatabase.CreateAsset(mat, matFilename);
                AssetDatabase.ImportAsset(matFilename);

                var storedMaterial = AssetDatabase.LoadAssetAtPath <Material>(matFilename);
                m_manager.AddGeneratedResource(storedMaterial);


                using (WorkingMaterial newWM = new WorkingMaterial(Collections.Allocator.Temp, storedMaterial))
                {
                    var newSM = new HLODData.SerializableMaterial();
                    newSM.From(newWM);

                    extractedMaterials.Add(id, newSM);
                }
            }

            //apply to HLODData
            var materials = hlodData.GetMaterials();

            for (int i = 0; i < materials.Count; ++i)
            {
                if (extractedMaterials.ContainsKey(materials[i].ID) == false)
                {
                    continue;
                }

                materials[i] = extractedMaterials[materials[i].ID];
            }

            var objects = hlodData.GetObjects();

            for (int oi = 0; oi < objects.Count; ++oi)
            {
                var matIds = objects[oi].GetMaterialIds();

                for (int mi = 0; mi < matIds.Count; ++mi)
                {
                    if (extractedMaterials.ContainsKey(matIds[mi]) == false)
                    {
                        continue;
                    }

                    matIds[mi] = extractedMaterials[matIds[mi]].ID;
                }
            }
        }