Compare commits

...

45 Commits

Author SHA1 Message Date
Tom Rothamel 693cf9f8c9 Version bumps for 6.9.2 2009-05-05 02:09:59 -04:00
Tom Rothamel 35c2ec5a83 Fixed a bug that could cause it to take two tries to define a joystick
button.
2009-05-02 23:31:13 -04:00
Tom Rothamel 3b60efd744 Update changelog.
Fix dequeue to have correct semantics.
2009-05-02 23:05:27 -04:00
Tom Rothamel daac5d8ebf Doing anything besides rollforward during rollback now terminates
rollback.

Queueing music immediately after a play statement now allows the first 
track from the play statement to play.
2009-05-02 22:41:04 -04:00
Tom Rothamel 1fab6d8707 Prevent slow_done from being repeatedly called. 2009-05-02 21:32:24 -04:00
Tom Rothamel aaff11668a Catch errors when saving screenshots. 2009-05-02 20:21:18 -04:00
Tom Rothamel 536341a819 Fix problem with window icon on 16bit screen. 2009-05-01 22:16:29 -04:00
Tom Rothamel b9c468e446 Fix repeate word in the question. 2009-04-27 07:50:09 -04:00
Tom Rothamel 03edec9785 Fix a bug with Container. 2009-04-24 19:22:04 -04:00
Tom Rothamel da70a85d75 Bring in changes from staging. 2009-04-23 00:53:14 -04:00
Tom Rothamel 4ba170b8d8 Bring in features from mainline. 2009-04-23 00:52:04 -04:00
Tom Rothamel 72ae15c635 Back out some changes that lead to a slowdown in dissolve. 2009-04-22 23:16:49 -04:00
Tom Rothamel 1179066dda Bump version to 6.9.1h 2009-04-20 23:05:00 -04:00
Tom Rothamel 62d0093bee End skipping on rollback. 2009-04-20 23:01:10 -04:00
Tom Rothamel 55c0d3b4a7 Convert to alpha before smoothscaling windows icon. 2009-04-19 16:03:42 -04:00
Tom Rothamel 92014eafdd Fix a bug with the icon on windows. 2009-04-19 16:01:55 -04:00
Tom Rothamel b1be4c8ed4 The library alias for config has been removed. 2009-04-19 02:00:53 -04:00
Tom Rothamel 06f36dd8d1 Prevent infinite loop in error handling. 2009-04-19 01:31:26 -04:00
Tom Rothamel 3a15f5c717 6.9.1g 2009-04-18 23:24:22 -04:00
Tom Rothamel 031f3338b1 Scale screenshot using an alpha image. 2009-04-17 19:44:00 -04:00
Tom Rothamel 66125b2e10 Bump version. 2009-04-16 21:03:48 -04:00
Tom Rothamel e6becffc4c Blacklist obsolete file formats.
Properly deallocate VideoStates of short/invalid media files.
2009-04-16 19:31:50 -04:00
Tom Rothamel d281e57879 Fix reported bugs.
Make scaling more accurate.
2009-04-16 18:04:10 -04:00
Tom Rothamel 5196a970a0 Channels now have a default tightness. 2009-04-15 12:12:40 -04:00
Tom Rothamel efcbc92e7a Reimplement smoothscale in terms of _renpy.pixellate and _renpy.bilinear. 2009-04-15 01:10:13 -04:00
Tom Rothamel 142fa33548 Changelog updates. 2009-04-13 23:49:39 -04:00
Tom Rothamel 4b6e871ac6 6.9.1d 2009-04-13 23:40:13 -04:00
Tom Rothamel 1fbbad053a Add _rollback. 2009-04-13 23:11:39 -04:00
Tom Rothamel 61aa933d97 Fix rendering of empty image-based fonts. 2009-04-13 19:31:11 -04:00
Tom Rothamel 70c3ea773e Fix conflict between window show and shift+>. 2009-04-13 11:54:40 -04:00
Tom Rothamel a16de04682 The demo now passes with RENPY_SCALE_FACTOR=1.5. This required various fixes.
Prevent blit_lock from being held over a traceback.
2009-04-13 01:27:34 -04:00
Tom Rothamel 0280a12589 In SayBehavior, when a click comes in at the same time as a skip
timeout, favor the click.
2009-04-12 23:53:22 -04:00
Tom Rothamel 4dc8fef9c1 Fix a problems in scaling caused when images of different physical
sizes map to the same virtual size.

