Compare commits

..

195 Commits

Author SHA1 Message Date
tom 311a09fb97 Tagging 5.4.1
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/tags/renpy-5.4.1@413 ef037c1b-3fee-0310-a5a7-a1260de54e99
2006-02-13 01:24:43 +00:00
tom df4154c854 A new variable, config.auto_choice_delay, has been added. If not None,
this variable gives a number of seconds that Ren'Py will pause at an
in-game menu before picking a random choice from that menu. We'd
expect this variable to always be set to None in released games, but
setting it to a number will allow for automated demonstrations of
games without much human interaction.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@270 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-11-04 15:07:06 +00:00
tom cbe66f8353 There is now a new function, LiveComposite, that can composite
together arbitrary displayables, rather than just images. It has the
same API as im.Composite, but should be used when one of the things
you wish to composite is an animation.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@269 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-11-03 03:47:59 +00:00
tom 143db03196 git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@268 ef037c1b-3fee-0310-a5a7-a1260de54e99 2005-11-02 17:10:54 +00:00
tom e879687a16 Character objects now can take properties prefixed with what_ or
window_. Properties prefixed with what_ are applied to the text being
spoken, while those prefixed with window_ are applied to the window
containing everything. Unprefixed properties are still applied to the
label giving the name of the character speaking.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@267 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-11-01 01:20:57 +00:00
tom fcb3286df9 Implemented a new text tag, {fast}. This tag causes the slow text
display to start from a given point in the text string. This allows
one to show some text, run some command, and show the same text with
additions, and have the slow text display occur correctly.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@266 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-10-30 01:29:08 +00:00
tom ba23df21ab Fixed Motion (the class that implements Move and Pan) to allow motions
to be used as transitions, in conjunction with the say and menu
statements. Previously, they only worked with the with statement.




git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@265 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-10-29 21:33:08 +00:00
tom 5f6f3d8e70 git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@261 ef037c1b-3fee-0310-a5a7-a1260de54e99 2005-10-26 03:08:45 +00:00
tom 9d7cd97fcc Added a new extra, quick_save.rpy, that adds a quick save feature to
Ren'Py. This feature adds a single save slot that can be quickly
accessed without going through the game menu. It also adds a quick
load button to the main menu, which causes a load from this slot. The
button is disabled if no quick save game exists.

To support this, changed the format of library.main_menu. Now, instead
of being a list of pairs, library.main_menu is a list of triples. The
new third component is an expression, which must evaluate to true for
the menu button to be enabled.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@260 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-10-26 02:26:53 +00:00
tom a90491b678 Adding raw strings.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@258 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-10-19 21:03:53 +00:00
tom ae8fc4b859 Adding raw strings.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@257 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-10-19 21:03:29 +00:00
tom c4605e915d Fixed regression in lint caused by imspec change.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@255 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-10-19 14:22:06 +00:00
tom e809b24663 Fixed regression affecting nested ctcs.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@251 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-10-15 02:46:37 +00:00
tom ebf669e8af Fixed changelog.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@250 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-10-15 00:32:54 +00:00
tom 3b7b40b85a Increased the default rollback length to back 100, now that we have a
readback extra people can use if they want to. Updated readback so it
works a little better.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@249 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-10-15 00:32:39 +00:00
tom 4225f92095 git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@248 ef037c1b-3fee-0310-a5a7-a1260de54e99 2005-10-13 04:14:34 +00:00
tom 31241ca637 Implemented two new text tags, {w} and {p}. {w} pauses the display of
dialogue, waiting for the user to click to continue. {p} does the same
thing, but also breaks the line where it occurs.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@246 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-10-13 03:17:39 +00:00
tom 6e06e155dd Added a framerate limiter. When enabled by setting config.framerate,
Ren'Py limits the number of frames that are displayed per second to
the supplied values. This tends to smooth out the framerate, and hence
the percieved smoothness of the program. It will lower the overall
framerate, but make it more regular.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@245 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-10-09 04:47:12 +00:00
tom c7059bc3cb The scene, show, and hide statements now take an onlayer clause, which
gives the layer that the operations occur on. So if we declare high to
be another layer (by setting config.layers to something like 
[ 'master', 'high', 'transient', 'overlay' ]), then one can use a
statement like "show eileen happy onlayer high" to show the given
image on the high layer. This image will not be removed when scene
statements clear other layers, such as the default master layer.

To support the above, the parameters to renpy.show() changed in an
incompatible way. If your code uses renpy.show(), it will need to be
upgraded. Instead of considering the second and later parameters to be
at expressions, it now takes as its second parameter a list of all at
expressions. (This lets us use the third parameter to accept the layer
name.) 

The label 'after_load' is now called after a game is loaded, if it
exists on disk. This label can be used to upgrade save files, restore
music, and the like.

It's now possible to pick the screen the game menu enters when it is
invoked, by setting the _game_menu_screen variable.

Simplified the demo game script by moving the style stuff out of that
first init block, and down to the bottom of the script where it's out
of the way of a first viewing. Hopefully, this will reduce the shock
of someone first encountering Ren'Py.

Documented how to modify and replace the game and main menus, and how
to add in one's own preferences.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@242 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-09-24 23:45:20 +00:00
tom f6c4f7fda1 The label 'after_load' is now called after a game is loaded, if it
exists on disk. This label can be used to upgrade save files, restore
music, and the like. 



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@241 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-09-16 04:04:19 +00:00
tom a6f04a6741 5.1.2
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@238 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-09-15 03:27:21 +00:00
tom 12e4028979 Ready for build...
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@237 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-09-15 02:29:57 +00:00
tom f06e4ab954 Custom mouse support has been totaly rewritten. It now supports
animated mice, and changing the mouse cursor based on the kind of
interaction that is ongoing. Rather than describe the changes here,
read the documentation of config.mouse to understand the new
behavior. Please note that config.mouse has changed, and so if you use
it in your game (and AFAIK noone does), it will need to be modified.

Custom mouse support has also had significant performance
improvements.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@236 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-09-14 16:51:07 +00:00
tom be98f91907 Mouse perf improvements.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@235 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-09-14 04:33:08 +00:00
tom ada05d2eb2 A new widget, anim.Blink, blinks a child widget in and out of
existence by varying its alpha channel. [doc]

Character now allows for the use of a click-to-continue widget when
the widget finishes showing text to the user. While many widgets can
be used, this feature is especially useful with Images, Animations,
and anim.Blink. The click-to-continue widget can be nestled in with
the end of the text, or placed at a fixed location on the screen.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@234 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-09-13 01:57:49 +00:00
tom 1d355ceb0b Ren'Py now supports embedding images inside text. Please read the
documentation of ui.text for some important caveats about how this
works, but basically, the input of ui.text can be a string or a list
containing strings and widgets. In the latter case, the widgets are
rendered inside the text. One can also use a text tag like
{image=filename.png} to include an image anywhere a text tag
works. One thing to realize is that images so included cannot be any
bigger then the text they are included with.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@233 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-09-12 05:03:47 +00:00
tom e26d93a3fa git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@231 ef037c1b-3fee-0310-a5a7-a1260de54e99 2005-09-08 03:22:12 +00:00
tom f622a4f7b6 git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@225 ef037c1b-3fee-0310-a5a7-a1260de54e99 2005-08-25 00:14:45 +00:00
tom 7cb63a3db9 git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@224 ef037c1b-3fee-0310-a5a7-a1260de54e99 2005-08-24 02:11:25 +00:00
tom 42b11c2e74 git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@223 ef037c1b-3fee-0310-a5a7-a1260de54e99 2005-08-23 01:40:00 +00:00
tom f4d5ef1425 git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@222 ef037c1b-3fee-0310-a5a7-a1260de54e99 2005-08-21 14:06:37 +00:00
tom 8109a8dbfe git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@221 ef037c1b-3fee-0310-a5a7-a1260de54e99 2005-08-21 13:34:54 +00:00
tom c8c1b93894 git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@219 ef037c1b-3fee-0310-a5a7-a1260de54e99 2005-08-14 19:21:40 +00:00
tom 597be879e4 git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@218 ef037c1b-3fee-0310-a5a7-a1260de54e99 2005-08-12 02:17:31 +00:00
tom 3d1a2e4d96 Ready to test, almost.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@217 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-08-12 01:56:36 +00:00
tom 00401fd0e9 git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@216 ef037c1b-3fee-0310-a5a7-a1260de54e99 2005-08-11 23:39:00 +00:00
tom 6eef431161 Fixed a bug that prevented rollback of the info object.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@215 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-08-10 03:10:42 +00:00
tom f3b31c8025 More work on renpy.audio
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@214 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-08-09 02:26:38 +00:00
tom df4fa900e9 git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@213 ef037c1b-3fee-0310-a5a7-a1260de54e99 2005-08-08 02:53:38 +00:00
tom fbd92b66b0 Working on sound.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@212 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-08-08 01:54:40 +00:00
tom a29fd3aa8b git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@211 ef037c1b-3fee-0310-a5a7-a1260de54e99 2005-08-08 01:16:06 +00:00
tom c9af317092 Menu text now supports percent-substitutions, like say statements
always did.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@210 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-07-29 12:24:52 +00:00
tom 91fdd68ec1 Fixed object rollback bug.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@209 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-07-28 14:14:40 +00:00
tom c8b90b04e2 git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@207 ef037c1b-3fee-0310-a5a7-a1260de54e99 2005-07-27 03:27:00 +00:00
tom 8c85390aaf Finalizing 5.0.1.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@203 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-07-26 02:46:01 +00:00
tom b77f295921 Finalizing 5.0.1.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@202 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-07-26 02:35:30 +00:00
tom c0e3dfc99b Finalizing 5.0.1.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@201 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-07-26 02:34:17 +00:00
tom f5c6ea530d The hovered callback on buttons was no longer working. This is now
fixed. Also added a complementary unhovered callback.

A number of changes have been made to Ren'Py, that shrink the zip file
by over ... k.

The math module is now included.

The presplash screen now displays without a title-bar.




git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@200 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-07-21 04:08:26 +00:00
tom ce7ccc2f87 Updated demo game. Ready for 5.0.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@194 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-06-28 12:37:59 +00:00
tom a4d1670378 git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@190 ef037c1b-3fee-0310-a5a7-a1260de54e99 2005-06-24 00:47:03 +00:00
tom c143c0c479 Fixed demo.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@189 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-06-23 03:14:21 +00:00
tom f7cb4eae9c Added config.font_replacement_map, which is used to map from a regular
font to a version of that font that is specialized as italic, bold, or
both.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@188 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-06-23 03:04:28 +00:00
tom bb35ff5658 Readying 4.8.9.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@185 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-06-18 00:56:30 +00:00
tom b479fd4a06 Fixed a bug that was preventing RevertableObjects from supporting
properties.


git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@184 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-06-17 02:04:18 +00:00
tom c9c0ac5809 Removing DSE from RenPY VC.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@183 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-06-16 16:52:57 +00:00
tom 04cbf7620c There is now a preference that controls skipping after choices.
The new function renpy.choice_for_skipping should be called by user
code to indicate that a choice is occuring, and therefore we might
want to end skipping.




git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@182 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-06-14 01:24:21 +00:00
tom 6770b268fc 4.4.8
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@178 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-06-12 15:24:59 +00:00
tom 60f988dc6c git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@177 ef037c1b-3fee-0310-a5a7-a1260de54e99 2005-06-12 14:31:29 +00:00
tom a8e8dc4f49 Unicode support has been extended to names in the script. Now names in
the script can contain unicode characters, as well as ascii
characters. This includes labels and image names. Right now, we
consider all unicode characters to be alphabetic, so be sure to use
ASCII space where spaces are required.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@176 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-06-12 14:26:46 +00:00
tom 622db83c50 Auto-forward-mode has been implemented. It is controlled by its own
preference, which gives the number of seconds for which a given number
of characters is shown to the user. The number of characters is
configured by config.afm_characters, which defaults to 250. The number
of characters is determined by the length of the string shown to the
user with a number of bonus characters added to it. The number of
bonus characters is configurable in config.afm_bonus, which defaults
to 25. Auto-forward-mode can be hidden from the user by setting 
library.had_afm to False.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@175 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-06-10 03:53:09 +00:00
tom d17b68a17c Added old_day_planner.
Now, the day planners will not let the user continue unless every
period has been assigned a valid value.




git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@173 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-06-09 17:06:00 +00:00
tom 8d0465e72e 4.8.7
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@170 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-06-09 03:37:41 +00:00
tom 3dc117ed96 Getting ready for 4.8.7.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@169 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-06-09 03:10:56 +00:00
tom 111b7e440d DSE.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@168 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-06-08 20:54:53 +00:00
tom 3e80c3acbb A new im.Tile image operator has been introduced. This operator tiles
a source image until it reaches a specified size, or the size of the
screen if no size is specified.

Ren'Py now supports a presplash screen. If the file presplash.png is
present in the game directory, it is shown to the user on
startup. This occurs before any loading or initialization occurs, so
the size of the window it is shown in is determined by the size of the
presplash.png image itself. 



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@166 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-06-07 21:35:17 +00:00
tom 56b6135b8e Implemented ImageDissolve, which is a transition that uses images to
control how the dissolve occurs.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@165 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-06-07 04:54:24 +00:00
tom 24ec412f1e The definitions found in common/definitions.rpy are now documented in
the reference. This gives a default set of transitions and positions,
as well as an image (black).



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@164 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-06-06 03:47:52 +00:00
tom cd987bdb6d The definitions found in common/definitions.rpy are now documented in
the reference. This gives a default set of transitions and positions,
as well as an image (black).



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@163 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-06-05 23:29:12 +00:00
tom d6f3b7aab0 Fade has been reimplemented in terms of Dissolve. This means that
fades will be as fast as dissolves. Fade now also can take a widget,
instead of a color, as an argument. If this widget is an Image, it
means that we will dissolve from the old screen to the image, hold at
the image for a given amount of time, and then dissolve from the image
to the new screen.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@162 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-06-04 15:10:39 +00:00
tom f2f9db46e9 As per user request, we have made programmatic equivalents of the
image, scene, show, and hide statements available. These functions are
named renpy.image, renpy.scene, renpy.show, and renpy.hide,
respectively.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@161 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-06-04 13:28:00 +00:00
tom 57c38e0363 Ren'Py now supports a new classification of layer, top layers. Top
layers are layers that are displayed above any transition. This is
useful if you want to have an overlay that is shown even when a
transition is in progress. To have the overlays be displayed as a 
top_layer, remove the string 'overlay' from config.layers and append
it to config.top_layers.

A new config variable, config.enable_fast_dissolve, was
introduced.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@160 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-06-04 12:35:44 +00:00
tom 6d055e775a Fixed bugs that caused blinking in overlay.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@159 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-06-03 14:32:00 +00:00
tom 48033b3b1e Ren'Py now supports a presplash screen. If the file presplash.png is
present in the game directory, it is shown to the user on
startup. This occurs before any loading or initialization occurs, so
the size of the window it is shown in is determined by the size of the
presplash.png image itself. 



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@158 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-06-02 18:05:07 +00:00
tom 9d57e0dad1 Separated out display, font, and mixer initialization code.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@157 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-06-02 16:46:03 +00:00
tom bed546e6e6 Added a RENPY_DISABLE_SOUND environment variable, which if set
disables support for sound in Ren'Py. (For use on platforms where
sound doesn't quite work.)

Fixed a bug in lint.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@156 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-06-01 21:20:39 +00:00
tom 94a9422ddc 4.8.6 made
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@150 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-29 16:11:30 +00:00
tom 8f7bd1be77 DynamicCharacter and Character have been unified into a single class,
such that now calling DynamicCharacter is equivalent to calling
Character with dynamic=True.

Character (and DynamicCharacter, and renpy.display_say) now take a new
argument, image. If this argument is set to True, then the name of the
character is interpreted as an image filename. This image is used
where the character's name would go, in place of a textual name.




git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@149 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-29 15:33:32 +00:00
tom e863d4a645 Ready for 4.8.6.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@148 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-29 02:57:14 +00:00
tom 8d1cf70edc Module version up.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@147 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-29 02:23:26 +00:00
tom eadb1c6385 Add document on how to release renpy games.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@146 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-29 02:17:38 +00:00
tom ad51d6a674 Ren'Py now takes a new option, --lint. (Or for those of you under
Windows, run lint.bat, editing it if necessary.) This option, when
supplied, causes Ren'Py to run checks for dozens of errors in the
script. Many of these checks test for problems that will only occur
at runtime, on platforms other than Windows, or when loading a
save-game after a change in script. This is the subtle stuff that my
script-review service was for... now it's automated, so you don't need
me anymore. 

Lint should be run before you release any game with Ren'Py, from now
on. In general, you should not release a game if lint gives you any
errors, but instead you should fix those errors first.

Lint also produces a count of the number of say statments and menus in
a program.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@145 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-29 00:44:56 +00:00
tom 6880da07b7 Fixed a bug in the _renpy module, in which we accidentally used the
height, rather than the width, of an image.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@144 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-28 20:02:43 +00:00
tom 35408d81ea git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@141 ef037c1b-3fee-0310-a5a7-a1260de54e99 2005-05-26 00:32:09 +00:00
tom d75eb13658 Ready for release, I think.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@140 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-25 23:06:51 +00:00
tom dc3a01aae4 Changed the look of the frame.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@139 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-25 21:41:55 +00:00
tom 1792f7a7af There is now a new config variable, config.text_tokenizer. This
variable is used to give a function that breaks a line of text up into
words, spaces, and other things. Providing a custom function here
allows for control of where line breaking is allowed, useful for
languages that have specific rules about that.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@138 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-25 19:47:50 +00:00
tom eb82c47109 Fixed bugs in image color mapping.
Got script ready for release.


git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@137 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-25 04:15:02 +00:00
tom 229748a68e Updated the Ren'Py module to 4.8.5.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@136 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-24 21:24:22 +00:00
tom d5d0d12697 There are now two new image operators. im.Map can map the pixels
values in an image to different values. Using this, one can adjust the
colors of an image. The im.Alpha function is built on top of this, and
allows one to alter the alpha of an image. (It even adjusts a
pre-existing alpha channel.)



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@135 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-24 20:53:59 +00:00
tom 6bce3b0e9a The SMAnimation framework can also be used to describe very
complicated, even nondeterministic, motions. This is done by declaring
a SMAnimation with None for the images, and then passing it in to the
at clause.

All motions (Motion, Pan, Move, and anim.SMAnimation when used as a
motion) can now be used as transitions, in which case the motion is
applied to the screen (or layer, as appropriate). This let us put
together two new transitions, hpunch and vpunch, which shake the
screen horizontally and vertically, as appropriate. Useful for when
the POV character gets punched by a particularly feisty girl.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@134 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-24 19:53:35 +00:00
tom 349f2479d3 Removed xblur32 code.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@133 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-24 05:05:41 +00:00
tom 75d2f81973 Before removing blur code.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@132 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-24 04:58:07 +00:00
tom eadbdebcb0 git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@131 ef037c1b-3fee-0310-a5a7-a1260de54e99 2005-05-24 01:41:47 +00:00
tom 196e3701e9 Added a new, state-machine based animation function,
anim.SMAnimation. This function creates animations by applying images
and transitions specified by the states and edges of a nondeterminstic
state machine. The result is that it's possible to specify
complicated random patterns of behavior. This can allow a character to
blink randomly, allow random backgrounds to be shown, and even allow
things to randomly move around the screen. 



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@130 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-24 01:39:18 +00:00
tom a2904a7618 MoveTransition works with pairs of displayables.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@129 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-23 18:51:20 +00:00
tom 3a2fc5498a Fixed the gallery.rpy extra, so that it now works properly with the
main menu being in a menu context. 



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@128 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-22 03:23:31 +00:00
tom c3757fdea9 4.8.4
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@124 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-14 02:57:47 +00:00
tom 6ee37d4933 Readying 4.8.4.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@122 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-14 00:54:51 +00:00
tom 4ded3eba45 The xanchor and yanchor arguments can now take numbers between 0 and 1
as well as names. Functions returned by Motion now can either return
an xpos, ypos tuple or a xpos, ypos, xanchor, yanchor tuple. Move has
been upgraded so that it can take similar tuples as the start and
end arguments, letting us interpolate the location of the anchors
while moving an image around.

The above modification allowed us to implement a new move
transition. This transition attempts to find images that are present
in both the old and new scenes, but have changed location between the
two scenes. Such images are moved from the old location to the new
location over the duration of the move transition. This makes it easy
to smoothly move characters from one location to another on the
screen.

The demo script was updated and reorganized, to demonstrate more
features.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@120 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-12 19:15:55 +00:00
tom 277c7b4d88 Removed some unnecessary conversion from pixellate, improving its
performance when running on a computer with 32 bits per pixel
graphics. 

Implemented a basic map function, but haven't tested it yet.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@119 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-12 03:46:30 +00:00
tom 403bb65826 The format of the compiled script (.rpyc) files has changed. The new
format is more efficent, both in terms of space and memory. 
Unfortunately, the format change is not backwards compatible,
and the automatic upgrade function probably won't work. So you'll need
to delete the rpyc files from the game directory when you copy it
over.




git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@117 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-09 20:10:34 +00:00
tom 0d1946f3bc git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@116 ef037c1b-3fee-0310-a5a7-a1260de54e99 2005-05-07 18:29:23 +00:00
tom 61381a2f12 Voice support.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@115 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-07 14:56:52 +00:00
tom 168729e9d9 Speedup loadable.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@114 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-07 06:45:04 +00:00
tom 42a2d2c8c0 A new Motion function allows the user to give a function that controls
how a displayable moves on the screen, allowing for customizable
motions. Pan and Move have been reimplemented in terms of Motion. All
three functions now take repeat and bounce parameters. Repeat causes
the motion to repeat after a single period is over, while bounce
causes the motion to bounce from extreme to extreme.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@113 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-07 05:44:02 +00:00
tom 42c8f4339c git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@111 ef037c1b-3fee-0310-a5a7-a1260de54e99 2005-05-07 04:00:03 +00:00
tom 8c7ca92e54 Fixed bugs in windows midi support.
Removed config.music_callback, replaced with interact_callbacks.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@109 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-07 03:35:54 +00:00
tom 0919f556b4 Removed psyco.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@108 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-06 06:07:22 +00:00
tom 50bb65973b Updates for 4.8.2a.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@105 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-04 00:00:30 +00:00
tom 660fa3114e 4.8 Release
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@102 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-03 03:40:17 +00:00
tom 9ebad42f5a Wrote a readme for the module.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@99 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-03 01:19:11 +00:00
tom cd8acdcd8a Moved the main menu into the same context as the game menu.
A number of changes to the menus.

The ability to run things in their own contexts.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@98 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-03 00:56:37 +00:00
tom 9bbecc250d Two-window-say extra, conditional dialogue.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@97 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-02 18:31:26 +00:00
tom 518a10cae0 Implemented pixellate transition, changed version of the Ren'Py module.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@96 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-02 16:31:06 +00:00
tom c1206e7fbd More work on the renpy module.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@95 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-02 04:36:53 +00:00
tom daaba9f294 Initial checkin of RenPy module.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@94 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-05-01 21:36:19 +00:00
tom 2e864c971d Unicode support in python blocks now works. This allows unicode
strings to be used with Ren'Py. This is especially useful when naming
characters and translating the various menus into your native
language. Please note that the only unicode allowed is inside unicode
strings, which begin with a u before the first quote. Unicode outside
of unicode strings is an error.

The special labels intended for main menu use, _continue and
_preferences, now call a user main menu after they finish executing,
rather than the library main menu. This simplifies the implementation
of user-defined main menus.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@93 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-04-29 03:44:46 +00:00
tom 5b9494ebcc PyLint done.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@91 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-04-26 14:49:05 +00:00
tom d228af6ffd Version up!
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@90 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-04-26 04:19:17 +00:00
tom 454f103818 git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@89 ef037c1b-3fee-0310-a5a7-a1260de54e99 2005-04-26 03:28:00 +00:00
tom e26989c288 An empty string is now rendered as if it was a string consisting of a
single space. This fixes a bug in which an empty string was rendered
with zero width and height.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@88 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-04-26 03:08:20 +00:00
tom 5c06b96c18 Update documentation.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@87 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-04-26 02:57:47 +00:00
tom d3bfda1a11 Character objects are no longer limited to displaying through
renpy.display_say, but can now be supplied a function argument, which
is a function that is called instead. This will make it easier to
radically change how dialogue is displayed.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@86 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-04-26 02:49:43 +00:00
tom 0308d48953 There is a new spinner preference type, which allows a value to be
incremented or decremented. This preference is now used to adjust the
speed at which text is shown to the user. So now this is controlled by
the user, rather than the config.annoying_text_cps parameter. If you
don't want to give the user this control, you can set library.has_cps
to False. A number of new styles define the spinner. [ document ]




git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@85 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-04-26 02:15:38 +00:00
tom 9525db2212 The way in which preferences are displayed has been made more
configurable. Now, there is a new variable, library.preferences, which
is a map from a style to a list of preferences to be displayed in a
vbox with that style. There are now two new styles (prefs_left and
prefs_right) which control the placement of the default preference 
columns. [ document ]



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@84 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-04-26 01:14:34 +00:00
tom 7afca9d5d5 There are two new style properties, xmaximum and ymaximum. These two
properties limit the size of the widgets that they are applied to, as
if that widget was placed inside a ui.sizer(). (In fact, ui.sizer() is
now implemented in terms of these properties.) [ document ]

Now, we only restore or rollback to places where all of the transient
layers are empty. This prevents a bug in which additional dialogue
will be lost when a restore or rollback occurs. 



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@83 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-04-26 00:48:17 +00:00
tom ccca92c88a The ui.grid object now has a new argument, transpose, which allows
widgets to be added down the columns first. It also is smarter about
allocating space to subwidgets when xfill or yfill are set.

The file entries in the load and save screens are now arraigned in a
grid, which has the style file_picker_grid. This means that we should
now be smarter in the presence of games of varying size, and we should
wrap text if it gets too long. As part of this,
library.file_picker_length has now been broken out into two variables,
library.file_picker_rows and library.file_picker_cols. [ document ]

renpy.music_stop now supports a fadeout parameter, for orthagonality
with the new renpy.music_start. 

Now, python blocks have the correct filename and line numbers
annotated onto them. This means that tracebacks generated in python
blocks will show a .rpy file and the appropriate line, rather than
showing "<none>" and a random line as they did before.




git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@82 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-04-25 16:25:52 +00:00
tom aa3ff2f012 Changelog fixes.
Added transition support to the gallery extra.


git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@80 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-04-22 14:25:50 +00:00
tom 46e8fdd092 Made the 'h' key now hide the windows, so there's a way to do that on
Mac OS X.

Many pylint inspired bug fixes.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@79 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-04-22 14:03:57 +00:00
tom f2963d33c3 Added focus.py
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@78 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-04-22 02:42:44 +00:00
tom 0c96d52b54 Added gallery script.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@77 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-04-22 02:37:05 +00:00
tom 74678d5cef Bug fixing.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@76 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-04-22 02:36:45 +00:00
tom 3dd6959fe1 Documentation update.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@75 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-04-22 02:26:59 +00:00
tom 7b6ec9db5b Rewrote styles so they're not buggy.
Fixed bugs with refresh.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@74 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-04-22 00:24:27 +00:00
tom 404936dae6 Replaced disabled buttons with the insensitive_ prefix.
Added support for the RENPY_DISABLE_FULLSCREEN environment variable.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@73 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-04-21 19:22:58 +00:00
tom f7de1b0eb0 Implemented new music and sound code.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@72 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-04-21 14:08:01 +00:00
tom 8614e6406d Fixed a bug that prevented character names from beginning with 'u'.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@71 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-04-20 15:09:27 +00:00
tom 0c6e1893e2 Implemented new image code, which now makes it possible and easy to
perform operations on images. This code includes a new size-based
image cache.

Rewrote imagemap in terms of cropped images and imagebuttons.

Added code to load images before peforming a transition.

Added code to store seen images in a dictionary.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@70 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-04-20 02:03:10 +00:00
tom f1bec25291 git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@69 ef037c1b-3fee-0310-a5a7-a1260de54e99 2005-04-11 03:00:50 +00:00
tom 429b34b80f New focus system.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@68 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-04-11 02:26:14 +00:00
tom 5a28ecd5f5 Eliminate game.store.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@67 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-04-06 01:02:44 +00:00
tom ab5d5c0e40 git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@65 ef037c1b-3fee-0310-a5a7-a1260de54e99 2005-04-02 22:57:20 +00:00
tom c28639ef0b 4.7.2 final
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@63 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-04-02 22:13:26 +00:00
tom a3b3d26816 git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@62 ef037c1b-3fee-0310-a5a7-a1260de54e99 2005-04-02 21:36:42 +00:00
tom ee6bbf5d9c git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@61 ef037c1b-3fee-0310-a5a7-a1260de54e99 2005-04-02 21:24:41 +00:00
tom 6e406cdae0 git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@60 ef037c1b-3fee-0310-a5a7-a1260de54e99 2005-04-02 20:44:26 +00:00
tom 8ef2d97247 git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@59 ef037c1b-3fee-0310-a5a7-a1260de54e99 2005-04-02 20:24:34 +00:00
tom e9be405aaf Installer.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@58 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-03-19 23:20:46 +00:00
tom 23dbab98d2 Readback.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@57 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-03-19 19:52:29 +00:00
tom 2865599e34 Added button_game_menu.rpy
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@56 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-03-11 03:39:31 +00:00
tom fb5957186a Changed back library transition.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@54 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-27 04:18:44 +00:00
tom 8d2e592589 Added dump_text
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@53 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-27 04:00:50 +00:00
tom c7714a69fd Added unicode_escape encoding.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@52 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-27 02:51:58 +00:00
tom 6d2dce1704 Fixed bug in subsurface.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@51 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-16 23:35:15 +00:00
tom 8ab32e8dba git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@45 ef037c1b-3fee-0310-a5a7-a1260de54e99 2005-02-14 21:05:59 +00:00
tom 00ee770512 Updated changelog for 4.7.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@44 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-14 20:15:00 +00:00
tom c5761728b3 Updated changelog for 4.7.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@43 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-14 19:33:00 +00:00
tom d33aa31101 Version to 4.7
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@42 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-14 15:38:59 +00:00
tom 34cfc4fa40 Made mixer access much more conservative.
Fixed performance problems with fonts on windows.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@41 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-14 04:31:05 +00:00
tom d603d62680 Documentation for text tags, and enhancements reccomended by it.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@40 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-14 02:17:54 +00:00
tom 4991c5761c Reimplemented Text, to support text tags, which allow the size, color, boldness, italics,
and underline of text to be changed.

Added text properties for bold, italic, and underline.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@39 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-13 23:50:51 +00:00
tom cf3f8afd9f 4.6.2
Fixed bug with no sound card.

Added speedtest.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@37 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-12 22:08:36 +00:00
tom 31fc8b213e Fixed bug in imagemap.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@36 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-11 05:08:28 +00:00
tom 74be98faba Changed console.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@34 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-11 00:31:51 +00:00
tom b4e6b24a86 Fixed bugs with predictive loading and surface reuse.
Updated changelog and version for 4.6.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@33 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-10 20:24:03 +00:00
tom 7c1980775e Fixed memory leak in / rewrote render.py
Added memory leak profiler.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@32 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-10 07:29:10 +00:00
tom 90d586968e Added a framecounter.
Changed dissolve to use compositing rather than drawing twice. Minor speedup. 



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@31 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-09 16:05:18 +00:00
tom af0778b8bc Fixed text of demo game.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@29 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-08 19:02:05 +00:00
tom 23bccf06cb config.overlay_during_wait added.
overlay_menu extra added.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@28 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-08 18:49:37 +00:00
tom 7558b20b1e Bug fixes.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@27 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-08 17:18:04 +00:00
tom 8fbb785674 Updated license.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@26 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-08 05:52:03 +00:00
tom d2210cf08f Added interact parameters to various says.
Added button_menu extra.

Fixed Lemmasoft url.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@25 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-08 05:51:30 +00:00
tom 8d8ba4fb00 Added the preferences screen to the main menu.
Readied the changelog and demo script for release.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@24 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-08 05:05:22 +00:00
tom 915df21775 Broke up the margin and padding properties.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@23 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-08 03:47:17 +00:00
tom 59c7baf1ff Added support for activating widgets.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@22 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-08 02:58:33 +00:00
tom dc0d2f8039 Minor fixes.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@21 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-08 02:05:11 +00:00
tom bcf752d3a6 Updated documentation to reflect previous checkin.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@20 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-08 01:48:45 +00:00
tom d95cd1f6a0 Added layer support.
Added interaction restart support.

Added support for game menu transitions.

Eliminated renpy.interact()





