Beispiel #1
0
    protected virtual void Start()
    {
        //Load the Character
        if (ExpressionSetFile != null)
        {
            character.Init(ExpressionSetFile.Expressions, ExpressionSetFile.Controls);
            List <string> missingCtrlList = LiveUnityInterface.ValidateControls(this.gameObject, character.GetControlList());
            if (missingCtrlList.Count > 0)
            {
                string msg = "[Faceware Live] These controls are not in your scene:\n";
                foreach (string ctrl in missingCtrlList)
                {
                    msg += ctrl;
                    msg += "\n";
                }
                Debug.LogWarning(msg);
            }

            //Setup Connection to Live
            live             = new LiveConnection(LiveServerHostIP, LiveServerHostPort);
            live.m_Reconnect = ReconnectOnLostConnection;
            // Connect on Play if toggled true
            if (ConnectOnPlay)
            {
                Connect();
            }
            live.m_DropPackets = DropPackets;
        }

        if (RecordOnStart && EnableRecording)
        {
            OnToggleRecording();
        }
    }
Beispiel #2
0
    /****************************************************************************************************/
    void Start()
    {
        if (ConnectOnPlay)
        {
            charSetupLoaded = LoadCharSetupFile(ExpressionSetFile.ToString());
            if (charSetupLoaded)
            {
                List <string> missingCtrlList = LiveUnityInterface.ValidateControls(data.GetControlList());
                if (missingCtrlList.Count > 0)
                {
                    string msg = "These controls are not in your scene:\n";
                    foreach (string ctrl in missingCtrlList)
                    {
                        msg += ctrl;
                        msg += "\n";
                    }
                    PrintError(msg);
                }
                controlOffsets = data.GetNeutralControlValues();
            }

            network.Connect(Server, Port);
            ConnectOnPlay = false;
            PrintMessage("LiveClient started.");
            PrintMessage(charSetupLoaded ? "Loaded Character Setup file." : "No Character Setup file loaded.");
            //PrintMessage( connected ? "Connected to Live Server." : "Could not connect to Live Server.  Check your hostname/port and make sure that Live Server is streaming data." );
        }
    }
Beispiel #3
0
    void IntializeRecording()
    {
        List <string>             controlNames = character.GetControlList();
        List <UnityEngine.Object> controls     = LiveUnityInterface.GetControls(this.gameObject, controlNames);

        recordingTime = 0.0f;

        //Loop through controls and create anim curves for each
        for (int i = 0; i < controlNames.Count; i++)
        {
            FTIAnimCurve ftiCurve = new FTIAnimCurve();

            UnityEngine.Object control = controls[i];

            if (control is Transform)
            {
                Transform transfromControl = (Transform)control;

                ftiCurve.hierachyPath = LiveUnityInterface.GetRelativeGameObjectPath(transfromControl.gameObject, this.gameObject);
                ftiCurve.isBlendShape = false;

                int curveNum = 3;

                string attr = LiveHelpers.GetAttrString(controlNames [i]);

                if (attr == LiveCharacterSetup.rotationSuffix)
                {
                    curveNum++;
                }

                for (int j = 0; j < curveNum; j++)
                {
                    ftiCurve.animCurves.Add(new AnimationCurve());

                    //Intialize values to have at least 1 keyframe
                    if (attr != LiveCharacterSetup.rotationSuffix)
                    {
                        ftiCurve.animCurves[j].AddKey(0f, transfromControl.localPosition[j]);
                    }
                    else
                    {
                        ftiCurve.animCurves[j].AddKey(0f, transfromControl.localRotation[j]);
                    }
                }
            }
            else if (control is SkinnedMeshRenderer)
            {
                SkinnedMeshRenderer blendShapeControl = (SkinnedMeshRenderer)control;
                string attr  = LiveHelpers.GetAttrString(controlNames[i]);
                int    index = LiveUnityInterface.GetBlendShapeIndex(blendShapeControl, attr);

                ftiCurve.hierachyPath = LiveUnityInterface.GetRelativeGameObjectPath(blendShapeControl.gameObject, this.gameObject);
                ftiCurve.isBlendShape = true;
                ftiCurve.animCurves.Add(new AnimationCurve());
                ftiCurve.animCurves[0].AddKey(0f, blendShapeControl.GetBlendShapeWeight(index));
            }

            RecordedCurves.Add(controlNames[i], ftiCurve);
        }
    }
