void IGameObjectManagerAction.perform() // before this call GO is like a ghost for FYFY (not known by families but present into the scene) { if (_gameObject == null) // The GO has been destroyed !!! { throw new DestroyedGameObjectException("You try to bind a GameObject that will be destroyed during this frame. In a same frame, your must not destroy a GameObject and ask Fyfy to perform an action on it.", _exceptionStackTrace); } int gameObjectId = _gameObject.GetInstanceID(); if (!GameObjectManager._gameObjectWrappers.ContainsKey(gameObjectId)) { GameObjectWrapper gameObjectWrapper = new GameObjectWrapper(_gameObject, _componentTypeNames); GameObjectManager._gameObjectWrappers.Add(gameObjectId, gameObjectWrapper); GameObjectManager._modifiedGameObjectIds.Add(gameObjectId); // Add the bridge if not already added if (!_gameObject.GetComponent <FyfyBridge>()) { _gameObject.AddComponent <FyfyBridge>(); } } else { throw new FyfyException("A game object can be binded to Fyfy only once. The game object \"" + _gameObject.name + "\" (instance id:" + gameObjectId + ") is already binded.", _exceptionStackTrace); } }
internal static void updateAfterGameObjectModified(int gameObjectId) { if (GameObjectManager._gameObjectWrappers.ContainsKey(gameObjectId)) { GameObjectWrapper gameObjectWrapper = GameObjectManager._gameObjectWrappers[gameObjectId]; UnityEngine.GameObject gameObject = gameObjectWrapper._gameObject; // Prevent user error if a GameObject is destroyed while it is still binded. It's a mistake, the user has to unbind game objects before destroying them. if (gameObject != null) { foreach (Family family in FamilyManager._families.Values) { if (family.matches(gameObjectWrapper)) { if (family.Add(gameObjectId, gameObject) && family._entryCallbacks != null) { // execute family's entry callbacks on the GameObject if added family._entryCallbacks(gameObject); } } else if (family.Remove(gameObjectId) && family._exitCallbacks != null) { // execute family's exit callbacks on the GameObject if removed family._exitCallbacks(gameObjectId); } } } } }
internal bool matches(GameObjectWrapper gameObjectWrapper) { for (int i = 0; i < _matchers.Length; ++i) { if (_matchers[i].matches(gameObjectWrapper) == false) { return(false); } } return(true); }
/// <summary> /// Gets the family defined by a set of <see cref="FYFY.Matcher"/>. /// </summary> /// <remarks> /// <para> /// You get always a family that is initialized, ie which contains the <c>GameObjects</c> /// of the actual scene which respect all the contraints and which are known by <c>FYFY</c>. /// So you can parse it directly. /// </para> /// <para> /// To be known by <c>FYFY</c>, a <c>GameObject</c> must be created in editor outside runtime /// or in code with <see cref="FYFY.GameObjectManager">functions</see>. /// </para> /// <para> /// This is the only way to get family reference. /// You cannot create a <see cref="FYFY.Family"/> object by yourself. /// </para> /// </remarks> /// <returns> /// The reference of the corresponding family. /// </returns> /// <param name="matchers"> /// Matchers. /// </param> public static Family getFamily(params Matcher[] matchers) { int mLength = matchers.Length; if (mLength == 0) { throw new System.ArgumentException("It is not allowed to get family without at least one matcher."); } string[] matchersDescriptors = new string[mLength]; for (int i = 0; i < mLength; ++i) { Matcher matcher = matchers[i]; if (matcher == null) { throw new System.ArgumentNullException("One of the matchers is null, family recovery aborted."); } matchersDescriptors[i] = matcher._descriptor; } System.Array.Sort(matchersDescriptors); string familyDescriptor = string.Join("/", matchersDescriptors); Family family; // If it doesn't exist yet, create it and add it in the families dictionary. if (_families.TryGetValue(familyDescriptor, out family) == false) { family = new Family(matchers); _families.Add(familyDescriptor, family); // Initialize with known GameObjects if they respect conditions. foreach (KeyValuePair <int, GameObjectWrapper> valuePair in GameObjectManager._gameObjectWrappers) { int gameObjectId = valuePair.Key; GameObjectWrapper gameObjectWrapper = valuePair.Value; if (family.matches(gameObjectWrapper)) { family.Add(gameObjectId, gameObjectWrapper._gameObject); } } } return(family); }
// Parse scene and bind all GameObjects to FYFY // Create all systems private void OnEnable() { // if upgrade FYFY, old version instance could be null because Awake is not called again, we set instance reference properly if (instance == null) { instance = this; } if (Application.isPlaying == false) { return; } // Parse scene and bind GameObjects to FYFY List <GameObject> sceneGameObjects = new List <GameObject>(); if (_loadingState == 0) { // Bind all game objects except ones defined in _specialGameObjects GameObject[] roots = UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects(); foreach (GameObject root in roots) { foreach (Transform childTransform in root.GetComponentsInChildren <Transform>(true)) // include root transform // Check if current game object is not an excluded game object or a child of an excluded game object { bool needToExclude = false; foreach (GameObject excluded in _specialGameObjects) { if (excluded != null) { if (childTransform.IsChildOf(excluded.transform)) // true if childTransform == excluded.transform { needToExclude = true; break; } } } if (!needToExclude) { sceneGameObjects.Add(childTransform.gameObject); } } } } else { // Bind only game objects defined in _specialGameObjects foreach (GameObject included in _specialGameObjects) { if (included != null) { foreach (Transform childTransform in included.GetComponentsInChildren <Transform>(true)) // include itself { sceneGameObjects.Add(childTransform.gameObject); } } } } // Bind all game object tagged as DontDestroyOnLoad foreach (GameObject ddol_go in GameObjectManager._ddolObjects) { if (ddol_go != null) { foreach (Transform childTransform in ddol_go.GetComponentsInChildren <Transform>(true)) // include itself { sceneGameObjects.Add(childTransform.gameObject); } } } foreach (GameObject gameObject in sceneGameObjects) { // In case of GameObject state (enable/disable) is controlled by Unity tools (animators for instance) Fyfy is not notified from this change => solution add a special component that catch Unity events and submit update to FYFY if (!gameObject.GetComponent <FyfyBridge>()) { gameObject.AddComponent <FyfyBridge>(); } // Compute Wrappers HashSet <string> componentTypeNames = new HashSet <string>(); foreach (Component c in gameObject.GetComponents <Component>()) { if (c != null) // it is possible if a GameObject contains a breaked component (Missing script) { System.Type type = c.GetType(); componentTypeNames.Add(type.FullName); } } GameObjectWrapper gameObjectWrapper = new GameObjectWrapper(gameObject, componentTypeNames); if (!GameObjectManager._gameObjectWrappers.ContainsKey(gameObject.GetInstanceID())) { GameObjectManager._gameObjectWrappers.Add(gameObject.GetInstanceID(), gameObjectWrapper); } } // Create all systems for (int i = 0; i < _fixedUpdateSystemDescriptions.Length; ++i) { SystemDescription systemDescription = _fixedUpdateSystemDescriptions[i]; try{ FSystem system = this.createSystemInstance(systemDescription); if (system != null) { FSystemManager._fixedUpdateSystems.Add(system); // set reference of this system in its wrapper string compilableName = systemDescription._typeFullName.Replace('.', '_'); Component wrapper = gameObject.GetComponent(compilableName + "_wrapper"); if (wrapper != null) { (wrapper as BaseWrapper).system = system; } } else { UnityEngine.Debug.LogError(systemDescription._typeFullName + " class doesn't exist, hooking up this FSystem to FixedUpdate context aborted. Check your MainLoop Game Object."); } }catch (System.Exception e) { UnityEngine.Debug.LogException(e); } } for (int i = 0; i < _updateSystemDescriptions.Length; ++i) { SystemDescription systemDescription = _updateSystemDescriptions[i]; try{ FSystem system = this.createSystemInstance(systemDescription); if (system != null) { FSystemManager._updateSystems.Add(system); // set reference of this system in its wrapper string compilableName = systemDescription._typeFullName.Replace('.', '_'); Component wrapper = gameObject.GetComponent(compilableName + "_wrapper"); if (wrapper != null) { (wrapper as BaseWrapper).system = system; } } else { UnityEngine.Debug.LogError(systemDescription._typeFullName + " class doesn't exist, hooking up this FSystem to Update context aborted. Check your MainLoop Game Object."); } } catch (System.Exception e) { UnityEngine.Debug.LogException(e); } } for (int i = 0; i < _lateUpdateSystemDescriptions.Length; ++i) { SystemDescription systemDescription = _lateUpdateSystemDescriptions[i]; try{ FSystem system = this.createSystemInstance(systemDescription); if (system != null) { FSystemManager._lateUpdateSystems.Add(system); // set reference of this system in its wrapper string compilableName = systemDescription._typeFullName.Replace('.', '_'); Component wrapper = gameObject.GetComponent(compilableName + "_wrapper"); if (wrapper != null) { (wrapper as BaseWrapper).system = system; } } else { UnityEngine.Debug.LogError(systemDescription._typeFullName + " class doesn't exist, hooking up this FSystem to LateUpdate context aborted. Check your MainLoop Game Object."); } } catch (System.Exception e) { UnityEngine.Debug.LogException(e); } } _stopwatch = new Stopwatch(); }