Compare commits

...

16 Commits

Author SHA1 Message Date
Tom Rothamel 7e2e123af7 Bump version, update changelog. 2010-01-21 18:53:32 -05:00
Tom Rothamel 14aa4c4e3d Do not display ctc when interact=False. 2010-01-21 18:04:22 -05:00
Tom Rothamel 2c15237b8a Implement renpy.config.default_transform, but don't make it the default yet. 2010-01-21 16:54:10 -05:00
Tom Rothamel b4845252c1 Bump version. 2010-01-20 13:03:58 -05:00
Tom Rothamel 2f513235b3 The launcher now accepts a RENPY_DEFAULT_PROJECTS_DIRECTORY, which sets
the default for the projects directory, if it has not already been set 
by the user. It also will report an error when creating a project fails,
rather than producing a traceback.
2010-01-20 11:16:55 -05:00
Tom Rothamel c68b3bae89 The new voice_replay function replays the voice played on the current
interaction. The new voice_can_replay function returns True if a voice
can be replayed.
2010-01-20 01:01:24 -05:00
Tom Rothamel 3825e88883 Properly purge images from the image cache. 2010-01-20 00:10:20 -05:00
Tom Rothamel bbe0fdb98f It's now possible to assign style properties to individual imagemap
buttons, by indexing style.imagemap_button. (So for example, one could 
assign to style.imagemap_button["Start Game"].hover_sound .)
2010-01-18 22:46:56 -05:00
Tom Rothamel 009969dab5 Can't pop from a tuple. 2010-01-18 03:04:02 -05:00
Tom Rothamel 376ac7ad81 Add a link to the Ren'Py Games List to the launcher. 2010-01-17 17:07:38 -05:00
Tom Rothamel de8257f459 Ren'Py now builds zip files in distributions 64k at a time. 2010-01-14 22:03:14 -05:00
Tom Rothamel 3b0fbcc55f Previously, it was impossible to pass an arguments list to a call
expression. Now, we allow the pass keyword to be used to distinguish 
the two, using code like:

