#include-once

; #INDEX# =======================================================================================================================
; Title .........: Water UDF
; Build .........: 2026-07-10
; AutoIt Version : 3.3.14+
; Description ...: Wrapper for Water.dll / Water_x64.dll - Water Effect (Hugo Elias) as a DLL with its own render thread
; Author(s) .....: UEZ
; Remarks .......: DLL bitness must match the AutoIt exe (auto-selected).
;                  All _Water_Set* functions can be changed live at runtime.
; ===============================================================================================================================

Global $__g_hWaterDll = -1

; #FUNCTION# ====================================================================================================================
; Name ..........: _Water_Startup
; Description ...: Loads the Water DLL (auto-selects x86/x64 based on @AutoItX64).
; Syntax ........: _Water_Startup([$sDllPath = ""])
; Parameters ....: $sDllPath - [optional] custom DLL path. Default: @ScriptDir & "\Water.dll" or "\Water_x64.dll"
; Return values .: Success: True | Failure: False and @error = 1 (DLL not loadable)
; Remarks .......: Safe to call multiple times; returns True immediately if the DLL is already loaded.
; ===============================================================================================================================
Func _Water_Startup($sDllPath = "")
	If $__g_hWaterDll <> -1 Then Return True
	If $sDllPath = "" Then $sDllPath = @ScriptDir & (@AutoItX64 ? "\Water_x64.dll" : "\Water.dll")
	$__g_hWaterDll = DllOpen($sDllPath)
	If $__g_hWaterDll = -1 Then Return SetError(1, 0, False)
	Return True
EndFunc   ;==>_Water_Startup

; #FUNCTION# ====================================================================================================================
; Name ..........: _Water_Shutdown
; Description ...: Stops the effect (if running) and releases the DLL.
; Syntax ........: _Water_Shutdown()
; Parameters ....: None
; Return values .: None
; Remarks .......: Internally calls _Water_Stop followed by DllClose. Safe to call if the DLL was never loaded.
; ===============================================================================================================================
Func _Water_Shutdown()
	If $__g_hWaterDll = -1 Then Return
	_Water_Stop()
	DllClose($__g_hWaterDll)
	$__g_hWaterDll = -1
EndFunc   ;==>_Water_Shutdown

; #FUNCTION# ====================================================================================================================
; Name ..........: _Water_Start
; Description ...: Starts the effect in its own DLL thread, background image loaded from file.
; Syntax ........: _Water_Start($hWnd, $sBmpPath)
; Parameters ....: $hWnd     - Window/control handle to render into (e.g. GUICtrlGetHandle of a Pic control)
;                  $sBmpPath - Path to background image (any format LoadImage accepts)
; Return values .: Success: 1 | Failure: 0 = already running, -1 = image not loadable, -2 = memory error
;                  @error = 1 on DllCall failure / DLL not loaded
; Remarks .......: Simulation size matches the image's native size. Output is automatically
;                  stretched to the target window's client area every frame.
; ===============================================================================================================================
Func _Water_Start($hWnd, $sBmpPath)
	If $__g_hWaterDll = -1 Then Return SetError(1, 0, 0)
	Local $aRet = DllCall($__g_hWaterDll, "long:cdecl", "Water_Start", "hwnd", $hWnd, "wstr", $sBmpPath)
	If @error Then Return SetError(1, @error, 0)
	Return $aRet[0]
EndFunc   ;==>_Water_Start

; #FUNCTION# ====================================================================================================================
; Name ..........: _Water_StartHBmp
; Description ...: Starts the effect in its own DLL thread, background from a GDI HBITMAP instead of a file.
; Syntax ........: _Water_StartHBmp($hWnd, $iW, $iH, $hHBmp)
; Parameters ....: $hWnd  - Window/control handle to render into
;                  $iW    - Internal simulation width
;                  $iH    - Internal simulation height
;                  $hHBmp - HBITMAP handle (e.g. via _GDIPlus_BitmapCreateHBITMAPFromBitmap)
; Return values .: Success: 1 | Failure: 0 = already running, -1 = bitmap not usable, -2 = memory error
;                  @error = 1 on DllCall failure / DLL not loaded
; Remarks .......: Pixels are copied into the DLL's buffer; the HBITMAP may be freed right after the call.
; ===============================================================================================================================
Func _Water_StartHBmp($hWnd, $iW, $iH, $hHBmp)
	If $__g_hWaterDll = -1 Then Return SetError(1, 0, 0)
	Local $aRet = DllCall($__g_hWaterDll, "long:cdecl", "Water_StartHBmp", "hwnd", $hWnd, "long", $iW, "long", $iH, "handle", $hHBmp)
	If @error Then Return SetError(1, @error, 0)
	Return $aRet[0]
