Skip to content

Commit d6ce1a0

Browse files
committed
Code cleanup
1 parent 96b7c1e commit d6ce1a0

File tree

9 files changed

+156
-62
lines changed

9 files changed

+156
-62
lines changed

Assets/Samples/RebindingUI/OnScreen/AreaShape.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,10 @@ public enum AreaShape
99
/// A rectangular clipping area is used (default).
1010
/// </summary>
1111
Rectangle = 0,
12+
13+
/// <summary>
14+
/// A ellipse shaped (or circular) clipping area is used.
15+
/// </summary>
16+
Ellipse = 1,
1217
}
1318
}

Assets/Samples/RebindingUI/OnScreen/CustomOnScreenControl.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,8 @@ private void OnGestureEvent(in GestureEvent gestureEvent)
278278
if (gestureEvent.flags.HasFlag(GestureEvent.Flags.PhaseStart) ||
279279
gestureEvent.flags.HasFlag(GestureEvent.Flags.PhaseChange))
280280
{
281-
var deltaMillimeters = UnitConverter.PixelsToMillimeters(gestureEvent.delta);
281+
var deltaMillimeters = gestureEvent.delta * UnitConverter.PixelsToMillimetersConversionFactor(
282+
UnitConverter.EffectivePixelDensity(Screen.dpi));
282283
var stickRadius = Vector2.ClampMagnitude(deltaMillimeters, m_StickRadiusMillimeters);
283284
value = stickRadius / m_StickRadiusMillimeters;
284285

Assets/Samples/RebindingUI/OnScreen/Detector.cs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,31 +14,39 @@ protected Detector(int maxTouches)
1414
Reset(Rect.zero, AreaShape.Rectangle, null);
1515
}
1616

17-
public virtual void Reset(Rect bounds, AreaShape shape, Detector.GestureEventHandler handler)
17+
public virtual void Reset(Rect bounds, AreaShape shape, GestureEventHandler handler)
1818
{
1919
m_Handler = handler;
2020
m_Bounds = bounds;
21+
m_Shape = shape;
2122
m_GestureFlags = GestureEvent.Flags.None;
2223
m_Count = 0;
2324
}
2425

