NTexture.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using Object = UnityEngine.Object;
  5. namespace FairyGUI
  6. {
  7. /// <summary>
  8. ///
  9. /// </summary>
  10. public enum DestroyMethod
  11. {
  12. Destroy,
  13. Unload,
  14. None,
  15. ReleaseTemp,
  16. Custom
  17. }
  18. /// <summary>
  19. ///
  20. /// </summary>
  21. public class NTexture
  22. {
  23. /// <summary>
  24. /// This event will trigger when a texture is destroying if its destroyMethod is Custom
  25. /// </summary>
  26. public static event Action<Texture> CustomDestroyMethod;
  27. /// <summary>
  28. ///
  29. /// </summary>
  30. public Rect uvRect;
  31. /// <summary>
  32. ///
  33. /// </summary>
  34. public bool rotated;
  35. /// <summary>
  36. ///
  37. /// </summary>
  38. public int refCount;
  39. /// <summary>
  40. ///
  41. /// </summary>
  42. public float lastActive;
  43. /// <summary>
  44. ///
  45. /// </summary>
  46. public DestroyMethod destroyMethod;
  47. /// <summary>
  48. /// This event will trigger when texture reloaded and size changed.
  49. /// </summary>
  50. public event Action<NTexture> onSizeChanged;
  51. /// <summary>
  52. /// This event will trigger when ref count is zero.
  53. /// </summary>
  54. public event Action<NTexture> onRelease;
  55. Texture _nativeTexture;
  56. Texture _alphaTexture;
  57. Rect _region;
  58. Vector2 _offset;
  59. Vector2 _originalSize;
  60. NTexture _root;
  61. Dictionary<string, MaterialManager> _materialManagers;
  62. internal static Texture2D CreateEmptyTexture()
  63. {
  64. Texture2D emptyTexture = new Texture2D(1, 1, TextureFormat.RGB24, false);
  65. emptyTexture.name = "White Texture";
  66. emptyTexture.hideFlags = DisplayObject.hideFlags;
  67. emptyTexture.SetPixel(0, 0, Color.white);
  68. emptyTexture.Apply();
  69. return emptyTexture;
  70. }
  71. static NTexture _empty;
  72. /// <summary>
  73. ///
  74. /// </summary>
  75. public static NTexture Empty
  76. {
  77. get
  78. {
  79. if (_empty == null)
  80. _empty = new NTexture(CreateEmptyTexture());
  81. return _empty;
  82. }
  83. }
  84. /// <summary>
  85. ///
  86. /// </summary>
  87. public static void DisposeEmpty()
  88. {
  89. if (_empty != null)
  90. {
  91. NTexture tmp = _empty;
  92. _empty = null;
  93. tmp.Dispose();
  94. }
  95. }
  96. /// <summary>
  97. ///
  98. /// </summary>
  99. /// <param name="texture"></param>
  100. public NTexture(Texture texture) : this(texture, null, 1, 1)
  101. {
  102. }
  103. /// <summary>
  104. ///
  105. /// </summary>
  106. /// <param name="texture"></param>
  107. /// <param name="xScale"></param>
  108. /// <param name="yScale"></param>
  109. public NTexture(Texture texture, Texture alphaTexture, float xScale, float yScale)
  110. {
  111. _root = this;
  112. _nativeTexture = texture;
  113. _alphaTexture = alphaTexture;
  114. uvRect = new Rect(0, 0, xScale, yScale);
  115. if (yScale < 0)
  116. {
  117. uvRect.y = -yScale;
  118. uvRect.yMax = 0;
  119. }
  120. if (xScale < 0)
  121. {
  122. uvRect.x = -xScale;
  123. uvRect.xMax = 0;
  124. }
  125. if (_nativeTexture != null)
  126. _originalSize = new Vector2(_nativeTexture.width, _nativeTexture.height);
  127. _region = new Rect(0, 0, _originalSize.x, _originalSize.y);
  128. }
  129. /// <summary>
  130. ///
  131. /// </summary>
  132. /// <param name="texture"></param>
  133. /// <param name="region"></param>
  134. public NTexture(Texture texture, Rect region)
  135. {
  136. _root = this;
  137. _nativeTexture = texture;
  138. _region = region;
  139. _originalSize = new Vector2(_region.width, _region.height);
  140. if (_nativeTexture != null)
  141. uvRect = new Rect(region.x / _nativeTexture.width, 1 - region.yMax / _nativeTexture.height,
  142. region.width / _nativeTexture.width, region.height / _nativeTexture.height);
  143. else
  144. uvRect.Set(0, 0, 1, 1);
  145. }
  146. /// <summary>
  147. ///
  148. /// </summary>
  149. /// <param name="root"></param>
  150. /// <param name="region"></param>
  151. /// <param name="rotated"></param>
  152. public NTexture(NTexture root, Rect region, bool rotated)
  153. {
  154. _root = root;
  155. this.rotated = rotated;
  156. region.x += root._region.x;
  157. region.y += root._region.y;
  158. uvRect = new Rect(region.x * root.uvRect.width / root.width, 1 - region.yMax * root.uvRect.height / root.height,
  159. region.width * root.uvRect.width / root.width, region.height * root.uvRect.height / root.height);
  160. if (rotated)
  161. {
  162. float tmp = region.width;
  163. region.width = region.height;
  164. region.height = tmp;
  165. tmp = uvRect.width;
  166. uvRect.width = uvRect.height;
  167. uvRect.height = tmp;
  168. }
  169. _region = region;
  170. _originalSize = _region.size;
  171. }
  172. /// <summary>
  173. ///
  174. /// </summary>
  175. /// <param name="root"></param>
  176. /// <param name="region"></param>
  177. /// <param name="rotated"></param>
  178. /// <param name="originalSize"></param>
  179. /// <param name="offset"></param>
  180. public NTexture(NTexture root, Rect region, bool rotated, Vector2 originalSize, Vector2 offset)
  181. : this(root, region, rotated)
  182. {
  183. _originalSize = originalSize;
  184. _offset = offset;
  185. }
  186. /// <summary>
  187. ///
  188. /// </summary>
  189. /// <param name="sprite"></param>
  190. public NTexture(Sprite sprite)
  191. {
  192. Rect rect = sprite.textureRect;
  193. rect.y = sprite.texture.height - rect.yMax;
  194. _root = this;
  195. _nativeTexture = sprite.texture;
  196. _region = rect;
  197. _originalSize = new Vector2(_region.width, _region.height);
  198. uvRect = new Rect(_region.x / _nativeTexture.width, 1 - _region.yMax / _nativeTexture.height,
  199. _region.width / _nativeTexture.width, _region.height / _nativeTexture.height);
  200. }
  201. /// <summary>
  202. ///
  203. /// </summary>
  204. public int width
  205. {
  206. get { return (int)_region.width; }
  207. }
  208. /// <summary>
  209. ///
  210. /// </summary>
  211. public int height
  212. {
  213. get { return (int)_region.height; }
  214. }
  215. /// <summary>
  216. ///
  217. /// </summary>
  218. public Vector2 offset
  219. {
  220. get { return _offset; }
  221. set { _offset = value; }
  222. }
  223. /// <summary>
  224. ///
  225. /// </summary>
  226. public Vector2 originalSize
  227. {
  228. get { return _originalSize; }
  229. set { _originalSize = value; }
  230. }
  231. /// <summary>
  232. ///
  233. /// </summary>
  234. /// <param name="drawRect"></param>
  235. /// <returns></returns>
  236. public Rect GetDrawRect(Rect drawRect)
  237. {
  238. if (_originalSize.x == _region.width && _originalSize.y == _region.height)
  239. return drawRect;
  240. float sx = drawRect.width / _originalSize.x;
  241. float sy = drawRect.height / _originalSize.y;
  242. return new Rect(_offset.x * sx, _offset.y * sy, _region.width * sx, _region.height * sy);
  243. }
  244. /// <summary>
  245. ///
  246. /// </summary>
  247. /// <param name="uv"></param>
  248. public void GetUV(Vector2[] uv)
  249. {
  250. uv[0] = uvRect.position;
  251. uv[1] = new Vector2(uvRect.xMin, uvRect.yMax);
  252. uv[2] = new Vector2(uvRect.xMax, uvRect.yMax);
  253. uv[3] = new Vector2(uvRect.xMax, uvRect.yMin);
  254. if (rotated)
  255. {
  256. float xMin = uvRect.xMin;
  257. float yMin = uvRect.yMin;
  258. float yMax = uvRect.yMax;
  259. float tmp;
  260. for (int i = 0; i < 4; i++)
  261. {
  262. Vector2 m = uv[i];
  263. tmp = m.y;
  264. m.y = yMin + m.x - xMin;
  265. m.x = xMin + yMax - tmp;
  266. uv[i] = m;
  267. }
  268. }
  269. }
  270. /// <summary>
  271. ///
  272. /// </summary>
  273. public NTexture root
  274. {
  275. get { return _root; }
  276. }
  277. /// <summary>
  278. ///
  279. /// </summary>
  280. public bool disposed
  281. {
  282. get { return _root == null; }
  283. }
  284. /// <summary>
  285. ///
  286. /// </summary>
  287. public Texture nativeTexture
  288. {
  289. get { return _root != null ? _root._nativeTexture : null; }
  290. }
  291. /// <summary>
  292. ///
  293. /// </summary>
  294. public Texture alphaTexture
  295. {
  296. get { return _root != null ? _root._alphaTexture : null; }
  297. }
  298. /// <summary>
  299. ///
  300. /// </summary>
  301. public MaterialManager GetMaterialManager(string shaderName)
  302. {
  303. if (_root != this)
  304. {
  305. if (_root == null)
  306. return null;
  307. else
  308. return _root.GetMaterialManager(shaderName);
  309. }
  310. if (_materialManagers == null)
  311. _materialManagers = new Dictionary<string, MaterialManager>();
  312. MaterialManager mm;
  313. if (!_materialManagers.TryGetValue(shaderName, out mm))
  314. {
  315. mm = new MaterialManager(this, ShaderConfig.GetShader(shaderName));
  316. _materialManagers.Add(shaderName, mm);
  317. }
  318. return mm;
  319. }
  320. /// <summary>
  321. ///
  322. /// </summary>
  323. public void Unload()
  324. {
  325. Unload(false);
  326. }
  327. /// <summary>
  328. ///
  329. /// </summary>
  330. public void Unload(bool destroyMaterials)
  331. {
  332. if (this == _empty)
  333. return;
  334. if (_root != this)
  335. throw new Exception("Unload is not allow to call on none root NTexture.");
  336. if (_nativeTexture != null)
  337. {
  338. DestroyTexture();
  339. if (destroyMaterials)
  340. DestroyMaterials();
  341. else
  342. RefreshMaterials();
  343. }
  344. }
  345. /// <summary>
  346. ///
  347. /// </summary>
  348. /// <param name="nativeTexture"></param>
  349. /// <param name="alphaTexture"></param>
  350. public void Reload(Texture nativeTexture, Texture alphaTexture)
  351. {
  352. if (_root != this)
  353. throw new System.Exception("Reload is not allow to call on none root NTexture.");
  354. if (_nativeTexture != null && _nativeTexture != nativeTexture)
  355. DestroyTexture();
  356. _nativeTexture = nativeTexture;
  357. _alphaTexture = alphaTexture;
  358. Vector2 lastSize = _originalSize;
  359. if (_nativeTexture != null)
  360. _originalSize = new Vector2(_nativeTexture.width, _nativeTexture.height);
  361. else
  362. _originalSize = Vector2.zero;
  363. _region = new Rect(0, 0, _originalSize.x, _originalSize.y);
  364. RefreshMaterials();
  365. if (onSizeChanged != null && lastSize != _originalSize)
  366. onSizeChanged(this);
  367. }
  368. void DestroyTexture()
  369. {
  370. switch (destroyMethod)
  371. {
  372. case DestroyMethod.Destroy:
  373. Object.DestroyImmediate(_nativeTexture, true);
  374. if (_alphaTexture != null)
  375. Object.DestroyImmediate(_alphaTexture, true);
  376. break;
  377. case DestroyMethod.Unload:
  378. Resources.UnloadAsset(_nativeTexture);
  379. if (_alphaTexture != null)
  380. Resources.UnloadAsset(_alphaTexture);
  381. break;
  382. case DestroyMethod.ReleaseTemp:
  383. RenderTexture.ReleaseTemporary((RenderTexture)_nativeTexture);
  384. if (_alphaTexture is RenderTexture)
  385. RenderTexture.ReleaseTemporary((RenderTexture)_alphaTexture);
  386. break;
  387. case DestroyMethod.Custom:
  388. if (CustomDestroyMethod == null)
  389. Debug.LogWarning("NTexture.CustomDestroyMethod must be set to handle DestroyMethod.Custom");
  390. else
  391. {
  392. CustomDestroyMethod(_nativeTexture);
  393. if (_alphaTexture != null)
  394. CustomDestroyMethod(_alphaTexture);
  395. }
  396. break;
  397. }
  398. _nativeTexture = null;
  399. _alphaTexture = null;
  400. }
  401. void RefreshMaterials()
  402. {
  403. if (_materialManagers != null && _materialManagers.Count > 0)
  404. {
  405. Dictionary<string, MaterialManager>.Enumerator iter = _materialManagers.GetEnumerator();
  406. while (iter.MoveNext())
  407. iter.Current.Value.RefreshMaterials();
  408. iter.Dispose();
  409. }
  410. }
  411. void DestroyMaterials()
  412. {
  413. if (_materialManagers != null && _materialManagers.Count > 0)
  414. {
  415. Dictionary<string, MaterialManager>.Enumerator iter = _materialManagers.GetEnumerator();
  416. while (iter.MoveNext())
  417. iter.Current.Value.DestroyMaterials();
  418. iter.Dispose();
  419. }
  420. }
  421. public void AddRef()
  422. {
  423. if (_root == null) //disposed
  424. return;
  425. if (_root != this && refCount == 0)
  426. _root.AddRef();
  427. refCount++;
  428. }
  429. public void ReleaseRef()
  430. {
  431. if (_root == null) //disposed
  432. return;
  433. refCount--;
  434. if (refCount == 0)
  435. {
  436. if (_root != this)
  437. _root.ReleaseRef();
  438. if (onRelease != null)
  439. onRelease(this);
  440. }
  441. }
  442. /// <summary>
  443. ///
  444. /// </summary>
  445. public void Dispose()
  446. {
  447. if (this == _empty)
  448. return;
  449. if (_root == this)
  450. Unload(true);
  451. _root = null;
  452. onSizeChanged = null;
  453. onRelease = null;
  454. }
  455. }
  456. }