Save RSC Meta files to RPF directly from Meta Editor form

This commit is contained in:
dexy 2018-12-14 21:23:05 +11:00
parent e7f5238c33
commit f84b51d1c1
5 changed files with 233 additions and 19 deletions

View File

@ -3426,6 +3426,8 @@ namespace CodeWalker.GameFiles
LODLights = 1326371921,
BoxOccluder = 975711773,
OccludeModel = 2741784237,
sirenLight = 4091688452,
sirenCorona = 472016577,

View File

@ -1763,4 +1763,15 @@ namespace CodeWalker.GameFiles
}
public enum MetaFormat
{
XML = 0,
RSC = 1,
PSO = 2,
RBF = 3,
CacheFile = 4,
}
}

View File

@ -487,18 +487,18 @@ namespace CodeWalker.GameFiles
new PsoStructureEntryInfo(MetaName.leftTailLightMultiples, PsoDataType.UByte, 122, 0, 0),
new PsoStructureEntryInfo(MetaName.rightTailLightMultiples, PsoDataType.UByte, 123, 0, 0),
new PsoStructureEntryInfo(MetaName.useRealLights, PsoDataType.Bool, 124, 0, 0),
new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, (MetaName)4091688452),
new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, MetaName.sirenLight),
new PsoStructureEntryInfo((MetaName)2047330294, PsoDataType.Array, 128, 1, (MetaName)1310739)
);
case (MetaName)188820339:
return new PsoStructureInfo((MetaName)188820339, 0, 0, 16,
new PsoStructureEntryInfo(MetaName.sequencer, PsoDataType.UInt, 8, 0, 0)
);
case (MetaName)4091688452:
return new PsoStructureInfo((MetaName)4091688452, 0, 0, 112,
case MetaName.sirenLight:
return new PsoStructureInfo(MetaName.sirenLight, 0, 0, 112,
new PsoStructureEntryInfo(MetaName.rotation, PsoDataType.Structure, 8, 0, (MetaName)1356743507),
new PsoStructureEntryInfo(MetaName.flashiness, PsoDataType.Structure, 40, 0, (MetaName)1356743507),
new PsoStructureEntryInfo(MetaName.corona, PsoDataType.Structure, 72, 0, (MetaName)472016577),
new PsoStructureEntryInfo(MetaName.corona, PsoDataType.Structure, 72, 0, MetaName.sirenCorona),
new PsoStructureEntryInfo(MetaName.color, PsoDataType.UInt, 96, 1, 0),
new PsoStructureEntryInfo(MetaName.intensity, PsoDataType.Float, 100, 0, 0),
new PsoStructureEntryInfo(MetaName.lightGroup, PsoDataType.UByte, 104, 0, 0),
@ -520,8 +520,8 @@ namespace CodeWalker.GameFiles
new PsoStructureEntryInfo(MetaName.direction, PsoDataType.Bool, 25, 0, 0),
new PsoStructureEntryInfo(MetaName.syncToBpm, PsoDataType.Bool, 26, 0, 0)
);
case (MetaName)472016577:
return new PsoStructureInfo((MetaName)472016577, 0, 0, 24,
case MetaName.sirenCorona:
return new PsoStructureInfo(MetaName.sirenCorona, 0, 0, 24,
new PsoStructureEntryInfo(MetaName.intensity, PsoDataType.Float, 8, 0, 0),
new PsoStructureEntryInfo(MetaName.size, PsoDataType.Float, 12, 0, 0),
new PsoStructureEntryInfo(MetaName.pull, PsoDataType.Float, 16, 0, 0),

View File

@ -44,7 +44,7 @@ namespace CodeWalker
private GameFileCache FileCache { get; set; } = GameFileCacheFactory.Create();
private object FileCacheSyncRoot = new object();
private bool EditMode = false;
public bool EditMode { get; private set; } = false;
public ThemeBase Theme { get; private set; }
@ -905,7 +905,6 @@ namespace CodeWalker
RecurseAddMainTreeViewNodes(f, CurrentFolder.TreeNode);
CurrentFolder.AddChild(f);
CurrentFolder.ListItems = null;
RefreshMainListView();
}
@ -1053,11 +1052,23 @@ namespace CodeWalker
}
}
public void RefreshMainListViewInvoke()
{
if (InvokeRequired)
{
BeginInvoke(new Action(() => { RefreshMainListView(); }));
}
else
{
RefreshMainListView();
}
}
private void RefreshMainListView()
{
MainListView.VirtualListSize = 0;
if (CurrentFolder != null)
{
CurrentFolder.ListItems = null; //makes sure to rebuild the current files list
CurrentFiles = CurrentFolder.GetListItems();
foreach (var file in CurrentFiles) //cache all the data for use by the list view.
@ -1314,6 +1325,13 @@ namespace CodeWalker
try
#endif
{
var exform = FindExistingForm(item?.File);
if (exform != null)
{
exform.Focus();
return;
}
byte[] data = null;
string name = "";
string path = "";
@ -1469,35 +1487,35 @@ namespace CodeWalker
private void ViewYmt(string name, string path, byte[] data, RpfFileEntry e)
{
var ymt = RpfFile.GetFile<YmtFile>(e, data);
MetaForm f = new MetaForm();
MetaForm f = new MetaForm(this);
f.Show();
f.LoadMeta(ymt);
}
private void ViewYmf(string name, string path, byte[] data, RpfFileEntry e)
{
var ymf = RpfFile.GetFile<YmfFile>(e, data);
MetaForm f = new MetaForm();
MetaForm f = new MetaForm(this);
f.Show();
f.LoadMeta(ymf);
}
private void ViewYmap(string name, string path, byte[] data, RpfFileEntry e)
{
var ymap = RpfFile.GetFile<YmapFile>(e, data);
MetaForm f = new MetaForm();
MetaForm f = new MetaForm(this);
f.Show();
f.LoadMeta(ymap);
}
private void ViewYtyp(string name, string path, byte[] data, RpfFileEntry e)
{
var ytyp = RpfFile.GetFile<YtypFile>(e, data);
MetaForm f = new MetaForm();
MetaForm f = new MetaForm(this);
f.Show();
f.LoadMeta(ytyp);
}
private void ViewJPso(string name, string path, byte[] data, RpfFileEntry e)
{
var pso = RpfFile.GetFile<JPsoFile>(e, data);
MetaForm f = new MetaForm();
MetaForm f = new MetaForm(this);
f.Show();
f.LoadMeta(pso);
}
@ -1538,7 +1556,7 @@ namespace CodeWalker
private void ViewCut(string name, string path, byte[] data, RpfFileEntry e)
{
var cut = RpfFile.GetFile<CutFile>(e, data);
MetaForm f = new MetaForm();
MetaForm f = new MetaForm(this);
f.Show();
f.LoadMeta(cut);
}
@ -1594,12 +1612,29 @@ namespace CodeWalker
private void ViewCacheDat(string name, string path, byte[] data, RpfFileEntry e)
{
var cachedat = RpfFile.GetFile<CacheDatFile>(e, data);
MetaForm f = new MetaForm();
MetaForm f = new MetaForm(this);
f.Show();
f.LoadMeta(cachedat);
}
private Form FindExistingForm(RpfFileEntry e)
{
if (e == null) return null;
var allforms = Application.OpenForms;
var path = e.Path.ToLowerInvariant();
foreach (var form in allforms)
{
var metaform = form as MetaForm;
if (metaform?.rpfFileEntry == e) return metaform;
if (metaform?.rpfFileEntry?.Path?.ToLowerInvariant() == path)
return metaform; //need to test the path as well since the file entry may have been replaced by a new version..!
}
return null;
}
private void ShowTreeContextMenu(TreeNode n, Point p)
{
var f = n?.Tag as MainTreeFolder;
@ -2265,7 +2300,6 @@ namespace CodeWalker
}
CurrentFolder.ListItems = null;
RefreshMainListView();
}
@ -2407,7 +2441,6 @@ namespace CodeWalker
}
}
CurrentFolder.ListItems = null;
RefreshMainListView();
}
private void CopySelected()