Beispiel #4
0
    /****************************************************************************************************/
    private void InitSelectControlList()
    {
        List <string> controlList = new List <string>();

        if (Selection.activeGameObject != null)
        {
            foreach (GameObject selected in Selection.gameObjects)
            {
                List <string> newControls = LiveUnityInterface.GetControls(selected);
                foreach (string ctrl in newControls)
                {
                    if (!controlList.Contains(ctrl))
                    {
                        controlList.Add(ctrl);
                    }
                }
            }
        }

        controlSelection.Clear();
        foreach (string control in controlList)
        {
            controlSelection.Add(control, false);
        }
    }
    void Update()
    {
        BaseUpdate();

        if (live != null && live.IsConnected() && ExpressionSetFile)
        {
            currentDatSet = live.GetLiveData();
            if (currentDatSet != null && currentDatSet.Count > 0)
            {
                var values = currentDatSet["animationValues"];
                Dictionary <string, float> animationValues = new Dictionary <string, float>();
                foreach (var key in values.Keys)
                {
                    if (key == "head_RightTilt" || key == "head_LeftTilt")
                    {
                        animationValues.Add(key, Math.Abs(values[key].AsFloat));
                    }
                    else
                    {
                        animationValues.Add(key, values[key].AsFloat);
                    }
                }
                cachedRigValues = character.ConstructRigValues(animationValues, character.GetNeutralControlValues());
                LiveUnityInterface.ApplyControlValues(this.gameObject, cachedRigValues);
            }
        }
    }
Beispiel #6
0
    /****************************************************************************************************/
    void Update()
    {
        if (charSetupLoaded)
        {
            expressionValues = network.Update();

            if (expressionValues != null && expressionValues.Count > 0)
            {
                Dictionary <string, Vector4> rigValues = data.ConstructRigValues(expressionValues, controlOffsets);
                LiveUnityInterface.ApplyControlValues(rigValues);
            }
        }
    }
    /****************************************************************************************************/
    private void ValidateControls()
    {
        List <string> missingControls           = LiveUnityInterface.ValidateControls(currentCharSetupFile.rootObject, currentCharSetupFile.Controls);
        string        removedControlsString     = "";
        string        fullRemovedControlsString = "";

        if (missingControls.Count > 0)
        {
            int removedControls = 0;
            //Remove from controls list and expression values
            for (int i = currentCharSetupFile.Controls.Count - 1; i >= 0; i--)
            {
                if (missingControls.Contains(currentCharSetupFile.Controls[i]))
                {
                    foreach (Expression exp in currentCharSetupFile.Expressions)
                    {
                        if (i < exp.Values.Count - 1)
                        {
                            exp.Values.RemoveAt(i);
                        }
                    }

                    if (removedControls < 11)
                    {
                        removedControlsString += "\n -" + currentCharSetupFile.Controls[i];
                    }
                    else if (removedControls == 12)
                    {
                        removedControlsString += "\n...See console for full list of removed controls...";
                    }

                    fullRemovedControlsString += "\n -" + currentCharSetupFile.Controls[i];
                    currentCharSetupFile.Controls.RemoveAt(i);

                    removedControls++;
                }
            }

            //Refresh added controls list
            InitAddedControls();
            //Display warnings
            Debug.LogWarning("The following controls were missing and have been removed from the character setup file. However, changes will not be applied until you hit save in character setup. Click this log message to see the list below: \n" + fullRemovedControlsString);
            EditorUtility.DisplayDialog("Missing Controls", "The following controls were missing and have been removed from the character setup file. However, changes will not be applied until you hit save.\n" + removedControlsString, "Ok");
        }

        charSetupData.UpdateData(currentCharSetupFile.Expressions, currentCharSetupFile.Controls);
    }
