Page 1 of 1

How to draw a line dynamically?

Posted: Sun May 09, 2021 3:47 am
by IdeasVacuum
Easy to use 2D Drawing LineXY to draw a line, but how to allow the User to define it dynamically? For my purposes, anti-aliasing is not required.

Image

Re: How to draw a line dynamically?

Posted: Sun May 09, 2021 5:54 am
by Tenaja
I'm inferring you want to duplicate the gif... Right?

I haven't done it in pb, but on another platform I took the mouse position xy at the mouse clicks; one for start, and one for end. You need to erase the line and redraw it each time it's moved, so using a separate layer for the active line helps... Then add it to the drawing after it's completed.

Re: How to draw a line dynamically?

Posted: Sun May 09, 2021 7:01 am
by #NULL
store some state about the current drawing (if user is drawing, and line coordinates), and store the previous lines in a list. redraw if necessary:

Code: Select all

EnableExplicit
Define ww, wh, style, win, canvas, event, quit

ww=800
wh=600
style | #PB_Window_ScreenCentered
style | #PB_Window_SystemMenu
style | #PB_Window_MinimizeGadget

win = OpenWindow(#PB_Any, 50, 100, ww, wh, "", style)
AddKeyboardShortcut(win, #PB_Shortcut_Escape, 10)
canvas = CanvasGadget(#PB_Any, 0, 0, ww, wh, #PB_Canvas_Keyboard)
SetActiveGadget(canvas)

Structure line
  x1.i
  y1.i
  x2.i
  y2.i
EndStructure

Define lining = #False
Define currentLine.line
NewList lines.line()

Procedure redrawCanvas()
  Shared canvas, lining, currentLine, lines()
  
  ; 2d drawing
;   If StartDrawing(CanvasOutput(canvas))
;     DrawingMode(#PB_2DDrawing_AllChannels)
;     Box(0, 0, OutputWidth(), OutputHeight(), $00ffffff)
;     DrawingMode(#PB_2DDrawing_AlphaBlend)
;     LineXY(currentLine\x1, currentLine\y1, currentLine\x2, currentLine\y2, $66660000)
;     ForEach lines()
;       LineXY(lines()\x1, lines()\y1, lines()\x2, lines()\y2, $66000066)
;     Next
;     StopDrawing()
;   EndIf
  
  ; vector drawing
  If StartVectorDrawing(CanvasVectorOutput(canvas))
    VectorSourceColor($ffffffff)
    FillVectorOutput()
    
    If lining
      VectorSourceColor($66ff0000)
      MovePathCursor(currentLine\x1, currentLine\y1)
      AddPathLine(currentLine\x2, currentLine\y2)
      StrokePath(4, #PB_Path_RoundEnd)
    EndIf
    
    VectorSourceColor($660000ff)
    ForEach lines()
      MovePathCursor(lines()\x1, lines()\y1)
      AddPathLine(lines()\x2, lines()\y2)
      StrokePath(4, #PB_Path_RoundEnd)
    Next
    
    StopVectorDrawing()
  EndIf
  
EndProcedure

Repeat
  If IsWindow(win) ;{
    Repeat
      event = WaitWindowEvent(100)
      Select event
        Case #PB_Event_CloseWindow
          quit = #True
        Case #PB_Event_Menu
          Select EventMenu()
            Case 10
              quit = #True
          EndSelect
        Case #PB_Event_Gadget
          Select EventGadget()
            Case canvas
              Select EventType()
                Case #PB_EventType_MouseMove
                  If lining
                    currentLine\x2 = GetGadgetAttribute(canvas, #PB_Canvas_MouseX)
                    currentLine\y2 = GetGadgetAttribute(canvas, #PB_Canvas_MouseY)
                    redrawCanvas()
                  EndIf
                Case #PB_EventType_LeftButtonDown
                  If Not lining
                    lining = #True
                    currentLine\x1 = GetGadgetAttribute(canvas, #PB_Canvas_MouseX)
                    currentLine\y1 = GetGadgetAttribute(canvas, #PB_Canvas_MouseY)
                    currentLine\x2 = GetGadgetAttribute(canvas, #PB_Canvas_MouseX)
                    currentLine\y2 = GetGadgetAttribute(canvas, #PB_Canvas_MouseY)
                    redrawCanvas()
                  EndIf
                Case #PB_EventType_LeftButtonUp
                  If lining
                    AddElement(lines())
                    lines() = currentLine
                    lining = #False
                    redrawCanvas()
                  EndIf
              EndSelect
          EndSelect
      EndSelect
    Until Not event
    ;}
  EndIf
  redrawCanvas()
  
Until quit

Re: How to draw a line dynamically?

Posted: Sun May 09, 2021 12:28 pm
by IdeasVacuum
Hi #NULL

Just your description was enough - brilliant help thank you!

Re: How to draw a line dynamically?

Posted: Sun May 09, 2021 12:49 pm
by IdeasVacuum
Hi Tenaja

That's correct, and many thanks for your description.

Re: How to draw a line dynamically?

Posted: Sun May 09, 2021 1:56 pm
by mk-soft
@NULL
very nice example ;)

Unfortunately, I have found a bug in macOS. The direct assignment of the structure variable to the list does not work.

Small fix

Code: Select all

                Case #PB_EventType_LeftButtonUp
                  If lining
                    AddElement(lines())
                    CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
                      CopyStructure(currentLine, lines(), line)
                    CompilerElse
                      lines() = currentLine
                    CompilerEndIf
                    lining = #False
                    redrawCanvas()

Re: How to draw a line dynamically?

Posted: Sun May 09, 2021 6:03 pm
by #NULL
Or you could copy the fields manually on macOS or on all OS. Thanks for pointing that out.

Code: Select all

                    AddElement(lines())
                    lines()\x1 = currentLine\x1
                    lines()\y1 = currentLine\y1
                    lines()\x2 = currentLine\x2
                    lines()\y2 = currentLine\y2

Re: How to draw a line dynamically?

Posted: Tue May 11, 2021 9:26 pm
by IdeasVacuum
Just thought I would mention that if the background is not a plain colour or is an image, you can replace:

Code: Select all

    VectorSourceColor($ffffffff)
    FillVectorOutput()
by re-drawing the background with:

Code: Select all

    StartDrawing(CanvasOutput(#Canvas))
            DrawImage(ImageID(#Image),0,0)
    StopDrawing()