Exemplo n.º 1
0
        bool SnapToSurface(Ray ray, ref Vector3 position, ref Quaternion rotation, SnappingState state, Vector3 boundsOffset, Vector3 targetPosition, Quaternion targetRotation, Quaternion rotationOffset, Vector3 upVector, float breakDistance, float raycastDistance)
        {
            RaycastHit hit;
            GameObject go;

            if (raycast(ray, out hit, out go, raycastDistance, m_CombinedIgnoreList))
            {
                var snappedRotation = Quaternion.LookRotation(hit.normal, upVector) * rotationOffset;

                var hitPoint = hit.point;
                m_CurrentSurfaceSnappingHit = hitPoint;
                var snappedPosition = pivotSnappingEnabled ? hitPoint : hitPoint + rotation * boundsOffset;

                if (localOnly && Vector3.Distance(snappedPosition, targetPosition) > breakDistance)
                {
                    return(false);
                }

                state.surfaceSnapping = true;
                state.groundSnapping  = false;

                position = snappedPosition;
                rotation = rotationSnappingEnabled ? snappedRotation : targetRotation;

                m_CurrentSurfaceSnappingPosition = position;
                m_CurrentSurfaceSnappingRotation = snappedRotation;
                return(true);
            }

            return(false);
        }
Exemplo n.º 2
0
    // The tile has 3 states: idle, wrapping and moving
    // If it's on idle and userSwipe transition is fired, it changes to moving
    // If it's on moving and reachedGoal transition is fired, it returns to idle
    // If it's on moving and offGrid is fired, it changes to wrapping
    // If it's on wrapping and finished wrap is fired, it changes to idle
    private void MakeFSM()
    {

        IdleState idle = new IdleState(this);
        idle.AddTransition(Transition.UserSwiped, StateID.Follow);

        FollowState follow = new FollowState(this);
        follow.AddTransition(Transition.FinishedFollow, StateID.Snapping);

        SnappingState snap = new SnappingState(this);
        snap.AddTransition(Transition.FinishedSnapping, StateID.Idle);
        snap.AddTransition(Transition.OffGrid, StateID.Wrapping);

        WrapState wrap = new WrapState(this);
        wrap.AddTransition(Transition.FinishedWrap, StateID.Idle);

        SetupState setup = new SetupState(this);
        setup.AddTransition(Transition.FinishedSetup, StateID.Idle);

        fsm = new FSMSystem();
        fsm.AddState(setup);
        fsm.AddState(idle);
        fsm.AddState(follow);
        fsm.AddState(snap);
        fsm.AddState(wrap);
    }
Exemplo n.º 3
0
        void Update()
        {
            if (snappingEnabled)
            {
                SnappingState surfaceSnapping           = null;
                var           shouldActivateGroundPlane = false;
                foreach (var statesForRay in m_SnappingStates.Values)
                {
                    foreach (var state in statesForRay.Values)
                    {
                        if (state.groundSnapping)
                        {
                            shouldActivateGroundPlane = true;
                        }

                        if (state.surfaceSnapping)
                        {
                            surfaceSnapping = state;
                        }
                    }
                }
                m_GroundPlane.SetActive(shouldActivateGroundPlane);

                if (widgetEnabled)
                {
                    var shouldActivateWidget = surfaceSnapping != null;
                    m_Widget.SetActive(shouldActivateWidget);
                    if (shouldActivateWidget)
                    {
                        var camera           = CameraUtils.GetMainCamera();
                        var distanceToCamera = Vector3.Distance(camera.transform.position, m_CurrentSurfaceSnappingPosition);
                        m_Widget.transform.position   = m_CurrentSurfaceSnappingHit;
                        m_Widget.transform.rotation   = m_CurrentSurfaceSnappingRotation;
                        m_Widget.transform.localScale = Vector3.one * k_WidgetScale * distanceToCamera;
                    }
                }
            }
            else
            {
                m_GroundPlane.SetActive(false);
                m_Widget.SetActive(false);
            }
        }
Exemplo n.º 4
0
        SnappingState GetSnappingState(Transform rayOrigin, GameObject[] objects, Vector3 position, Quaternion rotation)
        {
            Dictionary <GameObject, SnappingState> states;

            if (!m_SnappingStates.TryGetValue(rayOrigin, out states))
            {
                states = new Dictionary <GameObject, SnappingState>();
                m_SnappingStates[rayOrigin] = states;
            }

            var           firstObject = objects[0];
            SnappingState state;

            if (!states.TryGetValue(firstObject, out state))
            {
                state = new SnappingState(objects, position, rotation);
                states[firstObject] = state;
            }
            return(state);
        }
