Compare commits

...

63 Commits

Author SHA1 Message Date
Tom Rothamel e31f1ac63f Mark one pylint spurious warning. 2010-01-10 15:42:11 -05:00
Tom Rothamel 33a6c97446 Finalize changelog. 2010-01-10 15:37:57 -05:00
Tom Rothamel 99e9e6e9ba Bump version to 6.10.2a. 2010-01-10 15:34:31 -05:00
Tom Rothamel 1d81cede71 Unpack ScaledSurfaces before using them as a sample for an alpha channel. 2010-01-10 01:52:00 -05:00
Tom Rothamel 54ab9e0f1b Add copyright information to files that have it missing. 2010-01-09 13:25:18 -05:00
Tom Rothamel f0df9a7a05 Bump copyright to 2010. 2010-01-09 13:14:42 -05:00
Tom Rothamel adc3bf820b Fixed a bug that caused the overlay to display twice in some cases. 2010-01-05 18:07:28 -05:00
Tom Rothamel d26ac890a5 Add the ability to pin images into the cache, using the renpy.cache_pin function. 2010-01-05 02:30:39 -05:00
Tom Rothamel d0397b2111 The new config.automatic_images_strip variable can strip out prefixes
when automatically defining images.
2010-01-03 16:32:21 -05:00
Tom Rothamel 0229de3f0d The new config.menu_clear_layers variable allows layers to be cleared
when entering the game menu. This makes it easier for a layer to have 
overlay-like things on it when in the game, but not when in the game
menu.
2010-01-03 16:25:20 -05:00
Tom Rothamel 176150be7f Add renpylint script, a wrapper around pylint that gets rid of some
false positives where pylint isn't able to fully analyze Ren'Py.

