protected override void Rebuild(VisualElement root)
    {
        _localPlayerProfiles = PlayerProfileService.LoadProfilesOnDisk();

        _localPlayerProfileNames = new string[_localPlayerProfiles.Count + 1];
        for (int i = 0; i < _localPlayerProfiles.Count; i++)
        {
            _localPlayerProfileNames[i] = _localPlayerProfiles[i].playerName;
        }
        _localPlayerProfileNames[_localPlayerProfiles.Count] = "- none -";

        _profileElements.Clear();

        ////////////////////////////////////////////////////////////////////////////////////////
        //      Build
        ////////////////////////////////////////////////////////////////////////////////////////

        {
            var element = root.Q <Button>(name: "buildGame");
            element.clickable.clicked += OnClick_BuildGame;
        }

        {
            var element = root.Q <Button>(name: "buildGameAndRun");
            element.clickable.clicked += OnClick_BuildGameAndRun;
        }

        {
            var element = root.Q <Button>(name: "openBuildFolder");
            element.clickable.clicked += OnClick_OpenBuildFolder;
        }

        ////////////////////////////////////////////////////////////////////////////////////////
        //      Launch
        ////////////////////////////////////////////////////////////////////////////////////////
        {
            var element           = root.Q <Toggle>(name: "fromScratch");
            var childrenContainer = root.Q <VisualElement>(name: "startingPointContainer");

            element.value = EditorLaunchData.playFromScratch;
            childrenContainer.EnableInClassList("hidden", element.value);

            element.RegisterValueChangedCallback(
                (ChangeEvent <bool> changeEvent) =>
            {
                EditorLaunchData.playFromScratch = changeEvent.newValue;
                childrenContainer.EnableInClassList("hidden", changeEvent.newValue);
            });
        }

        {
            var container = root.Q <VisualElement>(name: "startingPointContainer");
            var levelBank = AssetDatabaseX.LoadAssetsOfType <LevelBank>().FirstOrDefault();

            List <string> levels = new List <string>();
            levels.Add(""); // the 'none' option

            if (levelBank != null)
            {
                foreach (var item in levelBank.Levels)
                {
                    levels.Add(item.name);
                }

                levels.Sort();
            }

            string levelToDisplayName(string level)
            {
                if (string.IsNullOrEmpty(level))
                {
                    return("- None -");
                }
                return(level);
            }

            _elementLevel = new PopupField <string>("Level", levels, 0,
                                                    formatSelectedValueCallback: levelToDisplayName,
                                                    formatListItemCallback: levelToDisplayName);

            container.Insert(0, _elementLevel);

            if (levels.Contains(EditorLaunchData.level))
            {
                _elementLevel.value = EditorLaunchData.level;
            }

            _elementLevel.RegisterValueChangedCallback(
                (ChangeEvent <string> changeEvent) =>
            {
                EditorLaunchData.level = changeEvent.newValue;
            });
        }

        {
            var elementPlayOnline = root.Q <Toggle>(name: "online");
            var elementServerName = root.Q <TextField>(name: "serverName");

            elementServerName.value = EditorLaunchData.serverName;
            elementServerName.RegisterValueChangedCallback(
                (ChangeEvent <string> changeEvent) =>
            {
                EditorLaunchData.serverName = changeEvent.newValue;
            });

            elementPlayOnline.value = EditorLaunchData.playOnline;
            elementPlayOnline.RegisterValueChangedCallback(
                (ChangeEvent <bool> changeEvent) =>
            {
                EditorLaunchData.playOnline = changeEvent.newValue;

                for (int i = 0; i < _profileElements.Count; i++)
                {
                    _profileElements[i].UpdateContent();
                }

                elementServerName.EnableInClassList("hidden", !changeEvent.newValue);
            });

            elementServerName.EnableInClassList("hidden", !elementPlayOnline.value);
        }

        {
            var element = root.Q <Foldout>(name: "advFoldout");
            element.value = false;
            element.text  = "Advanced";
        }

        {
            var element = root.Q <Toggle>(name: "headless");
            element.value = EditorLaunchData.serverIsHeadless;
            element.RegisterValueChangedCallback(
                (ChangeEvent <bool> changeEvent) =>
            {
                EditorLaunchData.serverIsHeadless = changeEvent.newValue;
            });
        }

        {
            var element = root.Q <TextField>(name: "extraArgs");
            element.value = EditorLaunchData.extraArguments;
            element.RegisterValueChangedCallback(
                (ChangeEvent <string> changeEvent) =>
            {
                GameConsole.EditorPlayCommands  = CommandLine.SplitCommandLineInGroups(changeEvent.newValue).ToArray();
                EditorLaunchData.extraArguments = changeEvent.newValue;
            });
        }

        {
            var element           = root.Q <Toggle>(name: "overrideScreen");
            var childrenContainer = root.Q <VisualElement>(name: "overrideScreenContainer");

            element.value = EditorLaunchData.launchOverrideScreen;
            childrenContainer.EnableInClassList("hidden", !element.value);

            element.RegisterValueChangedCallback(
                (ChangeEvent <bool> changeEvent) =>
            {
                EditorLaunchData.launchOverrideScreen = changeEvent.newValue;
                childrenContainer.EnableInClassList("hidden", !changeEvent.newValue);
            });
        }

        {
            var element = root.Q <Toggle>(name: "fullscreen");
            element.value = EditorLaunchData.launchFullscreen;
            element.RegisterValueChangedCallback(
                (ChangeEvent <bool> changeEvent) =>
            {
                EditorLaunchData.launchFullscreen = changeEvent.newValue;
            });
        }

        {
            var element = root.Q <IntegerField>(name: "screenWidth");
            element.value = EditorLaunchData.launchScreenWidth;
            element.RegisterValueChangedCallback(
                (ChangeEvent <int> changeEvent) =>
            {
                EditorLaunchData.launchScreenWidth = changeEvent.newValue;
            });
        }

        {
            var element = root.Q <IntegerField>(name: "screenHeight");
            element.value = EditorLaunchData.launchScreenHeight;
            element.RegisterValueChangedCallback(
                (ChangeEvent <int> changeEvent) =>
            {
                EditorLaunchData.launchScreenHeight = changeEvent.newValue;
            });
        }

        {
            var element = root.Q <VisualElement>(name: "profilesContainer");

            int whoIsServer = EditorLaunchData.whoIsServerId;
            int whoIsEditor = EditorLaunchData.whoIsEditorId;
            for (int i = 0; i < _localPlayerProfiles.Count; i++)
            {
                PlayerProfile        profile    = _localPlayerProfiles[i];
                LaunchProfileElement newElement = new LaunchProfileElement(profile)
                {
                    IsMarkedAsServer = (whoIsServer == profile.localId),
                    IsMarkedAsEditor = (whoIsEditor == profile.localId),
                };

                newElement.focusable   = true;
                newElement.pickingMode = PickingMode.Position;
                newElement.AddManipulator(new ContextualMenuManipulator((ContextualMenuPopulateEvent evt) =>
                {
                    evt.menu.AppendAction("Set Server", (DropdownMenuAction action) =>
                    {
                        if (newElement.IsMarkedAsServer)
                        {
                            SetAsServer(null);
                        }
                        else
                        {
                            SetAsServer(newElement);
                        }
                    }, status: newElement.IsMarkedAsServer?DropdownMenuAction.Status.Checked: DropdownMenuAction.Status.Normal);
                    evt.menu.AppendAction("Set Editor", (DropdownMenuAction action) =>
                    {
                        if (newElement.IsMarkedAsEditor)
                        {
                            SetAsEditor(null);
                        }
                        else
                        {
                            SetAsEditor(newElement);
                        }
                    }, status: newElement.IsMarkedAsEditor?DropdownMenuAction.Status.Checked: DropdownMenuAction.Status.Normal);
                }));

                _profileElements.Add(newElement);
                element.Add(newElement);
            }
        }

        UpdateFromScenes();
    }