Compare commits

..

22 Commits

Author SHA1 Message Date
tom 5ea9d436ce *** empty log message *** 2004-09-25 19:43:36 +00:00
tom c05e4e528e *** empty log message *** 2004-09-24 20:25:43 +00:00
tom e10488b77a *** empty log message *** 2004-09-24 02:31:54 +00:00
tom 86e0cb3331 *** empty log message *** 2004-09-23 22:20:34 +00:00
tom c6397c08af *** empty log message *** 2004-09-22 04:49:09 +00:00
tom f9db64231d *** empty log message *** 2004-09-22 04:39:38 +00:00
tom f3c3c67def *** empty log message *** 2004-09-22 00:15:05 +00:00
tom 6d316a9c78 *** empty log message *** 2004-09-21 23:54:02 +00:00
tom 6e7e68b31a Reorganizing to use common directory. 2004-09-13 18:16:40 +00:00
tom a24e6b2af1 *** empty log message *** 2004-09-12 13:51:22 +00:00
tom 597b01c26b Ready for 4.1 release? 2004-09-12 11:53:36 +00:00
tom a262eb0f60 *** empty log message *** 2004-09-11 18:30:37 +00:00
tom 92006d237c 4.0 Release 2004-09-06 20:33:05 +00:00
tom 1427336746 Feature complete. 2004-09-05 22:49:30 +00:00
tom c35ed8a7cd Before changing fill implementation. 2004-09-04 18:30:42 +00:00
tom 90f47eacf3 In the process of removing with. 2004-09-04 15:33:24 +00:00
tom ee093925f5 Before surface rewrite. 2004-08-31 14:33:13 +00:00
tom f686a810a7 *** empty log message *** 2004-08-31 03:43:43 +00:00
tom e2a12284d5 *** empty log message *** 2004-08-29 02:51:34 +00:00
tom 10b4064a53 *** empty log message *** 2004-08-25 02:18:07 +00:00
tom f1ea5289aa *** empty log message *** 2004-08-24 00:07:26 +00:00
tom a26ed9c328 *** empty log message *** 2004-08-23 01:21:57 +00:00
1177 changed files with 9204 additions and 232247 deletions
-60
View File
@@ -1,60 +0,0 @@
*.rpyc
*.rpyb
*.rpymc
*.pyc
*.pyo
*~
*.bak
saves
tmp
cache
env
log.txt
errors.txt
traceback.txt
styles.txt
/android
/build
/dist
/dists
/renpy.app
/jedit
/lint.txt
/renpy.code
/*testing*
/screenshot*
/renpy.exe
/lib
/lib.old
/doc
/.pydevproject
/.pydevproject.bak
/.project
/.settings
/LICENSE.txt
/templates/english/README.html
/the_question/README.html
/tutorial/README.html
/renpy/angle/*.pyx
/renpy/angle/*.pxd
/renpy-ppc.zip
/module/build
/module/gen
/editra
/launcher/game/theme
/launcher/game/script_version.rpy
/dl
renpy/vc_version.py
.externalToolBuilders
/rapt
/evil
/iaptest
/pygame_sdl2
/renios
/steam_appid.txt
BIN
View File
Binary file not shown.
+186
View File
@@ -0,0 +1,186 @@
New in 4.2
----------
Ren'Py now ships with a common directory that is used to store the
library files, as well as the files needed by a minimal game. (Such as
a default font.) The idea here is to allow one to copy a game
directory from one version of Ren'Py to another, and have it just
work.
One can upgrade from 4.1 to 4.2 by deleting script.rpy, script.rpyc,
library.rpy, and library.rpyc, and then copying in the game
directory.
We've also eliminated the default background images. To go back to the
images used with Ren'Py 4.1, add the following lines to your script,
and copy the images out of the 4.1 distribution, or your 4.1 based
game.
[code]
init:
$ style.mm_root_window.background = Image("mainmenu.jpg")
$ style.gm_root_window.background = Image("gamemenu.jpg")
$ style.window.background = Frame("frame.png", 125, 25)
[/code]
Added a new variable, config.hard_rollback_limit, which limits the
number of steps the user can rollback the game, interactively. This
limit now defaults to 10 steps. (suggested by Grey)
Added a second parameter to renpy.pause, that allows us to pause until
a particular offset in the background music is reached. (suggested by
Alessio)
Added keyboard mouse controls that can be used to move the mouse
around on the game and main menus. This allows us to manipulate the
game and main menus without having to touch the mouse. This is mostly
for completeness. (suggested by Alessio)
Changed the way in which overlays work. We now have the variable
config.overlay_functions, which contains a list of functions, each of
which returns a list of displayables that will be added to the
screen. (sorta-kinda suggested by Alessio)
Removed renpy.set_overlay, since config.overlay_functions is a more
flexible way of doing the same thing.
Now, defining the label main_menu allows you to totally replace the
main menu with something of your own devising. Changed the
documentation to reflect this, as well as the changes in startup that
happened in 4.1.
Added a program called "add_from", which adds from clauses to all bare
call statements found in the program.
Replaced the menu_selected and menu_unselected styles with a single
menu_choice style which participates in the hover protocol. This may
change user code, if you change the menu colors. To fix this, replace
style.menu_selected.color with style.menu_choice.hover_color, and
style.menu_unselected.color with style.menu_choice.idle_color.
Added the ability to play sound effects, by calling the renpy.play
function. Added a preference that allows the user to control if
sound effects are played or not.
Added sound styles, which are used to define the sounds that are
played when buttons, imagemaps, and menu choices are hovered and
activated. (By default, no such sounds are played.)
Implemented that annoying thing where text is typed on the screen one
character at a time. Also added a preference that allows the user to
disable it. Used all the restraint I could muster to avoid defaulting
that preference to off.
Added the ability to fade out music when changing music
tracks. This is controlled by the config.fade_music variable.
(suggested by Alessio)
Added parameterized images, and the ability to show text as image
using a command like:
[code]
show text "American Bishoujo Presents..."
[/code]
Added a Move function, which can be used in at to allow an image to be
moved on the screen. This is best used when the image is smaller than
the screen. (suggested by Alessio)
Changed the format of archive files, to make them somewhat harder to
reverse-engineer. This requires the user to regenerate the archive
files. To make this easier, we now ship a batch file (called
archive_images.bat) that automatically archives the images found in
the game directory.
Added a new function renpy.wait that is equivalent to the wait
statement, and made it and renpy.pause return True if they are
interrupted, or False if the run to their natural completions. This
now makes it possible to jump somewhere else when the user click,
rather than blindly going to the next label. For example:
[code]
# Actually, this runs before the library main menu.
label main_menu:
scene black
show text "American Bishoujo\nPresents" \
at Move((0.5, 0.0), (0.5, 0.5), 3.0,
xanchor='center', yanchor='bottom')
if renpy.pause(6):
jump _library_main_menu
show text "A PyTom Game" at Position(xpos=0.5, ypos=0.5,
xanchor="center", yanchor="bottom")
if renpy.with(fade) or renpy.pause(4):
jump _library_main_menu
$ renpy.transition(fade)
jump _library_main_menu
[code]
Updated renpy-mode.el to add imenu support, so (X)Emacs users can use
the speedbar to jump around in a script. If you don't know what this
means, you probably don't care.
Improved the comments in the demo script, to make it a better
example. Added a syntax-highlighted version of the demo script to the
tutorial, to make it easier on peoples eyes.
New in 4.1
----------
Added the ability to customize the main menu by giving a list of
buttons on the main menu and the labels that they jump the user to.
Added the ability to center-click to hide any displayed text or menus.
Added the ability to have a color mouse that we can move around the
screen.
Added a persistent object, which has fields that are persistent across
games. Made the preferences part of this object, so that they are
persisted across sessions. For simplicity's sake, made seen_ever part
of that persistent object.
Added a special character called "centered", which causes the text it
displays to be centered in the screen without any window. Added two
new styles (centered_window and centered_text), which are used for
this, and a new property, textalign, which controls the horizontal
alignment of text within the Text object itself.
Keywords are now special in all contexts. So you can no longer include
keywords in image names. Sorry.
Improved parse error messages. They now include the text of the
line and a caret indication the location in the line where the parse
error occurred.
Added a with clause to say statements and menus. This lets one display
dialogue, thoughts, or menus using a transition. In conjunction with
this, changed a bit the semantics of with statements, and with clauses
on show, hide, and scene statements. Rewrote the section on
transitions in the documentation to reflect the new reality.
Added the ability to translate the text of the game menu. Together
with the ability to change the main menu, this makes Ren'Py fully
localizable, except for error messages. Check out the Localization
section in the tutorial for more details.
Added confirmations for quitting and overwriting a save game. This
also includes quitting by trying to close the window.
Added a preferences screen, which lets users change the Ren'Py
preferences. Right now, this includes Windowed/Fullscreen, Music
Enabled/Disabled, CTRL Skips Unread/All messages, and Transitions
controls which transitions are performed.
Added a Pan function which can be used in an at clause. This allows us
to pan over a background image.
-164
View File
@@ -1,164 +0,0 @@
==============================
The Ren'Py Visual Novel Engine
==============================
http://www.renpy.org
Ren'Py development takes place on the ``master`` branch, and occasionally
on feature branches.
Getting Started
===============
Ren'Py depends on a number of python modules written in Cython and C. For
changes to Ren'Py that only involve python modules, you can use the modules
found in the latest nightly build. Otherwise, you'll have to compile the
modules yourself.
The development scripts assume a POSIX-like platform. The scripts should run
on Linux or Mac OS X, and can be made to run on Windows using an environment
like Msys.
Nightly Build
-------------
Nightly builds can be downloaded from:
http://nightly.renpy.org
Note that the latest nightly build is at the bottom of the list. Once you've
unpacked the nightly, change into this repository, and run::
./after_checkout.sh <path-to-nightly>
Once this script completes, you should be able to run Ren'Py using renpy.sh,
renpy.app, or renpy.exe, as appropriate for your platform.
If the current nightly build doesn't work, please wait 24 hours for a new
build to occur. If that build still doesn't work, contact Tom (`pytom at bishoujo.us`,
or @renpytom on twitter) to find out what's wrong.
The ``doc`` symlink will dangle until documentation is built, as described
below.
Compiling the Modules
----------------------
Building the modules requires you have the many dependencies installed on
your system. On Ubuntu and Debian, these dependencies can be installed with
the command::
apt-get install virtualenvwrapper python-dev libavcodec-dev libavformat-dev \
libavresample-dev libswscale-dev libfreetype6-dev libglew1.6-dev \
libfribidi-dev libsdl2-dev libsdl2-image-dev libsdl2-gfx-dev \
libsdl2-mixer-dev libsdl2-ttf-dev libjpeg-turbo8-dev
We strongly suggest installing the Ren'Py modules into a Python
virtualenv. To create a new virtualenv, open a new terminal and run::
mkvirtualenv renpy
To return to this virtualenv later, run::
workon renpy
After activating the virtualenv, install cython::
pip install -U cython
Then, install pygame_sdl2 by running the following commands::
git clone https://www.github.com/renpy/pygame_sdl2
pushd pygame_sdl2
python fix_virtualenv.py $VIRTUAL_ENV
python setup.py install
popd
Next, set RENPY_DEPS_INSTALL To a \::-separated list of paths containing the
dependencies, and RENPY_CYTHON to the name of the cython command::
export RENPY_DEPS_INSTALL="/usr::/usr/lib/x86_64-linux-gnu/"
export RENPY_CYTHON=cython
Finally, use setup.py in the Ren'Py ``module`` directory to compile and
install the modules that support Ren'Py::
pushd module
python setup.py install
popd
Ren'Py will be installed into the activated virtualenv. It can then be run
using the command::
python -O renpy.py
Documentation
=============
Building
--------
Building the documentation requires Ren'Py to work. You'll either need to
link in a nightly build, or compile the modules as described above. You'll
also need the `Sphinx <http://sphinx-doc.org/>`_ documentation generator.
If you have pip working, install Sphinx using::
pip install -U sphinx
Once Sphinx is installed, change into the ``sphinx`` directory inside the
Ren'Py checkout and run::
./build.sh
Format
------
Ren'Py's documentation consists of reStructuredText files found in sphinx/source, and
generated documentation found in function docstrings scattered throughout the code. Do
not edit the files in sphinx/source/inc directly, as they will be overwritten.
Docstrings may include tags on the first few lines:
\:doc: `section` `kind`
Indicates that this functions should be documented. `section` gives
the name of the include file the function will be documented in, while
`kind` indicates the kind of object to be documented (one of ``function``,
``method`` or ``class``. If omitted, `kind` will be auto-detected.
\:name: `name`
The name of the function to be documented. Function names are usually
detected, so this is only necessary when a function has multiple aliases.
\:args: `args`
This overrides the detected argument list. It can be used if some arguments
to the function are deprecated.
For example::
def warp_speed(factor, transwarp=False):
"""
:doc: warp
:name: renpy.warp_speed
:args: (factor)
Exceeds the speed of light.
"""
renpy.engine.warp_drive.engage(factor)
Translating
===========
For best practices when it comes to translating the launcher and template
game, please read:
http://lemmasoft.renai.us/forums/viewtopic.php?p=321603#p321603
Contributing
============
For bug fixes, documentation improvements, and simple changes, just
make a pull request. For more complex changes, it might make sense
to file an issue first so we can discuss the design.
-105
View File
@@ -1,105 +0,0 @@
#!/usr/bin/env python2
import argparse
import os
import subprocess
import sys
from renpy import version_tuple #@UnresolvedImport
SOURCE = [
"/home/tom/ab/renpy",
"/home/tom/ab/android/",
"/home/tom/ab/android/python-for-android",
"/home/tom/ab/ripe/renios",
"/home/tom/ab/renpy-deps",
"/home/tom/ab/pygame_sdl2",
]
version = ".".join(str(i) for i in version_tuple)
short_version = ".".join(str(i) for i in version_tuple[:3])
print "Version", version
ap = argparse.ArgumentParser()
ap.add_argument("--release", action="store_true")
ap.add_argument("--prerelease", action="store_true")
ap.add_argument("--experimental", action="store_true")
ap.add_argument("--no-tag", "-n", action="store_true")
ap.add_argument("--push-tags", action="store_true")
ap.add_argument("--delete-tag")
args = ap.parse_args()
if args.delete_tag:
for i in SOURCE:
os.chdir(i)
if i == SOURCE[0]:
tag = args.delete_tag
else:
tag = "renpy-" + args.delete_tag
subprocess.call([ "git", "tag", "-d", tag, ])
sys.exit(0)
if args.push_tags:
for i in SOURCE:
os.chdir(i)
if subprocess.call([ "git", "push", "--tags" ]):
print "Tags not pushed: {}".format(os.getcwd())
sys.exit(1)
print "Pushed tags."
sys.exit(0)
if args.release:
links = [ "release", "prerelease", "experimental" ]
tag = True
elif args.prerelease:
links = [ "prerelease", "experimental" ]
tag = True
elif args.experimental:
links = [ "experimental" ]
tag = False
else:
links = [ ]
tag = False
if args.no_tag:
tag = False
if tag:
for i in SOURCE:
os.chdir(i)
if subprocess.call([ "git", "diff", "--quiet", "HEAD" ]):
print "Directory not checked in: {}".format(os.getcwd())
sys.exit(1)
for i in SOURCE:
os.chdir(i)
if i == SOURCE[0]:
tag = version
else:
tag = "renpy-" + version
subprocess.check_call([ "git", "tag", "-a", tag, "-m", "Tagging Ren'Py + " + version + " release." ])
os.chdir("/home/tom/ab/renpy/dl")
for i in links:
if os.path.exists(i):
os.unlink(i)
os.symlink(short_version, i)
os.chdir("/home/tom/ab/website")
subprocess.check_call("./upload.sh")
print "Version", version
Executable
+79
View File
@@ -0,0 +1,79 @@
#!/usr/bin/env python
# This program adds froms to every unqualified call found in the game
# directory. It's not perfect, but it's better than nothing.
import sys
import os
import re
def find_labels(fn, labels):
f = file(fn, "r")
for l in f:
m = re.match(r'^\s*call\s+\w+\s+from\s+(\w+)\s*$', l)
if m:
labels[m.group(1)] = True
f.close()
def replace_labels(fn, labels):
f = file(fn, "r")
of = file(fn + ".new", "w")
def replaceit(m):
target = m.group(2)
num = 0
while True:
num += 1
label = "_call_%s_%d" % (target, num)
if label not in labels:
break
labels[label] = True
return m.group(1) + "call " + target + " from " + label + m.group(3)
for l in f:
l = re.sub(r'^(\s*)call\s+(\w+)(\s*$)', replaceit, l)
of.write(l)
f.close()
of.close()
os.rename(fn, fn + ".bak")
os.rename(fn + ".new", fn)
def main():
gamedir = "game"
if len(sys.argv) >= 2:
gamedir = sys.argv[1]
print "Processing files in", gamedir
files = [ gamedir + "/" + i for i in os.listdir(gamedir)
if i.endswith(".rpy") ]
labels = { }
for fn in files:
print "Finding labels in", fn
find_labels(fn, labels)
for fn in files:
print "Replacing labels in", fn
replace_labels(fn, labels)
if __name__ == "__main__":
main()
-15
View File
@@ -1,15 +0,0 @@
#!/bin/bash
ROOT="$(dirname $(python -c "import os;print(os.path.realpath('$0'))"))"
ln -s "$ROOT/help.html" "$ROOT/tutorial/README.html"
ln -s "$ROOT/help.html" "$ROOT/the_question/README.html"
ln -s "$ROOT/help.html" "$ROOT/templates/english/README.html"
ln -s "$ROOT/sphinx/source/license.rst" "$ROOT/LICENSE.txt"
if [ "$1" != "" ]; then
ln -s "$1/lib" "$ROOT/lib"
ln -s "$1/renpy.app" "$ROOT"
ln -s "$1/renpy.exe" "$ROOT"
fi
-10
View File
@@ -1,10 +0,0 @@
# This file sets up the normal python modules. It's used to help eclipse
# do type detection, by providing an importable version of the cython code.
from distutils.core import setup
setup(
packages=['renpy', 'renpy.gl', 'renpy.angle', 'renpy.display', 'renpy.audio', 'renpy.text', 'pysdlsound'],
package_dir={ 'pysdlsound' : 'module' },
)
+2
View File
@@ -0,0 +1,2 @@
cd images
..\archiver.exe images *.png *.jpg
Executable
+89
View File
@@ -0,0 +1,89 @@
#!/usr/bin/env python
# The Ren'Py archiver. This builds a Ren'Py archive file, and the
# associated index file. These files are really easy to reverse-engineer,
# but are probably better than nothing.
import sys
import os
import encodings.zlib_codec
import random
from cPickle import loads, dumps, HIGHEST_PROTOCOL
# The most we will go without inserting some padding. 10k.
padding_every = 10240
# The amount of padding we will add.
padding_max = 32
def randpadding():
plen = random.randint(1, padding_max)
rv = ""
for i in range(0, plen):
rv += chr(random.randint(1, 255))
return rv
def main():
if len(sys.argv) < 3:
print "Usage: %s <file-prefix> <files ...>" % sys.argv[0]
return
prefix = sys.argv[1]
# Archive file.
archivef = file(prefix + ".rpa", "wb")
# Index file.
indexf = file(prefix + ".rpi", "wb")
index = { }
random.seed()
offset = 0
for fn in sys.argv[2:]:
index[fn] = [ ]
print "Adding %s..." % fn
datafile = file(fn, "rb")
while True:
# Pad with junk.
padding = randpadding()
archivef.write(padding)
offset += len(padding)
# Pick a random block size.
block = random.randint(1, padding_every)
data = datafile.read(block)
if not data:
break
dlen = len(data)
archivef.write(data)
index[fn].append((offset, dlen))
offset += dlen
datafile.close()
archivef.close()
indexf.write(dumps(index, HIGHEST_PROTOCOL).encode("zlib"))
indexf.close()
if __name__ == "__main__":
main()
+31
View File
@@ -0,0 +1,31 @@
#!/usr/bin/env python
from distutils.core import setup
import py2exe
import sys
if len(sys.argv) != 2:
print "Usage: build_exe.py <prefix>"
print ""
print "Builds <prefix>.exe."
print "Expects icons in <prefix>.ico."
sys.exit(-1)
def program(name):
return dict(script="run_game.py",
icon_resources=[ (0, name + ".ico"),
],
dest_base=name)
programs = [
program(sys.argv[1]),
]
sys.argv[1:] = [ 'py2exe' ]
setup(name="RenPy",
windows=programs,
console=[ "archiver.py", "add_from.py" ],
zipfile='lib/renpy.zip',
)
BIN
View File
Binary file not shown.
+55
View File
@@ -0,0 +1,55 @@
This package was debianized by Michael Fedrowitz <michaelf@debian.org>
on Sun, 23 Feb 2003.
It was downloaded from
'http://ftp.gnome.org/pub/GNOME/sources/ttf-bitstream-vera/'.
Upstream Author: Bitstream, Inc.
Copyright:
Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream
Vera is a trademark of Bitstream, Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of the fonts accompanying this license ("Fonts") and associated
documentation files (the "Font Software"), to reproduce and distribute
the Font Software, including without limitation the rights to use,
copy, merge, publish, distribute, and/or sell copies of the Font
Software, and to permit persons to whom the Font Software is furnished
to do so, subject to the following conditions:
The above copyright and trademark notices and this permission notice
shall be included in all copies of one or more of the Font Software
typefaces.
The Font Software may be modified, altered, or added to, and in
particular the designs of glyphs or characters in the Fonts may be
modified and additional glyphs or characters may be added to the
Fonts, only if the fonts are renamed to names not containing either
the words "Bitstream" or the word "Vera".
This License becomes null and void to the extent applicable to Fonts
or Font Software that has been modified and is distributed under the
"Bitstream Vera" names.
The Font Software may be sold as part of a larger software package but
no copy of one or more of the Font Software typefaces may be sold by
itself.
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL,
OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT
SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
Except as contained in this notice, the names of Gnome, the Gnome
Foundation, and Bitstream Inc., shall not be used in advertising or
otherwise to promote the sale, use or other dealings in this Font
Software without prior written authorization from the Gnome Foundation
or Bitstream Inc., respectively. For further information, contact:
fonts at gnome dot org.
+422
View File
@@ -0,0 +1,422 @@
# This file consists of renpy functions that aren't expected to be
# touched by the user too much. We reserve the _ prefix for names
# defined in the library.
# It's strongly reccomended that you don't edit this file, as future
# releases of Ren'Py will probably change this file to include more
# functionality.
# It's also strongly recommended that you leave this file in the
# game directory, so its functionality is included in your game.
init -500:
python:
# These are settings that the user can tweak to control the
# look of the main menu and the load/save/escape screens.
# Used to store library settings.
library = object()
# The number of files to show at once.
library.file_page_length = 4
# A small amount of padding.
library.padding = 5
# The width of a thumbnail.
library.thumbnail_width = 100
# The height of a thumbnail.
library.thumbnail_height = 75
# The contents of the main menu.
library.main_menu = [
( "Start Game", "start" ),
( "Continue Game", "_continue" ),
( "Quit Game", "_quit" ),
]
# Used to translate strings in the library.
library.translations = { }
# This is updated to give the user an idea of where a save is
# taking place.
save_name = ''
# The function that's used to translate strings in the game menu.
init:
python:
def _(s):
"""
Translates s into another language or something.
"""
if s in library.translations:
return library.translations[s]
else:
return s
##############################################################################
init:
python:
# Called to make a screenshot happen.
def _screenshot():
renpy.screenshot("screenshot.bmp")
# Are the windows currently hidden?
_windows_hidden = False
# Hides the windows.
def _hide_windows():
global _windows_hidden
if _windows_hidden:
return
try:
_windows_hidden = True
renpy.interact(renpy.SayBehavior())
finally:
_windows_hidden = False
# A keymouse object that we use on the mainmenu and gamemenu
# screens.
_keymouse = renpy.KeymouseBehavior()
# Set up the default keymap.
python hide:
# The default keymap.
km = renpy.Keymap(
K_PAGEUP = renpy.rollback,
mouse_4 = renpy.rollback,
s = _screenshot,
f = renpy.toggle_fullscreen,
m = renpy.toggle_music,
K_ESCAPE = renpy.curried_call_in_new_context("_game_menu"),
mouse_3 = renpy.curried_call_in_new_context("_game_menu"),
mouse_2 = _hide_windows,
)
config.underlay = [ km ]
return
# This is the true starting point of the program. Sssh... Don't
# tell anyone.
label _start:
jump _main_menu
# This shows the main menu to the user.
label _main_menu:
# Let the user completely override the main menu.
if renpy.has_label("main_menu"):
jump main_menu
label _library_main_menu:
python hide:
# Show the main menu screen.
vbox = renpy.VBox()
for text, label in library.main_menu:
vbox.add(renpy.TextButton(text, clicked=_return(label)))
menu_window = renpy.Window(vbox, style='mm_menu_window')
fixed = renpy.Fixed()
fixed.add(menu_window)
root_window = renpy.Window(fixed, style='mm_root_window')
store._result = renpy.interact(_keymouse, root_window,
suppress_overlay=True,
suppress_underlay=True)
# Computed jump to the appropriate label.
$ renpy.jump(_result)
return
# Used to call the game menu.
label _continue:
$ renpy.call_in_new_context("_load_menu")
jump _library_main_menu
##############################################################################
#
# Code for the game menu.
init -500:
python:
# This returns a window containing the game menu navigation
# buttons, set up to jump to the appropriate screen sections.
def _game_nav(selected):
buttons = [
( "return", _("Return to Game"), "_return"),
( "load", _("Load Game"), "_load_screen" ),
( "save", _("Save Game"), "_save_screen" ),
( "prefs", _("Preferences"), "_prefs_screen" ),
( "mainmenu", _("Main Menu"), "_full_restart" ),
( "quit", _("Quit Game"), "_confirm_quit" ),
]
vbox = renpy.VBox()
win = renpy.Window(vbox, style='gm_nav_window')
for key, label, target in buttons:
style="button"
text_style="button_text"
if key == selected:
style = 'selected_button'
text_style = 'selected_button_text'
def clicked(target=target):
renpy.jump(target)
tb = renpy.TextButton(label,
style=style,
text_style=text_style,
clicked=clicked)
vbox.add(tb)
return win
def _game_interact(selected, *widgets):
fixed = renpy.Fixed()
win = renpy.Window(fixed, style='gm_root_window')
fixed.add(_game_nav(selected))
for w in widgets:
fixed.add(w)
return renpy.interact(_keymouse, win,
suppress_underlay=True,
suppress_overlay=True
)
_file_picker_index = 0
def _render_filename(filename, newest_filename):
if filename is None:
return renpy.Text(_("Save in new slot."), style='file_picker_new_slot')
hbox = renpy.HBox(padding=library.padding)
if filename == newest_filename:
hbox.add(renpy.Text(_("New"), style='file_picker_new'))
else:
hbox.add(renpy.Text(_("Old"), style='file_picker_old'))
hbox.add(renpy.load_screenshot(filename))
hbox.add(renpy.Text(renpy.load_extra_info(filename), style='file_picker_extra_info' ))
return hbox
# This displays a file picker that can chose a save file from
# the list of save files.
def _file_picker(selected, files):
nsg = renpy.newest_save_game()
while True:
if _file_picker_index >= len(files):
store._file_picker_index -= library.file_page_length
if _file_picker_index < 0:
store._file_picker_index = 0
fpi = _file_picker_index
cur_files = files[fpi:fpi + library.file_page_length]
vbox = renpy.VBox()
hbox = renpy.HBox(padding=library.padding * 3)
def tb(cond, label, clicked):
if cond:
style = 'button'
text_style = 'button_text'
else:
style = 'disabled_button'
text_style = 'disabled_button_text'
return renpy.TextButton(label, style=style, text_style=text_style, clicked=clicked)
hbox.add(tb(fpi > 0,
_('Previous Page'), _return(("fpidelta", -1))))
hbox.add(tb(fpi + library.file_page_length < len(files),
_('Next Page'), _return(("fpidelta", +1))))
vbox.add(hbox)
for i in cur_files:
child = _render_filename(i, nsg)
button = renpy.Button(child,
style='file_picker_entry',
clicked=_return(("return", i)))
vbox.add(button)
win = renpy.Window(vbox, style='file_picker_window')
result = _game_interact(selected, win)
type, value = result
if type == "return":
return value
if type == "fpidelta":
store._file_picker_index += value * library.file_page_length
def _yesno_prompt(screen, message):
prompt = renpy.Text(message, style='yesno_prompt')
yes = renpy.TextButton(_("Yes"), style='yesno_yes',
clicked=_return(True))
no = renpy.TextButton(_("No"), style='yesno_no',
clicked=_return(False))
return _game_interact(screen, prompt, yes, no)
# Returns a button for a single preference and value.
def _prefbutton(label, var, value):
def clicked():
setattr(_preferences, var, value)
return True
style = 'button'
text_style = 'button_text'
if getattr(_preferences, var) == value:
style = 'selected_button'
text_style = 'selected_button_text'
return renpy.TextButton(_(label), style=style,
text_style=text_style, clicked=clicked)
# Returns a vbox for a single preference.
def _prefvbox(label, var, entries):
rv = renpy.VBox(style='prefs_pref')
rv.add(renpy.Text(_(label), style='prefs_label'))
for blabel, value in entries:
rv.add(_prefbutton(blabel, var, value))
return rv
label _load_menu:
$ renpy.take_screenshot((library.thumbnail_width, library.thumbnail_height))
jump _load_screen
label _game_menu:
$ renpy.take_screenshot((library.thumbnail_width, library.thumbnail_height))
jump _save_screen
label _load_screen:
python:
_fn = _file_picker("load", renpy.saved_game_filenames() )
python:
renpy.load(_fn)
jump _load_screen
label _save_screen:
$ _fn = _file_picker("save", renpy.saved_game_filenames() + [ None ] )
if not _fn or _yesno_prompt("save", _("Are you sure you want to overwrite your save?")):
$ renpy.save(_fn, renpy.time.strftime("%Y-%m-%d %H:%M:%S\n") + save_name)
jump _save_screen
# The preferences screen.
label _prefs_screen:
python hide:
prefs_left = [
( 'Display', 'fullscreen',
[ ('Window', False), ('Fullscreen', True) ] ),
( 'Music', 'music',
[ ('Enabled', True), ('Disabled', False) ] ),
( 'Sound Effects', 'sound',
[ ('Enabled', True), ('Disabled', False) ] ),
]
prefs_right = [
('CTRL Skips', 'skip_unseen',
[ ('Seen Messages', False), ('All Messages', True) ] ),
('Transitions', 'transitions',
[ ('All', 2), ('Some', 1), ('None', 0) ]),
]
if config.annoying_text_cps:
prefs_right.append(('Text Display', 'fast_text', [ ('Slow', False), ('Fast', True) ]))
vbox_left = renpy.VBox(padding=library.padding * 3, style='prefs_left')
for label, var, entries in prefs_left:
vbox_left.add(_prefvbox(label, var, entries))
vbox_right = renpy.VBox(padding=library.padding * 3, style='prefs_right')
for label, var, entries in prefs_right:
vbox_right.add(_prefvbox(label, var, entries))
_game_interact("prefs", vbox_left, vbox_right)
jump _prefs_screen
# Asks the user if he wants to quit.
label _confirm_quit:
if _yesno_prompt("quit", _("Are you sure you want to end the game?")):
jump _quit
else:
jump _return
label _quit:
$ renpy.quit()
label _full_restart:
$ renpy.full_restart()
# Return to the game, after restoring the keymap.
label _return:
return
# Random nice things to have.
init:
$ centered = Character(None, what_style="centered_text", window_style="centered_window")
image text = renpy.ParameterizedText(style="centered_text")
+333
View File
@@ -0,0 +1,333 @@
# This file is responsible for creating and defining the default styles
# used by the system.
# This file should be considered part of the Ren'Py library, and not
# something that needs to be modified by the user. Instead, just update
# the appropriate style property in an init: block in your script.
#
# For example, to change the default window backgrounds to a
# transparent dark red, add:
#
# init:
# $ style.window.background = renpy.Solid((128, 0, 0, 128)
#
# to your script. No need to mess around here, it will just make your
# life harder when a new version of Ren'Py is released.
init -250:
python hide:
style.create('default', None,
'The default style that all styles inherit from.')
# Text properties.
style.default.font = "Vera.ttf"
style.default.size = 22
style.default.color = (255, 255, 255, 255)
style.default.drop_shadow = (2, 2)
style.default.drop_shadow_color = (0, 0, 0, 128)
style.default.minwidth = 0
style.default.textalign = 0
# Change this if you're not using Vera 22.
if renpy.windows():
style.default.line_height_fudge = -4
else:
style.default.line_height_fudge = 0
# Window properties.
style.default.background = None
style.default.xpadding = 0
style.default.ypadding = 0
style.default.xmargin = 0
style.default.ymargin = 0
style.default.xfill = False
style.default.yfill = False
style.default.xminimum = 0 # Includes margins and padding.
style.default.yminimum = 0 # Includes margins and padding.
# Placement properties.
style.default.xpos = 0
style.default.ypos = 0
style.default.xanchor = 'left'
style.default.yanchor = 'top'
# Sound properties.
style.default.hover_sound = None
style.default.activate_sound = None
# The base style for the large windows.
style.create('window', 'default',
'(window, placement) The base style for the windows that contain dialogue, thoughts, and menus.')
style.window.background = Solid((0, 0, 128, 128))
style.window.xpadding = 10
style.window.ypadding = 5
style.window.xmargin = 10
style.window.ymargin = 5
style.window.xfill = True
style.window.yfill = False
style.window.xminimum = 0 # Includes margins and padding.
style.window.yminimum = 150 # Includes margins and padding.
style.window.xpos = 0.5
style.window.ypos = 1.0
style.window.xanchor = 'center'
style.window.yanchor = 'bottom'
# This style controls the default placement of images on the screen.
style.create('image_placement', 'default',
'This style is used to control the default placement of images on the screen.')
style.image_placement.xpos = 0.5
style.image_placement.ypos = 1.0
style.image_placement.xanchor = 'center'
style.image_placement.yanchor = 'bottom'
# Styles that are used for dialogue.
style.create('say_label', 'default',
"""(text) The style that is used by default for
the label of dialogue. The label is used to
indicate who is saying something.""")
style.create('say_dialogue', 'default',
"""(text) The style that is used by default for
the text of dialogue.""")
style.create('say_thought', 'default',
"""(text) The label that is used by default for
the text of thoughts or narration, when no
speaker is given.""")
style.create('say_window', 'window',
'(window, position) The default style for windows containing dialogue and thoughts.')
# Styles that are used for menus.
style.create('menu_caption', 'default',
"""(text) The style that is used to render a menu
caption.""")
style.create('menu_choice', 'default',
"""(text, hover, sound) The style that is used to render a menu choice.""")
style.menu_choice.hover_color = (255, 255, 0, 255) # yellow
style.menu_choice.idle_color = (0, 255, 255, 255) # cyan
style.create('menu_window', 'window',
'(window, position) The default style for windows containing a menu.')
# Styles that are used by input widgets.
style.create('input_text', 'default',
'(text) The style used for the text of an input box.')
style.input_text.color = (255, 255, 0, 255)
style.create('input_prompt', 'default',
'(text) The style used for the prompt of an input box.')
style.create('input_window', 'window',
'(window, position) The style used for the window of an input box.')
# Styles used by centered.
style.create('centered_window', 'default',
'(window) The style that is used for a "window" containing centered text.')
style.create('centered_text', 'default',
'(text) The style used for centered text.')
style.centered_window.xpos = 0.5
style.centered_window.xanchor = 'center'
style.centered_window.xfill = False
style.centered_window.ypos = 0.5
style.centered_window.yanchor = 'center'
style.centered_window.yfill = False
style.centered_window.xpadding = 10
style.centered_text.textalign = 0.5
style.centered_text.xpos = 0.5
style.centered_text.ypos = 0.5
style.centered_text.xanchor = 'center'
style.centered_text.yanchor = 'center'
# Styles that are used by imagemaps
style.create('imagemap', 'image_placement',
'(sound, position) The style that is used for imagemaps.')
# Styles that are used by all Buttons.
style.create('button', 'default',
'(window, sound, hover) The default style used for buttons in the main and game menus.')
style.button.xpos = 0.5
style.button.xanchor = 'center'
style.create('button_text', 'default',
'(text, hover) The default style used for the label of a button.')
style.button_text.xpos = 0.5
style.button_text.xanchor = 'center'
style.button_text.size = 24
style.button_text.color = (0, 255, 255, 255)
style.button_text.hover_color = (128, 255, 255, 255)
# Selected button.
style.create('selected_button', 'button',
'(window, hover) The style that is used for a selected button (for example, the active screen or a chosen preference).')
style.create('selected_button_text', 'button_text',
'(text, hover) The style that is used for the label of a selected button.')
style.selected_button_text.color = (255, 255, 0, 255)
# Disabled button.
style.create('disabled_button', 'button',
'(window, hover) The style that is used for a disabled button.')
style.disabled_button.hover_sound = None
style.disabled_button.activate_sound = None
style.create('disabled_button_text', 'button_text',
'(text, hover) The style that is used for the label of a disabled button.')
style.disabled_button_text.color = (128, 128, 128, 255)
# Styles that are used when laying out the main menu.
style.create('mm_root_window', 'default',
'(window) The style used for the root window of the main menu. This is primarily used to set a background for the main menu.')
style.mm_root_window.background = Solid((0, 0, 0, 255))
style.create('mm_menu_window', 'default',
'(window, position) A window that contains the choices in the main menu. Change this to change the placement of these choices on the main menu screen.')
style.mm_menu_window.xpos = 0.9
style.mm_menu_window.xanchor = 'right'
style.mm_menu_window.ypos = 0.9
style.mm_menu_window.yanchor = 'bottom'
style.create('mm_button', 'button',
'(window, hover) The style that is used on buttons that are part of the main menu.')
style.create('mm_button_text', 'button_text',
'(text, hover) The style that is used for the labels of buttons that are part of the main menu.')
# Styles that are used to lay out the game menu.
style.create('gm_root_window', 'default',
'(window) The style used for the root window of the game menu. This is primarily used to change the background of the game menu.')
style.gm_root_window.background = Solid((0, 0, 0, 255))
style.create('gm_nav_window', 'default',
'(window, position) The style used by a window containing buttons that allow the user to navigate through the different screens of the game menu.')
style.gm_nav_window.xpos = 0.9
style.gm_nav_window.xanchor = 'right'
style.gm_nav_window.ypos = 0.95
style.gm_nav_window.yanchor = 'bottom'
style.create('file_picker_window', 'default',
'(window, position) A window containing the file picker that is used to choose slots for loading and saving.')
style.file_picker_window.xpos = 10
style.file_picker_window.xanchor = 'left'
style.file_picker_window.ypos = 10
style.file_picker_window.yanchor = 'top'
style.create('file_picker_entry', 'button',
'(window, hover) The style that is used for each of the slots in the file picker.')
style.file_picker_entry.xpadding = 3
style.file_picker_entry.xminimum = 780
style.file_picker_entry.ymargin = 5
style.file_picker_entry.idle_background = Solid((255, 255, 255, 255))
style.file_picker_entry.hover_background = Solid((255, 255, 192, 255))
style.create('file_picker_text', 'default',
'(text) A base style for all text that is displayed in the file picker.')
style.create('file_picker_new', 'file_picker_text',
'(text) The style that is applied to the new indicator in the file picker.')
style.create('file_picker_old', 'file_picker_text',
'(text) The style that is applied to the old indicator in the file pciker.')
style.file_picker_new.color = (255, 192, 192, 255)
style.file_picker_old.color = (192, 192, 255, 255)
style.file_picker_new.minwidth = 50
style.file_picker_old.minwidth = 50
style.create('file_picker_extra_info', 'file_picker_text',
'(text) The style that is applied to extra info in the file picker. The extra info is the save time, and the save_name if one exists.')
style.file_picker_extra_info.color = (192, 192, 255, 255)
style.create('file_picker_new_slot', 'file_picker_text',
'(text) The style that is used for the new slot indicator in the file picker.')
style.create('yesno_prompt', 'default',
'(text, position) The style used for the prompt in a yes/no dialog.')
style.yesno_prompt.xpos = 0.5
style.yesno_prompt.xanchor = 'center'
style.yesno_prompt.ypos = 0.25
style.yesno_prompt.yanchor = 'center'
style.create('yesno_yes', 'button',
'(position) The position of the yes button on the screen.')
style.yesno_yes.xpos = 0.33
style.yesno_yes.xanchor = 'center'
style.yesno_yes.ypos = 0.33
style.yesno_yes.yanchor = 'center'
style.create('yesno_no', 'button',
'(position) The position of the no button on the screen.')
style.yesno_no.xpos = 0.66
style.yesno_no.xanchor = 'center'
style.yesno_no.ypos = 0.33
style.yesno_no.yanchor = 'center'
# Preferences
style.create('prefs_label', 'default',
'(text, position) The style that is applied to the label of a block of preferences.')
style.prefs_label.xpos = 0.5
style.prefs_label.xanchor = "center"
style.create('prefs_pref', 'default',
'(position) The position of the box containing an individual preference.')
style.prefs_pref.xpos = 0.5
style.prefs_pref.xanchor = 'center'
style.create('prefs_left', 'default',
'(position) The position of the left column of preferences.')
style.prefs_left.xpos = 0.25
style.prefs_left.xanchor = "center"
style.prefs_left.ypos = 0.05
style.prefs_left.yalign = "top"
style.create('prefs_right', 'default',
'(position) The position of the right column of preferences.')
style.prefs_right.xpos = 0.75
style.prefs_right.xanchor = "center"
style.prefs_right.ypos = 0.05
style.prefs_right.yalign = "top"
-2
View File
@@ -1,2 +0,0 @@
lib\windows-i686\python.exe -OO renpy.py tutorial
pause
+207
View File
@@ -0,0 +1,207 @@
init:
# Set up the size of the screen.
$ config.screen_width = 800
$ config.screen_height = 600
# Positions of things on the screen.
$ left = Position(xpos=0.0, xanchor='left')
$ right = Position(xpos=1.0, xanchor='right')
$ center = Position()
# Backgrounds.
image whitehouse = Image("whitehouse.jpg")
# Character pictures.
image eileen happy = Image("9a_happy.png")
image eileen vhappy = Image("9a_vhappy.png")
image eileen concerned = Image("9a_concerned.png")
# Character objects.
$ e = Character('Eileen', color=(200, 255, 200, 255))
# The actual game starts here.
label start:
$ renpy.music_start('sun-flower-slow-drag.mid')
scene whitehouse
show eileen vhappy
"Girl" "Welcome to Ren'Py 4!"
show eileen happy
"Girl" "And welcome to American Bishoujo's former southern base,
just outside of Washington, D.C."
show eileen happy at left
"Girl" "This isn't the view from our former base, but it'll do for
this demo."
show eileen happy
"Girl" "My name is Eileen, and while I plan to star in my own game
one day, for now I'm helping to introduce you to Ren'Py."
e "Ren'Py is an engine that makes it easy to write visual novel
games, by taking care of much of the hard work of writing a
game."
e "For example, displaying a line of dialogue is a single
statement. So is displaying a thought or narration."
"I understand."
e "Dialogue is easy to write. Just put a string on a line by
itself, or to the right of an object name or label string."
e "Since dialogue makes up the bulk of these games, we thought it
should be easy to write."
e "Ren'Py can also display menus that let you alter the flow of
the story."
menu:
"Why don't you try a menu out by picking a number?"
"1":
show eileen concerned
e "You picked one. I don't like odd numbers."
"2":
show eileen vhappy
e "You picked two. Even numbers are lucky!"
show eileen happy
e "There are a number of statements that control what's displayed
on the screen. The image statement is used to introduce
images with names."
scene
e "The scene statement can clear the screen..."
scene whitehouse
e "... or it can clear the screen and then show a background."
show eileen happy
e "The show statement is used to show pictures."
e "When the show statement is used on an image with the same first
name (called a tag) as one already shown, it replaces that picture."
show eileen vhappy
e "This makes it easy for characters to change emotions."
hide eileen
e "The hide statement hides an image."
show eileen happy at center
e "A new feature in Ren'Py 4 is the at clause on images, which
lets you say where you want to show the image at. I can go
from the center of the screen..."
show eileen happy at left
e "... to the left of the screen ..."
show eileen happy at right
e "... to the right of the screen ..."
show eileen happy
e "... and back to the center."
e "Ren'Py supports a variety of control statements, such as jump,
call, return, if, and while statements."
e "Rather than bore you with the details, i'll just tell you to
check grab the Ren'Py tutorial from http://www.bishoujo.us/renpy/."
e "That's just about it for writing scripts. Let me show you some
of the new engine features."
e "The first feature I can show off is the ability to go
full-screen. Hit the 'f' key to try it out, and hit 'f'
again to go back to a window."
show eileen vhappy
e "The next feature, rollback, is really neat."
show eileen happy
menu:
"Would you like to see it?"
"Yes.":
pass
"No.":
jump after_rollback
e "Rollback lets you play the game backwards."
e "It lets you go back and reread a line of dialogue you missed,
or even to go back to a menu and make a different choice if you
made a mistake."
e "We do limit the number of steps someone can rollback."
e "Try it out now, by hitting page up until you get back to the
menu, and then choose 'No' instead of 'Yes'."
show eileen concerned
e "Well, try it."
e "You want to hit page up."
e "Well, whatever, your loss. Moving on."
label after_rollback:
show eileen happy
e "Another new feature works only on Windows. If a game crashes,
a notepad is brought up showing the crash message, to help
you debug what went wrong."
e "The biggest new feature, though, is reasonable
documentation, which you can read at http://www.bishoujo.us/renpy/."
show eileen concerned
e "Since this is just a preview release, there are still a few
things missing."
e "For example, there's no support for loading or saving."
e "We also left out music and animations."
show eileen happy
e "Don't worry, though. Those will be coming in the final release,
which is due out in a few weeks."
e "You can begin making your own game by editing game/script.rpy. That's
the script for the game you're playing now."
e "After you make a change, you have to re-run the game to see
the change take effect."
show eileen vhappy
e "Good luck making your own games!"
return
+568
View File
@@ -0,0 +1,568 @@
# This script, but not the artwork associated with it, is in the
# public domain. Feel free to use it as the basis for your own
# game.
# This init block runs first, and sets up all sorts of things that
# are used by the rest of the game. Variables that are set in init
# blocks are _not_ saved, unless they are changed later on in the
# program.
init:
# Set up the size of the screen, and the window title.
$ config.screen_width = 800
$ config.screen_height = 600
$ config.window_title = "The Ren'Py Demo Game"
# Set up the library.
$ library.file_page_length = 3
# Change some styles, to add images in the background of
# the menus and windows.
$ style.mm_root_window.background = Image("mainmenu.jpg")
$ style.gm_root_window.background = Image("gamemenu.jpg")
$ style.window.background = Frame("frame.png", 125, 25)
# These are positions that can be used inside at clauses. We set
# them up here so that they can be used throughout the program.
$ left = Position(xpos=0.0, xanchor='left')
$ right = Position(xpos=1.0, xanchor='right')
$ center = Position()
# Likewise, we set up some transitions that we can use in with
# clauses and statements.
$ fade = Fade(.5, 0, .5) # Fade to black and back.
$ dissolve = Dissolve(0.5)
# Now, we declare the images that are used in the program.
# Backgrounds.
image carillon = Image("carillon.jpg")
image whitehouse = Image("whitehouse.jpg")
image washington = Image("washington.jpg")
image black = Solid((0, 0, 0, 255))
# Character pictures.
image eileen happy = Image("9a_happy.png")
image eileen vhappy = Image("9a_vhappy.png")
image eileen concerned = Image("9a_concerned.png")
# Finally, the character object. This object lets us have the
# character say dialogue without us having to repeatedly type
# her name. It also lets us change the color of her name.
# Character objects.
$ e = Character('Eileen', color=(200, 255, 200, 255))
# The start label marks the place where the main menu jumps to to
# begin the actual game.
label start:
# The save_name variable sets the name of the save game. Like all
# variables declared outside of init blocks, this variable is
# saved and restored with a save file.
$ save_name = "Introduction"
# This variable is only used by our game. If it's true, it means
# that we won the date.
$ date = False
# Start some music playing in the background.
$ renpy.music_start('sun-flower-slow-drag.mid')
# Now, set up the first scene. We first fade in our washington
# background, and then we dissolve in the image of Eileen on top
# of it.
scene washington with fade
show eileen vhappy with dissolve
# Display a line of dialogue. In this case, we manually specify
# who's saying the line of dialoge.
"Girl" "Hi, and welcome to the Ren'Py 4 demo program."
# This instantly replaces the very happy picture of Eileen with
# one showing her merely happy. It demonstrates how the show
# statement lets characters change emotions.
show eileen happy
# Another line of dialogue.
"Girl" "My name is Eileen, and while I plan to one day star in a
real game, for now I'm here to tell you about Ren'Py."
# This line used the e character object, which displays Eileen's
# name in green. The use of a short name for a character object
# lets us save typing when writing the bulk of the dialogue.
e "Ren'Py is a language and engine for writing and playing visual
novel games."
e "Our goal is to allow people to be able to write the script for
a game, and with very little effort, turn that script into
a working game."
e "I can tell you about the features of Ren'Py games, or how to write
your own game. What do you want to know about?"
# This variable is used to save the choices that have been made in
# the main menu.
$ seen_set = [ ]
label choices:
# We change the save name here.
$ save_name = "Question Menu"
# This is the main menu, that lets the user decide what he wants
# to hear about.
menu:
# The set menu clause ensures that each menu choice can only
# be chosen once.
set seen_set
# This is a menu choice. When chosen, the statements in its
# block are executed.
"What are some features of Ren'Py games?":
# We call the features label. The from clause needs to be
# here to ensure that save games work, even after we
# change the script. It was added automatically.
call features from _call_features_1
# When we're done talking about features, jump back up
# to choices.
jump choices
# Another choice.
"How do I write my own games with it?":
call writing from _call_writing_1
jump choices
# This choice has a condition associated with it. It is only
# displayed if the condition is true (in this case, if we have
# selected at least one other choice has been chosen.)
"Where can I find out more?" if seen_set:
call find_out_more from _call_find_out_more_1
jump choices
"Why are we in Washington, DC?":
call washington from _call_washington_1
jump choices
"I think I've heard enough." if seen_set:
jump ending
# This is the section on writing games.
label writing:
# Change the title of the save games.
$ save_name = "Writing Games"
# We start off with a bunch of dialogue.
e "If you want to write a game, I recommend that you read the
Ren'Py tutorial, which you can get from our web page,
http://www.bishoujo.us/renpy/."
e "But here, we'll go over some of the basics of writing Ren'Py
scripts. It might make sense if you open the source for this
game."
e "The source for this game can be found in the file
game/script.rpy."
e "The goal of Ren'Py is to make writing the game similar to
typing up the script on the computer."
e "For example, a line of dialogue is expressed by putting the
character's name next to the dialogue string."
# A string by itself like this displays without a name associated
# with it. So it's useful for dialogue and narration.
"I somehow remember that strings by themselves are displayed as
thoughts or narration."
e "The menu statement makes it easy to create menus."
e "A number of statements let you control what is shown on the
screen."
# This scene statement has a with clause associated with it. In
# this case (based on what is defined in the init clause at the
# top of this script), it causes a fade to black, and then back
# to the new scene.
scene whitehouse with fade
e "The scene statement clears the scene list, which is the list of
things that are shown on the screen."
# This shows an image, and dissolves it in.
show eileen happy with dissolve
e "The show statement shows another image on the screen."
# The at clause here, displays the character on the left side of
# the screen.
show eileen happy at left with dissolve
e "Images can take at clauses that specify where on the screen
they are shown."
show eileen vhappy at left
e "Showing a new image with the same first part of the name
replaces the image in the scene list."
hide eileen with dissolve
e "Finally, the hide statement hides an image, which is useful
when a character leaves the scene."
show eileen happy with dissolve
e "Don't worry, I'm not going anywhere."
e "The with statement is used to cause transitions to
happen. Transitions like fade..."
# This statement hides the transient stuff from being included
# in the next fade.
with None
# This with statement causes things to fade without changing the
# scene.
with fade
e "... or dissolve ..."
# In this block, the scene statement clears the scene list. So we
# have to reshow the eileen happy image, so that it appears that
# just the background is dissolving. Sneaky.
with None
scene washington
show eileen happy
with dissolve
e "... are easily invoked."
e "As of version 4.2, Ren'Py supports image maps, which are like
another form of menu. Let's try one."
# This is an imagemap. It consists of two images, and a list of
# hotspots. For each hotspot we give the coordinates of the left,
# top, right, and bottom sides, and the value to return if it is
# picked.
$ result = renpy.imagemap("ground.png", "selected.png", [
(100, 100, 300, 400, "eileen"),
(500, 100, 700, 400, "lucy")
])
# We've assigned the chosen result from the imagemap to the
# result variable. We can use an if statement to vary what
# happens based on the user's choice.
if result == "eileen":
show eileen vhappy
e "You picked me!"
elif result == "lucy":
show eileen concerned
e "It looks like you picked Lucy."
# Eileen is being a bit possesive here. :-P
if date:
e "You can forget about Saturday."
$ date = False
show eileen happy
e "Ren'Py supports music, such as what's playing in the
background..."
# This plays a sound effect.
$ renpy.play("18005551212.wav")
e "... and sound effects, like the one that just played."
e "Ren'Py also includes a number of control statements, and even
lets you include python code."
e "Rather than go into this here, you can read all about it in the
tutorial."
e "If you want to make changes, you can edit the script for this
game by editing game/script.rpy"
e "When you've made a change, just re-run the game to see your
change in action."
e "Would you like to know about something else?"
# We return back up to the menu that lets the user pick a topic.
return
# This ends the well-commented portion of this script.
label features:
$ save_name = "Features"
e "By providing a range of useful features, we let game authors
focus on writing their games."
e "What are some of these features? Well, first of all, we take
care of displaying the screen, as well as dialogue and menus."
e "You can navigate through the game using the keyboard or the
mouse. If you've gotten this far, you've probably figured that
out already."
e "If you press 'f', you can toggle fullscreen mode. Pressing 'm'
will toggle music on and off."
e "Right-clicking or pressing escape will bring you to the game
menu."
e "The game menu lets you save or load the game. Ren'Py doesn't
limit the number of save slots available. You can create as
many slots as you can stand."
e "The game menu also lets you restart or quit the game. But you
wouldn't want to do that, would you?"
e "Finally, the game menu lets you set up the game
preferences. These preferences are saved between games."
show eileen vhappy
e "The next feature is really neat."
show eileen happy
menu rollback_menu:
"Would you like to hear about rollback?"
"Yes.":
pass
"No.":
jump after_rollback
e "Rollback is a feature that only Ren'Py has. It lets you go back
in time in a game."
e "For example, you can go back to a menu and save or make a
different choice."
e "You can access it by pressing page up or scrolling up on your
mouse wheel."
e "Why don't you try it by going back to the last menu and
choosing 'No.' instead of 'Yes.'"
e "Press page up or scroll up the mouse wheel."
show eileen concerned
e "Well, are you going to try it?"
e "Your loss."
e "Moving on."
label after_rollback:
show eileen happy
e "Ren'Py gives you a few ways of skipping dialogue. Pressing
control quickly skips dialogue you've seen at least once, ever."
e "Pressing page down or scrolling the mouse wheel down will let
you skip dialogue you've seen this session. This is useful
after a rollback."
e "If you want to try these, you might want to rollback a bit
first, so you can skip over something you've seen already."
e "Finally, Ren'Py has predictive image loading, so you rarely
have to wait for a new image to load."
e "Remember, all these features are built into the engine or
standard library. So every game written with Ren'Py has them."
e "Is there anything else you'd like to know about?"
return
label find_out_more:
$ save_name = "Find Out More"
e "There are a few places you can go to find out more about
Ren'Py."
e "The Ren'Py homepage, http://www.bishoujo.us/renpy/, is probably
the best place to start."
e "There, you can download new versions of Ren'Py, and read the
tutorial online."
e "If you have questions, the best place to ask them is the Ren'Py
forum of the Lemmasoft forums."
e "Just go to http://www.lemmasoft.net/forums/, and click on
Ren'Py."
e "We thank Blue Lemma for hosting our forum."
e "Finally, feel free to email or IM us if you need help. You can
get the addresses to use from http://www.bishoujo.us/renpy/."
e "We really want people to make their own games with Ren'Py, and
if there's anything we can do to help, just tell us."
e "Is there anything I can help you with now?"
return
label washington:
$ save_name = "Washington, DC"
e "We're in Washington, DC because over Summer 2004 American
Bishoujo's home base was just outside of DC."
scene whitehouse
show eileen happy at left
with fade
e "Even though we've moved back to New York, we took a bunch of
pictures, and decided to use them."
show eileen concerned at left
e "It was easier than drawing new pictures for this demo."
show eileen happy at left
e "Do you have a favorite landmark in or around DC?"
menu:
"The White House.":
e "I was supposed to go on a tour of the West Wing, once."
show eileen concerned
e "They wouldn't let us in."
e "The secret service guy who was supposed to show us
around was out of town that day."
e "Too bad."
"The National Mall.":
e "It's always fun to go down to the national mall."
e "You can visit the monuments, or see one of the
museums."
e "I guess you could run out of things to do after a while
but I didn't over the course of a summer."
"The Netherlands Carillon.":
jump netherlands
jump post_netherlands
label netherlands:
show eileen vhappy at left
e "You've been to the Netherlands Carillon?"
scene carillon
show eileen vhappy at left
with dissolve
e "It may not be much to look at but the sound of the bells is
really neat."
e "I love going there. Saturdays during the summer, they have
these recitals in the park where a guy comes and plays the
bells live."
e "You can climb to the top and talk to him, if you're not afraid
of heights."
e "Once, I saw a little girl there, maybe three or four years old.
The guy played the bumblebee song for here, and he even let her play the last
note. It was so cute!"
e "I haven't been there for so long."
menu:
"Would you like to go there sometime?":
e "You mean, together?"
e "Sure, why not. How does next Saturday sound?"
e "It's a date."
$ date = True
"That sounds nice.":
show eileen happy at left
e "Well, it is."
label post_netherlands:
scene washington
show eileen happy
with fade
e "Anyway, is there anything else you want to know about Ren'Py?"
return
label ending:
$ save_name = "Ending"
e "Well, that's okay."
e "I hope you'll consider using Ren'Py for your next game
project."
show eileen vhappy
e "Thanks for viewing this demo!"
if date:
e "And I'll see you on Saturday."
scene black with fade
"Ren'Py and the Ren'Py demo were written by PyTom."
'The background music is "Sun Flower Slow Drag" by S. Joplin
(1868-1917). Thanks to the Mutopia project for making it
available.'
'The author would like to thank everyone who makes original
English-language bishoujo games, and the people on the Lemmasoft forums
who encouraged him.'
"We can't wait to see what you do with this. Good luck!"
$ renpy.full_restart()
Executable → Regular
+99 -206
View File
@@ -1,236 +1,129 @@
#!/home/tom/ab/renpy/lib/linux-x86_64/python -O
# Builds a distribution of Ren'Py.
import sys
import os.path
import os
import compileall
import shutil
import subprocess
import argparse
import glob
import sys
if not sys.flags.optimize:
raise Exception("Optimization disabled.")
def match_times(source, dest):
ROOT = os.path.dirname(os.path.abspath(__file__))
stat = os.stat(source)
os.utime(dest, (stat.st_atime, stat.st_mtime))
def dosify(s):
return s.replace("\n", "\r\n")
return s
def copy_tutorial_file(src, dest):
"""
Copies a file from src to dst. Lines between "# tutorial-only" and
"# end-tutorial-only" comments are omitted from the copy.
"""
def copy_file(source, dest, license=""):
sf = open(src, "rb")
df = open(dest, "wb")
print source, "->", dest
# True if we want to copy the line.
copy = True
sf = file(source, "rb")
df = file(dest, "wb")
for l in sf:
if "# tutorial-only" in l:
copy = False
elif "# end-tutorial-only" in l:
copy = True
else:
if copy:
df.write(l)
df.write(license)
data = sf.read()
if dest.endswith(".txt") or dest.endswith(".py") or dest.endswith(".rpy") or dest.endswith(".bat"):
data = dosify(data)
df.write(data)
sf.close()
df.close()
match_times(source, dest)
def copy_tree(source, dest, should_copy=lambda fn : True, license=""):
os.makedirs(dest)
for dirpath, dirnames, filenames in os.walk(source):
if "/saves" in dirpath:
continue
if "/CVS" in dirpath:
continue
reldir = dirpath[len(source):]
dstrel = dest + "/" + reldir
for i in dirnames:
if i == "CVS":
continue
os.mkdir(dstrel + "/" + i)
for i in filenames:
if not should_copy(i):
continue
copy_file(dirpath + "/" + i, dstrel + "/" + i, license=license)
def main():
if not sys.flags.optimize:
raise Exception("Not running with python optimization.")
target = sys.argv[1]
gamedir = sys.argv[2]
ap = argparse.ArgumentParser()
ap.add_argument("version")
ap.add_argument("--fast", action="store_true")
ap.add_argument("--pygame", action="store", default=None)
ap.add_argument("--no-rapt", action="store_true")
# Read license.
lf = file("LICENSE.txt")
license = "#!/usr/bin/env python\n\n"
for l in lf:
license += "# " + l
args = ap.parse_args()
lf.close()
# Revision updating is done early, so we can do it even if the rest
# of the program fails.
license = dosify(license)
# Determine the version. We grab the current revision, and if any
# file has changed, bump it by 1.
import renpy
if os.path.exists(target):
raise Exception("Target exists!")
match_version = ".".join(str(i) for i in renpy.version_tuple[:2]) #@UndefinedVariable
# Start off with the target.
copy_tree("dist", target,
should_copy = lambda fn : fn not in [ 'traceback.txt' ] and not fn.endswith(".log"))
s = subprocess.check_output([ "git", "describe", "--tags", "--dirty", "--match", match_version ])
parts = s.strip().split("-")
# Copy renpy modules.
copy_tree("renpy", target + "/renpy",
should_copy = lambda fn : fn.endswith(".py"),
license=license)
if len(parts) <= 2:
vc_version = 0
else:
vc_version = int(parts[1])
doc_files = [
'example.html',
'tutorial.html',
'style.css',
]
if parts[-1] == "dirty":
vc_version += 1
# Copy doc
copy_tree("doc", target + "/doc",
should_copy = lambda fn : fn in doc_files)
with open("renpy/vc_version.py", "w") as f:
f.write("vc_version = {}".format(vc_version))
# Copy the game
copy_tree(gamedir, target + "/game",
should_copy = lambda fn : not fn.startswith(".") and not fn.endswith("~"))
try:
reload(sys.modules['renpy.vc_version']) #@UndefinedVariable
except:
import renpy.vc_version # @UnusedImport
reload(sys.modules['renpy'])
# Check that the versions match.
full_version = renpy.version_only #@UndefinedVariable
if "-" not in args.version \
and not full_version.startswith(args.version):
raise Exception("The command-line and Ren'Py versions do not match.")
os.environ['RENPY_BUILD_VERSION'] = args.version
# The destination directory.
destination = os.path.join("dl", args.version)
print "Version {} ({})".format(args.version, full_version)
# Perhaps autobuild.
if "RENPY_BUILD_ALL" in os.environ:
print("Autobuild...")
subprocess.check_call(["scripts/autobuild.sh"])
# Copy over the screens, to keep them up to date.
copy_tutorial_file("tutorial/game/screens.rpy", "templates/english/game/screens.rpy")
# Compile all the python files.
compileall.compile_dir("renpy/", ddir="renpy/", force=1, quiet=1)
# Compile the various games.
if not args.fast:
for i in [ 'tutorial', 'launcher', 'the_question' ]:
print "Compiling", i
subprocess.check_call(["./renpy.sh", i, "quit" ])
# Kick off the rapt build.
if not args.fast:
print "Cleaning RAPT."
sys.path.insert(0, os.path.join(ROOT, "rapt", "buildlib"))
import rapt.interface # @UnresolvedImport
import rapt.build # @UnresolvedImport
interface = rapt.interface.Interface()
rapt.build.distclean(interface)
print "Compiling RAPT and renios."
compileall.compile_dir("rapt/buildlib/", ddir="rapt/buildlib/", quiet=1)
compileall.compile_dir("renios/buildlib/", ddir="renios/buildlib/", quiet=1)
if not os.path.exists(destination):
os.makedirs(destination)
if args.fast:
cmd = [
"./renpy.sh",
"launcher",
"distribute",
"launcher",
"--package",
"sdk",
"--destination",
destination,
"--no-update",
]
else:
cmd = [
"./renpy.sh",
"launcher",
"distribute",
"launcher",
"--destination",
destination,
]
print
subprocess.check_call(cmd)
# Sign the update.
if not args.fast:
subprocess.check_call([
"scripts/sign_update.py",
"/home/tom/ab/keys/renpy_private.pem",
os.path.join(destination, "updates.json"),
])
# Package pygame_sdl2.
if not args.fast:
subprocess.check_call([
"pygame_sdl2/distribute.py",
"for-renpy-" + args.version,
"--dest",
os.path.abspath(destination)
])
# Write 7z.exe.
sdk = "renpy-{}-sdk".format(args.version)
if not args.fast:
# shutil.copy("renpy-ppc.zip", os.path.join(destination, "renpy-ppc.zip"))
with open("7z.sfx", "rb") as f:
sfx = f.read()
os.chdir(destination)
if os.path.exists(sdk):
shutil.rmtree(sdk)
subprocess.check_call([ "unzip", "-q", sdk + ".zip" ])
if os.path.exists(sdk + ".7z"):
os.unlink(sdk + ".7z")
sys.stdout.write("Creating -sdk.7z")
p = subprocess.Popen([ "7z", "a", sdk +".7z", sdk], stdout=subprocess.PIPE)
for i, _l in enumerate(p.stdout):
if i % 10 != 0:
continue
sys.stdout.write(".")
sys.stdout.flush()
if p.wait() != 0:
raise Exception("7z failed")
with open(sdk + ".7z", "rb") as f:
data = f.read()
with open(sdk + ".7z.exe", "wb") as f:
f.write(sfx)
f.write(data)
os.unlink(sdk + ".7z")
shutil.rmtree(sdk)
else:
os.chdir(destination)
if os.path.exists(sdk + ".7z.exe"):
os.unlink(sdk + ".7z.exe")
print
copy_tree("common", target + "/common",
should_copy = lambda fn : not fn.startswith(".") and not fn.endswith("~"))
def cp(x, license=""):
copy_file(x, target + "/" + x)
cp("CHANGELOG.txt")
cp("LICENSE.txt")
cp("README_RENPY.txt")
cp("archive_images.bat")
cp("run_game.py", license=license)
cp("archiver.py", license=license)
cp("build_exe.py", license=license)
cp("add_from.py", license=license)
cp("renpy-mode.el")
if __name__ == "__main__":
main()
+12
View File
@@ -0,0 +1,12 @@
all:: tutorial.html example.html
tutorial.html: tutorial.xml preprocess.py stylesheet.xslt style.css styles.xml
python preprocess.py tutorial.xml > tutorial.hi.xml
xsltproc stylesheet.xslt tutorial.hi.xml > tutorial.html
cp tutorial.html style.css ~/ab/website/renpy/devel/doc
example.html: example.xml preprocess.py stylesheet.xslt style.css styles.xml
python preprocess.py example.xml > example.hi.xml
xsltproc stylesheet.xslt example.hi.xml > example.html
cp example.html style.css ~/ab/website/renpy/devel/doc
+13
View File
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
<doc>
<title>Demo Script Example</title>
<p><a href="tutorial.html">Return to the tutorial.</a></p>
<example>
<!-- include ../demo2/script.rpy -->
</example>
<p><a href="tutorial.html">Return to the tutorial.</a></p>
</doc>
+138
View File
@@ -0,0 +1,138 @@
#!/usr/bin/python
import re
import sys
import time
import inspect
sys.path.append('..')
import renpy
keywords = [
r'\bimage\b',
r'\bscene\b',
r'\bshow\b',
r'\bhide\b',
r'\binit\b',
r'\$',
r'\blabel\b',
r'\bmenu\b',
r'\bset\b',
r'\bif\b',
r'\bwhile\b',
r'\bjump\b',
r'\blabel\b',
r'\bcall\b',
r'\breturn\b',
r'\bfrom\b',
r'\belif\b',
r'\belse\b',
r'\bpass\b',
r'\bwith\b',
r'\bat\b',
r'\bpython\b',
]
kwre = '|'.join(keywords)
def example(m):
s = m.group(1)
rv = ""
pos = 0
while pos < len(s):
m = re.compile(r'(?s)"(([^"]|\\.)*)"').match(s, pos)
if m:
rv += '"<span class="string">%s</span>"' % m.group(1)
pos = m.end()
continue
m = re.compile(r"(?s)'(([^']|\\.)*)'").match(s, pos)
if m:
rv += '\'<span class="string">%s</span>\'' % m.group(1)
pos = m.end()
continue
m = re.compile(r"(?s)(#[^\n]+)").match(s, pos)
if m:
rv += '<span class="comment">%s</span>' % m.group(1)
pos = m.end()
continue
m = re.compile(kwre).match(s, pos)
if m:
rv += '<span class="keyword">%s</span>' % m.group(0)
pos = m.end()
continue
rv += s[pos]
pos += 1
return "<example>" + rv + "</example>"
def function(m):
name = m.group(1)
store = vars(renpy.store)
renpy.store.renpy = renpy.exports
func = eval(name, store)
doc = func.__doc__
if inspect.isclass(func):
func = func.__init__
if func.__doc__:
doc += "\n" + func.__doc__
a, b, c, d = inspect.getargspec(func)
args = inspect.formatargspec(a[1:], b, c, d)
else:
args = inspect.formatargspec(*inspect.getargspec(func))
docparas = []
for p in re.split(r'\n\s*\n', doc):
p = p.strip()
p = re.sub(r"\@param (\w+):", r'<param>\1</param> -', p)
p = "<p>" + p + "</p>"
docparas.append(p)
doc = '\n'.join(docparas)
return '<function name="%(name)s" sig="%(args)s">%(doc)s</function>' % locals()
def include(m):
f = file(m.group(1))
rv = f.read()
f.close()
return rv
def main():
f = file(sys.argv[1])
s = f.read()
f.close()
s = re.sub(r"<!-- func (\S+) -->", function, s)
s = re.sub(r"<!-- include (\S+) -->", include, s)
s = re.sub(r"<!-- date -->", time.strftime("%04Y-%02m-%02d %02H:%02M"), s)
s = re.sub(r"(?s)<example>(.*?)</example>", example, s)
print s
if __name__ == "__main__":
main()
+81
View File
@@ -0,0 +1,81 @@
BODY {
font-family: sans-serif;
}
H1 {
text-align: center;
margin-top: 2em;
margin-bottom: 2em;
}
H2 {
text-align: center;
margin-top: 1em;
margin-bottom: 1em;
}
PRE.example {
border: 2px black solid;
margin-left: 10%;
margin-right: 10%;
background: #f0f0f0;
padding: 1em;
padding-bottom: 0em;
}
DIV.rule {
border: 2px black solid;
margin-left: 10%;
margin-right: 10%;
margin-bottom: 1em;
background: #f0f0ff;
padding: 1em;
}
SPAN.comment {
color: #800000;
}
SPAN.string {
color: #006000;
}
SPAN.keyword {
color: #804000;
}
TD.funcname {
font-family: monospace;
font-weight: bold;
}
TD.funcsig {
font-family: monospace;
}
DIV.funcbody {
margin-left: 5%;
margin-bottom: 1em;
}
SPAN.param {
font-style: italic;
}
P.prop {
margin-left: 5%;
}
SPAN.propname {
font-family: monospace;
font-weight: bold;
}
DT {
margin-top: 1em;
}
DT.code {
font-family: monospace;
}
+165
View File
@@ -0,0 +1,165 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- First, copy the element. -->
<xsl:template match="*" priority="-1">
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<!-- Now, handle some elements specially. -->
<xsl:template match="doc">
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css" />
<title><xsl:value-of select="title" /></title>
</head>
<body>
<xsl:apply-templates />
</body>
</html>
</xsl:template>
<xsl:template match="toc">
<ol>
<xsl:for-each select="../h3">
<li>
<a>
<xsl:attribute name="href">#<xsl:value-of select="." /></xsl:attribute>
<xsl:value-of select="."/>
</a>
</li>
</xsl:for-each>
</ol>
</xsl:template>
<xsl:template match="funcindex">
<ul>
<xsl:for-each select="//function">
<xsl:sort select="@name" />
<li>
<a>
<xsl:attribute name="href">#<xsl:value-of select="@name" /></xsl:attribute>
<xsl:value-of select="@name"/>
</a>
</li>
</xsl:for-each>
</ul>
</xsl:template>
<xsl:template match="varindex">
<ul>
<xsl:for-each select="//var">
<xsl:sort select="@name" />
<li>
<a>
<xsl:attribute name="href">#<xsl:value-of select="@name" /></xsl:attribute>
<xsl:value-of select="@name"/>
</a>
</li>
</xsl:for-each>
</ul>
</xsl:template>
<xsl:template match="styleindex">
<ul>
<xsl:for-each select="//renpy_style">
<xsl:sort select="@name" />
<li>
<a>
<xsl:attribute name="href">#<xsl:value-of select="@name" /></xsl:attribute>
<xsl:value-of select="@name"/>
</a>
</li>
</xsl:for-each>
</ul>
</xsl:template>
<xsl:template match="propindex">
<ul>
<xsl:for-each select="//prop">
<xsl:sort select="@name" />
<li>
<a>
<xsl:attribute name="href">#<xsl:value-of select="@name" /></xsl:attribute>
<xsl:value-of select="@name"/>
</a>
</li>
</xsl:for-each>
</ul>
</xsl:template>
<xsl:template match="h3">
<a>
<xsl:attribute name="name"><xsl:value-of select="." /></xsl:attribute>
<h3><xsl:apply-templates /></h3>
</a>
</xsl:template>
<xsl:template match="title">
<h1><xsl:apply-templates /></h1>
</xsl:template>
<xsl:template match="subtitle">
<h2><xsl:apply-templates /></h2>
</xsl:template>
<xsl:template match="def">
<b><i><xsl:apply-templates /></i></b>
</xsl:template>
<xsl:template match="example">
<pre class="example"><xsl:apply-templates /></pre>
</xsl:template>
<xsl:template match="rule">
<div class="rule"><xsl:apply-templates /></div>
</xsl:template>
<xsl:template match="function">
<a><xsl:attribute name="name"><xsl:value-of select="@name" /></xsl:attribute></a>
<table>
<tr>
<td valign="top" class="funcname"><xsl:value-of select="@name" /></td>
<td class="funcsig"><xsl:value-of select="@sig" />:</td>
</tr>
</table>
<div class="funcbody">
<xsl:apply-templates />
</div>
</xsl:template>
<xsl:template match="param">
<span class="param"><xsl:apply-templates /></span>
</xsl:template>
<xsl:template match="prop">
<a><xsl:attribute name="name"><xsl:value-of select="@name" /></xsl:attribute></a>
<p class="prop">
<span class="propname"><xsl:value-of select="@name" /></span>
--- <xsl:apply-templates />
</p>
</xsl:template>
<xsl:template match="renpy_style">
<a><xsl:attribute name="name"><xsl:value-of select="@name" /></xsl:attribute></a>
<dt><b><xsl:value-of select="@name" /></b>:</dt>
<dd><xsl:apply-templates /></dd>
</xsl:template>
<xsl:template match="renpy_style_inherits">
(inherits from <b><xsl:apply-templates /></b>) <br />
</xsl:template>
<xsl:template match="var">
<a><xsl:attribute name="name"><xsl:value-of select="@name" /></xsl:attribute></a>
<dt class="var"><b><xsl:value-of select="@name" /></b> = <xsl:value-of select="@value" /></dt>
<dd>
<xsl:apply-templates />
</dd>
</xsl:template>
</xsl:stylesheet>
+2466
View File
File diff suppressed because it is too large Load Diff
-178
View File
@@ -1,178 +0,0 @@
<html>
<head>
<title>README</title>
<style>
BODY {
background: #fff;
color: #444;
padding-left: 20%;
padding-top: 1em;
padding-bottom: 1em;
padding-right: 20%;
font-family: sans-serif;
line-height: 1.6em;
}
DT {
font-weight: bold;
margin-top: .33em;
}
H2 {
color: #000;
margin-left: -2.5em;
}
H3 {
color: #000;
margin-left: -1.5em;
}
.editsection {
display: none;
}
</style>
</head>
<body>
<h2>Basic Help</h2>
<p>
To advance through the game, <tt>left-click</tt> or press the <tt>space</tt> or <tt>enter</tt> keys. When at a menu,
<tt>left-click</tt> to make a choice, or use the arrow keys to select a choice and <tt>enter</tt> to activate it.
</p>
<h3>Game Menu</h3>
<p>
When playing a game, <tt>right-click</tt> or press the <tt>escape</tt> key to enter the game menu. The game menu
gives the following choices:
</p>
<dl>
<dt>Return</dt>
<dd>Returns to the game.</dd>
<dt>Save Game</dt>
<dd>Allows you to save a game by clicking on a save slot.</dd>
<dt>Load Game</dt>
<dd>Allows you to load a game by clicking on a save slot. Clicking on "Auto" accesses the automatic save slots.</dd>
<dt>Preferences</dt>
<dd>
Changes the game preferences (options/configuration):
<dl>
<dt>Display</dt>
<dd>Switches between fullscreen and windowed mode.</dd>
<dt>Transitions</dt>
<dd>Controls the display of transitions between game screens.</dd>
<dt>Text Speed</dt>
<dd>Controls the rate at which text displays. The further to the right this slider is, the faster the text
will display. All the way to the right causes text to be shown instantly.</dd>
<dt>Joystick</dt>
<dd>Lets you control the game using a joystick.</dd>
<dt>Skip</dt>
<dd>Chooses between skipping messages that have been already seen (in any play through the game), and
skipping all messages.</dd>
<dt>Begin Skipping</dt>
<dd>Returns to the game, while skipping.</dd>
<dt>After Choices</dt>
<dd>Controls if skipping stops upon reaching a menu.</dd>
<dt>Auto-Forward Time</dt>
<dd>Controls automatic advance. The further to the left this slider is, the shorter the amount of time
before the game advances. All the way to the right means text will never auto-forward.</dd>
<dt>Music, Sound, and Voice Volume</dt>
<dd>Controls the volume of the Music, Sound effect, and Voice channels, respectively. The further to the
right these are, the louder the volume.</dd>
</dl>
</dd>
<dt>Main Menu</dt>
<dd>Returns to the main menu, ending the current game.</dd>
<dt>Help</dt>
<dd>Shows this help screen.</dd>
<dt>Quit</dt>
<dd>Exits the game; the game will be closed and ended.</dd>
</dl>
<h3>Key and Mouse Bindings</h3>
<dl>
<dt>Left-click, Enter</dt>
<dd>Advances through the game, activates menu choices, buttons, and sliders.</dd>
<dt>Space</dt>
<dd>Advances through the game, but does not activate choices.</dd>
<dt>Arrow Keys</dt>
<dd>Navigates between menu choices, buttons, and sliders.</dd>
<dt>Ctrl</dt>
<dd>Causes skipping to occur while the ctrl key is held down.</dd>
<dt>Tab</dt>
<dd>Toggles skipping, causing it to occur until tab is pressed again.</dd>
<dt>Mousewheel-Up, PageUp</dt>
<dd>Causes rollback to occur. Rollback reverses the game back in time, showing prior text and even allowing
menu choices to be changed.</dd>
<dt>Mousewheel-Down, PageDown</dt>
<dd>Causes rollforward to occur, canceling out a previous rollback.</dd>
<dt>Right-click, Escape</dt>
<dd>Enters the game menu. When in the game menu, returns to the game.</dd>
<dt>Middle-click, H</dt>
<dd>Hides the text window and other transient displays.</dd>
<dt>F</dt>
<dd>Toggles fullscreen mode</dd>
<dt>S</dt>
<dd>Takes a screenshot, saving it in a file named screenshotxxxx.png, where xxxx is a serial number.</dd>
<dt>Alt-M, Command-H</dt>
<dd>Hides (iconifies) the window.</dd>
<dt>Alt-F4, Command-Q</dt>
<dd>Quits the game.</dd>
<dt>Delete</dt>
<dd>When a save slot is selected, deletes that save slot.</dd>
<dt>v</dt>
<dd>
Toggles self-voicing mode, which reads text to the user using an os-supplied speech synthesizer. For more
information, please read the <a href="http://www.renpy.org/doc/html/self_voicing.html">self-voicing</a>
documentation.
</dd>
<dt>Shift+C</dt>
<dd>Toggles clipboard-voicing mode, which copies text to the clipboard so it can be read by a screen reader.</dd>
</dl>
<h3>Controller Support and Bindings</h3>
<p>
This game should automatically detect and use game controllers supported by
SDL2. Other controllers can be configured using third-party configuration tools
like the <a href="http://www.generalarcade.com/gamepadtool/">SDL2 Gampad Tool</a>
</p>
<p>
A small number of systems may have problems using detected game controllers. Should
that happen, hold down shift as the game starts, and disable the controller support.
</p>
<p>The following bindings are used:</p>
<dl>
<dt>Right Trigger, A (Bottom Button)</dt>
<dd>Advances through the game, activates menu choices, buttons, and sliders.</dd>
<dt>Guide, Start</dt>
<dd>Enters the game menu. When in the game menu, returns to the game.</dd>
<dt>Directional Pad, Analog Sticks</dt>
<dd>Navigates between menu choices, buttons, and sliders.</dd>
<dt>Left Trigger, Left Shoulder, Back</dt>
<dd>Causes rollback to occur. Rollback reverses the game back in time, showing prior text and even allowing
menu choices to be changed.</dd>
<dt>Right Shoulder</dt>
<dd>Causes rollforward to occur, canceling out a previous rollback.</dd>
<dt>Y (Top Button)</dt>
<dd>Hides the text window and other transient displays.</dd>
</dl>
<h2>Legal Notice</h2>
<p>
This program contains free software licensed under a number of licenses, including the GNU Lesser Public License. A
complete list of software is available at <a href="http://www.renpy.org/doc/html/license.html">http://www.renpy.org/doc/html/license.html</a>.
</p>
</body>
</html>
-4
View File
@@ -1,4 +0,0 @@
import renpy
# Do nothing when the editor is invoked.
Editor = renpy.editor.Editor
-4
View File
@@ -1,4 +0,0 @@
import renpy
# Pass the file off to the system editor (as determined by file associations).
Editor = renpy.editor.SystemEditor
-144
View File
@@ -1,144 +0,0 @@
import binascii
def a2b(a):
return binascii.a2b_hex(''.join(a.split()))
resources = {
260 : a2b('''
01 00 ff ff 00 00 00 00 00 00 00 00 c8 00 c0 80
02 00 00 00 00 00 b8 00 29 00 00 00 00 00 00 00
08 00 90 01 00 01 4d 00 53 00 20 00 53 00 68 00
65 00 6c 00 6c 00 20 00 44 00 6c 00 67 00 00 00
00 00 00 00 00 00 00 00 01 00 01 50 7f 00 14 00
32 00 0e 00 01 00 00 00 ff ff 80 00 4f 00 4b 00
00 00 00 00 00 00 00 00 00 00 00 00 04 08 00 50
07 00 07 00 aa 00 0c 00 ea 03 00 00 ff ff 81 00
00 00 00 00
'''),
261 : a2b('''
01 00 ff ff 00 00 00 00 00 00 00 00 c8 00 c0 80
04 00 00 00 00 00 b8 00 3a 00 00 00 00 00 00 00
08 00 90 01 00 01 4d 00 53 00 20 00 53 00 68 00
65 00 6c 00 6c 00 20 00 44 00 6c 00 67 00 00 00
00 00 00 00 00 00 00 00 80 00 81 50 07 00 14 00
aa 00 0c 00 ec 03 00 00 ff ff 81 00 00 00 00 00
00 00 00 00 00 00 00 00 01 00 01 50 7f 00 25 00
32 00 0e 00 01 00 00 00 ff ff 80 00 4f 00 4b 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 50
4a 00 25 00 32 00 0e 00 02 00 00 00 ff ff 80 00
43 00 61 00 6e 00 63 00 65 00 6c 00 00 00 00 00
00 00 00 00 00 00 00 00 04 08 00 50 07 00 07 00
aa 00 0c 00 eb 03 00 00 ff ff 81 00 00 00 00 00
'''),
262 : a2b('''
01 00 ff ff 00 00 00 00 00 00 00 00 c8 00 c0 80
04 00 00 00 00 00 b8 00 29 00 00 00 00 00 00 00
08 00 90 01 00 01 4d 00 53 00 20 00 53 00 68 00
65 00 6c 00 6c 00 20 00 44 00 6c 00 67 00 00 00
00 00 00 00 00 00 00 00 00 00 01 50 7f 00 14 00
32 00 0e 00 06 00 00 00 ff ff 80 00 59 00 65 00
73 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
04 08 00 50 07 00 07 00 aa 00 0c 00 ed 03 00 00
ff ff 81 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 01 50 07 00 14 00 32 00 0e 00 07 00 00 00
ff ff 80 00 4e 00 6f 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 01 50 4b 00 14 00 32 00 0e 00
02 00 00 00 ff ff 80 00 43 00 61 00 6e 00 63 00
65 00 6c 00 00 00 00 00
'''),
263 : a2b('''
01 00 ff ff 00 00 00 00 00 00 00 00 80 00 ca 80
03 00 00 00 00 00 e2 00 29 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 81 50 07 00 14 00
97 00 0e 00 eb 03 00 00 6d 00 73 00 63 00 74 00
6c 00 73 00 5f 00 70 00 72 00 6f 00 67 00 72 00
65 00 73 00 73 00 33 00 32 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 04 08 00 50 07 00 07 00
d4 00 0c 00 ea 03 00 00 ff ff 81 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 50 a9 00 14 00
32 00 0e 00 02 00 00 00 ff ff 80 00 43 00 61 00
6e 00 63 00 65 00 6c 00 00 00 00 00
'''),
264 : a2b('''
01 00 ff ff 00 00 00 00 00 00 00 00 c8 00 c0 80
04 00 00 00 00 00 b8 00 3a 00 00 00 00 00 00 00
08 00 90 01 00 01 4d 00 53 00 20 00 53 00 68 00
65 00 6c 00 6c 00 20 00 44 00 6c 00 67 00 00 00
00 00 00 00 00 00 00 00 a0 00 81 50 07 00 14 00
aa 00 0c 00 ec 03 00 00 ff ff 81 00 00 00 00 00
00 00 00 00 00 00 00 00 01 00 01 50 7f 00 25 00
32 00 0e 00 01 00 00 00 ff ff 80 00 4f 00 4b 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 50
4a 00 25 00 32 00 0e 00 02 00 00 00 ff ff 80 00
43 00 61 00 6e 00 63 00 65 00 6c 00 00 00 00 00
00 00 00 00 00 00 00 00 04 08 00 50 07 00 07 00
aa 00 0c 00 eb 03 00 00 ff ff 81 00 00 00 00 00
'''),
265 : a2b('''
01 00 ff ff 00 00 00 00 00 00 00 00 c8 00 c8 80
12 00 00 00 00 00 d9 00 fc 00 00 00 00 00 00 00
08 00 90 01 00 01 4d 00 53 00 20 00 53 00 68 00
65 00 6c 00 6c 00 20 00 44 00 6c 00 67 00 00 00
00 00 00 00 00 00 00 00 01 00 01 50 6c 00 ea 00
30 00 0e 00 01 00 00 00 ff ff 80 00 4f 00 4b 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 50
a2 00 ea 00 30 00 0e 00 02 00 00 00 ff ff 80 00
43 00 61 00 6e 00 63 00 65 00 6c 00 00 00 00 00
00 00 00 00 00 00 00 00 07 00 00 50 06 00 06 00
cc 00 4e 00 ff ff ff ff ff ff 80 00 00 00 00 00
00 00 00 00 00 00 00 00 03 00 21 50 48 00 12 00
84 00 64 00 03 00 00 00 ff ff 85 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 02 50 0c 00 24 00
c0 00 08 00 04 00 00 00 ff ff 82 00 00 00 00 00
00 00 00 00 00 00 00 00 80 00 81 50 0c 00 30 00
c0 00 0e 00 05 00 00 00 ff ff 81 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 01 50 9c 00 42 00
30 00 0e 00 06 00 00 00 ff ff 80 00 41 00 64 00
64 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
07 00 00 50 06 00 54 00 cb 00 3c 00 ff ff ff ff
ff ff 80 00 00 00 00 00 00 00 00 00 00 00 00 00
03 00 21 50 48 00 61 00 84 00 64 00 07 00 00 00
ff ff 85 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 02 50 0c 00 72 00 c0 00 08 00 08 00 00 00
ff ff 82 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 01 50 9c 00 7e 00 30 00 0e 00 09 00 00 00
ff ff 80 00 41 00 64 00 64 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 01 50 06 00 96 00
42 00 0e 00 0a 00 00 00 ff ff 80 00 41 00 64 00
64 00 20 00 66 00 69 00 6c 00 65 00 2e 00 2e 00
2e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 01 50 4e 00 96 00 42 00 0e 00 0b 00 00 00
ff ff 80 00 41 00 64 00 64 00 20 00 6e 00 65 00
77 00 20 00 66 00 69 00 6c 00 65 00 2e 00 2e 00
2e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 01 50 06 00 a8 00 42 00 0e 00 0c 00 00 00
ff ff 80 00 41 00 64 00 64 00 20 00 66 00 6f 00
6c 00 64 00 65 00 72 00 2e 00 2e 00 2e 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 07 00 00 50
06 00 c6 00 cc 00 1e 00 ff ff ff ff ff ff 80 00
43 00 6f 00 6d 00 6d 00 61 00 6e 00 64 00 20 00
6c 00 69 00 6e 00 65 00 3a 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 80 00 81 50 0c 00 d2 00
c0 00 0e 00 0e 00 00 00 ff ff 81 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 02 50 0c 00 14 00
3c 00 08 00 1e 00 00 00 ff ff 82 00 4f 00 70 00
74 00 69 00 6f 00 6e 00 3a 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 02 50 0c 00 63 00
3c 00 08 00 46 00 00 00 ff ff 82 00 43 00 6f 00
6d 00 6d 00 61 00 6e 00 64 00 3a 00 00 00 00 00
'''),
270 : a2b('''
01 00 ff ff 00 00 00 00 00 00 00 00 48 04 00 44
02 00 00 00 00 00 23 01 1a 00 00 00 00 00 00 00
08 00 00 00 00 00 4d 00 53 00 20 00 53 00 68 00
65 00 6c 00 6c 00 20 00 44 00 6c 00 67 00 00 00
00 00 00 00 00 00 00 00 01 00 02 50 00 00 07 00
23 01 08 00 ff ff ff ff ff ff 82 00 53 00 74 00
61 00 74 00 69 00 63 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 02 40 00 00 12 00 23 01 08 00
5f 04 00 00 ff ff 82 00 73 00 74 00 63 00 33 00
32 00 00 00 00 00
'''),
}
File diff suppressed because it is too large Load Diff
Binary file not shown.
Binary file not shown.
-45
View File
@@ -1,45 +0,0 @@
# Copyright 2004-2015 Tom Rothamel <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# Checks for various abilities that might be taken away from us by
# redistributors.
init 1 python in ability:
from store import config
import store
import store.updater as updater
import os
EXECUTABLES = [ "renpy.exe", "renpy.app", "renpy.sh" ]
# can_distribute - True if we can distribute
for i in EXECUTABLES:
if not os.path.exists(os.path.join(config.renpy_base, i)):
can_distribute = False
else:
can_distribute = True
# can_update - True if we can update.
can_update = updater.can_update() or (store.UPDATE_SIMULATE is not None)
-49
View File
@@ -1,49 +0,0 @@
# Copyright 2004-2015 Tom Rothamel <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
screen about:
$ version = renpy.version()
frame:
style_group "l"
style "l_root"
window:
xfill True
has vbox xfill True
add "images/logo.png" xalign 0.5 yoffset -5
null height 15
text _("[version!q]") xalign 0.5 bold True
null height 20
textbutton _("View license") action interface.OpenLicense() xalign 0.5
textbutton _("Back") action Jump("front_page") style "l_left_button"
label about:
call screen about
-57
View File
@@ -1,57 +0,0 @@
# Copyright 2004-2015 Tom Rothamel <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
label add_file:
python hide:
import os
import codecs
filename = interface.input(_("FILENAME"), _("Enter the name of the script file to create."), filename="withslash", cancel=Jump("navigation"))
if "." in filename and not filename.endswith(".rpy"):
interface.error(_("The filename must have the .rpy extension."), label="navigation")
elif "." not in filename:
filename += ".rpy"
path = os.path.join(project.current.gamedir, filename)
dir = os.path.dirname(path)
if os.path.exists(path):
interface.error(_("The file already exists."), label="navigation")
contents = u"\uFEFF"
contents += _("# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n")
contents += "\n"
try:
os.makedirs(dir)
except:
pass
contents = u"\uFEFF"
contents += _("# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n")
with open(path, "wb") as f:
f.write(contents.encode("utf-8"))
jump navigation_refresh
-562
View File
@@ -1,562 +0,0 @@
# Copyright 2004-2015 Tom Rothamel <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
init python:
ANDROID_NO_RAPT = 0
ANDROID_NO_JDK = 1
ANDROID_NO_SDK = 2
ANDROID_NO_KEY = 3
ANDROID_NO_CONFIG = 4
ANDROID_OK = 5
NO_RAPT_TEXT = _("To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher.")
NO_JDK_TEXT = _("A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher.")
NO_SDK_TEXT = _("RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this.")
NO_KEY_TEXT = _("RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore.")
NO_CONFIG_TEXT = _("The current project has not been configured. Use \"Configure\" to configure it before building.")
OK_TEXT = _("Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device.")
PHONE_TEXT = _("Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button.")
TABLET_TEXT = _("Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button.")
OUYA_TEXT = _("Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button.")
INSTALL_SDK_TEXT = _("Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package.")
CONFIGURE_TEXT = _("Configures the package name, version, and other information about this project.")
PLAY_KEYS_TEXT = _("Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details.")
BUILD_TEXT = _("Builds the Android package.")
BUILD_AND_INSTALL_TEXT = _("Builds the Android package, and installs it on an Android device connected to your computer.")
BUILD_INSTALL_AND_LAUNCH_TEXT = _("Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device.")
CONNECT_TEXT = _("Connects to an Android device running ADB in TCP/IP mode.")
DISCONNECT_TEXT = _("Disconnects from an Android device running ADB in TCP/IP mode.")
LOGCAT_TEXT = _("Retrieves the log from the Android device and writes it to a file.")
import subprocess
import re
import os
import json
import glob
def find_rapt():
global RAPT_PATH
candidates = [ ]
RAPT_PATH = os.path.join(config.renpy_base, "rapt")
if os.path.isdir(RAPT_PATH) and check_hash_txt("rapt"):
import sys
sys.path.insert(0, os.path.join(RAPT_PATH, "buildlib"))
else:
RAPT_PATH = None
find_rapt()
import threading
if RAPT_PATH:
import rapt
import rapt.build
import rapt.configure
import rapt.install_sdk
import rapt.plat
import rapt.interface
rapt.plat.renpy = True
else:
rapt = None
def AndroidState():
"""
Determines the state of the android install, and returns it.
"""
if RAPT_PATH is None:
return ANDROID_NO_RAPT
if renpy.windows and not "JAVA_HOME" in os.environ:
return ANDROID_NO_JDK
if not os.path.exists(rapt.plat.path("android-sdk/extras/google/play_licensing")):
return ANDROID_NO_SDK
if not os.path.exists(rapt.plat.path("android.keystore")):
return ANDROID_NO_KEY
if not os.path.exists(rapt.plat.path("local.properties")):
return ANDROID_NO_KEY
if not os.path.exists(os.path.join(project.current.path, ".android.json")):
return ANDROID_NO_CONFIG
return ANDROID_OK
def AndroidStateText(state):
"""
Returns text corresponding to the state.
"""
if state == ANDROID_NO_RAPT:
return NO_RAPT_TEXT
if state == ANDROID_NO_JDK:
return NO_JDK_TEXT
if state == ANDROID_NO_SDK:
return NO_SDK_TEXT
if state == ANDROID_NO_KEY:
return NO_KEY_TEXT
if state == ANDROID_NO_CONFIG:
return NO_CONFIG_TEXT
if state == ANDROID_OK:
return OK_TEXT
def AndroidIfState(state, needed, action):
"""
If `state` is `needed` or better, `action` is returned. Otherwise,
returns None, disabling the button.
"""
if state >= needed:
return action
else:
return None
class AndroidBuild(Action):
"""
Activates an Android build process.
"""
def __init__(self, label):
self.label = label
def __call__(self):
renpy.jump(self.label)
def update_android_json(p, gui):
"""
Updates .android.json to include the google play information.
`p`
The project to update json for.
"""
p.update_dump(True, gui=gui)
build = p.dump["build"]
filename = os.path.join(p.path, ".android.json")
with open(filename, "r") as f:
android_json = json.load(f)
if "google_play_key" in build:
android_json["google_play_key"] = build["google_play_key"]
else:
android_json.pop("google_play_key", None)
if "google_play_salt" in build:
if len(build["google_play_salt"]) != 20:
raise Exception("build.google_play_salt must be exactly 20 bytes long.")
android_json["google_play_salt"] = ", ".join(str(i) for i in build["google_play_salt"])
else:
android_json.pop("google_play_salt", None)
with open(filename, "w") as f:
json.dump(android_json, f)
def android_build(command, p=None, gui=True, launch=False, destination=None, opendir=False):
"""
This actually builds the package.
"""
if p is None:
p = project.current
update_android_json(p, gui)
dist = p.temp_filename("android.dist")
if os.path.exists(dist):
shutil.rmtree(dist)
if gui:
reporter = distribute.GuiReporter()
rapt_interface = MobileInterface("android")
else:
reporter = distribute.TextReporter()
rapt_interface = rapt.interface.Interface()
distribute.Distributor(p,
reporter=reporter,
packages=[ 'android' ],
build_update=False,
noarchive=True,
packagedest=dist,
report_success=False,
)
def finished(files, destination=destination):
source_dir = rapt.plat.path("bin")
try:
destination_dir = destination
# Use default destination if not configured
if gui and destination is None:
build = p.dump['build']
destination = build["destination"]
if destination != "-dists":
parent = os.path.dirname(p.path)
destination_dir = os.path.join(parent, destination)
except:
destination_dir = None
dir_to_open = source_dir
if destination_dir is not None:
reporter.info(_("Copying Android files to distributions directory."))
try:
os.makedirs(destination_dir)
except:
pass
try:
for i in files:
shutil.copy(i, renpy.fsencode(destination_dir))
dir_to_open = destination_dir
except:
import traceback
traceback.print_exc()
pass
if opendir:
store.OpenDirectory(dir_to_open)()
with interface.nolinks():
rapt.build.build(rapt_interface, dist, command, launch=launch, finished=finished)
# The android support can stick unicode into os.environ. Fix that.
init 100 python:
for k, v in list(os.environ.items()):
if not isinstance(v, str):
os.environ[k] = renpy.fsencode(v)
screen android_process(interface):
zorder 100
default ft = FileTail(interface.filename)
text "[ft.text!q]":
size 14
color TEXT
font "Roboto-Light.ttf"
xpos 75
ypos 350
timer .1 action interface.check_process repeat True
timer .2 action ft.update repeat True
screen android:
default tt = Tooltip(None)
$ state = AndroidState()
frame:
style_group "l"
style "l_root"
window:
has vbox
label _("Android: [project.current.name!q]")
add HALF_SPACER
hbox:
# Left side.
frame:
style "l_indent"
xmaximum ONEHALF
xfill True
has vbox
add SEPARATOR2
frame:
style "l_indent"
has vbox
text _("Emulation:")
add HALF_SPACER
frame style "l_indent":
has hbox:
spacing 15
textbutton _("Phone"):
action LaunchEmulator("touch", "small phone touch android")
hovered tt.Action(PHONE_TEXT)
textbutton _("Tablet"):
action LaunchEmulator("touch", "medium tablet touch android")
hovered tt.Action(TABLET_TEXT)
textbutton _("Television"):
action LaunchEmulator("tv", "small tv android")
hovered tt.Action(OUYA_TEXT)
add SPACER
add SEPARATOR2
frame:
style "l_indent"
has vbox
text _("Build:")
add HALF_SPACER
frame style "l_indent":
has vbox
textbutton _("Install SDK & Create Keys"):
action AndroidIfState(state, ANDROID_NO_SDK, Jump("android_installsdk"))
hovered tt.Action(INSTALL_SDK_TEXT)
textbutton _("Configure"):
action AndroidIfState(state, ANDROID_NO_CONFIG, Jump("android_configure"))
hovered tt.Action(CONFIGURE_TEXT)
textbutton _("Build Package"):
action AndroidIfState(state, ANDROID_OK, AndroidBuild("android_build"))
hovered tt.Action(BUILD_TEXT)
textbutton _("Build & Install"):
action AndroidIfState(state, ANDROID_OK, AndroidBuild("android_build_and_install"))
hovered tt.Action(BUILD_AND_INSTALL_TEXT)
textbutton _("Build, Install & Launch"):
action AndroidIfState(state, ANDROID_OK, AndroidBuild("android_build_install_and_launch"))
hovered tt.Action(BUILD_INSTALL_AND_LAUNCH_TEXT)
add SPACER
add SEPARATOR2
frame:
style "l_indent"
has vbox
text _("Other:")
add HALF_SPACER
frame style "l_indent":
has vbox
textbutton _("Remote ADB Connect"):
action AndroidIfState(state, ANDROID_OK, Jump("android_connect"))
hovered tt.Action(CONNECT_TEXT)
textbutton _("Remote ADB Disconnect"):
action AndroidIfState(state, ANDROID_OK, Jump("android_disconnect"))
hovered tt.Action(DISCONNECT_TEXT)
textbutton _("Logcat"):
action AndroidIfState(state, ANDROID_NO_KEY, Jump("logcat"))
hovered tt.Action(LOGCAT_TEXT)
# Right side.
frame:
style "l_indent"
xmaximum ONEHALF
xfill True
has vbox
add SEPARATOR2
frame:
style "l_indent"
has vbox
add SPACER
if tt.value:
text tt.value
else:
text AndroidStateText(state)
textbutton _("Back") action Jump("front_page") style "l_left_button"
label android:
if RAPT_PATH is None:
$ interface.yesno(_("Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"), no=Jump("front_page"))
$ add_dlc("rapt", restart=True)
call screen android
label android_installsdk:
python:
with interface.nolinks():
rapt.install_sdk.install_sdk(MobileInterface("android"))
jump android
label android_configure:
python:
rapt.configure.configure(MobileInterface("android", edit=False), project.current.path)
jump android
label android_build:
$ android_build([ 'release' ], opendir=True)
jump android
label android_build_and_install:
$ android_build([ 'release', 'install' ])
jump android
label android_build_install_and_launch:
$ android_build([ 'release', 'install' ], launch=True)
jump android
label android_connect:
python hide:
if persistent.connect_address is not None:
address = persistent.connect_address
else:
address = ""
while True:
address = interface.input(
_("Remote ADB Address"),
_("Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."),
default=address,
cancel=Jump("android"),
)
address = address.strip()
try:
host, port = address.split(":")
except:
interface.error(_("Invalid remote ADB address"), _("The address must contain one exactly one ':'."), label=None)
continue
if " " in host:
interface.error(_("Invalid remote ADB address"), _("The host may not contain whitespace."), label=None)
continue
try:
int(port)
except:
interface.error(_("Invalid remote ADB address"), _("The port must be a number."), label=None)
continue
break
persistent.connect_address = address
rapt_interface = MobileInterface("android")
rapt.build.connect(rapt_interface, address)
jump android
label android_disconnect:
python hide:
rapt_interface = MobileInterface("android")
rapt.build.disconnect(rapt_interface)
jump android
label logcat:
python hide:
interface = MobileInterface("android", filename="logcat.txt")
interface.info(_("Retrieving logcat information from device."))
interface.call([ rapt.plat.adb, "logcat", "-d" ], cancel=True)
interface.open_editor()
jump android
init python:
def android_build_command():
ap = renpy.arguments.ArgumentParser()
ap.add_argument("android_project", help="The path to the project directory.")
ap.add_argument("ant_commands", help="Commands to pass to ant. (Try 'release' 'install'.)", nargs='+')
ap.add_argument("--launch", action="store_true", help="Launches the app after build and install compete.")
ap.add_argument("--destination", "--dest", default=None, action="store", help="The directory where the packaged files should be placed.")
args = ap.parse_args()
p = project.Project(args.android_project)
android_build(args.ant_commands, p=p, gui=False, launch=args.launch, destination=args.destination)
return False
renpy.arguments.register_command("android_build", android_build_command)
-85
View File
@@ -1,85 +0,0 @@
# Copyright 2004-2015 Tom Rothamel <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# Ren'Py archiver. This builds a Ren'Py archive file, and the
# associated index file. These files are really easy to
# reverse-engineer, but are probably better than nothing.
init python in archiver:
import sys
import random
import glob
from cPickle import dumps, HIGHEST_PROTOCOL
class Archive(object):
"""
Adds files from disk to a rpa archive.
"""
def __init__(self, filename):
# The archive file.
self.f = open(filename, "wb")
# The index to the file.
self.index = _dict()
# A fixed key minimizes difference between archive versions.
self.key = 0x42424242
padding = "RPA-3.0 XXXXXXXXXXXXXXXX XXXXXXXX\n"
self.f.write(padding)
def add(self, name, path):
"""
Adds a file to the archive.
"""
self.index[name] = _list()
with open(path, "rb") as df:
data = df.read()
dlen = len(data)
# Pad.
padding = "Made with Ren'Py."
self.f.write(padding)
offset = self.f.tell()
self.f.write(data)
self.index[name].append((offset ^ self.key, dlen ^ self.key, ""))
def close(self):
indexoff = self.f.tell()
self.f.write(dumps(self.index, HIGHEST_PROTOCOL).encode("zlib"))
self.f.seek(0)
self.f.write("RPA-3.0 %016x %08x\n" % (indexoff, self.key))
self.f.close()
-349
View File
@@ -1,349 +0,0 @@
# Copyright 2004-2015 Tom Rothamel <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# 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
import pefile # @UnresolvedImport
# 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): #@ReservedAssignment
return self.a[start:start+len].tostring()
def __init__(self, data):
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.
# The virtual address of the resource segment.
resource_virtual = 0
# This parses a data block out of the resources.
def parse_data(bf, offset):
bf.seek(offset)
data_offset = bf.u32()
data_len = bf.u32()
code_page = bf.u32()
bf.u32()
l = [ ]
bf.seek(data_offset - resource_virtual)
for _i in range(data_len):
l.append(chr(bf.u8()))
return (code_page, "".join(l))
# This parses a resource directory.
def parse_directory(bf, offset):
bf.seek(offset)
char = bf.u32() #@UnusedVariable
timedate = bf.u32() #@UnusedVariable
major = bf.u16() #@UnusedVariable
minor = bf.u16() #@UnusedVariable
n_named = bf.u16()
n_id = bf.u16()
entries = [ ]
for _i in range(n_named + n_id):
entries.append((bf.u32(), bf.u32()))
rv = { }
for name, value in entries:
if name & 0x80000000:
bf.seek((name & 0x7fffffff))
name = bf.name()
if value & 0x80000000:
value = parse_directory(bf, value & 0x7fffffff)
else:
value = parse_data(bf, 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(file(fn, "rb").read())
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 resource_virtual
pe = pefile.PE(oldexe)
for s in pe.sections:
if s.Name == ".rsrc\0\0\0":
rsrc_section = s
break
else:
raise Exception("Couldn't find resource section.")
base = rsrc_section.PointerToRawData
resource_virtual = rsrc_section.VirtualAddress
physize = rsrc_section.SizeOfRawData
virsize = rsrc_section.Misc_VirtualSize
f = file(oldexe, "rb")
f.seek(base)
data = f.read(physize)
f.close()
bf = BinFile(data)
resources = parse_directory(bf, 0)
# show_resources(resources, "")
resources.update(load_icon(icofn))
# show_resources(resources, "")
rsrc = Packer().pack(resources)
alignment = pe.OPTIONAL_HEADER.SectionAlignment
# print "Alignment is", alignment
if len(rsrc) % alignment:
pad = alignment - (len(rsrc) % alignment)
padding = "RENPYVNE" * (pad / 8 + 1)
padding = padding[:pad]
rsrc += padding
newsize = len(rsrc)
rsrc_section.Misc_VirtualSize += newsize - virsize
rsrc_section.Misc_PhysicalAddress += newsize - virsize
rsrc_section.Misc += newsize - virsize
rsrc_section.SizeOfRawData += newsize - physize
pe.OPTIONAL_HEADER.SizeOfInitializedData += newsize - physize
# Resource size.
pe.OPTIONAL_HEADER.DATA_DIRECTORY[2].Size += newsize - virsize
# Compute the total size of the image.
total_size = 0
for i in pe.sections:
sec_size = i.Misc_VirtualSize
sec_size = sec_size - (sec_size % alignment) + alignment
total_size += sec_size
pe.OPTIONAL_HEADER.SizeOfImage = total_size
return pe.write()[:base] + rsrc
if __name__ == "__main__":
f = file(sys.argv[3], "wb")
f.write(change_icons(sys.argv[1], sys.argv[2]))
f.close()
-93
View File
@@ -1,93 +0,0 @@
# Copyright 2004-2015 Tom Rothamel <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
init python:
def choose_directory(path):
"""
Pops up a directory chooser.
`path`
The directory that is selected by default. If None, config.renpy_base
is selected.
Returns a (path, is_default) tuple, where path is the chosen directory,
and is_default is true if and only if it was chosen by default mechanism
rather than user choice.
"""
if path:
default_path = path
else:
try:
default_path = os.path.dirname(os.path.abspath(config.renpy_base))
except:
default_path = os.path.abspath(config.renpy_base)
if EasyDialogs:
choice = EasyDialogs.AskFolder(defaultLocation=default_path, wanted=unicode)
if choice is not None:
path = choice
else:
path = None
else:
try:
cmd = [ "/usr/bin/python", os.path.join(config.gamedir, "tkaskdir.py"), renpy.fsencode(default_path) ]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
choice = p.stdout.read()
code = p.wait()
except:
import traceback
traceback.print_exc()
code = 0
choice = ""
path = None
interface.error(_("Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."), label=None)
if code:
interface.error(_("Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."), label=None)
elif choice:
path = choice.decode("utf-8")
is_default = False
if path is None:
path = default_path
is_default = True
path = renpy.fsdecode(path)
if not os.path.isdir(path):
path = os.path.abspath(config.renpy_base)
is_default = True
return path, is_default
-515
View File
@@ -1,515 +0,0 @@
# Copyright 2004-2015 Tom Rothamel <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
init python:
import random
import codecs
import re
import sys
def theme_names():
"""
Gets a list of all of the theme names we know about.
"""
names = list(theme_data.THEME.keys())
names.sort(key=lambda a : a.lower())
return names
def scheme_names(theme):
"""
Gets a list of the color scheme names corresponding to the given
theme.
"""
names = list(theme_data.THEME[theme].keys())
names.sort(key=lambda a : a.lower())
return names
def theme_yinitial():
names = theme_names()
if len(names) < 2:
return 0
return 1.0 * names.index(current_theme) / (len(names) - 1)
def scheme_yinitial():
names = scheme_names(current_theme)
if len(names) < 2:
return 0
return 1.0 * names.index(current_scheme) / (len(names) - 1)
def pick_theme(theme, scheme):
"""
Returns a theme and scheme that are similar to `theme` and `scheme`.
If the theme is known, picks it, otherwise picks a random theme. If
the scheme is known for that theme, picks it, otherwise picks a
random scheme that is known for the current theme.
"""
if theme not in theme_data.THEME:
theme = random.choice(list(theme_data.THEME))
schemes = theme_data.THEME[theme]
if scheme not in schemes:
if theme in schemes:
scheme = theme
else:
scheme = random.choice(list(schemes))
return theme, scheme
def implement_theme(theme, scheme):
"""
Implement the current theme.
This function uses non-public APIs.
"""
global showing_theme, showing_scheme
if theme == showing_theme and scheme == showing_scheme:
return
renpy.style.restore(style_backup)
exec theme_data.THEME[theme][scheme] in globals()
# Rebuild the style cache.
renpy.style.rebuild(False)
# Bust the render cache, so we re-evaluate the styles.
renpy.display.interface.kill_textures()
showing_theme = theme
showing_scheme = scheme
renpy.restart_interaction()
showing_theme = None
showing_scheme = None
class SetTheme(Action):
def __init__(self, theme):
self.theme = theme
def __call__(self):
global current_theme
global current_scheme
current_theme, current_scheme = pick_theme(self.theme, current_scheme)
implement_theme(current_theme, current_scheme)
renpy.restart_interaction()
def get_selected(self):
return current_theme == self.theme
class SetScheme(Action):
def __init__(self, scheme):
self.scheme = scheme
def __call__(self):
global current_theme
global current_scheme
current_theme, current_scheme = pick_theme(current_theme, self.scheme)
implement_theme(current_theme, current_scheme)
renpy.restart_interaction()
def get_selected(self):
return current_scheme == self.scheme
class PreviewTheme(Action):
def __init__(self, theme, scheme):
self.theme = theme
self.scheme = scheme
def __call__(self):
theme, scheme = pick_theme(self.theme, self.scheme)
implement_theme(theme, scheme)
def unhovered(self):
if (showing_theme == self.theme and showing_scheme == self.scheme):
implement_theme(current_theme, current_scheme)
def value_changed(value):
return None
##########################################################################
# Code to update options.rpy
def list_logical_lines(filename):
"""
This reads in filename, and turns it into a list of logical
lines.
"""
f = codecs.open(filename, "rb", "utf-8")
data = f.read()
f.close()
# The result.
rv = [ ]
# The current position we're looking at in the buffer.
pos = 0
# Looping over the lines in the file.
while pos < len(data):
# The line that we're building up.
line = ""
# The number of open parenthesis there are right now.
parendepth = 0
# Looping over the characters in a single logical line.
while pos < len(data):
c = data[pos]
if c == '\n' and not parendepth:
rv.append(line)
pos += 1
# This helps out error checking.
line = ""
break
# Backslash/newline.
if c == "\\" and data[pos+1] == "\n":
pos += 2
line += "\\\n"
continue
# Parenthesis.
if c in ('(', '[', '{'):
parendepth += 1
if c in ('}', ']', ')') and parendepth:
parendepth -= 1
# Comments.
if c == '#':
while data[pos] != '\n':
line += data[pos]
pos += 1
continue
# Strings.
if c in ('"', "'", "`"):
delim = c
line += c
pos += 1
escape = False
while pos < len(data):
c = data[pos]
if escape:
escape = False
pos += 1
line += c
continue
if c == delim:
pos += 1
line += c
break
if c == '\\':
escape = True
line += c
pos += 1
continue
continue
line += c
pos += 1
if line:
rv.append(line)
return rv
def switch_theme():
"""
Switches the theme of the current project to the current theme
and color scheme. (As set in current_theme and current_scheme.)
"""
theme_code = theme_data.THEME[current_theme][current_scheme]
# Did we change the file at all?
changed = False
filename = os.path.join(project.current.path, "game/options.rpy")
with codecs.open(filename + ".new", "wb", "utf-8") as out:
for l in list_logical_lines(filename):
m = re.match(r' theme.(\w+)\(', l)
if (not changed) and m and (m.group(1) in theme_data.THEME_FUNCTIONS):
l = " " + theme_code
changed = True
out.write(l + "\n")
if changed:
try:
os.unlink(filename + ".bak")
except:
pass
os.rename(filename, filename + ".bak")
os.rename(filename + ".new", filename)
else:
os.unlink(filename + ".new")
interface.error(_("Could not change the theme. Perhaps options.rpy was changed too much."))
# Now give the theme's screen-ops function a chance to make any
# necessary changes to the screens.rpy file
filename = os.path.join(project.current.path, "game/screens.rpy")
changed = False
try:
with codecs.open(filename + ".new", "wb", "utf-8") as out:
lines = list_logical_lines(filename)
lines = theme_data.THEME_SCREEN_OPERATIONS[current_theme](lines)
if lines != None:
for l in lines:
out.write(l + "\n")
changed = True
if changed:
try:
os.unlink(filename + ".bak")
except:
pass
os.rename(filename, filename + ".bak")
os.rename(filename + ".new", filename)
except Exception as inst:
try:
# just in case
os.unlink(filename + ".new")
except:
pass
pass
def make_style_backup():
"""
Call this to back up the styles. This should be called in a
translate python block in each translation.
"""
global style_backup
style_backup = renpy.style.backup()
translate None python:
make_style_backup()
screen theme_demo:
window:
style "gm_root"
xpadding 5
ypadding 5
grid 1 1:
xfill True
style_group "prefs"
vbox:
frame:
style_group "pref"
has vbox
label _("Display")
textbutton _("Window") action SelectedIf(True)
textbutton _("Fullscreen") action ui.returns(None)
textbutton _("Planetarium") action None
frame:
style_group "pref"
has vbox
label _("Sound Volume")
bar style "slider" value .75 range 1.0 changed value_changed
textbutton "Test":
action ui.returns(None)
style "soundtest_button"
init -2 python:
style.pref_frame.xfill = True
style.pref_frame.xmargin = 5
style.pref_frame.top_margin = 5
style.pref_vbox.xfill = True
style.pref_button.size_group = "pref"
style.pref_button.xalign = 1.0
style.pref_slider.xmaximum = 192
style.pref_slider.xalign = 1.0
style.soundtest_button.xalign = 1.0
screen choose_theme:
default scheme_yadjustment = ui.adjustment()
default theme_yadjustment = ui.adjustment()
default first = True
python:
if first:
theme_yinitial_value = theme_yinitial()
scheme_yinitial_value = scheme_yinitial()
else:
theme_yinitial_value = None
scheme_yinitial_value = None
first = False
frame:
style_group "l"
style "l_root"
window:
has vbox
label _("Choose Theme")
hbox:
yfill True
# Theme selector.
frame:
style "l_indent"
bottom_margin HALF_SPACER_HEIGHT
xmaximum 225
has vbox
label _("Theme") style "l_label_small"
viewport:
scrollbars "vertical"
mousewheel True
yadjustment theme_yadjustment
yinitial theme_yinitial_value
has vbox
for i in theme_names():
textbutton "[i]":
action SetTheme(i)
hovered PreviewTheme(i, current_scheme)
style "l_list2"
# Color scheme selector.
frame:
style "l_indent"
bottom_margin HALF_SPACER_HEIGHT
xmaximum 225
has vbox
label _("Color Scheme") style "l_label_small"
viewport:
scrollbars "vertical"
mousewheel True
yadjustment scheme_yadjustment
yinitial scheme_yinitial_value
has vbox
for i in scheme_names(current_theme):
textbutton "[i]":
action SetScheme(i)
hovered PreviewTheme(current_theme, i)
style "l_list2"
# Preview
frame:
style "l_default"
background Frame(PATTERN, 0, 0, tile=True)
xpadding 5
ypadding 5
xfill True
yfill True
xmargin 20
bottom_margin 6
use theme_demo
textbutton _("Back") action Jump("front_page") style "l_left_button"
textbutton _("Continue") action Return(True) style "l_right_button"
label choose_theme_callable:
python:
current_theme, current_scheme = pick_theme(None, None)
implement_theme(current_theme, current_scheme)
call screen choose_theme
python hide:
with interface.error_handling("changing the theme"):
switch_theme()
return
label choose_theme:
call choose_theme_callable
jump front_page
File diff suppressed because it is too large Load Diff
-292
View File
@@ -1,292 +0,0 @@
# Copyright 2004-2015 Tom Rothamel <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
init python:
class PackageToggle(Action):
def __init__(self, name):
self.name = name
def get_selected(self):
return self.name in project.current.data['packages']
def __call__(self):
packages = project.current.data['packages']
if self.name in packages:
packages.remove(self.name)
else:
packages.append(self.name)
project.current.save_data()
renpy.restart_interaction()
class DataToggle(Action):
def __init__(self, field):
self.field = field
def get_selected(self):
return project.current.data[self.field]
def __call__(self):
project.current.data[self.field] = not project.current.data[self.field]
project.current.save_data()
renpy.restart_interaction()
DEFAULT_BUILD_INFO = """
## This section contains information about how to build your project into
## distribution files.
init python:
## The name that's used for directories and archive files. For example, if
## this is 'mygame-1.0', the windows distribution will be in the
## directory 'mygame-1.0-win', in the 'mygame-1.0-win.zip' file.
build.directory_name = "PROJECTNAME-1.0"
## The name that's uses for executables - the program that users will run
## to start the game. For example, if this is 'mygame', then on Windows,
## users can click 'mygame.exe' to start the game.
build.executable_name = "PROJECTNAME"
## If True, Ren'Py will include update information into packages. This
## allows the updater to run.
build.include_update = False
## File patterns:
##
## The following functions take file patterns. File patterns are case-
## insensitive, and matched against the path relative to the base
## directory, with and without a leading /. If multiple patterns match,
## the first is used.
##
##
## In a pattern:
##
## /
## Is the directory separator.
## *
## Matches all characters, except the directory separator.
## **
## Matches all characters, including the directory separator.
##
## For example:
##
## *.txt
## Matches txt files in the base directory.
## game/**.ogg
## Matches ogg files in the game directory or any of its subdirectories.
## **.psd
## Matches psd files anywhere in the project.
## Classify files as None to exclude them from the built distributions.
build.classify('**~', None)
build.classify('**.bak', None)
build.classify('**/.**', None)
build.classify('**/#**', None)
build.classify('**/thumbs.db', None)
## To archive files, classify them as 'archive'.
# build.classify('game/**.png', 'archive')
# build.classify('game/**.jpg', 'archive')
## Files matching documentation patterns are duplicated in a mac app
## build, so they appear in both the app and the zip file.
build.documentation('*.html')
build.documentation('*.txt')
"""
# A screen that displays a file or directory name, and
# lets the user change it,
#
# title
# The title of the link.
# value
# The value of the field.
screen distribute_name:
add SEPARATOR2
frame:
style "l_indent"
has vbox
text title
add HALF_SPACER
frame:
style "l_indent"
text "[value!q]"
add SPACER
screen build_distributions:
frame:
style_group "l"
style "l_root"
window:
has vbox
label _("Build Distributions: [project.current.name!q]")
add HALF_SPACER
hbox:
# Left side.
frame:
style "l_indent"
xmaximum ONEHALF
xfill True
has vbox
use distribute_name(
title=_("Directory Name:"),
value=project.current.dump["build"]["directory_name"])
use distribute_name(
title=_("Executable Name:"),
value=project.current.dump["build"]["executable_name"])
add SEPARATOR2
frame:
style "l_indent"
has vbox
text _("Actions:")
add HALF_SPACER
frame style "l_indent":
has vbox
textbutton _("Edit options.rpy") action editor.Edit("game/options.rpy", check=True)
textbutton _("Add from clauses to calls, once") action Jump("add_from")
textbutton _("Refresh") action Jump("build_distributions")
# Right side.
frame:
style "l_indent"
xmaximum ONEHALF
xfill True
has vbox
add SEPARATOR2
frame:
style "l_indent"
has vbox
text _("Build Packages:")
add HALF_SPACER
$ packages = project.current.dump["build"]["packages"]
for pkg in packages:
if not pkg["hidden"]:
$ description = pkg["description"]
textbutton "[description!q]" action PackageToggle(pkg["name"]) style "l_checkbox"
add SPACER
add HALF_SPACER
add SEPARATOR2
frame:
style "l_indent"
has vbox
text _("Options:")
add HALF_SPACER
if project.current.dump["build"]["include_update"]:
textbutton _("Build Updates") action DataToggle("build_update") style "l_checkbox"
textbutton _("Add from clauses to calls") action DataToggle("add_from") style "l_checkbox"
textbutton _("Force Recompile") action DataToggle("force_recompile") style "l_checkbox"
textbutton _("Back") action Jump("front_page") style "l_left_button"
textbutton _("Build") action Jump("start_distribute") style "l_right_button"
label add_from_common:
python:
interface.processing(_("Adding from clauses to call statements that do not have them."))
project.current.launch([ "add_from" ], wait=True)
return
label add_from:
call add_from_common
jump build_distributions
label start_distribute:
if project.current.data["add_from"]:
call add_from_common
jump distribute
label build_update_dump:
python:
project.current.update_dump(True)
if project.current.dump.get("error", False):
interface.error(_("Errors were detected when running the project. Please ensure the project runs without errors before building distributions."))
return
label build_distributions:
call build_update_dump
if not project.current.dump["build"]["directory_name"]:
jump build_missing
call screen build_distributions
label build_missing:
python hide:
interface.yesno(_("Your project does not contain build information. Would you like to add build information to the end of options.rpy?"), yes=Return(True), no=Jump("front_page"))
build_info = DEFAULT_BUILD_INFO.replace("PROJECTNAME", project.current.name)
with open(os.path.join(project.current.path, "game", "options.rpy"), "a") as f:
f.write(build_info)
jump build_distributions
-150
View File
@@ -1,150 +0,0 @@
# Copyright 2004-2015 Tom Rothamel <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
init python:
import urllib2
import os
import threading
import time
class Downloader(object):
def __init__(self, url, dest):
"""
Downloads `url` to `dest`, providing progress reports
as necessary.
"""
self.url = url
# The destination file, and the destination temp file.
self.dest = dest
self.tmp = dest + ".tmp"
# Open the tmpfile.
self.safe_unlink(self.tmp)
self.tmpfile = open(self.tmp, "wb")
# Set by the thread to indicate progress (ranges from 0.0 to 1.0).
self.progress = 0.0
# This is set to true by cancel() to indicate the download should be cancelled.
self.cancelled = False
# Set on succes or failure.
self.success = False
self.failure = None
try:
# Open the URL.
self.urlfile = urllib2.urlopen(url)
t = threading.Thread(target=self.thread)
t.daemon = True
t.start()
except Exception as e:
self.failure = str(e)
def thread(self):
try:
count = 0
if "content-length" in self.urlfile.headers:
length = int(self.urlfile.headers["content-length"])
else:
length = 0
while not self.cancelled:
data = self.urlfile.read(65536)
if not data:
break
count += len(data)
self.tmpfile.write(data)
if length > 0:
self.progress = 1.0 * count / length
self.tmpfile.close()
if self.cancelled:
return
if length and count != length:
self.failure = "Download length does not match content length."
return
self.safe_unlink(self.dest)
os.rename(self.tmp, self.dest)
self.success = True
except Exception as e:
self.failure = str(e)
def safe_unlink(self, fn):
if os.path.exists(fn):
os.unlink(fn)
def cancel(self):
"""
Cancels the download.
"""
self.cancelled = True
def check(self):
"""
Returns True if the download is finished, False if it was cancelled,
None if it's ongoing, and raises an Exception if the download has failed.
"""
if self.success:
return True
if self.cancelled:
return False
if self.failure:
raise Exception("Downloading {} to {} failed: {}".format(self.url, self.dest, self.failure))
return None
class DownloaderValue(BarValue):
"""
A BarValue that reports the progress of a background download.
"""
def __init__(self, d):
self.downloader = d
def get_adjustment(self):
self.adjustment = ui.adjustment(value=0.0, range=1.0, adjustable=False)
return self.adjustment
def periodic(self, st):
self.adjustment.change(self.downloader.progress)
return .25
-498
View File
@@ -1,498 +0,0 @@
# Copyright 2004-2015 Tom Rothamel <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# Editor Support.
#
# This contains code for scanning for editors, and for allowing the user to
# select an editor.
init 1 python in editor:
from store import Action, renpy, config, persistent
import store.project as project
import store.updater as updater
import store.interface as interface
import store.util as util
import store
import glob
import re
import traceback
import os
import os.path
# Should we set up the editor?
set_editor = "RENPY_EDIT_PY" not in os.environ
# A map from editor name to EditorInfo object.
editors = { }
class EditorInfo(object):
def __init__(self, filename):
# The path to the editor info file.
self.filename = filename
# The name of the editor.
self.name = os.path.basename(filename)[:-len(".edit.py")]
# The time the editor file was last modified. We use this
# to decide if we should update the editors mat when we
# have multiple versions of an editor in contention.
self.mtime = os.path.getmtime(filename)
def scan_editor(filename):
"""
Inserts an editor into editors if there isn't a newer
editor there already.
"""
ei = EditorInfo(filename)
if ei.name in editors:
if editors[ei.name].mtime >= ei.mtime:
return
editors[ei.name] = ei
def scan_all():
"""
Finds all *.edit.py files, and uses them to populate the list
of editors.
"""
editors.clear()
for d in [ config.renpy_base, persistent.projects_directory ]:
if d is None:
continue
if not os.path.isdir(d):
continue
for i in util.listdir(d):
i = os.path.join(d, i)
if not os.path.isdir(d):
continue
for j in util.listdir(i):
j = os.path.join(i, j)
if j.endswith(".edit.py"):
scan_editor(j)
########################################################################
# A list of fancy_editor_info objects.
fancy_editors = [ ]
# The error message to display if an editor failed to start.
error_message = None
class FancyEditorInfo(object):
"""
Represents an editor in the selection screen. A FEI knows if the
editor is installed or not.
"""
def __init__(self, priority, name, description=None, dlc=None, dldescription=None, error_message=None):
# The priority of the editor. Lower priorities will come later
# in the list.
self.priority = priority
# The name of the editor.
self.name = name
# Is the editor installed?
self.installed = name in editors
# The dlc needed to install the editor.
self.dlc = dlc
# A description of the editor.
self.description = description
# A description of the download.
self.dldescription = dldescription
# An error message to display if the editor failed to start.
self.error_message = error_message
def fancy_scan_editors():
"""
Creates the list of FancyEditorInfo objects.
"""
global fancy_editors
scan_all()
fei = fancy_editors = [ ]
# Editra.
ED = _("{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input.")
EDL = _("{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython.")
if renpy.windows:
dlc = "editra-windows"
installed = os.path.exists(os.path.join(config.basedir, "editra/Editra-win32"))
description = ED
error_message = None
elif renpy.macintosh:
dlc = "editra-mac"
installed = os.path.exists(os.path.join(config.basedir, "editra/Editra-mac.app"))
description = ED
error_message = None
else:
dlc = "editra-linux"
installed = os.path.exists(os.path.join(config.basedir, "editra/Editra"))
description = EDL
error_message = _("This may have occured because wxPython is not installed on this system.")
e = FancyEditorInfo(
1,
"Editra",
description,
dlc,
_("Up to 22 MB download required."),
error_message)
e.installed = e.installed or installed
fei.append(e)
# jEdit
fei.append(FancyEditorInfo(
2,
"jEdit",
_("A mature editor that requires Java."),
"jedit",
_("1.8 MB download required."),
_("This may have occured because Java is not installed on this system."),
))
fei.append(FancyEditorInfo(
3,
"System Editor",
_("Invokes the editor your operating system has associated with .rpy files."),
None))
for k in editors:
if k in [ "Editra", "jEdit", "System Editor", "None" ]:
continue
fei.append(FancyEditorInfo(
4,
k,
None,
None))
fei.append(FancyEditorInfo(
5,
"None",
_("Prevents Ren'Py from opening a text editor."),
None))
fei.sort(key=lambda e : (e.priority, e.name.lower()))
# If we're in a linux distro or something, assume all editors work.
if not updater.can_update():
for i in fei:
i.installed = True
def fancy_activate_editor(default=False):
"""
Activates the editor in persistent.editor, if it's installed.
`default`
"""
global error_message
fancy_scan_editors()
if default and not set_editor:
renpy.editor.init()
return
for i in fancy_editors:
if i.name == persistent.editor:
if i.installed and i.name in editors:
ei = editors[i.name]
os.environ["RENPY_EDIT_PY"] = renpy.fsencode(os.path.abspath(ei.filename))
error_message = i.error_message
break
else:
persistent.editor = None
os.environ.pop("RENPY_EDIT_PY", None)
renpy.editor.init()
def fancy_select_editor(name):
"""
Selects the editor with the given name, installing it if it
doesn't already exist.
"""
for fe in fancy_editors:
if fe.name == name:
break
else:
return
if not fe.installed:
# We don't check the status of this because fancy_activate_editor
# will fail if the editor is not installed.
store.add_dlc(fe.dlc)
persistent.editor = fe.name
fancy_activate_editor()
return persistent.editor is not None
# Call fancy_activate_editor on startup.
fancy_activate_editor(True)
class SelectEditor(Action):
def __init__(self, name):
self.name = name
def get_selected(self):
return persistent.editor == self.name
def __call__(self):
return fancy_select_editor(self.name)
def check_editor():
"""
Checks to see if an editor is set. If one isn't asks the user to
select one.
Returns True if the editor is set and editing can proceed, and
False otherwise.
"""
if not set_editor:
return True
if persistent.editor and persistent.editor != "None":
return True
return renpy.invoke_in_new_context(renpy.call_screen, "editor")
##########################################################################
# Editing actions.
class Edit(Action):
alt = "Edit [text]."
def __init__(self, filename, line=None, check=False):
"""
An action that opens the given line of the given file in a
text editor.
`filename`
The filename to open.
`line`
The line in the file to jump to.
`check`
If true, we will check to see if the file exists, and gray
out the box if it does not.
"""
self.filename = filename
self.line = line
self.check = check
def get_sensitive(self):
if not self.check:
return True
fn = project.current.unelide_filename(self.filename)
return os.path.exists(fn)
def __call__(self):
if not self.get_sensitive():
return
if not check_editor():
return
fn = project.current.unelide_filename(self.filename)
try:
e = renpy.editor.editor
e.begin()
e.open(fn, line=self.line)
e.end()
except Exception, e:
exception = traceback.format_exception_only(type(e), e)[-1][:-1]
renpy.invoke_in_new_context(interface.error, _("An exception occured while launching the text editor:\n[exception!q]"), error_message, exception=exception)
class EditAbsolute(Action):
def __init__(self, filename, line=None, check=False):
"""
An action that lets us edit an absolutely-specified filename.
`filename`
The filename to open.
`line`
The line in the file to jump to.
`check`
If true, we will check to see if the file exists, and gray
out the box if it does not.
"""
self.filename = filename
self.line = line
self.check = check
def get_sensitive(self):
if not self.check:
return True
return os.path.exists(self.filename)
def __call__(self):
if not self.get_sensitive():
return
if not check_editor():
return
try:
e = renpy.editor.editor
e.begin()
e.open(self.filename, line=self.line)
e.end()
except Exception, e:
exception = traceback.format_exception_only(type(e), e)[-1][:-1]
renpy.invoke_in_new_context(interface.error, _("An exception occured while launching the text editor:\n[exception!q]"), error_message, exception=exception)
class EditAll(Action):
"""
Opens all scripts that are part of the current project in a web browser.
"""
alt = "Edit [text]."
def __init__(self):
return
def __call__(self):
if not check_editor():
return
scripts = project.current.script_files()
scripts = [ i for i in scripts if not i.startswith("game/tl/") ]
scripts.sort(key=lambda fn : fn.lower())
for fn in [ "game/screens.rpy", "game/options.rpy", "game/script.rpy" ]:
if fn in scripts:
scripts.remove(fn)
scripts.insert(0, fn)
try:
e = renpy.editor.editor
e.begin()
for fn in scripts:
fn = project.current.unelide_filename(fn)
e.open(fn)
e.end()
except Exception, e:
exception = traceback.format_exception_only(type(e), e)[-1][:-1]
renpy.invoke_in_new_context(interface.error, _("An exception occured while launching the text editor:\n[exception!q]"), error_message, exception=exception)
screen editor:
frame:
style_group "l"
style "l_root"
window:
has vbox
label _("Select Editor")
add HALF_SPACER
hbox:
frame:
style "l_indent"
xfill True
viewport:
scrollbars "vertical"
mousewheel True
has vbox
text _("A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed.") style "l_small_text"
for fe in editor.fancy_editors:
add SPACER
textbutton fe.name action editor.SelectEditor(fe.name)
add HALF_SPACER
frame:
style "l_indent"
has vbox
if fe.description:
text fe.description style "l_small_text"
if not fe.installed:
add HALF_SPACER
text fe.dldescription style "l_small_text"
textbutton _("Cancel") action Return(False) style "l_left_button"
label editor_preference:
call screen editor
jump preferences
-291
View File
@@ -1,291 +0,0 @@
# Copyright 2004-2015 Tom Rothamel <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
define PROJECT_ADJUSTMENT = ui.adjustment()
init python:
import os
import subprocess
class OpenDirectory(Action):
"""
Opens `directory` in a file browser. `directory` is relative to
the project root.
"""
alt = _("Open [text] directory.")
def __init__(self, directory, absolute=False):
if absolute:
self.directory = directory
else:
self.directory = os.path.join(project.current.path, directory)
def get_sensitive(self):
return os.path.exists(self.directory)
def __call__(self):
try:
directory = renpy.fsencode(self.directory)
if renpy.windows:
os.startfile(directory)
elif renpy.macintosh:
subprocess.Popen([ "open", directory ])
else:
subprocess.Popen([ "xdg-open", directory ])
except:
pass
# Used for testing.
def Relaunch():
renpy.quit(relaunch=True)
screen front_page:
frame:
alt ""
style_group "l"
style "l_root"
has hbox
# Projects list section - on left.
frame:
style "l_projects"
xmaximum 300
right_margin 2
top_padding 20
bottom_padding 26
side "t c b":
window style "l_label":
has hbox:
xfill True
text "PROJECTS:" style "l_label_text" size 36 yoffset 10
textbutton _("refresh"):
xalign 1.0
yalign 1.0
yoffset 5
style "l_small_button"
action project.Rescan()
right_margin HALF_INDENT
side "c r":
viewport:
yadjustment PROJECT_ADJUSTMENT
mousewheel True
use front_page_project_list
vbar:
style "l_vscrollbar"
adjustment PROJECT_ADJUSTMENT
vbox:
add HALF_SPACER
add SEPARATOR
add HALF_SPACER
hbox:
xfill True
textbutton _("+ Create New Project"):
left_margin (HALF_INDENT)
action Jump("new_project")
# Project section - on right.
if project.current is not None:
use front_page_project
if project.current is not None:
textbutton _("Launch Project") action project.Launch() style "l_right_button"
key "K_F5" action project.Launch()
# This is used by front_page to display the list of known projects on the screen.
screen front_page_project_list:
$ projects = project.manager.projects
$ templates = project.manager.templates
vbox:
if templates and persistent.show_templates:
for p in templates:
textbutton _("[p.name!q] (template)"):
action project.Select(p)
alt _("Select project [text].")
style "l_list"
null height 12
if projects:
for p in projects:
textbutton "[p.name!q]":
action project.Select(p)
alt _("Select project [text].")
style "l_list"
null height 12
textbutton _("Tutorial") action project.Select("tutorial") style "l_list" alt _("Select project [text].")
textbutton _("The Question") action project.Select("the_question") style "l_list" alt _("Select project [text].")
# This is used for the right side of the screen, which is where the project-specific
# buttons are.
screen front_page_project:
$ p = project.current
window:
has vbox
frame style "l_label":
has hbox xfill True
text "[p.name!q]" style "l_label_text"
label _("Active Project") style "l_alternate"
grid 2 1:
xfill True
spacing HALF_INDENT
vbox:
label _("Open Directory") style "l_label_small"
frame style "l_indent":
has vbox
textbutton _("game") action OpenDirectory("game")
textbutton _("base") action OpenDirectory(".")
textbutton _("images") action OpenDirectory("game/images")
# textbutton _("save") action None style "l_list"
vbox:
if persistent.show_edit_funcs:
label _("Edit File") style "l_label_small"
frame style "l_indent":
has vbox
textbutton "script.rpy" action editor.Edit("game/script.rpy", check=True)
textbutton "options.rpy" action editor.Edit("game/options.rpy", check=True)
textbutton "screens.rpy" action editor.Edit("game/screens.rpy", check=True)
textbutton _("All script files") action editor.EditAll()
add SPACER
add SEPARATOR
add SPACER
frame style "l_indent":
has vbox
textbutton _("Navigate Script") text_size 30 action Jump("navigation")
add SPACER
grid 2 1:
xfill True
spacing HALF_INDENT
frame style "l_indent":
has vbox
textbutton _("Check Script (Lint)") action Jump("lint")
textbutton _("Change Theme") action Jump("choose_theme")
textbutton _("Delete Persistent") action Jump("rmpersistent")
textbutton _("Force Recompile") action Jump("force_recompile")
# textbutton "Relaunch" action Relaunch
frame style "l_indent":
has vbox
if ability.can_distribute:
textbutton _("Build Distributions") action Jump("build_distributions")
textbutton _("Android") action Jump("android")
textbutton _("iOS") action Jump("ios")
textbutton _("Generate Translations") action Jump("translate")
textbutton _("Extract Dialogue") action Jump("extract_dialogue")
label main_menu:
return
label start:
show screen bottom_info
label front_page:
call screen front_page
jump front_page
label lint:
python hide:
interface.processing(_("Checking script for potential problems..."))
lint_fn = project.current.temp_filename("lint.txt")
project.current.launch([ 'lint', lint_fn ], wait=True)
e = renpy.editor.editor
e.begin(True)
e.open(lint_fn)
e.end()
jump front_page
label rmpersistent:
python hide:
interface.processing(_("Deleting persistent data..."))
project.current.launch([ 'rmpersistent' ], wait=True)
jump front_page
label force_recompile:
python hide:
interface.processing(_("Recompiling all rpy files into rpyc files..."))
project.current.launch([ 'compile' ], wait=True)
jump front_page
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 687 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

-482
View File
@@ -1,482 +0,0 @@
# Copyright 2004-2015 Tom Rothamel <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
################################################################################
# Interface actions.
init python in interface:
from store import OpenURL, config, Return
import store
import os.path
import contextlib
RENPY_URL = "http://www.renpy.org"
RENPY_GAMES_URL = "http://games.renpy.org"
DOC_PATH = os.path.join(config.renpy_base, "doc/index.html")
DOC_URL = "http://www.renpy.org/doc/html/"
LICENSE_PATH = os.path.join(config.renpy_base, "doc/license.html")
LICENSE_URL = "http://www.renpy.org/doc/html/license.html"
if os.path.exists(DOC_PATH):
DOC_LOCAL_URL = "file:///" + DOC_PATH
else:
DOC_LOCAL_URL = None
if os.path.exists(LICENSE_PATH):
LICENSE_LOCAL_URL = "file:///" + LICENSE_PATH
else:
LICENSE_LOCAL_URL = None
def OpenDocumentation():
"""
An action that opens the documentation.
"""
if DOC_LOCAL_URL is not None:
return OpenURL(DOC_LOCAL_URL)
else:
return OpenURL(DOC_URL)
def OpenLicense():
"""
An action that opens the license.
"""
if LICENSE_LOCAL_URL is not None:
return OpenURL(LICENSE_LOCAL_URL)
else:
return OpenURL(LICENSE_URL)
# Should we display the bottom links?
links = True
@contextlib.contextmanager
def nolinks():
global links
links = False
try:
yield
finally:
links = True
# This displays the bottom of the screen. If the tooltip is not None, this displays the
# tooltip. Otherwise, it displays a list of links (to various websites, and to the
# preferences and update screen), or is just blank.
screen bottom_info:
zorder 100
if interface.links:
frame:
style_group "l"
style "l_default"
left_margin (10 + INDENT)
right_margin (10 + INDENT)
xfill True
ypos 536
yanchor 0.0
hbox:
xfill True
hbox:
spacing INDENT
textbutton _("Documentation") style "l_link" action interface.OpenDocumentation()
textbutton _("Ren'Py Website") style "l_link" action OpenURL(interface.RENPY_URL)
textbutton _("Ren'Py Games List") style "l_link" action OpenURL(interface.RENPY_GAMES_URL)
textbutton _("About") style "l_link" action Jump("about")
hbox:
spacing INDENT
xalign 1.0
if ability.can_update:
textbutton _("update") action Jump("update") style "l_link"
textbutton _("preferences") style "l_link" action Jump("preferences")
textbutton _("quit") style "l_link" action Quit(confirm=False)
screen common:
default complete = None
default total = None
default yes = None
default no = None
default choices = None
default cancel = None
default bar_value = None
frame:
style "l_root"
frame:
style_group "l_info"
has vbox
text message:
text_align 0.5
xalign 0.5
layout "subtitle"
if complete is not None:
add SPACER
frame:
style "l_progress_frame"
bar:
range total
value complete
style "l_progress_bar"
if bar_value is not None:
add SPACER
frame:
style "l_progress_frame"
bar:
value bar_value
style "l_progress_bar"
if choices:
add SPACER
for v, l in choices:
textbutton l action SetScreenVariable("selected", v)
if selected is not None:
$ continue_ = Return(selected)
else:
$ continue_ = None
if submessage:
add SPACER
text submessage:
text_align 0.5
xalign 0.5
layout "subtitle"
if yes:
add SPACER
hbox:
xalign 0.5
textbutton _("Yes") style "l_button" action yes
null width 160
textbutton _("No") style "l_button" action no
label title text_color title_color style "l_info_label"
if back:
textbutton _("Back") action back style "l_left_button"
elif cancel:
textbutton _("Cancel") action cancel style "l_left_button"
if continue_:
textbutton _("Continue") action continue_ style "l_right_button"
key "input_enter" action continue_
screen launcher_input:
frame:
style "l_root"
frame:
style_group "l_info"
has vbox
text message:
text_align 0.5
xalign 0.5
layout "subtitle"
add SPACER
input style "l_default" size 24 xalign 0.5 default default color INPUT_COLOR
if filename:
add SPACER
text _("Due to package format limitations, non-ASCII file and directory names are not allowed.")
label title style "l_info_label" text_color QUESTION_COLOR
if cancel:
textbutton _("Cancel") action cancel style "l_left_button"
init python in interface:
import traceback
from store import Jump
def common(title, title_color, message, submessage=None, back=None, continue_=None, pause0=False, show_screen=False, **kwargs):
"""
Displays the info, interaction, and processing screens.
`title`
The title of the screen.
`message`
The main message that is displayed when the screen is.
`submessage`
If not None, a message that is displayed below the main message.
`back`
If not None, a back button will be present. `back` is the action that
is called when the button is clicked.
`cancel`
If not None, a cancel button will be present. `cancel` is the action
that is called when the button is clicked.
`continue_`
If True, a continue button will be present. `continue_` gives the action
that is called when that button is clicked.
`pause0`
If True, a zero-length pause will be inserted before calling the
screen. This will display it to the user and then immediately
return.
`show_screen`
If True, the screen will be show, and will return immediately. if False,
the screen will be called, and interaction will pause.
Other keyword arguments are passed to the screen itself.
"""
if show_screen:
screen_func = renpy.show_screen
else:
screen_func = renpy.call_screen
if pause0:
ui.pausebehavior(0)
return screen_func("common", title=title, title_color=title_color, message=message, submessage=submessage, back=back, continue_=continue_, **kwargs)
def hide_screen():
"""
Hides a screen that was shown with show_screen=True.
"""
renpy.hide_screen("common")
def error(message, submessage=None, label="front_page", **kwargs):
"""
Indicates to the user that an error has occured.
`message`
The message to display.
`submessage`
Optional secondary message information. For example, this may be
used to display an exception string.
`label`
The label to redirect to when the user finishes displaying the error. None
to just return False.
Keyword arguments are passed into the screen so that they can be substituted into
the message.
"""
if label is None:
action = Return(False)
else:
action = Jump(label)
common(_("ERROR"), store.ERROR_COLOR, message=message, submessage=submessage, back=action, **kwargs)
@contextlib.contextmanager
def error_handling(what, label="front_page"):
"""
This is a context manager that catches exceptions and displays them using
interface.error.
`what`
What we're doing when the error occurs. This is usually written using
the present participle.
`label`
The label to jump to when error handling finishes.
As an example of usage::
with interface.error_handling("opening the log file"):
f = open("log.txt", "w")
"""
try:
yield
except Exception, e:
import traceback
traceback.print_exc()
error(_("While [what!q], an error occured:"),
_("[exception!q]"),
what=what,
label=label,
exception=traceback.format_exception_only(type(e), e)[-1][:-1])
def input(title, message, filename=False, sanitize=True, cancel=None, default=""):
"""
Requests typewritten input from the user.
"""
rv = default
while True:
rv = renpy.call_screen("launcher_input", title=title, message=message, filename=filename, cancel=cancel, default=rv)
if sanitize:
if ("[" in rv) or ("{" in rv):
error(_("Text input may not contain the {{ or [[ characters."), label=None)
continue
if filename:
if filename and (filename != "withslash") and (("\\" in rv) or ("/" in rv)):
error(_("File and directory names may not contain / or \\."), label=None)
continue
try:
rv.encode("ascii")
except:
error(_("File and directory names must consist of ASCII characters."), label=None)
continue
return rv
def info(message, submessage=None, pause=True, **kwargs):
"""
Displays an informational message to the user. The user will be asked to click to
confirm that he has read the message.
`message`
The message to display.
`pause`
True if we should pause while showing the info.
Keyword arguments are passed into the screen so that they can be substituted into
the message.
"""
if pause:
common(_("INFORMATION"), store.INFO_COLOR, message, submessage, continue_=Return(True), **kwargs)
else:
common(_("INFORMATION"), store.INFO_COLOR, message, submessage, pause0=True, **kwargs)
def interaction(title, message, submessage=None, pause=0, **kwargs):
"""
Put up on the screen while an interaction with an external program occurs.
This shows the message, then immediately returns.
`title`
The title of the interaction.
`message`
The message itself.
`submessage`
An optional sub message.
`pause`
The amount of time to pause for after showing the message.
"""
common(title, store.INTERACTION_COLOR, message, submessage=None, pause=pause, show_screen=True, **kwargs)
renpy.pause(pause)
def processing(message, submessage=None, complete=None, total=None, **kwargs):
"""
Indicates to the user that processing is taking place. This should be used when
there is an indefinite amount of work to be done.
`message`
The message to display.
`submessage`
An additional message to display.
`complete`
The fraction complete the step is.
`total`
The total amount of work to do in this step.
Keyword arguments are passed into the screen so that they can be substituted into
the message.
"""
common(_("PROCESSING"), store.INTERACTION_COLOR, message, submessage, pause0=True, complete=complete, total=total, **kwargs)
def yesno(message, yes=Return(True), no=Return(False), **kwargs):
"""
Asks the user a yes or no question.
`message`
The question to ask.
`yes`
The action to perform if the user answers yes.
`no`
The action to perform if the user answer no.
"""
return common(_("QUESTION"), store.QUESTION_COLOR, message, yes=yes, no=no, **kwargs)
def choice(message, choices, selected, **kwargs):
"""
Asks the user to pick a choice from a menu.
`choices`
A list of (value, label) tuples, giving the choices.
`selected`
The default choice that we mark as selected.
"""
return common(_("CHOICE"), store.QUESTION_COLOR, message, choices=choices, selected=selected, **kwargs)
-374
View File
@@ -1,374 +0,0 @@
# Copyright 2004-2015 Tom Rothamel <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
init python:
IOS_NO_RENIOS = 0
IOS_NO_DIRECTORY = 1
IOS_NO_PROJECT = 2
IOS_OK = 3
IOS_NO_RENIOS_TEXT = _("To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher.")
IOS_NO_DIRECTORY_TEXT = _("The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it.")
IOS_NO_PROJECT_TEXT = _("There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one.")
IOS_OK_TEXT = _("An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it.")
IPHONE_TEXT = _("Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down.")
IPAD_TEXT = _("Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down.")
IOS_SELECT_DIRECTORY_TEXT = _("Selects the directory where Xcode projects will be placed.")
IOS_CREATE_PROJECT_TEXT = _("Creates an Xcode project corresponding to the current Ren'Py project.")
IOS_UPDATE_PROJECT_TEXT = _("Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes.")
IOS_XCODE_TEXT = _("Opens the Xcode project in Xcode.")
IOS_OPEN_DIRECTORY_TEXT = _("Opens the directory containing Xcode projects.")
def find_renios():
global RENIOS_PATH
candidates = [ ]
RENIOS_PATH = os.path.join(config.renpy_base, "renios")
if os.path.isdir(RENIOS_PATH) and check_hash_txt("renios"):
import sys
sys.path.insert(0, os.path.join(RENIOS_PATH, "buildlib"))
else:
RENIOS_PATH = None
find_renios()
if RENIOS_PATH:
import renios.create
def IOSState():
if not RENIOS_PATH:
return IOS_NO_RENIOS
elif not persistent.xcode_projects_directory:
return IOS_NO_DIRECTORY
elif not os.path.exists(xcode_project()):
return IOS_NO_PROJECT
else:
return IOS_OK
def IOSStateText(state):
if state == IOS_NO_RENIOS:
return IOS_NO_RENIOS_TEXT
elif state == IOS_NO_DIRECTORY:
return IOS_NO_DIRECTORY_TEXT
elif state == IOS_NO_PROJECT:
return IOS_NO_PROJECT_TEXT
else:
return IOS_OK_TEXT
def IOSIfState(state, needed, action):
"""
If `state` is `needed` or better, `action` is returned. Otherwise,
returns None, disabling the button.
"""
if state >= needed:
return action
else:
return None
xcode_name_cache = { }
def xcode_name(s):
"""
Returns a version of `s` that's safe to use in Xcode.
"""
if s in xcode_name_cache:
return xcode_name_cache[s]
s = re.sub(r'[^\w\-\.]', '', s)
xcode_name_cache[s] = s
return s
def xcode_project(p=None):
"""
Return the path to the Xcode project corresponding to `p`, or the current
project if `p` is None
"""
if p is None:
p = project.current
if persistent.xcode_projects_directory is None:
raise Exception("The Xcode projects directory has not been set.")
return os.path.join(persistent.xcode_projects_directory, xcode_name(p.name))
def ios_create(p=None, gui=True):
dest = xcode_project(p)
if os.path.exists(dest):
interface.yesno(_("The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"), no=Jump("ios"))
i = 0
while True:
i += 1
backup = dest + "." + str(i)
if not os.path.exists(backup):
break
os.rename(dest, backup)
iface = MobileInterface("ios")
renios.create.create_project(iface, dest)
ios_populate(p, gui=gui)
def ios_populate(p=None, gui=True):
"""
This actually builds the package.
"""
import shutil
if p is None:
p = project.current
dist = os.path.join(xcode_project(p), "base")
if os.path.exists(dist):
shutil.rmtree(dist)
if gui:
reporter = distribute.GuiReporter()
else:
reporter = distribute.TextReporter()
distribute.Distributor(p,
reporter=reporter,
packages=[ 'ios' ],
build_update=False,
noarchive=True,
packagedest=dist,
report_success=False,
)
main_fn = os.path.join(dist, "main.py")
for fn in os.listdir(dist):
if fn.endswith(".py"):
py_fn = os.path.join(dist, fn)
break
else:
raise Exception("Could not find a .py file.")
with open(py_fn, "r") as py_f:
with open(main_fn, "w") as main_f:
for l in py_f:
if l.startswith("#!"):
continue
main_f.write(l)
os.unlink(py_fn)
def launch_xcode():
dist = xcode_project(None)
base = os.path.basename(dist)
xcodeproj = "{}/{}.xcodeproj".format(dist, base)
subprocess.call([ 'open', renpy.fsencode(xcodeproj) ])
screen ios:
default tt = Tooltip(None)
$ state = IOSState()
frame:
style_group "l"
style "l_root"
window:
has vbox
label _("iOS: [project.current.name!q]")
add HALF_SPACER
hbox:
# Left side.
frame:
style "l_indent"
xmaximum ONEHALF
xfill True
has vbox
add SEPARATOR2
frame:
style "l_indent"
has vbox
text _("Emulation:")
add HALF_SPACER
frame style "l_indent":
has hbox:
spacing 15
textbutton _("iPhone"):
action LaunchEmulator("ios-touch", "small phone touch ios")
hovered tt.Action(IPHONE_TEXT)
textbutton _("iPad"):
action LaunchEmulator("ios-touch", "medium tablet touch ios")
hovered tt.Action(IPAD_TEXT)
add SPACER
add SEPARATOR2
frame:
style "l_indent"
has vbox
text _("Build:")
add HALF_SPACER
frame style "l_indent":
has vbox
textbutton _("Select Xcode Projects Directory"):
action IOSIfState(state, IOS_NO_DIRECTORY, Jump("select_xcode_projects_directory"))
hovered tt.Action(IOS_SELECT_DIRECTORY_TEXT)
textbutton _("Create Xcode Project"):
action IOSIfState(state, IOS_NO_PROJECT, Jump("create_xcode_project"))
hovered tt.Action(IOS_CREATE_PROJECT_TEXT)
textbutton _("Update Xcode Project"):
action IOSIfState(state, IOS_NO_PROJECT, Jump("update_xcode_project"))
hovered tt.Action(IOS_UPDATE_PROJECT_TEXT)
if renpy.macintosh:
textbutton _("Launch Xcode"):
action IOSIfState(state, IOS_OK, launch_xcode)
hovered tt.Action(IOS_XCODE_TEXT)
# textbutton _("Configure"):
# action AndroidIfState(state, ANDROID_NO_CONFIG, Jump("android_configure"))
# hovered tt.Action(CONFIGURE_TEXT)
#
# textbutton _("Build Package"):
# action AndroidIfState(state, ANDROID_OK, AndroidBuild("android_build"))
# hovered tt.Action(BUILD_TEXT)
#
# textbutton _("Build & Install"):
# action AndroidIfState(state, ANDROID_OK, AndroidBuild("android_build_and_install"))
# hovered tt.Action(BUILD_AND_INSTALL_TEXT)
#
# textbutton _("Build, Install & Launch"):
# action AndroidIfState(state, ANDROID_OK, AndroidBuild("android_build_install_and_launch"))
# hovered tt.Action(BUILD_INSTALL_AND_LAUNCH_TEXT)
add SPACER
add SEPARATOR2
frame:
style "l_indent"
has vbox
text _("Other:")
add HALF_SPACER
frame style "l_indent":
has vbox
textbutton _("Open Xcode Projects Directory"):
action IOSIfState(state, IOS_NO_PROJECT, OpenDirectory(persistent.xcode_projects_directory, absolute=True))
hovered tt.Action(IOS_OPEN_DIRECTORY_TEXT)
# Right side.
frame:
style "l_indent"
xmaximum ONEHALF
xfill True
has vbox
add SEPARATOR2
frame:
style "l_indent"
has vbox
add SPACER
if tt.value:
text tt.value
else:
text IOSStateText(state)
textbutton _("Back") action Jump("front_page") style "l_left_button"
label ios:
if RENIOS_PATH is None:
$ interface.yesno(_("Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"), no=Jump("front_page"))
$ add_dlc("renios", restart=True)
call screen ios
label select_xcode_projects_directory:
python hide:
interface.interaction(_("XCODE PROJECTS DIRECTORY"), _("Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"))
path, is_default = choose_directory(persistent.xcode_projects_directory)
if is_default:
interface.info(_("Ren'Py has set the Xcode Projects Directory to:"), "[path!q]", path=path)
persistent.xcode_projects_directory = path
jump ios
label create_xcode_project:
$ ios_create(None, True)
jump ios
label update_xcode_project:
$ ios_populate(None, True)
jump ios
-258
View File
@@ -1,258 +0,0 @@
# Copyright 2004-2015 Tom Rothamel <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# This file contains mobile build things that are shared by the android
# and iOS builds.
init -1 python:
def check_hash_txt(module):
fn1 = module + "_hash.txt"
fn2 = renpy.fsencode(os.path.join(config.renpy_base, module, "hash.txt"))
# No hash file? We're in dev mode - ignore.
if not renpy.loadable(fn1):
return True
hash1 = renpy.file(fn1).read()
if not os.path.exists(fn2):
return False
hash2 = open(fn2).read()
return hash1.strip() == hash2.strip()
class LaunchEmulator(Action):
def __init__(self, emulator, variants):
self.emulator = emulator
self.variants = variants
def __call__(self):
env = {
"RENPY_EMULATOR" : self.emulator,
"RENPY_VARIANT" : self.variants,
}
p = project.current
p.launch(env=env)
class MobileInterface(object):
"""
This is used to interface between the launcher and RAPT/RENIOS.
"""
def __init__(self, platform, edit=True, filename=None):
"""
`platform`
The name of the platform we're using for. Used for libraries,
cancel labels, and logfiles.
`edit`
If true, we launch the log file in the editor on failure.
"""
self.platform = platform
self.edit = edit
self.process = None
if filename is None:
filename = platform + ".txt"
self.filename = project.current.temp_filename(filename)
self.info_msg = ""
with open(self.filename, "w"):
pass
def log(self, msg):
with open(self.filename, "a") as f:
f.write("\n")
f.write(msg)
f.write("\n")
def info(self, prompt):
self.info_msg = prompt
interface.processing(prompt, pause=False)
self.log(prompt)
def yesno(self, prompt, submessage=None):
return interface.yesno(prompt, submessage=submessage)
def yesno_choice(self, prompt, default=None):
choices = [ (True, "Yes"), (False, "No") ]
return interface.choice(prompt, choices, default)
def terms(self, url, prompt):
submessage = _("{a=%s}%s{/a}") % (url, url)
if not interface.yesno(prompt, submessage=submessage):
self.fail("You must accept the terms and conditions to proceed.", edit=False)
def input(self, prompt, empty=None):
if empty is None:
empty = ''
while True:
rv = interface.input(_("QUESTION"), prompt, default=empty, cancel=Jump("android"))
rv = rv.strip()
if rv:
return rv
def choice(self, prompt, choices, default):
return interface.choice(prompt, choices, default, cancel=Jump("android"))
def fail(self, prompt, edit=True):
self.log(prompt)
prompt = re.sub(r'(http://\S+)', r'{a=\1}\1{/a}', prompt)
# Open android.txt in the editor.
if edit and self.edit:
self.open_editor()
interface.error(prompt, label="android")
def open_editor(self):
editor.EditAbsolute(self.filename)()
def success(self, prompt):
self.log(prompt)
interface.info(prompt, pause=False)
def final_success(self, prompt):
self.log(prompt)
interface.info(prompt, label="android")
def run_yes_thread(self):
import time
try:
while self.run_yes:
self.process.stdin.write('y\n')
self.process.stdin.flush()
time.sleep(.2)
except:
import traceback
traceback.print_exc()
def call(self, cmd, cancel=False, use_path=False, yes=False):
cmd = [ renpy.fsencode(i) for i in cmd ]
self.cmd = cmd
f = open(self.filename, "a")
f.write("\n\n\n")
if cancel:
cancel_action = self.cancel
else:
cancel_action = None
startupinfo = None
if renpy.windows:
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
self.yes_thread = None
try:
interface.processing(self.info_msg, show_screen=True, cancel=cancel_action)
kwargs = { }
if yes:
kwargs["stdin"] = subprocess.PIPE
try:
self.process = subprocess.Popen(cmd, cwd=renpy.fsencode(RAPT_PATH), stdout=f, stderr=f, startupinfo=startupinfo, **kwargs)
except:
import traceback
traceback.print_exc(file=f)
raise
if yes:
import threading
self.run_yes = True
self.yes_thread = threading.Thread(target=self.run_yes_thread)
self.yes_thread.daemon = True
self.yes_thread.start()
renpy.call_screen("android_process", interface=self)
finally:
f.close()
interface.hide_screen()
if yes and self.yes_thread:
self.run_yes = False
self.yes_thread.join()
self.process = None
self.yes_thread = None
def check_process(self):
rv = self.process.poll()
if rv is not None:
if rv:
raise subprocess.CalledProcessError(rv, self.cmd)
else:
return True
def download(self, url, dest):
try:
d = Downloader(url, dest)
cancel_action = [ d.cancel, Jump(self.platform) ]
interface.processing(self.info_msg, show_screen=True, cancel=cancel_action, bar_value=DownloaderValue(d))
ui.timer(.1, action=d.check, repeat=True)
ui.interact()
finally:
interface.hide_screen()
def background(self, f):
try:
t = threading.Thread(target=f)
t.start()
interface.processing(self.info_msg, show_screen=True)
while t.is_alive():
renpy.pause(0)
t.join(0.25)
finally:
interface.hide_screen()
def cancel(self):
if self.process:
self.process.terminate()
renpy.jump(self.platform)
-280
View File
@@ -1,280 +0,0 @@
# Copyright 2004-2015 Tom Rothamel <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
init python in navigation:
import store.interface as interface
import store.project as project
import store.editor as editor
from store import persistent, Action
# The last navigation screen we've seen. This is the scree we try to go
# to the next time we enter navigation. (We may not be able to go there,
# if the screen is empty.)
if persistent.navigation is None:
persistent.navigation = "label"
# A map from a kind of information, to how we should sort it. Possible
# sorts are alphabetical, by-file, natural.
if persistent.navigation_sort is None:
persistent.navigation_sort = { }
if persistent.navigate_private is None:
persistent.navigate_private = False
if persistent.navigate_library is None:
persistent.navigate_library = False
# A list of kinds of navigation we support.
KINDS = [ "file", "label", "define", "transform", "screen", "callable", "todo" ]
# A map from kind name to adjustment.
adjustments = { }
for i in KINDS:
persistent.navigation_sort.setdefault(i, "by-file")
adjustments[i] = ui.adjustment()
def group_and_sort(kind):
"""
This is responsible for pulling navigation information of the
appropriate kind out of project.current.dump, grouping it,
and sorting it.
This returns a list of (group, list of (name, filename, line)). The
group may be a string or None.
"""
project.current.update_dump()
sort = persistent.navigation_sort[kind]
name_map = project.current.dump.get("location", {}).get(kind, { })
groups = { }
for name, loc in name_map.items():
filename, line = loc
filename = filename.replace("\\", "/")
if sort == "alphabetical":
group = None
else:
group = filename
if group.startswith("game/"):
group = group[5:]
g = groups.get(group, None)
if g is None:
groups[group] = g = [ ]
g.append((name, filename, line))
for g in groups.values():
if sort == "natural":
g.sort(key=lambda a : a[2])
else:
g.sort(key=lambda a : a[0].lower())
rv = list(groups.items())
rv.sort()
return rv
def group_and_sort_files():
rv = [ ]
for fn in project.current.script_files():
shortfn = fn
shortfn = shortfn.replace("\\", "/")
if shortfn.startswith("game/"):
shortfn = fn[5:]
rv.append((shortfn, fn, None))
rv.sort()
return [ (None, rv) ]
class ChangeKind(Action):
"""
Changes the kind of thing we're navigating over.
"""
def __init__(self, kind):
self.kind = kind
def get_selected(self):
return persistent.navigation == self.kind
def __call__(self):
if persistent.navigation == self.kind:
return
persistent.navigation = self.kind
renpy.jump("navigation_loop")
class ChangeSort(Action):
"""
Changes the sort order.
"""
def __init__(self, sort):
self.sort = sort
def get_selected(self):
return persistent.navigation_sort[persistent.navigation] == self.sort
def __call__(self):
if self.get_selected():
return
persistent.navigation_sort[persistent.navigation] = self.sort
renpy.jump("navigation_loop")
screen navigation:
frame:
style_group "l"
style "l_root"
window:
has vbox
frame style "l_label":
has hbox xfill True
text _("Navigate: [project.current.name]") style "l_label_text"
frame:
style "l_alternate"
style_group "l_small"
has hbox
if persistent.navigation != "file":
text _("Order: ")
textbutton _("alphabetical") action navigation.ChangeSort("alphabetical")
text " | "
textbutton _("by-file") action navigation.ChangeSort("by-file")
text " | "
textbutton _("natural") action navigation.ChangeSort("natural")
null width HALF_INDENT
textbutton _("refresh") action Jump("navigation_refresh")
add HALF_SPACER
frame style "l_indent":
hbox:
spacing HALF_INDENT
text _("Category:")
textbutton _("files") action navigation.ChangeKind("file")
textbutton _("labels") action navigation.ChangeKind("label")
textbutton _("defines") action navigation.ChangeKind("define")
textbutton _("transforms") action navigation.ChangeKind("transform")
textbutton _("screens") action navigation.ChangeKind("screen")
textbutton _("callables") action navigation.ChangeKind("callable")
textbutton _("TODOs") action navigation.ChangeKind("todo")
add SPACER
add SEPARATOR
frame style "l_indent_margin":
if groups:
viewport:
mousewheel True
scrollbars "vertical"
yadjustment navigation.adjustments[persistent.navigation]
vbox:
style_group "l_navigation"
for group_name, group in groups:
if group_name is not None:
text "[group_name!q]"
if persistent.navigation == "todo":
vbox:
for name, filename, line in group:
textbutton "[name!q]" action editor.Edit(filename, line)
else:
hbox:
box_wrap True
for name, filename, line in group:
textbutton "[name!q]" action editor.Edit(filename, line)
if group_name is not None:
add SPACER
if persistent.navigation == "file":
add SPACER
textbutton _("+ Add script file") action Jump("add_file") style "l_button"
else:
fixed:
if persistent.navigation == "todo":
text _("No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."):
text_align 0.5
xalign 0.5
yalign 0.5
else:
text _("The list of names is empty."):
xalign 0.5
yalign 0.5
textbutton _("Back") action Jump("front_page") style "l_left_button"
textbutton _("Launch Project") action project.Launch() style "l_right_button"
label navigation:
label navigation_loop:
python in navigation:
kind = persistent.navigation
if kind == "file":
groups = group_and_sort_files()
else:
groups = group_and_sort(kind)
renpy.call_screen("navigation", groups=groups)
label navigation_refresh:
$ project.current.update_dump(True)
jump navigation_loop
-128
View File
@@ -1,128 +0,0 @@
# Copyright 2004-2015 Tom Rothamel <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
init python:
import shutil
import os
import time
import re
screen select_template:
default result = project.manager.get("english")
frame:
style_group "l"
style "l_root"
window:
has vbox
label _("Choose Project Template")
hbox:
frame:
style "l_indent"
xmaximum ONETHIRD
viewport:
scrollbars "vertical"
vbox:
for p in project.manager.templates:
textbutton "[p.name!q]" action SetScreenVariable("result", p) style "l_list"
frame:
style "l_indent"
xmaximum TWOTHIRDS
text _("Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'.")
textbutton _("Back") action Jump("front_page") style "l_left_button"
textbutton _("Continue") action Return(result) style "l_right_button"
label new_project:
if persistent.projects_directory is None:
call choose_projects_directory
if persistent.projects_directory is None:
$ interface.error(_("The projects directory could not be set. Giving up."))
python hide:
project_name = interface.input(
_("PROJECT NAME"),
_("Please enter the name of your project:"),
filename=True,
cancel=Jump("front_page"))
project_name = project_name.strip()
if not project_name:
interface.error(_("The project name may not be empty."))
project_dir = os.path.join(persistent.projects_directory, project_name)
if project.manager.get(project_name) is not None:
interface.error(_("[project_name!q] already exists. Please choose a different project name."), project_name=project_name)
if os.path.exists(project_dir):
interface.error(_("[project_dir!q] already exists. Please choose a different project name."), project_dir=project_dir)
if len(project.manager.templates) == 1:
template = project.manager.templates[0]
else:
template = renpy.call_screen("select_template")
template_path = template.path
with interface.error_handling("creating a new project"):
shutil.copytree(template_path, project_dir, symlinks=False)
# Delete the tmp directory, if it exists.
if os.path.isdir(os.path.join(project_dir, "tmp")):
shutil.rmtree(os.path.join(project_dir, "tmp"))
# Delete project.json, which must exist.
os.unlink(os.path.join(project_dir, "project.json"))
# Change the save directory in options.rpy
fn = os.path.join(project_dir, "game/options.rpy")
with open(fn, "rb") as f:
options = f.read().decode("utf-8")
options = options.replace("PROJECT_NAME", project_name)
options = options.replace("UNIQUE", str(int(time.time())))
with open(fn, "wb") as f:
f.write(options.encode("utf-8"))
# Activate the project.
with interface.error_handling("activating the new project"):
project.manager.scan()
project.Select(project.manager.get(project_name))()
call choose_theme_callable
jump front_page
-362
View File
@@ -1,362 +0,0 @@
# Copyright 2004-2015 Tom Rothamel <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
## This file contains some of the options that can be changed to customize
## your Ren'Py game. It only contains the most common options... there
## is quite a bit more customization you can do.
##
## Lines beginning with two '#' marks are comments, and you shouldn't
## uncomment them. Lines beginning with a single '#' mark are
## commented-out code, and you may want to uncomment them when
## appropriate.
init -1 python hide:
## Should we enable the use of developer tools? This should be
## set to False before the game is released, so the user can't
## cheat using developer tools.
config.developer = True
## These control the width and height of the screen.
config.screen_width = 800
config.screen_height = 600
## This controls the title of the window, when Ren'Py is
## running in a window.
config.window_title = u"Ren'Py Launcher"
# These control the name and version of the game, that are reported
# with tracebacks and other debugging logs.
config.name = "Ren'Py Launcher"
config.version = renpy.version().split()[1]
#########################################
# Themes
## We then want to call a theme function. themes.roundrect is
## a theme that features the use of rounded rectangles. It's
## the only theme we currently support.
##
## The theme function takes a number of parameters that can
## customize the color scheme.
theme.roundrect(
## Theme: Roundrect
## Color scheme: Basic Blue
## The color of an idle widget face.
widget = "#003c78",
## The color of a focused widget face.
widget_hover = "#0050a0",
## The color of the text in a widget.
widget_text = "#c8ffff",
## The color of the text in a selected widget. (For
## example, the current value of a preference.)
widget_selected = "#ffffc8",
## The color of a disabled widget face.
disabled = "#404040",
## The color of disabled widget text.
disabled_text = "#c8c8c8",
## The color of informational labels.
label = "#ffffff",
## The color of a frame containing widgets.
frame = "#6496c8",
## The background of the main menu. This can be a color
## beginning with '#', or an image filename. The latter
## should take up the full height and width of the screen.
mm_root = "#dcebff",
## The background of the game menu. This can be a color
## beginning with '#', or an image filename. The latter
## should take up the full height and width of the screen.
gm_root = "#dcebff",
## If this is True, the in-game window is rounded. If False,
## the in-game window is square.
rounded_window = False,
## And we're done with the theme. The theme will customize
## various styles, so if we want to change them, we should
## do so below.
)
#########################################
## Help.
## This lets you configure the help option on the Ren'Py menus.
## It may be:
## - A label in the script, in which case that label is called to
## show help to the user.
## - A file name relative to the base directory, which is opened in a
## web browser.
## - None, to disable help.
config.help = "README.html"
#########################################
## Transitions.
## Used when entering the game menu from the game.
config.enter_transition = None
## Used when exiting the game menu to the game.
config.exit_transition = None
## Used between screens of the game menu.
config.intra_transition = None
## Used when entering the game menu from the main menu.
config.main_game_transition = None
## Used when returning to the main menu from the game.
config.game_main_transition = None
## Used when entering the main menu from the splashscreen.
config.end_splash_transition = None
## Used when entering the main menu after the game has ended.
config.end_game_transition = None
## Used when a game is loaded.
config.after_load_transition = None
## Used when the window is shown.
config.window_show_transition = None
## Used when the window is hidden.
config.window_hide_transition = None
#########################################
## This is the name of the directory where the game's data is
## stored. (It needs to be set early, before any other init code
## is run, so the persistent information can be found by the init code.)
python early:
config.save_directory = "launcher-4"
init -1 python hide:
#########################################
## Default values of Preferences.
## Note: These options are only evaluated the first time a
## game is run. To have them run a second time, delete
## game/saves/persistent
## Should we start in fullscreen mode?
config.default_fullscreen = False
## The default text speed in characters per second. 0 is infinite.
config.default_text_cps = 0
#########################################
## More customizations can go here.
config.sound = False
config.quit_action = Quit(confirm=False)
config.gl_resize = False
config.window_icon = "images/logo.png"
config.windows_icon = "images/logo32.png"
config.has_autosave = False
config.log_enable = False
config.mouse_hide_time = 86400 * 366
_game_menu_screen = None
config.underlay = [
renpy.Keymap(
quit = renpy.quit_event,
iconify = renpy.iconify,
choose_renderer = renpy.curried_call_in_new_context("_choose_renderer"),
self_voicing = Preference("self voicing", "toggle"),
),
]
config.rollback_enabled = False
translate None python:
config.rtl = False
## This section controls how to build Ren'Py. (Building the launcher is how
## we build Ren'Py distributions.)
init python:
## We're building Ren'Py tonight.
build.renpy = True
## The version number that's supplied to the updater.
build.version = "Ren'Py {}".format(config.version)
## The name that's used for directories and archive files. For example, if
## this is 'mygame-1.0', the windows distribution will be in the
## directory 'mygame-1.0-win', in the 'mygame-1.0-win.zip' file.
if 'RENPY_BUILD_VERSION' in os.environ:
build.directory_name = "renpy-" + os.environ['RENPY_BUILD_VERSION']
else:
build.directory_name = "renpy-" + config.version.rsplit('.', 1)[0]
## The name that's uses for executables - the program that users will run
## to start the game. For example, if this is 'mygame', then on Windows,
## users can click 'mygame.exe' to start the game.
build.executable_name = "renpy"
## If True, Ren'Py will include update information into packages. This
## allows the updater to run.
build.include_update = True
## Allow empty directories, so we can distribute the images directory.
build.exclude_empty_directories = False
## Clear out various file patterns.
build.renpy_patterns = [ ]
build.early_base_patterns = [ ]
build.base_patterns = [ ]
build.late_base_patterns = [ ]
# We don't need to clear out the executable patterns, since they're
# correct for Ren'Py.
## Now, add the Ren'Py distribution in using classify_renpy.
build.classify_renpy("**~", None)
build.classify_renpy("**/#*", None)
build.classify_renpy("**/thumbs.db", None)
build.classify_renpy("**/.*", None)
build.classify_renpy("rapt/**", "rapt")
build.classify_renpy("renios/prototype/base/", None)
build.classify_renpy("renios/prototype/prototype.xcodeproj/*.xcworkspace/", None)
build.classify_renpy("renios/prototype/prototype.xcodeproj/xcuserdata/", None)
build.classify_renpy("renios/prototype/**", "renios")
build.classify_renpy("renios/buildlib/**", "renios")
build.classify_renpy("renios/ios.py", "renios")
build.classify_renpy("renios/version.txt", "renios")
build.classify_renpy("renios/", "renios")
build.classify_renpy("**.old", None)
build.classify_renpy("**.new", None)
build.classify_renpy("**.bak", None)
build.classify_renpy("**.pyc", None)
build.classify_renpy("**/log.txt", None)
build.classify_renpy("**/traceback.txt", None)
build.classify_renpy("**/errors.txt", None)
build.classify_renpy("**/saves/", None)
build.classify_renpy("**/tmp/", None)
build.classify_renpy("**/.Editra", None)
# main source.
def source_and_binary(pattern, source="source", binary="binary"):
"""
Classifies source and binary files beginning with `pattern`.
.pyo, .rpyc, .rpycm, and .rpyb go into binary, everything
else goes into source.
"""
build.classify_renpy(pattern + "/**.pyo", binary)
build.classify_renpy(pattern + "/**.rpyc", binary)
build.classify_renpy(pattern + "/**.rpymc", binary)
build.classify_renpy(pattern + "/**/cache/*", binary)
build.classify_renpy(pattern + "/**", source)
build.classify_renpy("renpy.py", "source")
source_and_binary("renpy")
# games.
build.classify_renpy("launcher/game/theme/", None)
source_and_binary("launcher")
source_and_binary("templates", binary=None)
source_and_binary("the_question")
source_and_binary("tutorial")
# docs.
build.classify_renpy("doc/", "source")
build.classify_renpy("doc/.doctrees/", None)
build.classify_renpy("doc/_sources/", None)
build.classify_renpy("doc/**", "source")
build.classify_renpy("LICENSE.txt", "source")
# module.
build.classify_renpy("module/", "source")
build.classify_renpy("module/*.c", "source")
build.classify_renpy("module/gen/", "source")
build.classify_renpy("module/gen/*.c", "source")
build.classify_renpy("module/*.h", "source")
build.classify_renpy("module/*.py*", "source")
build.classify_renpy("module/include/", "source")
build.classify_renpy("module/include/*.pxd", "source")
build.classify_renpy("module/include/*.pxi", "source")
build.classify_renpy("module/pysdlsound/", "source")
build.classify_renpy("module/pysdlsound/*.py", "source")
build.classify_renpy("module/pysdlsound/*.pyx", "source")
# all-platforms binary.
build.classify_renpy("lib/**/_renpysteam*", None)
build.classify_renpy("lib/**/*steam_api*", None)
build.classify_renpy("lib/*/renpy", None)
build.classify_renpy("lib/*/renpy.exe", None)
build.classify_renpy("lib/**", "binary")
build.classify_renpy("renpy.sh", "binary")
# renpy.app is now built from scratch from distribute.rpy.
# jedit rules.
build.classify_renpy("jedit/**", "jedit")
# editra rules.
build.classify_renpy("editra/", "editra-all")
build.classify_renpy("editra/Editra.edit.py", "editra-all")
build.classify_renpy("editra/Editra/**", "editra-linux editra-windows")
build.classify_renpy("editra/Editra-mac.app/**", "editra-mac")
build.classify_renpy("editra/lib/**", "editra-windows")
build.classify_renpy("editra/editra.exe", "editra-windows")
# Executable rules.
build.executable("editra/Editra/Editra")
# Packages.
build.packages = [ ]
build.package("sdk", "zip tar.bz2", "source binary")
build.package("source", "tar.bz2", "source", update=False)
build.package("jedit", "zip", "jedit", dlc=True)
build.package("editra-linux", "tar.bz2", "editra-all editra-linux", dlc=True)
build.package("editra-mac", "zip", "editra-all editra-mac", dlc=True)
build.package("editra-windows", "zip", "editra-all editra-windows", dlc=True)
build.package("rapt", "zip", "rapt", dlc=True)
build.package("renios", "zip", "renios", dlc=True)
-239
View File
@@ -1,239 +0,0 @@
# Copyright 2004-2015 Tom Rothamel <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
init python in distribute:
import time
import zipfile
import tarfile
import zlib
import struct
import stat
import shutil
from zipfile import crc32
zlib.Z_DEFAULT_COMPRESSION = 9
class ZipFile(zipfile.ZipFile):
def write_with_info(self, zinfo, filename):
"""Put the bytes from filename into the archive under the name
arcname."""
if not self.fp:
raise RuntimeError(
"Attempt to write to ZIP archive that was already closed")
st = os.stat(filename)
isdir = stat.S_ISDIR(st.st_mode)
zinfo.file_size = st.st_size
zinfo.flag_bits = 0x00
zinfo.header_offset = self.fp.tell() # Start of header bytes
self._writecheck(zinfo)
self._didModify = True
if isdir:
zinfo.file_size = 0
zinfo.compress_size = 0
zinfo.CRC = 0
self.filelist.append(zinfo)
self.NameToInfo[zinfo.filename] = zinfo
self.fp.write(zinfo.FileHeader())
return
with open(filename, "rb") as fp:
# Must overwrite CRC and sizes with correct data later
zinfo.CRC = CRC = 0
zinfo.compress_size = compress_size = 0
zinfo.file_size = file_size = 0
self.fp.write(zinfo.FileHeader())
if zinfo.compress_type == zipfile.ZIP_DEFLATED:
cmpr = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION,
zlib.DEFLATED, -15)
else:
cmpr = None
while 1:
buf = fp.read(1024 * 1024)
if not buf:
break
file_size = file_size + len(buf)
CRC = crc32(buf, CRC) & 0xffffffff
if cmpr:
buf = cmpr.compress(buf)
compress_size = compress_size + len(buf)
self.fp.write(buf)
if cmpr:
buf = cmpr.flush()
compress_size = compress_size + len(buf)
self.fp.write(buf)
zinfo.compress_size = compress_size
else:
zinfo.compress_size = file_size
zinfo.CRC = CRC
zinfo.file_size = file_size
# Seek backwards and write CRC and file sizes
position = self.fp.tell() # Preserve current position in file
self.fp.seek(zinfo.header_offset + 14, 0)
self.fp.write(struct.pack("<LLL", zinfo.CRC, zinfo.compress_size,
zinfo.file_size))
self.fp.seek(position, 0)
self.filelist.append(zinfo)
self.NameToInfo[zinfo.filename] = zinfo
class ZipPackage(object):
"""
A class that creates a zip file.
"""
def __init__(self, filename):
self.zipfile = ZipFile(filename, "w", zipfile.ZIP_DEFLATED, True)
def get_date_time(self, path):
"""
Gets the datetime for a file. If the time doesn't exist or is
weird, use the current time instead.
"""
try:
s = os.stat(path)
rv = time.gmtime(s.st_mtime)[:6]
# Check that the time is sensible.
if rv[0] < 2000:
rv = None
except:
rv = None
if rv is None:
rv = time.gmtime()[:6]
return rv
def add_file(self, name, path, xbit):
if path is None:
raise Exception("path for " + name + " must not be None.")
zi = zipfile.ZipInfo(name)
zi.date_time = self.get_date_time(path)
zi.compress_type = zipfile.ZIP_DEFLATED
zi.create_system = 3
if xbit:
zi.external_attr = long(0100755) << 16
else:
zi.external_attr = long(0100644) << 16
self.zipfile.write_with_info(zi, path)
def add_directory(self, name, path):
if path is None:
return
zi = zipfile.ZipInfo(name + "/")
zi.date_time = self.get_date_time(path)
zi.compress_type = zipfile.ZIP_STORED
zi.create_system = 3
zi.external_attr = (long(0040755) << 16) | 0x10
self.zipfile.write_with_info(zi, path)
def close(self):
self.zipfile.close()
class TarPackage(object):
def __init__(self, filename, mode, notime=False):
"""
notime
If true, times will be forced to the epoch.
"""
self.tarfile = tarfile.open(filename, mode)
self.tarfile.dereference = True
self.notime = notime
def add_file(self, name, path, xbit):
if path is not None:
info = self.tarfile.gettarinfo(path, name)
else:
info = tarfile.TarInfo(name)
info.size = 0
info.mtime = int(time.time())
info.type = tarfile.DIRTYPE
if xbit:
info.mode = 0755
else:
info.mode = 0644
info.uid = 1000
info.gid = 1000
info.uname = "renpy"
info.gname = "renpy"
if self.notime:
info.mtime = 0
if info.isreg():
with open(path, "rb") as f:
self.tarfile.addfile(info, f)
else:
self.tarfile.addfile(info)
def add_directory(self, name, path):
self.add_file(name, path, True)
def close(self):
self.tarfile.close()
class DirectoryPackage(object):
def mkdir(self, path):
if not os.path.isdir(path):
os.mkdir(path, 0755)
def __init__(self, path):
self.path = path
self.mkdir(path)
def add_file(self, name, path, xbit):
fn = os.path.join(self.path, name)
shutil.copy2(path, fn)
if xbit:
os.chmod(fn, 0755)
else:
os.chmod(fn, 0644)
def add_directory(self, name, path):
fn = os.path.join(self.path, name)
self.mkdir(fn)
def close(self):
return
File diff suppressed because it is too large Load Diff
-239
View File
@@ -1,239 +0,0 @@
# Copyright 2004-2015 Tom Rothamel <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
init python:
if persistent.gl_enable is None:
persistent.gl_enable = True
config.gl_enable = persistent.gl_enable
if persistent.show_edit_funcs is None:
persistent.show_edit_funcs = True
if persistent.windows_console is None:
persistent.windows_console = False
def scan_translations():
languages = renpy.known_languages()
if not languages:
return None
rv = [ ( "English", None) ]
for i in languages:
rv.append((i.replace("_", " ").title(), i))
rv.sort()
return rv
screen preferences:
$ translations = scan_translations()
frame:
style_group "l"
style "l_root"
alt "Preferences"
window:
has vbox
label _("Launcher Preferences")
add HALF_SPACER
hbox:
frame:
style "l_indent"
xmaximum ONETHIRD
xfill True
has vbox
# Projects directory selection.
add SEPARATOR2
frame:
style "l_indent"
yminimum 75
has vbox
text _("Projects Directory:")
add HALF_SPACER
frame style "l_indent":
if persistent.projects_directory:
textbutton _("[persistent.projects_directory!q]"):
action Jump("projects_directory_preference")
alt _("Projects directory: [text]")
else:
textbutton _("Not Set"):
action Jump("projects_directory_preference")
alt _("Projects directory: [text]")
add SPACER
# Text editor selection.
add SEPARATOR2
frame:
style "l_indent"
yminimum 75
has vbox
text _("Text Editor:")
add HALF_SPACER
frame style "l_indent":
if persistent.editor:
textbutton persistent.editor action Jump("editor_preference") alt _("Text editor: [text]")
else:
textbutton _("Not Set") action Jump("editor_preference") alt _("Text editor: [text]")
add SPACER
if ability.can_update:
# Update URL selection.
add SEPARATOR2
frame:
style "l_indent"
yminimum 75
has vbox
text _("Update Channel:")
add HALF_SPACER
frame style "l_indent":
textbutton persistent.update_channel action Jump("update_preference")
frame:
style "l_indent"
xmaximum ONETHIRD
xfill True
has vbox
add SEPARATOR2
frame:
style "l_indent"
yminimum 75
has vbox
text _("Navigation Options:")
add HALF_SPACER
textbutton _("Include private names") style "l_checkbox" action ToggleField(persistent, "navigate_private")
textbutton _("Include library names") style "l_checkbox" action ToggleField(persistent, "navigate_library")
add SPACER
add SEPARATOR2
frame:
style "l_indent"
yminimum 75
has vbox
text _("Launcher Options:")
add HALF_SPACER
textbutton _("Hardware rendering") style "l_checkbox" action ToggleField(persistent, "gl_enable")
textbutton _("Show templates") style "l_checkbox" action ToggleField(persistent, "show_templates")
textbutton _("Show edit file section") style "l_checkbox" action ToggleField(persistent, "show_edit_funcs")
textbutton _("Large fonts") style "l_checkbox" action [ ToggleField(persistent, "large_print"), renpy.utter_restart ]
textbutton _("Generate empty strings for translations") style "l_checkbox" action ToggleField(persistent, "generate_empty_strings")
if renpy.windows:
textbutton _("Console output") style "l_checkbox" action ToggleField(persistent, "windows_console")
frame:
style "l_indent"
xmaximum ONETHIRD
xfill True
has vbox
add SEPARATOR2
frame:
style "l_indent"
yminimum 75
has vbox
text _("Actions:")
add HALF_SPACER
textbutton _("Open launcher project") style "l_nonbox" action [ project.Select("launcher"), Jump("front_page") ]
if translations:
add SPACER
# Text editor selection.
add SEPARATOR2
frame:
style "l_indent"
yminimum 75
has vbox
text _("Language:")
add HALF_SPACER
viewport:
scrollbars "vertical"
mousewheel True
has vbox
# frame style "l_indent":
for tlname, tlvalue in translations:
textbutton tlname action Language(tlvalue) style "l_list"
textbutton _("Back") action Jump("front_page") style "l_left_button"
label projects_directory_preference:
call choose_projects_directory
jump preferences
label preferences:
call screen preferences
jump preferences
-595
View File
@@ -1,595 +0,0 @@
# Copyright 2004-2015 Tom Rothamel <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# Code that manages projects.
init python:
if renpy.windows:
import EasyDialogsWin as EasyDialogs
else:
EasyDialogs = None
import os
init python in project:
from store import persistent, config, Action, renpy
import store.util as util
import store.interface as interface
import sys
import os.path
import json
import subprocess
import re
import tempfile
if persistent.blurb is None:
persistent.blurb = 0
LAUNCH_BLURBS = [
_("After making changes to the script, press shift+R to reload your game."),
_("Press shift+O (the letter) to access the console."),
_("Press shift+D to access the developer menu."),
_("Have you backed up your projects recently?"),
]
class Project(object):
def __init__(self, path):
while path.endswith("/"):
path = path[:-1]
if not os.path.exists(path):
raise Exception("{} does not exist.".format(path))
# The name of the project.
if path.endswith(".app/Contents/Resources/autorun"):
self.name = os.path.basename(path[:-len(".app/Contents/Resources/autorun")])
else:
self.name = os.path.basename(path)
# The path to the project.
self.path = path
# The path to the game directory.
gamedir = os.path.join(path, "game")
if os.path.isdir(gamedir):
self.gamedir = gamedir
else:
self.gamedir = path
# Load the data.
self.load_data()
# The project's temporary directory.
self.tmp = None
# This contains the result of dumping information about the game
# to disk.
self.dump = { }
# The mtime of the last dump file loaded.
self.dump_mtime = 0
def get_dump_filename(self):
self.make_tmp()
return os.path.join(self.tmp, "navigation.json")
def load_data(self):
try:
f = open(os.path.join(self.path, "project.json"), "rb")
self.data = json.load(f)
f.close()
except:
self.data = { }
self.update_data()
def save_data(self):
"""
Saves the project data.
"""
try:
with open(os.path.join(self.path, "project.json"), "wb") as f:
json.dump(self.data, f)
except:
self.load_data()
def update_data(self):
data = self.data
data.setdefault("build_update", False)
data.setdefault("packages", [ "all" ])
data.setdefault("add_from", True)
data.setdefault("force_recompile", True)
def make_tmp(self):
"""
Makes the project's temporary directory, if it doesn't exist
yet.
"""
if self.tmp and os.path.isdir(self.tmp):
return
tmp = os.path.join(self.path, "tmp")
try:
os.mkdir(tmp)
except:
pass
if os.path.isdir(tmp):
self.tmp = tmp
return
self.tmp = tempfile.mkdtemp()
def temp_filename(self, filename):
"""
Returns a filename in the temporary directory.
"""
self.make_tmp()
return os.path.join(self.tmp, filename)
def launch(self, args=[], wait=False, env={}):
"""
Launches the project.
`args`
Additional arguments to give to the project.
`wait`
If true, waits for the launched project to terminate before
continuing.
`env`
Additional variables to include in the environment.
"""
self.make_tmp()
# Find the python executable to run.
executable_path = os.path.dirname(sys.executable)
if renpy.renpy.windows:
extension = ".exe"
else:
extension = ""
if persistent.windows_console:
executables = [ "python" + extension ]
else:
executables = [ "pythonw" + extension ]
executables.append(sys.executable)
for i in executables:
executable = os.path.join(executable_path, i)
if os.path.exists(executable):
break
else:
raise Exception("Python interpreter not found: %r", executables)
# Put together the basic command line.
cmd = [ executable, "-EO", sys.argv[0] ]
cmd.append(self.path)
cmd.extend(args)
# Add flags to dump game info.
cmd.append("--json-dump")
cmd.append(self.get_dump_filename())
if persistent.navigate_private:
cmd.append("--json-dump-private")
if persistent.navigate_library:
cmd.append("--json-dump-common")
environ = dict(os.environ)
environ.update(env)
for k in environ:
environ[k] = renpy.fsencode(environ[k])
# Launch the project.
cmd = [ renpy.fsencode(i) for i in cmd ]
p = subprocess.Popen(cmd, env=environ)
if wait:
if p.wait():
interface.error(_("Launching the project failed."), _("Please ensure that your project launches normally before running this command."))
def update_dump(self, force=False, gui=True, compile=False):
"""
If the dumpfile does not exist, runs Ren'Py to create it. Otherwise,
loads it in iff it's newer than the one that's already loaded.
"""
dump_filename = self.get_dump_filename()
if force or not os.path.exists(dump_filename):
if gui:
interface.processing(_("Ren'Py is scanning the project..."))
if compile:
self.launch(["compile", "--keep-orphan-rpyc" ], wait=True)
else:
self.launch(["quit"], wait=True)
if not os.path.exists(dump_filename):
self.dump["error"] = True
return
file_mtime = os.path.getmtime(dump_filename)
if file_mtime == self.dump_mtime:
return
self.dump_mtime = file_mtime
try:
with open(dump_filename, "r") as f:
self.dump = json.load(f)
# add todo list to dump data
self.update_todos()
except:
self.dump["error"] = True
def update_todos(self):
"""
Scans the scriptfiles for lines TODO comments and add them to
the dump data.
"""
todos = self.dump.setdefault("location", {})["todo"] = {}
files = self.script_files()
for f in files:
data = file(self.unelide_filename(f))
for l, line in enumerate(data):
l += 1
try:
line = line.decode("utf-8")
except:
continue
m = re.search(ur".*#\s*TODO(\s*:\s*|\s+)(.*)", line, re.I)
if m is None:
continue
raw_todo_text = m.group(2).strip()
todo_text = raw_todo_text
index = 0
while not todo_text or todo_text in todos:
index += 1
todo_text = u"{0} ({1})".format(raw_todo_text, index)
todos[todo_text] = [f, l]
def unelide_filename(self, fn):
"""
Unelides the filename relative to the project base.
"""
fn1 = os.path.join(self.path, fn)
if os.path.exists(fn1):
return fn1
fn2 = os.path.join(config.renpy_base, fn)
if os.path.exists(fn2):
return fn2
return fn
def script_files(self):
"""
Return a list of the script files that make up the project. These
are elided, and so need to be passed to unelide_filename before they
can be included in the project.
"""
rv = [ ]
rv.extend(i for i, isdir in util.walk(self.path)
if (not isdir) and (i.endswith(".rpy") or i.endswith(".rpym")) and (not i.startswith("tmp/")) )
return rv
class ProjectManager(object):
"""
This maintains a list of the various types of projects that
we know about.
"""
def __init__(self):
# The projects directory.
self.projects_directory = ""
# Normal projects, in alphabetical order by lowercase name.
self.projects = [ ]
# Template projects.
self.templates = [ ]
# All projects - normal, template, and hidden.
self.all_projects = [ ]
# Directories that have been scanned.
self.scanned = set()
self.scan()
def scan(self):
"""
Scans for projects.
"""
if (persistent.projects_directory is not None) and not os.path.isdir(persistent.projects_directory):
persistent.projects_directory = None
self.projects_directory = persistent.projects_directory
self.projects = [ ]
self.templates = [ ]
self.all_projects = [ ]
self.scanned = set()
if self.projects_directory is not None:
self.scan_directory(self.projects_directory)
self.scan_directory(config.renpy_base)
self.scan_directory(os.path.join(config.renpy_base, "templates"))
self.projects.sort(key=lambda p : p.name.lower())
self.templates.sort(key=lambda p : p.name.lower())
def scan_directory(self, d):
"""
Scans for projects in directories directly underneath `d`.
"""
global current
d = os.path.abspath(d)
if not os.path.isdir(d):
return
for pdir in util.listdir(d):
ppath = os.path.join(d, pdir)
# A project must be a directory.
if not os.path.isdir(ppath):
continue
autorun = os.path.join(ppath, "Contents", "Resources", "autorun")
if os.path.exists(autorun):
ppath = autorun
# A project has either a game/ directory, or a project.json
# file.
if (not os.path.isdir(os.path.join(ppath, "game"))) and (not os.path.exists(os.path.join(ppath, "project.json"))):
continue
if ppath in self.scanned:
continue
self.scanned.add(ppath)
# We have a project directory, so create a Project.
p = Project(ppath)
project_type = p.data.get("type", "normal")
if project_type == "hidden":
pass
elif project_type == "template":
self.templates.append(p)
else:
self.projects.append(p)
self.all_projects.append(p)
# Select the default project.
if persistent.active_project is not None:
p = self.get(persistent.active_project)
if p is not None:
current = p
return
p = self.get("tutorial")
if p is not None:
current = p
return
current = None
def get(self, name):
"""
Gets the project with the given name.
Returns None if the project doesn't exist.
"""
for p in self.all_projects:
if p.name == name:
return p
return None
manager = ProjectManager()
# The current project.
current = None
# Actions
class Select(Action):
"""
An action that causes p to become the selected project when it was
clicked. If label is not None, jumps to the given label.
"""
def __init__(self, p, label=None):
"""
`p`
Either a project object, or a string giving the name of a
project.
`label`
The label to jump to when clicked.
"""
if isinstance(p, basestring):
p = manager.get(p)
self.project = p
self.label = label
def get_selected(self):
if self.project is None:
return False
if current is None:
return False
return current.path == self.project.path
def get_sensitive(self):
return self.project is not None
def __call__(self):
global current
current = self.project
persistent.active_project = self.project.name
renpy.restart_interaction()
if self.label is not None:
renpy.jump(self.label)
class Launch(Action):
"""
An action that launches the supplied project, or the current
project if no project is supplied.
"""
def __init__(self, p=None):
if p is None:
self.project = current
elif isinstance(p, basestring):
self.project = manager.get(p)
else:
self.project = p
def get_sensitive(self):
return self.project is not None
def post_launch(self):
blurb = LAUNCH_BLURBS[persistent.blurb % len(LAUNCH_BLURBS)]
persistent.blurb += 1
interface.interaction(_("Launching"), blurb, pause=2.5)
def __call__(self):
self.project.launch()
renpy.invoke_in_new_context(self.post_launch)
class Rescan(Action):
def __call__(self):
"""
Rescans the projects directory.
"""
manager.scan()
renpy.restart_interaction()
manager.scan()
if isinstance(persistent.projects_directory, str):
persistent.projects_directory = renpy.fsdecode(persistent.projects_directory)
###############################################################################
# Code to choose the projects directory.
label choose_projects_directory:
python hide:
interface.interaction(_("PROJECTS DIRECTORY"), _("Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"), _("This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."),)
path, is_default = choose_directory(persistent.projects_directory)
if is_default:
interface.info(_("Ren'Py has set the projects directory to:"), "[path!q]", path=path)
persistent.projects_directory = path
project.manager.scan()
return
init python:
def set_projects_directory_command():
ap = renpy.arguments.ArgumentParser()
ap.add_argument("projects", help="The path to the projects directory.")
args = ap.parse_args()
persistent.projects_directory = args.projects
renpy.save_persistent()
return False
renpy.arguments.register_command("set_projects_directory", set_projects_directory_command)
def get_projects_directory_command():
ap = renpy.arguments.ArgumentParser()
args = ap.parse_args()
print persistent.projects_directory
return False
renpy.arguments.register_command("get_projects_directory", get_projects_directory_command)
-8
View File
@@ -1,8 +0,0 @@
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAnEdzfwV6FFnmjkbJHJKJ59jqLTGkPSES5LBFbxwweGuC3LU2sNs+
tRlWx+2+kbW6azb5yteP/O05/hzHdtIa4slao7s8A/wf0zA6HbLX4H5iqSosDvuw
FP9DAF46vH0Qn1a3k97JFV2eXoGAbwHZICKhbIPCm7qR39G8FvUrw7grCS+5Scb+
LzqkBv6TnwRDB4agcwhlkA432s6BTU8p9RIFmyldCEgq0SXeK07lkuDmOplp6IdL
bVwLoRWg6pngIEoPo/Qxt8ZnLdBthN+TAsMRiquz17GaAvERbkUBwYtlt7R8qx01
F3vzweKXSCguzr9XQBQflkVu2y6cmIEwPQIDAQAB
-----END RSA PUBLIC KEY-----
-347
View File
@@ -1,347 +0,0 @@
# Copyright 2004-2015 Tom Rothamel <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
init -1 python:
# The color of non-interactive text.
TEXT = "#545454"
# Colors for buttons in various states.
IDLE = "#42637b"
HOVER = "#d86b45"
DISABLED = "#808080"
# Colors for reversed text buttons (selected list entries).
REVERSE_IDLE = "#78a5c5"
REVERSE_HOVER = "#d86b45"
REVERSE_TEXT = "#ffffff"
# Colors for the scrollbar thumb.
SCROLLBAR_IDLE = "#dfdfdf"
SCROLLBAR_HOVER = "#d86b45"
# An image used as a separator pattern.
PATTERN = "images/pattern.png"
# A displayable used for the background of everything.
BACKGROUND = "images/background.png"
# A displayable used for the background of windows
# containing commands, preferences, and navigation info.
WINDOW = Frame("images/window.png", 0, 0, tile=True)
# A displayable used for the background of the projects list.
PROJECTS_WINDOW = Null()
# A displayable used the background of information boxes.
INFO_WINDOW = "#f9f9f9"
# Colors for the titles of information boxes.
ERROR_COLOR = "#d15353"
INFO_COLOR = "#545454"
INTERACTION_COLOR = "#d19753"
QUESTION_COLOR = "#d19753"
# The color of input text.
INPUT_COLOR = "#d86b45"
# FONTS/WEIGHTS
LIGHT = "Roboto-Light.ttf"
REGULAR = "Roboto-Regular.ttf"
if persistent.large_print:
LIGHT = REGULAR
init 1 python:
def size(n):
"""
Adjusts the font size if we're in large-print mode.
"""
if persistent.large_print and n < 18:
n = 18
return n
INDENT = 20
HALF_INDENT = 10
SCROLLBAR_SIZE = 16
SEPARATOR = Frame(PATTERN, 0, 0, tile=True, ymaximum=5, yalign=1.0)
SEPARATOR2 = Frame(PATTERN, 0, 0, tile=True, ymaximum=10, yalign=1.0)
SPACER_HEIGHT = 12
SPACER = Null(height=SPACER_HEIGHT)
HALF_SPACER_HEIGHT = 6
HALF_SPACER = Null(height=HALF_SPACER_HEIGHT)
# DIVIDING THE SCREEN
ONETHIRD = 258
TWOTHIRDS = 496
ONEHALF = 377
def checkbox(full, color):
if full:
return im.Twocolor("images/checkbox_full.png", color, color, style="l_checkbox_box")
else:
return im.Twocolor("images/checkbox_empty.png", color, color, style="l_checkbox_box")
init 1:
# The default style.
style l_default is default:
font LIGHT
color TEXT
idle_color IDLE
hover_color HOVER
size size(18)
style l_text is l_default
style l_button is l_default
style l_button_text is l_default:
insensitive_color DISABLED
selected_font REGULAR
# A small button, used at the bottom of the screen.
style l_link is l_default
style l_link_text is l_default:
size size(14)
font LIGHT
# Action buttons on the bottom of the screen.
style l_right_button is l_default:
xalign 1.0
ypos 600 - 128 + 12
left_margin 8 + INDENT
right_margin 10 + INDENT
style l_right_button_text is l_default:
size size(30)
style l_left_button is l_right_button:
xalign 0.0
style l_left_button_text is l_right_button_text
# The root frame. This contains everything but the bottom navigation,
# and buttons.
style l_root is l_default:
background BACKGROUND
xpadding 10
top_padding 64
bottom_padding 128
# An inner window.
style l_window is l_default:
background WINDOW
left_padding 6
xfill True
yfill True
# Normal size labels.
style l_label is l_default:
xfill True
top_padding 10
bottom_padding 8
bottom_margin 12
background SEPARATOR
style l_label_text is l_default:
size size(24)
xpos INDENT
yoffset 6
style l_label_small is l_default:
xfill True
bottom_padding 8
bottom_margin HALF_SPACER_HEIGHT
background SEPARATOR
# Small labels.
style l_label_small_text is l_default:
xpos INDENT
yoffset 6
size size(20)
# Alternate labels. This nests inside an l_label, and gives a button
# or label that's nested inside another label.
style l_alternate is l_default:
xalign 1.0
yalign 1.0
yoffset 4
right_margin INDENT
style l_alternate_text is l_default:
size size(14)
font LIGHT
text_align 1.0
style l_small_button is l_button
style l_small_button_text is l_button_text:
size size(14)
style l_small_text is l_text:
size size(14)
# Indents its contents.
style l_indent is l_default:
left_margin INDENT
# Indents its contents and pads vertically.
style l_indent_margin is l_indent:
ymargin 6
# Lists.
style l_list is l_default:
left_padding HALF_INDENT
xfill True
selected_background REVERSE_IDLE
selected_hover_background REVERSE_HOVER
style l_list_text is l_default:
idle_color IDLE
hover_color HOVER
selected_idle_color REVERSE_TEXT
selected_hover_color REVERSE_TEXT
insensitive_color DISABLED
style l_list2 is l_list:
left_padding (HALF_INDENT + INDENT)
style l_list2_text is l_list_text
# Scrollbar.
style l_vscrollbar is l_default:
thumb Fixed(
Solid(SCROLLBAR_IDLE, xmaximum=8, xalign=0.5),
Image("images/vscrollbar_center.png", xalign=0.5, yalign=0.5),
xmaximum = SCROLLBAR_SIZE)
hover_thumb Fixed(
Solid(SCROLLBAR_HOVER, xmaximum=8, xalign=0.5),
Image("images/vscrollbar_center.png", xalign=0.5, yalign=0.5),
xmaximum = SCROLLBAR_SIZE)
xmaximum SCROLLBAR_SIZE
bar_vertical True
bar_invert True
unscrollable "hide"
# Information window.
style l_info_vbox is vbox:
yalign 0.5
xalign 0.5
xfill True
style l_info_frame is l_default:
ypadding 21
xfill True
background Fixed(
INFO_WINDOW,
Frame(PATTERN, 0, 0, tile=True, ymaximum=5, yalign=0.0, yoffset=8),
Frame(PATTERN, 0, 0, tile=True, ymaximum=5, yalign=1.0, yoffset=-8),
)
yminimum 180
ypos 75
style l_info_label is l_default:
xalign 0.5
ypos 75
yanchor 1.0
yoffset 12
style l_info_label_text is l_default:
size size(36)
style l_info_text is l_default:
xalign 0.5
style l_info_button is l_button:
xalign 0.5
xmargin 50
style l_info_button_text is l_button_text:
text_align 0.5
layout "subtitle"
# Progress bar.
style l_progress_frame is l_default:
background Frame(PATTERN, 0, 0, tile=True)
ypadding 5
style l_progress_bar is l_default:
left_bar REVERSE_IDLE
right_bar Null()
ymaximum 24
# Navigation.
style l_navigation_button is l_button:
size_group "navigation"
right_margin INDENT
top_margin 3
style l_navigation_button_text is l_button_text:
size size(14)
font REGULAR
style l_navigation_text is l_text:
size size(14)
font LIGHT
color TEXT
# Checkboxes.
style l_checkbox is l_button:
left_padding INDENT
background checkbox(False, IDLE)
hover_background checkbox(False, HOVER)
selected_idle_background checkbox(True, IDLE)
selected_hover_background checkbox(True, HOVER)
insensitive_background checkbox(False, DISABLED)
style l_checkbox_box:
yanchor 0.5
ypos 11
style l_checkbox_text is l_button_text:
selected_font LIGHT
# Lines up with a checkbox.
style l_nonbox is l_button:
xpadding INDENT
style l_nonbox_text is l_button_text:
selected_font LIGHT
# Projects list.
style l_projects is l_default:
background PROJECTS_WINDOW
style hyperlink_text:
size size(18)
font LIGHT
color IDLE
hover_color HOVER
-68
View File
@@ -1,68 +0,0 @@
# Copyright 2004-2015 Tom Rothamel <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
init python:
class FileTail(object):
def __init__(self, filename, lines=8):
self.filename = filename
self.text = ""
self.lines = lines
def update(self):
try:
with open(self.filename) as f:
text = f.read()
try:
text = renpy.fsdecode(text)
except:
text = text.decode("latin-1")
text = text.strip()
text = text.split("\n")
newtext = [ ]
for l in text:
if "\r" in l:
_head, _sep, l = l.rpartition("\r")
while l:
newtext.append(l[:100])
l = l[100:]
text = newtext
text = text[-self.lines:]
text = "\n".join(text)
if text != self.text:
self.text = text
renpy.restart_interaction()
except:
pass
-609
View File
@@ -1,609 +0,0 @@
# Copyright 2004-2015 Tom Rothamel <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
init python in theme_data:
def __PerformScreenOperations(lines, file_picker_rows=5, file_picker_cols=2):
import re
x = 0
correct_section = False
while x < len(lines):
l = lines[x]
m = re.match(r'^screen\s+\w+\s*:\s*$', l)
if m:
correct_section = False
m = re.match(r'^screen\s+file_picker\s*:\s*$', l)
if m:
correct_section = True
if correct_section:
m = re.match(r'^\s+\$\s*columns\s*=\s*(\d+)\s*$', l)
if m:
l = l.replace(str(m.group(1)), str(file_picker_cols))
m = re.match(r'^\s+\$\s*rows\s*=\s*(\d+)\s*$', l)
if m:
l = l.replace(str(m.group(1)), str(file_picker_rows))
lines[x] = l
x = x + 1
return lines
def roundrect_screen_ops(lines):
return __PerformScreenOperations(lines)
def awt_screen_ops(lines):
return __PerformScreenOperations(lines, file_picker_rows=3)
# theme name -> (color scheme name -> code that implements it)
THEME = { }
# The set of theme functions.
THEME_FUNCTIONS = set()
# theme name -> function name to call to munge screens.rpy as appropriate
# for that theme.
THEME_SCREEN_OPERATIONS = { }
# Color schemes that work (technically - some are eye-melting) with the
# roundrect-style themes.
ROUNDRECT_SCHEMES = {
'Basic Blue': {'disabled': '#404040',
'disabled_text': '#c8c8c8',
'frame': '#6496c8',
'gm_root': '#dcebff',
'label': '#ffffff',
'mm_root': '#dcebff',
'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',
'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',
'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',
'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',
'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',
'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',
'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',
'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',
'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',
'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',
'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',
'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',
'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',
'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',
'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',
'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',
'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',
'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',
'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',
'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',
'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',
'widget': '#7AA27B',
'widget_hover': '#A3C7A3',
'widget_selected': '#ffffff',
'widget_text': '#CDE0CE'},
'Mint Chocolate': {'disabled': '#ffe69c',
'disabled_text': '#ddbc7e',
'frame': '#8ab395',
'gm_root': '#7a4229',
'label': '#7a4229',
'mm_root': '#7a4229',
'widget': '#ffe69c',
'widget_hover': '#f5c153',
'widget_selected': '#7a4229',
'widget_text': '#b5743a'},
'Parachute Pants': {'disabled': '#53c7bb',
'disabled_text': '#97d7bd',
'frame': '#457b9f',
'gm_root': '#37397f',
'label': '#cce2ae',
'mm_root': '#37397f',
'widget': '#53c7bb',
'widget_hover': '#97d7bd',
'widget_selected': '#37397f',
'widget_text': '#457b9f'},
'Strawberry Orchard': {'disabled': '#b3c292',
'disabled_text': '#525748',
'frame': '#d8ebae',
'gm_root': '#e7f3cb',
'label': '#525748',
'mm_root': '#e7f3cb',
'widget': '#525748',
'widget_hover': '#f45c73',
'widget_selected': '#ffce95',
'widget_text': '#e7f3cb'},
'Grape Jelly': {'disabled': '#81859a',
'disabled_text': '#5e2862',
'frame': '#8ea9b0',
'gm_root': '#5e2862',
'label': '#ffffff',
'mm_root': '#5e2862',
'widget': '#c45693',
'widget_hover': '#5e2862',
'widget_selected': '#e59eae',
'widget_text': '#ffffff'},
'Dreamscape': {'disabled': '#966077',
'disabled_text': '#c75f77',
'frame': '#836177',
'gm_root': '#c75f77',
'label': '#fefab6',
'mm_root': '#c75f77',
'widget': '#77a493',
'widget_hover': '#8accb3',
'widget_selected': '#c75f77',
'widget_text': '#ffffff'},
'Unrequited Love': {'disabled': '#dbe4dd',
'disabled_text': '#bd9ca9',
'frame': '#fffeed',
'gm_root': '#b38698',
'label': '#23000e',
'mm_root': '#b38698',
'widget': '#7fa1b3',
'widget_hover': '#b38698',
'widget_selected': '#fffeed',
'widget_text': '#ffffff'},
'Watermelon': {'disabled': '#f9cdad',
'disabled_text': '#fc9d9a',
'frame': '#f9cdad',
'gm_root': '#83af9b',
'label': '#fe4365',
'mm_root': '#83af9b',
'widget': '#fc9d9a',
'widget_hover': '#fe4365',
'widget_selected': '#e5fcc2',
'widget_text': '#ffffff'},
'City Lights': {'disabled': '#638e89',
'disabled_text': '#594f4f',
'frame': '#547980',
'gm_root': '#594f4f',
'label': '#e5fcc2',
'mm_root': '#594f4f',
'widget': '#45ada8',
'widget_hover': '#2e5860',
'widget_selected': '#e5fcc2',
'widget_text': '#9de0ad'},
'Vampire Bite': {'disabled': '#971140',
'disabled_text': '#bd4b40',
'frame': '#bd1550',
'gm_root': '#490a3d',
'label': '#f8ca00',
'mm_root': '#490a3d',
'widget': '#e97f02',
'widget_hover': '#f5a240',
'widget_selected': '#490a3d',
'widget_text': '#bd1550'},
'Underground Rave': {'disabled': '#57cdff',
'disabled_text': '#717be5',
'frame': '#04b4ff',
'gm_root': '#cd249b',
'label': '#000000',
'mm_root': '#cd249b',
'widget': '#8833ce',
'widget_hover': '#cd249b',
'widget_selected': '#b6d754',
'widget_text': '#000000'},
'Tree Frog': {'disabled': '#ffffff',
'disabled_text': '#1c140d',
'frame': '#cbe86b',
'gm_root': '#ffffff',
'label': '#1c140d',
'mm_root': '#ffffff',
'widget': '#1c140d',
'widget_hover': '#86827e',
'widget_selected': '#f2e9e1',
'widget_text': '#cbe86b'},
'Sun Kissed': {'disabled': '#ffffff',
'disabled_text': '#ec4c51',
'frame': '#f0874d',
'gm_root': '#f8c821',
'label': '#ffffff',
'mm_root': '#f8c821',
'widget': '#ec4c51',
'widget_hover': '#dc454a',
'widget_selected': '#f8c821',
'widget_text': '#ffffff'},
'Vintage Faded': {'disabled': '#b17d6f',
'disabled_text': '#8c4e3d',
'frame': '#ab7464',
'gm_root': '#935844',
'label': '#f7d3c8',
'mm_root': '#935844',
'widget': '#8c4e3d',
'widget_hover': '#734032',
'widget_selected': '#fcf5ed',
'widget_text': '#e2b9ad'},
'Vintage': {'disabled': '#883e35',
'disabled_text': '#b86258',
'frame': '#b86258',
'gm_root': '#a24637',
'label': '#ffffff',
'mm_root': '#a24637',
'widget': '#6c2921',
'widget_hover': '#832f26',
'widget_selected': '#ffc7c0',
'widget_text': '#fff4eb'},
'Earth Tones': {'disabled': '#12612f',
'disabled_text': '#2c6e44',
'frame': '#00551f',
'gm_root': '#6b4a27',
'label': '#ffffff',
'mm_root': '#568153',
'widget': '#ad8c31',
'widget_hover': '#568153',
'widget_selected': '#f2edc4',
'widget_text': '#ffffff'},
'Kindergarten': {'disabled': '#1ca4b2',
'disabled_text': '#22d5b3',
'frame': '#22d5b3',
'gm_root': '#ffeca6',
'label': '#ffffff',
'mm_root': '#ffeca6',
'widget': '#1781b1',
'widget_hover': '#12678e',
'widget_selected': '#f2edc4',
'widget_text': '#fdfbee'},
'Phone Operator': {'disabled': '#929292',
'disabled_text': '#ababab',
'frame': '#d2d2d2',
'gm_root': '#59667a',
'label': '#343e4d',
'mm_root': '#59667a',
'widget': '#59667a',
'widget_hover': '#343e4d',
'widget_selected': '#bed4f6',
'widget_text': '#ffffff'},
}
ROUNDRECT_VARIANTS = [
("Roundrect", "roundrect"),
("Bordered", "bordered"),
("Diamond", "diamond"),
("Regal", "regal"),
("Austen", "austen"),
("TV", "tv"),
("3D", "threeD"),
("Glow", "glow"),
("Marker", "marker"),
("Crayon", "crayon"),
]
ROUNDRECT_CODE = """theme.%(function)s(
## Theme: %(theme)s
## Color scheme: %(scheme)s
## The color of an idle widget face.
widget = "%(widget)s",
## The color of a focused widget face.
widget_hover = "%(widget_hover)s",
## The color of the text in a widget.
widget_text = "%(widget_text)s",
## The color of the text in a selected widget. (For
## example, the current value of a preference.)
widget_selected = "%(widget_selected)s",
## The color of a disabled widget face.
disabled = "%(disabled)s",
## The color of disabled widget text.
disabled_text = "%(disabled_text)s",
## The color of informational labels.
label = "%(label)s",
## The color of a frame containing widgets.
frame = "%(frame)s",
## The background of the main menu. This can be a color
## beginning with '#', or an image filename. The latter
## should take up the full height and width of the screen.
mm_root = "%(mm_root)s",
## The background of the game menu. This can be a color
## beginning with '#', or an image filename. The latter
## should take up the full height and width of the screen.
gm_root = "%(gm_root)s",
## If this is True, the in-game window is rounded. If False,
## the in-game window is square.
rounded_window = False,
## And we're done with the theme. The theme will customize
## various styles, so if we want to change them, we should
## do so below.
)"""
for theme, function in ROUNDRECT_VARIANTS:
THEME[theme] = { }
THEME_FUNCTIONS.add(function)
THEME_SCREEN_OPERATIONS[theme] = roundrect_screen_ops
for scheme, colors in ROUNDRECT_SCHEMES.iteritems():
subs = dict(colors)
subs["function"] = function
subs["theme"] = theme
subs["scheme"] = scheme
THEME[theme][scheme] = ROUNDRECT_CODE % (subs)
AWT_CODE = """theme.a_white_tulip(
## Theme: A White Tulip
## Scheme %(scheme)s
## The color of an idle widget face.
widget = "%(widget)s",
## The color of a focused widget face.
widget_hover = "%(widget_hover)s",
## The color of the text in a selected widget. (For
## example, the current value of a preference.)
widget_selected = "%(widget_selected)s",
## The color of a disabled widget face.
disabled = "%(disabled)s",
## The color of a frame containing widgets.
frame = "%(frame)s",
## The background of the main menu. This can be a color
## beginning with '#', or an image filename. The latter
## should take up the full height and width of the screen.
mm_root = "%(mm_root)s",
## The background of the game menu. This can be a color
## beginning with '#', or an image filename. The latter
## should take up the full height and width of the screen.
gm_root = "%(gm_root)s",
## The fonts used by this theme. The default fonts may not be
## suitable for non-English languages.
regular_font = "_theme_awt/Quicksand-Regular.ttf",
bold_font = "_theme_awt/Quicksand-Bold.ttf",
## And we're done with the theme. The theme will customize
## various styles, so if we want to change them, we should
## do so below.
)"""
THEME["A White Tulip"] = { }
THEME_FUNCTIONS.add("a_white_tulip")
THEME_SCREEN_OPERATIONS["A White Tulip"] = awt_screen_ops
for scheme, colors in ROUNDRECT_SCHEMES.iteritems():
subs = dict(colors)
subs["scheme"] = scheme
THEME["A White Tulip"][scheme] = AWT_CODE % (subs)
THEME["A White Tulip"]["A White Tulip"] = AWT_CODE % dict(
scheme = "A White Tulip",
widget = "#c1c6d3",
widget_hover = "#d7dbe5",
widget_text = "#6b6b6b",
widget_selected = "#c1c6d3",
disabled = "#b4b4b4",
disabled_text = "#6b6b6b",
label = "#6b6b6b",
frame = "#9391c9",
mm_root = "#ffffff",
gm_root = "#ffffff",
)
-50
View File
@@ -1,50 +0,0 @@
#!/usr/bin/env python
# Copyright 2004-2015 Tom Rothamel <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# This is used on Linux and Mac to prompt the user for the projects
# directory.
import sys
# Python3 and Python2-style imports.
try:
from tkinter import Tk
from tkinter.filedialog import askdirectory
except ImportError:
from Tkinter import Tk
from tkFileDialog import askdirectory
# Binary mode stdout for python3.
try:
sys.stdout = sys.stdout.buffer
except:
pass
# Create the TK canvas.
if __name__ == "__main__":
root = Tk()
root.withdraw()
result = askdirectory(initialdir=sys.argv[1], parent=root, title="Select Ren'Py Projects Directory")
sys.stdout.write(result.encode("utf8"))
-15
View File
@@ -1,15 +0,0 @@
translate arabic strings:
# game/about.rpy:21
old "[version!q]"
new "[version!q]"
# game/about.rpy:25
old "View license"
new "عرض الرخصة"
# game/about.rpy:27
old "Back"
new "عودة"
-23
View File
@@ -1,23 +0,0 @@
translate arabic strings:
# game/add_file.rpy:7
old "FILENAME"
new "اسم الملف"
# game/add_file.rpy:7
old "Enter the name of the script file to create."
new "إختر اسم لملف الحوار الذي سيتم تكوينه"
# game/add_file.rpy:10
old "The filename must have the .rpy extension."
new "يجب ان ينتهي اسم الملف بالصيغة .rpy"
# game/add_file.rpy:18
old "The file already exists."
new "هذا الملف موجود مسبقاً"
# game/add_file.rpy:21
old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
new "رينباي يقوم بتشغيل الملفات المنتهية بـ .rpy تلقائياً. لكي تستعمل هذا الملف, اختر له تبويب وافتحه عبر ملف آخر."
-200
View File
@@ -1,200 +0,0 @@
# : Translation updated at 2013-11-17 23:18
translate arabic strings:
# game/android.rpy:12
old "To build Android packages, please download RAPT (from {a=http://www.renpy.org/dl/android}here{/a}), unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
new "لتجهيز اللعبة للعمل على اجهزة اندرويد يمكنك تحميل الحزمة الخاصة بذلك {a=http://www.renpy.org/dl/android}here{/a}) و فك الضغط عنها, ثم نسخها إلى مجلد رينباي الرئيسي ثم إعادة فتح هذا المشغِّل."
# game/android.rpy:13
old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
new "حزمة الاندرويد RAPT موجوده, لكنك تحتاج لتنصيب Android SDK قبل ان تبدأ بتجهيز حزم للعمل على اندرويد. الرجاء اختيار تنصيب Android SDK لتستطيع ذلك."
# game/android.rpy:14
old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
new "حزمة اندرويد RAPT موجوده, لكن المفتاح لم يتم تجهيزه. الرجاء تكوين مفتاح جديد او استرجاع android.keystore"
# game/android.rpy:15
old "The current project has not been configured. Use \"Configure\" to configure it before building."
new "المشروع الحالي لم يتم تجهيز إعدادته. الرجاء اختيار \"Configure\" لتقوم بتجهيزها قبل بناء الحزمة."
# game/android.rpy:16
old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
new "قم باختيار زر \"Build\" لتقوم بتجهيز المشروع الحالي إلى حزمة قابلة للعمل على اندرويد. او قم بربط جهاز اندرويد و اختيار \"Build & Install\" ليتم تنصيبها مباشرة على الجهاز المطلوب."
# game/android.rpy:18
old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
new "يقوم بمحاكاة جهاز اندرويد هاتفي محمول. \n\n خاصية اللمس يتم محاكاتها عبر مؤشر الفأره, لكن فقط حين يكون زر الفأره مضغوطاً. زر الخروج يقوم باستدعاء نافذة القائمة الرئيسية, و PageUp هو زر العودة إلى الوراء."
# game/android.rpy:19
old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
new "يقوم بمحاكاة جهاز اندرويد تابلت. \n\n خاصية اللمس يتم محاكاتها عبر مؤشر الفأره, لكن فقط حين يكون زر الفأره مضغوطاً. زر الخروج يقوم باستدعاء نافذة القائمة الرئيسية, و PageUp هو زر العودة إلى الوراء"
# game/android.rpy:20
old "Attempts to emulate an OUYA console.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
new "يقوم بمحاكاة جهاز Ouya. \n\n يد التحكم تتم محاكاتها بأزرار الإتجاهات, زر الإدخال يحاكي select, زر الخروج يحاكي زر menu, و PageUp يحاكي زر العودة."
# game/android.rpy:22
old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
new "يقوم بتحميل و تنصيب Android SDK والحزم المساندة لها. يعطيك خيار تكوين المفاتيح المطلوبة لتتمكن من استعمال الحزمة."
# game/android.rpy:23
old "Configures the package name, version, and other information about this project."
new "يقوم بتجهيز إعدادات الحزمة, رقم النسخة, و معلومات أخرى تتعلق بهذا المشروع."
# game/android.rpy:24
old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
new "يفتح الملف الخاص بمعلومات مفتاح Google Play في محرر النصوص. \n\n هذه الخطوة غير مطلوبة إلا لو كان البرنامج يحتاج إحدى الحوم المساندة expansion APK. الرجاء الإطلاع على ملفات المساعدة للحصول على المزيد من المعلومات."
# game/android.rpy:25
old "Builds the Android package."
new "يقوم ببناء حزمة للأندرويد."
# game/android.rpy:26
old "Builds the Android package, and installs it on an Android device connected to your computer."
new "يقوم ببناء حزمة للأندرويد, ثم يقوم بتنصيبها على جهاز أندرويد المتصل بحاسوبك."
# game/android.rpy:142
old "{a=%s}%s{/a}"
new "{a=%s}%s{/a}"
# game/android.rpy:361
old "Android: [project.current.name!q]"
new "أندرويد: [project.current.name!q]"
# game/android.rpy:381
old "Emulation:"
new "محاكاة"
# game/android.rpy:389
old "Phone"
new "هاتف"
# game/android.rpy:393
old "Tablet"
new "تابلت/ لوحي"
# game/android.rpy:397
old "Television / OUYA"
new "تلفزيون / OUYA"
# game/android.rpy:409
old "Build:"
new "بناء"
# game/android.rpy:417
old "Install SDK & Create Keys"
new "تنصيب SDK و اختلاق مفاتيح"
# game/android.rpy:421
old "Configure"
new "إعدادات"
# game/android.rpy:425
old "Build Package"
new "بناء الحزمة"
# game/android.rpy:429
old "Build & Install"
new "بناء و تنصيب"
# : Translation updated at 2014-04-17 13:01
translate arabic strings:
# game/android.rpy:30
old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
new "لبناء ملفات الأندرويد, الرجاء تحميل RAPT, ثم فك الضغط عن الملف ووضعه في مجلد رينباي. قد تحتاج لإعادة تشغيل رينباي ليعمل بشكل صحيح."
# game/android.rpy:31
old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
new "تحتاج لنسخة برمجية من جافا تعتمد الـ 32-بت لتستطيع إنشاء ملفات الأندرويد على نظام الوندوز. حزمة JDK تختلف عن JRE, قد تكون الجافا لديك موجوده لكنها تفتقد الـ JDK. \n\n الرجاء {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}تحميل و تنصيب JDK{/a} ثم إعادة تشغيل رينباي"
# game/android.rpy:39
old "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
new "يحاول محاكاة نظام تلفزيوني للأندرويد مثل جهاز OUYA او Fire TV. \n\n يتم تخطيط الأزرار لعصا التحكم لتناسب ازرار جهاز التحكم عن بعد. Controller input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
# game/android.rpy:47
old "Connects to an Android device running ADB in TCP/IP mode."
new "يتصل بجهاز أندرويد يعمل على نظام ADB عن طريق TCP/IP mode"
# game/android.rpy:48
old "Disconnects from an Android device running ADB in TCP/IP mode."
new "يفصل الاتصال عن جهاز أندرويد يعمل على نظام ADB عن طريق TCP/IP mode"
# game/android.rpy:516
old "Other:"
new "آخر:"
# game/android.rpy:524
old "Remote ADB Connect"
new "الإتصال عن بعد عن طريق ADB"
# game/android.rpy:528
old "Remote ADB Disconnect"
new "قطع إتصال ADB عن بعد"
# game/android.rpy:561
old "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
new "قبل ان تصتطيع إنشاء ملفات للأندرويد, عليك ان تقوم بتحميل ملفات RAPT الخاصة بتحويل ملفات رينباي للأندرويد. هل تريد ان تقوم بتحميل الحزمة الآن؟"
# game/android.rpy:608
old "Remote ADB Address"
new "عنوان ADB عن بعد"
# game/android.rpy:609
old "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
new "الرجاء إدخال عنوان الأي بي ورقم المنفذ المطلوب للإتصال, على شكل \"192.168.1.143:5555\". الرجاء العودة لدليل المستخدم الخاص بجهازك لتعرف إن كان يدعم الإتصال عن بعد للـ ADB و إن كان قادراً على ذلك, ستجد العنوان و المنفذ المطلوبان."
# game/android.rpy:619
old "Invalid remote ADB address"
new "عنوان ِADB خاطيء"
# game/android.rpy:619
old "The address must contain one exactly one ':'."
new "العنوان يجب ان يحتوي على علامة ':' واحده فقط لا غير"
# game/android.rpy:623
old "The host may not contain whitespace."
new "الخادم يجب ان لا يحتوي على مساحات فارغة"
# game/android.rpy:629
old "The port must be a number."
new "يجب ان يكون العنوان مكون من أرقام فقط"
translate arabic strings:
# game/android.rpy:46
old "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
new "يبني الحزمة الخاصة بالأندرويد و يقوم بتنصيبها على جهاز أندرويد متصل بجهازك, ثم يقوم بإقلاع البرنامج على جهاز الأندرويد."
# game/android.rpy:290
old "Television"
new "تلفاز"
# game/android.rpy:326
old "Build, Install & Launch"
new "بناء,تنصيب و إقلاع."
# : Translation updated at 2015-06-19 08:55
translate arabic strings:
# game/android.rpy:50
old "Retrieves the log from the Android device and writes it to a file."
new "يجلب قائمة المهام من جعاز الأندرويد و يكتبها في ملف."
# game/android.rpy:240
old "Copying Android files to distributions directory."
new "يتم الآن نسخ ملفات الأندرويد إلى المجلد الخاص بالنشر"
# game/android.rpy:404
old "Logcat"
new "Logcat"
# game/android.rpy:538
old "Retrieving logcat information from device."
new "يتم النسخ من الجهاز لمعلومات Logcat"
@@ -1,7 +0,0 @@
translate arabic strings:
# game/choose_directory.rpy:73
old "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
new "لم يتمكن رينباي من تشغيل بايثون باستخدام tkinter لاختيار المجلد. الرجال تنصيب حزمة tkinter أو python-tk."
-43
View File
@@ -1,43 +0,0 @@
translate arabic strings:
# game/choose_theme.rpy:274
old "Could not change the theme. Perhaps options.rpy was changed too much."
new "لم يتمكن رينباي من تغيير المظهر, ربما ملف options.rpy قد تغير بشكل كبير"
# game/choose_theme.rpy:332
old "Display"
new "عرض"
# game/choose_theme.rpy:333
old "Window"
new "نافذة"
# game/choose_theme.rpy:334
old "Fullscreen"
new "ملء الشاشة"
# game/choose_theme.rpy:335
old "Planetarium"
new "Planetarium"
# game/choose_theme.rpy:342
old "Sound Volume"
new "مستوى الصوت"
# game/choose_theme.rpy:376
old "Choose Theme"
new "إختر المظهر"
# game/choose_theme.rpy:389
old "Theme"
new "المظهر"
# game/choose_theme.rpy:413
old "Color Scheme"
new "توليفة الألوان"
# game/choose_theme.rpy:444
old "Continue"
new "استمرار"
-589
View File
@@ -1,589 +0,0 @@
# : Translation updated at 2013-04-30 07:54
translate arabic strings:
# renpy/common/00action_file.rpy:118
old "%b %d, %H:%M"
new "%b %d, %H:%M"
# : Translation updated at 2013-04-30 07:54
translate arabic strings:
# renpy/common/00gltest.rpy:50
old "Graphics Acceleration"
new "تسريع الرسومات"
# renpy/common/00gltest.rpy:54
old "Automatically Choose"
new "إختر بشكل اوتوماتيكي"
# renpy/common/00gltest.rpy:59
old "Force Angle/DirectX Renderer"
new "فرض استعمال محركات Angle/DirectX"
# renpy/common/00gltest.rpy:63
old "Force OpenGL Renderer"
new "فرض استعمال محركات OpenGL"
# renpy/common/00gltest.rpy:67
old "Force Software Renderer"
new "فرض استعمال المحركات البرمجية software renderer"
# renpy/common/00gltest.rpy:73
old "Changes will take effect the next time this program is run."
new "سيتم تفعيل التغييرات في المرة القادمة التي تفتح فيها البرنامج"
# renpy/common/00gltest.rpy:77
old "Quit"
new "خروج"
# renpy/common/00gltest.rpy:82
old "Return"
new "عودة"
# renpy/common/00gltest.rpy:112
old "Performance Warning"
new "تحذير عن الأداء"
# renpy/common/00gltest.rpy:117
old "This computer is using software rendering."
new "هذا الجهاز يستعمل software rendering"
# renpy/common/00gltest.rpy:119
old "This computer is not using shaders."
new "هذا الجهاز لا يستعمل shaders"
# renpy/common/00gltest.rpy:121
old "This computer is displaying graphics slowly."
new "هذا الجهاز يستعرض الرسوميات بشكل بطيء"
# renpy/common/00gltest.rpy:123
old "This computer has a problem displaying graphics: [problem]."
new "هذا الجهاز يواجه مشكلة في استعراض الرسوميات [problem]"
# renpy/common/00gltest.rpy:128
old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
new "محركات الرسوميات قد تكون قديمة او لا تعمل بشكل صحيح. قد يسبب ذلك بطء او اخطاء في الاستعراض, القيام بتحديث directX قد يساعد في حل المشكلة."
# renpy/common/00gltest.rpy:130
old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
new " محركات الرسوميات قد تكون قديمة او لا تعمل بشكل صحيح. قد يسبب ذلك بطء او اخطاء في الاستعراض."
# renpy/common/00gltest.rpy:135
old "Update DirectX"
new "تحديث DirectX"
# renpy/common/00gltest.rpy:141
old "Continue, Show this warning again"
new "استمرار, الرجاء عرض هذا التحذير في المرة الثادمة ايضاً"
# renpy/common/00gltest.rpy:145
old "Continue, Don't show warning again"
new "استمرار, لا تعرض هذا التحذير مرة اخرى"
# renpy/common/00gltest.rpy:171
old "Updating DirectX."
new "يتم تحديث DirectX"
# renpy/common/00gltest.rpy:175
old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
new "يتم الآن تنصيب DirectX, قد يبدأ ذلك بشكل مصغر في شريط المهام. الرجاء اتباع التعليمات لاكمال التنصيب."
# renpy/common/00gltest.rpy:179
old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
new "{b}ملاحظة:{/b} مايكروسوفت دايركت أكس يقوم تلقائياً بتنصيب شريط بينق Bing toolbar. إذا لم ترغب بذلك الرجاء القيام بإلغاء تحديد خانة الاختيار"
# renpy/common/00gltest.rpy:183
old "When setup finishes, please click below to restart this program."
new "حيثن ينتهي التنصيب, الرجاء الضغط ادناه لإعادة تشغيل البرنامج"
# renpy/common/00gltest.rpy:185
old "Restart"
new "إعادة تشغيل"
# : Translation updated at 2013-04-30 07:54
translate arabic strings:
# renpy/common/00keymap.rpy:167
old "Saved screenshot as %s."
new "تم حفظ الصورة كـ %s"
# : Translation updated at 2013-04-30 07:54
translate arabic strings:
# renpy/common/00layout.rpy:421
old "Are you sure?"
new "هل انت متأكد؟"
# renpy/common/00layout.rpy:422
old "Are you sure you want to delete this save?"
new "هل انت متأكد من رغبتك في حذف خانة الحفظ هذه؟"
# renpy/common/00layout.rpy:423
old "Are you sure you want to overwrite your save?"
new "هل انت متأكد من رغبتك في الحفظ على هذه الخانة؟"
# renpy/common/00layout.rpy:424
old "Loading will lose unsaved progress.\nAre you sure you want to do this?"
new "الاسترجاع سيضيع كل ما فعلته منذ خانة الحفظ السابقة. \n هل انت متأكد من رغبتك في الاسترجاع إلى هذه النقطة؟"
# renpy/common/00layout.rpy:425
old "Are you sure you want to quit?"
new "هل انت متأكد من رغبتك في الخروج؟"
# renpy/common/00layout.rpy:426
old "Are you sure you want to return to the main menu?\nThis will lose unsaved progress."
new "هل انت متأكد من رغبتك في العودة للقائمة الرئيسية؟ \n كل ما لم تقم بحفظة سيضيع."
# : Translation updated at 2013-04-30 07:54
translate arabic strings:
# renpy/common/00library.rpy:77
old "Skip Mode"
new "وضع التسريع"
# renpy/common/00library.rpy:80
old "Fast Skip Mode"
new "وضع التسريع السريع"
# : Translation updated at 2013-04-30 07:54
translate arabic strings:
# renpy/common/00updater.rpy:1258
old "Updater"
new "برنامج التحديث"
# renpy/common/00updater.rpy:1267
old "This program is up to date."
new "هذه النسخة هي الأحدث"
# renpy/common/00updater.rpy:1269
old "[u.version] is available. Do you want to install it?"
new "النسخة [u.version] متوفرة, هل ترغب في تنصيبها؟"
# renpy/common/00updater.rpy:1271
old "Preparing to download the updates."
new "يتم التجهيز لتحميل البرنامج من الانترنت"
# renpy/common/00updater.rpy:1273
old "Downloading the updates."
new "يتم تنزيل التحديثات"
# renpy/common/00updater.rpy:1275
old "Unpacking the updates."
new "يتم فك الضغط عن التحديثات"
# renpy/common/00updater.rpy:1279
old "The updates have been installed. The program will restart."
new "تم التحديث.. سيتم إعادة تشغيل البرنامج."
# renpy/common/00updater.rpy:1281
old "The updates have been installed."
new "تم التحديث."
# renpy/common/00updater.rpy:1283
old "The updates were cancelled."
new "تم إلغاء التحديث."
# : Translation updated at 2013-04-30 07:54
translate arabic strings:
# renpy/common/_compat/gamemenu.rpym:180
old "Empty Slot."
new "خانة فارغة"
# renpy/common/_compat/gamemenu.rpym:337
old "Previous"
new "السابق"
# renpy/common/_compat/gamemenu.rpym:344
old "Next"
new "التالي"
# : Translation updated at 2013-04-30 07:54
translate arabic strings:
# renpy/common/_compat/preferences.rpym:411
old "Joystick Mapping"
new "خيارات عصى التحكم"
# : Translation updated at 2013-04-30 07:54
translate arabic strings:
# renpy/common/_errorhandling.rpym:408
old "An exception has occurred."
new "حصل استثناء"
# renpy/common/_errorhandling.rpym:434
old "Rollback"
new "تراجع"
# renpy/common/_errorhandling.rpym:436
old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
new "يقوم بالتراجع لنقطة سابقة لكي تستطيع اختيار شيء آخر"
# renpy/common/_errorhandling.rpym:439
old "Ignore"
new "تجاهل"
# renpy/common/_errorhandling.rpym:441
old "Ignores the exception, allowing you to continue. This often leads to additional errors."
new "يتجاهل الاستثناء مما يستمح لك بالاستمرار. قد يسبب هذا المزيد من الاخطاء."
# renpy/common/_errorhandling.rpym:444
old "Reload"
new "إعادة المحاولة"
# renpy/common/_errorhandling.rpym:446
old "Reloads the game from disk, saving and restoring game state if possible."
new "يعيد تشغيل اللعبة من القرص الصلب, مع محاولة استعمادة آخر نقطة وحفظها عند الإستطاعة."
# renpy/common/_errorhandling.rpym:448
old "Open Traceback"
new "قراءة التقرير"
# renpy/common/_errorhandling.rpym:450
old "Opens the traceback.txt file in a text editor."
new "يفتح تقرير الخطأ في برنامج الملفات النصية."
# renpy/common/_errorhandling.rpym:456
old "Quits the game."
new "يخرج من اللعبة."
# renpy/common/_errorhandling.rpym:483
old "Parsing the script failed."
new "حصل خطأ أثناء تشغيل النص."
# renpy/common/_errorhandling.rpym:510
old "Open Parse Errors"
new "يفتح قائمة اخطاء التشغيل."
# renpy/common/_errorhandling.rpym:512
old "Opens the errors.txt file in a text editor."
new "يفتح ملف errors.txt في برنامج الملفات النصية"
# : Translation updated at 2013-04-30 07:54
translate arabic strings:
# renpy/common/_layout/classic_load_save.rpym:152
old "a"
new "a"
# renpy/common/_layout/classic_load_save.rpym:161
old "q"
new "q"
# : Translation updated at 2013-11-17 23:18
translate arabic strings:
# renpy/common/00action_file.rpy:587
old "Quick save complete."
new "تم الحفظ السريع بنجاح"
# : Translation updated at 2013-11-17 23:18
translate arabic strings:
# renpy/common/00gallery.rpy:521
old "Image [index] of [count] locked."
new "يوجد عدد صور [index] من أصل [count] مقفل"
# renpy/common/00gallery.rpy:539
old "prev"
new "السابق"
# renpy/common/00gallery.rpy:540
old "next"
new "التالي"
# renpy/common/00gallery.rpy:541
old "slideshow"
new "عرض الشرائح"
# renpy/common/00gallery.rpy:542
old "return"
new "العودة"
# : Translation updated at 2013-11-17 23:18
translate arabic strings:
# renpy/common/00layout.rpy:427
old "Are you sure you want to begin skipping?"
new "هل أنت متأكد من رغبتك في البدء بالتسريع؟"
# renpy/common/00layout.rpy:428
old "Are you sure you want to skip to the next choice?"
new "هل انت متأكد من رغبتك في التسريع حتى الخيار التالي؟"
# renpy/common/00layout.rpy:429
old "Are you sure you want to skip to unseen dialogue or the next choice?"
new "هل انت متأكد من رغبتك في تسريع الخيارات و الحوار الذي لم يسبق لك قرائته؟"
# : Translation updated at 2014-04-17 13:01
translate arabic strings:
# renpy/common/00console.rpy:179
old "%(version)s console, originally by Shiz, C, and delta.\n"
new ""
# renpy/common/00console.rpy:180
old "Press <esc> to exit console. Type help for help.\n"
new "إضغط زر الخروج لإغلاق لوحة التحكم, اكتب كلمة help للمساعدة"
# renpy/common/00console.rpy:184
old "Ren'Py script enabled."
new "لغة برمحة رينباي متاحه"
# renpy/common/00console.rpy:186
old "Ren'Py script disabled."
new "لغة برمجة رينباي غير متاحه"
# renpy/common/00console.rpy:392
old "help: show this help"
new "مساعده: عرض هذه المساعده"
# renpy/common/00console.rpy:397
old "commands:\n"
new "أوامر: \n"
# renpy/common/00console.rpy:407
old " <renpy script statement>: run the statement\n"
new "<renpy script statement>: عرض الأوامر\n"
# renpy/common/00console.rpy:409
old " <python expression or statement>: run the expression or statement"
new " <python expression or statement>: عرض التعبير او الأوامر"
# renpy/common/00console.rpy:417
old "clear: clear the console history"
new "clear: مسح تاريخ لوحة التحكم"
# renpy/common/00console.rpy:421
old "exit: exit the console"
new "exit: الخروج من لوحة التحكم"
# renpy/common/00console.rpy:429
old "load <slot>: loads the game from slot"
new "استرجاع <slot>: يقوم باسترجاع اللعب من نقطة الحفظ"
# renpy/common/00console.rpy:442
old "save <slot>: saves the game in slot"
new "حفظ <slot>: يقوم بحفظ اللعب في نقطة الحفظ"
# renpy/common/00console.rpy:453
old "reload: reloads the game, refreshing the scripts"
new "reload: يعيد تشغيل اللعبة مع عرض التغييرات في النص"
# renpy/common/00console.rpy:461
old "watch <expression>: watch a python expression"
new "مشاهده <expression>: يقوم بعرض تبيرات بايثون"
# renpy/common/00console.rpy:470
old "unwatch <expression>: stop watching an expression"
new "unwatch <expression>: يقوم بإيقاف تعبير بايثون"
# renpy/common/00console.rpy:478
old "unwatchall: stop watching all expressions"
new "unwatchall: يقوم بإيقاف كل تعبيرات بايثون"
# renpy/common/00console.rpy:484
old "jump <label>: jumps to label"
new "jump <label>: يقفز للعنوان"
# : Translation updated at 2014-04-17 13:01
translate arabic strings:
# renpy/common/00keymap.rpy:332
old "Autoreload"
new "إعادة التحميل تلقائياً"
# : Translation updated at 2014-04-17 13:01
translate arabic strings:
# renpy/common/_developer/developer.rpym:65
old "Developer Menu"
new "قائمة المبرمج"
# renpy/common/_developer/developer.rpym:67
old "Reload Game (Shift+R)"
new "إعادة تشغيل اللعبة (Shift+R)"
# renpy/common/_developer/developer.rpym:69
old "Console (Shift+O)"
new "لوحة التحكم (Shift+O)"
# renpy/common/_developer/developer.rpym:71
old "Variable Viewer"
new "مستعرض الأوامر"
# renpy/common/_developer/developer.rpym:73
old "Theme Test"
new "اختبار القوالب"
# renpy/common/_developer/developer.rpym:75
old "Image Location Picker"
new "مكان الصور المطلوبة"
# renpy/common/_developer/developer.rpym:77
old "Filename List"
new "قائمة اسماء الملفات"
# renpy/common/_developer/developer.rpym:81
old "Show Image Load Log"
new "عرض قائمة الصور "
# renpy/common/_developer/developer.rpym:84
old "Hide Image Load Log"
new "إخفاء قائمة الصور"
# renpy/common/_developer/developer.rpym:149
old "No variables have changed since the game started."
new "لم يتم تغيير اي من الأوامر منذ ان بدأت اللعبة"
# renpy/common/_developer/developer.rpym:152
old "Return to the developer menu"
new "العودة للوحة المبرمج"
# renpy/common/_developer/developer.rpym:272
old "{b}Missing Images{/b}"
new "{b}صور مفقودة{/b}"
# renpy/common/_developer/developer.rpym:424
old "Rectangle: %r"
new "مثلث: %r"
# renpy/common/_developer/developer.rpym:429
old "Mouse position: %r"
new "مكان المؤشر: %r"
# renpy/common/_developer/developer.rpym:431
old "Right-click or escape to quit."
new "إضغط بالزر الايمن او إضغط زر الخروح للإغلاق"
# renpy/common/_developer/developer.rpym:482
old "Done"
new "تم"
# : Translation updated at 2014-04-17 13:01
translate arabic strings:
# renpy/common/_developer/inspector.rpym:43
old "Displayable Inspector"
new "اختبار المستعرضات"
# renpy/common/_developer/inspector.rpym:49
old "Nothing to inspect."
new "لا يوجد شيء ليتم اختباره"
# renpy/common/_developer/inspector.rpym:58
old "Size"
new "حجم"
# renpy/common/_developer/inspector.rpym:63
old "Style"
new "مظهر"
# renpy/common/_developer/inspector.rpym:123
old "Inspecting Styles of [displayable_name!q]"
new "يتم اختبار المظهر الخاص بـ [displayable_name!q]"
# renpy/common/_developer/inspector.rpym:135
old "displayable:"
new "مستعرضات"
# renpy/common/_developer/inspector.rpym:142
old " (no properties affect the displayable)"
new " (لا توجد اي مؤثرات على هذا المستعرض)"
# renpy/common/_developer/inspector.rpym:144
old " (default properties omitted)"
new " (تم استبعاد تأثير المؤثرات القياسية)"
# renpy/common/_developer/inspector.rpym:174
old "<repr() failed>"
new "<repr() failed>"
# Translation updated at 2014-09-30 23:01
translate arabic strings:
# renpy/common/_developer/inspector.rpym:80
old "Location"
new "الموقع"
translate arabic strings:
# renpy/common/00preferences.rpy:387
old "Clipboard voicing enabled. Press 'shift+C' to disable."
new "تشغيل الأصوات من الحافظة مفعّل. إضغط لإيقافه زريّ: Shift+C"
# renpy/common/00preferences.rpy:389
old "Self-voicing enabled. Press 'v' to disable."
new "التكلّم التلقائي مفعَل. لإيقافه إضغط زر V"
translate arabic strings:
# renpy/common/00updater.rpy:362
old "The Ren'Py Updater is not supported on mobile devices."
new "تحديث برنامج رينباي غير مدعوم على الأجهزة المحمولة."
# renpy/common/00updater.rpy:478
old "An error is being simulated."
new "يتم محاكاة خطأ الآن."
# renpy/common/00updater.rpy:654
old "Either this project does not support updating, or the update status file was deleted."
new "هذا المشروع لا يدعم التحديث، أو أن ملف حالة نسخة البرنامج محذوفة."
# renpy/common/00updater.rpy:668
old "This account does not have permission to perform an update."
new "هذا الحساب ليست لديه الصلاحية ليقوم بالتحديث."
# renpy/common/00updater.rpy:671
old "This account does not have permission to write the update log."
new " هذا الحساب ليست لديه الصلاحية ليكتب ملف التحديث."
# renpy/common/00updater.rpy:696
old "Could not verify update signature."
new "لم نتمكن من التحقق من توقيع التحديث update signature."
# renpy/common/00updater.rpy:956
old "The update file was not downloaded."
new "لم يتم تحميل ملف التحديث."
# renpy/common/00updater.rpy:974
old "The update file does not have the correct digest - it may have been corrupted."
new "ملف التحديث لا يحتوي على المختصرات الصحيحة - قد يكون معطوباً."
# renpy/common/00updater.rpy:1030
old "While unpacking {}, unknown type {}."
new "عند فك الحزمة {}، نوع مجهول {}."
translate arabic strings:
# renpy/common/_developer/developer.rpym:437
old "Rectangle copied to clipboard."
new "تم نسخ المربع إلى الحافظة."
# renpy/common/_developer/developer.rpym:440
old "Position copied to clipboard."
new "تم نسخ الموضع إلى الحافظة."
-52
View File
@@ -1,52 +0,0 @@
# : Translation updated at 2013-04-30 07:54
translate arabic strings:
# game/distribute.rpy:333
old "Nothing to do."
new "لا شيء لإنجازه"
# game/distribute.rpy:337
old "Scanning project files..."
new "يتم فحص الملفات..."
# game/distribute.rpy:344
old "Scanning Ren'Py files..."
new "يتم فحص ملفات رينباي..."
# game/distribute.rpy:494
old "Archiving files..."
new "يتم أرشفة الملفات..."
# game/distribute.rpy:745
old "Writing the [variant] [format] package."
new "يتم كتابة ملفات [variant] [format]"
# game/distribute.rpy:758
old "Making the [variant] update zsync file."
new "Making the [variant] update zsync file."
# game/distribute.rpy:854
old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
new "تم انهاء {b}[complete]{/b} من عدد {b}[total]{/b} من الملفات."
# game/distribute.rpy:915
old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
new "تم الإنتهاء من تكوين رزمة البيانات لنشر اللعبة. بسبب اختلاف نظام الملفات في الأنظمة التشغيلية ماك و لينوكس, لا يمكن فك الضغط عن الرزمة الخاصة بتلك الأنظمة على نظام وندوز."
# : Translation updated at 2013-11-17 23:18
translate arabic strings:
# game/distribute.rpy:358
old "No packages are selected, so there's nothing to do."
new "لم يتم اختيار اي حزمة, لم يحصل اي شيء."
# : Translation updated at 2014-04-17 13:01
translate arabic strings:
# game/distribute.rpy:335
old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
new "فشل بناء ملفات النشر. build.directory_name يجب أن لا يحتوي على مساحات فارغة, فواصل, او فواصل منقوطة في إسم المجلد "
@@ -1,66 +0,0 @@
translate arabic strings:
# game/distribute_gui.rpy:139
old "Build Distributions: [project.current.name!q]"
new "تجميع الملفات تجهيزاً للنشر: [project.current.name!q]"
# game/distribute_gui.rpy:154
old "Directory Name:"
new "اسم المجلد:"
# game/distribute_gui.rpy:158
old "Executable Name:"
new "اسم الملف التشغيلي:"
# game/distribute_gui.rpy:167
old "Actions:"
new "الأوامر:"
# game/distribute_gui.rpy:175
old "Edit options.rpy"
new "تحرير options.rpy"
# game/distribute_gui.rpy:176
old "Refresh"
new "إعادة تحميل"
# game/distribute_gui.rpy:193
old "Build Packages:"
new "بناء الرزمة البيانية:"
# game/distribute_gui.rpy:208
old "Build Updates"
new "بناء تحديثات:"
# game/distribute_gui.rpy:212
old "Build"
new "بناء"
# game/distribute_gui.rpy:219
old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
new "تم ايجاد بعض الاخطاء في المشروع. الرجاء التأكد من خلو المشروع من الأخطاء قبل نشره بشكل نهائي."
# game/distribute_gui.rpy:236
old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
new "مشروعك يخلو من معلومات النشر, هل ترغب في إضافة هذه المعلومات في نهاية ملف options.rpy؟"
translate arabic strings:
# game/distribute_gui.rpy:194
old "Add from clauses to calls, once"
new "إضافة بند 'مِن' إلى أمر الجلب, مرة واحدة"
# game/distribute_gui.rpy:231
old "Options:"
new "خيارات:"
# game/distribute_gui.rpy:238
old "Add from clauses to calls"
new "إضافة بنود 'مِن' إلى أمر الجلب"
# game/distribute_gui.rpy:246
old "Adding from clauses to call statements that do not have them."
new "إضافة بنود 'مِن' إلى أوامر الجلب التي لا تحتوي عليها."
-64
View File
@@ -1,64 +0,0 @@
# Translation updated at 2013-04-30 07:54
translate arabic strings:
# game/editor.rpy:120
old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
new "{b}نقترح.{/b} محرر نص له واجهة سهلة الاستعمال ويعين على كتابة النصوص البرمجية يفضل برنامج يحتوي على مدقق لغوي. Editraحالياً لا يدعم اللغات الأجنبية مثل اللغه الكورية و الصينية و اليابانية."
# game/editor.rpy:121
old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
new "{b}نقترح.{/b} محرر نص له واجهة سهلة الاستعمال ويعين على كتابة النصوص البرمجية يفضل برنامج يحتوي على مدقق لغوي. Editraحالياً لا يدعم اللغات الأجنبية مثل اللغه الكورية و الصينية و اليابانية. على نظام لينوكس, Editra يحتاج wxPython."
# game/editor.rpy:137
old "The may have occured because wxPython is not installed on this system."
new "قد يكون السبب ان wxPython غير موجود على هذا الجهاز."
# game/editor.rpy:144
old "Up to 22 MB download required."
new "مطلوب تحميل ملف بحجم 22 ميغا بايت."
# game/editor.rpy:157
old "1.8 MB download required."
new "مطلوب تحميل ملف بحجم 1.8 ميغا بايت."
# game/editor.rpy:158
old "This may have occured because Java is not installed on this system."
new "قد يكون السبب ان الجافا غير موجوده على هذا الجهاز."
# game/editor.rpy:327
old "An exception occured while launching the text editor:\n[exception!q]"
new "حصل استثناء اثناء فتح المحرر: \n[exception!q]"
# game/editor.rpy:378
old "Select Editor"
new "الرجاء اختيار المحرر"
# game/editor.rpy:393
old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
new "محرر النصوص هو برنامج يساعدك على تعديل ملفات رينباي البرمجية والحوار. هنا, يمكنك اختيار المحرر الذي سيستعلمه رينباي. إذا لم يكن لديك مسبقاً, سيتم تحميله و تنصيبه بشكل اوتوماتيكي."
# game/editor.rpy:415
old "Cancel"
new "إلغاء الامر"
# Translation updated at 2013-11-17 23:18
translate arabic strings:
# game/editor.rpy:137
old "This may have occured because wxPython is not installed on this system."
new "قد يكون سبب ذلك ان wxPython غير موجود في نظام التشغيل لديك"
# game/editor.rpy:155
old "A mature editor that requires Java."
new "محرر متخصص يستعمل لغة جافا"
# game/editor.rpy:164
old "Invokes the editor your operating system has associated with .rpy files."
new "يقوم بفتح البرنامج المسؤول عن تحرير ملفات .rpy في نظامك التشغيلي"
# game/editor.rpy:180
old "Prevents Ren'Py from opening a text editor."
new "يمنع رينباي من فتح اي محرر نصوص"
-131
View File
@@ -1,131 +0,0 @@
# : Translation updated at 2013-04-30 07:54
translate arabic strings:
# game/front_page.rpy:79
old "+ Create New Project"
new "+ إبدأ مشروعاً جديداً"
# game/front_page.rpy:90
old "Launch Project"
new "تشغيل المشروع"
# game/front_page.rpy:111
old "Tutorial"
new "الدليل العملي"
# game/front_page.rpy:112
old "The Question"
new "السؤال"
# game/front_page.rpy:128
old "Active Project"
new "المشروع الحالي"
# game/front_page.rpy:136
old "Open Directory"
new "فتح مجلد"
# game/front_page.rpy:141
old "game"
new "اللعبة"
# game/front_page.rpy:142
old "base"
new "المشروع كله"
# game/front_page.rpy:148
old "Edit File"
new "تحرير ملف"
# game/front_page.rpy:156
old "All script files"
new "جميع الملفات النصية"
# game/front_page.rpy:165
old "Navigate Script"
new "مهام إضافية"
# game/front_page.rpy:176
old "Check Script (Lint)"
new "فحص الملف (لينت)"
# game/front_page.rpy:177
old "Change Theme"
new "تغيير المظهر"
# game/front_page.rpy:178
old "Delete Persistent"
new "حذف الملفات المؤقتة"
# game/front_page.rpy:186
old "Build Distributions"
new "تجميع المشروع للنشر"
# game/front_page.rpy:188
old "Generate Translations"
new "تجهيز ملفات للترجمة"
# game/front_page.rpy:204
old "Checking script for potential problems..."
new "يتم فحص الملفات لأي اخطاء محتملة..."
# game/front_page.rpy:219
old "Deleting persistent data..."
new "يتم الآن حذف الملفات المؤقتة "
# : Translation updated at 2013-11-17 23:18
translate arabic strings:
# game/front_page.rpy:204
old "Android"
new "أندرويد"
# game/front_page.rpy:206
old "Extract Dialogue"
new "استخراج النص"
# : Translation updated at 2014-04-17 13:01
translate arabic strings:
# game/front_page.rpy:144
old "[p.name!q] (template)"
new "[p.name!q] (template)"
# Translation updated at 2014-09-30 23:01
translate arabic strings:
# game/front_page.rpy:35
old "Open [text] directory."
new "فتح المجلد [text]"
# game/front_page.rpy:150
old "Select project [text]."
new "اختر المشروع [text]"
# game/front_page.rpy:234
old "Force Recompile"
new "إعادة حزم الملفات"
# game/front_page.rpy:285
old "Recompiling all rpy files into rpyc files..."
new "يتم إعادة حزم الملفات من صيغة rpy إلى rpyc..."
translate arabic strings:
# game/front_page.rpy:246
old "iOS"
new "iOS نظام تشغيل"
# Translation updated at 2015-06-19 08:55
translate arabic strings:
# game/front_page.rpy:198
old "images"
new "الصور"
-90
View File
@@ -1,90 +0,0 @@
translate arabic strings:
# game/interface.rpy:89
old "Documentation"
new "المستندات المرفقة"
# game/interface.rpy:90
old "Ren'Py Website"
new "موقع رينباي"
# game/interface.rpy:91
old "Ren'Py Games List"
new "قائمة ألعاب رينباي"
# game/interface.rpy:92
old "About"
new "معلومات"
# game/interface.rpy:99
old "update"
new "تحديث"
# game/interface.rpy:101
old "preferences"
new "خيارات"
# game/interface.rpy:102
old "quit"
new "خروج"
# game/interface.rpy:149
old "Yes"
new "نعم"
# game/interface.rpy:151
old "No"
new "لا"
# game/interface.rpy:181
old "Due to package format limitations, non-ASCII file and directory names are not allowed."
new "بسبب محدودية التجميع, الاحرف الغير لاتينيه غير مسموح بها في اسم الملف او المجلدات"
# game/interface.rpy:183
old "[title]"
new "[title]"
# game/interface.rpy:248
old "ERROR"
new "خطأ"
# game/interface.rpy:280
old "While [what!q], an error occured:"
new "حصل خطأ أثناء [what!q]"
# game/interface.rpy:281
old "[exception!q]"
new "[exception!q]"
# game/interface.rpy:298
old "Text input may not contain the {{ or [[ characters."
new "لا يمكن استعمال الرمزان {{ و ]] هنا"
# game/interface.rpy:303
old "File and directory names may not contain / or \\."
new "غير مسموح ان يحتوي اسم الملف او المجلد على الرمزان / أو \\"
# game/interface.rpy:309
old "File and directory names must consist of ASCII characters."
new "اسم الملف و المجلدات التي تحتويه يجب ان تكون مكتوبة بأحرف ASCII "
# game/interface.rpy:330
old "INFORMATION"
new "معلومات"
# game/interface.rpy:373
old "PROCESSING"
new "يتم إجراء العمليات"
# game/interface.rpy:390
old "QUESTION"
new "سؤال"
translate arabic strings:
# game/interface.rpy:451
old "CHOICE"
new "إختيار"
-100
View File
@@ -1,100 +0,0 @@
# Translation updated at 2015-03-22 20:50
translate arabic strings:
# game/ios.rpy:28
old "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
new "لبناء حزم الـ iOS, الرجاء تحميل البرنامج الخاص بذلك renios و فك الضغط عنه, ثم وضعه في مجلد رينباي الرئيسي. بعد ذلك قم بإعادة تشغيل رينباي."
# game/ios.rpy:29
old "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
new "لم يتم اختيار المسار الذي سيتم وضع Xcode فيه. الرجاء ضغط زر اختيار المجلد لاختيار المكان الصحيح."
# game/ios.rpy:30
old "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
new "لا يوجد مشروع Xcode متطابق مع مشروع رينباي الحالي. الرجاء اختيار زر 'صنع مشروع Xcode' لبدء واحد."
# game/ios.rpy:31
old "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
new "يوجد مشروع Xcode. لتحديثه قم بضغط زر 'تحديث مشروع Xcode' ليصبح متطابقاً مع آخر التعديلات على اللعبة’ او قم باستعمال Xcode للبناء و التنصيب."
# game/ios.rpy:33
old "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
new "يقوم بمحاكاة جهاز أيفون. اللمس يتم محاكاته عن طريق الضغط بالزر الأيسر للفأرة."
# game/ios.rpy:34
old "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
new "يقوم بمحاكاة جهاز أيفون. اللمس يتم محاكاته عن طريق الضغط بالزر الأيسر للفأرة."
# game/ios.rpy:36
old "Selects the directory where Xcode projects will be placed."
new "إختر المجلد الذي سيكون فيه مشروع Xcode."
# game/ios.rpy:37
old "Creates an Xcode project corresponding to the current Ren'Py project."
new "يقوم بصنع مشروع Xcode متطابق مع مشروع رينباي الحالي."
# game/ios.rpy:38
old "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
new "يقوم بتحديث مشروع Xcode ليصبح متطابقاً مع ملفات اللعبة. يجب أن يتم تكرار هذه العملية مع كل تغيير في اللعبة."
# game/ios.rpy:39
old "Opens the Xcode project in Xcode."
new "يقوم بفتح مشروع Xcode في Xcode."
# game/ios.rpy:41
old "Opens the directory containing Xcode projects."
new "يقوم بفتح المجلد الموجود فيه مشاريع Xcode."
# game/ios.rpy:126
old "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
new "مشروع Xcode موجود مسبقاً. هل تريد تغيير إسم المشروع القديم, و استبداله بالجديد؟"
# game/ios.rpy:200
old "iOS: [project.current.name!q]"
new "iOS: [project.current.name!q]"
# game/ios.rpy:229
old "iPhone"
new "أيفون"
# game/ios.rpy:233
old "iPad"
new "أيباد"
# game/ios.rpy:253
old "Select Xcode Projects Directory"
new "إختر مسار مشاريع Xcode"
# game/ios.rpy:257
old "Create Xcode Project"
new "صنع مشروع Xcode"
# game/ios.rpy:261
old "Update Xcode Project"
new "تحديث مشروع Xcode"
# game/ios.rpy:266
old "Launch Xcode"
new "إقلاع Xcode"
# game/ios.rpy:301
old "Open Xcode Projects Directory"
new "فتح مجلد مشاريع Xcode"
# game/ios.rpy:334
old "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
new "قبل صنع الحزم الخاصة ببرامج iOS يجب ان تقوم بتحميل برنامج renios المساند لرينباي على اجهزة أبل. هل تريد تحميل renios الآن؟"
# game/ios.rpy:343
old "XCODE PROJECTS DIRECTORY"
new "مسار مشاريع Xcode"
# game/ios.rpy:343
old "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
new "الرجاء إختيار المجلد الذي سيتم وضع مشاريع Xcode فيه باستخدام نافذة اختيار المجلد. قد تكون النافذة مفتوحة خلف هذه النافذة."
# game/ios.rpy:348
old "Ren'Py has set the Xcode Projects Directory to:"
new "رينباي قام بتحديد مجلد مشاريع Xcode إلى:"
-71
View File
@@ -1,71 +0,0 @@
translate arabic strings:
# game/navigation.rpy:150
old "Navigate: [project.current.name]"
new "الذهاب إلى: [project.current.name]"
# game/navigation.rpy:159
old "Order: "
new "الترتيب:"
# game/navigation.rpy:160
old "alphabetical"
new "أبجدي"
# game/navigation.rpy:162
old "by-file"
new "ملف ملف"
# game/navigation.rpy:164
old "natural"
new "طبيعي"
# game/navigation.rpy:168
old "refresh"
new "إعادة تحميل"
# game/navigation.rpy:176
old "Category:"
new "فئة:"
# game/navigation.rpy:178
old "files"
new "ملفات"
# game/navigation.rpy:179
old "labels"
new "وسم"
# game/navigation.rpy:180
old "defines"
new "تحديد"
# game/navigation.rpy:181
old "transforms"
new "التحول"
# game/navigation.rpy:182
old "screens"
new "النوافذ"
# game/navigation.rpy:183
old "callables"
new "ما يمكن استجلابه"
# game/navigation.rpy:184
old "TODOs"
new "TODOs"
# game/navigation.rpy:223
old "+ Add script file"
new "+إضافة ملف نص"
# game/navigation.rpy:231
old "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
new "No TODO comments found.\n\nTo create one, include \"# TODO\" in your script."
# game/navigation.rpy:238
old "The list of names is empty."
new "قائمة الأسماء فارغة"
-48
View File
@@ -1,48 +0,0 @@
# : Translation updated at 2013-04-30 07:54
translate arabic strings:
# game/new_project.rpy:22
old "Choose Project Template"
new "الرجاء اختيار تصميم المظهر للمشروع"
# game/new_project.rpy:40
old "Please select a template to use for your new project. Ren'Py ships with a default template that creates an English-language game with standard screens."
new "الرجاء اختيار التصميم الذي ترغبه لمشروعك الجديد. رينباي يأتي بعدة تصاميم قياسية يمكنك التعديل عليها لاحقاً."
# game/new_project.rpy:55
old "PROJECT NAME"
new "اسم المشروع"
# game/new_project.rpy:56
old "Please enter the name of your project:"
new "الرجاء اختيار اسم لمشروعك الجديد"
# game/new_project.rpy:62
old "The project name may not be empty."
new "لا يمكن ان يكون اسم المشروع فارغاً"
# game/new_project.rpy:67
old "[project_name!q] already exists. Please choose a different project name."
new "الاسم [project_name!q] يوجد مسبقاً, الرجاء اختيار اسم مختلف."
# game/new_project.rpy:70
old "[project_dir!q] already exists. Please choose a different project name."
new "[project_dir!q] يوجد مسبقاً, الرجاء اختيار اسم مختلف."
# : Translation updated at 2013-11-17 23:18
translate arabic strings:
# game/new_project.rpy:40
old "Please select a template to use for your new project. The template sets the default font and the user interface language. If your language is not supported, choose 'english'."
new "الرجاء اختيار القالب المطلوب للمشروع الجديد. هذه القوالب تقوم بتجهيز اتجاه النص و اللغه المستخدمة في الواجهة لتسهل عملية البدء. إذا لم تكن لغتك مدعومة الرجاء اختيار اللغة الانجليزية."
# : Translation updated at 2014-04-17 13:01
translate arabic strings:
# game/new_project.rpy:71
old "The projects directory could not be set. Giving up."
new "لم يتم تحديد مجلد المشاريع, سيتم الإلغاء"
-95
View File
@@ -1,95 +0,0 @@
# : Translation updated at 2013-04-30 07:54
translate arabic strings:
# game/preferences.rpy:40
old "Launcher Preferences"
new "خيارات برنامج التشغيل"
# game/preferences.rpy:61
old "Projects Directory:"
new "دليل المشاريع:"
# game/preferences.rpy:68
old "[persistent.projects_directory!q]"
new "[persistent.projects_directory!q]"
# game/preferences.rpy:70
old "Not Set"
new "غير محدد"
# game/preferences.rpy:84
old "Text Editor:"
new "محرر الملفات النصية:"
# game/preferences.rpy:106
old "Update Channel:"
new "مصدر التحديثات:"
# game/preferences.rpy:126
old "Navigation Options:"
new "خيارات استعراض المجلدات"
# game/preferences.rpy:130
old "Include private names"
new "تضمين الأسماء الخاصة"
# game/preferences.rpy:131
old "Include library names"
new "تضمين اسماء المكتبات"
# game/preferences.rpy:141
old "Launcher Options:"
new "خيارات برنامج التشغيل:"
# game/preferences.rpy:145
old "Hardware rendering"
new "الإستعراض بواسطة قطع الجهاز الداخلية"
# game/preferences.rpy:148
old "Console output"
new "الإستعراض بواسطة البرمجيات المتوفرة"
# game/preferences.rpy:169
old "Open launcher project"
new "فتح الواجهة التشغيلية كمشروع"
# game/preferences.rpy:183
old "Language:"
new "اللغة:"
# Translation updated at 2014-04-17 13:01
translate arabic strings:
# game/preferences.rpy:164
old "Show templates"
new "عرض القوالب"
# Translation updated at 2014-09-30 23:01
translate arabic strings:
# game/preferences.rpy:91
old "Projects directory: [text]"
new "مجلد المشاريع [text]"
# game/preferences.rpy:114
old "Text editor: [text]"
new "محرر النصوص [text]"
# game/preferences.rpy:171
old "Large fonts"
new "خط كبير"
translate arabic strings:
# game/preferences.rpy:174
old "Show edit file section"
new "عرض قسم تعديل الملف"
# game/preferences.rpy:176
old "Generate empty strings for translations"
new "صنع خانات فارغة للترجمات"
-68
View File
@@ -1,68 +0,0 @@
# : Translation updated at 2013-04-30 07:54
translate arabic strings:
# game/project.rpy:196
old "Ren'Py is scanning the project..."
new "رينباي يقوم بفحص المشروع"
# game/project.rpy:485
old "PROJECTS DIRECTORY"
new "سياق مجلدات المشاريع"
# game/project.rpy:485
old "Please choose the projects directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
new "الرجاء اختيار نسق المشاريع من الصفحة الخاصة بذلك. \n{b}قد تكون النافذة ظهرت خلف هذه النافذة.{/b}"
# game/project.rpy:485
old "This launcher will scan for projects in this directory, will create new projects in this directory, and will place built projects into this directory."
new "سيقوم البرنامج بفحص المجلد هذا لإيجاد المشاريع السابقة, أو ليضع المشاريع الجديده فيه, و ايضاً لوضع المشاريع المنتهيه عند تجهيزها للنشر."
# game/project.rpy:525
old "Ren'Py was unable to run python with tkinter to choose the projects directory."
new "رينباي لم يستطع تشغيل برمجيات بايثون للبحث عن مجلد المشاريع."
# game/project.rpy:529
old "Ren'Py has set the projects directory to:"
new "رينباي قام بتحديد مجلد المشاريع إلى المكان التالي:"
# : Translation updated at 2014-04-17 13:01
translate arabic strings:
# game/project.rpy:48
old "After making changes to the script, press shift+R to reload your game."
new "عند إجراء أي تغييرات في ملف الحوار, يمكنك ضغط shift+R لترى التغييرات داخل اللعبة"
# game/project.rpy:49
old "Press shift+O (the letter) to access the console."
new "إضغط shift+O للدخول على لوحة التحكم"
# game/project.rpy:50
old "Press shift+D to access the developer menu."
new "إضغط shift+D للدخول على لوحة تحكم المبرمج"
# game/project.rpy:219
old "Launching the project failed."
new "لم تنجح محاولة إقلاع المشروع"
# game/project.rpy:219
old "Please ensure that your project launches normally before running this command."
new "الرجاء التأكد من سلامة إقلاع المشروع قبل تشغيل هذا الأمر البرمجي"
# game/project.rpy:516
old "Launching"
new "جاري الإقلاع"
# game/project.rpy:585
old "Ren'Py was unable to run python with tkinter to choose the projects directory. Please install the python-tk or tkinter package."
new "رينباي لم يتمكن من تشغيل بايثون مع tkinter لكي يختار مجلد المشاريع, الرجاء تنصيب Python-tk او tkinter"
# Translation updated at 2014-09-30 23:01
translate arabic strings:
# game/project.rpy:47
old "Have you backed up your projects recently?"
new "هل قمت بعمل نسخة احتياطية من مشاريعك مؤخراً؟"
-17
View File
@@ -1,17 +0,0 @@
translate arabic python:
al = "DejaVuSans.ttf"
style.l_default.font = al
style.l_default.size = 16
style.l_button_text.selected_font = al
style.l_button_text.selected_bold = True
style.l_link_text.font = al
style.l_alternate_text.font = al
style.l_navigation_button_text.font = al
style.l_navigation_text.font = al
style.l_navigation_text.bold = True
style.l_checkbox_text.selected_font = al
style.l_nonbox_text.selected_font = al
style.hyperlink_text.font = al
make_style_backup()
config.rtl = True
-38
View File
@@ -1,38 +0,0 @@
translate arabic strings:
# game/translations.rpy:10
old "Create or Update Translations"
new "صنع او تحديث الترجمات"
# game/translations.rpy:10
old "Please enter the name of the language for which you want to create or update translations."
new "الرجاء كتابة اسم اللغة التي ستقوم بالترجمة إليها و الضغط على زر انتر"
# game/translations.rpy:15
old "The language name can not be the empty string."
new "لا يمكن ان يكون اسم اللغة فارغاً"
# game/translations.rpy:26
old "Ren'Py is generating translations...."
new "يقوم رينباي بتصنيع ملفات الترجمة..."
# game/translations.rpy:30
old "Ren'Py has finished generating [language] translations."
new "انتهى رينباي من صناعة ملفات الترجمة إلى [language]"
translate arabic strings:
# game/translations.rpy:44
old "What format would you like for the extracted dialogue?"
new "ما هي الصيغة التي تريدها للنص المستخرج؟"
# game/translations.rpy:56
old "Ren'Py is extracting dialogue...."
new "رينباي يقوم باستخراج الحوار إلى ملف نص"
# game/translations.rpy:60
old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[format] in the base directory."
new "رينباي انتهى من استخراج الحوار. الحوار المستخرج يوجد الآن في [format] في المجلد الرئيسي"
-100
View File
@@ -1,100 +0,0 @@
# : Translation updated at 2013-04-30 07:54
translate arabic strings:
# game/updater.rpy:54
old "Select Update Channel"
new "الرجاء اختيار طريقة التحديث"
# game/updater.rpy:65
old "The update channel controls the version of Ren'Py the updater will download. Please select an update channel:"
new "طريقة التحديث تحدد لبرنامج رينباي اي المواقع يستخدم لإيجاد النسخ الجديدة. الرجاء اختيار الطريقة التي تناسبك."
# game/updater.rpy:70
old "Release"
new "نسخة مكتملة"
# game/updater.rpy:76
old "{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games."
new "{b}موصى به.{/b} نسخة رينباي التي يفضل استعمالها مع كل الالعاب الجديدة."
# game/updater.rpy:81
old "Prerelease"
new "نسخة مبدأية"
# game/updater.rpy:87
old "A preview of the next version of Ren'Py that can be used for testing and taking advantage of new features, but not for final releases of games."
new "عينة من نسخة رينباي القادمة تسمح لك بتجربة الإضافات الجديدة. لا ننصح باستعمالها لصناعة ألعاب معدة للنشر."
# game/updater.rpy:93
old "Experimental"
new "نسخة تجريبية"
# game/updater.rpy:99
old "Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer."
new "النسخ التجريبية من رينباي. الأفضل ألا تستعمل هذه النسخ إلا لو طلب منك ذلك احد مبرمجي رينباي"
# game/updater.rpy:119
old "An error has occured:"
new "حصل خطأ:"
# game/updater.rpy:121
old "Checking for updates."
new "يتم البحث عن تحديثات."
# game/updater.rpy:123
old "Ren'Py is up to date."
new "نسخة رينباي التي لديك هي الأحدث."
# game/updater.rpy:125
old "[u.version] is now available. Do you want to install it?"
new "النسخة [u.version] متوفرة, هل ترغب في تنصيبها؟"
# game/updater.rpy:127
old "Preparing to download the update."
new "يتم التجهيز لتنزيل التحديث."
# game/updater.rpy:129
old "Downloading the update."
new "يتم تنزيل التحديث."
# game/updater.rpy:131
old "Unpacking the update."
new "يتم فك الضغط عن التحديث."
# game/updater.rpy:133
old "Finishing up."
new "اللمسات النهائية."
# game/updater.rpy:135
old "The update has been installed. Ren'Py will restart."
new "تم تنصيب التحديثات بنجاح, سيتم إعادة تشغيل رينباي الآن."
# game/updater.rpy:137
old "The update has been installed."
new "تم تنصيب التحديثات."
# game/updater.rpy:139
old "The update was cancelled."
new "تم إلغاء التحديث."
# game/updater.rpy:156
old "Ren'Py Update"
new "تحديثات رينباي."
# game/updater.rpy:162
old "Proceed"
new "استمرار."
# : Translation updated at 2014-04-17 13:01
translate arabic strings:
# game/updater.rpy:129
old "Nightly"
new "مسائي"
# game/updater.rpy:135
old "The bleeding edge of Ren'Py development. This may have the latest features, or might not run at all."
new "أحدث نسخة طازجة من رينباي التجريبي, قد يحتوي على آخر مستجدات رينباي و قد لا يعمل مطلقاً"
-15
View File
@@ -1,15 +0,0 @@
translate finnish strings:
# game/about.rpy:39
old "[version!q]"
new "[version!q]"
# game/about.rpy:43
old "View license"
new "Näytä lisenssi"
# game/about.rpy:45
old "Back"
new "Takaisin"
-23
View File
@@ -1,23 +0,0 @@
translate finnish strings:
# game/add_file.rpy:28
old "FILENAME"
new "TIEDOSTONIMI"
# game/add_file.rpy:28
old "Enter the name of the script file to create."
new "Kirjoita skriptitiedoston nimi, jonka haluat luoda."
# game/add_file.rpy:31
old "The filename must have the .rpy extension."
new "Tiedostolla on oltava .rpy -tunniste."
# game/add_file.rpy:39
old "The file already exists."
new "Tiedosto on jo olemassa."
# game/add_file.rpy:42
old "# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n"
new "# Ren'Py lataa automaattisesti kaikki scriptitiedostot, joilla on .rpy pääte. Käyttääksesi tätä\n# tiedostoa, luo label ja hyppää siihen toisesta tiedostosta.\n"
-186
View File
@@ -1,186 +0,0 @@
translate finnish strings:
# game/android.rpy:30
old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
new "Luodaksesi Android-sovelluksia, ole hyvä ja lataa RAPT, pura se, ja aseta se Ren'Py kansioon. Tämän jälkeen käynnistä Ren'Py uudelleen."
# game/android.rpy:31
old "A 32-bit Java Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
new "32-bittinen Javan kehitystyökalu vaaditaan Android-sovellusten luomiseen Windowsilla. JDK on erilainen kuin JRE, joten on mahdollista, että sinulla on Java ilman JDK:ta.\n\n{a=http://www.oracle.com/technetwork/java/javase/downloads/index.html}Lataa ja asenna JDK{/a}, ja sen jälkeen käynnistä Ren'Py uudelleen."
# game/android.rpy:32
old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
new "RAPT on asennettu, mutta sinun on asennettava Android SDK ennen kuin voit luoda Android-sovelluksia. Valitse 'Asenna SDK' tehdäksesi tämän."
# game/android.rpy:33
old "RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore."
new "RAPT on asennettu, mutta avainta ei ole konfiguroitu. Luo uusi avain, tai palauta android.keystore."
# game/android.rpy:34
old "The current project has not been configured. Use \"Configure\" to configure it before building."
new "Valittua projektia ei ole konfiguroitu. Käytä \"Konfigurointi\" -toimintoa konfiguroidaksesi sen ennen sovelluksen kokoamista."
# game/android.rpy:35
old "Choose \"Build\" to build the current project, or attach an Android device and choose \"Build & Install\" to build and install it on the device."
new "Valitse \"Kokoa\" kootaksesi projektin, tai kiinnitä Android-laite ja valitse \"Kokoa ja asenna\" kootaksesi ja asentaaksesi sen laitteeseen."
# game/android.rpy:37
old "Attempts to emulate an Android phone.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
new "Ren'Py pyrkii emuloimaan Android-puhelinta.\n\nKosketus valintaa emuloidaan hiirellä, mutta vain kun nappia pidetään pohjassa. Esc toimii Menu-näppäimenä ja Pg Up toimii peruutusnappina."
# game/android.rpy:38
old "Attempts to emulate an Android tablet.\n\nTouch input is emulated through the mouse, but only when the button is held down. Escape is mapped to the menu button, and PageUp is mapped to the back button."
new "Ren'Py pyrkii emuloimaan Android-tablettia.\n\nKosketusta emuloidaan hiirellä, mutta vain kun nappia pidetään pohjassa. Esc toimii Menu-näppäimenä ja Pg Up toimii peruutusnappina."
# game/android.rpy:39
old "Attempts to emulate a televison-based Android console, like the OUYA or Fire TV.\n\nController input is mapped to the arrow keys, Enter is mapped to the select button, Escape is mapped to the menu button, and PageUp is mapped to the back button."
new "Ren'Py pyrkii emuloimaan televisiopohjaista Android-konsolia, kuten OUYA tai Fire TV.\n\nOhjainnäppäimet ovat nuolinäppäimet, Enter toimii valitsijana, Esc toimii Menu-näppäimenä ja Pg Up toimii peruutusnappina."
# game/android.rpy:41
old "Downloads and installs the Android SDK and supporting packages. Optionally, generates the keys required to sign the package."
new "Lataa ja asentaa Android SDK:n ja tarvittavat lisäpaketit. Lisäksi, voidaan käyttää avainten luomiseen."
# game/android.rpy:42
old "Configures the package name, version, and other information about this project."
new "Konfiguroi paketin nimen, version sekä kaiken muun projektia koskevan tiedon."
# game/android.rpy:43
old "Opens the file containing the Google Play keys in the editor.\n\nThis is only needed if the application is using an expansion APK. Read the documentation for more details."
new "Avaa tiedoston, joka sisältää Google Play -avaimet, editorissa.\n\nTätä tarvitaan vain, jos sovellus käyttää laajennus-APK:ta. Lue dokumentit saadaksesi lisätietoa."
# game/android.rpy:44
old "Builds the Android package."
new "Rakentaa Android-paketin."
# game/android.rpy:45
old "Builds the Android package, and installs it on an Android device connected to your computer."
new "Rakentaa Android-paketin, ja asentaa sen tietokoneeseen kytkettyyn Android-laitteeseen."
# game/android.rpy:47
old "Connects to an Android device running ADB in TCP/IP mode."
new "Yhdistää Android-laitteeseen, jossa on käytössä ADB TCP/IP -tilassa."
# game/android.rpy:48
old "Disconnects from an Android device running ADB in TCP/IP mode."
new "Katkaisee yhteyden Android-laitteeseen, jossa on käytössä ADB TCP/IP -tila."
# game/android.rpy:164
old "{a=%s}%s{/a}"
new "{a=%s}%s{/a}"
# game/android.rpy:176
old "QUESTION"
new "KYSYMYS"
# game/android.rpy:445
old "Android: [project.current.name!q]"
new "Android: [project.current.name!q]"
# game/android.rpy:465
old "Emulation:"
new "Emulointi:"
# game/android.rpy:473
old "Phone"
new "Puhelin"
# game/android.rpy:477
old "Tablet"
new "Tablettitietokone"
# game/android.rpy:481
old "Television / OUYA"
new "Televisio / OUYA"
# game/android.rpy:493
old "Build:"
new "Kokoa:"
# game/android.rpy:501
old "Install SDK & Create Keys"
new "Asenna SDK & Luo avaimet"
# game/android.rpy:505
old "Configure"
new "Muokkaa asetuksia"
# game/android.rpy:509
old "Build Package"
new "Kokoamispaketti:"
# game/android.rpy:513
old "Build & Install"
new "Kokoa & Asenna"
# game/android.rpy:524
old "Other:"
new "Muu:"
# game/android.rpy:532
old "Remote ADB Connect"
new "Langaton ADB-yhdistäminen:"
# game/android.rpy:536
old "Remote ADB Disconnect"
new "Langaton ADB-katkaisu:"
# game/android.rpy:569
old "Before packaging Android apps, you'll need to download RAPT, the Ren'Py Android Packaging Tool. Would you like to download RAPT now?"
new "Ennen Android-sovellusten pakkausta, sinun on ladattava RAPT (Ren'Py Android Packaging Tool). Haluatko ladata RAPT:in nyt?"
# game/android.rpy:615
old "Remote ADB Address"
new "Langaton ADB-osoite"
# game/android.rpy:615
old "Please enter the IP address and port number to connect to, in the form \"192.168.1.143:5555\". Consult your device's documentation to determine if it supports remote ADB, and if so, the address and port to use."
new "Syötä yhdistettävän kohteen IP-osoite ja porttinumero, esimerkin \"192.168.1.143:5555\" mukaisesti. Selvitä laitteesi tiedoista kykeneekö se langattomaan ADB:hen, ja jos näin on, käytettävä osoite ja portti."
# game/android.rpy:627
old "Invalid remote ADB address"
new "Langaton ADB-osoite ei kelpaa."
# game/android.rpy:627
old "The address must contain one exactly one ':'."
new "Osoitteessa on oltava yksi, ja vain yksi, ':'."
# game/android.rpy:631
old "The host may not contain whitespace."
new "Isäntä ei voi sisältää välilyöntejä."
# game/android.rpy:637
old "The port must be a number."
new "Portin on oltava numero."
translate finnish strings:
# game/android.rpy:46
old "Builds the Android package, installs it on an Android device connected to your computer, then launches the app on your device."
new "Kokoaa Android-paketin, asentaa sen tietokoneeseen kytkettyyn Android-laitteeseen ja käynnistää sovelluksen laitteessa."
# game/android.rpy:50
old "Retrieves the log from the Android device and writes it to a file."
new "Noutaa lokin Android-laitteesta ja kirjoittaa sen tiedostoon."
# game/android.rpy:240
old "Copying Android files to distributions directory."
new "Kopioidaan Android-tiedostoja jakelukansioon."
# game/android.rpy:341
old "Television"
new "Televisio"
# game/android.rpy:377
old "Build, Install & Launch"
new "Kokoa, Asenna & Suorita"
# game/android.rpy:404
old "Logcat"
new "Logcat"
# game/android.rpy:538
old "Retrieving logcat information from device."
new "Noudetaan logcat-informaatiota laitteesta."
@@ -1,7 +0,0 @@
translate finnish strings:
# game/choose_directory.rpy:73
old "Ren'Py was unable to run python with tkinter to choose the directory. Please install the python-tk or tkinter package."
new "Ren'Py ei kyennyt suorittamaan pythonia tkinterillä valitakseen kansion. Ole hyvä ja asenna python-tk tai tkinter-paketti."
-50
View File
@@ -1,50 +0,0 @@
translate finnish strings:
# game/choose_theme.rpy:303
old ""
new ""
# game/choose_theme.rpy:368
old "Display"
new "Näyttö"
# game/choose_theme.rpy:369
old "Window"
new "Ikkuna"
# game/choose_theme.rpy:370
old "Fullscreen"
new "Koko näyttö"
# game/choose_theme.rpy:371
old "Planetarium"
new "Planetaario"
# game/choose_theme.rpy:378
old "Sound Volume"
new "Ääniefektien voimakkuus"
# game/choose_theme.rpy:412
old "Choose Theme"
new "Valitse teema"
# game/choose_theme.rpy:425
old "Theme"
new "Teema"
# game/choose_theme.rpy:449
old "Color Scheme"
new "Värikartta"
# game/choose_theme.rpy:480
old "Continue"
new "Jatka"
translate finnish strings:
# game/choose_theme.rpy:303
old "Could not change the theme. Perhaps options.rpy was changed too much."
new "Teemaa ei voitu vaihtaa. Kenties options.rpy:tä muutettiin liikaa."
-554
View File
@@ -1,554 +0,0 @@
translate finnish strings:
# renpy/common/00action_file.rpy:142
old "%b %d, %H:%M"
new "%b %d, %H:%M"
# renpy/common/00action_file.rpy:621
old "Quick save complete."
new "Pikatallennus suoritettu."
translate finnish strings:
# renpy/common/00console.rpy:179
old "%(version)s console, originally by Shiz, C, and delta.\n"
new "%(version)n konsoli, alunperin tehneet Shiz, C ja delta.\n"
# renpy/common/00console.rpy:180
old "Press <esc> to exit console. Type help for help.\n"
new "Paina <esc> poistuaksesi konsolista. Käytä komentoa help saadaksesi apua."
# renpy/common/00console.rpy:184
old "Ren'Py script enabled."
new "Ren'Py-skriptikieli käytössä."
# renpy/common/00console.rpy:186
old "Ren'Py script disabled."
new "Ren'Py-skriptikieli poissa käytöstä."
# renpy/common/00console.rpy:392
old "help: show this help"
new "help: näytä tämä apuviesti"
# renpy/common/00console.rpy:397
old "commands:\n"
new "komennot:\n"
# renpy/common/00console.rpy:407
old " <renpy script statement>: run the statement\n"
new " <renpy script-väite>: suorita väite\n"
# renpy/common/00console.rpy:409
old " <python expression or statement>: run the expression or statement"
new " <python ekspressio tai väite>: suorita ekspressio tai väite"
# renpy/common/00console.rpy:417
old "clear: clear the console history"
new "clear: tyhjennä konsolin historia"
# renpy/common/00console.rpy:421
old "exit: exit the console"
new "exit: poistu konsolista"
# renpy/common/00console.rpy:429
old "load <slot>: loads the game from slot"
new "load <tallennuspaikka>: lataa pelin halutusta tallennuspaikasta"
# renpy/common/00console.rpy:442
old "save <slot>: saves the game in slot"
new "save <tallennuspaikka>: tallentaa pelin tallennuspaikkaan"
# renpy/common/00console.rpy:453
old "reload: reloads the game, refreshing the scripts"
new "reload: lataa pelin uudelleen, päivittäen skriptit"
# renpy/common/00console.rpy:461
old "watch <expression>: watch a python expression"
new "watch <ekspressio>: tarkkaile python-ekspressiota"
# renpy/common/00console.rpy:470
old "unwatch <expression>: stop watching an expression"
new "unwatch <ekspressio>: lakkaa tarkkailemasta ekspressiota"
# renpy/common/00console.rpy:478
old "unwatchall: stop watching all expressions"
new "unwatchall: lopeta kaikkien ekspressioiden tarkkailu"
# renpy/common/00console.rpy:484
old "jump <label>: jumps to label"
new "jump <tunnus>: hyppää 'script.rpy'-tiedosto(i)ssa olevaan, tunnuksella merkittyyn kohtaan"
translate finnish strings:
# renpy/common/00gallery.rpy:561
old "Image [index] of [count] locked."
new ""
# renpy/common/00gallery.rpy:581
old "prev"
new "edellinen"
# renpy/common/00gallery.rpy:582
old "next"
new "seuraava"
# renpy/common/00gallery.rpy:583
old "slideshow"
new "diaesitys"
# renpy/common/00gallery.rpy:584
old "return"
new "palaa"
translate finnish strings:
# renpy/common/00gltest.rpy:68
old "Graphics Acceleration"
new "Grafiikkakiihdytys"
# renpy/common/00gltest.rpy:72
old "Automatically Choose"
new "Valitse automaattisesti"
# renpy/common/00gltest.rpy:77
old "Force Angle/DirectX Renderer"
new "Pakota Angle/DirectX-renderöinti"
# renpy/common/00gltest.rpy:81
old "Force OpenGL Renderer"
new "Pakota OpenGL-renderöinti"
# renpy/common/00gltest.rpy:85
old "Force Software Renderer"
new "Pakota Software-renderöinti"
# renpy/common/00gltest.rpy:91
old "Changes will take effect the next time this program is run."
new "Muutokset tulevat voimaan, kun käynnistät ohjelman uudelleen."
# renpy/common/00gltest.rpy:95
old "Quit"
new "Poistu"
# renpy/common/00gltest.rpy:100
old "Return"
new "Palaa"
# renpy/common/00gltest.rpy:130
old "Performance Warning"
new "Suorituskyvyn varoitus"
# renpy/common/00gltest.rpy:135
old "This computer is using software rendering."
new "Tietokone käyttää software-renderöintiä."
# renpy/common/00gltest.rpy:137
old "This computer is not using shaders."
new "Tietokone ei käytä varjostimia."
# renpy/common/00gltest.rpy:139
old "This computer is displaying graphics slowly."
new "Tietokone näyttää grafiikkaa hitaasti."
# renpy/common/00gltest.rpy:141
old "This computer has a problem displaying graphics: [problem]."
new "Tietokoneella on ongelmia grafiikan näyttämisessä: [problem]"
# renpy/common/00gltest.rpy:146
old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display. Updating DirectX could fix this problem."
new "Sen grafiikka-ajurit voivat olla vanhentuneita tai ne saattavat toimia väärin. Tämä voi johtaa hitaaseen tai väärään grafiikan esittämiseen. DirectX:n päivittäminen saattaa korjata ongelman."
# renpy/common/00gltest.rpy:148
old "Its graphics drivers may be out of date or not operating correctly. This can lead to slow or incorrect graphics display."
new "Sen grafiikka-ajurit voivat olla vanhentuneita tai ne saattavat toimia väärin. Tämä voi johtaa hitaaseen tai väärään grafiikan esittämiseen."
# renpy/common/00gltest.rpy:153
old "Update DirectX"
new "Päivitä DirectX"
# renpy/common/00gltest.rpy:159
old "Continue, Show this warning again"
new "Jatka, näytä tämä varoitus uudelleen"
# renpy/common/00gltest.rpy:163
old "Continue, Don't show warning again"
new "Jatka, älä näytä tätä varoitusta enää uudelleen"
# renpy/common/00gltest.rpy:189
old "Updating DirectX."
new "Päivitetään DirectX:ää."
# renpy/common/00gltest.rpy:193
old "DirectX web setup has been started. It may start minimized in the taskbar. Please follow the prompts to install DirectX."
new "DirectX verkkoasennus on alkanut. Se voi olla aluksi minimisoituna työkalupalkilla. Seuraa ohjeita asentaaksesi DirectX:n."
# renpy/common/00gltest.rpy:197
old "{b}Note:{/b} Microsoft's DirectX web setup program will, by default, install the Bing toolbar. If you do not want this toolbar, uncheck the appropriate box."
new "{b}Huomaa:{/b} Microsoftin DirectX verkkoasennusohjelma asentaa, oletusarvoisesti, Bing-työkalupalkin. Jos et halua tätä työkalupalkkia, poista valinta oikeasta laatikosta."
# renpy/common/00gltest.rpy:201
old "When setup finishes, please click below to restart this program."
new "Kun asennus on valmis, klikkaa alhaalta käynnistääksesi tämän ohjelman uudelleen."
# renpy/common/00gltest.rpy:203
old "Restart"
new "Käynnistä uudelleen"
translate finnish strings:
# renpy/common/00keymap.rpy:199
old "Saved screenshot as %s."
new "Näytönkaappaus tallennettu nimellä %s."
translate finnish strings:
# renpy/common/00layout.rpy:444
old "Are you sure?"
new "Oletko varma?"
# renpy/common/00layout.rpy:445
old "Are you sure you want to delete this save?"
new "Oletko varma, että haluat poistaa tämän tallennuksen?"
# renpy/common/00layout.rpy:446
old "Are you sure you want to overwrite your save?"
new "Oletko varma, että haluat korvata tallennuksen uudella?"
# renpy/common/00layout.rpy:447
old "Loading will lose unsaved progress.\nAre you sure you want to do this?"
new "Lataamalla tallennuksen menetät tallentamattoman edistyksen.\nOletko varma, että haluat tehdä näin?"
# renpy/common/00layout.rpy:448
old "Are you sure you want to quit?"
new "Haluatko varmasti lopettaa?"
# renpy/common/00layout.rpy:449
old "Are you sure you want to return to the main menu?\nThis will lose unsaved progress."
new "Haluatko varmasti palata päävalikkoon?\nMenetät kaikki tallentamattomat tiedot."
# renpy/common/00layout.rpy:450
old "Are you sure you want to begin skipping?"
new "Oletko varma, että haluat käyttää skippausta?"
# renpy/common/00layout.rpy:451
old "Are you sure you want to skip to the next choice?"
new "Oletko varma, että haluat skipata seuraavaan valintaan?"
# renpy/common/00layout.rpy:452
old "Are you sure you want to skip to unseen dialogue or the next choice?"
new "Oletko varma, että haluat skipata uuteen dialogiin tai seuraavaan valintaan?"
translate finnish strings:
# renpy/common/00library.rpy:149
old "Skip Mode"
new "Skippaustila"
# renpy/common/00library.rpy:152
old "Fast Skip Mode"
new "Pikaskippaustila"
translate finnish strings:
# renpy/common/00preferences.rpy:373
old "Self-voicing enabled. Press 'v' to disable."
new "Tietokoneen ääninäyttely käytössä. Paina 'v' lopettaaksesi."
translate finnish strings:
# renpy/common/00updater.rpy:1377
old "Updater"
new "Päivittäjä"
# renpy/common/00updater.rpy:1386
old "This program is up to date."
new "Käytät jo uuinta versiota."
# renpy/common/00updater.rpy:1388
old "[u.version] is available. Do you want to install it?"
new "[u.version] on saatavilla. Haluatko asentaa sen?"
# renpy/common/00updater.rpy:1390
old "Preparing to download the updates."
new "Valmistellaan päivitysten lataamista."
# renpy/common/00updater.rpy:1392
old "Downloading the updates."
new "Ladataan päivityksiä."
# renpy/common/00updater.rpy:1394
old "Unpacking the updates."
new "Puretaan päivityksiä."
# renpy/common/00updater.rpy:1398
old "The updates have been installed. The program will restart."
new "Päivitykset on asennettu. Ohjelma käynnistyy nyt uudelleen."
# renpy/common/00updater.rpy:1400
old "The updates have been installed."
new "Päivitykset on asennettu."
# renpy/common/00updater.rpy:1402
old "The updates were cancelled."
new "Päivitykset peruttiin."
translate finnish strings:
# renpy/common/_compat/gamemenu.rpym:198
old "Empty Slot."
new "Tyhjä paikka."
# renpy/common/_compat/gamemenu.rpym:355
old "Previous"
new "Edellinen"
# renpy/common/_compat/gamemenu.rpym:362
old "Next"
new "Seuraava"
translate finnish strings:
# renpy/common/_compat/preferences.rpym:428
old "Joystick Mapping"
new "Peliohjaimen näppäimet"
translate finnish strings:
# renpy/common/_developer/developer.rpym:65
old "Developer Menu"
new "Kehittäjävalikko"
# renpy/common/_developer/developer.rpym:67
old "Reload Game (Shift+R)"
new "Käynnistä peli uudelleen (Shift+R)"
# renpy/common/_developer/developer.rpym:69
old "Console (Shift+O)"
new "Konsoli (Shift+O)"
# renpy/common/_developer/developer.rpym:71
old "Variable Viewer"
new "Muuttujat"
# renpy/common/_developer/developer.rpym:73
old "Theme Test"
new "Teematesti"
# renpy/common/_developer/developer.rpym:75
old "Image Location Picker"
new "Kuvan sijainnin selvitin"
# renpy/common/_developer/developer.rpym:77
old "Filename List"
new "Tiedostonimilista"
# renpy/common/_developer/developer.rpym:81
old "Show Image Load Log"
new "Näytä kuvanlatausloki"
# renpy/common/_developer/developer.rpym:84
old "Hide Image Load Log"
new "Piilota kuvanlatausloki"
# renpy/common/_developer/developer.rpym:150
old "No variables have changed since the game started."
new "Yksikään muuttuja ei ole muuttunut pelin alkamisen jälkeen."
# renpy/common/_developer/developer.rpym:153
old "Return to the developer menu"
new "Palaa kehittäjävalikkoon"
# renpy/common/_developer/developer.rpym:385
old "Rectangle: %r"
new "Suorakulmio: %r"
# renpy/common/_developer/developer.rpym:390
old "Mouse position: %r"
new "Hiiren sijainti: %r"
# renpy/common/_developer/developer.rpym:392
old "Right-click or escape to quit."
new "Paina Esc tai hiiren oikeaa näppäintä poistuaksesi."
# renpy/common/_developer/developer.rpym:443
old "Done"
new "Valmis"
translate finnish strings:
# renpy/common/_developer/inspector.rpym:46
old "Displayable Inspector"
new "Näkyvien objektien tutkija"
# renpy/common/_developer/inspector.rpym:52
old "Nothing to inspect."
new "Ei tutkittavaa."
# renpy/common/_developer/inspector.rpym:70
old "Size"
new "Koko"
# renpy/common/_developer/inspector.rpym:74
old "Style"
new "Tyyli"
# renpy/common/_developer/inspector.rpym:80
old "Location"
new "Sijainti"
# renpy/common/_developer/inspector.rpym:142
old "Inspecting Styles of [displayable_name!q]"
new "Tutkitaan [displayable_name!q]n tyylejä"
# renpy/common/_developer/inspector.rpym:155
old "displayable:"
new "näkyvä objekti:"
# renpy/common/_developer/inspector.rpym:162
old " (no properties affect the displayable)"
new " (mitkään ominaisuudet eivät vaikuta objektiin)"
# renpy/common/_developer/inspector.rpym:164
old " (default properties omitted)"
new " (perusominaisuudet sivuutettu)"
# renpy/common/_developer/inspector.rpym:206
old "<repr() failed>"
new "<repr() epäonnistui>"
translate finnish strings:
# renpy/common/_errorhandling.rpym:451
old "An exception has occurred."
new "Odottamaton virhe on tapahtunut."
# renpy/common/_errorhandling.rpym:477
old "Rollback"
new "Palaa edelliseen tilaan"
# renpy/common/_errorhandling.rpym:479
old "Attempts a roll back to a prior time, allowing you to save or choose a different choice."
new "Yrittää palata ajassa taaksepäin, antaen sinun tallentaa tai tehdä eri valinnan."
# renpy/common/_errorhandling.rpym:482
old "Ignore"
new "Sivuuta"
# renpy/common/_errorhandling.rpym:484
old "Ignores the exception, allowing you to continue. This often leads to additional errors."
new "Sivuuttaa poikkeuksen, antaen sinun jatkaa. Tämä johtaa usein uusiin virheisiin."
# renpy/common/_errorhandling.rpym:487
old "Reload"
new "Lataa uudelleen"
# renpy/common/_errorhandling.rpym:489
old "Reloads the game from disk, saving and restoring game state if possible."
new "Lataa pelin uudelleen muistista, tallentaen ja palauttaen pelitilan jos mahdollista."
# renpy/common/_errorhandling.rpym:491
old "Open Traceback"
new "Avaa virheenjäljitystoiminto"
# renpy/common/_errorhandling.rpym:493
old "Opens the traceback.txt file in a text editor."
new "Avaa traceback.txt-tiedoston tekstieditorissa."
# renpy/common/_errorhandling.rpym:499
old "Quits the game."
new "Lopettaa pelin."
# renpy/common/_errorhandling.rpym:526
old "Parsing the script failed."
new "Skriptin jäsennys epäonnistui."
# renpy/common/_errorhandling.rpym:553
old "Open Parse Errors"
new "Avaa jäsennysvirheet"
# renpy/common/_errorhandling.rpym:555
old "Opens the errors.txt file in a text editor."
new "Avaa errors.txt-tiedoston tekstieditorissa."
translate finnish strings:
# renpy/common/_layout/classic_load_save.rpym:170
old "a"
new "a"
# renpy/common/_layout/classic_load_save.rpym:179
old "q"
new "q"
translate finnish strings:
# renpy/common/00preferences.rpy:370
old "Clipboard voicing enabled. Press 'shift+C' to disable."
new "Leikepöydän teksti luetaan nyt ääneen. Paina 'shift+c' lopettaaksesi toimnnon käytön."
translate finnish strings:
# renpy/common/00updater.rpy:362
old "The Ren'Py Updater is not supported on mobile devices."
new "Mobiililaitteet eivät tue Ren'Py Updater -toimintoa."
# renpy/common/00updater.rpy:481
old "An error is being simulated."
new "Stimuloidaan havaittua ongelmaa."
# renpy/common/00updater.rpy:657
old "Either this project does not support updating, or the update status file was deleted."
new "Tämä projekti ei tue päivittämistä tai päivityksen statustiedosto poistettiin."
# renpy/common/00updater.rpy:671
old "This account does not have permission to perform an update."
new "Tällä käyttäjällä ei ole oikeutta päivityksen suorittamiseen."
# renpy/common/00updater.rpy:674
old "This account does not have permission to write the update log."
new "Tällä käyttäjällä ei ole oikeutta kirjoittaa dataa päivityslokiin."
# renpy/common/00updater.rpy:699
old "Could not verify update signature."
new "Päivityksen allekirjoitusta ei voitu vahvistaa."
# renpy/common/00updater.rpy:970
old "The update file was not downloaded."
new "Päivitystiedostoa ei ladattu."
# renpy/common/00updater.rpy:988
old "The update file does not have the correct digest - it may have been corrupted."
new "Päivitystiedosto ei sisällä oikeaa tiivistelmää - se on saattanut korruptoitua."
# renpy/common/00updater.rpy:1044
old "While unpacking {}, unknown type {}."
new "Purettaessa {}, tuntematon tyyppi {}."
translate finnish strings:
# renpy/common/_developer/developer.rpym:425
old "Rectangle copied to clipboard."
new "Suorakulmio kopioitu leikepöydälle."
# renpy/common/_developer/developer.rpym:428
old "Position copied to clipboard."
new "Sijainti kopioitu leikepöydälle."
-39
View File
@@ -1,39 +0,0 @@
translate finnish strings:
# game/distribute.rpy:335
old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
new "Ohjelman kokoaminen epäonnistui:\n\nbuild.directory_name -muuttuja ei saa sisältää välilyöntejä, pilkkuja tai puolipilkkuja."
# game/distribute.rpy:381
old "No packages are selected, so there's nothing to do."
new "Yhtäkään pakettia ei valittu, joten mitään ei ole tehtävissä."
# game/distribute.rpy:386
old "Scanning project files..."
new "Skannataan projektin tiedostoja..."
# game/distribute.rpy:396
old "Scanning Ren'Py files..."
new "Skannataan Ren'Py-tiedostoja..."
# game/distribute.rpy:444
old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
new "Kaikki paketit on koottu.\n\nLupainformaation läsnäolon vuoksi Linux- ja Macintosh-sovellusten pakkaamista Windows-järjestelmässä ei tueta."
# game/distribute.rpy:568
old "Archiving files..."
new "Arkistoidaan tiedostoja..."
# game/distribute.rpy:832
old "Writing the [variant] [format] package."
new "Kirjoitetaan [variant] [format]-pakettia."
# game/distribute.rpy:845
old "Making the [variant] update zsync file."
new "Luodaan [variant] zsync-päivitystiedostoa."
# game/distribute.rpy:941
old "Processed {b}[complete]{/b} of {b}[total]{/b} files."
new "Käsitelty {b}[complete]{/b}/{b}[total]{/b}:sta tiedostosta."
@@ -1,66 +0,0 @@
translate finnish strings:
# game/distribute_gui.rpy:157
old "Build Distributions: [project.current.name!q]"
new "Kokoa ohjelma levitykseen: [project.current.name!q]"
# game/distribute_gui.rpy:171
old "Directory Name:"
new "Kansion nimi:"
# game/distribute_gui.rpy:175
old "Executable Name:"
new "Suoritettavan tiedoston nimi:"
# game/distribute_gui.rpy:185
old "Actions:"
new "Toiminnot:"
# game/distribute_gui.rpy:193
old "Edit options.rpy"
new "Muokkaa options.rpy-tiedostoa"
# game/distribute_gui.rpy:194
old "Refresh"
new "Päivitä"
# game/distribute_gui.rpy:211
old "Build Packages:"
new "Kokoa paketteja:"
# game/distribute_gui.rpy:225
old "Build Updates"
new "Kokoa päivityksiä"
# game/distribute_gui.rpy:229
old "Build"
new "Kokoa"
# game/distribute_gui.rpy:236
old "Errors were detected when running the project. Please ensure the project runs without errors before building distributions."
new "Virheitä havaittu projektia suoritettaessa. Varmista, että projekti toimii moitteetta ennen kuin kokoat ohjelman."
# game/distribute_gui.rpy:253
old "Your project does not contain build information. Would you like to add build information to the end of options.rpy?"
new "Projektisi ei sisällä kokoamisinformaatiota. Haluatko lisätä kokoamisinormaation options.rpy-tiedoston loppuun?"
translate finnish strings:
# game/distribute_gui.rpy:194
old "Add from clauses to calls, once"
new ""
# game/distribute_gui.rpy:231
old "Options:"
new "Valinnat:"
# game/distribute_gui.rpy:238
old "Add from clauses to calls"
new ""
# game/distribute_gui.rpy:247
old "Adding from clauses to call statements that do not have them."
new ""
-55
View File
@@ -1,55 +0,0 @@
translate finnish strings:
# game/editor.rpy:150
old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input."
new "{b}Suositeltu.{/b} Helppokäyttöinen beta-asteella oleva tekstieditori, joka sisältää kehitystä helpottavia toimintoja. Toistaiseksi Editrasta puuttuu täysin kiinalaisen, japanilaisen ja korealaisen tekstin kannatus."
# game/editor.rpy:151
old "{b}Recommended.{/b} A beta editor with an easy to use interface and features that aid in development, such as spell-checking. Editra currently lacks the IME support required for Chinese, Japanese, and Korean text input. On Linux, Editra requires wxPython."
new "{b}Suositeltu.{/b} Helppokäyttöinen beta-asteella oleva tekstieditori, joka sisältää kehitystä helpottavia toimintoja. Toistaiseksi Editrasta puuttuu täysin kiinalaisen, japanilaisen ja korealaisen tekstin kannatus."
# game/editor.rpy:167
old "This may have occured because wxPython is not installed on this system."
new "Tämä saattoi tapahtua, koska wxPythonia ei ole asennettu järjestelmään."
# game/editor.rpy:169
old "Up to 22 MB download required."
new "22 MB lataus vaaditaan"
# game/editor.rpy:182
old "A mature editor that requires Java."
new "Edistynyt editori, joka vaatii Javan."
# game/editor.rpy:182
old "1.8 MB download required."
new "1.8 MB lataus vaaditaan."
# game/editor.rpy:182
old "This may have occured because Java is not installed on this system."
new "Tämä saattoi tapahtua, koska Javaa ei ole asennettu."
# game/editor.rpy:191
old "Invokes the editor your operating system has associated with .rpy files."
new "Käyttää editoria, jota käyttöjärjestelmäsi käyttää .rpy-tiedostojen kanssa."
# game/editor.rpy:207
old "Prevents Ren'Py from opening a text editor."
new "Estää Ren'Py-ohjelmaa avaamasta tekstieditoria."
# game/editor.rpy:359
old "An exception occured while launching the text editor:\n[exception!q]"
new "Virhe käynnistäessä tekstieditoria:\n[exception!q]"
# game/editor.rpy:457
old "Select Editor"
new "Valitse editori"
# game/editor.rpy:472
old "A text editor is the program you'll use to edit Ren'Py script files. Here, you can select the editor Ren'Py will use. If not already present, the editor will be automatically downloaded and installed."
new "Tekstieditori on ohjelma, jota käytät Ren'Py-skriptitiedostojen muokkaamiseen. Täällä voit valita, mitä editoria Ren'Py käyttää. Jos valitsemaasi editoria ei vielä ole asennettu, se ladataan ja asennetaan automaattisesti."
# game/editor.rpy:494
old "Cancel"
new "Peruuta"
-118
View File
@@ -1,118 +0,0 @@
translate finnish strings:
# game/front_page.rpy:35
old "Open [text] directory."
new "Avaa [text] sijainti."
# game/front_page.rpy:93
old "refresh"
new "päivitä"
# game/front_page.rpy:120
old "+ Create New Project"
new "+ Luo uusi projekti"
# game/front_page.rpy:132
old "Launch Project"
new "Käynnistä projekti"
# game/front_page.rpy:148
old "[p.name!q] (template)"
new "[p.name!q] (pohja)"
# game/front_page.rpy:150
old "Select project [text]."
new "Valitse projekti [text]."
# game/front_page.rpy:166
old "Tutorial"
new "Opas"
# game/front_page.rpy:167
old "The Question"
new "The Question -esimerkkipeli"
# game/front_page.rpy:183
old "Active Project"
new "Aktiivinen projekti"
# game/front_page.rpy:191
old "Open Directory"
new "Avaa sijainti"
# game/front_page.rpy:196
old "game"
new "game"
# game/front_page.rpy:197
old "base"
new "base"
# game/front_page.rpy:203
old "Edit File"
new "Muokkaa tiedostoa"
# game/front_page.rpy:211
old "All script files"
new "Kaikki skriptitiedostot"
# game/front_page.rpy:220
old "Navigate Script"
new "Navigoi skriptiä"
# game/front_page.rpy:231
old "Check Script (Lint)"
new "Tarkista skripti (Lint)"
# game/front_page.rpy:232
old "Change Theme"
new "Vaihda teemaa"
# game/front_page.rpy:233
old "Delete Persistent"
new "Poista pysyvästi tallennettu data"
# game/front_page.rpy:234
old "Force Recompile"
new "Pakota uudelleenkokoaminen"
# game/front_page.rpy:242
old "Build Distributions"
new "Kokoa jakeluun"
# game/front_page.rpy:244
old "Android"
new "Android"
# game/front_page.rpy:245
old "Generate Translations"
new "Luo käännöksiä"
# game/front_page.rpy:246
old "Extract Dialogue"
new "Kopioi dialogi"
# game/front_page.rpy:262
old "Checking script for potential problems..."
new "Tarkista skripti mahdollisten virheiden varalta..."
# game/front_page.rpy:277
old "Deleting persistent data..."
new "Poistetaan pysyvästi tallennettua dataa..."
# game/front_page.rpy:285
old "Recompiling all rpy files into rpyc files..."
new "Kasataan kaikista .rpy-tiedostoista .rpyc-tiedostoja..."
translate finnish strings:
# game/front_page.rpy:198
old "images"
new "kuvat"
# game/front_page.rpy:246
old "iOS"
new "iOS"
-79
View File
@@ -1,79 +0,0 @@
translate finnish strings:
# game/interface.rpy:107
old "Documentation"
new "Dokumentit"
# game/interface.rpy:108
old "Ren'Py Website"
new "Ren'Py:n verkkosivut"
# game/interface.rpy:109
old "Ren'Py Games List"
new "Lista Ren'Py-peleistä"
# game/interface.rpy:110
old "About"
new "Tietoja"
# game/interface.rpy:117
old "update"
new "päivitä"
# game/interface.rpy:119
old "preferences"
new "asetukset"
# game/interface.rpy:120
old "quit"
new "poistu"
# game/interface.rpy:192
old "Yes"
new "Kyllä"
# game/interface.rpy:194
old "No"
new "Ei"
# game/interface.rpy:229
old "Due to package format limitations, non-ASCII file and directory names are not allowed."
new "Pakettiformaatin rajoitusten vuoksi, ei-ASCII tiedostot ja kansion nimet eivät ole sallittuja."
# game/interface.rpy:321
old "ERROR"
new "VIRHE"
# game/interface.rpy:350
old "While [what!q], an error occured:"
new "Kun [what!q], tapahtui virhe."
# game/interface.rpy:350
old "[exception!q]"
new "[exception!q]"
# game/interface.rpy:369
old "Text input may not contain the {{ or [[ characters."
new "Teksti ei voi sisältää {{ tai [[-merkkejä."
# game/interface.rpy:374
old "File and directory names may not contain / or \\."
new "Tiedostot ja kansioiden nimet eivät voi sisältää / tai \\-merkkejä."
# game/interface.rpy:380
old "File and directory names must consist of ASCII characters."
new "Tiedostojen ja kansioiden nimet saavat koostua vain ASCII-merkeistä."
# game/interface.rpy:401
old "INFORMATION"
new "TIETOA"
# game/interface.rpy:448
old "PROCESSING"
new "KÄSITELLÄÄN"
# game/interface.rpy:478
old "CHOICE"
new "VALITSE"
-99
View File
@@ -1,99 +0,0 @@
translate finnish strings:
# game/ios.rpy:28
old "To build iOS packages, please download renios, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
new "Luodaksesi iOS-sovelluksia, ole hyvä ja lataa renios, pura se, ja aseta se Ren'Py kansioon. Tämän jälkeen käynnistä Ren'Py uudelleen."
# game/ios.rpy:29
old "The directory in where Xcode projects will be placed has not been selected. Choose 'Select Directory' to select it."
new "Kansiota, johon Xcode-projektit asetetaan, ei ole valittu. Klikkaa 'Valitse kansio' valitaksesi sen."
# game/ios.rpy:30
old "There is no Xcode project corresponding to the current Ren'Py project. Choose 'Create Xcode Project' to create one."
new "Nykyistä Ren'Py-projektia vastaavaa Xcode-projektia ei löydy. Klikkaa 'Luo Xcode-projekti' luodaksesi sellaisen."
# game/ios.rpy:31
old "An Xcode project exists. Choose 'Update Xcode Project' to update it with the latest game files, or use Xcode to build and install it."
new "Xcode-projekti on jo olemassa. Klikkaa 'Päivitä Xcode-projekti' päivittääksesi sen uusimmilla pelin tiedostoilla, tai käytä Xcodea kootaksesi ja asentaaksesi sen."
# game/ios.rpy:33
old "Attempts to emulate an iPhone.\n\nTouch input is emulated through the mouse, but only when the button is held down."
new "Ren'Py pyrkii emuloimaan iPhonea.\n\nKosketusta emuloidaan hiirellä, mutta vain kun nappia pidetään pohjassa."
# game/ios.rpy:34
old "Attempts to emulate an iPad.\n\nTouch input is emulated through the mouse, but only when the button is held down."
new "Ren'Py pyrkii emuloimaan iPadia.\n\nKosketusta emuloidaan hiirellä, mutta vain kun nappia pidetään pohjassa."
# game/ios.rpy:36
old "Selects the directory where Xcode projects will be placed."
new "Valitsee kansion, johon Xcode-projektit sijoitetaan."
# game/ios.rpy:37
old "Creates an Xcode project corresponding to the current Ren'Py project."
new "Luo Xcode-projektin tällä hetkellä valittuna olevasta Ren'Py-projektista."
# game/ios.rpy:38
old "Updates the Xcode project with the latest game files. This must be done each time the Ren'Py project changes."
new "Päivittää Xcode-projektin uusimmilla pelitiedostoilla. Tämä on tehtävä joka kerta Ren'Py-projektin muuttuessa."
# game/ios.rpy:39
old "Opens the Xcode project in Xcode."
new "Avaa Xcode-projektin Xcodessa."
# game/ios.rpy:41
old "Opens the directory containing Xcode projects."
new "Avaa Xcode-projektit sisältävän kansion."
# game/ios.rpy:126
old "The Xcode project already exists. Would you like to rename the old project, and replace it with a new one?"
new "Tämänniminen Xcode-projekti on jo olemassa. Haluatko nimetä vanhan projektin uudelleen ja korvata sen uudella?"
# game/ios.rpy:211
old "iOS: [project.current.name!q]"
new "iOS: [project.current.name!q]"
# game/ios.rpy:240
old "iPhone"
new "iPhone"
# game/ios.rpy:244
old "iPad"
new "iPad"
# game/ios.rpy:264
old "Select Xcode Projects Directory"
new "Valitse Xcode-projektikansio"
# game/ios.rpy:268
old "Create Xcode Project"
new "Luo Xcode-projekti"
# game/ios.rpy:272
old "Update Xcode Project"
new "Päivitä Xcode-projekti"
# game/ios.rpy:277
old "Launch Xcode"
new "Käynnistä Xcode"
# game/ios.rpy:312
old "Open Xcode Projects Directory"
new "Avaa Xcode-projektikansio"
# game/ios.rpy:345
old "Before packaging iOS apps, you'll need to download renios, Ren'Py's iOS support. Would you like to download renios now?"
new "Ennen iOS-sovellusten pakkaamista sinun on ladattava renios, Ren'Py:n iOS-tuki. Haluaisitko ladata reniosin nyt?"
# game/ios.rpy:354
old "XCODE PROJECTS DIRECTORY"
new "XCODE-PROJEKTIKANSIO"
# game/ios.rpy:354
old "Please choose the Xcode Projects Directory using the directory chooser.\n{b}The directory chooser may have opened behind this window.{/b}"
new "Ole hyvä ja valitse Xcode-projektikansio käyttämällä resurssienhallintaa.\n{b}Kansion valinta on saattanut aueta tämän ikkunan taakse.{/b}"
# game/ios.rpy:359
old "Ren'Py has set the Xcode Projects Directory to:"
new "Ren'Py on asettanut Xcode-projektikansioksi:"

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