public override void OnInspectorGUI() { serializedObject.Update(); var script = serializedObject.FindProperty("m_Script"); var updateRate = serializedObject.FindProperty("UpdateRate"); var positionThreshold = serializedObject.FindProperty("PositionThreshold"); var rotationThreshold = serializedObject.FindProperty("RotationThreshold"); var scaleThreshold = serializedObject.FindProperty("ScaleThreshold"); var useCustomId = serializedObject.FindProperty("UseCustomId"); var customId = serializedObject.FindProperty("CustomId"); var commonMeshName = serializedObject.FindProperty("CommonMesh"); var meshname = serializedObject.FindProperty("MeshName"); var useCustomMesh = serializedObject.FindProperty("UseCustomMesh"); var isController = serializedObject.FindProperty("IsController"); var syncWithGaze = serializedObject.FindProperty("SyncWithPlayerGazeTick"); var idPool = serializedObject.FindProperty("IdPool"); foreach (var t in serializedObject.targetObjects) //makes sure a custom id is valid { var dynamic = t as DynamicObject; if (dynamic.editorInstanceId != dynamic.GetInstanceID() || string.IsNullOrEmpty(dynamic.CustomId)) //only check if something has changed on a dynamic, or if the id is empty { if (dynamic.UseCustomId && idType == 0) { if (string.IsNullOrEmpty(AssetDatabase.GetAssetPath(dynamic.gameObject)))//scene asset { dynamic.editorInstanceId = dynamic.GetInstanceID(); CheckCustomId(); } else //project asset { dynamic.editorInstanceId = dynamic.GetInstanceID(); if (string.IsNullOrEmpty(dynamic.CustomId)) { string s = System.Guid.NewGuid().ToString(); dynamic.CustomId = "editor_" + s; } } } } } //display script on component EditorGUI.BeginDisabledGroup(true); EditorGUILayout.PropertyField(script, true, new GUILayoutOption[0]); EditorGUI.EndDisabledGroup(); //use custom mesh and mesh text field GUILayout.BeginHorizontal(); UnityEditor.EditorGUILayout.PropertyField(useCustomMesh); bool anycustomnames = false; foreach (var t in targets) { var dyn = t as DynamicObject; if (dyn.UseCustomMesh) { anycustomnames = true; if (string.IsNullOrEmpty(dyn.MeshName)) { dyn.MeshName = dyn.gameObject.name.ToLower().Replace(" ", "_").Replace("<", "_").Replace(">", "_").Replace("|", "_").Replace("?", "_").Replace("*", "_").Replace("\"", "_").Replace("/", "_").Replace("\\", "_").Replace(":", "_"); if (!Application.isPlaying) { UnityEditor.EditorUtility.SetDirty(dyn); UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene()); } } if (targets.Length == 1) { dyn.MeshName = UnityEditor.EditorGUILayout.TextField("", dyn.MeshName); } } } if (!anycustomnames) { UnityEditor.EditorGUILayout.PropertyField(commonMeshName, new GUIContent("")); } GUILayout.EndHorizontal(); if (idType == -1) { var dyn = target as DynamicObject; if (dyn.UseCustomId) { idType = 0; } else if (dyn.IdPool != null) { idType = 2; } else { idType = 1; } } GUILayout.BeginHorizontal(); idType = EditorGUILayout.Popup(new GUIContent("Id Source"), idType, idTypeNames); if (idType == 0) //custom id { EditorGUILayout.PropertyField(customId, new GUIContent("")); useCustomId.boolValue = true; idPool.objectReferenceValue = null; } else if (idType == 1) //generate id { EditorGUI.BeginDisabledGroup(true); EditorGUILayout.LabelField(new GUIContent("Id will be generated at runtime", "This object will not be included in aggregation metrics on the dashboard")); EditorGUI.EndDisabledGroup(); customId.stringValue = string.Empty; useCustomId.boolValue = false; idPool.objectReferenceValue = null; } else if (idType == 2) //id pool { EditorGUILayout.ObjectField(idPool, new GUIContent("", "Provides a consistent list of Ids to be used at runtime. Allows aggregated data from objects spawned at runtime")); customId.stringValue = string.Empty; useCustomId.boolValue = false; } GUILayout.EndHorizontal(); if (idType == 2) //id pool { var dyn = target as DynamicObject; if (dyn.IdPool == null) { if (GUILayout.Button("New Dynamic Object Id Pool")) { var pool = ScriptableObject.CreateInstance <DynamicObjectIdPool>(); //write some values pool.Ids = new string[1] { System.Guid.NewGuid().ToString() }; pool.MeshName = dyn.MeshName; pool.PrefabName = dyn.gameObject.name; //save to root assets folder AssetDatabase.CreateAsset(pool, "Assets/" + pool.MeshName + " Id Pool.asset"); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); //get reference to file idPool.objectReferenceValue = pool; } } } foldout = EditorGUILayout.Foldout(foldout, "Advanced"); if (foldout) { if (useCustomMesh.boolValue) { //Mesh GUILayout.Label("Export and Upload", EditorStyles.boldLabel); GUILayout.BeginHorizontal(); if (GUILayout.Button("Export Mesh", "ButtonLeft", GUILayout.Height(30))) { ExportUtility.ExportAllSelectedDynamicObjects(); } EditorGUI.BeginDisabledGroup(!EditorCore.HasDynamicExportFiles(meshname.stringValue)); if (GUILayout.Button("Thumbnail from\nSceneView", "ButtonMid", GUILayout.Height(30))) { foreach (var v in serializedObject.targetObjects) { EditorCore.SaveDynamicThumbnailSceneView((v as DynamicObject).gameObject); } } EditorGUI.EndDisabledGroup(); EditorGUI.BeginDisabledGroup(!EditorCore.HasDynamicExportFiles(meshname.stringValue)); if (GUILayout.Button("Upload Mesh", "ButtonRight", GUILayout.Height(30))) { ExportUtility.UploadSelectedDynamicObjectMeshes(true); } EditorGUI.EndDisabledGroup(); //texture export settings GUILayout.EndHorizontal(); GUIContent[] textureQualityNames = new GUIContent[] { new GUIContent("Full"), new GUIContent("Half"), new GUIContent("Quarter") /*, new GUIContent("Eighth"), new GUIContent("Sixteenth"), new GUIContent("Thirty Second"), new GUIContent("Sixty Fourth") */ }; int[] textureQualities = new int[] { 1, 2, 4 /*, 8, 16, 32, 64*/ }; CognitiveVR_Preferences.Instance.TextureResize = EditorGUILayout.IntPopup(new GUIContent("Texture Export Quality", "Reduce textures when uploading to scene explorer"), CognitiveVR_Preferences.Instance.TextureResize, textureQualityNames, textureQualities); GUILayout.Space(5); //ID upload var dyn = target as DynamicObject; if (dyn.UseCustomId) { EditorGUI.BeginDisabledGroup(!EditorCore.HasDynamicExportFiles(meshname.stringValue)); if (GUILayout.Button("Upload Custom ID for aggregation")) { Debug.Log("upload custom id to scene"); //ExportUtility.UploadSelectedDynamicObjectMeshes(true); EditorCore.RefreshSceneVersion(delegate() { ManageDynamicObjects.AggregationManifest manifest = new ManageDynamicObjects.AggregationManifest(); manifest.objects.Add(new ManageDynamicObjects.AggregationManifest.AggregationManifestEntry(dyn.gameObject.name, dyn.MeshName, dyn.CustomId)); ManageDynamicObjects.UploadManifest(manifest, null); }); } EditorGUI.EndDisabledGroup(); } else if (dyn.IdPool != null) { EditorGUI.BeginDisabledGroup(!EditorCore.HasDynamicExportFiles(meshname.stringValue)); if (GUILayout.Button("Upload ID Pool for aggregation")) { Debug.Log("upload id pool to scene"); //ExportUtility.UploadSelectedDynamicObjectMeshes(true); EditorCore.RefreshSceneVersion(delegate() { ManageDynamicObjects.AggregationManifest manifest = new ManageDynamicObjects.AggregationManifest(); for (int i = 0; i < dyn.IdPool.Ids.Length; i++) { manifest.objects.Add(new ManageDynamicObjects.AggregationManifest.AggregationManifestEntry(dyn.gameObject.name, dyn.MeshName, dyn.IdPool.Ids[i])); } ManageDynamicObjects.UploadManifest(manifest, null); }); } EditorGUI.EndDisabledGroup(); } } //Snapshot Threshold GUILayout.Label("Data Snapshot", EditorStyles.boldLabel); //controller stuff GUILayout.BeginHorizontal(); UnityEditor.EditorGUILayout.PropertyField(isController, new GUIContent("Is Controller", "If true, this will record user's inputs and display the inputs in a popup on SceneExplorer")); if (targets.Length == 1) { var dyn = targets[0] as DynamicObject; if (dyn.IsController) { dyn.ControllerType = (DynamicObject.ControllerDisplayType)EditorGUILayout.EnumPopup(dyn.ControllerType); } if (dyn.IsController) { EditorGUILayout.LabelField("Is Right", GUILayout.Width(60)); dyn.IsRight = EditorGUILayout.Toggle(dyn.IsRight, GUILayout.Width(20)); } } GUILayout.EndHorizontal(); EditorGUILayout.PropertyField(syncWithGaze, new GUIContent("Sync with Gaze", "Records the transform of the dynamic object on the same frame as gaze. This may smooth movement of this object in SceneExplorer relative to the player's position")); EditorGUI.BeginDisabledGroup(syncWithGaze.boolValue); EditorGUILayout.PropertyField(updateRate, new GUIContent("Update Rate", "This is the Snapshot interval in the Tracker Options Window"), GUILayout.MinWidth(50)); updateRate.floatValue = Mathf.Max(0.1f, updateRate.floatValue); EditorGUI.EndDisabledGroup(); EditorGUILayout.PropertyField(positionThreshold, new GUIContent("Position Threshold", "Meters the object must move to write a new snapshot. Checked each 'Tick'")); positionThreshold.floatValue = Mathf.Max(0, positionThreshold.floatValue); EditorGUILayout.PropertyField(rotationThreshold, new GUIContent("Rotation Threshold", "Degrees the object must rotate to write a new snapshot. Checked each 'Tick'")); rotationThreshold.floatValue = Mathf.Max(0, rotationThreshold.floatValue); EditorGUILayout.PropertyField(scaleThreshold, new GUIContent("Scale Threshold", "Scale multiplier that must be exceeded to write a new snapshot. Checked each 'Tick'")); scaleThreshold.floatValue = Mathf.Max(0, scaleThreshold.floatValue); EditorGUI.EndDisabledGroup(); } //advanced foldout if (GUI.changed) { foreach (var t in targets) { var dyn = t as DynamicObject; if (dyn.UseCustomMesh) { //replace all invalid characters <>|?*"/\: with _ dyn.MeshName = dyn.MeshName.Replace(" ", "_").Replace("<", "_").Replace(">", "_").Replace("|", "_").Replace("?", "_").Replace("*", "_").Replace("\"", "_").Replace("/", "_").Replace("\\", "_").Replace(":", "_"); } } //IMPROVEMENT should check that some meaningful property changed, not just foldout if (!Application.isPlaying) { foreach (var t in targets) { EditorUtility.SetDirty(t); } UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene()); } } serializedObject.ApplyModifiedProperties(); serializedObject.Update(); }
public override void OnInspectorGUI() { base.OnInspectorGUI(); var idpools = targets; var idpool = (DynamicObjectIdPool)target; if (!EditorCore.HasDynamicExportFiles(idpool.MeshName)) { EditorGUILayout.HelpBox("Mesh: " + idpool.MeshName + " not found!\nAdd your prefab to the scene and press 'Export Mesh' in the 'advanced' inspector foldout", MessageType.Warning); } bool holdingShift = Event.current.shift; string AddIdString = holdingShift ? "Add Id (x5)" : "Add Id"; GUILayout.BeginHorizontal(); if (GUILayout.Button(AddIdString, GUILayout.Width(100))) { foreach (Object opool in idpools) { var pool = (DynamicObjectIdPool)opool; if (pool.Ids == null) { pool.Ids = new string[0]; } if (holdingShift) { for (int i = 0; i < 5; i++) { ArrayUtility.Add(ref pool.Ids, System.Guid.NewGuid().ToString()); } } else { ArrayUtility.Add(ref pool.Ids, System.Guid.NewGuid().ToString()); } } } EditorGUI.BeginDisabledGroup(string.IsNullOrEmpty(idpool.PrefabName) || string.IsNullOrEmpty(idpool.MeshName) || idpool.Ids == null || idpool.Ids.Length == 0); if (GUILayout.Button("Upload Ids")) { EditorCore.RefreshSceneVersion(delegate() { ManageDynamicObjects.AggregationManifest manifest = new CognitiveVR.ManageDynamicObjects.AggregationManifest(); foreach (Object opool in idpools) { var pool = (DynamicObjectIdPool)opool; foreach (var id in pool.Ids) { manifest.objects.Add(new ManageDynamicObjects.AggregationManifest.AggregationManifestEntry(pool.PrefabName, pool.MeshName, id)); } } ManageDynamicObjects.UploadManifest(manifest, null); }); } EditorGUI.EndDisabledGroup(); GUILayout.EndHorizontal(); Repaint(); }
private void OnGUI() { if (needsRefreshDevKey == true) { EditorCore.CheckForExpiredDeveloperKey(GetDevKeyResponse); needsRefreshDevKey = false; } GUI.skin = EditorCore.WizardGUISkin; GUI.DrawTexture(new Rect(0, 0, 500, 550), EditorGUIUtility.whiteTexture); var currentscene = CognitiveVR_Preferences.FindCurrentScene(); if (string.IsNullOrEmpty(UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene().name)) { GUI.Label(steptitlerect, "DYNAMIC OBJECTS Scene Not Saved", "steptitle"); } else if (currentscene == null || string.IsNullOrEmpty(currentscene.SceneId)) { GUI.Label(steptitlerect, "DYNAMIC OBJECTS Scene Not Uploaded", "steptitle"); } else { GUI.Label(steptitlerect, "DYNAMIC OBJECTS " + currentscene.SceneName + " Version: " + currentscene.VersionNumber, "steptitle"); } GUI.Label(new Rect(30, 45, 440, 440), "These are the active <color=#8A9EB7FF>Dynamic Object components</color> currently found in your scene.", "boldlabel"); //headers Rect mesh = new Rect(30, 95, 120, 30); GUI.Label(mesh, "Mesh Name", "dynamicheader"); Rect gameobject = new Rect(190, 95, 120, 30); GUI.Label(gameobject, "GameObject", "dynamicheader"); //Rect ids = new Rect(320, 95, 120, 30); //GUI.Label(ids, "Ids", "dynamicheader"); Rect uploaded = new Rect(380, 95, 120, 30); GUI.Label(uploaded, "Exported Mesh", "dynamicheader"); //IMPROVEMENT get list of uploaded mesh names from dashboard //content DynamicObject[] tempdynamics = GetDynamicObjects; if (tempdynamics.Length == 0) { GUI.Label(new Rect(30, 120, 420, 270), "No objects found.\n\nHave you attached any Dynamic Object components to objects?\n\nAre they active in your hierarchy?", "button_disabledtext"); } DynamicObjectIdPool[] poolAssets = EditorCore.GetDynamicObjectPoolAssets; Rect innerScrollSize = new Rect(30, 0, 420, (tempdynamics.Length + poolAssets.Length) * 30); dynamicScrollPosition = GUI.BeginScrollView(new Rect(30, 120, 440, 285), dynamicScrollPosition, innerScrollSize, false, true); Rect dynamicrect; int GuiOffset = 0; for (; GuiOffset < tempdynamics.Length; GuiOffset++) { if (tempdynamics[GuiOffset] == null) { RefreshSceneDynamics(); GUI.EndScrollView(); return; } dynamicrect = new Rect(30, GuiOffset * 30, 460, 30); DrawDynamicObject(tempdynamics[GuiOffset], dynamicrect, GuiOffset % 2 == 0); } for (int i = 0; i < poolAssets.Length; i++) { //if (poolAssets[i] == null) { RefreshSceneDynamics(); GUI.EndScrollView(); return; } dynamicrect = new Rect(30, (i + GuiOffset) * 30, 460, 30); DrawDynamicObjectPool(poolAssets[i], dynamicrect, (i + GuiOffset) % 2 == 0); } GUI.EndScrollView(); GUI.Box(new Rect(30, 120, 425, 285), "", "box_sharp_alpha"); //buttons string scenename = "Not Saved"; int versionnumber = 0; //string buttontextstyle = "button_bluetext"; if (currentscene == null || string.IsNullOrEmpty(currentscene.SceneId)) { //buttontextstyle = "button_disabledtext"; } else { scenename = currentscene.SceneName; versionnumber = currentscene.VersionNumber; } int selectionCount = 0; foreach (var v in Selection.gameObjects) { if (v.GetComponentInChildren <DynamicObject>()) { selectionCount++; } } //IMPROVEMENT enable mesh upload from selected dynamic object id pool that has exported mesh files //if (Selection.activeObject.GetType() == typeof(DynamicObjectIdPool)) //{ // var pool = Selection.activeObject as DynamicObjectIdPool; // if (EditorCore.HasDynamicExportFiles(pool.MeshName)) // { // selectionCount++; // } //} //texture resolution if (CognitiveVR_Preferences.Instance.TextureResize > 4) { CognitiveVR_Preferences.Instance.TextureResize = 4; } //resolution settings here EditorGUI.BeginDisabledGroup(DisableButtons); if (GUI.Button(new Rect(30, 415, 140, 35), new GUIContent("1/4 Resolution", DisableButtons?"":"Quarter resolution of dynamic object textures"), CognitiveVR_Preferences.Instance.TextureResize == 4 ? "button_blueoutline" : "button_disabledtext")) { CognitiveVR_Preferences.Instance.TextureResize = 4; } if (CognitiveVR_Preferences.Instance.TextureResize != 4) { GUI.Box(new Rect(30, 415, 140, 35), "", "box_sharp_alpha"); } if (GUI.Button(new Rect(180, 415, 140, 35), new GUIContent("1/2 Resolution", DisableButtons ? "" : "Half resolution of dynamic object textures"), CognitiveVR_Preferences.Instance.TextureResize == 2 ? "button_blueoutline" : "button_disabledtext")) { CognitiveVR_Preferences.Instance.TextureResize = 2; } if (CognitiveVR_Preferences.Instance.TextureResize != 2) { GUI.Box(new Rect(180, 415, 140, 35), "", "box_sharp_alpha"); } if (GUI.Button(new Rect(330, 415, 140, 35), new GUIContent("1/1 Resolution", DisableButtons ? "" : "Full resolution of dynamic object textures"), CognitiveVR_Preferences.Instance.TextureResize == 1 ? "button_blueoutline" : "button_disabledtext")) { CognitiveVR_Preferences.Instance.TextureResize = 1; } if (CognitiveVR_Preferences.Instance.TextureResize != 1) { GUI.Box(new Rect(330, 415, 140, 35), "", "box_sharp_alpha"); } EditorGUI.EndDisabledGroup(); EditorGUI.BeginDisabledGroup(currentscene == null || string.IsNullOrEmpty(currentscene.SceneId) || selectionCount == 0); if (GUI.Button(new Rect(30, 460, 200, 30), new GUIContent("Upload " + selectionCount + " Selected Meshes", DisableButtons ? "" : "Export and Upload to " + scenename + " version " + versionnumber))) { EditorCore.RefreshSceneVersion(() => { foreach (var go in Selection.gameObjects) { var dyn = go.GetComponent <DynamicObject>(); if (dyn == null) { continue; } //check if export files exist if (!EditorCore.HasDynamicExportFiles(dyn.MeshName)) { ExportUtility.ExportDynamicObject(dyn); } //check if thumbnail exists if (!EditorCore.HasDynamicObjectThumbnail(dyn.MeshName)) { EditorCore.SaveDynamicThumbnailAutomatic(dyn.gameObject); } } EditorCore.RefreshSceneVersion(delegate() { var manifest = new AggregationManifest(); AddOrReplaceDynamic(manifest, GetDynamicObjectsInScene()); ManageDynamicObjects.UploadManifest(manifest, () => ExportUtility.UploadSelectedDynamicObjectMeshes(true)); }); }); } EditorGUI.EndDisabledGroup(); EditorGUI.BeginDisabledGroup(currentscene == null || string.IsNullOrEmpty(currentscene.SceneId)); if (GUI.Button(new Rect(270, 460, 200, 30), new GUIContent("Upload All Meshes", DisableButtons ? "" : "Export and Upload to " + scenename + " version " + versionnumber))) { EditorCore.RefreshSceneVersion(() => { var dynamics = GameObject.FindObjectsOfType <DynamicObject>(); List <GameObject> gos = new List <GameObject>(); foreach (var v in dynamics) { gos.Add(v.gameObject); } Selection.objects = gos.ToArray(); foreach (var go in Selection.gameObjects) { var dyn = go.GetComponent <DynamicObject>(); if (dyn == null) { continue; } //check if export files exist if (!EditorCore.HasDynamicExportFiles(dyn.MeshName)) { ExportUtility.ExportDynamicObject(dyn); } //check if thumbnail exists if (!EditorCore.HasDynamicObjectThumbnail(dyn.MeshName)) { EditorCore.SaveDynamicThumbnailAutomatic(dyn.gameObject); } } EditorCore.RefreshSceneVersion(delegate() { var manifest = new AggregationManifest(); AddOrReplaceDynamic(manifest, GetDynamicObjectsInScene()); ManageDynamicObjects.UploadManifest(manifest, () => ExportUtility.UploadSelectedDynamicObjectMeshes(true)); }); }); } EditorGUI.EndDisabledGroup(); DrawFooter(); Repaint(); //manually repaint gui each frame to make sure it's responsive }
public override void OnInspectorGUI() { serializedObject.Update(); var script = serializedObject.FindProperty("m_Script"); var groupName = serializedObject.FindProperty("GroupName"); var syncWithPlayerUpdate = serializedObject.FindProperty("SyncWithPlayerUpdate"); var updateRate = serializedObject.FindProperty("UpdateRate"); var positionThreshold = serializedObject.FindProperty("PositionThreshold"); var rotationThreshold = serializedObject.FindProperty("RotationThreshold"); var snapshotOnEnable = serializedObject.FindProperty("SnapshotOnEnable"); var updateTicksOnEnable = serializedObject.FindProperty("UpdateTicksOnEnable"); var releaseOnDisable = serializedObject.FindProperty("ReleaseIdOnDisable"); var releaseOnDestroy = serializedObject.FindProperty("ReleaseIdOnDestroy"); var useCustomID = serializedObject.FindProperty("UseCustomId"); var customId = serializedObject.FindProperty("CustomId"); var commonMeshName = serializedObject.FindProperty("CommonMesh"); var meshname = serializedObject.FindProperty("MeshName"); var useCustomMesh = serializedObject.FindProperty("UseCustomMesh"); var trackGaze = serializedObject.FindProperty("TrackGaze"); var requiresManualEnable = serializedObject.FindProperty("RequiresManualEnable"); foreach (var t in serializedObject.targetObjects) { var dynamic = t as DynamicObject; if (dynamic.iId != dynamic.GetInstanceID() || string.IsNullOrEmpty(dynamic.CustomId)) //only check if something has changed on a dynamic { if (dynamic.UseCustomId) { dynamic.iId = dynamic.GetInstanceID(); //this will often mark the scene dirty without any apparent or meaningful changes CheckCustomId(ref dynamic.CustomId); //TODO cache while scene active, but don't bother marking scene dirty if only iId is dirty } } } #if UNITY_5_6_OR_NEWER //video //var flipVideo = serializedObject.FindProperty("FlipVideo"); //var externalVideoSource = serializedObject.FindProperty("ExternalVideoSource"); var videoPlayer = serializedObject.FindProperty("VideoPlayer"); #endif //display script on component EditorGUI.BeginDisabledGroup(true); EditorGUILayout.PropertyField(script, true, new GUILayoutOption[0]); EditorGUI.EndDisabledGroup(); GUILayout.BeginHorizontal(); UnityEditor.EditorGUILayout.PropertyField(useCustomMesh); bool anycustomnames = false; foreach (var t in targets) { var dyn = t as DynamicObject; if (dyn.UseCustomMesh) { anycustomnames = true; if (string.IsNullOrEmpty(dyn.MeshName)) { dyn.MeshName = dyn.gameObject.name.ToLower().Replace(" ", "_"); UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene()); } if (targets.Length == 1) { dyn.MeshName = UnityEditor.EditorGUILayout.TextField("", dyn.MeshName); } } } if (!anycustomnames) { UnityEditor.EditorGUILayout.PropertyField(commonMeshName, new GUIContent("")); } GUILayout.EndHorizontal(); EditorGUILayout.PropertyField(trackGaze, new GUIContent("Track Gaze on Dynamic Object")); DisplayGazeTrackHelpbox(trackGaze.boolValue); GUILayout.Space(10); foldout = EditorGUILayout.Foldout(foldout, "Advanced"); if (foldout) { if (useCustomMesh.boolValue) { //Mesh GUILayout.Label("Mesh", EditorStyles.boldLabel); //EditorGUI.BeginDisabledGroup(useCustomMesh.boolValue); //UnityEditor.EditorGUILayout.PropertyField(commonMeshName); //EditorGUI.EndDisabledGroup(); if (string.IsNullOrEmpty(meshname.stringValue)) { //meshname.stringValue = serializedObject.targetObject.name.ToLower().Replace(" ", "_"); UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene()); } GUILayout.BeginHorizontal(); //UnityEditor.EditorGUILayout.PropertyField(useCustomMesh); //EditorGUI.BeginDisabledGroup(!useCustomMesh.boolValue); UnityEditor.EditorGUILayout.PropertyField(meshname, new GUIContent("")); if (GUILayout.Button("Export", "ButtonLeft", GUILayout.MaxWidth(100))) { CognitiveVR_SceneExportWindow.ExportSelectedObjectsPrefab(); foreach (var t in serializedObject.targetObjects) { var dyn = t as DynamicObject; if (!dyn.UseCustomId) { EditorCore.SaveDynamicThumbnailAutomatic(dyn.gameObject); } } } EditorGUI.BeginDisabledGroup(!EditorCore.HasDynamicExportFiles(meshname.stringValue)); if (GUILayout.Button("Upload", "ButtonRight", GUILayout.MaxWidth(100))) { CognitiveVR_SceneExportWindow.UploadSelectedDynamicObjects(true); } EditorGUI.EndDisabledGroup(); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); EditorGUI.BeginDisabledGroup(!EditorCore.HasDynamicExportFiles(meshname.stringValue)); if (GUILayout.Button("Thumbnail from SceneView", GUILayout.MaxWidth(180))) { foreach (var v in serializedObject.targetObjects) { EditorCore.SaveDynamicThumbnailSceneView((v as DynamicObject).gameObject); } } EditorGUI.EndDisabledGroup(); GUILayout.EndHorizontal(); } //Setup GUILayout.Label("Setup", EditorStyles.boldLabel); UnityEditor.EditorGUILayout.PropertyField(snapshotOnEnable, new GUIContent("Snapshot On Enable", "Save the transform when this object is first enabled")); //EditorGUI.BeginDisabledGroup(!snapshotOnEnable.boolValue); UnityEditor.EditorGUILayout.PropertyField(updateTicksOnEnable, new GUIContent("Update Ticks on Enable", "Begin coroutine that saves the transform of this object when it moves")); //EditorGUI.EndDisabledGroup(); EditorGUILayout.PropertyField(trackGaze, new GUIContent("Track Gaze on Dynamic Object")); DisplayGazeTrackHelpbox(trackGaze.boolValue); EditorGUILayout.PropertyField(requiresManualEnable, new GUIContent("Requires Manual Enable", "If true, ManualEnable must be called before OnEnable will function. Used to set initial variables on an object")); //Object ID GUILayout.Label("Ids", EditorStyles.boldLabel); GUILayout.BeginHorizontal(); EditorGUILayout.PropertyField(useCustomID, new GUIContent("Use Custom Id", "This is used to identify specific objects to aggregate the position across multiple play sessions")); EditorGUI.BeginDisabledGroup(!useCustomID.boolValue); EditorGUILayout.PropertyField(customId, new GUIContent("")); EditorGUI.EndDisabledGroup(); GUILayout.EndHorizontal(); EditorGUILayout.PropertyField(groupName, new GUIContent("Group Name", "This is used to identify types of objects and combine aggregated data")); EditorGUILayout.PropertyField(releaseOnDisable, new GUIContent("Release Id OnDisable", "Allow other objects to use this Id when this object is no longer active")); EditorGUILayout.PropertyField(releaseOnDestroy, new GUIContent("Release Id OnDestroy", "Allow other objects to use this Id when this object is no longer active")); //Snapshot Threshold GUILayout.Label("Snapshot Threshold", EditorStyles.boldLabel); EditorGUILayout.PropertyField(syncWithPlayerUpdate, new GUIContent("Sync with Player Update", "This is the Snapshot interval in the Tracker Options Window")); EditorGUI.BeginDisabledGroup(syncWithPlayerUpdate.boolValue); if (syncWithPlayerUpdate.boolValue) { EditorGUILayout.FloatField(new GUIContent("Update Rate", "Synced with Player Update.\nThe interval between checking for modified position and rotation"), EditorCore.GetPreferences().SnapshotInterval); } else { EditorGUILayout.PropertyField(updateRate, new GUIContent("Update Rate", "The interval between checking for modified position and rotation")); } updateRate.floatValue = Mathf.Max(0.1f, updateRate.floatValue); EditorGUI.EndDisabledGroup(); EditorGUILayout.PropertyField(positionThreshold, new GUIContent("Position Threshold", "Meters the object must move to write a new snapshot. Checked each 'Tick'")); positionThreshold.floatValue = Mathf.Max(0, positionThreshold.floatValue); EditorGUILayout.PropertyField(rotationThreshold, new GUIContent("Rotation Threshold", "Degrees the object must rotate to write a new snapshot. Checked each 'Tick'")); rotationThreshold.floatValue = Mathf.Max(0, rotationThreshold.floatValue); #if !UNITY_5_6_OR_NEWER GUILayout.Label("Video Settings", EditorStyles.boldLabel); EditorGUILayout.HelpBox("Video Player requires Unity 5.6 or newer!", MessageType.Warning); #else GUILayout.Label("Video Settings", EditorStyles.boldLabel); EditorGUILayout.PropertyField(videoPlayer, new GUIContent("Video Player")); //EditorGUILayout.PropertyField(externalVideoSource, new GUIContent("External Video Source", "The URL source of the video")); //EditorGUILayout.PropertyField(flipVideo, new GUIContent("Flip Video Horizontally")); #endif } //advanced foldout if (GUI.changed) { foreach (var t in targets) { var dyn = t as DynamicObject; if (dyn.UseCustomMesh) { dyn.MeshName = dyn.MeshName.Replace(" ", "_"); } } //remove spaces from meshname //meshname.stringValue = meshname.stringValue.Replace(" ", "_"); UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene()); } serializedObject.ApplyModifiedProperties(); serializedObject.Update(); }
public override void OnInspectorGUI() { serializedObject.Update(); var script = serializedObject.FindProperty("m_Script"); var updateRate = serializedObject.FindProperty("UpdateRate"); var positionThreshold = serializedObject.FindProperty("PositionThreshold"); var rotationThreshold = serializedObject.FindProperty("RotationThreshold"); var scaleThreshold = serializedObject.FindProperty("ScaleThreshold"); var useCustomId = serializedObject.FindProperty("UseCustomId"); var customId = serializedObject.FindProperty("CustomId"); var commonMeshName = serializedObject.FindProperty("CommonMesh"); var meshname = serializedObject.FindProperty("MeshName"); var useCustomMesh = serializedObject.FindProperty("UseCustomMesh"); var isController = serializedObject.FindProperty("IsController"); var syncWithGaze = serializedObject.FindProperty("SyncWithPlayerGazeTick"); foreach (var t in serializedObject.targetObjects) //makes sure a custom id is valid { var dynamic = t as DynamicObject; if (dynamic.editorInstanceId != dynamic.GetInstanceID() || string.IsNullOrEmpty(dynamic.CustomId)) //only check if something has changed on a dynamic, or if the id is empty { if (dynamic.UseCustomId) { if (string.IsNullOrEmpty(AssetDatabase.GetAssetPath(dynamic.gameObject)))//scene asset { dynamic.editorInstanceId = dynamic.GetInstanceID(); CheckCustomId(ref dynamic.CustomId); } else //project asset { dynamic.editorInstanceId = dynamic.GetInstanceID(); if (string.IsNullOrEmpty(dynamic.CustomId)) { string s = System.Guid.NewGuid().ToString(); dynamic.CustomId = "editor_" + s; } } } } } //video //var flipVideo = serializedObject.FindProperty("FlipVideo"); //var externalVideoSource = serializedObject.FindProperty("ExternalVideoSource"); //var videoPlayer = serializedObject.FindProperty("VideoPlayer"); //display script on component EditorGUI.BeginDisabledGroup(true); EditorGUILayout.PropertyField(script, true, new GUILayoutOption[0]); EditorGUI.EndDisabledGroup(); //use custom mesh and mesh text field GUILayout.BeginHorizontal(); UnityEditor.EditorGUILayout.PropertyField(useCustomMesh); bool anycustomnames = false; foreach (var t in targets) { var dyn = t as DynamicObject; if (dyn.UseCustomMesh) { anycustomnames = true; if (string.IsNullOrEmpty(dyn.MeshName)) { dyn.MeshName = dyn.gameObject.name.ToLower().Replace(" ", "_").Replace("<", "_").Replace(">", "_").Replace("|", "_").Replace("?", "_").Replace("*", "_").Replace("\"", "_").Replace("/", "_").Replace("\\", "_").Replace(":", "_"); if (!Application.isPlaying) { UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene()); } } if (targets.Length == 1) { dyn.MeshName = UnityEditor.EditorGUILayout.TextField("", dyn.MeshName); } } } if (!anycustomnames) { UnityEditor.EditorGUILayout.PropertyField(commonMeshName, new GUIContent("")); } GUILayout.EndHorizontal(); //use custom id and custom id text field GUILayout.BeginHorizontal(); bool previousUseCustomId = useCustomId.boolValue; EditorGUILayout.PropertyField(useCustomId, new GUIContent("Custom Id")); if (Selection.activeGameObject) { string path = AssetDatabase.GetAssetPath(Selection.activeObject); if (!string.IsNullOrEmpty(path) && useCustomId.boolValue) { //display small warning icon when prefab has custom id set EditorGUILayout.LabelField(new GUIContent(EditorCore.Alert, "Project assets should not have CustomId set, unless there will be only 1 instance spawned during runtime"), GUILayout.Width(20)); } } if (previousUseCustomId != useCustomId.boolValue) { if (previousUseCustomId != useCustomId.boolValue) //use custom id changed { if (useCustomId.boolValue == false) //changed to false { customId.stringValue = string.Empty; } else { foreach (var t in targets) { var dyn = t as DynamicObject; CheckCustomId(ref dyn.CustomId); } } } } if (!useCustomId.boolValue) //display custom id field { EditorGUI.BeginDisabledGroup(true); EditorGUILayout.LabelField(new GUIContent("Id will be generated at runtime", "This object will not be included in aggregation metrics on the dashboard")); EditorGUI.EndDisabledGroup(); } else { if (targets.Length > 1) { EditorGUI.BeginDisabledGroup(true); EditorGUILayout.LabelField("multiple values"); EditorGUI.EndDisabledGroup(); } else { EditorGUILayout.PropertyField(customId, new GUIContent("")); } } GUILayout.EndHorizontal(); foldout = EditorGUILayout.Foldout(foldout, "Advanced"); if (foldout) { if (useCustomMesh.boolValue) { //Mesh GUILayout.Label("Mesh", EditorStyles.boldLabel); //EditorGUI.BeginDisabledGroup(useCustomMesh.boolValue); //UnityEditor.EditorGUILayout.PropertyField(commonMeshName); //EditorGUI.EndDisabledGroup(); if (string.IsNullOrEmpty(meshname.stringValue)) { //meshname.stringValue = serializedObject.targetObject.name.ToLower().Replace(" ", "_"); if (!Application.isPlaying) { UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene()); } } GUILayout.BeginHorizontal(); //UnityEditor.EditorGUILayout.PropertyField(useCustomMesh); //EditorGUI.BeginDisabledGroup(!useCustomMesh.boolValue); //UnityEditor.EditorGUILayout.PropertyField(meshname, new GUIContent("")); if (GUILayout.Button("Export Mesh", "ButtonLeft", GUILayout.Height(30))) { CognitiveVR_SceneExportWindow.ExportSelectedObjectsPrefab(); } EditorGUI.BeginDisabledGroup(!EditorCore.HasDynamicExportFiles(meshname.stringValue)); if (GUILayout.Button("Thumbnail from\nSceneView", "ButtonMid", GUILayout.Height(30))) { foreach (var v in serializedObject.targetObjects) { EditorCore.SaveDynamicThumbnailSceneView((v as DynamicObject).gameObject); } } EditorGUI.EndDisabledGroup(); EditorGUI.BeginDisabledGroup(!EditorCore.HasDynamicExportFiles(meshname.stringValue)); if (GUILayout.Button("Upload Mesh", "ButtonRight", GUILayout.Height(30))) { CognitiveVR_SceneExportWindow.UploadSelectedDynamicObjects(true); } EditorGUI.EndDisabledGroup(); GUILayout.EndHorizontal(); //GUILayout.BeginHorizontal(); GUIContent[] textureQualityNames = new GUIContent[] { new GUIContent("Full"), new GUIContent("Half"), new GUIContent("Quarter"), new GUIContent("Eighth"), new GUIContent("Sixteenth"), new GUIContent("Thirty Second"), new GUIContent("Sixty Fourth") }; int[] textureQualities = new int[] { 1, 2, 4, 8, 16, 32, 64 }; CognitiveVR_Preferences.Instance.TextureResize = EditorGUILayout.IntPopup(new GUIContent("Texture Export Quality", "Reduce textures when uploading to scene explorer"), CognitiveVR_Preferences.Instance.TextureResize, textureQualityNames, textureQualities); //GUILayout.EndHorizontal(); GUILayout.Space(5); } //Snapshot Threshold GUILayout.Label("Snapshot", EditorStyles.boldLabel); //controller stuff GUILayout.BeginHorizontal(); UnityEditor.EditorGUILayout.PropertyField(isController, new GUIContent("Is Controller", "If true, this will record user's inputs and display the inputs in a popup on SceneExplorer")); if (targets.Length == 1) { var dyn = targets[0] as DynamicObject; if (dyn.IsController) { string[] controllernames = new string[3] { "vivecontroller", "oculustouchleft", "oculustouchright" }; int selected = 0; if (dyn.ControllerType == "vivecontroller") { selected = 0; } if (dyn.ControllerType == "oculustouchleft") { selected = 1; } if (dyn.ControllerType == "oculustouchright") { selected = 2; } selected = EditorGUILayout.Popup(selected, controllernames); dyn.ControllerType = controllernames[selected]; } if (dyn.IsController) { EditorGUILayout.LabelField("Is Right", GUILayout.Width(60)); dyn.IsRight = EditorGUILayout.Toggle(dyn.IsRight, GUILayout.Width(20)); } } GUILayout.EndHorizontal(); EditorGUILayout.PropertyField(syncWithGaze, new GUIContent("Sync with Gaze", "Records the transform of the dynamic object on the same frame as gaze. This may smooth movement of this object in SceneExplorer relative to the player's position")); EditorGUI.BeginDisabledGroup(syncWithGaze.boolValue); EditorGUILayout.PropertyField(updateRate, new GUIContent("Update Rate", "This is the Snapshot interval in the Tracker Options Window"), GUILayout.MinWidth(50)); updateRate.floatValue = Mathf.Max(0.1f, updateRate.floatValue); EditorGUI.EndDisabledGroup(); EditorGUILayout.PropertyField(positionThreshold, new GUIContent("Position Threshold", "Meters the object must move to write a new snapshot. Checked each 'Tick'")); positionThreshold.floatValue = Mathf.Max(0, positionThreshold.floatValue); EditorGUILayout.PropertyField(rotationThreshold, new GUIContent("Rotation Threshold", "Degrees the object must rotate to write a new snapshot. Checked each 'Tick'")); rotationThreshold.floatValue = Mathf.Max(0, rotationThreshold.floatValue); EditorGUILayout.PropertyField(scaleThreshold, new GUIContent("Scale Threshold", "Scale multiplier that must be exceeded to write a new snapshot. Checked each 'Tick'")); scaleThreshold.floatValue = Mathf.Max(0, scaleThreshold.floatValue); EditorGUI.EndDisabledGroup(); } //advanced foldout if (GUI.changed) { foreach (var t in targets) { var dyn = t as DynamicObject; if (dyn.UseCustomMesh) { //TODO replace all invalid characters <>|?*"/\: with _ dyn.MeshName = dyn.MeshName.Replace(" ", "_").Replace("<", "_").Replace(">", "_").Replace("|", "_").Replace("?", "_").Replace("*", "_").Replace("\"", "_").Replace("/", "_").Replace("\\", "_").Replace(":", "_"); } } //remove spaces from meshname //meshname.stringValue = meshname.stringValue.Replace(" ", "_"); if (!Application.isPlaying) { UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene()); } } serializedObject.ApplyModifiedProperties(); serializedObject.Update(); }