Image.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. using UnityEngine;
  2. namespace FairyGUI
  3. {
  4. /// <summary>
  5. ///
  6. /// </summary>
  7. public class Image : DisplayObject, IMeshFactory
  8. {
  9. protected Rect? _scale9Grid;
  10. protected bool _scaleByTile;
  11. protected Vector2 _textureScale;
  12. protected int _tileGridIndice;
  13. protected FillMesh _fillMesh;
  14. public Image() : this(null)
  15. {
  16. }
  17. /// <summary>
  18. ///
  19. /// </summary>
  20. /// <param name="texture"></param>
  21. public Image(NTexture texture)
  22. : base()
  23. {
  24. _flags |= Flags.TouchDisabled;
  25. CreateGameObject("Image");
  26. graphics = new NGraphics(gameObject);
  27. graphics.shader = ShaderConfig.imageShader;
  28. graphics.meshFactory = this;
  29. _textureScale = Vector2.one;
  30. if (texture != null)
  31. UpdateTexture(texture);
  32. }
  33. /// <summary>
  34. ///
  35. /// </summary>
  36. public NTexture texture
  37. {
  38. get { return graphics.texture; }
  39. set
  40. {
  41. UpdateTexture(value);
  42. }
  43. }
  44. public Vector2 textureScale
  45. {
  46. get { return _textureScale; }
  47. set
  48. {
  49. _textureScale = value;
  50. graphics.SetMeshDirty();
  51. }
  52. }
  53. /// <summary>
  54. ///
  55. /// </summary>
  56. public Color color
  57. {
  58. get
  59. {
  60. return graphics.color;
  61. }
  62. set
  63. {
  64. graphics.color = value;
  65. graphics.Tint();
  66. }
  67. }
  68. /// <summary>
  69. ///
  70. /// </summary>
  71. public FillMethod fillMethod
  72. {
  73. get { return _fillMesh != null ? _fillMesh.method : FillMethod.None; }
  74. set
  75. {
  76. if (_fillMesh == null)
  77. {
  78. if (value == FillMethod.None)
  79. return;
  80. _fillMesh = new FillMesh();
  81. }
  82. if (_fillMesh.method != value)
  83. {
  84. _fillMesh.method = value;
  85. graphics.SetMeshDirty();
  86. }
  87. }
  88. }
  89. /// <summary>
  90. ///
  91. /// </summary>
  92. public int fillOrigin
  93. {
  94. get { return _fillMesh != null ? _fillMesh.origin : 0; }
  95. set
  96. {
  97. if (_fillMesh == null)
  98. _fillMesh = new FillMesh();
  99. if (_fillMesh.origin != value)
  100. {
  101. _fillMesh.origin = value;
  102. graphics.SetMeshDirty();
  103. }
  104. }
  105. }
  106. /// <summary>
  107. ///
  108. /// </summary>
  109. public bool fillClockwise
  110. {
  111. get { return _fillMesh != null ? _fillMesh.clockwise : true; }
  112. set
  113. {
  114. if (_fillMesh == null)
  115. _fillMesh = new FillMesh();
  116. if (_fillMesh.clockwise != value)
  117. {
  118. _fillMesh.clockwise = value;
  119. graphics.SetMeshDirty();
  120. }
  121. }
  122. }
  123. /// <summary>
  124. ///
  125. /// </summary>
  126. public float fillAmount
  127. {
  128. get { return _fillMesh != null ? _fillMesh.amount : 0; }
  129. set
  130. {
  131. if (_fillMesh == null)
  132. _fillMesh = new FillMesh();
  133. if (_fillMesh.amount != value)
  134. {
  135. _fillMesh.amount = value;
  136. graphics.SetMeshDirty();
  137. }
  138. }
  139. }
  140. /// <summary>
  141. ///
  142. /// </summary>
  143. public Rect? scale9Grid
  144. {
  145. get { return _scale9Grid; }
  146. set
  147. {
  148. if (_scale9Grid != value)
  149. {
  150. _scale9Grid = value;
  151. graphics.SetMeshDirty();
  152. }
  153. }
  154. }
  155. /// <summary>
  156. ///
  157. /// </summary>
  158. public bool scaleByTile
  159. {
  160. get { return _scaleByTile; }
  161. set
  162. {
  163. if (_scaleByTile != value)
  164. {
  165. _scaleByTile = value;
  166. graphics.SetMeshDirty();
  167. }
  168. }
  169. }
  170. /// <summary>
  171. ///
  172. /// </summary>
  173. public int tileGridIndice
  174. {
  175. get { return _tileGridIndice; }
  176. set
  177. {
  178. if (_tileGridIndice != value)
  179. {
  180. _tileGridIndice = value;
  181. graphics.SetMeshDirty();
  182. }
  183. }
  184. }
  185. /// <summary>
  186. ///
  187. /// </summary>
  188. public void SetNativeSize()
  189. {
  190. if (graphics.texture != null)
  191. SetSize(graphics.texture.width, graphics.texture.height);
  192. else
  193. SetSize(0, 0);
  194. }
  195. virtual protected void UpdateTexture(NTexture value)
  196. {
  197. if (value == graphics.texture)
  198. return;
  199. graphics.texture = value;
  200. _textureScale = Vector2.one;
  201. if (_contentRect.width == 0)
  202. SetNativeSize();
  203. InvalidateBatchingState();
  204. }
  205. public void OnPopulateMesh(VertexBuffer vb)
  206. {
  207. if (_fillMesh != null && _fillMesh.method != FillMethod.None)
  208. {
  209. _fillMesh.OnPopulateMesh(vb);
  210. }
  211. else if (_scaleByTile)
  212. {
  213. NTexture texture = graphics.texture;
  214. if (texture.root == texture
  215. && texture.nativeTexture != null
  216. && texture.nativeTexture.wrapMode == TextureWrapMode.Repeat)
  217. {
  218. Rect uvRect = vb.uvRect;
  219. uvRect.width *= vb.contentRect.width / texture.width * _textureScale.x;
  220. uvRect.height *= vb.contentRect.height / texture.height * _textureScale.y;
  221. vb.AddQuad(vb.contentRect, vb.vertexColor, uvRect);
  222. vb.AddTriangles();
  223. }
  224. else
  225. {
  226. Rect contentRect = vb.contentRect;
  227. contentRect.width *= _textureScale.x;
  228. contentRect.height *= _textureScale.y;
  229. TileFill(vb, contentRect, vb.uvRect, texture.width, texture.height);
  230. vb.AddTriangles();
  231. }
  232. }
  233. else if (_scale9Grid != null)
  234. {
  235. SliceFill(vb);
  236. }
  237. else
  238. graphics.OnPopulateMesh(vb);
  239. }
  240. static int[] TRIANGLES_9_GRID = new int[] {
  241. 4,0,1,1,5,4,
  242. 5,1,2,2,6,5,
  243. 6,2,3,3,7,6,
  244. 8,4,5,5,9,8,
  245. 9,5,6,6,10,9,
  246. 10,6,7,7,11,10,
  247. 12,8,9,9,13,12,
  248. 13,9,10,10,14,13,
  249. 14,10,11,
  250. 11,15,14
  251. };
  252. static int[] gridTileIndice = new int[] { -1, 0, -1, 2, 4, 3, -1, 1, -1 };
  253. static float[] gridX = new float[4];
  254. static float[] gridY = new float[4];
  255. static float[] gridTexX = new float[4];
  256. static float[] gridTexY = new float[4];
  257. public void SliceFill(VertexBuffer vb)
  258. {
  259. NTexture texture = graphics.texture;
  260. Rect gridRect = (Rect)_scale9Grid;
  261. Rect contentRect = vb.contentRect;
  262. contentRect.width *= _textureScale.x;
  263. contentRect.height *= _textureScale.y;
  264. Rect uvRect = vb.uvRect;
  265. float sourceW = texture.width;
  266. float sourceH = texture.height;
  267. if (graphics.flip != FlipType.None)
  268. {
  269. if (graphics.flip == FlipType.Horizontal || graphics.flip == FlipType.Both)
  270. {
  271. gridRect.x = sourceW - gridRect.xMax;
  272. gridRect.xMax = gridRect.x + gridRect.width;
  273. }
  274. if (graphics.flip == FlipType.Vertical || graphics.flip == FlipType.Both)
  275. {
  276. gridRect.y = sourceH - gridRect.yMax;
  277. gridRect.yMax = gridRect.y + gridRect.height;
  278. }
  279. }
  280. float sx = uvRect.width / sourceW;
  281. float sy = uvRect.height / sourceH;
  282. float xMax = uvRect.xMax;
  283. float yMax = uvRect.yMax;
  284. float xMax2 = gridRect.xMax;
  285. float yMax2 = gridRect.yMax;
  286. gridTexX[0] = uvRect.x;
  287. gridTexX[1] = uvRect.x + gridRect.x * sx;
  288. gridTexX[2] = uvRect.x + xMax2 * sx;
  289. gridTexX[3] = xMax;
  290. gridTexY[0] = yMax;
  291. gridTexY[1] = yMax - gridRect.y * sy;
  292. gridTexY[2] = yMax - yMax2 * sy;
  293. gridTexY[3] = uvRect.y;
  294. if (contentRect.width >= (sourceW - gridRect.width))
  295. {
  296. gridX[1] = gridRect.x;
  297. gridX[2] = contentRect.width - (sourceW - xMax2);
  298. gridX[3] = contentRect.width;
  299. }
  300. else
  301. {
  302. float tmp = gridRect.x / (sourceW - xMax2);
  303. tmp = contentRect.width * tmp / (1 + tmp);
  304. gridX[1] = tmp;
  305. gridX[2] = tmp;
  306. gridX[3] = contentRect.width;
  307. }
  308. if (contentRect.height >= (sourceH - gridRect.height))
  309. {
  310. gridY[1] = gridRect.y;
  311. gridY[2] = contentRect.height - (sourceH - yMax2);
  312. gridY[3] = contentRect.height;
  313. }
  314. else
  315. {
  316. float tmp = gridRect.y / (sourceH - yMax2);
  317. tmp = contentRect.height * tmp / (1 + tmp);
  318. gridY[1] = tmp;
  319. gridY[2] = tmp;
  320. gridY[3] = contentRect.height;
  321. }
  322. if (_tileGridIndice == 0)
  323. {
  324. for (int cy = 0; cy < 4; cy++)
  325. {
  326. for (int cx = 0; cx < 4; cx++)
  327. vb.AddVert(new Vector2(gridX[cx] / _textureScale.x, gridY[cy] / _textureScale.y), vb.vertexColor, new Vector2(gridTexX[cx], gridTexY[cy]));
  328. }
  329. vb.AddTriangles(TRIANGLES_9_GRID);
  330. }
  331. else
  332. {
  333. Rect drawRect;
  334. Rect texRect;
  335. int row, col;
  336. int part;
  337. for (int pi = 0; pi < 9; pi++)
  338. {
  339. col = pi % 3;
  340. row = pi / 3;
  341. part = gridTileIndice[pi];
  342. drawRect = Rect.MinMaxRect(gridX[col], gridY[row], gridX[col + 1], gridY[row + 1]);
  343. texRect = Rect.MinMaxRect(gridTexX[col], gridTexY[row + 1], gridTexX[col + 1], gridTexY[row]);
  344. if (part != -1 && (_tileGridIndice & (1 << part)) != 0)
  345. {
  346. TileFill(vb, drawRect, texRect,
  347. (part == 0 || part == 1 || part == 4) ? gridRect.width : drawRect.width,
  348. (part == 2 || part == 3 || part == 4) ? gridRect.height : drawRect.height);
  349. }
  350. else
  351. {
  352. drawRect.x /= _textureScale.x;
  353. drawRect.y /= _textureScale.y;
  354. drawRect.width /= _textureScale.x;
  355. drawRect.height /= _textureScale.y;
  356. vb.AddQuad(drawRect, vb.vertexColor, texRect);
  357. }
  358. }
  359. vb.AddTriangles();
  360. }
  361. }
  362. void TileFill(VertexBuffer vb, Rect contentRect, Rect uvRect, float sourceW, float sourceH)
  363. {
  364. int hc = Mathf.CeilToInt(contentRect.width / sourceW);
  365. int vc = Mathf.CeilToInt(contentRect.height / sourceH);
  366. float tailWidth = contentRect.width - (hc - 1) * sourceW;
  367. float tailHeight = contentRect.height - (vc - 1) * sourceH;
  368. float xMax = uvRect.xMax;
  369. float yMax = uvRect.yMax;
  370. for (int i = 0; i < hc; i++)
  371. {
  372. for (int j = 0; j < vc; j++)
  373. {
  374. Rect uvTmp = uvRect;
  375. if (i == hc - 1)
  376. uvTmp.xMax = Mathf.Lerp(uvRect.x, xMax, tailWidth / sourceW);
  377. if (j == vc - 1)
  378. uvTmp.yMin = Mathf.Lerp(uvRect.y, yMax, 1 - tailHeight / sourceH);
  379. Rect drawRect = new Rect(contentRect.x + i * sourceW, contentRect.y + j * sourceH,
  380. i == (hc - 1) ? tailWidth : sourceW, j == (vc - 1) ? tailHeight : sourceH);
  381. drawRect.x /= _textureScale.x;
  382. drawRect.y /= _textureScale.y;
  383. drawRect.width /= _textureScale.x;
  384. drawRect.height /= _textureScale.y;
  385. vb.AddQuad(drawRect, vb.vertexColor, uvTmp);
  386. }
  387. }
  388. }
  389. }
  390. }