130 changes: 84 additions & 46 deletions Cardboard/Scripts/CardboardProfile.cs
Expand Up @@ -67,12 +67,27 @@ public struct MaxFOV {
/// distortion. Assumes a radially symmetric pincushion/barrel distortion model.
[System.Serializable]
public struct Distortion {
public float k1;
public float k2;
private float[] coef;
public float[] Coef {
get {
return coef;
}
set {
if (value != null) {
coef = (float[])value.Clone();
} else {
coef = null;
}
}
}

public float distort(float r) {
float r2 = r * r;
return ((k2 * r2 + k1) * r2 + 1) * r;
float ret = 0;
for (int j=coef.Length-1; j>=0; j--) {
ret = r2 * (ret + coef[j]);
}
return (ret + 1) * r;
}

public float distortInv(float radius) {
Expand Down Expand Up @@ -212,10 +227,9 @@ public enum DeviceTypes {
lower = 40.0f
},
distortion = {
k1 = 0.441f,
k2 = 0.156f
Coef = new [] { 0.441f, 0.156f },
},
inverse = ApproximateInverse(0.441f, 0.156f)
inverse = ApproximateInverse(new [] { 0.441f, 0.156f })
};

/// Parameters for a Cardboard v2.
Expand All @@ -233,10 +247,9 @@ public enum DeviceTypes {
lower = 60.0f
},
distortion = {
k1 = 0.34f,
k2 = 0.55f
Coef = new [] { 0.34f, 0.55f },
},
inverse = ApproximateInverse(0.34f, 0.55f)
inverse = ApproximateInverse(new [] { 0.34f, 0.55f })
};

/// Parameters for a Go4D C1-Glass.
Expand All @@ -254,10 +267,9 @@ public enum DeviceTypes {
lower = 50.0f
},
distortion = {
k1 = 0.3f,
k2 = 0
Coef = new [] { 0.3f, 0 },
},
inverse = ApproximateInverse(0.3f, 0)
inverse = ApproximateInverse(new [] { 0.3f, 0 })
};

/// Nexus 5 in a Cardboard v1.
Expand Down Expand Up @@ -386,6 +398,52 @@ public enum DeviceTypes {
return Mathf.Sqrt(x * x + y * y);
}

// Solves a small linear equation via destructive gaussian
// elimination and back substitution. This isn't generic numeric
// code, it's just a quick hack to work with the generally
// well-behaved symmetric matrices for least-squares fitting.
// Not intended for reuse.
//
// @param a Input positive definite symmetrical matrix. Destroyed
// during calculation.
// @param y Input right-hand-side values. Destroyed during calculation.
// @return Resulting x value vector.
//
private static double[] solveLinear(double[,] a, double[] y) {
int n = a.GetLength(0);

// Gaussian elimination (no row exchange) to triangular matrix.
// The input matrix is a A^T A product which should be a positive
// definite symmetrical matrix, and if I remember my linear
// algebra right this implies that the pivots will be nonzero and
// calculations sufficiently accurate without needing row
// exchange.
for (int j = 0; j < n - 1; ++j) {
for (int k = j + 1; k < n; ++k) {
double p = a[k, j] / a[j, j];
for (int i = j + 1; i < n; ++i) {
a[k, i] -= p * a[j, i];
}
y[k] -= p * y[j];
}
}
// From this point on, only the matrix elements a[j][i] with i>=j are
// valid. The elimination doesn't fill in eliminated 0 values.

double[] x = new double[n];

// Back substitution.
for (int j = n - 1; j >= 0; --j) {
double v = y[j];
for (int i = j + 1; i < n; ++i) {
v -= a[j, i] * x[i];
}
x[j] = v / a[j, j];
}

return x;
}

// Solves a least-squares matrix equation. Given the equation A * x = y, calculate the
// least-square fit x = inverse(A * transpose(A)) * transpose(A) * y. The way this works
// is that, while A is typically not a square matrix (and hence not invertible), A * transpose(A)
Expand All @@ -403,10 +461,6 @@ public enum DeviceTypes {
Debug.LogError("Matrix / vector dimension mismatch");
return null;
}
if (numCoefficients != 2) {
Debug.LogError("Only 2 coefficients supported.");
return null;
}

// Calculate transpose(A) * A
double[,] matATA = new double[numCoefficients, numCoefficients];
Expand All @@ -420,16 +474,6 @@ public enum DeviceTypes {
}
}

// Calculate the inverse of transpose(A) * A. Inverting isn't recommended for numerical
// stability, but should be ok for small and well-behaved data sets. Using manual matrix
// inversion here (hence the restriction of numCoefficients to 2 in this function).
double[,] matInvATA = new double[numCoefficients, numCoefficients];
double det = matATA[0, 0] * matATA[1, 1] - matATA[0, 1] * matATA[1, 0];
matInvATA[0, 0] = matATA[1, 1] / det;
matInvATA[1, 1] = matATA[0, 0] / det;
matInvATA[0, 1] = -matATA[1, 0] / det;
matInvATA[1, 0] = -matATA[0, 1] / det;

// Calculate transpose(A) * y
double[] vecATY = new double[numCoefficients];
for (int j = 0; j < numCoefficients; ++j) {
Expand All @@ -440,30 +484,22 @@ public enum DeviceTypes {
vecATY[j] = sum;
}

// Now matrix multiply the previous values to get the result.
double[] vecX = new double[numCoefficients];
for (int j = 0; j < numCoefficients; ++j) {
double sum = 0.0;
for (int i = 0; i < numCoefficients; ++i) {
sum += matInvATA[i, j] * vecATY[i];
}
vecX[j] = sum;
}
return vecX;
// Now solve (A * transpose(A)) * x = transpose(A) * y.
return solveLinear(matATA, vecATY);
}

