using KeepersCompound.LGS.Database.Chunks; namespace KeepersCompound.LGS.Database; public class ObjectHierarchy { private class DarkObject { public int objectId; public int parentId; public Dictionary properties; public DarkObject(int id) { objectId = id; parentId = 0; properties = new Dictionary(); } public T? GetProperty(string propName) where T : Property { if (properties.TryGetValue(propName, out var prop)) { return (T)prop; } return null; } } private Dictionary _objects; public ObjectHierarchy(DbFile db, DbFile gam = null) { _objects = new Dictionary(); T GetMergedChunk(string name) where T : IMergable { if (!db.TryGetChunk(name, out var chunk)) { throw new ArgumentException($"No chunk with name ({name}) found", nameof(name)); } if (gam != null && gam.TryGetChunk(name, out var gamChunk)) { gamChunk.Merge(chunk); return gamChunk; } return chunk; } // Add parentages var metaPropLinks = GetMergedChunk("L$MetaProp"); var metaPropLinkData = GetMergedChunk("LD$MetaProp"); 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 AddProp(string name) where T : Property, new() { var chunk = GetMergedChunk>(name); foreach (var prop in chunk.properties) { var id = prop.objectId; if (!_objects.TryGetValue(id, out var value)) { value = new DarkObject(id); _objects.Add(id, value); } value.properties.TryAdd(name, prop); } } AddProp("P$ModelName"); AddProp("P$Scale"); AddProp("P$RenderTyp"); AddProp("P$JointPos"); AddProp("P$Immobile"); AddProp("P$StatShad"); AddProp("P$OTxtRepr0"); AddProp("P$OTxtRepr1"); AddProp("P$OTxtRepr2"); AddProp("P$OTxtRepr3"); AddProp("P$RenderAlp"); AddProp("P$Light"); AddProp("P$AnimLight"); AddProp("P$LightColo"); AddProp("P$Spotlight"); AddProp("P$SpotAmb"); } // TODO: Work out if there's some nice way to automatically decide if we inherit public T? GetProperty(int objectId, string propName, bool inherit = true) 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(propName); if (prop != null || !inherit) { return prop; } parentId = obj.parentId; } return null; } }