private List <ObjectProximityInfo> FetchObjects(IProximityEffectObjectProvider provider) { var registeredObjects = new List <ObjectProximityInfo>(); provider.ForEachProximityObject(proximityObject => { registeredObjects.Add(new ObjectProximityInfo() { ScaledObject = proximityObject, ObjectVisualRenderer = proximityObject.gameObject.GetComponentInChildren <Renderer>() }); }); return(registeredObjects); }
/// <summary> /// register objects for proximity effect via a <see cref="IProximityEffectObjectProvider"/> /// </summary> public void AddObjects(IProximityEffectObjectProvider provider) { RegisteredObjects registeredObject = new RegisteredObjects() { objectProvider = provider, proximityInfos = new List <ObjectProximityInfo>() }; provider.ForEachProximityObject(proximityObject => { registeredObject.proximityInfos.Add(new ObjectProximityInfo() { ScaledObject = proximityObject, ObjectVisualRenderer = proximityObject.gameObject.GetComponentInChildren <Renderer>() }); }); registeredObjects.Add(registeredObject); }
private void RefreshObjects(IProximityEffectObjectProvider provider) { // refetch object list registeredObjects[provider] = FetchObjects(provider); }
/// <summary> /// register objects for proximity effect via a <see cref="IProximityEffectObjectProvider"/> /// </summary> public void RegisterObjectProvider(IProximityEffectObjectProvider provider) { registeredObjects.Add(provider, FetchObjects(provider)); // subscribe to object changes provider.ProximityObjectsChanged.AddListener(RefreshObjects); }
/// <summary> /// Updates proximity effect and its registered objects. /// Highlights and scales objects in proximity according to the pointer distance /// </summary> /// <param name="boundsCenter">gameobject position the proximity effect is attached to</param> /// <param name="boundsExtents">extents of the gameobject the proximity effect is attached to</param> public void UpdateScaling(Vector3 boundsCenter, Vector3 boundsExtents) { // early out if effect is disabled if (config.ProximityEffectActive == false || !IsAnyRegisteredObjectVisible()) { return; } proximityPointers.Clear(); proximityPoints.Clear(); // Find all valid pointers foreach (var inputSource in CoreServices.InputSystem.DetectedInputSources) { foreach (var pointer in inputSource.Pointers) { // don't use IsInteractionEnabled for near pointers as the pointers might have a different radius when deciding // if they can interact with a near-by object - we might still want to show proximity scaling even if // eg. grab pointer decides it's too far away to actually perform the interaction if (pointer.IsActive && !proximityPointers.Contains(pointer)) { proximityPointers.Add(pointer); } } } // Get the max radius possible of our current bounds and extent the range to include proximity scaled objects. This is done by adjusting the original bounds to include the ObjectMediumProximity range in x, y and z axis float squareMaxLength = boundsExtents.sqrMagnitude + (3 * config.ObjectMediumProximity * config.ObjectMediumProximity); // Grab points within sphere of influence from valid pointers foreach (var pointer in proximityPointers) { if (IsPointWithinBounds(boundsCenter, pointer.Position, squareMaxLength)) { proximityPoints.Add(pointer.Position); } if (pointer.Result?.CurrentPointerTarget != null) { Vector3?point = pointer.Result?.Details.Point; if (point.HasValue && IsPointWithinBounds(boundsCenter, pointer.Result.Details.Point, squareMaxLength)) { proximityPoints.Add(pointer.Result.Details.Point); } } } // Loop through all objects and find closest one Transform closestObject = null; float closestDistanceSqr = float.MaxValue; foreach (var point in proximityPoints) { foreach (var keyValuePair in registeredObjects) { foreach (var item in keyValuePair.Value) { // If object can't be visible, skip calculations if (!keyValuePair.Key.IsActive) { continue; } // Perform comparison on sqr distance since sqrt() operation is expensive in Vector3.Distance() float sqrDistance = (item.ScaledObject.transform.position - point).sqrMagnitude; if (sqrDistance < closestDistanceSqr) { closestObject = item.ScaledObject; closestDistanceSqr = sqrDistance; } } } } // Loop through all objects and update visual state based on closest point foreach (var keyValuePair in registeredObjects) { foreach (var item in keyValuePair.Value) { ProximityState newState = (closestObject == item.ScaledObject) ? GetProximityState(closestDistanceSqr) : ProximityState.FullsizeNoProximity; IProximityEffectObjectProvider provider = keyValuePair.Key; // Only apply updates if object is in a new state or closest object needs to lerp scaling if (item.ProximityState != newState) { // Update and save new state item.ProximityState = newState; if (item.ObjectVisualRenderer) { item.ObjectVisualRenderer.material = newState == ProximityState.CloseProximity ? provider.GetHighlightedMaterial() : provider.GetBaseMaterial(); } } ScaleObject(newState, item.ScaledObject, provider.GetObjectSize(), true); } } }