@@ -374,7 +374,7 @@ export class ClothSceneController {
374374 tessellationMin : 6 ,
375375 tessellationMax : 24 ,
376376 pointerCollider : false ,
377- pinMode : 'top ' ,
377+ pinMode : 'none ' ,
378378 worldSleepGuardEnabled : true ,
379379 }
380380 private onPointerMove = ( event : PointerEvent ) => this . handlePointerMove ( event )
@@ -523,7 +523,7 @@ export class ClothSceneController {
523523 const screenArea = Math . max ( 1 , vpW * vpH )
524524 const s = Math . sqrt ( area / screenArea ) // proportion of screen by diagonal
525525
526- const MIN_SEGMENTS = clamp ( round ( this . debug . tessellationMin ?? 6 ) , 1 , 40 )
526+ const MIN_SEGMENTS = clamp ( round ( this . debug . tessellationMin ?? 6 ) , 1 , 46 )
527527 const MAX_TESSELLATION_CAP = 48
528528 const rawMax = round ( maxCap )
529529 const maxUser = clamp ( round ( this . debug . tessellationMax ?? maxCap ) , MIN_SEGMENTS + 2 , MAX_TESSELLATION_CAP )
@@ -825,20 +825,44 @@ export class ClothSceneController {
825825 for ( const p of pts ) pins . push ( p )
826826 }
827827 this . overlayState . pinMarkers = pins
828- // Pointer collider radius: derive from first available record ( active or static) to approximate
828+ // Pointer collider radius: derive using shared helper; prefer first active item, else first available
829829 let r = 0.01
830+ let found = false
830831 for ( const item of this . items . values ( ) ) {
831- const record = item . record
832- if ( ! record ) continue
833- const base = Math . min ( record . widthMeters || 0 , record . heightMeters || 0 )
834- const MIN = 0.0006
835- const DEFAULT = 0.0012
836- r = base > 0 ? Math . max ( MIN , base / 12 ) : DEFAULT
832+ if ( ! item . isActive ) continue
833+ r = this . computePointerRadiusFor ( item )
834+ found = true
837835 break
838836 }
837+ if ( ! found ) {
838+ for ( const item of this . items . values ( ) ) {
839+ r = this . computePointerRadiusFor ( item )
840+ found = true
841+ break
842+ }
843+ }
839844 this . overlayState . pointerRadius = r
840845 }
841846
847+ /** Computes pointer collider radius in meters mirroring ClothBodyAdapter.getImpulseRadius logic. */
848+ private computePointerRadiusFor ( item : ClothItem ) {
849+ const attr = item . element . dataset . clothImpulseRadius
850+ const parsed = attr ? Number . parseFloat ( attr ) : NaN
851+ if ( ! Number . isNaN ( parsed ) && parsed > 0 ) {
852+ return parsed
853+ }
854+ const record = item . record
855+ const widthMeters = record ?. widthMeters ?? 0
856+ const heightMeters = record ?. heightMeters ?? 0
857+ const base = Math . min ( widthMeters , heightMeters )
858+ const MIN_POINTER_RADIUS = 0.0006
859+ const DEFAULT_POINTER_RADIUS = 0.0012
860+ if ( base > 0 ) {
861+ return Math . max ( MIN_POINTER_RADIUS , base / 12 )
862+ }
863+ return DEFAULT_POINTER_RADIUS
864+ }
865+
842866 private isSimSnapshot ( value : unknown ) : value is import ( './simWorld' ) . SimWorldSnapshot {
843867 return Boolean ( value && typeof value === 'object' && Array . isArray ( ( value as import ( './simWorld' ) . SimWorldSnapshot ) . bodies ) )
844868 }
0 commit comments