Exemplo n.º 5
0
        bool SnapToSurface(Ray ray, ref Vector3 position, ref Quaternion rotation, SnappingState state, Vector3 boundsOffset, Quaternion targetRotation, Quaternion rotationOffset, Vector3 upVector, float raycastDistance, float maxRayDot = Mathf.Infinity, bool constrained = false)
        {
            RaycastHit hit;
            GameObject go;

            if (this.Raycast(ray, out hit, out go, raycastDistance, m_CombinedIgnoreList))
            {
                if (Vector3.Dot(ray.direction, hit.normal) > maxRayDot)
                {
                    return(false);
                }

                if (!state.surfaceSnapping && hit.distance > raycastDistance * k_SnapDistanceScale)
                {
                    return(false);
                }

                var snappedRotation = Quaternion.LookRotation(hit.normal, upVector) * rotationOffset;

                state.snappingNormal = hit.normal;
                var hitPoint = hit.point;

                var snappedPosition = pivotSnappingEnabled ? hitPoint : hitPoint + boundsOffset;

                state.surfaceSnapping = true;
                state.groundSnapping  = false;

                position = snappedPosition;
                rotation = !constrained && rotationSnappingEnabled ? snappedRotation : targetRotation;

                state.snappingPosition = hitPoint;
                state.snappingRotation = snappedRotation;

                return(true);
            }

            return(false);
        }
Exemplo n.º 6
0
        bool SnapToGround(ref Vector3 position, ref Quaternion rotation, Vector3 targetPosition, Quaternion targetRotation, SnappingState state, float groundSnapMin, float groundSnapMax)
        {
            if (groundSnappingEnabled)
            {
                var diffGround = Mathf.Abs(targetPosition.y - k_GroundHeight);

                var bounds = state.rotatedBounds;
                if (rotationSnappingEnabled)
                {
                    bounds = state.identityBounds;
                }

                var offset = bounds.center.y - bounds.extents.y;

                if (!pivotSnappingEnabled)
                {
                    diffGround = Mathf.Abs(targetPosition.y + offset - k_GroundHeight);
                }

                if (diffGround < groundSnapMin)
                {
                    state.groundSnapping = true;
                }

                if (diffGround > groundSnapMax)
                {
                    state.groundSnapping = false;
                    position             = targetPosition;
                    rotation             = targetRotation;
                }

                if (state.groundSnapping)
                {
                    if (pivotSnappingEnabled)
                    {
                        targetPosition.y = k_GroundHeight;
                    }
                    else
                    {
                        targetPosition.y = k_GroundHeight - offset;
                    }

                    position = targetPosition;

                    if (rotationSnappingEnabled)
                    {
                        rotation = Quaternion.LookRotation(Vector3.up, targetRotation * Vector3.back) * Quaternion.AngleAxis(90, Vector3.right);
                    }

                    return(true);
                }
            }

            return(false);
        }
Exemplo n.º 7
0
        static bool TryBreakSurfaceSnap(ref Vector3 position, ref Quaternion rotation, Vector3 targetPosition, Quaternion targetRotation, SnappingState state, float breakDistance)
        {
            if (state.surfaceSnapping)
            {
                if (Vector3.Distance(position, targetPosition) > breakDistance)
                {
                    position = targetPosition;
                    rotation = targetRotation;
                    state.surfaceSnapping = false;
                }

                return(true);
            }
            return(false);
        }
Exemplo n.º 8
0
        bool DirectSnapToSurface(ref Vector3 position, ref Quaternion rotation, Vector3 targetPosition, SnappingState state, Quaternion targetRotation, float breakDistance)
        {
            var bounds       = state.identityBounds;
            var boundsCenter = bounds.center;

            for (int i = 0; i < k_Directions.Length; i++)
            {
                var direction       = k_Directions[i];
                var upVector        = targetRotation * direction.upVector;
                var directionVector = direction.direction;
                var rotationOffset  = direction.rotationOffset;
                var boundsRay       = new Ray(targetPosition + targetRotation * boundsCenter, targetRotation * directionVector);

                var boundsExtents    = bounds.extents;
                var projectedExtents = Vector3.Project(boundsExtents, directionVector);
                var raycastDistance  = projectedExtents.magnitude * k_DirectSurfaceSearchScale;
                var offset           = -boundsCenter;
                if (i > 2)
                {
                    offset -= projectedExtents;
                }
                else
                {
                    offset += projectedExtents;
                }

                if (SnapToSurface(boundsRay, ref position, ref rotation, state, offset, targetPosition, targetRotation, rotationOffset, upVector, breakDistance, raycastDistance))
                {
                    return(true);
                }
            }

            if (TryBreakSurfaceSnap(ref position, ref rotation, targetPosition, targetRotation, state, breakDistance))
            {
                return(true);
            }

            return(false);
        }
