using UnityEngine; using UnityEditor; using System.Linq; using SimpleJSON; using System.IO; using System.Collections.Generic; namespace dlu { [CustomEditor(typeof(SceneController))] public class SceneControllerEditor : Editor { private bool showLabels = false; public SemanticBehaviour[] semanticBehaviours; private JSONArray sceneJson; private JSONArray instructionJson; public SceneControllerEditor() { JSONNode.VectorContainerType = JSONContainerType.Object; JSONNode.QuaternionContainerType = JSONContainerType.Object; } public override void OnInspectorGUI() { SceneController sc = (SceneController) target; base.DrawDefaultInspector(); this.ImportInstruction(sc); EditorGUILayout.Space(); this.ExportContext(sc); EditorGUILayout.Space(); this.ShowSemanticLabels(sc); } private void ShowSemanticLabels(SceneController sc) { showLabels = EditorGUILayout.BeginFoldoutHeaderGroup(showLabels, "Semantic labels"); if (showLabels) { if (this.semanticBehaviours == null || GUILayout.Button("Refresh list of semantic labels")) { FindSemanticLabels(); } foreach (SemanticBehaviour sb in this.semanticBehaviours) { string label = sb.GetComponent().name; if (sb.is_a.Count() > 0) { label += $" a {sb.is_a.Split('#')[1]}"; } EditorGUILayout.ObjectField(label, sb.gameObject, typeof(GameObject), true); } } EditorGUILayout.EndFoldoutHeaderGroup(); } private void ExportContext(SceneController sc) { string exportFile = EditorGUILayout.TextField("Export Context File", "Assets/DLU/Resources/context.json"); if (sceneJson == null) { sceneJson = this.GenerateContextJSON(); } if (GUILayout.Button("Export to file")) { File.WriteAllText(exportFile, sceneJson.ToString()); } EditorGUILayout.TextArea(sceneJson == null ? "" : sceneJson.ToString()); } private void ImportInstruction(SceneController sc) { if (sc.instruction == null || GUILayout.Button("Import instruction JSON")) { sc.instruction = sc.LoadInstruction(sc.importInstructionFile); } EditorGUILayout.TextArea(sc.instruction == null ? "" : sc.instruction.ToString()); } public void FindSemanticLabels() { this.semanticBehaviours = GameObject.FindObjectsOfType(); } public JSONArray GenerateContextJSON() { if (this.semanticBehaviours == null) { FindSemanticLabels(); } Dictionary sceneDict = new Dictionary(); JSONArray sceneArray = new JSONArray(); foreach (SemanticBehaviour sb in this.semanticBehaviours) { JSONObject jsonObject = null; string name = sb.GetComponent().name; if (!sceneDict.ContainsKey(name)) { jsonObject = new JSONObject(); jsonObject.Add("name", name); jsonObject.Add("is_a", new JSONArray()); jsonObject.Add("components", new JSONObject()); sceneDict[name] = jsonObject; sceneArray.Add(sceneDict[name]); } jsonObject = sceneDict[name]; jsonObject["is_a"].Add(sb.is_a); switch (sb) { case Entity entity: Write(jsonObject, entity); break; case DesignedContainer designedContainer: Write(jsonObject, designedContainer); break; default: Debug.LogWarning($"No Write handler for SemanticBehaviour \"{sb.GetType().Name}\""); break; } } return sceneArray; } private void Write(JSONObject jsonObject, Entity entity) { JSONObject transform = new JSONObject(); transform["position"] = entity.transform.position; transform["orientation"] = entity.transform.rotation; jsonObject["components"]["transform"] = transform; MeshFilter meshFilter = entity.GetComponent(); if (meshFilter != null) { Mesh mesh = meshFilter.sharedMesh; JSONObject bounds = new JSONObject(); bounds["center"] = mesh.bounds.center; bounds["extents"] = mesh.bounds.extents; bounds["size"] = mesh.bounds.size; jsonObject["components"]["bounds"] = bounds; } } private void Write(JSONObject jsonObject, DesignedContainer designedContainer) { JSONArray containment = new JSONArray(); foreach (Collider collider in designedContainer.containmentParts) { JSONObject part = new JSONObject(); part.Add("type", collider.GetType().Name); part.Add("center", collider.bounds.center); part.Add("size", collider.bounds.size); part.Add("extents", collider.bounds.extents); containment.Add(part); } jsonObject["components"]["containerVolume"] = containment; } } }