Advertisement
NiCz

WaterFX

Sep 25th, 2012
342
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
VB.NET 9.64 KB | None | 0 0
  1. Imports System
  2. Imports System.Collections
  3. Imports System.Drawing
  4. Imports System.Drawing.Imaging
  5. Imports System.Runtime.InteropServices
  6. Imports System.Windows.Forms
  7. Public Class WaterFX
  8.     Inherits System.Windows.Forms.Panel
  9.  
  10.     Private effectTimer As System.Windows.Forms.Timer
  11.     Private tmrBalance As System.Windows.Forms.Timer
  12.     Private components As System.ComponentModel.IContainer
  13.  
  14.     Private _bmp As Bitmap
  15.     Private _waves As Short(,,)
  16.     Private _waveWidth As Integer
  17.     Private _waveHeight As Integer
  18.     Private _activeBuffer As Integer = 0
  19.     Private _weHaveWaves As Boolean
  20.     Private _bmpHeight As Integer, _bmpWidth As Integer
  21.     Private _bmpBytes As Byte()
  22.     Private _bmpBitmapData As BitmapData
  23.     Private _scale As Integer
  24.  
  25.     Private __IsBusy As Boolean
  26.  
  27.     Private Sub InitializeComponent()
  28.         Me.components = New System.ComponentModel.Container()
  29.         Me.effectTimer = New System.Windows.Forms.Timer(Me.components)
  30.         Me.tmrBalance = New System.Windows.Forms.Timer(Me.components)
  31.  
  32.         AddHandler Me.effectTimer.Tick, AddressOf Me.effectTimer_Tick
  33.         AddHandler Me.tmrBalance.Tick, AddressOf Me.tmrBalance_Tick
  34.  
  35.         AddHandler Me.Paint, AddressOf Me.WaterEffectControl_Paint
  36.         AddHandler Me.MouseMove, AddressOf Me.WaterEffectControl_MouseMove
  37.  
  38.     End Sub
  39.  
  40.     Public Sub New()
  41.         InitializeComponent()
  42.         effectTimer.Enabled = True
  43.         effectTimer.Interval = 100
  44.         tmrBalance.Interval = 1000
  45.         SetStyle(ControlStyles.UserPaint, True)
  46.         SetStyle(ControlStyles.AllPaintingInWmPaint, True)
  47.         SetStyle(ControlStyles.DoubleBuffer, True)
  48.         Me.BackColor = Color.Transparent
  49.         _weHaveWaves = False
  50.         _scale = 1
  51.     End Sub
  52.  
  53.     Public Sub New(ByVal bmp As Bitmap)
  54.         Me.New()
  55.         Me.ImageBitmap = bmp
  56.     End Sub
  57.  
  58.     Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
  59.         If disposing Then
  60.             If components IsNot Nothing Then
  61.                 components.Dispose()
  62.             End If
  63.         End If
  64.         MyBase.Dispose(disposing)
  65.     End Sub
  66.  
  67.     Private Sub effectTimer_Tick(ByVal sender As Object, ByVal e As System.EventArgs)
  68.         If _weHaveWaves Then
  69.             Invalidate()
  70.             ProcessWaves()
  71.         End If
  72.     End Sub
  73.     Private Sub tmrBalance_Tick(ByVal sender As Object, ByVal e As System.EventArgs)
  74.         __IsBusy = Not __IsBusy
  75.     End Sub
  76.  
  77.     Public Sub WaterEffectControl_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs)
  78.  
  79.         If IsNothing(_bmp) Then Return
  80.         Dim tmp As Bitmap = Nothing
  81.  
  82.         On Error Resume Next
  83.  
  84.         tmp = DirectCast(_bmp.Clone(), Bitmap)
  85.         Dim xOffset As Integer, yOffset As Integer
  86.         Dim alpha As Byte
  87.  
  88.         If _weHaveWaves Then
  89.             Dim tmpData As BitmapData = tmp.LockBits(New Rectangle(0, 0, _bmpWidth, _bmpHeight), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb)
  90.  
  91.             Dim tmpBytes As Byte() = New Byte(_bmpWidth * _bmpHeight * 4 - 1) {}
  92.  
  93.             Marshal.Copy(tmpData.Scan0, tmpBytes, 0, _bmpWidth * _bmpHeight * 4)
  94.  
  95.             For x As Integer = 1 To _bmpWidth - 2
  96.                 For y As Integer = 1 To _bmpHeight - 2
  97.                     Dim waveX As Integer = CInt(x) >> _scale
  98.                     Dim waveY As Integer = CInt(y) >> _scale
  99.  
  100.                     If waveX <= 0 Then
  101.                         waveX = 1
  102.                     End If
  103.                     If waveY <= 0 Then
  104.                         waveY = 1
  105.                     End If
  106.                     If waveX >= _waveWidth - 1 Then
  107.                         waveX = _waveWidth - 2
  108.                     End If
  109.                     If waveY >= _waveHeight - 1 Then
  110.                         waveY = _waveHeight - 2
  111.                     End If
  112.  
  113.                     xOffset = (_waves(waveX - 1, waveY, _activeBuffer) - _waves(waveX + 1, waveY, _activeBuffer)) >> 3
  114.                     yOffset = (_waves(waveX, waveY - 1, _activeBuffer) - _waves(waveX, waveY + 1, _activeBuffer)) >> 3
  115.  
  116.                     If (xOffset <> 0) OrElse (yOffset <> 0) Then
  117.                         If x + xOffset >= _bmpWidth - 1 Then
  118.                             xOffset = _bmpWidth - x - 1
  119.                         End If
  120.                         If y + yOffset >= _bmpHeight - 1 Then
  121.                             yOffset = _bmpHeight - y - 1
  122.                         End If
  123.                         If x + xOffset < 0 Then
  124.                             xOffset = -x
  125.                         End If
  126.                         If y + yOffset < 0 Then
  127.                             yOffset = -y
  128.                         End If
  129.                         If xOffset <= 0 Then xOffset = 0
  130.  
  131.                         alpha = CByte(200 - xOffset)
  132.                         If alpha < 0 Then
  133.                             alpha = 0
  134.                         End If
  135.                         If alpha > 255 Then
  136.                             alpha = 254
  137.                         End If
  138.  
  139.                         tmpBytes(4 * (x + y * _bmpWidth)) = _bmpBytes(4 * (x + xOffset + (y + yOffset) * _bmpWidth))
  140.                         tmpBytes(4 * (x + y * _bmpWidth) + 1) = _bmpBytes(4 * (x + xOffset + (y + yOffset) * _bmpWidth) + 1)
  141.                         tmpBytes(4 * (x + y * _bmpWidth) + 2) = _bmpBytes(4 * (x + xOffset + (y + yOffset) * _bmpWidth) + 2)
  142.                         tmpBytes(4 * (x + y * _bmpWidth) + 3) = alpha
  143.  
  144.                     End If
  145.  
  146.                 Next
  147.                 If Not Err.Number = 0 Then Exit For
  148.  
  149.             Next
  150.  
  151.             Marshal.Copy(tmpBytes, 0, tmpData.Scan0, _bmpWidth * _bmpHeight * 4)
  152.             tmp.UnlockBits(tmpData)
  153.  
  154.         End If
  155.  
  156.         e.Graphics.DrawImage(tmp, 0, 0, Me.ClientRectangle.Width, Me.ClientRectangle.Height)
  157.  
  158.         If Not Err.Number = 0 Then Debug.WriteLine("WaterEffectControl_Paint: " & Err.Description)
  159.  
  160.         If Not IsNothing(tmp) Then tmp.Dispose()
  161.  
  162.     End Sub
  163.  
  164.     Private Sub ProcessWaves()
  165.  
  166.         Dim newBuffer As Integer = If((_activeBuffer = 0), 1, 0)
  167.         Dim wavesFound As Boolean = False
  168.         If newBuffer < 0 Then newBuffer = 1
  169.  
  170.         On Error Resume Next
  171.         For x As Integer = 1 To _waveWidth - 2
  172.             For y As Integer = 1 To _waveHeight - 2
  173.                 _waves(x, y, newBuffer) = CShort((((_waves(x - 1, y - 1, _activeBuffer) + _waves(x, y - 1, _activeBuffer) + _waves(x + 1, y - 1, _activeBuffer) + _waves(x - 1, y, _activeBuffer) + _waves(x + 1, y, _activeBuffer) + _waves(x - 1, y + 1, _activeBuffer) + _waves(x, y + 1, _activeBuffer) + _waves(x + 1, y + 1, _activeBuffer)) >> 2) - _waves(x, y, newBuffer)))
  174.                 'damping
  175.                 If _waves(x, y, newBuffer) <> 0 Then
  176.                     _waves(x, y, newBuffer) -= CShort((_waves(x, y, newBuffer) >> 4))
  177.                     wavesFound = True
  178.                 End If
  179.                 If Not Err.Number = 0 Then Exit For
  180.             Next
  181.             If Not Err.Number = 0 Then Exit For
  182.         Next
  183.  
  184.         _weHaveWaves = wavesFound
  185.         _activeBuffer = newBuffer
  186.  
  187.     End Sub
  188.  
  189.     Private Sub PutDrop(ByVal x As Integer, ByVal y As Integer, ByVal height As Short)
  190.         _weHaveWaves = True
  191.         Dim radius As Integer = 20
  192.         Dim dist As Double
  193.         On Error Resume Next
  194.         For i As Integer = -radius To radius
  195.             For j As Integer = -radius To radius
  196.                 If ((x + i >= 0) AndAlso (x + i < _waveWidth - 1)) AndAlso ((y + j >= 0) AndAlso (y + j < _waveHeight - 1)) Then
  197.                     dist = Math.Sqrt(i * i + j * j)
  198.                     If dist < radius Then
  199.                         _waves(x + i, y + j, _activeBuffer) = CShort((Math.Cos(dist * Math.PI / radius) * height))
  200.                     End If
  201.                 End If
  202.                 If Not Err.Number = 0 Then Return
  203.             Next
  204.             If Not Err.Number = 0 Then Return
  205.         Next
  206.     End Sub
  207.  
  208.     Private Sub WaterEffectControl_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
  209.         On Error Resume Next
  210.         If Not __IsBusy Then
  211.             Dim realX As Integer = CInt(((e.X / CDbl(Me.ClientRectangle.Width)) * _waveWidth))
  212.             Dim realY As Integer = CInt(((e.Y / CDbl(Me.ClientRectangle.Height)) * _waveHeight))
  213.             If Not Err.Number = 0 Then Return
  214.             PutDrop(realX, realY, 200)
  215.         End If
  216.         If Not tmrBalance.Enabled Then tmrBalance.Start()
  217.     End Sub
  218.  
  219. #Region "Properties"
  220.     Public Property ImageBitmap() As Bitmap
  221.         Get
  222.             Return _bmp
  223.         End Get
  224.         Set(ByVal value As Bitmap)
  225.             _bmp = value
  226.             If IsNothing(_bmp) Then
  227.                 effectTimer.Stop()
  228.                 tmrBalance.Stop()
  229.                 Return
  230.             Else
  231.                 effectTimer.Start()
  232.                 __IsBusy = False
  233.             End If
  234.             _bmpHeight = _bmp.Height
  235.             _bmpWidth = _bmp.Width
  236.  
  237.             _waveWidth = _bmpWidth >> _scale
  238.             _waveHeight = _bmpHeight >> _scale
  239.             _waves = New Int16(_waveWidth - 1, _waveHeight - 1, 1) {}
  240.  
  241.             _bmpBytes = New Byte(_bmpWidth * _bmpHeight * 4 - 1) {}
  242.             _bmpBitmapData = _bmp.LockBits(New Rectangle(0, 0, _bmpWidth, _bmpHeight), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb)
  243.             Marshal.Copy(_bmpBitmapData.Scan0, _bmpBytes, 0, _bmpWidth * _bmpHeight * 4)
  244.         End Set
  245.     End Property
  246.     Public Shadows Property Scale() As Integer
  247.         Get
  248.             Return _scale
  249.         End Get
  250.         Set(ByVal value As Integer)
  251.             _scale = value
  252.         End Set
  253.     End Property
  254. #End Region
  255. End Class
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement