Add plugin for Microsoft Merlin game engine (Hover!)
This commit is contained in:
parent
58077533a9
commit
430ffe8e67
@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UniversalEditor.IO;
|
||||
|
||||
namespace UniversalEditor.DataFormats.Multimedia.FileSystem.Microsoft.Merlin.Mfc
|
||||
{
|
||||
public class CMerlinObject : MfcObject
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public override void LoadObject(Reader reader)
|
||||
{
|
||||
Name = reader.ReadMfcString();
|
||||
reader.ReadMfcObjectWithoutHeader<TrailingBytes>();
|
||||
}
|
||||
|
||||
public override void SaveObject(Writer writer)
|
||||
{
|
||||
// writer.WriteMfcString(Name);
|
||||
// writer.WriteMfcObjectWithoutHeader(new TrailingBytes());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,90 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace UniversalEditor.DataFormats.Multimedia.FileSystem.Microsoft.Merlin.Mfc
|
||||
{
|
||||
public class MipMap
|
||||
{
|
||||
public Size ImageDimensionsMinusOne { get; set; }
|
||||
public Size ImageDimensions { get; set; }
|
||||
public uint Level { get; set; }
|
||||
public byte[] ImageData { get; set; }
|
||||
|
||||
public List<List<PixelSpan>> PixelSpans { get; set; }
|
||||
}
|
||||
public struct PixelSpan
|
||||
{
|
||||
public ushort StartIndex;
|
||||
public ushort EndIndex;
|
||||
|
||||
public PixelSpan(ushort startIndex, ushort endIndex)
|
||||
{
|
||||
StartIndex = startIndex;
|
||||
EndIndex = endIndex;
|
||||
}
|
||||
};
|
||||
|
||||
[MfcSerialisable("CMerlinTexture")]
|
||||
internal class CMerlinTexture : CMerlinObject
|
||||
{
|
||||
public bool HasTransparency { get; private set; }
|
||||
public List<MipMap> Mipmaps { get; private set; }
|
||||
|
||||
public override void LoadObject(IO.Reader reader)
|
||||
{
|
||||
base.LoadObject(reader);
|
||||
|
||||
var flags = reader.ReadUInt16();
|
||||
this.HasTransparency = (flags & 1) != 0;
|
||||
if ((flags & ~1) != 0)
|
||||
{
|
||||
throw new NotImplementedException("Unexpected flag set in texture header");
|
||||
}
|
||||
|
||||
ushort mipmapCount = reader.ReadUInt16();
|
||||
this.Mipmaps = new List<MipMap>(mipmapCount);
|
||||
for (int i = 0; i < mipmapCount; i++)
|
||||
{
|
||||
MipMap mipmap = new MipMap();
|
||||
var nextLargestHeight = reader.ReadUInt16();
|
||||
var imageHeight = reader.ReadUInt16();
|
||||
var nextLargestWidth = reader.ReadUInt16();
|
||||
var imageWidth = reader.ReadUInt16();
|
||||
|
||||
mipmap.ImageDimensionsMinusOne = new Size(imageWidth, imageHeight);
|
||||
mipmap.ImageDimensions = new Size(nextLargestWidth, nextLargestHeight);
|
||||
mipmap.Level = reader.ReadUInt16();
|
||||
|
||||
var imageDataLength = reader.ReadUInt32();
|
||||
mipmap.ImageData = reader.ReadBytes((int)imageDataLength);
|
||||
|
||||
int totalSpanCount = (int)reader.ReadUInt32();
|
||||
mipmap.PixelSpans = new List<List<PixelSpan>>(totalSpanCount);
|
||||
for (int y = 0; y < nextLargestHeight; y++)
|
||||
{
|
||||
ushort rowSpanCount = reader.ReadUInt16();
|
||||
var rowSpans = new List<PixelSpan>(rowSpanCount);
|
||||
for (int k = 0; k < rowSpanCount; k++)
|
||||
{
|
||||
ushort startIndex = reader.ReadUInt16();
|
||||
ushort endIndex = reader.ReadUInt16();
|
||||
rowSpans.Add(new PixelSpan(startIndex, endIndex));
|
||||
}
|
||||
mipmap.PixelSpans.Add(rowSpans);
|
||||
}
|
||||
|
||||
reader.ReadMfcObjectWithoutHeader<TrailingBytes>();
|
||||
|
||||
this.Mipmaps.Add(mipmap);
|
||||
}
|
||||
}
|
||||
|
||||
public override void SaveObject(IO.Writer reader)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace UniversalEditor.DataFormats.Multimedia.FileSystem.Microsoft.Merlin.Mfc
|
||||
{
|
||||
[MfcSerialisable]
|
||||
internal class TrailingBytes : MfcObject
|
||||
{
|
||||
private byte[] trailingBytes = new byte[0];
|
||||
|
||||
public override void LoadObject(IO.Reader reader)
|
||||
{
|
||||
ushort byteCount = reader.ReadUInt16();
|
||||
trailingBytes = reader.ReadBytes(byteCount);
|
||||
}
|
||||
public override void SaveObject(IO.Writer writer)
|
||||
{
|
||||
writer.WriteUInt16(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,130 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UniversalEditor.Accessors;
|
||||
using UniversalEditor.DataFormats.Multimedia.FileSystem.Microsoft.Merlin.Mfc;
|
||||
using UniversalEditor.IO;
|
||||
using UniversalEditor.ObjectModels.FileSystem;
|
||||
using UniversalEditor.ObjectModels.Multimedia.Palette;
|
||||
|
||||
namespace UniversalEditor.DataFormats.Multimedia.FileSystem.Microsoft.Merlin
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a Microsoft Merlin Game Engine (Hover!) .TEX file,
|
||||
/// containing a shared palette and up to 65535 textures.
|
||||
/// </summary>
|
||||
public class TEXDataFormat : DataFormat
|
||||
{
|
||||
private static DataFormatReference _dfr = null;
|
||||
public override DataFormatReference MakeReference()
|
||||
{
|
||||
if (_dfr == null)
|
||||
{
|
||||
_dfr = base.MakeReference();
|
||||
_dfr.Capabilities.Add(typeof(FileSystemObjectModel), DataFormatCapabilities.All);
|
||||
_dfr.Filters.Add("Microsoft Merlin Game Engine (Hover!) texture pack", new string[] { "*.tex" });
|
||||
}
|
||||
return _dfr;
|
||||
}
|
||||
|
||||
private int mvarPaletteEntryCount = 256;
|
||||
private PaletteObjectModel mvarPalette = new PaletteObjectModel();
|
||||
|
||||
protected override void LoadInternal(ref ObjectModel objectModel)
|
||||
{
|
||||
FileSystemObjectModel fsom = (objectModel as FileSystemObjectModel);
|
||||
if (fsom == null) throw new ObjectModelNotSupportedException();
|
||||
|
||||
Reader reader = base.Accessor.Reader;
|
||||
reader.Accessor.Position = 0;
|
||||
fsom.Clear();
|
||||
mvarPalette.Clear();
|
||||
|
||||
for (int i = 0; i < mvarPaletteEntryCount; i++)
|
||||
{
|
||||
byte r = reader.ReadByte();
|
||||
byte g = reader.ReadByte();
|
||||
byte b = reader.ReadByte();
|
||||
byte a = reader.ReadByte();
|
||||
mvarPalette.Entries.Add(Color.FromRGBA(r, g, b, a));
|
||||
}
|
||||
|
||||
MemoryAccessor ma = new MemoryAccessor();
|
||||
Document.Save(mvarPalette, new DataFormats.Multimedia.Palette.Adobe.ACODataFormat(), ma, true);
|
||||
|
||||
fsom.Files.Add("PALETTE.ACO", ma.ToArray());
|
||||
|
||||
// Read a List<CMerlinTexture>
|
||||
List<CMerlinTexture> list = reader.ReadMfcList<CMerlinTexture>();
|
||||
for (ushort i = 0; i < list.Count; i++)
|
||||
{
|
||||
/*
|
||||
ushort tag = reader.ReadUInt16();
|
||||
uint objectTag = ((uint)(tag & ClassTag) << 16) | (uint)(tag & ~ClassTag);
|
||||
if (tag == BigObjectTag)
|
||||
{
|
||||
objectTag = reader.ReadUInt32();
|
||||
}
|
||||
|
||||
if (tag == NewClassTag)
|
||||
{
|
||||
// Not a class we've seen before; read it in
|
||||
ushort schemaVersion = reader.ReadUInt16();
|
||||
string className = reader.ReadUInt16String();
|
||||
}
|
||||
|
||||
Folder textureI = new Folder();
|
||||
|
||||
string name = ReadMFCString(reader);
|
||||
textureI.Name = name;
|
||||
|
||||
TEXTextureFlags flags = (TEXTextureFlags)reader.ReadUInt16();
|
||||
ushort mipmapCount = reader.ReadUInt16();
|
||||
for (ushort j = 0; j < mipmapCount; j++)
|
||||
{
|
||||
// TextureMipmap mipmap = new TextureMipmap();
|
||||
var nextLargestHeight = reader.ReadUInt16();
|
||||
var imageHeight = reader.ReadUInt16();
|
||||
var nextLargestWidth = reader.ReadUInt16();
|
||||
var imageWidth = reader.ReadUInt16();
|
||||
|
||||
// mipmap.ImageDimensionsMinusOne = new Size(imageWidth, imageHeight);
|
||||
// mipmap.ImageDimensions = new Size(nextLargestWidth, nextLargestHeight);
|
||||
// mipmap.Level = archive.DeserialiseUInt16();
|
||||
ushort mipmapLevel = reader.ReadUInt16();
|
||||
|
||||
var imageDataLength = reader.ReadUInt32();
|
||||
byte[] ImageData = reader.ReadBytes((int)imageDataLength);
|
||||
|
||||
textureI.Files.Add("MIPMAP" + j.ToString() + ".BMP", ImageData);
|
||||
|
||||
int totalSpanCount = (int)reader.ReadUInt32();
|
||||
// mipmap.PixelSpans = new List<List<PixelSpan>>(totalSpanCount);
|
||||
for (int y = 0; y < nextLargestHeight; y++)
|
||||
{
|
||||
ushort rowSpanCount = reader.ReadUInt16();
|
||||
// var rowSpans = new List<PixelSpan>(rowSpanCount);
|
||||
for (int k = 0; k < rowSpanCount; k++)
|
||||
{
|
||||
ushort startIndex = reader.ReadUInt16();
|
||||
ushort endIndex = reader.ReadUInt16();
|
||||
// rowSpans.Add(new PixelSpan(startIndex, endIndex));
|
||||
}
|
||||
// mipmap.PixelSpans.Add(rowSpans);
|
||||
}
|
||||
|
||||
ushort trailingByteCount = reader.ReadUInt16();
|
||||
byte[] trailingBytes = reader.ReadBytes(trailingByteCount);
|
||||
}
|
||||
fsom.Folders.Add(textureI);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
protected override void SaveInternal(ObjectModel objectModel)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace UniversalEditor.DataFormats.Multimedia.FileSystem.Microsoft.Merlin
|
||||
{
|
||||
[Flags()]
|
||||
public enum TEXTextureFlags : ushort
|
||||
{
|
||||
None = 0,
|
||||
HasTransparency = 1
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UniversalEditor.IO;
|
||||
|
||||
namespace UniversalEditor
|
||||
{
|
||||
public interface IMfcSerialisable<T> where T : IMfcSerialisable<T>
|
||||
{
|
||||
void LoadObject(Reader reader);
|
||||
void SaveObject(Writer writer);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace UniversalEditor
|
||||
{
|
||||
public class MfcClass
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public int SchemaVersion { get; set; }
|
||||
public Type RealType { get; set; }
|
||||
|
||||
internal T CreateNewObject<T>() where T : IMfcSerialisable<T>
|
||||
{
|
||||
if (RealType.IsAssignableFrom(typeof(T)))
|
||||
{
|
||||
throw new ArgumentException("Cannot assign " + RealType.Name + " from " + typeof(T).Name);
|
||||
}
|
||||
return (T)RealType.Assembly.CreateInstance(RealType.FullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace UniversalEditor
|
||||
{
|
||||
public class MfcClassRegistry
|
||||
{
|
||||
private Dictionary<string, MfcClass> _registry;
|
||||
|
||||
public MfcClassRegistry()
|
||||
{
|
||||
this._registry = new Dictionary<string, MfcClass>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a single serialised class name.
|
||||
/// </summary>
|
||||
/// <param name="mfcName">The serialised class name.</param>
|
||||
/// <param name="realType">The .Net type capable of deserialising the class data.</param>
|
||||
public void RegisterClass(string mfcName, Type realType)
|
||||
{
|
||||
_registry.Add(mfcName, new MfcClass
|
||||
{
|
||||
Name = mfcName,
|
||||
SchemaVersion = 1,
|
||||
RealType = realType
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers all exported classes from the specified assembly
|
||||
/// that are marked with the MfcSerialisable attribute.
|
||||
/// </summary>
|
||||
public void AutoRegisterClasses(Assembly assembly)
|
||||
{
|
||||
foreach (var type in assembly.GetExportedTypes())
|
||||
{
|
||||
var markers = type.GetCustomAttributes(typeof(MfcSerialisableAttribute), false).Cast<MfcSerialisableAttribute>();
|
||||
foreach (var marker in markers)
|
||||
{
|
||||
RegisterClass(marker.SerialisedName, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public MfcClass GetMfcClass(string mfcName)
|
||||
{
|
||||
return _registry[mfcName];
|
||||
}
|
||||
|
||||
public MfcClass GetMfcClass(Type realType)
|
||||
{
|
||||
var x = from c in _registry.Values where c.RealType == realType select c;
|
||||
return x.Single();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UniversalEditor.IO;
|
||||
|
||||
namespace UniversalEditor
|
||||
{
|
||||
public abstract class MfcObject : IMfcSerialisable<MfcObject>
|
||||
{
|
||||
public abstract void LoadObject(Reader reader);
|
||||
public abstract void SaveObject(Writer reader);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace UniversalEditor
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
|
||||
class MfcSerialisableAttribute : Attribute
|
||||
{
|
||||
private string _serialisedName;
|
||||
|
||||
/// <summary>
|
||||
/// Marks a type as serialisable with an explicit name.
|
||||
/// </summary>
|
||||
public MfcSerialisableAttribute(string serialisedName)
|
||||
{
|
||||
this._serialisedName = serialisedName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Marks a type as serialisable but with no name.
|
||||
/// Such types cannot be automatically deserialised;
|
||||
/// you must explicitly name the type for each serialise call.
|
||||
/// </summary>
|
||||
public MfcSerialisableAttribute()
|
||||
{
|
||||
_serialisedName = string.Format("Anonymous_{0}", Guid.NewGuid().ToString());
|
||||
}
|
||||
|
||||
public string SerialisedName
|
||||
{
|
||||
get
|
||||
{
|
||||
return _serialisedName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("UniversalEditor.Plugins.Microsoft.Merlin")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("City of Orlando")]
|
||||
[assembly: AssemblyProduct("UniversalEditor.Plugins.Microsoft.Merlin")]
|
||||
[assembly: AssemblyCopyright("Copyright © City of Orlando 2014")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("559ea7e5-9dcf-42c4-a7be-82af087449ae")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@ -0,0 +1,193 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UniversalEditor.IO;
|
||||
|
||||
namespace UniversalEditor
|
||||
{
|
||||
public static class ReaderExtensions
|
||||
{
|
||||
const UInt16 NullTag = 0;
|
||||
const UInt16 NewClassTag = 0xffff;
|
||||
const UInt16 ClassTag = 0x8000;
|
||||
const UInt32 BigClassTag = 0x80000000;
|
||||
const UInt16 BigObjectTag = 0x7fff;
|
||||
const UInt32 MaxMapCountTag = 0x3ffffffe;
|
||||
|
||||
private static MfcClassRegistry _classRegistry;
|
||||
private static List<MfcClass> _loadedClasses;
|
||||
private static List<MfcObject> _loadedObjects;
|
||||
|
||||
static ReaderExtensions()
|
||||
{
|
||||
_classRegistry = new MfcClassRegistry();
|
||||
_loadedClasses = new List<MfcClass>();
|
||||
_loadedObjects = new List<MfcObject>();
|
||||
|
||||
// Class index zero isn't used/represents an error
|
||||
_loadedClasses.Add(null);
|
||||
|
||||
// Object index zero isn't used/represents a null pointer
|
||||
_loadedObjects.Add(null);
|
||||
|
||||
_classRegistry.AutoRegisterClasses(typeof(ReaderExtensions).Assembly);
|
||||
}
|
||||
|
||||
public static MfcClass ReadNewMfcClass(this Reader reader)
|
||||
{
|
||||
ushort schemaVersion = reader.ReadUInt16();
|
||||
string className = reader.ReadUInt16String();
|
||||
|
||||
MfcClass mfcClass = _classRegistry.GetMfcClass(className);
|
||||
|
||||
if (mfcClass == null)
|
||||
{
|
||||
throw new System.IO.InvalidDataException("No registered class for MfcObject " + className);
|
||||
}
|
||||
if (mfcClass.SchemaVersion != schemaVersion)
|
||||
{
|
||||
throw new System.IO.InvalidDataException("Schema mismatch: file = " + schemaVersion + ", registered = " + mfcClass.SchemaVersion);
|
||||
}
|
||||
|
||||
return mfcClass;
|
||||
}
|
||||
|
||||
public static string ReadMfcString(this Reader reader)
|
||||
{
|
||||
int stringLength = 0;
|
||||
byte bLength = reader.ReadByte();
|
||||
if (bLength < 0xff)
|
||||
{
|
||||
stringLength = bLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
ushort wLength = reader.ReadUInt16();
|
||||
if (wLength < 0xfffe)
|
||||
{
|
||||
stringLength = wLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wLength == 0xfffe)
|
||||
{
|
||||
// Unicode string prefix -- not currently handled. See
|
||||
// CArchive::operator>>(CArchive& ar, CString& string)
|
||||
// for details on how to implement this when needed.
|
||||
}
|
||||
stringLength = reader.ReadInt32();
|
||||
}
|
||||
}
|
||||
|
||||
return reader.ReadFixedLengthString(stringLength);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to read in and return the MfcClass that is next in the stream.
|
||||
/// If the next object has already been loaded then null is returned and
|
||||
/// alreadyLoadedTag is set to the object ID of the object.
|
||||
/// </summary>
|
||||
public static MfcClass ReadMfcClass(this Reader reader, out uint alreadyLoadedTag)
|
||||
{
|
||||
ushort tag = reader.ReadUInt16();
|
||||
uint objectTag = ((uint)(tag & ClassTag) << 16) | (uint)(tag & ~ClassTag);
|
||||
if (tag == BigObjectTag)
|
||||
{
|
||||
objectTag = reader.ReadUInt32();
|
||||
}
|
||||
|
||||
// If it is an object tag and not a class tag then bail out -- caller will handle it
|
||||
alreadyLoadedTag = 0;
|
||||
if ((objectTag & BigClassTag) == 0)
|
||||
{
|
||||
alreadyLoadedTag = objectTag;
|
||||
return null;
|
||||
}
|
||||
|
||||
MfcClass mfcClass;
|
||||
if (tag == NewClassTag)
|
||||
{
|
||||
// Not a class we've seen before; read it in
|
||||
mfcClass = reader.ReadNewMfcClass();
|
||||
_loadedClasses.Add(mfcClass);
|
||||
return mfcClass;
|
||||
}
|
||||
|
||||
// A class we've seen before, look it up by index
|
||||
uint classIndex = objectTag & ~BigClassTag;
|
||||
if (classIndex == 0)
|
||||
{
|
||||
throw new System.IO.InvalidDataException("Got a invalid class index: 0");
|
||||
}
|
||||
if (classIndex > _loadedClasses.Count)
|
||||
{
|
||||
throw new System.IO.InvalidDataException("Got a class index larger than the currently loaded count: " + classIndex);
|
||||
}
|
||||
|
||||
return _loadedClasses[(int)classIndex];
|
||||
}
|
||||
|
||||
public static T ReadMfcObject<T>(this Reader reader) where T : MfcObject
|
||||
{
|
||||
uint objectTag;
|
||||
MfcClass mfcClass = reader.ReadMfcClass(out objectTag);
|
||||
|
||||
if (mfcClass == null)
|
||||
{
|
||||
// An object we've already loaded
|
||||
if (objectTag > _loadedObjects.Count)
|
||||
{
|
||||
throw new System.IO.InvalidDataException("Got an object tag larger than the count of loaded objects: " + objectTag);
|
||||
}
|
||||
|
||||
return (T)_loadedObjects[(int)objectTag];
|
||||
}
|
||||
|
||||
// An object we haven't yet loaded. Create a new instance and deserialise it.
|
||||
// Make sure to add it to the list of loaded objects before deserialising in
|
||||
// case it has (possibly indirect) references to itself.
|
||||
return reader.ReadNewMfcObject<T>(mfcClass);
|
||||
}
|
||||
public static T ReadNewMfcObject<T>(this Reader reader, MfcClass mfcClass) where T : MfcObject
|
||||
{
|
||||
MfcObject newObject = mfcClass.CreateNewObject<MfcObject>();
|
||||
_loadedObjects.Add(newObject);
|
||||
newObject.LoadObject(reader);
|
||||
return (T)newObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserialises an object of type T without reading in the header.
|
||||
/// This implies it must be a new object and not one that has already
|
||||
/// been loaded since there is no object tag to reference the loaded list.
|
||||
/// </summary>
|
||||
public static T ReadMfcObjectWithoutHeader<T>(this Reader reader) where T : MfcObject
|
||||
{
|
||||
MfcClass mfcClass = _classRegistry.GetMfcClass(typeof(T));
|
||||
return reader.ReadNewMfcObject<T>(mfcClass);
|
||||
}
|
||||
|
||||
public static List<T> ReadMfcList<T>(this Reader reader) where T : MfcObject
|
||||
{
|
||||
List<T> result = new List<T>();
|
||||
ushort listLength = reader.ReadUInt16();
|
||||
|
||||
if (listLength >= 1)
|
||||
{
|
||||
// First object has a valid runtime class header
|
||||
result.Add(reader.ReadMfcObject<T>());
|
||||
}
|
||||
for (int i = 1; i < listLength; i++)
|
||||
{
|
||||
// Subsequent objects are missing the runtime class header but have
|
||||
// a UInt16 preceding them that looks like an invalid runtime class
|
||||
// header.
|
||||
uint unknown1 = reader.ReadUInt16();
|
||||
result.Add(reader.ReadMfcObjectWithoutHeader<T>());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{9F1FDC26-5F1C-4C2A-BBBF-3A597A72802D}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>UniversalEditor</RootNamespace>
|
||||
<AssemblyName>UniversalEditor.Plugins.Microsoft.Merlin</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\..\Output\Debug\Plugins\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\..\Output\Release\Plugins\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="DataFormats\Multimedia\FileSystem\Microsoft\Merlin\Mfc\CMerlinObject.cs" />
|
||||
<Compile Include="DataFormats\Multimedia\FileSystem\Microsoft\Merlin\Mfc\CMerlinTexture.cs" />
|
||||
<Compile Include="DataFormats\Multimedia\FileSystem\Microsoft\Merlin\Mfc\TrailingBytes.cs" />
|
||||
<Compile Include="DataFormats\Multimedia\FileSystem\Microsoft\Merlin\TEXDataFormat.cs" />
|
||||
<Compile Include="DataFormats\Multimedia\FileSystem\Microsoft\Merlin\TEXTextureFlags.cs" />
|
||||
<Compile Include="IMfcSerializable.cs" />
|
||||
<Compile Include="MfcClass.cs" />
|
||||
<Compile Include="MfcClassRegistry.cs" />
|
||||
<Compile Include="MfcObject.cs" />
|
||||
<Compile Include="MfcSerializableAttribute.cs" />
|
||||
<Compile Include="ReaderExtensions.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Libraries\UniversalEditor.Core\UniversalEditor.Core.csproj">
|
||||
<Project>{2d4737e6-6d95-408a-90db-8dff38147e85}</Project>
|
||||
<Name>UniversalEditor.Core</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\UniversalEditor.Essential\UniversalEditor.Essential.csproj">
|
||||
<Project>{30467e5c-05bc-4856-aadc-13906ef4cadd}</Project>
|
||||
<Name>UniversalEditor.Essential</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\UniversalEditor.Plugins.Multimedia\UniversalEditor.Plugins.Multimedia.csproj">
|
||||
<Project>{be4d0ba3-0888-42a5-9c09-fc308a4509d2}</Project>
|
||||
<Name>UniversalEditor.Plugins.Multimedia</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
Loading…
x
Reference in New Issue
Block a user