Example #1
0
        public static string SafeGetAssetDesc(CustomAssetMetaData metaData, Package package)
        {
            string localeID;

            if (metaData.type == CustomAssetMetaData.Type.Building)
            {
                localeID = "BUILDING_DESC";
            }
            else if (metaData.type == CustomAssetMetaData.Type.Prop)
            {
                localeID = "PROPS_DESC";
            }
            else if (metaData.type == CustomAssetMetaData.Type.Tree)
            {
                localeID = "TREE_DESC";
            }
            else
            {
                if (metaData.type != CustomAssetMetaData.Type.Road)
                {
                    return(metaData.name);
                }
                localeID = "NET_DESC";
            }
            return(SafeGetAssetString(localeID, metaData.name, package));
        }
Example #2
0
        void AddToQueue(List <Package.Asset>[] queues, CustomAssetMetaData meta, int offset, bool dontSpawn)
        {
            Package.Asset assetRef = meta.assetRef;

            if (assetRef == null)
            {
                Util.DebugPrint(meta.name, " Warning : NULL asset");
                return;
            }

            CustomAssetMetaData.Type type = meta.type;
            Package package  = assetRef.package;
            string  fullName = type < CustomAssetMetaData.Type.RoadElevation ? assetRef.fullName : PillarOrElevationName(package.packageName, assetRef.name);

            if (!IsDuplicate(fullName, allLoads[(int)type], package))
            {
                queues[loadQueueIndex[(int)type] + offset].Add(assetRef);
                metaTypes[assetRef.fullName] = type;

                if (dontSpawn)
                {
                    dontSpawnNormally.Add(fullName);
                }

                if (type == CustomAssetMetaData.Type.Citizen)
                {
                    citizenMetaDatas[fullName] = meta;
                }
            }
        }
Example #3
0
        bool PropTreeTrailer(Package.Asset asset)
        {
            CustomAssetMetaData assetMetaData = null;

            try
            {
                bool wantBecauseEnabled = loadEnabled && IsEnabled(asset);

                if (!wantBecauseEnabled && !(loadUsed && refs.GotPropTreeTrailerPackage(asset.package.packageName)))
                {
                    return(false);
                }

                assetMetaData = asset.Instantiate <CustomAssetMetaData>();

                if (assetMetaData.type == CustomAssetMetaData.Type.Building || assetMetaData.type == CustomAssetMetaData.Type.Vehicle ||
                    assetMetaData.type == CustomAssetMetaData.Type.Unknown || (AssetImporterAssetTemplate.GetAssetDLCMask(assetMetaData) & notMask) != 0)
                {
                    return(false);
                }

                if (wantBecauseEnabled || loadUsed && refs.GotPropTreeAsset(assetMetaData.assetRef.fullName) ||
                    loadUsed && assetMetaData.type == CustomAssetMetaData.Type.Trailer && refs.GotTrailerAsset(assetMetaData.assetRef.fullName))
                {
                    PropTreeTrailerImpl(asset.package.packageName, assetMetaData.assetRef);
                }
            }
            catch (Exception ex)
            {
                Failed(assetMetaData?.assetRef, ex);
                // CODebugBase<LogChannel>.Warn(LogChannel.Modding, string.Concat(new object[] { ex.GetType(), ": Loading custom asset failed[", asset, "]\n", ex.Message }));
            }

            return(true);
        }
Example #4
0
        internal CustomAssetMetaData.Type GetMetaType(Package.Asset assetRef)
        {
            if (metaTypes.TryGetValue(assetRef.fullName, out CustomAssetMetaData.Type type))
            {
                return(type);
            }

            try
            {
                foreach (Package.Asset asset in assetRef.package.FilterAssets(UserAssetType.CustomAssetMetaData))
                {
                    CustomAssetMetaData meta = AssetDeserializer.Instantiate(asset) as CustomAssetMetaData;

                    if (meta?.assetRef != null)
                    {
                        metaTypes[meta.assetRef.fullName] = meta.type;
                    }
                }

                if (metaTypes.TryGetValue(assetRef.fullName, out type))
                {
                    return(type);
                }
            }
            catch (Exception) { }

            Util.DebugPrint("Cannot resolve metatype:", assetRef.fullName);
            return(CustomAssetMetaData.Type.Unknown);
        }
Example #5
0
        void AddToQueue(List <Package.Asset>[] queues, CustomAssetMetaData meta, CustomAssetMetaData.Type type, int offset, bool dontSpawn)
        {
            Package.Asset assetRef = meta.assetRef;

            if (assetRef == null)
            {
                Util.DebugPrint(meta.name, " Error : NULL asset");
                return;
            }

            if (assetRef.fullName == null)
            {
                Util.DebugPrint(meta.name, " Warning : NULL asset name");
            }

            Package package  = assetRef.package;
            string  fullName = type < CustomAssetMetaData.Type.RoadElevation ? assetRef.fullName : PillarOrElevationName(package.packageName, assetRef.name);

            if (!IsDuplicate(assetRef, type, queues))
            {
                int index = Math.Max(loadQueueIndex[(int)type] + offset, 0);
                queues[index].Add(assetRef);
                metaDatas[assetRef.fullName] = new SomeMetaData(meta.userDataRef, meta.name, type);

                if (dontSpawn)
                {
                    dontSpawnNormally.Add(fullName);
                }

                if (type == CustomAssetMetaData.Type.Citizen)
                {
                    citizenMetaDatas[fullName] = meta;
                }
            }
        }
Example #6
0
        public CustomAssetMetaData InstantiateAssetMetaData(Package.Asset asset)
        {
            //Profiler.Trace( "Instantiate asset start" );
            CustomAssetMetaData assetMetaData = asset.Instantiate <CustomAssetMetaData>();

            //Profiler.Trace( "Instantiate asset end" );
            return(assetMetaData);
        }
Example #7
0
        public static bool SaveTemplateAsset(TemplateAsset templateAsset)
        {
            SingletonMod <Mod> .Logger.Debug($"Start save template asset {templateAsset}");

            try
            {
                var meta = new CustomAssetMetaData()
                {
                    name      = $"{templateAsset.Template.Name}_{Guid.NewGuid().Unique()}",
                    timeStamp = DateTime.Now,
                    type      = CustomAssetMetaData.Type.Unknown,
                    dlcMask   = SteamHelper.DLC_BitMask.None,
                    steamTags = new string[] { "Marking" },
                    guid      = templateAsset.Template.Id.ToString(),
                };

                var package = new Package(templateAsset.IsWorkshop ? templateAsset.WorkshopId.ToString() : meta.name)
                {
                    packageMainAsset = meta.name,
                    packageAuthor    = $"steamid:{TemplateManager.UserId}",
                };

                var gameObject  = new GameObject(typeof(MarkingInfo).Name);
                var markingInfo = gameObject.AddComponent <MarkingInfo>();
                markingInfo.data = GetString(templateAsset.Template.ToXml());
                meta.assetRef    = package.AddAsset($"{meta.name}_Data", markingInfo.gameObject);

                if (templateAsset.Preview is Image image)
                {
                    meta.imageRef = package.AddAsset(templateAsset.MetaPreview, image, false, Image.BufferFileFormat.PNG, false, false);
                }

                if (templateAsset.SeparatePreview && templateAsset.SteamPreview is Image steamImage)
                {
                    meta.steamPreviewRef = package.AddAsset(templateAsset.MetaSteamPreview, steamImage, false, Image.BufferFileFormat.PNG, false, false);
                }
                else
                {
                    meta.steamPreviewRef = meta.imageRef;
                }

                package.AddAsset(meta.name, meta, UserAssetType.CustomAssetMetaData);

                var path = Path.Combine(DataLocation.assetsPath, PathUtils.AddExtension(PathEscaper.Escape(templateAsset.FileName), PackageManager.packageExtension));
                package.Save(path);

                SingletonMod <Mod> .Logger.Debug($"Template asset saved to {path}");

                return(true);
            }
            catch (Exception error)
            {
                SingletonMod <Mod> .Logger.Error($"Could not save template asset", error);

                return(false);
            }
        }
Example #8
0
        internal void AddPackage(Package p, CustomAssetMetaData lastmeta, bool enabled, bool useddir)
        {
            Package.Asset mainAssetRef = lastmeta.assetRef ?? AssetLoader.FindMainAssetRef(p);
            string        fullName     = mainAssetRef?.fullName;

            if (!string.IsNullOrEmpty(fullName))
            {
                assets[fullName] = new Available(mainAssetRef, lastmeta.type, enabled, useddir);
            }
        }
Example #9
0
        public GameObject InstantiateAssetGameObject(CustomAssetMetaData assetMetaData)
        {
            //Profiler.Trace( "Instantiate asset game object start {0}", notFound.Count() );
            var go = assetMetaData.assetRef.Instantiate <GameObject>();

            //Profiler.Trace( "Instantiate asset game object {0} end {1}", go, notFound.Count() );
            go.name = assetMetaData.assetRef.package.packageName + "." + assetMetaData.assetRef.name;
            go.SetActive(false);
            return(go);
        }
Example #10
0
 void ReadMetaData(Package package)
 {
     foreach (Package.Asset asset in package.FilterAssets(UserAssetType.CustomAssetMetaData))
     {
         try
         {
             CustomAssetMetaData meta = AssetDeserializer.Instantiate(asset) as CustomAssetMetaData;
             metaDatas[meta.assetRef.fullName] = new SomeMetaData(meta.userDataRef, meta.name, meta.type);
         }
         catch (Exception)
         {
             Util.DebugPrint("!Cannot read metadata from", package.packageName);
         }
     }
 }
Example #11
0
        static NetInfo GetOriginalNetInfo(CustomAssetMetaData listingMetaData)
        {
            LogCalled();
            var roadName = listingMetaData.name;

            if (!roadName.EndsWith("_Data"))
            {
                roadName = roadName + "_Data";
            }
            var packageName  = listingMetaData.assetRef.package.packageName;
            var originalName = packageName + "." + PackageHelper.StripName(roadName);

            Log.Debug("searching for raod:" + originalName);
            var ret = PrefabCollection <NetInfo> .FindLoaded(originalName);

            Log.Debug("GetOriginalNetInfo() returns " + ret.ToSTR());
            return(ret);
        }
Example #12
0
        public static string[] Tags(this CustomAssetMetaData metadata)
        {
            var tags = new List <string>();

            foreach (var tag in metadata.steamTags)
            {
                if (Tag2Category.TryGetValue(tag, out var cat))
                {
                    tags.Add(cat);
                }
                else
                {
                    tags.Add(tag);
                }
            }

            return(tags.ToArray());
        }
Example #13
0
        void Load(Package.Asset asset)
        {
            string fullName = null;

            try
            {
                CustomAssetMetaData assetMetaData = asset.Instantiate <CustomAssetMetaData>();

                // Always remember: assetRef may point to another package because the deserialization method accepts any asset with a matching checksum.
                // There is a bug in the 1.6.0 game update in this.
                fullName = asset.package.packageName + "." + assetMetaData.assetRef.name;

                CustomAssetMetaData.Type type = assetMetaData.type;
                bool spawnNormally            = (type == CustomAssetMetaData.Type.Building || type == CustomAssetMetaData.Type.SubBuilding) ?
                                                loadEnabled && IsEnabled(asset) || loadUsed && UsedAssets.instance.GotBuilding(fullName) : true;
                stack.Clear();
                LoadImpl(fullName, assetMetaData.assetRef, spawnNormally);
            }
            catch (Exception e)
            {
                AssetFailed(fullName ?? asset.fullName, e);
            }
        }
