Compare commits

...

42 Commits

Author SHA1 Message Date
Tom Rothamel c5ce6c0f4b Bump version. 2009-12-17 09:36:36 -05:00
Tom Rothamel 40f8644ac2 Export time from renpy.exports. 2009-12-17 09:35:34 -05:00
Tom Rothamel d45cf0d79a Bump version. 2009-12-16 19:17:18 -05:00
Tom Rothamel 68937a71b9 Add developer menu to string scanner. 2009-12-14 22:06:00 -05:00
Tom Rothamel db435f5a0a Bump version. 2009-12-14 19:06:43 -05:00
Tom Rothamel 40c469fa23 Add ctc_timedpause. 2009-12-14 19:04:10 -05:00
Tom Rothamel fe7c7e2299 Decode the tutorial properly, so international characters can be used. 2009-12-14 16:51:43 -05:00
Tom Rothamel 2f9d9f9dee Bump version numbers. 2009-12-13 11:26:44 -05:00
Tom Rothamel 293508969a The layout.imagemap_main_menu and layout.imagemap_load_save functions
now allow one to define variant screens. This allows one to select an 
imagemap main menu screen to use, or to define different screens for
loading and saving.
2009-12-13 11:05:58 -05:00
Tom Rothamel 5908546828 Ensure we get an alpha surface even if pygame hasn't been initialized.
Take the position from the transform, not something enclosing the transform.

Fix the archiver to not error out on import.
2009-12-12 23:16:59 -05:00
Tom Rothamel b80f6a1e8e Fix a bug with the last checkin. 2009-12-12 15:45:12 -05:00
Tom Rothamel d3434400cd The layout.imagemap_load_save function can now take dictionaries for
each of its arguments. This allows separate values of the arguments to
be specified for load and save.
2009-12-12 15:28:16 -05:00
Tom Rothamel 11a20e21d1 Update the font to the latest version. 2009-12-12 03:11:18 -05:00
Tom Rothamel 0de0aa292a ATL now has a "function" statement, which allows an ATL transform to
use the same functions that are supplied to Transform.
2009-12-12 01:28:41 -05:00
Tom Rothamel aa0d357bdc The transform state transfer now looks inside ImageReferences. This means
that it works when a transform is defined as part of an image, as well as
part of an at clause (or as an ATL block).

Parameterize ctc indicators.
2009-12-12 00:22:04 -05:00
Tom Rothamel ca16c24fc4 Make all of Ren'Py pyflakes-clean. 2009-12-11 01:38:28 -05:00
Tom Rothamel d32db0c9a3 Fix Pyflakes warnings. 2009-12-11 01:20:33 -05:00
Tom Rothamel 60b9f0522c Make shown_window an attribute of scene_lists. This tracks it better.
Change overlay semantics to match everything else.

Make core.py and exports.py pyflakes clean.
2009-12-11 00:39:17 -05:00
Tom Rothamel d3c58da216 Make core.py pyflakes-clean. 2009-12-10 11:31:46 -05:00
Tom Rothamel e81044465d Fix various bugs, incl lp:494820. 2009-12-10 01:01:59 -05:00
Tom Rothamel 75a0741c33 Scaling bug fixes. 2009-12-09 02:49:00 -05:00
Tom Rothamel a68f4af35d Vaguely working (not immediately crashing) rewrite of the scaling code. 2009-12-09 02:24:02 -05:00
Tom Rothamel 9e0932af5a Fix typo that prevented ui.at from working. 2009-12-07 09:58:04 -05:00
Tom Rothamel 112c0bce66 Only allow rollbacks to be committed in the top-level context. Fixes lp:493062.
Error handling improvements.

Allow ui.imagemap to take arbitrary displayables as the ground.
2009-12-06 15:30:36 -05:00
Tom Rothamel d640759ab8 Fixed a bug that prevented Ren'Py from interpolating image rotation
before image rotation was specified.
2009-12-05 17:05:14 -05:00
Tom Rothamel bb628bd9cd Make bilinear scaling precise.
Make im.Scale use the smooth scaling code. Fixes lp:488814.
2009-12-05 15:42:31 -05:00
Tom Rothamel ed3c0937d9 Check in cython-created files. 2009-12-05 13:32:26 -05:00
Tom Rothamel 48cf0cd50a Fixed a bug that caused Ren'Py to fail when scaling was enabled. 2009-12-05 03:09:56 -05:00
Tom Rothamel a39934d0c4 The image text tag can now take any textual image representation. So
something like {image=eileen happy} is legal, if odd.