git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@19 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-08 01:21:45 +00:00
tom c9f025dab2 Fixed bug in demo script. :-(
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@18 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-07 05:00:26 +00:00
tom d484cc2906 Fixed bug in distribute.py
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@16 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-05 05:00:45 +00:00
tom 18cf867432 Ready for the release of 4.5.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@15 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-05 04:55:45 +00:00
tom 149a2904a5 Added renpy.exists.
Made demo play video, if it exists.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@14 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-04 05:05:20 +00:00
tom ef2e78616f Bug fix in library.
Updated documentation and changelog.

Improved error reporting by printing error message at the top of 
traceback.txt.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@13 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-03 15:30:34 +00:00
tom 2711f79080 Implemented grid widget.
Changed the library to use constructors and grids.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@12 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-03 06:45:58 +00:00
tom fa31e03d06 Fixed bug where screen would not redraw after changing from fullscreen to
windowed, or vice-versa.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@11 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-02 18:31:10 +00:00
tom 6a27954677 New transition: CropMove
Extras directory for interesting sample code. It now includes kanamode
and fullscreen examples. An extragame tree exists to test out some of 
this code.

Now create Solids with an alpha of 255 as a surface w/o an alpha
channel.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@10 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-02 18:24:05 +00:00
tom eab1edd5b4 All new rendering code. Replaces renpy.surface.Surface with
renpy.render.Render, which handles caching and clipping properly. 



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@9 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-01 19:10:42 +00:00
tom b9624fe922 Redid the display routines so that everything is a widget inside an
interaction. It's one less thing to think of when doing transitions.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@8 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-02-01 05:31:39 +00:00
tom 69727f3baf Speed improvements to the library (we clear the unseed screne list before
showing the main or game menus).

Speed improvements with graphical mice, and also make sure that it works
with movies.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@7 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-01-31 15:30:10 +00:00
tom 0551eb6135 Rewrote movie support. Now, we also support overlaying things onto movies.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@6 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-01-31 06:34:59 +00:00
tom c0b8ca8777 Various minor speed improvements.
Turned renpy.sound and renpy.music into renpy.display.audio.

Added renpy.display.video, and the ability to play MPEG-1 video.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@5 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-01-29 16:05:58 +00:00
tom 7af2e3d066 Added ui.pausebehavior(). This separates pausing from the saybehavior
paving the way for uninterruptable pauses (a bad idea, IMO) and menus
that dismiss themseleves after a certain amount of time.



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@4 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-01-28 03:29:22 +00:00
tom 0a857f8879 Added the ability to bind mouse events to mouseup as well as
mousedown, and changed some of the default bindings to be on mouseup
rather than mousedown. If you make changes to config.keymaps, you'll
need to change mouse_1 to mousedown_1, and so on for various other
button numbers. 

Fixed a bug in which hiding the UI was not working properly. (This 
broke the center mouse button behavior.)



git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@3 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-01-28 01:30:56 +00:00
tom 839073ad8c Deleted release.txt.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@2 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-01-22 07:46:04 +00:00
tom eb22c24884 Initial import.
git-svn-id: file:///home/tom/magnetic/ab/cvs-and-svn/svn-repos/renpy/trunk@1 ef037c1b-3fee-0310-a5a7-a1260de54e99
2005-01-22 07:43:23 +00:00
1662 changed files with 33879 additions and 458074 deletions
-129
View File
@@ -1,129 +0,0 @@
# macOS-related files
.DS_Store
.AppleDouble
.LSOverride
# Windows-related files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
[Dd]esktop.ini
# Python related files.
*.pyc
*.pyo
*.pyi
*.egg-info
# Editor/tool files.
*~
*.bak
.gdb_history
# Compiled Ren'Py files.
*.rpyc
*.rpyb
*.rpymc
# Ren'Py log files.
log.txt
errors.txt
traceback.txt
lint.txt
# Created directories.
saves/
tmp/
cache/
# Executables.
/renpy.exe
/renpy2.exe
/renpy3.exe
/renpy-32.exe
/renpy.sh
/renpy2.sh
/renpy3.sh
/renpy.app
/renpy2.app
/renpy3.app
/7z.sfx
# Libraries.
/lib
# Platforms.
/rapt
/rapt2
/rapt3
/renios
/renios2
/renios3
/web
/web2
/web3
# Docs.
/sphinx/source/inc
/sphinx/source/thequestion.rst
/doc
/doc-web
/LICENSE.txt
# Gui template.
/gui/game/gui
# Editors.
/jedit
/atom
/vscode
# Generated source.
/renpy/vc_version.py
/module/gen/
/module/gen3/
/module/gen-static/
/module/gen3-static/
/tutorial/game/tutorial_director.rpy
# Module build.
/module/build
/module/dist
/module/emscripten-static
# Download target.
/dl
# Pygame_sdl2.
/pygame_sdl2
# Steam.
steam_appid.txt
/steamapi.py
# Android.
*.keystore
# Type analysis.
/typings
# Live2D
cubism
CubismSdkForNative-4-*.zip
# Created files.
/screenshot*
.android.json
# Old files.
/0old
# Works in progress, throwaway scripts, etc.
/scratch
/*-dists
-59
View File
@@ -1,59 +0,0 @@
{
"files.watcherExclude": {
"**/renpy/0old/**" : true,
"**/renpy/atom/**" : true,
"**/renpy/cubism/**" : true,
"**/renpy/dists/**" : true,
"**/renpy/dl/**" : true,
"**/renpy/doc/**" : true,
"**/renpy/doc-web/**" : true,
"**/renpy/jedit/**" : true,
"**/renpy/renpy*.app/**" : true,
"**/renpy/tmp/**" : true,
"**/renpy/web/**" : true,
},
"files.exclude": {
"0old": true,
"**-dists": true,
"**/*.pyc": true,
"**/*.pyo": true,
"renpy/**/*.pyi": true,
"**/*.rpmc": true,
"**/*.rpyc": true,
"**/__pycache__": true,
"**/screenshot-*": true,
"7z.sfx": true,
"atom": true,
"cubism": true,
"dl": true,
"doc": true,
"doc-web": true,
"jedit": true,
"lib*": true,
"live2d": true,
"rapt*": true,
"renios*": true,
"renpy*.app": true,
"renpy*.exe": true,
"tmp": true,
"web": true,
"**/*.rpa": true,
"**/*.rpymc": true,
"**/cache/": true
},
"python.languageServer": "Pylance",
"python.analysis.typeCheckingMode": "basic",
"python.analysis.diagnosticMode": "workspace",
"python.linting.pylintEnabled": false,
"python.analysis.diagnosticSeverityOverrides": {
"reportMissingModuleSource": "none"
},
"esbonio.server.enabled": true,
"esbonio.sphinx.confDir": "",
"renpy.excludeCompiledFilesFromWorkspace": true,
"renpy.watchFoldersForChanges": false,
"renpy.warnOnInvalidVariableNames": "Disabled",
"renpy.warnOnInvalidFilenameIssues": "Disabled",
"renpy.warnOnIndentationAndSpacingIssues": "Disabled",
}
+1895
View File
File diff suppressed because it is too large Load Diff
+60
View File
@@ -0,0 +1,60 @@
Copyright 2004-2006 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.
---
The character images in the demo game (game/9a_*.png) are under their
own copyright. I allow them to be used as part of the demo game, but
not as part of other games.
---
Please note that the above license only applies to Ren'Py
proper. A binary distribution of Ren'Py contains a number of other
packages, each with their own licenses, which you may be bound to
comply with when distributing a Ren'Py game.
For the purposes of complicance with the LGPL, we've made available
the source code to all of the LGPL libraries used by Ren'Py at
http://www.bishoujo.us/renpy/dl/lgpl/.
The following libraries are used in binary packages of Ren'Py:
Python (Python License)
http://www.python.org
Pygame (GNU LGPL)
http://www.pygame.org
SDL (GNU LGPL)
http://www.libsdl.org
SDL_image (GNU LGPL)
http://www.libsdl.org/projects/SDL_image/
SDL_sound (GNU LGPL)
http://www.icculus.org/SDL_sound/
SDL_ttf (GNU LGPL)
http://www.libsdl.org/projects/SDL_ttf
ctypes (MIT)
http://starship.python.net/crew/theller/ctypes/
-178
View File
@@ -1,178 +0,0 @@
==============================
The Ren'Py Visual Novel Engine
==============================
https://www.renpy.org
Ren'Py development takes place on the ``master`` branch, and occasionally
on feature branches.
Getting Started
===============
Ren'Py depends on a number of Python modules written in Cython and C. For
changes to Ren'Py that only involve Python modules, you can use the modules
found in the latest nightly build. Otherwise, you'll have to compile the
modules yourself.
The development scripts assume a POSIX-like platform. The scripts should run
on Linux or macOS, and can be made to run on Windows using an environment
like MSYS.
Nightly Build
-------------
Nightly builds can be downloaded from:
https://nightly.renpy.org
Note that the latest nightly build is at the bottom of the list. Once you've
unpacked the nightly, change into this repository, and run::
./after_checkout.sh <path-to-nightly>
Once this script completes, you should be able to run Ren'Py using renpy.sh,
renpy.app, or renpy.exe, as appropriate for your platform.
If the current nightly build doesn't work, please wait 24 hours for a new
build to occur. If that build still doesn't work, contact Tom (`pytom at bishoujo.us`,
or @renpytom on twitter) to find out what's wrong.
The ``doc`` symlink will dangle until documentation is built, as described
below.
Compiling the Modules
----------------------
Building the modules requires you have the many dependencies installed on
your system. On Ubuntu and Debian, these dependencies can be installed with
the command::
sudo apt install virtualenvwrapper python3-dev libavcodec-dev libavformat-dev \
libswresample-dev libswscale-dev libfreetype6-dev libfribidi-dev libsdl2-dev \
libsdl2-image-dev libsdl2-gfx-dev libsdl2-mixer-dev libsdl2-ttf-dev libjpeg-dev
Ren'Py requires SDL_image 2.6 or greater. If your distribution doesn't include
that version, you'll need to download it from:
https://github.com/libsdl-org/SDL_image/tree/SDL2
We strongly suggest installing the Ren'Py modules into a Python
virtualenv. To create a new virtualenv, open a new terminal and run::
. /usr/share/virtualenvwrapper/virtualenvwrapper.sh
mkvirtualenv renpy
To return to this virtualenv later, run::
. /usr/share/virtualenvwrapper/virtualenvwrapper.sh
workon renpy
After activating the virtualenv, install additional dependencies::
pip install -U cython future six typing pefile requests ecdsa
Then, install pygame_sdl2 by running the following commands::
git clone https://www.github.com/renpy/pygame_sdl2
pushd pygame_sdl2
python setup.py install
python setup.py install_headers
popd
Next, set RENPY_DEPS_INSTALL To a \:-separated (\;-separated on Windows)
list of paths containing the dependencies, and RENPY_CYTHON to the name
of the cython command::
export RENPY_DEPS_INSTALL="/usr:/usr/lib/$(gcc -dumpmachine)/"
export RENPY_CYTHON=cython
Finally, use setup.py in the Ren'Py ``module`` directory to compile and
install the modules that support Ren'Py::
pushd module
python setup.py install
popd
Ren'Py will be installed into the activated virtualenv. It can then be run
using the command::
python renpy.py
Documentation
=============
Building
--------
Building the documentation requires Ren'Py to work. You'll either need to
link in a nightly build, or compile the modules as described above. You'll
also need the `Sphinx <https://www.sphinx-doc.org>`_ documentation generator.
If you have pip working, install Sphinx using::
pip install -U sphinx sphinx-bootstrap-theme
Once Sphinx is installed, change into the ``sphinx`` directory inside the
Ren'Py checkout and run::
./build.sh
Format
------
Ren'Py's documentation consists of reStructuredText files found in sphinx/source, and
generated documentation found in function docstrings scattered throughout the code. Do
not edit the files in sphinx/source/inc directly, as they will be overwritten.
Docstrings may include tags on the first few lines:
\:doc: `section` `kind`
Indicates that this function should be documented. `section` gives
the name of the include file the function will be documented in, while
`kind` indicates the kind of object to be documented (one of ``function``,
``method`` or ``class``. If omitted, `kind` will be auto-detected.
\:name: `name`
The name of the function to be documented. Function names are usually
detected, so this is only necessary when a function has multiple aliases.
\:args: `args`
This overrides the detected argument list. It can be used if some arguments
to the function are deprecated.
For example::
def warp_speed(factor, transwarp=False):
"""
:doc: warp
:name: renpy.warp_speed
:args: (factor)
Exceeds the speed of light.
"""
renpy.engine.warp_drive.engage(factor)
Translating
===========
For best practices when it comes to translating the launcher and template
game, please read:
https://lemmasoft.renai.us/forums/viewtopic.php?p=321603#p321603
Contributing
============
For bug fixes, documentation improvements, and simple changes, just
make a pull request. For more complex changes, it might make sense
to file an issue first so we can discuss the design.
License
=======
For the complete licensing terms, please read:
https://www.renpy.org/doc/html/license.html
+55
View File
@@ -0,0 +1,55 @@
This file contains boilerplate information about running Ren'Py that
can be included into the README for your game. It may be necessary to
change some of the filenames in this document, to make it specific to
your game.
Feel free to use this in your projects.
Running the Game
================
(Windows)
If this game was installed on Windows using an installer, then you can
run it by choosing the shortcut left by the installer. If this game
was installed on Windows using the cross-platform zip file, then it
can be run by executing the run_game.exe file.
(Macintosh)
For information about running Ren'Py games on Mac OS 10.3 or higher,
please go to http://www.bishoujo.us/renpy/mac.html .
(Linux/Unix)
For information about running Ren'Py games under Linux and Unix,
please go to http://www.bishoujo.us/renpy/linux.html . At the very
least, you will need to compile the _renpy module. Read
the file module/README.txt for details.
Playing the Game
================
By default, the game starts running in full screen mode. On some
computers, especially some virtual machines, this can lead to mouse
problems. To fix this, press 'f'.
Some of the more interesting game actions can be performed as follows:
- The left mouse button is used to advance to the next line of
dialogue, or to pick menu options.
- The right mouse button brings you into a menu screen where you can
save the game, load the game, change preferences, return to the main
menu, or quit entirely.
- Scrolling the mouse wheel up or pushing page up returns you to the
previous screen.
- Holding down the CTRL key skips dialogue. By default, it only
skips read dialogue, but this can be changed by a preference. Tab
toggles skip mode.
+4
View File
@@ -0,0 +1,4 @@
Have a new form of imagemap that uses a color image to distinguish
hotspots.
Keyd compiles.
-56
View File
@@ -1,56 +0,0 @@
This file contains the names, contact information, and notes about each
language Ren'Py is translated in. When you're adding a translation or
taking responsibility for a translation, please send a pull request updating
this file.
Pig Latin
---------
This is an automatically-generated translation that lets me test various
translation mechanisms.
* Tom Rothamel <pytom@bishoujo.us>
Russian
---------
Translation to the Russian language. Most of translation provided by Project
Gardares, especially Ria-kon.
* Project Gardares <guardares@gmail.com>
Malay
---------
Translation to the Malay language. This will be translated to both writing
systems used in Malay, namely the Latin-based Rumi script system and the
Arabic-based Jawi script system, to provide compatibility in some areas where
there is still exist Malay people who still cannot read their language in the
newer Rumi script system, or refused to use it. The translation is being made
as general and native as possible to cover the entire region that uses Malay
language, this means native words take precedence over loanwords if and only if
both native and loanwords exist and both are suitable in the context of use.
* Muhammad Nur Hidayat (MNH48) <translation@mnh48.moe>
Turkish
---------
Translation to the Turkish language. Some terms and abbreviations (especially
those related to coding) are deliberately left untranslated (or the original words
are provided in brackets) to avoid confusion, relying on their common use in
Turkish language and among Turkish developers.
* Arda Güler (WKFO) <ardaguler09@gmail.com>
Finnish
---------
Translation to the Finnish language. Most terms have been translated,
sometimes requiring some imagination to come up with suitable terms.
The quality is not perfect, but it should make sense to any developer
fluent in Finnish but not English. Adjustments will be made if better
translations are suggested.
* Lari Liuhamo (Diapolo10) <lari.liuhamo+github116504@gmail.com>
-154
View File
@@ -1,154 +0,0 @@
#!/usr/bin/env python
from __future__ import print_function
import argparse
import os
import subprocess
import sys
from renpy import version_tuple # @UnresolvedImport
SOURCE = [
"/home/tom/ab/renpy",
"/home/tom/ab/renpy-build",
"/home/tom/ab/pygame_sdl2",
"/home/tom/ab/renpy-build/renpyweb",
]
version = ".".join(str(i) for i in version_tuple)
short_version = ".".join(str(i) for i in version_tuple[:-1])
major = short_version.split(".")[0]
print("Version", version)
ap = argparse.ArgumentParser()
ap.add_argument("--release", action="store_true")
ap.add_argument("--prerelease", action="store_true")
ap.add_argument("--experimental", action="store_true")
ap.add_argument("--no-tag", "-n", action="store_true")
ap.add_argument("--push-tags", action="store_true")
ap.add_argument("--delete-tag")
ap.add_argument("--github", action="store_true")
ap.add_argument("--real", action="store_true")
args = ap.parse_args()
if not args.real:
print("Did you want to use scripts/add_all.sh? If not, give --real.")
sys.exit(1)
if args.github:
subprocess.call([ "git", "push", "--tags" ])
subprocess.call([ "gh", "release", "create", version, "--notes", "See https://www.renpy.org/release/" + short_version, "-t", "Ren'Py {}".format(short_version) ])
dn = "/home/tom/ab/renpy/dl/" + short_version
for fn in os.listdir(dn):
if fn == ".build_cache":
continue
if fn.endswith(".update.gz"):
continue
if fn.endswith(".update.json"):
continue
if fn.startswith("updates.json"):
continue
if fn.endswith(".zsync"):
continue
if fn.endswith(".sums"):
continue
subprocess.call([ "gh", "release", "upload", version, os.path.join(dn, fn) ])
sys.exit(0)
if args.release:
subprocess.check_call([ "/home/tom/ab/renpy/scripts/checksums.py", "/home/tom/ab/renpy/dl/" + short_version ])
if args.delete_tag:
for i in SOURCE:
os.chdir(i)
if i == SOURCE[0]:
tag = args.delete_tag
else:
tag = "renpy-" + args.delete_tag
subprocess.call([ "git", "tag", "-d", tag, ])
sys.exit(0)
if args.push_tags:
for i in SOURCE:
os.chdir(i)
if subprocess.call([ "git", "push", "--tags" ]):
print("Tags not pushed: {}".format(os.getcwd()))
sys.exit(1)
print("Pushed tags.")
sys.exit(0)
if args.release:
links = [ "release", "prerelease", "experimental" ]
tag = True
elif args.prerelease:
links = [ "prerelease", "experimental" ]
tag = True
elif args.experimental:
links = [ "experimental" ]
tag = False
else:
links = [ ]
tag = False
if args.no_tag:
tag = False
links = [ i + "-" + major for i in links ]
if tag:
for i in SOURCE:
os.chdir(i)
if subprocess.call([ "git", "diff", "--quiet", "HEAD" ]):
print("Directory not checked in: {}".format(os.getcwd()))
sys.exit(1)
for i in SOURCE:
os.chdir(i)
if i == SOURCE[0]:
tag = version
else:
tag = "renpy-" + version
subprocess.check_call([ "git", "tag", "-a", tag, "-m", "Tagging Ren'Py + " + version + " release." ])
os.chdir("/home/tom/ab/renpy/dl")
for i in links:
if os.path.exists(i):
os.unlink(i)
os.symlink(short_version, i)
os.chdir("/home/tom/ab/website")
subprocess.check_call("./upload.sh")
os.chdir("/home/tom/ab/renpy/sphinx")
if args.release:
subprocess.check_call("./upload.sh")
elif args.prerelease:
subprocess.check_call("./upload_dev.sh")
print("Version", version)
Executable
+104
View File
@@ -0,0 +1,104 @@
#!/usr/bin/env python
# This program adds froms to every unqualified call found in the game
# directory. It's not perfect, but it's better than nothing.
import sys
import os
import re
import glob
def find_labels(fn, labels):
f = file(fn, "r")
for l in f:
m = re.match(r'^\s*call\s+\w+\s+from\s+(\w+)\s*$', l)
if m:
labels[m.group(1)] = True
m = re.match(r'^\s*call\s+expression.*from\s+(\w+)\s*$', l)
if m:
labels[m.group(1)] = True
f.close()
def replace_labels(fn, labels):
f = file(fn, "r")
of = file(fn + ".new", "w")
def replaceit(m):
target = m.group(2)
num = 0
while True:
num += 1
label = "_call_%s_%d" % (target, num)
if label not in labels:
break
labels[label] = True
return m.group(1) + "call " + target + " from " + label + m.group(3)
for l in f:
l = re.sub(r'^(\s*)call\s+(\w+)(\s*$)', replaceit, l)
if re.search(r'call\s+expression', l) and not re.search('from', l):
num = 0
while True:
num += 1
label = "_call_expression_%d" % num
if label not in labels:
break
labels[label] = label
l = l[:-1] + " from " + label + "\n"
of.write(l)
f.close()
of.close()
try:
os.unlink(fn + ".bak")
except:
pass
os.rename(fn, fn + ".bak")
os.rename(fn + ".new", fn)
def main():
pattern = "*/*.rpy"
if len(sys.argv) >= 2:
pattern = sys.argv[1]
files = glob.glob(pattern)
files = [ i for i in files if not i.startswith("common/") ]
labels = { }
for fn in files:
print "Finding labels in", fn
find_labels(fn, labels)
for fn in files:
print "Replacing labels in", fn
replace_labels(fn, labels)
if __name__ == "__main__":
main()
-16
View File
@@ -1,16 +0,0 @@
#!/bin/bash
ROOT="$(dirname $(python -c "import os;print(os.path.realpath('$0'))"))"
ln -s "$ROOT/help.html" "$ROOT/tutorial/README.html"
ln -s "$ROOT/help.html" "$ROOT/the_question/README.html"
ln -s "$ROOT/help.html" "$ROOT/templates/english/README.html"
ln -s "$ROOT/sphinx/source/license.rst" "$ROOT/LICENSE.txt"
if [ "$1" != "" ]; then
ln -s "$1/lib" "$ROOT/lib"
ln -s "$1/renpy.app" "$ROOT"
ln -s "$1/renpy.exe" "$ROOT"
ln -s "$1/renpy.sh" "$ROOT"
fi
+3
View File
@@ -0,0 +1,3 @@
cd game
..\archiver.exe images *.png *.jpg
pause
Executable
+96
View File
@@ -0,0 +1,96 @@
#!/usr/bin/env python
# The Ren'Py archiver. This builds a Ren'Py archive file, and the
# associated index file. These files are really easy to reverse-engineer,
# but are probably better than nothing.
import sys
import os
import encodings.zlib_codec
import random
import glob
from cPickle import loads, dumps, HIGHEST_PROTOCOL
# The most we will go without inserting some padding. 10k.
padding_every = 10240
# The amount of padding we will add.
padding_max = 4
def randpadding():
plen = random.randint(1, padding_max)
rv = ""
for i in range(0, plen):
rv += chr(random.randint(1, 255))
return rv
def main():
if len(sys.argv) < 3:
print "Usage: %s <file-prefix> <files ...>" % sys.argv[0]
return
prefix = sys.argv[1]
# Archive file.
archivef = file(prefix + ".rpa", "wb")
# Index file.
indexf = file(prefix + ".rpi", "wb")
index = { }
random.seed()
offset = 0
# Needed because windows sucks. It doesn't do globbing on the
# command line.
files = [ ]
for i in sys.argv[2:]:
files.extend(glob.glob(i))
for fn in files:
index[fn] = [ ]
print "Adding %s..." % fn
datafile = file(fn, "rb")
while True:
# Pad with junk.
padding = randpadding()
archivef.write(padding)
offset += len(padding)
# Pick a random block size.
block = random.randint(1, padding_every)
data = datafile.read(block)
if not data:
break
dlen = len(data)
archivef.write(data)
index[fn].append((offset, dlen))
offset += dlen
datafile.close()
archivef.close()
indexf.write(dumps(index, HIGHEST_PROTOCOL).encode("zlib"))
indexf.close()
if __name__ == "__main__":
main()
+1
View File
@@ -0,0 +1 @@
build_exe.py run_game
+39
View File
@@ -0,0 +1,39 @@
#!/usr/bin/env python
from distutils.core import setup
import py2exe
import sys
if len(sys.argv) != 2:
print "Usage: build_exe.py <prefix>"
print ""
print "Builds <prefix>.exe."
print "Expects icons in <prefix>.ico."
sys.exit(-1)
def program(name):
return dict(script="run_game.py",
icon_resources=[ (0, name + ".ico"),
],
dest_base=name)
programs = [
program(sys.argv[1]),
]
sys.argv[1:] = [ 'py2exe', '-x', '-a', '--dll-excludes', 'w9xpopen.exe' ]
setup(name="RenPy",
windows=programs,
console=[ "console.py" ],
zipfile='lib/renpy.code',
options={ 'py2exe' : { 'excludes' : [ 'doctest',
'pygame.macosx',
'pygame.surfarray',
'pygame.mixer',
'pygame.mixer_music',
'Numeric', ],
'optimize' : 2,
} },
)
+62
View File
@@ -0,0 +1,62 @@
#!/usr/bin/python
import glob
import os
files = glob.glob("common/*.rpy")
files.sort()
styles = [ ]
for fn in files:
f = file(fn)
fi = iter(f)
for l in iter(fi):
l = l.strip()
if l.startswith("### "):
prefix, style, parent = l.split()
desc = ""
for l in fi:
l = l.strip()
if not l.startswith("# "):
break
desc = desc + " " + l[2:]
styles.append(' style.create("%s", "%s", "%s")' % (style, parent, desc[1:]))
f.close()
f = file("common/style.rpy")
of = file("common/style.rpy.new", "w")
fi = iter(f)
for l in fi:
of.write(l)
if l.startswith("# AUTOMATICALLY GENERATED"):
for l in styles:
of.write(l + "\n")
for l in fi:
if l.startswith("# END AUTOMATICALLY GENERATED"):
break
of.write(l)
f.close()
of.close()
os.rename("common/style.rpy", "common/style.rpy.bak")
os.rename("common/style.rpy.new", "common/style.rpy")
BIN
View File
Binary file not shown.
+55
View File
@@ -0,0 +1,55 @@
This package was debianized by Michael Fedrowitz <michaelf@debian.org>
on Sun, 23 Feb 2003.
It was downloaded from
'http://ftp.gnome.org/pub/GNOME/sources/ttf-bitstream-vera/'.
Upstream Author: Bitstream, Inc.
Copyright:
Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream
Vera is a trademark of Bitstream, Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of the fonts accompanying this license ("Fonts") and associated
documentation files (the "Font Software"), to reproduce and distribute
the Font Software, including without limitation the rights to use,
copy, merge, publish, distribute, and/or sell copies of the Font
Software, and to permit persons to whom the Font Software is furnished
to do so, subject to the following conditions:
The above copyright and trademark notices and this permission notice
shall be included in all copies of one or more of the Font Software
typefaces.
The Font Software may be modified, altered, or added to, and in
particular the designs of glyphs or characters in the Fonts may be
modified and additional glyphs or characters may be added to the
Fonts, only if the fonts are renamed to names not containing either
the words "Bitstream" or the word "Vera".
This License becomes null and void to the extent applicable to Fonts
or Font Software that has been modified and is distributed under the
"Bitstream Vera" names.
The Font Software may be sold as part of a larger software package but
no copy of one or more of the Font Software typefaces may be sold by
itself.
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL,
OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT
SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
Except as contained in this notice, the names of Gnome, the Gnome
Foundation, and Bitstream Inc., shall not be used in advertising or
otherwise to promote the sale, use or other dealings in this Font
Software without prior written authorization from the Gnome Foundation
or Bitstream Inc., respectively. For further information, contact:
fonts at gnome dot org.

Before

Width:  |  Height:  |  Size: 693 B

After

Width:  |  Height:  |  Size: 693 B

+61
View File
@@ -0,0 +1,61 @@
# 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
# definitions.
init -425:
# Positions ##############################################################
# These are positions that can be used inside at clauses. We set
# them up here so that they can be used throughout the program.
$ left = Position(xpos=0.0, xanchor='left')
$ center = Position()
$ right = Position(xpos=1.0, xanchor='right')
# Offscreen positions for use with the move transition. Images at
# these positions are still shown (and consume
# resources)... remember to hide the image after the transition.
$ offscreenleft = Position(xpos=0.0, xanchor='right')
$ offscreenright = Position(xpos=1.0, xanchor='left')
# Transitions ############################################################
# Simple transitions.
$ fade = Fade(.5, 0, .5) # Fade to black and back.
$ dissolve = Dissolve(0.5)
$ pixellate = Pixellate(1.0, 5)
# Various uses of CropMove.
$ wiperight = CropMove(1.0, "wiperight")
$ wipeleft = CropMove(1.0, "wipeleft")
$ wipeup = CropMove(1.0, "wipeup")
$ wipedown = CropMove(1.0, "wipedown")
$ slideright = CropMove(1.0, "slideright")
$ slideleft = CropMove(1.0, "slideleft")
$ slideup = CropMove(1.0, "slideup")
$ slidedown = CropMove(1.0, "slidedown")
$ slideawayright = CropMove(1.0, "slideawayright")
$ slideawayleft = CropMove(1.0, "slideawayleft")
$ slideawayup = CropMove(1.0, "slideawayup")
$ slideawaydown = CropMove(1.0, "slideawaydown")
$ irisout = CropMove(1.0, "irisout")
$ irisin = CropMove(1.0, "irisin")
# This moves changed images to their new locations
$ move = MoveTransition(0.5)
# These shake the screen up and down for a quarter second.
# The delay needs to be an integer multiple of the period.
$ vpunch = Move((0, 10), (0, -10), .10, bounce=True, repeat=True, delay=.275)
$ hpunch = Move((15, 0), (-15, 0), .10, bounce=True, repeat=True, delay=.275)
# These use the ImageDissolve to do some nifty effects.
$ blinds = ImageDissolve(im.Tile("blindstile.png"), 1.0, 8)
$ squares = ImageDissolve(im.Tile("squarestile.png"), 1.0, 256)
image black = Solid((0, 0, 0, 255))
+590
View File
@@ -0,0 +1,590 @@
# This file contains code for the game menu, and associated
# functionality that looks an awful lot like it.
init -499:
python:
######################################################################
# First up, we define a bunch of configuration variable, which the
# user can change.
# The contents of the game menu choices.
library.game_menu = [
( "return", "Return", ui.jumps("_return"), 'True'),
( "prefs", "Preferences", ui.jumps("_prefs_screen"), 'True' ),
( "save", "Save Game", ui.jumps("_save_screen"), 'not renpy.context().main_menu' ),
( "load", "Load Game", ui.jumps("_load_screen"), 'True'),
( "mainmenu", "Main Menu", lambda : _mainmenu_prompt(), 'not renpy.context().main_menu' ),
( "quit", "Quit", lambda : _quit_prompt("quit"), 'True' ),
]
# If not None, a map from the names of the game menu
# navigation buttons to new fixed positions for them on
# the screen.
library.game_menu_positions = None
# The number of columns of files to show at once.
library.file_page_cols = 2
# The number of rows of files to show at once.
library.file_page_rows = 5
# The number of pages to add quick access buttons for.
library.file_quick_access_pages = 5
# The width of a thumbnail.
library.thumbnail_width = 66
# The height of a thumbnail.
library.thumbnail_height = 50
# Sound played when entering the library without clicking a
# button.
library.enter_sound = None
# Sound played when leaving the library without clicking a
# button.
library.exit_sound = None
# Transition that occurs when entering the game menu.
library.enter_transition = None
# Transition that occurs when leaving the game menu.
library.exit_transition = None
# This lets us disable the file pager. (So we only have one
# page of files.)
library.disable_file_pager = False
# This lets us disable the thumbnails in the file pager.
library.disable_thumbnails = False
# If True, we will be prompted before loading a game. (This can
# be changed from inside the game code, so that one can load from
# the first few screens but not after that.)
_load_prompt = True
# The screen that we go to when entering the game menu.
_game_menu_screen = "_save_screen"
######################################################################
# Next, support code.
# This is used to store scratch data that's used by the
# library, but shouldn't be saved out as part of the savegame.
_scratch = object()
# This returns a window containing the game menu navigation
# buttons, set up to jump to the appropriate screen sections.
#
# This can be overridden by user code. It's called with the
# name of the selected screen... one of "mainmenu", "prefs",
# "save", "load", or "quit", at least for the default game
# menu. If None, then it's an indication that none of the
# nav buttons should be shown.
def _game_nav(screen, buttons=True):
ui.add(renpy.Keymap(toggle_fullscreen = renpy.toggle_fullscreen))
ui.add(renpy.Keymap(game_menu=ui.jumps("_noisy_return")))
### gm_root_window default
# (window) The style used for the root window of the game
# menu. This is primarily used to change the background of
# the game menu.
ui.window(style='gm_root_window')
ui.null()
if not screen:
return
### gm_nav_window default
# (window) The style used by a window containing
# buttons that allow the user to navigate through the
# different screens of the game menu.
### gm_nav_vbox thin_vbox
# (box) The style that is used by the box inside the
# gm_nav_window
if library.game_menu_positions:
ui.fixed()
else:
ui.window(style='gm_nav_window')
ui.vbox(focus='gm_nav', style='gm_nav_vbox')
for key, label, clicked, enabled in library.game_menu:
disabled = False
if not eval(enabled):
disabled = True
clicked = None
### gm_nav_button button
# (window, hover) The style of an unselected game menu
# navigation button.
### gm_nav_button_text button_text
# (text, hover) The style of the text of an unselected game
# menu navigation button.
### gm_nav_selected_button selected_button
# (window, hover) The style of a selected game menu
# navigation button.
### gm_nav_selected_button_text selected_button_text
# (text, hover) The style of the text of a selected game
# menu navigation button.
if library.game_menu_positions:
kwargs = library.game_menu_positions.get(label, { })
else:
kwargs = { }
_button_factory(label, "gm_nav",
selected=(key==screen),
disabled=disabled,
clicked=clicked, **kwargs)
ui.close()
# This is called from the game menu to interact with the
# user. It suppresses all of the underlays and overlays.
def _game_interact():
return ui.interact(suppress_underlay=True,
suppress_overlay=True,
mouse="gamemenu")
# This renders a slot with a file in it, in the file picker.
def _render_savefile(name, info, newest):
image, extra = info
### file_picker_entry button
# (window, hover) The style that is used for each of the
# slots in the file picker.
ui.button(style='file_picker_entry',
clicked=ui.returns(("return", (name, True))))
### file_picker_entry_box thin_hbox
# (box) The style that is used for the hbox inside of a
# file picker entry.
ui.hbox(style='file_picker_entry_box')
if not library.disable_thumbnails:
ui.add(image)
### file_picker_text default
# (text) A base style for all text that is displayed in the
# file picker.
### file_picker_new file_picker_text
# (text) The style that is applied to the number of the new slot in
# the file picker.
### file_picker_old file_picker_text
# (text) The style that is applied to the number of the old slot in
# the file picker.
if name == newest:
ui.text(name + ". ", style='file_picker_new')
else:
ui.text(name + ". ", style='file_picker_old')
### file_picker_extra_info file_picker_text
# (text) The style that is applied to extra info in the file
# picker. The extra info is the save time, and the save_name
# if one exists.
ui.text(extra, style='file_picker_extra_info')
ui.close()
# This renders an empty slot in the file picker.
def _render_new_slot(name, save):
if save:
clicked=ui.returns(("return", (name, False)))
enable_hover = True
else:
clicked = None
enable_hover = True
ui.button(style='file_picker_entry',
clicked=clicked,
enable_hover=enable_hover)
ui.hbox(style='file_picker_entry_box')
if not library.disable_thumbnails:
ui.null(width=library.thumbnail_width,
height=library.thumbnail_height)
ui.text(name + ". ", style='file_picker_old')
### file_picker_empty_slot file_picker_text
# (text) The style that is used for the empty slot indicator
# in the file picker.
ui.text(_("Empty Slot."), style='file_picker_empty_slot')
ui.close()
_scratch.file_picker_index = None
# This displays a file picker that can chose a save file from
# the list of save files.
def _file_picker(selected, save):
# The number of slots in a page.
file_page_length = library.file_page_cols * library.file_page_rows
saves, newest = renpy.saved_games(regexp=r'[0-9]+')
# The index of the first entry in the page.
fpi = _scratch.file_picker_index
if fpi is None:
fpi = 0
if newest:
fpi = (int(newest) - 1) // file_page_length * file_page_length
if fpi < 0:
fpi = 0
while True:
if fpi < 0:
fpi = 0
_scratch.file_picker_index = fpi
# Show Navigation
_game_nav(selected)
### file_picker_window default
# (window) A window containing the file picker
# that is used to choose slots for loading and saving.
### file_picker_window_vbox thin_vbox
# (box) The vbox containing both the nav and the grid in
# the file picker.
ui.window(style='file_picker_window')
ui.vbox(style='file_picker_window_vbox') # whole thing.
if not library.disable_file_pager:
### file_picker_navbox thick_hbox
# (box) The box containing the naviation (next/previous)
# buttons in the file picker.
### file_picker_nav_button button
# (window, hover) The style that is used for enabled file
# picker navigation buttons.
### file_picker_nav_button_text button_text
# (text) The style that is used for the label of enabled
# file picker navigation buttons.
# Draw the navigation.
ui.hbox(style='file_picker_navbox') # nav buttons.
def tb(cond, label, clicked):
_button_factory(label, "file_picker_nav", disabled=not cond, clicked=clicked)
# Previous
tb(fpi > 0, _('Previous'), ui.returns(("fpidelta", -1)))
# Quick Access
for i in range(0, library.file_quick_access_pages):
target = i * file_page_length
tb(fpi != target, str(i + 1), ui.returns(("fpiset", target)))
# Next
tb(True, _('Next'), ui.returns(("fpidelta", +1)))
# Done with nav buttons.
ui.close()
# This draws a single slot.
def entry(offset):
i = fpi + offset
name = str(i + 1)
if name not in saves:
_render_new_slot(name, save)
else:
_render_savefile(name, saves[name], newest)
### file_picker_grid default
# The style of the grid containing the file
# picker entries.
# Actually draw a slot.
ui.grid(library.file_page_cols,
library.file_page_rows,
style='file_picker_grid',
transpose=True) # slots
for i in range(0, file_page_length):
entry(i)
ui.close() # slots
ui.close() # whole thing
result = _game_interact()
type, value = result
if type == "return":
return value
if type == "fpidelta":
fpi += value * file_page_length
if type == "fpiset":
fpi = value
# This renders a yes/no prompt, as part of the game menu. If
# screen is None, then it omits the game menu navigation.
def _yesno_prompt(screen, message):
"""
@param screen: The screen button that should be highlighted when this prompt is shown. If None, then no game menu navigation is shown.
@param message: The message that is shown to the user to prompt them to answer yes or no.
This function returns True if the user clicks Yes, or False if the user clicks No.
"""
_game_nav(screen)
### yesno_window default
# (window) The style of a window containing a yes/no prompt.
### yesno_window_vbox thick_vbox
# (box) The style of a box containing the widgets in a
# yes/no prompt.
ui.window(style='yesno_window')
ui.vbox(style='yesno_window_vbox')
### yesno_label default
# (text) The style used for the prompt in a yes/no
# dialog.
### yesno_button button
# (window, hover) The style of yes/no buttons.
### yesno_button_text button_text
# (window, hover) The style of yes/no button text.
_label_factory(message, "yesno", xpos=0.5, xanchor='center')
ui.grid(5, 1, xfill=True)
# The extra nulls are because we want equal whitespace surrounding
# the two buttons. It should work as long as we have xfill=True
ui.null()
_button_factory("Yes", 'yesno', clicked=ui.returns(True), xpos=0.5, xanchor='center')
ui.null()
_button_factory("No", 'yesno', clicked=ui.returns(False), xpos=0.5, xanchor='center')
ui.null()
ui.close()
ui.close()
return _game_interact()
def _show_exception(title, message):
### error_window default
# (window) The style of the window containing internal error
# messages.
### error_title default
# (text) The style of the text containing the title of an
# error message.
### error_body default
# (text) The style of the body of an error message.
ui.window(style='error_window')
ui.vbox()
ui.text(title, style='error_title')
ui.text("")
ui.text(message, style='error_body')
ui.text("")
ui.text(_("Please click to continue."), style='error_body')
ui.close()
ui.saybehavior()
ui.interact()
library.old_names["Are you sure you want to quit?"] = "Are you sure you want to quit the game?"
def _quit_prompt(screen="quit"):
def prompt():
return _yesno_prompt(screen, "Are you sure you want to quit?")
if renpy.invoke_in_new_context(prompt):
renpy.quit()
else:
return
library.old_names["Are you sure you want to return to the main menu?\nThis will lose unsaved progress."] = "Are you sure you want to return to the main menu?\nThis will end your game."
def _mainmenu_prompt(screen="mainmenu"):
def prompt():
return _yesno_prompt(screen, "Are you sure you want to return to the main menu?\nThis will lose unsaved progress.")
if renpy.invoke_in_new_context(prompt):
renpy.full_restart()
else:
return
##############################################################################
# The actual menus begin around here.
# First up, we have the code that is common to all of the entry points into
# the game.
# This is the code that executes when entering a menu context, except
# for the scene statement.
label _enter_menu_without_scene:
$ renpy.movie_stop()
$ renpy.take_screenshot((library.thumbnail_width, library.thumbnail_height))
# This may be changed, if we are already in the main menu.
$ renpy.context().main_menu = False
return
label _enter_menu:
call _enter_menu_without_scene from _call_enter_menu_without_scene_1
scene
return
# Factored this all into one place, to make our lives a bit easier.
label _enter_game_menu:
call _enter_menu from _call__enter_menu_2
if library.enter_transition:
$ renpy.transition(library.enter_transition)
if renpy.has_label("enter_game_menu"):
call expression "enter_game_menu" from _call_enter_game_menu_1
return
##############################################################################
# Now, we have the actual entry points into the various menu screens.
# Entry points from the game into menu-space.
label _game_menu:
call _enter_game_menu from _call__enter_game_menu_0
jump expression _game_menu_screen
label _game_menu_save:
call _enter_game_menu from _call__enter_game_menu_1
jump _save_screen
label _game_menu_load:
call _enter_game_menu from _call__enter_game_menu_2
jump _load_screen
label _game_menu_preferences:
call _enter_game_menu from _call__enter_game_menu_3
jump _prefs_screen
label _confirm_quit:
call _enter_menu from _call__enter_menu_3
$ _quit_prompt(None)
return
##############################################################################
# Finally, we have the actual menu screens that are shown to the user.
init -499:
$ library.old_names["Loading will lose unsaved progress.\nAre you sure you want to do this?"] = "Loading a new game will end your current game.\nAre you sure you want to do this?"
label _load_screen:
python hide:
fn, exists = _file_picker("load", False )
if not renpy.context().main_menu and _load_prompt:
if _yesno_prompt("load", "Loading will lose unsaved progress.\nAre you sure you want to do this?"):
renpy.load(fn)
else:
renpy.load(fn)
jump _load_screen
label _save_screen:
$ _fn, _exists = _file_picker("save", True)
if not _exists or _yesno_prompt("save", "Are you sure you want to overwrite your save?"):
python hide:
if save_name:
full_save_name = "\n" + save_name
else:
full_save_name = ""
try:
renpy.save(_fn, renpy.time.strftime("%b %d, %H:%M") +
full_save_name)
except Exception, e:
if config.debug:
raise
message = ( _("The error message was:\n\n") +
e.__class__.__name__ + ": " + unicode(e) + "\n\n" +
_("You may want to try saving in a different slot, or playing for a while and trying again later."))
_show_exception(_("Save Failed."), message)
jump _save_screen
label _quit:
$ renpy.quit()
# Make some noise, then return.
label _noisy_return:
$ renpy.play(library.exit_sound)
# Return to the game.
label _return:
if renpy.context().main_menu:
jump _main_menu
if library.exit_transition:
$ renpy.transition(library.exit_transition)
return
+246
View File
@@ -0,0 +1,246 @@
# This file consists of renpy functions that aren't expected to be
# touched by the user too much. We reserve the _ prefix for names
# defined in the library.
# It's strongly reccomended that you don't edit this file, as future
# releases of Ren'Py will probably change this file to include more
# functionality.
# It's also strongly recommended that you leave this file in the
# game directory, so its functionality is included in your game.
init -500:
python:
# These are settings that the user can tweak to control the
# look of the main menu and the load/save/escape screens.
# The class that stores library variables.
class _Library(object):
def __setattr__(self, name, value):
if getattr(self, 'lock', False):
if not name in vars(self):
raise Exception('library.%s is not a known configuration variable.' % name)
object.__setattr__(self, name, value)
# Used to store library settings.
library = _Library()
# The minimum version of the module we work with. Don't change
# this unless you know what you're doing.
library.module_version = 4008002
# Should we warn the user if the module is missing or has a bad
# version?
library.module_warning = False
# Used to translate strings in the library.
library.translations = { }
# Used internally to maintain compatiblity with old
# translations of strings.
library.old_names = { }
# True if the skip indicator should be shown.
library.skip_indicator = True
# This is updated to give the user an idea of where a save is
# taking place.
save_name = ''
def _button_factory(label,
type=None,
selected=None,
disabled=False,
clicked=None,
**properties):
"""
This function is called to create the various buttons used
in the game menu. By overriding this function, one can
(for example) replace the default textbuttons with image buttons.
When it is called, it's expected to add a button to the screen.
@param label: The label of this button, before translation.
@param type: The type of the button. One of "mm" (main menu),
"gm_nav" (game menu), "file_picker_nav", "yesno", or "prefs".
@param selected: True if the button is selected, False if not,
or None if it doesn't matter.
@param disabled: True if the button is disabled, False if not.
@param clicked: A function that should be executed when the
button is clicked.
@param properties: Addtional layout properties.
"""
style = type
if selected and not disabled:
style += "_selected"
if disabled:
clicked = None
style = style + "_button"
text_style = style + "_text"
ui.textbutton(_(label), style=style, text_style=text_style, clicked=clicked, **properties)
def _label_factory(label, type, **properties):
"""
This function is called to create a new label. It can be
overridden by the user to change how these labels are created.
@param label: The label of the box.
@param type: "prefs" or "yesno".
@param properties: This may contain position properties.
"""
ui.text(_(label), style=type + "_label", **properties)
# The function that's used to translate strings in the game menu.
def _(s):
"""
Translates s into another language or something.
"""
if s in library.translations:
return library.translations[s]
if s in library.old_names and library.old_names[s] in library.translations:
return library.translations[library.old_names[s]]
return s
# Are the windows currently hidden?
_windows_hidden = False
# Set up the default keymap.
python hide:
# Called to make a screenshot happen.
def screenshot():
import os.path
i = 1
while True:
fn = "screenshot%04d.bmp" % i
if not os.path.exists(fn):
break
i += 1
renpy.screenshot(fn)
def invoke_game_menu():
renpy.play(library.enter_sound)
renpy.call_in_new_context('_game_menu')
def toggle_skipping():
if not config.skipping:
config.skipping = "slow"
else:
config.skipping = None
renpy.restart_interaction()
def fast_skip():
if config.fast_skipping or config.developer:
config.skipping = "fast"
# The default keymap.
km = renpy.Keymap(
rollback = renpy.rollback,
screenshot = screenshot,
toggle_fullscreen = renpy.toggle_fullscreen,
toggle_music = renpy.toggle_music,
toggle_skip = toggle_skipping,
fast_skip = fast_skip,
game_menu = invoke_game_menu,
hide_windows = renpy.curried_call_in_new_context("_hide_windows"),
launch_editor = renpy.launch_editor,
)
config.underlay = [ km ]
# The skip indicator.
python hide:
def skip_indicator():
### skip_indicator default
# (text) The style and placement of the skip indicator.
if config.skipping == "slow" and library.skip_indicator:
ui.text(_("Skip Mode"), style='skip_indicator')
if config.skipping == "fast" and library.skip_indicator:
ui.text(_("Fast Skip Mode"), style='skip_indicator')
config.overlay_functions.append(skip_indicator)
return
label _hide_windows:
if _windows_hidden:
return
python:
_windows_hidden = True
ui.saybehavior()
ui.interact(suppress_overlay=True)
_windows_hidden = False
return
##############################################################################
#
# Code for the game menu.
# This code here handles check for the correct version of the Ren'Py module.
label _check_module:
if not library.module_warning:
return
python hide:
module_info = _("While Ren'Py games are playable without the _renpy module, some features may be disabled. For more information, read the module/README.txt file or go to http://www.bishoujo.us/renpy/.")
if renpy.module_version() == 0:
_show_exception(_("_renpy module not found."),
_("The _renpy module could not be loaded on your system.") + "\n\n" + module_info)
elif renpy.module_version() < library.module_version:
_show_exception(_("Old _renpy module found."),
_("An old version (%d) of the Ren'Py module was found on your system, while this game requires version %d.") % (renpy.module_version(), library.module_version) + "\n\n" + module_info)
return
init -401:
# Random nice things to have.
$ centered = Character(None, what_style="centered_text", window_style="centered_window")
image text = renpy.ParameterizedText(style="centered_text")
# Lock the library object.
$ library.lock = True
+121
View File
@@ -0,0 +1,121 @@
# This file contains code fo the main menu, and anything else that
# happens upon initial execution of a Ren'Py program.
init -498:
python hide:
library.old_names['Quit'] = 'Quit Game'
# The contents of the main menu.
library.main_menu = [
( "Start Game", "start", 'True'),
( "Continue Game", ui.jumps("_load_screen"), 'True' ),
( "Preferences", ui.jumps("_prefs_screen"), 'True' ),
( "Quit", ui.jumps("_quit"), 'True' ),
]
# If not None, this is used to fix the positions of the
# things in the main menu.
library.main_menu_positions = None
# This is the true starting point of the program. Sssh... Don't
# tell anyone.
label _start:
call _check_module from _call__check_module_1
if renpy.has_label("splashscreen") and not _restart:
call expression "splashscreen" from _call_splashscreen_1
# Clean out any residual scene from the splashscreen.
scene black
$ renpy.call_in_new_context("_enter_main_menu")
# Should never happen... but might as well do something
jump start
# At this point, we've been switched into a new context. So we
# initialize it.
label _enter_main_menu:
call _enter_menu from _call__enter_menu_1
$ renpy.context().main_menu = True
# This is called to show the main menu to the user.
label _main_menu:
# Let the user completely override the main menu. (But please note
# it still lives in the menu context, rather than the game context.)
if renpy.has_label("main_menu"):
jump expression "main_menu"
# This is the default main menu, which we get if the user hasn't
# defined his own, or if that function calls this explicitly.
label _library_main_menu:
scene
python hide:
ui.add(renpy.Keymap(toggle_fullscreen = renpy.toggle_fullscreen))
### mm_root_window default
# (window) The style used for the root window of the main
# menu. This is primarily used to set a background for the
# main menu.
ui.window(style='mm_root_window')
ui.fixed()
### mm_menu_window default
# (window) A window that contains the choices in
# the main menu. Change this to change the placement of
# these choices on the main menu screen.
### mm_menu_window_vbox thin_vbox
# (box) The vbox containing the main menu choices.
if library.main_menu_positions:
ui.fixed()
else:
ui.window(style='mm_menu_window')
ui.vbox(style='mm_menu_window_vbox')
for text, clicked, enabled in library.main_menu:
if isinstance(clicked, basestring):
clicked = ui.jumpsoutofcontext(clicked)
### mm_button button
# (window, hover) The style that is used on buttons that are
# part of the main menu.
### mm_button_text button_text
# (text, hover) The style that is used for the labels of
# buttons that are part of the main menu.
if library.main_menu_positions:
kwargs = library.main_menu_positions.get(text, { })
else:
kwargs = { }
if not eval(enabled):
clicked = None
disabled = True
else:
disabled = False
_button_factory(text, "mm", clicked=clicked, disabled=disabled, **kwargs)
ui.close()
ui.close()
store._result = ui.interact(suppress_overlay = True,
suppress_underlay = True,
mouse="mainmenu")
# Computed jump to the appropriate label.
jump _main_menu
+654
View File
@@ -0,0 +1,654 @@
# This file contains the code to implement the Ren'Py preferences
# screen.
init -450:
python:
# This is a map from the name of the style that is applied to
# a list of preferences that should be placed into a vbox
# with that style.
library.preferences = { }
# Ditto, for joystick preferences.
library.joystick_preferences = { }
# This is a map from preference name to that preference
# object, that can be used in rearranging preferences.
library.all_preferences = { }
# If true, the preference choices will be arranged in an
# hbox.
library.hbox_pref_choices = False
# A list of (readable name, synthetic key) tuples
# corresponding to joystick events.
library.joystick_keys = [
('Left', 'joy_left'),
('Right', 'joy_right'),
('Up', 'joy_up'),
('Down', 'joy_down'),
('Select/Dismiss', 'joy_dismiss'),
('Rollback', 'joy_rollback'),
('Hold to Skip', 'joy_holdskip'),
('Toggle Skip', 'joy_toggleskip'),
('Hide Text', 'joy_hide'),
('Menu', 'joy_menu'),
]
def _prefs_screen_run(prefs_map):
_game_nav("prefs")
### prefs_window default
# (window) A window containing all preferences.
ui.window(style='prefs_window')
ui.fixed()
for style, prefs in prefs_map.iteritems():
ui.vbox(style=style)
for i in prefs:
i.render_preference()
ui.close()
ui.close()
_game_interact()
class _Preference(object):
"""
This is a class that's used to represent a multiple-choice
preference.
"""
def __init__(self, name, field, values, base=_preferences):
"""
@param name: The name of this preference. It will be
displayed to the user.
@param variable: The field on the base object
that will be assigned the selected value. This field
must exist.
@param values: A list of value name, value, condition
triples. The value name is the name of this value that
will be shown to the user. The value is the literal
python value that will be assigned if this value is
selected. The condition is a condition that will be
evaluated to determine if this is a legal value. If no
conditions are true, this preference will not be
displayed to the user. A condition of None is always
considered to be True.
@param base: The base object on which the variable is
read from and set. This defaults to _preferences,
the user preferences object.
"""
self.name = name
self.field = field
self.values = values
self.base = base
library.all_preferences[name] = self
def render_preference(self):
values = [ (name, val) for name, val, cond in self.values
if cond is None or renpy.eval(cond) ]
if not values:
return
### prefs_pref default
# (window) A window containing an individual
# preference.
### prefs_pref_vbox thin_vbox
# (box) The style of the vbox containing a preference.
### prefs_label default
# (text) The style that is applied to the label of
# a block of preferences.
ui.window(style='prefs_pref')
ui.vbox(style='prefs_pref_vbox')
_label_factory(self.name, "prefs")
cur = getattr(self.base, self.field)
### prefs_hbox default
# If library.hbox_pref_choices is True, the style
# of the hbox containing the choices.
if library.hbox_pref_choices:
ui.hbox(style='prefs_hbox')
for name, value in values:
### prefs_button button
# (window, hover) The style of an unselected preferences
# button.
### prefs_button_text button_text
# (text, hover) The style of the text of an unselected
# preferences button.
### prefs_selected_button selected_button
# (window, hover) The style of a selected preferences
# button.
### prefs_selected_button_text selected_button_text
# (text, hover) The style of the text of a selected
# preferences button.
def clicked(value=value):
setattr(self.base, self.field, value)
return True
_button_factory(name, "prefs",
selected=cur==value,
clicked=clicked)
if library.hbox_pref_choices:
ui.close()
ui.close()
class _VolumePreference(object):
"""
This represents a preference that controls one of the
volumes in the system. It is represented as a slider bar,
and a button that can be pushed to play a sample sound on
a channel.
"""
def __init__(self, name, mixer, enable='True', sound='None', channel=0):
"""
@param name: The name of this preference, as shown to the user.
@param mixer: The mixer this preference controls.
@param enable: A string giving a python expression. If
the expression is evaluates to false, this preference
is not shown.
@param sound: A string that is evaluated to yield
another string. The yielded string is expected to give
a sound file, which is played as the sample sound. (We
apologize for the convolution of this.)
@param channel: The number of the channel the sample
sound is played on.
"""
self.name = name
self.mixer = mixer
self.enable = enable
self.sound = sound
self.channel = channel
library.all_preferences[name] = self
def render_preference(self):
if not eval(self.enable):
return
sound = eval(self.sound)
ui.window(style='prefs_pref')
ui.vbox(style='prefs_pref_vbox')
_label_factory(self.name, "prefs")
def changed(v):
if v == 0:
_preferences.mute[self.mixer] = True
else:
_preferences.mute[self.mixer] = False
v /= 128.0
_preferences.volumes[self.mixer] = v
### prefs_volume_slider prefs_slider
# (bar) The style that is applied to volume
# sliders.
ui.bar(128,
int(_preferences.volumes[self.mixer] * 128),
changed=changed,
style='prefs_volume_slider')
if sound:
def clicked():
renpy.sound.play(sound, channel=self.channel)
_button_factory("Test", "prefs", clicked=clicked)
ui.close()
class _SliderPreference(object):
"""
A class that represents a preference that is controlled by a
slider.
"""
def __init__(self, name, range, get, set, enable='True'):
"""
@param set: The name of this preference, that is shown to the user.
@param range: An integer giving the maximum value of
this slider. The slider goes from 0 to range.
@param get: A function that's called to get the
initial value of the slider. It's called with no
arguments, and should return an integet between 0 and
range, inclusive.
@param set: A function that's called when the value of
the slider is set by the user. It is called with a
single integer, in the range 0 to range, inclusive.
@param enable: A string giving a python expression. If
the expression is evaluates to false, this preference
is not shown.
"""
self.name = name
self.range = range
self.get = get
self.set = set
self.enable = enable
library.all_preferences[name] = self
def render_preference(self):
if not eval(self.enable):
return
ui.window(style='prefs_pref')
ui.vbox(style='prefs_pref_vbox')
_label_factory(self.name, "prefs")
def changed(v):
self.set(v)
### prefs_slider bar
# (bar) The style that is applied to preference
# sliders.
ui.bar(self.range,
self.get(),
changed=changed,
style='prefs_slider')
ui.close()
class _PreferenceSpinner(object):
"""
This is a class that's used to represent a preference
spinner, which is a preference that can be incremented
and decremented, when shown to the user.
"""
def __init__(self, name, field, minimum, maximum, delta,
cond = "True", render = lambda x : str(x),
base=_preferences):
"""
@param name: The name of this preference, that is presented
to the user.
@param field: The name of the field on the base object
that is updated by this spinner.
@param minimum: The minimum value that this spinner can set
the value to.
@param maximum: The maximum value that this spinner can set
the value to.
@param delta: The delta by which this spinner is
incremented or decremented.
@param cond: If this condition is not true, this spinner is
not shown.
@param render: This function is called with the value of
the field, and is expected to render that value to a
string.
@param base: The base object that this spinner updates
the field on. It defaults to _preferences, the preferences
object.
"""
self.name = name
self.field = field
self.minimum = minimum
self.maximum = maximum
self.delta = delta
self.cond = cond
self.render = render
self.base = base
library.all_preferences[name] = self
def render_preference(self):
### prefs_spinner default
# The position of the prefs spinner.
### prefs_spinner_label prefs_label
# (text) This is the style that displays the value of a
# preference spinner.
### prefs_spinner_button prefs_button
# (window, hover) The style of the + or - buttons in a
# preference spinner.
### prefs_spinner_button_text prefs_button_text
# (text, hover) The style of the text of the + and - buttons
# in a preference spinner.
if not renpy.eval(self.cond):
return
ui.window(style='prefs_pref')
ui.vbox(style='prefs_pref_vbox')
_label_factory(self.name, "prefs")
cur = getattr(self.base, self.field)
def minus_clicked():
value = cur - self.delta
value = max(self.minimum, value)
setattr(self.base, self.field, value)
return True
def plus_clicked():
value = cur + self.delta
value = min(self.maximum, value)
setattr(self.base, self.field, value)
return True
ui.hbox(style='prefs_spinner')
_button_factory("-", "prefs_spinner", clicked=minus_clicked)
_label_factory(self.render(cur), "prefs_spinner")
_button_factory("+", "prefs_spinner", clicked=plus_clicked)
ui.close()
ui.close()
class _JoystickPreference(object):
def __init__(self, name):
self.name = name
library.all_preferences[name] = self
def render_preference(self):
### prefs_js_button prefs_button
# (window, hover) The style of buttons giving a joystick mapping.
### prefs_js_button_text prefs_button_text
# (text, hover) The style of the text in buttons giving a joystick mapping.
### joy_window prefs_window
# (window) The window containing the joystick message.
### joy_vbox thick_vbox
# (window) The vbox containing the joistick mapping message.
### joyfunc_label prefs_label
# (text, position) The style of the joystick mapping function name.
### joyprompt_label prefs_label
# (text, position) The style of the joystick mapping prompt message.
def set_binding(key, label):
_game_nav(None)
ui.window(style='joy_window')
ui.vbox(style='joy_vbox')
_label_factory(_("Joystick Mapping") + " - " + _(label), "joyfunc")
_label_factory('Move the joystick or press a button to create the mapping. Click the mouse to remove the mapping.', 'joyprompt')
ui.close()
ui.saybehavior()
ui.add(renpy.display.joystick.JoyBehavior())
binding = _game_interact()
if not isinstance(binding, basestring):
del _preferences.joymap[key]
else:
_preferences.joymap[key] = binding
ui.window(style='prefs_pref')
ui.vbox(style='prefs_pref_vbox')
_label_factory(self.name, 'prefs')
for label, key in library.joystick_keys:
def clicked(label=label, key=key):
renpy.invoke_in_new_context(set_binding, key, label)
return True
_button_factory(_(label) + " - " + _(_preferences.joymap.get(key, "Not Assigned")), "prefs_js", clicked=clicked)
# def clicked():
# for label, key in library.joystick_keys:
# renpy.invoke_in_new_context(set_binding, key, label)
# return True
# _button_factory("Assign All Mappings", "prefs_js", clicked=clicked)
ui.close()
class _JumpPreference(object):
def __init__(self, name, target, condition="True"):
self.name = name
self.target = target
self.condition = condition
library.all_preferences[name] = self
def render_preference(self):
### prefs_jump prefs_pref
# (window) The style of a window containing a jump preference.
### prefs_jump_button prefs_button
# (window, hover) The style of a jump preference button.
### prefs_jump_button_text prefs_button_text
# (text, hover) The style of jump preference button text.
ui.window(style='prefs_jump')
if eval(self.condition):
clicked=ui.jumps(self.target)
else:
clicked=None
_button_factory(self.name, 'prefs_jump', clicked=clicked)
def _remove_preference(name):
"""
Removes the preference with the given name from the
preferences menu.
"""
pref = library.all_preferences.get(name, None)
if not pref:
return
for k, v in library.preferences.iteritems():
if pref in v:
v.remove(pref)
python hide:
# Enablers for some preferences.
library.has_music = True
library.has_sound = True
library.sample_sound = None
library.has_transitions = True
library.has_cps = True
library.has_afm = True
library.has_skipping = True
library.has_skip_after_choice = True
# Left
pl1 = _Preference('Display', 'fullscreen', [
('Window', False, None),
('Fullscreen', True, None),
])
pl2 = _Preference('Transitions', 'transitions', [
('All', 2, 'library.has_transitions'),
('Some', 1, 'library.has_transitions and default_transition'),
('None', 0, 'library.has_transitions'),
])
# Center
pc1 = _Preference('TAB and CTRL Skip', 'skip_unseen', [
('Seen Messages', False, 'config.allow_skipping and library.has_skipping'),
('All Messages', True, 'config.allow_skipping and library.has_skipping'),
])
pc2= _Preference('After Choices', 'skip_after_choices', [
('Stop Skipping', False, 'config.allow_skipping and library.has_skip_after_choice'),
('Continue Skipping', True, 'config.allow_skipping and library.has_skip_after_choice'),
])
def cps_render(n):
if n == 0:
return "Infinite"
else:
return str(n)
def cps_get():
cps = _preferences.text_cps
if cps == 0:
cps = 100
else:
cps -= 1
return cps
def cps_set(cps):
cps += 1
if cps == 101:
cps = 0
_preferences.text_cps = cps
pc3 = _SliderPreference('Text Speed', 100, cps_get, cps_set,
'library.has_cps')
def afm_get():
afm = _preferences.afm_time
if afm == 0:
afm = 40
else:
afm -= 1
return afm
def afm_set(afm):
afm += 1
if afm == 41:
afm = 0
_preferences.afm_time = afm
pc4 = _SliderPreference('Auto-Forward Time', 40, afm_get, afm_set,
'library.has_afm')
# Right
pr1 = _VolumePreference("Music Volume", 'music', 'library.has_music')
pr2 = _VolumePreference("Sound Volume", 'sfx', 'library.has_sound', 'library.sample_sound')
_JumpPreference('Joystick...', '_joystick_screen', 'renpy.display.joystick.enabled')
_JoystickPreference('Joystick Configuration')
# Advanced
### prefs_column default
# The style of a vbox containing a column of preferences.
### prefs_left prefs_column
# The position of the left column of preferences.
### prefs_center prefs_column
# The position of the center column of preferences.
### prefs_right prefs_column
# The position of the right column of preferences.
library.preferences['prefs_left'] = [
library.all_preferences['Display'],
library.all_preferences['Transitions'],
library.all_preferences['Joystick...'],
]
library.preferences['prefs_center'] = [
library.all_preferences['TAB and CTRL Skip'],
library.all_preferences['After Choices'],
library.all_preferences['Text Speed'],
library.all_preferences['Auto-Forward Time'],
]
library.preferences['prefs_right'] = [
library.all_preferences['Music Volume'],
library.all_preferences['Sound Volume'],
]
library.joystick_preferences['prefs_center'] = [
library.all_preferences['Joystick Configuration'],
]
label _prefs_screen:
$ _prefs_screen_run(library.preferences)
jump _prefs_screen
label _joystick_screen:
$ _prefs_screen_run(library.joystick_preferences)
jump _joystick_screen

Before

Width:  |  Height:  |  Size: 606 B

After

Width:  |  Height:  |  Size: 606 B

+456
View File
@@ -0,0 +1,456 @@
# This file is responsible for creating and defining the default styles
# used by the system.
# This file should be considered part of the Ren'Py library, and not
# something that needs to be modified by the user. Instead, just update
# the appropriate style property in an init: block in your script.
#
# For example, to change the default window backgrounds to a
# transparent dark red, add:
#
# init:
# $ style.window.background = renpy.Solid((128, 0, 0, 128)
#
# to your script. No need to mess around here, it will just make your
# life harder when a new version of Ren'Py is released.
init -1000:
python hide:
# Style Declarations #################################################
style.create('default', None,
'The default style that all styles inherit from.')
style.create('hbox', 'default', '(box) The base style for hboxen.')
style.create('vbox', 'default', '(box) The base style for vboxen.')
style.create('window', 'default', '(window) The base style for the windows that contain dialogue, thoughts, and menus.')
style.create('image_placement', 'default', 'This style is used to control the default placement of images on the screen.')
style.create('image', 'default', 'This is the style of images themselves. Don\'t change this, change image_placement instead.')
style.create('animation', 'default', 'This is the default style of animations. Don\'t change this, change image_placement instead.')
# say
style.create('say_label', 'default', '(text) The style that is used by default for the label of dialogue. The label is used to indicate who is saying something.')
style.create('say_dialogue', 'default', "(text) The style that is used by default for the text of dialogue.")
style.create('say_thought', 'default', "(text) The label that is used by default for the text of thoughts or narration, when no speaker is given.""")
style.create('say_window', 'window', '(window) The default style for windows containing dialogue and thoughts.')
# menu
style.create('menu', 'default', "(position) The style that is used for the vbox containing a menu.")
style.create('menu_caption', 'default', "(text) The style that is used to render a menu caption.")
style.create('menu_choice', 'default', "(text, hover) The style that is used to render the text of a menu choice.""")
style.create('menu_choice_button', 'default', "(window, hover, sound) The style that is used to render the button containing a menu choice.")
style.create('menu_choice_chosen', 'menu_choice', "(text, hover) The style that is used to render the text of a menu choice that has been chosen by the user sometime in the past.""")
style.create('menu_choice_chosen_button', 'menu_choice_button', "(window, hover, sound) The style that is used to render the button containing a menu choice that has been chosen by the user sometime in the past.")
style.create('menu_window', 'window', '(window) The default style for windows containing a menu.')
# input
style.create('input_text', 'default', '(text) The style used for the text of an input box.')
style.create('input_prompt', 'default', '(text) The style used for the prompt of an input box.')
style.create('input_window', 'window', '(window) The style used for the window of an input box.')
# centered
style.create('centered_window', 'default', '(window) The style that is used for a "window" containing centered text.')
style.create('centered_text', 'default', '(text) The style used for centered text.')
# imagemap
style.create('imagemap', 'image_placement', 'The style that is used for imagemaps.')
style.create('imagemap_button', 'default', '(window, sound, hover) The style that is used for buttons inside imagemaps.')
# imagebutton
style.create('image_button', 'default', '(window, sound, hover) The default style used for image buttons.')
style.create('image_button_image', 'default', 'The default style used for images inside image buttons.')
# button
style.create('button', 'default', '(window, sound, hover) The default style used for buttons in the main and game menus.')
style.create('button_text', 'default', '(text, hover) The default style used for the label of a button.')
style.create('selected_button', 'button', '(window, hover) The style that is used for a selected button (for example, the active screen or a chosen preference).')
style.create('selected_button_text', 'button_text', '(text, hover) The style that is used for the label of a selected button.')
# bar
style.create('bar', 'default', '(bar) The style that is used by default for bars.')
# boxen used by the various menus.
style.create('thin_hbox', 'hbox', '(box) A hbox with a small amount of spacing.')
style.create('thick_hbox', 'hbox', '(box) A hbox with a large amount of spacing.')
style.create('thin_vbox', 'vbox', '(box) A vbox with a small amount of spacing.')
style.create('thick_vbox', 'vbox', '(box) A vbox with a large amount of spacing.')
# AUTOMATICALLY GENERATED
style.create("gm_root_window", "default", "(window) The style used for the root window of the game menu. This is primarily used to change the background of the game menu.")
style.create("gm_nav_window", "default", "(window) The style used by a window containing buttons that allow the user to navigate through the different screens of the game menu.")
style.create("gm_nav_vbox", "thin_vbox", "(box) The style that is used by the box inside the gm_nav_window")
style.create("gm_nav_button", "button", "(window, hover) The style of an unselected game menu navigation button.")
style.create("gm_nav_button_text", "button_text", "(text, hover) The style of the text of an unselected game menu navigation button.")
style.create("gm_nav_selected_button", "selected_button", "(window, hover) The style of a selected game menu navigation button.")
style.create("gm_nav_selected_button_text", "selected_button_text", "(text, hover) The style of the text of a selected game menu navigation button.")
style.create("file_picker_entry", "button", "(window, hover) The style that is used for each of the slots in the file picker.")
style.create("file_picker_entry_box", "thin_hbox", "(box) The style that is used for the hbox inside of a file picker entry.")
style.create("file_picker_text", "default", "(text) A base style for all text that is displayed in the file picker.")
style.create("file_picker_new", "file_picker_text", "(text) The style that is applied to the number of the new slot in the file picker.")
style.create("file_picker_old", "file_picker_text", "(text) The style that is applied to the number of the old slot in the file picker.")
style.create("file_picker_extra_info", "file_picker_text", "(text) The style that is applied to extra info in the file picker. The extra info is the save time, and the save_name if one exists.")
style.create("file_picker_empty_slot", "file_picker_text", "(text) The style that is used for the empty slot indicator in the file picker.")
style.create("file_picker_window", "default", "(window) A window containing the file picker that is used to choose slots for loading and saving.")
style.create("file_picker_window_vbox", "thin_vbox", "(box) The vbox containing both the nav and the grid in the file picker.")
style.create("file_picker_navbox", "thick_hbox", "(box) The box containing the naviation (next/previous) buttons in the file picker.")
style.create("file_picker_nav_button", "button", "(window, hover) The style that is used for enabled file picker navigation buttons.")
style.create("file_picker_nav_button_text", "button_text", "(text) The style that is used for the label of enabled file picker navigation buttons.")
style.create("file_picker_grid", "default", "The style of the grid containing the file picker entries.")
style.create("yesno_window", "default", "(window) The style of a window containing a yes/no prompt.")
style.create("yesno_window_vbox", "thick_vbox", "(box) The style of a box containing the widgets in a yes/no prompt.")
style.create("yesno_label", "default", "(text) The style used for the prompt in a yes/no dialog.")
style.create("yesno_button", "button", "(window, hover) The style of yes/no buttons.")
style.create("yesno_button_text", "button_text", "(window, hover) The style of yes/no button text.")
style.create("error_window", "default", "(window) The style of the window containing internal error messages.")
style.create("error_title", "default", "(text) The style of the text containing the title of an error message.")
style.create("error_body", "default", "(text) The style of the body of an error message.")
style.create("skip_indicator", "default", "(text) The style and placement of the skip indicator.")
style.create("mm_root_window", "default", "(window) The style used for the root window of the main menu. This is primarily used to set a background for the main menu.")
style.create("mm_menu_window", "default", "(window) A window that contains the choices in the main menu. Change this to change the placement of these choices on the main menu screen.")
style.create("mm_menu_window_vbox", "thin_vbox", "(box) The vbox containing the main menu choices.")
style.create("mm_button", "button", "(window, hover) The style that is used on buttons that are part of the main menu.")
style.create("mm_button_text", "button_text", "(text, hover) The style that is used for the labels of buttons that are part of the main menu.")
style.create("prefs_window", "default", "(window) A window containing all preferences.")
style.create("prefs_pref", "default", "(window) A window containing an individual preference.")
style.create("prefs_pref_vbox", "thin_vbox", "(box) The style of the vbox containing a preference.")
style.create("prefs_label", "default", "(text) The style that is applied to the label of a block of preferences.")
style.create("prefs_hbox", "default", "If library.hbox_pref_choices is True, the style of the hbox containing the choices.")
style.create("prefs_button", "button", "(window, hover) The style of an unselected preferences button.")
style.create("prefs_button_text", "button_text", "(text, hover) The style of the text of an unselected preferences button.")
style.create("prefs_selected_button", "selected_button", "(window, hover) The style of a selected preferences button.")
style.create("prefs_selected_button_text", "selected_button_text", "(text, hover) The style of the text of a selected preferences button.")
style.create("prefs_volume_slider", "prefs_slider", "(bar) The style that is applied to volume sliders.")
style.create("prefs_slider", "bar", "(bar) The style that is applied to preference sliders.")
style.create("prefs_spinner", "default", "The position of the prefs spinner.")
style.create("prefs_spinner_label", "prefs_label", "(text) This is the style that displays the value of a preference spinner.")
style.create("prefs_spinner_button", "prefs_button", "(window, hover) The style of the + or - buttons in a preference spinner.")
style.create("prefs_spinner_button_text", "prefs_button_text", "(text, hover) The style of the text of the + and - buttons in a preference spinner.")
style.create("prefs_js_button", "prefs_button", "(window, hover) The style of buttons giving a joystick mapping.")
style.create("prefs_js_button_text", "prefs_button_text", "(text, hover) The style of the text in buttons giving a joystick mapping.")
style.create("joy_window", "prefs_window", "(window) The window containing the joystick message.")
style.create("joy_vbox", "thick_vbox", "(window) The vbox containing the joistick mapping message.")
style.create("joyfunc_label", "prefs_label", "(text, position) The style of the joystick mapping function name.")
style.create("joyprompt_label", "prefs_label", "(text, position) The style of the joystick mapping prompt message.")
style.create("prefs_jump", "prefs_pref", "(window) The style of a window containing a jump preference.")
style.create("prefs_jump_button", "prefs_button", "(window, hover) The style of a jump preference button.")
style.create("prefs_jump_button_text", "prefs_button_text", "(text, hover) The style of jump preference button text.")
style.create("prefs_column", "default", "The style of a vbox containing a column of preferences.")
style.create("prefs_left", "prefs_column", "The position of the left column of preferences.")
style.create("prefs_center", "prefs_column", "The position of the center column of preferences.")
style.create("prefs_right", "prefs_column", "The position of the right column of preferences.")
# END AUTOMATICALLY GENERATED
# Colors #############################################################
dark_cyan = (0, 192, 255, 255)
bright_cyan = (0, 255, 255, 255)
dark_red = (255, 128, 128, 255)
bright_red = (255, 64, 64, 255)
green = (0, 128, 0, 255)
# The Default Style ###################################################
# Magic.
style.default.enable_hover = True
# Text properties.
style.default.font = "Vera.ttf"
style.default.antialias = True
style.default.size = 22
style.default.color = (255, 255, 255, 255)
style.default.bold = False
style.default.italic = False
style.default.underline = False
style.default.drop_shadow = (1, 1)
style.default.drop_shadow_color = (0, 0, 0, 255)
style.default.minwidth = 0
style.default.textalign = 0
style.default.text_y_fudge = 0
style.default.first_indent = 0
style.default.rest_indent = 0
style.default.line_spacing = 0
# Window properties.
style.default.background = None
style.default.xpadding = 0
style.default.ypadding = 0
style.default.xmargin = 0
style.default.ymargin = 0
style.default.xfill = False
style.default.yfill = False
style.default.xminimum = 0 # Includes margins and padding.
style.default.yminimum = 0 # Includes margins and padding.
# Placement properties.
style.default.xpos = None # 0
style.default.ypos = None # 0
style.default.xanchor = None # 0
style.default.yanchor = None # 0
style.default.xmaximum = None
style.default.ymaximum = None
# Sound properties.
style.default.sound = None
# Box properties.
style.default.box_spacing = 0
style.default.box_layout = None
######################################################################
# The style of various boxes.
style.hbox.box_layout = 'horizontal'
style.vbox.box_layout = 'vertical'
style.thin_hbox.box_spacing = 3
style.thick_hbox.box_spacing = 30
style.thin_vbox.box_spacing = 0
style.thick_vbox.box_spacing = 30
######################################################################
# Windows.
style.window.background = Solid((0, 0, 128, 128))
style.window.xpadding = 10
style.window.ypadding = 5
style.window.xmargin = 10
style.window.ymargin = 5
style.window.xfill = True
style.window.yfill = False
style.window.xminimum = 0 # Includes margins and padding.
style.window.yminimum = 150 # Includes margins and padding.
style.window.xpos = 0.5
style.window.ypos = 1.0
style.window.xanchor = 'center'
style.window.yanchor = 'bottom'
######################################################################
# Image placement.
style.image_placement.xpos = 0.5
style.image_placement.ypos = 1.0
style.image_placement.xanchor = 'center'
style.image_placement.yanchor = 'bottom'
######################################################################
# Dialogue
style.say_label.bold = True
style.menu_choice.hover_color = (255, 255, 0, 255) # yellow
style.menu_choice.activate_color = (255, 255, 0, 255) # yellow
style.menu_choice.idle_color = (0, 255, 255, 255) # cyan
style.input_text.color = (255, 255, 0, 255)
# Styles used by centered.
style.centered_window.xpos = 0.5
style.centered_window.xanchor = 'center'
style.centered_window.xfill = False
style.centered_window.ypos = 0.5
style.centered_window.yanchor = 'center'
style.centered_window.yfill = False
style.centered_window.xpadding = 10
style.centered_text.textalign = 0.5
style.centered_text.xpos = 0.5
style.centered_text.ypos = 0.5
style.centered_text.xanchor = 'center'
style.centered_text.yanchor = 'center'
######################################################################
# Buttons.
style.button.xpos = 0.5
style.button.xanchor = 'center'
style.button_text.xpos = 0.5
style.button_text.xanchor = 'center'
style.button_text.size = 24
style.button_text.color = dark_cyan
style.button_text.hover_color = bright_cyan
style.button_text.activate_color = bright_cyan
style.button_text.insensitive_color = (192, 192, 192, 255)
style.button_text.drop_shadow = (2, 2)
style.selected_button_text.color = dark_red
style.selected_button_text.hover_color = bright_red
style.selected_button_text.activate_color = bright_red
######################################################################
# Bar.
style.bar.left_bar = Solid(bright_cyan)
style.bar.right_bar = Solid((0, 0, 0, 128))
style.bar.left_gutter = 0
style.bar.right_gutter = 0
style.bar.thumb = None
style.bar.thumb_offset = 0
style.bar.thumb_shadow = None
######################################################################
# Main menu.
style.mm_root_window.background = Solid((0, 0, 0, 255))
style.mm_root_window.xfill = True
style.mm_root_window.yfill = True
style.mm_menu_window.xpos = 0.9
style.mm_menu_window.xanchor = 'right'
style.mm_menu_window.ypos = 0.9
style.mm_menu_window.yanchor = 'bottom'
######################################################################
# Game menu common.
style.gm_root_window.background = Solid((0, 0, 0, 255))
style.gm_root_window.xfill = True
style.gm_root_window.yfill = True
style.gm_nav_window.xpos = 0.9
style.gm_nav_window.xanchor = 'right'
style.gm_nav_window.ypos = 0.95
style.gm_nav_window.yanchor = 'bottom'
##############################################################################
# File picker.
style.file_picker_window.xpos = 0
style.file_picker_window.xanchor = 'left'
style.file_picker_window.ypos = 0
style.file_picker_window.yanchor = 'top'
style.file_picker_window.xpadding = 5
style.file_picker_navbox.xpos = 10
style.file_picker_grid.xfill = True
style.file_picker_entry.xpadding = 5
style.file_picker_entry.ypadding = 2
style.file_picker_entry.xmargin = 5
style.file_picker_entry.xfill = True
style.file_picker_entry.ymargin = 2
style.file_picker_entry.background = Solid((255, 255, 255, 255))
style.file_picker_entry.hover_background = Solid((255, 255, 192, 255))
style.file_picker_entry.activate_background = Solid((255, 255, 192, 255))
style.file_picker_text.size = 18
style.file_picker_text.color = dark_cyan
style.file_picker_text.hover_color = bright_cyan
style.file_picker_new.hover_color = bright_red
style.file_picker_new.activate_color = bright_red
style.file_picker_new.idle_color = dark_red
style.file_picker_new.minwidth = 30
style.file_picker_old.minwidth = 30
######################################################################
# Yes/No Dialog
style.yesno_label.color = green
style.yesno_label.textalign = 0.5
style.yesno_window.xfill = True
style.yesno_window.yminimum = 0.5
style.yesno_window.xmargin = .1
style.yesno_window_vbox.xpos = 0.5
style.yesno_window_vbox.xanchor = 'center'
style.yesno_window_vbox.ypos = 0.5
style.yesno_window_vbox.yanchor = 'center'
##############################################################################
# Preferences.
style.prefs_pref.xpos = 0.5
style.prefs_pref.xanchor = 'center'
style.prefs_pref.bottom_margin = 10
style.prefs_label.xpos = 0.5
style.prefs_label.xanchor = "center"
style.prefs_label.color = green
style.prefs_slider.xmaximum=200
style.prefs_slider.ymaximum=22
style.prefs_slider.xpos = 0.5
style.prefs_slider.xanchor = 'center'
style.prefs_hbox.xpos = 0.5
style.prefs_hbox.xanchor = 'center'
style.prefs_button.xpos = 0.5
style.prefs_button.xanchor = 'center'
style.prefs_selected_button.xpos = 0.5
style.prefs_selected_button.xanchor = 'center'
style.prefs_window.xfill=True
style.prefs_window.ypadding = 0.05
style.prefs_column.box_spacing = 6
style.prefs_left.xanchor = 'center'
style.prefs_left.xpos = 1.0 / 6.0
style.prefs_center.xanchor = 'center'
style.prefs_center.xpos = 3.0 / 6.0
style.prefs_right.xanchor = 'center'
style.prefs_right.xpos = 5.0 / 6.0
style.prefs_spinner.xpos = 0.5
style.prefs_spinner.xanchor = 'center'
style.prefs_spinner_label.minwidth = 100
style.prefs_spinner_label.textalign = 0.5
style.prefs_js_button_text.size = 18
style.prefs_js_button_text.drop_shadow = (1, 1)
style.joyfunc_label.textalign = 0.5
style.joyprompt_label.textalign = 0.5
style.joy_window.xfill = True
style.joy_window.yminimum = 0.5
style.joy_window.xmargin = .1
style.joy_vbox.xpos = 0.5
style.joy_vbox.xanchor = 'center'
style.joy_vbox.ypos = 0.5
style.joy_vbox.yanchor = 'center'
######################################################################
# Skip indicator.
style.skip_indicator.xpos = 10
style.skip_indicator.ypos = 10
######################################################################
# Error messages.
style.error_window.background = Solid((220, 220, 255, 255))
style.error_window.xfill = True
style.error_window.yfill = True
style.error_window.xpadding = 20
style.error_window.ypadding = 20
style.error_title.color = (255, 128, 128, 255)
style.error_body.color = (128, 128, 255, 255)
+156
View File
@@ -0,0 +1,156 @@
#!/usr/bin/env python
import os.path
import codecs
import optparse
import traceback
import os
import re
import sys
# Extra things used for distribution.
import encodings.utf_8
import encodings.zlib_codec
import encodings.unicode_escape
import encodings.string_escape
import encodings.raw_unicode_escape
import math
def main():
dirname = os.path.dirname(sys.argv[0])
if dirname:
os.chdir(dirname)
# Add the path to the module.
sys.path.append("module")
name = os.path.basename(sys.argv[0])
if name.find(".") != -1:
name = name[:name.find(".")]
if name.find("_") != -1:
name = name[name.find("_") + 1:]
op = optparse.OptionParser()
op.add_option('--game', dest='game', default=name,
help='The directory the game is in.')
op.add_option('--python', dest='python', default=None,
help='Run the argument in the python interpreter.')
op.add_option('--lint', dest='lint', default=False, action='store_true',
help='Run a number of expensive tests, to try to detect errors in the script.')
op.add_option('--leak', dest='leak', action='store_true', default=False,
help='When the game exits, dumps a profile of memory usage.')
options, args = op.parse_args()
if options.python:
execfile(options.python)
sys.exit(0)
if not options.lint:
import renpy.display.presplash
renpy.display.presplash.start(options.game)
# Load up all of Ren'Py, in the right order.
import renpy
try:
renpy.main.main(options.game, lint=options.lint)
except Exception, e:
f = file("traceback.txt", "wU")
f.write(codecs.BOM_UTF8)
print >>f, "I'm sorry, but an exception occured while executing your Ren'Py"
print >>f, "script."
print >>f
type, value, tb = sys.exc_info()
print >>f, type.__name__ + ":",
print >>f, unicode(e).encode('utf-8')
print >>f
print >>f, renpy.game.exception_info
print >>f
print >>f, "-- Full Traceback ------------------------------------------------------------"
print >>f
traceback.print_tb(tb, None, sys.stdout)
traceback.print_tb(tb, None, f)
print >>f, type.__name__ + ":",
print type.__name__ + ":",
print >>f, unicode(e).encode('utf-8')
print unicode(e).encode('utf-8')
print
print >>f
print renpy.game.exception_info
print >>f, renpy.game.exception_info
print >>f
print >>f, "Ren'Py Version:", renpy.version
f.close()
try:
os.startfile('traceback.txt')
except:
pass
if options.leak:
memory_profile()
sys.exit(0)
def memory_profile():
import renpy
print "Memory Profile"
print
print "Showing all objects in memory at program termination."
print
import gc
gc.collect()
objs = gc.get_objects()
c = { } # count
dead_renders = 0
for i in objs:
t = type(i)
c[t] = c.get(t, 0) + 1
if isinstance(i, renpy.display.render.Render):
if i.dead:
dead_renders += 1
results = [ (count, ty) for ty, count in c.iteritems() ]
results.sort()
for count, ty in results:
print count, str(ty)
if dead_renders:
print
print "*** found", dead_renders, "dead Renders. ***"
if __name__ == "__main__":
main()
+822
View File
@@ -0,0 +1,822 @@
#!/usr/bin/python
#
# Perforce Defect Tracking Integration Project
# <http://www.ravenbrook.com/project/p4dti/>
#
# COVERAGE.PY -- COVERAGE TESTING
#
# Gareth Rees, Ravenbrook Limited, 2001-12-04
# Ned Batchelder, 2004-12-12
# http://nedbatchelder.com/code/modules/coverage.html
#
#
# 1. INTRODUCTION
#
# This module provides coverage testing for Python code.
#
# The intended readership is all Python developers.
#
# This document is not confidential.
#
# See [GDR 2001-12-04a] for the command-line interface, programmatic
# interface and limitations. See [GDR 2001-12-04b] for requirements and
# design.
"""Usage:
coverage.py -x MODULE.py [ARG1 ARG2 ...]
Execute module, passing the given command-line arguments, collecting
coverage data.
coverage.py -e
Erase collected coverage data.
coverage.py -r [-m] FILE1 FILE2 ...
Report on the statement coverage for the given files. With the -m
option, show line numbers of the statements that weren't executed.
coverage.py -a [-d dir] FILE1 FILE2 ...
Make annotated copies of the given files, marking statements that
are executed with > and statements that are missed with !. With
the -d option, make the copies in that directory. Without the -d
option, make each copy in the same directory as the original.
Coverage data is saved in the file .coverage by default. Set the
COVERAGE_FILE environment variable to save it somewhere else."""
__version__ = "2.2.20041231" # see detailed history at the end of this file.
import compiler
import compiler.visitor
import os
import re
import string
import sys
import types
# 2. IMPLEMENTATION
#
# This uses the "singleton" pattern.
#
# The word "morf" means a module object (from which the source file can
# be deduced by suitable manipulation of the __file__ attribute) or a
# filename.
#
# When we generate a coverage report we have to canonicalize every
# filename in the coverage dictionary just in case it refers to the
# module we are reporting on. It seems a shame to throw away this
# information so the data in the coverage dictionary is transferred to
# the 'cexecuted' dictionary under the canonical filenames.
#
# The coverage dictionary is called "c" and the trace function "t". The
# reason for these short names is that Python looks up variables by name
# at runtime and so execution time depends on the length of variables!
# In the bottleneck of this application it's appropriate to abbreviate
# names to increase speed.
# A dictionary with an entry for (Python source file name, line number
# in that file) if that line has been executed.
c = {}
# t(f, x, y). This method is passed to sys.settrace as a trace
# function. See [van Rossum 2001-07-20b, 9.2] for an explanation of
# sys.settrace and the arguments and return value of the trace function.
# See [van Rossum 2001-07-20a, 3.2] for a description of frame and code
# objects.
def t(f, w, a):
if w == 'line':
c[(f.f_code.co_filename, f.f_lineno)] = 1
return t
class StatementFindingAstVisitor(compiler.visitor.ASTVisitor):
def __init__(self, statements, excluded, suite_spots):
compiler.visitor.ASTVisitor.__init__(self)
self.statements = statements
self.excluded = excluded
self.suite_spots = suite_spots
self.excluding_suite = 0
def doRecursive(self, node):
self.recordNodeLine(node)
for n in node.getChildNodes():
self.dispatch(n)
visitStmt = visitModule = doRecursive
def doCode(self, node):
if hasattr(node, 'decorators') and node.decorators:
self.dispatch(node.decorators)
self.doSuite(node, node.code)
visitFunction = visitClass = doCode
def getFirstLine(self, node):
# Find the first line in the tree node.
lineno = node.lineno
for n in node.getChildNodes():
f = self.getFirstLine(n)
if lineno and f:
lineno = min(lineno, f)
else:
lineno = lineno or f
return lineno
def getLastLine(self, node):
# Find the first line in the tree node.
lineno = node.lineno
for n in node.getChildNodes():
lineno = max(lineno, self.getLastLine(n))
return lineno
def doStatement(self, node):
self.recordLine(self.getFirstLine(node))
visitAssert = visitAssign = visitAssTuple = visitDiscard = visitPrint = \
visitPrintnl = visitRaise = visitSubscript = \
visitDecorators = \
doStatement
def recordNodeLine(self, node):
return self.recordLine(node.lineno)
def recordLine(self, lineno):
# Returns a bool, whether the line is included or excluded.
if lineno:
# Multi-line tests introducing suites have to get charged to their
# keyword.
if lineno in self.suite_spots:
lineno = self.suite_spots[lineno][0]
# If we're inside an exluded suite, record that this line was
# excluded.
if self.excluding_suite:
self.excluded[lineno] = 1
return 0
# If this line is excluded, or suite_spots maps this line to
# another line that is exlcuded, then we're excluded.
elif self.excluded.has_key(lineno) or \
self.suite_spots.has_key(lineno) and \
self.excluded.has_key(self.suite_spots[lineno][1]):
return 0
# Otherwise, this is an executable line.
else:
self.statements[lineno] = 1
return 1
return 0
default = recordNodeLine
def recordAndDispatch(self, node):
self.recordNodeLine(node)
self.dispatch(node)
def doSuite(self, intro, body, exclude=0):
exsuite = self.excluding_suite
if exclude or (intro and not self.recordNodeLine(intro)):
self.excluding_suite = 1
self.recordAndDispatch(body)
self.excluding_suite = exsuite
def doPlainWordSuite(self, prevsuite, suite):
# Finding the exclude lines for else's is tricky, because they aren't
# present in the compiler parse tree. Look at the previous suite,
# and find its last line. If any line between there and the else's
# first line are excluded, then we exclude the else.
lastprev = self.getLastLine(prevsuite)
firstelse = self.getFirstLine(suite)
for l in range(lastprev+1, firstelse):
if self.suite_spots.has_key(l):
self.doSuite(None, suite, exclude=self.excluded.has_key(l))
break
else:
self.doSuite(None, suite)
def doElse(self, prevsuite, node):
if node.else_:
self.doPlainWordSuite(prevsuite, node.else_)
def visitFor(self, node):
self.doSuite(node, node.body)
self.doElse(node.body, node)
def visitIf(self, node):
# The first test has to be handled separately from the rest.
# The first test is credited to the line with the "if", but the others
# are credited to the line with the test for the elif.
self.doSuite(node, node.tests[0][1])
for t, n in node.tests[1:]:
self.doSuite(t, n)
self.doElse(node.tests[-1][1], node)
def visitWhile(self, node):
self.doSuite(node, node.body)
self.doElse(node.body, node)
def visitTryExcept(self, node):
self.doSuite(node, node.body)
for i in range(len(node.handlers)):
a, b, h = node.handlers[i]
if not a:
# It's a plain "except:". Find the previous suite.
if i > 0:
prev = node.handlers[i-1][2]
else:
prev = node.body
self.doPlainWordSuite(prev, h)
else:
self.doSuite(a, h)
self.doElse(node.handlers[-1][2], node)
def visitTryFinally(self, node):
self.doSuite(node, node.body)
self.doPlainWordSuite(node.body, node.final)
def visitGlobal(self, node):
# "global" statements don't execute like others (they don't call the
# trace function), so don't record their line numbers.
pass
the_coverage = None
class coverage:
error = "coverage error"
# Name of the cache file (unless environment variable is set).
cache_default = ".coverage"
# Environment variable naming the cache file.
cache_env = "COVERAGE_FILE"
# A map from canonical Python source file name to a dictionary in
# which there's an entry for each line number that has been
# executed.
cexecuted = {}
# Cache of results of calling the analysis2() method, so that you can
# specify both -r and -a without doing double work.
analysis_cache = {}
# Cache of results of calling the canonical_filename() method, to
# avoid duplicating work.
canonical_filename_cache = {}
def __init__(self):
global the_coverage
if the_coverage:
raise self.error, "Only one coverage object allowed."
self.usecache = 1
self.cache = None
self.exclude_re = ''
def help(self, error=None):
if error:
print error
print
print __doc__
sys.exit(1)
def command_line(self):
import getopt
settings = {}
optmap = {
'-a': 'annotate',
'-d:': 'directory=',
'-e': 'erase',
'-h': 'help',
'-i': 'ignore-errors',
'-m': 'show-missing',
'-r': 'report',
'-x': 'execute',
}
short_opts = string.join(map(lambda o: o[1:], optmap.keys()), '')
long_opts = optmap.values()
options, args = getopt.getopt(sys.argv[1:], short_opts,
long_opts)
for o, a in options:
if optmap.has_key(o):
settings[optmap[o]] = 1
elif optmap.has_key(o + ':'):
settings[optmap[o + ':']] = a
elif o[2:] in long_opts:
settings[o[2:]] = 1
elif o[2:] + '=' in long_opts:
settings[o[2:]] = a
else:
self.help("Unknown option: '%s'." % o)
if settings.get('help'):
self.help()
for i in ['erase', 'execute']:
for j in ['annotate', 'report']:
if settings.get(i) and settings.get(j):
self.help("You can't specify the '%s' and '%s' "
"options at the same time." % (i, j))
args_needed = (settings.get('execute')
or settings.get('annotate')
or settings.get('report'))
action = settings.get('erase') or args_needed
if not action:
self.help("You must specify at least one of -e, -x, -r, or -a.")
if not args_needed and args:
self.help("Unexpected arguments %s." % args)
self.get_ready()
self.exclude('#pragma[: ]+[nN][oO] [cC][oO][vV][eE][rR]')
if settings.get('erase'):
self.erase()
if settings.get('execute'):
if not args:
self.help("Nothing to do.")
sys.argv = args
self.start()
import __main__
sys.path[0] = os.path.dirname(sys.argv[0])
execfile(sys.argv[0], __main__.__dict__)
if not args:
args = self.cexecuted.keys()
ignore_errors = settings.get('ignore-errors')
show_missing = settings.get('show-missing')
directory = settings.get('directory=')
if settings.get('report'):
self.report(args, show_missing, ignore_errors)
if settings.get('annotate'):
self.annotate(args, directory, ignore_errors)
def use_cache(self, usecache):
self.usecache = usecache
def get_ready(self):
if self.usecache and not self.cache:
self.cache = os.environ.get(self.cache_env, self.cache_default)
self.restore()
self.analysis_cache = {}
def start(self):
self.get_ready()
sys.settrace(t)
def stop(self):
sys.settrace(None)
def erase(self):
global c
c = {}
self.analysis_cache = {}
self.cexecuted = {}
if self.cache and os.path.exists(self.cache):
os.remove(self.cache)
self.exclude_re = ''
def exclude(self, re):
if self.exclude_re:
self.exclude_re += "|"
self.exclude_re += "(" + re + ")"
# save(). Save coverage data to the coverage cache.
def save(self):
if self.usecache and self.cache:
self.canonicalize_filenames()
cache = open(self.cache, 'wb')
import marshal
marshal.dump(self.cexecuted, cache)
cache.close()
# restore(). Restore coverage data from the coverage cache (if it
# exists).
def restore(self):
global c
c = {}
self.cexecuted = {}
assert self.usecache
if not os.path.exists(self.cache):
return
try:
cache = open(self.cache, 'rb')
import marshal
cexecuted = marshal.load(cache)
cache.close()
if isinstance(cexecuted, types.DictType):
self.cexecuted = cexecuted
except:
pass
# canonical_filename(filename). Return a canonical filename for the
# file (that is, an absolute path with no redundant components and
# normalized case). See [GDR 2001-12-04b, 3.3].
def canonical_filename(self, filename):
if not self.canonical_filename_cache.has_key(filename):
f = filename
if os.path.isabs(f) and not os.path.exists(f):
f = os.path.basename(f)
if not os.path.isabs(f):
for path in [os.curdir] + sys.path:
g = os.path.join(path, f)
if os.path.exists(g):
f = g
break
cf = os.path.normcase(os.path.abspath(f))
self.canonical_filename_cache[filename] = cf
return self.canonical_filename_cache[filename]
# canonicalize_filenames(). Copy results from "executed" to
# "cexecuted", canonicalizing filenames on the way. Clear the
# "executed" map.
def canonicalize_filenames(self):
global c
for filename, lineno in c.keys():
f = self.canonical_filename(filename)
if not self.cexecuted.has_key(f):
self.cexecuted[f] = {}
self.cexecuted[f][lineno] = 1
c = {}
# morf_filename(morf). Return the filename for a module or file.
def morf_filename(self, morf):
if isinstance(morf, types.ModuleType):
if not hasattr(morf, '__file__'):
raise self.error, "Module has no __file__ attribute."
file = morf.__file__
else:
file = morf
return self.canonical_filename(file)
# analyze_morf(morf). Analyze the module or filename passed as
# the argument. If the source code can't be found, raise an error.
# Otherwise, return a tuple of (1) the canonical filename of the
# source code for the module, (2) a list of lines of statements
# in the source code, and (3) a list of lines of excluded statements.
def analyze_morf(self, morf):
if self.analysis_cache.has_key(morf):
return self.analysis_cache[morf]
filename = self.morf_filename(morf)
ext = os.path.splitext(filename)[1]
if ext == '.pyc':
if not os.path.exists(filename[0:-1]):
raise self.error, ("No source for compiled code '%s'."
% filename)
filename = filename[0:-1]
elif ext != '.py':
raise self.error, "File '%s' not Python source." % filename
source = open(filename, 'r')
lines, excluded_lines = self.find_executable_statements(
source.read(), exclude=self.exclude_re
)
source.close()
result = filename, lines, excluded_lines
self.analysis_cache[morf] = result
return result
def get_suite_spots(self, tree, spots):
import symbol, token
for i in range(1, len(tree)):
if type(tree[i]) == type(()):
if tree[i][0] == symbol.suite:
# Found a suite, look back for the colon and keyword.
lineno_colon = lineno_word = None
for j in range(i-1, 0, -1):
if tree[j][0] == token.COLON:
lineno_colon = tree[j][2]
elif tree[j][0] == token.NAME:
if tree[j][1] == 'elif':
# Find the line number of the first non-terminal
# after the keyword.
t = tree[j+1]
while t and token.ISNONTERMINAL(t[0]):
t = t[1]
if t:
lineno_word = t[2]
else:
lineno_word = tree[j][2]
break
elif tree[j][0] == symbol.except_clause:
# "except" clauses look like:
# ('except_clause', ('NAME', 'except', lineno), ...)
if tree[j][1][0] == token.NAME:
lineno_word = tree[j][1][2]
break
if lineno_colon and lineno_word:
# Found colon and keyword, mark all the lines
# between the two with the two line numbers.
for l in range(lineno_word, lineno_colon+1):
spots[l] = (lineno_word, lineno_colon)
self.get_suite_spots(tree[i], spots)
def find_executable_statements(self, text, exclude=None):
# Find lines which match an exclusion pattern.
excluded = {}
suite_spots = {}
if exclude:
reExclude = re.compile(exclude)
lines = text.split('\n')
for i in range(len(lines)):
if reExclude.search(lines[i]):
excluded[i+1] = 1
import parser
tree = parser.suite(text+'\n\n').totuple(1)
self.get_suite_spots(tree, suite_spots)
# Use the compiler module to parse the text and find the executable
# statements. We add newlines to be impervious to final partial lines.
statements = {}
ast = compiler.parse(text+'\n\n')
visitor = StatementFindingAstVisitor(statements, excluded, suite_spots)
compiler.walk(ast, visitor, walker=visitor)
lines = statements.keys()
lines.sort()
excluded_lines = excluded.keys()
excluded_lines.sort()
return lines, excluded_lines
# format_lines(statements, lines). Format a list of line numbers
# for printing by coalescing groups of lines as long as the lines
# represent consecutive statements. This will coalesce even if
# there are gaps between statements, so if statements =
# [1,2,3,4,5,10,11,12,13,14] and lines = [1,2,5,10,11,13,14] then
# format_lines will return "1-2, 5-11, 13-14".
def format_lines(self, statements, lines):
pairs = []
i = 0
j = 0
start = None
pairs = []
while i < len(statements) and j < len(lines):
if statements[i] == lines[j]:
if start == None:
start = lines[j]
end = lines[j]
j = j + 1
elif start:
pairs.append((start, end))
start = None
i = i + 1
if start:
pairs.append((start, end))
def stringify(pair):
start, end = pair
if start == end:
return "%d" % start
else:
return "%d-%d" % (start, end)
import string
return string.join(map(stringify, pairs), ", ")
# Backward compatibility with version 1.
def analysis(self, morf):
f, s, _, m, mf = self.analysis2(morf)
return f, s, m, mf
def analysis2(self, morf):
filename, statements, excluded = self.analyze_morf(morf)
self.canonicalize_filenames()
if not self.cexecuted.has_key(filename):
self.cexecuted[filename] = {}
missing = []
for line in statements:
if not self.cexecuted[filename].has_key(line):
missing.append(line)
return (filename, statements, excluded, missing,
self.format_lines(statements, missing))
def morf_name(self, morf):
if isinstance(morf, types.ModuleType):
return morf.__name__
else:
return os.path.splitext(os.path.basename(morf))[0]
def report(self, morfs, show_missing=1, ignore_errors=0):
if not isinstance(morfs, types.ListType):
morfs = [morfs]
max_name = max([5,] + map(len, map(self.morf_name, morfs)))
fmt_name = "%%- %ds " % max_name
fmt_err = fmt_name + "%s: %s"
header = fmt_name % "Name" + " Stmts Exec Cover"
fmt_coverage = fmt_name + "% 6d % 6d % 5d%%"
if show_missing:
header = header + " Missing"
fmt_coverage = fmt_coverage + " %s"
print header
print "-" * len(header)
total_statements = 0
total_executed = 0
for morf in morfs:
name = self.morf_name(morf)
try:
_, statements, _, missing, readable = self.analysis2(morf)
n = len(statements)
m = n - len(missing)
if n > 0:
pc = 100.0 * m / n
else:
pc = 100.0
args = (name, n, m, pc)
if show_missing:
args = args + (readable,)
print fmt_coverage % args
total_statements = total_statements + n
total_executed = total_executed + m
except KeyboardInterrupt:
raise
except:
if not ignore_errors:
type, msg = sys.exc_info()[0:2]
print fmt_err % (name, type, msg)
if len(morfs) > 1:
print "-" * len(header)
if total_statements > 0:
pc = 100.0 * total_executed / total_statements
else:
pc = 100.0
args = ("TOTAL", total_statements, total_executed, pc)
if show_missing:
args = args + ("",)
print fmt_coverage % args
# annotate(morfs, ignore_errors).
blank_re = re.compile("\\s*(#|$)")
else_re = re.compile("\\s*else\\s*:\\s*(#|$)")
def annotate(self, morfs, directory=None, ignore_errors=0):
for morf in morfs:
try:
filename, statements, excluded, missing, _ = self.analysis2(morf)
self.annotate_file(filename, statements, excluded, missing, directory)
except KeyboardInterrupt:
raise
except:
if not ignore_errors:
raise
def annotate_file(self, filename, statements, excluded, missing, directory=None):
source = open(filename, 'r')
if directory:
dest_file = os.path.join(directory,
os.path.basename(filename)
+ ',cover')
else:
dest_file = filename + ',cover'
dest = open(dest_file, 'w')
lineno = 0
i = 0
j = 0
covered = 1
while 1:
line = source.readline()
if line == '':
break
lineno = lineno + 1
while i < len(statements) and statements[i] < lineno:
i = i + 1
while j < len(missing) and missing[j] < lineno:
j = j + 1
if i < len(statements) and statements[i] == lineno:
covered = j >= len(missing) or missing[j] > lineno
if self.blank_re.match(line):
dest.write(' ')
elif self.else_re.match(line):
# Special logic for lines containing only
# 'else:'. See [GDR 2001-12-04b, 3.2].
if i >= len(statements) and j >= len(missing):
dest.write('! ')
elif i >= len(statements) or j >= len(missing):
dest.write('> ')
elif statements[i] == missing[j]:
dest.write('! ')
else:
dest.write('> ')
elif lineno in excluded:
dest.write('- ')
elif covered:
dest.write('> ')
else:
dest.write('! ')
dest.write(line)
source.close()
dest.close()
# Singleton object.
the_coverage = coverage()
# Module functions call methods in the singleton object.
def use_cache(*args, **kw): return the_coverage.use_cache(*args, **kw)
def start(*args, **kw): return the_coverage.start(*args, **kw)
def stop(*args, **kw): return the_coverage.stop(*args, **kw)
def erase(*args, **kw): return the_coverage.erase(*args, **kw)
def exclude(*args, **kw): return the_coverage.exclude(*args, **kw)
def analysis(*args, **kw): return the_coverage.analysis(*args, **kw)
def analysis2(*args, **kw): return the_coverage.analysis2(*args, **kw)
def report(*args, **kw): return the_coverage.report(*args, **kw)
def annotate(*args, **kw): return the_coverage.annotate(*args, **kw)
def annotate_file(*args, **kw): return the_coverage.annotate_file(*args, **kw)
# Save coverage data when Python exits. (The atexit module wasn't
# introduced until Python 2.0, so use sys.exitfunc when it's not
# available.)
try:
import atexit
atexit.register(the_coverage.save)
except ImportError:
sys.exitfunc = the_coverage.save
# Command-line interface.
if __name__ == '__main__':
the_coverage.command_line()
# A. REFERENCES
#
# [GDR 2001-12-04a] "Statement coverage for Python"; Gareth Rees;
# Ravenbrook Limited; 2001-12-04;
# <http://www.garethrees.org/2001/12/04/python-coverage/>.
#
# [GDR 2001-12-04b] "Statement coverage for Python: design and
# analysis"; Gareth Rees; Ravenbrook Limited; 2001-12-04;
# <http://www.garethrees.org/2001/12/04/python-coverage/design.html>.
#
# [van Rossum 2001-07-20a] "Python Reference Manual (releae 2.1.1)";
# Guide van Rossum; 2001-07-20;
# <http://www.python.org/doc/2.1.1/ref/ref.html>.
#
# [van Rossum 2001-07-20b] "Python Library Reference"; Guido van Rossum;
# 2001-07-20; <http://www.python.org/doc/2.1.1/lib/lib.html>.
#
#
# B. DOCUMENT HISTORY
#
# 2001-12-04 GDR Created.
#
# 2001-12-06 GDR Added command-line interface and source code
# annotation.
#
# 2001-12-09 GDR Moved design and interface to separate documents.
#
# 2001-12-10 GDR Open cache file as binary on Windows. Allow
# simultaneous -e and -x, or -a and -r.
#
# 2001-12-12 GDR Added command-line help. Cache analysis so that it
# only needs to be done once when you specify -a and -r.
#
# 2001-12-13 GDR Improved speed while recording. Portable between
# Python 1.5.2 and 2.1.1.
#
# 2002-01-03 GDR Module-level functions work correctly.
#
# 2002-01-07 GDR Update sys.path when running a file with the -x option,
# so that it matches the value the program would get if it were run on
# its own.
#
# 2004-12-12 NMB Significant code changes.
# - Finding executable statements has been rewritten so that docstrings and
# other quirks of Python execution aren't mistakenly identified as missing
# lines.
# - Lines can be excluded from consideration, even entire suites of lines.
# - The filesystem cache of covered lines can be disabled programmatically.
# - Modernized the code.
#
# 2004-12-14 NMB Minor tweaks. Return 'analysis' to its original behavior
# and add 'analysis2'. Add a global for 'annotate', and factor it, adding
# 'annotate_file'.
#
# 2004-12-31 NMB Allow for keyword arguments in the module global functions.
#
# C. COPYRIGHT AND LICENCE
#
# Copyright 2001 Gareth Rees. All rights reserved.
# Copyright 2004 Ned Batchelder. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the
# distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
# DAMAGE.
#
# $Id: coverage.py 5 2004-12-14 12:08:23Z ned $
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Before

Width:  |  Height:  |  Size: 505 B

After

Width:  |  Height:  |  Size: 505 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

BIN
View File
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

+1529
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Executable → Regular
+178 -310
View File
@@ -1,332 +1,200 @@
#!/home/tom/ab/renpy/lib/py3-linux-x86_64/python
# Builds a distribution of Ren'Py.
from __future__ import division, absolute_import, with_statement, print_function, unicode_literals
import future.standard_library
import future.utils
PY2 = future.utils.PY2
import sys
import os.path
import os
import compileall
import shutil
import subprocess
import argparse
import time
import collections
import sys
try:
from importlib import reload
except ImportError:
pass
def match_times(source, dest):
stat = os.stat(source)
os.utime(dest, (stat.st_atime, stat.st_mtime))
def dosify(s):
return s.replace("\n", "\r\n")
def copy_file(source, dest, license="", dos=True):
if dest.endswith(".bak"):
return
if dest.endswith(".cache"):
return
if dest.endswith("~"):
return
print source, "->", dest
sf = file(source, "rb")
df = file(dest, "wb")
if dest.endswith(".py") or dest.endswith(".rpy"):
if not dest.endswith("subprocess.py"):
df.write(license)
data = sf.read()
if dest.endswith(".txt") or dest.endswith(".py") or dest.endswith(".pyw") or \
dest.endswith(".rpy") or dest.endswith(".bat"):
if dos:
data = dosify(data)
if data.startswith("#!"):
data = data.replace("\r\n", "\n\r\n", 1)
df.write(data)
sf.close()
df.close()
match_times(source, dest)
ROOT = os.path.dirname(os.path.abspath(__file__))
def copy_tree(source, dest, should_copy=lambda fn : True, license=""):
os.makedirs(dest)
for dirpath, dirnames, filenames in os.walk(source):
def zip_rapt_symbols(destination):
"""
Zips up the rapt symbols.
"""
if "/saves" in dirpath:
continue
import zipfile
if "/CVS" in dirpath:
continue
if PY2:
zf = zipfile.ZipFile(destination + "/android-native-symbols.zip", "w", zipfile.ZIP_DEFLATED)
else:
zf = zipfile.ZipFile(destination + "/android-native-symbols.zip", "w", zipfile.ZIP_DEFLATED, compresslevel=3)
if "/.svn" in dirpath:
continue
for dn, dirs, files in os.walk("rapt/symbols"):
for fn in dirs + files:
fn = os.path.join(dn, fn)
arcname = os.path.relpath(fn, "rapt/symbols")
zf.write(fn, arcname)
reldir = dirpath[len(source):]
dstrel = dest + "/" + reldir
zf.close()
for i in dirnames:
if i == "CVS":
continue
def copy_tutorial_file(src, dest):
"""
Copies a file from src to dst. Lines between "# tutorial-only" and
"# end-tutorial-only" comments are omitted from the copy.
"""
if i == ".svn":
continue
# True if we want to copy the line.
copy = True
os.mkdir(dstrel + "/" + i)
with open(src, "r") as sf, open(dest, "w") as df:
for l in sf:
if "# tutorial-only" in l:
copy = False
elif "# end-tutorial-only" in l:
copy = True
else:
if copy:
df.write(l)
for i in filenames:
if not should_copy(i):
continue
def link_directory(dirname):
dn = os.path.join(ROOT, dirname)
if i.startswith("."):
continue
if os.path.exists(dn):
os.unlink(dn)
copy_file(dirpath + "/" + i, dstrel + "/" + i, license=license)
if PY2:
source = dn + "2"
else:
source = dn + "3"
if os.path.exists(source):
os.symlink(source, dn)
def main():
start = time.time()
ap = argparse.ArgumentParser()
ap.add_argument("version", nargs="?")
ap.add_argument("--fast", action="store_true")
ap.add_argument("--pygame", action="store", default=None)
ap.add_argument("--no-rapt", action="store_true")
ap.add_argument("--variant", action="store")
ap.add_argument("--sign", action="store_true", default=True)
ap.add_argument("--nosign", action="store_false", dest="sign")
ap.add_argument("--notarized", action="store_true", dest="notarized")
ap.add_argument("--vc-version-only", action="store_true")
ap.add_argument("--link-directories", action="store_true")
ap.add_argument("--append-version", action="store_true")
args = ap.parse_args()
link_directory("rapt")
link_directory("renios")
link_directory("web")
if args.link_directories:
return
if args.sign:
os.environ["RENPY_MAC_IDENTITY"] = "Developer ID Application: Tom Rothamel (XHTE5H7Z79)"
if PY2 and not sys.flags.optimize:
raise Exception("Not running with python optimization.")
if not os.path.abspath(sys.executable).startswith(ROOT + "/lib"):
raise Exception("Distribute must be run with the python in lib/.")
# Revision updating is done early, so we can do it even if the rest
# of the program fails.
# Determine the version. We grab the current revision, and if any
# file has changed, bump it by 1.
import renpy
if args.version is None:
args.version = ".".join(str(i) for i in renpy.version_tuple[:-1])
try:
s = subprocess.check_output([ "git", "describe", "--tags", "--dirty", ]).decode("utf-8").strip()
parts = s.strip().split("-")
dirty = "dirty" in parts
commits_per_day = collections.defaultdict(int)
for i in subprocess.check_output([ "git", "log", "-99", "--pretty=%cd", "--date=format:%Y%m%d" ]).decode("utf-8").split():
commits_per_day[i[2:]] += 1
if dirty:
key = time.strftime("%Y%m%d")[2:]
vc_version = "{}{:02d}".format(key, commits_per_day[key] + 1)
else:
key = max(commits_per_day.keys())
vc_version = "{}{:02d}".format(key, commits_per_day[key])
except Exception:
vc_version = 0
with open("renpy/vc_version.py", "w") as f:
import socket
official = socket.gethostname() == "eileen"
nightly = args.version and "nightly" in args.version
f.write("vc_version = {}\n".format(vc_version))
f.write("official = {}\n".format(official))
f.write("nightly = {}\n".format(nightly))
if args.vc_version_only:
return
try:
reload(sys.modules['renpy.vc_version']) # @UndefinedVariable
except Exception:
import renpy.vc_version # @UnusedImport
reload(sys.modules['renpy'])
if args.append_version:
args.version += "-" + renpy.version_only
# Check that the versions match.
full_version = renpy.version_only # @UndefinedVariable
if "-" not in args.version \
and not full_version.startswith(args.version):
raise Exception("The command-line and Ren'Py versions do not match.")
os.environ['RENPY_BUILD_VERSION'] = args.version
# The destination directory.
destination = os.path.join("dl", args.version)
if args.variant:
destination += "-" + args.variant
if os.path.exists(os.path.join(destination, "checksums.txt")):
raise Exception("The checksums.txt file exists.")
print("Version {} ({})".format(args.version, full_version))
if sys.version_info[0] >= 3:
renpy_sh = "./renpy3.sh"
else:
renpy_sh = "./renpy2.sh"
# Compile all the python files.
compileall.compile_dir("renpy/", ddir="renpy/", force=True, quiet=1)
# Compile the various games.
if not args.fast:
for i in [ 'tutorial', 'launcher', 'the_question' ]:
print("Compiling", i)
subprocess.check_call([renpy_sh, i, "compile" ])
# Kick off the rapt build.
if not args.fast:
print("Cleaning RAPT.")
sys.path.insert(0, os.path.join(ROOT, "rapt", "buildlib"))
import rapt.interface # type: ignore
import rapt.build # type: ignore
interface = rapt.interface.Interface()
rapt.build.distclean(interface)
print("Compiling RAPT and renios.")
compileall.compile_dir("rapt/buildlib/", ddir="rapt/buildlib/", quiet=1)
compileall.compile_dir("renios/buildlib/", ddir="renios/buildlib/", quiet=1)
if not os.path.exists(destination):
os.makedirs(destination)
zip_rapt_symbols(destination)
if args.fast:
cmd = [
renpy_sh,
"launcher",
"distribute",
"launcher",
"--package",
"sdk",
"--destination",
destination,
"--no-update",
]
else:
cmd = [
renpy_sh,
"launcher",
"distribute",
"launcher",
"--destination",
destination,
]
if args.notarized:
cmd.extend([
"--macapp",
"notarized/out",
])
print()
subprocess.check_call(cmd)
# Sign the update.
if not args.fast:
subprocess.check_call([
"scripts/sign_update.py",
"/home/tom/ab/keys/renpy_private.pem",
os.path.join(destination, "updates.json"),
])
# Package pygame_sdl2.
if not args.fast:
subprocess.check_call([
"pygame_sdl2/setup.py",
"-q",
"egg_info",
"--tag-build",
"-for-renpy-" + args.version,
"sdist",
"-d",
os.path.abspath(destination)
])
# Write 7z.exe.
sdk = "renpy-{}-sdk".format(args.version)
if not args.fast:
# shutil.copy("renpy-ppc.zip", os.path.join(destination, "renpy-ppc.zip"))
with open("7z.sfx", "rb") as f:
sfx = f.read()
os.chdir(destination)
if os.path.exists(sdk):
shutil.rmtree(sdk)
subprocess.check_call([ "unzip", "-q", sdk + ".zip" ])
if os.path.exists(sdk + ".7z"):
os.unlink(sdk + ".7z")
sys.stdout.write("Creating -sdk.7z")
p = subprocess.Popen([ "7z", "a", sdk + ".7z", sdk], stdout=subprocess.PIPE)
for i, _l in enumerate(p.stdout): # type: ignore
if i % 10 != 0:
continue
sys.stdout.write(".")
sys.stdout.flush()
if p.wait() != 0:
raise Exception("7z failed")
with open(sdk + ".7z", "rb") as f:
data = f.read()
with open(sdk + ".7z.exe", "wb") as f:
f.write(sfx)
f.write(data)
os.unlink(sdk + ".7z")
shutil.rmtree(sdk)
else:
os.chdir(destination)
if os.path.exists(sdk + ".7z.exe"):
os.unlink(sdk + ".7z.exe")
print()
print("Distribute took {:.0f} seconds.".format(time.time() - start))
target = sys.argv[1]
gamedir = sys.argv[2]
# Read license.
lf = file("LICENSE.txt")
license = "#!/usr/bin/env python\n\r\n"
for l in lf:
if l.startswith("---"):
break
license += "# " + l
lf.close()
license = dosify(license)
if os.path.exists(target):
raise Exception("Target exists!")
# Start off with the target.
copy_tree("dist", target,
should_copy = lambda fn : fn not in [ 'traceback.txt' ] and not fn.endswith(".log"))
# Copy renpy modules.
copy_tree("renpy", target + "/renpy",
should_copy = lambda fn : fn.endswith(".py"),
license=license)
doc_files = [
'example.html',
'reference.html',
'style.css',
'RELEASING.txt',
'EXTENDING.txt',
]
# Copy doc
copy_tree("doc", target + "/doc",
should_copy = lambda fn : fn in doc_files)
# Copy the game
copy_tree(gamedir, target + "/game",
should_copy = lambda fn : not fn.endswith(".mpg"))
copy_tree("common", target + "/common")
# copy_tree("dse", target + "/dse")
copy_tree("extras", target + "/extras",
should_copy = lambda fn : not (fn.endswith(".rpyc") or fn.endswith(".rpyb")) )
copy_tree("scripts", target + "/scripts")
copy_tree("tools", target + "/tools", license=license)
def cp(x, license="", dos=True):
copy_file(x, target + "/" + x, dos=dos)
cp("CHANGELOG.txt")
cp("LICENSE.txt")
cp("README_RENPY.txt")
# cp("archive_images.bat")
# cp("lint.bat")
cp("run_game.py", license=license)
# copy_file("run_game.py", target + "/run_game.pyw", license=license)
# copy_file("run_game.py", target + "/run_dse.py", license=license)
# copy_file("run_game.py", target + "/run_dse.pyw", license=license)
# copy_file("run_game.rpyl", target + "/run_game.rpyl")
# copy_file("run_dse.rpyl", target + "/run_dse.rpyl")
# cp("archiver.py", license=license)
# cp("build_exe.py", license=license)
# cp("add_from.py", license=license)
# cp("dump_text.py", license=license)
# cp("renpy-mode.el")
os.mkdir(target + "/module")
module_files = [
"README.txt",
"_renpy.pyx",
"_renpy.c",
"core.c",
"linmixer.py",
"native_midi.h",
"native_midi_common.c",
"native_midi_common.h",
"native_midi_mac.c",
"native_midi_win32.c",
"nativemidi.c",
"nativemidi.pyx",
"pss.c",
"pss.h",
"pysdlsound.c",
"pysdlsound.pyx",
"rwobject.c",
"renpy.h",
"setup.py",
"winmixer.c",
"winmixer.pyx",
]
for i in module_files:
cp("module/" + i)
if __name__ == "__main__":
main()
+13
View File
@@ -0,0 +1,13 @@
Steps one needs to take to make a Ren'Py distro.
0) Update the documentation. (This involves dump_styles, and perhaps
copying in a new config.keymap)
1) Change the version in run_game.py
2) In cygwin, run "release.sh <version>"
3) Test run_game.exe
4) Test console.exe
8) Release.
+98
View File
@@ -0,0 +1,98 @@
================
Extending Ren'Py
================
This document talks a bit about extending Ren'Py using Python
modules. This is fairly advanced stuff, as several things change
between python-in-Ren'Py and python modules. Still, python modules
allow one to extend the very core of Ren'Py itself, which may come in
handy one day. They also let you leave Ren'Py entirely, to write
things like minigames in pygame directly.
It's assumed that if you're reading this, you have a decent amount of
familiarity with programming in Python. If this isn't the case, then
you should probably go and read the documentation on
http://www.python.org/.
Python Modules in Ren'Py
========================
Python modules can be imported from Ren'Py code using the standard
Python import statement. Ren'Py installs an import hook that will
attempt to load python modules from the same places that it searches
for all game data. This includes the game directory, and any archives
listed in config.archives.
It's important to ensure that your modules do not conflict with
standard python modules used by Ren'Py, or with the renpy modules
themselves. This is best done by putting your modules in an unused
package, such as local. Ren'Py respects the Python convention that a
package is a directory with an __init__.py file in it, and extends
this convention into .rpa files when necessary.
There are a number of differences between Python modules loaded by
Ren'Py and python-in-renpy as found in the python blocks used in .rpy
scripts. One of these differences is that the module names used are
fairly different. Some of the commonly used modules have different
from python-in-renpy (and hence the documentation). Some of these
changes are:
* ui is renpy.ui
* anim is renpy.display.anim
* config is renpy.config
* renpy.sound is renpy.audio.sound
* renpy.music is renpy.audio.music
* renpy is renpy.exports
* The top-level namespace is renpy.store
It's important to deal with these name changes when writing python
module code.
A second, and perhaps more important, change is that objects loaded
from python modules do not, by default, participate in
rollback. Because of this, we do not recommend returning dictionaries,
lists, or objects from python module code, but instead we prefer
returning immutable types (such as strings, integers, floats, and
tuples).
If it is necessary to return an object that needs to participate in
rollback, then one must construct objects of the appropriate types
manually. Lists must be of type renpy.python.RevertableList,
dictionaries of type renpy.python.RevertableDict, and object should be
of a subclass of renpy.python.RevertableObject.
Writing Pygame in Ren'Py
========================
It's possible (if perhaps not recommended) to include pygame code in
Ren'Py. One use of this would be to implement mini-games that would
otherwise not fit into the Ren'Py framework. (But it may make more
sense to implement a minigame as a Ren'Py widget.) It can be done by
importing the appropriate pygame modules, and then calling pygame
functions as desired.
Ren'Py initializes the pygame display to be 24 or 32 bits in depth, at
the sizes chosen by screen_width and screen_height. The display is set
to be a software surface. The display can be retrieved with
pygame.display.get_surface().
The pygame mixer is not initialized, and is often not included as part
of Ren'Py. Instead, we recommend using renpy.audio.sound and
renpy.audio.music calls to play sound and music. When playing music,
it is necessary to call renpy.audio.interact() after music is changed,
and renpy.audio.periodic() on a regular basis (Ren'Py does it at 20Hz)
to ensure that track updates occur when appropriate.
On returning to Ren'Py from a pygame interation that redraws the
screen, it is necessary to call
renpy.exports.force_full_redraw(). This will force the screen to be
redrawn completely. If this is not done, Ren'Py may not know about
areas of the screen drawn to directly with pygame.
Implementing Ren'Py Widgets
===========================
(This hasn't been written yet, bug PyTom if you really need it.)
+14
View File
@@ -0,0 +1,14 @@
Some notes about making sure things are imported in the proper order:
1) Every module should import 'renpy'.
2) It's okay for modules to 'import renpy.game as game'.
3) Those are all the imports that normal modules should do.
4) renpy/__init__.py should list all the modules in the system, a
topologically sorted order, such that if a definition in a uses
a definition in b, b comes before a. Please note that this only
considers the top level of the file.
+12
View File
@@ -0,0 +1,12 @@
all:: reference.html example.html
reference.html: reference.xml preprocess.py stylesheet.xslt style.css styles.xml
python preprocess.py reference.xml > reference.hi.xml
xsltproc stylesheet.xslt reference.hi.xml > reference.html
cp reference.html style.css ~/ab/website/renpy/devel/doc
example.html: example.xml preprocess.py stylesheet.xslt style.css styles.xml ../demo2/script.rpy
python preprocess.py example.xml > example.hi.xml
xsltproc stylesheet.xslt example.hi.xml > example.html
cp example.html style.css ~/ab/website/renpy/devel/doc
+131
View File
@@ -0,0 +1,131 @@
Releasing Ren'Py Games
PyTom <pytom@bishoujo.us>
Updated: 2005-11-21
Okay, so you've finished creating a game using Ren'Py, and now you
want to release it. Congratulations! This tech note will help you to
package up your creation and send it into the world.
The first thing to do is to check to see if you have the latest
version of Ren'Py. New versions of Ren'Py fix bugs in old versions. If
you're not using the latest version, your game may have known bugs in
it. At the very least, ask about what was fixed between versions if
you insist on using an older version.
The next thing to do is to ensure that you actually have a finished
and working game. Did you remember to run add_from? The easiest way to
do this is to change into the tools/ directory, and run
game_add_from.bat. That tool will add from clauses to all of the call
statements in your program, ensuring that everything continues working
after a game is reloaded. It will also create .bak files for each of
the .rpy files it can find, so you'll probably want to delete those by
hand once you've tested the changes.
You'll also want to run game_lint.bat, also found in the tools/
directory. This is a tool that will check your Ren'Py game for subtle
bugs. If it reports any bugs, you should fix them, and run lint.bat
again until they're all fixed. If you've changed the name of the .exe,
you'll probably need to edit lint.bat so that it runs. In general, you
don't want to release a game with lint errors, or at least a good
excuse for said errors. Many of the problems that are found this way
are fairly subtle, and only manifest themselves on some of the
platforms Ren'Py supports.
If you're not totally sure that everything is A-OK, you can send me
the game and I will check it over in confidence. If there's enough
demand, I'll put together a tool that will elide the game text, so
just the code and structure is left.
I also ask that you add a Ren'Py credit into your game. I tend to use
the line "Powered by Ren'Py.", but feel free to word it however you
want.
Another thing to do is to change the icon of the exe file. The best
way to do this is to create a .ico file containing 48x48, 32x32, and
16x16 versions of your icon, and then to use XN Resource Explorer to
go in and change the icon of the file. Just delete off the existing
icon, and then do a command like "Import image resource..." (going
from memory here) to add in the new icon. Save the modified
executable.
Now, we have everything that goes into the final distribution. In
fact, we have more than enough, as Ren'Py ships with a number of tools
that aren't needed to run a game. So we need to decide which files to
keep in various circumstances.
There are basically three different kinds of distributions you can
make. The first is a windows executable distribution (abbreviated
windows), that allows the user to run your game without having to
download any additional software. The second kind is a
python-dependent (python) distribution, which can run on any computer
that supports python 2.3 and pygame. The final type of distribution
that is supported is a cross platform distribution, which can run both
on windows and on any computer that supports python.
To make a windows distribution, you need the files that I'll mark
windows or all. To make a python distribution, you need the files that
I'll mark python and all. And to make a cross-platform distribution,
you'll need all the indicated files.
Anyway, the list of files that you may concievably want to include as
part of your game are:
common/ [all] - A directory containing common script files that help
Ren'Py work.
lib/ [windows] - A directory containing the code and libraries needed
to run Ren'Py on windows.
game/ [all] - The game directory containing your scripts and
data. You probably do not want to distribute the saves/ directory
inside here, so remove that. Be sure not to distribute
game/saves/persistent, and be warned that it is recreated each time
Ren'Py is run.
run_game.exe [windows] - The game executable that the user runs.
moonlight.py [python] - The main python script that runs your game.
python23.dll [windows] - The DLL containing the python interpreter. It
may change versions in the future, in which case the numbers will
change.
renpy/ [python] - Contains the python source code for Ren'Py.
module/ [python] - Contains the source code for the _renpy module.
LICENSE.txt [all] - The license for Ren'Py. You may want to integrate
this into the license for your game as a whole.
README_RENPY.txt [all] - Instructions for running a Ren'Py game. You
may want to integrate this into your own README.
Anyway, once you have all of the files, you can zip them up (perhaps
adding in things like README and license files) and post them on the
web. You've just released a Ren'Py game!
For the record, the following are the files distributed with Ren'Py
that should not be distributed with a game.
CHANGELOG.txt - The Ren'Py changelog.
console.exe - A console/debugging version of Ren'Py.
extras - Scripts that give additional features. Uninteresting as a
whole, as to be used the scripts must be in the game/ directory.
scripts - Example scripts.
tools - Development tools.
game/saves - This is the directory containing the savegame info. It
should be deleted before distribution, but please note that running
Ren'Py recreates it automatically. It contains a file named persistent
that stores the list of seen lines. Shipping a persistent file
may lead to the option to skip seen text skipping text not seen by
the end-user.
+15
View File
@@ -0,0 +1,15 @@
# With pygame surfaces and fill.
Menu mousemove: .1336, .1244, .1437
"Save when I tell you to": .055, .066, .0476
# Without fill.
Menu mousemove: .115, .129, .134
"Save when I tell you to": .050, .057, .046
# With new surface code.
Menu mousemove: .02something
"Save when I tell you to": .038, .040, .038
+44
View File
@@ -0,0 +1,44 @@
import xml.dom.minidom
import sys
def escape(s):
return s.replace("&", "&amp;").replace("<", "&lt;").replace('"', "&quot;")
def transform_children(node):
rv = [ ]
for n in node.childNodes:
rv.append(transform(n))
return ''.join(rv)
def transformElement(node):
attributes = ' '.join(['%s="%s"' % (k, escape(v)) for k,v in node.attributes.items()])
tag = node.tagName
# Otherwise, the default.
return "<%s %s>%s</%s>" % (node.tagName, attributes,
transform_children(node), node.tagName)
def transform(node):
if node.nodeType == node.ELEMENT_NODE:
return transformElement(node)
else:
return escape(str(node))
def main():
dom = xml.dom.minidom.parse(sys.argv[1])
print transform(dom.documentElement)
if __name__ == "__main__":
main()
+13
View File
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
<doc>
<title>Demo Script Example</title>
<p><a href="tutorial.html">Return to the tutorial.</a></p>
<example>
<!-- include ../demo2/script.rpy -->
</example>
<p><a href="tutorial.html">Return to the tutorial.</a></p>
</doc>
+163
View File
@@ -0,0 +1,163 @@
<?xml version="1.0" encoding="utf-8" ?>
<renpydoc>
<!-- (define-key xml-mode-map '(control return) 'tompy-xml-ctrlret) -->
<section title="Say Statement">
<rule name="statement">
<alt>string</alt>
<alt>string string</alt>
<alt>identifier string</alt>
</rule>
<formal>
These three productions are the various forms of the say
statement. In order, they are the 1-string form, the 2-string
form, and the name-string form. We'll discuss individually
what each one does.
</formal><formal>
The 1-string form calls the <f>say</f> function (found in the
execution context) with the string.
</formal><formal>
The 2-string form also calls the <f>say</f> function, but this
time it passes it the two strings. The strings are passed in the
order in which they appear.
</formal><formal>
When a identifierstring say statement is executed, the first thing
that happens is that the identifier is looked up in the execution
context. It's an error if the name is not defined. If the name
is bound to a string, both strings are passed to the <f>say</f>
function, as if the 2-string form was used. Otherwise, the
<f>say</f> method is called on the object that the identifier was
bound to, with the string as the only argument.
</formal>
<user>
While the various say statements are very flexible, there are
some conventions that we suspect users will use when writing
games.
</user><user>
The 1-string form of the say statment is rendered to the user in
a text box without any name associated with it. It's used to
indicate the thoughts of the POV character, or to narrate
actions that occur in the game.
</user><user>
The 2-string form is displayed with the first string as a name,
and the second string as the line of dialogue said by the
character with that name. It's used to indicate spoken dialogue,
usually from characters that are minor enough to not have a
character object associated with them. The 2-string form is
rarely used directly, as normally the name-string or 1-string
forms are preferred for dialogue from main characters.
</user><user>
Generally, when the name-string form is used, the first name
refers to a character object. The name field of that character
object is looked up, and used to display dialogue as if the
2-string form was used. So the name-string form is what is used
when we want a main character to say something. This form allows
the direct use of the character's name before the dialogue,
without requiring the quoting needed by the 2-string form.
</user>
<example>
"I was walking down the street one day, when I came across the postman."
me "Hey, any mail for me today?"
"Postman" "Yeah, a package came for you. But there's no return address."
</example>
</section>
<subsection title="Image Display">
<formal>
In Ren'Py, image display is controlled by a pair of image
lists. The two image lists are the are called the master image
list and the temporary image list. These lists contain python
objects that are capable of drawing themselves to the
screen. When the time comes to show something to the user, we
iterate through the temporary image list, drawing things on
the screen in the order in which they appear in the list. So
the first thing in the list will be the background, and the
thing that's drawn closest to the user will be the last thing
in the list.
</formal><formal>
We can divide the execution of a Ren'Py program into periods
where we are showing a screen to the user (for example, during
the execution of a say statement) and periods where we are
not. After a period of showing the screen to the user, the master image
list is copied over the temporary image list.
</formal>
<user>
We have two image lists for two reasons. The first is the idea
that only the temporary image list will include transitions,
and once we're done performing the transition, we want it to
be remove from the list. The second reason is an idea that
(behind the scenes) the temporary list will also include
interface elements (like boxes containing character
dialog). We, in general, want these boxes to be shown to the
user once and then removed from the screen.
</user>
<rule name="image_name">
<alt>identifier+</alt>
</rule>
<formal>
An image name consists of one or more identifiers. The first
identifier is called the primary identifier of this image
name, while the second and later identifier are called
secondary identifers. An image name may not include a Ren'Py
keyword.
</formal><formal>
Ren'Py maintains an image dictionary, which maps between image
names and objects implementing images that can be show to the
user.
</formal>
<user>
The idea behind primary identifiers is that we will normally
want to display only one image of a character at a time. So we
use an image's primary identifier to find other images in the
master display list that have the same primary identifier.
</user>
<rule name="statement">
<alt>"image" image_name "=" python_expression</alt>
</rule>
<formal>
This adds a new entry to the image dictionary. Specifically, the
python_expression is evaluated to get something that's drawable,
and then that object is stored in a tuple in the image
dictionary.
</formal>
<user>
In general, the python expression will be a call to the image
constructor, which loads in a new image from disk (or
somewhere... read the documentation for the image constructor.)
It's also possible to use another constructor, like the one for
animation, but that will probably be more rare.
</user><user>
It's important to note that this doesn't actually load the image
into ram, until close to the time when the image is actually
needed.
</user><user>
In general, it makes sense to ensure that all image statements
execure during game startup, before the call to
startup_complete().
</user>
<example>
image woods = image("backgrounds/woods.jpg")
image eileen red upset = image("eileen/red_upset.png")
image eileen red happy = image("eileen/red_happy.png")
</example>
</subsection>
</renpydoc>
+373
View File
@@ -0,0 +1,373 @@
To write a game using Ren'Py, one must become familar with the Ren'Py
script language. This file gives some basic concepts and a list of
Ren'Py statements. A second file will give a list of python classes
and functions that are intended to be used from Ren'Py code.
A Ren'Py script can first be seen as a long string of unicode
characters. This string is first broken up into logical lines, then
the lines are organized into blocks, and finally as a tree of
statements. So we'll begin by defining some basic terms, and then
we'll go on to give a list of statements Ren'Py understands.
Logical Lines:
Each file consists of one or more logical lines. The first logical
line begins at the first character file, and subsequent logical lines
begin immediately following the end of the previous line. Logical
lines are normally ended by the first newline encountered. However,
there are several cases that will cause a logical line to extend past
a newline character:
<ul>
<li>
A logical line containing a string must extend at least until the
end of that string.
</li>
<li>
A logical line parenthesis, brackets, or braces cannot end until
each opening character ('(', ']', or '}') is matched with a closing
character (')', ']', or '}'). The expression enclosed within is called
a parenthetical expression.
</li>
<li>
A newline immediately preceded by a backslash will not end a logical
line. Instead, both characters will be treated as whitespace, and
ignored.
<li>
</ul>
Logical lines are numbered by giving the number of the physical line
in the file on which the logical line begins. (At most one logical
line can exist on each physical line.)
If a logical line contains a hash mark in it ('#'), all characters
from the hash mark to character before the next physical newline are
considered to be part of a comment, and are ignored as if they were
whitespace. If, after this step, a logical line consists entirely of
whitespace, it is ignored.
Each logical line has an indentaion level. This is computed by first
converting tabs to spaces (using 8-space tab stops), and then looking
at the number of spaces preceding the first non-whitespace character
on the line.
The following examples all consist of single logical lines with
indentation level 0.
<example>
me "How are you doing?"
</example>
<example>
"It's a question that I ask myself every day. Today, however, is
the first time I've asked it of someone else.
</example>
<example>
$ my_list = [ 1, 2, 3, 4,
5, 6, 7, 8 ]
</example>
<example>
$ a = 1 \
+ 2 \
+ 3
</example>
Blocks:
If a logical line is followed by a logical line with greater
indentation, the second logical line is considered to be part of the
block of the first logical line. This block contains all logical lines
with an indentation level equal to that of the second logical line,
provided there are no intervening lines with an indentaion level that
is less than that of the second logical line. If a line is encountered
with an indentation level that is greater than that of the first
logical line, but less than that of the second, the indentation is
mismatched and an error is reported.
An example of a block (as part of an if statement) is:
<example>
if happy:
e "I'm feeling really happy today."
e "It's like I'm the happiest person in the world."
</example>
An example of an indentation mismatch is:
<example>
else:
e "I'm having a really bad day."
e "I can't even get the indentation right."
</example>
One of the things we can parse is a string literal. String literals
begin with a quote character (' or "), and end with a matching
unescaped quote character. Strings use backslash (\) as an escape
character. The following are suppored escape sequences:
<ul>
<li>"\\" - Backslash</li>
<li>"\"" - Double Quote</li>
<li>"\'" - Single Quote</li>
<li>"\n" - Newline</li>
<li>"\ " - Space</li>
</ul>
As the string is being parsed, but before escape processing is done,
contiguous sequences of whitespace are converted to single space
characters. To include more than single spaces, explicitly escape the
desired whitespace.
<example>
"I hate having to \"escape\" whitespace."
</example>
Names and Numbers:
Names begin with a character in the set [a-zA-Z_], and may contain
additional characters in the set [a-zA-Z0-9_]. A keyword in Ren'Py may
not be used as a name.
Some example names are:
<example>
eileen
lucy
molly
crm_114
_underscore_
</example>
A dotted_name consists of one or more names, separated by dots '.'.
<example>
eileen
eileen.name
eileen.address.street
</example>
A number matches the characters [0-9.].
<example>
1
1234.
3.14159
.2
</example>
Python:
Ren'Py scripts may contain embedded python. There are three kinds of
python things that can be mixed into Ren'Py: simple_expressions,
python_expressions, and python_statements.
A simple_expression consists of either a dotted_name, string, or
number optionally followed by a parenthetical expression, or just a
single parenthetical expression.
Examples of simple_expressions are:
<example>
eileen
sample.image("foo.jpg", size=(100,200))
"test"
(1 + 2 + 3)
</example>
Python_expressions occur in statements such as if and while, and
extend from the current location on the logical line to just before
the next ':' that is not contained within a parenthetical expression
on the logical line.
Examples of expressions that are python_expressions but not
simple_expressions are:
<example>
1 + 2 + 3
foo.bar().baz()
</example>
Finally, python_statements simply assume that all remaining
information on the line should be interpreted as python code.
Statements:
The parsing of each logical line is syntax-directed. When parsing a
block, all of the logical lines in that block are parsed as
statements. The logical lines at the top level of a file are
considered to form a block. Here, we give the rules for parsing each
kind of statement, as well as an overview of what each statement
does. We'll first give some insight as to what a statement does when
used with the standard library, and then we'll write a little about
how it goes about accomplishing that task.
Say Statements:
<rule name="statement">
<alt>string</alt>
<alt>simple_expression string</alt>
</rule>
Probably the most commonly used statement in a Ren'Py script is the
say statement. It's so commonly used that we chose not to denote it
with a keyword, but instead to simply make all bare strings or
simple_expression string pairs into say statements.
Executing a say statement results in a line of dialogue or thought
being displayed to the user. Ren'Py then waits for the user to click
or otherwise dismiss the display before proceeding with execution of
the program.
In the single string version of the statement, the string is taken as
a thought or narration that should be displayed, unadorned, to the
user. If the string is preceded by a simple_expression, the expression
is first evaluated to yield a string, and that string is used to
indicate to the user who is speaking the line of dialogue.
Ren'Py executes say statements by first evaluating the
simple_expression, if present, and then calling the say function with
the values of the two strings, or None if the simple_expression is not
defined. Take a look at the documentation for the say function to see
what happens from there, as behind the scenes it's a little more
complicated that what we describe here.
Some example say statements are:
<example>
"I was walking down the street one day, when I came across the postman."
me "Hey, any mail for me today?"
"Postman" "Yeah, a package came for you. But there's no return address."
</example>
Here, we assume that 'me' is an expression that expands to the name of
the main character.
Menu Statement:
<rule name="statement">
<alt>"menu" name? ":" menu_block</alt>
</rule>
<rule name="menu_item">
<alt>string</alt>
<alt>string ( "if" python_expression )? ":" block</alt>
<alt>"set" simple_expression</alt>
</rule>
The menu statement displays a menu to the user, waits for the user to
provide a response, and then runs a block of code corresponding to the
choice that the user made. In a visual novel game, menu statement are
the main way in which the user can interact with the story.
Menu statements begin with the word "menu". This word can be followed
by an optional name. If the name is provided, it's as if the menu
statement was proceded by a label statement with that name. A menu
statement must have a block associated with it, and each of the
logical lines in this menu_block are parsed as menu_items.
There are three kinds of menu_items. The first is a logical line
containing only a string. These menu_items are used to provide blocks
of text in the menu that are not selectable. For example, they can be
use to provide a prompt to the user.
The second kind of menu_item is a string, followed by an optional if
clause, followed by a colon. This menu_item has a block of statements
associated with it. It's used to indicate a choice on the menu. If the
if clause is supplied, the choice is only presented to the user if the
python_expression is true. If a choice is selected by the user, the
statements in the block associated with the choice are executed before
control continues after the menu statement.
The final menu_item is the word "set" followed by a
simple_expression. The expression is evaluated to get a set of menu
items to supress. This set is used to filter the menu choices. If a
choice string is in the set, then the corresponding menu choice is not
displayed to the user. If a set is defined, then when a choice has
been made, the corresponding choice string is added to the set. This
provides an easy way of having a menu where the user can select each
item at most once.
Here's an example of a fairly complex menu, that demonstrates all
these features.
<example>
menu what_to_do:
set what_to_do_set
"What should we do today?"
"Go to the movies.":
"We went to the movies."
"Go shopping.":
"We went shopping, and the girls both bought swimsuits."
$ have_swimsuits = True
"Go to the beach." if have_swimsuits:
"We went to the beach together."
</example>
The actual task of displaying a menu is implemented internally by a
call to the menu python function.
Graphics Statements:
Before we can discuss the graphics statements, we must first discuss
the graphics model that Ren'Py uses. This will be covered in greater
detail in the library reference, but we want to cover the fundamentals
here to allow the graphics statements to be put in proper context.
First, let me define what it means to display a scene. The execution
of a Ren'Py script can be roughly divided into periods when the script
is executing code, and periods when the script is blocked wating for
user input (as is the case when a menu or say statement
executes). When Ren'Py is waiting for input, it is displaying a
scene. When it gets the input it's waiting for and execution
continues, we say it's finished displaying the scene.
The display in Ren'Py is controlled by three scene lists. These scene
lists are called the master scene list, the overlay scene list, and
the transient scene list.
The only scene list that is displayed to the user is the transient
scene list. This list is ordered such that items that are at the end
of the scene list are closest to the user. All of the items in the
scene lists must be displayable--- capable of drawing themselves to
the screen. See the library reference for the exact API displayable
objects must implement.
When a scene is displayed, the transient scene list is extended by
appending the overlay scene list to it. When display finishes, the
transient scene list is replaced with a copy of the master scene
list. The scene, show, and hide statements work by modifying both the
master and transient scene lists.
Having three scene lists may seem like needless complexity, but it's
useful in implementing transitions and other effects. When we want to
fade in an image, we add that image to the master scene list, and that
image wrapped in an object that handles the fade effect into the
transient scene list. When the scene is then displayed, the image will
fade it. The wrapped image on the transient list is then replaced
with the image from master list, removing any overhead the fade effect
can entail.
The transient list also helps when displaying UI elements, like
dialogue or menus. Finally, the overlay list is used to display things
that should always be presented to the user, like load and save
buttons.
+163
View File
@@ -0,0 +1,163 @@
#!/usr/bin/python
import os
import re
import sys
import time
import inspect
sys.path.append('..')
sys.path.append('../module')
import renpy
renpy.import_all()
keywords = [
r'\bimage\b',
r'\bscene\b',
r'\bshow\b',
r'\bhide\b',
r'\binit\b',
r'\$',
r'\blabel\b',
r'\bmenu\b',
r'\bset\b',
r'\bif\b',
r'\bwhile\b',
r'\bjump\b',
r'\blabel\b',
r'\bcall\b',
r'\breturn\b',
r'\bfrom\b',
r'\belif\b',
r'\belse\b',
r'\bpass\b',
r'\bwith\b',
r'\bat\b',
r'\bpython\b',
]
kwre = '|'.join(keywords)
def example(m):
s = m.group(1)
rv = ""
pos = 0
while pos < len(s):
m = re.compile(r'(?s)"(([^"]|\\.)*)"').match(s, pos)
if m:
rv += '"<span class="string">%s</span>"' % m.group(1)
pos = m.end()
continue
m = re.compile(r"(?s)'(([^']|\\.)*)'").match(s, pos)
if m:
rv += '\'<span class="string">%s</span>\'' % m.group(1)
pos = m.end()
continue
m = re.compile(r"(?s)(#[^\n]+)").match(s, pos)
if m:
rv += '<span class="comment">%s</span>' % m.group(1)
pos = m.end()
continue
m = re.compile(kwre).match(s, pos)
if m:
rv += '<span class="keyword">%s</span>' % m.group(0)
pos = m.end()
continue
rv += s[pos]
pos += 1
return "<example>" + rv + "</example>"
def function(m):
name = m.group(1)
store = vars(renpy.store)
renpy.store.renpy = renpy.exports
func = eval(name, store)
if isinstance(func, renpy.curry.Curry):
if func.callable == renpy.curry.Curry:
func = func.args[0]
else:
func = func.callable
doc = func.__doc__
if inspect.isclass(func):
func = func.__init__
if func.__doc__:
doc += "\n" + func.__doc__
a, b, c, d = inspect.getargspec(func)
args = inspect.formatargspec(a[1:], b, c, d)
else:
args = inspect.formatargspec(*inspect.getargspec(func))
args = re.sub(r"'\\x00\\x01.*?\\xff'", "im.ramp(0, 255)", args)
args = re.sub(r'<.*?>', '...', args)
docparas = []
for p in re.split(r'\n\s*\n', doc):
p = p.strip()
p = re.sub(r"\@param (\w+):", r'<param>\1</param> -', p)
p = "<p>" + p + "</p>"
docparas.append(p)
doc = '\n'.join(docparas)
return '<function name="%(name)s" sig="%(args)s">%(doc)s</function>' % locals()
def include(m):
f = file(m.group(1))
rv = f.read()
f.close()
return rv
class ret_none(object):
def __getattr__(self, k):
return None
def main():
f = file(sys.argv[1])
s = f.read()
f.close()
os.chdir("..")
try:
renpy.game.options = ret_none()
renpy.main.main("dump_styles")
except "foo":
pass
os.chdir("doc")
s = re.sub(r"<!-- func (\S+) -->", function, s)
s = re.sub(r"<!-- include (\S+) -->", include, s)
s = re.sub(r"<!-- date -->", time.strftime("%04Y-%02m-%02d %02H:%02M"), s)
s = re.sub(r"(?s)<example>(.*?)</example>", example, s)
print s
if __name__ == "__main__":
main()
+4442
View File
File diff suppressed because it is too large Load Diff
+81
View File
@@ -0,0 +1,81 @@
BODY {
font-family: sans-serif;
}
H1 {
text-align: center;
margin-top: 2em;
margin-bottom: 2em;
}
H2 {
text-align: center;
margin-top: 1em;
margin-bottom: 1em;
}
PRE.example {
border: 2px black solid;
margin-left: 10%;
margin-right: 10%;
background: #f0f0f0;
padding: 1em;
padding-bottom: 0em;
}
DIV.rule {
border: 2px black solid;
margin-left: 10%;
margin-right: 10%;
margin-bottom: 1em;
background: #f0f0ff;
padding: 1em;
}
SPAN.comment {
color: #800000;
}
SPAN.string {
color: #006000;
}
SPAN.keyword {
color: #804000;
}
TD.funcname {
font-family: monospace;
font-weight: bold;
}
TD.funcsig {
font-family: monospace;
}
DIV.funcbody {
margin-left: 5%;
margin-bottom: 1em;
}
SPAN.param {
font-style: italic;
}
P.prop {
margin-left: 5%;
}
SPAN.propname {
font-family: monospace;
font-weight: bold;
}
DT {
margin-top: 1em;
}
DT.code {
font-family: monospace;
}
+189
View File
@@ -0,0 +1,189 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- First, copy the element. -->
<xsl:template match="*" priority="-1">
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<!-- Now, handle some elements specially. -->
<xsl:template match="doc">
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css" />
<title><xsl:value-of select="title" /></title>
</head>
<body>
<xsl:apply-templates />
</body>
</html>
</xsl:template>
<xsl:template match="toc">
<ol>
<xsl:for-each select="../h3">
<li>
<a>
<xsl:attribute name="href">#<xsl:value-of select="." /></xsl:attribute>
<xsl:value-of select="."/>
</a>
</li>
</xsl:for-each>
</ol>
</xsl:template>
<xsl:template match="funcindex">
<ul>
<xsl:for-each select="//function">
<xsl:sort select="@name" />
<li>
<a>
<xsl:attribute name="href">#<xsl:value-of select="@name" /></xsl:attribute>
<xsl:value-of select="@name"/>
</a>
</li>
</xsl:for-each>
</ul>
</xsl:template>
<xsl:template match="defnindex">
<ul>
<xsl:for-each select="//defn">
<xsl:sort select="@name" />
<li>
<a>
<xsl:attribute name="href">#<xsl:value-of select="@name" /></xsl:attribute>
<xsl:value-of select="@name"/>
(<xsl:value-of select="@type"/>)
</a>
</li>
</xsl:for-each>
</ul>
</xsl:template>
<xsl:template match="varindex">
<ul>
<xsl:for-each select="//var">
<xsl:sort select="@name" />
<li>
<a>
<xsl:attribute name="href">#<xsl:value-of select="@name" /></xsl:attribute>
<xsl:value-of select="@name"/>
</a>
</li>
</xsl:for-each>
</ul>
</xsl:template>
<xsl:template match="styleindex">
<ul>
<xsl:for-each select="//renpy_style">
<xsl:sort select="@name" />
<li>
<a>
<xsl:attribute name="href">#<xsl:value-of select="@name" /></xsl:attribute>
<xsl:value-of select="@name"/>
</a>
</li>
</xsl:for-each>
</ul>
</xsl:template>
<xsl:template match="propindex">
<ul>
<xsl:for-each select="//prop">
<xsl:sort select="@name" />
<li>
<a>
<xsl:attribute name="href">#<xsl:value-of select="@name" /></xsl:attribute>
<xsl:value-of select="@name"/>
</a>
</li>
</xsl:for-each>
</ul>
</xsl:template>
<xsl:template match="h3">
<a>
<xsl:attribute name="name"><xsl:value-of select="." /></xsl:attribute>
<h3><xsl:apply-templates /></h3>
</a>
</xsl:template>
<xsl:template match="title">
<h1><xsl:apply-templates /></h1>
</xsl:template>
<xsl:template match="subtitle">
<h2><xsl:apply-templates /></h2>
</xsl:template>
<xsl:template match="def">
<b><i><xsl:apply-templates /></i></b>
</xsl:template>
<xsl:template match="example">
<pre class="example"><xsl:apply-templates /></pre>
</xsl:template>
<xsl:template match="rule">
<div class="rule"><xsl:apply-templates /></div>
</xsl:template>
<xsl:template match="function">
<a><xsl:attribute name="name"><xsl:value-of select="@name" /></xsl:attribute></a>
<table>
<tr>
<td valign="top" class="funcname"><xsl:value-of select="@name" /></td>
<td class="funcsig"><xsl:value-of select="@sig" />:</td>
</tr>
</table>
<div class="funcbody">
<xsl:apply-templates />
</div>
</xsl:template>
<xsl:template match="param">
<span class="param"><xsl:apply-templates /></span>
</xsl:template>
<xsl:template match="prop">
<a><xsl:attribute name="name"><xsl:value-of select="@name" /></xsl:attribute></a>
<p class="prop">
<span class="propname"><xsl:value-of select="@name" /></span>
--- <xsl:apply-templates />
</p>
</xsl:template>
<xsl:template match="renpy_style">
<a><xsl:attribute name="name"><xsl:value-of select="@name" /></xsl:attribute></a>
<dt><b><xsl:value-of select="@name" /></b>:</dt>
<dd><xsl:apply-templates /></dd>
</xsl:template>
<xsl:template match="renpy_style_inherits">
(inherits from <b><xsl:apply-templates /></b>) <br />
</xsl:template>
<xsl:template match="var">
<a><xsl:attribute name="name"><xsl:value-of select="@name" /></xsl:attribute></a>
<dt class="var"><b><xsl:value-of select="@name" /></b> = <xsl:value-of select="@value" /></dt>
<dd>
<xsl:apply-templates />
</dd>
</xsl:template>
<xsl:template match="defn">
<a><xsl:attribute name="name"><xsl:value-of select="@name" /></xsl:attribute></a>
<dt class="var"><b><xsl:value-of select="@name" /></b></dt>
<dd>
<xsl:apply-templates />
</dd>
</xsl:template>
</xsl:stylesheet>
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

+9
View File
@@ -0,0 +1,9 @@
init:
image black = Solid((0, 0, 0, 255))
label main_menu:
$ renpy.renpy.style.write_docs("doc/styles.xml")
$ renpy.renpy.style.write_hierarchy("doc/style_heirarchy.xml")
$ raise "foo"
Executable
+76
View File
@@ -0,0 +1,76 @@
#!/usr/bin/env python
# This program dumps all the text found in the script to the file text.txt.
# If on windows, it also tries to show text.txt to the user.
import codecs
import sys
import os
import re
import glob
import renpy
def process_block(block, out):
for fn, ln, text, child in block:
if text.startswith("$") or text.startswith("python"):
continue
if text.startswith("init"):
continue
if text.startswith("if") or text.startswith("while"):
process_block(child, out)
continue
for m in re.finditer(r'"((?:[^\\"]+|\\.)+)"|' +
r"'((?:[^\\']+|\\.)+)'", text):
s = m.group(1) or m.group(2)
s = re.sub(r'\s+', ' ', s)
s = re.sub(r'\\.', ' ', s)
s = re.sub(r'\{.*?\}', '', s)
print >>out, s.encode('utf-8')
print >>out
process_block(child, out)
def process(fn, out):
block = renpy.parser.group_logical_lines(renpy.parser.list_logical_lines(fn))
process_block(block, out)
def main():
pattern = "game/*.rpy"
if len(sys.argv) >= 2:
pattern = sys.argv[1]
files = glob.glob(pattern)
files = [ i for i in files if not i.startswith("common/") ]
out = file("text.txt", "w")
out.write(codecs.BOM_UTF8)
for fn in files:
process(fn, out)
out.close()
try:
os.startfile('text.txt')
except:
pass
if __name__ == "__main__":
main()
+1
View File
@@ -0,0 +1 @@
../../extras/fullscreen.rpy
+1
View File
@@ -0,0 +1 @@
../../extras/kanamode.rpy
+1
View File
@@ -0,0 +1 @@
../script.rpy
+102
View File
@@ -0,0 +1,102 @@
init -10:
$ config.searchpath.append('moonlight')
# Set up the size of the screen, and the window title.
$ config.screen_width = 800
$ config.screen_height = 600
$ config.window_title = "A Ren'Py Extras Game"
# These are positions that can be used inside at clauses. We set
# them up here so that they can be used throughout the program.
$ left = Position(xpos=0.0, xanchor='left')
$ right = Position(xpos=1.0, xanchor='right')
$ center = Position()
# Likewise, we set up some transitions that we can use in with
# clauses and statements.
$ fade = Fade(.5, 0, .5) # Fade to black and back.
$ dissolve = Dissolve(0.5)
$ wiperight = CropMove(1.0, "wiperight")
$ wipeleft = CropMove(1.0, "wipeleft")
$ wipeup = CropMove(1.0, "wipeup")
$ wipedown = CropMove(1.0, "wipedown")
$ slideright = CropMove(1.0, "slideright")
$ slideleft = CropMove(1.0, "slideleft")
$ slideup = CropMove(1.0, "slideup")
$ slidedown = CropMove(1.0, "slidedown")
$ slideawayright = CropMove(1.0, "slideawayright")
$ slideawayleft = CropMove(1.0, "slideawayleft")
$ slideawayup = CropMove(1.0, "slideawayup")
$ slideawaydown = CropMove(1.0, "slideawaydown")
$ irisout = CropMove(1.0, "irisout")
$ irisin = CropMove(1.0, "irisin")
# Now, we declare the images that are used in the program.
# Images.
image black = Solid((0, 0, 0, 255))
image white = Solid((255, 255, 255, 255))
image yellow = Solid((255, 255, 200, 255))
# Opening Sequence.
image bigbeach1 = Image("bigbeach1.jpg")
image presents = Image("presents.png")
# Backgrounds.
image beach1 = Image("beach1b.jpg")
image beach1 mary = Image("beach1c.jpg")
image beach1 title = Image("beach1a.jpg")
image beach2 = Image("beach2.jpg")
image beach3 = Image("beach3.jpg")
image dawn1 = Image("dawn1.jpg")
image dawn2 = Image("dawn2.jpg")
image library = Image("library.jpg")
# Ending 1.
image transfer = Image("transfer.png")
image moonpic = Image("moonpic.jpg")
image nogirlpic = Image("nogirlpic.jpg")
# Ending 3.
image littlemary = Image("littlemary.jpg")
# Ending 4.
image hospital1 = Image("hospital1.jpg")
image hospital2 = Image("hospital2.jpg")
image hospital3 = Image("hospital3.jpg")
image heaven = Image("heaven.jpg")
# Endings Common
image good_ending = Image("ending.jpg")
image bad_ending = Image("badending.jpg")
# Mary.
image mary dark confused smiling = Image("mary_dark_confused_smiling.png")
image mary dark confused wistful = Image("mary_dark_confused_wistful.png")
image mary dark crying = Image("mary_dark_crying.png")
image mary dark laughing = Image("mary_dark_laughing.png")
image mary dark sad = Image("mary_dark_sad.png")
image mary dark smiling = Image("mary_dark_smiling.png")
image mary dark vhappy = Image("mary_dark_vhappy.png")
image mary dark wistful = Image("mary_dark_wistful.png")
image mary dawn confused smiling = Image("mary_dawn_confused_smiling.png")
image mary dawn confused wistful = Image("mary_dawn_confused_wistful.png")
image mary dawn crying = Image("mary_dawn_crying.png")
image mary dawn laughing = Image("mary_dawn_laughing.png")
image mary dawn sad = Image("mary_dawn_sad.png")
image mary dawn smiling = Image("mary_dawn_smiling.png")
image mary dawn vhappy = Image("mary_dawn_vhappy.png")
image mary dawn wistful = Image("mary_dawn_wistful.png")
label start:
jump example
+16
View File
@@ -0,0 +1,16 @@
# This file contains a minimal set of style changes needed to have
# Ren'Py work with a game that's 640x480 in size.
init 1:
# Change the screen width.
$ config.screen_width = 640
$ config.screen_height = 480
# Font sizes.
$ style.default.size = 20
$ style.button_text.size = 20
$ style.file_picker_text.size = 14
# Change the size of the thumbnails in the file picker.
$ library.thumbnail_width = 60
$ library.thumbnail_height = 45
+35
View File
@@ -0,0 +1,35 @@
# This file adds a number of buttons to the lower-right hand corner of
# the screen. Three of these buttons jump to the game menu, which
# giving quick access to Load, Save, and Prefs. The fourth button
# toggles skipping, to make that more convenient.
init:
# Give us some space on the right side of the screen.
$ style.window.right_margin = 100
python:
def toggle_skipping():
config.skipping = not config.skipping
def button_game_menu():
# to save typing
ccinc = renpy.curried_call_in_new_context
ui.vbox(xpos=0.98, ypos=0.98, xanchor='right', yanchor='bottom')
ui.textbutton("Skip", clicked=toggle_skipping)
ui.textbutton("Save", clicked=ccinc("_game_menu_save"))
ui.textbutton("Load", clicked=ccinc("_game_menu_load"))
ui.textbutton("Prefs", clicked=ccinc("_game_menu_preferences"))
ui.close()
config.overlay_functions.append(button_game_menu)
+63
View File
@@ -0,0 +1,63 @@
# In this file, we have an example of replacing the default menu with
# a custom one. This new menu consists of a series of centered
# buttons, with dialogue appearing in a narration window.
# You can try this one out by dropping it right into the game
# directory.
# The code that implements button menus.
init:
python:
style.create('menu_button', 'button')
style.create('menu_button_text', 'button_text')
def menu(menuitems):
narration = None
ui.keymousebehavior()
ui.window(style='menu_window')
ui.vbox(xanchor='center', xpos=0.5)
for label, value in menuitems:
if value is None:
narration = label
continue
ui.textbutton(label,
style="menu_button",
text_style="menu_button_text",
clicked=ui.returns(value))
ui.close()
if narration:
narrator(narration, interact=False)
rv = ui.interact()
renpy.checkpoint()
return rv
# Styles to make button menus look good.
init 1:
python hide:
style.menu_window.background = None
style.menu_window.yminimum = 0
style.menu_window.ypos = 0.40
style.menu_window.yanchor = 'center'
style.menu_window.xfill = True
style.menu_button.background = Solid((0, 0, 255, 128))
style.menu_button.xfill = True
style.menu_button.top_padding = 5
style.menu_button.bottom_margin = 5
style.menu_button_text.xpos = 0.5
style.menu_button_text.xanchor = 'center'
style.menu_button_text.hover_color = (255, 255, 0, 255)
style.menu_button_text.idle_color = (255, 255, 255, 255)
+62
View File
@@ -0,0 +1,62 @@
# This file contains code to do chinese word-wrapping. It's based
# on what I gathered from the information found at:
#
# http://lemmasoft.renai.us/forums/viewtopic.php?p=9282#9282
init:
# You'll probably want to replace this with whatever you consider
# to be punctuation. I've used unicode escapes for many of the
# fullwidth characters, as I don't know how to type them otherwise.
$ chinese_punctuation = u";,.?\uff1b\uff1a\uff0c\u3002\u3001\uff1f\uff01"
python hide:
def text_tokenizer(s, style):
"""
This functions is used to tokenize text. It's called when laying
out a Text widget, and is given the string that is the text of the
widget, and the style associated with the widget.
It's expected to yield some number of pairs. In each pair, the
first element is the kind of token found, and the second element
is the text corresponding to that token. The following token
types are defined:
"newline" -- A newline, which when encountered starts a new line.
"word" -- A word of text. A line will never be broken inside of
a word.
"space" -- A space. Spaces are always placed on the current line,
and will never be placed as the start of a line.
"tag" -- A text tag. If encountered, the second element should be
the name of the tag, without any enclosing braces.
"""
regexp = r"""(?x)
(?P<space>\ )
| \{(?P<tag>[^{}]+)\}
| (?P<untag>\{\{)
| (?P<newline>\n)
| (?P<word>[^ \n\{][%s]*)
""" % chinese_punctuation
import re
for m in re.finditer(regexp, s):
if m.group('space'):
yield 'space', m.group('space')
elif m.group('word'):
yield 'word', m.group('word')
elif m.group('tag'):
yield 'tag', m.group('tag')
elif m.group('untag'):
yield 'word', '{'
elif m.group('newline'):
yield 'newline', m.group('newline')
config.text_tokenizer = text_tokenizer
+40
View File
@@ -0,0 +1,40 @@
# This function implements a commentary track, which is a special kind of
# say statement that only displays if commentary is set to on in the
# new preference that this mode creates. Making this unlockable is easy,
# but is left as an exercise for the reader.
#
# Use it by putting in lines like:
#
# commentary "Hey! This is commentary!"
init -10:
python:
# The style for the commentary window.
style.create('commentary_window', 'window', 'The commentary window.')
style.commentary_window.background = Solid((0, 0, 0, 192))
style.commentary_window.ypos = 0.0
style.commentary_window.yanchor = 'top'
# Ensure that the commentary attribute exists.
if persistent.commentary is None:
persistent.commentary = False
commentary = Character(None, window_style='commentary_window',
condition = 'persistent.commentary')
python hide:
cp = _Preference('Commentary', 'commentary', [
('Enabled', True, 'True'),
('Disabled', False, 'True')
], base=persistent)
library.preferences['prefs_right'].append(cp)
+83
View File
@@ -0,0 +1,83 @@
# This file contains code to do east asian word-wrapping. It's based
# on what I gathered from the information found at:
#
# http://lemmasoft.renai.us/forums/viewtopic.php?p=9282#9282
#
# It was then further enhanced with the information found at:
#
# http://zoonek.free.fr/LaTeX/Omega-Japanese/doc.html
#
# I'd expect it to do a decent job with Chinese and Japanese, but
# I have no idea how it does with Korean. If someone wants to clue
# me in, I'd be happy to hear more about it.
init:
python hide:
# These are characters for which line breaking is forbidden before them.
# In our algorithm, they try to cling to the back of a word.
not_before = ur'\!\"\%\)\,\-\.\:\;\?\]\}\u2010\u2019\u201d\u2030\u2032\u2033\u2103\u2212\u3001\u3002\u3005\u3009\u300b\u300d\u300f\u3011\u3015\u3017\u3041\u3043\u3045\u3047\u3049\u3063\u3083\u3085\u3087\u308e\u309b\u309c\u309d\u309e\u30a1\u30a3\u30a5\u30a7\u30a9\u30c3\u30e3\u30e5\u30e7\u30ee\u30f5\u30f6\u30fc\u30fd\u30fe\uff01\uff02\uff05\uff09\uff09\uff0c\uff0d\uff0e\uff1a\uff1b\uff1f\uff3d\uff5d\uff5d\uff61\uff63\uff9e\uff9f'
# These are characters for which line breaking is forbidden after them.
# In our algorithm, they try to cling to the front of a word.
not_after = ur'\"\#\$\(\@\[\{\xa2\xa3\xa5\xa7\u2018\u201c\u266f\u3008\u300a\u300c\u300e\u3010\u3012\u3014\u3016\uff03\uff04\uff08\uff08\uff20\uff3b\uff5b\uff5b\uff62\uffe0\uffe1\uffe5'
# These are ranges of characters that are treated as western. (And hence are always grouped
# together as a word.
western = ur'\'\w\u000a-\u0024f\uff10-\uff19\uff20-\uff2a\uff41-\uff5a'
regexp = ur"""(?x)
(?P<space>[ \u200b])
| \{(?P<tag>[^{}]+)\}
| (?P<untag>\{\{)
| (?P<newline>\n)
| (?P<word> [%(not_after)s]*
([^ \n\{\u200b%(not_before)s%(not_after)s%(western)s]|[%(western)s]+)
[%(not_before)s]*
)
""" % locals()
import re
store._cjk_regexp = re.compile(regexp)
def text_tokenizer(s, style):
"""
This functions is used to tokenize text. It's called when laying
out a Text widget, and is given the string that is the text of the
widget, and the style associated with the widget.
It's expected to yield some number of pairs. In each pair, the
first element is the kind of token found, and the second element
is the text corresponding to that token. The following token
types are defined:
"newline" -- A newline, which when encountered starts a new line.
"word" -- A word of text. A line will never be broken inside of
a word.
"space" -- A space. Spaces are always placed on the current line,
and will never be placed as the start of a line.
"tag" -- A text tag. If encountered, the second element should be
the name of the tag, without any enclosing braces.
"""
for m in store._cjk_regexp.finditer(s):
if m.group('space'):
yield 'space', m.group('space')
elif m.group('word'):
yield 'word', m.group('word')
elif m.group('tag'):
yield 'tag', m.group('tag')
elif m.group('untag'):
yield 'word', '{'
elif m.group('newline'):
yield 'newline', m.group('newline')
config.text_tokenizer = text_tokenizer
+23
View File
@@ -0,0 +1,23 @@
# This file contains code to automatically switch the game into
# fullscreen mode.
# Please note: Fullscreen mode is broken on some platforms (mostly
# virtual windows machines like vmware and virtual PC). So having
# this code automatically execute could make your game hard to use
# on those platforms.
#
# The way we work around this is to tell users of these platforms
# to press 'f' to toggle fullscreen mode. If the game's running in
# windowed mode, the problems don't seem to appear.
#
# You should probably put words to that effect in some sort of
# README file.
# The first time this code runs, the game switches into fullscreen.
# After that, it respects the user's preference.
init:
python:
if not persistent.set_fullscreen:
persistent.set_fullscreen = True
_preferences.fullscreen = True
+262
View File
@@ -0,0 +1,262 @@
# This extra implements an image gallery, complete with automatic
# unlocking of the images that have been shown to the user. The images
# are divided into pages, with a fixed number of images on each page.
# Right now, this is configured to used the images found in the demo.
# The images are repeated quite a bit, so that we can get four pages
# of them. You probably wouldn't do that if you were using this in a
# real game.
# To see this in action, drop it into the game directory of the
# demo.
# Configuration.
init:
python hide:
# The number of columns and rows of images to show in the
# gallery.
store.gallery_cols = 3
store.gallery_rows = 4
# The size that each image should be scaled to, and that
# thumbnails should be.
store.gallery_width = 160
store.gallery_height = 120
# The contents of each of the page. Each of these is a list of
# tuples with the first element of the tuple being the image
# filename and the second element being the name of the image
# that will unlock the image with this filename. (That is,
# the name that is used in show or scene statements, as a
# string.)
#
# When displaying an image as a thumbnail, this code first
# looks for the file thumbnail_<filename>. If that file
# exists, it should be a gallery_width x gallery_height
# thumbnail. Otherwise, a thumbnail is automatically
# generated, but it may screw up the aspect ratio of the
# image.
#
# You probably want to create thumbnails for most images, to
# limit memory consumption.
page1 = [
( "whitehouse.jpg", "whitehouse" ),
( "washington.jpg", "washington" ),
( "carillon.jpg", "carillon" ),
( "whitehouse.jpg", "whitehouse" ),
( "washington.jpg", "washington" ),
( "carillon.jpg", "carillon" ),
( "whitehouse.jpg", "whitehouse" ),
( "washington.jpg", "washington" ),
( "carillon.jpg", "carillon" ),
( "whitehouse.jpg", "whitehouse" ),
( "washington.jpg", "washington" ),
( "carillon.jpg", "carillon" ),
]
page2 = [
( "whitehouse.jpg", "whitehouse" ),
( "washington.jpg", "washington" ),
( "carillon.jpg", "carillon" ),
( "whitehouse.jpg", "whitehouse" ),
( "washington.jpg", "washington" ),
( "carillon.jpg", "carillon" ),
( "whitehouse.jpg", "whitehouse" ),
( "washington.jpg", "washington" ),
( "carillon.jpg", "carillon" ),
( "whitehouse.jpg", "whitehouse" ),
( "washington.jpg", "washington" ),
( "carillon.jpg", "carillon" ),
]
page3 = [
( "whitehouse.jpg", "whitehouse" ),
( "washington.jpg", "washington" ),
]
page4 = [
( "9a_happy.png", "eileen happy" ),
( "9a_vhappy.png", "eileen vhappy" ),
( "9a_concerned.png", "eileen concerned" ),
]
# This is the actual list of gallery pages. It's a list
# of tuples, with the first element being the name of the
# page, the second being the contents of the page (one of
# the lists created above), and the third image being the
# image used as the background of the page.
store.gallery_pages = [
("Backgrounds 1", page1, "washington.jpg"),
("Backgrounds 2", page2, "whitehouse.jpg"),
("Backgrounds 3", page3, "carillon.jpg"),
("Character Art", page4, "washington.jpg"),
]
# A window containing the gallery page buttons.
style.create('gallery_pages', 'default')
style.gallery_pages.xpos = 0.99
style.gallery_pages.xanchor='right'
style.gallery_pages.ypos = 0.02
style.gallery_pages.yanchor = 'top'
# A button that links to a gallery page.
style.create('gallery_page_button', 'button')
style.create('gallery_page_button_text', 'button_text')
# A button that returns us to from whence we came.
style.create('gallery_return_button', 'button')
style.create('gallery_return_button_text', 'button_text')
style.gallery_return_button.xpos = 0.99
style.gallery_return_button.xanchor='right'
style.gallery_return_button.ypos = 0.98
style.gallery_return_button.yanchor = 'bottom'
# The grid containing the gallery image buttons.
style.create('gallery_grid', 'default')
# The style of the buttons in the gallery.
style.create('gallery_button', 'default')
# Right now, the backgrounds are all solids, but in a more
# professional version, the insensitive background would
# probably be a placeholder image that indicates that a
# picture has yet to be unlocked.
style.gallery_button.insensitive_background = Solid((192, 192, 192, 255))
style.gallery_button.idle_background = Solid((255, 255, 255, 255))
style.gallery_button.hover_background = Solid((255, 255, 192, 255))
style.gallery_button.left_margin = 5
style.gallery_button.right_margin = 5
style.gallery_button.top_margin = 5
style.gallery_button.bottom_margin = 5
style.gallery_button.left_padding = 5
style.gallery_button.right_padding = 5
style.gallery_button.top_padding = 5
style.gallery_button.bottom_padding = 5
# The style of the images in the buttons in the gallery.
style.create('gallery_button_image', 'default')
# The style of the images that are being shown to the user.
style.create('gallery_image', 'image_placement')
# The transition used when switching gallery pages.
store.gallery_transition = Dissolve(0.5)
python:
# The function that actually manages the display of the image
# gallery.
def gallery():
page = 0
while True:
images = gallery_pages[page][1]
ui.image(gallery_pages[page][2])
# Show the names of the various gallery pages.
ui.window(style='gallery_pages')
ui.vbox(focus="gallery_pages")
for i in range(0, len(gallery_pages)):
if i == page:
clicked = None
else:
clicked = ui.returns(("page", i))
ui.textbutton(gallery_pages[i][0],
style='gallery_page_button',
text_style='gallery_page_button_text',
clicked=clicked)
ui.close()
# Show the return button.
ui.textbutton('Return',
style='gallery_return_button',
text_style='gallery_return_button_text',
clicked=ui.returns(("return", None)))
# Show the grid for this page.
ui.grid(gallery_cols, gallery_rows, style='gallery_grid')
# For each grid cell.
for i in range(0, gallery_cols * gallery_rows):
# Fill empty space with nulls.
if i >= len(images):
ui.null()
continue
# Otherwise, get the filename and spec and see if
# we've unlocked it.
filename, spec = images[i]
if spec:
spec = spec.split()
if spec and tuple(spec) not in persistent._seen_images:
filename = None
clicked = None
else:
clicked = ui.returns(('show', filename))
# Create the button, containing the appropriate
# image or a null if we haven't unlocked it yet.
ui.button(style='gallery_button', clicked=clicked)
if not filename:
ui.null(width=gallery_width, height=gallery_height)
else:
if renpy.loadable("thumbnail_" + filename):
ui.image("thumbnail_" + filename,
style="gallery_button_image")
else:
ui.add(im.Scale(filename,
gallery_width,
gallery_height))
ui.close()
# Interact with the user.
renpy.transition(gallery_transition)
cmd, arg = ui.interact(suppress_overlay=True, suppress_underlay=True)
# Process the user's commands.
if cmd == "show":
ui.add(Solid((0, 0, 0, 255)))
ui.image(arg)
ui.saybehavior()
renpy.transition(gallery_transition)
ui.interact(suppress_overlay=True, suppress_underlay=True)
if cmd == "page":
page = arg
if cmd == "return":
renpy.transition(gallery_transition)
return
library.main_menu.insert(2, ("CG Gallery", ui.jumps("gallery"), 'True'))
label gallery:
$ gallery()
jump _main_menu
+204
View File
@@ -0,0 +1,204 @@
# This is an implementation of Kana mode, a mode in which multiple
# lines of dialogue are shown at once, in a fullscreen window. A
# single line of dialogue is placed onto the screen for each mouse
# click. Calling the clear function clears the screen, ensuring that
# the next line will appear at the top of the sceen.
#
# An example of using Kana mode follows the code that implements it.
# This init block contains all of the code needed to implement
# Kana mode. You probably don't want to change this... unless you
# do. But all of the customization is found below.
init -100:
python:
# This is a list of KanaCharacter, what tuples.
kana_display_list = [ ]
# Spacings used.
kana_vspacing = 0
kana_hspacing = 0
def clear(arg=None):
global kana_display_list
kana_display_list = [ ]
def kana_show():
if not kana_display_list:
return
ui.window(style='say_window')
ui.vbox(kana_vspacing)
for i, (char, what) in enumerate(kana_display_list):
text = char.show(what, i == len(kana_display_list) - 1)
ui.close()
# Magic to support auto-forward mode.
b = ui.saybehavior()
b.set_afm_length(text.get_simple_length())
ui.interact()
renpy.checkpoint()
# Characters and the narrator should be instances of this
# object.
class KanaCharacter(object):
def __init__(self, who,
what_prefix='"',
what_suffix='"',
who_style='say_label',
what_style='say_dialogue',
**properties):
self.who = who
self.what_prefix = what_prefix
self.what_suffix = what_suffix
self.who_style = who_style
self.what_style = what_style
self.properties = properties
def __call__(self, what):
kana_display_list.append((self, what))
kana_show()
def show(self, what, slow):
ui.hbox(kana_hspacing)
ui.text(self.who, style=self.who_style,
**self.properties)
rv = ui.text(self.what_prefix + what + self.what_suffix,
style=self.what_style, slow=slow)
ui.close()
return rv
# This section updates the styles that are used by the Kana mode stuff
# so that they work well with Kana mode. The user may want to change
# these so that they look more appropriate.
init:
# The space between lines of dialogue.
$ kana_vspacing = 10
$ kana_hspacing = 10
$ style.say_window.background = Solid((0, 0, 0, 96))
$ style.say_window.xfill = True
$ style.say_window.yfill = True
$ style.say_window.xmargin = 0
$ style.say_window.ymargin = 0
$ style.say_window.xpadding = 20
$ style.say_window.ypadding = 20
$ style.say_label.minwidth = 100
$ style.say_label.textalign = 1.0
# This just makes it look nicer.
$ style.say_dialogue.rest_indent = 9
# Adjust the menu to match.
$ style.menu_window.background = Solid((0, 0, 0, 96))
$ style.menu_window.xfill = True
$ style.menu_window.yfill = True
$ style.menu_window.xmargin = 0
$ style.menu_window.ymargin = 0
$ style.menu_window.xpadding = 20
$ style.menu_window.ypadding = 20
$ style.menu.xpos = 110
# And now, the example. This example can't be simply run, but instead
# should serve as a guide to how to get Kana mode working in your own
# game.
# In the init block, declare the characters as KanaCharacters. We also
# want to declare the narrator as a special KanaCharacter.
init:
$ p = KanaCharacter("")
$ g = KanaCharacter("Girl:", color=(255, 128, 128, 255))
$ narrator = KanaCharacter("",
what_prefix='',
what_suffix='',
what_style='say_thought')
# Now, the actual script of the example. (An excerpt from Moonlight
# Walks.) Notice how we place calls to clear in places where the
# we want the screen to be cleared.
# This text is here to serve as an example, and shouldn't be used
# in your game.
label example:
show beach2
show mary dark wistful
$ clear()
p "What can you tell me about your parents?"
g "Papa and Mama both came across the ocean as settlers when they
were just children."
g "Papa fought in the war. When it was over, he married Mama, and
they used his pension to move here from the mainland, and to
build us a house."
g "Together, they farmed the land, and eventually they had
children."
g "I had an older sister and a younger sister. I was the middle
child."
$ clear()
show mary dark sad
"She paused for a second to collect her thoughts before
continuing. This part was taking a strain on her."
g "When I was ten, an epidemic hit the island."
g "We came down with it, and so did all of the other families."
g "My family was too sick to move, but our neighbors, the Millers,
sent some of their boys to get help from the mainland."
"I remember thinking that Miller was the last name of my aunt and
uncle, and wondering if they could be related to me."
g "I don't know what happened to them, but I never heard from them
again."
show mary dark crying
g "It lasted a week, and then it was over. My sisters... my
parents... they all..."
g "Now I'm the only one left."
$ clear()
p "I'm sorry."
"I didn't know what else to say to a girl that had lost her
family, and was obviously broken up about it."
show mary dark sad
"She nodded in response, wiped her tears, and we once again
started walking in silence."
menu menu_1:
"Show me the example again.":
jump example
"I'm done. Let me go.":
return
+27
View File
@@ -0,0 +1,27 @@
# This file gives an example of how the various entries on the main
# and game menus can be repositioned on the screen. Unlike the other
# extras, we don't intend this to be used as-is, but instead to be
# copied and changed to change the positions of buttons on the screen.
# Buttons should not overlap, and certain configurations may make
# buttons inaccessible with keyboard navigation.
init:
python hide:
library.main_menu_positions = {
'Start Game' : dict(xpos=400, ypos=400, xanchor='left', yanchor='top'),
'Continue Game' : dict(xpos=450, ypos=430, xanchor='left', yanchor='top'),
'Preferences' : dict(xpos=500, ypos=460, xanchor='left', yanchor='top'),
'Quit Game' : dict(xpos=550, ypos=490, xanchor='left', yanchor='top'),
}
library.game_menu_positions = {
'Return' : dict(xpos=400, ypos=400, xanchor='left', yanchor='top'),
'Preferences' : dict(xpos=450, ypos=430, xanchor='left', yanchor='top'),
'Save Game' : dict(xpos=500, ypos=460, xanchor='left', yanchor='top'),
'Load Game' : dict(xpos=550, ypos=490, xanchor='left', yanchor='top'),
'Main Menu' : dict(xpos=600, ypos=520, xanchor='left', yanchor='top'),
'Quit' : dict(xpos=650, ypos=550, xanchor='left', yanchor='top'),
}
+87
View File
@@ -0,0 +1,87 @@
# This file replaces most of the game menu navigation with overlay
# buttons that jump directly to various parts of the game menu.
# Right clicking hides and shows the buttons, rather than calling
# up the game menu directly.
init:
python hide:
# overlay_menu is an object storing information about the
# overlay menu state.
store.overlay_menu = object()
overlay_menu.shown = False
# overlay_menu is also a new layer, containing the overlay
# menu.
config.layers.append("overlay_menu")
config.overlay_layers.append("overlay_menu")
# This function actually draws the overlay menu.
def overlay_menu_func():
if overlay_menu.shown:
ui.layer("overlay_menu")
ui.vbox(xpos=1.0, xanchor="right", ypos=0.75, yanchor="bottom")
def button(label, target):
ui.textbutton(label, clicked=renpy.curried_call_in_new_context(target))
button("Load Game", "_game_menu_load")
button("Save Game", "_game_menu_save")
button("Preferences", "_game_menu_preferences")
ui.close()
ui.close()
config.overlay_functions.append(overlay_menu_func)
# This function toggles the visibility of the overlay menu.
def overlay_menu_toggle():
shown = not overlay_menu.shown
overlay_menu.shown = shown
# How long should the transitions take?
trans_delay = 0.5
# These transitions assume that the menu is placed on the
# right side of the screen. This indicator gives the
# fraction of the screen that participates in transitions.
trans_frac = 0.75
if shown:
trans = CropMove(trans_delay,
"custom",
startcrop=(trans_frac, 0.0, 0.0, 1.0),
startpos=(1.0, 0.0),
endcrop=(trans_frac, 0.0, 1.0-trans_frac, 1.0),
endpos=(trans_frac, 0.0),
topnew=True)
renpy.transition(trans, 'overlay_menu')
else:
trans = CropMove(trans_delay,
"custom",
endcrop=(trans_frac, 0.0, 0.0, 1.0),
endpos=(1.0, 0.0),
startcrop=(trans_frac, 0.0, 1.0-trans_frac, 1.0),
startpos=(trans_frac, 0.0),
topnew=False)
renpy.transition(trans, 'overlay_menu')
renpy.restart_interaction()
# Add a new underlay that handles the overlay menu toggle.
config.underlay.append(renpy.Keymap(game_menu = overlay_menu_toggle))
+47
View File
@@ -0,0 +1,47 @@
# This file implements quick save and load functionality. The
# quicksave functionality adds a button to the overlay that is
# displayed over the game. When the button is clicked, the game is
# saved in a special quicksave slot. It also adds a quick load button
# to the main menu. When that button is clicked, the quicksave game is
# loaded.
# This is called when the quick save button is clicked.
label _quick_save:
call _enter_menu_without_scene from __call__enter_menu_4
# Save the game.
$ renpy.save('quicksave', _('Quick Save'))
# Tell the user that we saved the game.
$ ui.add(Solid((0, 0, 0, 128)))
$ ui.text(_('The game has been saved using quick save.'),
xpos=0.5, xanchor='center', ypos=0.5, yanchor='center')
$ ui.saybehavior()
$ ui.interact(suppress_overlay=True, suppress_underlay=True)
return
# This is called when the quick load button is clicked, to load the
# game.
label _quick_load:
$ renpy.load('quicksave')
return
init -1:
python hide:
# Add the quick save button in as an overlay function.
def quick_save_button():
ui.textbutton(_("Quick Save"),
xpos=0.98, ypos=0.02,
xanchor='right', yanchor='top',
clicked=renpy.curried_call_in_new_context('_quick_save'))
config.overlay_functions.append(quick_save_button)
# Add the quick load function to the main menu.
library.main_menu.insert(1, ('Quick Load',
ui.jumps("_quick_load"),
'renpy.can_load("quicksave")'))
+229
View File
@@ -0,0 +1,229 @@
# This is the annoying readback mode. I implemented this because
# people asked for it, not because I like it. I'd prefer you use
# rollback, which is better in every way.
# To use readback, drop this file into your game directory. Readback
# will take over when rollback no longer works, so you'll also need to
# either reduce config.hard_rollback_limit or set
# config.rollback_enabled to false.
init -100:
$ config.hard_rollback_limit = 1
# Readback works by replacing the default Character and Menu objects
# with ones that record what is said in a readback buffer. The user
# can then go back, and what has been said will be shown to them
# again. Images and the like will not change... if you want that, use
# rollback. Heck, use rollback anyway. :-P
# The number of lines of readback can be changed by assigning an
# integer to the readback_limit variable. But leaving it None will
# leave the entire game in the buffer. As this is actually fairly
# memory-efficent, you should probably leave it as None.
# Readback uses two styles, readback_dialogue and
# readback_thought. Change them to change the color and look of
# read-back text.
# If you want to add your own message, as narration, to the readback
# buffer, you can do it by calling the readback function or having
# the readback character say it:
# $ readback('A message for readbackers only.')
# readback "A similar message."
# Note: When using Readback, you can no longer use a string for a
# character's name. All dialogue must be routed through Character
# objects, if it is to show up in the readback buffer. This limitation
# will be fixed in a future version of Ren'Py.
init -100:
python:
# The limit of the number of readbacks to keep. None means no limit.
readback_limit = None
# Set this to true to print out the contents of the readback
# buffer when it is saved.
readback_debug = False
# Readback styles.
style.create('readback_dialogue', 'say_dialogue', '')
style.create('readback_thought', 'say_thought', '')
style.readback_dialogue.color = (255, 128, 128, 255)
style.readback_thought.color = (255, 128, 128, 255)
# No user-servicable parts below this line. ######################
# The readback buffer is a doubly-linked list of readback
# objects.
class Readback(object):
def __init__(self, obj, args):
self.older = None
self.newer = None
self.obj = obj
self.args = args
def show(self):
self.obj.readback(*self.args)
readback_oldest = None
readback_newest = None
readback_count = 0
# This saves a readback entry to the readback buffer.
def readback_save(obj, *args):
store.readback_count += 1
if readback_limit and readback_count > readback_limit:
store.readback_count -= 1
readback_oldest.newer.older = None
store.readback_oldest = readback_oldest.newer
rb = Readback(obj, args)
if readback_newest:
readback_newest.newer = rb
else:
store.readback_oldest = rb
rb.older = readback_newest
store.readback_newest = rb
if readback_debug:
print "---- Readback Buffer ----"
rb = readback_oldest
while rb:
print rb.obj, rb.args
rb = rb.newer
# The rest of this file is replacing the default objects and
# functions with versions that save things in the readback
# buffer.
# Save the old character object.
readback_OldCharacter = Character
readback_oldmenu = menu
class Character(readback_OldCharacter):
def __init__(self, who,
readback_style='readback_dialogue',
**kwargs):
readback_OldCharacter.__init__(self, who, **kwargs)
self.readback_style = readback_style
def __call__(self, what, **kwargs):
if not self.check_condition():
return
readback_OldCharacter.__call__(self, what, **kwargs)
def store_readback(self, who, what):
readback_save(self, who, what)
def readback(self, who, what):
self.function(who, what,
who_style=self.who_style,
what_style=self.readback_style,
window_style=self.window_style,
interact=False,
all_at_once=True,
**self.properties)
class Sayer(object):
def __call__(self, who, what):
renpy.display_say(who, what)
readback_save(self, who, what)
def readback(self, who, what):
renpy.display_say(who, what,
what_style='readback_dialogue',
all_at_once=True,
interact=False)
narrator = Character(None, what_style='say_thought')
say = Sayer()
def readback(what):
narrator.store_readback(None, what)
def menu(menuitems):
rv = readback_oldmenu(menuitems)
text = '\n'.join([ l for l, v in menuitems
if v is None or v == rv ])
readback(text)
return rv
# This stuff is involved in entering the readback mode.
def readback_mode():
# Try rollback, first.
renpy.rollback()
# If we made it here, we're into readback mode. So let's
# go there now.
renpy.call_in_new_context("readback")
# Add in the readback function.
config.underlay.append(renpy.Keymap(rollback=readback_mode))
# This label is called in a new context, when the user succesfully
# enters Readback mode.
label readback:
# If we have an empty readback buffer, go home.
if not readback_newest:
return
python hide:
rb = readback_newest
while True:
rb.show()
ui.add(renpy.Keymap(rollback=lambda : "older",
rollforward=lambda : "newer",
dismiss=lambda : "dismiss",
))
res = ui.interact()
if res == "newer":
rb = rb.newer
if not rb:
break
elif res == "older":
if rb.older:
rb = rb.older
elif res == "dismiss":
break
return
+74
View File
@@ -0,0 +1,74 @@
# This extra demonstrates the two window say mode. In this mode, the
# character's name is placed in a different window than the line said
# by that character.
#
# You can use this by including this file in your game directory. You
# then need to change the definitions of Character and
# DynamicCharacter object to set function=two_window_say. For example:
#
# $ e = Character('Eileen', color=(200, 255, 200, 255),
# function=two_window_say)
#
# Once this is done, everything that is said by that character will be
# divided across two windows.
#
# You'll probably also want to customize the styles given below,
# especially by setting style.who_window.background to something
# a little more attractive.
init -100:
python:
style.create('two_window_say_position', 'default',
'(position) Used to get the position of the two windows in two window say mode.')
style.two_window_say_position.ypos = 1.0
style.two_window_say_position.yanchor = 'bottom'
style.create('who_window', 'default',
'(window) The style used for the window containing the who label when a Character uses the two_window_say function.')
style.who_window.background = Solid((0, 0, 255, 128))
style.who_window.xminimum = 150
style.who_window.xmargin = 10
style.who_window.xpadding = 10
style.who_window.ymargin = 5
style.who_window.ypadding = 5
def two_window_say(who, what,
who_style='say_label',
what_style='say_dialogue',
window_style='say_window',
who_window_style='who_window',
who_prefix='',
who_suffix=': ',
what_prefix='',
what_suffix='',
interact=True,
slow=True,
**properties):
if interact:
ui.saybehavior()
if who is not None:
who = who_prefix + who + who_suffix
what = what_prefix + what + what_suffix
ui.vbox(style='two_window_say_position')
if who is not None:
ui.window(style=who_window_style)
ui.text(who, style=who_style, **properties)
ui.window(style=window_style)
ui.text(what, style=what_style, slow=slow)
ui.close()
if interact:
ui.interact()
renpy.checkpoint()
+72
View File
@@ -0,0 +1,72 @@
# 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
# toggling it on or off for individual characters.
#
# To use it, place a voice "<wavfile>" line before each voiced line of
# dialogue.
#
# voice "e_1001.wav"
# e "Voice support lets you add the spoken word to your games."
#
# Normally, a voice is cancelled at the start of the next
# interaction. If you want a voice to span interactions, call
# voice_sustain.
#
# voice "e_1002.wav"
# e "Voice sustain is a technique that allows the same voice file.."
#
# $ voice_sustain()
# e "...to play for two lines of dialogue."
init -440:
python:
# Ensure the voice preference exists.
if persistent.voice is None:
persistent.voice = True
_voice = object()
_voice.play = None
_voice.sustain = False
# Call this to specify the voice file that will be played for
# the user.
def voice(file):
_voice.play = file
# Call this to specify that the currently playing voice file
# should be sustained through the current interaction.
def voice_sustain(ignored=""):
_voice.sustain = True
python hide:
renpy.sound.set_mixer(2, "voice")
library.has_voice = True
library.sample_voice = None
vp = _VolumePreference('Voice Volume',
'voice',
'library.has_voice',
'library.sample_voice')
library.preferences['prefs_right'].insert(1, vp)
# This is called on each interaction, to ensure that the
# appropriate voice file is played for the user.
def voice_interact():
if not persistent.voice:
return
if _voice.play and not config.skipping:
renpy.sound.play(_voice.play, channel=2)
elif not _voice.sustain:
renpy.sound.stop(channel=2)
_voice.play = None
_voice.sustain = False
config.start_interact_callbacks.append(voice_interact)
Symlink
+1
View File
@@ -0,0 +1 @@
demo2/
-18
View File
@@ -1,18 +0,0 @@
{
"start_a170b500": {
"area": [
53,
120,
426,
120
]
},
"start_f41f55d7": {
"area": [
106,
60,
426,
120
]
}
}
-478
View File
@@ -1,478 +0,0 @@
################################################################################
## Initialization
################################################################################
## The init offset statement causes the initialization statements in this file
## to run before init statements in any other file.
init offset = -2
## Calling gui.init resets the styles to sensible default values, and sets the
## width and height of the game.
init python:
gui.init(1280, 720)
## Enable checks for invalid or unstable properties in screens or transforms
define config.check_conflicting_properties = True
################################################################################
## GUI Configuration Variables
################################################################################
## Colors ######################################################################
##
## The colors of text in the interface.
## An accent color used throughout the interface to label and highlight
## text.
define gui.accent_color = "#00b8c3"
## The color used for a text button when it is neither selected nor hovered.
define gui.idle_color = "#888888"
## The small color is used for small text, which needs to be
## brighter/darker to achieve the same effect.
define gui.idle_small_color = "#aaaaaa"
## The color that is used for buttons and bars that are hovered.
define gui.hover_color = Color(gui.accent_color).tint(.6)
## The color used for a text button when it is selected but not focused.
## A button is selected if it is the current screen or preference value.
define gui.selected_color = "#ffffff"
## The color used for a text button when it cannot be selected.
define gui.insensitive_color = "#55555580"
## Colors used for the portions of bars that are not filled in. These are
## not used directly, but are used when re-generating bar image files.
define gui.muted_color = "#004e49"
define gui.hover_muted_color = "#006e75"
## The colors used for dialogue and menu choice text.
define gui.text_color = "#ffffff"
define gui.interface_text_color = "#ffffff"
## Fonts and Font Sizes ########################################################
## The font used for in-game text.
define gui.text_font = "DejaVuSans.ttf"
## The font used for character names.
define gui.name_text_font = "DejaVuSans.ttf"
## The font used for out-of-game text.
define gui.interface_text_font = "DejaVuSans.ttf"
## The size of normal dialogue text.
define gui.text_size = gui.scale(22)
## The size of character names.
define gui.name_text_size = gui.scale(30)
## The size of text in the game's user interface.
define gui.interface_text_size = gui.scale(22)
## The size of labels in the game's user interface.
define gui.label_text_size = gui.scale(24)
## The size of text on the notify screen.
define gui.notify_text_size = gui.scale(16)
## The size of the game's title.
define gui.title_text_size = gui.scale(50)
## Main and Game Menus #########################################################
## The images used for the main and game menus.
define gui.main_menu_background = "gui/main_menu.png"
define gui.game_menu_background = "gui/game_menu.png"
## Dialogue ####################################################################
##
## These variables control how dialogue is displayed on the screen one line
## at a time.
## The height of the textbox containing dialogue.
define gui.textbox_height = gui.scale(185)
## The placement of the textbox vertically on the screen. 0.0 is the top, 0.5 is
## center, and 1.0 is the bottom.
define gui.textbox_yalign = 1.0
## The placement of the speaking character's name, relative to the textbox.
## These can be a whole number of pixels from the left or top, or 0.5 to center.
define gui.name_xpos = gui.scale(240)
define gui.name_ypos = gui.scale(0)
## The horizontal alignment of the character's name. This can be 0.0 for
## left-aligned, 0.5 for centered, and 1.0 for right-aligned.
define gui.name_xalign = 0.0
## The width, height, and borders of the box containing the character's
## name, or None to automatically size it.
define gui.namebox_width = None
define gui.namebox_height = None
## The borders of the box containing the character's name, in left, top,
## right, bottom order.
define gui.namebox_borders = Borders(5, 5, 5, 5)
## If True, the background of the namebox will be tiled, if False, the background
## of the namebox will be scaled.
define gui.namebox_tile = False
## The placement of dialogue relative to the textbox. These can be a whole
## number of pixels relative to the left or top side of the textbox, or 0.5
## to center.
define gui.dialogue_xpos = gui.scale(268)
define gui.dialogue_ypos = gui.scale(50)
## The maximum width of dialogue text, in pixels.
define gui.dialogue_width = gui.scale(744)
## The horizontal alignment of the dialogue text. This can be 0.0 for
## left-aligned, 0.5 for centered, and 1.0 for right-aligned.
define gui.dialogue_text_xalign = 0.0
## Buttons #####################################################################
##
## These variables, along with the image files in gui/button, control aspects
## of how buttons are displayed.
## The width and height of a button, in pixels. If None, Ren'Py computes a size.
define gui.button_width = None
define gui.button_height = None
## The borders on each side of the button, in left, top, right, bottom order.
define gui.button_borders = Borders(gui.scale(4), gui.scale(4), gui.scale(4), gui.scale(4))
## If True, the background image will be tiled. If False, the background image
## will be linearly scaled.
define gui.button_tile = False
## The font used by the button.
define gui.button_text_font = gui.interface_text_font
## The size of the text used by the button.
define gui.button_text_size = gui.interface_text_size
## The color of button text in various states.
define gui.button_text_idle_color = gui.idle_color
define gui.button_text_hover_color = gui.hover_color
define gui.button_text_selected_color = gui.selected_color
define gui.button_text_insensitive_color = gui.insensitive_color
## The horizontal alignment of the button text. (0.0 is left, 0.5 is center,
## 1.0 is right).
define gui.button_text_xalign = 0.0
## These variables override settings for different kinds of buttons. Please
## see the gui documentation for the kinds of buttons available, and what
## each is used for.
##
## These customizations are used by the default interface:
define gui.radio_button_borders = Borders(gui.scale(18), gui.scale(4), gui.scale(4), gui.scale(4))
define gui.check_button_borders = Borders(gui.scale(18), gui.scale(4), gui.scale(4), gui.scale(4))
define gui.confirm_button_text_xalign = 0.5
define gui.page_button_borders = Borders(gui.scale(10), gui.scale(4), gui.scale(10), gui.scale(4))
define gui.quick_button_borders = Borders(gui.scale(10), gui.scale(4), gui.scale(10), gui.scale(0))
define gui.quick_button_text_size = gui.scale(14)
define gui.quick_button_text_idle_color = gui.idle_small_color
define gui.quick_button_text_selected_color = gui.accent_color
## You can also add your own customizations, by adding properly-named variables.
## For example, you can uncomment the following line to set the width of a
## navigation button.
# define gui.navigation_button_width = 250
## Choice Buttons ##############################################################
##
## Choice buttons are used in the in-game menus.
define gui.choice_button_width = gui.scale(790)
define gui.choice_button_height = None
define gui.choice_button_tile = False
define gui.choice_button_borders = Borders(gui.scale(100), gui.scale(5), gui.scale(100), gui.scale(5))
define gui.choice_button_text_font = gui.text_font
define gui.choice_button_text_size = gui.text_size
define gui.choice_button_text_xalign = 0.5
define gui.choice_button_text_idle_color = "#cccccc"
define gui.choice_button_text_hover_color = "#ffffff"
define gui.choice_button_text_insensitive_color = "#444444"
## File Slot Buttons ###########################################################
##
## A file slot button is a special kind of button. It contains a thumbnail
## image, and text describing the contents of the save slot. A save slot
## uses image files in gui/button, like the other kinds of buttons.
## The save slot button.
define gui.slot_button_width = gui.scale(276)
define gui.slot_button_height = gui.scale(206)
define gui.slot_button_borders = Borders(gui.scale(10), gui.scale(10), gui.scale(10), gui.scale(10))
define gui.slot_button_text_size = gui.scale(14)
define gui.slot_button_text_xalign = 0.5
define gui.slot_button_text_idle_color = gui.idle_small_color
define gui.slot_button_text_selected_idle_color = gui.selected_color
define gui.slot_button_text_selected_hover_color = gui.hover_color
## The width and height of thumbnails used by the save slots.
define config.thumbnail_width = gui.scale(256)
define config.thumbnail_height = gui.scale(144)
## The number of columns and rows in the grid of save slots.
define gui.file_slot_cols = 3
define gui.file_slot_rows = 2
## Positioning and Spacing #####################################################
##
## These variables control the positioning and spacing of various user interface
## elements.
## The position of the left side of the navigation buttons, relative
## to the left side of the screen.
define gui.navigation_xpos = gui.scale(40)
## The vertical position of the skip indicator.
define gui.skip_ypos = gui.scale(10)
## The vertical position of the notify screen.
define gui.notify_ypos = gui.scale(45)
## The spacing between menu choices.
define gui.choice_spacing = gui.scale(22)
## Buttons in the navigation section of the main and game menus.
define gui.navigation_spacing = gui.scale(4)
## Controls the amount of spacing between preferences.
define gui.pref_spacing = gui.scale(10)
## Controls the amount of spacing between preference buttons.
define gui.pref_button_spacing = gui.scale(0)
## The spacing between file page buttons.
define gui.page_spacing = gui.scale(0)
## The spacing between file slots.
define gui.slot_spacing = gui.scale(10)
## The position of the main menu text.
define gui.main_menu_text_xalign = 1.0
## Frames ######################################################################
##
## These variables control the look of frames that can contain user interface
## components when an overlay or window is not present.
## Generic frames.
define gui.frame_borders = Borders(gui.scale(4), gui.scale(4), gui.scale(4), gui.scale(4))
## The frame that is used as part of the confirm screen.
define gui.confirm_frame_borders = Borders(gui.scale(40), gui.scale(40), gui.scale(40), gui.scale(40))
## The frame that is used as part of the skip screen.
define gui.skip_frame_borders = Borders(gui.scale(16), gui.scale(5), gui.scale(50), gui.scale(5))
## The frame that is used as part of the notify screen.
define gui.notify_frame_borders = Borders(gui.scale(16), gui.scale(5), gui.scale(40), gui.scale(5))
## Should frame backgrounds be tiled?
define gui.frame_tile = False
## Bars, Scrollbars, and Sliders ###############################################
##
## These control the look and size of bars, scrollbars, and sliders.
##
## The default GUI only uses sliders and vertical scrollbars.
## All of the other bars are only used in creator-written screens.
## The height of horizontal bars, scrollbars, and sliders. The width of
## vertical bars, scrollbars, and sliders.
define gui.bar_size = gui.scale(25)
define gui.scrollbar_size = gui.scale(12)
define gui.slider_size = gui.scale(25)
## True if bar images should be tiled. False if they should be linearly scaled.
define gui.bar_tile = False
define gui.scrollbar_tile = False
define gui.slider_tile = False
## Horizontal borders.
define gui.bar_borders = Borders(gui.scale(4), gui.scale(4), gui.scale(4), gui.scale(4))
define gui.scrollbar_borders = Borders(gui.scale(4), gui.scale(4), gui.scale(4), gui.scale(4))
define gui.slider_borders = Borders(gui.scale(4), gui.scale(4), gui.scale(4), gui.scale(4))
## Vertical borders.
define gui.vbar_borders = Borders(gui.scale(4), gui.scale(4), gui.scale(4), gui.scale(4))
define gui.vscrollbar_borders = Borders(gui.scale(4), gui.scale(4), gui.scale(4), gui.scale(4))
define gui.vslider_borders = Borders(gui.scale(4), gui.scale(4), gui.scale(4), gui.scale(4))
## What to do with unscrollable scrollbars in the gui. "hide" hides them, while
## None shows them.
define gui.unscrollable = "hide"
## History #####################################################################
##
## The history screen displays dialogue that the player has already dismissed.
## The number of blocks of dialogue history Ren'Py will keep.
define config.history_length = 250
## The height of a history screen entry, or None to make the height variable
## at the cost of performance.
define gui.history_height = gui.scale(140)
## The position, width, and alignment of the label giving the name of the
## speaking character.
define gui.history_name_xpos = gui.scale(155)
define gui.history_name_ypos = 0
define gui.history_name_width = gui.scale(155)
define gui.history_name_xalign = 1.0
## The position, width, and alignment of the dialogue text.
define gui.history_text_xpos = gui.scale(170)
define gui.history_text_ypos = gui.scale(2)
define gui.history_text_width = gui.scale(740)
define gui.history_text_xalign = 0.0
## NVL-Mode ###################################################################
##
## The NVL-mode screen displays the dialogue spoken by NVL-mode characters.
## The borders of the background of the NVL-mode background window.
define gui.nvl_borders = Borders(0, gui.scale(10), 0, gui.scale(20))
## The maximum number of NVL-mode entries Ren'Py will display. When more
## entries than this are to be show, the oldest entry will be removed.
define gui.nvl_list_length = 6
## The height of an NVL-mode entry. Set this to None to have the entries
## dynamically adjust height.
define gui.nvl_height = gui.scale(115)
## The spacing between NVL-mode entries when gui.nvl_height is None, and
## between NVL-mode entries and an NVL-mode menu.
define gui.nvl_spacing = gui.scale(10)
## The position, width, and alignment of the label giving the name of the
## speaking character.
define gui.nvl_name_xpos = gui.scale(430)
define gui.nvl_name_ypos = 0
define gui.nvl_name_width = gui.scale(150)
define gui.nvl_name_xalign = 1.0
## The position, width, and alignment of the dialogue text.
define gui.nvl_text_xpos = gui.scale(450)
define gui.nvl_text_ypos = gui.scale(8)
define gui.nvl_text_width = gui.scale(590)
define gui.nvl_text_xalign = 0.0
## The position, width, and alignment of nvl_thought text (the text said by
## the nvl_narrator character.)
define gui.nvl_thought_xpos = gui.scale(240)
define gui.nvl_thought_ypos = gui.scale(0)
define gui.nvl_thought_width = gui.scale(780)
define gui.nvl_thought_xalign = 0.0
## The position of nvl menu_buttons.
define gui.nvl_button_xpos = gui.scale(450)
define gui.nvl_button_xalign = 0.0
## Localization ################################################################
## This controls where a line break is permitted. The default is suitable for
## most languages. A list of available values can be found at
## https://www.renpy.org/doc/html/style_properties.html#style-property-language
define gui.language = "unicode"
################################################################################
## Mobile devices
################################################################################
init python:
## This increases the size of the quick buttons to make them easier to
## touch on tablets and phones.
@gui.variant
def touch():
gui.quick_button_borders = Borders(gui.scale(40), gui.scale(14), gui.scale(40), gui.scale(0))
## This changes the size and spacing of various GUI elements to ensure
## they are easily visible on phones.
@gui.variant
def small():
## Font sizes.
gui.text_size = gui.scale(30)
gui.name_text_size = gui.scale(36)
gui.notify_text_size = gui.scale(25)
gui.interface_text_size = gui.scale(30)
gui.button_text_size = gui.scale(30)
gui.label_text_size = gui.scale(34)
## Adjust the location of the textbox.
gui.textbox_height = gui.scale(240)
gui.name_xpos = gui.scale(80)
gui.dialogue_xpos = gui.scale(90)
gui.dialogue_width = gui.scale(1100)
## Change the size and spacing of various things.
gui.slider_size = gui.scale(36)
gui.choice_button_width = gui.scale(1240)
gui.choice_button_text_size = gui.scale(30)
gui.navigation_spacing = gui.scale(20)
gui.pref_button_spacing = gui.scale(10)
gui.history_height = gui.scale(190)
gui.history_text_width = gui.scale(690)
gui.quick_button_text_size = gui.scale(20)
## File button layout.
gui.file_slot_cols = 2
gui.file_slot_rows = 2
## NVL-mode.
gui.nvl_height = gui.scale(170)
gui.nvl_name_width = gui.scale(305)
gui.nvl_name_xpos = gui.scale(325)
gui.nvl_text_width = gui.scale(915)
gui.nvl_text_xpos = gui.scale(345)
gui.nvl_text_ypos = gui.scale(5)
gui.nvl_thought_width = gui.scale(1240)
gui.nvl_thought_xpos = gui.scale(20)
gui.nvl_button_width = gui.scale(1240)
gui.nvl_button_xpos = gui.scale(20)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

-30
View File
@@ -1,30 +0,0 @@
init -100 python in gui:
def scale(n):
return int(n)
init 100 python in gui:
if not renpy.mobile:
from store import config
import sys
import os
sys.path.insert(0, os.path.join(config.renpy_base, "launcher", "game"))
from gui7.parameters import GuiParameters
from gui7.images import ImageGenerator
from gui7 import generate_gui
p = GuiParameters(
config.gamedir, config.gamedir,
config.screen_width, config.screen_height,
accent_color, "#000000", False, None,
True, False, False, "gui")
p.skip_backup = True
generate_gui(p)
_skip_backup = True
_gui_images()
-213
View File
@@ -1,213 +0,0 @@
## This file contains options that can be changed to customize your
## game.
##
## Lines beginning with two '#' marks are comments, and you shouldn't
## uncomment them. Lines beginning with a single '#' mark are
## commented-out code, and you may want to uncomment them when
## appropriate.
## Basics ######################################################################
## A human-readable name of the game. This is used to set the default
## window title, and shows up in the interface and error reports.
##
## The _() surrounding the string marks it as eligible for translation.
define config.name = _("Ren'Py 7 Default GUI")
## Determines if the title given above is shown on the main menu
## screen. Set this to False to hide the title.
define gui.show_name = True
## The version of the game.
define config.version = "1.0"
## Text that is placed on the game's about screen. Place the text between
## the triple-quotes, and leave a blank line between paragraphs.
define gui.about = _p("""
""")
## A short name for the game used for executables and directories in the
## built distribution. This must be ASCII-only, and must not contain
## spaces, colons, or semicolons.
define build.name = "gui"
## Sounds and music ############################################################
## These three variables control, among other things, which mixers are
## shown to the player by default. Setting one of these to False will
## hide the appropriate mixer.
define config.has_sound = True
define config.has_music = True
define config.has_voice = True
## To allow the user to play a test sound on the sound or voice channel,
## uncomment a line below and use it to set a sample sound to play.
# define config.sample_sound = "sample-sound.ogg"
# define config.sample_voice = "sample-voice.ogg"
## Uncomment the following line to set an audio file that will be played
## while the player is at the main menu. This file will continue playing
## into the game, until it is stopped or another file is played.
# define config.main_menu_music = "main-menu-theme.ogg"
## Transitions #################################################################
##
## These variables set transitions that are used when certain events occur.
## Each variable should be set to a transition, or None to indicate that
## no transition should be used.
## Entering or exiting the game menu.
define config.enter_transition = dissolve
define config.exit_transition = dissolve
## Between screens of the game menu.
define config.intra_transition = dissolve
## A transition that is used after a game has been loaded.
define config.after_load_transition = None
## Used when entering the main menu after the game has ended.
define config.end_game_transition = None
## A variable to set the transition used when the game starts
## does not exist. Instead, use a with statement after showing
## the initial scene.
## Window management ###########################################################
##
## This controls when the dialogue window is displayed. If "show", it is always
## displayed. If "hide", it is only displayed when dialogue is present. If
## "auto", the window is hidden before scene statements and shown again
## once dialogue is displayed.
##
## After the game has started, this can be changed with the "window show",
## "window hide", and "window auto" statements.
define config.window = "auto"
## Transitions used to show and hide the dialogue window
define config.window_show_transition = Dissolve(.2)
define config.window_hide_transition = Dissolve(.2)
## Preference defaults #########################################################
## Controls the default text speed. The default, 0, is infinite, while any
## other number is the number of characters per second to type out.
default preferences.text_cps = 0
## The default auto-forward delay. Larger numbers lead to longer waits,
## with 0 to 30 being the valid range.
default preferences.afm_time = 15
## Save directory ##############################################################
##
## Controls the platform-specific place Ren'Py will place the save
## files for this game. The save files will be placed in:
##
## Windows: %APPDATA\RenPy\<config.save_directory>
##
## Macintosh: $HOME/Library/RenPy/<config.save_directory>
##
## Linux: $HOME/.renpy/<config.save_directory>
##
## This generally should not be changed, and if it is, should always be a
## literal string, not an expression.
define config.save_directory = "gui-7"
## Icon ########################################################################
##
## The icon displayed on the taskbar or dock.
define config.window_icon = "gui/window_icon.png"
## Build configuration #########################################################
##
## This section controls how Ren'Py turns your project into distribution
## files.
init python:
## The following functions take file patterns. File patterns are case-
## insensitive, and matched against the path relative to the base
## directory, with and without a leading /. If multiple patterns match,
## the first is used.
##
## In a pattern:
##
## / is the directory separator.
##
## * matches all characters, except the directory separator.
##
## ** matches all characters, including the directory separator.
##
## For example, "*.txt" matches txt files in the base directory, "game/**.ogg"
## matches ogg files in the game directory or any of its subdirectories, and
## "**.psd" matches psd files anywhere in the project.
## Classify files as None to exclude them from the built distributions.
build.classify('**~', None)
build.classify('**.bak', None)
build.classify('**/.**', None)
build.classify('**/#**', None)
build.classify('**/thumbs.db', None)
## To archive files, classify them as 'archive'.
# build.classify('game/**.png', 'archive')
# build.classify('game/**.jpg', 'archive')
## Files matching documentation patterns are duplicated in a mac app
## build, so they appear in both the app and the zip file.
build.documentation('*.html')
build.documentation('*.txt')
## A Google Play license key is required to perform in-app purchases.
## It can be found in the Google Play developer console,
## under "Monetize" > "Monetization Setup" > "Licensing".
# define build.google_play_key = "..."
## The username and project name associated with an itch.io project,
## separated by a slash.
# define build.itch_project = "renpytom/test-project"
-1574
View File
File diff suppressed because it is too large Load Diff
-33
View File
@@ -1,33 +0,0 @@
# The script of the game goes in this file.
# Declare characters used by this game. The color argument colorizes the
# name of the character.
define e = Character("Eileen")
# The game starts here.
label start:
# Show a background. This uses a placeholder by default, but you can
# add a file (named either "bg room.png" or "bg room.jpg") to the
# images directory to show it.
scene bg room
# This shows a character sprite. A placeholder is used, but you can
# replace it by adding a file named "eileen happy.png" to the images
# directory.
show eileen happy
# These display lines of dialogue.
e "You've created a new Ren'Py game."
e "Once you add a story, pictures, and music, you can release it to the world!"
# This ends the game.
return
-160
View File
@@ -1,160 +0,0 @@
testcase default:
"Start"
pause .6
# Test rollback
"Hello, World."
"Back"
# Test history.
click
click
"History"
pause .6
# Test Help.
"Help"
"Keyboard"
# Test About
"About"
# Test Preferences
"Preferences"
"Left"
"Right"
"Disable"
"Unseen Text"
"Unseen Text"
"After Choices"
"After Choices"
"Transitions"
"Transitions"
"Mute All"
"Mute All"
"Save"
"Load"
"Return"
pause .6
run Jump("test")
"In testcase code."
# menu_1
click until "Choice A"
# input
type "Test User\n"
"Name: Test User"
# Nvl
click
click
click
click
click
click until "NVL 6"
# NVL Menu.
"Choice B"
$ renpy.unlink_save("1-1")
"Save"
pause .6
"Save slot 1"
pause .6
"Save slot 1"
"Yes"
"Main Menu"
"Yes"
"Load"
"Load slot 1"
pause .5
"Save"
pause .5
"Load"
"Load slot 1"
"No"
"Return"
# Done.
pause .5
"Done."
"Quit"
define nvle = Character("Eileen", kind=nvl)
label test:
"In testcase code."
menu menu_1:
"This is a menu."
"Choice A":
pass
"Choice B":
pass
label after_menu_1:
$ name = renpy.input("What is your name?")
"Name: [name]"
nvle "NVL 1"
nvle "NVL 2"
nvle "NVL 3"
nvl clear
nvle "NVL 4"
nvle "NVL 5"
nvle "NVL 6"
$ menu = nvl_menu
menu menu_2:
"This is a menu."
"Choice A":
pass
"Choice B":
pass
label after_menu_2:
"Done."
return
-1
View File
@@ -1 +0,0 @@
{ "type" : "hidden" }
BIN
View File
Binary file not shown.
+134
View File
@@ -0,0 +1,134 @@
;;; Comments beginning with ";;;" are commentary added by PyTom to
;;; try to help you understand this file.
;;;
;;; This installer expects that you will have supplied LICENSE.txt
;;; and README.txt files in the root directory of your game.
;;;
;;; To use this, place it in the root directory of your game,
;;; right-click on it, and choose "Compile NSIS script..."
;;; First up, change the settings below to match your game.
;;; The exe used to run your game.
!define EXE "moonlight.exe"
;;; The exe containing the installer. This will be created in the directory
;;; above the root directory containing your game.
!define INSTALLER_EXE "moonlight-1.0ni.exe"
;;; The name and version.
!define PRODUCT_NAME "Moonlight Walks"
!define PRODUCT_VERSION "1.0"
;;; The following settings are only shown to the user in Add/Remove programs
;;; but you'll still want to use them.
!define PRODUCT_WEB_SITE "http://www.bishoujo.us/moonlight/"
!define PRODUCT_PUBLISHER "American Bishoujo"
;;; Ignore this next block of stuff. It's mostly boilerplate.
!include "MUI.nsh"
!define MUI_ABORTWARNING
;;; Change this to change the compression scheme.
SetCompressor lzma
;;; You can change these to customize the bitmaps and icons used for
;;; your installer and uninstaller. Bitmaps should be 150x57.
; !define MUI_HEADERIMAGE
; !define MUI_HEADERIMAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Header\nsis.bmp"
; !define MUI_HEADERIMAGE_UNBITMAP "${NSISDIR}\Contrib\Graphics\Header\nsis.bmp"
!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install.ico"
!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico"
;;; This is the sequencing of the pages that does the actual installation.
;;; you can comment pages out, if you want to.
; Welcome page
!insertmacro MUI_PAGE_WELCOME
; License page
!insertmacro MUI_PAGE_LICENSE "LICENSE.txt"
; Directory page
!insertmacro MUI_PAGE_DIRECTORY
; Instfiles page
!insertmacro MUI_PAGE_INSTFILES
; Finish page
!define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\README.txt"
!insertmacro MUI_PAGE_FINISH
; Uninstaller pages
!insertmacro MUI_UNPAGE_INSTFILES
;;; Okay, that's it for the commentary. You're on your own from here...
;;; but you probably won't need to touch anything below this point.
; Various other defines.
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
!define PRODUCT_UNINST_ROOT_KEY "HKLM"
; Language files
!insertmacro MUI_LANGUAGE "English"
; Reserve files
!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS
Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
OutFile "..\${INSTALLER_EXE}"
InstallDir "$PROGRAMFILES\${PRODUCT_NAME}"
Section "!${PRODUCT_NAME}" SEC01
SetOutPath "$INSTDIR"
SetOverwrite ifnewer
File /r /x renpy /x *.py /x *.pyw /x installer.nsi /x persistent *.*
CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}"
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk" "$INSTDIR\${EXE}"
CreateShortCut "$DESKTOP\${PRODUCT_NAME}.lnk" "$INSTDIR\${EXE}"
SectionEnd
Section -AdditionalIcons
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk" "$INSTDIR\uninst.exe"
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\README.lnk" "$INSTDIR\README.txt"
SectionEnd
Section -Post
WriteUninstaller "$INSTDIR\uninst.exe"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\${EXE}"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
SectionEnd
Function un.onUninstSuccess
HideWindow
MessageBox MB_ICONINFORMATION|MB_OK "$(^Name) was successfully removed from your computer."
FunctionEnd
Function un.onInit
MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "Are you sure you want to completely remove $(^Name) and all of its components?" IDYES +2
Abort
FunctionEnd
Section Uninstall
Delete "$SMPROGRAMS\${PRODUCT_NAME}\README.lnk"
Delete "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk"
Delete "$DESKTOP\${PRODUCT_NAME}.lnk"
Delete "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk"
RMDir "$SMPROGRAMS\${PRODUCT_NAME}"
RMDir /r "$INSTDIR"
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
SetAutoClose true
SectionEnd
-86
View File
@@ -1,86 +0,0 @@
#!/usr/bin/env python
# The path to a copy of Atom that's been installed globally, if one exists.
# This is overidden by RENPY_ATOM, if set. If either is given, that is used
# and no special handing of the .atom directory is performed.
ATOM = None
import sys
import os
import subprocess
import platform
import shutil
import renpy
class Editor(renpy.editor.Editor):
has_projects = True
def get_atom(self):
"""
Returns the path to the atom executable, if None. Also takes care
of setting up the .atom directory if it's not available.
"""
atom = os.environ.get("RENPY_ATOM", ATOM)
if atom is not None:
return atom
DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
DIR = os.path.join(renpy.exports.fsdecode(DIR), "atom")
if renpy.windows:
atom = os.path.join(DIR, "atom-windows", "atom.exe")
elif renpy.macintosh:
atom = os.path.join(DIR, "Atom.app", "Contents", "Resources", "app", "atom.sh")
else:
atom = os.path.join(DIR, "atom-linux-" + platform.machine(), "atom")
default_dot_atom = os.path.join(DIR, "default-dot-atom")
dot_atom = os.path.join(DIR, ".atom")
if not os.path.exists(dot_atom) and os.path.exists(default_dot_atom):
shutil.copytree(default_dot_atom, dot_atom)
return atom
def begin(self, new_window=False, **kwargs):
self.args = [ ]
def open(self, filename, line=None, **kwargs):
if line:
filename = "{}:{}".format(filename, line)
self.args.append(filename)
def open_project(self, project):
self.args.append(project)
def end(self, **kwargs):
atom = self.get_atom()
self.args.reverse()
args = [ atom ] + self.args
args = [ renpy.exports.fsencode(i) for i in args ]
subprocess.Popen(args)
def main():
e = Editor()
e.begin()
for i in sys.argv[1:]:
e.open(i)
e.end()
if __name__ == "__main__":
main()

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