//----------------------------------------------------------------------------------------------------------------------
        public void Setup(VisualElement root)
        {
            VisualTreeAsset   tab         = UIElementsEditorUtility.LoadVisualTreeAsset(Constants.SCENE_CACHE_PLAYER_SETTINGS_TAB_PATH);
            TemplateContainer tabInstance = tab.CloneTree();

            VisualElement content = tabInstance.Query <VisualElement>("Content").First();

            m_generatedSCResPathTextField = tabInstance.Query <TextField>("GeneratedSCResPathText").First();
            m_generatedSCResPathTextField.RegisterValueChangedCallback((ChangeEvent <string> changeEvent) => {
                MeshSyncRuntimeSettings settings = MeshSyncRuntimeSettings.GetOrCreateSettings();
                settings.SetSceneCacheOutputPath(changeEvent.newValue);
                settings.SaveSettings();
            });

            m_outputPathSelectButton          = tabInstance.Query <Button>("OutputPathSelectButton").First();
            m_outputPathSelectButton.clicked += OnOutputPathSelectButtonClicked;
            RefreshSettings();

            //MeshSyncPlayerConfig
            MeshSyncPlayerConfigSection section = new MeshSyncPlayerConfigSection(MeshSyncPlayerType.CACHE_PLAYER);

            section.Setup(content);

            root.Add(tabInstance);
        }
        static void CreateSceneCachePlayerMenu(MenuCommand menuCommand)
        {
            string sceneCacheFilePath = EditorUtility.OpenFilePanelWithFilters("Select Cache File", "",
                                                                               new string[] { "All supported files", "sc", "All files", "*" });

            if (string.IsNullOrEmpty(sceneCacheFilePath))
            {
                return;
            }

            //Prefab and assets path
            MeshSyncRuntimeSettings runtimeSettings = MeshSyncRuntimeSettings.GetOrCreateSettings();

            string scOutputPath   = runtimeSettings.GetSceneCacheOutputPath();
            string prefabFileName = Path.GetFileNameWithoutExtension(sceneCacheFilePath);
            string prefabPath     = $"{scOutputPath}/{prefabFileName}.prefab";
            string assetsFolder   = Path.Combine(scOutputPath, prefabFileName);

            bool created = SceneCachePlayerEditorUtility.CreateSceneCachePlayerAndPrefab(sceneCacheFilePath, prefabPath,
                                                                                         assetsFolder, out SceneCachePlayer player, out GameObject prefab);


            if (!created)
            {
                EditorUtility.DisplayDialog("MeshSync"
                                            , "Failed to open " + sceneCacheFilePath
                                            + ". Possible reasons: file format version does not match, or the file is not scene cache."
                                            , "Ok"
                                            );
            }
        }
//----------------------------------------------------------------------------------------------------------------------
        void OnOutputPathSelectButtonClicked()
        {
            string path = EditorUtility.OpenFolderPanel("Select Scene Cache Output Path",
                                                        m_generatedSCResPathTextField.value,
                                                        "");

            if (string.IsNullOrEmpty(path))
            {
                return;
            }

            if (!path.StartsWith(Application.dataPath))
            {
                EditorUtility.DisplayDialog("MeshSync",
                                            $"Invalid path: {path}. " +
                                            "Path has to be under the Assets folder.",
                                            "Ok");
                return;
            }

            MeshSyncRuntimeSettings settings = MeshSyncRuntimeSettings.GetOrCreateSettings();

            path = AssetUtility.NormalizeAssetPath(path);
            settings.SetSceneCacheOutputPath(path);
            settings.SaveSettings();

            RefreshSettings();
        }
