Base class for all graphs
		public override void OnSceneGUI (NavGraph target) {
			
			//NavMeshGraph graph = target as NavMeshGraph;
			
			/*if (meshRenderer == null) {
				Debug.Log ("IsNull");
				meshRenderer = new GameObject ("NavmeshRenderer");
				meshRenderer.hideFlags = HideFlags.HideAndDontSave;
				
				Renderer renderer = meshRenderer.AddComponent (typeof(MeshRenderer)) as Renderer;
				MeshFilter filter = meshRenderer.AddComponent (typeof(MeshFilter)) as MeshFilter;
				
				Mesh mesh = new Mesh ();
				mesh.vertices = graph.vertices;
				mesh.triangles = graph.triangles;
				
				mesh.RecalculateBounds ();
				mesh.RecalculateNormals ();
				
				filter.mesh = mesh;
				
				renderer.material = new Material (Shader.Find ("Transparent/Diffuse"));
				renderer.material.color = AstarColor.MeshColor;
			} else {
				Debug.Log ("Not Null "+meshRenderer.renderer.enabled+" "+meshRenderer.hideFlags);
				//meshRenderer.transform.position = new Vector3 (0,5,0);//meshRenderer.transform.position+Vector3.up*0.5F;
				meshRenderer.active = false;
				meshRenderer.active = true;
				
				
			}*/
			
			//DrawAALine (Vector3.zero,Vector3.one*20);
		}
        public static void ScanGraph(NavGraph graph)
        {
            if (AstarPath.OnGraphPreScan != null) {
            AstarPath.OnGraphPreScan (graph);
            }

            graph.Scan ();

            int index = AstarPath.active.astarData.GetGraphIndex (graph);
            if (index < 0) throw new System.ArgumentException ("Graph is not added to AstarData");

            if (graph.nodes != null) {
            for (int j=0;j<graph.nodes.Length;j++) {
                if (graph.nodes[j] != null)
                    graph.nodes[j].graphIndex = index;
            }
            }

            if (AstarPath.OnGraphPostScan != null) {
            AstarPath.OnGraphPostScan (graph);
            }

            AstarPath.active.FloodFill ();

            AstarPath.active.DataUpdate ();
        }
		//public GameObject meshRenderer;
		
		public override void OnInspectorGUI (NavGraph target) {
			NavMeshGraph graph = target as NavMeshGraph;
	/*
	#if UNITY_3_3
			graph.sourceMesh = EditorGUILayout.ObjectField ("Source Mesh",graph.sourceMesh,typeof(Mesh)) as Mesh;
	#else
			graph.sourceMesh = EditorGUILayout.ObjectField ("Source Mesh",graph.sourceMesh,typeof(Mesh), true) as Mesh;
	#endif
	*/
			graph.sourceMesh = ObjectField ("Source Mesh", graph.sourceMesh, typeof(Mesh), false) as Mesh;
	
	#if UNITY_LE_4_3
			EditorGUIUtility.LookLikeControls ();
			EditorGUILayoutx.BeginIndent ();
	#endif
			graph.offset = EditorGUILayout.Vector3Field ("Offset",graph.offset);
	
	#if UNITY_LE_4_3
			EditorGUILayoutx.EndIndent ();
			
			EditorGUILayoutx.BeginIndent ();
	#endif
			graph.rotation = EditorGUILayout.Vector3Field ("Rotation",graph.rotation);
	
	#if UNITY_LE_4_3
			EditorGUILayoutx.EndIndent ();
			EditorGUIUtility.LookLikeInspector ();
	#endif
	
			graph.scale = EditorGUILayout.FloatField (new GUIContent ("Scale","Scale of the mesh"),graph.scale);
			graph.scale = (graph.scale < 0.01F && graph.scale > -0.01F) ? (graph.scale >= 0 ? 0.01F : -0.01F) : graph.scale;
			
			graph.accurateNearestNode = EditorGUILayout.Toggle (new GUIContent ("Accurate Nearest Node Queries","More accurate nearest node queries. See docs for more info"),graph.accurateNearestNode);
		}
        public override void Execute()
        {
            if (AstarPath.active.graphs.Length <= GraphIndex)
            { return; }

            LocatedGraph = AstarPath.active.graphs[GraphIndex];
        }
		public override void OnInspectorGUI (NavGraph target) {
			var graph = target as LayerGridGraph;

			base.OnInspectorGUI(target);

			if (graph.neighbours != NumNeighbours.Four) {
				Debug.Log("Note: Only 4 neighbours per grid node is allowed in this graph type");
			}
		}
		public override void OnInspectorGUI (NavGraph target) {
			var graph = target as NavMeshGraph;

			graph.sourceMesh = ObjectField ("Source Mesh", graph.sourceMesh, typeof(Mesh), false) as Mesh;

			graph.offset = EditorGUILayout.Vector3Field ("Offset",graph.offset);

			graph.rotation = EditorGUILayout.Vector3Field ("Rotation",graph.rotation);

			graph.scale = EditorGUILayout.FloatField (new GUIContent ("Scale","Scale of the mesh"),graph.scale);
			graph.scale = (graph.scale < 0.01F && graph.scale > -0.01F) ? (graph.scale >= 0 ? 0.01F : -0.01F) : graph.scale;

			graph.accurateNearestNode = EditorGUILayout.Toggle (new GUIContent ("Accurate Nearest Node Queries","More accurate nearest node queries. See docs for more info"),graph.accurateNearestNode);
		}
        public override void OnEnter()
        {
            var mo = graph.Value as FsmNavGraph;
            if(mo.Value == null)
            {
                Finish();
                return;
            } // it would continue for a frame without return

            g = FsmConverter.GetNavGraph(graph);

            DoStuff();

            if (!everyFrame.Value)
            { Finish(); }
        }
示例#8
0
        public override void OnInspectorGUI(NavGraph target)
        {
            var graph = target as PointGraph;

            graph.root = ObjectField (new GUIContent ("Root","All childs of this object will be used as nodes, if it is not set, a tag search will be used instead (see below)"),graph.root,typeof(Transform),true) as Transform;

            graph.recursive = EditorGUILayout.Toggle (new GUIContent ("Recursive","Should childs of the childs in the root GameObject be searched"),graph.recursive);
            graph.searchTag = EditorGUILayout.TagField (new GUIContent ("Tag","If root is not set, all objects with this tag will be used as nodes"),graph.searchTag);

            if (graph.root != null) {
                EditorGUILayout.HelpBox ("All childs "+(graph.recursive ? "and sub-childs ":"") +"of 'root' will be used as nodes\nSet root to null to use a tag search instead", MessageType.None);
            } else {
                EditorGUILayout.HelpBox ("All object with the tag '"+graph.searchTag+"' will be used as nodes"+(graph.searchTag == "Untagged" ? "\nNote: the tag 'Untagged' cannot be used" : ""), MessageType.None);
            }

            graph.maxDistance = EditorGUILayout.FloatField (new GUIContent ("Max Distance","The max distance in world space for a connection to be valid. A zero counts as infinity"),graph.maxDistance);

            graph.limits = EditorGUILayout.Vector3Field ("Max Distance (axis aligned)",graph.limits);

            graph.raycast = EditorGUILayout.Toggle (new GUIContent ("Raycast","Use raycasting to check if connections are valid between each pair of nodes"),graph.raycast);

            if ( graph.raycast ) {
                EditorGUI.indentLevel++;

                graph.use2DPhysics = EditorGUILayout.Toggle (new GUIContent ("Use 2D Physics", "If enabled, all raycasts will use the Unity 2D Physics API instead of the 3D one."), graph.use2DPhysics);
             	graph.thickRaycast = EditorGUILayout.Toggle (new GUIContent ("Thick Raycast","A thick raycast checks along a thick line with radius instead of just along a line"),graph.thickRaycast);

                if ( graph.thickRaycast ) {
                    EditorGUI.indentLevel++;
             		graph.thickRaycastRadius = EditorGUILayout.FloatField (new GUIContent ("Raycast Radius","The radius in world units for the thick raycast"),graph.thickRaycastRadius);
             		EditorGUI.indentLevel--;
                }

                graph.mask = EditorGUILayoutx.LayerMaskField ("Mask",graph.mask);
                EditorGUI.indentLevel--;
            }

            graph.optimizeForSparseGraph = EditorGUILayout.Toggle (new GUIContent ("Optimize For Sparse Graph","Check online documentation for more information."),graph.optimizeForSparseGraph);

            if ( graph.optimizeForSparseGraph ) {
                EditorGUI.indentLevel++;

                graph.optimizeFor2D = EditorGUILayout.Toggle (new GUIContent ("Optimize For XZ Plane","Check online documentation for more information."),graph.optimizeFor2D);

                EditorGUI.indentLevel--;
            }
        }
		public override void OnInspectorGUI (NavGraph target) {
			var graph = target as GridGraph;

			DrawFirstSection(graph);
			Separator();
			DrawMiddleSection(graph);
			Separator();
			DrawCollisionEditor(graph.collision);

			if (graph.collision.use2D) {
				if (Mathf.Abs(Vector3.Dot(Vector3.forward, Quaternion.Euler(graph.rotation) * Vector3.up)) < 0.9f) {
					EditorGUILayout.HelpBox("When using 2D it is recommended to rotate the graph so that it aligns with the 2D plane.", MessageType.Warning);
				}
			}

			Separator();
			DrawLastSection(graph);
		}
		public override void OnInspectorGUI (NavGraph target) {
			
			LayerGridGraph graph = target as LayerGridGraph;
			
			graph.mergeSpanRange = EditorGUILayout.FloatField ("Merge Span Range",graph.mergeSpanRange);
			graph.characterHeight = EditorGUILayout.FloatField ("Character Height",graph.characterHeight);
			graph.maxClimb = Mathf.Clamp (EditorGUILayout.FloatField ("Max climb",graph.maxClimb),0,graph.characterHeight);
			
			graph.neighbours = NumNeighbours.Four;
			textureVisible = false;
			base.OnInspectorGUI (target);
			
			if (graph.neighbours != NumNeighbours.Four) {
				Debug.Log ("Note: Only 4 neighbours per grid node is allowed in this graph type");
			}
			
			if (graph.collision.thickRaycast)
				HelpBox ("Note: Thick raycast cannot be used with this graph type");
		}
示例#11
0
        /** Adds a graph of type \a type to the #graphs array */
        public NavGraph AddGraph(string type)
        {
            NavGraph graph = null;

            for (int i = 0; i < graphTypes.Length; i++)
            {
                if (graphTypes[i].Name == type)
                {
                    graph = CreateGraph(graphTypes[i]);
                }
            }

            if (graph == null)
            {
                Debug.LogError("No NavGraph of type '" + type + "' could be found");
                return(null);
            }

            AddGraph(graph);

            return(graph);
        }
        public Vector3 GetClampedPoint(Vector3 from, Vector3 to, GraphNode hint)
        {
            //float minDistance = Mathf.Infinity;
            Vector3 minPoint = to;

            if (useRaycasting)
            {
                RaycastHit hit;
                if (Physics.Linecast(from, to, out hit, mask))
                {
                    minPoint = hit.point;
                    //minDistance = hit.distance;
                }
            }

            if (useGraphRaycasting && hint != null)
            {
                NavGraph graph = AstarData.GetGraph(hint);

                if (graph != null)
                {
                    IRaycastableGraph rayGraph = graph as IRaycastableGraph;

                    if (rayGraph != null)
                    {
                        GraphHitInfo hit;

                        if (rayGraph.Linecast(from, minPoint, hint, out hit))
                        {
                            //if ((hit.point-from).magnitude < minDistance) {
                            minPoint = hit.point;
                            //}
                        }
                    }
                }
            }

            return(minPoint);
        }
        public override void OnInspectorGUI(NavGraph target)
        {
            LayerGridGraph graph = target as LayerGridGraph;

            graph.mergeSpanRange  = EditorGUILayout.FloatField("Merge Span Range", graph.mergeSpanRange);
            graph.characterHeight = EditorGUILayout.FloatField("Character Height", graph.characterHeight);
            graph.maxClimb        = Mathf.Clamp(EditorGUILayout.FloatField("Max climb", graph.maxClimb), 0, graph.characterHeight);

            graph.neighbours = NumNeighbours.Four;
            textureVisible   = false;
            base.OnInspectorGUI(target);

            if (graph.neighbours != NumNeighbours.Four)
            {
                Debug.Log("Note: Only 4 neighbours per grid node is allowed in this graph type");
            }

            if (graph.collision.thickRaycast)
            {
                HelpBox("Note: Thick raycast cannot be used with this graph type");
            }
        }
        /** Adds the specified graph to the #graphs array */
        public void AddGraph(NavGraph graph)
        {
            // Make sure to not interfere with pathfinding
            AstarPath.active.BlockUntilPathQueueBlocked();

            // Try to fill in an empty position
            bool foundEmpty = false;

            for (int i = 0; i < graphs.Length; i++)
            {
                if (graphs[i] == null)
                {
                    graphs[i]        = graph;
                    graph.graphIndex = (uint)i;
                    foundEmpty       = true;
                    break;
                }
            }

            if (!foundEmpty)
            {
                if (graphs != null && graphs.Length >= GraphNode.MaxGraphIndex)
                {
                    throw new System.Exception("Graph Count Limit Reached. You cannot have more than " + GraphNode.MaxGraphIndex +
                                               " graphs. Some compiler directives can change this limit, e.g ASTAR_MORE_AREAS, look under the " +
                                               "'Optimizations' tab in the A* Inspector");
                }

                // Add a new entry to the list
                var ls = new List <NavGraph>(graphs ?? new NavGraph[0]);
                ls.Add(graph);
                graphs           = ls.ToArray();
                graph.graphIndex = (uint)(graphs.Length - 1);
            }

            UpdateShortcuts();
            graph.active = active;
            graph.Awake();
        }
示例#15
0
        /** Adds a graph of type \a type to the #graphs array */
        public NavGraph AddGraph(System.Type type)
        {
            NavGraph graph = null;

            for (int i = 0; i < graphTypes.Length; i++)
            {
                if (System.Type.Equals(graphTypes[i], type))
                {
                    graph = CreateGraph(graphTypes[i]);
                }
            }

            if (graph == null)
            {
                Debug.LogError("No NavGraph of type '" + type + "' could be found, " + graphTypes.Length + " graph types are avaliable");
                return(null);
            }

            AddGraph(graph);

            return(graph);
        }
