public InterpCurve(IMEPackage _pcc, PropertyReader.Property p) { pcc = _pcc; Curves = new ObservableCollection<Curve>(); Name = pcc.getNameEntry(p.Name); curveType = (CurveType)Enum.Parse(typeof(CurveType), pcc.getNameEntry(p.Value.IntValue)); float InVal = 0f; CurveMode InterpMode = CurveMode.CIM_Linear; var points = PropertyReader.ReadStructArrayProp(pcc, PropertyReader.getPropOrNull(pcc, p.raw, 32, "Points")); switch (curveType) { case CurveType.InterpCurveQuat: throw new NotImplementedException($"InterpCurveQuat has not been implemented yet."); case CurveType.InterpCurveFloat: float OutVal = 0f; float ArriveTangent = 0f; float LeaveTangent = 0f; LinkedList<CurvePoint> vals = new LinkedList<CurvePoint>(); foreach (var point in points) { foreach (var prop in point) { switch (pcc.getNameEntry(prop.Name)) { case "InVal": InVal = BitConverter.ToSingle(prop.raw, 24); break; case "OutVal": OutVal = BitConverter.ToSingle(prop.raw, 24); break; case "ArriveTangent": ArriveTangent = BitConverter.ToSingle(prop.raw, 24); break; case "LeaveTangent": LeaveTangent = BitConverter.ToSingle(prop.raw, 24); break; case "InterpMode": InterpMode = (CurveMode)Enum.Parse(typeof(CurveMode), pcc.getNameEntry(prop.Value.IntValue)); break; default: break; } } vals.AddLast(new CurvePoint(InVal, OutVal, ArriveTangent, LeaveTangent, InterpMode)); } Curves.Add(new Curve("X", vals)); break; case CurveType.InterpCurveVector: Vector OutValVec = new Vector(0, 0, 0); Vector ArriveTangentVec = new Vector(0, 0, 0); Vector LeaveTangentVec = new Vector(0, 0, 0); LinkedList<CurvePoint> x = new LinkedList<CurvePoint>(); LinkedList<CurvePoint> y = new LinkedList<CurvePoint>(); LinkedList<CurvePoint> z = new LinkedList<CurvePoint>(); foreach (var point in points) { foreach (var prop in point) { switch (pcc.getNameEntry(prop.Name)) { case "InVal": InVal = BitConverter.ToSingle(prop.raw, 24); break; case "OutVal": OutValVec = GetVector(prop); break; case "ArriveTangent": ArriveTangentVec = GetVector(prop); break; case "LeaveTangent": LeaveTangentVec = GetVector(prop); break; case "InterpMode": InterpMode = (CurveMode)Enum.Parse(typeof(CurveMode), pcc.getNameEntry(prop.Value.IntValue)); break; default: break; } } x.AddLast(new CurvePoint(InVal, OutValVec.X, ArriveTangentVec.X, LeaveTangentVec.X, InterpMode)); y.AddLast(new CurvePoint(InVal, OutValVec.Y, ArriveTangentVec.Y, LeaveTangentVec.Y, InterpMode)); z.AddLast(new CurvePoint(InVal, OutValVec.Z, ArriveTangentVec.Z, LeaveTangentVec.Z, InterpMode)); } if (Name == "EulerTrack") { Curves.Add(new Curve("Roll", x)); Curves.Add(new Curve("Pitch", y)); Curves.Add(new Curve("Yaw", z)); } else { Curves.Add(new Curve("X", x)); Curves.Add(new Curve("Y", y)); Curves.Add(new Curve("Z", z)); } break; case CurveType.InterpCurveVector2D: throw new NotImplementedException($"InterpCurveVector2D has not been implemented yet."); case CurveType.InterpCurveTwoVectors: throw new NotImplementedException($"InterpCurveTwoVectors has not been implemented yet."); case CurveType.InterpCurveLinearColor: throw new NotImplementedException($"InterpCurveLinearColor has not been implemented yet."); default: break; } foreach (var curve in Curves) { curve.SharedValueChanged += Curve_SharedValueChanged; curve.ListModified += Curve_ListModified; } }
private static Vector GetVector(PropertyReader.Property prop) { Vector vec; vec.X = BitConverter.ToSingle(prop.raw, 32); vec.Y = BitConverter.ToSingle(prop.raw, 36); vec.Z = BitConverter.ToSingle(prop.raw, 40); return vec; }
public static byte[] getDefaultClassValue(ME3Package pcc, string className, bool fullProps = false) { if (Structs.ContainsKey(className)) { bool immutable = isImmutable(className); ClassInfo info = Structs[className]; try { string filepath = (Path.Combine(ME3Directory.gamePath, @"BIOGame\" + info.pccPath)); if (File.Exists(info.pccPath)) { filepath = info.pccPath; //Used for dynamic lookup } using (ME3Package importPCC = MEPackageHandler.OpenME3Package(filepath)) { byte[] buff; //Plane and CoverReference inherit from other structs, meaning they don't have default values (who knows why) //thus, I have hardcoded what those default values should be if (className == "Plane") { buff = PlaneDefault; } else if (className == "CoverReference") { buff = CoverReferenceDefault; } else { buff = importPCC.Exports[info.exportIndex].Data.Skip(0x24).ToArray(); } List <PropertyReader.Property> Props = PropertyReader.ReadProp(importPCC, buff, 0); MemoryStream m = new MemoryStream(); foreach (PropertyReader.Property p in Props) { string propName = importPCC.getNameEntry(p.Name); //check if property is transient, if so, skip (neither of the structs that inherit have transient props) if (info.properties.ContainsKey(propName) || propName == "None" || info.baseClass != "Class") { if (immutable && !fullProps) { PropertyReader.ImportImmutableProperty(pcc, importPCC, p, className, m, true); } else { PropertyReader.ImportProperty(pcc, importPCC, p, className, m, true); } } } return(m.ToArray()); } } catch (Exception) { return(null); } } else if (Classes.ContainsKey(className)) { ClassInfo info = Structs[className]; try { string filepath = (Path.Combine(ME3Directory.gamePath, @"BIOGame\" + info.pccPath)); if (File.Exists(info.pccPath)) { filepath = info.pccPath; //Used for dynamic lookup } using (ME3Package importPCC = MEPackageHandler.OpenME3Package(filepath)) { IExportEntry entry = pcc.Exports[info.exportIndex + 1]; List <PropertyReader.Property> Props = PropertyReader.getPropList(entry); MemoryStream m = new MemoryStream(entry.DataSize - 4); foreach (PropertyReader.Property p in Props) { if (!info.properties.ContainsKey(importPCC.getNameEntry(p.Name))) { //property is transient continue; } PropertyReader.ImportProperty(pcc, importPCC, p, className, m); } return(m.ToArray()); } } catch (Exception) { return(null); } } return(null); }
public static InterpCurveVector GetCurveVector(PropertyReader.Property p, PCCObject pcc) { InterpCurveVector vec = new InterpCurveVector(); vec.Points = new List<InterpCurvePointVector>(); int pos = 60; int count = BitConverter.ToInt32(p.raw, 56); for (int j = 0; j < count; j++) { List<PropertyReader.Property> p2 = PropertyReader.ReadProp(pcc, p.raw, pos); InterpCurvePointVector point = new InterpCurvePointVector(); for (int i = 0; i < p2.Count(); i++) { if (pcc.getNameEntry(p2[i].Name) == "InVal") point.InVal = BitConverter.ToSingle(p2[i].raw, 24); else if (pcc.getNameEntry(p2[i].Name) == "OutVal") { point.OutVal.x = BitConverter.ToSingle(p2[i].raw, 32); point.OutVal.y = BitConverter.ToSingle(p2[i].raw, 36); point.OutVal.z = BitConverter.ToSingle(p2[i].raw, 40); } else if (pcc.getNameEntry(p2[i].Name) == "ArriveTangent") { point.ArriveTangent.x = BitConverter.ToSingle(p2[i].raw, 32); point.ArriveTangent.y = BitConverter.ToSingle(p2[i].raw, 36); point.ArriveTangent.z = BitConverter.ToSingle(p2[i].raw, 40); } else if (pcc.getNameEntry(p2[i].Name) == "LeaveTangent") { point.LeaveTangent.x = BitConverter.ToSingle(p2[i].raw, 32); point.LeaveTangent.y = BitConverter.ToSingle(p2[i].raw, 36); point.LeaveTangent.z = BitConverter.ToSingle(p2[i].raw, 40); } else if (pcc.getNameEntry(p2[i].Name) == "InterpMode") point.InterpMode = new byteprop(p2[i].raw, "EInterpCurveMode", new string[] { "CIM_Linear", "CIM_CurveAuto", "CIM_Constant", "CIM_CurveUser", "CIM_CurveBreak", "CIM_CurveAutoClamped"}); pos += p2[i].raw.Length; } vec.Points.Add(point); } return vec; }
public static InterpCurveFloat GetCurveFloat(PropertyReader.Property p, ME3Package pcc) { InterpCurveFloat CurveFloat = new InterpCurveFloat(); CurveFloat.Points = new List<InterpCurvePointFloat>(); int pos = 60; int count = BitConverter.ToInt32(p.raw, 56); for (int j = 0; j < count; j++) { List<PropertyReader.Property> p2 = PropertyReader.ReadProp(pcc, p.raw, pos); InterpCurvePointFloat point = new InterpCurvePointFloat(); for (int i = 0; i < p2.Count(); i++) { if (pcc.getNameEntry(p2[i].Name) == "InVal") point.InVal = BitConverter.ToSingle(p2[i].raw, 24); else if (pcc.getNameEntry(p2[i].Name) == "OutVal") { point.OutVal = BitConverter.ToSingle(p2[i].raw, 24); } else if (pcc.getNameEntry(p2[i].Name) == "ArriveTangent") { point.ArriveTangent = BitConverter.ToSingle(p2[i].raw, 24); } else if (pcc.getNameEntry(p2[i].Name) == "LeaveTangent") { point.LeaveTangent = BitConverter.ToSingle(p2[i].raw, 24); } else if (pcc.getNameEntry(p2[i].Name) == "InterpMode") point.InterpMode = new byteprop(p2[i].raw, "EInterpCurveMode", new string[] { "CIM_Linear", "CIM_CurveAuto", "CIM_Constant", "CIM_CurveUser", "CIM_CurveBreak", "CIM_CurveAutoClamped" }); pos += p2[i].raw.Length; } CurveFloat.Points.Add(point); } return CurveFloat; }
public static void propGridPropertyValueChanged(PropertyValueChangedEventArgs e, int n, IMEPackage pcc) { string name = e.ChangedItem.Label; GridItem parent = e.ChangedItem.Parent; //if (parent != null) name = parent.Label; if (parent.Label == "data") { GridItem parent2 = parent.Parent; if (parent2 != null) { name = parent2.Label; } } Type parentVal = null; if (parent.Value != null) { parentVal = parent.Value.GetType(); } if (name == "nameindex" || name == "index" || parentVal == typeof(ColorProp) || parentVal == typeof(VectorProp) || parentVal == typeof(Unreal.RotatorProp) || parentVal == typeof(Unreal.LinearColorProp)) { name = parent.Label; } IExportEntry ent = pcc.getExport(n); byte[] data = ent.Data; List <PropertyReader.Property> p = PropertyReader.getPropList(ent); int m = -1; for (int i = 0; i < p.Count; i++) { if (pcc.getNameEntry(p[i].Name) == name) { m = i; } } if (m == -1) { return; } byte[] buff2; switch (p[m].TypeVal) { case PropertyType.BoolProperty: byte res = 0; if ((bool)e.ChangedItem.Value == true) { res = 1; } data[p[m].offsetval] = res; break; case PropertyType.FloatProperty: buff2 = BitConverter.GetBytes((float)e.ChangedItem.Value); for (int i = 0; i < 4; i++) { data[p[m].offsetval + i] = buff2[i]; } break; case PropertyType.IntProperty: case PropertyType.StringRefProperty: int newv = Convert.ToInt32(e.ChangedItem.Value); int oldv = Convert.ToInt32(e.OldValue); buff2 = BitConverter.GetBytes(newv); for (int i = 0; i < 4; i++) { data[p[m].offsetval + i] = buff2[i]; } break; case PropertyType.StrProperty: string s = Convert.ToString(e.ChangedItem.Value); int stringMultiplier = 1; int oldLength = BitConverter.ToInt32(data, p[m].offsetval); if (oldLength < 0) { stringMultiplier = 2; oldLength *= -2; } int oldSize = 4 + oldLength; List <byte> stringBuff = new List <byte>(s.Length * stringMultiplier); if (stringMultiplier == 2) { for (int j = 0; j < s.Length; j++) { stringBuff.AddRange(BitConverter.GetBytes(s[j])); } stringBuff.Add(0); } else { for (int j = 0; j < s.Length; j++) { stringBuff.Add(BitConverter.GetBytes(s[j])[0]); } } stringBuff.Add(0); buff2 = BitConverter.GetBytes((s.Length + 1) * stringMultiplier + 4); for (int j = 0; j < 4; j++) { data[p[m].offsetval - 8 + j] = buff2[j]; } buff2 = BitConverter.GetBytes((s.Length + 1) * stringMultiplier == 1 ? 1 : -1); for (int j = 0; j < 4; j++) { data[p[m].offsetval + j] = buff2[j]; } buff2 = new byte[data.Length - oldLength + stringBuff.Count]; int startLength = p[m].offsetval + 4; int startLength2 = startLength + oldLength; for (int i = 0; i < startLength; i++) { buff2[i] = data[i]; } for (int i = 0; i < stringBuff.Count; i++) { buff2[i + startLength] = stringBuff[i]; } startLength += stringBuff.Count; for (int i = 0; i < data.Length - startLength2; i++) { buff2[i + startLength] = data[i + startLength2]; } data = buff2; break; case PropertyType.StructProperty: if (e.ChangedItem.Label != "nameindex" && parentVal == typeof(ColorProp)) { switch (e.ChangedItem.Label) { case "Alpha": data[p[m].offsetval + 11] = Convert.ToByte(e.ChangedItem.Value); break; case "Red": data[p[m].offsetval + 10] = Convert.ToByte(e.ChangedItem.Value); break; case "Green": data[p[m].offsetval + 9] = Convert.ToByte(e.ChangedItem.Value); break; case "Blue": data[p[m].offsetval + 8] = Convert.ToByte(e.ChangedItem.Value); break; default: break; } } else if (e.ChangedItem.Label != "nameindex" && parentVal == typeof(VectorProp)) { int offset = 0; switch (e.ChangedItem.Label) { case "X": offset = 8; break; case "Y": offset = 12; break; case "Z": offset = 16; break; default: break; } if (offset != 0) { buff2 = BitConverter.GetBytes(Convert.ToSingle(e.ChangedItem.Value)); for (int i = 0; i < 4; i++) { data[p[m].offsetval + offset + i] = buff2[i]; } } } else if (e.ChangedItem.Label != "nameindex" && parentVal == typeof(Unreal.RotatorProp)) { int offset = 0; switch (e.ChangedItem.Label) { case "Pitch": offset = 8; break; case "Yaw": offset = 12; break; case "Roll": offset = 16; break; default: break; } if (offset != 0) { int val = Convert.ToSingle(e.ChangedItem.Value).ToUnrealRotationUnits(); buff2 = BitConverter.GetBytes(val); for (int i = 0; i < 4; i++) { data[p[m].offsetval + offset + i] = buff2[i]; } } } else if (e.ChangedItem.Label != "nameindex" && parentVal == typeof(Unreal.LinearColorProp)) { int offset = 0; switch (e.ChangedItem.Label) { case "Red": offset = 8; break; case "Green": offset = 12; break; case "Blue": offset = 16; break; case "Alpha": offset = 20; break; default: break; } if (offset != 0) { buff2 = BitConverter.GetBytes(Convert.ToSingle(e.ChangedItem.Value)); for (int i = 0; i < 4; i++) { data[p[m].offsetval + offset + i] = buff2[i]; } } } else if (e.ChangedItem.Value is int) { int val = Convert.ToInt32(e.ChangedItem.Value); if (e.ChangedItem.Label == "nameindex") { int val1 = Convert.ToInt32(e.ChangedItem.Value); buff2 = BitConverter.GetBytes(val1); for (int i = 0; i < 4; i++) { data[p[m].offsetval + i] = buff2[i]; } } else { string sidx = e.ChangedItem.Label.Replace("[", ""); sidx = sidx.Replace("]", ""); int index = Convert.ToInt32(sidx); buff2 = BitConverter.GetBytes(val); for (int i = 0; i < 4; i++) { data[p[m].offsetval + i + index * 4 + 8] = buff2[i]; } } } break; case PropertyType.ByteProperty: case PropertyType.NameProperty: if (e.ChangedItem.Value is int) { int val = Convert.ToInt32(e.ChangedItem.Value); buff2 = BitConverter.GetBytes(val); for (int i = 0; i < 4; i++) { data[p[m].offsetval + i] = buff2[i]; } } break; case PropertyType.ObjectProperty: if (e.ChangedItem.Value is int) { int val = Convert.ToInt32(e.ChangedItem.Value); buff2 = BitConverter.GetBytes(val); for (int i = 0; i < 4; i++) { data[p[m].offsetval + i] = buff2[i]; } } break; default: return; } ent.Data = data; }