1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
|
==================
Screens and Python
==================
Ren'Py supports defining screens in Python, as well as in the Ren'Py
screen language. A Python screen is created by supplying a screen
function to the :func:`renpy.define_screen` function. It can then
be used like it was any other screen.
The screen function should have parameters corresponding to the scope
variables it expects, and it should ignore extra keyword
arguments. (That is, it should have `**kwargs` at the end of its
parameter list.) It is then expected to call the UI functions to add
displayables to the screen.The screen function is called whenever an
interaction starts or restarts.
To ensure that this restarting is seamless to the user (and
not causing things to reset), it's important that every call to a UI
function supply the `id` argument. As a screen is re-created, Ren'Py
will update each displayable with the contents of the old displayable
with the same id. Ids are generated automatically by the screen
language, but when doing things by hand, they must be manually
specified.
.. warning::
UI Functions are deprecated and not recommended.
Here's an example Python screen::
init python:
def say_screen(who, what, **kwargs):
ui.window(id="window")
ui.vbox(id="say_vbox")
ui.text(who, id="who")
ui.text(what, id="what")
ui.close()
renpy.define_screen("say", say_screen)
Screen Functions
================
The following functions support the definition, display, and hiding of
screens.
.. include:: inc/screens
UI Functions
============
.. note::
The implementation of Ren'Py has changed, and UI functions that
create displayables can now be far slower than their screen language
equivalents.
The UI functions are Python equivalents of the screen language
statements. For each screen language statement, there is a ui function
with the same name. For example, ui.text corresponds to the text
statement, and ui.add corresponds to the add statement.
There is a simple mapping between screen language parameters and
arguments and Python arguments. Screen language parameters
become positional arguments, while properties become keyword
arguments. For example, the screen language statement: ::
text "Hello, World" size 40 xalign 0.5
becomes: ::
ui.text("Hello, World", size=40, xalign=0.5)
(It really should have an `id` parameter added.)
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
* ui.bar
* ui.imagebutton
* ui.input
* ui.key
* ui.label
* ui.null
* ui.text
* ui.textbutton
* ui.timer
* ui.vbar
* ui.hotspot
* ui.hotbar
* ui.spritemanager
The following UI functions take a single child. They must be given
that child – use :func:`ui.null` if the child is missing.
* ui.button
* ui.frame
* ui.transform
* ui.window
* ui.drag
The following UI functions take multiple children. They continue
taking children until :func:`ui.close` is called.
* ui.fixed
* ui.grid
* ui.hbox
* ui.side
* ui.vbox
* ui.imagemap
* ui.draggroup
There are a few UI functions that do not correspond to screen language
statements, as they correspond to concepts that are not present in the
screen language.
.. include:: inc/ui
Actions
=======
Many of the displayables created in the screen language take actions
as arguments. An action is one of three things:
* A callable Python object (like a function or bound method) that
takes no arguments.
* An object of a class that inherits from the Action class.
* A list of other Actions.
The advantage to inheriting from the Action class is that it allows
you to override the methods that determine when a button should be
sensitive, and when it is selected.
.. class:: Action
To define a new action, inherit from this class. Override the
methods in this class to change the behavior of the action.
.. method:: __call__(self)
This is the method that is called when the action is
activated. In many cases, returning a non-None value from the
action will cause the current interaction to end.
This method must be overridden, as the default method will
raise NotImplemented (and hence cause Ren'Py to report an
error).
.. method:: get_sensitive(self)
This is called to determine if the button with this action
should be sensitive. It should return true if the button is
sensitive.
Note that __call__ can be called, even if this returns False.
The default implementation returns True.
.. method:: get_selected(self)
This should return true if the button should be rendered as a
selected button, and false otherwise.
The default implemention returns False.
.. method:: periodic(self, st)
This method is called once at the start of each interaction,
and then is called periodically thereafter. If it returns a
number, it will be called before that many seconds elapse, but
it might be called sooner.
The main use of this is to call
:func:`renpy.restart_interaction` if the value of
get_selected or get_sensitive should change.
It takes one argument:
`st`
The number of seconds since the screen or displayable this
action is associated with was first shown.
.. method:: unhovered(self):
When the action is used as the `hovered` parameter to a button (or
similar object), this method is called when the object loses focus.
To run an action from Python, use :func:`renpy.run`.
.. include:: inc/run
BarValues
=========
When creating a bar, vbar, or hotbar, a BarValue object can be supplied as
the `value` property. Methods on the BarValue object are called to get
the adjustment and styles.
.. class:: BarValue
To define a new BarValue, inherit from this class and override
some of the methods.
.. method:: get_adjustment(self)
This method is called to get an adjustment object for the
bar. It should create the adjustment with
:func:`ui.adjustment`, and then return the object created this
way.
This method must be overridden, as the default method will
raise NotImplemented (and hence cause Ren'Py to report an
error).
.. method:: get_style(self)
This is used to determine the style of bars that use this
value. It should return a tuple of two style names or style
objects. The first is used for a bar, and the
second for vbar.
This defaults to ("bar", "vbar").
.. method:: replaces(self, other)
This is called when a BarValue replaces another BarValue, such
as when a screen is updated. It can be used to update this
BarValue from the other. It is called before get_adjustment.
Note that `other` is not necessarily the same type as `self`.
.. method:: periodic(self, st)
This method is called once at the start of each interaction. If
it returns a number of seconds, it will be called before that
many seconds elapse, but it might be called sooner. It is
called after get_adjustment.
It can be used to update the value of the bar over time, like
:func:`AnimatedValue` does. To do this, get_adjustment should
store the adjustment, and periodic should call the
adjustment's changed method.
InputValue
==========
When creating an input, an InputValue object can be supplied as the
`value` property. Methods on the InputValue object are called to
get and set the text, determine if the input is editable, and handle
the enter key being pressed.
.. class:: InputValue
To define a new InputValue, inherit from this class, override
some or all of the methods, and set the value of the default
field.
.. attribute: editable
If true, this field is editable at all.
.. attribute:: default
If true, the input is eligible to be editable by default. (That
is, it may be given the caret when the screen is shown.)
.. method:: get_text(self)
Returns the default text of the input. This must be implemented.
.. method:: set_text(self, s)
Called when the text of the input is changed, with the new text.
This must be implemented.
.. method:: enter(self)
Called when the user presses enter. If this returns a non-None
value, that value is returned from the interacton. This may also
raise renpy.IgnoreEvent() to ignore the press. Otherwise, the
enter-press is propagated to other displayables.
The following actions are available as methods on InputValue:
.. method:: Enable()
Returns an action that enables text editing on the input.
.. method:: Disable()
Returns an action that disables text editing on the input.
.. method:: Toggle()
Returns an action that toggles text editing on the input.
.. _creator-defined-sl:
Creator-Defined Screen Language Statements
==========================================
Ren'Py supports defining custom screen language statements. Creator-defined screen
language statements are wrappers for the screen language :ref:`use statement <sl-use>`.
Positional arguments remain positional arguments, properties become keyword
arguments, and if the statement takes a block, so does the use statement. For
example, the custom screen language statement::
titledwindow "Test Window":
icon "icon.png"
text "This is a test."
becomes::
use titledwindow("Test Window", icon="icon.png"):
text "This is a test."
Creator-defined screen language statements must be registered in a ``python early`` block.
What's more, the filename containing the creator-defined statement must be be loaded earlier
than any file that uses it. Since Ren'Py loads files in Unicode sort order, it
generally makes sense to prefix the name of any file registering a user-defined
statement with 01, or some other small number.
Creator-defined screen language statements are registered with the renpy.register_sl_statement
function:
.. include:: inc/custom_sl
As an example of a creator-defined screen language statement, here's an
implementation of the ``titledwindow`` statement given above. First, the
statement must be registered in a ``python early`` block in a file that is loaded
early – a name like 01custom.rpy will often load soon enough. The registration
call looks like::
python early:
renpy.register_sl_statement("titledwindow", positional=1, children=1).add_property("icon").add_property("pos")
Then, we define a screen that implements the custom statement. This screen can be defined in
any file. One such screen is::
screen titledwindow(title, icon=None, pos=(0, 0)):
drag:
pos pos
frame:
background "#00000080"
has vbox
hbox:
if icon is not None:
add icon
text title
null height 15
transclude
|