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
This commit is contained in:
Gouvernathor 2023-11-19 00:23:33 +01:00
parent b3c16ff0d7
commit 7a25a13926

View File

@ -1,4 +1,3 @@
default wardrobe_music = False default wardrobe_music = False
default wardrobe_chitchats = True default wardrobe_chitchats = True
default wardrobe_autosave = False 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_categories = ("head", "piercings & tattoos", "upper body", "upper undergarment", "lower body", "lower undergarment", "legwear", "misc")
define wardrobe_outfit_schedule = ("day", "night", "cloudy", "rainy", "snowy") define wardrobe_outfit_schedule = ("day", "night", "cloudy", "rainy", "snowy")
default __lock = False
default __predicted = None
init python: init python:
def preload_wardrobe_assets(c):
global __lock, __predicted
_lock = False if renpy.version_tuple < (8, 2):
def preload_wardrobe_assets():
global _lock, _predicted
_lock = True
renpy.start_predict_screen("wardrobe") renpy.start_predict_screen("wardrobe")
c = get_character_object(states.active_girl) else:
# use the new renpy.invoke_in_main_thread
renpy.invoke_in_main_thread(renpy.start_predict_screen, "wardrobe")
# 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()] d = [v[0] for i in c.wardrobe_list for v in i.get_layers(i._hash).values()]
if renpy.version_tuple < (8, 2):
renpy.start_predict(*d, "interface/wardrobe/*.webp") renpy.start_predict(*d, "interface/wardrobe/*.webp")
_predicted = d else:
_lock = False renpy.invoke_in_main_thread(renpy.start_predict, *d, "interface/wardrobe/*.webp")
__predicted = d
__lock = False
def rebuild_wardrobe_icons(items, subcat): def rebuild_wardrobe_icons(items, subcat):
if not settings.get("multithreading"): if not settings.get("multithreading"):
@ -185,14 +192,15 @@ label _wardrobe:
show loading zorder 1000 show loading zorder 1000
# Ensure there's no thread in use before assigning a new one. # Ensure there's no thread in use before assigning a new one.
while _lock: while __lock:
$ renpy.pause(0.5, hard=True) $ 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 # Await thread return
# Note: renpy.pause must be called from within the main thread # Note: renpy.pause must be called from within the main thread
while _lock: while __lock:
$ renpy.pause(0.5, predict=True) $ renpy.pause(0.5, predict=True)
hide loading hide loading
@ -203,10 +211,10 @@ label _wardrobe:
show screen main_room show screen main_room
show screen ui_top_bar show screen ui_top_bar
$ _game_menu_screen = "save" $ _game_menu_screen = "save" # documented
$ _skipping = True $ _skipping = True # documented
$ renpy.stop_predict(_predicted) $ renpy.stop_predict(__predicted)
$ del _predicted $ __predicted = None
$ renpy.suspend_rollback(False) $ renpy.suspend_rollback(False)
$ renpy.block_rollback() $ renpy.block_rollback()
return return