Example #14
0
        bool BuildingVehicle(Package.Asset asset, bool includedInStyle)
        {
            CustomAssetMetaData assetMetaData = null;

            try
            {
                bool wantBecauseEnabled = loadEnabled && IsEnabled(asset);

                if (!includedInStyle && !wantBecauseEnabled && !(loadUsed && refs.GotBuildingVehiclePackage(asset.package.packageName)))
                {
                    return(false);
                }

                assetMetaData = asset.Instantiate <CustomAssetMetaData>();

                if (assetMetaData.type != CustomAssetMetaData.Type.Building && assetMetaData.type != CustomAssetMetaData.Type.Vehicle &&
                    assetMetaData.type != CustomAssetMetaData.Type.Unknown || (AssetImporterAssetTemplate.GetAssetDLCMask(assetMetaData) & notMask) != 0)
                {
                    return(false);
                }

                bool wanted = wantBecauseEnabled || loadUsed && refs.GotBuildingVehicleAsset(assetMetaData.assetRef.fullName);

                if (includedInStyle || wanted)
                {
                    BuildingVehicleImpl(asset.package.packageName, assetMetaData.assetRef, wanted);
                }
            }
            catch (Exception ex)
            {
                Failed(assetMetaData?.assetRef, ex);
                // CODebugBase<LogChannel>.Warn(LogChannel.Modding, string.Concat(new object[] { ex.GetType(), ": Loading custom asset failed:[", asset, "]\n", ex.Message }));
            }

            return(true);
        }
Example #15
0
 bool IsCommonBuilding(String fullName, Package.Asset asset, CustomAssetMetaData assetMetaData)
 {
     CustomAssetMetaData.Type type = assetMetaData.type;
     return(type == CustomAssetMetaData.Type.Building || type == CustomAssetMetaData.Type.SubBuilding);
 }
Example #16
0
        public bool LoadAsset(string fullName, Package.Asset asset, bool mainAsset = false)
        {
            if (asset == null)
            {
                return(StoreNotFoundName(fullName));
            }

            Profiler.Info("Loading asset {0}", asset.fullName);

            try
            {
                Profiler.Trace("Clearing stack");
                stack.Clear();

                if (mainAsset)
                {
                    Profiler.Info("Pushing {0} on stack", fullName);
                    stack.Push(fullName);
                }

                Profiler.Info("Stack count {0}, current {1}", stack.Count, Current);

                CustomAssetMetaData assetMetaData = InstantiateAssetMetaData(asset);

                // Always remember: assetRef may point to another package because the deserialization method accepts any asset with a matching checksum.
                // There is a bug in the 1.6.0 game update in this.
                fullName = asset.package.packageName + "." + assetMetaData.assetRef.name;

                //impl
                GameObject assetGameObject = InstantiateAssetGameObject(assetMetaData);
                assetGameObject.name = fullName;

                PrefabInfo assetPrefabInfo = InstantiateAssetPrefab(assetGameObject);

                if (mainAsset && Settings.instance.installDependencies && notFoundIndirect.Count > 0)
                {
                    return(HotloadManager.DeferLoad(fullName, notFoundIndirect.Keys.ToList()));
                }


                RegisterPrefab(fullName, asset, assetMetaData, assetPrefabInfo, assetGameObject);
                //impl
                if (mainAsset)
                {
                    Profiler.Trace("Popping {0} from stack", stack.Peek());
                    stack.Pop();
                }
                Profiler.Info("Stack count {0}", stack.Count);

                return(StorePrefabInfo(assetPrefabInfo));
            }
            catch (Exception e)
            {
                if (mainAsset)
                {
                    Profiler.Trace("Popping {0} from stack due to error {1}", stack.Peek(), e.Message);
                    stack.Pop();
                }
                Profiler.Error("Cannot load " + fullName, e);
                StoreFailedAssetName(fullName ?? asset.fullName, e);
                return(false);
            }
        }
