199 lines
5.7 KiB
C#
199 lines
5.7 KiB
C#
// Copyright 2017 Google Inc. All rights reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
using Gvr;
|
|
using UnityEngine;
|
|
|
|
namespace Gvr.Internal {
|
|
/// Mocks controller input by using the mouse.
|
|
/// The controller is connected when holding left shift.
|
|
/// Move the mouse to control gyroscope and orientation.
|
|
/// The left mouse button is used for the clickButton.
|
|
/// The right mouse button is used for the appButton.
|
|
/// The middle mouse button is used for the homeButton.
|
|
class MouseControllerProvider : IControllerProvider {
|
|
private const string AXIS_MOUSE_X = "Mouse X";
|
|
private const string AXIS_MOUSE_Y = "Mouse Y";
|
|
|
|
private ControllerState state = new ControllerState();
|
|
|
|
private Vector2 mouseDelta = new Vector2();
|
|
|
|
/// Need to store the state of the buttons from the previous frame.
|
|
/// This is because Input.GetMouseButtonDown and Input.GetMouseButtonUp
|
|
/// don't work when called after WaitForEndOfFrame, which is when ReadState is called.
|
|
private bool wasTouching;
|
|
private GvrControllerButton lastButtonsState;
|
|
|
|
private const float ROTATE_SENSITIVITY = 4.5f;
|
|
private const float TOUCH_SENSITIVITY = .12f;
|
|
private static readonly Vector3 INVERT_Y = new Vector3(1, -1, 1);
|
|
|
|
public static bool IsMouseAvailable {
|
|
get {
|
|
return Input.mousePresent && IsActivateButtonPressed;
|
|
}
|
|
}
|
|
|
|
public static bool IsActivateButtonPressed {
|
|
get {
|
|
return Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift);
|
|
}
|
|
}
|
|
|
|
public static bool IsClickButtonPressed {
|
|
get {
|
|
return Input.GetMouseButton(0);
|
|
}
|
|
}
|
|
|
|
public static bool IsAppButtonPressed {
|
|
get {
|
|
return Input.GetMouseButton(1);
|
|
}
|
|
}
|
|
|
|
public static bool IsHomeButtonPressed {
|
|
get {
|
|
return Input.GetMouseButton(2);
|
|
}
|
|
}
|
|
|
|
public static bool IsTouching {
|
|
get {
|
|
return Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl);
|
|
}
|
|
}
|
|
|
|
public bool SupportsBatteryStatus {
|
|
get { return false; }
|
|
}
|
|
|
|
public int MaxControllerCount {
|
|
get { return 1; }
|
|
}
|
|
|
|
internal MouseControllerProvider() {}
|
|
|
|
public void Dispose() {}
|
|
|
|
public void ReadState(ControllerState outState, int controller_id) {
|
|
if (controller_id != 0) {
|
|
return;
|
|
}
|
|
lock (state) {
|
|
UpdateState();
|
|
|
|
outState.CopyFrom(state);
|
|
}
|
|
state.ClearTransientState();
|
|
}
|
|
|
|
public void OnPause() {}
|
|
public void OnResume() {}
|
|
|
|
private void UpdateState() {
|
|
GvrCursorHelper.ControllerEmulationActive = IsMouseAvailable;
|
|
|
|
if (!IsMouseAvailable) {
|
|
ClearState();
|
|
return;
|
|
}
|
|
|
|
state.connectionState = GvrConnectionState.Connected;
|
|
state.apiStatus = GvrControllerApiStatus.Ok;
|
|
state.isCharging = false;
|
|
state.batteryLevel = GvrControllerBatteryLevel.Full;
|
|
|
|
UpdateButtonStates();
|
|
|
|
mouseDelta.Set(
|
|
Input.GetAxis(AXIS_MOUSE_X),
|
|
Input.GetAxis(AXIS_MOUSE_Y)
|
|
);
|
|
|
|
if (0 != (state.buttonsState & GvrControllerButton.TouchPadTouch)) {
|
|
UpdateTouchPos();
|
|
} else {
|
|
UpdateOrientation();
|
|
}
|
|
}
|
|
|
|
private void UpdateTouchPos() {
|
|
Vector3 currentMousePosition = Input.mousePosition;
|
|
Vector2 touchDelta = mouseDelta * TOUCH_SENSITIVITY;
|
|
touchDelta.y *= -1.0f;
|
|
|
|
state.touchPos += touchDelta;
|
|
state.touchPos.x = Mathf.Clamp01(state.touchPos.x);
|
|
state.touchPos.y = Mathf.Clamp01(state.touchPos.y);
|
|
}
|
|
|
|
private void UpdateOrientation() {
|
|
Vector3 deltaDegrees = Vector3.Scale(mouseDelta, INVERT_Y) * ROTATE_SENSITIVITY;
|
|
|
|
state.gyro = deltaDegrees * (Mathf.Deg2Rad / Time.deltaTime);
|
|
|
|
Quaternion yaw = Quaternion.AngleAxis(deltaDegrees.x, Vector3.up);
|
|
Quaternion pitch = Quaternion.AngleAxis(deltaDegrees.y, Vector3.right);
|
|
state.orientation = state.orientation * yaw * pitch;
|
|
}
|
|
|
|
private void UpdateButtonStates() {
|
|
state.buttonsState = 0;
|
|
if (IsClickButtonPressed) {
|
|
state.buttonsState |= GvrControllerButton.TouchPadButton;
|
|
}
|
|
if (IsAppButtonPressed) {
|
|
state.buttonsState |= GvrControllerButton.App;
|
|
}
|
|
if (IsHomeButtonPressed) {
|
|
state.buttonsState |= GvrControllerButton.System;
|
|
}
|
|
if (IsTouching) {
|
|
state.buttonsState |= GvrControllerButton.TouchPadTouch;
|
|
}
|
|
|
|
state.SetButtonsUpDownFromPrevious(lastButtonsState);
|
|
lastButtonsState = state.buttonsState;
|
|
|
|
if (0 != (state.buttonsUp & GvrControllerButton.TouchPadTouch)) {
|
|
ClearTouchPos();
|
|
}
|
|
|
|
if (0 != (state.buttonsUp & GvrControllerButton.System)) {
|
|
Recenter();
|
|
}
|
|
}
|
|
|
|
private void Recenter() {
|
|
Quaternion yawCorrection = Quaternion.AngleAxis(-state.orientation.eulerAngles.y, Vector3.up);
|
|
state.orientation = state.orientation * yawCorrection;
|
|
state.recentered = true;
|
|
}
|
|
|
|
private void ClearTouchPos() {
|
|
state.touchPos = new Vector2(0.5f, 0.5f);
|
|
}
|
|
|
|
private void ClearState() {
|
|
state.connectionState = GvrConnectionState.Disconnected;
|
|
state.buttonsState = 0;
|
|
state.buttonsDown = 0;
|
|
state.buttonsUp = 0;
|
|
ClearTouchPos();
|
|
}
|
|
}
|
|
}
|