#cs ----------------------------------------------------------------------------

 AutoIt Version: 3.3.14.2
 Author:         alpines
 Date:			 17.05.2017

 Script Function:
	Mesh Visualizer der .mesh Dateien visualisiert welche
	mit der NavMesh.au3 komptatibel sind.

	Thread-Link: https://autoit.de/index.php/Thread/45414-A-Algorithmus-Pathfinding-AI

#ce ----------------------------------------------------------------------------

#include <GDIPlus.au3>
#include "NavMesh.au3"

_GDIPlus_Startup()

Global $aMesh
Global $hCherryBrush = _GDIPlus_BrushCreateSolid(0x55FF00BB), _
	   $hLeafPen     = _GDIPLUS_PenCreate(0xFF6DB33F, 2), _
	   $hGrayBrush	 = _GDIPlus_BrushCreateSolid(0xFFF0F0F0), _
	   $hRedPen  = _GDIPlus_PenCreate(0xFFFF0000, 2)

Global Const $I_LEFT  =   8, $I_TOP    = 120, _
			 $I_WIDTH = 591, $I_HEIGHT = 352

$hGUI = GUICreate("Mesh Visualizer ~ alpines @ autoit.de", 610, 482)
$hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)

GUICtrlCreateGroup("Einstellungen", 8, 8, 593, 105)

GUICtrlCreateLabel("Pfad zur Mesh-Datei:", 24, 32, 103, 17)
$hPath = GUICtrlCreateInput("", 136, 30, 257, 21)
$hSelectFile = GUICtrlCreateButton("...", 400, 29, 27, 23)

GUICtrlCreateLabel("Start Waypoint:", 24, 56, 77, 17)
$hStartWaypoint = GUICtrlCreateCombo("", 136, 54, 257, 25, 67)
GUICtrlSendMsg(-1, 5889, 100, 0)

GUICtrlCreateLabel("End Waypoint:", 24, 80, 74, 17)
$hEndWaypoint = GUICtrlCreateCombo("", 136, 78, 257, 25, 67)
GUICtrlSendMsg(-1, 5889, 100, 0)

$hCalculateWay = GUICtrlCreateButton("Berechne Weg", 456, 66, 131, 33)
$hLoadMesh = GUICtrlCreateButton("Lade Mesh", 456, 26, 131, 33)

GUISetState(@SW_SHOW, $hGUI)

While Sleep(10)
	Switch GUIGetMsg()
		Case -3
			_GDIPlus_PenDispose($hRedPen)
			_GDIPlus_BrushDispose($hGrayBrush)
			_GDIPlus_PenDispose($hLeafPen)
			_GDIPlus_BrushDispose($hCherryBrush)
			_GDIPlus_GraphicsDispose($hGraphics)
			_GDIPlus_Shutdown()
			Exit

		Case $hSelectFile
			$sFile = FileOpenDialog("Wähle eine .mesh-Datei", @ScriptDir, "Mesh-Datei (*.mesh)")
			If $sFile <> "" Then GUICtrlSetData($hPath, $sFile)

		Case $hLoadMesh
			$aMesh = _NavMesh_LoadMeshFromFile(GUICtrlRead($hPath))

			Local $sStartWaypoint = ""

			For $i = 0 To UBound($aMesh) - 1
				$sStartWaypoint &= $i & "   (" & $aMesh[$i][0] & ", " & $aMesh[$i][1] & ")   ["

				If UBound($aMesh, 2) > 2 Then
					For $j = 2 To UBound($aMesh, 2) - 1
						If $aMesh[$i][$j] <> "-1" Then $sStartWaypoint &= $aMesh[$i][$j] & ", "
					Next
				EndIf

				If StringRight($sStartWaypoint, 2) = ", " Then $sStartWaypoint = StringTrimRight($sStartWaypoint, 2)
				$sStartWaypoint &= "]|"

				If $i = UBound($aMesh) - 1 Then $sStartWaypoint = StringTrimRight($sStartWaypoint, 1)
			Next

			GUICtrlSetData($hStartWaypoint, "")
			GUICtrlSetData($hEndWaypoint, "")

			GUICtrlSetData($hStartWaypoint, $sStartWaypoint)
			GUICtrlSetData($hEndWaypoint, $sStartWaypoint)

			Local $__aTmp = StringSplit($sStartWaypoint, "|", 3)

			ControlCommand($hGUI, "", $hStartWaypoint, "SelectString", $__aTmp[0])
			ControlCommand($hGUI, "", $hEndWaypoint,   "SelectString", $__aTmp[UBound($__aTmp) - 1])

			_DrawGraph($aMesh)

		Case $hCalculateWay
			Local $sStart = GUICtrlRead($hStartWaypoint)
			Local $sEnd   = GUICtrlRead($hEndWaypoint)

			Local $iStart = Number(StringLeft($sStart, StringInStr($sStart, " ") - 1))
			Local $iEnd   = Number(StringLeft($sEnd,   StringInStr($sEnd,   " ") - 1))

			Local $aPath = _NavMesh_GetPath($iStart, $iEnd, $aMesh)
			_DrawGraph($aMesh, $aPath)

			Local $sPath = "", $iTravelDistance = 0

			For $i = 0 To UBound($aPath) - 1
				$sPath &= $aPath[$i] & "-"

				If $i < UBound($aPath) - 1 Then
					Local $aPos  = _NavMesh_GetCoordinatesByWaypoint($aPath[$i]    , $aMesh)
					Local $aPos_ = _NavMesh_GetCoordinatesByWaypoint($aPath[$i + 1], $aMesh)

					$iTravelDistance += _NavMesh_GetDistance($aPos[0], $aPos[1], $aPos_[0], $aPos_[1])
				EndIf
			Next

			$sPath = StringTrimRight($sPath, 1)

			MsgBox(64, "Pfad berechnet", "Der Weg von Wegpunkt " & $iStart & " zu " & $iEnd & " lautet: " & $sPath & @CRLF & _
										 "Die gerundete Distanz die man auf dem Weg zurücklegt ist: " & Round($iTravelDistance, 2))
	EndSwitch
WEnd

Func _DrawGraph($aMesh, $aPath = Null)
	;Zeichne Graphen
	_GDIPlus_GraphicsFillRect($hGraphics, $I_LEFT - 1, $I_TOP - 1, $I_WIDTH + 3, $I_HEIGHT + 3, $hGrayBrush)
	_GDIPlus_GraphicsDrawRect($hGraphics, $I_LEFT, $I_TOP, $I_WIDTH, $I_HEIGHT)

	For $i = 0 To UBound($aMesh) - 1
		Local $iOnScreenX = _GetOnScreenX($aMesh[$i][0], $aMesh)
		Local $iOnScreenY = _GetOnScreenY($aMesh[$i][1], $aMesh)

		;Zeichne Kanten
		If UBound($aMesh, 2) > 2 Then
			For $j = 2 To UBound($aMesh, 2) - 1
				If $aMesh[$i][$j] = "-1" Then ExitLoop

				Local $iOnScreenX_ = _GetOnScreenX($aMesh[$aMesh[$i][$j]][0], $aMesh)
				Local $iOnScreenY_ = _GetOnScreenY($aMesh[$aMesh[$i][$j]][1], $aMesh)

				_GDIPlus_GraphicsDrawLine($hGraphics, $iOnScreenX, $iOnScreenY, $iOnScreenX_, $iOnScreenY_)
			Next
		EndIf
	Next

	;Falls Pfad berechnet, zeichne Kanten blattgrün
	If $aPath <> Null Then
		For $i = 0 To UBound($aPath) - 2
			_GDIPlus_GraphicsDrawLine($hGraphics, _GetOnScreenX($aMesh[$aPath[$i]][0], $aMesh), _GetOnScreenY($aMesh[$aPath[$i]][1], $aMesh), _
												  _GetOnScreenX($aMesh[$aPath[$i + 1]][0], $aMesh), _GetOnScreenY($aMesh[$aPath[$i + 1]][1], $aMesh), $hLeafPen)
		Next
	EndIf

	For $i = 0 To UBound($aMesh) - 1
		Local $iOnScreenX = _GetOnScreenX($aMesh[$i][0], $aMesh)
		Local $iOnScreenY = _GetOnScreenY($aMesh[$i][1], $aMesh)

		;Zeichne Wegpunkte
		_GDIPlus_GraphicsFillEllipse($hGraphics, $iOnScreenX - 10, $iOnScreenY - 10, 20, 20, $hGrayBrush)
		_GDIPlus_GraphicsFillEllipse($hGraphics, $iOnScreenX - 10, $iOnScreenY - 10, 20, 20, $hCherryBrush)
		_GDIPlus_GraphicsDrawString($hGraphics, $i, $iOnScreenX - ($i >= 10 ? 9 : 5), $iOnScreenY - 8)
	Next

	;Falls Pfad berechnet, zeichne Wegpunkte kirschrot
	If $aPath <> Null Then
		_GDIPlus_GraphicsDrawEllipse($hGraphics, _GetOnScreenX($aMesh[$aPath[0]][0], $aMesh) - 10, _GetOnScreenY($aMesh[$aPath[0]][1], $aMesh) - 10, 20, 20, $hRedPen)
		_GDIPlus_GraphicsDrawEllipse($hGraphics, _GetOnScreenX($aMesh[$aPath[UBound($aPath) - 1]][0], $aMesh) - 10, _GetOnScreenY($aMesh[$aPath[UBound($aPath) - 1]][1], $aMesh) - 10, 20, 20, $hRedPen)
	EndIf
EndFunc

Func _GetOnScreenX($iX, $aMesh)
	Local $iMin = 9e99, $iMax = -9e99

	For $i = 0 To UBound($aMesh) - 1
		If $aMesh[$i][0] < $iMin Then $iMin = $aMesh[$i][0]
		If $aMesh[$i][0] > $iMax Then $iMax = $aMesh[$i][0]
	Next

	If $iMax >= 0 Then
		Return Round(($I_LEFT + 10) + (($iX - $iMin) / ($iMax - $iMin)) * ($I_WIDTH - 20), 0)
	ElseIf $iMax < 0 Then
		Return Round(($I_LEFT + 10) + (($iX - $iMin) / (-$iMin - $iMax)) * ($I_WIDTH - 20), 0)
	EndIf
EndFunc

Func _GetOnScreenY($iY, $aMesh)
	Local $iMin = 9e99, $iMax = -9e99

	For $i = 0 To UBound($aMesh) - 1
		If $aMesh[$i][1] < $iMin Then $iMin = $aMesh[$i][1]
		If $aMesh[$i][1] > $iMax Then $iMax = $aMesh[$i][1]
	Next

	If $iMax >= 0 Then
		Return Round(($I_TOP + 10) + (($iY - $iMin) / ($iMax - $iMin)) * ($I_HEIGHT - 20), 0)
	ElseIf $iMax < 0 Then
		Return Round(($I_TOP + 10) + (($iY - $iMin) / (-$iMin - $iMax)) * ($I_HEIGHT - 20), 0)
	EndIf
EndFunc
