diff --git a/NewHorizons/Builder/Props/QuantumBuilder.cs b/NewHorizons/Builder/Props/QuantumBuilder.cs index 70b46e8f..000700f7 100644 --- a/NewHorizons/Builder/Props/QuantumBuilder.cs +++ b/NewHorizons/Builder/Props/QuantumBuilder.cs @@ -21,6 +21,7 @@ namespace NewHorizons.Builder.Props case PropModule.QuantumGroupType.Sockets: MakeSocketGroup (go, sector, config, mod, quantumGroup, propsInGroup); return; case PropModule.QuantumGroupType.States: MakeStateGroup (go, sector, config, mod, quantumGroup, propsInGroup); return; case PropModule.QuantumGroupType.Shuffle: MakeShuffleGroup(go, sector, config, mod, quantumGroup, propsInGroup); return; + // TODO: for quantum socket group allow specifying an _emptySocketObject } } @@ -29,6 +30,38 @@ namespace NewHorizons.Builder.Props // note: for the visibility boxes on quantum sockets, if there's only one prop that's part of this group, clone its visibility volume // otherwise, create a box according to the max and min dimensions across all props in this group (ie the box should be able to fit inside of it the visibility volume on any prop in this group) + var groupRoot = new GameObject("Quantum Sockets - " + quantumGroup.id); + groupRoot.transform.parent = sector.transform; + groupRoot.transform.localPosition = Vector3.zero; + + var sockets = new List(quantumGroup.sockets.Length); + for (int i = 0; i < quantumGroup.sockets.Length; i++) + { + var socketInfo = quantumGroup.sockets[i]; + + var socket = new GameObject("Socket " + i); + socket.transform.parent = groupRoot.transform; + socket.transform.localPosition = socketInfo.position; + socket.transform.localEulerAngles = socketInfo.rotation; + + sockets[i] = socket.AddComponent(); + } + + foreach(var prop in propsInGroup) + { + var quantumObject = prop.AddComponent(); + quantumObject._socketRoot = groupRoot; + quantumObject._socketList = sockets; + + if (quantumObject.gameObject.GetComponentInChildren() != null) continue; + + var boxBounds = GetBoundsOfSelfAndChildMeshes(prop); + var boxShape = prop.AddComponent(); + boxShape.center = boxBounds.center; + boxShape.extents = boxBounds.size; + + prop.AddComponent(); + } } public static void MakeStateGroup(GameObject go, Sector sector, PlanetConfig config, IModBehaviour mod, PropModule.QuantumGroupInfo quantumGroup, GameObject[] propsInGroup) @@ -42,5 +75,40 @@ namespace NewHorizons.Builder.Props // then, make all props children of it } + + + public static Bounds GetBoundsOfSelfAndChildMeshes(GameObject g) + { + var meshFilters = g.GetComponentsInChildren(); + var corners = meshFilters.SelectMany(m => GetMeshCorners(m, g)).ToList(); + + Bounds b = new Bounds(corners[0], Vector3.zero); + corners.ForEach(corner => b.Encapsulate(corner)); + + return b; + } + + public static Vector3[] GetMeshCorners(MeshFilter m, GameObject relativeTo = null) + { + var bounds = m.mesh.bounds; + + var localCorners = new Vector3[] + { + bounds.min, + bounds.max, + new Vector3(bounds.min.x, bounds.min.y, bounds.max.z), + new Vector3(bounds.min.x, bounds.max.y, bounds.min.z), + new Vector3(bounds.max.x, bounds.min.y, bounds.min.z), + new Vector3(bounds.min.x, bounds.max.y, bounds.max.z), + new Vector3(bounds.max.x, bounds.min.y, bounds.max.z), + new Vector3(bounds.max.x, bounds.max.y, bounds.min.z), + }; + + var globalCorners = localCorners.Select(localCorner => m.transform.TransformPoint(localCorner)).ToArray(); + + if (relativeTo == null) return globalCorners; + + return globalCorners.Select(globalCorner => relativeTo.transform.TransformPoint(globalCorner)).ToArray(); + } } } diff --git a/NewHorizons/External/Modules/PropModule.cs b/NewHorizons/External/Modules/PropModule.cs index 68d663c0..f4723e70 100644 --- a/NewHorizons/External/Modules/PropModule.cs +++ b/NewHorizons/External/Modules/PropModule.cs @@ -666,17 +666,17 @@ namespace NewHorizons.External.Modules /// /// The location of this socket /// - MVector3 position; + public MVector3 position; /// /// The rotation the quantum object will take if it's occupying this socket /// - MVector3 rotation; + public MVector3 rotation; /// /// The probability any props that are part of this group will occupy this socket /// - float probability; + public float probability; } } } \ No newline at end of file