- shape: hexagon, roundbox
- option: 4 Corners Radius
- waves line
- loops line
 
Code: Select all
DeclareModule PathAddons
   Enumeration
      #PB_WavePath_Default=0
      #PB_WavePath_Triangle
      #PB_WavePath_Square
      #PB_WavePath_Sine
      #PB_WavePath_Sawtooth
      
      #PB_LoopPath_Default=0
      #PB_LoopPath_Open
   EndEnumeration
   
   Declare PathWaveType(WaveType=#PB_WavePath_Default)
   Declare PathLoopType(LoopType=#PB_LoopPath_Default)
   Declare PathCornerRadius(x0.d, y0.d=#PB_Ignore, x1.d=#PB_Ignore, y1.d=#PB_Ignore, x2.d=#PB_Ignore, y2.d=#PB_Ignore, x3.d=#PB_Ignore, y3.d=#PB_Ignore)
   Declare AddPathRoundBox(x.d, y.d, Width.d, Height.d, Flags=#PB_Path_Default)
   Declare AddPathHexagon(x.d, y.d, Width.d, Height.d, Flags=#PB_Path_Default)
   Declare AddPathWaveLine(x.d, y.d, Count, Amplitude.d, Flags=#PB_Path_Default)
   Declare AddPathLoopLine(x.d, y.d, Count, Amplitude1.d, Amplitude2.d, Scale.d, Flags=#PB_Path_Default)
EndDeclareModule
Module PathAddons
   EnableExplicit
   Structure CORNER_RADIUS
      x.d
      y.d
   EndStructure
   Global CurrentWaveType=#PB_WavePath_Default
   Global CurrentLoopType=#PB_LoopPath_Default
   Global Dim CornerRadius.CORNER_RADIUS(3)
   
   Procedure PathWaveType(WaveType=#PB_WavePath_Default)
      CurrentWaveType=WaveType
   EndProcedure
   
   Procedure PathLoopType(LoopType=#PB_LoopPath_Default)
      CurrentLoopType=LoopType
   EndProcedure
   
   Procedure PathCornerRadius(x0.d, y0.d=#PB_Ignore, x1.d=#PB_Ignore, y1.d=#PB_Ignore, x2.d=#PB_Ignore, y2.d=#PB_Ignore, x3.d=#PB_Ignore, y3.d=#PB_Ignore)
      CornerRadius(0)\x=x0
      If y0=#PB_Ignore : y0=x0 : EndIf : CornerRadius(0)\y=y0
      
      If x1<>#PB_Ignore And y1<>#PB_Ignore And x2=#PB_Ignore And y2=#PB_Ignore And x3=#PB_Ignore And y3=#PB_Ignore
         x2=x1 : y2=y1
         x3=x1 : y3=y1
         x1=x0 : y1=y0
      EndIf
      
      If x1=#PB_Ignore : x1=x0 : EndIf : CornerRadius(1)\x=x1
      If y1=#PB_Ignore : y1=y0 : EndIf : CornerRadius(1)\y=y1
      
      If x2=#PB_Ignore : x2=x1 : EndIf : CornerRadius(2)\x=x2
      If y2=#PB_Ignore : y2=y1 : EndIf : CornerRadius(2)\y=y2
      
      If x3=#PB_Ignore : x3=x2 : EndIf : CornerRadius(3)\x=x3
      If y3=#PB_Ignore : y3=y2 : EndIf : CornerRadius(3)\y=y3
   EndProcedure
   
   Procedure AddPathRoundBox(x.d, y.d, Width.d, Height.d, Flags=#PB_Path_Default)
      MovePathCursor(x + CornerRadius(0)\x, y, Flags & #PB_Path_Relative)
      AddPathEllipse(0, CornerRadius(0)\y, CornerRadius(0)\x, CornerRadius(0)\y, 180, -90, #PB_Path_Relative)
      AddPathLine(Width-CornerRadius(0)\x-CornerRadius(1)\x, 0, #PB_Path_Relative)
      AddPathEllipse(0, CornerRadius(1)\y, CornerRadius(1)\x, CornerRadius(1)\y, -90, 0, #PB_Path_Connected | #PB_Path_Relative)
      AddPathLine(0, Height-CornerRadius(1)\y-CornerRadius(2)\y, #PB_Path_Relative)
      AddPathEllipse(-CornerRadius(2)\x, 0, CornerRadius(2)\x, CornerRadius(2)\y, 0, 90, #PB_Path_Connected | #PB_Path_Relative)
      AddPathLine(CornerRadius(2)\x + CornerRadius(3)\x-Width, 0, #PB_Path_Relative)
      AddPathEllipse(0, -CornerRadius(3)\y, CornerRadius(3)\x, CornerRadius(3)\y, 90, 180, #PB_Path_Connected | #PB_Path_Relative)
      ClosePath()
      MovePathCursor(0, -CornerRadius(0)\y, #PB_Path_Relative)
   EndProcedure
   
   Procedure AddPathHexagon(x.d, y.d, Width.d, Height.d, Flags=#PB_Path_Default)
      MovePathCursor(x, y + CornerRadius(0)\y, Flags & #PB_Path_Relative)
      AddPathLine(CornerRadius(0)\x, -CornerRadius(0)\y, #PB_Path_Relative)
      AddPathLine(Width-CornerRadius(0)\x-CornerRadius(1)\x, 0, #PB_Path_Relative)
      AddPathLine(CornerRadius(1)\x, CornerRadius(1)\y, #PB_Path_Relative)
      AddPathLine(0, Height-CornerRadius(1)\y-CornerRadius(2)\y, #PB_Path_Relative)
      AddPathLine(-CornerRadius(2)\x, CornerRadius(2)\y, #PB_Path_Relative)
      AddPathLine(CornerRadius(2)\x + CornerRadius(3)\x-Width, 0, #PB_Path_Relative)
      AddPathLine(-CornerRadius(3)\x, -CornerRadius(3)\y, #PB_Path_Relative)
      ClosePath()
      MovePathCursor(0, -CornerRadius(0)\y, #PB_Path_Relative)
   EndProcedure
   
   Procedure AddPathWaveLine(x.d, y.d, Count, Amplitude.d, Flags=#PB_Path_Default)
      If Count>0
         Protected.d xs=PathCursorX(), ys=PathCursorY() ;start pos
         Protected.d xd=x, yd=y                         ;destination pos
         Protected.d dx=(xd-xs), dy=(yd-ys)             ;distances
         If (Flags & #PB_Path_Relative) : dx=x : dy=y : EndIf
         Protected.d distHalf=Sqr(dx*dx + dy*dy) / Count / 2, distQuarter=distHalf / 2
         Protected.i i
         
         SaveVectorState()
         RotateCoordinates(xs, ys, Degree(ATan2(dx, dy)))
         Select CurrentWaveType
            Case #PB_WavePath_Default
               For i=1 To Count
                  AddPathCurve(distQuarter, -Amplitude, distQuarter, -Amplitude, distHalf, 0, #PB_Path_Relative)
                  AddPathCurve(distQuarter, Amplitude, distQuarter, Amplitude, distHalf, 0, #PB_Path_Relative)
               Next
            Case #PB_WavePath_Triangle
               For i=1 To Count
                  AddPathLine(distQuarter, -Amplitude, #PB_Path_Relative)
                  AddPathLine(distHalf, 2*Amplitude, #PB_Path_Relative)
                  AddPathLine(distQuarter, -Amplitude, #PB_Path_Relative)
               Next
            Case #PB_WavePath_Square
               For i=1 To Count
                  AddPathLine(0, -Amplitude, #PB_Path_Relative)
                  AddPathLine(distHalf, 0, #PB_Path_Relative)
                  AddPathLine(0, 2*Amplitude, #PB_Path_Relative)
                  AddPathLine(distHalf, 0, #PB_Path_Relative)
                  AddPathLine(0, -Amplitude, #PB_Path_Relative)
               Next
            Case #PB_WavePath_Sawtooth
               For i=1 To Count
                  AddPathLine(distHalf, -Amplitude, #PB_Path_Relative)
                  AddPathLine(0, 2*Amplitude, #PB_Path_Relative)
                  AddPathLine(distHalf, -Amplitude, #PB_Path_Relative)
               Next
            Case #PB_WavePath_Sine
               For i=1 To Count
                  AddPathCurve(distQuarter / 2, -Amplitude / 2, 1.5*distQuarter, -Amplitude / 2, distHalf, 0, #PB_Path_Relative)
                  AddPathCurve(distQuarter / 2, Amplitude / 2, 1.5*distQuarter, Amplitude / 2, distHalf, 0, #PB_Path_Relative)
                  
                  ;AddPathEllipse(distQuarter, 0, distQuarter, Amplitude, 180, 360, #PB_Path_Relative)
                  ;AddPathEllipse(distQuarter, 0, distQuarter, Amplitude, 180, 0, #PB_Path_Relative | #PB_Path_CounterClockwise)
               Next
         EndSelect
         RestoreVectorState()
      EndIf
   EndProcedure
   
   Procedure AddPathLoopLine(x.d, y.d, Count, Amplitude1.d, Amplitude2.d, Scale.d, Flags=#PB_Path_Default)
      If Count>0
         Protected.d xs=PathCursorX(), ys=PathCursorY() ;start pos
         Protected.d xd=x, yd=y                         ;destination pos
         Protected.d dx=(xd-xs), dy=(yd-ys)             ;distances
         If (Flags & #PB_Path_Relative) : dx=x : dy=y : EndIf
         Protected.d distHalf=Sqr(dx*dx + dy*dy) / 2, dist1, dist2, k=1 / Scale
         Protected.i i
         SaveVectorState()
         RotateCoordinates(xs, ys, Degree(ATan2(dx, dy)))
         Select CurrentLoopType
            Case #PB_LoopPath_Default
               dist1=k*distHalf / (Count*(k-1) + k)
               dist2=dist1 / k
               AddPathEllipse(dist1, 0, dist1, Amplitude1, -180, 0, #PB_Path_Connected | #PB_Path_Relative)
               For i=1 To Count
                  AddPathEllipse(-dist2, 0, dist2, Amplitude2, 0, 180, #PB_Path_Connected | #PB_Path_Relative)
                  AddPathEllipse(dist1, 0, dist1, Amplitude1, -180, 0, #PB_Path_Connected | #PB_Path_Relative)
               Next
            Case #PB_LoopPath_Open
               Count + 1
               dist1=k*distHalf / (Count*(k-1))
               dist2=dist1 / k
               For i=1 To Count
                  AddPathEllipse(dist1, 0, dist1, Amplitude1, -180, 0, #PB_Path_Connected | #PB_Path_Relative)
                  AddPathEllipse(-dist2, 0, dist2, Amplitude2, 0, 180, #PB_Path_Connected | #PB_Path_Relative)
               Next
         EndSelect
         RestoreVectorState()
      EndIf
   EndProcedure
EndModule
; ********************
; EXAMPLE
; ********************
UseModule PathAddons
Procedure DrawCurves()
   Protected startOffset.d=10.0*ElapsedMilliseconds() / 1000
   
   If StartVectorDrawing(CanvasVectorOutput(0))
      ; --------------------------------------------
      ; enable 2X zoom
      ScaleCoordinates(2, 2)
      
      ; --------------------------------------------
      ; draw white background
      VectorSourceColor(RGBA(255, 255, 255, 255))
      FillVectorOutput()
      
      ; --------------------------------------------
      ; draw loop lines
      Define.d x=100, y=130
      Define amplitude.d=10, count.i=3
      
      MovePathCursor(x, y)
      PathLoopType(#PB_LoopPath_Default)
      AddPathLoopLine(70, 60, count, amplitude / 2, amplitude / 3, 0.2, #PB_Path_Relative)
      VectorSourceColor(RGBA(255, 90, 90, 255))
      StrokePath(2, #PB_Path_RoundEnd)
      
      MovePathCursor(x, y)
      PathLoopType(#PB_LoopPath_Default)
      AddPathLoopLine(70, 60, count, amplitude, amplitude, 0.4, #PB_Path_Relative)
      VectorSourceColor(RGBA(38, 255, 0, 140))
      StrokePath(3, #PB_Path_RoundEnd)
      
      MovePathCursor(x + 20, y)
      PathLoopType(#PB_LoopPath_Open)
      AddPathLoopLine(70, 60, count, amplitude / 2, amplitude / 3, 0.2, #PB_Path_Relative)
      VectorSourceColor(RGBA(0, 251, 255, 200))
      StrokePath(3, #PB_Path_RoundEnd)
      
      ; --------------------------------------------
      ; draw dash line
      Define.d x=10, y=90
      MovePathCursor(x, y)
      AddPathLine(90, 90, #PB_Path_Relative)
      VectorSourceColor(RGBA(255, 0, 50, 255))
      DashPath(2, 5)
      
      ; --------------------------------------------
      ; draw wave lines
      Define amplitude.d=20, count.i=2
      MovePathCursor(x, y)
      PathWaveType(#PB_WavePath_Default)
      AddPathWaveLine(90, 90, count, amplitude, #PB_Path_Relative)
      VectorSourceColor(RGBA(255, 90, 90, 255))
      StrokePath(3, #PB_Path_RoundEnd)
      
      MovePathCursor(x, y)
      PathWaveType(#PB_WavePath_Sawtooth)
      AddPathWaveLine(90, 90, count, amplitude, #PB_Path_Relative)
      VectorSourceColor(RGBA(0, 251, 255, 200))
      StrokePath(3, #PB_Path_RoundEnd)
      
      MovePathCursor(x, y)
      PathWaveType(#PB_WavePath_Sine)
      AddPathWaveLine(90, 90, count, amplitude, #PB_Path_Relative)
      VectorSourceColor(RGBA(185, 0, 255, 100))
      StrokePath(3, #PB_Path_RoundEnd)
      
      MovePathCursor(x, y)
      PathWaveType(#PB_WavePath_Square)
      AddPathWaveLine(90, 90, count, amplitude, #PB_Path_Relative)
      VectorSourceColor(RGBA(38, 255, 0, 140))
      StrokePath(3, #PB_Path_RoundEnd)
      
      MovePathCursor(x, y)
      PathWaveType(#PB_WavePath_Triangle)
      AddPathWaveLine(90, 90, count, amplitude, #PB_Path_Relative)
      VectorSourceColor(RGBA(60, 100, 200, 200))
      DotPath(3, 5, #PB_Path_RoundEnd, startOffset)
      
      ; --------------------------------------------
      ; draw round boxs
      PathCornerRadius(10)
      AddPathRoundBox(10, 10, 50, 50)
      
      PathCornerRadius(10, 20)
      AddPathRoundBox(60, 0, 50, 50, #PB_Path_Relative)
      
      PathCornerRadius(25, 20, 20, 10)
      AddPathRoundBox(60, 0, 50, 50, #PB_Path_Relative)
      
      PathCornerRadius(10, 20, 20, 10, 20, 10)
      AddPathRoundBox(0, 60, 50, 50, #PB_Path_Relative)
      
      PathCornerRadius(25, 40, 10, 10, 25, 40, 10, 10)
      AddPathRoundBox(-60, 0, 50, 50, #PB_Path_Relative)
      
      VectorSourceColor(RGBA(255, 90, 90, 255))
      StrokePath(3, #PB_Path_RoundEnd)
      
      ; --------------------------------------------
      ; draw hexagons on Layer
      BeginVectorLayer(200)
      PathCornerRadius(10)
      AddPathHexagon(10, 10, 50, 50)
      
      PathCornerRadius(10, 20)
      AddPathHexagon(60, 0, 50, 50, #PB_Path_Relative)
      
      PathCornerRadius(25, 20, 20, 10)
      AddPathHexagon(60, 0, 50, 50, #PB_Path_Relative)
      
      PathCornerRadius(10, 20, 20, 10, 20, 10)
      AddPathHexagon(0, 60, 50, 50, #PB_Path_Relative)
      
      PathCornerRadius(25, 40, 10, 10, 25, 40, 10, 10)
      AddPathHexagon(-60, 0, 50, 50, #PB_Path_Relative)
      
      VectorSourceColor(RGBA(60, 100, 200, 255))
      DotPath(3, 5, #PB_Path_RoundEnd, startOffset)
      EndVectorLayer()
      
      StopVectorDrawing()
   EndIf
EndProcedure
If OpenWindow(0, 0, 0, 400, 400, "Animated Vector Drawing", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
   CanvasGadget(0, 0, 0, 400, 400)
   AddWindowTimer(0, 100, 1000 / 30)
   BindEvent(#PB_Event_Timer, @DrawCurves())
   
   Repeat
      Event=WaitWindowEvent()
   Until Event=#PB_Event_CloseWindow
EndIf



 i hope i can find some time soon to test it out.
  i hope i can find some time soon to test it out.




