Skip to content

Commit daf652b

Browse files
authored
Merge pull request #57 from OpenCommissioning/56-un_boundingbox
56 un boundingbox
2 parents 4fbc595 + 222a151 commit daf652b

13 files changed

Lines changed: 232 additions & 53 deletions

File tree

8.77 KB
Loading

Documentation/Images/BoundBoxColliderSize_Inspector.png.meta

Lines changed: 114 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,6 +1033,13 @@ In this example, groups based on the [`Hierarchy`](#defining-the-device-hierar
10331033
components in the project tree are created in the configuration file that contain
10341034
the devices located within the child objects of these groups.
10351035

1036+
## Useful Functions
1037+
### Auto Box Collider Size
1038+
Calculates and adjusts a GameObject's `Box Collider` to tightly enclose all child `MeshRenderer` meshes.
1039+
In the Unity Editor, select the Material Flow component in the Inspector and open its context menu:
1040+
You can call this function from the Material Flow component’s context menu in the Inspector.
1041+
1042+
![BoundBoxColliderSize_Inspector.png](Documentation/Images/BoundBoxColliderSize_Inspector.png)
10361043

10371044
# Contributing
10381045

Runtime/Scripts/Common/Utils.cs

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using System.Collections;
23
using System.Collections.Generic;
34
using System.Linq;
@@ -98,30 +99,61 @@ public static void Destroy(this Object obj)
9899
Object.Destroy(obj);
99100
}
100101
}
101-
102-
public static Bounds GetLocalBoundsForChildrenMeshes(GameObject go)
102+
103+
/// <summary>
104+
/// Adjusts the GameObject’s BoxCollider to bounding box for all child meshes.
105+
/// </summary>
106+
/// <param name="gameObject">Target GameObject.</param>
107+
/// <param name="boxCollider">The BoxCollider if found and updated; null otherwise.</param>
108+
/// <returns>True if the collider was found and updated; false on error.</returns>
109+
public static bool TryBoundBoxColliderSize(GameObject gameObject, out BoxCollider boxCollider)
103110
{
104-
var referenceTransform = go.transform;
105-
var b = new Bounds(Vector3.zero, Vector3.zero);
106-
RecurseEncapsulate(referenceTransform, ref b);
107-
return b;
108-
109-
void RecurseEncapsulate(Transform child, ref Bounds bounds)
111+
try
110112
{
111-
var mesh = child.GetComponent<MeshFilter>();
112-
if (mesh)
113-
{
114-
var lsBounds = mesh.sharedMesh.bounds;
115-
var wsMin = child.TransformPoint(lsBounds.center - lsBounds.extents);
116-
var wsMax = child.TransformPoint(lsBounds.center + lsBounds.extents);
117-
bounds.Encapsulate(referenceTransform.InverseTransformPoint(wsMin));
118-
bounds.Encapsulate(referenceTransform.InverseTransformPoint(wsMax));
119-
}
120-
foreach (Transform grandChild in child.transform)
113+
if (gameObject == null) throw new NullReferenceException("GameObject is null");
114+
boxCollider = gameObject.GetComponent<BoxCollider>();
115+
if (boxCollider == null)
121116
{
122-
RecurseEncapsulate(grandChild, ref bounds);
117+
throw new NullReferenceException("BoxCollider is null");
123118
}
119+
#if UNITY_EDITOR
120+
UnityEditor.Undo.RecordObject(boxCollider, "Set Box Collider Bound Size");
121+
#endif
122+
var bounds = GetLocalBoundsForChildrenMeshes(gameObject);
123+
boxCollider.center = bounds.center;
124+
boxCollider.size = bounds.size;
125+
126+
#if UNITY_EDITOR
127+
128+
UnityEditor.EditorUtility.SetDirty(gameObject);
129+
#endif
130+
return true;
131+
}
132+
catch (Exception exception)
133+
{
134+
Debug.LogError($"TryBoundBoxColliderSize: {exception}", gameObject);
135+
boxCollider = null;
136+
return false;
137+
}
138+
}
139+
140+
/// <summary>
141+
/// Computes the local-space axis-aligned Bounds that encapsulate all MeshFilter meshes in the given GameObject’s hierarchy.
142+
/// </summary>
143+
/// <param name="gameObject">Target GameObject.</param>
144+
/// <returns>Bounds in the GameObject’s local space covering all child meshes.</returns>
145+
public static Bounds GetLocalBoundsForChildrenMeshes(GameObject gameObject)
146+
{
147+
var transform = gameObject.transform;
148+
var localBounds = new Bounds(Vector3.zero, Vector3.zero);
149+
var filters = gameObject.GetComponentsInChildren<MeshFilter>();
150+
foreach (var meshFilter in filters)
151+
{
152+
var matrix = transform.localToWorldMatrix.inverse * meshFilter.transform.localToWorldMatrix;
153+
var axisAlignedBounds = GeometryUtility.CalculateBounds(meshFilter.sharedMesh.vertices, matrix);
154+
localBounds.Encapsulate(axisAlignedBounds);
124155
}
156+
return localBounds;
125157
}
126158
}
127159
}