示例#4
0
//----------------------------------------------------------------------------------------------------------------------

        //Support Toggle, FloatField, etc
        private F AddPlayerConfigField <F, V>(VisualTreeAsset template, VisualElement parent, GUIContent content,
                                              Action <MeshSyncPlayerConfig, V> onValueChanged) where F : VisualElement, INotifyValueChanged <V>, new()
        {
            TemplateContainer templateInstance = template.CloneTree();
            VisualElement     fieldContainer   = templateInstance.Query <VisualElement>("FieldContainer").First();
//		F field = templateInstance.Query<F>().First();
            Label label = templateInstance.Query <Label>().First();

            label.text    = content.text;
            label.tooltip = content.tooltip;

            F field = new F();

            field.AddToClassList("general-settings-field");
            field.RegisterValueChangedCallback((ChangeEvent <V> changeEvent) => {
                MeshSyncPlayerConfig config = field.userData as MeshSyncPlayerConfig;
                if (null == config)
                {
                    Debug.LogError("[MeshSync] Field doesn't have the correct user data");
                    return;
                }

                onValueChanged(config, changeEvent.newValue);
                MeshSyncRuntimeSettings.GetOrCreateSettings().SaveSettings();
            });

            fieldContainer.Add(field);
            parent.Add(templateInstance);
            m_playerConfigUIElements.Add(field);
            return(field);
        }
示例#5
0
//----------------------------------------------------------------------------------------------------------------------
        private PopupField <T> AddPlayerConfigPopupField <T>(VisualTreeAsset template, VisualElement parent, GUIContent content,
                                                             List <T> options, Action <MeshSyncPlayerConfig, int> onValueChanged)
        {
            TemplateContainer templateInstance = template.CloneTree();
            VisualElement     fieldContainer   = templateInstance.Query <VisualElement>("FieldContainer").First();
            PopupField <T>    popupField       = new PopupField <T>(options, options[0]);

            popupField.AddToClassList("general-settings-field");

            Label label = templateInstance.Query <Label>().First();

            label.text    = content.text;
            label.tooltip = content.tooltip;
            popupField.RegisterValueChangedCallback((ChangeEvent <T> changeEvent) => {
                MeshSyncPlayerConfig config = popupField.userData as MeshSyncPlayerConfig;
                if (null == config)
                {
                    Debug.LogError("[MeshSync] Toggle doesn't have the correct user data");
                    return;
                }

                onValueChanged(config, popupField.index);
                MeshSyncRuntimeSettings.GetOrCreateSettings().SaveSettings();
            });

            fieldContainer.Add(popupField);
            parent.Add(templateInstance);
            m_playerConfigUIElements.Add(popupField);
            return(popupField);
        }
        public void CreateRuntimeSettings()
        {
            MeshSyncRuntimeSettings runtimeSettings = MeshSyncRuntimeSettings.GetOrCreateSettings();

            Assert.NotNull(runtimeSettings);
            Assert.True(File.Exists(runtimeSettings.GetSettingsPath()));
        }
示例#7
0
        public IEnumerator SetServerPublicAccess()
        {
            EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects);

            MeshSyncRuntimeSettings runtimeSettings = MeshSyncRuntimeSettings.GetOrCreateSettings();
            MeshSyncServer          mss             = MeshSyncServerEditor.CreateMeshSyncServer(true);

            Assert.IsTrue(mss.IsServerStarted());
            yield return(null);

            //Check the original public access
            bool origPublicAccess = runtimeSettings.GetServerPublicAccess();

            UnityEngine.Assertions.Assert.AreEqual(origPublicAccess, mss.DoesServerAllowPublicAccess());
            yield return(null);

            //Change the public access and check
            runtimeSettings.SetServerPublicAccess(!origPublicAccess);
            mss.StopServer();
            mss.StartServer();
            Assert.IsTrue(mss.IsServerStarted());
            yield return(null);

            UnityEngine.Assertions.Assert.AreEqual(runtimeSettings.GetServerPublicAccess(), mss.DoesServerAllowPublicAccess());

            //Change back
            runtimeSettings.SetServerPublicAccess(origPublicAccess);
            UnityEngine.Assertions.Assert.AreEqual(origPublicAccess, runtimeSettings.GetServerPublicAccess());
        }