/// Calculates an approximate inverse to the given radial distortion parameters.
public static Distortion ApproximateInverse(float k1, float k2, float maxRadius = 1,
int numSamples = 10) {
return ApproximateInverse(new Distortion { k1=k1, k2=k2 }, maxRadius, numSamples);
public static Distortion ApproximateInverse(float[] coef, float maxRadius = 1,
int numSamples = 100) {
return ApproximateInverse(new Distortion { Coef=coef }, maxRadius, numSamples);
}

/// Calculates an approximate inverse to the given radial distortion parameters.
public static Distortion ApproximateInverse(Distortion distort, float maxRadius = 1,
int numSamples = 10) {
const int numCoefficients = 2;
int numSamples = 100) {
const int numCoefficients = 6;

// R + k1*R^3 + k2*R^5 = r, with R = rp = distort(r)
// R + K1*R^3 + K2*R^5 = r, with R = rp = distort(r)
// Repeating for numSamples:
// [ R0^3, R0^5 ] * [ K1 ] = [ r0 - R0 ]
// [ R1^3, R1^5 ] [ K2 ] [ r1 - R1 ]
Expand All @@ -486,10 +522,12 @@ public enum DeviceTypes {
vecY[i] = r - rp;
}
double[] vecK = solveLeastSquares(matA, vecY);
return new Distortion {
k1 = (float)vecK[0],
k2 = (float)vecK[1]
};
// Convert to float for use in a fresh Distortion object.
float[] coefficients = new float[vecK.Length];
for (int i = 0; i < vecK.Length; ++i) {
coefficients[i] = (float) vecK[i];
}
return new Distortion { Coef = coefficients };
}
}
/// @endcond
50 changes: 23 additions & 27 deletions Cardboard/Scripts/GazeInputModule.cs
Expand Up @@ -50,8 +50,7 @@ public class GazeInputModule : BaseInputModule {
public bool vrModeOnly = false;

/// Time in seconds between the pointer down and up events sent by a Cardboard trigger.
/// Allows time for the UI elements to make their state transitions. If you turn off
/// _TapIsTrigger_ in Cardboard, then this setting has no effect.
/// Allows time for the UI elements to make their state transitions.
[HideInInspector]
public float clickTime = 0.1f; // Based on default time for a button to animate to Pressed.

Expand All @@ -63,8 +62,8 @@ public class GazeInputModule : BaseInputModule {
private PointerEventData pointerData;
private Vector2 lastHeadPose;

// GazePointer callbacks
public static ICardboardPointer cardboardPointer;
/// The ICardboardGazePointer which will be responding to gaze events.
public static ICardboardGazePointer cardboardPointer;
// Active state
private bool isActive = false;

Expand Down Expand Up @@ -112,22 +111,15 @@ public class GazeInputModule : BaseInputModule {
UpdateCurrentObject();
UpdateReticle(gazeObjectPrevious);

// Get the camera
Camera camera = pointerData.enterEventCamera;

// Handle input
if (!Cardboard.SDK.TapIsTrigger && !Input.GetMouseButtonDown(0) && Input.GetMouseButton(0)) {
// Drag is only supported if TapIsTrigger is false.
if (!Input.GetMouseButtonDown(0) && Input.GetMouseButton(0)) {
HandleDrag();
} else if (Time.unscaledTime - pointerData.clickTime < clickTime) {
// Delay new events until clickTime has passed.
} else if (!pointerData.eligibleForClick &&
(Cardboard.SDK.Triggered || !Cardboard.SDK.TapIsTrigger && Input.GetMouseButtonDown(0))) {
(Cardboard.SDK.Triggered || Input.GetMouseButtonDown(0))) {
// New trigger action.
HandleTrigger();
if (cardboardPointer != null) {
cardboardPointer.OnGazeTriggerStart(camera);
}
} else if (!Cardboard.SDK.Triggered && !Input.GetMouseButton(0)) {
// Check if there is a pending click to handle.
HandlePendingClick();
Expand Down Expand Up @@ -174,20 +166,22 @@ public class GazeInputModule : BaseInputModule {
}

Camera camera = pointerData.enterEventCamera; // Get the camera
GameObject currentGazeObject = GetCurrentGameObject(); // Get the gaze target
GameObject gazeObject = GetCurrentGameObject(); // Get the gaze target
Vector3 intersectionPosition = GetIntersectionPosition();
bool isInteractive = pointerData.pointerPress != null ||
ExecuteEvents.GetEventHandler<IPointerClickHandler>(gazeObject) != null;

if (currentGazeObject == previousGazedObject) {
if (currentGazeObject != null) {
cardboardPointer.OnGazeStay(camera, currentGazeObject, intersectionPosition);
if (gazeObject == previousGazedObject) {
if (gazeObject != null) {
cardboardPointer.OnGazeStay(camera, gazeObject, intersectionPosition, isInteractive);
}
} else {
if (previousGazedObject != null) {
cardboardPointer.OnGazeExit(camera, previousGazedObject);
}

if (currentGazeObject != null) {
cardboardPointer.OnGazeStart(camera, currentGazeObject, intersectionPosition);
if (gazeObject != null) {
cardboardPointer.OnGazeStart(camera, gazeObject, intersectionPosition, isInteractive);
}
}
}
Expand Down Expand Up @@ -217,7 +211,7 @@ public class GazeInputModule : BaseInputModule {
}

private void HandlePendingClick() {
if (!pointerData.eligibleForClick) {
if (!pointerData.eligibleForClick && !pointerData.dragging) {
return;
}

Expand All @@ -230,13 +224,10 @@ public class GazeInputModule : BaseInputModule {

// Send pointer up and click events.
ExecuteEvents.Execute(pointerData.pointerPress, pointerData, ExecuteEvents.pointerUpHandler);
ExecuteEvents.Execute(pointerData.pointerPress, pointerData, ExecuteEvents.pointerClickHandler);

if (pointerData.pointerDrag != null) {
if (pointerData.eligibleForClick) {
ExecuteEvents.Execute(pointerData.pointerPress, pointerData, ExecuteEvents.pointerClickHandler);
} else if (pointerData.dragging) {
ExecuteEvents.ExecuteHierarchy(go, pointerData, ExecuteEvents.dropHandler);
}

if (pointerData.pointerDrag != null && pointerData.dragging) {
ExecuteEvents.Execute(pointerData.pointerDrag, pointerData, ExecuteEvents.endDragHandler);
}

Expand All @@ -245,6 +236,7 @@ public class GazeInputModule : BaseInputModule {
pointerData.rawPointerPress = null;
pointerData.eligibleForClick = false;
pointerData.clickCount = 0;
pointerData.clickTime = 0;
pointerData.pointerDrag = null;
pointerData.dragging = false;
}
Expand All @@ -261,7 +253,7 @@ public class GazeInputModule : BaseInputModule {

// Save the drag handler as well
pointerData.pointerDrag = ExecuteEvents.GetEventHandler<IDragHandler>(go);
if (pointerData.pointerDrag != null && !Cardboard.SDK.TapIsTrigger) {
if (pointerData.pointerDrag != null) {
ExecuteEvents.Execute(pointerData.pointerDrag, pointerData, ExecuteEvents.initializePotentialDrag);
}

Expand All @@ -273,6 +265,10 @@ public class GazeInputModule : BaseInputModule {
pointerData.useDragThreshold = true;
pointerData.clickCount = 1;
pointerData.clickTime = Time.unscaledTime;

if (cardboardPointer != null) {
cardboardPointer.OnGazeTriggerStart(pointerData.enterEventCamera);
}
}

private Vector2 NormalizedCartesianToSpherical(Vector3 cartCoords) {
Expand Down
20 changes: 0 additions & 20 deletions Cardboard/Scripts/StereoController.cs
Expand Up @@ -256,12 +256,6 @@ public class StereoController : MonoBehaviour {
/// Helper routine for creation of a stereo rig. Used by the
/// custom editor for this class, or to build the rig at runtime.
public void AddStereoRig() {
#if UNITY_EDITOR
// Member variable 'cam' not always initialized when this method called in Editor.
// So, we'll just make a local of the same name.
var cam = GetComponent<Camera>();
#endif

// Simplistic test if rig already exists.
// Note: Do not use Eyes property, because it caches the result before we have created the rig.
var eyes = GetComponentsInChildren<CardboardEye>(true).Where(eye => eye.Controller == this);
Expand All @@ -276,11 +270,6 @@ public class StereoController : MonoBehaviour {
// you may unexpectedly find your camera pinned to the origin.
head.trackPosition = false;
}
#if !UNITY_5
if (cam.tag == "MainCamera" && GetComponent<SkyboxMesh>() == null) {
gameObject.AddComponent<SkyboxMesh>();
}
#endif
}

// Helper routine for creation of a stereo eye.
Expand All @@ -289,11 +278,6 @@ public class StereoController : MonoBehaviour {
GameObject go = new GameObject(nm);
go.transform.SetParent(transform, false);
go.AddComponent<Camera>().enabled = false;
#if !UNITY_5
if (GetComponent("FlareLayer") != null) {
go.AddComponent("FlareLayer");
}
#endif
var cardboardEye = go.AddComponent<CardboardEye>();
cardboardEye.eye = eye;
cardboardEye.CopyCameraAndMakeSideBySide(this);
Expand Down Expand Up @@ -363,10 +347,6 @@ public class StereoController : MonoBehaviour {
renderedStereo = true;
} else {
Cardboard.SDK.UpdateState();
// Make sure any vertex-distorting shaders don't break completely.
Shader.SetGlobalMatrix("_RealProjection", cam.projectionMatrix);
Shader.SetGlobalMatrix("_FixProjection", cam.cameraToWorldMatrix);
Shader.SetGlobalFloat("_NearClip", cam.nearClipPlane);
}
}

Expand Down
14 changes: 7 additions & 7 deletions Cardboard/Scripts/StereoRenderEffect.cs
Expand Up @@ -20,16 +20,16 @@
public class StereoRenderEffect : MonoBehaviour {
private Material material;

#if UNITY_5
private new Camera camera;
private Camera cam;

private static readonly Rect fullRect = new Rect(0, 0, 1, 1);

void Awake() {
camera = GetComponent<Camera>();
cam = GetComponent<Camera>();
}
#endif

void Start() {
material = new Material(Shader.Find("Cardboard/SkyboxMesh"));
material = new Material(Shader.Find("Cardboard/UnlitTexture"));
}

void OnRenderImage(RenderTexture source, RenderTexture dest) {
Expand All @@ -39,11 +39,11 @@ public class StereoRenderEffect : MonoBehaviour {
GL.LoadPixelMatrix(0, width, height, 0);
// Camera rects are in screen coordinates (bottom left is origin), but DrawTexture takes a
// rect in GUI coordinates (top left is origin).
Rect blitRect = camera.pixelRect;
Rect blitRect = cam.pixelRect;
blitRect.y = height - blitRect.height - blitRect.y;
RenderTexture oldActive = RenderTexture.active;
RenderTexture.active = dest;
Graphics.DrawTexture(blitRect, source, material);
Graphics.DrawTexture(blitRect, source, fullRect, 0, 0, 0, 0, Color.white, material);
RenderTexture.active = oldActive;
GL.PopMatrix();
}
Expand Down
293 changes: 293 additions & 0 deletions Cardboard/Scripts/UI/CardboardGaze.cs
@@ -0,0 +1,293 @@
// Copyright 2015 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 UnityEngine;
using System.Collections;
using System.Linq;

[RequireComponent(typeof(Camera))]
public class CardboardGaze : MonoBehaviour {
/// The active Gaze Pointer for this camera. Must have ICardboardGazePointer.
/// The ICardboardGazePointer responds to events from this class.
public GameObject PointerObject {
get {
return pointerObject;
}
set {
if (value != null) {
// Retrieve the ICardboardGazePointer component.
var ptr = value.GetComponents<MonoBehaviour>()
.Select(c => c as ICardboardGazePointer)
.Where(c => c != null)
.FirstOrDefault();

if (ptr != null) {
if (pointer != null) {
if (cardboardTrigger) {
pointer.OnGazeTriggerEnd(cam);
}
if (currentGazeObject != null) {
pointer.OnGazeExit(cam, currentGazeObject);
}
pointer.OnGazeDisabled();
}
pointerObject = value;
pointer = ptr;
pointer.OnGazeEnabled();
if (currentGazeObject != null) {
pointer.OnGazeStart(cam, currentGazeObject, lastIntersectPosition,
currentTarget != null);
}
if (cardboardTrigger) {
pointer.OnGazeTriggerStart(cam);
}
} else {
Debug.LogError("Object must have component which implements ICardboardGazePointer.");
}
} else {
if (pointer != null) {
if (cardboardTrigger) {
pointer.OnGazeTriggerEnd(cam);
}
if (currentTarget != null) {
pointer.OnGazeExit(cam, currentGazeObject);
}
}
pointer = null;
pointerObject = null;
}
}
}
[SerializeField][HideInInspector]
private GameObject pointerObject;
private ICardboardGazePointer pointer;

// Convenient accessor to the camera component used throughout this script.
public Camera cam { get; private set; }

/// The layers to use for finding objects which intersect the user's gaze.
public LayerMask mask = -1;

// Current target detected the user is "gazing" at.
private ICardboardGazeResponder currentTarget;
private GameObject currentGazeObject;

private Vector3 lastIntersectPosition;

// Cardboard Trigger state.
private bool cardboardTrigger;

void Awake() {
cam = GetComponent<Camera>();
PointerObject = pointerObject;
}

void OnEnable() {
if (pointer != null) {
pointer.OnGazeEnabled();
}
}

void OnDisable() {
// Is there a current target?
if (currentTarget != null) {
currentTarget.OnGazeExit();
}
// Tell pointer to exit target.
if (pointer != null) {
// Is there a pending Cardboard trigger?
if (cardboardTrigger) {
pointer.OnGazeTriggerEnd(cam);
}
if (currentGazeObject != null) {
pointer.OnGazeExit(cam, currentGazeObject);
}
pointer.OnGazeDisabled();
}
currentGazeObject = null;
currentTarget = null;
cardboardTrigger = false;
}

void LateUpdate () {
Cardboard.SDK.UpdateState();

// Handle pointer and finding current target.
HandleGaze();

// Handle Cardboard trigger state.
HandleTrigger();
}

private void HandleGaze() {
// Retrieve GazePointer radius.
float innerRadius = 0.0f;
float outerRadius = 0.0f;
if (pointer != null) {
pointer.GetPointerRadius(out innerRadius, out outerRadius);
}

// Find what object the user is looking at.
Vector3 intersectPosition;
ICardboardGazeResponder target = null;
GameObject targetObject = FindGazeTarget(innerRadius, out target, out intersectPosition);

// Found a target?
if (targetObject != null) {
lastIntersectPosition = intersectPosition;

// Is the object new?
if (targetObject != currentGazeObject) {
if (pointer != null) {
pointer.OnGazeExit(cam, currentGazeObject);
}
if (currentTarget != null) {
// Replace with current object.
currentTarget.OnGazeExit();
}

// Save new object.
currentTarget = target;
currentGazeObject = targetObject;

// Inform pointer and target of gaze.
if (pointer != null) {
pointer.OnGazeStart(cam, currentGazeObject, intersectPosition,
currentTarget != null);
}
if (currentTarget != null) {
currentTarget.OnGazeEnter();
}
} else {
// Same object, inform pointer of new intersection.
if (pointer != null) {
pointer.OnGazeStay(cam, currentGazeObject, intersectPosition,
currentTarget != null);
}
}
} else {
// Failed to find an object by inner radius.
if (currentGazeObject != null) {
// Already gazing an object? Check against outer radius.
if (IsGazeNearObject(outerRadius, currentGazeObject, out intersectPosition)) {
// Still gazing.
if (pointer != null) {
pointer.OnGazeStay(cam, currentGazeObject, intersectPosition, currentTarget != null);
}
} else {
// No longer gazing any object.
if (pointer != null) {
pointer.OnGazeExit(cam, currentGazeObject);
}
if (currentTarget != null) {
currentTarget.OnGazeExit();
}
currentTarget = null;
currentGazeObject = null;
}
}
}
}

private GameObject FindGazeTarget(float radius, out ICardboardGazeResponder responder,
out Vector3 intersectPosition) {
RaycastHit hit;
GameObject targetObject = null;
bool hitResult = false;

// Use Raycast or SphereCast?
if (radius > 0.0f) {
// Cast a sphere against the scene.
hitResult = Physics.SphereCast(transform.position,
radius, transform.forward, out hit, cam.farClipPlane, mask);
} else {
// Cast a Ray against the scene.
Ray ray = new Ray(transform.position, transform.forward);
hitResult = Physics.Raycast(ray, out hit, cam.farClipPlane, mask);
}

// Found anything?
if (hitResult) {
// Set object and ICardboardGazeResponder if any.
targetObject = hit.collider.gameObject;
responder = targetObject.GetComponent(typeof(ICardboardGazeResponder))
as ICardboardGazeResponder;
intersectPosition = transform.position + transform.forward * hit.distance;
} else {
// Nothing? Reset variables.
intersectPosition = Vector3.zero;
responder = null;
}

return targetObject;
}

private bool IsGazeNearObject(float radius, GameObject target, out Vector3 intersectPosition) {
RaycastHit[] hits;

// Use Raycast or SphereCast?
if (radius > 0.0f) {
// Cast a sphere against the scene.
hits = Physics.SphereCastAll(transform.position,
radius, transform.forward, cam.farClipPlane, mask);
} else {
// Cast a Ray against the object.
RaycastHit hitInfo;
Ray ray = new Ray(transform.position, transform.forward);

if (target.GetComponent<Collider>().Raycast(ray, out hitInfo, cam.farClipPlane)) {
hits = new RaycastHit[1];
hits[0] = hitInfo;
} else {
hits = new RaycastHit[0];
}
}

// Iterate all intersected objects to find the object we are looking for.
foreach (RaycastHit hit in hits) {
if (hit.collider.gameObject == target) {
// Found our object, save intersection position.
intersectPosition = transform.position + transform.forward * hit.distance;

return true;
}
}

// Desired object was not intersected.
intersectPosition = Vector3.zero;
return false;
}

private void HandleTrigger() {
// If trigger isn't already held.
if (!cardboardTrigger) {
if (Cardboard.SDK.Triggered || Input.GetMouseButtonDown(0)) {
// Trigger started.
cardboardTrigger = true;
if (pointer != null) {
pointer.OnGazeTriggerStart(cam);
}
}
} else if (!Cardboard.SDK.Triggered && !Input.GetMouseButton(0)) {
// Trigger ended.
if (pointer != null) {
pointer.OnGazeTriggerEnd(cam);
}
if (currentTarget != null) {
currentTarget.OnGazeTrigger();
}
cardboardTrigger = false;
}
}
}
35 changes: 25 additions & 10 deletions Cardboard/Scripts/UI/CardboardReticle.cs
Expand Up @@ -18,7 +18,7 @@

[AddComponentMenu("Cardboard/UI/CardboardReticle")]
[RequireComponent(typeof(Renderer))]
public class CardboardReticle : MonoBehaviour, ICardboardPointer {
public class CardboardReticle : MonoBehaviour, ICardboardGazePointer {
/// Number of segments making the reticle circle.
public int reticleSegments = 20;

Expand All @@ -45,7 +45,7 @@ public class CardboardReticle : MonoBehaviour, ICardboardPointer {
private const float kReticleGrowthAngle = 1.5f;

// Minimum distance of the reticle (in meters).
private const float kReticleDistanceMin = 0.75f;
private const float kReticleDistanceMin = 0.45f;
// Maximum distance of the reticle (in meters).
private const float kReticleDistanceMax = 10.0f;

Expand Down Expand Up @@ -90,8 +90,9 @@ public class CardboardReticle : MonoBehaviour, ICardboardPointer {
/// The camera is the event camera, the target is the object
/// the user is looking at, and the intersectionPosition is the intersection
/// point of the ray sent from the camera on the object.
public void OnGazeStart(Camera camera, GameObject targetObject, Vector3 intersectionPosition) {
SetGazeTarget(intersectionPosition);
public void OnGazeStart(Camera camera, GameObject targetObject, Vector3 intersectionPosition,
bool isInteractive) {
SetGazeTarget(intersectionPosition, isInteractive);
}

/// Called every frame the user is still looking at a valid GameObject. This
Expand All @@ -100,8 +101,9 @@ public class CardboardReticle : MonoBehaviour, ICardboardPointer {
/// The camera is the event camera, the target is the object the user is
/// looking at, and the intersectionPosition is the intersection point of the
/// ray sent from the camera on the object.
public void OnGazeStay(Camera camera, GameObject targetObject, Vector3 intersectionPosition) {
SetGazeTarget(intersectionPosition);
public void OnGazeStay(Camera camera, GameObject targetObject, Vector3 intersectionPosition,
bool isInteractive) {
SetGazeTarget(intersectionPosition, isInteractive);
}

/// Called when the user's look no longer intersects an object previously
Expand Down Expand Up @@ -129,6 +131,14 @@ public class CardboardReticle : MonoBehaviour, ICardboardPointer {
// Put your reticle trigger end logic here :)
}

public void GetPointerRadius(out float innerRadius, out float outerRadius) {
float min_inner_angle_radians = Mathf.Deg2Rad * kReticleMinInnerAngle;
float max_inner_angle_radians = Mathf.Deg2Rad * (kReticleMinInnerAngle + kReticleGrowthAngle);

innerRadius = 2.0f * Mathf.Tan(min_inner_angle_radians);
outerRadius = 2.0f * Mathf.Tan(max_inner_angle_radians);
}

private void CreateReticleVertices() {
Mesh mesh = new Mesh();
gameObject.AddComponent<MeshFilter>();
Expand Down Expand Up @@ -209,12 +219,17 @@ public class CardboardReticle : MonoBehaviour, ICardboardPointer {
materialComp.SetFloat("_DistanceInMeters", reticleDistanceInMeters);
}

private void SetGazeTarget(Vector3 target) {
Vector3 targetLocalPosition = transform.parent.InverseTransformPoint(target);
private void SetGazeTarget(Vector3 target, bool interactive) {
Vector3 targetLocalPosition = transform.InverseTransformPoint(target);

reticleDistanceInMeters =
Mathf.Clamp(targetLocalPosition.z, kReticleDistanceMin, kReticleDistanceMax);
reticleInnerAngle = kReticleMinInnerAngle + kReticleGrowthAngle;
reticleOuterAngle = kReticleMinOuterAngle + kReticleGrowthAngle;
if (interactive) {
reticleInnerAngle = kReticleMinInnerAngle + kReticleGrowthAngle;
reticleOuterAngle = kReticleMinOuterAngle + kReticleGrowthAngle;
} else {
reticleInnerAngle = kReticleMinInnerAngle;
reticleOuterAngle = kReticleMinOuterAngle;
}
}
}
Expand Up @@ -31,7 +31,7 @@
/// This class is expected to be inherited by pointers responding to the user's
/// looking at objects in the scene by the movement of their head. For example,
/// see the CardboardReticle class.
public interface ICardboardPointer {
public interface ICardboardGazePointer {
/// This is called when the 'BaseInputModule' system should be enabled.
void OnGazeEnabled();
/// This is called when the 'BaseInputModule' system should be disabled.
Expand All @@ -43,15 +43,17 @@ public interface ICardboardPointer {
/// The camera is the event camera, the target is the object
/// the user is looking at, and the intersectionPosition is the intersection
/// point of the ray sent from the camera on the object.
void OnGazeStart(Camera camera, GameObject targetObject, Vector3 intersectionPosition);
void OnGazeStart(Camera camera, GameObject targetObject, Vector3 intersectionPosition,
bool isInteractive);

/// Called every frame the user is still looking at a valid GameObject. This
/// can be a 3D or UI element.
///
/// The camera is the event camera, the target is the object the user is
/// looking at, and the intersectionPosition is the intersection point of the
/// ray sent from the camera on the object.
void OnGazeStay(Camera camera, GameObject targetObject, Vector3 intersectionPosition);
void OnGazeStay(Camera camera, GameObject targetObject, Vector3 intersectionPosition,
bool isInteractive);

/// Called when the user's look no longer intersects an object previously
/// intersected with a ray projected from the camera.
Expand All @@ -69,4 +71,12 @@ public interface ICardboardPointer {
/// Called when the Cardboard trigger is finished. This is practically when
/// the user releases the trigger.
void OnGazeTriggerEnd(Camera camera);

/// Return the radius of the gaze pointer. This is used when searching for
/// valid gaze targets. If a radius is 0, the CardboardGaze will use a ray
/// to find a valid gaze target. Otherwise it will use a SphereCast.
/// The *innerRadius* is used for finding new targets while the *outerRadius*
/// is used to see if you are still nearby the object currently looked at
/// to avoid a flickering effect when just at the border of the intersection.
void GetPointerRadius(out float innerRadius, out float outerRadius);
}
32 changes: 32 additions & 0 deletions Cardboard/Scripts/UI/ICardboardGazeResponder.cs
@@ -0,0 +1,32 @@
// Copyright 2015 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 UnityEngine;
using System.Collections;

/// This script provides an interface for gaze based responders used with
/// the CardboardGaze script.
public interface ICardboardGazeResponder {
/// Called when the user is looking on a GameObject with this script,
/// as long as it is set to an appropriate layer (see CardboardGaze).
void OnGazeEnter();

/// Called when the user stops looking on the GameObject, after OnGazeEnter
/// was already called.
void OnGazeExit();

// Called when the Cardboard trigger is used, between OnGazeEnter
/// and OnGazeExit.
void OnGazeTrigger();
}
20 changes: 6 additions & 14 deletions Cardboard/Scripts/VRDevices/BaseAndroidDevice.cs
Expand Up @@ -19,14 +19,6 @@
public abstract class BaseAndroidDevice : BaseVRDevice {
protected AndroidJavaObject androidActivity;

public override bool SupportsNativeDistortionCorrection(List<string> diagnostics) {
bool support = base.SupportsNativeDistortionCorrection(diagnostics);
if (androidActivity == null) {
diagnostics.Add("Cannot access Activity");
}
return support;
}

public override void Destroy() {
if (androidActivity != null) {
androidActivity.Dispose();
Expand All @@ -46,7 +38,7 @@ public abstract class BaseAndroidDevice : BaseVRDevice {
}
}

protected AndroidJavaClass GetClass(string className) {
public static AndroidJavaClass GetClass(string className) {
try {
return new AndroidJavaClass(className);
} catch (AndroidJavaException e) {
Expand All @@ -55,7 +47,7 @@ public abstract class BaseAndroidDevice : BaseVRDevice {
}
}

protected AndroidJavaObject Create(string className, params object[] args) {
public static AndroidJavaObject Create(string className, params object[] args) {
try {
return new AndroidJavaObject(className, args);
} catch (AndroidJavaException e) {
Expand All @@ -64,7 +56,7 @@ public abstract class BaseAndroidDevice : BaseVRDevice {
}
}

protected static bool CallStaticMethod(AndroidJavaObject jo, string name, params object[] args) {
public static bool CallStaticMethod(AndroidJavaObject jo, string name, params object[] args) {
if (jo == null) {
Debug.LogError("Object is null when calling static method " + name);
return false;
Expand All @@ -78,7 +70,7 @@ public abstract class BaseAndroidDevice : BaseVRDevice {
}
}

protected static bool CallObjectMethod(AndroidJavaObject jo, string name, params object[] args) {
public static bool CallObjectMethod(AndroidJavaObject jo, string name, params object[] args) {
if (jo == null) {
Debug.LogError("Object is null when calling method " + name);
return false;
Expand All @@ -92,7 +84,7 @@ public abstract class BaseAndroidDevice : BaseVRDevice {
}
}

protected static bool CallStaticMethod<T>(ref T result, AndroidJavaObject jo, string name,
public static bool CallStaticMethod<T>(ref T result, AndroidJavaObject jo, string name,
params object[] args) {
if (jo == null) {
Debug.LogError("Object is null when calling static method " + name);
Expand All @@ -107,7 +99,7 @@ public abstract class BaseAndroidDevice : BaseVRDevice {
}
}

protected static bool CallObjectMethod<T>(ref T result, AndroidJavaObject jo, string name,
public static bool CallObjectMethod<T>(ref T result, AndroidJavaObject jo, string name,
params object[] args) {
if (jo == null) {
Debug.LogError("Object is null when calling method " + name);
Expand Down
110 changes: 31 additions & 79 deletions Cardboard/Scripts/VRDevices/BaseCardboardDevice.cs
Expand Up @@ -28,35 +28,24 @@ public abstract class BaseCardboardDevice :
// A relatively unique id to use when calling our C++ native render plugin.
private const int kCardboardRenderEvent = 0x47554342;

// Event IDs sent up from native layer.
private const int kTriggered = 1;
private const int kTilted = 2;
private const int kProfileChanged = 3;
private const int kVRBackButton = 4;
// Event IDs sent up from native layer. Bit flags.
// Keep in sync with the corresponding declaration in unity.h.
private const int kTriggered = 1 << 0;
private const int kTilted = 1 << 1;
private const int kProfileChanged = 1 << 2;
private const int kVRBackButtonPressed = 1 << 3;

private float[] headData = new float[16];
private float[] viewData = new float[16 * 6 + 10];
private float[] viewData = new float[16 * 6 + 12];
private float[] profileData = new float[13];

private Matrix4x4 headView = new Matrix4x4();
private Matrix4x4 leftEyeView = new Matrix4x4();
private Matrix4x4 rightEyeView = new Matrix4x4();

private Queue<int> eventQueue = new Queue<int>();

protected bool debugDisableNativeProjections = false;
protected bool debugDisableNativeDistortion = false;
protected bool debugDisableNativeUILayer = false;

public override bool SupportsNativeDistortionCorrection(List<string> diagnostics) {
bool supported = base.SupportsNativeDistortionCorrection(diagnostics);
if (debugDisableNativeDistortion) {
supported = false;
diagnostics.Add("Debug override");
}
return supported;
}

public override void SetDistortionCorrectionEnabled(bool enabled) {
EnableDistortionCorrection(enabled);
}
Expand All @@ -79,22 +68,10 @@ public abstract class BaseCardboardDevice :
}

public override void Init() {
DisplayMetrics dm = GetDisplayMetrics();

// Start will send a log event, so SetUnityVersion first.
byte[] version = System.Text.Encoding.UTF8.GetBytes(Application.unityVersion);
SetUnityVersion(version, version.Length);
Start(dm.width, dm.height, dm.xdpi, dm.ydpi);
SetEventCallback(OnVREvent);
}

public override void SetStereoScreen(RenderTexture stereoScreen) {
#if UNITY_5 || !UNITY_IOS
SetTextureId(stereoScreen != null ? (int)stereoScreen.GetNativeTexturePtr() : 0);
#else
// Using old API for Unity 4.x and iOS because Metal crashes on GetNativeTexturePtr()
SetTextureId(stereoScreen != null ? stereoScreen.GetNativeTextureID() : 0);
#endif
Start();
}

public override void UpdateState() {
Expand All @@ -118,7 +95,8 @@ public abstract class BaseCardboardDevice :
ResetHeadTracker();
}

public override void PostRender() {
public override void PostRender(RenderTexture stereoScreen) {
SetTextureId((int)stereoScreen.GetNativeTexturePtr());
GL.IssuePluginEvent(kCardboardRenderEvent);
}

Expand Down Expand Up @@ -157,6 +135,10 @@ public abstract class BaseCardboardDevice :
rightEyeDistortedViewport = rightEyeUndistortedViewport;
j += 4;

leftEyeOrientation = (int)viewData[j];
rightEyeOrientation = (int)viewData[j+1];
j += 2;

recommendedTextureSize = new Vector2(viewData[j], viewData[j+1]);
j += 2;
}
Expand All @@ -176,11 +158,15 @@ public abstract class BaseCardboardDevice :
device.lenses.offset = profileData[8];
device.lenses.screenDistance = profileData[9];
device.lenses.alignment = (int)profileData[10];
device.distortion.k1 = profileData[11];
device.distortion.k2 = profileData[12];
device.inverse = CardboardProfile.ApproximateInverse(device.distortion);
device.distortion.Coef = new [] { profileData[11], profileData[12] };
Profile.screen = screen;
Profile.device = device;

float[] rect = new float[4];
Profile.GetLeftEyeNoLensTanAngles(rect);
float maxRadius = CardboardProfile.GetMaxRadius(rect);
Profile.device.inverse = CardboardProfile.ApproximateInverse(
Profile.device.distortion, maxRadius);
}

private static int ExtractMatrix(ref Matrix4x4 mat, float[] data, int i = 0) {
Expand All @@ -193,45 +179,13 @@ public abstract class BaseCardboardDevice :
return i;
}

private int[] events = new int[4];

protected virtual void ProcessEvents() {
int num = 0;
lock (eventQueue) {
num = eventQueue.Count;
if (num == 0) {
return;
}
if (num > events.Length) {
events = new int[num];
}
eventQueue.CopyTo(events, 0);
eventQueue.Clear();
}
for (int i = 0; i < num; i++) {
switch (events[i]) {
case kTriggered:
triggered = true;
break;
case kTilted:
tilted = true;
break;
case kProfileChanged:
UpdateScreenData();
break;
case kVRBackButton:
backButtonPressed = true;
break;
}
}
}

[MonoPInvokeCallback(typeof(VREventCallback))]
private static void OnVREvent(int eventID) {
BaseCardboardDevice device = GetDevice() as BaseCardboardDevice;
// This function is called back from random native code threads.
lock (device.eventQueue) {
device.eventQueue.Enqueue(eventID);
int flags = GetEventFlags();
triggered = ((flags & kTriggered) != 0);
tilted = ((flags & kTilted) != 0);
backButtonPressed = ((flags & kVRBackButtonPressed) != 0);
if ((flags & kProfileChanged) != 0) {
UpdateScreenData();
}
}

Expand All @@ -241,13 +195,8 @@ public abstract class BaseCardboardDevice :
private const string dllName = "vrunity";
#endif

delegate void VREventCallback(int eventID);

[DllImport(dllName)]
private static extern void Start(int width, int height, float xdpi, float ydpi);

[DllImport(dllName)]
private static extern void SetEventCallback(VREventCallback callback);
private static extern void Start();

[DllImport(dllName)]
private static extern void SetTextureId(int id);
Expand All @@ -273,6 +222,9 @@ public abstract class BaseCardboardDevice :
[DllImport(dllName)]
private static extern void ResetHeadTracker();

[DllImport(dllName)]
private static extern int GetEventFlags();

[DllImport(dllName)]
private static extern void GetProfile(float[] profile);

Expand Down
57 changes: 15 additions & 42 deletions Cardboard/Scripts/VRDevices/BaseVRDevice.cs
Expand Up @@ -28,11 +28,6 @@
// Represents a vr device that this plugin interacts with.
// Please do not interact with this class directly, instead use the interface in Cardboard.cs.
public abstract class BaseVRDevice {
public struct DisplayMetrics {
public int width, height;
public float xdpi, ydpi;
}

private static BaseVRDevice device = null;

protected BaseVRDevice() {
Expand All @@ -46,62 +41,42 @@ public struct DisplayMetrics {
public abstract void SetUILayerEnabled(bool enabled);
public abstract void SetVRModeEnabled(bool enabled);
public abstract void SetDistortionCorrectionEnabled(bool enabled);
public abstract void SetStereoScreen(RenderTexture stereoScreen);

public abstract void SetSettingsButtonEnabled(bool enabled);
public abstract void SetAlignmentMarkerEnabled(bool enabled);
public abstract void SetVRBackButtonEnabled(bool enabled);
public abstract void SetShowVrBackButtonOnlyInVR(bool only);

public abstract void SetTapIsTrigger(bool enabled);
public abstract void SetNeckModelScale(float scale);
public abstract void SetAutoDriftCorrectionEnabled(bool enabled);
public abstract void SetElectronicDisplayStabilizationEnabled(bool enabled);

// Returns landscape orientation display metrics.
public virtual DisplayMetrics GetDisplayMetrics() {
// Always return landscape orientation.
int width = Mathf.Max(Screen.width, Screen.height);
int height = Mathf.Min(Screen.width, Screen.height);
return new DisplayMetrics { width = width, height = height, xdpi = Screen.dpi, ydpi = Screen.dpi };
public virtual bool SupportsNativeDistortionCorrection(List<string> diagnostics) {
return true;
}

public virtual bool SupportsNativeDistortionCorrection(List<string> diagnostics) {
bool support = true;
if (!SystemInfo.supportsRenderTextures) {
diagnostics.Add("RenderTexture (Unity Pro feature) is unavailable");
support = false;
}
if (!SupportsUnityRenderEvent()) {
diagnostics.Add("Unity 4.5+ is needed for UnityRenderEvent");
support = false;
}
return support;
public virtual bool RequiresNativeDistortionCorrection() {
return leftEyeOrientation != 0 || rightEyeOrientation != 0;
}

public virtual bool SupportsNativeUILayer(List<string> diagnostics) {
return true;
}

public bool SupportsUnityRenderEvent() {
bool support = true;
if (Application.isMobilePlatform) {
try {
string version = new Regex(@"(\d+\.\d+)\..*").Replace(Application.unityVersion, "$1");
if (new Version(version) < new Version("4.5")) {
support = false;
}
} catch {
Debug.LogWarning("Unable to determine Unity version from: " + Application.unityVersion);
}
}
return support;
public virtual bool ShouldRecreateStereoScreen(int curWidth, int curHeight) {
return this.RequiresNativeDistortionCorrection()
&& (curWidth != (int)recommendedTextureSize[0]
|| curHeight != (int)recommendedTextureSize[1]);
}

public virtual RenderTexture CreateStereoScreen() {
float scale = Cardboard.SDK.StereoScreenScale;
int width = Mathf.RoundToInt(Screen.width * scale);
int height = Mathf.RoundToInt(Screen.height * scale);
if (this.RequiresNativeDistortionCorrection()) {
width = (int)recommendedTextureSize[0];
height = (int)recommendedTextureSize[1];
}
//Debug.Log("Creating new default cardboard screen texture "
// + width+ "x" + height + ".");
var rt = new RenderTexture(width, height, 24, RenderTextureFormat.Default);
Expand Down Expand Up @@ -175,6 +150,8 @@ public struct DisplayMetrics {
protected Rect rightEyeUndistortedViewport;

protected Vector2 recommendedTextureSize;
protected int leftEyeOrientation;
protected int rightEyeOrientation;

public bool triggered;
public bool tilted;
Expand All @@ -187,11 +164,7 @@ public struct DisplayMetrics {

public abstract void Recenter();

public abstract void PostRender();

public virtual void SetTouchCoordinates(int x, int y) {
// Do nothing
}
public abstract void PostRender(RenderTexture stereoScreen);

public virtual void OnPause(bool pause) {
if (!pause) {
Expand Down
41 changes: 0 additions & 41 deletions Cardboard/Scripts/VRDevices/CardboardAndroidDevice.cs
Expand Up @@ -34,27 +34,6 @@ public class CardboardAndroidDevice : BaseCardboardDevice {
}
}

// Returns landscape orientation display metrics.
public override DisplayMetrics GetDisplayMetrics() {
using (var listenerClass = GetClass(ActivityListenerClass)) {
// Sadly some Android devices still don't report accurate values. If this
// doesn't work correctly on your device, comment out this function to try
// the Unity implementation.
float[] metrics = listenerClass.CallStatic<float[]>("getDisplayMetrics");
// Always return landscape orientation.
int width, height;
if (metrics[0] > metrics[1]) {
width = (int)metrics[0];
height = (int)metrics[1];
} else {
width = (int)metrics[1];
height = (int)metrics[0];
}
// DPI-x (metrics[2]) on Android appears to refer to the narrow dimension of the screen.
return new DisplayMetrics { width = width, height = height, xdpi = metrics[3], ydpi = metrics[2] };
}
}

public override void SetUILayerEnabled(bool enabled) {
CallObjectMethod(activityListener, "setUILayerEnabled", enabled);
}
Expand All @@ -79,30 +58,10 @@ public class CardboardAndroidDevice : BaseCardboardDevice {
CallObjectMethod(activityListener, "setShowVrBackButtonOnlyInVR", only);
}

public override void SetTapIsTrigger(bool enabled) {
CallObjectMethod(activityListener, "setTapIsTrigger", enabled);
}

public override void SetTouchCoordinates(int x, int y) {
CallObjectMethod(activityListener, "setTouchCoordinates", x, y);
}

public override void ShowSettingsDialog() {
CallObjectMethod(activityListener, "launchConfigureActivity");
}

protected override void ProcessEvents() {
base.ProcessEvents();
if (!Cardboard.SDK.TapIsTrigger) {
if (triggered) {
CallObjectMethod(activityListener, "injectSingleTap");
}
if (backButtonPressed) {
CallObjectMethod(activityListener, "injectKeyPress", 111); // Escape key.
}
}
}

public override void OnPause(bool pause) {
base.OnPause(pause);
CallObjectMethod(activityListener, "onPause", pause);
Expand Down
48 changes: 0 additions & 48 deletions Cardboard/Scripts/VRDevices/CardboardiOSDevice.cs
Expand Up @@ -21,15 +21,6 @@ public class CardboardiOSDevice : BaseCardboardDevice {
// Native code libraries use OpenGL, but Unity picks Metal for iOS by default.
bool isOpenGL = false;

// Returns landscape orientation display metrics.
public override DisplayMetrics GetDisplayMetrics() {
// Always return landscape orientation.
int width = Mathf.Max(Screen.width, Screen.height);
int height = Mathf.Min(Screen.width, Screen.height);
float dpi = getScreenDPI();
return new DisplayMetrics { width = width, height = height, xdpi = dpi, ydpi = dpi };
}

public override bool SupportsNativeDistortionCorrection(List<string> diagnostics) {
bool support = base.SupportsNativeDistortionCorrection(diagnostics);
if (!isOpenGL) {
Expand Down Expand Up @@ -68,37 +59,13 @@ public class CardboardiOSDevice : BaseCardboardDevice {
base.SetAutoDriftCorrectionEnabled(false);
}

public override void SetTapIsTrigger(bool enabled) {
// Not supported on iOS.
}

public override bool SetDefaultDeviceProfile(System.Uri uri) {
bool result = base.SetDefaultDeviceProfile(uri);
if (result) {
setOnboardingDone();
}
return result;
}

public override void Init() {
isOpenGL = isOpenGLAPI();
setSyncWithCardboardEnabled(Cardboard.SDK.SyncWithCardboardApp);
base.Init();
// For iOS don't use Drift Correction.
SetAutoDriftCorrectionEnabled(false);
}

// Set this to true to force an onboarding process.
private bool debugOnboarding = false;

public void ShowOnboardingDialog() {
if (debugOnboarding || !isOnboardingDone()) {
debugOnboarding = false;
launchOnboardingDialog();
setOnboardingDone();
}
}

public override void ShowSettingsDialog() {
launchSettingsDialog();
}
Expand All @@ -124,23 +91,8 @@ public class CardboardiOSDevice : BaseCardboardDevice {
[DllImport("__Internal")]
private static extern void setVRBackButtonEnabled(bool enabled);

[DllImport("__Internal")]
private static extern void setSyncWithCardboardEnabled(bool enabled);

[DllImport("__Internal")]
private static extern void setOnboardingDone();

[DllImport("__Internal")]
private static extern bool isOnboardingDone();

[DllImport("__Internal")]
private static extern void launchSettingsDialog();

[DllImport("__Internal")]
private static extern void launchOnboardingDialog();

[DllImport("__Internal")]
private static extern float getScreenDPI();
}

#endif
8 changes: 1 addition & 7 deletions Cardboard/Scripts/VRDevices/UnityEditorDevice.cs
Expand Up @@ -44,27 +44,21 @@ public class UnityEditorDevice : BaseVRDevice {
public override void SetUILayerEnabled(bool enabled) {}
public override void SetVRModeEnabled(bool enabled) {}
public override void SetDistortionCorrectionEnabled(bool enabled) {}
public override void SetStereoScreen(RenderTexture stereoScreen) {}
public override void SetSettingsButtonEnabled(bool enabled) {}
public override void SetAlignmentMarkerEnabled(bool enabled) {}
public override void SetVRBackButtonEnabled(bool enabled) {}
public override void SetShowVrBackButtonOnlyInVR(bool only) {}
public override void SetNeckModelScale(float scale) {}
public override void SetAutoDriftCorrectionEnabled(bool enabled) {}
public override void SetElectronicDisplayStabilizationEnabled(bool enabled) {}
public override void SetTapIsTrigger(bool enabled) {}

private Quaternion initialRotation = Quaternion.identity;

private bool remoteCommunicating = false;
private bool RemoteCommunicating {
get {
if (!remoteCommunicating) {
#if UNITY_5
remoteCommunicating = EditorApplication.isRemoteConnected;
#else
remoteCommunicating = Vector3.Dot(Input.gyro.rotationRate, Input.gyro.rotationRate) > 0.05;
#endif
}
return remoteCommunicating;
}
Expand Down Expand Up @@ -105,7 +99,7 @@ public class UnityEditorDevice : BaseVRDevice {
tilted = Input.GetKeyUp(KeyCode.Escape);
}

public override void PostRender() {
public override void PostRender(RenderTexture stereoScreen) {
// Do nothing.
}

Expand Down
Binary file modified CardboardDemoForUnity.unitypackage
Binary file not shown.
Binary file modified CardboardSDKForUnity.unitypackage
Binary file not shown.
Expand Up @@ -37,21 +37,11 @@ float _MaxRadSq;
float4x4 _RealProjection;

float4 undistort(float4 pos) {


#if SHADER_API_GLES || SHADER_API_GLES3
pos = mul(UNITY_MATRIX_MV, pos);
float near = -(UNITY_MATRIX_P[2][2] + 1) / UNITY_MATRIX_P[3][2];
if (pos.z < near) {
float r2 = clamp(dot(pos.xy, pos.xy) / (pos.z*pos.z), 0, _MaxRadSq);
pos.xy *= 1 + (_Undistortion.x + _Undistortion.y*r2)*r2;
}
#else

return mul(UNITY_MATRIX_MVP, pos);
#endif
//return mul(UNITY_MATRIX_P, pos);
return mul(_RealProjection, pos);

//return mul(transpose(UNITY_MATRIX_IT_MV), pos);
}
3 changes: 2 additions & 1 deletion ThirdParty/LICENSE.GL → ThirdParty/GL.html
@@ -1,4 +1,4 @@
Mesa Component Licenses
<!DOCTYPE html><html><head><style> body { font-family: sans-serif; } pre { white-space: pre-wrap; } </style></head><body><pre>Mesa Component Licenses

Component Location Primary Author License
----------------------------------------------------------------------------
Expand Down Expand Up @@ -578,3 +578,4 @@
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.
</pre></body></html>
36 changes: 0 additions & 36 deletions ThirdParty/LICENSE.harfbuzz

This file was deleted.

55 changes: 0 additions & 55 deletions ThirdParty/LICENSE.jsoncpp

This file was deleted.

20 changes: 0 additions & 20 deletions ThirdParty/LICENSE.rply

This file was deleted.

943 changes: 943 additions & 0 deletions ThirdParty/Xorg.html

Large diffs are not rendered by default.

@@ -1,4 +1,4 @@

<!DOCTYPE html><html><head><style> body { font-family: sans-serif; } pre { white-space: pre-wrap; } </style></head><body><pre>
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
Expand Down Expand Up @@ -200,3 +200,4 @@
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.
</pre></body></html>
28 changes: 28 additions & 0 deletions ThirdParty/chromium_audio.html
@@ -0,0 +1,28 @@
<!DOCTYPE html><html><head><style> body { font-family: sans-serif; } pre { white-space: pre-wrap; } </style></head><body><pre>// Copyright 2014 The Chromium Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</pre></body></html>
22 changes: 22 additions & 0 deletions ThirdParty/curl.html
@@ -0,0 +1,22 @@
<!DOCTYPE html><html><head><style> body { font-family: sans-serif; } pre { white-space: pre-wrap; } </style></head><body><pre>COPYRIGHT AND PERMISSION NOTICE

Copyright (c) 1996 - 2014, Daniel Stenberg, <daniel@haxx.se>.

All rights reserved.

Permission to use, copy, modify, and distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright
notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
OR OTHER DEALINGS IN THE SOFTWARE.

Except as contained in this notice, the name of a copyright holder shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization of the copyright holder.
</pre></body></html>
27 changes: 13 additions & 14 deletions ThirdParty/LICENSE.libwebp → ThirdParty/dynamic_annotations.html
@@ -1,30 +1,29 @@
Copyright (c) 2010, Google Inc. All rights reserved.
<!DOCTYPE html><html><head><style> body { font-family: sans-serif; } pre { white-space: pre-wrap; } </style></head><body><pre>Copyright (c) 2008-2009, Google Inc.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.

* Neither the name of Google nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

</pre></body></html>
3 changes: 2 additions & 1 deletion ThirdParty/LICENSE.eigen3 → ThirdParty/eigen3.html
@@ -1,4 +1,4 @@
Eigen is primarily MPL2 licensed. See COPYING.MPL2 and these links:
<!DOCTYPE html><html><head><style> body { font-family: sans-serif; } pre { white-space: pre-wrap; } </style></head><body><pre>Eigen is primarily MPL2 licensed. See COPYING.MPL2 and these links:
http://www.mozilla.org/MPL/2.0/
http://www.mozilla.org/MPL/2.0/FAQ.html

Expand Down Expand Up @@ -1934,3 +1934,4 @@
(INCLUDING NEGLIGENCE OR STRICT LIABILITY), OR OTHERWISE,
EVEN IF ANY OF SAID PARTIES HAS BEEN WARNED OF THE
POSSIBILITY OF SUCH LOSS OR DAMAGES.
</pre></body></html>
3 changes: 2 additions & 1 deletion ThirdParty/LICENSE.freetype2 → ThirdParty/freetype2.html
@@ -1,4 +1,4 @@
FreeType
<!DOCTYPE html><html><head><style> body { font-family: sans-serif; } pre { white-space: pre-wrap; } </style></head><body><pre>FreeType

Quoth http://freetype.sourceforge.net/license.html:

Expand Down Expand Up @@ -185,3 +185,4 @@


--- end of FTL.TXT ---
</pre></body></html>
103 changes: 103 additions & 0 deletions ThirdParty/googleurl.html
@@ -0,0 +1,103 @@
<!DOCTYPE html><html><head><style> body { font-family: sans-serif; } pre { white-space: pre-wrap; } </style></head><body><pre>Copyright 2007, Google Inc.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

-------------------------------------------------------------------------------

The file url_parse.cc is based on nsURLParsers.cc from Mozilla. This file is
licensed separately as follows:

The contents of this file are subject to the Mozilla Public License Version
1.1 (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.mozilla.org/MPL/

Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
for the specific language governing rights and limitations under the
License.

The Original Code is mozilla.org code.

The Initial Developer of the Original Code is
Netscape Communications Corporation.
Portions created by the Initial Developer are Copyright (C) 1998
the Initial Developer. All Rights Reserved.

Contributor(s):
Darin Fisher (original author)

Alternatively, the contents of this file may be used under the terms of
either the GNU General Public License Version 2 or later (the "GPL"), or
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
in which case the provisions of the GPL or the LGPL are applicable instead
of those above. If you wish to allow use of your version of this file only
under the terms of either the GPL or the LGPL, and not to allow others to
use your version of this file under the terms of the MPL, indicate your
decision by deleting the provisions above and replace them with the notice
and other provisions required by the GPL or the LGPL. If you do not delete
the provisions above, a recipient may use your version of this file under
the terms of any one of the MPL, the GPL or the LGPL.

-------------------------------------------------------------------------------

The file icu_utf.cc is from IBM. This file is licensed separately as follows:

ICU License - ICU 1.8.1 and later

COPYRIGHT AND PERMISSION NOTICE

Copyright (c) 1995-2009 International Business Machines Corporation and others

All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, and/or sell copies of the Software, and to permit persons
to whom the Software is furnished to do so, provided that the above
copyright notice(s) and this permission notice appear in all copies of
the Software and that both the above copyright notice(s) and this
permission notice appear in supporting documentation.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

Except as contained in this notice, the name of a copyright holder
shall not be used in advertising or otherwise to promote the sale, use
or other dealings in this Software without prior written authorization
of the copyright holder.
</pre></body></html>
132 changes: 66 additions & 66 deletions ThirdParty/LICENSE.libresample → ThirdParty/grte.html
@@ -1,52 +1,4 @@
All of the files in this package are Copyright 2003 by Dominic
Mazzoni <dominic@minorninth.com>. This library was based heavily
on Resample-1.7, Copyright 1994-2002 by Julius O. Smith III
<jos@ccrma.stanford.edu>, all rights reserved.

Permission to use and copy is granted subject to the terms of the
"GNU Lesser General Public License" (LGPL) as published by the
Free Software Foundation; either version 2.1 of the License,
or any later version. In addition, Julius O. Smith III requests
that a copy of any modified files be sent by email to
jos@ccrma.stanford.edu so that he may incorporate them into the
CCRMA version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

Permission to use and copy is also granted subject to the terms of the
BSD license found below.

-------------------------------------------------------------------------------

Copyright (c) 2003, Dominic Mazzoni
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

-------------------------------------------------------------------------------

<!DOCTYPE html><html><head><style> body { font-family: sans-serif; } pre { white-space: pre-wrap; } </style></head><body><pre>
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999

Expand Down Expand Up @@ -105,7 +57,7 @@
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.

^L
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
Expand Down Expand Up @@ -137,9 +89,9 @@
special circumstances.

For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
encourage the widest possible use of a certain library, so that it
becomes a de-facto standard. To achieve this, non-free programs must
be allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
Expand All @@ -161,7 +113,7 @@
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.

^L
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

Expand All @@ -187,8 +139,7 @@
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control
compilation
and installation of the library.
compilation and installation of the library.

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
Expand All @@ -209,7 +160,7 @@
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.


2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
Expand Down Expand Up @@ -267,7 +218,7 @@
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.

^L
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
Expand Down Expand Up @@ -318,7 +269,7 @@
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.

^L
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
Expand Down Expand Up @@ -354,10 +305,10 @@
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.

c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
c) Accompany the work with a written offer, valid for at least
three years, to give the same user the materials specified in
Subsection 6a, above, for a charge no more than the cost of
performing this distribution.

d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
Expand All @@ -380,7 +331,7 @@
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.

^L
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
Expand Down Expand Up @@ -421,7 +372,7 @@
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.

^L
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
Expand Down Expand Up @@ -474,7 +425,7 @@
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.

^L
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
Expand Down Expand Up @@ -508,4 +459,53 @@
DAMAGES.

END OF TERMS AND CONDITIONS
^L
How to Apply These Terms to Your New Libraries

If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms
of the ordinary General Public License).

To apply these terms, attach the following notices to the library.
It is safest to attach them to the start of each source file to most
effectively convey the exclusion of warranty; and each file should
have at least the "copyright" line and a pointer to where the full
notice is found.


<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

Also add information on how to contact you by electronic and paper mail.

You should also get your employer (if you work as a programmer) or
your school, if any, to sign a "copyright disclaimer" for the library,
if necessary. Here is a sample; alter the names:

Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James
Random Hacker.

<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice

That's all there is to it!


</pre></body></html>
37 changes: 37 additions & 0 deletions ThirdParty/gsc_licenses_index.txt
@@ -0,0 +1,37 @@
GL.html/GL
Xorg.html/Xorg
bazel.html/bazel_src_main_protobuf
chromium_audio.html/chromium_audio
curl.html/curl
dynamic_annotations.html/DynamicAnnotations
eigen3.html/Eigen 3
freetype2.html/freetype2
googleurl.html/googleurl
grte.html/grte
icu.html/ICU4C
java_android_libs_protobuf_nano.html/Protobuf Nano
javascript_jquery_ui.html/javascript_jquery_ui
javascript_jquery_v2_0_1.html/javascript_jquery
javascript_tracing_framework.html/javascript_tracing_framework
libunwind.html/libunwind
libxcb.html/libxcb
lodepng.html/lodepng
minizip.html/minizip
mongoose.html/mongoose
objective_c_google_toolbox_for_mac.html/objective_c_google_toolbox_for_mac
objective_c_gtm_session_fetcher.html/objective_c_gtm_session_fetcher
objective_c_material_components_ios.html/Material Components iOS
objective_c_nimbus.html/objective_c_nimbus
openctm.html/openctm
openssl.html/openssl
openssl_boringssl.html/openssl_boringssl
pcre.html/pcre
pffft.html/pffft
protobuf.html/protobuf
re2.html/re2
stblib.html/stblib
stl.html/stl
tinyxml.html/tinyxml
tz.html/tz
utf.html/UTF
zlib.html/zlib
3 changes: 2 additions & 1 deletion ThirdParty/LICENSE.icu → ThirdParty/icu.html
@@ -1,4 +1,4 @@
ICU
<!DOCTYPE html><html><head><style> body { font-family: sans-serif; } pre { white-space: pre-wrap; } </style></head><body><pre>ICU

There are two licenses here:
- ICU license
Expand Down Expand Up @@ -197,3 +197,4 @@
Unicode and the Unicode logo are trademarks of Unicode, Inc., and may be
registered in some jurisdictions. All other trademarks and registered
trademarks mentioned herein are the property of their respective owners.
</pre></body></html>
@@ -1,4 +1,4 @@
Copyright 2008, Google Inc.
<!DOCTYPE html><html><head><style> body { font-family: sans-serif; } pre { white-space: pre-wrap; } </style></head><body><pre>Copyright 2008, Google Inc.
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -31,3 +31,4 @@
of the input file used when generating it. This code is not
standalone and requires a support library to be linked with it. This
support library is itself covered by the above license.
</pre></body></html>
21 changes: 21 additions & 0 deletions ThirdParty/javascript_jquery_ui.html
@@ -0,0 +1,21 @@
<!DOCTYPE html><html><head><style> body { font-family: sans-serif; } pre { white-space: pre-wrap; } </style></head><body><pre>The MIT License (MIT)

Copyright (c) 2015 jQuery Foundation and other contributors

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
</pre></body></html>
35 changes: 35 additions & 0 deletions ThirdParty/javascript_jquery_v2_0_1.html
@@ -0,0 +1,35 @@
<!DOCTYPE html><html><head><style> body { font-family: sans-serif; } pre { white-space: pre-wrap; } </style></head><body><pre>Copyright 2013 jQuery Foundation and other contributors
http://jquery.com/

https://github.com/jquery/jquery/blob/master/MIT-LICENSE.txt
https://github.com/jquery/sizzle/blob/master/LICENSE

jQuery and Sizzle are released under MIT Licence.

The text is provided below.

MIT License
----

Copyright 2013 jQuery Foundation and other contributors
http://jquery.com/

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
</pre></body></html>
@@ -1,4 +1,4 @@
Copyright (c) 2006, Google Inc.
<!DOCTYPE html><html><head><style> body { font-family: sans-serif; } pre { white-space: pre-wrap; } </style></head><body><pre>Copyright 2012, Google Inc.
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -26,3 +26,4 @@
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</pre></body></html>
21 changes: 21 additions & 0 deletions ThirdParty/libunwind.html
@@ -0,0 +1,21 @@
<!DOCTYPE html><html><head><style> body { font-family: sans-serif; } pre { white-space: pre-wrap; } </style></head><body><pre>Copyright (c) 2002 Hewlett-Packard Co.

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
</pre></body></html>
31 changes: 31 additions & 0 deletions ThirdParty/libxcb.html
@@ -0,0 +1,31 @@
<!DOCTYPE html><html><head><style> body { font-family: sans-serif; } pre { white-space: pre-wrap; } </style></head><body><pre>Copyright (C) 2001-2006 Bart Massey, Jamey Sharp, and Josh Triplett.
All Rights Reserved.

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall
be included in all copies or substantial portions of the
Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

Except as contained in this notice, the names of the authors
or their institutions shall not be used in advertising or
otherwise to promote the sale, use or other dealings in this
Software without prior written authorization from the
authors.
</pre></body></html>
3 changes: 2 additions & 1 deletion ThirdParty/LICENSE.lodepng → ThirdParty/lodepng.html
@@ -1,4 +1,4 @@
LodePNG
<!DOCTYPE html><html><head><style> body { font-family: sans-serif; } pre { white-space: pre-wrap; } </style></head><body><pre>LodePNG

Copyright (c) 2005-2013 Lode Vandevenne

Expand All @@ -20,3 +20,4 @@

3. This notice may not be removed or altered from any source
distribution.
</pre></body></html>
3 changes: 2 additions & 1 deletion ThirdParty/LICENSE.minizip → ThirdParty/minizip.html
@@ -1,4 +1,4 @@
zlib
<!DOCTYPE html><html><head><style> body { font-family: sans-serif; } pre { white-space: pre-wrap; } </style></head><body><pre>zlib

(extracted from README, except for match.S)

Expand Down Expand Up @@ -45,3 +45,4 @@
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
</pre></body></html>
20 changes: 20 additions & 0 deletions ThirdParty/mongoose.html
@@ -0,0 +1,20 @@
<!DOCTYPE html><html><head><style> body { font-family: sans-serif; } pre { white-space: pre-wrap; } </style></head><body><pre>Copyright (c) 2004-2013 Sergey Lyubka

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
</pre></body></html>