-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAutoAdaptResolution
More file actions
220 lines (195 loc) · 9.1 KB
/
AutoAdaptResolution
File metadata and controls
220 lines (195 loc) · 9.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
using System;
using GameLogic;
using UnityEngine;
namespace GameLogic
{
public static class AutoAdaptResolution
{
public static float matchWidthOrHeight = 0;
public static float viewAnchorX = 0;
public static float viewAnchorY = 0;
public static float viewAnchorYMin = 0;
public static float viewAnchorYMax = 1;
public static float viewAnchorYMin_IgnoreSafeArea = 0;
public static float viewAnchorYMax_IgnoreSafeArea = 1;
public static void InitAdaptUI()
{
float screenFixWidth=AdaptUISetting.screenFixWidth;
float screenMinHeight=AdaptUISetting.screenMinHeight;
float screenMaxHeight = AdaptUISetting.screenMaxHeight_UI;
float screenWidth = UnityEngine.Device.Screen.width;
float screenHeight = UnityEngine.Device.Screen.height;
float screenRatio = screenHeight / screenWidth;
float baseRatio = screenMinHeight / screenFixWidth;
float maxRatio = screenMaxHeight / screenFixWidth;
float safeAreaRatio = UnityEngine.Device.Screen.safeArea.height / UnityEngine.Device.Screen.safeArea.width;
matchWidthOrHeight = safeAreaRatio > baseRatio ? 0 : 1;
UpdateXAnchor(safeAreaRatio, baseRatio);
UpdateYAnchor(screenRatio, maxRatio);
//为了微信小程序,上面最少留70,下面最少留0,暂时不用考虑微信小游戏,就设置0
float minAppBottomBar = 0;
float minAppTopBar = 0;
var heightWithBar = screenMaxHeight + minAppBottomBar + minAppTopBar;
var screenRatioWithBar = heightWithBar / screenFixWidth;
if (safeAreaRatio > screenRatioWithBar) //安全区域比例比最高分设计比+上下刘海大,这时候上下已经保证了刘海,只要把区域限制在最高分设计比例就行
{
var maxHeight = screenWidth * maxRatio;
var emptyHeight = screenHeight - maxHeight;
var halfOffset = emptyHeight / screenHeight * 0.5f;
viewAnchorYMin = halfOffset;
viewAnchorYMax = 1 - halfOffset;
}
else
{
UpdateBySafeArea( baseRatio, screenRatio, minAppTopBar, minAppBottomBar);
}
UpdateAnchorWithoutSafeArea(baseRatio,screenRatio,screenRatioWithBar,screenWidth,maxRatio,screenHeight);
}
private static void UpdateAnchorWithoutSafeArea(float baseRatio,float screenRatio,float screenRatioWithBar,float screenWidth,float maxRatio,float screenHeight )
{
if (screenRatio > screenRatioWithBar)
{
var maxHeight = screenWidth * maxRatio;
var emptyHeight = screenHeight - maxHeight;
var halfOffset = emptyHeight / screenHeight * 0.5f;
viewAnchorYMin_IgnoreSafeArea = halfOffset;
viewAnchorYMax_IgnoreSafeArea = 1 - halfOffset;
}
else
{
UpdateBySafeArea( baseRatio, screenRatio, 0, 0);
}
}
private static void UpdateBySafeArea( float baseRatio, float screenRatio,
float minAppTopBar, float minAppBottomBar)
{
Rect safeArea = UnityEngine.Screen.safeArea;
float screenWidth = UnityEngine.Device.Screen.width;
float screenHeight = UnityEngine.Device.Screen.height;
var minY = safeArea.yMin;
var maxY = safeArea.yMax;
if (TryIgnoreTopAdaptByCutout())
{
//真机实验备注: 经实验,cutout的数据只有当挖孔的区域是在上面的时候才会有数据,如果是在左右或者在下面,就没有数据
maxY = screenHeight;
Debug.Log("IgnoreTopAdaptByCutout---");
}
float safeAreaRatio = safeArea.height / screenWidth;
if (safeAreaRatio > baseRatio)
{
float flexibleRatio = screenRatio - baseRatio;
var topRatio = minAppTopBar / screenHeight;
//尽量保留,不够空间就不留
if (flexibleRatio > topRatio)
{
maxY = Mathf.Min(maxY, screenHeight - minAppTopBar);
flexibleRatio -= topRatio;
}
var bottomRatio = minAppBottomBar / screenHeight;
if (flexibleRatio > bottomRatio)
{
minY = Mathf.Max(minY, minAppBottomBar);
}
}
else
{
//屏幕比例比标准的还小,左右会留黑边,这时候不做最少留90,下面最少留50的限制
}
viewAnchorYMin = minY / screenHeight;
viewAnchorYMax = maxY / screenHeight;
}
/// <summary>
/// 如果挖孔区域在左右摄像机范围外,就不用管上面的安全区域
/// </summary>
/// <returns></returns>
static bool TryIgnoreTopAdaptByCutout()
{
if(viewAnchorX <= 0) //左右没有给摄像机留空间,就不能用挖孔区域来判断
{
return false;
}
var cutouts = UnityEngine.Device.Screen.cutouts;
if(cutouts == null || cutouts.Length == 0)//没有挖孔区域,就不能用挖孔区域来判断
{
return false;
}
//如果挖孔区域在左右摄像机范围外,就不用管上面的安全区域
bool cutoutInCameraRange = false;
var screenWidth = UnityEngine.Device.Screen.width;
float cameraMinX = viewAnchorX * screenWidth;
float cameraMaxX = (1- viewAnchorX) * screenWidth;
foreach (var cutout in cutouts)
{
var notInRange =cutout.xMax < cameraMinX || cutout.xMin > cameraMaxX;
Debug.Log("viewAnchorX"+viewAnchorX+" not in range "+notInRange+" xMax"+cutout.xMax+" xMin"+cutout.xMin+" cameraMinX"+cameraMinX+" cameraMaxX"+cameraMaxX);
if (notInRange==false)
{
cutoutInCameraRange = true;
break;
}
}
return cutoutInCameraRange==false;
}
private static void UpdateXAnchor(float screenRatio, float baseRatio)
{
if (screenRatio < baseRatio)
{
viewAnchorX = (baseRatio - screenRatio) / baseRatio / 2;
}
}
private static void UpdateYAnchor(float screenRatio, float maxRatio)
{
if (screenRatio > maxRatio)
{
viewAnchorY = (screenRatio-maxRatio ) / screenRatio / 2;
}
}
public static void SetupCanvasRoot(RectTransform rootTransform,bool ignoreBottom=false)
{
rootTransform.anchorMin = new Vector2(viewAnchorX, ignoreBottom?viewAnchorYMin_IgnoreSafeArea:viewAnchorYMin);
rootTransform.anchorMax = new Vector2(1 - viewAnchorX, viewAnchorYMax);
}
public static void SetupCanvasRootWithoutSafeArea(RectTransform rootTransform)
{
rootTransform.anchorMin = new Vector2(viewAnchorX, viewAnchorYMin_IgnoreSafeArea);
rootTransform.anchorMax = new Vector2(1 - viewAnchorX, viewAnchorYMax_IgnoreSafeArea);
}
public static void AdaptSceneCamera(Camera targetCamera)
{
if (targetCamera == null)
{
return;
}
float defaultRatio = AdaptUISetting.screenMaxHeight_Scene / AdaptUISetting.screenFixWidth;
float maxUIRatio = AdaptUISetting.screenMaxHeight_Scene / AdaptUISetting.screenFixWidth;
float minRatio = AdaptUISetting.screenMinHeight / AdaptUISetting.screenFixWidth;
float screenWidth = UnityEngine.Device.Screen.width;
float screenHeight = UnityEngine.Device.Screen.height;
float screenRatio = screenHeight / screenWidth;
float fovRatio = 1;
if (screenRatio < maxUIRatio)
{
screenRatio = Math.Max(screenRatio, minRatio);
fovRatio = defaultRatio / screenRatio;
}
else
{
fovRatio = defaultRatio / maxUIRatio;
}
var defaultFov = targetCamera.fieldOfView;
float finalFov = defaultFov / fovRatio;
targetCamera.fieldOfView = finalFov;
targetCamera.rect = new Rect(viewAnchorX, viewAnchorY, 1 - viewAnchorX * 2, 1-viewAnchorY*2);
}
private const float ShowModelProportion = 750 / 1500f;
/// <summary>
/// 检测是否是长屏,目前宽高比小于0.5就是长屏
/// </summary>
/// <returns></returns>
public static bool CheckIsHeightView(Canvas canvas)
{
var rect = canvas.gameObject.GetComponent<RectTransform>();
return rect.rect.width / rect.rect.height <= ShowModelProportion;
}
}
}