private void UpdateInteract(Hand hand, float3 handPos, ref HandState state)
        {
            if (UseToolAction.GetStateDown(hand.handType))
            {
                state.IsActionHeld = true;

                if (state.HoveredHalfEdge != Entity.Null)
                {
                    CreateNewVertexAtHover(ref state);
                }

                if (MultiSelectAction.GetState(hand.handType))
                {
                    StartSelecting(ref state);
                }
                else
                {
                    StartDragging(handPos, ref state);
                }
            }
            else if (state.IsActionHeld && UseToolAction.GetState(hand.handType))
            {
                if (state.IsDragging)
                {
                    UpdateDragging(hand, handPos, ref state);
                    return;
                }

                UpdateSelecting(ref state);
            }

            if (state.IsActionHeld && UseToolAction.GetStateUp(hand.handType))
            {
                state.IsActionHeld = false;

                if (state.IsDragging)
                {
                    StopDragging(ref state);
                }
            }
        }
Exemple #2
0
        private void Update()
        {
            if (TargetLevel == null)
            {
                return;
            }

            var player = Player.instance;

            var leftValid  = player.leftHand.TryGetPointerPosition(out var leftWorldPos) && LeftHandActive;
            var rightValid = player.rightHand.TryGetPointerPosition(out var rightWorldPos) && RightHandActive;

            var leftPressed  = leftValid && UseToolAction.GetStateDown(SteamVR_Input_Sources.LeftHand);
            var rightPressed = rightValid && UseToolAction.GetStateDown(SteamVR_Input_Sources.RightHand);

            var leftReleased  = leftValid && UseToolAction.GetStateUp(SteamVR_Input_Sources.LeftHand);
            var rightReleased = rightValid && UseToolAction.GetStateUp(SteamVR_Input_Sources.RightHand);

            _leftHeld  &= leftValid && UseToolAction.GetState(SteamVR_Input_Sources.LeftHand);
            _rightHeld &= rightValid && UseToolAction.GetState(SteamVR_Input_Sources.RightHand);

            var leftLocalPos  = TargetLevel.transform.InverseTransformPoint(leftWorldPos);
            var rightLocalPos = TargetLevel.transform.InverseTransformPoint(rightWorldPos);

            var crosshairsInvalid = false;

            // New anchor points if anything pressed or released

            if (leftPressed || rightPressed || leftReleased || rightReleased)
            {
                _leftLocalAnchor  = leftLocalPos;
                _rightLocalAnchor = rightLocalPos;

                _leftHeld  |= leftPressed;
                _rightHeld |= rightPressed;

                crosshairsInvalid = true;
            }

            // Check for new scale / rotation target

            if (_leftHeld && _rightHeld)
            {
                _worldPivotPos = (leftWorldPos + rightWorldPos) * 0.5f;

                var betweenAnchorDiff = _rightLocalAnchor - _leftLocalAnchor;
                var betweenLocalDiff  = rightLocalPos - leftLocalPos;

                var isScaling = Mathf.Abs(betweenAnchorDiff.normalized.y) >= Mathf.Sqrt(0.5f);

                if (isScaling)
                {
                    var sizeRatio   = betweenLocalDiff.magnitude / betweenAnchorDiff.magnitude;
                    var newScale    = TargetLevel.transform.localScale.x * sizeRatio;
                    var logNewScale = math.log10(newScale);

                    var bestScale        = 1f;
                    var bestLogScaleDiff = float.PositiveInfinity;

                    foreach (var scale in _scales)
                    {
                        var logScale     = math.log10(scale);
                        var logScaleDiff = math.abs(logScale - logNewScale);

                        if (logScaleDiff < bestLogScaleDiff)
                        {
                            bestLogScaleDiff = logScaleDiff;
                            bestScale        = scale;
                        }
                    }

                    if (bestScale != _targetScale)
                    {
                        _prevScale   = _targetScale;
                        _targetScale = bestScale;
                        _scaleTimer  = 1f;

                        player.leftHand.TriggerHapticPulse(500);
                        player.rightHand.TriggerHapticPulse(500);

                        UpdateScaleText();
                    }
                }
                else
                {
                    var betweenAnchorAngle = Mathf.Atan2(betweenAnchorDiff.z, betweenAnchorDiff.x) * Mathf.Rad2Deg;
                    var betweenLocalAngle  = Mathf.Atan2(betweenLocalDiff.z, betweenLocalDiff.x) * Mathf.Rad2Deg;

                    var angleDiff   = Mathf.DeltaAngle(betweenLocalAngle, betweenAnchorAngle);
                    var targetAngle = TargetLevel.transform.localEulerAngles.y + angleDiff;

                    targetAngle  = math.round(targetAngle / SnapAngle) * SnapAngle;
                    targetAngle -= math.floor(targetAngle / 360f) * 360f;

                    if (Mathf.DeltaAngle(_targetAngle, targetAngle) != 0f)
                    {
                        _prevAngle   = _targetAngle;
                        _targetAngle = targetAngle;
                        _angleTimer  = 1f;

                        player.leftHand.TriggerHapticPulse(500);
                        player.rightHand.TriggerHapticPulse(500);

                        UpdateAngleText();
                    }
                }

                if (isScaling != _isScaling)
                {
                    _isScaling        = isScaling;
                    crosshairsInvalid = true;
                }
            }

            // Handle rotation / scale animation

            var rotatedOrScaled = false;

            if (_scaleTimer > 0f)
            {
                _scaleTimer -= Time.deltaTime / EasingTime;
                var t = Mathf.Clamp01(1f - _scaleTimer);

                var scale = _prevScale + Easing.InOutCubic(t) * (_targetScale - _prevScale);
                TargetLevel.transform.localScale = Vector3.one * scale;

                rotatedOrScaled = true;
            }

            if (_angleTimer > 0f)
            {
                _angleTimer -= Time.deltaTime / EasingTime;
                var t = Mathf.Clamp01(1f - _angleTimer);

                var angle    = _prevAngle + Easing.InOutCubic(t) * Mathf.DeltaAngle(_prevAngle, _targetAngle);
                var curAngle = TargetLevel.transform.localEulerAngles.y;

                TargetLevel.transform.RotateAround(_worldPivotPos, Vector3.up, angle - curAngle);

                rotatedOrScaled = true;
            }

            // Local positions will have changed if scale or rotation changed

            if (rotatedOrScaled)
            {
                leftLocalPos  = TargetLevel.transform.InverseTransformPoint(leftWorldPos);
                rightLocalPos = TargetLevel.transform.InverseTransformPoint(rightWorldPos);
            }

            // Grab translation

            if (_leftHeld || _rightHeld)
            {
                Vector3 anchor, pos;

                if (_leftHeld && _rightHeld)
                {
                    anchor = (_leftLocalAnchor + _rightLocalAnchor) * 0.5f;
                    pos    = (leftLocalPos + rightLocalPos) * 0.5f;
                }
                else
                {
                    anchor = _leftHeld ? _leftLocalAnchor : _rightLocalAnchor;
                    pos    = _leftHeld ? leftLocalPos : rightLocalPos;
                }

                var localDiff = pos - anchor;
                var worldDiff = TargetLevel.transform.TransformVector(localDiff);

                TargetLevel.transform.Translate(worldDiff, Space.World);
            }

            // Update widgets

            if (crosshairsInvalid)
            {
                UpdateCrosshairTextures();
            }

            if (Text.gameObject.activeSelf)
            {
                Text.transform.position = _worldPivotPos;
                Text.transform.rotation = Quaternion.LookRotation(_worldPivotPos - Player.instance.hmdTransform.position);
            }
        }