DataProvider.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. //------------------------------------------------------------
  2. // Game Framework
  3. // Copyright © 2013-2021 loyalsoft. All rights reserved.
  4. // Homepage: http://www.game7000.com/
  5. // Feedback: http://www.game7000.com/
  6. //------------------------------------------------------------
  7. using GameFramework.Resource;
  8. using System;
  9. namespace GameFramework
  10. {
  11. /// <summary>
  12. /// 数据提供者。
  13. /// </summary>
  14. /// <typeparam name="T">数据提供者的持有者的类型。</typeparam>
  15. internal sealed class DataProvider<T> : IDataProvider<T>
  16. {
  17. private const int BlockSize = 1024 * 4;
  18. private static byte[] s_CachedBytes = null;
  19. private readonly T m_Owner;
  20. private readonly LoadAssetCallbacks m_LoadAssetCallbacks;
  21. private readonly LoadBinaryCallbacks m_LoadBinaryCallbacks;
  22. private IResourceManager m_ResourceManager;
  23. private IDataProviderHelper<T> m_DataProviderHelper;
  24. private EventHandler<ReadDataSuccessEventArgs> m_ReadDataSuccessEventHandler;
  25. private EventHandler<ReadDataFailureEventArgs> m_ReadDataFailureEventHandler;
  26. private EventHandler<ReadDataUpdateEventArgs> m_ReadDataUpdateEventHandler;
  27. private EventHandler<ReadDataDependencyAssetEventArgs> m_ReadDataDependencyAssetEventHandler;
  28. /// <summary>
  29. /// 初始化数据提供者的新实例。
  30. /// </summary>
  31. /// <param name="owner">数据提供者的持有者。</param>
  32. public DataProvider(T owner)
  33. {
  34. m_Owner = owner;
  35. m_LoadAssetCallbacks = new LoadAssetCallbacks(LoadAssetSuccessCallback, LoadAssetOrBinaryFailureCallback, LoadAssetUpdateCallback, LoadAssetDependencyAssetCallback);
  36. m_LoadBinaryCallbacks = new LoadBinaryCallbacks(LoadBinarySuccessCallback, LoadAssetOrBinaryFailureCallback);
  37. m_ResourceManager = null;
  38. m_DataProviderHelper = null;
  39. m_ReadDataSuccessEventHandler = null;
  40. m_ReadDataFailureEventHandler = null;
  41. m_ReadDataUpdateEventHandler = null;
  42. m_ReadDataDependencyAssetEventHandler = null;
  43. }
  44. /// <summary>
  45. /// 获取缓冲二进制流的大小。
  46. /// </summary>
  47. public static int CachedBytesSize
  48. {
  49. get
  50. {
  51. return s_CachedBytes != null ? s_CachedBytes.Length : 0;
  52. }
  53. }
  54. /// <summary>
  55. /// 读取数据成功事件。
  56. /// </summary>
  57. public event EventHandler<ReadDataSuccessEventArgs> ReadDataSuccess
  58. {
  59. add
  60. {
  61. m_ReadDataSuccessEventHandler += value;
  62. }
  63. remove
  64. {
  65. m_ReadDataSuccessEventHandler -= value;
  66. }
  67. }
  68. /// <summary>
  69. /// 读取数据失败事件。
  70. /// </summary>
  71. public event EventHandler<ReadDataFailureEventArgs> ReadDataFailure
  72. {
  73. add
  74. {
  75. m_ReadDataFailureEventHandler += value;
  76. }
  77. remove
  78. {
  79. m_ReadDataFailureEventHandler -= value;
  80. }
  81. }
  82. /// <summary>
  83. /// 读取数据更新事件。
  84. /// </summary>
  85. public event EventHandler<ReadDataUpdateEventArgs> ReadDataUpdate
  86. {
  87. add
  88. {
  89. m_ReadDataUpdateEventHandler += value;
  90. }
  91. remove
  92. {
  93. m_ReadDataUpdateEventHandler -= value;
  94. }
  95. }
  96. /// <summary>
  97. /// 读取数据时加载依赖资源事件。
  98. /// </summary>
  99. public event EventHandler<ReadDataDependencyAssetEventArgs> ReadDataDependencyAsset
  100. {
  101. add
  102. {
  103. m_ReadDataDependencyAssetEventHandler += value;
  104. }
  105. remove
  106. {
  107. m_ReadDataDependencyAssetEventHandler -= value;
  108. }
  109. }
  110. /// <summary>
  111. /// 确保二进制流缓存分配足够大小的内存并缓存。
  112. /// </summary>
  113. /// <param name="ensureSize">要确保二进制流缓存分配内存的大小。</param>
  114. public static void EnsureCachedBytesSize(int ensureSize)
  115. {
  116. if (ensureSize < 0)
  117. {
  118. throw new GameFrameworkException("Ensure size is invalid.");
  119. }
  120. if (s_CachedBytes == null || s_CachedBytes.Length < ensureSize)
  121. {
  122. FreeCachedBytes();
  123. int size = (ensureSize - 1 + BlockSize) / BlockSize * BlockSize;
  124. s_CachedBytes = new byte[size];
  125. }
  126. }
  127. /// <summary>
  128. /// 释放缓存的二进制流。
  129. /// </summary>
  130. public static void FreeCachedBytes()
  131. {
  132. s_CachedBytes = null;
  133. }
  134. /// <summary>
  135. /// 读取数据。
  136. /// </summary>
  137. /// <param name="dataAssetName">内容资源名称。</param>
  138. public void ReadData(string dataAssetName)
  139. {
  140. ReadData(dataAssetName, Constant.DefaultPriority, null);
  141. }
  142. /// <summary>
  143. /// 读取数据。
  144. /// </summary>
  145. /// <param name="dataAssetName">内容资源名称。</param>
  146. /// <param name="priority">加载数据资源的优先级。</param>
  147. public void ReadData(string dataAssetName, int priority)
  148. {
  149. ReadData(dataAssetName, priority, null);
  150. }
  151. /// <summary>
  152. /// 读取数据。
  153. /// </summary>
  154. /// <param name="dataAssetName">内容资源名称。</param>
  155. /// <param name="userData">用户自定义数据。</param>
  156. public void ReadData(string dataAssetName, object userData)
  157. {
  158. ReadData(dataAssetName, Constant.DefaultPriority, userData);
  159. }
  160. /// <summary>
  161. /// 读取数据。
  162. /// </summary>
  163. /// <param name="dataAssetName">内容资源名称。</param>
  164. /// <param name="priority">加载数据资源的优先级。</param>
  165. /// <param name="userData">用户自定义数据。</param>
  166. public void ReadData(string dataAssetName, int priority, object userData)
  167. {
  168. if (m_ResourceManager == null)
  169. {
  170. throw new GameFrameworkException("You must set resource manager first.");
  171. }
  172. if (m_DataProviderHelper == null)
  173. {
  174. throw new GameFrameworkException("You must set data provider helper first.");
  175. }
  176. HasAssetResult result = m_ResourceManager.HasAsset(dataAssetName);
  177. switch (result)
  178. {
  179. case HasAssetResult.AssetOnDisk:
  180. case HasAssetResult.AssetOnFileSystem:
  181. m_ResourceManager.LoadAsset(dataAssetName, priority, m_LoadAssetCallbacks, userData);
  182. break;
  183. case HasAssetResult.BinaryOnDisk:
  184. m_ResourceManager.LoadBinary(dataAssetName, m_LoadBinaryCallbacks, userData);
  185. break;
  186. case HasAssetResult.BinaryOnFileSystem:
  187. int dataLength = m_ResourceManager.GetBinaryLength(dataAssetName);
  188. EnsureCachedBytesSize(dataLength);
  189. if (dataLength != m_ResourceManager.LoadBinaryFromFileSystem(dataAssetName, s_CachedBytes))
  190. {
  191. throw new GameFrameworkException(Utility.Text.Format("Load binary '{0}' from file system with internal error.", dataAssetName));
  192. }
  193. try
  194. {
  195. if (!m_DataProviderHelper.ReadData(m_Owner, dataAssetName, s_CachedBytes, 0, dataLength, userData))
  196. {
  197. throw new GameFrameworkException(Utility.Text.Format("Load data failure in data provider helper, data asset name '{0}'.", dataAssetName));
  198. }
  199. if (m_ReadDataSuccessEventHandler != null)
  200. {
  201. ReadDataSuccessEventArgs loadDataSuccessEventArgs = ReadDataSuccessEventArgs.Create(dataAssetName, 0f, userData);
  202. m_ReadDataSuccessEventHandler(this, loadDataSuccessEventArgs);
  203. ReferencePool.Release(loadDataSuccessEventArgs);
  204. }
  205. }
  206. catch (Exception exception)
  207. {
  208. if (m_ReadDataFailureEventHandler != null)
  209. {
  210. ReadDataFailureEventArgs loadDataFailureEventArgs = ReadDataFailureEventArgs.Create(dataAssetName, exception.ToString(), userData);
  211. m_ReadDataFailureEventHandler(this, loadDataFailureEventArgs);
  212. ReferencePool.Release(loadDataFailureEventArgs);
  213. return;
  214. }
  215. throw;
  216. }
  217. break;
  218. default:
  219. throw new GameFrameworkException(Utility.Text.Format("Data asset '{0}' is '{1}'.", dataAssetName, result));
  220. }
  221. }
  222. /// <summary>
  223. /// 解析内容。
  224. /// </summary>
  225. /// <param name="dataString">要解析的内容字符串。</param>
  226. /// <returns>是否解析内容成功。</returns>
  227. public bool ParseData(string dataString)
  228. {
  229. return ParseData(dataString, null);
  230. }
  231. /// <summary>
  232. /// 解析内容。
  233. /// </summary>
  234. /// <param name="dataString">要解析的内容字符串。</param>
  235. /// <param name="userData">用户自定义数据。</param>
  236. /// <returns>是否解析内容成功。</returns>
  237. public bool ParseData(string dataString, object userData)
  238. {
  239. if (m_DataProviderHelper == null)
  240. {
  241. throw new GameFrameworkException("You must set data helper first.");
  242. }
  243. if (dataString == null)
  244. {
  245. throw new GameFrameworkException("Data string is invalid.");
  246. }
  247. try
  248. {
  249. return m_DataProviderHelper.ParseData(m_Owner, dataString, userData);
  250. }
  251. catch (Exception exception)
  252. {
  253. if (exception is GameFrameworkException)
  254. {
  255. throw;
  256. }
  257. throw new GameFrameworkException(Utility.Text.Format("Can not parse data string with exception '{0}'.", exception), exception);
  258. }
  259. }
  260. /// <summary>
  261. /// 解析内容。
  262. /// </summary>
  263. /// <param name="dataBytes">要解析的内容二进制流。</param>
  264. /// <returns>是否解析内容成功。</returns>
  265. public bool ParseData(byte[] dataBytes)
  266. {
  267. if (dataBytes == null)
  268. {
  269. throw new GameFrameworkException("Data bytes is invalid.");
  270. }
  271. return ParseData(dataBytes, 0, dataBytes.Length, null);
  272. }
  273. /// <summary>
  274. /// 解析内容。
  275. /// </summary>
  276. /// <param name="dataBytes">要解析的内容二进制流。</param>
  277. /// <param name="userData">用户自定义数据。</param>
  278. /// <returns>是否解析内容成功。</returns>
  279. public bool ParseData(byte[] dataBytes, object userData)
  280. {
  281. if (dataBytes == null)
  282. {
  283. throw new GameFrameworkException("Data bytes is invalid.");
  284. }
  285. return ParseData(dataBytes, 0, dataBytes.Length, userData);
  286. }
  287. /// <summary>
  288. /// 解析内容。
  289. /// </summary>
  290. /// <param name="dataBytes">要解析的内容二进制流。</param>
  291. /// <param name="startIndex">内容二进制流的起始位置。</param>
  292. /// <param name="length">内容二进制流的长度。</param>
  293. /// <returns>是否解析内容成功。</returns>
  294. public bool ParseData(byte[] dataBytes, int startIndex, int length)
  295. {
  296. return ParseData(dataBytes, startIndex, length, null);
  297. }
  298. /// <summary>
  299. /// 解析内容。
  300. /// </summary>
  301. /// <param name="dataBytes">要解析的内容二进制流。</param>
  302. /// <param name="startIndex">内容二进制流的起始位置。</param>
  303. /// <param name="length">内容二进制流的长度。</param>
  304. /// <param name="userData">用户自定义数据。</param>
  305. /// <returns>是否解析内容成功。</returns>
  306. public bool ParseData(byte[] dataBytes, int startIndex, int length, object userData)
  307. {
  308. if (m_DataProviderHelper == null)
  309. {
  310. throw new GameFrameworkException("You must set data helper first.");
  311. }
  312. if (dataBytes == null)
  313. {
  314. throw new GameFrameworkException("Data bytes is invalid.");
  315. }
  316. if (startIndex < 0 || length < 0 || startIndex + length > dataBytes.Length)
  317. {
  318. throw new GameFrameworkException("Start index or length is invalid.");
  319. }
  320. try
  321. {
  322. return m_DataProviderHelper.ParseData(m_Owner, dataBytes, startIndex, length, userData);
  323. }
  324. catch (Exception exception)
  325. {
  326. if (exception is GameFrameworkException)
  327. {
  328. throw;
  329. }
  330. throw new GameFrameworkException(Utility.Text.Format("Can not parse data bytes with exception '{0}'.", exception), exception);
  331. }
  332. }
  333. /// <summary>
  334. /// 设置资源管理器。
  335. /// </summary>
  336. /// <param name="resourceManager">资源管理器。</param>
  337. internal void SetResourceManager(IResourceManager resourceManager)
  338. {
  339. if (resourceManager == null)
  340. {
  341. throw new GameFrameworkException("Resource manager is invalid.");
  342. }
  343. m_ResourceManager = resourceManager;
  344. }
  345. /// <summary>
  346. /// 设置数据提供者辅助器。
  347. /// </summary>
  348. /// <param name="dataProviderHelper">数据提供者辅助器。</param>
  349. internal void SetDataProviderHelper(IDataProviderHelper<T> dataProviderHelper)
  350. {
  351. if (dataProviderHelper == null)
  352. {
  353. throw new GameFrameworkException("Data provider helper is invalid.");
  354. }
  355. m_DataProviderHelper = dataProviderHelper;
  356. }
  357. private void LoadAssetSuccessCallback(string dataAssetName, object dataAsset, float duration, object userData)
  358. {
  359. try
  360. {
  361. if (!m_DataProviderHelper.ReadData(m_Owner, dataAssetName, dataAsset, userData))
  362. {
  363. throw new GameFrameworkException(Utility.Text.Format("Load data failure in data provider helper, data asset name '{0}'.", dataAssetName));
  364. }
  365. if (m_ReadDataSuccessEventHandler != null)
  366. {
  367. ReadDataSuccessEventArgs loadDataSuccessEventArgs = ReadDataSuccessEventArgs.Create(dataAssetName, duration, userData);
  368. m_ReadDataSuccessEventHandler(this, loadDataSuccessEventArgs);
  369. ReferencePool.Release(loadDataSuccessEventArgs);
  370. }
  371. }
  372. catch (Exception exception)
  373. {
  374. if (m_ReadDataFailureEventHandler != null)
  375. {
  376. ReadDataFailureEventArgs loadDataFailureEventArgs = ReadDataFailureEventArgs.Create(dataAssetName, exception.ToString(), userData);
  377. m_ReadDataFailureEventHandler(this, loadDataFailureEventArgs);
  378. ReferencePool.Release(loadDataFailureEventArgs);
  379. return;
  380. }
  381. throw;
  382. }
  383. finally
  384. {
  385. m_DataProviderHelper.ReleaseDataAsset(m_Owner, dataAsset);
  386. }
  387. }
  388. private void LoadAssetOrBinaryFailureCallback(string dataAssetName, LoadResourceStatus status, string errorMessage, object userData)
  389. {
  390. string appendErrorMessage = Utility.Text.Format("Load data failure, data asset name '{0}', status '{1}', error message '{2}'.", dataAssetName, status, errorMessage);
  391. if (m_ReadDataFailureEventHandler != null)
  392. {
  393. ReadDataFailureEventArgs loadDataFailureEventArgs = ReadDataFailureEventArgs.Create(dataAssetName, appendErrorMessage, userData);
  394. m_ReadDataFailureEventHandler(this, loadDataFailureEventArgs);
  395. ReferencePool.Release(loadDataFailureEventArgs);
  396. return;
  397. }
  398. throw new GameFrameworkException(appendErrorMessage);
  399. }
  400. private void LoadAssetUpdateCallback(string dataAssetName, float progress, object userData)
  401. {
  402. if (m_ReadDataUpdateEventHandler != null)
  403. {
  404. ReadDataUpdateEventArgs loadDataUpdateEventArgs = ReadDataUpdateEventArgs.Create(dataAssetName, progress, userData);
  405. m_ReadDataUpdateEventHandler(this, loadDataUpdateEventArgs);
  406. ReferencePool.Release(loadDataUpdateEventArgs);
  407. }
  408. }
  409. private void LoadAssetDependencyAssetCallback(string dataAssetName, string dependencyAssetName, int loadedCount, int totalCount, object userData)
  410. {
  411. if (m_ReadDataDependencyAssetEventHandler != null)
  412. {
  413. ReadDataDependencyAssetEventArgs loadDataDependencyAssetEventArgs = ReadDataDependencyAssetEventArgs.Create(dataAssetName, dependencyAssetName, loadedCount, totalCount, userData);
  414. m_ReadDataDependencyAssetEventHandler(this, loadDataDependencyAssetEventArgs);
  415. ReferencePool.Release(loadDataDependencyAssetEventArgs);
  416. }
  417. }
  418. private void LoadBinarySuccessCallback(string dataAssetName, byte[] dataBytes, float duration, object userData)
  419. {
  420. try
  421. {
  422. if (!m_DataProviderHelper.ReadData(m_Owner, dataAssetName, dataBytes, 0, dataBytes.Length, userData))
  423. {
  424. throw new GameFrameworkException(Utility.Text.Format("Load data failure in data provider helper, data asset name '{0}'.", dataAssetName));
  425. }
  426. if (m_ReadDataSuccessEventHandler != null)
  427. {
  428. ReadDataSuccessEventArgs loadDataSuccessEventArgs = ReadDataSuccessEventArgs.Create(dataAssetName, duration, userData);
  429. m_ReadDataSuccessEventHandler(this, loadDataSuccessEventArgs);
  430. ReferencePool.Release(loadDataSuccessEventArgs);
  431. }
  432. }
  433. catch (Exception exception)
  434. {
  435. if (m_ReadDataFailureEventHandler != null)
  436. {
  437. ReadDataFailureEventArgs loadDataFailureEventArgs = ReadDataFailureEventArgs.Create(dataAssetName, exception.ToString(), userData);
  438. m_ReadDataFailureEventHandler(this, loadDataFailureEventArgs);
  439. ReferencePool.Release(loadDataFailureEventArgs);
  440. return;
  441. }
  442. throw;
  443. }
  444. }
  445. }
  446. }