@@ -12,6 +12,7 @@ local StaticPartMonitors = {};
1212local RecalculateStaticExtents = true ;
1313local AggregatingStaticParts = false ;
1414local StaticPartAggregators = {};
15+ local PotentialPartMonitors = {};
1516
1617function BoundingBoxModule .StartBoundingBox (HandleAttachmentCallback )
1718 -- Creates and starts a selection bounding box
@@ -40,12 +41,15 @@ function BoundingBoxModule.StartBoundingBox(HandleAttachmentCallback)
4041 RecalculateStaticExtents = true ;
4142 StartAggregatingStaticParts ();
4243
44+ -- Store handle attachment callback
45+ BoundingBoxHandleCallback = HandleAttachmentCallback ;
46+
4347 -- Begin the bounding box's updater
44- BoundingBoxUpdater = Support .ScheduleRecurringTask (UpdateBoundingBox , 0.05 );
48+ BoundingBoxModule .UpdateBoundingBox ();
49+ BoundingBoxUpdater = Support .ScheduleRecurringTask (BoundingBoxModule .UpdateBoundingBox , 0.05 );
4550
4651 -- Attach handles if requested
47- if HandleAttachmentCallback then
48- BoundingBoxHandleCallback = HandleAttachmentCallback ;
52+ if BoundingBoxHandleCallback then
4953 BoundingBoxHandleCallback (BoundingBox );
5054 end ;
5155
@@ -59,7 +63,20 @@ function BoundingBoxModule.GetBoundingBox()
5963
6064end ;
6165
62- function UpdateBoundingBox ()
66+ function IsPhysicsStatic ()
67+ -- Returns whether the game's physics are active or static
68+
69+ -- Determine value if not yet cached
70+ if _IsPhysicsStatic == nil then
71+ _IsPhysicsStatic = (Core .Mode == ' Plugin' ) and (Workspace .DistributedGameTime == 0 );
72+ end ;
73+
74+ -- Return cached value
75+ return _IsPhysicsStatic ;
76+
77+ end ;
78+
79+ function BoundingBoxModule .UpdateBoundingBox ()
6380 -- Updates the bounding box to fit the selection's extents
6481
6582 -- Make sure the bounding box is enabled
@@ -140,24 +157,13 @@ function AddStaticParts(Parts)
140157 for _ , Part in pairs (Parts ) do
141158
142159 -- Ensure part isn't already indexed, and verify it is static
143- if not StaticPartsIndex [Part ] and Part .Anchored then
160+ if not StaticPartsIndex [Part ] and ( IsPhysicsStatic () or Part .Anchored ) then
144161
145162 -- Add part to static index
146163 StaticPartsIndex [Part ] = true ;
147164
148- -- Start monitoring part for changes
149- StaticPartMonitors [Part ] = Part .Changed :connect (function (Property )
150-
151- -- Trigger static extent recalculations on position or size changes
152- if Property == ' CFrame' or Property == ' Size' then
153- RecalculateStaticExtents = true ;
154-
155- -- Remove part from static index if it becomes mobile
156- elseif Property == ' Anchored' and not Part .Anchored then
157- RemoveStaticParts { Part };
158- end ;
159-
160- end );
165+ -- Monitor static part for changes
166+ AddStaticPartMonitor (Part );
161167
162168 end ;
163169
@@ -171,6 +177,30 @@ function AddStaticParts(Parts)
171177
172178end ;
173179
180+ function AddStaticPartMonitor (Part )
181+ -- Monitors the given part to track when it is no longer static
182+
183+ -- Ensure part isn't already monitored
184+ if not StaticPartsIndex [Part ] then
185+ return ;
186+ end ;
187+
188+ -- Start monitoring part for changes
189+ StaticPartMonitors [Part ] = Part .Changed :connect (function (Property )
190+
191+ -- Trigger static extent recalculations on position or size changes
192+ if Property == ' CFrame' or Property == ' Size' then
193+ RecalculateStaticExtents = true ;
194+
195+ -- Remove part from static index if it becomes mobile
196+ elseif Property == ' Anchored' and not IsPhysicsStatic () and not Part .Anchored then
197+ RemoveStaticParts { Part };
198+ end ;
199+
200+ end );
201+
202+ end ;
203+
174204function RemoveStaticParts (Parts )
175205 -- Removes the given parts from the static parts index
176206
@@ -203,12 +233,8 @@ function StartAggregatingStaticParts()
203233 AddStaticParts (Core .Selection .Items );
204234
205235 -- Watch for parts that become static
206- for _ , Part in pairs (Core .Selection .Items ) do
207- table.insert (StaticPartAggregators , Part .Changed :connect (function (Property )
208- if Property == ' Anchored' and Part .Anchored then
209- AddStaticParts { Part };
210- end ;
211- end ));
236+ for Part in pairs (Core .Selection .ItemIndex ) do
237+ AddPotentialPartMonitor (Part );
212238 end ;
213239
214240 -- Watch newly selected parts
@@ -219,22 +245,92 @@ function StartAggregatingStaticParts()
219245
220246 -- Watch for parts that become anchored
221247 for _ , Part in pairs (Parts ) do
222- table.insert (StaticPartAggregators , Part .Changed :connect (function (Property )
223- if Property == ' Anchored' and Part .Anchored then
224- AddStaticParts { Part };
225- end ;
226- end ));
248+ AddPotentialPartMonitor (Part );
227249 end ;
228250
229251 end ));
230252
231253 -- Remove deselected parts from static parts index
232254 table.insert (StaticPartAggregators , Core .Selection .ItemsRemoved :connect (function (Parts )
233255 RemoveStaticParts (Parts );
256+ for _ , Part in pairs (Parts ) do
257+ if PotentialPartMonitors [Part ] then
258+ PotentialPartMonitors [Part ]:disconnect ();
259+ PotentialPartMonitors [Part ] = nil ;
260+ end ;
261+ end ;
234262 end ));
235263
236264end ;
237265
266+ function BoundingBoxModule .RecalculateStaticExtents ()
267+ -- Sets flag indicating that extents of static items should be recalculated
268+
269+ -- Set flag to trigger recalculation on the next step in the update loop
270+ RecalculateStaticExtents = true ;
271+
272+ end ;
273+
274+ function AddPotentialPartMonitor (Part )
275+ -- Monitors the given part to track when it becomes static
276+
277+ -- Ensure part is not already monitored
278+ if PotentialPartMonitors [Part ] then
279+ return ;
280+ end ;
281+
282+ -- Create anchored state change monitor
283+ PotentialPartMonitors [Part ] = Part .Changed :connect (function (Property )
284+ if Property == ' Anchored' and Part .Anchored then
285+ AddStaticParts { Part };
286+ end ;
287+ end );
288+
289+ end ;
290+
291+ function BoundingBoxModule .PauseMonitoring ()
292+ -- Disables part monitors
293+
294+ -- Disconnect all potential part monitors
295+ for Part , Monitor in pairs (PotentialPartMonitors ) do
296+ Monitor :disconnect ();
297+ PotentialPartMonitors [Part ] = nil ;
298+ end ;
299+
300+ -- Disconnect all static part monitors
301+ for Part , Monitor in pairs (StaticPartMonitors ) do
302+ Monitor :disconnect ();
303+ StaticPartMonitors [Part ] = nil ;
304+ end ;
305+
306+ -- Stop update loop
307+ if BoundingBoxUpdater then
308+ BoundingBoxUpdater :Stop ();
309+ BoundingBoxUpdater = nil ;
310+ end ;
311+
312+ end ;
313+
314+ function BoundingBoxModule .ResumeMonitoring ()
315+ -- Starts update loop and part monitors for selected and indexed parts
316+
317+ -- Start static part monitors
318+ for StaticPart in pairs (StaticPartsIndex ) do
319+ AddStaticPartMonitor (StaticPart );
320+ end ;
321+
322+ -- Start potential part monitors
323+ for Part in pairs (Core .Selection .ItemIndex ) do
324+ AddPotentialPartMonitor (Part );
325+ end ;
326+
327+ -- Start update loop
328+ if not BoundingBoxUpdater then
329+ BoundingBoxUpdater = Support .ScheduleRecurringTask (BoundingBoxModule .UpdateBoundingBox , 0.05 );
330+ end ;
331+
332+ end ;
333+
238334function StopAggregatingStaticParts ()
239335 -- Stops looking for static parts, clears unnecessary data
240336
@@ -250,6 +346,12 @@ function StopAggregatingStaticParts()
250346 StaticPartMonitors [MonitorKey ] = nil ;
251347 end ;
252348
349+ -- Remove all potential part monitors
350+ for MonitorKey , Monitor in pairs (PotentialPartMonitors ) do
351+ Monitor :disconnect ();
352+ PotentialPartMonitors [MonitorKey ] = nil ;
353+ end ;
354+
253355 -- Clear all static part information
254356 StaticParts = {};
255357 StaticPartsIndex = {};
@@ -283,7 +385,7 @@ function BoundingBoxModule.CalculateExtents(Items, StaticExtents, ExtentsOnly)
283385 for _ , Part in pairs (Items ) do
284386
285387 -- Avoid re-calculating for static parts
286- if not (Part .Anchored and StaticExtents ) then
388+ if not (( IsPhysicsStatic () or Part .Anchored ) and StaticExtents ) then
287389
288390 -- Get shortcuts to part data
289391 local PartCFrame = Part .CFrame ;
0 commit comments