Beispiel #8
0
 /****************************************************************************************************/
 private void CreateFileGUI()
 {
     EditorGUILayout.BeginVertical();
     {
         EditorGUILayout.LabelField("Faceware Live Client for Unity - Character Setup", titleStyle, GUILayout.ExpandHeight(true));
         EditorGUILayout.LabelField("Current File: " + charSetupFilename);
         EditorGUILayout.BeginHorizontal();
         {
             GUILayoutOption buttonWidth = GUILayout.Width(162);
             if (GUILayout.Button("New", buttonWidth))
             {
                 charSetupData.Init();
                 controlSelection.Clear();
                 addedControls.Clear();
                 charSetupFilename = "";
                 sceneControlObjectList.Clear();
             }
             if (GUILayout.Button("Open...", buttonWidth))
             {
                 string filename = EditorUtility.OpenFilePanel("Open Character Setup", "", "json");
                 if (filename != null && filename != "")
                 {
                     if (charSetupData.LoadExpressionSet(filename, false))
                     {
                         charSetupFilename = filename;
                         controlSelection.Clear();
                         InitAddedControls();
                         sceneControlObjectList = LiveUnityInterface.GetControls(charSetupData.GetControlList());
                         LiveJsonParser.Serialize(charSetupData);
                     }
                 }
             }
             if (GUILayout.Button("Save As...", buttonWidth))
             {
                 charSetupFilename = SaveExpressionSet() ?? "";
             }
         }
         EditorGUILayout.EndHorizontal();
     }
     EditorGUILayout.EndVertical();
     CreateSpace(2);
 }
