mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/PCK-Studio.git
synced 2026-06-17 05:52:29 +00:00
TextureAtlas - Impl extraction&import of large tiles
This commit is contained in:
@@ -16,19 +16,22 @@
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Drawing;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Windows.Forms;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
|
||||
using System.Drawing.Imaging;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using OMI.Formats.Color;
|
||||
using OMI.Workers.Color;
|
||||
using PckStudio.Controls;
|
||||
using PckStudio.Core;
|
||||
using PckStudio.Core.Extensions;
|
||||
using PckStudio.Interfaces;
|
||||
using PckStudio.Controls;
|
||||
using OMI.Formats.Color;
|
||||
using PckStudio.Core.Json;
|
||||
using PckStudio.Interfaces;
|
||||
using PckStudio.Internal;
|
||||
using PckStudio.Properties;
|
||||
|
||||
namespace PckStudio.Forms.Editor
|
||||
{
|
||||
@@ -50,16 +53,15 @@ namespace PckStudio.Forms.Editor
|
||||
|
||||
_ = atlas ?? throw new ArgumentNullException(nameof(atlas));
|
||||
_ = resourceLocation ?? throw new ArgumentNullException(nameof(resourceLocation));
|
||||
|
||||
_atlas = atlas;
|
||||
Text = _atlas.Name;
|
||||
originalPictureBox.Image = atlas;
|
||||
|
||||
_colourTable = colorContainer ?? new ColorContainer();
|
||||
_colourTable = colorContainer ?? AppResourceManager.Default.GetData(Resources.tu69colours, new COLFileReader());
|
||||
_tryGetAnimation = tryGetAnimation;
|
||||
_tryGetAnimationSaveContext = tryGetAnimationSaveContext;
|
||||
_atlas = atlas;
|
||||
_resourceLocationCategory = resourceLocation.Category;
|
||||
|
||||
_atlas.AllowGroups = allowGroupsToolStripMenuItem.Checked;
|
||||
SelectedIndex = 0;
|
||||
|
||||
animationButton.Enabled =
|
||||
@@ -110,7 +112,7 @@ namespace PckStudio.Forms.Editor
|
||||
g.DrawImage(image, 0, 0, image.Width, image.Height);
|
||||
|
||||
SolidBrush brush = new SolidBrush(Color.FromArgb(127, Color.White));
|
||||
g.FillRectangle(brush, _atlas.GetTileArea(_selectedTile));
|
||||
g.FillRectangle(brush, allowGroupsToolStripMenuItem.Checked ? _atlas.GetTileArea(_selectedTile) : _selectedTile.GetArea(_atlas.TileSize));
|
||||
}
|
||||
originalPictureBox.Invalidate();
|
||||
}
|
||||
@@ -294,6 +296,15 @@ namespace PckStudio.Forms.Editor
|
||||
|
||||
private void SetTile(Image texture)
|
||||
{
|
||||
if (_selectedTile.IsPartOfGroup)
|
||||
{
|
||||
AtlasGroup group = _selectedTile.GetGroup();
|
||||
_atlas.SetGroup(group, texture);
|
||||
selectTilePictureBox.Image = _atlas.GetTileTexture(_selectedTile);
|
||||
UpdateAtlasDisplay();
|
||||
return;
|
||||
}
|
||||
|
||||
if (texture.Size != _atlas.TileSize)
|
||||
texture = texture.Resize(_atlas.TileSize, _graphicsConfig);
|
||||
|
||||
@@ -415,7 +426,7 @@ namespace PckStudio.Forms.Editor
|
||||
|
||||
if (fileDialog.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
var img = Image.FromFile(fileDialog.FileName);
|
||||
Image img = Image.FromFile(fileDialog.FileName).ReleaseFromFile();
|
||||
SetTile(img);
|
||||
}
|
||||
}
|
||||
@@ -457,10 +468,9 @@ namespace PckStudio.Forms.Editor
|
||||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
private void extractTileToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
string filename = _selectedTile.TryGetUserDataOfType(out JsonTileInfo tileInfo) ? tileInfo.InternalName : "tile";
|
||||
string filename = GetSanitizedFilename();
|
||||
SaveFileDialog saveFileDialog = new SaveFileDialog()
|
||||
{
|
||||
Filter = "Tile Texture|*.png",
|
||||
@@ -468,10 +478,22 @@ namespace PckStudio.Forms.Editor
|
||||
};
|
||||
if (saveFileDialog.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
_selectedTile.Texture.Save(saveFileDialog.FileName, ImageFormat.Png);
|
||||
_atlas.GetTileTexture(_selectedTile).Save(saveFileDialog.FileName, ImageFormat.Png);
|
||||
}
|
||||
}
|
||||
|
||||
private string GetSanitizedFilename()
|
||||
{
|
||||
if (_selectedTile.IsPartOfGroup)
|
||||
{
|
||||
AtlasGroup group = _selectedTile.GetGroup();
|
||||
return group.Name.Replace(' ', '_').Trim().ToLower();
|
||||
}
|
||||
if (_selectedTile.TryGetUserDataOfType(out JsonTileInfo tileInfo) && !string.IsNullOrWhiteSpace(tileInfo.InternalName))
|
||||
return tileInfo.InternalName;
|
||||
return "tile";
|
||||
}
|
||||
|
||||
private void variantComboBox_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (_selectedTile.TryGetUserDataOfType(out JsonTileInfo tileInfo) && variantComboBox.SelectedItem is not null)
|
||||
|
||||
45
PCK-Studio/Internal/AppResourceManager.cs
Normal file
45
PCK-Studio/Internal/AppResourceManager.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Resources;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
using OMI.Workers;
|
||||
using PckStudio.Properties;
|
||||
|
||||
namespace PckStudio.Internal
|
||||
{
|
||||
internal sealed class AppResourceManager
|
||||
{
|
||||
public static readonly AppResourceManager Default = new AppResourceManager(Resources.ResourceManager, Resources.Culture);
|
||||
private ResourceManager _resourceManager;
|
||||
private readonly CultureInfo _culture;
|
||||
|
||||
public AppResourceManager(ResourceManager resourceManager, CultureInfo culture)
|
||||
{
|
||||
_resourceManager = resourceManager ?? throw new ArgumentNullException(nameof(resourceManager));
|
||||
_culture = culture;
|
||||
}
|
||||
|
||||
public T GetData<T>(byte[] rawData, IDataFormatReader<T> dataFormatReader) where T : class
|
||||
{
|
||||
_ = rawData ?? throw new ArgumentNullException(nameof(rawData));
|
||||
_ = dataFormatReader ?? throw new ArgumentNullException(nameof(dataFormatReader));
|
||||
|
||||
T result = default;
|
||||
using (Stream resourceStream = new MemoryStream(rawData))
|
||||
{
|
||||
result = dataFormatReader.FromStream(resourceStream);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public T GetDataFromResource<T>(string name, IDataFormatReader<T> dataFormatReader) where T : class
|
||||
{
|
||||
return GetData((byte[])_resourceManager.GetObject(name, _culture), dataFormatReader);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -171,6 +171,7 @@
|
||||
<DependentUpon>ModelEditor.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Internal\ApplicationScope.cs" />
|
||||
<Compile Include="Internal\AppResourceManager.cs" />
|
||||
<Compile Include="Internal\CommitInfo.cs" />
|
||||
<Compile Include="Internal\Entities.cs" />
|
||||
<Compile Include="Internal\RichPresenceClient.cs" />
|
||||
|
||||
@@ -32,8 +32,6 @@ namespace PckStudio.Core
|
||||
public Size TileSize { get; }
|
||||
public int TileCount => _tiles.Length;
|
||||
|
||||
public bool AllowGroups { get; set; } = default;
|
||||
|
||||
private readonly AtlasTile[] _tiles;
|
||||
private readonly ImageLayoutDirection _layoutDirection;
|
||||
private readonly List<AtlasGroup> _groups;
|
||||
@@ -122,22 +120,19 @@ namespace PckStudio.Core
|
||||
yield break;
|
||||
}
|
||||
|
||||
private void SetRange(int row, int col, int count, IEnumerable<Image> tiles)
|
||||
private void SetRange(int row, int col, int count, ImageLayoutDirection direction, IEnumerable<Image> tiles)
|
||||
=> SetRange(row, col, direction == ImageLayoutDirection.Horizontal ? count : 1, direction == ImageLayoutDirection.Vertical ? count : 1, tiles);
|
||||
private void SetRange(int row, int col, int rowCount, int columnCount, IEnumerable<Image> tiles)
|
||||
{
|
||||
Image[] atlasTiles = tiles.ToArray();
|
||||
if (atlasTiles.Length < count)
|
||||
return;
|
||||
count = count < atlasTiles.Length ? count : atlasTiles.Length;
|
||||
for (int i = 0; i < count; i++)
|
||||
for (int j = 0; j < columnCount; j++)
|
||||
{
|
||||
if (row < Rows)
|
||||
for (int i = 0; i < rowCount; i++)
|
||||
{
|
||||
this[row++, col].Texture = atlasTiles[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
row %= Rows;
|
||||
this[row, col++].Texture = atlasTiles[i];
|
||||
if ((row + i) < Rows && (col + j) < Columns)
|
||||
{
|
||||
this[row + i, col + j].Texture = atlasTiles[(j * rowCount) + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -179,7 +174,7 @@ namespace PckStudio.Core
|
||||
|
||||
public void SetGroupTilesFromAnimation(AtlasGroup group, Animation animation)
|
||||
{
|
||||
SetRange(group.Row, group.Column, group.Count, animation.GetFrames().Select(f => f.Texture));
|
||||
SetRange(group.Row, group.Column, group.Count, group.Direction, animation.GetFrames().Select(f => f.Texture));
|
||||
}
|
||||
|
||||
private IEnumerable<AtlasTile> GetLargeTile(AtlasGroupLargeTile group) => GetRange(group.Row, group.Column, group.RowSpan, group.ColumnSpan);
|
||||
@@ -218,10 +213,19 @@ namespace PckStudio.Core
|
||||
|
||||
public Rectangle GetTileArea(AtlasTile tile)
|
||||
{
|
||||
if (!tile.IsPartOfGroup || !AllowGroups)
|
||||
return new Rectangle(new Point(tile.Row * TileSize.Width, tile.Column * TileSize.Height), TileSize);
|
||||
if (!tile.IsPartOfGroup)
|
||||
return tile.GetArea(TileSize);
|
||||
AtlasGroup group = tile.GetGroup();
|
||||
return new Rectangle(new Point(group.Row * TileSize.Width, group.Column * TileSize.Height), group.GetSize(TileSize));
|
||||
}
|
||||
|
||||
public void SetGroup(AtlasGroup group, Image texture)
|
||||
{
|
||||
IEnumerable<Image> images = texture.Split(TileSize, group.Direction);
|
||||
if (!images.All(img => img.Size == TileSize))
|
||||
return;
|
||||
Size s = group.GetSize(new Size(1, 1));
|
||||
SetRange(group.Row, group.Column, s.Width, s.Height, images);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,7 @@ namespace PckStudio.Core
|
||||
public bool IsAnimation() => isAnimation;
|
||||
public bool IsLargeTile() => isLargeTile;
|
||||
|
||||
internal abstract Size GetSize(Size tileSize);
|
||||
public abstract Size GetSize(Size tileSize);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,7 @@ namespace PckStudio.Core
|
||||
|
||||
protected override bool isLargeTile => false;
|
||||
|
||||
internal override Size GetSize(Size tileSize) => new Size(tileSize.Width * (Direction == ImageLayoutDirection.Horizontal ? Count : 1), tileSize.Height * (Direction == ImageLayoutDirection.Vertical ? Count : 1));
|
||||
public override Size GetSize(Size tileSize) => new Size(tileSize.Width * (Direction == ImageLayoutDirection.Horizontal ? Count : 1), tileSize.Height * (Direction == ImageLayoutDirection.Vertical ? Count : 1));
|
||||
|
||||
public AtlasGroupAnimation(string name, int row, int column, int frameCount, ImageLayoutDirection direction, int frameTime = Animation.MinimumFrameTime)
|
||||
: base(name, row, column)
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace PckStudio.Core
|
||||
|
||||
protected override bool isLargeTile => true;
|
||||
|
||||
internal override Size GetSize(Size tileSize) => new Size(RowSpan * tileSize.Width, ColumnSpan * tileSize.Height);
|
||||
public override Size GetSize(Size tileSize) => new Size(RowSpan * tileSize.Width, ColumnSpan * tileSize.Height);
|
||||
|
||||
public AtlasGroupLargeTile(string name, int row, int column, int rowSpan, int columnSpan)
|
||||
: base(name, row, column)
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace PckStudio.Core
|
||||
|
||||
protected override bool isLargeTile => true;
|
||||
|
||||
internal override Size GetSize(Size tileSize) => new Size(RowSpan * tileSize.Width * (Direction == ImageLayoutDirection.Horizontal ? _frameCount : 1), ColumnSpan * tileSize.Height * (Direction == ImageLayoutDirection.Vertical ? _frameCount : 1));
|
||||
public override Size GetSize(Size tileSize) => new Size(RowSpan * tileSize.Width * (Direction == ImageLayoutDirection.Horizontal ? _frameCount : 1), ColumnSpan * tileSize.Height * (Direction == ImageLayoutDirection.Vertical ? _frameCount : 1));
|
||||
|
||||
public AtlasGroupLargeTileAnimation(string name, int row, int column, int rowSpan, int columnSpan, int frameCount, ImageLayoutDirection direction, int frameTime = Animation.MinimumFrameTime)
|
||||
: base(name, row, column)
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
namespace PckStudio.Core
|
||||
@@ -47,6 +48,8 @@ namespace PckStudio.Core
|
||||
}
|
||||
|
||||
public AtlasGroup GetGroup() => _group;
|
||||
|
||||
public Rectangle GetArea(Size tileSize) => new Rectangle(new Point(Row * tileSize.Width, Column * tileSize.Height), tileSize);
|
||||
|
||||
public static implicit operator Image(AtlasTile tile) => tile.Texture;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user