Fix a problem with restart.
2009-04-12 23:47:42 -04:00
Tom Rothamel 2c02645ec7 Lint now reports all uses of missing files, rather than just the first. 2009-04-12 15:14:19 -04:00
Tom Rothamel 40bad327fe renpy.full_restart now takes a target parameter, which is a screen on
the main menu to target.
2009-04-12 14:48:26 -04:00
Tom Rothamel f5653d3c4d Releasing 6.9.1c. 2009-04-11 14:16:14 -04:00
Tom Rothamel 4026d7818b Provide a basic mechanism for invoking the main menu with a particular screen. 2009-04-11 14:04:54 -04:00
Tom Rothamel a0fda2f058 Do not offer an editor if none exists.
Modified setup.py to check dependencies. It can now be used to build
on a stock ubuntu system, if all dependencies are in place.
2009-04-11 13:47:35 -04:00
Tom Rothamel 93546e2d5c Allow the movie channel to play back while muted. 2009-04-11 01:41:29 -04:00
Tom Rothamel 85a562713a Fix memory leak in the redraw queue. 2009-04-11 00:47:51 -04:00
Tom Rothamel 4e9beb1a5d Minor tweaks to the includes of ffdecode.c 2009-04-10 11:01:12 -04:00
Tom Rothamel 522333e0f5 Update help file to include a link to renpy/LICENSE.txt. 2009-04-10 10:15:06 -04:00
Tom Rothamel b4c4d0264c Make scale correct and higher quality. 2009-04-10 02:40:15 -04:00
Tom Rothamel 21c3187fa3 Fix help on an imagemap menu. 2009-04-10 00:03:42 -04:00
Tom Rothamel b377cfcdef Only play activate and hover sounds if defined. 2009-04-09 22:52:09 -04:00
40 changed files with 808 additions and 366 deletions
+52
View File
@@ -1,3 +1,43 @@
New in Ren'Py 6.9.2
-------------------
The semantics for play and queue have changed slightly. Now, when a
play statement is followed by one or more queue statements, the first
file in each play or queue statement will be played. For example:
play music "a.ogg"
queue music "b.ogg"
queue music "c.ogg"
will play "a.ogg", "b.ogg", and then loop "c.ogg". This change also
applies to renpy.music.play and renpy.music.queue.
Rollback was changed so that doing anything other than a roll-forward
while in rollback mode exits rollback immediately.
The library alias for config has been removed.
Fixed a regression that caused dissolves to be terribly slow.
Fixed a bug that caused Ren'Py to crash when playing music on Windows
when Data Execution Prevention was enabled. DEP is enabled by default
on 64-bit Windows Vista.
Fixed a bug that caused Ren'Py to crash when a window icon was used on
a computer with a 16-bit or 8-bit screen depth.
Fixed a bug that caused ui.sizer to malfunction.
Fixed a repeated word in "The Question".
Fixed a bug that could cause it to take two tries to define a joystick
button.
New in Ren'Py 6.9.1
-------------------
@@ -62,6 +102,10 @@ There is a new config.windows_icon variable, that lets one set the
window icon for Windows separately from Mac OS X and Linux.
Ren'Py now automatically scales itself down when it detects that the
game window is too large for the screen.
The define.move_transitions function can now pass keyword arguments to
the moves it creates. The most useful thing with this is to pass
subpixel=True, in order to create subpixel move transitions.
@@ -93,6 +137,14 @@ Added more verbose diagnostics when illegal statements are run in the
init phase.
Added _rollback, which controls if rollback is enabled.
Added a target parameter to renpy.full_restart, which allows the main
menu screen to be selected after a restart.
Fixed a bug that caused layout.imagemap_main_menu to call a label even
though there was a button with the same name.
+1 -1
View File
@@ -35,7 +35,7 @@ launchers may contain code taken from the following projects:
* SDL_ttf (LGPL)
* SDL_mixer (LGPL)
* Freetype (LGPL)
* ffmpeg (LGPL)
* FFmpeg (LGPL)
* jpeg (JPEG License)
* libpng (PNG license)
* zlib (Zlib License)
+3
View File
@@ -13,6 +13,9 @@ init -1210 python:
if version <= (6, 5, 0):
layout.compat()
if version <= (6, 9, 1):
store.library = store.config
init 1210 python hide::
# This returns true if the script_version is <= the
+11 -11
View File
@@ -607,7 +607,7 @@ label _return:
if renpy.context().main_menu:
$ renpy.transition(config.game_main_transition)
jump _main_menu
jump _main_menu_screen
$ renpy.transition(config.exit_transition)
@@ -682,12 +682,6 @@ label _start:
$ renpy.block_rollback()
python hide:
for i in range(0, 7):
# renpy.music.stop(channel=i)
# renpy.sound.stop(channel=i)
pass
if config.main_menu_music:
$ renpy.music.play(config.main_menu_music, if_changed=True)
else:
@@ -703,15 +697,19 @@ label _start:
jump expression _restart[1]
label _invoke_main_menu:
$ renpy.call_in_new_context("_enter_main_menu")
if _restart:
$ renpy.call_in_new_context(_restart[2])
else:
$ renpy.call_in_new_context("_main_menu")
# If the main menu returns, then start the game.
jump start
# At this point, we've been switched into a new context. So we
# initialize it.
label _enter_main_menu:
label _main_menu(_main_menu_screen="_main_menu_screen"):
call _enter_menu from _call__enter_menu_1
@@ -721,9 +719,11 @@ label _enter_main_menu:
renpy.context().main_menu = True
store.main_menu = True
jump expression _main_menu_screen
# This is called to show the main menu to the user.
label _main_menu:
label _main_menu_screen:
# Let the user completely override the main menu. (But please note
# it still lives in the menu context, rather than the game context.)
+1 -1
View File
@@ -18,7 +18,7 @@ init -1130 python hide:
for i in xrange(0, 8):
renpy.music.register_channel(i)
renpy.music.register_channel("movie", "music", False)
renpy.music.register_channel("movie", "music", False, stop_on_mute=False)
# Set up default names for some of the channels.
renpy.music.alias_channel(0, "sound")
@@ -28,8 +28,6 @@ init python:
style.js_prefs_button.xminimum = 0.5
style.js_prefs_box.box_first_spacing = 10
config.joystick_keys = [
(u'Left', 'joy_left'),
(u'Right', 'joy_right'),
@@ -42,8 +40,6 @@ init python:
(u'Hide Text', 'joy_hide'),
(u'Menu', 'joy_menu'),
]
def _joystick_select_binding():
@@ -55,8 +51,8 @@ init python:
layout.button(_(label) + " - " + _(_preferences.joymap.get(key, u"Not Assigned")), "prefs_js", clicked=my_clicked, index=label)
def _joystick_get_binding():
ui.add(renpy.display.joystick.JoyBehavior())
ui.saybehavior()
ui.add(renpy.display.joystick.JoyBehavior())
def _joystick_take_binding(binding, key):
+2 -1
View File
@@ -49,6 +49,7 @@ label main_menu_screen:
else:
ui.jumpsoutofcontext(rv)()
jump main_menu_screen
+2
View File
@@ -49,6 +49,8 @@ label start:
e "We look forward to seeing what you can make with this! Good luck!"
window hide
# Returning from the top level quits the game.
return
+1
View File
@@ -228,6 +228,7 @@ def main():
print "Did you remember to rebuild the exe after the last change?"
print "Did you run me with renpython -OO?"
print "Was ming using the right crt?"
print "Did you update renpy.py and launcher/script_version.rpy?"
if __name__ == "__main__":
main()
+5 -1
View File
@@ -29,9 +29,10 @@ margin-left: -2.5em;
</style>
</head>
<body>
<div id="renpy_help"></div>
<p><a name="Basic_Help" id="Basic_Help"></a></p>
<h3><span class="mw-headline">Basic Help</span></h3>
<h2><span class="mw-headline">Basic Help</span></h2>
<p>To advance through the game, <tt>left-click</tt> or press the <tt>space</tt> or <tt>enter</tt> keys. When at a menu, <tt>left-click</tt> to make a choice, or use the arrow keys to select a choice and <tt>enter</tt> to activate it.</p>
<p><a name="Game_Menu" id="Game_Menu"></a></p>
<h3><span class="mw-headline">Game Menu</span></h3>
@@ -105,5 +106,8 @@ margin-left: -2.5em;
<dt>Alt-F4, Command-Q</dt>
<dd>Quits the game.</dd>
</dl>
<p><a name="Legal_Notice" id="Legal_Notice"></a></p>
<h2><span class="mw-headline">Legal Notice</span></h2>
<p>This game uses source code from a number of open source projects. For a list, and a location where the source code can be downloaded from, please view the <a href="./renpy/LICENSE.txt">LICENSE.txt</a> file in the renpy directory.</p>
</body>
</html>
+10 -7
View File
@@ -10,14 +10,17 @@ init:
if not config.editor:
editor = os.path.normpath(config.renpy_base + "/jedit/jedit.jar")
editor = renpy.shell_escape(editor)
if sys.platform == 'win32':
config.editor = 'javaw.exe -jar "' + editor + '" -reuseview "%(filename)s" +line:%(line)d "%(otherfiles)s"'
config.editor_transient = 'javaw.exe -jar "' + editor + '" -newplainview "%(filename)s" +line:%(line)d "%(otherfiles)s"'
else:
config.editor = 'java -jar "' + editor + '" -reuseview "%(filename)s" +line:%(line)d "%(otherfiles)s"'
config.editor_transient = 'java -jar "' + editor + '" -newplainview "%(filename)s" +line:%(line)d "%(otherfiles)s"'
if os.path.exists(editor):
editor = renpy.shell_escape(editor)
if sys.platform == 'win32':
config.editor = 'javaw.exe -jar "' + editor + '" -reuseview "%(filename)s" +line:%(line)d "%(otherfiles)s"'
config.editor_transient = 'javaw.exe -jar "' + editor + '" -newplainview "%(filename)s" +line:%(line)d "%(otherfiles)s"'
else:
config.editor = 'java -jar "' + editor + '" -reuseview "%(filename)s" +line:%(line)d "%(otherfiles)s"'
config.editor_transient = 'java -jar "' + editor + '" -newplainview "%(filename)s" +line:%(line)d "%(otherfiles)s"'
if config.editor:
os.environ['RENPY_EDITOR'] = config.editor
+1 -1
View File
@@ -1,3 +1,3 @@
init -999:
$ config.script_version = (6, 9, 0)
$ config.script_version = (6, 9, 2)
+25 -25
View File
@@ -1000,18 +1000,18 @@ void transform32_std(PyObject *pysrc, PyObject *pydst,
unsigned int amul = (int) (a * 256);
lsx = corner_x * 256;
lsy = corner_y * 256;
lsx = corner_x * 65536;
lsy = corner_y * 65536;
xdx *= 256;
ydx *= 256;
xdy *= 256;
ydy *= 256;
xdx *= 65536;
ydx *= 65536;
xdy *= 65536;
ydy *= 65536;
// Scaled subtracted srcw and srch.
float fsw = (srcw - 2) * 256;
float fsh = (srch - 2) * 256;
float fsw = (srcw - 1) * 65536 - 1;
float fsh = (srch - 1) * 65536 - 1;
for (y = 0; y < dsth; y++, lsx += xdy, lsy += ydy) {
@@ -1058,7 +1058,7 @@ void transform32_std(PyObject *pysrc, PyObject *pydst,
sx = lsx + minx * xdx;
sy = lsy + minx * ydx;
int sxi = (int) sx;
int syi = (int) sy;
int xdxi = (int) xdx;
@@ -1066,13 +1066,13 @@ void transform32_std(PyObject *pysrc, PyObject *pydst,
while (d <= dend) {
int px, py;
px = sxi >> 8;
py = syi >> 8;
px = sxi >> 16;
py = syi >> 16;
unsigned char *sp = srcpixels + py * srcpitch + px * 4;
int yfrac = syi & 0xff; // ((short) sy) & 0xff;
int xfrac = sxi & 0xff; // ((short) sx) & 0xff;
int yfrac = (syi >> 8) & 0xff; // ((short) sy) & 0xff;
int xfrac = (sxi >> 8) & 0xff; // ((short) sx) & 0xff;
unsigned int pal = *(unsigned int *) sp;
unsigned int pbl = *(unsigned int *) (sp + 4);
@@ -1164,17 +1164,17 @@ int transform32_mmx(PyObject *pysrc, PyObject *pydst,
// Compute the coloring multiplier.
unsigned int amul = (unsigned int) (a * 256);
lsx = corner_x * 256;
lsy = corner_y * 256;
lsx = corner_x * 65536;
lsy = corner_y * 65536;
xdx *= 256;
ydx *= 256;
xdy *= 256;
ydy *= 256;
xdx *= 65536;
ydx *= 65536;
xdy *= 65536;
ydy *= 65536;
// Scaled subtracted srcw and srch.
float fsw = (srcw - 2) * 256;
float fsh = (srch - 2) * 256;
float fsw = (srcw - 1) * 65536 - 1;
float fsh = (srch - 1) * 65536 - 1;
for (y = 0; y < dsth; y++, lsx += xdy, lsy += ydy) {
@@ -1235,13 +1235,13 @@ int transform32_mmx(PyObject *pysrc, PyObject *pydst,
while (d <= dend) {
px = sxi >> 8;
py = syi >> 8;
px = sxi >> 16;
py = syi >> 16;
unsigned char *sp = srcpixels + py * srcpitch + px * 4;
unsigned int yfrac = syi & 0xff; // ((short) sy) & 0xff;
unsigned int xfrac = sxi & 0xff; // ((short) sx) & 0xff;
unsigned int yfrac = (syi >> 8) & 0xff; // ((short) sy) & 0xff;
unsigned int xfrac = (sxi >> 8) & 0xff; // ((short) sx) & 0xff;
// Put xfrac in mm5, yfrac in m6
pxor_r2r(mm5, mm5);
+5 -4
View File
@@ -22,11 +22,12 @@
#include <pygame/pygame.h>
#include <math.h>
#include <limits.h>
#include "libavutil/avstring.h"
#include "libavformat/avformat.h"
#include <libavutil/avstring.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
// #include "libavdevice/avdevice.h"
#include "libswscale/swscale.h"
#include "libavcodec/audioconvert.h"
#include <libswscale/swscale.h>
// #include "libavcodec/audioconvert.h"
// #include "libavcodec/opt.h"
// #include "cmdutils.h"
+42 -19
View File
@@ -1,4 +1,3 @@
/*
Copyright 2005-2009 PyTom <pytom@bishoujo.us>
@@ -112,9 +111,6 @@ struct Channel {
/* The queued up sample. */
struct VideoState *queued;
/* A sample that's dying, and needs to be deallocated. */
struct VideoState *dying;
/* The name of the queued up sample. */
PyObject *queued_name;
@@ -173,6 +169,13 @@ struct Channel {
unsigned int vol2_done;
};
struct Dying {
struct VideoState *stream;
struct Dying *next;
};
static struct Dying *dying = NULL;
/*
* The number of channels the system knows about.
*/
@@ -247,8 +250,12 @@ static void start_sample(struct Channel* c, int reset_fade) {
c->fade_off = 0;
c->fade_vol = 0;
c->fade_step_len = ms_to_bytes(c->playing_fadein) / fade_steps;
c->fade_step_len &= ~0x7; // Even sample.
if (fade_steps) {
c->fade_step_len = ms_to_bytes(c->playing_fadein) / fade_steps;
c->fade_step_len &= ~0x7; // Even sample.
} else {
c->fade_step_len = 0;
}
}
c->stop_bytes = -1;
@@ -440,10 +447,15 @@ static void callback(void *userdata, Uint8 *stream, int length) {
if (c->stop_bytes == 0 || bytes == 0) {
int old_tight = c->playing_tight;
struct Dying *d;
post_event(c);
c->dying = c->playing;
d = malloc(sizeof(struct Dying));
d->next = dying;
d->stream = c->playing;
dying = d;
decref(c->playing_name);
c->playing = c->queued;
@@ -488,7 +500,6 @@ static int check_channel(int c) {
channels[i].queued = NULL;
channels[i].playing_name = NULL;
channels[i].queued_name = NULL;
channels[i].dying = NULL;
channels[i].volume = SDL_MIX_MAXVOLUME;
channels[i].paused = 1;
channels[i].event = 0;
@@ -786,14 +797,20 @@ void PSS_fadeout(int channel, int ms) {
return;
}
fade_steps = c->volume;
c->fade_delta = -1;
c->fade_off = 0;
c->fade_vol = c->volume;
c->fade_step_len = ms_to_bytes(ms) / fade_steps;
c->fade_step_len &= ~0x7; // Even sample.
if (fade_steps) {
c->fade_step_len = ms_to_bytes(ms) / fade_steps;
c->fade_step_len &= ~0x7; // Even sample.
} else {
c->fade_step_len = 0;
}
c->stop_bytes = ms_to_bytes(ms);
c->queued_tight = 0;
@@ -1080,14 +1097,20 @@ void PSS_periodic() {
int i;
for (i = 0; i < num_channels; i++) {
if (channels[i].dying) {
ENTER();
ffpy_stream_close(channels[i].dying);
channels[i].dying = NULL;
EXIT();
}
if (!dying) {
return;
}
ENTER();
while (dying) {
struct Dying *d = dying;
ffpy_stream_close(d->stream);
dying = d->next;
free(d);
}
EXIT();
}
/* This should be called in response to an FF_ALLOC_EVENT, with a pygame
+1 -1
View File
@@ -27,7 +27,7 @@
#include <Python.h>
#include <stdio.h>
#include <string.h>
#include "pygame.h"
#include <pygame/pygame.h>
#include "structmember.h"
#include "renpy_ttf.h"
Regular → Executable
+103 -35
View File
@@ -1,6 +1,4 @@
#!/usr/bin/env python
import distutils.core
import os
import os.path
@@ -12,45 +10,119 @@ try:
except:
pass
# These control the level of optimization versus debugging.
extra_compile_args = [ "-O3", "-funroll-loops" ]
# extra_compile_args = [ "-O0", "-ggdb" ]
# extra_compile_args = [ "-O0", "-gstabs" ]
# This environment variable should have the full path to the installed
# Ren'Py dependencies.
install = os.environ.get("RENPY_DEPS_INSTALL", "/does/not/exist")
install = os.environ.get("RENPY_DEPS_INSTALL", None)
# Check to see if that's the case.
if not os.path.isdir(install):
print "The Ren'Py dependencies install directory:"
print
print install
print
print "does not exist. Please set RENPY_DEPS_INSTALL to the correct"
print "location of the Ren'Py dependencies install directory, and "
print "re-run this script."
if install is None:
print """
The RENPY_DEPS_INSTALL environment variable has not been set. This
should be set to a double-colon-delimited list of places where the
Ren'Py dependencies can be found. (To use system libraries, this can
be set to a system directory, like /usr.)
"""
sys.exit(-1)
ffmpeg = os.environ.get("FFMPEG_BUILD_PATH", "/does/not/exist")
install = install.split("::")
if not os.path.isdir(install):
print "The FFMPEG build path:"
print
print ffmpeg
print
print "does not exist. Please set FFMPEG_BUILD_PATH to the correct"
print "location and re-run this script."
sys.exit(-1)
include_dirs = [ ]
library_dirs = [ ]
def add_include(prefix, file):
"""
Search for prefix/file underneath <i> and <i>/include, for each of the
directories <i> in install. When found, puts the directory it was found
in into include_dirs.
"""
checked = [ ]
for i in install:
dir = os.path.join(i, prefix)
fn = os.path.join(dir, file)
fn = os.path.normpath(fn)
checked.append(fn)
if os.path.exists(fn):
break
dir = os.path.join(i, "include", prefix)
fn = os.path.join(dir, file)
fn = os.path.normpath(fn)
checked.append(fn)
if os.path.exists(fn):
break
else:
print "Could not find include %s." % file
print "The paths searched were:"
for i in checked:
print "-", i
sys.exit(-1)
dir = os.path.normpath(dir)
print "Found %s in %s." % (file, dir)
if dir not in include_dirs:
include_dirs.append(dir)
def add_library(name):
"""
This looks for a library named name in the <i> and <i>/lib, for all
<i> in install. When found, it adds it to library_dirs.
"""
checked = [ ]
# Default compile arguements for everybody.
include_dirs = [ install + "/include",
install + "/include/SDL",
install + "/include/freetype2",
install + "/include/pygame",
ffmpeg]
for i in install:
for d in ('', 'lib'):
for suffix in (".so", ".dylib", ".a"):
library_dirs = [ install + "/lib" ]
dir = os.path.join(i, d)
fn = os.path.join(dir, name + suffix)
checked.append(fn)
if os.path.exists(fn):
print "Found %s." % fn
if dir not in library_dirs:
library_dirs.append(dir)
return
print "Couldn't find library %s." % name
print "The paths searched were:"
for i in checked:
print "-", i
sys.exit(-1)
add_include("", "zlib.h")
add_include("", "png.h")
add_include("SDL", "SDL.h")
add_include("", "ft2build.h")
add_include("freetype2", "freetype/freetype.h")
add_include("", "libavutil/avstring.h")
add_include("", "libavformat/avformat.h")
add_include("", "libavcodec/avcodec.h")
add_include("", "libswscale/swscale.h")
add_library("libSDL")
add_library("libz")
add_library("libpng")
add_library("libavformat")
add_library("libavcodec")
add_library("libavutil")
add_library("libfreetype")
# Fast math breaks on windows. :-(
extra_compile_args = [ "-O3", "-funroll-loops" ] # , "-ffast-math" ]
# extra_compile_args = [ "-O0", "-ggdb" ]
extra_link_args = [ ]
@@ -67,10 +139,6 @@ if platform.win32_ver()[0]:
extra_compile_args.append("-fno-strict-aliasing")
winmixer = True
# Detect mac.
if platform.mac_ver()[0]:
nativemidi_libs = [ 'SDL' ]
# Detect OSS.
try:
import ossaudiodev
+5 -1
View File
@@ -124,7 +124,11 @@ def get_pos(channel):
return PSS_get_pos(channel)
def set_volume(channel, volume):
PSS_set_volume(channel, 10 ** volume / 10 )
if volume == 0:
PSS_set_volume(channel, 0)
else:
PSS_set_volume(channel, 10 ** volume / 10 )
check_error()
def set_pan(channel, pan, delay):
+1 -1
View File
@@ -1 +1 @@
dist/MSVCR71.dll
dist/msvcr71.dll
+1 -1
View File
@@ -27,7 +27,7 @@
# ***** ***** ***** ***** ***** ***** **** ***** ***** ***** *****
# Be sure to change script_version in launcher/script_version.rpy, too!
# Also check to see if we have to update renpy.py.
version = "Ren'Py 6.9.1b"
version = "Ren'Py 6.9.2a"
script_version = 5003000
savegame_suffix = "-LT1.save"
+54 -34
View File
@@ -181,7 +181,7 @@ class Channel(object):
This stores information about the currently-playing music.
"""
def __init__(self, name, default_loop):
def __init__(self, name, default_loop, stop_on_mute, tight):
# The name assigned to this channel. This is used to look up
# information about the channel in the MusicContext object.
@@ -235,6 +235,17 @@ class Channel(object):
# The time the secondary volume of this channel was last set.
self.secondary_volume_time = None
# Should we stop playing on mute?
self.stop_on_mute = stop_on_mute
# Is this channel tight?
self.tight = tight
# The number of items in the queue that should be kept
# on queue clear.
self.keep_queue = 0
if default_loop is None:
# By default, should we loop the music?
self.default_loop = True
@@ -287,10 +298,9 @@ class Channel(object):
# This should be set from something that checks to see if our
# mixer is muted.
force_stop = self.context.force_stop or renpy.game.preferences.mute[self.mixer]
force_stop = self.context.force_stop or (renpy.game.preferences.mute[self.mixer] and self.stop_on_mute)
if self.playing and force_stop:
pss.stop(self.number)
self.playing = False
self.wait_stop = False
@@ -335,14 +345,18 @@ class Channel(object):
break
# Otherwise, we might be able to enqueue something.
topq = self.queue[0]
topq = self.queue.pop(0)
# At this point, we've decided to try to play
# top. So let's see how far we can get.
# Update the queue
self.queue = self.queue[1:]
# Blacklist of old file formats we used to support, but we now
# ignore.
lfn = topq.filename.lower()
for i in (".mod", ".xm", ".mid", ".midi"):
if lfn.endswith(i):
topq = None
if not topq:
continue
try:
topf = load(topq.filename)
@@ -374,22 +388,27 @@ class Channel(object):
def dequeue(self, even_tight=False):
"""
Clears any queued music. Doesn't stop the playing music, if
any, but will prevent looping from occuring.
Clears the queued music.
If the first item in the queue has not been started, then it is
left in the queue unless all is given.
"""
self.queue = [ ]
self.queue = self.queue[:self.keep_queue]
self.loop = [ ]
if not pcm_ok:
return
pss.dequeue(self.number, even_tight)
if self.keep_queue == 0:
pss.dequeue(self.number, even_tight)
def interact(self):
"""
Called (mostly) once per interaction.
"""
self.keep_queue = 0
if pcm_ok:
@@ -418,6 +437,7 @@ class Channel(object):
of seconds. Also clears any queued music.
"""
self.keep_queue = 0
self.dequeue()
if not pcm_ok:
@@ -429,7 +449,7 @@ class Channel(object):
pss.fadeout(self.number, int(secs * 1000))
def enqueue(self, filenames, loop=True, synchro_start=False, fadein=0, tight=False):
def enqueue(self, filenames, loop=True, synchro_start=False, fadein=0, tight=None):
for filename in filenames:
renpy.game.persistent._seen_audio[filename] = True
@@ -437,6 +457,11 @@ class Channel(object):
if not pcm_ok:
return
if tight is None:
tight = self.tight
self.keep_queue += 1
for filename in filenames:
qe = QueueEntry(filename, int(fadein * 1000), tight)
self.queue.append(qe)
@@ -494,11 +519,11 @@ all_channels = [ ]
channels = { }
def register_channel(name, mixer=None, loop=None):
def register_channel(name, mixer=None, loop=None, stop_on_mute=True, tight=False):
if not renpy.game.init_phase:
raise Exception("Can't register channel outside of init phase.")
c = Channel(name, loop)
c = Channel(name, loop, stop_on_mute, tight)
c.mixer = mixer
all_channels.append(c)
channels[name] = c
@@ -634,7 +659,7 @@ def periodic():
max_volume = -1.0
volumes = renpy.game.preferences.volumes
if mix_ok:
anything_playing = False
@@ -646,28 +671,26 @@ def periodic():
if vol != 0:
anything_playing = True
if not anything_playing:
disable_mixer()
return
enable_mixer()
if max_volume == -1.0:
return
if max_volume == 0.0:
return
if not anything_playing:
disable_mixer()
pcm_volume = -1.0
else:
enable_mixer()
if max_volume != pcm_volume:
mix.set_wave(max_volume)
pcm_volume = max_volume
if max_volume != pcm_volume:
mix.set_wave(max_volume)
pcm_volume = max_volume
for c in all_channels:
vol = c.chan_volume * volumes[c.mixer]
vol /= max_volume
if c.actual_volume != vol:
pss.set_volume(c.number, vol)
c.actual_volume = vol
@@ -676,9 +699,6 @@ def periodic():
for c in all_channels:
if not c.playing:
continue
vol = c.chan_volume * volumes[c.mixer]
if vol != c.actual_volume:
+2 -4
View File
@@ -35,7 +35,7 @@ from renpy.audio.audio import get_channel, get_serial
# Part of the public api:
from renpy.audio.audio import register_channel, alias_channel
def play(filenames, channel="music", loop=None, fadeout=None, synchro_start=False, fadein=0, tight=False, if_changed=False):
def play(filenames, channel="music", loop=None, fadeout=None, synchro_start=False, fadein=0, tight=None, if_changed=False):
"""
This stops the music currently playing on the numbered channel, dequeues
any queued music, and begins playing the specified file or files. If loop
@@ -108,7 +108,7 @@ def play(filenames, channel="music", loop=None, fadeout=None, synchro_start=Fals
raise
def queue(filenames, channel="music", loop=None, clear_queue=True, fadein=0, tight=False):
def queue(filenames, channel="music", loop=None, clear_queue=True, fadein=0, tight=None):
"""
This queues the given filenames on the specified channel. If
clear_queue is True, then the queue is cleared, making these files
@@ -185,8 +185,6 @@ def stop(channel="music", fadeout=None):
try:
c = get_channel(channel)
ctx = c.context
c.dequeue()
if fadeout is None:
fadeout = renpy.config.fade_music
+1 -1
View File
@@ -214,7 +214,7 @@ def display_say(show_function,
# If we're in fast skipping mode, don't bother with say
# statements at all.
if renpy.config.skipping == "fast":
if interact and renpy.config.skipping == "fast":
# Clears out transients.
renpy.exports.with_statement(None)
+23 -22
View File
@@ -187,9 +187,7 @@ class Keymap(renpy.display.layout.Null):
class RollForward(renpy.display.layout.Null):
"""
This is a behavior that maps keys to functions that are called when
the key is pressed. The keys are specified by giving the appropriate
k_constant from pygame.constants, or the unicode for the key.
This behavior implements rollforward.
"""
def __init__(self, value):
@@ -202,6 +200,7 @@ class RollForward(renpy.display.layout.Null):
if map_event(ev, "rollforward"):
renpy.game.interface.suppress_transition = True
renpy.game.after_rollback = True
renpy.game.log.rolled_forward = True
return self.value
class PauseBehavior(renpy.display.layout.Null):
@@ -276,22 +275,6 @@ class SayBehavior(renpy.display.layout.Null):
def event(self, ev, x, y, st):
skip_delay = renpy.config.skip_delay / 1000.0
if renpy.config.allow_skipping and renpy.config.skipping and \
st >= skip_delay:
if renpy.game.preferences.skip_unseen:
return True
elif renpy.config.skipping == "fast":
return True
elif renpy.game.context().seen_current(True):
return True
if renpy.config.allow_skipping and renpy.config.skipping and \
st < skip_delay:
renpy.game.interface.timeout(skip_delay - st)
if self.afm_length and renpy.game.preferences.afm_time and renpy.game.preferences.afm_enable:
afm_delay = ( 1.0 * ( renpy.config.afm_bonus + self.afm_length ) / renpy.config.afm_characters ) * renpy.game.preferences.afm_time
@@ -311,7 +294,7 @@ class SayBehavior(renpy.display.layout.Null):
renpy.game.interface.timeout(afm_delay - st)
for dismiss in self.dismiss:
if map_event(ev, dismiss) and self.is_focused():
if renpy.config.skipping:
@@ -325,6 +308,23 @@ class SayBehavior(renpy.display.layout.Null):
return True
skip_delay = renpy.config.skip_delay / 1000.0
if renpy.config.allow_skipping and renpy.config.skipping and \
st >= skip_delay:
if renpy.game.preferences.skip_unseen:
return True
elif renpy.config.skipping == "fast":
return True
elif renpy.game.context().seen_current(True):
return True
if renpy.config.allow_skipping and renpy.config.skipping and \
st < skip_delay:
renpy.game.interface.timeout(skip_delay - st)
return None
@@ -423,8 +423,9 @@ class Button(renpy.display.layout.Window):
self.activated = True
self.style.set_prefix(self.role + 'activate_')
renpy.audio.sound.play(self.style.sound)
if self.style.sound:
renpy.audio.music.play(self.style.sound, channel="sound")
rv = self.clicked()
+19 -13
View File
@@ -119,7 +119,8 @@ class Displayable(renpy.object.Object):
self.set_style_prefix(self.role + "hover_")
if not default and not self.activated:
renpy.audio.sound.play(self.style.sound)
if self.style.sound:
renpy.audio.music.play(self.style.sound, channel="sound")
def unfocus(self):
"""
@@ -698,15 +699,13 @@ class Display(object):
# Convert the aspect ratio to be square.
iw, ih = im.get_size()
if iw != ih:
imax = max(iw, ih)
square_im = renpy.display.scale.PygameSurface((imax, imax), pygame.SRCALPHA)
square_im.blit(im, ( (imax-iw)/2, (imax-ih)/2 ))
im = square_im
imax = max(iw, ih)
square_im = renpy.display.scale.PygameSurface((imax, imax), pygame.SRCALPHA, depth=32)
square_im.blit(im, ( (imax-iw)/2, (imax-ih)/2 ))
im = square_im
if on_windows and im.get_size() != (32, 32):
im = renpy.display.scale.real_bilinear(im, (32, 32))
im = renpy.display.scale.real_smoothscale(im, (32, 32))
pygame.display.set_icon(im)
@@ -1014,16 +1013,23 @@ class Display(object):
Saves a full-size screenshot in the given filename.
"""
renpy.display.scale.image_save_unscaled(self.window, filename)
try:
renpy.display.scale.image_save_unscaled(self.window, filename)
except:
if renpy.config.debug:
raise
pass
def screenshot(self, scale):
"""
Returns a pygame Surface that is a screenshot of the current
contents of the window.
Returns a string containing the contents of the window, as a PNG.
"""
surf = renpy.display.module.scale(self.window, scale)
surf = self.window.convert_alpha()
surf = renpy.display.scale.smoothscale(surf, scale)
surf = surf.convert()
sio = cStringIO.StringIO()
renpy.display.module.save_png(surf, sio, 0)
+2 -1
View File
@@ -78,7 +78,8 @@ class ImageFont(object):
def render(self, text, antialias, color, black_color=(0, 0, 0, 255), background=None):
if not text:
return surf
return pygame.Surface((0, self.height), 0,
renpy.game.interface.display.sample_surface)
xoff, _ = self.offsets[text[0]]
x = -xoff
+39 -21
View File
@@ -687,7 +687,7 @@ class FrameImage(ImageBase):
tilew, tileh = srcsize
dstw, dsth = dstsize
surf2 = pygame.Surface(dstsize, 0, surf)
surf2 = renpy.display.scale.PygameSurface(dstsize, 0, surf)
for y in range(0, dsth, tileh):
for x in range(0, dstw, tilew):
@@ -707,6 +707,7 @@ class FrameImage(ImageBase):
# Blit.
dest.blit(surf, (dx0, dy0))
# Top row.
draw(0, xb, 0, yb)
draw(xb, -xb, 0, yb)
@@ -721,7 +722,7 @@ class FrameImage(ImageBase):
draw(0, xb, -yb, 0)
draw(xb, -xb, -yb, 0)
draw(-xb, 0, -yb, 0)
# And, finish up.
return rv
@@ -770,15 +771,20 @@ class Scale(ImageBase):
def load(self):
child = cache.get(self.image)
if self.bilinear:
renpy.display.render.blit_lock.acquire()
rv = pygame.transform.smoothscale(cache.get(self.image), (self.width, self.height))
renpy.display.render.blit_lock.release()
try:
renpy.display.render.blit_lock.acquire()
rv = renpy.display.scale.smoothscale(child, (self.width, self.height))
finally:
renpy.display.render.blit_lock.release()
else:
renpy.display.render.blit_lock.acquire()
rv = pygame.transform.scale(cache.get(self.image), (self.width, self.height))
renpy.display.render.blit_lock.release()
try:
renpy.display.render.blit_lock.acquire()
rv = pygame.transform.scale(child, (self.width, self.height))
finally:
renpy.display.render.blit_lock.release()
return rv
@@ -813,14 +819,18 @@ class FactorScale(ImageBase):
height = int(height * self.height)
if self.bilinear:
renpy.display.render.blit_lock.acquire()
rv = pygame.transform.smoothscale(surf, (width, height))
renpy.display.render.blit_lock.release()
try:
renpy.display.render.blit_lock.acquire()
rv = renpy.display.scale.smoothscale(surf, (width, height))
finally:
renpy.display.render.blit_lock.release()
else:
renpy.display.render.blit_lock.acquire()
rv = pygame.transform.scale(surf, (width, height))
renpy.display.render.blit_lock.release()
try:
renpy.display.render.blit_lock.acquire()
rv = pygame.transform.scale(surf, (width, height))
finally:
renpy.display.render.blit_lock.release()
return rv
@@ -856,9 +866,13 @@ class Flip(ImageBase):
def load(self):
renpy.display.render.blit_lock.acquire()
rv = pygame.transform.flip(cache.get(self.image), self.horizontal, self.vertical)
renpy.display.render.blit_lock.release()
child = cache.get(self.image)
try:
renpy.display.render.blit_lock.acquire()
rv = pygame.transform.flip(child, self.horizontal, self.vertical)
finally:
renpy.display.render.blit_lock.release()
return rv
@@ -893,9 +907,13 @@ class Rotozoom(ImageBase):
def load(self):
renpy.display.render.blit_lock.acquire()
rv = pygame.transform.rotozoom(cache.get(self.image), self.angle, self.zoom)
renpy.display.render.blit_lock.release()
child = cache.get(self.image)
try:
renpy.display.render.blit_lock.acquire()
rv = pygame.transform.rotozoom(child, self.angle, self.zoom)
finally:
renpy.display.render.blit_lock.release()
return rv
+1 -1
View File
@@ -26,7 +26,7 @@ import pygame
from pygame.constants import *
import renpy
from renpy.display.render import render, IDENTITY, Matrix2D
from renpy.display.render import render, Render, IDENTITY, Matrix2D
import time
import math
+1
View File
@@ -383,6 +383,7 @@ else:
if version >= 6009000:
def subpixel(src, dst, x, y):
shift = renpy.game.interface.display.sample_surface.get_shifts()[3]
_renpy.subpixel(src, dst, x, y, shift)
+115 -78
View File
@@ -27,6 +27,7 @@ import math
import renpy
# We grab the blit lock each time it is necessary to blit
# something. This allows call to the pygame.transform functions to
# disable blitting, should it prove necessary.
@@ -177,30 +178,43 @@ def process_redraws():
need to redraw the screen now, false otherwise.
"""
global redraw_queue
redraw_queue.sort()
now = renpy.display.core.get_time()
rv = invalidated
new_redraw_queue = [ ]
seen = set()
while redraw_queue:
when, d = redraw_queue[0]
for t in redraw_queue:
when, d = t
if when > now:
break
if d in seen:
continue
redraw_queue.pop(0)
seen.add(d)
# Remove this displayable and all its parents from the
# render cache. But don't kill them yet, as that will kill the
# children that we want to reuse.
if d not in render_cache:
continue
if d in render_cache:
if when <= now:
# Remove this displayable and all its parents from the
# render cache. But don't kill them yet, as that will kill the
# children that we want to reuse.
for v in render_cache[d].values():
v.kill_cache()
rv = True
else:
new_redraw_queue.append(t)
redraw_queue = new_redraw_queue
return rv
@@ -222,7 +236,7 @@ def redraw(d, when):
if not renpy.game.interface:
return
redraw_queue.append((when + renpy.game.interface.frame_time, d))
@@ -475,10 +489,12 @@ def draw(dest, clip, what, xo, yo, screen):
if clip:
w, h = what.get_size()
dest.blits.append((xo, yo, xo + w, yo + h, clip, what, None))
else:
blit_lock.acquire()
dest.blit(what, (xo, yo))
blit_lock.release()
else:
try:
blit_lock.acquire()
dest.blit(what, (xo, yo))
finally:
blit_lock.release()
# Subpixel blit.
else:
@@ -1262,7 +1278,7 @@ class Render(object):
vc = [ ]
rv = True
else:
if not source.get_masks()[3]:
if not child.get_masks()[3]:
vc = [ ]
rv = True
@@ -1333,82 +1349,103 @@ class Canvas(object):
self.surf = surf
def rect(self, color, rect, width=0):
blit_lock.acquire()
pygame.draw.rect(self.surf,
renpy.easy.color(color),
rect,
width)
blit_lock.release()
try:
blit_lock.acquire()
pygame.draw.rect(self.surf,
renpy.easy.color(color),
rect,
width)
finally:
blit_lock.release()
def polygon(self, color, pointlist, width=0):
blit_lock.acquire()
pygame.draw.polygon(self.surf,
renpy.easy.color(color),
pointlist,
width)
blit_lock.release()
try:
blit_lock.acquire()
pygame.draw.polygon(self.surf,
renpy.easy.color(color),
pointlist,
width)
finally:
blit_lock.release()
def circle(self, color, pos, radius, width=0):
blit_lock.acquire()
pygame.draw.circle(self.surf,
renpy.easy.color(color),
pos,
radius,
width)
blit_lock.release()
try:
blit_lock.acquire()
pygame.draw.circle(self.surf,
renpy.easy.color(color),
pos,
radius,
width)
finally:
blit_lock.release()
def ellipse(self, color, rect, width=0):
blit_lock.acquire()
pygame.draw.ellipse(self.surf,
renpy.easy.color(color),
rect,
width)
blit_lock.release()
try:
blit_lock.acquire()
pygame.draw.ellipse(self.surf,
renpy.easy.color(color),
rect,
width)
finally:
blit_lock.release()
def arc(self, color, rect, start_angle, stop_angle, width=1):
blit_lock.acquire()
pygame.draw.arc(self.surf,
renpy.easy.color(color),
rect,
start_angle,
stop_angle,
width)
blit_lock.release()
try:
blit_lock.acquire()
pygame.draw.arc(self.surf,
renpy.easy.color(color),
rect,
start_angle,
stop_angle,
width)
finally:
blit_lock.release()
def line(self, color, start_pos, end_pos, width=1):
blit_lock.acquire()
pygame.draw.line(self.surf,
renpy.easy.color(color),
start_pos,
end_pos,
width)
blit_lock.release()
try:
blit_lock.acquire()
pygame.draw.line(self.surf,
renpy.easy.color(color),
start_pos,
end_pos,
width)
finally:
blit_lock.release()
def lines(self, color, closed, pointlist, width=1):
blit_lock.acquire()
pygame.draw.lines(self.surf,
renpy.easy.color(color),
closed,
pointlist,
width)
blit_lock.release()
try:
blit_lock.acquire()
pygame.draw.lines(self.surf,
renpy.easy.color(color),
closed,
pointlist,
width)
finally:
blit_lock.release()
def aaline(self, color, startpos, endpos, blend=1):
blit_lock.acquire()
pygame.draw.aaline(self.surf,
renpy.easy.color(color),
startpos,
endpos,
blend)
blit_lock.release()
try:
blit_lock.acquire()
pygame.draw.aaline(self.surf,
renpy.easy.color(color),
startpos,
endpos,
blend)
finally:
blit_lock.release()
def aalines(self, color, closed, pointlist, blend=1):
blit_lock.acquire()
pygame.draw.aalines(self.surf,
renpy.easy.color(color),
closed,
pointlist,
blend)
blit_lock.release()
try:
blit_lock.acquire()
pygame.draw.aalines(self.surf,
renpy.easy.color(color),
closed,
pointlist,
blend)
finally:
blit_lock.release()
+228 -50
View File
@@ -39,21 +39,17 @@ try:
import _renpy
except ImportError:
_renpy = None
# The factor we're scaling by.
factor = 1.0
if ('RENPY_SCALE_FACTOR' in os.environ) or ('RENPY_SCALE_WIDTH' in os.environ):
enable_scaling = True
else:
enable_scaling = False
# Should we scale fast or scale good-looking?
scale_fast = False
##############################################################################
# The scaling API that's used if we don't enable scaling.
def init():
return
# Gets the real pygame surface.
def real(s):
return s
@@ -71,7 +67,6 @@ def real_bilinear(src, size):
def real_transform_scale(surf, size):
global real_transform_scale
real_transform_scale = pygame.transform.scale
return real_transform_scale(surf, size)
# Loads an image, without scaling it.
@@ -92,10 +87,60 @@ def image_save_unscaled(surf, dest):
pygame.image.save(surf, dest)
if _renpy:
real_renpy_pixellate = _renpy.pixellate
real_renpy_transform = _renpy.transform
def real_smoothscale(src, size, dest=None):
"""
This scales src up or down to size. This uses both the pixellate
and the bilinear operations to handle the scaling.
"""
width, height = size
srcwidth, srcheight = src.get_size()
iwidth, iheight = srcwidth, srcheight
if dest is None:
dest = PygameSurface(size, src.get_flags(), src)
if width == 0 or height == 0:
return dest
xshrink = 1
yshrink = 1
while iwidth >= width * 2:
xshrink *= 2
iwidth /= 2
while iheight >= height * 2:
yshrink *= 2
iheight /= 2
if iwidth != srcwidth or iheight != srcheight:
inter = PygameSurface((iwidth, iheight), src.get_flags(), src)
real_renpy_pixellate(src, inter, xshrink, yshrink, 1, 1)
src = inter
real_renpy_transform(src, dest,
0, 0,
1.0 * iwidth / width , 0,
0, 1.0 * iheight / height,
)
return dest
else:
real_smoothscale = pygame.transform.smoothscale
smoothscale = real_smoothscale
def init():
global factor
global scale_fast
if 'RENPY_SCALE_FACTOR' in os.environ:
factor = float(os.environ['RENPY_SCALE_FACTOR'])
elif 'RENPY_SCALE_WIDTH' in os.environ:
@@ -107,24 +152,26 @@ def init():
else:
factor = 1.0
# Automatically scale to screen if too small.
# info = pygame.display.Info()
info = pygame.display.Info()
# factor = min(1.0,
# 1.0 * info.current_w / renpy.config.screen_width,
# 1.0 * info.current_h / renpy.config.screen_height)
# if factor <= 0:
# factor = 1.0
factor = min(1.0,
1.0 * info.current_w / renpy.config.screen_width,
1.0 * info.current_h / renpy.config.screen_height)
if factor <= 0:
factor = 1.0
if factor != 1.0:
print "Using scale factor of %f." % factor
load_scaling()
if 'RENPY_SCALE_FAST' in os.environ:
scale_fast = True
else:
scale_fast = False
scaling_loaded = False
@@ -143,6 +190,29 @@ def load_scaling():
def real(s):
return s.surface
def same_size(*args):
"""
If all the surfaces in args are the same size, return them all
unchanged. Otherwise, compute smallest width and height, and
take subsurfaces of anythign bigger.
"""
w = min(i.get_width() for i in args)
h = min(i.get_height() for i in args)
size = (w, h)
rv = [ ]
for i in args:
if i.get_size() != size:
i = i.subsurface((0, 0) + size)
rv.append(i)
return rv
def scale(n):
if n is None:
return n
@@ -164,7 +234,13 @@ def load_scaling():
return rv
def surface_scale(full):
return Surface(old_transform_scale(full, v2p(full.get_size())), wh=full.get_size())
if scale_fast:
scaled = old_transform_scale(full, v2p(full.get_size()))
else:
scaled = real_smoothscale(full, v2p(full.get_size()))
return Surface(scaled, wh=full.get_size())
# Project a tuple from virtual to physical coordinates.
def v2p(n):
@@ -193,6 +269,8 @@ def load_scaling():
func = getattr(PygameSurface, name)
def rv(self, *args, **kwargs):
return func(self.surface, *args, **kwargs)
return rv
class Surface(object):
@@ -211,7 +289,10 @@ def load_scaling():
else:
w, h = what
self.width, self.height = w, h
w = int(w)
h = int(h)
self.width = w
self.height = h
w = int(w * factor)
h = int(h * factor)
@@ -223,16 +304,68 @@ def load_scaling():
sample = sample.surface
self.surface = PygameSurface((w, h), flags, sample)
self.virtx = 0
self.virty = 0
self.physx = 0
self.physy = 0
def transform_pos(self, (x, y)):
"""
Converts a virtual position into a physical one.
"""
x0 = x + self.virtx
y0 = y + self.virty
x0 *= factor
y0 *= factor
x0 = int(x0)
y0 = int(y0)
return (x0 - self.physx, y0 - self.physy)
def transform_rect(self, (x, y, w, h)):
"""
Converts a virtual rectangle into a physical one.
"""
x0 = x + self.virtx
y0 = y + self.virty
x1 = x0 + w
y1 = y0 + h
x0 *= factor
y0 *= factor
x1 *= factor
y1 *= factor
x0 = int(x0)
y0 = int(y0)
x1 = int(x1)
y1 = int(y1)
rv = (x0 - self.physx, y0 - self.physy, x1 - x0, y1 - y0)
return rv
def __repr__(self):
return "<scale.Surface %r %r>" % (self.get_size(), self.surface)
def blit(self, s, destpos, sourcerect=None):
if sourcerect is None:
self.surface.blit(s.surface, v2p(destpos))
self.surface.blit(
s.surface,
self.transform_pos(destpos))
else:
self.surface.blit(s.surface, v2p(destpos), v2p(sourcerect))
self.surface.blit(
s.surface,
self.transform_pos(destpos),
self.transform_rect(sourcerect))
def convert(self, *args):
if args:
@@ -254,7 +387,7 @@ def load_scaling():
return self.surface.get_alpha()
def get_at(self, pos):
x, y = v2p(pos)
x, y = self.transform_pos(pos)
w, h = self.surface.get_size()
return self.surface.get_at((min(x, w - 1), min(y, h - 1)))
@@ -285,9 +418,6 @@ def load_scaling():
def get_bitsize(self):
return self.surface.get_bitsize()
def get_clip(self):
return p2v(self.surface.get_clip())
def get_colorkey(self):
return self.surface.get_colorkey()
@@ -303,13 +433,23 @@ def load_scaling():
def set_alpha(self, alpha, flags):
self.surface.set_alpha(alpha, flags)
def set_clip(self, rect):
self.surface.set_clip(v2pplus(rect))
pass
def subsurface(self, rect):
return Surface(self.surface.subsurface(v2p(rect)), wh=rect[2:])
prect = self.transform_rect(rect)
surf = self.surface.subsurface(prect)
rv = Surface(surf, wh=rect[2:])
vx, vy, vw, vh = rect
px, py, pw, ph = prect
rv.virtx = vx + self.virtx
rv.virty = vy + self.virty
rv.physx = px + self.physx
rv.physy = py + self.physy
return rv
def mustlock(self):
return False
@@ -371,15 +511,19 @@ def load_scaling():
pygame.display.get_surface = get_surface
old_image_load = pygame.image.load
old_transform_scale = pygame.transform.scale
def image_load(*args, **kwargs):
full = old_image_load(*args, **kwargs)
full = full.convert_alpha()
return surface_scale(full)
pygame.image.load = image_load
old_transform_scale = pygame.transform.scale
def transform_scale(surf, size):
rv = old_transform_scale(surf.surface, v2p(size))
@@ -389,6 +533,21 @@ def load_scaling():
pygame.transform.scale = transform_scale
old_transform_smoothscale = pygame.transform.smoothscale
def transform_smoothscale(surf, size, dest=None):
if dest is not None:
rv = old_transform_smoothscale(surf.surface, v2p(size), dest.surface)
else:
rv = old_transform_smoothscale(surf.surface, v2p(size))
rv = Surface(rv, wh=size)
return rv
pygame.transform.smoothscale = transform_smoothscale
old_transform_flip = pygame.transform.flip
def transform_flip(surf, xbool, ybool):
@@ -413,7 +572,7 @@ def load_scaling():
# Ignoring scale2x and chop. The former due to a pending api change,
# the latter due to general uselessness.
PygameFont = font_module.Font
class Font(object):
@@ -457,13 +616,9 @@ def load_scaling():
def get_descent(self):
return int(self.font.get_descent() / factor)
# Ignored:
#
# set_at
# Anything involving palettes.
# Anything involving the parents of subsurfaces.
# get_pitch, get_shifts, get_losses
def set_expand(self, value):
self.font.set_expand(value * factor)
font_module.Font = Font
old_image_save = pygame.image.save
@@ -517,7 +672,8 @@ def load_scaling():
old_map = _renpy.map
def map(pysrc, pydst, r, g, b, a):
old_map(pysrc.surface, pydst.surface, r, g, b, a)
pysrc, pydst = same_size(pysrc.surface, pydst.surface)
old_map(pysrc, pydst, r, g, b, a)
_renpy.map = map
@@ -525,7 +681,8 @@ def load_scaling():
old_linmap = _renpy.linmap
def linmap(pysrc, pydst, r, g, b, a):
old_linmap(pysrc.surface, pydst.surface, r, g, b, a)
pysrc, pydst = same_size(pysrc.surface, pydst.surface)
old_linmap(pysrc, pydst, r, g, b, a)
_renpy.linmap = linmap
@@ -567,8 +724,8 @@ def load_scaling():
def alpha_munge(pysrc, pydst, srcchan, dstchan, amap):
old_alpha_munge(pysrc.surface, pydst.surface,
srcchan, dstchan, amap)
pysrc, pydst = same_size(pysrc.surface, pydst.surface)
old_alpha_munge(pysrc, pydst, srcchan, dstchan, amap)
_renpy.alpha_munge = alpha_munge
@@ -596,18 +753,27 @@ def load_scaling():
old_blend = _renpy.blend
def blend(pysrca, pysrcb, pydst, alpha):
old_blend(pysrca.surface, pysrcb.surface, pydst.surface, alpha)
pysrca, pysrcb, pydst = same_size(pysrca.surface, pysrcb.surface, pydst.surface)
old_blend(pysrca, pysrcb, pydst, alpha)
_renpy.blend = blend
old_imageblend = _renpy.imageblend
def imageblend(pysrca, pysrcb, pydst, pyimg, aoff, amap):
old_imageblend(pysrca.surface, pysrcb.surface, pydst.surface,
pyimg.surface, aoff, amap)
pysrca, pysrcb, pydst, pyimg = same_size(pysrca.surface, pysrcb.surface, pydst.surface, pyimg.surface)
old_imageblend(pysrca, pysrcb, pydst, pyimg, aoff, amap)
_renpy.imageblend = imageblend
old_colormatrix = _renpy.colormatrix
def colormatrix(src, dst, *args):
src, dst = same_size(src.surface, dst.surface)
old_colormatrix(src, dst, *args)
_renpy.colormatrix = colormatrix
def draw_scale(o):
if isinstance(o, int):
@@ -643,7 +809,19 @@ def load_scaling():
pygame.draw.aaline = draw_wrap(pygame.draw.aaline)
pygame.draw.aalines = draw_wrap(pygame.draw.aalines)
# Smoothscale:
def smoothscale(surf, size, dest=None):
if dest is not None:
dest = dest.surface
rv = real_smoothscale(surf.surface, v2p(size), dest)
if rv is None:
return rv
else:
return Surface(rv, wh=size)
# Now, put everything from this function's namespace into the
# module namespace.
+4
View File
@@ -813,6 +813,7 @@ class Text(renpy.display.core.Displayable):
return True
else:
renpy.game.interface.timeout((self.slow_done_time + self.pause_length) - st)
if self.slow and self.style.slow_abortable and renpy.display.behavior.map_event(ev, "dismiss"):
self.slow = False
raise renpy.display.core.IgnoreEvent()
@@ -1301,6 +1302,9 @@ class Text(renpy.display.core.Displayable):
Called to call slow_done, and also to update slow_done_time.
"""
if not self.slow:
return
self.slow = False
if self.slow_done:
+3 -3
View File
@@ -286,7 +286,6 @@ class Pixellate(Transition):
rdr = render(visible, width, height, st, at)
# No alpha support.
surf = rdr.pygame_surface(False)
if surf.get_size() != self.surface_size:
@@ -348,7 +347,7 @@ class Dissolve(Transition):
bottom = render(self.old_widget, width, height, st, at)
top = render(self.new_widget, width, height, st, at)
bottom_surface = bottom.pygame_surface(self.alpha)
top_surface = top.pygame_surface(self.alpha)
@@ -356,7 +355,7 @@ class Dissolve(Transition):
height = min(top.height, bottom.height)
def draw(dest, x, y):
dw, dh = dest.get_size()
w = min(dw, width + x)
@@ -371,6 +370,7 @@ class Dissolve(Transition):
dest.subsurface((0, 0, w, h)),
alpha)
if self.alpha:
rv = renpy.display.render.Render(width, height)
+10 -5
View File
@@ -58,7 +58,7 @@ def roll_forward_info():
def in_rollback():
return renpy.game.log.in_rollback()
def checkpoint(data=None):
def checkpoint(data=None, keep_rollback=False):
"""
This creates a checkpoint that the user can rollback to. The
checkpoint is placed at the statement after the last statement
@@ -67,7 +67,8 @@ def checkpoint(data=None):
statement.
"""
renpy.game.log.checkpoint(data)
if renpy.store._rollback:
renpy.game.log.checkpoint(data, keep_rollback=keep_rollback)
def block_rollback():
"""
@@ -589,7 +590,7 @@ def pause(delay=None, music=None, with_none=None, hard=False):
roll_forward = None
rv = renpy.ui.interact(mouse='pause', type='pause', roll_forward=roll_forward)
renpy.exports.checkpoint(rv)
renpy.exports.checkpoint(rv, keep_rollback=True)
if with_none is None:
@@ -684,10 +685,14 @@ def rollback():
Rolls the state of the game back to the last checkpoint.
"""
if not renpy.store._rollback:
return
if not renpy.game.context().rollback:
return
if renpy.config.rollback_enabled:
renpy.config.skipping = None
renpy.game.log.complete()
renpy.game.log.rollback(1)
@@ -734,7 +739,7 @@ def take_screenshot(scale=None):
renpy.game.interface.take_screenshot(scale)
def full_restart(transition=False, label="_invoke_main_menu"):
def full_restart(transition=False, label="_invoke_main_menu", target="_main_menu"):
"""
This causes a full restart of Ren'Py.
"""
@@ -742,7 +747,7 @@ def full_restart(transition=False, label="_invoke_main_menu"):
if transition is False:
transition = renpy.config.end_game_transition
raise renpy.game.FullRestartException((transition, label))
raise renpy.game.FullRestartException((transition, label, target))
def utter_restart():
"""
+1 -1
View File
@@ -76,7 +76,7 @@ seen_session = { }
# The set of statements we've ever seen.
seen_ever = { }
# True if we're in the first interaction after a rollback.
# True if we're in the first interaction after a rollback or rollforward.
after_rollback = False
# Code that's run after the init code.
+9 -3
View File
@@ -108,15 +108,21 @@ def image_exists(name, expression, tag):
check_file_cache = { }
def check_file(what, fn):
if fn in check_file_cache:
return True
check_file_cache[fn] = True
present = check_file_cache.get(fn, None)
if present is True:
return
if present is False:
report("%s uses file '%s', which is not loadable.", what.capitalize(), fn)
return
if not renpy.loader.loadable(fn):
report("%s uses file '%s', which is not loadable.", what.capitalize(), fn)
check_file_cache[fn] = False
return
check_file_cache[fn] = True
try:
renpy.loader.transfn(fn)
except:
+1 -1
View File
@@ -307,7 +307,7 @@ def main():
try:
run(restart)
finally:
restart = (renpy.config.end_game_transition, "_invoke_main_menu")
restart = (renpy.config.end_game_transition, "_invoke_main_menu", "_main_menu")
save_persistent()
except game.QuitException, e:
+14 -5
View File
@@ -601,13 +601,19 @@ class RollbackLog(renpy.object.Object):
self.ever_been_changed = { }
self.rollback_limit = 0
self.forward = [ ]
# Did we just do a roll forward?
self.rolled_forward = False
# Reset the RNG on the creation of a new game.
rng.reset()
def after_setstate(self):
self.mutated = { }
self.rolled_forward = False
def begin(self):
"""
Called before a node begins executing, to indicate that the
@@ -639,6 +645,8 @@ class RollbackLog(renpy.object.Object):
# save code.
global mutate_flag
mutate_flag = True
self.rolled_forward = False
def complete(self):
"""
@@ -738,7 +746,7 @@ class RollbackLog(renpy.object.Object):
return None
def checkpoint(self, data=None):
def checkpoint(self, data=None, keep_rollback=False):
"""
Called to indicate that this is a checkpoint, which means
that the user may want to rollback to just before this
@@ -760,7 +768,10 @@ class RollbackLog(renpy.object.Object):
# Otherwise, clear the forward stack.
fwd_name, fwd_data = self.forward[0]
if (self.current.context.current == fwd_name and data == fwd_data):
if (self.current.context.current == fwd_name
and data == fwd_data
and (keep_rollback or self.rolled_forward)
):
self.forward.pop(0)
else:
self.forward = [ ]
@@ -768,8 +779,6 @@ class RollbackLog(renpy.object.Object):
# Log the data in case we roll back again.
self.current.forward = data
def block(self):
"""
Called to indicate that the user should not be able to rollback
+7 -7
View File
@@ -44,14 +44,15 @@ _window = False
# The window subtitle.
_window_subtitle = ''
# Should rollback be allowed?
_rollback = True
# config.
_config = renpy.config
class _Config(object):
def __init__(self, name):
vars(self)["_name"] = name
def register(self, name, default, cat=None, help=None):
setattr(self, name, default)
_config.help.append((cat, name, help))
@@ -60,7 +61,7 @@ class _Config(object):
cvars = vars(_config)
if name not in cvars:
raise Exception('%s.%s is not a known configuration variable.' % (self._name, name))
raise Exception('config.%s is not a known configuration variable.' % (name))
return cvars[name]
@@ -68,7 +69,7 @@ class _Config(object):
cvars = vars(_config)
if name not in cvars and renpy.config.locked:
raise Exception('%s.%s is not a known configuration variable.' % (self._name, name))
raise Exception('config.%s is not a known configuration variable.' % (name))
if name == "script_version":
renpy.store._set_script_version(value)
@@ -81,8 +82,7 @@ class _Config(object):
else:
delattr(renpy.config, name)
config = _Config("config")
library = _Config("library")
config = _Config()
_list = list
_dict = dict
+1 -1
View File
@@ -190,7 +190,7 @@ label marry:
s "I know. So, will you marry me?"
m "Ummm, of course I will. I've actually been meaning to ask you, but since you brought it up..."
s "I know, but you are so indecisive, that I thought I'd take the initiative. "
m "I guess... It's all all about asking the right question... at the right time."
m "I guess... It's all about asking the right question... at the right time."
show sylvie2 giggle