using System; using System.Collections.Generic; using XGame.Framework.Asyncs; using XGame.Framework.Interfaces; namespace XGame.Framework.Nodes { public class NodeGroup : INodeGroup, IUpdate, ILateUpdate, IDisposable { private Dictionary _openedMap; /// /// 加载中,卸载中,关闭的都在这里 /// private Dictionary _closedMap; private List _updateNodes; /// /// 每个Group单独一个Context /// private NodeContext _context; public NodeGroup(NodeContext context) { _context = context; _openedMap = new Dictionary(); _closedMap = new Dictionary(); _updateNodes = new List(); } #region 接口实现 bool INodeGroup.IsActive(NodeKey nodeKey) { if (_openedMap.TryGetValue(nodeKey, out var node)) { return node.Active; } return false; } IAsync INodeGroup.AddAsync(NodeKey nodeKey, object intent) { var key = nodeKey.Key; if (_openedMap.ContainsKey(key)) { Log.Warn($"重复开启Node. Key:{key}"); var asyncGroup = new AsyncGroup(); asyncGroup.End(); return asyncGroup; } if (_closedMap.TryGetValue(key, out var node)) { if (node.State == Loadable.LoadState.Loading) { var loadingAsync = node.LoadingAsync; loadingAsync.On(_ => { ShowNode(key, node, intent); }); return loadingAsync; } if (node.State == Loadable.LoadState.Unloading) { Log.Error($"卸载中的Node又开始加载.Key:{key}"); node.ClearAsyncs(); } } else { node = Activator.CreateInstance(nodeKey.NodeType) as Node; node.Init(_context); _closedMap.Add(key, node); } var loadAsync = node.LoadAsync(); loadAsync.On(_ => { ShowNode(key, node, intent); }); return loadAsync; } void INodeGroup.Remove(NodeKey nodeKey, bool isDestroy) { var key = nodeKey.Key; if (_closedMap.TryGetValue(key, out var node)) { if (node.State == Loadable.LoadState.Unloading) { Log.Debug($"重复移除Node. Key:{key} isDestroy:{isDestroy}"); if (isDestroy) { // 保证能执行destroy node.UnloadingAsync.On(_ => { _closedMap.Remove(key); DestroyNode(node); }); } return; } if (node.State == Loadable.LoadState.Unloaded) { // 已经卸载完成 if (isDestroy) { _closedMap.Remove(key); DestroyNode(node); } return; } } else if (_openedMap.TryGetValue(key, out node)) { _openedMap.Remove(key); node.Disable(); _closedMap.Add(key, node); } else { // 没有数据 return; } var unloadAsync = node.UnloadAsync(); unloadAsync.On(_ => { if (isDestroy) { _closedMap.Remove(key); DestroyNode(node); } }); } IAsync INodeGroup.Preload(NodeKey nodeKey) { var key = nodeKey.Key; if (_openedMap.ContainsKey(key) || _closedMap.ContainsKey(key)) { return null; } var node = Activator.CreateInstance(nodeKey.NodeType) as Node; node.Init(_context); _closedMap.Add(key, node); return node.LoadAsync(); } void IUpdate.Update(int millisecond) { if (_openedMap.Count == 0) return; _updateNodes.Clear(); _updateNodes.AddRange(_openedMap.Values); for (var i = 0; i < _updateNodes.Count;) { var node = _updateNodes[i]; node.Update(millisecond); if (node.Active) { i++; } else { _updateNodes.RemoveAt(i); } } } void ILateUpdate.LateUpdate(int millisecond) { if (_updateNodes.Count == 0) return; foreach (var node in _updateNodes) { node.LateUpdate(millisecond); } _updateNodes.Clear(); } void IDisposable.Dispose() { foreach (var node in _openedMap.Values) { DestroyNode(node); } _openedMap.Clear(); foreach (var node in _closedMap.Values) { DestroyNode(node); } _closedMap.Clear(); _updateNodes.Clear(); (_context as IDisposable)?.Dispose(); _context = null; } #endregion public IAsync RemoveAll(bool isDestroy) { var asyncGroup = new AsyncGroup(); var copyMap = new Dictionary(_openedMap); foreach(var item in copyMap) { var key = item.Key; var node = item.Value; _openedMap.Remove(key); node.Disable(); if (!isDestroy) { _closedMap.Add(key, node); } var unloadAsync = node.UnloadAsync(); unloadAsync.Join(asyncGroup); unloadAsync.On(_ => { if (isDestroy) { DestroyNode(node); } }); } copyMap.Clear(); if (isDestroy) { foreach (var item in _closedMap) { var key = item.Key; var node = item.Value; if (node.State == Loadable.LoadState.Unloading) { var unloadingAsync = node.UnloadingAsync; unloadingAsync.Join(asyncGroup); // 保证能执行destroy unloadingAsync.On(_ => { DestroyNode(node); }); continue; } if (node.State == Loadable.LoadState.Unloaded) { // 已经卸载完成 DestroyNode(node); continue; } var unloadAsync = node.UnloadAsync(); unloadAsync.Join(asyncGroup); unloadAsync.On(_ => { DestroyNode(node); }); } _closedMap.Clear(); } asyncGroup.End(); return asyncGroup; } #region 内部函数 private void ShowNode(string key, Node node, object intent) { if (_openedMap.ContainsKey(key)) { Log.Debug($"重复激活Node. Key:{key}"); return; } _closedMap.Remove(key); _openedMap.Add(key, node); node.Enable(intent); } private void DestroyNode(Node node) { (node as IDisposable)?.Dispose(); } #endregion } }