您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

322 行
7.8 KiB

  1. using System;
  2. using UnityEngine;
  3. using UnityEngine.EventSystems;
  4. namespace CIG
  5. {
  6. [RequireComponent(typeof(Canvas))]
  7. [ExecuteInEditMode]
  8. [AddComponentMenu("Layout/CIG Canvas Scaler", 101)]
  9. public class CIGCanvasScaler : UIBehaviour
  10. {
  11. protected override void Awake()
  12. {
  13. base.Awake();
  14. if (this._canvas == null)
  15. {
  16. this._canvas = base.GetComponent<Canvas>();
  17. }
  18. }
  19. protected override void Start()
  20. {
  21. base.Start();
  22. this._currentDPI = Screen.dpi;
  23. }
  24. protected override void OnEnable()
  25. {
  26. base.OnEnable();
  27. this.Handle();
  28. }
  29. protected override void OnDisable()
  30. {
  31. this.SetScaleFactor(1f);
  32. this.SetReferencePixelsPerUnit(100f);
  33. base.OnDisable();
  34. }
  35. private void Update()
  36. {
  37. this.Handle();
  38. }
  39. public CIGCanvasScaler.ScaleMode UIScaleMode
  40. {
  41. get
  42. {
  43. return this._uiScaleMode;
  44. }
  45. set
  46. {
  47. this._uiScaleMode = value;
  48. }
  49. }
  50. public float ReferencePixelsPerUnit
  51. {
  52. get
  53. {
  54. return this._referencePixelsPerUnit;
  55. }
  56. set
  57. {
  58. this._referencePixelsPerUnit = value;
  59. }
  60. }
  61. public Vector2 ReferenceResolution
  62. {
  63. get
  64. {
  65. return this._referenceResolution;
  66. }
  67. set
  68. {
  69. this._referenceResolution = value;
  70. }
  71. }
  72. public float MatchWidthOrHeight
  73. {
  74. get
  75. {
  76. return this._matchWidthOrHeight;
  77. }
  78. set
  79. {
  80. this._matchWidthOrHeight = value;
  81. }
  82. }
  83. public float ReferenceDPI
  84. {
  85. get
  86. {
  87. return this._referenceDPI;
  88. }
  89. set
  90. {
  91. this._referenceDPI = value;
  92. }
  93. }
  94. public float ScaleFactor
  95. {
  96. get
  97. {
  98. return this._scaleFactor;
  99. }
  100. set
  101. {
  102. this._scaleFactor = value;
  103. }
  104. }
  105. public float LargeScreenMatchWidthOrHeight
  106. {
  107. get
  108. {
  109. return this._largeScreenMatchWidthOrHeight;
  110. }
  111. set
  112. {
  113. this._largeScreenMatchWidthOrHeight = value;
  114. }
  115. }
  116. public float LargeScreenThresholdInches
  117. {
  118. get
  119. {
  120. return this._largeScreenThresholdInches;
  121. }
  122. set
  123. {
  124. this._largeScreenThresholdInches = value;
  125. }
  126. }
  127. public float MinimumCanvasScale
  128. {
  129. get
  130. {
  131. return this._minimumCanvasScale;
  132. }
  133. set
  134. {
  135. this._minimumCanvasScale = value;
  136. }
  137. }
  138. public float LargeScreenDampeningFactor
  139. {
  140. get
  141. {
  142. return this._largeScreenDampeningFactor;
  143. }
  144. set
  145. {
  146. this._largeScreenDampeningFactor = value;
  147. }
  148. }
  149. private void Handle()
  150. {
  151. if (this._canvas == null || !this._canvas.isRootCanvas || this._canvas.renderMode == RenderMode.WorldSpace)
  152. {
  153. return;
  154. }
  155. CIGCanvasScaler.ScaleMode uiScaleMode = this._uiScaleMode;
  156. switch (uiScaleMode)
  157. {
  158. case CIGCanvasScaler.ScaleMode.ConstantPixelSize:
  159. this.HandleConstantPixelSize();
  160. break;
  161. case CIGCanvasScaler.ScaleMode.ScaleWithScreenSize:
  162. this.HandleScaleWithScreenSize();
  163. break;
  164. case CIGCanvasScaler.ScaleMode.ConstantPhysicalSize:
  165. this.HandleConstantPhysicalSize();
  166. break;
  167. default:
  168. if (uiScaleMode == CIGCanvasScaler.ScaleMode.ScaleWithDPIScreenSize)
  169. {
  170. this.HandleScaleWithDPIScreenSize();
  171. }
  172. break;
  173. }
  174. }
  175. private void HandleConstantPixelSize()
  176. {
  177. this.SetScaleFactor(this._scaleFactor);
  178. this.SetReferencePixelsPerUnit(this._referencePixelsPerUnit);
  179. }
  180. private void HandleScaleWithScreenSize()
  181. {
  182. float scaleFactor = this.CalculateScreenSizeScaleFactor();
  183. this.SetScaleFactor(scaleFactor);
  184. this.SetReferencePixelsPerUnit(this._referencePixelsPerUnit);
  185. }
  186. private float CalculateScreenSizeScaleFactor()
  187. {
  188. Vector2 vector = new Vector2((float)Screen.width, (float)Screen.height);
  189. float a = Mathf.Log(vector.x / this._referenceResolution.x, 2f);
  190. float b = Mathf.Log(vector.y / this._referenceResolution.y, 2f);
  191. float p = Mathf.Lerp(a, b, this._matchWidthOrHeight);
  192. return Mathf.Pow(2f, p);
  193. }
  194. private void HandleConstantPhysicalSize()
  195. {
  196. float num = (this._currentDPI > 0f) ? this._currentDPI : this._referenceDPI;
  197. float scaleFactor = num / this._referenceDPI * this._scaleFactor;
  198. this.SetScaleFactor(scaleFactor);
  199. this.SetReferencePixelsPerUnit(this._referencePixelsPerUnit);
  200. }
  201. private void HandleScaleWithDPIScreenSize()
  202. {
  203. float num = this.CalculateScreenSizeScaleFactor();
  204. float num2 = (this._currentDPI > 0f) ? this._currentDPI : this._referenceDPI;
  205. float num3 = Mathf.Lerp((float)Screen.width, (float)Screen.height, this._matchWidthOrHeight) / num2;
  206. float num4 = 1f;
  207. if (num3 > this._largeScreenThresholdInches)
  208. {
  209. float num5 = num3 - this._largeScreenThresholdInches;
  210. num4 -= num5 * this._largeScreenDampeningFactor;
  211. }
  212. float num6 = num * num4;
  213. num6 = Mathf.Max(this._minimumCanvasScale, num6);
  214. this.SetScaleFactor(num6);
  215. this.SetReferencePixelsPerUnit(this._referencePixelsPerUnit);
  216. }
  217. private void SetScaleFactor(float scaleFactor)
  218. {
  219. if (scaleFactor == this._prevScaleFactor)
  220. {
  221. return;
  222. }
  223. this._canvas.scaleFactor = scaleFactor;
  224. this._prevScaleFactor = scaleFactor;
  225. }
  226. private void SetReferencePixelsPerUnit(float referencePixelsPerUnit)
  227. {
  228. if (referencePixelsPerUnit == this._prevReferencePixelsPerUnit)
  229. {
  230. return;
  231. }
  232. this._canvas.referencePixelsPerUnit = referencePixelsPerUnit;
  233. this._prevReferencePixelsPerUnit = referencePixelsPerUnit;
  234. }
  235. private const float LogBase = 2f;
  236. [Tooltip("The Canvas to which the Scale Factor and Reference PPU will be applied.")]
  237. [SerializeField]
  238. private Canvas _canvas;
  239. [Tooltip("Determines how UI elements in the Canvas are scaled.")]
  240. [SerializeField]
  241. private CIGCanvasScaler.ScaleMode _uiScaleMode = CIGCanvasScaler.ScaleMode.ScaleWithDPIScreenSize;
  242. [Tooltip("If a sprite has this 'Pixels Per Unit' setting, then one pixel in the sprite will cover one unit in the UI.")]
  243. [SerializeField]
  244. private float _referencePixelsPerUnit = 100f;
  245. [Tooltip("The resolution the UI layout is designed for. If the screen resolution is larger, the UI will be scaled up, and if it's smaller, the UI will be scaled down. This is done in accordance with the Screen Match Mode.")]
  246. [SerializeField]
  247. private Vector2 _referenceResolution = new Vector2(1280f, 720f);
  248. [Tooltip("The DPI the UI layout is designed for. Or to use when the screen DPI is not known.")]
  249. [SerializeField]
  250. private float _referenceDPI = 96f;
  251. [Tooltip("Determines if the scaling is using the width or height as reference, or a mix in between.")]
  252. [Range(0f, 1f)]
  253. [SerializeField]
  254. private float _matchWidthOrHeight = 1f;
  255. [Tooltip("Scales all UI elements in the Canvas by this factor. (Only used for Constant Pixel and Physical Size)")]
  256. [SerializeField]
  257. private float _scaleFactor = 1f;
  258. [Tooltip("Determines if the Large Screen Threshold formula is using the width or height as reference, or a mix in between.")]
  259. [Range(0f, 1f)]
  260. [SerializeField]
  261. private float _largeScreenMatchWidthOrHeight = 1f;
  262. [Tooltip("The Threshold (in Inches) used to determine if a screen is considered large enough to have its scaling factor dampened.")]
  263. [SerializeField]
  264. private float _largeScreenThresholdInches = 2.69f;
  265. [Tooltip("The Dampening Factor used when calculating the scaling factor for Large Screens.")]
  266. [SerializeField]
  267. private float _largeScreenDampeningFactor = 0.025f;
  268. [Tooltip("The scale of the canvas will never go below this value.")]
  269. [SerializeField]
  270. private float _minimumCanvasScale = 0.25f;
  271. private float _currentDPI;
  272. private float _prevScaleFactor = 1f;
  273. private float _prevReferencePixelsPerUnit = 100f;
  274. public enum ScaleMode
  275. {
  276. ConstantPixelSize,
  277. ScaleWithScreenSize,
  278. ConstantPhysicalSize,
  279. ScaleWithDPIScreenSize = 99
  280. }
  281. }
  282. }