How to draw a line dynamically?

Windows specific forum
IdeasVacuum
Always Here
Always Here
Posts: 6424
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

How to draw a line dynamically?

Post 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
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
Tenaja
Addict
Addict
Posts: 1948
Joined: Tue Nov 09, 2010 10:15 pm

Re: How to draw a line dynamically?

Post 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.
#NULL
Addict
Addict
Posts: 1440
Joined: Thu Aug 30, 2007 11:54 pm
Location: right here

Re: How to draw a line dynamically?

Post 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
IdeasVacuum
Always Here
Always Here
Posts: 6424
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: How to draw a line dynamically?

Post by IdeasVacuum »

Hi #NULL

Just your description was enough - brilliant help thank you!
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
IdeasVacuum
Always Here
Always Here
Posts: 6424
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: How to draw a line dynamically?

Post by IdeasVacuum »

Hi Tenaja

That's correct, and many thanks for your description.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
mk-soft
Always Here
Always Here
Posts: 5313
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: How to draw a line dynamically?

Post 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()
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
#NULL
Addict
Addict
Posts: 1440
Joined: Thu Aug 30, 2007 11:54 pm
Location: right here

Re: How to draw a line dynamically?

Post 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
IdeasVacuum
Always Here
Always Here
Posts: 6424
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: How to draw a line dynamically?

Post 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()
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
Post Reply