示例#16
0
        /// <summary>Adds the specified graph to the <see cref="graphs"/> array</summary>
        void AddGraph(NavGraph graph)
        {
            // Make sure to not interfere with pathfinding
            var graphLock = AssertSafe(true);

            // Try to fill in an empty position
            bool foundEmpty = false;

            for (int i = 0; i < graphs.Length; i++)
            {
                if (graphs[i] == null)
                {
                    graphs[i]        = graph;
                    graph.graphIndex = (uint)i;
                    foundEmpty       = true;
                    break;
                }
            }

            if (!foundEmpty)
            {
                if (graphs != null && graphs.Length >= GraphNode.MaxGraphIndex)
                {
                    throw new System.Exception("Graph Count Limit Reached. You cannot have more than " +
                                               GraphNode.MaxGraphIndex + " graphs.");
                }

                // Add a new entry to the list
                var graphList = new List <NavGraph>(graphs ?? new NavGraph[0]);
                graphList.Add(graph);
                graphs           = graphList.ToArray();
                graph.graphIndex = (uint)(graphs.Length - 1);
            }

            UpdateShortcuts();
            graph.active = active;
            graphLock.Release();
        }
示例#17
0
        /** Removes the specified graph from the #graphs array and Destroys it in a safe manner.
         * To avoid changing graph indices for the other graphs, the graph is simply nulled in the array instead
         * of actually removing it from the array.
         * The empty position will be reused if a new graph is added.
         *
         * \returns True if the graph was sucessfully removed (i.e it did exist in the #graphs array). False otherwise.
         *
         * \version Changed in 3.2.5 to call SafeOnDestroy before removing
         * and nulling it in the array instead of removing the element completely in the #graphs array.
         */
        public bool RemoveGraph(NavGraph graph)
        {
            // Make sure all graph updates and other callbacks are done
            active.FlushWorkItemsInternal(false);

            // Make sure the pathfinding threads are stopped
            // If we don't wait until pathfinding that is potentially running on
            // this graph right now we could end up with NullReferenceExceptions
            active.BlockUntilPathQueueBlocked();

            graph.OnDestroy();

            int i = System.Array.IndexOf(graphs, graph);

            if (i == -1)
            {
                return(false);
            }

            graphs[i] = null;
            UpdateShortcuts();
            return(true);
        }
示例#18
0
        /** Removes the specified graph from the #graphs array and Destroys it in a safe manner.
         * To avoid changing graph indices for the other graphs, the graph is simply nulled in the array instead
         * of actually removing it from the array.
         * The empty position will be reused if a new graph is added.
         *
         * \returns True if the graph was sucessfully removed (i.e it did exist in the #graphs array). False otherwise.
         *
         * \see NavGraph.SafeOnDestroy
         *
         * \version Changed in 3.2.5 to call SafeOnDestroy before removing
         * and nulling it in the array instead of removing the element completely in the #graphs array.
         *
         */
        public bool RemoveGraph(NavGraph graph)
        {
            //Safe OnDestroy is called since there is a risk that the pathfinding is searching through the graph right now,
            //and if we don't wait until the search has completed we could end up with evil NullReferenceExceptions
            graph.SafeOnDestroy();

            int i = 0;

            for (; i < graphs.Length; i++)
            {
                if (graphs[i] == graph)
                {
                    break;
                }
            }
            if (i == graphs.Length)
            {
                return(false);
            }

            graphs[i] = null;
            return(true);
        }
示例#19
0
		/** Removes the specified graph from the #graphs array and Destroys it in a safe manner.
		 * To avoid changing graph indices for the other graphs, the graph is simply nulled in the array instead
		 * of actually removing it from the array.
		 * The empty position will be reused if a new graph is added.
		 *
		 * \returns True if the graph was sucessfully removed (i.e it did exist in the #graphs array). False otherwise.
		 *
		 *
		 * \version Changed in 3.2.5 to call SafeOnDestroy before removing
		 * and nulling it in the array instead of removing the element completely in the #graphs array.
		 *
		 */
		public bool RemoveGraph (NavGraph graph) {
			// Make sure all graph updates and other callbacks are done
			active.FlushWorkItems(false, true);

			// Make sure the pathfinding threads are stopped
			active.BlockUntilPathQueueBlocked();

			// //Safe OnDestroy is called since there is a risk that the pathfinding is searching through the graph right now,
			// //and if we don't wait until the search has completed we could end up with evil NullReferenceExceptions
			graph.OnDestroy();

			int i = System.Array.IndexOf(graphs, graph);

			if (i == -1) {
				return false;
			}

			graphs[i] = null;

			UpdateShortcuts();

			return true;
		}
示例#20
0
        public override void OnInspectorGUI(NavGraph target)
        {
            var graph = target as GridGraph;

            DrawFirstSection(graph);
            Separator();
            DrawMiddleSection(graph);
            Separator();
            DrawCollisionEditor(graph.collision);

            if (graph.collision.use2D)
            {
                if (Mathf.Abs(Vector3.Dot(Vector3.forward, Quaternion.Euler(graph.rotation) * Vector3.up)) < 0.9f)
                {
                    EditorGUILayout.HelpBox(
                        "When using 2D physics it is recommended to rotate the graph so that it aligns with the 2D plane.",
                        MessageType.Warning);
                }
            }

            Separator();
            DrawLastSection(graph);
        }
示例#21
0
        public void InitializeSerializeNodes()
        {
            if (mask == SMask.SaveNodes)
            {
                AstarData data = active.astarData;

                for (int g = 0; g < data.graphs.Length; g++)
                {
                    NavGraph graph = data.graphs[g];

                    if (graph.nodes == null)
                    {
                        continue;
                    }

                    for (int i = 0; i < graph.nodes.Length; i++)
                    {
                        graph.nodes[i].h = g;
                        graph.nodes[i].g = i;
                    }
                }
            }
        }
示例#22
0
        /** Removes the specified graph from the #graphs array and Destroys it in a safe manner.
         * To avoid changing graph indices for the other graphs, the graph is simply nulled in the array instead
         * of actually removing it from the array.
         * The empty position will be reused if a new graph is added.
         *
         * \returns True if the graph was sucessfully removed (i.e it did exist in the #graphs array). False otherwise.
         *
         * \version Changed in 3.2.5 to call SafeOnDestroy before removing
         * and nulling it in the array instead of removing the element completely in the #graphs array.
         */
        public bool RemoveGraph(NavGraph graph)
        {
            // Make sure the pathfinding threads are stopped
            // If we don't wait until pathfinding that is potentially running on
            // this graph right now we could end up with NullReferenceExceptions
            var graphLock = active.PausePathfinding();

            // Make sure all graph updates and other callbacks are done
            active.FlushWorkItems();

            graph.OnDestroy();

            int i = System.Array.IndexOf(graphs, graph);

            if (i != -1)
            {
                graphs[i] = null;
            }

            UpdateShortcuts();
            graphLock.Release();
            return(i != -1);
        }
        /// <summary>Schedules graph updates internally</summary>
        private void QueueGraphUpdatesInternal()
        {
            while (graphUpdateQueue.Count > 0)
            {
                GraphUpdateObject ob = graphUpdateQueue.Dequeue();

                foreach (IUpdatableGraph g in astar.data.GetUpdateableGraphs())
                {
                    NavGraph gr = g as NavGraph;
                    if (ob.nnConstraint == null || ob.nnConstraint.SuitableGraph(astar.data.GetGraphIndex(gr), gr))
                    {
                        var guo = new GUOSingle();
                        guo.order = GraphUpdateOrder.GraphUpdate;
                        guo.obj   = ob;
                        guo.graph = g;
                        graphUpdateQueueRegular.Enqueue(guo);
                    }
                }
            }

            GraphModifier.TriggerEvent(GraphModifier.EventType.PreUpdate);
            anyGraphUpdateInProgress = true;
        }
        // Token: 0x060006F5 RID: 1781 RVA: 0x000444A0 File Offset: 0x000428A0
        public Vector3 GetClampedPoint(Vector3 from, Vector3 to, GraphNode hint)
        {
            Vector3    vector = to;
            RaycastHit raycastHit;

            if (this.useRaycasting && Physics.Linecast(from, to, out raycastHit, this.mask))
            {
                vector = raycastHit.point;
            }
            if (this.useGraphRaycasting && hint != null)
            {
                NavGraph graph = AstarData.GetGraph(hint);
                if (graph != null)
                {
                    IRaycastableGraph raycastableGraph = graph as IRaycastableGraph;
                    GraphHitInfo      graphHitInfo;
                    if (raycastableGraph != null && raycastableGraph.Linecast(from, vector, hint, out graphHitInfo))
                    {
                        vector = graphHitInfo.point;
                    }
                }
            }
            return(vector);
        }
        //public GameObject meshRenderer;

        public override void OnInspectorGUI(NavGraph target)
        {
            NavMeshGraph graph = target as NavMeshGraph;

            /*
             #if UNITY_3_3
             *              graph.sourceMesh = EditorGUILayout.ObjectField ("Source Mesh",graph.sourceMesh,typeof(Mesh)) as Mesh;
             #else
             *              graph.sourceMesh = EditorGUILayout.ObjectField ("Source Mesh",graph.sourceMesh,typeof(Mesh), true) as Mesh;
             #endif
             */
            graph.sourceMesh = ObjectField("Source Mesh", graph.sourceMesh, typeof(Mesh), false) as Mesh;

        #if UNITY_LE_4_3
            EditorGUIUtility.LookLikeControls();
            EditorGUILayoutx.BeginIndent();
        #endif
            graph.offset = EditorGUILayout.Vector3Field("Offset", graph.offset);

        #if UNITY_LE_4_3
            EditorGUILayoutx.EndIndent();

            EditorGUILayoutx.BeginIndent();
        #endif
            graph.rotation = EditorGUILayout.Vector3Field("Rotation", graph.rotation);

        #if UNITY_LE_4_3
            EditorGUILayoutx.EndIndent();
            EditorGUIUtility.LookLikeInspector();
        #endif

            graph.scale = EditorGUILayout.FloatField(new GUIContent("Scale", "Scale of the mesh"), graph.scale);
            graph.scale = (graph.scale <0.01F && graph.scale> -0.01F) ? (graph.scale >= 0 ? 0.01F : -0.01F) : graph.scale;

            graph.accurateNearestNode = EditorGUILayout.Toggle(new GUIContent("Accurate Nearest Node Queries", "More accurate nearest node queries. See docs for more info"), graph.accurateNearestNode);
        }
        /// <summary>Schedules graph updates internally</summary>
        void QueueGraphUpdatesInternal(IWorkItemContext context)
        {
            while (graphUpdateQueue.Count > 0)
            {
                GraphUpdateObject ob = graphUpdateQueue.Dequeue();

                foreach (IUpdatableGraph g in astar.data.GetUpdateableGraphs())
                {
                    NavGraph gr = g as NavGraph;
                    if (ob.nnConstraint == null || ob.nnConstraint.SuitableGraph(astar.data.GetGraphIndex(gr), gr))
                    {
                        var guo = new GUOSingle();
                        guo.order = GraphUpdateOrder.GraphUpdate;
                        guo.obj   = ob;
                        guo.graph = g;
                        graphUpdateQueueRegular.Enqueue(guo);
                        context.SetGraphDirty(gr);
                    }
                }
            }

            context.PreUpdate();
            anyGraphUpdateInProgress = true;
        }
        /** Schedules graph updates internally */
        void QueueGraphUpdatesInternal()
        {
            bool anyRequiresFloodFill = false;

            while (graphUpdateQueue.Count > 0)
            {
                GraphUpdateObject ob = graphUpdateQueue.Dequeue();

                if (ob.requiresFloodFill)
                {
                    anyRequiresFloodFill = true;
                }

                foreach (IUpdatableGraph g in astar.astarData.GetUpdateableGraphs())
                {
                    NavGraph gr = g as NavGraph;
                    if (ob.nnConstraint == null || ob.nnConstraint.SuitableGraph(astar.astarData.GetGraphIndex(gr), gr))
                    {
                        var guo = new GUOSingle();
                        guo.order = GraphUpdateOrder.GraphUpdate;
                        guo.obj   = ob;
                        guo.graph = g;
                        graphUpdateQueueRegular.Enqueue(guo);
                    }
                }
            }

            if (anyRequiresFloodFill)
            {
                var guo = new GUOSingle();
                guo.order = GraphUpdateOrder.FloodFill;
                graphUpdateQueueRegular.Enqueue(guo);
            }

            GraphModifier.TriggerEvent(GraphModifier.EventType.PreUpdate);
        }
示例#28
0
        /** Serializes the graph settings to JSON and returns the data */
        public byte[] Serialize(NavGraph graph)
        {
            System.Text.StringBuilder output = GetStringBuilder ();//new System.Text.StringBuilder();
            JsonWriter writer = new JsonWriter (output,writerSettings);
            writer.Write (graph);

            return encoding.GetBytes (output.ToString());
        }
