Is the canvas the only way to draw?

Just starting out? Need help? Post your questions and find answers here.
User avatar
Random Terrain
Posts: 63
Joined: Fri Jul 09, 2021 9:48 pm
Location: USA
Contact:

Is the canvas the only way to draw?

Post by Random Terrain »

I posted the related thread below a couple days ago:

viewtopic.php?f=6&t=2159

I've been looking at example programs and looking over the manual, but I'm not sure if the canvas will do what I want.

I'm trying to have an editor where the user can draw/paint inside an area that has 32 "boxes" across and up to 176 rows going down. There will be defaults that the user can choose from:
32 columns with 176 rows that are 1 pixel high

32 columns with 88 rows that are 2 pixels high

32 columns with 44 rows that are 4 pixels high

32 columns with 22 rows that are 8 pixels high

32 columns with 11 rows that are 16 pixels high

(There are always 32 columns. That can't be changed. The user shouldn't be able to change the number of columns.)

The user also has to be able to change each row background color and each row foreground color

So the user needs to be able to change the number of rows, the height of each row, the background color of each row, and the foreground color of each row.

When finished drawing/painting, the user needs to be able to click a button to output the data in a box. Example:

Code: Select all

   playfield:
   ................................
   ................................
   ................................
   ................................
   .XXXXX.XXXX.XX...XXXX.XXXX.XXXX.
   .XX....XX...XX...XX...XX....XX..
   .XXXXX.XXXX.XX...XXXX.XX....XX..
   ....XX.XX...XX...XX...XX....XX..
   .XXXXX.XXXX.XXXX.XXXX.XXXX..XX..
   ................................
   ................................
   XXXXX.XXXX.XXXX.XXXXX....XX.XX..
   XX....XX...XX...XX..XX..XXXXXXX.
   XXXXX.XXXX.XXXX.XX..XX...XX.XX..
   ...XX.XX...XX...XX..XX..XXXXXXX.
   XXXXX.XXXX.XXXX.XXXXX....XX.XX..
   ................................
   ................................
   ................................
   ................................
   ................................
   ................................
end

   pfcolors:
   $00
   $00
   $00
   $00
   $0E
   $0C
   $0A
   $08
   $06
   $00
   $00
   $0E
   $0C
   $0A
   $08
   $06
   $00
   $00
   $0E
   $0C
   $0A
   $08
   $06
   $00
   $00
   $06
end

   bkcolors:
   $80
   $80
   $80
   $80
   $80
   $80
   $80
   $80
   $80
   $80
   $80
   $80
   $80
   $80
   $80
   $80
   $80
   $80
   $80
   $80
   $80
   $80
end
So far I don't see a way to keep track of all those "boxes," row background colors, and row foreground colors using the canvas.

How do I keep track of all of that information and have it display the data when the user clicks on the button?

Once that's figured out, would it be possible for it to be able to read data and recreate it on the screen? It would look at the playfield data, pfcolors data, and bkcolors data and put it all up there ready for the user to start making changes to it.


Thanks.
munfraid
Posts: 104
Joined: Sat Mar 24, 2018 1:33 pm

Re: Is the canvas the only way to draw?

Post by munfraid »

Yes, there are other ways to draw, for example screen or windowed screen, but in fact canvas is what you need here.
You have to calculate your block position from the mouse coordinates by yourself anyway.

Let me enhance my previous example to show how it works. I put some comments in the code.

Code: Select all

Global rowHeight = 16

