8000 Fix a few issues with draw.rect() by Starbuck5 · Pull Request #2406 · pygame/pygame · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Fix a few issues with draw.rect() #2406

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 21, 2020
Merged

Fix a few issues with draw.rect() #2406

merged 1 commit into from
Dec 21, 2020

Conversation

Starbuck5
Copy link
Contributor

Fixes #2359, Fixes #2245

In pygame 2, there is an issue where rects draw like this:
2359ex1
Or even not draw at all, if the rect has negative width or height.

I tracked this back to 2.0.0.dev8, the first version where this issue appears. (The same version as rounded rects were added).

The reason for this was this bit of code in draw.c (https://github.com/pygame/pygame/blob/main/src_c/draw.c#L908:L910):

    if (width > rect->w / 2 || width > rect->h / 2) {
        width = MAX(rect->w / 2, rect->h / 2);
    }

This bit of code really messes up the draw width of rectangles, usually evident with thin rectangles or ones with negative dimensions. (Especially with negative dimensions, since there isn't any abs() on it).

I tracked down the commit that added this in #1503, and I found out that this is actually for the rounded_rect function, which was merged into the normal rect draw function, usable through keyword arguments. However when the two functions were merged this code chunk got added so that it affected all rects, not just ones that were going to be drawn rounded.

So I fixed the reported issues by moving the above chunk of code into the conditional for drawing rounded rects.

But then I thought I have such a nice rect benchmark by dr0id - I should set it up to draw rounded rects.
2359-ex2

Turns out the rounded rect drawing was failing with negative width or negative height dimensions, so I set up some code to normalize the rects in the rounded rect draw.

The rounded rect drawing also fails on very thin rectangles. (See the normalized ones that are showing up as huge squares, like <rect(190, 433, 50, 1)>. I fixed this by only drawing a rect using the rounded rect code when it has a border_radius (or any variant) and it has a thickness on the x and y axis of 2 or more. (That threshold may seem arbitrary: but it's legit. Rects with an x/y dimension that equals 2 draw properly, those with dimensions that equal 0 or 1 draw improperly.)

Result:
2359-ex3

See the PR for an actual explanation.
@illume
Copy link
Member
illume commented Dec 20, 2020

Woh, this is epic!

Copy link
Contributor
@MightyJosip MightyJosip left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ty so much <3

Copy link
Contributor
@ankith26 ankith26 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!
8000 LGTM 👍

Cheers :)

@illume illume merged commit 4b1e75e into pygame:main Dec 21, 2020
@dr0id
Copy link
Contributor
dr0id commented Dec 21, 2020

good to see that my benchmark helped to fix and verify that it works again as intended.

@illume
Copy link
Member
illume commented Dec 21, 2020

@dr0id indeed!

btw, @Starbuck5 would you mind pasting the code for the script with rounded corners added?

@Starbuck5
Copy link
Contributor Author

Yeah, this is the script: Just changed a line or two from the original.

import pygame
import pygame.font

pygame.init()
pygame.font.init()
screen_w = 1024
screen_h = 768
screen = pygame.display.set_mode((screen_w, screen_h), pygame.RESIZABLE)
font = pygame.font.SysFont(None, 20)

# create grid coordinates
space_x = 8 * 20
space_y = 70
grid_coordinates = []
for y in range(50, screen_h // 2 + 0 * space_y, space_y):
    for x in range(space_x // 2, screen_w, space_x):
        grid_coordinates.append((x, y))

# draw grid
grid_color = (100, 0, 0)
for x, y in grid_coordinates:
    pygame.draw.line(screen, grid_color, (0, y), (screen_w, y))
    pygame.draw.line(screen, grid_color, (0, y + screen_h / 2), (screen_w, y + screen_h / 2))
    pygame.draw.line(screen, grid_color, (x, 0), (x, screen_h))


def draw_rect(rr, rect_color):
    print(pygame.draw.rect(screen, rect_color, rr, 1, border_radius=15))
    # screen.set_at(rr.topleft, grid_color)
    text = font.render(str(rr), True, (255, 255, 255))
    f_rect = text.get_rect(center=rr.center)
    screen.blit(text, f_rect.move(0, rect_h + font.get_height()))


# create rects of interest
rects = []
rect_w = 50
rect_h = 20
for w in (-rect_w, -1, 0, 1, rect_w):
    for h in (-rect_h, -1, 0, 1, rect_h):
        rects.append(pygame.Rect(0, 0, w, h))

print("rects:", len(rects), rects)

# draw the 'raw' rects
for idx, r in enumerate(rects):
    x, y = grid_coordinates[idx]
    rr = r.move(x, y)
    print("raw", rr)
    draw_rect(rr, (255, 255, 255))

# draw normalized rects
for idx, r in enumerate(rects):
    x, y = grid_coordinates[idx]
    rr = r.move(x, y + screen_h / 2)
    rr.normalize()
    print("normalized", rr)
    draw_rect(rr, (0, 255, 255))

pygame.display.flip()

# wait for a 'escape' keypress or quit event
pygame.event.clear()
running = True
while running:

    for event in [pygame.event.wait()]:
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
              
8000
  running = False

pygame.quit()

@illume illume added the rect pygame.rect label Dec 24, 2020
@illume
Copy link
Member
illume commented Dec 24, 2020

Thanks :)

@illume illume added the draw pygame.draw label Dec 24, 2020
@illume illume added this to the 2.0.2 milestone Aug 21, 2021
@illume illume added the bug label Aug 21, 2021
@illume illume modified the milestones: 2.0.2, 2.0.1 Aug 21, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug draw pygame.draw rect pygame.rect
Projects
None yet
Development

Successfully merging this pull request may close these issues.

pygame.draw.rect draws strange rects pygame2 draw.rect() for zero-width rects differs from pygame1
5 participants
0