Example #17
0
        Package.Asset[] GetLoadQueue(HashSet <string> styleBuildings)
        {
            Package[] packages = PackageManager.allPackages.ToArray();
            Array.Sort(packages, (a, b) => string.Compare(a.packageName, b.packageName));
            List <Package.Asset>       assets = new List <Package.Asset>(8);
            List <CustomAssetMetaData> metas  = new List <CustomAssetMetaData>(8);

            // Why this load order? By having related and identical assets close to each other, we get more loader cache hits (of meshes and textures)
            // in Sharing. We also get faster disk reads.
            // [0] propvar and prop, citizen  [1] prop, tree  [2] pillar and elevation and road  [3] road
            // [4] sub-building and building  [5] building    [6] trailer and vehicle            [7] vehicle
            List <Package.Asset>[] queues = { new List <Package.Asset>(4), new List <Package.Asset>(64), new List <Package.Asset>(4),  new List <Package.Asset>(4),
                                              new List <Package.Asset>(4), new List <Package.Asset>(64), new List <Package.Asset>(32), new List <Package.Asset>(32) };

            SteamHelper.DLC_BitMask notMask = ~SteamHelper.GetOwnedDLCMask();
            bool loadEnabled = Settings.settings.loadEnabled, loadUsed = Settings.settings.loadUsed, report = loadUsed && Settings.settings.reportAssets;

            //PrintPackages(packages);

            foreach (Package p in packages)
            {
                CustomAssetMetaData meta = null;

                try
                {
                    assets.Clear();
                    assets.AddRange(p.FilterAssets(UserAssetType.CustomAssetMetaData));

                    if (assets.Count == 0)
                    {
                        continue;
                    }

                    if (report)
                    {
                        AssetReport.instance.AddPackage(p);
                    }

                    bool enabled = loadEnabled && IsEnabled(p);

                    if (assets.Count == 1) // the common case
                    {
                        bool want = enabled || styleBuildings.Contains(assets[0].fullName);

                        // Fast exit.
                        if (!want && !(loadUsed && UsedAssets.instance.GotPackage(p.packageName)))
                        {
                            continue;
                        }

                        meta = AssetDeserializer.Instantiate(assets[0]) as CustomAssetMetaData;
                        bool used = loadUsed && UsedAssets.instance.IsUsed(meta);

                        if (used || want && (AssetImporterAssetTemplate.GetAssetDLCMask(meta) & notMask) == 0)
                        {
                            CustomAssetMetaData.Type type = meta.type;
                            int offset = type == CustomAssetMetaData.Type.Trailer || type == CustomAssetMetaData.Type.SubBuilding ||
                                         type == CustomAssetMetaData.Type.PropVariation || type >= CustomAssetMetaData.Type.RoadElevation ? -1 : 0;
                            AddToQueue(queues, meta, offset, !(enabled | used));
                        }
                    }
                    else
                    {
                        bool want = enabled;

                        // Fast exit.
                        if (!want)
                        {
                            for (int i = 0; i < assets.Count; i++)
                            {
                                want = want || styleBuildings.Contains(assets[i].fullName);
                            }

                            if (!want && !(loadUsed && UsedAssets.instance.GotPackage(p.packageName)))
                            {
                                continue;
                            }
                        }

                        metas.Clear();
                        bool used = false;

                        for (int i = 0; i < assets.Count; i++)
                        {
                            meta = AssetDeserializer.Instantiate(assets[i]) as CustomAssetMetaData;
                            metas.Add(meta);
                            want = want && (AssetImporterAssetTemplate.GetAssetDLCMask(meta) & notMask) == 0;
                            used = used || loadUsed && UsedAssets.instance.IsUsed(meta);
                        }

                        if (want | used)
                        {
                            metas.Sort((a, b) => b.type - a.type); // prop variation, sub-building, trailer, elevation, pillar before main asset
                            CustomAssetMetaData.Type type = metas[0].type;
                            int offset = type == CustomAssetMetaData.Type.Trailer || type == CustomAssetMetaData.Type.SubBuilding ||
                                         type == CustomAssetMetaData.Type.PropVariation || type >= CustomAssetMetaData.Type.RoadElevation ? -1 : 0;
                            bool dontSpawn = !(enabled | used);

                            for (int i = 0; i < metas.Count; i++)
                            {
                                AddToQueue(queues, metas[i], offset, dontSpawn);
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    AssetFailed(meta?.assetRef?.fullName ?? p.packageName + "." + p.packageMainAsset, e);
                }
            }

            Package.Asset[] queue = new Package.Asset[queues.Select(lst => lst.Count).Sum()];

            for (int i = 0, k = 0; i < queues.Length; k += queues[i].Count, i++)
            {
                queues[i].CopyTo(queue, k);
            }

            return(queue);
        }
Example #18
0
 /// <summary>
 /// Is the asset used in the city?
 /// </summary>
 internal bool IsUsed(CustomAssetMetaData meta)
 {
     Package.Asset assetRef = meta.assetRef;
     return(assetRef != null ? allAssets[(int)meta.type].Contains(assetRef.fullName) : false);
 }
Example #19
0
        bool RegisterPrefab(String fullName, Package.Asset asset, CustomAssetMetaData metaData, PrefabInfo info, GameObject go)
        {
            PropInfo pi = go.GetComponent <PropInfo>();

            if (pi != null)
            {
                if (pi.m_lodObject != null)
                {
                    pi.m_lodObject.SetActive(false);
                }

                if (StorePropName(fullName))
                {
                    PrefabCollection <PropInfo> .InitializePrefabs("Custom Assets", pi, null);

                    return(true);
                }
            }

            TreeInfo ti = go.GetComponent <TreeInfo>();

            if (ti != null && StoreTreeName(fullName))
            {
                PrefabCollection <TreeInfo> .InitializePrefabs("Custom Assets", ti, null);

                return(true);
            }

            BuildingInfo bi = go.GetComponent <BuildingInfo>();

            if (bi != null)
            {
                if (bi.m_lodObject != null)
                {
                    bi.m_lodObject.SetActive(false);
                }

                if (StoreBuildingName(fullName))
                {
                    PrefabCollection <BuildingInfo> .InitializePrefabs("Custom Assets", bi, null);

                    bi.m_dontSpawnNormally = !IsCommonBuilding(fullName, asset, metaData);

                    if (bi.GetAI() is IntersectionAI)
                    {
                        loadedIntersections.Add(fullName);
                    }

                    return(true);
                }
            }

            VehicleInfo vi = go.GetComponent <VehicleInfo>();

            if (vi != null)
            {
                if (vi.m_lodObject != null)
                {
                    vi.m_lodObject.SetActive(false);
                }

                if (StoreVehicleName(fullName))
                {
                    PrefabCollection <VehicleInfo> .InitializePrefabs("Custom Assets", vi, null);

                    return(true);
                }
            }

            return(false);
        }
Example #20
0
        List <Package.Asset>[] GetLoadQueues(IEnumerable <Package.Asset> assets)
        {
            Profiler.Info("Create Load queue for {0} assets", assets.Count());
            List <Package.Asset>[]  queues  = { new List <Package.Asset>(4), new List <Package.Asset>(64), new List <Package.Asset>(4), new List <Package.Asset>(64) };
            SteamHelper.DLC_BitMask notMask = ~SteamHelper.GetOwnedDLCMask();

            foreach (Package.Asset asset in assets)
            {
                string fullName = null;
                // Profiler.Trace( "Q {0} - {1} - {2} - {3}", asset, loadEnabled, IsEnabled( asset ), styleBuildings.Contains( asset.fullName ) );
                //Profiler.Trace( "Q {0} - {1} - {2}", asset, IsEnabled( asset ), styleBuildings);
                try
                {
                    //triggers calls to CustomSerialize
                    CustomAssetMetaData assetMetaData = asset.Instantiate <CustomAssetMetaData>();
                    //Profiler.Trace( "meta {0}", assetMetaData );
                    // Always remember: assetRef may point to another package because the deserialization method accepts any asset with the same checksum.
                    // Think of identical vehicle trailers in different crp's.
                    // There is a bug in the 1.6.0 game update in this.
                    fullName = asset.package.packageName + "." + assetMetaData.assetRef.name;

                    if ((AssetImporterAssetTemplate.GetAssetDLCMask(assetMetaData) & notMask) == 0)
                    {
                        switch (assetMetaData.type)
                        {
                        case CustomAssetMetaData.Type.Building:
                            if (!IsDuplicate(fullName, loadedBuildings, asset.package))
                            {
                                queues[3].Add(asset);
                            }
                            break;

                        case CustomAssetMetaData.Type.Prop:
                            if (!IsDuplicate(fullName, loadedProps, asset.package))
                            {
                                queues[1].Add(asset);
                            }
                            break;

                        case CustomAssetMetaData.Type.Tree:
                            if (!IsDuplicate(fullName, loadedTrees, asset.package))
                            {
                                queues[1].Add(asset);
                            }
                            break;

                        case CustomAssetMetaData.Type.Vehicle:
                            if (!IsDuplicate(fullName, loadedVehicles, asset.package))
                            {
                                queues[3].Add(asset);
                            }
                            break;

                        case CustomAssetMetaData.Type.Trailer:
                            if (!IsDuplicate(fullName, loadedVehicles, asset.package))
                            {
                                queues[1].Add(asset);
                            }
                            break;

                        case CustomAssetMetaData.Type.Unknown:
                            queues[3].Add(asset);
                            break;

                        case CustomAssetMetaData.Type.SubBuilding:
                            if (!IsDuplicate(fullName, loadedBuildings, asset.package))
                            {
                                queues[2].Add(asset);
                            }
                            break;

                        case CustomAssetMetaData.Type.PropVariation:
                            if (!IsDuplicate(fullName, loadedProps, asset.package))
                            {
                                queues[0].Add(asset);
                            }
                            break;
                        }
                    }
                }
                catch (Exception e)
                {
                    Profiler.Error("GetLoadQueues", e);
                    StoreFailedAssetName(fullName ?? asset.fullName, e);
                }
            }

            return(queues);
        }
Example #21
0
        public override void OnLevelLoaded(LoadMode mode)
        {
            Debug.Log("IconModifier: Patching icons");
            int patchCount = 0;

            // Load the selection filter LUT texture
            var stream = (UnmanagedMemoryStream)Assembly.GetAssembly(typeof(IconModifier)).GetManifestResourceStream("AssetIcons.Assets.SelectFilter.png");
            var data   = new BinaryReader(stream).ReadBytes((int)stream.Length);

            focusedFilterTexture = new Texture2D(1024, 32);
            focusedFilterTexture.LoadImage(data);

            // Build references to the assets for thumbnails and tooltips.
            var thumbnails = new Dictionary <string, Package.Asset>();
            var tooltips   = new Dictionary <string, Package.Asset>();

            foreach (Package package in PackageManager.allPackages)
            {
                foreach (Package.Asset asset in package)
                {
                    if (asset.type == UserAssetType.CustomAssetMetaData)
                    {
                        CustomAssetMetaData md = asset.Instantiate <CustomAssetMetaData>();
                        if (md.imageRef != null && !thumbnails.ContainsKey(package.packageName))
                        {
                            md.imageRef.Cache();
                            thumbnails.Add(package.packageName, md.imageRef);
                        }
                        if (md.steamPreviewRef != null && !tooltips.ContainsKey(package.packageName))
                        {
                            md.steamPreviewRef.Cache();
                            tooltips.Add(package.packageName, md.steamPreviewRef);
                        }
                    }
                }
            }

            // Now go through all BuildingInfos and patch their icons.
            int infoCount = PrefabCollection <BuildingInfo> .LoadedCount();

            for (uint infoIndex = 0; infoIndex < infoCount; ++infoIndex)
            {
                BuildingInfo info = PrefabCollection <BuildingInfo> .GetLoaded(infoIndex);

                Texture2D thumbnailTexture = null;
                Texture2D tooltipTexture   = null;
                string    packageName      = info.name.Split('.')[0];

                if (!string.IsNullOrEmpty(info.m_Thumbnail))
                {
                    // This item has a thumbnail, check if it's a generated one.
                    GameObject gameObject = GameObject.Find(info.name);
                    if (gameObject != null)
                    {
                        UIButton uiButton = gameObject.GetComponent <UIButton>();

                        if (uiButton != null && uiButton.atlas != null)
                        {
                            var focusedSpriteInfo = uiButton.atlas[uiButton.focusedFgSprite];
                            if (focusedSpriteInfo != null && focusedSpriteInfo.texture != null)
                            {
                                long nonBlueCount = 0;
                                try
                                {
                                    Color32[] focusedPixels = focusedSpriteInfo.texture.GetPixels32();
                                    // The default atlas generator creates ugly dark blue focused icons
                                    // by removing everything from the red and green channel.  Detect these
                                    // by adding up the amount of red and green in the image.
                                    foreach (Color32 pixel in focusedPixels)
                                    {
                                        if (pixel.a > 32)
                                        {
                                            nonBlueCount += pixel.r + pixel.g;
                                        }
                                    }
                                }
                                catch (Exception)
                                {
                                    Debug.Log(String.Format("Failed to patch texture for {0}, skipping.", info.name));
                                    continue;
                                }

                                if (nonBlueCount < 10000)
                                {
                                    // This is a generated atlas.  Replace the focused icon by generating
                                    // a new atlas.  Include the tooltip if there is one.
                                    var thumbnailSpriteInfo = uiButton.atlas[uiButton.normalFgSprite];
                                    if (thumbnailSpriteInfo != null && thumbnailSpriteInfo.texture != null)
                                    {
                                        thumbnailTexture      = thumbnailSpriteInfo.texture;
                                        thumbnailTexture.name = info.name + "Icon";
                                    }
                                    var tooltipSpriteInfo = uiButton.atlas["tooltip"];
                                    if (tooltipSpriteInfo != null && thumbnailSpriteInfo.texture != null)
                                    {
                                        tooltipTexture      = tooltipSpriteInfo.texture;
                                        tooltipTexture.name = "tooltip";
                                    }
                                }
                            }
                        }
                    }
                }

                // Create a thumbnail based on the steam workshop image.
                if (string.IsNullOrEmpty(info.m_Thumbnail) && thumbnails.ContainsKey(packageName))
                {
                    thumbnailTexture = thumbnails[packageName].Instantiate <Texture2D>();
                    if (thumbnailTexture != null)
                    {
                        thumbnailTexture.wrapMode = TextureWrapMode.Clamp;
                        thumbnailTexture.name     = info.name + "Icon";
                        if (thumbnailTexture.width > thumbnailTexture.height)
                        {
                            ScaleTexture(thumbnailTexture, THUMBNAIL_SIZE, (THUMBNAIL_SIZE * thumbnailTexture.height) / thumbnailTexture.width);
                        }
                        else
                        {
                            ScaleTexture(thumbnailTexture, (THUMBNAIL_SIZE * thumbnailTexture.width) / thumbnailTexture.height, THUMBNAIL_SIZE);
                        }
                    }
                }

                // Create a tooltip image based on the steam workshop image.
                if (string.IsNullOrEmpty(info.m_InfoTooltipThumbnail) && tooltips.ContainsKey(packageName))
                {
                    tooltipTexture = tooltips[packageName].Instantiate <Texture2D>();
                    if (tooltipTexture != null)
                    {
                        // The tooltip texture name must match the info name, as that's the key value that's used
                        // (stored on UIButton.m_Tooltip, not by us).
                        tooltipTexture.name = info.name;

                        // Crop and scale the tooltip to TOOLTIP_WIDTH x TOOLTIP_HEIGHT
                        if (((float)tooltipTexture.width / (float)tooltipTexture.height) > (float)TOOLTIP_WIDTH / (float)TOOLTIP_HEIGHT)
                        {
                            // Picture is too wide, scale to TOOLTIP_HEIGHT pixels tall and then crop out the middle
                            ScaleTexture(tooltipTexture, (TOOLTIP_HEIGHT * tooltipTexture.width) / tooltipTexture.height, TOOLTIP_HEIGHT);
                            CropTexture(tooltipTexture, (tooltipTexture.width - TOOLTIP_WIDTH) / 2, 0, TOOLTIP_WIDTH, TOOLTIP_HEIGHT);
                        }
                        else if (((float)tooltipTexture.width / (float)tooltipTexture.height) < (float)TOOLTIP_WIDTH / (float)TOOLTIP_HEIGHT)
                        {
                            // Picture is too tall, scale to TOOLTIP_WIDTH pixels wide and then crop out the middle
                            ScaleTexture(tooltipTexture, TOOLTIP_WIDTH, (TOOLTIP_WIDTH * tooltipTexture.height) / tooltipTexture.width);
                            CropTexture(tooltipTexture, 0, (tooltipTexture.height - TOOLTIP_HEIGHT) / 2, TOOLTIP_WIDTH, TOOLTIP_HEIGHT);
                        }
                        else
                        {
                            // Picture is the right aspect ratio, just scale it
                            ScaleTexture(tooltipTexture, TOOLTIP_WIDTH, TOOLTIP_HEIGHT);
                        }
                    }
                }

                // Build these textures into an atlas.
                Texture2D[] textures;
                if (thumbnailTexture != null)
                {
                    if (tooltipTexture != null)
                    {
                        textures = new Texture2D[] { thumbnailTexture, null, null, null, null, tooltipTexture };
                    }
                    else
                    {
                        textures = new Texture2D[] { thumbnailTexture, null, null, null, null };
                    }
                    GenerateMissingThumbnailVariants(ref textures);
                }
                else if (tooltipTexture != null)
                {
                    textures = new Texture2D[] { tooltipTexture };
                }
                else
                {
                    // Hmm, we've failed to make any textures.  Move on to the next BuildingInfo.
                    continue;
                }

                UITextureAtlas atlas = AssetImporterThumbnails.CreateThumbnailAtlas(textures, info.name + "Atlas");

                if (thumbnailTexture != null)
                {
                    // Store the thumbnail atlas and icon names on the uiButton for this building.
                    GameObject gameObject = GameObject.Find(info.name);
                    if (gameObject != null)
                    {
                        UIButton uiButton = gameObject.GetComponent <UIButton>();

                        if (uiButton != null)
                        {
                            uiButton.atlas = atlas;

                            string baseIconName = info.name + "Icon";
                            uiButton.normalFgSprite   = baseIconName;
                            uiButton.focusedFgSprite  = baseIconName + "Focused";
                            uiButton.hoveredFgSprite  = baseIconName + "Hovered";
                            uiButton.pressedFgSprite  = baseIconName + "Pressed";
                            uiButton.disabledFgSprite = baseIconName + "Disabled";
                        }
                    }
                }

                if (tooltipTexture != null)
                {
                    // Store the tooltip atlas for this building.
                    info.m_InfoTooltipAtlas = atlas;

                    // This is actually the transition thumbnail, we set it to the default to blank
                    // out the tooltip during transitions, which matches the behaviour of the
                    // existing icons.
                    info.m_InfoTooltipThumbnail = "ThumbnailBuildingDefault";
                }

                ++patchCount;
            }

            Debug.Log(String.Format("IconModifier: Complete.  Patched {0} icons.", patchCount));
        }
        public override void OnLevelLoaded(LoadMode mode)
        {
            Debug.Log("IconModifier: Patching icons");
            loadCount  = 0;
            patchCount = 0;
            var stopwatch = System.Diagnostics.Stopwatch.StartNew();

            // Load the selection filter LUT texture
            var stream = (UnmanagedMemoryStream)Assembly.GetAssembly(typeof(IconModifier)).GetManifestResourceStream("AssetIcons.Assets.SelectFilter.png");
            var data   = new BinaryReader(stream).ReadBytes((int)stream.Length);

            focusedFilterTexture = new Texture2D(1024, 32);
            focusedFilterTexture.LoadImage(data);

            // Build references to the assets for thumbnails and tooltips.
            var thumbnails = new Dictionary <string, Package.Asset>();
            var tooltips   = new Dictionary <string, Package.Asset>();
            var timestamps = new Dictionary <string, DateTime>();

            foreach (Package package in PackageManager.allPackages)
            {
                foreach (Package.Asset asset in package)
                {
                    if (asset.type == UserAssetType.CustomAssetMetaData)
                    {
                        try
                        {
                            CustomAssetMetaData md = asset.Instantiate <CustomAssetMetaData>();
                            if (md.imageRef != null && !thumbnails.ContainsKey(package.packageName))
                            {
                                thumbnails.Add(package.packageName, md.imageRef);
                            }
                            if (md.steamPreviewRef != null && !tooltips.ContainsKey(package.packageName))
                            {
                                tooltips.Add(package.packageName, md.steamPreviewRef);
                            }
                            if (!timestamps.ContainsKey(package.packageName))
                            {
                                timestamps.Add(package.packageName, md.timeStamp);
                            }
                        }
                        catch (Exception e)
                        {
                            Debug.LogException(e);
                        }
                    }
                }
            }

            // Now go through all BuildingInfos and patch their icons.
            int infoCount = PrefabCollection <BuildingInfo> .LoadedCount();

            for (uint infoIndex = 0; infoIndex < infoCount; ++infoIndex)
            {
                try
                {
                    BuildingInfo info = PrefabCollection <BuildingInfo> .GetLoaded(infoIndex);

                    PatchIcons(info, thumbnails, tooltips, timestamps);
                }
                catch (Exception e)
                {
                    Debug.LogException(e);
                }
            }

            // Now go through all TreeInfos and patch their icons.
            infoCount = PrefabCollection <TreeInfo> .LoadedCount();

            for (uint infoIndex = 0; infoIndex < infoCount; ++infoIndex)
            {
                try
                {
                    TreeInfo info = PrefabCollection <TreeInfo> .GetLoaded(infoIndex);

                    PatchIcons(info, thumbnails, tooltips, timestamps);
                }
                catch (Exception e)
                {
                    Debug.LogException(e);
                }
            }

            stopwatch.Stop();

            Debug.Log(String.Format(
                          "IconModifier: Complete.  Patched {0} icons, loading {1} from cache in {2}.",
                          patchCount,
                          loadCount,
                          stopwatch.Elapsed));
        }
Example #23
0
        List <Package.Asset>[] GetLoadQueues(HashSet <string> styleBuildings)
        {
            Package.Asset[]         assets  = FilterAssets(UserAssetType.CustomAssetMetaData);
            List <Package.Asset>[]  queues  = { new List <Package.Asset>(4), new List <Package.Asset>(64), new List <Package.Asset>(4), new List <Package.Asset>(64) };
            SteamHelper.DLC_BitMask notMask = ~SteamHelper.GetOwnedDLCMask();

            for (int i = 0; i < assets.Length; i++)
            {
                Package.Asset asset    = assets[i];
                string        fullName = null;

                try
                {
                    bool wantThis = loadEnabled && IsEnabled(asset) || styleBuildings.Contains(asset.fullName);

                    // Make the first check fast.
                    if (wantThis || loadUsed && UsedAssets.instance.GotPackage(asset.package.packageName))
                    {
                        CustomAssetMetaData assetMetaData = asset.Instantiate <CustomAssetMetaData>();

                        // Always remember: assetRef may point to another package because the deserialization method accepts any asset with the same checksum.
                        // Think of identical vehicle trailers in different crp's.
                        // There is a bug in the 1.6.0 game update in this.
                        fullName = asset.package.packageName + "." + assetMetaData.assetRef.name;

                        if ((AssetImporterAssetTemplate.GetAssetDLCMask(assetMetaData) & notMask) == 0)
                        {
                            switch (assetMetaData.type)
                            {
                            case CustomAssetMetaData.Type.Building:
                                if ((wantThis || loadUsed && UsedAssets.instance.GotBuilding(fullName)) && !IsDuplicate(fullName, loadedBuildings, asset.package))
                                {
                                    queues[3].Add(asset);
                                }
                                break;

                            case CustomAssetMetaData.Type.Prop:
                                if ((wantThis || loadUsed && UsedAssets.instance.GotProp(fullName)) && !IsDuplicate(fullName, loadedProps, asset.package))
                                {
                                    queues[1].Add(asset);
                                }
                                break;

                            case CustomAssetMetaData.Type.Tree:
                                if ((wantThis || loadUsed && UsedAssets.instance.GotTree(fullName)) && !IsDuplicate(fullName, loadedTrees, asset.package))
                                {
                                    queues[1].Add(asset);
                                }
                                break;

                            case CustomAssetMetaData.Type.Vehicle:
                                if ((wantThis || loadUsed && UsedAssets.instance.GotVehicle(fullName)) && !IsDuplicate(fullName, loadedVehicles, asset.package))
                                {
                                    queues[3].Add(asset);
                                }
                                break;

                            case CustomAssetMetaData.Type.Trailer:
                                if ((wantThis || loadUsed && UsedAssets.instance.GotVehicle(fullName)) && !IsDuplicate(fullName, loadedVehicles, asset.package))
                                {
                                    queues[1].Add(asset);
                                }
                                break;

                            case CustomAssetMetaData.Type.Unknown:
                                if (wantThis)
                                {
                                    queues[3].Add(asset);
                                }
                                break;

                            case CustomAssetMetaData.Type.SubBuilding:
                                if ((wantThis || loadUsed && UsedAssets.instance.GotBuilding(fullName)) && !IsDuplicate(fullName, loadedBuildings, asset.package))
                                {
                                    queues[2].Add(asset);
                                }
                                break;

                            case CustomAssetMetaData.Type.PropVariation:
                                if ((wantThis || loadUsed && UsedAssets.instance.GotProp(fullName)) && !IsDuplicate(fullName, loadedProps, asset.package))
                                {
                                    queues[0].Add(asset);
                                }
                                break;
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    AssetFailed(fullName ?? asset.fullName, e);
                }
            }

            return(queues);
        }
Example #24
0
        Package.Asset[] GetLoadQueue(HashSet <string> styleBuildings)
        {
            Package.AssetType[] customAssets = { UserAssetType.CustomAssetMetaData };
            Package[]           packages     = { };

            try
            {
                packages = PackageManager.allPackages.Where(p => p.FilterAssets(customAssets).Any()).ToArray();
                Array.Sort(packages, PackageComparison);
            }
            catch (Exception e)
            {
                UnityEngine.Debug.LogException(e);
            }

            List <Package.Asset>       assets = new List <Package.Asset>(8);
            List <CustomAssetMetaData> metas  = new List <CustomAssetMetaData>(8);

            // Why this load order? By having related and identical assets close to each other, we get more loader cache hits (of meshes and textures)
            // in Sharing. We also get faster disk reads.
            // [0] propvar and prop, tree, citizen  [1] prop      [2] pillar and elevation and road  [3] road
            // [4] sub-building and building        [5] building  [6] trailer and vehicle            [7] vehicle
            List <Package.Asset>[] queues = { new List <Package.Asset>(32), new List <Package.Asset>(64), new List <Package.Asset>(4),  new List <Package.Asset>(4),
                                              new List <Package.Asset>(16), new List <Package.Asset>(64), new List <Package.Asset>(32), new List <Package.Asset>(32) };

            SteamHelper.DLC_BitMask notMask = ~SteamHelper.GetOwnedDLCMask();
            bool loadEnabled = Settings.settings.loadEnabled, loadUsed = Settings.settings.loadUsed;

            //PrintPackages(packages);

            foreach (Package p in packages)
            {
                CustomAssetMetaData meta = null;

                try
                {
                    assets.Clear();
                    assets.AddRange(p.FilterAssets(customAssets));
                    int count = assets.Count;

                    CustomDeserializer.instance.AddPackage(p);
                    bool enabled = loadEnabled && IsEnabled(p);

                    if (count == 1) // the common case
                    {
                        bool want = enabled || styleBuildings.Contains(assets[0].fullName);

                        // Fast exit.
                        if (!want && !(loadUsed && UsedAssets.instance.GotPackage(p.packageName)))
                        {
                            continue;
                        }

                        meta = AssetDeserializer.Instantiate(assets[0]) as CustomAssetMetaData;
                        bool used = loadUsed && UsedAssets.instance.IsUsed(meta);

                        if (used || want && (AssetImporterAssetTemplate.GetAssetDLCMask(meta) & notMask) == 0)
                        {
                            if (reportAssets)
                            {
                                AssetReport.instance.AddPackage(p, meta, want, used);
                            }

                            CustomAssetMetaData.Type type = meta.type;
                            int offset = type == CustomAssetMetaData.Type.Trailer || type == CustomAssetMetaData.Type.SubBuilding ||
                                         type == CustomAssetMetaData.Type.PropVariation || type >= CustomAssetMetaData.Type.RoadElevation ? -1 : 0;

                            AddToQueue(queues, meta, type, offset, !(enabled | used));
                        }
                    }
                    else
                    {
                        bool want = enabled;

                        // Fast exit.
                        if (!want)
                        {
                            for (int i = 0; i < count; i++)
                            {
                                want = want || styleBuildings.Contains(assets[i].fullName);
                            }

                            if (!want && !(loadUsed && UsedAssets.instance.GotPackage(p.packageName)))
                            {
                                continue;
                            }
                        }

                        metas.Clear();
                        bool used = false;

                        for (int i = 0; i < count; i++)
                        {
                            meta = AssetDeserializer.Instantiate(assets[i]) as CustomAssetMetaData;
                            metas.Add(meta);
                            want = want && (AssetImporterAssetTemplate.GetAssetDLCMask(meta) & notMask) == 0;
                            used = used || loadUsed && UsedAssets.instance.IsUsed(meta);
                        }

                        if (want | used)
                        {
                            metas.Sort((a, b) => b.type - a.type); // prop variation, sub-building, trailer, elevation, pillar before main asset
                            CustomAssetMetaData lastmeta = metas[count - 1];

                            if (reportAssets)
                            {
                                AssetReport.instance.AddPackage(p, lastmeta, want, used);
                            }

                            CustomAssetMetaData.Type type = metas[0].type;
                            int offset = type == CustomAssetMetaData.Type.Trailer || type == CustomAssetMetaData.Type.SubBuilding ||
                                         type == CustomAssetMetaData.Type.PropVariation || type >= CustomAssetMetaData.Type.RoadElevation ? -1 : 0;
                            bool treeVariations = lastmeta.type == CustomAssetMetaData.Type.Tree, dontSpawn = !(enabled | used);

                            for (int i = 0; i < count; i++)
                            {
                                CustomAssetMetaData      m = metas[i];
                                CustomAssetMetaData.Type t = m.type;

                                if (treeVariations && t == CustomAssetMetaData.Type.PropVariation)
                                {
                                    t = CustomAssetMetaData.Type.Tree;
                                }

                                AddToQueue(queues, m, t, offset, dontSpawn);
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    AssetFailed(meta?.assetRef, p, e);
                }
            }

            CheckSuspects();

            for (int i = 0; i < queuedLoads.Length; i++)
            {
                queuedLoads[i].Clear();
                queuedLoads[i] = null;
            }

            queuedLoads = null;
            Package.Asset[] queue = new Package.Asset[queues.Sum(lst => lst.Count)];

            for (int i = 0, k = 0; i < queues.Length; i++)
            {
                queues[i].CopyTo(queue, k);
                k += queues[i].Count;
                queues[i].Clear(); queues[i] = null;
            }

            return(queue);
        }