Procedure GadgetEvents() ; here all events like mouse clicks are proceeded
  Select EventGadget()
    Case 1 ; canvas was clicked
      If EventType() = #PB_EventType_LeftButtonDown Or (EventType() = #PB_EventType_MouseMove And GetGadgetAttribute(1, #PB_Canvas_Buttons) & #PB_Canvas_LeftButton)
        If StartDrawing(CanvasOutput(1))
          ; now calculate from mouse pixel position, which block was clicked
          x = (GetGadgetAttribute(1, #PB_Canvas_MouseX)/10)*10
          y = (GetGadgetAttribute(1, #PB_Canvas_MouseY)/(rowHeight*2))*rowHeight*2
          ; draw box
          Box(x, y, 10, rowHeight*2, #Black)
          StopDrawing()
        EndIf
      EndIf
    Case 2 ; combo box was clicked
      rowHeight = Pow(2, GetGadgetState(2))
    Case 3 ; clear button was clicked
      If StartDrawing(CanvasOutput(1))
        Box(0, 0, 320, 352, #White)
        StopDrawing()
      EndIf     
    Case 5 ; generate code button was clicked
      MessageRequester("Here just open a window and display your code in an EditorGagdet. ") 
  EndSelect
EndProcedure

; create the window
OpenWindow(0, 0, 0, 0, 0, "Playfield Editor", #PB_Window_Background)
SetWindowColor(0, #Gray)

; create the ui
TextGadget(0, 30, 30, 300, 30, "Playfield Editor")
LoadFont(0, "Arial", 30) 
SetGadgetFont(0, FontID(0))
SetGadgetColor(0, #PB_Gadget_FrontColor, #White)

CanvasGadget(1, 30, 90, 320, 352)
ComboBoxGadget(2, 380, 90, 220, 30)
AddGadgetItem(2, -1, " 32 columns with 176 rows")
AddGadgetItem(2, -1, " 32 columns with 88 rows")
AddGadgetItem(2, -1, " 32 columns with 44 rows")
AddGadgetItem(2, -1, " 32 columns with 22 rows")
AddGadgetItem(2, -1, " 32 columns with 11 rows")
SetGadgetState(2, 4)
ButtonGadget(3, 30, 472, 80, 30, "Clear")
ButtonGadget(5, 380, 472, 220, 30, "Generate Code")

; define which procedure is called if a gadget event occurs
BindEvent(#PB_Event_Gadget, @GadgetEvents())
Again: This is just a simplified code to keep it short.

edit: Fixed blog size bug - sorry! Now it should work.
User avatar
Random Terrain
Posts: 63
Joined: Fri Jul 09, 2021 9:48 pm
Location: USA
Contact:

Re: Is the canvas the only way to draw?

Post by Random Terrain »

Thanks. I'll examine the code in more detail after supper.
User avatar
Random Terrain
Posts: 63
Joined: Fri Jul 09, 2021 9:48 pm
Location: USA
Contact:

Re: Is the canvas the only way to draw?

Post by Random Terrain »

Still not time to eat. Thanks for the comments in the code. That's very helpful.

I'm still not sure how to make a single row have a different background color and a different foreground color using canvas. So far I can't even get BackColor to do anything.

https://www.spiderbasic.com/documentati ... color.html

Maybe I'm putting it in the wrong place in the code.
User avatar
Random Terrain
Posts: 63
Joined: Fri Jul 09, 2021 9:48 pm
Location: USA
Contact:

Re: Is the canvas the only way to draw?

Post by Random Terrain »

As an experiment, I added a line to the program:

Code: Select all

 
          Box(0, y, 320, rowHeight*2, BackColor($00CCFF))  ; This is the added line.
          Box(x, y, 10, rowHeight*2, #Black)
I assumed that using BackColor would leave anything drawn in the foreground alone, but everything is erased except for the latest foreground box drawn. In other words, doing that causes only one black box to be drawn on a row.
munfraid
Posts: 104
Joined: Sat Mar 24, 2018 1:33 pm

Re: Is the canvas the only way to draw?

Post by munfraid »

"BackColor" is not working like this. You just draw a box, there is no backcolor. Your case is also special because of this "background per row" system, which I couldn't understand completely.

You'll have to work with a background and a foreground layer. I'm pretty busy with a deadline from a contract work tonight. Tomorrow I'll get back to you and explain how this can be done.
User avatar
Random Terrain
Posts: 63
Joined: Fri Jul 09, 2021 9:48 pm
Location: USA
Contact:

Re: Is the canvas the only way to draw?

Post by Random Terrain »

Thanks.
User avatar
Random Terrain
Posts: 63
Joined: Fri Jul 09, 2021 9:48 pm
Location: USA
Contact:

Re: Is the canvas the only way to draw?

Post by Random Terrain »

I made a short video showing how the foreground and background colors of individual rows can be changed:

https://youtu.be/V1RCxXzLOQY

When you're not as busy, please watch the video and you'll get a better idea of what I'm trying to let the user do.
munfraid
Posts: 104
Joined: Sat Mar 24, 2018 1:33 pm

Re: Is the canvas the only way to draw?

Post by munfraid »

Thanks for the video, this make things much clearer. So each row has just one foreground color and one background color and each column owns a foreground pixel or not. Weird…

This makes things a little bit trickier. I put in a new program with is more structured and it’s better to read and to maintain:

Code: Select all

;- META
EnableExplicit

#AppName = "Playfield Editor"
#Version = "0.0.1"


;- DECLARATIONS

; defining named constants for all objects
; important for much better code readability

Enumeration windows
  #Window_Main  
  #Window_Code
EndEnumeration

Enumeration gadgets
  #Button_Clear
  #Button_ColorWhite
  #Button_ColorBlack
  #Button_ColorRed
  #Button_ColorBlue
  #Button_ColorYellow
  #Button_ColorGreen
  #Button_Draw
  #Button_EditBG  
  #Button_EditFG
  #Canvas_Playfield
  #Combo_Rows  
  #Text_EditingMode
  #Text_Color
  #Text_Footer
  #Text_Mode
  #Text_Title
EndEnumeration

Enumeration fonts
  #Font_UiBig
  #Font_UiNormal
  #Font_UiSmall
EndEnumeration

;- SETTINGS

; defines several settings for the appearance
; change as you wish

; ui
Global colorWindowBG = RGB(64,64,64)   ; colors for the editor
Global colorText = RGB(255,255,255)     
Global fontUiBig.s = "Arial"           ; fonts for text in editor ui 
Global fontUiBigSize = 30
Global fontUiNormal.s = "Arial"
Global fontUiNormalSize = 16
Global fontUiSmall.s = "Arial"
Global fontUiSmallSize = 10
Global spacer = 10                     ; space between ui elements; change as you like
Global textFooter.s = #AppName + " v." + #Version + " by randomterrain.com"

; playyfield
Global mode = #Button_Draw            ; default mode 
Global colorFG = #Black               ; default foreground color
Global colorBG = #White               ; default background color
Global cols = 32                      ; fixed value for number of columns
Global colScale = 15                  ; currently set to 15, which results in 15*32 columns = 480 pixel width; change as you wish
Global rows = 176                     ; same as for columns
Global rowScale = 2                   ; same as for columns
Global rowHeight = 16                 ; set to 16 by default because I put 11 rows as default in the initUI() procedure
Global x, y
Global Dim playfieldData(cols, rows)
Global Dim playfieldFG(rows)
Global Dim playfieldBG(rows)
Define i
For i = 0 To rows-1
  playfieldFG(i) = colorFG
  playfieldBG(i) = colorBG
Next


;- PROCEDURES

Procedure GadgetEvents()
  
  ; handle all that happens during runtime 
  
  Protected gadget = EventGadget()
  Protected i
  
  Select gadget
      
    Case #Canvas_Playfield
      If EventType() = #PB_EventType_LeftButtonDown Or (EventType() = #PB_EventType_MouseMove And GetGadgetAttribute(#Canvas_Playfield, #PB_Canvas_Buttons) & #PB_Canvas_LeftButton)
        If StartDrawing(CanvasOutput(#Canvas_Playfield))
          
          ; find out which column and row was clicked
          x = (GetGadgetAttribute(#Canvas_Playfield, #PB_Canvas_MouseX)/colScale)
          y = (GetGadgetAttribute(#Canvas_Playfield, #PB_Canvas_MouseY)/(rowHeight*rowScale))
          
          ; perform drawing depending on current mode
          If mode = #Button_Draw
            playfieldData(x, y*rowHeight) = 1 
            Box(x*colScale, y*rowScale*rowHeight, colScale, rowHeight*rowScale, playfieldFG(y*rowheight))
            
          ElseIf mode = #Button_EditBG
            playfieldBG(y*rowHeight) = colorBG
            Box(0, y*rowHeight*rowScale, cols*colScale, rowHeight*rowScale, colorBG)
            For i = 0 To cols-1
              If playfieldData(i,y*rowHeight) = 1
                Box(i*colScale, y*rowScale*rowHeight, colScale, rowHeight*rowScale, playfieldFG(y*rowheight))
              EndIf
            Next
            
          ElseIf mode = #Button_EditFG
            playfieldFG(y*rowHeight) = colorFG
            For i = 0 To cols-1
              If playfieldData(i,y*rowHeight) = 1
                Box(i*colScale, y*rowScale*rowHeight, colScale, rowHeight*rowScale, colorFG)
              EndIf
            Next
          EndIf
          
          StopDrawing()
          
        EndIf
      EndIf
      
    Case #Combo_Rows 
      rowHeight = Pow(2, GetGadgetState(2))
     
    Case #Button_Draw To #Button_EditFG
      ; set drawing mode
      SetGadgetState(#Button_Draw, 0)
      SetGadgetState(#Button_EditBG, 0)
      SetGadgetState(#Button_EditFG, 0)
      SetGadgetState(gadget, 1)
      mode = gadget
      
    Case #Button_ColorWhite To #Button_ColorGreen
      ; color selection (provisory solution to test, you might want to change this for a better one)
      For i = #Button_ColorWhite To #Button_ColorGreen
        SetGadgetState(i, 0)
      Next
      SetGadgetState(gadget, 1)
      If mode = #Button_EditFG
        colorFG = GetGadgetData(gadget)
      ElseIf mode = #Button_EditBG
        colorBG = GetGadgetData(gadget)
      EndIf
      
    Case #Button_Clear
      Dim playfieldData(cols, rows)
      Dim playfieldFG(rows)
      Dim playfieldBG(rows)
      StartDrawing(CanvasOutput(#Canvas_Playfield))
      Box(0, 0, cols*colScale, rows*rowHeight, #White)
      StopDrawing()

  EndSelect
  
EndProcedure


Procedure initUI()
  
  ; create main window and user interface
 
  LoadFont(#Font_UiBig, fontUiBig, fontUiBigSize)
  LoadFont(#Font_UiNormal, fontUiNormal, fontUiNormalSize)
  LoadFont(#Font_UiSmall, fontUiSmall, fontUiSmallSize)
     
  If OpenWindow(#Window_Main, 0, 0, 0, 0, #AppName, #PB_Window_Background)
    
    SetWindowColor(#Window_Main, colorWindowBG)
    
    ; title
    TextGadget(#Text_Title, 5*spacer, 5*spacer, cols*colScale*3, fontUiBigSize, #AppName)
    SetGadgetFont(#Text_Title, FontID(#Font_UiBig))
    SetGadgetColor(#Text_Title, #PB_Gadget_FrontColor, colorText)
    
    ; playfield
    CanvasGadget(#Canvas_Playfield, GadgetX(#Text_Title), GadgetY(#Text_Title)+GadgetHeight(#Text_Title)+4*spacer,
                 cols*colScale, rows*rowScale, #PB_Canvas_Border)
    
    ; clear button
    ButtonGadget(#Button_Clear, GadgetX(#Text_Title), GadgetY(#Canvas_Playfield)+GadgetHeight(#Canvas_Playfield)+3*spacer,
                 80, 30, "Clear")
    
    ; row modes
    TextGadget(#Text_Mode, GadgetX(#Canvas_Playfield)+GadgetWidth(#Canvas_Playfield)+3*spacer, GadgetY(#Canvas_Playfield), 
               200, fontUiNormalSize, "Row Mode")
    SetGadgetFont(#Text_Mode, FontID(#Font_UiNormal))
    SetGadgetColor(#Text_Mode, #PB_Gadget_FrontColor, colorText)
    
    ComboBoxGadget(#Combo_Rows, GadgetX(#Text_Mode), GadgetY(#Text_Mode)+fontUiNormalSize+spacer, 240, 30)
    AddGadgetItem(#Combo_Rows, -1, " 32 columns with 176 rows")
    AddGadgetItem(#Combo_Rows, -1, " 32 columns with 88 rows")
    AddGadgetItem(#Combo_Rows, -1, " 32 columns with 44 rows")
    AddGadgetItem(#Combo_Rows, -1, " 32 columns with 22 rows")
    AddGadgetItem(#Combo_Rows, -1, " 32 columns with 11 rows")
    SetGadgetState(#Combo_Rows, 4)
    
    ; editing mode
    TextGadget(#Text_EditingMode, GadgetX(#Text_Mode), GadgetY(#Combo_Rows)+30+3*spacer, 240, fontUiNormalSize, "Editing Mode")
    SetGadgetFont(#Text_EditingMode, FontID(#Font_UiNormal))
    SetGadgetColor(#Text_EditingMode, #PB_Gadget_FrontColor, colorText)
        
    ButtonGadget(#Button_Draw, GadgetX(#Text_Mode), GadgetY(#Text_EditingMode)+fontUiNormalSize+spacer, 80, 30,
                 "Draw", #PB_Button_Toggle )
    ButtonGadget(#Button_EditFG, GadgetX(#Text_Mode)+80, GadgetY(#Text_EditingMode)+fontUiNormalSize+spacer, 80, 30,
                 "Color FG", #PB_Button_Toggle )
    ButtonGadget(#Button_EditBG, GadgetX(#Text_Mode)+160, GadgetY(#Text_EditingMode)+fontUiNormalSize+spacer, 80, 30,
                 "Color BG", #PB_Button_Toggle)
    SetGadgetState(#Button_Draw, 1)
    
    ; color
    TextGadget(#Text_Color, GadgetX(#Text_Mode), GadgetY(#Button_EditFG)+30+3*spacer, 240, fontUiNormalSize, "Color")
    SetGadgetFont(#Text_Color, FontID(#Font_UiNormal))
    SetGadgetColor(#Text_Color, #PB_Gadget_FrontColor, colorText)
    
    ButtonGadget(#Button_ColorWhite, GadgetX(#Text_Mode), GadgetY(#Text_Color)+fontUiNormalSize+spacer, 80, 30, 
                 "White", #PB_Button_Toggle)
    SetGadgetData(#Button_ColorWhite, #White)
    ButtonGadget(#Button_ColorBlack, GadgetX(#Text_Mode)+80, GadgetY(#Text_Color)+fontUiNormalSize+spacer, 80, 30, 
                 "Black", #PB_Button_Toggle)
    SetGadgetData(#Button_ColorBlack, #Black)
    ButtonGadget(#Button_ColorRed, GadgetX(#Text_Mode)+160, GadgetY(#Text_Color)+fontUiNormalSize+spacer, 80, 30, 
                 "Red", #PB_Button_Toggle)
    SetGadgetData(#Button_ColorRed, #Red)
    ButtonGadget(#Button_ColorBlue, GadgetX(#Text_Mode), GadgetY(#Text_Color)+fontUiNormalSize+spacer+30, 80, 30, 
                 "Blue", #PB_Button_Toggle)
    SetGadgetData(#Button_ColorBlue, #Blue)
    ButtonGadget(#Button_ColorGreen, GadgetX(#Text_Mode)+80, GadgetY(#Text_Color)+fontUiNormalSize+spacer+30, 80, 30, 
                 "Green", #PB_Button_Toggle)
    SetGadgetData(#Button_ColorGreen, #Green)
    ButtonGadget(#Button_ColorYellow, GadgetX(#Text_Mode)+160, GadgetY(#Text_Color)+fontUiNormalSize+spacer+30, 80, 30, 
                 "Yellow", #PB_Button_Toggle)
    SetGadgetData(#Button_ColorYellow, #Yellow)
    SetGadgetState(#Button_ColorBlack, 1)
    
    ; footer
    TextGadget(#Text_Footer, GadgetX(#Text_Title), GadgetY(#Button_Clear)+GadgetHeight(#Button_Clear)+3*spacer,
               cols*colScale*3, fontUiSmallSize, textFooter)
    SetGadgetFont(#Text_Footer, FontID(#Font_UiSmall))
    SetGadgetColor(#Text_Footer, #PB_Gadget_FrontColor, colorText)
    
    
  EndIf

EndProcedure

;- POINT OF ENTRY

; programm starts here

initUI()
BindEvent(#PB_Event_Gadget, @GadgetEvents())
User avatar
Random Terrain
Posts: 63
Joined: Fri Jul 09, 2021 9:48 pm
Location: USA
Contact:

Re: Is the canvas the only way to draw?

Post by Random Terrain »

Thanks! That's exactly what I need. Now I'll try to add the Atari 2600 pallet that you saw in the video. It will look similar to this:

Image
https://www.randomterrain.com/atari-260 ... color_tool

Is the best way to make a bunch of copies of the color buttons you already have on the page and adjust them (make them smaller and give them the correct colors) or is there a better way to do it? I want to make sure I'm doing the correct thing from the start since it will probably take me two or three days to recreate the color pallet using SpiderBasic.


Thanks.
Post Reply