thief-mission-viewer/project/code/LGS/Database/ObjectHierarchy.cs

179 lines
6.9 KiB
C#

using System.Collections.Generic;
using KeepersCompound.LGS.Database.Chunks;
namespace KeepersCompound.LGS.Database;
public class ObjectHierarchy
{
public class DarkObject
{
public int objectId;
public int parentId;
public Dictionary<string, Property> properties;
public DarkObject(int id)
{
objectId = id;
parentId = 0;
properties = new Dictionary<string, Property>();
}
public T GetProperty<T>(string propName) where T : Property
{
if (properties.TryGetValue(propName, out var prop))
{
return (T)prop;
}
return null;
}
}
private Dictionary<int, DarkObject> _objects;
public ObjectHierarchy(DbFile db, DbFile gam = null)
{
_objects = new Dictionary<int, DarkObject>();
if (db.Chunks.TryGetValue("P$ModelName", out var modelNamesRaw) &&
db.Chunks.TryGetValue("P$Scale", out var scalesRaw) &&
db.Chunks.TryGetValue("P$RenderTyp", out var renderTypesRaw) &&
db.Chunks.TryGetValue("P$OTxtRepr0", out var txtRepl0Raw) &&
db.Chunks.TryGetValue("P$OTxtRepr1", out var txtRepl1Raw) &&
db.Chunks.TryGetValue("P$OTxtRepr2", out var txtRepl2Raw) &&
db.Chunks.TryGetValue("P$OTxtRepr3", out var txtRepl3Raw) &&
db.Chunks.TryGetValue("P$RenderAlp", out var renderAlphaRaw) &&
db.Chunks.TryGetValue("L$MetaProp", out var metaPropLinksRaw) &&
db.Chunks.TryGetValue("LD$MetaProp", out var metaPropLinkDataRaw))
{
var modelNames = (PropertyChunk<PropModelName>)modelNamesRaw;
var scales = (PropertyChunk<PropScale>)scalesRaw;
var renderTypes = (PropertyChunk<PropRenderType>)renderTypesRaw;
var txtRepl0s = (PropertyChunk<PropString>)txtRepl0Raw;
var txtRepl1s = (PropertyChunk<PropString>)txtRepl1Raw;
var txtRepl2s = (PropertyChunk<PropString>)txtRepl2Raw;
var txtRepl3s = (PropertyChunk<PropString>)txtRepl3Raw;
var renderAlpha = (PropertyChunk<PropFloat>)renderAlphaRaw;
var metaPropLinks = (LinkChunk)metaPropLinksRaw;
var metaPropLinkData = (LinkDataMetaProp)metaPropLinkDataRaw;
// Merge gam chunks
if (gam != null &&
gam.Chunks.TryGetValue("P$ModelName", out var gamModelNames) &&
gam.Chunks.TryGetValue("P$Scale", out var gamScales) &&
gam.Chunks.TryGetValue("P$RenderTyp", out var gamRenderTypes) &&
gam.Chunks.TryGetValue("P$OTxtRepr0", out var gamTxtRepl0s) &&
gam.Chunks.TryGetValue("P$OTxtRepr1", out var gamTxtRepl1s) &&
gam.Chunks.TryGetValue("P$OTxtRepr2", out var gamTxtRepl2s) &&
gam.Chunks.TryGetValue("P$OTxtRepr3", out var gamTxtRepl3s) &&
gam.Chunks.TryGetValue("P$RenderAlp", out var gamRenderAlpha) &&
gam.Chunks.TryGetValue("L$MetaProp", out var gamLinks) &&
gam.Chunks.TryGetValue("LD$MetaProp", out var gamLinkData))
{
modelNames.properties.AddRange(((PropertyChunk<PropModelName>)gamModelNames).properties);
scales.properties.AddRange(((PropertyChunk<PropScale>)gamScales).properties);
renderTypes.properties.AddRange(((PropertyChunk<PropRenderType>)gamRenderTypes).properties);
txtRepl0s.properties.AddRange(((PropertyChunk<PropString>)gamTxtRepl0s).properties);
txtRepl1s.properties.AddRange(((PropertyChunk<PropString>)gamTxtRepl1s).properties);
txtRepl2s.properties.AddRange(((PropertyChunk<PropString>)gamTxtRepl2s).properties);
txtRepl3s.properties.AddRange(((PropertyChunk<PropString>)gamTxtRepl3s).properties);
renderAlpha.properties.AddRange(((PropertyChunk<PropFloat>)gamRenderAlpha).properties);
metaPropLinks.links.AddRange(((LinkChunk)gamLinks).links);
metaPropLinkData.linkData.AddRange(((LinkDataMetaProp)gamLinkData).linkData);
}
// Add parentages
var length = metaPropLinks.links.Count;
for (var i = 0; i < length; i++)
{
var link = metaPropLinks.links[i];
var linkData = metaPropLinkData.linkData[i];
var childId = link.source;
var parentId = link.destination;
if (!_objects.ContainsKey(childId))
{
_objects.Add(childId, new DarkObject(childId));
}
if (!_objects.ContainsKey(parentId))
{
_objects.Add(parentId, new DarkObject(parentId));
}
if (linkData.priority == 0)
{
_objects[childId].parentId = parentId;
}
}
void TryAddProp(string propName, Property prop)
{
var id = prop.objectId;
if (!_objects.ContainsKey(id))
{
_objects.Add(id, new DarkObject(id));
}
_objects[id].properties.TryAdd(propName, prop);
}
// TODO: Find a way to do this better
foreach (var prop in modelNames.properties)
{
TryAddProp("P$ModelName", prop);
}
foreach (var prop in scales.properties)
{
TryAddProp("P$Scale", prop);
}
foreach (var prop in renderTypes.properties)
{
TryAddProp("P$RenderTyp", prop);
}
foreach (var prop in txtRepl0s.properties)
{
TryAddProp("P$OTxtRepr0", prop);
}
foreach (var prop in txtRepl1s.properties)
{
TryAddProp("P$OTxtRepr1", prop);
}
foreach (var prop in txtRepl2s.properties)
{
TryAddProp("P$OTxtRepr2", prop);
}
foreach (var prop in txtRepl3s.properties)
{
TryAddProp("P$OTxtRepr3", prop);
}
foreach (var prop in renderAlpha.properties)
{
TryAddProp("P$RenderAlp", prop);
}
}
}
public T GetProperty<T>(int objectId, string propName) where T : Property
{
if (!_objects.ContainsKey(objectId))
{
return null;
}
var parentId = objectId;
while (parentId != 0)
{
if (!_objects.TryGetValue(parentId, out var obj))
{
return null;
}
var prop = obj.GetProperty<T>(propName);
if (prop != null)
{
return prop;
}
parentId = obj.parentId;
}
return null;
}
}