Compare commits

...

187 Commits

Author SHA1 Message Date
Tom Rothamel 375af0cccd 6.11.2b 2010-10-26 22:12:50 -04:00
Tom Rothamel 8ae8e887f5 Fix a bug in Frame that can cause an image to be drawn more than once
a border size is 0.
2010-10-24 18:06:36 -04:00
Tom Rothamel 201b6432c4 6.11.2a 2010-10-24 14:59:33 -04:00
Tom Rothamel fc10bbf6b6 Update themes code to support Aleema's new themes. 2010-10-23 14:14:27 -04:00
Tom Rothamel 1c82c71aea Defensively code adding an event to the queue. 2010-10-23 00:13:53 -04:00
Tom Rothamel a59abd3135 Rewrote MoveTransition to deal with changes in order more gracefully. 2010-10-22 01:15:41 -04:00
Tom Rothamel a51633b511 Fixed :lpbug:647324, where ImageDissolves are rendered as if
specified with alpha=True whether or not alpha=True was set.
2010-10-21 23:26:41 -04:00
Tom Rothamel 2b40d265f9 Search for environment.txt in the directory containing the mac .app file. 2010-10-21 22:56:54 -04:00
Tom Rothamel 734b5b02f8 Buttons now only pass key events to their children when they are
focused. This allows a screen language key statement to be used as the
child of a button, and only activate when the button is focused.
2010-10-21 22:34:44 -04:00
Tom Rothamel 4120434e5a Add four themes contributed by Aleema. 2010-10-21 20:15:49 -04:00
Tom Rothamel 6d9c4dc6d9 Preserve statement names over more changes. 2010-10-21 19:47:21 -04:00
Tom Rothamel ce94a1360a Fixed a problem that prevented AnimatedValue from functioning properly
when delay was not 1.0. Thanks to Scout for the fix.
2010-10-20 01:09:56 -04:00
Tom Rothamel 27a61f4faf Proofreading by Doomfest. 2010-10-20 00:57:07 -04:00
Tom Rothamel 36f50a482b Deallocate movie surface when a movie is not playing, to prevent the last frame of the previous movie. 2010-10-20 00:47:10 -04:00
Tom Rothamel 28d681b29b Change movie drawing so that we use swscale to convert to RGB, rather
than the SDL stuff. The SDL was broken when video resize was used.
2010-10-20 00:38:32 -04:00
Tom Rothamel ddb53bfce1 Fixed :lpbug:661983, which caused insensitive hotspots to default to
the idle, rather than ground, image when no insensitive image was
supplied.
2010-10-17 02:02:33 -04:00
Tom Rothamel 81414254f9 The maximum default physical size of the Ren'Py window is now 102
pixels smaller than the height of the screen.
2010-10-16 23:33:14 -04:00
Tom Rothamel 4af4481a17 Fixed launchpad bug 647686, a regression that prevented sounds from looping properly.
Added lpbug documentation reference.
2010-10-16 19:06:28 -04:00
Tom Rothamel f1cff045e1 Better handle the overloading of Return(). 2010-10-09 18:13:11 -04:00
Tom Rothamel f75f0ccb14 Allow the default property to be set in the screen language. 2010-09-16 08:31:39 -04:00
Tom Rothamel 01f82aaf4c Bump version. 2010-09-15 23:37:44 -04:00
Tom Rothamel 8b294e05ad Fix problem where if you hit quit, no at the main menu, the game starts. 2010-09-15 23:34:14 -04:00
Tom Rothamel 5b2fcb85e5 Fixed character not respecting the interact argument. 2010-09-15 22:34:29 -04:00
Tom Rothamel fb1d38dc3a Enter the with mode on with None. 2010-09-14 23:18:08 -04:00
Tom Rothamel 5cc6a8d75a Ensure that empty strings render with 0 width. 2010-09-13 23:22:58 -04:00
Tom Rothamel fbe2a03933 Normalize file line endings during updates. 2010-09-13 21:04:48 -04:00
Tom Rothamel 915bccf099 Fixed problem with modes (reported with patch by Spiky Catapillar.) 2010-09-12 23:52:08 -04:00
Tom Rothamel 0943e368e7 Fix mode to work with nvl and extend. 2010-09-12 23:48:39 -04:00
Tom Rothamel d35c6e190c Fix docs. 2010-09-09 11:37:34 -04:00
Tom Rothamel 1025ad5a6a Reduce size of updates. 2010-09-09 11:23:42 -04:00
Tom Rothamel fd74541318 Check that sayer is valid. 2010-09-09 11:23:24 -04:00
Tom Rothamel 821db477ae Update default enter/leave factories to work with offsets. 2010-09-09 10:06:40 -04:00
Tom Rothamel ed66034930 Fix bug that caused atl revolution not to work. 2010-09-09 09:58:30 -04:00
Tom Rothamel a9c91378fd Another version bump. 2010-09-08 22:17:48 -04:00
Tom Rothamel 1dc58f2ed1 Add AlphaDissolve to the tutorial. 2010-09-08 09:36:56 -04:00
Tom Rothamel ae916e2a59 More updater work. 2010-09-07 22:17:31 -04:00
Tom Rothamel f3af72e67e Properly notify on update events. 2010-09-07 21:52:45 -04:00
Tom Rothamel 939c2121b7 Fixes to updater. 2010-09-07 21:41:02 -04:00
Tom Rothamel 46699bfc1e Update copyright, and bump versions. 2010-09-07 21:19:54 -04:00
Tom Rothamel 63d381d5a6 FieldValues with max_is_zero set to True now work properly. Thanks to
SleepKirby for the fix.
2010-09-07 08:13:30 -04:00
Tom Rothamel c608d18684 Update distribution building to reflect new Windows layout. 2010-09-07 00:05:11 -04:00
Tom Rothamel c31f61e7b6 Integrate updater support w/ launcher. 2010-09-06 23:45:41 -04:00
Tom Rothamel 9912c15c04 Don't consider hidden screens when assigning default focus. 2010-09-06 14:19:07 -04:00
Tom Rothamel 651653593c Make MoveTransition respect offsets. 2010-09-06 12:52:29 -04:00
Tom Rothamel 85858974b8 Add urllib to dependencies. 2010-09-05 23:48:52 -04:00
Tom Rothamel a265fbb797 Fix problem with screen language lines numbers being in error. 2010-09-05 23:26:24 -04:00
Tom Rothamel e353ea2d56 Don't crash when compiling shaders. 2010-09-05 22:54:00 -04:00
Tom Rothamel 6f91db067a Fix a bug with hotbars not working.
Fix a bug caused by an incorrect texture unit check.
2010-09-05 18:32:49 -04:00
Tom Rothamel 8ed51cc810 Add renpy.notify and Notify. 2010-09-04 17:25:59 -04:00
Tom Rothamel f256f174f9 The new :func:HideInterface action allows the interface to
temporarily be hidden, as a screen language action.
2010-09-04 15:59:30 -04:00
Tom Rothamel 49d3796378 Added the :ref:renpy.focus_coordinates function, which returns the
coordinates of the currently focused displayable, when possible.
2010-09-04 15:46:30 -04:00
Tom Rothamel bfb6a18527 The new :ref:modes system allows one to invoke callbacks when
switching from one type of interaction to another. This can be used,
for example, to automatically hide the window before transitions.
2010-09-04 12:30:21 -04:00
Tom Rothamel 2960220a74 Improvements to updater. 2010-09-03 22:52:10 -04:00
Tom Rothamel c6605f1742 Add experimental update code. 2010-09-03 18:17:48 -04:00
Tom Rothamel cebffcfee1 Imagemaps created using the screen language now only have a size equal
to that of their ground image. (Previously, they took up the entire
screen.) This change makes it easier to position an imagemap at a
different location on screen, such as the bottom.

Imagemaps now take an alpha argument. If true (the default), hotspots
are only focused if the mouse is over a non-transparent part of the
idle or hover image. If set to false, the hotspot is focused whenever
the mouse is within its boundaries.
2010-09-03 17:42:46 -04:00
Tom Rothamel 006cdb8c3b The developer menu now includes a command that will list all the files
in the game directory.
2010-09-02 01:08:18 -04:00
Tom Rothamel 374e0697bf Fix documentation generation from curried functions. 2010-09-02 00:48:57 -04:00
Tom Rothamel f988878424 Transforms no longer cause a divide by zero exception when the zoom,
xzoom, or yzoom properties are 0.
2010-09-02 00:02:46 -04:00
Tom Rothamel e59b252dce Fix problems with scaling (and especially, switching back and forth
between GL and scaled SW modes.)
2010-08-31 16:36:00 -04:00
Tom Rothamel b2747914d8 Fix hotspot so that it properly handles insensitive and selected images. 2010-08-28 18:47:15 -04:00
Tom Rothamel 41aeb625f3 Try to fix backwards compatibility problem. 2010-08-24 21:55:20 -04:00
Tom Rothamel 4cfa8aa06c Document AlphaDissolve. 2010-08-24 21:51:42 -04:00
Tom Rothamel 8cb4a4e3b9 Merge alphadissolve. 2010-08-24 21:46:58 -04:00
Tom Rothamel 9a84c9715f Use 256 as the parameter - allows alphablend to use the full 8 bits of alpha
range.
2010-08-24 21:17:52 -04:00
Tom Rothamel 38538f1d9a Add AlphaBlend. 2010-08-24 02:33:29 -04:00
Tom Rothamel 6a42b2a107 Initial implementation of AlphaDissolve transition. 2010-08-24 02:20:38 -04:00
Tom Rothamel 486790b810 merge w/ renpy 2010-08-22 16:11:15 -04:00
Tom Rothamel 0e538e2261 Remove obsolete files.
Remove symlinks in documentation.
2010-08-22 16:08:03 -04:00
Tom Rothamel 9042fcca55 Redo the windows build process, so that no symlinks are involved, and so
that dlls are no longer bundled inside renpy.code.
2010-08-22 15:53:55 -04:00
Tom Rothamel 040035adbc Allow keymap to take a list of actions. 2010-08-21 11:58:32 -04:00
Tom Rothamel d72097de18 add comment 2010-08-19 13:23:27 -04:00
Tom Rothamel d9771bdade Draw mouse cursor in right place. 2010-08-19 13:01:20 -04:00
Tom Rothamel 07ca905373 Fix the parameters for define_screen. 2010-08-19 08:48:58 -04:00
Tom Rothamel ccd0d45a67 A sub-render should inherit alpha from the parent render. 2010-08-18 19:54:59 -04:00
Tom Rothamel 15a15870e7 Start of new updater code. 2010-08-18 18:11:09 -04:00
Tom Rothamel 28108c7796 Remove launcher1. 2010-08-18 12:30:05 -04:00
Tom Rothamel 171f388120 6.11.0k 2010-08-17 21:19:01 -04:00
Tom Rothamel bc50f171db Add transition parameters to Show and Hide. 2010-08-17 01:08:10 -04:00
Tom Rothamel ea4c955f1f Modal and zorder are now expressions. Note that this changes the signature to define_screen. 2010-08-16 02:22:54 -04:00
Tom Rothamel 27524457d0 Copy a screen when keeping it around after a hide, rather than modifying the original screen. 2010-08-16 01:53:51 -04:00
Tom Rothamel 01fe67cfa9 Fix problems with screens caused by renpy.transition being given None as an argument, by making it handle that case properly, rather than simply delegating to with_none. 2010-08-15 21:46:21 -04:00
Tom Rothamel f4d493465d Fix problem with iterating over a list that's changing. 2010-08-15 19:15:32 -04:00
Tom Rothamel 33cbe44390 Only call _hide on direct children of the screen. 2010-08-15 02:53:41 -04:00
Tom Rothamel 5214f08d1a Assign ids to displayables correctly.
Remove non-transitions from screens at hide-time.x
2010-08-15 01:50:46 -04:00
Tom Rothamel 608fc986c4 Now can hide screens by name and tag. 2010-08-15 00:39:01 -04:00
Tom Rothamel 779a96f97f Things in a screen without an on hide method go away once hidden. 2010-08-15 00:32:53 -04:00
Tom Rothamel faf48246d7 Don't let a hiding displayable pass along focus. 2010-08-14 20:10:10 -04:00
Tom Rothamel 81ec2a6c35 fix modal when hiding. 2010-08-14 19:12:56 -04:00
Tom Rothamel 803423f12b Was over-aggressive in combining screen and old_transfers - split them. 2010-08-14 17:17:11 -04:00
Tom Rothamel b384ee0381 Make the gl-test strings translatable. Bump version. 2010-08-14 13:29:41 -04:00
Tom Rothamel b8862d6b24 Add support for a "Graphics Acceleration" menu, which allows the user
to choose between software and opengl rendering.
2010-08-13 00:50:48 -04:00
Tom Rothamel dbfa4ed46d Fix problem where displayables on a screen of one name could inherit transforms and state from displayables on a screen of a different name. 2010-08-13 00:38:43 -04:00
Tom Rothamel d9eb999775 Report when a grid is overfull. 2010-08-11 16:30:43 -04:00
Tom Rothamel b4a9ca3f87 Tweaks to gltest.
FilePageNext grows a max argument.

Report screen errors better.
2010-08-11 16:25:31 -04:00
Tom Rothamel d087c86d1a Set correct variable when setting default afm time. 2010-08-10 22:08:14 -04:00
Tom Rothamel 0cfc7b25a6 Remove imagemap rectangle from the image picker. 2010-08-10 00:35:50 -04:00
Tom Rothamel 8f3c9bd2ba Cycle through OpenGL logfile. 2010-08-09 23:19:55 -04:00
Tom Rothamel 91c79cdac9 sl: add default statement. 2010-08-09 21:42:49 -04:00
Tom Rothamel 20e4e110ce Add a check for calling ui.interact inside itself. 2010-08-09 18:57:12 -04:00
Tom Rothamel 870d7ffe2c Try the opengl test twice. 2010-08-09 16:29:10 -04:00
Tom Rothamel 6ff88c914d Fix use of modal in docs. 2010-08-08 22:46:59 -04:00
Tom Rothamel 2a2078517f Only don't transition when failing to go to the game menu from the main
menu.
2010-08-08 22:33:27 -04:00
Tom Rothamel c09f697293 6.11.0i 2010-08-08 20:20:20 -04:00
Tom Rothamel a9e273a13d Document modal more precisely. 2010-08-07 14:53:50 -04:00
Tom Rothamel 592665aa9a Various fixes to cause modal displayables to work better. 2010-08-07 14:43:13 -04:00
Tom Rothamel 3745788f06 Store the OpenGL-giveup value on startup, and use it on a restart. 2010-08-07 10:59:18 -04:00
Tom Rothamel 52b09d8f4c Fix problems with y aspect ratio. 2010-08-07 10:47:22 -04:00
Tom Rothamel 32f25cdcec Fix problem with lint_play_sound. 2010-08-07 09:06:41 -04:00
Tom Rothamel 6f022a9b6a 6.11.0h 2010-08-07 08:52:31 -04:00
Tom Rothamel eea6970929 (doc) Clarify that the hide event isn't called on scene or context exit. 2010-08-07 07:59:41 -04:00
Tom Rothamel 35ecfd279f Tweak when we run the hide event. 2010-08-07 07:52:49 -04:00
Tom Rothamel 1f5c610843 Better logic before picking between adv and nvl windows. 2010-08-07 00:30:52 -04:00
Tom Rothamel 05f4c52c33 Always render to an alpha texture, for dissolve/imagedissolve in sw mode. 2010-08-06 12:27:54 -04:00
Tom Rothamel 326f773e75 Constrain drawing area using glViewport. 2010-08-06 02:08:03 -04:00
Tom Rothamel 2079b518a2 F11 now toggles fullscreen. 2010-08-04 01:15:20 -04:00
Tom Rothamel 70ed15e5ac Add If function. 2010-08-04 00:59:09 -04:00
Tom Rothamel f1d7fe0c73 Rename group -> style_group. 2010-08-03 22:59:53 -04:00
Tom Rothamel 08e4b9bafc Minor optimizations in GL code. 2010-08-03 22:22:01 -04:00
Tom Rothamel 56a0212316 Fix problem with mouse, when going fullscreen. 2010-08-03 22:17:09 -04:00
Tom Rothamel 5df6506191 Take file_prefix and file_suffix into account for lint. 2010-08-02 23:36:10 -04:00
Tom Rothamel 39779be980 Fix problems with lint and call. Humanize lint output. 2010-08-02 18:22:13 -04:00
Tom Rothamel bdacdddf14 Fix crash with shift+Y and generated styles. 2010-08-02 17:59:40 -04:00
Tom Rothamel 4b32337ef3 Command the mouse to be displayed once a second. 2010-08-02 17:58:01 -04:00
Tom Rothamel 4897d5b7a9 Ensure Ren'Py starts when the GL modules can't be loaded. 2010-08-02 12:29:58 -04:00
Tom Rothamel 6daa64facd Store and restore the windows size on a shift+R reload. 2010-08-02 12:19:31 -04:00
Tom Rothamel 07651e414d Ensure we always check for yesno_prompt. 2010-08-01 21:33:29 -04:00
Tom Rothamel 7e1e76f0d8 When loading textures, load the borders with adjacent pixels, rather than
transparency. This means we no longer have to distort textures when
upscaling, which improves quality.
2010-08-01 13:47:05 -04:00
Tom Rothamel b91a5d1a16 Check in keywords file. 2010-07-31 23:19:39 -04:00
Tom Rothamel 39b0646f24 Change around some things involving clip planes to try to fix a
problem with them on the mac.

6.11.0g
2010-07-31 21:08:58 -04:00
Tom Rothamel ea6406f144 When upscaling, adjust texture coordinates so that we never go outside
the loaded texture.
2010-07-31 13:30:23 -04:00
Tom Rothamel 7ed3f3fbad Add the quickstart to the manual. 2010-07-30 13:16:50 -04:00
Tom Rothamel cacb4ac40e Allow {fast} to work in menus and all-at-once mode. 2010-07-28 23:27:52 -04:00
Tom Rothamel 9503744631 Unbranding error messages. 2010-07-28 22:45:00 -04:00
Tom Rothamel 58dfd5dbfa Document focus, and use it to ensure that menus do not have any choice highlighted by default. 2010-07-28 22:40:48 -04:00
Tom Rothamel 60d5507184 Only call unhovered when a non-default unhover occurs. 2010-07-28 22:34:39 -04:00
Tom Rothamel 5641cec146 Give a proper error when someone tries to use an empty string as a displayable. 2010-07-28 22:32:51 -04:00
Tom Rothamel dd455e3d14 Fix problems with window hide / window show and NVL-mode. 2010-07-28 21:55:16 -04:00
Tom Rothamel 6876697f74 Fixed proble with default focus and subsurface. 2010-07-25 23:15:40 -04:00
Tom Rothamel 4373cab8cf 6.11.0f 2010-07-25 20:10:01 -04:00
Tom Rothamel eeccb5833b Doc fixes, remove AutoForward as an independent action. 2010-07-25 20:07:22 -04:00
Tom Rothamel 790dad0330 Fix / document screens. 2010-07-25 19:58:48 -04:00
Tom Rothamel 078a38af5d Pass transform events through to children of Transforms. 2010-07-25 13:55:44 -04:00
Tom Rothamel 8c186d2eb1 Remove extraneous print. 2010-07-25 13:40:04 -04:00
Tom Rothamel 81b94b27e0 Display problems documentation.
Limit display to screen size.
2010-07-25 01:15:20 -04:00
Tom Rothamel 17e8616e8c Do not buffer playback of movies.
Change get_playing to return audio that's queued up to play, as well as audio that's currently playing.
2010-07-24 16:44:39 -04:00
Tom Rothamel 50b0dc3c5e Add the ability to blacklist mugen's video card. 2010-07-24 13:24:49 -04:00
Tom Rothamel 9e217e722f Introduce StoreProxy object. 2010-07-24 11:41:22 -04:00
Tom Rothamel f466b44b66 Fix problem with negative line_spacing. 2010-07-23 02:32:31 -04:00
Tom Rothamel 34e0fc7cba Always take screenshots from the main thread. 2010-07-23 01:53:39 -04:00
Tom Rothamel bb88a7bb95 Remove letterboxing when taking a screenshot. 2010-07-23 01:14:06 -04:00
Tom Rothamel 71ba444e62 6.11.0e. 2010-07-18 10:39:09 -04:00
Tom Rothamel 3e0baee463 Update documentation. 2010-07-17 22:44:53 -04:00
Tom Rothamel a0064f5511 Disable OpenGL in launcher. 2010-07-17 22:37:01 -04:00
Tom Rothamel e7ce23f377 Fix potential video race. 2010-07-17 22:35:11 -04:00
Tom Rothamel 9c6d93968c Stop defining default in terms of other transforms, to allow those
transforms to be re-defined.
2010-07-17 22:00:21 -04:00
Tom Rothamel e4b29d58f4 Include indentation in text size. 2010-07-17 17:38:44 -04:00
Tom Rothamel a48b87a0d6 Fixed a bug that could cause ATL transforms to over-compute changes,
this leading to problems when used in parallel
2010-07-17 16:17:26 -04:00
Tom Rothamel 763515a937 Add GL Performance test. 2010-07-17 14:02:00 -04:00
Tom Rothamel 46a8242e51 Make sure that lexer revert also reverts the line. 2010-07-17 12:59:18 -04:00
Tom Rothamel efa8d66d3d Make placement of developer menu more friendly. 2010-07-15 23:28:37 -04:00
Tom Rothamel b7c71bb3b8 Work better with broken fonts. 2010-07-15 22:36:05 -04:00
Tom Rothamel aca5438b5a Use shift to disable OpenGL. Add deinit to swdraw. 2010-07-15 17:15:54 -04:00
Tom Rothamel e7eb23ab5e Create layout.yesno_screen function.
Doc update.

Bump to 6.11.0d.
2010-07-14 21:47:46 -04:00
Tom Rothamel 05dd8bfcc7 Use "screen" as the screen type and mouse for screens. 2010-07-14 20:39:30 -04:00
Tom Rothamel 2c299ab079 Share code between fullscreen and displayable versions of video playback. 2010-07-14 19:00:33 -04:00
Tom Rothamel 62acff5c75 CTRL on startup aborts OpenGL mode. 2010-07-14 01:22:40 -04:00
Tom Rothamel 316d146893 Make imagedissolve use the correct texture units. 2010-07-13 22:28:41 -04:00
Tom Rothamel e69fee2108 Auto-vivification of styles.
New styles.
2010-07-13 01:09:14 -04:00
Tom Rothamel 8fe6e1cf20 Add group argument to ui functions. 2010-07-13 00:27:48 -04:00
Tom Rothamel 6fcf7dbbba Blacklist Mesa Indirect GLX renderer. 2010-07-12 21:13:32 -04:00
Tom Rothamel f55c5f0ce5 Make screen language automatically prefix unicode-containing strings with u"" - like we do for other strings. 2010-07-12 20:42:32 -04:00
Tom Rothamel aaf8369421 Deallocate textures on shutdown. 2010-07-12 20:40:41 -04:00
Tom Rothamel 8e26c7730c Finish has rename.
Fix bugs with screens.
2010-07-11 22:46:19 -04:00
Tom Rothamel 556ca0611a Add has statement. 2010-07-11 17:25:46 -04:00
Tom Rothamel e2e78c175b Tweak the parser so that it recognizes \$ as a word unto itself. 2010-07-11 15:14:44 -04:00
Tom Rothamel 7b8033e6b2 A reference loop was preventing the weakref-based way of dealing with
PyCode from working. So instead, manually control when PyCodes are
recorded.
2010-07-11 13:04:44 -04:00
Tom Rothamel d602645fee Use button_text rather than default as the default button text style. 2010-07-11 11:57:06 -04:00
Tom Rothamel f8ac9c9e83 Bump version to 6.11.0c. 2010-07-10 16:06:22 -04:00
Tom Rothamel 98c90f8ab3 Shutdown trace.
Restrict minimum window size to 256x256.