Add annotations to Ren'Py to further supress false positives. The result
is that we can now run pylint and pick out regressions.
2010-01-02 02:38:07 -05:00
Tom Rothamel 04992fa431 Flag spurious pylint warnings, in the renpy/ directory. 2010-01-01 16:30:38 -05:00
Tom Rothamel b26725fd01 pylint done. 2010-01-01 15:09:36 -05:00
Tom Rothamel 601e7b1949 pylint: Initial pass through renpy directory. 2010-01-01 14:27:20 -05:00
Tom Rothamel 37c1571792 pylint: ast.py and atl.py 2010-01-01 13:30:39 -05:00
Tom Rothamel 812144bdf0 Fixed a bug that caused pixellate to crash. 2009-12-31 16:16:20 -05:00
Tom Rothamel 6e616fda4e When a music filename is unknown, remove it from the loop, so we don't keep
trying to access it.
2009-12-31 15:44:40 -05:00
Tom Rothamel 3f120ce658 Ren'Py now caches the individual words of text that are rendered. This
can lead to a speedup in text display when there are many words of
text on the screen, and that text is re-displayed, as is the case
where the text text speed is not the maximum. This is especially 
beneficial for eastasian languages, where every character is treated
as a word.
2009-12-30 16:24:18 -05:00
Tom Rothamel 5446da46dc Ren'Py now caches the individual words of text that are rendered. This
can lead to a speedup in text display when there are many words of
text on the screen, and that text is re-displayed, as is the case
where the text text speed is not the maximum. This is especially 
beneficial for eastasian languages, where every character is treated
as a word.
2009-12-30 15:41:29 -05:00
Tom Rothamel 172efcac94 Surface creation parameter was missing when creating a Frame with tile=True.
Fixes lp:501351.
2009-12-30 00:24:27 -05:00
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
Tom Rothamel babd95540d ATL add contains expression statement. 2009-11-15 00:51:53 -05:00
115 changed files with 13952 additions and 2039 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
+96
View File
@@ -1,3 +1,99 @@
New in Ren'Py 6.10.2
--------------------
Ren'Py now caches the individual words of text that are rendered. This
can lead to a speedup in text display when there are many words of
text on the screen, and that text is re-displayed, as is the case
where the text text speed is not the maximum. This is especially
beneficial for eastasian languages, where every character is treated
as a word.
The new config.menu_clear_layers variable allows layers to be cleared
when entering the game menu. This makes it easier for a layer to have
overlay-like things on it when in the game, but not when in the game
menu.
The new renpy.cache_pin function pins images into memory, loading them
as soon as possible and keeping them loaded.
The new config.automatic_images_strip variable can strip out prefixes
when automatically defining images.
Ren'Py will now ignore music files that do not exist. Previously, it
could loop trying to play them. (This would increase CPU usage, rather
than causing a crash.)
The following numbered bugs were fixed:
* lp:501351 - Displaying a Frame() with tile=True crashes
In addition:
* Fixed a bug that caused pixellate to crash.
* Fixed a bug that caused the overlay to display twice in some cases.
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")
+3
View File
@@ -1,3 +1,6 @@
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
# This file contains warpers that are used by ATL. They need to be defined
# early, so Ren'Py knows about them when parsing other files.
+3
View File
@@ -1,3 +1,6 @@
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
init -1210 python:
# This is called when script_version is set, to immediately
+3
View File
@@ -1,3 +1,6 @@
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
# This file contains a number of definitions of standard
# locations and transitions. We've moved them into the common
# directory so that it's easy for an updated version of all of these
+15 -16
View File
@@ -1,7 +1,5 @@
# Copyright 2004-2007 PyTom
#
# Please see the LICENSE.txt distributed with Ren'Py for permission to
# copy and modify.
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
init -1105 python:
@@ -288,13 +286,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 +333,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?"
+35 -13
View File
@@ -1,7 +1,5 @@
# Copyright 2004-2007 PyTom
#
# Please see the LICENSE.txt distributed with Ren'Py for permission to
# copy and modify.
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
# This file consists of renpy functions that aren't expected to be
# touched by the user too much. We reserve the _ prefix for names
@@ -52,8 +50,14 @@ init -1180 python:
# Should we automatically define images?
config.automatic_images = None
# Prefixes to strip from automatic images.
config.automatic_images_strip = [ ]
# A save to automatically load, if it exists.
config.auto_load = None
# Layers to clear when entering the menus.
config.menu_clear_layers = [ ]
# This is updated to give the user an idea of where a save is
# taking place.
@@ -528,6 +532,9 @@ label _enter_menu:
renpy.movie_stop(only_fullscreen=True)
renpy.take_screenshot((config.thumbnail_width, config.thumbnail_height))
for i in config.menu_clear_layers:
renpy.scene(layer=i)
renpy.context()._menu = True
# This may be changed, if we are already in the main menu.
@@ -702,18 +709,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.
@@ -777,6 +790,15 @@ init 1180 python hide:
name = ( shortfn, )
for sep in seps:
name = tuple(j for i in name for j in i.split(sep))
# Strip name components.
while name:
for i in config.automatic_images_strip:
if name[0] == i:
name.pop(0)
break
else:
break
# Only names of 2 components or more.
if len(name) < 2:
+2 -4
View File
@@ -1,7 +1,5 @@
# Copyright 2008 PyTom
#
# Please see the LICENSE.txt distributed with Ren'Py for permission to
# copy and modify.
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
# Common stuff that's used by the various Ren'Py menus. This includes
# the default definitions of config.main_menu and config.game_menu, as
+3
View File
@@ -1,3 +1,6 @@
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
# This file contains code that sets up the various mixers, based on how
# the user sets config.has_music, .has_sound, and .has_voice.
+3
View File
@@ -1,3 +1,6 @@
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
# This is an implementation of NVL-mode, which can be used to show
# dialogue in a fullscreen way, like NVL-style games. Multiple lines
# of dialogue are shown on the screen at once, whenever a line of
+3
View File
@@ -1,3 +1,6 @@
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
# This file contains code that creates a few new statements. We'll
# also describe here the API for defining your own statements.
#
+2 -4
View File
@@ -1,7 +1,5 @@
# Copyright 2004-2008 PyTom
#
# Please see the LICENSE.txt distributed with Ren'Py for permission to
# copy and modify.
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
# This file is responsible for creating and defining the default styles
# used by the system.
+2 -4
View File
@@ -1,7 +1,5 @@
# Copyright 2004-2008 PyTom
#
# Please see the LICENSE.txt distributed with Ren'Py for permission to
# copy and modify.
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
init -1110 python:
+3
View File
@@ -1,3 +1,6 @@
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
# This extra contains a basic implementation of voice support. Right
# now, voice is given its own toggle, and can either be turned on or
# turned off. In the future, we'll probably provide some way of
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 $
+3
View File
@@ -1,3 +1,6 @@
# Copyright 2004-2008 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
init python:
######################################################################
+3
View File
@@ -1,3 +1,6 @@
# Copyright 2004-2008 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
init:
python:
+3
View File
@@ -1,3 +1,6 @@
# Copyright 2004-2008 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
init -1170 python hide:
config.old_names['Quit'] = 'Quit Game'
+3
View File
@@ -1,3 +1,6 @@
# Copyright 2004-2008 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
# Copyright 2004-2006 PyTom
#
# Please see the LICENSE.txt distributed with Ren'Py for permission to
+3
View File
@@ -1,3 +1,6 @@
# Copyright 2004-2008 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
init python hide:
style.menu_button = Style(style.button, heavy=True, help='Buttons that are part of the main or game menus.')
+3
View File
@@ -1,3 +1,6 @@
# Copyright 2004-2008 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
# Copyright 2004-2007 PyTom
#
# Please see the LICENSE.txt distributed with Ren'Py for permission to
@@ -1,3 +1,6 @@
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
init python:
layout.provides('joystick_preferences')
+3
View File
@@ -1,3 +1,6 @@
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
init python:
layout.provides('load_save')
+3
View File
@@ -1,3 +1,6 @@
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
init python:
layout.provides('main_menu')
+3
View File
@@ -1,3 +1,6 @@
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
init python:
layout.provides('navigation')
+3
View File
@@ -1,3 +1,6 @@
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
init python:
layout.provides('preferences')
@@ -1,3 +1,6 @@
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
init python:
# Styles
+3
View File
@@ -1,3 +1,6 @@
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
init python hide:
layout.provides('yesno_prompt')
+3
View File
@@ -1,3 +1,6 @@
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
init python:
layout.provides('main_menu')
+3
View File
@@ -1,3 +1,6 @@
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
init python:
layout.provides('navigation')
+50 -22
View File
@@ -1,46 +1,69 @@
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
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 +97,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 +119,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()
+18 -9
View File
@@ -1,22 +1,25 @@
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
init python:
layout.provides('load_save')
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 +27,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 +162,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 +257,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):
+44 -20
View File
@@ -1,13 +1,20 @@
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
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 +23,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 +38,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
+3
View File
@@ -1,3 +1,6 @@
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
init python:
layout.provides('navigation')
+3
View File
@@ -1,3 +1,6 @@
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
init python:
layout.provides('preferences')
@@ -1,3 +1,6 @@
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
init python hide:
layout.provides('yesno_prompt')
@@ -1,3 +1,6 @@
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
init python:
layout.provides('preferences')
+3
View File
@@ -1,3 +1,6 @@
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
init python:
layout.provides('load_save')
@@ -1,3 +1,6 @@
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
init python:
layout.provides('preferences')
+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, 2)
+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
+9 -5
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# Copyright 2004-2007 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -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:
+15 -7
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -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.0c"
version = "Ren'Py 6.10.2a"
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:
+8 -7
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -92,7 +92,7 @@ class PyExpr(unicode):
return self
def __getnewargs__(self):
return (unicode(self), self.filename, self.linenumber)
return (unicode(self), self.filename, self.linenumber) # E1101
class PyCode(object):
@@ -186,6 +186,7 @@ class Node(object):
self.filename, self.linenumber = loc
self.name = None
self.next = None
def diff_info(self):
"""
@@ -266,7 +267,7 @@ class Node(object):
"""
rv = Scry()
rv._next = self.next
rv._next = self.next # W0201
return rv
def say_menu_with(expression, callback):
@@ -334,7 +335,7 @@ class Say(Node):
what = self.what
if renpy.config.say_menu_text_filter:
what = renpy.config.say_menu_text_filter(what)
what = renpy.config.say_menu_text_filter(what) # E1102
say_menu_with(self.with_, renpy.game.interface.set_transition)
renpy.exports.say(who, what, interact=getattr(self, 'interact', True))
@@ -372,11 +373,11 @@ class Say(Node):
def scry(self):
rv = Node.scry(self)
rv.interacts = True
rv.interacts = True # W0201
return rv
# Copy the descriptor.
setattr(Say, "with", Say.with_)
setattr(Say, "with", Say.with_) # E1101
class Init(Node):
@@ -1154,7 +1155,7 @@ class Menu(Node):
rv.interacts = True
return rv
setattr(Menu, "with", Menu.with_)
setattr(Menu, "with", Menu.with_) # E1101
# Goto is considered harmful. So we decided to name it "jump"
+239 -125
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -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
@@ -155,6 +175,8 @@ class ATLTransformBase(renpy.object.Object):
parameters = renpy.ast.ParameterInfo([ ], [ ], None, None)
def __init__(self, atl, context, parameters):
super(ATLTransformBase, self).__init__()
if parameters is None:
parameters = ATLTransformBase.parameters
@@ -268,7 +290,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
@@ -346,6 +368,10 @@ class ATLTransformBase(renpy.object.Object):
# The base class for raw ATL statements.
class RawStatement(renpy.object.Object):
def __init__(self, loc):
super(RawStatement, self).__init__()
self.loc = loc
# Compiles this RawStatement into a Statement, by using ctx to
# evaluate expressions as necessary.
def compile(self, ctx):
@@ -359,6 +385,10 @@ class RawStatement(renpy.object.Object):
# The base class for compiled ATL Statements.
class Statement(renpy.object.Object):
def __init__(self, loc):
super(Statement, self).__init__()
self.loc = loc
# trans is the transform we're working on.
# st is the time since this statement started executing.
# state is the state stored by this statement, or None if
@@ -399,7 +429,7 @@ class RawBlock(RawStatement):
def __init__(self, loc, statements, animation):
self.loc = loc
super(RawBlock, self).__init__(loc)
# A list of RawStatements in this block.
self.statements = statements
@@ -422,7 +452,7 @@ class RawBlock(RawStatement):
class Block(Statement):
def __init__(self, loc, statements):
self.loc = loc
super(Block, self).__init__(loc)
# A list of statements in the block.
self.statements = statements
@@ -475,67 +505,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,9 +583,11 @@ class Block(Statement):
# values of the variables here.
class RawMultipurpose(RawStatement):
warp_function = None
def __init__(self, loc):
self.loc = loc
super(RawMultipurpose, self).__init__(loc)
self.warper = None
self.duration = None
@@ -578,9 +597,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 +625,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 +639,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 +651,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 = [ ]
@@ -697,11 +722,28 @@ class RawMultipurpose(RawStatement):
if isinstance(i, renpy.display.core.Displayable):
i.predict(callback)
# This lets us have an ATL transform as our child.
class RawContainsExpr(RawStatement):
def __init__(self, loc, expr):
super(RawContainsExpr, self).__init__(loc)
self.expression = expr
def compile(self, ctx):
compiling(self.loc)
child = ctx.eval(self.expression)
return Child(self.loc, child, None)
# This allows us to have multiple children, inside a Fixed.
class RawChild(RawStatement):
def __init__(self, loc, child):
self.loc = loc
super(RawChild, self).__init__(loc)
self.children = [ child ]
def compile(self, ctx):
@@ -717,8 +759,9 @@ class RawChild(RawStatement):
class Child(Statement):
def __init__(self, loc, child, transition):
self.loc = loc
super(Child, self).__init__(loc)
self.child = renpy.easy.displayable(child)
self.transition = transition
@@ -747,7 +790,9 @@ class Child(Statement):
class Interpolation(Statement):
def __init__(self, loc, warper, duration, properties, revolution, circles, splines):
self.loc = loc
super(Interpolation, self).__init__(loc)
self.warper = warper
self.duration = duration
self.properties = properties
@@ -763,7 +808,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)
@@ -785,6 +830,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 = [ ]
@@ -843,14 +889,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:
@@ -870,7 +916,9 @@ class Interpolation(Statement):
class RawRepeat(RawStatement):
def __init__(self, loc, repeats):
self.loc = loc
super(RawRepeat, self).__init__(loc)
self.repeats = repeats
def compile(self, ctx):
@@ -887,7 +935,9 @@ class RawRepeat(RawStatement):
class Repeat(Statement):
def __init__(self, loc, repeats):
self.loc = loc
super(Repeat, self).__init__(loc)
self.repeats = repeats
def execute(self, trans, st, state, event):
@@ -899,7 +949,8 @@ class Repeat(Statement):
class RawParallel(RawStatement):
def __init__(self, loc, block):
self.loc = loc
super(RawParallel, self).__init__(loc)
self.blocks = [ block ]
def compile(self, ctx):
@@ -911,9 +962,9 @@ class RawParallel(RawStatement):
class Parallel(Statement):
def __init__(self, loc, blocks):
self.loc = loc
super(Parallel, self).__init__(loc)
self.blocks = blocks
def execute(self, trans, st, state, event):
@@ -960,7 +1011,8 @@ class Parallel(Statement):
class RawChoice(RawStatement):
def __init__(self, loc, chance, block):
self.loc = loc
super(RawChoice, self).__init__(loc)
self.choices = [ (chance, block) ]
def compile(self, ctx):
@@ -974,7 +1026,9 @@ class RawChoice(RawStatement):
class Choice(Statement):
def __init__(self, loc, choices):
self.loc = loc
super(Choice, self).__init__(loc)
self.choices = choices
def execute(self, trans, st, state, event):
@@ -1015,7 +1069,8 @@ class Choice(Statement):
class RawTime(RawStatement):
def __init__(self, loc, time):
self.loc = loc
super(RawTime, self).__init__(loc)
self.time = time
def compile(self, ctx):
@@ -1025,7 +1080,8 @@ class RawTime(RawStatement):
class Time(Statement):
def __init__(self, loc, time):
self.loc = loc
super(Time, self).__init__(loc)
self.time = time
def execute(self, trans, st, state, event):
@@ -1037,7 +1093,8 @@ class Time(Statement):
class RawOn(RawStatement):
def __init__(self, loc, name, block):
self.loc = loc
super(RawOn, self).__init__(loc)
self.handlers = { name : block }
def compile(self, ctx):
@@ -1058,13 +1115,13 @@ class RawOn(RawStatement):
class On(Statement):
def __init__(self, loc, handlers):
self.loc = loc
super(On, self).__init__(loc)
self.handlers = handlers
def execute(self, trans, st, state, event):
executing(self.loc)
# If it's our first time through, start in the start state.
if state is None:
@@ -1137,7 +1194,8 @@ class On(Statement):
class RawEvent(RawStatement):
def __init__(self, loc, name):
self.loc = loc
super(RawEvent, self).__init__(loc)
self.name = name
def compile(self, ctx):
@@ -1147,12 +1205,42 @@ class RawEvent(RawStatement):
class Event(Statement):
def __init__(self, loc, name):
self.loc = loc
super(Event, self).__init__(loc)
self.name = name
def execute(self, trans, st, state, event):
return "event", (self.name, st), None
class RawFunction(RawStatement):
def __init__(self, loc, expr):
super(RawFunction, self).__init__(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):
super(Function, self).__init__(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):
@@ -1182,12 +1270,22 @@ def parse_atl(l):
statements.append(block)
elif l.keyword('contains'):
l.require(':')
l.expect_eol()
l.expect_block('contains')
block = parse_atl(l.subblock_lexer())
statements.append(RawChild(loc, block))
expr = l.simple_expression()
if expr:
l.expect_noblock('contains expression')
statements.append(RawContainsExpr(loc, expr))
else:
l.require(':')
l.expect_eol()
l.expect_block('contains')
block = parse_atl(l.subblock_lexer())
statements.append(RawChild(loc, block))
elif l.keyword('parallel'):
l.require(':')
@@ -1227,6 +1325,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')
@@ -1260,15 +1364,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:
+1 -1
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
+19 -11
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -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
@@ -139,6 +142,8 @@ class MusicContext(renpy.python.RevertableObject):
def __init__(self):
super(MusicContext, self).__init__()
# The time this channel was last ordered panned.
self.pan_time = None
@@ -283,7 +288,7 @@ class Channel(object):
rv = mcd.get(self.name)
if rv is None:
rv = mcd[self.name] = MusicContext();
rv = mcd[self.name] = MusicContext()
return rv
@@ -368,6 +373,12 @@ class Channel(object):
self.playing = True
except:
# If playing failed, remove topq.filename from self.loop
# so we don't keep trying.
while topq.filename in self.loop:
self.loop.remove(topq.filename)
if renpy.config.debug_sound:
raise
else:
@@ -384,7 +395,7 @@ class Channel(object):
# Queue empty callback.
if do_callback and self.callback:
self.callback()
self.callback() # E1102
def dequeue(self, even_tight=False):
"""
@@ -424,11 +435,9 @@ class Channel(object):
pss.set_secondary_volume(self.number,
self.context.secondary_volume,
0)
self.pan_delay = 0
if not self.queue and self.callback:
self.callback()
self.callback() # E1102
def fadeout(self, secs):
@@ -591,7 +600,6 @@ def init():
def quit():
global pcm_ok
global midi_ok
global mix_ok
if not pcm_ok:
@@ -779,7 +787,7 @@ def event(ev):
if ev.type == REFRESH_EVENT:
if renpy.audio.music.get_playing("movie"):
pss.refresh_event()
# Return False, as a Movie should get this to know when to
# redraw itself.
return False
+3 -3
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -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
+1 -1
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
+35 -30
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 # W0403
import ctypes
import ctypes.wintypes
import EasyDialogs
import ctypes.wintypes; ctypes.wintypes
import EasyDialogs; EasyDialogs
trace_file = None
trace_local = None
@@ -90,15 +90,15 @@ def popen_del(self, _deadstate=sys.maxint):
self.poll(_deadstate=_deadstate)
try:
import subprocess
if self.returncode is None and subprocess._active is not None:
subprocess._active.append(self)
import subprocess # W0403
if self.returncode is None and subprocess._active is not None: # E1101
subprocess._active.append(self) # E1101
except:
pass
def bootstrap(renpy_base):
global renpy
global renpy # W0602
os.environ["RENPY_BASE"] = os.path.abspath(renpy_base)
@@ -226,12 +226,12 @@ def bootstrap(renpy_base):
# Show the presplash.
if not options.lint and not options.compile and not options.version and not options.rmpersistent:
import renpy.display.presplash
import renpy.display.presplash # W0404
renpy.display.presplash.start(gamedir)
# Fix an exception thrown by garbage collection.
import subprocess
subprocess.Popen.__del__ = popen_del
import subprocess # W0403
subprocess.Popen.__del__ = popen_del # E1101
# If we're on a mac, install our own os.start.
if sys.platform == "darwin":
@@ -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."
+17 -10
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -42,7 +42,8 @@ def predict_show_display_say(who, what, who_args, what_args, window_args, image=
rv.append(renpy.game.style.say_who_window.background)
if image:
rv.append(renpy.display.im.image(who, True))
if image != "<Dynamic>":
rv.append(renpy.display.im.image(who, True))
if side_image:
rv.append(renpy.display.im.image(side_image, True))
@@ -213,9 +214,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 +290,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)
@@ -318,7 +327,7 @@ def display_say(show_function,
c("show_done", interact=interact, type=type, **cb_args)
if behavior and afm:
behavior.set_afm_length(what_text.get_simple_length() - slow_start)
behavior.set_afm_length(what_text.get_simple_length() - slow_start) # E1103
if interact:
@@ -426,6 +435,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'),
@@ -562,9 +572,6 @@ class ADVCharacter(object):
def predict(self, what):
if self.dynamic and self.image:
return [ ]
if self.dynamic:
who = "<Dynamic>"
else:
+15 -3
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -401,9 +401,21 @@ rtl = False
# A callback for file opening.
file_open_callback = None
# The size of screenshot thumbnails. (Redefined in common/)
thumbnail_width = None
thumbnail_height = None
# The end game transition.
end_game_transition = None
# Various directories.
gamedir = None
basedir = None
renpy_base = None
del renpy
def init():
import renpy
global properties
import renpy # W0404
global style_properties
style_properties = renpy.style.style_properties
+1 -1
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
+1 -1
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
+5 -28
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -22,7 +22,6 @@
# This file contains support for state-machine controlled animations.
import renpy
import pygame
import random
class State(object):
@@ -77,7 +76,7 @@ class State(object):
def motion_copy(self, child):
if self.image is not None:
child = self.mage
child = self.image
return State(self.name, child, *self.atlist)
@@ -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)
+17 -12
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -26,7 +26,6 @@ import renpy
from renpy.display.render import render
import pygame
from pygame.constants import *
def compile_event(key, keydown):
"""
@@ -557,7 +556,7 @@ class Input(renpy.display.text.Text):
self.content = content
if self.changed:
self.change(content)
self.changed(content)
self.editable = editable
@@ -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
@@ -619,6 +616,8 @@ adj_registered = { }
class Adjustment(renpy.object.Object):
def __init__(self, range=1, value=0, step=None, page=0, changed=None, adjustable=True, ranged=None):
super(Adjustment, self).__init__()
self._value = value
self._range = range
self._page = page
@@ -701,14 +700,14 @@ 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)
self.adjustment = Adjustment(self.range, self.value, changed=self.changed) # E1101
self.adjustment.register(self)
del self.range
del self.value
del self.changed
del self.range # E1101
del self.value # E1101
del self.changed # E1101
def __init__(self,
range=None,
@@ -736,6 +735,12 @@ class Bar(renpy.display.core.Displayable):
self.adjustment = adjustment
self.focusable = adjustment.adjustable
# These are set when we are first rendered.
self.thumb_dim = 0
self.height = 0
self.width = 0
self.hidden = False
def visit(self):
return [ self.style.fore_bar, self.style.aft_bar, self.style.thumb, self.style.thumb_shadow ]
@@ -898,7 +903,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:
+128 -83
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -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 ]
@@ -102,7 +100,7 @@ class Displayable(renpy.object.Object):
# Can we change our look in response to transform_events?
transform_event_responder = False
def __init__(self, focus=None, default=False, style='default', **properties):
def __init__(self, focus=None, default=False, style='default', **properties): # W0231
self.style = renpy.style.Style(style, properties, heavy=True)
self.focus_name = focus
self.default = default
@@ -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):
"""
@@ -385,6 +393,8 @@ class ImagePredictInfo(renpy.object.Object):
def __init__(self, ipi=None):
super(ImagePredictInfo, self).__init__()
# layer -> (tag -> image name)
self.images = { }
@@ -425,7 +435,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 +454,22 @@ 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):
super(SceneLists, self).__init__()
# 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 +525,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,16 +610,13 @@ 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()
if zorder == zo:
if zorder == zo: # W0631
l[index] = (key, zorder, st, at, thing)
return
else:
@@ -765,11 +797,8 @@ class SceneLists(renpy.object.Object):
self.layers[l] = newl
class Display(object):
"""
This is responsible for managing the display window.
@@ -778,10 +807,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 +830,6 @@ class Display(object):
"""
def __init__(self, interface):
self.interface = interface
@@ -852,7 +876,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 +891,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 +924,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 +980,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 +989,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 +1027,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 +1053,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 +1077,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 +1138,7 @@ class Display(object):
return updates
def update_mouse(self):
"""
Draws the mouse, and then updates the screen.
@@ -1159,6 +1185,7 @@ class Display(object):
self.suppressed_blit = suppress_blit
self.surftree = surftree
def save_screenshot(self, filename):
"""
@@ -1171,7 +1198,6 @@ class Display(object):
if renpy.config.debug:
raise
pass
def screenshot(self, scale):
@@ -1179,9 +1205,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)
@@ -1311,7 +1337,10 @@ class Interface(object):
# for contexts outside the current one. This is used to restore those
# in the case where nothing has changed in the new context.
self.transition_info_stack = [ ]
# The time when the event was dispatched.
self.event_time = 0
def take_screenshot(self, scale):
"""
@@ -1321,6 +1350,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 +1362,7 @@ class Interface(object):
return self.screenshot
def lose_screenshot(self):
"""
This deallocates the saved screenshot.
@@ -1339,17 +1370,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 +1404,25 @@ 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]
# Get rid of transient things.
for i in renpy.config.overlay_layers:
scene_lists.clear(i)
scene_lists = renpy.game.context().scene_lists
scene_lists.replace_transient()
self.shown_window = False
scene_lists.shown_window = False
def set_transition(self, transition, layer=None, force=False):
"""
@@ -1409,7 +1446,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 +1491,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 +1544,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 +1555,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 +1587,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 +1617,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 +1674,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 +1685,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 +1760,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 +1986,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 +2000,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 +2037,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 +2050,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
+4 -7
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -24,9 +24,6 @@
import pygame
import renpy
import textwrap
import select
import sys
import os
import os.path
@@ -43,7 +40,7 @@ class ReportError(object):
# In the report method, Ren'Py may be in an ill-defined state.
def report(self, error_type):
import os.path
import pygame
import pygame # W0404
pygame.display.init()
msg = "Ren'Py has experienced " + error_type + ".\n"
@@ -59,7 +56,7 @@ class ReportError(object):
y += self.font.get_linesize()
pygame.display.flip()
pygame.display.flip() # E1120
pygame.time.set_timer(pygame.USEREVENT + 1, 50)
@@ -69,7 +66,7 @@ class ReportError(object):
return True
ev = pygame.event.wait()
if ev.type == pygame.MOUSEBUTTONUP:
if ev.button == 1:
+3 -7
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -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):
@@ -177,9 +176,6 @@ def before_interact(roots):
# This changes the focus to be the widget contained inside the new
# focus object.
def change_focus(newfocus, default=False):
global argument
rv = None
if grab:
@@ -216,7 +212,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)
+35 -32
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -20,7 +20,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):
@@ -126,6 +123,8 @@ class SFont(ImageFont):
kerns,
charset):
super(SFont, self).__init__()
self.filename = filename
self.spacewidth = spacewidth
self.default_kern = default_kern
@@ -134,21 +133,21 @@ class SFont(ImageFont):
def load(self):
self.chars = { }
self.width = { }
self.advance = { }
self.offsets = { }
self.chars = { } # W0201
self.width = { } # W0201
self.advance = { } # W0201
self.offsets = { } # W0201
# Load in the image.
surf = renpy.display.im.Image(self.filename).load(unscaled=True)
sw, sh = surf.get_size()
height = sh
self.height = height
self.baseline = height
self.height = height # W0201
self.baseline = height # W0201
# 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)
@@ -204,6 +203,8 @@ class MudgeFont(ImageFont):
default_kern,
kerns):
super(MudgeFont, self).__init__()
self.filename = filename
self.xml = xml
self.spacewidth = spacewidth
@@ -212,10 +213,10 @@ class MudgeFont(ImageFont):
def load(self):
self.chars = { }
self.width = { }
self.advance = { }
self.offsets = { }
self.chars = { } # W0201
self.width = { } # W0201
self.advance = { } # W0201
self.offsets = { } # W0201
# Load in the image.
surf = renpy.display.im.Image(self.filename).load(unscaled=True)
@@ -248,12 +249,12 @@ class MudgeFont(ImageFont):
height = max(height, h)
self.height = height
self.baseline = height
self.height = height # W0201
self.baseline = height # W0201
# 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)
@@ -296,16 +297,18 @@ def parse_bmfont_line(l):
class BMFont(ImageFont):
def __init__(self, filename):
super(BMFont, self).__init__()
self.filename = filename
def load(self):
self.chars = { }
self.width = { }
self.advance = { }
self.offsets = { }
self.kerns = { }
self.default_kern = 0
self.chars = { } # W0201
self.width = { } # W0201
self.advance = { } # W0201
self.offsets = { } # W0201
self.kerns = { } # W0201
self.default_kern = 0 # W0201
pages = { }
@@ -315,8 +318,8 @@ class BMFont(ImageFont):
kind, args = parse_bmfont_line(l)
if kind == "common":
self.height = int(args["lineHeight"])
self.baseline = int(args["base"])
self.height = int(args["lineHeight"]) # W0201
self.baseline = int(args["base"]) # W0201
elif kind == "page":
pages[int(args["id"])] = renpy.display.im.Image(args["file"]).load(unscaled=True)
elif kind == "char":
+1 -1
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
+117 -101
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -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):
@@ -82,12 +80,22 @@ class Cache(object):
# Is the preload_thread alive?
self.keep_preloading = True
# A list of images that want to be pinned into memory.
self.global_pins = [ ]
# A map from image object to surface, only for objects that have
# been pinned into memory.
self.pin_cache = { }
# 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()
@@ -105,6 +113,7 @@ class Cache(object):
def clear(self):
self.lock.acquire()
self.pin_cache = { }
self.cache = { }
self.preloads = [ ]
self.first_preload_in_tick = True
@@ -146,9 +155,21 @@ class Cache(object):
else:
return
self.lock.acquire()
self.preloads.append(image)
self.lock.release()
# Called to report that a given image would like to be pinned into memory.
def pin_image(self, image):
if renpy.config.debug_image_cache:
print "IC Request Pin", image
if not isinstance(image, ImageBase):
if renpy.config.debug_image_cache:
print "IC Can't pin non image: ", image
else:
return
if image not in self.global_pins:
self.global_pins.append(image)
# This returns the pygame surface corresponding to the provided
# image. It also takes care of updating the age of images in the
@@ -160,9 +181,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 +199,21 @@ class Cache(object):
ce = self.cache.get(image, None)
if ce is not None:
self.cache.release()
self.lock.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:
if image in self.pin_cache:
surf = self.pin_cache[image]
else:
surf = image.load()
except:
self.lock.release()
raise
ce = CacheEntry(image, surf)
self.total_cache_size += ce.size
self.cache[image] = ce
@@ -202,33 +227,29 @@ class Cache(object):
# RLE detection. (ce.size is used to check that we're not
# 0 pixels big.)
if id(ce.surf) not in rle_cache and ce.size:
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_cache[id(ce.surf)] = rle_surf
renpy.display.render.mutated_surface(ce.surf)
idsurf = id(ce.surf)
if idsurf in pin_rle_cache:
rle_surf = pin_rle_cache[idsurf]
else:
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[idsurf] = rle_surf
if renpy.config.debug_image_cache:
print "Added to rle cache:", image
self.lock.release()
# Move it into the current generation. This isn't protected by
# a lock, so in certain circumstances we could have an
@@ -239,10 +260,11 @@ class Cache(object):
if ce.time != self.time:
ce.time = self.time
self.size_of_current_generation += ce.size
# Done... return the surface.
return ce.surf
# This kills off a given cache entry.
def kill(self, ce):
@@ -357,12 +379,41 @@ class Cache(object):
self.cleanout()
self.lock.release()
# If we have time, preload pinned images.
if self.keep_preloading and not renpy.game.less_memory:
# Compute the pin worklist.
pin_worklist = [ i for i in self.global_pins if i not in self.pin_cache ]
# For each image in the worklist...
for image in pin_worklist:
# If we have normal preloads, break out.
if self.preloads:
break
# Otherwise, pin preload the image.
if renpy.config.debug_image_cache:
print "IC Pin Preload", image
surf = image.load()
self.pin_cache[image] = surf
rle_surf = renpy.display.pgrender.copy_surface(surf)
rle_surf.set_alpha(255, pygame.RLEACCEL)
pin_rle_cache[id(surf)] = rle_surf
cache = Cache()
# A map from id(cached surface) to rle version of cached surface.
rle_cache = { }
# Same thing, for pinned surfaces.
pin_rle_cache = { }
def free_memory():
"""
Frees some memory.
@@ -370,7 +421,8 @@ def free_memory():
cache.clear()
rle_cache.clear()
pin_rle_cache.clear()
class ImageBase(renpy.display.core.Displayable):
"""
@@ -449,13 +501,13 @@ class Image(ImageBase):
super(Image, self).__init__(filename, **properties)
self.filename = filename
def load(self, unscaled=False):
def load(self, unscaled=False): # W0221
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 +545,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 +594,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 +661,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 +736,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, surf)
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 +788,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 +801,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 +822,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 +868,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 +898,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 +950,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 +1039,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 +1078,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 +1115,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 +1148,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)
@@ -1294,9 +1312,9 @@ im.matrix(%f, %f, %f, %f, %f.
h = h * math.pi / 180
cosVal = math.cos(h)
sinVal = math.sin(h)
lumR = 0.213;
lumG = 0.715;
lumB = 0.072;
lumR = 0.213
lumG = 0.715
lumB = 0.072
return matrix(
lumR+cosVal*(1-lumR)+sinVal*(-lumR),lumG+cosVal*(-lumG)+sinVal*(-lumG),lumB+cosVal*(-lumB)+sinVal*(1-lumB),0,0,
lumR+cosVal*(-lumR)+sinVal*(0.143),lumG+cosVal*(1-lumG)+sinVal*(0.140),lumB+cosVal*(-lumB)+sinVal*(-0.283),0,0,
@@ -1363,11 +1381,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 +1412,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 +1447,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 +1467,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.
+9 -6
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -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.load_image(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:
+4 -7
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -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,
+23 -42
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -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):
"""
@@ -126,7 +122,7 @@ class Container(renpy.display.core.Displayable):
else:
return
self.children.pop(i)
self.children.pop(i) # W0631
self.offsets = self._list_type()
if self.children:
@@ -434,7 +430,7 @@ class MultiBox(Container):
# The scene list for this widget.
self.scene_list = None
def add(self, widget, start_time=None, anim_time=None):
def add(self, widget, start_time=None, anim_time=None): # W0221
super(MultiBox, self).add(widget)
self.start_times.append(start_time)
self.anim_times.append(anim_time)
@@ -480,7 +476,7 @@ class MultiBox(Container):
if layout is None:
layout = self.default_layout
self.layout = layout
self.layout = layout # W0201
else:
layout = self.layout
@@ -660,6 +656,9 @@ def Fixed(**properties):
class SizeGroup(renpy.object.Object):
def __init__(self):
super(SizeGroup, self).__init__()
self.members = [ ]
self._width = None
self.computing_width = False
@@ -807,7 +806,7 @@ class Window(Container):
self.offsets = [ offsets ]
self.window_size = width, height
self.window_size = width, height # W0201
return rv
@@ -1080,7 +1079,7 @@ class Viewport(Container):
self.xadjustment.change(self.xadjustment.value - dx)
self.yadjustment.change(self.yadjustment.value - dy)
self.drag_position = (x, y)
self.drag_position = (x, y) # W0201
if renpy.display.behavior.map_event(ev, 'viewport_drag_end'):
renpy.display.focus.set_grab(None)
@@ -1172,10 +1171,10 @@ class Side(Container):
else:
return 0, axis
self.left_space, width = spacer('tl', 'l', 'bl', width)
self.right_space, width = spacer('tr', 'r', 'br', width)
self.top_space, height = spacer('tl', 't', 'tr', height)
self.bottom_space, height = spacer('bl', 'b', 'br', height)
self.left_space, width = spacer('tl', 'l', 'bl', width) # W0201
self.right_space, width = spacer('tr', 'r', 'br', width) # W0201
self.top_space, height = spacer('tl', 't', 'tr', height) # W0201
self.bottom_space, height = spacer('bl', 'b', 'br', height) # W0201
# The sizes of the various borders.
left = 0
@@ -1205,13 +1204,13 @@ class Side(Container):
right, top = sizeit('tr', right, top, right, top)
right, bottom = sizeit('br', right, bottom, right, bottom)
self.cwidth = cwidth
self.cheight = cheight
self.cwidth = cwidth # W0201
self.cheight = cheight # W0201
self.top = top
self.bottom = bottom
self.left = left
self.right = right
self.top = top # W0201
self.bottom = bottom # W0201
self.left = left # W0201
self.right = right # W0201
else:
cwidth = self.cwidth
@@ -1312,28 +1311,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
+2 -2
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -73,7 +73,7 @@ class Minigame(renpy.display.core.Displayable):
if rv is None:
font = renpy.display.text.get_font(font, size, bold=bold, italics=italics, underline=underline)
font = renpy.display.text.get_font(font, size, bold, italics, underline)
rv = font.render(text, antialias, color)
self.mutated_surface(rv)
+150 -277
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -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
+56 -36
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -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
@@ -60,7 +56,7 @@ def polar_to_cartesian(angle, radius, xaround, yaround):
class TransformState(renpy.object.Object):
def __init__(self):
def __init__(self): # W0231
self.alpha = 1
self.rotate = None
self.zoom = 1
@@ -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)
+2 -2
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -124,7 +124,7 @@ class SnowBlossomFactory(object):
self.init()
def init(self):
self.starts = [ random.uniform(0, self.start) for i in range(0, self.count) ]
self.starts = [ random.uniform(0, self.start) for i in range(0, self.count) ] # W0201
self.starts.append(self.start)
self.starts.sort()
+162
View File
@@ -0,0 +1,162 @@
# Copyright 2004-2010 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) # W0201
opygame.transform = ModuleProxy(pygame.transform) # W0201
opygame.image = ModuleProxy(pygame.image) # W0201
# 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)) # E1101
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
+4 -4
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -53,9 +53,9 @@ def start(gamedir):
import sys
if sys.argv[0].lower().endswith(".exe"):
proc = subprocess.Popen([sys.argv[0], "--presplash", fn], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
proc = subprocess.Popen([sys.argv[0], "--presplash", fn], stdin=subprocess.PIPE, stdout=subprocess.PIPE) # W0631
else:
proc = subprocess.Popen([sys.executable, sys.argv[0], "--presplash", fn], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
proc = subprocess.Popen([sys.executable, sys.argv[0], "--presplash", fn], stdin=subprocess.PIPE, stdout=subprocess.PIPE) # W0631
except:
pass
@@ -92,7 +92,7 @@ def show(fn):
pygame.display.init()
img = pygame.image.load(fn)
img = pygame.image.load(fn, fn)
screen = pygame.display.set_mode(img.get_size(), pygame.constants.NOFRAME)
screen.blit(img, (0, 0))
pygame.display.update()
+36 -19
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -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))
+302 -284
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -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
@@ -296,21 +292,18 @@ 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)
if isinstance(alpha, ScaledSurface):
alpha = alpha.surface # E1103
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 +320,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 +347,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 +362,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 +382,12 @@ 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 +411,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 +420,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 +441,6 @@ def load_scaling():
def unlock(self):
pass
def mustlock(self):
return False
def get_locked(self):
return False
@@ -474,23 +453,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 +488,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 +589,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 +612,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 +804,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 +838,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.
+90 -52
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -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
@@ -102,9 +99,25 @@ class TextStyle(object):
def __init__(self, source=None):
if source is not None:
vars(self).update(vars(source))
else:
self.font = ""
self.size = 0
self.bold = False
self.italic = False
self.underline = False
self.strikethrough = False
self.color = None
self.black_color = None
self.hyperlink = None
# The cached font.
self.f = None
# Width cache.
self.wcache = { }
# Surface cache.
self.scache = { }
def update(self):
self.f = get_font(self.font, self.size, self.bold, self.italic, self.underline, 0)
@@ -127,12 +140,17 @@ class TextStyle(object):
return self.get_width(text), self.f.get_ascent() - self.f.get_descent()
def render(self, text, antialias, color, black_color, use_colors, time, at, expand):
def render(self, text, antialias, color, black_color, use_colors, time, at, expand, use_cache):
if use_colors:
color = self.color or color
black_color = self.black_color or black_color
key = (text, antialias, color, black_color, expand)
if use_cache and key in self.scache:
return self.scache[key]
if expand:
font = get_font(self.font, self.size, self.bold, self.italic, self.underline, expand)
else:
@@ -151,26 +169,21 @@ 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)
if use_cache and not renpy.game.less_memory:
self.scache[key] = (rv, rv.get_size())
return rv, rv.get_size()
def length(self, text):
@@ -207,7 +220,7 @@ class WidgetStyle(object):
def sizes(self, widget):
return self.width, self.height
def render(self, widget, antialias, color, black_color, foreground, st, at, expand):
def render(self, widget, antialias, color, black_color, foreground, st, at, expand, use_cache):
# If in the foreground
if foreground:
@@ -464,8 +477,6 @@ def greedy_text_layout(triples, width, style):
def subtitle_text_layout_core(triples, width, style, soft, n, justify):
sizecache = { }
lines = [ ]
line = [ ]
@@ -669,7 +680,12 @@ class Text(renpy.display.core.Displayable):
self.tokens = None
# The duration of each pause, or None if the pause is infinite.
self.pause_lengths = [ ]
# The width we've been laid out for.
self.width = -1
self.update(redraw=False)
@@ -717,29 +733,49 @@ class Text(renpy.display.core.Displayable):
new_tokens = [ ]
fasts = 0
self.no_wait = False
self.no_wait_once = False
self.no_wait_done = False
self.pauses = 0
self.no_wait = False # W0201
self.no_wait_once = False # W0201
self.no_wait_done = False # W0201
self.pauses = 0 # W0201
self.pause_lengths = [ ] # W0201
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)
@@ -793,7 +829,7 @@ class Text(renpy.display.core.Displayable):
# Postprocess the tokens list to create widgets, as necessary.
self.children = [ ]
self.children = [ ] # W0201
newtokens = [ ]
for tl in self.tokens:
@@ -803,7 +839,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 +846,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)
@@ -870,10 +905,10 @@ class Text(renpy.display.core.Displayable):
def visit(self):
if self.tokens is None:
if self.tokens is None:
self.update()
return self.children
return self.children
def layout(self, width, time):
@@ -911,12 +946,12 @@ class Text(renpy.display.core.Displayable):
tsl[-1].hyperlink = None
tsl[-1].update()
self.laidout_hyperlinks = [ ]
self.laidout_hyperlinks = [ ] # W0201
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):
@@ -1123,14 +1158,14 @@ class Text(renpy.display.core.Displayable):
# Now, we need to go through these lines, to generate the data
# we need to render text.
self.laidout = [ ]
self.laidout_lineheights = [ ]
self.laidout_linewidths = [ ]
self.laidout_length = 0
self.laidout_start = 0
self.laidout_width = self.style.min_width
self.laidout_height = 0
self.laidout_lines_last = lines_last
self.laidout = [ ] # W0201
self.laidout_lineheights = [ ] # W0201
self.laidout_linewidths = [ ] # W0201
self.laidout_length = 0 # W0201
self.laidout_start = 0 # W0201
self.laidout_width = self.style.min_width # W0201
self.laidout_height = 0 # W0201
self.laidout_lines_last = lines_last # W0201
# Add something to empty lines.
for l in linetriples:
@@ -1276,8 +1311,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)
@@ -1308,13 +1341,18 @@ class Text(renpy.display.core.Displayable):
length -= ts.length(text)
# Should we cache the rendered text?
use_cache = True
if length < 0:
use_cache = False
if isinstance(text, (str, unicode)):
text = text[:length]
else:
return False
surf, (sw, sh) = ts.render(text, antialias, color, black_color, user_colors, time, at, expand)
surf, (sw, sh) = ts.render(text, antialias, color, black_color, user_colors, time, at, expand, use_cache)
if expand:
(sw, sh) = ts.sizes(text)
@@ -1417,7 +1455,7 @@ class Text(renpy.display.core.Displayable):
else:
length = sys.maxint
self.call_slow_done(st)
rv = renpy.display.render.Render(self.laidout_width - mindsx + maxdsx, self.laidout_height - mindsy + maxdsy)
for dsxo, dsyo in dslist:
+226 -244
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -37,8 +37,6 @@
import renpy
from renpy.display.render import render
import pygame
from pygame.constants import *
class Transition(renpy.display.core.Displayable):
@@ -55,12 +53,12 @@ class Transition(renpy.display.core.Displayable):
def event(self, ev, x, y, st):
if self.events or ev.type == renpy.display.core.TIMEEVENT:
return self.new_widget.event(ev, x, y, st)
return self.new_widget.event(ev, x, y, st) # E1101
else:
return None
def visit(self):
return [ self.new_widget, self.old_widget ]
return [ self.new_widget, self.old_widget ] # E1101
def null_render(d, width, height, st, at):
@@ -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, surf)
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,223 @@ 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
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:
@@ -877,231 +1079,11 @@ def MoveTransition(delay, old_widget=None, new_widget=None, factory=None, enter
# This calls merge_slide to actually do the merging.
rv = merge_slide(old_widget, new_widget)
rv.delay = delay
rv.delay = delay # W0201
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:
+2 -7
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -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))
+1 -1
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
+9 -6
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -23,7 +23,7 @@
# renpy object, as well as the context object.
import renpy
import copy
class Delete(object):
pass
@@ -36,6 +36,8 @@ class PredictInfo(renpy.object.Object):
def __init__(self, pi=None):
super(PredictInfo, self).__init__()
if pi:
self.images = renpy.display.core.ImagePredictInfo(pi.images)
else:
@@ -82,6 +84,8 @@ class Context(renpy.object.Object):
def __init__(self, rollback, context=None):
super(Context, self).__init__()
self.current = None
self.call_location_stack = [ ]
self.return_stack = [ ]
@@ -176,7 +180,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()
@@ -253,7 +257,7 @@ class Context(renpy.object.Object):
"""
if not self.current:
raise "Context not capable of executing Ren'Py code."
raise Exception("Context not capable of executing Ren'Py code.")
if return_site is None:
return_site = self.current
@@ -345,8 +349,7 @@ class Context(renpy.object.Object):
print "While predicting images."
# We accept that sometimes prediction won't work.
pass
self.predict_info = old_predict_info
+55 -23
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -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
@@ -484,7 +508,7 @@ def predict_say(who, what):
"""
if who is None:
who = renpy.store.narrator
who = renpy.store.narrator # E1101
if isinstance(who, (str, unicode)):
return renpy.store.predict_say(who, what)
@@ -507,7 +531,7 @@ def say(who, what, interact=True):
what = what % tag_quoting_dict
if who is None:
who = renpy.store.narrator
who = renpy.store.narrator # E1101
if isinstance(who, (str, unicode)):
renpy.store.say(who, what, interact=interact)
@@ -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):
@@ -1012,7 +1033,7 @@ def launch_editor(filenames, line=1, transient=0):
cmd = cmd.replace('""', '')
try:
subprocess.Popen(split_args(cmd))
subprocess.Popen(split_args(cmd)) # E1101
return True
except:
if renpy.config.debug:
@@ -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,21 +1242,24 @@ 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
class placement(renpy.python.RevertableObject):
def __init__(self, p):
super(placement, self).__init__()
self.xpos = p[0]
self.ypos = p[1]
self.xanchor = p[2]
self.yanchor = p[3]
self.xoffset = p[4]
self.yoffset = p[5]
self.subpixel = p[6]
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]
return o
return placement(p)
# User-Defined Displayable stuff.
@@ -1250,6 +1277,11 @@ class Container(renpy.display.core.Displayable, renpy.python.RevertableObject):
def get_roll_forward():
return renpy.game.interface.shown_window
def cache_pin(*args):
for i in args:
renpy.display.im.cache.pin_image(renpy.easy.displayable(i))
# This is a map from a definition to the place where it was
# defined.
definitions = collections.defaultdict(list)
+18 -15
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -42,6 +42,9 @@ searchpath = [ ]
# The options that were read off the command line.
options = None
# The game's script.
script = None
# A shallow copy of the store dictionary made at the end of the init
# phase. If a key in here points to the same value here as it does in
# the store, it is not saved.
@@ -113,31 +116,31 @@ class Preferences(object):
Stores preferences that will one day be persisted.
"""
def reinit(self):
self.fullscreen = False
self.skip_unseen = False
self.text_cps = 0
self.afm_time = 0
self.afm_enable = True
self.fullscreen = False # W0201
self.skip_unseen = False # W0201
self.text_cps = 0 # W0201
self.afm_time = 0 # W0201
self.afm_enable = True # W0201
# These will be going away soon.
self.sound = True
self.music = True
self.sound = True # W0201
self.music = True # W0201
# 2 - All transitions.
# 1 - Only non-default transitions.
# 0 - No transitions.
self.transitions = 2
self.transitions = 2 # W0201
self.skip_after_choices = False
self.skip_after_choices = False # W0201
# Mixer channel info.
self.volumes = { }
self.mute = { }
self.volumes = { } # W0201
self.mute = { } # W0201
# Joystick mappings.
self.joymap = dict(
self.joymap = dict( # W0201
joy_left="Axis 0.0 Negative",
joy_right="Axis 0.0 Positive",
joy_up="Axis 0.1 Negative",
@@ -171,7 +174,7 @@ class RestartException(Exception):
been changed, and therefore execution needs to be restarted.
"""
def __init__(self, contexts, label):
def __init__(self, contexts, label): # W0231
self.contexts = contexts
self.label = label
@@ -181,7 +184,7 @@ class FullRestartException(Exception):
destroying the store and config and so on.
"""
def __init__(self, reason="end_game"):
def __init__(self, reason="end_game"): # W0231
self.reason = reason
+5 -3
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -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.
@@ -124,7 +126,7 @@ def check_file(what, fn):
check_file_cache[fn] = True
try:
renpy.loader.transfn(fn)
renpy.loader.transfn(fn)
except:
return
+4 -2
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -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)
+4 -3
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -28,7 +28,6 @@ import StringIO
import cStringIO
import zipfile
import time
import os
import os.path
import re
@@ -408,6 +407,8 @@ def MultiPersistent(name):
except:
pass
fn = "" # prevent a warning from happening.
# Find the first file that actually exists. Otherwise, use the last
# file.
for fn in files:
@@ -420,7 +421,7 @@ def MultiPersistent(name):
except:
rv = _MultiPersistent()
rv._filename = fn
rv._filename = fn # W0201
return rv
+13 -10
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -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
@@ -129,7 +131,7 @@ def main():
renpy.config.searchpath = [ renpy.config.gamedir ]
# Find the common directory.
commondir = __main__.path_to_common(renpy.config.renpy_base)
commondir = __main__.path_to_common(renpy.config.renpy_base) # E1101
if os.path.isdir(commondir):
renpy.config.searchpath.append(commondir)
@@ -177,7 +179,7 @@ def main():
# Find the save directory.
if renpy.config.savedir is None:
renpy.config.savedir = __main__.path_to_saves(renpy.config.gamedir)
renpy.config.savedir = __main__.path_to_saves(renpy.config.gamedir) # E1101
if renpy.game.options.savedir:
renpy.config.savedir = renpy.game.options.savedir
@@ -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()
+3 -3
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -51,10 +51,10 @@ class Object(object):
self.__dict__.update(new_dict)
if version != self.__version__:
self.after_upgrade(version)
self.after_upgrade(version) # E1101
if self.after_setstate:
self.after_setstate()
self.after_setstate() # E1102
# We don't handle slots with this mechanism, since the call to vars should
# throw an error.
+29 -15
View File
@@ -1,4 +1,4 @@
# Copyright 2004-2009 PyTom <pytom@bishoujo.us>
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
@@ -25,7 +25,6 @@
import codecs
import re
import os
import sets
import renpy
import renpy.ast as ast
@@ -82,6 +81,15 @@ class ParseError(Exception):
def __unicode__(self):
return self.message
# Something to hold the expected line number.
class LineNumberHolder(object):
"""
Holds the expected line number.
"""
def __init__(self):
self.line = 0
def unicode_filename(fn):
"""
Converts the supplied filename to unicode.
@@ -344,7 +352,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',
@@ -378,7 +386,16 @@ class Lexer(object):
self.eob = False
self.line = -1
# These are set by advance.
self.filename = ""
self.text = ""
self.number = 0
self.subblock = [ ]
self.pos = 0
self.word_cache_pos = -1
self.word_cache_newpos = -1
self.word_cache = ""
def advance(self):
"""
@@ -717,12 +734,12 @@ class Lexer(object):
extending to a colon.
"""
rv = self.delimited_python(':')
pe = self.delimited_python(':')
if not rv:
if not pe:
self.error("expected python_expression")
rv = renpy.ast.PyExpr(rv.strip(), rv.filename, rv.linenumber)
rv = renpy.ast.PyExpr(pe.strip(), pe.filename, pe.linenumber) # E1101
return rv
@@ -868,10 +885,7 @@ class Lexer(object):
rv = [ ]
# Something to hold the expected line number.
class Object(object):
pass
o = Object()
o = LineNumberHolder()
o.line = self.number
def process(block, indent):
@@ -1156,7 +1170,7 @@ def parse_parameters(l):
add_positional = True
names = sets.Set()
names = set()
if not l.match(r'\('):
return None
@@ -1212,7 +1226,7 @@ def parse_parameters(l):
parameters.append((name, default))
if add_positional:
positional.append(name)
positional.append(name)
if l.match(r'\)'):
break
@@ -1535,7 +1549,7 @@ def parse_statement(l):
rv = ast.Define(loc, name, expr)
if not l.init:
rv = ast.Init(loc, [ rv ], priority)
rv = ast.Init(loc, [ rv ], priority)
l.advance()
@@ -1811,7 +1825,7 @@ def report_parse_errors():
if renpy.config.editor:
renpy.exports.launch_editor([ 'errors.txt' ], 1, transient=1)
else:
os.startfile('errors.txt')
os.startfile('errors.txt') # E1101
except:
pass

Some files were not shown because too many files have changed in this diff Show More