diff --git a/PCK-Studio/Forms/Editor/TextureAtlasEditor.cs b/PCK-Studio/Forms/Editor/TextureAtlasEditor.cs index d3ffee2a..78ef3d85 100644 --- a/PCK-Studio/Forms/Editor/TextureAtlasEditor.cs +++ b/PCK-Studio/Forms/Editor/TextureAtlasEditor.cs @@ -30,6 +30,7 @@ using OMI.Workers.Color; using PckStudio.Extensions; +using PckStudio.Internal; using PckStudio.Internal.Deserializer; using PckStudio.Internal.Json; using PckStudio.Internal.Serializer; @@ -54,7 +55,7 @@ public Image FinalTexture private readonly Size _areaSize; private readonly int _rowCount; private readonly int _columnCount; - private readonly string _atlasType; + private readonly ResourceLocation _atlasType; private readonly List _tiles; private AtlasTile _selectedTile; @@ -93,7 +94,7 @@ private int SelectedIndex private const ImageLayoutDirection _imageLayout = ImageLayoutDirection.Horizontal; - public TextureAtlasEditor(PckFile pckFile, string path, Image atlas, Size areaSize) + public TextureAtlasEditor(PckFile pckFile, ResourceLocation resourceLocation, Image atlas) { InitializeComponent(); @@ -101,23 +102,24 @@ public TextureAtlasEditor(PckFile pckFile, string path, Image atlas, Size areaSi _workingTexture = atlas; - _areaSize = areaSize; + _areaSize = resourceLocation.GetTileArea(atlas.Size); _pckFile = pckFile; - _rowCount = atlas.Width / areaSize.Width; - _columnCount = atlas.Height / areaSize.Height; - (var tileInfos, _atlasType) = Path.GetFileNameWithoutExtension(path) switch + _rowCount = atlas.Width / _areaSize.Width; + _columnCount = atlas.Height / _areaSize.Height; + _atlasType = resourceLocation; + var tileInfos = resourceLocation.Category switch { - "terrain" => (Tiles.BlockTileInfos, "blocks"), - "items" => (Tiles.ItemTileInfos, "items"), - "particles" => (Tiles.ParticleTileInfos, "particles"), - "mapicons" => (Tiles.MapIconTileInfos, "map_icons"), - "additionalmapicons" => (Tiles.AdditionalMapIconTileInfos, "additional_map_icons"), - "moon_phases" => (Tiles.MoonPhaseTileInfos, "moon_phases"), - "xporb" => (Tiles.ExperienceOrbTileInfos, "experience_orbs"), - "explosion" => (Tiles.ExplosionTileInfos, "explosions"), - "kz" => (Tiles.PaintingTileInfos, "paintings"), - "Banner_Atlas" => (Tiles.BannerTileInfos, "banners"), - _ => (null, null), + ResourceCategory.BlockAtlas => Tiles.BlockTileInfos, + ResourceCategory.ItemAtlas => Tiles.ItemTileInfos, + ResourceCategory.ParticleAtlas => Tiles.ParticleTileInfos, + ResourceCategory.MapIconAtlas => Tiles.MapIconTileInfos, + ResourceCategory.AdditionalMapIconsAtlas => Tiles.AdditionalMapIconTileInfos, + ResourceCategory.MoonPhaseAtlas => Tiles.MoonPhaseTileInfos, + ResourceCategory.ExperienceOrbAtlas => Tiles.ExperienceOrbTileInfos, + ResourceCategory.ExplosionAtlas => Tiles.ExplosionTileInfos, + ResourceCategory.PaintingAtlas => Tiles.PaintingTileInfos, + ResourceCategory.BannerAtlas => Tiles.BannerTileInfos, + _ => null, }; originalPictureBox.Image = atlas.GetArea(new Rectangle(0, 0, atlas.Width, atlas.Height)); @@ -156,7 +158,7 @@ public TextureAtlasEditor(PckFile pckFile, string path, Image atlas, Size areaSi SelectedIndex = 0; - bool isParticles = _atlasType == "particles"; + bool isParticles = _atlasType.Category == ResourceCategory.ParticleAtlas; // this is directly based on Java's source code for handling enchanted hits // the particle is assigned a random grayscale color between roughly 154 and 230 @@ -239,7 +241,7 @@ private void SetImageDisplayed(int index) selectTilePictureBox.BlendColor = GetBlendColor(); selectTilePictureBox.UseBlendColor = applyColorMaskToolStripMenuItem.Checked; - if (animationButton.Enabled = _atlasType == "blocks" || _atlasType == "items") + if (animationButton.Enabled = _atlasType.Category == ResourceCategory.BlockAtlas || _atlasType.Category == ResourceCategory.ItemAtlas) { PckAsset animationAsset; diff --git a/PCK-Studio/Internal/ResourceCategory.cs b/PCK-Studio/Internal/ResourceCategory.cs index 0233ef62..8b8c1243 100644 --- a/PCK-Studio/Internal/ResourceCategory.cs +++ b/PCK-Studio/Internal/ResourceCategory.cs @@ -22,6 +22,16 @@ internal enum ResourceCategory { Unknown = -1, ItemAnimation, - BlockAnimation + BlockAnimation, + ItemAtlas, + BlockAtlas, + ParticleAtlas, + BannerAtlas, + PaintingAtlas, + ExplosionAtlas, + ExperienceOrbAtlas, + MoonPhaseAtlas, + MapIconAtlas, + AdditionalMapIconsAtlas, } } diff --git a/PCK-Studio/Internal/ResourceLocation.cs b/PCK-Studio/Internal/ResourceLocation.cs index e9984d86..59a726be 100644 --- a/PCK-Studio/Internal/ResourceLocation.cs +++ b/PCK-Studio/Internal/ResourceLocation.cs @@ -1,19 +1,46 @@ using System; using System.Collections.Generic; +using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PckStudio.Internal { - internal class ResourceLocation + internal sealed class ResourceLocation { + private static readonly Dictionary _categoryLookUp = new Dictionary() + { + ["textures/items"] = new ResourceLocation("textures/items", ResourceCategory.ItemAnimation, 16, isGroup: true), + ["textures/blocks"] = new ResourceLocation("textures/blocks", ResourceCategory.BlockAnimation, 16, isGroup: true), + ["terrain.png"] = new ResourceLocation("terrain.png", ResourceCategory.BlockAtlas, 16), + ["items.png"] = new ResourceLocation("items.png", ResourceCategory.ItemAtlas, 16), + ["particles.png"] = new ResourceLocation("particles.png", ResourceCategory.ParticleAtlas, 16), + ["item/banner/Banner_Atlas.png"] = new ResourceLocation("item/banner/Banner_Atlas.png", ResourceCategory.BannerAtlas, new Size(6, 7), TillingMode.Custom), + ["art/kz.png"] = new ResourceLocation("art/kz.png", ResourceCategory.PaintingAtlas, 16), + ["misc/explosion.png"] = new ResourceLocation("misc/explosion.png", ResourceCategory.ExplosionAtlas, 4), + ["item/xporb.png"] = new ResourceLocation("item/xporb.png", ResourceCategory.ExperienceOrbAtlas, 4), + ["terrain/moon_phases.png"] = new ResourceLocation("terrain/moon_phases.png", ResourceCategory.MoonPhaseAtlas, 4), + ["misc/mapicons.png"] = new ResourceLocation("misc/mapicons.png", ResourceCategory.MapIconAtlas, 4), + ["misc/additionalmapicons.png"] = new ResourceLocation("misc/additionalmapicons.png", ResourceCategory.AdditionalMapIconsAtlas, 4), + }; + public static string GetPathFromCategory(ResourceCategory category) { return category switch { - ResourceCategory.ItemAnimation => "res/textures/items", - ResourceCategory.BlockAnimation => "res/textures/blocks", + ResourceCategory.ItemAnimation => "res/textures/items", + ResourceCategory.BlockAnimation => "res/textures/blocks", + ResourceCategory.BlockAtlas => "res/terrain.png", + ResourceCategory.ItemAtlas => "res/items.png", + ResourceCategory.ParticleAtlas => "res/particles.png", + ResourceCategory.BannerAtlas => "res/item/banner/Banner_Atlas.png", + ResourceCategory.PaintingAtlas => "res/art/kz.png", + ResourceCategory.ExplosionAtlas => "res/misc/explosion.png", + ResourceCategory.ExperienceOrbAtlas => "res/item/xporb.png", + ResourceCategory.MoonPhaseAtlas => "res/terrain/moon_phases.png", + ResourceCategory.MapIconAtlas => "res/misc/mapicons.png", + ResourceCategory.AdditionalMapIconsAtlas => "res/misc/additionalmapicons.png", _ => string.Empty }; } @@ -29,7 +56,65 @@ public static ResourceCategory GetCategoryFromPath(string path) if (path.StartsWith("res/textures/blocks")) return ResourceCategory.BlockAnimation; - return ResourceCategory.Unknown; + string categoryPath = path.Substring("res/".Length); + return _categoryLookUp.ContainsKey(categoryPath) ? _categoryLookUp[categoryPath].Category : ResourceCategory.Unknown; + } + + public static ResourceLocation GetFromPath(string path) + { + if (string.IsNullOrWhiteSpace(path) || !path.StartsWith("res/")) + return null; + string categoryPath = path.Substring("res/".Length); + if (categoryPath.StartsWith("textures/items")) + categoryPath = "textures/items"; + if (categoryPath.StartsWith("textures/blocks")) + categoryPath = "textures/blocks"; + return _categoryLookUp.ContainsKey(categoryPath) ? _categoryLookUp[categoryPath] : null; + } + + public enum TillingMode + { + Width, + Height, + Custom + } + + public readonly string Path; + public readonly ResourceCategory Category; + public readonly Size TillingFactor; + public readonly TillingMode TillingResolution; + public readonly bool IsGroup; + + public Size GetTileArea(Size imgSize) + { + int tileFactorWidth = Math.Max(1, TillingFactor.Width); + int tileFactorHeight = Math.Max(1, TillingFactor.Height); + return TillingResolution switch + { + TillingMode.Width => new Size(imgSize.Width / tileFactorWidth, imgSize.Width / tileFactorHeight), + TillingMode.Height => new Size(imgSize.Height / tileFactorWidth, imgSize.Height / tileFactorHeight), + TillingMode.Custom => new Size(imgSize.Width / tileFactorWidth, imgSize.Height / tileFactorHeight), + _ => Size.Empty, + }; + } + + private ResourceLocation(string path, ResourceCategory category, int tillingFactor, TillingMode tillingResolution = TillingMode.Width, bool isGroup = false) + : this(path, category, new Size(tillingFactor, tillingFactor), tillingResolution, isGroup) + { + } + + private ResourceLocation(string path, ResourceCategory category, Size tillingFactor, TillingMode tillingResolution = TillingMode.Width, bool isGroup = false) + { + Path = path; + Category = category; + TillingFactor = tillingFactor; + TillingResolution = tillingResolution; + IsGroup = isGroup; + } + + public override string ToString() + { + return "res/" + Path; } } } diff --git a/PCK-Studio/MainForm.cs b/PCK-Studio/MainForm.cs index 4912cee9..4354fe17 100644 --- a/PCK-Studio/MainForm.cs +++ b/PCK-Studio/MainForm.cs @@ -457,71 +457,19 @@ private void HandleTextureFile(PckAsset asset) return; } - bool isTerrain = asset.Filename == "res/terrain.png"; - bool isItems = asset.Filename == "res/items.png"; - bool isParticles = asset.Filename == "res/particles.png"; - bool isMoonPhases = asset.Filename == "res/terrain/moon_phases.png"; - bool isMapIcons = asset.Filename == "res/misc/mapicons.png"; - bool isAdditionalMapIcons = asset.Filename == "res/misc/additionalmapicons.png"; - bool isXPOrbs = asset.Filename == "res/item/xporb.png"; - bool isExplosions = asset.Filename == "res/misc/explosion.png"; - bool isPaintings = asset.Filename == "res/art/kz.png"; - bool isBanners = asset.Filename == "res/item/banner/Banner_Atlas.png"; - - if ( - isTerrain || isItems || isParticles || isMoonPhases || isPaintings || - isMapIcons || isAdditionalMapIcons || isXPOrbs || isExplosions || isBanners - ) + ResourceLocation resourceLocation = ResourceLocation.GetFromPath(asset.Filename); + Debug.WriteLine("Handling Resource file: " + resourceLocation.ToString()); + if (resourceLocation is null || resourceLocation.Category == ResourceCategory.Unknown) + return; + + if (resourceLocation.Category != ResourceCategory.BlockAnimation && + resourceLocation.Category != ResourceCategory.ItemAnimation) { Image img = asset.GetTexture(); - var tile_size = new Size(); - - int banner_scale = img.Width / Resources.banners_atlas.Width; - - if (isBanners) - { - // The banner atlas has extra space on it that has to be truncated for the editor - img = img.GetArea(new Rectangle(0, 0, img.Width - (4 * banner_scale), img.Height - (1 * banner_scale))); - - // banners are 42x41 because of course they are - tile_size = new Size(42 * banner_scale, 41 * banner_scale); - } - - // most atlases have 4 columns - int columnCount = isBanners ? 6 : 4; - - if (isTerrain || isItems || isParticles || isPaintings) columnCount = 16; - - if (!isBanners) - { - int resolution = img.Width / columnCount; - tile_size = new Size(resolution, resolution); - } - - var viewer = new TextureAtlasEditor(currentPCK, asset.Filename, img, tile_size); + var viewer = new TextureAtlasEditor(currentPCK, resourceLocation, img); if (viewer.ShowDialog(this) == DialogResult.OK) { Image texture = viewer.FinalTexture; - if(isBanners) - { - var graphicsConfig = new GraphicsConfig() - { - InterpolationMode = InterpolationMode.NearestNeighbor, - PixelOffsetMode = PixelOffsetMode.HighQuality - }; - - var _img = new Bitmap((Resources.banners_atlas.Width + 4) * banner_scale, - (Resources.banners_atlas.Height + 1) * banner_scale); - - using (Graphics g = Graphics.FromImage(_img)) - { - g.ApplyConfig(graphicsConfig); - g.DrawImage(texture, 0, 0, texture.Width, texture.Height); - } - - texture = _img; - } - asset.SetTexture(texture); wasModified = true; BuildMainTreeView(); @@ -529,24 +477,24 @@ private void HandleTextureFile(PckAsset asset) return; } - if (!asset.Filename.StartsWith(ResourceLocation.GetPathFromCategory(ResourceCategory.ItemAnimation)) && - !asset.Filename.StartsWith(ResourceLocation.GetPathFromCategory(ResourceCategory.BlockAnimation))) + if (resourceLocation.Category != ResourceCategory.ItemAnimation && + resourceLocation.Category != ResourceCategory.BlockAnimation) return; Animation animation = asset.GetDeserializedData(AnimationDeserializer.DefaultDeserializer); - string filename = Path.GetFileNameWithoutExtension(asset.Filename); + string internalName = Path.GetFileNameWithoutExtension(asset.Filename); - var textureInfos = ResourceLocation.GetCategoryFromPath(asset.Filename) switch + var textureInfos = resourceLocation.Category switch { ResourceCategory.BlockAnimation => Tiles.BlockTileInfos, ResourceCategory.ItemAnimation => Tiles.ItemTileInfos, _ => Array.Empty().ToList() }; - string displayname = textureInfos.FirstOrDefault(p => p.InternalName == filename)?.DisplayName ?? filename; + string displayname = textureInfos.FirstOrDefault(p => p.InternalName == internalName)?.DisplayName ?? internalName; string[] specialTileNames = { "clock", "compass" }; - using (AnimationEditor animationEditor = new AnimationEditor(animation, displayname, filename.ToLower().EqualsAny(specialTileNames))) + using (AnimationEditor animationEditor = new AnimationEditor(animation, displayname, internalName.ToLower().EqualsAny(specialTileNames))) { if (animationEditor.ShowDialog(this) == DialogResult.OK) { @@ -708,34 +656,24 @@ private void treeViewMain_AfterSelect(object sender, TreeViewEventArgs e) Debug.WriteLine(string.Format("An error occured of type: {0} with message: {1}", ex.GetType(), ex.Message), "Exception"); } - if ((asset.Filename.StartsWith(ResourceLocation.GetPathFromCategory(ResourceCategory.ItemAnimation)) || - asset.Filename.StartsWith(ResourceLocation.GetPathFromCategory(ResourceCategory.BlockAnimation))) && - asset.Type == PckAssetType.TextureFile - && !asset.IsMipmappedFile()) + if (asset.Type != PckAssetType.TextureFile) + break; + + ResourceLocation resourceLocation = ResourceLocation.GetFromPath(asset.Filename); + if (resourceLocation is null || resourceLocation.Category == ResourceCategory.Unknown) + break; + + if (resourceLocation.Category == ResourceCategory.ItemAnimation || + resourceLocation.Category == ResourceCategory.BlockAnimation && + !asset.IsMipmappedFile()) { buttonEdit.Text = "EDIT TILE ANIMATION"; buttonEdit.Visible = true; + break; } - bool isTerrain = asset.Filename == "res/terrain.png"; - bool isItems = asset.Filename == "res/items.png"; - bool isParticles = asset.Filename == "res/particles.png"; - bool isMoonPhases = asset.Filename == "res/terrain/moon_phases.png"; - bool isMapIcons = asset.Filename == "res/misc/mapicons.png"; - bool isAdditionalMapIcons = asset.Filename == "res/misc/additionalmapicons.png"; - bool isXPOrbs = asset.Filename == "res/item/xporb.png"; - bool isExplosions = asset.Filename == "res/misc/explosion.png"; - bool isPaintings = asset.Filename == "res/art/kz.png"; - bool isBanners = asset.Filename == "res/item/banner/Banner_Atlas.png"; - - if (( - isTerrain || isItems || isParticles || isMoonPhases || isPaintings || - isMapIcons || isAdditionalMapIcons || isXPOrbs || isExplosions || isBanners - ) && asset.Type == PckAssetType.TextureFile) - { - buttonEdit.Text = "EDIT TEXTURE ATLAS"; - buttonEdit.Visible = true; - } + buttonEdit.Text = "EDIT TEXTURE ATLAS"; + buttonEdit.Visible = true; } break;