Dragging images around a Canvas

Just starting out? Need help? Post your questions and find answers here.
User avatar
em_uk
Enthusiast
Enthusiast
Posts: 366
Joined: Sun Aug 08, 2010 3:32 pm
Location: Manchester UK

Dragging images around a Canvas

Post by em_uk »

Hi guys,

I have a requirement to be able to re-organise a number of "tiles" on a canvas, while my routine works well horizontally, vertically is swaps the blocks and really I would want to insert the block and push the tiles along.

I can't seem to think of a way to do this, any ideas? Example here (its ripped from my code so may be a couple of redundant lines that can be ignored) :

Code: Select all

Global Window_1

Global Canvas_TileDisplay

Global Dim imagetiles(256)


Procedure OpenWindow_1(x = 0, y = 0, width = 600, height = 400)
  Window_1 = OpenWindow(#PB_Any, x, y, width, height, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_WindowCentered)
  Canvas_TileDisplay = CanvasGadget(#PB_Any, 10, 10, 580, 190)
EndProcedure


Procedure CheckTileDisplayEvents(Type)
 
  Static startx, starty, firsttile, moveddone, movex, movey, stayx, stayy
 
  offya = GetGadgetAttribute(Canvas_TileDisplay, #PB_Canvas_MouseY) /16           ; get mouse position
  offxa = GetGadgetAttribute(Canvas_TileDisplay, #PB_Canvas_MouseX) /16
 
  If offxa <32 And offxa >=0 And offya >= 0 And offya < 8
   
    If Type=#PB_EventType_LeftButtonDown
      startx = offxa : starty = offya
      StartDrawing(CanvasOutput(Canvas_TileDisplay))
      DrawText(520,10,"Tile : "+RSet(Str(CurrentEditTile),3,"0")+" / $"+RSet(Hex((CurrentEditTile),#PB_Byte),2,"0")+"  ")
      StopDrawing()
      firsttile = (starty*32+startx)
    EndIf
    If (Type = #PB_EventType_MouseMove And GetGadgetAttribute(Canvas_TileDisplay, #PB_Canvas_Buttons) & #PB_Canvas_LeftButton) 
      If (startx<>offxa) Or (starty <> offya)
        Debug Str(startx)+" "+Str(starty)
        Debug Str(offxa)+" "+Str(offya)
       
        firsttile = (starty*32+startx)
        secondtile = (offya*32+offxa)
        tmp = imagetiles(firsttile)                    ; get the first tile id
        imagetiles(firsttile)=imagetiles(secondtile)   ; set the first id to secondtile
        imagetiles(secondtile)=tmp                     ; put first tile into second
       
        StartDrawing(CanvasOutput(Canvas_TileDisplay))
        x = 0 : y = 0 : tile = 0
        For tiles = 0 To 255
          DrawImage(ImageID(imagetiles(tiles)),x,y,16,16)
          x=x+16 : If x=512 : x = 0 : y+16 : EndIf
        Next tiles
        StopDrawing()       
        startx = offxa : starty = offya
      EndIf
    EndIf
  EndIf
EndProcedure

OpenWindow_1()

; make some test images
For x = 0 To 255
  imagetiles(x)=CreateImage(#PB_Any,16,16)
  StartDrawing(ImageOutput(imagetiles(x)))
  Box(0,0,16,16,RGB(Random(255,0),Random(255,0),Random(255,0)))
  StopDrawing()
Next
StartDrawing(CanvasOutput(Canvas_TileDisplay))
x = 0 : y = 0 : tile = 0
For tiles = 0 To 255
  DrawImage(ImageID(imagetiles(tiles)),x,y,16,16)
  x=x+16 : If x=512 : x = 0 : y+16 : EndIf
Next tiles
StopDrawing()


Repeat
 
  event=WaitWindowEvent()
 
  Select event
    Case #PB_Event_CloseWindow
      quit=1
     
    Case #PB_Event_Menu
      Select EventMenu()
      EndSelect
     
    Case #PB_Event_Gadget
      Select EventGadget()
        Case Canvas_TileDisplay
          Type=EventType()
          CheckTileDisplayEvents(Type)
         
      EndSelect
  EndSelect
 
Until quit=1
----

R Tape loading error, 0:1
User avatar
em_uk
Enthusiast
Enthusiast
Posts: 366
Joined: Sun Aug 08, 2010 3:32 pm
Location: Manchester UK

Re: Dragging images around a Canvas

Post by em_uk »

I seemed to have solved it by splitting up left/right from up and down, drawing the tiles to a backbuffer image then regrabbing.
----

R Tape loading error, 0:1
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: Dragging images around a Canvas

Post by davido »

@em_uk,

Please look at the following thread; 'move/drag canvas image'

http://www.purebasic.fr/english/viewtop ... 13&t=54098
DE AA EB
User avatar
em_uk
Enthusiast
Enthusiast
Posts: 366
Joined: Sun Aug 08, 2010 3:32 pm
Location: Manchester UK

Re: Dragging images around a Canvas

Post by em_uk »

I had a specific use case, it wasn't just dragging images, more for a palette layout so it needed to insert tiles in order, my solution (not the prettiest):

Code: Select all

Global Window_1

Global Canvas_TileDisplay

Global Dim imagetiles(256)


Procedure OpenWindow_1(x = 0, y = 0, width = 600, height = 400)
  Window_1 = OpenWindow(#PB_Any, x, y, width, height, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_WindowCentered)
  Canvas_TileDisplay = CanvasGadget(#PB_Any, 10, 10, 580, 190)
EndProcedure

Global backbuffer = CreateImage(#PB_Any,512,384)

Procedure CheckTileDisplayEvents(Type)
  
  Static startx, starty, firsttile, moveddone, movex, movey, stayx, stayy
  
  offya = GetGadgetAttribute(Canvas_TileDisplay, #PB_Canvas_MouseY) /16           ; get mouse position
  offxa = GetGadgetAttribute(Canvas_TileDisplay, #PB_Canvas_MouseX) /16
  
  If offxa <32 And offxa >=0 And offya >= 0 And offya < 8
    
    If Type=#PB_EventType_LeftButtonDown
      startx = offxa : starty = offya
      StartDrawing(CanvasOutput(Canvas_TileDisplay))
      DrawText(520,10,"Tile : "+RSet(Str(CurrentEditTile),3,"0")+" / $"+RSet(Hex((CurrentEditTile),#PB_Byte),2,"0")+"  ")
      StopDrawing()
      firsttile = (starty*32+startx)
    EndIf
    If (Type = #PB_EventType_MouseMove And GetGadgetAttribute(Canvas_TileDisplay, #PB_Canvas_Buttons) & #PB_Canvas_LeftButton) 
      If (startx<>offxa) 
        Debug Str(startx)+" "+Str(starty)
        Debug Str(offxa)+" "+Str(offya)
        
        firsttile = (starty*32+startx)
        secondtile = (offya*32+offxa)
        tmp = imagetiles(firsttile)                    ; get the first tile id
        imagetiles(firsttile)=imagetiles(secondtile)   ; set the first id to secondtile
        imagetiles(secondtile)=tmp                     ; put first tile into second
        
        StartDrawing(ImageOutput(backbuffer))
        x = 0 : y = 0 : tile = 0
        For tiles = 0 To 255
          DrawImage(ImageID(imagetiles(tiles)),x,y,16,16)
          x=x+16 : If x=512 : x = 0 : y+16 : EndIf
        Next tiles
        StopDrawing()       
        startx = offxa
        StartDrawing(CanvasOutput(Canvas_TileDisplay))
        DrawImage(ImageID(backbuffer),0,0)
        StopDrawing()
      ElseIf (starty > offya)
        Debug "up"
        Debug Str(startx)+" "+Str(starty)
        Debug Str(offxa)+" "+Str(offya)
        
        firsttile = (starty*32+startx)
        secondtile = (offya*32+offxa)
        
        StartDrawing(ImageOutput(backbuffer))
        x = 0 : y = 0 : tile = 0 
        For tiles = 0 To secondtile-1
          DrawImage(ImageID(imagetiles(tiles)),x,y,16,16)
          x=x+16 : If x=512 : x = 0 : y+16 : EndIf 
        Next tiles 
        
        DrawImage(ImageID(imagetiles(firsttile)),x,y,16,16)
        x=x+16 : If x=512 : x = 0 : y+16 : EndIf 
        For tiles = secondtile To firsttile-1
          DrawImage(ImageID(imagetiles(tiles)),x,y,16,16)
          x=x+16 : If x=512 : x = 0 : y+16 : EndIf 
        Next tiles 
        
        StopDrawing()
        
        x = 0 : y = 0 : tile = 0
        For tiles = 0 To 255
          FreeImage(imagetiles(tiles))
          imagetiles(tiles)=GrabImage(backbuffer,#PB_Any,x,y,16,16)
          x=x+16 : If x=512 : x = 0 : y+16 : EndIf
        Next tiles
        starty = offya    
        StartDrawing(CanvasOutput(Canvas_TileDisplay))
        DrawImage(ImageID(backbuffer),0,0)
        StopDrawing()
      ElseIf (starty < offya)
        
        Debug "down"
        Debug Str(startx)+" "+Str(starty)
        Debug Str(offxa)+" "+Str(offya)
        
        firsttile = (starty*32+startx)
        secondtile = (offya*32+offxa)
        
        StartDrawing(ImageOutput(backbuffer))
        x = startx*16 : y = starty*16 : tile = 0 
        For tiles = firsttile+1 To secondtile
          DrawImage(ImageID(imagetiles(tiles)),x,y,16,16)
          x=x+16 : If x=512 : x = 0 : y+16 : EndIf 
        Next tiles 
        
        DrawImage(ImageID(imagetiles(firsttile)),x,y,16,16)
        x=x+16 : If x=512 : x = 0 : y+16 : EndIf 
        StopDrawing()
        
        x = 0 : y = 0 : tile = 0
        For tiles = 0 To 255
          FreeImage(imagetiles(tiles))
          imagetiles(tiles)=GrabImage(backbuffer,#PB_Any,x,y,16,16)
          x=x+16 : If x=512 : x = 0 : y+16 : EndIf
        Next tiles
        
        starty = offya    
        StartDrawing(CanvasOutput(Canvas_TileDisplay))
        DrawImage(ImageID(backbuffer),0,0)
        StopDrawing()
        
      EndIf
    EndIf
  EndIf
EndProcedure

OpenWindow_1()

; make some test images
For x = 0 To 255
  imagetiles(x)=CreateImage(#PB_Any,16,16)
  StartDrawing(ImageOutput(imagetiles(x)))
  Box(0,0,16,16,RGB(Int(128 + 128 * Sin(3.1415 * x / 16.0)),Int(128 + 128 * Cos(3.1415 * x / 32.0)),Int(128 + 128 * Sin(3.1415 * x / 64.0))))
  StopDrawing()
  c=c+2 & 255
Next
StartDrawing(ImageOutput(backbuffer))
x = 0 : y = 0 : tile = 0
For tiles = 0 To 255
  DrawImage(ImageID(imagetiles(tiles)),x,y,16,16)
  x=x+16 : If x=512 : x = 0 : y+16 : EndIf
Next tiles
StopDrawing()
StartDrawing(CanvasOutput(Canvas_TileDisplay))
DrawImage(ImageID(backbuffer),0,0)
StopDrawing()

Repeat
  
  event=WaitWindowEvent()
  
  Select event
    Case #PB_Event_CloseWindow
      quit=1
      
    Case #PB_Event_Menu
      Select EventMenu()
      EndSelect
      
    Case #PB_Event_Gadget
      Select EventGadget()
        Case Canvas_TileDisplay
          Type=EventType()
          CheckTileDisplayEvents(Type)
          
      EndSelect
  EndSelect
  
Until quit=1
----

R Tape loading error, 0:1
Post Reply