//============= Copyright (c) Ludic GmbH, All rights reserved. ============== // // Purpose: Part of the My Behaviour Tree Code // //============================================================================= using UnityEngine; using System; using System.Linq; //using System.Runtime.Serialization.Configuration; using System.Collections; using System.Collections.Generic; using System.IO; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Serialization; using System.Xml.Serialization; #if UNITY_EDITOR using UnityEditor; #endif namespace MyBT { [System.Serializable] public class DictionaryOfStringAndMethodImplementation : SerializableDictionary {} [System.Serializable] public class DictionaryOfStringAndDictionaryOfStringAndMethodImplementation : SerializableDictionary {} public enum TickUpdateMode { // run in update / lateUpdate Update, LateUpdate, // run in an interval for 1 step DelayedUpdate, DelayedLateUpdate, // run for a maximum time MaximumTimeUpdate, MaximumTimeLateUpdate, // run a full cycle FullrunUpdate, FullrunLateUpdate, // run manually Manual } [ExecuteInEditMode, System.Serializable] public partial class TaskController : MonoBehaviour { #region unity inspector updater (only in editor) // handling changes of the bt -> requires redrawing of the editor ui [NonSerialized] public Action InspectorRedraw; [NonSerialized] public Action InspectorRegenerate; // called from lateUpdate [System.Diagnostics.Conditional("UNITY_EDITOR")] void CallInspectorRedraw() { // makes unity editor very slow!!! //UnityEditorInternal.InternalEditorUtility.RepaintAllViews(); lastTickTime = currentUiTime; if (InspectorRedraw != null) InspectorRedraw.Invoke(false); } // called from lateUpdate [System.Diagnostics.Conditional("UNITY_EDITOR")] void CallInspectorRegenerate() { if (InspectorRegenerate != null) InspectorRegenerate.Invoke(false); } // when was the tick executed last time public float lastTickTime = 0; // when was the behaviour tree changed last time private float lastUiChangedTime = 0; // has the behaviour tree changed in this frame? // it is called from TaskControllerInspector public bool UiChangedThisFrame () { return (lastTickTime == lastUiChangedTime); } public bool UiChangedAt (float time) { return lastTickTime == time; } // called to set behaviour tree changed public void SetUiUpdate() { // time at beginning of frame lastUiChangedTime = TaskController.currentUiTime; } public static float currentUiTime { get { return Time.time; } } #endregion #region settings // tick settings public float tickDelay = 0f; public float maximumRuntime = 0.1f; public TickUpdateMode tickMode = TickUpdateMode.Update; // generation settings public bool runtimeAutomaticRegenerate = true; public bool resetDataOnCodeChange = false; // logging public bool runtimeLogging = false; public bool overrideLogStringDisplay = false; public bool overrideDebugInternalActive = false; public bool overrideDebugChangesActive = false; // timer for tick delay calculation private float tickDelayTimer = 0f; NodeResult rootResult = NodeResult.Succeeded; #if false public IEnumerator _tickEnumerator; public IEnumerator tickEnumerator { get { return _tickEnumerator; } set { if (runtimeLogging) Debug.LogWarning($"setting tickEnumerator to '{value}'"); _tickEnumerator = value; } } #else public IEnumerator tickEnumerator; #endif private bool tickSuccess = false; #endregion #region duplicate watcher // #if UNITY_EDITOR // Catch duplication of this GameObject [SerializeField] private int instanceID = 0; /// /// Detect when the GameObject has been duplicated /// if so make sure then dont share the same instance of the behaviour tree generator /// void AwakeDuplicateCatcher() { if (instanceID != GetInstanceID()) { if (generatorLogging) Debug.Log($"Detected Duplicate! ( {instanceID} != {GetInstanceID()} )"); // Do whatever you need to set up the duplicate // copy old contents // List oldTaskScripts = new List(); // for (int i=0; i(); } if (__behaviourTreeGenerator == null) { Debug.LogError($"behaviourTreeGenerator is null... how? {behaviourTreeGenerator}"); } return __behaviourTreeGenerator; } } // expose parts of the behaviourTreeGenerator #endregion #region functions and variables from behaviourTreeGenerator // configuration [SerializeField] public List taskScripts; public bool generatorLogging { get { return behaviourTreeGenerator.generatorLogging; } set { behaviourTreeGenerator.generatorLogging = value; } } public bool internalAutomaticRegenerate { get { return behaviourTreeGenerator.internalAutomaticRegenerate; } set { behaviourTreeGenerator.internalAutomaticRegenerate = value; } } public TreeNode rootNode { get { return behaviourTreeGenerator.rootNode; } } public bool hasRootNode { get { return (behaviourTreeGenerator.rootNode != null); } } public void FullGenerate (bool force) { behaviourTreeGenerator.FullGenerate(this, force); } public void FullReset () { behaviourTreeGenerator.FullReset(); } private bool restartBehaviourTreeNextFrame = false; public void Restart(bool forceImmediate=false) { restartBehaviourTreeNextFrame = true; if (forceImmediate) { RestartNow(); } } private void RestartNow () { behaviourTreeGenerator.Restart(); restartBehaviourTreeNextFrame = false; } public void VerifyBindings() { behaviourTreeGenerator.VerifyBinding(this); } public void RegenerateBehaviourTreeIfRequired (bool forceUpdate) { behaviourTreeGenerator.RegenerateBehaviourTreeIfRequired(this, forceUpdate); } /// /// the methods called have changed (or might have...) /// we dont yet filter which scripts are changed /// public void ClearBindingsAndScanAndBindMethods(bool forceUpdate = false) { // forcefully clear and regenerate behaviourTreeGenerator.ClearBindingsAndScanAndBindMethods(this, forceUpdate); } /// /// is called by DetectBtChanges /// /// public void BtScriptChangeDetected(bool forceUpdate = false) { behaviourTreeGenerator.BtScriptChangeDetected(this, forceUpdate); } public void ResetNodesAndTokens() { behaviourTreeGenerator.ResetNodesAndTokens(); } public void GenerateTokensAndNodes(bool forceUpdate = false) { Debug.Log("GenerateTokensAndNodes"); behaviourTreeGenerator.GenerateTokensAndNodes(this, forceUpdate); } public void ClearBinding() { behaviourTreeGenerator.ClearBinding(); } public void ScanAndBindMethods(bool forceUpdate = false) { behaviourTreeGenerator.ScanAndBindMethods(this, forceUpdate); } public void SetTaskController() { behaviourTreeGenerator.SetTaskControllerAndGenerateCache(this); } public void SetBehaviourTreeDirty() { #if UNITY_EDITOR EditorUtility.SetDirty(behaviourTreeGenerator); #endif } public bool CheckBindingOutdated(bool allowNull = true) { return behaviourTreeGenerator.CheckBindingOutdated(this, allowNull); } public bool CheckGenerationOutdated(bool allowNull = true) { return behaviourTreeGenerator.CheckGenerationOutdated(allowNull); } // status // hasScript && tokensGenerated && nodesGenerated // public bool isGenerated { // get { return behaviourTreeGenerator.isGenerated; } // } // public string generationState { // get { return behaviourTreeGenerator.generationState; } // } public bool hasScript { get { return behaviourTreeGenerator.HasScripts(this); } } // public bool tokensGenerated { // get { return behaviourTreeGenerator.tokensGenerated; } // } // public bool nodesGenerated { // get { return behaviourTreeGenerator.nodesGenerated; } // } public FileHash textAssetHashes { get { return behaviourTreeGenerator.textAssetHashes; } } public FileHash generatedCodeBtFileHashes { get { return behaviourTreeGenerator.generatedCodeBtFileHashes; } } public FileHash boundCodeBtFileHashes { get { return behaviourTreeGenerator.boundCodeBtFileHashes; } } public List tokens { get { return behaviourTreeGenerator.tokens; } } public List treeRootNodes { get { return behaviourTreeGenerator.treeRootNodes; } } #if UNITY_EDITOR public SerializedProperty treeRootNodesAsSerializedProperty { get { SerializedObject sObj = new SerializedObject(behaviourTreeGenerator); return sObj.FindProperty("treeRootNodes"); } } #endif public int nodeCount { get { return behaviourTreeGenerator.nodeCount; } } public bool generationError { get { return behaviourTreeGenerator.generationError; } } public bool bindingError { get { return behaviourTreeGenerator.bindingError; } } // public bool methodsScanned { // get { return behaviourTreeGenerator.methodsScanned; } // } // public bool methodsBound { // get { return behaviourTreeGenerator.methodsBound; } // } public DictionaryOfStringAndDictionaryOfStringAndMethodImplementation methods { get { return behaviourTreeGenerator.methods; } } #endregion } }