Exemplo n.º 9
0
        bool ManipulatorSnapToSurface(Transform rayOrigin, ref Vector3 position, ref Quaternion rotation, Vector3 targetPosition, SnappingState state, Quaternion targetRotation, float breakDistance)
        {
            var bounds           = state.identityBounds;
            var boundsExtents    = bounds.extents;
            var projectedExtents = Vector3.Project(boundsExtents, Vector3.down);
            var offset           = projectedExtents - bounds.center;
            var rotationOffset   = Quaternion.AngleAxis(90, Vector3.right);
            var startRotation    = state.startRotation;
            var upVector         = startRotation * Vector3.back;
            var maxRayLength     = k_SurfaceSnappingMaxRayLength * this.GetViewerScale();

            var pointerRay = new Ray(rayOrigin.position, rayOrigin.forward);

            return(SnapToSurface(pointerRay, ref position, ref rotation, state, offset, targetPosition, targetRotation, rotationOffset, upVector, breakDistance, maxRayLength) ||
                   TryBreakSurfaceSnap(ref position, ref rotation, targetPosition, startRotation, state, breakDistance));
        }
Exemplo n.º 10
0
        bool SnapToGround(Ray ray, ref Vector3 position, ref Quaternion rotation, Vector3 targetPosition, Quaternion targetRotation, SnappingState state, float raycastDistance, Vector3 boundsOffset = default(Vector3), bool constrained = false)
        {
            if (Mathf.Approximately(Vector3.Dot(ray.direction, Vector3.up), 0))
            {
                return(false);
            }

            var   groundPlane = new Plane(Vector3.up, k_GroundHeight);
            float distance;

            if (groundPlane.Raycast(ray, out distance) && distance <= raycastDistance)
            {
                state.groundSnapping = true;

                state.snappingNormal = -Vector3.Project(ray.direction, Vector3.up).normalized;

                var hitPoint        = ray.origin + ray.direction * distance;
                var snappedPosition = pivotSnappingEnabled ? hitPoint : hitPoint + boundsOffset;
                position = snappedPosition;

                if (!constrained && rotationSnappingEnabled)
                {
                    rotation = Quaternion.LookRotation(Vector3.up, targetRotation * Vector3.back) * Quaternion.AngleAxis(90, Vector3.right);
                }
                else
                {
                    rotation = targetRotation;
                }

                return(true);
            }

            state.groundSnapping = false;
            position             = targetPosition;
            rotation             = targetRotation;

            return(false);
        }
Exemplo n.º 11
0
        bool LocalSnapToSurface(ref Vector3 position, ref Quaternion rotation, Vector3 targetPosition, Quaternion targetRotation, SnappingState state)
        {
            var bounds        = state.identityBounds;
            var boundsCenter  = bounds.center;
            var boundsExtents = bounds.extents;

            var viewerScale   = this.GetViewerScale();
            var breakDistance = viewerScale * k_BreakDistance;

            if (state.snapping)
            {
                var directionIndex  = state.directionIndex;
                var direction       = k_Directions[directionIndex];
                var upVector        = targetRotation * direction.upVector;
                var directionVector = direction.direction;
                var rotationOffset  = direction.rotationOffset;

                var projectedExtents = Vector3.Project(boundsExtents, directionVector);
                var offset           = -boundsCenter;
                if (directionIndex > 2)
                {
                    offset -= projectedExtents;
                }
                else
                {
                    offset += projectedExtents;
                }

                offset = rotation * offset;

                var snappingNormal = state.snappingNormal;
                var breakVector    = targetPosition - position;
                if (Vector3.Dot(snappingNormal, breakVector) < 0)
                {
                    var boundsBreakDist = breakDistance * k_BlockedBreakScale;
                    var raycastDistance = projectedExtents.magnitude + breakVector.magnitude;
                    directionVector = targetRotation * directionVector;

                    var boundsRay = new Ray(targetPosition - Vector3.Project(breakVector, directionVector), directionVector);
                    if (pivotSnappingEnabled)
                    {
                        var extra = k_RayExtra * viewerScale;
                        raycastDistance  += extra;
                        boundsRay.origin -= directionVector * extra;
                    }
                    else
                    {
                        boundsRay.origin += targetRotation * boundsCenter;
                    }

                    if (TryBreakSnap(ref position, ref rotation, targetPosition, targetRotation, state, boundsBreakDist))
                    {
                        return(true);
                    }

                    if (surfaceSnappingEnabled && SnapToSurface(boundsRay, ref position, ref rotation, state, offset, targetRotation, rotationOffset, upVector, raycastDistance))
                    {
                        return(true);
                    }

                    if (groundSnappingEnabled && SnapToGround(boundsRay, ref position, ref rotation, targetPosition, targetRotation, state, raycastDistance, offset))
                    {
                        return(true);
                    }

                    return(true);
                }

                if (TryBreakSnap(ref position, ref rotation, targetPosition, targetRotation, state, breakDistance))
                {
                    return(true);
                }
            }

            for (var i = 0; i < k_Directions.Length; i++)
            {
                var direction       = k_Directions[i];
                var upVector        = targetRotation * direction.upVector;
                var directionVector = direction.direction;
                var rotationOffset  = direction.rotationOffset;
                var offset          = Vector3.zero;
                if (!pivotSnappingEnabled)
                {
                    var projectedExtents = Vector3.Project(boundsExtents, directionVector);
                    offset = -boundsCenter;
                    if (i > 2)
                    {
                        offset -= projectedExtents;
                    }
                    else
                    {
                        offset += projectedExtents;
                    }

                    offset = rotation * offset;
                }

                var raycastDistance = breakDistance * 2;
                directionVector = targetRotation * directionVector;
                var boundsRay = new Ray(targetPosition - offset - directionVector * breakDistance, directionVector);

                if (surfaceSnappingEnabled && SnapToSurface(boundsRay, ref position, ref rotation, state, offset, targetRotation, rotationOffset, upVector, raycastDistance, k_MaxRayDot))
                {
                    state.directionIndex = i;
                    return(true);
                }

                if (groundSnappingEnabled && SnapToGround(boundsRay, ref position, ref rotation, targetPosition, targetRotation, state, raycastDistance, offset))
                {
                    state.directionIndex = i;
                    return(true);
                }
            }

            if (TryBreakSnap(ref position, ref rotation, targetPosition, targetRotation, state, breakDistance))
            {
                return(true);
            }

            if (TryBreakSnap(ref position, ref rotation, state.snappingPosition, targetRotation, state, breakDistance))
            {
                return(true);
            }

            return(false);
        }