EndFunc   ;==>_Water_StartHBmp

; #FUNCTION# ====================================================================================================================
; Name ..........: _Water_Stop
; Description ...: Cleanly stops the render thread and frees all internal memory.
; Syntax ........: _Water_Stop()
; Parameters ....: None
; Return values .: Success: True | Failure: False and @error = 1 (DLL not loaded)
; Remarks .......: Blocks until the render thread has exited. No-op if the effect is not running.
; ===============================================================================================================================
Func _Water_Stop()
	If $__g_hWaterDll = -1 Then Return SetError(1, 0, 0)
	DllCall($__g_hWaterDll, "none:cdecl", "Water_Stop")
	Return SetError(@error, 0, @error = 0)
EndFunc   ;==>_Water_Stop

; #FUNCTION# ====================================================================================================================
; Name ..........: _Water_Drop
; Description ...: Triggers a drop at the given simulation coordinates.
; Syntax ........: _Water_Drop($iX, $iY[, $fPower = 128])
; Parameters ....: $iX     - X coordinate in simulation space (0..simulation width - 1)
;                  $iY     - Y coordinate in simulation space (0..simulation height - 1)
;                  $fPower - [optional] drop strength (default 128, useful range 32..256)
; Return values .: Success: True | Failure: False and @error = 1 (DLL not loaded)
; Remarks .......: Coordinates are in the DLL's internal simulation size, not window size.
;                  Map window coordinates yourself if needed.
; ===============================================================================================================================
Func _Water_Drop($iX, $iY, $fPower = 128)
	If $__g_hWaterDll = -1 Then Return SetError(1, 0, 0)
	DllCall($__g_hWaterDll, "none:cdecl", "Water_Drop", "long", $iX, "long", $iY, "float", $fPower)
	Return SetError(@error, 0, @error = 0)
EndFunc   ;==>_Water_Drop

; #FUNCTION# ====================================================================================================================
; Name ..........: _Water_SetMouse
; Description ...: Enables or disables the built-in mouse interaction (left button creates ripples).
; Syntax ........: _Water_SetMouse([$bEnable = True])
; Parameters ....: $bEnable - [optional] True to enable, False to disable (default True)
; Return values .: Success: True | Failure: False and @error = 1 (DLL not loaded)
; Remarks .......: Live-adjustable at runtime. Default in the DLL is on.
; ===============================================================================================================================
Func _Water_SetMouse($bEnable = True)
	If $__g_hWaterDll = -1 Then Return SetError(1, 0, 0)
	DllCall($__g_hWaterDll, "none:cdecl", "Water_SetMouse", "long", $bEnable ? 1 : 0)
	Return SetError(@error, 0, @error = 0)
EndFunc   ;==>_Water_SetMouse

; #FUNCTION# ====================================================================================================================
; Name ..........: _Water_SetDamping
; Description ...: Sets the damping divisor for wave decay.
; Syntax ........: _Water_SetDamping([$fDamping = 160])
; Parameters ....: $fDamping - [optional] damping divisor (>= 2; default 160)
; Return values .: Success: True | Failure: False and @error = 1 (DLL not loaded)
; Remarks .......: Smaller values = waves decay faster; larger values = waves persist longer.
;                  Live-adjustable at runtime.
; ===============================================================================================================================
Func _Water_SetDamping($fDamping = 160)
	If $__g_hWaterDll = -1 Then Return SetError(1, 0, 0)
	DllCall($__g_hWaterDll, "none:cdecl", "Water_SetDamping", "float", $fDamping)
	Return SetError(@error, 0, @error = 0)
EndFunc   ;==>_Water_SetDamping