示例#8
0
        public IEnumerator CheckServerSettings()
        {
            MeshSyncServer          mss             = MeshSyncMenu.CreateMeshSyncServer(true);
            MeshSyncRuntimeSettings runtimeSettings = MeshSyncRuntimeSettings.GetOrCreateSettings();

            Assert.AreEqual(runtimeSettings.GetDefaultServerPort(), mss.GetServerPort());
            yield return(null);
        }
//----------------------------------------------------------------------------------------------------------------------    
    
    internal static void ChangeSceneCacheFile(SceneCachePlayer cachePlayer, string sceneCacheFilePath) {
        string     prefabPath = null;
        GameObject go         = cachePlayer.gameObject;
        //Check if it's possible to reuse the old assetsFolder
        string assetsFolder = cachePlayer.GetAssetsFolder();
        if (string.IsNullOrEmpty(assetsFolder)) {
            MeshSyncRuntimeSettings runtimeSettings = MeshSyncRuntimeSettings.GetOrCreateSettings();        
            string                  scOutputPath    = runtimeSettings.GetSceneCacheOutputPath();            
            assetsFolder = Path.Combine(scOutputPath, Path.GetFileNameWithoutExtension(sceneCacheFilePath));
        }
        
        bool isPrefabInstance = cachePlayer.gameObject.IsPrefabInstance();        
        //We are directly modifying a prefab
        if (!isPrefabInstance && go.IsPrefab()) {
            prefabPath = AssetDatabase.GetAssetPath(go);
            CreateSceneCachePlayerAndPrefab(sceneCacheFilePath, prefabPath, assetsFolder, out SceneCachePlayer player,
                out GameObject newPrefab);
            Object.DestroyImmediate(player.gameObject);
            return;

        } 
        
        if (isPrefabInstance) {
            GameObject prefab = PrefabUtility.GetCorrespondingObjectFromSource(cachePlayer.gameObject);
            prefabPath = AssetDatabase.GetAssetPath(prefab);
        } 
        
        cachePlayer.CloseCache();
        
        //[TODO-sin: 2020-9-28] Find out if it is possible to do undo properly
        Undo.RegisterFullObjectHierarchyUndo(cachePlayer.gameObject, "SceneCachePlayer");
        
        cachePlayer.Init(assetsFolder);
        cachePlayer.OpenCacheInEditor(sceneCacheFilePath);

        //Save as prefab again
        if (string.IsNullOrEmpty(prefabPath)) {
            return;
        }
        
        //Prevent overwriting ".sc" file itself
        bool isPrefabExt = (Path.GetExtension(prefabPath).ToLower() == ".prefab");
        if (isPrefabExt) {
            cachePlayer.gameObject.SaveAsPrefab(prefabPath);            
        }        
    }
