Dear PyGui but broken
This commit is contained in:
parent
dde22479b6
commit
02e42ad5d0
BIN
pygame-imgui/__pycache__/pygui.cpython-311.pyc
Normal file
BIN
pygame-imgui/__pycache__/pygui.cpython-311.pyc
Normal file
Binary file not shown.
BIN
pygame-imgui/__pycache__/pygui_pygame_backend.cpython-311.pyc
Normal file
BIN
pygame-imgui/__pycache__/pygui_pygame_backend.cpython-311.pyc
Normal file
Binary file not shown.
@ -0,0 +1,87 @@
|
|||||||
|
import pygame
|
||||||
|
import sys
|
||||||
|
import math
|
||||||
|
import pygui
|
||||||
|
from pygui_pygame_backend import Render, Rect, get_mouse_pos, get_mouse_pressed, MOUSEBUTTONDOWN, MOUSEBUTTONUP, MOUSEMOTION
|
||||||
|
import pygui_pygame_backend as backend
|
||||||
|
|
||||||
|
pygame.init()
|
||||||
|
WIDTH, HEIGHT = 800, 600
|
||||||
|
screen = pygame.display.set_mode((WIDTH, HEIGHT))
|
||||||
|
pygame.display.set_caption("Bouncing Ball with Enhanced PyGUI")
|
||||||
|
clock = pygame.time.Clock()
|
||||||
|
|
||||||
|
# Create the backend renderer and assign the backend to PyGUI.
|
||||||
|
renderer = Render(screen)
|
||||||
|
pygui.PyGUI.set_backend(backend, renderer)
|
||||||
|
|
||||||
|
# ---------------------
|
||||||
|
# Ball Simulation
|
||||||
|
# ---------------------
|
||||||
|
class Ball:
|
||||||
|
def __init__(self, pos, velocity, radius, color):
|
||||||
|
self.pos = list(pos)
|
||||||
|
self.velocity = list(velocity)
|
||||||
|
self.radius = radius
|
||||||
|
self.color = color
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
self.pos[0] += self.velocity[0]
|
||||||
|
self.pos[1] += self.velocity[1]
|
||||||
|
if self.pos[0] - self.radius < 0 or self.pos[0] + self.radius > WIDTH:
|
||||||
|
self.velocity[0] = -self.velocity[0]
|
||||||
|
if self.pos[1] - self.radius < 0 or self.pos[1] + self.radius > HEIGHT:
|
||||||
|
self.velocity[1] = -self.velocity[1]
|
||||||
|
|
||||||
|
def draw(self, surface):
|
||||||
|
pygame.draw.circle(surface, self.color, (int(self.pos[0]), int(self.pos[1])), int(self.radius))
|
||||||
|
|
||||||
|
ball = Ball((WIDTH // 2, HEIGHT // 2), (4, 3), 30, (255, 100, 50))
|
||||||
|
ball_speed = 4.0
|
||||||
|
ball_direction = 0.0
|
||||||
|
ball_radius = 30.0
|
||||||
|
ball_color_r = 255.0
|
||||||
|
ball_color_g = 100.0
|
||||||
|
ball_color_b = 50.0
|
||||||
|
bounce_enabled = True
|
||||||
|
|
||||||
|
running = True
|
||||||
|
while running:
|
||||||
|
dt = clock.tick(60) / 1000.0
|
||||||
|
for event in pygame.event.get():
|
||||||
|
if event.type == pygame.QUIT:
|
||||||
|
running = False
|
||||||
|
pygui.PyGUI.handle_event(event)
|
||||||
|
|
||||||
|
screen.fill((30, 30, 30))
|
||||||
|
|
||||||
|
# Draw a draggable, auto–sizing GUI window.
|
||||||
|
pygui.PyGUI.Begin("Ball Controls", 10, 10)
|
||||||
|
ball_speed = pygui.PyGUI.Slider("Speed", ball_speed, 1, 10)
|
||||||
|
ball_direction = pygui.PyGUI.Slider("Direction", ball_direction, 0, 360)
|
||||||
|
ball_radius = pygui.PyGUI.Slider("Radius", ball_radius, 10, 100)
|
||||||
|
ball_color_r = pygui.PyGUI.Slider("Red", ball_color_r, 0, 255)
|
||||||
|
ball_color_g = pygui.PyGUI.Slider("Green", ball_color_g, 0, 255)
|
||||||
|
ball_color_b = pygui.PyGUI.Slider("Blue", ball_color_b, 0, 255)
|
||||||
|
bounce_enabled = pygui.PyGUI.Checkbox("Bounce", bounce_enabled)
|
||||||
|
if pygui.PyGUI.Button("Reset Position"):
|
||||||
|
ball.pos = [WIDTH // 2, HEIGHT // 2]
|
||||||
|
pygui.PyGUI.End()
|
||||||
|
|
||||||
|
rad = math.radians(ball_direction)
|
||||||
|
ball.velocity[0] = ball_speed * math.cos(rad)
|
||||||
|
ball.velocity[1] = ball_speed * math.sin(rad)
|
||||||
|
ball.radius = ball_radius
|
||||||
|
ball.color = (int(ball_color_r), int(ball_color_g), int(ball_color_b))
|
||||||
|
if not bounce_enabled:
|
||||||
|
ball.velocity[0] *= 0.5
|
||||||
|
ball.velocity[1] *= 0.5
|
||||||
|
|
||||||
|
ball.update()
|
||||||
|
ball.draw(screen)
|
||||||
|
|
||||||
|
pygame.display.flip()
|
||||||
|
pygui.PyGUI.update()
|
||||||
|
|
||||||
|
pygame.quit()
|
||||||
|
sys.exit()
|
@ -0,0 +1,194 @@
|
|||||||
|
# pygui.py: Immediate–mode GUI library.
|
||||||
|
# This file contains no direct Pygame calls—it relies entirely on functions supplied by the backend.
|
||||||
|
# The backend must supply: Rect, get_mouse_pos, get_mouse_pressed,
|
||||||
|
# and event type constants: MOUSEBUTTONDOWN, MOUSEBUTTONUP, MOUSEMOTION.
|
||||||
|
|
||||||
|
class Window:
|
||||||
|
TITLE_HEIGHT = 30
|
||||||
|
PADDING = 5
|
||||||
|
SPACING = 5
|
||||||
|
|
||||||
|
def __init__(self, title, x, y, width=None, height=None):
|
||||||
|
self.title = title
|
||||||
|
self.x = x
|
||||||
|
self.y = y
|
||||||
|
self.width = width if width is not None else 200
|
||||||
|
# Start with a minimal height if none is provided.
|
||||||
|
self.height = height if height is not None else (self.TITLE_HEIGHT + self.PADDING)
|
||||||
|
self.cursor_y = self.y + self.TITLE_HEIGHT + self.PADDING
|
||||||
|
self.dragging = False
|
||||||
|
self.drag_offset = (0, 0)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def rect(self):
|
||||||
|
return Window.backend.Rect(self.x, self.y, self.width, self.height)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def title_rect(self):
|
||||||
|
return Window.backend.Rect(self.x, self.y, self.width, self.TITLE_HEIGHT)
|
||||||
|
|
||||||
|
def handle_event(self, ev):
|
||||||
|
# ev is a dictionary with keys: type, button, pos.
|
||||||
|
if ev.get('type') == 'MOUSEBUTTONDOWN':
|
||||||
|
if ev.get('button') == 1 and self.title_rect.collidepoint(ev.get('pos')):
|
||||||
|
self.dragging = True
|
||||||
|
self.drag_offset = (ev.get('pos')[0] - self.x, ev.get('pos')[1] - self.y)
|
||||||
|
elif ev.get('type') == 'MOUSEBUTTONUP':
|
||||||
|
if ev.get('button') == 1:
|
||||||
|
self.dragging = False
|
||||||
|
elif ev.get('type') == 'MOUSEMOTION':
|
||||||
|
if self.dragging:
|
||||||
|
self.x = ev.get('pos')[0] - self.drag_offset[0]
|
||||||
|
self.y = ev.get('pos')[1] - self.drag_offset[1]
|
||||||
|
self.cursor_y = self.y + self.TITLE_HEIGHT + self.PADDING
|
||||||
|
|
||||||
|
def begin(self, render):
|
||||||
|
render.draw_rect((50, 50, 50), self.rect.rect)
|
||||||
|
render.draw_rect((70, 70, 70), self.title_rect.rect)
|
||||||
|
render.draw_text(self.title, (self.x + self.PADDING, self.y + 5))
|
||||||
|
self.cursor_y = self.y + self.TITLE_HEIGHT + self.PADDING
|
||||||
|
|
||||||
|
def layout(self):
|
||||||
|
return (self.x + self.PADDING, self.cursor_y)
|
||||||
|
|
||||||
|
def next(self, widget_height):
|
||||||
|
self.cursor_y += widget_height + self.SPACING
|
||||||
|
|
||||||
|
class PyGUI:
|
||||||
|
# These are assigned via set_backend.
|
||||||
|
backend = None
|
||||||
|
renderer = None
|
||||||
|
|
||||||
|
current_window = None
|
||||||
|
windows = []
|
||||||
|
active_slider = None # Stores (window_id, label, offset)
|
||||||
|
prev_mouse = False # For one–click widget toggling
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def set_backend(backend, renderer):
|
||||||
|
"""
|
||||||
|
backend: an object that provides Rect, get_mouse_pos, get_mouse_pressed,
|
||||||
|
and event type constants: MOUSEBUTTONDOWN, MOUSEBUTTONUP, MOUSEMOTION.
|
||||||
|
renderer: an instance of the backend’s Render class.
|
||||||
|
"""
|
||||||
|
PyGUI.backend = backend
|
||||||
|
PyGUI.renderer = renderer
|
||||||
|
Window.backend = backend
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def Begin(title, x, y, width=None, height=None):
|
||||||
|
win = Window(title, x, y, width, height)
|
||||||
|
PyGUI.current_window = win
|
||||||
|
PyGUI.windows.append(win)
|
||||||
|
win.begin(PyGUI.renderer)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def End():
|
||||||
|
if PyGUI.current_window:
|
||||||
|
win = PyGUI.current_window
|
||||||
|
# Auto–resize window height to enclose all widgets.
|
||||||
|
win.height = win.cursor_y - win.y + win.PADDING
|
||||||
|
PyGUI.current_window = None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def Label(text):
|
||||||
|
if not PyGUI.current_window:
|
||||||
|
return
|
||||||
|
win = PyGUI.current_window
|
||||||
|
pos = win.layout()
|
||||||
|
PyGUI.renderer.draw_text(text, pos)
|
||||||
|
win.next(20)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def Button(text):
|
||||||
|
if not PyGUI.current_window:
|
||||||
|
return False
|
||||||
|
win = PyGUI.current_window
|
||||||
|
btn_rect = PyGUI.backend.Rect(win.x + win.PADDING, win.cursor_y, win.width - 2 * win.PADDING, 25)
|
||||||
|
PyGUI.renderer.draw_rect((100, 100, 100), btn_rect.rect)
|
||||||
|
PyGUI.renderer.draw_text(text, (btn_rect.x + 5, btn_rect.y + 5))
|
||||||
|
clicked = False
|
||||||
|
mouse_pos = PyGUI.backend.get_mouse_pos()
|
||||||
|
if btn_rect.collidepoint(mouse_pos):
|
||||||
|
PyGUI.renderer.draw_rect((150, 150, 150), btn_rect.rect, border=2)
|
||||||
|
if PyGUI.backend.get_mouse_pressed()[0]:
|
||||||
|
clicked = True
|
||||||
|
win.next(25)
|
||||||
|
return clicked
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def Slider(label, value, min_val, max_val):
|
||||||
|
if not PyGUI.current_window:
|
||||||
|
return value
|
||||||
|
win = PyGUI.current_window
|
||||||
|
pos = win.layout()
|
||||||
|
text = f"{label}: {value:.2f}"
|
||||||
|
PyGUI.renderer.draw_text(text, pos)
|
||||||
|
win.next(20)
|
||||||
|
slider_width = win.width - 2 * win.PADDING
|
||||||
|
slider_rect = PyGUI.backend.Rect(win.x + win.PADDING, win.cursor_y, slider_width, 10)
|
||||||
|
PyGUI.renderer.draw_rect((100, 100, 100), slider_rect.rect)
|
||||||
|
norm = (value - min_val) / (max_val - min_val)
|
||||||
|
knob_x = win.x + win.PADDING + norm * slider_width
|
||||||
|
knob_rect = PyGUI.backend.Rect(knob_x - 5, win.cursor_y - 5, 10, 20)
|
||||||
|
PyGUI.renderer.draw_rect((200, 200, 200), knob_rect.rect)
|
||||||
|
|
||||||
|
slider_id = (id(win), label)
|
||||||
|
mp = PyGUI.backend.get_mouse_pos()
|
||||||
|
mp_pressed = PyGUI.backend.get_mouse_pressed()[0]
|
||||||
|
# Start slider drag if none active and mouse is pressed inside slider_rect.
|
||||||
|
if PyGUI.active_slider is None and slider_rect.collidepoint(mp) and mp_pressed:
|
||||||
|
offset = mp[0] - knob_x
|
||||||
|
PyGUI.active_slider = (slider_id, offset)
|
||||||
|
if PyGUI.active_slider is not None and PyGUI.active_slider[0] == slider_id:
|
||||||
|
offset = PyGUI.active_slider[1]
|
||||||
|
rel = mp[0] - (win.x + win.PADDING) - offset
|
||||||
|
norm = max(0, min(rel / slider_width, 1))
|
||||||
|
value = min_val + norm * (max_val - min_val)
|
||||||
|
if not mp_pressed:
|
||||||
|
PyGUI.active_slider = None
|
||||||
|
win.next(20)
|
||||||
|
return value
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def Checkbox(label, value):
|
||||||
|
if not PyGUI.current_window:
|
||||||
|
return value
|
||||||
|
win = PyGUI.current_window
|
||||||
|
pos = win.layout()
|
||||||
|
box_rect = PyGUI.backend.Rect(win.x + win.PADDING, win.cursor_y, 20, 20)
|
||||||
|
PyGUI.renderer.draw_rect((100, 100, 100), box_rect.rect, border=2)
|
||||||
|
if value:
|
||||||
|
PyGUI.renderer.draw_rect((200, 200, 200), box_rect.rect)
|
||||||
|
PyGUI.renderer.draw_text(label, (box_rect.x + box_rect.width + 5, win.cursor_y))
|
||||||
|
new_value = value
|
||||||
|
mp = PyGUI.backend.get_mouse_pos()
|
||||||
|
mp_pressed = PyGUI.backend.get_mouse_pressed()[0]
|
||||||
|
# Toggle only on the transition (mouse pressed now but not in the previous frame).
|
||||||
|
if box_rect.collidepoint(mp) and mp_pressed and not PyGUI.prev_mouse:
|
||||||
|
new_value = not value
|
||||||
|
win.next(20)
|
||||||
|
return new_value
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def handle_event(event):
|
||||||
|
# Convert a backend event (e.g. a Pygame event) into a generic dictionary.
|
||||||
|
generic = {}
|
||||||
|
if event.type == PyGUI.backend.MOUSEBUTTONDOWN:
|
||||||
|
generic['type'] = 'MOUSEBUTTONDOWN'
|
||||||
|
generic['button'] = event.button
|
||||||
|
generic['pos'] = event.pos
|
||||||
|
elif event.type == PyGUI.backend.MOUSEBUTTONUP:
|
||||||
|
generic['type'] = 'MOUSEBUTTONUP'
|
||||||
|
generic['button'] = event.button
|
||||||
|
generic['pos'] = event.pos
|
||||||
|
elif event.type == PyGUI.backend.MOUSEMOTION:
|
||||||
|
generic['type'] = 'MOUSEMOTION'
|
||||||
|
generic['pos'] = event.pos
|
||||||
|
for win in PyGUI.windows:
|
||||||
|
win.handle_event(generic)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def update():
|
||||||
|
# Call at end of frame to record the current mouse state (for one–click toggling).
|
||||||
|
PyGUI.prev_mouse = PyGUI.backend.get_mouse_pressed()[0]
|
59
pygame-imgui/pygui_pygame_backend.py
Normal file
59
pygame-imgui/pygui_pygame_backend.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import pygame
|
||||||
|
|
||||||
|
# Event type constants.
|
||||||
|
MOUSEBUTTONDOWN = pygame.MOUSEBUTTONDOWN
|
||||||
|
MOUSEBUTTONUP = pygame.MOUSEBUTTONUP
|
||||||
|
MOUSEMOTION = pygame.MOUSEMOTION
|
||||||
|
|
||||||
|
class Render:
|
||||||
|
"""
|
||||||
|
Provides basic drawing functions via Pygame.
|
||||||
|
"""
|
||||||
|
def __init__(self, surface):
|
||||||
|
self.surface = surface
|
||||||
|
self.font = pygame.font.SysFont("Arial", 16)
|
||||||
|
|
||||||
|
def draw_rect(self, color, rect, border=0):
|
||||||
|
pygame.draw.rect(self.surface, color, rect, border)
|
||||||
|
|
||||||
|
def draw_text(self, text, pos, color=(255, 255, 255)):
|
||||||
|
text_surface = self.font.render(text, True, color)
|
||||||
|
self.surface.blit(text_surface, pos)
|
||||||
|
|
||||||
|
def draw_line(self, color, start_pos, end_pos, width=1):
|
||||||
|
pygame.draw.line(self.surface, color, start_pos, end_pos, width)
|
||||||
|
|
||||||
|
def draw_circle(self, color, center, radius, border=0):
|
||||||
|
pygame.draw.circle(self.surface, color, center, radius, border)
|
||||||
|
|
||||||
|
class Rect:
|
||||||
|
"""
|
||||||
|
A simple rectangle wrapper.
|
||||||
|
"""
|
||||||
|
def __init__(self, x, y, width, height):
|
||||||
|
self.rect = pygame.Rect(x, y, width, height)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def x(self):
|
||||||
|
return self.rect.x
|
||||||
|
|
||||||
|
@property
|
||||||
|
def y(self):
|
||||||
|
return self.rect.y
|
||||||
|
|
||||||
|
@property
|
||||||
|
def width(self):
|
||||||
|
return self.rect.width
|
||||||
|
|
||||||
|
@property
|
||||||
|
def height(self):
|
||||||
|
return self.rect.height
|
||||||
|
|
||||||
|
def collidepoint(self, pos):
|
||||||
|
return self.rect.collidepoint(pos)
|
||||||
|
|
||||||
|
def get_mouse_pos():
|
||||||
|
return pygame.mouse.get_pos()
|
||||||
|
|
||||||
|
def get_mouse_pressed():
|
||||||
|
return pygame.mouse.get_pressed()
|
Loading…
Reference in New Issue
Block a user