public void AddPtrRef(ISmartPtr <AssetsObject> ptr) { if (!_knownPointers.Contains(ptr)) { _knownPointers.Add(ptr); } }
private void Parse(AssetsFile assetsFile, AssetsObject owner, AssetsReader reader) { Difficulty = (Difficulty)reader.ReadInt32(); DifficultyRank = reader.ReadInt32(); NoteJumpMovementSpeed = reader.ReadSingle(); NoteJumpStartBeatOffset = reader.ReadInt32(); BeatmapDataPtr = SmartPtr <BeatmapDataObject> .Read(assetsFile, owner, reader); }
protected override void Parse(AssetsReader reader) { base.Parse(reader); PlayerModel = SmartPtr <MonoBehaviourObject> .Read(ObjectInfo.ParentFile, this, reader); ColorA = SmartPtr <MonoBehaviourObject> .Read(ObjectInfo.ParentFile, this, reader); ColorB = SmartPtr <MonoBehaviourObject> .Read(ObjectInfo.ParentFile, this, reader); }
public override void Parse(AssetsReader reader) { base.ParseBase(reader); PackID = reader.ReadString(); PackName = reader.ReadString(); CoverImage = SmartPtr <SpriteObject> .Read(ObjectInfo.ParentFile, this, reader); BeatmapLevelCollection = SmartPtr <BeatmapLevelCollectionObject> .Read(ObjectInfo.ParentFile, this, reader); }
public override void Parse(AssetsReader reader) { base.ParseBase(reader); PlayerModel = SmartPtr <AssetsObject> .Read(ObjectInfo.ParentFile, this, reader); ColorA = SmartPtr <SimpleColorSO> .Read(ObjectInfo.ParentFile, this, reader); ColorB = SmartPtr <SimpleColorSO> .Read(ObjectInfo.ParentFile, this, reader); }
protected override void Parse(AssetsReader reader) { base.Parse(reader); PackID = reader.ReadString(); PackName = reader.ReadString(); CoverImage = SmartPtr <SpriteObject> .Read(ObjectInfo.ParentFile, this, reader); IsPackAlwaysOwned = reader.ReadBoolean(); BeatmapLevelCollection = SmartPtr <BeatmapLevelCollectionObject> .Read(ObjectInfo.ParentFile, this, reader); }
public static void AddObjectToEnum(ISmartPtr <AssetsObject> toAdd, IEnumerable <ISmartPtr <AssetsObject> > target) { var addMethod = target.GetType().GetMethod("Add"); if (addMethod == null) { throw new Exception($"Add method could not be found on type {target.GetType().Name}! The passed object should be a List<>!"); } addMethod.Invoke(target, new object[] { toAdd }); }
public static void Write <T>(this ISmartPtr <T> ptr, AssetsWriter writer) where T : AssetsObject { if (ptr == null) { writer.Write((Int32)0); writer.Write((Int64)0); } else { ptr.WritePtr(writer); } }
protected override void Parse(AssetsReader reader) { base.Parse(reader); LevelID = reader.ReadString(); SongName = reader.ReadString(); SongSubName = reader.ReadString(); SongAuthorName = reader.ReadString(); LevelAuthorName = reader.ReadString(); AudioClip = SmartPtr <AudioClipObject> .Read(ObjectInfo.ParentFile, this, reader); BeatsPerMinute = reader.ReadSingle(); SongTimeOffset = reader.ReadSingle(); Shuffle = reader.ReadSingle(); ShufflePeriod = reader.ReadSingle(); PreviewStartTime = reader.ReadSingle(); PreviewDuration = reader.ReadSingle(); CoverImageTexture2D = SmartPtr <Texture2DObject> .Read(ObjectInfo.ParentFile, this, reader); EnvironmentSceneInfo = SmartPtr <AssetsObject> .Read(ObjectInfo.ParentFile, this, reader); DifficultyBeatmapSets = reader.ReadArrayOf(x => new DifficultyBeatmapSet(ObjectInfo.ParentFile, this, x)); }
private static void ClonePropsInObj(object curObj, AssetsObject parentObj, Dictionary <AssetsObject, AssetsObject> clonedObjects, AssetsFile toFile, List <AssetsObject> addedObjects, List <CloneExclusion> exclusions) { var file = parentObj.ObjectInfo.ParentFile.AssetsFilename; var updateProps = curObj.GetType().GetProperties().ToList(); //remove any array properties that are a string or a value type updateProps.Where(x => x.PropertyType.IsArray && (x.PropertyType.GetElementType().IsValueType || x.PropertyType.GetElementType() == typeof(string))) .ToList().ForEach(x => updateProps.Remove(x)); //look through any properties that are smart pointers, clone their targets and make a new pointer, then remove them from the list of props to update var propsToClone = updateProps.Where(x => typeof(ISmartPtr <AssetsObject>).IsAssignableFrom(x.PropertyType)).ToList(); foreach (var prop in propsToClone) { var baseVal = prop.GetValue(curObj, null); if (baseVal == null) { continue; } var propPtr = (prop.GetValue(curObj, null) as ISmartPtr <AssetsObject>); var propObj = propPtr.Target.Object; AssetsObject assignObject = null; switch (exclusions.GetExclusionMode(propPtr, prop)) { case ExclusionMode.LeaveRef: assignObject = propObj; break; case ExclusionMode.Remove: assignObject = null; Log.LogErr($"WARNING: Cloner is leaving the pointer NULL on property '{curObj.GetType().Name}.{prop.Name}'"); break; default: assignObject = DeepClone(propObj, toFile, addedObjects, clonedObjects, exclusions); break; } prop.SetValue(curObj, ReflectionHelper.MakeTypedPointer(parentObj, assignObject), null); } propsToClone.ForEach(x => updateProps.Remove(x)); //look through any properties that lists of smart pointers, this code isn't ideal because it only actually supports things that have a default indexer // I should clean this up to work better var listsToClone = updateProps.Where(x => typeof(IEnumerable <ISmartPtr <AssetsObject> >).IsAssignableFrom(x.PropertyType)).ToList(); foreach (var listProp in listsToClone) { var listVal = listProp.GetValue(curObj, null) as IEnumerable <ISmartPtr <AssetsObject> >; if (listVal == null) { continue; } if (listProp.PropertyType.IsArray) { Array listArr = (Array)listVal; for (int i = 0; i < listArr.Length; i++) { var ptrVal = listArr.GetValue(i) as ISmartPtr <AssetsObject>; ISmartPtr <AssetsObject> clonedObj = null; switch (exclusions.GetExclusionMode(ptrVal, listProp)) { case ExclusionMode.LeaveRef: clonedObj = listArr.GetValue(i) as ISmartPtr <AssetsObject>; break; case ExclusionMode.Remove: clonedObj = null; break; default: clonedObj = ReflectionHelper.MakeTypedPointer(DeepClone(ptrVal.Target.Object, toFile, addedObjects, clonedObjects, exclusions), parentObj); break; } if (clonedObj == null) { listArr.RemoveAt(i); i--; } else { listArr.SetValue(clonedObj, i); } } } else { var indexerProp = listVal.GetType().GetProperties().Where(x => x.Name == "Item").FirstOrDefault(); if (indexerProp == null) { throw new NotSupportedException($"Couldn't find the default indexer property on {curObj.GetType().Name}.{listProp.Name}!"); } for (int i = 0; i < listVal.Count(); i++) { var ptrVal = indexerProp.GetValue(listVal, new object[] { i }) as ISmartPtr <AssetsObject>; AssetsObject clonedObj = null; switch (exclusions.GetExclusionMode(ptrVal, listProp)) { case ExclusionMode.LeaveRef: clonedObj = ptrVal.Target.Object; break; case ExclusionMode.Remove: clonedObj = null; break; default: clonedObj = DeepClone(ptrVal.Target.Object, toFile, addedObjects, clonedObjects, exclusions); break; } //if the cloned object comes back null, remove it from the list instead of setting it null if (clonedObj == null) { ReflectionHelper.InvokeRemoveAt(listVal, i); } else { indexerProp.SetValue(listVal, ReflectionHelper.MakeTypedPointer(parentObj as AssetsObject, clonedObj), new object[] { i }); } } } } listsToClone.ForEach(x => updateProps.Remove(x)); //look through any objects that are plain old lists of whatever. this is to catch lists of "structs" that may have pointers in them var plainEnumerableToClone = updateProps.Where(x => !x.PropertyType.IsValueType && !(x.PropertyType == typeof(string)) && typeof(IEnumerable).IsAssignableFrom(x.PropertyType)).ToList(); foreach (var enumProp in plainEnumerableToClone) { var listVal = enumProp.GetValue(curObj, null) as IEnumerable; if (listVal == null) { continue; } foreach (var plainObj in listVal) { //pass in the parent AssetsObject that was passed to us since that object will be the "owner", not the struct object ClonePropsInObj(plainObj, parentObj, clonedObjects, toFile, addedObjects, exclusions); } } plainEnumerableToClone.ForEach(x => updateProps.Remove(x)); //look through any "struct" type properties that may have pointers in them var plainObjToClone = updateProps.Where(x => !x.PropertyType.IsValueType && !(x.PropertyType == typeof(string))); foreach (var plainProp in plainObjToClone) { var objVal = plainProp.GetValue(curObj, null) as IEnumerable; if (objVal == null) { continue; } foreach (var plainObj in objVal) { //pass in the parent AssetsObject that was passed to us since that object will be the "owner", not the struct object ClonePropsInObj(plainObj, parentObj, clonedObjects, toFile, addedObjects, exclusions); } } }
public void RemovePtrRef(ISmartPtr <AssetsObject> ptr) { _knownPointers.Remove(ptr); }
public static RawPtr ToRawPtr <T>(this ISmartPtr <T> ptr) where T : AssetsObject { return(new RawPtr(ptr.FileID, ptr.PathID)); }
public static void AssignPtrToPropName(object targetObject, string targetPropName, ISmartPtr <AssetsObject> ptr) { var prop = targetObject.GetType().GetProperty(targetPropName); if (prop == null) { throw new Exception($"Couldn't find property {targetPropName} on type {targetObject.GetType().Name}."); } prop.SetValue(targetObject, ptr, null); }
public static Node MakeNode(object o, int depth = 0, Dictionary <object, Node> trackedObjects = null) { if (trackedObjects == null) { trackedObjects = new Dictionary <object, Node>(); } else { depth += 1; } Node node = null; if (o == null) { node = new Node() { Text = "(null)", TypeName = null, Obj = null, Depth = depth }; return(node); } Type t = o.GetType(); if (typeof(IObjectInfo <AssetsObject>).IsAssignableFrom(t)) { o = (o as IObjectInfo <AssetsObject>).Object; t = o.GetType(); } node = new Node(o, depth); if (!t.IsValueType && t != typeof(string) && !(t.IsArray && (t.GetElementType().IsValueType || t.GetElementType() == typeof(string))) && trackedObjects.ContainsKey(o)) { var otherNode = trackedObjects[o]; node.Text = ""; node.StubToNode = otherNode; if (otherNode.Depth > depth) { node.Depth = otherNode.Depth; node.Parent = otherNode.Parent; node.ParentPropertyName = otherNode.ParentPropertyName; int otherIndex = otherNode.Parent.Nodes.IndexOf(otherNode); otherNode.Parent.Nodes.RemoveAt(otherIndex); otherNode.Parent.Nodes.Insert(otherIndex, node); otherNode.Depth = depth; otherNode.Parent = null; node = otherNode; } return(node); } else { if (!t.IsValueType && t != typeof(string) && !(t.IsArray && (t.GetElementType().IsValueType || t.GetElementType() == typeof(string)))) { trackedObjects.Add(o, node); } } string nodeName1; string typeName1; MakeNodeAndTypeName(o, out nodeName1, out typeName1); node.Set(nodeName1, typeName1); if (typeof(ISmartPtr <AssetsObject>).IsAssignableFrom(t)) { ISmartPtr <AssetsObject> ptr = o as ISmartPtr <AssetsObject>; var targetNode = MakeNode(ptr.Target.Object, depth, trackedObjects); //targetNode.Text = targetNode.Text; //targetNode.TypeName = o.GetType().GetGenericArguments()[0].Name; node.AddNode(targetNode); } else if (typeof(IEnumerable).IsAssignableFrom(t)) { int i = 0; foreach (object obj in o as IEnumerable) { Node childNode = MakeNode(obj, depth, trackedObjects); childNode.Text = $"{("[" + i.ToString() + "]").PadRight(3)} {childNode?.Text}"; node.AddNode(childNode); i++; } } else if (t.GetProperties().Count() > 0) { List <PropertyInfo> props = new List <PropertyInfo>(t.GetProperties()); foreach (PropertyInfo prop in props) { object propValue = null; try { //filters just to stop the exceptions, even though they're handled if (!(prop.Name == "Data" && o.GetType() != typeof(AssetsObject)) && !(prop.Name == "ScriptParametersData" && o.GetType() != typeof(MonoBehaviourObject))) { propValue = prop.GetValue(o, null); } } catch (Exception ex) { QuestomAssets.Log.LogErr($"Failed loading property {prop.Name} on object type {o.GetType().Name}", ex); node.AddNode(new Node() { Text = $"{prop.Name}: (Inaccessible)", TypeName = "", Depth = depth, ParentPropertyName = prop.Name }); continue; } if (propValue != null && typeof(IObjectInfo <AssetsObject>).IsAssignableFrom(propValue.GetType()) && prop.Name == nameof(AssetsObject.ObjectInfo)) { continue; } if (prop.PropertyType.IsValueType || prop.PropertyType == typeof(string) || (prop.PropertyType.IsArray && (prop.PropertyType.GetElementType().IsValueType || prop.PropertyType.GetElementType() == typeof(string)))) { continue; } var childNode = MakeNode(propValue, depth, trackedObjects); childNode.ParentPropertyName = prop.Name; //stupid place for this if (typeof(IEnumerable).IsAssignableFrom(propValue?.GetType())) { foreach (Node n in childNode.Nodes) { if (string.IsNullOrWhiteSpace(n.ParentPropertyName)) { n.ParentPropertyName = prop.Name; } } } if (string.IsNullOrEmpty(childNode.Text)) { childNode.Text = $"{prop.Name}: {propValue?.GetType()?.Name ?? "((null)"}"; } else { childNode.Text = $"{prop.Name}: {childNode.Text}"; } node.AddNode(childNode); } } else { node.Set($"{o}", t.Name); } return(node); }
public static void MakeNodeAndTypeName(object o, out string nodeName, out string typeName) { Type t = o.GetType(); if (typeof(IObjectInfo <AssetsObject>).IsAssignableFrom(t)) { o = (o as IObjectInfo <AssetsObject>).Object; t = o.GetType(); } if (t.IsValueType) { nodeName = $"{o}"; typeName = t.Name; } else if (t == typeof(string)) { nodeName = $"\"{o}\""; typeName = t.Name; } else if (t.IsArray && (t.GetElementType().IsValueType || t.GetElementType() == typeof(string))) { nodeName = $"{o}"; typeName = t.Name; } else if (typeof(ISmartPtr <AssetsObject>).IsAssignableFrom(t)) { ISmartPtr <AssetsObject> ptr = o as ISmartPtr <AssetsObject>; nodeName = $"PtrTo F:{ptr.FileID} P:{ptr.PathID} ({o.GetType().GetGenericArguments()[0].Name})"; typeName = o.GetType().GetGenericArguments()[0].Name; } else if (typeof(IEnumerable).IsAssignableFrom(t)) { int i = 0; var thisNodeName = ""; if (t.IsGenericType) { thisNodeName = "[List<"; //half assed, only 1 generic arg to keep it simple var genArg = t.GetGenericArguments()[0]; if (genArg.IsGenericType) { thisNodeName += genArg.GetGenericTypeDefinition().Name; thisNodeName = thisNodeName.Substring(0, thisNodeName.LastIndexOf('`')); thisNodeName += "<"; thisNodeName += genArg.GetGenericArguments()[0].Name; thisNodeName += ">"; //nodeName = nodeName.Substring(0, nodeName.Length - 1); //nodeName += string.Join(", ", t.GetGenericArguments().Select(x => x.Name)); //nodeName += ">"; } else { thisNodeName += genArg.Name; } thisNodeName += ">]"; } else { thisNodeName = "[List]"; } nodeName = thisNodeName; typeName = t.Name; } else if (t.GetProperties().Count() > 0) { if (typeof(AssetsObject).IsAssignableFrom(t)) { var ao = o as AssetsObject; nodeName = $"{ao.ObjectInfo.ObjectID,5} {t.Name} {((o is IHaveName) ? (": " + (o as IHaveName)?.Name) : "")}"; typeName = ao.GetType().Name; } else { nodeName = o.GetType().Name; typeName = o.GetType().Name; } } else { nodeName = $"{o}"; typeName = t.Name; } }
public static Node MakeNode(object o, int depth = 0, Dictionary <object, Node> trackedObjects = null) { if (trackedObjects == null) { trackedObjects = new Dictionary <object, Node>(); } else { depth += 1; } Node node = null; if (o == null) { node = new Node() { Text = "(null)", TypeName = null, Obj = null, Depth = depth }; return(node); } Type t = o.GetType(); if (typeof(IObjectInfo <AssetsObject>).IsAssignableFrom(t)) { o = (o as IObjectInfo <AssetsObject>).Object; t = o.GetType(); } node = new Node(o, depth); if (!t.IsValueType && t != typeof(string) && !(t.IsArray && (t.GetElementType().IsValueType || t.GetElementType() == typeof(string))) && trackedObjects.ContainsKey(o)) { var otherNode = trackedObjects[o]; node.Text = ""; node.StubToNode = otherNode; if (otherNode.Depth > depth) { node.Depth = otherNode.Depth; node.Parent = otherNode.Parent; node.ParentPropertyName = otherNode.ParentPropertyName; int otherIndex = otherNode.Parent.Nodes.IndexOf(otherNode); otherNode.Parent.Nodes.RemoveAt(otherIndex); otherNode.Parent.Nodes.Insert(otherIndex, node); otherNode.Depth = depth; otherNode.Parent = null; node = otherNode; } return(node); } else { if (!t.IsValueType && t != typeof(string) && !(t.IsArray && (t.GetElementType().IsValueType || t.GetElementType() == typeof(string)))) { trackedObjects.Add(o, node); } } if (t.IsValueType) { node.Set($"{o}", t.Name); } else if (t == typeof(string)) { node.Set($"\"{o}\"", t.Name); } else if (t.IsArray && (t.GetElementType().IsValueType || t.GetElementType() == typeof(string))) { node.Set($"{o}", t.Name); } else if (typeof(ISmartPtr <AssetsObject>).IsAssignableFrom(t)) { ISmartPtr <AssetsObject> ptr = o as ISmartPtr <AssetsObject>; node.Set($"PtrTo F:{ptr.FileID} P:{ptr.PathID} ({o.GetType().GetGenericArguments()[0].Name})", o.GetType().GetGenericArguments()[0].Name); var targetNode = MakeNode(ptr.Target.Object, depth, trackedObjects); //targetNode.Text = targetNode.Text; //targetNode.TypeName = o.GetType().GetGenericArguments()[0].Name; node.AddNode(targetNode); } else if (typeof(IEnumerable).IsAssignableFrom(t)) { int i = 0; var nodeName = ""; if (t.IsGenericType) { nodeName = "[List<"; //half assed, only 1 generic arg to keep it simple var genArg = t.GetGenericArguments()[0]; if (genArg.IsGenericType) { nodeName += genArg.GetGenericTypeDefinition().Name; nodeName = nodeName.Substring(0, nodeName.LastIndexOf('`')); nodeName += "<"; nodeName += genArg.GetGenericArguments()[0].Name; nodeName += ">"; //nodeName = nodeName.Substring(0, nodeName.Length - 1); //nodeName += string.Join(", ", t.GetGenericArguments().Select(x => x.Name)); //nodeName += ">"; } else { nodeName += genArg.Name; } nodeName += ">]"; } else { nodeName = "[List]"; } node.Set(nodeName, t.Name); foreach (object obj in o as IEnumerable) { Node childNode = MakeNode(obj, depth, trackedObjects); childNode.Text = $"{("[" + i.ToString() + "]").PadRight(3)} {childNode?.Text}"; node.AddNode(childNode); i++; } } else if (t.GetProperties().Count() > 0) { if (typeof(AssetsObject).IsAssignableFrom(t)) { var ao = o as AssetsObject; node.Set($"{ao.ObjectInfo.ObjectID,5} {t.Name} {((o is IHaveName) ? (": " + (o as IHaveName)?.Name) : "")}", ao.GetType().Name); } else { node.Set(o.GetType().Name, o.GetType().Name); } List <PropertyInfo> props = new List <PropertyInfo>(t.GetProperties()); foreach (PropertyInfo prop in props) { object propValue = null; try { //filters just to stop the exceptions, even though they're handled if (!(prop.Name == "Data" && o.GetType() != typeof(AssetsObject)) && !(prop.Name == "ScriptParametersData" && o.GetType() != typeof(MonoBehaviourObject))) { propValue = prop.GetValue(o, null); } } catch (Exception ex) { QuestomAssets.Log.LogErr($"Failed loading property {prop.Name} on object type {o.GetType().Name}", ex); node.AddNode(new Node() { Text = $"{prop.Name}: (Inaccessible)", TypeName = "", Depth = depth, ParentPropertyName = prop.Name }); continue; } if (propValue != null && typeof(IObjectInfo <AssetsObject>).IsAssignableFrom(propValue.GetType()) && prop.Name == nameof(AssetsObject.ObjectInfo)) { continue; } var childNode = MakeNode(propValue, depth, trackedObjects); childNode.ParentPropertyName = prop.Name; //stupid place for this if (typeof(IEnumerable).IsAssignableFrom(propValue?.GetType())) { foreach (Node n in childNode.Nodes) { if (string.IsNullOrWhiteSpace(n.ParentPropertyName)) { n.ParentPropertyName = prop.Name; } } } if (string.IsNullOrEmpty(childNode.Text)) { childNode.Text = $"{prop.Name}: {propValue?.GetType()?.Name ?? "((null)"}"; } else { childNode.Text = $"{prop.Name}: {childNode.Text}"; } node.AddNode(childNode); } } else { node.Set($"{o}", t.Name); } return(node); }