public IEnumerator Quit()
        {
            quitStarted = true;
            yield return(new WaitForEndOfFrame());

            if (MainSettingsVars.initialized && MainSettingsVars.animationComponents != null)
            {
                if (MainSettingsVars.animationComponents.Length > 0)
                {
                    for (int i = 0; i < MainSettingsVars.animationComponents.Length; i++)
                    {
                        MainSettingsVars.animationComponents[i].stopAndSave();
                        yield return(null);
                    }
                }
            }
            MainSettingsVars.saveData();
            yield return(null);

            #if UNITY_EDITOR
            UnityEditor.EditorApplication.isPlaying = false;
            #else
            Application.Quit();
            #endif
            yield break;
        }
        IEnumerator Initialize()
        {
            if (MainSettingsVars.initialized)
            {
                yield break;
            }

            MainSettingsVars.mainsettingsComponent = this;

            // optional
            // light
            Light lightComponent = (Light)FindObjectOfType(typeof(Light));

            if (lightComponent)
            {
                MainSettingsVars.lightObject          = lightComponent.gameObject;
                MainSettingsVars.lightComponent       = lightComponent;
                MainSettingsVars.lightComponent.color = Color.white;
            }
            else
            {
                UnityEngine.Debug.Log("HALFTHEORY: " + this.GetType() + ": Light not found");
            }
            // mouselook
            if (GetComponent <MouseLook>())
            {
                MainSettingsVars.mouselookComponent = GetComponent <MouseLook>();
            }
            // audiosource
            if (GetComponent <AudioSource>())
            {
                MainSettingsVars.audiosourceComponent = GetComponent <AudioSource>();
            }

            // required
            // camera
            if (GetComponent <Camera>())
            {
                MainSettingsVars.maincameraObject                    = this.gameObject;
                MainSettingsVars.maincameraComponent                 = GetComponent <Camera>();
                MainSettingsVars.maincameraComponent.clearFlags      = CameraClearFlags.SolidColor;
                MainSettingsVars.maincameraComponent.backgroundColor = Color.black;

                MainSettingsVars.renderCamerasComponents.Add(0, new Camera[] { MainSettingsVars.maincameraComponent });
            }
            else
            {
                UnityEngine.Debug.Log("HALFTHEORY: " + this.GetType() + ": Camera not found");
                yield break;
            }

            // stereo3d
            if (GetComponent <stereo3dCameraSBS>())
            {
                MainSettingsVars.stereo3dComponent = GetComponent <stereo3dCameraSBS>();

                if (MainSettingsVars.stereo3dComponent.leftCam != null && MainSettingsVars.stereo3dComponent.rightCam != null)
                {
                    MainSettingsVars.renderCamerasComponents.Add(1, new Camera[] { MainSettingsVars.stereo3dComponent.leftCam.GetComponent <Camera>(), MainSettingsVars.stereo3dComponent.rightCam.GetComponent <Camera>() });
                }
                if (MainSettingsVars.stereo3dComponent.leftCamRecord != null && MainSettingsVars.stereo3dComponent.rightCamRecord != null)
                {
                    MainSettingsVars.renderCamerasComponents.Add(2, new Camera[] { MainSettingsVars.stereo3dComponent.leftCamRecord.GetComponent <Camera>(), MainSettingsVars.stereo3dComponent.rightCamRecord.GetComponent <Camera>() });
                }
            }
            else
            {
                UnityEngine.Debug.Log("HALFTHEORY: " + this.GetType() + ": stereo3dCameraSBS not found");
                yield break;
            }

            // osc
            OSC oscComponent = (OSC)FindObjectOfType(typeof(OSC));

            if (oscComponent)
            {
                MainSettingsVars.oscObject    = oscComponent.gameObject;
                MainSettingsVars.oscComponent = oscComponent;
                if (!MainSettingsVars.oscObject.GetComponent <OSC_Distributor>())
                {
                    MainSettingsVars.oscObject.AddComponent <OSC_Distributor>();
                }
            }
            else
            {
                UnityEngine.Debug.Log("HALFTHEORY: " + this.GetType() + ": OSC not found");
                yield break;
            }

            // gui
            GUISettings guiComponent = (GUISettings)FindObjectOfType(typeof(GUISettings));

            if (guiComponent)
            {
                MainSettingsVars.guiComponent = guiComponent;
            }
            else
            {
                UnityEngine.Debug.Log("HALFTHEORY: " + this.GetType() + ": GUISettings not found");
            }

            MainSettingsVars.initialized = true;

            // data
            bool test = MainSettingsVars.loadData();

            yield return(null);

            if (!test)
            {
                UnityEngine.Debug.Log("HALFTHEORY: " + this.GetType() + ": loadData failed");
                yield break;
            }

            // get these after data is loaded
            test = MainSettingsVars.loadCurrentAnimation(MainSettingsVars.data.currentAnimation);
            yield return(null);

            if (!test)
            {
                UnityEngine.Debug.Log("HALFTHEORY: " + this.GetType() + ": loadCurrentAnimation failed");
            }

            yield break;
        }
 void OnDisable()
 {
     MainSettingsVars.saveData();
 }
        void guiWindowFunc(int id = 0)
        {
            guiTextFieldId = 0; // must be here - stops working inside OnGUI?
            if (hasScroll)
            {
                scrollPosition = GUILayout.BeginScrollView(scrollPosition);
            }

            // Select Mode
            GUILayout.BeginVertical("box");
            guiGridGameModeIntNew = GUILayout.SelectionGrid(guiGridGameModeInt, guiGridGameMode, guiGridGameMode.Length);
            if (guiGridGameModeInt != guiGridGameModeIntNew)
            {
                guiGridGameModeInt = guiGridGameModeIntNew;
                MainSettingsVars.data.currentGameMode = (gameMode)System.Enum.Parse(typeof(gameMode), guiGridGameModeInt.ToString());
            }
            GUILayout.EndVertical();

            // Main Settings
            guiToggleMain = guiLabel(guiToggleMain, "Main Settings");
            if (guiToggleMain)
            {
                GUILayout.Label("Main Settings");
                MainSettingsVars.data.maxSizeCollections = guiField(MainSettingsVars.data.maxSizeCollections, "Maximum Size of Collections.", MainSettingsVars.defaults["maxSizeCollections"], 2000, 20000);
                MainSettingsVars.data.maxSizeChildren    = guiField(MainSettingsVars.data.maxSizeChildren, "Maximum Number of Child Objects.", MainSettingsVars.defaults["maxSizeChildren"], 100, 5000);
                // 3D Settings
                GUILayout.Label("3D Settings");
                MainSettingsVars.data.stereo3d_enabled      = guiField(MainSettingsVars.data.stereo3d_enabled, "Enable Side-By-Side");
                MainSettingsVars.data.stereo3d_interaxial   = guiField(MainSettingsVars.data.stereo3d_interaxial, "Interaxial (mm) - Distance (in millimeters) between cameras.", MainSettingsVars.defaults["stereo3d_interaxial"], 0.0f, 1000f);
                MainSettingsVars.data.stereo3d_zeroPrlxDist = guiField(MainSettingsVars.data.stereo3d_zeroPrlxDist, "Zero Prlx Dist (M) - Distance (in meters) at which left and right images converge.", MainSettingsVars.defaults["stereo3d_zeroPrlxDist"], 0.1f, 100f);
                MainSettingsVars.data.stereo3d_H_I_T        = guiField(MainSettingsVars.data.stereo3d_H_I_T, "H I T - Horizontal Image Transform.", MainSettingsVars.defaults["stereo3d_H_I_T"], -25f, 25f);
                // OSC Settings
                GUILayout.Label("OSC Settings");
                MainSettingsVars.data.osc_inPort = guiField(MainSettingsVars.data.osc_inPort, "Incoming Port.", MainSettingsVars.defaults["osc_inPort"], 1000, 10000);
                // Render Settings
                GUILayout.Label("Render Settings");
                GUILayout.BeginHorizontal();
                // antiAliasing
                GUILayout.BeginVertical("box");
                GUILayout.Label("Anti-aliasing", guiStyleLabelCenter);
                guiGridAntiAliasingIntNew = GUILayout.SelectionGrid(guiGridAntiAliasingInt, guiGridAntiAliasing, 1);
                if (guiGridAntiAliasingInt != guiGridAntiAliasingIntNew)
                {
                    guiGridAntiAliasingInt = guiGridAntiAliasingIntNew;
                    foreach (var pair in MainSettingsVars.renderAntiAliasing)
                    {
                        if (pair.Value == guiGridAntiAliasing[guiGridAntiAliasingInt])
                        {
                            MainSettingsVars.data.renderAntiAliasing = pair.Key;
                            break;
                        }
                    }
                }
                GUILayout.EndVertical();
                // codec
                GUILayout.BeginVertical("box");
                GUILayout.Label("Codec", guiStyleLabelCenter);
                guiGridCodecIntNew = GUILayout.SelectionGrid(guiGridCodecInt, guiGridCodec, 1);
                if (guiGridCodecInt != guiGridCodecIntNew)
                {
                    guiGridCodecInt = guiGridCodecIntNew;
                    MainSettingsVars.data.renderCodec = guiGridCodec[guiGridCodecInt];
                }
                GUILayout.EndVertical();
                // resolution helpers
                GUILayout.BeginVertical();
                foreach (var pair in MainSettingsVars.renderResolutions)
                {
                    if (GUILayout.Button(pair.Key))
                    {
                        string x  = pair.Value.x.ToString();
                        string x2 = (pair.Value.x * 2.0f).ToString();
                        string y  = pair.Value.y.ToString();
                        for (int i = 0; i < MainSettingsVars.renderCamerasNames.Count; i++)
                        {
                            if (i == 2)
                            {
                                renderCamerasResolution_x[i] = x2;
                            }
                            else
                            {
                                renderCamerasResolution_x[i] = x;
                            }
                            renderCamerasResolution_y[i] = y;
                        }
                    }
                }
                GUILayout.EndVertical();
                // cameras
                foreach (var pair in MainSettingsVars.renderCamerasNames)
                {
                    GUILayout.BeginVertical("box");
                    GUILayout.Label(pair.Value, guiStyleLabelCenter);
                    MainSettingsVars.data.renderCamerasActive[pair.Key] = guiField(MainSettingsVars.data.renderCamerasActive[pair.Key], "Active");
                    GUILayout.BeginHorizontal();
                    GUILayout.Label("");
                    renderCamerasResolution_x[pair.Key] = GUILayout.TextField(renderCamerasResolution_x[pair.Key], 4, GUILayout.Width(50));
                    GUILayout.Label("x", guiStyleLabelCenter, GUILayout.Width(10));
                    renderCamerasResolution_y[pair.Key] = GUILayout.TextField(renderCamerasResolution_y[pair.Key], 4, GUILayout.Width(50));
                    GUILayout.Label("");
                    GUILayout.EndHorizontal();
                    if (GUILayout.Button("confirm"))
                    {
                        MainSettingsVars.data.renderCamerasResolution[pair.Key] = new Vector2(float.Parse(renderCamerasResolution_x[pair.Key]), float.Parse(renderCamerasResolution_y[pair.Key]));
                    }
                    GUILayout.EndVertical();
                }
                GUILayout.EndHorizontal();
                // Data Settings
                GUILayout.Label("Data Settings");
                GUILayout.BeginVertical("box");
                guiGridDataInt = GUILayout.SelectionGrid(guiGridDataInt, guiGridDataArr, guiGridDataArr.Length);
                if (guiGridDataInt != -1)
                {
                    GUILayout.BeginHorizontal();
                    if (GUILayout.Button("confirm"))
                    {
                        MainSettingsVars.dataActions(guiGridDataInt);
                        guiGridDataInt = -1;
                    }
                    if (GUILayout.Button("cancel"))
                    {
                        guiGridDataInt = -1;
                    }
                    GUILayout.EndHorizontal();
                }
                GUILayout.EndVertical();
            }

            // Animation Settings
            guiToggleAnimation = guiLabel(guiToggleAnimation, "Animation Settings");
            if (guiToggleAnimation)
            {
                // Select Animation
                if (guiGridAnimations.Length > 0)
                {
                    GUILayout.Label("Select Animation");
                    GUILayout.BeginVertical("box");
                    guiGridAnimationSelectInt = GUILayout.SelectionGrid(guiGridAnimationSelectInt, guiGridAnimations, MainSettingsVars.groupsLength);
                    if (guiGridAnimationSelectInt != -1)
                    {
                        GUILayout.Label("Audio File: " + MainSettingsVars.animationComponents[guiGridAnimationSelectInt].data.audio_file_path);
                        GUILayout.Label("FPS: " + MainSettingsVars.animationComponents[guiGridAnimationSelectInt].data.fps);
                        // Data
                        GUILayout.BeginHorizontal("box");
                        GUILayout.Label("Data:", GUILayout.Width(80));
                        bool test = MainSettingsVars.animationComponents[guiGridAnimationSelectInt].hasDataFile();
                        if (test)
                        {
                            GUILayout.Label("File:", GUILayout.Width(30));
                            GUILayout.Label(MainSettingsVars.animationComponents[guiGridAnimationSelectInt].dataFile);
                        }
                        if (GUILayout.Button("delete", GUILayout.Width(50)))
                        {
                            if (test)
                            {
                                File.Delete(MainSettingsVars.animationComponents[guiGridAnimationSelectInt].dataFile);
                                #if UNITY_EDITOR
                                File.Delete(MainSettingsVars.animationComponents[guiGridAnimationSelectInt].dataFile + ".meta");
                                #endif
                            }
                            MainSettingsVars.animationComponents[guiGridAnimationSelectInt].dataFile = null;
                            MainSettingsVars.animationComponents[guiGridAnimationSelectInt].loadData();
                        }
                        GUILayout.EndHorizontal();
                        // Points
                        GUILayout.BeginHorizontal("box");
                        GUILayout.Label("Points:", GUILayout.Width(80));
                        test = MainSettingsVars.animationComponents[guiGridAnimationSelectInt].hasPointsFile();
                        if (test)
                        {
                            GUILayout.Label("File:", GUILayout.Width(30));
                            GUILayout.Label(MainSettingsVars.animationComponents[guiGridAnimationSelectInt].pointsFile);
                        }
                        if (GUILayout.Button("delete", GUILayout.Width(50)))
                        {
                            if (test)
                            {
                                File.Delete(MainSettingsVars.animationComponents[guiGridAnimationSelectInt].pointsFile);
                                #if UNITY_EDITOR
                                File.Delete(MainSettingsVars.animationComponents[guiGridAnimationSelectInt].pointsFile + ".meta");
                                #endif
                            }
                            MainSettingsVars.animationComponents[guiGridAnimationSelectInt].pointsFile = null;
                            StartCoroutine(MainSettingsVars.animationComponents[guiGridAnimationSelectInt].loadPointsData());
                        }
                        GUILayout.EndHorizontal();

                        // Animation
                        GUILayout.BeginHorizontal("box");
                        GUILayout.Label("Animation:", GUILayout.Width(80));
                        test = MainSettingsVars.animationComponents[guiGridAnimationSelectInt].hasAnimationFile();
                        if (test)
                        {
                            GUILayout.Label("File:", GUILayout.Width(30));
                            GUILayout.Label(MainSettingsVars.animationComponents[guiGridAnimationSelectInt].animationFile);
                        }
                        if (GUILayout.Button("delete", GUILayout.Width(50)))
                        {
                            if (test)
                            {
                                File.Delete(MainSettingsVars.animationComponents[guiGridAnimationSelectInt].animationFile);
                                #if UNITY_EDITOR
                                File.Delete(MainSettingsVars.animationComponents[guiGridAnimationSelectInt].animationFile + ".meta");
                                #endif
                            }
                            MainSettingsVars.animationComponents[guiGridAnimationSelectInt].animationFile = null;
                            StartCoroutine(MainSettingsVars.animationComponents[guiGridAnimationSelectInt].loadAnimationData());
                        }
                        GUILayout.EndHorizontal();

                        GUILayout.BeginHorizontal();
                        if (GUILayout.Button("confirm"))
                        {
                            MainSettingsVars.data.currentAnimation = MainSettingsVars.data.animations[guiGridAnimationSelectInt];
                            setAnimationGui();
                            setMeshGui();
                        }
                        if (GUILayout.Button("cancel"))
                        {
                            guiGridAnimationSelectInt = -1;
                        }
                        GUILayout.EndHorizontal();
                    }
                    GUILayout.EndVertical();
                }
                // New Animation
                GUILayout.Label("New Animation");
                GUILayout.BeginHorizontal("box");
                GUILayout.Label("Name", GUILayout.Width(50));
                if (string.IsNullOrEmpty(guiStringAnimationNew))
                {
                    guiStringAnimationNew = MainSettingsVars.getAnimationName();
                }
                guiStringAnimationNew = Regex.Replace(guiStringAnimationNew, "[^a-z0-9_-]+", "_", RegexOptions.IgnoreCase);
                guiStringAnimationNew = GUILayout.TextField(guiStringAnimationNew, 50);
                if (GUILayout.Button("ok", GUILayout.Width(50)))
                {
                    List <string> animationsList = new List <string>(MainSettingsVars.data.animations);
                    animationsList.Add(guiStringAnimationNew);
                    MainSettingsVars.data.animations = animationsList.ToArray();
                    MainSettingsVars.loadAnimations();
                    MainSettingsVars.data.currentAnimation = guiStringAnimationNew;
                    guiStringAnimationNew = "";
                    setAnimationGui();
                    setMeshGui();
                }
                GUILayout.EndHorizontal();
                // Delete Animation
                if (guiGridAnimations.Length > 0)
                {
                    GUILayout.Label("Delete Animation");
                    GUILayout.BeginVertical("box");
                    guiGridAnimationDeleteInt = GUILayout.SelectionGrid(guiGridAnimationDeleteInt, guiGridAnimations, MainSettingsVars.groupsLength);
                    if (guiGridAnimationDeleteInt != -1)
                    {
                        GUILayout.BeginHorizontal();
                        if (GUILayout.Button("confirm"))
                        {
                            if (MainSettingsVars.data.currentAnimation == MainSettingsVars.data.animations[guiGridAnimationDeleteInt])
                            {
                                MainSettingsVars.data.currentAnimation = "";
                            }
                            List <string> animationsList = new List <string>(MainSettingsVars.data.animations);
                            animationsList.RemoveAt(guiGridAnimationDeleteInt);
                            MainSettingsVars.data.animations = animationsList.ToArray();
                            MainSettingsVars.loadAnimations();
                            setAnimationGui();
                            setMeshGui();
                        }
                        if (GUILayout.Button("cancel"))
                        {
                            guiGridAnimationDeleteInt = -1;
                        }
                        GUILayout.EndHorizontal();
                    }
                    GUILayout.EndVertical();
                }
            }

            // Mesh Settings
            if (MainSettingsVars.currentAnimationComponent != null)
            {
                guiToggleMesh = guiLabel(guiToggleMesh, "Mesh Settings : " + MainSettingsVars.data.currentAnimation);
                if (guiToggleMesh)
                {
                    GUILayout.BeginHorizontal();
                    for (int i = 0; i < MainSettingsVars.groupsLength; i++)
                    {
                        GUILayout.BeginVertical("box");
                        GUILayout.Label("Group " + (i + 1), guiStyleLabelCenter);
                        MainSettingsVars.currentAnimationComponent.meshComponents[i].active = guiField(MainSettingsVars.currentAnimationComponent.meshComponents[i].active, "Active");
                        MainSettingsVars.currentAnimationComponent.meshComponents[i].peaks  = guiField(MainSettingsVars.currentAnimationComponent.meshComponents[i].peaks, "Peaks", MainSettingsVars.defaults["meshPeaks"], 0, MainSettingsVars.pointsLength, true);
                        MainSettingsVars.currentAnimationComponent.meshComponents[i].level  = guiField(MainSettingsVars.currentAnimationComponent.meshComponents[i].level, "Level", MainSettingsVars.defaults["meshLevel"], 0.0f, 1.0f, true);
                        guiToggleMeshTopology[i] = guiLabel(guiToggleMeshTopology[i], "Topology", MainSettingsVars.currentAnimationComponent.meshComponents[i].meshTopologySelect.ToString(), true);
                        if (guiToggleMeshTopology[i])
                        {
                            guiGridMeshTopologyIntNew[i] = GUILayout.SelectionGrid(guiGridMeshTopologyInt[i], guiGridMeshTopology, 2);
                            if (guiGridMeshTopologyInt[i] != guiGridMeshTopologyIntNew[i])
                            {
                                guiGridMeshTopologyInt[i] = guiGridMeshTopologyIntNew[i];
                                MainSettingsVars.currentAnimationComponent.meshComponents[i].meshTopologySelect = (meshTopology)System.Enum.Parse(typeof(meshTopology), guiGridMeshTopologyInt[i].ToString());
                                guiToggleMeshTopology[i] = false;
                            }
                        }
                        guiToggleMeshColor[i] = guiLabel(guiToggleMeshColor[i], "Color", MainSettingsVars.currentAnimationComponent.meshComponents[i].meshColorSelect.ToString(), true);
                        if (guiToggleMeshColor[i])
                        {
                            guiGridMeshColorIntNew[i] = GUILayout.SelectionGrid(guiGridMeshColorInt[i], guiGridMeshColor, 2);
                            if (guiGridMeshColorInt[i] != guiGridMeshColorIntNew[i])
                            {
                                guiGridMeshColorInt[i] = guiGridMeshColorIntNew[i];
                                MainSettingsVars.currentAnimationComponent.meshComponents[i].meshColorSelect = (meshColor)System.Enum.Parse(typeof(meshColor), guiGridMeshColorInt[i].ToString());
                                guiToggleMeshColor[i] = false;
                            }
                        }
                        guiToggleMeshShader[i] = guiLabel(guiToggleMeshShader[i], "Material", MainSettingsVars.currentAnimationComponent.meshComponents[i].meshShaderSelect.ToString(), true);
                        if (guiToggleMeshShader[i])
                        {
                            guiGridMeshShaderIntNew[i] = GUILayout.SelectionGrid(guiGridMeshShaderInt[i], guiGridMeshShader, 2);
                            if (guiGridMeshShaderInt[i] != guiGridMeshShaderIntNew[i])
                            {
                                guiGridMeshShaderInt[i] = guiGridMeshShaderIntNew[i];
                                MainSettingsVars.currentAnimationComponent.meshComponents[i].meshShaderSelect = (meshShader)System.Enum.Parse(typeof(meshShader), guiGridMeshShaderInt[i].ToString());
                                guiToggleMeshShader[i] = false;
                            }
                        }
                        if (guiGridMeshShaderInt[i] == 2)
                        {
                            MainSettingsVars.currentAnimationComponent.meshComponents[i].alpha = guiField(MainSettingsVars.currentAnimationComponent.meshComponents[i].alpha, "Opacity", MainSettingsVars.defaults["meshAlpha"], 0.0f, 1.0f, true);
                        }
                        MainSettingsVars.currentAnimationComponent.meshComponents[i].randomX     = guiField(MainSettingsVars.currentAnimationComponent.meshComponents[i].randomX, "Random end X", null, null, null, true);
                        MainSettingsVars.currentAnimationComponent.meshComponents[i].randomY     = guiField(MainSettingsVars.currentAnimationComponent.meshComponents[i].randomY, "Random end Y", null, null, null, true);
                        MainSettingsVars.currentAnimationComponent.meshComponents[i].rotateSpeed = guiField(MainSettingsVars.currentAnimationComponent.meshComponents[i].rotateSpeed, "Rotate", MainSettingsVars.defaults["meshRotateSpeed"], -1.0f, 1.0f, true);
                        MainSettingsVars.currentAnimationComponent.meshComponents[i].smoothTime  = guiField(MainSettingsVars.currentAnimationComponent.meshComponents[i].smoothTime, "Smooth time", MainSettingsVars.defaults["meshSmoothTime"], 0.0f, 0.5f, true);
                        MainSettingsVars.currentAnimationComponent.meshComponents[i].clearTime   = guiField(MainSettingsVars.currentAnimationComponent.meshComponents[i].clearTime, "Clear time", MainSettingsVars.defaults["meshClearTime"], 0.0f, 30.0f, true);
                        MainSettingsVars.currentAnimationComponent.meshComponents[i].noClearTime = guiField(MainSettingsVars.currentAnimationComponent.meshComponents[i].noClearTime, "No clear time", null, null, null, true);
                        MainSettingsVars.currentAnimationComponent.meshComponents[i].traceTime   = guiField(MainSettingsVars.currentAnimationComponent.meshComponents[i].traceTime, "Trace time", MainSettingsVars.defaults["meshTraceTime"], 0.0f, 2.0f, true);
                        GUILayout.EndVertical();
                    }
                    GUILayout.EndHorizontal();
                }
            }

            if (hasScroll)
            {
                GUILayout.EndScrollView();
            }
        }