From 8cfff1febe04e89f4e5aa558348cc210605dce58 Mon Sep 17 00:00:00 2001 From: LoafyLemon Date: Thu, 7 Nov 2024 08:44:09 +0000 Subject: [PATCH] Wardrobe 2.0 - Performance boost, hook cache into export func --- game/scripts/doll/clothes.rpy | 7 ++- game/scripts/doll/outfits.rpy | 78 +++++++++++------------------- game/scripts/wardrobe/wardrobe.rpy | 11 +++-- 3 files changed, 40 insertions(+), 56 deletions(-) diff --git a/game/scripts/doll/clothes.rpy b/game/scripts/doll/clothes.rpy index 185e059f..42b88b17 100644 --- a/game/scripts/doll/clothes.rpy +++ b/game/scripts/doll/clothes.rpy @@ -177,7 +177,7 @@ init python: @functools.cache def build_icon(self, hash): if (d := self.get_disk_cache(hash)): - return d + return AlphaMask(Transform(d, xysize=(96, 96)), Transform("wheelmenu_button_opaque", xysize=(96, 96))) matrix = SaturationMatrix(0.0) sprites = [i for i in self.build_image(hash, matrix=matrix) if not i[0] == "mask"] @@ -209,7 +209,7 @@ init python: y = hmax-h d = Transform(Fixed(*[i[1] for i in sprites], fit_first=True), crop=(x, y, w, h), size=(256, 256), fit="contain", align=(0.5, 0.5)) - return self.create_disk_cache(d, hash) + return AlphaMask(Transform(self.create_disk_cache(d, hash), xysize=(96, 96)), Transform("wheelmenu_button_opaque", xysize=(96, 96))) @property def icon(self): @@ -230,7 +230,7 @@ init python: blacklister = self.char.get_blacklister(self.type) # Victim (List clothing types blacklisting this item ) warnings.append("Incompatible with:{size=-4}\n" + "\n".join(set(blacklisted + blacklister)) + "{/size}") - child = AlphaMask(Transform(self.icon, xysize=(96, 96)), Transform("wheelmenu_button_opaque", xysize=(96, 96))) + child = self.icon hbox = [] overlay = [] @@ -276,7 +276,6 @@ init python: else: alternate = [Function(wardrobe.equip, self), Function(wardrobe.jump_to_item, self, "color_picker")] - return Button(child=child, focus_mask=None, xysize=(96, 96), action=action, tooltip=("\n".join(warnings)), unhovered=unhovered, style=style, selected=is_equipped, alternate=alternate) @functools.cache diff --git a/game/scripts/doll/outfits.rpy b/game/scripts/doll/outfits.rpy index b249e2d1..cdba035c 100644 --- a/game/scripts/doll/outfits.rpy +++ b/game/scripts/doll/outfits.rpy @@ -92,21 +92,21 @@ init python: @functools.cache def build_icon(self, hash): sprite = self.build_image(self._hash) - - return Transform(sprite, crop=(220, 0, 680, 1200), size=(96, 168), fit="contain", align=(0.5, 1.0), yoffset=-6) + sprite = Transform(sprite, crop=(220, 0, 680, 1200), size=(96, 168), fit="contain", align=(0.5, 1.0), yoffset=-6) + return AlphaMask(Transform(sprite, xysize=(96, 168)), Transform("wheelmenu_button_opaque", xysize=(96, 168))) @property def icon(self): return self.build_icon(self._hash) def _build_button(self, _hash): - style = "wardrobe_item_button" - # is_equipped = self.char.is_equipped_item(self) + style = "wardrobe_item_rectangular_button" + is_equipped = self.char.is_equipped_item(self) is_modded = self.is_modded() # is_inadequate = wardrobe.wardrobe_check_equip_outfit(self) has_schedule = any(self.schedule.values()) - child = Frame(gui.format("interface/frames/{}/iconframe.webp"), 6, 6) + child = self.icon warnings = [] hbox = [] vbox = [] @@ -119,40 +119,9 @@ init python: action = [Function(wardrobe.wheelmenu, self, "outfits"), self.build_button] alternate = None unhovered = None - foreground = None - hover_foreground = "#ffffff80" - selected_foreground = None - - # if is_inadequate: - # foreground = "#b2000040" - # hover_foreground = "#CD5C5C40" - # selected_foreground = "#CD5C5C40" - - # if subcat == "delete": - # action = Return(["deloutfit", self]) - # elif subcat == "load": - # action = Return(["equip", self]) - # elif subcat == "save": - # action = Return(["addoutfit", self]) - # elif subcat == "export": - # action = Return(["export", self]) - # elif subcat == "schedule": - # if not has_schedule and not is_inadequate: - # action = Return(["schedule", self]) - # alternate = Return(["schedule", self]) - # foreground = "#00000040" - # hover_foreground = "#80808040" - # selected_foreground = "#80808040" - # elif has_schedule: - # action = Return(["schedule", self]) - # alternate = Return(["schedule", self]) - # # elif is_inadequate: - # # foreground = "#b2000040" - # # hover_foreground = "#CD5C5C40" - # # selected_foreground = "#CD5C5C40" if has_schedule: - for i in wardrobe.outfit_schedule: # Wardrobe store var + for i in wardrobe.outfit_schedule: # NONLOCAL if self.schedule[i]: vbox.append(Transform(f"interface/wardrobe/icons/outfits/{i}.webp", size=(16, 16), offset=(6, 6))) @@ -165,7 +134,7 @@ init python: if hbox: child = Fixed(child, HBox(*hbox), fit_first=True) - return Button(child=child, focus_mask=None, xysize=(96, 168), background=self.icon, action=action, alternate=alternate, tooltip=("\n".join(warnings)), foreground=foreground, hover_foreground=hover_foreground, selected_foreground=selected_foreground, unhovered=unhovered, style=style) + return Button(child=child, focus_mask=None, xysize=(96, 168), action=action, tooltip=("\n".join(warnings)), unhovered=unhovered, style=style, selected=is_equipped, alternate=alternate) @functools.cache def build_button(self): @@ -193,6 +162,10 @@ init python: def export_data(self, filename, tofile=True): """Exports outfit to .png file or clipboard text.""" + # Export data consists of the following: + # [0] - Character name + # [1] - [Item ID, Colour List] + exported = [self.group[0].name] for i in self.group: @@ -202,25 +175,32 @@ init python: # Encode data if tofile: - path = os.path.join(config.gamedir, "outfits") + fp_input = os.path.join("game", "outfits").replace("\\", "/") # Ren'py Paths are UNIX based + fn_input = f"{self._hash}_temp.png" + fn_output = f"{self._hash}.png" + fpt_output = os.path.join(fp_input, fn_input).replace("\\", "/") # Ren'py Paths are UNIX based - if not os.path.exists(path): - os.makedirs(path) + osfp = os.path.join(config.basedir, fpt_output) # Python paths are OS based - path = os.path.join(path, "_temp.png") + if not os.path.exists(fp_input): + os.makedirs(fp_input) - d = Transform(self.image, crop=(210, 200, 700, 1000), anchor=(0.5, 1.0), align=(0.5, 1.0), xsize=310, ysize=470, fit="contain") + width, height = self.sizes + d = self.build_image(self._hash) + # d = Transform(d, crop=(220, 0, 680, 1200), size=(96, 168), fit="contain", align=(0.5, 1.0), yoffset=-6) d = Fixed( - "interface/wardrobe/export_background.webp", d, - "interface/wardrobe/export_frame.webp", Text(states.active_girl, align=(0.5, 0.995)), - Text(f"Ver. {config.version}", size=10, align=(0.99, 0.99)) + Text(f"Ver. {config.version}", size=24, align=(0.99, 0.99)) ) - displayable_to_file(d, path, size=(310, 470) ) - image_payload.inject("_temp.png", filename, str(exported)) - os.remove(path) + try: + renpy.render_to_file(d, fpt_output, width=width, height=height, resize=True) + except Exception as e: + print(f"Warning! Failed to write to path: {fp}/{fn_input} - {e}") + + image_payload.inject(fn_input, fn_output, str(exported)) + os.remove(osfp) # Remove temp file else: set_clipboard(exported) renpy.notify("Export successful!") diff --git a/game/scripts/wardrobe/wardrobe.rpy b/game/scripts/wardrobe/wardrobe.rpy index 19e48305..2803928c 100644 --- a/game/scripts/wardrobe/wardrobe.rpy +++ b/game/scripts/wardrobe/wardrobe.rpy @@ -22,7 +22,6 @@ default wardrobe.allow_opacity = False # Functions init python in wardrobe: import functools - import datetime import os from collections import OrderedDict @@ -65,10 +64,11 @@ init python in wardrobe: def change_category(category): scope = renpy.get_screen("wardrobe").scope + character = scope["character"] if scope["selected_category"] == category: return scope["selected_category"] = category - scope["selected_subcategory"] = None + scope["selected_subcategory"] = next((subcat for subcat in character.wardrobe[category]), None) def change_subcategory(subcategory): scope = renpy.get_screen("wardrobe").scope @@ -273,7 +273,7 @@ init python in wardrobe: d = {} if section == "outfits": delete_action = item.delete - export_action = renpy.store.Function(item.export_data, datetime.datetime.now().strftime("%d %b %Y-%H%M%S") + ".png") + export_action = renpy.store.Function(item.export_data, f"{item._hash}.png") overwrite_action = renpy.store.Function(_overwrite_outfit, character, item) d[_("Equip")] = (renpy.store.Text("👗", align=(0.5, 0.5)), [exit_action, equip_action]) @@ -670,6 +670,11 @@ style wardrobe_item_small_button is wardrobe_item_button: hover_background At(Transform("wheelmenu_button_opaque", xysize=(48,48)), wheelmenu_hover_anim) selected_foreground Transform("interface/topbar/icon_check.webp", align=(1.0, 1.0), size=(24, 24)) +style wardrobe_item_rectangular_button is wardrobe_item_button: + background Transform("wheelmenu_button", xysize=(96,168)) + hover_background At(Transform("wheelmenu_button_opaque", xysize=(96,168)), wheelmenu_hover_anim) + selected_foreground Transform("interface/topbar/icon_check.webp", align=(1.0, 1.0), size=(24, 24)) + style wardrobe_outline: padding (2, 2) foreground Frame(Image("gui/creamy_pumpkin_pie/colorpicker/colorpicker_outline.png"), 2, 0, 2, 0, tile=False)