Beispiel #9
0
    public void RecordFrame()
    {
        if (Recording && live.m_RecievedNewData)
        {
            live.m_RecievedNewData = false;
            //Grab values from rig
            Dictionary <string, Vector4> controlValues;
            if (cachedRigValues == null)
            {
                controlValues = LiveUnityInterface.GetControlValues(this.gameObject, character.GetControlList());
            }
            else
            {
                controlValues = cachedRigValues;
            }

            //Write keyframes for each control, if keyframe on new data only check if there is new data
            foreach (KeyValuePair <string, Vector4> controlKvp in controlValues)
            {
                string       controlName = controlKvp.Key;
                FTIAnimCurve curveData   = RecordedCurves[controlName];

                if (curveData.isBlendShape)
                {
                    if (!KeyframeOnNewData || curveData.animCurves[0].keys[curveData.animCurves[0].keys.Length - 1].value != controlKvp.Value.x)
                    {
                        Keyframe newFrame = new Keyframe(recordingTime, controlKvp.Value.x);
                        curveData.animCurves[0].AddKey(newFrame);
                    }
                }
                else
                {
                    if (!KeyframeOnNewData || curveData.animCurves[0].keys[curveData.animCurves[0].keys.Length - 1].value != controlKvp.Value.x)
                    {
                        Keyframe newFrame = new Keyframe(recordingTime, controlKvp.Value.x);
                        curveData.animCurves[0].AddKey(newFrame);
                    }

                    if (!KeyframeOnNewData || curveData.animCurves[1].keys[curveData.animCurves[1].keys.Length - 1].value != controlKvp.Value.y)
                    {
                        Keyframe newFrame = new Keyframe(recordingTime, controlKvp.Value.y);
                        curveData.animCurves[1].AddKey(newFrame);
                    }

                    if (!KeyframeOnNewData || curveData.animCurves[2].keys[curveData.animCurves[2].keys.Length - 1].value != controlKvp.Value.z)
                    {
                        Keyframe newFrame = new Keyframe(recordingTime, controlKvp.Value.z);
                        curveData.animCurves[2].AddKey(newFrame);
                    }

                    string attr = LiveHelpers.GetAttrString(controlName);

                    if (attr == LiveCharacterSetup.rotationSuffix)
                    {
                        if (!KeyframeOnNewData || curveData.animCurves[3].keys[curveData.animCurves[3].keys.Length - 1].value != controlKvp.Value.w)
                        {
                            Keyframe newFrame = new Keyframe(recordingTime, controlKvp.Value.w);
                            curveData.animCurves[3].AddKey(newFrame);
                        }
                    }
                }
            }
        }
    }
    /****************************************************************************************************/
    private void InitSelectControlList()
    {
        List <string> controlList = new List <string>();

        if (Selection.gameObjects.Length == 1)
        {
            if (currentCharSetupFile != null)
            {
                bool       validateCurrentControls = false;
                GameObject selectedGameobject      = Selection.gameObjects[0];
                if (currentCharSetupFile.rootObject != null)
                {
                    if (selectedGameobject != currentCharSetupFile.rootObject)
                    {
                        //Prompt before continueing with yes or cancel
                        if (!EditorUtility.DisplayDialog("Override associated character?", "This character setup file was made with " + currentCharSetupFile.rootObjectName + ". Do you wish to override this with your current selection?\n\nIf controls associated to " + currentCharSetupFile.rootObjectName + " do not exist on your new selection they will be removed.", "Yes", "Cancel"))
                        {
                            return;
                        }
                        else
                        {
                            validateCurrentControls = true;
                        }
                    }
                }

                currentCharSetupFile.rootObject     = selectedGameobject;
                currentCharSetupFile.rootObjectName = currentCharSetupFile.rootObject.name;
                List <GameObject> selectedChildren = new List <GameObject>();
                currentCharSetupFile.rootObject.transform.ReturnAllChildren(selectedChildren);

                foreach (GameObject selected in selectedChildren)
                {
                    List <string> newControls = LiveUnityInterface.GetControls(selected);
                    foreach (string ctrl in newControls)
                    {
                        if (!controlList.Contains(ctrl))
                        {
                            controlList.Add(ctrl);
                        }
                    }
                }

                if (validateCurrentControls)
                {
                    ValidateControls();
                }

                controlSelection.Clear();
                foreach (string control in controlList)
                {
                    controlSelection.Add(control, false);
                }
            }
            else
            {
                ShowNoSetupFileMsg();
            }
        }
        else
        {
            //Prompt nothing is selected
            EditorUtility.DisplayDialog("Invalid Selection!", "Please select a single root game object and try again.", "Ok");
        }
    }
    /****************************************************************************************************/
    private void CreateExpressionSetGUI()
    {
        EditorGUILayout.BeginVertical("Box");         //Root layout group
        {
            EditorGUILayout.LabelField("Step 2: Expression Set", titleStyle);
            EditorGUILayout.BeginHorizontal("Box");                                                                       //Scroll view container region
            {
                expressionScrollPos = GUILayout.BeginScrollView(expressionScrollPos, false, true, GUILayout.Height(300)); //Scroll view region
                EditorGUILayout.BeginVertical();
                GUILayoutOption buttonWidth = GUILayout.Width(95);
                foreach (KeyValuePair <string, string> kvp in charSetupData.GetExpressionNameAttrList()) //Create controls within scroll view
                {
                    EditorGUILayout.BeginHorizontal();                                                   //Individual control region
                    {
                        bool hasData = charSetupData.InUse(kvp.Value);
                        GUILayout.Label(hasData ? yesIcon : noIcon, GUILayout.Width(20));
                        EditorGUILayout.LabelField(kvp.Key, GUILayout.Width(205));
                        GUILayout.FlexibleSpace();
                        if (GUILayout.Button(hasData ? "Update Pose" : "Save Pose", buttonWidth))
                        {
                            bool updateExpression = true;
                            if (hasData)
                            {
                                updateExpression = EditorUtility.DisplayDialog("Update Pose", "Are you sure you want to overwrite this Pose?", "Yes", "No");
                            }
                            if (updateExpression)
                            {
                                List <string> controls = charSetupData.GetControlList();
                                if (controls.Count > 0)
                                {
                                    charSetupData.SetControlValues(kvp.Value, LiveUnityInterface.GetControlValues(currentCharSetupFile.rootObject, controls));
                                    charSetupData.SetInUse(kvp.Value, true);
                                    currentCharSetupFile.Expressions = charSetupData.data.Expressions;
                                    EditorUtility.SetDirty(currentCharSetupFile);
                                    AssetDatabase.SaveAssets();
                                }
                            }
                        }
                        if (GUILayout.Button("Show Saved", buttonWidth))
                        {
                            Undo.RecordObjects(sceneControlObjectList.ToArray(), ("Set '" + kvp.Key + "' Expression"));
                            LiveUnityInterface.ApplyControlValues(currentCharSetupFile.rootObject, charSetupData.GetControlValues(kvp.Value));
                        }
                    }
                    EditorGUILayout.EndHorizontal(); //End of individual control region
                }
                GUILayout.EndScrollView();           //End scroll view region
                GUILayout.FlexibleSpace();
            }
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.EndVertical();

            CreateSpace(1);
            EditorGUILayout.BeginHorizontal(); //Reset to neutral button region
            {
                GUILayout.FlexibleSpace();
                if (GUILayout.Button("Reset Character to 'Neutral'", GUILayout.Width(496)))
                {
                    if (currentCharSetupFile != null)
                    {
                        LiveUnityInterface.ApplyControlValues(currentCharSetupFile.rootObject, charSetupData.GetControlValues("neutral"));
                    }
                    else
                    {
                        ShowNoSetupFileMsg();
                    }
                }
                GUILayout.FlexibleSpace();
            }
            EditorGUILayout.EndHorizontal(); //End neutral button region
        }
        CreateSpace(1);
        EditorGUILayout.EndVertical();
        CreateSpace(1);
    }
    /****************************************************************************************************/
    private void CreateControlSetupGUI()
    {
        //Root control group
        EditorGUILayout.BeginVertical("Box");
        {
            EditorGUILayout.LabelField("Step 1: Control Setup", titleStyle);
            EditorGUILayout.BeginHorizontal(); //Get Selected scene objects control group
            {
                GUILayout.FlexibleSpace();
                if (GUILayout.Button("Get Controls From Selected Object", GUILayout.Width(494)))
                {
                    InitSelectControlList();
                    sortSelectControl      = false;
                    selectControlSelectAll = false;
                }
                GUILayout.FlexibleSpace();
            }
            EditorGUILayout.EndHorizontal();

            CreateSpace(1);
            EditorGUILayout.BeginHorizontal();
            {
                GUILayout.FlexibleSpace();
                EditorGUILayout.BeginVertical(); //Selected objects region
                {
                    EditorGUILayout.LabelField("Selected Objects:", headingStyle);
                    EditorGUILayout.BeginHorizontal(); //Add controls button region
                    {
                        GUILayout.FlexibleSpace();
                        if (GUILayout.Button("Add Controls", GUILayout.MaxWidth(240)))
                        {
                            AddControls();
                            if (currentCharSetupFile != null)
                            {
                                sceneControlObjectList = LiveUnityInterface.GetControls(currentCharSetupFile.rootObject, charSetupData.GetControlList());
                            }
                            sortAddedControl      = false;
                            addedControlSelectAll = false;
                        }
                        GUILayout.FlexibleSpace();
                    }
                    EditorGUILayout.EndHorizontal();
                    bool checkSelectAll;
                    bool checkSort;
                    EditorGUILayout.BeginHorizontal();                     //Toggle controls region for selected objects
                    {
                        checkSelectAll = GUILayout.Toggle(selectControlSelectAll, "Select All");
                        GUILayout.FlexibleSpace();
                        checkSort = GUILayout.Toggle(sortSelectControl, "Sort A-Z");
                    }
                    EditorGUILayout.EndHorizontal();

                    EditorGUILayout.BeginVertical("Box");//Selected controls scroll area region
                    {
                        selectedControlScrollPos = EditorGUILayout.BeginScrollView(selectedControlScrollPos, false, false, GUILayout.MinHeight(150));
                        PopulateControlScrollView(controlSelection, selectControlSelectAll != checkSelectAll, checkSelectAll, checkSort);
                        EditorGUILayout.EndScrollView();
                    }
                    EditorGUILayout.EndVertical();

                    sortSelectControl      = checkSort;
                    selectControlSelectAll = checkSelectAll;
                }
                EditorGUILayout.EndVertical();   //End Selected objects region
                GUILayout.FlexibleSpace();
                EditorGUILayout.BeginVertical(); //Added controls region
                {
                    EditorGUILayout.LabelField("Added Controls:", headingStyle);
                    EditorGUILayout.BeginHorizontal(); //Remove controls button region
                    {
                        GUILayout.FlexibleSpace();
                        if (GUILayout.Button("Remove Controls", GUILayout.MaxWidth(240)))
                        {
                            RemoveControls();
                            if (currentCharSetupFile != null)
                            {
                                sceneControlObjectList = LiveUnityInterface.GetControls(currentCharSetupFile.rootObject, charSetupData.GetControlList());
                            }
                        }
                        GUILayout.FlexibleSpace();
                    }
                    EditorGUILayout.EndHorizontal();

                    bool checkSelectAll;
                    bool checkSort;
                    EditorGUILayout.BeginHorizontal();                     //Toggle controls region for added objects
                    {
                        checkSelectAll = GUILayout.Toggle(addedControlSelectAll, "Select All");
                        GUILayout.FlexibleSpace();
                        checkSort = GUILayout.Toggle(sortAddedControl, "Sort A-Z");
                    }
                    EditorGUILayout.EndHorizontal();

                    EditorGUILayout.BeginVertical("Box"); //Added controls scroll area region
                    {
                        addedControlScrollPos = EditorGUILayout.BeginScrollView(addedControlScrollPos, false, false, GUILayout.MinHeight(150));
                        PopulateControlScrollView(addedControls, addedControlSelectAll != checkSelectAll, checkSelectAll, checkSort);
                        EditorGUILayout.EndScrollView();
                    }
                    EditorGUILayout.EndVertical();                     //End added controls scroll region

                    sortAddedControl      = checkSort;
                    addedControlSelectAll = checkSelectAll;
                }
                EditorGUILayout.EndVertical();                 //End added controls region
                GUILayout.FlexibleSpace();
            }
            EditorGUILayout.EndHorizontal();
            CreateSpace(1);
        }
        EditorGUILayout.EndVertical();
        CreateSpace(1);
    }
Beispiel #13
0
    /****************************************************************************************************/
    private void CreateExpressionSetGUI()
    {
        EditorGUILayout.BeginVertical();
        {
            EditorGUILayout.LabelField("Step 2: Expression Set", titleStyle, GUILayout.ExpandHeight(true));

            EditorGUILayout.BeginHorizontal(exprSetBgStyle, GUILayout.Width(492));
            {
                expressionScrollPos = GUILayout.BeginScrollView(expressionScrollPos, false, true, GUILayout.Width(491), GUILayout.Height(300));
                EditorGUILayout.BeginVertical();
                GUILayoutOption buttonWidth = GUILayout.Width(95);
                foreach (KeyValuePair <string, string> kvp in charSetupData.GetExpressionNameAttrList())
                {
                    EditorGUILayout.BeginHorizontal(exprBgStyle);
                    {
                        bool hasData = charSetupData.InUse(kvp.Value);
                        GUILayout.Label(hasData ? yesIcon : noIcon, GUILayout.Width(20));
                        EditorGUILayout.LabelField(kvp.Key, GUILayout.Width(205));
                        if (GUILayout.Button(hasData ? "Update Pose" : "Save Pose", buttonWidth))
                        {
                            bool updateExpression = true;
                            if (hasData)
                            {
                                updateExpression = EditorUtility.DisplayDialog("Update Pose", "Are you sure you want to overwrite this Pose?", "Yes", "No");
                            }
                            if (updateExpression)
                            {
                                List <string> controls = charSetupData.GetControlList();
                                if (controls.Count > 0)
                                {
                                    charSetupData.SetControlValues(kvp.Value, LiveUnityInterface.GetControlValues(controls));
                                    charSetupData.SetInUse(kvp.Value, true);
                                }
                            }
                        }
                        if (GUILayout.Button("Show Saved", buttonWidth))
                        {
                            Undo.RecordObjects(sceneControlObjectList.ToArray(), ("Set '" + kvp.Key + "' Expression"));
                            LiveUnityInterface.ApplyControlValues(charSetupData.GetControlValues(kvp.Value));
                        }
                        if (GUILayout.Button(helpIcon, EditorStyles.miniButton))
                        {
                            System.Diagnostics.Process.Start("http://support.facewaretech.com/entries/37471737#" + kvp.Value);
                        }
                    }
                    EditorGUILayout.EndHorizontal();
                }
            }
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.EndVertical();
            GUILayout.EndScrollView();

            CreateSpace(1);
            if (GUILayout.Button("Reset Character to 'Neutral'", GUILayout.Width(496)))
            {
                LiveUnityInterface.ApplyControlValues(charSetupData.GetControlValues("neutral"));
            }
        }
        EditorGUILayout.EndVertical();
        CreateSpace(2);
    }
