MB3_MBVersionConcrete.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  1. /**
  2. * \brief Hax! DLLs cannot interpret preprocessor directives, so this class acts as a "bridge"
  3. */
  4. using System;
  5. using UnityEngine;
  6. using System.Collections;
  7. using System.Collections.Generic;
  8. namespace DigitalOpus.MB.Core
  9. {
  10. public class MBVersionConcrete : MBVersionInterface
  11. {
  12. public string version()
  13. {
  14. return "3.29.1";
  15. }
  16. public int GetMajorVersion()
  17. {
  18. /*
  19. #if UNITY_3_0 || UNITY_3_0_0 || UNITY_3_1 || UNITY_3_2 || UNITY_3_3 || UNITY_3_4 || UNITY_3_5
  20. return 3;
  21. #elif UNITY_4_0 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7
  22. return 4;
  23. #else
  24. return 5;
  25. #endif
  26. */
  27. string v = Application.unityVersion;
  28. String[] vs = v.Split(new char[] { '.' });
  29. return Int32.Parse(vs[0]);
  30. }
  31. public int GetMinorVersion()
  32. {
  33. /*
  34. #if UNITY_3_0 || UNITY_3_0_0
  35. return 0;
  36. #elif UNITY_3_1
  37. return 1;
  38. #elif UNITY_3_2
  39. return 2;
  40. #elif UNITY_3_3
  41. return 3;
  42. #elif UNITY_3_4
  43. return 4;
  44. #elif UNITY_3_5
  45. return 5;
  46. #elif UNITY_4_0 || UNITY_4_0_1
  47. return 0;
  48. #elif UNITY_4_1
  49. return 1;
  50. #elif UNITY_4_2
  51. return 2;
  52. #elif UNITY_4_3
  53. return 3;
  54. #elif UNITY_4_4
  55. return 4;
  56. #elif UNITY_4_5
  57. return 5;
  58. #else
  59. return 0;
  60. #endif
  61. */
  62. string v = Application.unityVersion;
  63. String[] vs = v.Split(new char[] { '.' });
  64. return Int32.Parse(vs[1]);
  65. }
  66. public bool GetActive(GameObject go)
  67. {
  68. #if UNITY_3_0 || UNITY_3_0_0 || UNITY_3_1 || UNITY_3_2 || UNITY_3_3 || UNITY_3_4 || UNITY_3_5
  69. return go.active;
  70. #else
  71. return go.activeInHierarchy;
  72. #endif
  73. }
  74. public void SetActive(GameObject go, bool isActive)
  75. {
  76. #if UNITY_3_0 || UNITY_3_0_0 || UNITY_3_1 || UNITY_3_2 || UNITY_3_3 || UNITY_3_4 || UNITY_3_5
  77. go.active = isActive;
  78. #else
  79. go.SetActive(isActive);
  80. #endif
  81. }
  82. public void SetActiveRecursively(GameObject go, bool isActive)
  83. {
  84. #if UNITY_3_0 || UNITY_3_0_0 || UNITY_3_1 || UNITY_3_2 || UNITY_3_3 || UNITY_3_4 || UNITY_3_5
  85. go.SetActiveRecursively(isActive);
  86. #else
  87. go.SetActive(isActive);
  88. #endif
  89. }
  90. public UnityEngine.Object[] FindSceneObjectsOfType(Type t)
  91. {
  92. #if UNITY_3_0 || UNITY_3_0_0 || UNITY_3_1 || UNITY_3_2 || UNITY_3_3 || UNITY_3_4 || UNITY_3_5
  93. return GameObject.FindSceneObjectsOfType(t);
  94. #else
  95. return GameObject.FindObjectsOfType(t);
  96. #endif
  97. }
  98. public void OptimizeMesh(Mesh m)
  99. {
  100. #if UNITY_EDITOR
  101. #if UNITY_5_5_OR_NEWER
  102. UnityEditor.MeshUtility.Optimize(m);
  103. #else
  104. m.Optimize();
  105. #endif
  106. #endif
  107. }
  108. public bool IsRunningAndMeshNotReadWriteable(Mesh m)
  109. {
  110. if (Application.isPlaying)
  111. {
  112. #if UNITY_3_0 || UNITY_3_0_0 || UNITY_3_1 || UNITY_3_2 || UNITY_3_3 || UNITY_3_4 || UNITY_3_5
  113. return false;
  114. #else
  115. return !m.isReadable;
  116. #endif
  117. }
  118. else
  119. {
  120. return false;
  121. }
  122. }
  123. Vector2 _HALF_UV = new Vector2(.5f, .5f);
  124. public Vector2[] GetMeshUV1s(Mesh m, MB2_LogLevel LOG_LEVEL)
  125. {
  126. Vector2[] uv;
  127. #if (UNITY_4_6 || UNITY_4_7 || UNITY_4_5 || UNITY_4_3 || UNITY_4_2 || UNITY_4_1 || UNITY_4_0_1 || UNITY_4_0 || UNITY_3_5)
  128. uv = m.uv1;
  129. #else
  130. if (LOG_LEVEL >= MB2_LogLevel.warn) MB2_Log.LogDebug("UV1 does not exist in Unity 5+");
  131. uv = m.uv;
  132. #endif
  133. if (uv.Length == 0)
  134. {
  135. if (LOG_LEVEL >= MB2_LogLevel.debug) MB2_Log.LogDebug("Mesh " + m + " has no uv1s. Generating");
  136. if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Mesh " + m + " didn't have uv1s. Generating uv1s.");
  137. uv = new Vector2[m.vertexCount];
  138. for (int i = 0; i < uv.Length; i++) { uv[i] = _HALF_UV; }
  139. }
  140. return uv;
  141. }
  142. public Vector2[] GetMeshUVChannel(int channel, Mesh m, MB2_LogLevel LOG_LEVEL)
  143. {
  144. Vector2[] uvs = new Vector2[0];
  145. switch (channel)
  146. {
  147. case 0:
  148. uvs = m.uv;
  149. break;
  150. case 2:
  151. uvs = m.uv2;
  152. break;
  153. case 3:
  154. uvs = m.uv3;
  155. break;
  156. case 4:
  157. uvs = m.uv4;
  158. break;
  159. #if UNITY_2018_2_OR_NEWER
  160. case 5:
  161. uvs = m.uv5;
  162. break;
  163. case 6:
  164. uvs = m.uv6;
  165. break;
  166. case 7:
  167. uvs = m.uv7;
  168. break;
  169. case 8:
  170. uvs = m.uv8;
  171. break;
  172. #endif
  173. default:
  174. Debug.LogError("Mesh does not have UV channel " + channel);
  175. break;
  176. }
  177. if (uvs.Length == 0)
  178. {
  179. if (LOG_LEVEL >= MB2_LogLevel.debug) MB2_Log.LogDebug("Mesh " + m + " has no uv" + channel + ". Generating");
  180. uvs = new Vector2[m.vertexCount];
  181. for (int i = 0; i < uvs.Length; i++) { uvs[i] = _HALF_UV; }
  182. }
  183. return uvs;
  184. }
  185. public void MeshClear(Mesh m, bool t)
  186. {
  187. #if UNITY_3_5
  188. m.Clear();
  189. #else
  190. m.Clear(t);
  191. #endif
  192. }
  193. public void MeshAssignUVChannel(int channel, Mesh m, Vector2[] uvs)
  194. {
  195. switch (channel)
  196. {
  197. case 0:
  198. m.uv = uvs;
  199. break;
  200. case 2:
  201. m.uv2 = uvs;
  202. break;
  203. case 3:
  204. m.uv3 = uvs;
  205. break;
  206. case 4:
  207. m.uv4 = uvs;
  208. break;
  209. #if UNITY_2018_2_OR_NEWER
  210. case 5:
  211. m.uv5 = uvs;
  212. break;
  213. case 6:
  214. m.uv6 = uvs;
  215. break;
  216. case 7:
  217. m.uv7 = uvs;
  218. break;
  219. case 8:
  220. m.uv8 = uvs;
  221. break;
  222. #endif
  223. default:
  224. Debug.LogError("Mesh does not have UV channel " + channel);
  225. break;
  226. }
  227. }
  228. public Vector4 GetLightmapTilingOffset(Renderer r)
  229. {
  230. #if (UNITY_4_6 || UNITY_4_7 || UNITY_4_5 || UNITY_4_3 || UNITY_4_2 || UNITY_4_1 || UNITY_4_0_1 || UNITY_4_0 || UNITY_3_5)
  231. return r.lightmapTilingOffset ;
  232. #else
  233. return r.lightmapScaleOffset; //r.lightmapScaleOffset ;
  234. #endif
  235. }
  236. #if UNITY_5_OR_NEWER
  237. public Transform[] GetBones(Renderer r)
  238. {
  239. if (r is SkinnedMeshRenderer)
  240. {
  241. Transform[] bone;
  242. //check if I need to deoptimize
  243. Animator anim = r.GetComponentInParent<Animator>();
  244. if (anim != null)
  245. {
  246. if (anim.hasTransformHierarchy)
  247. {
  248. //nothing to do
  249. } else if (anim.isOptimizable)
  250. {
  251. //Deoptimize
  252. AnimatorUtility.DeoptimizeTransformHierarchy(anim.gameObject);
  253. }
  254. else
  255. {
  256. Debug.LogError("Could not getBones. Bones optimized but could not create TransformHierarchy.");
  257. return null;
  258. }
  259. bone = ((SkinnedMeshRenderer)r).bones;
  260. //can't deoptimize here because the transforms need to exist for the combined mesh
  261. } else
  262. {
  263. //no Animator component but check to see if bones were optimized on import
  264. bone = ((SkinnedMeshRenderer)r).bones;
  265. #if UNITY_EDITOR
  266. if (bone.Length == 0)
  267. {
  268. Mesh m = ((SkinnedMeshRenderer)r).sharedMesh;
  269. if (m.bindposes.Length != bone.Length) Debug.LogError("SkinnedMesh (" + r.gameObject + ") in the list of objects to combine has no bones. Check that 'optimize game object' is not checked in the 'Rig' tab of the asset importer. Mesh Baker cannot combine optimized skinned meshes because the bones are not available.");
  270. }
  271. #endif
  272. }
  273. return bone;
  274. }
  275. else if (r is MeshRenderer)
  276. {
  277. Transform[] bone = new Transform[1];
  278. bone[0] = r.transform;
  279. return bone;
  280. }
  281. else {
  282. Debug.LogError("Could not getBones. Object is not a Renderer.");
  283. return null;
  284. }
  285. }
  286. #else
  287. public Transform[] GetBones(Renderer r)
  288. {
  289. if (r is SkinnedMeshRenderer)
  290. {
  291. Transform[] bone = ((SkinnedMeshRenderer)r).bones;
  292. #if UNITY_EDITOR
  293. if (bone.Length == 0)
  294. {
  295. Mesh m = ((SkinnedMeshRenderer)r).sharedMesh;
  296. if (m.bindposes.Length != bone.Length) Debug.LogError("SkinnedMesh (" + r.gameObject + ") in the list of objects to combine has no bones. Check that 'optimize game object' is not checked in the 'Rig' tab of the asset importer. Mesh Baker cannot combine optimized skinned meshes because the bones are not available.");
  297. }
  298. #endif
  299. return bone;
  300. }
  301. else if (r is MeshRenderer)
  302. {
  303. Transform[] bone = new Transform[1];
  304. bone[0] = r.transform;
  305. return bone;
  306. }
  307. else
  308. {
  309. Debug.LogError("Could not getBones. Object does not have a renderer");
  310. return null;
  311. }
  312. }
  313. #endif
  314. public int GetBlendShapeFrameCount(Mesh m, int shapeIndex)
  315. {
  316. #if UNITY_5_3_OR_NEWER
  317. return m.GetBlendShapeFrameCount(shapeIndex);
  318. #else
  319. return 0;
  320. #endif
  321. }
  322. public float GetBlendShapeFrameWeight(Mesh m, int shapeIndex, int frameIndex)
  323. {
  324. #if UNITY_5_3_OR_NEWER
  325. return m.GetBlendShapeFrameWeight(shapeIndex, frameIndex);
  326. #else
  327. return 0;
  328. #endif
  329. }
  330. public void GetBlendShapeFrameVertices(Mesh m, int shapeIndex, int frameIndex, Vector3[] vs, Vector3[] ns, Vector3[] ts)
  331. {
  332. #if UNITY_5_3_OR_NEWER
  333. m.GetBlendShapeFrameVertices(shapeIndex, frameIndex, vs, ns, ts);
  334. #endif
  335. }
  336. public void ClearBlendShapes(Mesh m)
  337. {
  338. #if UNITY_5_3_OR_NEWER
  339. m.ClearBlendShapes();
  340. #endif
  341. }
  342. public void AddBlendShapeFrame(Mesh m, string nm, float wt, Vector3[] vs, Vector3[] ns, Vector3[] ts)
  343. {
  344. #if UNITY_5_3_OR_NEWER
  345. m.AddBlendShapeFrame(nm, wt, vs, ns, ts);
  346. #endif
  347. }
  348. public int MaxMeshVertexCount()
  349. {
  350. #if UNITY_2017_3_OR_NEWER
  351. return 2147483646;
  352. #else
  353. return 65535;
  354. #endif
  355. }
  356. public void SetMeshIndexFormatAndClearMesh(Mesh m, int numVerts, bool vertices, bool justClearTriangles)
  357. {
  358. #if UNITY_2017_3_OR_NEWER
  359. if (vertices && numVerts > 65534 && m.indexFormat == UnityEngine.Rendering.IndexFormat.UInt16)
  360. {
  361. MBVersion.MeshClear(m, false);
  362. m.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
  363. return;
  364. }
  365. else if (vertices && numVerts <= 65534 && m.indexFormat == UnityEngine.Rendering.IndexFormat.UInt32)
  366. {
  367. MBVersion.MeshClear(m, false);
  368. m.indexFormat = UnityEngine.Rendering.IndexFormat.UInt16;
  369. return;
  370. }
  371. #endif
  372. if (justClearTriangles)
  373. {
  374. MBVersion.MeshClear(m, true); //clear just triangles
  375. }
  376. else
  377. {//clear all the data and start with a blank mesh
  378. MBVersion.MeshClear(m, false);
  379. }
  380. }
  381. public bool GraphicsUVStartsAtTop()
  382. {
  383. #if UNITY_2017_1_OR_NEWER
  384. return SystemInfo.graphicsUVStartsAtTop;
  385. #else
  386. if (SystemInfo.graphicsDeviceVersion.Contains("metal"))
  387. {
  388. return false;
  389. }
  390. else
  391. {
  392. // "opengl es, direct3d"
  393. return true;
  394. }
  395. #endif
  396. }
  397. public bool IsTextureReadable(Texture2D tex)
  398. {
  399. #if UNITY_2018_3_OR_NEWER
  400. return tex.isReadable;
  401. #else
  402. try
  403. {
  404. tex.GetPixel(0, 0);
  405. return true;
  406. }
  407. catch
  408. {
  409. return false;
  410. }
  411. #endif
  412. }
  413. public bool CollectPropertyNames(List<ShaderTextureProperty> texPropertyNames, ShaderTextureProperty[] shaderTexPropertyNames, List<ShaderTextureProperty> _customShaderPropNames, Material resultMaterial, MB2_LogLevel LOG_LEVEL)
  414. {
  415. #if UNITY_2018_3_OR_NEWER
  416. // 2018.2 and up
  417. // Collect the property names from the material
  418. // Check with the lists of property names to flag which ones are normal maps.
  419. string[] matPropertyNames = resultMaterial.GetTexturePropertyNames();
  420. for (int matIdx = 0; matIdx < matPropertyNames.Length; matIdx++)
  421. {
  422. string matPropName = matPropertyNames[matIdx];
  423. if (resultMaterial.GetTextureOffset(matPropName) != new Vector2(0f, 0f))
  424. {
  425. if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Result material has non-zero offset for property " + matPropName + ". This is probably incorrect.");
  426. }
  427. if (resultMaterial.GetTextureScale(matPropName) != new Vector2(1f, 1f))
  428. {
  429. if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Result material should probably have tiling of 1,1 for propert " + matPropName);
  430. }
  431. ShaderTextureProperty pn = null;
  432. // We need to know if the property is a normal map or not.
  433. // first check the list of default names
  434. for (int defaultIdx = 0; defaultIdx < shaderTexPropertyNames.Length; defaultIdx++)
  435. {
  436. if (shaderTexPropertyNames[defaultIdx].name == matPropName)
  437. {
  438. pn = new ShaderTextureProperty(matPropName, shaderTexPropertyNames[defaultIdx].isNormalMap);
  439. }
  440. }
  441. // now check the list of custom property names
  442. for (int custPropIdx = 0; custPropIdx < _customShaderPropNames.Count; custPropIdx++)
  443. {
  444. if (_customShaderPropNames[custPropIdx].name == matPropName)
  445. {
  446. pn = new ShaderTextureProperty(matPropName, _customShaderPropNames[custPropIdx].isNormalMap);
  447. }
  448. }
  449. if (pn == null)
  450. {
  451. pn = new ShaderTextureProperty(matPropName, false, true);
  452. }
  453. texPropertyNames.Add(pn);
  454. }
  455. return true;
  456. #else
  457. { // Pre 2018.2, doesn't have API for querying material for property names.
  458. //Collect the property names for the textures
  459. string shaderPropStr = "";
  460. for (int i = 0; i < shaderTexPropertyNames.Length; i++)
  461. {
  462. if (resultMaterial.HasProperty(shaderTexPropertyNames[i].name))
  463. {
  464. shaderPropStr += ", " + shaderTexPropertyNames[i].name;
  465. if (!texPropertyNames.Contains(shaderTexPropertyNames[i])) texPropertyNames.Add(shaderTexPropertyNames[i]);
  466. if (resultMaterial.GetTextureOffset(shaderTexPropertyNames[i].name) != new Vector2(0f, 0f))
  467. {
  468. if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Result material has non-zero offset. This is may be incorrect.");
  469. }
  470. if (resultMaterial.GetTextureScale(shaderTexPropertyNames[i].name) != new Vector2(1f, 1f))
  471. {
  472. if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Result material should have tiling of 1,1");
  473. }
  474. }
  475. }
  476. for (int i = 0; i < _customShaderPropNames.Count; i++)
  477. {
  478. if (resultMaterial.HasProperty(_customShaderPropNames[i].name))
  479. {
  480. shaderPropStr += ", " + _customShaderPropNames[i].name;
  481. texPropertyNames.Add(_customShaderPropNames[i]);
  482. if (resultMaterial.GetTextureOffset(_customShaderPropNames[i].name) != new Vector2(0f, 0f))
  483. {
  484. if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Result material has non-zero offset. This is probably incorrect.");
  485. }
  486. if (resultMaterial.GetTextureScale(_customShaderPropNames[i].name) != new Vector2(1f, 1f))
  487. {
  488. if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Result material should probably have tiling of 1,1.");
  489. }
  490. }
  491. else
  492. {
  493. if (LOG_LEVEL >= MB2_LogLevel.warn) Debug.LogWarning("Result material shader does not use property " + _customShaderPropNames[i].name + " in the list of custom shader property names");
  494. }
  495. }
  496. }
  497. return true;
  498. #endif
  499. }
  500. }
  501. }