示例#10
0
//----------------------------------------------------------------------------------------------------------------------

        private void UpdatePlayerConfigUIElements(MeshSyncPlayerType playerType)
        {
            MeshSyncRuntimeSettings runtimeSettings = MeshSyncRuntimeSettings.GetOrCreateSettings();
            MeshSyncPlayerConfig    config          = runtimeSettings.GetDefaultPlayerConfig(playerType);

            //sync
            m_syncVisibilityToggle.SetValueWithoutNotify(config.SyncVisibility);
            m_syncTransformToggle.SetValueWithoutNotify(config.SyncTransform);
            m_syncCamerasToggle.SetValueWithoutNotify(config.SyncCameras);
            m_syncLightsToggle.SetValueWithoutNotify(config.SyncLights);
            m_syncMeshesToggle.SetValueWithoutNotify(config.SyncMeshes);
            m_updateMeshCollidersToggle.SetValueWithoutNotify(config.UpdateMeshColliders);
            m_syncMaterialsToggle.SetValueWithoutNotify(config.SyncMaterials);
            m_findMaterialFromAssetsToggle.SetValueWithoutNotify(config.FindMaterialFromAssets);

            //Import
            m_animationInterpolationPopup.SetValueWithoutNotify(m_animationInterpolationEnums[config.AnimationInterpolation]);
            m_keyframeReductionToggle.SetValueWithoutNotify(config.KeyframeReduction);
            m_reductionThresholdField.SetValueWithoutNotify(config.ReductionThreshold);
            m_reductionEraseFlatCurves.SetValueWithoutNotify(config.ReductionEraseFlatCurves);
            m_zUpCorrectionPopup.SetValueWithoutNotify(m_zUpCorrectionEnums[config.ZUpCorrection]);

            //Misc
            m_syncMaterialListToggle.SetValueWithoutNotify(config.SyncMaterialList);
            m_progressiveDisplayToggle.SetValueWithoutNotify(config.ProgressiveDisplay);
            m_loggingToggle.SetValueWithoutNotify(config.Logging);
            m_profilingToggle.SetValueWithoutNotify(config.Profiling);

            //Animation Tweak
            AnimationTweakSettings animationTweakSettings = config.GetAnimationTweakSettings();

            m_animationTweakTimeScaleField.SetValueWithoutNotify(animationTweakSettings.TimeScale);
            m_animationTweakTimeOffsetField.SetValueWithoutNotify(animationTweakSettings.TimeOffset);
            m_animationTweakDropStepField.SetValueWithoutNotify(animationTweakSettings.DropStep);
            m_animationTweakReductionThresholdField.SetValueWithoutNotify(animationTweakSettings.ReductionThreshold);
            m_animationTweakEraseFlatCurvesToggle.SetValueWithoutNotify(animationTweakSettings.EraseFlatCurves);

            //userData
            foreach (VisualElement uiElement in m_playerConfigUIElements)
            {
                uiElement.userData = config;
            }


            m_selectedPlayerType = playerType;
        }
//----------------------------------------------------------------------------------------------------------------------    

    private static bool ValidateSceneCacheOutputPath() {
        
        MeshSyncRuntimeSettings runtimeSettings = MeshSyncRuntimeSettings.GetOrCreateSettings();
        string                  scOutputPath    = runtimeSettings.GetSceneCacheOutputPath();
        if (!scOutputPath.StartsWith("Assets")) {
            DisplaySceneCacheOutputPathErrorDialog(scOutputPath);
            return false;            
        }        
        
        try {
            Directory.CreateDirectory(scOutputPath);
        } catch {
            DisplaySceneCacheOutputPathErrorDialog(scOutputPath);
            return false;
        }

        return true;
    }
示例#12
0
//----------------------------------------------------------------------------------------------------------------------
        public void Setup(VisualElement root)
        {
            VisualTreeAsset   tab         = UIElementsEditorUtility.LoadVisualTreeAsset(Constants.SERVER_SETTINGS_TAB_PATH);
            TemplateContainer tabInstance = tab.CloneTree();

            VisualElement content = tabInstance.Query <VisualElement>("Content").First();


            //Templates
            VisualTreeAsset         fieldTemplate   = LoadVisualTreeAsset(Constants.PROJECT_SETTINGS_FIELD_TEMPLATE_PATH);
            MeshSyncRuntimeSettings runtimeSettings = MeshSyncRuntimeSettings.GetOrCreateSettings();

            //Add server port
            m_serverPortField = AddField <IntegerField, int>(fieldTemplate, content, Contents.ServerPort,
                                                             runtimeSettings.GetDefaultServerPort(),
                                                             (int newValue) => {
                MeshSyncRuntimeSettings settings = MeshSyncRuntimeSettings.GetOrCreateSettings();
                settings.SetDefaultServerPort((ushort)newValue);
            }
                                                             );

            m_allowPublicAccessToggle = AddField <Toggle, bool>(fieldTemplate, content, Contents.AllowPublicAccess,
                                                                runtimeSettings.GetServerPublicAccess(),
                                                                (bool newValue) => {
                MeshSyncRuntimeSettings settings = MeshSyncRuntimeSettings.GetOrCreateSettings();
                settings.SetServerPublicAccess(newValue);
            }
                                                                );


            //MeshSyncPlayerConfig section
            MeshSyncPlayerConfigSection section = new MeshSyncPlayerConfigSection(MeshSyncPlayerType.SERVER);

            section.Setup(content);



            root.Add(tabInstance);
        }
