Exemple #1
0
            internal void OnWorkspaceCreated(IWorkspace workspace)
            {
                var miniWorldWorkspace = workspace as MiniWorldWorkspace;

                if (!miniWorldWorkspace)
                {
                    return;
                }

                miniWorldWorkspace.zoomSliderMax = evr.GetModule <SpatialHashModule>().GetMaxBounds().size.MaxComponent()
                                                   / miniWorldWorkspace.contentBounds.size.MaxComponent();

                var miniWorld = miniWorldWorkspace.miniWorld;

                m_Worlds.Add(miniWorld);

                var intersectionModule = evr.GetModule <IntersectionModule>();

                Rays.ForEachProxyDevice(deviceData =>
                {
                    var miniWorldRayOrigin    = InstantiateMiniWorldRay();
                    miniWorldRayOrigin.parent = workspace.transform;

                    var tester    = miniWorldRayOrigin.GetComponentInChildren <IntersectionTester>();
                    tester.active = false;

                    m_Rays[miniWorldRayOrigin] = new MiniWorldRay
                    {
                        originalRayOrigin = deviceData.rayOrigin,
                        miniWorld         = miniWorld,
                        proxy             = deviceData.proxy,
                        node = deviceData.node,
                        directSelectInput = deviceData.directSelectInput,
                        tester            = tester
                    };

                    intersectionModule.AddTester(tester);

                    evr.GetModule <HighlightModule>().AddRayOriginForNode(deviceData.node, miniWorldRayOrigin);

                    if (deviceData.proxy.active)
                    {
                        if (deviceData.node == Node.LeftHand)
                        {
                            miniWorldWorkspace.leftRayOrigin = deviceData.rayOrigin;
                        }

                        if (deviceData.node == Node.RightHand)
                        {
                            miniWorldWorkspace.rightRayOrigin = deviceData.rayOrigin;
                        }
                    }
                }, false);
            }
            internal void OnWorkspaceCreated(IWorkspace workspace)
            {
                var miniWorldWorkspace = workspace as MiniWorldWorkspace;

                if (!miniWorldWorkspace)
                {
                    return;
                }

                miniWorldWorkspace.zoomSliderMax = evr.GetModule <SpatialHashModule>().GetMaxBounds().size.MaxComponent()
                                                   / miniWorldWorkspace.contentBounds.size.MaxComponent();

                var miniWorld = miniWorldWorkspace.miniWorld;
                var worldID   = m_Worlds.Count;

                miniWorld.miniWorldTransform.name = string.Format("Miniworld {0}", worldID);
                m_Worlds.Add(miniWorld);

                var intersectionModule = evr.GetModule <IntersectionModule>();

                Rays.ForEachProxyDevice(deviceData =>
                {
                    var node      = deviceData.node;
                    var rayOrigin = deviceData.rayOrigin;
                    var proxy     = deviceData.proxy;

                    var miniWorldRayOrigin    = InstantiateMiniWorldRay();
                    miniWorldRayOrigin.name   = string.Format("{0} Miniworld {1} Ray", node, worldID);
                    miniWorldRayOrigin.parent = workspace.transform;

                    var tester    = miniWorldRayOrigin.GetComponentInChildren <IntersectionTester>();
                    tester.active = false;

                    m_Rays[miniWorldRayOrigin] = new MiniWorldRay(rayOrigin, miniWorld, proxy, node, tester);

                    intersectionModule.AddTester(tester);

                    evr.GetModule <HighlightModule>().AddRayOriginForNode(node, miniWorldRayOrigin);

                    if (proxy.active)
                    {
                        if (node == Node.LeftHand)
                        {
                            miniWorldWorkspace.leftRayOrigin = rayOrigin;
                        }

                        if (node == Node.RightHand)
                        {
                            miniWorldWorkspace.rightRayOrigin = rayOrigin;
                        }
                    }
                }, false);
            }
                public void TransferObjects(MiniWorldRay destinationRay, Transform rayOrigin = null)
                {
                    var destinationGrabData = destinationRay.m_GrabData;

                    destinationGrabData.AddRange(m_GrabData);
                    m_GrabData.Clear();
                    destinationRay.dragStartedOutside = dragStartedOutside;

                    if (rayOrigin)
                    {
                        foreach (var grabData in destinationGrabData)
                        {
                            grabData.GetCurrentOffsets(rayOrigin);
                        }
                    }
                }
            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);
                        }

                        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
                foreach (var deviceData in evr.m_DeviceData)
                {
                    var proxy = deviceData.proxy;
                    if (!proxy.active)
                    {
                        continue;
                    }

                    UpdateRayContaimnent(deviceData);
                }
            }
        void CreateWorkspace(Type t, Action <IWorkspace> createdCallback = null)
        {
            var cameraTransform = U.Camera.GetMainCamera().transform;

            var workspace = (IWorkspace)U.Object.CreateGameObjectWithComponent(t, U.Camera.GetViewerPivot());

            m_Workspaces.Add(workspace);
            workspace.destroyed += OnWorkspaceDestroyed;
            ConnectInterfaces(workspace);

            //Explicit setup call (instead of setting up in Awake) because we need interfaces to be hooked up first
            workspace.Setup();

            var offset = kDefaultWorkspaceOffset;

            offset.z += workspace.vacuumBounds.extents.z;

            var workspaceTransform = workspace.transform;

            workspaceTransform.position  = cameraTransform.TransformPoint(offset);
            workspaceTransform.rotation *= Quaternion.LookRotation(cameraTransform.forward) * kDefaultWorkspaceTilt;

            m_Vacuumables.Add(workspace);

            if (createdCallback != null)
            {
                createdCallback(workspace);
            }

            // MiniWorld is a special case that we handle due to all of the mini world interactions
            var miniWorldWorkspace = workspace as MiniWorldWorkspace;

            if (!miniWorldWorkspace)
            {
                return;
            }

            var miniWorld = miniWorldWorkspace.miniWorld;

            m_MiniWorlds.Add(miniWorld);

            ForEachRayOrigin((proxy, rayOriginPair, device, deviceData) =>
            {
                var miniWorldRayOrigin    = InstantiateMiniWorldRay();
                miniWorldRayOrigin.parent = workspace.transform;

#if ENABLE_MINIWORLD_RAY_SELECTION
                // Use the mini world ray origin instead of the original ray origin
                m_InputModule.AddRaycastSource(proxy, rayOriginPair.Key, deviceData.uiInput, miniWorldRayOrigin, (source) =>
                {
                    if (!IsRayActive(source.rayOrigin))
                    {
                        return(false);
                    }

                    if (source.hoveredObject)
                    {
                        return(!m_Workspaces.Any(w => source.hoveredObject.transform.IsChildOf(w.transform)));
                    }

                    return(true);
                });
#endif

                var tester    = miniWorldRayOrigin.GetComponentInChildren <IntersectionTester>();
                tester.active = false;

                m_MiniWorldRays[miniWorldRayOrigin] = new MiniWorldRay
                {
                    originalRayOrigin = rayOriginPair.Value,
                    miniWorld         = miniWorld,
                    proxy             = proxy,
                    node = rayOriginPair.Key,
                    directSelectInput = deviceData.directSelectInput,
                    tester            = tester
                };

                m_IntersectionModule.AddTester(tester);
            }, false);

            UpdatePlayerHandleMaps();
        }
