/// <summary> /// Sets new enemy type. /// </summary> /// <param name="dfUnity">DaggerfallUnity singleton. Required for content readers and settings.</param> /// <param name="enemyType">Enemy type.</param> public void SetEnemy(DaggerfallUnity dfUnity, MobileEnemy enemy, MobileReactions reaction) { // Initial enemy settings summary.Enemy = enemy; summary.EnemyState = MobileStates.Move; summary.Enemy.Reactions = reaction; // Load enemy content int archive = GetTextureArchive(); if (TextureReplacement.CustomTextureExist(archive, TextureReplacement.enemyDefaultRecord, TextureReplacement.enemyDefaultFrame)) { summary.CustomMaterial.isCustom = true; } else { summary.CustomMaterial.isCustom = false; } CacheRecordSizesAndFrames(dfUnity, archive); AssignMeshAndMaterial(dfUnity, archive); // Apply enemy state and update orientation lastOrientation = -1; ApplyEnemyState(); // Raise setup flag summary.IsSetup = true; }
/// <summary> /// Gets terrain albedo texture array containing each terrain tile in a seperate array slice. /// </summary> /// <param name="archive">Archive index.</param> /// <param name="stayReadable">Texture should stay readable.</param> /// <param name="nonAlphaFormat">Non-alpha TextureFormat.</param> /// <returns>Texture2DArray or null</returns> public Texture2DArray GetTerrainAlbedoTextureArray( int archive, bool stayReadable = false, SupportedNonAlphaTextureFormats nonAlphaFormat = SupportedNonAlphaTextureFormats.RGB24) { // Load texture file and check count matches terrain tiles TextureFile textureFile = new TextureFile(Path.Combine(Arena2Path, TextureFile.IndexToFileName(archive)), FileUsage.UseMemory, true); int numSlices = 0; if (textureFile.RecordCount == 56) { numSlices = textureFile.RecordCount; } else { return(null); } Texture2DArray textureArray; if (TextureReplacement.CustomTextureExist(archive, 0, 0)) { Texture2D albedoMap = TextureReplacement.LoadCustomTexture(archive, 0, 0); textureArray = new Texture2DArray(albedoMap.width, albedoMap.height, numSlices, ParseTextureFormat(nonAlphaFormat), MipMaps); } else { textureArray = new Texture2DArray(textureFile.GetWidth(0), textureFile.GetWidth(1), numSlices, ParseTextureFormat(nonAlphaFormat), MipMaps); } // Rollout tiles into texture array for (int record = 0; record < textureFile.RecordCount; record++) { Color32[] albedo; if (TextureReplacement.CustomTextureExist(archive, record, 0)) { // Import custom texture Texture2D albedoMap = TextureReplacement.LoadCustomTexture(archive, record, 0); albedo = albedoMap.GetPixels32(); } else { // Create base image with gutter DFSize sz; albedo = textureFile.GetColor32(record, 0, -1, 0, out sz); } // Insert into texture array textureArray.SetPixels32(albedo, record, 0); } textureArray.Apply(true, !stayReadable); // Change settings for these textures textureArray.wrapMode = TextureWrapMode.Clamp; textureArray.anisoLevel = 8; return(textureArray); }
/// <summary> /// Adds light flats and prefabs. /// </summary> public static void AddLights( ref DFBlock blockData, Transform flatsParent, Transform lightsParent, DaggerfallBillboardBatch billboardBatch = null) { DaggerfallUnity dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady) { return; } // Do nothing if import option not enabled or missing prefab if (!dfUnity.Option_ImportLightPrefabs || dfUnity.Option_CityLightPrefab == null) { return; } // Iterate block flats for lights foreach (DFBlock.RmbBlockFlatObjectRecord obj in blockData.RmbBlock.MiscFlatObjectRecords) { // Add point lights if (obj.TextureArchive == TextureReader.LightsTextureArchive) { // Calculate position Vector3 billboardPosition = new Vector3( obj.XPos, -obj.YPos + blockFlatsOffsetY, obj.ZPos + BlocksFile.RMBDimension) * MeshReader.GlobalScale; // Import custom 3d gameobject instead of flat if (MeshReplacement.ImportCustomFlatGameobject(obj.TextureArchive, obj.TextureRecord, billboardPosition, flatsParent) != null) { continue; } // Add billboard to batch or standalone if ((billboardBatch != null) && (!TextureReplacement.CustomTextureExist(obj.TextureArchive, obj.TextureRecord))) { billboardBatch.AddItem(obj.TextureRecord, billboardPosition); } else { GameObject go = GameObjectHelper.CreateDaggerfallBillboardGameObject(obj.TextureArchive, obj.TextureRecord, flatsParent); go.transform.position = billboardPosition; AlignBillboardToBase(go); } // Import light prefab AddLight(dfUnity, obj, lightsParent); } } }
/// <summary> /// Add nature billboards. /// </summary> public static void AddNatureFlats( ref DFBlock blockData, Transform flatsParent, DaggerfallBillboardBatch billboardBatch = null, ClimateNatureSets climateNature = ClimateNatureSets.TemperateWoodland, ClimateSeason climateSeason = ClimateSeason.Summer) { DaggerfallUnity dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady) { return; } for (int y = 0; y < 16; y++) { for (int x = 0; x < 16; x++) { // Get scenery item - ignore indices -1 (empty) and 0 (marker/waypoint of some kind) DFBlock.RmbGroundScenery scenery = blockData.RmbBlock.FldHeader.GroundData.GroundScenery[x, 15 - y]; if (scenery.TextureRecord < 1) { continue; } // Calculate position Vector3 billboardPosition = new Vector3( x * BlocksFile.TileDimension, natureFlatsOffsetY, y * BlocksFile.TileDimension + BlocksFile.TileDimension) * MeshReader.GlobalScale; // Get Archive int natureArchive = ClimateSwaps.GetNatureArchive(climateNature, climateSeason); // Import custom 3d gameobject instead of flat if (MeshReplacement.ImportCustomFlatGameobject(natureArchive, scenery.TextureRecord, billboardPosition, flatsParent) != null) { continue; } // Add billboard to batch or standalone if ((billboardBatch != null) && (!TextureReplacement.CustomTextureExist(natureArchive, scenery.TextureRecord))) { billboardBatch.AddItem(scenery.TextureRecord, billboardPosition); } else { GameObject go = GameObjectHelper.CreateDaggerfallBillboardGameObject(natureArchive, scenery.TextureRecord, flatsParent); go.transform.position = billboardPosition; AlignBillboardToBase(go); } } } }
void LoadAssets() { if (TextureReplacement.CustomTextureExist(defaultCrosshairFilename)) { CrosshairTexture = TextureReplacement.LoadCustomTexture(defaultCrosshairFilename); } else { CrosshairTexture = Resources.Load <Texture2D>(defaultCrosshairFilename); } }
public void RestoreSaveData(object dataIn) { if (!loot) { return; } LootContainerData_v1 data = (LootContainerData_v1)dataIn; if (data.loadID != LoadID) { return; } DaggerfallBillboard billboard = loot.GetComponent <DaggerfallBillboard>(); // Restore position loot.transform.position = data.currentPosition; // Restore billboard appearance if present if (billboard) { billboard.SetMaterial(data.textureArchive, data.textureRecord); // Setup custom material if available if (TextureReplacement.CustomTextureExist(data.textureArchive, data.textureRecord)) { TextureReplacement.SetBillboardCustomMaterial(billboard.gameObject, data.textureArchive, data.textureRecord); } } // Restore items loot.Items.DeserializeItems(data.items); // Restore other data loot.ContainerType = data.containerType; loot.ContainerImage = data.containerImage; loot.LootTableKey = data.lootTableKey; loot.TextureArchive = data.textureArchive; loot.TextureRecord = data.textureRecord; loot.playerOwned = data.playerOwned; loot.customDrop = data.customDrop; loot.name = loot.ContainerType.ToString(); // Remove loot container if empty if (loot.Items.Count == 0) { GameObjectHelper.RemoveLootContainer(loot); } }
public override void Update() { if (CrosshairTexture && Enabled) { BackgroundTexture = CrosshairTexture; if (TextureReplacement.CustomTextureExist(defaultCrosshairFilename)) { Size = XMLManager.GetSize(defaultCrosshairFilename, TextureReplacement.TexturesPath, CrosshairScale, CrosshairScale); } else { Size = new Vector2(CrosshairTexture.width * CrosshairScale, CrosshairTexture.height * CrosshairScale); } base.Update(); } }
/// <summary> /// Gets Unity textures from Daggerfall texture with all options. /// Returns all supported texture maps for Standard shader in one call. /// </summary> /// <param name="settings">Get texture settings.</param> /// <param name="alphaTextureFormat">Alpha TextureFormat.</param> /// <param name="nonAlphaFormat">Non-alpha TextureFormat.</param> /// <param name="allowImport">Import texture from disk if present.</param> /// <returns>GetTextureResults.</returns> public GetTextureResults GetTexture2D( GetTextureSettings settings, SupportedAlphaTextureFormats alphaTextureFormat = SupportedAlphaTextureFormats.RGBA32, SupportedNonAlphaTextureFormats nonAlphaFormat = SupportedNonAlphaTextureFormats.RGB24, bool allowImport = true) { GetTextureResults results = new GetTextureResults(); // Check if window or auto-emissive bool isWindow = ClimateSwaps.IsExteriorWindow(settings.archive, settings.record); bool isEmissive = (settings.autoEmission) ? IsEmissive(settings.archive, settings.record) : false; // Override readable flag when user has set preference in material reader if (DaggerfallUnity.Instance.MaterialReader.ReadableTextures) { settings.stayReadable = true; } // Assign texture file TextureFile textureFile; if (settings.textureFile == null) { textureFile = new TextureFile(Path.Combine(Arena2Path, TextureFile.IndexToFileName(settings.archive)), FileUsage.UseMemory, true); } else { textureFile = settings.textureFile; } // Get starting DFBitmap and albedo Color32 array DFSize sz; DFBitmap srcBitmap = textureFile.GetDFBitmap(settings.record, settings.frame); Color32[] albedoColors = textureFile.GetColor32(srcBitmap, settings.alphaIndex, settings.borderSize, out sz); // Sharpen source image if (settings.sharpen) { albedoColors = ImageProcessing.Sharpen(ref albedoColors, sz.Width, sz.Height); } // Dilate edges if (settings.borderSize > 0 && settings.dilate && !settings.copyToOppositeBorder) { ImageProcessing.DilateColors(ref albedoColors, sz); } // Copy to opposite border if (settings.borderSize > 0 && settings.copyToOppositeBorder) { ImageProcessing.WrapBorder(ref albedoColors, sz, settings.borderSize); } // Set albedo texture Texture2D albedoMap = null; if (allowImport && TextureReplacement.CustomTextureExist(settings.archive, settings.record, settings.frame)) { // Import albedo texture albedoMap = TextureReplacement.LoadCustomTexture(settings.archive, settings.record, settings.frame); } else { // Create albedo texture if (settings.alphaIndex < 0) { albedoMap = new Texture2D(sz.Width, sz.Height, ParseTextureFormat(nonAlphaFormat), MipMaps); } else { albedoMap = new Texture2D(sz.Width, sz.Height, ParseTextureFormat(alphaTextureFormat), MipMaps); } albedoMap.SetPixels32(albedoColors); albedoMap.Apply(true, !settings.stayReadable); } // Set normal texture Texture2D normalMap = null; if (allowImport && TextureReplacement.CustomNormalExist(settings.archive, settings.record, settings.frame)) { // Always import normal if present on disk normalMap = TextureReplacement.LoadCustomNormal(settings.archive, settings.record, settings.frame); } else if (settings.createNormalMap && textureFile.SolidType == TextureFile.SolidTypes.None) { // Create normal texture - must be ARGB32 // Normal maps are bypassed for solid-colour textures Color32[] normalColors; normalColors = ImageProcessing.GetBumpMap(ref albedoColors, sz.Width, sz.Height); normalColors = ImageProcessing.ConvertBumpToNormals(ref normalColors, sz.Width, sz.Height, settings.normalStrength); normalMap = new Texture2D(sz.Width, sz.Height, TextureFormat.ARGB32, MipMaps); normalMap.SetPixels32(normalColors); normalMap.Apply(true, !settings.stayReadable); } // Import emission map or create basic emissive texture Texture2D emissionMap = null; bool resultEmissive = false; if (allowImport && TextureReplacement.CustomEmissionExist(settings.archive, settings.record, settings.frame)) { // Always import emission if present on disk emissionMap = TextureReplacement.LoadCustomEmission(settings.archive, settings.record, settings.frame); resultEmissive = true; } else { if (settings.createEmissionMap || (settings.autoEmission && isEmissive) && !isWindow) { // Just reuse albedo map for basic colour emission emissionMap = albedoMap; resultEmissive = true; } // Windows need special handling as only glass parts are emissive if ((settings.createEmissionMap || settings.autoEmissionForWindows) && isWindow) { // Create custom emission texture for glass area of windows Color32[] emissionColors = textureFile.GetWindowColors32(srcBitmap); emissionMap = new Texture2D(sz.Width, sz.Height, ParseTextureFormat(alphaTextureFormat), MipMaps); emissionMap.SetPixels32(emissionColors); emissionMap.Apply(true, !settings.stayReadable); resultEmissive = true; } // Lights need special handling as this archive contains a mix of emissive and non-emissive flats // This can cause problems with atlas packing due to mismatch between albedo and emissive texture counts if ((settings.createEmissionMap || settings.autoEmission) && settings.archive == LightsTextureArchive) { // For the unlit flats we create a null-emissive black texture if (!isEmissive) { Color32[] emissionColors = new Color32[sz.Width * sz.Height]; emissionMap = new Texture2D(sz.Width, sz.Height, ParseTextureFormat(alphaTextureFormat), MipMaps); emissionMap.SetPixels32(emissionColors); emissionMap.Apply(true, !settings.stayReadable); resultEmissive = true; } } } // Shrink UV rect to compensate for internal border float ru = 1f / sz.Width; float rv = 1f / sz.Height; results.singleRect = new Rect( settings.borderSize * ru, settings.borderSize * rv, (sz.Width - settings.borderSize * 2) * ru, (sz.Height - settings.borderSize * 2) * rv); // Store results results.albedoMap = albedoMap; results.normalMap = normalMap; results.emissionMap = emissionMap; results.isWindow = isWindow; results.isEmissive = resultEmissive; results.textureFile = textureFile; return(results); }
/// <summary> /// Add misc block flats. /// Batching is conditionally supported. /// </summary> public static void AddMiscBlockFlats( ref DFBlock blockData, Transform flatsParent, DaggerfallBillboardBatch animalsBillboardBatch = null, TextureAtlasBuilder miscBillboardsAtlas = null, DaggerfallBillboardBatch miscBillboardsBatch = null) { DaggerfallUnity dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady) { return; } // Add block flats foreach (DFBlock.RmbBlockFlatObjectRecord obj in blockData.RmbBlock.MiscFlatObjectRecords) { // Ignore lights as they are handled by AddLights() if (obj.TextureArchive == TextureReader.LightsTextureArchive) { continue; } // Calculate position Vector3 billboardPosition = new Vector3( obj.XPos, -obj.YPos + blockFlatsOffsetY, obj.ZPos + BlocksFile.RMBDimension) * MeshReader.GlobalScale; // Import custom 3d gameobject instead of flat if (MeshReplacement.ImportCustomFlatGameobject(obj.TextureArchive, obj.TextureRecord, billboardPosition, flatsParent) != null) { continue; } if (!TextureReplacement.CustomTextureExist(obj.TextureArchive, obj.TextureRecord)) { // Use misc billboard atlas where available if (miscBillboardsAtlas != null && miscBillboardsBatch != null) { TextureAtlasBuilder.AtlasItem item = miscBillboardsAtlas.GetAtlasItem(obj.TextureArchive, obj.TextureRecord); if (item.key != -1) { miscBillboardsBatch.AddItem(item.rect, item.textureItem.size, item.textureItem.scale, billboardPosition); continue; } } // Add to batch where available if (obj.TextureArchive == TextureReader.AnimalsTextureArchive && animalsBillboardBatch != null) { animalsBillboardBatch.AddItem(obj.TextureRecord, billboardPosition); continue; } } // Add standalone billboard gameobject GameObject go = GameObjectHelper.CreateDaggerfallBillboardGameObject(obj.TextureArchive, obj.TextureRecord, flatsParent); go.transform.position = billboardPosition; AlignBillboardToBase(go); } }
/// <summary> /// Sets new Daggerfall material and recreates mesh. /// Will use an atlas if specified in DaggerfallUnity singleton. /// </summary> /// <param name="dfUnity">DaggerfallUnity singleton. Required for content readers and settings.</param> /// <param name="archive">Texture archive index.</param> /// <param name="record">Texture record index.</param> /// <param name="frame">Frame index.</param> /// <returns>Material.</returns> public Material SetMaterial(int archive, int record, int frame = 0) { // Get DaggerfallUnity DaggerfallUnity dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady) { return(null); } // Get references meshRenderer = GetComponent <MeshRenderer>(); Vector2 size; Mesh mesh = null; Material material = null; if (dfUnity.MaterialReader.AtlasTextures) { material = dfUnity.MaterialReader.GetMaterialAtlas( archive, 0, 4, 2048, out summary.AtlasRects, out summary.AtlasIndices, 4, true, 0, false, true); mesh = dfUnity.MeshReader.GetBillboardMesh( summary.AtlasRects[summary.AtlasIndices[record].startIndex], archive, record, out size); summary.AtlasedMaterial = true; if (summary.AtlasIndices[record].frameCount > 1) { summary.AnimatedMaterial = true; } else { summary.AnimatedMaterial = false; } } else { material = dfUnity.MaterialReader.GetMaterial( archive, record, frame, 0, out summary.Rect, 4, true, true); mesh = dfUnity.MeshReader.GetBillboardMesh( summary.Rect, archive, record, out size); summary.AtlasedMaterial = false; summary.AnimatedMaterial = false; } // Set summary summary.FlatType = MaterialReader.GetFlatType(archive); summary.Archive = archive; summary.Record = record; summary.Size = size; // Set editor flat types if (summary.FlatType == FlatTypes.Editor) { summary.EditorFlatType = MaterialReader.GetEditorFlatType(summary.Record); } // Set NPC flat type based on archive if (RDBLayout.IsNPCFlat(summary.Archive)) { summary.FlatType = FlatTypes.NPC; } // Assign mesh and material MeshFilter meshFilter = GetComponent <MeshFilter>(); Mesh oldMesh = meshFilter.sharedMesh; if (mesh) { meshFilter.sharedMesh = mesh; meshRenderer.sharedMaterial = material; } if (oldMesh) { // The old mesh is no longer required #if UNITY_EDITOR DestroyImmediate(oldMesh); #else Destroy(oldMesh); #endif } // Import custom textures if (TextureReplacement.CustomTextureExist(archive, record)) { TextureReplacement.SetBillboardCustomMaterial(gameObject, ref summary); } // Standalone billboards never cast shadows meshRenderer.shadowCastingMode = ShadowCastingMode.Off; // Add NPC trigger collider if (summary.FlatType == FlatTypes.NPC) { Collider col = gameObject.AddComponent <BoxCollider>(); col.isTrigger = true; } return(material); }
IEnumerator AnimateBillboard() { while (true) { float speed = FramesPerSecond; if (summary.Archive == Utility.TextureReader.AnimalsTextureArchive) { speed = animalFps; } else if (summary.Archive == Utility.TextureReader.LightsTextureArchive) { speed = lightFps; } if (meshFilter != null) { summary.CurrentFrame++; // Original Daggerfall textures if (!TextureReplacement.CustomTextureExist(summary.Archive, summary.Record)) { if (summary.CurrentFrame >= summary.AtlasIndices[summary.Record].frameCount) { summary.CurrentFrame = 0; if (OneShot) { GameObject.Destroy(gameObject); } } int index = summary.AtlasIndices[summary.Record].startIndex + summary.CurrentFrame; Rect rect = summary.AtlasRects[index]; // Update UVs on mesh Vector2[] uvs = new Vector2[4]; uvs[0] = new Vector2(rect.x, rect.yMax); uvs[1] = new Vector2(rect.xMax, rect.yMax); uvs[2] = new Vector2(rect.x, rect.y); uvs[3] = new Vector2(rect.xMax, rect.y); meshFilter.sharedMesh.uv = uvs; } // Custom textures else { // Restart animation or destroy gameobject // The game uses all -and only- textures found on disk, even if they are less or more than vanilla frames if (summary.CurrentFrame >= summary.CustomBillboard.NumberOfFrames) { summary.CurrentFrame = 0; if (OneShot) { GameObject.Destroy(gameObject); } } // Set Main texture for current frame meshRenderer.materials[0].SetTexture("_MainTex", summary.CustomBillboard.MainTexture[summary.CurrentFrame]); // Set Emission map for current frame if (summary.CustomBillboard.isEmissive) { meshRenderer.materials[0].SetTexture("_EmissionMap", summary.CustomBillboard.EmissionMap[summary.CurrentFrame]); } } } yield return(new WaitForSeconds(1f / speed)); } }
protected override void Setup() { // Main panel mainPanel.HorizontalAlignment = HorizontalAlignment.Center; mainPanel.VerticalAlignment = VerticalAlignment.Middle; mainPanel.Size = mainPanelSize; mainPanel.Outline.Enabled = true; if (TextureReplacement.CustomTextureExist("mainPanelBackgroundColor")) { mainPanel.BackgroundTexture = TextureReplacement.LoadCustomTexture("mainPanelBackgroundColor"); } else { mainPanel.BackgroundColor = mainPanelBackgroundColor; } NativePanel.Components.Add(mainPanel); // Prompt promptLabel.ShadowPosition = Vector2.zero; promptLabel.Position = new Vector2(4, 4); mainPanel.Components.Add(promptLabel); // Name panel Panel namePanel = new Panel(); namePanel.Position = new Vector2(4, 12); namePanel.Size = new Vector2(272, 9); namePanel.Outline.Enabled = true; if (TextureReplacement.CustomTextureExist("namePanelBackgroundColor")) { namePanel.BackgroundTexture = TextureReplacement.LoadCustomTexture("namePanelBackgroundColor"); } else { namePanel.BackgroundColor = namePanelBackgroundColor; } mainPanel.Components.Add(namePanel); // Name input saveNameTextBox.Position = new Vector2(2, 2); saveNameTextBox.MaxCharacters = 26; saveNameTextBox.OnType += SaveNameTextBox_OnType; namePanel.Components.Add(saveNameTextBox); // Save panel Panel savesPanel = new Panel(); savesPanel.Position = new Vector2(4, 25); savesPanel.Size = new Vector2(100, 141); savesPanel.Outline.Enabled = true; mainPanel.Components.Add(savesPanel); // Save list savesList.Position = new Vector2(2, 2); savesList.Size = new Vector2(91, 129); savesList.TextColor = savesListTextColor; if (TextureReplacement.CustomTextureExist("savesListBackgroundColor")) { savesList.BackgroundTexture = TextureReplacement.LoadCustomTexture("savesListBackgroundColor"); } else { savesList.BackgroundColor = savesListBackgroundColor; } savesList.ShadowPosition = Vector2.zero; savesList.RowsDisplayed = 16; savesList.OnScroll += SavesList_OnScroll; savesList.OnSelectItem += SavesList_OnSelectItem; savesList.OnMouseDoubleClick += SaveLoadEventHandler; savesPanel.Components.Add(savesList); // Save scroller savesScroller.Position = new Vector2(94, 2); savesScroller.Size = new Vector2(5, 129); savesScroller.DisplayUnits = 16; savesScroller.OnScroll += SavesScroller_OnScroll; savesPanel.Components.Add(savesScroller); // Save/Load button goButton.Position = new Vector2(108, 150); goButton.Size = new Vector2(40, 16); goButton.Label.ShadowColor = Color.black; if (TextureReplacement.CustomTextureExist("saveButtonBackgroundColor")) { TextureReplacement.SetCustomButton(ref goButton, "saveButtonBackgroundColor"); } else { goButton.BackgroundColor = saveButtonBackgroundColor; } goButton.Outline.Enabled = true; goButton.OnMouseClick += SaveLoadEventHandler; mainPanel.Components.Add(goButton); // Switch to classic save window button switchClassicButton.Position = new Vector2(172, 150); switchClassicButton.Size = new Vector2(40, 16); switchClassicButton.Label.Text = "Classic"; //switchClassicButton.Label.TextColor = new Color(0.6f, 0.3f, 0.6f); switchClassicButton.Label.ShadowColor = Color.black; if (TextureReplacement.CustomTextureExist("switchClassicButtonBackgroundColor")) { TextureReplacement.SetCustomButton(ref switchClassicButton, "switchClassicButtonBackgroundColor"); } else { switchClassicButton.BackgroundColor = new Color(0.2f, 0.2f, 0); } switchClassicButton.Outline.Enabled = true; switchClassicButton.OnMouseClick += SwitchClassicButton_OnMouseClick; mainPanel.Components.Add(switchClassicButton); // Cancel button Button cancelButton = new Button(); cancelButton.Position = new Vector2(236, 150); cancelButton.Size = new Vector2(40, 16); cancelButton.Label.Text = "Cancel"; cancelButton.Label.ShadowColor = Color.black; if (TextureReplacement.CustomTextureExist("cancelButtonBackgroundColor")) { TextureReplacement.SetCustomButton(ref cancelButton, "cancelButtonBackgroundColor"); } else { cancelButton.BackgroundColor = cancelButtonBackgroundColor; } cancelButton.Outline.Enabled = true; cancelButton.OnMouseClick += CancelButton_OnMouseClick; mainPanel.Components.Add(cancelButton); // Screenshot panel screenshotPanel.Position = new Vector2(108, 25); screenshotPanel.Size = new Vector2(168, 95); screenshotPanel.BackgroundTextureLayout = BackgroundLayout.ScaleToFit; if (TextureReplacement.CustomTextureExist("screenshotPanelBackgroundColor")) { screenshotPanel.BackgroundTexture = TextureReplacement.LoadCustomTexture("screenshotPanelBackgroundColor"); } else { screenshotPanel.BackgroundColor = savesListBackgroundColor; } screenshotPanel.Outline.Enabled = true; mainPanel.Components.Add(screenshotPanel); // Info panel Panel infoPanel = new Panel(); infoPanel.Position = new Vector2(108, 122); infoPanel.Size = new Vector2(168, 26); mainPanel.Components.Add(infoPanel); // Save version saveVersionLabel.ShadowColor = Color.black; saveVersionLabel.Position = new Vector2(1, 1); saveVersionLabel.TextColor = saveFolderColor; screenshotPanel.Components.Add(saveVersionLabel); // Save folder saveFolderLabel.ShadowColor = Color.black; saveFolderLabel.HorizontalAlignment = HorizontalAlignment.Right; saveFolderLabel.Position = new Vector2(0, 1); saveFolderLabel.TextColor = saveFolderColor; screenshotPanel.Components.Add(saveFolderLabel); // Time labels saveTimeLabel.ShadowPosition = Vector2.zero; saveTimeLabel.HorizontalAlignment = HorizontalAlignment.Center; saveTimeLabel.Position = new Vector2(0, 0); infoPanel.Components.Add(saveTimeLabel); gameTimeLabel.ShadowPosition = Vector2.zero; gameTimeLabel.HorizontalAlignment = HorizontalAlignment.Center; gameTimeLabel.Position = new Vector2(0, 9); infoPanel.Components.Add(gameTimeLabel); // Delete save button deleteSaveButton.Position = new Vector2(0, 132); deleteSaveButton.Size = new Vector2(98, 8); deleteSaveButton.HorizontalAlignment = HorizontalAlignment.Center; deleteSaveButton.Label.Text = "Delete Save"; deleteSaveButton.Label.ShadowColor = Color.black; if (TextureReplacement.CustomTextureExist("deleteSaveButtonBackgroundColor")) { TextureReplacement.SetCustomButton(ref deleteSaveButton, "deleteSaveButtonBackgroundColor"); } else { deleteSaveButton.BackgroundColor = namePanelBackgroundColor; } deleteSaveButton.Outline.Enabled = false; deleteSaveButton.OnMouseClick += DeleteSaveButton_OnMouseClick; savesPanel.Components.Add(deleteSaveButton); // Switch character button switchCharButton.Position = new Vector2(216, 2); switchCharButton.Size = new Vector2(60, 8); switchCharButton.Label.Text = "Switch Char"; switchCharButton.Label.ShadowColor = Color.black; if (TextureReplacement.CustomTextureExist("switchCharButtonBackgroundColor")) { TextureReplacement.SetCustomButton(ref switchCharButton, "switchCharButtonBackgroundColor"); } else { switchCharButton.BackgroundColor = saveButtonBackgroundColor; } switchCharButton.OnMouseClick += SwitchCharButton_OnMouseClick; mainPanel.Components.Add(switchCharButton); }