示例#29
0
        /// <summary>
        /// Check if a straight path between v1 and v2 is valid.
        /// If both n1 and n2 are supplied it is assumed that the line goes from the center of n1 to the center of n2 and a more optimized graph linecast may be done.
        /// </summary>
        protected bool ValidateLine(GraphNode n1, GraphNode n2, Vector3 v1, Vector3 v2)
        {
            if (useRaycasting)
            {
                // Use raycasting to check if a straight path between v1 and v2 is valid
                if (use2DPhysics)
                {
                    if (thickRaycast && thickRaycastRadius > 0 && Physics2D.CircleCast(v1 + raycastOffset, thickRaycastRadius, v2 - v1, (v2 - v1).magnitude, mask))
                    {
                        return(false);
                    }

                    if (Physics2D.Linecast(v1 + raycastOffset, v2 + raycastOffset, mask))
                    {
                        return(false);
                    }
                }
                else
                {
                    // Perform a thick raycast (if enabled)
                    if (thickRaycast && thickRaycastRadius > 0 && Physics.SphereCast(new Ray(v1 + raycastOffset, v2 - v1), thickRaycastRadius, (v2 - v1).magnitude, mask))
                    {
                        return(false);
                    }

                    // Perform a normal raycast
                    // This is done even if a thick raycast is also done because thick raycasts do not report collisions for
                    // colliders that overlapped the (imaginary) sphere at the origin of the thick raycast.
                    // If this raycast was not done then some obstacles could be missed.
                    if (Physics.Linecast(v1 + raycastOffset, v2 + raycastOffset, mask))
                    {
                        return(false);
                    }
                }
            }

            if (useGraphRaycasting)
            {
                bool betweenNodeCenters = n1 != null && n2 != null;
                if (n1 == null)
                {
                    n1 = AstarPath.active.GetNearest(v1).node;
                }
                if (n2 == null)
                {
                    n2 = AstarPath.active.GetNearest(v2).node;
                }

                if (n1 != null && n2 != null)
                {
                    // Use graph raycasting to check if a straight path between v1 and v2 is valid
                    NavGraph graph  = n1.Graph;
                    NavGraph graph2 = n2.Graph;

                    if (graph != graph2)
                    {
                        return(false);
                    }

                    var       rayGraph = graph as IRaycastableGraph;
                    GridGraph gg       = graph as GridGraph;
                    if (betweenNodeCenters && gg != null)
                    {
                        // If the linecast is exactly between the centers of two nodes on a grid graph then a more optimized linecast can be used.
                        // This method is also more stable when raycasting along a diagonal when the line just touches an obstacle.
                        // The normal linecast method may or may not detect that as a hit depending on floating point errors
                        // however this method never detect it as an obstacle (and that is very good for this component as it improves the simplification).
                        return(!gg.Linecast(n1 as GridNodeBase, n2 as GridNodeBase));
                    }
                    else
                    if (rayGraph != null)
                    {
                        return(!rayGraph.Linecast(v1, v2, n1));
                    }
                }
            }
            return(true);
        }
示例#30
0
 /// <summary>Override to implement graph inspectors</summary>
 public virtual void OnInspectorGUI(NavGraph target)
 {
 }
示例#31
0
        /** Called to serialize a graphs settings. \note Before calling this, setting #sPrefix to something unique for the graph is a good idea to avoid collisions in variable names */
        public void SerializeSettings(NavGraph graph, AstarPath active)
        {
            ISerializableGraph serializeGraph = graph as ISerializableGraph;

            if (serializeGraph == null) {
                Debug.LogError ("The graph specified is not serializable, the graph is of type "+graph.GetType());
                return;
            }

            serializeGraph.SerializeSettings (this);
        }
示例#32
0
        public void SerializeEditorSettings(NavGraph graph, ISerializableGraphEditor editor, AstarPath active)
        {
            if (editor == null) {
                Debug.LogError ("The editor specified is Null");
                return;
            }

            //The script will return to this value and write the number of variables serialized with the simple serializer
            positionAtCounter = (int)writerStream.BaseStream.Position;
            writerStream.Write (0);//This will be overwritten
            counter = 0;

            editor.SerializeSettings (graph,this);
        }
示例#33
0
		/** Returns the node at \a graphs[graphIndex].nodes[nodeIndex]. The graphIndex refers to the specified graphs array.\n
		 * All kinds of error checking is done to make sure no exceptions are thrown */
		public GraphNode GetNode (int graphIndex, int nodeIndex, NavGraph[] graphs) {
			throw new System.NotImplementedException ();
			
			/*
			if (graphs == null) {
				return null;
			}
			
			if (graphIndex < 0 || graphIndex >= graphs.Length) {
				Debug.LogError ("Graph index is out of range"+graphIndex+ " [0-"+(graphs.Length-1)+"]");
				return null;
			}
			
			NavGraph graph = graphs[graphIndex];
			
			if (graph.nodes == null) {
				return null;
			}
			
			if (nodeIndex < 0 || nodeIndex >= graph.nodes.Length) {
				Debug.LogError ("Node index is out of range : "+nodeIndex+ " [0-"+(graph.nodes.Length-1)+"]"+" (graph "+graphIndex+")");
				return null;
			}
			
			return graph.nodes[nodeIndex];*/
		}
		/** Returns whether or not the graph conforms to this NNConstraint's rules.
		  * Note that only the first 31 graphs are considered using this function.
		  * If the graphMask has bit 31 set (i.e the last graph possible to fit in the mask), all graphs
		  * above index 31 will also be considered suitable.
		  */
		public virtual bool SuitableGraph (int graphIndex, NavGraph graph) {
			return ((graphMask >> graphIndex) & 1) != 0;
		}
示例#35
0
        public override void OnSceneGUI(NavGraph target)
        {
            var graph = target as RecastGraph;

            Handles.matrix = Matrix4x4.identity;
            Handles.color  = AstarColor.BoundsHandles;
            Handles.CapFunction cap = Handles.CylinderHandleCap;

            var       center = graph.forcedBoundsCenter;
            Matrix4x4 matrix = Matrix4x4.TRS(center, Quaternion.Euler(graph.rotation), graph.forcedBoundsSize * 0.5f);

            if (Tools.current == Tool.Scale)
            {
                const float HandleScale = 0.1f;

                Vector3 mn = Vector3.zero;
                Vector3 mx = Vector3.zero;
                EditorGUI.BeginChangeCheck();
                for (int i = 0; i < handlePoints.Length; i++)
                {
                    var     ps = matrix.MultiplyPoint3x4(handlePoints[i]);
                    Vector3 p  = matrix.inverse.MultiplyPoint3x4(Handles.Slider(ps, ps - center, HandleScale * HandleUtility.GetHandleSize(ps), cap, 0));

                    if (i == 0)
                    {
                        mn = mx = p;
                    }
                    else
                    {
                        mn = Vector3.Min(mn, p);
                        mx = Vector3.Max(mx, p);
                    }
                }

                if (EditorGUI.EndChangeCheck())
                {
                    graph.forcedBoundsCenter = matrix.MultiplyPoint3x4((mn + mx) * 0.5f);
                    graph.forcedBoundsSize   = Vector3.Scale(graph.forcedBoundsSize, (mx - mn) * 0.5f);
                }
            }
            else if (Tools.current == Tool.Move)
            {
                EditorGUI.BeginChangeCheck();
                center = Handles.PositionHandle(center, Tools.pivotRotation == PivotRotation.Global ? Quaternion.identity : Quaternion.Euler(graph.rotation));

                if (EditorGUI.EndChangeCheck() && Tools.viewTool != ViewTool.Orbit)
                {
                    graph.forcedBoundsCenter = center;
                }
            }
            else if (Tools.current == Tool.Rotate)
            {
                EditorGUI.BeginChangeCheck();
                var rot = Handles.RotationHandle(Quaternion.Euler(graph.rotation), graph.forcedBoundsCenter);

                if (EditorGUI.EndChangeCheck() && Tools.viewTool != ViewTool.Orbit)
                {
                    graph.rotation = rot.eulerAngles;
                }
            }
        }
示例#36
0
 /** Returns whether or not the graph conforms to this NNConstraint's rules.
  */
 public virtual bool SuitableGraph(int graphIndex, NavGraph graph)
 {
     return(((graphMask >> graphIndex) & 1) != 0);
 }
示例#37
0
		public virtual Vector3[] Apply (GraphNode[] path, Vector3 start, Vector3 end, int startIndex, int endIndex, NavGraph graph) {
			
			var p = new Vector3[endIndex-startIndex];
			
			for (var i=startIndex;i< endIndex;i++) {
				p[i-startIndex] = (Vector3)path[i].position;
			}
			
			return p;
		}
        public override void OnSceneGUI(NavGraph target)
        {
            Event e = Event.current;

            var graph = target as GridGraph;

            graph.UpdateTransform();
            var currentTransform = graph.transform * Matrix4x4.Scale(new Vector3(graph.width, 1, graph.depth));

            if (e.type == EventType.MouseDown)
            {
                isMouseDown = true;
            }
            else if (e.type == EventType.MouseUp)
            {
                isMouseDown = false;
            }

            if (!isMouseDown)
            {
                savedTransform  = currentTransform;
                savedDimensions = new Vector2(graph.width, graph.depth);
                savedNodeSize   = graph.nodeSize;
            }

            Handles.matrix = Matrix4x4.identity;
            Handles.color  = AstarColor.BoundsHandles;
#if UNITY_5_5_OR_NEWER
            Handles.CapFunction cap = Handles.CylinderHandleCap;
#else
            Handles.DrawCapFunction cap = Handles.CylinderCap;
#endif

            var center = currentTransform.Transform(new Vector3(0.5f, 0, 0.5f));
            if (Tools.current == Tool.Scale)
            {
                const float HandleScale = 0.1f;

                Vector3 mn = Vector3.zero;
                Vector3 mx = Vector3.zero;
                EditorGUI.BeginChangeCheck();
                for (int i = 0; i < handlePoints.Length; i++)
                {
                    var     ps = currentTransform.Transform(handlePoints[i]);
                    Vector3 p  = savedTransform.InverseTransform(Handles.Slider(ps, ps - center, HandleScale * HandleUtility.GetHandleSize(ps), cap, 0));

                    // Snap to increments of whole nodes
                    p.x = Mathf.Round(p.x * savedDimensions.x) / savedDimensions.x;
                    p.z = Mathf.Round(p.z * savedDimensions.y) / savedDimensions.y;

                    if (i == 0)
                    {
                        mn = mx = p;
                    }
                    else
                    {
                        mn = Vector3.Min(mn, p);
                        mx = Vector3.Max(mx, p);
                    }
                }

                if (EditorGUI.EndChangeCheck())
                {
                    graph.center        = savedTransform.Transform((mn + mx) * 0.5f);
                    graph.unclampedSize = Vector2.Scale(new Vector2(mx.x - mn.x, mx.z - mn.z), savedDimensions) * savedNodeSize;
                }
            }
            else if (Tools.current == Tool.Move)
            {
                EditorGUI.BeginChangeCheck();
                center = Handles.PositionHandle(graph.center, Tools.pivotRotation == PivotRotation.Global ? Quaternion.identity : Quaternion.Euler(graph.rotation));

                if (EditorGUI.EndChangeCheck() && Tools.viewTool != ViewTool.Orbit)
                {
                    graph.center = center;
                }
            }
            else if (Tools.current == Tool.Rotate)
            {
                EditorGUI.BeginChangeCheck();
                var rot = Handles.RotationHandle(Quaternion.Euler(graph.rotation), graph.center);

                if (EditorGUI.EndChangeCheck() && Tools.viewTool != ViewTool.Orbit)
                {
                    graph.rotation = rot.eulerAngles;
                }
            }

            Handles.matrix = Matrix4x4.identity;
        }
示例#39
0
		/** This performs a linear search through all polygons returning the closest one.
		  * This will fill the NNInfo with .node for the closest node not necessarily complying with the NNConstraint, and .constrainedNode with the closest node
		  * complying with the NNConstraint.
		  * \see GetNearestForce(Node[],Int3[],Vector3,NNConstraint,bool)
		  */
		public static NNInfo GetNearestForceBoth (NavGraph graph, INavmeshHolder navmesh, Vector3 position, NNConstraint constraint, bool accurateNearestNode) {
			Int3 pos = (Int3)position;
			
			float minDist = -1;
			GraphNode minNode = null;
			
			float minConstDist = -1;
			GraphNode minConstNode = null;
			
			float maxDistSqr = constraint.constrainDistance ? AstarPath.active.maxNearestNodeDistanceSqr : float.PositiveInfinity;
			
			GraphNodeDelegateCancelable del = delegate (GraphNode _node) {
				TriangleMeshNode node = _node as TriangleMeshNode;
				
				if (accurateNearestNode) {
					
					Vector3 closest = node.ClosestPointOnNode (position);
					float dist = ((Vector3)pos-closest).sqrMagnitude;
					
					if (minNode == null || dist < minDist) {
						minDist = dist;
						minNode = node;
					}
					
					if (dist < maxDistSqr && constraint.Suitable (node)) {
						if (minConstNode == null || dist < minConstDist) {
							minConstDist = dist;
							minConstNode = node;
						}
					}
					
				} else {
					
					if (!node.ContainsPoint ((Int3)position)) {
						
						float dist = (node.position-pos).sqrMagnitude;
						if (minNode == null || dist < minDist) {
							minDist = dist;
							minNode = node;
						}
						
						if (dist < maxDistSqr && constraint.Suitable (node)) {
							if (minConstNode == null || dist < minConstDist) {
								minConstDist = dist;
								minConstNode = node;
							}
						}
						
					} else {
					
#if ASTARDEBUG
						Debug.DrawLine ((Vector3)vertices[node.v0],(Vector3)vertices[node.v1],Color.blue);
						Debug.DrawLine ((Vector3)vertices[node.v1],(Vector3)vertices[node.v2],Color.blue);
						Debug.DrawLine ((Vector3)vertices[node.v2],(Vector3)vertices[node.v0],Color.blue);
#endif
						
						int dist = AstarMath.Abs (node.position.y-pos.y);
						
						if (minNode == null || dist < minDist) {
							minDist = dist;
							minNode = node;
						}
						
						if (dist < maxDistSqr && constraint.Suitable (node)) {
							if (minConstNode == null || dist < minConstDist) {
								minConstDist = dist;
								minConstNode = node;
							}
						}
					}
				}
				return true;
			};
			
			graph.GetNodes (del);
			
			NNInfo nninfo = new NNInfo (minNode);
			
			//Find the point closest to the nearest triangle
				
			if (nninfo.node != null) {
				TriangleMeshNode node = nninfo.node as TriangleMeshNode;//minNode2 as MeshNode;
				
				Vector3 clP = node.ClosestPointOnNode (position);
				
				nninfo.clampedPosition = clP;
			}
			
			nninfo.constrainedNode = minConstNode;
			if (nninfo.constrainedNode != null) {
				TriangleMeshNode node = nninfo.constrainedNode as TriangleMeshNode;//minNode2 as MeshNode;
				
				Vector3 clP = node.ClosestPointOnNode (position);
				
				nninfo.constClampedPosition = clP;
			}
			
			return nninfo;
		}
示例#40
0
        public static NNInfo GetNearestForceBoth(NavGraph graph, INavmeshHolder navmesh, Vector3 position, NNConstraint constraint, bool accurateNearestNode)
        {
            Int3      pos                   = (Int3)position;
            float     minDist               = -1f;
            GraphNode minNode               = null;
            float     minConstDist          = -1f;
            GraphNode minConstNode          = null;
            float     maxDistSqr            = (!constraint.constrainDistance) ? float.PositiveInfinity : AstarPath.active.maxNearestNodeDistanceSqr;
            GraphNodeDelegateCancelable del = delegate(GraphNode _node)
            {
                TriangleMeshNode triangleMeshNode3 = _node as TriangleMeshNode;
                if (accurateNearestNode)
                {
                    Vector3 b            = triangleMeshNode3.ClosestPointOnNode(position);
                    float   sqrMagnitude = ((Vector3)pos - b).sqrMagnitude;
                    if (minNode == null || sqrMagnitude < minDist)
                    {
                        minDist = sqrMagnitude;
                        minNode = triangleMeshNode3;
                    }
                    if (sqrMagnitude < maxDistSqr && constraint.Suitable(triangleMeshNode3) && (minConstNode == null || sqrMagnitude < minConstDist))
                    {
                        minConstDist = sqrMagnitude;
                        minConstNode = triangleMeshNode3;
                    }
                }
                else if (!triangleMeshNode3.ContainsPoint((Int3)position))
                {
                    float sqrMagnitude2 = (triangleMeshNode3.position - pos).sqrMagnitude;
                    if (minNode == null || sqrMagnitude2 < minDist)
                    {
                        minDist = sqrMagnitude2;
                        minNode = triangleMeshNode3;
                    }
                    if (sqrMagnitude2 < maxDistSqr && constraint.Suitable(triangleMeshNode3) && (minConstNode == null || sqrMagnitude2 < minConstDist))
                    {
                        minConstDist = sqrMagnitude2;
                        minConstNode = triangleMeshNode3;
                    }
                }
                else
                {
                    int num = AstarMath.Abs(triangleMeshNode3.position.y - pos.y);
                    if (minNode == null || (float)num < minDist)
                    {
                        minDist = (float)num;
                        minNode = triangleMeshNode3;
                    }
                    if ((float)num < maxDistSqr && constraint.Suitable(triangleMeshNode3) && (minConstNode == null || (float)num < minConstDist))
                    {
                        minConstDist = (float)num;
                        minConstNode = triangleMeshNode3;
                    }
                }
                return(true);
            };

            graph.GetNodes(del);
            NNInfo result = new NNInfo(minNode);

            if (result.node != null)
            {
                TriangleMeshNode triangleMeshNode = result.node as TriangleMeshNode;
                Vector3          clampedPosition  = triangleMeshNode.ClosestPointOnNode(position);
                result.clampedPosition = clampedPosition;
            }
            result.constrainedNode = minConstNode;
            if (result.constrainedNode != null)
            {
                TriangleMeshNode triangleMeshNode2    = result.constrainedNode as TriangleMeshNode;
                Vector3          constClampedPosition = triangleMeshNode2.ClosestPointOnNode(position);
                result.constClampedPosition = constClampedPosition;
            }
            return(result);
        }
示例#41
0
		/** Removes the specified graph from the #graphs array and Destroys it in a safe manner.
		 * To avoid changing graph indices for the other graphs, the graph is simply nulled in the array instead
		 * of actually removing it from the array.
		 * The empty position will be reused if a new graph is added.
		 * 
		 * \returns True if the graph was sucessfully removed (i.e it did exist in the #graphs array). False otherwise.
		 * 
		 * \see NavGraph.SafeOnDestroy
		 * 
		 * \version Changed in 3.2.5 to call SafeOnDestroy before removing
		 * and nulling it in the array instead of removing the element completely in the #graphs array.
		 * 
		 */
		public bool RemoveGraph (NavGraph graph) {
			
			//Safe OnDestroy is called since there is a risk that the pathfinding is searching through the graph right now,
			//and if we don't wait until the search has completed we could end up with evil NullReferenceExceptions
			graph.SafeOnDestroy ();
			
			int i=0;
			for (;i<graphs.Length;i++) if (graphs[i] == graph) break;
			if (i == graphs.Length) {
				return false;
			}
			
			graphs[i] = null;
			
			UpdateShortcuts ();
			
			return true;
		}
        // Token: 0x060027A4 RID: 10148 RVA: 0x001B33F8 File Offset: 0x001B15F8
        public static void GetPointsAroundPoint(Vector3 center, IRaycastableGraph g, List <Vector3> previousPoints, float radius, float clearanceRadius)
        {
            if (g == null)
            {
                throw new ArgumentNullException("g");
            }
            NavGraph navGraph = g as NavGraph;

            if (navGraph == null)
            {
                throw new ArgumentException("g is not a NavGraph");
            }
            NNInfoInternal nearestForce = navGraph.GetNearestForce(center, NNConstraint.Default);

            center = nearestForce.clampedPosition;
            if (nearestForce.node == null)
            {
                return;
            }
            radius           = Mathf.Max(radius, 1.4142f * clearanceRadius * Mathf.Sqrt((float)previousPoints.Count));
            clearanceRadius *= clearanceRadius;
            int i = 0;

            while (i < previousPoints.Count)
            {
                Vector3 vector    = previousPoints[i];
                float   magnitude = vector.magnitude;
                if (magnitude > 0f)
                {
                    vector /= magnitude;
                }
                float num = radius;
                vector *= num;
                int     num2 = 0;
                Vector3 vector2;
                for (;;)
                {
                    vector2 = center + vector;
                    GraphHitInfo graphHitInfo;
                    if (g.Linecast(center, vector2, nearestForce.node, out graphHitInfo))
                    {
                        if (graphHitInfo.point == Vector3.zero)
                        {
                            num2++;
                            if (num2 > 8)
                            {
                                goto Block_7;
                            }
                        }
                        else
                        {
                            vector2 = graphHitInfo.point;
                        }
                    }
                    bool flag = false;
                    for (float num3 = 0.1f; num3 <= 1f; num3 += 0.05f)
                    {
                        Vector3 vector3 = Vector3.Lerp(center, vector2, num3);
                        flag = true;
                        for (int j = 0; j < i; j++)
                        {
                            if ((previousPoints[j] - vector3).sqrMagnitude < clearanceRadius)
                            {
                                flag = false;
                                break;
                            }
                        }
                        if (flag || num2 > 8)
                        {
                            flag = true;
                            previousPoints[i] = vector3;
                            break;
                        }
                    }
                    if (flag)
                    {
                        break;
                    }
                    clearanceRadius *= 0.9f;
                    vector           = UnityEngine.Random.onUnitSphere * Mathf.Lerp(num, radius, (float)(num2 / 5));
                    vector.y         = 0f;
                    num2++;
                }
IL_19D:
                i++;
                continue;
Block_7:
                previousPoints[i] = vector2;
                goto IL_19D;
            }
        }
示例#43
0
		/** Gets the index of the NavGraph in the #graphs array */
		public int GetGraphIndex (NavGraph graph) {
			if (graph == null) throw new System.ArgumentNullException ("graph");
			
			if ( graphs != null ) {
				for (int i=0;i<graphs.Length;i++) {
					if (graph == graphs[i]) {
						return i;
					}
				}
			}
			Debug.LogError ("Graph doesn't exist");
			return -1;
		}
示例#44
0
        /** Deserializes one node from the stream into the specified graphs and to the specified graph index.
          * \astarpro */
        private void DeSerializeNode(Node node, NavGraph[] graphs, int graphIndex, BinaryReader stream)
        {
            //NavGraph graph = graphs[graphIndex];

            if (mask == SMask.SaveNodePositions) {
                node.position = new Int3(
                    stream.ReadInt32 (), //X
                    stream.ReadInt32 (), //Y
                    stream.ReadInt32 ()	 //Z
                );
            }

            if (mask != SMask.RunLengthEncoding) {
                node.penalty = (uint)stream.ReadInt32 ();
                node.flags = stream.ReadInt32 ();
            }

            if (mask == SMask.SaveNodeConnections) {

                if (tmpConnections == null) {
                    tmpConnections = new List<Node> ();
                    tmpConnectionCosts = new List<int> ();
                } else {
                    tmpConnections.Clear ();
                    tmpConnectionCosts.Clear ();
                }

                int numConn = (int)stream.ReadByte ();

                for (int i=0;i<numConn;i++) {

                    int nodeIndex = stream.ReadInt32 ();

                    //Graph index as in, which graph
                    int nodeGraphIndex = (nodeIndex >> 26) & 0x3F;

                    nodeIndex &= 0x3FFFFFF;

                    int cost = stream.ReadInt32 ();

                    bool containsLink = false;

                    if (nodeGraphIndex != graphIndex) {
                        containsLink = stream.ReadBoolean ();
                    }

                    if (graphRefGuids[graphIndex] != -1) {
                        Node other = active.astarData.GetNode (graphRefGuids[nodeGraphIndex],nodeIndex, graphs);

                        //Shouldn't really have to check for this, but just in case of corrupt serialization data
                        if (other != null) {
                            tmpConnections.Add (other);

                            if (mask == SMask.SaveNodeConnectionCosts) {
                                tmpConnectionCosts.Add (cost);
                            }

                            if (containsLink) {
                                other.AddConnection (node,cost);
                            }
                        }
                    }
                }

                node.connections = tmpConnections.ToArray ();

                if (mask == SMask.SaveNodeConnectionCosts) {
                    node.connectionCosts = tmpConnectionCosts.ToArray ();
                } else {
                    node.connectionCosts = new int[node.connections.Length];
                }
            }
        }
示例#45
0
        /** Serializes the nodes in the graph.
         * \astarpro */
        public void SerializeNodes(NavGraph graph, AstarPath active)
        {
            if (mask == SMask.SaveNodes) {

                ISerializableGraph serializeGraph = graph as ISerializableGraph;

                if (serializeGraph == null) {
                    Debug.LogError ("The graph specified is not serializable, the graph is of type "+graph.GetType());
                    return;
                }

                if (graph.nodes == null || graph.nodes.Length == 0) {
                    writerStream.Write (0);
                    //Debug.LogWarning ("No nodes to serialize");
                    return;
                }

                writerStream.Write (graph.nodes.Length);

                //writerStream.Write (savingToFile ? 753 : 1337);
                Debug.Log ("Stored nodes "+" "+writerStream.BaseStream.Position);

                SizeProfiler.Begin ("Graph specific nodes",writerStream);

                AddVariableAnchor ("DeserializeGraphNodes");
                serializeGraph.SerializeNodes (graph.nodes,this);

                SizeProfiler.End ("Graph specific nodes",writerStream);

                AddVariableAnchor ("DeserializeNodes");

                if (mask == SMask.RunLengthEncoding) {

                    SizeProfiler.Begin ("RLE Penalty",writerStream);
                    //Penalties
                    int lastValue = (int)graph.nodes[0].penalty;
                    int lastEntry = 0;

                    for (int i=1;i<graph.nodes.Length;i++) {
                        if (graph.nodes[i].penalty != lastValue || (i-lastEntry) >= byte.MaxValue-1) {
                            writerStream.Write ((byte)(i-lastEntry));
                            writerStream.Write (lastValue);
                            lastValue = (int)graph.nodes[i].penalty;
                            lastEntry = i;
                        }
                    }

                    writerStream.Write ((byte)(graph.nodes.Length-lastEntry));
                    writerStream.Write (lastValue);

                    SizeProfiler.Begin ("RLE Flags",writerStream);

                    //Flags
                    lastValue = graph.nodes[0].flags;
                    lastEntry = 0;

                    for (int i=1;i<graph.nodes.Length;i++) {
                        if (graph.nodes[i].flags != lastValue || (i-lastEntry) >= byte.MaxValue) {
                            writerStream.Write ((byte)(i-lastEntry));
                            writerStream.Write (lastValue);
                            lastValue = graph.nodes[i].flags;
                            lastEntry = i;
                        }
                    }
                    writerStream.Write ((byte)(graph.nodes.Length-lastEntry));
                    writerStream.Write (lastValue);

                    SizeProfiler.End ("RLE Flags",writerStream);
                }

                SizeProfiler.Begin ("Nodes, other",writerStream);

                for (int i=0;i<graph.nodes.Length;i++) {
                    SerializeNode (graph.nodes[i], writerStream);
                }

                SizeProfiler.End ("Nodes, other",writerStream);
            }
        }
示例#46
0
        /** Deserializes nodes in the graph. The deserialized nodes will be created using graph.CreateNodes (numberOfNodes).
         * \astarpro */
        public void DeserializeNodes(NavGraph graph, NavGraph[] graphs, int graphIndex, AstarPath active)
        {
            if (mask == SMask.SaveNodes) {

                ISerializableGraph serializeGraph = graph as ISerializableGraph;

                if (serializeGraph == null) {
                    Debug.LogError ("The graph specified is not serializable, the graph is of type "+graph.GetType());
                    return;
                }

                int numNodes = readerStream.ReadInt32 ();

                graph.nodes = serializeGraph.CreateNodes (numNodes);

                if (numNodes == 0) {
                    return;
                }

                for (int i=0;i<graph.nodes.Length;i++) {
                    graph.nodes[i].graphIndex = graphIndex;
                }

                Debug.Log ("Loading "+numNodes+ " nodes");
                if (!MoveToVariableAnchor ("DeserializeGraphNodes")) {
                    Debug.LogError ("Error loading nodes - Couldn't find anchor");
                }

                serializeGraph.DeSerializeNodes (graph.nodes,this);

                if (!MoveToVariableAnchor ("DeserializeNodes")) {
                    Debug.LogError ("Error loading nodes - Couldn't find anchor");
                    return;
                }

                if (mask == SMask.RunLengthEncoding) {
                    int totalCount = 0;

                    //Penalties
                    while (totalCount < graph.nodes.Length) {
                        int runLength = (int)readerStream.ReadByte ();
                        int value = readerStream.ReadInt32 ();
                        int endIndex = totalCount+runLength;

                        if (endIndex > graph.nodes.Length) {
                            Debug.LogError ("Run Length Encoding is too long "+runLength+" "+endIndex+ " "+graph.nodes.Length+" "+totalCount);
                            endIndex = graph.nodes.Length;
                        }

                        for (int i=totalCount;i<endIndex;i++) {
                            graph.nodes[i].penalty = (uint)value;
                        }
                        totalCount = endIndex;
                    }

                    totalCount = 0;

                    //Flags
                    while (totalCount < graph.nodes.Length) {
                        int runLength = (int)readerStream.ReadByte ();
                        int value = readerStream.ReadInt32 ();
                        int endIndex = totalCount+runLength;

                        if (endIndex > graph.nodes.Length) {
                            Debug.LogError ("Run Length Encoding is too long "+runLength+" "+endIndex+ " "+graph.nodes.Length+" "+totalCount);
                            endIndex = graph.nodes.Length;
                        }

                        for (int i=totalCount;i<endIndex;i++) {
                            graph.nodes[i].flags = value;
                        }
                        totalCount += runLength;
                    }
                }

                for (int i=0;i<graph.nodes.Length;i++) {
                    DeSerializeNode (graph.nodes[i], graphs, graphIndex, readerStream);
                }
            }
        }
