< Summary

Class:DCL.ABConverter.Utils
Assembly:ABConverter
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/ABConverter/Utils.cs
Covered lines:0
Uncovered lines:117
Coverable lines:117
Total lines:412
Line coverage:0% (0 of 117)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
ParseOption(...)0%2100%
ParseOption(...)0%2100%
ParseOptionExplicit(...)0%1321100%
Exit(...)0%6200%
MarkFolderForAssetBundleBuild(...)0%2100%
MarkAssetForAssetBundleBuild(...)0%2100%
Utils()0%2100%
CidToGuid(...)0%6200%
GetSceneCids(...)0%6200%
GetScenesCids(...)0%12300%
GetSceneMappingsData(...)0%12300%
GetPathsFromPairs(...)0%20400%
FixGltfRootInvalidUriCharacters(...)0%1101000%
CleanAssetBundleFolder(...)0%20400%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/ABConverter/Utils.cs

#LineLine coverage
 1using DCL.Helpers;
 2using GLTF.Schema;
 3using System;
 4using System.Collections.Generic;
 5using System.IO;
 6using System.Linq;
 7using System.Net.Http;
 8using System.Security.Cryptography;
 9using System.Text;
 10using System.Text.RegularExpressions;
 11using UnityEditor;
 12using UnityEngine;
 13using UnityEngine.Assertions;
 14using UnityEngine.Networking;
 15using static DCL.ContentServerUtils;
 16
 17namespace DCL.ABConverter
 18{
 19    public static class MeshUtils
 20    {
 21        public static Bounds BuildMergedBounds(Renderer[] renderers)
 22        {
 23            Bounds bounds = new Bounds();
 24
 25            for (int i = 0; i < renderers.Length; i++)
 26            {
 27                if (renderers[i] == null)
 28                    continue;
 29
 30                if (i == 0)
 31                    bounds = renderers[i].GetSafeBounds();
 32                else
 33                    bounds.Encapsulate(renderers[i].GetSafeBounds());
 34            }
 35
 36            return bounds;
 37        }
 38
 39        /// <summary>
 40        /// This get the renderer bounds with a check to ensure the renderer is at a safe position.
 41        /// If the renderer is too far away from 0,0,0, wasm target ensures a crash.
 42        /// </summary>
 43        /// <param name="renderer"></param>
 44        /// <returns>The bounds value if the value is correct, or a mocked bounds object with clamped values if its too 
 45        public static Bounds GetSafeBounds( this Renderer renderer )
 46        {
 47            // World extents are of 4800 world mts, so this limit far exceeds the world size.
 48            const float POSITION_OVERFLOW_LIMIT = 10000;
 49            const float POSITION_OVERFLOW_LIMIT_SQR = POSITION_OVERFLOW_LIMIT * POSITION_OVERFLOW_LIMIT;
 50
 51            if ( renderer.transform.position.sqrMagnitude > POSITION_OVERFLOW_LIMIT_SQR )
 52                return new Bounds( Vector3.one * POSITION_OVERFLOW_LIMIT, Vector3.one * 0.1f );
 53
 54            return renderer.bounds;
 55        }
 56    }
 57
 58    public static class PathUtils
 59    {
 60        /// <summary>
 61        /// Gets the relative path ("..\..\to_file_or_dir") of another file or directory (to) in relation to the current
 62        /// </summary>
 63        /// <param name="to"></param>
 64        /// <param name="from"></param>
 65        /// <returns></returns>
 66        public static string GetRelativePathTo(string from, string to)
 67        {
 68            var fromPath = Path.GetFullPath(from);
 69            var toPath = Path.GetFullPath(to);
 70
 71            var fromUri = new Uri(fromPath);
 72            var toUri = new Uri(toPath);
 73
 74            var relativeUri = fromUri.MakeRelativeUri(toUri);
 75            var relativePath = Uri.UnescapeDataString(relativeUri.ToString());
 76
 77            string result = FixDirectorySeparator(relativePath);
 78
 79            return result;
 80        }
 81
 82        /// <summary>
 83        /// Converts an absolute path to an Application.dataPath relative path.
 84        /// </summary>
 85        /// <param name="fullPath">the full path.</param>
 86        /// <returns>the Application.dataPath relative path</returns>
 87        public static string FullPathToAssetPath(string fullPath)
 88        {
 89            char ps = Path.DirectorySeparatorChar;
 90
 91            fullPath = fullPath.Replace('/', ps);
 92            fullPath = fullPath.Replace('\\', ps);
 93
 94            string pattern = $".*?\\{ps}(?<assetpath>Assets\\{ps}.*?$)";
 95
 96            var regex = new Regex(pattern);
 97
 98            var match = regex.Match(fullPath);
 99
 100            if (match.Success && match.Groups["assetpath"] != null)
 101                return match.Groups["assetpath"].Value;
 102
 103            return string.Empty;
 104        }
 105
 106        public static string FixDirectorySeparator(string path)
 107        {
 108            char ps = Path.DirectorySeparatorChar;
 109            path = path.Replace('/', ps);
 110            path = path.Replace('\\', ps);
 111            return path;
 112        }
 113
 114        /// <summary>
 115        /// Convert a path relative to Application.dataPath to an absolute path.
 116        /// </summary>
 117        /// <param name="assetPath">The relative path</param>
 118        /// <param name="overrideDataPath">Convert from an arbitrary path instead of Application.dataPath. Used for test
 119        /// <returns>The full path.</returns>
 120        public static string AssetPathToFullPath(string assetPath, string overrideDataPath = null)
 121        {
 122            assetPath = FixDirectorySeparator(assetPath);
 123
 124            string dataPath = overrideDataPath ?? Application.dataPath;
 125            dataPath = FixDirectorySeparator(dataPath);
 126
 127            char ps = Path.DirectorySeparatorChar;
 128            string dataPathWithoutAssets = dataPath.Replace($"{ps}Assets", "");
 129            return dataPathWithoutAssets + "/" + assetPath;
 130        }
 131
 132        public static long GetFreeSpace()
 133        {
 134            DriveInfo info = new DriveInfo(new DirectoryInfo(Application.dataPath).Root.FullName);
 135            return info.AvailableFreeSpace;
 136        }
 137    }
 138
 139    public static class Utils
 140    {
 0141        internal static bool ParseOption(string[] fullCmdArgs, string optionName, int argsQty, out string[] foundArgs) {
 142
 0143        internal static bool ParseOption(string optionName, int argsQty, out string[] foundArgs) { return ParseOptionExp
 144
 145        internal static bool ParseOptionExplicit(string[] rawArgsList, string optionName, int expectedArgsQty, out strin
 146        {
 0147            foundArgs = null;
 148
 0149            if (rawArgsList == null || rawArgsList.Length < expectedArgsQty + 1)
 0150                return false;
 151
 0152            expectedArgsQty = Mathf.Min(expectedArgsQty, 100);
 153
 0154            var foundArgsList = new List<string>();
 0155            int argState = 0;
 156
 0157            for (int i = 0; i < rawArgsList.Length; i++)
 158            {
 159                switch (argState)
 160                {
 161                    case 0:
 0162                        if (rawArgsList[i] == "-" + optionName)
 163                        {
 0164                            argState++;
 165                        }
 166
 0167                        break;
 168                    default:
 0169                        foundArgsList.Add(rawArgsList[i]);
 0170                        argState++;
 171                        break;
 172                }
 173
 0174                if (argState > 0 && foundArgsList.Count == expectedArgsQty)
 175                    break;
 176            }
 177
 0178            if (argState == 0 || foundArgsList.Count < expectedArgsQty)
 0179                return false;
 180
 0181            if (expectedArgsQty > 0)
 0182                foundArgs = foundArgsList.ToArray();
 183
 0184            return true;
 185        }
 186
 187        internal static void Exit(int errorCode = 0)
 188        {
 0189            Debug.Log($"Process finished with code {errorCode}");
 190
 0191            if (Application.isBatchMode)
 0192                EditorApplication.Exit(errorCode);
 0193        }
 194
 195        internal static void MarkFolderForAssetBundleBuild(string fullPath, string abName)
 196        {
 0197            string assetPath = PathUtils.GetRelativePathTo(Application.dataPath, fullPath);
 0198            assetPath = Path.GetDirectoryName(assetPath);
 0199            AssetImporter importer = AssetImporter.GetAtPath(assetPath);
 0200            importer.SetAssetBundleNameAndVariant(abName, "");
 0201        }
 202
 203        internal static void MarkAssetForAssetBundleBuild(IAssetDatabase assetDb, UnityEngine.Object asset, string abNam
 204        {
 0205            string assetPath = PathUtils.GetRelativePathTo(Application.dataPath, assetDb.GetAssetPath(asset));
 0206            var importer = AssetImporter.GetAtPath(assetPath);
 0207            importer.SetAssetBundleNameAndVariant(abName, "");
 0208        }
 209
 0210        public static MD5 md5 = new MD5CryptoServiceProvider();
 211
 212        public static string CidToGuid(string cid)
 213        {
 0214            byte[] data = md5.ComputeHash(Encoding.UTF8.GetBytes(cid));
 0215            StringBuilder sBuilder = new StringBuilder();
 216
 0217            for (int i = 0; i < data.Length; i++)
 218            {
 0219                sBuilder.Append(data[i].ToString("x2"));
 220            }
 221
 0222            return sBuilder.ToString();
 223        }
 224
 225        public static HashSet<string> GetSceneCids(IWebRequest webRequest, ApiTLD tld, Vector2Int coords, Vector2Int siz
 226        {
 0227            HashSet<string> sceneCids = new HashSet<string>();
 228
 0229            string url = GetScenesAPIUrl(tld, coords.x, coords.y, size.x, size.y);
 230
 0231            DownloadHandler downloadHandler = null;
 232
 233            try
 234            {
 0235                downloadHandler = webRequest.Get(url);
 0236            }
 0237            catch (HttpRequestException e)
 238            {
 0239                throw new Exception($"Request error! Parcels couldn't be fetched! -- {e.Message}", e);
 240            }
 241
 0242            ScenesAPIData scenesApiData = JsonUtility.FromJson<ScenesAPIData>(downloadHandler.text);
 0243            downloadHandler.Dispose();
 244
 0245            Assert.IsTrue(scenesApiData != null, "Invalid response from ScenesAPI");
 0246            Assert.IsTrue(scenesApiData.data != null, "Invalid response from ScenesAPI");
 247
 0248            foreach (var data in scenesApiData.data)
 249            {
 0250                sceneCids.Add(data.root_cid);
 251            }
 252
 0253            return sceneCids;
 254        }
 255
 256        public static HashSet<string> GetScenesCids(IWebRequest webRequest, ApiTLD tld, List<Vector2Int> coords)
 257        {
 0258            HashSet<string> sceneCids = new HashSet<string>();
 259
 0260            foreach (Vector2Int v in coords)
 261            {
 0262                string url = GetScenesAPIUrl(tld, v.x, v.y, 0, 0);
 263
 0264                DownloadHandler downloadHandler = null;
 265
 266                try
 267                {
 0268                    downloadHandler = webRequest.Get(url);
 0269                }
 0270                catch (HttpRequestException e)
 271                {
 0272                    throw new HttpRequestException($"Request error! Parcels couldn't be fetched! -- {url} -- {e.Message}
 273                }
 274
 0275                ScenesAPIData scenesApiData = JsonUtility.FromJson<ScenesAPIData>(downloadHandler.text);
 0276                downloadHandler.Dispose();
 277
 0278                Assert.IsTrue(scenesApiData != null, "Invalid response from ScenesAPI");
 0279                Assert.IsTrue(scenesApiData.data != null, "Invalid response from ScenesAPI");
 280
 0281                foreach (var data in scenesApiData.data)
 282                {
 0283                    sceneCids.Add(data.root_cid);
 284                }
 285            }
 286
 0287            return sceneCids;
 288        }
 289
 290        public static MappingsAPIData GetSceneMappingsData(IWebRequest webRequest, ApiTLD tld, string sceneCid)
 291        {
 0292            string url = GetMappingsAPIUrl(tld, sceneCid);
 293
 0294            DownloadHandler downloadHandler = null;
 295
 296            try
 297            {
 0298                downloadHandler = webRequest.Get(url);
 0299            }
 0300            catch (HttpRequestException e)
 301            {
 0302                throw new Exception($"Request error! mappings couldn't be fetched for scene {sceneCid}! -- {e.Message}")
 303            }
 304
 0305            MappingsAPIData parcelInfoApiData = JsonUtility.FromJson<MappingsAPIData>(downloadHandler.text);
 0306            downloadHandler.Dispose();
 307
 0308            if (parcelInfoApiData.data.Length == 0 || parcelInfoApiData.data == null)
 309            {
 0310                throw new Exception("MappingsAPIData is null?");
 311            }
 312
 0313            return parcelInfoApiData;
 314        }
 315
 316        /// <summary>
 317        /// Given a MappingPair list, returns a AssetPath list filtered by file extensions
 318        /// </summary>
 319        /// <param name="pairsToSearch">The MappingPair list to be filtered and converted</param>
 320        /// <param name="extensions">An array detailing the extensions to filter them</param>
 321        /// <returns>A dictionary that maps hashes to mapping pairs</returns>
 322        public static List<AssetPath> GetPathsFromPairs(string basePath, MappingPair[] pairsToSearch, string[] extension
 323        {
 0324            var tmpResult = new Dictionary<(string, string), AssetPath>();
 325
 0326            for (int i = 0; i < pairsToSearch.Length; i++)
 327            {
 0328                MappingPair mappingPair = pairsToSearch[i];
 329
 0330                bool hasExtension = extensions.Any((x) => mappingPair.file.ToLower().EndsWith(x));
 331
 0332                if (hasExtension)
 333                {
 0334                    if (!tmpResult.ContainsKey((mappingPair.hash, mappingPair.file)))
 0335                        tmpResult.Add((mappingPair.hash, mappingPair.file), new AssetPath(basePath, mappingPair));
 336                }
 337            }
 338
 0339            return tmpResult.Values.ToList();
 340        }
 341
 342        public static void FixGltfRootInvalidUriCharacters(GLTFRoot gltfRoot)
 343        {
 0344            if (gltfRoot == null)
 345            {
 0346                Debug.LogError("FixGltfRootInvalidUriCharacters >>> gltfRoot is null!");
 0347                return;
 348            }
 349
 0350            GLTFRoot root = gltfRoot;
 351
 0352            if (root.Images != null)
 353            {
 0354                foreach (GLTFImage image in root.Images)
 355                {
 0356                    if (!string.IsNullOrEmpty(image.Uri))
 357                    {
 0358                        bool isBase64 = URIHelper.IsBase64Uri(image.Uri);
 359
 0360                        if (!isBase64)
 361                        {
 0362                            image.Uri = image.Uri.Replace('/', Path.DirectorySeparatorChar);
 363                        }
 364                    }
 365                }
 366            }
 367
 0368            if (root.Buffers != null)
 369            {
 0370                foreach (GLTFBuffer buffer in root.Buffers)
 371                {
 0372                    if (!string.IsNullOrEmpty(buffer.Uri))
 373                    {
 0374                        bool isBase64 = URIHelper.IsBase64Uri(buffer.Uri);
 375
 0376                        if (!isBase64)
 377                        {
 0378                            buffer.Uri = buffer.Uri.Replace('/', Path.DirectorySeparatorChar);
 379                        }
 380                    }
 381                }
 382            }
 0383        }
 384
 385        public static void CleanAssetBundleFolder(IFile file, string pathToSearch, string[] assetBundlesList, Dictionary
 386        {
 0387            for (int i = 0; i < assetBundlesList.Length; i++)
 388            {
 0389                if (string.IsNullOrEmpty(assetBundlesList[i]))
 390                    continue;
 391
 392                try
 393                {
 394                    //NOTE(Brian): This is done for correctness sake, rename files to preserve the hash upper-case
 0395                    if (lowerToUpperDictionary.TryGetValue(assetBundlesList[i], out string hashWithUppercase))
 396                    {
 0397                        string oldPath = pathToSearch + assetBundlesList[i];
 0398                        string path = pathToSearch + hashWithUppercase;
 0399                        file.Move(oldPath, path);
 400                    }
 401
 0402                    string oldPathMf = pathToSearch + assetBundlesList[i] + ".manifest";
 0403                    file.Delete(oldPathMf);
 0404                }
 0405                catch (Exception e)
 406                {
 0407                    Debug.LogWarning("Error! " + e.Message);
 0408                }
 409            }
 0410        }
 411    }
 412}