From 4b1b01eb091ee635154a364fd6e559a3eb60306b Mon Sep 17 00:00:00 2001 From: LoafyLemon Date: Fri, 14 Jul 2023 00:59:26 +0100 Subject: [PATCH] Doll performance and bug fixes * Implemented threading and lazyloading for the main doll * Added global rebuild method for the dolls * Updated save compatibility patch * Fixed wardrobe categories showing locked items --- game/scripts/doll/common.rpy | 8 ++++++++ game/scripts/doll/main.rpy | 22 ++++++++++++++++++++-- game/scripts/utility/skipping.rpy | 5 +---- game/scripts/utility/updater.rpy | 2 +- game/scripts/wardrobe/wardrobe.rpy | 21 +++++++++++++++++++-- 5 files changed, 49 insertions(+), 9 deletions(-) diff --git a/game/scripts/doll/common.rpy b/game/scripts/doll/common.rpy index 763c9dbd..59141225 100644 --- a/game/scripts/doll/common.rpy +++ b/game/scripts/doll/common.rpy @@ -74,3 +74,11 @@ init -1 python: stale = curr_hash != self._hash self._hash = curr_hash return stale + + def DollRebuild(): + for i in states.dolls: + doll = getattr(store, i) + doll.build_image() + + config.after_load_callbacks.append(DollRebuild) + # end_skip_callbacks.append(DollRebuild) \ No newline at end of file diff --git a/game/scripts/doll/main.rpy b/game/scripts/doll/main.rpy index 31f38f0e..d85bf6be 100644 --- a/game/scripts/doll/main.rpy +++ b/game/scripts/doll/main.rpy @@ -60,6 +60,7 @@ init python: self.pose = "default" self.emote = Null() self._hash = None + self._sprite = DefaultQueue() # Image properties self.zorder = 15 @@ -103,7 +104,7 @@ init python: renpy.hide(name=self.tag, layer=self.layer) @functools.cache - def build_image(self, hash): + def _build_image(self, hash): from itertools import chain # Note: Bodyparts are a part of 'self.states' now. @@ -140,13 +141,30 @@ init python: return Fixed(*sprites, self.emote, fit_first=True) + def build_image(self): + + def _func(self, hash): + result = self._build_image(hash) + self._sprite.put(result) + + thread = DollThread(target=_func, args=(self, self._hash)) + thread.start() + + def _image(self, st, at): + return self._sprite.get_with_default(None), None + @property def image(self): + if not renpy.is_skipping() and self.is_stale(): + self.build_image() + if renpy.showing(get_character_tag(self.name), layer=self.layer): self.show() + elif renpy.in_rollback(): + self.build_image() - return self.build_image(self._hash) + return DynamicDisplayable(self._image) def equip(self, obj, remove_old=True): """Takes DollCloth or DollOutfit object to equip.""" diff --git a/game/scripts/utility/skipping.rpy b/game/scripts/utility/skipping.rpy index 035bea46..e1fe93e3 100644 --- a/game/scripts/utility/skipping.rpy +++ b/game/scripts/utility/skipping.rpy @@ -1,4 +1,4 @@ -init -1 python: +init -5 python: start_skip_callbacks = [] end_skip_callbacks = [] @@ -23,6 +23,3 @@ init -1 python: c() config.interact_callbacks.append(SkipCallbacksHandler()) - - #end_skip_callbacks.append(rebuild_dolls) - diff --git a/game/scripts/utility/updater.rpy b/game/scripts/utility/updater.rpy index 493ddac5..58d62f34 100644 --- a/game/scripts/utility/updater.rpy +++ b/game/scripts/utility/updater.rpy @@ -101,9 +101,9 @@ init python: if current < 1.452: - for i in states.dolls: doll = getattr(store, i) + doll._sprite = DefaultQueue() for j in doll.wardrobe_list: # Add new button handler for clothes diff --git a/game/scripts/wardrobe/wardrobe.rpy b/game/scripts/wardrobe/wardrobe.rpy index 92abd4d0..9d705298 100644 --- a/game/scripts/wardrobe/wardrobe.rpy +++ b/game/scripts/wardrobe/wardrobe.rpy @@ -91,6 +91,20 @@ init python: thread = DollThread(target=_func, args=(cloth,), interval=0.05) thread.start() + @functools.cache # Cache resets on wardrobe exit + def set_wardrobe_categories(current_category): + category_items = OrderedDict( + sorted( + [ + (subcat, [item for item in items if item.unlocked]) + for subcat, items in wardrobe_subcategories.get(current_category, {}).items() + ], + key=lambda x: wardrobe_subcategories_sorted.get(x[0], 0), + reverse=True + ) + ) + return category_items + style loading_text: color "#ffffff" size 64 @@ -217,7 +231,7 @@ label wardrobe_menu(): # Defaults current_category = "head" - category_items = OrderedDict(sorted(iter(list(wardrobe_subcategories.get(current_category, {}).items())), key=lambda x: wardrobe_subcategories_sorted.get(x[0], 0), reverse=True)) + category_items = set_wardrobe_categories(current_category) current_subcategory = list(category_items.keys())[0] if category_items else "" current_item = char_active.get_equipped_wardrobe_item(category_items, current_subcategory) last_track = renpy.music.get_playing() @@ -251,7 +265,7 @@ label wardrobe_menu(): if wardrobe_check_category(_choice[1]): $ current_category = _choice[1] - $ category_items = OrderedDict(sorted(iter(wardrobe_subcategories.get(current_category, {}).items()), key=lambda x: wardrobe_subcategories_sorted.get(x[0], 0), reverse=True)) + $ category_items = set_wardrobe_categories(current_category) $ current_subcategory = list(category_items.keys())[0] if category_items else "" if current_category == "outfits": @@ -566,10 +580,13 @@ label wardrobe_menu(): renpy.music.play(last_track) DollThread.stop_all() + set_wardrobe_categories.cache_clear() + char_active.build_image() enable_game_menu() renpy.return_statement() + $ char_active.build_image() jump .after_init