Skip to content
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

List UI more optimized #64

Merged
merged 3 commits into from
Jun 16, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 83 additions & 31 deletions engine/uimenu/uimenu.py
Original file line number Diff line number Diff line change
Expand Up @@ -1479,6 +1479,8 @@ def get_size(self):

class ListUI(UIMenu, Containable):

frame = None

def __init__(self, origin, pivot, size, items, parent, item_size, layer=0):

from engine.game.game import Game
Expand All @@ -1489,9 +1491,12 @@ def __init__(self, origin, pivot, size, items, parent, item_size, layer=0):
self.pivot = pivot
self.origin = origin
self.parent = parent
frame_file = "new_button.png" # "list_frame.png" # using the button frame to test if it looks good
self.frame = load_image(game.module_dir, (1, 1), frame_file, ("ui", "mainmenu_ui"))
self.scroll_box_frame = load_image(game.module_dir, (1, 1), "scroll_box_frame.png", ("ui", "mainmenu_ui"))

# if the frame images are the same for every list we can store them in class variables
if ListUI.frame is None:
frame_file = "new_button.png" # "list_frame.png" # using the button frame to test if it looks good
ListUI.frame = load_image(game.module_dir, (1, 1), frame_file, ("ui", "mainmenu_ui"))
ListUI.scroll_box_frame = load_image(game.module_dir, (1, 1), "scroll_box_frame.png", ("ui", "mainmenu_ui"))

self.item_size = item_size

Expand Down Expand Up @@ -1537,54 +1542,101 @@ def get_item_height(self):
def get_relative_size_inside_container(self):
return self.relative_size_inside_container



def get_refreshed_image(self):
assert type(self.scroll_box_index) == int, type(self.scroll_box_index)
item_height = self.get_item_height()
size = self.rect[2:]
self.image = make_image_by_frame(self.frame, size)
item_height = self.get_item_height()

self.image = ListUI.inner_get_refreshed_image(
self.scroll_box_index,
self.get_item_height(),
tuple(self.rect),
self.item_size,
self.items,
self.selected_index,
self.items.get_highlighted_index(),
tuple(self.get_scroll_bar_rect()) if self.get_scroll_bar_rect() else None,
tuple(self.get_scroll_box_rect()) if self.get_scroll_box_rect() else None,
self.in_scroll_box,
self.hold_scroll_box,
self.has_scroll,
self.scroll_box_height,
)
return self.image

@lru_cache(maxsize=2**4) # size has to be big enough to fit all active list ui on screen but not big enough to take to much memory
def inner_get_refreshed_image(scroll_box_index, item_height, rect, item_size, items, selected_index, highlighted_index, scroll_bar_rect, scroll_box_rect, in_scroll_box, hold_scroll_box, has_scroll, scroll_box_height):
from engine.game.game import Game

ui_font = Game.ui_font

if not type(scroll_box_index) == int: raise TypeError()
if not type(item_height) == int: raise TypeError()
if not type(rect) == tuple: raise TypeError()
if not type(item_size) == int: raise TypeError()
if not type(items) in ( CampaignListAdapter, ListAdapter ): raise TypeError(items)
if not type(selected_index) in ( type(None), int ): raise TypeError(type(selected_index))
if not type(highlighted_index) in ( int, type(None) ): raise TypeError(highlighted_index)
if not type(scroll_bar_rect) in ( type(None), tuple ): raise TypeError(scroll_bar_rect)
if not type(scroll_box_rect) in ( type(None), tuple ): raise TypeError()
if not type(in_scroll_box) == bool : raise TypeError()
if not type(hold_scroll_box) == type(None): raise TypeError(hold_scroll_box)
if not type(has_scroll) == bool: raise TypeError()
if not type(scroll_box_height) == int: raise TypeError()

scroll_box = make_image_by_frame(ListUI.scroll_box_frame, (14, scroll_box_height))

rect = pygame.Rect(*rect)
scroll_bar_rect = pygame.Rect(*scroll_bar_rect) if scroll_bar_rect else None
scroll_box_rect = pygame.Rect(*scroll_box_rect) if scroll_box_rect else None

font1 = Font(ui_font["main_button"], 20)
font2 = Font(ui_font["main_button"], 14)
font3 = Font(ui_font["main_button"], 18)

assert type(scroll_box_index) == int, type(scroll_box_index)
size = rect[2:]

image = make_image_by_frame(ListUI.frame, size)
# draw items
item_size = self.item_size
if len(self.items) < item_size: # For listui with item less than provided size
item_size = len(self.items)
if len(items) < item_size: # For listui with item less than provided size
item_size = len(items)
for i in range(item_size):
item_index = i + self.scroll_box_index
text_color = (47 if item_index == self.selected_index else 0,) * 3
if item_index == self.selected_index or item_index == self.items.get_highlighted_index():
item_index = i + scroll_box_index
text_color = (47 if item_index == selected_index else 0,) * 3
if item_index == selected_index or item_index == highlighted_index:

background_color = "#cbc2a9"
if item_index == self.items.get_highlighted_index():
if item_index == highlighted_index:
background_color = "#776622"
text_color = "#eeeeee"
draw.rect(self.image, background_color, (6, 6 + i * item_height, size[0] - 13 * self.has_scroll - 12, item_height))
draw.rect(image, background_color, (6, 6 + i * item_height, size[0] - 13 * has_scroll - 12, item_height))

font = Font(self.ui_font["main_button"], 20)
blit_text = self.items[item_index]
if self.items[item_index] is not None: # assuming list ui has only 3 levels
if ">>" in self.items[item_index] or "||" in self.items[item_index]:
font = Font(self.ui_font["main_button"], 14)
blit_text = items[item_index]
font = font1
if items[item_index] is not None: # assuming list ui has only 3 levels
if ">>" in items[item_index] or "||" in items[item_index]:
font = font2
blit_text = " " + blit_text
elif ">" in self.items[item_index] or "|" in self.items[item_index]:
font = Font(self.ui_font["main_button"], 18)
elif ">" in items[item_index] or "|" in items[item_index]:
font = font3
blit_text = " " + blit_text

self.image.blit(
image.blit(
draw_text(blit_text, font, text_color, ellipsis_length=size[0]-55),
(20, item_height // 2 + 6 - 9 + i * item_height))

# draw scroll bar
if scroll_bar_rect := self.get_scroll_bar_rect():
draw.rect(self.image, "#d2cab4", scroll_bar_rect)
if scroll_bar_rect := scroll_bar_rect:
draw.rect(image, "#d2cab4", scroll_bar_rect)

# draw scroll box
if scroll_box_rect := self.get_scroll_box_rect():
self.image.blit(self.scroll_box, scroll_box_rect)
if self.in_scroll_box or self.hold_scroll_box is not None:
draw.rect(self.image, (100, 0, 0) if self.hold_scroll_box is not None else (50,) * 3,
if scroll_box_rect := scroll_box_rect:
image.blit(scroll_box, scroll_box_rect)
if in_scroll_box or hold_scroll_box is not None:
draw.rect(image, (100, 0, 0) if hold_scroll_box is not None else (50,) * 3,
scroll_box_rect, 1)

return self.image
return image

def get_scroll_bar_rect(self):
if not self.has_scroll: return None
Expand Down