void OnTriggerExit(Collider otherCollider) { DistanceGrabbable dg = otherCollider.GetComponentInChildren <DistanceGrabbable>(); if (dg) { dg.InRange = false; } }
void Unhighlight(DistanceGrabbable grabbable) { if (!outlines.ContainsKey(grabbable)) { throw new ArgumentOutOfRangeException(string.Format("Grabbable {0} hasn't been highlighted!", grabbable)); } Destroy(outlines[grabbable].gameObject); outlines.Remove(grabbable); }
protected override void GrabBegin() { DistanceGrabbable closestGrabbable = m_target; Collider closestGrabbableCollider = m_targetCollider; GrabVolumeEnable(false); if (closestGrabbable != null) { if (closestGrabbable.isGrabbed) { ((DistanceGrabber)closestGrabbable.grabbedBy).OffhandGrabbed(closestGrabbable); } m_grabbedObj = closestGrabbable; m_grabbedObj.GrabBegin(this, closestGrabbableCollider); m_movingObjectToHand = true; m_lastPos = transform.position; m_lastRot = transform.rotation; // If it's within a certain distance respect the no-snap. Vector3 closestPointOnBounds = closestGrabbableCollider.ClosestPointOnBounds(m_gripTransform.position); if (!m_grabbedObj.snapPosition && !m_grabbedObj.snapOrientation && m_noSnapThreshhold > 0.0f && (closestPointOnBounds - m_gripTransform.position).magnitude < m_noSnapThreshhold) { Vector3 relPos = m_grabbedObj.transform.position - transform.position; m_movingObjectToHand = false; relPos = Quaternion.Inverse(transform.rotation) * relPos; m_grabbedObjectPosOff = relPos; Quaternion relOri = Quaternion.Inverse(transform.rotation) * m_grabbedObj.transform.rotation; m_grabbedObjectRotOff = relOri; } else { // Set up offsets for grabbed object desired position relative to hand. m_grabbedObjectPosOff = m_gripTransform.localPosition; if (m_grabbedObj.snapOffset) { Vector3 snapOffset = m_grabbedObj.snapOffset.position; if (m_controller == OVRInput.Controller.LTouch) { snapOffset.x = -snapOffset.x; } m_grabbedObjectPosOff += snapOffset; } m_grabbedObjectRotOff = m_gripTransform.localRotation; if (m_grabbedObj.snapOffset) { m_grabbedObjectRotOff = m_grabbedObj.snapOffset.rotation * m_grabbedObjectRotOff; } } } }
protected bool FindTargetWithSpherecast(out DistanceGrabbable dgOut, out Collider collOut) { dgOut = null; collOut = null; Ray ray = new Ray(m_gripTransform.position, m_gripTransform.forward); RaycastHit hitInfo; // If no objects in grab volume, raycast. // Potential optimization: // In DistanceGrabbable.RefreshCrosshairs, we could move the object between collision layers. // If it's in range, it would move into the layer DistanceGrabber.m_grabObjectsInLayer, // and if out of range, into another layer so it's ignored by DistanceGrabber's SphereCast. // However, we're limiting the SphereCast by m_maxGrabDistance, so the optimization doesn't seem // essential. if (Physics.SphereCast(ray, m_spherecastRadius, out hitInfo, m_maxGrabDistance, 1 << m_grabObjectsInLayer)) { DistanceGrabbable grabbable = null; Collider hitCollider = null; if (hitInfo.collider != null) { grabbable = hitInfo.collider.gameObject.GetComponentInParent <DistanceGrabbable>(); hitCollider = grabbable == null ? null : hitInfo.collider; } if (grabbable != null && m_preventGrabThroughWalls) { // Found a valid hit. Now test to see if it's blocked by collision. RaycastHit obstructionHitInfo; ray.direction = hitInfo.point - m_gripTransform.position; dgOut = grabbable; collOut = hitCollider; if (Physics.Raycast(ray, out obstructionHitInfo, 1 << m_obstructionLayer)) { DistanceGrabbable obstruction = null; if (hitInfo.collider != null) { obstruction = obstructionHitInfo.collider.gameObject.GetComponentInParent <DistanceGrabbable>(); } if (obstruction != grabbable && obstructionHitInfo.distance < hitInfo.distance) { dgOut = null; collOut = null; } } } } return(dgOut != null); }
void Hightlight(DistanceGrabbable grabbable) { if (outlines.ContainsKey(grabbable)) { throw new ArgumentOutOfRangeException(string.Format("Grabbable {0} is already highlighted!", grabbable)); } var outlineInstance = Instantiate(outlinePrefab, grabbable.meshFilter.transform); outlineInstance.transform.localPosition = Vector3.zero; outlineInstance.transform.localRotation = Quaternion.identity; outlineInstance.transform.localScale = Vector3.one * (1 + width); outlineInstance.mesh = grabbable.meshFilter.mesh; outlines[grabbable] = outlineInstance; }
void Update() { DistanceGrabbable target; Collider targetColl; FindTarget(out target, out targetColl); if (target != m_target) { if (m_target != null) { //m_target.Highlight = m_otherHand.m_target == m_target; m_target.Targeted = m_otherHand.m_target == m_target; } m_target = target; m_targetCollider = targetColl; if (m_target != null) { //m_target.Highlight = true; m_target.Targeted = true; } } }
protected bool FindTarget(out DistanceGrabbable dgOut, out Collider collOut) { dgOut = null; collOut = null; float closestMagSq = float.MaxValue; // First test for objects within the grab volume, if we're using those. // (Some usage of DistanceGrabber will not use grab volumes, and will only // use spherecasts, and that's supported.) foreach (ColorGrabbable cg in m_grabCandidates.Keys) { DistanceGrabbable grabbable = cg as DistanceGrabbable; bool canGrab = grabbable != null && grabbable.InRange && !(grabbable.isGrabbed && !grabbable.allowOffhandGrab); if (!canGrab) { continue; } for (int j = 0; j < grabbable.grabPoints.Length; ++j) { Collider grabbableCollider = grabbable.grabPoints[j]; // Store the closest grabbable Vector3 closestPointOnBounds = grabbableCollider.ClosestPointOnBounds(m_gripTransform.position); float grabbableMagSq = (m_gripTransform.position - closestPointOnBounds).sqrMagnitude; if (grabbableMagSq < closestMagSq) { bool accept = true; if (m_preventGrabThroughWalls) { // NOTE: if this raycast fails, ideally we'd try other rays near the edges of the object, especially for large objects. // NOTE 2: todo optimization: sort the objects before performing any raycasts. Ray ray = new Ray(); ray.direction = grabbable.transform.position - m_gripTransform.position; ray.origin = m_gripTransform.position; RaycastHit obstructionHitInfo; Debug.DrawRay(ray.origin, ray.direction, Color.red, 0.1f); if (Physics.Raycast(ray, out obstructionHitInfo, m_maxGrabDistance, 1 << m_obstructionLayer)) { float distToObject = (grabbableCollider.ClosestPointOnBounds(m_gripTransform.position) - m_gripTransform.position).magnitude; if (distToObject > obstructionHitInfo.distance * 1.1) { accept = false; } } } if (accept) { closestMagSq = grabbableMagSq; dgOut = grabbable; collOut = grabbableCollider; } } } } if (dgOut == null && m_useSpherecast) { return(FindTargetWithSpherecast(out dgOut, out collOut)); } return(dgOut != null); }
protected override void GrabBegin() { DistanceGrabbable closestGrabbable = m_target; Collider closestGrabbableCollider = m_targetCollider; GrabVolumeEnable(false); if (closestGrabbable != null) { if (closestGrabbable.isGrabbed) { ((DistanceGrabber)closestGrabbable.grabbedBy).OffhandGrabbed(closestGrabbable); } m_grabbedObj = closestGrabbable; m_grabbedObj.GetComponent <Rigidbody>().constraints = RigidbodyConstraints.None; if (graph == null) { graph = TGraph.GlobalVariables.Graph; handIndex = graph.handIndex; graph.handIndex++; } SelectNode(closestGrabbable.transform.GetSiblingIndex()); Debug.Log(graph.selectedNodes[handIndex] + " other:" + graph.selectedNodes[(handIndex + 1) % 2]); /* * for (int i = 0; i < removeList.Count; i++) * { * int idx = removeList[i]; * * graph.selectedNodes.Remove(graph.nodes[idx]); * * if (!graph.selectedNodes.Contains(graph.nodes[idx])) * { * graph.nodes[idx].labelObject.GetComponent<TextMesh>().color = new Color(0.87f, 0.87f, 0.7f); * foreach (int nidx in graph.nodes[idx].connectedNodes) * { * graph.nodes[nidx].labelObject.layer = 18; * graph.nodes[nidx].labelObject.GetComponent<TextMesh>().color = new Color(0.87f, 0.87f, 0.7f); * } * GameObject.Destroy(graph.nodes[idx].nodeEdgeObject); * } * * * removeList.Remove(idx); * i--; * * } * * * * if (!graph.selectedNodes.Contains(graph.nodes[nodeId])) * { * var edges = new List<TGraph.ReadJSON.MyEdge>(); * // foreach (TGraph.ReadJSON.MyNode node in graph.selectedNodes) * { * TGraph.ReadJSON.MyNode node = graph.nodes[nodeId]; * * node.labelObject.GetComponent<TextMesh>().color = new Color(0.6f, 0.6f, 0.05f); * foreach (int nidx in node.connectedNodes) * { * graph.nodes[nidx].labelObject.layer = 0; * graph.nodes[nidx].labelObject.GetComponent<TextMesh>().color = new Color(0.6f, 0.6f, 0.05f); * } * foreach (int idx in node.edgeIndicesIn) * { * edges.Add(graph.edges[idx]); * } * foreach (int idx in node.edgeIndicesOut) * { * edges.Add(graph.edges[idx]); * } * } * * graph.nodes[nodeId].nodeEdgeObject = TGraph.ReadJSON.BuildEdges(edges, graph, graph.nodeDict, graph.edgeObject.GetComponent<MeshRenderer>().sharedMaterial); * graph.selectedNodes.Add(graph.nodes[nodeId]); * }*/ m_grabbedObj.GrabBegin(this, closestGrabbableCollider); m_movingObjectToHand = true; m_lastPos = transform.position; m_lastRot = transform.rotation; // If it's within a certain distance respect the no-snap. Vector3 closestPointOnBounds = closestGrabbableCollider.ClosestPointOnBounds(m_gripTransform.position); if (!m_grabbedObj.snapPosition && !m_grabbedObj.snapOrientation && m_noSnapThreshhold > 0.0f && (closestPointOnBounds - m_gripTransform.position).magnitude < m_noSnapThreshhold) { Vector3 relPos = m_grabbedObj.transform.position - transform.position; m_movingObjectToHand = false; relPos = Quaternion.Inverse(transform.rotation) * relPos; m_grabbedObjectPosOff = relPos; Quaternion relOri = Quaternion.Inverse(transform.rotation) * m_grabbedObj.transform.rotation; m_grabbedObjectRotOff = relOri; } else { // Set up offsets for grabbed object desired position relative to hand. m_grabbedObjectPosOff = m_gripTransform.localPosition; if (m_grabbedObj.snapOffset) { Vector3 snapOffset = m_grabbedObj.snapOffset.position; if (m_controller == OVRInput.Controller.LTouch) { snapOffset.x = -snapOffset.x; } m_grabbedObjectPosOff += snapOffset; } m_grabbedObjectRotOff = m_gripTransform.localRotation; if (m_grabbedObj.snapOffset) { m_grabbedObjectRotOff = m_grabbedObj.snapOffset.rotation * m_grabbedObjectRotOff; } } } }
void Update() { DistanceGrabbable target; Collider targetColl; FindTarget(out target, out targetColl); if (target != m_target) { if (m_target != null) { //m_target.Highlight = m_otherHand.m_target == m_target; m_target.Targeted = m_otherHand.m_target == m_target; } m_target = target; m_targetCollider = targetColl; if (m_target != null) { //m_target.Highlight = true; m_target.Targeted = true; } } if (OVRInput.Get(OVRInput.Button.SecondaryThumbstickLeft) && graph != null && graph.latestSelection == graph.selectedNodes[handIndex]) { if (ReadyToSnapTurn) { // Debug.Log(graph.currentTarget+ " "+ graph.latestSelection); if (graph.currentTarget != -1 && graph.currentTarget != graph.nodes[graph.latestSelection].connectedNodes.Count) { graph.nodes[graph.nodes[graph.latestSelection].connectedNodes[graph.currentTarget]].labelObject.GetComponent <TextMesh>().color = TGraph.ReadJSON.ConnectedColor; } graph.currentTarget = (graph.currentTarget - 1) % (graph.nodes[graph.latestSelection].connectedNodes.Count + 1); if (graph.currentTarget == -2) { graph.currentTarget = graph.nodes[graph.latestSelection].connectedNodes.Count - 1; } if (OnSelectionChanged != null) { OnSelectionChanged(); } ReadyToSnapTurn = false; } if (graph.currentTarget == -1 || graph.currentTarget == graph.nodes[graph.latestSelection].connectedNodes.Count) { m_camera.transform.rotation = Quaternion.identity; } else { // Debug.Log(graph.currentTarget + " " + graph.latestSelection); graph.nodes[graph.nodes[graph.latestSelection].connectedNodes[graph.currentTarget]].labelObject.GetComponent <TextMesh>().color = TGraph.ReadJSON.TargetColor; Vector3 relativePos = graph.nodes[graph.nodes[graph.latestSelection].connectedNodes[graph.currentTarget]].nodeObject.transform.position - m_camera.transform.position; Quaternion rotation = Quaternion.LookRotation(relativePos, Vector3.up); rotation.eulerAngles = new Vector3(0, rotation.eulerAngles.y, 0); m_camera.transform.localRotation = rotation; m_camera.transform.Rotate(new Vector3(0, -Camera.main.transform.localEulerAngles.y, 0)); } } else if (OVRInput.Get(OVRInput.Button.SecondaryThumbstickRight) && graph != null && graph.latestSelection == graph.selectedNodes[handIndex]) { if (ReadyToSnapTurn) { if (graph.currentTarget != -1 && graph.currentTarget != graph.nodes[graph.latestSelection].connectedNodes.Count) { graph.nodes[graph.nodes[graph.latestSelection].connectedNodes[graph.currentTarget]].labelObject.GetComponent <TextMesh>().color = TGraph.ReadJSON.ConnectedColor; } graph.currentTarget = (graph.currentTarget + 1) % (graph.nodes[graph.latestSelection].connectedNodes.Count + 1); if (OnSelectionChanged != null) { OnSelectionChanged(); } ReadyToSnapTurn = false; } if (graph.currentTarget == -1 || graph.currentTarget == graph.nodes[graph.latestSelection].connectedNodes.Count) { m_camera.transform.rotation = Quaternion.identity; } else { graph.nodes[graph.nodes[graph.latestSelection].connectedNodes[graph.currentTarget]].labelObject.GetComponent <TextMesh>().color = TGraph.ReadJSON.TargetColor; Vector3 relativePos = graph.nodes[graph.nodes[graph.latestSelection].connectedNodes[graph.currentTarget]].nodeObject.transform.position - m_camera.transform.position; Quaternion rotation = Quaternion.LookRotation(relativePos, Vector3.up); rotation.eulerAngles = new Vector3(0, rotation.eulerAngles.y, 0); m_camera.transform.localRotation = rotation; m_camera.transform.Rotate(new Vector3(0, -Camera.main.transform.localEulerAngles.y, 0)); } } else { ReadyToSnapTurn = true; } }