//============= Copyright (c) Ludic GmbH, All rights reserved. ============== // // Purpose: Part of the My Behaviour Tree Controller Code // //============================================================================= using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Video; using MyBT; using System.Linq; #if FMOD_AVAILABLE using FMODUnity; #endif #if UNITY_EDITOR using UnityEditor; using UnityEditor.SceneManagement; [CustomEditor(typeof(BTC))] public class BehaviourTreeControllerInspector : Editor { public override void OnInspectorGUI() { BTC myTarget = (BTC)target; if (GUILayout.Button("ClearObjects")) { myTarget.ClearObjects(); SetDirty(myTarget); } if (GUILayout.Button("UpdateObjects")) { myTarget.UpdateObjects(); SetDirty(myTarget); } DrawDefaultInspector(); } public void SetDirty (BTC myTarget) { EditorUtility.SetDirty(myTarget); EditorSceneManager.MarkSceneDirty(myTarget.gameObject.scene); } } #endif public class BTC : MonoBehaviour { static BTC _instance = null; public static BTC Instance { get { if (_instance != null) { return _instance; } if (_instance == null) { _instance = Resources.FindObjectsOfTypeAll().FirstOrDefault(); if (_instance == null) { _instance = new GameObject("BTC", typeof(BTC)).GetComponent(); } } return _instance; } } public List namedObjects = new List(); #region update list of objects in rooms public void ClearObjects() { namedObjects = new List(); } public T GetNamedObject(string objectName) where T : ComponentController { for (int i = namedObjects.Count - 1; i >= 0; i--) { T ngo = namedObjects[i] as T; if (ngo != null) { // if name equals if (ngo.objectName == objectName) { return ngo; } } } return null; } public List GetHandlers (string objectName) { ComponentController ctrl = GetNamedObject(objectName); if (ctrl != null) return ctrl.handlers.ToList(); return new List(); } public bool autoUpdateAllObjects = true; public void UpdateObjects() { // iterate all objects in scene foreach (ComponentController namedObject in Resources.FindObjectsOfTypeAll()) { if (autoUpdateAllObjects) { namedObject.UpdateObject(); } // get object room id, create if not existing // RoomData roomData = GetRoomData(namedObject.roomId); // if (roomData != null) { // if room contains object (name equals), overwrite bool objectIdFound = false; bool objectNameFound = false; for (int i=0; i handlers = GetHandlers(objectName); handlers.ForEach(handler => handler.Run(Task.getState)); if (handlers.Count == 0) { Debug.LogWarning($"BTC.Run: no components under the name '{objectName}'"); Task.SetSucceeded(); } } [Task] public void Abort(string objectName) { List handlers = GetHandlers(objectName); handlers.ForEach(handler => handler.Abort(Task.getState)); if (handlers.Count == 0) { Debug.LogWarning($"BTC.Abort: no components under the name '{objectName}'"); Task.SetSucceeded(); } } [Task] public void IsRunning(string objectName) { List handlers = GetHandlers(objectName); handlers.All(handler => handler.IsRunning(Task.getState)); if (handlers.Count == 0) { Debug.LogWarning($"BTC.IsRunning: no components under the name '{objectName}'"); Task.SetSucceeded(); } } [Task] public void Show(string objectName) { List handlers = GetHandlers(objectName); handlers.ForEach(handler => handler.Show(Task.getState)); if (handlers.Count == 0) { Debug.LogWarning($"BTC.Show: no components under the name '{objectName}'"); Task.SetSucceeded(); } } [Task] public void Hide(string objectName) { List handlers = GetHandlers(objectName); handlers.ForEach(handler => handler.Hide(Task.getState)); if (handlers.Count == 0) { Debug.LogWarning($"BTC.Hide: no components under the name '{objectName}'"); Task.SetSucceeded(); } } [Task] public void FadeIn(string objectName) { List handlers = GetHandlers(objectName); handlers.ForEach(handler => handler.FadeIn(Task.getState)); if (handlers.Count == 0) { Debug.LogWarning($"BTC.FadeIn: no components under the name '{objectName}'"); Task.SetSucceeded(); } } [Task] public void FadeOut(string objectName) { List handlers = GetHandlers(objectName); handlers.ForEach(handler => handler.FadeOut(Task.getState)); if (handlers.Count == 0) { Debug.LogWarning($"BTC.FadeOut: no components under the name '{objectName}'"); Task.SetSucceeded(); } } [Task] public void Set(string objectName, string key, string value) { List handlers = GetHandlers(objectName); handlers.ForEach(handler => handler.Set(Task.getState, key, value)); if (handlers.Count == 0) { Debug.LogWarning($"BTC.Set: no components under the name '{objectName}'"); Task.SetSucceeded(); } } [Task] public void Enable(string objectName) { List handlers = GetHandlers(objectName); handlers.ForEach(handler => handler.Enable(Task.getState)); if (handlers.Count == 0) { Debug.LogWarning($"BTC.Enable: no components under the name '{objectName}'"); Task.SetSucceeded(); } } [Task] public void Disable(string objectName) { List handlers = GetHandlers(objectName); handlers.ForEach(handler => handler.Disable(Task.getState)); if (handlers.Count == 0) { Debug.LogWarning($"BTC.Disable: no components under the name '{objectName}'"); Task.SetSucceeded(); } } [Task] public void SetPosition(string objectName, float newX, float newY, float newZ) { List handlers = GetHandlers(objectName); handlers.ForEach(handler => handler.SetPosition(Task.getState, newX, newY, newZ)); if (handlers.Count == 0) { Debug.LogWarning($"BTC.SetPosition: no components under the name '{objectName}'"); Task.SetSucceeded(); } } [Task] public void AbortEventListener(string objectName) { List handlers = GetHandlers(objectName); handlers.ForEach(handler => handler.AbortEventListener(Task.getState)); if (handlers.Count == 0) { Debug.LogWarning($"BTC.AbortEventListener: no components under the name '{objectName}'"); Task.SetSucceeded(); } } [Task] public void ListenToEvent(string objectName) { List handlers = GetHandlers(objectName); handlers.ForEach(handler => handler.ListenToEvent(Task.getState)); if (handlers.Count == 0) { Debug.LogWarning($"BTC.ListenToEvent: no components under the name '{objectName}'"); Task.SetSucceeded(); } } #endregion #region video & sound tasks #if FMOD [Task] public void PlayVideoAndSound(string videoName, string soundName) { NamedStudioEventEmitter sound = GetNamedObject(soundName); NamedVideoPlayer player = GetNamedObject(videoName); if ((player != null) && (sound != null)) { int val = -1; FMOD.RESULT res = sound.sound.EventInstance.getTimelinePosition(out val); Task.log = "audio " + res.ToString() + " " + val + " video playing=" + player.video.isPlaying + " isPrepared=" + player.video.isPrepared; // on start, play if (Task.isStarting) { Debug.Log("PlayVideoAndSound.isStarting : starting video='" + videoName + "' and sound='" + soundName + "'"); player.HideNow(); player.FadeInStart(); player.video.Play(); sound.sound.Play(); } else { // if stopped playing if (!player.video.isPrepared) { // not even prepared return; } if ((!player.video.isPlaying) && (!sound.sound.IsPlaying())) { player.ShowNow(); player.FadeOutStart(); Task.SetSucceeded(); } } if (Input.GetKeyDown(KeyCode.Backspace)) { player.HideNow(); player.video.Stop(); sound.sound.Stop(); Task.SetSucceeded(); } } else { Debug.LogError("PlayVideoAndSound: Play Error: " + roomId + " video='" + videoName + "' (" + player + ") sound='" + soundName + "' (" + sound + ")"); } } [Task] public void AbortVideoAndSound(string videoName, string soundName) { if (Task.isStarting) { NamedVideoPlayer player = GetNamedObject(videoName); if (player != null) { player.FadeOutStart(); player.video.Stop(); } NamedStudioEventEmitter sound = GetNamedObject(soundName); if (sound != null) { sound.sound.Stop(); } } Task.SetSucceeded(); } #endif #endregion #region gameobject tasks // This structure is used to store data for rotation tweening. struct QuaternionData { public Quaternion startQuaternion; } [Task] public void TrackerRotatedAtLeast(string gameObjectName, float successRotation) { foreach (NamedGameObject ngo in GetHandlers(gameObjectName)) { // NamedGameObject ngo = GetNamedObject(gameObjectName); if (ngo != null) { QuaternionData rd; if (Task.isStarting) { Debug.Log("TrackerRotatedAtLeast.isStarting : gameObject=" + ngo.name); rd.startQuaternion = ngo.transform.rotation; Task.data = rd; } rd = (QuaternionData)Task.data; float angleOffset = Quaternion.Angle(rd.startQuaternion, ngo.transform.rotation); Task.log = string.Format(angleOffset + " " + rd.startQuaternion + " " + ngo.transform.rotation); if (angleOffset > successRotation) { Task.SetSucceeded(); } } } } [Task] public void TrackerRotatedAtMax(string gameObjectName, float successRotation) { foreach (NamedGameObject ngo in GetHandlers(gameObjectName)) { // NamedGameObject ngo = GetNamedObject(gameObjectName); if (ngo != null) { QuaternionData rd; if (Task.isStarting) { Debug.Log("TrackerRotatedAtMax.isStarting : trackerId=" + ngo.name + " status " + Task.getState + " "); rd.startQuaternion = ngo.transform.rotation; Task.data = rd; } rd = (QuaternionData)Task.data; float angleOffset = Quaternion.Angle(rd.startQuaternion, ngo.transform.rotation); Task.log = string.Format(angleOffset + " " + rd.startQuaternion + " " + ngo.transform.rotation); if (angleOffset < successRotation) { Task.SetSucceeded(); } } } } [Task] public void TrackerRotatedToAngle(string gameObjectName, float targetAngleFloat, float maxOffset) { foreach (NamedGameObject ngo in GetHandlers(gameObjectName)) { // NamedGameObject ngo = GetNamedObject(gameObjectName); if (ngo != null) { Quaternion targetAngle = Quaternion.Euler(0, targetAngleFloat, 0); float angleOffset = Quaternion.Angle(targetAngle, ngo.transform.rotation); Task.log = string.Format(angleOffset + " < " + maxOffset + " ? " + ngo.transform.rotation.eulerAngles + " " + targetAngle.eulerAngles); if (angleOffset < maxOffset) { Task.SetSucceeded(); } } } } struct FloatData { public float startFloat; } [Task] public void TrackerMovedY(string gameObjectName, float successMovement) { foreach (NamedGameObject ngo in GetHandlers(gameObjectName)) { // NamedGameObject ngo = GetNamedObject(gameObjectName); if (ngo != null) { //if ((trackerId >= 0) && (trackerId < GetRoomData(roomId).trackers.Count)) { //TrackerDataApplier tda = GetRoomData(roomId).trackers[trackerId]; FloatData pd; if (Task.isStarting) { Debug.Log("TrackerRotated.isStarting : gameObjectName=" + ngo.go.name); pd.startFloat = ngo.go.transform.position.y; Task.data = pd; } pd = (FloatData)Task.data; float positionOffset = Mathf.Abs(pd.startFloat - ngo.go.transform.position.y); Task.log = string.Format(positionOffset + " " + pd.startFloat + " " + ngo.go.transform.position.y); if (positionOffset > successMovement) { Task.SetSucceeded(); } } } } struct DataFloat2 { public float startTime; public float startY; } [Task] public void MoveObjectY(string gameObjectName, float startY, float finalY, float timer) { foreach (NamedGameObject ngo in GetHandlers(gameObjectName)) { // NamedGameObject ngo = GetNamedObject(gameObjectName); if (ngo != null) { NodeState thisNodeState = Task.getState; switch (thisNodeState) { case NodeState.FirstRun: Task.data = new DataFloat2() { startTime = Time.time, startY=ngo.transform.localPosition.y }; goto case NodeState.Running; case NodeState.Running: DataFloat2 data = (DataFloat2)Task.data; float elapsed = Time.time - data.startTime; float newY = finalY; if (timer > 0) { // newY = finalY; //} else { float interpolation = Mathf.Pow(elapsed / timer, 1f / 7f); newY = Mathf.Lerp(startY, finalY, interpolation); } ngo.transform.localPosition = new Vector3(ngo.transform.localPosition.x, newY, ngo.transform.localPosition.z); if (elapsed >= timer) { Task.SetSucceeded(); return; } break; case NodeState.Aborting: ngo.transform.localPosition = new Vector3(ngo.transform.localPosition.x, finalY, ngo.transform.localPosition.z); break; } } else { Debug.LogError($"MoveObjectY {gameObjectName} not found"); Task.SetFailed(); } } } [Task] public void SendGameObjectMessage(string gameObjectName, string methodName) { foreach (NamedGameObject ngo in GetHandlers(gameObjectName)) { // NamedGameObject ngo = GetNamedObject(gameObjectName); if (ngo != null) { NodeState thisNodeState = Task.getState; switch (thisNodeState) { case NodeState.FirstRun: ngo.SendMessage(methodName); goto case NodeState.Running; case NodeState.Running: Task.SetSucceeded(); break; case NodeState.Aborting: break; } } else { Debug.LogError($"SendGameObjectMessage {gameObjectName} {methodName}"); Task.SetFailed(); } } } #endregion #region camera or player tracking [Task] public bool CameraNearPosition(float x, float y, float z, float range) { Vector3 position = new Vector3(x, y, z); float positionOffset = (Camera.main.transform.position - position).magnitude; Task.log = $"{positionOffset} {Camera.main.transform.position} {position}"; // string.Format(positionOffset + " " + Camera.main.transform.position + " " + position); if (positionOffset < range) { Task.SetSucceeded(); return true; } return false; } [Task] public void CameraXZNearPosition(float x, float z, float range) { Vector3 cameraPos = Camera.main.transform.position; Vector3 position = new Vector3(x, cameraPos.y, z); float positionOffset = (cameraPos - position).magnitude; Task.log = $"{positionOffset} {cameraPos} {position}"; // string.Format(positionOffset + " " + cameraPos + " " + position); if (positionOffset < range) { Task.SetSucceeded(); } } [Task] public void SetCameraRootPosition(float x, float y, float z) { if (Task.isStarting) { Camera.main.transform.root.position = new Vector3(x, y, z); } Task.SetSucceeded(); } #endregion #region MegapointCache #if MEGAFIERS [Task] public void PlayMegaPointCache(string string gameObjectName, float startTime, bool playing, float playRate) { NamedMegaPointCache nmpc = GetNamedObject(gameObjectName); if (nmpc != null) { if (Task.isStarting) { nmpc.SetFrame(startTime); nmpc.SetPlay(playing); nmpc.SetPlayRate(playRate); Task.SetSucceeded(); } } } /// /// attack: animation time to ease in the animation /// delay: animation time at full speed /// release: animation time to ease out the animation /// /// attack * 2 + delay + release * 2 = animation play rate /// public float gletscherFrame = 0; [Task] public void PlayMegaPointCacheTimeline(string objectName, float start, float attack, float delay, float release, float duration) { NamedMegaPointCache nmpc = GetNamedObject(objectName); if (nmpc != null) { float overallTime = Mathf.Abs(attack * 2 + delay + release * 2); // for example: 0.2 * 2 + 0.6 + 0.2 * 2 = 1.4, after 10 seconds of real time, the internal counter needs to have run 1.4 seconds float timeScale = overallTime / duration; // for example: 1.4 / 10 = 0.14 float internalCounter = 0; // between 0 and overallTime float animationTime = start; // final time written to animation string state = "undefined"; // only for debugging gletscherFrame = nmpc.GetFrame(); switch (Task.getState) { case NodeState.FirstRun: // equals isStarting Task.data = Time.time; // store starttime nmpc.SetPlay(false); nmpc.SetPlayRate(0); Debug.Log("BTC.PlayMegaPointCacheTimeline: start "+ start + " attack " + attack + " delay " + delay + " release " + release + " duration " + duration + " timeScale " + timeScale + " frame " + Time.frameCount); break; case NodeState.Running: float startTime = (float)Task.data; // for example 33 internalCounter = (Time.time - startTime) * timeScale; // for example: (33-35) * 0.14 = 0.28 if (internalCounter >= overallTime) { //Debug.Log("BTC.PlayMegaPointCacheTimeline.running: finished " + nmpc.GetFrame() + " " + internalCounter); state = "finished"; animationTime += overallTime; Task.SetSucceeded(); //return; } // in release else if (internalCounter >= Mathf.Abs(attack * 2 + delay)) { // for example: 0.28 > (0.2*2+0.6) = false internalCounter -= Mathf.Abs(attack * 2 + delay); float t = internalCounter / (2 * release); animationTime += attack + delay + release * IntegralEasing.EaseOutCubic(t); //Debug.Log("BTC.PlayMegaPointCacheTimeline: release " + animationTime + " i " + internalCounter + " t " + t); state = "release"; } // in delay else if (internalCounter >= Mathf.Abs(attack * 2)) { // for example: 0.28 > (0.2*2) = false internalCounter -= Mathf.Abs(attack * 2); float t = internalCounter / delay; animationTime += attack + delay * t; //Debug.Log("BTC.PlayMegaPointCacheTimeline: delay " + animationTime + " i " + internalCounter + " t " + t); state = "delay"; } // in attack else { // for example: true internalCounter = internalCounter; // for example: 0.28 = 0.28 float t = internalCounter / (2 * attack); animationTime += attack * IntegralEasing.EaseInCubic(t); //Debug.Log("BTC.PlayMegaPointCacheTimeline: attack " + animationTime + " i " + internalCounter + " t " + t); state = "attack"; } break; case NodeState.Aborting: //Debug.Log("BTC.PlayMegaPointCacheTimeline.stopping: " + nmpc.GetFrame() + " " + internalCounter); internalCounter = overallTime; //Debug.Log("BTC.PlayMegaPointCacheTimeline: stop "); state = "stop"; animationTime += attack + delay + release; // prevent applying the time return; break; } //Task.log = "t " + animationTime + " i " + internalCounter + " s " + timeScale + " o " + overallTime; float delta = (animationTime - nmpc.GetFrame()) / timeScale; //Debug.Log("BTC.PlayMegaPointCacheTimeline: " + state + " " + animationTime + " delta " + delta + " i " + internalCounter); nmpc.SetFrame(animationTime); } } #endif #endregion #region Speech Intent Recognizer and Speech Synthesizer private ViaggioAIManager _speechMng { get { return ViaggioAIManager.Instance; } } private RequestDataModel _requestDataModel = new RequestDataModel(); private string _recognizedIntentID = ""; private bool _onIntentRecognitionSucceededEventTriggered = false; private bool _onUserSpeechInputStartedEventTriggered = false; private bool _onIntentRecognitionFailedEventTriggered = false; private bool _onSpeechOutputStartedEventTriggered = false; private bool _onSpeechOutputEndedEventTriggered = false; private bool _abortSpeechEventListener = false; void OnDisable() { UnsubscribeFromEvents(); } private void SubscribeToEvents() { if (_speechMng != null) { // Speech Intent Recognizer Events _speechMng.OnUserSpeechInputStartedEvent += UserSpeechInputStartedEventHandler; _speechMng.OnIntentRecognitionSucceededEvent += IntentRecognitionSucceededEventHandler; _speechMng.OnIntentRecognitionFailedEvent += IntentRecognitionFailedEventHandler; // Speech Output Events _speechMng.OnSpeechOutputStartedEvent += SpeechOutputStartedEventHandler; _speechMng.OnSpeechOutputEndedEvent += SpeechOutputEndedEventHandler; Debug.Log("SubscribeToEvents successfull."); } } private void UnsubscribeFromEvents() { if (_speechMng != null) { _speechMng.OnIntentRecognitionSucceededEvent -= IntentRecognitionSucceededEventHandler; _speechMng.OnUserSpeechInputStartedEvent -= UserSpeechInputStartedEventHandler; _speechMng.OnIntentRecognitionFailedEvent -= IntentRecognitionFailedEventHandler; _speechMng.OnSpeechOutputStartedEvent -= SpeechOutputStartedEventHandler; _speechMng.OnSpeechOutputEndedEvent -= SpeechOutputEndedEventHandler; } } private void IntentRecognitionSucceededEventHandler(object sender, string intentID) { _onIntentRecognitionSucceededEventTriggered = true; _recognizedIntentID = intentID; } private void UserSpeechInputStartedEventHandler(object sender, object e) { _onUserSpeechInputStartedEventTriggered = true; } private void IntentRecognitionFailedEventHandler(object sender, bool e) { _onIntentRecognitionFailedEventTriggered = true; } private void SpeechOutputStartedEventHandler(object sender, bool e) { _onSpeechOutputStartedEventTriggered = true; } private void SpeechOutputEndedEventHandler(object sender, bool e) { _onSpeechOutputEndedEventTriggered = true; } [Task] public async void InitializeSpeechManager() { if (Task.getState == NodeState.FirstRun) { while (_speechMng == null) { await System.Threading.Tasks.Task.Delay(10); } SubscribeToEvents(); Task.SetSucceeded(); return; } } [Task] public void AddPossbileSpeechIntent(string intentID, string intentText) { if (Task.getState == NodeState.FirstRun) { _requestDataModel.PossibleIntents.Add(intentID, intentText); foreach (var r in _requestDataModel.PossibleIntents) { Debug.Log($"Possible Intent: {r.Key}, {r.Value}"); } Task.SetSucceeded(); return; } } [Task] public void StartSpeechIntentRecognition() { if (Task.getState == NodeState.FirstRun) { _onUserSpeechInputStartedEventTriggered = false; _speechMng.StartIntentRecognition(_requestDataModel.PossibleIntents); Task.SetSucceeded(); return; } } [Task] public void UserStartedSpeechInput() { if (Task.getState == NodeState.FirstRun) { _onIntentRecognitionSucceededEventTriggered = false; _onIntentRecognitionFailedEventTriggered = false; } if (_onUserSpeechInputStartedEventTriggered) { Task.SetSucceeded(); Debug.Log("UserStartedSpeechInput succeded."); return; } if (_abortSpeechEventListener) { Task.SetFailed(); Debug.Log("UserStartedSpeechInput failed."); _abortSpeechEventListener = false; return; } } [Task] public void SpeechIntentRecognized() { if (_onIntentRecognitionSucceededEventTriggered) { Task.SetSucceeded(); Debug.Log("SpeechIntentRecognized successfull"); return; } if (_onIntentRecognitionFailedEventTriggered) { Task.SetFailed(); Debug.Log("SpeechIntentRecognized failed"); return; } } [Task] public void CompareUserSpeechInputStarted(bool value) { if (Task.getState == NodeState.FirstRun) { if (_onUserSpeechInputStartedEventTriggered == value) { Debug.Log($"CompareUserSpeechInputStarted with {value} = equal"); Task.SetSucceeded(); return; } else { Debug.Log($"CompareUserSpeechInputStarted with {value} = not equal"); Task.SetFailed(); return; } } } [Task] public void CompareIntentID(string intentID) { if (Task.getState == NodeState.FirstRun) { if (_recognizedIntentID == intentID) { Debug.Log($"CompareIntentID {_recognizedIntentID} with {intentID} = equal"); Task.SetSucceeded(); return; } else { Debug.Log($"CompareIntentID {_recognizedIntentID} with {intentID} = not equal"); Task.SetFailed(); return; } } } [Task] public void AbortSpeechEventListener() { if (Task.getState == NodeState.FirstRun) { _abortSpeechEventListener = true; Task.SetSucceeded(); return; } } [Task] public void ClearPossbileSpeechIntents() { if (Task.getState == NodeState.FirstRun) { _requestDataModel.PossibleIntents.Clear(); _recognizedIntentID = ""; Task.SetSucceeded(); return; } } [Task] public void StopSpeechIntentRecognition() { if (Task.getState == NodeState.FirstRun) { _speechMng.StopIntentRecognition(); Task.SetSucceeded(); return; } } [Task] public void SetSpeechRecognitionLanguage(string languageCode) { if (Task.getState == NodeState.FirstRun) { _speechMng.SetSpeechRecognitionLanguage(languageCode); Debug.Log($"Set Speech Recognition Language to {languageCode}"); Task.SetSucceeded(); return; } } [Task] public void SynthesizeText(string text, string languageCode, string voiceName) { if (Task.getState == NodeState.FirstRun) { _onSpeechOutputStartedEventTriggered = false; _onSpeechOutputEndedEventTriggered = false; if (voiceName == "") { // Default Voice _speechMng.SynthesizeText(text, languageCode); } else { _speechMng.SynthesizeText(text, languageCode, voiceName); } } if (_onSpeechOutputStartedEventTriggered) { Debug.Log("SynthesizeText: Speech Output started."); Task.SetSucceeded(); return; } } [Task] public void SpeechOutputEnded() { if (_onSpeechOutputEndedEventTriggered) { Debug.Log("SynthesizeText: Speech Output ended."); Task.SetSucceeded(); return; } } #endregion #region Visited Stories Manager [Task] public void StoryAVisited() { if (Task.getState == NodeState.FirstRun) { if (VisitedStories.StoryA) { Debug.Log("Story A was visited."); Task.SetSucceeded(); return; } else { Debug.Log("Story A was not visited."); Task.SetFailed(); return; } } } [Task] public void StoryBVisited() { if (Task.getState == NodeState.FirstRun) { if (VisitedStories.StoryB) { Debug.Log("Story B was visited."); Task.SetSucceeded(); return; } else { Debug.Log("Story B was not visited."); Task.SetFailed(); return; } } } [Task] public void StoryCVisited() { if (Task.getState == NodeState.FirstRun) { if (VisitedStories.StoryC) { Debug.Log("Story C was visited."); Task.SetSucceeded(); return; } else { Debug.Log("Story C was not visited."); Task.SetFailed(); return; } } } [Task] public void SetStoryAVisited() { if (Task.getState == NodeState.FirstRun) { VisitedStories.StoryA = true; Debug.Log($"Set Visited Story A = {VisitedStories.StoryA}"); Task.SetSucceeded(); return; } } [Task] public void SetStoryBVisited() { if (Task.getState == NodeState.FirstRun) { VisitedStories.StoryB = true; Debug.Log($"Set Visited Story B = {VisitedStories.StoryB}"); Task.SetSucceeded(); return; } } [Task] public void SetStoryCVisited() { if (Task.getState == NodeState.FirstRun) { VisitedStories.StoryC = true; Debug.Log($"Set Visited Story C = {VisitedStories.StoryC}"); Task.SetSucceeded(); return; } } [Task] public void IncrementRepetitionVisitedCounter() { if (Task.getState == NodeState.FirstRun) { VisitedStories.RepetitionCounter++; Debug.Log($"Set Visited Repetition Counter = {VisitedStories.RepetitionCounter}"); Task.SetSucceeded(); return; } } [Task] public void CompareRepetitionVisitedCounter(int number) { if (Task.getState == NodeState.FirstRun) { if (VisitedStories.RepetitionCounter == number) { Debug.Log($"Visited Repetition Counter equals {number}"); Task.SetSucceeded(); return; } else { Debug.Log($"Visited Repetition Counter not equals {number}"); Task.SetFailed(); return; } } } #endregion #region Oculus Input #if OCULUSVR_AVAILABLE [Task] public void OVRInputGetDown (string buttonName) { if (System.Enum.TryParse(buttonName, out OVRInput.Button button)) { switch (Task.getState) { case NodeState.FirstRun: case NodeState.Running: if (OVRInput.GetDown(button)) { Task.SetSucceeded(); return; } break; case NodeState.Aborting: case NodeState.NotRunning: break; } } else { Debug.LogError($"OVRInputGetDown: unknown button {buttonName}"); Task.SetError(); } } [Task] public void OVRInputGetUp (string buttonName) { if (System.Enum.TryParse(buttonName, out OVRInput.Button button)) { switch (Task.getState) { case NodeState.FirstRun: case NodeState.Running: if (OVRInput.GetUp(button)) { Task.SetSucceeded(); return; } break; case NodeState.Aborting: case NodeState.NotRunning: break; } } else { Debug.LogError($"OVRInputGetUp: unknown button {buttonName}"); Task.SetError(); } } [Task] public void OVRInputGet (string buttonName) { if (System.Enum.TryParse(buttonName, out OVRInput.Button button)) { switch (Task.getState) { case NodeState.FirstRun: case NodeState.Running: if (OVRInput.Get(button)) { Task.SetSucceeded(); return; } else { Task.SetFailed(); return; } break; case NodeState.Aborting: case NodeState.NotRunning: break; } } else { Debug.LogError($"OVRInputGet: unknown button {buttonName}"); Task.SetError(); } } #endif #endregion #region keyboard input [Task] public void GetKeyDown (string buttonName) { KeyCode button; if (System.Enum.TryParse(buttonName, out button)) { switch (Task.getState) { case NodeState.FirstRun: case NodeState.Running: // Debug.Log($"GetKey: checking {button}"); if (UnityEngine.Input.GetKeyDown(button)) { Task.SetSucceeded(); return; } break; case NodeState.Aborting: case NodeState.NotRunning: break; } } else { Debug.LogError($"GetKeyDown: unknown key {buttonName}"); Task.SetError(); } } [Task] public void GetKeyUp (string buttonName) { KeyCode button; if (System.Enum.TryParse(buttonName, out button)) { switch (Task.getState) { case NodeState.FirstRun: case NodeState.Running: // Debug.Log($"GetKey: checking {button}"); if (UnityEngine.Input.GetKeyUp(button)) { Task.SetSucceeded(); return; } break; case NodeState.Aborting: case NodeState.NotRunning: break; } } else { Debug.LogError($"GetKeyUp: unknown key {buttonName}"); Task.SetError(); } } [Task] public void GetKey (string buttonName) { KeyCode button; if (System.Enum.TryParse(buttonName, out button)) { switch (Task.getState) { case NodeState.FirstRun: case NodeState.Running: // Debug.Log($"GetKey: checking {button}"); if (UnityEngine.Input.GetKey(button)) { Task.SetSucceeded(); return; } else { Task.SetFailed(); return; } break; case NodeState.Aborting: case NodeState.NotRunning: break; } } else { Debug.LogError($"GetKey: unknown key {buttonName}"); Task.SetError(); } } #endregion #region SC public Transform cameraRoot; //public Transform[] cameraRootPositions; [Task] void ReparentCameraToGameObject(string gameObjectName) { foreach (NamedGameObject ngo in GetHandlers(gameObjectName)) { // NamedGameObject ngo = GetNamedObject(gameObjectName); if (ngo != null) { if (Task.isStarting) { cameraRoot.transform.parent = ngo.transform; cameraRoot.localPosition = Vector3.zero; Debug.Log($"BTC.ReparentCameraToGameObject: reparent camera to {ngo.name}"); } Task.SetSucceeded(); return; } Task.SetFailed(); } } [Task] public void Wait(float timer) { switch (Task.getState) { case NodeState.FirstRun: Task.data = Time.time; break; case NodeState.Running: float startTime = (float)Task.data; float elapsed = Time.time - startTime; Task.log = "" + timer; if (elapsed > timer) { Task.SetSucceeded(); return; } break; case NodeState.Aborting: break; } //if (debug) // Debug.Log("TestScript.Timer: " + timer + " " + thisNodeState); } [Task] public void RestartBT() { switch (Task.getState) { case NodeState.FirstRun: case NodeState.Running: GetComponent().Restart(); // dont succeeed, wait for restart break; case NodeState.Aborting: break; } } #endregion #region Blackboard Dictionary boolValueDictionary = new Dictionary(); [Task] void ClearBool (string key) { if ((Task.getState == NodeState.FirstRun) || (Task.getState == NodeState.Running)) { Debug.Log($"ClearBool {key}"); boolValueDictionary.Remove(key); Task.SetSucceeded(); } } [Task] void SetBool (string key) { if ((Task.getState == NodeState.FirstRun) || (Task.getState == NodeState.Running)) { SetBool(key, true); Task.SetSucceeded(); } } [Task] void SetBool (string key, bool value) { if ((Task.getState == NodeState.FirstRun) || (Task.getState == NodeState.Running)) { Debug.Log($"SetBool {key} to {value}"); boolValueDictionary[key] = value; Task.SetSucceeded(); } } [Task] void CompareBool (string key) { if ((Task.getState == NodeState.FirstRun) || (Task.getState == NodeState.Running)) { CompareBool(key, true); } } [Task] void CompareBool (string key, bool value) { if ((Task.getState == NodeState.FirstRun) || (Task.getState == NodeState.Running)) { if (boolValueDictionary.ContainsKey(key)) { if (boolValueDictionary[key] == value) { Debug.Log($"CompareBool {key} with {value} = equal"); Task.SetSucceeded(); return; } else { Debug.Log($"CompareBool {key} with {value} = not equal"); Task.SetFailed(); return; } } else { Task.SetFailed(); return; } } } Dictionary floatValueDictionary = new Dictionary(); [Task] void ClearFloat (string key) { if ((Task.getState == NodeState.FirstRun) || (Task.getState == NodeState.Running)) { floatValueDictionary.Remove(key); Task.SetSucceeded(); } } [Task] void AddFloat (string key, float value) { if ((Task.getState == NodeState.FirstRun) || (Task.getState == NodeState.Running)) { if (!floatValueDictionary.ContainsKey(key)) { floatValueDictionary[key] = 0; } floatValueDictionary[key] += value; Task.SetSucceeded(); } } [Task] void SetFloat (string key, int value) { if ((Task.getState == NodeState.FirstRun) || (Task.getState == NodeState.Running)) { floatValueDictionary[key] = value; Task.SetSucceeded(); } } [Task] void CompareFloatBigger (string key, float compareValue) { if ((Task.getState == NodeState.FirstRun) || (Task.getState == NodeState.Running)) { float value = 0; if (floatValueDictionary.ContainsKey(key)) { value = floatValueDictionary[key]; } else { Debug.LogError($"FloatBigger: no value defined for {key}"); } if (value > compareValue) { Task.SetSucceeded(); } else { Task.SetFailed(); } } } Dictionary intDictionary = new Dictionary(); [Task] void ClearInt (string key) { if ((Task.getState == NodeState.FirstRun) || (Task.getState == NodeState.Running)) { intDictionary.Remove(key); Task.SetSucceeded(); } } [Task] void AddInt (string key, int value) { if ((Task.getState == NodeState.FirstRun) || (Task.getState == NodeState.Running)) { if (!intDictionary.ContainsKey(key)) { intDictionary[key] = 0; } intDictionary[key] += value; Debug.Log($"IndAdd {key} {intDictionary[key]}"); Task.SetSucceeded(); } } [Task] void SetInt (string key, int value) { if ((Task.getState == NodeState.FirstRun) || (Task.getState == NodeState.Running)) { intDictionary[key] = value; Debug.Log("IntSet "+key+" "+intDictionary[key]); Task.SetSucceeded(); } } [Task] void CompareIntBigger (string key, float compareValue) { if ((Task.getState == NodeState.FirstRun) || (Task.getState == NodeState.Running)) { int value = 0; if (intDictionary.ContainsKey(key)) { value = intDictionary[key]; } else { Debug.LogError("CounterBigger: no value defined for "+key); } Debug.Log("IntBigger "+key+" "+value+" > "+compareValue); if (value > compareValue) { Task.SetSucceeded(); } else { Task.SetFailed(); } } } [Task] void LogMessage(string logMessage) { Debug.Log(logMessage); Task.SetSucceeded(); } #endregion #region Succeed and fail [Task] void Fail() { Task.SetFailed(); } [Task] void Succeed() { Task.SetSucceeded(); } #endregion }