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); }
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); }
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); }
private void SaveAsset(string assetName, string packageName) { if (m_info == null || string.IsNullOrEmpty(assetName) || string.IsNullOrEmpty(packageName)) { return; } Debug.Log("Starting save for asset " + assetName + " in package " + packageName); Package package = new Package(packageName); // Create lead vehicle prefab object VehicleInfo leadInfo = Util.InstantiateVehicleCopy(m_info); leadInfo.name = assetName; string[] steamTags = leadInfo.GetSteamTags(); // Set up trailers if (m_info.m_trailers != null && m_info.m_trailers.Length > 0) { // Keep track of added trailer prefabs to prevent duplicates Dictionary <string, VehicleInfo> addedTrailers = new Dictionary <string, VehicleInfo>(); for (int i = 0; i < m_info.m_trailers.Length; i++) { VehicleInfo trailerInfo; if (!addedTrailers.TryGetValue(m_info.m_trailers[i].m_info.name, out trailerInfo)) { Debug.Log("Trailer " + m_info.m_trailers[i].m_info.name + " not yet in package " + packageName); // Trailer not yet added to package trailerInfo = Util.InstantiateVehicleCopy(m_info.m_trailers[i].m_info); // Set placment mode to Procedural, this seems to be the only difference between engines (Automatic) and trailers (Procedural) trailerInfo.m_placementStyle = ItemClass.Placement.Procedural; // Include packagename in trailer, fixes Duplicate Prefab errors with multi .crp workshop uploads if (m_namingDropdown.selectedIndex == 0) { // TrailerPackageName0 trailerInfo.name = "Trailer" + packageName + addedTrailers.Count; Debug.Log("Renaming copy of trailer " + m_info.m_trailers[i].m_info.name + " to " + trailerInfo.name + " in package " + packageName); } else { // Default, Trailer0 trailerInfo.name = "Trailer" + addedTrailers.Count; } // Fix for 1.6 try { trailerInfo.m_mesh.name += packageName; } catch (Exception e) { Debug.LogException(e); Debug.Log("me"); }; try { trailerInfo.m_lodMesh.name += packageName; } catch (Exception e) { Debug.LogException(e); Debug.Log("lme"); }; try { trailerInfo.m_material.name += packageName; } catch (Exception e) { Debug.LogException(e); Debug.Log("m"); }; try { trailerInfo.m_lodMaterial.name += packageName; } catch (Exception e) { Debug.LogException(e); Debug.Log("lm"); }; // Needed because of the 'set engine' feature. trailerInfo.m_trailers = null; // Add stuff to package //PackVariationMasksInSubMeshNames(trailerInfo); // Don't actually do it for trailers, they should already have the name set correctly Package.Asset trailerAsset = package.AddAsset(trailerInfo.name, trailerInfo.gameObject); package.AddAsset(packageName + "_trailer" + addedTrailers.Count, new CustomAssetMetaData { assetRef = trailerAsset, name = trailerInfo.name, guid = Guid.NewGuid().ToString(), steamTags = steamTags, type = CustomAssetMetaData.Type.Trailer, timeStamp = DateTime.Now, dlcMask = AssetImporterAssetTemplate.GetAssetDLCMask(trailerInfo), mods = EmbedModInfo() }, UserAssetType.CustomAssetMetaData); // Don't need the locale // Update dictonary addedTrailers.Add(m_info.m_trailers[i].m_info.name, trailerInfo); Debug.Log("Finished adding trailer " + trailerInfo.name + " to package " + packageName); } leadInfo.m_trailers[i].m_info = trailerInfo; } } // Add lead vehicle to package var assetImport = FindObjectOfType <AssetImporterAssetImport>(); if (assetImport == null) { Util.LogWarning("Unable to find AssetImporterAssetImport object"); } else if (string.IsNullOrEmpty(leadInfo.m_Thumbnail)) // Regenerate thumbnails because they are pretty { var thumbnails = new Texture2D[5]; thumbnails[0] = null; assetImport.m_PreviewCamera.target = leadInfo.gameObject; AssetImporterThumbnails.CreateThumbnails(leadInfo.gameObject, null, assetImport.m_PreviewCamera); } FixSubmeshInfoNames(leadInfo); PackVariationMasksInSubMeshNames(leadInfo, true); Package.Asset leadAsset = package.AddAsset(assetName + "_Data", leadInfo.gameObject); // Previews Package.Asset steamPreviewRef = null; Package.Asset imageRef = null; // Add snapshot image if (m_snapshotPaths.Count > 0) { Image image = new Image(m_snapshotPaths[m_currentSnapshot]); image.Resize(644, 360); steamPreviewRef = package.AddAsset(assetName + "_SteamPreview", image, false, Image.BufferFileFormat.PNG, false, false); image = new Image(m_snapshotPaths[m_currentSnapshot]); image.Resize(400, 224); imageRef = package.AddAsset(assetName + "_Snapshot", image, false, Image.BufferFileFormat.PNG, false, false); } package.AddAsset(packageName, new CustomAssetMetaData { // Name of asset name = assetName, // Time created? timeStamp = DateTime.Now, // Reference to Asset (VehicleInfo GameObject) added to the package earlier assetRef = leadAsset, // Snapshot imageRef = imageRef, // Steam Preview steamPreviewRef = steamPreviewRef, // Steam tags steamTags = steamTags, // Asset GUID guid = Guid.NewGuid().ToString(), // Type of this asset type = CustomAssetMetaData.Type.Vehicle, // DLCs required for this asset dlcMask = AssetImporterAssetTemplate.GetAssetDLCMask(leadInfo), // Mods active when making asset mods = EmbedModInfo() }, UserAssetType.CustomAssetMetaData, false); // Set main asset to lead vehicle package.packageMainAsset = packageName; // Create and add locale Locale locale = new Locale(); locale.AddLocalizedString(new Locale.Key { m_Identifier = "VEHICLE_TITLE", m_Key = assetName + "_Data" }, assetName); package.AddAsset(assetName + "_Locale", locale, false); // Save package to file package.Save(GetSavePathName(packageName)); Debug.Log("Finished save for asset " + assetName + " in package " + packageName); m_info = null; isVisible = false; }
private void CreateComponents() { int headerHeight = 40; UIHelperBase uiHelper = new UIHelper(this); // Label UILabel label = AddUIComponent <UILabel>(); label.text = "Vehicles"; label.relativePosition = new Vector3(WIDTH / 2 - label.width / 2, 10); // Drag handle UIDragHandle handle = AddUIComponent <UIDragHandle>(); handle.target = this; handle.constrainToScreen = true; handle.width = WIDTH; handle.height = headerHeight; handle.relativePosition = Vector3.zero; // Dropdown m_vehicleDropdown = UIUtils.CreateDropDown(this); m_vehicleDropdown.width = WIDTH - 20; m_vehicleDropdown.relativePosition = new Vector3(10, headerHeight + 10); m_vehicleDropdown.eventSelectedIndexChanged += DropdownSelctionChanged; // Trailer panel m_trailerPanel = AddUIComponent <UIPanel>(); m_trailerPanel.size = Vector2.zero; m_trailerPanel.relativePosition = new Vector3(0, headerHeight + 50); UIHelper uiTrailerHelper = new UIHelper(m_trailerPanel); m_trailerPanelStart = m_trailerPanel.relativePosition; // Checkbox invert m_invertCheckbox = (UICheckBox)uiTrailerHelper.AddCheckbox("Is inverted", false, (b) => { if (!m_checkingEvents) { return; } if (m_vehicleDropdown.items.Length > 1) { m_mainVehicleInfo.m_trailers[m_vehicleDropdown.selectedIndex - 1].m_invertProbability = b ? 100 : 0; m_doorTool.UpdateMarkerVisibility(); } }); m_invertCheckbox.width = WIDTH - 20; m_invertCheckbox.relativePosition = new Vector3(10, 0); // Button engine m_engineButton = UIUtils.CreateButton(m_trailerPanel); m_engineButton.eventClicked += (c, b) => { if (!m_checkingEvents) { return; } if (m_vehicleDropdown.items.Length > 1) { m_mainVehicleInfo.m_trailers[m_vehicleDropdown.selectedIndex - 1].m_info = m_mainVehicleInfo; } }; m_engineButton.text = "Set engine"; m_engineButton.tooltip = "Sets this trailer to the same vehicle as the engine. Recommened to be used for the last trailer only."; m_engineButton.relativePosition = new Vector3(10, 30); // Button engine (copy) m_engineCopyButton = UIUtils.CreateButton(m_trailerPanel); m_engineCopyButton.eventClicked += (c, b) => { if (!m_checkingEvents) { return; } if (m_vehicleDropdown.items.Length > 1) { m_mainVehicleInfo.m_trailers[m_vehicleDropdown.selectedIndex - 1].m_info = GetEngineAsTrailerUnchecked(); } }; m_engineCopyButton.width = 140; m_engineCopyButton.text = "Set engine (copy)"; m_engineCopyButton.tooltip = "Sets this trailer to a copy of the engine. This means that you can edit this trailer's settings without it affecting the actual engine."; m_engineCopyButton.relativePosition = new Vector3(WIDTH - 10 - m_engineCopyButton.width, 30); // Button insert trailer m_insertTrailerButton = UIUtils.CreateButton(m_trailerPanel); m_insertTrailerButton.eventClicked += (c, b) => { if (!m_checkingEvents) { return; } InsertTrailer(m_selectedVehicleInfo, m_vehicleDropdown.selectedIndex); }; m_insertTrailerButton.text = "Duplicate"; m_insertTrailerButton.tooltip = "Insert another trailer of this type after the currently selected trailer."; m_insertTrailerButton.relativePosition = new Vector3(10, 70); // Button remove trailer m_removeTrailerButton = UIUtils.CreateButton(m_trailerPanel); m_removeTrailerButton.eventClicked += (c, b) => { if (!m_checkingEvents) { return; } RemoveTrailer(m_vehicleDropdown.selectedIndex - 1); }; m_removeTrailerButton.text = "Remove"; m_removeTrailerButton.tooltip = "Remove this trailer from the vehicle."; m_removeTrailerButton.relativePosition = new Vector3((WIDTH - m_removeTrailerButton.width) / 2, 70); // Button change trailer m_changeTrailerButton = UIUtils.CreateButton(m_trailerPanel); m_changeTrailerButton.eventClicked += (c, b) => { if (!m_checkingEvents) { return; } if (m_selectRef.isVisible) { return; } m_changeTrailerIndex = m_vehicleDropdown.selectedIndex - 1; // 0 is the engine, so we do -1 to get trailer index m_selectRefReason = LoadPanelReason.Trailer; AssetImporterAssetTemplate assetImporterAssetTemplate = m_selectRef.GetComponent <AssetImporterAssetTemplate>(); assetImporterAssetTemplate.ReferenceCallback = new AssetImporterAssetTemplate.ReferenceCallbackDelegate(OnConfirmLoad); assetImporterAssetTemplate.Reset(); // Get correct filter if (m_mainVehicleInfo.m_vehicleAI as TramBaseAI != null) { assetImporterAssetTemplate.RefreshWithFilter(AssetImporterAssetTemplate.Filter.TramTrailer); } else if (m_mainVehicleInfo.m_vehicleAI as TrainAI != null) { assetImporterAssetTemplate.RefreshWithFilter(AssetImporterAssetTemplate.Filter.TrainCars); } else if (m_mainVehicleInfo.m_vehicleAI as CarAI != null) { assetImporterAssetTemplate.RefreshWithFilter(AssetImporterAssetTemplate.Filter.CarTrailers); } else if (m_mainVehicleInfo.m_vehicleAI as HelicopterAI != null) { assetImporterAssetTemplate.RefreshWithFilter(AssetImporterAssetTemplate.Filter.HelicopterTrailer); } else { assetImporterAssetTemplate.RefreshWithFilter(AssetImporterAssetTemplate.Filter.Vehicles); } m_selectRef.isVisible = true; }; m_changeTrailerButton.text = "Change"; m_changeTrailerButton.tooltip = "Select a trailer asset to use for this trailer."; m_changeTrailerButton.relativePosition = new Vector3(WIDTH - 10 - m_changeTrailerButton.width, 70); // Light panel m_lightPanel = AddUIComponent <UIPanel>(); m_lightPanel.relativePosition = new Vector3(0, headerHeight + 160); m_lightPanel.size = Vector2.zero; UIHelper uiLightsHelper = new UIHelper(m_lightPanel); m_lightPanelStart = m_lightPanel.relativePosition; // Checkbox passenger light m_passengerLightCheckbox = (UICheckBox)uiLightsHelper.AddCheckbox("Has passenger light", false, (b) => { if (!m_checkingEvents) { return; } if (m_selectedVehicleInfo != null) { int index = Util.GetEffectIndex(m_selectedVehicleInfo, "Train Light Passenger"); if (b && index < 0) { // Add effect Util.AddEffect(m_selectedVehicleInfo, "Train Light Passenger"); } else if (!b && index >= 0) { // Remove effect Util.RemoveEffect(m_selectedVehicleInfo, index); } } }); m_passengerLightCheckbox.width = WIDTH - 20; m_passengerLightCheckbox.relativePosition = new Vector3(10, 0); // Lights dropdown m_lightDropdown = UIUtils.CreateDropDown(m_lightPanel); m_lightDropdown.width = WIDTH - 20; m_lightDropdown.relativePosition = new Vector3(10, 30); m_lightDropdown.eventSelectedIndexChanged += LightSelectionChanged; // Light add button m_lightAddButton = UIUtils.CreateButton(m_lightPanel); m_lightAddButton.text = "Add"; m_lightAddButton.tooltip = "Adds another light to the vehicle, if possible. Recommened to only use lights on front and/or rear vehicle(s)."; m_lightAddButton.relativePosition = new Vector3(10, 70); m_lightAddButton.eventClicked += (c, b) => { AddLight(); }; // Light remove button m_lightRemoveButton = UIUtils.CreateButton(m_lightPanel); m_lightRemoveButton.text = "Remove"; m_lightRemoveButton.tooltip = "Removes the light with the highest index from the vehicle."; m_lightRemoveButton.relativePosition = new Vector3(WIDTH - m_lightRemoveButton.width - 10, 70); m_lightRemoveButton.eventClicked += (c, b) => { RemoveLight(); }; // Light pos x m_lightPosXField = UIFloatField.CreateField("Pos X:", m_lightPanel); m_lightPosXField.panel.relativePosition = new Vector3(10, 110); m_lightPosXField.textField.eventTextChanged += (c, s) => { if (!m_checkingEvents) { return; } if (m_selectedVehicleInfo != null && m_selectedVehicleInfo.m_lightPositions?.Length > 0) { UIFloatField.FloatFieldHandler(m_lightPosXField.textField, s, ref m_selectedVehicleInfo.m_lightPositions[m_lightDropdown.selectedIndex].x); } }; m_lightPosXField.buttonUp.eventClicked += (c, b) => { if (!m_checkingEvents) { return; } m_lightPosXField.SetValue(m_selectedVehicleInfo.m_lightPositions[m_lightDropdown.selectedIndex].x + 0.1f); }; m_lightPosXField.buttonDown.eventClicked += (c, b) => { if (!m_checkingEvents) { return; } m_lightPosXField.SetValue(m_selectedVehicleInfo.m_lightPositions[m_lightDropdown.selectedIndex].x - 0.1f); }; // Light pos y m_lightPosYField = UIFloatField.CreateField("Pos Y:", m_lightPanel); m_lightPosYField.panel.relativePosition = new Vector3(10, 140); m_lightPosYField.textField.eventTextChanged += (c, s) => { if (!m_checkingEvents) { return; } if (m_selectedVehicleInfo != null && m_selectedVehicleInfo.m_lightPositions?.Length > 0) { UIFloatField.FloatFieldHandler(m_lightPosYField.textField, s, ref m_selectedVehicleInfo.m_lightPositions[m_lightDropdown.selectedIndex].y); } }; m_lightPosYField.buttonUp.eventClicked += (c, b) => { if (!m_checkingEvents) { return; } m_lightPosYField.SetValue(m_selectedVehicleInfo.m_lightPositions[m_lightDropdown.selectedIndex].y + 0.1f); }; m_lightPosYField.buttonDown.eventClicked += (c, b) => { if (!m_checkingEvents) { return; } m_lightPosYField.SetValue(m_selectedVehicleInfo.m_lightPositions[m_lightDropdown.selectedIndex].y - 0.1f); }; // Light pos z m_lightPosZField = UIFloatField.CreateField("Pos Z:", m_lightPanel); m_lightPosZField.panel.relativePosition = new Vector3(10, 170); m_lightPosZField.textField.eventTextChanged += (c, s) => { if (!m_checkingEvents) { return; } if (m_selectedVehicleInfo != null && m_selectedVehicleInfo.m_lightPositions?.Length > 0) { UIFloatField.FloatFieldHandler(m_lightPosZField.textField, s, ref m_selectedVehicleInfo.m_lightPositions[m_lightDropdown.selectedIndex].z); } }; m_lightPosZField.buttonUp.eventClicked += (c, b) => { if (!m_checkingEvents) { return; } m_lightPosZField.SetValue(m_selectedVehicleInfo.m_lightPositions[m_lightDropdown.selectedIndex].z + 0.1f); }; m_lightPosZField.buttonDown.eventClicked += (c, b) => { if (!m_checkingEvents) { return; } m_lightPosZField.SetValue(m_selectedVehicleInfo.m_lightPositions[m_lightDropdown.selectedIndex].z - 0.1f); }; // Effect panel button m_effectButton = m_saveButton = UIUtils.CreateButton(this); m_effectButton.text = "Effect Editor"; m_effectButton.width = (WIDTH - 20); m_effectButton.relativePosition = new Vector3(10, m_lightPanel.relativePosition.y + 200); m_effectButton.eventClicked += (c, b) => { if (m_mainVehicleInfo != null && m_effectPanel != null) { m_effectPanel.Show(); } }; // Save button m_saveButton = UIUtils.CreateButton(this); m_saveButton.text = "Save Asset"; m_saveButton.width = (WIDTH - 30) / 2; m_saveButton.relativePosition = new Vector3(10, m_effectButton.relativePosition.y + m_effectButton.height + 10); m_saveButton.eventClicked += (c, b) => { if (m_mainVehicleInfo != null && m_savePanel != null) { m_savePanel.ShowForAsset(m_mainVehicleInfo); } }; // Load button m_loadButton = UIUtils.CreateButton(this); m_loadButton.text = "Load Asset"; m_loadButton.width = (WIDTH - 30) / 2; m_loadButton.relativePosition = new Vector3(20 + m_saveButton.width, m_effectButton.relativePosition.y + m_effectButton.height + 10); m_loadButton.eventClicked += (c, b) => { if (m_selectRef.isVisible) { return; } m_selectRefReason = LoadPanelReason.Full; AssetImporterAssetTemplate assetImporterAssetTemplate = m_selectRef.GetComponent <AssetImporterAssetTemplate>(); assetImporterAssetTemplate.ReferenceCallback = new AssetImporterAssetTemplate.ReferenceCallbackDelegate(OnConfirmLoad); assetImporterAssetTemplate.Reset(); assetImporterAssetTemplate.RefreshWithFilter(AssetImporterAssetTemplate.Filter.Vehicles); m_selectRef.isVisible = true; }; m_checkingEvents = true; }
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); }
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); }
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); }