Commit 29de0c28 authored by BlackAngle233's avatar BlackAngle233
Browse files

10.19 learned

parent 912976bb
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using UnityEngine;
namespace Microsoft.MixedReality.Toolkit
{
public class ReadOnlyAttribute : PropertyAttribute { }
public class BeginReadOnlyGroupAttribute : PropertyAttribute { }
public class EndReadOnlyGroupAttribute : PropertyAttribute { }
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System;
using UnityEngine;
namespace Microsoft.MixedReality.Toolkit
{
/// <summary>
/// Attribute to mark up an int field to be drawn using the
/// ScenePickPropertyDrawer
/// This allows the UI to display a dropdown instead of a
/// numeric entry field.
/// </summary>
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class ScenePickAttribute : PropertyAttribute
{
// Nothing to see Here, This only acts as a marker to help the editor.
}
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using Microsoft.MixedReality.Toolkit.Utilities;
#if WINDOWS_UWP && !ENABLE_IL2CPP
using Microsoft.MixedReality.Toolkit;
#endif // WINDOWS_UWP && !ENABLE_IL2CPP
using System;
using UnityEngine;
namespace Microsoft.MixedReality.Toolkit
{
/// <summary>
/// Base class for class selection constraints that can be applied when selecting
/// a <see cref="Utilities.SystemType"/> with the Unity inspector.
/// </summary>
public abstract class SystemTypeAttribute : PropertyAttribute
{
/// <summary>
/// Gets or sets grouping of selectable classes. Defaults to <see cref="Utilities.TypeGrouping.ByNamespaceFlat"/> unless explicitly specified.
/// </summary>
public TypeGrouping Grouping { get; protected set; }
/// <summary>
/// Gets or sets whether abstract classes can be selected from drop-down.
/// Defaults to a value of <c>false</c> unless explicitly specified.
/// </summary>
public bool AllowAbstract { get; protected set; } = false;
/// <summary>
///
/// </summary>
/// <param name="type">Initializes a new instance of the <see cref="SystemTypeAttribute"/> class.</param>
/// <param name="grouping">Gets or sets grouping of selectable classes. Defaults to <see cref="Utilities.TypeGrouping.ByNamespaceFlat"/> unless explicitly specified.</param>
protected SystemTypeAttribute(Type type, TypeGrouping grouping = TypeGrouping.ByNamespaceFlat)
{
#if WINDOWS_UWP && !ENABLE_IL2CPP
bool isValid = type.IsClass() || type.IsInterface() || type.IsValueType() && !type.IsEnum();
#else
bool isValid = type.IsClass || type.IsInterface || type.IsValueType && !type.IsEnum;
#endif // WINDOWS_UWP && !ENABLE_IL2CPP
Debug.Assert(isValid, $"Invalid Type {type} in attribute.");
Grouping = grouping;
}
/// <summary>
/// Determines whether the specified <see cref="System.Type"/> satisfies filter constraint.
/// </summary>
/// <param name="type">Type to test.</param>
/// <returns>
/// A <see cref="bool"/> value indicating if the type specified by <paramref name="type"/>
/// satisfies this constraint and should thus be selectable.
/// </returns>
public virtual bool IsConstraintSatisfied(Type type)
{
#if WINDOWS_UWP && !ENABLE_IL2CPP
return AllowAbstract || !type.IsAbstract();
#else
return AllowAbstract || !type.IsAbstract;
#endif // WINDOWS_UWP && !ENABLE_IL2CPP
}
}
}
\ No newline at end of file
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using UnityEngine;
using System;
namespace Microsoft.MixedReality.Toolkit
{
/// <summary>
/// A PropertyAttribute for Unity tags (a string field).
/// </summary>
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class TagPropertyAttribute : PropertyAttribute
{
// Do nothing
}
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System;
using UnityEngine;
namespace Microsoft.MixedReality.Toolkit
{
/// <summary>
/// Attribute used to make a float or int variable in a script be restricted to a specific range.
/// </summary>
[AttributeUsage(AttributeTargets.Field)]
public sealed class Vector3RangeAttribute : PropertyAttribute
{
/// <summary>
/// Minimum value.
/// </summary>
public readonly float Min;
/// <summary>
/// Maximum value.
/// </summary>
public readonly float Max;
/// <summary>
/// Attribute used to make a float or int variable in a script be restricted to a specific range.
/// </summary>
/// <param name="min">The minimum allowed value.</param>
/// <param name="max">The maximum allowed value.</param>
public Vector3RangeAttribute(float min, float max)
{
Min = min;
Max = max;
}
}
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System;
using UnityEngine;
namespace Microsoft.MixedReality.Toolkit
{
/// <summary>
/// Base abstract class for all Mixed Reality profile configurations.
/// Extends ScriptableObject and used as a property container to initialize MRTK services.
/// </summary>
[Serializable]
public abstract class BaseMixedRealityProfile : ScriptableObject
{
[SerializeField]
[HideInInspector]
private bool isCustomProfile = true;
internal bool IsCustomProfile => isCustomProfile;
}
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
namespace Microsoft.MixedReality.Toolkit.Boundary
{
/// <summary>
/// Defines different types of boundaries that can be requested.
/// </summary>
public enum BoundaryType
{
/// <summary>
/// A rectangular area calculated as the largest rectangle within the tracked area, good for placing content near the user.
/// </summary>
PlayArea,
/// <summary>
/// The full tracked boundary, typically manually drawn by a user while setting up their device.
/// </summary>
TrackedArea
}
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using UnityEngine;
namespace Microsoft.MixedReality.Toolkit.Boundary
{
/// <summary>
/// The Edge structure defines the points of a line segment that are used to
/// construct a polygonal boundary.
/// </summary>
public struct Edge
{
/// <summary>
/// The first point of the edge line segment.
/// </summary>
public readonly Vector2 PointA;
/// <summary>
/// The second point of the edge line segment.
/// </summary>
public readonly Vector2 PointB;
/// <summary>
/// Initializes the Edge structure.
/// </summary>
/// <param name="pointA">The first point of the line segment.</param>
/// <param name="pointB">The second point of the line segment.</param>
public Edge(Vector2 pointA, Vector2 pointB)
{
PointA = pointA;
PointB = pointB;
}
/// <summary>
/// Initializes the Edge structure.
/// </summary>
/// <param name="pointA">The first point of the line segment.</param>
/// <param name="pointB">The second point of the line segment.</param>
public Edge(Vector3 pointA, Vector3 pointB) :
// Use the X and Z parameters as our edges are height agnostic.
this(new Vector2(pointA.x, pointA.z), new Vector2(pointB.x, pointB.z))
{ }
}
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using Microsoft.MixedReality.Toolkit.Utilities;
using System;
using UnityEngine;
namespace Microsoft.MixedReality.Toolkit.Boundary
{
/// <summary>
/// The InscribedRectangle class defines the largest rectangle within an
/// arbitrary shape.
/// </summary>
public class InscribedRectangle
{
/// <summary>
/// Total number of starting points randomly generated within the boundary.
/// </summary>
private const int randomPointCount = 30;
/// <summary>
/// The total amount of height, in meters, we want to gain with each binary search
/// change before we decide that it's good enough.
/// </summary>
private const float minimumHeightGain = 0.01f;
/// <summary>
/// Angles to use for fitting the rectangle within the boundary.
/// </summary>
private static readonly float[] fitAngles = { 0, 15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165 };
/// <summary>
/// Aspect ratios used when fitting rectangles within the boundary.
/// </summary>
private static float[] aspectRatios = {
1.0f, 1.5f, 2.0f, 2.5f, 3.0f, 3.5f, 4.0f, 4.5f,
5.0f, 5.5f, 6, 6.5f, 7, 7.5f, 8.0f, 8.5f, 9.0f,
9.5f, 10.0f, 10.5f, 11.0f, 11.5f, 12.0f, 12.5f,
13.0f, 13.5f, 14.0f, 14.5f, 15.0f};
/// <summary>
/// The center point of the inscribed rectangle.
/// </summary>
public Vector2 Center { get; private set; } = EdgeUtilities.InvalidPoint;
/// <summary>
/// The width of the inscribed rectangle.
/// </summary>
public float Width { get; private set; } = 0f;
/// <summary>
/// The height of the inscribed rectangle.
/// </summary>
public float Height { get; private set; } = 0f;
/// <summary>
/// The rotation angle, in degrees, of the inscribed rectangle.
/// </summary>
public float Angle { get; private set; } = 0f;
/// <summary>
/// Is the described rectangle valid?
/// </summary>
/// <remarks>
/// A rectangle is considered valid if its center point is valid.
/// </remarks>
public bool IsValid => EdgeUtilities.IsValidPoint(Center);
/// <summary>
/// Finds a large inscribed rectangle. Tries to be maximal but this is
/// best effort. The algorithm used was inspired by the blog post
/// https://d3plus.org/blog/behind-the-scenes/2014/07/08/largest-rect/
/// Random points within the polygon are chosen, and then 2 lines are
/// drawn through those points. The midpoints of those lines are
/// used as the center of various rectangles, using a binary search to
/// vary the size, until the largest fit-able rectangle is found.
/// This is then repeated for predefined angles (0-180 in steps of 15)
/// and aspect ratios (1 to 15 in steps of 0.5).
/// </summary>
/// <param name="geometryEdges">The boundary geometry.</param>
/// <param name="randomSeed">Random number generator seed.</param>
/// <remarks>
/// For the most reproducible results, use the same randomSeed value
/// each time this method is called.
/// </remarks>
public InscribedRectangle(Edge[] geometryEdges, int randomSeed)
{
if (geometryEdges == null || geometryEdges.Length == 0)
{
Debug.LogError("InscribedRectangle requires an array of Edges. You passed in a null or empty array.");
return;
}
// Clear previous rectangle
Center = EdgeUtilities.InvalidPoint;
Width = 0;
Height = 0;
Angle = 0;
float minX = EdgeUtilities.maxWidth;
float minY = EdgeUtilities.maxWidth;
float maxX = -EdgeUtilities.maxWidth;
float maxY = -EdgeUtilities.maxWidth;
// Find min x, min y, max x, max y
for (int i = 0; i < geometryEdges.Length; i++)
{
Edge edge = geometryEdges[i];
if ((edge.PointA.x < minX) || (edge.PointB.x < minX))
{
minX = Mathf.Min(edge.PointA.x, edge.PointB.x);
}
if ((edge.PointA.y < minY) || (edge.PointB.y < minY))
{
minY = Mathf.Min(edge.PointA.y, edge.PointB.y);
}
if ((edge.PointA.x > maxX) || (edge.PointB.x > maxX))
{
maxX = Mathf.Max(edge.PointA.x, edge.PointB.x);
}
if ((edge.PointA.y > maxY) || (edge.PointB.y > maxY))
{
maxY = Mathf.Max(edge.PointA.y, edge.PointB.y);
}
}
// Generate random points until we have randomPointCount starting points
Vector2[] startingPoints = new Vector2[randomPointCount];
{
System.Random random = new System.Random(randomSeed);
for (int i = 0; i < startingPoints.Length; i++)
{
Vector2 candidatePoint;
do
{
candidatePoint.x = ((float)random.NextDouble() * (maxX - minX)) + minX;
candidatePoint.y = ((float)random.NextDouble() * (maxY - minY)) + minY;
}
while (!EdgeUtilities.IsInsideBoundary(geometryEdges, candidatePoint));
startingPoints[i] = candidatePoint;
}
}
for (int angleIndex = 0; angleIndex < fitAngles.Length; angleIndex++)
{
for (int pointIndex = 0; pointIndex < startingPoints.Length; pointIndex++)
{
Vector2 topCollisionPoint;
Vector2 bottomCollisionPoint;
Vector2 leftCollisionPoint;
Vector2 rightCollisionPoint;
float angleRadians = MathUtilities.DegreesToRadians(fitAngles[angleIndex]);
// Find the collision point of a cross through the given point at the given angle.
// Note, we are ignoring the return value as we are checking each point's validity
// individually.
FindSurroundingCollisionPoints(
geometryEdges,
startingPoints[pointIndex],
angleRadians,
out topCollisionPoint,
out bottomCollisionPoint,
out leftCollisionPoint,
out rightCollisionPoint);
float newWidth;
float newHeight;
if (EdgeUtilities.IsValidPoint(topCollisionPoint) && EdgeUtilities.IsValidPoint(bottomCollisionPoint))
{
float aX = topCollisionPoint.x;
float aY = topCollisionPoint.y;
float bX = bottomCollisionPoint.x;
float bY = bottomCollisionPoint.y;
// Calculate the midpoint between the top and bottom collision points.
Vector2 verticalMidpoint = new Vector2((aX + bX) * 0.5f, (aY + bY) * 0.5f);
if (TryFixMaximumRectangle(
geometryEdges,
verticalMidpoint,
angleRadians,
Width * Height,
out newWidth,
out newHeight))
{
Center = verticalMidpoint;
Angle = fitAngles[angleIndex];
Width = newWidth;
Height = newHeight;
}
}
if (EdgeUtilities.IsValidPoint(leftCollisionPoint) && EdgeUtilities.IsValidPoint(rightCollisionPoint))
{
float aX = leftCollisionPoint.x;
float aY = leftCollisionPoint.y;
float bX = rightCollisionPoint.x;
float bY = rightCollisionPoint.y;
// Calculate the midpoint between the left and right collision points.
Vector2 horizontalMidpoint = new Vector2((aX + bX) * 0.5f, (aY + bY) * 0.5f);
if (TryFixMaximumRectangle(
geometryEdges,
horizontalMidpoint,
angleRadians,
Width * Height,
out newWidth,
out newHeight))
{
Center = horizontalMidpoint;
Angle = fitAngles[angleIndex];
Width = newWidth;
Height = newHeight;
}
}
}
}
}
/// <summary>
/// Find points at which there are collisions with the geometry around a given point.
/// </summary>
/// <param name="geometryEdges">The boundary geometry.</param>
/// <param name="point">The point around which collisions will be identified.</param>
/// <param name="angleRadians">The angle, in radians, at which the collision points will be oriented.</param>
/// <param name="topCollisionPoint">Receives the coordinates of the upper collision point.</param>
/// <param name="bottomCollisionPoint">Receives the coordinates of the lower collision point.</param>
/// <param name="leftCollisionPoint">Receives the coordinates of the left collision point.</param>
/// <param name="rightCollisionPoint">Receives the coordinates of the right collision point.</param>
/// <returns>
/// True if all of the required collision points are located, false otherwise.
/// If a point is unable to be found, the appropriate out parameter will be set to <see cref="EdgeUtilities.InvalidPoint"/>.
/// </returns>
private bool FindSurroundingCollisionPoints(
Edge[] geometryEdges,
Vector2 point,
float angleRadians,
out Vector2 topCollisionPoint,
out Vector2 bottomCollisionPoint,
out Vector2 leftCollisionPoint,
out Vector2 rightCollisionPoint)
{
// Initialize out parameters.
topCollisionPoint = EdgeUtilities.InvalidPoint;
bottomCollisionPoint = EdgeUtilities.InvalidPoint;
leftCollisionPoint = EdgeUtilities.InvalidPoint;
rightCollisionPoint = EdgeUtilities.InvalidPoint;
// Check to see if the point is inside the geometry.
if (!EdgeUtilities.IsInsideBoundary(geometryEdges, point))
{
return false;
}
// Define values that are outside of the maximum boundary size.
float largeValue = EdgeUtilities.maxWidth;
float smallValue = -largeValue;
// Find the top and bottom collision points by creating a large line segment that goes through the point to MAX and MIN values on Y
Vector2 topEndpoint = new Vector2(point.x, largeValue);
Vector2 bottomEndpoint = new Vector2(point.x, smallValue);
topEndpoint = RotatePoint(topEndpoint, point, angleRadians);
bottomEndpoint = RotatePoint(bottomEndpoint, point, angleRadians);
Edge verticalLine = new Edge(topEndpoint, bottomEndpoint);
// Find the left and right collision points by creating a large line segment that goes through the point to MAX and Min values on X
Vector2 rightEndpoint = new Vector2(largeValue, point.y);
Vector2 leftEndpoint = new Vector2(smallValue, point.y);
rightEndpoint = RotatePoint(rightEndpoint, point, angleRadians);
leftEndpoint = RotatePoint(leftEndpoint, point, angleRadians);
Edge horizontalLine = new Edge(rightEndpoint, leftEndpoint);
for (int i = 0; i < geometryEdges.Length; i++)
{
// Look for a vertical collision
Vector2 verticalIntersectionPoint = EdgeUtilities.GetIntersectionPoint(geometryEdges[i], verticalLine);
if (EdgeUtilities.IsValidPoint(verticalIntersectionPoint))
{
// Is the intersection above or below the point?
if (RotatePoint(verticalIntersectionPoint, point, -angleRadians).y > point.y)
{
// Update the top collision point
if (!EdgeUtilities.IsValidPoint(topCollisionPoint) ||
(Vector2.SqrMagnitude(point - verticalIntersectionPoint) < Vector2.SqrMagnitude(point - topCollisionPoint)))
{
topCollisionPoint = verticalIntersectionPoint;
}
}
else
{
// Update the bottom collision point
if (!EdgeUtilities.IsValidPoint(bottomCollisionPoint) ||
(Vector2.SqrMagnitude(point - verticalIntersectionPoint) < Vector2.SqrMagnitude(point - bottomCollisionPoint)))
{
bottomCollisionPoint = verticalIntersectionPoint;
}
}
}
// Look for a horizontal collision
Vector2 horizontalIntersection = EdgeUtilities.GetIntersectionPoint(geometryEdges[i], horizontalLine);
if (EdgeUtilities.IsValidPoint(horizontalIntersection))
{
// Is this intersection to the left or the right of the point?
if (RotatePoint(horizontalIntersection, point, -angleRadians).x < point.x)
{
// Update the left collision point
if (!EdgeUtilities.IsValidPoint(leftCollisionPoint) ||
(Vector2.SqrMagnitude(point - horizontalIntersection) < Vector2.SqrMagnitude(point - leftCollisionPoint)))
{
leftCollisionPoint = horizontalIntersection;
}
}
else
{
// Update the right collision point
if (!EdgeUtilities.IsValidPoint(rightCollisionPoint) ||
(Vector2.SqrMagnitude(point - horizontalIntersection) < Vector2.SqrMagnitude(point - rightCollisionPoint)))
{
rightCollisionPoint = horizontalIntersection;
}
}
}
}
// Each corner of the rectangle must intersect with the geometry.
if (!EdgeUtilities.IsValidPoint(topCollisionPoint) ||
!EdgeUtilities.IsValidPoint(bottomCollisionPoint) ||
!EdgeUtilities.IsValidPoint(leftCollisionPoint) ||
!EdgeUtilities.IsValidPoint(rightCollisionPoint))
{
return false;
}
return true;
}
/// <summary>
/// Determine of the provided point lies within the defined rectangle.
/// </summary>
/// <param name="point">The point to check</param>
/// <returns>
/// True if the point is within the rectangle's bounds, false otherwise.
/// </returns>
/// <exception cref="System.InvalidOperationException">The rectangle is not valid.</exception>
public bool IsInsideBoundary(Vector2 point)
{
if (!IsValid)
{
throw new InvalidOperationException("A point cannot be within an invalid rectangle.");
}
point -= Center;
point = RotatePoint(point, Vector2.zero, MathUtilities.DegreesToRadians(-Angle));
bool inWidth = Mathf.Abs(point.x) <= (Width * 0.5f);
bool inHeight = Mathf.Abs(point.y) <= (Height * 0.5f);
return (inWidth && inHeight);
}
/// <summary>
/// Rotate a two dimensional point about another point by the specified angle.
/// </summary>
/// <param name="point">The point to be rotated.</param>
/// <param name="origin">The point about which the rotation is to occur.</param>
/// <param name="angleRadians">The angle for the rotation, in radians</param>
/// <returns>
/// The coordinates of the rotated point.
/// </returns>
private Vector2 RotatePoint(Vector2 point, Vector2 origin, float angleRadians)
{
if (angleRadians.Equals(0f))
{
return point;
}
Vector2 rotated = point;
// Translate to origin of rotation
rotated.x -= origin.x;
rotated.y -= origin.y;
// Rotate the point
float sin = Mathf.Sin(angleRadians);
float cos = Mathf.Cos(angleRadians);
float x = rotated.x * cos - rotated.y * sin;
float y = rotated.x * sin + rotated.y * cos;
// Translate back and return
rotated.x = x + origin.x;
rotated.y = y + origin.y;
return rotated;
}
/// <summary>
/// Check to see if a rectangle centered at the specified point and oriented at
/// the specified angle will fit within the geometry.
/// </summary>
/// <param name="geometryEdges">The boundary geometry.</param>
/// <param name="centerPoint">The center point of the rectangle.</param>
/// <param name="angleRadians">The orientation, in radians, of the rectangle.</param>
/// <param name="width">The width of the rectangle.</param>
/// <param name="height">The height of the rectangle.</param>
private bool CheckRectangleFit(
Edge[] geometryEdges,
Vector2 centerPoint,
float angleRadians,
float width,
float height)
{
float halfWidth = width * 0.5f;
float halfHeight = height * 0.5f;
// Calculate the rectangle corners.
Vector2 topLeft = new Vector2(centerPoint.x - halfWidth, centerPoint.y + halfHeight);
Vector2 topRight = new Vector2(centerPoint.x + halfWidth, centerPoint.y + halfHeight);
Vector2 bottomLeft = new Vector2(centerPoint.x - halfWidth, centerPoint.y - halfHeight);
Vector2 bottomRight = new Vector2(centerPoint.x + halfWidth, centerPoint.y - halfHeight);
// Rotate the rectangle.
topLeft = RotatePoint(topLeft, centerPoint, angleRadians);
topRight = RotatePoint(topRight, centerPoint, angleRadians);
bottomLeft = RotatePoint(bottomLeft, centerPoint, angleRadians);
bottomRight = RotatePoint(bottomRight, centerPoint, angleRadians);
// Get the rectangle edges.
Edge topEdge = new Edge(topLeft, topRight);
Edge rightEdge = new Edge(topRight, bottomRight);
Edge bottomEdge = new Edge(bottomLeft, bottomRight);
Edge leftEdge = new Edge(topLeft, bottomLeft);
// Check for collisions with the boundary geometry. If any of our edges collide,
// the rectangle will not fit within the playspace.
for (int i = 0; i < geometryEdges.Length; i++)
{
if (EdgeUtilities.IsValidPoint(EdgeUtilities.GetIntersectionPoint(geometryEdges[i], topEdge)) ||
EdgeUtilities.IsValidPoint(EdgeUtilities.GetIntersectionPoint(geometryEdges[i], rightEdge)) ||
EdgeUtilities.IsValidPoint(EdgeUtilities.GetIntersectionPoint(geometryEdges[i], bottomEdge)) ||
EdgeUtilities.IsValidPoint(EdgeUtilities.GetIntersectionPoint(geometryEdges[i], leftEdge)))
{
return false;
}
}
// No collisions found with the rectangle. Success!
return true;
}
/// <summary>
/// Attempt to fit the largest rectangle possible within the geometry.
/// </summary>
/// <param name="geometryEdges">The boundary geometry.</param>
/// <param name="centerPoint">The center point for the rectangle.</param>
/// <param name="angleRadians">The rotation, in radians, of the rectangle.</param>
/// <param name="minArea">The smallest allowed area.</param>
/// <param name="width">Returns the width of the rectangle.</param>
/// <param name="height">Returns the height of the rectangle.</param>
/// <returns>
/// True if a rectangle with an area greater than or equal to minArea was able to be fit
/// within the geometry at centerPoint.
/// </returns>
private bool TryFixMaximumRectangle(
Edge[] geometryEdges,
Vector2 centerPoint,
float angleRadians,
float minArea,
out float width,
out float height)
{
width = 0.0f;
height = 0.0f;
Vector2 topCollisionPoint;
Vector2 bottomCollisionPoint;
Vector2 leftCollisionPoint;
Vector2 rightCollisionPoint;
// Find the collision points with the geometry
if (!FindSurroundingCollisionPoints(geometryEdges, centerPoint, angleRadians,
out topCollisionPoint, out bottomCollisionPoint, out leftCollisionPoint, out rightCollisionPoint))
{
return false;
}
// Start by calculating max width and height by ray-casting a cross from the point at the given angle
// and taking the shortest leg of each ray. Width is the longest.
float verticalMinDistanceToEdge = Mathf.Min(
Vector2.Distance(centerPoint, topCollisionPoint),
Vector2.Distance(centerPoint, bottomCollisionPoint));
float horizontalMinDistanceToEdge = Mathf.Min(
Vector2.Distance(centerPoint, leftCollisionPoint),
Vector2.Distance(centerPoint, rightCollisionPoint));
// Width is the largest of the possible dimensions
float maxWidth = Math.Max(verticalMinDistanceToEdge, horizontalMinDistanceToEdge) * 2.0f;
float maxHeight = Math.Min(verticalMinDistanceToEdge, horizontalMinDistanceToEdge) * 2.0f;
float aspectRatio = 0.0f;
// For each aspect ratio we do a binary search to find the maximum rectangle that fits,
// though once we start increasing our area by minimumHeightGain we call it good enough.
for (int i = 0; i < aspectRatios.Length; i++)
{
// The height is limited by the width. If a height would make our width exceed maxWidth, it can't be used
float searchHeightUpperBound = Mathf.Max(maxHeight, maxWidth / aspectRatios[i]);
// Set to the min height that will out perform our previous area at the given aspect ratio. This is 0 the first time.
// Derived from biggestAreaSoFar=height*(height*aspectRatio)
float searchHeightLowerBound = Mathf.Sqrt(Mathf.Max((width * height), minArea) / aspectRatios[i]);
// If the lowest value needed to outperform the previous best is greater than our max,
// this aspect ratio can't outperform what we've already calculated.
if ((searchHeightLowerBound > searchHeightUpperBound) ||
(searchHeightLowerBound * aspectRatios[i] > maxWidth))
{
continue;
}
float currentTestingHeight = Mathf.Max(searchHeightLowerBound, maxHeight * 0.5f);
// Perform the binary search until continuing to search will not give us a significant win.
do
{
if (CheckRectangleFit(geometryEdges,
centerPoint,
angleRadians,
aspectRatios[i] * currentTestingHeight,
currentTestingHeight))
{
// Binary search up-ward
// If the rectangle will fit, increase the lower bounds of our binary search
searchHeightLowerBound = currentTestingHeight;
width = currentTestingHeight * aspectRatios[i];
height = currentTestingHeight;
aspectRatio = aspectRatios[i];
currentTestingHeight = (searchHeightUpperBound + currentTestingHeight) * 0.5f;
}
else
{
// If the rectangle won't fit, update our upper bound and lower our binary search
searchHeightUpperBound = currentTestingHeight;
currentTestingHeight = (currentTestingHeight + searchHeightLowerBound) * 0.5f;
}
}
while ((searchHeightUpperBound - searchHeightLowerBound) > minimumHeightGain);
}
return (aspectRatio > 0.0f);
}
}
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using Microsoft.MixedReality.Toolkit.Utilities;
using UnityEngine;
using Microsoft.MixedReality.Toolkit.Physics;
namespace Microsoft.MixedReality.Toolkit.Boundary
{
/// <summary>
/// Configuration profile settings for setting up boundary visualizations.
/// </summary>
[CreateAssetMenu(menuName = "Mixed Reality Toolkit/Profiles/Mixed Reality Boundary Visualization Profile", fileName = "MixedRealityBoundaryVisualizationProfile", order = (int)CreateProfileMenuItemIndices.BoundaryVisualization)]
[MixedRealityServiceProfile(typeof(IMixedRealityBoundarySystem))]
[HelpURL("https://microsoft.github.io/MixedRealityToolkit-Unity/Documentation/Boundary/BoundarySystemGettingStarted.html")]
public class MixedRealityBoundaryVisualizationProfile : BaseMixedRealityProfile
{
[SerializeField]
[Tooltip("The approximate height of the play space, in meters.")]
private float boundaryHeight = 3.0f;
/// <summary>
/// The developer defined height of the boundary, in meters.
/// </summary>
/// <remarks>
/// The BoundaryHeight property is used to create a three dimensional volume for the play space.
/// </remarks>
public float BoundaryHeight => boundaryHeight;
#region Floor settings
[SerializeField]
[Tooltip("Should the floor be displayed in the scene?")]
private bool showFloor = true;
/// <summary>
/// Should the boundary system display the floor?
/// </summary>
public bool ShowFloor => showFloor;
// todo: consider allowing optional custom prefab
[SerializeField]
[Tooltip("The material to use when displaying the floor.")]
private Material floorMaterial = null;
/// <summary>
/// The material to use for the floor <see href="https://docs.unity3d.com/ScriptReference/GameObject.html">GameObject</see> when created by the boundary system.
/// </summary>
public Material FloorMaterial => floorMaterial;
[PhysicsLayer]
[SerializeField]
[Tooltip("The physics layer to assign to the generated floor.")]
private int floorPhysicsLayer = 0;
/// <summary>
/// The physics layer to assign to the generated floor.
/// </summary>
public int FloorPhysicsLayer => floorPhysicsLayer;
[SerializeField]
[Tooltip("The dimensions of the floor, in meters.")]
private Vector2 floorScale = new Vector2(10f, 10f);
/// <summary>
/// The size at which to display the rectangular floor plane <see href="https://docs.unity3d.com/ScriptReference/GameObject.html">GameObject</see>.
/// </summary>
public Vector2 FloorScale => floorScale;
#endregion Floor settings
#region Play area settings
[SerializeField]
[Tooltip("Should the play area be displayed in the scene?")]
private bool showPlayArea = true;
/// <summary>
/// Should the boundary system display the play area?
/// </summary>
public bool ShowPlayArea => showPlayArea;
[SerializeField]
[Tooltip("The material to use when displaying the play area.")]
private Material playAreaMaterial = null;
/// <summary>
/// The material to use for the rectangular play area <see href="https://docs.unity3d.com/ScriptReference/GameObject.html">GameObject</see>.
/// </summary>
public Material PlayAreaMaterial => playAreaMaterial;
[PhysicsLayer]
[SerializeField]
[Tooltip("The physics layer to assign to the generated play area.")]
private int playAreaPhysicsLayer = 2;
/// <summary>
/// The physics layer to assign to the generated play area.
/// </summary>
public int PlayAreaPhysicsLayer => playAreaPhysicsLayer;
#endregion Play area settings
#region Tracked area settings
[SerializeField]
[Tooltip("Should the tracked area be displayed in the scene?")]
private bool showTrackedArea = true;
/// <summary>
/// Should the boundary system display the tracked area?
/// </summary>
public bool ShowTrackedArea => showTrackedArea;
[SerializeField]
[Tooltip("The material to use when displaying the tracked area.")]
private Material trackedAreaMaterial = null;
/// <summary>
/// The material to use for the boundary geometry <see href="https://docs.unity3d.com/ScriptReference/GameObject.html">GameObject</see>.
/// </summary>
public Material TrackedAreaMaterial => trackedAreaMaterial;
[PhysicsLayer]
[SerializeField]
[Tooltip("The physics layer to assign to the generated tracked area.")]
private int trackedAreaPhysicsLayer = 2;
/// <summary>
/// The physics layer to assign to the generated tracked area.
/// </summary>
public int TrackedAreaPhysicsLayer => trackedAreaPhysicsLayer;
#endregion Tracked area settings
#region Boundary wall settings
[SerializeField]
[Tooltip("Should the boundary walls be displayed in the scene?")]
private bool showBoundaryWalls = false;
/// <summary>
/// Should the boundary system display the boundary geometry walls?
/// </summary>
public bool ShowBoundaryWalls => showBoundaryWalls;
[SerializeField]
[Tooltip("The material to use when displaying the boundary walls.")]
private Material boundaryWallMaterial = null;
/// <summary>
/// The material to use for displaying the boundary geometry walls.
/// </summary>
public Material BoundaryWallMaterial => boundaryWallMaterial;
[PhysicsLayer]
[SerializeField]
[Tooltip("The physics layer to assign to the generated boundary walls.")]
private int boundaryWallsPhysicsLayer = 2;
/// <summary>
/// The physics layer to assign to the generated boundary walls.
/// </summary>
public int BoundaryWallsPhysicsLayer => boundaryWallsPhysicsLayer;
#endregion Boundary wall settings
#region Boundary ceiling settings
[SerializeField]
[Tooltip("Should the boundary ceiling be displayed in the scene?")]
private bool showBoundaryCeiling = false;
/// <summary>
/// Should the boundary system display the boundary ceiling?
/// </summary>
public bool ShowBoundaryCeiling => showBoundaryCeiling;
[SerializeField]
[Tooltip("The material to use when displaying the boundary ceiling.")]
private Material boundaryCeilingMaterial = null;
/// <summary>
/// The material to use for displaying the boundary ceiling.
/// </summary>
public Material BoundaryCeilingMaterial => boundaryCeilingMaterial;
[PhysicsLayer]
[SerializeField]
[Tooltip("The physics layer to assign to the generated boundary ceiling.")]
private int ceilingPhysicsLayer = 2;
/// <summary>
/// The physics layer to assign to the generated boundary ceiling.
/// </summary>
public int CeilingPhysicsLayer => ceilingPhysicsLayer;
#endregion Boundary ceiling settings
}
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System;
namespace Microsoft.MixedReality.Toolkit.CameraSystem
{
/// <summary>
/// Base class used to derive custom camera settings profiles.
/// </summary>
[Serializable]
public class BaseCameraSettingsProfile : BaseMixedRealityProfile
{
// This class is intentionally blank. It exists for future expansion of common functionality.
}
}
\ No newline at end of file
// Copyright (c) Microsoft Corporation.
// Copyright(c) 2019 Takahiro Miyaura
// Licensed under the MIT License.
namespace Microsoft.MixedReality.Toolkit.CameraSystem
{
/// <summary>
/// The type of displays on which an application may run.
/// </summary>
public enum DisplayType
{
/// <summary>
/// The display is opaque. Devices on the digital reality (ex: VR) side of the Mixed Reality
/// spectrum generally have opaque displays.
/// </summary>
Opaque = 0,
/// <summary>
/// The display is transparent. Devices on the physical reality (ex: Microsoft HoloLens) side
/// of the Mixed Reality spectrum generally have transparent displays.
/// </summary>
Transparent
}
}
\ No newline at end of file
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using Microsoft.MixedReality.Toolkit.CameraSystem;
using Microsoft.MixedReality.Toolkit.Utilities;
using System;
using UnityEngine;
using UnityEngine.Serialization;
namespace Microsoft.MixedReality.Toolkit
{
/// <summary>
/// This Scriptable Object tells you if your head mounted display (HMD)
/// is a transparent device or an occluded device.
/// Based on those values, you can customize your camera and quality settings.
/// </summary>
[CreateAssetMenu(menuName = "Mixed Reality Toolkit/Profiles/Mixed Reality Camera Profile", fileName = "MixedRealityCameraProfile", order = (int)CreateProfileMenuItemIndices.Camera)]
[MixedRealityServiceProfile(typeof(IMixedRealityCameraSystem))]
[HelpURL("https://microsoft.github.io/MixedRealityToolkit-Unity/Documentation/MixedRealityConfigurationGuide.html#camera")]
public class MixedRealityCameraProfile : BaseMixedRealityProfile
{
[SerializeField]
[Tooltip("Configuration objects describing the registered settings providers.")]
private MixedRealityCameraSettingsConfiguration[] settingsConfigurations = new MixedRealityCameraSettingsConfiguration[0];
/// <summary>
/// Configuration objects describing the registered settings providers.
/// </summary>
public MixedRealityCameraSettingsConfiguration[] SettingsConfigurations
{
get { return settingsConfigurations; }
internal set { settingsConfigurations = value; }
}
[SerializeField]
[Tooltip("Near clipping plane distance for an opaque display.")]
private float nearClipPlaneOpaqueDisplay = 0.1f;
/// <summary>
/// Near clipping plane distance for an opaque display.
/// </summary>
public float NearClipPlaneOpaqueDisplay => nearClipPlaneOpaqueDisplay;
[SerializeField]
[Tooltip("Far clipping plane distance for an opaque display.")]
private float farClipPlaneOpaqueDisplay = 1000f;
/// <summary>
/// Far clipping plane distance for an opaque display.
/// </summary>
public float FarClipPlaneOpaqueDisplay => farClipPlaneOpaqueDisplay;
[SerializeField]
[Tooltip("Flags describing how to clear the camera for an opaque display.")]
private CameraClearFlags cameraClearFlagsOpaqueDisplay = CameraClearFlags.Skybox;
/// <summary>
/// Flags describing how to clear the camera for an opaque display.
/// </summary>
public CameraClearFlags CameraClearFlagsOpaqueDisplay => cameraClearFlagsOpaqueDisplay;
[SerializeField]
[Tooltip("Background color for an opaque display.")]
private Color backgroundColorOpaqueDisplay = Color.black;
/// <summary>
/// Background color for an opaque display.
/// </summary>
public Color BackgroundColorOpaqueDisplay => backgroundColorOpaqueDisplay;
[SerializeField]
[Tooltip("Quality level for an opaque display.")]
private int opaqueQualityLevel = 0;
/// <summary>
/// Quality level for an opaque display.
/// </summary>
public int OpaqueQualityLevel => opaqueQualityLevel;
[SerializeField]
[Tooltip("Near clipping plane distance for a transparent display.")]
private float nearClipPlaneTransparentDisplay = 0.85f;
/// <summary>
/// Near clipping plane distance for a transparent display.
/// </summary>
public float NearClipPlaneTransparentDisplay => nearClipPlaneTransparentDisplay;
[SerializeField]
[Tooltip("Far clipping plane distance for a transparent display.")]
private float farClipPlaneTransparentDisplay = 50f;
/// <summary>
/// Far clipping plane distance for a transparent display.
/// </summary>
public float FarClipPlaneTransparentDisplay => farClipPlaneTransparentDisplay;
[SerializeField]
[Tooltip("Flags describing how to clear the camera for a transparent display.")]
private CameraClearFlags cameraClearFlagsTransparentDisplay = CameraClearFlags.SolidColor;
/// <summary>
/// Flags describing how to clear the camera for a transparent display.
/// </summary>
public CameraClearFlags CameraClearFlagsTransparentDisplay => cameraClearFlagsTransparentDisplay;
[SerializeField]
[Tooltip("Background color for a transparent display.")]
private Color backgroundColorTransparentDisplay = Color.clear;
/// <summary>
/// Background color for a transparent display.
/// </summary>
public Color BackgroundColorTransparentDisplay => backgroundColorTransparentDisplay;
[SerializeField]
[Tooltip("Quality level for a transparent display.")]
[FormerlySerializedAs("holoLensQualityLevel")]
private int transparentQualityLevel = 0;
/// <summary>
/// Quality level for a transparent display.
/// </summary>
public int TransparentQualityLevel => transparentQualityLevel;
#region Obsolete properties
/// <summary>
/// Quality level for a HoloLens device.
/// </summary>
/// <remarks>
/// HoloLensQualityLevel is obsolete and will be removed in a future Mixed Reality Toolkit release. Please use TransparentQualityLevel.
/// </remarks>
[Obsolete("HoloLensQualityLevel is obsolete and will be removed in a future Mixed Reality Toolkit release. Please use TransparentQualityLevel.")]
public int HoloLensQualityLevel => transparentQualityLevel;
#endregion Obsolete properties
}
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using Microsoft.MixedReality.Toolkit.Utilities;
using System;
using UnityEngine;
namespace Microsoft.MixedReality.Toolkit.CameraSystem
{
/// <summary>
/// Defines the configuration for a camera settings provider.
/// </summary>
[Serializable]
public struct MixedRealityCameraSettingsConfiguration : IMixedRealityServiceConfiguration
{
[SerializeField]
[Tooltip("The concrete type of the camera settings provider.")]
[Implements(typeof(IMixedRealityCameraSettingsProvider), TypeGrouping.ByNamespaceFlat)]
private SystemType componentType;
/// <inheritdoc />
public SystemType ComponentType => componentType;
[SerializeField]
[Tooltip("The name of the camera settings provider.")]
private string componentName;
/// <inheritdoc />
public string ComponentName => componentName;
[SerializeField]
[Tooltip("The camera settings provider priority.")]
private uint priority;
/// <inheritdoc />
public uint Priority => priority;
[SerializeField]
[Tooltip("The platform(s) on which the camera settings provider is supported.")]
[EnumFlags]
private SupportedPlatforms runtimePlatform;
/// <inheritdoc />
public SupportedPlatforms RuntimePlatform => runtimePlatform;
[SerializeField]
private BaseCameraSettingsProfile settingsProfile;
/// <inheritdoc />
public BaseMixedRealityProfile Profile => settingsProfile;
/// <summary>
/// Camera settings specific configuration profile.
/// </summary>
public BaseCameraSettingsProfile SettingsProfile => settingsProfile;
/// <summary>
/// Constructor.
/// </summary>
/// <param name="componentType">The <see cref="Microsoft.MixedReality.Toolkit.Utilities.SystemType"/> of the provider.</param>
/// <param name="componentName">The friendly name of the provider.</param>
/// <param name="priority">The load priority of the provider.</param>
/// <param name="runtimePlatform">The runtime platform(s) supported by the provider.</param>
/// <param name="settingsProfile">The configuration profile for the provider.</param>
public MixedRealityCameraSettingsConfiguration(
SystemType componentType,
string componentName,
uint priority,
SupportedPlatforms runtimePlatform,
BaseCameraSettingsProfile configurationProfile)
{
this.componentType = componentType;
this.componentName = componentName;
this.priority = priority;
this.runtimePlatform = runtimePlatform;
this.settingsProfile = configurationProfile;
}
}
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#if UNITY_EDITOR
using Microsoft.MixedReality.Toolkit.Utilities;
using Microsoft.MixedReality.Toolkit.Utilities.Editor;
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
#endif
namespace Microsoft.MixedReality.Toolkit.Input
{
/// <summary>
/// Helper utility to manage all the required Axis configuration for platforms, where required
/// </summary>
public static class ControllerMappingLibrary
{
#region Constants
/// <summary>
/// Axis for movement along the up (gravity) vector.
/// </summary>
public const string UP_DOWN = "UpDown";
/// <summary>
/// Mouse: Position Horizontal Movement<para/>
/// HTC Vive Controller: Left Controller Trackpad (2) Horizontal Movement<para/>
/// Oculus Touch Controller: Axis2D.PrimaryThumbstick Horizontal Movement<para/>
/// Valve Knuckles Controller: Left Controller Trackpad Horizontal Movement<para/>
/// Windows Mixed Reality Motion Controller: Left Thumbstick Horizontal Movement<para/>
/// Xbox Controller: Left Thumbstick Horizontal Movement<para/>
/// </summary>
public const string AXIS_1 = "AXIS_1";
/// <summary>
/// Mouse: Position Vertical Movement<para/>
/// HTC Vive Controller: Left Controller Trackpad (2) Vertical Movement<para/>
/// Oculus Touch Controller: Axis2D.PrimaryThumbstick Vertical Movement<para/>
/// Valve Knuckles Controller: Left Controller Trackpad Vertical Movement<para/>
/// Windows Mixed Reality Motion Controller: Left Thumbstick Vertical Movement<para/>
/// Xbox Controller: Left Thumbstick Vertical Movement<para/>
/// </summary>
public const string AXIS_2 = "AXIS_2";
/// <summary>
/// Mouse: Scroll<para/>
/// Xbox Controller: Shared Trigger<para/>
/// </summary>
public const string AXIS_3 = "AXIS_3";
/// <summary>
/// HTC Vive Controller: Right Controller Trackpad (2) Horizontal Movement<para/>
/// Oculus Touch Controller: Axis2D.SecondaryThumbstick Horizontal Movement<para/>
/// Valve Knuckles Controller: Right Controller Trackpad Horizontal Movement<para/>
/// Windows Mixed Reality Motion Controller: Right Thumbstick Horizontal Movement<para/>
/// Xbox Controller: Right Thumbstick Vertical Movement<para/>
/// </summary>
public const string AXIS_4 = "AXIS_4";
/// <summary>
/// HTC Vive Controller: Right Controller Trackpad (2) Vertical Movement<para/>
/// Oculus Touch Controller: Axis2D.SecondaryThumbstick Vertical Movement<para/>
/// Valve Knuckles Controller: Right Controller Trackpad Vertical Movement<para/>
/// Windows Mixed Reality Motion Controller: Right Thumbstick Vertical Movement<para/>
/// Xbox Controller: Right Thumbstick Vertical Movement<para/>
/// </summary>
public const string AXIS_5 = "AXIS_5";
/// <summary>
/// None
/// </summary>
public const string AXIS_6 = "AXIS_6";
/// <summary>
/// Xbox Controller: D-Pad Horizontal<para/>
/// </summary>
public const string AXIS_7 = "AXIS_7";
/// <summary>
/// Xbox Controller: D-Pad Vertical<para/>
/// </summary>
public const string AXIS_8 = "AXIS_8";
/// <summary>
/// HTC Vive Controller: Left Controller Trigger (7) Squeeze<para/>
/// Oculus Touch Controller: Axis1D.PrimaryIndexTrigger Squeeze<para/>
/// Valve Knuckles Controller: Left Controller Trigger Squeeze<para/>
/// Windows Mixed Reality Motion Controller: Left Trigger Squeeze<para/>
/// </summary>
public const string AXIS_9 = "AXIS_9";
/// <summary>
/// HTC Vive Controller: Right Controller Trigger (7) Squeeze<para/>
/// Oculus Touch Controller: Axis1D.SecondaryIndexTrigger Movement Squeeze<para/>
/// Valve Knuckles Controller: Right Controller Trigger Squeeze<para/>
/// Windows Mixed Reality Motion Controller: Right Trigger Squeeze<para/>
/// </summary>
public const string AXIS_10 = "AXIS_10";
/// <summary>
/// HTC Vive Controller: Left Controller Grip Button (8) Squeeze<para/>
/// Oculus Touch Controller: Axis1D.PrimaryHandTrigger Squeeze<para/>
/// Valve Knuckles Controller: Left Controller Grip Average Squeeze<para/>
/// Windows Mixed Reality Motion Controller: Left Grip Squeeze<para/>
/// </summary>
public const string AXIS_11 = "AXIS_11";
/// <summary>
/// HTC Vive Controller: Right Controller Grip Button (8) Squeeze<para/>
/// Oculus Touch Controller: Axis1D.SecondaryHandTrigger Squeeze<para/>
/// Valve Knuckles Controller: Right Controller Grip Average Squeeze<para/>
/// Windows Mixed Reality Motion Controller: Right Grip Squeeze<para/>
/// </summary>
public const string AXIS_12 = "AXIS_12";
/// <summary>
/// Oculus Touch Controller: Axis1D.PrimaryIndexTrigger Near Touch<para/>
/// </summary>
public const string AXIS_13 = "AXIS_13";
/// <summary>
/// Oculus Touch Controller: Axis1D.SecondaryIndexTrigger Near Touch<para/>
/// </summary>
public const string AXIS_14 = "AXIS_14";
/// <summary>
/// Oculus Touch Controller: Touch.PrimaryThumbRest Near Touch<para/>
/// </summary>
public const string AXIS_15 = "AXIS_15";
/// <summary>
/// Oculus Touch Controller: Button.SecondaryThumbstick Near Touch<para/>
/// </summary>
public const string AXIS_16 = "AXIS_16";
/// <summary>
/// Windows Mixed Reality Motion Controller: Left Touchpad Horizontal Movement<para/>
/// </summary>
public const string AXIS_17 = "AXIS_17";
/// <summary>
/// Windows Mixed Reality Motion Controller: Left Touchpad Vertical Movement<para/>
/// </summary>
public const string AXIS_18 = "AXIS_18";
/// <summary>
/// Windows Mixed Reality Motion Controller: Right Touchpad Horizontal Movement<para/>
/// </summary>
public const string AXIS_19 = "AXIS_19";
/// <summary>
/// Windows Mixed Reality Motion Controller: Right Touchpad Vertical Movement<para/>
/// Valve Knuckles Controller: Left Controller Index Finger Cap Sensor<para/>
/// </summary>
public const string AXIS_20 = "AXIS_20";
/// <summary>
/// Valve Knuckles Controller: Right Controller Index Finger Cap Sensor<para/>
/// </summary>
public const string AXIS_21 = "AXIS_21";
/// <summary>
/// Valve Knuckles Controller: Left Controller Middle Finger Cap Sensor<para/>
/// </summary>
public const string AXIS_22 = "AXIS_22";
/// <summary>
/// Valve Knuckles Controller: Right Controller Middle Finger Cap Sensor<para/>
/// </summary>
public const string AXIS_23 = "AXIS_23";
/// <summary>
/// Valve Knuckles Controller: Left Controller Ring Finger Cap Sensor<para/>
/// </summary>
public const string AXIS_24 = "AXIS_24";
/// <summary>
/// Valve Knuckles Controller: Right Controller Ring Finger Cap Sensor<para/>
/// </summary>
public const string AXIS_25 = "AXIS_25";
/// <summary>
/// Valve Knuckles Controller: Left Controller Pinky Finger Cap Sensor<para/>
/// </summary>
public const string AXIS_26 = "AXIS_26";
/// <summary>
/// Valve Knuckles Controller: Right Controller Pinky Finger Cap Sensor<para/>
/// </summary>
public const string AXIS_27 = "AXIS_27";
public const string AXIS_28 = "AXIS_28";
#endregion Constants
#if UNITY_EDITOR
#region InputAxisConfig
// Default value for the dead zone. This should match the default used by Unity for the pre-created Horizontal and Vertical axes.
public const float defaultDeadZone = 0.19f;
/// <summary>
/// Get the InputManagerAxis data needed to configure the Input Mappings for a controller
/// </summary>
public static InputManagerAxis[] UnityInputManagerAxes => new[]
{
new InputManagerAxis { Name = AXIS_1, Dead = defaultDeadZone, Sensitivity = 1, Invert = false, Type = InputManagerAxisType.JoystickAxis, Axis = 1 },
new InputManagerAxis { Name = AXIS_2, Dead = defaultDeadZone, Sensitivity = 1, Invert = false, Type = InputManagerAxisType.JoystickAxis, Axis = 2 },
new InputManagerAxis { Name = AXIS_3, Dead = defaultDeadZone, Sensitivity = 1, Invert = false, Type = InputManagerAxisType.JoystickAxis, Axis = 3 },
new InputManagerAxis { Name = AXIS_4, Dead = defaultDeadZone, Sensitivity = 1, Invert = false, Type = InputManagerAxisType.JoystickAxis, Axis = 4 },
new InputManagerAxis { Name = AXIS_5, Dead = defaultDeadZone, Sensitivity = 1, Invert = false, Type = InputManagerAxisType.JoystickAxis, Axis = 5 },
new InputManagerAxis { Name = AXIS_6, Dead = defaultDeadZone, Sensitivity = 1, Invert = false, Type = InputManagerAxisType.JoystickAxis, Axis = 6 },
new InputManagerAxis { Name = AXIS_7, Dead = defaultDeadZone, Sensitivity = 1, Invert = false, Type = InputManagerAxisType.JoystickAxis, Axis = 7 },
new InputManagerAxis { Name = AXIS_8, Dead = defaultDeadZone, Sensitivity = 1, Invert = false, Type = InputManagerAxisType.JoystickAxis, Axis = 8 },
new InputManagerAxis { Name = AXIS_9, Dead = defaultDeadZone, Sensitivity = 1, Invert = false, Type = InputManagerAxisType.JoystickAxis, Axis = 9 },
new InputManagerAxis { Name = AXIS_10, Dead = defaultDeadZone, Sensitivity = 1, Invert = false, Type = InputManagerAxisType.JoystickAxis, Axis = 10 },
new InputManagerAxis { Name = AXIS_11, Dead = defaultDeadZone, Sensitivity = 1, Invert = false, Type = InputManagerAxisType.JoystickAxis, Axis = 11 },
new InputManagerAxis { Name = AXIS_12, Dead = defaultDeadZone, Sensitivity = 1, Invert = false, Type = InputManagerAxisType.JoystickAxis, Axis = 12 },
new InputManagerAxis { Name = AXIS_13, Dead = defaultDeadZone, Sensitivity = 1, Invert = false, Type = InputManagerAxisType.JoystickAxis, Axis = 13 },
new InputManagerAxis { Name = AXIS_14, Dead = defaultDeadZone, Sensitivity = 1, Invert = false, Type = InputManagerAxisType.JoystickAxis, Axis = 14 },
new InputManagerAxis { Name = AXIS_15, Dead = defaultDeadZone, Sensitivity = 1, Invert = false, Type = InputManagerAxisType.JoystickAxis, Axis = 15 },
new InputManagerAxis { Name = AXIS_16, Dead = defaultDeadZone, Sensitivity = 1, Invert = false, Type = InputManagerAxisType.JoystickAxis, Axis = 16 },
new InputManagerAxis { Name = AXIS_17, Dead = defaultDeadZone, Sensitivity = 1, Invert = false, Type = InputManagerAxisType.JoystickAxis, Axis = 17 },
new InputManagerAxis { Name = AXIS_18, Dead = defaultDeadZone, Sensitivity = 1, Invert = false, Type = InputManagerAxisType.JoystickAxis, Axis = 18 },
new InputManagerAxis { Name = AXIS_19, Dead = defaultDeadZone, Sensitivity = 1, Invert = false, Type = InputManagerAxisType.JoystickAxis, Axis = 19 },
new InputManagerAxis { Name = AXIS_20, Dead = defaultDeadZone, Sensitivity = 1, Invert = false, Type = InputManagerAxisType.JoystickAxis, Axis = 20 },
new InputManagerAxis { Name = AXIS_21, Dead = defaultDeadZone, Sensitivity = 1, Invert = false, Type = InputManagerAxisType.JoystickAxis, Axis = 21 },
new InputManagerAxis { Name = AXIS_22, Dead = defaultDeadZone, Sensitivity = 1, Invert = false, Type = InputManagerAxisType.JoystickAxis, Axis = 22 },
new InputManagerAxis { Name = AXIS_23, Dead = defaultDeadZone, Sensitivity = 1, Invert = false, Type = InputManagerAxisType.JoystickAxis, Axis = 23 },
new InputManagerAxis { Name = AXIS_24, Dead = defaultDeadZone, Sensitivity = 1, Invert = false, Type = InputManagerAxisType.JoystickAxis, Axis = 24 },
new InputManagerAxis { Name = AXIS_25, Dead = defaultDeadZone, Sensitivity = 1, Invert = false, Type = InputManagerAxisType.JoystickAxis, Axis = 25 },
new InputManagerAxis { Name = AXIS_26, Dead = defaultDeadZone, Sensitivity = 1, Invert = false, Type = InputManagerAxisType.JoystickAxis, Axis = 26 },
new InputManagerAxis { Name = AXIS_27, Dead = defaultDeadZone, Sensitivity = 1, Invert = false, Type = InputManagerAxisType.JoystickAxis, Axis = 27 },
new InputManagerAxis { Name = AXIS_28, Dead = defaultDeadZone, Sensitivity = 1, Invert = false, Type = InputManagerAxisType.JoystickAxis, Axis = 28 },
new InputManagerAxis { Name = UP_DOWN, Gravity = 3, Dead = 0.001f, Sensitivity = 3, Snap = true, Invert = false, Type = InputManagerAxisType.KeyOrMouseButton, PositiveButton = "e", NegativeButton = "q" },
new InputManagerAxis { Name = UP_DOWN, Dead = defaultDeadZone, Sensitivity = 1, Invert = false, Type = InputManagerAxisType.JoystickAxis, Axis = 3 },
};
#endregion InputAxisConfig
private static Dictionary<Tuple<Type, Handedness, string>, Texture2D> cachedTextures = new Dictionary<Tuple<Type, Handedness, string>, Texture2D>();
public static Texture2D GetControllerTexture(Type controllerType, Handedness handedness)
{
return GetControllerTextureCached(controllerType, handedness, "");
}
public static Texture2D GetControllerTextureScaled(Type controllerType, Handedness handedness)
{
return GetControllerTextureCached(controllerType, handedness, "_scaled");
}
private static Texture2D GetControllerTextureCached(Type controllerType, Handedness handedness, string suffix)
{
Texture2D texture;
var key = new Tuple<Type, Handedness, string>(controllerType, handedness, suffix);
if (cachedTextures.TryGetValue(key, out texture))
{
return texture;
}
texture = GetControllerTextureInternal(controllerType, handedness, suffix);
cachedTextures.Add(key, texture);
return texture;
}
private static Texture2D GetControllerTextureInternal(Type controllerType, Handedness handedness, string suffix)
{
if (controllerType != null)
{
var attr = MixedRealityControllerAttribute.Find(controllerType);
if (attr != null)
{
if (attr.TexturePath.Length > 0)
{
Texture2D texture = GetControllerTextureInternal(attr.TexturePath, handedness, suffix);
if (texture != null)
{
return texture;
}
}
}
}
return GetControllerTextureInternal("Textures/Generic_controller", Handedness.None, suffix);
}
private static Texture2D GetControllerTextureInternal(string relativeTexturePath, Handedness handedness, string suffix)
{
string handednessSuffix = string.Empty;
if (handedness == Handedness.Left)
{
handednessSuffix = "_left";
}
else if (handedness == Handedness.Right)
{
handednessSuffix = "_right";
}
string themeSuffix = EditorGUIUtility.isProSkin ? "_white" : "_black";
string fullTexturePath = MixedRealityToolkitFiles.MapRelativeFilePath(MixedRealityToolkitModuleType.StandardAssets, $"{relativeTexturePath}{handednessSuffix}{themeSuffix}{suffix}.png");
return (Texture2D)AssetDatabase.LoadAssetAtPath(fullTexturePath, typeof(Texture2D));
}
#endif // UNITY_EDITOR
}
}
\ No newline at end of file
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
namespace Microsoft.MixedReality.Toolkit.Input
{
// TODO - Expand input list for additional controller types and have a filter defined by the controller
/// <summary>
/// The InputType defines the types of input exposed by a controller.
/// Denoting the available buttons / interactions that a controller supports.
/// </summary>
public enum DeviceInputType
{
None = 0,
Gaze,
Voice,
/// <summary>
/// 6 Dof Pointer with position and rotation.
/// </summary>
SpatialPointer,
/// <summary>
/// 3 Dof Pointer with only position.
/// </summary>
PointerPosition,
/// <summary>
/// 3 Dof Pointer with only rotation.
/// </summary>
PointerRotation,
PointerClick,
ButtonPress,
ButtonTouch,
ButtonNearTouch,
Trigger,
TriggerTouch,
TriggerNearTouch,
// TriggerPress, in some cases, maps to the Grab gesture.
TriggerPress,
/// <summary>
/// 6 DoF Grip with position and rotation.
/// </summary>
SpatialGrip,
/// <summary>
/// 3 DoF Grip with only position.
/// </summary>
GripPosition,
/// <summary>
/// 3 Dof Grip with only rotation.
/// </summary>
GripRotation,
ThumbStick,
ThumbStickPress,
ThumbStickTouch,
ThumbStickNearTouch,
Touchpad,
TouchpadTouch,
TouchpadNearTouch,
TouchpadPress,
/// <summary>
/// Select maps to the Pinch/Air Tap gesture
/// </summary>
Select,
Start,
Menu,
Hand,
Thumb,
ThumbTouch,
ThumbNearTouch,
ThumbPress,
IndexFinger,
IndexFingerTouch,
IndexFingerNearTouch,
IndexFingerPress,
MiddleFinger,
MiddleFingerTouch,
MiddleFingerNearTouch,
MiddleFingerPress,
RingFinger,
RingFingerTouch,
RingFingerNearTouch,
RingFingerPress,
PinkyFinger,
PinkyFingerTouch,
PinkyFingerNearTouch,
PinkyFingerPress,
DirectionalPad,
Scroll,
PrimaryButtonPress,
PrimaryButtonTouch,
PrimaryButtonNearTouch,
SecondaryButtonPress,
SecondaryButtonTouch,
SecondaryButtonNearTouch,
Grip,
GripTouch,
GripNearTouch,
// GripPress, in some cases, maps to the Grab gesture.
GripPress,
}
}
\ No newline at end of file
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
namespace Microsoft.MixedReality.Toolkit.Input
{
/// <summary>
/// The GestureInputType defines the types of gestures exposed by a controller.
/// </summary>
public enum GestureInputType
{
None = 0,
Hold,
Navigation,
Manipulation,
Select
}
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using UnityEngine;
namespace Microsoft.MixedReality.Toolkit.Input
{
// TODO - currently not used, consider removing maybe?
/// <summary>
/// The headset definition defines the headset as defined by the SDK / Unity.
/// </summary>
public struct Headset
{
/// <summary>
/// The ID assigned to the Headset
/// </summary>
public string Id { get; set; }
/// <summary>
/// The designated hand that the controller is managing, as defined by the SDK / Unity.
/// </summary>
public SDKType HeadsetSDKType { get; set; }
/// <summary>
/// Indicates whether or not the headset is currently providing position data.
/// </summary>
public bool IsPositionAvailable { get; set; }
/// <summary>
/// Outputs the current position of the headset, as defined by the SDK / Unity.
/// </summary>
public Vector3 Position { get; set; }
/// <summary>
/// Indicates whether or not the headset is currently providing rotation data.
/// </summary>
public bool IsRotationAvailable { get; set; }
/// <summary>
/// Outputs the current rotation of the headset, as defined by the SDK / Unity.
/// </summary>
public Quaternion Rotation { get; set; }
/// <summary>
/// Outputs the current state of the headset, whether it is tracked or not. As defined by the SDK / Unity.
/// </summary>
public TrackingState TrackingState { get; set; }
/// <summary>
/// Indicates whether or not the headset display is opaque. As defined by the SDK / Unity.
/// </summary>
public bool IsOpaque { get; set; }
}
}
\ No newline at end of file
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
namespace Microsoft.MixedReality.Toolkit.Input
{
/// <summary>
/// The InputSourceType defines the types of input sources.
/// </summary>
public enum InputSourceType
{
Other = 0,
Hand,
Controller,
Voice,
Head,
Eyes
}
}
\ No newline at end of file
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
namespace Microsoft.MixedReality.Toolkit.Input
{
/// <summary>
/// Flags used by MixedRealityControllerAttribute.
/// </summary>
[System.Flags]
public enum MixedRealityControllerConfigurationFlags : byte
{
/// <summary>
/// Controllers with custom interaction mappings can have their mappings be added / removed to the
/// controller mapping profile in the property inspector.
/// </summary>
UseCustomInteractionMappings = 1 << 0,
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment