SceneController.cs 6.63 KB
Newer Older
1
using UnityEngine;
2
using UnityEngine.SceneManagement;
3
using SimpleJSON;
4
using System;
5
6
using System.Collections;
using System.Collections.Generic;
7
8
9
10
11
12

namespace dlu
{

public class SceneController : MonoBehaviour
{
13
14
15
    private JSONArray instruction;
    public string contextScene = "Kitchen";
    private Func<string, IEnumerator> replyRequest;
16

17
    private Dictionary<string, bool> actionParticipants;
18

19
20
    public void Start()
    {
21
        if (!SceneManager.GetSceneByName(contextScene).isLoaded)
22
        {
23
24
            SceneManager.sceneLoaded += SimpleSceneLoaded;
            SceneManager.LoadSceneAsync(contextScene, LoadSceneMode.Additive);
25
        }
26
        if (!Application.isEditor && !SceneManager.GetSceneByName("UI").isLoaded)
27
        {
28
            SceneManager.LoadSceneAsync("UI", LoadSceneMode.Additive);
29
        }
30
    }
31

32
    public void SimpleSceneLoaded(Scene scene, LoadSceneMode mode)
33
    {
34
35
        JSONHandler.instance.RefreshSemanticLabels();
        SceneManager.sceneLoaded -= SimpleSceneLoaded;
36
    }
37

38
    public IEnumerator GetContext(Func<string, IEnumerator> replyRequest)
39
    {
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
        yield return RunSimulation(null, replyRequest);
    }

    public IEnumerator RunSimulation(JSONArray instruction, Func<string, IEnumerator> replyRequest)
    {
        this.instruction = instruction;
        this.replyRequest = replyRequest;
        SceneManager.sceneUnloaded += OnSceneUnloaded;
        SceneManager.UnloadSceneAsync(contextScene);
        yield return null;
    }

    public void OnSceneUnloaded(Scene scene)
    {
        SceneManager.sceneUnloaded -= OnSceneUnloaded;
        SceneManager.sceneLoaded += OnSceneLoaded;
        SceneManager.LoadSceneAsync(scene.buildIndex, LoadSceneMode.Additive);
    }

    public void OnSceneLoaded(Scene scene, LoadSceneMode mode)
    {
        JSONHandler.instance.RefreshSemanticLabels();
        SceneManager.sceneLoaded -= OnSceneLoaded;
        if (this.instruction != null)
        {
            StartCoroutine(EvaluateInstruction());
        }
        else
        {
            StartCoroutine(replyRequest(JSONHandler.instance.GenerateContextJSON().ToString()));
        }
71
72
73
74
75
76
77
    }

    public IEnumerator EvaluateInstruction()
    {
        Dictionary<string, JSONObject> taskDict = new Dictionary<string, JSONObject>();
        JSONObject task = null;
        // Populate quick access dict and search for task
78
        foreach (JSONObject jo in this.instruction)
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
        {
            taskDict[jo["name"]] = jo;
            if (task == null && jo.HasKey("classifies"))
            {
                task = jo;
                Debug.Log($"Task identified: {task}");
            }
        }

        // If no task is found, stop
        if (task == null)
        {
            Debug.LogError("No task found!");
            yield return null;
        }
        else  // if task is found, execute actions
        {
            foreach (JSONNode action in task["classifies"])
            {
                yield return ExecuteAction(action, taskDict);
            }
        }
    }

    public IEnumerator ExecuteAction(string actionName, Dictionary<string, JSONObject> taskDict)
    {
105
106
        actionParticipants = new Dictionary<string, bool>();

107
108
109
110
111
112
113
114
        JSONObject action = taskDict[actionName];
        Debug.Log($"Performing action {actionName}: {action}");
        List<string> participants = new List<string>();
        foreach (JSONNode participant in action["hasParticipant"])
        {
            Debug.Log($"Participant: {participant}");
            foreach(JSONNode is_a in taskDict[participant]["is_a"])
            {
115
                // TODO(@shoeffner): This is not good: we should query the ontology and don't use is_a which are also PhysicalAgents etc., also just add participants once
116
117
118
                if (is_a != "http://www.ontologydesignpatterns.org/ont/dul/DUL.owl#PhysicalAgent")
                {
                    participants.Add(participant);
119
                    break;
120
121
122
123
124
                }
            }
        }
        foreach (string participant in participants)
        {
125
126
127
128
            string referenceName = $"{actionName}/{participant}";
            actionParticipants.Add(referenceName, false);

            GameObject participantGO = JSONHandler.instance.sceneDict[participant];
129
            GameObject targetGO = new GameObject($"Target of {participant}");
130
            SceneManager.MoveGameObjectToScene(targetGO, SceneManager.GetSceneByName(contextScene));
131
132
133
134
135
136
137
138
139
140

            // Setup visuals
            GameObject renderer = new GameObject("RenderComponents");
            renderer.transform.SetParent(targetGO.transform);
            renderer.transform.localScale = participantGO.transform.lossyScale;
            MeshFilter mesh = renderer.AddComponent<MeshFilter>();
            mesh.mesh = participantGO.GetComponent<MeshFilter>().mesh;
            MeshRenderer mr = renderer.AddComponent<MeshRenderer>();
            mr.material = Resources.Load<Material>("Target");

141
142
143
144
145
146
147
148
149
            Vector3 position = taskDict[participant]["components"]["transform"]["position"];
            Quaternion orientation = taskDict[participant]["components"]["transform"]["orientation"];
            targetGO.transform.SetPositionAndRotation(position, orientation);
            double speed = taskDict[participant]["components"].HasKey("speed") ? taskDict[participant]["components"]["speed"].AsDouble : 1.0;

            Hashtable arguments = new Hashtable();
            arguments["name"] = actionName;
            arguments["position"] = targetGO.transform;
            arguments["speed"] = speed;
150
151
152
            arguments["oncomplete"] = "ActionParticipantDone";
            arguments["oncompleteparams"] = referenceName;
            arguments["oncompletetarget"] = gameObject;
153

154
            iTween.MoveTo(participantGO, arguments);
155
        }
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
        yield return WaitForActionsOrTimeout();
    }

    public void ActionParticipantDone(string referenceName)
    {
        Debug.Log($"{referenceName} is done.");
        actionParticipants[referenceName] = true;
    }

    public IEnumerator WaitForActionsOrTimeout()
    {
        bool allDone = true;
        foreach(bool status in actionParticipants.Values)
        {
            allDone &= status;
        }

        if (!allDone)
        {
            yield return new WaitForSeconds(1);
            yield return WaitForActionsOrTimeout();
        }
        else
        {
180
181
            yield return new WaitForSeconds(5);
            // TODO: record trajectories of objects etc.
182
183
            yield return replyRequest("{\"result\": \"Success!\"}");
        }
184
    }
185
186
187
}

}