MegaMorphAnimator.cs 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. using UnityEngine;
  2. using System.Collections.Generic;
  3. [System.Serializable]
  4. public class MegaMorphAnimClip
  5. {
  6. public string name;
  7. public float start;
  8. public float end;
  9. public MegaRepeatMode loop;
  10. public float speed = 1.0f;
  11. public MegaMorphAnimClip(string _name, float _start, float _end, MegaRepeatMode _loop)
  12. {
  13. name = _name;
  14. start = _start;
  15. end = _end;
  16. loop = _loop;
  17. }
  18. }
  19. public class MegaPlayingClip
  20. {
  21. public float weight = 1.0f;
  22. public float t = 0.0f;
  23. public float at = 0.0f;
  24. public float targetblendtime = 1.0f;
  25. public float blendtime = 0.0f; // if not 0 then count down to 0, lerp weight and when 0 remove from playing
  26. public int clipIndex = 0;
  27. public float[] channelValues;
  28. }
  29. //public delegate bool MegaMorphAnimClipEvent(int clip, int id);
  30. [AddComponentMenu("Modifiers/Morph Animator")]
  31. [ExecuteInEditMode]
  32. public class MegaMorphAnimator : MonoBehaviour
  33. {
  34. public MegaMorphBase morph;
  35. public MegaMorphBase[] morphs;
  36. public List<MegaMorphAnimClip> clips = new List<MegaMorphAnimClip>();
  37. public List<MegaPlayingClip> playing = new List<MegaPlayingClip>();
  38. public int current = 0;
  39. public float t = -1.0f; // Current clip time
  40. public float at = 0.0f;
  41. public int sourceFPS = 30;
  42. public bool useFrames = true;
  43. Stack<MegaPlayingClip> clippool;
  44. public void UpdatePlayingClips()
  45. {
  46. if ( playing.Count == 0 )
  47. return;
  48. // reset blends
  49. morph.ClearBlends();
  50. for ( int i = playing.Count - 1; i >= 0; i-- )
  51. {
  52. MegaPlayingClip pclip = playing[i];
  53. MegaMorphAnimClip clip = clips[pclip.clipIndex];
  54. if ( pclip.t >= 0.0f )
  55. {
  56. pclip.t += Time.deltaTime * clip.speed;
  57. float dt = clip.end - clip.start;
  58. switch ( clip.loop )
  59. {
  60. //case MegaRepeatMode.Loop: pclip.at = Mathf.Repeat(pclip.t, dt); break;
  61. case MegaRepeatMode.Loop:
  62. pclip.at = Mathf.Repeat(pclip.t, Mathf.Abs(dt));
  63. if ( dt < 0.0f )
  64. pclip.at = clip.start - pclip.at;
  65. break;
  66. case MegaRepeatMode.PingPong: pclip.at = Mathf.PingPong(pclip.t, dt); break;
  67. case MegaRepeatMode.Clamp: pclip.at = Mathf.Clamp(pclip.t, 0.0f, dt); break;
  68. }
  69. pclip.at += clip.start;
  70. if ( pclip.targetblendtime != 0.0f )
  71. {
  72. if ( pclip.targetblendtime > 0.0f )
  73. {
  74. pclip.blendtime += Time.deltaTime;
  75. if ( pclip.blendtime >= pclip.targetblendtime )
  76. {
  77. pclip.targetblendtime = 0.0f;
  78. pclip.weight = 1.0f;
  79. }
  80. else
  81. pclip.weight = (pclip.targetblendtime - pclip.blendtime) / pclip.targetblendtime;
  82. }
  83. else
  84. {
  85. pclip.blendtime -= Time.deltaTime;
  86. if ( pclip.blendtime <= pclip.targetblendtime )
  87. {
  88. pclip.targetblendtime = 0.0f;
  89. pclip.weight = 0.0f;
  90. }
  91. else
  92. pclip.weight = (pclip.targetblendtime - pclip.blendtime) / pclip.targetblendtime;
  93. }
  94. }
  95. if ( pclip.weight != 0.0f )
  96. {
  97. if ( MultipleMorphs )
  98. {
  99. if ( morphs != null )
  100. {
  101. for ( int m = 0; m < morphs.Length; m++ )
  102. {
  103. morphs[m].SetAnimBlend(pclip.at, pclip.weight);
  104. }
  105. }
  106. }
  107. else
  108. {
  109. if ( morph )
  110. morph.SetAnimBlend(pclip.at, pclip.weight);
  111. }
  112. }
  113. else
  114. {
  115. PushClip(pclip);
  116. playing.RemoveAt(i);
  117. }
  118. }
  119. }
  120. }
  121. [ContextMenu("Help")]
  122. public void Help()
  123. {
  124. Application.OpenURL("http://www.west-racing.com/mf/?page_id=1108");
  125. }
  126. public bool IsPlaying()
  127. {
  128. if ( t >= 0.0f )
  129. return true;
  130. return false;
  131. }
  132. public void SetTime(float time)
  133. {
  134. t = time;
  135. }
  136. public float GetTime()
  137. {
  138. return at;
  139. }
  140. public void PlayClipEvent(int i)
  141. {
  142. PlayClip(i);
  143. }
  144. public void PlayClipNameEvent(string name)
  145. {
  146. PlayClip(name);
  147. }
  148. public void PlayClip(int i)
  149. {
  150. if ( i < clips.Count )
  151. {
  152. current = i;
  153. t = 0.0f;
  154. }
  155. }
  156. public void PlayClip(string name)
  157. {
  158. for ( int i = 0; i < clips.Count; i++ )
  159. {
  160. if ( clips[i].name == name )
  161. {
  162. current = i;
  163. t = 0.0f;
  164. return;
  165. }
  166. }
  167. }
  168. public void PlayClip(int i, float blend)
  169. {
  170. if ( i < clips.Count )
  171. {
  172. current = i;
  173. t = 0.0f;
  174. MegaPlayingClip pclip = PopClip(); //new MegaPlayingClip(); // TODO: have a pool for these
  175. pclip.t = 0.0f;
  176. pclip.targetblendtime = blend;
  177. MegaPlayingClip cclip = playing[playing.Count - 1];
  178. cclip.blendtime = -Mathf.Abs(cclip.blendtime);
  179. cclip.targetblendtime = -blend;
  180. playing.Add(pclip);
  181. }
  182. }
  183. public void PlayClip(string name, float blend)
  184. {
  185. for ( int i = 0; i < clips.Count; i++ )
  186. {
  187. if ( clips[i].name == name )
  188. {
  189. PlayClip(i, blend);
  190. return;
  191. }
  192. }
  193. }
  194. public void Stop()
  195. {
  196. t = -1.0f;
  197. }
  198. public int AddClip(string name, float start, float end, MegaRepeatMode loop)
  199. {
  200. MegaMorphAnimClip clip = new MegaMorphAnimClip(name, start, end, loop);
  201. clips.Add(clip);
  202. return clips.Count - 1;
  203. }
  204. public string[] GetClipNames()
  205. {
  206. string[] names = new string[clips.Count];
  207. for ( int i = 0; i < clips.Count; i++ )
  208. {
  209. names[i] = clips[i].name;
  210. }
  211. return names;
  212. }
  213. void Start()
  214. {
  215. if ( clippool == null )
  216. {
  217. clippool = new Stack<MegaPlayingClip>(8);
  218. }
  219. if ( PlayOnStart )
  220. t = 0.0f;
  221. else
  222. t = -1.0f;
  223. }
  224. MegaPlayingClip PopClip()
  225. {
  226. return clippool.Pop();
  227. }
  228. void PushClip(MegaPlayingClip clip)
  229. {
  230. clippool.Push(clip);
  231. }
  232. void Update()
  233. {
  234. DoUpdate();
  235. }
  236. void DoUpdate()
  237. {
  238. if ( MultipleMorphs )
  239. {
  240. if ( morphs == null )
  241. morphs = GetComponentsInChildren<MegaMorphBase>();
  242. }
  243. else
  244. {
  245. if ( morph == null )
  246. morph = (MegaMorphBase)GetComponent<MegaMorphBase>();
  247. }
  248. if ( LinkedUpdate )
  249. {
  250. DoLinkedUpdate();
  251. }
  252. else
  253. {
  254. //if ( morph && clips.Count > 0 && current < clips.Count )
  255. if ( clips.Count > 0 && current < clips.Count )
  256. {
  257. UpdatePlayingClips();
  258. if ( t >= 0.0f )
  259. {
  260. t += Time.deltaTime * clips[current].speed;
  261. float dt = clips[current].end - clips[current].start;
  262. switch ( clips[current].loop )
  263. {
  264. case MegaRepeatMode.Loop: at = Mathf.Repeat(t, dt); break;
  265. case MegaRepeatMode.PingPong: at = Mathf.PingPong(t, dt); break;
  266. case MegaRepeatMode.Clamp: at = Mathf.Clamp(t, 0.0f, dt); break;
  267. }
  268. at += clips[current].start;
  269. if ( MultipleMorphs )
  270. {
  271. if ( morphs != null )
  272. {
  273. for ( int i = 0; i < morphs.Length; i++ )
  274. {
  275. morphs[i].SetAnim(at);
  276. }
  277. }
  278. }
  279. else
  280. {
  281. if ( morph )
  282. morph.SetAnim(at);
  283. }
  284. }
  285. }
  286. }
  287. }
  288. public bool MultipleMorphs = false;
  289. public bool LinkedUpdate = false;
  290. public bool PlayOnStart = true;
  291. Animation myanim;
  292. void DoLinkedUpdate()
  293. {
  294. if ( myanim == null )
  295. myanim = GetComponent<Animation>();
  296. if ( myanim != null )
  297. {
  298. foreach ( AnimationState state in myanim )
  299. {
  300. if ( state.enabled )
  301. {
  302. AnimationClip clip = state.clip;
  303. if ( clip != null )
  304. {
  305. for ( int i = 0; i < clips.Count; i++ )
  306. {
  307. if ( clips[i].name == clip.name )
  308. {
  309. current = i;
  310. float ct = state.time;
  311. WrapMode wm = clip.wrapMode;
  312. if ( wm == WrapMode.Default )
  313. {
  314. wm = myanim.wrapMode;
  315. }
  316. switch ( clip.wrapMode )
  317. {
  318. case WrapMode.Loop:
  319. ct = Mathf.Repeat(ct, clip.length);
  320. break;
  321. case WrapMode.PingPong:
  322. ct = Mathf.PingPong(ct, clip.length);
  323. break;
  324. case WrapMode.ClampForever:
  325. ct = Mathf.Clamp(ct, 0.0f, clip.length);
  326. break;
  327. case WrapMode.Once:
  328. if ( ct > clip.length )
  329. ct = 0.0f;
  330. break;
  331. }
  332. ct += clips[current].start;
  333. if ( MultipleMorphs )
  334. {
  335. if ( morphs != null )
  336. {
  337. for ( int m = 0; m < morphs.Length; m++ )
  338. {
  339. morphs[m].SetAnim(at);
  340. }
  341. }
  342. }
  343. else
  344. {
  345. if ( morph )
  346. morph.SetAnim(ct); //state.time + clips[current].start);
  347. }
  348. return;
  349. }
  350. }
  351. }
  352. }
  353. }
  354. }
  355. }
  356. }