示例#13
0
//----------------------------------------------------------------------------------------------------------------------

        //Support Toggle, FloatField, etc
        private F AddField <F, V>(VisualTreeAsset template, VisualElement parent, GUIContent content,
                                  V initialValue, Action <V> onValueChanged) where F : VisualElement, INotifyValueChanged <V>, new()
        {
            TemplateContainer templateInstance = template.CloneTree();
            VisualElement     fieldContainer   = templateInstance.Query <VisualElement>("FieldContainer").First();
            Label             label            = templateInstance.Query <Label>().First();

            label.text    = content.text;
            label.tooltip = content.tooltip;

            F field = new F();

            field.AddToClassList("project-settings-field");
            field.SetValueWithoutNotify(initialValue);
            field.RegisterValueChangedCallback((ChangeEvent <V> changeEvent) => {
                onValueChanged(changeEvent.newValue);
                MeshSyncRuntimeSettings.GetOrCreateSettings().SaveSettings();
            });

            fieldContainer.Add(field);
            parent.Add(templateInstance);
            return(field);
        }
//----------------------------------------------------------------------------------------------------------------------

        void RefreshSettings()
        {
            MeshSyncRuntimeSettings settings = MeshSyncRuntimeSettings.GetOrCreateSettings();

            m_generatedSCResPathTextField.value = settings.GetSceneCacheOutputPath();
        }
