#include <Color.au3>
#include <GDIP.au3>
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <Array.au3>

Opt("GUIOnEventMode", 1)

Global $iWidth = @DesktopWidth;*0.3
Global $iHeight = @DesktopHeight;*0.3

_GDIPlus_Startup()

Global $nColor = 0x0000FF00
Global $iLineW = 4
Global $iLineCntH = 4
Global $iSpeed = 10
Global $aItem[7]
$aItem[0] = -1

Global $hPath = _GDIPlus_PathCreate($FillModeWinding)
For $i = 0 To 500 - $iLineW Step (500 - $iLineW) / $iLineCntH
	_GDIPlus_PathAddRectangle($hPath, 0, $i, 1000, $iLineW)
Next
Global $aBounds = _GDIPlus_PathGetWorldBounds($hPath)
;_ArrayDisplay($aBounds)

Global $hGui = GUICreate("Test", $iWidth, $iHeight, 0, 0, $WS_POPUP)
GUISetOnEvent($GUI_EVENT_CLOSE, "_EXIT")
Global $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGui)
Global $hBmpBuffer = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $hGraphics)
Global $hGfxBuffer = _GDIPlus_ImageGetGraphicsContext($hBmpBuffer)
_GDIPlus_GraphicsSetSmoothingMode($hGfxBuffer, 2)
_GDIPlus_GraphicsClear($hGfxBuffer, 0xFF000000)

Global $aBrush[4]
Global $hBrush = _GDIPlus_BrushCreateSolid(0xFFFF0000)
Global $hPen = _GDIPlus_PenCreate(0xFFFFFFFF)

GUIRegisterMsg($WM_PAINT, "WM_PAINT")
GUIRegisterMsg($WM_ERASEBKGND, "WM_ERASEBKGND")
GUIRegisterMsg($WM_MOUSEWHEEL, "_WM_MOUSEWHEEL")
GUISetState()

_WinAPI_ShowCursor(False)
Global $iStep = 0, $iMX, $iMY
While 1
	$iMX = MouseGetPos(0)
	$iMY = MouseGetPos(1)
	$iStep += $iSpeed
	$aItem[0] -= $iSpeed
	_GDIPlus_GraphicsClear($hGfxBuffer, 0xFF000000)
	_DrawTunnel($hGfxBuffer, $hPath, $aBounds, $iStep, 8, $iWidth, $iHeight, $iMX, $iMY, 0.06)
	If $aItem[0] > 0 Then
		_DrawItem($hGfxBuffer, $aItem, $iWidth, $iHeight, $iMX, $iMY, 0.06)
	Else
		If Random(0, 10, 1) = 5 Then
			$aItem[2] = Random(20, 50, 1)
			$aItem[3] = Random(50, 400, 1)
			$aItem[5] = Random(50, 400, 1)

			$aItem[0] = 1000 - $aItem[2]
			$aItem[1] = Random(0, $iHeight - $aItem[3] * 2, 1)

			$aItem[4] = Random(0, $iWidth - $aItem[5], 1)
		EndIf
	EndIf
	_GDIPlus_GraphicsDrawRect($hGfxBuffer, $iWidth / 2 - 60, 10, 120, 20, $hPen)
	If $iSpeed < 0 Then
		_GDIPlus_GraphicsFillRect($hGfxBuffer, $iWidth / 2 - 20 + $iSpeed, 11, -$iSpeed, 18, $hBrush)
	Else
		_GDIPlus_GraphicsFillRect($hGfxBuffer, $iWidth / 2 - 20, 11, $iSpeed, 18, $hBrush)
	EndIf
	_GDIPlus_GraphicsDrawImage($hGraphics, $hBmpBuffer, 0, 0)
	Sleep(10)
WEnd