Ensure window caption and icon are set when reiniting pygame.
2010-07-10 16:03:54 -04:00
Tom Rothamel 16bb21ee62 Always have an auto-forward length of 1. 2010-07-10 13:44:00 -04:00
Tom Rothamel 46bfec93d4 Set the window caption and icon whenenver we reinit the display. 2010-07-10 13:42:38 -04:00
Tom Rothamel 00e1ecf37d Fix DBZ protection. 2010-07-10 11:45:41 -04:00
Tom Rothamel a3e7b290fb Make references to PyCode weak, so that they are not compiled if they
do not live into the final game script.
2010-07-09 01:35:40 -04:00
Tom Rothamel 27ce59963f Document ui.detached, and make it work in an init block. 2010-07-09 01:02:10 -04:00
Tom Rothamel 54e3a97447 Play test sounds on the "sound" channel. 2010-07-09 00:36:41 -04:00
Tom Rothamel f886f710b7 Make video transient.
Fix most problems with ui.textbutton.
2010-07-09 00:06:30 -04:00
Tom Rothamel a895e1dc6c Always use copy RTT.
Deinitialize pygame on shutdown, and log that deinit, so we can notice where a crash there occurs.
2010-07-08 23:22:27 -04:00
181 changed files with 6522 additions and 5693 deletions
+10 -1
View File
@@ -49,7 +49,6 @@ renpygame-1.2.zip
speedtest
styles.txt
renpygame-demo/game/saves
./lib
Lucy Sprites.zip
translate
close_bugs.py
@@ -58,3 +57,13 @@ scite-6.10.zip
scite-renpy-20090803.zip
module/cython.sh
old_demo
opengl.txt
Microsoft.VC90.CRT.manifest
console.exe
msvcr90.dll
python26.dll
renpy.exe
lib/windows-x86
sphinx/source/inc/*
doc/*
updates/prerelease
+5 -3
View File
@@ -2,7 +2,7 @@
License
=======
Ren'Py itself is covered by the terms of the following (MIT) license:
Most of Ren'Py is covered by the terms of the following (MIT) license:
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
@@ -23,13 +23,15 @@ Ren'Py itself is covered by the terms of the following (MIT) license:
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Portions of Ren'Py are derived from code that is copyright using the
Lesser GNU Public License, so Ren'Py games must be distributed in a
manner that satisfies the LGPL.
Please see each individual source file for a list of copyright
holders. The artwork in the demo is released by various copyright
holders, under the same terms.
The Ren'Py module, the Ren'Py windows binaries, and the various Ren'Py
launchers may contain code taken from the following projects:
Ren'Py binaries include code from the following projects:
* Python (Python License)
* Pygame (LGPL)
-1
View File
@@ -1 +0,0 @@
dist/Microsoft.VC90.CRT.manifest
+2
View File
@@ -5,6 +5,8 @@ if [ "x$1" = "x" ]; then
exit
fi
rsync -av updates tom@onegeek.org:/home/tom/WWW.update/renpy/
mkdir ~/ab/website/renpy/dl/$1
cp dists/renpy-$1-* ~/ab/website/renpy/dl/$1
cp CHANGELOG.txt ~/ab/website/renpy/dl/$1
+30 -7
View File
@@ -6,15 +6,29 @@ import py2exe
import sys
import zipfile
import traceback
import os
# The pythonpath on my system.
sys.path.insert(0, 'c:\\msys\\1.0\\newbuild\\install\\bin')
sys.path.insert(0, 'c:\\msys\\1.0\\newbuild\\install\\python')
def move_from_dist(fn):
"""
Moves the file `fn` from the dist directory to the main
directory. (This means we don't need symlinks on windows.)
"""
if os.path.isdir(fn):
shutil.rmtree(fn)
elif os.path.exists(fn):
os.unlink(fn)
os.rename("dist/" + fn, fn)
def main():
sys.argv[1:] = [ 'py2exe', '--bundle', '2', '-a', '--dll-excludes', 'w9xpopen.exe', ]
# sys.argv[1:] = [ 'py2exe', '-a', '--dll-excludes', 'w9xpopen.exe', ]
sys.argv[1:] = [ 'py2exe', '-a', '--dll-excludes', 'w9xpopen.exe', ]
setup(name="Ren'Py",
windows=[ dict(script="renpy.py",
@@ -25,7 +39,7 @@ def main():
console=[ dict(script="renpy.py", dest_base="console") ],
zipfile='renpy.code',
zipfile='lib/windows-x86/renpy.code',
options={ 'py2exe' : { 'excludes' : [ 'doctest',
'pygame.macosx',
@@ -49,8 +63,8 @@ def main():
)
zfold = zipfile.ZipFile("dist/renpy.code")
zfnew = zipfile.ZipFile("renpy.code", "w", zipfile.ZIP_STORED)
zfold = zipfile.ZipFile("dist/lib/windows-x86/renpy.code")
zfnew = zipfile.ZipFile("dist/lib/windows-x86/renpy.code.new", "w", zipfile.ZIP_STORED)
seen = { }
@@ -71,8 +85,17 @@ def main():
zfold.close()
zfnew.close()
shutil.copy("c:/Python26/Microsoft.VC90.CRT.manifest", "dist/Microsoft.VC90.CRT.manifest")
shutil.copy("c:/Python26/msvcr90.dll", "dist/msvcr90.dll")
os.unlink("dist/lib/windows-x86/renpy.code")
os.rename("dist/lib/windows-x86/renpy.code.new", "dist/lib/windows-x86/renpy.code")
shutil.copy("c:/Python26/Microsoft.VC90.CRT.manifest", "Microsoft.VC90.CRT.manifest")
shutil.copy("c:/Python26/msvcr90.dll", "msvcr90.dll")
move_from_dist("lib/windows-x86")
move_from_dist("console.exe")
move_from_dist("python26.dll")
move_from_dist("renpy.exe")
try:
main()
-84
View File
@@ -1,84 +0,0 @@
1#!/usr/bin/env python
import collections
import glob
import re
import sys
import time
# A map from string to filename, line number where the string is found.
strings = collections.defaultdict(list)
def process(fn):
lineno = 0
for data in file(fn, "r"):
lineno += 1
matches = [ ]
matches += re.finditer(r'\bu\"(\\"|[^"])+\"', data)
matches += re.finditer(r"\bu\'(\\'|[^'])+\'", data)
for m in matches:
s = m.group(0)[2:-1]
if "\\u" in s:
continue
if len(s) == 1:
continue
strings[s].append("%s:%d" % (fn, lineno))
if __name__ == "__main__":
files = [ ]
files += glob.glob("launcher2/*.rpy")
files += glob.glob("common/*.rpy")
files += glob.glob("common/_layout/*.rpym")
files += glob.glob("common/_compat/*.rpym")
for fn in files:
process(fn)
converse = [ ]
for k, v in strings.iteritems():
v = " ".join(sorted(v))
converse.append((v, k))
converse.sort()
print """\
# Ren'Py Visual Novel Engine
# Copyright (C) 2009 PyTom <pytom@bishoujo.us>
# This file is distributed under the same license as the Ren'Py package.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: mainline\\n"
"Report-Msgid-Bugs-To: PyTom <pytom@bishoujo.us>\\n"
"POT-Creation-Date: %s\\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\\n"
"Language-Team: LANGUAGE <LL@li.org>\\n"
"MIME-Version: 1.0\\n"
"Content-Type: text/plain; charset=UTF-8\\n"
"Content-Transfer-Encoding: 8bit\\n"
""" % time.strftime("%Y-%m-%d %H:%M%z")
for v, k in converse:
print
print "#:", v
print "#, python-format"
print "msgid \"%s\"" % k
print "msgstr \"\""
+3
View File
@@ -41,6 +41,9 @@ init -1210 python:
config.default_transform = None
config.start_scene_black = True
if version <= (6, 11, 0):
config.movetransition_respects_offsets = False
init 1210 python hide::
+2 -2
View File
@@ -35,8 +35,8 @@ init -1110:
xpos 1.0 xanchor 0.0 ypos 1.0 yanchor 1.0
transform default:
reset
center
alpha 1 rotate None zoom 1 xzoom 1 yzoom 1 align (0, 0) alignaround (0, 0) subpixel False size None crop None
xpos 0.5 xanchor 0.5 ypos 1.0 yanchor 1.0
python:
config.default_transform = default
+180
View File
@@ -0,0 +1,180 @@
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
# See LICENSE.txt for license details.
# This contains code to choose between OpenGL and Software rendering, when
# a system supports both.
init -1024:
screen _gl_test:
frame:
xalign .5
yalign .33
xpadding 20
ypadding 20
has vbox
label _(u"Graphics Acceleration")
null height 10
textbutton _(u"Automatically Choose"):
size_group "gl"
action SetField(persistent, "_gl_test", "auto")
textbutton _(u"Prefer Software Renderer"):
size_group "gl"
action SetField(persistent, "_gl_test", "sw")
textbutton _(u"Prefer OpenGL Renderer"):
size_group "gl"
action SetField(persistent, "_gl_test", "gl")
null height 10
textbutton _(u"Continue"):
size_group "gl"
action Return(True)
init -1024 python:
# The image that we fill the screen with in GL-test mode.
config.gl_test_image = "black"
class __GLTest(renpy.Displayable):
"""
This counts the number of times it's been rendered, and
the number of seconds it's been displayed, and uses them
to make the decisions as to if OpenGL is working or not.
"""
def __init__(self, frames, fps, timeout):
super(__GLTest, self).__init__()
self.target = 1.0 * frames / fps
self.frames = frames
self.timeout = timeout
self.times = [ ]
self.success = False
def render(self, width, height, st, at):
self.times.append(st)
renpy.redraw(self, 0)
if len(self.times) >= self.frames:
if (self.times[-1] - self.times[-self.frames]) < self.target:
self.success = True
renpy.timeout(0)
rv = renpy.Render(width, height)
return rv
def event(self, ev, x, y, st):
if self.success:
return True
if st > self.timeout:
return False
renpy.timeout(self.timeout - st)
def __gl_prefer_renderers(renderers):
"""
Forces the current renderer to be renderer, one of gl or sw.
"""
if renpy.display.prefer_renderers == renderers:
return
renpy.display.prefer_renderers = renderers
renpy.display_reset()
def __gl_prompt():
"""
Decides if we want to prompt the user to enable OpenGL mode.
If so, shows a screen that allows the user to alter the
OpenGL setting.
"""
if not renpy.display.interface.safe_mode:
return
__gl_prefer_renderers("sw")
renpy.call_screen("_gl_test")
renpy.display.interface.safe_mode = False
def __gl_test():
"""
Makes the decision as to if we should use GL or SW mode.
"""
import os
if "RENPY_RENDERER" in os.environ:
return
# Our decision survives a restart.
if _restart:
return
# If GL is disabled, don't bother.
if not config.gl_enable:
return
__gl_prompt()
if persistent._gl_test == "gl":
__gl_prefer_renderers("gl,sw")
return
if persistent._gl_test == "sw":
__gl_prefer_renderers("sw")
return
__gl_prefer_renderers("gl,sw")
ui.pausebehavior(0)
ui.interact(suppress_underlay=True, suppress_overlay=True)
# If GL is able to render FRAMES frames at FPS fps in less
# than DELAY seconds, we consider it to be operational, and
# continue in GL mode. Otherwise, we rever to software
# rendering mode.
FRAMES = 5
FPS = 15
DELAY = 1
renpy.transition(Dissolve(DELAY), always=True, force=True)
ui.add(__GLTest(FRAMES, FPS, DELAY))
result = ui.interact(suppress_overlay=True, suppress_underlay=True)
if result:
__gl_prefer_renderers("gl,sw")
else:
__gl_prefer_renderers("sw")
# Init-time code:
# Make a guess as to what modes we should be in.
if persistent._gl_test is None:
persistent._gl_test = "auto"
if persistent._gl_test == "sw":
renpy.display.prefer_renderers = "sw"
label _gl_test:
# Show the test image.
scene
show expression config.gl_test_image
$ __gl_test()
# Hide the test image.
scene
return
+46 -2
View File
@@ -62,7 +62,7 @@ init -1105 python hide:
if renpy.has_screen("load") and renpy.has_screen("save"):
defaults["load_save"] = layout.screen_load_save
if renpy.has_screen("yesno"):
if renpy.has_screen("yesno_prompt"):
defaults["yesno_prompt"] = layout.screen_yesno_prompt
if renpy.has_screen("preferences"):
@@ -386,5 +386,49 @@ init -1105 python hide:
layout.QUIT = u"Are you sure you want to quit?"
layout.MAIN_MENU = u"Are you sure you want to return to the main menu?\nThis will lose unsaved progress."
@layout
def yesno_screen(message, yes=None, no=None):
"""
:doc: other
This causes the a yes/no prompt screen with the given message
to be displayed. The screen will be hidden when the user hits
yes or no.
`message`
The message that will be displayed.
`yes`
An action that is run when the user chooses yes.
`no`
An action that is run when the user chooses no.
"""
if renpy.has_screen("yesno_prompt"):
yes_action = [ Hide("yesno_prompt") ]
no_action = [ Hide("yesno_prompt") ]
if yes is not None:
yes_action.append(yes)
if no is not None:
no_action.append(no)
renpy.show_screen(
"yesno_prompt",
message=message,
yes_action=yes_action,
no_action=no_action)
renpy.restart_interaction()
return
if renpy.invoke_in_new_context(layout.yesno_prompt, None, message):
if yes is not None:
yes()
else:
if no is not None:
no()
+36 -12
View File
@@ -90,8 +90,20 @@ init -1180 python:
def _default_empty_window():
store.narrator("", interact=False)
who = _last_say_who
if who is not None:
who = eval(who)
if who is None:
who = narrator
if isinstance(who, NVLCharacter):
nvl_show_core()
else:
store.narrator("", interact=False)
config.empty_window = _default_empty_window
style.skip_indicator = Style(style.default, heavy=True, help='The skip indicator.')
@@ -139,19 +151,23 @@ init -1180 python:
config.help = None
def _help():
if not config.help:
def _help(help=None):
if help is None:
help = config.help
if help is None:
return
if renpy.has_label(config.help):
renpy.call_in_new_context(config.help)
if renpy.has_label(help):
renpy.call_in_new_context(help)
return
_preferences.fullscreen = False
try:
import webbrowser
webbrowser.open_new("file:///" + config.basedir + "/" + config.help)
webbrowser.open_new("file:///" + config.basedir + "/" + help)
except:
pass
@@ -200,7 +216,10 @@ init -1180 python hide:
def invoke_game_menu():
if renpy.context()._menu:
renpy.jump("_noisy_return")
if renpy.context()._main_menu:
return
else:
renpy.jump("_noisy_return")
else:
if config.game_menu_action:
renpy.display.behavior.run(config.game_menu_action)
@@ -406,7 +425,7 @@ init 1180 python:
_preferences.text_cps = config.default_text_cps
if config.default_afm_time is not None:
_preferences.default_afm_time = config.default_afm_time
_preferences.afm_time = config.default_afm_time
if config.default_afm_enable is not None:
_preferences.afm_enable = config.default_afm_enable
@@ -562,7 +581,7 @@ label _enter_menu:
renpy.context()._menu = True
# This may be changed, if we are already in the main menu.
renpy.context().main_menu = False
renpy.context()._main_menu = False
renpy.context_dynamic("main_menu")
renpy.context_dynamic("_window_subtitle")
renpy.context_dynamic("_window")
@@ -651,7 +670,7 @@ label _noisy_return:
# Return to the game.
label _return:
if renpy.context().main_menu:
if renpy.context()._main_menu:
$ renpy.transition(config.game_main_transition)
jump _main_menu_screen
@@ -685,6 +704,7 @@ init -1180 python hide:
# after_load.
label _after_load:
$ renpy.context()._menu = False
$ renpy.context()._main_menu = False
if config.after_load_transition:
$ renpy.transition(config.after_load_transition, force=True)
@@ -705,7 +725,11 @@ label _start:
for i in config.start_callbacks:
i()
$ renpy.block_rollback()
call _gl_test
call _load_reload_game from _call__load_reload_game_1
if not _restart and config.auto_load and renpy.can_load(config.auto_load):
@@ -777,7 +801,7 @@ label _main_menu(_main_menu_screen="_main_menu_screen"):
renpy.dynamic("_load_prompt")
_load_prompt = False
renpy.context().main_menu = True
renpy.context()._main_menu = True
store.main_menu = True
jump expression _main_menu_screen
+1 -1
View File
@@ -21,7 +21,7 @@ init -1130 python hide:
for i in xrange(0, 8):
renpy.music.register_channel(i)
renpy.music.register_channel("movie", "music", False, stop_on_mute=False)
renpy.music.register_channel("movie", "music", False, stop_on_mute=False, buffer_queue=False)
# Set up default names for some of the channels.
renpy.music.alias_channel(0, "sound")
+18 -20
View File
@@ -245,6 +245,7 @@ init -1100 python:
nvl_clear()
def do_extend(self):
renpy.mode(self.mode)
store.nvl_list = store.nvl_list[:-1]
# The default NVLCharacter.
@@ -254,6 +255,7 @@ init -1100 python:
what_style='nvl_dialogue',
window_style='nvl_entry',
type='nvl',
mode='nvl',
clear=False,
kind=adv)
@@ -265,6 +267,8 @@ init -1100 python:
def nvl_menu(items):
renpy.mode('nvl_menu')
if nvl_list is None:
store.nvl_list = [ ]
@@ -312,29 +316,23 @@ init -1100 python:
config.nvl_adv_transition = None
config.adv_nvl_transition = None
init 1140 python:
if config.nvl_adv_transition or config.adv_nvl_transition:
# This is used to execute the nvl and adv mode transitions.
def _nvl_adv_callback(mode, old_modes):
def _nvl_adv_callback(event, interact, type, **kwargs):
if event != "begin" or not interact or renpy.get_transition():
return
old_type = renpy.last_interact_type()
if old_type == "say" and type == "nvl":
# We have an extra line in the nvl_list as we do this. So
# take it out for the duration of the nvl_show.
old_nvl_list = store.nvl_list
store.nvl_list = old_nvl_list[:-1]
nvl_show(config.adv_nvl_transition)
store.nvl_list = old_nvl_list
elif old_type == "nvl" and type == "say":
nvl_hide(config.nvl_adv_transition)
config.all_character_callbacks.insert(0, _nvl_adv_callback)
old = old_modes[0]
if config.adv_nvl_transition:
if mode == "nvl" or mode == "nvl_menu":
if old == "say" or old == "menu":
nvl_show(config.adv_nvl_transition)
if config.nvl_adv_transition:
if mode == "say" or mode == "menu":
if old == "nvl" or old == "nvl_menu":
nvl_hide(config.nvl_adv_transition)
config.mode_callbacks.append(_nvl_adv_callback)
python early hide:
+162 -58
View File
@@ -2,30 +2,6 @@
init -1140 python:
def __yesno_prompt(message, yes=None, no=None):
if renpy.has_screen("yesno_prompt"):
yes_action = [ Hide("yesno_prompt") ]
no_action = [ Hide("yesno_prompt") ]
if yes is not None:
yes_action.append(yes)
if no is not None:
no_action.append(no)
renpy.display.show_screen(
"yesno_prompt",
message=message,
yes_action=yes_action,
no_action=no_action)
if renpy.invoke_in_new_context(layout.yesno_prompt, None, message):
if yes is not None:
yes()
else:
if no is not None:
no()
class Return(Action):
"""
:doc: control_action
@@ -37,13 +13,17 @@ init -1140 python:
When in a menu, this returns from the menu.
"""
def __init__(self, value=True):
def __init__(self, value=None):
self.value = value
def __call__(self):
if renpy.context()._main_menu:
ShowMenu("main_menu")()
if self.value is None:
if renpy.context()._main_menu:
ShowMenu("main_menu")()
else:
return True
else:
return self.value
@@ -71,14 +51,21 @@ init -1140 python:
This causes another screen to be shown. `screen` is a string
giving the name of the screen. The keyword arguments are
passed to the screen being shown.
If not None, `transition` is use to show the new screen.
"""
def __init__(self, screen, **kwargs):
def __init__(self, screen, transition=None, **kwargs):
self.screen = screen
self.kwargs = kwargs
self.transition = transition
def __call__(self):
renpy.show_screen(self.screen, **self.kwargs)
if self.transition is not None:
renpy.transition(self.transition)
renpy.restart_interaction()
def get_selected(self):
@@ -101,13 +88,21 @@ init -1140 python:
:doc: control_action
This causes the screen named `screen` to be hidden, if it is shown.
`transition`
If not None, a transition that occurs when hiding the screen.
"""
def __init__(self, screen):
def __init__(self, screen, transition=None):
self.screen = screen
self.transition = transition
def __call__(self):
renpy.hide_screen(self.screen)
if self.transition is not None:
renpy.transition(self.transition)
renpy.restart_interaction()
@@ -121,7 +116,45 @@ init -1140 python:
def __call__(self):
_screenshot()
def HideInterface():
"""
:doc other_action
Causes the interface to be hidden until the user clicks.
"""
return ui.callsinnewcontext("_hide_windows")
class With(Action):
"""
:doc: other_action
Causes `transition` to occur.
"""
def __init__(self, transition):
self.transition = transition
def __call__(self):
renpy.transition(self.transition)
renpy.restart_interaction()
class Notify(Action):
"""
:doc: other_action
Displays `message` using :func:`renpy.notify`.
"""
def __init__(self, message):
self.message = message
def __call__(self):
renpy.notify(self.message)
class InvertSelected(Action):
"""
:doc: other_action
@@ -145,7 +178,20 @@ init -1140 python:
def periodic(self, st):
return self.action.periodic(st)
def If(expression, true=None, false=None):
"""
:doc: other_action
This returns `true` if `expression` is true, and `false`
otherwise. Use this to select an action based on an expression.
Note that the default, None, can be used as an action that causes
a button to be disabled.
"""
if expression:
return true
else:
return false
##########################################################################
# Menu-related actions.
@@ -191,19 +237,24 @@ init -1140 python:
if not (renpy.has_screen(screen) or renpy.has_label(screen)):
screen = screen + "_screen"
# Ugly. We have different code depending on if we're in the
# game menu or not.
if renpy.context()._menu:
if renpy.has_screen(screen):
renpy.transition(config.intra_transition)
renpy.show_screen(screen, _transient=True)
renpy.restart_interaction()
elif renpy.has_label(screen):
renpy.transition(config.intra_transition)
renpy.scene(layer='screens')
ui.layer("screens")
ui.remove_above(None)
ui.close()
renpy.jump(screen)
else:
@@ -262,7 +313,7 @@ init -1140 python:
return
if self.confirm:
__yesno_prompt(layout.MAIN_MENU, MainMenu(False))
layout.yesno_screen(layout.MAIN_MENU, MainMenu(False))
else:
renpy.full_restart()
@@ -283,12 +334,13 @@ init -1140 python:
"""
def __init__(self, confirm=True):
self.confirm = True
self.confirm = confirm
def __call__(self):
if self.confirm:
__yesno_prompt(layout.QUIT, Quit(False))
renpy.loadsave.force_autosave()
layout.yesno_screen(layout.QUIT, Quit(False))
else:
renpy.quit()
@@ -317,10 +369,27 @@ init -1140 python:
def get_sensitive(self):
return config.allow_skipping and (not renpy.context()._main_menu)
class Help(Action):
"""
:doc: other_action
Displays help.
`help`
If this is a string giving a label in the programe, then
that label is called in a new context when the button is
chosen. Otherwise, it should be a string giving a file
that is opened in a web browser. If None, the value of
config.help is used in the same wayt.
"""
def __init__(self, help=None):
self.help = help
def AutoForward(Action):
return Preference("auto-forward")
def __call__(self):
_help(self.help)
##########################################################################
# Functions that set variables or fields.
@@ -345,7 +414,7 @@ init -1140 python:
def get_selected(self):
return getattr(self.object, self.field) == self.value
def SetVariable(variable, value):
"""
@@ -512,7 +581,7 @@ init -1140 python:
def get_selected(self):
return renpy.music.get_playing(self.channel) == self.file
def periodic(self):
def periodic(self, st):
if self.selected != self.get_selected():
renpy.restart_interaction()
@@ -637,7 +706,7 @@ init -1140 python:
if self.value == self.old_value:
return
fraction = st - (self.start_time) / self.delay
fraction = (st - self.start_time) / self.delay
fraction = min(1.0, fraction)
value = self.old_value + fraction * (self.value - self.old_value)
@@ -693,8 +762,8 @@ init -1140 python:
def changed(self, value):
if self.max_is_zero:
if value == 0:
value = self.range
if value == self.range:
value = 0
else:
value = value + 1
@@ -761,7 +830,7 @@ init -1140 python:
def get_adjustment(self):
w = renpy.get_widget(None, self.viewport)
if not isinstance(w, Viewport):
raise Exception("The displayable with id %r is not declared, or not a viewport.")
raise Exception("The displayable with id %r is not declared, or not a viewport." % self.viewport)
return w.xadjustment
@@ -783,7 +852,7 @@ init -1140 python:
def get_adjustment(self):
w = renpy.get_widget(None, self.viewport)
if not isinstance(w, Viewport):
raise Exception("The displayable with id %r is not declared, or not a viewport.")
raise Exception("The displayable with id %r is not declared, or not a viewport." % self.viewport)
return w.yadjustment
@@ -914,9 +983,9 @@ init -1140 python:
if renpy.scan_saved_game(fn):
if self.confirm:
__yesno_prompt(layout.OVERWRITE_SAVE, FileSave(self.name, False, self.newest, self.page))
layout.yesno_screen(layout.OVERWRITE_SAVE, FileSave(self.name, False, self.newest, self.page))
return
renpy.save(fn, extra_info=save_name)
if self.newest:
@@ -959,7 +1028,7 @@ init -1140 python:
if not renpy.context()._main_menu:
if self.confirm:
__yesno_prompt(layout.LOADING, FileLoad(self.name, False, self.page))
layout.yesno_screen(layout.LOADING, FileLoad(self.name, False, self.page))
return
renpy.load(fn)
@@ -993,7 +1062,7 @@ init -1140 python:
fn = __filename(self.name, self.page)
if self.confirm:
__yesno_prompt(layout.DELETE_SAVE, FileDelete(self.name, False, self.page))
layout.yesno_screen(layout.DELETE_SAVE, FileDelete(self.name, False, self.page))
return
renpy.unlink_save(fn)
@@ -1014,9 +1083,9 @@ init -1140 python:
"""
if renpy.current_screen().screen_name[0] == "load":
return FileLoad(name, page)
return FileLoad(name, page=page)
else:
return FileSave(name, page)
return FileSave(name, page=page)
class FilePage(Action):
@@ -1053,11 +1122,14 @@ init -1140 python:
"""
:doc: file_action
Goes to the next file page. (It's always possible to get to the
next file page.)
Goes to the next file page.
`max`
If set, this should be an integer that gives the number of
the maximum file page we can go to.
"""
def __init__(self):
def __init__(self, max=None):
page = persistent._file_page
@@ -1071,7 +1143,14 @@ init -1140 python:
page = "1"
else:
page = str(int(page) + 1)
page = int(page) + 1
if max is not None:
if page > max:
page = None
if page is not None:
page = str(page)
self.page = page
@@ -1082,6 +1161,9 @@ init -1140 python:
persistent._file_page = self.page
renpy.restart_interaction()
def get_sensitive(self):
return self.page is not None
class FilePagePrevious(Action):
"""
@@ -1334,7 +1416,7 @@ init -1140 python:
# What we do on a quit, by default.
config.quit_action = ShowMenu("_confirm_quit")
config.quit_action = ui.gamemenus("_confirm_quit")
# This is used to ensure a fixed click-to-continue indicator is shown on
@@ -1342,3 +1424,25 @@ init -1140 python:
screen _ctc:
add ctc
# These are used by renpy.notify.
transform _notify_transform:
# These control the position.
xalign .02 yalign .015
# These control the actions on show and hide.
on show:
alpha 0
linear .25 alpha 1.0
on hide:
linear .5 alpha 0.0
screen notify:
zorder 100
text message at _notify_transform
# This controls how long it takes between when the screen is
# first shown, and when it begins hiding.
timer 3.25 action Hide('notify')
+17 -9
View File
@@ -137,19 +137,24 @@ python early hide:
def predict_play_music(p):
return [ ]
def lint_play_music(p):
def lint_play_music(p, channel="music"):
file = _try_eval(p["file"], 'filename')
if p["channel"] is not None:
_try_eval(p["channel"], 'channel')
if p["channel"] is not None:
channel = _try_eval(p["channel"], 'channel')
if not isinstance(file, list):
file = [ file ]
for fn in file:
if isinstance(fn, basestring) and not renpy.loadable(fn):
renpy.error("%r is not loadable" % fn)
if isinstance(fn, basestring):
try:
if not renpy.music.playable(fn, channel):
renpy.error("%r is not loadable" % fn)
except:
pass
renpy.statements.register('play music',
parse=parse_play_music,
execute=execute_play_music,
@@ -254,11 +259,14 @@ python early hide:
fadeout=fadeout,
fadein=eval(p["fadein"]),
channel=channel)
def lint_play_sound(p, lint_play_music=lint_play_music):
return lint_play_music(p, channel="sound")
renpy.statements.register('play sound',
parse=parse_play_music,
execute=execute_play_sound,
lint=lint_play_music)
lint=lint_play_sound)
def execute_queue_sound(p):
if p["channel"] is not None:
@@ -334,7 +342,7 @@ python early hide:
if not renpy.music.channel_defined(channel):
renpy.error("channel %r is not defined" % channel)
lint_play_music(p)
lint_play_music(p, channel)
def lint_stop_generic(p):
channel = eval(p["channel"])
+8 -3
View File
@@ -22,10 +22,14 @@ init -1200 python hide:
# Style Declarations #################################################
style.default = Style(None, help='root of style hierarchy')
style.text = Style(style.default, help='style of text')
style.fixed = Style(style.default, help='fixed layouts')
style.hbox = Style(style.default, help='horizontal boxes')
style.vbox = Style(style.default, help='vertical boxes')
style.grid = Style(style.default, help='grid layouts')
style.side = Style(style.default, help='side layouts')
style.window = Style(style.default, help='windows created with ui.window')
style.image_placement = Style(style.default, help='default placement of images on the screen')
@@ -50,7 +54,8 @@ init -1200 python hide:
style.menu_choice_chosen_button = Style(style.menu_choice_button, help='buttons containing chosen in-game menu choices')
style.menu_window = Style(style.window, help='a window containing a menu')
style.input_text = Style(style.default, help='text of an input box')
style.input = Style(style.default, help='style of an input control')
style.input_text = Style(style.input, help='text of an input box')
style.input_prompt = Style(style.default, help='prompt of an input box')
style.input_window = Style(style.window, help='window of an input box')
@@ -235,7 +240,7 @@ init -1090 python:
# Menus.
style.menu_choice.idle_color = "#0ff"
style.menu_choice.hover_color = "#ff0"
style.input_text.color = "#ff0"
style.input.color = "#ff0"
# Styles used by centered.
style.centered_window.xalign = 0.5
+306 -281
View File
@@ -71,9 +71,7 @@ init -1110 python hide:
style.vscrollbar.bar_vertical = True
style.vscrollbar.bar_invert = True
# This recolors the given image using one or two colors.
@theme
def OneOrTwoColor(image, color):
@@ -82,246 +80,68 @@ init -1110 python hide:
else:
return im.Twocolor(image, color, color)
@theme
def roundrect_frames(
less_rounded,
frame):
def roundrect_based_theme(name, file_prefix, Box=None, frame_png=None):
theme.clear_frames()
style.frame.background = RoundRect(frame, less_rounded)
if Box is None:
def Box(color, ignored):
return Frame(theme.OneOrTwoColor(file_prefix + "_box.png", color), 12, 12)
style.frame.xpadding = 6
style.frame.ypadding = 6
if frame_png is not None:
def FrameBox(color, ignored):
return Frame(theme.OneOrTwoColor(file_prefix + frame_png, color), 12, 12)
else:
FrameBox = Box
@theme
def roundrect_buttons(text_size,
less_rounded,
widget,
widget_hover,
widget_text,
widget_selected,
disabled,
disabled_text):
theme.clear_buttons()
style.button.background = RoundRect(widget, less_rounded)
style.button.hover_background = RoundRect(widget_hover, less_rounded)
style.button.insensitive_background = RoundRect(disabled, less_rounded)
style.button_text.size = text_size
style.button_text.color = widget_text
style.button_text.selected_color = widget_selected
style.button_text.insensitive_color = disabled_text
if less_rounded:
style.button.xpadding = 6
else:
style.button.xpadding = 12
style.button.ypadding = 1
style.button.xmargin = 1
style.button.ymargin = 1
style.button_text.xalign = 0.5
style.button_text.yalign = 0.5
style.button_text.text_align = 0.5
@theme
def roundrect_large_buttons(
text_size,
less_rounded,
widget,
widget_hover,
widget_text,
widget_selected,
disabled,
disabled_text):
theme.clear_large_buttons()
if less_rounded:
style.large_button.xpadding = 6
else:
style.large_button.xpadding = 12
style.large_button.ypadding = 1
style.large_button.xmargin = 1
style.large_button.ymargin = 1
style.large_button.background = RoundRect(widget, less_rounded)
style.large_button.hover_background = RoundRect(widget_hover, less_rounded)
style.large_button.insensitive_background = RoundRect(disabled, less_rounded)
style.large_button_text.size = text_size
style.large_button_text.color = widget_text
style.large_button_text.selected_color = widget_selected
style.large_button_text.insensitive_color = disabled_text
style.large_button_text.xalign = 0
style.large_button_text.yalign = 0
@theme
def roundrect_labels(
text_size,
label):
theme.clear_labels()
style.label_text.size = text_size
style.label_text.color = label
@theme
def roundrect_prompts(
text_size,
label):
theme.clear_prompts()
style.prompt_text.size = text_size
style.prompt_text.color = label
style.prompt.xalign = 0.5
style.prompt_text.text_align = 0.5
style.prompt_text.layout = "subtitle"
@theme
def roundrect_bars(
widget,
widget_hover):
theme.clear_bars()
def img(name, color, x, y):
rv = theme.OneOrTwoColor("_roundrect/" + name + ".png", color)
if x is not None:
rv = Frame(rv, x, y)
return rv
# Bars.
style.bar.ymaximum = 24
style.bar.left_gutter = 6
style.bar.right_gutter = 6
style.bar.thumb_offset = 6
style.bar.left_bar = img("rrslider_full", widget, 12, 0)
style.bar.right_bar = img("rrslider_empty", widget, 12, 0)
style.bar.thumb = img("rrslider_thumb", widget, None, None)
style.bar.hover_left_bar = img("rrslider_full", widget_hover, 12, 0)
style.bar.hover_right_bar = img("rrslider_empty", widget_hover, 12, 0)
style.bar.hover_thumb = img("rrslider_thumb", widget_hover, None, None)
style.vbar.xmaximum = 24
style.vbar.top_gutter = 6
style.vbar.bottom_gutter = 6
style.vbar.thumb_offset = 6
style.vbar.bottom_bar = img("rrvslider_full", widget, 0, 12)
style.vbar.top_bar = img("rrvslider_empty", widget, 0, 12)
style.vbar.thumb = img("rrvslider_thumb", widget, None, None)
style.vbar.hover_bottom_bar = img("rrvslider_full", widget_hover, 0, 12)
style.vbar.hover_top_bar = img("rrvslider_empty", widget_hover, 0, 12)
style.vbar.hover_thumb = img("rrvslider_thumb", widget_hover, None, None)
# Sliders.
style.slider.ymaximum = 24
style.slider.left_gutter = 6
style.slider.right_gutter = 6
style.slider.thumb_offset = 6
style.slider.left_bar = img("rrslider_full", widget, 12, 0)
style.slider.right_bar = img("rrslider_empty", widget, 12, 0)
style.slider.thumb = img("rrslider_thumb", widget, None, None)
style.slider.hover_left_bar = img("rrslider_full", widget_hover, 12, 0)
style.slider.hover_right_bar = img("rrslider_empty", widget_hover, 12, 0)
style.slider.hover_thumb = img("rrslider_thumb", widget_hover, None, None)
style.vslider.xmaximum = 24
style.vslider.top_gutter = 6
style.vslider.bottom_gutter = 6
style.vslider.thumb_offset = 6
style.vslider.bottom_bar = img("rrvslider_full", widget, 0, 12)
style.vslider.top_bar = img("rrvslider_empty", widget, 0, 12)
style.vslider.thumb = img("rrvslider_thumb", widget, None, None)
style.vslider.hover_bottom_bar = img("rrvslider_full", widget_hover, 0, 12)
style.vslider.hover_top_bar = img("rrvslider_empty", widget_hover, 0, 12)
style.vslider.hover_thumb = img("rrvslider_thumb", widget_hover, None, None)
# Scrollbars.
style.scrollbar.left_gutter = 6
style.scrollbar.right_gutter = 6
style.scrollbar.thumb_offset = 6
style.scrollbar.ymaximum = 12
style.scrollbar.left_bar = img("rrscrollbar", widget, 12, 0)
style.scrollbar.right_bar = img("rrscrollbar", widget, 12, 0)
style.scrollbar.thumb = img("rrscrollbar_thumb", widget, None, None)
style.scrollbar.hover_left_bar = img("rrscrollbar", widget_hover, 12, 0)
style.scrollbar.hover_right_bar = img("rrscrollbar", widget_hover, 12, 0)
style.scrollbar.hover_thumb = img("rrscrollbar_thumb", widget_hover, None, None)
style.vscrollbar.top_gutter = 6
style.vscrollbar.bottom_gutter = 6
style.vscrollbar.thumb_offset = 6
style.vscrollbar.xmaximum = 12
style.vscrollbar.left_bar = img("rrvscrollbar", widget, 0, 12)
style.vscrollbar.right_bar = img("rrvscrollbar", widget, 0, 12)
style.vscrollbar.thumb = img("rrvscrollbar_thumb", widget, None, None)
style.vscrollbar.hover_left_bar = img("rrvscrollbar", widget_hover, 0, 12)
style.vscrollbar.hover_right_bar = img("rrvscrollbar", widget_hover, 0, 12)
style.vscrollbar.hover_thumb = img("rrvscrollbar_thumb", widget_hover, None, None)
@theme
def roundrect(
widget = (0, 60, 120, 255),
widget_hover = (0, 80, 160, 255),
widget_text = (200, 225, 255, 255),
widget_selected = (255, 255, 200, 255),
disabled = (64, 64, 64, 255),
disabled_text = (200, 200, 200, 255),
label = (255, 255, 255, 255),
frame = (100, 150, 200, 255),
text_size=None,
small_text_size=None,
less_rounded = False,
# Compat for the old roundrect theme.
window = None,
button_menu = None,
rounded_window = True,
outline_bars = False,
mm_root = None,
gm_root = None):
if button_menu is None:
if (config.script_version is not None) and (config.script_version < (6, 9, 0)):
button_menu = True
else:
button_menu = False
layout.defaults()
if config.screen_width <= 640:
text_size = text_size or 18
small_text_size = small_text_size or 12
less_rounded = True
else:
text_size = text_size or 22
small_text_size = small_text_size or 16
radius = 12
theme.roundrect_frames(
def frames(
less_rounded,
frame)
frame):
theme.roundrect_buttons(
theme.clear_frames()
style.frame.background = Box(frame, less_rounded)
style.frame.xpadding = 6
style.frame.ypadding = 6
setattr(theme, name + "_frames", frames)
def buttons(text_size,
less_rounded,
widget,
widget_hover,
widget_text,
widget_selected,
disabled,
disabled_text):
theme.clear_buttons()
style.button.background = Box(widget, less_rounded)
style.button.hover_background = Box(widget_hover, less_rounded)
style.button.insensitive_background = Box(disabled, less_rounded)
style.button_text.size = text_size
style.button_text.color = widget_text
style.button_text.selected_color = widget_selected
style.button_text.insensitive_color = disabled_text
if less_rounded:
style.button.xpadding = 6
else:
style.button.xpadding = 12
style.button.ypadding = 1
style.button.xmargin = 1
style.button.ymargin = 1
style.button_text.xalign = 0.5
style.button_text.yalign = 0.5
style.button_text.text_align = 0.5
setattr(theme, name + "_buttons", buttons)
def large_buttons(
text_size,
less_rounded,
widget,
@@ -329,55 +149,260 @@ init -1110 python hide:
widget_text,
widget_selected,
disabled,
disabled_text)
disabled_text):
theme.roundrect_large_buttons(
small_text_size,
less_rounded,
widget,
widget_hover,
widget_text,
widget_selected,
disabled,
disabled_text)
theme.clear_large_buttons()
theme.roundrect_labels(
text_size,
label)
theme.roundrect_prompts(
text_size,
label)
theme.roundrect_bars(
widget,
widget_hover)
if mm_root is not None:
style.mm_root.background = mm_root
if gm_root is not None:
style.gm_root.background = gm_root
if window is not None:
if rounded_window:
style.window.background = RoundRect(window, less_rounded)
style.window.xpadding = 6
style.window.xmargin = 6
style.window.ypadding = 6
style.window.ymargin = 6
if less_rounded:
style.large_button.xpadding = 6
else:
style.window.background = Solid(window)
style.window.xpadding = 6
style.window.xmargin = 0
style.window.ypadding = 6
style.window.ymargin = 0
style.large_button.xpadding = 12
style.large_button.ypadding = 1
style.large_button.xmargin = 1
style.large_button.ymargin = 1
style.large_button.background = Box(widget, less_rounded)
style.large_button.hover_background = Box(widget_hover, less_rounded)
style.large_button.insensitive_background = Box(disabled, less_rounded)
style.large_button_text.size = text_size
style.large_button_text.color = widget_text
style.large_button_text.selected_color = widget_selected
style.large_button_text.insensitive_color = disabled_text
style.large_button_text.xalign = 0
style.large_button_text.yalign = 0
setattr(theme, name + "_large_buttons", large_buttons)
def labels(
text_size,
label):
theme.clear_labels()
style.label_text.size = text_size
style.label_text.color = label
setattr(theme, name + "_labels", labels)
def prompts(
text_size,
label):
theme.clear_prompts()
style.prompt_text.size = text_size
style.prompt_text.color = label
style.prompt.xalign = 0.5
style.prompt_text.text_align = 0.5
style.prompt_text.layout = "subtitle"
setattr(theme, name + "_prompts", prompts)
def bars(
widget,
widget_hover):
theme.clear_bars()
def img(name, color, x, y):
rv = theme.OneOrTwoColor(file_prefix + name + ".png", color)
if x is not None:
rv = Frame(rv, x, y, tile=True)
return rv
# Bars.
style.bar.ymaximum = 24
style.bar.left_gutter = 6
style.bar.right_gutter = 6
style.bar.thumb_offset = 6
style.bar.left_bar = img("slider_full", widget, 12, 0)
style.bar.right_bar = img("slider_empty", widget, 12, 0)
style.bar.thumb = img("slider_thumb", widget, None, None)
style.bar.hover_left_bar = img("slider_full", widget_hover, 12, 0)
style.bar.hover_right_bar = img("slider_empty", widget_hover, 12, 0)
style.bar.hover_thumb = img("slider_thumb", widget_hover, None, None)
style.vbar.xmaximum = 24
style.vbar.top_gutter = 6
style.vbar.bottom_gutter = 6
style.vbar.thumb_offset = 6
style.vbar.bottom_bar = img("vslider_full", widget, 0, 12)
style.vbar.top_bar = img("vslider_empty", widget, 0, 12)
style.vbar.thumb = img("vslider_thumb", widget, None, None)
style.vbar.hover_bottom_bar = img("vslider_full", widget_hover, 0, 12)
style.vbar.hover_top_bar = img("vslider_empty", widget_hover, 0, 12)
style.vbar.hover_thumb = img("vslider_thumb", widget_hover, None, None)
# Sliders.
style.slider.ymaximum = 24
style.slider.left_gutter = 6
style.slider.right_gutter = 6
style.slider.thumb_offset = 6
style.slider.left_bar = img("slider_full", widget, 12, 0)
style.slider.right_bar = img("slider_empty", widget, 12, 0)
style.slider.thumb = img("slider_thumb", widget, None, None)
style.slider.hover_left_bar = img("slider_full", widget_hover, 12, 0)
style.slider.hover_right_bar = img("slider_empty", widget_hover, 12, 0)
style.slider.hover_thumb = img("slider_thumb", widget_hover, None, None)
style.vslider.xmaximum = 24
style.vslider.top_gutter = 6
style.vslider.bottom_gutter = 6
style.vslider.thumb_offset = 6
style.vslider.bottom_bar = img("vslider_full", widget, 0, 12)
style.vslider.top_bar = img("vslider_empty", widget, 0, 12)
style.vslider.thumb = img("vslider_thumb", widget, None, None)
style.vslider.hover_bottom_bar = img("vslider_full", widget_hover, 0, 12)
style.vslider.hover_top_bar = img("vslider_empty", widget_hover, 0, 12)
style.vslider.hover_thumb = img("vslider_thumb", widget_hover, None, None)
if button_menu:
layout.button_menu()
# Scrollbars.
style.scrollbar.left_gutter = 6
style.scrollbar.right_gutter = 6
style.scrollbar.thumb_offset = 6
style.scrollbar.ymaximum = 12
style.scrollbar.left_bar = img("scrollbar", widget, 12, 0)
style.scrollbar.right_bar = img("scrollbar", widget, 12, 0)
style.scrollbar.thumb = img("scrollbar_thumb", widget, None, None)
style.scrollbar.hover_left_bar = img("scrollbar", widget_hover, 12, 0)
style.scrollbar.hover_right_bar = img("scrollbar", widget_hover, 12, 0)
style.scrollbar.hover_thumb = img("scrollbar_thumb", widget_hover, None, None)
style.vscrollbar.top_gutter = 6
style.vscrollbar.bottom_gutter = 6
style.vscrollbar.thumb_offset = 6
style.vscrollbar.xmaximum = 12
style.vscrollbar.left_bar = img("vscrollbar", widget, 0, 12)
style.vscrollbar.right_bar = img("vscrollbar", widget, 0, 12)
style.vscrollbar.thumb = img("vscrollbar_thumb", widget, None, None)
style.vscrollbar.hover_left_bar = img("vscrollbar", widget_hover, 0, 12)
style.vscrollbar.hover_right_bar = img("vscrollbar", widget_hover, 0, 12)
style.vscrollbar.hover_thumb = img("vscrollbar_thumb", widget_hover, None, None)
setattr(theme, name + "_bars", bars)
def main(
widget = (0, 60, 120, 255),
widget_hover = (0, 80, 160, 255),
widget_text = (200, 225, 255, 255),
widget_selected = (255, 255, 200, 255),
disabled = (64, 64, 64, 255),
disabled_text = (200, 200, 200, 255),
label = (255, 255, 255, 255),
frame = (100, 150, 200, 255),
text_size=None,
small_text_size=None,
less_rounded = False,
# Compat for the old roundrect theme.
window = None,
button_menu = None,
rounded_window = True,
outline_bars = False,
mm_root = None,
gm_root = None):
if button_menu is None:
if (config.script_version is not None) and (config.script_version < (6, 9, 0)):
button_menu = True
else:
button_menu = False
layout.defaults()
if config.screen_width <= 640:
text_size = text_size or 18
small_text_size = small_text_size or 12
less_rounded = True
else:
text_size = text_size or 22
small_text_size = small_text_size or 16
radius = 12
frames(
less_rounded,
frame)
buttons(
text_size,
less_rounded,
widget,
widget_hover,
widget_text,
widget_selected,
disabled,
disabled_text)
large_buttons(
small_text_size,
less_rounded,
widget,
widget_hover,
widget_text,
widget_selected,
disabled,
disabled_text)
labels(
text_size,
label)
prompts(
text_size,
label)
bars(
widget,
widget_hover)
if mm_root is not None:
style.mm_root.background = mm_root
if gm_root is not None:
style.gm_root.background = gm_root
if window is not None:
if rounded_window:
style.window.background = RoundRect(window, less_rounded)
style.window.xpadding = 6
style.window.xmargin = 6
style.window.ypadding = 6
style.window.ymargin = 6
else:
style.window.background = Solid(window)
style.window.xpadding = 6
style.window.xmargin = 0
style.window.ypadding = 6
style.window.ymargin = 0
if button_menu:
layout.button_menu()
setattr(theme, name, main)
roundrect_based_theme("roundrect", "_roundrect/rr", RoundRect)
roundrect_based_theme("bordered", "_theme_bordered/br")
roundrect_based_theme("diamond", "_theme_diamond/d")
roundrect_based_theme("tv", "_theme_tv/t")
roundrect_based_theme("glow", "_theme_glow/g", None, "_outline.png")
@theme
def ancient():
+53 -24
View File
@@ -1,29 +1,34 @@
# This file contains code that helps support the development of Ren'Py
# games.
screen _developer:
window style "gm_root"
frame:
style_group "_developer"
align (.025, .05)
has vbox:
first_spacing 10
label "Developer Menu"
textbutton _(u"Return") action Return()
textbutton _(u"Reload Game (Shift + R)") action ui.callsinnewcontext("_save_reload_game")
textbutton _(u"Variable Viewer") action Jump("_debugger_screen")
textbutton _(u"Theme Test") action Jump("_theme_test")
textbutton _(u"Style Hierarchy") action Jump("_style_hierarchy")
textbutton _(u"Image Location Picker") action Jump("_image_location_picker")
textbutton _(u"Filename List") action Jump("_filename_list")
init python hide:
style._developer_button = Style(style.button)
style._developer_button.size_group = "_developer"
label _developer_screen:
python hide:
ui.window(style=style.gm_root)
ui.null()
ui.frame(xpos=10, ypos=10, style=style.menu_frame)
ui.vbox(box_first_spacing=10)
layout.label(u"Developer Menu", None)
sg = "developer_menu"
layout.button(u"Return", None, clicked=ui.returns(True), size_group=sg)
layout.button(u"Reload Game (Shift+R)", None, clicked=ui.callsinnewcontext("_save_reload_game"), size_group=sg)
layout.button(u"Variable Viewer", None, clicked=ui.jumps("_debugger_screen"), size_group=sg)
layout.button(u"Theme Test", None, clicked=ui.jumps("_theme_test"), size_group=sg)
layout.button(u"Style Hierarchy", None, clicked=ui.jumps("_style_hierarchy"), size_group=sg)
# layout.button(u"FPS Meter", None, clicked=ui.jumps("_fps_meter"), size_group=sg)
layout.button(u"Image Location Picker", None, clicked=ui.jumps("_image_location_picker"), size_group=sg)
ui.close()
ui.interact()
call screen _developer
return
@@ -92,7 +97,7 @@ label _theme_test:
return ""
toggle_var = True
adj = ui.adjustment(100, 25, page=25)
adj = ui.adjustment(100, 25, page=25, adjustable=True)
while True:
@@ -369,8 +374,8 @@ init python:
sr = renpy.render(Solid("#0ff4"), w, h, st, at)
rv.blit(sr, (minx, miny))
text.append("Imagemap rectangle: %r" % ((minx, miny, maxx, maxy),))
text.append("Cropping rectangle: %r" % ((minx, miny, w, h),))
# text.append("Imagemap rectangle: %r" % ((minx, miny, maxx, maxy),))
text.append("Rectangle: %r" % ((minx, miny, w, h),))
if self.mouse:
mx, my = self.mouse
@@ -466,6 +471,30 @@ label _image_location_picker:
renpy.jump("_image_location_picker")
label _filename_list:
python hide:
import os
f = file("files.txt", "w")
for dirname, dirs, files in os.walk(config.gamedir):
dirs.sort()
files.sort()
for fn in files:
fn = os.path.join(dirname, fn)
fn = fn[len(config.gamedir) + 1:]
print >>f, fn
print fn
f.close()
renpy.launch_editor(["files.txt"], transient=1)
jump _developer_screen
init python:
config.underlay.append(im.Tile("_transparent_tile.png"))
@@ -133,7 +133,7 @@ init python:
a channel.
"""
def __init__(self, name, mixer, enable='True', sound='None', channel=0):
def __init__(self, name, mixer, enable='True', sound='None', channel="sound"):
"""
@param name: The name of this preference, as shown to the user.
@@ -360,15 +360,18 @@ init python hide:
_VolumePreference(u"Music Volume",
'music',
'config.has_music')
_VolumePreference(u"Sound Volume",
'sfx',
'config.has_sound',
'config.sample_sound')
'config.sample_sound',
'sound')
_VolumePreference(u'Voice Volume',
'voice',
'config.has_voice',
'config.sample_voice',
2)
'voice')
_JumpPreference(u'Joystick...',
'joystick_preferences_screen',
+2 -2
View File
@@ -77,12 +77,12 @@ init python:
ime.button("Joystick", ui.jumps("joystick_preferences_screen"), False)
def play_sound():
renpy.sound.play(config.sample_sound)
renpy.music.play(config.sample_sound, channel="sound")
ime.button("Sound Test", play_sound, False)
def play_voice():
renpy.sound.play(config.sample_sound, channel=2)
renpy.music.play(config.sample_sound, channel="voice")
ime.button("Voice Test", play_voice, False)
Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 489 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 359 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 763 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 524 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 781 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 545 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 611 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 460 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 816 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 529 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 315 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 408 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

-1
View File
@@ -1 +0,0 @@
dist/console.exe
+43 -34
View File
@@ -9,6 +9,9 @@ import time
import zlib
import compileall
import shutil
import subprocess
import makeupdate
import time
zlib.Z_DEFAULT_COMPRESSION = 9
@@ -20,7 +23,7 @@ def data(fn):
if fn.startswith("renpy.app"):
return rv
if fn.endswith(".rpy") or fn.endswith(".py") or fn.endswith(".txt"):
if fn.endswith(".rpy") or fn.endswith(".rpym") or fn.endswith(".py") or fn.endswith(".txt"):
rv = rv.replace("\n", "\r\n")
rv = rv.replace("\r\r\n", "\r\n")
@@ -87,7 +90,11 @@ def tree(root):
if ".svn" in dirs:
dirs.remove(".svn")
if ".doctrees" in dirs:
dirs.remove(".doctrees")
for f in filenames:
if f[-1] == '~' or f[0] == '.':
continue
@@ -113,41 +120,44 @@ def main():
prefix = sys.argv[1]
# Update the update-version.txt file.
p = subprocess.Popen(["bzr", "revno"], stdout=subprocess.PIPE)
revno = p.stdout.read().strip() + "-" + str(time.time())
p.wait()
f = file("lib/update-version.txt", "w")
f.write(revno + " base\n")
f.close()
# Compile all the python files.
compileall.compile_dir("renpy/", ddir=prefix + "/renpy/", force=1)
os.environ['RENPY_PATH_ELIDE'] = '/home/tom/ab/renpy:' + prefix
# Chmod the mac app.
os.chmod("./renpy.app/Contents/MacOS/Ren'Py Launcher", 0755)
# Chmod down renpy.py, for now.
os.chmod("renpy.py", 0644)
# Compile the various games
for i in [ 'tutorial/game', 'launcher', 'template/game', 'the_question/game' ]:
os.system("./renpy.sh --compile --game " + i)
files = [ ]
more_files = [ ]
files.append("CHANGELOG.txt")
files.append("LICENSE.txt")
files.extend(tree("common"))
more_files.append("console.exe")
files.extend(tree("launcher"))
files.extend(tree("tutorial"))
# files.extend(tree("dse"))
files.extend(tree("the_question"))
# editor = tree("editor")
# editor.remove("editor/scite.exe")
# files.append("editor/scite.exe")
# more_files.extend(editor)
more_files.extend(tree("jedit"))
# files.extend(tree("extras"))
more_files.extend(tree("lib"))
more_files.extend(tree("lib/linux-x86"))
module_files = [
"lib/pysdlsound/linmixer.py",
"lib/pysdlsound/__init__.py",
@@ -185,32 +195,20 @@ def main():
for i in module_files:
files.append('module/' + i)
files.extend(tree('renpy'))
files.append('renpy.py')
more_files.append('python26.dll')
more_files.append('msvcr90.dll')
more_files.append('Microsoft.VC90.CRT.manifest')
files.extend(tree('renpy'))
more_files.extend(tree('renpy.app'))
more_files.append('renpy.code')
more_files.append('renpy.exe')
files.append('renpy.py')
more_files.append('renpy.exe')
more_files.append("console.exe")
more_files.append('renpy.sh')
files.extend(tree('template'))
# files.extend(tree('tools'))
files.extend(tree('doc'))
# files.append('doc/index.html')
# files.append('doc/common.css')
# files.append('doc/docs.css')
# files.append('doc/monobook.css')
# files.append('doc/monobook2.css')
# files.append('doc/shared.css')
# files.extend(tree('doc/reference'))
# files.extend(tree('doc/tutorials'))
# files.extend(tree('doc/images'))
files.sort()
more_files.sort()
@@ -222,6 +220,7 @@ def main():
print "----"
tarup("dists/" + prefix + "-source.tar.bz2", prefix, files)
print "----"
# Make the 7zip.
os.chdir("dists")
os.system("unzip " + prefix + "-sdk.zip")
@@ -233,13 +232,23 @@ def main():
os.system("7z a " + prefix + "-sdk.7z " + prefix)
os.system("cat ../7z.sfx " + prefix + "-sdk.7z > " + prefix + "-sdk.7z.exe""")
shutil.rmtree(prefix)
os.unlink(prefix + "-sdk.7z")
os.chdir("..")
if os.path.exists("updates/prerelease"):
shutil.rmtree("updates/prerelease")
os.rename("dists/" + prefix, "updates/prerelease")
os.unlink("updates/prerelease/lib/update-version.txt")
makeupdate.make_update("updates/prerelease", revno)
os.chmod("renpy.py", 0755)
print
print "Did you remember to rebuild the exe after the last change?"
print "Did you run me with renpython -OO?"
print "Was ming using the right crt?"
print "Did you update renpy.py and launcher/script_version.rpy?"
print "Did you run with a RENPY_SCALE_FACTOR?"
+15 -17
View File
@@ -108,7 +108,7 @@ init python:
return rv
def switch_theme(name):
def switch_theme(theme_function, name):
"""
Switches the theme of the current project to the named theme.
"""
@@ -130,7 +130,7 @@ init python:
m = re.match(r' theme.(\w+)\(', l)
if m:
if m.group(1) in theme_functions:
l = theme_templates[td["theme"]] % td
l = theme_templates[theme_function] % td
changed = True
out.write(l + "\n")
@@ -160,29 +160,26 @@ init python:
##########################################################################
# Code that handles display.
current_theme_function = None
current_theme = None
def show_theme(name, target):
def show_theme(function, name, target):
"""
Changes from the current theme to the roundrect theme named
`name`.
Changes from the current theme to the theme named `name`.
"""
if current_theme == name:
if current_theme_function == function and current_theme == name:
return
store.current_theme_function = function
store.current_theme = name
td = theme_data[name].copy()
kind = td["theme"]
del td["theme"]
if kind == "roundrect":
td["rounded_window"] = False
td["rounded_window"] = False
renpy.style.restore(style_backup)
getattr(theme, kind)(**td)
getattr(theme, function)(**td)
customize_styles()
renpy.style.rebuild()
@@ -264,7 +261,7 @@ label repeat_choose_theme:
button(name,
ui.returns(function),
"",
hovered=curried_show_theme(exemplar, "repeat_choose_theme"),
hovered=curried_show_theme(function, exemplar, "repeat_choose_theme"),
unhovered=does_nothing)
ui.close() # vbox
@@ -292,7 +289,8 @@ label repeat_choose_color_scheme:
tip = _(u"Please choose a color scheme for your project.")
themes = [ k for k,v in theme_data.iteritems() if v["theme"] == theme_function ]
themes = theme_data.keys()
themes.sort()
screen()
@@ -307,9 +305,9 @@ label repeat_choose_color_scheme:
for i in themes:
button(i,
curried_switch_theme(i),
curried_switch_theme(theme_function, i),
"",
hovered=curried_show_theme(i, "repeat_choose_color_scheme"),
hovered=curried_show_theme(theme_function, i, "repeat_choose_color_scheme"),
unhovered=does_nothing)
ui.close() # vbox
+5 -2
View File
@@ -41,6 +41,7 @@ ignored_files = (
"thumbs.db",
"traceback.txt",
"errors.txt",
"files.txt",
"saves"
)
@@ -146,7 +147,7 @@ class MyZipFile(zipfile.ZipFile):
def tree(
src,
dest,
exclude_suffix=[ ".pyc", "~", ".bak" ],
exclude_suffix=[ ".pyc", "~", ".bak", ".old", ".new" ],
exclude_prefix=[ "#", "." ],
exclude_files = set(ignored_files),
root_exclude_prefix = [ ],
@@ -392,11 +393,13 @@ def distribute(
if build_windows or build_all:
win_files.append((rb + "renpy.exe", "/" + executable_name + ".exe"))
win_files.append((rb + "renpy.code", "/renpy.code"))
win_files.append((rb + "python26.dll", "/python26.dll"))
win_files.append((rb + "msvcr90.dll", "/msvcr90.dll"))
win_files.append((rb + "Microsoft.VC90.CRT.manifest", "/Microsoft.VC90.CRT.manifest"))
win_files.append((rb + "lib", "/lib"))
win_files.extend(tree(rb + "lib/windows-x86", "/lib/windows-x86"))
if os.path.exists(project_path + "/icon.ico"):
file_data[rb + "renpy.exe"] = change_icon.change_icons(
rb + "renpy.exe",
+21
View File
@@ -221,6 +221,27 @@ init 11 python:
interact()
def pauseinfo(t, message):
"""
Displays an error to the user, and lets him click to return to
`target`.
"""
set_tooltip("")
screen()
ui.vbox()
title(t)
text(message)
ui.null(height=20)
button(_(u"Ok"), ui.returns(True), None)
ui.close()
interact()
def info(t, message):
"""
Displays an informational message to the user, and immediately
+3
View File
@@ -100,6 +100,9 @@ init -1 python hide:
## Set this to False if the game does not have any sound effects.
config.sound = False
# Disable opengl.
config.gl_enable = False
python early:
config.save_directory = "launcher-2"
+47
View File
@@ -0,0 +1,47 @@
def k(s):
s = s.replace(" ", "")
s = s.replace(":", "")
s = s.replace("\n", "")
return int(s, 16)
modulus = k("""
00:c2:e6:31:c6:7d:b3:cf:57:12:91:cf:b4:2c:9d:
25:17:cf:21:f8:ac:5b:1d:c1:95:56:9d:1c:1c:d5:
eb:67:ca:0a:a4:3f:e5:9c:6c:10:6e:4a:7a:2c:c2:
d6:e3:3f:84:6d:b1:6f:70:3d:05:4e:06:91:3c:51:
28:3f:b1:26:a5:be:6e:a6:14:a1:09:95:87:10:4d:
c3:4b:44:fd:e0:a6:9d:f8:1f:50:ca:8a:0d:fd:86:
7d:39:74:af:af:4e:05:8b:bd:93:b5:9b:6a:85:ca:
1e:47:25:ca:f1:31:47:10:3e:a2:26:79:d2:00:34:
f4:c5:a8:db:b6:36:2b:70:ef:14:8c:44:41:02:11:
64:31:d4:d8:cd:7b:a7:e1:af:25:2c:a4:31:fb:84:
c7:bc:6e:7c:fb:6a:46:5d:ee:bb:5f:74:96:a1:fe:
13:79:55:e8:c4:74:77:1c:ea:6a:8e:a8:cb:89:da:
20:db:88:18:e5:4a:f9:93:43:03:53:c3:d8:a3:2c:
73:ea:8c:64:55:da:cf:a5:c7:11:70:ce:d4:51:3c:
2c:19:06:3c:23:0c:d6:02:a5:95:28:b7:b0:34:1f:
5d:32:38:e0:01:f2:12:b5:b2:8f:6b:83:83:06:6c:
e0:ca:ec:e5:45:3e:75:79:f4:bf:47:e2:56:cd:8a:
7b:cc:c7:0d:14:af:00:f6:e0:64:e2:30:a3:6c:ed:
05:1e:33:9a:88:8b:0d:31:48:2b:02:65:61:4b:cd:
84:90:c5:83:ba:93:1f:b7:78:7f:ec:4e:e9:bc:02:
03:86:c2:a9:00:87:4c:e1:bb:d8:e7:b2:12:a6:9b:
ab:9f:24:6f:6d:fe:09:60:22:d9:45:c2:20:55:70:
27:9d:3a:84:fb:57:9a:d3:d0:d2:d3:18:25:8c:40:
f8:2c:15:98:de:2e:2d:be:b4:dd:6e:24:2b:07:0b:
21:08:a6:db:30:df:5c:7f:50:6f:be:b7:2e:40:28:
58:85:89:de:4e:c7:66:af:fc:05:1c:c7:4d:d1:d2:
fa:2c:00:1a:0e:47:5f:30:b6:e6:90:fe:99:96:42:
4d:17:d3:13:36:7b:76:1c:36:c6:31:f3:a8:b0:9c:
33:a1:b3:e9:40:51:b9:29:1d:b4:36:2a:20:0e:c0:
f7:fb:a9:db:18:e0:67:ca:5d:d7:46:03:17:32:04:
35:24:5a:fe:0a:1e:7b:96:8b:0a:fb:3c:f6:94:92:
ab:d8:7d:ed:e4:2b:64:d7:ab:8d:11:89:e3:80:9d:
28:59:da:de:6f:55:30:30:78:9a:06:30:5b:a4:ff:
7a:70:49:b6:8c:9a:66:c0:a8:77:74:ca:f5:02:05:
63:8c:83
""")
exponent = 0x10001
+4 -1
View File
@@ -105,11 +105,14 @@ label top:
ui.null()
ui.null()
ui.close()
ui.close()
if update_allowed:
ui.key("U", Jump("update"))
interact()
# ProcessBehavior can return True, which sends us here.
+1 -1
View File
@@ -1,3 +1,3 @@
init -999:
$ config.script_version = (6, 11, 0)
$ config.script_version = (6, 11, 2)
+29 -21
View File
@@ -1,8 +1,13 @@
init python:
LAUNCHER_RPYS = set(['options.rpy', 'strings.rpy', 'transupdate.rpy', 'choose_theme.rpy', 'archiver.rpy', 'project.rpy', 'script_version.rpy', 'new.rpy', 'themes_data.rpy', 'opts.rpy', 'interface.rpy', 'projectsdir.rpy', 'distribute.rpy', 'script.rpy', 'editor.rpy'])
LAUNCHER_RPYS = set(['options.rpy', 'strings.rpy', 'transupdate.rpy', 'choose_theme.rpy', 'archiver.rpy', 'project.rpy', 'script_version.rpy', 'new.rpy', 'updater.rpy', 'themes_data.rpy', 'opts.rpy', 'interface.rpy', 'projectsdir.rpy', 'update_interface.rpy', 'distribute.rpy', 'script.rpy', 'editor.rpy'])
TRANSLATION_STRINGS = [
u"Graphics Acceleration",
u"Automatically Choose",
u"Prefer Software Renderer",
u"Prefer OpenGL Renderer",
u"Continue",
u"Are you sure?",
u"Are you sure you want to delete this save?",
u"Are you sure you want to overwrite your save?",
@@ -64,14 +69,13 @@ init python:
u"Joystick...",
u"Joystick Configuration",
u"Voice Volume",
u"Developer Menu",
u"Return to the developer menu",
u"Reload Game (Shift+R)",
u"Reload Game (Shift + R)",
u"Variable Viewer",
u"Return to the developer menu",
u"Theme Test",
u"Style Hierarchy",
u"FPS Meter",
u"Image Location Picker",
u"Filename List",
u"Done",
u"Auto",
u"Quick",
@@ -104,6 +108,16 @@ init python:
u"Choose Theme",
u"Please choose a color scheme for your project.",
u"Choose Color Scheme",
u"Base Name",
u"Please enter in the base name for your distribution. This name is used to generate the names of directories and archive files. Usually, this is the name of your game, plus a version number, like \"moonlight-1.0\".",
u"Executable Name",
u"Please enter a name for the executables in your distribution. This should not include an extension, as that will be added automatically.",
u"Ignore Extensions",
u"Please enter a space-separated list of file extensions. Files with these extensions will not be included in the built distributions.",
u"Documentation Extensions",
u"Please enter a space separated list of documentation extensions. Files in the base directory with these extensions will have a second copy stored outside of the Macintosh application.",
u"Thank you for choosing Ren'Py.",
u"The distributions have been built. Be sure to test them before release.\n\nNote that unpacking and repacking the Macintosh, Linux, or Combined distributions on Windows is not supported.\n\nPlease announce your release at the {a=http://lemmasoft.renai.us/forums/}Lemma Soft Forums{/a}, and add it to {a=http://games.renpy.org}games.renpy.org{/a}.",
u"Building Distributions",
u"I've just performed a lint on your project. If it contains errors, you should say no and fix them.\nPlease also check {a=http://www.renpy.org/wiki/renpy/Download_Ren'Py}www.renpy.org{/a} to see if updates or fixes are available.\n\nDo you want to continue?",
u"Base Name:",
@@ -125,21 +139,6 @@ init python:
u"Zip distribution for the Windows x86, Linux x86, Macintosh x86 and Macintosh ppc platforms.",
u"Build",
u"Start building the distributions.",
u"Base Name",
u"Please enter in the base name for your distribution. This name is used to generate the names of directories and archive files. Usually, this is the name of your game, plus a version number, like \"moonlight-1.0\".",
u"Executable Name",
u"Please enter a name for the executables in your distribution. This should not include an extension, as that will be added automatically.",
u"Ignore Extensions",
u"Please enter a space-separated list of file extensions. Files with these extensions will not be included in the built distributions.",
u"Documentation Extensions",
u"Please enter a space separated list of documentation extensions. Files in the base directory with these extensions will have a second copy stored outside of the Macintosh application.",
u"Scanning...",
u"Building Windows...",
u"Building Linux...",
u"Building Macintosh...",
u"Building Combined...",
u"Thank you for choosing Ren'Py.",
u"The distributions have been built. Be sure to test them before release.\n\nNote that unpacking and repacking the Macintosh, Linux, or Combined distributions on Windows is not supported.\n\nPlease announce your release at the {a=http://lemmasoft.renai.us/forums/}Lemma Soft Forums{/a}, so we can add it to the Ren'Py web site.",
u"The editor has been set from the RENPY_EDITOR environment variable, and cannot be changed.",
u"Choose Editor",
u"Please choose the editor that will be use to edit scripts and display errors. More editors can be downloaded from {a=http://www.renpy.org/wiki/renpy/Editors}the Ren'Py website{/a}.",
@@ -154,6 +153,7 @@ init python:
u"Something with that name already exists in the projects directory.",
u"Creating Project",
u"Please wait while we create the project.",
u"Could not create the project directory. The error was: %s",
u"%s Launcher",
u"Launcher Options",
u"Using RENPY_EDITOR",
@@ -177,7 +177,10 @@ init python:
u"Choose Projects Directory",
u"Please choose the directory containing your projects.",
u"Could not run zenity. The projects directory has been set to the directory immediately above the directory containing Ren'Py.",
u"Tutorial Game",
u"Launches the Ren'Py tutorial game.",
u"Update Ren'Py",
u"Updates Ren'Py to the latest version.",
u"Now showing the Ren'Py documentation in your web browser.",
u"Now showing the Ren'Py Games List in your web browser.",
u"Launch",
@@ -204,6 +207,11 @@ init python:
u"Change Ren'Py launcher options.",
u"Ren'Py Help",
u"Open the Ren'Py documentation in a web browser.",
u"Tutorial Game",
u"Retrieving catalog",
u"Checking files",
u"Making directories.",
u"Downloading updated files",
u"Renaming files",
u"Fixing permissions.",
]
+9 -22
View File
@@ -3,6 +3,10 @@ init 1 python:
# This is a list of (theme name, theme function, theme exemplar) tuples.
themes = [
("Roundrect", "roundrect", "Basic Blue"),
("Bordered", "bordered", "Dramatic Flesh"),
("Diamond", "diamond", "Colorblind"),
("TV", "tv", "Fine China"),
("Glow", "glow", "Really Red"),
]
# This is a map from theme function to template text that sensibly calls
@@ -57,6 +61,11 @@ init 1 python:
## do so below.
)"""
theme_templates["bordered"] = theme_templates["roundrect"].replace("roundrect", "bordered")
theme_templates["diamond"] = theme_templates["roundrect"].replace("roundrect", "diamond")
theme_templates["tv"] = theme_templates["roundrect"].replace("roundrect", "tv")
theme_templates["glow"] = theme_templates["roundrect"].replace("roundrect", "glow")
# This is a map from theme name to the code needed to implement that
# theme.
theme_data = {
@@ -66,7 +75,6 @@ init 1 python:
'gm_root': '#dcebff',
'label': '#ffffff',
'mm_root': '#dcebff',
'theme': 'roundrect',
'widget': '#003c78',
'widget_hover': '#0050a0',
'widget_selected': '#ffffc8',
@@ -77,7 +85,6 @@ init 1 python:
'gm_root': '#000000',
'label': '#ffffff',
'mm_root': '#000000',
'theme': 'roundrect',
'widget': '#000000',
'widget_hover': '#830000',
'widget_selected': '#ffffff',
@@ -88,7 +95,6 @@ init 1 python:
'gm_root': '#393939',
'label': '#c2c2c2',
'mm_root': '#393939',
'theme': 'roundrect',
'widget': '#898989',
'widget_hover': '#464646',
'widget_selected': '#F2F2F2',
@@ -99,7 +105,6 @@ init 1 python:
'gm_root': '#D0B4BA',
'label': '#805C40',
'mm_root': '#D0B4BA',
'theme': 'roundrect',
'widget': '#ECC7D0',
'widget_hover': '#E1D4C9',
'widget_selected': '#805C40',
@@ -110,7 +115,6 @@ init 1 python:
'gm_root': '#FDF5E3',
'label': '#502F13',
'mm_root': '#FDF5E3',
'theme': 'roundrect',
'widget': '#D96B00',
'widget_hover': '#FD9B1C',
'widget_selected': '#ffffff',
@@ -121,7 +125,6 @@ init 1 python:
'gm_root': '#2a201f',
'label': '#ffffff',
'mm_root': '#2a201f',
'theme': 'roundrect',
'widget': '#BF7C51',
'widget_hover': '#dda570',
'widget_selected': '#ffffff',
@@ -132,7 +135,6 @@ init 1 python:
'gm_root': '#FBF9DF',
'label': '#698071',
'mm_root': '#FBF9DF',
'theme': 'roundrect',
'widget': '#F5D4EE',
'widget_hover': '#F0DDFF',
'widget_selected': '#000000',
@@ -143,7 +145,6 @@ init 1 python:
'gm_root': '#b0b8ba',
'label': '#ffffff',
'mm_root': '#b0b8ba',
'theme': 'roundrect',
'widget': '#8699a7',
'widget_hover': '#9eb1ad',
'widget_selected': '#ffffff',
@@ -154,7 +155,6 @@ init 1 python:
'gm_root': '#F7F7FA',
'label': '#39435E',
'mm_root': '#F7F7FA',
'theme': 'roundrect',
'widget': '#6A7183',
'widget_hover': '#1A2B47',
'widget_selected': '#E3E3E4',
@@ -165,7 +165,6 @@ init 1 python:
'gm_root': '#D98989',
'label': '#5D1010',
'mm_root': '#D98989',
'theme': 'roundrect',
'widget': '#F09898',
'widget_hover': '#D6C5BB',
'widget_selected': '#B31E1E',
@@ -176,7 +175,6 @@ init 1 python:
'gm_root': '#E6E6E6',
'label': '#D9D9D9',
'mm_root': '#E6E6E6',
'theme': 'roundrect',
'widget': '#D9D9D9',
'widget_hover': '#F0F2F2',
'widget_selected': '#737373',
@@ -187,7 +185,6 @@ init 1 python:
'gm_root': '#1A140E',
'label': '#F1EBE5',
'mm_root': '#1A140E',
'theme': 'roundrect',
'widget': '#4D3B29',
'widget_hover': '#996E45',
'widget_selected': '#ffffff',
@@ -198,7 +195,6 @@ init 1 python:
'gm_root': '#1A0001',
'label': '#1A0001',
'mm_root': '#1A0001',
'theme': 'roundrect',
'widget': '#777777',
'widget_hover': '#73735C',
'widget_selected': '#000000',
@@ -209,7 +205,6 @@ init 1 python:
'gm_root': '#A84A3E',
'label': '#ffffff',
'mm_root': '#A84A3E',
'theme': 'roundrect',
'widget': '#A89E7D',
'widget_hover': '#8DB6B9',
'widget_selected': '#ffffff',
@@ -220,7 +215,6 @@ init 1 python:
'gm_root': '#ffd0d0',
'label': '#ffffff',
'mm_root': '#ffd0d0',
'theme': 'roundrect',
'widget': '#963232',
'widget_hover': '#c83232',
'widget_selected': '#ffffc8',
@@ -231,7 +225,6 @@ init 1 python:
'gm_root': '#B4CDD4',
'label': '#94C7D4',
'mm_root': '#B4CDD4',
'theme': 'roundrect',
'widget': '#F2E6AA',
'widget_hover': '#FCFCA4',
'widget_selected': '#1A5766',
@@ -242,7 +235,6 @@ init 1 python:
'gm_root': '#B09D5A',
'label': '#ffffff',
'mm_root': '#B09B4F',
'theme': 'roundrect',
'widget': '#753D00',
'widget_hover': '#B19A48',
'widget_selected': '#ffffff',
@@ -253,7 +245,6 @@ init 1 python:
'gm_root': '#000000',
'label': '#ffffff',
'mm_root': '#000000',
'theme': 'roundrect',
'widget': '#333333',
'widget_hover': '#000000',
'widget_selected': '#ffffff',
@@ -264,7 +255,6 @@ init 1 python:
'gm_root': '#695640',
'label': '#F2EDC4',
'mm_root': '#695640',
'theme': 'roundrect',
'widget': '#7A674F',
'widget_hover': '#BDA77D',
'widget_selected': '#FDFBEE',
@@ -275,7 +265,6 @@ init 1 python:
'gm_root': '#F7F7C5',
'label': '#FCFCD7',
'mm_root': '#F7F7C5',
'theme': 'roundrect',
'widget': '#FFE06D',
'widget_hover': '#E38A4F',
'widget_selected': '#996600',
@@ -286,7 +275,6 @@ init 1 python:
'gm_root': '#FBF9EA',
'label': '#F1EBE5',
'mm_root': '#FBF9EA',
'theme': 'roundrect',
'widget': '#33271C',
'widget_hover': '#ECE7C4',
'widget_selected': '#ffffff',
@@ -297,7 +285,6 @@ init 1 python:
'gm_root': '#e5f1e5',
'label': '#ffffff',
'mm_root': '#e5f1e5',
'theme': 'roundrect',
'widget': '#7AA27B',
'widget_hover': '#A3C7A3',
'widget_selected': '#ffffff',
+58
View File
@@ -0,0 +1,58 @@
# This is an early version of an interface for the updater. For now, we just
# assume that the user wants to update the prerelease channel, and the
# base tag.
init python:
import os
import time
version_fn = os.path.join(config.basedir, "lib", "update-version.txt")
update_allowed = os.path.exists(version_fn)
label update:
python hide:
try:
info("Checking for update...", "")
old_version = file(version_fn, "rb").read()
updater = Updater(config.basedir, 'http://update.renpy.org/renpy/updates/prerelease', [ 'base' ])
# Check the version.
version, verbose_version = updater.check_version(old_version)
if version is None:
pauseinfo("Up To Date", "Your version of Ren'Py is up to date.")
renpy.jump("top")
if not yesno("Update Available", "Would you like to update to %s?" % verbose_version):
renpy.jump("top")
# If we've made it this far, the user has decided that he wants
# to try an update.
for what, amount, limit in updater.step():
progress(what, limit, amount)
f = file(version_fn, "wb")
f.write(version)
f.close()
pauseinfo("Update complete.", "The update has finished. Ren'Py will now restart.")
if sys.platform == "win32" and sys.argv[0].lower().endswith(".exe"):
proc = subprocess.Popen([sys.argv[0], config.basedir])
else:
proc = subprocess.Popen([sys.executable, sys.argv[0], config.basedir])
renpy.quit()
except UpdateException, e:
error('The update has failed, with the error message: %s' % e.args[0])
+328
View File
@@ -0,0 +1,328 @@
init python:
import urllib2
import bz2
import os
import hashlib
import public
class UpdateException(Exception):
"""
The exception that we return if the update fails.
"""
pass
class Updater(object):
"""
A class that attempts to update a tree of files, with a reasonable
degree of safety, security, speed, and progress reporting.
"""
def __init__(self, local, remote, tags):
"""
Create a new updater.
`local`
The name of the local directory where the files are stored.
`remote`
The remote url base.
`tags`
A list of tags to update.
"""
self.local = local
self.remote = remote
# The remote version we're upgrading to.
self.version = None
# A list of directory names.
self.directories = [ ]
# A list of file, bz2-size, adler32 tuples.
self.files = [ ]
# Xbit files.
self.xbit = [ ]
# The tags we use.
self.tags = set(tags)
def snarf(self, url):
"""
Gets the url as a string.
"""
url = self.remote + "/" + url
try:
u = urllib2.urlopen(url, None, 5)
return u.read()
except Exception, e:
raise UpdateException("Could not download %r: %r" % (url, e))
def retrieve(self, relative):
"""
Downloads the bz2-compressed file, and then decompresses it into
relative.new.
"""
bz = os.path.join(self.local, relative + ".new.bz2")
new = os.path.join(self.local, relative + ".new")
url = self.remote + "/" + relative + ".bz2"
try:
u = urllib2.urlopen(url, None, 5)
f = file(bz, "wb")
f.write(u.read())
f.close()
u.close()
bzf = bz2.BZ2File(bz, "rb")
f = file(new, "wb")
while True:
buf = bzf.read(1024 * 1024)
if not buf:
break
f.write(buf)
f.close()
bzf.close()
os.unlink(bz)
except Exception, e:
raise UpdateException("Could not download %r: %r" % (url, e))
def check_version(self, version):
"""
Checks to see if version is still up to date. Returns a new-version,
verbose-version string. new-version is an internal representation
of the version being downloaded, while verbose-version is a
string that can be presented to the user.
The `version` argument should be given the new-version returned
from the last successful update. new-version is None if we are
up to date.
"""
remote_version = self.snarf("version")
self.version, verbose_version = remote_version.split("\n", 1)
self.version += " " + " ".join(sorted(self.tags))
if self.version.strip() == version.strip():
return None, verbose_version
else:
return self.version, verbose_version
def verify_hash(self, relative, digest):
"""
Verifies that the file `relative` has the hash value `digest`.
"""
fn = os.path.join(self.local, relative)
if not os.path.exists(fn):
return False
hash = hashlib.sha256()
try:
f = file(fn, "rb")
while True:
data = f.read(1024 * 1024)
if not data:
break
if not "renpy.app" in fn:
if fn.endswith(".rpy") or fn.endswith(".rpym") or fn.endswith(".py") or fn.endswith(".txt"):
data = data.replace("\n", "\r\n")
data = data.replace("\r\r\n", "\r\n")
hash.update(data)
f.close()
except:
return False
return hash.hexdigest() == digest
def get_catalog(self):
"""
Downloads the catalog file from the server, checking the signature
as necessary.
"""
self.retrieve("catalog1")
catalog_fn = os.path.join(self.local, "catalog1.new")
verified = False
try:
hash = hashlib.sha256()
f = file(catalog_fn, "rb")
# Read control information.
for l in f:
if l[0] == "-":
break
hash.update(l)
l = l[:-1]
a = l.split("\t")
if a[0] == "file":
cmd, digest, size, tag, name = a
if tag in self.tags:
self.files.append((name, digest, int(size)))
elif a[0] == "dir":
cmd, tag, name = a
if tag in self.tags:
self.directories.append(name)
elif a[0] == "xbit":
cmd, name = a
self.xbit.append(name)
else:
raise UpdateException("Unknown upgrade command: %r" % l)
# Compute the unsigned message.
unsigned = int("01" + hash.hexdigest(), 16)
for l in f:
a = l[:-1].split("\t")
if a[0] != "signature":
continue
signature = int(a[1], 16)
if pow(signature, public.exponent, public.modulus) == unsigned:
verified = True
f.close()
os.unlink(catalog_fn)
except UpdateException:
raise
except Exception, e:
raise UpdateException("Could not download catalog: %r" % (e,))
if not verified:
raise UpdateException("Could not verify catalog signature.")
def step(self):
"""
This is a generator that performs the steps in the update
process. It yields a (message, complete, total) tuple for
each step, and terminates upon success.
"""
yield (u"Retrieving catalog", 0, 1)
self.get_catalog()
updated_files = [ ]
download_size = 0
for i, (name, hash, size) in enumerate(self.files):
yield (u"Checking files", i, len(self.files))
if not self.verify_hash(name, hash):
updated_files.append((name, hash, size))
download_size += size
complete_size = 0
# Todo: Make directories.
for i, dir in enumerate(self.directories):
yield (u"Making directories", i, len(self.directories))
dir = os.path.join(self.local, dir)
if not os.path.exists(dir):
try:
os.mkdir(dir)
except:
raise UpdateException("Couldn't make directory %r." % dir)
complete = 0
for name, hash, size in updated_files:
yield (u"Downloading updated files", complete, len(updated_files))
if self.verify_hash(name + ".new", hash):
complete_size += size
continue
self.retrieve(name)
if not self.verify_hash(name + ".new", hash):
raise UpdateException("Could not verify download of %r." % name)
complete_size += size
complete += 1
umask = os.umask(0)
os.umask(umask)
for i, (name, hash, size) in enumerate(updated_files):
yield (u"Renaming files", i, len(updated_files))
fn = os.path.join(self.local, name)
if os.path.exists(fn + ".old"):
os.unlink(fn + ".old")
if os.path.exists(fn):
os.rename(fn, fn + ".old")
os.rename(fn + ".new", fn)
if fn.endswith(".py") and os.path.exists(fn + 'o'):
os.unlink(fn + 'o')
for i, name in enumerate(self.xbit):
yield (u"Fixing permissions", i, len(self.xbit))
fn = os.path.join(self.local, name)
if os.path.exists(fn):
os.chmod(fn, 0777 & (~umask))
# if __name__ == "__main__":
# up = Updater("/tmp/renpy-1", "file:///tmp/renpy-6.11.0", [ "base" ])
# version, verbose_version = up.check_version(1)
# for message, done, total in up.step():
# print message, "(%d/%d)" % (done, total)
# print version
# print verbose_version
-534
View File
@@ -1,534 +0,0 @@
# This file contains the code needed to build a Ren'Py distribution.
init python:
import zipfile
import tarfile
import os
import os.path
import time
import sys
import zlib
import pefile
# Returns true if a file or directory should not be included in
# the distribution
ignored_files = ("thumbs.db",
"launcherinfo.py",
"traceback.txt",
"errors.txt",
"icon.ico",
"icon.icns"
)
root_ignored_files = (
"common",
"renpy",
"renpy.code",
"python23.dll",
"python24.dll",
"python25.dll",
"msvcr71.dll",
"lib",
"iliad-icon.png",
"manifest.xml"
)
def ignored(fn, dir, dest, root):
if fn[0] == ".":
return True
for i in store.ignore_extensions:
if fn.endswith(i):
return True
if fn.lower() in ignored_files:
return True
if fn == "saves":
return True
if fn == "archived":
return True
if root and dir == dest:
if fn.endswith(".py") or fn.endswith(".sh") or fn.endswith(".app"):
return True
if fn in root_ignored_files:
return True
return False
def tree(src, dest,
exclude_suffix=[ ".pyc", "~", ".bak" ],
exclude_prefix=[ ".", '#' ],
exclude=ignored_files,
exclude_func=ignored,
root=False,
):
# Get rid of trailing slashes.
if src[-1] == "/":
src = src[:-1]
if dest and dest[-1] == "/":
dest = dest[:-1]
# What should we include?
def include(fn, destdir, dest):
for i in exclude_suffix:
if fn.endswith(i):
return False
for i in exclude_prefix:
if fn.startswith(i):
return False
for i in exclude:
if i == fn.lower():
return False
if exclude_func and exclude_func(fn, destdir, dest, root):
return False
return True
rv = [ ]
# Walk the tree, including what is necessary.
for srcdir, dirs, files in os.walk(src):
if dest:
destdir = dest + srcdir[len(src):]
else:
destdir = srcdir[len(src) + 1:]
if destdir:
rv.append((srcdir, destdir))
for fn in files:
if not include(fn, destdir, dest):
continue
sfn = srcdir + "/" + fn
if destdir:
dfn = destdir + "/" + fn
else:
dfn = fn
dfn = dfn.replace("\\", "/")
rv.append((sfn, dfn))
dirs[:] = [ i for i in dirs if include(i, destdir, dest) ]
return rv
label distribute:
python hide:
zlib.Z_DEFAULT_COMPRESSION = 9
store.progress_time = 0
def progress(tit, n, m, time=time):
if time.time() < store.progress_time + .1:
return
title(tit)
mid(message)
ui.bar(m, n, xmaximum=200, xalign=0.5)
ui.close()
ui.pausebehavior(0)
interact()
# Check to see which platforms we can build on.
if os.path.exists(config.renpy_base + "/renpy.exe"):
windows = True
else:
windows = False
if os.path.exists(config.renpy_base + "/lib/linux-x86"):
linux = True
else:
linux = False
if os.path.exists(config.renpy_base + "/lib/linux-iliad"):
iliad = True
else:
iliad = False
if os.path.exists(config.renpy_base + "/renpy.app"):
mac = True
else:
mac = False
if not (windows or mac or linux or iliad):
store.error(u"Can't Distribute", u"Ren'Py is missing files required for distribution. Please download the full package from {a=http://www.renpy.org/}www.renpy.org{/a}.", "tools_menu")
lint()
store.message = ""
title(_(u"Building Distributions"))
mid()
text(u"I've just performed a lint on your project. If it contains errors, you should say no and fix them.\nCheck {a=http://www.renpy.org/wiki/renpy/Download_Ren'Py}www.renpy.org{/a} to see if updates or fixes are available.\n\nDo you want to continue?")
ui.close()
bottom()
button(u"Yes", clicked=ui.returns(True))
button(u"No", clicked=ui.returns(False))
ui.close()
if not interact():
renpy.jump("tools")
# if not windows or not mac or not linux:
# store.message = "The full version of Ren'Py can build for Windows, Mac, and Linux. Download it from www.renpy.org."
title(u"Building Distributions")
mid()
text(u"Distributions will be built for the following platforms:")
spacer()
if windows:
text(u"Windows 2000+", style='launcher_input')
if linux:
text(u"Linux x86", style='launcher_input')
if iliad:
text(u"iLiad", style='launcher_input')
if mac:
text(u"Mac OS X 10.4+", style='launcher_input')
spacer()
# TODO: If missing platforms, prompt for a DL.
text(u"Is this okay?")
ui.close()
bottom()
button(u"Yes", clicked=ui.returns(True))
button(u"No", clicked=ui.returns(False))
ui.close()
if not interact():
renpy.jump("tools")
default_name = project.info.get('distribution_base', project.name)
name = prompt(u"Building Distributions",
u"Please enter a base name for the directories making up this distribution.",
"tools",
default_name,
u"This usually should include a name and version number, like 'moonlight_walks-1.0'.")
name = name.strip()
if not name:
store.error(u"Error", u"The distribution name should not be empty.", "tools_menu")
try:
name = name.encode("ascii")
except:
store.error(u"Error", u"Distribution names must be ASCII. This is because archive file formats do not support non-ASCII characters in a uniform way.", "tools_menu")
project.info['distribution_base'] = name
ignore_extensions = project.info.get('ignore_extensions', "~ .bak")
ignore_extensions = prompt(u"Building Distributions", u"Please enter a space separated list of the file extensions you do not want included in the distribution.", "tools", ignore_extensions)
store.ignore_extensions = [ i.strip() for i in ignore_extensions.strip().split() ]
project.info['ignore_extensions'] = ignore_extensions
project.save()
# Figure out the files that will make up the distribution.
multi = [ ]
# This finds the files and directories in the tree, and includes
# them in the result.
# renpy and common directories.
multi.extend(tree(config.renpy_base + "/renpy", "renpy"))
multi.append((config.renpy_base + "/LICENSE.txt", "renpy/LICENSE.txt"))
multi.extend(tree(config.commondir, "common"))
# Include the project.
multi.extend(tree(project.path, '',
exclude_suffix = [ ],
exclude_prefix = [ ],
exclude=[ ],
root=True))
shortgamedir = project.gamedir[len(project.path)+1:]
def add_script_version(fn, multi=multi, shortgamedir=shortgamedir):
for a, b in multi:
if b == shortgamedir + "/" + fn:
return
for i in store.ignore_extensions:
if fn.endswith(i):
return
multi.append((config.gamedir + "/" + fn, shortgamedir + "/" + fn))
add_script_version("script_version.rpy")
add_script_version("script_version.rpyc")
# renpy.py
multi.append((config.renpy_base + "/renpy.py",
project.name + ".py"))
# Windows Zip
if windows:
win_files = [
( config.renpy_base + "/renpy.exe", project.name + ".exe"),
( config.renpy_base + "/renpy.code", "renpy.code" ),
( config.renpy_base + "/python25.dll", "python25.dll" ),
( config.renpy_base + "/msvcr71.dll", "msvcr71.dll" ),
]
win_data = { }
if os.path.exists(project.path + "/icon.ico"):
win_data[project.name + ".exe"] = pefile.change_icons(
config.renpy_base + "/renpy.exe",
project.path + "/icon.ico",
)
zf = zipfile.ZipFile(name + ".zip", "w", zipfile.ZIP_DEFLATED)
progress_len = len(multi) + len(win_files)
store.message = u"Be sure to announce your project at the Lemma Soft Forums."
for i, (fn, an) in enumerate(multi + win_files):
progress(u"Building Windows", i, progress_len)
if os.path.isdir(fn):
continue
zi = zipfile.ZipInfo(name + "/" + an)
s = os.stat(fn)
zi.date_time = time.gmtime(s.st_mtime)[:6]
zi.compress_type = zipfile.ZIP_DEFLATED
zi.create_system = 3
zi.external_attr = long(0100666) << 16
data = file(fn, "rb").read()
data = win_data.get(an, data)
zf.writestr(zi, data)
zf.close()
# Linux Tar Bz2
if linux:
linux_files = [
(config.renpy_base + "/lib/linux-x86", "lib/linux-x86"),
(config.renpy_base + "/renpy.sh", project.name + ".sh"),
(config.renpy_base + "/lib/python", "lib/python"),
]
linux_files.extend(tree(config.renpy_base + "/lib/linux-x86", "lib/linux-x86"))
tf = tarfile.open(name + "-linux-x86.tar.bz2", "w:bz2")
tf.dereference = True
progress_len = len(multi) + len(linux_files)
store.message = u"If appropriate, please submit your game to www.renai.us."
for j, i in enumerate(multi + linux_files):
progress(u"Building Linux", j, progress_len)
fn, an = i
info = tf.gettarinfo(fn, name + "-linux-x86/" + an)
if info.isdir():
perms = 0777
elif info.name.endswith(".sh"):
perms = 0777
elif info.name.endswith(".so"):
perms = 0777
elif info.name.endswith("python"):
perms = 0777
elif info.name.endswith("python.real"):
perms = 0777
else:
perms = 0666
info.mode = perms
info.uid = 1000
info.gid = 1000
info.uname = "renpy"
info.gname = "renpy"
if info.isreg():
tf.addfile(info, file(fn, "rb"))
else:
tf.addfile(info)
tf.close()
# iLiad Tar Bz2
if iliad:
iliad_files = [
(config.renpy_base + "/lib", "lib"),
(config.renpy_base + "/renpy-iliad.sh", project.name + ".sh"),
(config.renpy_base + "/lib/python", "lib/python"),
(config.renpy_base + "/manifest.xml", "manifest.xml"),
(config.renpy_base + "/iliad-icon.png", "iliad-icon.png"),
]
iliad_files.extend(tree(config.renpy_base + "/lib/linux-iliad", "lib/linux-iliad"))
iliad_data = { }
manifest = file(config.renpy_base + "/manifest.xml", "r").read()
manifest = manifest.replace("GAMENAME", project.name)
iliad_data["manifest.xml"] = manifest
zf = zipfile.ZipFile(name + "-iLiad.zip", "w", zipfile.ZIP_DEFLATED)
progress_len = len(multi) + len(iliad_files)
store.message = u"We thank Hixbooks for sponsoring iLiad support."
for i, (fn, an) in enumerate(multi + iliad_files):
progress(u"Building iLiad", i, progress_len)
if os.path.isdir(fn):
continue
zi = zipfile.ZipInfo(project.name + "/" + an)
s = os.stat(fn)
zi.date_time = time.gmtime(s.st_mtime)[:6]
zi.compress_type = zipfile.ZIP_DEFLATED
zi.create_system = 3
for ext in [ ".sh", ".so", "python", "python.real" ]:
if fn.endswith(ext):
zi.external_attr = long(0100777) << 16
data = file(fn, "rb").read()
break
else:
zi.external_attr = long(0100666) << 16
data = file(fn, "rb").read()
data = iliad_data.get(an, data)
zf.writestr(zi, data)
zf.close()
if mac:
mac_files = tree(config.renpy_base + "/renpy.app",
project.name + ".app")
mac_files = [ (fn, an.replace("Ren'Py Launcher", project.name)) for (fn, an) in mac_files ]
# Data replacement for macintosh.
mac_data = { }
quoted_name = project.name.replace("&", "&amp;").replace("<", "&lt;")
info_plist = file(config.renpy_base + "/renpy.app/Contents/Info.plist", "rb").read().replace("Ren'Py Launcher", quoted_name)
mac_data[project.name + ".app/Contents/Info.plist"] = info_plist
quoted_name = project.name.replace("\"", "\\\"")
launcher_py = file(config.renpy_base + "/renpy.app/Contents/Resources/launcher.py", "rb").read().replace("Ren'Py Launcher", quoted_name)
mac_data[project.name + ".app/Contents/Resources/launcher.py"] = launcher_py
if os.path.exists(project.path + "/icon.icns"):
icon_data = file(project.path + "/icon.icns", "rb").read()
mac_data[project.name + ".app/Contents/Resources/launcher.icns"] = icon_data
zf = zipfile.ZipFile(name + "-mac.zip", "w", zipfile.ZIP_DEFLATED)
progress_len = len(multi) + len(mac_files)
store.message = u"Thank you for choosing Ren'Py."
for i, (fn, an) in enumerate(multi + mac_files):
progress(u"Building Mac OS X", i, progress_len)
if os.path.isdir(fn):
continue
zi = zipfile.ZipInfo(name + "-mac/" + an)
s = os.stat(fn)
zi.date_time = time.gmtime(s.st_mtime)[:6]
zi.compress_type = zipfile.ZIP_DEFLATED
zi.create_system = 3
if os.path.dirname(fn).endswith("MacOS") or fn.endswith(".so") or fn.endswith(".dylib"):
zi.external_attr = long(0100777) << 16
data = file(fn, "rb").read()
else:
zi.external_attr = long(0100666) << 16
data = file(fn, "rb").read()
data = mac_data.get(an, data)
zf.writestr(zi, data)
zf.close()
# Announce Success
store.message = ""
title(u"Success")
mid()
text(u"The distribution(s) have been built. Be sure to test them before release.")
spacer()
if mac:
text(u"Note that unpacking and repacking Mac zips and Linux tarballs on Windows isn't supported.")
ui.close()
bottom()
button(u"Return", clicked=ui.returns(True))
ui.close()
interact()
jump tools
-29
View File
@@ -1,29 +0,0 @@
# This file contains logic for detecting an editor, and for selecting
# the default editor.
init:
python hide:
import os
import os.path
import sys
if not config.editor:
editor = os.path.normpath(config.renpy_base + "/jedit/jedit.jar")
if os.path.exists(editor):
editor = renpy.shell_escape(editor)
if sys.platform == 'win32':
config.editor = 'javaw.exe -jar "' + editor + '" -reuseview "%(filename)s" +line:%(line)d "%(otherfiles)s"'
config.editor_transient = 'javaw.exe -jar "' + editor + '" -newplainview "%(filename)s" +line:%(line)d "%(otherfiles)s"'
else:
config.editor = 'java -jar "' + editor + '" -reuseview "%(filename)s" +line:%(line)d "%(otherfiles)s"'
config.editor_transient = 'java -jar "' + editor + '" -newplainview "%(filename)s" +line:%(line)d "%(otherfiles)s"'
if config.editor:
os.environ['RENPY_EDITOR'] = config.editor
if config.editor_transient:
os.environ['RENPY_EDITOR_TRANSIENT'] = config.editor_transient
Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

-792
View File
@@ -1,792 +0,0 @@
python early:
config.save_directory = "launcher-1"
init:
python:
# Set up the window.
config.screen_width = 350
config.screen_height = 450
config.window_title = "Ren'Py Launcher"
# Disable sound and joystick.
config.sound = False
config.joystick = False
# Disables autosave (we can't save/load)
config.has_autosave = False
# Create some launcher styles.
style.create('launcher_button', 'button')
style.create('launcher_button_text', 'button_text')
style.create('launcher_title_label', 'default')
style.create('launcher_label', 'default')
style.create('launcher_input', 'default')
style.create('launcher_text', 'default')
style.create('launcher_bottom_vbox', 'vbox')
style.create('launcher_mid_vbox', 'vbox')
style_backup = renpy.style.backup()
_launcher_per_page = 8
# Choose the roundrect theme for the buttons.
layout.compat()
theme.roundrect(launcher=True)
style.hyperlink_text.color = "#0ff"
config.underlay = [
renpy.Keymap(
quit = renpy.quit_event,
iconify = renpy.iconify,
)
]
def quote(c):
n = ord(c)
if 0x20 <= n <= 0x7f:
return c
else:
return "\\x%02x" % n
def ifrw(label):
if project.info.get("ro", False):
return None
else:
return ui.jumps(label)
# We don't want the user going into the game menu.
def interact():
ui.window(background=Solid("#0008"), ypos=1.0, yminimum=80, xmargin=0, ymargin=0)
ui.null()
ui.image("eileen_small.png", xalign=0.0, yalign=1.0)
ui.add(DynamicDisplayable("Text(_(store.message), size=14, color='#fff', xpos=100, ypos=375, xmaximum=240)"))
ui.text(renpy.version(), xalign=0, yalign=1.0, size=12, color='#000')
return ui.interact()
def title(name):
ui.window(style='mm_root')
ui.null()
ui.frame(xminimum=350, yminimum=370)
ui.viewport(child_size=(2000, None), draggable=True, ymaximum=34)
_label_factory(name, "launcher_title", size=28)
# ui.text(name, xpos=4, ypos=4, size=30, color="#559")
def text(name, style="launcher_text"):
ui.text(_(name), style=style)
def label(name):
_label_factory(name, "launcher")
def spacer():
ui.add(Null(1, 6))
def mid(focus="mid"):
ui.vbox(style='launcher_mid_vbox', focus=focus)
def bottom(focus="bottom"):
ui.vbox(style='launcher_bottom_vbox', focus=focus)
def button(text, hover_text=None, clicked=None, hovered=None, selected=False):
if hover_text:
def hovered(hover_text=_(hover_text)):
if store.message != hover_text:
store.message = hover_text
renpy.restart_interaction()
# ui.button(clicked=clicked, hovered=hovered)
# ui.text(text, style="button_text")
_button_factory(text, 'launcher', clicked=clicked, hovered=hovered, selected=selected, xmaximum=200)
def prompt(name, message, cancel, default='', hint=''):
store.message = _(hint)
# Creating the project.
title(name)
mid()
text(message)
ui.input(default, exclude='{}/\\', style='launcher_input')
ui.close()
bottom()
button("Cancel", clicked=ui.jumps("main"))
ui.close()
return interact()
def error(name, message, target):
store.message = ''
# Creating the project.
title(name)
mid()
text(message)
ui.close()
bottom()
button("Cancel", clicked=ui.jumps(target))
ui.close()
return interact()
def paged_menu(tit, choices, message, per_page=None, cancel='main'):
if per_page is None:
per_page = _launcher_per_page
page = 0
pages = (len(choices) - 1) / per_page
while True:
store.message = message
title(tit)
mid(focus="paged_menu")
for name, desc, ret, hovered, selected in choices[page * per_page:(page + 1) * per_page]:
if len(name) > 19:
name = name[:18] + u"\u2026"
button(name, desc, clicked=ui.returns(("return", ret)), hovered=hovered, selected=selected)
ui.close()
bottom()
if pages >= 1:
if page < pages:
button(u"Next Page", u"Go to the next page of projects.", clicked=ui.returns(("page", page + 1)))
else:
button(u"Next Page")
if page > 0:
button(u"Previous Page", u"Go to the previous page of projects.", clicked=ui.returns(("page", page - 1)))
else:
button(u"Previous Page")
button(u"Cancel", u"Return to the top menu.", ui.jumps(cancel))
ui.close()
cmd, arg = interact()
if cmd == "repeat":
continue
if cmd == "page":
page = arg
continue
if cmd == "return":
return arg
class ProcessBehavior(renpy.display.layout.Null):
def __init__(self, proc):
super(ProcessBehavior, self).__init__()
self.proc = proc
def event(self, ev, x, y, st):
if self.proc.poll() is not None:
return True
renpy.game.interface.timeout(.25)
class Project(object):
def __init__(self, name, path, gamedir, info):
# name
self.name = name
# path to project
self.path = path
# gamedir
self.gamedir = gamedir
self.info = info
import re
def upper(m):
return m.group(0).upper()
title = re.sub(r'^.', upper, name)
title = re.sub(r'\s+\S', upper, title)
self.title = title
def save(self):
import os
f = file(self.path + "/" + "launcherinfo.py.new", "w")
for k, v in self.info.iteritems():
f.write("%s = %r\n" % (k, v))
f.close()
try:
os.rename(self.path + "/launcherinfo.py.new", self.path + "/launcherinfo.py")
except:
os.unlink(self.path + "/launcherinfo.py")
os.rename(self.path + "/launcherinfo.py.new", self.path + "/launcherinfo.py")
def load_project(dir, name):
import os.path
# Ignore unicode files.
for i in name:
if ord(i) >= 127:
return
if os.path.isdir(dir + "/game"):
gamedir = dir + "/game"
elif os.path.isdir(dir + "/data"):
gamedir = dir + "/data"
else:
return
desc = u""
info = dict()
info["description"] = desc
if os.path.exists(dir + "/launcherinfo.py"):
source = file(dir + "/launcherinfo.py", "rU").read().decode("utf8")
if source[0] == u'\ufeff':
source = source[1:]
source = source.encode("raw_unicode_escape")
exec source in info
del info["__builtins__"]
store.projects.append(Project(name, dir, gamedir, info))
def load_projects():
import os
import os.path
store.projects = [ ]
cwd = os.getcwd()
if cwd == config.renpy_base:
dirs = [ cwd ]
else:
dirs = [ config.renpy_base, cwd ]
for d in dirs:
contents = os.listdir(d)
contents.sort()
for dd in contents:
dir = d + "/" + dd
if os.path.isdir(dir):
load_project(dir, dd)
if not store.projects:
raise Exception("The launcher will not function without any projects.")
def lint():
import renpy.subprocess as subprocess
import sys
import os.path
store.message = u"Lint in progress."
title(u"Lint")
ui.pausebehavior(0)
interact()
lf = file("lint.txt", "w+")
if hasattr(sys, "winver") and sys.argv[0].lower().endswith(".exe"):
proc = subprocess.Popen([config.renpy_base + "/console.exe", "--lint", project.path], stdin=lf, stdout=lf, stderr=lf)
else:
proc = subprocess.Popen([sys.executable, sys.argv[0], "--lint", project.path], stdout=lf)
proc.wait()
lf.close()
renpy.launch_editor([ "lint.txt" ],transient=1)
def rmpersistent():
import renpy.subprocess as subprocess
import sys
import os.path
store.message = u"Deleting persistent data."
title(u"Delete Persistent")
ui.pausebehavior(0)
interact()
if hasattr(sys, "winver") and sys.argv[0].lower().endswith(".exe"):
proc = subprocess.Popen([config.renpy_base + "/console.exe", "--rmpersistent", project.path])
else:
proc = subprocess.Popen([sys.executable, sys.argv[0], "--rmpersistent", project.path])
proc.wait()
label main_menu:
return
label find_project:
python hide:
load_projects()
wanted = persistent.project or "demo"
for p in projects:
if p.name == wanted:
store.project = p
break
else:
store.project = projects[0]
store.game_proc = None
return
label start:
call find_project from _call_find_project_1
label main:
python:
store.message = u"What do you want to do?"
label top_menu:
python hide:
while True:
title(project.title)
mid()
label(u"This Project")
if not game_proc or game_proc.poll() is not None:
clicked = ui.jumps("launch")
else:
clicked = None
button(u"Launch",
u"Starts the project running.",
clicked=clicked)
if config.editor:
button(u"Edit Script",
u"Edits the script files.",
clicked=ui.jumps("edit"))
button(u"Change Theme",
u"Changes the color theme of the project.",
ifrw("choose_theme"))
button(u"Game Directory",
u"Opens the game directory.",
clicked=ui.jumps("game_directory"))
button(u"Tools",
u"Shows the tools menu.",
clicked=ui.jumps("tools"))
spacer()
label(u"Change Project")
button(u"Select Project",
u"Select a project to work with.",
clicked=ui.jumps("select_project"))
button(u"New Project",
u"Create a new project from a template.",
clicked=ui.jumps("new"))
ui.close()
bottom()
button(u"Documentation", u"Read Ren'Py tutorials and manuals.", clicked=ui.jumps("documentation"))
button(u"Quit", u"Quit the Ren'Py Launcher.", clicked=ui.jumps("confirm_quit"))
ui.close()
if game_proc and game_proc.poll() is None:
ui.add(ProcessBehavior(game_proc))
interact()
jump top_menu
label select_project:
python hide:
choices = [ (p.name, p.info["description"], p, None, False) for p in projects if not p.info.get("template") ]
store.project = paged_menu(u"Select a Project", choices, u"Please select a project.")
persistent.project = store.project.name
store.game_proc = None
jump main
label launch:
python hide:
import renpy.subprocess
import sys
import os.path
import os
if hasattr(sys, "winver") and sys.argv[0].lower().endswith(".exe"):
proc = renpy.subprocess.Popen([sys.argv[0], project.path])
else:
proc = renpy.subprocess.Popen([sys.executable, sys.argv[0], project.path])
store.message = _(u"%s has been launched.") % project.title
store.game_proc = proc
jump top_menu
label edit:
python hide:
import os
files = [ project.gamedir + "/" + i for i in os.listdir(project.gamedir) if i.endswith(".rpy") if not i[0] == "."]
files.sort()
for i in files[:]:
if i.endswith("options.rpy"):
files.remove(i)
files.insert(0, i)
for i in files[:]:
if i.endswith("script.rpy"):
files.remove(i)
files.insert(0, i)
if not renpy.launch_editor(files):
error(u"Error", u"Launching the editor failed. You may need Java, which can be downloaded for free from {a=http://www.java.com}java.com{/a}.", "start")
store.message = _(u"Launched editor with %d script files.") % len(files)
jump top_menu
label game_directory:
python hide:
import os
import os.path
import platform
import sys
gamedir = os.path.normpath(project.gamedir)
if sys.platform == "win32":
os.startfile(gamedir)
elif platform.mac_ver()[0]:
import renpy.subprocess as subprocess
subprocess.Popen([ "open", gamedir ])
else:
import renpy.subprocess as subprocess
subprocess.Popen([ "xdg-open", gamedir ])
gamedir = "".join(quote(i) for i in gamedir)
store.message = _(u"Opening game directory:\n%s") % gamedir
jump top_menu
label tools:
$ store.message = u"Please choose a tool you want to use with this project."
label tools_menu:
python hide:
title(_("Tools: %s") % project.title)
mid()
label(u"Anytime")
button(u"Check Script (Lint)",
u"Checks the game's script for likely errors. This should be run before releasing.",
clicked=ui.jumps("lint"))
button(u"Delete Persistent",
u"Deletes the game's persistent data.",
clicked=ui.jumps("rmpersistent"))
# button("Quick Backup",
# "Makes a backup copy of the project. You also need to make backups somewhere other then this computer.",
# clicked=ui.jumps("backup"))
spacer()
label(u"Release Day")
button(u"Add From to Calls",
u"Adds a from clause to each of the call statements in your script.",
clicked=ifrw("add_from_to_calls"))
button(u"Archive Files",
u"Archive files found under the game and archived directories.",
clicked=ifrw("archive_files"))
button(u"Build Distributions",
u"Build distributions for the platforms supported by Ren'Py.",
clicked=ui.jumps("distribute"))
ui.close()
bottom()
button(u"Back",
u"Goes back to the top menu.",
clicked=ui.jumps("main"))
ui.close()
interact()
label lint:
python hide:
lint()
store.message = u"A lint report should appear shortly."
jump tools_menu
label archive_files:
python hide:
import os
import os.path
import renpy.tools.archiver as archiver
extensions = project.info.get('archive_extensions', "*.png *.gif *.jpg")
extensions = prompt(u"Archiving Files", u"Please enter a space separated list of the file patterns you want archived.", "tools", extensions)
if not extensions.strip():
renpy.jumps("tools_menu")
project.info['archive_extensions'] = extensions
extensions = [ i.strip() for i in extensions.strip().split() ]
base = project.info.get('archive_base', "data")
base = prompt(u"Archiving Files", u"Please enter the name of the archive file, without the .rpa extension.", "tools", base)
base = base.strip()
if not base:
renpy.jumps("tools_menu")
project.info['archive_base'] = base
project.save()
# Tell the user we're archiving images.
title(u"Archiving Files")
store.message = u"Please wait while we archive files."
ui.pausebehavior(0)
interact()
gamedir = project.gamedir
archived = project.path + "/archived"
files = [ ]
prefix = gamedir + "/" + base
def should_archive(fn, extensions=extensions):
import fnmatch
fn = fn.lower()
if fn[0] == ".":
return False
if fn == "presplash.png":
return False
if fn == "presplash.jpg":
return False
for e in extensions:
if fnmatch.fnmatch(fn, e):
return True
return False
archived_files = set()
for bdir in (gamedir, archived):
for dirname, dirs, filenames in os.walk(bdir):
# Ignore svn.
dirs[:] = [ i for i in dirs if not i[0] == '.' ]
for fn in filenames:
fullfn = dirname + "/" + fn
shortfn = fullfn[len(bdir)+1:]
if shortfn in archived_files:
continue
if not should_archive(shortfn):
continue
files.append((fullfn, shortfn))
archived_files.add(shortfn)
archiver.archive(prefix, files)
# f = file(gamedir + "/images.rpy", "w")
# print >>f, "init:"
# print >>f, " $ config.archives.append('images')"
# f.close()
for fullfn, shortfn in files:
afn = archived + "/" + shortfn
if fullfn == afn:
continue
try:
os.makedirs(os.path.dirname(afn))
except:
pass
try:
os.rename(fullfn, afn)
except:
os.rename(afn, afn + ".old")
os.rename(fullfn, afn)
os.unlink(afn + ".old")
store.message = u"The files have been added to the archive, and moved into the archived directory."
jump tools_menu
label backup:
python hide:
import os
import time
import shutil
# Tell the user we're archiving images.
title(u"Making Backup")
store.message = u"Please wait while we make a backup."
ui.pausebehavior(0)
interact()
try:
os.mkdir('backups')
except:
pass
while True:
btime = str(int(time.time()))
bdir = "backups/%s.%s" % (project.name, btime)
if not os.path.exists(bdir):
break
time.sleep(1)
shutil.copytree(project.path, bdir)
store.message = _(u"The backup was placed into %s.") % bdir
jump tools_menu
label add_from_to_calls:
python hide:
import os
import time
import shutil
title(u"Add From to Calls")
store.message = u"Please wait while we add from clauses to call statements."
ui.pausebehavior(0)
interact()
import renpy.tools.add_from as add_from
add_from.add_from(project.gamedir, config.commondir)
store.message = _(u"Done adding from clauses to call statements. You may want to remove the .bak files created.")
jump tools_menu
label rmpersistent:
python hide:
rmpersistent()
store.message = _(u"Done deleting persistent data.")
jump tools_menu
label confirm_quit:
$ renpy.quit()
label documentation:
python hide:
import webbrowser
webbrowser.open_new("file:///" + config.renpy_base + "/doc/index.html")
store.message = _(u"Now showing the Ren'Py documentation in your web browser.")
jump top_menu
-167
View File
@@ -1,167 +0,0 @@
label new:
python hide:
import os
import os.path
import time
# Select a template.
choices = [ (p.name, p.info["description"], p, None, False) for p in projects if p.info.get("template", None)]
template = paged_menu(u"Select a Template", choices, u"Please select a project to use as a template for your project.")
# Choose project name.
name = prompt(u"Project Name", u"Type the name of your new project, and press enter.\n", "main")
name = name.strip()
error = None
if not name:
error = u"Please enter a non-empty project name."
elif os.path.exists(name):
error = u"A file or directory named '%s' already exists." % name
else:
try:
name = name.encode("ascii")
except:
error = u"Project names must be ASCII. This is because the ZIP file format does not support non-ASCII characters in a uniform way."
if error:
store.error(u"Error", error, "main")
# Tell the user we're creating the project.
title(u"Creating Project")
store.message = u"Please wait while we create the project."
ui.pausebehavior(0)
interact()
# Here is where we actually create the project.
import shutil
shutil.copytree(template.path, name)
unlink = template.info.get("unlink", [ ])
unlink += [ 'launcherinfo.py' ]
for i in unlink:
if os.path.exists(name + "/" + i):
os.unlink(name + "/" + i)
for dir, dirs, files in os.walk(name):
for d in list(dirs):
if d.startswith("."):
dirs.remove(d)
dn = dir + "/" + d
shutil.rmtree(dn, True)
# Change the save directory.
options = file(name + "/game/options.rpy").read()
save_dir = "%s-%d" % (name, time.time())
options = options.replace("template-1220804310", save_dir)
file(name + "/game/options.rpy", "w").write(options)
persistent.project = name
call find_project from _call_find_project_2
label choose_theme:
python hide:
# Select a color scheme.
themes = theme_data.keys()
themes.sort()
choices = [ ]
for i in themes:
def hovered(i=i):
td = theme_data[i].copy()
engine = td["theme"]
del td["theme"]
if engine == "roundrect":
renpy.style.restore(style_backup)
theme.roundrect(launcher=True, **td)
renpy.style.rebuild()
return ("repeat", 0)
choices.append((i, None, i, hovered, False))
color_theme = paged_menu(u"Select a Theme", choices, u"Please select a color theme for your project. You can always change the colors later.", cancel='color_theme_cancel')
# Restore default theme.
renpy.style.restore(style_backup)
theme.roundrect(launcher=True)
renpy.style.rebuild()
ofn = project.path + "/game/options.rpy"
import os
import re
if not os.path.exists(ofn):
error(u"Changing Theme", u"The options file does not seem to exist.", "main")
inf = file(ofn, "rU")
outf = file(ofn + ".new", "w")
td = theme_data[color_theme]
# TODO: Make this less specific to roundrect. Need to figure out
# how to switch themes, rather than just recolor them.
changing = False
changed = False
for l in inf:
if re.match(r'\s*theme.roundrect\(', l):
changing = True
changed = True
elif re.match(r'\s*\)', l):
changing = False
elif changing:
def repl(m, td=td):
return m.group(1) + m.group(2) + " = \"" + td.get(m.group(2), m.group(3)) + "\","
l = re.sub(r'^(\s*)(\w+) = "([\da-fA-F#]+)",', repl, l)
outf.write(l)
outf.close()
inf.close()
try:
os.rename(ofn + ".new", ofn)
except:
# I hate windows.
os.rename(ofn, ofn + ".old")
os.rename(ofn + ".new", ofn)
os.unlink(ofn + ".old")
if not changed:
error(u"Changing Theme", u"Could not modify options.rpy, perhaps it was edited too much.", "main")
jump main
label color_theme_cancel:
python hide:
# Restore default theme.
renpy.style.restore(style_backup)
theme.roundrect(launcher=True)
renpy.style.rebuild()
jump main
-343
View File
@@ -1,343 +0,0 @@
# http://www.csn.ul.ie/~caolan/publink/winresdump/winresdump/doc/pefile.html
# Contains a reasonable description of the format.
import struct
import sys
import array
# The starting point of the resource segment in the file.
RESOURCE_BASE=0x3600
# The virtual memory location the resource segment is loaded
# to.
RESOURCE_VIRTUAL=0x6000
# The offset of the field that tells us with the alignment need be.
ALIGNMENT_FIELD = 0x130
# The start of the .rsrc segment header.
RSRC_HEADER = 0x268
# Locations in the file where we need to patch in the resource
# segment length.
RESOURCE_LENGTH_PATCHES = [ 0x0184, RSRC_HEADER + 0x8 ]
# Locations in the file where we need to patch in the padded
# resource segment length.
RESOURCE_PADDED_PATCHES = [ RSRC_HEADER + 0x10 ]
# Locations in the file where we need to patch in the change in the
# size of the resource segement (and hence the change in the file's
# total size.)
SIZE_DELTA_PATCHES = [ 0x148 ]
# A location in the file that will be checked to be sure it matches
# RESOURCE_BASE.
CHECK_ADDRESS = RSRC_HEADER + 0x14
# A location in the file that will be checked to make sure it matches
# RESOURCE_VIRTUAL
CHECK_ADDRESS2 = RSRC_HEADER + 0xc
# This class performs various operations on memory-loaded binary files,
# including modifications.
class BinFile(object):
def set_u32(self, addr, value):
self.a[addr+0] = (value >> 0) & 0xff
self.a[addr+1] = (value >> 8) & 0xff
self.a[addr+2] = (value >> 16) & 0xff
self.a[addr+3] = (value >> 24) & 0xff
def u32(self):
addr = self.addr
rv = self.a[addr]
rv |= self.a[addr+1] << 8
rv |= self.a[addr+2] << 16
rv |= self.a[addr+3] << 24
self.addr += 4
return rv
def u16(self):
addr = self.addr
rv = self.a[addr]
rv |= self.a[addr+1] << 8
self.addr += 2
return rv
def u8(self):
rv = self.a[self.addr]
self.addr += 1
return rv
def name(self):
c = self.u16()
rv = u""
for i in range(c):
rv += unichr(self.u16())
return rv
def seek(self, addr):
self.addr = addr
def tostring(self):
return self.a.tostring()
def substring(self, start, len):
return self.a[start:start+len].tostring()
def __init__(self, fn):
data = open(fn, "rb").read()
self.a = array.array('B')
self.a.fromstring(data)
##############################################################################
# These functions parse data out of the file. In these functions, offset is
# relative to the start of the file.
# This parses a data block out of the resources.
def parse_data(offset):
pe.seek(RESOURCE_BASE + offset)
data_offset = pe.u32()
data_len = pe.u32()
code_page = pe.u32()
pe.u32()
l = [ ]
pe.seek(data_offset + RESOURCE_BASE - RESOURCE_VIRTUAL)
for i in range(data_len):
l.append(chr(pe.u8()))
return (code_page, "".join(l))
# This parses a resource directory.
def parse_directory(offset):
pe.seek(RESOURCE_BASE + offset)
char = pe.u32()
timedate = pe.u32()
major = pe.u16()
minor = pe.u16()
n_named = pe.u16()
n_id = pe.u16()
entries = [ ]
for i in range(n_named + n_id):
entries.append((pe.u32(), pe.u32()))
rv = { }
for name, value in entries:
if name & 0x80000000:
pe.seek((name & 0x7fffffff) + RESOURCE_BASE)
name = pe.name()
if value & 0x80000000:
value = parse_directory(value & 0x7fffffff)
else:
value = parse_data(value)
rv[name] = value
return rv
##############################################################################
# This utility function displays the tree of resources that have been loaded.
def show_resources(d, prefix):
if not isinstance(d, dict):
print prefix, "Codepage", d[0], "length", len(d[1])
return
for k in d:
print prefix, k
show_resources(d[k], prefix + " ")
##############################################################################
# These functions repack the resources into a new resource segment. Here,
# the offset is relative to the start of the resource segment.
class Packer(object):
def pack(self, d):
self.data = ""
self.data_offset = 0
self.entries = ""
self.entries_offset = 0
head = self.pack_dict(d, 0)
self.data = ""
self.data_offset = len(head) + len(self.entries)
self.entries = ""
self.entries_offset = len(head)
return self.pack_dict(d, 0) + self.entries + self.data
def pack_name(self, s):
rv = self.data_offset + len(self.data)
l = len(s)
s = s.encode("utf-16le")
self.data += struct.pack("<H", l) + s + "\0\0"
return rv
def pack_tuple(self, t):
codepage, data = t
rv = len(self.entries) + self.entries_offset
if len(self.data) % 2:
self.data += "P"
daddr = len(self.data) + self.data_offset
self.entries += struct.pack("<IIII", daddr + RESOURCE_VIRTUAL, len(data), codepage, 0)
self.data += data
# if len(self.data) % 1 == 1:
# self.data += 'P'
return rv
def pack_dict(self, d, offset):
name_entries = sorted((a, b) for a, b in d.iteritems() if isinstance(a, unicode))
id_entries = sorted((a, b) for a, b in d.iteritems() if isinstance(a, int))
rv = struct.pack("<IIHHHH", 0, 0, 4, 0, len(name_entries), len(id_entries))
offset += len(rv) + (len(name_entries) + len(id_entries)) * 8
rest = ""
for (name, value) in name_entries + id_entries:
if isinstance(name, unicode):
name = 0x80000000 | self.pack_name(name)
if isinstance(value, dict):
addr = offset | 0x80000000
packed = self.pack_dict(value, offset)
offset += len(packed)
rest += packed
else:
addr = self.pack_tuple(value)
rv += struct.pack("<II", name, addr)
return rv + rest
##############################################################################
# This loads in an icon file, and returns a dictionary that is suitable for
# use in the resources of an exe file.
def load_icon(fn):
f = BinFile(fn)
f.seek(0)
f.u16()
f.u16()
count = f.u16()
rv = { }
rv[3] = { }
group = struct.pack("HHH", 0, 1, count)
for i in range(count):
width = f.u8()
height = f.u8()
colors = f.u8()
reserved = f.u8()
planes = f.u16()
bpp = f.u16()
size = f.u32()
offset = f.u32()
addr = f.addr
f.seek(offset + 16)
if not f.u32():
f.set_u32(offset + 20, 0)
rv[3][i + 1] = { 0 : (1252, f.substring(offset, size)) }
group += struct.pack("BBBBHHIH", width, height, colors, reserved,
planes, bpp, size, i + 1)
f.seek(addr)
rv[14] = { 1 : { 0 : (1252, group) } }
return rv
##############################################################################
# This is the main function that should be called externally, that copies over
# the icons.
def change_icons(oldexe, icofn):
global pe
pe = BinFile(oldexe)
# Check that RESOURCE_BASE and RESOURCE_VIRTUAL are still valid.
pe.seek(CHECK_ADDRESS)
if pe.u32() != RESOURCE_BASE:
raise Exception("RESOURCE_BASE is no longer correct. Please check all relocations.")
pe.seek(CHECK_ADDRESS2)
if pe.u32() != RESOURCE_VIRTUAL:
raise Exception("RESOURCE_VIRTUAL is no longer correct. Please check all relocations.")
resources = parse_directory(0)
# show_resources(resources, "")
resources.update(load_icon(icofn))
# show_resources(resources, "")
rsrc = Packer().pack(resources)
rsrc_len = len(rsrc)
pe.seek(ALIGNMENT_FIELD)
alignment = pe.u32()
if len(rsrc) % alignment:
pad = alignment - (len(rsrc) % alignment)
padding = "RENPYVNE" * (pad / 8 + 1)
padding = padding[:pad]
rsrc += padding
padded_len = len(rsrc)
for addr in RESOURCE_LENGTH_PATCHES:
pe.set_u32(addr, rsrc_len)
for addr in RESOURCE_PADDED_PATCHES:
pe.seek(addr)
size_delta = padded_len - pe.u32()
pe.set_u32(addr, padded_len)
for addr in SIZE_DELTA_PATCHES:
pe.seek(addr)
pe.set_u32(addr, pe.u32() + size_delta)
return pe.tostring()[:RESOURCE_BASE] + rsrc
if __name__ == "__main__":
f = file(sys.argv[3], "wb")
f.write(change_icons(sys.argv[1], sys.argv[2]))
f.close()
-244
View File
@@ -1,244 +0,0 @@
init 1 python:
theme_data = {'Basic Blue': {'disabled': '#404040',
'disabled_text': '#c8c8c8',
'frame': '#6496c8',
'gm_root': '#dcebff',
'label': '#ffffff',
'mm_root': '#dcebff',
'theme': 'roundrect',
'widget': '#003c78',
'widget_hover': '#0050a0',
'widget_selected': '#ffffc8',
'widget_text': '#c8ffff'},
'Bloody Mary': {'disabled': '#400000',
'disabled_text': '#260000',
'frame': '#400808',
'gm_root': '#000000',
'label': '#ffffff',
'mm_root': '#000000',
'theme': 'roundrect',
'widget': '#000000',
'widget_hover': '#830000',
'widget_selected': '#ffffff',
'widget_text': '#C2C2C2'},
'Colorblind': {'disabled': '#898989',
'disabled_text': '#666666',
'frame': '#252525',
'gm_root': '#393939',
'label': '#c2c2c2',
'mm_root': '#393939',
'theme': 'roundrect',
'widget': '#898989',
'widget_hover': '#464646',
'widget_selected': '#F2F2F2',
'widget_text': '#CCCCCC'},
'Cotton Candy': {'disabled': '#C8AFA1',
'disabled_text': '#E1D4C9',
'frame': '#FCF5F2',
'gm_root': '#D0B4BA',
'label': '#805C40',
'mm_root': '#D0B4BA',
'theme': 'roundrect',
'widget': '#ECC7D0',
'widget_hover': '#E1D4C9',
'widget_selected': '#805C40',
'widget_text': '#805C40'},
'Creamsicle': {'disabled': '#FFECBF',
'disabled_text': '#ffffff',
'frame': '#FFECBF',
'gm_root': '#FDF5E3',
'label': '#502F13',
'mm_root': '#FDF5E3',
'theme': 'roundrect',
'widget': '#D96B00',
'widget_hover': '#FD9B1C',
'widget_selected': '#ffffff',
'widget_text': '#FCE6B1'},
'Dramatic Flesh': {'disabled': '#ab6038',
'disabled_text': '#BF7C51',
'frame': '#49271b',
'gm_root': '#2a201f',
'label': '#ffffff',
'mm_root': '#2a201f',
'theme': 'roundrect',
'widget': '#BF7C51',
'widget_hover': '#dda570',
'widget_selected': '#ffffff',
'widget_text': '#E5DFDF'},
'Easter Baby': {'disabled': '#DDE9FF',
'disabled_text': '#A6AFBF',
'frame': '#CCF8DC',
'gm_root': '#FBF9DF',
'label': '#698071',
'mm_root': '#FBF9DF',
'theme': 'roundrect',
'widget': '#F5D4EE',
'widget_hover': '#F0DDFF',
'widget_selected': '#000000',
'widget_text': '#698071'},
'Favorite Jeans': {'disabled': '#919994',
'disabled_text': '#B6BFB9',
'frame': '#6f7571',
'gm_root': '#b0b8ba',
'label': '#ffffff',
'mm_root': '#b0b8ba',
'theme': 'roundrect',
'widget': '#8699a7',
'widget_hover': '#9eb1ad',
'widget_selected': '#ffffff',
'widget_text': '#dcdfd6'},
'Fine China': {'disabled': '#ADB9CC',
'disabled_text': '#DFBA14',
'frame': '#ADB9CC',
'gm_root': '#F7F7FA',
'label': '#39435E',
'mm_root': '#F7F7FA',
'theme': 'roundrect',
'widget': '#6A7183',
'widget_hover': '#1A2B47',
'widget_selected': '#E3E3E4',
'widget_text': '#C9C9CB'},
'First Valentines': {'disabled': '#F8F2D0',
'disabled_text': '#BFA1A1',
'frame': '#F8F2D0',
'gm_root': '#D98989',
'label': '#5D1010',
'mm_root': '#D98989',
'theme': 'roundrect',
'widget': '#F09898',
'widget_hover': '#D6C5BB',
'widget_selected': '#B31E1E',
'widget_text': '#593131'},
'Ice Queen': {'disabled': '#F0F2F2',
'disabled_text': '#FBFBFB',
'frame': '#ffffff',
'gm_root': '#E6E6E6',
'label': '#D9D9D9',
'mm_root': '#E6E6E6',
'theme': 'roundrect',
'widget': '#D9D9D9',
'widget_hover': '#F0F2F2',
'widget_selected': '#737373',
'widget_text': '#ffffff'},
'Mocha Latte': {'disabled': '#614D3A',
'disabled_text': '#80654D',
'frame': '#926841',
'gm_root': '#1A140E',
'label': '#F1EBE5',
'mm_root': '#1A140E',
'theme': 'roundrect',
'widget': '#4D3B29',
'widget_hover': '#996E45',
'widget_selected': '#ffffff',
'widget_text': '#B99D83'},
'Muted Horror': {'disabled': '#73735C',
'disabled_text': '#8C8C70',
'frame': '#555544',
'gm_root': '#1A0001',
'label': '#1A0001',
'mm_root': '#1A0001',
'theme': 'roundrect',
'widget': '#777777',
'widget_hover': '#73735C',
'widget_selected': '#000000',
'widget_text': '#404033'},
'Old Polaroid': {'disabled': '#A89E7D',
'disabled_text': '#CCC097',
'frame': '#49403E',
'gm_root': '#A84A3E',
'label': '#ffffff',
'mm_root': '#A84A3E',
'theme': 'roundrect',
'widget': '#A89E7D',
'widget_hover': '#8DB6B9',
'widget_selected': '#ffffff',
'widget_text': '#49403E'},
'Really Red': {'disabled': '#404040',
'disabled_text': '#c8c8c8',
'frame': '#e17373',
'gm_root': '#ffd0d0',
'label': '#ffffff',
'mm_root': '#ffd0d0',
'theme': 'roundrect',
'widget': '#963232',
'widget_hover': '#c83232',
'widget_selected': '#ffffc8',
'widget_text': '#ffffff'},
'Summer Sky': {'disabled': '#6074BF',
'disabled_text': '#7383BF',
'frame': '#6074BF',
'gm_root': '#B4CDD4',
'label': '#94C7D4',
'mm_root': '#B4CDD4',
'theme': 'roundrect',
'widget': '#F2E6AA',
'widget_hover': '#FCFCA4',
'widget_selected': '#1A5766',
'widget_text': '#7DA8B3'},
'Swamp Critter': {'disabled': '#A2521D',
'disabled_text': '#753D00',
'frame': '#797C1C',
'gm_root': '#B09D5A',
'label': '#ffffff',
'mm_root': '#B09B4F',
'theme': 'roundrect',
'widget': '#753D00',
'widget_hover': '#B19A48',
'widget_selected': '#ffffff',
'widget_text': '#CCCAC2'},
'Urban Sprawl': {'disabled': '#8F0000',
'disabled_text': '#333333',
'frame': '#8F0000',
'gm_root': '#000000',
'label': '#ffffff',
'mm_root': '#000000',
'theme': 'roundrect',
'widget': '#333333',
'widget_hover': '#000000',
'widget_selected': '#ffffff',
'widget_text': '#6C8A2F'},
'Victorian Gingerbread': {'disabled': '#7A674F',
'disabled_text': '#664F33',
'frame': '#BF8A73',
'gm_root': '#695640',
'label': '#F2EDC4',
'mm_root': '#695640',
'theme': 'roundrect',
'widget': '#7A674F',
'widget_hover': '#BDA77D',
'widget_selected': '#FDFBEE',
'widget_text': '#F2EDC4'},
'Watermelon Pie': {'disabled': '#FABF46',
'disabled_text': '#FFE06D',
'frame': '#C3CD91',
'gm_root': '#F7F7C5',
'label': '#FCFCD7',
'mm_root': '#F7F7C5',
'theme': 'roundrect',
'widget': '#FFE06D',
'widget_hover': '#E38A4F',
'widget_selected': '#996600',
'widget_text': '#FAA700'},
'White Chocolate': {'disabled': '#614D3A',
'disabled_text': '#80654D',
'frame': '#926841',
'gm_root': '#FBF9EA',
'label': '#F1EBE5',
'mm_root': '#FBF9EA',
'theme': 'roundrect',
'widget': '#33271C',
'widget_hover': '#ECE7C4',
'widget_selected': '#ffffff',
'widget_text': '#B99D83'},
'Winter Mint': {'disabled': '#426143',
'disabled_text': '#819981',
'frame': '#245536',
'gm_root': '#e5f1e5',
'label': '#ffffff',
'mm_root': '#e5f1e5',
'theme': 'roundrect',
'widget': '#7AA27B',
'widget_hover': '#A3C7A3',
'widget_selected': '#ffffff',
'widget_text': '#CDE0CE'}}
+96
View File
@@ -0,0 +1,96 @@
#!/usr/bin/env python
import sys
sys.path.append('/home/tom/ab/keys/')
import os
import bz2
import hashlib
import public
import private
import shutil
def sha(s):
"""
Hashes s into a string.
"""
hash = hashlib.sha256()
hash.update(s)
return hash.hexdigest()
def make_update(root, version):
# A list of command strings.
commands = [ ]
for dir, dirs, files in os.walk(root):
for fn in files:
fn = os.path.join(dir, fn)
oldf = file(fn, "rb")
bzf = bz2.BZ2File(fn + ".bz2", "wb")
bzf.write(oldf.read())
bzf.close()
oldf.close()
shutil.copymode(fn, fn + ".bz2")
os.unlink(fn)
for dir, dirs, files in os.walk(root):
for fn in dirs + files:
path = os.path.join(dir, fn)
relpath = os.path.relpath(path, root)
if relpath in [ "version", "catalog1.bz2" ]:
continue
if os.path.isdir(path):
commands.append(('dir', "base", relpath))
elif relpath.endswith(".rpyc.bz2"):
continue
elif relpath.endswith(".rpymc.bz2"):
continue
elif relpath.endswith(".rpyb.bz2"):
continue
elif relpath.endswith(".pyo.bz2"):
continue
elif relpath.endswith(".bz2"):
hash = sha(bz2.BZ2File(path, "r").read())
size = "%d" % (os.path.getsize(path))
commands.append(('file', hash, size, "base", relpath[:-4]))
if os.access(path, os.X_OK):
commands.append(('xbit', relpath[:-4]))
out = bz2.BZ2File(os.path.join(root, "catalog1.bz2"), "w")
hash = hashlib.sha256()
for i in commands:
line = "\t".join(i) + "\n"
hash.update(line)
out.write(line)
unsigned = int("01" + hash.hexdigest(), 16)
signed = pow(unsigned, private.exponent, public.modulus)
out.write("-\n")
out.write("signature\t%x\n" % signed)
out.close()
f = file(os.path.join(root, "version"), "w")
f.write(version)
f.write("\n")
f.write("the latest Ren'Py pre-release")
f.close()
+626 -266
View File
File diff suppressed because it is too large Load Diff
+47 -9
View File
@@ -105,11 +105,13 @@ def premultiply(
int x,
int y,
int w,
int h):
int h,
border_left, border_top, border_right, border_bottom):
"""
Creates a string containing the premultiplied image data for
for the (x, y, w, h) box inside pysurf.
for the (x, y, w, h) box inside pysurf. The various border_
parameters control the addition of a border on the sides.
"""
# Adjust the alpha if we have an alpha-free image.
@@ -145,8 +147,10 @@ def premultiply(
# alpha value.
cdef unsigned int a
# pixel pointer.
cdef unsigned int *pp
surf = PySurface_AsSurface(pysurf)
pixels = <unsigned char *> surf.pixels
@@ -170,10 +174,42 @@ def premultiply(
p += 4
op += 4
if border_left:
pp = <unsigned int *> (out)
for y from 0 <= y < h:
pp[0] = pp[1]
pp += w
if border_right:
pp = <unsigned int *> (out)
pp += w - 2
for y from 0 <= y < h:
pp[1] = pp[0]
pp += w
if border_top:
pp = <unsigned int *> (out)
for x from 0 <= x < w:
pp[0] = pp[w]
pp += 1
if border_top:
pp = <unsigned int *> (out)
pp += (y - 2) * w
for x from 0 <= x < w:
pp[w] = pp[0]
pp += 1
return rv
def load_premultiplied(data, width, height, update):
def load_premultiplied(
data, width, height, update, format,
):
cdef char *pixels
@@ -191,7 +227,7 @@ def load_premultiplied(data, width, height, update):
0,
width,
height,
GL_BGRA,
format,
GL_UNSIGNED_BYTE,
pixels)
@@ -203,13 +239,14 @@ def load_premultiplied(data, width, height, update):
width,
height,
0,
GL_BGRA,
format,
GL_UNSIGNED_BYTE,
pixels)
def store_framebuffer(
object pysurf,
int format,
):
"""
@@ -231,7 +268,7 @@ def store_framebuffer(
0,
surf.w,
surf.h,
GL_BGRA,
format,
GL_UNSIGNED_BYTE,
pixels)
@@ -246,7 +283,8 @@ def draw_rectangle(
transform,
tex0, int tex0x, int tex0y,
tex1, int tex1x, int tex1y,
tex2, int tex2x, int tex2y):
tex2, int tex2x, int tex2y,
):
"""
This draws a rectangle (textured with up to four textures) to the
+116 -84
View File
@@ -85,7 +85,9 @@ typedef struct PacketQueue {
typedef struct VideoPicture {
double pts; ///<presentation time stamp for this picture
SDL_Overlay *bmp;
SDL_Surface *surf;
AVFrame *frame;
int fmt;
int width, height; /* source height & width */
int allocated;
} VideoPicture;
@@ -684,15 +686,19 @@ static void free_subpicture(SubPicture *sp)
static void video_image_display(VideoState *is)
{
VideoPicture *vp;
#if 0
SubPicture *sp;
#endif
AVPicture pict;
float aspect_ratio;
int width, height, x, y;
SDL_Rect rect;
int i;
static struct SwsContext *img_convert_ctx;
vp = &is->pictq[is->pictq_rindex];
if (vp->bmp) {
if (vp->surf) {
/* XXX: use variable in the frame */
if (is->video_st->sample_aspect_ratio.num)
aspect_ratio = av_q2d(is->video_st->sample_aspect_ratio);
@@ -738,6 +744,7 @@ static void video_image_display(VideoState *is)
}
#endif
#if 0
if (is->subtitle_st)
{
if (is->subpq_size > 0)
@@ -764,35 +771,60 @@ static void video_image_display(VideoState *is)
}
}
}
#endif
/* XXX: we suppose the screen has a 1.0 pixel ratio */
height = is->height;
width = ((int)rint(height * aspect_ratio)) & ~1;
if (width > is->width) {
width = is->width;
height = ((int)rint(width / aspect_ratio)) & ~1;
}
x = (is->width - width) / 2;
y = (is->height - height) / 2;
if (!is->no_background) {
/* fill the background */
// fill_border(is, x, y, width, height, QERGB(0x00, 0x00, 0x00));
} else {
is->no_background = 0;
}
rect.x = is->xleft + x;
rect.y = is->ytop + y;
rect.w = width;
rect.h = height;
SDL_DisplayYUVOverlay(vp->bmp, &rect);
img_convert_ctx = sws_getCachedContext(
img_convert_ctx,
is->video_st->codec->width,
is->video_st->codec->height,
is->video_st->codec->pix_fmt,
rect.w,
rect.h,
vp->fmt, //dst_pix_fmt,
sws_flags,
NULL, NULL, NULL);
if (img_convert_ctx != NULL) {
pict.data[0] = &((uint8_t *)vp->surf->pixels)[rect.y * vp->surf->pitch + rect.x * 4];
pict.linesize[0] = vp->surf->pitch;
sws_scale(
img_convert_ctx,
(const uint8_t * const *) vp->frame->data,
vp->frame->linesize,
0,
is->video_st->codec->height,
pict.data,
pict.linesize);
}
} else {
#if 0
fill_rectangle(screen,
is->xleft, is->ytop, is->width, is->height,
QERGB(0x00, 0x00, 0x00));
#endif
}
}
@@ -970,8 +1002,10 @@ static void video_refresh_timer(void *opaque)
VideoState *is = opaque;
VideoPicture *vp;
#if 0
SubPicture *sp, *sp2;
#endif
double delay;
if (is->video_st) {
@@ -1039,7 +1073,10 @@ static void video_refresh_timer(void *opaque)
if (delay > 0.010) {
video_display(is);
}
av_free(vp->frame);
vp->frame = NULL;
/* update queue size and signal for next picture */
if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)
is->pictq_rindex = 0;
@@ -1085,9 +1122,11 @@ static void alloc_picture(void *opaque, PyObject *pysurf)
{
VideoState *is = opaque;
VideoPicture *vp;
SDL_Surface *surf;
uint32_t pixel;
uint8_t *bytes = (uint8_t *) &pixel;
if (!is->needs_alloc) {
return;
}
@@ -1097,39 +1136,26 @@ static void alloc_picture(void *opaque, PyObject *pysurf)
surf = PySurface_AsSurface(pysurf);
is->width = surf->w;
is->height = surf->h;
vp = &is->pictq[is->pictq_windex];
if (vp->bmp)
SDL_FreeYUVOverlay(vp->bmp);
#if 0
/* XXX: use generic function */
/* XXX: disable overlay if no hardware acceleration or if RGB format */
switch(is->video_st->codec->pix_fmt) {
case PIX_FMT_YUV420P:
case PIX_FMT_YUV422P:
case PIX_FMT_YUV444P:
case PIX_FMT_YUYV422:
case PIX_FMT_YUV410P:
case PIX_FMT_YUV411P:
is_yuv = 1;
break;
default:
is_yuv = 0;
break;
}
#endif
vp->bmp = SDL_CreateYUVOverlay(
is->video_st->codec->width,
is->video_st->codec->height,
SDL_YV12_OVERLAY,
surf);
vp->surf = surf;
vp->width = is->video_st->codec->width;
vp->height = is->video_st->codec->height;
pixel = SDL_MapRGBA(surf->format, 1, 2, 3, 4);
if (bytes[0] == 4 && bytes[1] == 1) {
vp->fmt = PIX_FMT_ARGB;
} else if (bytes[0] == 4 && bytes[1] == 3) {
vp->fmt = PIX_FMT_ABGR;
} else if (bytes[0] == 1) {
vp->fmt = PIX_FMT_RGBA;
} else {
vp->fmt = PIX_FMT_BGRA;
}
pixel = SDL_MapRGBA(surf->format, 0, 0, 0, 255);
SDL_FillRect(surf, NULL, pixel);
SDL_LockMutex(is->pictq_mutex);
vp->allocated = 1;
SDL_CondSignal(is->pictq_cond);
@@ -1143,10 +1169,13 @@ static void alloc_picture(void *opaque, PyObject *pysurf)
static int queue_picture(VideoState *is, AVFrame *src_frame, double pts)
{
VideoPicture *vp;
#if 0
int dst_pix_fmt;
AVPicture pict;
static struct SwsContext *img_convert_ctx;
#endif
/* wait until we have space to put a new picture */
SDL_LockMutex(is->pictq_mutex);
while (is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE &&
@@ -1161,13 +1190,12 @@ static int queue_picture(VideoState *is, AVFrame *src_frame, double pts)
vp = &is->pictq[is->pictq_windex];
/* alloc or resize hardware picture buffer */
if (!vp->bmp ||
if (!vp->surf ||
vp->width != is->video_st->codec->width ||
vp->height != is->video_st->codec->height) {
SDL_Event event;
vp->allocated = 0;
is->needs_alloc = 1;
/* the allocation must be done in the main thread to avoid
@@ -1175,7 +1203,6 @@ static int queue_picture(VideoState *is, AVFrame *src_frame, double pts)
event.type = FF_ALLOC_EVENT;
event.user.data1 = is;
SDL_PushEvent(&event);
/* wait until the picture is allocated */
SDL_LockMutex(is->pictq_mutex);
@@ -1188,42 +1215,47 @@ static int queue_picture(VideoState *is, AVFrame *src_frame, double pts)
return -1;
}
/* if the frame is not skipped, then display it */
if (vp->bmp) {
/* get a pointer on the bitmap */
SDL_LockYUVOverlay (vp->bmp);
vp->frame = src_frame;
vp->pts = pts;
dst_pix_fmt = PIX_FMT_YUV420P;
pict.data[0] = vp->bmp->pixels[0];
pict.data[1] = vp->bmp->pixels[2];
pict.data[2] = vp->bmp->pixels[1];
pict.linesize[0] = vp->bmp->pitches[0];
pict.linesize[1] = vp->bmp->pitches[2];
pict.linesize[2] = vp->bmp->pitches[1];
// sws_flags = av_get_int(sws_opts, "sws_flags", NULL);
img_convert_ctx = sws_getCachedContext(img_convert_ctx,
is->video_st->codec->width, is->video_st->codec->height,
is->video_st->codec->pix_fmt,
is->video_st->codec->width, is->video_st->codec->height,
dst_pix_fmt, sws_flags, NULL, NULL, NULL);
if (img_convert_ctx == NULL) {
fprintf(stderr, "Cannot initialize the conversion context\n");
}
sws_scale(img_convert_ctx, src_frame->data, src_frame->linesize,
0, is->video_st->codec->height, pict.data, pict.linesize);
/* update the bitmap content */
SDL_UnlockYUVOverlay(vp->bmp);
/* now we can update the picture count */
if (++is->pictq_windex == VIDEO_PICTURE_QUEUE_SIZE)
is->pictq_windex = 0;
SDL_LockMutex(is->pictq_mutex);
is->pictq_size++;
SDL_UnlockMutex(is->pictq_mutex);
/* /\* if the frame is not skipped, then display it *\/ */
/* if (vp->bmp) { */
/* /\* get a pointer on the bitmap *\/ */
/* SDL_LockYUVOverlay (vp->bmp); */
vp->pts = pts;
/* dst_pix_fmt = PIX_FMT_YUV420P; */
/* pict.data[0] = vp->bmp->pixels[0]; */
/* pict.data[1] = vp->bmp->pixels[2]; */
/* pict.data[2] = vp->bmp->pixels[1]; */
/* now we can update the picture count */
if (++is->pictq_windex == VIDEO_PICTURE_QUEUE_SIZE)
is->pictq_windex = 0;
SDL_LockMutex(is->pictq_mutex);
is->pictq_size++;
SDL_UnlockMutex(is->pictq_mutex);
}
/* pict.linesize[0] = vp->bmp->pitches[0]; */
/* pict.linesize[1] = vp->bmp->pitches[2]; */
/* pict.linesize[2] = vp->bmp->pitches[1]; */
/* // sws_flags = av_get_int(sws_opts, "sws_flags", NULL); */
/* img_convert_ctx = sws_getCachedContext(img_convert_ctx, */
/* is->video_st->codec->width, is->video_st->codec->height, */
/* is->video_st->codec->pix_fmt, */
/* is->video_st->codec->width, is->video_st->codec->height, */
/* dst_pix_fmt, sws_flags, NULL, NULL, NULL); */
/* if (img_convert_ctx == NULL) { */
/* fprintf(stderr, "Cannot initialize the conversion context\n"); */
/* } */
/* sws_scale(img_convert_ctx, src_frame->data, src_frame->linesize, */
/* 0, is->video_st->codec->height, pict.data, pict.linesize); */
/* /\* update the bitmap content *\/ */
/* SDL_UnlockYUVOverlay(vp->bmp); */
/* vp->pts = pts; */
/* } */
return 0;
}
@@ -1271,10 +1303,12 @@ static int video_thread(void *arg)
VideoState *is = arg;
AVPacket pkt1, *pkt = &pkt1;
int len1, got_picture;
AVFrame *frame= avcodec_alloc_frame();
AVFrame *frame;
double pts;
for(;;) {
frame = avcodec_alloc_frame();
while (is->paused && !is->videoq.abort_request) {
SDL_Delay(10);
}
@@ -1311,7 +1345,6 @@ static int video_thread(void *arg)
av_free_packet(pkt);
}
the_end:
av_free(frame);
return 0;
}
@@ -2268,11 +2301,10 @@ void ffpy_stream_close(VideoState *is)
SDL_WaitThread(is->parse_tid, NULL);
/* free all pictures */
for(i=0;i<VIDEO_PICTURE_QUEUE_SIZE; i++) {
for(i=0; i<VIDEO_PICTURE_QUEUE_SIZE; i++) {
vp = &is->pictq[i];
if (vp->bmp) {
SDL_FreeYUVOverlay(vp->bmp);
vp->bmp = NULL;
if (vp->frame) {
av_free(vp->frame);
}
}
-1
View File
@@ -1 +0,0 @@
dist/msvcr90.dll
BIN
View File
Binary file not shown.
-1
View File
@@ -1 +0,0 @@
dist/python26.dll
-13
View File
@@ -1,13 +0,0 @@
#!/bin/sh
rm -Rf spline_editor/*~
rm -Rf spline_editor/game/*~
rm -Rf spline_editor/game/*.rpyc
rm -Rf spline_editor/game/*.rpyb
rm -Rf spline_editor/game/saves
rm spline_editor.zip
zip -9r spline_editor.zip spline_editor -x \*.svn\*
-1
View File
@@ -1 +0,0 @@
dist/renpy.exe
-877
View File
@@ -1,877 +0,0 @@
# Ren'Py Visual Novel Engine
# Copyright (C) 2009 PyTom <pytom@bishoujo.us>
# This file is distributed under the same license as the Ren'Py package.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: mainline\n"
"Report-Msgid-Bugs-To: PyTom <pytom@bishoujo.us>\n"
"POT-Creation-Date: 2009-06-27 23:09-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: common/00developer.rpy:18
#, python-format
msgid "Developer Menu"
msgstr ""
#: common/00developer.rpy:190 common/00developer.rpy:78
#, python-format
msgid "Return to the developer menu"
msgstr ""
#: common/00library.rpy:221
#, python-format
msgid "Skip Mode"
msgstr ""
#: common/00library.rpy:224
#, python-format
msgid "Fast Skip Mode"
msgstr ""
#: common/00library.rpy:307
#, python-format
msgid "While Ren'Py games may be 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/."
msgstr ""
#: common/00library.rpy:310
#, python-format
msgid "renpy module not found."
msgstr ""
#: common/00library.rpy:311
#, python-format
msgid "The renpy module could not be loaded on your system."
msgstr ""
#: common/00library.rpy:313
#, python-format
msgid "Old renpy module found."
msgstr ""
#: common/00library.rpy:314
#, python-format
msgid "An old version (%d) of the Ren'Py module was found on your system, while this game requires version %d."
msgstr ""
#: common/00library.rpy:498
#, python-format
msgid "Please click to continue."
msgstr ""
#: common/00menus.rpy:14 common/_compat/mainmenu.rpym:7
#, python-format
msgid "Start Game"
msgstr ""
#: common/00menus.rpy:15 common/00menus.rpy:25 common/_compat/gamemenu.rpym:13
#, python-format
msgid "Load Game"
msgstr ""
#: common/00menus.rpy:16 common/00menus.rpy:23 common/_compat/gamemenu.rpym:11 common/_compat/mainmenu.rpym:9
#, python-format
msgid "Preferences"
msgstr ""
#: common/00menus.rpy:17 common/00menus.rpy:27
#, python-format
msgid "Help"
msgstr ""
#: common/00menus.rpy:18 common/00menus.rpy:28 common/_compat/gamemenu.rpym:15 common/_compat/mainmenu.rpym:10
#, python-format
msgid "Quit"
msgstr ""
#: common/00menus.rpy:22 common/_compat/gamemenu.rpym:9 launcher2/archiver.rpy:170 launcher2/distribute.rpy:534 launcher2/interface.rpy:189
#, python-format
msgid "Return"
msgstr ""
#: common/00menus.rpy:24 common/_compat/gamemenu.rpym:12
#, python-format
msgid "Save Game"
msgstr ""
#: common/00menus.rpy:26 common/_compat/gamemenu.rpym:14
#, python-format
msgid "Main Menu"
msgstr ""
#: common/00menus.rpy:34 common/_compat/gamemenu.rpym:427
#, python-format
msgid "Are you sure you want to quit?"
msgstr ""
#: common/00menus.rpy:40 common/_compat/gamemenu.rpym:439
#, python-format
msgid "Are you sure you want to return to the main menu?\nThis will lose unsaved progress."
msgstr ""
#: common/_compat/gamemenu.rpym:10 common/_layout/classic_preferences.rpym:65 common/_layout/classic_preferences_common.rpym:339 common/_layout/one_column_preferences.rpym:52 common/_layout/two_column_preferences.rpym:59
#, python-format
msgid "Begin Skipping"
msgstr ""
#: common/_compat/gamemenu.rpym:177 common/_layout/classic_load_save.rpym:115 common/_layout/imagemap_load_save.rpym:95 common/_layout/scrolling_load_save.rpym:171
#, python-format
msgid "Empty Slot."
msgstr ""
#: common/_compat/gamemenu.rpym:334 common/_layout/classic_load_save.rpym:250
#, python-format
msgid "Previous"
msgstr ""
#: common/_compat/gamemenu.rpym:341 common/_layout/classic_load_save.rpym:257
#, python-format
msgid "Next"
msgstr ""
#: common/_compat/gamemenu.rpym:412 common/_layout/classic_yesno_prompt.rpym:46 launcher2/interface.rpy:223
#, python-format
msgid "Yes"
msgstr ""
#: common/_compat/gamemenu.rpym:413 common/_layout/classic_yesno_prompt.rpym:47 launcher2/interface.rpy:224
#, python-format
msgid "No"
msgstr ""
#: common/_compat/gamemenu.rpym:464 common/_layout/classic_load_save.rpym:328 common/_layout/imagemap_load_save.rpym:325 common/_layout/scrolling_load_save.rpym:214
#, python-format
msgid "Loading will lose unsaved progress.\nAre you sure you want to do this?"
msgstr ""
#: common/_compat/gamemenu.rpym:478 common/_layout/classic_load_save.rpym:314 common/_layout/imagemap_load_save.rpym:312 common/_layout/scrolling_load_save.rpym:200
#, python-format
msgid "Are you sure you want to overwrite your save?"
msgstr ""
#: common/_compat/gamemenu.rpym:494
#, python-format
msgid "The error message was:"
msgstr ""
#: common/_compat/gamemenu.rpym:496
#, python-format
msgid "You may want to try saving in a different slot, or playing for a while and trying again later."
msgstr ""
#: common/_compat/gamemenu.rpym:498
#, python-format
msgid "Save Failed."
msgstr ""
#: common/_compat/mainmenu.rpym:8
#, python-format
msgid "Continue Game"
msgstr ""
#: common/_compat/preferences.rpym:225 common/_layout/classic_preferences_common.rpym:179 common/_layout/classic_preferences_common.rpym:190 launcher2/choose_theme.rpy:228
#, python-format
msgid "Test"
msgstr ""
#: common/_compat/preferences.rpym:34 common/_layout/classic_joystick_preferences.rpym:32
#, python-format
msgid "Left"
msgstr ""
#: common/_compat/preferences.rpym:35 common/_layout/classic_joystick_preferences.rpym:33
#, python-format
msgid "Right"
msgstr ""
#: common/_compat/preferences.rpym:36 common/_layout/classic_joystick_preferences.rpym:34
#, python-format
msgid "Up"
msgstr ""
#: common/_compat/preferences.rpym:37 common/_layout/classic_joystick_preferences.rpym:35
#, python-format
msgid "Down"
msgstr ""
#: common/_compat/preferences.rpym:377 common/_compat/preferences.rpym:428 common/_layout/classic_joystick_preferences.rpym:51 common/_layout/classic_joystick_preferences.rpym:93
#, python-format
msgid "Not Assigned"
msgstr ""
#: common/_compat/preferences.rpym:38 common/_layout/classic_joystick_preferences.rpym:36
#, python-format
msgid "Select/Dismiss"
msgstr ""
#: common/_compat/preferences.rpym:39 common/_layout/classic_joystick_preferences.rpym:37
#, python-format
msgid "Rollback"
msgstr ""
#: common/_compat/preferences.rpym:40 common/_layout/classic_joystick_preferences.rpym:38
#, python-format
msgid "Hold to Skip"
msgstr ""
#: common/_compat/preferences.rpym:408 common/_layout/classic_joystick_preferences.rpym:73
#, python-format
msgid "Joystick Mapping"
msgstr ""
#: common/_compat/preferences.rpym:409 common/_layout/classic_joystick_preferences.rpym:74
#, python-format
msgid "Move the joystick or press a joystick button to create the mapping. Click the mouse to remove the mapping."
msgstr ""
#: common/_compat/preferences.rpym:41 common/_layout/classic_joystick_preferences.rpym:39
#, python-format
msgid "Toggle Skip"
msgstr ""
#: common/_compat/preferences.rpym:42 common/_layout/classic_joystick_preferences.rpym:40
#, python-format
msgid "Hide Text"
msgstr ""
#: common/_compat/preferences.rpym:43 common/_layout/classic_joystick_preferences.rpym:41
#, python-format
msgid "Menu"
msgstr ""
#: common/_compat/preferences.rpym:482 common/_compat/preferences.rpym:557 common/_layout/classic_preferences.rpym:57 common/_layout/classic_preferences_common.rpym:321 common/_layout/one_column_preferences.rpym:49 common/_layout/two_column_preferences.rpym:56 launcher2/choose_theme.rpy:208
#, python-format
msgid "Display"
msgstr ""
#: common/_compat/preferences.rpym:483 common/_layout/classic_preferences_common.rpym:322 launcher2/choose_theme.rpy:209
#, python-format
msgid "Window"
msgstr ""
#: common/_compat/preferences.rpym:484 common/_layout/classic_preferences_common.rpym:323 launcher2/choose_theme.rpy:210
#, python-format
msgid "Fullscreen"
msgstr ""
#: common/_compat/preferences.rpym:487 common/_compat/preferences.rpym:558 common/_layout/classic_preferences.rpym:58 common/_layout/classic_preferences_common.rpym:326 common/_layout/one_column_preferences.rpym:50 common/_layout/two_column_preferences.rpym:57
#, python-format
msgid "Transitions"
msgstr ""
#: common/_compat/preferences.rpym:488 common/_layout/classic_preferences_common.rpym:327
#, python-format
msgid "All"
msgstr ""
#: common/_compat/preferences.rpym:489 common/_layout/classic_preferences_common.rpym:328
#, python-format
msgid "Some"
msgstr ""
#: common/_compat/preferences.rpym:490 common/_layout/classic_preferences_common.rpym:329
#, python-format
msgid "None"
msgstr ""
#: common/_compat/preferences.rpym:495 common/_compat/preferences.rpym:563 common/_layout/classic_preferences.rpym:64 common/_layout/classic_preferences_common.rpym:334 common/_layout/one_column_preferences.rpym:51 common/_layout/two_column_preferences.rpym:58
#, python-format
msgid "Skip"
msgstr ""
#: common/_compat/preferences.rpym:496 common/_layout/classic_preferences_common.rpym:335
#, python-format
msgid "Seen Messages"
msgstr ""
#: common/_compat/preferences.rpym:497 common/_layout/classic_preferences_common.rpym:336
#, python-format
msgid "All Messages"
msgstr ""
#: common/_compat/preferences.rpym:504 common/_compat/preferences.rpym:564 common/_layout/classic_preferences.rpym:66 common/_layout/classic_preferences_common.rpym:345 common/_layout/one_column_preferences.rpym:53 common/_layout/two_column_preferences.rpym:60
#, python-format
msgid "After Choices"
msgstr ""
#: common/_compat/preferences.rpym:505 common/_layout/classic_preferences_common.rpym:346
#, python-format
msgid "Stop Skipping"
msgstr ""
#: common/_compat/preferences.rpym:506 common/_layout/classic_preferences_common.rpym:347
#, python-format
msgid "Keep Skipping"
msgstr ""
#: common/_compat/preferences.rpym:526 common/_compat/preferences.rpym:565 common/_layout/classic_preferences.rpym:59 common/_layout/classic_preferences_common.rpym:352 common/_layout/one_column_preferences.rpym:54 common/_layout/two_column_preferences.rpym:61
#, python-format
msgid "Text Speed"
msgstr ""
#: common/_compat/preferences.rpym:544 common/_compat/preferences.rpym:566 common/_layout/classic_preferences.rpym:67 common/_layout/classic_preferences_common.rpym:353 common/_layout/one_column_preferences.rpym:55 common/_layout/two_column_preferences.rpym:62
#, python-format
msgid "Auto-Forward Time"
msgstr ""
#: common/_compat/preferences.rpym:549 common/_compat/preferences.rpym:570 common/_layout/classic_preferences.rpym:71 common/_layout/classic_preferences_common.rpym:357 common/_layout/one_column_preferences.rpym:56 common/_layout/two_column_preferences.rpym:66
#, python-format
msgid "Music Volume"
msgstr ""
#: common/_compat/preferences.rpym:550 common/_compat/preferences.rpym:571 common/_layout/classic_preferences.rpym:72 common/_layout/classic_preferences_common.rpym:360 common/_layout/one_column_preferences.rpym:57 common/_layout/two_column_preferences.rpym:67
#, python-format
msgid "Sound Volume"
msgstr ""
#: common/_compat/preferences.rpym:552 common/_compat/preferences.rpym:559 common/_layout/classic_preferences.rpym:60 common/_layout/classic_preferences_common.rpym:370 common/_layout/one_column_preferences.rpym:59 common/_layout/two_column_preferences.rpym:69
#, python-format
msgid "Joystick..."
msgstr ""
#: common/_compat/preferences.rpym:554 common/_compat/preferences.rpym:575
#, python-format
msgid "Joystick Configuration"
msgstr ""
#: common/_compat/preferences.rpym:580 common/_layout/classic_preferences.rpym:73 common/_layout/classic_preferences_common.rpym:364 common/_layout/one_column_preferences.rpym:58 common/_layout/two_column_preferences.rpym:68
#, python-format
msgid "Voice Volume"
msgstr ""
#: common/_layout/classic_load_save.rpym:126
#, python-format
msgid "Auto"
msgstr ""
#: common/_layout/classic_load_save.rpym:129
#, python-format
msgid "Quick"
msgstr ""
#: launcher2/archiver.rpy:135
#, python-format
msgid "The patterns did not match any files, so no archive was created."
msgstr ""
#: launcher2/archiver.rpy:138
#, python-format
msgid "Archiving Files..."
msgstr ""
#: launcher2/archiver.rpy:165 launcher2/distribute.rpy:529
#, python-format
msgid "Success"
msgstr ""
#: launcher2/archiver.rpy:166
#, python-format
msgid "The files have been added to the archive, and moved into the \"archived\" directory. Future runs of the archiver will archive files in both the \"game\" and \"archived\" directories."
msgstr ""
#: launcher2/archiver.rpy:30
#, python-format
msgid "Archive Name:"
msgstr ""
#: launcher2/archiver.rpy:31
#, python-format
msgid "The name of the archive to create."
msgstr ""
#: launcher2/archiver.rpy:33
#, python-format
msgid "Include Patterns:"
msgstr ""
#: launcher2/archiver.rpy:34
#, python-format
msgid "Files matching these patterns are included in the archive."
msgstr ""
#: launcher2/archiver.rpy:36
#, python-format
msgid "Exclude Patterns:"
msgstr ""
#: launcher2/archiver.rpy:37
#, python-format
msgid "Files matching these patterns are excluded from the archive."
msgstr ""
#: launcher2/archiver.rpy:41
#, python-format
msgid "Archive"
msgstr ""
#: launcher2/archiver.rpy:41
#, python-format
msgid "Build the archive."
msgstr ""
#: launcher2/archiver.rpy:42 launcher2/distribute.rpy:304 launcher2/interface.rpy:159
#, python-format
msgid "Cancel"
msgstr ""
#: launcher2/archiver.rpy:50
#, python-format
msgid "Archive Name"
msgstr ""
#: launcher2/archiver.rpy:51
#, python-format
msgid "The name of the archive file to create, without the .rpa extension.\n\nThe \"data\" archive is loaded automatically. Other archives must be added to config.archives."
msgstr ""
#: launcher2/archiver.rpy:56 launcher2/archiver.rpy:62
#, python-format
msgid "Include Patterns"
msgstr ""
#: launcher2/archiver.rpy:57
#, python-format
msgid "This is a space-separated list of file patterns. Files matching these patterns are added to the archive.\n\nAsterisks (*) can be used as a wildcard."
msgstr ""
#: launcher2/archiver.rpy:63
#, python-format
msgid "This is a space-separated list of file patterns. Files matching these patterns are excluded from the archive. If a file is matched by both an exclude and include pattern, the exclude takes precedence.\n\nAsterisks (*) can be used as a wildcard."
msgstr ""
#: launcher2/archiver.rpy:98
#, python-format
msgid "Scanning Files..."
msgstr ""
#: launcher2/choose_theme.rpy:155
#, python-format
msgid "Could not modify options.rpy. Perhaps it was changed too much."
msgstr ""
#: launcher2/choose_theme.rpy:157
#, python-format
msgid "Theme changed to %s."
msgstr ""
#: launcher2/choose_theme.rpy:211
#, python-format
msgid "Planetarium"
msgstr ""
#: launcher2/choose_theme.rpy:245
#, python-format
msgid "The options.rpy file does not exist in the game directory, so this launcher cannot change the theme."
msgstr ""
#: launcher2/choose_theme.rpy:254
#, python-format
msgid "Themes control the basic look of interface elements. You'll be able to pick a color scheme next."
msgstr ""
#: launcher2/choose_theme.rpy:258 launcher2/script.rpy:45
#, python-format
msgid "Choose Theme"
msgstr ""
#: launcher2/choose_theme.rpy:296
#, python-format
msgid "Please choose a color scheme for your project."
msgstr ""
#: launcher2/choose_theme.rpy:303
#, python-format
msgid "Choose Color Scheme"
msgstr ""
#: launcher2/distribute.rpy:270
#, python-format
msgid "Base Name:"
msgstr ""
#: launcher2/distribute.rpy:271
#, python-format
msgid "Used to generate the names of directories and archive files."
msgstr ""
#: launcher2/distribute.rpy:273
#, python-format
msgid "Executable Name:"
msgstr ""
#: launcher2/distribute.rpy:274
#, python-format
msgid "Used to generate the names of executables and runnable programs."
msgstr ""
#: launcher2/distribute.rpy:276
#, python-format
msgid "Ignore Extensions:"
msgstr ""
#: launcher2/distribute.rpy:277
#, python-format
msgid "Files with these extensions will not be included in the distributions."
msgstr ""
#: launcher2/distribute.rpy:279
#, python-format
msgid "Documentation Extensions:"
msgstr ""
#: launcher2/distribute.rpy:280
#, python-format
msgid "Files with these extensions will be treated as documentation, when building the Macintosh application."
msgstr ""
#: launcher2/distribute.rpy:282
#, python-format
msgid "Distributions to Build:"
msgstr ""
#: launcher2/distribute.rpy:285
#, python-format
msgid "Windows x86"
msgstr ""
#: launcher2/distribute.rpy:286
#, python-format
msgid "Zip distribution for the 32-bit Windows platform."
msgstr ""
#: launcher2/distribute.rpy:289
#, python-format
msgid "Linux x86"
msgstr ""
#: launcher2/distribute.rpy:290
#, python-format
msgid "Tar.Bz2 distribution for the Linux x86 platform."
msgstr ""
#: launcher2/distribute.rpy:293
#, python-format
msgid "Macintosh Universal"
msgstr ""
#: launcher2/distribute.rpy:294
#, python-format
msgid "Single application distribution for the Macintosh x86 and ppc platforms."
msgstr ""
#: launcher2/distribute.rpy:297
#, python-format
msgid "Windows/Linux/Mac Combined"
msgstr ""
#: launcher2/distribute.rpy:298
#, python-format
msgid "Zip distribution for the Windows x86, Linux x86, Macintosh x86 and Macintosh ppc platforms."
msgstr ""
#: launcher2/distribute.rpy:303
#, python-format
msgid "Build"
msgstr ""
#: launcher2/distribute.rpy:303
#, python-format
msgid "Start building the distributions."
msgstr ""
#: launcher2/distribute.rpy:321
#, python-format
msgid "Base Name"
msgstr ""
#: launcher2/distribute.rpy:322
#, python-format
msgid "Please enter in the base name for your distribution. This name is used to generate the names of directories and archive files. Usually, this is the name of your game, plus a version number, like \"moonlight-1.0\"."
msgstr ""
#: launcher2/distribute.rpy:328
#, python-format
msgid "Executable Name"
msgstr ""
#: launcher2/distribute.rpy:329
#, python-format
msgid "Please enter a name for the executables in your distribution. This should not include an extension, as that will be added automatically."
msgstr ""
#: launcher2/distribute.rpy:335
#, python-format
msgid "Ignore Extensions"
msgstr ""
#: launcher2/distribute.rpy:336
#, python-format
msgid "Please enter a space-separated list of file extensions. Files with these extensions will not be included in the built distributions."
msgstr ""
#: launcher2/distribute.rpy:342
#, python-format
msgid "Documentation Extensions"
msgstr ""
#: launcher2/distribute.rpy:343
#, python-format
msgid "Please enter a space separated list of documentation extensions. Files in the base directory with these extensions will have a second copy stored outside of the Macintosh application."
msgstr ""
#: launcher2/distribute.rpy:368
#, python-format
msgid "Scanning..."
msgstr ""
#: launcher2/distribute.rpy:476
#, python-format
msgid "Building Windows..."
msgstr ""
#: launcher2/distribute.rpy:483
#, python-format
msgid "Building Linux..."
msgstr ""
#: launcher2/distribute.rpy:510
#, python-format
msgid "Building Macintosh..."
msgstr ""
#: launcher2/distribute.rpy:518
#, python-format
msgid "Building Combined..."
msgstr ""
#: launcher2/distribute.rpy:524
#, python-format
msgid "Thank you for choosing Ren'Py."
msgstr ""
#: launcher2/distribute.rpy:530
#, python-format
msgid "The distributions have been built. Be sure to test them before release.\n\nNote that unpacking and repacking the Macintosh, Linux, or Combined distributions on Windows is not supported.\n\nPlease announce your release at the {a=http://lemmasoft.renai.us/forums/}Lemma Soft Forums{/a}, so we can add it to the Ren'Py web site."
msgstr ""
#: launcher2/interface.rpy:179
#, python-format
msgid "Error"
msgstr ""
#: launcher2/interface.rpy:237
#, python-format
msgid "Press enter when done."
msgstr ""
#: launcher2/interface.rpy:255
#, python-format
msgid "The string cannot be empty. Please enter some text."
msgstr ""
#: launcher2/interface.rpy:26
#, python-format
msgid "Welcome!"
msgstr ""
#: launcher2/interface.rpy:264
#, python-format
msgid "Non-ASCII filenames are not allowed. This is because Zip files cannot reliably represent non-ASCII filenames."
msgstr ""
#: launcher2/interface.rpy:292
#, python-format
msgid "Processed %d of %d files."
msgstr ""
#: launcher2/options.rpy:26
#, python-format
msgid "%s Launcher"
msgstr ""
#: launcher2/project.rpy:173 launcher2/script.rpy:67
#, python-format
msgid "Select Project"
msgstr ""
#: launcher2/project.rpy:201
#, python-format
msgid "%s has been launched."
msgstr ""
#: launcher2/project.rpy:221
#, python-format
msgid "Opening game directory:\n%s"
msgstr ""
#: launcher2/project.rpy:244
#, python-format
msgid "No files to edit."
msgstr ""
#: launcher2/project.rpy:247
#, python-format
msgid "Launching the editor failed. You may need Java, which can be downloaded for free from {a=http://www.java.com}java.com{/a}."
msgstr ""
#: launcher2/project.rpy:249
#, python-format
msgid "Launched editor with %d script files."
msgstr ""
#: launcher2/project.rpy:282
#, python-format
msgid "Lint complete."
msgstr ""
#: launcher2/project.rpy:292
#, python-format
msgid "Deleting persistent data."
msgstr ""
#: launcher2/project.rpy:292 launcher2/script.rpy:49
#, python-format
msgid "Delete Persistent"
msgstr ""
#: launcher2/project.rpy:301
#, python-format
msgid "Persistent data has been deleted."
msgstr ""
#: launcher2/script.rpy:113
#, python-format
msgid "Now showing the Ren'Py documentation in your web browser."
msgstr ""
#: launcher2/script.rpy:28
#, python-format
msgid "Launch"
msgstr ""
#: launcher2/script.rpy:30
#, python-format
msgid "Launches the project."
msgstr ""
#: launcher2/script.rpy:32
#, python-format
msgid "Edit Script"
msgstr ""
#: launcher2/script.rpy:34
#, python-format
msgid "Edits the script of the project."
msgstr ""
#: launcher2/script.rpy:36
#, python-format
msgid "Game Directory"
msgstr ""
#: launcher2/script.rpy:38
#, python-format
msgid "Opens the project's game directory."
msgstr ""
#: launcher2/script.rpy:40
#, python-format
msgid "Check Script (Lint)"
msgstr ""
#: launcher2/script.rpy:42
#, python-format
msgid "Checks the script of the project for likely errors."
msgstr ""
#: launcher2/script.rpy:47
#, python-format
msgid "Changes the theme used by the project."
msgstr ""
#: launcher2/script.rpy:51
#, python-format
msgid "Deletes the persistent data associated with the project."
msgstr ""
#: launcher2/script.rpy:53
#, python-format
msgid "Archive Files"
msgstr ""
#: launcher2/script.rpy:55
#, python-format
msgid "Archives files found in the game and archived directories."
msgstr ""
#: launcher2/script.rpy:57
#, python-format
msgid "Build Distributions"
msgstr ""
#: launcher2/script.rpy:59
#, python-format
msgid "Builds distributions of the project."
msgstr ""
#: launcher2/script.rpy:69
#, python-format
msgid "Select a project to work with."
msgstr ""
#: launcher2/script.rpy:71
#, python-format
msgid "New Project"
msgstr ""
#: launcher2/script.rpy:73
#, python-format
msgid "Create a new project."
msgstr ""
#: launcher2/script.rpy:81
#, python-format
msgid "Project Directory"
msgstr ""
#: launcher2/script.rpy:83
#, python-format
msgid "Select the directory in which the project can be found."
msgstr ""
#: launcher2/script.rpy:85
#, python-format
msgid "Select Editor"
msgstr ""
#: launcher2/script.rpy:87
#, python-format
msgid "Select the text editor to use."
msgstr ""
#: launcher2/script.rpy:89
#, python-format
msgid "Add-ons"
msgstr ""
#: launcher2/script.rpy:91
#, python-format
msgid "Download additional components for use with Ren'Py."
msgstr ""
#: launcher2/script.rpy:93
#, python-format
msgid "Ren'Py Help"
msgstr ""
#: launcher2/script.rpy:95
#, python-format
msgid "Open the Ren'Py documentation in a web browser."
msgstr ""
+2 -2
View File
@@ -83,8 +83,8 @@ def path_to_renpy_base():
##############################################################################
# The version of the Mac Launcher and py4renpy that we require.
macos_version = (6, 10, 1)
linux_version = (6, 10, 1)
macos_version = (6, 11, 1)
linux_version = (6, 11, 1)
# Doing the version check this way also doubles as an import of ast,
# which helps py2exe et al.
+5 -5
View File
@@ -27,10 +27,14 @@
# ***** ***** ***** ***** ***** ***** **** ***** ***** ***** *****
# Be sure to change script_version in launcher/script_version.rpy, too!
# Also check to see if we have to update renpy.py.
version = "Ren'Py 6.11.0b"
version = "Ren'Py 6.11.2b"
script_version = 5003000
savegame_suffix = "-LT1.save"
# True if this is the first time we've started - even including
# utter restarts.
first_utter_start = True
def import_all():
# Should probably be early, as we will add it as a base to serialized things.
@@ -81,10 +85,6 @@ def import_all():
import renpy.display.error
import renpy.display.swdraw
import renpy.display.glshader
import renpy.display.glenviron
import renpy.display.gltexture
import renpy.display.gldraw
# Note: For windows to work, renpy.audio.audio needs to be after
+14 -7
View File
@@ -104,17 +104,16 @@ class PyCode(object):
'bytecode',
]
# All PyCodes known to the system.
extent = [ ]
def __getstate__(self):
return (1, self.source, self.location, self.mode)
def __setstate__(self, state):
(_, self.source, self.location, self.mode) = state
self.bytecode = None
renpy.game.script.all_pycode.append(self)
if renpy.game.script.record_pycode:
renpy.game.script.all_pycode.append(self)
def __init__(self, source, loc=('<none>', 1), mode='exec'):
if isinstance(source, PyExpr):
@@ -131,7 +130,8 @@ class PyCode(object):
# This will be initialized later on, after we are serialized.
self.bytecode = None
renpy.game.script.all_pycode.append(self)
if renpy.game.script.record_pycode:
renpy.game.script.all_pycode.append(self)
def chain_block(block, next):
"""
@@ -332,6 +332,13 @@ class Say(Node):
else:
who = None
if not (
(who is None) or
callable(who) or
isinstance(who, basestring) ):
raise Exception("Sayer %s is not a function or string." % self.who.encode("utf-8"))
what = self.what
if renpy.config.say_menu_text_filter:
what = renpy.config.say_menu_text_filter(what) # E1102
@@ -948,7 +955,7 @@ class With(Node):
return [ self.next ]
class Call(Node):
+17 -9
View File
@@ -232,7 +232,7 @@ class ATLTransformBase(renpy.object.Object):
if t.atl is not self.atl:
return
self.done = t.done
self.block = t.block
self.atl_state = t.atl_state
@@ -334,7 +334,7 @@ class ATLTransformBase(renpy.object.Object):
if self.child.transform_event != self.last_child_transform_event:
self.last_child_transform_event = self.child.transform_event
self.transform_event = self.child.transform_event
# Hide request.
if trans.hide_request:
self.transform_event = "hide"
@@ -355,7 +355,7 @@ class ATLTransformBase(renpy.object.Object):
timebase = at
else:
timebase = st
action, arg, pause = self.block.execute(trans, timebase, self.atl_state, event)
renpy.game.exception_info = old_exception_info
@@ -846,10 +846,10 @@ class Interpolation(Statement):
# Now, the things we change linearly are in the difference
# between the new and old states.
linear = trans.state.diff(newts)
revolution = None
splines = [ ]
# Clockwise revolution.
if self.revolution is not None:
@@ -900,12 +900,19 @@ class Interpolation(Statement):
state = (linear, revolution, splines)
# Ensure that we set things, even if they don't actually
# change from the old state.
for k, v in self.properties:
if k not in linear:
setattr(trans.state, k, v)
else:
linear, revolution, splines = state
# Linearly interpolate between the things in linear.
for k, (old, new) in linear.iteritems():
value = interpolate(complete, old, new, PROPERTIES[k])
setattr(trans.state, k, value)
# Handle the revolution.
@@ -914,6 +921,7 @@ class Interpolation(Statement):
trans.state.angle = interpolate(complete, startangle, endangle, float)
trans.state.radius = interpolate(complete, startradius, endradius, float)
# Handle any splines we might have.
for name, values in splines:
value = interpolate_spline(complete, values)
@@ -1145,7 +1153,6 @@ class On(Statement):
else:
name, start, cstate = state
# If we have an external event, and we have a handler for it,
# handle it.
if event in self.handlers:
@@ -1156,6 +1163,7 @@ class On(Statement):
name = event
start = st
cstate = None
while True:
@@ -1167,7 +1175,7 @@ class On(Statement):
# If we get a continue, save our state.
if action == "continue":
# If it comes from a hide block, indicate that.
if name == "hide" or name == "replaced":
trans.hide_response = False
@@ -1179,7 +1187,7 @@ class On(Statement):
# event, unless we're already in default, in which case we
# go to None.
elif action == "next":
if name == "default" or name == "hide":
if name == "default" or name == "hide" or name == "replaced":
name = None
else:
name = "default"
+51 -19
View File
@@ -186,7 +186,7 @@ class Channel(object):
This stores information about the currently-playing music.
"""
def __init__(self, name, default_loop, stop_on_mute, tight, file_prefix, file_suffix):
def __init__(self, name, default_loop, stop_on_mute, tight, file_prefix, file_suffix, buffer_queue):
# The name assigned to this channel. This is used to look up
# information about the channel in the MusicContext object.
@@ -253,6 +253,9 @@ class Channel(object):
# A prefix and suffix that are used to create the full filenames.
self.file_prefix = file_prefix
self.file_suffix = file_suffix
# Should we buffer upcoming music/video in the queue?
self.buffer_queue = buffer_queue
if default_loop is None:
# By default, should we loop the music?
@@ -343,6 +346,11 @@ class Channel(object):
if depth >= 2:
break
# If we can't buffer things, and we're playing something
# give up here.
if not self.buffer_queue and depth >= 1:
break
# We can't queue anything if the depth is > 0 and we're
# waiting for a synchro_start.
if self.synchro_start and depth:
@@ -493,8 +501,18 @@ class Channel(object):
if not pcm_ok:
return None
return pss.playing_name(self.number)
rv = pss.playing_name(self.number)
if rv is None and self.queue:
rv = self.queue[0].filename
if rv is None and self.loop:
rv = self.loop[0]
return rv
def set_volume(self, volume):
self.chan_volume = volume
@@ -531,7 +549,7 @@ all_channels = [ ]
channels = { }
def register_channel(name, mixer=None, loop=None, stop_on_mute=True, tight=False, file_prefix="", file_suffix=""):
def register_channel(name, mixer=None, loop=None, stop_on_mute=True, tight=False, file_prefix="", file_suffix="", buffer_queue=True):
"""
:doc: other
@@ -563,15 +581,16 @@ def register_channel(name, mixer=None, loop=None, stop_on_mute=True, tight=False
`file_suffix`
A suffix that is appended to the filenames of the sound files being
played on this channel.
"""
`buffer_queue`
Should we buffer the first second or so of a queued file? This should
be True for audio, and False for movie playback.
"""
if not renpy.game.init_phase:
raise Exception("Can't register channel outside of init phase.")
c = Channel(name, loop, stop_on_mute, tight, file_prefix, file_suffix)
c = Channel(name, loop, stop_on_mute, tight, file_prefix, file_suffix, buffer_queue)
c.mixer = mixer
all_channels.append(c)
channels[name] = c
@@ -813,7 +832,24 @@ def rollback():
ALLOC_EVENT = pygame.USEREVENT
REFRESH_EVENT = pygame.USEREVENT + 1
# The last surface we allocated.
last_alloc_surface = None
def alloc_surface(force):
global last_alloc_surface
if renpy.display.video.fullscreen and renpy.display.draw.fullscreen_surface:
surf = renpy.display.draw.fullscreen_surface
else:
surf = renpy.display.video.surface
if (surf is not last_alloc_surface) or force:
last_alloc_surface = surf
pss.alloc_event(surf)
def event(ev):
"""
Handles an event generated by pss (really, the ffdecode
@@ -824,24 +860,20 @@ def event(ev):
if not pcm_ok:
return False
if renpy.display.video.fullscreen or not renpy.display.video.surface:
surf = renpy.display.draw.fullscreen_surface
else:
surf = renpy.display.video.surface
if ev.type == ALLOC_EVENT:
pss.alloc_event(surf)
alloc_surface(True)
return True
if ev.type == REFRESH_EVENT:
elif ev.type == REFRESH_EVENT:
alloc_surface(False)
if renpy.audio.music.get_playing("movie"):
pss.refresh_event()
renpy.display.draw.mutated_surface(surf)
if surf is renpy.display.draw.fullscreen_surface:
renpy.game.interface.force_redraw = True
renpy.game.interface.force_redraw = True
# Return False, as a Movie should get this to know when to
# redraw itself.

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