public SplinePoint0Node(int idx, float x, float y, IMEPackage p, PathingGraphEditor grapheditor) : base(idx, p, grapheditor) { StructProperty splineInfo = export.GetProperty <StructProperty>("SplineInfo"); if (splineInfo != null) { var pointsProp = splineInfo.GetProp <ArrayProperty <StructProperty> >("Points"); StructProperty point0 = pointsProp[0]; StructProperty point1 = pointsProp[1]; a = CommonStructs.GetVector2(point0.GetProp <StructProperty>("OutVal")); tan1 = CommonStructs.GetVector2(point0.GetProp <StructProperty>("LeaveTangent")); tan2 = CommonStructs.GetVector2(point1.GetProp <StructProperty>("ArriveTangent")); d = CommonStructs.GetVector2(point1.GetProp <StructProperty>("OutVal")); const float w = 25; const float h = 25; shape = PPath.CreateEllipse(0, 0, w, h); outlinePen = new Pen(color); shape.Pen = outlinePen; shape.Brush = pathfindingNodeBrush; shape.Pickable = false; this.AddChild(shape); this.Bounds = new RectangleF(0, 0, w, h); SText val = new SText($"{export.Index}\nSpline Start"); val.Pickable = false; val.TextAlignment = StringAlignment.Center; val.X = w / 2 - val.Width / 2; val.Y = h / 2 - val.Height / 2; this.AddChild(val); this.TranslateBy(x, y); } }
public SplineActorNode(int idx, float x, float y, IMEPackage p, PathingGraphEditor grapheditor) : base(idx, p, grapheditor) { var splprop = export.GetProperty <ArrayProperty <StructProperty> >("Connections"); if (splprop != null) { foreach (var prop in splprop) { var spcomp = prop.GetProp <ObjectProperty>("SplineComponent"); var cmpidx = spcomp?.Value ?? 0; var cntcomp = prop.GetProp <ObjectProperty>("ConnectTo"); pcc.TryGetUExport(cntcomp?.Value ?? 0, out ExportEntry cnctn); if (spcomp != null && cmpidx > 0) { var component = pcc.GetUExport(cmpidx); var spline = new Spline(component, grapheditor, cnctn); Splines.Add(spline); spline.Pickable = false; g.nodeLayer.AddChild(spline); } connections.Add(cnctn); } } Vector3 tangent = CommonStructs.GetVector3(export, "SplineActorTangent", new Vector3(300f, 0f, 0f)); //(float controlPointX, float controlPointY, _) = tangent; (float controlPointX, float controlPointY, float controlPointZ) = ActorUtils.GetLocalToWorld(export).TransformNormal(tangent); LeaveTangentControlNode = new SplinePointControlNode(this, controlPointX, controlPointY, controlPointZ, UpdateMode.LeaveTangent); ArriveTangentControlNode = new SplinePointControlNode(this, -controlPointX, -controlPointY, controlPointZ, UpdateMode.ArriveTangent); AddChild(LeaveTangentControlNode); AddChild(ArriveTangentControlNode); shape = PPath.CreatePolygon(edgeShape); outlinePen = new Pen(color); shape.Pen = outlinePen; shape.Brush = splineNodeBrush; shape.Pickable = false; AddChild(shape); float w = shape.Width; float h = shape.Height; Bounds = new RectangleF(0, 0, w, h); SText val = new SText(idx.ToString()) { Pickable = false, TextAlignment = StringAlignment.Center }; val.X = w / 2 - val.Width / 2; val.Y = h / 2 - val.Height / 2; AddChild(val); SetOffset(x, y); }
public static void GenerateNewNavGUID(ExportEntry export) { StructProperty guidProp = export.GetProperty <StructProperty>("NavGuid"); if (guidProp != null) { export.WriteProperty(CommonStructs.GuidProp(Guid.NewGuid(), "NavGuid")); } }
public static void SetLocation(ExportEntry export, float x, float y, float z) { if (export.ClassName.Contains("Component")) { SetCollectionActorLocation(export, x, y, z); } else { export.WriteProperty(CommonStructs.Vector3Prop(x, y, z, "location")); } }
StructProperty ISpec <Vector3> .ToStructProperty(InterpCurvePoint <Vector3> icp, MEGame game) { return(new StructProperty("InterpCurvePointVector", new PropertyCollection { new FloatProperty(icp.InVal, "InVal"), CommonStructs.Vector3Prop(icp.OutVal, "OutVal"), CommonStructs.Vector3Prop(icp.ArriveTangent, "ArriveTangent"), CommonStructs.Vector3Prop(icp.LeaveTangent, "LeaveTangent"), icp.GetEnumProp(game) })); }
public static string GenerateUDKFileForLevel(string udkPath, IMEPackage pcc) { #region AssetPackage string meshPackageName = $"{Path.GetFileNameWithoutExtension(pcc.FilePath)}Meshes"; string meshFile = Path.Combine(udkPath, @"UDKGame\Content\Shared\", $"{meshPackageName}.upk"); MEPackageHandler.CreateAndSavePackage(meshFile, MEGame.UDK); using IMEPackage meshPackage = MEPackageHandler.OpenUDKPackage(meshFile); meshPackage.getEntryOrAddImport("Core.Package"); IEntry defMat = meshPackage.getEntryOrAddImport("EngineMaterials.DefaultMaterial", "Material", "Engine"); var allMats = new HashSet <int>(); var relinkMap = new Dictionary <IEntry, IEntry>(); #region StaticMeshes List <ExportEntry> staticMeshes = pcc.Exports.Where(exp => exp.ClassName == "StaticMesh").ToList(); foreach (ExportEntry mesh in staticMeshes) { var mats = new Queue <int>(); StaticMesh stm = ObjectBinary.From <StaticMesh>(mesh); foreach (StaticMeshRenderData lodModel in stm.LODModels) { foreach (StaticMeshElement meshElement in lodModel.Elements) { mats.Enqueue(meshElement.Material); allMats.Add(meshElement.Material); meshElement.Material = 0; } } if (pcc.GetEntry(stm.BodySetup) is ExportEntry rbBodySetup) { rbBodySetup.RemoveProperty("PhysMaterial"); } mesh.WriteBinary(stm); IEntry newParent = EntryImporter.GetOrAddCrossImportOrPackage(mesh.ParentFullPath, pcc, meshPackage); EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.CloneTreeAsChild, mesh, meshPackage, newParent, false, out IEntry ent, relinkMap); ExportEntry portedMesh = (ExportEntry)ent; stm = ObjectBinary.From <StaticMesh>(portedMesh); foreach (StaticMeshRenderData lodModel in stm.LODModels) { foreach (StaticMeshElement meshElement in lodModel.Elements) { meshElement.Material = mats.Dequeue(); } } portedMesh.WriteBinary(stm); } #endregion #region Materials using (IMEPackage udkResources = MEPackageHandler.OpenMEPackageFromStream(Utilities.GetCustomAppResourceStream(MEGame.UDK))) { ExportEntry normDiffMat = udkResources.Exports.First(exp => exp.ObjectName == "NormDiffMat"); foreach (int matUIndex in allMats) { if (pcc.GetEntry(matUIndex) is ExportEntry matExp) { List <IEntry> textures = new MaterialInstanceConstant(matExp).Textures; ExportEntry diff = null; ExportEntry norm = null; foreach (IEntry texEntry in textures) { if (texEntry is ExportEntry texport) { if (texport.ObjectName.Name.ToLower().Contains("diff")) { diff = texport; } else if (texport.ObjectName.Name.ToLower().Contains("norm")) { norm = texport; } } } if (diff == null) { relinkMap[matExp] = defMat; continue; } else { EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.AddSingularAsChild, diff, meshPackage, null, false, out IEntry ent); diff = (ExportEntry)ent; diff.RemoveProperty("TextureFileCacheName"); diff.RemoveProperty("TFCFileGuid"); diff.RemoveProperty("LODGroup"); } if (norm != null) { EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.AddSingularAsChild, norm, meshPackage, null, false, out IEntry ent); norm = (ExportEntry)ent; norm.RemoveProperty("TextureFileCacheName"); norm.RemoveProperty("TFCFileGuid"); norm.RemoveProperty("LODGroup"); } EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.CloneTreeAsChild, normDiffMat, meshPackage, null, true, out IEntry matEnt); ExportEntry newMat = (ExportEntry)matEnt; newMat.ObjectName = matExp.ObjectName; Material matBin = ObjectBinary.From <Material>(newMat); matBin.SM3MaterialResource.UniformExpressionTextures = new UIndex[] { norm?.UIndex ?? 0, diff.UIndex }; newMat.WriteBinary(matBin); relinkMap[matExp] = newMat; if (newMat.GetProperty <ArrayProperty <ObjectProperty> >("Expressions") is {} expressionsProp&& expressionsProp.Count >= 2) { ExportEntry diffExpression = meshPackage.GetUExport(expressionsProp[0].Value); ExportEntry normExpression = meshPackage.GetUExport(expressionsProp[1].Value); diffExpression.WriteProperty(new ObjectProperty(diff.UIndex, "Texture")); normExpression.WriteProperty(new ObjectProperty(norm?.UIndex ?? 0, "Texture")); } } else if (pcc.GetEntry(matUIndex) is ImportEntry matImp) { relinkMap[matImp] = defMat; } } var relinkMapping = new OrderedMultiValueDictionary <IEntry, IEntry>(relinkMap); foreach (ExportEntry stmExport in staticMeshes) { if (relinkMap.TryGetValue(stmExport, out IEntry destEnt) && destEnt is ExportEntry destExp) { Relinker.Relink(stmExport, destExp, relinkMapping); } } } #endregion meshPackage.Save(); #endregion var staticMeshActors = new List <ExportEntry>(); var lightActors = new List <ExportEntry>(); string tempPackagePath = Path.Combine(App.ExecFolder, $"{Path.GetFileNameWithoutExtension(pcc.FilePath)}.udk"); File.Copy(Path.Combine(App.ExecFolder, "empty.udk"), tempPackagePath, true); using IMEPackage udkPackage = MEPackageHandler.OpenUDKPackage(tempPackagePath); { var topLevelMeshPackages = new List <IEntry>(); foreach (ExportEntry exportEntry in staticMeshes) { IEntry imp = udkPackage.getEntryOrAddImport($"{exportEntry.FullPath}", "StaticMesh", "Engine", exportEntry.ObjectName.Number); while (imp.Parent != null) { imp = imp.Parent; } if (!topLevelMeshPackages.Contains(imp)) { topLevelMeshPackages.Add(imp); } } ExportEntry levelExport = udkPackage.Exports.First(exp => exp.ClassName == "Level"); List <int> actorsInLevel = ObjectBinary.From <Level>(pcc.Exports.First(exp => exp.ClassName == "Level")).Actors.Select(u => u.value).ToList(); var componentToMatrixMap = new Dictionary <int, Matrix>(); foreach (int uIndex in actorsInLevel) { if (pcc.GetEntry(uIndex) is ExportEntry stcExp) { if (stcExp.ClassName == "StaticMeshCollectionActor") { StaticMeshCollectionActor stmc = ObjectBinary.From <StaticMeshCollectionActor>(stcExp); var components = stcExp.GetProperty <ArrayProperty <ObjectProperty> >("StaticMeshComponents"); for (int i = 0; i < components.Count; i++) { componentToMatrixMap[components[i].Value] = stmc.LocalToWorldTransforms[i]; } } else if (stcExp.ClassName == "StaticLightCollectionActor") { StaticLightCollectionActor stlc = ObjectBinary.From <StaticLightCollectionActor>(stcExp); var components = stcExp.GetProperty <ArrayProperty <ObjectProperty> >("LightComponents"); for (int i = 0; i < components.Count; i++) { componentToMatrixMap[components[i].Value] = stlc.LocalToWorldTransforms[i]; } } } } #region StaticMeshActors { var emptySMCBin = new StaticMeshComponent(); IEntry staticMeshActorClass = udkPackage.getEntryOrAddImport("Engine.StaticMeshActor"); udkPackage.getEntryOrAddImport("Engine.Default__StaticMeshActor", "StaticMeshActor", "Engine"); IEntry staticMeshComponentArchetype = udkPackage.getEntryOrAddImport("Engine.Default__StaticMeshActor.StaticMeshComponent0", "StaticMeshComponent", "Engine"); int smaIndex = 2; int smcIndex = 2; foreach (ExportEntry smc in pcc.Exports.Where(exp => exp.ClassName == "StaticMeshComponent")) { if (smc.Parent is ExportEntry parent && actorsInLevel.Contains(parent.UIndex) && parent.IsA("StaticMeshActorBase")) { StructProperty locationProp; StructProperty rotationProp; StructProperty scaleProp = null; smc.CondenseArchetypes(); if (!(smc.GetProperty <ObjectProperty>("StaticMesh") is { } meshProp) || !pcc.IsUExport(meshProp.Value)) { continue; } smc.WriteBinary(emptySMCBin); smc.RemoveProperty("bBioIsReceivingDecals"); smc.RemoveProperty("bBioForcePrecomputedShadows"); //smc.RemoveProperty("bUsePreComputedShadows"); smc.RemoveProperty("bAcceptsLights"); smc.RemoveProperty("IrrelevantLights"); smc.RemoveProperty("Materials"); //should make use of this? smc.ObjectName = new NameReference("StaticMeshComponent", smcIndex++); if (parent.ClassName == "StaticMeshCollectionActor") { if (!componentToMatrixMap.TryGetValue(smc.UIndex, out Matrix m)) { continue; } (Vector3 posVec, Vector3 scaleVec, Rotator rotator) = m.UnrealDecompose(); locationProp = CommonStructs.Vector3Prop(posVec, "Location"); rotationProp = CommonStructs.RotatorProp(rotator, "Rotation"); scaleProp = CommonStructs.Vector3Prop(scaleVec, "DrawScale3D"); //smc.WriteProperty(CommonStructs.Matrix(m, "CachedParentToWorld")); } else { locationProp = parent.GetProperty <StructProperty>("Location"); rotationProp = parent.GetProperty <StructProperty>("Rotation"); scaleProp = parent.GetProperty <StructProperty>("DrawScale3D"); if (parent.GetProperty <FloatProperty>("DrawScale")?.Value is float scale) { Vector3 scaleVec = Vector3.One; if (scaleProp != null) { scaleVec = CommonStructs.GetVector3(scaleProp); } scaleProp = CommonStructs.Vector3Prop(scaleVec * scale, "DrawScale3D"); } } ExportEntry sma = new ExportEntry(udkPackage, EntryImporter.CreateStack(MEGame.UDK, staticMeshActorClass.UIndex)) { ObjectName = new NameReference("StaticMeshActor", smaIndex++), Class = staticMeshActorClass, Parent = levelExport }; sma.ObjectFlags |= UnrealFlags.EObjectFlags.HasStack; udkPackage.AddExport(sma); EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.AddSingularAsChild, smc, udkPackage, sma, true, out IEntry result); var props = new PropertyCollection { new ObjectProperty(result.UIndex, "StaticMeshComponent"), new NameProperty(new NameReference(Path.GetFileNameWithoutExtension(smc.FileRef.FilePath), smc.UIndex), "Tag"), new ObjectProperty(result.UIndex, "CollisionComponent") }; if (locationProp != null) { props.Add(locationProp); } if (rotationProp != null) { props.Add(rotationProp); } if (scaleProp != null) { props.Add(scaleProp); } sma.WriteProperties(props); staticMeshActors.Add(sma); } } IEntry topMeshPackageImport = udkPackage.getEntryOrAddImport(meshPackageName, "Package"); foreach (IEntry mp in topLevelMeshPackages) { mp.Parent = topMeshPackageImport; } } #endregion #region LightActors { IEntry pointLightClass = udkPackage.getEntryOrAddImport("Engine.PointLight"); IEntry spotLightClass = udkPackage.getEntryOrAddImport("Engine.SpotLight"); IEntry directionalLightClass = udkPackage.getEntryOrAddImport("Engine.DirectionalLight"); int plaIndex = 1; int plcIndex = 1; int slaIndex = 1; int slcIndex = 1; int dlaIndex = 1; int dlcIndex = 1; foreach (ExportEntry lightComponent in pcc.Exports) { if (!(lightComponent.Parent is ExportEntry parent && actorsInLevel.Contains(parent.UIndex))) { continue; } StructProperty locationProp; StructProperty rotationProp; StructProperty scaleProp; switch (lightComponent.ClassName) { case "PointLightComponent": lightComponent.CondenseArchetypes(); lightComponent.ObjectName = new NameReference("PointLightComponent", plcIndex++); if (parent.ClassName == "StaticLightCollectionActor") { if (!componentToMatrixMap.TryGetValue(lightComponent.UIndex, out Matrix m)) { continue; } (Vector3 posVec, Vector3 scaleVec, Rotator rotator) = m.UnrealDecompose(); locationProp = CommonStructs.Vector3Prop(posVec, "Location"); rotationProp = CommonStructs.RotatorProp(rotator, "Rotation"); scaleProp = CommonStructs.Vector3Prop(scaleVec, "DrawScale3D"); } else { locationProp = parent.GetProperty <StructProperty>("Location"); rotationProp = parent.GetProperty <StructProperty>("Rotation"); scaleProp = parent.GetProperty <StructProperty>("DrawScale3D"); if (parent.GetProperty <FloatProperty>("DrawScale")?.Value is float scale) { Vector3 scaleVec = Vector3.One; if (scaleProp != null) { scaleVec = CommonStructs.GetVector3(scaleProp); } scaleProp = CommonStructs.Vector3Prop(scaleVec * scale, "DrawScale3D"); } } ExportEntry pla = new ExportEntry(udkPackage, EntryImporter.CreateStack(MEGame.UDK, pointLightClass.UIndex)) { ObjectName = new NameReference("PointLight", plaIndex++), Class = pointLightClass, Parent = levelExport }; pla.ObjectFlags |= UnrealFlags.EObjectFlags.HasStack; udkPackage.AddExport(pla); EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.AddSingularAsChild, lightComponent, udkPackage, pla, true, out IEntry portedPLC); var plsProps = new PropertyCollection { new ObjectProperty(portedPLC.UIndex, "LightComponent"), new NameProperty("PointLight", "Tag"), }; if (locationProp != null) { plsProps.Add(locationProp); } if (rotationProp != null) { plsProps.Add(rotationProp); } if (scaleProp != null) { plsProps.Add(scaleProp); } pla.WriteProperties(plsProps); lightActors.Add(pla); break; case "SpotLightComponent": lightComponent.CondenseArchetypes(); lightComponent.ObjectName = new NameReference("SpotLightComponent", slcIndex++); if (parent.ClassName == "StaticLightCollectionActor") { if (!componentToMatrixMap.TryGetValue(lightComponent.UIndex, out Matrix m)) { continue; } (Vector3 posVec, Vector3 scaleVec, Rotator rotator) = m.UnrealDecompose(); locationProp = CommonStructs.Vector3Prop(posVec, "Location"); rotationProp = CommonStructs.RotatorProp(rotator, "Rotation"); scaleProp = CommonStructs.Vector3Prop(scaleVec, "DrawScale3D"); } else { locationProp = parent.GetProperty <StructProperty>("Location"); rotationProp = parent.GetProperty <StructProperty>("Rotation"); scaleProp = parent.GetProperty <StructProperty>("DrawScale3D"); if (parent.GetProperty <FloatProperty>("DrawScale")?.Value is float scale) { Vector3 scaleVec = Vector3.One; if (scaleProp != null) { scaleVec = CommonStructs.GetVector3(scaleProp); } scaleProp = CommonStructs.Vector3Prop(scaleVec * scale, "DrawScale3D"); } } ExportEntry sla = new ExportEntry(udkPackage, EntryImporter.CreateStack(MEGame.UDK, spotLightClass.UIndex)) { ObjectName = new NameReference("SpotLight", slaIndex++), Class = spotLightClass, Parent = levelExport }; sla.ObjectFlags |= UnrealFlags.EObjectFlags.HasStack; udkPackage.AddExport(sla); EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.AddSingularAsChild, lightComponent, udkPackage, sla, true, out IEntry portedSLC); var slaProps = new PropertyCollection { new ObjectProperty(portedSLC.UIndex, "LightComponent"), new NameProperty("SpotLight", "Tag"), }; if (locationProp != null) { slaProps.Add(locationProp); } if (rotationProp != null) { slaProps.Add(rotationProp); } if (scaleProp != null) { slaProps.Add(scaleProp); } sla.WriteProperties(slaProps); lightActors.Add(sla); break; case "DirectionalLightComponent": lightComponent.CondenseArchetypes(); lightComponent.ObjectName = new NameReference("DirectionalLightComponent", dlcIndex++); if (parent.ClassName == "StaticLightCollectionActor") { if (!componentToMatrixMap.TryGetValue(lightComponent.UIndex, out Matrix m)) { continue; } (Vector3 posVec, Vector3 scaleVec, Rotator rotator) = m.UnrealDecompose(); locationProp = CommonStructs.Vector3Prop(posVec, "Location"); rotationProp = CommonStructs.RotatorProp(rotator, "Rotation"); scaleProp = CommonStructs.Vector3Prop(scaleVec, "DrawScale3D"); } else { locationProp = parent.GetProperty <StructProperty>("Location"); rotationProp = parent.GetProperty <StructProperty>("Rotation"); scaleProp = parent.GetProperty <StructProperty>("DrawScale3D"); if (parent.GetProperty <FloatProperty>("DrawScale")?.Value is float scale) { Vector3 scaleVec = Vector3.One; if (scaleProp != null) { scaleVec = CommonStructs.GetVector3(scaleProp); } scaleProp = CommonStructs.Vector3Prop(scaleVec * scale, "DrawScale3D"); } } ExportEntry dla = new ExportEntry(udkPackage, EntryImporter.CreateStack(MEGame.UDK, directionalLightClass.UIndex)) { ObjectName = new NameReference("DirectionalLight", dlaIndex++), Class = directionalLightClass, Parent = levelExport }; dla.ObjectFlags |= UnrealFlags.EObjectFlags.HasStack; udkPackage.AddExport(dla); EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.AddSingularAsChild, lightComponent, udkPackage, dla, true, out IEntry portedDLC); var dlaProps = new PropertyCollection { new ObjectProperty(portedDLC.UIndex, "LightComponent"), new NameProperty("DirectionalLight", "Tag"), }; if (locationProp != null) { dlaProps.Add(locationProp); } if (rotationProp != null) { dlaProps.Add(rotationProp); } if (scaleProp != null) { dlaProps.Add(scaleProp); } dla.WriteProperties(dlaProps); lightActors.Add(dla); break; } } } UDKifyLights(udkPackage); #endregion Level level = ObjectBinary.From <Level>(levelExport); level.Actors = levelExport.GetChildren().Where(ent => ent.IsA("Actor")).Select(ent => new UIndex(ent.UIndex)).ToList(); levelExport.WriteBinary(level); udkPackage.Save(); } string resultFilePath = Path.Combine(udkPath, @"UDKGame\Content\Maps\", $"{Path.GetFileNameWithoutExtension(pcc.FilePath)}.udk"); using (IMEPackage udkPackage2 = MEPackageHandler.OpenUDKPackage(Path.Combine(App.ExecFolder, "empty.udk"))) { ExportEntry levelExport = udkPackage2.Exports.First(exp => exp.ClassName == "Level"); Level levelBin = ObjectBinary.From <Level>(levelExport); foreach (ExportEntry actor in staticMeshActors) { EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.CloneTreeAsChild, actor, udkPackage2, levelExport, true, out IEntry result); levelBin.Actors.Add(result.UIndex); } foreach (ExportEntry actor in lightActors) { EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.CloneTreeAsChild, actor, udkPackage2, levelExport, true, out IEntry result); levelBin.Actors.Add(result.UIndex); } levelExport.WriteBinary(levelBin); udkPackage2.Save(resultFilePath); } File.Delete(tempPackagePath); return(resultFilePath); }
public static void SetLocation(ExportEntry export, float x, float y, float z) { export.WriteProperty(CommonStructs.Vector3(x, y, z, "location")); }
public InterpCurve(IMEPackage _pcc, StructProperty prop) { pcc = _pcc; Curves = new ObservableCollectionExtended <Curve>(); Name = prop.Name; curveType = Enums.Parse <CurveType>(prop.StructType); float InVal = 0f; CurveMode InterpMode = CurveMode.CIM_Linear; var points = prop.Properties.GetProp <ArrayProperty <StructProperty> >("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; var vals = new LinkedList <CurvePoint>(); foreach (var point in points) { foreach (var p in point.Properties) { switch (p) { case FloatProperty floatProp when floatProp.Name == "InVal": InVal = floatProp.Value; break; case FloatProperty floatProp when floatProp.Name == "OutVal": OutVal = floatProp.Value; break; case FloatProperty floatProp when floatProp.Name == "ArriveTangent": ArriveTangent = floatProp.Value; break; case FloatProperty floatProp when floatProp.Name == "LeaveTangent": LeaveTangent = floatProp.Value; break; case EnumProperty enumProp when enumProp.Name == "InterpMode" && Enum.TryParse(enumProp.Value, out CurveMode enumVal): InterpMode = enumVal; break; } } vals.AddLast(new CurvePoint(InVal, OutVal, ArriveTangent, LeaveTangent, InterpMode)); } Curves.Add(new Curve("X", vals)); break; case CurveType.InterpCurveVector: Vector3 OutValVec = new Vector3(0, 0, 0); Vector3 ArriveTangentVec = new Vector3(0, 0, 0); Vector3 LeaveTangentVec = new Vector3(0, 0, 0); var x = new LinkedList <CurvePoint>(); var y = new LinkedList <CurvePoint>(); var z = new LinkedList <CurvePoint>(); foreach (var point in points) { foreach (var p in point.Properties) { switch (p) { case FloatProperty floatProp when floatProp.Name == "InVal": InVal = floatProp.Value; break; case StructProperty structProp when structProp.Name == "OutVal": OutValVec = CommonStructs.GetVector3(structProp); break; case StructProperty structProp when structProp.Name == "ArriveTangent": ArriveTangentVec = CommonStructs.GetVector3(structProp); break; case StructProperty structProp when structProp.Name == "LeaveTangent": LeaveTangentVec = CommonStructs.GetVector3(structProp); break; case EnumProperty enumProp when enumProp.Name == "InterpMode" && Enum.TryParse(enumProp.Value, out CurveMode enumVal): InterpMode = enumVal; 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."); } foreach (var curve in Curves) { curve.SharedValueChanged += Curve_SharedValueChanged; curve.ListModified += Curve_ListModified; } }
InterpCurvePoint <Vector2> ISpec <Vector2> .FromStructProperty(StructProperty prop) => new InterpCurvePoint <Vector2>(prop.GetProp <FloatProperty>("InVal"), CommonStructs.GetVector2(prop.GetProp <StructProperty>("OutVal")), CommonStructs.GetVector2(prop.GetProp <StructProperty>("ArriveTangent")), CommonStructs.GetVector2(prop.GetProp <StructProperty>("LeaveTangent")), GetCurveMode(prop));
public void UpdateSplines(UpdateMode mode, bool save = false) { if (mode == UpdateMode.ArriveTangent || mode == UpdateMode.LeaveTangent) { Vector3 worldCoords; if (mode == UpdateMode.ArriveTangent) { worldCoords = new Vector3(ArriveTangentControlNode.OffsetX, ArriveTangentControlNode.OffsetY, ArriveTangentControlNode.Z); LeaveTangentControlNode.SetOffset(-worldCoords.X, -worldCoords.Y); worldCoords = -worldCoords; } else { worldCoords = new Vector3(LeaveTangentControlNode.OffsetX, LeaveTangentControlNode.OffsetY, LeaveTangentControlNode.Z); ArriveTangentControlNode.SetOffset(-worldCoords.X, -worldCoords.Y); } if (save) { //will cause a refresh,so no need to update UI export.WriteProperty(CommonStructs.Vector3Prop(ActorUtils.GetWorldToLocal(export).TransformNormal(worldCoords), "SplineActorTangent")); return; } foreach (Spline spline in Splines) { spline.SplineInfo.Points[0].ArriveTangent = -worldCoords; spline.SplineInfo.Points[0].LeaveTangent = worldCoords; UpdateSpline(spline); } foreach (SplineActorNode prevSplineActor in LinksFrom) { foreach (Spline spline in prevSplineActor.Splines) { if (spline.NextActor == export) { spline.SplineInfo.Points[1].ArriveTangent = worldCoords; spline.SplineInfo.Points[1].LeaveTangent = -worldCoords; UpdateSpline(spline); } } } } else { float z = (float)SharedPathfinding.GetLocation(export).Z; Vector3 location = new Vector3(OffsetX, OffsetY, z); if (save) { //will cause a refresh,so no need to update UI SharedPathfinding.SetLocation(export, location.X, location.Y, location.Z); return; } foreach (Spline spline in Splines) { spline.SplineInfo.Points[0].OutVal = location; UpdateSpline(spline); } foreach (SplineActorNode prevSplineActor in LinksFrom) { foreach (Spline spline in prevSplineActor.Splines) { if (spline.NextActor == export) { spline.SplineInfo.Points[1].OutVal = location; UpdateSpline(spline); } } } } PathingGraphEditor.UpdateEdgeStraight(ArriveTangentControlNode.Edge); PathingGraphEditor.UpdateEdgeStraight(LeaveTangentControlNode.Edge); void UpdateSpline(Spline spline) { spline.RegenerateReparamTable(); for (int i = 0; i < spline.ReparamTable.Points.Count; i++) { (float x, float y, _) = spline.SplineInfo.Eval(spline.ReparamTable.Points[i].OutVal, Vector3.Zero); spline.nodes[i].SetOffset(x, y); } if (spline.nodes.Count > 7) { var directionVector = new Vector2(spline.nodes[7].OffsetX, spline.nodes[7].OffsetY) - new Vector2(spline.nodes[5].OffsetX, spline.nodes[5].OffsetY); directionVector.Normalize(); spline.nodes[6].Rotation = (float)(Math.Atan2(directionVector.X, -directionVector.Y) * 180 / Math.PI); } foreach (PathfindingEditorEdge edge in spline.edges) { PathingGraphEditor.UpdateEdgeStraight(edge); } } }