Page 1 of 1

A few screen gadgets bugs (my screen menu fail)

Posted: Sun Mar 01, 2026 1:55 am
by benubi
I failed at making a simple "menu", the reasons are multiple. Maybe there are some that are unknown?

I'm not sure but I wonder why there's not an event queue like it's usually the case for such kind of libraries, it doesn't prevent "loops"; why is the last event gadgets sometimes repeatedly clicked. Disabling hidden windows (and sometimes closed) doesn't prevent the invisible gadgets to receive events and display "hover" textures. Closing a window will also cause IMA the next time it is opened with the same ID.

Edit: you have to click on the "round" mini buttons to open the "menu"

Code: Select all

Procedure CloseMenu()
  If IsScreenGadget(5)
  DisableScreenWindow(3,1)
  HideScreenWindow(3,1)
  If IsScreenGadget(5)
    ClearGadgetItems(5)
  EndIf 
  EndIf 
EndProcedure

Procedure DisplayScreenMenu(Menu,x,y,ItemList$) ; separated by chr(10) (LF)
  Protected count = CountString(ItemList$,Chr(10))+1
  Protected height = 18 * count 
  Protected item$
  Protected size ,i=1,menulist
  OpenScreenWindow(3,x,y,100,height,"",#PB_Window_BorderLess)
  menulist=ListViewScreenGadget(Menu,0,0,200,height)
  While i<=count 
    item$ = StringField(ItemList$,i,Chr(10))
    If Left(item$,3)="---"
      item$=LSet("",20,"-")
    EndIf 
    AddScreenGadgetItem(menulist,-1,item$)
    If size<Len(item$) And Left(item$,3)<>"---"
      size=Len(item$)
    EndIf 
    i+1
  Wend 
  If size*12 > 100
    ResizeScreenWindow(Menu,x,y,(size*12),height)
    ResizeScreenGadget(menulist,0,0,size*12,height)
  EndIf 
  CloseScreenGadgetList()
  ProcedureReturn #True
EndProcedure


InitEngine3D()
  InitSprite()

  OpenWindow(0, 0, 0, 640, 480, "Line3D example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  OpenWindowedScreen(WindowID(0), 0, 0, 640, 480, 0, 0, 0,#PB_Screen_NoSynchronization)

  ; Light
  CreateLight(#PB_Any, RGB(25, 25, 180), -5, 10, 5, #PB_Light_Point)

  ; Camera
  CreateCamera(0, 0, 0, 100, 100)
  MoveCamera(0, 2, 1, 3, #PB_Absolute | #PB_Local)
  CameraLookAt(0, 0, 0, 0)

  ; Create the line and attach it to the scene
  CreateLine3D(0, 0, 0, 0, RGB(255, 0, 0), 1, 1, 1, RGB(0, 0, 255))
  CreateEntity(0, MeshID(0), #PB_Material_None)
  
  InitKeyboard() : InitMouse() : InitScreenGadgets()
  
  ButtonScreenGadget(1,CameraProjectionX(0,0,0,0)-4,CameraProjectionY(0,0,0,0)-4,9,9,"")
  ScreenGadgetToolTip(1,"Line3D start")

  ButtonScreenGadget(2,CameraProjectionX(0,1,1,1)-4,CameraProjectionY(0,1,1,1)-4,9,9,"")
  ScreenGadgetToolTip(2,"Line3D finish")  

  
  Repeat
    If IsScreenActive()
      ExamineKeyboard()
      If KeyboardPushed(#PB_Key_Escape)
        Break
      EndIf 
      
      ExamineMouse()
      
      ; InputEvent(MouseX(),MouseY(),MouseButton(1),KeyboardInkey(),0)
      
    If ScreenWindowEvent()=#PB_Event_Gadget
      Select EventScreenGadget()
        Case 1,2
          DisplayScreenMenu(5,MouseX(),MouseY(),~"Move\nRotate\n------\nCopy\nCut\nDelete")
        Case 5
          Debug "Menu! "
          Debug "state="+GetScreenGadgetState(5)
          Debug "text="+GetScreenGadgetText(5) ; <---- frees the gadget?
                                               ;ClearGadgetItems(5) ; <----- uncomment for after gettext crash
          DisableScreenWindow(3,1)
         ; CloseScreenWindow(3) ;  ; closescreenwindow causes crash on next openscreenwindow
           HideScreenWindow(3,1) ; make ghost window
          
        Default
          If IsScreenGadget(5)
            DisableScreenWindow(3,1)
            HideScreenWindow(3,1)
          EndIf 
        EndSelect  
      ElseIf MouseButton(1) = 0 And lastmb=1
        If IsScreenGadget(5)
          DisableScreenWindow(3,1)
          HideScreenWindow(3,1)
        EndIf 
      EndIf 
    lastmb = MouseButton(1)
    RenderWorld()
    RenderScreenGadgets()
    FlipBuffers()
    EndIf 
  Until WaitWindowEvent(1) = #PB_Event_CloseWindow

Re: A few screen gadgets bugs (my screen menu fail)

Posted: Sun Mar 01, 2026 2:36 pm
by miso
benubi wrote: Sun Mar 01, 2026 1:55 am I failed at making a simple "menu", the reasons are multiple. Maybe there are some that are unknown?
Yes, I'm also waiting for the final release.
benubi wrote: Sun Mar 01, 2026 1:55 am I'm not sure but I wonder why there's not an event queue like it's usually the case for such kind of libraries, it doesn't prevent "loops";
a single event per loop can be enough.
benubi wrote: Sun Mar 01, 2026 1:55 am why is the last event gadgets sometimes repeatedly clicked.
Its annoying, but I know how to reproduce/avoid with the current build. Right mouseclick triggers last button. You can clear it if you leftclick first anywhere on screen, after that you can rightclick without issue.


My needs would be primarily to fix the last one.
Addition: I would like to replace the mouse image. So I want to hide the mouse, and display my cursor at mouseposition. (But with hidden mouse, I cant reach the gadgets, so that solution is not working... There should be a setmousesprite/image, or hide/show and set active/inactive mouse commands.

Re: A few screen gadgets bugs (my screen menu fail)

Posted: Tue Mar 03, 2026 12:57 pm
by benubi
Hi miso!

I believe you can change the screengadget mouse this way (allegedly):

ScreenGadgetSkin(SkinPart, #Image [, FreePrevious])

#Image = #PB_ScreenGadget_Mouse

One event may be enough for simple clicks, but isn't in many cases. When you change a trackbar, or something, there are multiple events being fired. I had two tries at writing an own GUI system before ScreenGui and even CEGUI were implemented, but ultimately failed or gave up. In fact my first attempt had an own XML parser and dialog-like system in it's infancy, before PB officially integrated XML as standard library :) Time flies, it was bug ridden anyways.

I always used event loops and remember a few of the caveats; my first system leaned a lot on the win api style with 4 parameters, and I had issues with loops and unclear event routing. The second attempt had strings only as ID's e.g. CreateLabel("LabelName123",x,y,w,h,text$), and I also believe in the events (I believe Java is/can be similar, back then with SDK version 1.4, 25 years ago) and trying to distinguish windows from controls made the thing more complicated in the drawing routine; also the second attempt lacked the pretty useful UseBuffer() procedure (in the first I even had a MovieWindow using the other extinct rendermovieframe procedure). In the last version I remember that I avoided for-ever event loops by directly taking the last element in the event list and set it as the "last" to be processed, no matter how much the list grows in between. Just a little, very helpful detail. In both cases you have to double and tripple check all global/shared pointers like *Hover etc. for the last control the mouse was hovering over, when you delete/free the controls because of obviously dangling pointers. This can be tricky. The next time I would probably go for a more "object oriented" approach leaning on the original PB gadget library, just like the ScreenGadgets library looks like. Oh yeah, there can be orphans in the event list. E.g. you delete a GUI element, but there still events in the list addressed to it. This means, probably, that the best approach would be to use handles instead of pointers and make it very robust this way, but this needs to be understood & practiced first - which is not where I am exactly arrived yet - PB does it also in a very similar way with the #ID's.

Re: A few screen gadgets bugs (my screen menu fail)

Posted: Thu Mar 05, 2026 10:03 pm
by miso
@benubi, yes, that should do it.