示例#47
0
        public void SetUpGraphRefs(NavGraph[] graphs)
        {
            graphRefGuids = new int[loadedGraphGuids.Length];

            for (int i=0;i<loadedGraphGuids.Length;i++) {

                Pathfinding.Util.Guid guid = new Pathfinding.Util.Guid (loadedGraphGuids[i]);

                graphRefGuids[i] = -1;

                for (int j=0;j<graphs.Length;j++) {
                    if (graphs[j].guid == guid) {
                        graphRefGuids[i] = i;
                    }
                }
                //graphRefGuids[i] = astarData.GuidToIndex ());
            }
        }
示例#48
0
        //GraphUndo undoState;
        //byte[] savedBytes;

        public override void OnSceneGUI(NavGraph target)
        {
            Event e = Event.current;



            GridGraph graph = target as GridGraph;

            Matrix4x4 matrixPre = graph.matrix;

            graph.GenerateMatrix();

            if (e.type == EventType.MouseDown)
            {
                isMouseDown = true;
            }
            else if (e.type == EventType.MouseUp)
            {
                isMouseDown = false;
            }

            if (!isMouseDown)
            {
                savedMatrix = graph.boundsMatrix;
            }

            Handles.matrix = savedMatrix;

            if ((graph.GetType() == typeof(GridGraph) && graph.nodes == null) || (graph.uniformWidthDepthGrid && graph.depth * graph.width != graph.nodes.Length) || graph.matrix != matrixPre)
            {
                //Rescan the graphs
                if (AutoScan())
                {
                    GUI.changed = true;
                }
            }

            Matrix4x4 inversed = savedMatrix.inverse;

            Handles.color = AstarColor.BoundsHandles;

            Handles.DrawCapFunction cap = Handles.CylinderCap;

            Vector2 extents = graph.unclampedSize * 0.5F;

            Vector3 center = inversed.MultiplyPoint3x4(graph.center);


        #if UNITY_3_3
            if (Tools.current == 3)
            {
        #else
            if (Tools.current == Tool.Scale)
            {
        #endif

                Vector3 p1 = Handles.Slider(center + new Vector3(extents.x, 0, 0), Vector3.right, 0.1F * HandleUtility.GetHandleSize(center + new Vector3(extents.x, 0, 0)), cap, 0);
                Vector3 p2 = Handles.Slider(center + new Vector3(0, 0, extents.y), Vector3.forward, 0.1F * HandleUtility.GetHandleSize(center + new Vector3(0, 0, extents.y)), cap, 0);
                //Vector3 p3 = Handles.Slider (center+new Vector3 (0,extents.y,0),	Vector3.up,			0.1F*HandleUtility.GetHandleSize (center+new Vector3 (0,extents.y,0)),cap,0);

                Vector3 p4 = Handles.Slider(center + new Vector3(-extents.x, 0, 0), -Vector3.right, 0.1F * HandleUtility.GetHandleSize(center + new Vector3(-extents.x, 0, 0)), cap, 0);
                Vector3 p5 = Handles.Slider(center + new Vector3(0, 0, -extents.y), -Vector3.forward, 0.1F * HandleUtility.GetHandleSize(center + new Vector3(0, 0, -extents.y)), cap, 0);

                Vector3 p6 = Handles.Slider(center, Vector3.up, 0.1F * HandleUtility.GetHandleSize(center), cap, 0);

                Vector3 r1 = new Vector3(p1.x, p6.y, p2.z);
                Vector3 r2 = new Vector3(p4.x, p6.y, p5.z);

                //Debug.Log (graph.boundsMatrix.MultiplyPoint3x4 (Vector3.zero)+" "+graph.boundsMatrix.MultiplyPoint3x4 (Vector3.one));

                //if (Tools.viewTool != ViewTool.Orbit) {

                graph.center = savedMatrix.MultiplyPoint3x4((r1 + r2) / 2F);

                Vector3 tmp = r1 - r2;
                graph.unclampedSize = new Vector2(tmp.x, tmp.z);

                //}

        #if UNITY_3_3
            }
            else if (Tools.current == 1)
            {
        #else
            }
            else if (Tools.current == Tool.Move)
            {
        #endif

                if (Tools.pivotRotation == PivotRotation.Local)
                {
                    center = Handles.PositionHandle(center, Quaternion.identity);

                    if (Tools.viewTool != ViewTool.Orbit)
                    {
                        graph.center = savedMatrix.MultiplyPoint3x4(center);
                    }
                }
                else
                {
                    Handles.matrix = Matrix4x4.identity;

                    center = Handles.PositionHandle(graph.center, Quaternion.identity);

                    if (Tools.viewTool != ViewTool.Orbit)
                    {
                        graph.center = center;
                    }
                }
        #if UNITY_3_3
            }
            else if (Tools.current == 2)
            {
        #else
            }
            else if (Tools.current == Tool.Rotate)
            {
        #endif
                //The rotation handle doesn't seem to be able to handle different matrixes of some reason
                Handles.matrix = Matrix4x4.identity;

                Quaternion rot = Handles.RotationHandle(Quaternion.Euler(graph.rotation), graph.center);

                if (Tools.viewTool != ViewTool.Orbit)
                {
                    graph.rotation = rot.eulerAngles;
                }
            }

            //graph.size.x = Mathf.Max (graph.size.x,1);
            //graph.size.y = Mathf.Max (graph.size.y,1);
            //graph.size.z = Mathf.Max (graph.size.z,1);

            Handles.matrix = Matrix4x4.identity;



        #if ASTARDEBUG
            //Draws some info over the node closest to the mouse
            Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);

            Vector3 p = ray.GetPoint(100);


            if (Event.current.shift)
            {
                GraphNode close = graph.GetNearest(p).node;

                if (close != null)
                {
                    node1 = close;
                }

                if (node1 == null)
                {
                    return;
                }

                Handles.SphereCap(0, (Vector3)node1.position, Quaternion.identity, graph.nodeSize * 0.5F);


                //Node node = node1;

                GUI.color = Color.white;
                //Handles.Label((Vector3)node.position + Vector3.up*2,"G : "+node.+"\nH : "+node.h+"\nF : "+node.f+"\nPosition : "+node.position.ToString (),EditorStyles.whiteBoldLabel);
            }
        #endif
        }
示例#49
0
        public void DeSerializeEditorSettings(NavGraph graph, ISerializableGraphEditor editor, AstarPath active)
        {
            if (editor == null) {
                Debug.LogError ("The editor specified is Null");
                return;
            }

            editor.DeSerializeSettings (graph,this);
        }
