mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/PCK-Studio.git
synced 2026-06-06 10:15:18 +00:00
Merge branch main into '3dSkinRenderer'
This commit is contained in:
@@ -1,17 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Drawing;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using OMI.Formats.Languages;
|
||||
using OMI.Formats.Pck;
|
||||
using OMI.Workers;
|
||||
|
||||
using PckStudio.Interfaces;
|
||||
using PckStudio.Internal.Deserializer;
|
||||
using PckStudio.Internal.Serializer;
|
||||
using PckStudio.Internal.Skin;
|
||||
using System.Linq;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace PckStudio.Extensions
|
||||
{
|
||||
@@ -176,26 +178,22 @@ namespace PckStudio.Extensions
|
||||
return asset.Filename.Remove(asset.Filename.Length - (MipMap.Length + 1) - ext.Length) + ext;
|
||||
}
|
||||
|
||||
internal static void DeserializePropertiesFromString(this PckAsset asset, string serializedData)
|
||||
internal static void DeserializeProperties(this PckAsset asset, IEnumerable<string> serializedData)
|
||||
{
|
||||
string[] lines = serializedData.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (string line in lines)
|
||||
IEnumerable<KeyValuePair<string, string>> lines = serializedData
|
||||
.Select(line => line.Split([' '], 2))
|
||||
.Where (keyValue => keyValue.Length == 2)
|
||||
.Select(keyValue => new KeyValuePair<string, string>(keyValue[0].Replace(":", ""), keyValue[1]));
|
||||
foreach (KeyValuePair<string, string> kv in lines)
|
||||
{
|
||||
int idx = line.IndexOf(' ');
|
||||
if (idx == -1 || line.Length - 1 == idx)
|
||||
continue;
|
||||
asset.AddProperty(line.Substring(0, idx).Replace(":", string.Empty), line.Substring(idx + 1));
|
||||
asset.AddProperty(kv);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string SerializePropertiesToString(this PckAsset asset)
|
||||
internal static IEnumerable<string> SerializeProperties(this PckAsset asset, string seperater = ":")
|
||||
{
|
||||
StringBuilder builder = new StringBuilder(asset.PropertyCount * 20);
|
||||
foreach (KeyValuePair<string, string> property in asset.GetProperties())
|
||||
{
|
||||
builder.AppendLine(property.Key + ": " + property.Value);
|
||||
}
|
||||
return builder.ToString();
|
||||
IReadOnlyList<KeyValuePair<string, string>> properties = asset.GetProperties();
|
||||
return properties.Select(property => property.Key + seperater + property.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace PckStudio.Forms.Additional_Popups
|
||||
{
|
||||
public partial class MultiTextPrompt : MetroFramework.Forms.MetroForm
|
||||
{
|
||||
public string[] TextOutput => DialogResult == DialogResult.OK ? PromptTextBox.Lines : Array.Empty<string>();
|
||||
public MultiTextPrompt(string[] list = null)
|
||||
public IEnumerable<string> TextOutput => DialogResult == DialogResult.OK ? PromptTextBox.Lines : Array.Empty<string>();
|
||||
|
||||
public MultiTextPrompt(IEnumerable<string> textLines)
|
||||
{
|
||||
InitializeComponent();
|
||||
PromptTextBox.Lines = list;
|
||||
PromptTextBox.Lines = textLines.ToArray();
|
||||
}
|
||||
|
||||
public MultiTextPrompt()
|
||||
: this(Enumerable.Empty<string>())
|
||||
{
|
||||
}
|
||||
|
||||
private void okBtn_Click(object sender, EventArgs e)
|
||||
|
||||
24
PCK-Studio/Internal/Json/UpdateInformation.cs
Normal file
24
PCK-Studio/Internal/Json/UpdateInformation.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace PckStudio.Internal.Json
|
||||
{
|
||||
internal class UpdateInformation
|
||||
{
|
||||
[JsonProperty("version")]
|
||||
public string Version { get; set; }
|
||||
|
||||
[JsonProperty("url")]
|
||||
public string Url { get; set; }
|
||||
|
||||
[JsonProperty("changelog")]
|
||||
public string Changelog { get; set; }
|
||||
|
||||
[JsonProperty("mandatory")]
|
||||
public bool Mandatory { get; set; }
|
||||
}
|
||||
}
|
||||
62
PCK-Studio/Internal/Updater.cs
Normal file
62
PCK-Studio/Internal/Updater.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
using AutoUpdaterDotNET;
|
||||
using Newtonsoft.Json;
|
||||
using PckStudio.Internal.Json;
|
||||
using PckStudio.Properties;
|
||||
|
||||
namespace PckStudio.Internal
|
||||
{
|
||||
internal static class Updater
|
||||
{
|
||||
private static Uri _appCast;
|
||||
|
||||
internal static void Initialize(Uri appCast)
|
||||
{
|
||||
_appCast = appCast;
|
||||
//AutoUpdater.ClearAppDirectory = true;
|
||||
#if DEBUG
|
||||
AutoUpdater.ReportErrors = true;
|
||||
#endif
|
||||
AutoUpdater.DownloadPath = Application.StartupPath;
|
||||
AutoUpdater.ExecutablePath = "./PCK-Studio.exe";
|
||||
AutoUpdater.TopMost = true;
|
||||
|
||||
string jsonPath = Path.Combine(Environment.CurrentDirectory, "updates.json");
|
||||
AutoUpdater.PersistenceProvider = new JsonFilePersistenceProvider(jsonPath);
|
||||
AutoUpdater.ParseUpdateInfoEvent += AutoUpdaterOnParseUpdateInfoEvent;
|
||||
AutoUpdater.Icon = Resources.ProjectLogo.ToBitmap();
|
||||
|
||||
if (Settings.Default.AutoUpdate)
|
||||
{
|
||||
UpdateToLatest();
|
||||
}
|
||||
}
|
||||
|
||||
internal static void SetOwner(Form owner) => AutoUpdater.SetOwner(owner);
|
||||
|
||||
internal static void UpdateToLatest()
|
||||
{
|
||||
#if NDEBUG
|
||||
string url = $"{_appCast}/main/Version.json";
|
||||
AutoUpdater.Start(url);
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void AutoUpdaterOnParseUpdateInfoEvent(ParseUpdateInfoEventArgs args)
|
||||
{
|
||||
UpdateInformation json = JsonConvert.DeserializeObject<UpdateInformation>(args.RemoteData);
|
||||
args.UpdateInfo = new UpdateInfoEventArgs
|
||||
{
|
||||
CurrentVersion = json.Version,
|
||||
DownloadURL = json.Url,
|
||||
ChangelogURL = json.Changelog,
|
||||
Mandatory = new Mandatory()
|
||||
{
|
||||
Value = json.Mandatory,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -264,16 +264,14 @@ namespace PckStudio
|
||||
|
||||
private void openToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
using (var ofd = new OpenFileDialog())
|
||||
{
|
||||
ofd.CheckFileExists = true;
|
||||
ofd.Filter = "PCK (Minecraft Console Package)|*.pck";
|
||||
if (ofd.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
LoadPckFromFile(ofd.FileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
using var ofd = new OpenFileDialog();
|
||||
ofd.CheckFileExists = true;
|
||||
ofd.Filter = "PCK (Minecraft Console Package)|*.pck";
|
||||
if (ofd.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
LoadPckFromFile(ofd.FileName);
|
||||
}
|
||||
}
|
||||
|
||||
private PckFile OpenPck(string filePath)
|
||||
{
|
||||
@@ -759,7 +757,7 @@ namespace PckStudio
|
||||
File.WriteAllBytes(outFilePath, asset.Data);
|
||||
if (asset.PropertyCount > 0)
|
||||
{
|
||||
File.WriteAllText($"{outFilePath}.txt", asset.SerializePropertiesToString());
|
||||
File.WriteAllLines($"{outFilePath}.txt", asset.SerializeProperties());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -785,27 +783,10 @@ namespace PckStudio
|
||||
|
||||
string selectedFolder = node.FullPath;
|
||||
|
||||
if (IsSubPCKNode(node.FullPath))
|
||||
{
|
||||
GetAllChildNodes(node.Nodes).ForEach(fileNode =>
|
||||
{
|
||||
if (fileNode.TryGetTagData(out PckAsset asset))
|
||||
{
|
||||
extractFolderFile(outPath, asset);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (PckAsset asset in currentPCK.GetAssets())
|
||||
{
|
||||
if (asset.Filename.StartsWith(selectedFolder))
|
||||
{
|
||||
extractFolderFile(outPath, asset);
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (PckAsset asset in currentPCK.GetAssets().Where(asset => asset.Filename.StartsWith(selectedFolder)))
|
||||
{
|
||||
extractFolderFile(outPath, asset);
|
||||
}
|
||||
}
|
||||
|
||||
private void extractToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
@@ -898,7 +879,6 @@ namespace PckStudio
|
||||
string newFileExt = Path.GetExtension(ofd.FileName);
|
||||
asset.SetData(File.ReadAllBytes(ofd.FileName));
|
||||
asset.Filename = asset.Filename.Replace(fileExt, newFileExt);
|
||||
RebuildSubPCK(treeViewMain.SelectedNode.FullPath);
|
||||
wasModified = true;
|
||||
BuildMainTreeView();
|
||||
}
|
||||
@@ -964,7 +944,6 @@ namespace PckStudio
|
||||
node.Remove();
|
||||
wasModified = true;
|
||||
}
|
||||
RebuildSubPCK(path);
|
||||
}
|
||||
|
||||
private void renameFileToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
@@ -1003,7 +982,6 @@ namespace PckStudio
|
||||
}
|
||||
}
|
||||
wasModified = true;
|
||||
RebuildSubPCK(path);
|
||||
BuildMainTreeView();
|
||||
}
|
||||
}
|
||||
@@ -1124,120 +1102,6 @@ namespace PckStudio
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete()]
|
||||
bool IsSubPCKNode(string nodePath, string extention = ".pck")
|
||||
{
|
||||
// written by miku, implemented and modified by MattNL
|
||||
if (nodePath.EndsWith(extention))
|
||||
return false;
|
||||
|
||||
string[] subpaths = nodePath.Split('/');
|
||||
|
||||
bool isSubFile = subpaths.Any(s => Path.GetExtension(s).Equals(extention));
|
||||
|
||||
Debug.WriteLineIf(isSubFile, $"{nodePath} is a Sub-PCK File", category: nameof(IsSubPCKNode));
|
||||
|
||||
return isSubFile;
|
||||
}
|
||||
|
||||
List<TreeNode> GetAllChildNodes(TreeNodeCollection root)
|
||||
{
|
||||
List<TreeNode> childNodes = new List<TreeNode>();
|
||||
foreach (TreeNode node in root)
|
||||
{
|
||||
childNodes.Add(node);
|
||||
if (node.Nodes.Count > 0)
|
||||
{
|
||||
childNodes.AddRange(GetAllChildNodes(node.Nodes));
|
||||
}
|
||||
}
|
||||
return childNodes;
|
||||
}
|
||||
|
||||
[Obsolete()]
|
||||
TreeNode GetSubPCK(string childPath)
|
||||
{
|
||||
string parentPath = childPath.Replace('\\', '/');
|
||||
Debug.WriteLine(parentPath);
|
||||
string[] s = parentPath.Split('/');
|
||||
Debug.WriteLine(s.Length);
|
||||
foreach (string node in s)
|
||||
{
|
||||
TreeNode parent = treeViewMain.Nodes.Find(node, true)[0];
|
||||
if (parent.TryGetTagData(out PckAsset asset) &&
|
||||
(asset.Type is PckAssetType.TexturePackInfoFile ||
|
||||
asset.Type is PckAssetType.SkinDataFile))
|
||||
return parent;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
[Obsolete()]
|
||||
void RebuildSubPCK(string childPath)
|
||||
{
|
||||
// Support for if a file is edited within a nested PCK File (AKA SubPCK)
|
||||
|
||||
if (!IsSubPCKNode(childPath))
|
||||
return;
|
||||
|
||||
TreeNode parent = GetSubPCK(childPath);
|
||||
Debug.WriteLine(parent.Name);
|
||||
if (parent == null)
|
||||
return;
|
||||
|
||||
PckAsset parentAsset = parent.Tag as PckAsset;
|
||||
PckFile parentAssetPck =
|
||||
new PckFileReader(
|
||||
LittleEndianCheckBox.Checked ?
|
||||
OMI.Endianness.LittleEndian :
|
||||
OMI.Endianness.BigEndian
|
||||
).FromStream(new MemoryStream(parentAsset.Data));
|
||||
|
||||
if (parentAsset.Type is PckAssetType.TexturePackInfoFile || parentAsset.Type is PckAssetType.SkinDataFile)
|
||||
{
|
||||
Debug.WriteLine("Rebuilding " + parentAsset.Filename);
|
||||
PckFile newPCKFile = new PckFile(3, parentAsset.Type is PckAssetType.SkinDataFile);
|
||||
|
||||
bool hasSkinsFolder = false;
|
||||
|
||||
// add original pck files to prevent data loss
|
||||
foreach (PckAsset asset in parentAssetPck.GetAssets())
|
||||
{
|
||||
PckAsset newAsset = newPCKFile.CreateNewAsset(asset.Filename, asset.Type);
|
||||
// check for skins folder so files are placed consistently in final pck
|
||||
if (asset.Filename.StartsWith("Skins/") && parentAsset.Type is PckAssetType.SkinDataFile)
|
||||
hasSkinsFolder = true;
|
||||
foreach (KeyValuePair<string, string> prop in asset.GetProperties())
|
||||
newAsset.AddProperty(prop);
|
||||
newAsset.SetData(asset.Data);
|
||||
}
|
||||
|
||||
foreach (TreeNode node in GetAllChildNodes(parent.Nodes))
|
||||
{
|
||||
if (node.Tag is PckAsset nodeAsset)
|
||||
{
|
||||
PckAsset newAsset = newPCKFile.CreateNewAsset(
|
||||
(hasSkinsFolder ? "Skins/" : String.Empty)
|
||||
+ nodeAsset.Filename.Replace(parentAsset.Filename + "/", String.Empty), nodeAsset.Type);
|
||||
foreach (KeyValuePair<string, string> prop in nodeAsset.GetProperties())
|
||||
newAsset.AddProperty(prop);
|
||||
newAsset.SetData(nodeAsset.Data);
|
||||
}
|
||||
}
|
||||
|
||||
parentAsset.SetData(new PckFileWriter(newPCKFile, LittleEndianCheckBox.Checked ? OMI.Endianness.LittleEndian : OMI.Endianness.BigEndian));
|
||||
parent.Tag = parentAsset;
|
||||
|
||||
// erase hidden sub-pck nodes to prevent duplication
|
||||
parent.Nodes.Clear();
|
||||
|
||||
BuildMainTreeView();
|
||||
|
||||
MessageBox.Show(this, $"Files added successfully to {parentAsset.Filename}");
|
||||
}
|
||||
}
|
||||
|
||||
private void treeViewMain_DoubleClick(object sender, EventArgs e)
|
||||
{
|
||||
if (treeViewMain.SelectedNode.TryGetTagData(out PckAsset asset))
|
||||
@@ -1276,7 +1140,6 @@ namespace PckStudio
|
||||
if (diag.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
asset.SetProperty(asset.GetPropertyIndex(property), new KeyValuePair<string, string>("ANIM", diag.ResultAnim.ToString()));
|
||||
RebuildSubPCK(treeViewMain.SelectedNode.FullPath);
|
||||
ReloadMetaTreeView();
|
||||
wasModified = true;
|
||||
}
|
||||
@@ -1293,11 +1156,10 @@ namespace PckStudio
|
||||
case "BOX" when asset.Type == PckAssetType.SkinFile:
|
||||
try
|
||||
{
|
||||
using BoxEditor diag = new BoxEditor(property.Value, IsSubPCKNode(treeViewMain.SelectedNode.FullPath));
|
||||
using BoxEditor diag = new BoxEditor(property.Value, false);
|
||||
if (diag.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
asset.SetProperty(asset.GetPropertyIndex(property), new KeyValuePair<string, string>("BOX", diag.Result.ToString()));
|
||||
RebuildSubPCK(treeViewMain.SelectedNode.FullPath);
|
||||
ReloadMetaTreeView();
|
||||
wasModified = true;
|
||||
}
|
||||
@@ -1321,7 +1183,6 @@ namespace PckStudio
|
||||
if (addProperty.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
asset.SetProperty(asset.GetPropertyIndex(property), addProperty.Property);
|
||||
RebuildSubPCK(treeViewMain.SelectedNode.FullPath);
|
||||
ReloadMetaTreeView();
|
||||
wasModified = true;
|
||||
}
|
||||
@@ -1358,7 +1219,7 @@ namespace PckStudio
|
||||
newNode.ImageIndex = node.ImageIndex;
|
||||
newNode.SelectedImageIndex = node.SelectedImageIndex;
|
||||
|
||||
if (GetAllChildNodes(treeViewMain.Nodes).Find(n => n.FullPath == diag.NewText) != null)
|
||||
if (GetAllChildNodes(treeViewMain.Nodes).FirstOrDefault(n => n.FullPath == diag.NewText) is not null)
|
||||
{
|
||||
MessageBox.Show(
|
||||
this,
|
||||
@@ -1368,17 +1229,10 @@ namespace PckStudio
|
||||
return;
|
||||
}
|
||||
|
||||
// adds generated file node
|
||||
if (node.Parent == null)
|
||||
treeViewMain.Nodes.Insert(node.Index + 1, newNode);
|
||||
// adds generated file node to selected folder
|
||||
else
|
||||
node.Parent.Nodes.Insert(node.Index + 1, newNode);
|
||||
TreeNodeCollection nodeCollection = node.Parent?.Nodes ?? treeViewMain.Nodes;
|
||||
nodeCollection.Insert(node.Index + 1, newNode);
|
||||
|
||||
if (!IsSubPCKNode(node.FullPath))
|
||||
currentPCK.InsertAsset(node.Index + 1, newFile);
|
||||
else
|
||||
RebuildSubPCK(node.FullPath);
|
||||
currentPCK.InsertAsset(node.Index + 1, newFile);
|
||||
BuildMainTreeView();
|
||||
wasModified = true;
|
||||
}
|
||||
@@ -1392,7 +1246,6 @@ namespace PckStudio
|
||||
asset.RemoveProperty(property))
|
||||
{
|
||||
treeMeta.SelectedNode.Remove();
|
||||
RebuildSubPCK(treeViewMain.SelectedNode.FullPath);
|
||||
wasModified = true;
|
||||
}
|
||||
}
|
||||
@@ -1419,7 +1272,6 @@ namespace PckStudio
|
||||
if (addProperty.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
asset.AddProperty(addProperty.Property);
|
||||
RebuildSubPCK(treeViewMain.SelectedNode.FullPath);
|
||||
ReloadMetaTreeView();
|
||||
wasModified = true;
|
||||
}
|
||||
@@ -1536,7 +1388,7 @@ namespace PckStudio
|
||||
}
|
||||
else
|
||||
{
|
||||
List<PckAsset> pckFiles = GetEndingNodes(draggedNode.Nodes).Where(t => t.IsTagOfType<PckAsset>()).Select(t => t.Tag as PckAsset).ToList();
|
||||
IEnumerable<PckAsset> pckFiles = GetAllChildNodes(draggedNode.Nodes).Where(t => t.IsTagOfType<PckAsset>()).Select(t => t.Tag as PckAsset);
|
||||
string oldPath = draggedNode.FullPath;
|
||||
string newPath = Path.Combine(isTargetPckFile ? Path.GetDirectoryName(targetNode.FullPath) : targetNode.FullPath, draggedNode.Text).Replace('\\', '/');
|
||||
foreach (PckAsset pckFile in pckFiles)
|
||||
@@ -1548,20 +1400,17 @@ namespace PckStudio
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<TreeNode> GetEndingNodes(TreeNodeCollection collection)
|
||||
IEnumerable<TreeNode> GetAllChildNodes(TreeNodeCollection root)
|
||||
{
|
||||
List<TreeNode> trailingNodes = new List<TreeNode>(collection.Count);
|
||||
foreach (TreeNode node in collection)
|
||||
{
|
||||
if (node.Nodes.Count > 0)
|
||||
{
|
||||
trailingNodes.AddRange(GetEndingNodes(node.Nodes));
|
||||
continue;
|
||||
}
|
||||
trailingNodes.Add(node);
|
||||
}
|
||||
return trailingNodes;
|
||||
}
|
||||
List<TreeNode> childNodes = new List<TreeNode>(root.Count);
|
||||
foreach (TreeNode childNode in root)
|
||||
{
|
||||
childNodes.Add(childNode);
|
||||
childNodes.AddRange(GetAllChildNodes(childNode.Nodes));
|
||||
}
|
||||
return childNodes;
|
||||
}
|
||||
|
||||
|
||||
private void ImportFiles(string[] files)
|
||||
{
|
||||
@@ -1574,14 +1423,14 @@ namespace PckStudio
|
||||
|
||||
if (currentPCK.Contains(addFile.Filepath, addFile.Filetype))
|
||||
{
|
||||
MessageBox.Show(this, $"'{addFile.Filepath}' of type {addFile.Filetype} already exists.", "Import failed", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
MessageBox.Show(this, $"'{addFile.Filepath}' of type {addFile.Filetype} already exists.\nSkiping file.", "File already exists", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1);
|
||||
continue;
|
||||
}
|
||||
PckAsset importedAsset = currentPCK.CreateNewAsset(addFile.Filepath, addFile.Filetype, () => File.ReadAllBytes(filepath));
|
||||
string propertyFile = filepath + ".txt";
|
||||
if (File.Exists(propertyFile))
|
||||
{
|
||||
importedAsset.DeserializePropertiesFromString(File.ReadAllText(propertyFile));
|
||||
importedAsset.DeserializeProperties(File.ReadAllLines(propertyFile));
|
||||
}
|
||||
addedCount++;
|
||||
|
||||
@@ -1743,16 +1592,19 @@ namespace PckStudio
|
||||
e.CancelEdit = true;
|
||||
}
|
||||
|
||||
[Obsolete("Move this")]
|
||||
public string GetDataPath()
|
||||
{
|
||||
return Path.Combine(Path.GetDirectoryName(saveLocation), "Data");
|
||||
}
|
||||
|
||||
[Obsolete("Move this")]
|
||||
public bool HasDataFolder()
|
||||
{
|
||||
return Directory.Exists(GetDataPath());
|
||||
}
|
||||
|
||||
[Obsolete("Move this")]
|
||||
public bool CreateDataFolder()
|
||||
{
|
||||
if (!HasDataFolder())
|
||||
@@ -1771,49 +1623,7 @@ namespace PckStudio
|
||||
if (e.KeyData == Keys.Delete)
|
||||
deleteEntryToolStripMenuItem_Click(sender, e);
|
||||
}
|
||||
|
||||
private void importExtractedSkinsFolder(object sender, EventArgs e)
|
||||
{
|
||||
using FolderBrowserDialog contents = new FolderBrowserDialog();
|
||||
if (contents.ShowDialog(this) == DialogResult.OK && Directory.Exists(contents.SelectedPath))
|
||||
{
|
||||
string filepath = treeViewMain.SelectedNode?.FullPath ?? "";
|
||||
if (treeViewMain.SelectedNode is not null && treeViewMain.SelectedNode.IsTagOfType<PckAsset>())
|
||||
filepath = treeViewMain.SelectedNode.Parent?.FullPath ?? "";
|
||||
|
||||
foreach (var fullfilename in Directory.GetFiles(contents.SelectedPath, "dlc*.png"))
|
||||
{
|
||||
string filename = Path.GetFileName(fullfilename);
|
||||
// only accept skin or cape named files
|
||||
if (!filename.StartsWith("dlcskin") && !filename.StartsWith("dlccape"))
|
||||
continue;
|
||||
// sets file type based on wether its a cape or skin
|
||||
PckAssetType pckfiletype = filename.StartsWith("dlccape", StringComparison.OrdinalIgnoreCase)
|
||||
? PckAssetType.CapeFile
|
||||
: PckAssetType.SkinFile;
|
||||
string pckfilepath = Path.Combine(filepath, filename);
|
||||
|
||||
if (currentPCK.Contains(pckfilepath, pckfiletype))
|
||||
{
|
||||
Trace.TraceInformation("[{0}] {1} already exists.", nameof(importExtractedSkinsFolder), pckfilepath);
|
||||
continue;
|
||||
}
|
||||
|
||||
PckAsset newAsset = currentPCK.CreateNewAsset(pckfilepath, pckfiletype);
|
||||
byte[] filedata = File.ReadAllBytes(fullfilename);
|
||||
newAsset.SetData(filedata);
|
||||
|
||||
if (File.Exists(fullfilename + ".txt"))
|
||||
{
|
||||
string propertiesFileContent = File.ReadAllText(fullfilename + ".txt");
|
||||
newAsset.DeserializePropertiesFromString(propertiesFileContent);
|
||||
}
|
||||
}
|
||||
BuildMainTreeView();
|
||||
wasModified = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private bool TryGetLocFile(out LOCFile locFile)
|
||||
{
|
||||
if (!currentPCK.TryGetAsset("localisation.loc", PckAssetType.LocalisationFile, out PckAsset locAsset) &&
|
||||
@@ -1856,6 +1666,47 @@ namespace PckStudio
|
||||
return false;
|
||||
}
|
||||
|
||||
private void importExtractedSkinsFolder(object sender, EventArgs e)
|
||||
{
|
||||
OpenFolderDialog contents = new OpenFolderDialog();
|
||||
if (contents.ShowDialog(Handle) == true && Directory.Exists(contents.ResultPath))
|
||||
{
|
||||
string filepath = treeViewMain.SelectedNode?.FullPath ?? "";
|
||||
if (treeViewMain.SelectedNode is not null && treeViewMain.SelectedNode.IsTagOfType<PckAsset>())
|
||||
filepath = treeViewMain.SelectedNode.Parent?.FullPath ?? "";
|
||||
|
||||
foreach (var fullfilename in Directory.GetFiles(contents.ResultPath, "dlc*.png"))
|
||||
{
|
||||
string filename = Path.GetFileName(fullfilename);
|
||||
// only accept skin or cape named files
|
||||
if (!filename.StartsWith("dlcskin") && !filename.StartsWith("dlccape"))
|
||||
continue;
|
||||
// sets file type based on wether its a cape or skin
|
||||
PckAssetType pckfiletype = filename.StartsWith("dlccape", StringComparison.OrdinalIgnoreCase)
|
||||
? PckAssetType.CapeFile
|
||||
: PckAssetType.SkinFile;
|
||||
string pckfilepath = Path.Combine(filepath, filename);
|
||||
|
||||
if (currentPCK.Contains(pckfilepath, pckfiletype))
|
||||
{
|
||||
Trace.TraceInformation("[{0}] {1} already exists.", nameof(importExtractedSkinsFolder), pckfilepath);
|
||||
continue;
|
||||
}
|
||||
|
||||
PckAsset newAsset = currentPCK.CreateNewAsset(pckfilepath, pckfiletype);
|
||||
byte[] filedata = File.ReadAllBytes(fullfilename);
|
||||
newAsset.SetData(filedata);
|
||||
|
||||
if (File.Exists(fullfilename + ".txt"))
|
||||
{
|
||||
string[] propertiesFileContent = File.ReadAllLines(fullfilename + ".txt");
|
||||
newAsset.DeserializeProperties(propertiesFileContent);
|
||||
}
|
||||
}
|
||||
BuildMainTreeView();
|
||||
wasModified = true;
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("Refactor or remove this")]
|
||||
private void importSkinToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
@@ -1881,13 +1732,14 @@ namespace PckStudio
|
||||
string propertyFile = contents.FileName + ".txt";
|
||||
if (File.Exists(propertyFile))
|
||||
{
|
||||
string txtProperties = File.ReadAllText(propertyFile);
|
||||
importSkinAsset.DeserializePropertiesFromString(txtProperties);
|
||||
|
||||
// Because extracting/exporting an assest doesn't export
|
||||
// the actual loc value we just get an undefined loc key
|
||||
// - Miku
|
||||
importSkinAsset.RemoveProperty("DISPLAYNAMEID");
|
||||
string[] txtProperties = File.ReadAllLines(propertyFile);
|
||||
importSkinAsset.DeserializeProperties(txtProperties);
|
||||
|
||||
// Because extracting/exporting an assest doesn't export
|
||||
// the actual loc value we just get an undefined loc key.
|
||||
// That's why why remove them after deserializing.
|
||||
// - Miku
|
||||
importSkinAsset.RemoveProperty("DISPLAYNAMEID");
|
||||
importSkinAsset.RemoveProperty("THEMENAMEID");
|
||||
BuildMainTreeView();
|
||||
wasModified = true;
|
||||
@@ -2015,13 +1867,9 @@ namespace PckStudio
|
||||
{
|
||||
pckOpen.Image = Resources.pckDrop;
|
||||
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop) ?? Array.Empty<string>();
|
||||
foreach (string file in files)
|
||||
{
|
||||
string ext = Path.GetExtension(file);
|
||||
if (ext.Equals(".pck", StringComparison.CurrentCultureIgnoreCase))
|
||||
e.Effect = DragDropEffects.Copy;
|
||||
return;
|
||||
}
|
||||
e.Effect = files.Any(file => Path.GetExtension(file).Equals(".pck", StringComparison.CurrentCultureIgnoreCase))
|
||||
? DragDropEffects.Copy
|
||||
: DragDropEffects.None;
|
||||
}
|
||||
|
||||
private void OpenPck_DragDrop(object sender, DragEventArgs e)
|
||||
@@ -2067,23 +1915,23 @@ namespace PckStudio
|
||||
break;
|
||||
case PckAssetType.TexturePackInfoFile:
|
||||
goto default;
|
||||
node.ImageIndex = 4;
|
||||
node.SelectedImageIndex = 4;
|
||||
break;
|
||||
//node.ImageIndex = 4;
|
||||
//node.SelectedImageIndex = 4;
|
||||
//break;
|
||||
case PckAssetType.ColourTableFile:
|
||||
node.ImageIndex = 6;
|
||||
node.SelectedImageIndex = 6;
|
||||
break;
|
||||
case PckAssetType.ModelsFile:
|
||||
goto default;
|
||||
node.ImageIndex = 8;
|
||||
node.SelectedImageIndex = 8;
|
||||
break;
|
||||
//node.ImageIndex = 8;
|
||||
//node.SelectedImageIndex = 8;
|
||||
//break;
|
||||
case PckAssetType.SkinDataFile:
|
||||
goto default;
|
||||
node.ImageIndex = 7;
|
||||
node.SelectedImageIndex = 7;
|
||||
break;
|
||||
//node.ImageIndex = 7;
|
||||
//node.SelectedImageIndex = 7;
|
||||
//break;
|
||||
case PckAssetType.GameRulesFile:
|
||||
node.ImageIndex = 9;
|
||||
node.SelectedImageIndex = 9;
|
||||
@@ -2130,11 +1978,9 @@ namespace PckStudio
|
||||
Debug.WriteLine($"Setting {asset.Type} to {type}");
|
||||
asset.Type = type;
|
||||
SetNodeIcon(treeViewMain.SelectedNode, type);
|
||||
RebuildSubPCK(treeViewMain.SelectedNode.FullPath);
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete()]
|
||||
private void addTextureToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
using OpenFileDialog fileDialog = new OpenFileDialog();
|
||||
@@ -2260,23 +2106,14 @@ namespace PckStudio
|
||||
{
|
||||
if (treeViewMain.SelectedNode.TryGetTagData(out PckAsset asset))
|
||||
{
|
||||
using (var input = new MultiTextPrompt())
|
||||
{
|
||||
if (input.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
foreach (string line in input.TextOutput)
|
||||
{
|
||||
int idx = line.IndexOf(' ');
|
||||
if (idx == -1 || line.Length - 1 == idx)
|
||||
continue;
|
||||
asset.AddProperty(line.Substring(0, idx), line.Substring(idx + 1));
|
||||
}
|
||||
ReloadMetaTreeView();
|
||||
RebuildSubPCK(treeViewMain.SelectedNode.FullPath);
|
||||
wasModified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
using var input = new MultiTextPrompt();
|
||||
if (input.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
asset.DeserializeProperties(input.TextOutput);
|
||||
ReloadMetaTreeView();
|
||||
wasModified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void correctSkinDecimalsToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
@@ -2290,7 +2127,6 @@ namespace PckStudio
|
||||
asset.SetProperty(asset.GetPropertyIndex(p), new KeyValuePair<string, string>(p.Key, p.Value.Replace(',', '.')));
|
||||
}
|
||||
ReloadMetaTreeView();
|
||||
RebuildSubPCK(treeViewMain.SelectedNode.FullPath);
|
||||
wasModified = true;
|
||||
}
|
||||
}
|
||||
@@ -2313,21 +2149,14 @@ namespace PckStudio
|
||||
{
|
||||
if (treeViewMain.SelectedNode.TryGetTagData(out PckAsset asset))
|
||||
{
|
||||
string[] props = asset.GetProperties().Select(p => p.Key + " " + p.Value).ToArray();
|
||||
IEnumerable<string> props = asset.SerializeProperties(seperater:" ");
|
||||
using (var input = new MultiTextPrompt(props))
|
||||
{
|
||||
if (input.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
asset.ClearProperties();
|
||||
foreach (string line in input.TextOutput)
|
||||
{
|
||||
int idx = line.IndexOf(' ');
|
||||
if (idx == -1 || line.Length - 1 == idx)
|
||||
continue;
|
||||
asset.AddProperty(line.Substring(0, idx).Replace(":", string.Empty), line.Substring(idx + 1));
|
||||
}
|
||||
asset.DeserializeProperties(input.TextOutput);
|
||||
ReloadMetaTreeView();
|
||||
RebuildSubPCK(treeViewMain.SelectedNode.FullPath);
|
||||
wasModified = true;
|
||||
}
|
||||
}
|
||||
@@ -2354,8 +2183,6 @@ namespace PckStudio
|
||||
}
|
||||
PckAsset asset = currentPCK.CreateNewAsset(diag.Filepath, diag.Filetype, () => File.ReadAllBytes(ofd.FileName));
|
||||
|
||||
RebuildSubPCK(treeViewMain.SelectedNode.FullPath);
|
||||
|
||||
BuildMainTreeView();
|
||||
wasModified = true;
|
||||
}
|
||||
@@ -2451,11 +2278,10 @@ namespace PckStudio
|
||||
{
|
||||
if (treeViewMain.SelectedNode is TreeNode t && t.Tag is PckAsset asset)
|
||||
{
|
||||
using BoxEditor diag = new BoxEditor(SkinBOX.Empty, IsSubPCKNode(treeViewMain.SelectedNode.FullPath));
|
||||
using BoxEditor diag = new BoxEditor(SkinBOX.Empty, false);
|
||||
if (diag.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
asset.AddProperty("BOX", diag.Result);
|
||||
RebuildSubPCK(treeViewMain.SelectedNode.FullPath);
|
||||
ReloadMetaTreeView();
|
||||
wasModified = true;
|
||||
}
|
||||
@@ -2471,7 +2297,6 @@ namespace PckStudio
|
||||
if (diag.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
asset.AddProperty("ANIM", diag.ResultAnim);
|
||||
RebuildSubPCK(treeViewMain.SelectedNode.FullPath);
|
||||
ReloadMetaTreeView();
|
||||
wasModified = true;
|
||||
}
|
||||
@@ -2481,7 +2306,7 @@ namespace PckStudio
|
||||
|
||||
private void checkForUpdatesToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
Program.UpdateToLatest();
|
||||
Updater.UpdateToLatest();
|
||||
}
|
||||
|
||||
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
@@ -2522,6 +2347,7 @@ namespace PckStudio
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
@@ -45,6 +45,8 @@
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<NoWarn>CS0618</NoWarn>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
@@ -175,6 +177,7 @@
|
||||
<Compile Include="Internal\ModelPartSpecifics.cs" />
|
||||
<Compile Include="Internal\Json\JsonModelMetaData.cs" />
|
||||
<Compile Include="Internal\NamedTexture.cs" />
|
||||
<Compile Include="Internal\Json\UpdateInformation.cs" />
|
||||
<Compile Include="Internal\Serializer\AnimationSerializer.cs" />
|
||||
<Compile Include="Internal\Deserializer\AnimationDeserializer.cs" />
|
||||
<Compile Include="Interfaces\IPckAssetDeserializer.cs" />
|
||||
@@ -192,6 +195,7 @@
|
||||
<Compile Include="Internal\Serializer\ImageSerializer.cs" />
|
||||
<Compile Include="Internal\Skin\SkinAnimFlag.cs" />
|
||||
<Compile Include="Internal\Skin\SkinAnimMask.cs" />
|
||||
<Compile Include="Internal\Updater.cs" />
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
|
||||
@@ -31,74 +31,18 @@ namespace PckStudio
|
||||
[STAThread]
|
||||
static void Main(string[] args)
|
||||
{
|
||||
AutoUpdater.SetOwner(MainInstance);
|
||||
//AutoUpdater.ClearAppDirectory = true;
|
||||
#if DEBUG
|
||||
AutoUpdater.ReportErrors = true;
|
||||
#endif
|
||||
AutoUpdater.DownloadPath = Application.StartupPath;
|
||||
AutoUpdater.ExecutablePath = "./PCK-Studio.exe";
|
||||
AutoUpdater.TopMost = true;
|
||||
|
||||
string jsonPath = Path.Combine(Environment.CurrentDirectory, "updates.json");
|
||||
AutoUpdater.PersistenceProvider = new JsonFilePersistenceProvider(jsonPath);
|
||||
AutoUpdater.ParseUpdateInfoEvent += AutoUpdaterOnParseUpdateInfoEvent;
|
||||
AutoUpdater.Icon = Resources.ProjectLogo.ToBitmap();
|
||||
|
||||
if (Settings.Default.AutoUpdate)
|
||||
{
|
||||
UpdateToLatest();
|
||||
}
|
||||
Updater.Initialize(RawProjectUrl);
|
||||
|
||||
ApplicationScope.Initialize();
|
||||
Trace.TraceInformation("Startup");
|
||||
RPC.Initialize();
|
||||
MainInstance = new MainForm();
|
||||
Updater.SetOwner(MainInstance);
|
||||
if (args.Length > 0 && File.Exists(args[0]) && args[0].EndsWith(".pck"))
|
||||
MainInstance.InitPckFromFile(args[0]);
|
||||
Application.ApplicationExit += (sender, e) => { RPC.Deinitialize(); };
|
||||
MainInstance.FocusMe();
|
||||
Application.Run(MainInstance);
|
||||
}
|
||||
|
||||
|
||||
internal static void UpdateToLatest()
|
||||
{
|
||||
#if NDEBUG
|
||||
string url = $"{RawProjectUrl}/main/Version.json";
|
||||
AutoUpdater.Start(url);
|
||||
#endif
|
||||
}
|
||||
|
||||
class UpdateInfo
|
||||
{
|
||||
[JsonProperty("version")]
|
||||
public string Version { get; set; }
|
||||
|
||||
[JsonProperty("url")]
|
||||
public string Url { get; set; }
|
||||
|
||||
[JsonProperty("changelog")]
|
||||
public string Changelog { get; set; }
|
||||
|
||||
[JsonProperty("mandatory")]
|
||||
public bool Mandatory { get; set; }
|
||||
}
|
||||
|
||||
private static void AutoUpdaterOnParseUpdateInfoEvent(ParseUpdateInfoEventArgs args)
|
||||
{
|
||||
UpdateInfo json = JsonConvert.DeserializeObject<UpdateInfo>(args.RemoteData);
|
||||
args.UpdateInfo = new UpdateInfoEventArgs
|
||||
{
|
||||
CurrentVersion = json.Version,
|
||||
DownloadURL = json.Url,
|
||||
ChangelogURL = json.Changelog,
|
||||
Mandatory = new Mandatory()
|
||||
{
|
||||
Value = json.Mandatory,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
2
Vendor/OMI-Lib
vendored
2
Vendor/OMI-Lib
vendored
Submodule Vendor/OMI-Lib updated: 02d37596d0...8da4606797
Reference in New Issue
Block a user