protected override void Setup() { AllowCancel = false; LoadResources(); // Add exit button Button exitButton = new Button(); exitButton.Size = new Vector2(20, 9); exitButton.HorizontalAlignment = HorizontalAlignment.Center; exitButton.VerticalAlignment = VerticalAlignment.Bottom; exitButton.BackgroundColor = new Color(0.2f, 0.2f, 0.2f, 0.6f); exitButton.Outline.Enabled = true; exitButton.Label.Text = GetText("exit"); exitButton.OnMouseClick += ExitButton_OnMouseClick; exitButton.Hotkey = DaggerfallShortcut.GetBinding(DaggerfallShortcut.Buttons.GameSetupExit); NativePanel.Components.Add(exitButton); // If actually validated and we just want to see settings then move direct to settings page if (DaggerfallUnity.Instance.IsPathValidated && (DaggerfallUnity.Settings.ShowOptionsAtStart || Input.anyKey)) { currentStage = SetupStages.Options - 1; } moveNextStage = true; // Apply joystick settings to input manager to keep consistency between the setup wizard and the game InputManager.Instance.JoystickCursorSensitivity = DaggerfallUnity.Settings.JoystickCursorSensitivity; InputManager.Instance.JoystickDeadzone = DaggerfallUnity.Settings.JoystickDeadzone; // Override cursor Texture2D tex; if (TextureReplacement.TryImportTexture("Cursor", true, out tex)) { Cursor.SetCursor(tex, Vector2.zero, CursorMode.Auto); Debug.Log("Cursor texture overridden by mods."); } }
/// <summary> /// Gets terrain metallic gloss map 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 GetTerrainMetallicGlossMapTextureArray( int archive, bool stayReadable = false) { Color32[] defaultMetallicGlossMap; // 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; int width; int height; // try to import first replacement texture for tile archive to determine width and height of replacement texture set (must be the same for all replacement textures for Texture2DArray) Texture2D metallicGlossMap; if (TextureReplacement.TryImportTexture(archive, 0, 0, TextureMap.MetallicGloss, out metallicGlossMap)) { width = metallicGlossMap.width; height = metallicGlossMap.height; } else { // create default texture array (1x1 texture) width = 1; height = 1; } textureArray = new Texture2DArray(width, height, numSlices, TextureFormat.ARGB32, MipMaps); defaultMetallicGlossMap = new Color32[width * height]; for (int i = 0; i < width * height; i++) { defaultMetallicGlossMap[i] = new Color32(0, 0, 0, 255); } // Rollout tiles into texture array for (int record = 0; record < textureFile.RecordCount; record++) { // Import custom texture(s) if (!TextureReplacement.TryImportTexture(archive, record, 0, TextureMap.MetallicGloss, out metallicGlossMap)) { metallicGlossMap = new Texture2D(width, height, TextureFormat.ARGB32, MipMaps); metallicGlossMap.SetPixels32(defaultMetallicGlossMap); } // enforce that all custom metallicgloss map textures have the same dimension (requirement of Texture2DArray) if ((metallicGlossMap.width != width) || (metallicGlossMap.height != height)) { Debug.LogErrorFormat("Terrain: failed to inject metallicgloss maps for archive {0}, incorrect size at record {1}.", archive, record); return(null); } // Insert into texture array textureArray.SetPixels32(metallicGlossMap.GetPixels32(), record, 0); } textureArray.Apply(true, !stayReadable); // Change settings for these textures textureArray.wrapMode = TextureWrapMode.Clamp; textureArray.anisoLevel = 8; return(textureArray); }
/// <summary> /// Gets terrain normal map 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 GetTerrainNormalMapTextureArray( int archive, bool stayReadable = false, SupportedAlphaTextureFormats alphaFormat = SupportedAlphaTextureFormats.ARGB32) { // 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; int width; int height; // try to import first replacement texture for tile archive to determine width and height of replacement texture set (must be the same for all replacement textures for Texture2DArray) Texture2D normalMap; if (TextureReplacement.TryImportTexture(archive, 0, 0, TextureMap.Normal, out normalMap)) { width = normalMap.width; height = normalMap.height; } else { return(null); } textureArray = new Texture2DArray(width, height, numSlices, ParseTextureFormat(alphaFormat), MipMaps); // Rollout tiles into texture array for (int record = 0; record < textureFile.RecordCount; record++) { // Import custom texture(s) if (!TextureReplacement.TryImportTexture(archive, record, 0, TextureMap.Normal, out normalMap)) { // if current texture does not exist Debug.LogErrorFormat("Terrain: imported archive {0} does not contain normal for record {1}.", archive, record); return(null); } // enforce that all custom normal map textures have the same dimension (requirement of Texture2DArray) if ((normalMap.width != width) || (normalMap.height != height)) { Debug.LogErrorFormat("Terrain: failed to inject normal maps for archive {0}, incorrect size at record {1}.", archive, record); return(null); } // Insert into texture array textureArray.SetPixels32(normalMap.GetPixels32(), record, 0); } textureArray.Apply(true, !stayReadable); // Change settings for these textures textureArray.wrapMode = TextureWrapMode.Clamp; textureArray.anisoLevel = 8; return(textureArray); }
/// <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="textureImport">Options for import of custom textures.</param> /// <returns>GetTextureResults.</returns> public GetTextureResults GetTexture2D( GetTextureSettings settings, SupportedAlphaTextureFormats alphaTextureFormat = SupportedAlphaTextureFormats.ARGB32, TextureImport textureImport = TextureImport.None) { 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; if (!TextureReplacement.TryImportTexture(settings.archive, settings.record, settings.frame, TextureMap.Albedo, textureImport, out albedoMap)) { // Create albedo texture albedoMap = new Texture2D(sz.Width, sz.Height, ParseTextureFormat(alphaTextureFormat), MipMaps); albedoMap.SetPixels32(albedoColors); albedoMap.Apply(true, !settings.stayReadable); } // Set normal texture (always import normal if present on disk) Texture2D normalMap = null; bool normalMapImported = TextureReplacement.TryImportTexture(settings.archive, settings.record, settings.frame, TextureMap.Normal, textureImport, out normalMap); if (!normalMapImported && 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 (TextureReplacement.TryImportTexture(settings.archive, settings.record, settings.frame, TextureMap.Emission, textureImport, out emissionMap)) { // Always import emission if present on disk 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> /// 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> /// <returns>Texture2DArray or null</returns> public Texture2DArray GetTerrainAlbedoTextureArray( int archive, bool stayReadable = false) { // 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 (!stayReadable && TextureReplacement.TryImportTextureArray(archive, numSlices, TextureMap.Albedo, null, out textureArray)) { return(textureArray); } Texture2D albedoMap; if (TextureReplacement.TryImportTexture(archive, 0, 0, out albedoMap)) { textureArray = new Texture2DArray(albedoMap.width, albedoMap.height, numSlices, TextureFormat.ARGB32, MipMaps); } else { textureArray = new Texture2DArray(textureFile.GetWidth(0), textureFile.GetWidth(1), numSlices, TextureFormat.ARGB32, MipMaps); } // Rollout tiles into texture array for (int record = 0; record < textureFile.RecordCount; record++) { Color32[] albedo; if (TextureReplacement.TryImportTexture(archive, record, 0, out albedoMap)) { // Import custom texture 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); }
protected override void Setup() { // Load textures nativeTexture = DaggerfallUI.GetTextureFromImg(nativeTextureName); if (!nativeTexture) { throw new Exception("DaggerfallControlsWindow: Could not load native texture."); } mLookAltTexture = DaggerfallUI.GetTextureFromImg(mLookAltTextureName); // Always dim background ParentPanel.BackgroundColor = ScreenDimColor; // Controls panel controlsPanel.HorizontalAlignment = HorizontalAlignment.Center; controlsPanel.Size = NativePanel.Size; controlsPanel.BackgroundTexture = nativeTexture; NativePanel.Components.Add(controlsPanel); // Mouse Look Alternative Controls Panel mLookAltPanel.Position = new Vector2(152, 100); mLookAltPanel.Size = new Vector2(168, 45); mLookAltPanel.BackgroundTexture = mLookAltTexture; controlsPanel.Components.Add(mLookAltPanel); #region Tab Buttons // Joystick Button joystickButton = DaggerfallUI.AddButton(new Rect(0, 190, 80, 10), controlsPanel); joystickButton.OnMouseClick += JoystickButton_OnMouseClick; // Mouse Button mouseButton = DaggerfallUI.AddButton(new Rect(80, 190, 80, 10), controlsPanel); mouseButton.BackgroundColor = new Color(0f, 0f, 0f, 1f); Texture2D tex; if (!TextureReplacement.TryImportTexture("advanced_controls_button", true, out tex)) { tex = Resources.Load <Texture2D>("advanced_controls_button"); } tex.filterMode = FilterMode.Point; mouseButton.BackgroundTexture = tex; //mouseButton.Label.Text = "ADVANCED"; mouseButton.OnMouseClick += MouseButton_OnMouseClick; // Default Button defaultButton = DaggerfallUI.AddButton(new Rect(160, 190, 80, 10), controlsPanel); defaultButton.OnMouseClick += DefaultButton_OnMouseClick; // Continue Button continueButton = DaggerfallUI.AddButton(new Rect(240, 190, 80, 10), controlsPanel); continueButton.OnMouseClick += ContinueButton_OnMouseClick; #endregion #region Keybind Buttons currentBindingsButton = DaggerfallUI.AddButton(new Rect(268, 0, 50, 8), controlsPanel); currentBindingsButton.Label.ShadowPosition = Vector2.zero; currentBindingsButton.Outline.Enabled = true; currentBindingsButton.OnMouseClick += CurrentBindingsButton_OnMouseClick; currentBindingsButton.Label.Text = ControlsConfigManager.Instance.UsingPrimary ? "Primary" : "Secondary"; ControlsConfigManager.Instance.ResetUnsavedKeybinds(); DaggerfallJoystickControlsWindow.ResetUnsavedSettings(); SetupKeybindButtons(moveKeysOne, 2, 8, 57, 13, true); SetupKeybindButtons(moveKeysTwo, 8, 14, 164, 13, true); SetupKeybindButtons(modeKeys, 14, 20, 270, 13, true); SetupKeybindButtons(magicKeys, 20, 24, 102, 80, true); SetupKeybindButtons(weaponKeys, 24, 27, 102, 125, true); SetupKeybindButtons(statusKeys, 27, 30, 102, 159, true); SetupKeybindButtons(activateKeys, 30, 32, 270, 80, true); SetupKeybindButtons(lookKeys, 32, 36, 270, 103, true); SetupKeybindButtons(uiKeys, 36, 40, 270, 148, true); CheckDuplicates(); #endregion }
/// <summary> /// Gets inventory/equip image for specified item. /// Image will be cached based on material and hand for faster subsequent fetches. /// Animated item images do not support dyes. /// </summary> /// <param name="item">Item to fetch image for.</param> /// <param name="removeMask">Removes mask index (e.g. around helmets) from final image.</param> /// <param name="forPaperDoll">Image is for paper doll.</param> /// <param name="allowAnimation">Read animated textures.</param> /// <returns>ImageData.</returns> public ImageData GetItemImage(DaggerfallUnityItem item, bool removeMask = false, bool forPaperDoll = false, bool allowAnimation = false) { // Get colour int color = (int)item.dyeColor; // Get archive and record indices int archive = item.InventoryTextureArchive; int record = item.InventoryTextureRecord; // Paper doll handling if (forPaperDoll) { // 1H Weapons in right hand need record + 1 if (item.ItemGroup == ItemGroups.Weapons && item.EquipSlot == EquipSlots.RightHand) { if (ItemEquipTable.GetItemHands(item) == ItemHands.Either) { record += 1; } } } else { // Katanas need +1 for inventory image as they use right-hand image instead of left if (item.IsOfTemplate(ItemGroups.Weapons, (int)Weapons.Katana)) { record += 1; } } // Use world texture archive if inventory texture not set // Examples are gold pieces and wayrest painting if (archive == 0 && record == 0) { archive = item.ItemTemplate.worldTextureArchive; record = item.ItemTemplate.worldTextureRecord; } // Get unique key int key = MakeImageKey(color, archive, record, removeMask); // Get existing icon if in cache if (itemImages.ContainsKey(key)) { return(itemImages[key]); } // Load image data string filename = TextureFile.IndexToFileName(archive); ImageData data = ImageReader.GetImageData(filename, record, 0, true, false, allowAnimation); if (data.type == ImageTypes.None) { throw new Exception("GetItemImage() could not load image data."); } // Fix items with known incorrect paper doll offsets if (archive == 237 && (record == 52 || record == 54)) { // "Short shirt" template index 202 variants 2 and 5 for human female data.offset = new DaggerfallConnect.Utility.DFPosition(237, 43); } Texture2D tex; if (!forPaperDoll && TextureReplacement.TryImportTexture(archive, record, 0, item.dyeColor, out tex)) { // Assign imported texture // Paperdoll is disabled for now data.texture = tex; } else { // Remove mask if requested if (removeMask) { data.dfBitmap = ImageProcessing.ChangeMask(data.dfBitmap); } // Change dye or just update texture ItemGroups group = item.ItemGroup; DyeColors dye = (DyeColors)color; if (group == ItemGroups.Weapons || group == ItemGroups.Armor) { data = ChangeDye(data, dye, DyeTargets.WeaponsAndArmor); } else if (item.ItemGroup == ItemGroups.MensClothing || item.ItemGroup == ItemGroups.WomensClothing) { data = ChangeDye(data, dye, DyeTargets.Clothing); } else { ImageReader.UpdateTexture(ref data); } } // Add to cache itemImages.Add(key, data); return(data); }
/// <summary> /// Get a texture from resources with modding support. /// </summary> public static Texture2D GetTextureFromResources(string name) { Texture2D tex; return(TextureReplacement.TryImportTexture(name, out tex) ? tex : Resources.Load <Texture2D>(name)); }
/// <summary> /// Makes a texture array from textures loaded from mods, using <see cref="Graphics.CopyTexture"/> which is very efficient. /// The result texture array respects format and settings of individual textures and is not available on the cpu side. /// </summary> /// <remarks> /// <see cref="Graphics.CopyTexture"/> provides a very fast copy operation between textures, but is not supported on some platforms. /// The result is also not available for further edits from the cpu. /// The first record must be available and defines size and format that all records must match. A fallback color can be provided for other layers. /// </remarks> /// <param name="archive">The requested texture archive.</param> /// <param name="depth">The expected number of layer.</param> /// <param name="textureMap">The texture type.</param> /// <param name="fallbackColor">If provided is used silenty for missing layers.</param> /// <param name="textureArray">The created texture array or null.</param> /// <returns>True if the texture array has been created.</returns> private static bool TryMakeTextureArrayCopyTexture(int archive, int depth, TextureMap textureMap, Color32?fallbackColor, out Texture2DArray textureArray) { textureArray = null; if ((SystemInfo.copyTextureSupport & CopyTextureSupport.DifferentTypes) == CopyTextureSupport.None) { return(false); } bool mipMaps = false; Texture2D fallback = null; for (int record = 0; record < depth; record++) { Texture2D tex; if (!TextureReplacement.TryImportTexture(archive, record, 0, textureMap, true, out tex)) { if (!textureArray) { return(false); } if (!fallbackColor.HasValue) { Debug.LogErrorFormat("Failed to inject record {0} for texture archive {1} ({2}) because texture data is not available.", record, archive, textureMap); continue; } if (!fallback) { fallback = new Texture2D(textureArray.width, textureArray.height, textureArray.format, mipMaps); Color32[] colors = new Color32[fallback.width * fallback.height]; for (int i = 0; i < colors.Length; i++) { colors[i] = fallbackColor.Value; } fallback.SetPixels32(colors); fallback.Apply(mipMaps, true); } tex = fallback; } if (!textureArray) { textureArray = new Texture2DArray(tex.width, tex.height, depth, tex.format, mipMaps = tex.mipmapCount > 1); } if (tex.width == textureArray.width && tex.height == textureArray.height && tex.format == textureArray.format) { Graphics.CopyTexture(tex, 0, textureArray, record); } else { Debug.LogErrorFormat("Failed to inject record {0} for texture archive {1} ({2}) due to size or format mismatch.", record, archive, textureMap); } } if (fallback) { Texture2D.Destroy(fallback); } if (textureArray) { textureArray.wrapMode = TextureWrapMode.Clamp; textureArray.anisoLevel = 8; return(true); } return(false); }
/// <summary> /// Tries loading day sky files from mods and loose files /// </summary> /// <param name="skyIndex"></param> /// <param name="frame"></param> /// <param name="westTexture"></param> /// <param name="eastTexture"></param> /// <param name="applyStars"></param> /// <returns></returns> private bool TryLoadNightSkyTextures(int skyIndex, int frame, out Texture2D westTexture, out Texture2D eastTexture) { // Get night sky matching sky index int vanillaNightSky; if (skyIndex >= 0 && skyIndex <= 7) { vanillaNightSky = 3; } else if (skyIndex >= 8 && skyIndex <= 15) { vanillaNightSky = 1; } else if (skyIndex >= 16 && skyIndex <= 23) { vanillaNightSky = 2; } else { vanillaNightSky = 0; } //TYPE 1: NIGHTIME VANILLA string baseName = string.Format("NITE{0:00}I0.IMG", vanillaNightSky); TextureReplacement.TryImportTexture(baseName, false, out westTexture); //Vanilla worked! if (westTexture != null) { //Note east is copied from west eastTexture = westTexture; return(true); } //TYPE 2: FULL NIGHTIME baseName = string.Format("NITEFULL{0:00}I0.IMG", skyIndex); TextureReplacement.TryImportTexture(baseName, false, out westTexture); //Full worked! if (westTexture != null) { //Note east is copied from west eastTexture = westTexture; return(true); } //TYPE 3: NIGHTIME VANILLA baseName = string.Format("NITE{0:00}I0.IMG", vanillaNightSky); string eastName = Path.GetFileNameWithoutExtension(baseName) + "-0" + Path.GetExtension(baseName); string westName = Path.GetFileNameWithoutExtension(baseName) + "-1" + Path.GetExtension(baseName); TextureReplacement.TryImportTexture(eastName, false, out eastTexture); TextureReplacement.TryImportTexture(westName, false, out westTexture); //Vanilla with east+west worked! if (westTexture != null && eastTexture != null) { return(true); } //TYPE 2: FULL NIGHTIME baseName = string.Format("NITEFULL{0:00}I0.IMG", skyIndex); eastName = Path.GetFileNameWithoutExtension(baseName) + "-0" + Path.GetExtension(baseName); westName = Path.GetFileNameWithoutExtension(baseName) + "-1" + Path.GetExtension(baseName); TextureReplacement.TryImportTexture(eastName, false, out eastTexture); TextureReplacement.TryImportTexture(westName, false, out westTexture); //Full with east+west worked! if (westTexture != null && eastTexture != null) { return(true); } westTexture = null; eastTexture = null; return(false); }