private bool UpdateSaberConfig(AssetsManager manager, SaberModel saberCfg) { try { if (saberCfg != null && (!string.IsNullOrWhiteSpace(saberCfg.CustomSaberFolder) || !string.IsNullOrWhiteSpace(saberCfg.SaberID))) { var currentSaber = GetCurrentSaberID(manager); if (!string.IsNullOrWhiteSpace(saberCfg.SaberID) && SaberExists(manager, saberCfg.SaberID)) { if (currentSaber == saberCfg.SaberID) { Log.LogMsg($"Current saber is already set to {currentSaber}, no changes needed."); return(true); } Log.LogMsg($"SaberID {saberCfg.SaberID} was found already in the assets, using it."); SwapToSaberID(manager, saberCfg.SaberID); return(true); } else { SaberInfo newSaber = SaberInfo.FromFolderOrZip(saberCfg.CustomSaberFolder); if (SaberExists(manager, newSaber.ID)) { Log.LogErr($"Saber ID {newSaber.ID} that was loaded already exists. Cannot load another saber with the same name."); return(false); } MakeSaber(manager, newSaber); SwapToSaberID(manager, saberCfg.SaberID); return(true); } } else { Log.LogMsg("Saber config is null, saber configuration will not be changed."); return(true); } } catch (Exception ex) { Log.LogErr("Failed to update saber configuration.", ex); return(false); } }
//TODO: this whole section is a lot of copy/paste that needs to be cleaned up after I make sure it works at all private Transform MakeSaber(AssetsManager manager, SaberInfo saberInfo) { if (string.IsNullOrEmpty(saberInfo?.ID)) { throw new ArgumentNullException("saberInfo.ID must not be null or empty!"); } var file11 = manager.GetAssetsFile(BSConst.KnownFiles.File11); //lots of double checking things in this function, first time I've done object manipulation this detailed var newSaber = file11.FindAsset <GameObject>(x => x.Object.Name == $"{saberInfo.ID}Saber")?.Object; if (newSaber != null) { throw new Exception($"Saber with ID {saberInfo.ID} already exists!"); } //find the "basic saber" game object, we're going to copy it var basicSaber = file11.FindAsset <GameObject>(x => x.Object.Name == "BasicSaber").Object; //do some detailed checking to make sure the objects are in the places we expect and get the object we're going to clone var transform = basicSaber.Components.FirstOrDefault(x => x is SmartPtr <Transform>)?.Object as Transform; if (transform == null) { throw new Exception("Unable to find Transform on Saber!"); } var saberBladeGOTransform = transform.Children.FirstOrDefault(x => x.Object.GameObject?.Object.Name == "SaberBlade")?.Object; var saberGlowingEdgesGOTransform = transform.Children.FirstOrDefault(x => x.Object.GameObject?.Object.Name == "SaberGlowingEdges")?.Object; var saberHandleGOTransform = transform.Children.FirstOrDefault(x => x.Object.GameObject?.Object.Name == "SaberHandle")?.Object; if (saberBladeGOTransform == null) { throw new Exception("Unable to find parent transform of SaberBlade on Transform!"); } if (saberGlowingEdgesGOTransform == null) { throw new Exception("Unable to find parent transform of SaberGlowingEdges on Transform!"); } if (saberHandleGOTransform == null) { throw new Exception("Unable to find parent transform of SaberHandle on Transform!"); } var saberBladeGO = saberBladeGOTransform.GameObject.Object; var saberGlowingEdgesGO = saberGlowingEdgesGOTransform.GameObject.Object; var saberHandleGO = saberHandleGOTransform.GameObject.Object; if (saberBladeGO == null) { throw new Exception("Unable to find SaberBlade on Transform!"); } if (saberGlowingEdgesGO == null) { throw new Exception("Unable to find SaberGlowingEdges on Transform!"); } if (saberHandleGO == null) { throw new Exception("Unable to find SaberHandle on Transform!"); } var saberBladeMeshFilter = (saberBladeGO.Components.FirstOrDefault(x => x is ISmartPtr <MeshFilterObject>) as ISmartPtr <MeshFilterObject>)?.Object; var saberGlowingEdgesMeshFilter = (saberBladeGO.Components.FirstOrDefault(x => x is ISmartPtr <MeshFilterObject>) as ISmartPtr <MeshFilterObject>)?.Object; var saberHandleMeshFilter = (saberBladeGO.Components.FirstOrDefault(x => x is ISmartPtr <MeshFilterObject>) as ISmartPtr <MeshFilterObject>)?.Object; if (saberBladeMeshFilter == null) { throw new Exception("Unable to find SaberBlade MeshFilter on Transform!"); } if (saberGlowingEdgesMeshFilter == null) { throw new Exception("Unable to find SaberGlowingEdges MeshFilter on Transform!"); } if (saberHandleMeshFilter == null) { throw new Exception("Unable to find SaberHandle MeshFilter on Transform!"); } if (saberBladeMeshFilter?.Mesh?.Object?.Name != "SaberBlade") { throw new Exception($"Should be named SaberBlade but is named {saberBladeMeshFilter?.Mesh?.Object?.Name}!"); } if (saberGlowingEdgesMeshFilter?.Mesh?.Object?.Name != "SaberGlowingEdges") { throw new Exception($"Should be named SaberGlowingEdges but is named {saberGlowingEdgesMeshFilter?.Mesh?.Object?.Name}!"); } if (saberHandleMeshFilter?.Mesh?.Object?.Name != "SaberHandle") { throw new Exception($"Should be named SaberHandle but is named {saberHandleMeshFilter?.Mesh?.Object?.Name}!"); } //there's a bunch of other pointers we can leave in place, but we have to make //copies of all objects in the tree that we're changing: // BasicSaber -> Transform -> another Transform for each of the 3, SaberBlade/edges/handle (GO) (which contains the previous transform) -> MeshFilter -> SaberBlade/edges/handle (Mesh) //clone the SaberBlade/edges/handle meshes, give them new names, and set the new dat file data for the meshes var newSaberBladeMesh = saberBladeMeshFilter.Mesh.Object.ObjectInfo.Clone().Object as MeshObject; newSaberBladeMesh.Name = $"{saberInfo.ID}SaberBlade"; newSaberBladeMesh.MeshData = saberInfo.DatFiles.SaberBladeBytes; file11.AddObject(newSaberBladeMesh); var newSaberGlowingEdgesMesh = saberGlowingEdgesMeshFilter.Mesh.Object.ObjectInfo.Clone().Object as MeshObject; newSaberGlowingEdgesMesh.Name = $"{saberInfo.ID}SaberGlowingEdges"; newSaberGlowingEdgesMesh.MeshData = saberInfo.DatFiles.SaberGlowingEdgesBytes; file11.AddObject(newSaberGlowingEdgesMesh); var newSaberHandleMesh = saberGlowingEdgesMeshFilter.Mesh.Object.ObjectInfo.Clone().Object as MeshObject; newSaberHandleMesh.Name = $"{saberInfo.ID}SaberHandle"; newSaberHandleMesh.MeshData = saberInfo.DatFiles.SaberHandleBytes; file11.AddObject(newSaberHandleMesh); //clone the MeshFilters, set their Mesh pointers to the new parts above. var newSaberBladeMeshFilter = saberBladeMeshFilter.ObjectInfo.Clone().Object as MeshFilterObject; newSaberBladeMeshFilter.Mesh = newSaberBladeMesh.PtrFrom(newSaberBladeMeshFilter); file11.AddObject(newSaberBladeMeshFilter); var newSaberGlowingEdgesMeshFilter = saberBladeMeshFilter.ObjectInfo.Clone().Object as MeshFilterObject; newSaberGlowingEdgesMeshFilter.Mesh = newSaberGlowingEdgesMesh.PtrFrom(newSaberGlowingEdgesMeshFilter); file11.AddObject(newSaberGlowingEdgesMeshFilter); var newSaberHandleMeshFilter = saberHandleMeshFilter.ObjectInfo.Clone().Object as MeshFilterObject; newSaberHandleMeshFilter.Mesh = newSaberHandleMesh.PtrFrom(newSaberHandleMeshFilter); file11.AddObject(newSaberHandleMeshFilter); //clone those weird transforms in the middle... this goes into the components of the GO, and into the parent transform // and gets its parent pointer set to the parent transform var newSaberBladeGOTransform = saberBladeGOTransform.ObjectInfo.Clone().Object as Transform; file11.AddObject(newSaberBladeGOTransform); var newSaberGlowingEdgesGOTransform = saberGlowingEdgesGOTransform.ObjectInfo.Clone().Object as Transform; file11.AddObject(newSaberGlowingEdgesGOTransform); var newSaberHandleGOTransform = saberHandleGOTransform.ObjectInfo.Clone().Object as Transform; file11.AddObject(newSaberHandleGOTransform); //clone the saberblade/edges/handle game objects and name them //remove the old mesh filter, and add the new one //not sure how careful to be, so we'll get it at the same index in each var newSaberBladeGO = saberBladeGO.ObjectInfo.Clone().Object as GameObject; newSaberBladeGO.Name = $"{saberInfo.ID}SaberBlade"; var bladeIndexGO = newSaberBladeGO.Components.IndexOf(newSaberBladeGO.Components.First(x => x.Object is MeshFilterObject)); var bladeIndexTrans = newSaberBladeGO.Components.IndexOf(newSaberBladeGO.Components.First(x => x.Object is Transform)); newSaberBladeGO.Components[bladeIndexGO] = newSaberBladeMeshFilter.PtrFrom(newSaberBladeGO); newSaberBladeGO.Components[bladeIndexTrans] = newSaberBladeGOTransform.PtrFrom(newSaberBladeGO); file11.AddObject(newSaberBladeGO); var newSaberGlowingEdgesGO = saberGlowingEdgesGO.ObjectInfo.Clone().Object as GameObject; newSaberGlowingEdgesGO.Name = $"{saberInfo.ID}SaberGlowingEdges"; var geIndexGO = newSaberGlowingEdgesGO.Components.IndexOf(newSaberGlowingEdgesGO.Components.First(x => x.Object is MeshFilterObject)); var geIndexTrans = newSaberGlowingEdgesGO.Components.IndexOf(newSaberGlowingEdgesGO.Components.First(x => x.Object is Transform)); newSaberGlowingEdgesGO.Components[geIndexGO] = newSaberGlowingEdgesMeshFilter.PtrFrom(newSaberGlowingEdgesGO); newSaberGlowingEdgesGO.Components[geIndexTrans] = newSaberGlowingEdgesGOTransform.PtrFrom(newSaberGlowingEdgesGO); file11.AddObject(newSaberGlowingEdgesGO); var newSaberHandleGO = saberHandleGO.ObjectInfo.Clone().Object as GameObject; newSaberHandleGO.Name = $"{saberInfo.ID}SaberHandle"; var handleIndexGO = newSaberHandleGO.Components.IndexOf(newSaberHandleGO.Components.First(x => x.Object is MeshFilterObject)); newSaberHandleGO.Components[handleIndexGO] = newSaberHandleMeshFilter.PtrFrom(newSaberHandleGO); file11.AddObject(newSaberHandleGO); //clone the Transform var newTransform = transform.ObjectInfo.Clone().Object as Transform; //get the new game objects in the right spots in the transform. not sure how much index matters, but we'll be careful int bladeIndex = newTransform.Children.IndexOf(newTransform.Children.First(x => x.Object.GameObject.Object.Name == "SaberBlade")); int geIndex = newTransform.Children.IndexOf(newTransform.Children.First(x => x.Object.GameObject.Object.Name == "SaberGlowingEdges")); int handleIndex = newTransform.Children.IndexOf(newTransform.Children.First(x => x.Object.GameObject.Object.Name == "SaberHandle")); newTransform.Children[bladeIndex] = newSaberBladeGOTransform.PtrFrom(newTransform); newSaberBladeGOTransform.Father = newTransform.PtrFrom(newSaberBladeGOTransform); newTransform.Children[geIndex] = newSaberGlowingEdgesGOTransform.PtrFrom(newTransform); newSaberGlowingEdgesGOTransform.Father = newTransform.PtrFrom(newSaberGlowingEdgesGOTransform); newTransform.Children[handleIndex] = newSaberHandleGOTransform.PtrFrom(newTransform); newSaberHandleGOTransform.Father = newTransform.PtrFrom(newSaberHandleGOTransform); file11.AddObject(newTransform); //clone the BasicSaber and give it a new name newSaber = basicSaber.ObjectInfo.Clone().Object as GameObject; newSaber.Name = $"{saberInfo.ID}Saber"; //assign the transform newSaber.Components[0] = newTransform.PtrFrom(newSaber); file11.AddObject(newSaber); //holy shit, is there any chance all of this verbosity and double checking things will work? return(newTransform); }