2022-07-07 21:05:22 +00:00
|
|
|
init python:
|
2022-06-27 21:31:51 +00:00
|
|
|
|
|
|
|
if renpy.android:
|
2022-07-07 21:05:22 +00:00
|
|
|
settings.default("crashdefendersetting", 0)
|
|
|
|
|
2022-06-27 21:31:51 +00:00
|
|
|
# Attempts at fixing the texture leak plaguing
|
|
|
|
# android devices, mainly running on Android11 & Android 12.
|
|
|
|
class Android11TextureLeakFix(NoRollback):
|
|
|
|
def __init__(self, limit=100):
|
|
|
|
self.statements = 0
|
2022-07-07 21:05:22 +00:00
|
|
|
|
|
|
|
self.set_mode(settings.get("crashdefendersetting"))
|
|
|
|
|
|
|
|
def set_mode(self, mode):
|
|
|
|
if mode == 3:
|
|
|
|
self.limit = 15
|
|
|
|
elif mode == 2:
|
|
|
|
self.limit = 25
|
|
|
|
elif mode == 1:
|
|
|
|
self.limit = 55
|
|
|
|
else:
|
|
|
|
self.limit = 0
|
2022-06-27 21:31:51 +00:00
|
|
|
|
|
|
|
def __call__(self, name):
|
2022-07-07 21:05:22 +00:00
|
|
|
if renpy.is_init_phase() or self.limit == 0:
|
2022-06-27 21:31:51 +00:00
|
|
|
return
|
|
|
|
|
|
|
|
self.statements += 1
|
|
|
|
|
|
|
|
if self.statements > self.limit:
|
|
|
|
self.statements = 0
|
|
|
|
|
|
|
|
# Big thanks to Andykl (https://github.com/Andykl)
|
|
|
|
# for finding the issue and inventing this workaround.
|
|
|
|
# https://github.com/renpy/renpy/issues/3643
|
|
|
|
|
|
|
|
cache = renpy.display.im.cache
|
|
|
|
cache_size = cache.get_total_size()
|
|
|
|
cache_limit = cache.cache_limit * 0.95
|
|
|
|
|
|
|
|
if cache_size >= cache_limit:
|
|
|
|
if config.developer:
|
|
|
|
print("Cache limit reached, purging cache... ({}/{})\n{}".format(cache_size, cache_limit, renpy.get_filename_line()))
|
|
|
|
|
|
|
|
cache.clear()
|
|
|
|
|
|
|
|
if renpy.game.interface is not None:
|
|
|
|
if config.developer:
|
|
|
|
print("Statements limit reached, cleaning textures... ({})\n{}".format(self.limit, renpy.get_filename_line()))
|
|
|
|
|
|
|
|
renpy.game.interface.full_redraw = True
|
|
|
|
renpy.game.interface.restart_interaction = True
|
|
|
|
|
|
|
|
if renpy.display.draw is not None:
|
|
|
|
renpy.display.draw.kill_textures()
|
|
|
|
|
|
|
|
renpy.display.render.free_memory()
|
|
|
|
|
2022-07-07 21:05:22 +00:00
|
|
|
crashdefender = Android11TextureLeakFix()
|
|
|
|
|
|
|
|
config.statement_callbacks.append(crashdefender)
|
|
|
|
|
2023-03-16 22:55:14 +00:00
|
|
|
python early hide:
|
IO Overhaul, Refactoring, and more
* Refactored DollFace
* Refactored DollBody
* Refactored DollCum
* Refactored DollCloth
* Refactored Doll
* Refactored clothing item zorders
* Refactored implementation of body, face, cum, clothing layers
* Refactored function calls
* Removed DollLipstick
* Added DollMakeup class, allowing adding dynamic clothes tracking face states
* Added DollClothDynamic, allowing dynamic clothes tracking other cloth states with bangs support
* Added cache to frequently called functions, drastically reducing the overhead
* Added hash system, reducing clone redundancy
* Added layer modifiers support for all types (face, body, cum, clothes etc.)
* Added support for an arbitrary number of equipped multislot clothing items (makeup, tattoos, piercings, etc.)
* Simplified initialization for clothing items and dolls
* Simplified class function calls
* Reduced the number of image creation calls
* Added hue support for additional skin layers
* Added displayable support to image cropping function
* Replaced store cache with built-in functools cache for _list_files function
* Refactored all character files
* and more...
2023-01-14 23:04:54 +00:00
|
|
|
import functools
|
2022-06-27 21:31:51 +00:00
|
|
|
|
|
|
|
if renpy.windows:
|
|
|
|
# On windows, Renpy does not support backslashes in some of its functions,
|
|
|
|
# but because the code needs to be platform-independent,
|
|
|
|
# we require to monkey patch those functions in order
|
|
|
|
# to remain compatible with all platforms without losing functionality.
|
|
|
|
|
|
|
|
@renpy.pure
|
|
|
|
def _loadable(filename):
|
|
|
|
filename = filename.replace("\\", "/")
|
|
|
|
|
2022-06-29 18:46:19 +00:00
|
|
|
return renpy.loader.loadable(filename)
|
2022-06-27 21:31:51 +00:00
|
|
|
|
|
|
|
renpy.loadable = _loadable
|
2023-01-03 21:27:35 +00:00
|
|
|
|
|
|
|
# renpy.list_files does not use cached results, let's fix that.
|
|
|
|
|
IO Overhaul, Refactoring, and more
* Refactored DollFace
* Refactored DollBody
* Refactored DollCum
* Refactored DollCloth
* Refactored Doll
* Refactored clothing item zorders
* Refactored implementation of body, face, cum, clothing layers
* Refactored function calls
* Removed DollLipstick
* Added DollMakeup class, allowing adding dynamic clothes tracking face states
* Added DollClothDynamic, allowing dynamic clothes tracking other cloth states with bangs support
* Added cache to frequently called functions, drastically reducing the overhead
* Added hash system, reducing clone redundancy
* Added layer modifiers support for all types (face, body, cum, clothes etc.)
* Added support for an arbitrary number of equipped multislot clothing items (makeup, tattoos, piercings, etc.)
* Simplified initialization for clothing items and dolls
* Simplified class function calls
* Reduced the number of image creation calls
* Added hue support for additional skin layers
* Added displayable support to image cropping function
* Replaced store cache with built-in functools cache for _list_files function
* Refactored all character files
* and more...
2023-01-14 23:04:54 +00:00
|
|
|
@functools.cache
|
|
|
|
def _list_files(common=False):
|
|
|
|
rv = [fn for dir, fn in renpy.loader.listdirfiles(common) if not fn.startswith("saves/")]
|
|
|
|
rv.sort()
|
|
|
|
return rv
|
2023-01-03 21:27:35 +00:00
|
|
|
|
|
|
|
renpy.list_files = _list_files
|
2023-03-23 21:25:38 +00:00
|
|
|
|
|
|
|
# Default focus behaviour restarts the interaction whenever
|
|
|
|
# any element that contains a tooltip is being hovered or unhovered.
|
|
|
|
# Restarting interactions in a short timespan causes massive lag spikes,
|
|
|
|
# in order to fix it, we'll refresh just the tooltip screen and skip the rest.
|
|
|
|
|
|
|
|
def set_focused(widget, arg, screen):
|
|
|
|
global _tooltip
|
|
|
|
renpy.display.focus.argument = arg
|
|
|
|
renpy.display.focus.screen_of_focused = screen
|
|
|
|
|
|
|
|
if screen is not None:
|
|
|
|
renpy.display.focus.screen_of_focused_names = { screen.screen_name[0], screen.tag }
|
|
|
|
else:
|
|
|
|
renpy.display.focus.screen_of_focused_names = set()
|
|
|
|
|
|
|
|
renpy.game.context().scene_lists.focused = widget
|
|
|
|
renpy.display.tts.displayable(widget)
|
|
|
|
|
|
|
|
# Figure out the tooltip.
|
|
|
|
|
|
|
|
_tooltip = widget._get_tooltip() if widget else None
|
|
|
|
|
|
|
|
# setattr(renpy.store, "widget", widget) # DEBUG
|
|
|
|
|
|
|
|
# if renpy.display.focus.tooltip != new_tooltip:
|
|
|
|
# renpy.display.focus.tooltip = new_tooltip
|
|
|
|
# renpy.display.focus.capture_focus("tooltip")
|
|
|
|
|
|
|
|
# renpy.exports.restart_interaction()
|
|
|
|
|
|
|
|
# if renpy.display.focus.tooltip is not None:
|
|
|
|
# renpy.display.focus.last_tooltip = renpy.display.focus.tooltip
|
|
|
|
# renpy.display.focus.screen_of_last_focused_names = renpy.display.focus.screen_of_focused_names
|
|
|
|
|
|
|
|
renpy.display.focus.set_focused = set_focused
|
|
|
|
|