using NavMeshPlus.Components; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; namespace NavMeshPlus.Extensions { [ExecuteAlways] [AddComponentMenu("Navigation/Navigation CacheSources2d", 30)] public class CollectSourcesCache2d : NavMeshExtension { List _sources; Dictionary _lookup; private Bounds _sourcesBounds; public bool IsDirty { get; protected set; } private NavMeshBuilder2dState _state; public int SourcesCount => _sources.Count; public int CahcheCount => _lookup.Count; public List Cache { get => _sources; } protected override void Awake() { _lookup = new Dictionary(); _sources = new List(); IsDirty = false; Order = -1000; _sourcesBounds = new Bounds(); base.Awake(); } protected override void OnDestroy() { _state?.Dispose(); base.OnDestroy(); } public bool AddSource(GameObject gameObject) { var res = _lookup.ContainsKey(gameObject); if (res) { return UpdateSource(gameObject); } NavMeshBuilder2d.CollectSources(gameObject, _sources, _state); IsDirty = true; return true; } public bool AddSource(GameObject gameObject, NavMeshBuildSource source) { var res = _lookup.ContainsKey(gameObject); if (res) { return UpdateSource(gameObject); } _sources.Add(source); _lookup.Add(gameObject, source); IsDirty = true; return true; } public bool UpdateSource(GameObject gameObject, int? area = null) { var res = _lookup.ContainsKey(gameObject); if(res) { IsDirty = true; var source = _lookup[gameObject]; var idx = _sources.IndexOf(source); if (idx >= 0) { source.transform = Matrix4x4.TRS(gameObject.transform.position, gameObject.transform.rotation, gameObject.transform.lossyScale); if (area.HasValue) { source.area = area.Value; } _sources[idx] = source; _lookup[gameObject] = source; } } return res; } public bool RemoveSource(GameObject gameObject) { var res = _lookup.ContainsKey(gameObject); if (res) { IsDirty = true; var source = _lookup[gameObject]; _lookup.Remove(gameObject); _sources.Remove(source); } return res; } public AsyncOperation UpdateNavMesh(NavMeshData data) { IsDirty = false; return NavMeshBuilder.UpdateNavMeshDataAsync(data, NavMeshSurfaceOwner.GetBuildSettings(), _sources, _sourcesBounds); } public AsyncOperation UpdateNavMesh() { return UpdateNavMesh(NavMeshSurfaceOwner.navMeshData); } public override void CollectSources(NavMeshSurface surface, List sources, NavMeshBuilderState navMeshState) { _lookup.Clear(); IsDirty = false; _state?.Dispose(); _state = navMeshState.GetExtraState(false); _state.lookupCallback = LookupCallback; } private void LookupCallback(UnityEngine.Object component, NavMeshBuildSource source) { if (component == null) { return; } _lookup.Add(component, source); } public override void PostCollectSources(NavMeshSurface surface, List sources, NavMeshBuilderState navNeshState) { _sourcesBounds = navNeshState.worldBounds; _sources = sources; } } }