2526
protected bool Contains(in TouchState touch)
2627
{
28+
// TODO Consider transforming touch into normalized instead? E.g. touch / renderingSize
29+
30+
var display = Display.displays[touch.displayIndex];
31+
var absoluteBounds = new Rect(
32+
x: m_Bounds.xMin * display.renderingWidth,
33+
y: m_Bounds.yMin * display.renderingHeight,
34+
width: m_Bounds.width * display.renderingWidth,
35+
height: m_Bounds.height * display.renderingHeight);
36+
2737
switch (m_Shape)
2838
{
2939
case AreaShape.Rectangle:
3040
{
31-
// TODO Caching opportunities here
32-
var display = Display.displays[touch.displayIndex];
33-
var width = display.renderingWidth;
34-
var height = display.renderingHeight;
35-
var absoluteBounds = new Rect(
36-
x: m_Bounds.xMin * width,
37-
y: m_Bounds.yMin * height,
38-
width: m_Bounds.width * width,
39-
height: m_Bounds.height * height);
4041
return absoluteBounds.Contains(touch.position);
4142
}
43+
case AreaShape.Ellipse:
44+
{
45+
var delta = touch.position - absoluteBounds.center;
46+
var radius = absoluteBounds.size / 2;
47+
var value = (delta.x * delta.x) / (radius.x * radius.x) + (delta.y * delta.y) / (radius.y * radius.y);
48+
return value <= 1f;
49+
}
4250
}
4351

4452
return false;

Assets/Samples/RebindingUI/OnScreen/ITouchProcessor.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
namespace UnityEngine.InputSystem.Samples.RebindUI
44
{
5+
/// <summary>
6+
/// Interface for a processor of touch events.
7+
/// </summary>
58
internal interface ITouchProcessor
69
{
710
void OnTouchBegin(Detector context, in TouchState[] touches, int count, int index);

Assets/Samples/RebindingUI/OnScreen/OnScreenControlUI.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
public class OnScreenControlUI : MonoBehaviour
1414
{
1515
public Canvas canvas;
16-
public Camera camera;
16+
public new Camera camera;
1717
public CustomOnScreenControl control;
1818
public RectTransform area;
1919
public RectTransform bounds;
@@ -82,7 +82,8 @@ void Update()
8282
return;
8383

8484
var normalizedBounds = control.bounds;
85-
var stickRadiusPixels = UnitConverter.MillimetersToPixels(control.stickRadiusMillimeters);
85+
var stickRadiusPixels = control.stickRadiusMillimeters * UnitConverter.MillimetersToPixelsConversionFactor(
86+
UnitConverter.EffectivePixelDensity(Screen.dpi));
8687
var stickCenter = control.stickCenter;
8788
var stickViewport = camera.ScreenToViewportPoint(new Vector2(stickRadiusPixels, stickRadiusPixels));
8889
var stickRect = new Rect(
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
using Unity.Android.Gradle.Manifest;
2+
3+
namespace UnityEngine.InputSystem.Samples.RebindUI
4+
{
5+
/// <summary>
6+
/// Defines a 2D rect transform suitable for device-specific bounds.
7+
/// </summary>
8+
/// <remarks>
9+
/// This is useful to anchor interactive regions based on physical aspects of a device, in
10+
/// particular touchscreen. When designing on-screen-controls, you want e.g. an on screen stick
11+
/// to stay consistent in size across devices. This mimics the behavior of a physical device
12+
/// where the mechanical offset of a gamepad stick wouldn't change depending on the screen size
13+
/// or resolution. This is relevant since our physical ability as humans is limited to our limbs, e.g.
14+
/// our number of fingers and their reaching length is fixed.
15+
///
16+
/// When using a UI framework to visualize on-screen controls, you likely want to combine screen-based (pixels)
17+
/// and physical layout (millimeters or inches).
18+
/// </remarks>
19+
public struct PhysicalBounds
20+
{
21+
/// <summary>
22+
/// Evaluates whether this transform bounding rectangle contains the associated viewport coordinate.
23+
/// </summary>
24+
/// <param name="point">Viewport coordinate (normalized).</param>
25+
/// <returns>true if bounds contains point, else false.</returns>
26+
public bool ContainsViewportPoint(Vector2 point)
27+
{
28+
return ContainsPhysicalPoint(new Vector2(point.x * rect.width, point.y * rect.height));
29+
}
30+
31+
/// <summary>
32+
/// Evaluates whether this transform bounding rectangle contains the associated screen point.
33+
/// </summary>
34+
/// <param name="screenPoint">Screen point.</param>
35+
/// <param name="pixelsPerInch">Pixels-per-inch (PPI) pixel density of the associated display.</param>
36+
/// <remarks>Due to limited support for multiple displays, this may return incorrect results
37+
/// since it will use DPI (rather PPI) reported by Screen and not individual displays.</remarks>
38+
/// <returns>true if bounds contains point, else false.</returns>
39+
public bool ContainsScreenPoint(Vector2 screenPoint, float pixelsPerInch)
40+
{
41+
return ContainsPhysicalPoint(screenPoint * UnitConverter.PixelsToMillimetersConversionFactor(pixelsPerInch));
42+
}
43+
44+
/// <summary>
45+
/// Returns whether this transform bounding rectangle contains the associated physical point.
46+
/// </summary>
47+
/// <param name="point">Physical space point in millimeters.</param>
48+
/// <returns></returns>
49+
public bool ContainsPhysicalPoint(Vector2 point)
50+
{
51+
switch (shape)
52+
{
53+
case AreaShape.Rectangle:
54+
return rect.Contains(point);
55+
case AreaShape.Ellipse:
56+
{
57+
var delta = point - rect.center;
58+
var radius = rect.size / 2;
59+
var value = (delta.x * delta.x) / (radius.x * radius.x) +
60+
(delta.y * delta.y) / (radius.y * radius.y);
61+
return value <= 1f;
62+
}
63+
default:
64+
return false;
65+
}
66+
}
67+
68+
/// <summary>
69+
/// A bounding rectangle in millimeters.
70+
/// </summary>
71+
[SerializeField]
72+
private Rect rect;
73+
74+
/// <summary>
75+
/// The axis-aligned clipping shape.
76+
/// </summary>
77+
[SerializeField]
78+
private AreaShape shape;
79+
}
80+
}

Assets/Samples/RebindingUI/OnScreen/PhysicalBounds.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 33 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,50 @@
1+
using System;
2+
13
namespace UnityEngine.InputSystem.Samples.RebindUI
24
{
5+
/// <summary>
6+
/// Conversion utility class for physical coordinate transforms.
7+
/// </summary>
38
internal static class UnitConverter
49
{
5-
private const float kMillimetersPerInch = 25.4f;
6-
private const string kWarningMessage = "Screen.dpi not available, assuming 96 DPI.";
7-
8-
private static float EffectivePpi(float ppi) => ppi <= 0.0f ? 96.0f : ppi;
9-
private static float PixelsToMillimetersFactor(float ppi) => kMillimetersPerInch / EffectivePpi(ppi);
10-
private static float MillimetersToPixelsFactor(float ppi) => EffectivePpi(ppi) / kMillimetersPerInch;
11-
12-
#region PixelsToMillimeters
13-
14-
public static float PixelsToMillimeters(float pixels, float ppi) => pixels * PixelsToMillimetersFactor(ppi);
15-
16-
public static float PixelsToMillimeters(float millimeters) => PixelsToMillimeters(millimeters, Screen.dpi);
17-
1810
/// <summary>
19-
/// Converts a pixel size to millimeters, based on Screen.dpi.
11+
/// Conversion factor for millimeters per inch.
2012
/// </summary>
21-
/// <remarks>Screen.dpi may not be available on some platforms. In such cases, 96 DPI is assumed.</remarks>
22-
public static Vector2 PixelsToMillimeters(Vector2 pixels) => PixelsToMillimeters(pixels, Screen.dpi);
23-
13+
/// <example>
14+
/// var millimeters = 10.0f;
15+
/// Debug.Log($"{millimeters} mm is equal to {millimeters / MillimetersPerInch} inches.");
16+
/// </example>
17+
public const float MillimetersPerInch = 25.4f;
2418

2519
/// <summary>
26-
/// Converts a size in pixels to millimeters based on the given PPI (Pixels-per-inch).
20+
/// Returns a conversion factor for converting pixels to millimeters using the given pixel density.
2721
/// </summary>
28-
/// <param name="pixels">The size in pixels (screen-space).</param>
29-
/// <param name="ppi">Pixels-per-inch (PPI). If this is zero or negative DefaultPixelsPerInch will be used.</param>
30-
/// <returns></returns>
31-
public static Vector2 PixelsToMillimeters(Vector2 pixels, float ppi) => pixels * PixelsToMillimetersFactor(ppi);
32-
33-
#endregion
34-
35-
#region MillimetersToPixels
36-
37-
public static float MillimetersToPixels(float millimeters, float ppi) => millimeters * MillimetersToPixelsFactor(ppi);
38-
39-
public static float MillimetersToPixels(float millimeters) => MillimetersToPixels(millimeters, Screen.dpi);
22+
/// <param name="ppi">Pixel density expressed as pixels-per-inch (PPI).</param>
23+
/// <returns>Conversion ratio for converting pixels to millimeters.</returns>
24+
public static float PixelsToMillimetersConversionFactor(float ppi)
25+
{
26+
if (ppi <= 0.0f)
27+
throw new ArgumentOutOfRangeException($"Invalid pixel density: {ppi}");
28+
return MillimetersPerInch / ppi;
29+
}
4030

4131
/// <summary>
42-
/// Converts a size in millimeters to pixels based on the given PPI (Pixels-per-inch).
32+
/// Returns a conversion factor for converting millimeters to pixels using the given pixel density.
4333
/// </summary>
44-
/// <param name="millimeters">The size in millimeters</param>
45-
/// <param name="ppi">Pixels-per-inch (PPI). If this is zero or negative kDefaultPixelsPerInch will be used.</param>
46-
/// <returns>Size expressed in pixels.</returns>
47-
public static Vector2 MillimetersToPixels(Vector2 millimeters, float ppi) => millimeters * MillimetersToPixelsFactor(ppi);
34+
/// <param name="ppi">Pixel density expressed as pixels-per-inch (PPI).</param>
35+
/// <returns>Conversion ratio for converting millimeters to pixels.</returns>
36+
public static float MillimetersToPixelsConversionFactor(float ppi)
37+
{
38+
if (ppi <= 0.0f)
39+
throw new ArgumentOutOfRangeException($"Invalid pixel density: {ppi}");
40+
return ppi / MillimetersPerInch;
41+
}
4842

4943
/// <summary>
50-
/// Converts a size in millimeters to pixels, based on Screen.dpi.
44+
/// Given a pixel density, returns the same pixel density (if positive), or returns a fallback PPI of 96.
5145
/// </summary>
52-
/// <remarks>Screen.dpi may not be available on some platforms. In such cases, 96 DPI is assumed.</remarks>
53-
public static Vector2 MillimetersToPixels(Vector2 millimeters) => MillimetersToPixels(millimeters, Screen.dpi);
54-
55-
#endregion
46+
/// <param name="ppi">The candidate pixel density expressed as pixels-per-inch (PPI).</param>
47+
/// <returns>Returns <paramref name="ppi"/> if positive, otherwise 96 PPI.</returns>
48+
public static float EffectivePixelDensity(float ppi) => ppi <= 0.0f ? 96.0f : ppi;
5649
}
5750
}

Assets/Samples/RebindingUI/RebindingUISampleScene.unity

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1087,11 +1087,11 @@ MonoBehaviour:
10871087
m_Script: {fileID: 11500000, guid: 5514b68a2410f4ab8a2e19c8b963b6f3, type: 3}
10881088
m_Name:
10891089
m_EditorClassIdentifier: Unity.InputSystem.RebindingUI::UnityEngine.InputSystem.Samples.RebindUI.CustomOnScreenControl
1090-
m_Shape: 0
1090+
m_Shape: 1
10911091
m_NormalizedBounds:
10921092
serializedVersion: 2
10931093
x: 0.86
1094-
y: 0.2
1094+
y: 0.3
10951095
width: 0.15
10961096
height: 0.25
10971097
m_ControlPath: <Gamepad>/buttonEast
@@ -2166,7 +2166,7 @@ GameObject:
21662166
m_Icon: {fileID: 0}
21672167
m_NavMeshLayer: 0
21682168
m_StaticEditorFlags: 0
2169-
m_IsActive: 0
2169+
m_IsActive: 1
21702170
--- !u!224 &585912951
21712171
RectTransform:
21722172
m_ObjectHideFlags: 0
@@ -4209,7 +4209,7 @@ GameObject:
42094209
m_Icon: {fileID: 0}
42104210
m_NavMeshLayer: 0
42114211
m_StaticEditorFlags: 0
4212-
m_IsActive: 0
4212+
m_IsActive: 1
42134213
--- !u!224 &901700405
42144214
RectTransform:
42154215
m_ObjectHideFlags: 0
@@ -4226,8 +4226,8 @@ RectTransform:
42264226
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
42274227
m_AnchorMin: {x: 0.5, y: 0.5}
42284228
m_AnchorMax: {x: 0.5, y: 0.5}
4229-
m_AnchoredPosition: {x: 712.44666, y: -132.47499}
4230-
m_SizeDelta: {x: 245.6712, y: 189.24997}
4229+
m_AnchoredPosition: {x: 712.44666, y: -56.774994}
4230+
m_SizeDelta: {x: 245.6712, y: 189.25}
42314231
m_Pivot: {x: 0.5, y: 0.5}
42324232
--- !u!114 &901700406
42334233
MonoBehaviour:
@@ -4874,7 +4874,7 @@ GameObject:
48744874
m_Icon: {fileID: 0}
48754875
m_NavMeshLayer: 0
48764876
m_StaticEditorFlags: 0
4877-
m_IsActive: 0
4877+
m_IsActive: 1
48784878
--- !u!224 &1053028838
48794879
RectTransform:
48804880
m_ObjectHideFlags: 0
@@ -5066,8 +5066,8 @@ RectTransform:
50665066
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
50675067
m_AnchorMin: {x: 0.5, y: 0.5}
50685068
m_AnchorMax: {x: 0.5, y: 0.5}
5069-
m_AnchoredPosition: {x: 712.44666, y: -132.47502}
5070-
m_SizeDelta: {x: 153.08221, y: 153.0823}
5069+
m_AnchoredPosition: {x: 712.44666, y: -56.774963}
5070+
m_SizeDelta: {x: 153.08221, y: 153.08237}
50715071
m_Pivot: {x: 0.5, y: 0.5}
50725072
--- !u!114 &1090088430
50735073
MonoBehaviour:

0 commit comments

Comments
 (0)