Func _DrawItem($hGraphics, $aItem, $iW, $iH, $iMX, $iMY, $nBS)
	Local $hPath = _GDIPlus_PathCreate($FillModeWinding)
	_GDIPlus_PathAddRectangle($hPath, $aItem[0], $aItem[1], $aItem[2], $aItem[3])
	Local $hPath2 = _GDIPlus_PathClone($hPath)
	Local $aPoints[5][2] = [[4]]
	$aPoints[1][0] = $aItem[4]
	$aPoints[1][1] = 0
	$aPoints[3][0] = $aItem[4]
	$aPoints[3][1] = $iH
	$aPoints[2][0] = $iMX - $iW / 2 * $nBS + $aItem[4] * $nBS
	$aPoints[2][1] = $iMY - $iH / 2 * $nBS
	$aPoints[4][0] = $iMX - $iW / 2 * $nBS + $aItem[4] * $nBS
	$aPoints[4][1] = $iMY + $iH / 2 * $nBS
	_GDIPlus_PathWarp($hPath, 0, $aPoints, 0, 0, 1000, 500)

	$aPoints[1][0] = $aItem[4] + $aItem[5]
	$aPoints[1][1] = 0
	$aPoints[3][0] = $aItem[4] + $aItem[5]
	$aPoints[3][1] = $iH
	$aPoints[2][0] = $iMX - $iW / 2 * $nBS + ($aItem[4] + $aItem[5]) * $nBS
	$aPoints[2][1] = $iMY - $iH / 2 * $nBS
	$aPoints[4][0] = $iMX - $iW / 2 * $nBS + ($aItem[4] + $aItem[5]) * $nBS
	$aPoints[4][1] = $iMY + $iH / 2 * $nBS
	_GDIPlus_PathWarp($hPath2, 0, $aPoints, 0, 0, 1000, 500)

	Local $aData = _GDIPlus_PathGetData($hPath)
	Local $aData2 = _GDIPlus_PathGetData($hPath2)

	For $i = 1 To $aData[0][0]
		_GDIPlus_PathAddLine($hPath, $aData[$i][0], $aData[$i][1], $aData2[$i][0], $aData2[$i][1])
		_GDIPlus_PathCloseFigure($hPath)
	Next
	_GDIPlus_PathAddPath($hPath, $hPath2)
	_GDIPlus_PenDispose($aItem[6])
	$aItem[6] = _GDIPlus_PenCreate(BitOR(BitShift(0xFF - (0xFF * $aItem[0] / 1000), -24), 0x00FFFFFF))
	_GDIPlus_GraphicsDrawPath($hGraphics, $hPath, $aItem[6])

	_GDIPlus_PathDispose($hPath)
	_GDIPlus_PathDispose($hPath2)
EndFunc   ;==>_DrawItem


Func _WM_MOUSEWHEEL($hWnd, $Msg, $wParam, $lParam)
	If $hWnd <> $hGui Then Return $GUI_RUNDEFMSG
	Local $bDown = True
	If BitShift($wParam, 16) > 0 Then $bDown = False
	Switch $bDown
		Case False
			$iSpeed += 1
		Case Else
			$iSpeed -= 1
	EndSwitch
	If $iSpeed > 80 Then $iSpeed = 80
	If $iSpeed < -40 Then $iSpeed = -40
	Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_MOUSEWHEEL


