MyreMylar / pygame_gui

A GUI system for pygame.
MIT License
698 stars 83 forks source link

UIButton not visible in UIScrollingContainer #487

Closed GimLala closed 8 months ago

GimLala commented 11 months ago

Description When using the Scrolling Container with a button inside, if the button is initially placed outside of the rect of the scrolling container, then when the button is scrolled into view, it is not seen until you hover over it. After you have hovered over it once, it behaves as expected

To Reproduce Steps to reproduce the behaviour:

  1. Run the code below
  2. Click the button
  3. Scroll the new button into view
  4. Repeat 2 and 3
  5. The button will not be visible, but then hover over the button
  6. Now that the button is visible once, you can scroll it in and out of view and the button behaves properly Code:
    
    import pygame
    import pygame_gui
    from pygame_gui.core import UIContainer
    from pygame_gui.elements import UIButton, UIScrollingContainer

pygame.init()

pygame.display.set_caption('Quick Start') window_surface = pygame.display.set_mode((800, 600))

background = pygame.Surface((800, 600)) background.fill(pygame.Color('#000000'))

manager = pygame_gui.UIManager((800, 600))

resizing_test = UIScrollingContainer(pygame.Rect(40, 50, 700, 500), manager) hello_button = UIButton(relative_rect=pygame.Rect((350, 275), (100, 50)), text='Say Hello 1', manager=manager, container=resizing_test)

clock = pygame.time.Clock() is_running = True

while is_running: time_delta = clock.tick(60) / 1000.0 for event in pygame.event.get(): if event.type == pygame.QUIT: is_running = False

    elif event.type == pygame_gui.UI_BUTTON_PRESSED and event.ui_element == hello_button:

        hello_button = UIButton(relative_rect=pygame.Rect((50, 75), (150, 25)),
                                text='Say Hello' + str(int(hello_button.text[-1]) + 1),
                                manager=manager, container=resizing_test,
                                anchors={"left_target": hello_button, "top_target": hello_button})

        size = pygame.Vector2(hello_button.rect.bottomright) - pygame.Vector2(resizing_test.rect.topleft)
        resizing_test.set_scrollable_area_dimensions(size)

    manager.process_events(event)

manager.update(time_delta)

window_surface.blit(background, (0, 0))
pygame.draw.rect(window_surface, "White", resizing_test.rect, 1)
pygame.draw.rect(window_surface, "Orange", hello_button.rect, 1)
manager.draw_ui(window_surface)

pygame.display.update()


**Expected behaviour**
The button should be visible as soon as it is placed in view

**Screenshots**
<img width="594" alt="image" src="https://github.com/MyreMylar/pygame_gui/assets/74864888/6d91afdd-24ac-4375-8559-7dc981805845">
<img width="597" alt="image" src="https://github.com/MyreMylar/pygame_gui/assets/74864888/c5e135d6-1aea-43c2-9329-d2d51bde2d44">

**Platform and software:**
 - OS:  Windows
 - Pygame GUI version 0.6.8
 - Pygame version 2.1.0
MyreMylar commented 11 months ago

I can't reproduce this on the current main branch.

GimLala commented 11 months ago

I can't reproduce this on the current main branch.

Even I can't pin point what is causing the bug, but here is something else I found which I think is a bit strange. When I comment the two lines (see below) then the bug is that the second button isn't loaded until I hover over it, even if it is completely inside the container. But, when I rerun the code with the lines commented, the button is not loaded only until it's fully visible in the scrolling container, without the need to hover over it. The behaviour I would normally expect is that the button to be partially visible as it scrolls into view. Both of the behaviours are (I think) incorrect but if you can't reproduce the bug, maybe something got fixed that unintentionally fixed this bug

import pygame_gui
from pygame_gui.elements import UIButton, UIScrollingContainer

pygame.init()

pygame.display.set_caption('Quick Start')
window_surface = pygame.display.set_mode((800, 600))

background = pygame.Surface((800, 600))
background.fill(pygame.Color('#000000'))

manager = pygame_gui.UIManager((800, 600))

resizing_test = UIScrollingContainer(pygame.Rect(40, 50, 700, 500), manager)
hello_button = UIButton(relative_rect=pygame.Rect((650, 275), (100, 50)),
                        text='Say Hello 1',
                        manager=manager, container=resizing_test)

size = pygame.Vector2(hello_button.rect.bottomright) - pygame.Vector2(resizing_test.rect.topleft) + pygame.Vector2(200, 0)
resizing_test.set_scrollable_area_dimensions(size)

hello_button = UIButton(relative_rect=pygame.Rect((25, 75), (150, 25)),
                        text='Say Hello' + str(int(hello_button.text[-1]) + 1),
                        manager=manager, container=resizing_test,
                        anchors={"left_target": hello_button, "top_target": hello_button})

#####

size = pygame.Vector2(hello_button.rect.bottomright) - pygame.Vector2(resizing_test.rect.topleft) + pygame.Vector2(200, 0)
resizing_test.set_scrollable_area_dimensions(size)

# Try commenting the two lines above

clock = pygame.time.Clock()
is_running = True

while is_running:
    time_delta = clock.tick(60) / 1000.0
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            is_running = False

        elif event.type == pygame_gui.UI_BUTTON_PRESSED and event.ui_element == hello_button:

            hello_button = UIButton(relative_rect=pygame.Rect((50, 75), (150, 25)),
                                    text='Say Hello' + str(int(hello_button.text[-1]) + 1),
                                    manager=manager, container=resizing_test,
                                    anchors={"left_target": hello_button, "top_target": hello_button})
            print(hello_button.rect, hello_button.relative_rect)

            size = pygame.Vector2(hello_button.rect.bottomright) - pygame.Vector2(resizing_test.rect.topleft)
            resizing_test.set_scrollable_area_dimensions(size)

        manager.process_events(event)

    manager.update(time_delta)

    window_surface.blit(background, (0, 0))
    pygame.draw.rect(window_surface, "White", resizing_test.rect, 1)
    pygame.draw.rect(window_surface, "Orange", hello_button.rect, 1)
    manager.draw_ui(window_surface)

    pygame.display.update()
GimLala commented 11 months ago

I think after some testing, I have found the following: The button will load as soon as it is in the view, if it is fully contained in the scrollable rect of the scrolling container The button will need to be hovered after it is in view, if it is only partially contained in the scrollable rect of the scrolling container

But, I think what should happen is: The button should load partially, when it is partially in view, and the scrollable container contains the element atleast partially

MyreMylar commented 8 months ago

I can't reproduce this as described. You do seem to be setting the scrollable container too short (height wise) to contain your buttons in one of these scenarios but everything behaves as I would expect for a button falling below a container.