; #FUNCTION# ====================================================================================================================
; Name ..........: _Water_SetRefraction
; Description ...: Sets the refraction divisor controlling image distortion strength.
; Syntax ........: _Water_SetRefraction([$fRefraction = 1024])
; Parameters ....: $fRefraction - [optional] refraction divisor (>= 64; default 1024)
; Return values .: Success: True | Failure: False and @error = 1 (DLL not loaded)
; Remarks .......: Smaller values = stronger image distortion. Live-adjustable at runtime.
; ===============================================================================================================================
Func _Water_SetRefraction($fRefraction = 1024)
	If $__g_hWaterDll = -1 Then Return SetError(1, 0, 0)
	DllCall($__g_hWaterDll, "none:cdecl", "Water_SetRefraction", "float", $fRefraction)
	Return SetError(@error, 0, @error = 0)
EndFunc   ;==>_Water_SetRefraction

; #FUNCTION# ====================================================================================================================
; Name ..........: _Water_SetLight
; Description ...: Sets wave-crest highlight gain and brightness clamp range.
; Syntax ........: _Water_SetLight([$fGain = 1.0[, $iClampMin = -16[, $iClampMax = 64]]])
; Parameters ....: $fGain     - [optional] highlight scale factor (default 1.0)
;                  $iClampMin - [optional] lower brightness bound (-255..255; default -16)
;                  $iClampMax - [optional] upper brightness bound (-255..255; default 64)
; Return values .: Success: True | Failure: False and @error = 1 (DLL not loaded)
; Remarks .......: Live-adjustable at runtime. Higher gain / wider clamp = more visible highlights.
; ===============================================================================================================================
Func _Water_SetLight($fGain = 1.0, $iClampMin = -16, $iClampMax = 64)
	If $__g_hWaterDll = -1 Then Return SetError(1, 0, 0)
	DllCall($__g_hWaterDll, "none:cdecl", "Water_SetLight", "float", $fGain, "long", $iClampMin, "long", $iClampMax)
	Return SetError(@error, 0, @error = 0)
EndFunc   ;==>_Water_SetLight

; #FUNCTION# ====================================================================================================================
; Name ..........: _Water_SetTurbulence
; Description ...: Sets the amount of random surface disturbance applied every frame.
; Syntax ........: _Water_SetTurbulence([$iAmount = 20])
; Parameters ....: $iAmount - [optional] number of random pokes per frame (0..1000; default 20, 0 = off)
; Return values .: Success: True | Failure: False and @error = 1 (DLL not loaded)
; Remarks .......: Live-adjustable at runtime. Small values give a subtle shimmer; large values look choppy.
; ===============================================================================================================================
Func _Water_SetTurbulence($iAmount = 20)
	If $__g_hWaterDll = -1 Then Return SetError(1, 0, 0)
	DllCall($__g_hWaterDll, "none:cdecl", "Water_SetTurbulence", "long", $iAmount)
	Return SetError(@error, 0, @error = 0)
EndFunc   ;==>_Water_SetTurbulence

; #FUNCTION# ====================================================================================================================
; Name ..........: _Water_SetAutoDrops
; Description ...: Enables or disables the random auto-drops feature.
; Syntax ........: _Water_SetAutoDrops([$bEnable = True])
; Parameters ....: $bEnable - [optional] True to enable, False to disable (default True)
; Return values .: Success: True | Failure: False and @error = 1 (DLL not loaded)
; Remarks .......: Timing and strength of the drops are controlled by _Water_SetAutoDropParams.
;                  Live-adjustable at runtime.
; ===============================================================================================================================
Func _Water_SetAutoDrops($bEnable = True)
	If $__g_hWaterDll = -1 Then Return SetError(1, 0, 0)
	DllCall($__g_hWaterDll, "none:cdecl", "Water_SetAutoDrops", "long", $bEnable ? 1 : 0)
	Return SetError(@error, 0, @error = 0)
EndFunc   ;==>_Water_SetAutoDrops

; #FUNCTION# ====================================================================================================================
; Name ..........: _Water_SetFrameDelay
; Description ...: Sets the per-frame delay of the render thread in milliseconds.
; Syntax ........: _Water_SetFrameDelay([$iMs = 10])
; Parameters ....: $iMs - [optional] delay in ms (0..1000; default 10)
; Return values .: Success: True | Failure: False and @error = 1 (DLL not loaded)
; Remarks .......: Lower = smoother/faster but more CPU. Higher = slower and easier on the CPU.
;                  Live-adjustable at runtime.
; ===============================================================================================================================
Func _Water_SetFrameDelay($iMs = 10)
	If $__g_hWaterDll = -1 Then Return SetError(1, 0, 0)
	DllCall($__g_hWaterDll, "none:cdecl", "Water_SetFrameDelay", "long", $iMs)
	Return SetError(@error, 0, @error = 0)
