Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5ea9d436ce | |||
| c05e4e528e | |||
| e10488b77a | |||
| 86e0cb3331 | |||
| c6397c08af | |||
| f9db64231d | |||
| f3c3c67def | |||
| 6d316a9c78 | |||
| 6e7e68b31a | |||
| a24e6b2af1 | |||
| 597b01c26b | |||
| a262eb0f60 | |||
| 92006d237c | |||
| 1427336746 | |||
| c35ed8a7cd | |||
| 90f47eacf3 | |||
| ee093925f5 | |||
| f686a810a7 | |||
| e2a12284d5 | |||
| 10b4064a53 | |||
| f1ea5289aa | |||
| a26ed9c328 |
@@ -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
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
@@ -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
|
||||
@@ -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()
|
||||
@@ -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
|
||||
@@ -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' },
|
||||
)
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
cd images
|
||||
..\archiver.exe images *.png *.jpg
|
||||
@@ -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()
|
||||
@@ -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',
|
||||
)
|
||||
@@ -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.
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
lib\windows-i686\python.exe -OO renpy.py tutorial
|
||||
pause
|
||||
@@ -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
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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>
|
||||
@@ -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()
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -1,4 +0,0 @@
|
||||
import renpy
|
||||
|
||||
# Do nothing when the editor is invoked.
|
||||
Editor = renpy.editor.Editor
|
||||
@@ -1,4 +0,0 @@
|
||||
import renpy
|
||||
|
||||
# Pass the file off to the system editor (as determined by file associations).
|
||||
Editor = renpy.editor.SystemEditor
|
||||
@@ -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
|
||||
'''),
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 687 B |
|
Before Width: | Height: | Size: 96 B |
|
Before Width: | Height: | Size: 106 B |
|
Before Width: | Height: | Size: 2.8 KiB |
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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-----
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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",
|
||||
)
|
||||
|
||||
@@ -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"))
|
||||
@@ -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 "عودة"
|
||||
|
||||
@@ -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 تلقائياً. لكي تستعمل هذا الملف, اختر له تبويب وافتحه عبر ملف آخر."
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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 "استمرار"
|
||||
|
||||
@@ -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 "تم نسخ الموضع إلى الحافظة."
|
||||
|
||||
@@ -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 "إضافة بنود 'مِن' إلى أوامر الجلب التي لا تحتوي عليها."
|
||||
|
||||
@@ -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 "يمنع رينباي من فتح اي محرر نصوص"
|
||||
|
||||
@@ -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 "الصور"
|
||||
|
||||
@@ -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 "إختيار"
|
||||
|
||||
@@ -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 إلى:"
|
||||
|
||||
@@ -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 "قائمة الأسماء فارغة"
|
||||
|
||||
@@ -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 "لم يتم تحديد مجلد المشاريع, سيتم الإلغاء"
|
||||
|
||||
@@ -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 "صنع خانات فارغة للترجمات"
|
||||
|
||||
@@ -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 "هل قمت بعمل نسخة احتياطية من مشاريعك مؤخراً؟"
|
||||
|
||||
@@ -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
|
||||
@@ -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] في المجلد الرئيسي"
|
||||
|
||||
@@ -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 "أحدث نسخة طازجة من رينباي التجريبي, قد يحتوي على آخر مستجدات رينباي و قد لا يعمل مطلقاً"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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 ""
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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:"
|
||||
|
||||