void UpdateRayContaimnent(DeviceData data)
            {
                bool wasContained;
                var  rayOrigin = data.rayOrigin;

                m_RayWasContained.TryGetValue(rayOrigin, out wasContained);

                var isContained = false;

                foreach (var miniWorld in m_Worlds)
                {
                    isContained |= miniWorld.Contains(rayOrigin.position + rayOrigin.forward * DirectSelection.GetPointerLength(rayOrigin));
                }

                if (isContained && !wasContained)
                {
                    Rays.AddVisibilitySettings(rayOrigin, this, false, true);
                }

                if (!isContained && wasContained)
                {
                    Rays.RemoveVisibilitySettings(rayOrigin, this);
                }

                m_RayWasContained[rayOrigin] = isContained;
            }
Exemplo n.º 2
0
            internal void UpdateMiniWorlds()
            {
                if (m_MiniWorldIgnoreListDirty)
                {
                    UpdateMiniWorldIgnoreList();
                    m_MiniWorldIgnoreListDirty = false;
                }

                var directSelection = evr.GetNestedModule <DirectSelection>();

                // Update MiniWorldRays
                foreach (var ray in m_Rays)
                {
                    var miniWorldRayOrigin = ray.Key;
                    var miniWorldRay       = ray.Value;

                    if (!miniWorldRay.proxy.active)
                    {
                        miniWorldRay.tester.active = false;
                        continue;
                    }

                    var miniWorld    = miniWorldRay.miniWorld;
                    var inverseScale = miniWorld.miniWorldTransform.lossyScale.Inverse();

                    if (float.IsInfinity(inverseScale.x) || float.IsNaN(inverseScale.x))                     // Extreme scales cause transform errors
                    {
                        continue;
                    }

                    // Transform into reference space
                    var originalRayOrigin  = miniWorldRay.originalRayOrigin;
                    var referenceTransform = miniWorld.referenceTransform;
                    var miniWorldTransform = miniWorld.miniWorldTransform;
                    miniWorldRayOrigin.position   = referenceTransform.TransformPoint(miniWorldTransform.InverseTransformPoint(originalRayOrigin.position));
                    miniWorldRayOrigin.rotation   = referenceTransform.rotation * Quaternion.Inverse(miniWorldTransform.rotation) * originalRayOrigin.rotation;
                    miniWorldRayOrigin.localScale = Vector3.Scale(inverseScale, referenceTransform.localScale);

                    // Set miniWorldRayOrigin active state based on whether controller is inside corresponding MiniWorld
                    var originalPointerPosition = originalRayOrigin.position + originalRayOrigin.forward * DirectSelection.GetPointerLength(originalRayOrigin);
                    var isContained             = miniWorld.Contains(originalPointerPosition);
                    miniWorldRay.tester.active = isContained;
                    miniWorldRayOrigin.gameObject.SetActive(isContained);

                    var miniWorldRayObjects = directSelection.GetHeldObjects(miniWorldRayOrigin);
                    var originalRayObjects  = directSelection.GetHeldObjects(originalRayOrigin);

                    var hasPreview = miniWorldRay.hasPreview;
                    if (miniWorldRayObjects == null && originalRayObjects == null && !hasPreview)
                    {
                        miniWorldRay.isContained = isContained;
                        continue;
                    }

                    var wasContained       = miniWorldRay.isContained;
                    var dragStartedOutside = miniWorldRay.dragStartedOutside;
                    if (isContained != wasContained)
                    {
                        // Early out if we grabbed a real-world object that started inside a mini world
                        if (!isContained && miniWorldRayObjects == null)
                        {
                            miniWorldRay.isContained = false;
                            continue;
                        }

                        // Transfer objects to and from original ray and MiniWorld ray (e.g. outside to inside mini world)
                        var from = isContained ? originalRayOrigin : miniWorldRayOrigin;
                        var to   = isContained ? miniWorldRayOrigin : originalRayOrigin;

                        KeyValuePair <Transform, MiniWorldRay>?overlapPair = null;
                        MiniWorldRay incomingPreview = null;

                        // Try to transfer objects between MiniWorlds
                        if (miniWorldRayObjects != null && !isContained)
                        {
                            foreach (var kvp in m_Rays)
                            {
                                var otherRayOrigin = kvp.Key;
                                var otherRay       = kvp.Value;
                                if (originalRayOrigin == otherRay.originalRayOrigin && otherRay != miniWorldRay && otherRay.isContained)
                                {
                                    overlapPair = kvp;
                                    from        = miniWorldRayOrigin;
                                    to          = otherRayOrigin;
                                    break;
                                }
                            }
                        }

                        if (originalRayObjects != null && isContained && !dragStartedOutside)
                        {
                            //Check for other miniworlds' previews entering this ray's miniworld
                            foreach (var kvp in m_Rays)
                            {
                                var otherRay = kvp.Value;
                                if (originalRayOrigin == otherRay.originalRayOrigin && otherRay != miniWorldRay && otherRay.hasObjects)
                                {
                                    incomingPreview = otherRay;
                                    from            = originalRayOrigin;
                                    to = miniWorldRayOrigin;
                                    break;
                                }
                            }
                        }

                        var pointerLengthDiff = DirectSelection.GetPointerLength(to) - DirectSelection.GetPointerLength(from);
                        directSelection.TransferHeldObjects(from, to, Vector3.forward * pointerLengthDiff);

                        if (overlapPair.HasValue)
                        {
                            var kvp = overlapPair.Value;
                            miniWorldRay.TransferObjects(kvp.Value, kvp.Key);
                        }

                        if (incomingPreview != null)
                        {
                            incomingPreview.ExitPreviewMode(this);
                            incomingPreview.TransferObjects(miniWorldRay);
                            directSelection.ResumeGrabbers(incomingPreview.node);
                        }

                        miniWorldRay.UpdatePreview();                         // Otherwise the object is in the wrong position for a frame

                        if (!isContained)
                        {
                            m_RayWasContained[originalRayOrigin] = false;                             //Prevent ray from showing
                        }
                    }

                    if (dragStartedOutside)
                    {
                        miniWorldRay.isContained = isContained;
                        continue;
                    }

                    var node = miniWorldRay.node;

                    if (miniWorldRayObjects != null && !isContained && wasContained)
                    {
                        var containedInOtherMiniWorld = false;
                        foreach (var world in m_Worlds)
                        {
                            if (miniWorld != world && world.Contains(originalPointerPosition))
                            {
                                containedInOtherMiniWorld = true;
                            }
                        }

                        // Transfer objects from miniworld to preview state
                        // Don't switch to previewing the objects we are dragging if we are still in another mini world
                        if (!containedInOtherMiniWorld)
                        {
                            // Check for player head
                            var playerHead = false;
                            foreach (var obj in miniWorldRayObjects)
                            {
                                if (obj.CompareTag(k_VRPlayerTag))
                                {
                                    playerHead = true;
                                    directSelection.DropHeldObjects(node);
                                    break;
                                }
                            }

                            if (!playerHead)
                            {
                                var scaleFactor = this.GetViewerScale() / miniWorld.referenceTransform.localScale.x;
                                miniWorldRay.EnterPreviewMode(this, scaleFactor);
                                directSelection.SuspendGrabbers(node);
                            }
                        }
                    }

                    if (hasPreview)
                    {
                        // Check if we have just entered another miniworld
                        var enterOther = false;
                        foreach (var kvp in m_Rays)
                        {
                            var otherRay       = kvp.Value;
                            var otherMiniWorld = otherRay.miniWorld;
                            if (otherMiniWorld != miniWorld && otherRay.node == node && otherMiniWorld.Contains(originalPointerPosition))
                            {
                                miniWorldRay.ExitPreviewMode(this);
                                directSelection.ResumeGrabbers(node);
                                enterOther = true;
                                break;
                            }
                        }

                        if (!enterOther)
                        {
                            if (!isContained)
                            {
                                miniWorldRay.UpdatePreview();
                            }
                            else if (!wasContained)
                            {
                                miniWorldRay.ExitPreviewMode(this);
                                directSelection.ResumeGrabbers(node);
                            }
                        }
                    }

                    miniWorldRay.isContained = isContained;
                }

                // Update ray visibilities
                Rays.ForEachProxyDevice(data =>
                {
                    bool wasContained;
                    var rayOrigin = data.rayOrigin;
                    m_RayWasContained.TryGetValue(rayOrigin, out wasContained);

                    var isContained = false;
                    foreach (var miniWorld in m_Worlds)
                    {
                        isContained |= miniWorld.Contains(rayOrigin.position + rayOrigin.forward * DirectSelection.GetPointerLength(rayOrigin));
                    }

                    if (isContained && !wasContained)
                    {
                        Rays.AddVisibilitySettings(rayOrigin, this, false, true);
                    }

                    if (!isContained && wasContained)
                    {
                        Rays.RemoveVisibilitySettings(rayOrigin, this);
                    }

                    m_RayWasContained[rayOrigin] = isContained;
                });
            }