mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/PCK-Studio.git
synced 2026-06-04 15:15:01 +00:00
Extended ResourceLocation for better atlas handling
This commit is contained in:
@@ -30,6 +30,7 @@ using OMI.Formats.Pck;
|
||||
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 @@ namespace PckStudio.Forms.Editor
|
||||
private readonly Size _areaSize;
|
||||
private readonly int _rowCount;
|
||||
private readonly int _columnCount;
|
||||
private readonly string _atlasType;
|
||||
private readonly ResourceLocation _atlasType;
|
||||
private readonly List<AtlasTile> _tiles;
|
||||
|
||||
private AtlasTile _selectedTile;
|
||||
@@ -93,7 +94,7 @@ namespace PckStudio.Forms.Editor
|
||||
|
||||
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 @@ namespace PckStudio.Forms.Editor
|
||||
|
||||
_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 @@ namespace PckStudio.Forms.Editor
|
||||
|
||||
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 @@ namespace PckStudio.Forms.Editor
|
||||
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;
|
||||
|
||||
|
||||
@@ -22,6 +22,16 @@ namespace PckStudio.Internal
|
||||
{
|
||||
Unknown = -1,
|
||||
ItemAnimation,
|
||||
BlockAnimation
|
||||
BlockAnimation,
|
||||
ItemAtlas,
|
||||
BlockAtlas,
|
||||
ParticleAtlas,
|
||||
BannerAtlas,
|
||||
PaintingAtlas,
|
||||
ExplosionAtlas,
|
||||
ExperienceOrbAtlas,
|
||||
MoonPhaseAtlas,
|
||||
MapIconAtlas,
|
||||
AdditionalMapIconsAtlas,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<string, ResourceLocation> _categoryLookUp = new Dictionary<string, ResourceLocation>()
|
||||
{
|
||||
["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 @@ namespace PckStudio.Internal
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -457,71 +457,19 @@ namespace PckStudio
|
||||
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";
|
||||
ResourceLocation resourceLocation = ResourceLocation.GetFromPath(asset.Filename);
|
||||
Debug.WriteLine("Handling Resource file: " + resourceLocation.ToString());
|
||||
if (resourceLocation is null || resourceLocation.Category == ResourceCategory.Unknown)
|
||||
return;
|
||||
|
||||
if (
|
||||
isTerrain || isItems || isParticles || isMoonPhases || isPaintings ||
|
||||
isMapIcons || isAdditionalMapIcons || isXPOrbs || isExplosions || isBanners
|
||||
)
|
||||
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 @@ namespace PckStudio
|
||||
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<JsonTileInfo>().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 @@ namespace PckStudio
|
||||
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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user