示例#15
0
//----------------------------------------------------------------------------------------------------------------------
        public void Setup(VisualElement root)
        {
            m_playerConfigUIElements = new List <VisualElement>();
            VisualTreeAsset container = UIElementsEditorUtility.LoadVisualTreeAsset(
                Path.Combine(MeshSyncEditorConstants.PROJECT_SETTINGS_UIELEMENTS_PATH, "GeneralSettings_Container")
                );
            TemplateContainer containerInstance = container.CloneTree();


            List <string> objectTypes = new List <string> {
                MeshSyncPlayerType.SERVER.ToString(),
                          MeshSyncPlayerType.CACHE_PLAYER.ToString(),
            };

            //Templates
            VisualTreeAsset fieldTemplate = UIElementsEditorUtility.LoadVisualTreeAsset(
                Path.Combine(MeshSyncEditorConstants.PROJECT_SETTINGS_UIELEMENTS_PATH, "GeneralSettingsFieldTemplate")
                );

            MeshSyncRuntimeSettings runtimeSettings = MeshSyncRuntimeSettings.GetOrCreateSettings();
            VisualElement           headerContainer = containerInstance.Query <VisualElement>("HeaderContainer").First();

            //Add server port
            Foldout serverSettingsFoldout = containerInstance.Query <Foldout>("ServerSettingsFoldout").First();

            m_serverPortField = AddField <IntegerField, int>(fieldTemplate, serverSettingsFoldout, Contents.ServerPort,
                                                             runtimeSettings.GetDefaultServerPort(),
                                                             (int newValue) => {
                MeshSyncRuntimeSettings settings = MeshSyncRuntimeSettings.GetOrCreateSettings();
                settings.SetDefaultServerPort((ushort)newValue);
            }
                                                             );

            m_allowPublicAccessToggle = AddField <Toggle, bool>(fieldTemplate, serverSettingsFoldout, Contents.AllowPublicAccess,
                                                                runtimeSettings.GetServerPublicAccess(),
                                                                (bool newValue) => {
                MeshSyncRuntimeSettings settings = MeshSyncRuntimeSettings.GetOrCreateSettings();
                settings.SetServerPublicAccess(newValue);
            }
                                                                );


            //Add playerType popup
            VisualElement       playerTypePopupContainer = containerInstance.Query <VisualElement>("PlayerTypePopupContainer").First();
            PopupField <string> playerTypePopup          = new PopupField <string>("Settings for Object Type", objectTypes, objectTypes[0]);

            playerTypePopup.RegisterValueChangedCallback(OnPlayerTypePopupChanged);
            playerTypePopupContainer.Add(playerTypePopup);


            Foldout syncSettingsFoldout = containerInstance.Query <Foldout>("SyncSettingsFoldout").First();

            //Sync
            m_syncVisibilityToggle = AddPlayerConfigField <Toggle, bool>(fieldTemplate, syncSettingsFoldout, Contents.Visibility,
                                                                         (MeshSyncPlayerConfig config, bool newValue) => { config.SyncVisibility = newValue; }
                                                                         );
            m_syncTransformToggle = AddPlayerConfigField <Toggle, bool>(fieldTemplate, syncSettingsFoldout, Contents.Transform,
                                                                        (MeshSyncPlayerConfig config, bool newValue) => { config.SyncTransform = newValue; }
                                                                        );
            m_syncCamerasToggle = AddPlayerConfigField <Toggle, bool>(fieldTemplate, syncSettingsFoldout, Contents.Cameras,
                                                                      (MeshSyncPlayerConfig config, bool newValue) => { config.SyncCameras = newValue; }
                                                                      );
            m_syncLightsToggle = AddPlayerConfigField <Toggle, bool>(fieldTemplate, syncSettingsFoldout, Contents.Lights,
                                                                     (MeshSyncPlayerConfig config, bool newValue) => { config.SyncLights = newValue; }
                                                                     );
            m_syncMeshesToggle = AddPlayerConfigField <Toggle, bool>(fieldTemplate, syncSettingsFoldout, Contents.Meshes,
                                                                     (MeshSyncPlayerConfig config, bool newValue) => { config.SyncMeshes = newValue; }
                                                                     );
            m_updateMeshCollidersToggle = AddPlayerConfigField <Toggle, bool>(fieldTemplate, syncSettingsFoldout,
                                                                              Contents.UpdateMeshColliders,
                                                                              (MeshSyncPlayerConfig config, bool newValue) => { config.UpdateMeshColliders = newValue; }
                                                                              );
            m_syncMaterialsToggle = AddPlayerConfigField <Toggle, bool>(fieldTemplate, syncSettingsFoldout, Contents.Materials,
                                                                        (MeshSyncPlayerConfig config, bool newValue) => { config.SyncMaterials = newValue; }
                                                                        );
            m_findMaterialFromAssetsToggle = AddPlayerConfigField <Toggle, bool>(fieldTemplate, syncSettingsFoldout,
                                                                                 Contents.FindMaterialsFromAssetDatabase,
                                                                                 (MeshSyncPlayerConfig config, bool newValue) => { config.FindMaterialFromAssets = newValue; }
                                                                                 );

            //import
            Foldout importSettingsFoldout = containerInstance.Query <Foldout>("ImportSettingsFoldout").First();

            m_animationInterpolationPopup = AddPlayerConfigPopupField(fieldTemplate, importSettingsFoldout,
                                                                      Contents.AnimationInterpolation, m_animationInterpolationEnums,
                                                                      (MeshSyncPlayerConfig config, int newValue) => { config.AnimationInterpolation = newValue; }
                                                                      );
            m_keyframeReductionToggle = AddPlayerConfigField <Toggle, bool>(fieldTemplate, importSettingsFoldout,
                                                                            Contents.KeyframeReduction,
                                                                            (MeshSyncPlayerConfig config, bool newValue) => { config.KeyframeReduction = newValue; }
                                                                            );
            m_reductionThresholdField = AddPlayerConfigField <FloatField, float>(fieldTemplate, importSettingsFoldout,
                                                                                 Contents.ReductionThreshold,
                                                                                 (MeshSyncPlayerConfig config, float newValue) => { config.ReductionThreshold = newValue; }
                                                                                 );
            m_reductionEraseFlatCurves = AddPlayerConfigField <Toggle, bool>(fieldTemplate, importSettingsFoldout,
                                                                             Contents.ReductionEraseFlatCurves,
                                                                             (MeshSyncPlayerConfig config, bool newValue) => { config.ReductionEraseFlatCurves = newValue; }
                                                                             );
            m_zUpCorrectionPopup = AddPlayerConfigPopupField(fieldTemplate, importSettingsFoldout,
                                                             Contents.ZUpCorrection, m_zUpCorrectionEnums,
                                                             (MeshSyncPlayerConfig config, int newValue) => { config.ZUpCorrection = newValue; }
                                                             );

            //Misc
            Foldout miscSettingsFoldout = containerInstance.Query <Foldout>("MiscSettingsFoldout").First();

            m_syncMaterialListToggle = AddPlayerConfigField <Toggle, bool>(fieldTemplate, miscSettingsFoldout,
                                                                           Contents.SyncMaterialList,
                                                                           (MeshSyncPlayerConfig config, bool newValue) => { config.SyncMaterialList = newValue; }
                                                                           );
            m_progressiveDisplayToggle = AddPlayerConfigField <Toggle, bool>(fieldTemplate, miscSettingsFoldout,
                                                                             Contents.ProgressiveDisplay,
                                                                             (MeshSyncPlayerConfig config, bool newValue) => { config.ProgressiveDisplay = newValue; }
                                                                             );
            m_loggingToggle = AddPlayerConfigField <Toggle, bool>(fieldTemplate, miscSettingsFoldout,
                                                                  Contents.Logging,
                                                                  (MeshSyncPlayerConfig config, bool newValue) => { config.Logging = newValue; }
                                                                  );
            m_profilingToggle = AddPlayerConfigField <Toggle, bool>(fieldTemplate, miscSettingsFoldout,
                                                                    Contents.Profiling,
                                                                    (MeshSyncPlayerConfig config, bool newValue) => { config.Profiling = newValue; }
                                                                    );

            //Animation Tweak
            Foldout animationTweakSettingsFoldout = containerInstance.Query <Foldout>("AnimationTweakSettingsFoldout").First();

            m_animationTweakTimeScaleField = AddPlayerConfigField <FloatField, float>(fieldTemplate, animationTweakSettingsFoldout,
                                                                                      Contents.TweakTimeScale,
                                                                                      (MeshSyncPlayerConfig config, float newValue) => {
                config.GetAnimationTweakSettings().TimeScale = newValue;
            }
                                                                                      );
            m_animationTweakTimeOffsetField = AddPlayerConfigField <FloatField, float>(fieldTemplate, animationTweakSettingsFoldout,
                                                                                       Contents.TweakTimeOffset,
                                                                                       (MeshSyncPlayerConfig config, float newValue) => {
                config.GetAnimationTweakSettings().TimeOffset = newValue;
            }
                                                                                       );
            m_animationTweakDropStepField = AddPlayerConfigField <IntegerField, int>(fieldTemplate, animationTweakSettingsFoldout,
                                                                                     Contents.TweakDropStep,
                                                                                     (MeshSyncPlayerConfig config, int newValue) => {
                config.GetAnimationTweakSettings().DropStep = newValue;
            }
                                                                                     );
            m_animationTweakReductionThresholdField = AddPlayerConfigField <FloatField, float>(fieldTemplate, animationTweakSettingsFoldout,
                                                                                               Contents.TweakReductionThreshold,
                                                                                               (MeshSyncPlayerConfig config, float newValue) => {
                config.GetAnimationTweakSettings().ReductionThreshold = newValue;
            }
                                                                                               );
            m_animationTweakEraseFlatCurvesToggle = AddPlayerConfigField <Toggle, bool>(fieldTemplate, animationTweakSettingsFoldout,
                                                                                        Contents.TweakEraseFlatCurves,
                                                                                        (MeshSyncPlayerConfig config, bool newValue) => {
                config.GetAnimationTweakSettings().EraseFlatCurves = newValue;
            }
                                                                                        );

            UpdatePlayerConfigUIElements(MeshSyncPlayerType.SERVER);

            root.Add(containerInstance);
        }