PathGuide Module: anchors, arrow heads, decoration

Share your advanced PureBasic knowledge/code with the community.
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

PathGuide Module: anchors, arrow heads, decoration

Post by eddy »

- fancy decorated path animation
Image

Code: Select all

DeclareModule PathGuide
   Declare.i AddPathAnchor(Position.d, Flags=#PB_Relative)
   Declare AnchorCoordinates(PathAnchor)
   Declare.d PathAnchorX(PathAnchor) 
   Declare.d PathAnchorY(PathAnchor) 
   Declare.d PathAnchorAngle(PathAnchor)
   Declare.d PathAnchorPos(PathAnchor, Flags=#PB_Relative)
EndDeclareModule

Module PathGuide    
   Structure PATH_ANCHOR
      pos.d
      percent.d
      x.d
      y.d
      a.d
   EndStructure
   Global NewList PathAnchors.PATH_ANCHOR()
   
   Procedure.i AddPathAnchor(Position.d, Flags=#PB_Relative)
      If Flags=#PB_Relative : Position=PathLength()*Position : EndIf
      Protected *PathAnchor.PATH_ANCHOR=AddElement(PathAnchors())
      With *PathAnchor
         \pos=Position
         \percent=Position / PathLength()
         \x=PathPointX(Position)
         \y=PathPointY(Position)
         \a=PathPointAngle(Position)
      EndWith
      ProcedureReturn *PathAnchor
   EndProcedure
   
   Procedure.d PathAnchorX(*PathAnchor.PATH_ANCHOR)
      ProcedureReturn *PathAnchor\x
   EndProcedure
   Procedure.d PathAnchorY(*PathAnchor.PATH_ANCHOR)
      ProcedureReturn *PathAnchor\y
   EndProcedure
   Procedure.d PathAnchorAngle(*PathAnchor.PATH_ANCHOR)
      ProcedureReturn *PathAnchor\a
   EndProcedure
   Procedure.d PathAnchorPos(*PathAnchor.PATH_ANCHOR, Flags=#PB_Relative)
      If (Flags=#PB_Relative)
         ProcedureReturn *PathAnchor\percent
      Else
         ProcedureReturn *PathAnchor\pos
      EndIf      
   EndProcedure
   
   Procedure AnchorCoordinates(*PathAnchor.PATH_ANCHOR)
      With *PathAnchor
         ResetCoordinates()
         TranslateCoordinates(\x, \y)
         RotateCoordinates(0, 0, \a)
      EndWith      
   EndProcedure
   
EndModule

CompilerIf #PB_Compiler_IsMainFile
   ; ********************
   ; EXAMPLE
   ; ********************
   UseModule PathGuide
   
   Procedure AddDecoratedPath(type$, x0.d, y0.d, x1.d, y1.d, x2.d, y2.d, x.d, y.d, offset.d, color1, color2)
      ;path (extract anchors)
      MovePathCursor(x0, y0)
      AddPathCurve(x1, y1, x2, y2, x, y)
      PathLength=PathLength()
      Dim anchors(3)
      anchors(1)=AddPathAnchor(Mod(0.66 + offset, 1))
      anchors(2)=AddPathAnchor(Mod(0.33 + offset, 1))
      anchors(3)=AddPathAnchor(Mod(0.00 + offset, 1))
      VectorSourceColor(color1)
      StrokePath(10, #PB_Path_RoundEnd)
      ;arrow heads
      SaveVectorState()
      Select type$
         Case "ArrowHead"            
            Length.d=19
            Width.d=20
            For i=1 To ArraySize(anchors())
               AnchorCoordinates(anchors(i))
               MovePathCursor(-Length, -Width)
               AddPathLine(0, 0)
               AddPathLine(-Length, Width)
            Next
            VectorSourceColor(color2)
            StrokePath(15, #PB_Path_RoundCorner)         
         Case "Letter"            
            VectorFont(FontID(0), 50)
            For i=1 To ArraySize(anchors())
               AnchorCoordinates(anchors(i))            
               MovePathCursor(0, 0)
               AddPathText("A")
            Next
            VectorSourceColor(color2)
            StrokePath(5)
         Case "Dot"
            For i=1 To ArraySize(anchors())
               AnchorCoordinates(anchors(i))
               MovePathCursor(0, 0)
               radius=50 - 45*PathAnchorPos(anchors(i))
               AddPathCircle(0, 0, radius)
            Next
            VectorSourceColor(RGBA(255, 255, 255, 255))
            FillPath(#PB_Path_Preserve)
            VectorSourceColor(color2)
            StrokePath(5)            
      EndSelect
      RestoreVectorState()
   EndProcedure
   
   Procedure Draw()
      Static k.d
      k + 30 / 1000.0
      If StartVectorDrawing(CanvasVectorOutput(0))
         ;fill background color
         VectorSourceColor(RGBA(255, 255, 255, 255))
         FillVectorOutput()
         
         ;decorated paths
         x.d=WindowMouseX(0)
         y.d=WindowMouseY(0)
         AddDecoratedPath("Letter", 50, 100, 90, 30, 250, 180, x, y, k, RGBA(150, 171, 255, 225), RGBA(255, 150, 173, 206))
         AddDecoratedPath("ArrowHead", 500, 350, 400, 320, x + 100, y-20, x, y, k, RGBA(255, 19, 73, 206), RGBA(255, 19, 246, 145))
         AddDecoratedPath("Dot", 50, 350, x, 300, x, y + 50, x, y, k, RGBA(19, 255, 25, 145), RGBA(204, 255, 19, 145))
         
         ;target
         MovePathCursor(x, y)         
         AddPathCircle(x, y, 20)
         VectorSourceColor(RGBA(50, 120, 170, 200))
         DashPath(5, PathLength() / 12, #PB_Path_RoundEnd, k*100)
         
         StopVectorDrawing()
      EndIf
   EndProcedure
   
   LoadFont(0, "Arial", 14)
   If OpenWindow(0, 0, 0, 600, 400, "Vector2D: complex path drawing", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
      AddWindowTimer(0, 1, 1000 / 30)
      CanvasGadget(0, 0, 0, WindowWidth(0), WindowHeight(0))
      BindEvent(#PB_Event_Timer, @Draw())
      Repeat: Until WaitWindowEvent()=#PB_Event_CloseWindow
   EndIf
CompilerEndIf
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool