Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 71ba444e62 | |||
| 3e0baee463 | |||
| a0064f5511 | |||
| e7ce23f377 | |||
| 9c6d93968c | |||
| e4b29d58f4 | |||
| a48b87a0d6 | |||
| 763515a937 | |||
| 46a8242e51 | |||
| efa8d66d3d | |||
| b7c71bb3b8 | |||
| aca5438b5a | |||
| e7eb23ab5e | |||
| 05dd8bfcc7 | |||
| 2c299ab079 | |||
| 62acff5c75 | |||
| 316d146893 | |||
| e69fee2108 | |||
| 8fe6e1cf20 | |||
| 6fcf7dbbba | |||
| f55c5f0ce5 | |||
| aaf8369421 | |||
| 8e26c7730c | |||
| 556ca0611a | |||
| e2e78c175b | |||
| 7b8033e6b2 | |||
| d602645fee |
@@ -35,8 +35,8 @@ init -1110:
|
||||
xpos 1.0 xanchor 0.0 ypos 1.0 yanchor 1.0
|
||||
|
||||
transform default:
|
||||
reset
|
||||
center
|
||||
alpha 1 rotate None zoom 1 xzoom 1 yzoom 1 align (0, 0) alignaround (0, 0) subpixel False size None crop None
|
||||
xpos 0.5 xanchor 0.5 ypos 1.0 yanchor 1.0
|
||||
|
||||
python:
|
||||
config.default_transform = default
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
# Copyright 2004-2010 PyTom <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
# This file contains code to perform the OpenGL test. This is always
|
||||
# run - even in software mode - so that the user experience remains
|
||||
# consistent. (But it terminates early in sw-mode.)
|
||||
|
||||
init -1024 python:
|
||||
# The image that we fill the screen with in GL-test mode.
|
||||
config.gl_test_image = "black"
|
||||
|
||||
class __GLTest(renpy.Displayable):
|
||||
"""
|
||||
This counts the number of times it's been rendered, and
|
||||
the number of seconds it's been displayed, and uses them
|
||||
to make the decisions as to if OpenGL is working or not.
|
||||
"""
|
||||
|
||||
def __init__(self, frames, timeout):
|
||||
super(__GLTest, self).__init__()
|
||||
|
||||
self.frames = frames
|
||||
self.timeout = timeout
|
||||
|
||||
def render(self, width, height, st, at):
|
||||
self.frames -= 1
|
||||
|
||||
if self.frames <= 0:
|
||||
renpy.timeout(0)
|
||||
|
||||
renpy.redraw(self, 0)
|
||||
|
||||
rv = renpy.Render(width, height)
|
||||
return rv
|
||||
|
||||
|
||||
def event(self, ev, x, y, st):
|
||||
st = st
|
||||
|
||||
if self.frames <= 0:
|
||||
return True
|
||||
|
||||
if st > self.timeout:
|
||||
return False
|
||||
|
||||
renpy.timeout(self.timeout - st)
|
||||
|
||||
label _gl_test:
|
||||
|
||||
# Show the test image.
|
||||
show expression config.gl_test_image
|
||||
|
||||
python hide:
|
||||
|
||||
# If GL is able to render FRAMES in DELAY seconds, we consider it to
|
||||
# be operational, and continue in GL mode. Otherwise, we rever to
|
||||
# software rendering mode.
|
||||
FRAMES = 4
|
||||
DELAY = .25
|
||||
|
||||
import os
|
||||
|
||||
if (not "RENPY_RENDERER" in os.environ) and (renpy.get_renderer_info()["renderer"] == "gl"):
|
||||
|
||||
renpy.pause(0)
|
||||
|
||||
renpy.transition(Dissolve(DELAY))
|
||||
ui.add(__GLTest(FRAMES, DELAY))
|
||||
rv = ui.interact(suppress_overlay=True, suppress_underlay=False)
|
||||
|
||||
if not rv:
|
||||
config.gl_enable = False
|
||||
renpy.display_reset()
|
||||
|
||||
# Hide the test image.
|
||||
scene
|
||||
|
||||
return
|
||||
|
||||
+44
-1
@@ -386,5 +386,48 @@ init -1105 python hide:
|
||||
layout.QUIT = u"Are you sure you want to quit?"
|
||||
layout.MAIN_MENU = u"Are you sure you want to return to the main menu?\nThis will lose unsaved progress."
|
||||
|
||||
@layout
|
||||
def yesno_screen(message, yes=None, no=None):
|
||||
"""
|
||||
:doc: other
|
||||
|
||||
|
||||
This causes the a yes/no prompt screen with the given message
|
||||
to be displayed. The screen will be hidden when the user hits
|
||||
yes or no.
|
||||
|
||||
`message`
|
||||
The message that will be displayed.
|
||||
|
||||
`yes`
|
||||
An action that is run when the user chooses yes.
|
||||
|
||||
`no`
|
||||
An action that is run when the user chooses no.
|
||||
"""
|
||||
|
||||
|
||||
if renpy.has_screen("yesno_prompt"):
|
||||
|
||||
yes_action = [ Hide("yesno_prompt") ]
|
||||
no_action = [ Hide("yesno_prompt") ]
|
||||
|
||||
if yes is not None:
|
||||
yes_action.append(yes)
|
||||
if no is not None:
|
||||
no_action.append(no)
|
||||
|
||||
renpy.display.show_screen(
|
||||
"yesno_prompt",
|
||||
message=message,
|
||||
yes_action=yes_action,
|
||||
no_action=no_action)
|
||||
|
||||
return
|
||||
|
||||
if renpy.invoke_in_new_context(layout.yesno_prompt, None, message):
|
||||
if yes is not None:
|
||||
yes()
|
||||
else:
|
||||
if no is not None:
|
||||
no()
|
||||
|
||||
|
||||
@@ -562,7 +562,7 @@ label _enter_menu:
|
||||
renpy.context()._menu = True
|
||||
|
||||
# This may be changed, if we are already in the main menu.
|
||||
renpy.context().main_menu = False
|
||||
renpy.context()._main_menu = False
|
||||
renpy.context_dynamic("main_menu")
|
||||
renpy.context_dynamic("_window_subtitle")
|
||||
renpy.context_dynamic("_window")
|
||||
@@ -651,7 +651,7 @@ label _noisy_return:
|
||||
# Return to the game.
|
||||
label _return:
|
||||
|
||||
if renpy.context().main_menu:
|
||||
if renpy.context()._main_menu:
|
||||
$ renpy.transition(config.game_main_transition)
|
||||
jump _main_menu_screen
|
||||
|
||||
@@ -685,6 +685,7 @@ init -1180 python hide:
|
||||
# after_load.
|
||||
label _after_load:
|
||||
$ renpy.context()._menu = False
|
||||
$ renpy.context()._main_menu = False
|
||||
|
||||
if config.after_load_transition:
|
||||
$ renpy.transition(config.after_load_transition, force=True)
|
||||
@@ -705,7 +706,9 @@ label _start:
|
||||
|
||||
for i in config.start_callbacks:
|
||||
i()
|
||||
|
||||
|
||||
call _gl_test
|
||||
|
||||
call _load_reload_game from _call__load_reload_game_1
|
||||
|
||||
if not _restart and config.auto_load and renpy.can_load(config.auto_load):
|
||||
@@ -777,7 +780,7 @@ label _main_menu(_main_menu_screen="_main_menu_screen"):
|
||||
renpy.dynamic("_load_prompt")
|
||||
_load_prompt = False
|
||||
|
||||
renpy.context().main_menu = True
|
||||
renpy.context()._main_menu = True
|
||||
store.main_menu = True
|
||||
|
||||
jump expression _main_menu_screen
|
||||
|
||||
+6
-30
@@ -2,30 +2,6 @@
|
||||
|
||||
init -1140 python:
|
||||
|
||||
def __yesno_prompt(message, yes=None, no=None):
|
||||
if renpy.has_screen("yesno_prompt"):
|
||||
|
||||
yes_action = [ Hide("yesno_prompt") ]
|
||||
no_action = [ Hide("yesno_prompt") ]
|
||||
|
||||
if yes is not None:
|
||||
yes_action.append(yes)
|
||||
if no is not None:
|
||||
no_action.append(no)
|
||||
|
||||
renpy.display.show_screen(
|
||||
"yesno_prompt",
|
||||
message=message,
|
||||
yes_action=yes_action,
|
||||
no_action=no_action)
|
||||
|
||||
if renpy.invoke_in_new_context(layout.yesno_prompt, None, message):
|
||||
if yes is not None:
|
||||
yes()
|
||||
else:
|
||||
if no is not None:
|
||||
no()
|
||||
|
||||
class Return(Action):
|
||||
"""
|
||||
:doc: control_action
|
||||
@@ -262,7 +238,7 @@ init -1140 python:
|
||||
return
|
||||
|
||||
if self.confirm:
|
||||
__yesno_prompt(layout.MAIN_MENU, MainMenu(False))
|
||||
layout.yesno_screen(layout.MAIN_MENU, MainMenu(False))
|
||||
else:
|
||||
renpy.full_restart()
|
||||
|
||||
@@ -283,12 +259,12 @@ init -1140 python:
|
||||
"""
|
||||
|
||||
def __init__(self, confirm=True):
|
||||
self.confirm = True
|
||||
self.confirm = confirm
|
||||
|
||||
def __call__(self):
|
||||
|
||||
if self.confirm:
|
||||
__yesno_prompt(layout.QUIT, Quit(False))
|
||||
layout.yesno_screen(layout.QUIT, Quit(False))
|
||||
else:
|
||||
renpy.quit()
|
||||
|
||||
@@ -914,7 +890,7 @@ init -1140 python:
|
||||
|
||||
if renpy.scan_saved_game(fn):
|
||||
if self.confirm:
|
||||
__yesno_prompt(layout.OVERWRITE_SAVE, FileSave(self.name, False, self.newest, self.page))
|
||||
layout.yesno_screen(layout.OVERWRITE_SAVE, FileSave(self.name, False, self.newest, self.page))
|
||||
return
|
||||
|
||||
renpy.save(fn, extra_info=save_name)
|
||||
@@ -959,7 +935,7 @@ init -1140 python:
|
||||
|
||||
if not renpy.context()._main_menu:
|
||||
if self.confirm:
|
||||
__yesno_prompt(layout.LOADING, FileLoad(self.name, False, self.page))
|
||||
layout.yesno_screen(layout.LOADING, FileLoad(self.name, False, self.page))
|
||||
return
|
||||
|
||||
renpy.load(fn)
|
||||
@@ -993,7 +969,7 @@ init -1140 python:
|
||||
fn = __filename(self.name, self.page)
|
||||
|
||||
if self.confirm:
|
||||
__yesno_prompt(layout.DELETE_SAVE, FileDelete(self.name, False, self.page))
|
||||
layout.yesno_screen(layout.DELETE_SAVE, FileDelete(self.name, False, self.page))
|
||||
return
|
||||
|
||||
renpy.unlink_save(fn)
|
||||
|
||||
+8
-3
@@ -22,10 +22,14 @@ init -1200 python hide:
|
||||
# Style Declarations #################################################
|
||||
|
||||
style.default = Style(None, help='root of style hierarchy')
|
||||
style.text = Style(style.default, help='style of text')
|
||||
|
||||
style.fixed = Style(style.default, help='fixed layouts')
|
||||
style.hbox = Style(style.default, help='horizontal boxes')
|
||||
style.vbox = Style(style.default, help='vertical boxes')
|
||||
|
||||
style.grid = Style(style.default, help='grid layouts')
|
||||
style.side = Style(style.default, help='side layouts')
|
||||
|
||||
style.window = Style(style.default, help='windows created with ui.window')
|
||||
|
||||
style.image_placement = Style(style.default, help='default placement of images on the screen')
|
||||
@@ -50,7 +54,8 @@ init -1200 python hide:
|
||||
style.menu_choice_chosen_button = Style(style.menu_choice_button, help='buttons containing chosen in-game menu choices')
|
||||
style.menu_window = Style(style.window, help='a window containing a menu')
|
||||
|
||||
style.input_text = Style(style.default, help='text of an input box')
|
||||
style.input = Style(style.default, help='style of an input control')
|
||||
style.input_text = Style(style.input, help='text of an input box')
|
||||
style.input_prompt = Style(style.default, help='prompt of an input box')
|
||||
style.input_window = Style(style.window, help='window of an input box')
|
||||
|
||||
@@ -235,7 +240,7 @@ init -1090 python:
|
||||
# Menus.
|
||||
style.menu_choice.idle_color = "#0ff"
|
||||
style.menu_choice.hover_color = "#ff0"
|
||||
style.input_text.color = "#ff0"
|
||||
style.input.color = "#ff0"
|
||||
|
||||
# Styles used by centered.
|
||||
style.centered_window.xalign = 0.5
|
||||
|
||||
@@ -8,7 +8,7 @@ label _developer_screen:
|
||||
ui.window(style=style.gm_root)
|
||||
ui.null()
|
||||
|
||||
ui.frame(xpos=10, ypos=10, style=style.menu_frame)
|
||||
ui.frame(xalign=.025, yalign=.05, style=style.menu_frame)
|
||||
ui.vbox(box_first_spacing=10)
|
||||
layout.label(u"Developer Menu", None)
|
||||
|
||||
@@ -92,7 +92,7 @@ label _theme_test:
|
||||
return ""
|
||||
|
||||
toggle_var = True
|
||||
adj = ui.adjustment(100, 25, page=25)
|
||||
adj = ui.adjustment(100, 25, page=25, adjustable=True)
|
||||
|
||||
while True:
|
||||
|
||||
|
||||
@@ -100,6 +100,9 @@ init -1 python hide:
|
||||
## Set this to False if the game does not have any sound effects.
|
||||
config.sound = False
|
||||
|
||||
# Disable opengl.
|
||||
config.gl_enable = False
|
||||
|
||||
python early:
|
||||
config.save_directory = "launcher-2"
|
||||
|
||||
|
||||
+1
-1
@@ -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.11.0c"
|
||||
version = "Ren'Py 6.11.0e"
|
||||
script_version = 5003000
|
||||
savegame_suffix = "-LT1.save"
|
||||
|
||||
|
||||
+6
-5
@@ -29,7 +29,6 @@
|
||||
import renpy
|
||||
import re
|
||||
import time
|
||||
import weakref
|
||||
|
||||
# Called to set the state of a Node, when necessary.
|
||||
def setstate(node, state):
|
||||
@@ -103,7 +102,6 @@ class PyCode(object):
|
||||
'location',
|
||||
'mode',
|
||||
'bytecode',
|
||||
'__weakref__',
|
||||
]
|
||||
|
||||
def __getstate__(self):
|
||||
@@ -112,8 +110,10 @@ class PyCode(object):
|
||||
def __setstate__(self, state):
|
||||
(_, self.source, self.location, self.mode) = state
|
||||
self.bytecode = None
|
||||
renpy.game.script.all_pycode.append(weakref.ref(self))
|
||||
|
||||
|
||||
if renpy.game.script.record_pycode:
|
||||
renpy.game.script.all_pycode.append(self)
|
||||
|
||||
def __init__(self, source, loc=('<none>', 1), mode='exec'):
|
||||
|
||||
if isinstance(source, PyExpr):
|
||||
@@ -130,7 +130,8 @@ class PyCode(object):
|
||||
# This will be initialized later on, after we are serialized.
|
||||
self.bytecode = None
|
||||
|
||||
renpy.game.script.all_pycode.append(weakref.ref(self))
|
||||
if renpy.game.script.record_pycode:
|
||||
renpy.game.script.all_pycode.append(self)
|
||||
|
||||
def chain_block(block, next):
|
||||
"""
|
||||
|
||||
@@ -847,6 +847,12 @@ class Interpolation(Statement):
|
||||
# between the new and old states.
|
||||
linear = trans.state.diff(newts)
|
||||
|
||||
# Ensure that we set things, even if they don't actually
|
||||
# change from the old state.
|
||||
for k, v in self.properties:
|
||||
if k not in linear:
|
||||
setattr(trans.state, k, v)
|
||||
|
||||
revolution = None
|
||||
splines = [ ]
|
||||
|
||||
@@ -906,6 +912,7 @@ class Interpolation(Statement):
|
||||
# Linearly interpolate between the things in linear.
|
||||
for k, (old, new) in linear.iteritems():
|
||||
value = interpolate(complete, old, new, PROPERTIES[k])
|
||||
|
||||
setattr(trans.state, k, value)
|
||||
|
||||
# Handle the revolution.
|
||||
|
||||
+25
-12
@@ -813,7 +813,24 @@ def rollback():
|
||||
|
||||
ALLOC_EVENT = pygame.USEREVENT
|
||||
REFRESH_EVENT = pygame.USEREVENT + 1
|
||||
|
||||
|
||||
# The last surface we allocated.
|
||||
last_alloc_surface = None
|
||||
|
||||
def alloc_surface(force):
|
||||
|
||||
global last_alloc_surface
|
||||
|
||||
if renpy.display.video.fullscreen and renpy.display.draw.fullscreen_surface:
|
||||
surf = renpy.display.draw.fullscreen_surface
|
||||
else:
|
||||
surf = renpy.display.video.surface
|
||||
|
||||
if (surf is not last_alloc_surface) or force:
|
||||
last_alloc_surface = surf
|
||||
pss.alloc_event(surf)
|
||||
|
||||
def event(ev):
|
||||
"""
|
||||
Handles an event generated by pss (really, the ffdecode
|
||||
@@ -824,24 +841,20 @@ def event(ev):
|
||||
if not pcm_ok:
|
||||
return False
|
||||
|
||||
|
||||
if renpy.display.video.fullscreen or not renpy.display.video.surface:
|
||||
surf = renpy.display.draw.fullscreen_surface
|
||||
else:
|
||||
surf = renpy.display.video.surface
|
||||
|
||||
if ev.type == ALLOC_EVENT:
|
||||
pss.alloc_event(surf)
|
||||
|
||||
alloc_surface(True)
|
||||
|
||||
return True
|
||||
|
||||
if ev.type == REFRESH_EVENT:
|
||||
elif ev.type == REFRESH_EVENT:
|
||||
|
||||
alloc_surface(False)
|
||||
|
||||
if renpy.audio.music.get_playing("movie"):
|
||||
pss.refresh_event()
|
||||
|
||||
renpy.display.draw.mutated_surface(surf)
|
||||
|
||||
if surf is renpy.display.draw.fullscreen_surface:
|
||||
renpy.game.interface.force_redraw = True
|
||||
renpy.game.interface.force_redraw = True
|
||||
|
||||
# Return False, as a Movie should get this to know when to
|
||||
# redraw itself.
|
||||
|
||||
+58
-55
@@ -239,69 +239,72 @@ def bootstrap(renpy_base):
|
||||
keep_running = True
|
||||
report_error = None
|
||||
|
||||
while keep_running:
|
||||
try:
|
||||
renpy.game.options = options
|
||||
try:
|
||||
while keep_running:
|
||||
try:
|
||||
renpy.game.options = options
|
||||
|
||||
renpy.config.renpy_base = renpy_base
|
||||
renpy.config.basedir = basedir
|
||||
renpy.config.gamedir = gamedir
|
||||
renpy.config.args = options.args
|
||||
|
||||
renpy.main.main()
|
||||
keep_running = False
|
||||
renpy.config.renpy_base = renpy_base
|
||||
renpy.config.basedir = basedir
|
||||
renpy.config.gamedir = gamedir
|
||||
renpy.config.args = options.args
|
||||
|
||||
except KeyboardInterrupt:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
break
|
||||
|
||||
except renpy.game.UtterRestartException:
|
||||
|
||||
if renpy.display.draw:
|
||||
renpy.display.draw.deinit()
|
||||
|
||||
# Only works after a full restart.
|
||||
report_error = renpy.display.error.ReportError()
|
||||
|
||||
# On an UtterRestart, reload Ren'Py.
|
||||
renpy.reload_all()
|
||||
continue
|
||||
|
||||
except renpy.game.ParseErrorException:
|
||||
|
||||
if report_error and report_error.report('a parse error'):
|
||||
renpy.reload_all()
|
||||
keep_running = True
|
||||
else:
|
||||
renpy.main.main()
|
||||
keep_running = False
|
||||
|
||||
except KeyboardInterrupt:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
break
|
||||
|
||||
except renpy.game.UtterRestartException:
|
||||
|
||||
if renpy.display.draw:
|
||||
renpy.display.draw.deinit()
|
||||
|
||||
# Only works after a full restart.
|
||||
report_error = renpy.display.error.ReportError()
|
||||
|
||||
# On an UtterRestart, reload Ren'Py.
|
||||
renpy.reload_all()
|
||||
continue
|
||||
|
||||
except renpy.game.ParseErrorException:
|
||||
|
||||
if report_error and report_error.report('a parse error'):
|
||||
renpy.reload_all()
|
||||
keep_running = True
|
||||
else:
|
||||
keep_running = False
|
||||
|
||||
except Exception, e:
|
||||
report_exception(e)
|
||||
|
||||
if report_error and report_error.report('an exception'):
|
||||
renpy.reload_all()
|
||||
keep_running = True
|
||||
else:
|
||||
keep_running = False
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
finally:
|
||||
|
||||
except Exception, e:
|
||||
report_exception(e)
|
||||
if "RENPY_SHUTDOWN_TRACE" in os.environ:
|
||||
enable_trace(int(os.environ["RENPY_SHUTDOWN_TRACE"]))
|
||||
|
||||
if report_error and report_error.report('an exception'):
|
||||
renpy.reload_all()
|
||||
keep_running = True
|
||||
else:
|
||||
keep_running = False
|
||||
renpy.display.im.cache.quit()
|
||||
|
||||
if "RENPY_SHUTDOWN_TRACE" in os.environ:
|
||||
enable_trace(int(os.environ["RENPY_SHUTDOWN_TRACE"]))
|
||||
|
||||
if options.leak:
|
||||
memory_profile()
|
||||
if renpy.display.draw:
|
||||
renpy.display.draw.quit()
|
||||
|
||||
renpy.display.im.cache.quit()
|
||||
|
||||
if renpy.display.draw:
|
||||
renpy.display.draw.quit()
|
||||
# Prevent subprocess from throwing errors while trying to run it's
|
||||
# __del__ method during shutdown.
|
||||
import subprocess # W0403
|
||||
subprocess.Popen.__del__ = popen_del # E1101
|
||||
|
||||
# Prevent subprocess from throwing errors while trying to run it's
|
||||
# __del__ method during shutdown.
|
||||
import subprocess # W0403
|
||||
subprocess.Popen.__del__ = popen_del # E1101
|
||||
|
||||
sys.exit(0)
|
||||
if options.leak:
|
||||
memory_profile()
|
||||
|
||||
|
||||
def report_tb(out, tb):
|
||||
|
||||
@@ -431,6 +431,9 @@ gamedir = None
|
||||
basedir = None
|
||||
renpy_base = None
|
||||
|
||||
# Should we enable OpenGL mode?
|
||||
gl_enable = True
|
||||
|
||||
del renpy
|
||||
|
||||
def init():
|
||||
|
||||
@@ -615,7 +615,7 @@ class Input(renpy.display.text.Text):
|
||||
def __init__(self,
|
||||
default="",
|
||||
length=None,
|
||||
style='input_text',
|
||||
style='input',
|
||||
allow=None,
|
||||
exclude=None,
|
||||
prefix="",
|
||||
|
||||
@@ -1221,6 +1221,11 @@ class Interface(object):
|
||||
This sets the video mode. It also picks the draw object.
|
||||
"""
|
||||
|
||||
if self.display_reset:
|
||||
renpy.display.draw.deinit()
|
||||
renpy.display.draw.quit()
|
||||
renpy.display.draw = None
|
||||
|
||||
self.display_reset = False
|
||||
|
||||
# Ensure that we kill off the movie when changing screen res.
|
||||
@@ -1272,6 +1277,8 @@ class Interface(object):
|
||||
|
||||
def draw_screen(self, root_widget, fullscreen_video):
|
||||
|
||||
|
||||
|
||||
surftree = renpy.display.render.render_screen(
|
||||
root_widget,
|
||||
renpy.config.screen_width,
|
||||
|
||||
+30
-14
@@ -80,9 +80,6 @@ class GLDraw(object):
|
||||
# This is used to cache the surface->texture operation.
|
||||
self.texture_cache = weakref.WeakKeyDictionary()
|
||||
|
||||
# This is a fullscreen surface used for video playback.
|
||||
self.fullscreen_surface = None
|
||||
|
||||
# The time of the last redraw.
|
||||
self.last_redraw_time = 0
|
||||
|
||||
@@ -91,7 +88,9 @@ class GLDraw(object):
|
||||
|
||||
# Old value of fullscreen.
|
||||
self.old_fullscreen = None
|
||||
|
||||
|
||||
# We don't use a fullscreen surface.
|
||||
self.fullscreen_surface = None
|
||||
|
||||
def log(self, msg, *args):
|
||||
"""
|
||||
@@ -114,6 +113,10 @@ class GLDraw(object):
|
||||
# If GL can't be loaded, give up.
|
||||
if not gl:
|
||||
return False
|
||||
|
||||
if not renpy.config.gl_enable:
|
||||
self.log("GL Disabled.")
|
||||
return False
|
||||
|
||||
if self.did_init:
|
||||
self.deinit()
|
||||
@@ -201,9 +204,6 @@ class GLDraw(object):
|
||||
self.environ.init()
|
||||
self.rtt.init()
|
||||
|
||||
# Allocate a fullscreen surface for video playback.
|
||||
self.fullscreen_surface = renpy.display.pgrender.surface(self.virtual_size, False)
|
||||
|
||||
# Prepare a mouse call.
|
||||
self.mouse_old_visible = None
|
||||
|
||||
@@ -228,7 +228,11 @@ class GLDraw(object):
|
||||
self.environ.deinit()
|
||||
|
||||
def quit(self):
|
||||
|
||||
|
||||
self.log("Deallocating textures.")
|
||||
gltexture.dealloc_textures()
|
||||
self.log("Done deallocating textures.")
|
||||
|
||||
self.log("About to quit GL.")
|
||||
pygame.display.quit()
|
||||
self.log("Finished quit GL.")
|
||||
@@ -241,12 +245,15 @@ class GLDraw(object):
|
||||
|
||||
# Init glew.
|
||||
pysdlgl.init_glew()
|
||||
|
||||
|
||||
renderer = pysdlgl.get_string(gl.RENDERER)
|
||||
|
||||
# Log the GL version.
|
||||
self.log("Vendor: %r", pysdlgl.get_string(gl.VENDOR))
|
||||
self.log("Renderer: %r", pysdlgl.get_string(gl.RENDERER))
|
||||
self.log("Renderer: %r", renderer)
|
||||
self.log("Version: %r", pysdlgl.get_string(gl.VERSION))
|
||||
|
||||
self.log("Video Info: %s", pygame.display.Info())
|
||||
|
||||
extensions = set(pysdlgl.get_string(gl.EXTENSIONS).split(" "))
|
||||
|
||||
self.log("Extensions:")
|
||||
@@ -340,7 +347,14 @@ class GLDraw(object):
|
||||
self.log("Using copy RTT.")
|
||||
self.rtt = glenviron.CopyRtt()
|
||||
self.info["rtt"] = "copy"
|
||||
|
||||
|
||||
# Check for ctrl held down at startup - revert to software
|
||||
# rendering if that's the case.
|
||||
|
||||
if pygame.key.get_mods() & pygame.KMOD_SHIFT:
|
||||
self.log("Giving up on OpenGL, because SHIFT is held down.")
|
||||
return False
|
||||
|
||||
# Do additional setup needed.
|
||||
|
||||
renpy.display.pgrender.set_bgra_masks()
|
||||
@@ -351,7 +365,7 @@ class GLDraw(object):
|
||||
def should_redraw(self, needs_redraw, first_pass):
|
||||
"""
|
||||
Redraw whenever the screen needs it, but at least once every
|
||||
1/20 seconds. We rely on VSYNC to slow down our maximum
|
||||
.2 seconds. We rely on VSYNC to slow down our maximum
|
||||
draw speed.
|
||||
"""
|
||||
|
||||
@@ -449,7 +463,9 @@ class GLDraw(object):
|
||||
self.undefine_clip()
|
||||
|
||||
if renpy.audio.music.get_playing("movie") and renpy.display.video.fullscreen:
|
||||
tex = self.load_texture(self.fullscreen_surface, transient=True)
|
||||
tex = renpy.display.video.get_movie_texture(self.virtual_size)
|
||||
|
||||
# self.load_texture(self.fullscreen_surface, transient=True)
|
||||
self.draw_transformed(tex, clip, 0, 0, 1.0, forward, reverse)
|
||||
else:
|
||||
self.draw_transformed(surftree, clip, 0, 0, 1.0, forward, reverse)
|
||||
|
||||
@@ -393,12 +393,9 @@ class ShaderEnviron(object):
|
||||
|
||||
if self.last != IMAGEBLEND:
|
||||
gl.UseProgramObjectARB(self.imageblend_program)
|
||||
|
||||
# Permute the texture units so they match the way the
|
||||
# fixed-function system uses them.
|
||||
gl.Uniform1iARB(self.imageblend_tex0_uniform, 1)
|
||||
gl.Uniform1iARB(self.imageblend_tex1_uniform, 2)
|
||||
gl.Uniform1iARB(self.imageblend_tex2_uniform, 0)
|
||||
gl.Uniform1iARB(self.imageblend_tex0_uniform, 0)
|
||||
gl.Uniform1iARB(self.imageblend_tex1_uniform, 1)
|
||||
gl.Uniform1iARB(self.imageblend_tex2_uniform, 2)
|
||||
|
||||
self.last = IMAGEBLEND
|
||||
|
||||
|
||||
@@ -80,9 +80,9 @@ void main()
|
||||
vec4 color1 = texture2D(tex1, gl_TexCoord[1].st);
|
||||
vec4 color2 = texture2D(tex2, gl_TexCoord[2].st);
|
||||
|
||||
float a = clamp((color2.a + offset) * multiplier, 0.0, 1.0);
|
||||
float a = clamp((color0.a + offset) * multiplier, 0.0, 1.0);
|
||||
|
||||
gl_FragColor = mix(color0, color1, a) * gl_Color;
|
||||
gl_FragColor = mix(color1, color2, a) * gl_Color;
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
+148
-4
@@ -751,11 +751,11 @@ def imageblend(tg0, tg1, tg2, sx, sy, transform, alpha, fraction, ramp, environ)
|
||||
x = 0
|
||||
|
||||
for (t0x, t0w, t0ci), (t1x, t1w, t1ci), (t2x, t2w, t2ci) in zip(cols0, cols1, cols2):
|
||||
|
||||
|
||||
t0 = tg0.tiles[t0ri][t0ci]
|
||||
t1 = tg1.tiles[t1ri][t1ci]
|
||||
t2 = tg2.tiles[t2ri][t2ci]
|
||||
|
||||
|
||||
pysdlgl.draw_rectangle(
|
||||
sx, sy,
|
||||
x, y,
|
||||
@@ -764,9 +764,153 @@ def imageblend(tg0, tg1, tg2, sx, sy, transform, alpha, fraction, ramp, environ)
|
||||
t0, t0x, t0y,
|
||||
t1, t1x, t1y,
|
||||
t2, t2x, t2y)
|
||||
|
||||
|
||||
x += t0w
|
||||
|
||||
|
||||
y += t0h
|
||||
|
||||
|
||||
def draw_rectangle(
|
||||
sx,
|
||||
sy,
|
||||
x,
|
||||
y,
|
||||
w,
|
||||
h,
|
||||
transform,
|
||||
tex0, tex0x, tex0y,
|
||||
tex1, tex1x, tex1y,
|
||||
tex2, tex2x, tex2y):
|
||||
|
||||
"""
|
||||
This draws a rectangle (textured with up to four textures) to the
|
||||
screen.
|
||||
"""
|
||||
|
||||
# Pull apart the transform.
|
||||
xdx = transform.xdx
|
||||
xdy = transform.xdy
|
||||
ydx = transform.ydx
|
||||
ydy = transform.ydy
|
||||
|
||||
# Transform the vertex coordinates to screen-space.
|
||||
x0 = (x + 0) * xdx + (y + 0) * xdy + sx
|
||||
y0 = (x + 0) * ydx + (y + 0) * ydy + sy
|
||||
|
||||
x1 = (x + w) * xdx + (y + 0) * xdy + sx
|
||||
y1 = (x + w) * ydx + (y + 0) * ydy + sy
|
||||
|
||||
x2 = (x + 0) * xdx + (y + h) * xdy + sx
|
||||
y2 = (x + 0) * ydx + (y + h) * ydy + sy
|
||||
|
||||
x3 = (x + w) * xdx + (y + h) * xdy + sx
|
||||
y3 = (x + w) * ydx + (y + h) * ydy + sy
|
||||
|
||||
# Compute the texture coordinates, and set up the textures.
|
||||
|
||||
if tex0 is not None:
|
||||
|
||||
has_tex0 = 1
|
||||
|
||||
gl.ActiveTextureARB(gl.TEXTURE0_ARB)
|
||||
gl.BindTexture(gl.TEXTURE_2D, tex0.number)
|
||||
|
||||
xadd = tex0.xadd
|
||||
yadd = tex0.yadd
|
||||
xmul = tex0.xmul
|
||||
ymul = tex0.ymul
|
||||
|
||||
t0u0 = xadd + xmul * (tex0x + 0)
|
||||
t0u1 = xadd + xmul * (tex0x + w)
|
||||
t0v0 = yadd + ymul * (tex0y + 0)
|
||||
t0v1 = yadd + ymul * (tex0y + h)
|
||||
|
||||
else:
|
||||
has_tex0 = 0
|
||||
|
||||
if tex1 is not None:
|
||||
|
||||
has_tex1 = 1
|
||||
|
||||
gl.ActiveTextureARB(gl.TEXTURE1_ARB)
|
||||
gl.BindTexture(gl.TEXTURE_2D, tex1.number)
|
||||
|
||||
xadd = tex1.xadd
|
||||
yadd = tex1.yadd
|
||||
xmul = tex1.xmul
|
||||
ymul = tex1.ymul
|
||||
|
||||
t1u0 = xadd + xmul * (tex1x + 0)
|
||||
t1u1 = xadd + xmul * (tex1x + w)
|
||||
t1v0 = yadd + ymul * (tex1y + 0)
|
||||
t1v1 = yadd + ymul * (tex1y + h)
|
||||
|
||||
else:
|
||||
has_tex1 = 0
|
||||
|
||||
if tex2 is not None:
|
||||
|
||||
has_tex2 = 1
|
||||
|
||||
gl.ActiveTextureARB(gl.TEXTURE2_ARB)
|
||||
gl.BindTexture(gl.TEXTURE_2D, tex2.number)
|
||||
|
||||
xadd = tex2.xadd
|
||||
yadd = tex2.yadd
|
||||
xmul = tex2.xmul
|
||||
ymul = tex2.ymul
|
||||
|
||||
t2u0 = xadd + xmul * (tex2x + 0)
|
||||
t2u1 = xadd + xmul * (tex2x + w)
|
||||
t2v0 = yadd + ymul * (tex2y + 0)
|
||||
t2v1 = yadd + ymul * (tex2y + h)
|
||||
|
||||
else:
|
||||
has_tex2 = 0
|
||||
|
||||
# Now, actually draw the textured rectangle.
|
||||
|
||||
gl.Begin(gl.TRIANGLE_STRIP)
|
||||
|
||||
if has_tex0:
|
||||
gl.MultiTexCoord2fARB(gl.TEXTURE0_ARB, t0u0, t0v0)
|
||||
if has_tex1:
|
||||
gl.MultiTexCoord2fARB(gl.TEXTURE1_ARB, t1u0, t1v0)
|
||||
if has_tex2:
|
||||
gl.MultiTexCoord2fARB(gl.TEXTURE2_ARB, t2u0, t2v0)
|
||||
gl.Vertex2f(x0, y0)
|
||||
|
||||
if has_tex0:
|
||||
gl.MultiTexCoord2fARB(gl.TEXTURE0_ARB, t0u1, t0v0)
|
||||
if has_tex1:
|
||||
gl.MultiTexCoord2fARB(gl.TEXTURE1_ARB, t1u1, t1v0)
|
||||
if has_tex2:
|
||||
gl.MultiTexCoord2fARB(gl.TEXTURE2_ARB, t2u1, t2v0)
|
||||
gl.Vertex2f(x1, y1)
|
||||
|
||||
if has_tex0:
|
||||
gl.MultiTexCoord2fARB(gl.TEXTURE0_ARB, t0u0, t0v1)
|
||||
if has_tex1:
|
||||
gl.MultiTexCoord2fARB(gl.TEXTURE1_ARB, t1u0, t1v1)
|
||||
if has_tex2:
|
||||
gl.MultiTexCoord2fARB(gl.TEXTURE2_ARB, t2u0, t2v1)
|
||||
gl.Vertex2f(x2, y2)
|
||||
|
||||
if has_tex0:
|
||||
gl.MultiTexCoord2fARB(gl.TEXTURE0_ARB, t0u1, t0v1)
|
||||
if has_tex1:
|
||||
gl.MultiTexCoord2fARB(gl.TEXTURE1_ARB, t1u1, t1v1)
|
||||
if has_tex2:
|
||||
gl.MultiTexCoord2fARB(gl.TEXTURE2_ARB, t2u1, t2v1)
|
||||
gl.Vertex2f(x3, y3)
|
||||
|
||||
gl.End()
|
||||
|
||||
|
||||
C_DRAW=True
|
||||
|
||||
if C_DRAW:
|
||||
if pysdlgl:
|
||||
draw_rectangle = pysdlgl.draw_rectangle
|
||||
else:
|
||||
print "Warning: Draw not using C code."
|
||||
|
||||
@@ -307,7 +307,7 @@ class Grid(Container):
|
||||
|
||||
def __init__(self, cols, rows, padding=None,
|
||||
transpose=False,
|
||||
style='default', **properties):
|
||||
style='grid', **properties):
|
||||
"""
|
||||
@param cols: The number of columns in this widget.
|
||||
|
||||
@@ -1138,7 +1138,7 @@ class Side(Container):
|
||||
def after_setstate(self):
|
||||
self.sized = False
|
||||
|
||||
def __init__(self, positions, style='default', **properties):
|
||||
def __init__(self, positions, style='side', **properties):
|
||||
|
||||
super(Side, self).__init__(style=style, **properties)
|
||||
|
||||
|
||||
@@ -176,7 +176,7 @@ class TransformState(renpy.object.Object):
|
||||
else:
|
||||
old_value = old
|
||||
|
||||
if new_value != new or new_value != old_value:
|
||||
if new_value != old_value:
|
||||
rv[prop] = (old_value, new_value)
|
||||
|
||||
diff2("alpha", newts.alpha, self.alpha)
|
||||
@@ -199,6 +199,7 @@ class TransformState(renpy.object.Object):
|
||||
diff2("size", newts.size, self.size)
|
||||
|
||||
diff4("xpos", newts.xpos, newts.default_xpos, self.xpos, self.default_xpos)
|
||||
|
||||
diff4("xanchor", newts.xanchor, newts.default_xanchor, self.xanchor, self.default_xanchor)
|
||||
diff2("xoffset", newts.xoffset, self.xoffset)
|
||||
|
||||
@@ -382,6 +383,8 @@ class Transform(Container):
|
||||
xoffset = Proxy("xoffset")
|
||||
yoffset = Proxy("yoffset")
|
||||
offset = Proxy("offset")
|
||||
|
||||
subpixel = Proxy("subpixel")
|
||||
|
||||
def after_upgrade(self, version):
|
||||
|
||||
|
||||
@@ -137,8 +137,12 @@ def render(d, width, height, st, at):
|
||||
rv = render_cache[d].get(wh, None)
|
||||
if rv is not None:
|
||||
return rv
|
||||
|
||||
|
||||
rv = d.render(width, height, st, at)
|
||||
|
||||
if rv is None:
|
||||
print d.style.parent, d.style, d.style.box_layout, d.style.name
|
||||
|
||||
rv.render_of.append(d)
|
||||
|
||||
if style.clipping:
|
||||
|
||||
@@ -225,7 +225,6 @@ class Clipper(object):
|
||||
|
||||
updates.append((ix0, iy0, ix1 - ix0, iy1 - iy0))
|
||||
|
||||
|
||||
return (x0, y0, x1 - x0, y1 - y0), updates
|
||||
|
||||
clippers = [ Clipper() ]
|
||||
@@ -918,10 +917,8 @@ class SWDraw(object):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def mutated_surface(self, surf):
|
||||
"""
|
||||
Called to indicate that the given surface has changed.
|
||||
@@ -964,6 +961,12 @@ class SWDraw(object):
|
||||
|
||||
rle_cache.clear()
|
||||
|
||||
def deinit(self):
|
||||
"""
|
||||
Called when we're restarted.
|
||||
"""
|
||||
|
||||
return
|
||||
|
||||
def quit(self):
|
||||
"""
|
||||
|
||||
@@ -139,8 +139,8 @@ class TextStyle(object):
|
||||
return rv
|
||||
|
||||
def sizes(self, text):
|
||||
|
||||
return self.get_width(text), self.f.get_ascent() - self.f.get_descent()
|
||||
height = max(self.f.get_ascent() - self.f.get_descent(), self.f.get_height())
|
||||
return self.get_width(text), height
|
||||
|
||||
def render(self, text, antialias, color, black_color, use_colors, time, at, expand, use_cache):
|
||||
|
||||
@@ -1316,7 +1316,7 @@ class Text(renpy.display.core.Displayable):
|
||||
length = sys.maxint
|
||||
self.call_slow_done(st)
|
||||
|
||||
final_width = self.laidout_width - mindsx + maxdsx
|
||||
final_width = self.laidout_width - mindsx + maxdsx + max(self.style.first_indent, self.style.rest_indent)
|
||||
final_height = self.laidout_height - mindsy + maxdsy
|
||||
|
||||
rv = renpy.display.render.Render(final_width, final_height)
|
||||
|
||||
@@ -413,7 +413,7 @@ class ImageDissolve(Transition):
|
||||
image = render(self.image, width, height, st, at)
|
||||
bottom = render(self.old_widget, width, height, st, at)
|
||||
top = render(self.new_widget, width, height, st, at)
|
||||
|
||||
|
||||
width = min(bottom.width, top.width, image.width)
|
||||
height = min(bottom.height, top.height, image.height)
|
||||
|
||||
|
||||
+30
-19
@@ -34,7 +34,6 @@ surface_file = None
|
||||
# The surface to display the movie on, if not fullscreen.
|
||||
surface = None
|
||||
|
||||
|
||||
def movie_stop(clear=True, only_fullscreen=False):
|
||||
"""
|
||||
Stops the currently playing movie.
|
||||
@@ -68,7 +67,7 @@ def movie_start(filename, size=None, loops=0):
|
||||
filename = filename * (loops + 1)
|
||||
|
||||
renpy.audio.music.play(filename, channel='movie', loop=loop)
|
||||
|
||||
|
||||
movie_start_fullscreen = movie_start
|
||||
movie_start_displayable = movie_start
|
||||
|
||||
@@ -81,7 +80,6 @@ def early_interact():
|
||||
global fullscreen
|
||||
fullscreen = True
|
||||
|
||||
|
||||
def interact():
|
||||
"""
|
||||
This is called each time the screen is redrawn. It helps us decide if
|
||||
@@ -93,44 +91,57 @@ def interact():
|
||||
else:
|
||||
return False
|
||||
|
||||
def get_movie_texture(size):
|
||||
"""
|
||||
Gets a movie texture we can draw to the screen.
|
||||
"""
|
||||
|
||||
global surface
|
||||
global surface_file
|
||||
|
||||
playing = renpy.audio.music.get_playing("movie")
|
||||
|
||||
if (surface is None) or (surface.get_size() != size) or (surface_file != playing):
|
||||
surface = renpy.display.pgrender.surface(size, False)
|
||||
surface_file = playing
|
||||
surface.fill((0, 0, 0, 255))
|
||||
|
||||
tex = None
|
||||
|
||||
if playing is not None:
|
||||
renpy.display.render.mutated_surface(surface)
|
||||
tex = renpy.display.draw.load_texture(surface)
|
||||
|
||||
return tex
|
||||
|
||||
|
||||
class Movie(renpy.display.core.Displayable):
|
||||
"""
|
||||
This is a displayable that shows the current movie.
|
||||
"""
|
||||
|
||||
fullscreen = False
|
||||
|
||||
def __init__(self, fps=24, size=None, **properties):
|
||||
"""
|
||||
@param fps: The framerate that the movie should be shown at.
|
||||
"""
|
||||
super(Movie, self).__init__(**properties)
|
||||
self.size = size
|
||||
|
||||
|
||||
def render(self, width, height, st, at):
|
||||
|
||||
global surface
|
||||
global surface_file
|
||||
|
||||
size = self.size
|
||||
|
||||
if size is None:
|
||||
size = default_size
|
||||
|
||||
playing = renpy.audio.music.get_playing("movie")
|
||||
|
||||
if (surface is None) or (surface.get_size() != size) or (surface_file != playing):
|
||||
surface = renpy.display.pgrender.surface(size, False)
|
||||
surface_file = playing
|
||||
surface.fill((0, 0, 0, 255))
|
||||
|
||||
width, height = size
|
||||
rv = renpy.display.render.Render(width, height)
|
||||
|
||||
if playing is not None:
|
||||
renpy.display.render.mutated_surface(surface)
|
||||
tex = renpy.display.draw.load_texture(surface)
|
||||
rv = renpy.display.render.Render(width, height, opaque=True)
|
||||
|
||||
tex = get_movie_texture(size)
|
||||
|
||||
if tex is not None:
|
||||
rv.blit(tex, (0, 0))
|
||||
|
||||
return rv
|
||||
|
||||
+8
-1
@@ -1365,7 +1365,7 @@ def call_screen(_screen_name, **kwargs):
|
||||
rv = None
|
||||
|
||||
try:
|
||||
rv = renpy.ui.interact(roll_forward=roll_forward)
|
||||
rv = renpy.ui.interact(mouse="screen", type="screen", roll_forward=roll_forward)
|
||||
return rv
|
||||
|
||||
finally:
|
||||
@@ -1417,3 +1417,10 @@ def get_renderer_info():
|
||||
|
||||
return renpy.display.draw.info
|
||||
|
||||
def display_reset():
|
||||
"""
|
||||
Used internally. Causes the display to be restarted at the start of
|
||||
the next interaction.
|
||||
"""
|
||||
|
||||
renpy.display.interface.display_reset = True
|
||||
|
||||
+4
-4
@@ -610,7 +610,7 @@ class Lexer(object):
|
||||
return self.word_cache
|
||||
|
||||
self.word_cache_pos = self.pos
|
||||
rv = self.match(ur'[a-zA-Z_\u00a0-\ufffd\$][0-9a-zA-Z_\u00a0-\ufffd\$]*')
|
||||
rv = self.match(ur'[a-zA-Z_\u00a0-\ufffd][0-9a-zA-Z_\u00a0-\ufffd]*')
|
||||
self.word_cache = rv
|
||||
self.word_cache_newpos = self.pos
|
||||
|
||||
@@ -829,7 +829,7 @@ class Lexer(object):
|
||||
passed to revert to back the lexer up.
|
||||
"""
|
||||
|
||||
return self.filename, self.number, self.text, self.subblock, self.pos
|
||||
return self.line, self.filename, self.number, self.text, self.subblock, self.pos
|
||||
|
||||
def revert(self, state):
|
||||
"""
|
||||
@@ -837,7 +837,7 @@ class Lexer(object):
|
||||
by a previous checkpoint operation on this lexer.
|
||||
"""
|
||||
|
||||
self.filename, self.number, self.text, self.subblock, self.pos = state
|
||||
self.line, self.filename, self.number, self.text, self.subblock, self.pos = state
|
||||
self.word_cache_pos = -1
|
||||
|
||||
def get_location(self):
|
||||
@@ -1321,7 +1321,7 @@ class ParseTrie(object):
|
||||
def parse(self, l):
|
||||
old_pos = l.pos
|
||||
|
||||
word = l.word()
|
||||
word = l.word() or l.match(r'\$')
|
||||
|
||||
if not word in self.words:
|
||||
l.pos = old_pos
|
||||
|
||||
+10
-6
@@ -164,7 +164,7 @@ def set_filename(filename, offset, tree):
|
||||
worklist.extend(node.getChildNodes())
|
||||
|
||||
|
||||
def make_unicode(m):
|
||||
def unicode_sub(m):
|
||||
"""
|
||||
If the string s contains a unicode character, make it into a
|
||||
unicode string.
|
||||
@@ -188,6 +188,13 @@ def make_unicode(m):
|
||||
|
||||
string_re = re.compile(r'([uU]?[rR]?)("""|"|\'\'\'|\')((\\.|.)*?)\2')
|
||||
|
||||
def escape_unicode(s):
|
||||
s = s.encode("raw_unicode_escape")
|
||||
|
||||
if "\\u" in s:
|
||||
s = string_re.sub(unicode_sub, s)
|
||||
|
||||
return s
|
||||
|
||||
def py_compile(source, mode, filename='<none>', lineno=1):
|
||||
"""
|
||||
@@ -195,7 +202,7 @@ def py_compile(source, mode, filename='<none>', lineno=1):
|
||||
Lists, List Comprehensions, and Dictionaries are wrapped when
|
||||
appropriate.
|
||||
|
||||
@param source: The sourccode, as a string.
|
||||
@param source: The source code, as a string.
|
||||
|
||||
@param mode: 'exec' or 'eval'.
|
||||
|
||||
@@ -212,10 +219,7 @@ def py_compile(source, mode, filename='<none>', lineno=1):
|
||||
lineno = source.linenumber
|
||||
|
||||
source = source.replace("\r", "")
|
||||
source = source.encode('raw_unicode_escape')
|
||||
|
||||
if "\\u" in source:
|
||||
source = string_re.sub(make_unicode, source)
|
||||
source = escape_unicode(source)
|
||||
|
||||
try:
|
||||
line_offset = lineno - 1
|
||||
|
||||
+81
-21
@@ -152,15 +152,22 @@ class Parser(object):
|
||||
elif isinstance(i, Parser):
|
||||
self.children[i.name] = i
|
||||
|
||||
def parse_statement(self, l, name):
|
||||
word = l.word()
|
||||
def parse_statement(self, l, name, layout_mode=False):
|
||||
word = l.word() or l.match(r'\$')
|
||||
|
||||
if word and word in self.children:
|
||||
c = self.children[word].parse(l, name)
|
||||
if layout_mode:
|
||||
c = self.children[word].parse_layout(l, name)
|
||||
else:
|
||||
c = self.children[word].parse(l, name)
|
||||
|
||||
return c
|
||||
else:
|
||||
return None
|
||||
|
||||
def parse_layout(self, l, name):
|
||||
l.error("The %s statement cannot be used as a container for the has statement." % self.name)
|
||||
|
||||
def parse_children(self, stmt, l, name):
|
||||
l.expect_block(stmt)
|
||||
|
||||
@@ -195,6 +202,9 @@ class Parser(object):
|
||||
and expr instances, and adjusts the line number.
|
||||
"""
|
||||
|
||||
if isinstance(expr, unicode):
|
||||
expr = renpy.python.escape_unicode(expr)
|
||||
|
||||
try:
|
||||
rv = ast.parse(expr, 'eval').body[0].value
|
||||
except SyntaxError, e:
|
||||
@@ -215,12 +225,13 @@ class Parser(object):
|
||||
adjusts the line number. Returns a list of statements.
|
||||
"""
|
||||
|
||||
if isinstance(code, unicode):
|
||||
code = renpy.python.escape_unicode(code)
|
||||
|
||||
try:
|
||||
rv = ast.parse(code, 'exec')
|
||||
except SyntaxError, e:
|
||||
|
||||
print repr(e)
|
||||
|
||||
raise renpy.parser.ParseError(
|
||||
filename,
|
||||
lineno + e[1][1] - 1,
|
||||
@@ -281,8 +292,11 @@ class FunctionStatementParser(Parser):
|
||||
|
||||
if nchildren != 0:
|
||||
childbearing_statements.append(self)
|
||||
|
||||
def parse_layout(self, l, name):
|
||||
return self.parse(l, name, True)
|
||||
|
||||
def parse(self, l, name):
|
||||
def parse(self, l, name, layout_mode=False):
|
||||
|
||||
# The list of nodes this function returns.
|
||||
rv = [ ]
|
||||
@@ -290,6 +304,9 @@ class FunctionStatementParser(Parser):
|
||||
# The line number of the current node.
|
||||
lineno = l.number
|
||||
|
||||
if layout_mode and self.nchildren is not many:
|
||||
l.error("The %s statement cannot be used as a layout." % self.name)
|
||||
|
||||
func = self.parse_eval(self.function, lineno)
|
||||
|
||||
call_node = ast.Call(
|
||||
@@ -303,14 +320,14 @@ class FunctionStatementParser(Parser):
|
||||
)
|
||||
|
||||
seen_keywords = set()
|
||||
|
||||
|
||||
# Parses a keyword argument from the lexer.
|
||||
def parse_keyword(l):
|
||||
name = l.word()
|
||||
|
||||
if name is None:
|
||||
l.error('expected a keyword argument, colon, or end of line.')
|
||||
|
||||
|
||||
if name not in self.keyword:
|
||||
l.error('%r is not a keyword argument or valid child for the %s statement.' % (name, self.name))
|
||||
|
||||
@@ -351,22 +368,49 @@ class FunctionStatementParser(Parser):
|
||||
if self.nchildren == 1:
|
||||
rv.extend(self.parse_exec('ui.child_or_fixed()'))
|
||||
|
||||
needs_close = (self.nchildren != 0)
|
||||
|
||||
# The index of the child we're adding to this statement.
|
||||
child_index = 0
|
||||
|
||||
# The variable we store the child's name in.
|
||||
with new_variable() as child_name:
|
||||
|
||||
|
||||
old_l = l
|
||||
|
||||
# If we have a block, then parse each line.
|
||||
if block:
|
||||
|
||||
l = l.subblock_lexer()
|
||||
|
||||
|
||||
while l.advance():
|
||||
|
||||
state = l.checkpoint()
|
||||
|
||||
if l.keyword(r'has'):
|
||||
if self.nchildren != 1:
|
||||
l.error("The %s statement does not take a layout." % self.name)
|
||||
|
||||
if child_index != 0:
|
||||
l.error("The has statement may not be given after a child has been supplied.")
|
||||
|
||||
c = self.parse_statement(l, child_name, layout_mode=True)
|
||||
|
||||
if c is None:
|
||||
l.error('Has expects a child statement.')
|
||||
|
||||
# Remove the call to child_or_fixed.
|
||||
rv.pop()
|
||||
|
||||
rv.extend(self.parse_exec("%s = (%s, %d)" % (child_name, name, child_index)))
|
||||
rv.extend(c)
|
||||
|
||||
needs_close = False
|
||||
|
||||
continue
|
||||
|
||||
c = self.parse_statement(l, child_name)
|
||||
|
||||
if c is not None:
|
||||
|
||||
rv.extend(self.parse_exec("%s = (%s, %d)" % (child_name, name, child_index)))
|
||||
@@ -381,7 +425,24 @@ class FunctionStatementParser(Parser):
|
||||
while not l.eol():
|
||||
parse_keyword(l)
|
||||
|
||||
if self.nchildren != 0:
|
||||
l = old_l
|
||||
|
||||
if layout_mode:
|
||||
|
||||
while l.advance():
|
||||
c = self.parse_statement(l, child_name)
|
||||
|
||||
if c is not None:
|
||||
|
||||
rv.extend(self.parse_exec("%s = (%s, %d)" % (child_name, name, child_index)))
|
||||
rv.extend(c)
|
||||
|
||||
child_index += 1
|
||||
|
||||
else:
|
||||
l.error("Expected a screen language statement.")
|
||||
|
||||
if needs_close:
|
||||
rv.extend(self.parse_exec("ui.close()"))
|
||||
|
||||
if "id" not in seen_keywords:
|
||||
@@ -416,6 +477,8 @@ position_properties = [ Style(i) for i in [
|
||||
"ymaximum",
|
||||
"area",
|
||||
"clipping",
|
||||
"xfill",
|
||||
"yfill",
|
||||
] ]
|
||||
|
||||
text_properties = [ Style(i) for i in [
|
||||
@@ -447,8 +510,6 @@ text_properties = [ Style(i) for i in [
|
||||
"ymaximum",
|
||||
"xminimum",
|
||||
"yminimum",
|
||||
"xfill",
|
||||
"yfill",
|
||||
] ]
|
||||
|
||||
window_properties = [ Style(i) for i in [
|
||||
@@ -469,8 +530,6 @@ window_properties = [ Style(i) for i in [
|
||||
"size_group",
|
||||
"xminimum",
|
||||
"yminimum",
|
||||
"xfill",
|
||||
"yfill",
|
||||
] ]
|
||||
|
||||
button_properties = [ Style(i) for i in [
|
||||
@@ -501,14 +560,13 @@ box_properties = [ Style(i) for i in [
|
||||
"box_layout",
|
||||
"spacing",
|
||||
"first_spacing",
|
||||
"xfill",
|
||||
"yfill",
|
||||
] ]
|
||||
|
||||
ui_properties = [
|
||||
Keyword("at"),
|
||||
Keyword("id"),
|
||||
Keyword("style"),
|
||||
Keyword("group"),
|
||||
]
|
||||
|
||||
|
||||
@@ -795,13 +853,13 @@ class IfParser(Parser):
|
||||
|
||||
count += 1
|
||||
|
||||
while l.advance():
|
||||
state = l.checkpoint()
|
||||
|
||||
while l.advance():
|
||||
|
||||
old_orelse = orelse
|
||||
lineno = l.number
|
||||
|
||||
state = l.checkpoint()
|
||||
|
||||
if l.keyword("elif"):
|
||||
condition = self.parse_eval(l.require(l.python_expression), lineno)
|
||||
|
||||
@@ -813,6 +871,8 @@ class IfParser(Parser):
|
||||
|
||||
count += 1
|
||||
|
||||
state = l.checkpoint()
|
||||
|
||||
elif l.keyword("else"):
|
||||
|
||||
old_orelse.extend(self.parse_exec("%s = (%s, %d)" % (child_name, name, count)))
|
||||
@@ -823,7 +883,7 @@ class IfParser(Parser):
|
||||
else:
|
||||
l.revert(state)
|
||||
break
|
||||
|
||||
|
||||
return [ rv ]
|
||||
|
||||
IfParser("if")
|
||||
|
||||
+7
-9
@@ -110,7 +110,8 @@ class Script(object):
|
||||
self.namemap = { }
|
||||
self.all_stmts = [ ]
|
||||
self.all_pycode = [ ]
|
||||
|
||||
self.record_pycode = True
|
||||
|
||||
# Bytecode caches.
|
||||
self.bytecode_oldcache = { }
|
||||
self.bytecode_newcache = { }
|
||||
@@ -246,11 +247,15 @@ class Script(object):
|
||||
# See if we have a corresponding .rpyc file. If so, then
|
||||
# we want to try to upgrade our .rpy file with it.
|
||||
try:
|
||||
self.record_pycode = False
|
||||
old_data, old_stmts = self.load_file_core(dir, fn + "c")
|
||||
self.merge_names(old_stmts, stmts)
|
||||
del old_data
|
||||
del old_stmts
|
||||
except:
|
||||
pass
|
||||
finally:
|
||||
self.record_pycode = True
|
||||
|
||||
self.assign_names(stmts, fullfn)
|
||||
|
||||
@@ -286,12 +291,9 @@ class Script(object):
|
||||
return None, None
|
||||
|
||||
return data, stmts
|
||||
|
||||
|
||||
|
||||
|
||||
def load_file(self, dir, fn, initcode):
|
||||
|
||||
|
||||
# Actually do the loading.
|
||||
data, stmts = self.load_file_core(dir, fn)
|
||||
if data is None:
|
||||
@@ -415,10 +417,6 @@ class Script(object):
|
||||
# bytecode.
|
||||
for i in self.all_pycode:
|
||||
|
||||
i = i()
|
||||
if i is None:
|
||||
continue
|
||||
|
||||
codes = self.bytecode_oldcache.get(i.location, { })
|
||||
|
||||
if magic in codes:
|
||||
|
||||
+18
-4
@@ -384,14 +384,28 @@ def reset():
|
||||
class StyleManager(object):
|
||||
"""
|
||||
This is the singleton object that is exported into the store
|
||||
as style
|
||||
as style.
|
||||
"""
|
||||
|
||||
def __getattr__(self, name):
|
||||
try:
|
||||
return style_map[name]
|
||||
except:
|
||||
raise Exception('The style %s does not exist.' % name)
|
||||
pass
|
||||
|
||||
# Automatically create styles, maybe.
|
||||
if not styles_built:
|
||||
|
||||
if "_" in name:
|
||||
first, rest = name.split("_", 1)
|
||||
if rest in style_map:
|
||||
s = Style(rest)
|
||||
self.__setattr__(name, s)
|
||||
return s
|
||||
else:
|
||||
raise Exception("The style %s does not exist, and couldn't be auto-created because %s doesn't exist, either." % (name, rest))
|
||||
|
||||
raise Exception('The style %s does not exist.' % name)
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
|
||||
@@ -477,7 +491,7 @@ def expand_properties(properties):
|
||||
|
||||
# This builds the style.
|
||||
def build_style(style):
|
||||
|
||||
|
||||
if style.cache is not None:
|
||||
return
|
||||
|
||||
@@ -592,7 +606,7 @@ def build_styles():
|
||||
|
||||
global styles_pending
|
||||
global styles_built
|
||||
|
||||
|
||||
for s in styles_pending:
|
||||
build_style(s)
|
||||
|
||||
|
||||
+93
-45
@@ -29,7 +29,6 @@
|
||||
import sys
|
||||
import renpy
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Special classes that can be subclassed from the outside.
|
||||
|
||||
@@ -76,6 +75,9 @@ class BarValue(renpy.object.Object):
|
||||
# closed.
|
||||
|
||||
class Addable(object):
|
||||
# A group associates with this addable.
|
||||
group = None
|
||||
|
||||
def get_layer(self):
|
||||
return Exception("Operation can only be performed on a layer.")
|
||||
|
||||
@@ -101,9 +103,10 @@ class Many(Addable):
|
||||
A widget that takes many children.
|
||||
"""
|
||||
|
||||
def __init__(self, displayable, imagemap):
|
||||
def __init__(self, displayable, imagemap, group):
|
||||
self.displayable = displayable
|
||||
self.imagemap = False
|
||||
self.group = group
|
||||
|
||||
def add(self, d, key):
|
||||
self.displayable.add(d)
|
||||
@@ -122,9 +125,10 @@ class One(Addable):
|
||||
A widget that expects exactly one child.
|
||||
"""
|
||||
|
||||
def __init__(self, displayable):
|
||||
def __init__(self, displayable, group):
|
||||
self.displayable = displayable
|
||||
|
||||
self.group = group
|
||||
|
||||
def add(self, d, key):
|
||||
self.displayable.add(d)
|
||||
stack.pop()
|
||||
@@ -150,9 +154,10 @@ class ChildOrFixed(Addable):
|
||||
the widgets are added to that.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, group):
|
||||
self.queue = [ ]
|
||||
|
||||
self.group = group
|
||||
|
||||
def add(self, d, key):
|
||||
self.queue.append(d)
|
||||
|
||||
@@ -225,7 +230,7 @@ def child_or_fixed():
|
||||
a fixed will be created, and the children will be added to that.
|
||||
"""
|
||||
|
||||
stack.append(ChildOrFixed())
|
||||
stack.append(ChildOrFixed(stack[-1].group))
|
||||
|
||||
def remove(d):
|
||||
layer = stack[-1].get_layer()
|
||||
@@ -301,7 +306,27 @@ def context_enter(w):
|
||||
def context_exit(w):
|
||||
close(w)
|
||||
|
||||
NoGroupGiven = object()
|
||||
|
||||
def group_style(s, group):
|
||||
"""
|
||||
Given a style name s, combine it with the group to create a new
|
||||
style. If the style doesn't exist, create a new lightweight style.
|
||||
"""
|
||||
|
||||
if group is NoGroupGiven:
|
||||
group = stack[-1].group
|
||||
|
||||
if group is None:
|
||||
return s
|
||||
|
||||
new_style = group + "_" + s
|
||||
|
||||
if new_style not in renpy.style.style_map:
|
||||
renpy.style.style_map[new_style] = renpy.style.Style(s, heavy=False, name=new_style)
|
||||
|
||||
return new_style
|
||||
|
||||
# The screen we're using as we add widgets. None if there isn't a
|
||||
# screen.
|
||||
screen = None
|
||||
@@ -311,7 +336,7 @@ class Wrapper(renpy.object.Object):
|
||||
def __reduce__(self):
|
||||
return self.name
|
||||
|
||||
def __init__(self, function, one=False, many=False, imagemap=False, replaces=False, **kwargs):
|
||||
def __init__(self, function, one=False, many=False, imagemap=False, replaces=False, style=None, **kwargs):
|
||||
|
||||
# The name assigned to this wrapper. This is used to serialize us correctly.
|
||||
self.name = None
|
||||
@@ -331,18 +356,30 @@ class Wrapper(renpy.object.Object):
|
||||
# Default keyword arguments to the function.
|
||||
self.kwargs = kwargs
|
||||
|
||||
# Default style (suffix).
|
||||
self.style = style
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
|
||||
global add_tag
|
||||
|
||||
# Pull out the special kwargs, id and at.
|
||||
if not stack:
|
||||
raise Exception("Can't add displayable during init phase.")
|
||||
|
||||
# Pull out the special kwargs, id, at, and group.
|
||||
|
||||
id = kwargs.pop("id", None)
|
||||
|
||||
at_list = kwargs.pop("at", [ ])
|
||||
if not isinstance(at_list, list):
|
||||
at_list = [ at_list ]
|
||||
|
||||
|
||||
group = kwargs.pop("group", NoGroupGiven)
|
||||
|
||||
# Figure out our group.
|
||||
if group is NoGroupGiven:
|
||||
group = stack[-1].group
|
||||
|
||||
# Figure out the keyword arguments, based on the parameters.
|
||||
|
||||
if self.kwargs:
|
||||
@@ -358,16 +395,16 @@ class Wrapper(renpy.object.Object):
|
||||
if self.replaces:
|
||||
keyword["replaces"] = screen.old_widgets.get(id, None)
|
||||
|
||||
if self.style and "style" not in keyword:
|
||||
keyword["style"] = group_style(self.style, group)
|
||||
|
||||
try:
|
||||
w = self.function(*args, **keyword)
|
||||
|
||||
# We want to rewrite the type error so that it mentions our name,
|
||||
# so the user gcan figure out WTF is going on.
|
||||
except TypeError:
|
||||
except TypeError, e:
|
||||
etype, e, tb = sys.exc_info(); etype
|
||||
|
||||
if tb.tb_next is None:
|
||||
e.args = (e.args[0].replace("__init__", "ui." + self.name), )
|
||||
e.args = (e.args[0].replace("__call__", "ui." + self.name), )
|
||||
|
||||
del tb # Important! Prevents memory leaks via our frame.
|
||||
raise
|
||||
@@ -385,17 +422,13 @@ class Wrapper(renpy.object.Object):
|
||||
atw = atf(atw)
|
||||
|
||||
# Add to the displayable at the bottom of the stack.
|
||||
|
||||
if stack:
|
||||
stack[-1].add(atw, add_tag)
|
||||
else:
|
||||
raise Exception("Can't add displayable during init phase.")
|
||||
stack[-1].add(atw, add_tag)
|
||||
|
||||
# Update the stack, as necessary.
|
||||
if self.one:
|
||||
stack.append(One(w))
|
||||
stack.append(One(w, group))
|
||||
elif self.many:
|
||||
stack.append(Many(w, self.imagemap))
|
||||
stack.append(Many(w, self.imagemap, group))
|
||||
|
||||
# If we have an id, record the displayable, the transform,
|
||||
# and maybe take the state from a previous transform.
|
||||
@@ -466,19 +499,19 @@ def _image(im, **properties):
|
||||
image = Wrapper(_image)
|
||||
|
||||
null = Wrapper(renpy.display.layout.Null)
|
||||
text = Wrapper(renpy.display.text.Text, replaces=True)
|
||||
text = Wrapper(renpy.display.text.Text, style="text", replaces=True)
|
||||
hbox = Wrapper(renpy.display.layout.MultiBox, layout="horizontal", style="hbox", many=True)
|
||||
vbox = Wrapper(renpy.display.layout.MultiBox, layout="vertical", style="vbox", many=True)
|
||||
fixed = Wrapper(renpy.display.layout.MultiBox, layout="fixed", many=True)
|
||||
grid = Wrapper(renpy.display.layout.Grid, many=True)
|
||||
side = Wrapper(renpy.display.layout.Side, many=True)
|
||||
fixed = Wrapper(renpy.display.layout.MultiBox, layout="fixed", style="fixed", many=True)
|
||||
grid = Wrapper(renpy.display.layout.Grid, style="grid", many=True)
|
||||
side = Wrapper(renpy.display.layout.Side, style="side", many=True)
|
||||
|
||||
def _sizer(maxwidth=None, maxheight=None, **properties):
|
||||
return renpy.display.layout.Container(xmaximum=maxwidth, ymaximum=maxheight, **properties)
|
||||
|
||||
sizer = Wrapper(_sizer, one=True)
|
||||
window = Wrapper(renpy.display.layout.Window, one=True, child=None)
|
||||
frame = Wrapper(renpy.display.layout.Window, style='frame', one=True, child=None)
|
||||
window = Wrapper(renpy.display.layout.Window, style="window", one=True, child=None)
|
||||
frame = Wrapper(renpy.display.layout.Window, style="frame", one=True, child=None)
|
||||
|
||||
keymap = Wrapper(renpy.display.behavior.Keymap)
|
||||
saybehavior = Wrapper(renpy.display.behavior.SayBehavior)
|
||||
@@ -553,7 +586,7 @@ def menu(menuitems,
|
||||
|
||||
close()
|
||||
|
||||
input = Wrapper(renpy.display.behavior.Input, exclude='{}', replaces=True)
|
||||
input = Wrapper(renpy.display.behavior.Input, exclude='{}', style="input", replaces=True)
|
||||
|
||||
def imagemap_compat(ground,
|
||||
selected,
|
||||
@@ -591,7 +624,7 @@ def imagemap_compat(ground,
|
||||
|
||||
close()
|
||||
|
||||
button = Wrapper(renpy.display.behavior.Button, one=True)
|
||||
button = Wrapper(renpy.display.behavior.Button, style='button', one=True)
|
||||
|
||||
def _imagebutton(idle_image = None,
|
||||
hover_image = None,
|
||||
@@ -607,7 +640,6 @@ def _imagebutton(idle_image = None,
|
||||
selected_idle=None,
|
||||
selected_hover=None,
|
||||
selected_insensitive=None,
|
||||
style='image_button',
|
||||
image_style=None,
|
||||
auto=None,
|
||||
**properties):
|
||||
@@ -638,17 +670,15 @@ def _imagebutton(idle_image = None,
|
||||
selected_hover_image = selected_hover,
|
||||
selected_insensitive_image = selected_insensitive,
|
||||
selected_activate_image = selected_activate_image,
|
||||
style=style,
|
||||
**properties)
|
||||
|
||||
imagebutton = Wrapper(_imagebutton)
|
||||
imagebutton = Wrapper(_imagebutton, style="image_button")
|
||||
|
||||
def get_text_style(style, default):
|
||||
if isinstance(style, basestring):
|
||||
base = style
|
||||
rest = ()
|
||||
else:
|
||||
print style
|
||||
base = style.name[0]
|
||||
rest = style.name[1:]
|
||||
|
||||
@@ -657,26 +687,32 @@ def get_text_style(style, default):
|
||||
rv = renpy.style.style_map.get(base, None)
|
||||
|
||||
if rv is None:
|
||||
rv = renpy.style.style_map['default']
|
||||
rv = renpy.style.style_map[default]
|
||||
|
||||
for i in rest:
|
||||
rv = rv[i]
|
||||
|
||||
return rv
|
||||
|
||||
def textbutton(label, clicked=None, style='button', text_style=None, **kwargs):
|
||||
def textbutton(label, clicked=None, style=None, text_style=None, **kwargs):
|
||||
|
||||
if style is None:
|
||||
style = group_style('button', NoGroupGiven)
|
||||
|
||||
if text_style is None:
|
||||
text_style = get_text_style(style, 'button_text')
|
||||
|
||||
text_style = get_text_style(style, group_style('button_text', NoGroupGiven))
|
||||
|
||||
button(style=style, clicked=clicked, **kwargs)
|
||||
text(label, style=text_style)
|
||||
|
||||
def label(label, style='label', text_style=None, **kwargs):
|
||||
def label(label, style=None, text_style=None, **kwargs):
|
||||
|
||||
if style is None:
|
||||
style = group_style('label', NoGroupGiven)
|
||||
|
||||
if text_style is None:
|
||||
text_style = get_text_style(style, 'label_text')
|
||||
|
||||
text_style = get_text_style(style, group_style('label_text', NoGroupGiven))
|
||||
|
||||
window(style=style, **kwargs)
|
||||
text(label, style=text_style)
|
||||
|
||||
@@ -708,10 +744,22 @@ def _bar(*args, **properties):
|
||||
if "value" in properties:
|
||||
value = properties.pop("value")
|
||||
|
||||
if "style" not in properties:
|
||||
if isinstance(value, BarValue):
|
||||
if properties["vertical"]:
|
||||
style = value.get_style()[1]
|
||||
else:
|
||||
style = value.get_style()[0]
|
||||
|
||||
if isinstance(style, basestring):
|
||||
style = group_style(style, NoGroupGiven)
|
||||
|
||||
properties["style"] = style
|
||||
|
||||
return renpy.display.behavior.Bar(range, value, width, height, **properties)
|
||||
|
||||
bar = Wrapper(_bar, style=None, vertical=False, replaces=True)
|
||||
vbar = Wrapper(_bar, style=None, vertical=True, replaces=True)
|
||||
bar = Wrapper(_bar, vertical=False, replaces=True)
|
||||
vbar = Wrapper(_bar, vertical=True, replaces=True)
|
||||
slider = Wrapper(_bar, style='slider', replaces=True)
|
||||
vslider = Wrapper(_bar, style='vslider', replaces=True)
|
||||
scrollbar = Wrapper(_bar, style='scrollbar', replaces=True)
|
||||
@@ -735,8 +783,8 @@ def _autobar(range, start, end, time, **properties):
|
||||
return renpy.display.layout.DynamicDisplayable(autobar_interpolate(range, start, end, time, **properties))
|
||||
|
||||
autobar = Wrapper(_autobar)
|
||||
transform = Wrapper(renpy.display.motion.Transform, one=True)
|
||||
viewport = Wrapper(renpy.display.layout.Viewport, one=True, replaces=True)
|
||||
transform = Wrapper(renpy.display.motion.Transform, one=True, style='transform')
|
||||
viewport = Wrapper(renpy.display.layout.Viewport, one=True, replaces=True, style='viewport')
|
||||
conditional = Wrapper(renpy.display.behavior.Conditional, one=True)
|
||||
timer = Wrapper(renpy.display.behavior.Timer, replaces=True)
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
import inspect
|
||||
import re
|
||||
import collections
|
||||
@@ -80,6 +81,7 @@ hotbar
|
||||
transform
|
||||
add
|
||||
use
|
||||
has
|
||||
"""
|
||||
|
||||
|
||||
|
||||
@@ -146,6 +146,13 @@ Other Changes
|
||||
* When there are transparent areas on the screen, and
|
||||
:var:`config.developer` is true, the transparent areas are filled
|
||||
with a checkerboard pattern.
|
||||
|
||||
* The new ``input``, ``side``, ``grid``, and ``fixed`` styles were created,
|
||||
and the corresponding displayables use them by default.
|
||||
|
||||
* When a style is accessed at init-time, and doesn't exist, we divide it
|
||||
into two parts at the first underscore. If the second part corresponds
|
||||
to an existing style, we create a new style instead of causing an error.
|
||||
|
||||
* The python compiler has been rewritten to use the python ast module.
|
||||
This should both improve performance, and improve error handling for
|
||||
|
||||
@@ -304,6 +304,12 @@ Occasionally Used
|
||||
|
||||
If not None, a music file to play when at the game menu.
|
||||
|
||||
.. var:: config.gl_test_image = "black"
|
||||
|
||||
The name of the image that is used when running the OpenGL
|
||||
performance test. This image will be shown for 5 frames or .25
|
||||
seconds, on startup. It will then be automatically hidden.
|
||||
|
||||
.. var:: config.has_autosave = True
|
||||
|
||||
If true, the game will autosave. If false, no autosaving will
|
||||
@@ -604,13 +610,20 @@ Rarely or Internally Used
|
||||
mechanisms. Your file-like object must implement at least the
|
||||
read, seek, tell, and close methods.
|
||||
|
||||
|
||||
.. var:: config.focus_crossrange_penalty = 1024
|
||||
|
||||
This is the amount of penalty to apply to moves perpendicular to
|
||||
the selected direction of motion, when moving focus with the
|
||||
keyboard.
|
||||
|
||||
.. var:: config.gl_enable = True
|
||||
|
||||
Set this to False to disable OpenGL acceleration. OpenGL acceleration
|
||||
will automatically be disabled if it's determined that the system
|
||||
cannot support it, so it usually isn't necessary to set this.
|
||||
|
||||
OpenGL can also be disabled by holding down shift at startup.
|
||||
|
||||
.. var:: config.hard_rollback_limit = 100
|
||||
|
||||
This is the number of steps that Ren'Py will let the user
|
||||
|
||||
@@ -72,6 +72,9 @@ becomes: ::
|
||||
There are three groups of UI functions, corresponding to the number
|
||||
of children they take.
|
||||
|
||||
.. When updating this list, be sure to update the documentation for
|
||||
the layout statement in screens.rst as well.
|
||||
|
||||
The following UI functions do not take any children.
|
||||
|
||||
* ui.add
|
||||
@@ -103,6 +106,7 @@ taking children until :func:`ui.close` is called.
|
||||
* ui.grid
|
||||
* ui.hbox
|
||||
* ui.side
|
||||
* ui.vbox
|
||||
* ui.imagemap
|
||||
|
||||
There are a few UI functions that do not correspond to screen language
|
||||
|
||||
+90
-28
@@ -150,14 +150,29 @@ All user interface statements take the following common properties:
|
||||
given identifier. Some screens will require that a displayable
|
||||
with a given identifier is created.
|
||||
|
||||
By default, the
|
||||
By default, the id is automatically-generated.
|
||||
|
||||
`style`
|
||||
The name of the style applied to this displayable. This may be a
|
||||
string name, or a style object. The style gives default
|
||||
values for style properties.
|
||||
|
||||
`group`
|
||||
Group is used to provide a prefix to the style of a displayable,
|
||||
for this displayable and all of its children (unless they have a
|
||||
more specific group set).
|
||||
|
||||
For example, if a vbox has a group of ``"pref"``, then the vbox will
|
||||
have the style ``"pref_vbox"``, unless a more specific style is
|
||||
supplied to it. A button inside that vbox would default to the
|
||||
style ``"pref_button"``.
|
||||
|
||||
Styles accessed in this way are automatically created, if they do
|
||||
not exist. This prevents an error from being signalled.
|
||||
|
||||
Setting a group of ``None`` disables this behavior for a
|
||||
displayable and all of its children.
|
||||
|
||||
Many user interface statements take classes of style properties, or
|
||||
transform properties. These properties can have a style prefix
|
||||
associated with them, that determines when they apply. For example, if
|
||||
@@ -215,12 +230,13 @@ This does not take children.
|
||||
::
|
||||
|
||||
screen volume_controls:
|
||||
frame:
|
||||
vbox:
|
||||
bar value Preference("sound volume")
|
||||
bar value Preference("music volume")
|
||||
bar value Preference("voice volume")
|
||||
|
||||
frame:
|
||||
has vbox
|
||||
|
||||
bar value Preference("sound volume")
|
||||
bar value Preference("music volume")
|
||||
bar value Preference("voice volume")
|
||||
|
||||
Button
|
||||
------
|
||||
|
||||
@@ -471,10 +487,10 @@ This does not take any children.
|
||||
|
||||
screen input_screen:
|
||||
window:
|
||||
vbox:
|
||||
spacing 10
|
||||
text "Enter your name."
|
||||
input default "Joseph P. Blow, ESQ."
|
||||
has vbox
|
||||
|
||||
text "Enter your name."
|
||||
input default "Joseph P. Blow, ESQ."
|
||||
|
||||
Key
|
||||
---
|
||||
@@ -528,10 +544,11 @@ It does not take children.
|
||||
|
||||
screen display_preference:
|
||||
frame:
|
||||
vbox:
|
||||
label "Display"
|
||||
textbutton "Fullscreen" action Preference("display", "fullscreen")
|
||||
textbutton "Window" action Preference("display", "window")
|
||||
has vbox
|
||||
|
||||
label "Display"
|
||||
textbutton "Fullscreen" action Preference("display", "fullscreen")
|
||||
textbutton "Window" action Preference("display", "window")
|
||||
|
||||
Null
|
||||
----
|
||||
@@ -699,10 +716,11 @@ as `bar`.
|
||||
|
||||
screen volume_controls:
|
||||
frame:
|
||||
hbox:
|
||||
vbar value Preference("sound volume")
|
||||
vbar value Preference("music volume")
|
||||
vbar value Preference("voice volume")
|
||||
has hbox
|
||||
|
||||
vbar value Preference("sound volume")
|
||||
vbar value Preference("music volume")
|
||||
vbar value Preference("voice volume")
|
||||
|
||||
|
||||
Vbox
|
||||
@@ -934,6 +952,48 @@ function takes:
|
||||
|
||||
This does not take children.
|
||||
|
||||
Has Statement
|
||||
=============
|
||||
|
||||
The has statment allows you to specify a container to use, instead of
|
||||
fixed, for statements that take only one child. The has statement
|
||||
may only be used inside a statement that takes one child. The keyword
|
||||
``has`` is followed (on the same line) by another statement, which
|
||||
must be a statement that creates a container displayable, one that
|
||||
takes more than one child.
|
||||
|
||||
The has statement changes the way in which the block that contains
|
||||
it is parsed. Child displayables created in that block are added to
|
||||
the container, rather than the parent displayable. Keyword arguments
|
||||
to the parent displayable are not allowed after the has statement.
|
||||
|
||||
The has statement can be supplied as a child of the following
|
||||
statements:
|
||||
|
||||
* button
|
||||
* frame
|
||||
* window
|
||||
|
||||
The has statement can be given the following statements as a
|
||||
container.
|
||||
|
||||
* fixed
|
||||
* grid
|
||||
* hbox
|
||||
* side
|
||||
* vbox
|
||||
|
||||
::
|
||||
|
||||
screen volume_controls:
|
||||
frame:
|
||||
has vbox
|
||||
|
||||
bar value Preference("sound volume")
|
||||
bar value Preference("music volume")
|
||||
bar value Preference("voice volume")
|
||||
|
||||
|
||||
Control Statements
|
||||
==================
|
||||
|
||||
@@ -991,10 +1051,11 @@ occurs.
|
||||
|
||||
screen preferences:
|
||||
frame:
|
||||
hbox:
|
||||
text "Display"
|
||||
textbutton "Fullscreen" action Preferences("display", "fullscreen")
|
||||
textbutton "Window" action Preferences("display", "window")
|
||||
has hbox
|
||||
|
||||
text "Display"
|
||||
textbutton "Fullscreen" action Preferences("display", "fullscreen")
|
||||
textbutton "Window" action Preferences("display", "window")
|
||||
|
||||
on "show" action Show("navigation")
|
||||
on "hide" action Hide("navigation")
|
||||
@@ -1017,11 +1078,12 @@ values.
|
||||
button:
|
||||
action FileAction(slot)
|
||||
|
||||
hbox:
|
||||
add FileScreenshot(slot)
|
||||
vbox:
|
||||
text FileTime(slot, empty="Empty Slot.")
|
||||
text FileSaveName(slot)
|
||||
has hbox
|
||||
|
||||
add FileScreenshot(slot)
|
||||
vbox:
|
||||
text FileTime(slot, empty="Empty Slot.")
|
||||
text FileSaveName(slot)
|
||||
|
||||
|
||||
screen save:
|
||||
|
||||
+16
-12
@@ -254,6 +254,22 @@ layout.
|
||||
|
||||
Specifies the maximum vertical size of the displayable in pixels.
|
||||
|
||||
.. style-property:: xfill boolean
|
||||
|
||||
If true, the displayable will expand to fill all available
|
||||
horizontal space. If not true, it will only be large enough to
|
||||
contain its children.
|
||||
|
||||
This only works for displayables that can change size.
|
||||
|
||||
.. style-property:: yfill boolean
|
||||
|
||||
If true, the displayable will expand to fill all available
|
||||
horizontal space. If not true, it will only be large enough to
|
||||
contain its children.
|
||||
|
||||
This only works for displayables that can change size.
|
||||
|
||||
.. style-property:: area tuple of (int, int, int, int)
|
||||
|
||||
The tuple is interpreted as (`xpos`, `ypos`, `width`,
|
||||
@@ -502,18 +518,6 @@ buttons.
|
||||
|
||||
Sets the minimum height of the window, in pixels.
|
||||
|
||||
.. style-property:: xfill boolean
|
||||
|
||||
If true, the window will expand to fill all available horizontal
|
||||
space. If not true, it will only be large enough to contain its
|
||||
child.
|
||||
|
||||
.. style-property:: yfill boolean
|
||||
|
||||
If true, the window will expand to fill all available horizontal
|
||||
space. If not true, it will only be large enough to contain its
|
||||
child.
|
||||
|
||||
|
||||
.. _button-style-properties:
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
executable_name = 'the_question'
|
||||
documentation_extensions = 'txt html'
|
||||
description = "A simple and complete Ren'Py game."
|
||||
build_mac = False
|
||||
build_mac = True
|
||||
build_all = True
|
||||
build_windows = True
|
||||
distribution_base = 'the_question-1.0'
|
||||
ignore_extensions = '~ .bak'
|
||||
build_linux = False
|
||||
build_all = False
|
||||
build_linux = True
|
||||
executable_name = 'the_question'
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user