コード例 #1
0
      private bool IsValidContact(InteractableTool collidingTool, Vector3 buttonDirection)
      {
          if (_contactTests == null || collidingTool.IsFarFieldTool)
          {
              return(true);
          }

          foreach (var contactTest in _contactTests)
          {
              switch (contactTest)
              {
              case ContactTest.BackwardsPress:
                  if (!PassEntryTest(collidingTool, buttonDirection))
                  {
                      return(false);
                  }

                  break;

              default:
                  if (!PassPerpTest(collidingTool, buttonDirection))
                  {
                      return(false);
                  }

                  break;
              }
          }

          return(true);
      }
コード例 #2
0
      /// <summary>
      /// Is tool entering button correctly? Check velocity and make sure that
      /// tool is not below action zone.
      /// </summary>
      private bool PassEntryTest(InteractableTool collidingTool, Vector3 buttonDirection)
      {
          var jointVelocityVector = collidingTool.Velocity.normalized;
          var dotProduct          = Vector3.Dot(jointVelocityVector, buttonDirection);

          if (dotProduct < ENTRY_DOT_THRESHOLD)
          {
              return(false);
          }

          return(true);
      }
コード例 #3
0
      /// <summary>
      /// Is our tool pointing in opposite direction compared to button?
      /// </summary>
      private bool PassPerpTest(InteractableTool collidingTool, Vector3 buttonDirection)
      {
          // the "right" vector points along tool by default
          // if it's right hand, then flip that direction
          var toolDirection = collidingTool.ToolTransform.right;

          if (collidingTool.IsRightHandedTool)
          {
              toolDirection = -toolDirection;
          }

          var dotProduct = Vector3.Dot(toolDirection, buttonDirection);

          if (dotProduct < PERP_DOT_THRESHOLD)
          {
              return(false);
          }

          return(true);
      }
コード例 #4
0
      public override void UpdateCollisionDepth(InteractableTool interactableTool,
                                                InteractableCollisionDepth oldCollisionDepth,
                                                InteractableCollisionDepth collisionDepth, InteractableTool collidingTool)
      {
          bool isFarFieldTool = interactableTool.IsFarFieldTool;

          // if this is a near field tool and another tool already controls it, bail.
          if (!isFarFieldTool && _toolToState.Keys.Count > 0 && !_toolToState.ContainsKey(interactableTool))
          {
              return;
          }

          var oldState = _currentButtonState;

          // ignore contact test if you are using the far field tool
          var  currButtonDirection = transform.TransformDirection(_localButtonDirection);
          bool validContact        = IsValidContact(collidingTool, currButtonDirection) || collidingTool.IsFarFieldTool;
          // in case finger enters contact zone first, we are in proximity as well
          bool toolInActionZone = collisionDepth == InteractableCollisionDepth.Action;

          // plane describing positive side of button
          var buttonZonePlane = new Plane(-currButtonDirection, _buttonPlaneCenter.position);
          // skip plane test if the boolean flag tells us not to test it
          bool onPositiveSideOfButton = !_makeSureToolIsOnPositiveSide ||
                                        buttonZonePlane.GetSide(collidingTool.InteractionPosition);

          bool switchingStates = oldCollisionDepth != collisionDepth;

          if (!switchingStates)
          {
              if (collisionDepth == InteractableCollisionDepth.Action)
              {
                  if (OnStayInActionZone != null)
                  {
                      OnStayInActionZone.Invoke();
                  }
              }
          }

          var newState = oldState;

          if (collidingTool.IsFarFieldTool)
          {
              newState = toolInActionZone ? InteractableState.ActionState : InteractableState.Default;
          }
          else
          {
              switch (oldState)
              {
              case InteractableState.ActionState:
                  if (!toolInActionZone)
                  {
                      newState = InteractableState.Default;
                      if (OnExitActionZone != null)
                      {
                          OnExitActionZone.Invoke();
                      }
                  }

                  break;

              case InteractableState.Default:
                  // test contact, action first then proximity (more important states
                  // take precedence)
                  if (validContact &&
                      collisionDepth == InteractableCollisionDepth.Action)
                  {
                      newState = InteractableState.ActionState;
                      if (OnEnterActionZone != null)
                      {
                          OnEnterActionZone.Invoke();
                      }
                  }

                  break;
              }
          }

          if (newState != InteractableState.Default)
          {
              _toolToState[interactableTool] = newState;
          }
          else
          {
              _toolToState.Remove(interactableTool);
          }

          // far field tools depend on max state set
          if (isFarFieldTool)
          {
              foreach (var toolState in _toolToState.Values)
              {
                  if (newState < toolState)
                  {
                      newState = toolState;
                  }
              }
          }

          if (oldState != newState)
          {
              _currentButtonState = newState;
              var interactionType = !switchingStates ? InteractionType.Stay :
                                    collisionDepth == InteractableCollisionDepth.None ? InteractionType.Exit :
                                    InteractionType.Enter;
              if (InteractableStateChanged != null)
              {
                  InteractableStateChanged.Invoke(new InteractableStateArgs(this, interactableTool,
                                                                            _currentButtonState, oldState, new ColliderZoneArgs(ContactCollider, Time.frameCount,
                                                                                                                                collidingTool, interactionType)));
              }
          }
      }