mirror of
https://mirror.ghproxy.com/https://github.com/dexyfex/CodeWalker
synced 2024-11-22 15:02:54 +08:00
feat(ytdform): add drag-and-drop support for multiple files with uniqueness and power-of-2 checks
This commit is contained in:
parent
c45ea83733
commit
40e9757dbc
@ -3,16 +3,15 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
|
|
||||||
namespace CodeWalker.GameFiles
|
namespace CodeWalker.GameFiles
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class TextureDictionary : ResourceFileBase
|
[TypeConverter(typeof(ExpandableObjectConverter))]
|
||||||
|
public class TextureDictionary : ResourceFileBase
|
||||||
{
|
{
|
||||||
public override long BlockLength
|
public override long BlockLength
|
||||||
{
|
{
|
||||||
@ -172,7 +171,7 @@ namespace CodeWalker.GameFiles
|
|||||||
public void BuildFromTextureList(List<Texture> textures)
|
public void BuildFromTextureList(List<Texture> textures)
|
||||||
{
|
{
|
||||||
textures.Sort((a, b) => a.NameHash.CompareTo(b.NameHash));
|
textures.Sort((a, b) => a.NameHash.CompareTo(b.NameHash));
|
||||||
|
|
||||||
var texturehashes = new List<uint>();
|
var texturehashes = new List<uint>();
|
||||||
foreach (var tex in textures)
|
foreach (var tex in textures)
|
||||||
{
|
{
|
||||||
@ -188,7 +187,8 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class TextureBase : ResourceSystemBlock
|
[TypeConverter(typeof(ExpandableObjectConverter))]
|
||||||
|
public class TextureBase : ResourceSystemBlock
|
||||||
{
|
{
|
||||||
public override long BlockLength
|
public override long BlockLength
|
||||||
{
|
{
|
||||||
@ -430,7 +430,8 @@ namespace CodeWalker.GameFiles
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class Texture : TextureBase
|
[TypeConverter(typeof(ExpandableObjectConverter))]
|
||||||
|
public class Texture : TextureBase
|
||||||
{
|
{
|
||||||
public override long BlockLength
|
public override long BlockLength
|
||||||
{
|
{
|
||||||
@ -475,6 +476,23 @@ namespace CodeWalker.GameFiles
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the <see cref="Texture.Width"/> and <see cref="Texture.Height"/> are powers of two.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// It is not necessary for the <see cref="Texture.Width"/> and <see cref="Texture.Height"/> to be the same.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>
|
||||||
|
/// <see langword="true"/> if the <see cref="Texture.Width"/> and <see cref="Texture.Height"/> are powers of two; otherwise, <see langword="false"/>.
|
||||||
|
/// </value>
|
||||||
|
public bool IsPowerOf2
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (Width & (Width - 1)) == 0 && (Height & (Height - 1)) == 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void Read(ResourceDataReader reader, params object[] parameters)
|
public override void Read(ResourceDataReader reader, params object[] parameters)
|
||||||
{
|
{
|
||||||
base.Read(reader, parameters);
|
base.Read(reader, parameters);
|
||||||
@ -612,7 +630,8 @@ namespace CodeWalker.GameFiles
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class TextureData : ResourceGraphicsBlock
|
[TypeConverter(typeof(ExpandableObjectConverter))]
|
||||||
|
public class TextureData : ResourceGraphicsBlock
|
||||||
{
|
{
|
||||||
public override long BlockLength
|
public override long BlockLength
|
||||||
{
|
{
|
||||||
|
3
CodeWalker/Forms/YtdForm.Designer.cs
generated
3
CodeWalker/Forms/YtdForm.Designer.cs
generated
@ -310,6 +310,7 @@
|
|||||||
//
|
//
|
||||||
// TexturesListView
|
// TexturesListView
|
||||||
//
|
//
|
||||||
|
this.TexturesListView.AllowDrop = true;
|
||||||
this.TexturesListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
this.TexturesListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
| System.Windows.Forms.AnchorStyles.Left)
|
| System.Windows.Forms.AnchorStyles.Left)
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
@ -326,6 +327,8 @@
|
|||||||
this.TexturesListView.UseCompatibleStateImageBehavior = false;
|
this.TexturesListView.UseCompatibleStateImageBehavior = false;
|
||||||
this.TexturesListView.View = System.Windows.Forms.View.Details;
|
this.TexturesListView.View = System.Windows.Forms.View.Details;
|
||||||
this.TexturesListView.SelectedIndexChanged += new System.EventHandler(this.TexturesListView_SelectedIndexChanged);
|
this.TexturesListView.SelectedIndexChanged += new System.EventHandler(this.TexturesListView_SelectedIndexChanged);
|
||||||
|
this.TexturesListView.DragDrop += new System.Windows.Forms.DragEventHandler(this.TexturesListView_DragDrop);
|
||||||
|
this.TexturesListView.DragEnter += new System.Windows.Forms.DragEventHandler(this.TexturesListView_DragEnter);
|
||||||
//
|
//
|
||||||
// TextureNameColumnHeader
|
// TextureNameColumnHeader
|
||||||
//
|
//
|
||||||
|
@ -200,8 +200,13 @@ namespace CodeWalker.Forms
|
|||||||
var tex = OpenDDSFile();
|
var tex = OpenDDSFile();
|
||||||
if (tex == null) return;
|
if (tex == null) return;
|
||||||
|
|
||||||
var textures = new List<Texture>();
|
var textures = new List<Texture>(TexDict.Textures.data_items);
|
||||||
textures.AddRange(TexDict.Textures.data_items);
|
if (textures.Any(t => t.Name.Equals(tex.Name, StringComparison.InvariantCultureIgnoreCase)))
|
||||||
|
{
|
||||||
|
MessageBox.Show($"A texture with the name {tex.Name} already exists in this YTD.\nAll textures must have unique names in a YTD.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
textures.Add(tex);
|
textures.Add(tex);
|
||||||
|
|
||||||
TexDict.BuildFromTextureList(textures);
|
TexDict.BuildFromTextureList(textures);
|
||||||
@ -322,6 +327,12 @@ namespace CodeWalker.Forms
|
|||||||
{
|
{
|
||||||
var dds = File.ReadAllBytes(fn);
|
var dds = File.ReadAllBytes(fn);
|
||||||
var tex = DDSIO.GetTexture(dds);
|
var tex = DDSIO.GetTexture(dds);
|
||||||
|
if (!tex.IsPowerOf2)
|
||||||
|
{
|
||||||
|
MessageBox.Show($"The texture is not a power of two texture.\nThe texture must have a width and height equal to a power of two e.g. 256, 512, 1024, etc...");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
tex.Name = Path.GetFileNameWithoutExtension(fn);
|
tex.Name = Path.GetFileNameWithoutExtension(fn);
|
||||||
tex.NameHash = JenkHash.GenHash(tex.Name?.ToLowerInvariant());
|
tex.NameHash = JenkHash.GenHash(tex.Name?.ToLowerInvariant());
|
||||||
JenkIndex.Ensure(tex.Name?.ToLowerInvariant());
|
JenkIndex.Ensure(tex.Name?.ToLowerInvariant());
|
||||||
@ -649,5 +660,120 @@ namespace CodeWalker.Forms
|
|||||||
{
|
{
|
||||||
RenameTexture(SelTextureNameTextBox.Text);
|
RenameTexture(SelTextureNameTextBox.Text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add one or more textures to the YTD by dragging and dropping them into the YTD.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">
|
||||||
|
/// The source of the event.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="e">
|
||||||
|
/// The <see cref="DragEventArgs"/> that contains the event data.
|
||||||
|
/// </param>
|
||||||
|
private void TexturesListView_DragDrop(object sender, DragEventArgs e)
|
||||||
|
{
|
||||||
|
if (TexDict.Textures?.data_items == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!e.Data.GetDataPresent(DataFormats.FileDrop))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string[] filePaths = e.Data.GetData(DataFormats.FileDrop) as string[];
|
||||||
|
if (filePaths == null)
|
||||||
|
{
|
||||||
|
// Couldn't get files paths?
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Texture> newTextures = new List<Texture>(TexDict.Textures.data_items);
|
||||||
|
foreach (string filePath in filePaths)
|
||||||
|
{
|
||||||
|
if (!filePath.EndsWith(".dds", StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
// Not a DDS file?
|
||||||
|
MessageBox.Show("You can only drag and drop DDS files into an YTD.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!File.Exists(filePath))
|
||||||
|
{
|
||||||
|
// Couldn't find file?
|
||||||
|
MessageBox.Show($"Couldn't find file {filePath}.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if a texture with the same name already exists in the YTD.
|
||||||
|
string textureName = Path.GetFileNameWithoutExtension(filePath);
|
||||||
|
if(newTextures.Any(t => t.Name.Equals(textureName, StringComparison.InvariantCultureIgnoreCase)))
|
||||||
|
{
|
||||||
|
MessageBox.Show($"A texture with the name {textureName} already exists in this YTD.\nAll textures must have unique names in a YTD.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] dds = File.ReadAllBytes(filePath);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Texture texture = DDSIO.GetTexture(dds);
|
||||||
|
if(texture == null)
|
||||||
|
{
|
||||||
|
throw new Exception("Something went wrong while loading the texture.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!texture.IsPowerOf2)
|
||||||
|
{
|
||||||
|
MessageBox.Show($"The texture {filePath} is not a power of two texture.\nThe texture must have a width and height equal to a power of two e.g. 256, 512, 1024, etc...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
texture.Name = textureName;
|
||||||
|
texture.NameHash = JenkHash.GenHash(texture.Name?.ToLowerInvariant());
|
||||||
|
JenkIndex.Ensure(texture.Name?.ToLowerInvariant());
|
||||||
|
newTextures.Add(texture);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
MessageBox.Show($"Unable to load {filePath}.\nAre you sure it's a valid .dds file?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TexDict.BuildFromTextureList(newTextures);
|
||||||
|
|
||||||
|
Modified = true;
|
||||||
|
|
||||||
|
LoadTexDict(TexDict, FileName);
|
||||||
|
|
||||||
|
UpdateModelFormTextures();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the files can be dropped into the YTD.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">
|
||||||
|
/// The source of the event.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="e">
|
||||||
|
/// The <see cref="DragEventArgs"/> that contains the event data.
|
||||||
|
/// </param>
|
||||||
|
private void TexturesListView_DragEnter(object sender, DragEventArgs e)
|
||||||
|
{
|
||||||
|
if (!e.Data.GetDataPresent(DataFormats.FileDrop))
|
||||||
|
{
|
||||||
|
e.Effect = DragDropEffects.None;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string[] files = e.Data.GetData(DataFormats.FileDrop) as string[];
|
||||||
|
if (files == null)
|
||||||
|
{
|
||||||
|
e.Effect = DragDropEffects.None;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
e.Effect = DragDropEffects.Copy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user