177 lines
6.6 KiB
C#
177 lines
6.6 KiB
C#
|
// Copyright 2016 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 permissioßns and
|
||
|
// limitations under the License.
|
||
|
|
||
|
// The controller is not available for versions of Unity without the
|
||
|
// // GVR native integration.
|
||
|
#if UNITY_HAS_GOOGLEVR && (UNITY_ANDROID || UNITY_EDITOR)
|
||
|
|
||
|
using UnityEngine;
|
||
|
|
||
|
/// @cond
|
||
|
namespace Gvr.Internal {
|
||
|
/// Controller provider that connects to the controller emulator to obtain controller events.
|
||
|
class EmulatorControllerProvider : IControllerProvider {
|
||
|
private ControllerState state = new ControllerState();
|
||
|
|
||
|
/// Yaw correction due to recentering.
|
||
|
private Quaternion yawCorrection = Quaternion.identity;
|
||
|
|
||
|
/// True if we performed the initial recenter.
|
||
|
private bool initialRecenterDone = false;
|
||
|
|
||
|
/// The last (uncorrected) orientation received from the emulator.
|
||
|
private Quaternion lastRawOrientation = Quaternion.identity;
|
||
|
|
||
|
/// Creates a new EmulatorControllerProvider with the specified settings.
|
||
|
internal EmulatorControllerProvider(GvrController.EmulatorConnectionMode connectionMode) {
|
||
|
if (connectionMode == GvrController.EmulatorConnectionMode.USB) {
|
||
|
EmulatorConfig.Instance.PHONE_EVENT_MODE = EmulatorConfig.Mode.USB;
|
||
|
} else if (connectionMode == GvrController.EmulatorConnectionMode.WIFI) {
|
||
|
EmulatorConfig.Instance.PHONE_EVENT_MODE = EmulatorConfig.Mode.WIFI;
|
||
|
} else {
|
||
|
EmulatorConfig.Instance.PHONE_EVENT_MODE = EmulatorConfig.Mode.OFF;
|
||
|
}
|
||
|
|
||
|
EmulatorManager.Instance.touchEventListeners += HandleTouchEvent;
|
||
|
EmulatorManager.Instance.orientationEventListeners += HandleOrientationEvent;
|
||
|
EmulatorManager.Instance.buttonEventListeners += HandleButtonEvent;
|
||
|
EmulatorManager.Instance.gyroEventListeners += HandleGyroEvent;
|
||
|
EmulatorManager.Instance.accelEventListeners += HandleAccelEvent;
|
||
|
}
|
||
|
|
||
|
public void ReadState(ControllerState outState) {
|
||
|
lock (state) {
|
||
|
state.connectionState = EmulatorManager.Instance.Connected ? GvrConnectionState.Connected :
|
||
|
GvrConnectionState.Connecting;
|
||
|
state.apiStatus = EmulatorManager.Instance.Connected ? GvrControllerApiStatus.Ok :
|
||
|
GvrControllerApiStatus.Unavailable;
|
||
|
|
||
|
// During emulation, just assume the controller is fully charged
|
||
|
state.isCharging = false;
|
||
|
state.batteryLevel = GvrControllerBatteryLevel.Full;
|
||
|
|
||
|
outState.CopyFrom(state);
|
||
|
}
|
||
|
state.ClearTransientState();
|
||
|
}
|
||
|
|
||
|
public void OnPause() {}
|
||
|
public void OnResume() {}
|
||
|
|
||
|
private void HandleTouchEvent(EmulatorTouchEvent touchEvent) {
|
||
|
if (touchEvent.pointers.Count < 1) return;
|
||
|
EmulatorTouchEvent.Pointer pointer = touchEvent.pointers[0];
|
||
|
|
||
|
lock (state) {
|
||
|
state.touchPos = new Vector2(pointer.normalizedX, pointer.normalizedY);
|
||
|
switch (touchEvent.getActionMasked()) {
|
||
|
case EmulatorTouchEvent.Action.kActionDown:
|
||
|
state.touchDown = true;
|
||
|
state.isTouching = true;
|
||
|
break;
|
||
|
case EmulatorTouchEvent.Action.kActionMove:
|
||
|
state.isTouching = true;
|
||
|
break;
|
||
|
case EmulatorTouchEvent.Action.kActionUp:
|
||
|
state.isTouching = false;
|
||
|
state.touchUp = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void HandleOrientationEvent(EmulatorOrientationEvent orientationEvent) {
|
||
|
lastRawOrientation = ConvertEmulatorQuaternion(orientationEvent.orientation);
|
||
|
if (!initialRecenterDone) {
|
||
|
Recenter();
|
||
|
initialRecenterDone = true;
|
||
|
}
|
||
|
lock (state) {
|
||
|
state.orientation = yawCorrection * lastRawOrientation;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void HandleButtonEvent(EmulatorButtonEvent buttonEvent) {
|
||
|
if (buttonEvent.code == EmulatorButtonEvent.ButtonCode.kHome) {
|
||
|
if (buttonEvent.down) {
|
||
|
lock (state) {
|
||
|
// Started the recentering gesture.
|
||
|
state.recentering = true;
|
||
|
}
|
||
|
} else {
|
||
|
// Finished the recentering gesture. Recenter controller.
|
||
|
Recenter();
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (buttonEvent.code != EmulatorButtonEvent.ButtonCode.kApp &&
|
||
|
buttonEvent.code != EmulatorButtonEvent.ButtonCode.kClick) return;
|
||
|
|
||
|
lock (state) {
|
||
|
if (buttonEvent.code == EmulatorButtonEvent.ButtonCode.kApp) {
|
||
|
state.appButtonState = buttonEvent.down;
|
||
|
state.appButtonDown = buttonEvent.down;
|
||
|
state.appButtonUp = !buttonEvent.down;
|
||
|
} else {
|
||
|
state.clickButtonState = buttonEvent.down;
|
||
|
state.clickButtonDown = buttonEvent.down;
|
||
|
state.clickButtonUp = !buttonEvent.down;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void HandleGyroEvent(EmulatorGyroEvent gyroEvent) {
|
||
|
lock (state) {
|
||
|
state.gyro = ConvertEmulatorGyro(gyroEvent.value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void HandleAccelEvent(EmulatorAccelEvent accelEvent) {
|
||
|
lock (state) {
|
||
|
state.accel = ConvertEmulatorAccel(accelEvent.value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static Quaternion ConvertEmulatorQuaternion(Quaternion emulatorQuat) {
|
||
|
// Convert from the emulator's coordinate space to Unity's standard coordinate space.
|
||
|
return new Quaternion(emulatorQuat.x, -emulatorQuat.z, emulatorQuat.y, emulatorQuat.w);
|
||
|
}
|
||
|
|
||
|
private static Vector3 ConvertEmulatorGyro(Vector3 emulatorGyro) {
|
||
|
// Convert from the emulator's coordinate space to Unity's standard coordinate space.
|
||
|
return new Vector3(-emulatorGyro.x, -emulatorGyro.z, -emulatorGyro.y);
|
||
|
}
|
||
|
|
||
|
private static Vector3 ConvertEmulatorAccel(Vector3 emulatorAccel) {
|
||
|
// Convert from the emulator's coordinate space to Unity's standard coordinate space.
|
||
|
return new Vector3(emulatorAccel.x, emulatorAccel.z, emulatorAccel.y);
|
||
|
}
|
||
|
|
||
|
private void Recenter() {
|
||
|
lock (state) {
|
||
|
// We want the current orientation to be "forward" so, we set the yaw correction
|
||
|
// to undo the current rotation's yaw.
|
||
|
yawCorrection = Quaternion.AngleAxis(-lastRawOrientation.eulerAngles.y, Vector3.up);
|
||
|
state.orientation = Quaternion.identity;
|
||
|
state.recentering = false;
|
||
|
state.recentered = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
/// @endcond
|
||
|
|
||
|
#endif // UNITY_HAS_GOOGLEVR && (UNITY_ANDROID || UNITY_EDITOR)
|