MegaMorphOMaticEditor.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704
  1. 
  2. using UnityEngine;
  3. using UnityEditor;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using System;
  7. [CanEditMultipleObjects, CustomEditor(typeof(MegaMorphOMatic))]
  8. public class MegaMorphOMaticEditor : Editor
  9. {
  10. static string lastpath = " ";
  11. static public Color ChanCol1 = new Color(0.44f, 0.67f, 1.0f);
  12. static public Color ChanCol2 = new Color(1.0f, 0.67f, 0.44f);
  13. Stack<Color> bcol = new Stack<Color>();
  14. Stack<Color> ccol = new Stack<Color>();
  15. Stack<Color> col = new Stack<Color>();
  16. bool extraparams = false;
  17. bool showmodparams = false;
  18. bool showchannels = true;
  19. MegaMorphChan currentChan;
  20. MegaMorphTarget currentTarget;
  21. // Remove morph and pass tolerance then can morph to Utils
  22. // TODO: report error if target vert counts dont match base mapping
  23. bool DoMapping(MegaModifiers mod, MegaMorphOMatic morph, MegaTargetMesh tm, float scale, bool flipyz, bool negx)
  24. {
  25. for ( int i = 0; i < mod.verts.Length; i++ )
  26. {
  27. float a = (float)i / (float)mod.verts.Length;
  28. EditorUtility.DisplayProgressBar("Mapping", "Mapping vertex " + i, a);
  29. int map = MegaUtils.FindVert(mod.verts[i], tm.verts, morph.tolerance, scale, flipyz, negx, i);
  30. if ( map == -1 )
  31. {
  32. // Failed
  33. EditorUtility.ClearProgressBar();
  34. return false;
  35. }
  36. }
  37. EditorUtility.ClearProgressBar();
  38. return true;
  39. }
  40. void DisplayTarget(MegaMorphOMatic morph, MegaMorphChan channel, MegaMorphTarget mt, int num)
  41. {
  42. PushCols();
  43. EditorGUI.indentLevel = 1;
  44. mt.name = EditorGUILayout.TextField("Name", mt.name);
  45. //mt.percent = EditorGUILayout.Slider("Percent", mt.percent, 0.0f, 100.0f);
  46. mt.percent = EditorGUILayout.Slider("Percent", mt.percent, channel.mSpinmin, channel.mSpinmax); //.0f, 100.0f);
  47. EditorGUILayout.BeginHorizontal();
  48. if ( mt.points == null || mt.points.Length != morph.oPoints.Length )
  49. GUI.backgroundColor = new Color(0.5f, 0.5f, 0.5f);
  50. else
  51. GUI.backgroundColor = new Color(0.0f, 1.0f, 0.0f);
  52. GUI.backgroundColor = new Color(1.0f, 0.5f, 0.5f);
  53. EditorGUILayout.EndHorizontal();
  54. EditorGUI.indentLevel = 0;
  55. PopCols();
  56. }
  57. // These should be in EditorUtils
  58. void PushCols()
  59. {
  60. bcol.Push(GUI.backgroundColor);
  61. ccol.Push(GUI.contentColor);
  62. col.Push(GUI.color);
  63. }
  64. void PopCols()
  65. {
  66. GUI.backgroundColor = bcol.Pop();
  67. GUI.contentColor = ccol.Pop();
  68. GUI.color = col.Pop();
  69. }
  70. // This is common to other morpher
  71. void DisplayChannel(MegaMorphOMatic morph, MegaMorphChan channel)
  72. {
  73. if ( GUILayout.Button(channel.mName) )
  74. channel.showparams = !channel.showparams;
  75. GUI.backgroundColor = new Color(1, 1, 1);
  76. if ( channel.showparams )
  77. {
  78. channel.mName = EditorGUILayout.TextField("Name", channel.mName);
  79. if ( channel.mTargetCache != null && channel.mTargetCache.Count > 0 )
  80. {
  81. channel.mActiveOverride = EditorGUILayout.Toggle("Active", channel.mActiveOverride);
  82. channel.Percent = EditorGUILayout.Slider("Percent", channel.Percent, channel.mSpinmin, channel.mSpinmax); //.0f, 100.0f);
  83. channel.mCurvature = EditorGUILayout.FloatField("Tension", channel.mCurvature);
  84. }
  85. channel.mUseLimit = EditorGUILayout.Toggle("Use Limit", channel.mUseLimit);
  86. if ( channel.mUseLimit )
  87. {
  88. channel.mSpinmin = EditorGUILayout.FloatField("Min", channel.mSpinmin);
  89. channel.mSpinmax = EditorGUILayout.FloatField("Max", channel.mSpinmax);
  90. }
  91. EditorGUILayout.BeginHorizontal();
  92. PushCols();
  93. GUI.backgroundColor = new Color(0.5f, 0.5f, 0.5f);
  94. GUI.backgroundColor = new Color(1.5f, 0.5f, 0.5f);
  95. if ( GUILayout.Button("Delete Channel") )
  96. morph.chanBank.Remove(channel);
  97. EditorGUILayout.EndHorizontal();
  98. PopCols();
  99. if ( channel.mTargetCache != null && channel.mTargetCache.Count > 0 )
  100. {
  101. channel.showtargets = EditorGUILayout.Foldout(channel.showtargets, "Targets");
  102. if ( channel.showtargets )
  103. {
  104. if ( channel.mTargetCache != null )
  105. {
  106. for ( int i = 0; i < channel.mTargetCache.Count; i++ )
  107. DisplayTarget(morph, channel, channel.mTargetCache[i], i);
  108. }
  109. }
  110. }
  111. }
  112. else
  113. {
  114. if ( channel.mActiveOverride && channel.mTargetCache != null && channel.mTargetCache.Count > 0 )
  115. {
  116. channel.Percent = EditorGUILayout.Slider("Percent", channel.Percent, channel.mSpinmin, channel.mSpinmax); //.0f, 100.0f);
  117. }
  118. }
  119. }
  120. public override void OnInspectorGUI()
  121. {
  122. MegaMorphOMatic morph = (MegaMorphOMatic)target;
  123. PushCols();
  124. if ( GUILayout.Button("Import MorphOMatic File") )
  125. {
  126. LoadMorph();
  127. EditorUtility.SetDirty(target);
  128. }
  129. // Basic mod stuff
  130. showmodparams = EditorGUILayout.Foldout(showmodparams, "Modifier Common Params");
  131. if ( showmodparams )
  132. {
  133. morph.Label = EditorGUILayout.TextField("Label", morph.Label);
  134. morph.MaxLOD = EditorGUILayout.IntField("MaxLOD", morph.MaxLOD);
  135. morph.ModEnabled = EditorGUILayout.Toggle("Mod Enabled", morph.ModEnabled);
  136. morph.DisplayGizmo = EditorGUILayout.Toggle("Display Gizmo", morph.DisplayGizmo);
  137. morph.Order = EditorGUILayout.IntField("Order", morph.Order);
  138. morph.gizCol1 = EditorGUILayout.ColorField("Giz Col 1", morph.gizCol1);
  139. morph.gizCol2 = EditorGUILayout.ColorField("Giz Col 2", morph.gizCol2);
  140. }
  141. morph.animate = EditorGUILayout.Toggle("Animate", morph.animate);
  142. if ( morph.animate )
  143. {
  144. morph.animtime = EditorGUILayout.FloatField("AnimTime", morph.animtime);
  145. morph.looptime = EditorGUILayout.FloatField("LoopTime", morph.looptime);
  146. morph.speed = EditorGUILayout.FloatField("Speed", morph.speed);
  147. morph.repeatMode = (MegaRepeatMode)EditorGUILayout.EnumPopup("RepeatMode", morph.repeatMode);
  148. }
  149. EditorGUILayout.BeginHorizontal();
  150. PushCols();
  151. if ( morph.mapping == null || morph.mapping.Length == 0 )
  152. GUI.backgroundColor = Color.red;
  153. else
  154. GUI.backgroundColor = Color.green;
  155. PopCols();
  156. if ( GUILayout.Button("Add Channel") )
  157. {
  158. if ( morph.chanBank == null )
  159. morph.chanBank = new List<MegaMorphChan>();
  160. MegaMorphChan nc = new MegaMorphChan();
  161. nc.mName = "Empty";
  162. morph.chanBank.Add(nc);
  163. }
  164. EditorGUILayout.EndHorizontal();
  165. string bname = "Hide Channels";
  166. if ( !showchannels )
  167. bname = "Show Channels";
  168. if ( GUILayout.Button(bname) )
  169. showchannels = !showchannels;
  170. #if false
  171. if ( showchannels && morph.chanBank != null )
  172. {
  173. for ( int i = 0; i < morph.chanBank.Count; i++ )
  174. {
  175. PushCols();
  176. if ( (i & 1) == 0 )
  177. GUI.backgroundColor = ChanCol1;
  178. else
  179. GUI.backgroundColor = ChanCol2;
  180. DisplayChannel(morph, morph.chanBank[i]);
  181. PopCols();
  182. }
  183. }
  184. #else
  185. morph.limitchandisplay = EditorGUILayout.Toggle("Compact Display", morph.limitchandisplay);
  186. if ( showchannels && morph.chanBank != null )
  187. {
  188. if ( morph.limitchandisplay )
  189. {
  190. morph.startchannel = EditorGUILayout.IntField("Start", morph.startchannel);
  191. morph.displaychans = EditorGUILayout.IntField("Display", morph.displaychans);
  192. if ( morph.displaychans < 0 )
  193. morph.displaychans = 0;
  194. if ( morph.startchannel < 0 )
  195. morph.startchannel = 0;
  196. if ( morph.startchannel >= morph.chanBank.Count - 1 )
  197. morph.startchannel = morph.chanBank.Count - 1;
  198. int end = morph.startchannel + morph.displaychans;
  199. if ( end >= morph.chanBank.Count )
  200. end = morph.chanBank.Count;
  201. for ( int i = morph.startchannel; i < end; i++ )
  202. {
  203. PushCols();
  204. if ( (i & 1) == 0 )
  205. GUI.backgroundColor = ChanCol1;
  206. else
  207. GUI.backgroundColor = ChanCol2;
  208. DisplayChannel(morph, morph.chanBank[i]);
  209. PopCols();
  210. }
  211. }
  212. else
  213. {
  214. for ( int i = 0; i < morph.chanBank.Count; i++ )
  215. {
  216. PushCols();
  217. if ( (i & 1) == 0 )
  218. GUI.backgroundColor = ChanCol1;
  219. else
  220. GUI.backgroundColor = ChanCol2;
  221. DisplayChannel(morph, morph.chanBank[i]);
  222. PopCols();
  223. }
  224. }
  225. }
  226. #endif
  227. extraparams = EditorGUILayout.Foldout(extraparams, "Extra Params");
  228. if ( extraparams )
  229. {
  230. ChanCol1 = EditorGUILayout.ColorField("Channel Col 1", ChanCol1);
  231. ChanCol2 = EditorGUILayout.ColorField("Channel Col 2", ChanCol2);
  232. }
  233. PopCols();
  234. if ( GUI.changed )
  235. EditorUtility.SetDirty(target);
  236. }
  237. public void ParseFile(String assetpath, ParseClassCallbackType cb)
  238. {
  239. FileStream fs = new FileStream(assetpath, FileMode.Open, FileAccess.Read, System.IO.FileShare.Read);
  240. BinaryReader br = new BinaryReader(fs);
  241. bool processing = true;
  242. while ( processing )
  243. {
  244. string classname = MegaParse.ReadString(br);
  245. if ( classname == "Done" )
  246. break;
  247. int chunkoff = br.ReadInt32();
  248. long fpos = fs.Position;
  249. cb(classname, br);
  250. fs.Position = fpos + chunkoff;
  251. }
  252. br.Close();
  253. }
  254. void MorphCallback(string classname, BinaryReader br)
  255. {
  256. switch ( classname )
  257. {
  258. case "Morph": LoadMorph(br); break;
  259. }
  260. }
  261. void LoadMorph()
  262. {
  263. MegaMorphOMatic mr = (MegaMorphOMatic)target;
  264. string filename = EditorUtility.OpenFilePanel("Morph-O-Matic Morph File", lastpath, "mmf");
  265. if ( filename == null || filename.Length < 1 )
  266. return;
  267. lastpath = filename;
  268. // Clear what we have
  269. mr.chanBank.Clear();
  270. ParseFile(filename, MorphCallback);
  271. mr.animate = false;
  272. float looptime = 0.0f;
  273. // Set Looptime and animate if there is an anim
  274. for ( int i = 0; i < mr.chanBank.Count; i++ )
  275. {
  276. MegaMorphChan mc = mr.chanBank[i];
  277. if ( mc.control != null )
  278. {
  279. mr.animate = true;
  280. float t = mc.control.Times[mc.control.Times.Length - 1];
  281. if ( t > looptime )
  282. looptime = t;
  283. }
  284. }
  285. if ( mr.animate )
  286. mr.looptime = looptime;
  287. BuildData();
  288. }
  289. public void LoadMorph(BinaryReader br)
  290. {
  291. MegaParse.Parse(br, ParseMorph);
  292. }
  293. bool AnimCallback(BinaryReader br, string id)
  294. {
  295. MegaMorphOMatic mr = (MegaMorphOMatic)target;
  296. switch ( id )
  297. {
  298. case "Chan":
  299. int cn = br.ReadInt32();
  300. currentChan = mr.chanBank[cn]; break;
  301. case "Anim": currentChan.control = LoadAnim(br); break;
  302. default: return false;
  303. }
  304. return true;
  305. }
  306. void LoadAnimation(MegaMorphOMatic mr, BinaryReader br)
  307. {
  308. MegaParse.Parse(br, AnimCallback);
  309. }
  310. // Fbx could have been exported any which way so still need to do try all mappings to find correct
  311. public bool ParseMorph(BinaryReader br, string id)
  312. {
  313. MegaMorphOMatic mr = (MegaMorphOMatic)target;
  314. switch ( id )
  315. {
  316. case "Max": mr.Max = br.ReadSingle(); break;
  317. case "Min": mr.Min = br.ReadSingle(); break;
  318. case "UseLim": mr.UseLimit = (br.ReadInt32() == 1); break;
  319. // This will only be changed points, but we need scale
  320. case "StartPoints": // Mapping
  321. MegaTargetMesh tm = new MegaTargetMesh();
  322. tm.verts = MegaParse.ReadP3l(br); // make a vector
  323. if ( !TryMapping1(tm, mr) )
  324. {
  325. EditorUtility.DisplayDialog("Mapping Failed!", "Mapping failed!", "OK");
  326. EditorUtility.ClearProgressBar();
  327. return false;
  328. }
  329. break;
  330. case "Channel": mr.chanBank.Add(LoadChan(br)); break;
  331. case "Animation": LoadAnimation(mr, br); break;
  332. default: return false;
  333. }
  334. return true;
  335. }
  336. public MegaMorphChan LoadChan(BinaryReader br)
  337. {
  338. MegaMorphChan chan = new MegaMorphChan();
  339. chan.control = null;
  340. chan.showparams = false;
  341. chan.mTargetCache = new List<MegaMorphTarget>();
  342. currentChan = chan;
  343. MegaParse.Parse(br, ParseChan);
  344. return chan;
  345. }
  346. public static MegaBezFloatKeyControl LoadAnim(BinaryReader br)
  347. {
  348. //MegaBezFloatKeyControl con = new MegaBezFloatKeyControl();
  349. //MegaParse.Parse(br, con.Parse);
  350. //return con;
  351. return MegaParseBezFloatControl.LoadBezFloatKeyControl(br);
  352. }
  353. public bool ParseChan(BinaryReader br, string id)
  354. {
  355. switch ( id )
  356. {
  357. case "Target": currentChan.mTargetCache.Add(LoadTarget(br)); break;
  358. case "Name": currentChan.mName = MegaParse.ReadString(br); break;
  359. case "Percent": currentChan.Percent = br.ReadSingle(); break;
  360. case "SpinMax": currentChan.mSpinmax = br.ReadSingle(); break;
  361. case "SpinMin": currentChan.mSpinmin = br.ReadSingle(); break;
  362. case "UseLim": currentChan.mUseLimit = (br.ReadInt32() == 1); break;
  363. case "Override": currentChan.mActiveOverride = (br.ReadInt32() == 1); break;
  364. case "Curve": currentChan.mCurvature = br.ReadSingle(); break;
  365. }
  366. return true;
  367. }
  368. Vector3 ConvertPoint(Vector3 v)
  369. {
  370. MegaMorphOMatic mr = (MegaMorphOMatic)target;
  371. Vector3 p = v * mr.importScale;
  372. if ( mr.negx )
  373. p.x = -p.x;
  374. if ( mr.flipyz )
  375. {
  376. float y = p.y;
  377. p.y = p.z;
  378. p.z = y;
  379. }
  380. return p;
  381. }
  382. public bool ParseTarget(BinaryReader br, string id)
  383. {
  384. switch ( id )
  385. {
  386. case "Name": currentTarget.name = MegaParse.ReadString(br); break;
  387. case "Percent": currentTarget.percent = br.ReadSingle(); break;
  388. case "MoPoints":
  389. int count = br.ReadInt32();
  390. if ( count > 0 )
  391. {
  392. currentTarget.loadpoints = new MOPoint[count];
  393. for ( int i = 0; i < count; i++ )
  394. {
  395. MOPoint p = new MOPoint();
  396. p.id = br.ReadInt32(); // we need to find the ids for this point (could be more than one)
  397. p.p = ConvertPoint(MegaParse.ReadP3(br));
  398. p.w = br.ReadSingle();
  399. currentTarget.loadpoints[i] = p;
  400. }
  401. }
  402. break;
  403. }
  404. return true;
  405. }
  406. public MegaMorphTarget LoadTarget(BinaryReader br)
  407. {
  408. MegaMorphTarget target = new MegaMorphTarget();
  409. currentTarget = target;
  410. MegaParse.Parse(br, ParseTarget);
  411. return target;
  412. }
  413. // We should know the mapping
  414. // remove morph pass tolerance instead
  415. bool TryMapping1(MegaTargetMesh tm, MegaMorphOMatic morph)
  416. {
  417. MegaModifiers mod = morph.GetComponent<MegaModifiers>();
  418. if ( mod == null )
  419. {
  420. EditorUtility.DisplayDialog("Missing ModifyObject!", "No ModifyObject script found on the object", "OK");
  421. return false;
  422. }
  423. // Get extents for mod verts and for imported meshes, if not the same then scale
  424. Vector3 min1,max1;
  425. Vector3 min2,max2;
  426. Vector3 ex1 = MegaUtils.Extents(mod.verts, out min1, out max1);
  427. Vector3 ex2 = MegaUtils.Extents(tm.verts, out min2, out max2);
  428. // need min max on all axis so we can produce an offset to add
  429. float d1 = ex1.x;
  430. float d2 = ex2.x;
  431. float scl = d1 / d2; //d2 / d1;
  432. bool flipyz = false;
  433. bool negx = false;
  434. // So try to match first vert using autoscale and no flip
  435. bool mapped = DoMapping(mod, morph, tm, scl, flipyz, negx);
  436. if ( !mapped )
  437. {
  438. flipyz = true;
  439. mapped = DoMapping(mod, morph, tm, scl, flipyz, negx);
  440. if ( !mapped ) //DoMapping(mod, morph, tm, mapping, scl, flipyz, negx) )
  441. {
  442. flipyz = false;
  443. negx = true;
  444. mapped = DoMapping(mod, morph, tm, scl, flipyz, negx);
  445. if ( !mapped )
  446. {
  447. flipyz = true;
  448. mapped = DoMapping(mod, morph, tm, scl, flipyz, negx);
  449. }
  450. }
  451. }
  452. if ( mapped )
  453. {
  454. morph.importScale = scl;
  455. morph.flipyz = flipyz;
  456. morph.negx = negx;
  457. // if mapping was ok set opoints
  458. morph.oPoints = tm.verts.ToArray();
  459. for ( int i = 0; i < morph.oPoints.Length; i++ )
  460. {
  461. Vector3 p = morph.oPoints[i];
  462. if ( negx )
  463. p.x = -p.x;
  464. if ( flipyz )
  465. {
  466. float z = p.z;
  467. p.z = p.y;
  468. p.y = z;
  469. }
  470. morph.oPoints[i] = p * morph.importScale;
  471. }
  472. morph.mapping = new MegaMomVertMap[morph.oPoints.Length];
  473. for ( int i = 0; i < morph.oPoints.Length; i++ )
  474. {
  475. //int[] indices = morph.FindVerts(morph.oPoints[i], mod);
  476. int[] indices = FindVerts(morph.oPoints[i], mod);
  477. morph.mapping[i] = new MegaMomVertMap();
  478. morph.mapping[i].indices = indices; //morph.FindVerts(morph.oPoints[i], mod);
  479. }
  480. return true;
  481. }
  482. return false;
  483. }
  484. bool GetDelta(MegaMorphTarget targ, int v, out Vector3 delta, out float w)
  485. {
  486. MegaMorphOMatic mod = (MegaMorphOMatic)target;
  487. if ( targ.loadpoints != null )
  488. {
  489. for ( int i = 0; i < targ.loadpoints.Length; i++ )
  490. {
  491. int id = targ.loadpoints[i].id;
  492. if ( id == v )
  493. {
  494. delta = targ.loadpoints[i].p - mod.oPoints[id];
  495. w = targ.loadpoints[i].w;
  496. return true;
  497. }
  498. }
  499. }
  500. delta = Vector3.zero;
  501. w = 0.0f;
  502. return false;
  503. }
  504. public int[] FindVerts(Vector3 p, MegaModifiers mods)
  505. {
  506. List<int> indices = new List<int>();
  507. for ( int i = 0; i < mods.verts.Length; i++ )
  508. {
  509. float dist = Vector3.Distance(p, mods.verts[i]);
  510. if ( dist < 0.0001f ) //mods.verts[i].Equals(p) )
  511. indices.Add(i);
  512. }
  513. return indices.ToArray();
  514. }
  515. // Build the morphing data
  516. // each target holds only the points that differe from the base so need to build table showing for each
  517. // target the points that differ
  518. public void BuildData()
  519. {
  520. MegaMorphOMatic mod = (MegaMorphOMatic)target;
  521. List<MOMVert> verts = new List<MOMVert>();
  522. for ( int c = 0; c < mod.chanBank.Count; c++ )
  523. {
  524. MegaMorphChan chan = mod.chanBank[c];
  525. int maxverts = 0;
  526. for ( int t = 0; t < chan.mTargetCache.Count - 1; t++ )
  527. {
  528. MegaMorphTarget targ = chan.mTargetCache[t];
  529. MegaMorphTarget targ1 = chan.mTargetCache[t + 1];
  530. // if t is 0 then just use the points
  531. Vector3 delta = Vector3.zero;
  532. Vector3 delta1 = Vector3.zero;
  533. float w = 1.0f;
  534. verts.Clear();
  535. for ( int v = 0; v < mod.oPoints.Length; v++ )
  536. {
  537. bool t1 = GetDelta(targ, v, out delta, out w);
  538. bool t2 = GetDelta(targ1, v, out delta1, out w);
  539. if ( t1 || t2 ) //GetDelta(targ, v, out delta, out w) || GetDelta(targ1, v, out delta1, out w) )
  540. {
  541. MOMVert vert = new MOMVert();
  542. vert.id = v;
  543. vert.w = w;
  544. vert.start = delta;
  545. vert.delta = delta1 - delta;
  546. verts.Add(vert);
  547. }
  548. }
  549. if ( verts.Count > maxverts )
  550. maxverts = verts.Count;
  551. if ( verts.Count > 0 )
  552. targ.mompoints = verts.ToArray();
  553. }
  554. for ( int t = 0; t < chan.mTargetCache.Count; t++ )
  555. chan.mTargetCache[t].loadpoints = null;
  556. chan.diff = new Vector3[maxverts];
  557. }
  558. }
  559. }