View File

@ -11,6 +11,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
namespace CodeWalker.Forms
{
@ -44,8 +45,15 @@ namespace CodeWalker.Forms
private bool DelayHighlight = false;
public MetaForm()
private ExploreForm exploreForm = null;
public RpfFileEntry rpfFileEntry { get; private set; } = null;
private MetaFormat metaFormat = MetaFormat.XML;
public MetaForm(ExploreForm owner)
{
exploreForm = owner;
InitializeComponent();
}
@ -119,14 +127,18 @@ namespace CodeWalker.Forms
Xml = "";
RawPropertyGrid.SelectedObject = null;
modified = false;
rpfFileEntry = null;
return true;
}
private void NewDocument()
{
if (!CloseDocument()) return; //same thing really..
if (!CloseDocument()) return;
FileName = "New.xml";
rpfFileEntry = null;
//TODO: decide XML/RSC/PSO/RBF format..?
}
private void OpenDocument()
{
@ -144,9 +156,32 @@ namespace CodeWalker.Forms
FilePath = fn;
FileName = new FileInfo(fn).Name;
RawPropertyGrid.SelectedObject = null;
rpfFileEntry = null;
//TODO: open RSC/PSO/RBF..?
}
private void SaveDocument(bool saveAs = false)
{
if ((metaFormat != MetaFormat.XML) && (saveAs == false))
{
var doc = new XmlDocument();
try
{
doc.LoadXml(xml);
}
catch (Exception ex)
{
MessageBox.Show("There's something wrong with your XML document:\r\n" + ex.Message, "Unable to parse XML");
return;
}
if (SaveMeta(doc))
{
return;
}
//if Meta saving failed for whatever reason, fallback to saving the XML in the filesystem.
saveAs = true;
}
if (string.IsNullOrEmpty(FileName)) saveAs = true;
if (string.IsNullOrEmpty(FilePath)) saveAs = true;
else if ((FilePath.ToLowerInvariant().StartsWith(GTAFolder.CurrentGTAFolder.ToLowerInvariant()))) saveAs = true;
@ -171,6 +206,7 @@ namespace CodeWalker.Forms
modified = false;
FilePath = fn;
FileName = new FileInfo(fn).Name;
metaFormat = MetaFormat.XML;
}
@ -181,7 +217,15 @@ namespace CodeWalker.Forms
Xml = MetaXml.GetXml(ymt, out fn);
FileName = fn;
RawPropertyGrid.SelectedObject = ymt;
rpfFileEntry = ymt?.RpfFileEntry;
modified = false;
metaFormat = MetaFormat.XML;
if (ymt != null)
{
if (ymt.Meta != null) metaFormat = MetaFormat.RSC;
if (ymt.Pso != null) metaFormat = MetaFormat.PSO;
if (ymt.Rbf != null) metaFormat = MetaFormat.RBF;
}
}
public void LoadMeta(YmfFile ymf)
{
@ -189,7 +233,15 @@ namespace CodeWalker.Forms
Xml = MetaXml.GetXml(ymf, out fn);
FileName = fn;
RawPropertyGrid.SelectedObject = ymf;
rpfFileEntry = ymf?.FileEntry;
modified = false;
metaFormat = MetaFormat.XML;
if (ymf != null)
{
if (ymf.Meta != null) metaFormat = MetaFormat.RSC;
if (ymf.Pso != null) metaFormat = MetaFormat.PSO;
if (ymf.Rbf != null) metaFormat = MetaFormat.RBF;
}
}
public void LoadMeta(YmapFile ymap)
{
@ -197,7 +249,15 @@ namespace CodeWalker.Forms
Xml = MetaXml.GetXml(ymap, out fn);
FileName = fn;
RawPropertyGrid.SelectedObject = ymap;
rpfFileEntry = ymap?.RpfFileEntry;
modified = false;
metaFormat = MetaFormat.XML;
if (ymap != null)
{
if (ymap.Meta != null) metaFormat = MetaFormat.RSC;
if (ymap.Pso != null) metaFormat = MetaFormat.PSO;
if (ymap.Rbf != null) metaFormat = MetaFormat.RBF;
}
}
public void LoadMeta(YtypFile ytyp)
{
@ -205,7 +265,15 @@ namespace CodeWalker.Forms
Xml = MetaXml.GetXml(ytyp, out fn);
FileName = fn;
RawPropertyGrid.SelectedObject = ytyp;
rpfFileEntry = ytyp?.RpfFileEntry;
modified = false;
metaFormat = MetaFormat.XML;
if (ytyp != null)
{
if (ytyp.Meta != null) metaFormat = MetaFormat.RSC;
if (ytyp.Pso != null) metaFormat = MetaFormat.PSO;
if (ytyp.Rbf != null) metaFormat = MetaFormat.RBF;
}
}
public void LoadMeta(JPsoFile jpso)
{
@ -213,7 +281,13 @@ namespace CodeWalker.Forms
Xml = MetaXml.GetXml(jpso, out fn);
FileName = fn;
RawPropertyGrid.SelectedObject = jpso;
rpfFileEntry = jpso?.FileEntry;
modified = false;
metaFormat = MetaFormat.XML;
if (jpso != null)
{
if (jpso.Pso != null) metaFormat = MetaFormat.PSO;
}
}
public void LoadMeta(CutFile cut)
{
@ -221,7 +295,13 @@ namespace CodeWalker.Forms
Xml = MetaXml.GetXml(cut, out fn);
FileName = fn;
RawPropertyGrid.SelectedObject = cut;
rpfFileEntry = cut?.FileEntry;
modified = false;
metaFormat = MetaFormat.XML;
if (cut != null)
{
if (cut.Pso != null) metaFormat = MetaFormat.PSO;
}
}
public void LoadMeta(CacheDatFile cachedat)
{
@ -229,11 +309,99 @@ namespace CodeWalker.Forms
Xml = cachedat.GetXml();
FileName = fn;
RawPropertyGrid.SelectedObject = cachedat;
rpfFileEntry = cachedat?.FileEntry;
modified = false;
metaFormat = MetaFormat.XML;
if (cachedat?.FileEntry != null)
{
metaFormat = MetaFormat.CacheFile;
}
}
public bool SaveMeta(XmlDocument doc)
{
//if explorer is in edit mode, and the current RpfFileEntry is valid, convert XML to the
//current meta format and then save the file into the RPF.
//otherwise, save the generated file to disk?
//(currently just return false and revert to XML file save)
if (!(exploreForm?.EditMode ?? false)) return false;
if (rpfFileEntry?.Parent == null) return false;
byte[] data = null;
try
{
switch (metaFormat)
{
default:
case MetaFormat.XML: return false;//what are we even doing here?
case MetaFormat.RSC:
var meta = XmlMeta.GetMeta(doc);
if ((meta.DataBlocks?.Data == null) || (meta.DataBlocks.Count == 0))
{
MessageBox.Show("Schema not supported.", "Cannot import Meta XML");
return false;
}
data = ResourceBuilder.Build(meta, 2); //meta is RSC "Version":2 (it's actually a type identifier, not a version!)
break;
case MetaFormat.PSO:
MessageBox.Show("Sorry, PSO import is not supported yet.", "Cannot import PSO XML");
return false;
case MetaFormat.RBF:
MessageBox.Show("Sorry, RBF import is not supported.", "Cannot import RBF XML");
return false;
case MetaFormat.CacheFile:
MessageBox.Show("Sorry, CacheFile import is not supported.", "Cannot import CacheFile XML");
return false;
}
}
catch (Exception ex)
{
MessageBox.Show("Exception encountered!\r\n" + ex.Message, "Cannot convert XML");
return false;
}
if (data == null)
{
MessageBox.Show("Schema not supported. (Unspecified error - data was null!)", "Cannot convert XML");
return false;
}
if (!rpfFileEntry.Path.ToLowerInvariant().StartsWith("mods"))
{
if (MessageBox.Show("This file is NOT located in the mods folder - Are you SURE you want to save this file?\r\nWARNING: This could cause permanent damage to your game!!!", "WARNING: Are you sure about this?", MessageBoxButtons.YesNo) != DialogResult.Yes)
{
return false;//that was a close one
}
}
try
{
var newentry = RpfFile.CreateFile(rpfFileEntry.Parent, rpfFileEntry.Name, data);
if (newentry != rpfFileEntry)
{ }
rpfFileEntry = newentry;
exploreForm?.RefreshMainListViewInvoke(); //update the file details in explorer...
modified = false;
return true; //victory!
}
catch (Exception ex)
{
MessageBox.Show("Error saving file to RPF! The RPF archive may be corrupted...\r\n" + ex.Message, "Really Bad Error");
}
return false;
}
Style BlueStyle = new TextStyle(Brushes.Blue, null, FontStyle.Regular);
Style RedStyle = new TextStyle(Brushes.Red, null, FontStyle.Regular);
Style MaroonStyle = new TextStyle(Brushes.Maroon, null, FontStyle.Regular);