Func _DrawTunnel($hGraphics, $hPath, $aBounds, ByRef $nOffset, $iCnt, $iW, $iH, $iMX, $iMY, $nBS)
	Local $hPathTemp = _GDIPlus_PathClone($hPath)
	If $nOffset >= (1000 - $iLineW) / $iCnt Then $nOffset -= (1000 - $iLineW) / $iCnt
	If $nOffset <= -((1000 - $iLineW) / $iCnt) Then $nOffset += (1000 - $iLineW) / $iCnt
	For $i = 0 To 1000 - $iLineW Step (1000 - $iLineW) / $iCnt
		If $i - $nOffset < 0 Then ContinueLoop
		_GDIPlus_PathAddRectangle($hPathTemp, $i - $nOffset, 0, $iLineW, 500)
	Next
	Local $aPoints[5][2] = [[4]]
	For $i = 0 To 3
		$hPathClone = _GDIPlus_PathClone($hPathTemp)
		Switch $i
			Case 0
				$aPoints[1][0] = 0
				$aPoints[1][1] = $iH
				$aPoints[2][0] = $iMX - $iW / 2 * $nBS
				$aPoints[2][1] = $iMY + $iH / 2 * $nBS
				$aPoints[3][0] = $iW
				$aPoints[3][1] = $iH
				$aPoints[4][0] = $iMX + $iW / 2 * $nBS
				$aPoints[4][1] = $iMY + $iH / 2 * $nBS
				_GDIPlus_BrushDispose($aBrush[$i])
				$aBrush[$i] = _GDIPlus_LineBrushCreate(0, $iH, 0, $iMY + $iH / 2 * $nBS, BitOR(0xFF000000, $nColor), 0xFF000000, 1)
				_GDIPlus_PathWarp($hPathClone, 0, $aPoints, 0, 0, 1000, 500)
			Case 1
				$aPoints[3][0] = 0
				$aPoints[3][1] = 0
				$aPoints[1][0] = $iW
				$aPoints[1][1] = 0
				$aPoints[4][0] = $iMX - $iW / 2 * $nBS
				$aPoints[4][1] = $iMY - $iH / 2 * $nBS
				$aPoints[2][0] = $iMX + $iW / 2 * $nBS
				$aPoints[2][1] = $iMY - $iH / 2 * $nBS
				_GDIPlus_BrushDispose($aBrush[$i])
				$aBrush[$i] = _GDIPlus_LineBrushCreate(0, 0, 0, $iMY - $iH / 2 * $nBS, BitOR(0xFF000000, $nColor), 0xFF000000, 1)
				_GDIPlus_PathWarp($hPathClone, 0, $aPoints, 0, 0, 1000, 500)
			Case 2
				$aPoints[2][0] = $iMX - $iW / 2 * $nBS
				$aPoints[2][1] = $iMY - $iH / 2 * $nBS
				$aPoints[4][0] = $iMX - $iW / 2 * $nBS
				$aPoints[4][1] = $iMY + $iH / 2 * $nBS
				$aPoints[1][0] = 0
				$aPoints[1][1] = 0
				$aPoints[3][0] = 0
				$aPoints[3][1] = $iH
				_GDIPlus_BrushDispose($aBrush[$i])
				$aBrush[$i] = _GDIPlus_LineBrushCreate(0, 0, $iMX - $iW / 2 * $nBS, 0, BitOR(0xFF000000, $nColor), 0xFF000000, 1)
				_GDIPlus_PathWarp($hPathClone, 0, $aPoints, 0, 0, 1000, 500)
			Case 3
				$aPoints[4][0] = $iMX + $iW / 2 * $nBS
				$aPoints[4][1] = $iMY - $iH / 2 * $nBS
				$aPoints[2][0] = $iMX + $iW / 2 * $nBS
				$aPoints[2][1] = $iMY + $iH / 2 * $nBS
				$aPoints[3][0] = $iW
				$aPoints[3][1] = 0
				$aPoints[1][0] = $iW
				$aPoints[1][1] = $iH
				_GDIPlus_BrushDispose($aBrush[$i])
				$aBrush[$i] = _GDIPlus_LineBrushCreate($iW, 0, $iMX + $iW / 2 * $nBS, 0, BitOR(0xFF000000, $nColor), 0xFF000000, 1)
				_GDIPlus_PathWarp($hPathClone, 0, $aPoints, 0, 0, 1000, 500)
		EndSwitch
		_GDIPlus_GraphicsFillPath($hGraphics, $hPathClone, $aBrush[$i])
		_GDIPlus_PathDispose($hPathClone)
	Next
	_GDIPlus_PathDispose($hPathTemp)
EndFunc   ;==>_DrawTunnel


Func WM_PAINT($hWnd, $uMsgm, $wParam, $lParam)
	_GDIPlus_GraphicsDrawImage($hGraphics, $hBmpBuffer, 0, 0)
	Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_PAINT

Func WM_ERASEBKGND($hWnd, $uMsgm, $wParam, $lParam)
	_GDIPlus_GraphicsDrawImage($hGraphics, $hBmpBuffer, 0, 0)
	Return True
EndFunc   ;==>WM_ERASEBKGND

Func _Exit()
	_GDIPlus_BrushDispose($hBrush)
	_GDIPlus_PenDispose($hPen)
	_GDIPlus_GraphicsDispose($hGfxBuffer)
	_GDIPlus_BitmapDispose($hBmpBuffer)
	_GDIPlus_GraphicsDispose($hGraphics)
	_GDIPlus_Shutdown()
	_WinAPI_ShowCursor(True)
	Exit
EndFunc   ;==>_Exit