示例#50
0
		//GraphUndo undoState;
		//byte[] savedBytes;
		
		public override void OnSceneGUI (NavGraph target) {
			
			Event e = Event.current;
			
			
			
			GridGraph graph = target as GridGraph;
			
			Matrix4x4 matrixPre = graph.matrix;
			
			graph.GenerateMatrix ();
			
			if (e.type == EventType.MouseDown) {
				isMouseDown = true;
			} else if (e.type == EventType.MouseUp) {
				isMouseDown = false;
			}
			
			if (!isMouseDown) {
				savedMatrix = graph.boundsMatrix;
			}
			
			Handles.matrix = savedMatrix;
			
			if ((graph.GetType() == typeof(GridGraph) && graph.nodes == null) || (graph.uniformWidthDepthGrid && graph.depth*graph.width != graph.nodes.Length) || graph.matrix != matrixPre) {
				//Rescan the graphs
				if (AstarPath.active.AutoScan ()) {
					GUI.changed = true;
				}
			}
			
			Matrix4x4 inversed = savedMatrix.inverse;
			
			Handles.color = AstarColor.BoundsHandles;
			
			Handles.DrawCapFunction cap = Handles.CylinderCap;
			
			Vector2 extents = graph.unclampedSize*0.5F;
			
			Vector3 center = inversed.MultiplyPoint3x4 (graph.center);
			
			
	#if UNITY_3_3
			if (Tools.current == 3) {
	#else
			if (Tools.current == Tool.Scale) {
	#endif
			
				Vector3 p1 = Handles.Slider (center+new Vector3 (extents.x,0,0),	Vector3.right,		0.1F*HandleUtility.GetHandleSize (center+new Vector3 (extents.x,0,0)),cap,0);
				Vector3 p2 = Handles.Slider (center+new Vector3 (0,0,extents.y),	Vector3.forward,	0.1F*HandleUtility.GetHandleSize (center+new Vector3 (0,0,extents.y)),cap,0);
				//Vector3 p3 = Handles.Slider (center+new Vector3 (0,extents.y,0),	Vector3.up,			0.1F*HandleUtility.GetHandleSize (center+new Vector3 (0,extents.y,0)),cap,0);
				
				Vector3 p4 = Handles.Slider (center+new Vector3 (-extents.x,0,0),	-Vector3.right,		0.1F*HandleUtility.GetHandleSize (center+new Vector3 (-extents.x,0,0)),cap,0);
				Vector3 p5 = Handles.Slider (center+new Vector3 (0,0,-extents.y),	-Vector3.forward,	0.1F*HandleUtility.GetHandleSize (center+new Vector3 (0,0,-extents.y)),cap,0);
				
				Vector3 p6 = Handles.Slider (center,	Vector3.up,		0.1F*HandleUtility.GetHandleSize (center),cap,0);
				
				Vector3 r1 = new Vector3 (p1.x,p6.y,p2.z);
				Vector3 r2 = new Vector3 (p4.x,p6.y,p5.z);
				
				//Debug.Log (graph.boundsMatrix.MultiplyPoint3x4 (Vector3.zero)+" "+graph.boundsMatrix.MultiplyPoint3x4 (Vector3.one));
				
				//if (Tools.viewTool != ViewTool.Orbit) {
				
					graph.center = savedMatrix.MultiplyPoint3x4 ((r1+r2)/2F);
					
					Vector3 tmp = r1-r2;
					graph.unclampedSize = new Vector2(tmp.x,tmp.z);
					
				//}		
			
	#if UNITY_3_3
			} else if (Tools.current == 1) {
	#else
			} else if (Tools.current == Tool.Move) {
	#endif
				
				if (Tools.pivotRotation == PivotRotation.Local) {	
					center = Handles.PositionHandle (center,Quaternion.identity);
					
					if (Tools.viewTool != ViewTool.Orbit) {
						graph.center = savedMatrix.MultiplyPoint3x4 (center);
					}
				} else {
					Handles.matrix = Matrix4x4.identity;
					
					center = Handles.PositionHandle (graph.center,Quaternion.identity);
					
					if (Tools.viewTool != ViewTool.Orbit) {
						graph.center = center;
					}
				}
	#if UNITY_3_3
			} else if (Tools.current == 2) {
	#else
			} else if (Tools.current == Tool.Rotate) {
	#endif
				//The rotation handle doesn't seem to be able to handle different matrixes of some reason
				Handles.matrix = Matrix4x4.identity;
				
				Quaternion rot = Handles.RotationHandle (Quaternion.Euler (graph.rotation),graph.center);
				
				if (Tools.viewTool != ViewTool.Orbit) {
					graph.rotation = rot.eulerAngles;
				}
			}
			
			//graph.size.x = Mathf.Max (graph.size.x,1);
			//graph.size.y = Mathf.Max (graph.size.y,1);
			//graph.size.z = Mathf.Max (graph.size.z,1);
			
			Handles.matrix = Matrix4x4.identity;
			
			
			
	#if ASTARDEBUG
			//Draws some info over the node closest to the mouse
			Ray ray = HandleUtility.GUIPointToWorldRay (Event.current.mousePosition);
			
			Vector3 p = ray.GetPoint (100);
			
			
			if (Event.current.shift) {
				
				GraphNode close = graph.GetNearest (p).node;
				
				if (close != null) {
					node1 = close;
				}
					
				if (node1 == null) {
					return;
				}
				
				Handles.SphereCap (0,(Vector3)node1.position,Quaternion.identity,graph.nodeSize*0.5F);
				
				
				//Node node = node1;
				
				GUI.color = Color.white;
				//Handles.Label((Vector3)node.position + Vector3.up*2,"G : "+node.+"\nH : "+node.h+"\nF : "+node.f+"\nPosition : "+node.position.ToString (),EditorStyles.whiteBoldLabel);
			}
			
	#endif
			
		}
示例#51
0
        //This is intended for quick saving of settings for e.g Undo operations
        public void DeSerializeSettings(NavGraph graph, AstarPath active)
        {
            ISerializableGraph serializeGraph = graph as ISerializableGraph;

            if (serializeGraph == null) {
                Debug.LogError ("The graph specified is not (de)serializable (how it could be serialized in the first place is a mystery) the graph was of type "+graph.GetType());
                return;
            }

            graph.open = readerStream.ReadBoolean ();

            //readerStream.ReadString ();
            serializeGraph.DeSerializeSettings (this);
        }
示例#52
0
		public override void OnInspectorGUI (NavGraph target) {
			
			GridGraph graph = target as GridGraph;
			
			//GUILayout.BeginHorizontal ();
			//GUILayout.BeginVertical ();
			Rect lockRect;
			
			GUIStyle lockStyle = AstarPathEditor.astarSkin.FindStyle ("GridSizeLock");
			if (lockStyle == null) {
				lockStyle = new GUIStyle ();
			}
	
	#if !UNITY_LE_4_3 || true
			GUILayout.BeginHorizontal ();
			GUILayout.BeginVertical ();
			int newWidth = EditorGUILayout.IntField (new GUIContent ("Width (nodes)","Width of the graph in nodes"), graph.width);
			int newDepth = EditorGUILayout.IntField (new GUIContent ("Depth (nodes)","Depth (or height you might also call it) of the graph in nodes"), graph.depth);
			GUILayout.EndVertical ();
	
			lockRect = GUILayoutUtility.GetRect (lockStyle.fixedWidth,lockStyle.fixedHeight);
	
			// Add a small offset to make it better centred around the controls
			lockRect.y += 3;
			GUILayout.EndHorizontal ();
	
			// All the layouts mess up the margin to the next control, so add it manually
			GUILayout.Space (2);
	#elif UNITY_4
			Rect tmpLockRect;
			int newWidth = IntField (new GUIContent ("Width (nodes)","Width of the graph in nodes"),graph.width,100,0, out lockRect, out sizeSelected1);
			int newDepth = IntField (new GUIContent ("Depth (nodes)","Depth (or height you might also call it) of the graph in nodes"),graph.depth,100,0, out tmpLockRect, out sizeSelected2);
	#else
			Rect tmpLockRect;
			int newWidth = IntField (new GUIContent ("Width (nodes)","Width of the graph in nodes"),graph.width,50,0, out lockRect, out sizeSelected1);
			int newDepth = IntField (new GUIContent ("Depth (nodes)","Depth (or height you might also call it) of the graph in nodes"),graph.depth,50,0, out tmpLockRect, out sizeSelected2);
	#endif
			
			lockRect.width = lockStyle.fixedWidth;
			lockRect.height = lockStyle.fixedHeight;
			lockRect.x += lockStyle.margin.left;
			lockRect.y += lockStyle.margin.top;
			
			locked = GUI.Toggle (lockRect,locked,new GUIContent ("","If the width and depth values are locked, changing the node size will scale the grid which keeping the number of nodes consistent instead of keeping the size the same and changing the number of nodes in the graph"),lockStyle);
			
			//GUILayout.EndHorizontal ();
			
			if (newWidth != graph.width || newDepth != graph.depth) {
				SnapSizeToNodes (newWidth,newDepth,graph);
			}
			
			GUI.SetNextControlName ("NodeSize");
			newNodeSize = EditorGUILayout.FloatField (new GUIContent ("Node size","The size of a single node. The size is the side of the node square in world units"),graph.nodeSize);
			
			newNodeSize = newNodeSize <= 0.01F ? 0.01F : newNodeSize;
			
			float prevRatio = graph.aspectRatio;
			graph.aspectRatio = EditorGUILayout.FloatField (new GUIContent ("Aspect Ratio","Scaling of the nodes width/depth ratio. Good for isometric games"),graph.aspectRatio);
	
			if (graph.nodeSize != newNodeSize || prevRatio != graph.aspectRatio) {
				if (!locked) {
					graph.nodeSize = newNodeSize;
					Matrix4x4 oldMatrix = graph.matrix;
					graph.GenerateMatrix ();
					if (graph.matrix != oldMatrix) {
						//Rescann the graphs
						//AstarPath.active.AutoScan ();
						GUI.changed = true;
					}
				} else {
					float delta = newNodeSize / graph.nodeSize;
					graph.nodeSize = newNodeSize;
					graph.unclampedSize = new Vector2 (newWidth*graph.nodeSize,newDepth*graph.nodeSize);
					Vector3 newCenter = graph.matrix.MultiplyPoint3x4 (new Vector3 ((newWidth/2F)*delta,0,(newDepth/2F)*delta));
					graph.center = newCenter;
					graph.GenerateMatrix ();
					
					//Make sure the width & depths stay the same
					graph.width = newWidth;
					graph.depth = newDepth;
					AstarPath.active.AutoScan ();
				}
			}
			
			Vector3 pivotPoint;
			Vector3 diff;
	
	#if UNITY_LE_4_3
			EditorGUIUtility.LookLikeControls ();
	#endif
	
	#if !UNITY_4
			EditorGUILayoutx.BeginIndent ();
	#else
			GUILayout.BeginHorizontal ();
	#endif
			
			switch (pivot) {
				case GridPivot.Center:
					graph.center = RoundVector3 ( graph.center );
					graph.center = EditorGUILayout.Vector3Field ("Center",graph.center);
					break;
				case GridPivot.TopLeft:
					pivotPoint = graph.matrix.MultiplyPoint3x4 (new Vector3 (0,0,graph.depth));
					pivotPoint = RoundVector3 ( pivotPoint );
					diff = pivotPoint-graph.center;
					pivotPoint = EditorGUILayout.Vector3Field ("Top-Left",pivotPoint);
					graph.center = pivotPoint-diff;
					break;
				case GridPivot.TopRight:
					pivotPoint = graph.matrix.MultiplyPoint3x4 (new Vector3 (graph.width,0,graph.depth));
					pivotPoint = RoundVector3 ( pivotPoint );
					diff = pivotPoint-graph.center;
					pivotPoint = EditorGUILayout.Vector3Field ("Top-Right",pivotPoint);
					graph.center = pivotPoint-diff;
					break;
				case GridPivot.BottomLeft:
					pivotPoint = graph.matrix.MultiplyPoint3x4 (new Vector3 (0,0,0));
					pivotPoint = RoundVector3 ( pivotPoint );
					diff = pivotPoint-graph.center;
					pivotPoint = EditorGUILayout.Vector3Field ("Bottom-Left",pivotPoint);
					graph.center = pivotPoint-diff;
					break;
				case GridPivot.BottomRight:
					pivotPoint = graph.matrix.MultiplyPoint3x4 (new Vector3 (graph.width,0,0));
					pivotPoint = RoundVector3 ( pivotPoint );
					diff = pivotPoint-graph.center;
					pivotPoint = EditorGUILayout.Vector3Field ("Bottom-Right",pivotPoint);
					graph.center = pivotPoint-diff;
					break;
			}
			
			graph.GenerateMatrix ();
			
			pivot = PivotPointSelector (pivot);
			
	#if !UNITY_4
			EditorGUILayoutx.EndIndent ();
			
			EditorGUILayoutx.BeginIndent ();
	#else
			GUILayout.EndHorizontal ();
	#endif
			
			graph.rotation = EditorGUILayout.Vector3Field ("Rotation",graph.rotation);
	
	#if UNITY_LE_4_3
			//Add some space to make the Rotation and postion fields be better aligned (instead of the pivot point selector)
			//GUILayout.Space (19+7);
	#endif
			//GUILayout.EndHorizontal ();
			
	#if !UNITY_4
			EditorGUILayoutx.EndIndent ();
	#endif
	#if UNITY_LE_4_3
			EditorGUIUtility.LookLikeInspector ();
	#endif
	
			if (GUILayout.Button (new GUIContent ("Snap Size","Snap the size to exactly fit nodes"),GUILayout.MaxWidth (100),GUILayout.MaxHeight (16))) {
				SnapSizeToNodes (newWidth,newDepth,graph);
			}
			
			Separator ();
			
			graph.cutCorners = EditorGUILayout.Toggle (new GUIContent ("Cut Corners","Enables or disables cutting corners. See docs for image example"),graph.cutCorners);
			graph.neighbours = (NumNeighbours)EditorGUILayout.EnumPopup (new GUIContent ("Connections","Sets how many connections a node should have to it's neighbour nodes."),graph.neighbours);
			
			//GUILayout.BeginHorizontal ();
			//EditorGUILayout.PrefixLabel ("Max Climb");
			graph.maxClimb = EditorGUILayout.FloatField (new GUIContent ("Max Climb","How high, relative to the graph, should a climbable level be. A zero (0) indicates infinity"),graph.maxClimb);
			if ( graph.maxClimb < 0 ) graph.maxClimb = 0;
			EditorGUI.indentLevel++;
			graph.maxClimbAxis = EditorGUILayout.IntPopup (new GUIContent ("Climb Axis","Determines which axis the above setting should test on"),graph.maxClimbAxis,new GUIContent[3] {new GUIContent ("X"),new GUIContent ("Y"),new GUIContent ("Z")},new int[3] {0,1,2});
			EditorGUI.indentLevel--;
			
			if ( graph.maxClimb > 0 && Mathf.Abs((Quaternion.Euler (graph.rotation) * new Vector3 (graph.nodeSize,0,graph.nodeSize))[graph.maxClimbAxis]) > graph.maxClimb ) {
				EditorGUILayout.HelpBox ("Nodes are spaced further apart than this in the grid. You might want to increase this value or change the axis", MessageType.Warning );
			}
			
			//GUILayout.EndHorizontal ();
			
			graph.maxSlope = EditorGUILayout.Slider (new GUIContent ("Max Slope","Sets the max slope in degrees for a point to be walkable. Only enabled if Height Testing is enabled."),graph.maxSlope,0,90F);
			
			graph.erodeIterations = EditorGUILayout.IntField (new GUIContent ("Erosion iterations","Sets how many times the graph should be eroded. This adds extra margin to objects. This will not work when using Graph Updates, so if you can, use the Diameter setting in collision settings instead"),graph.erodeIterations);
			graph.erodeIterations = graph.erodeIterations < 0 ? 0 : (graph.erodeIterations > 16 ? 16 : graph.erodeIterations); //Clamp iterations to [0,16]
	
			if ( graph.erodeIterations > 0 ) {
				EditorGUI.indentLevel++;
				graph.erosionUseTags = EditorGUILayout.Toggle (new GUIContent ("Erosion Uses Tags","Instead of making nodes unwalkable, " +
				"nodes will have their tag set to a value corresponding to their erosion level, " +
				"which is a quite good measurement of their distance to the closest wall.\nSee online documentation for more info."),
			                                               graph.erosionUseTags);
				if (graph.erosionUseTags) {
					EditorGUI.indentLevel++;
					graph.erosionFirstTag = EditorGUILayoutx.SingleTagField ("First Tag",graph.erosionFirstTag);
					EditorGUI.indentLevel--;
				}
				EditorGUI.indentLevel--;
			}
			DrawCollisionEditor (graph.collision);
			
			if ( graph.collision.use2D ) {
				if ( Mathf.Abs ( Vector3.Dot ( Vector3.forward, Quaternion.Euler (graph.rotation) * Vector3.up ) ) < 0.9f ) {
					EditorGUILayout.HelpBox ("When using 2D it is recommended to rotate the graph so that it aligns with the 2D plane.", MessageType.Warning );
				}
			}
			
			Separator ();
			
			showExtra = EditorGUILayout.Foldout (showExtra, "Extra");
			
			if (showExtra) {
				EditorGUI.indentLevel+=2;
				
				graph.penaltyAngle = ToggleGroup (new GUIContent ("Angle Penalty","Adds a penalty based on the slope of the node"),graph.penaltyAngle);
				//bool preGUI = GUI.enabled;
				//GUI.enabled = graph.penaltyAngle && GUI.enabled;
				if (graph.penaltyAngle) {
					EditorGUI.indentLevel++;
					graph.penaltyAngleFactor = EditorGUILayout.FloatField (new GUIContent ("Factor","Scale of the penalty. A negative value should not be used"),graph.penaltyAngleFactor);
					//GUI.enabled = preGUI;
					HelpBox ("Applies penalty to nodes based on the angle of the hit surface during the Height Testing");
					
					EditorGUI.indentLevel--;
				}
				
				graph.penaltyPosition = ToggleGroup ("Position Penalty",graph.penaltyPosition);
					//EditorGUILayout.Toggle ("Position Penalty",graph.penaltyPosition);
				//preGUI = GUI.enabled;
				//GUI.enabled = graph.penaltyPosition && GUI.enabled;
				if (graph.penaltyPosition) {
					EditorGUI.indentLevel++;
					graph.penaltyPositionOffset = EditorGUILayout.FloatField ("Offset",graph.penaltyPositionOffset);
					graph.penaltyPositionFactor = EditorGUILayout.FloatField ("Factor",graph.penaltyPositionFactor);
					HelpBox ("Applies penalty to nodes based on their Y coordinate\nSampled in Int3 space, i.e it is multiplied with Int3.Precision first ("+Int3.Precision+")\n" +
						"Be very careful when using negative values since a negative penalty will underflow and instead get really high");
					//GUI.enabled = preGUI;
					EditorGUI.indentLevel--;
				}
				
				if (textureVisible) {
					DrawTextureData (graph.textureData, graph);
				}
				EditorGUI.indentLevel-=2;
			}
		}
示例#53
0
 /// <summary>Override to implement scene GUI drawing for the graph</summary>
 public virtual void OnSceneGUI(NavGraph target)
 {
 }
示例#54
0
        public override void OnSceneGUI(NavGraph target)
        {
            Event e = Event.current;

            var graph = target as GridGraph;

            Matrix4x4 matrixPre = graph.matrix;

            graph.GenerateMatrix();

            if (e.type == EventType.MouseDown)
            {
                isMouseDown = true;
            }
            else if (e.type == EventType.MouseUp)
            {
                isMouseDown = false;
            }

            if (!isMouseDown)
            {
                savedMatrix = graph.boundsMatrix;
            }

            Handles.matrix = savedMatrix;

            if ((graph is GridGraph && graph.nodes == null) || (graph.uniformWidthDepthGrid && graph.depth * graph.width != graph.nodes.Length) || graph.matrix != matrixPre)
            {
                //Rescan the graphs
                if (AutoScan())
                {
                    GUI.changed = true;
                }
            }

            Matrix4x4 inversed = savedMatrix.inverse;

            Handles.color = AstarColor.BoundsHandles;

            Handles.DrawCapFunction cap = Handles.CylinderCap;

            Vector2 extents = graph.unclampedSize * 0.5F;

            Vector3 center = inversed.MultiplyPoint3x4(graph.center);


            if (Tools.current == Tool.Scale)
            {
                const float HandleScale = 0.1f;

                EditorGUI.BeginChangeCheck();

                Vector3 p1 = Handles.Slider(center + new Vector3(extents.x, 0, 0), Vector3.right, HandleScale * HandleUtility.GetHandleSize(center + new Vector3(extents.x, 0, 0)), cap, 0);
                Vector3 p2 = Handles.Slider(center + new Vector3(0, 0, extents.y), Vector3.forward, HandleScale * HandleUtility.GetHandleSize(center + new Vector3(0, 0, extents.y)), cap, 0);

                Vector3 p4 = Handles.Slider(center + new Vector3(-extents.x, 0, 0), -Vector3.right, HandleScale * HandleUtility.GetHandleSize(center + new Vector3(-extents.x, 0, 0)), cap, 0);
                Vector3 p5 = Handles.Slider(center + new Vector3(0, 0, -extents.y), -Vector3.forward, HandleScale * HandleUtility.GetHandleSize(center + new Vector3(0, 0, -extents.y)), cap, 0);

                Vector3 p6 = Handles.Slider(center, Vector3.up, HandleScale * HandleUtility.GetHandleSize(center), cap, 0);

                var r1 = new Vector3(p1.x, p6.y, p2.z);
                var r2 = new Vector3(p4.x, p6.y, p5.z);

                if (EditorGUI.EndChangeCheck())
                {
                    graph.center = savedMatrix.MultiplyPoint3x4((r1 + r2) / 2F);

                    Vector3 tmp = r1 - r2;
                    graph.unclampedSize = new Vector2(tmp.x, tmp.z);
                }
            }
            else if (Tools.current == Tool.Move)
            {
                if (Tools.pivotRotation == PivotRotation.Local)
                {
                    EditorGUI.BeginChangeCheck();
                    center = Handles.PositionHandle(center, Quaternion.identity);

                    if (EditorGUI.EndChangeCheck() && Tools.viewTool != ViewTool.Orbit)
                    {
                        graph.center = savedMatrix.MultiplyPoint3x4(center);
                    }
                }
                else
                {
                    Handles.matrix = Matrix4x4.identity;

                    EditorGUI.BeginChangeCheck();
                    center = Handles.PositionHandle(graph.center, Quaternion.identity);

                    if (EditorGUI.EndChangeCheck() && Tools.viewTool != ViewTool.Orbit)
                    {
                        graph.center = center;
                    }
                }
            }
            else if (Tools.current == Tool.Rotate)
            {
                //The rotation handle doesn't seem to be able to handle different matrixes of some reason
                Handles.matrix = Matrix4x4.identity;

                EditorGUI.BeginChangeCheck();
                var rot = Handles.RotationHandle(Quaternion.Euler(graph.rotation), graph.center);

                if (EditorGUI.EndChangeCheck() && Tools.viewTool != ViewTool.Orbit)
                {
                    graph.rotation = rot.eulerAngles;
                }
            }

            Handles.matrix = Matrix4x4.identity;
        }
		public override void OnInspectorGUI (NavGraph target) {
			PointGraph graph = target as PointGraph;
	
	/*
	#if UNITY_3_3
			graph.root = (Transform)EditorGUILayout.ObjectField (new GUIContent ("Root","All childs of this object will be used as nodes, if it is not set, a tag search will be used instead (see below)"),graph.root,typeof(Transform));
	#else
			graph.root = (Transform)EditorGUILayout.ObjectField (new GUIContent ("Root","All childs of this object will be used as nodes, if it is not set, a tag search will be used instead (see below)"),graph.root,typeof(Transform),true);
	#endif
	*/
			//Debug.Log (EditorGUI.indentLevel);
			
			graph.root = ObjectField (new GUIContent ("Root","All childs of this object will be used as nodes, if it is not set, a tag search will be used instead (see below)"),graph.root,typeof(Transform),true) as Transform;
			
			graph.recursive = EditorGUILayout.Toggle (new GUIContent ("Recursive","Should childs of the childs in the root GameObject be searched"),graph.recursive);
			graph.searchTag = EditorGUILayout.TagField (new GUIContent ("Tag","If root is not set, all objects with this tag will be used as nodes"),graph.searchTag);
	
	#if UNITY_4
			if (graph.root != null) {
				EditorGUILayout.HelpBox ("All childs "+(graph.recursive ? "and sub-childs ":"") +"of 'root' will be used as nodes\nSet root to null to use a tag search instead", MessageType.None);
			} else {
				EditorGUILayout.HelpBox ("All object with the tag '"+graph.searchTag+"' will be used as nodes"+(graph.searchTag == "Untagged" ? "\nNote: the tag 'Untagged' cannot be used" : ""), MessageType.None);
			}
	#else
			if (graph.root != null) {
				GUILayout.Label ("All childs "+(graph.recursive ? "and sub-childs ":"") +"of 'root' will be used as nodes\nSet root to null to use a tag search instead",AstarPathEditor.helpBox);
			} else {
				GUILayout.Label ("All object with the tag '"+graph.searchTag+"' will be used as nodes"+(graph.searchTag == "Untagged" ? "\nNote: the tag 'Untagged' cannot be used" : ""),AstarPathEditor.helpBox);
			}
	#endif
	
			graph.maxDistance = EditorGUILayout.FloatField (new GUIContent ("Max Distance","The max distance in world space for a connection to be valid. A zero counts as infinity"),graph.maxDistance);
	
	#if UNITY_LE_4_3
			EditorGUIUtility.LookLikeControls ();
	#endif
	#if UNITY_4
			graph.limits = EditorGUILayout.Vector3Field ("Max Distance (axis aligned)",graph.limits);
	#else
			EditorGUILayoutx.BeginIndent ();
			graph.limits = EditorGUILayout.Vector3Field ("Max Distance (axis aligned)",graph.limits);
			EditorGUILayoutx.EndIndent ();
	#endif
	#if UNITY_LE_4_3
			EditorGUIUtility.LookLikeInspector ();
	#endif
	
			graph.raycast = EditorGUILayout.Toggle (new GUIContent ("Raycast","Use raycasting to check if connections are valid between each pair of nodes"),graph.raycast);
			
			//EditorGUILayoutx.FadeArea fade = editor.GUILayoutx.BeginFadeArea (graph.raycast,"raycast");
			//if ( fade.Show () ) {
			if ( graph.raycast ) {
				EditorGUI.indentLevel++;

				graph.use2DPhysics = EditorGUILayout.Toggle (new GUIContent ("Use 2D Physics", "If enabled, all raycasts will use the Unity 2D Physics API instead of the 3D one."), graph.use2DPhysics);
			 	graph.thickRaycast = EditorGUILayout.Toggle (new GUIContent ("Thick Raycast","A thick raycast checks along a thick line with radius instead of just along a line"),graph.thickRaycast);
			 	
			 	//editor.GUILayoutx.BeginFadeArea (graph.thickRaycast,"thickRaycast");
				if ( graph.thickRaycast ) {
			 		graph.thickRaycastRadius = EditorGUILayout.FloatField (new GUIContent ("Raycast Radius","The radius in world units for the thick raycast"),graph.thickRaycastRadius);
				}
			 	//editor.GUILayoutx.EndFadeArea ();
			 	
				//graph.mask = 1 << EditorGUILayout.LayerField ("Mask",(int)Mathf.Log (graph.mask,2));
				graph.mask = EditorGUILayoutx.LayerMaskField (/*new GUIContent (*/"Mask"/*,"Used to mask which layers should be checked")*/,graph.mask);
				EditorGUI.indentLevel--;
			}
	
			//editor.GUILayoutx.EndFadeArea ();

			graph.optimizeForSparseGraph = EditorGUILayout.Toggle (new GUIContent ("Optimize For Sparse Graph","Check online documentation for more information."),graph.optimizeForSparseGraph);
	
			//fade = editor.GUILayoutx.BeginFadeArea (graph.optimizeForSparseGraph,"optimizeForSparseGraph");
			//if ( fade.Show () ) {
			if ( graph.optimizeForSparseGraph ) {
				EditorGUI.indentLevel++;
				
				graph.optimizeFor2D = EditorGUILayout.Toggle (new GUIContent ("Optimize For XZ Plane","Check online documentation for more information."),graph.optimizeFor2D);
	
				EditorGUI.indentLevel--;
			}
			
			//editor.GUILayoutx.EndFadeArea ();
		}
示例#56
0
        /** This performs a linear search through all polygons returning the closest one.
         * This will fill the NNInfo with .node for the closest node not necessarily complying with the NNConstraint, and .constrainedNode with the closest node
         * complying with the NNConstraint.
         * \see GetNearestForce(Node[],Int3[],Vector3,NNConstraint,bool)
         */
        public static NNInfo GetNearestForceBoth(NavGraph graph, INavmeshHolder navmesh, Vector3 position, NNConstraint constraint, bool accurateNearestNode)
        {
            Int3 pos = (Int3)position;

            float     minDist = -1;
            GraphNode minNode = null;

            float     minConstDist = -1;
            GraphNode minConstNode = null;

            float maxDistSqr = constraint.constrainDistance ? AstarPath.active.maxNearestNodeDistanceSqr : float.PositiveInfinity;

            GraphNodeDelegateCancelable del = delegate(GraphNode _node) {
                TriangleMeshNode node = _node as TriangleMeshNode;

                if (accurateNearestNode)
                {
                    Vector3 closest = node.ClosestPointOnNode(position);
                    float   dist    = ((Vector3)pos - closest).sqrMagnitude;

                    if (minNode == null || dist < minDist)
                    {
                        minDist = dist;
                        minNode = node;
                    }

                    if (dist < maxDistSqr && constraint.Suitable(node))
                    {
                        if (minConstNode == null || dist < minConstDist)
                        {
                            minConstDist = dist;
                            minConstNode = node;
                        }
                    }
                }
                else
                {
                    if (!node.ContainsPoint((Int3)position))
                    {
                        float dist = (node.position - pos).sqrMagnitude;
                        if (minNode == null || dist < minDist)
                        {
                            minDist = dist;
                            minNode = node;
                        }

                        if (dist < maxDistSqr && constraint.Suitable(node))
                        {
                            if (minConstNode == null || dist < minConstDist)
                            {
                                minConstDist = dist;
                                minConstNode = node;
                            }
                        }
                    }
                    else
                    {
                        int dist = AstarMath.Abs(node.position.y - pos.y);

                        if (minNode == null || dist < minDist)
                        {
                            minDist = dist;
                            minNode = node;
                        }

                        if (dist < maxDistSqr && constraint.Suitable(node))
                        {
                            if (minConstNode == null || dist < minConstDist)
                            {
                                minConstDist = dist;
                                minConstNode = node;
                            }
                        }
                    }
                }
                return(true);
            };

            graph.GetNodes(del);

            NNInfo nninfo = new NNInfo(minNode);

            //Find the point closest to the nearest triangle

            if (nninfo.node != null)
            {
                TriangleMeshNode node = nninfo.node as TriangleMeshNode;                //minNode2 as MeshNode;

                Vector3 clP = node.ClosestPointOnNode(position);

                nninfo.clampedPosition = clP;
            }

            nninfo.constrainedNode = minConstNode;
            if (nninfo.constrainedNode != null)
            {
                TriangleMeshNode node = nninfo.constrainedNode as TriangleMeshNode;                //minNode2 as MeshNode;

                Vector3 clP = node.ClosestPointOnNode(position);

                nninfo.constClampedPosition = clP;
            }

            return(nninfo);
        }
示例#57
0
        public void SerializeGraphs(NavGraph[] _graphs)
        {
            if (graphs != null) throw new InvalidOperationException ("Cannot serialize graphs multiple times.");
            graphs = _graphs;

            if (zip == null) throw new NullReferenceException ("You must not call CloseSerialize before a call to this function");

            if (graphs == null) graphs = new NavGraph[0];

            for (int i=0;i<graphs.Length;i++) {
                byte[] bytes = Serialize(graphs[i]);

                AddChecksum (bytes);
                zip.AddEntry ("graph"+i+jsonExt,bytes);
            }
        }
示例#58
0
		/** Adds the specified graph to the #graphs array */
		public void AddGraph (NavGraph graph) {
			
			// Make sure to not interfere with pathfinding
			AstarPath.active.BlockUntilPathQueueBlocked();
			
			//Try to fill in an empty position
			for (int i=0;i<graphs.Length;i++) {
				if (graphs[i] == null) {
					graphs[i] = graph;
					return;
				}
			}
			
			if (graphs != null && graphs.Length >= GraphNode.MaxGraphCount-1) {
				throw new System.Exception("Graph Count Limit Reached. You cannot have more than " + GraphNode.MaxGraphCount +
					" graphs. Some compiler directives can change this limit, e.g ASTAR_MORE_AREAS, look under the " +
					"'Optimizations' tab in the A* Inspector");
			}
			
			//Add a new entry to the list
			List<NavGraph> ls = new List<NavGraph> (graphs);
			ls.Add (graph);
			graphs = ls.ToArray ();
			
			UpdateShortcuts ();
			
			graph.active = active;
			graph.Awake ();
			graph.graphIndex = (uint)(graphs.Length-1);
		}
        // Token: 0x060022EF RID: 8943 RVA: 0x001968C8 File Offset: 0x00194AC8
        public void FloodFill()
        {
            NavGraph[] graphs = this.astar.graphs;
            if (graphs == null)
            {
                return;
            }
            foreach (NavGraph navGraph in graphs)
            {
                if (navGraph != null)
                {
                    navGraph.GetNodes(delegate(GraphNode node)
                    {
                        node.Area = 0U;
                    });
                }
            }
            this.lastUniqueAreaIndex = 0U;
            uint area               = 0U;
            int  forcedSmallAreas   = 0;
            Stack <GraphNode> stack = StackPool <GraphNode> .Claim();

            Action <GraphNode> < > 9__1;
            foreach (NavGraph navGraph2 in graphs)
            {
                if (navGraph2 != null)
                {
                    NavGraph           navGraph3 = navGraph2;
                    Action <GraphNode> action;
                    if ((action = < > 9__1) == null)
                    {
                        action = (< > 9__1 = delegate(GraphNode node)
                        {
                            if (node.Walkable && node.Area == 0U)
                            {
                                uint area = area;
                                area += 1U;
                                uint area2 = area;
                                if (area > 131071U)
                                {
                                    area = area;
                                    area -= 1U;
                                    area2 = area;
                                    int forcedSmallAreas;
                                    if (forcedSmallAreas == 0)
                                    {
                                        forcedSmallAreas = 1;
                                    }
                                    forcedSmallAreas = forcedSmallAreas;
                                    forcedSmallAreas++;
                                }
                                stack.Clear();
                                stack.Push(node);
                                int num = 1;
                                node.Area = area2;
                                while (stack.Count > 0)
                                {
                                    num++;
                                    stack.Pop().FloodFill(stack, area2);
                                }
                            }
                        });
                    }
                    navGraph3.GetNodes(action);
                }
            }
            this.lastUniqueAreaIndex = area;
            if (forcedSmallAreas > 0)
            {
                Debug.LogError(string.Concat(new object[]
                {
                    forcedSmallAreas,
                    " areas had to share IDs. This usually doesn't affect pathfinding in any significant way (you might get 'Searched whole area but could not find target' as a reason for path failure) however some path requests may take longer to calculate (specifically those that fail with the 'Searched whole area' error).The maximum number of areas is ",
                    131071U,
                    "."
                }));
            }
            StackPool <GraphNode> .Release(stack);
        }
示例#60
0
        public override void OnInspectorGUI(NavGraph target)
        {
            var graph = target as RecastGraph;

            bool preEnabled = GUI.enabled;

            System.Int64 estWidth = Mathf.RoundToInt(Mathf.Ceil(graph.forcedBoundsSize.x / graph.cellSize));
            System.Int64 estDepth = Mathf.RoundToInt(Mathf.Ceil(graph.forcedBoundsSize.z / graph.cellSize));

            // Show a warning if the number of voxels is too large
            if (estWidth * estDepth >= 1024 * 1024 || estDepth >= 1024 * 1024 || estWidth >= 1024 * 1024)
            {
                GUIStyle helpBox = GUI.skin.FindStyle("HelpBox") ?? GUI.skin.FindStyle("Box");

                Color preColor = GUI.color;
                if (estWidth * estDepth >= 2048 * 2048 || estDepth >= 2048 * 2048 || estWidth >= 2048 * 2048)
                {
                    GUI.color = Color.red;
                }
                else
                {
                    GUI.color = Color.yellow;
                }

                GUILayout.Label("Warning : Might take some time to calculate", helpBox);
                GUI.color = preColor;
            }

            GUI.enabled = false;
            EditorGUILayout.LabelField(new GUIContent("Width (voxels)", "Based on the cell size and the bounding box"), new GUIContent(estWidth.ToString()));

            EditorGUILayout.LabelField(new GUIContent("Depth (voxels)", "Based on the cell size and the bounding box"), new GUIContent(estDepth.ToString()));
            GUI.enabled = preEnabled;

            graph.cellSize = EditorGUILayout.FloatField(new GUIContent("Cell Size", "Size of one voxel in world units"), graph.cellSize);
            if (graph.cellSize < 0.001F)
            {
                graph.cellSize = 0.001F;
            }

            graph.useTiles = (UseTiles)EditorGUILayout.EnumPopup("Use Tiles", graph.useTiles ? UseTiles.UseTiles : UseTiles.DontUseTiles) == UseTiles.UseTiles;

            if (graph.useTiles)
            {
                EditorGUI.indentLevel++;
                graph.editorTileSize = EditorGUILayout.IntField(new GUIContent("Tile Size", "Size in voxels of a single tile.\n" +
                                                                               "This is the width of the tile.\n" +
                                                                               "\n" +
                                                                               "A large tile size can be faster to initially scan (but beware of out of memory issues if you try with a too large tile size in a large world)\n" +
                                                                               "smaller tile sizes are (much) faster to update.\n" +
                                                                               "\n" +
                                                                               "Different tile sizes can affect the quality of paths. It is often good to split up huge open areas into several tiles for\n" +
                                                                               "better quality paths, but too small tiles can lead to effects looking like invisible obstacles."), graph.editorTileSize);
                EditorGUI.indentLevel--;
            }

            graph.minRegionSize = EditorGUILayout.FloatField(new GUIContent("Min Region Size", "Small regions will be removed. In square world units"), graph.minRegionSize);

            graph.walkableHeight = EditorGUILayout.DelayedFloatField(new GUIContent("Walkable Height", "Minimum distance to the roof for an area to be walkable"), graph.walkableHeight);
            graph.walkableHeight = Mathf.Max(graph.walkableHeight, 0);

            graph.walkableClimb = EditorGUILayout.FloatField(new GUIContent("Walkable Climb", "How high can the character climb"), graph.walkableClimb);

            // A walkableClimb higher than this can cause issues when generating the navmesh since then it can in some cases
            // Both be valid for a character to walk under an obstacle and climb up on top of it (and that cannot be handled with a navmesh without links)
            if (graph.walkableClimb >= graph.walkableHeight)
            {
                graph.walkableClimb = graph.walkableHeight;
                EditorGUILayout.HelpBox("Walkable climb should be less than walkable height. Clamping to " + graph.walkableHeight + ".", MessageType.Warning);
            }
            else if (graph.walkableClimb < 0)
            {
                graph.walkableClimb = 0;
            }

            graph.characterRadius = EditorGUILayout.FloatField(new GUIContent("Character Radius", "Radius of the character. It's good to add some margin.\nIn world units."), graph.characterRadius);
            graph.characterRadius = Mathf.Max(graph.characterRadius, 0);

            if (graph.characterRadius < graph.cellSize * 2)
            {
                EditorGUILayout.HelpBox("For best navmesh quality, it is recommended to keep the character radius at least 2 times as large as the cell size. Smaller cell sizes will give you higher quality navmeshes, but it will take more time to scan the graph.", MessageType.Warning);
            }

            graph.maxSlope      = EditorGUILayout.Slider(new GUIContent("Max Slope", "Approximate maximum slope"), graph.maxSlope, 0F, 90F);
            graph.maxEdgeLength = EditorGUILayout.FloatField(new GUIContent("Max Border Edge Length", "Maximum length of one border edge in the completed navmesh before it is split. A lower value can often yield better quality graphs, but don't use so low values so that you get a lot of thin triangles."), graph.maxEdgeLength);
            graph.maxEdgeLength = graph.maxEdgeLength < graph.cellSize ? graph.cellSize : graph.maxEdgeLength;

            graph.contourMaxError = EditorGUILayout.FloatField(new GUIContent("Max Edge Error", "Amount of simplification to apply to edges.\nIn world units."), graph.contourMaxError);

            graph.rasterizeTerrain = EditorGUILayout.Toggle(new GUIContent("Rasterize Terrain", "Should a rasterized terrain be included"), graph.rasterizeTerrain);
            if (graph.rasterizeTerrain)
            {
                EditorGUI.indentLevel++;
                graph.rasterizeTrees = EditorGUILayout.Toggle(new GUIContent("Rasterize Trees", "Rasterize tree colliders on terrains. " +
                                                                             "If the tree prefab has a collider, that collider will be rasterized. " +
                                                                             "Otherwise a simple box collider will be used and the script will " +
                                                                             "try to adjust it to the tree's scale, it might not do a very good job though so " +
                                                                             "an attached collider is preferable."), graph.rasterizeTrees);
                if (graph.rasterizeTrees)
                {
                    EditorGUI.indentLevel++;
                    graph.colliderRasterizeDetail = EditorGUILayout.FloatField(new GUIContent("Collider Detail", "Controls the detail of the generated collider meshes. " +
                                                                                              "Increasing does not necessarily yield better navmeshes, but lowering will speed up scan.\n" +
                                                                                              "Spheres and capsule colliders will be converted to meshes in order to be able to rasterize them, a higher value will increase the number of triangles in those meshes."), graph.colliderRasterizeDetail);
                    EditorGUI.indentLevel--;
                }

                graph.terrainSampleSize = EditorGUILayout.IntField(new GUIContent("Terrain Sample Size", "Size of terrain samples. A lower value is better, but slower"), graph.terrainSampleSize);
                graph.terrainSampleSize = graph.terrainSampleSize < 1 ? 1 : graph.terrainSampleSize;                //Clamp to at least 1
                EditorGUI.indentLevel--;
            }

            graph.rasterizeMeshes    = EditorGUILayout.Toggle(new GUIContent("Rasterize Meshes", "Should meshes be rasterized and used for building the navmesh"), graph.rasterizeMeshes);
            graph.rasterizeColliders = EditorGUILayout.Toggle(new GUIContent("Rasterize Colliders", "Should colliders be rasterized and used for building the navmesh"), graph.rasterizeColliders);
            if (graph.rasterizeColliders)
            {
                EditorGUI.indentLevel++;
                graph.colliderRasterizeDetail = EditorGUILayout.FloatField(new GUIContent("Collider Detail", "Controls the detail of the generated collider meshes. " +
                                                                                          "Increasing does not necessarily yield better navmeshes, but lowering will speed up scan.\n" +
                                                                                          "Spheres and capsule colliders will be converted to meshes in order to be able to rasterize them, a higher value will increase the number of triangles in those meshes."), graph.colliderRasterizeDetail);
                EditorGUI.indentLevel--;
            }

            if (graph.rasterizeMeshes && graph.rasterizeColliders)
            {
                EditorGUILayout.HelpBox("You are rasterizing both meshes and colliders, this might just be duplicating the work that is done if the colliders and meshes are similar in shape. You can use the RecastMeshObj component" +
                                        " to always include some specific objects regardless of what the above settings are set to.", MessageType.Info);
            }

            Separator();

            graph.forcedBoundsCenter = EditorGUILayout.Vector3Field("Center", graph.forcedBoundsCenter);
            graph.forcedBoundsSize   = EditorGUILayout.Vector3Field("Size", graph.forcedBoundsSize);
            // Make sure the bounding box is not infinitely thin along any axis
            graph.forcedBoundsSize = Vector3.Max(graph.forcedBoundsSize, Vector3.one * 0.001f);
            graph.rotation         = EditorGUILayout.Vector3Field("Rotation", graph.rotation);

            if (GUILayout.Button(new GUIContent("Snap bounds to scene", "Will snap the bounds of the graph to exactly contain all meshes in the scene that matches the masks.")))
            {
                graph.SnapForceBoundsToScene();
                GUI.changed = true;
            }

            Separator();

            EditorGUILayout.HelpBox("Objects contained in any of these masks will be rasterized", MessageType.None);
            graph.mask     = EditorGUILayoutx.LayerMaskField("Layer Mask", graph.mask);
            tagMaskFoldout = EditorGUILayoutx.UnityTagMaskList(new GUIContent("Tag Mask"), tagMaskFoldout, graph.tagMask);

            graph.enableNavmeshCutting = EditorGUILayout.Toggle(new GUIContent("Affected by navmesh cuts", "Makes this graph affected by NavmeshCut and NavmeshAdd components. See the documentation for more info."), graph.enableNavmeshCutting);

            Separator();

            GUILayout.BeginHorizontal();
            GUILayout.Space(18);
            graph.showMeshSurface     = GUILayout.Toggle(graph.showMeshSurface, new GUIContent("Show surface", "Toggles gizmos for drawing the surface of the mesh"), EditorStyles.miniButtonLeft);
            graph.showMeshOutline     = GUILayout.Toggle(graph.showMeshOutline, new GUIContent("Show outline", "Toggles gizmos for drawing an outline of the nodes"), EditorStyles.miniButtonMid);
            graph.showNodeConnections = GUILayout.Toggle(graph.showNodeConnections, new GUIContent("Show connections", "Toggles gizmos for drawing node connections"), EditorStyles.miniButtonRight);
            GUILayout.EndHorizontal();


            Separator();
            GUILayout.Label(new GUIContent("Advanced"), EditorStyles.boldLabel);

            if (GUILayout.Button("Export to .obj file"))
            {
                ExportToFile(graph);
            }

            graph.relevantGraphSurfaceMode = (RecastGraph.RelevantGraphSurfaceMode)EditorGUILayout.EnumPopup(new GUIContent("Relevant Graph Surface Mode",
                                                                                                                            "Require every region to have a RelevantGraphSurface component inside it.\n" +
                                                                                                                            "A RelevantGraphSurface component placed in the scene specifies that\n" +
                                                                                                                            "the navmesh region it is inside should be included in the navmesh.\n\n" +
                                                                                                                            "If this is set to OnlyForCompletelyInsideTile\n" +
                                                                                                                            "a navmesh region is included in the navmesh if it\n" +
                                                                                                                            "has a RelevantGraphSurface inside it, or if it\n" +
                                                                                                                            "is adjacent to a tile border. This can leave some small regions\n" +
                                                                                                                            "which you didn't want to have included because they are adjacent\n" +
                                                                                                                            "to tile borders, but it removes the need to place a component\n" +
                                                                                                                            "in every single tile, which can be tedious (see below).\n\n" +
                                                                                                                            "If this is set to RequireForAll\n" +
                                                                                                                            "a navmesh region is included only if it has a RelevantGraphSurface\n" +
                                                                                                                            "inside it. Note that even though the navmesh\n" +
                                                                                                                            "looks continous between tiles, the tiles are computed individually\n" +
                                                                                                                            "and therefore you need a RelevantGraphSurface component for each\n" +
                                                                                                                            "region and for each tile."),
                                                                                                             graph.relevantGraphSurfaceMode);

            graph.nearestSearchOnlyXZ = EditorGUILayout.Toggle(new GUIContent("Nearest node queries in XZ space",
                                                                              "Recomended for single-layered environments.\nFaster but can be inacurate esp. in multilayered contexts."), graph.nearestSearchOnlyXZ);

            if (graph.nearestSearchOnlyXZ && (Mathf.Abs(graph.rotation.x) > 1 || Mathf.Abs(graph.rotation.z) > 1))
            {
                EditorGUILayout.HelpBox("Nearest node queries in XZ space is not recommended for rotated graphs since XZ space no longer corresponds to the ground plane", MessageType.Warning);
            }
        }