call expression foo pass (bar, baz)
2010-01-14 12:48:54 -05:00
Tom Rothamel e33abc05fb Prevent infinite looping when iterating over an object with
__getitem__ defined.
2010-01-14 11:37:59 -05:00
Tom Rothamel 430ee03d45 Bump version to 6.10.2b. 2010-01-14 00:12:46 -05:00
Tom Rothamel 03477d1c75 Fix lp:506322 - MoveTransition wouldn't work on the overlay layer, even if explicitly specified. 2010-01-13 23:20:15 -05:00
Tom Rothamel ef9ee657f7 Add cache_unpin 2010-01-12 23:48:57 -05:00
20 changed files with 292 additions and 61 deletions
+39 -1
View File
@@ -16,13 +16,49 @@ menu.
The new renpy.cache_pin function pins images into memory, loading them
as soon as possible and keeping them loaded.
as soon as possible and keeping them loaded. The renpy.cache_unpin function
undoes this.
The new config.automatic_images_strip variable can strip out prefixes
when automatically defining images.
It's now possible to assign style properties to individual imagemap
buttons, by indexing style.imagemap_button. (So for example, one could
assign to style.imagemap_button["Start Game"].hover_sound .)
The new voice_replay function replays the voice played on the current
interaction. The new voice_can_replay function returns True if a voice
can be replayed.
The launcher now accepts a RENPY_DEFAULT_PROJECTS_DIRECTORY, which sets
the default for the projects directory, if it has not already been set
by the user. It also will report an error when creating a project fails,
rather than producing a traceback.
The launcher now links to the new Ren'Py Games List, at
http://games.renpy.org/.
Previously, it was impossible to pass an arguments list to a call
expression. Now, we allow the pass keyword to be used to distinguish
the two, using code like:
call expression foo pass (bar, baz)
Ren'Py will now not show the click-to-continue indicator when a
character is called with interact=False, unless that character is also
called with ctc_force=True.
Ren'Py now builds zip files in distributions 64k at a time.
Ren'Py will now ignore music files that do not exist. Previously, it
could loop trying to play them. (This would increase CPU usage, rather
than causing a crash.)
@@ -31,11 +67,13 @@ than causing a crash.)
The following numbered bugs were fixed:
* lp:501351 - Displaying a Frame() with tile=True crashes
* lp:506322 - MoveTransition is not applied to overlay even when explicitly stated
In addition:
* Fixed a bug that caused pixellate to crash.
* Fixed a bug that caused the overlay to display twice in some cases.
* Fix an infinite loop that could rarely occur when rolling back or saving.
+15
View File
@@ -7,6 +7,10 @@
# definitions.
init -1110:
transform reset:
alpha 1 rotate None zoom 1 xzoom 1 yzoom 1 align (0, 0) alignaround (0, 0) subpixel False size None crop None
# These are positions that can be used inside at clauses. We set
# them up here so that they can be used throughout the program.
transform left:
@@ -30,6 +34,13 @@ init -1110:
transform offscreenright:
xpos 1.0 xanchor 0.0 ypos 1.0 yanchor 1.0
transform default:
reset
center
python:
config.default_transform = right
init -1110 python:
@@ -179,3 +190,7 @@ init 1110 python:
if not hasattr(store, 'centered'):
centered = Character(None, what_style="centered_text", window_style="centered_window")
# This is necessary to ensure that config.default_transform works.
if config.default_transform:
config.default_transform.show()
+1 -1
View File
@@ -795,7 +795,7 @@ init 1180 python hide:
while name:
for i in config.automatic_images_strip:
if name[0] == i:
name.pop(0)
name = name[1:]
break
else:
break
+14 -2
View File
@@ -30,15 +30,17 @@ init -1120:
_voice.play = None
_voice.sustain = False
_voice.seen_in_lint = False
# Call this to specify the voice file that will be played for
# the user.
def voice(file, **kwargs):
if not config.has_voice:
return
_voice.play = file
_last_voice_play = file
# Call this to specify that the currently playing voice file
# should be sustained through the current interaction.
def voice_sustain(ignored="", **kwargs):
@@ -47,6 +49,14 @@ init -1120:
_voice.sustain = True
# Call this to replay the last bit of voice.
def voice_replay():
renpy.sound.play(_last_voice_play, channel=2)
# Returns true if we can replay the voice.
def voice_can_replay():
return _last_voice_play != None
python hide:
# basics: True if the game will have voice.
@@ -61,8 +71,10 @@ init -1120:
if _voice.play and not config.skipping:
renpy.sound.play(_voice.play, channel=2)
store._last_voice_play = _voice.play
elif not _voice.sustain:
renpy.sound.stop(channel=2)
store._last_voice_play = _voice.play
_voice.play = None
_voice.sustain = False
+78 -4
View File
@@ -7,9 +7,12 @@ init python:
import tarfile
import time
import sys
import struct
import zlib
zlib.Z_DEFAULT_COMPRESSION = 9
import binascii
import pefile
# These are files that are ignored wherever they are found in a
@@ -147,7 +150,7 @@ init python:
fn = os.path.join(os.path.dirname(project.path), filename)
zf = zipfile.ZipFile(fn + ".zip", "w", zipfile.ZIP_DEFLATED)
zf = MyZipFile(fn + ".zip", "w", zipfile.ZIP_DEFLATED)
for i, (fn, an) in enumerate(files):
@@ -172,10 +175,9 @@ init python:
if fn in file_data:
data = file_data[fn]
zf.writestr(zi, data)
else:
data = file(fn, "rb").read()
zf.writestr(zi, data)
zf.write_file_with_zipinfo(fn, zi)
zf.close()
@@ -552,3 +554,75 @@ label distribute:
interact()
init python:
class MyZipFile(zipfile.ZipFile):
"""
Modified ZipFile class that can insert a file into the archive,
using a supplied ZipInfo object. Code comes from the writestr
and write methods of ZipFile.
"""
def write_file_with_zipinfo(self, filename, zinfo, compress_type=None):
"""Put the bytes from filename into the archive under the name
arcname."""
st = os.stat(filename)
if compress_type is None:
zinfo.compress_type = self.compression
else:
zinfo.compress_type = compress_type
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
fp = open(filename, "rb")
# 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 * 64)
if not buf:
break
file_size = file_size + len(buf)
CRC = binascii.crc32(buf, CRC)
if cmpr:
buf = cmpr.compress(buf)
compress_size = compress_size + len(buf)
self.fp.write(buf)
fp.close()
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
+5 -2
View File
@@ -29,9 +29,12 @@ label new_project:
_(u"Please wait while we create the project."))
template = os.path.join(config.renpy_base, "template")
shutil.copytree(template, path)
try:
shutil.copytree(template, path)
except OSError, e:
error(_(u"Could not create the project directory. The error was: %s") % unicode(e))
launcherinfo = os.path.join(path, "launcherinfo.py")
if os.path.exists(launcherinfo):
os.unlink(launcherinfo)
+2 -1
View File
@@ -26,7 +26,8 @@ label choose_projects_directory:
if path is None:
path = os.path.dirname(config.renpy_base)
path = os.environ.get("RENPY_DEFAULT_PROJECTS_DIRECTORY", path)
if EasyDialogs:
+15 -2
View File
@@ -68,7 +68,7 @@ label top:
title(_(u"Ren'Py"))
ui.grid(2, 3, transpose=True)
ui.grid(2, 4, transpose=True)
button(_(u"Select Project"),
ui.jumps("select_project"),
@@ -78,6 +78,10 @@ label top:
ui.jumps("new_project"),
_(u"Create a new project."))
button(_(u"Ren'Py Games List"),
ui.jumps("renpy_games_list"),
_(u"Visit the Ren'Py games list, at http://games.renpy.org."))
button(_(u"Quit"),
renpy.quit,
_(u"Causes the launcher to exit."))
@@ -99,7 +103,8 @@ label top:
else:
ui.null()
ui.null()
ui.close()
@@ -121,6 +126,14 @@ label documentation:
jump top
label renpy_games_list:
python hide:
import webbrowser
webbrowser.open_new("http://games.renpy.org")
set_tooltip(_(u"Now showing the Ren'Py Games List in your web browser."))
jump top
label confirm_quit:
$ renpy.quit()
+7 -4
View File
@@ -33,14 +33,14 @@ init python:
u"Test",
u"Left",
u"Right",
u"Not Assigned",
u"Up",
u"Down",
u"Not Assigned",
u"Select/Dismiss",
u"Rollback",
u"Hold to Skip",
u"Joystick Mapping",
u"Move the joystick or press a joystick button to create the mapping. Click the mouse to remove the mapping.",
u"Rollback",
u"Hold to Skip",
u"Toggle Skip",
u"Hide Text",
u"Menu",
@@ -177,7 +177,9 @@ init python:
u"Choose Projects Directory",
u"Please choose the directory containing your projects.",
u"Could not run zenity. The projects directory has been set to the directory immediately above the directory containing Ren'Py.",
u"Launches the Ren'Py tutorial game.",
u"Now showing the Ren'Py documentation in your web browser.",
u"Now showing the Ren'Py Games List in your web browser.",
u"Launch",
u"Launches the project.",
u"Edit Script",
@@ -195,12 +197,13 @@ init python:
u"Ren'Py",
u"Select a project to work with.",
u"Create a new project.",
u"Ren'Py Games List",
u"Visit the Ren'Py games list, at http://games.renpy.org.",
u"Causes the launcher to exit.",
u"Options",
u"Change Ren'Py launcher options.",
u"Ren'Py Help",
u"Open the Ren'Py documentation in a web browser.",
u"Tutorial Game",
u"Launches the Ren'Py tutorial game.",
]
+1 -1
View File
@@ -27,7 +27,7 @@
# ***** ***** ***** ***** ***** ***** **** ***** ***** ***** *****
# Be sure to change script_version in launcher/script_version.rpy, too!
# Also check to see if we have to update renpy.py.
version = "Ren'Py 6.10.2a"
version = "Ren'Py 6.10.2d"
script_version = 5003000
savegame_suffix = "-LT1.save"
+5 -1
View File
@@ -215,7 +215,8 @@ def display_say(show_function,
callback,
type,
checkpoint=True,
ctc_timedpause=None):
ctc_timedpause=None,
ctc_force=False):
# If we're in fast skipping mode, don't bother with say
@@ -296,6 +297,9 @@ def display_say(show_function,
what_ctc = ctc_pause
else:
what_ctc = ctc
if not (interact or ctc_force):
what_ctc = None
what_ctc = renpy.easy.displayable_or_none(what_ctc)
+4
View File
@@ -1,3 +1,4 @@
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
@@ -408,6 +409,9 @@ thumbnail_height = None
# The end game transition.
end_game_transition = None
# The default transform.
default_transform = None
# Various directories.
gamedir = None
basedir = None
+6 -1
View File
@@ -531,6 +531,9 @@ class SceneLists(renpy.object.Object):
to the new thing.
"""
if old_thing is None:
return new_thing
old_transform = old_thing.get_parameterized()
if not isinstance(old_transform, renpy.display.motion.Transform):
return new_thing
@@ -543,7 +546,7 @@ class SceneLists(renpy.object.Object):
return new_thing
def add(self, layer, thing, key=None, zorder=0, behind=[ ], at_list=[ ], name=None, atl=None):
def add(self, layer, thing, key=None, zorder=0, behind=[ ], at_list=[ ], name=None, atl=None, default_transform=None):
"""
This is called to add something to a layer. Layer is
the name of the layer that we need to add the thing to,
@@ -632,6 +635,8 @@ class SceneLists(renpy.object.Object):
else:
index = len(l)
thing = self.transform_state(default_transform, thing)
thing.set_transform_event("show")
thing.show()
l.insert(index, (key, zorder, st, at, thing))
+53 -33
View File
@@ -1,3 +1,4 @@
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
@@ -80,9 +81,6 @@ class Cache(object):
# Is the preload_thread alive?
self.keep_preloading = True
# A list of images that want to be pinned into memory.
self.global_pins = [ ]
# A map from image object to surface, only for objects that have
# been pinned into memory.
self.pin_cache = { }
@@ -156,20 +154,6 @@ class Cache(object):
return
self.preloads.append(image)
# Called to report that a given image would like to be pinned into memory.
def pin_image(self, image):
if renpy.config.debug_image_cache:
print "IC Request Pin", image
if not isinstance(image, ImageBase):
if renpy.config.debug_image_cache:
print "IC Can't pin non image: ", image
else:
return
if image not in self.global_pins:
self.global_pins.append(image)
# This returns the pygame surface corresponding to the provided
# image. It also takes care of updating the age of images in the
@@ -348,7 +332,7 @@ class Cache(object):
def preload_thread_main(self):
while self.keep_preloading:
self.lock.acquire()
self.lock.wait()
self.lock.release()
@@ -371,7 +355,14 @@ class Cache(object):
try:
image = self.preloads.pop(0)
self.get(image)
if image not in preload_blacklist:
try:
self.get(image)
except:
preload_blacklist.add(image)
except:
pass
@@ -382,12 +373,33 @@ class Cache(object):
# If we have time, preload pinned images.
if self.keep_preloading and not renpy.game.less_memory:
# Compute the pin worklist.
pin_worklist = [ i for i in self.global_pins if i not in self.pin_cache ]
workset = set(renpy.store._cache_pin_set)
# Remove things that are not in the workset from the pin cache,
# and remove things that are in the workset from pin cache.
for i in self.pin_cache.keys():
if i in workset:
workset.remove(i)
else:
if renpy.config.debug_image_cache:
print "IC Pin Clear", image
idsurf = id(self.pin_cache[i])
if idsurf in pin_rle_cache:
del pin_rle_cache[idsurf]
del self.pin_cache[i]
# For each image in the worklist...
for image in pin_worklist:
for image in workset:
if image in preload_blacklist:
continue
# If we have normal preloads, break out.
if self.preloads:
break
@@ -396,24 +408,32 @@ class Cache(object):
if renpy.config.debug_image_cache:
print "IC Pin Preload", image
surf = image.load()
try:
surf = image.load()
self.pin_cache[image] = surf
rle_surf = renpy.display.pgrender.copy_surface(surf)
rle_surf.set_alpha(255, pygame.RLEACCEL)
pin_rle_cache[id(surf)] = rle_surf
except:
preload_blacklist.add(image)
self.pin_cache[image] = surf
rle_surf = renpy.display.pgrender.copy_surface(surf)
rle_surf.set_alpha(255, pygame.RLEACCEL)
pin_rle_cache[id(surf)] = rle_surf
cache = Cache()
# A map from id(cached surface) to rle version of cached surface.
rle_cache = { }
# Same thing, for pinned surfaces.
pin_rle_cache = { }
# Images that we tried, and failed, to preload.
preload_blacklist = set()
cache = Cache()
def free_memory():
"""
Frees some memory.
+2 -3
View File
@@ -961,9 +961,8 @@ def MoveTransition(delay, old_widget=None, new_widget=None, factory=None, enter
if (isinstance(f, renpy.display.layout.MultiBox)
and layer in layers
and f.scene_list is not None
and layer not in renpy.config.overlay_layers):
and f.scene_list is not None):
f = merge_slide(old.layers[layer], new.layers[layer])
rv.layers[layer] = f
+31 -2
View File
@@ -235,7 +235,7 @@ def show(name, at_list=[ ], layer='master', what=None, zorder=0, tag=None, behin
if renpy.config.missing_hide:
renpy.config.missing_hide(name, layer)
sls.add(layer, img, key, zorder, behind, at_list=at_list, name=name, atl=atl)
sls.add(layer, img, key, zorder, behind, at_list=at_list, name=name, atl=atl, default_transform=renpy.config.default_transform)
def hide(name, layer='master'):
@@ -1278,8 +1278,37 @@ def get_roll_forward():
return renpy.game.interface.shown_window
def cache_pin(*args):
new_pins = renpy.python.RevertableSet()
for i in args:
renpy.display.im.cache.pin_image(renpy.easy.displayable(i))
im = renpy.easy.displayable(i)
if not isinstance(im, renpy.display.im.ImageBase):
raise Exception("Cannot pin non-image-manipulator %r" % im)
new_pins.add(im)
renpy.store._cache_pin_set = new_pins | renpy.store._cache_pin_set
def cache_unpin(*args):
new_pins = renpy.python.RevertableSet()
for i in args:
im = renpy.easy.displayable(i)
if not isinstance(im, renpy.display.im.ImageBase):
raise Exception("Cannot unpin non-image-manipulator %r" % im)
new_pins.add(im)
renpy.store._cache_pin_set = renpy.store._cache_pin_set - new_pins
# This is a map from a definition to the place where it was
+5
View File
@@ -1425,10 +1425,15 @@ def parse_statement(l):
if l.keyword('expression'):
expression = True
target = l.require(l.simple_expression)
else:
expression = False
target = l.require(l.name)
# Optional pass, to let someone write:
# call expression foo pass (bar, baz)
l.keyword('pass')
arguments = parse_arguments(l)
rv = [ ast.Call(loc, target, expression, arguments) ]
+2 -2
View File
@@ -72,9 +72,9 @@ def reached(obj, reachable, wait):
pass
try:
# Treat as iterable
# Treat as iterable
if not isinstance(obj, basestring):
for v in obj:
for v in obj.__iter__():
reached(v, reachable, wait)
except:
pass
+2
View File
@@ -298,6 +298,8 @@ def say(who, what, interact=True):
_last_say_who = None
_last_say_what = None
# Used to store the things pinned into the cache.
_cache_pin_set = set()
__name__ = 'store'
+5 -1
View File
@@ -62,6 +62,7 @@ def interact(type='misc', **kwargs):
if current_stack:
raise Exception("ui.interact called with non-empty widget/layer stack. Did you forget a ui.close() somewhere?")
if at_stack:
raise Exception("ui.interact called with non-empty at stack.")
@@ -326,6 +327,9 @@ def imagemap(ground,
button_style='imagemap_button',
**properties):
if isinstance(button_style, basestring):
button_style = getattr(renpy.game.style, button_style)
rv = fixed(style=style, **properties)
if unselected is None:
@@ -341,7 +345,7 @@ def imagemap(ground,
imagebutton(renpy.display.layout.LiveCrop((x0, y0, x1 - x0, y1 - y0), unselected),
renpy.display.layout.LiveCrop((x0, y0, x1 - x0, y1 - y0), selected),
clicked=returns(result),
style=button_style,
style=button_style[result],
xpos=x0,
xanchor=0,
ypos=y0,