From 7a25a13926cd40e7f657f6336062aa48255b4b64 Mon Sep 17 00:00:00 2001 From: Gouvernathor <44340603+Gouvernathor@users.noreply.github.com> Date: Sun, 19 Nov 2023 00:23:33 +0100 Subject: [PATCH] Improve threading when predicting the wardrobe don't use single-underscore names if available, use the thread-safer invoke_in_main_thread (not required when setting the global variables) set __lock to True outside of the thread, otherwise if the thread starts late, the while loop is skipped call get_character_object in the main thread --- game/scripts/wardrobe/wardrobe.rpy | 42 ++++++++++++++++++------------ 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/game/scripts/wardrobe/wardrobe.rpy b/game/scripts/wardrobe/wardrobe.rpy index 56671402..a5de21e5 100644 --- a/game/scripts/wardrobe/wardrobe.rpy +++ b/game/scripts/wardrobe/wardrobe.rpy @@ -1,4 +1,3 @@ - default wardrobe_music = False default wardrobe_chitchats = True default wardrobe_autosave = False @@ -19,20 +18,28 @@ define wardrobe_subcategories_sorted = { define wardrobe_categories = ("head", "piercings & tattoos", "upper body", "upper undergarment", "lower body", "lower undergarment", "legwear", "misc") define wardrobe_outfit_schedule = ("day", "night", "cloudy", "rainy", "snowy") +default __lock = False +default __predicted = None init python: + def preload_wardrobe_assets(c): + global __lock, __predicted - _lock = False + if renpy.version_tuple < (8, 2): + renpy.start_predict_screen("wardrobe") + else: + # use the new renpy.invoke_in_main_thread + renpy.invoke_in_main_thread(renpy.start_predict_screen, "wardrobe") - def preload_wardrobe_assets(): - global _lock, _predicted - _lock = True - renpy.start_predict_screen("wardrobe") - c = get_character_object(states.active_girl) + # this is not thread-safe, but there's no better way : it's the slow part d = [v[0] for i in c.wardrobe_list for v in i.get_layers(i._hash).values()] - renpy.start_predict(*d, "interface/wardrobe/*.webp") - _predicted = d - _lock = False + + if renpy.version_tuple < (8, 2): + renpy.start_predict(*d, "interface/wardrobe/*.webp") + else: + renpy.invoke_in_main_thread(renpy.start_predict, *d, "interface/wardrobe/*.webp") + __predicted = d + __lock = False def rebuild_wardrobe_icons(items, subcat): if not settings.get("multithreading"): @@ -185,14 +192,15 @@ label _wardrobe: show loading zorder 1000 # Ensure there's no thread in use before assigning a new one. - while _lock: + while __lock: $ renpy.pause(0.5, hard=True) - $ renpy.invoke_in_thread(preload_wardrobe_assets) + $ __lock = True + $ renpy.invoke_in_thread(preload_wardrobe_assets, get_character_object(states.active_girl)) # Await thread return # Note: renpy.pause must be called from within the main thread - while _lock: + while __lock: $ renpy.pause(0.5, predict=True) hide loading @@ -203,10 +211,10 @@ label _wardrobe: show screen main_room show screen ui_top_bar - $ _game_menu_screen = "save" - $ _skipping = True - $ renpy.stop_predict(_predicted) - $ del _predicted + $ _game_menu_screen = "save" # documented + $ _skipping = True # documented + $ renpy.stop_predict(__predicted) + $ __predicted = None $ renpy.suspend_rollback(False) $ renpy.block_rollback() return