diff --git a/PCK-Studio/Controls/CustomTabControl.cs b/PCK-Studio/Controls/CustomTabControl.cs index 94437008..a9e09f03 100644 --- a/PCK-Studio/Controls/CustomTabControl.cs +++ b/PCK-Studio/Controls/CustomTabControl.cs @@ -47,7 +47,8 @@ namespace PckStudio.Controls PageClosing?.Invoke(this, eventArg); if (!eventArg.Cancel) { - TabPages.RemoveAt(SelectedIndex); + SelectedIndex -= 1; + TabPages.RemoveAt(SelectedIndex + 1); } } } diff --git a/PCK-Studio/Controls/PckEditor.Designer.cs b/PCK-Studio/Controls/PckEditor.Designer.cs index fd54fbf1..a5351572 100644 --- a/PCK-Studio/Controls/PckEditor.Designer.cs +++ b/PCK-Studio/Controls/PckEditor.Designer.cs @@ -721,6 +721,7 @@ namespace PckStudio.Controls // this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(18)))), ((int)(((byte)(18)))), ((int)(((byte)(18))))); resources.ApplyResources(this, "$this"); + this.Controls.Add(this.previewPictureBox); this.Controls.Add(this.LittleEndianCheckBox); this.Controls.Add(this.pckFileLabel); this.Controls.Add(this.labelImageSize); @@ -729,7 +730,6 @@ namespace PckStudio.Controls this.Controls.Add(this.label11); this.Controls.Add(this.treeViewMain); this.Controls.Add(logoPictureBox); - this.Controls.Add(this.previewPictureBox); this.ForeColor = System.Drawing.Color.Transparent; this.Name = "PckEditor"; this.Load += new System.EventHandler(this.PckEditor_Load); diff --git a/PCK-Studio/Controls/PckEditor.cs b/PCK-Studio/Controls/PckEditor.cs index 047eb534..1684d54a 100644 --- a/PCK-Studio/Controls/PckEditor.cs +++ b/PCK-Studio/Controls/PckEditor.cs @@ -45,19 +45,18 @@ using OMI.Formats.Color; using OMI.Workers.Color; using MetroFramework.Forms; using PckStudio.Rendering; -using DiscordRPC; namespace PckStudio.Controls { - public partial class PckEditor : UserControl, IEditor + internal partial class PckEditor : EditorControl { - public PckFile Value => _pck; - public string SavePath => _location; - private PckFile _pck; private string _location = string.Empty; - bool __modified = false; - bool _wasModified + + private readonly OMI.Endianness _originalEndianness; + private OMI.Endianness _currentEndianness; + private bool __modified = false; + private bool _wasModified { get => __modified; set @@ -72,9 +71,10 @@ namespace PckStudio.Controls private bool _isTemplateFile = false; private int _timesSaved = 0; - private readonly Dictionary> pckFileTypeHandler; + private readonly Dictionary> pckAssetTypeHandler; - public PckEditor() + public PckEditor(PckFile pck, ISaveContext saveContext) + : base(pck, saveContext) { InitializeComponent(); @@ -111,7 +111,7 @@ namespace PckStudio.Controls imageList.Images.Add(Resources.BEHAVIOURS_ICON); // Icon for Behaviour files (behaviours.bin) imageList.Images.Add(Resources.ENTITY_MATERIALS_ICON); // Icon for Entity Material files (entityMaterials.bin) - pckFileTypeHandler = new Dictionary>(15) + pckAssetTypeHandler = new Dictionary>(15) { [PckAssetType.SkinFile] = HandleSkinFile, [PckAssetType.CapeFile] = null, @@ -130,33 +130,414 @@ namespace PckStudio.Controls [PckAssetType.MaterialFile] = HandleMaterialFile, }; } + + public new void Save() + { + base.Save(); + _timesSaved++; + _wasModified = false; + } - private void HandleInnerPckFile(PckAsset file) + public override void SaveAs() + { + using SaveFileDialog saveFileDialog = new SaveFileDialog + { + Filter = "PCK (Minecraft Console Package)|*.pck", + DefaultExt = ".pck", + }; + if (saveFileDialog.ShowDialog() == DialogResult.OK) + { + SaveTo(saveFileDialog.FileName); + pckFileLabel.Text = "Current PCK File: " + Path.GetFileName(_location); + } + } + + public override void Close() + { + if ((_wasModified || _isTemplateFile) && + MessageBox.Show("Save PCK?", _isTemplateFile ? "Unsaved PCK" : "Modified PCK", + MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes) + { + if (_isTemplateFile || string.IsNullOrEmpty(_location) || !File.Exists(_location)) + { + SaveAs(); + return; + } + Save(); + } + } + + public override void UpdateView() + { + BuildMainTreeView(); + } + + private void SaveTo(string filepath) + { + _location = filepath; + _isTemplateFile = false; + Save(); + } + + private void HandleInnerPckFile(PckAsset asset) { if (Settings.Default.LoadSubPcks && - (file.Type == PckAssetType.SkinDataFile || file.Type == PckAssetType.TexturePackInfoFile) && - file.Size > 0 && treeViewMain.SelectedNode.Nodes.Count == 0) + (asset.Type == PckAssetType.SkinDataFile || asset.Type == PckAssetType.TexturePackInfoFile) && + asset.Size > 0) { - try + ISaveContext saveContext = new DelegatedSaveContext(false, (pck) => { - var reader = new PckFileReader(LittleEndianCheckBox.Checked ? OMI.Endianness.LittleEndian : OMI.Endianness.BigEndian); - PckFile subPCKfile = file.GetData(reader); - BuildPckTreeView(treeViewMain.SelectedNode.Nodes, subPCKfile); - treeViewMain.SelectedNode.ExpandAll(); - - } - catch (OverflowException ex) - { - MessageBox.Show("Failed to open pck\n" + - "Try checking the 'Open/Save as Switch/Vita/PS4 pck' checkbox in the upper right corner.", - "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - Debug.WriteLine(ex.Message); - } - + asset.SetData(new PckFileWriter(pck, OMI.Endianness.BigEndian)); + }); + string identifier = _location + Path.GetFileName(asset.Filename); + Program.MainInstance.OpenNewPckTab(Path.GetFileName(asset.Filename), identifier, asset.GetData(new PckFileReader()), saveContext); return; } - treeViewMain.SelectedNode.Nodes.Clear(); - treeViewMain.SelectedNode.Collapse(); + } + + private void HandleTextureFile(PckAsset asset) + { + _ = asset.IsMipmappedFile() && EditorValue.TryGetValue(asset.GetNormalPath(), PckAssetType.TextureFile, out asset); + + if (asset.Size <= 0) + { + Debug.WriteLine($"'{asset.Filename}' size is 0.", category: nameof(HandleTextureFile)); + return; + } + + ResourceLocation resourceLocation = ResourceLocation.GetFromPath(asset.Filename); + Debug.WriteLine("Handling Resource file: " + resourceLocation?.ToString()); + + switch (resourceLocation.Category) + { + case ResourceCategory.Unknown: + Debug.WriteLine($"Unknown Resource Category."); + break; + case ResourceCategory.MobEntityTextures: + case ResourceCategory.ItemEntityTextures: + { + string texturePath = asset.Filename.Substring(0, asset.Filename.Length - Path.GetExtension(asset.Filename).Length); + string[] modelNames = GameModelImporter.ModelMetaData.Where(kv => kv.Value.TextureLocations.Contains(texturePath)).Select(kv => kv.Key).ToArray(); + + if (modelNames.Length == 0) + { + MessageBox.Show("No Model info found"); + return; + } + + string modelName = modelNames[0]; + if (modelNames.Length > 1) + { + using ItemSelectionPopUp itemSelectionPopUp = new ItemSelectionPopUp(modelNames.ToArray()); + itemSelectionPopUp.ButtonText = "View"; + itemSelectionPopUp.LabelText = "Models:"; + if (itemSelectionPopUp.ShowDialog() != DialogResult.OK || !modelNames.IndexInRange(itemSelectionPopUp.SelectedIndex)) + { + return; + } + modelName = modelNames[itemSelectionPopUp.SelectedIndex]; + } + + NamedTexture modelTexture = new NamedTexture(Path.GetFileName(texturePath), asset.GetTexture()); + + Model model = GetDefaultEntityModel(modelName); + if (EditorValue.TryGetAsset("models.bin", PckAssetType.ModelsFile, out PckAsset modelsAsset)) + { + ModelContainer models = modelsAsset.GetData(new ModelFileReader()); + if (models.ContainsModel(modelName)) + { + Debug.WriteLine($"Custom model for '{modelName}' found."); + model = models.GetModelByName(modelName); + } + } + + if (model is not null) + { + ShowSimpleModelRender(model, modelTexture); + } + } + break; + + case ResourceCategory.ItemAnimation: + case ResourceCategory.BlockAnimation: + Animation animation = asset.GetDeserializedData(AnimationDeserializer.DefaultDeserializer); + string internalName = Path.GetFileNameWithoutExtension(asset.Filename); + IList textureInfos = resourceLocation.Category == ResourceCategory.ItemAnimation ? Tiles.ItemTileInfos : Tiles.BlockTileInfos; + string displayname = textureInfos.FirstOrDefault(p => p.InternalName == internalName)?.DisplayName ?? internalName; + + string[] specialTileNames = { "clock", "compass" }; + + ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (animation) => + { + asset.SetSerializedData(animation, AnimationSerializer.DefaultSerializer); + }); + + using (AnimationEditor animationEditor = new AnimationEditor(animation, saveContext, displayname, internalName.ToLower().EqualsAny(specialTileNames))) + { + if (animationEditor.ShowDialog(this) == DialogResult.OK) + { + _wasModified = true; + BuildMainTreeView(); + } + } + break; + case ResourceCategory.ItemAtlas: + case ResourceCategory.BlockAtlas: + case ResourceCategory.ParticleAtlas: + case ResourceCategory.BannerAtlas: + case ResourceCategory.PaintingAtlas: + case ResourceCategory.ExplosionAtlas: + case ResourceCategory.ExperienceOrbAtlas: + case ResourceCategory.MoonPhaseAtlas: + case ResourceCategory.MapIconAtlas: + case ResourceCategory.AdditionalMapIconsAtlas: + Image atlas = asset.GetTexture(); + ColorContainer colorContainer = default; + if (EditorValue.TryGetAsset("colours.col", PckAssetType.ColourTableFile, out PckAsset colAsset)) + colorContainer = colAsset.GetData(new COLFileReader()); + + ITryGet tryGetAnimation = TryGet.FromDelegate((string key, out Animation animation) => + { + bool found = EditorValue.TryGetAsset(key + ".png", PckAssetType.TextureFile, out PckAsset foundAsset) || + EditorValue.TryGetAsset(key + ".tga", PckAssetType.TextureFile, out foundAsset); + if (found) + { + animation = foundAsset.GetDeserializedData(AnimationDeserializer.DefaultDeserializer); + return true; + } + animation = default; + return false; + }); + + ITryGet> tryGetAnimationSaveContext = TryGet> + .FromDelegate((string key, out ISaveContext animationSaveContext) => + { + bool found = EditorValue.TryGetAsset(key + ".png", PckAssetType.TextureFile, out PckAsset foundAsset) || + EditorValue.TryGetAsset(key + ".tga", PckAssetType.TextureFile, out foundAsset); + + if (found) + { + animationSaveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (animation) => + foundAsset.SetSerializedData(animation, AnimationSerializer.DefaultSerializer)); + return true; + } + + // you could validate the key(animationAssetPath) for validity. -miku + animationSaveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (animation) => + { + if (animation.FrameCount == 0) + { + Debug.WriteLine("New animation has 0 frames. Aborting saving."); + return; + } + PckAsset newAnimationAsset = EditorValue.CreateNewAsset(key + ".png", PckAssetType.TextureFile); + newAnimationAsset.SetSerializedData(animation, AnimationSerializer.DefaultSerializer); + BuildMainTreeView(); + }); + return true; + }); + + ISaveContext textureAtlasSaveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, asset.SetTexture); + + var viewer = new TextureAtlasEditor(atlas, textureAtlasSaveContext, resourceLocation, colorContainer, tryGetAnimation, tryGetAnimationSaveContext); + if (viewer.ShowDialog(this) == DialogResult.OK) + { + _wasModified = true; + BuildMainTreeView(); + } + break; + default: + Debug.WriteLine($"Unhandled Resource Category: {resourceLocation.Category}"); + break; + } + } + + private void HandleGameRuleFile(PckAsset asset) + { + const string use_deflate = "PS3"; + const string use_xmem = "Xbox 360"; + const string use_zlib = "Other Platforms"; + + ItemSelectionPopUp dialog = new ItemSelectionPopUp(use_zlib, use_deflate, use_xmem); + dialog.LabelText = "Type"; + dialog.ButtonText = "Ok"; + if (dialog.ShowDialog() != DialogResult.OK) + return; + + GameRuleFile.CompressionType compressiontype = dialog.SelectedItem switch + { + use_deflate => GameRuleFile.CompressionType.Deflate, + use_xmem => GameRuleFile.CompressionType.XMem, + use_zlib => GameRuleFile.CompressionType.Zlib, + _ => GameRuleFile.CompressionType.Unknown + }; + + GameRuleFile grf = asset.GetData(new GameRuleFileReader(compressiontype)); + + ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (gameRuleFile) => + { + asset.SetData(new GameRuleFileWriter(gameRuleFile)); + }); + + using GameRuleFileEditor grfEditor = new GameRuleFileEditor(grf, saveContext); + if (grfEditor.ShowDialog(this) == DialogResult.OK) + { + _wasModified = true; + UpdateRichPresence(); + } + } + + private void HandleAudioFile(PckAsset asset) + { + try + { + OMI.Endianness endianness = LittleEndianCheckBox.Checked ? OMI.Endianness.LittleEndian : OMI.Endianness.BigEndian; + ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (audioFile) => + { + asset.SetData(new PckAudioFileWriter(audioFile, endianness)); + }); + PckAudioFile audioFile = asset.GetData(new PckAudioFileReader(endianness)); + using AudioEditor audioEditor = new AudioEditor(audioFile, saveContext); + _wasModified = audioEditor.ShowDialog(this) == DialogResult.OK; + } + catch (OverflowException) + { + MessageBox.Show(this, $"Failed to open {asset.Filename}\n" + + "Try converting the file by using the \"Misc. Functions/Set PCK Endianness\" tool and try again.", + "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning); + } + catch (Exception ex) + { + MessageBox.Show($"Failed to open {asset.Filename}\n" + ex.Message, + "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void HandleLocalisationFile(PckAsset asset) + { + LOCFile locFile = asset.GetData(new LOCFileReader()); + ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (locFile) => + { + asset.SetData(new LOCFileWriter(locFile, 2)); + }); + using LOCEditor locedit = new LOCEditor(locFile, saveContext); + _wasModified = locedit.ShowDialog(this) == DialogResult.OK; + UpdateRichPresence(); + } + + private void HandleColourFile(PckAsset asset) + { + ColorContainer colorContainer = asset.GetData(new COLFileReader()); + ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (colorContainer) => + { + asset.SetData(new COLFileWriter(colorContainer)); + }); + using COLEditor diag = new COLEditor(colorContainer, saveContext); + _wasModified = diag.ShowDialog(this) == DialogResult.OK; + } + + private void HandleSkinFile(PckAsset asset) + { + Skin skin = asset.GetSkin(); + if (asset.HasProperty("CAPEPATH")) + { + string capeAssetPath = asset.GetProperty("CAPEPATH"); + if (EditorValue.TryGetAsset(capeAssetPath, PckAssetType.CapeFile, out PckAsset capeAsset)) + { + skin.CapeTexture = capeAsset.GetTexture(); + } + } + + ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (customSkin) => + { + if (!TryGetLocFile(out LOCFile locFile)) + Debug.WriteLine("Failed to aquire loc file."); + asset.SetSkin(customSkin, locFile); + }); + + using CustomSkinEditor skinEditor = new CustomSkinEditor(skin, saveContext, EditorValue.HasVerionString); + if (skinEditor.ShowDialog() == DialogResult.OK) + { + entryDataTextBox.Text = entryTypeTextBox.Text = string.Empty; + _wasModified = true; + ReloadMetaTreeView(); + } + } + + private void HandleModelsFile(PckAsset asset) + { + ModelContainer modelContainer = asset.GetData(new ModelFileReader()); + if (modelContainer.ModelCount == 0) + { + MessageBox.Show("No models found.", "Empty Model file", MessageBoxButtons.OK, MessageBoxIcon.Information); + return; + } + + TryGetDelegate tryGetTexture = (string path, out Image img) => + { + bool found = EditorValue.TryGetAsset(path + ".png", PckAssetType.TextureFile, out PckAsset asset) || + EditorValue.TryGetAsset(path + ".tga", PckAssetType.TextureFile, out asset); + img = found ? asset.GetTexture() : default; + return found; + }; + + TrySetDelegate trySetTexture = (string path, Image img) => + { + bool found = EditorValue.TryGetAsset(path + ".png", PckAssetType.TextureFile, out PckAsset foundAsset) || + EditorValue.TryGetAsset(path + ".tga", PckAssetType.TextureFile, out foundAsset); + PckAsset asset = foundAsset ?? EditorValue.CreateNewAsset(path + ".png", PckAssetType.TextureFile); + asset.SetTexture(img); + return true; + }; + + bool hasMaterialAsset = EditorValue.TryGetAsset("entityMaterials.bin", PckAssetType.MaterialFile, out PckAsset entityMaterialAsset); + IReadOnlyDictionary entityMaterials = + hasMaterialAsset + ? entityMaterialAsset?.GetData(new MaterialFileReader()).ToDictionary(mat => mat.Name) + : new Dictionary(); + + ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (modelContainer) => + { + asset.SetData(new ModelFileWriter(modelContainer, modelContainer.Version)); + }); + + var editor = new ModelEditor(modelContainer, saveContext, TryGetSet.FromDelegates(tryGetTexture, trySetTexture), TryGet.FromDelegate(entityMaterials.TryGetValue)); + if (editor.ShowDialog() == DialogResult.OK) + { + BuildMainTreeView(); + _wasModified = true; + return; + } + } + + private void HandleBehavioursFile(PckAsset asset) + { + BehaviourFile behaviourFile = asset.GetData(new BehavioursReader()); + ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (behaviourFile) => + { + asset.SetData(new BehavioursWriter(behaviourFile)); + }); + using BehaviourEditor edit = new BehaviourEditor(behaviourFile, saveContext); + _wasModified = edit.ShowDialog(this) == DialogResult.OK; + } + + private void HandleMaterialFile(PckAsset asset) + { + MaterialContainer materials = asset.GetData(new MaterialFileReader()); + ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (materials) => + { + asset.SetData(new MaterialFileWriter(materials)); + }); + using MaterialsEditor edit = new MaterialsEditor(materials, saveContext); + _wasModified = edit.ShowDialog(this) == DialogResult.OK; + } + + private void CheckForPasswordAndRemove() + { + if (EditorValue.TryGetAsset("0", PckAssetType.InfoFile, out PckAsset asset)) + { + asset.RemoveProperties("LOCK"); + } } /// @@ -165,7 +546,7 @@ namespace PckStudio.Controls /// /// /// new Created TreeNode - internal static TreeNode CreateNode(string name, object tag = null) + private static TreeNode CreateNode(string name, object tag = null) { TreeNode node = new TreeNode(name); node.Name = name; @@ -173,14 +554,6 @@ namespace PckStudio.Controls return node; } - private void CheckForPasswordAndRemove() - { - if (_pck.TryGetAsset("0", PckAssetType.InfoFile, out PckAsset file)) - { - file.RemoveProperties("LOCK"); - } - } - private TreeNode BuildNodeTreeBySeperator(TreeNodeCollection root, string path, char seperator) { _ = root ?? throw new ArgumentNullException(nameof(root)); @@ -209,79 +582,11 @@ namespace PckStudio.Controls { foreach (PckAsset asset in pckFile.GetAssets()) { - // fix any file paths that may be incorrect - //if (file.Filename.StartsWith(parentPath)) - // file.Filename = file.Filename.Remove(0, parentPath.Length); TreeNode node = BuildNodeTreeBySeperator(root, asset.Filename, '/'); node.Tag = asset; - SetNodeIcon(node, asset.Type); - } - } - - private void SetNodeIcon(TreeNode node, PckAssetType type) - { - switch (type) - { - case PckAssetType.AudioFile: - node.ImageIndex = 1; - node.SelectedImageIndex = 1; - break; - case PckAssetType.LocalisationFile: - node.ImageIndex = 3; - node.SelectedImageIndex = 3; - break; - case PckAssetType.TexturePackInfoFile: - node.ImageIndex = 4; - node.SelectedImageIndex = 4; - break; - case PckAssetType.ColourTableFile: - node.ImageIndex = 6; - node.SelectedImageIndex = 6; - break; - case PckAssetType.ModelsFile: - node.ImageIndex = 8; - node.SelectedImageIndex = 8; - break; - case PckAssetType.SkinDataFile: - node.ImageIndex = 7; - node.SelectedImageIndex = 7; - break; - case PckAssetType.GameRulesFile: - node.ImageIndex = 9; - node.SelectedImageIndex = 9; - break; - case PckAssetType.GameRulesHeader: - node.ImageIndex = 10; - node.SelectedImageIndex = 10; - break; - case PckAssetType.InfoFile: - node.ImageIndex = 11; - node.SelectedImageIndex = 11; - break; - case PckAssetType.SkinFile: - node.ImageIndex = 12; - node.SelectedImageIndex = 12; - break; - case PckAssetType.CapeFile: - node.ImageIndex = 13; - node.SelectedImageIndex = 13; - break; - case PckAssetType.TextureFile: - node.ImageIndex = 14; - node.SelectedImageIndex = 14; - break; - case PckAssetType.BehavioursFile: - node.ImageIndex = 15; - node.SelectedImageIndex = 15; - break; - case PckAssetType.MaterialFile: - node.ImageIndex = 16; - node.SelectedImageIndex = 16; - break; - default: // unknown file format - node.ImageIndex = 5; - node.SelectedImageIndex = 5; - break; + int nodeIconId = GetNodeIconId(asset.Type); + node.ImageIndex = nodeIconId; + node.SelectedImageIndex = nodeIconId; } } @@ -292,7 +597,7 @@ namespace PckStudio.Controls previewPictureBox.Image = Resources.NoImageFound; treeMeta.Nodes.Clear(); treeViewMain.Nodes.Clear(); - BuildPckTreeView(treeViewMain.Nodes, _pck); + BuildPckTreeView(treeViewMain.Nodes, EditorValue); //if (isTemplateFile && currentPCK.HasAsset("Skins.pck", PckAssetType.SkinDataFile)) //{ @@ -312,6 +617,29 @@ namespace PckStudio.Controls } } + private int GetNodeIconId(PckAssetType type) + { + return type switch + { + PckAssetType.AudioFile => 1, + PckAssetType.LocalisationFile => 3, + PckAssetType.TexturePackInfoFile => 4, + PckAssetType.ColourTableFile => 6, + PckAssetType.ModelsFile => 8, + PckAssetType.SkinDataFile => 7, + PckAssetType.GameRulesFile => 9, + PckAssetType.GameRulesHeader => 10, + PckAssetType.InfoFile => 11, + PckAssetType.SkinFile => 12, + PckAssetType.CapeFile => 13, + PckAssetType.TextureFile => 14, + PckAssetType.BehavioursFile => 15, + PckAssetType.MaterialFile => 16, + // unknown file format + _ => 5, + }; + } + private List GetAllChildNodes(TreeNodeCollection root) { List childNodes = new List(); @@ -328,8 +656,8 @@ namespace PckStudio.Controls private bool TryGetLocFile(out LOCFile locFile) { - if (!_pck.TryGetAsset("localisation.loc", PckAssetType.LocalisationFile, out PckAsset locAsset) && - !_pck.TryGetAsset("languages.loc", PckAssetType.LocalisationFile, out locAsset)) + if (!EditorValue.TryGetAsset("localisation.loc", PckAssetType.LocalisationFile, out PckAsset locAsset) && + !EditorValue.TryGetAsset("languages.loc", PckAssetType.LocalisationFile, out locAsset)) { locFile = null; return false; @@ -350,8 +678,8 @@ namespace PckStudio.Controls private bool TrySetLocFile(in LOCFile locFile) { - if (!_pck.TryGetAsset("localisation.loc", PckAssetType.LocalisationFile, out PckAsset locAsset) && - !_pck.TryGetAsset("languages.loc", PckAssetType.LocalisationFile, out locAsset)) + if (!EditorValue.TryGetAsset("localisation.loc", PckAssetType.LocalisationFile, out PckAsset locAsset) && + !EditorValue.TryGetAsset("languages.loc", PckAssetType.LocalisationFile, out locAsset)) { return false; } @@ -383,7 +711,7 @@ namespace PckStudio.Controls private void UpdateRichPresence() { - if (_pck is not null && + if (EditorValue is not null && TryGetLocFile(out LOCFile locfile) && locfile.HasLocEntry("IDS_DISPLAY_NAME") && locfile.Languages.Contains("en-EN")) @@ -395,6 +723,22 @@ namespace PckStudio.Controls RPC.SetPresence("An Open Source .PCK File Editor"); } + private static PckAsset CreateNewAudioAsset(bool isLittle, PckAudioFile audioFile) + { + PckAsset newAsset = new PckAsset("audio.pck", PckAssetType.AudioFile); + newAsset.SetData(new PckAudioFileWriter(audioFile, isLittle ? OMI.Endianness.LittleEndian : OMI.Endianness.BigEndian)); + return newAsset; + } + + private static PckAudioFile CreateNewAudioFile() + { + PckAudioFile audioFile = new PckAudioFile(); + audioFile.AddCategory(PckAudioFile.AudioCategory.EAudioType.Overworld); + audioFile.AddCategory(PckAudioFile.AudioCategory.EAudioType.Nether); + audioFile.AddCategory(PckAudioFile.AudioCategory.EAudioType.End); + return audioFile; + } + private void addFileToolStripMenuItem_Click(object sender, EventArgs e) { using var ofd = new OpenFileDialog(); @@ -408,12 +752,12 @@ namespace PckStudio.Controls using AddFilePrompt diag = new AddFilePrompt("res/" + Path.GetFileName(ofd.FileName)); if (diag.ShowDialog(this) == DialogResult.OK) { - if (_pck.Contains(diag.Filepath, diag.Filetype)) + if (EditorValue.Contains(diag.Filepath, diag.Filetype)) { MessageBox.Show(this, $"'{diag.Filepath}' of type {diag.Filetype} already exists.", "Import failed", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } - PckAsset asset = _pck.CreateNewAsset(diag.Filepath, diag.Filetype, () => File.ReadAllBytes(ofd.FileName)); + PckAsset asset = EditorValue.CreateNewAsset(diag.Filepath, diag.Filetype, () => File.ReadAllBytes(ofd.FileName)); BuildMainTreeView(); _wasModified = true; @@ -432,12 +776,12 @@ namespace PckStudio.Controls renamePrompt.LabelText = "Path"; if (renamePrompt.ShowDialog(this) == DialogResult.OK && !string.IsNullOrEmpty(renamePrompt.NewText)) { - if (_pck.Contains(renamePrompt.NewText, PckAssetType.TextureFile)) + if (EditorValue.Contains(renamePrompt.NewText, PckAssetType.TextureFile)) { MessageBox.Show(this, $"'{renamePrompt.NewText}' already exists.", "Import failed", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } - PckAsset asset = _pck.CreateNewAsset(renamePrompt.NewText, PckAssetType.TextureFile, () => File.ReadAllBytes(fileDialog.FileName)); + PckAsset asset = EditorValue.CreateNewAsset(renamePrompt.NewText, PckAssetType.TextureFile, () => File.ReadAllBytes(fileDialog.FileName)); BuildMainTreeView(); _wasModified = true; } @@ -456,7 +800,7 @@ namespace PckStudio.Controls { string skinNameImport = Path.GetFileName(contents.FileName); byte[] data = File.ReadAllBytes(contents.FileName); - PckAsset mfNew = _pck.CreateNewAsset(skinNameImport, PckAssetType.SkinFile); + PckAsset mfNew = EditorValue.CreateNewAsset(skinNameImport, PckAssetType.SkinFile); mfNew.SetData(data); string propertyFile = Path.GetFileNameWithoutExtension(contents.FileName) + ".txt"; if (File.Exists(propertyFile)) @@ -542,7 +886,9 @@ namespace PckStudio.Controls { Debug.WriteLine($"Setting {asset.Type} to {type}"); asset.Type = type; - SetNodeIcon(treeViewMain.SelectedNode, type); + int nodeIconId = GetNodeIconId(type); + treeViewMain.SelectedNode.ImageIndex = nodeIconId; + treeViewMain.SelectedNode.SelectedImageIndex = nodeIconId; } } @@ -556,86 +902,78 @@ namespace PckStudio.Controls previewPictureBox.Image = Resources.NoImageFound; viewFileInfoToolStripMenuItem.Visible = false; - if (e.Node.TryGetTagData(out PckAsset asset)) + if (!e.Node.TryGetTagData(out PckAsset asset)) { - viewFileInfoToolStripMenuItem.Visible = true; - if (asset.HasProperty("BOX")) - { - buttonEdit.Text = "EDIT BOXES"; - buttonEdit.Visible = true; - } - else if (asset.HasProperty("ANIM") && - asset.GetProperty("ANIM", s => SkinANIM.FromString(s) == (SkinAnimMask.RESOLUTION_64x64 | SkinAnimMask.SLIM_MODEL))) - { - buttonEdit.Text = "View Skin"; - buttonEdit.Visible = true; - } + return; + } - switch (asset.Type) + viewFileInfoToolStripMenuItem.Visible = true; + if (asset.HasProperty("BOX")) + { + buttonEdit.Text = "EDIT BOXES"; + buttonEdit.Visible = true; + } + else if (asset.HasProperty("ANIM") && + asset.GetProperty("ANIM", s => SkinANIM.FromString(s) == (SkinAnimMask.RESOLUTION_64x64 | SkinAnimMask.SLIM_MODEL))) + { + buttonEdit.Text = "View Skin"; + buttonEdit.Visible = true; + } + + switch (asset.Type) + { + case PckAssetType.SkinFile: + case PckAssetType.CapeFile: + case PckAssetType.TextureFile: { - case PckAssetType.SkinFile: - case PckAssetType.CapeFile: - case PckAssetType.TextureFile: + Image img = asset.GetTexture(); + + previewPictureBox.Image = img; + labelImageSize.Text = $"{previewPictureBox.Image.Size.Width}x{previewPictureBox.Image.Size.Height}"; + + 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()) { - Image img = asset.GetTexture(); - - try - { - previewPictureBox.Image = img; - labelImageSize.Text = $"{previewPictureBox.Image.Size.Width}x{previewPictureBox.Image.Size.Height}"; - } - catch (Exception ex) - { - labelImageSize.Text = ""; - previewPictureBox.Image = Resources.NoImageFound; - Debug.WriteLine("Not a supported image format. Setting back to default"); - Debug.WriteLine(string.Format("An error occured of type: {0} with message: {1}", ex.GetType(), ex.Message), "Exception"); - } - - 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; - } - - buttonEdit.Text = "EDIT TEXTURE ATLAS"; + buttonEdit.Text = "EDIT TILE ANIMATION"; buttonEdit.Visible = true; + break; } + + buttonEdit.Text = "EDIT TEXTURE ATLAS"; + buttonEdit.Visible = true; + } + break; + + case PckAssetType.LocalisationFile: + buttonEdit.Text = "EDIT LOC"; + buttonEdit.Visible = true; break; - case PckAssetType.LocalisationFile: - buttonEdit.Text = "EDIT LOC"; - buttonEdit.Visible = true; - break; + case PckAssetType.AudioFile: + buttonEdit.Text = "EDIT MUSIC CUES"; + buttonEdit.Visible = true; + break; - case PckAssetType.AudioFile: - buttonEdit.Text = "EDIT MUSIC CUES"; - buttonEdit.Visible = true; - break; + case PckAssetType.ColourTableFile when asset.Filename == "colours.col": + buttonEdit.Text = "EDIT COLORS"; + buttonEdit.Visible = true; + break; - case PckAssetType.ColourTableFile when asset.Filename == "colours.col": - buttonEdit.Text = "EDIT COLORS"; - buttonEdit.Visible = true; - break; - - case PckAssetType.BehavioursFile when asset.Filename == "behaviours.bin": - buttonEdit.Text = "EDIT BEHAVIOURS"; - buttonEdit.Visible = true; - break; - default: - buttonEdit.Visible = false; - break; - } + case PckAssetType.BehavioursFile when asset.Filename == "behaviours.bin": + buttonEdit.Text = "EDIT BEHAVIOURS"; + buttonEdit.Visible = true; + break; + default: + buttonEdit.Visible = false; + break; } } @@ -648,12 +986,10 @@ namespace PckStudio.Controls Trace.WriteLine($"'{asset.Filename}' has no data attached.", category: nameof(treeViewMain_DoubleClick)); return; } - pckFileTypeHandler[asset.Type]?.Invoke(asset); + pckAssetTypeHandler[asset.Type]?.Invoke(asset); } } - #region drag and drop for main tree node - // Most of the code below is modified code from this link: // https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.treeview.itemdrag?view=windowsdesktop-6.0 // - MattNL @@ -663,7 +999,7 @@ namespace PckStudio.Controls if (e.Button != MouseButtons.Left || e.Item is not TreeNode node) return; - if ((node.TryGetTagData(out PckAsset asset) && _pck.Contains(asset.Filename, asset.Type)) || node.Parent is TreeNode) + if ((node.TryGetTagData(out PckAsset asset) && EditorValue.Contains(asset.Filename, asset.Type)) || node.Parent is TreeNode) { // TODO: add (mouse) scrolling while dragging item(s) treeViewMain.DoDragDrop(node, DragDropEffects.Scroll | DragDropEffects.Move); @@ -839,14 +1175,14 @@ namespace PckStudio.Controls } } - if (_pck.Contains(filepath, assetType)) + if (EditorValue.Contains(filepath, assetType)) { if (askForAssetType) MessageBox.Show(this, $"'{assetPath}' of type {assetType} already exists.\nSkiping file.", "File already exists", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1); Debug.WriteLine($"'{assetPath}' of type {assetType} already exists.\nSkiping file."); continue; } - PckAsset importedAsset = _pck.CreateNewAsset(assetPath, assetType, () => File.ReadAllBytes(filepath)); + PckAsset importedAsset = EditorValue.CreateNewAsset(assetPath, assetType, () => File.ReadAllBytes(filepath)); string propertyFile = filepath + ".txt"; if (File.Exists(propertyFile)) { @@ -887,12 +1223,12 @@ namespace PckStudio.Controls if (addFile.ShowDialog(this) != DialogResult.OK) continue; - if (_pck.Contains(addFile.Filepath, addFile.Filetype)) + if (EditorValue.Contains(addFile.Filepath, addFile.Filetype)) { MessageBox.Show(this, $"'{addFile.Filepath}' of type {addFile.Filetype} already exists.", "Import failed", MessageBoxButtons.OK, MessageBoxIcon.Warning); continue; } - _pck.CreateNewAsset(addFile.Filepath, addFile.Filetype, () => File.ReadAllBytes(file)); + EditorValue.CreateNewAsset(addFile.Filepath, addFile.Filetype, () => File.ReadAllBytes(file)); addedCount++; BuildMainTreeView(); @@ -901,8 +1237,6 @@ namespace PckStudio.Controls Trace.TraceInformation("[{0}] Imported {1} file(s).", nameof(ImportFiles), addedCount); } - #endregion - private void createSkinToolStripMenuItem_Click(object sender, EventArgs e) { using (AddSkinPrompt addNewSkinDialog = new AddSkinPrompt()) @@ -910,7 +1244,7 @@ namespace PckStudio.Controls { TryGetLocFile(out LOCFile locFile); PckAsset skinAsset = addNewSkinDialog.NewSkin.CreateFile(locFile); - _pck.AddAsset(skinAsset); + EditorValue.AddAsset(skinAsset); // if (currentPCK.HasAsset("Skins.pck", PckAssetType.SkinDataFile)) // Prioritize Skins.pck //{ // TreeNode subPCK = treeViewMain.Nodes.Find("Skins.pck", false).FirstOrDefault(); @@ -927,7 +1261,7 @@ namespace PckStudio.Controls { if (treeViewMain.Nodes.ContainsKey("Skins")) skinAsset.Filename = skinAsset.Filename.Insert(0, "Skins/"); // Then Skins folder - _pck.AddAsset(skinAsset); + EditorValue.AddAsset(skinAsset); } if (addNewSkinDialog.NewSkin.HasCape) @@ -949,7 +1283,7 @@ namespace PckStudio.Controls { if (treeViewMain.Nodes.ContainsKey("Skins")) capeFile.Filename = capeFile.Filename.Insert(0, "Skins/"); // Then Skins folder - _pck.AddAsset(capeFile); + EditorValue.AddAsset(capeFile); } } @@ -967,14 +1301,14 @@ namespace PckStudio.Controls string animationFilepath = $"{ResourceLocation.GetPathFromCategory(diag.Category)}/{diag.SelectedTile.InternalName}.png"; - if (_pck.Contains(animationFilepath, PckAssetType.TextureFile)) + if (EditorValue.Contains(animationFilepath, PckAssetType.TextureFile)) { MessageBox.Show(this, $"{diag.SelectedTile.DisplayName} is already present.", "File already present"); return; } Animation newAnimation = default; - DelegatedSaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (animation) => + ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (animation) => { newAnimation = animation; }); @@ -983,32 +1317,16 @@ namespace PckStudio.Controls if (animationEditor.ShowDialog() == DialogResult.OK && newAnimation is not null) { _wasModified = true; - PckAsset asset = _pck.CreateNewAsset(animationFilepath, PckAssetType.TextureFile); + PckAsset asset = EditorValue.CreateNewAsset(animationFilepath, PckAssetType.TextureFile); asset.SetSerializedData(newAnimation, AnimationSerializer.DefaultSerializer); BuildMainTreeView(); ReloadMetaTreeView(); } } - private static PckAsset CreateNewAudioAsset(bool isLittle, PckAudioFile audioFile) - { - PckAsset newAsset = new PckAsset("audio.pck", PckAssetType.AudioFile); - newAsset.SetData(new PckAudioFileWriter(audioFile, isLittle ? OMI.Endianness.LittleEndian : OMI.Endianness.BigEndian)); - return newAsset; - } - - private static PckAudioFile CreateNewAudioFile() - { - PckAudioFile audioFile = new PckAudioFile(); - audioFile.AddCategory(PckAudioFile.AudioCategory.EAudioType.Overworld); - audioFile.AddCategory(PckAudioFile.AudioCategory.EAudioType.Nether); - audioFile.AddCategory(PckAudioFile.AudioCategory.EAudioType.End); - return audioFile; - } - private void audiopckToolStripMenuItem_Click(object sender, EventArgs e) { - if (_pck.Contains(PckAssetType.AudioFile)) + if (EditorValue.Contains(PckAssetType.AudioFile)) { // the chance of this happening is really really slim but just in case MessageBox.Show(this, "There is already an audio file in this PCK!", "Can't create audio.pck"); @@ -1032,7 +1350,7 @@ namespace PckStudio.Controls AudioEditor diag = new AudioEditor(newAudioFile, saveContext); if (diag.ShowDialog(this) == DialogResult.OK) { - _pck.AddAsset(newAudioAsset); + EditorValue.AddAsset(newAudioAsset); } diag.Dispose(); BuildMainTreeView(); @@ -1040,25 +1358,25 @@ namespace PckStudio.Controls private void colourscolToolStripMenuItem_Click(object sender, EventArgs e) { - if (_pck.TryGetAsset("colours.col", PckAssetType.ColourTableFile, out _)) + if (EditorValue.TryGetAsset("colours.col", PckAssetType.ColourTableFile, out _)) { MessageBox.Show(this, "A color table file already exists in this PCK and a new one cannot be created.", "Operation aborted"); return; } - PckAsset newColorAsset = _pck.CreateNewAsset("colours.col", PckAssetType.ColourTableFile); + PckAsset newColorAsset = EditorValue.CreateNewAsset("colours.col", PckAssetType.ColourTableFile); newColorAsset.SetData(Resources.tu69colours); BuildMainTreeView(); } private void CreateSkinsPCKToolStripMenuItem1_Click(object sender, EventArgs e) { - if (_pck.TryGetAsset("Skins.pck", PckAssetType.SkinDataFile, out _)) + if (EditorValue.TryGetAsset("Skins.pck", PckAssetType.SkinDataFile, out _)) { MessageBox.Show(this, "A Skins.pck file already exists in this PCK and a new one cannot be created.", "Operation aborted"); return; } - _pck.CreateNewAsset("Skins.pck", PckAssetType.SkinDataFile, new PckFileWriter(new PckFile(3, true), + EditorValue.CreateNewAsset("Skins.pck", PckAssetType.SkinDataFile, new PckFileWriter(new PckFile(3, true), LittleEndianCheckBox.Checked ? OMI.Endianness.LittleEndian : OMI.Endianness.BigEndian)); BuildMainTreeView(); @@ -1066,45 +1384,45 @@ namespace PckStudio.Controls private void behavioursbinToolStripMenuItem_Click(object sender, EventArgs e) { - if (_pck.TryGetAsset("behaviours.bin", PckAssetType.BehavioursFile, out _)) + if (EditorValue.TryGetAsset("behaviours.bin", PckAssetType.BehavioursFile, out _)) { MessageBox.Show(this, "A behaviours file already exists in this PCK and a new one cannot be created.", "Operation aborted"); return; } - _pck.CreateNewAsset("behaviours.bin", PckAssetType.BehavioursFile, new BehavioursWriter(new BehaviourFile())); + EditorValue.CreateNewAsset("behaviours.bin", PckAssetType.BehavioursFile, new BehavioursWriter(new BehaviourFile())); BuildMainTreeView(); } private void entityMaterialsbinToolStripMenuItem_Click(object sender, EventArgs e) { - if (_pck.TryGetAsset("entityMaterials.bin", PckAssetType.MaterialFile, out _)) + if (EditorValue.TryGetAsset("entityMaterials.bin", PckAssetType.MaterialFile, out _)) { MessageBox.Show(this, "A behaviours file already exists in this PCK and a new one cannot be created.", "Operation aborted"); return; } var materialContainer = new MaterialContainer(); materialContainer.InitializeDefault(); - _pck.CreateNewAsset("entityMaterials.bin", PckAssetType.MaterialFile, new MaterialFileWriter(materialContainer)); + EditorValue.CreateNewAsset("entityMaterials.bin", PckAssetType.MaterialFile, new MaterialFileWriter(materialContainer)); BuildMainTreeView(); } [Obsolete("Refactor or remove this")] private void importExtractedSkinsFolder(object sender, EventArgs e) { - using FolderBrowserDialog contents = new FolderBrowserDialog(); - if (contents.ShowDialog() == DialogResult.OK) + OpenFolderDialog contents = new OpenFolderDialog(); + if (contents.ShowDialog() == true) { //checks to make sure selected path exist - if (!Directory.Exists(contents.SelectedPath)) + if (!Directory.Exists(contents.ResultPath)) { MessageBox.Show("Directory Lost"); return; } // creates variable to indicate wether current pck skin structure is mashup or regular skin - bool hasSkinsPck = _pck.HasAsset("Skins.pck", PckAssetType.SkinDataFile); + bool hasSkinsPck = EditorValue.HasAsset("Skins.pck", PckAssetType.SkinDataFile); - foreach (var fullfilename in Directory.GetFiles(contents.SelectedPath, "*.png")) + foreach (var fullfilename in Directory.GetFiles(contents.ResultPath, "*.png")) { string filename = Path.GetFileNameWithoutExtension(fullfilename); // sets file type based on wether its a cape or skin @@ -1149,7 +1467,7 @@ namespace PckStudio.Controls } if (hasSkinsPck) { - PckAsset skinsFileAsset = _pck.GetAsset("Skins.pck", PckAssetType.SkinDataFile); + PckAsset skinsFileAsset = EditorValue.GetAsset("Skins.pck", PckAssetType.SkinDataFile); using (var ms = new MemoryStream(skinsFileAsset.Data)) { //var reader = new PckFileReader(LittleEndianCheckBox.Checked ? OMI.Endianness.LittleEndian : OMI.Endianness.BigEndian); @@ -1162,7 +1480,7 @@ namespace PckStudio.Controls } continue; } - _pck.AddAsset(newFile); + EditorValue.AddAsset(newFile); } BuildMainTreeView(); _wasModified = true; @@ -1211,8 +1529,8 @@ namespace PckStudio.Controls { string mippedPath = $"{textureDirectory}/{textureName}MipMapLevel{i}{textureExtension}"; Debug.WriteLine(mippedPath); - if (_pck.HasAsset(mippedPath, PckAssetType.TextureFile)) - _pck.RemoveAsset(_pck.GetAsset(mippedPath, PckAssetType.TextureFile)); + if (EditorValue.HasAsset(mippedPath, PckAssetType.TextureFile)) + EditorValue.RemoveAsset(EditorValue.GetAsset(mippedPath, PckAssetType.TextureFile)); PckAsset mipMappedAsset = new PckAsset(mippedPath, PckAssetType.TextureFile); Image originalTexture = asset.GetTexture(); @@ -1231,7 +1549,7 @@ namespace PckStudio.Controls mipMappedAsset.SetTexture(mippedTexture); - _pck.InsertAsset(_pck.IndexOfAsset(asset) + i - 1, mipMappedAsset); + EditorValue.InsertAsset(EditorValue.IndexOfAsset(asset) + i - 1, mipMappedAsset); } BuildMainTreeView(); } @@ -1312,7 +1630,7 @@ namespace PckStudio.Controls string selectedFolder = node.FullPath; - foreach (PckAsset asset in _pck.GetAssets().Where(asset => asset.Filename.StartsWith(selectedFolder))) + foreach (PckAsset asset in EditorValue.GetAssets().Where(asset => asset.Filename.StartsWith(selectedFolder))) { extractFolderFile(outPath, asset); } @@ -1384,7 +1702,7 @@ namespace PckStudio.Controls TreeNodeCollection nodeCollection = node.Parent?.Nodes ?? treeViewMain.Nodes; nodeCollection.Insert(node.Index + 1, newNode); - _pck.InsertAsset(node.Index + 1, newFile); + EditorValue.InsertAsset(node.Index + 1, newFile); BuildMainTreeView(); _wasModified = true; } @@ -1406,7 +1724,7 @@ namespace PckStudio.Controls { if (isFile) { - if (_pck.Contains(diag.NewText, asset.Type)) + if (EditorValue.Contains(diag.NewText, asset.Type)) { MessageBox.Show(this, $"{diag.NewText} already exists", "File already exists"); return; @@ -1509,7 +1827,7 @@ namespace PckStudio.Controls if (node.TryGetTagData(out PckAsset asset)) { - if (!BeforeFileRemove(asset) && _pck.RemoveAsset(asset)) + if (!BeforeFileRemove(asset) && EditorValue.RemoveAsset(asset)) { node.Remove(); _wasModified = true; @@ -1519,7 +1837,7 @@ namespace PckStudio.Controls MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes) { string pckFolderDir = node.FullPath; - _pck.RemoveAll(file => file.Filename.StartsWith(pckFolderDir) && !BeforeFileRemove(file)); + EditorValue.RemoveAll(file => file.Filename.StartsWith(pckFolderDir) && !BeforeFileRemove(file)); node.Remove(); _wasModified = true; } @@ -1716,12 +2034,12 @@ namespace PckStudio.Controls } } - private static Model HandleDefaultEntityModel(string modelName) + private static Model GetDefaultEntityModel(string modelName) { if (!GameModelImporter.DefaultModels.TryGetValue(modelName, out DefaultModel defaultModel) || defaultModel is null) { MessageBox.Show("No Default Model found."); - return null; + return default; } Model model = new Model(modelName, new Size((int)defaultModel.TextureSize.X, (int)defaultModel.TextureSize.Y)); @@ -1790,343 +2108,6 @@ namespace PckStudio.Controls form.Dispose(); } - private void HandleTextureFile(PckAsset asset) - { - _ = asset.IsMipmappedFile() && _pck.TryGetValue(asset.GetNormalPath(), PckAssetType.TextureFile, out asset); - - if (asset.Size <= 0) - { - Debug.WriteLine($"'{asset.Filename}' size is 0.", category: nameof(HandleTextureFile)); - return; - } - - ResourceLocation resourceLocation = ResourceLocation.GetFromPath(asset.Filename); - Debug.WriteLine("Handling Resource file: " + resourceLocation?.ToString()); - - switch (resourceLocation.Category) - { - case ResourceCategory.Unknown: - Debug.WriteLine($"Unknown Resource Category."); - break; - case ResourceCategory.MobEntityTextures: - case ResourceCategory.ItemEntityTextures: - { - string texturePath = asset.Filename.Substring(0, asset.Filename.Length - Path.GetExtension(asset.Filename).Length); - string[] modelNames = GameModelImporter.ModelMetaData.Where(kv => kv.Value.TextureLocations.Contains(texturePath)).Select(kv => kv.Key).ToArray(); - - if (modelNames.Length == 0) - { - MessageBox.Show("No Model info found"); - return; - } - - string modelName = modelNames[0]; - if (modelNames.Length > 1) - { - using ItemSelectionPopUp itemSelectionPopUp = new ItemSelectionPopUp(modelNames.ToArray()); - itemSelectionPopUp.ButtonText = "View"; - itemSelectionPopUp.LabelText = "Models:"; - if (itemSelectionPopUp.ShowDialog() != DialogResult.OK || !modelNames.IndexInRange(itemSelectionPopUp.SelectedIndex)) - { - return; - } - modelName = modelNames[itemSelectionPopUp.SelectedIndex]; - } - - NamedTexture modelTexture = new NamedTexture(Path.GetFileName(texturePath), asset.GetTexture()); - - Model model = HandleDefaultEntityModel(modelName); - if (_pck.TryGetAsset("models.bin", PckAssetType.ModelsFile, out PckAsset modelsAsset)) - { - ModelContainer models = modelsAsset.GetData(new ModelFileReader()); - if (models.ContainsModel(modelName)) - { - Debug.WriteLine($"Custom model for '{modelName}' found."); - model = models.GetModelByName(modelName); - } - } - - if (model is not null) - { - ShowSimpleModelRender(model, modelTexture); - } - } - break; - - case ResourceCategory.ItemAnimation: - case ResourceCategory.BlockAnimation: - Animation animation = asset.GetDeserializedData(AnimationDeserializer.DefaultDeserializer); - string internalName = Path.GetFileNameWithoutExtension(asset.Filename); - IList textureInfos = resourceLocation.Category == ResourceCategory.ItemAnimation ? Tiles.ItemTileInfos : Tiles.BlockTileInfos; - string displayname = textureInfos.FirstOrDefault(p => p.InternalName == internalName)?.DisplayName ?? internalName; - - string[] specialTileNames = { "clock", "compass" }; - - ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (animation) => - { - asset.SetSerializedData(animation, AnimationSerializer.DefaultSerializer); - }); - - using (AnimationEditor animationEditor = new AnimationEditor(animation, saveContext, displayname, internalName.ToLower().EqualsAny(specialTileNames))) - { - if (animationEditor.ShowDialog(this) == DialogResult.OK) - { - _wasModified = true; - BuildMainTreeView(); - } - } - break; - case ResourceCategory.ItemAtlas: - case ResourceCategory.BlockAtlas: - case ResourceCategory.ParticleAtlas: - case ResourceCategory.BannerAtlas: - case ResourceCategory.PaintingAtlas: - case ResourceCategory.ExplosionAtlas: - case ResourceCategory.ExperienceOrbAtlas: - case ResourceCategory.MoonPhaseAtlas: - case ResourceCategory.MapIconAtlas: - case ResourceCategory.AdditionalMapIconsAtlas: - Image atlas = asset.GetTexture(); - ColorContainer colorContainer = default; - if (_pck.TryGetAsset("colours.col", PckAssetType.ColourTableFile, out PckAsset colAsset)) - colorContainer = colAsset.GetData(new COLFileReader()); - - ITryGet tryGetAnimation = TryGet.FromDelegate((string key, out Animation animation) => - { - bool found = _pck.TryGetAsset(key + ".png", PckAssetType.TextureFile, out PckAsset foundAsset) || - _pck.TryGetAsset(key + ".tga", PckAssetType.TextureFile, out foundAsset); - if (found) - { - animation = foundAsset.GetDeserializedData(AnimationDeserializer.DefaultDeserializer); - return true; - } - animation = default; - return false; - }); - - ITryGet> tryGetAnimationSaveContext = TryGet> - .FromDelegate((string key, out ISaveContext animationSaveContext) => - { - bool found = _pck.TryGetAsset(key + ".png", PckAssetType.TextureFile, out PckAsset foundAsset) || - _pck.TryGetAsset(key + ".tga", PckAssetType.TextureFile, out foundAsset); - - if (found) - { - animationSaveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (animation) => - foundAsset.SetSerializedData(animation, AnimationSerializer.DefaultSerializer)); - return true; - } - - // you could validate the key(animationAssetPath) for validity. -miku - animationSaveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (animation) => - { - if (animation.FrameCount == 0) - { - Debug.WriteLine("New animation has 0 frames. Aborting saving."); - return; - } - PckAsset newAnimationAsset = _pck.CreateNewAsset(key + ".png", PckAssetType.TextureFile); - newAnimationAsset.SetSerializedData(animation, AnimationSerializer.DefaultSerializer); - BuildMainTreeView(); - }); - return true; - }); - - ISaveContext textureAtlasSaveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, asset.SetTexture); - - var viewer = new TextureAtlasEditor(atlas, textureAtlasSaveContext, resourceLocation, colorContainer, tryGetAnimation, tryGetAnimationSaveContext); - if (viewer.ShowDialog(this) == DialogResult.OK) - { - _wasModified = true; - BuildMainTreeView(); - } - break; - default: - Debug.WriteLine($"Unhandled Resource Category: {resourceLocation.Category}"); - break; - } - } - - private void HandleGameRuleFile(PckAsset asset) - { - const string use_deflate = "PS3"; - const string use_xmem = "Xbox 360"; - const string use_zlib = "Other Platforms"; - - ItemSelectionPopUp dialog = new ItemSelectionPopUp(use_zlib, use_deflate, use_xmem); - dialog.LabelText = "Type"; - dialog.ButtonText = "Ok"; - if (dialog.ShowDialog() != DialogResult.OK) - return; - - GameRuleFile.CompressionType compressiontype = dialog.SelectedItem switch - { - use_deflate => GameRuleFile.CompressionType.Deflate, - use_xmem => GameRuleFile.CompressionType.XMem, - use_zlib => GameRuleFile.CompressionType.Zlib, - _ => GameRuleFile.CompressionType.Unknown - }; - - GameRuleFile grf = asset.GetData(new GameRuleFileReader(compressiontype)); - - ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (gameRuleFile) => - { - asset.SetData(new GameRuleFileWriter(gameRuleFile)); - }); - - using GameRuleFileEditor grfEditor = new GameRuleFileEditor(grf, saveContext); - if (grfEditor.ShowDialog(this) == DialogResult.OK) - { - _wasModified = true; - UpdateRichPresence(); - } - } - - private void HandleAudioFile(PckAsset asset) - { - try - { - OMI.Endianness endianness = LittleEndianCheckBox.Checked ? OMI.Endianness.LittleEndian : OMI.Endianness.BigEndian; - ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (audioFile) => - { - asset.SetData(new PckAudioFileWriter(audioFile, endianness)); - }); - PckAudioFile audioFile = asset.GetData(new PckAudioFileReader(endianness)); - using AudioEditor audioEditor = new AudioEditor(audioFile, saveContext); - _wasModified = audioEditor.ShowDialog(this) == DialogResult.OK; - } - catch (OverflowException) - { - MessageBox.Show(this, $"Failed to open {asset.Filename}\n" + - "Try converting the file by using the \"Misc. Functions/Set PCK Endianness\" tool and try again.", - "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning); - } - catch (Exception ex) - { - MessageBox.Show($"Failed to open {asset.Filename}\n" + ex.Message, - "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - } - - private void HandleLocalisationFile(PckAsset asset) - { - LOCFile locFile = asset.GetData(new LOCFileReader()); - ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (locFile) => - { - asset.SetData(new LOCFileWriter(locFile, 2)); - }); - using LOCEditor locedit = new LOCEditor(locFile, saveContext); - _wasModified = locedit.ShowDialog(this) == DialogResult.OK; - UpdateRichPresence(); - } - - private void HandleColourFile(PckAsset asset) - { - ColorContainer colorContainer = asset.GetData(new COLFileReader()); - ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (colorContainer) => - { - asset.SetData(new COLFileWriter(colorContainer)); - }); - using COLEditor diag = new COLEditor(colorContainer, saveContext); - _wasModified = diag.ShowDialog(this) == DialogResult.OK; - } - - public void HandleSkinFile(PckAsset asset) - { - Skin skin = asset.GetSkin(); - if (asset.HasProperty("CAPEPATH")) - { - string capeAssetPath = asset.GetProperty("CAPEPATH"); - if (_pck.TryGetAsset(capeAssetPath, PckAssetType.CapeFile, out PckAsset capeAsset)) - { - skin.CapeTexture = capeAsset.GetTexture(); - } - } - - ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (customSkin) => - { - if (!TryGetLocFile(out LOCFile locFile)) - Debug.WriteLine("Failed to aquire loc file."); - asset.SetSkin(customSkin, locFile); - }); - - using CustomSkinEditor skinEditor = new CustomSkinEditor(skin, saveContext, _pck.HasVerionString); - if (skinEditor.ShowDialog() == DialogResult.OK) - { - entryDataTextBox.Text = entryTypeTextBox.Text = string.Empty; - _wasModified = true; - ReloadMetaTreeView(); - } - } - - public void HandleModelsFile(PckAsset asset) - { - ModelContainer modelContainer = asset.GetData(new ModelFileReader()); - if (modelContainer.ModelCount == 0) - { - MessageBox.Show("No models found.", "Empty Model file", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - - TryGetDelegate tryGetTexture = (string path, out Image img) => - { - bool found = _pck.TryGetAsset(path + ".png", PckAssetType.TextureFile, out PckAsset asset) || - _pck.TryGetAsset(path + ".tga", PckAssetType.TextureFile, out asset); - img = found ? asset.GetTexture() : default; - return found; - }; - - TrySetDelegate trySetTexture = (string path, Image img) => - { - bool found = _pck.TryGetAsset(path + ".png", PckAssetType.TextureFile, out PckAsset foundAsset) || - _pck.TryGetAsset(path + ".tga", PckAssetType.TextureFile, out foundAsset); - PckAsset asset = foundAsset ?? _pck.CreateNewAsset(path + ".png", PckAssetType.TextureFile); - asset.SetTexture(img); - return true; - }; - - bool hasMaterialAsset = _pck.TryGetAsset("entityMaterials.bin", PckAssetType.MaterialFile, out PckAsset entityMaterialAsset); - IReadOnlyDictionary entityMaterials = - hasMaterialAsset - ? entityMaterialAsset?.GetData(new MaterialFileReader()).ToDictionary(mat => mat.Name) - : new Dictionary(); - - ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (modelContainer) => - { - asset.SetData(new ModelFileWriter(modelContainer, modelContainer.Version)); - }); - - var editor = new ModelEditor(modelContainer, saveContext, TryGetSet.FromDelegates(tryGetTexture, trySetTexture), TryGet.FromDelegate(entityMaterials.TryGetValue)); - if (editor.ShowDialog() == DialogResult.OK) - { - BuildMainTreeView(); - _wasModified = true; - return; - } - } - - public void HandleBehavioursFile(PckAsset asset) - { - BehaviourFile behaviourFile = asset.GetData(new BehavioursReader()); - ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (behaviourFile) => - { - asset.SetData(new BehavioursWriter(behaviourFile)); - }); - using BehaviourEditor edit = new BehaviourEditor(behaviourFile, saveContext); - _wasModified = edit.ShowDialog(this) == DialogResult.OK; - } - - public void HandleMaterialFile(PckAsset asset) - { - MaterialContainer materials = asset.GetData(new MaterialFileReader()); - ISaveContext saveContext = new DelegatedSaveContext(Settings.Default.AutoSaveChanges, (materials) => - { - asset.SetData(new MaterialFileWriter(materials)); - }); - using MaterialsEditor edit = new MaterialsEditor(materials, saveContext); - _wasModified = edit.ShowDialog(this) == DialogResult.OK; - } - private void PckEditor_Load(object sender, EventArgs e) { CheckForPasswordAndRemove(); @@ -2134,67 +2115,6 @@ namespace PckStudio.Controls UpdateRichPresence(); } - public void Close() - { - if ((_wasModified || _isTemplateFile) && - MessageBox.Show("Save PCK?", _isTemplateFile ? "Unsaved PCK" : "Modified PCK", - MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes) - { - if (_isTemplateFile || string.IsNullOrEmpty(_location) || !File.Exists(_location)) - { - SaveAs(); - return; - } - Save(); - } - } - - public void SaveAs() - { - using SaveFileDialog saveFileDialog = new SaveFileDialog - { - Filter = "PCK (Minecraft Console Package)|*.pck", - DefaultExt = ".pck", - }; - if (saveFileDialog.ShowDialog() == DialogResult.OK) - { - SaveTo(saveFileDialog.FileName); - pckFileLabel.Text = "Current PCK File: " + Path.GetFileName(_location); - } - } - - public void SaveTo(string filepath) - { - _location = filepath; - _isTemplateFile = false; - Save(); - } - - public void Save() - { - var writer = new PckFileWriter(_pck, GetEndianess()); - writer.WriteToFile(_location); - _timesSaved++; - _wasModified = false; - } - - public bool Open(string filepath, OMI.Endianness endianness) - { - SetEndianess(endianness); - _location = filepath; - try - { - var reader = new PckFileReader(endianness); - _pck = reader.FromFile(filepath); - return true; - } - catch (Exception ex) - { - Debug.WriteLine(ex.Message, category: $"{nameof(PckEditor)}.{nameof(Open)}"); - } - return false; - } - private void SetEndianess(OMI.Endianness endianness) { LittleEndianCheckBox.Checked = endianness == OMI.Endianness.LittleEndian; @@ -2205,18 +2125,6 @@ namespace PckStudio.Controls return LittleEndianCheckBox.Checked ? OMI.Endianness.LittleEndian : OMI.Endianness.BigEndian; } - public bool Open(PckFile pck) - { - _pck = pck; - _isTemplateFile = true; - return true; - } - - public void UpdateView() - { - BuildMainTreeView(); - } - private void buttonEdit_Click(object sender, EventArgs e) { treeViewMain_DoubleClick(sender, e); @@ -2226,19 +2134,19 @@ namespace PckStudio.Controls { try { - if (treeViewMain.SelectedNode.Tag is PckAsset file && (file.Type is PckAssetType.AudioFile || file.Type is PckAssetType.SkinDataFile || file.Type is PckAssetType.TexturePackInfoFile)) + if (treeViewMain.SelectedNode.Tag is PckAsset asset && (asset.Type is PckAssetType.AudioFile || asset.Type is PckAssetType.SkinDataFile || asset.Type is PckAssetType.TexturePackInfoFile)) { - IDataFormatReader reader = file.Type is PckAssetType.AudioFile + IDataFormatReader reader = asset.Type is PckAssetType.AudioFile ? new PckAudioFileReader(endianness == OMI.Endianness.BigEndian ? OMI.Endianness.LittleEndian : OMI.Endianness.BigEndian) : new PckFileReader(endianness == OMI.Endianness.BigEndian ? OMI.Endianness.LittleEndian : OMI.Endianness.BigEndian); - object pck = reader.FromStream(new MemoryStream(file.Data)); + object pck = reader.FromStream(new MemoryStream(asset.Data)); - IDataFormatWriter writer = file.Type is PckAssetType.AudioFile + IDataFormatWriter writer = asset.Type is PckAssetType.AudioFile ? new PckAudioFileWriter((PckAudioFile)pck, endianness) : new PckFileWriter((PckFile)pck, endianness); - file.SetData(writer); + asset.SetData(writer); _wasModified = true; - MessageBox.Show($"\"{file.Filename}\" successfully converted to {(endianness == OMI.Endianness.LittleEndian ? "little" : "big")} endian.", "Converted PCK file"); + MessageBox.Show($"\"{asset.Filename}\" successfully converted to {(endianness == OMI.Endianness.LittleEndian ? "little" : "big")} endian.", "Converted PCK file"); } } catch (OverflowException) @@ -2254,6 +2162,7 @@ namespace PckStudio.Controls } private void littleEndianToolStripMenuItem_Click(object sender, EventArgs e) => SetPckEndianness(OMI.Endianness.LittleEndian); + private void bigEndianToolStripMenuItem_Click(object sender, EventArgs e) => SetPckEndianness(OMI.Endianness.BigEndian); private void SetModelVersion(int version) @@ -2324,12 +2233,6 @@ namespace PckStudio.Controls private void contextMenuPCKEntries_Opening(object sender, System.ComponentModel.CancelEventArgs e) { - if (treeViewMain?.SelectedNode == null) - { - e.Cancel = true; - return; - } - correctSkinDecimalsToolStripMenuItem.Visible = false; generateMipMapTextureToolStripMenuItem1.Visible = false; setModelContainerFormatToolStripMenuItem.Visible = false; @@ -2337,7 +2240,7 @@ namespace PckStudio.Controls exportToolStripMenuItem.Visible = false; toolStripSeparator5.Visible = false; toolStripSeparator6.Visible = false; - if (treeViewMain.SelectedNode.TryGetTagData(out PckAsset asset)) + if (treeViewMain?.SelectedNode.TryGetTagData(out PckAsset asset) ?? false) { replaceToolStripMenuItem.Visible = true; cloneFileToolStripMenuItem.Visible = true; @@ -2364,6 +2267,5 @@ namespace PckStudio.Controls setFileTypeToolStripMenuItem.Visible = false; } } - } } \ No newline at end of file diff --git a/PCK-Studio/Controls/PckEditor.resx b/PCK-Studio/Controls/PckEditor.resx index 7786e820..6df9e8a1 100644 --- a/PCK-Studio/Controls/PckEditor.resx +++ b/PCK-Studio/Controls/PckEditor.resx @@ -117,9 +117,10 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + + False - + @@ -793,7 +794,6 @@ Zoom - 14 @@ -807,7 +807,7 @@ $this - 9 + 10 8, 27 @@ -828,7 +828,7 @@ $this - 3 + 4 Top, Right @@ -840,11 +840,14 @@ 1369, 252 - 0, 0 + 30, 19 19 + + aaa + labelImageSize @@ -855,7 +858,7 @@ $this - 4 + 0 Top, Right @@ -882,143 +885,8 @@ $this - 5 - - - MetaTab - - - MetroFramework.Controls.MetroTabPage, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a - - - PropertiesTabControl - - - 0 - - - Bottom - - - 279, 270 - - - 732, 281 - - - 11 - - - PropertiesTabControl - - - MetroFramework.Controls.MetroTabControl, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a - - - $this - - 6 - - metroLabel2 - - - MetroFramework.Controls.MetroLabel, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a - - - MetaTab - - - 2 - - - entryTypeTextBox - - - MetroFramework.Controls.MetroTextBox, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a - - - MetaTab - - - 3 - - - entryDataTextBox - - - MetroFramework.Controls.MetroTextBox, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a - - - MetaTab - - - 4 - - - buttonEdit - - - MetroFramework.Controls.MetroButton, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a - - - MetaTab - - - 5 - - - metroLabel1 - - - MetroFramework.Controls.MetroLabel, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a - - - MetaTab - - - 6 - - - treeMeta - - - System.Windows.Forms.TreeView, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - MetaTab - - - 7 - - - 4, 38 - - - 5, 5, 5, 5 - - - 724, 239 - - - 0 - - - Properties - - - MetaTab - - - MetroFramework.Controls.MetroTabPage, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a - - - PropertiesTabControl - - - 0 - Bottom, Right @@ -1026,7 +894,7 @@ True - 204, 156 + 204, 147 0, 0 @@ -1071,7 +939,7 @@ False - 215, 126 + 215, 117 146, 20 @@ -1116,7 +984,7 @@ False - 215, 158 + 215, 149 146, 20 @@ -1140,7 +1008,7 @@ Bottom, Right - 215, 184 + 215, 175 146, 33 @@ -1173,7 +1041,7 @@ True - 266, 49 + 266, 40 0, 0 @@ -1193,9 +1061,59 @@ 6 - + 301, 19 - + + + 160, 22 + + + Add Entry + + + 160, 22 + + + Add BOX Entry + + + 160, 22 + + + Add ANIM Entry + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xMkMEa+wAAABSSURBVDhP5c0x + DsAgDENRxt7/wmkNSpRGf0CCCZAegxNMM7MlGMp3dIU6dxhKf/QMNxRogeQC8ivw5Vn7C0heJlFA+kL5 + jWAohxRkde4wnGftBS90axNmphIGAAAAAElFTkSuQmCC + + + + 181, 22 + + + Add Entry + + + 181, 22 + + + Add Multiple Entries + + + 181, 22 + + + Delete Entry + + + 181, 22 + + + Edit All Entries + 182, 92 @@ -1229,59 +1147,60 @@ 7 - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO - vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xMkMEa+wAAABSSURBVDhP5c0x - DsAgDENRxt7/wmkNSpRGf0CCCZAegxNMM7MlGMp3dIU6dxhKf/QMNxRogeQC8ivw5Vn7C0heJlFA+kL5 - jWAohxRkde4wnGftBS90axNmphIGAAAAAElFTkSuQmCC - + + 4, 38 - - 181, 22 + + 5, 5, 5, 5 - - Add Entry + + 724, 239 - - 180, 22 + + 0 - - Add Entry + + Properties - - 180, 22 + + MetaTab - - Add BOX Entry + + MetroFramework.Controls.MetroTabPage, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a - - 180, 22 + + PropertiesTabControl - - Add ANIM Entry + + 0 - - 181, 22 + + Bottom - - Add Multiple Entries + + 279, 270 - - 181, 22 + + 732, 281 - - Delete Entry + + 11 - - 181, 22 + + PropertiesTabControl - - Edit All Entries + + MetroFramework.Controls.MetroTabControl, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a - + + $this + + + 7 + + True - + True @@ -1304,225 +1223,11 @@ $this - 7 - - - 22, 20 - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO - vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xOdTWsmQAAAA3SURBVDhPY/j/ - /z9FGKsgGIsCKWSMTQ0QYxUE45FmALpiYvFwMgAbxqIYG8YqCMajBhCJ/zMAAPGwpV/Xje8RAAAAAElF - TkSuQmCC - - - - 180, 22 - - - Create - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO - vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xOdTWsmQAAABzSURBVDhPpYzB - DQAhCARp4hr3Txu254WTjYRb9cEmk/BgRjBVHTv85Twmgt77PcJEYIFrhIkAgWOEiSAGthEmgtbaD9fW - mBgpB4xywCgFxiMf5YDdrq3l5wjEjKtzTARMNlydY2IGot2ureVnRjkQmZbICyCi7XU5cfqKAAAAAElF - TkSuQmCC - - - - 180, 22 - - - Import - - - 180, 22 - - - Export - - - 180, 22 - - - Set File Type - - - 177, 6 - - - 223, 22 - - - Generate MipMap Texture - - - 223, 22 - - - View File Info - - - 223, 22 - - - Correct Skin Decimals - - - 180, 22 - - - Big - - - 180, 22 - - - Little - - - 223, 22 - - - Set Endianness - - - 180, 22 - - - 1 - - - 180, 22 - - - 2 - - - 180, 22 - - - 3 - - - 223, 22 - - - Set Model Container version - - - 180, 22 - - - Misc. Functions - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO - vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xMkMEa+wAAACYSURBVDhPpZBZ - CsQwDEOd5QK5/2E9qCBGXtopzMcDxxKyY3P3izmnm9kt0OlVvsVVVgOAtvduQ4KJdYbaGKOEFFOHamut - ENKaMlk75zi2QX1rUqDpkbEF/cGktb47ygb5ODA8hVArgsK1cx+EAE7LaB8+hb3QzDx942eAXrqjBOgR - MRkBfHeUADbe8ncANw4NhLwF33R3+wA6sV5/E8GOLwAAAABJRU5ErkJggg== - - - - 180, 22 - - - Extract - - - 177, 6 - - - 180, 22 - - - Clone - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO - vAAADrwBlbxySQAAACVJREFUOE9jwAL+E8AkAbI0IYNRA0YNAIFRA8g0AKYJF0YCDAwAzhor1TRE/JoA - AAAASUVORK5CYII= - - - - 180, 22 - - - Rename - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO - vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xMkMEa+wAAAC/SURBVDhPlVHB - DQMhDEOIfwfoOuzFoPxhAd5c6/SMAgq0tRQFmdgXfA5IKUkBMcbHPxyJCxVCkK7rm+EwaK1dQO9dClzO - WfpOTM7hy1oMGNvY4pucxNY2p6cAWzFw2oZuMmiJweGeHM634UdLg50YwD05vQ2fYoaoDTEMrJyIfw3R - 4qYQWUZgg6OwlDJyMH8LcwF2T8FZ5kYQb4Lde/9Et8S6Dy1z0LUGi7VpWGvl3Lw2V98ZrtwIUYktwwPn - 3AtE5NqX8pp0ZQAAAABJRU5ErkJggg== - - - - 180, 22 - - - Replace - - - 180, 22 - - - Delete - - - 181, 258 - - - contextMenuPCKEntries - - - System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Left - - - 0 - - - 204, 20 - - - 32, 32 - - - 5, 50 - - - 0 - - - 274, 501 - - - 20 - - - treeViewMain - - - System.Windows.Forms.TreeView, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - 8 + + 22, 20 + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO @@ -1611,6 +1316,20 @@ EntityMaterials.bin + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xOdTWsmQAAAA3SURBVDhPY/j/ + /z9FGKsgGIsCKWSMTQ0QYxUE45FmALpiYvFwMgAbxqIYG8YqCMajBhCJ/zMAAPGwpV/Xje8RAAAAAElF + TkSuQmCC + + + + 157, 22 + + + Create + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO @@ -1663,12 +1382,33 @@ Add File + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xOdTWsmQAAABzSURBVDhPpYzB + DQAhCARp4hr3Txu254WTjYRb9cEmk/BgRjBVHTv85Twmgt77PcJEYIFrhIkAgWOEiSAGthEmgtbaD9fW + mBgpB4xywCgFxiMf5YDdrq3l5wjEjKtzTARMNlydY2IGot2ureVnRjkQmZbICyCi7XU5cfqKAAAAAElF + TkSuQmCC + + + + 157, 22 + + + Import + 186, 22 Export as 3DS Texture + + 157, 22 + + + Export + 222, 22 @@ -1741,6 +1481,185 @@ Entity Materials File (.BIN) + + 157, 22 + + + Set File Type + + + 154, 6 + + + 223, 22 + + + Generate MipMap Texture + + + 223, 22 + + + View File Info + + + 223, 22 + + + Correct Skin Decimals + + + 100, 22 + + + Big + + + 100, 22 + + + Little + + + 223, 22 + + + Set Endianness + + + 80, 22 + + + 1 + + + 80, 22 + + + 2 + + + 80, 22 + + + 3 + + + 223, 22 + + + Set Model Container version + + + 157, 22 + + + Misc. Functions + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xMkMEa+wAAACYSURBVDhPpZBZ + CsQwDEOd5QK5/2E9qCBGXtopzMcDxxKyY3P3izmnm9kt0OlVvsVVVgOAtvduQ4KJdYbaGKOEFFOHamut + ENKaMlk75zi2QX1rUqDpkbEF/cGktb47ygb5ODA8hVArgsK1cx+EAE7LaB8+hb3QzDx942eAXrqjBOgR + MRkBfHeUADbe8ncANw4NhLwF33R3+wA6sV5/E8GOLwAAAABJRU5ErkJggg== + + + + 157, 22 + + + Extract + + + 154, 6 + + + 157, 22 + + + Clone + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + vAAADrwBlbxySQAAACVJREFUOE9jwAL+E8AkAbI0IYNRA0YNAIFRA8g0AKYJF0YCDAwAzhor1TRE/JoA + AAAASUVORK5CYII= + + + + 157, 22 + + + Rename + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xMkMEa+wAAAC/SURBVDhPlVHB + DQMhDEOIfwfoOuzFoPxhAd5c6/SMAgq0tRQFmdgXfA5IKUkBMcbHPxyJCxVCkK7rm+EwaK1dQO9dClzO + WfpOTM7hy1oMGNvY4pucxNY2p6cAWzFw2oZuMmiJweGeHM634UdLg50YwD05vQ2fYoaoDTEMrJyIfw3R + 4qYQWUZgg6OwlDJyMH8LcwF2T8FZ5kYQb4Lde/9Et8S6Dy1z0LUGi7VpWGvl3Lw2V98ZrtwIUYktwwPn + 3AtE5NqX8pp0ZQAAAABJRU5ErkJggg== + + + + 157, 22 + + + Replace + + + 157, 22 + + + Delete + + + 158, 236 + + + contextMenuPCKEntries + + + System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Left + + + 0 + + + 204, 20 + + + 32, 32 + + + 5, 50 + + + 0 + + + 274, 501 + + + 20 + + + treeViewMain + + + System.Windows.Forms.TreeView, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 9 + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO @@ -1783,7 +1702,7 @@ $this - 2 + 3 Top, Bottom, Left, Right @@ -1816,11 +1735,11 @@ $this - 10 + 0 - + True - + None @@ -2173,6 +2092,6 @@ PckEditor - System.Windows.Forms.UserControl, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + PckStudio.Internal.EditorControl`1[[OMI.Formats.Pck.PckFile, OMI Filetypes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], PCK-Studio, Version=7.0.0.2, Culture=neutral, PublicKeyToken=null \ No newline at end of file diff --git a/PCK-Studio/Forms/Editor/AnimationEditor.cs b/PCK-Studio/Forms/Editor/AnimationEditor.cs index 188f3f78..7aa1dd6d 100644 --- a/PCK-Studio/Forms/Editor/AnimationEditor.cs +++ b/PCK-Studio/Forms/Editor/AnimationEditor.cs @@ -38,7 +38,7 @@ using PckStudio.Interfaces; namespace PckStudio.Forms.Editor { - public partial class AnimationEditor : Editor + public partial class AnimationEditor : EditorForm { private bool _isSpecialTile; diff --git a/PCK-Studio/Forms/Editor/AudioEditor.cs b/PCK-Studio/Forms/Editor/AudioEditor.cs index ffdedc21..10bd5ba1 100644 --- a/PCK-Studio/Forms/Editor/AudioEditor.cs +++ b/PCK-Studio/Forms/Editor/AudioEditor.cs @@ -27,7 +27,7 @@ using PckStudio.Interfaces; namespace PckStudio.Forms.Editor { - public partial class AudioEditor : Editor + public partial class AudioEditor : EditorForm { public string defaultType = "yes"; MainForm parent = null; diff --git a/PCK-Studio/Forms/Editor/BehaviourEditor.cs b/PCK-Studio/Forms/Editor/BehaviourEditor.cs index 8ac726e1..1f929839 100644 --- a/PCK-Studio/Forms/Editor/BehaviourEditor.cs +++ b/PCK-Studio/Forms/Editor/BehaviourEditor.cs @@ -12,7 +12,7 @@ using PckStudio.Forms.Additional_Popups.EntityForms; namespace PckStudio.Forms.Editor { // Behaviours File Format research by Miku and MattNL - public partial class BehaviourEditor : Editor + public partial class BehaviourEditor : EditorForm { private const string BehaviourEntryDataType = "behaviours"; private readonly List BehaviourData = Entities.BehaviourInfos; diff --git a/PCK-Studio/Forms/Editor/COLEditor.cs b/PCK-Studio/Forms/Editor/COLEditor.cs index 6279fab1..381bf5a1 100644 --- a/PCK-Studio/Forms/Editor/COLEditor.cs +++ b/PCK-Studio/Forms/Editor/COLEditor.cs @@ -16,7 +16,7 @@ using System.Collections.ObjectModel; namespace PckStudio.Forms.Editor { - public partial class COLEditor : Editor + public partial class COLEditor : EditorForm { ColorContainer _defaultColourfile; string _clipboard_color = "#FFFFFF"; diff --git a/PCK-Studio/Forms/Editor/CustomSkinEditor.cs b/PCK-Studio/Forms/Editor/CustomSkinEditor.cs index 582ffb4e..d2e7beb5 100644 --- a/PCK-Studio/Forms/Editor/CustomSkinEditor.cs +++ b/PCK-Studio/Forms/Editor/CustomSkinEditor.cs @@ -18,7 +18,7 @@ using PckStudio.Interfaces; namespace PckStudio.Forms.Editor { - public partial class CustomSkinEditor : Editor + public partial class CustomSkinEditor : EditorForm { private Random rng; private bool _inflateOverlayParts; diff --git a/PCK-Studio/Forms/Editor/GameRuleFileEditor.cs b/PCK-Studio/Forms/Editor/GameRuleFileEditor.cs index c34ea8c8..252de9c0 100644 --- a/PCK-Studio/Forms/Editor/GameRuleFileEditor.cs +++ b/PCK-Studio/Forms/Editor/GameRuleFileEditor.cs @@ -29,7 +29,7 @@ using PckStudio.Interfaces; namespace PckStudio.Forms.Editor { - public partial class GameRuleFileEditor : Editor + public partial class GameRuleFileEditor : EditorForm { public GameRuleFileEditor(GameRuleFile gameRuleFile, ISaveContext saveContext) : base(gameRuleFile, saveContext) diff --git a/PCK-Studio/Forms/Editor/LOCEditor.cs b/PCK-Studio/Forms/Editor/LOCEditor.cs index 96bcd0b2..bd148b3d 100644 --- a/PCK-Studio/Forms/Editor/LOCEditor.cs +++ b/PCK-Studio/Forms/Editor/LOCEditor.cs @@ -13,7 +13,7 @@ using PckStudio.Interfaces; namespace PckStudio.Forms.Editor { - public partial class LOCEditor : Editor + public partial class LOCEditor : EditorForm { public LOCEditor(LOCFile locFile, ISaveContext context) : base(locFile, context) diff --git a/PCK-Studio/Forms/Editor/MaterialsEditor.cs b/PCK-Studio/Forms/Editor/MaterialsEditor.cs index 84e7cb30..62fb7f66 100644 --- a/PCK-Studio/Forms/Editor/MaterialsEditor.cs +++ b/PCK-Studio/Forms/Editor/MaterialsEditor.cs @@ -12,7 +12,7 @@ using PckStudio.Interfaces; namespace PckStudio.Forms.Editor { // Materials File Format research by PhoenixARC - public partial class MaterialsEditor : Editor + public partial class MaterialsEditor : EditorForm { private readonly List MaterialData = Entities.BehaviourInfos; diff --git a/PCK-Studio/Forms/Editor/ModelEditor.cs b/PCK-Studio/Forms/Editor/ModelEditor.cs index 57d7240c..fe459e26 100644 --- a/PCK-Studio/Forms/Editor/ModelEditor.cs +++ b/PCK-Studio/Forms/Editor/ModelEditor.cs @@ -19,7 +19,7 @@ using OMI.Formats.Material; namespace PckStudio.Forms.Editor { - public partial class ModelEditor : Editor + public partial class ModelEditor : EditorForm { private readonly ITryGetSet _textures; private readonly ITryGet _tryGetEntityMaterial; diff --git a/PCK-Studio/Forms/Editor/TextureAtlasEditor.cs b/PCK-Studio/Forms/Editor/TextureAtlasEditor.cs index de318dd6..2479ebe4 100644 --- a/PCK-Studio/Forms/Editor/TextureAtlasEditor.cs +++ b/PCK-Studio/Forms/Editor/TextureAtlasEditor.cs @@ -33,7 +33,7 @@ using PckStudio.Internal.Json; namespace PckStudio.Forms.Editor { - internal partial class TextureAtlasEditor : Editor + internal partial class TextureAtlasEditor : EditorForm { private readonly ITryGet _tryGetAnimation; private readonly ITryGet> _tryGetAnimationSaveContext; diff --git a/PCK-Studio/Forms/Skins-And-Textures/AdvancedOptions.cs b/PCK-Studio/Forms/Skins-And-Textures/AdvancedOptions.cs index 863353b7..2390a2a5 100644 --- a/PCK-Studio/Forms/Skins-And-Textures/AdvancedOptions.cs +++ b/PCK-Studio/Forms/Skins-And-Textures/AdvancedOptions.cs @@ -54,9 +54,7 @@ namespace PckStudio.Popups { try { - var reader = new PckFileReader(_endianness); - using var ms = new MemoryStream(asset.Data); - PckFile subPCK = reader.FromStream(ms); + PckFile subPCK = asset.GetData(new PckFileReader(_endianness)); applyBulkProperties(subPCK.GetAssets(), index); asset.SetData(new PckFileWriter(subPCK, _endianness)); } diff --git a/PCK-Studio/Interfaces/IEditor.cs b/PCK-Studio/Interfaces/IEditor.cs index 15b762d3..b8d337f9 100644 --- a/PCK-Studio/Interfaces/IEditor.cs +++ b/PCK-Studio/Interfaces/IEditor.cs @@ -9,19 +9,13 @@ namespace PckStudio.Interfaces { internal interface IEditor where T : class { - T Value { get; } + T EditorValue { get; } - string SavePath { get; } - - bool Open(string filepath, OMI.Endianness endianness); - - bool Open(T value); + ISaveContext SaveContext { get; } void Save(); void SaveAs(); - - void SaveTo(string filepath); void Close(); diff --git a/PCK-Studio/Interfaces/ISaveContext.cs b/PCK-Studio/Interfaces/ISaveContext.cs index 3abbddba..1b11d4f4 100644 --- a/PCK-Studio/Interfaces/ISaveContext.cs +++ b/PCK-Studio/Interfaces/ISaveContext.cs @@ -1,6 +1,4 @@ -using System; - -namespace PckStudio.Interfaces +namespace PckStudio.Interfaces { public interface ISaveContext { @@ -8,18 +6,4 @@ namespace PckStudio.Interfaces public void Save(T value); } - - public sealed class DelegatedSaveContext : ISaveContext - { - private readonly Action _saveAction; - public bool AutoSave { get; } - - public void Save(T value) => _saveAction(value); - - public DelegatedSaveContext(bool autoSave, Action saveAction) - { - AutoSave = autoSave; - _saveAction = saveAction; - } - } } \ No newline at end of file diff --git a/PCK-Studio/Internal/DelegatedFileSaveContext.cs b/PCK-Studio/Internal/DelegatedFileSaveContext.cs new file mode 100644 index 00000000..9f5ce4f6 --- /dev/null +++ b/PCK-Studio/Internal/DelegatedFileSaveContext.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using Newtonsoft.Json.Linq; +using PckStudio.Interfaces; + +namespace PckStudio.Internal +{ + internal sealed class DelegatedFileSaveContext : ISaveContext + { + public delegate void SerializeDataToStreamDelegate(T value, Stream stream); + + public bool AutoSave { get; } + public string Filepath { get; private set; } + private SerializeDataToStreamDelegate _serializeDataDelegate; + private FileDialogFilter _dialogFilter; + + public DelegatedFileSaveContext(string filepath, bool autoSave, FileDialogFilter dialogFilter, SerializeDataToStreamDelegate serializeDataDelegate) + { + AutoSave = autoSave; + Filepath = filepath; + _serializeDataDelegate = serializeDataDelegate; + _dialogFilter = dialogFilter; + } + + public void Save(T value) + { + if (!File.Exists(Filepath)) + { + SaveFileDialog saveFileDialog = new SaveFileDialog(); + saveFileDialog.Filter = _dialogFilter.ToString(); + if (saveFileDialog.ShowDialog() != DialogResult.OK) + return; + Filepath = saveFileDialog.FileName; + } + using (Stream stream = File.OpenWrite(Filepath)) + { + _serializeDataDelegate(value, stream); + } + } + } +} diff --git a/PCK-Studio/Internal/DelegatedSaveContext.cs b/PCK-Studio/Internal/DelegatedSaveContext.cs new file mode 100644 index 00000000..a6fb2452 --- /dev/null +++ b/PCK-Studio/Internal/DelegatedSaveContext.cs @@ -0,0 +1,19 @@ +using System; +using PckStudio.Interfaces; + +namespace PckStudio.Internal +{ + public class DelegatedSaveContext : ISaveContext + { + private readonly Action _saveAction; + public bool AutoSave { get; } + + public void Save(T value) => _saveAction(value); + + public DelegatedSaveContext(bool autoSave, Action saveAction) + { + AutoSave = autoSave; + _saveAction = saveAction; + } + } +} \ No newline at end of file diff --git a/PCK-Studio/Internal/EditorControl.cs b/PCK-Studio/Internal/EditorControl.cs new file mode 100644 index 00000000..cceb09cf --- /dev/null +++ b/PCK-Studio/Internal/EditorControl.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using PckStudio.Interfaces; + +namespace PckStudio.Internal +{ + internal class EditorControl : UserControl, IEditor where T : class + { + public T EditorValue { get; } + + public ISaveContext SaveContext { get; } + + public EditorControl() + { + } + + protected EditorControl(T value, ISaveContext saveContext) + { + _ = value ?? throw new ArgumentNullException(nameof(value)); + EditorValue = value; + SaveContext = saveContext; + } + + public void Save() => SaveContext.Save(EditorValue); + + protected override void OnControlRemoved(ControlEventArgs e) + { + if (SaveContext.AutoSave) + Save(); + base.OnControlRemoved(e); + } + + public virtual void SaveAs() + { + } + + public virtual void Close() + { + } + + public virtual void UpdateView() + { + } + } +} diff --git a/PCK-Studio/Internal/Editor.cs b/PCK-Studio/Internal/EditorForm.cs similarity index 84% rename from PCK-Studio/Internal/Editor.cs rename to PCK-Studio/Internal/EditorForm.cs index 66e8e9eb..1cf19eff 100644 --- a/PCK-Studio/Internal/Editor.cs +++ b/PCK-Studio/Internal/EditorForm.cs @@ -9,12 +9,12 @@ using PckStudio.Interfaces; namespace PckStudio.Internal { - public abstract class Editor : MetroForm where T : class + public abstract class EditorForm : MetroForm where T : class { protected T EditorValue; private readonly ISaveContext SaveContext; - protected Editor(T value, ISaveContext saveContext) + protected EditorForm(T value, ISaveContext saveContext) { _ = value ?? throw new ArgumentNullException(nameof(value)); EditorValue = value; diff --git a/PCK-Studio/MainForm.Designer.cs b/PCK-Studio/MainForm.Designer.cs index 19af50d7..c9bcfaff 100644 --- a/PCK-Studio/MainForm.Designer.cs +++ b/PCK-Studio/MainForm.Designer.cs @@ -81,7 +81,6 @@ this.pckOpen = new System.Windows.Forms.PictureBox(); this.editorTab = new MetroFramework.Controls.MetroTabPage(); this.label11 = new MetroFramework.Controls.MetroLabel(); - this.LittleEndianCheckBox = new MetroFramework.Controls.MetroCheckBox(); toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator(); @@ -503,21 +502,11 @@ resources.ApplyResources(this.label11, "label11"); this.label11.Name = "label11"; // - // LittleEndianCheckBox - // - resources.ApplyResources(this.LittleEndianCheckBox, "LittleEndianCheckBox"); - this.LittleEndianCheckBox.BackColor = System.Drawing.Color.Transparent; - this.LittleEndianCheckBox.Name = "LittleEndianCheckBox"; - this.LittleEndianCheckBox.Style = MetroFramework.MetroColorStyle.White; - this.LittleEndianCheckBox.Theme = MetroFramework.MetroThemeStyle.Dark; - this.LittleEndianCheckBox.UseSelectable = true; - // // MainForm // this.ApplyImageInvert = true; resources.ApplyResources(this, "$this"); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.Controls.Add(this.LittleEndianCheckBox); this.Controls.Add(this.menuStrip); this.Controls.Add(this.tabControl); this.DisplayHeader = false; @@ -553,7 +542,6 @@ private System.Windows.Forms.ToolStripMenuItem saveToolStripMenuItem; private PckStudio.Controls.CustomTabControl tabControl; private MetroFramework.Controls.MetroTabPage editorTab; - private MetroFramework.Controls.MetroCheckBox LittleEndianCheckBox; private MetroFramework.Controls.MetroLabel label11; private System.Windows.Forms.ToolStripMenuItem skinPackToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem texturePackToolStripMenuItem; diff --git a/PCK-Studio/MainForm.cs b/PCK-Studio/MainForm.cs index 6d97509b..9156fbb3 100644 --- a/PCK-Studio/MainForm.cs +++ b/PCK-Studio/MainForm.cs @@ -1,52 +1,28 @@ using System; -using System.Collections.Generic; -using System.Drawing; using System.IO; using System.Linq; -using System.Windows.Forms; -using System.Drawing.Drawing2D; using System.Diagnostics; -using System.Drawing.Imaging; +using System.Windows.Forms; +using System.Collections.Generic; using System.Text.RegularExpressions; using OMI.Formats.Pck; -using OMI.Formats.Color; -using OMI.Formats.Model; using OMI.Formats.GameRule; -using OMI.Formats.Material; -using OMI.Formats.Behaviour; using OMI.Formats.Languages; -using OMI.Workers; using OMI.Workers.Pck; -using OMI.Workers.Color; -using OMI.Workers.Model; using OMI.Workers.GameRule; -using OMI.Workers.Material; using OMI.Workers.Language; -using OMI.Workers.Behaviour; using PckStudio.Properties; -using PckStudio.Internal.FileFormats; using PckStudio.Forms; -using PckStudio.Forms.Editor; -using PckStudio.Forms.Additional_Popups.Animation; using PckStudio.Forms.Additional_Popups; using PckStudio.Internal.Misc; -using PckStudio.Internal.IO.PckAudio; -using PckStudio.Internal.IO._3DST; -using PckStudio.Internal; using PckStudio.Forms.Features; using PckStudio.Extensions; using PckStudio.Popups; using PckStudio.External.API.Miles; -using PckStudio.Internal.Json; -using PckStudio.Internal.Deserializer; -using PckStudio.Internal.Serializer; using PckStudio.Internal.App; -using PckStudio.Internal.Skin; using PckStudio.Interfaces; -using PckStudio.Rendering; -using MetroFramework.Forms; -using System.Windows.Forms.Design; using PckStudio.Controls; +using PckStudio.Internal; namespace PckStudio { @@ -54,7 +30,7 @@ namespace PckStudio { private PckManager PckManager = null; - private Dictionary openFiles = new Dictionary(); + private Dictionary openTabPages = new Dictionary(); public MainForm() { @@ -82,42 +58,124 @@ namespace PckStudio AddEditorPage(filepath); } - private void AddEditorPage(PckFile pck) - { - var editor = new PckEditor(); - editor.Open(pck); - AddPage("Unsaved pck", editor); + internal void OpenNewPckTab(string caption, string identifier, PckFile pckFile, ISaveContext saveContext) + { + if (openTabPages.ContainsKey(identifier)) + { + tabControl.SelectTab(openTabPages[identifier]); + return; + } + var editor = new PckEditor(pckFile, saveContext); + AddPage(caption, identifier, editor); } - private TabPage AddPage(string caption, Control control) + private void AddEditorPage(string caption, string identifier, PckFile pck, OMI.Endianness endianness = OMI.Endianness.BigEndian, ISaveContext saveContext = null) + { + saveContext ??= GetSaveContext("./new.pck", "PCK (Minecraft Console Package)", endianness); + var editor = new PckEditor(pck, saveContext); + AddPage(caption, identifier, editor); + } + + + private PckFile ReadPck(string filePath, OMI.Endianness endianness) + { + var pckReader = new PckFileReader(endianness); + return pckReader.FromFile(filePath); + } + + private class PackInfo + { + public static readonly PackInfo Empty = new PackInfo(default, default, default); + public bool IsValid { get; } + public PckFile File { get; } + public OMI.Endianness Endianness { get; } + + public bool AllowEndianSwap { get; } + + public PackInfo(PckFile file, OMI.Endianness endianness, bool allowEndianSwap) + { + File = file; + Endianness = endianness; + AllowEndianSwap = allowEndianSwap; + IsValid = file is not null && Enum.IsDefined(typeof(OMI.Endianness), endianness); + } + } + + private bool TryOpenPck(string filepath, out PackInfo packInfo) + { + if (!File.Exists(filepath) || !filepath.EndsWith(".pck")) + { + packInfo = PackInfo.Empty; + return false; + } + try + { + PckFile pckFile = ReadPck(filepath, OMI.Endianness.BigEndian); + packInfo = new PackInfo(pckFile, OMI.Endianness.BigEndian, true); + return packInfo.IsValid; + } + catch (OverflowException) + { + try + { + // if failed, attempt again in the reverse. THEN throw an error if failed + PckFile pckFile = ReadPck(filepath, OMI.Endianness.LittleEndian); + packInfo = new PackInfo(pckFile, OMI.Endianness.LittleEndian, true); + return packInfo.IsValid; + } + catch (OverflowException ex) + { + MessageBox.Show(this, "Failed to open pck", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + Debug.WriteLine(ex.Message); + } + } + catch + { + MessageBox.Show(this, "Failed to open pck. There's two common reasons for this:\n" + + "1. The file is audio/music cues PCK file. Please use the specialized editor while inside of a pck file.\n" + + "2. We're aware of an issue where a pck file might fail to load because it contains multiple entries with the same path.", + "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + packInfo = PackInfo.Empty; + return false; + } + + private void AddEditorPage(string filepath) + { + if (openTabPages.ContainsKey(filepath)) + { + tabControl.SelectTab(openTabPages[filepath]); + return; + } + SaveToRecentFiles(filepath); + + if (TryOpenPck(filepath, out PackInfo packInfo)) + { + ISaveContext saveContext = GetSaveContext(filepath, "PCK (Minecraft Console Package)", packInfo.Endianness); + var editor = new PckEditor(packInfo.File, saveContext); + TabPage page = AddPage(Path.GetFileName(filepath), filepath, editor); + return; + } + MessageBox.Show(string.Format("Failed to load {0}", Path.GetFileName(filepath)), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + + private ISaveContext GetSaveContext(string filepath, string description, OMI.Endianness endianness) + { + return new DelegatedFileSaveContext(filepath, false, new FileDialogFilter(description, "*"+Path.GetExtension(filepath)),(pck, stream) => new PckFileWriter(pck, endianness).WriteToStream(stream)); + } + + private TabPage AddPage(string caption, string identifier, Control control) { control.Dock = DockStyle.Fill; var page = new TabPage(caption); page.Controls.Add(control); tabControl.TabPages.Add(page); tabControl.SelectTab(page); + if (!openTabPages.ContainsKey(identifier)) + openTabPages.Add(identifier, page); return page; } - private void AddEditorPage(string filepath) - { - if (openFiles.ContainsKey(filepath)) - { - tabControl.SelectTab(openFiles[filepath]); - return; - } - SaveToRecentFiles(filepath); - - var editor = new PckEditor(); - if (editor.Open(filepath, Settings.Default.UseLittleEndianAsDefault ? OMI.Endianness.LittleEndian : OMI.Endianness.BigEndian)) - { - TabPage page = AddPage(Path.GetFileName(filepath), editor); - openFiles.Add(filepath, page); - return; - } - MessageBox.Show(string.Format("Failed to load {0}", Path.GetFileName(filepath)), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - private bool TryGetEditor(TabPage page, out IEditor editor) { if (page.Controls[0] is IEditor outEditor) @@ -129,50 +187,17 @@ namespace PckStudio return false; } - private bool TryGetEditor(out IEditor editor) - { - return TryGetEditor(tabControl.SelectedTab, out editor); - } + private bool TryGetCurrentEditor(out IEditor editor) => TryGetEditor(tabControl.SelectedTab, out editor); - // TODO: decide on how to handle embedded pck files - // private void HandleInnerPckFile(PckAsset asset) - // { - //if (Settings.Default.LoadSubPcks && - // (asset.Type == PckAssetType.SkinDataFile || asset.Type == PckAssetType.TexturePackInfoFile) && - // asset.Size > 0 && treeViewMain.SelectedNode.Nodes.Count == 0) - //{ - // try - // { - // PckFile subPCKfile = asset.GetData(new PckFileReader(LittleEndianCheckBox.Checked ? OMI.Endianness.LittleEndian : OMI.Endianness.BigEndian)); - // BuildPckTreeView(treeViewMain.SelectedNode.Nodes, subPCKfile); - // treeViewMain.SelectedNode.ExpandAll(); - // } - // catch (OverflowException ex) - // { - // MessageBox.Show(this, "Failed to open pck\n" + - // "Try checking the 'Open/Save as Switch/Vita/PS4/Xbox One pck' checkbox in the upper right corner.", - // "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - // Debug.WriteLine(ex.Message); - // } - // return; - //} - //treeViewMain.SelectedNode.Nodes.Clear(); - //treeViewMain.SelectedNode.Collapse(); - // } - - private void MainForm_Load(object sender, EventArgs e) + private void MainForm_Load(object sender, EventArgs e) { - SettingsManager.Default.RegisterPropertyChangedCallback(nameof(Settings.Default.UseLittleEndianAsDefault), state => - { - LittleEndianCheckBox.Checked = state; - }); - SettingsManager.Default.RegisterPropertyChangedCallback(nameof(Settings.Default.LoadSubPcks), () => - { - if (TryGetEditor(out IEditor editor)) - { - editor.UpdateView(); - } - }); + //SettingsManager.Default.RegisterPropertyChangedCallback(nameof(Settings.Default.LoadSubPcks), () => + //{ + // if (TryGetCurrentEditor(out IEditor editor)) + // { + // editor.UpdateView(); + // } + // }); LoadRecentFileList(); } @@ -209,10 +234,10 @@ namespace PckStudio private void RemoveOpenFile(TabPage page) { - KeyValuePair kv = openFiles.FirstOrDefault((kv) => kv.Value == page); - if (kv.Key != null && kv.Value != null) + KeyValuePair kv = openTabPages.FirstOrDefault((kv) => kv.Value == page); + if (kv.Key != default) { - openFiles.Remove(kv.Key); + openTabPages.Remove(kv.Key); } } @@ -308,9 +333,8 @@ namespace PckStudio { closeToolStripMenuItem.Visible = tabControl.SelectedIndex > 0; closeAllToolStripMenuItem.Visible = tabControl.SelectedIndex == 0 && tabControl.TabCount > 1; + saveToolStripMenuItem.Visible = tabControl.SelectedIndex > 0; saveAsToolStripMenuItem.Visible = tabControl.SelectedIndex > 0; - saveAsToolStripMenuItem.Visible = tabControl.SelectedIndex > 0; - if (tabControl.SelectedIndex == 0) { @@ -330,10 +354,7 @@ namespace PckStudio locFile.InitializeDefault(packName); pack.CreateNewAsset("localisation.loc", PckAssetType.LocalisationFile, new LOCFileWriter(locFile, 2)); - pack.CreateNewAssetIf(createSkinsPCK, "Skins.pck", PckAssetType.SkinDataFile, new PckFileWriter(new PckFile(3, true), - LittleEndianCheckBox.Checked - ? OMI.Endianness.LittleEndian - : OMI.Endianness.BigEndian)); + pack.CreateNewAssetIf(createSkinsPCK, "Skins.pck", PckAssetType.SkinDataFile, new PckFileWriter(new PckFile(3, true), OMI.Endianness.BigEndian)); return pack; } @@ -354,7 +375,7 @@ namespace PckStudio texturepackInfoAsset.AddProperty("PACKID", "0"); texturepackInfoAsset.AddProperty("DATAPATH", $"{res}Data.pck"); - texturepackInfoAsset.SetData(new PckFileWriter(infoPCK, LittleEndianCheckBox.Checked ? OMI.Endianness.LittleEndian : OMI.Endianness.BigEndian)); + texturepackInfoAsset.SetData(new PckFileWriter(infoPCK, OMI.Endianness.BigEndian)); return pack; } @@ -391,7 +412,7 @@ namespace PckStudio if (namePrompt.ShowDialog(this) == DialogResult.OK) { PckFile skinPck = InitializePack(new Random().Next(8000, int.MaxValue), 0, namePrompt.NewText, true); - AddEditorPage(skinPck); + AddEditorPage("Unsaved skin pack", "Unsaved skin pack", skinPck); } } @@ -401,7 +422,7 @@ namespace PckStudio if (packPrompt.ShowDialog() == DialogResult.OK) { PckFile texturePackPck = InitializeTexturePack(new Random().Next(8000, int.MaxValue), 0, packPrompt.PackName, packPrompt.PackRes, packPrompt.CreateSkinsPck); - AddEditorPage(texturePackPck); + AddEditorPage("Unsaved texture pack", "Unsaved texture pack", texturePackPck); } } @@ -411,16 +432,17 @@ namespace PckStudio if (packPrompt.ShowDialog() == DialogResult.OK) { PckFile mashUpPck = InitializeMashUpPack(new Random().Next(8000, int.MaxValue), 0, packPrompt.PackName, packPrompt.PackRes); - AddEditorPage(mashUpPck); + AddEditorPage("Unsaved mash-up pack", "Unsaved mash-up pack", mashUpPck); } } private void quickChangeToolStripMenuItem_Click(object sender, EventArgs e) { - if (TryGetEditor(out IEditor editor)) + if (TryGetCurrentEditor(out IEditor editor)) { - using AdvancedOptions advanced = new AdvancedOptions(editor.Value); - advanced.IsLittleEndian = LittleEndianCheckBox.Checked; + using AdvancedOptions advanced = new AdvancedOptions(editor.EditorValue); + // TODO: + //advanced.IsLittleEndian = LittleEndianCheckBox.Checked; if (advanced.ShowDialog() == DialogResult.OK) { editor.UpdateView(); @@ -439,13 +461,9 @@ namespace PckStudio info.ShowDialog(this); } - [Obsolete("Move this")] + [Obsolete("ReMove this")] public string GetDataPath() { - if (TryGetEditor(out IEditor editor)) - { - return Path.Combine(Path.GetDirectoryName(editor.SavePath), "Data"); - } return ""; } @@ -561,7 +579,7 @@ namespace PckStudio private void saveToolStripMenuItem_Click(object sender, EventArgs e) { - if (TryGetEditor(out IEditor editor)) + if (TryGetCurrentEditor(out IEditor editor)) { editor.Save(); } @@ -569,7 +587,7 @@ namespace PckStudio private void saveAsToolStripMenuItem_Click(object sender, EventArgs e) { - if (TryGetEditor(out IEditor editor)) + if (TryGetCurrentEditor(out IEditor editor)) { editor.SaveAs(); } @@ -625,9 +643,9 @@ namespace PckStudio private void fullBoxSupportToolStripMenuItem_CheckedChanged(object sender, EventArgs e) { - if (TryGetEditor(out IEditor editor)) + if (TryGetCurrentEditor(out IEditor editor)) { - editor.Value.SetVersion(fullBoxSupportToolStripMenuItem.Checked); + editor.EditorValue.SetVersion(fullBoxSupportToolStripMenuItem.Checked); } } diff --git a/PCK-Studio/MainForm.resx b/PCK-Studio/MainForm.resx index 260f1702..b1bb4ce0 100644 --- a/PCK-Studio/MainForm.resx +++ b/PCK-Studio/MainForm.resx @@ -128,13 +128,13 @@ False - 183, 6 + 167, 6 False - 183, 6 + 167, 6 202, 6 @@ -149,111 +149,6 @@ None - - 37, 20 - - - File - - - 39, 20 - - - Edit - - - - iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAL - DAAACwwBP0AiyAAAA6pJREFUeF7tms9vDVEYhouqpFZVRFpdd+cPkFphQeKPqIUfSVl0Y9OQWNpXE/ak - SEhYkEjZUFZERCxtCaKKWKDe787jpNftmTlzz4x0rvMkb3Lzzfu9c8690zkz0+lLJBKJRCKRqIOVlZUx - 6Yb0WSqL9dyUxolrFhq4Tf6DFMtHaYzY5qBB2y9fFdeIbQ4adDeHvY8lYpsDA3dQDoY2B+XmwLgdlIOh - zUG5OTBuB+VgaHNQbg6M20E5GNoclP8N2l/M+r3eKHc9IWNV6/d6I+x6QqYq1+/1RvH1hEy9cNj7KL6e - wNizME0/+HoWpukHX8/CNP3gK8NeWq13IivVStT+aPUjz6R0S/pmDUXQ5qBcG+zGQbmIr5LNaZK2YmQe - lA5K56V70hvpu9QGdgfl2mA3DsqrsTHaWO9KNvYD0iD2RKIIHS7T0h5pA6XGY3NhTtOU/Mj0h7fSFem4 - ZGfbXdIWbOsWGyNjtTGfkK5KNpcW2PzgC4Y2B+XaYDcOysHQ5gdfMLQ5KNcGu3FQDoY2P/jKMEGr9e7L - SrUStT9a/eDrWZimH3x18Ez6kX3M5af0PPtYPUzTD74qeS0dJnumVclnBu9+6UWrUiGWnQu+KrBHUGek - AaIte6N0X/LxUNqE3fz90jHpnVQJRPvBF8ttaZjINlQfkeyXfSktSA+kV5IdKSPY2lB9WLojRUOkH3yx - XCCuMiwzi46DOD/4YrHDfyuR0SjL7kzfW3AsRPrBVwUniYzGsrLIeIj0g68KFoiMRll2nqgEIv3gi+WX - dITIaJR1iMxoiPSDL5aLxFWGZWbRcRDnB18M9ixxB3EdaJvdrp6WnkhfkH0+JXlvt7Vtu2TP9qIgzg++ - GOaI6kDbRqW8y1y7XB7F3oG2zbZcERDlB18ZHkmXpLOSPVEeIqoN1e2XD7nGty9hzSNB9SHpqHROuiw9 - lkpBlB98ZeinNRf57LAPZYq2XOTbnNnDodUPvmBoK0TWp1lHEIu0FYI/GNr84AuGtkJkXc46glimrRD8 - wdDmB18wtBUia5kvIPi1OPzB0OYHXzC0FSJrY/4Eyr4gEXoStHU+lLpOgp9o9SOTvVBUBluKbEmypcmW - qLxl0Ja4IszjHqKsRvVtUswyOE+UH5nGJbud7ZZZojrQNrsQyvsSii6E5lqu7rDb6d1E5SOjvSl2Xerm - fSG7XF3zaZChbQPSlLQo2YnRZL+k1db85Q1t2ykF/cv+L5akeSls8olEIpFIJP4T+vp+A8lMcFIN42ej - AAAAAElFTkSuQmCC - - - - 62, 20 - - - Tools - - - - iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAL - DAAACwwBP0AiyAAAAeRJREFUeF7tzjGOIzEMAEH//9N3SaEzwzLH2plAFTZEUq/jOI7jOI5f+beZM8/l - n9s481z+uY0zz+Wf2zjzHP4VeRtnIt/HPyJv40zk+/hH5G2ciXwf/4i8jTOR/467kW/jG5H3cSfybXwj - 8j7uRL6Nb0Tex53It/GNyL9jb+RlxsasWWYs8pw9kZcZG7NmmbHIc/ZEXmZszJplxiLP2RN5mbExa5YZ - izxnT+RlxiK/5VnkZcYiz9kTeZmxyG95FnmZschz9kReZizyW55FXmYs8pw9kZcZi/yWZ5GXGYs8Z0/k - bZyJvMxY5Dl7Im/jTORlxiLP2RN5G2ciLzMWec6eyNs4E3mZschz9kS+zLqPPF9mLPKcPZEvs+4jz5cZ - izxnT+TLrPvI82XGIs/ZE/ky6z7yfJmxyHP2RL7MusiXWRd5zp7Il1kX+TLrIs/ZE/mxfDPynD2RH8s3 - I8/ZE/mxfDPynD2RH8s3I8/ZE/ky6yJfZl3kOXsiX2Zd5Musi/w79kb+mvHIXzMeeR93In/NeOSvGY+8 - jzuRb+MbkfdxJ/JtfCPy33E38jbORL6Pf0TexpnI9/GPyNs4E/k+/hF5G2ciP4d/bePMc/nnNs48l39u - 48xz+ec2zhzHcRzHcVz0ev0HFtq118xXwn0AAAAASUVORK5CYII= - - - - 60, 20 - - - Help - - - 14, 3 - - - 0, 6, 60, 0 - - - 326, 24 - - - - 2 - - - MainMenuStrip - - - menuStrip - - - System.Windows.Forms.MenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 1 - - - - iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO - vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4yMfEgaZUAAADuSURBVFhH7ZbB - CsMgEERDbv5A/v83e2jNTmCKGdegJk0heHgUn7vrKBQyxRj/iivJPM9WMTWjc45wJeAwhAghVJEG1nkl - XNkziLCvtteXphFCfQ08nOi+4kvTeFL1NfBQ/BLuefjS9NkAADOwPnpNX14UADBEaV4mNnkygN34Y/1v - AgeWZXll9So2eTLAEVm9ik2a7g1Qgn9t9bvFV/4gAOZdHgB1RPeUEeAZAeBr0d4R4JIACuqI7ikjwDMD - tDACNAfo/Sou0fQ9wGKvoQfO8i61W6SkTXi+XtLLgOwcFSna3It3c+LKO3HlfcRpBa3JBjU5E8DiAAAA - AElFTkSuQmCC - - - - 186, 22 - - - New - 151, 22 @@ -272,6 +167,23 @@ Mash-Up Pack + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4yMfEgaZUAAADuSURBVFhH7ZbB + CsMgEERDbv5A/v83e2jNTmCKGdegJk0heHgUn7vrKBQyxRj/iivJPM9WMTWjc45wJeAwhAghVJEG1nkl + XNkziLCvtteXphFCfQ08nOi+4kvTeFL1NfBQ/BLuefjS9NkAADOwPnpNX14UADBEaV4mNnkygN34Y/1v + AgeWZXll9So2eTLAEVm9ik2a7g1Qgn9t9bvFV/4gAOZdHgB1RPeUEeAZAeBr0d4R4JIACuqI7ikjwDMD + tDACNAfo/Sou0fQ9wGKvoQfO8i61W6SkTXi+XtLLgOwcFSna3It3c+LKO3HlfcRpBa3JBjU5E8DiAAAA + AElFTkSuQmCC + + + + 170, 22 + + + New + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO @@ -284,7 +196,7 @@ Ctrl+O - 186, 22 + 170, 22 Open @@ -305,28 +217,22 @@ - 186, 22 + 170, 22 Recently open - - 186, 22 - - - Pack Settings - - - False - 160, 22 Full box support - - False + + 170, 22 + + + Pack Settings @@ -342,16 +248,23 @@ Ctrl+Shift+S - 186, 22 + 170, 22 - Save As + Save + + + + False - 186, 22 + 170, 22 - Save + Save As + + + False @@ -375,7 +288,7 @@ - 186, 22 + 170, 22 Close @@ -384,7 +297,7 @@ False - 186, 22 + 170, 22 Close all @@ -402,11 +315,17 @@ - 186, 22 + 170, 22 Exit + + 37, 20 + + + File + False @@ -564,6 +483,12 @@ Quick Change + + 39, 20 + + + Edit + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAA @@ -585,12 +510,6 @@ Pck Manager - - 161, 22 - - - Audio Converter - 145, 22 @@ -603,6 +522,40 @@ Binka -> Wav + + 161, 22 + + + Audio Converter + + + + iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAL + DAAACwwBP0AiyAAAA6pJREFUeF7tms9vDVEYhouqpFZVRFpdd+cPkFphQeKPqIUfSVl0Y9OQWNpXE/ak + SEhYkEjZUFZERCxtCaKKWKDe787jpNftmTlzz4x0rvMkb3Lzzfu9c8690zkz0+lLJBKJRCKRqIOVlZUx + 6Yb0WSqL9dyUxolrFhq4Tf6DFMtHaYzY5qBB2y9fFdeIbQ4adDeHvY8lYpsDA3dQDoY2B+XmwLgdlIOh + zUG5OTBuB+VgaHNQbg6M20E5GNoclP8N2l/M+r3eKHc9IWNV6/d6I+x6QqYq1+/1RvH1hEy9cNj7KL6e + wNizME0/+HoWpukHX8/CNP3gK8NeWq13IivVStT+aPUjz6R0S/pmDUXQ5qBcG+zGQbmIr5LNaZK2YmQe + lA5K56V70hvpu9QGdgfl2mA3DsqrsTHaWO9KNvYD0iD2RKIIHS7T0h5pA6XGY3NhTtOU/Mj0h7fSFem4 + ZGfbXdIWbOsWGyNjtTGfkK5KNpcW2PzgC4Y2B+XaYDcOysHQ5gdfMLQ5KNcGu3FQDoY2P/jKMEGr9e7L + SrUStT9a/eDrWZimH3x18Ez6kX3M5af0PPtYPUzTD74qeS0dJnumVclnBu9+6UWrUiGWnQu+KrBHUGek + AaIte6N0X/LxUNqE3fz90jHpnVQJRPvBF8ttaZjINlQfkeyXfSktSA+kV5IdKSPY2lB9WLojRUOkH3yx + XCCuMiwzi46DOD/4YrHDfyuR0SjL7kzfW3AsRPrBVwUniYzGsrLIeIj0g68KFoiMRll2nqgEIv3gi+WX + dITIaJR1iMxoiPSDL5aLxFWGZWbRcRDnB18M9ixxB3EdaJvdrp6WnkhfkH0+JXlvt7Vtu2TP9qIgzg++ + GOaI6kDbRqW8y1y7XB7F3oG2zbZcERDlB18ZHkmXpLOSPVEeIqoN1e2XD7nGty9hzSNB9SHpqHROuiw9 + lkpBlB98ZeinNRf57LAPZYq2XOTbnNnDodUPvmBoK0TWp1lHEIu0FYI/GNr84AuGtkJkXc46glimrRD8 + wdDmB18wtBUia5kvIPi1OPzB0OYHXzC0FSJrY/4Eyr4gEXoStHU+lLpOgp9o9SOTvVBUBluKbEmypcmW + qLxl0Ja4IszjHqKsRvVtUswyOE+UH5nGJbud7ZZZojrQNrsQyvsSii6E5lqu7rDb6d1E5SOjvSl2Xerm + fSG7XF3zaZChbQPSlLQo2YnRZL+k1db85Q1t2ykF/cv+L5akeSls8olEIpFIJP4T+vp+A8lMcFIN42ej + AAAAAElFTkSuQmCC + + + + 62, 20 + + + Tools + iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO @@ -1116,20 +1069,6 @@ About - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAKdJREFUOE+1 - jzEKwzAQBNUEXKQIBOwifcgTUvkDbt2p9qP0Ev1E31FYkVXOx2FLRRYWi7NnTnZ/z/MxZPY7aguhbZlq - myQafL+ubRINshCwnO0kFqi3HkpwWOf7DkC1RBfvx9slV4ElscqbxBiz9/4nwOBIQjCEUL7FswhwDYAp - JVMiN0oYs/ILiCXRIGHOwVQBoiXsKSgjJdzaBMpQ0g3KEOoG++PcBx9PFJGNjU4vAAAAAElFTkSuQmCC - - - - 205, 22 - - - Tutorials - 312, 22 @@ -1172,6 +1111,38 @@ How PCKs work + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAKdJREFUOE+1 + jzEKwzAQBNUEXKQIBOwifcgTUvkDbt2p9qP0Ev1E31FYkVXOx2FLRRYWi7NnTnZ/z/MxZPY7aguhbZlq + myQafL+ubRINshCwnO0kFqi3HkpwWOf7DkC1RBfvx9slV4ElscqbxBiz9/4nwOBIQjCEUL7FswhwDYAp + JVMiN0oYs/ILiCXRIGHOwVQBoiXsKSgjJdzaBMpQ0g3KEOoG++PcBx9PFJGNjU4vAAAAAElFTkSuQmCC + + + + 205, 22 + + + Tutorials + + + 233, 22 + + + Nobledez (Original Developer) + + + 233, 22 + + + PhoenixARC (Developer) + + + 233, 22 + + + MattNL (Other Developer) + iVBORw0KGgoAAAANSUhEUgAAAgAAAAIBCAYAAAA/JAdfAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAN @@ -1470,24 +1441,6 @@ Support a Developer - - 233, 22 - - - Nobledez (Original Developer) - - - 233, 22 - - - PhoenixARC (Developer) - - - 233, 22 - - - MattNL (Other Developer) - iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO @@ -1944,115 +1897,51 @@ Settings - - StartPage + + + iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAL + DAAACwwBP0AiyAAAAeRJREFUeF7tzjGOIzEMAEH//9N3SaEzwzLH2plAFTZEUq/jOI7jOI5f+beZM8/l + n9s481z+uY0zz+Wf2zjzHP4VeRtnIt/HPyJv40zk+/hH5G2ciXwf/4i8jTOR/467kW/jG5H3cSfybXwj + 8j7uRL6Nb0Tex53It/GNyL9jb+RlxsasWWYs8pw9kZcZG7NmmbHIc/ZEXmZszJplxiLP2RN5mbExa5YZ + izxnT+RlxiK/5VnkZcYiz9kTeZmxyG95FnmZschz9kReZizyW55FXmYs8pw9kZcZi/yWZ5GXGYs8Z0/k + bZyJvMxY5Dl7Im/jTORlxiLP2RN5G2ciLzMWec6eyNs4E3mZschz9kS+zLqPPF9mLPKcPZEvs+4jz5cZ + izxnT+TLrPvI82XGIs/ZE/ky6z7yfJmxyHP2RL7MusiXWRd5zp7Il1kX+TLrIs/ZE/mxfDPynD2RH8s3 + I8/ZE/mxfDPynD2RH8s3I8/ZE/ky6yJfZl3kOXsiX2Zd5Musi/w79kb+mvHIXzMeeR93In/NeOSvGY+8 + jzuRb+MbkfdxJ/JtfCPy33E38jbORL6Pf0TexpnI9/GPyNs4E/k+/hF5G2ciP4d/bePMc/nnNs48l39u + 48xz+ec2zhzHcRzHcVz0ev0HFtq118xXwn0AAAAASUVORK5CYII= + - - MetroFramework.Controls.MetroTabPage, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a + + 60, 20 - - tabControl + + Help - - 0 + + 14, 3 - - Fill + + 0, 6, 60, 0 - - 20, 30 + + 326, 24 - - 0, 0, 0, 0 + + 2 - - 1024, 600 + + MainMenuStrip - - 0 + + menuStrip - - tabControl + + System.Windows.Forms.MenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - PckStudio.Controls.CustomTabControl, PCK-Studio, Version=7.0.0.2, Culture=neutral, PublicKeyToken=null - - + $this - - 2 - - - labelVersion - - - MetroFramework.Controls.MetroLabel, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a - - - StartPage - - - 2 - - - label5 - - - MetroFramework.Controls.MetroLabel, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a - - - StartPage - - - 3 - - - ChangelogRichTextBox - - - System.Windows.Forms.RichTextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - StartPage - - - 4 - - - pckOpen - - - System.Windows.Forms.PictureBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - StartPage - - - 5 - - - 4, 38 - - - 1016, 558 - - - 0 - - - Start Page - - - StartPage - - - MetroFramework.Controls.MetroTabPage, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a - - - tabControl - - + 0 @@ -3165,11 +3054,74 @@ 5 + + 4, 38 + + + 1016, 558 + + + 0 + + + Start Page + + + StartPage + + + MetroFramework.Controls.MetroTabPage, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a + + + tabControl + + + 0 + + + Fill + + + 20, 30 + + + 0, 0, 0, 0 + + + 1024, 600 + + + 0 + + + tabControl + + + PckStudio.Controls.CustomTabControl, PCK-Studio, Version=7.0.0.2, Culture=neutral, PublicKeyToken=null + + + $this + + + 1 + + + None + True - - None + + True + + + 433, 71 + + + 0, 0 + + + 3 label11 @@ -3201,63 +3153,6 @@ MetroFramework.Controls.MetroTabPage, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a - - True - - - True - - - 433, 71 - - - 0, 0 - - - 3 - - - label11 - - - MetroFramework.Controls.MetroLabel, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a - - - editorTab - - - 2 - - - Top, Right - - - True - - - 720, 12 - - - 264, 15 - - - 21 - - - Open/Save as Switch/Vita/PS4/Xbox One PCK - - - LittleEndianCheckBox - - - MetroFramework.Controls.MetroCheckBox, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a - - - $this - - - 0 - True diff --git a/PCK-Studio/PckStudio.csproj b/PCK-Studio/PckStudio.csproj index 3af6f721..3ed7f5c0 100644 --- a/PCK-Studio/PckStudio.csproj +++ b/PCK-Studio/PckStudio.csproj @@ -164,6 +164,7 @@ ContributorsForm.cs + @@ -175,9 +176,13 @@ - + + UserControl + + Form +