internal SpatialScrollData PerformScroll(IControlSpatialScrolling caller, Node node, Vector3 startingPosition, Vector3 currentPosition, float repeatingScrollLengthRange, int scrollableItemCount, int maxItemCount = -1, bool centerScrollVisuals = true) { // Continue processing of spatial scrolling for a given caller, // Or create new instance of scroll data for new callers. (Initial structure for support of simultaneous callers) SpatialScrollData scrollData = null; foreach (var scroller in m_ScrollCallers) { if (scroller == caller) { scrollData = scroller.spatialScrollData; scrollData.UpdateExistingScrollData(currentPosition); break; } } if (scrollData == null) { scrollData = new SpatialScrollData(caller, node, startingPosition, currentPosition, repeatingScrollLengthRange, scrollableItemCount, maxItemCount, centerScrollVisuals); m_ScrollCallers.Add(caller); this.AddRayVisibilitySettings(scrollData.rayOrigin, caller, false, false, 1); } var directionVector = currentPosition - startingPosition; if (scrollData.spatialDirection == null) { var newDirectionVectorThreshold = 0.0175f; // Initial magnitude beyond which spatial scrolling will be evaluated newDirectionVectorThreshold *= this.GetViewerScale(); var dragMagnitude = Vector3.Magnitude(directionVector); var dragPercentage = dragMagnitude / newDirectionVectorThreshold; const int kPulseSpeedMultiplier = 20; const float kPulseThreshold = 0.5f; const float kPulseOnAmount = 1f; const float kPulseOffAmount = 0f; var repeatingPulseAmount = Mathf.Sin(Time.realtimeSinceStartup * kPulseSpeedMultiplier) > kPulseThreshold ? kPulseOnAmount : kPulseOffAmount; // Perform an on/off repeating pulse while waiting for the drag threshold to be crossed scrollData.dragDistance = dragMagnitude > 0 ? dragPercentage : 0f; // Set value representing how much of the pre-scroll drag amount has occurred this.Pulse(node, m_ActivationPulse, repeatingPulseAmount, repeatingPulseAmount); if (dragMagnitude > newDirectionVectorThreshold) { scrollData.spatialDirection = directionVector; // Initialize vector defining the spatial scroll direction } } else { var spatialDirection = scrollData.spatialDirection.Value; var scrollingAfterTriggerOirigin = Vector3.Dot(directionVector, spatialDirection) >= 0; // Detect that the user is scrolling forward from the trigger origin point var projectionVector = scrollingAfterTriggerOirigin ? spatialDirection : spatialDirection + spatialDirection; var projectedAmount = Vector3.Project(directionVector, projectionVector).magnitude / this.GetViewerScale(); // Mandate that scrolling maintain the initial direction, regardless of the user scrolling before/after the trigger origin point; prevent direction flipping projectedAmount = scrollingAfterTriggerOirigin ? projectedAmount : 1 - projectedAmount; scrollData.normalizedLoopingPosition = (Mathf.Abs(projectedAmount * (maxItemCount / scrollableItemCount)) % repeatingScrollLengthRange) * (1 / repeatingScrollLengthRange); } return(scrollData); }
public SpatialScrollData(IControlSpatialScrolling caller, Node node, Vector3 startingPosition, Vector3 currentPosition, float repeatingScrollLengthRange, int scrollableItemCount, int maxItemCount = -1, bool centerVisuals = true) { this.caller = caller; this.node = node; this.startingPosition = startingPosition; this.currentPosition = currentPosition; this.repeatingScrollLengthRange = repeatingScrollLengthRange; this.scrollableItemCount = scrollableItemCount; this.maxItemCount = maxItemCount; this.centerVisuals = centerVisuals; spatialDirection = null; rayOrigin = this.RequestRayOriginFromNode(node); }
internal void EndScroll(IControlSpatialScrolling caller) { if (m_ScrollCallers.Count == 0) { return; } foreach (var scroller in m_ScrollCallers) { if (scroller == caller) { this.RemoveRayVisibilitySettings(caller.spatialScrollData.rayOrigin, caller); this.SetSpatialHintState(SpatialHintState.Hidden); caller.spatialScrollData = null; // clear reference to the previously used scrollData m_ScrollCallers.Remove(caller); return; } } }
/// <summary> /// End a spatial scrolling action for a given caller /// </summary> /// "obj" : The caller whose spatial scroll action will be ended public static void EndSpatialScroll(this IControlSpatialScrolling obj) { endSpatialScroll(obj); }
/// <summary> /// Perform a spatial scroll action /// </summary> /// "obj" : The object requesting the performance of a spatial scroll action /// <param name="node">The node on which to display & perform the spatial scroll</param> /// <param name="startingPosition">The initial position of the spatial scroll</param> /// <param name="currentPosition">The current/updated position of the spatial scroll</param> /// <param name="repeatingScrollLengthRange">The length at which a scroll action will return a repeating/looping value</param> /// <param name="scrollableItemCount">The number of items being scrolled through with this action</param> /// <param name="maxItemCount">The maximum number of items that can be scrolled through for this action</param> /// <param name="centerVisuals">If true, expand the scroll line visuals outward in both directions from the scroll start position</param> /// <returns>The spatial scroll data for a single scroll action, but an individual caller object</returns> public static SpatialScrollModule.SpatialScrollData PerformSpatialScroll(this IControlSpatialScrolling obj, Node node, Vector3 startingPosition, Vector3 currentPosition, float repeatingScrollLengthRange, int scrollableItemCount, int maxItemCount = -1, bool centerVisuals = true) { return(performSpatialScroll(obj, node, startingPosition, currentPosition, repeatingScrollLengthRange, scrollableItemCount, maxItemCount, centerVisuals)); }