Runtime/Scripts/Components/SensorBinary.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,15 @@ private void Reset()
7676
_length.OnValidate();
7777
}
7878

79+
[ContextMenu("Bound Box Collider Size", false, 100)]
80+
public new void BoundBoxColliderSize()
81+
{
82+
if (Utils.TryBoundBoxColliderSize(gameObject, out _))
83+
{
84+
_useBoxCollider = true;
85+
}
86+
}
87+
7988
protected override void OnCollisionChangedAction(bool value)
8089
{
8190
base.OnCollisionChangedAction(value);

Runtime/Scripts/Interactions/Interaction.cs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4-
using NaughtyAttributes;
54
using UnityEngine;
65
using UnityEngine.Events;
76
using UnityEngine.EventSystems;
@@ -64,7 +63,7 @@ protected void OnDestroy()
6463

6564
private void Reset()
6665
{
67-
BoundColliderSize();
66+
BoundBoxColliderSize();
6867
gameObject.layer = (int)DefaultLayers.Interactions;
6968
}
7069

@@ -126,15 +125,13 @@ public void OnPointerUp(PointerEventData eventData)
126125
if (_mode.HasFlag(InteractionMode.Click)) OnPointerUpEvent?.Invoke();
127126
}
128127

129-
[Button]
130-
public void BoundColliderSize()
128+
[ContextMenu("Bound Box Collider Size", false, 100)]
129+
public void BoundBoxColliderSize()
131130
{
132-
var bounds = Utils.GetLocalBoundsForChildrenMeshes(gameObject);
133-
134-
var boxCollider = GetComponent<BoxCollider>();
135-
boxCollider.isTrigger = true;
136-
boxCollider.center = bounds.center;
137-
boxCollider.size = bounds.size;
131+
if (Utils.TryBoundBoxColliderSize(gameObject, out var boxCollider))
132+
{
133+
boxCollider.isTrigger = true;
134+
}
138135
}
139136
}
140137
}

Runtime/Scripts/MaterialFlow/Detector.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,5 +84,11 @@ protected virtual void OnPayloadExitAction(PayloadBase payloadBase)
8484
"Static",
8585
"Storage"
8686
};
87+
88+
[ContextMenu("Bound Box Collider Size", false, 100)]
89+
public void BoundBoxColliderSize()
90+
{
91+
Utils.TryBoundBoxColliderSize(gameObject, out _);
92+
}
8793
}
8894
}

Runtime/Scripts/MaterialFlow/Payload.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ namespace OC.MaterialFlow
88
[SelectionBase]
99
[DisallowMultipleComponent]
1010
[RequireComponent(typeof(Rigidbody))]
11-
[RequireComponent(typeof(BoxCollider))]
1211
public class Payload : PayloadBase, IInteractable
1312
{
1413
public IProperty<ControlState> ControlState => _controlState;
@@ -53,6 +52,7 @@ private void Awake()
5352
{
5453
_rigidbody = GetComponent<Rigidbody>();
5554
_collider = GetComponent<Collider>();
55+
if (_collider == null) Debug.LogError($"Collider not found on {gameObject}", this);
5656
}
5757

5858
private void OnEnable()
@@ -85,6 +85,14 @@ private void OnEnable()
8585
UnregistrateInParent();
8686
}
8787

88+
private void Reset()
89+
{
90+
if (GetComponent<Collider>() == null)
91+
{
92+
gameObject.AddComponent<BoxCollider>();
93+
}
94+
}
95+
8896
public void Registrate(ulong uniqueId = 0)
8997
{
9098
_isRegistered = true;
@@ -97,7 +105,7 @@ public void Unregistrate(ulong uniqueId = 0)
97105
_uniqueId = uniqueId;
98106
}
99107

100-
public void ApplyDiscription(PayloadDescription description)
108+
public void ApplyDescription(PayloadDescription description)
101109
{
102110
Unregistrate(description.UniqueId);
103111
name = description.Name;
@@ -108,6 +116,12 @@ public void ApplyDiscription(PayloadDescription description)
108116
_typeId = description.TypeId;
109117
_parentUniqueId = description.ParentUniqueId;
110118
}
119+
120+
[ContextMenu("Bound Box Collider Size", false, 100)]
121+
public void BoundBoxColliderSize()
122+
{
123+
Utils.TryBoundBoxColliderSize(gameObject, out _);
124+
}
111125

112126
private void OnControlStateChanged(ControlState state)
113127
{

Runtime/Scripts/MaterialFlow/PoolManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public Payload Instantiate(PayloadDescription description)
111111
var payload = Instantiate(description.Transform.GetPosition(), description.Transform.rotation, description.TypeId, description.UniqueId);
112112
if (payload is null) return null;
113113

114-
payload.ApplyDiscription(description);
114+
payload.ApplyDescription(description);
115115

116116
var parent = FindPayload(description.ParentUniqueId);
117117
if (parent is not null)

0 commit comments

Comments
 (0)