Files
PCK-Studio/MinecraftUSkinEditor/Forms/Utilities/Audio/AudioEditor.cs
MattNL 7ac0688654 Huge Animation Editor Update
-"Move Up" and "Move Down" functions finally work properly and with folders!
-Animation Editor can import Java block and item animations
-Animation Editor has a built-in Change Tile function where every single block and item that can be animated is listed (clock and compass are excluded since they have animations based on game data). When selected, it will automatically set your animation to that tile for you. If a required folder is missing, the function will create the folder for you and place the file inside. Happy animating! (:
-Removed the old "Create Animated Texture" function and replaced it with the new Animation Editor
-Moved the Audio Editor and Animation Editor into their own folders in the Utilities folder to keep things a little more organized in the solution.
2022-04-29 19:57:16 -04:00

289 lines
8.4 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using MetroFramework.Forms;
using PckStudio;
// Audio Editor by MattNL
namespace PckStudio.Forms.Utilities
{
public partial class AudioEditor : MetroForm
{
public string defaultType;
public string cat;
public List<int> cats = new List<int>();
public List<int> totalCats = new List<int>();
public string getCatString(int cat)
{
switch (cat)
{
case 0: return "Overworld"; break;
case 1: return "Nether"; break;
case 2: return "End"; break;
case 3: return "Creative"; break;
case 4: return "Menu"; break;
case 5: return "Battle"; break;
case 6: return "Tumble"; break;
case 7: return "Glide"; break;
case 8: return "Unused"; break; // Unknown what this is used for. Probably the scrapped Mini Game 4 referenced in the code
default: return "Not valid"; break;
}
}
public int getCatID(string cat)
{
switch (cat)
{
case "Overworld": return 0; break;
case "Nether": return 1; break;
case "End": return 2; break;
case "Creative": return 3; break;
case "Menu": return 4; break;
case "Battle": return 5; break;
case "Tumble": return 6; break;
case "Glide": return 7; break;
case "Unused": return 8; break; // Unknown what this is used for. Probably the scrapped Mini Game 4 referenced in the code
default: return -1; break;
}
}
PCK audioPCK = new PCK();
PCK.MineFile mf;
public AudioEditor(byte[] data, PCK.MineFile MineFile)
{
InitializeComponent();
audioPCK.Read(data);
int check; // This is needed for the TryGetValue function which is annoying
if(!audioPCK.typeCodes.TryGetValue("CUENAME", out check))
{
throw new System.Exception("This is not a valid audio.pck file");
}
mf = MineFile;
int index = 0;
List<PCK.MineFile> tempMineFiles = audioPCK.mineFiles.ToList();
foreach (PCK.MineFile mineFile in tempMineFiles)
{
mineFile.name = getCatString(mineFile.type);
Console.WriteLine("Category Found: " + mineFile.name);
if (cats.Contains<int>(mineFile.type))
{
Console.WriteLine("Duplicate category found, " + getCatString(mineFile.type) + ". Combining...");
List<object[]> newEntries = mineFile.entries.ToList();
audioPCK.mineFiles.Remove(mineFile);
audioPCK.mineFiles.Find(category => category.name == getCatString(mineFile.type)).entries.AddRange(newEntries);
}
else
{
TreeNode treeNode = new TreeNode();
treeNode.Text = mineFile.name;
treeNode.Tag = mineFile;
treeView1.Nodes.Add(treeNode);
cats.Add(mineFile.type);
}
index++;
continue;
}
}
private void treeView2_AfterSelect(object sender, TreeViewEventArgs e)
{
comboBox1.Items.Clear();//Resets metadata combobox of selectable entry names
object[] strings = (object[])e.Node.Tag;
string type = audioPCK.types[0];
defaultType = type;
string value = "";
if(strings != null)
{
type = (string)strings[0];
value = (string)strings[1];
}
foreach (int metaType in audioPCK.types.Keys)
comboBox1.Items.Add(audioPCK.types[metaType]);//fills combobox with metadata from the main metadatabase
comboBox1.Text = type;//Sets currently selected metadata type to type selected in selected metadata node
textBox1.Text = value;//Sets currently selected metadata value to value selected in selected metadata node
}
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
treeView2.Nodes.Clear();
PCK.MineFile mineFile = (PCK.MineFile)e.Node.Tag;
foreach (object[] entry in mineFile.entries) //object = metadata entry(name:value)
{
object[] strings = (object[])entry;
TreeNode meta = new TreeNode();
foreach (object[] entryy in mineFile.entries)
meta.Text = (string)strings[0];
meta.Tag = entry;
treeView2.Nodes.Add(meta);
continue;
}
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (treeView2.SelectedNode != null)
{
object[] strings = (object[])treeView2.SelectedNode.Tag;
strings[1] = textBox1.Text;
}
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (treeView2.SelectedNode != null)
{
//Sets metadata type to new chosen one
object[] strings = (object[])treeView2.SelectedNode.Tag;
treeView2.SelectedNode.Text = comboBox1.Text;
strings[0] = comboBox1.Text;
}
}
private void addCategoryStripMenuItem_Click(object sender, EventArgs e)
{
try
{
int check = Enumerable.Range(0, 8).Except(cats).First(); // Exclude Unused for now
if (0 <= check && check <= 8)
{
PckStudio.addCategory add = new PckStudio.addCategory(this);//sets category adding dialog
add.ShowDialog();//displays metadata adding dialog
add.Dispose();//diposes generated metadata adding dialog data
cats.Add(getCatID(cat));
PCK.MineFile mf = new PCK.MineFile();//Creates new minefile template
var emptyBytes = new List<byte>(); // the category files are empty to not take up space
byte[] emptyBytesArray = emptyBytes.ToArray();
mf.data = emptyBytesArray;//adds file data to minefile
mf.filesize = mf.data.Length;//gets filesize for minefile
mf.name = cat;//sets minfile name to file name
mf.type = getCatID(cat);//sets minefile type to default
TreeNode addNode = new TreeNode(mf.name) { Tag = mf };//creates node for minefile
audioPCK.mineFiles.Add(mf);
treeView1.Nodes.Add(addNode);
}
}
catch(Exception ex)
{
MessageBox.Show("All possible categories are used", "There are no more categories that could be added");
}
}
private void addEntryMenuItem_Click(object sender, EventArgs e)
{
object[] obj = { defaultType, "New Entry" };
TreeNode meta = new TreeNode();
meta.Text = "New Entry";
meta.Tag = obj;
treeView2.Nodes.Insert(treeView2.SelectedNode == null ? 0 : treeView2.SelectedNode.Index + 1, meta);
((PCK.MineFile)treeView1.SelectedNode.Tag).entries.Add(obj);
}
public void treeView2_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Delete && treeView2.SelectedNode != null)
{
((PCK.MineFile)treeView1.SelectedNode.Tag).entries.Remove((object[])treeView2.SelectedNode.Tag);
treeView2.SelectedNode.Remove();
}
}
private void removeCategoryStripMenuItem_Click(object sender, EventArgs e)
{
cats.Remove(getCatID(treeView1.SelectedNode.Text));
audioPCK.mineFiles.Remove((PCK.MineFile)treeView1.SelectedNode.Tag);
treeView1.SelectedNode.Remove();
treeView2.Nodes.Clear();
}
private void removeEntryMenuItem_Click(object sender, EventArgs e)
{
((PCK.MineFile)treeView1.SelectedNode.Tag).entries.Remove((object[])treeView2.SelectedNode.Tag);
treeView2.SelectedNode.Remove();
}
private static byte[] endianReverseUnicode(byte[] str)
{
byte[] newStr = new byte[str.Length];
for (int i = 0; i < str.Length; i += 2)
{
newStr[i] = str[i + 1];
newStr[i + 1] = str[i];
}
return newStr;
}
private static void writeMinecraftString(FileOutput f, string str)
{
byte[] d = Encoding.Unicode.GetBytes(str);
f.writeInt(d.Length / 2);
f.writeBytes(endianReverseUnicode(d));
f.writeInt(0);
}
private void saveToolStripMenuItem1_Click(object sender, EventArgs e)
{
FileOutput f = new FileOutput();
f.Endian = Endianness.Big;
f.writeInt(1);
f.writeInt(audioPCK.types.Count);
foreach (int type in audioPCK.types.Keys)
{
f.writeInt(type);
writeMinecraftString(f, audioPCK.types[type]);
}
f.writeInt(audioPCK.mineFiles.Count);
foreach (PCK.MineFile mf in audioPCK.mineFiles)
{
mf.name = "";
f.writeInt(mf.data.Length);
f.writeInt(mf.type);
writeMinecraftString(f, mf.name);
}
foreach (PCK.MineFile mf in audioPCK.mineFiles)
{
string missing = "";
try
{
f.writeInt(mf.entries.Count);
foreach (object[] entry in mf.entries)
{
missing = entry[0].ToString();
f.writeInt(audioPCK.typeCodes[(string)entry[0]]);
writeMinecraftString(f, (string)entry[1]);
}
f.writeBytes(mf.data);
}
catch (Exception)
{
MessageBox.Show(missing + " is not in the main metadatabase");
break;
}
}
mf.data = f.getBytes();
}
private void metroLabel2_Click(object sender, EventArgs e)
{
}
}
}