Merge branch 'master' into pep-657-munge
This commit is contained in:
@@ -255,7 +255,6 @@ name_blacklist = {
|
||||
"renpy.gl2.assimp.loader",
|
||||
"renpy.gl2.assimp.loader_lock",
|
||||
"renpy.gl2.gl2draw.default_position",
|
||||
"renpy.lexer._python_updatecache",
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
# Copyright 2004-2024 Tom Rothamel <pytom@bishoujo.us>
|
||||
# Copyright 2004-2025 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
|
||||
@@ -326,6 +326,7 @@ init -1100 python:
|
||||
|
||||
if version <= (8, 3, 99):
|
||||
config.old_show_expression = True
|
||||
config.mipmap = True
|
||||
|
||||
|
||||
# The version of Ren'Py this script is intended for, or
|
||||
|
||||
+44
-44
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2004-2024 Tom Rothamel <pytom@bishoujo.us>
|
||||
/* Copyright 2004-2025 Tom Rothamel <pytom@bishoujo.us>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
@@ -26,12 +26,12 @@ const DEBUG_OUT = false;
|
||||
|
||||
const USE_FRAME_CB = 'requestVideoFrameCallback' in HTMLVideoElement.prototype;
|
||||
|
||||
renpyAudio = { };
|
||||
renpyAudio = {};
|
||||
|
||||
/**
|
||||
* A map from channel to channel object.
|
||||
*/
|
||||
let channels = { };
|
||||
let channels = {};
|
||||
let next_chan_id = 0;
|
||||
|
||||
let context = new AudioContext();
|
||||
@@ -50,14 +50,14 @@ let get_channel = (channel) => {
|
||||
}
|
||||
|
||||
c = {
|
||||
playing : null,
|
||||
queued : null,
|
||||
stereo_pan : context.createStereoPanner(),
|
||||
fade_volume : context.createGain(),
|
||||
primary_volume : context.createGain(),
|
||||
secondary_volume : context.createGain(),
|
||||
relative_volume : context.createGain(),
|
||||
paused : false,
|
||||
playing: null,
|
||||
queued: null,
|
||||
stereo_pan: context.createStereoPanner(),
|
||||
fade_volume: context.createGain(),
|
||||
primary_volume: context.createGain(),
|
||||
secondary_volume: context.createGain(),
|
||||
relative_volume: context.createGain(),
|
||||
paused: false,
|
||||
video: false,
|
||||
video_el: null,
|
||||
chan_id: next_chan_id++,
|
||||
@@ -278,7 +278,7 @@ let video_start = (c) => {
|
||||
c.video_el.muted = true;
|
||||
c.video_el.play().then(() => {
|
||||
// TODO?
|
||||
}).catch( (e) => {
|
||||
}).catch((e) => {
|
||||
console.warn('Video is NOT playing even when muted', e.name);
|
||||
renpyAudio.videoPlayPrompt(renpyAudio._web_video_prompt, c.video_el);
|
||||
});
|
||||
@@ -386,24 +386,24 @@ renpyAudio.queue = (channel, file, name, synchro_start, fadein, tight, start, en
|
||||
}
|
||||
|
||||
const q = {
|
||||
url: url,
|
||||
name : name,
|
||||
start : start, // TODO?
|
||||
end : end, // TODO?
|
||||
relative_volume : relative_volume,
|
||||
started : null,
|
||||
fadein : fadein, // TODO?
|
||||
fadeout: null, // TODO?
|
||||
tight : tight, // TODO?
|
||||
filter : renpyAudio.getFilter(afid),
|
||||
synchro_start : synchro_start,
|
||||
url: url,
|
||||
name: name,
|
||||
start: start, // TODO?
|
||||
end: end, // TODO?
|
||||
relative_volume: relative_volume,
|
||||
started: null,
|
||||
fadein: fadein, // TODO?
|
||||
fadeout: null, // TODO?
|
||||
tight: tight, // TODO?
|
||||
filter: renpyAudio.getFilter(afid),
|
||||
synchro_start: synchro_start,
|
||||
|
||||
period_stats: [0, 0], // time sum, count
|
||||
fetch_stats: [0, 0],
|
||||
draw_stats: [0, 0, 0, 0], // time sum, count, first timestamp, last timestamp
|
||||
blob_stats: [0, 0],
|
||||
array_stats: [0, 0],
|
||||
file_stats: [0, 0, 0, 0], // time sum, count, first timestamp, last timestamp
|
||||
period_stats: [0, 0], // time sum, count
|
||||
fetch_stats: [0, 0],
|
||||
draw_stats: [0, 0, 0, 0], // time sum, count, first timestamp, last timestamp
|
||||
blob_stats: [0, 0],
|
||||
array_stats: [0, 0],
|
||||
file_stats: [0, 0, 0, 0], // time sum, count, first timestamp, last timestamp
|
||||
};
|
||||
|
||||
if (c.video_el === null) {
|
||||
@@ -413,11 +413,11 @@ renpyAudio.queue = (channel, file, name, synchro_start, fadein, tight, start, en
|
||||
c.video_el.playsInline = true; // For autoplay on Safari
|
||||
document.body.appendChild(c.video_el);
|
||||
|
||||
c.video_el.addEventListener('loadedmetadata', function() {
|
||||
c.video_el.addEventListener('loadedmetadata', function () {
|
||||
c.video_size = [c.video_el.videoWidth, c.video_el.videoHeight];
|
||||
});
|
||||
|
||||
c.video_el.addEventListener('error', function(e) {
|
||||
c.video_el.addEventListener('error', function (e) {
|
||||
|
||||
});
|
||||
|
||||
@@ -433,7 +433,7 @@ renpyAudio.queue = (channel, file, name, synchro_start, fadein, tight, start, en
|
||||
c.is_playing = false;
|
||||
});
|
||||
|
||||
c.video_el.addEventListener('playing', function() {
|
||||
c.video_el.addEventListener('playing', function () {
|
||||
c.is_playing = true;
|
||||
});
|
||||
|
||||
@@ -462,19 +462,19 @@ renpyAudio.queue = (channel, file, name, synchro_start, fadein, tight, start, en
|
||||
}
|
||||
|
||||
const q = {
|
||||
source : null,
|
||||
buffer : null,
|
||||
name : name,
|
||||
start : start,
|
||||
end : end,
|
||||
relative_volume : relative_volume,
|
||||
started : null,
|
||||
fadein : fadein,
|
||||
source: null,
|
||||
buffer: null,
|
||||
name: name,
|
||||
start: start,
|
||||
end: end,
|
||||
relative_volume: relative_volume,
|
||||
started: null,
|
||||
fadein: fadein,
|
||||
fadeout: null,
|
||||
tight : tight,
|
||||
tight: tight,
|
||||
file: file,
|
||||
filter : renpyAudio.getFilter(afid),
|
||||
synchro_start : synchro_start,
|
||||
filter: renpyAudio.getFilter(afid),
|
||||
synchro_start: synchro_start,
|
||||
};
|
||||
|
||||
function reuseBuffer(c) {
|
||||
@@ -868,7 +868,7 @@ renpyAudio.read_video = (channel, video_tex, width, height) => {
|
||||
|
||||
if (DEBUG_OUT) {
|
||||
// DEBUG Dumps all method calls to renpyAudio
|
||||
renpyAudio._nodump = {'queue_depth': 1, 'playing_name': 1, 'video_ready': 1, 'read_video': 1};
|
||||
renpyAudio._nodump = { 'queue_depth': 1, 'playing_name': 1, 'video_ready': 1, 'read_video': 1 };
|
||||
renpyAudio = new Proxy(renpyAudio, {
|
||||
get(target, prop) {
|
||||
const origMethod = target[prop];
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2004-2024 Tom Rothamel <pytom@bishoujo.us>
|
||||
/* Copyright 2004-2025 Tom Rothamel <pytom@bishoujo.us>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
@@ -20,7 +20,7 @@
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
let afidToFilter = {0 : null};
|
||||
let afidToFilter = { 0: null };
|
||||
|
||||
/**
|
||||
* Given an afid, return the filter associated with it. Returns null if the
|
||||
@@ -94,7 +94,7 @@ renpyAudio.disconnectFilter = function (filter, source, destination) {
|
||||
}
|
||||
|
||||
|
||||
renpyAudio.filter = { }
|
||||
renpyAudio.filter = {}
|
||||
let filter = renpyAudio.filter;
|
||||
|
||||
/**
|
||||
@@ -112,7 +112,7 @@ filter.filterToFilter = function (filter1, filter2) {
|
||||
/**
|
||||
* Connects a filter to a node.
|
||||
*/
|
||||
filter.filterToNode = function(filter, node) {
|
||||
filter.filterToNode = function (filter, node) {
|
||||
for (let output of filter.outputs) {
|
||||
output.connect(node);
|
||||
}
|
||||
@@ -121,22 +121,22 @@ filter.filterToNode = function(filter, node) {
|
||||
/**
|
||||
* Connects a node to a filter.
|
||||
*/
|
||||
filter.nodeToFilter = function(node, filter) {
|
||||
filter.nodeToFilter = function (node, filter) {
|
||||
for (let input of filter.inputs) {
|
||||
node.connect(input);
|
||||
}
|
||||
}
|
||||
|
||||
filter.Null = function() {
|
||||
filter.Null = function () {
|
||||
let node = new GainNode(renpyAudio.context, { gain: 1 });
|
||||
|
||||
return {
|
||||
inputs: [ node ],
|
||||
outputs: [ node ],
|
||||
inputs: [node],
|
||||
outputs: [node],
|
||||
};
|
||||
}
|
||||
|
||||
filter.Crossfade = function(afid1, afid2, t) {
|
||||
filter.Crossfade = function (afid1, afid2, t) {
|
||||
let filter1 = renpyAudio.getFilter(afid1);
|
||||
let filter2 = renpyAudio.getFilter(afid2);
|
||||
|
||||
@@ -150,13 +150,13 @@ filter.Crossfade = function(afid1, afid2, t) {
|
||||
gain2.gain.linearRampToValueAtTime(1, renpyAudio.context.currentTime + t);
|
||||
|
||||
return {
|
||||
inputs: [ ...filter1.inputs, ...filter2.inputs ],
|
||||
inputs: [...filter1.inputs, ...filter2.inputs],
|
||||
outputs: [gain1, gain2],
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
filter.Biquad = function(kind, frequency, Q, gain) {
|
||||
filter.Biquad = function (kind, frequency, Q, gain) {
|
||||
let node = new BiquadFilterNode(renpyAudio.context, {
|
||||
type: kind,
|
||||
frequency: frequency,
|
||||
@@ -170,7 +170,7 @@ filter.Biquad = function(kind, frequency, Q, gain) {
|
||||
};
|
||||
};
|
||||
|
||||
filter.Sequence = function(...filters) {
|
||||
filter.Sequence = function (...filters) {
|
||||
let first = filters[0];
|
||||
let last = filters[filters.length - 1];
|
||||
|
||||
@@ -184,7 +184,7 @@ filter.Sequence = function(...filters) {
|
||||
};
|
||||
}
|
||||
|
||||
filter.Mix = function(...filters) {
|
||||
filter.Mix = function (...filters) {
|
||||
let inputs = [];
|
||||
let outputs = [];
|
||||
|
||||
@@ -199,7 +199,7 @@ filter.Mix = function(...filters) {
|
||||
};
|
||||
}
|
||||
|
||||
filter.Multiply = function(factor) {
|
||||
filter.Multiply = function (factor) {
|
||||
let node = new GainNode(renpyAudio.context, { gain: factor });
|
||||
|
||||
return {
|
||||
@@ -209,7 +209,7 @@ filter.Multiply = function(factor) {
|
||||
}
|
||||
|
||||
|
||||
filter.Delay = function(delay) {
|
||||
filter.Delay = function (delay) {
|
||||
|
||||
if (typeof delay !== "number") {
|
||||
delay = delay[0];
|
||||
@@ -223,7 +223,7 @@ filter.Delay = function(delay) {
|
||||
};
|
||||
}
|
||||
|
||||
filter.Comb = function(delay, child, multiplier, wet) {
|
||||
filter.Comb = function (delay, child, multiplier, wet) {
|
||||
if (typeof delay !== "number") {
|
||||
delay = delay[0];
|
||||
}
|
||||
@@ -237,8 +237,8 @@ filter.Comb = function(delay, child, multiplier, wet) {
|
||||
multiplierNode.connect(delayNode);
|
||||
|
||||
let rv = {
|
||||
inputs: [ delayNode ],
|
||||
outputs: [ multiplierNode ],
|
||||
inputs: [delayNode],
|
||||
outputs: [multiplierNode],
|
||||
};
|
||||
|
||||
if (wet) {
|
||||
@@ -252,7 +252,7 @@ filter.Comb = function(delay, child, multiplier, wet) {
|
||||
}
|
||||
|
||||
|
||||
filter.WetDry = function(child, wet, dry) {
|
||||
filter.WetDry = function (child, wet, dry) {
|
||||
let wetNode = new GainNode(renpyAudio.context, { gain: wet });
|
||||
let dryNode = new GainNode(renpyAudio.context, { gain: dry });
|
||||
|
||||
|
||||
@@ -1133,6 +1133,9 @@ controller_blocklist = [
|
||||
"030000006d0400000000", # Razer Xbox 360 Controller (#4622)
|
||||
]
|
||||
|
||||
# Should other textures be mipmapped by default?
|
||||
mipmap = "auto"
|
||||
|
||||
# Should dissolve transitions be mipmapped by default?
|
||||
mipmap_dissolves = False
|
||||
|
||||
|
||||
+10
-4
@@ -355,7 +355,7 @@ class Cache(object):
|
||||
texsurf = ce.surf.subsurface(ce.bounds)
|
||||
renpy.display.render.mutated_surface(texsurf)
|
||||
|
||||
ce.texture = renpy.display.draw.load_texture(texsurf)
|
||||
ce.texture = renpy.display.draw.load_texture(texsurf, properties={ 'mipmap' : image.mipmap })
|
||||
|
||||
# This was loaded while predicting images for immediate use,
|
||||
# so get it onto the GPU.
|
||||
@@ -586,7 +586,7 @@ class ImageBase(renpy.display.displayable.Displayable):
|
||||
obsolete = True
|
||||
|
||||
obsolete_list = [ ]
|
||||
|
||||
mipmap = True
|
||||
|
||||
# If the image failed to load, a placeholder used to report the error.
|
||||
fail = None
|
||||
@@ -601,6 +601,7 @@ class ImageBase(renpy.display.displayable.Displayable):
|
||||
self.cache = properties.pop('cache', True)
|
||||
self.optimize_bounds = properties.pop('optimize_bounds', True)
|
||||
self.oversample = properties.pop('oversample', 1)
|
||||
self.mipmap = properties.pop('mipmap', "auto")
|
||||
|
||||
if self.oversample <= 0:
|
||||
raise Exception("Image's oversample parameter must be greater than 0.")
|
||||
@@ -2012,7 +2013,7 @@ def image(arg, loose=False, **properties):
|
||||
"""
|
||||
:doc: im_image
|
||||
:name: Image
|
||||
:args: (filename, *, optimize_bounds=True, oversample=1, dpi=96, **properties)
|
||||
:args: (filename, *, optimize_bounds=True, oversample=1, dpi=96, mipmap="auto", **properties)
|
||||
|
||||
Loads an image from a file. `filename` is a
|
||||
string giving the name of the file.
|
||||
@@ -2036,6 +2037,11 @@ def image(arg, loose=False, **properties):
|
||||
The DPI of an SVG image. This defaults to 96, but that can be
|
||||
increased to render the SVG larger, and decreased to render
|
||||
it smaller.
|
||||
|
||||
`mipmap`
|
||||
If this is "auto", then mipmaps are generated for the image only if the game is scaled down to less than
|
||||
75% of its default size. If this is True, mipmaps are always generated. If this is False, mipmaps are never
|
||||
generated.
|
||||
"""
|
||||
|
||||
"""
|
||||
@@ -2160,7 +2166,7 @@ def unoptimized_texture(d):
|
||||
"""
|
||||
|
||||
if isinstance(d, ImageBase):
|
||||
return UnoptimizedTexture(d)
|
||||
return UnoptimizedTexture(d, mipmap=True)
|
||||
else:
|
||||
return d
|
||||
|
||||
|
||||
@@ -58,6 +58,8 @@ cdef class GL2Draw:
|
||||
cdef public Matrix virt_to_draw
|
||||
cdef public Matrix draw_to_virt
|
||||
|
||||
cdef public bint auto_mipmap
|
||||
|
||||
# The matrix that goes from drawable space to the window. This isn't used
|
||||
# directly, it's used to determine if something is being drawn in a wa
|
||||
# that it should be lined up with pixels.
|
||||
|
||||
@@ -137,6 +137,9 @@ cdef class GL2Draw:
|
||||
# The old value of fullscreen.
|
||||
self.old_fullscreen = False
|
||||
|
||||
# Should mipmaps be generated when mipmap == "auto"?
|
||||
self.auto_mipmap = False
|
||||
|
||||
def get_texture_size(self):
|
||||
"""
|
||||
Returns the amount of memory locked up in textures.
|
||||
@@ -611,6 +614,8 @@ cdef class GL2Draw:
|
||||
self.init_fbo()
|
||||
self.texture_loader.init()
|
||||
|
||||
self.auto_mipmap = self.draw_per_virt < 0.75
|
||||
|
||||
def resize(self):
|
||||
"""
|
||||
Documented in renderer.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2004-2024 Tom Rothamel <pytom@bishoujo.us>
|
||||
# Copyright 2004-2025 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2004-2024 Tom Rothamel <pytom@bishoujo.us>
|
||||
# Copyright 2004-2025 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2004-2024 Tom Rothamel <pytom@bishoujo.us>
|
||||
# Copyright 2004-2025 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2004-2024 Tom Rothamel <pytom@bishoujo.us>
|
||||
# Copyright 2004-2025 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2004-2024 Tom Rothamel <pytom@bishoujo.us>
|
||||
# Copyright 2004-2025 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2004-2024 Tom Rothamel <pytom@bishoujo.us>
|
||||
# Copyright 2004-2025 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
|
||||
@@ -307,7 +307,12 @@ cdef class GLTexture(GL2Model):
|
||||
when it's loaded).
|
||||
"""
|
||||
|
||||
return self.properties.get("mipmap", True)
|
||||
rv = self.properties.get("mipmap", renpy.config.mipmap)
|
||||
|
||||
if rv == "auto":
|
||||
rv = renpy.display.draw.auto_mipmap
|
||||
|
||||
return rv
|
||||
|
||||
def get_number(GLTexture self):
|
||||
return self.number if renpy.emscripten else None
|
||||
@@ -333,7 +338,7 @@ cdef class GLTexture(GL2Model):
|
||||
"""
|
||||
|
||||
self.properties = {
|
||||
"mipmap" : properties.get("mipmap", True),
|
||||
"mipmap" : properties.get("mipmap", renpy.config.mipmap),
|
||||
"pixel_perfect" : properties.get("pixel_perfect", False),
|
||||
}
|
||||
|
||||
@@ -585,7 +590,7 @@ cdef class GLTexture(GL2Model):
|
||||
|
||||
max_level = renpy.config.max_mipmap_level
|
||||
|
||||
if not properties.get("mipmap", True):
|
||||
if not self.has_mipmaps():
|
||||
max_level = 0
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, max_level)
|
||||
@@ -630,7 +635,7 @@ cdef class GLTexture(GL2Model):
|
||||
|
||||
cdef GLuint level = renpy.config.max_mipmap_level
|
||||
|
||||
if not properties.get("mipmap", True):
|
||||
if not self.has_mipmaps():
|
||||
level = 0
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, tex)
|
||||
@@ -654,7 +659,7 @@ cdef class GLTexture(GL2Model):
|
||||
self.loader.total_texture_size -= int(self.width * self.height * 4 * 1.34)
|
||||
else:
|
||||
self.loader.total_texture_size -= int(self.width * self.height * 4)
|
||||
except TypeError:
|
||||
except (TypeError, AttributeError):
|
||||
pass # Let's not error on shutdown.
|
||||
|
||||
def load(self):
|
||||
|
||||
+39
-20
@@ -1165,18 +1165,32 @@ def py_compile(source, mode, filename='<none>', lineno=1, ast_node=False, cache=
|
||||
else:
|
||||
py_mode = mode
|
||||
|
||||
flags |= new_compile_flags
|
||||
|
||||
try:
|
||||
with save_warnings():
|
||||
tree = compile(source, filename, py_mode, ast.PyCF_ONLY_AST | flags, True)
|
||||
except SyntaxError as orig_e:
|
||||
tree: Any = None
|
||||
with save_warnings():
|
||||
try:
|
||||
fixed_source = renpy.compat.fixes.fix_tokens(source)
|
||||
with save_warnings():
|
||||
tree = compile(fixed_source, filename, py_mode, ast.PyCF_ONLY_AST | flags, True)
|
||||
except Exception:
|
||||
raise orig_e
|
||||
tree = compile(
|
||||
source,
|
||||
filename,
|
||||
py_mode,
|
||||
ast.PyCF_ONLY_AST | flags,
|
||||
True)
|
||||
|
||||
except SyntaxError:
|
||||
handled = False
|
||||
try:
|
||||
fixed_source = renpy.compat.fixes.fix_tokens(source)
|
||||
tree = compile(
|
||||
fixed_source,
|
||||
filename,
|
||||
py_mode,
|
||||
ast.PyCF_ONLY_AST | flags,
|
||||
True)
|
||||
handled = True
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if not handled:
|
||||
raise
|
||||
|
||||
tree = wrap_node.visit(tree)
|
||||
|
||||
@@ -1193,18 +1207,23 @@ def py_compile(source, mode, filename='<none>', lineno=1, ast_node=False, cache=
|
||||
if ast_node:
|
||||
return tree.body
|
||||
|
||||
try:
|
||||
with save_warnings():
|
||||
rv = compile(tree, filename, py_mode, flags, True)
|
||||
except SyntaxError as orig_e:
|
||||
rv: Any = None
|
||||
with save_warnings():
|
||||
try:
|
||||
tree = renpy.compat.fixes.fix_ast(tree)
|
||||
fix_locations(tree, 1, 0)
|
||||
with save_warnings():
|
||||
rv = compile(tree, filename, py_mode, flags, True)
|
||||
except SyntaxError:
|
||||
handled = False
|
||||
try:
|
||||
tree = renpy.compat.fixes.fix_ast(tree)
|
||||
fix_locations(tree, 1, 0)
|
||||
rv = compile(tree, filename, py_mode, flags, True)
|
||||
except Exception:
|
||||
raise orig_e
|
||||
handled = True
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if not handled:
|
||||
raise
|
||||
|
||||
if cache:
|
||||
py_compile_cache[key] = rv
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright 2004-2024 Tom Rothamel <pytom@bishoujo.us>
|
||||
# Copyright 2004-2025 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
|
||||
@@ -47,6 +47,21 @@ merged with the player's script, a library can be placed under game/libs, and wi
|
||||
|
||||
`.rpe` and `.rpe.py` files are also searched in the libs directory.
|
||||
|
||||
Optional Mipmaps
|
||||
----------------
|
||||
|
||||
Mipmaps are smaller versions of an image that are used when Ren'Py scales an image down. Using mipmaps
|
||||
prevents the image from becoming jagged when scaled down, but generating mipmaps takes time and can cause the game
|
||||
to use more memory.
|
||||
|
||||
Ren'Py now leaves the decision of if to create mipmaps to the developer, who knows if the game will scale down an
|
||||
image. To always enable mipmaps, set :var:`config.mipmap` to True. If this isn't set to true, Ren'Py will only
|
||||
create mipmaps if the display is scaled down to less than 75% of the virtual window size.
|
||||
|
||||
Mipmaps will automatically be created for images loaded for the purpose of Live2D or AssimpModel, as these are
|
||||
likely to be scaled down. Mipmaps can be created for specific images by providing True to the mipmap parameter
|
||||
of :func:`Image`.
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
@@ -84,9 +99,14 @@ apply :ref:`text interpolation <text-interpolation>` to the result. Interpolatio
|
||||
that the function is called from. The triple underscore function also marks the string contained
|
||||
inside for translation.
|
||||
|
||||
|
||||
Other Changes
|
||||
-------------
|
||||
|
||||
By default, Ren'Py now only creates mipmaps for textures if the display is scaled down to less than .75 of virtual
|
||||
window size. This is suitable for games that do not scale down images. To enable mipmapping again, set
|
||||
:var:`config.mipmap` to True.
|
||||
|
||||
Ren'Py no longer triggers and autoreload when a file that had not existed comes into existence. This behavior
|
||||
had been inconsistent, working in some places but not others, required Ren'Py to spent time scanning for files
|
||||
that do not exist.
|
||||
|
||||
@@ -74,7 +74,7 @@ Auto-Forward Mode
|
||||
.. var:: config.afm_callback = None
|
||||
|
||||
If not None, a Python function that is called to determine if it
|
||||
is safe to auto-forward. If None, an internal function is used to
|
||||
is safe to auto-forward. If None, an internal function is used to
|
||||
disable auto-forwarding when a voice is playing, unless :var:`preferences.wait_voice`
|
||||
is set to False.
|
||||
|
||||
@@ -755,10 +755,30 @@ Media (Music, Sound, and Video)
|
||||
A list of channels that are stopped when entering or returning to the
|
||||
main menu.
|
||||
|
||||
.. var:: config.mipmap = "auto"
|
||||
|
||||
This controls if Ren'Py generates mipmaps for image. If True, mipmaps are always generated. If "auto", mipmaps
|
||||
are generated only if the window is smaller than 75% of the virtual screen size. If False, mipmaps are never
|
||||
generated.
|
||||
|
||||
.. var:: config.mipmap_dissolves = False
|
||||
|
||||
If True, mipmaps are generated for dissolve transitions.
|
||||
|
||||
This takes the same values as :var:`config.mipmap`.
|
||||
|
||||
.. var:: config.mipmap_movies = False
|
||||
|
||||
The default value of the mipmap argument to :func:`Movie`.
|
||||
|
||||
This takes the same values as :var:`config.mipmap`.
|
||||
|
||||
.. var:: config.mipmap_text = False
|
||||
|
||||
If True, mipmaps are generated for text.
|
||||
|
||||
This takes the same values as :var:`config.mipmap`.
|
||||
|
||||
.. var:: config.movie_mixer = "music"
|
||||
|
||||
The mixer that is used when a :func:`Movie` automatically defines
|
||||
|
||||
@@ -17,6 +17,21 @@ such changes only take effect when the GUI is regenerated.
|
||||
8.4.0
|
||||
-----
|
||||
|
||||
|
||||
**Mipmaps**
|
||||
Mipmaps are smaller versions of an image that are used when Ren'Py scales an image down. Using mipmaps
|
||||
prevents the image from becoming jagged when scaled down, but generating mipmaps takes time and can cause the game
|
||||
to use more memory.
|
||||
|
||||
Ren'Py now leaves the decision of if to create mipmaps to the developer, who knows if the game will scale down an
|
||||
image. To always enable mipmaps, set :var:`config.mipmap` to True. If this isn't set to true, Ren'Py will only
|
||||
create mipmaps if the display is scaled down to less than 75% of the virtual window size.
|
||||
|
||||
Mipmaps will automatically be created for images loaded for the purpose of Live2D or AssimpModel, as these are
|
||||
likely to be scaled down. Mipmaps can be created for specific images by providing True to the mipmap parameter
|
||||
of :func:`Image`.
|
||||
|
||||
|
||||
**Show expression.** The ``show expression`` statement has been changed so that::
|
||||
|
||||
show expression "bg washington"
|
||||
|
||||
Reference in New Issue
Block a user