123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704 |
-
- using UnityEngine;
- using UnityEditor;
- using System.Collections.Generic;
- using System.IO;
- using System;
- [CanEditMultipleObjects, CustomEditor(typeof(MegaMorphOMatic))]
- public class MegaMorphOMaticEditor : Editor
- {
- static string lastpath = " ";
- static public Color ChanCol1 = new Color(0.44f, 0.67f, 1.0f);
- static public Color ChanCol2 = new Color(1.0f, 0.67f, 0.44f);
- Stack<Color> bcol = new Stack<Color>();
- Stack<Color> ccol = new Stack<Color>();
- Stack<Color> col = new Stack<Color>();
- bool extraparams = false;
- bool showmodparams = false;
- bool showchannels = true;
- MegaMorphChan currentChan;
- MegaMorphTarget currentTarget;
- // Remove morph and pass tolerance then can morph to Utils
- // TODO: report error if target vert counts dont match base mapping
- bool DoMapping(MegaModifiers mod, MegaMorphOMatic morph, MegaTargetMesh tm, float scale, bool flipyz, bool negx)
- {
- for ( int i = 0; i < mod.verts.Length; i++ )
- {
- float a = (float)i / (float)mod.verts.Length;
- EditorUtility.DisplayProgressBar("Mapping", "Mapping vertex " + i, a);
- int map = MegaUtils.FindVert(mod.verts[i], tm.verts, morph.tolerance, scale, flipyz, negx, i);
- if ( map == -1 )
- {
- // Failed
- EditorUtility.ClearProgressBar();
- return false;
- }
- }
- EditorUtility.ClearProgressBar();
- return true;
- }
- void DisplayTarget(MegaMorphOMatic morph, MegaMorphChan channel, MegaMorphTarget mt, int num)
- {
- PushCols();
- EditorGUI.indentLevel = 1;
- mt.name = EditorGUILayout.TextField("Name", mt.name);
- //mt.percent = EditorGUILayout.Slider("Percent", mt.percent, 0.0f, 100.0f);
- mt.percent = EditorGUILayout.Slider("Percent", mt.percent, channel.mSpinmin, channel.mSpinmax); //.0f, 100.0f);
- EditorGUILayout.BeginHorizontal();
- if ( mt.points == null || mt.points.Length != morph.oPoints.Length )
- GUI.backgroundColor = new Color(0.5f, 0.5f, 0.5f);
- else
- GUI.backgroundColor = new Color(0.0f, 1.0f, 0.0f);
- GUI.backgroundColor = new Color(1.0f, 0.5f, 0.5f);
- EditorGUILayout.EndHorizontal();
- EditorGUI.indentLevel = 0;
- PopCols();
- }
- // These should be in EditorUtils
- void PushCols()
- {
- bcol.Push(GUI.backgroundColor);
- ccol.Push(GUI.contentColor);
- col.Push(GUI.color);
- }
- void PopCols()
- {
- GUI.backgroundColor = bcol.Pop();
- GUI.contentColor = ccol.Pop();
- GUI.color = col.Pop();
- }
- // This is common to other morpher
- void DisplayChannel(MegaMorphOMatic morph, MegaMorphChan channel)
- {
- if ( GUILayout.Button(channel.mName) )
- channel.showparams = !channel.showparams;
- GUI.backgroundColor = new Color(1, 1, 1);
- if ( channel.showparams )
- {
- channel.mName = EditorGUILayout.TextField("Name", channel.mName);
- if ( channel.mTargetCache != null && channel.mTargetCache.Count > 0 )
- {
- channel.mActiveOverride = EditorGUILayout.Toggle("Active", channel.mActiveOverride);
- channel.Percent = EditorGUILayout.Slider("Percent", channel.Percent, channel.mSpinmin, channel.mSpinmax); //.0f, 100.0f);
- channel.mCurvature = EditorGUILayout.FloatField("Tension", channel.mCurvature);
- }
- channel.mUseLimit = EditorGUILayout.Toggle("Use Limit", channel.mUseLimit);
- if ( channel.mUseLimit )
- {
- channel.mSpinmin = EditorGUILayout.FloatField("Min", channel.mSpinmin);
- channel.mSpinmax = EditorGUILayout.FloatField("Max", channel.mSpinmax);
- }
- EditorGUILayout.BeginHorizontal();
- PushCols();
- GUI.backgroundColor = new Color(0.5f, 0.5f, 0.5f);
- GUI.backgroundColor = new Color(1.5f, 0.5f, 0.5f);
- if ( GUILayout.Button("Delete Channel") )
- morph.chanBank.Remove(channel);
- EditorGUILayout.EndHorizontal();
- PopCols();
- if ( channel.mTargetCache != null && channel.mTargetCache.Count > 0 )
- {
- channel.showtargets = EditorGUILayout.Foldout(channel.showtargets, "Targets");
- if ( channel.showtargets )
- {
- if ( channel.mTargetCache != null )
- {
- for ( int i = 0; i < channel.mTargetCache.Count; i++ )
- DisplayTarget(morph, channel, channel.mTargetCache[i], i);
- }
- }
- }
- }
- else
- {
- if ( channel.mActiveOverride && channel.mTargetCache != null && channel.mTargetCache.Count > 0 )
- {
- channel.Percent = EditorGUILayout.Slider("Percent", channel.Percent, channel.mSpinmin, channel.mSpinmax); //.0f, 100.0f);
- }
- }
- }
- public override void OnInspectorGUI()
- {
- MegaMorphOMatic morph = (MegaMorphOMatic)target;
- PushCols();
- if ( GUILayout.Button("Import MorphOMatic File") )
- {
- LoadMorph();
- EditorUtility.SetDirty(target);
- }
- // Basic mod stuff
- showmodparams = EditorGUILayout.Foldout(showmodparams, "Modifier Common Params");
- if ( showmodparams )
- {
- morph.Label = EditorGUILayout.TextField("Label", morph.Label);
- morph.MaxLOD = EditorGUILayout.IntField("MaxLOD", morph.MaxLOD);
- morph.ModEnabled = EditorGUILayout.Toggle("Mod Enabled", morph.ModEnabled);
- morph.DisplayGizmo = EditorGUILayout.Toggle("Display Gizmo", morph.DisplayGizmo);
- morph.Order = EditorGUILayout.IntField("Order", morph.Order);
- morph.gizCol1 = EditorGUILayout.ColorField("Giz Col 1", morph.gizCol1);
- morph.gizCol2 = EditorGUILayout.ColorField("Giz Col 2", morph.gizCol2);
- }
- morph.animate = EditorGUILayout.Toggle("Animate", morph.animate);
- if ( morph.animate )
- {
- morph.animtime = EditorGUILayout.FloatField("AnimTime", morph.animtime);
- morph.looptime = EditorGUILayout.FloatField("LoopTime", morph.looptime);
- morph.speed = EditorGUILayout.FloatField("Speed", morph.speed);
- morph.repeatMode = (MegaRepeatMode)EditorGUILayout.EnumPopup("RepeatMode", morph.repeatMode);
- }
- EditorGUILayout.BeginHorizontal();
- PushCols();
- if ( morph.mapping == null || morph.mapping.Length == 0 )
- GUI.backgroundColor = Color.red;
- else
- GUI.backgroundColor = Color.green;
- PopCols();
- if ( GUILayout.Button("Add Channel") )
- {
- if ( morph.chanBank == null )
- morph.chanBank = new List<MegaMorphChan>();
- MegaMorphChan nc = new MegaMorphChan();
- nc.mName = "Empty";
- morph.chanBank.Add(nc);
- }
- EditorGUILayout.EndHorizontal();
- string bname = "Hide Channels";
- if ( !showchannels )
- bname = "Show Channels";
- if ( GUILayout.Button(bname) )
- showchannels = !showchannels;
- #if false
- if ( showchannels && morph.chanBank != null )
- {
- for ( int i = 0; i < morph.chanBank.Count; i++ )
- {
- PushCols();
- if ( (i & 1) == 0 )
- GUI.backgroundColor = ChanCol1;
- else
- GUI.backgroundColor = ChanCol2;
- DisplayChannel(morph, morph.chanBank[i]);
- PopCols();
- }
- }
- #else
- morph.limitchandisplay = EditorGUILayout.Toggle("Compact Display", morph.limitchandisplay);
- if ( showchannels && morph.chanBank != null )
- {
- if ( morph.limitchandisplay )
- {
- morph.startchannel = EditorGUILayout.IntField("Start", morph.startchannel);
- morph.displaychans = EditorGUILayout.IntField("Display", morph.displaychans);
- if ( morph.displaychans < 0 )
- morph.displaychans = 0;
- if ( morph.startchannel < 0 )
- morph.startchannel = 0;
- if ( morph.startchannel >= morph.chanBank.Count - 1 )
- morph.startchannel = morph.chanBank.Count - 1;
- int end = morph.startchannel + morph.displaychans;
- if ( end >= morph.chanBank.Count )
- end = morph.chanBank.Count;
- for ( int i = morph.startchannel; i < end; i++ )
- {
- PushCols();
- if ( (i & 1) == 0 )
- GUI.backgroundColor = ChanCol1;
- else
- GUI.backgroundColor = ChanCol2;
- DisplayChannel(morph, morph.chanBank[i]);
- PopCols();
- }
- }
- else
- {
- for ( int i = 0; i < morph.chanBank.Count; i++ )
- {
- PushCols();
- if ( (i & 1) == 0 )
- GUI.backgroundColor = ChanCol1;
- else
- GUI.backgroundColor = ChanCol2;
- DisplayChannel(morph, morph.chanBank[i]);
- PopCols();
- }
- }
- }
- #endif
- extraparams = EditorGUILayout.Foldout(extraparams, "Extra Params");
- if ( extraparams )
- {
- ChanCol1 = EditorGUILayout.ColorField("Channel Col 1", ChanCol1);
- ChanCol2 = EditorGUILayout.ColorField("Channel Col 2", ChanCol2);
- }
- PopCols();
- if ( GUI.changed )
- EditorUtility.SetDirty(target);
- }
- public void ParseFile(String assetpath, ParseClassCallbackType cb)
- {
- FileStream fs = new FileStream(assetpath, FileMode.Open, FileAccess.Read, System.IO.FileShare.Read);
- BinaryReader br = new BinaryReader(fs);
- bool processing = true;
- while ( processing )
- {
- string classname = MegaParse.ReadString(br);
- if ( classname == "Done" )
- break;
- int chunkoff = br.ReadInt32();
- long fpos = fs.Position;
- cb(classname, br);
- fs.Position = fpos + chunkoff;
- }
- br.Close();
- }
- void MorphCallback(string classname, BinaryReader br)
- {
- switch ( classname )
- {
- case "Morph": LoadMorph(br); break;
- }
- }
- void LoadMorph()
- {
- MegaMorphOMatic mr = (MegaMorphOMatic)target;
- string filename = EditorUtility.OpenFilePanel("Morph-O-Matic Morph File", lastpath, "mmf");
- if ( filename == null || filename.Length < 1 )
- return;
- lastpath = filename;
- // Clear what we have
- mr.chanBank.Clear();
- ParseFile(filename, MorphCallback);
- mr.animate = false;
- float looptime = 0.0f;
- // Set Looptime and animate if there is an anim
- for ( int i = 0; i < mr.chanBank.Count; i++ )
- {
- MegaMorphChan mc = mr.chanBank[i];
- if ( mc.control != null )
- {
- mr.animate = true;
- float t = mc.control.Times[mc.control.Times.Length - 1];
- if ( t > looptime )
- looptime = t;
- }
- }
- if ( mr.animate )
- mr.looptime = looptime;
- BuildData();
- }
- public void LoadMorph(BinaryReader br)
- {
- MegaParse.Parse(br, ParseMorph);
- }
- bool AnimCallback(BinaryReader br, string id)
- {
- MegaMorphOMatic mr = (MegaMorphOMatic)target;
- switch ( id )
- {
- case "Chan":
- int cn = br.ReadInt32();
- currentChan = mr.chanBank[cn]; break;
- case "Anim": currentChan.control = LoadAnim(br); break;
- default: return false;
- }
- return true;
- }
- void LoadAnimation(MegaMorphOMatic mr, BinaryReader br)
- {
- MegaParse.Parse(br, AnimCallback);
- }
- // Fbx could have been exported any which way so still need to do try all mappings to find correct
- public bool ParseMorph(BinaryReader br, string id)
- {
- MegaMorphOMatic mr = (MegaMorphOMatic)target;
- switch ( id )
- {
- case "Max": mr.Max = br.ReadSingle(); break;
- case "Min": mr.Min = br.ReadSingle(); break;
- case "UseLim": mr.UseLimit = (br.ReadInt32() == 1); break;
- // This will only be changed points, but we need scale
- case "StartPoints": // Mapping
- MegaTargetMesh tm = new MegaTargetMesh();
- tm.verts = MegaParse.ReadP3l(br); // make a vector
- if ( !TryMapping1(tm, mr) )
- {
- EditorUtility.DisplayDialog("Mapping Failed!", "Mapping failed!", "OK");
- EditorUtility.ClearProgressBar();
- return false;
- }
- break;
- case "Channel": mr.chanBank.Add(LoadChan(br)); break;
- case "Animation": LoadAnimation(mr, br); break;
- default: return false;
- }
- return true;
- }
- public MegaMorphChan LoadChan(BinaryReader br)
- {
- MegaMorphChan chan = new MegaMorphChan();
- chan.control = null;
- chan.showparams = false;
- chan.mTargetCache = new List<MegaMorphTarget>();
- currentChan = chan;
- MegaParse.Parse(br, ParseChan);
- return chan;
- }
- public static MegaBezFloatKeyControl LoadAnim(BinaryReader br)
- {
- //MegaBezFloatKeyControl con = new MegaBezFloatKeyControl();
- //MegaParse.Parse(br, con.Parse);
- //return con;
- return MegaParseBezFloatControl.LoadBezFloatKeyControl(br);
- }
- public bool ParseChan(BinaryReader br, string id)
- {
- switch ( id )
- {
- case "Target": currentChan.mTargetCache.Add(LoadTarget(br)); break;
- case "Name": currentChan.mName = MegaParse.ReadString(br); break;
- case "Percent": currentChan.Percent = br.ReadSingle(); break;
- case "SpinMax": currentChan.mSpinmax = br.ReadSingle(); break;
- case "SpinMin": currentChan.mSpinmin = br.ReadSingle(); break;
- case "UseLim": currentChan.mUseLimit = (br.ReadInt32() == 1); break;
- case "Override": currentChan.mActiveOverride = (br.ReadInt32() == 1); break;
- case "Curve": currentChan.mCurvature = br.ReadSingle(); break;
- }
- return true;
- }
- Vector3 ConvertPoint(Vector3 v)
- {
- MegaMorphOMatic mr = (MegaMorphOMatic)target;
- Vector3 p = v * mr.importScale;
- if ( mr.negx )
- p.x = -p.x;
- if ( mr.flipyz )
- {
- float y = p.y;
- p.y = p.z;
- p.z = y;
- }
- return p;
- }
- public bool ParseTarget(BinaryReader br, string id)
- {
- switch ( id )
- {
- case "Name": currentTarget.name = MegaParse.ReadString(br); break;
- case "Percent": currentTarget.percent = br.ReadSingle(); break;
- case "MoPoints":
- int count = br.ReadInt32();
- if ( count > 0 )
- {
- currentTarget.loadpoints = new MOPoint[count];
- for ( int i = 0; i < count; i++ )
- {
- MOPoint p = new MOPoint();
- p.id = br.ReadInt32(); // we need to find the ids for this point (could be more than one)
- p.p = ConvertPoint(MegaParse.ReadP3(br));
- p.w = br.ReadSingle();
- currentTarget.loadpoints[i] = p;
- }
- }
- break;
- }
- return true;
- }
- public MegaMorphTarget LoadTarget(BinaryReader br)
- {
- MegaMorphTarget target = new MegaMorphTarget();
- currentTarget = target;
- MegaParse.Parse(br, ParseTarget);
- return target;
- }
- // We should know the mapping
- // remove morph pass tolerance instead
- bool TryMapping1(MegaTargetMesh tm, MegaMorphOMatic morph)
- {
- MegaModifiers mod = morph.GetComponent<MegaModifiers>();
- if ( mod == null )
- {
- EditorUtility.DisplayDialog("Missing ModifyObject!", "No ModifyObject script found on the object", "OK");
- return false;
- }
- // Get extents for mod verts and for imported meshes, if not the same then scale
- Vector3 min1,max1;
- Vector3 min2,max2;
- Vector3 ex1 = MegaUtils.Extents(mod.verts, out min1, out max1);
- Vector3 ex2 = MegaUtils.Extents(tm.verts, out min2, out max2);
- // need min max on all axis so we can produce an offset to add
- float d1 = ex1.x;
- float d2 = ex2.x;
- float scl = d1 / d2; //d2 / d1;
- bool flipyz = false;
- bool negx = false;
- // So try to match first vert using autoscale and no flip
- bool mapped = DoMapping(mod, morph, tm, scl, flipyz, negx);
- if ( !mapped )
- {
- flipyz = true;
- mapped = DoMapping(mod, morph, tm, scl, flipyz, negx);
- if ( !mapped ) //DoMapping(mod, morph, tm, mapping, scl, flipyz, negx) )
- {
- flipyz = false;
- negx = true;
- mapped = DoMapping(mod, morph, tm, scl, flipyz, negx);
- if ( !mapped )
- {
- flipyz = true;
- mapped = DoMapping(mod, morph, tm, scl, flipyz, negx);
- }
- }
- }
- if ( mapped )
- {
- morph.importScale = scl;
- morph.flipyz = flipyz;
- morph.negx = negx;
- // if mapping was ok set opoints
- morph.oPoints = tm.verts.ToArray();
- for ( int i = 0; i < morph.oPoints.Length; i++ )
- {
- Vector3 p = morph.oPoints[i];
- if ( negx )
- p.x = -p.x;
- if ( flipyz )
- {
- float z = p.z;
- p.z = p.y;
- p.y = z;
- }
- morph.oPoints[i] = p * morph.importScale;
- }
- morph.mapping = new MegaMomVertMap[morph.oPoints.Length];
- for ( int i = 0; i < morph.oPoints.Length; i++ )
- {
- //int[] indices = morph.FindVerts(morph.oPoints[i], mod);
- int[] indices = FindVerts(morph.oPoints[i], mod);
- morph.mapping[i] = new MegaMomVertMap();
- morph.mapping[i].indices = indices; //morph.FindVerts(morph.oPoints[i], mod);
- }
- return true;
- }
- return false;
- }
- bool GetDelta(MegaMorphTarget targ, int v, out Vector3 delta, out float w)
- {
- MegaMorphOMatic mod = (MegaMorphOMatic)target;
- if ( targ.loadpoints != null )
- {
- for ( int i = 0; i < targ.loadpoints.Length; i++ )
- {
- int id = targ.loadpoints[i].id;
- if ( id == v )
- {
- delta = targ.loadpoints[i].p - mod.oPoints[id];
- w = targ.loadpoints[i].w;
- return true;
- }
- }
- }
- delta = Vector3.zero;
- w = 0.0f;
- return false;
- }
- public int[] FindVerts(Vector3 p, MegaModifiers mods)
- {
- List<int> indices = new List<int>();
- for ( int i = 0; i < mods.verts.Length; i++ )
- {
- float dist = Vector3.Distance(p, mods.verts[i]);
- if ( dist < 0.0001f ) //mods.verts[i].Equals(p) )
- indices.Add(i);
- }
- return indices.ToArray();
- }
- // Build the morphing data
- // each target holds only the points that differe from the base so need to build table showing for each
- // target the points that differ
- public void BuildData()
- {
- MegaMorphOMatic mod = (MegaMorphOMatic)target;
- List<MOMVert> verts = new List<MOMVert>();
- for ( int c = 0; c < mod.chanBank.Count; c++ )
- {
- MegaMorphChan chan = mod.chanBank[c];
- int maxverts = 0;
- for ( int t = 0; t < chan.mTargetCache.Count - 1; t++ )
- {
- MegaMorphTarget targ = chan.mTargetCache[t];
- MegaMorphTarget targ1 = chan.mTargetCache[t + 1];
- // if t is 0 then just use the points
- Vector3 delta = Vector3.zero;
- Vector3 delta1 = Vector3.zero;
- float w = 1.0f;
- verts.Clear();
- for ( int v = 0; v < mod.oPoints.Length; v++ )
- {
- bool t1 = GetDelta(targ, v, out delta, out w);
- bool t2 = GetDelta(targ1, v, out delta1, out w);
- if ( t1 || t2 ) //GetDelta(targ, v, out delta, out w) || GetDelta(targ1, v, out delta1, out w) )
- {
- MOMVert vert = new MOMVert();
- vert.id = v;
- vert.w = w;
- vert.start = delta;
- vert.delta = delta1 - delta;
- verts.Add(vert);
- }
- }
- if ( verts.Count > maxverts )
- maxverts = verts.Count;
- if ( verts.Count > 0 )
- targ.mompoints = verts.ToArray();
- }
- for ( int t = 0; t < chan.mTargetCache.Count; t++ )
- chan.mTargetCache[t].loadpoints = null;
- chan.diff = new Vector3[maxverts];
- }
- }
- }
|