private static extern int GvrShimUnity_getControllerState(int device, ref GvrShimUnityControllerState state);
/// Reads the controller's current state and stores it in outState. public void ReadState(ControllerState outState, int controller_id) { int retval = 0; if (lastUpdateFrame != Time.frameCount) { lastUpdateFrame = Time.frameCount; retval = GvrShimUnity_updateState(); if (retval != GVR_SHIM_OK) { Debug.LogError("GvrShimUnity_updateState returned error."); return; } } int connStatus = 0; retval = GvrShimUnity_getControllerConnectionStatus(controller_id, ref connStatus); if (retval != GVR_SHIM_OK) { Debug.LogError("GvrShimUnity_getControllerConnectionStatus returned error."); return; } outState.connectionState = ConvertConnectionState(connStatus); // Early out if not connected. No other state is relevant. if (outState.connectionState != GvrConnectionState.Connected) { return; } GvrShimUnityControllerState aState = new GvrShimUnityControllerState(); retval = GvrShimUnity_getControllerState(controller_id, ref aState); if (retval != GVR_SHIM_OK) { Debug.LogError("GvrShimUnity_getControllerState returned error."); return; } // Convert GVR API orientation (right-handed) into Unity axis system (left-handed). pose3d.Set(aState.position, aState.orientation); pose3d.SetRightHanded(pose3d.Matrix); outState.orientation = pose3d.Orientation; outState.position = pose3d.Position; // For accelerometer, we have to flip Z because the GVR API has Z pointing backwards // and Unity has Z pointing forward. outState.accel = aState.acceleration; outState.accel.z *= -1; // Gyro in GVR represents a right-handed angular velocity about each axis (positive means // clockwise when sighting along axis). Since Unity uses a left-handed system, we flip the // signs to adjust the sign of the rotational velocity (so that positive means // counter-clockwise). In addition, since in Unity the Z axis points forward while GVR // has Z pointing backwards, we flip the Z axis sign again. So the result is that // we should use -X, -Y, +Z: outState.gyro = aState.gyro; outState.gyro.Scale(new Vector3(-1, -1, 1)); outState.touchPos = aState.touchPos; // Shim outputs centered touchpos coordinates, but the ControllerState struct is // top-left coordinates. Convert back to top-left. outState.touchPos.x = (outState.touchPos.x / 2.0f) + 0.5f; outState.touchPos.y = (-outState.touchPos.y / 2.0f) + 0.5f; outState.is6DoF = (aState.trackedDataAvailable & (int)GvrShimTrackedDataAvailableFlags.PositionAvailable) != 0; outState.buttonsState = (GvrControllerButton)aState.buttonState; // Derive button up/down state from Unity perspective, as it can miss // up/downs from platform, like on pause/resume. if (controller_id >= 0 && controller_id < lastButtonStates.Length) { outState.SetButtonsUpDownFromPrevious(lastButtonStates[controller_id]); lastButtonStates[controller_id] = outState.buttonsState; } outState.recentered = (aState.recentered != 0); outState.isCharging = (aState.batteryCharging != 0); outState.batteryLevel = (GvrControllerBatteryLevel)aState.batteryLevel; }