Fixed a bug that could prevent files from being loaded if Ren'Py was
run from a path that contains non-ascii characters. (Even in directories
that were not part of the Ren'Py distribution.)
2009-12-05 00:38:30 -05:00
Tom Rothamel 2a9eaf9dea Fix a no-shutdown bug. 2009-12-05 00:15:07 -05:00
Tom Rothamel 0d07b4dcb6 Be sure blit lock is held. 2009-12-02 18:14:11 -05:00
Tom Rothamel 76fbce3304 Fix bug that could cause shift+R to fail when going back to a menu after a restart.
Fix bug that could prevent Ren'Py from exiting if image or auto-save threads felt like keeping us around.
2009-12-02 17:51:08 -05:00
Tom Rothamel 510eba1628 Hide deprecation warnings on Python 2.6. 2009-11-30 02:54:16 -05:00
Tom Rothamel c37fede2f1 Add precise mode for transform32.
Remove can_ tests from the module as obsolete.
2009-11-30 02:01:45 -05:00
Tom Rothamel 3ccb522e33 Replace all surface creation with calls to
renpy.display.pgrender.surface and other functions in that
module. This function creates a surface with a 1px border in
all directions. This will let us not have to worry about transform32 
overrunning the surface.
2009-11-29 16:01:42 -05:00
Tom Rothamel a067d0c830 Bump version to 6.10.0e 2009-11-16 23:20:12 -05:00
Tom Rothamel 2f82c7466d Adjust the types of ATL properties as necessary. 2009-11-16 02:22:37 -05:00
Tom Rothamel 9e9a6b7f8e Change the strategy used for cropping in Transform. The new one allows for floating pointy crop windows. 2009-11-16 02:04:41 -05:00
Tom Rothamel 9db36905c6 Fix bug that prevented ATL default parameters from working. 2009-11-15 19:29:17 -05:00
Tom Rothamel e5ae260c33 Add ATL warp construct. 2009-11-15 19:24:17 -05:00
Tom Rothamel 4e3a579eed ATL: fix bug with bare number as pause. 2009-11-15 15:44:49 -05:00
Tom Rothamel 4cd1e62978 Simplify module.py, now that we error out if the module isn't loadable.
Make it possible to build on a stock ubuntu.
2009-11-15 15:31:09 -05:00
68 changed files with 13267 additions and 1757 deletions
+2 -4
View File
@@ -5,10 +5,6 @@ renpy.app
**/*.rpyc
**/*.rpyb
**/*.rpymc
_renpy.c
nativemidi.c
sound.c
winmixer.c
jedit
lint.txt
renpy.code
@@ -60,3 +56,5 @@ close_bugs.py
.logplayer
scite-6.10.zip
scite-renpy-20090803.zip
module/cython.sh
old_demo
+55
View File
@@ -1,3 +1,58 @@
New in Ren'Py 6.10.1
--------------------
Images and other surfaces are now created with a 1px transparent border
around them. This change allows transform to work correctly with a 1:1
scale, where as previously Ren'Py would blur the image slightly, while
trying to ensure it never accessed a pixel outside of the original
image bounds.
ATL now has a "function" statement, which allows an ATL transform to
use the same functions that are supplied to Transform.
The layout.imagemap_main_menu and layout.imagemap_load_save functions
now allow one to define variant screens. This allows one to select an
imagemap main menu screen to use, or to define different screens for
loading and saving.
The overlay semantics were changed such that transitions apply to overlays
in the same way they apply to everything else. (So, for example, dissolves
will apply to overlays.)
The image text tag can now take any textual image representation. So
something like {image=eileen happy} is legal, if odd.
The following numbered bugs were fixed:
lp:366412 - Ren'Py could crash on shift+R at the main menu, under some circumstances.
lp:485631 - The transfer of state from a transfrom to a transform supplied as part of an image didn't work.
lp:487688 - non-ASCII characters didn't display in the window title bar.
lp:487701 - Ren'Py didn't work when in a directory containing non-ASCII characters.
lp:488814 - Scaling to the same size could blur an image.
lp:489212 - Interpolation didn't work when the starting value was None.
lp:493062 - One could roll back into an imagemap main menu.
lp:494779 - The window shown state wasn't being tracked correctly.
lp:494820 - Error handling in ATL hid too many error messages.
A major bug that caused Ren'Py to fail as scaling was enabled was fixed.
A number of minor bugs revealed by pyflakes were fixed.
New in Ren'Py 6.10.0
--------------------
+1
View File
@@ -40,6 +40,7 @@ if __name__ == "__main__":
files += glob.glob("launcher/*.rpy")
files += glob.glob("common/*.rpy")
files += glob.glob("common/*.rpym")
files += glob.glob("common/_layout/*.rpym")
files += glob.glob("common/_compat/*.rpym")
+13 -12
View File
@@ -288,13 +288,14 @@ init -1105 python hide:
@layout
def imagemap_main_menu(ground, selected, hotspots):
def imagemap_main_menu(ground, selected, hotspots, idle=None, variant=None):
renpy.load_module("_layout/imagemap_main_menu")
config.main_menu_ground = ground
config.main_menu_selected = selected
config.main_menu_hotspots = hotspots
config.main_menu_ground[variant] = ground
config.main_menu_selected[variant] = selected
config.main_menu_hotspots[variant] = hotspots
config.main_menu_idle[variant] = idle
@layout
def imagemap_navigation(ground, idle, hover, selected_idle, selected_hover,
hotspots):
@@ -334,16 +335,16 @@ init -1105 python hide:
@layout
def imagemap_load_save(ground, idle, hover, selected_idle, selected_hover,
hotspots):
hotspots, variant=None):
renpy.load_module("_layout/imagemap_load_save")
config.load_save_ground = ground
config.load_save_idle = idle
config.load_save_hover = hover
config.load_save_selected_idle = selected_idle
config.load_save_selected_hover = selected_hover
config.load_save_hotspots = hotspots
config.load_save_ground[variant] = ground
config.load_save_idle[variant] = idle
config.load_save_hover[variant] = hover
config.load_save_selected_idle[variant] = selected_idle
config.load_save_selected_hover[variant] = selected_hover
config.load_save_hotspots[variant] = hotspots
layout.ARE_YOU_SURE = u"Are you sure?"
+15 -9
View File
@@ -702,18 +702,24 @@ label _start:
# Clean out any residual scene from the splashscreen.
scene black
if _restart is None:
$ renpy.transition(config.end_splash_transition)
else:
$ renpy.transition(_restart[0])
jump expression _restart[1]
# This has to be python, to deal with a case where _restart may
# change across a shift-reload.
python:
if _restart is None:
renpy.transition(config.end_splash_transition)
else:
renpy.transition(_restart[0])
renpy.jump(_restart[1])
label _invoke_main_menu:
if _restart:
$ renpy.call_in_new_context(_restart[2])
else:
$ renpy.call_in_new_context("_main_menu")
# Again, this has to be python.
python:
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.
Binary file not shown.
+3 -2
View File
@@ -1,4 +1,5 @@
Fonts are (c) Bitstream (see below). DejaVu changes are in public domain. Glyphs imported from Arev fonts are (c) Tavmjung Bah (see below)
Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below)
Bitstream Vera Fonts Copyright
------------------------------
@@ -95,4 +96,4 @@ dealings in this Font Software without prior written authorization
from Tavmjong Bah. For further information, contact: tavmjong @ free
. fr.
$Id: LICENSE 778 2006-04-20 18:14:24Z moyogo $
$Id: LICENSE 2133 2007-11-28 02:46:28Z lechimp $
+47 -22
View File
@@ -2,45 +2,65 @@ init python:
class _ImageMapper(object):
def __init__(self, screen, ground, idle, hover, selected_idle, selected_hover, hotspots):
def __init__(self, screen, ground, idle, hover, selected_idle, selected_hover, hotspots, navigation=True, variant=None):
self.idle = idle
self.hover = hover
self.selected_idle = selected_idle
self.selected_hover = selected_hover
# If the argument is a dict, look up the screen in that dict, and
# return the result. Otherwise, just return the result.
def maybe_variant(a):
if isinstance(a, dict):
if variant in a:
return a[variant]
else:
return a[None]
return a
ground = maybe_variant(ground)
self.idle = maybe_variant(idle) or ground
self.hover = maybe_variant(hover) or self.idle
self.selected_idle = maybe_variant(selected_idle) or self.idle
self.selected_hover = maybe_variant(selected_hover) or self.hover
self.hotspots = { }
for (x1, y1, x2, y2, name) in hotspots:
for (x1, y1, x2, y2, name) in maybe_variant(hotspots):
self.hotspots[name] = (x1, y1, x2, y2)
# Display the layout navigation only if there are no
# game menu buttons defined.
for i in config.game_menu:
if i[1] in self.hotspots:
break
else:
layout.navigation(screen)
self.remaining_hotspots = set(self.hotspots.keys())
if navigation:
# Display the layout navigation only if there are no
# game menu buttons defined.
for i in config.game_menu:
if i[1] in self.hotspots:
break
else:
layout.navigation(screen)
ui.fixed(style='imagemap')
ui.image(ground)
if navigation:
# Display any navigation buttons that exist.
for e in config.game_menu:
screen_ = e[0]
name = e[1]
act = e[2]
enable = e[3]
# Display any navigation buttons that exist.
for e in config.game_menu:
screen_ = e[0]
name = e[1]
act = e[2]
enable = e[3]
if not eval(enable):
continue
if not eval(enable):
continue
self.button(name, act, screen == screen_)
self.button(name, act, screen == screen_)
def button(self, name, clicked, selected, keymap={}):
if name not in self.hotspots:
return None
self.remaining_hotspots.discard(name)
x1, y1, x2, y2 = self.hotspots[name]
if clicked is None:
@@ -74,6 +94,8 @@ init python:
if name not in self.hotspots:
return
self.remaining_hotspots.discard(name)
x1, y1, x2, y2 = self.hotspots[name]
ui.bar(
@@ -94,6 +116,9 @@ init python:
thumb=None,
thumb_shadow=None,
thumb_offset=0)
def nothing(self, name):
self.remaining_hotspots.discard(name)
def close(self):
ui.close()
+15 -9
View File
@@ -4,19 +4,19 @@ init python:
renpy.load_module("_layout/imagemap_common")
# The ground image.
config.load_save_ground = None
config.load_save_ground = { }
# The idle image.
config.load_save_idle = None
config.load_save_idle = { }
# The hover image.
config.load_save_hover = None
config.load_save_hover = { }
# The selected idle image.
config.load_save_selected_idle = None
config.load_save_selected_idle = { }
# The selected hover image.
config.load_save_selected_hover = None
config.load_save_selected_hover = { }
# The hotspots. Each hotspot is defined by a tuple giving:
# - The x-coordinate of the left side.
@@ -24,7 +24,7 @@ init python:
# - The x-coordinate of the right side.
# - The y-coordinate of the bottoms side.
# - The name of the button or slider this is equivalent to.
config.load_save_hotspots = None
config.load_save_hotspots = { }
# Define styles
style.file_picker_text = Style(style.large_button_text, help="text inside a file picker entry")
@@ -159,8 +159,13 @@ init python:
hotspots = set()
for (x1, y1, x2, y2, name) in config.load_save_hotspots:
hotspots.add(name)
if isinstance(config.load_save_hotspots, dict):
for d in config.load_save_hotspots.values():
for (x1, y1, x2, y2, name) in d:
hotspots.add(name)
else:
for (x1, y1, x2, y2, name) in config.load_save_hotspots:
hotspots.add(name)
__scratch.has_autosave = ("page_auto" in hotspots)
__scratch.has_quicksave = ("page_quick" in hotspots)
@@ -249,7 +254,8 @@ init python:
config.load_save_hover,
config.load_save_selected_idle,
config.load_save_selected_hover,
config.load_save_hotspots)
config.load_save_hotspots,
variant=screen)
def tb(enabled, label, clicked, selected):
+41 -20
View File
@@ -1,13 +1,17 @@
init python:
layout.provides('main_menu')
renpy.load_module("_layout/imagemap_common")
# The ground image.
config.main_menu_ground = None
config.main_menu_ground = { }
# The selected image.
config.main_menu_selected = None
# The selected/hover image.
config.main_menu_selected = { }
# The idle image.
config.main_menu_idle = { }
# The hotspots. Each hotspot is defined by a tuple giving:
# - The x-coordinate of the left side.
# - The y-coordinate of the top side.
@@ -16,7 +20,10 @@ init python:
# - Either the (untranslated) name of the main menu button this hotspot
# is equivalent to, or, a label in the program to jump to when this
# hotspot is clicked.
config.main_menu_hotspots = [ ]
config.main_menu_hotspots = { }
# This can be set from user code to define the main menu variant to use.
_main_menu_variant = None
label main_menu_screen:
@@ -28,28 +35,42 @@ label main_menu_screen:
# Show the background.
ui.window(style='mm_root')
ui.null()
rv = renpy.imagemap(
ime = _ImageMapper(
None,
config.main_menu_ground,
config.main_menu_idle,
config.main_menu_selected,
config.main_menu_idle,
config.main_menu_selected,
config.main_menu_hotspots,
mouse="mainmenu")
for e in config.main_menu:
name = e[0]
act = e[1]
enable = e[2]
navigation=False,
variant=_main_menu_variant)
if name == rv:
for e in config.main_menu:
if len(e) == 4:
name, act, enabled, shown = e
else:
name, act, enabled = e
shown = "True"
if not eval(shown):
ime.nothing(name)
if isinstance(act, basestring):
act = ui.jumpsoutofcontext(act)
act()
if not eval(enabled):
act = None
break
else:
ui.jumpsoutofcontext(rv)()
if isinstance(act, basestring):
act = ui.jumpsoutofcontext(act)
ime.button(name, act, False)
for i in list(ime.remaining_hotspots):
ime.button(i, ui.jumpsoutofcontext(i), None)
ime.close()
ui.interact(mouse='mainmenu')
jump main_menu_screen
+1
View File
@@ -232,6 +232,7 @@ def main():
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?"
print "Did you run with a RENPY_SCALE_FACTOR?"
if __name__ == "__main__":
main()
+1 -1
View File
@@ -159,7 +159,7 @@ init python:
zi = zipfile.ZipInfo(filename + an)
s = os.stat(fn)
zi.date_time = time.gmtime(s.st_mtime)[:6]
zi.date_time = time.gmtime(s.st_mtime)[:6]
zi.compress_type = zipfile.ZIP_DEFLATED
zi.create_system = 3
+1 -1
View File
@@ -1,3 +1,3 @@
init -999:
$ config.script_version = (6, 10, 0)
$ config.script_version = (6, 10, 1)
+9
View File
@@ -64,6 +64,15 @@ init python:
u"Joystick...",
u"Joystick Configuration",
u"Voice Volume",
u"Developer Menu",
u"Return to the developer menu",
u"Reload Game (Shift+R)",
u"Variable Viewer",
u"Theme Test",
u"Style Hierarchy",
u"FPS Meter",
u"Image Location Picker",
u"Done",
u"Auto",
u"Quick",
u"The patterns did not match any files, so no archive was created.",
+5742
View File
File diff suppressed because it is too large Load Diff
+9 -7
View File
@@ -62,7 +62,8 @@ cdef extern from "renpy.h":
void scale32_core(object, object,
float, float, float, float,
float, float, float, float)
float, float, float, float,
int)
void scale24_core(object, object,
float, float, float, float,
@@ -70,7 +71,7 @@ cdef extern from "renpy.h":
void transform32_core(object, object,
float, float, float, float, float, float,
int, float)
int, float, int)
void blend32_core(object, object, object, int)
@@ -95,7 +96,7 @@ import pygame
PygameSurface = pygame.Surface
def version():
return (6, 10, 0)
return (6, 10, 1)
def save_png(surf, file, compress=-1):
@@ -283,7 +284,8 @@ def alpha_munge(pysrc, pydst, srcchan, dstchan, amap):
def bilinear(pysrc, pydst,
source_xoff=0.0, source_yoff=0.0, source_width=None, source_height=None,
dest_xoff=0.0, dest_yoff=0.0, dest_width=None, dest_height=None):
dest_xoff=0.0, dest_yoff=0.0, dest_width=None, dest_height=None,
precise=0):
if not isinstance(pysrc, PygameSurface):
raise Exception("bilinear requires a pygame Surface as its first argument.")
@@ -309,7 +311,7 @@ def bilinear(pysrc, pydst,
if pysrc.get_bitsize() == 32:
scale32_core(pysrc, pydst,
source_xoff, source_yoff, source_width, source_height,
dest_xoff, dest_yoff, dest_width, dest_height)
dest_xoff, dest_yoff, dest_width, dest_height, precise)
else:
scale24_core(pysrc, pydst,
@@ -331,7 +333,7 @@ def check(surf):
def transform(pysrc, pydst,
corner_x, corner_y,
xdx, ydx, xdy, ydy, a=1.0):
xdx, ydx, xdy, ydy, a=1.0, precise=0):
check(pysrc)
check(pydst)
@@ -343,7 +345,7 @@ def transform(pysrc, pydst,
corner_x, corner_y,
xdx, ydx,
xdy, ydy,
pysrc.get_shifts()[3], a)
pysrc.get_shifts()[3], a, precise)
# pydst.unlock()
# pysrc.unlock()
+418 -258
View File
File diff suppressed because it is too large Load Diff
+11 -11
View File
@@ -1,19 +1,19 @@
cdef extern from "fribidi/fribidi.h":
int FRIBIDI_PAR_LTR
int FRIBIDI_PAR_WLTR
int FRIBIDI_PAR_ON
int FRIBIDI_PAR_WRTL
int FRIBIDI_PAR_RTL
int FRIBIDI_TYPE_LTR
int FRIBIDI_TYPE_ON
int FRIBIDI_TYPE_RTL
int FRIBIDI_TYPE_WR
int FRIBIDI_TYPE_WL
cdef extern object renpybidi_log2vis(object, int *)
LTR = FRIBIDI_PAR_LTR
WLTR = FRIBIDI_PAR_WLTR
ON = FRIBIDI_PAR_ON
WRTL = FRIBIDI_PAR_WRTL
RTL = FRIBIDI_PAR_RTL
WLTR = FRIBIDI_TYPE_WL
LTR = FRIBIDI_TYPE_LTR
ON = FRIBIDI_TYPE_ON
RTL = FRIBIDI_TYPE_RTL
WRTL = FRIBIDI_TYPE_WR
def log2vis(s, int direction=FRIBIDI_PAR_ON):
def log2vis(s, int direction=FRIBIDI_TYPE_ON):
s = s.encode("utf8")
s = renpybidi_log2vis(s, &direction)
+93 -50
View File
@@ -773,7 +773,9 @@ void scale32_core(PyObject *pysrc, PyObject *pydst,
float source_xoff, float source_yoff,
float source_width, float source_height,
float dest_xoff, float dest_yoff,
float dest_width, float dest_height) {
float dest_width, float dest_height,
int precise
) {
SDL_Surface *src;
@@ -803,9 +805,25 @@ void scale32_core(PyObject *pysrc, PyObject *pydst,
srch = src->h;
dsth = dst->h;
xdelta = 255.0 * (source_width - 1) / dest_width;
ydelta = 255.0 * (source_height - 1) / dest_height;
if (precise) {
if (dest_width > 1) {
xdelta = 256.0 * (source_width - 1) / (dest_width - 1);
} else {
xdelta = 0;
}
if (dest_height > 1) {
ydelta = 256.0 * (source_height - 1) / (dest_height - 1);
} else {
ydelta = 0;
}
} else {
xdelta = 255.0 * (source_width - 1) / dest_width;
ydelta = 255.0 * (source_height - 1) / dest_height;
}
for (y = 0; y < dsth; y++) {
unsigned char *s0;
@@ -821,14 +839,14 @@ void scale32_core(PyObject *pysrc, PyObject *pydst,
d = dstpixels + dstpitch * y;
dend = d + 4 * dstw; // bpp
sline = source_yoff * 255 + (y + dest_yoff) * ydelta;
sline = source_yoff * 256 + (y + dest_yoff) * ydelta;
s1frac = (int) sline & 255;
s0frac = 256 - s1frac;
s0 = srcpixels + (sline >> 8) * srcpitch;
s1 = s0 + srcpitch;
scol = source_xoff * 255 + dest_xoff * xdelta;
scol = source_xoff * 256 + dest_xoff * xdelta;
while (d < dend) {
@@ -960,17 +978,22 @@ void scale24_core(PyObject *pysrc, PyObject *pydst,
}
#define I(a, b, mul) ((((((b - a) * mul)) >> 8) + a) & 0xff00ff)
/** This appears to limit the expansion, such that 1/x yields a max
expansion of lg x */
#define EPSILON (1.0 / 256.0)
/****************************************************************************/
/* A similar concept to rotozoom, but implemented differently, so we
can limit the target area. */
int transform32_std(PyObject *pysrc, PyObject *pydst,
float corner_x, float corner_y,
float xdx, float ydx,
float xdy, float ydy,
int ashift,
float a) {
float corner_x, float corner_y,
float xdx, float ydx,
float xdy, float ydy,
int ashift,
float a,
int precise
) {
SDL_Surface *src;
SDL_Surface *dst;
@@ -982,7 +1005,7 @@ int transform32_std(PyObject *pysrc, PyObject *pydst,
// The x and y source pixel coordinates, times 65536. And their
// delta-per-dest-x-pixel.
int sxi, syi, dsxi, dsyi;
int sxi = 0, syi = 0, dsxi = 0, dsyi = 0;
unsigned char *srcpixels;
unsigned char *dstpixels;
@@ -1005,23 +1028,31 @@ int transform32_std(PyObject *pysrc, PyObject *pydst,
unsigned int amul = (unsigned int) (a * 256);
// Compute the maximum x and y coordinates.
double maxsx = srcw - 1 - EPSILON;
double maxsy = srch - 1 - EPSILON;
// If a delta is too even, subtract epsilon (towards 0) from it.
if (xdx && fabs(fmodf(1.0 / xdx, 1)) < EPSILON) {
xdx -= (xdx / fabs(xdx)) * EPSILON;
}
if (xdy && fabs(fmodf(1.0 / xdy, 1)) < EPSILON) {
xdy -= (xdy / fabs(xdy)) * EPSILON;
}
if (ydx && fabs(fmodf(1.0 / ydx, 1)) < EPSILON) {
ydx -= (ydx / fabs(ydx)) * EPSILON;
}
if (ydy && fabs(fmodf(1.0 / ydy, 1)) < EPSILON) {
ydy -= (ydy / fabs(ydy)) * EPSILON;
double maxsx = srcw - 1;
double maxsy = srch - 1;
// Deal with pre-6.10.1 versions of Ren'Py, which didn't give us
// that 1px border that allows us to be precise.
if (! precise) {
maxsx -= EPSILON;
maxsy -= EPSILON;
// If a delta is too even, subtract epsilon (towards 0) from it.
if (xdx && fabs(fmodf(1.0 / xdx, 1)) < EPSILON) {
xdx -= (xdx / fabs(xdx)) * EPSILON;
}
if (xdy && fabs(fmodf(1.0 / xdy, 1)) < EPSILON) {
xdy -= (xdy / fabs(xdy)) * EPSILON;
}
if (ydx && fabs(fmodf(1.0 / ydx, 1)) < EPSILON) {
ydx -= (ydx / fabs(ydx)) * EPSILON;
}
if (ydy && fabs(fmodf(1.0 / ydy, 1)) < EPSILON) {
ydy -= (ydy / fabs(ydy)) * EPSILON;
}
}
// Loop through every line.
for (y = 0; y < dsth; y++) {
@@ -1155,11 +1186,13 @@ int transform32_std(PyObject *pysrc, PyObject *pydst,
/* A similar concept to rotozoom, but implemented differently, so we
can limit the target area. */
int transform32_mmx(PyObject *pysrc, PyObject *pydst,
float corner_x, float corner_y,
float xdx, float ydx,
float xdy, float ydy,
int ashift,
float a) {
float corner_x, float corner_y,
float xdx, float ydx,
float xdy, float ydy,
int ashift,
float a,
int precise
) {
SDL_Surface *src;
SDL_Surface *dst;
@@ -1171,7 +1204,7 @@ int transform32_mmx(PyObject *pysrc, PyObject *pydst,
// The x and y source pixel coordinates, times 65536. And their
// delta-per-dest-x-pixel.
int sxi, syi, dsxi, dsyi;
int sxi = 0, syi = 0, dsxi = 0, dsyi = 0;
unsigned char *srcpixels;
unsigned char *dstpixels;
@@ -1197,23 +1230,31 @@ int transform32_mmx(PyObject *pysrc, PyObject *pydst,
unsigned int amul = (unsigned int) (a * 256);
// Compute the maximum x and y coordinates.
double maxsx = srcw - 1 - EPSILON;
double maxsy = srch - 1 - EPSILON;
// If a delta is too even, subtract epsilon (towards 0) from it.
if (xdx && fabs(fmodf(1.0 / xdx, 1)) < EPSILON) {
xdx -= (xdx / fabs(xdx)) * EPSILON;
}
if (xdy && fabs(fmodf(1.0 / xdy, 1)) < EPSILON) {
xdy -= (xdy / fabs(xdy)) * EPSILON;
}
if (ydx && fabs(fmodf(1.0 / ydx, 1)) < EPSILON) {
ydx -= (ydx / fabs(ydx)) * EPSILON;
}
if (ydy && fabs(fmodf(1.0 / ydy, 1)) < EPSILON) {
ydy -= (ydy / fabs(ydy)) * EPSILON;
double maxsx = srcw - 1;
double maxsy = srch - 1;
// Deal with pre-6.10.1 versions of Ren'Py, which didn't give us
// that 1px border that allows us to be precise.
if (! precise) {
maxsx -= EPSILON;
maxsy -= EPSILON;
// If a delta is too even, subtract epsilon (towards 0) from it.
if (xdx && fabs(fmodf(1.0 / xdx, 1)) < EPSILON) {
xdx -= (xdx / fabs(xdx)) * EPSILON;
}
if (xdy && fabs(fmodf(1.0 / xdy, 1)) < EPSILON) {
xdy -= (xdy / fabs(xdy)) * EPSILON;
}
if (ydx && fabs(fmodf(1.0 / ydx, 1)) < EPSILON) {
ydx -= (ydx / fabs(ydx)) * EPSILON;
}
if (ydy && fabs(fmodf(1.0 / ydy, 1)) < EPSILON) {
ydy -= (ydy / fabs(ydy)) * EPSILON;
}
}
// Loop through every line.
for (y = 0; y < dsth; y++) {
@@ -1394,7 +1435,9 @@ void transform32_core(PyObject *pysrc, PyObject *pydst,
float xdx, float ydx,
float xdy, float ydy,
int ashift,
float a) {
float a,
int precise
) {
#ifdef GCC_MMX
static int checked_mmx = 0;
@@ -1407,14 +1450,14 @@ void transform32_core(PyObject *pysrc, PyObject *pydst,
if (has_mmx) {
transform32_mmx(pysrc, pydst, corner_x, corner_y,
xdx, ydx, xdy, ydy, ashift, a);
xdx, ydx, xdy, ydy, ashift, a, precise);
return;
}
#endif
transform32_std(pysrc, pydst, corner_x, corner_y,
xdx, ydx, xdy, ydy, ashift, a);
xdx, ydx, xdy, ydy, ashift, a, precise);
}
+3 -2
View File
@@ -75,7 +75,8 @@ void alphamunge_core(PyObject *pysrc,
void scale32_core(PyObject *pysrc,
PyObject *pydst,
float, float, float, float,
float, float, float, float);
float, float, float, float,
int);
void scale24_core(PyObject *pysrc,
PyObject *pydst,
@@ -87,7 +88,7 @@ void transform32_core(PyObject *pysrc,
float, float,
float, float,
float, float,
int, float);
int, float, int);
void blend32_core(PyObject *pysrca,
PyObject *pysrcb,
-2
View File
@@ -13,8 +13,6 @@ PyObject *renpybidi_log2vis(PyObject *s, int *direction) {
FriBidiChar *dstuni;
char *dst;
int i;
src = PyString_AsString(s);
if (src == NULL) {
+11 -6
View File
@@ -1,4 +1,3 @@
#!/usr/bin/env python
import distutils.core
import os
@@ -75,7 +74,7 @@ def add_include(prefix, file):
if dir not in include_dirs:
include_dirs.append(dir)
def add_library(name):
def add_library(name, optional=False):
"""
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.
@@ -96,8 +95,11 @@ def add_library(name):
if dir not in library_dirs:
library_dirs.append(dir)
return
return True
if optional:
return False
print "Couldn't find library %s." % name
print "The paths searched were:"
for i in checked:
@@ -119,17 +121,20 @@ add_library("libpng")
add_library("libavformat")
add_library("libavcodec")
add_library("libavutil")
has_swscale = add_library("libswscale", True)
add_library("libfreetype")
add_library("libfribidi")
add_library("libz")
extra_link_args = [ ]
sdl_libraries = [ 'SDL' ]
sound_libraries = [ "avformat", "avcodec", "avutil", "z" ]
png_libraries = [ 'png', "z" ]
sound_libraries = [ "avformat", "avcodec", "avutil", "z" ]
if has_swscale:
sound_libraries.insert(0, "swscale")
# The following turn on optional modules.
winmixer = None
linmixer = None
@@ -211,7 +216,7 @@ extensions.append(renpybidi)
distutils.core.setup(
name = "renpy_module",
version = "6.9.1",
version = "6.10.1",
ext_modules = extensions,
py_modules = py_modules,
package_dir = { '' : 'lib' },
+3453
View File
File diff suppressed because it is too large Load Diff
+1825
View File
File diff suppressed because it is too large Load Diff
+8 -4
View File
@@ -25,6 +25,7 @@ import os
import os.path
import sys
import platform
import warnings
# Functions to be customized by distributors. ################################
@@ -81,9 +82,9 @@ def path_to_renpy_base():
##############################################################################
# The version of the Mac Launcher and py4renpy that we use.
macos_version = (6, 10, 0)
linux_version = (6, 10, 0)
# The version of the Mac Launcher and py4renpy that we require.
macos_version = (6, 10, 1)
linux_version = (6, 10, 1)
if __name__ == "__main__":
@@ -91,7 +92,7 @@ if __name__ == "__main__":
# Check for mac compatibility.
if "mac_version" in globals():
mac_version(macos_version)
globals()["mac_version"](macos_version)
# Check py4renpy compatibility.
try:
@@ -116,6 +117,9 @@ if __name__ == "__main__":
if os.path.exists(renpy_base + "/renpy.zip"):
sys.path.append(renpy_base + "/renpy.zip")
# Ignore warnings that happen.
warnings.simplefilter("ignore", DeprecationWarning)
# Start Ren'Py proper.
try:
+14 -6
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.10.0d"
version = "Ren'Py 6.10.1d"
script_version = 5003000
savegame_suffix = "-LT1.save"
@@ -56,7 +56,8 @@ def import_all():
import renpy.display
import renpy.display.presplash
import renpy.display.iliad # Must be before scale.
import renpy.display.iliad # Must be before scale and pgrender.
import renpy.display.pgrender
import renpy.display.scale # Must be before module.
import renpy.display.module
import renpy.display.render # Most display stuff depends on this.
@@ -102,15 +103,22 @@ def import_all():
# This reloads all modules.
def reload_all():
# Shut down the cache thread.
display.im.cache.quit()
import renpy
# Shut down the cache thread.
renpy.display.im.cache.quit()
# Cleans out the RenpyImporter.
import sys
sys.meta_path.pop()
blacklist = [ "renpy", "renpy.bootstrap", "renpy.display", "renpy.display.iliad", "renpy.display.scale" ]
blacklist = [ "renpy",
"renpy.bootstrap",
"renpy.display",
"renpy.display.iliad",
"renpy.display.pgrender",
"renpy.display.scale" ]
for i in sys.modules.keys():
if i.startswith("renpy") and i not in blacklist:
+158 -99
View File
@@ -50,36 +50,53 @@ def pause(t):
else:
return 1.0
position = object()
# A dictionary giving property names and the corresponding default
# values.
PROPERTIES = set([
"pos",
"xpos",
"ypos",
"anchor",
"xanchor",
"yanchor",
"align",
"xalign",
"yalign",
"rotate",
"xzoom",
"yzoom",
"zoom",
"alpha",
"around",
"alignaround",
"angle",
"radius",
"crop",
"size",
"corner1",
"corner2",
"subpixel",
"delay",
])
PROPERTIES = {
"pos" : (position, position),
"xpos" : position,
"ypos" : position,
"anchor" : (position, position),
"xanchor" : position,
"yanchor" : position,
"xaround" : position,
"yaround" : position,
"xanchoraround" : float,
"yanchoraround" : float,
"align" : (float, float),
"xalign" : float,
"yalign" : float,
"rotate" : float,
"xzoom" : float,
"yzoom" : float,
"zoom" : float,
"alpha" : float,
"around" : (position, position),
"alignaround" : (float, float),
"angle" : float,
"radius" : float,
"crop" : (float, float, float, float),
"size" : (int, int),
"corner1" : (float, float),
"corner2" : (float, float),
"subpixel" : bool,
"delay" : float,
}
def interpolate(t, a, b):
def correct_type(v, b, ty):
"""
Corrects the type of v to match ty. b is used to inform the match.
"""
if ty is position:
return type(b)(v)
else:
return ty(v)
def interpolate(t, a, b, type):
"""
Linearly interpolate the arguments.
"""
@@ -89,18 +106,21 @@ def interpolate(t, a, b):
# Recurse into tuples.
if isinstance(b, tuple):
return tuple(interpolate(t, i, j) for i, j in zip(a, b))
return tuple(interpolate(t, i, j, ty) for i, j, ty in zip(a, b, type))
# Deal with strings.
elif isinstance(b, (str, unicode)):
# Deal with booleans, nones, etc.
elif b is None or isinstance(b, bool):
if t >= 1.0:
return a
else:
return b
else:
return a
# Interpolate everything else.
else:
return type(b)(a + t * (b - a))
if a is None:
a = 0
return correct_type(a + t * (b - a), b, type)
# Interpolate the value of a spline. This code is based on Aenakume's code,
# from 00splines.rpy.
@@ -133,7 +153,7 @@ def interpolate_spline(t, spline):
else:
raise Exception("ATL can't interpolate splines of length %d." % len(spline))
return type(spline[-1])(rv)
return correct_type(rv, spline[-1], position)
# This is the context used when compiling an ATL statement. It stores the
@@ -268,7 +288,7 @@ class ATLTransformBase(renpy.object.Object):
properties.
"""
if self.parameters.positional:
if self.parameters.positional and self.parameters.positional[0][1] is None:
raise Exception("Cannot compile ATL Transform, as it's missing positional parameter %s." % self.parameters.positional[0])
old_exception_info = renpy.game.exception_info
@@ -475,67 +495,54 @@ class Block(Statement):
if index >= len(self.statements):
return "next", target - start, None
try:
# Find the statement and try to run it.
stmt = self.statements[index]
action, arg, pause = stmt.execute(trans, target - start, child_state, event)
# Find the statement and try to run it.
stmt = self.statements[index]
action, arg, pause = stmt.execute(trans, target - start, child_state, event)
# On continue, persist our state.
if action == "continue":
if pause is None:
pause = max_pause
action, arg, pause = "continue", (index, start, loop_start, repeats, times, arg), min(max_pause, pause)
break
# On continue, persist our state.
if action == "continue":
if pause is None:
pause = max_pause
elif action == "event":
return action, arg, pause
# On next, advance to the next statement in the block.
elif action == "next":
index += 1
start = target - arg
child_state = None
action, arg, pause = "continue", (index, start, loop_start, repeats, times, arg), min(max_pause, pause)
break
# On repeat, either terminate the block, or go to
# the first statement.
elif action == "repeat":
count, arg = arg
loop_end = target - arg
duration = loop_end - loop_start
# Figure how many durations can occur between the
# start of the loop and now.
new_repeats = int((target - loop_start) / duration)
if duration <= 0:
raise Exception("ATL appears to be in an infinite loop.")
if count is not None:
if repeats + new_repeats >= count:
new_repeats = count - repeats
loop_start += new_repeats * duration
return "next", target - loop_start, None
repeats += new_repeats
loop_start = loop_start + new_repeats * duration
start = loop_start
index = 0
child_state = None
except:
# If an exception occurs when dealing with a statment,
# advance to the next statement.
if renpy.config.debug:
raise
elif action == "event":
return action, arg, pause
# On next, advance to the next statement in the block.
elif action == "next":
index += 1
start = target
start = target - arg
child_state = None
# On repeat, either terminate the block, or go to
# the first statement.
elif action == "repeat":
count, arg = arg
loop_end = target - arg
duration = loop_end - loop_start
# Figure how many durations can occur between the
# start of the loop and now.
new_repeats = int((target - loop_start) / duration)
if duration <= 0:
raise Exception("ATL appears to be in an infinite loop.")
if count is not None:
if repeats + new_repeats >= count:
new_repeats = count - repeats
loop_start += new_repeats * duration
return "next", target - loop_start, None
repeats += new_repeats
loop_start = loop_start + new_repeats * duration
start = loop_start
index = 0
child_state = None
if times:
time, tindex = times[0]
@@ -566,6 +573,8 @@ class Block(Statement):
# values of the variables here.
class RawMultipurpose(RawStatement):
warp_function = None
def __init__(self, loc):
self.loc = loc
@@ -578,9 +587,10 @@ class RawMultipurpose(RawStatement):
self.revolution = None
self.circles = "0"
def add_warper(self, name, duration):
def add_warper(self, name, duration, warp_function):
self.warper = name
self.duration = duration
self.warp_function = warp_function
def add_property(self, name, exprs):
self.properties.append((name, exprs))
@@ -605,6 +615,7 @@ class RawMultipurpose(RawStatement):
# interpolator, and no properties, than we have either a
# call, or a child statement.
if (self.warper is None and
self.warp_function is None and
not self.properties and
not self.splines and
len(self.expressions) == 1):
@@ -618,7 +629,7 @@ class RawMultipurpose(RawStatement):
transition = None
if isinstance(child, (int, float)):
return Interpolation(self.loc, "pause", child, [ ])
return Interpolation(self.loc, "pause", child, [ ], None, 0, [ ])
if isinstance(child, ATLTransformBase):
child.compile()
@@ -630,10 +641,14 @@ class RawMultipurpose(RawStatement):
compiling(self.loc)
# Otherwise, we probably have an interpolation statement.
warper = self.warper or "pause"
if warper not in warpers:
raise Exception("ATL Warper %s is unknown at runtime." % warper)
if self.warp_function:
warper = ctx.eval(self.warp_function)
else:
warper = self.warper or "pause"
if warper not in warpers:
raise Exception("ATL Warper %s is unknown at runtime." % warper)
properties = [ ]
@@ -776,7 +791,7 @@ class Interpolation(Statement):
executing(self.loc)
warper = warpers[self.warper]
warper = warpers.get(self.warper, self.warper)
if self.duration:
complete = min(1.0, st / self.duration)
@@ -798,6 +813,7 @@ class Interpolation(Statement):
# Now, the things we change linearly are in the difference
# between the new and old states.
linear = trans.state.diff(newts)
revolution = None
splines = [ ]
@@ -856,14 +872,14 @@ class Interpolation(Statement):
# Linearly interpolate between the things in linear.
for k, (old, new) in linear.iteritems():
value = interpolate(complete, old, new)
setattr(trans.state, k, value)
value = interpolate(complete, old, new, PROPERTIES[k])
setattr(trans.state, k, value)
# Handle the revolution.
if revolution is not None:
startangle, endangle, startradius, endradius = revolution
trans.state.angle = interpolate(complete, startangle, endangle)
trans.state.radius = interpolate(complete, startradius, endradius)
trans.state.angle = interpolate(complete, startangle, endangle, float)
trans.state.radius = interpolate(complete, startradius, endradius, float)
# Handle any splines we might have.
for name, values in splines:
@@ -1166,6 +1182,33 @@ class Event(Statement):
def execute(self, trans, st, state, event):
return "event", (self.name, st), None
class RawFunction(RawStatement):
def __init__(self, loc, expr):
self.loc = loc
self.expr = expr
def compile(self, ctx):
compiling(self.loc)
return Function(self.loc, ctx.eval(self.expr))
class Function(Statement):
def __init__(self, loc, function):
self.loc = loc
self.function = function
def execute(self, trans, st, state, event):
fr = self.function(trans, st, trans.at)
if fr is not None:
return "continue", None, fr
else:
return "next", 0, None
# This parses an ATL block.
def parse_atl(l):
@@ -1250,6 +1293,12 @@ def parse_atl(l):
statements.append(RawTime(loc, time))
elif l.keyword('function'):
expr = l.require(l.simple_expression)
l.expect_noblock('function')
statements.append(RawFunction(loc, expr))
elif l.keyword('event'):
name = l.require(l.word)
l.expect_noblock('event')
@@ -1283,15 +1332,25 @@ def parse_atl(l):
cp = l.checkpoint()
warper = l.name()
if warper in warpers:
duration = l.require(l.simple_expression)
warp_function = None
elif warper == "warp":
warper = None
warp_function = l.require(l.simple_expression)
duration = l.require(l.simple_expression)
else:
l.revert(cp)
warper = None
warp_function = None
duration = "0"
rm.add_warper(warper, duration)
rm.add_warper(warper, duration, warp_function)
# Now, look for properties and simple_expressions.
while True:
+6 -3
View File
@@ -26,10 +26,10 @@
import renpy
import time
import pygame
import os
import atexit
import time
# Import the appropriate modules, or set them to None if we cannot.
@@ -48,15 +48,18 @@ if 'pss' not in disable:
if 'mix' not in disable:
try:
import winmixer as mix
import winmixer as mix; mix
except:
try:
import linmixer as mix
import linmixer as mix; mix
except:
pass
# Save the mixer, and restore it at exit.
old_wave = None
old_midi = None
if mix:
mixer_enabled = False
+2 -2
View File
@@ -21,7 +21,6 @@
# The public API for music in games.
import time
import renpy
# A list of music channels.
@@ -34,6 +33,7 @@ from renpy.audio.audio import get_channel, get_serial
# Part of the public api:
from renpy.audio.audio import register_channel, alias_channel
register_channel; alias_channel
def play(filenames, channel="music", loop=None, fadeout=None, synchro_start=False, fadein=0, tight=None, if_changed=False):
"""
@@ -333,7 +333,7 @@ def channel_defined(channel):
"""
try:
c = renpy.audio.audio.get_channel(channel)
renpy.audio.audio.get_channel(channel)
return True
except:
return False
+28 -23
View File
@@ -26,7 +26,7 @@ import sys
# Extra things used for distribution.
def extra_imports():
import datetime
import datetime; datetime
import encodings.ascii
import encodings.utf_8
import encodings.zlib_codec
@@ -35,29 +35,29 @@ def extra_imports():
import encodings.raw_unicode_escape
import encodings.mbcs
import encodings.utf_16_be
import encodings.utf_16_le
import math
import glob
import pickle
import platform
import encodings.utf_16_le; encodings.utf_16_le
import math; math
import glob; glob
import pickle; pickle
import platform; platform
import pysdlsound
import pysdlsound.sound
import pysdlsound.winmixer
import pysdlsound.linmixer
import difflib
import shutil
import pysdlsound.linmixer; pysdlsound.linmixer
import difflib; difflib
import shutil; shutil
import renpy.tools.archiver
import renpy.tools.add_from
import tarfile
import bz2
import webbrowser
import renpy.tools.add_from; renpy.tools.add_from
import tarfile; tarfile
import bz2; bz2
import webbrowser; webbrowser
import pygame.locals
import pygame.color
import pygame.colordict
import posixpath
import pygame.colordict; pygame.colordict
import posixpath; posixpath
import ctypes
import ctypes.wintypes
import EasyDialogs
import ctypes.wintypes; ctypes.wintypes
import EasyDialogs; EasyDialogs
trace_file = None
trace_local = None
@@ -266,7 +266,7 @@ def bootstrap(renpy_base):
break
except renpy.game.UtterRestartException:
# Only works after a full restart.
report_error = renpy.display.error.ReportError()
@@ -294,6 +294,8 @@ def bootstrap(renpy_base):
if options.leak:
memory_profile()
renpy.display.im.cache.quit()
sys.exit(0)
@@ -311,6 +313,8 @@ def report_tb(out, tb):
elif 'self' in f.f_locals:
obj = f.f_locals['self']
import renpy
if isinstance(obj, renpy.execution.Context):
obj.report_tb(out)
@@ -325,12 +329,15 @@ def report_exception(e):
type, value, tb = sys.exc_info()
def safe_utf8(e):
m = unicode(e)
try:
m = unicode(e)
except:
m = str(e)
if isinstance(m, unicode):
return m.encode("utf-8")
else:
return str(m)
return m
# Outside of the file.
traceback.print_tb(tb, None, sys.stdout)
@@ -389,8 +396,6 @@ def report_exception(e):
def memory_profile():
import renpy
print "Memory Profile"
print
print "Showing all objects in memory at program termination."
+13 -4
View File
@@ -213,9 +213,9 @@ def display_say(show_function,
with_none,
callback,
type,
checkpoint=True):
checkpoint=True,
ctc_timedpause=None):
ctc = renpy.easy.displayable_or_none(ctc)
# If we're in fast skipping mode, don't bother with say
# statements at all.
@@ -289,10 +289,18 @@ def display_say(show_function,
# Update the properties of the what_text widget.
if pause is not None and pause < what_text.pauses:
what_ctc = ctc_pause
if what_text.pause_lengths[pause] is not None:
what_ctc = ctc_timedpause or ctc_pause
else:
what_ctc = ctc_pause
else:
what_ctc = ctc
what_ctc = renpy.easy.displayable_or_none(what_ctc)
if what_ctc is not None:
what_ctc = what_ctc.parameterize(('ctc',), ())
# This object is called when the slow text is done.
slow_done = SlowDone(what_ctc, ctc_position, callback, interact, type, cb_args)
@@ -426,6 +434,7 @@ class ADVCharacter(object):
afm = d('afm'),
ctc = renpy.easy.displayable_or_none(d('ctc')),
ctc_pause = renpy.easy.displayable_or_none(d('ctc_pause')),
ctc_timedpause = renpy.easy.displayable_or_none(d('ctc_timedpause')),
ctc_position = d('ctc_position'),
all_at_once = d('all_at_once'),
with_none = d('with_none'),
+1 -1
View File
@@ -405,5 +405,5 @@ del renpy
def init():
import renpy
global properties
global style_properties
style_properties = renpy.style.style_properties
+3 -26
View File
@@ -22,7 +22,6 @@
# This file contains support for state-machine controlled animations.
import renpy
import pygame
import random
class State(object):
@@ -557,34 +556,12 @@ class Blink(renpy.display.core.Displayable):
rend = renpy.display.render.render(self.image, height, width, st, at)
if not renpy.display.module.can_linmap:
return rend
w, h = rend.get_size()
rv = renpy.display.render.Render(w, h)
if renpy.game.less_updates:
alpha = 1.0
oldsurf = rend.pygame_surface()
if not (oldsurf.get_masks()[3]):
oldsurf = oldsurf.convert_alpha(renpy.game.interface.display.window)
newsurf = pygame.Surface(oldsurf.get_size(), oldsurf.get_flags(), oldsurf)
# amap = renpy.display.im.ramp(0, int(alpha * 255.0))
# identity = renpy.display.im.identity
renpy.display.module.linmap(oldsurf, newsurf,
256, 256, 256, int(alpha * 256.0))
renpy.display.render.mutated_surface(newsurf)
rv.blit(newsurf, (0, 0))
rv.depends_on(rend)
rv.blit(rend, (0, 0))
rv.alpha = alpha
if not renpy.game.less_updates:
renpy.display.render.redraw(self, delay)
+3 -6
View File
@@ -26,7 +26,6 @@ import renpy
from renpy.display.render import render
import pygame
from pygame.constants import *
def compile_event(key, keydown):
"""
@@ -579,8 +578,6 @@ class Input(renpy.display.text.Text):
if map_event(ev, "input_backspace"):
old_content = self.content
if self.content:
content = self.content[:-1]
self.update_text(content, self.editable)
@@ -591,7 +588,7 @@ class Input(renpy.display.text.Text):
if not self.changed:
return self.content
elif ev.type == KEYDOWN and ev.unicode:
elif ev.type == pygame.KEYDOWN and ev.unicode:
if ord(ev.unicode[0]) < 32:
return None
@@ -701,7 +698,7 @@ class Bar(renpy.display.core.Displayable):
__version__ = 1
def after_upgrade(version):
def after_upgrade(self, version):
if version < 1:
self.adjustment = Adjustment(self.range, self.value, changed=self.changed)
@@ -898,7 +895,7 @@ class Bar(renpy.display.core.Displayable):
if map_event(ev, "bar_increase"):
value += self.adjustment.step
if ev.type in (MOUSEMOTION, MOUSEBUTTONUP, MOUSEBUTTONDOWN):
if ev.type in (pygame.MOUSEMOTION, pygame.MOUSEBUTTONUP, pygame.MOUSEBUTTONDOWN):
if self.style.bar_vertical:
+116 -80
View File
@@ -25,13 +25,11 @@
import renpy
import pygame
from pygame.constants import *
import sys
import os
import time
import cStringIO
import threading
import collections
on_windows = (sys.platform == 'win32')
@@ -45,10 +43,10 @@ cpu_idle = threading.Event()
cpu_idle.clear()
# Need to be +4, so we don't interfere with FFMPEG's events.
TIMEEVENT = USEREVENT + 4
PERIODIC = USEREVENT + 5
JOYEVENT = USEREVENT + 6
REDRAW = USEREVENT + 7
TIMEEVENT = pygame.USEREVENT + 4
PERIODIC = pygame.USEREVENT + 5
JOYEVENT = pygame.USEREVENT + 6
REDRAW = pygame.USEREVENT + 7
# All events except for TIMEEVENT and REDRAW
ALL_EVENTS = [ i for i in range(0, REDRAW + 1) if i != TIMEEVENT and i != REDRAW ]
@@ -372,7 +370,17 @@ class Displayable(renpy.object.Object):
"""
Called when the displayable is added to a scene list.
"""
def get_parameterized(self):
"""
If this is a ImageReference to a parameterized image, return
the get_parameterized() of the parameterized image. Otherwise,
return this displayable.
"""
return self
class ImagePredictInfo(renpy.object.Object):
"""
@@ -425,7 +433,7 @@ class SceneLists(renpy.object.Object):
things to the user.
"""
__version__ = 2
__version__ = 3
def after_setstate(self):
for i in renpy.config.layers + renpy.config.top_layers:
@@ -444,15 +452,21 @@ class SceneLists(renpy.object.Object):
self.at_list[i] = { }
self.layer_at_list[i] = (None, [ ])
if version < 3:
self.shown_window = False
def __init__(self, oldsl, ipi):
# Has a window been shown as part of these scene lists?
self.shown_window = False
# A map from layer name -> list of
# (key, zorder, show time, animation time, displayable)
self.layers = { }
self.at_list = { }
self.layer_at_list = { }
self.image_predict_info = ipi
if oldsl:
@@ -508,6 +522,24 @@ class SceneLists(renpy.object.Object):
return True
def transform_state(self, old_thing, new_thing):
"""
If the old thing is a transform, then move the state of that transform
to the new thing.
"""
old_transform = old_thing.get_parameterized()
if not isinstance(old_transform, renpy.display.motion.Transform):
return new_thing
new_transform = new_thing.get_parameterized()
if not isinstance(new_transform, renpy.display.motion.Transform):
new_thing = new_transform = renpy.display.motion.Transform(child=new_thing)
new_transform.take_state(old_transform)
return new_thing
def add(self, layer, thing, key=None, zorder=0, behind=[ ], at_list=[ ], name=None, atl=None):
"""
This is called to add something to a layer. Layer is
@@ -575,11 +607,9 @@ class SceneLists(renpy.object.Object):
# If the old thing was a transform, make sure the new thing
# is a transform, and then take the transform state.
if isinstance(old_thing, renpy.display.motion.Transform):
if not isinstance(thing, renpy.display.motion.Transform):
thing = renpy.display.motion.Transform(child=thing)
thing.take_state(old_thing)
thing = self.transform_state(old_thing, thing)
thing.set_transform_event("replace")
thing.show()
@@ -765,11 +795,8 @@ class SceneLists(renpy.object.Object):
self.layers[l] = newl
class Display(object):
"""
This is responsible for managing the display window.
@@ -778,10 +805,6 @@ class Display(object):
@ivar window: The window that is being presented to the user.
@ivar sample_surface: A sample surface that is optimized for fast
blitting to the window, with alpha. Used to create other surfaces
from.
@ivar fullscreen: Is the window in fullscreen mode?
@ivar mouse: The mouse image, if we have one, or None if
@@ -805,7 +828,6 @@ class Display(object):
"""
def __init__(self, interface):
self.interface = interface
@@ -852,7 +874,7 @@ class Display(object):
# Convert the aspect ratio to be square.
iw, ih = im.get_size()
imax = max(iw, ih)
square_im = renpy.display.scale.PygameSurface((imax, imax), pygame.SRCALPHA, depth=32)
square_im = renpy.display.pgrender.surface_unscaled((imax, imax), True)
square_im.blit(im, ( (imax-iw)/2, (imax-ih)/2 ))
im = square_im
@@ -867,7 +889,7 @@ class Display(object):
# If we're in fullscreen mode, and changing to another mode, go to
# windowed mode first.
s = pygame.display.get_surface()
if s and (s.get_flags() & FULLSCREEN):
if s and (s.get_flags() & pygame.FULLSCREEN):
fullscreen = False
self.fullscreen = fullscreen
@@ -900,37 +922,31 @@ class Display(object):
if w < renpy.config.screen_width or h < renpy.config.screen_height:
continue
fsflag = FULLSCREEN
fsflag = pygame.FULLSCREEN
width = w
height = h
self.screen_xoffset = (width - renpy.config.screen_width) / 2
self.screen_yoffset = (height - renpy.config.screen_height) / 2
elif fullscreen:
fsflag = FULLSCREEN
fsflag = pygame.FULLSCREEN
# If a window exists of the right size and flags, use it. Otherwise,
# make our own window.
old_window = pygame.display.get_surface()
if ((old_window is not None) and
(old_window.get_size() == (width, height)) and
(old_window.get_flags() & FULLSCREEN == fsflag)):
(old_window.get_flags() & pygame.FULLSCREEN == fsflag)):
self.window = old_window
else:
self.window = pygame.display.set_mode((width, height), fsflag, 32)
self.window = renpy.display.pgrender.set_mode((width, height), fsflag, 32)
# Window title.
self.window_caption = None
self.set_window_caption()
# Sample surface that all surfaces are created based on.
sample = pygame.Surface((10, 10), 0, self.window)
self.sample_surface = sample.convert_alpha(self.window)
pygame.event.set_grab(False)
# Load the mouse image, if any.
@@ -962,6 +978,7 @@ class Display(object):
# Setup periodic event.
pygame.time.set_timer(PERIODIC, PERIODIC_INTERVAL)
def set_window_caption(self):
caption = renpy.config.window_title + renpy.store._window_subtitle
if caption == self.window_caption:
@@ -970,8 +987,10 @@ class Display(object):
self.window_caption = caption
pygame.display.set_caption(caption.encode("utf-8"))
def iconify(self):
pygame.display.iconify()
def can_redraw(self, first_pass):
"""
@@ -1006,11 +1025,13 @@ class Display(object):
return True
def mouse_event(self, ev):
if ev.type == pygame.MOUSEMOTION or pygame.MOUSEBUTTONDOWN or pygame.MOUSEBUTTONUP:
self.mouse_event_time = get_time()
def show_mouse(self, pos, info):
"""
Actually shows the mouse.
@@ -1030,13 +1051,14 @@ class Display(object):
by = my - myo
self.mouse_backing_pos = (bx, by)
self.mouse_backing = pygame.Surface((mw, mh), self.window.get_flags(), self.window)
self.mouse_backing = renpy.display.pgrender.surface((mw, mh), False)
self.mouse_backing.blit(self.window, (0, 0), (bx, by, mw, mh))
self.window.blit(mouse, (bx, by))
return bx, by, mw, mh
def hide_mouse(self):
"""
Actually hides the mouse.
@@ -1053,6 +1075,7 @@ class Display(object):
return rv
def draw_mouse(self, show_mouse=True):
"""
This draws the mouse to the screen, if necessary. It uses the
@@ -1113,6 +1136,7 @@ class Display(object):
return updates
def update_mouse(self):
"""
Draws the mouse, and then updates the screen.
@@ -1159,6 +1183,7 @@ class Display(object):
self.suppressed_blit = suppress_blit
self.surftree = surftree
def save_screenshot(self, filename):
"""
@@ -1171,7 +1196,6 @@ class Display(object):
if renpy.config.debug:
raise
pass
def screenshot(self, scale):
@@ -1179,9 +1203,9 @@ class Display(object):
Returns a string containing the contents of the window, as a PNG.
"""
surf = self.window.convert_alpha()
surf = renpy.display.pgrender.copy_surface(self.window, True)
surf = renpy.display.scale.smoothscale(surf, scale)
surf = surf.convert()
surf = renpy.display.pgrender.copy_surface(surf, False)
sio = cStringIO.StringIO()
renpy.display.module.save_png(surf, sio, 0)
@@ -1321,6 +1345,7 @@ class Interface(object):
self.screenshot = self.display.screenshot(scale)
def get_screenshot(self):
"""
Gets the current screenshot, as a string. Returns None if there isn't
@@ -1332,6 +1357,7 @@ class Interface(object):
return self.screenshot
def lose_screenshot(self):
"""
This deallocates the saved screenshot.
@@ -1339,17 +1365,19 @@ class Interface(object):
self.screenshot = None
def show_window(self):
if not renpy.store._window:
return
if self.shown_window:
if renpy.game.context().scene_lists.shown_window:
return
if renpy.config.empty_window:
renpy.config.empty_window()
def do_with(self, trans, paired, clear=False):
if renpy.config.with_callback:
@@ -1371,21 +1399,21 @@ class Interface(object):
be transitioning from.
"""
# Show the window, if that's necessary.
self.show_window()
# Compute the overlay.
self.compute_overlay()
scene_lists = renpy.game.context().scene_lists
old_old_scene = self.old_scene
# Compute the scene.
self.old_scene = self.compute_scene(scene_lists)
if renpy.config.overlay_during_with and old_old_scene:
for i in renpy.config.overlay_layers:
self.old_scene[i] = old_old_scene[i]
scene_lists = renpy.game.context().scene_lists
# Get rid of transient things.
scene_lists.replace_transient()
self.shown_window = False
scene_lists.shown_window = False
def set_transition(self, transition, layer=None, force=False):
"""
@@ -1409,7 +1437,7 @@ class Interface(object):
ev = pygame.event.poll()
if ev.type == NOEVENT:
if ev.type == pygame.NOEVENT:
# Seems to prevent the CPU from speeding up.
time.sleep(0.001)
return None
@@ -1454,7 +1482,25 @@ class Interface(object):
self.last_event = ev
return ev
def compute_overlay(self):
if renpy.store.suppress_overlay:
return
# Figure out what the overlay layer should look like.
renpy.ui.layer("overlay")
for i in renpy.config.overlay_functions:
i()
if renpy.game.context().scene_lists.shown_window:
for i in renpy.config.window_overlay_functions:
i()
renpy.ui.close()
def compute_scene(self, scene_lists):
"""
This converts scene lists into a dictionary mapping layer
@@ -1489,6 +1535,7 @@ class Interface(object):
else:
raise renpy.game.QuitException()
def interact(self, clear=True, suppress_window=False, **kwargs):
"""
This handles an interaction, restarting it if necessary. All of the
@@ -1499,17 +1546,15 @@ class Interface(object):
if not suppress_window:
self.show_window()
# These things can be done once per interaction.
import time
start = time.time()
preloads = self.preloads
self.preloads = [ ]
try:
renpy.game.after_rollback = False
for i in renpy.config.start_interact_callbacks:
i()
@@ -1533,8 +1578,10 @@ class Interface(object):
self.restart_interaction = True
self.shown_window = False
renpy.game.context().scene_lists.shown_window = False
def interact_core(self,
show_mouse=True,
trans_pause=False,
@@ -1561,7 +1608,6 @@ class Interface(object):
self.roll_forward = roll_forward
suppress_overlay = suppress_overlay or renpy.store.suppress_overlay
suppress_transition = renpy.config.skipping or renpy.game.less_updates
# The global one.
@@ -1619,8 +1665,10 @@ class Interface(object):
renpy.display.layout.size_groups.clear()
# Clear some events.
pygame.event.clear((MOUSEMOTION, PERIODIC,
TIMEEVENT, REDRAW))
pygame.event.clear((pygame.MOUSEMOTION,
PERIODIC,
TIMEEVENT,
REDRAW))
# Add a single TIMEEVENT to the queue.
pygame.event.post(self.time_event)
@@ -1628,20 +1676,12 @@ class Interface(object):
# Figure out the scene list we want to show.
scene_lists = renpy.game.context().scene_lists
# Remove the now-hidden things.
scene_lists.remove_hidden()
# Figure out what the overlay layer should look like.
renpy.ui.layer("overlay")
# Compute the overlay.
if not suppress_overlay:
for i in renpy.config.overlay_functions:
i()
if self.shown_window:
for i in renpy.config.window_overlay_functions:
i()
renpy.ui.close()
self.compute_overlay()
# The root widget of everything that is displayed on the screen.
root_widget = renpy.display.layout.MultiBox(layout='fixed')
@@ -1711,11 +1751,7 @@ class Interface(object):
old_root.layers = { }
for layer in renpy.config.layers:
if layer in renpy.config.overlay_layers:
d = scene[layer]
else:
d = self.transition_from[None].layers[layer]
d = self.transition_from[None].layers[layer]
old_root.layers[layer] = d
old_root.add(d)
@@ -1941,7 +1977,7 @@ class Interface(object):
else:
ev = self.event_wait()
if ev.type == NOEVENT:
if ev.type == pygame.NOEVENT:
continue
if renpy.config.profile:
@@ -1955,7 +1991,7 @@ class Interface(object):
ev2 = self.event_peek()
if ev2 and ev2.type not in (NOEVENT, PERIODIC, REDRAW, QUIT):
if ev2 and ev2.type not in (pygame.NOEVENT, PERIODIC, REDRAW, pygame.QUIT):
ev = self.event_poll()
# Handle redraw timeouts.
@@ -1992,12 +2028,12 @@ class Interface(object):
renpy.display.behavior.skipping(ev)
# Handle quit specially for now.
if ev.type == QUIT:
if ev.type == pygame.QUIT:
self.quit_event()
# Merge mousemotion events.
if ev.type == MOUSEMOTION:
evs = pygame.event.get([MOUSEMOTION])
if ev.type == pygame.MOUSEMOTION:
evs = pygame.event.get([pygame.MOUSEMOTION])
if len(evs):
ev = evs[-1]
@@ -2005,7 +2041,7 @@ class Interface(object):
self.focused = True
# Handle focus notifications.
if ev.type == ACTIVEEVENT:
if ev.type == pygame.ACTIVEEVENT:
if ev.state & 1:
self.focused = ev.gain
+1 -4
View File
@@ -24,9 +24,6 @@
import pygame
import renpy
import textwrap
import select
import sys
import os
import os.path
@@ -69,7 +66,7 @@ class ReportError(object):
return True
ev = pygame.event.wait()
if ev.type == pygame.MOUSEBUTTONUP:
if ev.button == 1:
+2 -3
View File
@@ -21,9 +21,8 @@
# This file contains code to manage focus on the display.
import renpy
import pygame
from pygame.constants import *
import renpy
class Focus(object):
@@ -216,7 +215,7 @@ def change_focus(newfocus, default=False):
# This handles mouse events, to see if they change the focus.
def mouse_handler(ev, x, y, default=False):
if ev.type not in (MOUSEMOTION, MOUSEBUTTONUP, MOUSEBUTTONDOWN):
if ev.type not in (pygame.MOUSEMOTION, pygame.MOUSEBUTTONUP, pygame.MOUSEBUTTONDOWN):
return
new_focus = renpy.display.render.focus_at_point(x, y)
+8 -11
View File
@@ -20,7 +20,6 @@
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import pygame
from pygame.constants import *
import xml.etree.ElementTree as etree
@@ -75,15 +74,14 @@ class ImageFont(object):
def render(self, text, antialias, color, black_color=(0, 0, 0, 255), background=None):
if not text:
return pygame.Surface((0, self.height), 0,
renpy.game.interface.display.sample_surface)
return renpy.display.pgrender.surface((0, self.height), True)
xoff, _ = self.offsets[text[0]]
x = -xoff
y = 0
surf = pygame.Surface(self.size(text), 0,
renpy.game.interface.display.sample_surface)
surf = renpy.display.pgrender.surface(self.size(text), True)
for a, b in zip(text, text[1:]):
xoff, yoff = self.offsets[a]
surf.blit(self.chars[a], (x + xoff, y + yoff))
@@ -93,15 +91,14 @@ class ImageFont(object):
surf.blit(self.chars[text[-1]], (x + xoff, y + yoff))
if renpy.config.recolor_sfonts and \
(color != (255, 255, 255, 255) or black_color != (0, 0, 0, 255) ) and \
renpy.display.module.can_twomap:
(color != (255, 255, 255, 255) or black_color != (0, 0, 0, 255)):
newsurf = pygame.Surface(surf.get_size(), surf.get_flags(), surf)
newsurf = renpy.display.pgrender.surface(surf.get_size(), True)
renpy.display.module.twomap(surf, newsurf, color, black_color)
renpy.display.render.mutated_surface(newsurf)
surf = newsurf
renpy.display.render.mutated_surface(surf)
return surf
def get_linesize(self):
@@ -148,7 +145,7 @@ class SFont(ImageFont):
self.baseline = height
# Create space characters.
self.chars[u' '] = pygame.Surface((self.spacewidth, height), 0, surf)
self.chars[u' '] = renpy.display.pgrender.surface((self.spacewidth, height), True)
self.width[u' '] = self.spacewidth
self.advance[u' '] = self.spacewidth
self.offsets[u' '] = (0, 0)
@@ -253,7 +250,7 @@ class MudgeFont(ImageFont):
# Create space characters.
if u' ' not in self.chars:
self.chars[u' '] = pygame.Surface((self.spacewidth, height), 0, surf)
self.chars[u' '] = renpy.display.pgrender.surface((self.spacewidth, height), True)
self.width[u' '] = self.spacewidth
self.advance[u' '] = self.spacewidth
self.offsets[u' '] = (0, 0)
+42 -87
View File
@@ -24,14 +24,12 @@
# cropping and scaling).
import renpy
import random
import math
import zipfile
import cStringIO
import threading
import pygame
from pygame.constants import *
# This is an entry in the image cache.
class CacheEntry(object):
@@ -83,11 +81,14 @@ class Cache(object):
self.keep_preloading = True
# The preload thread.
self.preload_thread = threading.Thread(target=self.preload_thread_main)
self.preload_thread = threading.Thread(target=self.preload_thread_main, name="preloader")
self.preload_thread.setDaemon(True)
self.preload_thread.start()
def quit(self):
if not self.preload_thread.isAlive():
return
self.lock.acquire()
self.keep_preloading = False
self.lock.notify()
@@ -160,9 +161,7 @@ class Cache(object):
raise Exception("Expected an image of some sort, but got" + str(image) + ".")
if not image.cache:
surf = image.load()
surf = surf.convert_alpha(renpy.game.interface.display.window)
surf = image.load()
renpy.display.render.mutated_surface(surf)
return surf
@@ -180,15 +179,17 @@ class Cache(object):
ce = self.cache.get(image, None)
if ce is not None:
self.cache.release()
self.cache.release()
# Otherwise, we keep the lock, and load the image ourselves.
if ce is None:
surf = image.load()
has_alpha = surf.get_masks()[3]
surf = surf.convert_alpha(renpy.game.interface.display.window)
try:
surf = image.load()
except:
self.lock.release()
raise
ce = CacheEntry(image, surf)
self.total_cache_size += ce.size
self.cache[image] = ce
@@ -205,26 +206,16 @@ class Cache(object):
rle = not renpy.game.less_memory
# rle = image.rle
surf = ce.surf
# # If we don't know if the image is RLE or not, guess.
# # Only do so if the image has an alpha channel.
# if rle is None and has_alpha and not renpy.game.less_memory:
# sw, sh = surf.get_size()
# for i in range(0, 10):
# if surf.get_at((random.randint(0, sw-1),
# random.randint(0, sh-1)))[3] == 0:
# rle = True
# break
if rle:
# We must copy the surface, so we have a RLE-specific version.
rle_surf = ce.surf.convert_alpha(renpy.game.interface.display.window)
rle_surf.set_alpha(255, RLEACCEL)
rle_surf = renpy.display.pgrender.copy_surface(ce.surf)
rle_surf.set_alpha(255, pygame.RLEACCEL)
renpy.display.render.mutated_surface(rle_surf)
rle_cache[id(ce.surf)] = rle_surf
renpy.display.render.mutated_surface(ce.surf)
if renpy.config.debug_image_cache:
print "Added to rle cache:", image
@@ -453,9 +444,9 @@ class Image(ImageBase):
try:
if unscaled:
surf = renpy.display.scale.image_load_unscaled(renpy.loader.load(self.filename), self.filename)
surf = renpy.display.pgrender.load_image_unscaled(renpy.loader.load(self.filename), self.filename)
else:
surf = pygame.image.load(renpy.loader.load(self.filename), self.filename)
surf = renpy.display.pgrender.load_image(renpy.loader.load(self.filename), self.filename)
return surf
@@ -493,7 +484,7 @@ class ZipFileImage(ImageBase):
def load(self):
zf = zipfile.ZipFile(self.zipfilename, 'r')
sio = cStringIO.StringIO(zf.read(self.filename))
rv = pygame.image.load(sio, self.filename)
rv = renpy.display.pgrender.load_image(sio, self.filename)
zf.close()
return rv
@@ -542,8 +533,7 @@ class Composite(ImageBase):
else:
size = cache.get(self.images[0]).get_size()
rv = pygame.Surface(size, 0,
renpy.game.interface.display.sample_surface)
rv = renpy.display.pgrender.surface(size, True)
for pos, im in zip(self.positions, self.images):
rv.blit(cache.get(im), pos)
@@ -610,9 +600,7 @@ class FrameImage(ImageBase):
dw = self.width
dh = self.height
dest = pygame.Surface((dw, dh), 0,
renpy.game.interface.display.sample_surface)
dest = renpy.display.pgrender.surface((dw, dh), True)
rv = dest
source = cache.get(self.image)
@@ -687,18 +675,17 @@ class FrameImage(ImageBase):
tilew, tileh = srcsize
dstw, dsth = dstsize
surf2 = renpy.display.scale.PygameSurface(dstsize, 0, surf)
surf2 = renpy.display.pgrender.surface_unscaled(dstsize)
for y in range(0, dsth, tileh):
for x in range(0, dstw, tilew):
surf2.blit(surf, (x, y))
surf = surf2
else:
if self.bilinear and renpy.display.module.can_bilinear_scale:
surf2 = renpy.display.scale.real_bilinear(surf, dstsize)
if self.bilinear:
surf2 = renpy.display.scale.real_smoothscale(surf, dstsize)
else:
surf2 = renpy.display.scale.real_transform_scale(surf, dstsize)
@@ -740,10 +727,7 @@ class SolidImage(ImageBase):
def load(self):
sample = renpy.game.interface.display.sample_surface
rv = pygame.Surface((self.width, self.height), 0,
sample)
rv = renpy.display.pgrender.surface((self.width, self.height), True)
rv.fill(self.color)
return rv
@@ -756,8 +740,6 @@ class Scale(ImageBase):
def __init__(self, im, width, height, bilinear=True, **properties):
bilinear = bilinear and renpy.display.module.can_bilinear_scale
im = image(im)
super(Scale, self).__init__(im, width, height, bilinear, **properties)
@@ -779,7 +761,7 @@ class Scale(ImageBase):
else:
try:
renpy.display.render.blit_lock.acquire()
rv = pygame.transform.scale(child, (self.width, self.height))
rv = renpy.display.pgrender.transform_scale(child, (self.width, self.height))
finally:
renpy.display.render.blit_lock.release()
@@ -825,7 +807,7 @@ class FactorScale(ImageBase):
else:
try:
renpy.display.render.blit_lock.acquire()
rv = pygame.transform.scale(surf, (width, height))
rv = renpy.display.pgrender.transform_scale(surf, (width, height))
finally:
renpy.display.render.blit_lock.release()
@@ -855,29 +837,28 @@ class Flip(ImageBase):
im = image(im)
super(Flip, self).__init__(im, horizontal, vertical, **properties)
self.image = im
self.horizontal = horizontal
self.vertical = vertical
def load(self):
child = cache.get(self.image)
try:
renpy.display.render.blit_lock.acquire()
rv = pygame.transform.flip(child, self.horizontal, self.vertical)
rv = renpy.display.pgrender.flip(child, self.horizontal, self.vertical)
finally:
renpy.display.render.blit_lock.release()
return rv
def predict_files(self):
return self.image.predict_files()
class Rotozoom(ImageBase):
"""
@@ -908,7 +889,7 @@ class Rotozoom(ImageBase):
try:
renpy.display.render.blit_lock.acquire()
rv = pygame.transform.rotozoom(child, self.angle, self.zoom)
rv = renpy.display.pgrender.rotozoom(child, self.angle, self.zoom)
finally:
renpy.display.render.blit_lock.release()
@@ -997,13 +978,7 @@ class Map(ImageBase):
surf = cache.get(self.image)
if not renpy.display.module.can_map:
return surf
if self.force_alpha and not (surf.get_masks()[3]):
surf = surf.convert_alpha(renpy.game.interface.display.window)
rv = pygame.Surface(surf.get_size(), surf.get_flags(), surf)
rv = renpy.display.pgrender.surface(surf.get_size(), True)
renpy.display.module.map(surf, rv,
self.rmap, self.gmap, self.bmap, self.amap)
@@ -1042,13 +1017,7 @@ class Twocolor(ImageBase):
surf = cache.get(self.image)
if not renpy.display.module.can_twomap:
return surf
if self.force_alpha and not (surf.get_masks()[3]):
surf = surf.convert_alpha(renpy.game.interface.display.window)
rv = pygame.Surface(surf.get_size(), surf.get_flags(), surf)
rv = renpy.display.pgrender.surface(surf.get_size(), True)
renpy.display.module.twomap(surf, rv,
self.white, self.black)
@@ -1085,13 +1054,7 @@ class Recolor(ImageBase):
surf = cache.get(self.image)
if not renpy.display.module.can_linmap:
return surf
if self.force_alpha and not (surf.get_masks()[3]):
surf = surf.convert_alpha(renpy.game.interface.display.window)
rv = pygame.Surface(surf.get_size(), surf.get_flags(), surf)
rv = renpy.display.pgrender.surface(surf.get_size(), True)
renpy.display.module.linmap(surf, rv,
self.rmul, self.gmul, self.bmul, self.amul)
@@ -1124,13 +1087,7 @@ class MatrixColor(ImageBase):
surf = cache.get(self.image)
if not renpy.display.module.can_colormatrix:
return surf
if not (surf.get_masks()[3]):
surf = surf.convert_alpha(renpy.game.interface.display.window)
rv = pygame.Surface(surf.get_size(), surf.get_flags(), surf)
rv = renpy.display.pgrender.surface(surf.get_size(), True)
renpy.display.module.colormatrix(surf, rv, self.matrix)
@@ -1363,11 +1320,11 @@ class Tile(ImageBase):
surf = cache.get(self.image)
rv = renpy.display.pgrender.surface(size, True)
width, height = size
sw, sh = surf.get_size()
rv = pygame.Surface(size, 0, surf)
for y in range(0, height, sh):
for x in range(0, width, sw):
rv.blit(surf, (x, y))
@@ -1394,10 +1351,8 @@ class AlphaMask(ImageBase):
raise Exception("AlphaMask surfaces must be the same size.")
# Used to copy the surface.
rv = basesurf.convert_alpha(renpy.game.interface.display.window)
if renpy.display.module.can_munge:
renpy.display.module.alpha_munge(masksurf, rv, identity)
rv = renpy.display.pgrender.copy_surface(basesurf)
renpy.display.module.alpha_munge(masksurf, rv, identity)
return rv
@@ -1431,8 +1386,7 @@ def image(arg, loose=False, **properties):
if isinstance(arg, renpy.display.image.ImageReference):
arg.find_target()
return image(arg.target, loose=loose, **properties)
elif isinstance(arg, basestring):
return Image(arg, **properties)
@@ -1452,7 +1406,8 @@ def image(arg, loose=False, **properties):
raise Exception("Expected an image, but got a general displayable.")
else:
raise Exception("Could not construct image from argument.")
def load_image(fn):
"""
This loads an image from the given filename, using the cache.
+8 -5
View File
@@ -26,8 +26,6 @@
import renpy
from renpy.display.render import render, Render
import pygame
from pygame.constants import *
Image = renpy.display.im.image
@@ -48,12 +46,11 @@ class UncachedImage(renpy.display.core.Displayable):
super(UncachedImage, self).__init__(style=style, **properties)
self.surf = pygame.image.load(file, hint)
self.surf = self.surf.convert_alpha(renpy.game.interface.display.window)
self.surf = renpy.display.pgrender.image_load(file, hint)
if scale:
renpy.display.render.blit_lock.acquire()
self.surf = pygame.transform.scale(self.surf, scale)
self.surf = renpy.display.pgrender.transform_scale(self.surf, scale)
renpy.display.render.blit_lock.release()
renpy.display.render.mutated_surface(self.surf)
@@ -86,6 +83,12 @@ class ImageReference(renpy.display.core.Displayable):
self.name = name
def get_parameterized(self):
if self.param_target:
return self.param_target.get_parameterized()
return self
def find_target(self):
if self.param_target:
+3 -6
View File
@@ -22,12 +22,9 @@
# This file is responsible for joystick support in Ren'Py.
import os
import pygame
from pygame.constants import *
import renpy
import sets
# Do we have a joystick enabled?
enabled = False
@@ -63,7 +60,7 @@ def event(ev):
if not enabled:
return ev
if ev.type == JOYAXISMOTION:
if ev.type == pygame.JOYAXISMOTION:
if ev.value >= 0.5:
state = "Positive"
@@ -95,12 +92,12 @@ def event(ev):
return pygame.event.Event(renpy.display.core.JOYEVENT,
press=press, release=release)
if ev.type == JOYBUTTONDOWN:
if ev.type == pygame.JOYBUTTONDOWN:
return pygame.event.Event(renpy.display.core.JOYEVENT,
press="Button %d.%d" % (ev.joy, ev.button),
release=None)
if ev.type == JOYBUTTONUP:
if ev.type == pygame.JOYBUTTONUP:
return pygame.event.Event(renpy.display.core.JOYEVENT,
press=None,
+4 -26
View File
@@ -22,13 +22,9 @@
# This file contains classes that handle layout of displayables on
# the screen.
import pygame
from pygame.constants import *
import renpy
from renpy.display.render import render, Render, IDENTITY, Matrix2D
import time
import math
from renpy.display.render import render, Render
def scale(num, base):
"""
@@ -1312,28 +1308,10 @@ class Alpha(renpy.display.core.Displayable):
rend = renpy.display.render.render(self.child, height, width, st, at)
if not renpy.display.module.can_linmap:
return rend
w, h = rend.get_size()
rv = renpy.display.render.Render(w, h)
oldsurf = rend.pygame_surface()
if not (oldsurf.get_masks()[3]):
oldsurf = oldsurf.convert_alpha(renpy.game.interface.display.window)
newsurf = pygame.Surface(oldsurf.get_size(), oldsurf.get_flags(), oldsurf)
renpy.display.module.linmap(oldsurf, newsurf,
256, 256, 256, int(alpha * 256.0))
renpy.display.render.mutated_surface(newsurf)
rv.blit(newsurf, (0, 0))
rv.depends_on(rend)
rv.blit(rend, (0, 0))
rv.alpha = alpha
return rv
+149 -276
View File
@@ -23,8 +23,7 @@
# allows us to enhance the feature set of pygame in a renpy specific way.
import renpy
import pygame
from pygame.constants import *
import pygame; pygame # prevents pyflakes warning.
import sys
@@ -32,7 +31,7 @@ try:
import _renpy
version = _renpy.version()
if version < (6, 10, 0):
if version < (6, 10, 1):
print >>sys.stderr, "The _renpy module was found, but is out of date."
print >>sys.stderr, "Trying to run anyway, but you should expect errors."
@@ -51,87 +50,54 @@ def convert_and_call(function, src, dst, *args):
same format, they are converted and then converted back.
"""
# Now that all surfaces are 32bpp, this function doesn't do much
# of anything anymore.
if (dst.get_masks()[3] != 0) != (src.get_masks()[3] != 0):
raise Exception("Surface alphas do not match.")
dstsize = dst.get_bitsize()
function(src, dst, *args)
if dst.get_bitsize() in (24, 32):
target = dst
else:
if dst.get_masks()[3]:
target = pygame.Surface(dst.get_size(), SRCALPHA, 32)
else:
target = pygame.Surface(dst.get_size(), 0, 24)
if src.get_bitsize() == target.get_bitsize():
source = src
else:
source = src.convert(target)
def pixellate(src, dst, avgwidth, avgheight, outwidth, outheight):
"""
This pixellates the source surface. First, every pixel in the
source surface is projected onto a virtual surface, such that
the average value of every avgwidth x avgheight pixels becomes
one virtual pixel. It then gets projected back onto the
destination surface at a ratio of one virtual pixel to every
outwidth x outheight destination pixels.
function(source, target, *args)
If either src or dst is not a 24 or 32 bit surface, they are
converted... but that may be a significant performance hit.
The two surfaces must either have the same alpha or no alpha.
"""
convert_and_call(_renpy.pixellate,
src, dst,
avgwidth, avgheight,
outwidth, outheight)
def scale(s, size):
"""
Scales down the supplied pygame surface by the given X and Y
factors.
Always works, but may not be high quality.
"""
width, height = s.get_size()
dx, dy = size
d = renpy.display.pgrender.surface(size, True)
bilinear_scale(s, d)
if target is not dst:
dst.blit(target, (0, 0))
return d
if version >= 4008002:
can_pixellate = True
def pixellate(src, dst, avgwidth, avgheight, outwidth, outheight):
"""
This pixellates the source surface. First, every pixel in the
source surface is projected onto a virtual surface, such that
the average value of every avgwidth x avgheight pixels becomes
one virtual pixel. It then gets projected back onto the
destination surface at a ratio of one virtual pixel to every
outwidth x outheight destination pixels.
If either src or dst is not a 24 or 32 bit surface, they are
converted... but that may be a significant performance hit.
The two surfaces must either have the same alpha or no alpha.
"""
convert_and_call(_renpy.pixellate,
src, dst,
avgwidth, avgheight,
outwidth, outheight)
def scale(s, size):
"""
Scales down the supplied pygame surface by the given X and Y
factors.
Always works, but may not be high quality.
"""
width, height = s.get_size()
dx, dy = size
d = pygame.Surface(size, s.get_flags(), s)
if can_bilinear_scale:
bilinear_scale(s, d)
else:
pixellate(s, d, width / dx, height / dy, 1, 1)
return d
else:
can_pixellate = False
def scale(s, size):
renpy.display.render.blit_lock.acquire()
rv = pygame.transform.scale(s, size)
renpy.display.render.blit_lock.release()
return rv
# What we have here are a pair of tables mapping masks to byte offsets
# for 24 and 32 bpp modes. We represent 0xff000000 as positive and negative
# numbers so that it doesn't yield a warning, and so that it works on
@@ -170,230 +136,137 @@ def endian_order(src, r, g, b, a):
return rv
if version >= 5005000:
can_linmap = True
def linmap(src, dst, rmap, gmap, bmap, amap):
"""
This maps the colors between two surfaces. The various map
parameters should be fixed-point integers, with 1.0 == 256.
"""
def linmap(src, dst, rmap, gmap, bmap, amap):
"""
This maps the colors between two surfaces. The various map
parameters should be fixed-point integers, with 1.0 == 256.
"""
convert_and_call(_renpy.linmap,
src, dst,
*endian_order(dst, rmap, gmap, bmap, amap))
convert_and_call(_renpy.linmap,
src, dst,
*endian_order(dst, rmap, gmap, bmap, amap))
save_png = _renpy.save_png
save_png = _renpy.save_png
else:
def map(src, dst, rmap, gmap, bmap, amap):
"""
This maps the colors between two surfaces. The various map
parameters must be 256 character long strings, with the value
of a character at a given offset being what a particular pixel
component value is mapped to.
"""
can_linmap = False
def save_png(surf, file, compress=-1):
convert_and_call(_renpy.map,
src, dst,
*endian_order(dst, rmap, gmap, bmap, amap))
def twomap(src, dst, white, black):
"""
Given colors for white and black, linearly maps things
appropriately, taking the alpha channel from white.
"""
wr = white[0]
wg = white[1]
wb = white[2]
wa = white[3]
br = black[0]
bg = black[1]
bb = black[2]
ramp = renpy.display.im.ramp
if br == 0 and bg == 0 and bb == 0:
linmap(src, dst,
wr + 1,
wg + 1,
wb + 1,
wa + 1)
else:
map(src, dst,
ramp(br, wr),
ramp(bg, wg),
ramp(bb, wb),
ramp(0, wa))
def alpha_munge(src, dst, amap):
"""
This samples the red channel from src, maps it through amap, and
place it into the alpha channel of amap.
"""
if src.get_size() != dst.get_size():
return
red = byte_offset(src)[0]
alpha = byte_offset(dst)[3]
if version >= 4008005:
can_map = True
def map(src, dst, rmap, gmap, bmap, amap):
"""
This maps the colors between two surfaces. The various map
parameters must be 256 character long strings, with the value
of a character at a given offset being what a particular pixel
component value is mapped to.
"""
convert_and_call(_renpy.map,
src, dst,
*endian_order(dst, rmap, gmap, bmap, amap))
if red is not None and alpha is not None:
_renpy.alpha_munge(src, dst, red, alpha, amap)
else:
def bilinear_scale(src, dst, sx=0, sy=0, sw=None, sh=None, dx=0, dy=0, dw=None, dh=None, precise=0):
can_map = False
if sw is None:
sw, sh = src.get_size()
if dw is None:
dw, dh = dst.get_size()
while True:
if can_map or can_linmap:
if sw <= dw * 2 and sh <= dh * 2:
break
can_twomap = True
nsw = max(sw / 2, dw)
nsh = max(sh / 2, dh)
def twomap(src, dst, white, black):
"""
Given colors for white and black, linearly maps things
appropriately, taking the alpha channel from white.
"""
nsrc = renpy.display.pgrender.surface((nsw, nsh), src.get_masks()[3])
wr = white[0]
wg = white[1]
wb = white[2]
wa = white[3]
br = black[0]
bg = black[1]
bb = black[2]
_renpy.bilinear(src, nsrc, sx, sy, sw, sh, precise=precise)
ramp = renpy.display.im.ramp
sx = 0
sy = 0
sw = nsw
sh = nsh
src = nsrc
if can_linmap and br == 0 and bg == 0 and bb == 0:
linmap(src, dst,
wr + 1,
wg + 1,
wb + 1,
wa + 1)
else:
map(src, dst,
ramp(br, wr),
ramp(bg, wg),
ramp(bb, wb),
ramp(0, wa))
else:
can_twomap = False
if version >= 4008007:
can_munge = True
def alpha_munge(src, dst, amap):
"""
This samples the red channel from src, maps it through amap, and
place it into the alpha channel of amap.
"""
if src.get_size() != dst.get_size():
return
red = byte_offset(src)[0]
alpha = byte_offset(dst)[3]
if red is not None and alpha is not None:
_renpy.alpha_munge(src, dst, red, alpha, amap)
else:
can_munge = False
def alpha_munge(src, dst, amap):
return
if version >= 5006000:
can_bilinear_scale = True
def bilinear_scale(src, dst, sx=0, sy=0, sw=None, sh=None, dx=0, dy=0, dw=None, dh=None):
if sw is None:
sw, sh = src.get_size()
if dw is None:
dw, dh = dst.get_size()
while True:
if sw <= dw * 2 and sh <= dh * 2:
break
nsw = max(sw / 2, dw)
nsh = max(sh / 2, dh)
nsrc = pygame.Surface((nsw, nsh), src.get_flags(), src)
_renpy.bilinear(src, nsrc, sx, sy, sw, sh)
sx = 0
sy = 0
sw = nsw
sh = nsh
src = nsrc
_renpy.bilinear(src, dst, sx, sy, sw, sh, dx, dy, dw, dh)
_renpy.bilinear(src, dst, sx, sy, sw, sh, dx, dy, dw, dh, precise=precise)
transform = _renpy.transform
else:
# Note: Blend requires all surfaces to be the same size.
blend = _renpy.blend
def imageblend(a, b, dst, img, amap):
red = byte_offset(img)[0]
_renpy.imageblend(a, b, dst, img, red, amap)
can_bilinear_scale = False
def bilinear_scale(src, dst, sx=0, sy=0, sw=None, sh=None, dx=0, dy=0, dw=None, dh=None):
return
def colormatrix(src, dst, matrix):
c = [ matrix[0:5], matrix[5:10], matrix[10:15], matrix[15:20] ]
offs = byte_offset(src)
o = [ None ] * 4
for i in range(0, 4):
o[offs[i]] = i
_renpy.colormatrix(src, dst,
c[o[0]][o[0]], c[o[0]][o[1]], c[o[0]][o[2]], c[o[0]][o[3]], c[o[0]][4],
c[o[1]][o[0]], c[o[1]][o[1]], c[o[1]][o[2]], c[o[1]][o[3]], c[o[1]][4],
c[o[2]][o[0]], c[o[2]][o[1]], c[o[2]][o[2]], c[o[2]][o[3]], c[o[2]][4],
c[o[3]][o[0]], c[o[3]][o[1]], c[o[3]][o[2]], c[o[3]][o[3]], c[o[3]][4])
def subpixel(src, dst, x, y):
shift = src.get_shifts()[3]
_renpy.subpixel(src, dst, x, y, shift)
if version >= 5006006:
can_transform = True
transform = _renpy.transform
else:
can_transform = False
if version >= 6001000:
# Note: Blend requires all surfaces to be the same size.
can_blend = True
blend = _renpy.blend
else:
can_blend = False
if version >= 6001000:
# Note: Blend requires all surfaces to be the same size.
can_imageblend = True
def imageblend(a, b, dst, img, amap):
red = byte_offset(img)[0]
_renpy.imageblend(a, b, dst, img, red, amap)
else:
can_imageblend = False
if version >= 6002001:
can_colormatrix = True
def colormatrix(src, dst, matrix):
c = [ matrix[0:5], matrix[5:10], matrix[10:15], matrix[15:20] ]
offs = byte_offset(src)
o = [ None ] * 4
for i in range(0, 4):
o[offs[i]] = i
_renpy.colormatrix(src, dst,
c[o[0]][o[0]], c[o[0]][o[1]], c[o[0]][o[2]], c[o[0]][o[3]], c[o[0]][4],
c[o[1]][o[0]], c[o[1]][o[1]], c[o[1]][o[2]], c[o[1]][o[3]], c[o[1]][4],
c[o[2]][o[0]], c[o[2]][o[1]], c[o[2]][o[2]], c[o[2]][o[3]], c[o[2]][4],
c[o[3]][o[0]], c[o[3]][o[1]], c[o[3]][o[2]], c[o[3]][o[3]], c[o[3]][4])
else:
can_colormatrix = False
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)
else:
def subpixel(src, dst, x, y):
renpy.display.render.blit_lock.acquire()
dst.blit(src, (int(x), int(y)))
renpy.display.render.blit_lock.release()
if version >= 6009000:
can_alpha_transform = True
alpha_transform = _renpy.transform
else:
can_alpha_transform = False
+54 -34
View File
@@ -22,12 +22,8 @@
# This file contains displayables that move, zoom, rotate, or otherwise
# transform displayables. (As well as displayables that support them.)
import time
import math
import pygame
from pygame.constants import *
import renpy
from renpy.display.render import render, IDENTITY, Matrix2D
from renpy.display.layout import Container
@@ -133,7 +129,7 @@ class TransformState(renpy.object.Object):
def set_alignaround(self, value):
self.xaround, self.yaround = value
self.xanchoraround, self.yanchoraround = value
around = property(get_around, set_around)
alignaround = property(get_around, set_alignaround)
@@ -223,15 +219,20 @@ class Transform(Container):
ypos = Proxy("ypos")
xanchor = Proxy("xanchor")
yanchor = Proxy("yanchor")
xalign = Proxy("xalign")
yalign = Proxy("yalign")
around = Proxy("around")
around = Proxy("alignaround")
alignaround = Proxy("alignaround")
angle = Proxy("angle")
radius = Proxy("radius")
xaround = Proxy("xaround")
yaround = Proxy("yaround")
xanchoraround = Proxy("xanchoraround")
yanchoraround = Proxy("yanchoraround")
pos = Proxy("pos")
anchor = Proxy("anchor")
align = Proxy("align")
@@ -362,6 +363,9 @@ class Transform(Container):
def render(self, width, height, st, at):
# Should we perform clipping?
clipping = False
# Preserve the illusion of linear time.
if st == 0:
self.st_offset = self.st
@@ -388,8 +392,13 @@ class Transform(Container):
raise Exception("Transform does not have a child.")
cr = render(self.child, width, height, st - self.child_st_base, at)
# Compute the crop.
width, height = cr.get_size()
forward = IDENTITY
reverse = IDENTITY
xo = yo = 0
# Cropping.
crop = self.state.crop
if crop is None and self.state.corner1 and self.state.corner2:
x1, y1 = self.state.corner1
@@ -401,18 +410,24 @@ class Transform(Container):
maxy = max(y1, y2)
crop = (minx, miny, maxx - minx, maxy - miny)
# Handle cropping.
if crop:
cr = cr.subsurface(crop)
width, height = cr.get_size()
forward = IDENTITY
reverse = IDENTITY
xo = yo = 0
negative_xo, negative_yo, width, height = crop
xo = -negative_xo
yo = -negative_yo
clipping = True
# Handle size.
if self.state.rotate:
clipcr = renpy.display.render.Render(width, height)
clipcr.subpixel_blit(cr, (xo, yo))
clipcr.clipping = clipping
xo = yo = 0
cr = clipcr
clipping = False
# Size.
if self.state.size and self.state.size != (width, height):
nw, nh = self.state.size
xzoom = 1.0 * nw / width
@@ -420,11 +435,15 @@ class Transform(Container):
forward = forward * Matrix2D(1.0 / xzoom, 0, 0, 1.0 / yzoom)
reverse = Matrix2D(xzoom, 0, 0, yzoom) * reverse
width, height = self.state.size
xo = xo * xzoom
yo = yo * yzoom
# Rotation first.
if self.state.rotate is not None:
width, height = self.state.size
# Rotation.
if self.state.rotate is not None:
cw = width
ch = height
@@ -474,6 +493,8 @@ class Transform(Container):
rv.alpha = self.state.alpha
rv.clipping = clipping
if self.state.subpixel:
rv.subpixel_blit(cr, (xo, yo), main=True)
else:
@@ -993,7 +1014,7 @@ class Zoom(renpy.display.core.Displayable):
self.after_child = None
self.time_warp = time_warp
self.bilinear = bilinear and renpy.display.module.can_bilinear_scale
self.bilinear = bilinear
self.opaque = opaque
self.anim_timebase = anim_timebase
@@ -1075,7 +1096,8 @@ def zoom_core(rend, surf, rect, neww, newh, bilinear, opaque):
renpy.display.module.bilinear_scale(surf, dest,
sx, sy, sw, sh,
-x, -y, neww, newh)
-x, -y, neww, newh,
precise=1)
rv = renpy.display.render.Render(neww, newh, draw_func=draw, opaque=True)
@@ -1085,15 +1107,16 @@ def zoom_core(rend, surf, rect, neww, newh, bilinear, opaque):
if bilinear:
sx, sy, sw, sh = rect
scalesurf = pygame.Surface((neww, newh), surf.get_flags(), surf)
scalesurf = renpy.display.pgrender.surface((neww, newh), True)
renpy.display.module.bilinear_scale(surf, scalesurf,
sx, sy, sw, sh,
0, 0, neww, newh)
0, 0, neww, newh,
precise=1)
else:
renpy.display.render.blit_lock.acquire()
scalesurf = pygame.transform.scale(surf.subsurface(rect), (neww, newh))
scalesurf = renpy.display.pgrender.transform_scale(surf.subsurface(rect), (neww, newh))
renpy.display.render.blit_lock.release()
renpy.display.render.mutated_surface(scalesurf)
@@ -1134,7 +1157,7 @@ class FactorZoom(renpy.display.core.Displayable):
self.after_child = None
self.time_warp = time_warp
self.bilinear = bilinear and renpy.display.module.can_bilinear_scale
self.bilinear = bilinear
self.opaque = opaque
self.done = 0.0
self.anim_timebase = anim_timebase
@@ -1219,7 +1242,7 @@ class SizeZoom(renpy.display.core.Displayable):
self.after_child = None
self.time_warp = time_warp
self.bilinear = bilinear and renpy.display.module.can_bilinear_scale
self.bilinear = bilinear
self.opaque = opaque
self.done = 0.0
self.anim_timebase = anim_timebase
@@ -1321,10 +1344,6 @@ class RotoZoom(renpy.display.core.Displayable):
def render(self, w, h, st, at):
if not renpy.display.module.can_transform:
rv = renpy.display.render.Render(1, 1)
return rv
if self.rot_anim_timebase:
rot_time = at
else:
@@ -1413,8 +1432,9 @@ class RotoZoom(renpy.display.core.Displayable):
culcy = ch / 2.0 + ydx * dulcx + ydy * dulcy
renpy.display.module.transform(surf, target,
culcx, culcy,
xdx, ydx, xdy, ydy)
culcx, culcy,
xdx, ydx, xdy, ydy,
1.0, True)
rv = renpy.display.render.Render(dw, dh, draw_func=draw, opaque=self.opaque)
rv.depends_on(child_rend)
+162
View File
@@ -0,0 +1,162 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# This module deals with pygame-specific rendering tasks.
import pygame
import renpy
# This class is used to make a copy of a pygame module's functions. We
# can then access those functions, and be relatively sure that those
# have not changed.
class ModuleProxy(object):
def __init__(self, module):
self.__dict__.update(module.__dict__)
opygame = ModuleProxy(pygame)
opygame.display = ModuleProxy(pygame.display)
opygame.transform = ModuleProxy(pygame.transform)
opygame.image = ModuleProxy(pygame.image)
# Sample surfaces, with and without alpha.
sample_alpha = None
sample_noalpha = None
def set_mode(resolution, flags=0, depth=0):
"""
Sets the mode of the pygame screen, and creates the sample
surfaces.
"""
global sample_alpha
global sample_noalpha
rv = opygame.display.set_mode(resolution, flags, depth)
s = opygame.Surface((10, 10))
sample_alpha = s.convert_alpha(rv)
sample_noalpha = s.convert(rv)
return rv
set_mode_unscaled = set_mode
class Surface(opygame.Surface):
"""
This allows us to wrap around pygame's surface, to change
its mode, as necessary.
"""
def convert_alpha(self, surface=None):
return copy_surface_unscaled(self, True)
def convert(self, surface=None):
return copy_surface(self, False)
def copy(self):
return copy_surface(self, self)
def surface((width, height), alpha):
"""
Constructs a new surface. The allocated surface is actually a subsurface
of a surface that has a 1 pixel border in all directions.
`alpha` - True if the new surface should have an alpha channel.
"""
if isinstance(alpha, opygame.Surface):
alpha = alpha.get_masks()[3]
if alpha:
sample = sample_alpha
else:
sample = sample_noalpha
# We might not have initialized properly yet. This is enough
# to get us underway.
if sample is None:
sample = opygame.Surface((2, 2), opygame.SRCALPHA, 32)
surf = Surface((width + 2, height + 2), 0, sample)
return surf.subsurface((1, 1, width, height))
surface_unscaled = surface
def copy_surface(surf, alpha=True):
"""
Creates a copy of the surface.
"""
rv = surface_unscaled(surf.get_size(), alpha)
renpy.display.render.blit_lock.acquire()
rv.blit(surf, (0, 0))
renpy.display.render.blit_lock.release()
return rv
copy_surface_unscaled = copy_surface
# Wrapper around image loading.
def load_image(f, filename):
surf = opygame.image.load(f, filename)
return copy_surface_unscaled(surf)
load_image_unscaled = load_image
# Wrapper around functions we use from pygame.surface.
def flip(surf, horizontal, vertical):
surf = opygame.transform.flip(surf, horizontal, vertical)
return copy_surface_unscaled(surf)
flip_unscaled = flip
def rotozoom(surf, angle, zoom):
surf = opygame.transform.rotozoom(surf, angle, zoom)
return copy_surface_unscaled(surf)
rotozoom_unscaled = rotozoom
def transform_scale(surf, size):
surf = opygame.transform.scale(surf, size)
return copy_surface_unscaled(surf, surf)
transform_scale_unscaled = transform_scale
def transform_rotate(surf, angle):
surf = opygame.transform.rotate(surf, angle)
return copy_surface(surf)
transform_rotate_unscaled = transform_rotate
+35 -18
View File
@@ -20,11 +20,9 @@
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import collections
import time
import pygame
import threading
import math
import renpy
@@ -625,9 +623,6 @@ def draw_transformed(dest, clip, what, xo, yo, alpha, forward, reverse):
if not isinstance(what, Render):
if not renpy.display.module.can_alpha_transform:
return
# Figure out where the other corner of the transformed surface
# is on the screen.
sw, sh = what.get_size()
@@ -677,13 +672,13 @@ def draw_transformed(dest, clip, what, xo, yo, alpha, forward, reverse):
else:
dest = dest.subsurface((minx, miny, maxx - minx, maxy - miny))
renpy.display.module.alpha_transform(
renpy.display.module.transform(
what, dest,
cx, cy,
forward.xdx, forward.ydx,
forward.xdy, forward.ydy,
alpha)
alpha, True)
return
@@ -866,6 +861,28 @@ def mutated_surface(surf):
for i in clippers:
i.mutated.add(id(surf))
# Possible operations that can be done as part of a render.
# Blit the children one on top of another.
BLIT = 0
# Dissolve between the first and second children, using the dissolve
# parameter. The children need to be opaque.
OPAQUE_DISSOLVE = 1
# Dissolve between the first and second children, using the dissolve
# parameter.
ALPHA_DISSOLVE = 2
# Dissolve between the first and second children, using the third child
# as a mask image. The children need to be opaque.
OPAQUE_IMAGE_DISSOLVE = 3
# Dissolve between the first and second children, using the third child
# as a mask image.
ALPHA_IMAGE_DISSOLVE = 4
class Render(object):
@@ -902,6 +919,13 @@ class Render(object):
# len(self.parents) + len(self.depends_on_us)
self.refcount = 0
# The operation we're performing.
self.operation = BLIT
# If the operation is one of the DISSOLVES, this controls the
# amount of the new image we'll be using.
self.dissolve = 0.0
# These are Matrix2D objects used to transform the children of
# this render. If None, then no transformation is done. Otherwise,
@@ -1054,15 +1078,11 @@ class Render(object):
# Otherwise, draw the current surface.
if rv is None:
if alpha:
sample = renpy.game.interface.display.sample_surface
else:
sample = renpy.game.interface.display.window
# Compute opacity information, as necessary.
self.is_opaque()
rv = pygame.Surface((self.width, self.height), 0, sample)
rv = renpy.display.pgrender.surface((self.width, self.height), alpha)
draw(rv, None, self, 0, 0, False)
# Stash and return the surface.
@@ -1412,11 +1432,8 @@ class Render(object):
"""
Returns a canvas object that draws to this Render.
"""
surf = pygame.Surface(
(self.width, self.height),
renpy.game.interface.display.sample_surface.get_flags(),
renpy.game.interface.display.sample_surface)
surf = renpy.display.pgrender.surface((self.width, self.height), True)
mutated_surface(surf)
self.blit(surf, (0, 0))
+298 -282
View File
@@ -25,20 +25,15 @@ import os
import math
import pygame
import renpy
import renpy.display.pgrender as pgrender
# These need to be here before we mess with Pygame.
import _renpy_font
import _renpy
# Store this before we change it.
PygameSurface = pygame.Surface
try:
import _renpy_font as font_module
except ImportError:
import pygame.font as font_module
# This needs to be done before we mess too hard with pygame.
try:
import _renpy
except ImportError:
_renpy = None
# The factor we're scaling by.
factor = 1.0
@@ -59,80 +54,70 @@ def scale(n):
return n
def real_bilinear(src, size):
rv = pygame.Surface(size, 0, src)
rv = pgrender.surface_unscaled(size, src)
renpy.display.module.bilinear_scale(src, rv)
return rv
# Does pygame.transform.scale.
def real_transform_scale(surf, size):
global real_transform_scale
real_transform_scale = pygame.transform.scale
return real_transform_scale(surf, size)
return pgrender.transform_scale_unscaled(surf, size)
# Loads an image, without scaling it.
def image_load_unscaled(f, hint, convert=True):
rv = pygame.image.load(f, hint)
if convert:
rv = rv.convert_alpha()
rv = pgrender.load_image_unscaled(f, hint)
return rv
# Scales down a surface.
def surface_scale(full):
return full
# Saves an image without rescaling.
def image_save_unscaled(surf, dest):
pygame.image.save(surf, dest)
# Scales down a surface.
def surface_scale(full):
return full
if _renpy:
real_renpy_pixellate = _renpy.pixellate
real_renpy_transform = _renpy.transform
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.
"""
def real_smoothscale(src, size, dest=None):
"""
This scales src up or down to size. This uses both the pixellate
and the transform operations to handle the scaling.
"""
width, height = size
srcwidth, srcheight = src.get_size()
iwidth, iheight = srcwidth, srcheight
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,
)
if dest is None:
dest = pgrender.surface_unscaled(size, src)
if width == 0 or height == 0:
return dest
else:
real_smoothscale = pygame.transform.smoothscale
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 = pgrender.surface_unscaled((iwidth, iheight), 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,
precise=1,
)
return dest
smoothscale = real_smoothscale
@@ -190,12 +175,12 @@ 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.
take subsurfaces of anything bigger.
"""
w = min(i.get_width() for i in args)
@@ -212,6 +197,7 @@ def load_scaling():
rv.append(i)
return rv
def scale(n):
if n is None:
@@ -219,29 +205,17 @@ def load_scaling():
return int(n * factor)
def real_bilinear(src, size):
rv = PygameSurface(size, 0, src)
old_bilinear(src, rv)
return rv
def real_transform_scale(surf, size):
return old_transform_scale(surf, size)
def image_load_unscaled(f, hint, convert=True):
rv = old_image_load(f, hint)
if convert:
rv = rv.convert_alpha()
return rv
def surface_scale(full):
if scale_fast:
scaled = old_transform_scale(full, v2p(full.get_size()))
scaled = real_transform_scale(full, v2p(full.get_size()))
else:
scaled = real_smoothscale(full, v2p(full.get_size()))
return Surface(scaled, wh=full.get_size())
return ScaledSurface(scaled, wh=full.get_size())
# Project a tuple from virtual to physical coordinates.
def v2p(n):
if n is None:
@@ -249,6 +223,7 @@ def load_scaling():
return tuple([ int(i * factor) for i in n ])
# Similar, but include an extra pixel to deal with rounding.
def v2pplus(n):
@@ -257,6 +232,7 @@ def load_scaling():
return tuple([ int(i * factor) + k for i, k in zip(n, (0, 0, 1, 1)) ])
# Project a tuple from physical to virtual coordinates.
def p2v(n):
if n is None:
@@ -264,17 +240,37 @@ def load_scaling():
return tuple([ int(i / factor) for i in n ])
# Proxies a function call from a PygameSurface to a surface.
def set_mode((w, h), flags, bpp):
global screen
width = int(w * factor)
height = int(h * factor)
real_screen = pgrender.set_mode_unscaled((width, height), flags, bpp)
screen = ScaledSurface(real_screen, wh=(w, h))
return screen
pgrender.set_mode = set_mode
pygame.display.set_mode = set_mode
# Proxies a function call from a Surface to a pygame surface.
def proxy(name):
func = getattr(PygameSurface, name)
def rv(self, *args, **kwargs):
return func(self.surface, *args, **kwargs)
return rv
class Surface(object):
def __init__(self, what, flags=0, sample=None, wh=None):
# When scaling is enabled, objects of this class are returned from
# pgrender.surface instead of pygame surfaces.
class ScaledSurface(object):
def __init__(self, what, alpha=True, wh=None):
if isinstance(what, PygameSurface):
self.surface = what
@@ -297,20 +293,14 @@ def load_scaling():
w = int(w * factor)
h = int(h * factor)
if sample is None:
sample = screen
if not isinstance(sample, PygameSurface):
sample = sample.surface
self.surface = PygameSurface((w, h), flags, sample)
self.surface = pgrender.surface_unscaled((w, h), alpha)
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.
@@ -327,6 +317,7 @@ def load_scaling():
return (x0 - self.physx, y0 - self.physy)
def transform_rect(self, (x, y, w, h)):
"""
Converts a virtual rectangle into a physical one.
@@ -353,8 +344,9 @@ def load_scaling():
def __repr__(self):
return "<scale.Surface %r %r>" % (self.get_size(), self.surface)
return "<ScaledSurface %r %r>" % (self.get_size(), self.surface)
def blit(self, s, destpos, sourcerect=None):
if sourcerect is None:
@@ -367,25 +359,19 @@ def load_scaling():
self.transform_pos(destpos),
self.transform_rect(sourcerect))
def convert(self, *args):
if args:
args = (args[0].surface,)
return Surface(self.surface.convert(*args), wh=self.get_size())
def convert_alpha(self, *args):
if args:
args = (args[0].surface,)
return Surface(self.surface.convert_alpha(*args), wh=self.get_size())
def copy(self):
return Surface(self.surface.copy(), wh=self.get_size())
return ScaledSurface(self.surface.copy(), wh=self.get_size())
def fill(self, color):
self.surface.fill(color)
def get_alpha(self):
return self.surface.get_alpha()
def get_at(self, pos):
x, y = self.transform_pos(pos)
w, h = self.surface.get_size()
@@ -393,19 +379,13 @@ def load_scaling():
return self.surface.get_at((min(x, w - 1), min(y, h - 1)))
get_colorkey = proxy("get_colorkey")
set_colorkey = proxy("set_colorkey")
get_alpha = proxy("get_alpha")
set_alpha = proxy("set_alpha")
get_locked = proxy("get_locked")
get_locks = proxy("get_locks")
map_rgb = proxy("map_rgb")
unmap_rgb = proxy("unmap_rgb")
get_bytesize = proxy("get_bytesize")
get_bitsize = proxy("get_bitsize")
get_flags = proxy("get_flags")
get_pitch = proxy("get_pitch")
get_masks = proxy("get_masks")
set_masks = proxy("set_masks")
get_shifts = proxy("get_shifts")
set_shifts = proxy("set_shifts")
@@ -429,7 +409,7 @@ def load_scaling():
def get_size(self):
return (self.width, self.height)
def set_alpha(self, alpha, flags):
self.surface.set_alpha(alpha, flags)
@@ -438,7 +418,7 @@ def load_scaling():
prect = self.transform_rect(rect)
surf = self.surface.subsurface(prect)
rv = Surface(surf, wh=rect[2:])
rv = ScaledSurface(surf, wh=rect[2:])
vx, vy, vw, vh = rect
px, py, pw, ph = prect
@@ -459,9 +439,6 @@ def load_scaling():
def unlock(self):
pass
def mustlock(self):
return False
def get_locked(self):
return False
@@ -474,23 +451,27 @@ def load_scaling():
return rv
pygame.Surface = Surface
pgrender.surface = ScaledSurface
old_set_mode = pygame.display.set_mode
def set_mode((w, h), flags, bpp):
def copy_surface(surf, alpha=True):
# We don't need to unbox alpha, since all relevant methods
# are proxied.
global screen
new_surf = pgrender.copy_surface_unscaled(surf.surface, alpha)
return ScaledSurface(new_surf, wh=(surf.width, surf.height))
width = int(w * factor)
height = int(h * factor)
pgrender.copy_surface = copy_surface
screen = Surface(old_set_mode((width, height), flags, bpp), wh=(w, h))
return screen
pygame.display.set_mode = set_mode
def pygame_surface(size, flags, sample):
return ScaledSurface(size, sample)
pygame.Surface = pygame_surface
old_update = pygame.display.update
def update(rects=None):
@@ -505,83 +486,70 @@ def load_scaling():
pygame.display.update = update
def get_surface():
return screen
pygame.display.get_surface = get_surface
old_image_load = pygame.image.load
def image_load(*args, **kwargs):
full = old_image_load(*args, **kwargs)
full = full.convert_alpha()
def load_image(f, filename):
full = pgrender.load_image_unscaled(f, filename)
return surface_scale(full)
pygame.image.load = image_load
old_transform_scale = pygame.transform.scale
pgrender.load_image = load_image
pygame.image.load = load_image
def transform_scale(surf, size):
rv = old_transform_scale(surf.surface, v2p(size))
rv = Surface(rv, wh=size)
rv = pgrender.transform_scale_unscaled(surf.surface, v2p(size))
rv = ScaledSurface(rv, wh=size)
return rv
pgrender.transform_scale = transform_scale
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):
return Surface(old_transform_flip(surf.surface, xbool, ybool),
wh=surf.get_size())
new_surf = pgrender.flip_unscaled(surf.surface, xbool, ybool)
return ScaledSurface(new_surf, wh=surf.get_size())
pgrender.flip = transform_flip
pygame.transform.flip = transform_flip
old_transform_rotate = pygame.transform.rotate
def transform_rotate(surf, angle):
return Surface(old_transform_flip(surf.surface, angle))
new_surf = pgrender.transform_rotate_unscaled(surf.surface, angle)
return ScaledSurface(new_surf)
pgrender.transform_rotate = transform_rotate
pygame.transform.rotate = transform_rotate
old_transform_rotozoom = pygame.transform.rotozoom
def transform_rotozoom(surf, angle, scale):
return Surface(old_transform_flip(surf.surface, angle, scale))
def rotozoom(surf, angle, scale):
new_surf = pgrender.rotozoom(surf.surface, angle, scale)
return ScaledSurface(new_surf)
pygame.transform.rotozoom = transform_rotozoom
pgrender.rotozoom = rotozoom
pygame.transform.rotozoom = rotozoom
# Ignoring scale2x and chop. The former due to a pending api change,
# the latter due to general uselessness.
PygameFont = font_module.Font
PygameFont = _renpy_font.Font
class Font(object):
def __init__(self, o, size):
self.font = PygameFont(o, int(size * factor))
def __init__(self, o, size, index):
self.font = PygameFont(o, int(size * factor), index)
def render(self, *args):
return Surface(self.font.render(*args))
return ScaledSurface(self.font.render(*args))
def size(self, text):
return p2v(self.font.size(text))
@@ -619,18 +587,21 @@ def load_scaling():
def set_expand(self, value):
self.font.set_expand(value * factor)
font_module.Font = Font
_renpy_font.Font = Font
old_image_save = pygame.image.save
def image_save(surf, dest):
surf = old_transform_scale(surf.surface, surf.get_size())
surf = pgrender.transform_scale_unscaled(surf.surface, surf.get_size())
old_image_save(surf, dest)
pygame.image.save = image_save
def image_save_unscaled(surf, dest):
old_image_save(surf.surface, dest)
old_mouse_get_pos = pygame.mouse.get_pos
@@ -639,140 +610,182 @@ def load_scaling():
pygame.mouse.get_pos = mouse_get_pos
def scale_event(ev):
if ev.type == pygame.MOUSEMOTION:
return pygame.event.Event(ev.type, pos=p2v(ev.pos), rel=p2v(ev.rel), buttons=ev.buttons)
elif ev.type == pygame.MOUSEBUTTONUP or ev.type == pygame.MOUSEBUTTONDOWN:
return pygame.event.Event(ev.type, pos=p2v(ev.pos), button=ev.button)
else:
return ev
if _renpy is not None:
old_save_png = _renpy.save_png
def save_png(surf, dest, compress=-1):
surf = old_transform_scale(surf.surface, surf.get_size())
old_save_png(surf, dest, compress=compress)
_renpy.save_png = save_png
old_event_poll = pygame.event.poll
def event_poll():
ev = old_event_poll()
return scale_event(ev)
pygame.event.poll = event_poll
old_event_wait = pygame.event.wait
def event_wait():
ev = old_event_wait()
return scale_event(ev)
pygame.event.wait = event_wait
old_event_get = pygame.event.get
def event_get(*args):
rv = old_event_get(*args)
if rv:
rv[-1] = scale_event(rv[-1])
return rv
pygame.event.get = event_get
old_pixellate = _renpy.pixellate
old_save_png = _renpy.save_png
def pixellate(pysrc, pydst, avgwidth, avgheight, outwidth, outheight):
ow = max(int(outwidth * factor), 1)
oh = max(int(outheight * factor), 1)
def save_png(surf, dest, compress=-1):
surf = pgrender.transform_scale_unscaled(surf.surface, surf.get_size())
old_save_png(surf, dest, compress=compress)
owf = 1.0 * ow / outwidth
ohf = 1.0 * oh / outheight
old_pixellate(pysrc.surface, pydst.surface,
max(avgwidth * owf, 1),
max(avgheight * ohf, 1),
ow, oh)
_renpy.pixellate = pixellate
old_map = _renpy.map
def map(pysrc, pydst, r, g, b, a):
pysrc, pydst = same_size(pysrc.surface, pydst.surface)
old_map(pysrc, pydst, r, g, b, a)
_renpy.map = map
_renpy.save_png = save_png
old_linmap = _renpy.linmap
old_pixellate = _renpy.pixellate
def linmap(pysrc, pydst, r, g, b, a):
pysrc, pydst = same_size(pysrc.surface, pydst.surface)
old_linmap(pysrc, pydst, r, g, b, a)
def pixellate(pysrc, pydst, avgwidth, avgheight, outwidth, outheight):
ow = max(int(outwidth * factor), 1)
oh = max(int(outheight * factor), 1)
_renpy.linmap = linmap
owf = 1.0 * ow / outwidth
ohf = 1.0 * oh / outheight
old_pixellate(pysrc.surface, pydst.surface,
max(avgwidth * owf, 1),
max(avgheight * ohf, 1),
ow, oh)
_renpy.pixellate = pixellate
old_bilinear = _renpy.bilinear
def bilinear(pysrc, pydst, source_xoff=0.0, source_yoff=0.0,
source_width=None, source_height=None,
dest_xoff=0.0, dest_yoff=0.0, dest_width=None, dest_height=None):
old_map = _renpy.map
def f(n):
if n is None:
return n
return n * factor
source_xoff = f(source_xoff)
source_yoff = f(source_yoff)
source_width = f(source_width)
source_height = f(source_height)
def map(pysrc, pydst, r, g, b, a):
pysrc, pydst = same_size(pysrc.surface, pydst.surface)
old_map(pysrc, pydst, r, g, b, a)
dest_xoff = f(dest_xoff)
dest_yoff = f(dest_yoff)
dest_width = f(dest_width)
dest_height = f(dest_height)
old_bilinear(pysrc.surface, pydst.surface,
source_xoff=source_xoff,
source_yoff=source_yoff,
source_width=source_width,
source_height=source_height,
dest_xoff=dest_xoff,
dest_yoff=dest_yoff,
dest_width=dest_width,
dest_height=dest_height)
_renpy.bilinear = bilinear
old_alpha_munge = _renpy.alpha_munge
def alpha_munge(pysrc, pydst, srcchan, dstchan, amap):
pysrc, pydst = same_size(pysrc.surface, pydst.surface)
old_alpha_munge(pysrc, pydst, srcchan, dstchan, amap)
_renpy.alpha_munge = alpha_munge
_renpy.map = map
old_transform = _renpy.transform
old_linmap = _renpy.linmap
def transform(pysrc, pydst, corner_x, corner_y,
xdx, ydx, xdy, ydy, a=1.0):
old_transform(pysrc.surface, pydst.surface,
corner_x * factor, corner_y * factor,
xdx, ydx, xdy, ydy, a)
_renpy.transform = transform
def linmap(pysrc, pydst, r, g, b, a):
pysrc, pydst = same_size(pysrc.surface, pydst.surface)
old_linmap(pysrc, pydst, r, g, b, a)
old_subpixel = _renpy.subpixel
def subpixel(pysrc, pydst, x, y, shift):
return old_subpixel(pysrc.surface, pydst.surface, x * factor, y * factor, shift)
_renpy.linmap = linmap
_renpy.subpixel = subpixel
old_blend = _renpy.blend
old_bilinear = _renpy.bilinear
def bilinear(pysrc, pydst, source_xoff=0.0, source_yoff=0.0,
source_width=None, source_height=None,
dest_xoff=0.0, dest_yoff=0.0, dest_width=None,
dest_height=None, precise=0):
def blend(pysrca, pysrcb, pydst, alpha):
pysrca, pysrcb, pydst = same_size(pysrca.surface, pysrcb.surface, pydst.surface)
old_blend(pysrca, pysrcb, pydst, alpha)
def f(n):
if n is None:
return n
return n * factor
_renpy.blend = blend
old_imageblend = _renpy.imageblend
source_xoff = f(source_xoff)
source_yoff = f(source_yoff)
source_width = f(source_width)
source_height = f(source_height)
def imageblend(pysrca, pysrcb, pydst, pyimg, aoff, amap):
pysrca, pysrcb, pydst, pyimg = same_size(pysrca.surface, pysrcb.surface, pydst.surface, pyimg.surface)
old_imageblend(pysrca, pysrcb, pydst, pyimg, aoff, amap)
dest_xoff = f(dest_xoff)
dest_yoff = f(dest_yoff)
dest_width = f(dest_width)
dest_height = f(dest_height)
_renpy.imageblend = imageblend
old_bilinear(pysrc.surface, pydst.surface,
source_xoff=source_xoff,
source_yoff=source_yoff,
source_width=source_width,
source_height=source_height,
dest_xoff=dest_xoff,
dest_yoff=dest_yoff,
dest_width=dest_width,
dest_height=dest_height,
precise=precise)
old_colormatrix = _renpy.colormatrix
_renpy.bilinear = bilinear
def colormatrix(src, dst, *args):
src, dst = same_size(src.surface, dst.surface)
old_colormatrix(src, dst, *args)
_renpy.colormatrix = colormatrix
old_alpha_munge = _renpy.alpha_munge
def alpha_munge(pysrc, pydst, srcchan, dstchan, amap):
pysrc, pydst = same_size(pysrc.surface, pydst.surface)
old_alpha_munge(pysrc, pydst, srcchan, dstchan, amap)
_renpy.alpha_munge = alpha_munge
old_transform = _renpy.transform
def transform(pysrc, pydst, corner_x, corner_y,
xdx, ydx, xdy, ydy, a=1.0, precise=0):
old_transform(pysrc.surface, pydst.surface,
corner_x * factor, corner_y * factor,
xdx, ydx, xdy, ydy, a, precise)
_renpy.transform = transform
old_subpixel = _renpy.subpixel
def subpixel(pysrc, pydst, x, y, shift):
return old_subpixel(pysrc.surface, pydst.surface, x * factor, y * factor, shift)
_renpy.subpixel = subpixel
old_blend = _renpy.blend
def blend(pysrca, pysrcb, pydst, 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):
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):
@@ -789,15 +802,18 @@ def load_scaling():
else:
return None
def draw_wrap(f):
def newf(surf, color, *args, **kwargs):
f(surf.surface, color, *draw_scale(args), **draw_scale(kwargs))
return newf
def arc_wrap(f):
def newf(surf, color, Rect, start_angle, stop_angle, width=1):
f(surf.surface, color, draw_scale(Rect), start_angle, stop_angle, draw_scale(width))
return newf
pygame.draw.rect = draw_wrap(pygame.draw.rect)
pygame.draw.polygon = draw_wrap(pygame.draw.polygon)
@@ -820,7 +836,7 @@ def load_scaling():
if rv is None:
return rv
else:
return Surface(rv, wh=size)
return ScaledSurface(rv, wh=size)
# Now, put everything from this function's namespace into the
# module namespace.
+35 -29
View File
@@ -19,9 +19,6 @@
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import pygame
# from pygame.constants import *
import re
import renpy
import sys
@@ -151,23 +148,15 @@ class TextStyle(object):
color = (r, g, b, 255)
surf = font.render(text, antialias, color)
rv = renpy.display.pgrender.copy_surface(surf)
if self.strikethrough:
sw, sh = surf.get_size()
soh = max(sh / 10, 1)
surf.subsurface((0, sh / 2, sw, soh)).fill(color)
rv.subsurface((0, sh / 2, sw, soh)).fill(color)
if a != 255 and renpy.display.module.can_linmap:
if not surf.get_masks()[3]:
surf = surf.convert_alpha(renpy.game.interface.display.window)
rv = pygame.Surface(surf.get_size(), surf.get_flags(), surf)
renpy.display.module.linmap(surf, rv, 256, 256, 256, a + 1)
else:
rv = surf
if a != 255:
renpy.display.module.linmap(rv, rv, 256, 256, 256, a + 1)
renpy.display.render.mutated_surface(rv)
@@ -464,8 +453,6 @@ def greedy_text_layout(triples, width, style):
def subtitle_text_layout_core(triples, width, style, soft, n, justify):
sizecache = { }
lines = [ ]
line = [ ]
@@ -669,6 +656,8 @@ class Text(renpy.display.core.Displayable):
self.tokens = None
# The duration of each pause, or None if the pause is infinite.
self.pause_lengths = [ ]
self.update(redraw=False)
@@ -722,24 +711,44 @@ class Text(renpy.display.core.Displayable):
self.no_wait_done = False
self.pauses = 0
self.pause_lengths = [ ]
for i in self.tokens[0]:
type, text = i
if type == "tag":
if text == "p" or text.startswith("p="):
new_tokens.append(("tag", 'w' + text[1:]))
if text == "p":
new_tokens.append(("tag", 'w'))
new_tokens.append(("newline", "\n"))
self.pauses += 1
self.pause_lengths.append(None)
continue
elif text.startswith("p="):
new_tokens.append(("tag", 'w=' + text[2:]))
new_tokens.append(("newline", "\n"))
self.pauses += 1
self.pause_lengths.append(float(text[2:]))
continue
elif text == "nw":
self.no_wait = True
elif text == "fast":
self.no_wait = False
fasts += 1
self.pauses = 0
elif text == "w" or text.startswith("w="):
self.pause_lengths = [ ]
elif text == "w":
self.pauses += 1
self.pause_lengths.append(None)
elif text.startswith("w="):
self.pauses += 1
self.pause_lengths.append(float(text[2:]))
new_tokens.append(i)
@@ -803,7 +812,6 @@ class Text(renpy.display.core.Displayable):
for kind, i in tliter:
if kind == "tag" and i.startswith("image="):
m = re.match(r'image=(.*)', i)
@@ -811,7 +819,7 @@ class Text(renpy.display.core.Displayable):
if not m:
raise Exception('Image tag %s could not be parsed.' % i)
i = renpy.display.im.image(m.group(1))
i = renpy.easy.displayable(m.group(1))
ntl.append(("widget", i))
self.children.append(i)
@@ -913,10 +921,10 @@ class Text(renpy.display.core.Displayable):
self.laidout_hyperlinks = [ ]
if not self.text:
text = " "
else:
text = self.text
# if not self.text:
# text = " "
# else:
# text = self.text
# for i in re.split(r'( |\{[^{}]+\}|\{\{|\n)', text):
@@ -1276,8 +1284,6 @@ class Text(renpy.display.core.Displayable):
text_align = self.style.text_align
justify = self.style.justify
lines = len(self.laidout)
for line, line_height, line_width, last in zip(self.laidout, self.laidout_lineheights, self.laidout_linewidths, self.laidout_lines_last):
if justify and not last:
empty_space = (self.laidout_width - line_width - indent)
+233 -240
View File
@@ -37,8 +37,6 @@
import renpy
from renpy.display.render import render
import pygame
from pygame.constants import *
class Transition(renpy.display.core.Displayable):
@@ -243,18 +241,10 @@ class Pixellate(Transition):
steps in each direction.
"""
nosave = [ 'surface', 'surface_size' ]
surface = None
surface_size = None
def __init__(self, time, steps, old_widget=None, new_widget=None, **properties):
time = float(time)
if not renpy.display.module.can_pixellate:
time = 0
super(Pixellate, self).__init__(time, **properties)
self.time = time
@@ -287,18 +277,17 @@ class Pixellate(Transition):
rdr = render(visible, width, height, st, at)
surf = rdr.pygame_surface(False)
if surf.get_size() != self.surface_size:
self.surface_size = surf.get_size()
self.surface = pygame.Surface(self.surface_size, surf.get_flags(), surf)
size = surf.get_size()
newsurf = renpy.display.pgrender.surface(size, False)
px = 2 ** step
renpy.display.module.pixellate(surf, self.surface, px, px, px, px)
renpy.display.render.mutated_surface(self.surface)
renpy.display.module.pixellate(surf, newsurf, px, px, px, px)
renpy.display.render.mutated_surface(newsurf)
rv = renpy.display.render.Render(rdr.width, rdr.height)
rv.blit(self.surface, (0, 0))
rv.blit(newsurf, (0, 0))
rv.depends_on(rdr)
renpy.display.render.redraw(self, 0)
@@ -336,7 +325,7 @@ class Dissolve(Transition):
if renpy.game.less_updates:
return null_render(self, width, height, st, at)
if st >= self.time or not renpy.display.module.can_blend:
if st >= self.time:
self.events = True
return render(self.new_widget, width, height, st, at)
@@ -372,10 +361,234 @@ class Dissolve(Transition):
if self.alpha:
rv = renpy.display.render.Render(width, height)
surf = pygame.Surface((width, height), bottom_surface.get_flags(), bottom_surface)
surf = renpy.display.pgrender.surface((width, height), True)
draw(surf, 0, 0)
renpy.display.render.mutated_surface(surf)
rv = renpy.display.render.Render(width, height)
rv.blit(surf, (0, 0))
else:
rv = renpy.display.render.Render(width, height, draw_func=draw, opaque=True)
rv.depends_on(top, True)
rv.depends_on(bottom)
return rv
class ImageDissolve(Transition):
"""
This dissolves the old scene into the new scene, using an image
to control the dissolve process.
A list of values is used to control this mapping. This list of
values consists 256 fully transparent values, a ramp (of a
specified number of steps) from full transparency to full opacity,
and 256 fully opaque values. A 256 entry window is slid over this
list, and the values found within are used to map the red channel
of the image onto the opacity of the new scene.
Basically, this means that while pixels come in first, black last,
and the ramp controls the sharpness of the transition.
@param image: The image that will be used to control this
transition. The image should be the same size as the scene being
dissolved.
@param time: The amount of time the dissolve will take.
@param ramplen: The number of pixels of ramp to use. This defaults
to 8.
@param ramptype: Type of alpha ramp. Possible types are: linear, cube,
dcube, mcube. Default is linear. Non-linear types must have
ramplen >= 8. "cube": Ease in, sharp out. "dcube": Sharp in, sharp out.
"mcube": Ease in, ease out.
@param ramp: If given, this is expected to be a sequence of
integers in the range 0 to 255. This sequence explicitly gives the
ramp to be used. If given, this overrides ramplen and ramptype.
@param reverse: This reverses the ramp and the direction of the window
slide. When True, black pixels dissolve in first, and while pixels come
in last.
"""
__version__ = 1
def after_upgrade(self, version):
if version < 1:
self.alpha = False
def generate_ramp(self, ramplen, ramptype, explicit_ramp, reverse):
"""
Precomputes the ramp.
"""
ramp = '\x00' * 256
if explicit_ramp is not None:
for i in explicit_ramp:
ramp += chr(i)
else:
if ramptype == 'cube':
# make sure ramplen is big enough, to avoid div-by-0 errors
# Not much point in nonlinear if the size is that small, anyway
if ramplen >= 8:
table = []
for i in range(ramplen):
table.append(i * i * i)
scale = max(table) / 255.0
for i in range(ramplen):
#print i, table[i], table[i] / scale
ramp += chr(int(table[i] / scale))
else:
ramptype = 'linear'
elif ramptype == 'dcube':
if ramplen >= 8:
table = []
for i in range(ramplen / 2 - ramplen, ramplen / 2):
table.append(i * i * i)
adj = abs(min(table))
for i in range(len(table)):
table[i] += adj
scale = max(table) / 255.0
#print "scale:", scale
for i in range(ramplen):
#print i, table[i], table[i] / scale
ramp += chr(int(table[i] / scale))
else:
ramptype = 'linear'
elif ramptype == 'mcube':
if ramplen >= 8:
ramplen = (ramplen / 2) * 2 # make sure it's even
table = []
for i in range(ramplen / 2):
table.append(i * i * i)
adj = table[-1]
tmptable = []
for i in table:
tmptable.append(i)
for i in range(1, len(table) + 1):
tmptable.append(abs(table[len(table) - i] - adj) + adj)
table = tmptable
scale = max(table) / 255.0
#print "scale:", scale
for i in range(ramplen):
#print i, table[i], table[i] / scale
ramp += chr(int(table[i] / scale))
else:
ramptype = 'linear'
if ramptype == 'linear':
for i in range(ramplen):
ramp += chr(255 * i / ramplen)
ramp += '\xff' * 256
old = 0
for i in ramp:
i = ord(i)
if i < old:
self.can_fast = False
break
old = i
else:
self.can_fast = True
if reverse:
ramp = list(ramp)
ramp.reverse()
ramp = ''.join(ramp)
return ramp
def __init__(self, image, time, ramplen=8, ramptype='linear', ramp=None, reverse=False, alpha=False,
old_widget=None, new_widget=None, **properties):
super(ImageDissolve, self).__init__(time, **properties)
self.time = time
self.old_widget = old_widget
self.new_widget = new_widget
self.events = False
self.alpha = alpha
self.image = renpy.display.im.image(image)
if ramp is not None:
ramplen = len(ramp)
self.ramp = self.generate_ramp(ramplen, ramptype, ramp, reverse)
self.steps = ramplen + 256
self.reverse = reverse
def visit(self):
return super(ImageDissolve, self).visit() + [ self.image ]
def render(self, width, height, st, at):
if renpy.game.less_updates:
return null_render(self, width, height, st, at)
if st >= self.time:
self.events = True
return render(self.new_widget, width, height, st, at)
image = renpy.display.im.cache.get(self.image)
if st < self.time:
renpy.display.render.redraw(self, 0)
step = int(self.steps * st / self.time)
if self.reverse:
step = self.steps - step
ramp = self.ramp[step:step+256]
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)
iw, ih = image.get_size()
width = min(bottom.width, top.width, iw)
height = min(bottom.height, top.height, ih)
def draw(dest, x, y):
dw, dh = dest.get_size()
w = min(dw, width + x)
h = min(dh, height + y)
renpy.display.module.imageblend(
bottom_surface.subsurface((-x, -y, w, h)),
top_surface.subsurface((-x, -y, w, h)),
dest.subsurface((0, 0, w, h)),
image.subsurface((-x, -y, w, h)),
ramp)
if self.alpha:
surf = renpy.display.pgrender.surface((width, height), True)
draw(surf, 0, 0)
renpy.display.render.mutated_surface(surf)
rv = renpy.display.render.Render(width, height)
rv.blit(surf, (0, 0))
else:
@@ -882,226 +1095,6 @@ def MoveTransition(delay, old_widget=None, new_widget=None, factory=None, enter
return rv
class ImageDissolve(Transition):
"""
This dissolves the old scene into the new scene, using an image
to control the dissolve process.
A list of values is used to control this mapping. This list of
values consists 256 fully transparent values, a ramp (of a
specified number of steps) from full transparency to full opacity,
and 256 fully opaque values. A 256 entry window is slid over this
list, and the values found within are used to map the red channel
of the image onto the opacity of the new scene.
Basically, this means that while pixels come in first, black last,
and the ramp controls the sharpness of the transition.
@param image: The image that will be used to control this
transition. The image should be the same size as the scene being
dissolved.
@param time: The amount of time the dissolve will take.
@param ramplen: The number of pixels of ramp to use. This defaults
to 8.
@param ramptype: Type of alpha ramp. Possible types are: linear, cube,
dcube, mcube. Default is linear. Non-linear types must have
ramplen >= 8. "cube": Ease in, sharp out. "dcube": Sharp in, sharp out.
"mcube": Ease in, ease out.
@param ramp: If given, this is expected to be a sequence of
integers in the range 0 to 255. This sequence explicitly gives the
ramp to be used. If given, this overrides ramplen and ramptype.
@param reverse: This reverses the ramp and the direction of the window
slide. When True, black pixels dissolve in first, and while pixels come
in last.
"""
__version__ = 1
def after_upgrade(self, version):
if version < 1:
self.alpha = False
def generate_ramp(self, ramplen, ramptype, explicit_ramp, reverse):
"""
Precomputes the ramp.
"""
ramp = '\x00' * 256
if explicit_ramp is not None:
for i in explicit_ramp:
ramp += chr(i)
else:
if ramptype == 'cube':
# make sure ramplen is big enough, to avoid div-by-0 errors
# Not much point in nonlinear if the size is that small, anyway
if ramplen >= 8:
table = []
for i in range(ramplen):
table.append(i * i * i)
scale = max(table) / 255.0
for i in range(ramplen):
#print i, table[i], table[i] / scale
ramp += chr(int(table[i] / scale))
else:
ramptype = 'linear'
elif ramptype == 'dcube':
if ramplen >= 8:
table = []
for i in range(ramplen / 2 - ramplen, ramplen / 2):
table.append(i * i * i)
adj = abs(min(table))
for i in range(len(table)):
table[i] += adj
scale = max(table) / 255.0
#print "scale:", scale
for i in range(ramplen):
#print i, table[i], table[i] / scale
ramp += chr(int(table[i] / scale))
else:
ramptype = 'linear'
elif ramptype == 'mcube':
if ramplen >= 8:
ramplen = (ramplen / 2) * 2 # make sure it's even
table = []
for i in range(ramplen / 2):
table.append(i * i * i)
adj = table[-1]
tmptable = []
for i in table:
tmptable.append(i)
for i in range(1, len(table) + 1):
tmptable.append(abs(table[len(table) - i] - adj) + adj)
table = tmptable
scale = max(table) / 255.0
#print "scale:", scale
for i in range(ramplen):
#print i, table[i], table[i] / scale
ramp += chr(int(table[i] / scale))
else:
ramptype = 'linear'
if ramptype == 'linear':
for i in range(ramplen):
ramp += chr(255 * i / ramplen)
ramp += '\xff' * 256
old = 0
for i in ramp:
i = ord(i)
if i < old:
self.can_fast = False
break
old = i
else:
self.can_fast = True
if reverse:
ramp = list(ramp)
ramp.reverse()
ramp = ''.join(ramp)
return ramp
def __init__(self, image, time, ramplen=8, ramptype='linear', ramp=None, reverse=False, alpha=False,
old_widget=None, new_widget=None, **properties):
super(ImageDissolve, self).__init__(time, **properties)
self.time = time
self.old_widget = old_widget
self.new_widget = new_widget
self.events = False
self.alpha = alpha
self.image = renpy.display.im.image(image)
if ramp is not None:
ramplen = len(ramp)
self.ramp = self.generate_ramp(ramplen, ramptype, ramp, reverse)
self.steps = ramplen + 256
self.reverse = reverse
def visit(self):
return super(ImageDissolve, self).visit() + [ self.image ]
def render(self, width, height, st, at):
if renpy.game.less_updates:
return null_render(self, width, height, st, at)
if st >= self.time or not renpy.display.module.can_imageblend:
self.events = True
return render(self.new_widget, width, height, st, at)
image = renpy.display.im.cache.get(self.image)
if st < self.time:
renpy.display.render.redraw(self, 0)
step = int(self.steps * st / self.time)
if self.reverse:
step = self.steps - step
ramp = self.ramp[step:step+256]
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)
iw, ih = image.get_size()
width = min(bottom.width, top.width, iw)
height = min(bottom.height, top.height, ih)
def draw(dest, x, y):
dw, dh = dest.get_size()
w = min(dw, width + x)
h = min(dh, height + y)
renpy.display.module.imageblend(
bottom_surface.subsurface((-x, -y, w, h)),
top_surface.subsurface((-x, -y, w, h)),
dest.subsurface((0, 0, w, h)),
image.subsurface((-x, -y, w, h)),
ramp)
if self.alpha:
rv = renpy.display.render.Render(width, height)
surf = pygame.Surface((width, height), bottom_surface.get_flags(), bottom_surface)
draw(surf, 0, 0)
renpy.display.render.mutated_surface(surf)
rv.blit(surf, (0, 0))
else:
rv = renpy.display.render.Render(width, height, draw_func=draw, opaque=True)
rv.depends_on(top, True)
rv.depends_on(bottom)
return rv
def ComposeTransition(trans, before=None, after=None, new_widget=None, old_widget=None):
if before is not None:
+1 -6
View File
@@ -20,9 +20,6 @@
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import renpy
from renpy.display.render import render
import pygame
import sys # for maxint
# True if the movie that is currently displaying is in fullscreen mode,
# False if it's a smaller size.
@@ -91,8 +88,6 @@ def interact():
the movie should be displayed fullscreen or not.
"""
playing = renpy.audio.music.get_playing("movie")
if fullscreen and renpy.audio.music.get_playing("movie"):
return True
else:
@@ -125,7 +120,7 @@ class Movie(renpy.display.core.Displayable):
playing = renpy.audio.music.get_playing("movie")
if (surface is None) or (surface.get_size() != size) or (surface_file != playing):
surface = pygame.Surface(size, 0, renpy.game.interface.display.window)
surface = renpy.display.pgrender.surface(size, False)
surface_file = playing
surface.fill((0, 0, 0, 255))
+2 -2
View File
@@ -23,7 +23,7 @@
# renpy object, as well as the context object.
import renpy
import copy
class Delete(object):
pass
@@ -176,7 +176,7 @@ class Context(renpy.object.Object):
Pops all levels of the dynamic stack. Called when we jump
out of a context.
"""
while self.dynamic_stack:
self.pop_dynamic()
+40 -16
View File
@@ -47,7 +47,31 @@ import renpy.audio.sound as sound
import renpy.audio.music as music
import time
import sets
def public_api():
"""
This does nothing, except to make the pyflakes warnings about
unused imports go away.
"""
ParameterizedText
register_sfont, register_mudgefont, register_bmfont
Keymap
Minigame
curry, partial
play
movie_start_fullscreen, movie_start_displayable, movie_stop
load, save, list_saved_games, can_load, rename_save, unlink_save, scan_saved_game
eval
random
atl_warper
show_display_say, predict_show_display_say, display_say
sound
music
time
del public_api
import collections
@@ -985,7 +1009,6 @@ def launch_editor(filenames, line=1, transient=0):
statement.
"""
import sys
import renpy.subprocess as subprocess
import os.path
@@ -995,13 +1018,11 @@ def launch_editor(filenames, line=1, transient=0):
if not len(filenames):
return
shell = True
filenames = [ shell_escape(os.path.normpath(i)) for i in filenames ]
filename = filenames[0]
allfiles = config.editor_file_separator.join(filenames)
otherfiles = config.editor_file_separator.join(filenames[1:])
allfiles = renpy.config.editor_file_separator.join(filenames)
otherfiles = renpy.config.editor_file_separator.join(filenames[1:])
subs = dict(filename=filename, line=line, allfiles=allfiles, otherfiles=otherfiles)
if transient and (renpy.config.editor_transient is not None):
@@ -1067,7 +1088,10 @@ def do_reshow_say(who, what, interact=False):
curried_do_reshow_say = curry(do_reshow_say)
def get_reshow_say(**kwargs):
return curried_do_reshow_say(store._last_say_who, store._last_say_what, **kwargs)
return curried_do_reshow_say(
renpy.store._last_say_who,
renpy.store._last_say_what,
**kwargs)
def reshow_say(**kwargs):
get_reshow_say()(**kwargs)
@@ -1109,7 +1133,7 @@ def image_size(im):
raise Exception("renpy.image_size expects it's argument to be an image.")
surf = im.load()
return im.get_size()
return surf.get_size()
def get_at_list(name, layer='master'):
if isinstance(name, basestring):
@@ -1218,19 +1242,19 @@ def game_menu(screen=None):
call_in_new_context("_game_menu", screen)
def shown_window():
renpy.game.interface.shown_window = True
renpy.game.context().scene_lists.shown_window = True
def get_placement(d):
o = renpy.store.object()
p = d.get_placement()
o.xpos = d[0]
o.ypos = d[1]
o.xanchor = d[2]
o.yanchor = d[3]
o.xoffset = d[4]
o.yoffset = d[5]
o.subpixel = d[6]
o.xpos = p[0]
o.ypos = p[1]
o.xanchor = p[2]
o.yanchor = p[3]
o.xoffset = p[4]
o.yoffset = p[5]
o.subpixel = p[6]
return o
+3 -1
View File
@@ -20,12 +20,14 @@
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import renpy
import sys
import codecs
import os
import os.path
import time
image_prefixes = None
filenames = None
# Things to check in lint.
#
# Image files exist, and are of the right case.
+3 -1
View File
@@ -26,7 +26,6 @@ from pickle import loads
from cStringIO import StringIO
import sys
import types
import codecs
# Files on disk should be checked before archives. Otherwise, among
# other things, using a new version of bytecode.rpb will break.
@@ -346,6 +345,9 @@ def transfn(name):
if renpy.config.reject_backslash and "\\" in name:
raise Exception("Backslash in filename, use '/' instead: %r" % name)
if isinstance(name, unicode):
name = name.encode("utf-8")
for d in renpy.config.searchpath:
fn = os.path.join(renpy.config.basedir, d, name)
-1
View File
@@ -28,7 +28,6 @@ import StringIO
import cStringIO
import zipfile
import time
import os
import os.path
import re
+10 -7
View File
@@ -25,7 +25,7 @@ import os
import sys
import time
import zipfile
from cPickle import loads, dumps, HIGHEST_PROTOCOL
from cPickle import loads, dumps
import __main__
def save_persistent():
@@ -50,9 +50,6 @@ def run(restart):
store.clear()
store.update(renpy.game.clean_store)
# Note that this is a restart.
renpy.store._restart = restart
# Re-Initialize the log.
game.log = renpy.python.RollbackLog()
@@ -87,6 +84,10 @@ def run(restart):
renpy.exports.log("--- " + time.ctime())
renpy.exports.log("")
# Note if this is a restart.
renpy.store._restart = restart
restart = None
# We run until we get an exception.
try:
game.context().run()
@@ -96,6 +97,7 @@ def run(restart):
# We get this when the context has changed, and so we go and
# start running from the new context.
except game.RestartException, e:
renpy.game.contexts = e.contexts
label = e.label
@@ -314,8 +316,9 @@ def main():
break
except game.FullRestartException, e:
restart = e.reason
finally:
renpy.display.core.cpu_idle.set()
renpy.loadsave.autosave_not_running.wait()
# This is stuff we do on a normal, non-error return.
renpy.display.core.cpu_idle.set()
renpy.display.render.check_at_shutdown()
renpy.loadsave.autosave_not_running.wait()
+2 -3
View File
@@ -25,7 +25,6 @@
import codecs
import re
import os
import sets
import renpy
import renpy.ast as ast
@@ -344,7 +343,7 @@ class Lexer(object):
# A list of keywords which should not be parsed as names, because
# there is a huge chance of confusion.
keywords = sets.Set([
keywords = set([
'as',
'at',
'behind',
@@ -1156,7 +1155,7 @@ def parse_parameters(l):
add_positional = True
names = sets.Set()
names = set()
if not l.match(r'\('):
return None
+6 -5
View File
@@ -31,11 +31,9 @@ import compiler.ast as ast
import marshal
import random
import types
import weakref
import re
import sets
import sys
import renpy
@@ -410,7 +408,6 @@ class RevertableSet(sets.Set):
class RevertableObject(object):
def __setattr__(self, attr, value):
import sys
object.__setattr__(self, attr, value)
def __delattr__(self, attr):
@@ -758,10 +755,14 @@ class RollbackLog(renpy.object.Object):
that the user may want to rollback to just before this
node.
"""
if self.current.checkpoint:
return
# Only allow checkpoints in the top-level context.
if len(renpy.game.contexts) > 1:
return
if self.rollback_limit < renpy.config.hard_rollback_limit:
self.rollback_limit += 1
-2
View File
@@ -36,8 +36,6 @@
# Empty lines are ignored. (This lets us clear out outstanding errors.)
import renpy
import sys
import select
import os
import os.path
+3
View File
@@ -178,6 +178,9 @@ class Script(object):
self.load_appropriate_file(".rpymc", ".rpym", dir, fn, initcode)
if renpy.parser.report_parse_errors():
raise SystemExit(-1)
return initcode
def assign_names(self, stmts, fn):
+18 -1
View File
@@ -50,6 +50,9 @@ _rollback = True
# config.
_config = renpy.config
# The special character used for name-only dialogue.
name_only = None
class _Config(object):
def register(self, name, default, cat=None, help=None):
@@ -179,7 +182,7 @@ def layout(cls, doc, nargs=0, **extra_kwargs):
kwargs = extra_kwargs.copy()
kwargs.update(properties)
rv = cls(**kwargs)
rv = cls(*conargs, **kwargs)
for i in kids:
rv.add(renpy.easy.displayable(i))
@@ -264,6 +267,7 @@ adv = ADVCharacter(None,
afm=True,
ctc=None,
ctc_pause=None,
ctc_timedpause=None,
ctc_position="nestled",
all_at_once=False,
with_none=None,
@@ -287,4 +291,17 @@ def say(who, what, interact=True):
who = Character(who, kind=name_only)
who(what, interact=interact)
__name__ = 'store'
import sys
sys.modules['store'] = sys.modules['renpy.store']
def public_api():
ui
im
object
range
sorted
del public_api
+17 -10
View File
@@ -31,6 +31,16 @@ prefixes = [ 'hover_', 'idle_', 'insensitive_', 'activate_', ]
# A map from prefix to priority and alternates.
prefix_subs = { }
# These allow quick access to important properties.
prop_xpos = None
prop_ypos = None
prop_xanchor = None
prop_yanchor = None
prop_xoffset = None
prop_yoffset = None
prop_subpixel = None
def register_prefix(prefix, prio, addprefixes=[]):
for r in roles:
@@ -547,25 +557,25 @@ def restore(o):
def style_metaclass(name, bases, attrs):
for k in expansions.iterkeys():
def setter(self, v, k=k):
def setter_a(self, v, k=k):
self.setattr(k, v)
def deleter(self, k=k):
def deleter_a(self, k=k):
self.delattr(k)
attrs[k] = property(None, setter, deleter)
attrs[k] = property(None, setter_a, deleter_a)
for k, number in property_number.iteritems():
def getter(self, number=number):
def getter_b(self, number=number):
return self.cache[self.offset + number]
def setter(self, v, k=k):
def setter_b(self, v, k=k):
self.setattr(k, v)
def deleter(self, k=k):
def deleter_b(self, k=k):
self.delattr(k)
attrs[k] = property(getter, setter, deleter)
attrs[k] = property(getter_b, setter_b, deleter_b)
return type(name, bases, attrs)
@@ -744,9 +754,6 @@ def write_text(filename):
styles = style_map.items()
styles.sort()
style_props = { }
for name, sty in styles:
if not isinstance(sty, Style):
-2
View File
@@ -24,10 +24,8 @@
# This program adds froms to every unqualified call found in the game
# directory. It's not perfect, but it's better than nothing.
import sys
import os
import re
import glob
def find_labels(fn, labels):
+2 -3
View File
@@ -26,12 +26,11 @@
# but are probably better than nothing.
import sys
import os
import encodings.zlib_codec
import encodings.zlib_codec; encodings.zlib_codec
import random
import glob
from cPickle import loads, dumps, HIGHEST_PROTOCOL
from cPickle import dumps, HIGHEST_PROTOCOL
# The amount of padding we will add.
padding_max = 64
+3 -4
View File
@@ -95,7 +95,7 @@ def add(w, make_current=False, once=False):
if isinstance(atf, renpy.display.motion.Transform):
atw = atf(child=atw)
else:
atq = atf(atw)
atw = atf(atw)
if isinstance(current, str):
renpy.game.context(-1).scene_lists.add(current, atw, key=add_tag)
@@ -289,8 +289,7 @@ def menu(menuitems,
chosen.add(label)
return val
else:
def clicked(val=val):
return val
clicked = renpy.ui.returns(val)
if isinstance(button, basestring):
button = getattr(renpy.game.style, button)
@@ -332,7 +331,7 @@ def imagemap(ground,
if unselected is None:
unselected = ground
image(ground)
add(ground)
for x0, y0, x1, y1, result in hotspots:
-1
View File
@@ -25,7 +25,6 @@
import renpy
import sets
import os.path
def warp(spec):
"""
+1
View File
@@ -180,6 +180,7 @@ init python hide:
for l in f:
l = l.decode("utf-8")
l = l.rstrip()
m = re.match("\s*#begin (\w+)", l)
+1 -1
View File
@@ -275,7 +275,7 @@ image main_menu:
size (800, 509)
contains:
Text("Ren'Py 6.10.0 \"You Ain't Seen Nothing Yet\"", size=18)
Text("Ren'Py 6.10.1 \"I Can See Clearly Now\"", size=18)
yalign .98
xalign .02