CodeWalker/Project/Panels/EditProjectManifestPanel.cs

320 lines
13 KiB
C#

using CodeWalker.GameFiles;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
using WeifenLuo.WinFormsUI.Docking;
namespace CodeWalker.Project.Panels
{
public partial class EditProjectManifestPanel : ProjectPanel
{
public ProjectForm ProjectForm { get; set; }
public ProjectFile CurrentProjectFile { get; set; }
public EditProjectManifestPanel(ProjectForm projectForm)
{
ProjectForm = projectForm;
InitializeComponent();
Tag = "_manifest.ymf";
}
public override void SetTheme(ThemeBase theme)
{
base.SetTheme(theme);
var txtback = SystemColors.Window;
var indback = Color.WhiteSmoke;
if (theme is VS2015DarkTheme)
{
txtback = theme.ColorPalette.MainWindowActive.Background;
indback = theme.ColorPalette.MainWindowActive.Background;
}
ProjectManifestTextBox.BackColor = txtback;
ProjectManifestTextBox.IndentBackColor = indback;
}
public void SetProject(ProjectFile project)
{
//TODO: include _manifest.ymf in project and load/save
CurrentProjectFile = project;
GenerateProjectManifest();
}
private void GenerateProjectManifest()
{
var sb = new StringBuilder();
var mapdeps = new Dictionary<string, YtypFile>();
var typdeps = new Dictionary<string, Dictionary<string, YtypFile>>();
var interiors = new List<string>();
sb.AppendLine("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>");
sb.AppendLine("<CPackFileMetaData>");
sb.AppendLine(" <MapDataGroups/>");
sb.AppendLine(" <HDTxdBindingArray/>");
sb.AppendLine(" <imapDependencies/>");
var getYtypName = new Func<YtypFile, string>((ytyp) =>
{
var ytypname = ytyp?.RpfFileEntry?.NameLower;
if (ytyp != null)
{
if (string.IsNullOrEmpty(ytypname))
{
ytypname = ytyp.RpfFileEntry?.Name?.ToLowerInvariant();
if (ytypname == null) ytypname = "";
}
if (ytypname.EndsWith(".ytyp"))
{
ytypname = ytypname.Substring(0, ytypname.Length - 5);
}
}
return ytypname;
});
if (CurrentProjectFile != null)
{
if (CurrentProjectFile.YmapFiles.Count > 0)
{
sb.AppendLine(" <imapDependencies_2>");
foreach (var ymap in CurrentProjectFile.YmapFiles)
{
var ymapname = ymap.RpfFileEntry?.NameLower;
if (string.IsNullOrEmpty(ymapname))
{
ymapname = ymap.Name.ToLowerInvariant();
}
if (ymapname.EndsWith(".ymap"))
{
ymapname = ymapname.Substring(0, ymapname.Length - 5);
}
mapdeps.Clear();
bool ismilo = false;
if (ymap.AllEntities != null)
{
foreach (var ent in ymap.AllEntities)
{
var ytyp = ent.Archetype?.Ytyp;
var ytypname = getYtypName(ytyp);
if (ytyp != null)
{
mapdeps[ytypname] = ytyp;
}
if (ent.IsMlo)
{
ismilo = true;
if (ent.MloInstance?.Entities != null)
{
Dictionary<string, YtypFile> typdepdict;
if (!typdeps.TryGetValue(ytypname, out typdepdict))
{
typdepdict = new Dictionary<string, YtypFile>();
typdeps[ytypname] = typdepdict;
}
foreach (var ient in ent.MloInstance.Entities)
{
var iytyp = ient.Archetype?.Ytyp;
var iytypname = getYtypName(iytyp);
if ((iytyp != null) && (iytypname != ytypname))
{
typdepdict[iytypname] = iytyp;
}
}
}
}
}
}
if (ymap.GrassInstanceBatches != null)
{
foreach (var batch in ymap.GrassInstanceBatches)
{
var ytyp = batch.Archetype?.Ytyp;
var ytypname = getYtypName(ytyp);
if (ytyp != null)
{
mapdeps[ytypname] = ytyp;
}
}
}
sb.AppendLine(" <Item>");
sb.AppendLine(" <imapName>" + ymapname + "</imapName>");
if (ismilo)
{
sb.AppendLine(" <manifestFlags>INTERIOR_DATA</manifestFlags>");
}
else
{
sb.AppendLine(" <manifestFlags/>");
}
sb.AppendLine(" <itypDepArray>");
foreach (var kvp in mapdeps)
{
sb.AppendLine(" <Item>" + kvp.Key + "</Item>");
}
sb.AppendLine(" </itypDepArray>");
sb.AppendLine(" </Item>");
}
sb.AppendLine(" </imapDependencies_2>");
}
else
{
sb.AppendLine(" <imapDependencies_2/>");
}
if ((CurrentProjectFile.YtypFiles.Count > 0) && (ProjectForm?.GameFileCache != null))
{
foreach (var ytyp in CurrentProjectFile.YtypFiles)
{
var ytypname = getYtypName(ytyp);
foreach (var archm in ytyp.AllArchetypes)
{
var mloa = archm as MloArchetype;
if (mloa != null)
{
interiors.Add(mloa.Name);
Dictionary<string, YtypFile> typdepdict;
if (!typdeps.TryGetValue(ytypname, out typdepdict))
{
typdepdict = new Dictionary<string, YtypFile>();
typdeps[ytypname] = typdepdict;
}
if (mloa.entities != null)
{
foreach (var ent in mloa.entities)
{
var archname = ent._Data.archetypeName;
var arch = ProjectForm.GameFileCache.GetArchetype(archname);
var iytyp = arch?.Ytyp;
var iytypname = getYtypName(iytyp);
if ((iytyp != null) && (iytypname != ytypname))
{
typdepdict[iytypname] = iytyp;
}
}
}
if (mloa.entitySets != null)
{
foreach (var entset in mloa.entitySets)
{
if (entset.Entities != null)
{
foreach (var ent in entset.Entities)
{
var archname = ent._Data.archetypeName;
var arch = ProjectForm.GameFileCache.GetArchetype(archname);
var iytyp = arch?.Ytyp;
var iytypname = getYtypName(iytyp);
if ((iytyp != null) && (iytypname != ytypname))
{
typdepdict[iytypname] = iytyp;
}
}
}
}
}
}
}
}
}
}
if (typdeps.Count > 0)
{
sb.AppendLine(" <itypDependencies_2>");
foreach (var kvp1 in typdeps)
{
sb.AppendLine(" <Item>");
sb.AppendLine(" <itypName>" + kvp1.Key + "</itypName>");
sb.AppendLine(" <manifestFlags>INTERIOR_DATA</manifestFlags>");
sb.AppendLine(" <itypDepArray>");
foreach (var kvp2 in kvp1.Value)
{
sb.AppendLine(" <Item>" + kvp2.Key + "</Item>");
}
sb.AppendLine(" </itypDepArray>");
sb.AppendLine(" </Item>");
}
sb.AppendLine(" </itypDependencies_2>");
}
else
{
sb.AppendLine(" <itypDependencies_2/>");
}
if (interiors.Count > 0)
{
sb.AppendLine(" <Interiors itemType=\"CInteriorBoundsFiles\">");
foreach (var interior in interiors)
{
sb.AppendLine(" <Item>");
sb.AppendLine(" <Name>" + interior + "</Name>");
sb.AppendLine(" <Bounds>");
sb.AppendLine(" <Item>" + interior + "</Item>");
sb.AppendLine(" </Bounds>");
sb.AppendLine(" </Item>");
}
sb.AppendLine(" </Interiors>");
}
else
{
sb.AppendLine(" <Interiors/>");
}
sb.AppendLine("</CPackFileMetaData>");
ProjectManifestTextBox.Text = sb.ToString();
Text = "_manifest.ymf*";
}
private void ProjectManifestGenerateButton_Click(object sender, EventArgs e)
{
CurrentProjectFile = ProjectForm.CurrentProjectFile;
GenerateProjectManifest();
}
private void SaveManifestButton_Click(object sender, EventArgs e)
{
if (SaveFileDialog.ShowDialog() != DialogResult.OK) return;
try
{
var filename = SaveFileDialog.FileName;
var xml = ProjectManifestTextBox.Text;
var xmldoc = new XmlDocument();
xmldoc.LoadXml(xml);
var pso = XmlPso.GetPso(xmldoc);
var bytes = pso.Save();
File.WriteAllBytes(filename, bytes);
}
catch (Exception ex)
{
MessageBox.Show("Error saving _manifest.ymf file:\n" + ex.ToString());
}
}
}
}