Add option to toggle quantum object visualization separate from debug (#1011)

## Improvements

- Added option separate from Debug for visualizing quantum object
visibility shapes
This commit is contained in:
xen-42 2025-01-06 10:42:55 -05:00 committed by GitHub
commit b9e0eb3b43
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 52 additions and 37 deletions

View File

@ -12,17 +12,17 @@ namespace NewHorizons.Builder.Props
{ {
public static class QuantumBuilder public static class QuantumBuilder
{ {
public static void Make(GameObject go, Sector sector, PlanetConfig config, IModBehaviour mod, QuantumGroupInfo quantumGroup, GameObject[] propsInGroup) public static void Make(GameObject go, Sector sector, PlanetConfig config, IModBehaviour mod, QuantumGroupInfo quantumGroup, GameObject[] propsInGroup)
{ {
switch(quantumGroup.type) switch (quantumGroup.type)
{ {
case QuantumGroupType.Sockets: MakeSocketGroup (go, sector, config, mod, quantumGroup, propsInGroup); return; case QuantumGroupType.Sockets: MakeSocketGroup(go, sector, config, mod, quantumGroup, propsInGroup); return;
case QuantumGroupType.States: MakeStateGroup (go, sector, config, mod, quantumGroup, propsInGroup); return; case QuantumGroupType.States: MakeStateGroup(go, sector, config, mod, quantumGroup, propsInGroup); return;
// case PropModule.QuantumGroupType.Shuffle: MakeShuffleGroup(go, sector, config, mod, quantumGroup, propsInGroup); return; // case PropModule.QuantumGroupType.Shuffle: MakeShuffleGroup(go, sector, config, mod, quantumGroup, propsInGroup); return;
} }
} }
// TODO: Socket groups that have an equal number of props and sockets // TODO: Socket groups that have an equal number of props and sockets
// Nice to have: socket groups that specify a filledSocketObject and an emptySocketObject (eg the archway in the giant's deep tower) // Nice to have: socket groups that specify a filledSocketObject and an emptySocketObject (eg the archway in the giant's deep tower)
public static void MakeSocketGroup(GameObject go, Sector sector, PlanetConfig config, IModBehaviour mod, QuantumGroupInfo quantumGroup, GameObject[] propsInGroup) public static void MakeSocketGroup(GameObject go, Sector sector, PlanetConfig config, IModBehaviour mod, QuantumGroupInfo quantumGroup, GameObject[] propsInGroup)
@ -31,7 +31,7 @@ namespace NewHorizons.Builder.Props
groupRoot.transform.parent = sector?.transform ?? go.transform; groupRoot.transform.parent = sector?.transform ?? go.transform;
groupRoot.transform.localPosition = Vector3.zero; groupRoot.transform.localPosition = Vector3.zero;
groupRoot.transform.localEulerAngles = Vector3.zero; groupRoot.transform.localEulerAngles = Vector3.zero;
var sockets = new QuantumSocket[quantumGroup.sockets.Length]; var sockets = new QuantumSocket[quantumGroup.sockets.Length];
for (int i = 0; i < quantumGroup.sockets.Length; i++) for (int i = 0; i < quantumGroup.sockets.Length; i++)
{ {
@ -44,7 +44,7 @@ namespace NewHorizons.Builder.Props
socket.SetActive(true); socket.SetActive(true);
} }
foreach(var prop in propsInGroup) foreach (var prop in propsInGroup)
{ {
prop.SetActive(false); prop.SetActive(false);
var quantumObject = prop.AddComponent<SocketedQuantumObject>(); var quantumObject = prop.AddComponent<SocketedQuantumObject>();
@ -55,7 +55,7 @@ namespace NewHorizons.Builder.Props
quantumObject._childSockets = new List<QuantumSocket>(); quantumObject._childSockets = new List<QuantumSocket>();
// TODO: support _alignWithGravity? // TODO: support _alignWithGravity?
if (prop.GetComponentInChildren<VisibilityTracker>() == null) AddBoundsVisibility(prop); if (prop.GetComponentInChildren<VisibilityTracker>() == null) AddBoundsVisibility(prop);
prop.SetActive(true); prop.SetActive(true);
} }
} }
@ -72,7 +72,7 @@ namespace NewHorizons.Builder.Props
groupRoot.transform.localPosition = Vector3.zero; groupRoot.transform.localPosition = Vector3.zero;
var states = new List<QuantumState>(); var states = new List<QuantumState>();
foreach(var prop in propsInGroup) foreach (var prop in propsInGroup)
{ {
prop.transform.parent = groupRoot.transform; prop.transform.parent = groupRoot.transform;
var state = prop.AddComponent<QuantumState>(); var state = prop.AddComponent<QuantumState>();
@ -87,7 +87,7 @@ namespace NewHorizons.Builder.Props
if (quantumGroup.hasEmptyState) if (quantumGroup.hasEmptyState)
{ {
var template = propsInGroup[0]; var template = propsInGroup[0];
var empty = new GameObject("Empty State"); var empty = new GameObject("Empty State");
empty.transform.parent = groupRoot.transform; empty.transform.parent = groupRoot.transform;
var state = empty.AddComponent<QuantumState>(); var state = empty.AddComponent<QuantumState>();
@ -97,8 +97,8 @@ namespace NewHorizons.Builder.Props
var boxShape = empty.AddComponent<BoxShape>(); var boxShape = empty.AddComponent<BoxShape>();
boxShape.center = boxBounds.center; boxShape.center = boxBounds.center;
boxShape.extents = boxBounds.size; boxShape.extents = boxBounds.size;
if (Main.Debug) empty.AddComponent<BoxShapeVisualizer>(); empty.AddComponent<BoxShapeVisualizer>();
empty.AddComponent<ShapeVisibilityTracker>(); empty.AddComponent<ShapeVisibilityTracker>();
} }
@ -121,43 +121,43 @@ namespace NewHorizons.Builder.Props
shuffleParent.SetActive(false); shuffleParent.SetActive(false);
shuffleParent.transform.parent = sector?.transform ?? go.transform; shuffleParent.transform.parent = sector?.transform ?? go.transform;
shuffleParent.transform.localPosition = Vector3.zero; shuffleParent.transform.localPosition = Vector3.zero;
propsInGroup.ToList().ForEach(p => p.transform.parent = shuffleParent.transform); propsInGroup.ToList().ForEach(p => p.transform.parent = shuffleParent.transform);
var shuffle = shuffleParent.AddComponent<QuantumShuffleObject>(); var shuffle = shuffleParent.AddComponent<QuantumShuffleObject>();
shuffle._shuffledObjects = propsInGroup.Select(p => p.transform).ToArray(); shuffle._shuffledObjects = propsInGroup.Select(p => p.transform).ToArray();
shuffle.Awake(); // this doesn't get called on its own for some reason. what? how? shuffle.Awake(); // this doesn't get called on its own for some reason. what? how?
AddBoundsVisibility(shuffleParent); AddBoundsVisibility(shuffleParent);
shuffleParent.SetActive(true); shuffleParent.SetActive(true);
} }
struct BoxShapeReciever struct BoxShapeReciever
{ {
public MeshFilter f; public MeshFilter f;
public SkinnedMeshRenderer s; public SkinnedMeshRenderer s;
public GameObject g; public GameObject gameObject;
} }
public static void AddBoundsVisibility(GameObject g) public static void AddBoundsVisibility(GameObject g)
{ {
var meshFilters = g.GetComponentsInChildren<MeshFilter>(); var meshFilters = g.GetComponentsInChildren<MeshFilter>();
var skinnedMeshRenderers = g.GetComponentsInChildren<SkinnedMeshRenderer>(); var skinnedMeshRenderers = g.GetComponentsInChildren<SkinnedMeshRenderer>();
var boxShapeRecievers = meshFilters var boxShapeRecievers = meshFilters
.Select(f => new BoxShapeReciever() { f=f, g=f.gameObject }) .Select(f => new BoxShapeReciever() { f = f, gameObject = f.gameObject })
.Concat ( .Concat(
skinnedMeshRenderers.Select(s => new BoxShapeReciever() { s=s, g=s.gameObject }) skinnedMeshRenderers.Select(s => new BoxShapeReciever() { s = s, gameObject = s.gameObject })
) )
.ToList(); .ToList();
foreach(var boxshapeReciever in boxShapeRecievers) foreach (var boxshapeReciever in boxShapeRecievers)
{ {
var box = boxshapeReciever.g.AddComponent<BoxShape>(); var box = boxshapeReciever.gameObject.AddComponent<BoxShape>();
boxshapeReciever.g.AddComponent<ShapeVisibilityTracker>(); boxshapeReciever.gameObject.AddComponent<ShapeVisibilityTracker>();
if (Main.Debug) boxshapeReciever.g.AddComponent<BoxShapeVisualizer>(); boxshapeReciever.gameObject.AddComponent<BoxShapeVisualizer>();
var fixer = boxshapeReciever.g.AddComponent<BoxShapeFixer>(); var fixer = boxshapeReciever.gameObject.AddComponent<BoxShapeFixer>();
fixer.shape = box; fixer.shape = box;
fixer.meshFilter = boxshapeReciever.f; fixer.meshFilter = boxshapeReciever.f;
fixer.skinnedMeshRenderer = boxshapeReciever.s; fixer.skinnedMeshRenderer = boxshapeReciever.s;
@ -169,7 +169,7 @@ namespace NewHorizons.Builder.Props
{ {
var meshFilters = g.GetComponentsInChildren<MeshFilter>(); var meshFilters = g.GetComponentsInChildren<MeshFilter>();
var corners = meshFilters.SelectMany(m => GetMeshCorners(m, g)).ToList(); var corners = meshFilters.SelectMany(m => GetMeshCorners(m, g)).ToList();
Bounds b = new Bounds(corners[0], Vector3.zero); Bounds b = new Bounds(corners[0], Vector3.zero);
corners.ForEach(corner => b.Encapsulate(corner)); corners.ForEach(corner => b.Encapsulate(corner));
@ -191,9 +191,9 @@ namespace NewHorizons.Builder.Props
new Vector3(bounds.max.x, bounds.min.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), new Vector3(bounds.max.x, bounds.max.y, bounds.min.z),
}; };
var globalCorners = localCorners.Select(localCorner => m.transform.TransformPoint(localCorner)).ToArray(); var globalCorners = localCorners.Select(localCorner => m.transform.TransformPoint(localCorner)).ToArray();
if (relativeTo == null) return globalCorners; if (relativeTo == null) return globalCorners;
return globalCorners.Select(globalCorner => relativeTo.transform.InverseTransformPoint(globalCorner)).ToArray(); return globalCorners.Select(globalCorner => relativeTo.transform.InverseTransformPoint(globalCorner)).ToArray();
@ -213,9 +213,13 @@ namespace NewHorizons.Builder.Props
public MeshFilter meshFilter; public MeshFilter meshFilter;
public SkinnedMeshRenderer skinnedMeshRenderer; public SkinnedMeshRenderer skinnedMeshRenderer;
void Update() public void Update()
{ {
if (meshFilter == null && skinnedMeshRenderer == null) { NHLogger.LogVerbose("Useless BoxShapeFixer, destroying"); DestroyImmediate(this); } if (meshFilter == null && skinnedMeshRenderer == null)
{
NHLogger.LogVerbose("Useless BoxShapeFixer, destroying");
DestroyImmediate(this);
}
Mesh sharedMesh = null; Mesh sharedMesh = null;
if (meshFilter != null) sharedMesh = meshFilter.sharedMesh; if (meshFilter != null) sharedMesh = meshFilter.sharedMesh;
@ -223,7 +227,7 @@ namespace NewHorizons.Builder.Props
if (sharedMesh == null) return; if (sharedMesh == null) return;
if (sharedMesh.bounds.size == Vector3.zero) return; if (sharedMesh.bounds.size == Vector3.zero) return;
shape.size = sharedMesh.bounds.size; shape.size = sharedMesh.bounds.size;
shape.center = sharedMesh.bounds.center; shape.center = sharedMesh.bounds.center;

View File

@ -47,6 +47,7 @@ namespace NewHorizons
// Settings // Settings
public static bool Debug { get; private set; } public static bool Debug { get; private set; }
public static bool VisualizeQuantumObjects { get; private set; }
public static bool VerboseLogs { get; private set; } public static bool VerboseLogs { get; private set; }
public static bool SequentialPreCaching { get; private set; } public static bool SequentialPreCaching { get; private set; }
public static bool CustomTitleScreen { get; private set; } public static bool CustomTitleScreen { get; private set; }
@ -134,6 +135,7 @@ namespace NewHorizons
var currentScene = SceneManager.GetActiveScene().name; var currentScene = SceneManager.GetActiveScene().name;
Debug = config.GetSettingsValue<bool>(nameof(Debug)); Debug = config.GetSettingsValue<bool>(nameof(Debug));
VisualizeQuantumObjects = config.GetSettingsValue<bool>(nameof(VisualizeQuantumObjects));
VerboseLogs = config.GetSettingsValue<bool>(nameof(VerboseLogs)); VerboseLogs = config.GetSettingsValue<bool>(nameof(VerboseLogs));
SequentialPreCaching = config.GetSettingsValue<bool>(nameof(SequentialPreCaching)); SequentialPreCaching = config.GetSettingsValue<bool>(nameof(SequentialPreCaching));

View File

@ -4,16 +4,19 @@ namespace NewHorizons.Utility.Geometry
{ {
public class BoxShapeVisualizer : MonoBehaviour public class BoxShapeVisualizer : MonoBehaviour
{ {
BoxShape box; private BoxShape _box;
void Awake() public void Awake()
{ {
box = GetComponent<BoxShape>(); _box = GetComponent<BoxShape>();
} }
void OnRenderObject() public void OnRenderObject()
{ {
Popcron.Gizmos.Cube(transform.TransformPoint(box.center), transform.rotation, Vector3.Scale(box.size, transform.lossyScale)); if (Main.Debug && Main.VisualizeQuantumObjects)
{
Popcron.Gizmos.Cube(transform.TransformPoint(_box.center), transform.rotation, Vector3.Scale(_box.size, transform.lossyScale));
}
} }
} }
} }

View File

@ -16,6 +16,12 @@
"value": false, "value": false,
"tooltip": "Enables the debug raycast, visible quantum object colliders, and debug options menu." "tooltip": "Enables the debug raycast, visible quantum object colliders, and debug options menu."
}, },
"VisualizeQuantumObjects": {
"title": "Visualize Quantum Objects",
"type": "toggle",
"value": false,
"tooltip": "Draws boundaries around quantum objects when Debug mode is on."
},
"VerboseLogs": { "VerboseLogs": {
"title": "Verbose Logs", "title": "Verbose Logs",
"type": "toggle", "type": "toggle",