Beispiel #14
0
    /****************************************************************************************************/
    private void CreateControlSetupGUI()
    {
        GUILayoutOption scrollViewWidth    = GUILayout.Width(240);
        GUILayoutOption scrollViewBtnWidth = GUILayout.Width(242);
        GUILayoutOption scrollViewHeight   = GUILayout.Height(200);

        EditorGUILayout.BeginVertical();
        {
            EditorGUILayout.LabelField("Step 1: Control Setup", titleStyle, GUILayout.ExpandHeight(true));
            if (GUILayout.Button("Get Selected Scene Objects", GUILayout.Width(494)))
            {
                InitSelectControlList();
                sortSelectControl      = false;
                selectControlSelectAll = false;
            }
            CreateSpace(1);
            EditorGUILayout.BeginHorizontal(GUILayout.Width(500));
            {
                EditorGUILayout.BeginVertical();
                {
                    EditorGUILayout.LabelField("Selected Objects:", headingStyle);
                    if (GUILayout.Button("Add Controls", scrollViewBtnWidth))
                    {
                        AddControls();
                        sceneControlObjectList = LiveUnityInterface.GetControls(charSetupData.GetControlList());
                        sortAddedControl       = false;
                        addedControlSelectAll  = false;
                    }
                    bool checkSelectAll;
                    bool checkSort;
                    EditorGUILayout.BeginHorizontal();
                    {
                        checkSelectAll = GUILayout.Toggle(selectControlSelectAll, "Select All");
                        checkSort      = GUILayout.Toggle(sortSelectControl, "Sort A-Z");
                    }
                    EditorGUILayout.EndHorizontal();

                    EditorGUILayout.BeginHorizontal(scrollviewBgStyle, GUILayout.Width(200));
                    {
                        selectedControlScrollPos = EditorGUILayout.BeginScrollView(selectedControlScrollPos, false, false, scrollViewWidth, scrollViewHeight);
                        PopulateControlScrollView(controlSelection, selectControlSelectAll != checkSelectAll, checkSelectAll, checkSort);
                        EditorGUILayout.EndScrollView();
                    }
                    EditorGUILayout.EndHorizontal();

                    sortSelectControl      = checkSort;
                    selectControlSelectAll = checkSelectAll;
                }
                EditorGUILayout.EndVertical();
                EditorGUILayout.BeginVertical();
                {
                    EditorGUILayout.LabelField("Added Controls:", headingStyle);
                    if (GUILayout.Button("Remove Controls", scrollViewBtnWidth))
                    {
                        RemoveControls();
                        sceneControlObjectList = LiveUnityInterface.GetControls(charSetupData.GetControlList());
                    }
                    bool checkSelectAll;
                    bool checkSort;
                    EditorGUILayout.BeginHorizontal();
                    {
                        checkSelectAll = GUILayout.Toggle(addedControlSelectAll, "Select All");
                        checkSort      = GUILayout.Toggle(sortAddedControl, "Sort A-Z");
                    }
                    EditorGUILayout.EndHorizontal();

                    EditorGUILayout.BeginHorizontal(scrollviewBgStyle, GUILayout.Width(200));
                    {
                        addedControlScrollPos = EditorGUILayout.BeginScrollView(addedControlScrollPos, false, false, scrollViewWidth, scrollViewHeight);
                        PopulateControlScrollView(addedControls, addedControlSelectAll != checkSelectAll, checkSelectAll, checkSort);
                        EditorGUILayout.EndScrollView();
                    }
                    EditorGUILayout.EndHorizontal();

                    sortAddedControl      = checkSort;
                    addedControlSelectAll = checkSelectAll;
                }
                EditorGUILayout.EndVertical();
            }
            EditorGUILayout.EndHorizontal();
        }
        EditorGUILayout.EndVertical();
        CreateSpace(2);
    }