EndFunc   ;==>_Water_SetFrameDelay

; #FUNCTION# ====================================================================================================================
; Name ..........: _Water_SetRippleRadius
; Description ...: Sets the base radius used for drops.
; Syntax ........: _Water_SetRippleRadius([$iRad = 3])
; Parameters ....: $iRad - [optional] base radius (1..64; default 3)
; Return values .: Success: True | Failure: False and @error = 1 (DLL not loaded)
; Remarks .......: The actual per-drop radius adds a small random amount on top.
;                  Live-adjustable at runtime.
; ===============================================================================================================================
Func _Water_SetRippleRadius($iRad = 3)
	If $__g_hWaterDll = -1 Then Return SetError(1, 0, 0)
	DllCall($__g_hWaterDll, "none:cdecl", "Water_SetRippleRadius", "long", $iRad)
	Return SetError(@error, 0, @error = 0)
EndFunc   ;==>_Water_SetRippleRadius

; #FUNCTION# ====================================================================================================================
; Name ..........: _Water_SetAutoDropParams
; Description ...: Sets timing and strength ranges for the random auto-drops.
; Syntax ........: _Water_SetAutoDropParams([$iMinMs = 1000[, $iMaxMs = 11000[, $fMinPow = 32[, $fMaxPow = 256]]]])
; Parameters ....: $iMinMs  - [optional] minimum delay between drops in ms (default 1000)
;                  $iMaxMs  - [optional] maximum delay between drops in ms (default 11000)
;                  $fMinPow - [optional] minimum drop strength (default 32)
;                  $fMaxPow - [optional] maximum drop strength (default 256)
; Return values .: Success: True | Failure: False and @error = 1 (DLL not loaded)
; Remarks .......: Each drop picks a random delay in $iMinMs..$iMaxMs and a random strength in $fMinPow..$fMaxPow.
;                  Only takes effect while auto-drops are enabled (see _Water_SetAutoDrops).
;                  Live-adjustable at runtime.
; ===============================================================================================================================
Func _Water_SetAutoDropParams($iMinMs = 1000, $iMaxMs = 11000, $fMinPow = 32, $fMaxPow = 256)
	If $__g_hWaterDll = -1 Then Return SetError(1, 0, 0)
	DllCall($__g_hWaterDll, "none:cdecl", "Water_SetAutoDropParams", "long", $iMinMs, "long", $iMaxMs, "float", $fMinPow, "float", $fMaxPow)
	Return SetError(@error, 0, @error = 0)
EndFunc   ;==>_Water_SetAutoDropParams

; #FUNCTION# ====================================================================================================================
; Name ..........: _Water_About
; Description ...: Shows the DLL's About message box (version, build, credits).
; Syntax ........: _Water_About()
; Parameters ....: None
; Return values .: Success: True | Failure: False and @error = 1 (DLL not loaded)
; Remarks .......: The message box is modal to the render target window but does NOT pause the effect -
;                  the render thread keeps running while the dialog is open.
; ===============================================================================================================================
Func _Water_About()
	If $__g_hWaterDll = -1 Then Return SetError(1, 0, False)
	DllCall($__g_hWaterDll, "none:cdecl", "Water_About")
	Return SetError(@error, 0, @error = 0)
EndFunc   ;==>_Water_About

; #FUNCTION# ====================================================================================================================
; Name ..........: _Water_SetEdgeReflection
; Description ...: Enables or disables wave reflection at the borders.
; Syntax ........: _Water_SetEdgeReflection([$bEnable = True])
; Parameters ....: $bEnable - [optional] True = waves bounce off the borders (default), False = open borders,
;                             waves pass out instead of bouncing back
; Return values .: Success: True | Failure: False and @error = 1 (DLL not loaded)
; Remarks .......: Live-adjustable at runtime. A small residual reflection remains with open borders.
; ===============================================================================================================================
Func _Water_SetEdgeReflection($bEnable = True)
	If $__g_hWaterDll = -1 Then Return SetError(1, 0, 0)
	DllCall($__g_hWaterDll, "none:cdecl", "Water_SetEdgeReflection", "long", $bEnable ? 1 : 0)
	Return SetError(@error, 0, @error = 0)
EndFunc   ;==>_Water_SetEdgeReflection

#include "Water_dll.au3"