Exemplo n.º 12
0
        bool ManipulatorSnapConstrained(ref Vector3 position, ref Quaternion rotation, Vector3 delta, Vector3 targetPosition, Quaternion targetRotation, SnappingState state, float raycastDistance, AxisFlags constraints, PivotMode pivotMode)
        {
            var rotationOffset = Quaternion.AngleAxis(90, Vector3.right);
            var startRotation  = state.startRotation;
            var upVector       = startRotation * Vector3.back;

            var direction        = delta.normalized;
            var bounds           = state.identityBounds;
            var projectedExtents = Vector3.Project(rotation * bounds.extents, direction);
            var axisRay          = new Ray(targetPosition, direction);

            var objectCenter = Vector3.zero;
            var offset       = Vector3.zero;

            if (!pivotSnappingEnabled)
            {
                objectCenter = targetPosition;
                if (pivotMode != PivotMode.Center)
                {
                    objectCenter += targetRotation * state.identityBounds.center;
                }

                switch (constraints)
                {
                case AxisFlags.X:
                    if (Vector3.Dot(rotation * Vector3.right, direction) > 0)
                    {
                        projectedExtents *= -1;
                    }
                    break;

                case AxisFlags.Y:
                    if (Vector3.Dot(rotation * Vector3.up, direction) > 0)
                    {
                        projectedExtents *= -1;
                    }
                    break;

                case AxisFlags.Z:
                    if (Vector3.Dot(rotation * Vector3.forward, direction) > 0)
                    {
                        projectedExtents *= -1;
                    }
                    break;
                }

                axisRay.origin = objectCenter - projectedExtents;
                offset         = targetPosition - axisRay.origin;
            }

            if (state.snapping)
            {
                var breakDistance = raycastDistance;
                if (Vector3.Dot(targetPosition - position, state.snappingNormal) < 0)
                {
                    breakDistance *= k_BlockedBreakScale;
                }

                TryBreakSnap(ref position, ref rotation, targetPosition, startRotation, state, breakDistance);
                return(true);
            }

            if (surfaceSnappingEnabled && SnapToSurface(axisRay, ref position, ref rotation, state, offset, targetRotation, rotationOffset, upVector, raycastDistance, constrained: true))
            {
                return(true);
            }

            if (groundSnappingEnabled && SnapToGround(axisRay, ref position, ref rotation, targetPosition, targetRotation, state, raycastDistance, offset, true))
            {
                return(true);
            }

            // Check other direction
            axisRay.direction *= -1;
            if (!pivotSnappingEnabled)
            {
                axisRay.origin = objectCenter + projectedExtents;
                offset         = targetPosition - axisRay.origin;
            }

            if (surfaceSnappingEnabled && SnapToSurface(axisRay, ref position, ref rotation, state, offset, targetRotation, rotationOffset, upVector, raycastDistance, constrained: true))
            {
                return(true);
            }

            if (groundSnappingEnabled && SnapToGround(axisRay, ref position, ref rotation, targetPosition, targetRotation, state, raycastDistance, offset, true))
            {
                return(true);
            }

            if (TryBreakSnap(ref position, ref rotation, targetPosition, startRotation, state, raycastDistance))
            {
                return(true);
            }

            return(false);
        }