public override void OnInspectorGUI() { if (!EditorPrefs.GetBool ("AstarInitialized")) { return; } //First the editor will do a series of checks to see if any assets are damaged or if there is a new version of the pathfinding system available AstarPath path = target as AstarPath; EditorGUIUtility.LookLikeInspector (); //Should we check for updates if (EditorPrefs.GetBool ("CheckForUpdates")) { GetUpdateNews (); } else { updateVersion = "noCheck"; } //This is the A* info bar at the top of the inspector GUIContent co = new GUIContent (version != updateVersion && updateVersion != "error" && updateVersion != "noCheck" ? "You are using an outdated version of this script" : "Your are using version "+version); Rect r = GUILayoutUtility.GetRect (co,EditorStyles.toolbarButton); GUI.BeginGroup (r); if (GUI.Button (new Rect (0,0,Screen.width,20),co,EditorStyles.toolbarButton)) { if (version != updateVersion && updateVersion != "" && updateVersion != "noCheck") { if (updateVersion == "error") { if (EditorUtility.DisplayDialog ("A* Pathfinding Project Info","You are using version "+version+" of the A* Pathfinding Project.\n\nHowever the update-check for the system failed, please make sure you have an internet connection or if that isn't the problem, visit the download page to find out the latest info.\n\nThe A* Pathfinding Project was made by\nAron Granberg","Go to download page","Close")) { Application.OpenURL ("http://arongranberg.com/unity/a-pathfinding"); } } else { if (EditorUtility.DisplayDialog ("A* Pathfinding Project Update","You are using version "+version+" of the A* Pathfinding Project. The latest version is "+updateVersion+".","Go to download page","Close")) { Application.OpenURL ("http://arongranberg.com/unity/a-pathfinding"); } } } else if (updateVersion != "noCheck") { EditorUtility.DisplayDialog ("A* Pathfinding Project Info","You are using version "+version+" of the A* Pathfinding Project, this is the latest version.\n\nThe A* Pathfinding Project was made by\nAron Granberg","Close"); } else { EditorUtility.DisplayDialog ("A* Pathfinding Project Info","You are using version "+version+" of the A* Pathfinding Project\n\nAutomatic update check is turned off, you can turn this on by changing the settings in \nWindow/A*/Welcome\n\nThe A* Pathfinding Project was made by\nAron Granberg","Close"); } } GUI.EndGroup (); if (singletonWarning) { co = new GUIContent ("There are more than one instance of the AstarPath script in the scene\n\nYou should never have more than one AstarPath script in the scene"); GUI.color = Color.red;//(GUILayoutUtility.GetRect (co,EditorStyles.toolbarButton,GUILayout.Height(60)) GUILayout.Button(co, EditorStyles.wordWrappedLabel); GUI.color = Color.white; return; } string[] iconNames = new string[11] { "grid","texture","mesh","bounds", "DontCutCorners_Off","DontCutCorners_On", "HeightFlat","HeightTerrain","HeightRaycast", "NeighboursFour","NeighboursEight" }; if (icons == null || icons[0] == null) { icons = new Texture[11]; for (int i=0;i<icons.Length;i++) { icons[i] = EditorGUIUtility.Load ("AstarSkin/Icons/"+iconNames[i]+".png") as Texture; } } //The script will now check if all icons/skins/styles required for this editor script to run exists in the project, and if not, point the user to a unitypackage which includes the missing files. bool allIconsAreFound = true; bool skinIsFound = true; bool styleIsFound = true; string missingIcons = ""; //Does all icons exist for (int i=0;i<icons.Length;i++) { if (icons[i] == null) { allIconsAreFound = false; missingIcons += "\n "+iconNames[i]+".png"; } } //Try to load the GUISkin GUISkin astarSkin = EditorGUIUtility.Load ("AstarSkin/AstarSkin.GUISkin") as GUISkin; if (astarSkin == null) { skinIsFound = false; //Check if the skin is just named to something else and still exists in the correct folder, but do not show an error message if the icons are also missing, since then the posability is large that all editor assets are missing and another error message should be shown Object folder = EditorGUIUtility.Load ("AstarSkin"); if (folder != null && allIconsAreFound) { EditorGUIUtility.PingObject (folder); //Move the selection to the folder where the skin should exist and search for GUISkins there Selection.activeObject = folder; Object[] ob = Selection.GetFiltered (typeof(GUISkin),SelectionMode.DeepAssets); //GUISkins where found if (ob.Length > 0) { astarSkin = ob[0] as GUISkin; string skinName = ob[0].name; if (astarSkin != null) { if (Event.current.type == EventType.Repaint) { //Display an error message if (EditorUtility.DisplayDialog ("Damaged Assets","The AstarSkin asset may be named incorrectly.\nFound a GUISkin named "+skinName+" but the correct name should be AstarSkin.","Change Name Automatically","Cancel")) { string success = AssetDatabase.RenameAsset ("Assets/Editor Default Resources/AstarSkin/"+skinName+".GUISkin","AstarSkin"); if (success == "") { EditorUtility.DisplayDialog ("Damaged Assets","The skin was renamed correctly","Ok"); EditorGUIUtility.PingObject (astarSkin); //Selection.activeObject = path.gameObject; } else { EditorUtility.DisplayDialog ("Damaged Assets","An error ocurred when renaming the skin:\n"+success,"Ok"); } AssetDatabase.Refresh (); return; } else { return; } } else { return; } } } } } //Only look for the style if the skin has been found if (skinIsFound) { separator = astarSkin.FindStyle ("separator"); if (separator == null) { styleIsFound = false; } GUIStyle minusButton = astarSkin.FindStyle ("MinusButton"); if (minusButton == null) { styleIsFound = false; } else if (minusButton.normal.background == null) { styleIsFound = false; } } //Display an error message if some editor resources are missing if (!allIconsAreFound || !styleIsFound || !skinIsFound) { if (Event.current.type == EventType.Repaint) { switch (EditorUtility.DisplayDialogComplex ("A* Editor Resources Not Found","Some A* editor resources are not found or are damaged, you can download a UnityPackage with the required editor assets or download a package with both editor resources and scripts.\nThe packages can also be found in the example project folder (outside the assets folder)." +(allIconsAreFound ? "" : "\n\nAll or some icons were not found, the correct location for the icons should be 'Assets/Editor Default Resources/AstarSkin/Icons/'.\n\nThe missing icon files are:"+missingIcons+"\n\nMake sure you haven't renamed the icons since importing a package wont work then.") +(skinIsFound ? "" : "\n\nThe AstarSkin was not found, the correct location should be 'Assets/Editor Default Resources/AstarSkin/'") +(styleIsFound ? "" : "\n\nThe AstarSkin asset is damaged, please download and import the asset again") ,"Download Editor Assets","Cancel","Download All Required Assets")) { case 0: Application.OpenURL ("http://arongranberg.com/wp-content/uploads/astarpathfinding/editorAssets2_5.unitypackage"); return; case 1: return; case 2: Application.OpenURL ("http://arongranberg.com/wp-content/uploads/astarpathfinding/allRequiredAssets2_5.unitypackage"); return; } } else { return; } } GUIStyle labelStyle = EditorStyles.miniLabel; labelStyle.wordWrap = true; settings = (AstarTab)GUILayout.Toolbar ((int)settings,new string [4] {"Static Settings","Runtime Settings","Node Links","Debug"}); EditorGUILayout.Separator (); //LINKS if (settings == AstarTab.Links) { path.showLinks = GUILayout.Toggle (path.showLinks,"Show Links","Button"); Color preCol = GUI.color; GUI.color = new Color (0,0.5F,0); if (linkClickStatus == 2) { GUILayout.Label ("And now click on a second node which will be the end node",EditorStyles.whiteLabel); } else if (Event.current.shift) { GUILayout.Label ("Now click on a node to make it the start node",EditorStyles.whiteLabel); } else { GUI.color = new Color (0,0.0F,0); GUILayout.Label ("Hold shift in the scene view to create links easier\n\nYou can click on links in the scene view to select them\nbut be sure you use the move tool otherwise the it wont work\n\nClick on links with ctrl pressed to remove links",EditorStyles.whiteLabel); } GUI.color = preCol; if (GUILayout.Button ("Add Link")) { ArrayList a= new ArrayList (path.links); a.Add (new NodeLink ()); path.links = a.ToArray (typeof(NodeLink)) as NodeLink[]; Repaint (); HandleUtility.Repaint (); } for (int i=0;i<path.links.Length;i++) { EditorGUILayout.BeginHorizontal (); if (GUILayout.Toggle (selectedLink == i,"Link "+i,"Button")) { selectedLink = i; } if (GUILayout.Button ("Remove",GUILayout.MaxWidth (70))) { RemoveLink (i); break; } EditorGUILayout.EndHorizontal (); if (selectedLink==i) { NodeLink link = path.links[i]; //GUILayout.Label ("Offset"); //grid.offset.x = EditorGUILayout.FloatField ("X",grid.offset.x); //grid.offset.y = EditorGUILayout.FloatField ("Y",grid.offset.y); //grid.offset.z = EditorGUILayout.FloatField ("Z",grid.offset.z); link.fromVector = Vector3Field ("From",link.fromVector); if (link.linkType == LinkType.Link || link.linkType == LinkType.Disabler) { link.toVector = Vector3Field ("To",link.toVector); } GUILayout.BeginHorizontal (); GUILayout.FlexibleSpace (); if (link.oneWay && GUILayout.Button ("Reverse")) { Vector3 tmpVector = link.fromVector; link.fromVector = link.toVector; link.toVector = tmpVector; } link.oneWay = GUILayout.Toggle (link.oneWay,"One Way","Button"); GUILayout.EndHorizontal (); link.linkType = (LinkType)GUILayout.Toolbar ((int)link.linkType,new string[3] { "Link", "NodeDisabler", "NodeEnabler" }); } } } //Static Settings if (settings == AstarTab.Static) { //GRIDS START path.showGrid = GUILayout.Toggle (path.showGrid,"Show Grid","Button"); path.gridGenerator = (GridGenerator)GUILayout.SelectionGrid ((int)path.gridGenerator,new GUIContent [6] { new GUIContent ("Grid",icons[0]), new GUIContent ("Texture",icons[1]), new GUIContent ("Mesh",icons[2]), new GUIContent ("Bounds",icons[3]), new GUIContent ("List"), new GUIContent ("Procedural") }, 3,GUILayout.Height (40)); EditorGUILayout.Separator (); if (path.gridGenerator == GridGenerator.Grid || path.gridGenerator == GridGenerator.Texture) { path.dontCutCorners = GUILayout.Toggle (path.dontCutCorners,new GUIContent ("Dont Cut Corners",(path.dontCutCorners ? icons[5] : icons[4])) , "Button"); } path.cachePaths = GUILayout.Toggle (path.cachePaths, "Cache Paths", "Button"); if (path.cachePaths) { path.cacheLimit = EditorGUILayout.IntField ("Cache Limit",path.cacheLimit); path.cacheTimeLimit = EditorGUILayout.FloatField ("Cache Time Limit",path.cacheTimeLimit); } EditorGUILayout.Separator (); if (path.gridGenerator == GridGenerator.Grid) { string listTooltip = "This list contains all grids, this also works as a priority list, the higher up a grid is in the list the higher priority it has.\nIf a small grid is inside a big grid you would want the smaller grid to have a higher priority, to do so you can move it higher up"; EditorGUILayout.Separator (); showGrids = EditorGUILayout.Foldout (showGrids,new GUIContent ("Grids",listTooltip)); if (showGrids) { EditorGUILayout.BeginHorizontal (); EditorGUILayout.Space (); EditorGUILayout.Space (); EditorGUILayout.BeginVertical (); if (GUILayout.Button ("Add Grid")) { ArrayList a= new ArrayList (path.grids); a.Add (new Grid (100)); path.grids = a.ToArray (typeof(Grid)) as Grid[]; Scan (); } //Reset the variable each OnGUI so it will not get turned on and then stay like that forever //path.anyPhysicsChanged = false; for (int i=0;i<path.grids.Length;i++) { Grid grid = path.grids[i]; EditorGUILayout.BeginHorizontal (); grid.showInEditor = EditorGUILayout.Foldout (grid.showInEditor,grid.name == "New Grid" ? "Grid "+i : grid.name); if (GUILayout.Button ("Remove",astarSkin.GetStyle ("MinusButton"))) { ArrayList a= new ArrayList (path.grids); a.RemoveAt (i); path.grids = a.ToArray (typeof(Grid)) as Grid[]; Scan (); break; } if (GUILayout.Button (new GUIContent ("Move Up",listTooltip),astarSkin.GetStyle ("ArrowUp")) && i > 0) { Grid tmpGrid = path.grids[i-1]; path.grids[i-1] = path.grids[i]; path.grids[i] = tmpGrid; break; } if (GUILayout.Button (new GUIContent ("Move Down",listTooltip),astarSkin.GetStyle ("ArrowDown")) && i < path.grids.Length-1) { Grid tmpGrid = path.grids[i+1]; path.grids[i+1] = path.grids[i]; path.grids[i] = tmpGrid; break; } GUILayout.FlexibleSpace (); EditorGUILayout.EndHorizontal (); EditorGUILayout.BeginHorizontal (); EditorGUILayout.Space (); EditorGUILayout.BeginVertical (); if (grid.showInEditor) { bool preChange = GUI.changed; GUI.changed = false; grid.debug = GUILayout.Toggle (grid.debug,"Show Debug"); //grid.name = EditorGUILayout.TextField ("Name",grid.name); grid.width = EditorGUILayout.IntField ("Grid Width",grid.width); grid.globalWidth = grid.width-1; grid.depth = EditorGUILayout.IntField ("Grid Depth",grid.depth); grid.globalDepth = grid.depth-1; grid.nodeSize = EditorGUILayout.FloatField ("Node Size",grid.nodeSize); grid.height = EditorGUILayout.FloatField ("Height",grid.height); //EditorGUILayout.BeginHorizontal (); grid.offset = Vector3Field ("Offset",grid.offset); //GUILayout.Label ("Offset",GUILayout.Width (100)); //grid.offset.x = EditorGUILayout.FloatField ("X",grid.offset.x,GUILayout.Width (70)); //grid.offset.y = EditorGUILayout.FloatField ("Y",grid.offset.y,GUILayout.Width (70)); //grid.offset.z = EditorGUILayout.FloatField ("Z",grid.offset.z,GUILayout.Width (70)); //EditorGUILayout.EndHorizontal (); grid.showPhysics = EditorGUILayout.Foldout (grid.showPhysics,new GUIContent ("Physics","The settings here determines how the script will check for obstacles")); if (grid.showPhysics) { //Physics Check START bool preGUIChanged = GUI.changed; GUI.changed = false; EditorGUILayout.BeginHorizontal (); GUILayout.Space (14); EditorGUILayout.BeginVertical (); EditorGUILayout.BeginHorizontal (); GUILayout.Label ("Walkable Check"); grid.physicsType = (PhysicsType)GUILayout.Toolbar (((int)grid.physicsType),new string [4] {"Overlap","Touch","Capsule","Raycast"}); EditorGUILayout.EndHorizontal (); if (grid.physicsType==PhysicsType.OverlapSphere) { grid.physicsRadius = EditorGUILayout.FloatField ("Radius",grid.physicsRadius); grid.ignoreLayer = EditorGUILayout.LayerField ("Ignore Layer",grid.ignoreLayer); } else if (grid.physicsType==PhysicsType.TouchCapsule) { grid.capsuleHeight = EditorGUILayout.FloatField ("Height",grid.capsuleHeight); grid.physicsRadius = EditorGUILayout.FloatField ("Radius",grid.physicsRadius); grid.physicsMask = LayerMaskField(grid.physicsMask); } else if (grid.physicsType==PhysicsType.Raycast) { grid.physicsMask = LayerMaskField(grid.physicsMask); EditorGUILayout.BeginHorizontal (); //GUILayout.Label ("Direction"); GUILayout.Label ("Direction"); grid.raycastUpDown = (UpDown)GUILayout.Toolbar (((int)grid.raycastUpDown),new string [2] {"Up","Down"}); EditorGUILayout.EndHorizontal (); grid.raycastLength = EditorGUILayout.FloatField ("Length",grid.raycastLength); } else if (grid.physicsType==PhysicsType.TouchSphere) { grid.physicsRadius = EditorGUILayout.FloatField ("Radius",grid.physicsRadius); grid.physicsMask = LayerMaskField(grid.physicsMask); } EditorGUILayout.EndVertical (); EditorGUILayout.EndHorizontal (); //if (GUI.changed) { // path.physicsChangedGrid = lOutIndex; // path.anyPhysicsChanged = true; //} GUI.changed = GUI.changed || preGUIChanged; //Physics Check END } if (GUI.changed) { grid.changed = true; anyGridsChanged = true; } GUI.changed = GUI.changed ? GUI.changed : preChange; } EditorGUILayout.EndVertical (); EditorGUILayout.EndHorizontal (); } EditorGUILayout.EndVertical (); EditorGUILayout.EndHorizontal (); } EditorGUILayout.Separator (); GUILayout.Box ("",separator); //GRIDS END //Y POSITION EditorGUILayout.BeginHorizontal (); GUILayout.Label ("Y position"); path.heightMode = (Height)GUILayout.Toolbar (((int)path.heightMode),new GUIContent[3] { new GUIContent ("Flat",icons[6]), new GUIContent ("Terrain",icons[7]), new GUIContent ("Raycast",icons[8]) }); EditorGUILayout.EndHorizontal (); if (path.heightMode == Height.Raycast) { path.heightRaycast = EditorGUILayout.FloatField ("From Height",path.heightRaycast); path.useNormal = GUILayout.Toggle (path.useNormal,"Use normal for max angle calculation","Button"); path.staticMaxAngle = EditorGUILayout.Slider (new GUIContent ("Static Max Angle", path.useNormal ? "If a normal of a node or an angle between two nodes exceed the static max angle value it will be considered as unwalkable with these settings" : "If an angle between two nodes exceed the static max angle value it will be considered as unwalkable with these settings" ), path.staticMaxAngle,0.0F,90.0F); path.groundLayer = LayerMaskField(path.groundLayer); } else if (path.heightMode == Height.Terrain) { path.staticMaxAngle = EditorGUILayout.Slider (new GUIContent ("Static Max Angle", "Note: Static Max Angle works best with raycast mode since it can use normals and angles instead of just angles which is the only thing terrain mode can use.\n\nIf an angle between two nodes exceed the static max angle value it will be considered as unwalkable") ,path.staticMaxAngle,0.0F,90.0F); } EditorGUILayout.Separator (); } if (path.gridGenerator == GridGenerator.Texture) { RenderTextureSettings (); } if (path.gridGenerator == GridGenerator.Mesh) { RenderMeshSettings (); } if (path.gridGenerator == GridGenerator.Procedural) { RenderProceduralSettings (); } GUILayout.BeginHorizontal (); GUILayout.Space (4); GUILayout.BeginVertical (); if (path.gridGenerator == GridGenerator.Bounds) { path.boundsTag = EditorGUILayout.TagField ("Used Tag",path.boundsTag); path.neighbourDistanceLimit = EditorGUILayout.FloatField ("Neighbour Distance Limit",path.neighbourDistanceLimit); path.boundMargin = EditorGUILayout.FloatField ("Margin",path.boundMargin); path.boundsRayHitMask = LayerMaskField (path.boundsRayHitMask); path.boundsMargin = EditorGUILayout.FloatField ("Grid Bounds Margin",path.boundsMargin); path.yLimit = EditorGUILayout.FloatField ("Y Limit",path.yLimit); } if (path.gridGenerator == GridGenerator.List) { path.neighbourDistanceLimit = EditorGUILayout.FloatField ("Neighbour Distance Limit",path.neighbourDistanceLimit); path.boundMargin = EditorGUILayout.FloatField ("Margin",path.boundMargin); path.boundsRayHitMask = LayerMaskField (path.boundsRayHitMask); path.boundsMargin = EditorGUILayout.FloatField ("Grid Bounds Margin",path.boundsMargin); path.yLimit = EditorGUILayout.FloatField ("Y Limit",path.yLimit); path.listRootNode = EditorGUILayout.ObjectField ("Root Node",path.listRootNode,typeof (Transform)) as Transform; } GUILayout.EndHorizontal (); GUILayout.EndVertical (); GUILayout.Box ("",separator); if (path.gridGenerator == GridGenerator.Grid || path.gridGenerator == GridGenerator.Texture) { EditorGUILayout.Separator (); EditorGUILayout.BeginHorizontal (); GUILayout.Label ("Neighbours"); path.isNeighbours = (IsNeighbour)GUILayout.Toolbar (((int)path.isNeighbours),new GUIContent [2] { new GUIContent ("Eight",icons[10]), new GUIContent ("Four",icons[9]) }); EditorGUILayout.EndHorizontal (); EditorGUILayout.Separator (); } path.heapSize = EditorGUILayout.Slider ("Heap Size",path.heapSize,0.0F,1.0F); if (path.gridGenerator == GridGenerator.Texture) { if (path.navTex == null) { GUI.color = Color.red; if (GUILayout.Button ("Scan Map")) { EditorUtility.DisplayDialog ("Can't Generate Navmesh","Please assign a navigation texture","Ok"); } GUI.color = Color.white; } else { if (GUILayout.Button ("Scan Map")) { Scan (); path.showGrid = true; } } } else if (path.gridGenerator == GridGenerator.Mesh) { if (path.navmesh == null) { GUI.color = Color.red; if (GUILayout.Button ("Scan Map")) { EditorUtility.DisplayDialog ("Can't Generate Navmesh","Please assign a navmesh","Ok"); } GUI.color = Color.white; } else { if (GUILayout.Button ("Scan Map")) { Scan (); path.showGrid = true; } } } else if (path.gridGenerator == GridGenerator.List) { if (path.listRootNode == null) { GUI.color = Color.red; if (GUILayout.Button ("Scan Map")) { EditorUtility.DisplayDialog ("Can't Generate Navmesh","Please assign a root node","Ok"); } GUI.color = Color.white; } else { if (GUILayout.Button ("Scan Map")) { Scan (); path.showGrid = true; } } } else { if (anyGridsChanged) { GUI.color = Color.green; } if (GUILayout.Button ("Scan Map")) { Scan (); path.showGrid = true; } GUI.color = Color.white; } path.calculateOnStartup = GUILayout.Toggle (path.calculateOnStartup,new GUIContent ("Calculate Grid On Startup","Do you want to calculate the grid when the game starts?\nIf not you will have to manually call Scan () to calculate the grid attach a AstarSerializer component and call Load () to load the grid from saved data"),"Button"); } //Start for Runtime settings -----------------------> if (settings == AstarTab.Runtime) { EditorGUILayout.BeginHorizontal (); GUILayout.Label ("Simplification"); path.simplify = (Simplify)GUILayout.Toolbar (((int)path.simplify),new GUIContent [3] {new GUIContent ("None"),new GUIContent ("Simple","Removes nodes so there are only two nodes for each line, not one node for every step"),new GUIContent ("Full","Tests if there is a better way to travel along the path and removes all nodes which are not neccecery")}); EditorGUILayout.EndHorizontal (); EditorGUILayout.Separator (); path.maxFrameTime = EditorGUILayout.FloatField ("Max Frame Time",path.maxFrameTime); path.maxPathsPerFrame = EditorGUILayout.IntField ("Max Paths per Frame",path.maxPathsPerFrame); path.levelCost = EditorGUILayout.IntField (new GUIContent ("Grid to grid cost","The cost for moving from one grid to another\nThe cost from one node to another is 10 or 14 for diagonal"),path.levelCost); EditorGUILayout.Separator (); path.testStraightLine = GUILayout.Toggle (path.testStraightLine,new GUIContent ("Straight Line Testing","Tests if there is a straight line directly to the target first"),"Button"); EditorGUILayout.Separator (); path.lineAccuracy = EditorGUILayout.FloatField (new GUIContent ("Line Test Accuracy" ,"Used for simplification and for straight line testing, lower is better"), path.lineAccuracy); EditorGUILayout.BeginHorizontal (); GUILayout.Label ("Formula"); path.formula = (Formula)GUILayout.Toolbar (((int)path.formula),new GUIContent [3] { new GUIContent ("HG","H+G, this is what is commonly used in A*, the cost of moving to this point (G) plus the estimated distance to the target (H)"), new GUIContent ("H","H (the heuristic) uses only the estimated distance to the end\nthis is the fastest option but has the lowest accuracy"), new GUIContent ("G","G uses only the cost of moving to this point (the current node), this is the slowest option but with the best accuracy.\nThis formula is also often refered to as Dijkstra's algorithm.") }); EditorGUILayout.EndHorizontal (); //'Use World Position' Setting if (path.useWorldPositions == false && (path.gridGenerator == GridGenerator.Mesh || path.gridGenerator == GridGenerator.Bounds || path.gridGenerator == GridGenerator.List || path.gridGenerator == GridGenerator.Procedural)) { GUI.backgroundColor = Color.red; GUILayout.Label ("WARNING: It is recomended to use 'World Positions' when using the 'Mesh', 'List' or the 'Bounds' generator, otherwise you might end up with strange paths",EditorStyles.wordWrappedLabel); } EditorGUILayout.BeginHorizontal (); GUILayout.Label ("H calculation"); path.useWorldPositions = GUILayout.Toolbar ((path.useWorldPositions == true ? 1 : 0),new GUIContent [2] { new GUIContent ("Array Positions","Uses the nodes array position to calculate an H value from, recomended for the 'Texture' and 'Grid' generators"), new GUIContent ("World Positions","Uses the world position of the node to calculate an H value from, recomended for the 'Mesh', 'List' and 'Bounds' generators") }) == 1 ? true : false; GUI.backgroundColor = Color.white; EditorGUILayout.EndHorizontal (); //End 'Use World Position' Setting } //Start for Debug settings -----------------------> if (settings == AstarTab.Debug) { path.showGrid = GUILayout.Toggle (path.showGrid,"Show Grid","Button"); path.showGridBounds = GUILayout.Toggle (path.showGridBounds,"Show Grid Bounds","Button"); GUILayout.Box ("",separator); GUILayout.Label ("Hold shift in the Scene View to show debug info for the nodes",EditorStyles.miniLabel); path.showUnwalkable = GUILayout.Toggle (path.showUnwalkable,"Show Unwalkable nodes","Button"); path.debugMode = (DebugMode)GUILayout.Toolbar (((int)path.debugMode),new GUIContent[5] {new GUIContent ("Areas"),new GUIContent ("Angles"),new GUIContent ("H","H is called the heuristic value\nit is the estimated cost of moving to the target"),new GUIContent ("G","G is the distance from the start to the current node"),new GUIContent ("F","F is most often H+G (see Formula setting for more info) but can be different depending on what settings are used in the Runtime Settings")}); if (path.debugMode == DebugMode.H || path.debugMode == DebugMode.G || path.debugMode == DebugMode.F) { if (!Application.isPlaying) { GUILayout.Label ("The H, G & F values are runtime values, you won't see anything in editmode",labelStyle); } path.debugModeRoof = EditorGUILayout.FloatField ("Max Value",path.debugModeRoof); } EditorGUILayout.Separator (); path.onlyShowLastPath = GUILayout.Toggle (path.onlyShowLastPath,new GUIContent ("Only Show Last Path","In play mode, if this is true, only the nodes which were searched in the last path will be showed"),"Button"); path.showParent = GUILayout.Toggle (path.showParent,new GUIContent ("Show Search Tree","In play mode, if this is true all nodes will point towards their parents showing the search tree"),"Button"); GUILayout.Box ("",separator); //GUILayout.Space (10); if (path.staticNodes != null) { GUILayout.Label ("Grid Contains:\n"+AstarPath.totalNodeAmount+" Nodes ("+path.GetWalkableNodeAmount ()+" Walkable and "+path.GetUnwalkableNodeAmount ()+" Unwalkable)\n" +path.area+" Areas\n"); } else { GUILayout.Label ("No Info Available"); } GUILayout.Box ("",separator); if (GUILayout.Button ("Documentation")) { Application.OpenURL ("http://arongranberg.com/unity/a-pathfinding/docs/"); } isReportingBug = GUILayout.Toggle (isReportingBug,"Report Bug","Button"); if (isReportingBug) { EditorGUIUtility.LookLikeControls (); //GUI.color = new Color (0.5F,0.5F,0.5F,1F); GUILayout.BeginHorizontal (); GUILayout.Label ("Email"); bugReportEmail = EditorGUILayout.TextField ("",bugReportEmail,GUILayout.MinWidth (250)); GUILayout.EndHorizontal (); GUILayout.Label ("Message"); bugReportText = EditorGUILayout.TextArea (bugReportText,GUILayout.MinHeight (200)); if (GUILayout.Button ("Send Bug Report")) { path.SendBugReport (bugReportEmail,bugReportText); EditorUtility.DisplayDialog ("Thank You!","Your bug report has been sent!","Ok"); isReportingBug = false; bugReportText = ""; } /*if (path.reportReturnMessage != "") { path.reportReturnMessage = ""; isReportingBug = false; bugReportText = ""; EditorUtility.DisplayDialog ("Thank You!","Your bug report has been sent!","Ok"); }*/ } } if (GUI.changed) { EditorUtility.SetDirty (target); } }
public override void OnInspectorGUI () { if (!EditorPrefs.GetBool ("AstarInitialized")) { return; } //First the editor will do a series of checks to see if any assets are damaged or if there is a new version of the pathfinding system available EditorGUIUtility.LookLikeInspector (); RunDamagedAssetsCheck (); RenderUpdateBar (); //Make sure there's only one instance of the A* Path gameObject in the scene if (singletonWarning) { GUIContent co = new GUIContent ("There are more than one instance of the AstarPath script in the scene\n\nYou should never have more than one AstarPath script in the scene"); GUI.color = Color.red; GUILayout.Button (co); GUI.color = Color.white; return; } GUIStyle labelStyle = EditorStyles.miniLabel; labelStyle.wordWrap = true; settings = (AstarTab)GUILayout.Toolbar ((int)settings,new string [4] {"Static Settings","Runtime Settings","Node Links","Debug"}); EditorGUILayout.Separator (); //LINKS if (settings == AstarTab.Links) { RenderLinkSettings (); } //Static Settings if (settings == AstarTab.Static) { RenderStaticSettings (); } //Start Runtime settings -----------------------> if (settings == AstarTab.Runtime) { RenderRuntimeSettings (); } //Start Debug Settings -----------------------> if (settings == AstarTab.Debug) { RenderDebugSettings (labelStyle); } if (GUI.changed) { EditorUtility.SetDirty (target); } }