AustL / PygameWidgets

A module for use with Pygame. Includes fully customisable buttons, textboxes, sliders and many more, as well as the ability to create and run animations on these widgets.
MIT License
57 stars 16 forks source link

Support for drawing in any surface. #34

Closed tgonzalez89 closed 3 years ago

tgonzalez89 commented 3 years ago

Right now the code expects the widget to be drawn in the display surface. If I draw it in another surface it doesn't understand the widget's position relative to the top level display surface only to the "local" surface and it doesn't handle mouse events properly.

AustL commented 3 years ago

I'm not sure I understand exactly. Could you please provide some code to replicate the issue?

tgonzalez89 commented 3 years ago

Here is some example code that illustrates what I mean.

There are 4 buttons.

To get a workaround going for the sub2 case (surface drawn into another one) the only way is to manually track all the offsets from each surface all the way to the top level. I didn't put this case here, but I think this library shouldn't support this case because it'll make it cumbersome to do. You would have ask the user for the abs offset, I don't think you can get it automatically from anywhere.

import pygame
from pygame_widgets import Button

pygame.init()
win = pygame.display.set_mode((600, 600))
sub1 = win.subsurface((300, 300, 300, 300))
sub2 = pygame.Surface((300, 300))
sub1_wa = win.subsurface((0, 300, 300, 300))

button_win = Button(
    win, 0, 0, 50, 50,
    text='W',
    onClick=lambda: print('Click Win')
)
button_sub1 = Button(
    sub1, 0, 0, 50, 50,
    text='S1',
    onClick=lambda: print('Click Sub1')
)
button_sub2 = Button(
    sub2, 0, 0, 50, 50,
    text='S2',
    onClick=lambda: print('Click Sub2')
)
button_sub1_wa = Button(
    win, 0, sub1_wa.get_abs_offset()[1], 50, 50,
    text='S1WA',
    onClick=lambda: print('Click Sub1_WA')
)

run = True
while run:
    events = pygame.event.get()
    for event in events:
        if event.type == pygame.QUIT:
            pygame.quit()
            run = False
            quit()

    win.fill((255, 255, 255))
    sub1.fill((192, 192, 192))
    sub2.fill((64, 64, 64))
    sub1_wa.fill((0, 0, 0))

    button_win.listen(events)
    button_win.draw()
    button_sub1.listen(events)
    button_sub1.draw()
    button_sub2.listen(events)
    button_sub2.draw()
    button_sub1_wa.listen(events)
    button_sub1_wa.draw()

    win.blit(sub2, (300, 0))

    pygame.display.update()
AustL commented 3 years ago

I fixed the subsurface case, by making the 'contains' method take into account the absolute offset. I agree that the sub2 case should not be handled, as offsets would need to be handled manually.