made ui components inherit one from the other; added new ui components functionality; improved "menu"
This commit is contained in:
parent
d8f1101bc6
commit
46b6db6c00
27
main.py
27
main.py
@ -1,7 +1,4 @@
|
||||
# libraries
|
||||
import sys
|
||||
|
||||
import pygame
|
||||
import time
|
||||
from pyglet.gl import * # for blocky textures
|
||||
import random
|
||||
@ -34,18 +31,30 @@ def main():
|
||||
in_menu = True
|
||||
|
||||
# counting coordinates for ui components
|
||||
ib_width, ib_height = 65, 48
|
||||
bt_width, bt_height = 140, 32
|
||||
ib_y = 230
|
||||
ib_width, ib_height = 100, 65
|
||||
bt_width, bt_height = 210, 55
|
||||
ib_y = 200
|
||||
ib1_x = const.SCREEN.get_width() / 2 - ib_width - 5
|
||||
ib2_x = const.SCREEN.get_width() / 2 + 5
|
||||
bt_x = const.SCREEN.get_width() / 2 - bt_width / 2
|
||||
bt1_y = ib_y + ib_height + 10
|
||||
bt2_y = bt1_y + bt_height + 10
|
||||
|
||||
# basic font for user typed
|
||||
input1 = InputBox(position=(ib1_x, ib_y), dimensions=(ib_width, ib_height), label="x", input_centered=True)
|
||||
input2 = InputBox(position=(ib2_x, ib_y), dimensions=(ib_width, ib_height), label="y", input_centered=True)
|
||||
# creating ui components used in menu
|
||||
input1 = InputBox(
|
||||
position=(ib1_x, ib_y),
|
||||
dimensions=(ib_width, ib_height),
|
||||
text="row",
|
||||
input_centered=True,
|
||||
clear_input_on_click=True
|
||||
)
|
||||
input2 = InputBox(
|
||||
position=(ib2_x, ib_y),
|
||||
dimensions=(ib_width, ib_height),
|
||||
text="column",
|
||||
input_centered=True,
|
||||
clear_input_on_click=True
|
||||
)
|
||||
random_button = Button(position=(bt_x, bt1_y), dimensions=(bt_width, bt_height), text="random")
|
||||
ok_button = Button(position=(bt_x, bt2_y), dimensions=(bt_width, bt_height), text="ok")
|
||||
|
||||
|
6
ui/auxiliary_decorator.py
Normal file
6
ui/auxiliary_decorator.py
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
def _return_itself(fun):
|
||||
def wrapper(*args, **kwargs):
|
||||
fun(*args, **kwargs)
|
||||
|
||||
return wrapper
|
223
ui/button.py
223
ui/button.py
@ -1,8 +1,14 @@
|
||||
import pygame
|
||||
from math import floor
|
||||
|
||||
# importing an auxiliary functions
|
||||
from ui.auxiliary_decorator import _return_itself
|
||||
from ui.text_box import get_fixed_rgb
|
||||
|
||||
# importing parent class
|
||||
from ui.text_box import TextBox
|
||||
|
||||
|
||||
class Button:
|
||||
class Button(TextBox):
|
||||
# constructor that can be used to set parameters of Button instance
|
||||
def __init__(
|
||||
self,
|
||||
@ -17,90 +23,82 @@ class Button:
|
||||
is_active=True,
|
||||
fit_text=True,
|
||||
outline=True,
|
||||
irregular_outline=False,
|
||||
outline_additional_pixel=False,
|
||||
outline_hover_inclusive=True,
|
||||
outline_thickness=None,
|
||||
outline_color=(50, 50, 50),
|
||||
box_transform_hover=1.16,
|
||||
box_transform_inactive=0.9,
|
||||
font_transform_hover=1.24,
|
||||
font_transform_inactive=0.85
|
||||
font_transform_inactive=0.85,
|
||||
outline_transform_hover=1,
|
||||
outline_transform_inactive=0.9
|
||||
):
|
||||
# extracting and setting values
|
||||
smaller_dimension = min(dimensions)
|
||||
width, height = dimensions
|
||||
|
||||
# counting default outline thickness
|
||||
default_outline_thickness = (smaller_dimension + (width + height) / 4) / 50
|
||||
# calling base class constructor
|
||||
super().__init__(
|
||||
position=position,
|
||||
dimensions=dimensions,
|
||||
text=text,
|
||||
box_color=box_color,
|
||||
font=font,
|
||||
font_color=font_color,
|
||||
font_size=font_size,
|
||||
is_visible=is_visible,
|
||||
fit_text=fit_text,
|
||||
outline=outline,
|
||||
irregular_outline=irregular_outline,
|
||||
outline_additional_pixel=outline_additional_pixel,
|
||||
outline_hover_inclusive=outline_hover_inclusive,
|
||||
outline_thickness=outline_thickness,
|
||||
outline_color=outline_color
|
||||
)
|
||||
|
||||
# setting attributes
|
||||
self.position = position
|
||||
self.dimensions = dimensions
|
||||
self.text = text
|
||||
self.box_color = _get_proper_rgb(box_color)
|
||||
self.font_color = _get_proper_rgb(font_color)
|
||||
self.font_size = _return_value_or_default(font_size, floor(smaller_dimension / 2))
|
||||
self.font = pygame.font.SysFont(font, self.font_size)
|
||||
self.is_visible = is_visible
|
||||
self.is_active = is_active
|
||||
self.fit_text = fit_text
|
||||
self.outline = outline
|
||||
self.outline_thickness = _return_value_or_default(outline_thickness, default_outline_thickness)
|
||||
self.outline_color = _get_proper_rgb(outline_color)
|
||||
self.box_transform_hover = box_transform_hover
|
||||
self.box_transform_inactive = box_transform_inactive
|
||||
self.font_transform_hover = font_transform_hover
|
||||
self.font_transform_inactive = font_transform_inactive
|
||||
|
||||
# rendering text to get it's width and height
|
||||
rendered_text = self.font.render(text, True, (0, 0, 0))
|
||||
|
||||
# if text is out of bounds and fit_text=True - resizing text to fit the box
|
||||
if self.fit_text and rendered_text.get_width() > self.dimensions[0]:
|
||||
self.font_size = floor(self.font_size / (rendered_text.get_width() / width + 0.1))
|
||||
self.font = pygame.font.SysFont(font, self.font_size)
|
||||
self.outline_transform_hover = outline_transform_hover
|
||||
self.outline_transform_inactive = outline_transform_inactive
|
||||
|
||||
# counting colors on: hover, inactive
|
||||
self.box_hover_color = _get_proper_rgb(tuple(_transform(self.box_color, self.box_transform_hover)))
|
||||
self.box_inactive_color = _get_proper_rgb(tuple(_transform(self.box_color, self.box_transform_inactive)))
|
||||
self.font_hover_color = _get_proper_rgb(tuple(_transform(self.font_color, self.font_transform_hover)))
|
||||
self.font_inactive_color = _get_proper_rgb(tuple(_transform(self.font_color, self.font_transform_inactive)))
|
||||
self.box_hover_color = get_fixed_rgb(_transform_rgb(self.box_color, self.box_transform_hover))
|
||||
self.box_inactive_color = get_fixed_rgb(_transform_rgb(self.box_color, self.box_transform_inactive))
|
||||
self.font_hover_color = get_fixed_rgb(_transform_rgb(self.font_color, self.font_transform_hover))
|
||||
self.font_inactive_color = get_fixed_rgb(_transform_rgb(self.font_color, self.font_transform_inactive))
|
||||
self.outline_hover_color = get_fixed_rgb(_transform_rgb(self.outline_color, self.outline_transform_hover))
|
||||
self.outline_inactive_color = get_fixed_rgb(_transform_rgb(self.outline_color, self.outline_transform_inactive))
|
||||
|
||||
# draws the Button instance
|
||||
def draw(self, window, mouse_position):
|
||||
# if is_visible=True - drawing Button
|
||||
if self.is_visible:
|
||||
# extracting and setting values from attributes
|
||||
box_x, box_y = self.position
|
||||
width, height = self.dimensions
|
||||
|
||||
# if outline=True - drawing an outline
|
||||
if self.outline:
|
||||
padding = self.outline_thickness
|
||||
outline_coordinates = (box_x - padding, box_y - padding, width + 2 * padding, height + 2 * padding)
|
||||
pygame.draw.rect(window, self.outline_color, outline_coordinates)
|
||||
|
||||
# setting values accordingly to InputBox'es state
|
||||
# is active and mouse is not over
|
||||
if not self.is_over(mouse_position) and self.is_active:
|
||||
pygame.draw.rect(window, self.box_color, (box_x, box_y, width, height))
|
||||
text_color = self.font_color
|
||||
@_return_itself
|
||||
def draw(self, window, mouse_position, *args, **kwargs):
|
||||
# saving attribute values
|
||||
box_color_attribute_value = self.box_color
|
||||
text_color_attribute_value = self.font_color
|
||||
outline_attribute_value = self.outline_color
|
||||
|
||||
# temporarily changing box and font color if necessary
|
||||
# is active and mouse is over
|
||||
elif self.is_active:
|
||||
pygame.draw.rect(window, self.box_hover_color, (box_x, box_y, width, height))
|
||||
text_color = self.font_hover_color
|
||||
if self.is_active and self.is_over(mouse_position):
|
||||
self.box_color = self.box_hover_color
|
||||
self.font_color = self.font_hover_color
|
||||
self.outline_color = self.outline_hover_color
|
||||
|
||||
# is not active
|
||||
else:
|
||||
pygame.draw.rect(window, self.box_inactive_color, (box_x, box_y, width, height))
|
||||
text_color = self.font_inactive_color
|
||||
self.box_color = self.box_inactive_color
|
||||
self.font_color = self.font_inactive_color
|
||||
self.outline_color = self.outline_inactive_color
|
||||
|
||||
# rendering text and counting its coordinates
|
||||
rendered_text = self.font.render(self.text, True, text_color)
|
||||
rendered_text_x = box_x + width / 2 - rendered_text.get_width() / 2
|
||||
rendered_text_y = box_y + height / 2 - rendered_text.get_height() / 2
|
||||
# calling the draw function of base class
|
||||
super().draw(window)
|
||||
|
||||
# drawing the text on the coordinates
|
||||
window.blit(rendered_text, (rendered_text_x, rendered_text_y))
|
||||
# resetting colors to original values
|
||||
self.box_color = box_color_attribute_value
|
||||
self.font_color = text_color_attribute_value
|
||||
self.outline_color = outline_attribute_value
|
||||
|
||||
# returns True if the Button is clicked, or False otherwise
|
||||
def is_clicked(self, mouse_position, events):
|
||||
@ -114,49 +112,6 @@ class Button:
|
||||
|
||||
return False
|
||||
|
||||
# checks if a position is over the InputBox and returns True or False
|
||||
def is_over(self, position):
|
||||
mouse_x, mouse_y = position
|
||||
button_x, button_y = self.position
|
||||
width, height = self.dimensions
|
||||
|
||||
return button_x <= mouse_x <= (button_x + width) and button_y <= mouse_y <= (button_y + height)
|
||||
|
||||
# returns text value
|
||||
def get_text(self):
|
||||
return self.text
|
||||
|
||||
# sets chosen coordinates
|
||||
def set_coordinates(self, position=None, dimensions=None, outline_thickness=None):
|
||||
if position is not None:
|
||||
self.position = position
|
||||
|
||||
if dimensions is not None:
|
||||
self.dimensions = dimensions
|
||||
|
||||
if outline_thickness is not None:
|
||||
self.outline_thickness = outline_thickness
|
||||
|
||||
# sets text attribute
|
||||
def set_text(self, text):
|
||||
self.text = text
|
||||
|
||||
# sets chosen font attributes
|
||||
def set_font(self, font=None, font_size=None):
|
||||
if font_size is not None:
|
||||
self.font_size = font_size
|
||||
|
||||
# rendering text to get it's width and height
|
||||
rendered_text = self.font.render(self.text, True, (0, 0, 0))
|
||||
|
||||
# if text is out of bounds and fit_text=True - resizing text to fit the box
|
||||
if self.fit_text and rendered_text.get_width() > self.dimensions[0]:
|
||||
self.font_size = floor(self.font_size / (rendered_text.get_width() / self.dimensions[0] + 0.1))
|
||||
self.font = pygame.font.SysFont(font, self.font_size)
|
||||
|
||||
if font is not None:
|
||||
self.font = pygame.font.SysFont(font, self.font_size)
|
||||
|
||||
# sets chosen color attributes
|
||||
def set_colors(
|
||||
self,
|
||||
@ -168,14 +123,7 @@ class Button:
|
||||
font_transform_hover=None,
|
||||
font_transform_inactive=None
|
||||
):
|
||||
if box_color is not None:
|
||||
self.box_color = _get_proper_rgb(box_color)
|
||||
|
||||
if font_color is not None:
|
||||
self.font_color = _get_proper_rgb(font_color)
|
||||
|
||||
if outline_color is not None:
|
||||
self.outline_color = _get_proper_rgb(outline_color)
|
||||
super().set_colors(box_color=box_color, font_color=font_color, outline_color=outline_color)
|
||||
|
||||
if box_transform_hover is not None:
|
||||
self.box_transform_hover = box_transform_hover
|
||||
@ -189,33 +137,44 @@ class Button:
|
||||
if font_transform_inactive is not None:
|
||||
self.font_transform_inactive = font_transform_inactive
|
||||
|
||||
self.box_hover_color = _get_proper_rgb(tuple(_transform(self.box_color, self.box_transform_hover)))
|
||||
self.box_inactive_color = _get_proper_rgb(tuple(_transform(self.box_color, self.box_transform_inactive)))
|
||||
self.font_hover_color = _get_proper_rgb(tuple(_transform(self.font_color, self.font_transform_hover)))
|
||||
self.font_inactive_color = _get_proper_rgb(tuple(_transform(self.font_color, self.font_transform_inactive)))
|
||||
self.box_hover_color = get_fixed_rgb(tuple(_transform_rgb(self.box_color, self.box_transform_hover)))
|
||||
self.box_inactive_color = get_fixed_rgb(tuple(_transform_rgb(self.box_color, self.box_transform_inactive)))
|
||||
self.font_hover_color = get_fixed_rgb(tuple(_transform_rgb(self.font_color, self.font_transform_hover)))
|
||||
self.font_inactive_color = get_fixed_rgb(tuple(_transform_rgb(self.font_color, self.font_transform_inactive)))
|
||||
|
||||
# sets chosen flags
|
||||
def set_flags(self, is_visible=None, is_active=None, outline=None):
|
||||
if is_visible is not None:
|
||||
self.is_visible = is_visible
|
||||
def set_flags(
|
||||
self,
|
||||
is_visible=None,
|
||||
is_active=None,
|
||||
outline=None,
|
||||
irregular_outline=None,
|
||||
outline_additional_pixel=None,
|
||||
outline_hover_inclusive=None
|
||||
):
|
||||
super().set_flags(
|
||||
is_visible=is_visible,
|
||||
outline=outline,
|
||||
irregular_outline=irregular_outline,
|
||||
outline_additional_pixel=outline_additional_pixel,
|
||||
outline_hover_inclusive=outline_hover_inclusive
|
||||
)
|
||||
|
||||
if is_active is not None:
|
||||
self.is_active = is_active
|
||||
|
||||
if outline is not None:
|
||||
self.outline = outline
|
||||
|
||||
def _transform_rgb(iterable, transform_value):
|
||||
if isinstance(transform_value, int) or isinstance(transform_value, float):
|
||||
return tuple([x * transform_value for x in iterable])
|
||||
|
||||
def _get_proper_rgb(x):
|
||||
r, g, b = x
|
||||
r, g, b = max(0, min(255, floor(r))), max(0, min(255, floor(g))), max(0, min(255, floor(b)))
|
||||
elif isinstance(transform_value, tuple) or isinstance(transform_value, list):
|
||||
if len(transform_value) == 3 and all([isinstance(x, int) or isinstance(x, float) for x in transform_value]):
|
||||
rgb_list = [x for x in iterable]
|
||||
|
||||
return tuple((r, g, b))
|
||||
for i in range(3):
|
||||
rgb_list[i] += transform_value[i]
|
||||
|
||||
return tuple(rgb_list)
|
||||
|
||||
def _transform(iterable, transform_value):
|
||||
return [x * transform_value for x in iterable]
|
||||
|
||||
|
||||
def _return_value_or_default(value, default):
|
||||
return default if value is None else value
|
||||
return [0, 0, 0]
|
||||
|
258
ui/input_box.py
258
ui/input_box.py
@ -1,24 +1,33 @@
|
||||
import pygame
|
||||
from math import floor
|
||||
|
||||
from ui.auxiliary_decorator import _return_itself
|
||||
|
||||
class InputBox:
|
||||
from ui.button import Button
|
||||
from ui.button import get_fixed_rgb
|
||||
from ui.button import _transform_rgb
|
||||
from ui.text_box import _return_value_or_default
|
||||
|
||||
|
||||
class InputBox(Button):
|
||||
backspace_tick = 0
|
||||
backspace_deleted_streak = 0
|
||||
backspace_breakpoint = 6
|
||||
deleting_speeds = [12, 4]
|
||||
was_enter_hit = False
|
||||
|
||||
# constructor that can be used to set parameters of InputBox instance
|
||||
def __init__(
|
||||
self,
|
||||
position,
|
||||
dimensions,
|
||||
text="",
|
||||
input_box_position=None,
|
||||
input_box_dimensions=None,
|
||||
label="",
|
||||
user_input="",
|
||||
box_color=(195, 195, 195),
|
||||
input_box_color=(225, 245, 245),
|
||||
writing_highlight_color=(150, 255, 255),
|
||||
inner_box_color=(205, 205, 205),
|
||||
bottom_strip_color=(180, 180, 180),
|
||||
font=pygame.font.get_default_font(),
|
||||
@ -28,13 +37,46 @@ class InputBox:
|
||||
is_active=True,
|
||||
input_centered=False,
|
||||
fit_text=True,
|
||||
clear_input_on_click=False,
|
||||
outline=True,
|
||||
irregular_outline=False,
|
||||
outline_additional_pixel=False,
|
||||
outline_hover_inclusive=True,
|
||||
outline_thickness=None,
|
||||
outline_color=(50, 50, 50),
|
||||
box_transform_hover=1,
|
||||
box_transform_inactive=1,
|
||||
font_transform_hover=1,
|
||||
font_transform_inactive=1,
|
||||
outline_transform_hover=1,
|
||||
outline_transform_inactive=0.9,
|
||||
input_box_transform_hover=1.07,
|
||||
input_box_transform_selected=2,
|
||||
input_box_transform_inactive=0.9
|
||||
):
|
||||
super().__init__(
|
||||
position=position,
|
||||
dimensions=dimensions,
|
||||
text=text,
|
||||
box_color=box_color,
|
||||
font_color=font_color,
|
||||
is_visible=is_visible,
|
||||
is_active=is_active,
|
||||
fit_text=fit_text,
|
||||
outline=outline,
|
||||
irregular_outline=irregular_outline,
|
||||
outline_additional_pixel=outline_additional_pixel,
|
||||
outline_hover_inclusive=outline_hover_inclusive,
|
||||
outline_thickness=outline_thickness,
|
||||
outline_color=outline_color,
|
||||
box_transform_hover=box_transform_hover,
|
||||
box_transform_inactive=box_transform_inactive,
|
||||
font_transform_hover=font_transform_hover,
|
||||
font_transform_inactive=font_transform_inactive,
|
||||
outline_transform_hover=outline_transform_hover,
|
||||
outline_transform_inactive=outline_transform_inactive
|
||||
)
|
||||
|
||||
# extracting and setting values
|
||||
smaller_dimension = min(dimensions)
|
||||
box_x, box_y = position
|
||||
@ -49,59 +91,59 @@ class InputBox:
|
||||
default_input_box_position = (box_x + width / 12, box_y + height / 2)
|
||||
default_input_box_dimensions = (width - width / 6, 3 * height / 10)
|
||||
|
||||
# counting default outline thickness
|
||||
default_outline_thickness = (smaller_dimension + (width + height) / 4) / 50
|
||||
|
||||
# setting attributes
|
||||
self.position = position
|
||||
self.dimensions = dimensions
|
||||
self.input_box_position = _return_value_or_default(input_box_position, default_input_box_position)
|
||||
self.input_box_dimensions = _return_value_or_default(input_box_dimensions, default_input_box_dimensions)
|
||||
self.label = label
|
||||
self.user_input = user_input
|
||||
self.box_color = _get_proper_rgb(box_color)
|
||||
self.ib_color = _get_proper_rgb(input_box_color)
|
||||
self.inner_box_color = _get_proper_rgb(inner_box_color)
|
||||
self.bottom_strip_color = _get_proper_rgb(bottom_strip_color)
|
||||
self.font_color = _get_proper_rgb(font_color)
|
||||
self.ib_color = get_fixed_rgb(input_box_color)
|
||||
self.typing_highlight_color = get_fixed_rgb(writing_highlight_color)
|
||||
self.inner_box_color = get_fixed_rgb(inner_box_color)
|
||||
self.bottom_strip_color = get_fixed_rgb(bottom_strip_color)
|
||||
self.clear_input_on_click = clear_input_on_click
|
||||
self.font_size = _return_value_or_default(font_size, floor(smaller_dimension / 2.8))
|
||||
self.font = pygame.font.SysFont(font, self.font_size)
|
||||
self.input_font_size = max(15, floor(self.input_box_dimensions[1] - 2))
|
||||
self.input_font = pygame.font.SysFont(font, self.input_font_size)
|
||||
self.is_visible = is_visible
|
||||
self.is_active = is_active
|
||||
self.is_selected = False
|
||||
self.is_active = is_active
|
||||
self.input_centered = input_centered
|
||||
self.fit_text = fit_text
|
||||
self.outline = outline
|
||||
self.outline_thickness = _return_value_or_default(outline_thickness, default_outline_thickness)
|
||||
self.outline_color = outline_color
|
||||
self.ib_transform_hover = input_box_transform_hover
|
||||
self.ib_transform_selected = input_box_transform_selected
|
||||
self.ib_transform_inactive = input_box_transform_inactive
|
||||
self.backspace_pressed_down = False
|
||||
|
||||
# rendering label to get it's width and height
|
||||
rendered_label = self.font.render(label, True, (0, 0, 0))
|
||||
# rendering text to get it's width and height
|
||||
rendered_text = self.font.render(text, True, (0, 0, 0))
|
||||
|
||||
# if text is out of bounds and fit_text=True - resizing text to fit the box
|
||||
if self.fit_text and rendered_label.get_width() > self.input_box_dimensions[0]:
|
||||
self.font_size = floor(self.font_size / (rendered_label.get_width() / width + 0.1))
|
||||
if self.fit_text and rendered_text.get_width() > self.input_box_dimensions[0]:
|
||||
self.font_size = floor(self.font_size / (rendered_text.get_width() / width + 0.1))
|
||||
self.font = pygame.font.SysFont(font, self.font_size)
|
||||
|
||||
# counting colors on: hover, inactive, selected
|
||||
self.ib_hover_color = _get_proper_rgb(tuple(_transform(self.ib_color, self.ib_transform_hover)))
|
||||
self.ib_inactive_color = _get_proper_rgb(tuple(_transform(self.ib_color, self.ib_transform_inactive)))
|
||||
self.ib_selected_color = _get_proper_rgb(tuple(_transform(self.ib_color, self.ib_transform_selected)))
|
||||
self.ib_hover_color = get_fixed_rgb(tuple(_transform_rgb(self.ib_color, self.ib_transform_hover)))
|
||||
self.ib_inactive_color = get_fixed_rgb(tuple(_transform_rgb(self.ib_color, self.ib_transform_inactive)))
|
||||
self.ib_selected_color = get_fixed_rgb(tuple(_transform_rgb(self.ib_color, self.ib_transform_selected)))
|
||||
|
||||
# draws, updates and selects on mouse click the InputBox instance
|
||||
def run(self, window, mouse_position, events):
|
||||
self.select_on_click(mouse_position, events)
|
||||
self.clear_user_input_on_click(mouse_position, events)
|
||||
self.draw(window, mouse_position)
|
||||
self.update(events)
|
||||
|
||||
@_return_itself
|
||||
# draws an InputBox instance (doesn't run interactions [for everything use run(self, ...) method])
|
||||
def draw(self, window, mouse_position):
|
||||
def draw(self, window, mouse_position, *args, **kwargs):
|
||||
text_attribute_value = self.text
|
||||
|
||||
self.text = ""
|
||||
|
||||
super().draw(window, mouse_position, *args, **kwargs)
|
||||
|
||||
# resetting original attribute values
|
||||
self.text = text_attribute_value
|
||||
|
||||
# if is_visible=True drawing the InputBox
|
||||
if self.is_visible:
|
||||
# extracting and setting values from attributes
|
||||
@ -110,12 +152,6 @@ class InputBox:
|
||||
input_box_x, input_box_y = self.input_box_position
|
||||
input_width, input_height = self.input_box_dimensions
|
||||
|
||||
# if outline=True - drawing an outline
|
||||
if self.outline:
|
||||
padding = self.outline_thickness
|
||||
outline_coordinates = (box_x - padding, box_y - padding, width + 2 * padding, height + 2 * padding)
|
||||
pygame.draw.rect(window, self.outline_color, outline_coordinates)
|
||||
|
||||
# setting "transparent" background color
|
||||
text_background_color = self.ib_color
|
||||
|
||||
@ -123,7 +159,7 @@ class InputBox:
|
||||
# is selected
|
||||
if self.is_selected:
|
||||
input_box_color = self.ib_selected_color
|
||||
text_background_color = (150, 255, 255)
|
||||
text_background_color = self.typing_highlight_color
|
||||
|
||||
# is active and mouse is not over
|
||||
elif not self.is_over(mouse_position) and self.is_active:
|
||||
@ -137,9 +173,6 @@ class InputBox:
|
||||
else:
|
||||
input_box_color = self.ib_inactive_color
|
||||
|
||||
# drawing outer box
|
||||
pygame.draw.rect(window, self.box_color, (box_x, box_y, width, height))
|
||||
|
||||
# drawing inner (upper) box
|
||||
pygame.draw.rect(window,
|
||||
self.inner_box_color,
|
||||
@ -152,13 +185,13 @@ class InputBox:
|
||||
# drawing bottom strip
|
||||
pygame.draw.rect(window, self.bottom_strip_color, (box_x, box_y + 9 * height / 10, width, 1 * height / 10))
|
||||
|
||||
# rendering label and counting its coordinates
|
||||
rendered_label = self.font.render(self.label, True, self.font_color)
|
||||
rendered_label_x = box_x + width / 2 - rendered_label.get_width() / 2
|
||||
rendered_label_y = box_y + height / 4 - rendered_label.get_height() / 2
|
||||
# rendering text and counting its coordinates
|
||||
rendered_text = self.font.render(self.text, True, self.font_color)
|
||||
rendered_text_x = box_x + width / 2 - rendered_text.get_width() / 2
|
||||
rendered_text_y = box_y + height / 4 - rendered_text.get_height() / 2
|
||||
|
||||
# drawing the label on the coordinates
|
||||
window.blit(rendered_label, (rendered_label_x, rendered_label_y))
|
||||
# drawing the text on the coordinates
|
||||
window.blit(rendered_text, (rendered_text_x, rendered_text_y))
|
||||
|
||||
# rendering input
|
||||
rendered_input_text = self.input_font.render(self.user_input, True, self.font_color, text_background_color)
|
||||
@ -177,6 +210,9 @@ class InputBox:
|
||||
|
||||
# updates InputBox'es attributes if user types something in it
|
||||
def update(self, events):
|
||||
# resetting attribute value
|
||||
self.was_enter_hit = False
|
||||
|
||||
# if the InputBox is selected - updating the input text
|
||||
if self.is_selected:
|
||||
self._delete_characters_if_backspace_pressed()
|
||||
@ -194,6 +230,7 @@ class InputBox:
|
||||
|
||||
elif event.key == pygame.K_RETURN:
|
||||
self.is_selected = False
|
||||
self.was_enter_hit = True
|
||||
|
||||
# if text isn't too long - adding a character
|
||||
elif rendered_input.get_width() + 10 < self.input_box_dimensions[0]:
|
||||
@ -210,28 +247,42 @@ class InputBox:
|
||||
# if is active set is_selected attribute accordingly
|
||||
if self.is_active:
|
||||
for event in events:
|
||||
# if mouse is clicked set as selected if mouse is over, or set as not selected otherwise
|
||||
|
||||
if event.type == pygame.MOUSEBUTTONUP:
|
||||
self.set_is_selected(self.is_over(mouse_position))
|
||||
|
||||
# checks if a position is over the InputBox and returns True or False
|
||||
def is_over(self, position):
|
||||
mouse_x, mouse_y = position
|
||||
button_x, button_y = self.position
|
||||
width, height = self.dimensions
|
||||
# clears user's input on click
|
||||
def clear_user_input_on_click(self, mouse_position, events):
|
||||
if self.is_active and self.clear_input_on_click:
|
||||
for event in events:
|
||||
|
||||
return button_x <= mouse_x <= (button_x + width) and button_y <= mouse_y <= (button_y + height)
|
||||
if event.type == pygame.MOUSEBUTTONUP and self.is_over(mouse_position):
|
||||
self.clear_input()
|
||||
|
||||
# returns InputBox'es label
|
||||
def get_label(self):
|
||||
return self.label
|
||||
# returns True if user input is empty, or False otherwise
|
||||
def is_input_empty(self):
|
||||
return not any(self.user_input)
|
||||
|
||||
# clears user's input
|
||||
def clear_input(self):
|
||||
self.user_input = ""
|
||||
|
||||
# returns True if enter key is hit, or False otherwise
|
||||
def is_enter_hit(self, events):
|
||||
|
||||
if self.is_active and self.is_selected:
|
||||
for event in events:
|
||||
if event.type == pygame.KEYDOWN and event.key == pygame.K_RETURN:
|
||||
return True
|
||||
|
||||
return self.was_enter_hit
|
||||
|
||||
# returns InputBox'es user's input
|
||||
def get_input(self):
|
||||
return self.user_input
|
||||
|
||||
# sets chosen coordinates
|
||||
def set_space(
|
||||
def set_coordinates(
|
||||
self,
|
||||
position=None,
|
||||
dimensions=None,
|
||||
@ -239,11 +290,7 @@ class InputBox:
|
||||
input_box_dimensions=None,
|
||||
outline_thickness=None
|
||||
):
|
||||
if position is not None:
|
||||
self.position = position
|
||||
|
||||
if dimensions is not None:
|
||||
self.dimensions = dimensions
|
||||
super().set_coordinates(position=position, dimensions=dimensions, outline_thickness=outline_thickness)
|
||||
|
||||
if input_box_position is not None:
|
||||
self.input_box_position = input_box_position
|
||||
@ -251,13 +298,9 @@ class InputBox:
|
||||
if input_box_dimensions is not None:
|
||||
self.input_box_dimensions = input_box_dimensions
|
||||
|
||||
if outline_thickness is not None:
|
||||
self.outline_thickness = outline_thickness
|
||||
|
||||
# sets chosen text attributes
|
||||
def set_texts(self, label=None, user_input=None):
|
||||
if label is not None:
|
||||
self.label = label
|
||||
def set_texts(self, text=None, user_input=None):
|
||||
super().set_text(text=text)
|
||||
|
||||
if user_input is not None:
|
||||
self.user_input = user_input
|
||||
@ -268,15 +311,14 @@ class InputBox:
|
||||
self.font_size = font_size
|
||||
|
||||
# rendering text to get it's width and height
|
||||
rendered_text = self.font.render(self.user_input, True, (0, 0, 0))
|
||||
rendered_text = self.font.render(self.text, True, (0, 0, 0))
|
||||
|
||||
# if text is out of bounds and fit_text=True - resizing text to fit the box
|
||||
if self.fit_text and rendered_text.get_width() > self.dimensions[0]:
|
||||
if self.fit_text and rendered_text.get_width() > self.input_box_dimensions[0]:
|
||||
self.font_size = floor(self.font_size / (rendered_text.get_width() / self.dimensions[0] + 0.1))
|
||||
self.font = pygame.font.SysFont(font, self.font_size)
|
||||
|
||||
if font is not None:
|
||||
self.font = pygame.font.SysFont(font, self.font_size)
|
||||
super().set_font(font=font)
|
||||
|
||||
# sets chosen color attributes
|
||||
def set_colors(
|
||||
@ -284,30 +326,39 @@ class InputBox:
|
||||
box_color=None,
|
||||
input_box_color=None,
|
||||
inner_box_color=None,
|
||||
writing_highlight_color=None,
|
||||
bottom_strip_color=None,
|
||||
font_color=None,
|
||||
outline_color=None,
|
||||
box_transform_hover=None,
|
||||
box_transform_inactive=None,
|
||||
font_transform_hover=None,
|
||||
font_transform_inactive=None,
|
||||
input_box_transform_hover=None,
|
||||
input_box_transform_selected=None,
|
||||
input_box_transform_inactive=None
|
||||
input_box_transform_inactive=None,
|
||||
):
|
||||
if box_color is not None:
|
||||
self.box_color = _get_proper_rgb(box_color)
|
||||
super().set_colors(
|
||||
box_color=box_color,
|
||||
font_color=font_color,
|
||||
outline_color=outline_color,
|
||||
box_transform_hover=box_transform_hover,
|
||||
box_transform_inactive=box_transform_inactive,
|
||||
font_transform_hover=font_transform_hover,
|
||||
font_transform_inactive=font_transform_inactive
|
||||
)
|
||||
|
||||
if input_box_color is not None:
|
||||
self.ib_color = _get_proper_rgb(input_box_color)
|
||||
self.ib_color = get_fixed_rgb(input_box_color)
|
||||
|
||||
if writing_highlight_color is not None:
|
||||
self.typing_highlight_color = writing_highlight_color
|
||||
|
||||
if inner_box_color is not None:
|
||||
self.inner_box_color = _get_proper_rgb(inner_box_color)
|
||||
self.inner_box_color = get_fixed_rgb(inner_box_color)
|
||||
|
||||
if bottom_strip_color is not None:
|
||||
self.bottom_strip_color = _get_proper_rgb(bottom_strip_color)
|
||||
|
||||
if font_color is not None:
|
||||
self.font_color = _get_proper_rgb(font_color)
|
||||
|
||||
if outline_color is not None:
|
||||
self.outline_color = _get_proper_rgb(outline_color)
|
||||
self.bottom_strip_color = get_fixed_rgb(bottom_strip_color)
|
||||
|
||||
if input_box_transform_hover is not None:
|
||||
self.ib_transform_hover = input_box_transform_hover
|
||||
@ -318,14 +369,29 @@ class InputBox:
|
||||
if input_box_transform_inactive is not None:
|
||||
self.ib_transform_inactive = input_box_transform_inactive
|
||||
|
||||
self.ib_hover_color = _get_proper_rgb(tuple(_transform(self.ib_color, self.ib_transform_hover)))
|
||||
self.ib_inactive_color = _get_proper_rgb(tuple(_transform(self.ib_color, self.ib_transform_inactive)))
|
||||
self.ib_selected_color = _get_proper_rgb(tuple(_transform(self.ib_color, self.ib_transform_selected)))
|
||||
self.ib_hover_color = get_fixed_rgb(tuple(_transform_rgb(self.ib_color, self.ib_transform_hover)))
|
||||
self.ib_inactive_color = get_fixed_rgb(tuple(_transform_rgb(self.ib_color, self.ib_transform_inactive)))
|
||||
self.ib_selected_color = get_fixed_rgb(tuple(_transform_rgb(self.ib_color, self.ib_transform_selected)))
|
||||
|
||||
# sets chosen flag attributes
|
||||
def set_flags(self, is_visible=None, is_active=None, input_centered=None, fit_text=None, outline=None):
|
||||
if is_visible is not None:
|
||||
self.is_visible = is_visible
|
||||
def set_flags(
|
||||
self,
|
||||
is_visible=None,
|
||||
is_active=None,
|
||||
input_centered=None,
|
||||
fit_text=None,
|
||||
outline=None,
|
||||
irregular_outline=None,
|
||||
outline_additional_pixel=None,
|
||||
outline_hover_inclusive=None
|
||||
):
|
||||
super().set_flags(
|
||||
is_visible=is_visible,
|
||||
outline=outline,
|
||||
irregular_outline=None,
|
||||
outline_additional_pixel=None,
|
||||
outline_hover_inclusive=None
|
||||
)
|
||||
|
||||
if is_active is not None:
|
||||
self.is_active = is_active
|
||||
@ -336,9 +402,6 @@ class InputBox:
|
||||
if fit_text is not None:
|
||||
self.fit_text = fit_text
|
||||
|
||||
if outline is not None:
|
||||
self.outline = outline
|
||||
|
||||
# sets is_selected with a given value
|
||||
def set_is_selected(self, is_selected):
|
||||
self.is_selected = is_selected
|
||||
@ -360,18 +423,3 @@ class InputBox:
|
||||
|
||||
elif self.backspace_pressed_down:
|
||||
self.backspace_tick += 1
|
||||
|
||||
|
||||
def _get_proper_rgb(x):
|
||||
r, g, b = x
|
||||
r, g, b = max(0, min(255, floor(r))), max(0, min(255, floor(g))), max(0, min(255, floor(b)))
|
||||
|
||||
return tuple((r, g, b))
|
||||
|
||||
|
||||
def _transform(iterable, transform_value):
|
||||
return [x * transform_value for x in iterable]
|
||||
|
||||
|
||||
def _return_value_or_default(value, default):
|
||||
return default if value is None else value
|
||||
|
@ -16,6 +16,9 @@ class TextBox:
|
||||
is_visible=True,
|
||||
fit_text=True,
|
||||
outline=True,
|
||||
irregular_outline=False,
|
||||
outline_additional_pixel=False,
|
||||
outline_hover_inclusive=True,
|
||||
outline_thickness=None,
|
||||
outline_color=(50, 50, 50)
|
||||
):
|
||||
@ -24,21 +27,24 @@ class TextBox:
|
||||
width, height = dimensions
|
||||
|
||||
# counting default outline thickness
|
||||
default_outline_thickness = (smaller_dimension + (width + height) / 4) / 50
|
||||
default_outline_thickness = max(1, floor((2 * smaller_dimension + width + height) / 200))
|
||||
|
||||
# setting attributes
|
||||
self.position = position
|
||||
self.dimensions = dimensions
|
||||
self.text = text
|
||||
self.box_color = _get_proper_rgb(box_color)
|
||||
self.font_color = _get_proper_rgb(font_color)
|
||||
self.box_color = get_fixed_rgb(box_color)
|
||||
self.font_color = get_fixed_rgb(font_color)
|
||||
self.font_size = _return_value_or_default(font_size, floor(smaller_dimension / 2))
|
||||
self.font = pygame.font.SysFont(font, self.font_size)
|
||||
self.is_visible = is_visible
|
||||
self.fit_text = fit_text
|
||||
self.outline = outline
|
||||
self.irregular_outline = irregular_outline
|
||||
self.outline_additional_pixel = outline_additional_pixel
|
||||
self.outline_hover_inclusive = outline_hover_inclusive
|
||||
self.outline_thickness = _return_value_or_default(outline_thickness, default_outline_thickness)
|
||||
self.outline_color = _get_proper_rgb(outline_color)
|
||||
self.outline_color = get_fixed_rgb(outline_color)
|
||||
|
||||
# rendering text to get it's width and height
|
||||
rendered_text = self.font.render(text, True, (0, 0, 0))
|
||||
@ -49,7 +55,7 @@ class TextBox:
|
||||
self.font = pygame.font.SysFont(font, self.font_size)
|
||||
|
||||
# draws the TextBox
|
||||
def draw(self, window):
|
||||
def draw(self, window, *args, **kwargs):
|
||||
# if is_visible=True drawing the TextBox
|
||||
if self.is_visible:
|
||||
# extracting and setting values from attributes
|
||||
@ -58,8 +64,9 @@ class TextBox:
|
||||
|
||||
# if outline=True - drawing an outline
|
||||
if self.outline:
|
||||
padding = self.outline_thickness
|
||||
padding = self.outline_thickness - self.irregular_outline / 2 + self.outline_additional_pixel
|
||||
outline_coordinates = (box_x - padding, box_y - padding, width + 2 * padding, height + 2 * padding)
|
||||
|
||||
pygame.draw.rect(window, self.outline_color, outline_coordinates)
|
||||
|
||||
# drawing the box
|
||||
@ -73,6 +80,27 @@ class TextBox:
|
||||
# drawing the box on the coordinates
|
||||
window.blit(rendered_text, (rendered_text_x, rendered_text_y))
|
||||
|
||||
# checks if a position is over the InputBox and returns True or False
|
||||
def is_over(self, position):
|
||||
mouse_x, mouse_y = position
|
||||
|
||||
if not self.outline_hover_inclusive:
|
||||
button_x, button_y = self.position
|
||||
width, height = self.dimensions
|
||||
|
||||
else:
|
||||
padding = self.outline_thickness
|
||||
button_x, button_y = self.position
|
||||
width, height = self.dimensions
|
||||
button_x, button_y = button_x - padding, button_y - padding
|
||||
width, height = width + 2 * padding, height + 2 * padding
|
||||
|
||||
return button_x <= mouse_x <= (button_x + width) and button_y <= mouse_y <= (button_y + height)
|
||||
|
||||
# returns text value
|
||||
def get_text(self):
|
||||
return self.text
|
||||
|
||||
# sets chosen coordinates
|
||||
def set_coordinates(self, position=None, dimensions=None, outline_thickness=None):
|
||||
if position is not None:
|
||||
@ -86,6 +114,7 @@ class TextBox:
|
||||
|
||||
# sets the TextBox's text
|
||||
def set_text(self, text):
|
||||
if text is not None:
|
||||
self.text = text
|
||||
|
||||
# sets chosen font attributes
|
||||
@ -107,25 +136,41 @@ class TextBox:
|
||||
# sets chosen color attributes
|
||||
def set_colors(self, box_color=None, font_color=None, outline_color=None):
|
||||
if box_color is not None:
|
||||
self.box_color = _get_proper_rgb(box_color)
|
||||
self.box_color = get_fixed_rgb(box_color)
|
||||
|
||||
if font_color is not None:
|
||||
self.font_color = _get_proper_rgb(font_color)
|
||||
self.font_color = get_fixed_rgb(font_color)
|
||||
|
||||
if outline_color is not None:
|
||||
self.outline_color = outline_color
|
||||
|
||||
# sets chosen flags
|
||||
def set_flags(self, is_visible=None, outline=None):
|
||||
def set_flags(
|
||||
self,
|
||||
is_visible=None,
|
||||
outline=None,
|
||||
irregular_outline=None,
|
||||
outline_additional_pixel=None,
|
||||
outline_hover_inclusive=None
|
||||
):
|
||||
if is_visible is not None:
|
||||
self.is_visible = is_visible
|
||||
|
||||
if outline is not None:
|
||||
self.outline = outline
|
||||
|
||||
if irregular_outline is not None:
|
||||
self.irregular_outline = irregular_outline
|
||||
|
||||
if outline_additional_pixel is not None:
|
||||
self.outline_additional_pixel = outline_additional_pixel
|
||||
|
||||
if outline_hover_inclusive is not None:
|
||||
self.outline_hover_inclusive = outline_hover_inclusive
|
||||
|
||||
|
||||
# returns values that are not out of range
|
||||
def _get_proper_rgb(x):
|
||||
def get_fixed_rgb(x):
|
||||
r, g, b = x
|
||||
r, g, b = max(0, min(255, floor(r))), max(0, min(255, floor(g))), max(0, min(255, floor(b)))
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user