MorphSelectUI CreateMorphSelector()
        {
            MorphSelectUI morphSelect = new MorphSelectUI(this);

            morphSelectors.Add(morphSelect);
            RegenerateFooter();

            CancelDeleteConfirmation();
            return(morphSelect);
        }
 public void OnMorphSelectorRemoved(MorphSelectUI selector)
 {
     morphSelectors.Remove(selector);
 }
        public override void Init()
        {
            try
            {
                PATH_WHEN_LOADED = SuperController.singleton.currentLoadDir;

                SuperController sc = SuperController.singleton;

                CreateButton("New").button.onClick.AddListener(() =>
                {
                    audioChoice.SetVal("");
                    RemoveAllSteps();
                    RemoveAllSelectors();
                    CreateStep(0);
                    CreateStep(1);
                    playback.SetVal(0);
                    totalDuration.SetVal(totalDuration.defaultVal);
                });

                CreateButton("Save").button.onClick.AddListener(() =>
                {
                    if (steps.Count <= 0)
                    {
                        return;
                    }

                    List <ExpressionKeyframe> keyframes = steps.Select((step) => step.ToKeyFrame()).ToList();

                    string audioUID = "";
                    if (currentClip != null)
                    {
                        audioUID = currentClip.uid;
                    }

                    ExpressionAnimation animation = new ExpressionAnimation()
                    {
                        audio     = audioUID,
                        duration  = totalDuration.val,
                        keyframes = keyframes
                    };

                    JSONNode json = animation.GetJSON();
                    //Debug.Log(json.ToString());

                    //sc.activeUI = SuperController.ActiveUI.None;
                    sc.fileBrowserUI.defaultPath = PATH_WHEN_LOADED;
                    sc.fileBrowserUI.SetTextEntry(true);

                    sc.fileBrowserUI.Show((path) =>
                    {
                        //  cancel or invalid
                        if (string.IsNullOrEmpty(path))
                        {
                            return;
                        }

                        //  ensure extension
                        if (!path.EndsWith(".json"))
                        {
                            path += ".json";
                        }

                        sc.SaveStringIntoFile(path, json.ToString(""));
                        SuperController.LogMessage("Wrote expression file: " + path);
                    });

                    //  set default filename
                    if (sc.fileBrowserUI.fileEntryField != null)
                    {
                        sc.fileBrowserUI.fileEntryField.text = currentClip.uid + ".json";
                        sc.fileBrowserUI.ActivateFileNameField();
                    }
                });
                CreateSpacer().height = 12;

                CreateButton("Load", true).button.onClick.AddListener(() =>
                {
                    sc.fileBrowserUI.defaultPath = PATH_WHEN_LOADED;
                    sc.fileBrowserUI.SetTextEntry(false);
                    sc.fileBrowserUI.Show((path) =>
                    {
                        if (string.IsNullOrEmpty(path))
                        {
                            return;
                        }

                        string jsonString = sc.ReadFileIntoString(path);

                        /*
                         * Example:
                         *
                         * {
                         * "audio" : "holding it 1.mp3",
                         * "keyframes" : [
                         *    {
                         *       "time" : "0",
                         *       "Brow Down" : "0"
                         *    },
                         *    {
                         *       "time" : "1",
                         *       "Brow Down" : "1"
                         *    }
                         * ]
                         * }
                         *
                         */

                        JSONClass jsc = JSON.Parse(jsonString).AsObject;


                        string clipId = jsc["audio"].Value;

                        //  validate this audio clip exists
                        NamedAudioClip nac = URLAudioClipManager.singleton.GetClip(clipId);
                        if (nac == null)
                        {
                            //SuperController.LogError("Clip " + clipId + " is not loaded to scene. Add it first.");
                            //return;
                        }

                        audioChoice.SetVal(jsc["audio"].Value);
                        totalDuration.SetVal(jsc["duration"].AsFloat);

                        RemoveAllSteps();
                        RemoveAllSelectors();

                        JSONArray keyframes = jsc["keyframes"].AsArray;

                        HashSet <DAZMorph> morphSet             = new HashSet <DAZMorph>();
                        GenerateDAZMorphsControlUI morphControl = GetMorphControl();

                        for (int i = 0; i < keyframes.Count; i++)
                        {
                            JSONClass keyframe = keyframes[i].AsObject;
                            float time         = keyframe["time"].AsFloat;

                            ExpressionStep step = CreateStep(time);

                            keyframe.Keys.ToList().ForEach((key =>
                            {
                                if (key == "time")
                                {
                                    return;
                                }

                                string morphName = key;

                                DAZMorph morph = morphControl.GetMorphByDisplayName(morphName);
                                if (morph == null)
                                {
                                    SuperController.LogError("Expression has a morph not imported: " + morphName);
                                    return;
                                }

                                if (morphSet.Contains(morph) == false)
                                {
                                    morphSet.Add(morph);
                                    MorphSelectUI selector = CreateMorphSelector();
                                    selector.morphString.SetVal(morphName);
                                    selector.SetCollapse(morphsCollapsed);
                                }

                                float value = keyframe[morphName].AsFloat;
                                step.morphKeyframe[morph] = value;
                            }));
                        }

                        playback.SetVal(0);
                    });
                });
                CreateSpacer(true).height = 12;

                totalDuration = new JSONStorableFloat("duration", 2.0f, (float newDuration) =>
                {
                }, 0.0f, 10.0f, false);

                UIDynamicSlider slider = CreateSlider(totalDuration);
                slider.label = "Duration (based on audio clip if selected)";

                audioChoice = new JSONStorableStringChooser("clip", GetAudioClipIds(), "", "Audio Clip", (string clipId) => {
                    NamedAudioClip nac = URLAudioClipManager.singleton.GetClip(clipId);
                    if (nac == null)
                    {
                        currentClip = null;
                        return;
                    }

                    currentClip = nac;
                    PlayAudioClipAtT(nac, 0);

                    totalDuration.SetVal(nac.sourceClip.length);
                });
                //RegisterStringChooser(audioChoice);

                UIDynamicPopup popup = CreateScrollablePopup(audioChoice);
                popup.popup.onOpenPopupHandlers += () =>
                {
                    audioChoice.choices = GetAudioClipIds();
                };

                playback = new JSONStorableFloat("time", 0, (float t) =>
                {
                    if (isTesting == false)
                    {
                        if (currentClip != null)
                        {
                            SampleAudioClipAtT(currentClip, t);
                        }
                        SetMorphAtT(t);
                    }

                    createKeyButton.label = "Key At " + t;

                    CancelDeleteConfirmation();
                }, 0, 1, true, true);

                UIDynamicSlider playbackSlider = CreateSlider(playback);
                playbackSlider.quickButtonsEnabled  = false;
                playbackSlider.rangeAdjustEnabled   = false;
                playbackSlider.defaultButtonEnabled = false;

                CreateButton("Test").button.onClick.AddListener(() =>
                {
                    if (isTesting == true)
                    {
                        isTesting = false;
                        return;
                    }

                    isTesting     = true;
                    testStartTime = Time.time;
                    if (currentClip != null)
                    {
                        PlayAudioClipAtT(currentClip, 0);
                    }

                    CancelDeleteConfirmation();
                });

                createKeyButton = CreateButton("Key At 0");
                createKeyButton.button.onClick.AddListener(() => {
                    CreateStep(playback.val);
                });

                CreateSpacer();


                UIDynamicButton addMorphButton = CreateButton("Add Morph", true);
                addMorphButton.button.onClick.AddListener(() =>
                {
                    CreateMorphSelector();
                });

                UIDynamicButton minimizeViewButton = CreateButton("Minimize Morph Controls", true);
                minimizeViewButton.button.onClick.AddListener(() =>
                {
                    morphsCollapsed = !morphsCollapsed;
                    morphSelectors.ForEach((selector) =>
                    {
                        selector.SetCollapse(morphsCollapsed);
                    });

                    CancelDeleteConfirmation();

                    minimizeViewButton.label = morphsCollapsed ? "Maximize Morph Controls" : "Minimize Morph Controls";
                });

                deleteButton = CreateButton("Delete Selected", false);
                deleteButton.button.onClick.AddListener(() =>
                {
                    if (selectedStep == null)
                    {
                        return;
                    }

                    if (deleteConfirmation == false)
                    {
                        BeginDeleteConfirmation();
                        return;
                    }
                    else
                    {
                        RemoveStep(selectedStep);
                        CancelDeleteConfirmation();
                    }
                });

                CreateStep(0);
                CreateStep(1);
                playback.SetVal(0);
            }
            catch (Exception e)
            {
                SuperController.LogError("Exception caught: " + e);
            }
        }