Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8e7ffc881b | |||
| d9ccfb84c2 | |||
| 845d47dca9 | |||
| d654be1585 | |||
| 4896b15327 | |||
| 5ea9d436ce | |||
| c05e4e528e | |||
| e10488b77a | |||
| 86e0cb3331 | |||
| c6397c08af | |||
| f9db64231d | |||
| f3c3c67def | |||
| 6d316a9c78 | |||
| 6e7e68b31a | |||
| a24e6b2af1 | |||
| 597b01c26b | |||
| a262eb0f60 | |||
| 92006d237c | |||
| 1427336746 | |||
| c35ed8a7cd | |||
| 90f47eacf3 | |||
| ee093925f5 | |||
| f686a810a7 | |||
| e2a12284d5 | |||
| 10b4064a53 | |||
| f1ea5289aa | |||
| a26ed9c328 |
@@ -1,54 +0,0 @@
|
||||
*.rpyc
|
||||
*.rpyb
|
||||
*.rpymc
|
||||
*.pyc
|
||||
*.pyo
|
||||
|
||||
*~
|
||||
*.bak
|
||||
|
||||
saves
|
||||
tmp
|
||||
cache
|
||||
|
||||
log.txt
|
||||
errors.txt
|
||||
traceback.txt
|
||||
styles.txt
|
||||
|
||||
/build
|
||||
/dist
|
||||
/dists
|
||||
/renpy.app
|
||||
/jedit
|
||||
/lint.txt
|
||||
/renpy.code
|
||||
/testing*
|
||||
/screenshot*
|
||||
/Microsoft.VC90.CRT.manifest
|
||||
/console.exe
|
||||
/msvcr90.dll
|
||||
/python27.dll
|
||||
/renpy.exe
|
||||
/lib
|
||||
/lib.old
|
||||
/doc
|
||||
/.pydevproject
|
||||
/.pydevproject.bak
|
||||
/.project
|
||||
/.settings
|
||||
/LICENSE.txt
|
||||
/template/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
|
||||
|
||||
dl
|
||||
renpy/vc_version.py
|
||||
.externalToolBuilders
|
||||
@@ -0,0 +1,244 @@
|
||||
New in 4.3
|
||||
----------
|
||||
|
||||
Now, when the library first starts up, it tries calling the
|
||||
"splashscreen" label, if it exists. The splashscreen will not be
|
||||
called in the case of a full reset (known to the user as a return to
|
||||
the main menu).
|
||||
|
||||
Added a new text property, antialias, that controls the antialiasing
|
||||
of text. Also made the font property optionally take a comma-separated
|
||||
list of font names, which are searched for in the
|
||||
|
||||
Added a new class, DynamicCharacter, which is now the preferred way of
|
||||
having a character with a changable and/or user-input name.
|
||||
|
||||
A new random number generator has been implemented as
|
||||
renpy.random. This random number generator cooperates with rollback,
|
||||
always producing the same random numbers when a rollback occurs.
|
||||
|
||||
Added a set of UI functions, that allow the user to build up a user
|
||||
interface themselves. These could be useful when implementing more
|
||||
complex games, such as those that require the user to schedule a day
|
||||
in advance. Also new is a new imagebutton, a button consisting of two
|
||||
images.
|
||||
|
||||
Sticky postions have been implemented. Enabling this (using the
|
||||
variable config.sticky_positions) cause the at clause corresponding to
|
||||
a given character to be remembered, allowing the character to change
|
||||
emotion without changing places on the screen (or requiring a second
|
||||
at clause).
|
||||
|
||||
Rewrote the implementation of preferences, to clean up the code. Moved
|
||||
it into its own file, preferences.rpy. Also, made it possible for a
|
||||
user to add his own preferences into the system, although that isn't
|
||||
really recommended.
|
||||
|
||||
The various imagemap functions now have a new parameter, unselected,
|
||||
which gives an image to use when a hotspot is present but not
|
||||
hovered. This lets us distinguish between between hotspots that are
|
||||
present and exist, and hotspots that are totally absent. This could be
|
||||
used to implement something like an image gallery that only displays
|
||||
unlocked images.
|
||||
|
||||
Implemented config.keymap, which allows the changing of keys and mouse
|
||||
buttons that trigger various Ren'Py events.
|
||||
|
||||
There's now a new look for loading and saving games, that allows 10
|
||||
saves to be presented at once. I strongly recommend removing the
|
||||
library.file_page_length line at the start of your game scripts, if
|
||||
it exists.
|
||||
|
||||
Fixed a bug in sound.init that lead to crashes in some cases.
|
||||
|
||||
Fixed a bug in ast.Node.predict that was causing an exception when
|
||||
config.debug was turned on.
|
||||
|
||||
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]
|
||||
|
||||
Fixed several bugs with the archiver. This version just might actually
|
||||
work on Windows.
|
||||
|
||||
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,55 +0,0 @@
|
||||
==============================
|
||||
The Ren'Py Visual Novel Engine
|
||||
==============================
|
||||
|
||||
http://www.renpy.org
|
||||
|
||||
|
||||
Branches
|
||||
========
|
||||
|
||||
Ren'Py development takes place on two branches, ``master`` and
|
||||
``devel``, as well as the occasional feature branch.
|
||||
|
||||
Master
|
||||
-----
|
||||
|
||||
The master branch contains code that can be run using the libraries in
|
||||
the latest (release or pre-release) version of Ren'Py. It's used for
|
||||
bugfixes and features that do not require C or Cython code to
|
||||
implement.
|
||||
|
||||
After checking out master, run::
|
||||
|
||||
./after_checkout.sh <path-to-renpy>
|
||||
|
||||
to link in the libraries from the most recent Ren'Py. (On Windows, you
|
||||
will need to run this under msys or cygwin.)
|
||||
|
||||
Ren'Py can then be run by running renpy.exe, renpy.sh, or renpy.app as
|
||||
appropriate.
|
||||
|
||||
Devel
|
||||
-----
|
||||
|
||||
The devel branch contains code that requires a recompile of modules
|
||||
implemented in C or Cython. Building devel requires you to have the
|
||||
prerequisite libraries installed. Then set RENPY_DEPS_INSTALLED to
|
||||
a \::-separated list of paths containing dependencies. For example::
|
||||
|
||||
export RENPY_DEPS_INSTALL=/usr::/usr/lib/x86_64-linux-gnu/
|
||||
|
||||
Finally, change into the modules directory, and run::
|
||||
|
||||
python setup.py install
|
||||
|
||||
Ren'Py can then be run by using python to run renpy.py.
|
||||
|
||||
|
||||
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 so we can discuss the design.
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
from renpy import version_tuple #@UnresolvedImport
|
||||
|
||||
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")
|
||||
|
||||
args = ap.parse_args()
|
||||
|
||||
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
|
||||
|
||||
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/renpy")
|
||||
|
||||
if tag and not args.no_tag:
|
||||
cmd = [ "git", "tag", "-a", version, "-m", "Ren'Py " + version ]
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
os.chdir("/home/tom/ab/website")
|
||||
subprocess.check_call("./upload.sh")
|
||||
@@ -0,0 +1,85 @@
|
||||
#!/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()
|
||||
|
||||
|
||||
try:
|
||||
os.unlink(fn + ".bak")
|
||||
except:
|
||||
pass
|
||||
|
||||
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,16 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
ROOT="$(dirname $(readlink -f $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/template/README.html"
|
||||
|
||||
ln -s "$ROOT/sphinx/source/license.rst" "$ROOT/LICENSE.txt"
|
||||
ln -s "$ROOT/sphinx/build/html" "$ROOT/doc"
|
||||
|
||||
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,3 @@
|
||||
cd game
|
||||
..\archiver.exe images *.png *.jpg
|
||||
pause
|
||||
@@ -0,0 +1,96 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# The Ren'Py archiver. This builds a Ren'Py archive file, and the
|
||||
# associated index file. These files are really easy to reverse-engineer,
|
||||
# but are probably better than nothing.
|
||||
|
||||
import sys
|
||||
import os
|
||||
import encodings.zlib_codec
|
||||
import random
|
||||
import glob
|
||||
|
||||
from cPickle import loads, dumps, HIGHEST_PROTOCOL
|
||||
|
||||
# The most we will go without inserting some padding. 10k.
|
||||
padding_every = 10240
|
||||
|
||||
# The amount of padding we will add.
|
||||
padding_max = 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
|
||||
|
||||
# Needed because windows sucks. It doesn't do globbing on the
|
||||
# command line.
|
||||
files = [ ]
|
||||
for i in sys.argv[2:]:
|
||||
files.extend(glob.glob(i))
|
||||
|
||||
for fn in files:
|
||||
index[fn] = [ ]
|
||||
|
||||
print "Adding %s..." % fn
|
||||
|
||||
datafile = file(fn, "rb")
|
||||
|
||||
while True:
|
||||
|
||||
# Pad with junk.
|
||||
padding = randpadding()
|
||||
archivef.write(padding)
|
||||
offset += len(padding)
|
||||
|
||||
# Pick a random block size.
|
||||
block = random.randint(1, padding_every)
|
||||
|
||||
data = datafile.read(block)
|
||||
|
||||
if not data:
|
||||
break
|
||||
|
||||
dlen = len(data)
|
||||
|
||||
archivef.write(data)
|
||||
|
||||
index[fn].append((offset, dlen))
|
||||
offset += dlen
|
||||
|
||||
datafile.close()
|
||||
|
||||
archivef.close()
|
||||
|
||||
indexf.write(dumps(index, HIGHEST_PROTOCOL).encode("zlib"))
|
||||
indexf.close()
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -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", "console.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,382 @@
|
||||
# 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 = 10
|
||||
|
||||
# A small amount of padding.
|
||||
library.padding = 2
|
||||
|
||||
# The width of a thumbnail.
|
||||
library.thumbnail_width = 250
|
||||
|
||||
# The height of a thumbnail.
|
||||
library.thumbnail_height = 188
|
||||
|
||||
# The contents of the main menu.
|
||||
library.main_menu = [
|
||||
( "Start Game", "start" ),
|
||||
( "Continue Game", "_continue" ),
|
||||
( "Quit Game", "_quit" ),
|
||||
]
|
||||
|
||||
# The contents of the game menu choices.
|
||||
library.game_menu = [
|
||||
( "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", "_quit_screen" ),
|
||||
]
|
||||
|
||||
# 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.
|
||||
def _(s):
|
||||
"""
|
||||
Translates s into another language or something.
|
||||
"""
|
||||
|
||||
if s in library.translations:
|
||||
return library.translations[s]
|
||||
else:
|
||||
return s
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
# Set up the default keymap.
|
||||
python hide:
|
||||
# The default keymap.
|
||||
km = renpy.Keymap(
|
||||
rollback = renpy.rollback,
|
||||
screenshot = _screenshot,
|
||||
toggle_fullscreen = renpy.toggle_fullscreen,
|
||||
toggle_music = renpy.toggle_music,
|
||||
game_menu = renpy.curried_call_in_new_context("_game_menu"),
|
||||
hide_windows = _hide_windows,
|
||||
)
|
||||
|
||||
config.underlay = [ km ]
|
||||
|
||||
return
|
||||
|
||||
# This is the true starting point of the program. Sssh... Don't
|
||||
# tell anyone.
|
||||
label _start:
|
||||
|
||||
if renpy.has_label("splashscreen") and not _restart:
|
||||
call splashscreen
|
||||
|
||||
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:
|
||||
|
||||
ui.keymousebehavior()
|
||||
|
||||
ui.window(style='mm_root_window')
|
||||
ui.fixed()
|
||||
|
||||
ui.window(style='mm_menu_window')
|
||||
ui.vbox()
|
||||
|
||||
for text, label in library.main_menu:
|
||||
ui.textbutton(text, clicked=ui.returns(label))
|
||||
|
||||
ui.close()
|
||||
ui.close()
|
||||
|
||||
store._result = renpy.interact(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):
|
||||
|
||||
ui.keymousebehavior()
|
||||
|
||||
ui.window(style='gm_root_window')
|
||||
ui.fixed()
|
||||
|
||||
ui.window(style='gm_nav_window')
|
||||
ui.vbox()
|
||||
|
||||
for key, label, target in library.game_menu:
|
||||
style="button"
|
||||
text_style="button_text"
|
||||
|
||||
if key == selected:
|
||||
style = 'selected_button'
|
||||
text_style = 'selected_button_text'
|
||||
|
||||
ui.textbutton(_(label), style=style, text_style=text_style,
|
||||
clicked=ui.jumps(target))
|
||||
|
||||
ui.close()
|
||||
ui.close()
|
||||
|
||||
def _game_interact():
|
||||
|
||||
return renpy.interact(suppress_underlay=True,
|
||||
suppress_overlay=True)
|
||||
|
||||
_file_picker_index = 0
|
||||
|
||||
# This is used to render a single filename to the screen.
|
||||
def _render_filename(index, filename, newest_filename):
|
||||
|
||||
if filename is None:
|
||||
ui.text(_("Save in new slot."), style='file_picker_new_slot')
|
||||
return
|
||||
|
||||
|
||||
ui.hbox(padding=library.padding)
|
||||
|
||||
num = "% 2d." % index
|
||||
|
||||
if filename == newest_filename:
|
||||
ui.text(num, style='file_picker_new')
|
||||
else:
|
||||
ui.text(num, style='file_picker_old')
|
||||
|
||||
# Do something better about this.
|
||||
# ui.add(renpy.load_screenshot(filename))
|
||||
|
||||
ui.text(renpy.load_extra_info(filename), style='file_picker_extra_info')
|
||||
|
||||
ui.close()
|
||||
|
||||
# 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]
|
||||
|
||||
# Navigation
|
||||
_game_nav(selected)
|
||||
|
||||
ui.window(style='file_picker_window')
|
||||
ui.hbox()
|
||||
|
||||
ui.vbox()
|
||||
|
||||
ui.hbox(padding=library.padding * 10)
|
||||
|
||||
def tb(cond, label, clicked):
|
||||
if cond:
|
||||
style = 'button'
|
||||
text_style = 'button_text'
|
||||
else:
|
||||
style = 'disabled_button'
|
||||
text_style = 'disabled_button_text'
|
||||
|
||||
ui.textbutton(label, style=style, text_style=text_style, clicked=clicked)
|
||||
|
||||
|
||||
tb(fpi > 0, _('Previous Page'), ui.returns(("fpidelta", -1)))
|
||||
tb(fpi + library.file_page_length < len(files),
|
||||
_('Next Page'), ui.returns(("fpidelta", +1)))
|
||||
|
||||
ui.close() # hbox
|
||||
|
||||
for index, i in enumerate(cur_files):
|
||||
|
||||
def hover(i=i):
|
||||
ui.reopen(image_win, True)
|
||||
|
||||
if i:
|
||||
ui.add(renpy.load_screenshot(i))
|
||||
else:
|
||||
ui.null()
|
||||
|
||||
ui.close()
|
||||
|
||||
|
||||
ui.button(style='file_picker_entry',
|
||||
clicked=ui.returns(("return", i)),
|
||||
hovered=hover)
|
||||
|
||||
_render_filename(index + fpi + 1, i, nsg)
|
||||
|
||||
|
||||
ui.close() # vbox
|
||||
|
||||
image_win = ui.window(style='file_picker_image')
|
||||
ui.null()
|
||||
|
||||
ui.close() # hbox
|
||||
|
||||
result = _game_interact()
|
||||
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):
|
||||
|
||||
_game_nav(screen)
|
||||
|
||||
ui.text(message, style='yesno_prompt')
|
||||
ui.textbutton(_("Yes"), style='yesno_yes', clicked=ui.returns(True))
|
||||
ui.textbutton(_("No"), style='yesno_no', clicked=ui.returns(False))
|
||||
|
||||
return _game_interact()
|
||||
|
||||
|
||||
|
||||
# Factored this all into one place, to make our lives a bit easier.
|
||||
label _take_screenshot:
|
||||
$ renpy.take_screenshot((library.thumbnail_width, library.thumbnail_height))
|
||||
return
|
||||
|
||||
# Entry points from the game into menu-space.
|
||||
label _load_menu:
|
||||
call _take_screenshot
|
||||
jump _load_screen
|
||||
|
||||
label _game_menu:
|
||||
call _take_screenshot
|
||||
jump _save_screen
|
||||
|
||||
label _confirm_quit:
|
||||
call _take_screenshot
|
||||
jump _quit_screen
|
||||
|
||||
# Menu screens.
|
||||
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?")):
|
||||
python hide:
|
||||
|
||||
if save_name:
|
||||
full_save_name = " - " + save_name
|
||||
else:
|
||||
full_save_name = ""
|
||||
|
||||
renpy.save(_fn, renpy.time.strftime("%b %d, %H:%M") +
|
||||
full_save_name)
|
||||
|
||||
jump _save_screen
|
||||
|
||||
# Asks the user if he wants to quit.
|
||||
label _quit_screen:
|
||||
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,146 @@
|
||||
# This file contains the code to implement the Ren'Py preferences
|
||||
# screen.
|
||||
|
||||
init -450:
|
||||
python:
|
||||
|
||||
# Used to collect the various preferences the system knows
|
||||
# about.
|
||||
library.left_preferences = [ ]
|
||||
library.right_preferences = [ ]
|
||||
|
||||
class _Preference(object):
|
||||
"""
|
||||
This is a class that's used to represent a preference that
|
||||
may be shown to the user.
|
||||
"""
|
||||
|
||||
def __init__(self, name, field, values):
|
||||
"""
|
||||
@param name: The name of this preference. It will be
|
||||
displayed to the user.
|
||||
|
||||
@param variable: The field on the _preferences object
|
||||
that will be assigned the selected value. This field
|
||||
must exist.
|
||||
|
||||
@param values: A list of value name, value, condition
|
||||
triples. The value name is the name of this value that
|
||||
will be shown to the user. The value is the literal
|
||||
python value that will be assigned if this value is
|
||||
selected. The condition is a condition that will be
|
||||
evaluated to determine if this is a legal value. If no
|
||||
conditions are true, this preference will not be
|
||||
displayed to the user. A condition of None is always
|
||||
considered to be True.
|
||||
"""
|
||||
|
||||
self.name = name
|
||||
self.field = field
|
||||
self.values = values
|
||||
|
||||
def render_preference(self):
|
||||
values = [ (name, val) for name, val, cond in self.values
|
||||
if cond is None or renpy.eval(cond) ]
|
||||
|
||||
if not values:
|
||||
return
|
||||
|
||||
ui.vbox(style='prefs_pref')
|
||||
ui.text(_(self.name), style='prefs_label')
|
||||
|
||||
cur = getattr(_preferences, self.field)
|
||||
|
||||
for name, value in values:
|
||||
|
||||
style = 'button'
|
||||
text_style = 'button_text'
|
||||
|
||||
if cur == value:
|
||||
style = 'selected_button'
|
||||
text_style = 'selected_button_text'
|
||||
|
||||
def clicked(value=value):
|
||||
setattr(_preferences, self.field, value)
|
||||
return True
|
||||
|
||||
ui.textbutton(_(name),
|
||||
style=style,
|
||||
text_style=text_style,
|
||||
clicked=clicked)
|
||||
|
||||
ui.close()
|
||||
|
||||
|
||||
python hide:
|
||||
|
||||
# Enablers for some preferences.
|
||||
library.has_music = True
|
||||
library.has_sound = True
|
||||
library.has_transitions = True
|
||||
|
||||
|
||||
p1 = _Preference('Display', 'fullscreen', [
|
||||
('Window', False, None),
|
||||
('Fullscreen', True, None),
|
||||
])
|
||||
|
||||
p2 = _Preference('Music', 'music', [
|
||||
('Enabled', True, 'library.has_music'),
|
||||
('Disabled', False, 'library.has_music'),
|
||||
])
|
||||
|
||||
p3 = _Preference('Sound Effects', 'sound', [
|
||||
('Enabled', True, 'library.has_sound'),
|
||||
('Disabled', False, 'library.has_sound'),
|
||||
])
|
||||
|
||||
|
||||
library.left_preferences = [ p1, p2, p3 ]
|
||||
|
||||
p4 = _Preference('CTRL Skips', 'skip_unseen', [
|
||||
('Seen Messages', False, None),
|
||||
('All Messages', True, None),
|
||||
])
|
||||
|
||||
p5 = _Preference('Transitions', 'transitions', [
|
||||
('All', 2, 'library.has_transitions'),
|
||||
('Some', 1, 'library.has_transitions and default_transition'),
|
||||
('None', 0, 'library.has_transitions'),
|
||||
])
|
||||
|
||||
p6 = _Preference('Text Display', 'fast_text', [
|
||||
('Fast', True, 'config.annoying_text_cps'),
|
||||
('Slow', False, 'config.annoying_text_cps'),
|
||||
])
|
||||
|
||||
|
||||
library.right_preferences = [ p4, p5, p6 ]
|
||||
|
||||
label _prefs_screen:
|
||||
|
||||
python hide:
|
||||
|
||||
_game_nav("prefs")
|
||||
|
||||
ui.vbox(library.padding * 3, style='prefs_left')
|
||||
for i in library.left_preferences:
|
||||
i.render_preference()
|
||||
ui.close()
|
||||
|
||||
ui.vbox(library.padding * 3, style='prefs_right')
|
||||
for i in library.right_preferences:
|
||||
i.render_preference()
|
||||
ui.close()
|
||||
|
||||
_game_interact()
|
||||
|
||||
jump _prefs_screen
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,348 @@
|
||||
# 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.antialias = True
|
||||
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
|
||||
style.default.text_y_fudge = 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.')
|
||||
|
||||
# Style that is used by imagebutttons.
|
||||
style.create('image_button', 'default',
|
||||
'(window, sound, hover) The default style used for image buttons.')
|
||||
|
||||
style.create('image_button_image', 'default',
|
||||
'The default style used for images inside image buttons.')
|
||||
|
||||
|
||||
# Styles that are used by all other 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_image', 'default')
|
||||
|
||||
style.file_picker_image.xminimum = 280
|
||||
|
||||
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 = 500
|
||||
style.file_picker_entry.ymargin = 2
|
||||
|
||||
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.file_picker_text.size = 18
|
||||
|
||||
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 = 30
|
||||
style.file_picker_old.minwidth = 30
|
||||
|
||||
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"
|
||||
|
||||
@@ -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,611 @@
|
||||
# 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.
|
||||
|
||||
# If you're trying to understand this script, I recommend skipping
|
||||
# down to the line beginning with 'label start:', at least on your
|
||||
# first read-through.
|
||||
|
||||
# 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"
|
||||
|
||||
# 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)
|
||||
|
||||
# Change button styles.
|
||||
$ style.button.background = Frame("button.png", 25, 10)
|
||||
$ style.selected_button.background = Frame("button_checked.png", 25, 10)
|
||||
$ del style.selected_button_text.color
|
||||
$ style.button_text.drop_shadow = None
|
||||
$ style.button_text.xpos = 28
|
||||
$ style.button_text.xanchor = 'left'
|
||||
$ style.button_text.ypos = 0.6
|
||||
$ style.button_text.yanchor = 'center'
|
||||
$ style.button_text.color = (255, 255, 255, 255)
|
||||
$ style.button_text.hover_color = (255, 255, 0, 255)
|
||||
$ style.button.xminimum = 250
|
||||
|
||||
# Change other styles.
|
||||
$ style.prefs_label.color = (64, 64, 255, 255)
|
||||
$ style.yesno_prompt.color = (64, 64, 255, 255)
|
||||
$ style.file_picker_entry.xpos = 0
|
||||
$ style.file_picker_entry.xanchor = 'left'
|
||||
$ style.file_picker_entry.xminimum = 520
|
||||
$ style.file_picker_text.xpos = 0
|
||||
$ style.file_picker_text.ypos = 3
|
||||
$ style.file_picker_text.drop_shadow = None
|
||||
$ style.file_picker_entry.idle_background = Solid((0, 0, 192, 255))
|
||||
$ style.file_picker_entry.hover_background = Solid((64, 64, 255, 255))
|
||||
$ style.file_picker_old.color = (255, 255, 255, 255)
|
||||
$ style.file_picker_extra_info.color = (255, 255, 255, 255)
|
||||
$ style.file_picker_new_slot.color = (255, 255, 255, 255)
|
||||
|
||||
|
||||
# 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 splashscreen is called, if it exists, before the main menu is
|
||||
# shown the first time. It is not called if the game has restarted.
|
||||
|
||||
# We'll comment it out for now.
|
||||
#
|
||||
# label splashscreen:
|
||||
# scene black
|
||||
# show text "American Bishoujo Presents..." with fade
|
||||
# $ renpy.pause(1.0)
|
||||
# hide text with fade
|
||||
#
|
||||
# return
|
||||
|
||||
|
||||
# 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,286 +1,129 @@
|
||||
#!/home/tom/bin/renpython -OO
|
||||
# Builds a distributions of Ren'Py.
|
||||
|
||||
import sys
|
||||
import os.path
|
||||
import os
|
||||
import zipfile
|
||||
import tarfile
|
||||
import zlib
|
||||
import compileall
|
||||
import shutil
|
||||
import subprocess
|
||||
import time
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
CWD = os.getcwdu()
|
||||
def match_times(source, dest):
|
||||
|
||||
zlib.Z_DEFAULT_COMPRESSION = 9
|
||||
|
||||
# Gets the data for the given file.
|
||||
def data(fn):
|
||||
|
||||
rv = file(fn, "rb").read()
|
||||
|
||||
if fn.startswith("renpy.app"):
|
||||
return rv
|
||||
|
||||
if fn.endswith(".rpy") or fn.endswith(".rpym") or fn.endswith(".py") or fn.endswith(".txt"):
|
||||
rv = rv.replace("\n", "\r\n")
|
||||
rv = rv.replace("\r\r\n", "\r\n")
|
||||
|
||||
return rv
|
||||
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 tarup(filename, prefix, files):
|
||||
def copy_file(source, dest, license=""):
|
||||
|
||||
tf = tarfile.open(filename, "w:bz2")
|
||||
tf.dereference = True
|
||||
print source, "->", dest
|
||||
|
||||
sys.stdout.write(filename)
|
||||
sys.stdout.flush()
|
||||
sf = file(source, "rb")
|
||||
df = file(dest, "wb")
|
||||
|
||||
for fn in files:
|
||||
sys.stdout.write(".")
|
||||
sys.stdout.flush()
|
||||
|
||||
tf.add(fn, prefix + "/" + fn, False)
|
||||
df.write(license)
|
||||
|
||||
sys.stdout.write("\n")
|
||||
|
||||
tf.close()
|
||||
|
||||
data = sf.read()
|
||||
if dest.endswith(".txt") or dest.endswith(".py") or dest.endswith(".rpy") or dest.endswith(".bat"):
|
||||
data = dosify(data)
|
||||
|
||||
# Creates a zip file.
|
||||
def zipup(filename, prefix, files):
|
||||
df.write(data)
|
||||
|
||||
zf = zipfile.ZipFile(filename, "w")
|
||||
|
||||
sys.stdout.write(filename)
|
||||
sys.stdout.flush()
|
||||
|
||||
for fn in files:
|
||||
sys.stdout.write(".")
|
||||
sys.stdout.flush()
|
||||
|
||||
zi = zipfile.ZipInfo(prefix + "/" + fn)
|
||||
|
||||
st = os.stat(fn)
|
||||
|
||||
zi.date_time = time.gmtime(st.st_mtime)[:6]
|
||||
zi.compress_type = zipfile.ZIP_DEFLATED
|
||||
zi.create_system = 3
|
||||
zi.external_attr = long(st.st_mode) << 16
|
||||
|
||||
zf.writestr(zi, data(fn))
|
||||
|
||||
zf.close()
|
||||
|
||||
sys.stdout.write("\n")
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
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.
|
||||
"""
|
||||
|
||||
sf = open(src, "rb")
|
||||
df = open(dest, "wb")
|
||||
|
||||
# True if we want to copy the line.
|
||||
copy = True
|
||||
|
||||
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)
|
||||
|
||||
sf.close()
|
||||
df.close()
|
||||
|
||||
|
||||
def tree(root):
|
||||
|
||||
rv = [ ]
|
||||
match_times(source, dest)
|
||||
|
||||
for dirname, dirs, filenames in os.walk(root):
|
||||
|
||||
if "saves" in dirs:
|
||||
dirs.remove("saves")
|
||||
def copy_tree(source, dest, should_copy=lambda fn : True, license=""):
|
||||
|
||||
if ".svn" in dirs:
|
||||
dirs.remove(".svn")
|
||||
os.makedirs(dest)
|
||||
|
||||
if ".doctrees" in dirs:
|
||||
dirs.remove(".doctrees")
|
||||
for dirpath, dirnames, filenames in os.walk(source):
|
||||
|
||||
for f in filenames:
|
||||
if f[-1] == '~' or f[0] == '.':
|
||||
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
|
||||
|
||||
if f.endswith(".bak") or f.endswith(".pyc"):
|
||||
continue
|
||||
copy_file(dirpath + "/" + i, dstrel + "/" + i, license=license)
|
||||
|
||||
|
||||
if f == "semantic.cache":
|
||||
continue
|
||||
|
||||
if "libSDL_mixer" in f or "mixer_music" in f:
|
||||
continue
|
||||
|
||||
rv.append(dirname + "/" + f)
|
||||
|
||||
return rv
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument("version")
|
||||
ap.add_argument("--fast", action="store_true")
|
||||
target = sys.argv[1]
|
||||
gamedir = sys.argv[2]
|
||||
|
||||
# Read license.
|
||||
lf = file("LICENSE.txt")
|
||||
license = "#!/usr/bin/env python\n\n"
|
||||
|
||||
args = ap.parse_args()
|
||||
for l in lf:
|
||||
license += "# " + l
|
||||
|
||||
# Revision updating is done early, so we can do it even if the rest
|
||||
# of the program fails.
|
||||
lf.close()
|
||||
|
||||
# Determine the version. We grab the current revision, and if any
|
||||
# file has changed, bump it by 1.
|
||||
import renpy
|
||||
license = dosify(license)
|
||||
|
||||
match_version = ".".join(str(i) for i in renpy.version_tuple[:2]) #@UndefinedVariable
|
||||
zip_version = ".".join(str(i) for i in renpy.version_tuple[:3]) #@UndefinedVariable
|
||||
if os.path.exists(target):
|
||||
raise Exception("Target exists!")
|
||||
|
||||
s = subprocess.check_output([ "git", "describe", "--tags", "--dirty", "--match", match_version ])
|
||||
parts = s.strip().split("-")
|
||||
vc_version = int(parts[1])
|
||||
# Start off with the target.
|
||||
copy_tree("dist", target,
|
||||
should_copy = lambda fn : fn not in [ 'traceback.txt' ] and not fn.endswith(".log"))
|
||||
|
||||
# Copy renpy modules.
|
||||
copy_tree("renpy", target + "/renpy",
|
||||
should_copy = lambda fn : fn.endswith(".py"),
|
||||
license=license)
|
||||
|
||||
doc_files = [
|
||||
'example.html',
|
||||
'tutorial.html',
|
||||
'style.css',
|
||||
]
|
||||
|
||||
# Copy doc
|
||||
copy_tree("doc", target + "/doc",
|
||||
should_copy = lambda fn : fn in doc_files)
|
||||
|
||||
# Copy the game
|
||||
copy_tree(gamedir, target + "/game",
|
||||
should_copy = lambda fn : not fn.startswith(".") and not fn.endswith("~"))
|
||||
|
||||
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 parts[-1] == "dirty":
|
||||
vc_version += 1
|
||||
|
||||
with open("renpy/vc_version.py", "w") as f:
|
||||
f.write("vc_version = {}".format(vc_version))
|
||||
|
||||
reload(sys.modules['renpy.vc_version']) #@UndefinedVariable
|
||||
reload(sys.modules['renpy'])
|
||||
|
||||
# Check that the versions match.
|
||||
full_version = ".".join(str(i) for i in renpy.version_tuple) #@UndefinedVariable
|
||||
if args.version != "experimental" and not full_version.startswith(args.version):
|
||||
raise Exception("The command-line and Ren'Py versions do not match.")
|
||||
|
||||
print "Version {} ({})".format(args.version, full_version)
|
||||
|
||||
# Copy over the screens, to keep them up to date.
|
||||
copy_tutorial_file("tutorial/game/screens.rpy", "template/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', 'template', 'the_question' ]:
|
||||
print "Compiling", i
|
||||
subprocess.check_call(["./renpy.sh", i, "compile" ])
|
||||
|
||||
# The destination directory.
|
||||
destination = os.path.join("dl", args.version)
|
||||
|
||||
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"),
|
||||
])
|
||||
|
||||
|
||||
|
||||
# Write 7z.exe.
|
||||
sdk = "renpy-{}-sdk".format(zip_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
|
||||
print "Did you run me with renpython -OO?"
|
||||
print "Did you update renpy.py and launcher/script_version.rpy?"
|
||||
|
||||
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 ../demo2/script.rpy
|
||||
python preprocess.py example.xml > example.hi.xml
|
||||
xsltproc stylesheet.xslt example.hi.xml > example.html
|
||||
cp example.html style.css ~/ab/website/renpy/devel/doc
|
||||
@@ -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,128 +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>
|
||||
|
||||
<div id="renpy_help"></div>
|
||||
|
||||
|
||||
|
||||
|
||||
<p><a name="Basic_Help" id="Basic_Help"></a></p>
|
||||
<h2><span class="editsection">[<a href="/w/index.php?title=renpy/Help&action=edit&section=1" title="Edit section: Basic Help">edit</a>]</span> <span class="mw-headline">Basic Help</span></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>
|
||||
<p><a name="Game_Menu" id="Game_Menu"></a></p>
|
||||
<h3><span class="editsection">[<a href="/w/index.php?title=renpy/Help&action=edit&section=2" title="Edit section: Game Menu">edit</a>]</span> <span class="mw-headline">Game Menu</span></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>
|
||||
</dl>
|
||||
<dl>
|
||||
<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>
|
||||
<p><a name="Key_and_Mouse_Bindings" id="Key_and_Mouse_Bindings"></a></p>
|
||||
<h3><span class="editsection">[<a href="/w/index.php?title=renpy/Help&action=edit&section=3" title="Edit section: Key and Mouse Bindings">edit</a>]</span> <span class="mw-headline">Key and Mouse Bindings</span></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>Selects 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, cancelling 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>
|
||||
</dl>
|
||||
<p><a name="Legal_Notice" id="Legal_Notice"></a></p>
|
||||
<h2><span class="editsection">[<a href="/w/index.php?title=renpy/Help&action=edit&section=4" title="Edit section: Legal Notice">edit</a>]</span> <span class="mw-headline">Legal Notice</span></h2>
|
||||
<p>This game uses source code from a number of open source projects. For a list, and a location where the source code can be downloaded from, please view the LICENSE.txt file in the renpy directory, or visit <a href="http://www.renpy.org/wiki/renpy/License" class="external free" title="http://www.renpy.org/wiki/renpy/License" rel="nofollow">http://www.renpy.org/wiki/renpy/License</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,27 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
# 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,31 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
screen about:
|
||||
|
||||
$ version = renpy.version()
|
||||
|
||||
frame:
|
||||
style_group "l"
|
||||
style "l_root"
|
||||
|
||||
window:
|
||||
xfill True
|
||||
|
||||
has vbox xfill True
|
||||
|
||||
add "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,36 +0,0 @@
|
||||
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,67 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
# 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()
|
||||
|
||||
|
Before Width: | Height: | Size: 2.3 KiB |
@@ -1,328 +0,0 @@
|
||||
|
||||
# http://www.csn.ul.ie/~caolan/publink/winresdump/winresdump/doc/pefile.html
|
||||
# Contains a reasonable description of the format.
|
||||
|
||||
import struct
|
||||
import sys
|
||||
import array
|
||||
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()
|
||||
|
||||
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
@@ -1,465 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
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):
|
||||
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()
|
||||
renpy.style.rebuild()
|
||||
|
||||
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
|
||||
|
||||
|
||||
init 100 python:
|
||||
style_backup = renpy.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:
|
||||
|
||||
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"
|
||||
yinitial theme_yinitial()
|
||||
mousewheel True
|
||||
|
||||
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
|
||||
yinitial scheme_yinitial()
|
||||
|
||||
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,923 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
# This file contains code that manages the distribution of Ren'Py games
|
||||
# and Ren'Py proper.
|
||||
#
|
||||
# In this module, all files and paths are stored in unicode. Full paths
|
||||
# might include windows path separators (\), but archive paths and names we
|
||||
# deal with/match against use the unix separator (/).
|
||||
|
||||
|
||||
init python in distribute:
|
||||
|
||||
from store import config, persistent
|
||||
import store.project as project
|
||||
import store.interface as interface
|
||||
import store.archiver as archiver
|
||||
import store.updater as updater
|
||||
import store as store
|
||||
|
||||
from change_icon import change_icons
|
||||
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
import subprocess
|
||||
import hashlib
|
||||
import struct
|
||||
import collections
|
||||
import os
|
||||
import io
|
||||
import re
|
||||
import plistlib
|
||||
import time
|
||||
|
||||
match_cache = { }
|
||||
|
||||
def compile_match(pattern):
|
||||
"""
|
||||
Compiles a pattern for use with match.
|
||||
"""
|
||||
|
||||
regexp = ""
|
||||
|
||||
while pattern:
|
||||
if pattern.startswith("**"):
|
||||
regexp += r'.*'
|
||||
pattern = pattern[2:]
|
||||
elif pattern[0] == "*":
|
||||
regexp += r'[^/]*/?'
|
||||
pattern = pattern[1:]
|
||||
elif pattern[0] == '[':
|
||||
regexp += r'['
|
||||
pattern = pattern[1:]
|
||||
|
||||
while pattern and pattern[0] != ']':
|
||||
regexp += pattern[0]
|
||||
pattern = pattern[1:]
|
||||
|
||||
pattern = pattern[1:]
|
||||
regexp += ']'
|
||||
|
||||
else:
|
||||
regexp += re.escape(pattern[0])
|
||||
pattern = pattern[1:]
|
||||
|
||||
regexp += "$"
|
||||
|
||||
return re.compile(regexp, re.I)
|
||||
|
||||
def match(s, pattern):
|
||||
"""
|
||||
Matches a glob-style pattern against s. Returns True if it matches,
|
||||
and False otherwise.
|
||||
|
||||
** matches every character.
|
||||
* matches every character but /.
|
||||
[abc] matches a, b, or c.
|
||||
|
||||
Things are matched case-insensitively.
|
||||
"""
|
||||
|
||||
regexp = match_cache.get(pattern, None)
|
||||
if regexp is None:
|
||||
regexp = compile_match(pattern)
|
||||
match_cache[pattern] = regexp
|
||||
|
||||
if regexp.match(s):
|
||||
return True
|
||||
|
||||
if regexp.match("/" + s):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
class File(object):
|
||||
"""
|
||||
Represents a file that we can distribute.
|
||||
|
||||
self.name
|
||||
The name of the file as it will be stored in the archives.
|
||||
|
||||
self.path
|
||||
The path to the file on disk. None if it won't be stored
|
||||
on disk.
|
||||
|
||||
self.directory
|
||||
True if this is a directory.
|
||||
|
||||
self.executable
|
||||
True if this is an executable that should be distributed
|
||||
with the xbit set.
|
||||
"""
|
||||
|
||||
def __init__(self, name, path, directory, executable):
|
||||
self.name = name
|
||||
self.path = path
|
||||
self.directory = directory
|
||||
self.executable = executable
|
||||
|
||||
def __repr__(self):
|
||||
if self.directory:
|
||||
extra = "dir"
|
||||
elif self.executable:
|
||||
extra = "x-bit"
|
||||
else:
|
||||
extra = ""
|
||||
|
||||
return "<File {!r} {!r} {}>".format(self.name, self.path, extra)
|
||||
|
||||
def copy(self):
|
||||
return File(self.name, self.path, self.directory, self.executable)
|
||||
|
||||
|
||||
class FileList(list):
|
||||
"""
|
||||
This represents a list of files that we know about.
|
||||
"""
|
||||
|
||||
def sort(self):
|
||||
list.sort(self, key=lambda a : a.name)
|
||||
|
||||
def copy(self):
|
||||
"""
|
||||
Makes a deep copy of this file list.
|
||||
"""
|
||||
|
||||
rv = FileList()
|
||||
|
||||
for i in self:
|
||||
rv.append(i.copy())
|
||||
|
||||
return rv
|
||||
|
||||
def filter_empty(self):
|
||||
"""
|
||||
Makes a deep copy of this file list with empty directories
|
||||
omitted.
|
||||
"""
|
||||
|
||||
rv = FileList()
|
||||
|
||||
needed_dirs = set()
|
||||
|
||||
for i in reversed(self):
|
||||
|
||||
if (not i.directory) or (i.name in needed_dirs):
|
||||
rv.insert(0, i.copy())
|
||||
|
||||
directory, _sep, _filename = i.name.rpartition("/")
|
||||
needed_dirs.add(directory)
|
||||
|
||||
return rv
|
||||
|
||||
@staticmethod
|
||||
def merge(l):
|
||||
"""
|
||||
Merges a list of file lists into a single file list with no
|
||||
duplicate entries.
|
||||
"""
|
||||
|
||||
rv = FileList()
|
||||
|
||||
seen = set()
|
||||
|
||||
for fl in l:
|
||||
for f in fl:
|
||||
if f.name in seen:
|
||||
continue
|
||||
|
||||
rv.append(f)
|
||||
seen.add(f.name)
|
||||
|
||||
return rv
|
||||
|
||||
def prepend_directory(self, directory):
|
||||
"""
|
||||
Modifies this file list such that every file in it has `directory`
|
||||
prepended.
|
||||
"""
|
||||
|
||||
for i in self:
|
||||
i.name = directory + "/" + i.name
|
||||
|
||||
self.insert(0, File(directory, None, True, False))
|
||||
|
||||
|
||||
def mac_transform(self, app, documentation):
|
||||
"""
|
||||
Creates a new file list that has the mac transform applied to it.
|
||||
|
||||
The mac transform places all files that aren't already in <app> in
|
||||
<app>/Contents/Resources/autorun. If it matches one of the documentation
|
||||
patterns, then it appears both inside and outside of the app.
|
||||
"""
|
||||
|
||||
rv = FileList()
|
||||
|
||||
for f in self:
|
||||
|
||||
# Already in the app.
|
||||
if f.name == app or f.name.startswith(app + "/"):
|
||||
rv.append(f)
|
||||
continue
|
||||
|
||||
# If it's documentation, keep the file. (But also make
|
||||
# a copy.)
|
||||
for pattern in documentation:
|
||||
if match(f.name, pattern):
|
||||
rv.append(f)
|
||||
|
||||
if match("/" + f.name, pattern):
|
||||
rv.append(f)
|
||||
|
||||
# Make a copy.
|
||||
f = f.copy()
|
||||
|
||||
f.name = app + "/Contents/Resources/autorun/" + f.name
|
||||
rv.append(f)
|
||||
|
||||
rv.append(File(app + "/Contents/Resources/autorun", None, True, False))
|
||||
rv.sort()
|
||||
|
||||
return rv
|
||||
|
||||
|
||||
class Distributor(object):
|
||||
"""
|
||||
This manages the process of building distributions.
|
||||
"""
|
||||
|
||||
def __init__(self, project, destination=None, reporter=None, packages=None, build_update=True):
|
||||
"""
|
||||
Distributes `project`.
|
||||
|
||||
`destination`
|
||||
The destination in which the distribution will be placed. If None,
|
||||
uses a default location.
|
||||
|
||||
`reporter`
|
||||
An object that's used to report status and progress to the user.
|
||||
|
||||
`packages`
|
||||
If not None, a list of packages to distributed. If None, all
|
||||
packages are distributed.
|
||||
|
||||
`build_update`
|
||||
Will updates be built?
|
||||
"""
|
||||
|
||||
|
||||
# Safety - prevents us frome releasing a launcher that won't update.
|
||||
if store.UPDATE_SIMULATE:
|
||||
raise Exception("Cannot build distributions when UPDATE_SIMULATE is True.")
|
||||
|
||||
# The project we want to distribute.
|
||||
self.project = project
|
||||
|
||||
# Logfile.
|
||||
self.log = open(self.temp_filename("distribute.txt"), "w")
|
||||
|
||||
# Start by scanning the project, to get the data and build
|
||||
# dictionaries.
|
||||
data = project.data
|
||||
|
||||
project.update_dump(force=True, gui=False)
|
||||
if project.dump.get("error", False):
|
||||
raise Exception("Could not get build data from the project. Please ensure the project runs.")
|
||||
|
||||
self.build = build = project.dump['build']
|
||||
|
||||
# Map from file list name to file list.
|
||||
self.file_lists = collections.defaultdict(FileList)
|
||||
|
||||
self.base_name = build['directory_name']
|
||||
self.executable_name = build['executable_name']
|
||||
self.pretty_version = build['version']
|
||||
|
||||
# The destination directory.
|
||||
if destination is None:
|
||||
parent = os.path.dirname(project.path)
|
||||
self.destination = os.path.join(parent, self.base_name + "-dists")
|
||||
try:
|
||||
os.makedirs(self.destination)
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
self.destination = destination
|
||||
|
||||
# Status reporter.
|
||||
self.reporter = reporter
|
||||
|
||||
self.include_update = build['include_update']
|
||||
self.build_update = self.include_update and build_update
|
||||
|
||||
# The various executables, which change names based on self.executable_name.
|
||||
self.app = self.executable_name + ".app"
|
||||
self.exe = self.executable_name + ".exe"
|
||||
self.sh = self.executable_name + ".sh"
|
||||
self.py = self.executable_name + ".py"
|
||||
|
||||
self.documentation_patterns = build['documentation_patterns']
|
||||
|
||||
build_packages = [ ]
|
||||
|
||||
for i in build['packages']:
|
||||
name = i['name']
|
||||
|
||||
if (packages is None) or (name in packages):
|
||||
build_packages.append(i)
|
||||
|
||||
if not build_packages:
|
||||
self.reporter.info(_("Nothing to do."), pause=True)
|
||||
return
|
||||
|
||||
# add the game.
|
||||
self.reporter.info(_("Scanning project files..."))
|
||||
|
||||
self.scan_and_classify(project.path, build["base_patterns"])
|
||||
|
||||
self.archive_files(build["archives"])
|
||||
|
||||
# Add Ren'Py.
|
||||
self.reporter.info(_("Scanning Ren'Py files..."))
|
||||
self.scan_and_classify(config.renpy_base, build["renpy_patterns"])
|
||||
|
||||
# Add Python (with the same name as our executables)
|
||||
self.add_python()
|
||||
|
||||
# Build the mac app.
|
||||
self.add_mac_files()
|
||||
|
||||
# Add generated/special files.
|
||||
if not build['renpy']:
|
||||
self.add_renpy_files()
|
||||
self.add_windows_files()
|
||||
|
||||
# Assign the x-bit as necessary.
|
||||
self.mark_executable()
|
||||
|
||||
# Rename the executable-like files.
|
||||
if not build['renpy']:
|
||||
self.rename()
|
||||
|
||||
# The time of the update version.
|
||||
self.update_version = int(time.time())
|
||||
|
||||
for p in build_packages:
|
||||
|
||||
for f in p["formats"]:
|
||||
self.make_package(
|
||||
p["name"],
|
||||
f,
|
||||
p["file_lists"],
|
||||
dlc=p["dlc"])
|
||||
|
||||
if self.build_update and p["update"]:
|
||||
self.make_package(
|
||||
p["name"],
|
||||
"update",
|
||||
p["file_lists"],
|
||||
dlc=False)
|
||||
|
||||
|
||||
if self.build_update:
|
||||
self.finish_updates(build_packages)
|
||||
|
||||
self.log.close()
|
||||
|
||||
|
||||
def scan_and_classify(self, directory, patterns):
|
||||
"""
|
||||
Walks through the `directory`, finds files and directories that
|
||||
match the pattern, and assds them to the appropriate file list.
|
||||
|
||||
`patterns`
|
||||
A list of pattern, file_list tuples. The pattern is a string
|
||||
that is matched using match. File_list is either
|
||||
a space-separated list of file lists to add the file to,
|
||||
or None to ignore it.
|
||||
|
||||
Directories are matched with a trailing /, but added to the
|
||||
file list with the trailing / removed.
|
||||
"""
|
||||
|
||||
def walk(name, path):
|
||||
is_dir = os.path.isdir(path)
|
||||
|
||||
if is_dir:
|
||||
match_name = name + "/"
|
||||
else:
|
||||
match_name = name
|
||||
|
||||
for pattern, file_list in patterns:
|
||||
if match(match_name, pattern):
|
||||
break
|
||||
else:
|
||||
print >> self.log, match_name.encode("utf-8"), "doesn't match anything."
|
||||
|
||||
pattern = None
|
||||
file_list = None
|
||||
|
||||
print >> self.log, match_name.encode("utf-8"), "matches", pattern, "(" + str(file_list) + ")."
|
||||
|
||||
if file_list is None:
|
||||
return
|
||||
|
||||
for fl in file_list:
|
||||
f = File(name, path, is_dir, False)
|
||||
self.file_lists[fl].append(f)
|
||||
|
||||
if is_dir:
|
||||
|
||||
for fn in os.listdir(path):
|
||||
walk(
|
||||
name + "/" + fn,
|
||||
os.path.join(path, fn),
|
||||
)
|
||||
|
||||
for fn in os.listdir(directory):
|
||||
walk(fn, os.path.join(directory, fn))
|
||||
|
||||
def temp_filename(self, name):
|
||||
self.project.make_tmp()
|
||||
return os.path.join(self.project.tmp, name)
|
||||
|
||||
def add_file(self, file_list, name, path, executable=False):
|
||||
"""
|
||||
Adds a file to the file lists.
|
||||
|
||||
`file_list`
|
||||
A space-separated list of file list names.
|
||||
|
||||
`name`
|
||||
The name of the file to be added.
|
||||
|
||||
`path`
|
||||
The path to that file on disk.
|
||||
"""
|
||||
|
||||
if not os.path.exists(path):
|
||||
raise Exception("{} does not exist.".format(path))
|
||||
|
||||
if isinstance(file_list, basestring):
|
||||
file_list = file_list.split()
|
||||
|
||||
f = File(name, path, False, executable)
|
||||
|
||||
for fl in file_list:
|
||||
self.file_lists[fl].append(f)
|
||||
|
||||
def archive_files(self, archives):
|
||||
"""
|
||||
Add files to archives.
|
||||
"""
|
||||
|
||||
for arcname, file_list in archives:
|
||||
|
||||
if not self.file_lists[arcname]:
|
||||
continue
|
||||
|
||||
arcfn = arcname + ".rpa"
|
||||
arcpath = self.temp_filename(arcfn)
|
||||
|
||||
af = archiver.Archive(arcpath)
|
||||
|
||||
fll = len(self.file_lists[arcname])
|
||||
|
||||
for i, entry in enumerate(self.file_lists[arcname]):
|
||||
|
||||
if entry.directory:
|
||||
continue
|
||||
|
||||
self.reporter.progress(_("Archiving files..."), i, fll)
|
||||
|
||||
name = "/".join(entry.name.split("/")[1:])
|
||||
af.add(name, entry.path)
|
||||
|
||||
self.reporter.progress_done()
|
||||
|
||||
af.close()
|
||||
|
||||
self.add_file(file_list, "game/" + arcfn, arcpath)
|
||||
|
||||
def add_renpy_files(self):
|
||||
"""
|
||||
Add Ren'Py-generic files to the project.
|
||||
"""
|
||||
|
||||
if not os.path.exists(os.path.join(self.project.path, "game", "script_version.rpy")):
|
||||
self.add_file("all", "game/script_version.rpy", os.path.join(config.gamedir, "script_version.rpy"))
|
||||
|
||||
if not os.path.exists(os.path.join(self.project.path, "game", "script_version.rpyc")):
|
||||
self.add_file("all", "game/script_version.rpyc", os.path.join(config.gamedir, "script_version.rpyc"))
|
||||
|
||||
self.add_file("all", "renpy/LICENSE.txt", os.path.join(config.renpy_base, "LICENSE.txt"))
|
||||
|
||||
|
||||
def write_plist(self):
|
||||
|
||||
display_name = self.build['display_name']
|
||||
executable_name = self.executable_name
|
||||
version = self.build['version']
|
||||
|
||||
plist = dict(
|
||||
CFBundleDevelopmentRegion="English",
|
||||
CFBundleDisplayName=display_name,
|
||||
CFBundleExecutable=executable_name,
|
||||
CFBundleIconFile="icon",
|
||||
CFBundleInfoDictionaryVersion="6.0",
|
||||
CFBundleName=display_name,
|
||||
CFBundlePackageType="APPL",
|
||||
CFBundleShortVersionString=version,
|
||||
CFBundleVersion="1.0.{0}".format(int(time.time())),
|
||||
CFBundleDocumentTypes = [
|
||||
{
|
||||
"CFBundleTypeOSTypes" : [ "****", "fold", "disk" ],
|
||||
"CFBundleTypeRole" : "Viewer",
|
||||
},
|
||||
],
|
||||
UTExportedTypeDeclarations = [
|
||||
{
|
||||
"UTTypeConformsTo" : [ "public.python-script" ],
|
||||
"UTTypeDescription" : "Ren'Py Script",
|
||||
"UTTypeIdentifier" : "org.renpy.rpy",
|
||||
"UTTypeTagSpecification" : { "public.filename-extension" : [ "rpy" ] }
|
||||
},
|
||||
],
|
||||
)
|
||||
|
||||
rv = self.temp_filename("Info.plist")
|
||||
plistlib.writePlist(plist, rv)
|
||||
return rv
|
||||
|
||||
def add_python(self):
|
||||
|
||||
if self.build['renpy']:
|
||||
windows = 'binary'
|
||||
linux = 'binary'
|
||||
mac = 'binary'
|
||||
else:
|
||||
windows = 'windows'
|
||||
linux = 'linux'
|
||||
mac = 'mac'
|
||||
|
||||
self.add_file(
|
||||
linux,
|
||||
"lib/linux-i686/" + self.executable_name,
|
||||
os.path.join(config.renpy_base, "lib/linux-i686/pythonw"),
|
||||
True)
|
||||
|
||||
self.add_file(
|
||||
linux,
|
||||
"lib/linux-x86_64/" + self.executable_name,
|
||||
os.path.join(config.renpy_base, "lib/linux-x86_64/pythonw"),
|
||||
True)
|
||||
|
||||
self.add_file(
|
||||
mac,
|
||||
"lib/darwin-x86_64/" + self.executable_name,
|
||||
os.path.join(config.renpy_base, "lib/darwin-x86_64/pythonw"),
|
||||
True)
|
||||
|
||||
self.add_file(
|
||||
windows,
|
||||
"lib/windows-i686/" + self.executable_name + ".exe",
|
||||
os.path.join(config.renpy_base, "lib/windows-i686/pythonw.exe"))
|
||||
|
||||
def add_mac_files(self):
|
||||
"""
|
||||
Add mac-specific files to the distro.
|
||||
"""
|
||||
|
||||
if self.build['renpy']:
|
||||
filelist = "binary"
|
||||
else:
|
||||
filelist = "mac"
|
||||
|
||||
contents = self.app + "/Contents"
|
||||
|
||||
plist_fn = self.write_plist()
|
||||
self.add_file(filelist, contents + "/Info.plist", plist_fn)
|
||||
self.add_file(filelist, contents + "/MacOS/" + self.executable_name, os.path.join(config.renpy_base, "renpy.sh"))
|
||||
|
||||
custom_fn = os.path.join(self.project.path, "icon.icns")
|
||||
default_fn = os.path.join(config.renpy_base, "launcher/icon.icns")
|
||||
|
||||
if os.path.exists(custom_fn):
|
||||
icon_fn = custom_fn
|
||||
else:
|
||||
icon_fn = default_fn
|
||||
|
||||
self.add_file(filelist, contents + "/Resources/icon.icns", icon_fn)
|
||||
|
||||
|
||||
def add_windows_files(self):
|
||||
"""
|
||||
Adds windows-specific files.
|
||||
"""
|
||||
|
||||
icon_fn = os.path.join(self.project.path, "icon.ico")
|
||||
old_exe_fn = os.path.join(config.renpy_base, "renpy.exe")
|
||||
|
||||
if os.path.exists(icon_fn):
|
||||
exe_fn = self.temp_filename("renpy.exe")
|
||||
|
||||
with open(exe_fn, "wb") as f:
|
||||
f.write(change_icons(old_exe_fn, icon_fn))
|
||||
|
||||
else:
|
||||
exe_fn = old_exe_fn
|
||||
|
||||
self.add_file("windows", "renpy.exe", exe_fn)
|
||||
|
||||
def mark_executable(self):
|
||||
"""
|
||||
Marks files as executable.
|
||||
"""
|
||||
|
||||
for l in self.file_lists.values():
|
||||
for f in l:
|
||||
for pat in self.build['xbit_patterns']:
|
||||
if match(f.name, pat):
|
||||
f.executable = True
|
||||
|
||||
if match("/" + f.name, pat):
|
||||
f.executable = True
|
||||
|
||||
def rename(self):
|
||||
"""
|
||||
Rename files in all lists to match the executable names.
|
||||
"""
|
||||
|
||||
def rename_one(fn):
|
||||
parts = fn.split('/')
|
||||
p = parts[0]
|
||||
|
||||
if p == "renpy.exe":
|
||||
p = self.exe
|
||||
elif p == "renpy.sh":
|
||||
p = self.sh
|
||||
elif p == "renpy.py":
|
||||
p = self.py
|
||||
|
||||
parts[0] = p
|
||||
return "/".join(parts)
|
||||
|
||||
for l in self.file_lists.values():
|
||||
for f in l:
|
||||
f.name = rename_one(f.name)
|
||||
|
||||
def make_package(self, variant, format, file_lists, dlc=False):
|
||||
"""
|
||||
Creates a package file in the projects directory.
|
||||
|
||||
`variant`
|
||||
The name of the variant to package. This is appended to the base name to become
|
||||
part of the file and directory names.
|
||||
|
||||
`format`
|
||||
The format things will be packaged in. This should be one of "zip", "tar.bz2", or
|
||||
"update".
|
||||
|
||||
`file_lists`
|
||||
A string containing a space-separated list of file_lists to include in this
|
||||
package.
|
||||
|
||||
`dlc`
|
||||
True if we want to build a non-update file in DLC mode.
|
||||
"""
|
||||
filename = self.base_name + "-" + variant
|
||||
path = os.path.join(self.destination, filename)
|
||||
|
||||
fl = FileList.merge([ self.file_lists[i] for i in file_lists ])
|
||||
fl = fl.copy()
|
||||
fl.sort()
|
||||
|
||||
if self.build.get("exclude_empty_directories", True):
|
||||
fl = fl.filter_empty()
|
||||
|
||||
# Write the update information.
|
||||
update_files = [ ]
|
||||
update_xbit = [ ]
|
||||
update_directories = [ ]
|
||||
|
||||
for i in fl:
|
||||
if not i.directory:
|
||||
update_files.append(i.name)
|
||||
else:
|
||||
update_directories.append(i.name)
|
||||
|
||||
if i.executable:
|
||||
update_xbit.append(i.name)
|
||||
|
||||
update = { variant : { "version" : self.update_version, "pretty_version" : self.pretty_version, "files" : update_files, "directories" : update_directories, "xbit" : update_xbit } }
|
||||
|
||||
if self.include_update and not dlc:
|
||||
update_fn = os.path.join(self.destination, filename + ".update.json")
|
||||
|
||||
with open(update_fn, "wb") as f:
|
||||
json.dump(update, f)
|
||||
|
||||
fl.append(File("update", None, True, False))
|
||||
fl.append(File("update/current.json", update_fn, False, False))
|
||||
|
||||
# The mac transform.
|
||||
if format == "app-zip":
|
||||
fl = fl.mac_transform(self.app, self.documentation_patterns)
|
||||
|
||||
# If we're not an update file, prepend the directory.
|
||||
if (not dlc) and format != "update":
|
||||
fl.prepend_directory(filename)
|
||||
|
||||
if format == "tar.bz2":
|
||||
path += ".tar.bz2"
|
||||
pkg = TarPackage(path, "w:bz2")
|
||||
elif format == "update":
|
||||
path += ".update"
|
||||
pkg = TarPackage(path, "w", notime=True)
|
||||
elif format == "zip" or format == "app-zip":
|
||||
path += ".zip"
|
||||
pkg = ZipPackage(path)
|
||||
|
||||
for i, f in enumerate(fl):
|
||||
self.reporter.progress(_("Writing the [variant] [format] package."), i, len(fl), variant=variant, format=format)
|
||||
|
||||
if f.directory:
|
||||
pkg.add_directory(f.name, f.path)
|
||||
else:
|
||||
pkg.add_file(f.name, f.path, f.executable)
|
||||
|
||||
self.reporter.progress_done()
|
||||
pkg.close()
|
||||
|
||||
if format == "update":
|
||||
# Build the zsync file.
|
||||
|
||||
self.reporter.info(_("Making the [variant] update zsync file."), variant=variant)
|
||||
|
||||
cmd = [
|
||||
updater.zsync_path("zsyncmake"),
|
||||
"-z",
|
||||
# -u url to gzipped data - not a local filename!
|
||||
"-u", filename + ".update.gz",
|
||||
"-o", os.path.join(self.destination, filename + ".zsync"),
|
||||
os.path.abspath(path),
|
||||
]
|
||||
|
||||
subprocess.check_call([ renpy.fsencode(i) for i in cmd ])
|
||||
|
||||
# Build the sums file. This is a file with an adler32 hash of each 64k block
|
||||
# of the zsync file. It's used to help us determine how much of the file is
|
||||
# downloaded.
|
||||
with open(path, "rb") as src:
|
||||
with open(renpy.fsencode(os.path.join(self.destination, filename + ".sums")), "wb") as sums:
|
||||
while True:
|
||||
data = src.read(65536)
|
||||
|
||||
if not data:
|
||||
break
|
||||
|
||||
sums.write(struct.pack("I", zlib.adler32(data) & 0xffffffff))
|
||||
|
||||
if self.include_update and not self.build_update and not dlc:
|
||||
os.unlink(update_fn)
|
||||
|
||||
|
||||
def finish_updates(self, packages):
|
||||
"""
|
||||
Indexes the updates, then removes the .update files.
|
||||
"""
|
||||
|
||||
if not self.build_update:
|
||||
return
|
||||
|
||||
index = { }
|
||||
|
||||
def add_variant(variant):
|
||||
fn = renpy.fsencode(os.path.join(self.destination, self.base_name + "-" + variant + ".update"))
|
||||
|
||||
with open(fn, "rb") as f:
|
||||
digest = hashlib.sha256(f.read()).hexdigest()
|
||||
|
||||
index[variant] = {
|
||||
"version" : self.update_version,
|
||||
"pretty_version" : self.pretty_version,
|
||||
"digest" : digest,
|
||||
"zsync_url" : self.base_name + "-" + variant + ".zsync",
|
||||
"sums_url" : self.base_name + "-" + variant + ".sums",
|
||||
"json_url" : self.base_name + "-" + variant + ".update.json",
|
||||
}
|
||||
|
||||
os.unlink(fn)
|
||||
|
||||
for p in packages:
|
||||
if p["update"]:
|
||||
add_variant(p["name"])
|
||||
|
||||
fn = renpy.fsencode(os.path.join(self.destination, "updates.json"))
|
||||
with open(fn, "wb") as f:
|
||||
json.dump(index, f)
|
||||
|
||||
|
||||
def dump(self):
|
||||
for k, v in sorted(self.file_lists.items()):
|
||||
print
|
||||
print k + ":"
|
||||
|
||||
v.sort()
|
||||
|
||||
for i in v:
|
||||
print " ", i.name, "xbit" if i.executable else ""
|
||||
|
||||
class GuiReporter(object):
|
||||
"""
|
||||
Displays progress using the gui.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
# The time at which we should next report progress.
|
||||
self.next_progress = 0
|
||||
|
||||
def info(self, what, pause=False, **kwargs):
|
||||
if pause:
|
||||
interface.information(what, **kwargs)
|
||||
else:
|
||||
interface.processing(what, **kwargs)
|
||||
|
||||
def progress(self, what, complete, total, **kwargs):
|
||||
|
||||
if (complete > 0) and (time.time() < self.next_progress):
|
||||
return
|
||||
|
||||
interface.processing(what, _("Processed {b}[complete]{/b} of {b}[total]{/b} files."), complete=complete, total=total, **kwargs)
|
||||
|
||||
self.next_progress = time.time() + .05
|
||||
|
||||
def progress_done(self):
|
||||
return
|
||||
|
||||
|
||||
class TextReporter(object):
|
||||
"""
|
||||
Displays progress on the command line.
|
||||
"""
|
||||
|
||||
def info(self, what, pause=False, **kwargs):
|
||||
what = what.replace("[", "{")
|
||||
what = what.replace("]", "}")
|
||||
what = what.format(**kwargs)
|
||||
print what
|
||||
|
||||
def progress(self, what, done, total, **kwargs):
|
||||
what = what.replace("[", "{")
|
||||
what = what.replace("]", "}")
|
||||
what = what.format(**kwargs)
|
||||
|
||||
sys.stdout.write("\r{} - {} of {}".format(what, done + 1, total))
|
||||
sys.stdout.flush()
|
||||
|
||||
def progress_done(self):
|
||||
sys.stdout.write("\n")
|
||||
|
||||
|
||||
def distribute_command():
|
||||
ap = renpy.arguments.ArgumentParser()
|
||||
ap.add_argument("--destination", "--dest", default=None, action="store", help="The directory where the packaged files should be placed.")
|
||||
ap.add_argument("--no-update", default=True, action="store_false", dest="build_update", help="Prevents updates from being built.")
|
||||
ap.add_argument("project", help="The path to the project directory.")
|
||||
ap.add_argument("--package", action="append", help="If given, a package to build. Defaults to building all packages.")
|
||||
|
||||
args = ap.parse_args()
|
||||
|
||||
p = project.Project(args.project)
|
||||
|
||||
if args.package:
|
||||
packages = args.package
|
||||
else:
|
||||
packages = None
|
||||
|
||||
Distributor(p, destination=args.destination, reporter=TextReporter(), packages=packages, build_update=args.build_update)
|
||||
|
||||
return False
|
||||
|
||||
renpy.arguments.register_command("distribute", distribute_command)
|
||||
|
||||
label distribute:
|
||||
|
||||
python hide:
|
||||
|
||||
data = project.current.data
|
||||
d = distribute.Distributor(project.current, reporter=distribute.GuiReporter(), packages=data['packages'], build_update=data['build_update'])
|
||||
OpenDirectory(d.destination)()
|
||||
|
||||
interface.info(_("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."))
|
||||
|
||||
jump front_page
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,247 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
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 _("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:
|
||||
|
||||
$ description = pkg["description"]
|
||||
|
||||
textbutton "[description!q]" action PackageToggle(pkg["name"]) style "l_checkbox"
|
||||
|
||||
add SPACER
|
||||
|
||||
if project.current.dump["build"]["include_update"]:
|
||||
textbutton _("Build Updates") action DataToggle("build_update") style "l_checkbox"
|
||||
|
||||
|
||||
textbutton _("Back") action Jump("front_page") style "l_left_button"
|
||||
textbutton _("Build") action Jump("distribute") style "l_right_button"
|
||||
|
||||
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,421 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
# Editor Support.
|
||||
#
|
||||
# This contains code for scanning for editors, and for allowing the user to
|
||||
# select an editor.
|
||||
|
||||
init 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
|
||||
|
||||
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
|
||||
|
||||
for filename in glob.glob(d + "/*/*.edit.py"):
|
||||
scan_editor(filename)
|
||||
|
||||
########################################################################
|
||||
|
||||
# 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 = _("The 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:
|
||||
return True
|
||||
|
||||
return renpy.invoke_in_new_context(renpy.call_screen, "editor")
|
||||
|
||||
##########################################################################
|
||||
# Editing actions.
|
||||
|
||||
|
||||
class Edit(Action):
|
||||
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 EditAll(Action):
|
||||
"""
|
||||
Opens all scripts that are part of the current project in a web browser.
|
||||
"""
|
||||
|
||||
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,223 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
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.
|
||||
"""
|
||||
|
||||
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):
|
||||
|
||||
directory = renpy.fsencode(self.directory)
|
||||
|
||||
if renpy.windows:
|
||||
os.startfile(directory)
|
||||
elif renpy.macintosh:
|
||||
subprocess.Popen([ "open", directory ])
|
||||
else:
|
||||
subprocess.Popen([ "xdg-open", directory ])
|
||||
|
||||
# Used for testing.
|
||||
def Relaunch():
|
||||
renpy.quit(relaunch=True)
|
||||
|
||||
screen front_page:
|
||||
frame:
|
||||
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":
|
||||
text "PROJECTS:" style "l_label_text" size 36 yoffset 10
|
||||
|
||||
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
|
||||
|
||||
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"
|
||||
|
||||
|
||||
|
||||
# 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
|
||||
|
||||
vbox:
|
||||
|
||||
if projects:
|
||||
|
||||
for p in projects:
|
||||
|
||||
textbutton "[p.name!q]":
|
||||
action project.Select(p)
|
||||
style "l_list"
|
||||
|
||||
null height 12
|
||||
|
||||
textbutton _("Tutorial") action project.Select("tutorial") style "l_list"
|
||||
textbutton _("The Question") action project.Select("the_question") style "l_list"
|
||||
|
||||
|
||||
# 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") style "l_list"
|
||||
# textbutton _("save") action None style "l_list"
|
||||
|
||||
vbox:
|
||||
|
||||
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 "Relaunch" action Relaunch
|
||||
|
||||
frame style "l_indent":
|
||||
has vbox
|
||||
|
||||
if ability.can_distribute:
|
||||
textbutton _("Build Distributions") action Jump("build_distributions")
|
||||
|
||||
textbutton _("Generate Translations") action Jump("translate")
|
||||
|
||||
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
|
||||
|
||||
@@ -1,391 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
################################################################################
|
||||
# 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
|
||||
|
||||
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 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 Return(False) style "l_left_button"
|
||||
|
||||
if continue_:
|
||||
textbutton _("Continue") action Return(True) style "l_right_button"
|
||||
|
||||
|
||||
screen launcher_input:
|
||||
|
||||
frame:
|
||||
style "l_root"
|
||||
|
||||
frame:
|
||||
style_group "l_info"
|
||||
|
||||
has vbox
|
||||
|
||||
text message
|
||||
|
||||
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
|
||||
|
||||
def common(title, title_color, message, submessage=None, back=False, continue_=False, pause0=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 True, a back button will be present. If it's clicked, False will
|
||||
be returned.
|
||||
|
||||
`continue_`
|
||||
If True, a continue button will be present. If it's clicked, True
|
||||
will be returned.
|
||||
|
||||
`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.
|
||||
|
||||
|
||||
Other keyword arguments are passed to the screen itself.
|
||||
"""
|
||||
|
||||
if pause0:
|
||||
ui.pausebehavior(0)
|
||||
|
||||
return renpy.call_screen("common", title=title, title_color=title_color, message=message, submessage=submessage, back=back, continue_=continue_, **kwargs)
|
||||
|
||||
|
||||
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.
|
||||
|
||||
Keyword arguments are passed into the screen so that they can be substituted into
|
||||
the message.
|
||||
"""
|
||||
|
||||
common(_("ERROR"), store.ERROR_COLOR, message=message, submessage=submessage, back=True, **kwargs)
|
||||
|
||||
|
||||
if label:
|
||||
renpy.jump(label)
|
||||
|
||||
@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,
|
||||
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_=True, **kwargs)
|
||||
else:
|
||||
common(_("INFORMATION"), store.INFO_COLOR, message, submessage, pause=0, **kwargs)
|
||||
|
||||
|
||||
def interaction(title, message, submessage=None, **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.
|
||||
"""
|
||||
|
||||
common(title, store.INTERACTION_COLOR, message, submessage, pause0=True, **kwargs)
|
||||
|
||||
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)
|
||||
|
||||
|
Before Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
@@ -1,262 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
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,109 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
init python:
|
||||
import shutil
|
||||
import os
|
||||
import time
|
||||
import re
|
||||
|
||||
screen select_template:
|
||||
|
||||
default result = project.manager.get("template")
|
||||
|
||||
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. Ren'Py ships with a default template that creates an English-language game with standard screens.")
|
||||
|
||||
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
# Delete the tmp directory, if it exists.
|
||||
if os.path.isdir(os.path.join(project_dir, "tmp")):
|
||||
os.path.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")
|
||||
|
||||
save_dir = project_name + "-" + str(int(time.time()))
|
||||
options = re.sub(r'template-\d+', save_dir, options)
|
||||
|
||||
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,301 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
## 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 = "logo.png"
|
||||
config.windows_icon = "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"),
|
||||
),
|
||||
]
|
||||
|
||||
config.rollback_enabled = 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.
|
||||
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
|
||||
|
||||
## 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("**.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("**/saves/", None)
|
||||
build.classify_renpy("**/tmp/", None)
|
||||
build.classify_renpy("**/.Editra", None)
|
||||
|
||||
# main source.
|
||||
build.classify_renpy("renpy.py", "source")
|
||||
build.classify_renpy("renpy/**", "source")
|
||||
|
||||
# games.
|
||||
build.classify_renpy("launcher/game/theme/", None)
|
||||
build.classify_renpy("launcher/**", "source")
|
||||
build.classify_renpy("template/**", "source")
|
||||
build.classify_renpy("the_question/**", "source")
|
||||
build.classify_renpy("tutorial/**", "source")
|
||||
|
||||
# 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/pysdlsound/", "source")
|
||||
build.classify_renpy("module/pysdlsound/*.py", "source")
|
||||
build.classify_renpy("module/pysdlsound/*.pyx", "source")
|
||||
|
||||
# all-platforms binary.
|
||||
build.classify_renpy("lib/*/renpy", None)
|
||||
build.classify_renpy("lib/*/renpy.exe", None)
|
||||
build.classify_renpy("lib/**", "binary")
|
||||
build.classify_renpy("renpy.sh", "binary")
|
||||
build.classify_renpy("renpy.exe", "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")
|
||||
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)
|
||||
|
||||
@@ -1,175 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
init python in distribute:
|
||||
|
||||
import time
|
||||
import zipfile
|
||||
import tarfile
|
||||
import zlib
|
||||
import struct
|
||||
import stat
|
||||
|
||||
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)
|
||||
|
||||
def add_file(self, name, path, xbit):
|
||||
|
||||
if path is None:
|
||||
raise Exception("path for " + name + " must not be None.")
|
||||
|
||||
zi = zipfile.ZipInfo(name)
|
||||
|
||||
s = os.stat(path)
|
||||
zi.date_time = time.gmtime(s.st_mtime)[:6]
|
||||
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 + "/")
|
||||
|
||||
s = os.stat(path)
|
||||
zi.date_time = time.gmtime(s.st_mtime)[:6]
|
||||
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()
|
||||
|
Before Width: | Height: | Size: 687 B |
@@ -1,202 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
init python:
|
||||
if persistent.gl_enable is None:
|
||||
persistent.gl_enable = True
|
||||
|
||||
config.gl_enable = persistent.gl_enable
|
||||
|
||||
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.title(), i))
|
||||
|
||||
return rv
|
||||
|
||||
|
||||
screen preferences:
|
||||
|
||||
$ translations = scan_translations()
|
||||
|
||||
frame:
|
||||
style_group "l"
|
||||
style "l_root"
|
||||
|
||||
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")
|
||||
else:
|
||||
textbutton _("Not Set") action Jump("projects_directory_preference")
|
||||
|
||||
|
||||
|
||||
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")
|
||||
else:
|
||||
textbutton _("Not Set") action Jump("editor_preference")
|
||||
|
||||
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")
|
||||
|
||||
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
|
||||
|
||||
# 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,536 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
# Code that manages projects.
|
||||
|
||||
init python:
|
||||
try:
|
||||
import EasyDialogsWin as EasyDialogs
|
||||
except:
|
||||
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
|
||||
|
||||
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.
|
||||
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" ])
|
||||
|
||||
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):
|
||||
"""
|
||||
Launches the project.
|
||||
|
||||
`args`
|
||||
Additional arguments to give to the project.
|
||||
|
||||
`wait`
|
||||
If true, waits for the launched project to terminate before
|
||||
continuing.
|
||||
"""
|
||||
|
||||
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, "-EOO", 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")
|
||||
|
||||
# Launch the project.
|
||||
with interface.error_handling("launching the project"):
|
||||
cmd = [ renpy.fsencode(i) for i in cmd ]
|
||||
|
||||
p = subprocess.Popen(cmd)
|
||||
|
||||
if wait:
|
||||
p.wait()
|
||||
|
||||
def update_dump(self, force=False, gui=True):
|
||||
"""
|
||||
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..."))
|
||||
|
||||
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
|
||||
|
||||
m = re.search(r".*#\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 = "{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")) )
|
||||
|
||||
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 os.listdir(d):
|
||||
ppath = os.path.join(d, pdir)
|
||||
|
||||
# A project must be a directory.
|
||||
if not os.path.isdir(ppath):
|
||||
continue
|
||||
|
||||
# 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 __call__(self):
|
||||
self.project.launch()
|
||||
|
||||
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 = persistent.projects_directory
|
||||
|
||||
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()
|
||||
p.wait()
|
||||
|
||||
if choice:
|
||||
path = renpy.fsdecode(choice)
|
||||
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
path = None
|
||||
interface.error(_("Ren'Py was unable to run python with tkinter to choose the projects directory."), label=None)
|
||||
|
||||
if path is None:
|
||||
path = default_path
|
||||
interface.info(_("Ren'Py has set the projects directory to:"), "[path!q]", path=path)
|
||||
|
||||
path = renpy.fsdecode(path)
|
||||
|
||||
persistent.projects_directory = path
|
||||
project.manager.scan()
|
||||
|
||||
return
|
||||
@@ -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,4 +0,0 @@
|
||||
init -999:
|
||||
$ config.script_version = (6, 15, 7)
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 96 B |
@@ -1,295 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
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 = "pattern.png"
|
||||
|
||||
# A displayable used for the background of everything.
|
||||
BACKGROUND = "background.png"
|
||||
|
||||
# A displayable used for the background of windows
|
||||
# containing commands, preferences, and navigation info.
|
||||
WINDOW = Frame("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"
|
||||
|
||||
|
||||
init 1 python:
|
||||
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)
|
||||
|
||||
# FONTS/WEIGHTS
|
||||
LIGHT = "Roboto-Light.ttf"
|
||||
REGULAR = "Roboto-Regular.ttf"
|
||||
DARK = "Roboto-Medium.ttf"
|
||||
|
||||
# DIVIDING THE SCREEN
|
||||
ONETHIRD = 258
|
||||
TWOTHIRDS = 496
|
||||
ONEHALF = 377
|
||||
|
||||
# Default style.
|
||||
style.l_default = Style(style.default)
|
||||
style.l_default.font = LIGHT
|
||||
style.l_default.color = TEXT
|
||||
style.l_default.idle_color = IDLE
|
||||
style.l_default.hover_color = HOVER
|
||||
style.l_default.size = 18
|
||||
|
||||
style.l_text = Style(style.l_default)
|
||||
|
||||
style.l_button = Style(style.l_default)
|
||||
style.l_button_text = Style(style.l_default)
|
||||
style.l_button_text.insensitive_color = DISABLED
|
||||
style.l_button_text.selected_font = REGULAR
|
||||
|
||||
# A small button, used at the bottom of the screen.
|
||||
style.l_link = Style(style.l_default)
|
||||
style.l_link_text = Style(style.l_default)
|
||||
style.l_link_text.size = 14
|
||||
style.l_link_text.font = LIGHT
|
||||
|
||||
# Action buttons on the bottom of the screen.
|
||||
style.l_right_button = Style(style.l_default)
|
||||
style.l_right_button.xalign = 1.0
|
||||
style.l_right_button.ypos = 600 - 128 + 12
|
||||
style.l_right_button.left_margin = 8 + INDENT
|
||||
style.l_right_button.right_margin = 10 + INDENT
|
||||
style.l_right_button_text = Style(style.l_default)
|
||||
style.l_right_button_text.size = 30
|
||||
|
||||
style.l_left_button = Style(style.l_right_button)
|
||||
style.l_left_button.xalign = 0.0
|
||||
style.l_left_button_text = Style(style.l_right_button_text)
|
||||
|
||||
|
||||
# The root frame. This contains everything but the bottom navigation, back
|
||||
# button, and tooltip button.
|
||||
style.l_root = Style(style.l_default)
|
||||
style.l_root.background = BACKGROUND
|
||||
style.l_root.xpadding = 10
|
||||
style.l_root.top_padding = 64
|
||||
style.l_root.bottom_padding = 128
|
||||
|
||||
# An inner window.
|
||||
style.l_window = Style(style.l_default)
|
||||
|
||||
style.l_window.background = WINDOW
|
||||
|
||||
style.l_window.left_padding = 6
|
||||
style.l_window.xfill = True
|
||||
style.l_window.yfill = True
|
||||
|
||||
|
||||
# Normal-sized labels.
|
||||
style.l_label = Style(style.l_default)
|
||||
style.l_label.xfill = True
|
||||
style.l_label.top_padding = 10
|
||||
style.l_label.bottom_padding = 8
|
||||
style.l_label.bottom_margin = 12
|
||||
style.l_label.background = SEPARATOR
|
||||
style.l_label_text = Style(style.l_default)
|
||||
style.l_label_text.size = 24
|
||||
style.l_label_text.xpos = INDENT
|
||||
style.l_label_text.yoffset = 6
|
||||
|
||||
# Small labels.
|
||||
style.l_label_small = Style(style.l_default)
|
||||
style.l_label_small.xfill = True
|
||||
style.l_label_small.bottom_padding = 8
|
||||
style.l_label_small.bottom_margin = HALF_SPACER_HEIGHT
|
||||
style.l_label_small.background = SEPARATOR
|
||||
style.l_label_small_text = Style(style.l_default)
|
||||
style.l_label_small_text.xpos = INDENT
|
||||
style.l_label_small_text.yoffset = 6
|
||||
style.l_label_small_text.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 = Style(style.l_default)
|
||||
style.l_alternate.xalign = 1.0
|
||||
style.l_alternate.yalign = 1.0
|
||||
style.l_alternate.yoffset = 4
|
||||
style.l_alternate.right_margin = INDENT
|
||||
style.l_alternate_text = Style(style.l_default)
|
||||
style.l_alternate_text.size = 14
|
||||
style.l_alternate_text.font = LIGHT
|
||||
style.l_alternate_text.text_align = 1.0
|
||||
|
||||
style.l_small_button = Style(style.l_button)
|
||||
style.l_small_button_text = Style(style.l_button_text)
|
||||
style.l_small_button_text.size = 14
|
||||
style.l_small_text = Style(style.l_text)
|
||||
style.l_small_text.size = 14
|
||||
|
||||
# Indents its contents.
|
||||
style.l_indent = Style(style.l_default)
|
||||
style.l_indent.left_margin = INDENT
|
||||
|
||||
# Indents its contents and pads them vertically.
|
||||
style.l_indent_margin = Style(style.l_indent)
|
||||
style.l_indent_margin.ymargin = 6
|
||||
|
||||
# List button.
|
||||
style.l_list = Style(style.l_default)
|
||||
style.l_list.left_padding = HALF_INDENT
|
||||
style.l_list.xfill = True
|
||||
style.l_list.selected_background = REVERSE_IDLE
|
||||
style.l_list.selected_hover_background = REVERSE_HOVER
|
||||
style.l_list_text = Style(style.l_default)
|
||||
style.l_list_text.idle_color = IDLE
|
||||
style.l_list_text.hover_color = HOVER
|
||||
style.l_list_text.selected_idle_color = REVERSE_TEXT
|
||||
style.l_list_text.selected_hover_color = REVERSE_TEXT
|
||||
style.l_list_text.insensitive_color = DISABLED
|
||||
|
||||
style.l_list2 = Style(style.l_list)
|
||||
style.l_list2.left_padding = HALF_INDENT + INDENT
|
||||
style.l_list2_text = Style(style.l_list_text)
|
||||
|
||||
|
||||
# Scrollbar.
|
||||
style.l_vscrollbar = Style(style.l_default)
|
||||
style.l_vscrollbar.thumb = Fixed(
|
||||
Solid(SCROLLBAR_IDLE, xmaximum=8, xalign=0.5),
|
||||
Image("vscrollbar_center.png", xalign=0.5, yalign=0.5),
|
||||
xmaximum = SCROLLBAR_SIZE)
|
||||
style.l_vscrollbar.hover_thumb = Fixed(
|
||||
Solid(SCROLLBAR_HOVER, xmaximum=8, xalign=0.5),
|
||||
Image("vscrollbar_center.png", xalign=0.5, yalign=0.5),
|
||||
xmaximum = SCROLLBAR_SIZE)
|
||||
style.l_vscrollbar.xmaximum = SCROLLBAR_SIZE
|
||||
style.l_vscrollbar.bar_vertical = True
|
||||
style.l_vscrollbar.bar_invert = True
|
||||
style.l_vscrollbar.unscrollable = "hide"
|
||||
|
||||
|
||||
# Information window.
|
||||
style.l_info_vbox = Style(style.vbox)
|
||||
style.l_info_vbox.yalign = 0.5
|
||||
style.l_info_vbox.xalign = 0.5
|
||||
style.l_info_vbox.xfill = True
|
||||
|
||||
style.l_info_frame = Style(style.l_default)
|
||||
style.l_info_frame.ypadding = 21
|
||||
style.l_info_frame.xfill = True
|
||||
|
||||
style.l_info_frame.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),
|
||||
)
|
||||
|
||||
style.l_info_frame.yminimum = 180
|
||||
style.l_info_frame.ypos = 100
|
||||
|
||||
style.l_info_label = Style(style.l_default)
|
||||
style.l_info_label.xalign = 0.5
|
||||
style.l_info_label.ypos = 100
|
||||
style.l_info_label.yanchor = 1.0
|
||||
style.l_info_label.yoffset = 12
|
||||
style.l_info_label_text = Style(style.l_default)
|
||||
style.l_info_label_text.size = 36
|
||||
|
||||
style.l_info_text = Style(style.l_default)
|
||||
style.l_info_text.xalign = 0.5
|
||||
|
||||
style.l_info_button = Style(style.l_button)
|
||||
style.l_info_button.xalign = 0.5
|
||||
style.l_info_button_text = Style(style.l_button_text)
|
||||
|
||||
# Code navigation
|
||||
style.l_navigation_button = Style(style.l_button)
|
||||
style.l_navigation_button.size_group = "navigation"
|
||||
style.l_navigation_button.right_margin = INDENT
|
||||
style.l_navigation_button.top_margin = 3
|
||||
style.l_navigation_button_text = Style(style.l_button_text)
|
||||
style.l_navigation_button_text.size = 14
|
||||
style.l_navigation_button_text.font = REGULAR
|
||||
|
||||
style.l_navigation_text = Style(style.l_text)
|
||||
style.l_navigation_text.size = 12
|
||||
style.l_navigation_text.font = LIGHT
|
||||
style.l_navigation_text.color = TEXT
|
||||
|
||||
# Check boxes
|
||||
style.l_checkbox = Style(style.l_button)
|
||||
style.l_checkbox.left_padding = INDENT
|
||||
|
||||
def checkbox(full, color):
|
||||
if full:
|
||||
return im.Twocolor("checkbox_full.png", color, color, yalign=0.5)
|
||||
else:
|
||||
return im.Twocolor("checkbox_empty.png", color, color, yalign=0.5)
|
||||
|
||||
style.l_checkbox.background = checkbox(False, IDLE)
|
||||
style.l_checkbox.hover_background = checkbox(False, HOVER)
|
||||
style.l_checkbox.selected_idle_background = checkbox(True, IDLE)
|
||||
style.l_checkbox.selected_hover_background = checkbox(True, HOVER)
|
||||
style.l_checkbox.insensitive_background = checkbox(False, DISABLED)
|
||||
|
||||
style.l_checkbox_text = Style(style.l_button_text)
|
||||
style.l_checkbox_text.selected_font = LIGHT
|
||||
|
||||
# A normal button that lines up with checkboxes.
|
||||
style.l_nonbox = Style(style.l_button)
|
||||
style.l_nonbox.xpadding = INDENT
|
||||
style.l_nonbox_text = Style(style.l_button_text)
|
||||
style.l_nonbox_text.selected_font = LIGHT
|
||||
|
||||
# A progress bar and its frame.
|
||||
style.l_progress_frame = Style(style.l_default)
|
||||
style.l_progress_frame.background = Frame(PATTERN, 0, 0, tile=True)
|
||||
style.l_progress_frame.ypadding = 5
|
||||
|
||||
style.l_progress_bar = Style(style.l_default)
|
||||
style.l_progress_bar.left_bar = REVERSE_IDLE
|
||||
style.l_progress_bar.right_bar = Null()
|
||||
style.l_progress_bar.ymaximum = 24
|
||||
|
||||
# The projects window.
|
||||
style.l_projects = Style(style.l_default)
|
||||
style.l_projects.background = PROJECTS_WINDOW
|
||||
@@ -1,586 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
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",
|
||||
|
||||
## 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,26 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
# 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
|
||||
|
||||
# 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)
|
||||
@@ -1,34 +0,0 @@
|
||||
init python:
|
||||
|
||||
if persistent.translate_language is None:
|
||||
persistent.translate_language = "english"
|
||||
|
||||
label translate:
|
||||
|
||||
python:
|
||||
|
||||
language = interface.input(_("Create or Update Translations"), _("Please enter the name of the language for which you want to create or update translations."), filename=True, default=persistent.translate_language, cancel=Jump("front_page"))
|
||||
|
||||
language = language.strip()
|
||||
|
||||
if not language:
|
||||
interface.error(_("The language name can not be the empty string."))
|
||||
|
||||
persistent.translate_language = language
|
||||
|
||||
args = [ "translate", language ]
|
||||
|
||||
if language == "rot13":
|
||||
args.append("--rot13")
|
||||
else:
|
||||
args.append("--empty")
|
||||
|
||||
interface.processing(_("Ren'Py is generating translations...."))
|
||||
project.current.launch(args, wait=True)
|
||||
project.current.update_dump(force=True)
|
||||
|
||||
interface.info(_("Ren'Py has finished generating [language] translations."))
|
||||
|
||||
jump front_page
|
||||
|
||||
|
||||
@@ -1,171 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
init python:
|
||||
# This can be one of None, "available", "not-available", or "error".
|
||||
#
|
||||
# It must be None for a release.
|
||||
UPDATE_SIMULATE = None
|
||||
|
||||
PUBLIC_KEY = "renpy_public.pem"
|
||||
|
||||
UPDATE_URLS = {
|
||||
"Release" : "http://update.renpy.org/release/updates.json",
|
||||
"Prerelease" : "http://update.renpy.org/prerelease/updates.json",
|
||||
"Experimental" : "http://update.renpy.org/experimental/updates.json"
|
||||
}
|
||||
|
||||
version_tuple = renpy.version(tuple=True)
|
||||
|
||||
DLC_URL = "http://update.renpy.org/{0}.{1}.{2}/updates.json".format(version_tuple[0], version_tuple[1], version_tuple[2])
|
||||
|
||||
if persistent.update_channel not in UPDATE_URLS:
|
||||
persistent.update_channel = "Release"
|
||||
|
||||
def check_dlc(name):
|
||||
"""
|
||||
Returns true if the named dlc package is present.
|
||||
"""
|
||||
|
||||
return name in updater.get_installed_packages()
|
||||
|
||||
def add_dlc(name):
|
||||
"""
|
||||
Adds the DLC package, if it doesn't already exist.
|
||||
|
||||
Returns True if the DLC is installed, False otherwise.
|
||||
"""
|
||||
|
||||
if check_dlc(name):
|
||||
return True
|
||||
|
||||
return renpy.invoke_in_new_context(updater.update, DLC_URL, add=[name], public_key=PUBLIC_KEY, simulate=UPDATE_SIMULATE, restart=False)
|
||||
|
||||
screen update_channel:
|
||||
|
||||
frame:
|
||||
style_group "l"
|
||||
style "l_root"
|
||||
|
||||
window:
|
||||
|
||||
has vbox
|
||||
|
||||
label _("Select Update Channel")
|
||||
|
||||
add HALF_SPACER
|
||||
|
||||
hbox:
|
||||
frame:
|
||||
style "l_indent"
|
||||
xfill True
|
||||
|
||||
has vbox
|
||||
|
||||
text _("The update channel controls the version of Ren'Py the updater will download. Please select an update channel:") style "l_small_text"
|
||||
|
||||
# Release
|
||||
add SPACER
|
||||
|
||||
textbutton _("Release") action [ SetField(persistent, "update_channel", "Release"), Jump("preferences") ]
|
||||
|
||||
add HALF_SPACER
|
||||
|
||||
frame:
|
||||
style "l_indent"
|
||||
text _("{b}Recommended.{/b} The version of Ren'Py that should be used in all newly-released games.") style "l_small_text"
|
||||
|
||||
# Prerelease
|
||||
add SPACER
|
||||
|
||||
textbutton _("Prerelease") action [ SetField(persistent, "update_channel", "Prerelease"), Jump("preferences") ]
|
||||
|
||||
add HALF_SPACER
|
||||
|
||||
frame:
|
||||
style "l_indent"
|
||||
text _("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.") style "l_small_text"
|
||||
|
||||
|
||||
# Experimental
|
||||
add SPACER
|
||||
|
||||
textbutton _("Experimental") action [ SetField(persistent, "update_channel", "Experimental"), Jump("preferences") ]
|
||||
|
||||
add HALF_SPACER
|
||||
|
||||
frame:
|
||||
style "l_indent"
|
||||
text _("Experimental versions of Ren'Py. You shouldn't select this channel unless asked by a Ren'Py developer.") style "l_small_text"
|
||||
|
||||
|
||||
textbutton _("Cancel") action Jump("preferences") style "l_left_button"
|
||||
|
||||
label update_preference:
|
||||
call screen update_channel
|
||||
return
|
||||
|
||||
screen updater:
|
||||
|
||||
frame:
|
||||
style "l_root"
|
||||
|
||||
frame:
|
||||
style_group "l_info"
|
||||
|
||||
has vbox
|
||||
|
||||
if u.state == u.ERROR:
|
||||
text _("An error has occured:")
|
||||
elif u.state == u.CHECKING:
|
||||
text _("Checking for updates.")
|
||||
elif u.state == u.UPDATE_NOT_AVAILABLE:
|
||||
text _("Ren'Py is up to date.")
|
||||
elif u.state == u.UPDATE_AVAILABLE:
|
||||
text _("[u.version] is now available. Do you want to install it?")
|
||||
elif u.state == u.PREPARING:
|
||||
text _("Preparing to download the update.")
|
||||
elif u.state == u.DOWNLOADING:
|
||||
text _("Downloading the update.")
|
||||
elif u.state == u.UNPACKING:
|
||||
text _("Unpacking the update.")
|
||||
elif u.state == u.FINISHING:
|
||||
text _("Finishing up.")
|
||||
elif u.state == u.DONE:
|
||||
text _("The update has been installed. Ren'Py will restart.")
|
||||
elif u.state == u.DONE_NO_RESTART:
|
||||
text _("The update has been installed.")
|
||||
elif u.state == u.CANCELLED:
|
||||
text _("The update was cancelled.")
|
||||
|
||||
if u.message is not None:
|
||||
add SPACER
|
||||
text "[u.message!q]"
|
||||
|
||||
if u.progress is not None:
|
||||
add SPACER
|
||||
|
||||
frame:
|
||||
style "l_progress_frame"
|
||||
|
||||
bar:
|
||||
range 1.0
|
||||
value u.progress
|
||||
style "l_progress_bar"
|
||||
|
||||
label _("Ren'Py Update") style "l_info_label"
|
||||
|
||||
if u.can_cancel:
|
||||
textbutton _("Cancel") action u.cancel style "l_left_button"
|
||||
|
||||
if u.can_proceed:
|
||||
textbutton _("Proceed") action u.proceed style "l_right_button"
|
||||
|
||||
label update:
|
||||
|
||||
python:
|
||||
updater.update(UPDATE_URLS[persistent.update_channel], simulate=UPDATE_SIMULATE, public_key=PUBLIC_KEY)
|
||||
|
||||
# This should never happen.
|
||||
jump front_page
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
init python in util:
|
||||
import os
|
||||
|
||||
def walk(directory, base=None):
|
||||
"""
|
||||
Walks through the directories and files underneath `directory`,
|
||||
yielding (name, isdir) tuples. The names are given relative to
|
||||
`base`, which defaults to `directory` if None.
|
||||
"""
|
||||
|
||||
directory = renpy.fsdecode(directory)
|
||||
|
||||
if base is None:
|
||||
base = directory
|
||||
else:
|
||||
base = renpy.fsdecode(base)
|
||||
|
||||
for subdir, directories, files in os.walk(directory):
|
||||
for fn in directories:
|
||||
fullfn = os.path.join(subdir, fn)
|
||||
relfn = os.path.relpath(fullfn, base)
|
||||
|
||||
relfn = relfn.replace("\\", "/")
|
||||
|
||||
yield relfn, True
|
||||
|
||||
for fn in files:
|
||||
fullfn = os.path.join(subdir, fn)
|
||||
relfn = os.path.relpath(fullfn, base)
|
||||
|
||||
relfn = relfn.replace("\\", "/")
|
||||
|
||||
yield relfn, False
|
||||
|
||||
|
Before Width: | Height: | Size: 106 B |
|
Before Width: | Height: | Size: 2.8 KiB |
@@ -1 +0,0 @@
|
||||
{"build_update": true, "packages": ["all", "linux", "mac", "win", "sdk", "source", "jedit", "editra-mac", "editra-linux", "editra-windows"], "type": "hidden"}
|
||||
@@ -1,286 +0,0 @@
|
||||
/*
|
||||
Based on zlib license - see http://www.gzip.org/zlib/zlib_license.html
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
"Philip D. Bober" <wildfire1138@mchsi.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* 4/17/04 - IMG_SavePNG & IMG_SavePNG_RW - Philip D. Bober
|
||||
* 11/08/2004 - Compr fix, levels -1,1-7 now work - Tyler Montbriand
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <SDL/SDL.h>
|
||||
#include <SDL/SDL_byteorder.h>
|
||||
#include <png.h>
|
||||
#include <zlib.h>
|
||||
#include "IMG_savepng.h"
|
||||
|
||||
#ifndef png_voidp
|
||||
#define png_voidp voidp
|
||||
#endif
|
||||
|
||||
int IMG_SavePNG(const char *file, SDL_Surface *surf,int compression){
|
||||
SDL_RWops *fp;
|
||||
int ret;
|
||||
|
||||
fp=SDL_RWFromFile(file,"wb");
|
||||
|
||||
if( fp == NULL ) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
ret=IMG_SavePNG_RW(fp,surf,compression);
|
||||
SDL_RWclose(fp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void png_write_data(png_structp png_ptr,png_bytep data, png_size_t length){
|
||||
SDL_RWops *rp = (SDL_RWops*) png_get_io_ptr(png_ptr);
|
||||
SDL_RWwrite(rp,data,1,length);
|
||||
}
|
||||
|
||||
int IMG_SavePNG_RW(SDL_RWops *src, SDL_Surface *surf,int compression){
|
||||
png_structp png_ptr;
|
||||
png_infop info_ptr;
|
||||
SDL_PixelFormat *fmt=NULL;
|
||||
SDL_Surface *tempsurf=NULL;
|
||||
int ret,funky_format,used_alpha;
|
||||
unsigned int i,temp_alpha;
|
||||
png_colorp palette;
|
||||
Uint8 *palette_alpha=NULL;
|
||||
png_byte **row_pointers=NULL;
|
||||
png_ptr=NULL;info_ptr=NULL;palette=NULL;ret=-1;
|
||||
funky_format=0;
|
||||
|
||||
if( !src || !surf) {
|
||||
goto savedone; /* Nothing to do. */
|
||||
}
|
||||
|
||||
row_pointers=(png_byte **)malloc(surf->h * sizeof(png_byte*));
|
||||
if (!row_pointers) {
|
||||
SDL_SetError("Couldn't allocate memory for rowpointers");
|
||||
goto savedone;
|
||||
}
|
||||
|
||||
png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,NULL,NULL);
|
||||
if (!png_ptr){
|
||||
SDL_SetError("Couldn't allocate memory for PNG file");
|
||||
goto savedone;
|
||||
}
|
||||
info_ptr= png_create_info_struct(png_ptr);
|
||||
if (!info_ptr){
|
||||
SDL_SetError("Couldn't allocate image information for PNG file");
|
||||
goto savedone;
|
||||
}
|
||||
/* setup custom writer functions */
|
||||
png_set_write_fn(png_ptr,(png_voidp)src,png_write_data,NULL);
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr))){
|
||||
SDL_SetError("Unknown error writing PNG");
|
||||
goto savedone;
|
||||
}
|
||||
|
||||
if(compression>Z_BEST_COMPRESSION)
|
||||
compression=Z_BEST_COMPRESSION;
|
||||
|
||||
if(compression == Z_NO_COMPRESSION) // No compression
|
||||
{
|
||||
png_set_filter(png_ptr,0,PNG_FILTER_NONE);
|
||||
png_set_compression_level(png_ptr,Z_NO_COMPRESSION);
|
||||
}
|
||||
else if(compression<0) // Default compression
|
||||
png_set_compression_level(png_ptr,Z_DEFAULT_COMPRESSION);
|
||||
else
|
||||
png_set_compression_level(png_ptr,compression);
|
||||
|
||||
fmt=surf->format;
|
||||
if(fmt->BitsPerPixel==8){ /* Paletted */
|
||||
png_set_IHDR(png_ptr,info_ptr,
|
||||
surf->w,surf->h,8,PNG_COLOR_TYPE_PALETTE,
|
||||
PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT,
|
||||
PNG_FILTER_TYPE_DEFAULT);
|
||||
palette=(png_colorp) malloc(fmt->palette->ncolors * sizeof(png_color));
|
||||
if (!palette) {
|
||||
SDL_SetError("Couldn't create memory for palette");
|
||||
goto savedone;
|
||||
}
|
||||
for (i=0;i<fmt->palette->ncolors;i++) {
|
||||
palette[i].red=fmt->palette->colors[i].r;
|
||||
palette[i].green=fmt->palette->colors[i].g;
|
||||
palette[i].blue=fmt->palette->colors[i].b;
|
||||
}
|
||||
png_set_PLTE(png_ptr,info_ptr,palette,fmt->palette->ncolors);
|
||||
if (surf->flags&SDL_SRCCOLORKEY) {
|
||||
palette_alpha=(Uint8 *)malloc((fmt->colorkey+1)*sizeof(Uint8));
|
||||
if (!palette_alpha) {
|
||||
SDL_SetError("Couldn't create memory for palette transparency");
|
||||
goto savedone;
|
||||
}
|
||||
/* FIXME: memset? */
|
||||
for (i=0;i<(fmt->colorkey+1);i++) {
|
||||
palette_alpha[i]=255;
|
||||
}
|
||||
palette_alpha[fmt->colorkey]=0;
|
||||
png_set_tRNS(png_ptr,info_ptr,palette_alpha,fmt->colorkey+1,NULL);
|
||||
}
|
||||
}else{ /* Truecolor */
|
||||
if (fmt->Amask) {
|
||||
png_set_IHDR(png_ptr,info_ptr,
|
||||
surf->w,surf->h,8,PNG_COLOR_TYPE_RGB_ALPHA,
|
||||
PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT,
|
||||
PNG_FILTER_TYPE_DEFAULT);
|
||||
} else {
|
||||
png_set_IHDR(png_ptr,info_ptr,
|
||||
surf->w,surf->h,8,PNG_COLOR_TYPE_RGB,
|
||||
PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT,
|
||||
PNG_FILTER_TYPE_DEFAULT);
|
||||
}
|
||||
}
|
||||
png_write_info(png_ptr, info_ptr);
|
||||
|
||||
if (fmt->BitsPerPixel==8) { /* Paletted */
|
||||
for(i=0;i<surf->h;i++){
|
||||
row_pointers[i]= ((png_byte*)surf->pixels) + i*surf->pitch;
|
||||
}
|
||||
if(SDL_MUSTLOCK(surf)){
|
||||
SDL_LockSurface(surf);
|
||||
}
|
||||
png_write_image(png_ptr, row_pointers);
|
||||
if(SDL_MUSTLOCK(surf)){
|
||||
SDL_UnlockSurface(surf);
|
||||
}
|
||||
}else{ /* Truecolor */
|
||||
if(fmt->BytesPerPixel==3){
|
||||
if(fmt->Amask){ /* check for 24 bit with alpha */
|
||||
funky_format=1;
|
||||
}else{
|
||||
/* Check for RGB/BGR/GBR/RBG/etc surfaces.*/
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
if(fmt->Rmask!=0xFF0000
|
||||
|| fmt->Gmask!=0x00FF00
|
||||
|| fmt->Bmask!=0x0000FF){
|
||||
#else
|
||||
if(fmt->Rmask!=0x0000FF
|
||||
|| fmt->Gmask!=0x00FF00
|
||||
|| fmt->Bmask!=0xFF0000){
|
||||
#endif
|
||||
funky_format=1;
|
||||
}
|
||||
}
|
||||
}else if (fmt->BytesPerPixel==4){
|
||||
if (!fmt->Amask) { /* check for 32bit but no alpha */
|
||||
funky_format=1;
|
||||
}else{
|
||||
/* Check for ARGB/ABGR/GBAR/RABG/etc surfaces.*/
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
if(fmt->Rmask!=0xFF000000
|
||||
|| fmt->Gmask!=0x00FF0000
|
||||
|| fmt->Bmask!=0x0000FF00
|
||||
|| fmt->Amask!=0x000000FF){
|
||||
#else
|
||||
if(fmt->Rmask!=0x000000FF
|
||||
|| fmt->Gmask!=0x0000FF00
|
||||
|| fmt->Bmask!=0x00FF0000
|
||||
|| fmt->Amask!=0xFF000000){
|
||||
#endif
|
||||
funky_format=1;
|
||||
}
|
||||
}
|
||||
}else{ /* 555 or 565 16 bit color */
|
||||
funky_format=1;
|
||||
}
|
||||
if (funky_format) {
|
||||
/* Allocate non-funky format, and copy pixeldata in*/
|
||||
if(fmt->Amask){
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
tempsurf = SDL_CreateRGBSurface(SDL_SWSURFACE, surf->w, surf->h, 24,
|
||||
0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
|
||||
#else
|
||||
tempsurf = SDL_CreateRGBSurface(SDL_SWSURFACE, surf->w, surf->h, 24,
|
||||
0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
|
||||
#endif
|
||||
}else{
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
tempsurf = SDL_CreateRGBSurface(SDL_SWSURFACE, surf->w, surf->h, 24,
|
||||
0xff0000, 0x00ff00, 0x0000ff, 0x00000000);
|
||||
#else
|
||||
tempsurf = SDL_CreateRGBSurface(SDL_SWSURFACE, surf->w, surf->h, 24,
|
||||
0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000);
|
||||
#endif
|
||||
}
|
||||
if(!tempsurf){
|
||||
SDL_SetError("Couldn't allocate temp surface");
|
||||
goto savedone;
|
||||
}
|
||||
if(surf->flags&SDL_SRCALPHA){
|
||||
temp_alpha=fmt->alpha;
|
||||
used_alpha=1;
|
||||
SDL_SetAlpha(surf,0,255); /* Set for an opaque blit */
|
||||
}else{
|
||||
used_alpha=0;
|
||||
}
|
||||
if(SDL_BlitSurface(surf,NULL,tempsurf,NULL)!=0){
|
||||
SDL_SetError("Couldn't blit surface to temp surface");
|
||||
SDL_FreeSurface(tempsurf);
|
||||
goto savedone;
|
||||
}
|
||||
if (used_alpha) {
|
||||
SDL_SetAlpha(surf,SDL_SRCALPHA,(Uint8)temp_alpha); /* Restore alpha settings*/
|
||||
}
|
||||
for(i=0;i<tempsurf->h;i++){
|
||||
row_pointers[i]= ((png_byte*)tempsurf->pixels) + i*tempsurf->pitch;
|
||||
}
|
||||
if(SDL_MUSTLOCK(tempsurf)){
|
||||
SDL_LockSurface(tempsurf);
|
||||
}
|
||||
png_write_image(png_ptr, row_pointers);
|
||||
if(SDL_MUSTLOCK(tempsurf)){
|
||||
SDL_UnlockSurface(tempsurf);
|
||||
}
|
||||
SDL_FreeSurface(tempsurf);
|
||||
} else {
|
||||
for(i=0;i<surf->h;i++){
|
||||
row_pointers[i]= ((png_byte*)surf->pixels) + i*surf->pitch;
|
||||
}
|
||||
if(SDL_MUSTLOCK(surf)){
|
||||
SDL_LockSurface(surf);
|
||||
}
|
||||
png_write_image(png_ptr, row_pointers);
|
||||
if(SDL_MUSTLOCK(surf)){
|
||||
SDL_UnlockSurface(surf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
png_write_end(png_ptr, NULL);
|
||||
ret=0; /* got here, so nothing went wrong. YAY! */
|
||||
|
||||
savedone: /* clean up and return */
|
||||
png_destroy_write_struct(&png_ptr,&info_ptr);
|
||||
if (palette) {
|
||||
free(palette);
|
||||
}
|
||||
if (palette_alpha) {
|
||||
free(palette_alpha);
|
||||
}
|
||||
if (row_pointers) {
|
||||
free(row_pointers);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
Based on zlib license - see http://www.gzip.org/zlib/zlib_license.html
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
"Philip D. Bober" <wildfire1138@mchsi.com>
|
||||
*/
|
||||
#ifndef __IMG_SAVETOPNG_H__
|
||||
#define __IMG_SAVETOPNG_H__
|
||||
|
||||
/* #include <SDL/begin_code.h> */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define IMG_COMPRESS_OFF 0
|
||||
#define IMG_COMPRESS_MAX 9
|
||||
#define IMG_COMPRESS_DEFAULT -1
|
||||
|
||||
/**
|
||||
* Takes a filename, a surface to save, and a compression level. The
|
||||
* compression level can be 0(min) through 9(max), or -1(default).
|
||||
*/
|
||||
DECLSPEC int SDLCALL IMG_SavePNG(const char *file,
|
||||
SDL_Surface *surf,
|
||||
int compression);
|
||||
/**
|
||||
* Takes a SDL_RWops pointer, a surface to save, and a compression level.
|
||||
* compression can be 0(min) through 9(max), or -1(default).
|
||||
*/
|
||||
DECLSPEC int SDLCALL IMG_SavePNG_RW(SDL_RWops *src,
|
||||
SDL_Surface *surf,
|
||||
int compression);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif/*__IMG_SAVETOPNG_H__*/
|
||||
@@ -1,3 +0,0 @@
|
||||
For instructions on compling the module yourself, please read:
|
||||
|
||||
http://www.bishoujo.us/renpy/dl/lgpl/README.txt
|
||||
@@ -1,430 +0,0 @@
|
||||
# -*- python -*-
|
||||
# Copyright 2004-2012 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.
|
||||
|
||||
def version():
|
||||
return (6, 12, 0)
|
||||
|
||||
cdef extern from "pygame/pygame.h":
|
||||
cdef struct SDL_RWops:
|
||||
pass
|
||||
|
||||
void import_pygame_rwobject()
|
||||
SDL_RWops* RWopsFromPython(object obj)
|
||||
|
||||
|
||||
cdef extern from "renpy.h":
|
||||
|
||||
void core_init()
|
||||
|
||||
void save_png_core(object, SDL_RWops *, int)
|
||||
|
||||
void pixellate32_core(object, object, int, int, int, int)
|
||||
void pixellate24_core(object, object, int, int, int, int)
|
||||
|
||||
void map32_core(object, object,
|
||||
char *,
|
||||
char *,
|
||||
char *,
|
||||
char *)
|
||||
|
||||
void map24_core(object, object,
|
||||
char *,
|
||||
char *,
|
||||
char *)
|
||||
|
||||
void linmap32_core(object, object,
|
||||
int,
|
||||
int,
|
||||
int,
|
||||
int)
|
||||
|
||||
void linmap24_core(object, object,
|
||||
int,
|
||||
int,
|
||||
int)
|
||||
|
||||
void xblur32_core(object, object, int)
|
||||
|
||||
void alphamunge_core(object, object, int, int, int, char *)
|
||||
|
||||
void scale32_core(object, object,
|
||||
float, float, float, float,
|
||||
float, float, float, float,
|
||||
int)
|
||||
|
||||
void scale24_core(object, object,
|
||||
float, float, float, float,
|
||||
float, float, float, float)
|
||||
|
||||
void transform32_core(object, object,
|
||||
float, float, float, float, float, float,
|
||||
int, float, int)
|
||||
|
||||
void blend32_core(object, object, object, int)
|
||||
|
||||
void imageblend32_core(object, object, object, object, int, char *)
|
||||
|
||||
void colormatrix32_core(object, object,
|
||||
float, float, float, float, float,
|
||||
float, float, float, float, float,
|
||||
float, float, float, float, float,
|
||||
float, float, float, float, float)
|
||||
|
||||
void staticgray_core(object, object,
|
||||
int, int, int, int, int, char *)
|
||||
|
||||
int subpixel32(object, object, float, float, int)
|
||||
|
||||
void PyErr_Clear()
|
||||
|
||||
|
||||
import pygame
|
||||
|
||||
PygameSurface = pygame.Surface
|
||||
|
||||
def save_png(surf, file, compress=-1):
|
||||
|
||||
if not isinstance(surf, PygameSurface):
|
||||
raise Exception("save_png requires a pygame Surface as its first argument.")
|
||||
|
||||
save_png_core(surf, RWopsFromPython(file), compress)
|
||||
|
||||
|
||||
def pixellate(pysrc, pydst, avgwidth, avgheight, outwidth, outheight):
|
||||
|
||||
if not isinstance(pysrc, PygameSurface):
|
||||
raise Exception("pixellate requires a pygame Surface as its first argument.")
|
||||
|
||||
if not isinstance(pydst, PygameSurface):
|
||||
raise Exception("pixellate requires a pygame Surface as its second argument.")
|
||||
|
||||
if pysrc.get_bitsize() not in (24, 32):
|
||||
raise Exception("pixellate requires a 24 or 32 bit surface.")
|
||||
|
||||
if pydst.get_bitsize() != pysrc.get_bitsize():
|
||||
raise Exception("pixellate requires both surfaces have the same bitsize.")
|
||||
|
||||
# pysrc.lock()
|
||||
# pydst.lock()
|
||||
|
||||
if pysrc.get_bitsize() == 32:
|
||||
pixellate32_core(pysrc, pydst, avgwidth, avgheight, outwidth, outheight)
|
||||
else:
|
||||
pixellate24_core(pysrc, pydst, avgwidth, avgheight, outwidth, outheight)
|
||||
|
||||
# pydst.unlock()
|
||||
# pysrc.unlock()
|
||||
|
||||
|
||||
# Please note that r, g, b, and a are not necessarily red, green, blue
|
||||
# and alpha. Instead, they are the first through fourth byte of data.
|
||||
# The mapping between byte and color/alpha varies from system to
|
||||
# system, and needs to be determined at a higher level.
|
||||
def map(pysrc, pydst, r, g, b, a): # @ReservedAssignment
|
||||
|
||||
if not isinstance(pysrc, PygameSurface):
|
||||
raise Exception("map requires a pygame Surface as its first argument.")
|
||||
|
||||
if not isinstance(pydst, PygameSurface):
|
||||
raise Exception("map requires a pygame Surface as its second argument.")
|
||||
|
||||
if pysrc.get_bitsize() not in (24, 32):
|
||||
raise Exception("map requires a 24 or 32 bit surface.")
|
||||
|
||||
if pydst.get_bitsize() != pysrc.get_bitsize():
|
||||
raise Exception("map requires both surfaces have the same bitsize.")
|
||||
|
||||
if pydst.get_size() != pysrc.get_size():
|
||||
raise Exception("map requires both surfaces have the same size.")
|
||||
|
||||
# pysrc.lock()
|
||||
# pydst.lock()
|
||||
|
||||
if pysrc.get_bitsize() == 32:
|
||||
map32_core(pysrc, pydst, r, g, b, a)
|
||||
else:
|
||||
map24_core(pysrc, pydst, r, g, b)
|
||||
|
||||
# pydst.unlock()
|
||||
# pysrc.unlock()
|
||||
|
||||
# Please note that r, g, b, and a are not necessarily red, green, blue
|
||||
# and alpha. Instead, they are the first through fourth byte of data.
|
||||
# The mapping between byte and color/alpha varies from system to
|
||||
# system, and needs to be determined at a higher level.
|
||||
def linmap(pysrc, pydst, r, g, b, a):
|
||||
|
||||
if not isinstance(pysrc, PygameSurface):
|
||||
raise Exception("map requires a pygame Surface as its first argument.")
|
||||
|
||||
if not isinstance(pydst, PygameSurface):
|
||||
raise Exception("map requires a pygame Surface as its second argument.")
|
||||
|
||||
if pysrc.get_bitsize() not in (24, 32):
|
||||
raise Exception("map requires a 24 or 32 bit surface.")
|
||||
|
||||
if pydst.get_bitsize() != pysrc.get_bitsize():
|
||||
raise Exception("map requires both surfaces have the same bitsize.")
|
||||
|
||||
if pydst.get_size() != pysrc.get_size():
|
||||
raise Exception("map requires both surfaces have the same size.")
|
||||
|
||||
# pysrc.lock()
|
||||
# pydst.lock()
|
||||
|
||||
if pysrc.get_bitsize() == 32:
|
||||
linmap32_core(pysrc, pydst, r, g, b, a)
|
||||
else:
|
||||
linmap24_core(pysrc, pydst, r, g, b)
|
||||
|
||||
# pydst.unlock()
|
||||
# pysrc.unlock()
|
||||
|
||||
|
||||
def alpha_munge(pysrc, pydst, srcchan, dstchan, amap):
|
||||
|
||||
if not isinstance(pysrc, PygameSurface):
|
||||
raise Exception("alpha_munge requires a pygame Surface as its first argument.")
|
||||
|
||||
if not isinstance(pydst, PygameSurface):
|
||||
raise Exception("alpha_munge requires a pygame Surface as its second argument.")
|
||||
|
||||
if pysrc.get_bitsize() not in (24, 32):
|
||||
raise Exception("alpha_munge requires a 24 or 32 bit surface.")
|
||||
|
||||
if pydst.get_bitsize() != pysrc.get_bitsize():
|
||||
raise Exception("alpha_munge requires both surfaces have the same bitsize.")
|
||||
|
||||
if pydst.get_size() != pysrc.get_size():
|
||||
raise Exception("alpha_munge requires both surfaces have the same size.")
|
||||
|
||||
|
||||
if pysrc.get_bitsize() == 24:
|
||||
bytes = 3
|
||||
else:
|
||||
bytes = 4
|
||||
|
||||
# pysrc.lock()
|
||||
# pydst.lock()
|
||||
|
||||
alphamunge_core(pysrc, pydst, bytes, srcchan, dstchan, amap)
|
||||
|
||||
# pydst.unlock()
|
||||
# pysrc.unlock()
|
||||
|
||||
|
||||
|
||||
|
||||
# def xblur(pysrc, pydst, radius):
|
||||
|
||||
# if not isinstance(pysrc, PygameSurface):
|
||||
# raise Exception("blur requires a pygame Surface as its first argument.")
|
||||
|
||||
# if not isinstance(pydst, PygameSurface):
|
||||
# raise Exception("blur requires a pygame Surface as its second argument.")
|
||||
|
||||
# if pysrc.get_bitsize() not in (24, 32):
|
||||
# raise Exception("blur requires a 24 or 32 bit surface.")
|
||||
|
||||
# if pydst.get_bitsize() != pysrc.get_bitsize():
|
||||
# raise Exception("blur requires both surfaces have the same bitsize.")
|
||||
|
||||
# if pydst.get_size() != pysrc.get_size():
|
||||
# raise Exception("blur requires both surfaces have the same size.")
|
||||
|
||||
# pysrc.lock()
|
||||
# pydst.lock()
|
||||
|
||||
# if pysrc.get_bitsize() == 32:
|
||||
# xblur32_core(pysrc, pydst, radius)
|
||||
# else:
|
||||
# # blur24_core(pysrc, pydst, radius)
|
||||
# assert False
|
||||
|
||||
|
||||
# pydst.unlock()
|
||||
# pysrc.unlock()
|
||||
|
||||
|
||||
# def stretch(pysrc, pydst, rect):
|
||||
|
||||
# if not isinstance(pysrc, PygameSurface):
|
||||
# raise Exception("stretch requires a pygame Surface as its first argument.")
|
||||
|
||||
# if not isinstance(pydst, PygameSurface):
|
||||
# raise Exception("stretch requires a pygame Surface as its second argument.")
|
||||
|
||||
# if pydst.get_bitsize() != pysrc.get_bitsize():
|
||||
# raise Exception("stretch requires both surfaces have the same bitsize.")
|
||||
|
||||
# if rect:
|
||||
# x, y, w, h = rect
|
||||
# else:
|
||||
# x, y = 0, 0
|
||||
# w, h = pysrc.get_size()
|
||||
|
||||
# return stretch_core(pysrc, pydst, x, y, w, h)
|
||||
|
||||
|
||||
def bilinear(pysrc, pydst,
|
||||
source_xoff=0.0, source_yoff=0.0, source_width=None, source_height=None,
|
||||
dest_xoff=0.0, dest_yoff=0.0, dest_width=None, dest_height=None,
|
||||
precise=0):
|
||||
|
||||
if not isinstance(pysrc, PygameSurface):
|
||||
raise Exception("bilinear requires a pygame Surface as its first argument.")
|
||||
|
||||
if not isinstance(pydst, PygameSurface):
|
||||
raise Exception("bilinear requires a pygame Surface as its second argument.")
|
||||
|
||||
if pysrc.get_bitsize() not in (24, 32):
|
||||
raise Exception("bilinear requires a 24 or 32 bit surface.")
|
||||
|
||||
if pydst.get_bitsize() != pysrc.get_bitsize():
|
||||
raise Exception("bilinear requires both surfaces have the same bitsize.")
|
||||
|
||||
if source_width is None or source_height is None:
|
||||
source_width, source_height = pysrc.get_size()
|
||||
|
||||
if dest_width is None or dest_height is None:
|
||||
dest_width, dest_height = pydst.get_size()
|
||||
|
||||
# pysrc.lock()
|
||||
# pydst.lock()
|
||||
|
||||
if pysrc.get_bitsize() == 32:
|
||||
scale32_core(pysrc, pydst,
|
||||
source_xoff, source_yoff, source_width, source_height,
|
||||
dest_xoff, dest_yoff, dest_width, dest_height, precise)
|
||||
|
||||
else:
|
||||
scale24_core(pysrc, pydst,
|
||||
source_xoff, source_yoff, source_width, source_height,
|
||||
dest_xoff, dest_yoff, dest_width, dest_height)
|
||||
|
||||
|
||||
# pydst.unlock()
|
||||
# pysrc.unlock()
|
||||
|
||||
|
||||
def check(surf):
|
||||
if not isinstance(surf, PygameSurface):
|
||||
raise Exception("Surface must be a pygame surface.")
|
||||
|
||||
if surf.get_bitsize() != 32:
|
||||
raise Exception("Surface must be 32-bit.")
|
||||
|
||||
|
||||
def transform(pysrc, pydst,
|
||||
corner_x, corner_y,
|
||||
xdx, ydx, xdy, ydy, a=1.0, precise=0):
|
||||
|
||||
check(pysrc)
|
||||
check(pydst)
|
||||
|
||||
# pysrc.lock()
|
||||
# pydst.lock()
|
||||
|
||||
transform32_core(pysrc, pydst,
|
||||
corner_x, corner_y,
|
||||
xdx, ydx,
|
||||
xdy, ydy,
|
||||
pysrc.get_shifts()[3], a, precise)
|
||||
|
||||
# pydst.unlock()
|
||||
# pysrc.unlock()
|
||||
|
||||
|
||||
def blend(pysrca, pysrcb, pydst, alpha):
|
||||
|
||||
check(pysrca)
|
||||
check(pysrcb)
|
||||
check(pydst)
|
||||
|
||||
# pysrca.lock()
|
||||
# pysrcb.lock()
|
||||
# pydst.lock()
|
||||
|
||||
blend32_core(pysrca, pysrcb, pydst, alpha)
|
||||
|
||||
# pydst.unlock()
|
||||
# pysrcb.unlock()
|
||||
# pysrca.unlock()
|
||||
|
||||
def imageblend(pysrca, pysrcb, pydst, pyimg, aoff, amap):
|
||||
check(pysrca)
|
||||
check(pysrcb)
|
||||
check(pydst)
|
||||
check(pyimg)
|
||||
|
||||
# pysrca.lock()
|
||||
# pysrcb.lock()
|
||||
# pydst.lock()
|
||||
# pyimg.lock()
|
||||
|
||||
imageblend32_core(pysrca, pysrcb, pydst, pyimg, aoff, amap)
|
||||
|
||||
# pyimg.unlock()
|
||||
# pydst.unlock()
|
||||
# pysrcb.unlock()
|
||||
# pysrca.unlock()
|
||||
|
||||
def colormatrix(pysrc, pydst,
|
||||
c00, c01, c02, c03, c04,
|
||||
c10, c11, c12, c13, c14,
|
||||
c20, c21, c22, c23, c24,
|
||||
c30, c31, c32, c33, c34):
|
||||
|
||||
check(pysrc)
|
||||
check(pydst)
|
||||
|
||||
# pysrc.lock()
|
||||
# pydst.lock()
|
||||
|
||||
colormatrix32_core(pysrc, pydst,
|
||||
c00, c01, c02, c03, c04,
|
||||
c10, c11, c12, c13, c14,
|
||||
c20, c21, c22, c23, c24,
|
||||
c30, c31, c32, c33, c34)
|
||||
|
||||
# pydst.unlock()
|
||||
# pysrc.unlock()
|
||||
|
||||
|
||||
def staticgray(pysrc, pydst, rmul, gmul, bmul, amul, shift, vmap):
|
||||
PyErr_Clear()
|
||||
staticgray_core(pysrc, pydst, rmul, gmul, bmul, amul, shift, vmap)
|
||||
|
||||
|
||||
def subpixel(pysrc, pydst, xoffset, yoffset, shift):
|
||||
|
||||
if subpixel32(pysrc, pydst, xoffset, yoffset, shift):
|
||||
return
|
||||
|
||||
pydst.blit(pysrc, (int(xoffset), int(yoffset)))
|
||||
|
||||
|
||||
# Be sure to update scale.py when adding something new here!
|
||||
|
||||
import_pygame_rwobject()
|
||||
core_init()
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
|
||||
cdef extern from "fribidi/fribidi.h":
|
||||
int FRIBIDI_TYPE_LTR
|
||||
int FRIBIDI_TYPE_ON
|
||||
int FRIBIDI_TYPE_RTL
|
||||
int FRIBIDI_TYPE_WR
|
||||
int FRIBIDI_TYPE_WL
|
||||
|
||||
cdef extern from "renpybidicore.h":
|
||||
object renpybidi_log2vis(object, int *)
|
||||
|
||||
WLTR = FRIBIDI_TYPE_WL
|
||||
LTR = FRIBIDI_TYPE_LTR
|
||||
ON = FRIBIDI_TYPE_ON
|
||||
RTL = FRIBIDI_TYPE_RTL
|
||||
WRTL = FRIBIDI_TYPE_WR
|
||||
|
||||
def log2vis(s, int direction=FRIBIDI_TYPE_ON):
|
||||
|
||||
s = s.encode("utf8")
|
||||
s = renpybidi_log2vis(s, &direction)
|
||||
return s.decode("utf8"), direction
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <SDL/SDL.h>
|
||||
#include <SDL/SDL_syswm.h>
|
||||
#include "EGL/egl.h"
|
||||
#include "GLES2/gl2.h"
|
||||
|
||||
HWND window;
|
||||
|
||||
EGLDisplay display;
|
||||
EGLSurface surface;
|
||||
EGLConfig config;
|
||||
EGLContext context;
|
||||
|
||||
int initialized = 0;
|
||||
|
||||
char error_message[100];
|
||||
|
||||
// Checks for an EGL error. Returns an error string if there is one,
|
||||
// or NULL otherwise.
|
||||
char *egl_error(char *where) {
|
||||
EGLint error;
|
||||
|
||||
error = eglGetError();
|
||||
|
||||
if (error == EGL_SUCCESS) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
snprintf(error_message, 100, "Error %s (egl error 0x%x)", where, error);
|
||||
return error_message;
|
||||
}
|
||||
|
||||
#define egl_check(where) { char *rv = egl_error(where); if (rv) return rv; }
|
||||
|
||||
/* Sets up an OpenGL ES 2 context. Returnes NULL if it succeeds, or
|
||||
* an error message on failure.
|
||||
*/
|
||||
char *egl_init(int interval) {
|
||||
SDL_SysWMinfo wminfo;
|
||||
EGLint major, minor;
|
||||
EGLint num_config;
|
||||
|
||||
const EGLint attrs[] = {
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||
EGL_ALPHA_SIZE, 8,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
const EGLint context_attrs[] = {
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
SDL_VERSION(&wminfo.version);
|
||||
SDL_GetWMInfo(&wminfo);
|
||||
|
||||
if (! initialized) {
|
||||
|
||||
display = eglGetDisplay(GetDC(wminfo.window));
|
||||
egl_check("getting display");
|
||||
|
||||
eglInitialize(display, &major, &minor);
|
||||
egl_check("initializing EGL");
|
||||
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
egl_check("binding OpenGL ES");
|
||||
|
||||
eglChooseConfig(display, attrs, &config, 1, &num_config);
|
||||
egl_check("choosing EGL config");
|
||||
|
||||
context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_attrs);
|
||||
egl_check("creating EGL context");
|
||||
|
||||
surface = eglCreateWindowSurface(display, config, wminfo.window, NULL);
|
||||
egl_check("creating EGL surface");
|
||||
|
||||
|
||||
} else if (window != wminfo.window) {
|
||||
|
||||
eglDestroySurface(display, surface);
|
||||
egl_check("destroying existing EGL surface")
|
||||
|
||||
surface = eglCreateWindowSurface(display, config, wminfo.window, NULL);
|
||||
egl_check("creating EGL surface");
|
||||
|
||||
}
|
||||
|
||||
eglMakeCurrent(display, surface, surface, context);
|
||||
egl_check("making EGL context current");
|
||||
|
||||
eglSwapInterval(display, interval);
|
||||
egl_check("setting swap interval")
|
||||
|
||||
initialized = 1;
|
||||
window = wminfo.window;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void egl_swap() {
|
||||
eglSwapBuffers(display, surface);
|
||||
}
|
||||
|
||||
void egl_quit() {
|
||||
// Does nothing at the moment.
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
#ifndef ANGLESUPPORT_H
|
||||
#define ANGLESUPPORT_H
|
||||
|
||||
char *egl_error(char *where);
|
||||
char *egl_init(int interval);
|
||||
void egl_swap();
|
||||
void egl_quit();
|
||||
|
||||
#endif
|
||||
@@ -1,4 +0,0 @@
|
||||
try () { "$@" || exit 1; }
|
||||
|
||||
try python setup.py clean --all
|
||||
try python setup.py install_lib -d $PYTHONPATH
|
||||
@@ -1,15 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
A="$RENPY_ANDROID"
|
||||
|
||||
CFLAGS="$CFLAGS -DANDROID"
|
||||
CFLAGS="$CFLAGS -I$A/sdl/sdl-1.2/include"
|
||||
CFLAGS="$CFLAGS -I$A/jni/png"
|
||||
CFLAGS="$CFLAGS -I$A/jni/freetype/include"
|
||||
|
||||
LDFLAGS="$LDFLAGS -L$A/libs/armeabi -L$A/obj/local/armeabi"
|
||||
|
||||
export CFLAGS
|
||||
export LDFLAGS
|
||||
|
||||
$A/python-install/bin/python.host setup.py build_ext -b build/lib.android -t build/tmp.android build_ext
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/bin/sh
|
||||
python setup.py clean
|
||||
python setup.py build --compiler=mingw32 install_lib -d $PYTHONPATH
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
#include "pyfreetype.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#undef __FTERRORS_H__
|
||||
#define FT_ERRORDEF( e, v, s ) { e, s },
|
||||
#define FT_ERROR_START_LIST
|
||||
#define FT_ERROR_END_LIST { 0, 0 }
|
||||
const struct {
|
||||
int err_code;
|
||||
char* err_msg;
|
||||
} ft_errors[] = {
|
||||
#include FT_ERRORS_H
|
||||
};
|
||||
|
||||
|
||||
char *freetype_error_to_string(int code) {
|
||||
|
||||
int i = 0;
|
||||
|
||||
while (1) {
|
||||
|
||||
if (ft_errors[i].err_code == code) {
|
||||
return ft_errors[i].err_msg;
|
||||
}
|
||||
|
||||
if (ft_errors[i].err_msg == NULL) {
|
||||
return "unknown error";
|
||||
}
|
||||
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
#ifndef FTSUPPORT_H
|
||||
#define FTSUPPORT_H
|
||||
char *freetype_error_to_string(int error);
|
||||
#endif
|
||||
@@ -1,176 +0,0 @@
|
||||
# encoding: utf-8
|
||||
|
||||
# Based on: http://www.unicode.org/Public/UNIDATA/LineBreak.txt
|
||||
# Based on: http://unicode.org/reports/tr14/#PairBasedImplementation
|
||||
|
||||
import re
|
||||
|
||||
breaking = """OP CL CP QU GL NS EX SY IS PR PO NU AL HL ID IN HY BA BB B2 ZW CM WJ H2 H3 JL JV JT RI
|
||||
OP ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ @ ^ ^ ^ ^ ^ ^ ^
|
||||
CL _ ^ ^ % % ^ ^ ^ ^ % % _ _ _ _ _ % % _ _ ^ # ^ _ _ _ _ _ _
|
||||
CP _ ^ ^ % % ^ ^ ^ ^ % % % % % _ _ % % _ _ ^ # ^ _ _ _ _ _ _
|
||||
QU ^ ^ ^ % % % ^ ^ ^ % % % % % % % % % % % ^ # ^ % % % % % %
|
||||
GL % ^ ^ % % % ^ ^ ^ % % % % % % % % % % % ^ # ^ % % % % % %
|
||||
NS _ ^ ^ % % % ^ ^ ^ _ _ _ _ _ _ _ % % _ _ ^ # ^ _ _ _ _ _ _
|
||||
EX _ ^ ^ % % % ^ ^ ^ _ _ _ _ _ _ _ % % _ _ ^ # ^ _ _ _ _ _ _
|
||||
SY _ ^ ^ % % % ^ ^ ^ _ _ % _ _ _ _ % % _ _ ^ # ^ _ _ _ _ _ _
|
||||
IS _ ^ ^ % % % ^ ^ ^ _ _ % % % _ _ % % _ _ ^ # ^ _ _ _ _ _ _
|
||||
PR % ^ ^ % % % ^ ^ ^ _ _ % % % % _ % % _ _ ^ # ^ % % % % % _
|
||||
PO % ^ ^ % % % ^ ^ ^ _ _ % % % _ _ % % _ _ ^ # ^ _ _ _ _ _ _
|
||||
NU % ^ ^ % % % ^ ^ ^ % % % % % _ % % % _ _ ^ # ^ _ _ _ _ _ _
|
||||
AL % ^ ^ % % % ^ ^ ^ _ _ % % % _ % % % _ _ ^ # ^ _ _ _ _ _ _
|
||||
HL % ^ ^ % % % ^ ^ ^ _ _ % % % _ % % % _ _ ^ # ^ _ _ _ _ _ _
|
||||
ID _ ^ ^ % % % ^ ^ ^ _ % _ _ _ _ % % % _ _ ^ # ^ _ _ _ _ _ _
|
||||
IN _ ^ ^ % % % ^ ^ ^ _ _ _ _ _ _ % % % _ _ ^ # ^ _ _ _ _ _ _
|
||||
HY _ ^ ^ % _ % ^ ^ ^ _ _ % _ _ _ _ % % _ _ ^ # ^ _ _ _ _ _ _
|
||||
BA _ ^ ^ % _ % ^ ^ ^ _ _ _ _ _ _ _ % % _ _ ^ # ^ _ _ _ _ _ _
|
||||
BB % ^ ^ % % % ^ ^ ^ % % % % % % % % % % % ^ # ^ % % % % % %
|
||||
B2 _ ^ ^ % % % ^ ^ ^ _ _ _ _ _ _ _ % % _ ^ ^ # ^ _ _ _ _ _ _
|
||||
ZW _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ^ _ _ _ _ _ _ _ _
|
||||
CM % ^ ^ % % % ^ ^ ^ _ _ % % % _ % % % _ _ ^ # ^ _ _ _ _ _ _
|
||||
WJ % ^ ^ % % % ^ ^ ^ % % % % % % % % % % % ^ # ^ % % % % % %
|
||||
H2 _ ^ ^ % % % ^ ^ ^ _ % _ _ _ _ % % % _ _ ^ # ^ _ _ _ % % _
|
||||
H3 _ ^ ^ % % % ^ ^ ^ _ % _ _ _ _ % % % _ _ ^ # ^ _ _ _ _ % _
|
||||
JL _ ^ ^ % % % ^ ^ ^ _ % _ _ _ _ % % % _ _ ^ # ^ % % % % _ _
|
||||
JV _ ^ ^ % % % ^ ^ ^ _ % _ _ _ _ % % % _ _ ^ # ^ _ _ _ % % _
|
||||
JT _ ^ ^ % % % ^ ^ ^ _ % _ _ _ _ % % % _ _ ^ # ^ _ _ _ _ % _
|
||||
RI _ ^ ^ % % % ^ ^ ^ _ _ _ _ _ _ _ % % _ _ ^ # ^ _ _ _ _ _ %
|
||||
"""
|
||||
|
||||
other_classes = " PITCH AI BK CB CJ CR LF NL SA SG SP XX"
|
||||
|
||||
lines = breaking.split("\n")
|
||||
|
||||
print "# This is generated code. Do not edit."
|
||||
print
|
||||
|
||||
# A map from character class to the number that represents it.
|
||||
cl = { }
|
||||
|
||||
|
||||
for i, j in enumerate((lines[0] + other_classes).split()):
|
||||
print "cdef char BC_{} = {}".format(j, i)
|
||||
cl[j] = i
|
||||
|
||||
print "CLASSES = {"
|
||||
|
||||
for i, j in enumerate((lines[0] + other_classes).split()):
|
||||
print " \"{}\" : {},".format(j, i)
|
||||
cl[j] = i
|
||||
|
||||
print "}"
|
||||
|
||||
rules = [ ]
|
||||
|
||||
for l in lines[1:]:
|
||||
for c in l.split()[1:]:
|
||||
rules.append(c)
|
||||
|
||||
print
|
||||
print "cdef char *break_rules = \"" + "".join(rules) + "\""
|
||||
|
||||
cc = [ 'XX' ] * 65536
|
||||
|
||||
for l in file("LineBreak.txt"):
|
||||
m = re.match("(\w+)\.\.(\w+);(\w\w)", l)
|
||||
if m:
|
||||
start = int(m.group(1), 16)
|
||||
end = int(m.group(2), 16)
|
||||
|
||||
if start > 65535:
|
||||
continue
|
||||
|
||||
if end > 65535:
|
||||
end = 65535
|
||||
|
||||
for i in range(start, end + 1):
|
||||
cc[i] = m.group(3)
|
||||
|
||||
continue
|
||||
|
||||
m = re.match("(\w+);(\w\w)", l)
|
||||
if m:
|
||||
start = int(m.group(1), 16)
|
||||
|
||||
if start > 65535:
|
||||
continue
|
||||
|
||||
cc[start] = m.group(2)
|
||||
continue
|
||||
|
||||
def generate(name, func):
|
||||
|
||||
ncc = [ ]
|
||||
|
||||
for i, ccl in enumerate(cc):
|
||||
ncc.append(func(i, ccl))
|
||||
|
||||
assert "CJ" not in ncc
|
||||
assert "AI" not in ncc
|
||||
|
||||
print "cdef char *break_" + name + " = \"" + "".join("\\x%02x" % cl[i] for i in ncc) + "\""
|
||||
|
||||
def western(i, cl):
|
||||
if cl == "CJ":
|
||||
return "ID"
|
||||
elif cl == "AI":
|
||||
return "AL"
|
||||
|
||||
return cl
|
||||
|
||||
hyphens = [ 0x2010, 0x2013, 0x301c, 0x30a0 ]
|
||||
|
||||
iteration = [ 0x3005, 0x303B, 0x309D, 0x309E, 0x30FD, 0x30FE ]
|
||||
inseperable = [ 0x2025, 0x2026 ]
|
||||
|
||||
centered = [ 0x003A, 0x003B, 0x30FB, 0xff1a, 0xff1b, 0xff65, 0x0021, 0x003f, 0x203c, 0x2047, 0x2048, 0x2049, 0xff01, 0xff1f ]
|
||||
postfixes = [ 0x0025, 0x00A2, 0x00B0, 0x2030, 0x2032, 0x2033, 0x2103, 0xff05, 0xffe0 ]
|
||||
prefixes = [ 0x0024, 0x00a3, 0x00a5, 0x20ac, 0x2116, 0xff04, 0xffe1, 0xffe5 ]
|
||||
|
||||
def cjk_strict(i, cl):
|
||||
|
||||
if cl == "CJ":
|
||||
return "NS"
|
||||
if cl == "AI":
|
||||
return "ID"
|
||||
|
||||
return cl
|
||||
|
||||
def cjk_normal(i, cl):
|
||||
|
||||
if i in hyphens:
|
||||
return "ID"
|
||||
|
||||
if cl == "CJ":
|
||||
return "ID"
|
||||
if cl == "AI":
|
||||
return "ID"
|
||||
|
||||
return cl
|
||||
|
||||
def cjk_loose(i, cl):
|
||||
|
||||
if i in hyphens:
|
||||
return "ID"
|
||||
if i in iteration:
|
||||
return "ID"
|
||||
if i in inseperable:
|
||||
return "ID"
|
||||
if i in centered:
|
||||
return "ID"
|
||||
if i in postfixes:
|
||||
return "ID"
|
||||
if i in prefixes:
|
||||
return "ID"
|
||||
|
||||
if cl == "CJ":
|
||||
return "ID"
|
||||
if cl == "AI":
|
||||
return "ID"
|
||||
|
||||
return cl
|
||||
|
||||
generate("western", western)
|
||||
generate("cjk_strict", cjk_strict)
|
||||
generate("cjk_normal", cjk_normal)
|
||||
generate("cjk_loose", cjk_loose)
|
||||
@@ -1,153 +0,0 @@
|
||||
/**
|
||||
* This takes care of abstracting between OpenGL and OpenGL ES, by
|
||||
* choosing the appropriate header file, and renaming various names
|
||||
* in the ES case.
|
||||
*/
|
||||
#ifndef GL_COMPAT_H
|
||||
#define GL_COMPAT_H
|
||||
|
||||
// Environ is defined on windows, but our GL code uses it as an
|
||||
// identifier. So get rid of it here.
|
||||
#undef environ
|
||||
|
||||
#if defined ANDROID
|
||||
|
||||
#define RENPY_GLES_2
|
||||
|
||||
#elif defined ANGLE
|
||||
|
||||
#define RENPY_GLES_2
|
||||
|
||||
#else
|
||||
|
||||
#define RENPY_OPENGL
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if defined RENPY_GLES_1
|
||||
|
||||
#include <GLES/gl.h>
|
||||
#include <GLES/glext.h>
|
||||
|
||||
#define glOrtho glOrthof
|
||||
|
||||
#define GL_SOURCE0_ALPHA GL_SRC0_ALPHA
|
||||
#define GL_SOURCE1_ALPHA GL_SRC1_ALPHA
|
||||
#define GL_SOURCE2_ALPHA GL_SRC2_ALPHA
|
||||
#define GL_SOURCE0_RGB GL_SRC0_RGB
|
||||
#define GL_SOURCE1_RGB GL_SRC1_RGB
|
||||
#define GL_SOURCE2_RGB GL_SRC2_RGB
|
||||
|
||||
#define GL_FRAMEBUFFER_EXT GL_FRAMEBUFFER_OES
|
||||
#define GL_COLOR_ATTACHMENT0_EXT GL_COLOR_ATTACHMENT0_OES
|
||||
#define glBindFramebufferEXT glBindFramebufferOES
|
||||
#define glFramebufferTexture2DEXT glFramebufferTexture2DOES
|
||||
#define glGenFramebuffersEXT glGenFramebuffersOES
|
||||
#define glDeleteFramebuffersEXT glDeleteFramebuffersOES
|
||||
#define glCheckFramebufferStatusEXT glCheckFramebufferStatusOES
|
||||
|
||||
#define RENPY_THIRD_TEXTURE 0
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if defined RENPY_GLES_2
|
||||
|
||||
#ifndef ANDROID
|
||||
#include <EGL/egl.h>
|
||||
#endif
|
||||
|
||||
#include <GLES2/gl2.h>
|
||||
|
||||
typedef GLuint GLhandleARB;
|
||||
typedef GLchar GLcharARB;
|
||||
|
||||
#define GL_MAX_TEXTURE_UNITS GL_MAX_TEXTURE_IMAGE_UNITS
|
||||
|
||||
#define GL_FRAMEBUFFER_EXT GL_FRAMEBUFFER
|
||||
#define GL_COLOR_ATTACHMENT0_EXT GL_COLOR_ATTACHMENT0
|
||||
#define glBindFramebufferEXT glBindFramebuffer
|
||||
#define glFramebufferTexture2DEXT glFramebufferTexture2D
|
||||
#define glGenFramebuffersEXT glGenFramebuffers
|
||||
#define glDeleteFramebuffersEXT glDeleteFramebuffers
|
||||
#define glCheckFramebufferStatusEXT glCheckFramebufferStatus
|
||||
|
||||
#define GL_OBJECT_INFO_LOG_LENGTH_ARB GL_INFO_LOG_LENGTH
|
||||
#define GL_OBJECT_COMPILE_STATUS_ARB GL_COMPILE_STATUS
|
||||
#define GL_VERTEX_SHADER_ARB GL_VERTEX_SHADER
|
||||
#define GL_FRAGMENT_SHADER_ARB GL_FRAGMENT_SHADER
|
||||
#define GL_OBJECT_LINK_STATUS_ARB GL_LINK_STATUS
|
||||
|
||||
#define glCreateShaderObjectARB glCreateShader
|
||||
#define glShaderSourceARB glShaderSource
|
||||
#define glCompileShaderARB glCompileShader
|
||||
#define glCreateProgramObjectARB glCreateProgram
|
||||
#define glAttachObjectARB glAttachShader
|
||||
#define glLinkProgramARB glLinkProgram
|
||||
#define glUseProgramObjectARB glUseProgram
|
||||
#define glGetAttribLocationARB glGetAttribLocation
|
||||
#define glGetUniformLocationARB glGetUniformLocation
|
||||
#define glUniformMatrix4fvARB glUniformMatrix4fv
|
||||
#define glUniform1iARB glUniform1i
|
||||
#define glUniform1fARB glUniform1f
|
||||
#define glUniform2fARB glUniform2f
|
||||
#define glUniform4fARB glUniform4f
|
||||
#define glVertexAttribPointerARB glVertexAttribPointer
|
||||
#define glEnableVertexAttribArrayARB glEnableVertexAttribArray
|
||||
#define glDisableVertexAttribArrayARB glDisableVertexAttribArray
|
||||
|
||||
#define RENPY_THIRD_TEXTURE 1
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if defined RENPY_GLES_1 || defined RENPY_GLES_2
|
||||
|
||||
typedef GLfloat GLdouble;
|
||||
|
||||
#define glewInit() (1)
|
||||
#define GLEW_OK (1)
|
||||
#define glewGetErrorString(x) ("Unknown Error")
|
||||
#define glewIsSupported(x) (1)
|
||||
#define glClipPlane glClipPlanef
|
||||
|
||||
// This isn't defined on GL ES, but that's okay, since we'll disable
|
||||
// screenshots on Android.
|
||||
#define GL_PACK_ROW_LENGTH 0
|
||||
|
||||
#define glClientActiveTextureARB glClientActiveTexture
|
||||
#define glActiveTextureARB glActiveTexture
|
||||
|
||||
#define GL_BGRA GL_RGBA
|
||||
#define GL_UNSIGNED_INT_8_8_8_8_REV GL_UNSIGNED_BYTE
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if defined RENPY_OPENGL
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#define RENPY_THIRD_TEXTURE 1
|
||||
|
||||
// These have to be written 2.0-style, since the ARB-style doesn't
|
||||
// include the object type.
|
||||
#undef GL_INFO_LOG_LENGTH
|
||||
#define GL_INFO_LOG_LENGTH GL_OBJECT_INFO_LOG_LENGTH_ARB
|
||||
#undef glDeleteShader
|
||||
#define glDeleteShader glDeleteObjectARB
|
||||
#undef glDeleteProgram
|
||||
#define glDeleteProgram glDeleteObjectARB
|
||||
#undef glGetShaderiv
|
||||
#define glGetShaderiv glGetObjectParameterivARB
|
||||
#undef glGetProgramiv
|
||||
#define glGetProgramiv glGetObjectParameterivARB
|
||||
#undef glGetShaderInfoLog
|
||||
#define glGetShaderInfoLog glGetInfoLogARB
|
||||
#undef glGetProgramInfoLog
|
||||
#define glGetProgramInfoLog glGetInfoLogARB
|
||||
|
||||
#endif
|
||||
|
||||
#endif // GL_COMPAT_H
|
||||
@@ -1,606 +0,0 @@
|
||||
# Originally taken from the pyopenvg SVN, which is available at:
|
||||
# http://code.google.com/p/pyopenvg/source/browse/trunk/
|
||||
# and is licensed under the new BSD license.
|
||||
|
||||
cdef extern from "stdlib.h":
|
||||
ctypedef long size_t
|
||||
|
||||
cdef extern from "pyfreetype.h":
|
||||
#ftconfig.h
|
||||
#Some tweaking may be needed on a platform-by-platform basis
|
||||
DEF FT_SIZEOF_INT = 4
|
||||
DEF FT_SIZEOF_LONG = 4
|
||||
|
||||
ctypedef signed short FT_Int16
|
||||
ctypedef unsigned short FT_UInt16
|
||||
IF FT_SIZEOF_INT == 4:
|
||||
ctypedef signed int FT_Int32
|
||||
ctypedef unsigned int FT_UInt32
|
||||
ELIF FT_SIZEOF_LONG == 4:
|
||||
ctypedef signed long FT_Int32
|
||||
ctypedef unsigned long FT_UInt32
|
||||
|
||||
IF FT_SIZEOF_INT >= 4:
|
||||
ctypedef int FT_Fast
|
||||
ctypedef unsigned int FT_UFast
|
||||
ELIF FT_SIZEOF_LONG >= 4:
|
||||
ctypedef long FT_Fast
|
||||
ctypedef unsigned long FT_UFast
|
||||
|
||||
|
||||
|
||||
#fttypes.h
|
||||
ctypedef unsigned char FT_Bool
|
||||
ctypedef signed short FT_FWord
|
||||
ctypedef unsigned short FT_UFWord
|
||||
ctypedef signed char FT_Char
|
||||
ctypedef unsigned char FT_Byte
|
||||
ctypedef FT_Byte* FT_Bytes
|
||||
ctypedef FT_UInt32 FT_Tag
|
||||
ctypedef char FT_String
|
||||
ctypedef signed short FT_Short
|
||||
ctypedef unsigned short FT_UShort
|
||||
ctypedef signed int FT_Int
|
||||
ctypedef unsigned int FT_UInt
|
||||
ctypedef signed long FT_Long
|
||||
ctypedef unsigned long FT_ULong
|
||||
ctypedef signed short FT_F2Dot14
|
||||
ctypedef signed long FT_F26Dot6
|
||||
ctypedef signed long FT_Fixed
|
||||
ctypedef int FT_Error
|
||||
ctypedef void* FT_Pointer
|
||||
ctypedef size_t FT_Offset
|
||||
#ctypedef ft_ptrdiff_t FT_PtrDist
|
||||
ctypedef void (*FT_Generic_Finalizer)(void* object)
|
||||
|
||||
ctypedef struct FT_UnitVector:
|
||||
FT_F2Dot14 x,y
|
||||
|
||||
ctypedef struct FT_Matrix:
|
||||
FT_Fixed xx, xy, yx, yy
|
||||
|
||||
ctypedef struct FT_Data:
|
||||
FT_Bytes pointer
|
||||
FT_Int length
|
||||
|
||||
ctypedef struct FT_Generic:
|
||||
void *data
|
||||
FT_Generic_Finalizer finalizer
|
||||
|
||||
#ftimage.h
|
||||
ctypedef signed long FT_Pos
|
||||
ctypedef struct FT_Vector:
|
||||
FT_Pos x,y
|
||||
|
||||
ctypedef struct FT_BBox:
|
||||
FT_Pos xMin, yMin, xMax, yMax
|
||||
|
||||
ctypedef enum FT_Pixel_Mode:
|
||||
FT_PIXEL_MODE_NONE = 0,
|
||||
FT_PIXEL_MODE_MONO,
|
||||
FT_PIXEL_MODE_GRAY,
|
||||
FT_PIXEL_MODE_GRAY2,
|
||||
FT_PIXEL_MODE_GRAY4,
|
||||
FT_PIXEL_MODE_LCD,
|
||||
FT_PIXEL_MODE_LCD_V,
|
||||
|
||||
FT_PIXEL_MODE_MAX
|
||||
|
||||
ctypedef struct FT_Bitmap:
|
||||
int rows, width, pitch
|
||||
unsigned char *buffer
|
||||
short num_grays
|
||||
char pixel_mode, palette_mode
|
||||
void *palette
|
||||
|
||||
ctypedef struct FT_Outline:
|
||||
short n_contours, n_points
|
||||
FT_Vector *points
|
||||
char *tags
|
||||
short *contours
|
||||
int flags
|
||||
|
||||
DEF FT_OUTLINE_NONE = 0
|
||||
DEF FT_OUTLINE_OWNER = 1 << 0
|
||||
DEF FT_OUTLINE_EVEN_ODD_FILL = 1 << 1
|
||||
DEF FT_OUTLINE_REVERSE_FILL = 1 << 2
|
||||
DEF FT_OUTLINE_IGNORE_DROPOUTS = 1 << 3
|
||||
DEF FT_OUTLINE_HIGH_PRECISION = 1 << 8
|
||||
DEF FT_OUTLINE_SINGLE_PASS = 1 << 9
|
||||
|
||||
ctypedef int (*FT_Outline_MoveToFunc)(FT_Vector *to, void *user)
|
||||
ctypedef int (*FT_Outline_LineToFunc)(FT_Vector *to, void *user)
|
||||
ctypedef int (*FT_Outline_ConicToFunc)(FT_Vector *control, FT_Vector *to, void *user)
|
||||
ctypedef int (*FT_Outline_CubicToFunc)(FT_Vector *control1, FT_Vector *control2, FT_Vector *to, void *user)
|
||||
|
||||
ctypedef struct FT_Outline_Funcs:
|
||||
FT_Outline_MoveToFunc move_to
|
||||
FT_Outline_LineToFunc line_to
|
||||
FT_Outline_ConicToFunc conic_to
|
||||
FT_Outline_CubicToFunc cubic_to
|
||||
|
||||
int shift
|
||||
FT_Pos delta
|
||||
|
||||
ctypedef enum FT_Glyph_Format:
|
||||
FT_GLYPH_FORMAT_NONE = 0
|
||||
FT_GLYPH_FORMAT_COMPOSITE = ((<unsigned long>c'c' << 24) |
|
||||
(<unsigned long>c'o' << 16) |
|
||||
(<unsigned long>c'm' << 8) |
|
||||
(<unsigned long>c'p')),
|
||||
FT_GLYPH_FORMAT_BITMAP = ((<unsigned long>c'b' << 24) |
|
||||
(<unsigned long>c'i' << 16) |
|
||||
(<unsigned long>c't' << 8) |
|
||||
(<unsigned long>c's')),
|
||||
FT_GLYPH_FORMAT_OUTLINE = ((<unsigned long>c'o' << 24) |
|
||||
(<unsigned long>c'u' << 16) |
|
||||
(<unsigned long>c't' << 8) |
|
||||
(<unsigned long>c'l')),
|
||||
FT_GLYPH_FORMAT_PLOTTER = ((<unsigned long>c'p' << 24) |
|
||||
(<unsigned long>c'l' << 16) |
|
||||
(<unsigned long>c'o' << 8) |
|
||||
(<unsigned long>c't'))
|
||||
|
||||
|
||||
|
||||
#freetype.h
|
||||
ctypedef struct FT_Glyph_Metrics:
|
||||
FT_Pos width, height
|
||||
FT_Pos horiBearingX, horiBearingY, horiAdvance
|
||||
FT_Pos vertBearingX, vertBearingY, vertAdvance
|
||||
|
||||
ctypedef struct FT_Bitmap_Size:
|
||||
FT_Short height, width
|
||||
FT_Pos size
|
||||
FT_Pos x_ppem, y_ppem
|
||||
|
||||
## cdef struct FT_LibraryRec_:
|
||||
## pass
|
||||
## cdef struct FT_ModuleRec_:
|
||||
## pass
|
||||
## cdef struct FT_DriverRec_:
|
||||
## pass
|
||||
## cdef struct FT_RendererRec_:
|
||||
## pass
|
||||
|
||||
cdef struct FT_FaceRec_
|
||||
cdef struct FT_SizeRec_
|
||||
cdef struct FT_GlyphSlotRec_
|
||||
cdef struct FT_CharMapRec_
|
||||
|
||||
## ctypedef FT_LibraryRec_* FT_Library
|
||||
## ctypedef FT_ModuleRec_* FT_Module
|
||||
## ctypedef FT_DriverRec_* FT_Driver
|
||||
## ctypedef FT_RendererRec_* FT_Renderer
|
||||
ctypedef void* FT_Library
|
||||
ctypedef void* FT_Module
|
||||
ctypedef void* FT_Driver
|
||||
ctypedef void* FT_Renderer
|
||||
ctypedef FT_FaceRec_* FT_Face
|
||||
ctypedef FT_SizeRec_* FT_Size
|
||||
ctypedef FT_GlyphSlotRec_* FT_GlyphSlot
|
||||
ctypedef FT_CharMapRec_* FT_CharMap
|
||||
|
||||
ctypedef enum FT_Encoding:
|
||||
FT_ENCODING_NONE = 0
|
||||
FT_ENCODING_MS_SYMBOL = ((<FT_UInt32>c's' << 24) |
|
||||
(<FT_UInt32>c'y' << 16) |
|
||||
(<FT_UInt32>c'm' << 8) |
|
||||
(<FT_UInt32>c'b')),
|
||||
FT_ENCODING_UNICODE = ((<FT_UInt32>c'u' << 24) |
|
||||
(<FT_UInt32>c'n' << 16) |
|
||||
(<FT_UInt32>c'i' << 8) |
|
||||
(<FT_UInt32>c'c')),
|
||||
|
||||
FT_ENCODING_SJIS = ((<FT_UInt32>c's' << 24) |
|
||||
(<FT_UInt32>c'j' << 16) |
|
||||
(<FT_UInt32>c'i' << 8) |
|
||||
(<FT_UInt32>c's')),
|
||||
FT_ENCODING_GB2312 = ((<FT_UInt32>c'g' << 24) |
|
||||
(<FT_UInt32>c'b' << 16) |
|
||||
(<FT_UInt32>c' ' << 8) |
|
||||
(<FT_UInt32>c' ')),
|
||||
FT_ENCODING_BIG5 = ((<FT_UInt32>c'b' << 24) |
|
||||
(<FT_UInt32>c'i' << 16) |
|
||||
(<FT_UInt32>c'g' << 8) |
|
||||
(<FT_UInt32>c'5')),
|
||||
FT_ENCODING_WANSUNG = ((<FT_UInt32>c'w' << 24) |
|
||||
(<FT_UInt32>c'a' << 16) |
|
||||
(<FT_UInt32>c'n' << 8) |
|
||||
(<FT_UInt32>c's')),
|
||||
FT_ENCODING_JOHAB = ((<FT_UInt32>c'j' << 24) |
|
||||
(<FT_UInt32>c'o' << 16) |
|
||||
(<FT_UInt32>c'h' << 8) |
|
||||
(<FT_UInt32>c'a')),
|
||||
|
||||
FT_ENCODING_ADOBE_STANDARD = ((<FT_UInt32>c'A' << 24) |
|
||||
(<FT_UInt32>c'D' << 16) |
|
||||
(<FT_UInt32>c'O' << 8) |
|
||||
(<FT_UInt32>c'B')),
|
||||
FT_ENCODING_ADOBE_EXPERT = ((<FT_UInt32>c'A' << 24) |
|
||||
(<FT_UInt32>c'D' << 16) |
|
||||
(<FT_UInt32>c'B' << 8) |
|
||||
(<FT_UInt32>c'E')),
|
||||
FT_ENCODING_ADOBE_CUSTOM = ((<FT_UInt32>c'A' << 24) |
|
||||
(<FT_UInt32>c'D' << 16) |
|
||||
(<FT_UInt32>c'B' << 8) |
|
||||
(<FT_UInt32>c'C')),
|
||||
FT_ENCODING_ADOBE_LATIN_1 = ((<FT_UInt32>c'l' << 24) |
|
||||
(<FT_UInt32>c'a' << 16) |
|
||||
(<FT_UInt32>c't' << 8) |
|
||||
(<FT_UInt32>c'1')),
|
||||
|
||||
FT_ENCODING_OLD_LATIN_2 = ((<FT_UInt32>c'l' << 24) |
|
||||
(<FT_UInt32>c'a' << 16) |
|
||||
(<FT_UInt32>c't' << 8) |
|
||||
(<FT_UInt32>c'2')),
|
||||
|
||||
FT_ENCODING_APPLE_ROMAN = ((<FT_UInt32>c'a' << 24) |
|
||||
(<FT_UInt32>c'r' << 16) |
|
||||
(<FT_UInt32>c'm' << 8) |
|
||||
(<FT_UInt32>c'n'))
|
||||
|
||||
cdef struct FT_CharMapRec_:
|
||||
FT_Face face
|
||||
FT_Encoding encoding
|
||||
FT_UShort platform_id
|
||||
FT_UShort encoding_id
|
||||
ctypedef FT_CharMapRec_ FT_CharMapRec
|
||||
|
||||
cdef struct FT_FaceRec_:
|
||||
FT_Long num_faces
|
||||
FT_Long face_index
|
||||
|
||||
FT_Long face_flags
|
||||
FT_Long style_flags
|
||||
|
||||
FT_Long num_glyphs
|
||||
|
||||
FT_String* family_name
|
||||
FT_String* style_name
|
||||
|
||||
FT_Int num_fixed_sizes
|
||||
FT_Bitmap_Size* available_sizes
|
||||
|
||||
FT_Int num_charmaps
|
||||
FT_CharMap* charmaps
|
||||
|
||||
FT_Generic generic
|
||||
|
||||
FT_BBox bbox
|
||||
|
||||
FT_UShort units_per_EM
|
||||
FT_Short ascender
|
||||
FT_Short descender
|
||||
FT_Short height
|
||||
|
||||
FT_Short max_advance_width
|
||||
FT_Short max_advance_height
|
||||
|
||||
FT_Short underline_position
|
||||
FT_Short underline_thickness
|
||||
|
||||
FT_GlyphSlot glyph
|
||||
FT_Size size
|
||||
FT_CharMap charmap
|
||||
ctypedef FT_FaceRec_ FT_FaceRec
|
||||
|
||||
DEF FT_FACE_FLAG_SCALABLE = 1L << 0
|
||||
DEF FT_FACE_FLAG_FIXED_SIZES = 1L << 1
|
||||
DEF FT_FACE_FLAG_FIXED_WIDTH = 1L << 2
|
||||
DEF FT_FACE_FLAG_SFNT = 1L << 3
|
||||
DEF FT_FACE_FLAG_HORIZONTAL = 1L << 4
|
||||
DEF FT_FACE_FLAG_VERTICAL = 1L << 5
|
||||
DEF FT_FACE_FLAG_KERNING = 1L << 6
|
||||
DEF FT_FACE_FLAG_FAST_GLYPHS = 1L << 7
|
||||
DEF FT_FACE_FLAG_MULTIPLE_MASTERS = 1L << 8
|
||||
DEF FT_FACE_FLAG_GLYPH_NAMES = 1L << 9
|
||||
DEF FT_FACE_FLAG_EXTERNAL_STREAM = 1L << 10
|
||||
DEF FT_FACE_FLAG_HINTER = 1L << 11
|
||||
|
||||
DEF FT_STYLE_FLAG_ITALIC = 1 << 0
|
||||
DEF FT_STYLE_FLAG_BOLD = 1 << 1
|
||||
|
||||
ctypedef struct FT_Size_Metrics:
|
||||
FT_UShort x_ppem, y_ppem
|
||||
FT_Fixed x_scale, y_scale
|
||||
FT_Pos ascender, descender
|
||||
FT_Pos height
|
||||
FT_Pos max_advance
|
||||
|
||||
cdef struct FT_SizeRec_:
|
||||
FT_Face face
|
||||
FT_Generic generic
|
||||
FT_Size_Metrics metrics
|
||||
ctypedef FT_SizeRec_ FT_SizeRec
|
||||
|
||||
cdef struct FT_SubGlyphRec_:
|
||||
pass
|
||||
ctypedef FT_SubGlyphRec_* FT_SubGlyph
|
||||
|
||||
cdef struct FT_GlyphSlotRec_:
|
||||
FT_Library library
|
||||
FT_Face face
|
||||
FT_GlyphSlot next
|
||||
FT_UInt reserved
|
||||
FT_Generic generic
|
||||
|
||||
FT_Glyph_Metrics metrics
|
||||
FT_Fixed linearHoriAdvance, linearVertAdvance
|
||||
FT_Vector advance
|
||||
|
||||
FT_Glyph_Format format
|
||||
|
||||
FT_Bitmap bitmap
|
||||
FT_Int bitmap_left, bitmap_top
|
||||
|
||||
FT_Outline outline
|
||||
|
||||
FT_UInt num_subglyphs
|
||||
FT_SubGlyph subglyphs
|
||||
|
||||
void* control_data
|
||||
long control_len
|
||||
|
||||
FT_Pos lsb_delta, rsb_delta
|
||||
|
||||
ctypedef FT_GlyphSlotRec_ FT_GlyphSlotRec
|
||||
|
||||
FT_Error FT_Init_FreeType(FT_Library *lib)
|
||||
FT_Error FT_Done_FreeType(FT_Library lib)
|
||||
|
||||
FT_Error FT_New_Face(FT_Library lib, char *path, FT_Long face_index, FT_Face *face)
|
||||
FT_Error FT_Attach_File(FT_Face face, char *path)
|
||||
FT_Error FT_Done_Face(FT_Face face)
|
||||
|
||||
ctypedef enum FT_Size_Request_Type:
|
||||
FT_SIZE_REQUEST_TYPE_NOMINAL,
|
||||
FT_SIZE_REQUEST_TYPE_REAL_DIM,
|
||||
FT_SIZE_REQUEST_TYPE_BBOX,
|
||||
FT_SIZE_REQUEST_TYPE_CELL,
|
||||
FT_SIZE_REQUEST_TYPE_SCALES,
|
||||
|
||||
FT_SIZE_REQUEST_TYPE_MAX
|
||||
|
||||
ctypedef struct FT_Size_RequestRec:
|
||||
FT_Size_Request_Type type
|
||||
FT_Long width, height
|
||||
FT_UInt horiResolution, vertResolution
|
||||
ctypedef FT_Size_RequestRec* FT_Size_Request
|
||||
|
||||
FT_Error FT_Select_Size(FT_Face face, FT_Int strike_index)
|
||||
FT_Error FT_Request_Size(FT_Face face, FT_Size_Request req)
|
||||
FT_Error FT_Set_Char_Size(FT_Face, FT_F26Dot6 char_width, FT_F26Dot6 char_height, FT_UInt hres, FT_UInt vres)
|
||||
FT_Error FT_Set_Pixel_Sizes(FT_Face face, FT_UInt pixel_width, FT_UInt pixel_height)
|
||||
|
||||
ctypedef enum FT_Load_Flags:
|
||||
FT_LOAD_DEFAULT
|
||||
FT_LOAD_NO_SCALE
|
||||
FT_LOAD_NO_HINTING
|
||||
FT_LOAD_RENDER
|
||||
FT_LOAD_NO_BITMAP
|
||||
FT_LOAD_VERTICAL_LAYOUT
|
||||
FT_LOAD_FORCE_AUTOHINT
|
||||
FT_LOAD_CROP_BITMAP
|
||||
FT_LOAD_PEDANTIC
|
||||
FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH
|
||||
FT_LOAD_NO_RECURSE
|
||||
FT_LOAD_IGNORE_TRANSFORM
|
||||
FT_LOAD_MONOCHROME
|
||||
FT_LOAD_LINEAR_DESIGN
|
||||
FT_LOAD_SBITS_ONLY
|
||||
FT_LOAD_NO_AUTOHINT
|
||||
|
||||
FT_Error FT_Load_Glyph(FT_Face face, FT_UInt glyph_index, FT_Int32 flags)
|
||||
FT_Error FT_Load_Char(FT_Face face, FT_ULong char_code, FT_Int32 flags)
|
||||
|
||||
|
||||
|
||||
void FT_Set_Transform(FT_Face face, FT_Matrix *matrix, FT_Vector *delta)
|
||||
|
||||
ctypedef enum FT_Render_Mode:
|
||||
FT_RENDER_MODE_NORMAL = 0,
|
||||
FT_RENDER_MODE_LIGHT,
|
||||
FT_RENDER_MODE_MONO,
|
||||
FT_RENDER_MODE_LCD,
|
||||
FT_RENDER_MODE_LCD_V,
|
||||
|
||||
FT_RENDER_MODE_MAX
|
||||
|
||||
FT_Error FT_Render_Glyph(FT_GlyphSlot slot, FT_Render_Mode mode)
|
||||
|
||||
ctypedef enum FT_Kerning_Mode:
|
||||
FT_KERNING_DEFAULT = 0
|
||||
FT_KERNING_UNFITTED,
|
||||
FT_KERNING_UNSCALED
|
||||
|
||||
FT_Error FT_Get_Kerning(FT_Face face, FT_UInt left_glyph, FT_UInt right_glyph, FT_UInt mode, FT_Vector *kerning)
|
||||
FT_Error FT_Get_Track_Kerning(FT_Face face, FT_Fixed point_size, FT_Int degree, FT_Fixed *kerning)
|
||||
FT_Error FT_Get_Glyph_Name(FT_Face face, FT_UInt glyph_index, FT_Pointer buffer, FT_UInt buffer_max)
|
||||
char* FT_Get_Postscript_Name(FT_Face face)
|
||||
FT_Error FT_Select_Charmap(FT_Face face, FT_Encoding encoding)
|
||||
FT_Error FT_Set_Charmap(FT_Face face, FT_CharMap charmap)
|
||||
|
||||
FT_Int FT_Get_Charmap_Index(FT_CharMap charmap)
|
||||
FT_UInt FT_Get_Char_Index(FT_Face face, FT_ULong charcode)
|
||||
FT_ULong FT_Get_First_Char(FT_Face face, FT_UInt *glyph_index)
|
||||
FT_ULong FT_Get_Next_Char(FT_Face face, FT_ULong charcode, FT_UInt *glyph_index)
|
||||
FT_UInt FT_Get_Name_Index(FT_Face face, FT_String *glyph_name)
|
||||
|
||||
DEF FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS = 1
|
||||
DEF FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES = 2
|
||||
DEF FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID = 4
|
||||
DEF FT_SUBGLYPH_FLAG_SCALE = 8
|
||||
DEF FT_SUBGLYPH_FLAG_XY_SCALE = 64
|
||||
DEF FT_SUBGLYPH_FLAG_2X2 = 128
|
||||
DEF FT_SUBGLYPH_FLAG_USE_MY_METRICS = 512
|
||||
|
||||
void FT_Library_Version(FT_Library, FT_Int *major, FT_Int *minor, FT_Int *patch)
|
||||
FT_Bool FT_Face_CheckTrueTypePatents(FT_Face face)
|
||||
FT_Bool FT_Face_SetUnpatentedHinting(FT_Face face, FT_Bool value)
|
||||
|
||||
|
||||
|
||||
#ftglyph.h
|
||||
ctypedef struct FT_GlyphRec:
|
||||
FT_Library library
|
||||
FT_Glyph_Format format
|
||||
FT_Vector advance
|
||||
ctypedef FT_GlyphRec* FT_Glyph
|
||||
|
||||
ctypedef struct FT_BitmapGlyphRec:
|
||||
FT_GlyphRec root
|
||||
FT_Int left, top
|
||||
FT_Bitmap bitmap
|
||||
ctypedef FT_BitmapGlyphRec* FT_BitmapGlyph
|
||||
|
||||
ctypedef struct FT_OutlineGlyphRec:
|
||||
FT_GlyphRec root
|
||||
FT_Outline outline
|
||||
ctypedef FT_OutlineGlyphRec* FT_OutlineGlyph
|
||||
|
||||
FT_Error FT_Get_Glyph(FT_GlyphSlot slot, FT_Glyph *glyph)
|
||||
FT_Error FT_Glyph_Copy(FT_Glyph source, FT_Glyph *target)
|
||||
FT_Error FT_Glyph_Transform(FT_Glyph glyph, FT_Matrix *matrix, FT_Vector *delta)
|
||||
|
||||
ctypedef enum FT_Glyph_BBox_Mode:
|
||||
FT_GLYPH_BBOX_UNSCALED = 0,
|
||||
FT_GLYPH_BBOX_SUBPIXELS = 0,
|
||||
FT_GLYPH_BBOX_GRIDFIT = 1,
|
||||
FT_GLYPH_BBOX_TRUNCATE = 2,
|
||||
FT_GLYPH_BBOX_PIXELS = 3
|
||||
|
||||
void FT_Glyph_Get_CBox(FT_Glyph glyph, FT_UInt bbox_mode, FT_BBox *cbox)
|
||||
FT_Error FT_Glyph_To_Bitmap(FT_Glyph *glyph, FT_Render_Mode mode, FT_Vector *origin, FT_Bool destroy)
|
||||
void FT_Done_Glyph(FT_Glyph glyph)
|
||||
|
||||
void FT_Matrix_Multiply(FT_Matrix *a, FT_Matrix *b)
|
||||
FT_Error FT_Matrix_Invert(FT_Matrix *matrix)
|
||||
|
||||
|
||||
|
||||
#ftoutln.h
|
||||
FT_Error FT_Outline_Decompose(FT_Outline *outline, FT_Outline_Funcs *funcs, void *user)
|
||||
FT_Error FT_Outline_New(FT_Library lib, FT_UInt n_points, FT_Int n_contours, FT_Outline *outline)
|
||||
FT_Error FT_Outline_Done(FT_Library lib, FT_Outline *outline)
|
||||
FT_Error FT_Outline_Copy(FT_Outline *source, FT_Outline *target)
|
||||
FT_Error FT_Outline_Check(FT_Outline *outline)
|
||||
|
||||
void FT_Outline_Get_CBox(FT_Outline *outline, FT_BBox *cbox)
|
||||
void FT_Outline_Translate(FT_Outline *outline, FT_Pos xOffset, FT_Pos yOffset)
|
||||
void FT_Outline_Transform(FT_Outline *outline, FT_Matrix *matrix)
|
||||
FT_Error FT_Outline_Embolden(FT_Outline *outline, FT_Pos strength)
|
||||
void FT_Outline_Reverse(FT_Outline *outline)
|
||||
FT_Error FT_Outline_Get_Bitmap(FT_Library lib, FT_Outline *outline, FT_Bitmap *bitmap)
|
||||
#FT_Error FT_Outline_Render(FT_Library lib, FT_Outline *outline, FT_Raster_params *params)
|
||||
|
||||
ctypedef enum FT_Orientation:
|
||||
FT_ORIENTATION_TRUETYPE = 0,
|
||||
FT_ORIENTATION_POSTSCRIPT = 1,
|
||||
FT_ORIENTATION_FILL_RIGHT = FT_ORIENTATION_TRUETYPE,
|
||||
FT_ORIENTATION_FILL_LEFT = FT_ORIENTATION_POSTSCRIPT,
|
||||
FT_ORIENTATION_NONE
|
||||
|
||||
FT_Orientation FT_Outline_Get_Orientation(FT_Outline *outline)
|
||||
|
||||
#ftbitmap.h
|
||||
void FT_Bitmap_New(FT_Bitmap *bitmap)
|
||||
FT_Error FT_Bitmap_Done(FT_Library lib, FT_Bitmap *bitmap)
|
||||
FT_Error FT_Bitmap_Copy(FT_Library lib, FT_Bitmap *source, FT_Bitmap *target)
|
||||
FT_Error FT_Bitmap_Embolden(FT_Library lib, FT_Bitmap *bitmap, FT_Pos xStrength, FT_Pos yStrength)
|
||||
FT_Error FT_Bitmap_Convert(FT_Library lib, FT_Bitmap *source, FT_Bitmap *target, FT_Int alignment)
|
||||
|
||||
# Additions by Tom Rothame.
|
||||
|
||||
cdef struct FT_MemoryRec_
|
||||
ctypedef FT_MemoryRec_ *FT_Memory
|
||||
|
||||
ctypedef void * (*FT_AllocFunc)(FT_Memory, long)
|
||||
ctypedef void (*FT_FreeFunc)(FT_Memory, void *)
|
||||
ctypedef void * (*FT_Realloc_Func)(FT_Memory, long, long, void*)
|
||||
|
||||
cdef struct FT_StreamRec_
|
||||
ctypedef FT_StreamRec_* FT_Stream
|
||||
|
||||
cdef union FT_StreamDesc:
|
||||
long value
|
||||
void *pointer
|
||||
|
||||
ctypedef unsigned long (*FT_Stream_IoFunc)(
|
||||
FT_Stream,
|
||||
unsigned long,
|
||||
unsigned char *,
|
||||
unsigned long)
|
||||
|
||||
ctypedef void (*FT_Stream_CloseFunc)(
|
||||
FT_Stream stream)
|
||||
|
||||
cdef struct FT_StreamRec_:
|
||||
unsigned char *base
|
||||
unsigned long size
|
||||
unsigned long pos
|
||||
FT_StreamDesc descriptor
|
||||
FT_StreamDesc pathname
|
||||
FT_Stream_IoFunc read
|
||||
FT_Stream_CloseFunc close
|
||||
|
||||
FT_Memory memory
|
||||
unsigned char *cursor
|
||||
unsigned char *limit
|
||||
|
||||
ctypedef FT_StreamRec_ FT_StreamRec
|
||||
|
||||
cdef struct FT_ModuleRec_
|
||||
ctypedef FT_ModuleRec_ *FT_Module
|
||||
cdef struct FT_ParameterRec_
|
||||
ctypedef struct FT_Parameter
|
||||
|
||||
ctypedef struct FT_Open_Args:
|
||||
FT_UInt flags
|
||||
FT_Byte *memory_base
|
||||
FT_Long memory_size
|
||||
FT_String *pathname
|
||||
FT_Stream stream
|
||||
|
||||
FT_Module driver
|
||||
FT_Int num_params
|
||||
FT_Parameter *params
|
||||
|
||||
cdef enum:
|
||||
FT_OPEN_MEMORY
|
||||
FT_OPEN_STREAM
|
||||
FT_OPEN_PATHNAME
|
||||
FT_OPEN_DRIVER
|
||||
FT_OPEN_PARAMS
|
||||
|
||||
FT_Error FT_Open_Face(
|
||||
FT_Library library,
|
||||
FT_Open_Args *args,
|
||||
FT_Long face_index,
|
||||
FT_Face *aface)
|
||||
|
||||
cdef struct FT_Stroker_Rec_
|
||||
ctypedef FT_Stroker_Rec_ *FT_Stroker
|
||||
|
||||
FT_Error FT_Stroker_New( FT_Library library,
|
||||
FT_Stroker *astroker )
|
||||
|
||||
cdef enum FT_Stroker_LineCap:
|
||||
FT_STROKER_LINECAP_ROUND
|
||||
cdef enum FT_Stroker_LineJoin:
|
||||
FT_STROKER_LINEJOIN_ROUND
|
||||
|
||||
void FT_Stroker_Set( FT_Stroker stroker,
|
||||
FT_Fixed radius,
|
||||
FT_Stroker_LineCap line_cap,
|
||||
FT_Stroker_LineJoin line_join,
|
||||
FT_Fixed miter_limit )
|
||||
|
||||
void FT_Glyph_StrokeBorder(FT_Glyph *, FT_Stroker, FT_Bool, FT_Bool)
|
||||
|
||||
void FT_Stroker_Done(FT_Stroker)
|
||||
|
||||
cdef FT_Long FT_MulFix(FT_Long, FT_Long)
|
||||
cdef FT_Long FT_CEIL(FT_Long)
|
||||
cdef FT_Long FT_FLOOR(FT_Long)
|
||||
cdef FT_Long FT_ROUND(FT_Long)
|
||||
@@ -1,23 +0,0 @@
|
||||
cdef extern from "pygame/pygame.h":
|
||||
struct SDL_Surface:
|
||||
int w
|
||||
int h
|
||||
int pitch
|
||||
int flags
|
||||
void *pixels
|
||||
|
||||
struct SDL_Rect:
|
||||
int x
|
||||
int y
|
||||
int w
|
||||
int h
|
||||
|
||||
SDL_Surface *PySurface_AsSurface(object)
|
||||
int SDL_SetAlpha(SDL_Surface *surface, unsigned int flag, char alpha)
|
||||
|
||||
enum:
|
||||
SDL_SRCALPHA
|
||||
|
||||
cdef extern int SDL_BlitSurface(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect) nogil
|
||||
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
from freetype cimport *
|
||||
|
||||
cdef extern from "stdint.h":
|
||||
ctypedef signed short int16_t
|
||||
ctypedef unsigned short uint16_t
|
||||
ctypedef signed long int32_t
|
||||
ctypedef unsigned long uint32_t
|
||||
|
||||
cdef extern from "ttgsubtable.h":
|
||||
|
||||
ctypedef struct tt_gsub_header:
|
||||
uint32_t Version
|
||||
uint16_t ScriptList
|
||||
uint16_t FeatureList
|
||||
uint16_t LookupList
|
||||
|
||||
ctypedef struct TLangSys:
|
||||
uint16_t LookupOrder
|
||||
uint16_t ReqFeatureIndex
|
||||
uint16_t FeatureCount
|
||||
uint16_t *FeatureIndex
|
||||
|
||||
ctypedef struct TLangSysRecord:
|
||||
uint32_t LangSysTag
|
||||
TLangSys LangSys
|
||||
|
||||
ctypedef struct TScript:
|
||||
uint16_t DefaultLangSys
|
||||
uint16_t LangSysCount
|
||||
TLangSysRecord *LangSysRecord
|
||||
|
||||
ctypedef struct TScriptRecord:
|
||||
uint32_t ScriptTag
|
||||
TScript Script
|
||||
|
||||
ctypedef struct TScriptList:
|
||||
uint16_t ScriptCount
|
||||
TScriptRecord *ScriptRecord
|
||||
|
||||
ctypedef struct TFeature:
|
||||
uint16_t FeatureParams
|
||||
int LookupCount
|
||||
uint16_t *LookupListIndex
|
||||
|
||||
ctypedef struct TFeatureRecord:
|
||||
uint32_t FeatureTag
|
||||
TFeature Feature
|
||||
|
||||
ctypedef struct TFeatureList:
|
||||
int FeatureCount
|
||||
TFeatureRecord *FeatureRecord
|
||||
|
||||
ctypedef struct TRangeRecord:
|
||||
uint16_t Start
|
||||
uint16_t End
|
||||
uint16_t StartCoverageIndex
|
||||
|
||||
ctypedef struct TCoverageFormat:
|
||||
uint16_t CoverageFormat
|
||||
uint16_t GlyphCount
|
||||
uint16_t *GlyphArray
|
||||
uint16_t RangeCount
|
||||
TRangeRecord *RangeRecord
|
||||
|
||||
ctypedef struct TSingleSubstFormat:
|
||||
uint16_t SubstFormat
|
||||
TCoverageFormat Coverage
|
||||
int16_t DeltaGlyphID
|
||||
uint16_t GlyphCount
|
||||
uint16_t *Substitute
|
||||
|
||||
ctypedef struct TLookup:
|
||||
uint16_t LookupType
|
||||
uint16_t LookupFlag
|
||||
uint16_t SubTableCount
|
||||
TSingleSubstFormat *SubTable
|
||||
|
||||
ctypedef struct TLookupList:
|
||||
int LookupCount
|
||||
TLookup *Lookup
|
||||
|
||||
ctypedef struct TTGSUBTable:
|
||||
int loaded
|
||||
tt_gsub_header header
|
||||
TScriptList ScriptList
|
||||
TFeatureList FeatureList
|
||||
TLookupList LookupList
|
||||
|
||||
ctypedef struct TTGSUBTable:
|
||||
int loaded
|
||||
tt_gsub_header header
|
||||
TScriptList ScriptList
|
||||
TFeatureList FeatureList
|
||||
TLookupList LookupList
|
||||
|
||||
void LoadGSUBTable(TTGSUBTable *table, FT_Face face)
|
||||
int GetVerticalGlyph(TTGSUBTable *table, uint32_t glyphnum, uint32_t *vglyphnum)
|
||||
void init_gsubtable(TTGSUBTable *table)
|
||||
void free_gsubtable(TTGSUBTable *table)
|
||||
@@ -1,706 +0,0 @@
|
||||
/* mmx.h
|
||||
|
||||
MultiMedia eXtensions GCC interface library for IA32.
|
||||
|
||||
To use this library, simply include this header file
|
||||
and compile with GCC. You MUST have inlining enabled
|
||||
in order for mmx_ok() to work; this can be done by
|
||||
simply using -O on the GCC command line.
|
||||
|
||||
Compiling with -DMMX_TRACE will cause detailed trace
|
||||
output to be sent to stderr for each mmx operation.
|
||||
This adds lots of code, and obviously slows execution to
|
||||
a crawl, but can be very useful for debugging.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
|
||||
LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS FOR ANY PARTICULAR PURPOSE.
|
||||
|
||||
1997-99 by H. Dietz and R. Fisher
|
||||
|
||||
Notes:
|
||||
It appears that the latest gas has the pand problem fixed, therefore
|
||||
I'll undefine BROKEN_PAND by default.
|
||||
*/
|
||||
|
||||
#ifndef _MMX_H
|
||||
#define _MMX_H
|
||||
|
||||
|
||||
/* Warning: at this writing, the version of GAS packaged
|
||||
with most Linux distributions does not handle the
|
||||
parallel AND operation mnemonic correctly. If the
|
||||
symbol BROKEN_PAND is defined, a slower alternative
|
||||
coding will be used. If execution of mmxtest results
|
||||
in an illegal instruction fault, define this symbol.
|
||||
*/
|
||||
#undef BROKEN_PAND
|
||||
|
||||
|
||||
/* The type of an value that fits in an MMX register
|
||||
(note that long long constant values MUST be suffixed
|
||||
by LL and unsigned long long values by ULL, lest
|
||||
they be truncated by the compiler)
|
||||
*/
|
||||
typedef union {
|
||||
long long q; /* Quadword (64-bit) value */
|
||||
unsigned long long uq; /* Unsigned Quadword */
|
||||
int d[2]; /* 2 Doubleword (32-bit) values */
|
||||
unsigned int ud[2]; /* 2 Unsigned Doubleword */
|
||||
short w[4]; /* 4 Word (16-bit) values */
|
||||
unsigned short uw[4]; /* 4 Unsigned Word */
|
||||
char b[8]; /* 8 Byte (8-bit) values */
|
||||
unsigned char ub[8]; /* 8 Unsigned Byte */
|
||||
float s[2]; /* Single-precision (32-bit) value */
|
||||
} __attribute__ ((aligned (8))) mmx_t; /* On an 8-byte (64-bit) boundary */
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
/* Function to test if multimedia instructions are supported...
|
||||
*/
|
||||
inline extern int
|
||||
mm_support(void)
|
||||
{
|
||||
/* Returns 1 if MMX instructions are supported,
|
||||
3 if Cyrix MMX and Extended MMX instructions are supported
|
||||
5 if AMD MMX and 3DNow! instructions are supported
|
||||
0 if hardware does not support any of these
|
||||
*/
|
||||
register int rval = 0;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
/* See if CPUID instruction is supported ... */
|
||||
/* ... Get copies of EFLAGS into eax and ecx */
|
||||
"pushf\n\t"
|
||||
"popl %%eax\n\t"
|
||||
"movl %%eax, %%ecx\n\t"
|
||||
|
||||
/* ... Toggle the ID bit in one copy and store */
|
||||
/* to the EFLAGS reg */
|
||||
"xorl $0x200000, %%eax\n\t"
|
||||
"push %%eax\n\t"
|
||||
"popf\n\t"
|
||||
|
||||
/* ... Get the (hopefully modified) EFLAGS */
|
||||
"pushf\n\t"
|
||||
"popl %%eax\n\t"
|
||||
|
||||
/* ... Compare and test result */
|
||||
"xorl %%eax, %%ecx\n\t"
|
||||
"testl $0x200000, %%ecx\n\t"
|
||||
"jz NotSupported1\n\t" /* CPUID not supported */
|
||||
|
||||
|
||||
/* Get standard CPUID information, and
|
||||
go to a specific vendor section */
|
||||
"movl $0, %%eax\n\t"
|
||||
"cpuid\n\t"
|
||||
|
||||
/* Check for Intel */
|
||||
"cmpl $0x756e6547, %%ebx\n\t"
|
||||
"jne TryAMD\n\t"
|
||||
"cmpl $0x49656e69, %%edx\n\t"
|
||||
"jne TryAMD\n\t"
|
||||
"cmpl $0x6c65746e, %%ecx\n"
|
||||
"jne TryAMD\n\t"
|
||||
"jmp Intel\n\t"
|
||||
|
||||
/* Check for AMD */
|
||||
"\nTryAMD:\n\t"
|
||||
"cmpl $0x68747541, %%ebx\n\t"
|
||||
"jne TryCyrix\n\t"
|
||||
"cmpl $0x69746e65, %%edx\n\t"
|
||||
"jne TryCyrix\n\t"
|
||||
"cmpl $0x444d4163, %%ecx\n"
|
||||
"jne TryCyrix\n\t"
|
||||
"jmp AMD\n\t"
|
||||
|
||||
/* Check for Cyrix */
|
||||
"\nTryCyrix:\n\t"
|
||||
"cmpl $0x69727943, %%ebx\n\t"
|
||||
"jne NotSupported2\n\t"
|
||||
"cmpl $0x736e4978, %%edx\n\t"
|
||||
"jne NotSupported3\n\t"
|
||||
"cmpl $0x64616574, %%ecx\n\t"
|
||||
"jne NotSupported4\n\t"
|
||||
/* Drop through to Cyrix... */
|
||||
|
||||
|
||||
/* Cyrix Section */
|
||||
/* See if extended CPUID level 80000001 is supported */
|
||||
/* The value of CPUID/80000001 for the 6x86MX is undefined
|
||||
according to the Cyrix CPU Detection Guide (Preliminary
|
||||
Rev. 1.01 table 1), so we'll check the value of eax for
|
||||
CPUID/0 to see if standard CPUID level 2 is supported.
|
||||
According to the table, the only CPU which supports level
|
||||
2 is also the only one which supports extended CPUID levels.
|
||||
*/
|
||||
"cmpl $0x2, %%eax\n\t"
|
||||
"jne MMXtest\n\t" /* Use standard CPUID instead */
|
||||
|
||||
/* Extended CPUID supported (in theory), so get extended
|
||||
features */
|
||||
"movl $0x80000001, %%eax\n\t"
|
||||
"cpuid\n\t"
|
||||
"testl $0x00800000, %%eax\n\t" /* Test for MMX */
|
||||
"jz NotSupported5\n\t" /* MMX not supported */
|
||||
"testl $0x01000000, %%eax\n\t" /* Test for Ext'd MMX */
|
||||
"jnz EMMXSupported\n\t"
|
||||
"movl $1, %0:\n\n\t" /* MMX Supported */
|
||||
"jmp Return\n\n"
|
||||
"EMMXSupported:\n\t"
|
||||
"movl $3, %0:\n\n\t" /* EMMX and MMX Supported */
|
||||
"jmp Return\n\t"
|
||||
|
||||
|
||||
/* AMD Section */
|
||||
"AMD:\n\t"
|
||||
|
||||
/* See if extended CPUID is supported */
|
||||
"movl $0x80000000, %%eax\n\t"
|
||||
"cpuid\n\t"
|
||||
"cmpl $0x80000000, %%eax\n\t"
|
||||
"jl MMXtest\n\t" /* Use standard CPUID instead */
|
||||
|
||||
/* Extended CPUID supported, so get extended features */
|
||||
"movl $0x80000001, %%eax\n\t"
|
||||
"cpuid\n\t"
|
||||
"testl $0x00800000, %%edx\n\t" /* Test for MMX */
|
||||
"jz NotSupported6\n\t" /* MMX not supported */
|
||||
"testl $0x80000000, %%edx\n\t" /* Test for 3DNow! */
|
||||
"jnz ThreeDNowSupported\n\t"
|
||||
"movl $1, %0:\n\n\t" /* MMX Supported */
|
||||
"jmp Return\n\n"
|
||||
"ThreeDNowSupported:\n\t"
|
||||
"movl $5, %0:\n\n\t" /* 3DNow! and MMX Supported */
|
||||
"jmp Return\n\t"
|
||||
|
||||
|
||||
/* Intel Section */
|
||||
"Intel:\n\t"
|
||||
|
||||
/* Check for MMX */
|
||||
"MMXtest:\n\t"
|
||||
"movl $1, %%eax\n\t"
|
||||
"cpuid\n\t"
|
||||
"testl $0x00800000, %%edx\n\t" /* Test for MMX */
|
||||
"jz NotSupported7\n\t" /* MMX Not supported */
|
||||
"movl $1, %0:\n\n\t" /* MMX Supported */
|
||||
"jmp Return\n\t"
|
||||
|
||||
/* Nothing supported */
|
||||
"\nNotSupported1:\n\t"
|
||||
"#movl $101, %0:\n\n\t"
|
||||
"\nNotSupported2:\n\t"
|
||||
"#movl $102, %0:\n\n\t"
|
||||
"\nNotSupported3:\n\t"
|
||||
"#movl $103, %0:\n\n\t"
|
||||
"\nNotSupported4:\n\t"
|
||||
"#movl $104, %0:\n\n\t"
|
||||
"\nNotSupported5:\n\t"
|
||||
"#movl $105, %0:\n\n\t"
|
||||
"\nNotSupported6:\n\t"
|
||||
"#movl $106, %0:\n\n\t"
|
||||
"\nNotSupported7:\n\t"
|
||||
"#movl $107, %0:\n\n\t"
|
||||
"movl $0, %0:\n\n\t"
|
||||
|
||||
"Return:\n\t"
|
||||
: "=a" (rval)
|
||||
: /* no input */
|
||||
: "eax", "ebx", "ecx", "edx"
|
||||
);
|
||||
|
||||
/* Return */
|
||||
return(rval);
|
||||
}
|
||||
|
||||
/* Function to test if mmx instructions are supported...
|
||||
*/
|
||||
inline extern int
|
||||
mmx_ok(void)
|
||||
{
|
||||
/* Returns 1 if MMX instructions are supported, 0 otherwise */
|
||||
return ( mm_support() & 0x1 );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Helper functions for the instruction macros that follow...
|
||||
(note that memory-to-register, m2r, instructions are nearly
|
||||
as efficient as register-to-register, r2r, instructions;
|
||||
however, memory-to-memory instructions are really simulated
|
||||
as a convenience, and are only 1/3 as efficient)
|
||||
*/
|
||||
#ifdef MMX_TRACE
|
||||
|
||||
/* Include the stuff for printing a trace to stderr...
|
||||
*/
|
||||
|
||||
#define mmx_i2r(op, imm, reg) \
|
||||
{ \
|
||||
mmx_t mmx_trace; \
|
||||
mmx_trace.uq = (imm); \
|
||||
printf(#op "_i2r(" #imm "=0x%08x%08x, ", \
|
||||
mmx_trace.d[1], mmx_trace.d[0]); \
|
||||
__asm__ __volatile__ ("movq %%" #reg ", %0" \
|
||||
: "=X" (mmx_trace) \
|
||||
: /* nothing */ ); \
|
||||
printf(#reg "=0x%08x%08x) => ", \
|
||||
mmx_trace.d[1], mmx_trace.d[0]); \
|
||||
__asm__ __volatile__ (#op " %0, %%" #reg \
|
||||
: /* nothing */ \
|
||||
: "X" (imm)); \
|
||||
__asm__ __volatile__ ("movq %%" #reg ", %0" \
|
||||
: "=X" (mmx_trace) \
|
||||
: /* nothing */ ); \
|
||||
printf(#reg "=0x%08x%08x\n", \
|
||||
mmx_trace.d[1], mmx_trace.d[0]); \
|
||||
}
|
||||
|
||||
#define mmx_m2r(op, mem, reg) \
|
||||
{ \
|
||||
mmx_t mmx_trace; \
|
||||
mmx_trace = (mem); \
|
||||
printf(#op "_m2r(" #mem "=0x%08x%08x, ", \
|
||||
mmx_trace.d[1], mmx_trace.d[0]); \
|
||||
__asm__ __volatile__ ("movq %%" #reg ", %0" \
|
||||
: "=X" (mmx_trace) \
|
||||
: /* nothing */ ); \
|
||||
printf(#reg "=0x%08x%08x) => ", \
|
||||
mmx_trace.d[1], mmx_trace.d[0]); \
|
||||
__asm__ __volatile__ (#op " %0, %%" #reg \
|
||||
: /* nothing */ \
|
||||
: "X" (mem)); \
|
||||
__asm__ __volatile__ ("movq %%" #reg ", %0" \
|
||||
: "=X" (mmx_trace) \
|
||||
: /* nothing */ ); \
|
||||
printf(#reg "=0x%08x%08x\n", \
|
||||
mmx_trace.d[1], mmx_trace.d[0]); \
|
||||
}
|
||||
|
||||
#define mmx_r2m(op, reg, mem) \
|
||||
{ \
|
||||
mmx_t mmx_trace; \
|
||||
__asm__ __volatile__ ("movq %%" #reg ", %0" \
|
||||
: "=X" (mmx_trace) \
|
||||
: /* nothing */ ); \
|
||||
printf(#op "_r2m(" #reg "=0x%08x%08x, ", \
|
||||
mmx_trace.d[1], mmx_trace.d[0]); \
|
||||
mmx_trace = (mem); \
|
||||
printf(#mem "=0x%08x%08x) => ", \
|
||||
mmx_trace.d[1], mmx_trace.d[0]); \
|
||||
__asm__ __volatile__ (#op " %%" #reg ", %0" \
|
||||
: "=X" (mem) \
|
||||
: /* nothing */ ); \
|
||||
mmx_trace = (mem); \
|
||||
printf(#mem "=0x%08x%08x\n", \
|
||||
mmx_trace.d[1], mmx_trace.d[0]); \
|
||||
}
|
||||
|
||||
#define mmx_r2r(op, regs, regd) \
|
||||
{ \
|
||||
mmx_t mmx_trace; \
|
||||
__asm__ __volatile__ ("movq %%" #regs ", %0" \
|
||||
: "=X" (mmx_trace) \
|
||||
: /* nothing */ ); \
|
||||
printf(#op "_r2r(" #regs "=0x%08x%08x, ", \
|
||||
mmx_trace.d[1], mmx_trace.d[0]); \
|
||||
__asm__ __volatile__ ("movq %%" #regd ", %0" \
|
||||
: "=X" (mmx_trace) \
|
||||
: /* nothing */ ); \
|
||||
printf(#regd "=0x%08x%08x) => ", \
|
||||
mmx_trace.d[1], mmx_trace.d[0]); \
|
||||
__asm__ __volatile__ (#op " %" #regs ", %" #regd); \
|
||||
__asm__ __volatile__ ("movq %%" #regd ", %0" \
|
||||
: "=X" (mmx_trace) \
|
||||
: /* nothing */ ); \
|
||||
printf(#regd "=0x%08x%08x\n", \
|
||||
mmx_trace.d[1], mmx_trace.d[0]); \
|
||||
}
|
||||
|
||||
#define mmx_m2m(op, mems, memd) \
|
||||
{ \
|
||||
mmx_t mmx_trace; \
|
||||
mmx_trace = (mems); \
|
||||
printf(#op "_m2m(" #mems "=0x%08x%08x, ", \
|
||||
mmx_trace.d[1], mmx_trace.d[0]); \
|
||||
mmx_trace = (memd); \
|
||||
printf(#memd "=0x%08x%08x) => ", \
|
||||
mmx_trace.d[1], mmx_trace.d[0]); \
|
||||
__asm__ __volatile__ ("movq %0, %%mm0\n\t" \
|
||||
#op " %1, %%mm0\n\t" \
|
||||
"movq %%mm0, %0" \
|
||||
: "=X" (memd) \
|
||||
: "X" (mems)); \
|
||||
mmx_trace = (memd); \
|
||||
printf(#memd "=0x%08x%08x\n", \
|
||||
mmx_trace.d[1], mmx_trace.d[0]); \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* These macros are a lot simpler without the tracing...
|
||||
*/
|
||||
|
||||
#define mmx_i2r(op, imm, reg) \
|
||||
__asm__ __volatile__ (#op " %0, %%" #reg \
|
||||
: /* nothing */ \
|
||||
: "X" (imm) )
|
||||
|
||||
#define mmx_m2r(op, mem, reg) \
|
||||
__asm__ __volatile__ (#op " %0, %%" #reg \
|
||||
: /* nothing */ \
|
||||
: "m" (mem))
|
||||
|
||||
#define mmx_r2m(op, reg, mem) \
|
||||
__asm__ __volatile__ (#op " %%" #reg ", %0" \
|
||||
: "=m" (mem) \
|
||||
: /* nothing */ )
|
||||
|
||||
#define mmx_r2r(op, regs, regd) \
|
||||
__asm__ __volatile__ (#op " %" #regs ", %" #regd)
|
||||
|
||||
#define mmx_m2m(op, mems, memd) \
|
||||
__asm__ __volatile__ ("movq %0, %%mm0\n\t" \
|
||||
#op " %1, %%mm0\n\t" \
|
||||
"movq %%mm0, %0" \
|
||||
: "=X" (memd) \
|
||||
: "X" (mems))
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* 1x64 MOVe Quadword
|
||||
(this is both a load and a store...
|
||||
in fact, it is the only way to store)
|
||||
*/
|
||||
#define movq_m2r(var, reg) mmx_m2r(movq, var, reg)
|
||||
#define movq_r2m(reg, var) mmx_r2m(movq, reg, var)
|
||||
#define movq_r2r(regs, regd) mmx_r2r(movq, regs, regd)
|
||||
#define movq(vars, vard) \
|
||||
__asm__ __volatile__ ("movq %1, %%mm0\n\t" \
|
||||
"movq %%mm0, %0" \
|
||||
: "=X" (vard) \
|
||||
: "X" (vars))
|
||||
|
||||
|
||||
/* 1x32 MOVe Doubleword
|
||||
(like movq, this is both load and store...
|
||||
but is most useful for moving things between
|
||||
mmx registers and ordinary registers)
|
||||
*/
|
||||
#define movd_m2r(var, reg) mmx_m2r(movd, var, reg)
|
||||
#define movd_r2m(reg, var) mmx_r2m(movd, reg, var)
|
||||
#define movd_r2r(regs, regd) mmx_r2r(movd, regs, regd)
|
||||
#define movd(vars, vard) \
|
||||
__asm__ __volatile__ ("movd %1, %%mm0\n\t" \
|
||||
"movd %%mm0, %0" \
|
||||
: "=X" (vard) \
|
||||
: "X" (vars))
|
||||
|
||||
|
||||
/* 2x32, 4x16, and 8x8 Parallel ADDs
|
||||
*/
|
||||
#define paddd_m2r(var, reg) mmx_m2r(paddd, var, reg)
|
||||
#define paddd_r2r(regs, regd) mmx_r2r(paddd, regs, regd)
|
||||
#define paddd(vars, vard) mmx_m2m(paddd, vars, vard)
|
||||
|
||||
#define paddw_m2r(var, reg) mmx_m2r(paddw, var, reg)
|
||||
#define paddw_r2r(regs, regd) mmx_r2r(paddw, regs, regd)
|
||||
#define paddw(vars, vard) mmx_m2m(paddw, vars, vard)
|
||||
|
||||
#define paddb_m2r(var, reg) mmx_m2r(paddb, var, reg)
|
||||
#define paddb_r2r(regs, regd) mmx_r2r(paddb, regs, regd)
|
||||
#define paddb(vars, vard) mmx_m2m(paddb, vars, vard)
|
||||
|
||||
|
||||
/* 4x16 and 8x8 Parallel ADDs using Saturation arithmetic
|
||||
*/
|
||||
#define paddsw_m2r(var, reg) mmx_m2r(paddsw, var, reg)
|
||||
#define paddsw_r2r(regs, regd) mmx_r2r(paddsw, regs, regd)
|
||||
#define paddsw(vars, vard) mmx_m2m(paddsw, vars, vard)
|
||||
|
||||
#define paddsb_m2r(var, reg) mmx_m2r(paddsb, var, reg)
|
||||
#define paddsb_r2r(regs, regd) mmx_r2r(paddsb, regs, regd)
|
||||
#define paddsb(vars, vard) mmx_m2m(paddsb, vars, vard)
|
||||
|
||||
|
||||
/* 4x16 and 8x8 Parallel ADDs using Unsigned Saturation arithmetic
|
||||
*/
|
||||
#define paddusw_m2r(var, reg) mmx_m2r(paddusw, var, reg)
|
||||
#define paddusw_r2r(regs, regd) mmx_r2r(paddusw, regs, regd)
|
||||
#define paddusw(vars, vard) mmx_m2m(paddusw, vars, vard)
|
||||
|
||||
#define paddusb_m2r(var, reg) mmx_m2r(paddusb, var, reg)
|
||||
#define paddusb_r2r(regs, regd) mmx_r2r(paddusb, regs, regd)
|
||||
#define paddusb(vars, vard) mmx_m2m(paddusb, vars, vard)
|
||||
|
||||
|
||||
/* 2x32, 4x16, and 8x8 Parallel SUBs
|
||||
*/
|
||||
#define psubd_m2r(var, reg) mmx_m2r(psubd, var, reg)
|
||||
#define psubd_r2r(regs, regd) mmx_r2r(psubd, regs, regd)
|
||||
#define psubd(vars, vard) mmx_m2m(psubd, vars, vard)
|
||||
|
||||
#define psubw_m2r(var, reg) mmx_m2r(psubw, var, reg)
|
||||
#define psubw_r2r(regs, regd) mmx_r2r(psubw, regs, regd)
|
||||
#define psubw(vars, vard) mmx_m2m(psubw, vars, vard)
|
||||
|
||||
#define psubb_m2r(var, reg) mmx_m2r(psubb, var, reg)
|
||||
#define psubb_r2r(regs, regd) mmx_r2r(psubb, regs, regd)
|
||||
#define psubb(vars, vard) mmx_m2m(psubb, vars, vard)
|
||||
|
||||
|
||||
/* 4x16 and 8x8 Parallel SUBs using Saturation arithmetic
|
||||
*/
|
||||
#define psubsw_m2r(var, reg) mmx_m2r(psubsw, var, reg)
|
||||
#define psubsw_r2r(regs, regd) mmx_r2r(psubsw, regs, regd)
|
||||
#define psubsw(vars, vard) mmx_m2m(psubsw, vars, vard)
|
||||
|
||||
#define psubsb_m2r(var, reg) mmx_m2r(psubsb, var, reg)
|
||||
#define psubsb_r2r(regs, regd) mmx_r2r(psubsb, regs, regd)
|
||||
#define psubsb(vars, vard) mmx_m2m(psubsb, vars, vard)
|
||||
|
||||
|
||||
/* 4x16 and 8x8 Parallel SUBs using Unsigned Saturation arithmetic
|
||||
*/
|
||||
#define psubusw_m2r(var, reg) mmx_m2r(psubusw, var, reg)
|
||||
#define psubusw_r2r(regs, regd) mmx_r2r(psubusw, regs, regd)
|
||||
#define psubusw(vars, vard) mmx_m2m(psubusw, vars, vard)
|
||||
|
||||
#define psubusb_m2r(var, reg) mmx_m2r(psubusb, var, reg)
|
||||
#define psubusb_r2r(regs, regd) mmx_r2r(psubusb, regs, regd)
|
||||
#define psubusb(vars, vard) mmx_m2m(psubusb, vars, vard)
|
||||
|
||||
|
||||
/* 4x16 Parallel MULs giving Low 4x16 portions of results
|
||||
*/
|
||||
#define pmullw_m2r(var, reg) mmx_m2r(pmullw, var, reg)
|
||||
#define pmullw_r2r(regs, regd) mmx_r2r(pmullw, regs, regd)
|
||||
#define pmullw(vars, vard) mmx_m2m(pmullw, vars, vard)
|
||||
|
||||
|
||||
/* 4x16 Parallel MULs giving High 4x16 portions of results
|
||||
*/
|
||||
#define pmulhw_m2r(var, reg) mmx_m2r(pmulhw, var, reg)
|
||||
#define pmulhw_r2r(regs, regd) mmx_r2r(pmulhw, regs, regd)
|
||||
#define pmulhw(vars, vard) mmx_m2m(pmulhw, vars, vard)
|
||||
|
||||
|
||||
/* 4x16->2x32 Parallel Mul-ADD
|
||||
(muls like pmullw, then adds adjacent 16-bit fields
|
||||
in the multiply result to make the final 2x32 result)
|
||||
*/
|
||||
#define pmaddwd_m2r(var, reg) mmx_m2r(pmaddwd, var, reg)
|
||||
#define pmaddwd_r2r(regs, regd) mmx_r2r(pmaddwd, regs, regd)
|
||||
#define pmaddwd(vars, vard) mmx_m2m(pmaddwd, vars, vard)
|
||||
|
||||
|
||||
/* 1x64 bitwise AND
|
||||
*/
|
||||
#ifdef BROKEN_PAND
|
||||
#define pand_m2r(var, reg) \
|
||||
{ \
|
||||
mmx_m2r(pandn, (mmx_t) -1LL, reg); \
|
||||
mmx_m2r(pandn, var, reg); \
|
||||
}
|
||||
#define pand_r2r(regs, regd) \
|
||||
{ \
|
||||
mmx_m2r(pandn, (mmx_t) -1LL, regd); \
|
||||
mmx_r2r(pandn, regs, regd) \
|
||||
}
|
||||
#define pand(vars, vard) \
|
||||
{ \
|
||||
movq_m2r(vard, mm0); \
|
||||
mmx_m2r(pandn, (mmx_t) -1LL, mm0); \
|
||||
mmx_m2r(pandn, vars, mm0); \
|
||||
movq_r2m(mm0, vard); \
|
||||
}
|
||||
#else
|
||||
#define pand_m2r(var, reg) mmx_m2r(pand, var, reg)
|
||||
#define pand_r2r(regs, regd) mmx_r2r(pand, regs, regd)
|
||||
#define pand(vars, vard) mmx_m2m(pand, vars, vard)
|
||||
#endif
|
||||
|
||||
|
||||
/* 1x64 bitwise AND with Not the destination
|
||||
*/
|
||||
#define pandn_m2r(var, reg) mmx_m2r(pandn, var, reg)
|
||||
#define pandn_r2r(regs, regd) mmx_r2r(pandn, regs, regd)
|
||||
#define pandn(vars, vard) mmx_m2m(pandn, vars, vard)
|
||||
|
||||
|
||||
/* 1x64 bitwise OR
|
||||
*/
|
||||
#define por_m2r(var, reg) mmx_m2r(por, var, reg)
|
||||
#define por_r2r(regs, regd) mmx_r2r(por, regs, regd)
|
||||
#define por(vars, vard) mmx_m2m(por, vars, vard)
|
||||
|
||||
|
||||
/* 1x64 bitwise eXclusive OR
|
||||
*/
|
||||
#define pxor_m2r(var, reg) mmx_m2r(pxor, var, reg)
|
||||
#define pxor_r2r(regs, regd) mmx_r2r(pxor, regs, regd)
|
||||
#define pxor(vars, vard) mmx_m2m(pxor, vars, vard)
|
||||
|
||||
|
||||
/* 2x32, 4x16, and 8x8 Parallel CoMPare for EQuality
|
||||
(resulting fields are either 0 or -1)
|
||||
*/
|
||||
#define pcmpeqd_m2r(var, reg) mmx_m2r(pcmpeqd, var, reg)
|
||||
#define pcmpeqd_r2r(regs, regd) mmx_r2r(pcmpeqd, regs, regd)
|
||||
#define pcmpeqd(vars, vard) mmx_m2m(pcmpeqd, vars, vard)
|
||||
|
||||
#define pcmpeqw_m2r(var, reg) mmx_m2r(pcmpeqw, var, reg)
|
||||
#define pcmpeqw_r2r(regs, regd) mmx_r2r(pcmpeqw, regs, regd)
|
||||
#define pcmpeqw(vars, vard) mmx_m2m(pcmpeqw, vars, vard)
|
||||
|
||||
#define pcmpeqb_m2r(var, reg) mmx_m2r(pcmpeqb, var, reg)
|
||||
#define pcmpeqb_r2r(regs, regd) mmx_r2r(pcmpeqb, regs, regd)
|
||||
#define pcmpeqb(vars, vard) mmx_m2m(pcmpeqb, vars, vard)
|
||||
|
||||
|
||||
/* 2x32, 4x16, and 8x8 Parallel CoMPare for Greater Than
|
||||
(resulting fields are either 0 or -1)
|
||||
*/
|
||||
#define pcmpgtd_m2r(var, reg) mmx_m2r(pcmpgtd, var, reg)
|
||||
#define pcmpgtd_r2r(regs, regd) mmx_r2r(pcmpgtd, regs, regd)
|
||||
#define pcmpgtd(vars, vard) mmx_m2m(pcmpgtd, vars, vard)
|
||||
|
||||
#define pcmpgtw_m2r(var, reg) mmx_m2r(pcmpgtw, var, reg)
|
||||
#define pcmpgtw_r2r(regs, regd) mmx_r2r(pcmpgtw, regs, regd)
|
||||
#define pcmpgtw(vars, vard) mmx_m2m(pcmpgtw, vars, vard)
|
||||
|
||||
#define pcmpgtb_m2r(var, reg) mmx_m2r(pcmpgtb, var, reg)
|
||||
#define pcmpgtb_r2r(regs, regd) mmx_r2r(pcmpgtb, regs, regd)
|
||||
#define pcmpgtb(vars, vard) mmx_m2m(pcmpgtb, vars, vard)
|
||||
|
||||
|
||||
/* 1x64, 2x32, and 4x16 Parallel Shift Left Logical
|
||||
*/
|
||||
#define psllq_i2r(imm, reg) mmx_i2r(psllq, imm, reg)
|
||||
#define psllq_m2r(var, reg) mmx_m2r(psllq, var, reg)
|
||||
#define psllq_r2r(regs, regd) mmx_r2r(psllq, regs, regd)
|
||||
#define psllq(vars, vard) mmx_m2m(psllq, vars, vard)
|
||||
|
||||
#define pslld_i2r(imm, reg) mmx_i2r(pslld, imm, reg)
|
||||
#define pslld_m2r(var, reg) mmx_m2r(pslld, var, reg)
|
||||
#define pslld_r2r(regs, regd) mmx_r2r(pslld, regs, regd)
|
||||
#define pslld(vars, vard) mmx_m2m(pslld, vars, vard)
|
||||
|
||||
#define psllw_i2r(imm, reg) mmx_i2r(psllw, imm, reg)
|
||||
#define psllw_m2r(var, reg) mmx_m2r(psllw, var, reg)
|
||||
#define psllw_r2r(regs, regd) mmx_r2r(psllw, regs, regd)
|
||||
#define psllw(vars, vard) mmx_m2m(psllw, vars, vard)
|
||||
|
||||
|
||||
/* 1x64, 2x32, and 4x16 Parallel Shift Right Logical
|
||||
*/
|
||||
#define psrlq_i2r(imm, reg) mmx_i2r(psrlq, imm, reg)
|
||||
#define psrlq_m2r(var, reg) mmx_m2r(psrlq, var, reg)
|
||||
#define psrlq_r2r(regs, regd) mmx_r2r(psrlq, regs, regd)
|
||||
#define psrlq(vars, vard) mmx_m2m(psrlq, vars, vard)
|
||||
|
||||
#define psrld_i2r(imm, reg) mmx_i2r(psrld, imm, reg)
|
||||
#define psrld_m2r(var, reg) mmx_m2r(psrld, var, reg)
|
||||
#define psrld_r2r(regs, regd) mmx_r2r(psrld, regs, regd)
|
||||
#define psrld(vars, vard) mmx_m2m(psrld, vars, vard)
|
||||
|
||||
#define psrlw_i2r(imm, reg) mmx_i2r(psrlw, imm, reg)
|
||||
#define psrlw_m2r(var, reg) mmx_m2r(psrlw, var, reg)
|
||||
#define psrlw_r2r(regs, regd) mmx_r2r(psrlw, regs, regd)
|
||||
#define psrlw(vars, vard) mmx_m2m(psrlw, vars, vard)
|
||||
|
||||
|
||||
/* 2x32 and 4x16 Parallel Shift Right Arithmetic
|
||||
*/
|
||||
#define psrad_i2r(imm, reg) mmx_i2r(psrad, imm, reg)
|
||||
#define psrad_m2r(var, reg) mmx_m2r(psrad, var, reg)
|
||||
#define psrad_r2r(regs, regd) mmx_r2r(psrad, regs, regd)
|
||||
#define psrad(vars, vard) mmx_m2m(psrad, vars, vard)
|
||||
|
||||
#define psraw_i2r(imm, reg) mmx_i2r(psraw, imm, reg)
|
||||
#define psraw_m2r(var, reg) mmx_m2r(psraw, var, reg)
|
||||
#define psraw_r2r(regs, regd) mmx_r2r(psraw, regs, regd)
|
||||
#define psraw(vars, vard) mmx_m2m(psraw, vars, vard)
|
||||
|
||||
|
||||
/* 2x32->4x16 and 4x16->8x8 PACK and Signed Saturate
|
||||
(packs source and dest fields into dest in that order)
|
||||
*/
|
||||
#define packssdw_m2r(var, reg) mmx_m2r(packssdw, var, reg)
|
||||
#define packssdw_r2r(regs, regd) mmx_r2r(packssdw, regs, regd)
|
||||
#define packssdw(vars, vard) mmx_m2m(packssdw, vars, vard)
|
||||
|
||||
#define packsswb_m2r(var, reg) mmx_m2r(packsswb, var, reg)
|
||||
#define packsswb_r2r(regs, regd) mmx_r2r(packsswb, regs, regd)
|
||||
#define packsswb(vars, vard) mmx_m2m(packsswb, vars, vard)
|
||||
|
||||
|
||||
/* 4x16->8x8 PACK and Unsigned Saturate
|
||||
(packs source and dest fields into dest in that order)
|
||||
*/
|
||||
#define packuswb_m2r(var, reg) mmx_m2r(packuswb, var, reg)
|
||||
#define packuswb_r2r(regs, regd) mmx_r2r(packuswb, regs, regd)
|
||||
#define packuswb(vars, vard) mmx_m2m(packuswb, vars, vard)
|
||||
|
||||
|
||||
/* 2x32->1x64, 4x16->2x32, and 8x8->4x16 UNPaCK Low
|
||||
(interleaves low half of dest with low half of source
|
||||
as padding in each result field)
|
||||
*/
|
||||
#define punpckldq_m2r(var, reg) mmx_m2r(punpckldq, var, reg)
|
||||
#define punpckldq_r2r(regs, regd) mmx_r2r(punpckldq, regs, regd)
|
||||
#define punpckldq(vars, vard) mmx_m2m(punpckldq, vars, vard)
|
||||
|
||||
#define punpcklwd_m2r(var, reg) mmx_m2r(punpcklwd, var, reg)
|
||||
#define punpcklwd_r2r(regs, regd) mmx_r2r(punpcklwd, regs, regd)
|
||||
#define punpcklwd(vars, vard) mmx_m2m(punpcklwd, vars, vard)
|
||||
|
||||
#define punpcklbw_m2r(var, reg) mmx_m2r(punpcklbw, var, reg)
|
||||
#define punpcklbw_r2r(regs, regd) mmx_r2r(punpcklbw, regs, regd)
|
||||
#define punpcklbw(vars, vard) mmx_m2m(punpcklbw, vars, vard)
|
||||
|
||||
|
||||
/* 2x32->1x64, 4x16->2x32, and 8x8->4x16 UNPaCK High
|
||||
(interleaves high half of dest with high half of source
|
||||
as padding in each result field)
|
||||
*/
|
||||
#define punpckhdq_m2r(var, reg) mmx_m2r(punpckhdq, var, reg)
|
||||
#define punpckhdq_r2r(regs, regd) mmx_r2r(punpckhdq, regs, regd)
|
||||
#define punpckhdq(vars, vard) mmx_m2m(punpckhdq, vars, vard)
|
||||
|
||||
#define punpckhwd_m2r(var, reg) mmx_m2r(punpckhwd, var, reg)
|
||||
#define punpckhwd_r2r(regs, regd) mmx_r2r(punpckhwd, regs, regd)
|
||||
#define punpckhwd(vars, vard) mmx_m2m(punpckhwd, vars, vard)
|
||||
|
||||
#define punpckhbw_m2r(var, reg) mmx_m2r(punpckhbw, var, reg)
|
||||
#define punpckhbw_r2r(regs, regd) mmx_r2r(punpckhbw, regs, regd)
|
||||
#define punpckhbw(vars, vard) mmx_m2m(punpckhbw, vars, vard)
|
||||
|
||||
|
||||
/* Empty MMx State
|
||||
(used to clean-up when going from mmx to float use
|
||||
of the registers that are shared by both; note that
|
||||
there is no float-to-mmx operation needed, because
|
||||
only the float tag word info is corruptible)
|
||||
*/
|
||||
#ifdef MMX_TRACE
|
||||
|
||||
#define emms() \
|
||||
{ \
|
||||
printf("emms()\n"); \
|
||||
__asm__ __volatile__ ("emms"); \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define emms() __asm__ __volatile__ ("emms")
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
Copyright 2005 PyTom <pytom@bishoujo.us>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation files
|
||||
(the "Software"), to deal in the Software without restriction,
|
||||
including without limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef PSS_H
|
||||
#define PSS_H
|
||||
|
||||
#include <Python.h>
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
void PSS_play(int channel, SDL_RWops *rw, const char *ext, PyObject *name, int fadeout, int tight, int paused);
|
||||
void PSS_queue(int channel, SDL_RWops *rw, const char *ext, PyObject *name, int fadeout, int tight);
|
||||
void PSS_stop(int channel);
|
||||
void PSS_dequeue(int channel, int even_tight);
|
||||
int PSS_queue_depth(int channel);
|
||||
PyObject *PSS_playing_name(int channel);
|
||||
void PSS_fadeout(int channel, int ms);
|
||||
void PSS_pause(int channel, int pause);
|
||||
void PSS_unpause_all(void);
|
||||
void PSS_set_endevent(int channel, int event);
|
||||
int PSS_get_pos(int channel);
|
||||
void PSS_set_volume(int channel, float volume);
|
||||
float PSS_get_volume(int channel);
|
||||
void PSS_set_pan(int channel, float pan, float delay);
|
||||
void PSS_set_secondary_volume(int channel, float vol2, float delay);
|
||||
void PSS_init(int freq, int stereo, int samples, int status);
|
||||
void PSS_quit(void);
|
||||
|
||||
void PSS_periodic(void);
|
||||
void PSS_alloc_event(PyObject *surface);
|
||||
int PSS_refresh_event(void);
|
||||
|
||||
char *PSS_get_error(void);
|
||||
|
||||
extern int ffpy_needs_alloc;
|
||||
extern int ffpy_movie_width;
|
||||
extern int ffpy_movie_height;
|
||||
|
||||
#endif
|
||||
@@ -1,13 +0,0 @@
|
||||
#include <ft2build.h>
|
||||
#include FT_CONFIG_CONFIG_H
|
||||
#include FT_TYPES_H
|
||||
#include FT_FREETYPE_H
|
||||
#include FT_IMAGE_H
|
||||
#include FT_GLYPH_H
|
||||
#include FT_OUTLINE_H
|
||||
#include FT_BITMAP_H
|
||||
#include FT_STROKER_H
|
||||
|
||||
#define FT_FLOOR(X) ((X & -64) >> 6)
|
||||
#define FT_CEIL(X) (((X + 63) & -64) >> 6)
|
||||
#define FT_ROUND(X) (((X + 32) & -64) >> 6)
|
||||
@@ -1,16 +0,0 @@
|
||||
import sys
|
||||
|
||||
from sound import *
|
||||
|
||||
try:
|
||||
import winmixer #@UnresolvedImport
|
||||
sys.modules['winmixer'] = sys.modules['pysdlsound.winmixer']
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
import linmixer #@UnresolvedImport
|
||||
sys.modules['linmixer'] = sys.modules['pysdlsound.linmixer']
|
||||
except:
|
||||
pass
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
from ossaudiodev import * #@UnusedWildImport
|
||||
mixer = openmixer()
|
||||
|
||||
def get_wave():
|
||||
if not mixer.controls() & 1 << SOUND_MIXER_PCM:
|
||||
return None
|
||||
|
||||
l, r = mixer.get(SOUND_MIXER_PCM)
|
||||
|
||||
return (l + r) / 200.0
|
||||
|
||||
def set_wave(vol):
|
||||
if not mixer.controls() & 1 << SOUND_MIXER_PCM:
|
||||
return None
|
||||
|
||||
v = int(vol * 100)
|
||||
|
||||
mixer.set(SOUND_MIXER_PCM, (v, v))
|
||||
|
||||
|
||||
def get_midi():
|
||||
return None
|
||||
|
||||
def set_midi(vol):
|
||||
return
|
||||
@@ -1,188 +0,0 @@
|
||||
# -*- python -*-
|
||||
# Copyright 2004-2012 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.
|
||||
|
||||
cdef extern from "pygame/pygame.h":
|
||||
cdef struct SDL_RWops:
|
||||
pass
|
||||
|
||||
void import_pygame_rwobject()
|
||||
SDL_RWops* RWopsFromPythonThreaded(object obj)
|
||||
|
||||
cdef extern from "pss.h":
|
||||
|
||||
void PSS_play(int channel, SDL_RWops *rw, char *ext, object name, int fadein, int tight, int paused)
|
||||
void PSS_queue(int channel, SDL_RWops *rw, char *ext, object name, int fadein, int tight)
|
||||
void PSS_stop(int channel)
|
||||
void PSS_dequeue(int channel, int even_tight)
|
||||
int PSS_queue_depth(int channel)
|
||||
object PSS_playing_name(int channel)
|
||||
void PSS_fadeout(int channel, int ms)
|
||||
void PSS_pause(int channel, int pause)
|
||||
void PSS_unpause_all()
|
||||
int PSS_get_pos(int channel)
|
||||
void PSS_set_endevent(int channel, int event)
|
||||
void PSS_set_volume(int channel, float volume)
|
||||
float PSS_get_volume(int channel)
|
||||
void PSS_set_pan(int channel, float pan, float delay)
|
||||
void PSS_set_secondary_volume(int channel, float vol2, float delay)
|
||||
void PSS_init(int freq, int stereo, int samples, int status)
|
||||
void PSS_quit()
|
||||
|
||||
void PSS_periodic()
|
||||
void PSS_alloc_event(object)
|
||||
int PSS_refresh_event()
|
||||
|
||||
char *PSS_get_error()
|
||||
|
||||
int ffpy_needs_alloc
|
||||
int ffpy_movie_width
|
||||
int ffpy_movie_height
|
||||
|
||||
def check_error():
|
||||
e = PSS_get_error();
|
||||
|
||||
if str(e):
|
||||
raise Exception(e)
|
||||
|
||||
def play(channel, file, name, paused=False, fadein=0, tight=False):
|
||||
cdef SDL_RWops *rw
|
||||
|
||||
rw = RWopsFromPythonThreaded(file)
|
||||
|
||||
if rw == NULL:
|
||||
raise Exception, "Could not create RWops."
|
||||
|
||||
if paused:
|
||||
pause = 1
|
||||
else:
|
||||
pause = 0
|
||||
|
||||
if tight:
|
||||
tight = 1
|
||||
else:
|
||||
tight = 0
|
||||
|
||||
PSS_play(channel, rw, name, name, fadein, tight, pause)
|
||||
check_error()
|
||||
|
||||
def queue(channel, file, name, fadein=0, tight=False):
|
||||
cdef SDL_RWops *rw
|
||||
|
||||
rw = RWopsFromPythonThreaded(file)
|
||||
|
||||
if tight:
|
||||
tight = 1
|
||||
else:
|
||||
tight = 0
|
||||
|
||||
PSS_queue(channel, rw, name, name, fadein, tight)
|
||||
check_error()
|
||||
|
||||
def stop(channel):
|
||||
PSS_stop(channel)
|
||||
check_error()
|
||||
|
||||
def dequeue(channel, even_tight=False):
|
||||
PSS_dequeue(channel, even_tight)
|
||||
|
||||
def queue_depth(channel):
|
||||
return PSS_queue_depth(channel)
|
||||
|
||||
def playing_name(channel):
|
||||
return PSS_playing_name(channel)
|
||||
|
||||
def pause(channel):
|
||||
PSS_pause(channel, 1)
|
||||
check_error()
|
||||
|
||||
def unpause(channel):
|
||||
PSS_pause(channel, 0)
|
||||
check_error()
|
||||
|
||||
def unpause_all():
|
||||
PSS_unpause_all()
|
||||
|
||||
def fadeout(channel, ms):
|
||||
PSS_fadeout(channel, ms)
|
||||
check_error()
|
||||
|
||||
def busy(channel):
|
||||
return PSS_get_pos(channel) != -1
|
||||
|
||||
def get_pos(channel):
|
||||
return PSS_get_pos(channel)
|
||||
|
||||
def set_volume(channel, volume):
|
||||
if volume == 0:
|
||||
PSS_set_volume(channel, 0)
|
||||
else:
|
||||
PSS_set_volume(channel, 10 ** volume / 10 )
|
||||
|
||||
check_error()
|
||||
|
||||
def set_pan(channel, pan, delay):
|
||||
PSS_set_pan(channel, pan, delay)
|
||||
check_error()
|
||||
|
||||
def set_secondary_volume(channel, volume, delay):
|
||||
PSS_set_secondary_volume(channel, volume, delay)
|
||||
check_error()
|
||||
|
||||
def set_end_event(channel, event):
|
||||
PSS_set_endevent(channel, event)
|
||||
check_error()
|
||||
|
||||
def get_volume(channel):
|
||||
return PSS_get_volume(channel)
|
||||
|
||||
def init(freq, stereo, samples, status=False):
|
||||
if status:
|
||||
status = 1
|
||||
else:
|
||||
status = 0
|
||||
|
||||
PSS_init(freq, stereo, samples, status)
|
||||
check_error()
|
||||
|
||||
def quit(): # @ReservedAssignment
|
||||
PSS_quit()
|
||||
|
||||
def periodic():
|
||||
PSS_periodic()
|
||||
|
||||
def alloc_event(surf):
|
||||
PSS_alloc_event(surf)
|
||||
|
||||
def refresh_event():
|
||||
return PSS_refresh_event()
|
||||
|
||||
def needs_alloc():
|
||||
return ffpy_needs_alloc
|
||||
|
||||
def movie_size():
|
||||
return ffpy_movie_width, ffpy_movie_height
|
||||
|
||||
def check_version(version):
|
||||
if version < 2 or version > 4:
|
||||
raise Exception("pysdlsound version mismatch.")
|
||||
|
||||
import_pygame_rwobject()
|
||||
@@ -1,117 +0,0 @@
|
||||
#ifndef RENPY_H
|
||||
#define RENPY_H
|
||||
|
||||
#include <Python.h>
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
void core_init(void);
|
||||
|
||||
void save_png_core(PyObject *pysurf, SDL_RWops *file, int compress);
|
||||
|
||||
void pixellate32_core(PyObject *pysrc,
|
||||
PyObject *pydst,
|
||||
int avgwidth,
|
||||
int avgheight,
|
||||
int outwidth,
|
||||
int outheight);
|
||||
|
||||
void pixellate24_core(PyObject *pysrc,
|
||||
PyObject *pydst,
|
||||
int avgwidth,
|
||||
int avgheight,
|
||||
int outwidth,
|
||||
int outheight);
|
||||
|
||||
void map32_core(PyObject *pysrc,
|
||||
PyObject *pydst,
|
||||
char *rmap,
|
||||
char *gmap,
|
||||
char *bmap,
|
||||
char *amap);
|
||||
|
||||
void map24_core(PyObject *pysrc,
|
||||
PyObject *pydst,
|
||||
char *rmap,
|
||||
char *gmap,
|
||||
char *bmap);
|
||||
|
||||
void linmap32_core(PyObject *pysrc,
|
||||
PyObject *pydst,
|
||||
int rmap,
|
||||
int gmap,
|
||||
int bmap,
|
||||
int amap);
|
||||
|
||||
void linmap24_core(PyObject *pysrc,
|
||||
PyObject *pydst,
|
||||
int rmap,
|
||||
int gmap,
|
||||
int bmap);
|
||||
|
||||
#if 0
|
||||
|
||||
void xblur32_core(PyObject *pysrc,
|
||||
PyObject *pydst,
|
||||
int radius);
|
||||
|
||||
#endif
|
||||
|
||||
void alphamunge_core(PyObject *pysrc,
|
||||
PyObject *pydst,
|
||||
int src_bypp, // bytes per pixel.
|
||||
int src_aoff, // alpha offset.
|
||||
int dst_aoff, // alpha offset.
|
||||
char *amap);
|
||||
|
||||
/* int stretch_core(PyObject *pysrc, */
|
||||
/* PyObject *pydst, */
|
||||
/* int x, */
|
||||
/* int y, */
|
||||
/* int w, */
|
||||
/* int h); */
|
||||
|
||||
void scale32_core(PyObject *pysrc,
|
||||
PyObject *pydst,
|
||||
float, float, float, float,
|
||||
float, float, float, float,
|
||||
int);
|
||||
|
||||
void scale24_core(PyObject *pysrc,
|
||||
PyObject *pydst,
|
||||
float, float, float, float,
|
||||
float, float, float, float);
|
||||
|
||||
void transform32_core(PyObject *pysrc,
|
||||
PyObject *pydst,
|
||||
float, float,
|
||||
float, float,
|
||||
float, float,
|
||||
int, float, int);
|
||||
|
||||
void blend32_core(PyObject *pysrca,
|
||||
PyObject *pysrcb,
|
||||
PyObject *pydst,
|
||||
int alpha);
|
||||
|
||||
void imageblend32_core(PyObject *pysrca, PyObject *pysrcb,
|
||||
PyObject *pydst, PyObject *pyimg,
|
||||
int alpha, char *amap);
|
||||
|
||||
|
||||
void colormatrix32_core(PyObject *pysrc, PyObject *pydst,
|
||||
float c00, float c01, float c02, float c03, float c04,
|
||||
float c10, float c11, float c12, float c13, float c14,
|
||||
float c20, float c21, float c22, float c23, float c24,
|
||||
float c30, float c31, float c32, float c33, float c34);
|
||||
|
||||
void staticgray_core(
|
||||
PyObject *pysrc, PyObject *pydst,
|
||||
int rmul, int gmul, int bmul, int amul, int shift,
|
||||
char *vmap);
|
||||
|
||||
int subpixel32(
|
||||
PyObject *pysrc, PyObject *pydst,
|
||||
float xoffset, float yoffset, int ashift);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,42 +0,0 @@
|
||||
#include <Python.h>
|
||||
#include <fribidi/fribidi.h>
|
||||
|
||||
/* This is easier than trying to figure out the header that alloca is */
|
||||
/* defined in. */
|
||||
void *alloca(size_t size);
|
||||
|
||||
PyObject *renpybidi_log2vis(PyObject *s, int *direction) {
|
||||
char *src;
|
||||
int size;
|
||||
FriBidiChar *srcuni;
|
||||
int unisize;
|
||||
FriBidiChar *dstuni;
|
||||
char *dst;
|
||||
|
||||
src = PyString_AsString(s);
|
||||
|
||||
if (src == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size = PyString_Size(s);
|
||||
|
||||
srcuni = (FriBidiChar *) alloca(size * 4);
|
||||
dstuni = (FriBidiChar *) alloca(size * 4);
|
||||
dst = (char *) alloca(size * 4);
|
||||
|
||||
unisize = fribidi_charset_to_unicode(FRIBIDI_CHAR_SET_UTF8, src, size, srcuni);
|
||||
|
||||
fribidi_log2vis(
|
||||
srcuni,
|
||||
unisize,
|
||||
direction,
|
||||
dstuni,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
fribidi_unicode_to_charset(FRIBIDI_CHAR_SET_UTF8, dstuni, unisize, dst);
|
||||
|
||||
return PyString_FromString(dst);
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#ifndef RENPYBIDICORE_H
|
||||
#define RENPYBIDICORE_H
|
||||
#include <Python.h>
|
||||
|
||||
PyObject *renpybidi_log2vis(PyObject *s, int *direction);
|
||||
#endif
|
||||