Exemple #6
0
    private void CreateWorkspace(Type t)
    {
        var defaultOffset = Workspace.kDefaultOffset;
        var defaultTilt   = Workspace.kDefaultTilt;

        var     viewerPivot = U.Camera.GetViewerPivot();
        Vector3 position    = viewerPivot.position + defaultOffset;

        Quaternion rotation  = defaultTilt;
        float      arcLength = Mathf.Atan(Workspace.kDefaultBounds.x /
                                          (defaultOffset.z - Workspace.kDefaultBounds.z * 0.5f)) * Mathf.Rad2Deg //Calculate arc length at front of workspace
                               + kWorkspaceAnglePadding;                                                         //Need some extra padding because workspaces are tilted
        float heightOffset = Workspace.kDefaultBounds.y + kWorkspaceYPadding;                                    //Need padding in Y as well

        float currentRotation = arcLength;
        float currentHeight   = 0;

        int     count      = 0;
        int     direction  = 1;
        Vector3 halfBounds = Workspace.kDefaultBounds * 0.5f;

        //While the current position is occupied, try a new one
        while (Physics.CheckBox(position, halfBounds, rotation) && count++ < kMaxWorkspacePlacementAttempts)
        {
            //The next position will be rotated by currentRotation, as if the hands of a clock
            Quaternion rotateAroundY = Quaternion.AngleAxis(currentRotation * direction, Vector3.up);
            position = viewerPivot.position + rotateAroundY * defaultOffset + Vector3.up * currentHeight;
            rotation = rotateAroundY * defaultTilt;

            //Every other iteration, rotate a little further
            if (direction < 0)
            {
                currentRotation += arcLength;
            }

            //Switch directions every iteration (left, right, left, right)
            direction *= -1;

            //If we've one more than half way around, we have tried the whole circle, bump up one level and keep trying
            if (currentRotation > 180)
            {
                direction       = -1;
                currentRotation = 0;
                currentHeight  += heightOffset;
            }
        }

        Workspace workspace = (Workspace)U.Object.CreateGameObjectWithComponent(t, U.Camera.GetViewerPivot());

        m_AllWorkspaces.Add(workspace);
        workspace.destroyed += OnWorkspaceDestroyed;
        ConnectInterfaces(workspace);
        workspace.transform.position = position;
        workspace.transform.rotation = rotation;

        //Explicit setup call (instead of setting up in Awake) because we need interfaces to be hooked up first
        workspace.Setup();

        var miniWorld = workspace as IMiniWorld;

        if (miniWorld == null)
        {
            return;
        }

        m_MiniWorlds.Add(miniWorld);

        foreach (var proxy in m_AllProxies)
        {
            foreach (var rayOriginBase in proxy.rayOrigins)
            {
                foreach (var device in InputSystem.devices)                 // Find device tagged with the node that matches this RayOrigin node
                {
                    var node = GetDeviceNode(device);
                    if (node.HasValue && node.Value == rayOriginBase.Key)
                    {
                        DeviceData deviceData;
                        if (m_DeviceData.TryGetValue(device, out deviceData))
                        {
                            // Create MiniWorld rayOrigin
                            var miniWorldRayOrigin = new GameObject("MiniWorldRayOrigin").transform;
                            miniWorldRayOrigin.parent = workspace.transform;

                            var uiInput = CreateActionMapInput(m_InputModule.actionMap, device);
                            m_PlayerHandle.maps.Insert(m_PlayerHandle.maps.IndexOf(deviceData.uiInput), uiInput);
                            // Add RayOrigin transform, proxy and ActionMapInput references to input module list of sources
                            m_InputModule.AddRaycastSource(proxy, rayOriginBase.Key, uiInput, miniWorldRayOrigin);
                            m_MiniWorldRays[miniWorldRayOrigin] = new MiniWorldRay()
                            {
                                originalRayOrigin = rayOriginBase.Value,
                                miniWorld         = miniWorld,
                                proxy             = proxy,
                                uiInput           = uiInput
                            };
                        }
                        break;
                    }
                }
            }
        }
    }