File: tutorial_screen_displayables.rpy

package info (click to toggle)
renpy 8.0.3%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 81,768 kB
  • sloc: python: 44,587; ansic: 13,708; javascript: 308; makefile: 41; sh: 13
file content (897 lines) | stat: -rw-r--r-- 30,957 bytes parent folder | download
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
label screen_displayables:

    e "There are quite a few screen displayables. Here, I'll tell you about some of the most important ones."

label screen_displayables_menu:

    $ reset_example()

    menu:

        e "What would you like to know about?"

        "Common properties all displayables share.":
            call screen_displayable_properties

        "Adding images and other displayables.":
            call add_displayable

        "Text.":
            call text_displayable

        "Boxes and other layouts.":
            call layout_displayables

        "Windows and frames.":
            call window_displayables

        "Buttons.":
            call button_displayables

        "Bars.":
            call bar_displayables

        "Viewports.":
            call viewport_displayables

        "Imagemaps.":
            call imagemap_displayables

        "That's all for now.":
            return

    jump screen_displayables_menu



label screen_displayable_properties:

    e "There are a few properties that every screen language displayable shares. Here, I'll demonstrate them for you."

    example large:
        screen pos_example():
            frame:
                xalign 0.5 ypos 50
                text _("This uses position properties.")

    e "First off, every screen language displayable supports the position properties. When the container a displayable is in supports it, you can use properties like align, anchor, pos, and so so on."

    example:
        screen at_example():
            frame:
                xalign 0.5 ypos 50
                text _("And the world turned upside down..."):
                    at rotated

        transform rotated:
            rotate 180 rotate_pad False

    e "The at property applies a transform to the displayable, the same way the at clause in the show statement does."


#     example large:
#         screen event_example():
#             frame:
#                 at inout
#                 xalign 0.5 ypos 50
#                 text _("This is an event.") at textform
#
#
#         transform inout:
#             on show:
#                 zoom 1.5 alpha 0.0
#                 linear .5 zoom 1.0 alpha 1.0
#
#             on hide:
#                 linear .5 zoom 1.5 alpha 0.0

#
#     example:
#         screen default_example():
#             frame:
#                 xalign 0.5 ypos 50
#
#                 vbox:
#
#                     textbutton "Choice 1" action Return(1)
#                     textbutton "Choice 2" action Return(1) default True
#                     textbutton "Choice 3" action Return(1)


    hide screen at_example
    with dissolve

    show example say_screen

    e "The id property is mostly used with the say screen, which is used to show dialogue. Outside of the say screen, it isn't used much."

    e "It tells Ren'Py which displayables are the background window, 'who' is speaking, and 'what' is being said. This used to apply per-Character styles, and help with auto-forward mode."

    example:
        screen style_example():
            frame:
                xalign 0.5 ypos 50
                vbox:
                    text _("Flight pressure in tanks.") style "green_text"
                    text _("On internal power.")
                    text _("Launch enabled.")
                    text _("Liftoff!")

    style green_text:
        color "#c8ffc8"

    e "The style property lets you specify the style of a single displayable."

    example:
        screen style_prefix_example():
            frame:
                xalign 0.5 ypos 50
                vbox:
                    vbox:
                        style_prefix "green"
                        text _("Flight pressure in tanks.")
                        text _("On internal power.")

                    vbox:
                        style_prefix "yellow"
                        text _("Launch enabled.")
                        text _("Liftoff!")

    style yellow_text:
        color "#ffffc8"


    e "The style_prefix property sets the prefix of the style that's used for a displayable and its children."

    e "For example, when the style_prefix property is 'green', the vbox has the 'green_vbox' style, and the text in it has the 'green_text' style."

    hide example

    e "There are a few more properties than these, and you can find the rest in the documentation. But these are the ones you can expect to see in your game, in the default screens."

    return

label add_displayable:

    e "Sometimes you'll have a displayable, like an image, that you want to add to a screen."

    example large:

        screen add_image_example():
            frame:
                xalign 0.5 ypos 50
                add "logo base"

    e "This can be done using the add statement, which adds an image or other displayable to the screen."

    e "There are a few ways to refer to the image. If it's in the images directory or defined with the image statement, you can just put the name inside a quoted string."

    example large:

        screen add_filename_example():
            frame:
                xalign 0.5 ypos 50
                add "images/logo base.png"

    e "An image can also be referred to by its filename, relative to the game directory." id add_displayable_8ba81c26

    example large:

        screen add_displayable_example():
            frame:
                xalign 0.5 ypos 50
                add Solid("#0000ff", xsize=234, ysize=360)

    e "Other displayables can also be added using the add statement. Here, we add the Solid displayable, showing a solid block of color."


    example large:

        screen add_transform_example():
            frame:
                xalign 0.5 ypos 50
                add "logo base" zoom 0.7 rotate 43.21

    e "In addition to the displayable, the add statement can be given transform properties. These can place or otherwise transform the displayable being added."

    example:

        screen add_at_transform_example():
            frame:
                xalign 0.5 ypos 50
                add "logo base" at unrotate

        transform unrotate:
            zoom 0.7 rotate 43.21
            linear 1.0 rotate 0
    e "Of course, the add statement can also take the at property, letting you give it a more complex transform."

    hide example

    return

label text_displayable:

    example large:
        screen text_example():
            frame:
                xalign 0.5 ypos 50
                text _("This is a text displayable."):
                    size 30

    e "The screen language text statement adds a text displayable to the screen. It takes one argument, the text to be displayed."

    e "In addition to the common properties that all displayables take, text takes the text style properties. For example, size sets the size of the text."

    example large:
        screen text_interpolation_example():
            $ answer = 42

            frame:
                xalign 0.5 ypos 50
                text _("The answer is [answer].")

    e "The text displayable can also interpolate values enclosed in square brackets."

    e "When text is displayed in a screen using the text statement, variables defined in the screen take precedence over those defined outside it." id text_displayable_32d76ccb

    e "Those variables may be parameters given to the screen, defined with the default or python statements, or set using the SetScreenVariable action."

    example large:
        screen text_tax_example():
            frame:
                xalign 0.5 ypos 50
                text _("Text tags {color=#c8ffc8}work{/color} in screens.")


    e "There's not much more to say about text in screens, as it works the same way as all other text in Ren'Py."

    hide example
    return


label layout_displayables:

    e "The layout displayables take other displayables and lay them out on the screen."

    example large:
        screen hbox_example():
            frame:
                xalign 0.5 ypos 50
                hbox:
                    spacing 10
                    text "1"
                    text "2"
                    text "3"
                    text "4"
                    text "5"

    e "For example, the hbox displayable takes its children and lays them out horizontally."

    example:
        screen vbox_example():
            frame:
                xalign 0.5 ypos 50
                vbox:
                    spacing 10
                    text "1"
                    text "2"
                    text "3"
                    text "4"
                    text "5"


    e "The vbox displayable is similar, except it takes its children and arranges them vertically."

    e "Both of the boxes take the box style properties, the most useful of which is spacing, the amount of space to leave between children."

    example:
        screen grid_example():
            frame:
                xalign 0.5 ypos 50
                grid 3 2:
                    spacing 10
                    text "1"
                    text "2"
                    text "3"
                    text "4"
                    text "5"
                    null

    e "The grid displayable displays its children in a grid of equally-sized cells. It takes two arguments, the number of columns and the number of rows."

    e "The grid has to be full, or Ren'Py will produce an error. Notice how in this example, the empty cell is filled with a null."

    e "Like the boxes, grid uses the spacing property to specify the space between cells."

    example:
        screen grid_transpose_example():
            frame:
                xalign 0.5 ypos 50
                grid 3 2:
                    spacing 10
                    transpose True
                    text "1"
                    text "2"
                    text "3"
                    text "4"
                    text "5"
                    null

    e "Grid also takes the transpose property, to make it fill top-to-bottom before it fills left-to-right."


    example:
        screen grid_bigger_example():
            frame:
                xalign 0.5 ypos 50
                grid 3 2:
                    spacing 10
                    transpose True
                    text "1"
                    text "2"
                    text "3"
                    text "4"
                    text "5"
                    text _("Bigger")

    e "And just to demonstrate that all cells are equally-sized, here's what happens when once child is bigger than the others."


    example:
        screen fixed_example():
            frame:
                xalign 0.5 ypos 50
                fixed:
                    xsize 400 ysize 300
                    text "1" xpos 41 ypos 184
                    text "2" xpos 135 ypos 177
                    text "3" xpos 92 ypos 3
                    text "4" xpos 359 ypos 184
                    text "5" xpos 151 ypos 25

    e "The fixed displayable displays the children using Ren'Py's normal placement algorithm. This lets you place displayables anywhere in the screen."

    e "By default, the layout expands to fill all the space available to it. To prevent that, we use the xsize and ysize properties to set its size in advance."

    example:
        screen implicit_fixed_example():
            frame:
                xalign 0.5 ypos 50
                xsize 440 ysize 316

                text "1" xpos 41 ypos 184
                text "2" xpos 135 ypos 177
                text "3" xpos 92 ypos 3
                text "4" xpos 359 ypos 184
                text "5" xpos 151 ypos 25

    e "When a non-layout displayable is given two or more children, it's not necessary to create a fixed. A fixed is automatically added, and the children are added to it."

    example large:
        screen hbox_example():
            frame:
                xalign 0.5 ypos 50

                has hbox spacing 10

                text "1"
                text "2"
                text "3"
                text "4"
                text "5"

    e "Finally, there's one convenience to save space. When many displayables are nested, adding a layout to each could cause crazy indent levels."

    e "The has statement creates a layout, and then adds all further children of its parent to that layout. It's just a convenience to make screens more readable."

    hide example

    return


label window_displayables:

    e "In the default GUI that Ren'Py creates for a game, most user interface elements expect some sort of background."

    example large:
        screen noframe_example():
            vbox:
                xalign 0.5 ypos 50
                text _("This is a screen.")
                textbutton _("Okay"):
                    action Return(True)

    e "Without the background, text can be hard to read. While a frame isn't strictly required, many screens have one or more of them."

    example large:
        screen frame_example():
            frame:
                xalign 0.5 ypos 50
                vbox:
                    text _("This is a screen.")
                    textbutton _("Okay"):
                        action Return(True)


    e "But when I add a background, it's much easier. That's why there are two displayables that are intended to give backgrounds to user interface elements."

    e "The two displayables are frame and window. Frame is the one we use above, and it's designed to provide a background for arbitrary parts of the user interface."

    show example say_screen

    e "On the other hand, the window displayable is very specific. It's used to provide the text window. If you're reading what I'm saying, you're looking at the text window right now."

    e "Both frames and windows can be given window style properties, allowing you to change things like the background, margins, and padding around the window."

    hide example
    return


label button_displayables:

    e "One of the most flexible displayables is the button displayable, and its textbutton and imagebutton variants."

    example large:
        screen button_example():
            frame:
                xalign 0.5 ypos 50
                button:
                    action Notify(_("You clicked the button."))
                    text _("Click me.") style "button_text"

    e "A button is a displayable that when selected runs an action. Buttons can be selected by clicking with the mouse, by touch, or with the keyboard and controller."

    e "Actions can do many things, like setting variables, showing screens, jumping to a label, or returning a value. There are many {a=https://www.renpy.org/doc/html/screen_actions.html}actions in the Ren'Py documentation{/a}, and you can also write your own."

    example large:
        screen button_hover_example():
            frame:
                xalign 0.5 ypos 50
                button:
                    action Notify(_("You clicked the button."))
                    hovered Notify(_("You hovered the button."))
                    unhovered Notify(_("You unhovered the button."))
                    text _("Click me.") style "button_text"


    e "It's also possible to run actions when a button gains and loses focus."

    example large:
        screen button_heal_example():
            default health = 42

            frame:
                xalign 0.5 ypos 50
                button:
                    action SetScreenVariable("health", 100)
                    hbox:
                        spacing 10
                        text _("Heal") style "button_text" yalign 0.5
                        bar value AnimatedValue(health, 100, 1.0) yalign 0.5 xsize 200

    e "A button takes another displayable as a child. Since that child can be a layout, it can take as many children as you want." id button_displayables_47af4bb9

    example large:
        screen textbutton_example():
            frame:
                xalign 0.5 ypos 50
                textbutton _("This is a textbutton."):
                    action Notify(_("You clicked the button."))


    e "In many cases, buttons will be given text. To make that easier, there's the textbutton displayable that takes the text as an argument."

    e "Since the textbutton displayable manages the style of the button text for you, it's the kind of button that's used most often in the default GUI."


    example large:
        screen imagebutton_example():
            frame:
                xalign 0.5 ypos 50
                imagebutton:
                    idle "logo bw"
                    hover "logo base"

                    action Notify(_("You clicked the button."))

    e "There's also the imagebutton, which takes displayables, one for each state the button can be in, and displays them as the button."

    e "An imagebutton gives you the most control over what a button looks like, but is harder to translate and won't look as good if the game window is resized."


    example large:
        screen button_inline_style_example():
            frame:
                xalign 0.5 ypos 50
                textbutton _("Click me."):
                    idle_background Frame("button glossy idle", 12, 12)
                    hover_background Frame("button glossy hover", 12, 12)
                    xpadding 20
                    ypadding 10
                    xmargin 5
                    ymargin 5

                    hover_sound "pong_beep.opus"

                    text_idle_color "#c0c0c0"
                    text_hover_color "#ffffff"

                    action Notify(_("You clicked the button."))

    e "Buttons take Window style properties, that are used to specify the background, margins, and padding. They also take Button-specific properties, like a sound to play on hover."

    e "When used with a button, style properties can be given prefixes like idle and hover to make the property change with the button state."

    e "A text button also takes Text style properties, prefixed with text. These are applied to the text displayable it creates internally."

    example large:
        screen button_style_example():
            frame:
                xalign 0.5 ypos 50

                has vbox

                textbutton _("Click me."):
                    style "custom_button"
                    action Notify(_("You clicked the button."))

                textbutton _("Or me."):
                    style "custom_button"
                    action Notify(_("You clicked the other button."))

        style custom_button:
            idle_background Frame("button glossy idle", 12, 12)
            hover_background Frame("button glossy hover", 12, 12)
            xpadding 20
            ypadding 10
            xmargin 5
            ymargin 5
            size_group "custom_button"

            hover_sound "pong_beep.opus"

        style custom_button_text:
            idle_color "#c0c0c0"
            hover_color "#ffffff"

    e "Of course, it's prety rare we'd ever customize a button in a screen like that. Instead, we'd create custom styles and tell Ren'Py to use them."

    hide example
    return

    return


label bar_displayables:

    example large:
        screen bar_example():
            frame:
                xalign 0.5 ypos 50
                xsize 500
                bar:
                    value StaticValue(66, 100)


    e "The bar and vbar displayables are flexible displayables that show bars representing a value. The value can be static, animated, or adjustable by the player."

    e "The value property gives a BarValue, which is an object that determines the bar's value and range. Here, a StaticValue sets the range to 100 and the value to 66, making a bar that's two thirds full."

    e "A list of all the BarValues that can be used is found {a=https://www.renpy.org/doc/html/screen_actions.html#bar-values}in the Ren'Py documentation{/a}."

    e "In this example, we give the frame the xsize property. If we didn't do that, the bar would expand to fill all available horizontal space."

    example large:
        screen bars_example():
            default n = 66

            frame:
                xalign 0.5 ypos 50
                xsize 500

                vbox:
                    spacing 10

                    bar value AnimatedValue(n, 100, 0.5) style "bar"
                    bar value ScreenVariableValue("n", 100) style "slider"
                    bar value ScreenVariableValue("n", 100) style "scrollbar"

    e "There are a few different bar styles that are defined in the default GUI. The styles are selected by the style property, with the default selected by the value."

    e "The top style is the 'bar' style. It's used to display values that the player can't adjust, like a life or progress bar."

    e "The middle style is the 'slider' value. It's used for values the player is expected to adjust, like a volume preference." id bar_displayables_c2aa4725

    e "Finally, the bottom style is the 'scrollbar' style, which is used for horizontal scrollbars. When used as a scrollbar, the thumb in the center changes size to reflect the visible area of a viewport."

    example large:
        screen vbars_example():
            default n = 66

            frame:
                xalign 0.5 ypos 50
                ysize 300

                hbox:
                    spacing 10

                    vbar value AnimatedValue(n, 100, 0.5)
                    vbar value ScreenVariableValue("n", 100) style "vslider"
                    vbar value ScreenVariableValue("n", 100) style "vscrollbar"

    e "The vbar displayable is similar to the bar displayable, except it uses vertical styles - 'vbar', 'vslider', and 'vscrollbar' - by default."


    e "Bars take the Bar style properties, which can customize the look and feel greatly. Just look at the difference between the bar, slider, and scrollbar styles."

    hide example
    return



label imagemap_displayables:

    e "Imagemaps use two or more images to show buttons and bars. Let me start by showing you an example of an imagemap in action."

    window hide None

    example imagemap hide noshow:
        screen imagemap_example():
            imagemap:
                idle "imagemap ground"
                hover "imagemap hover"

                hotspot (44, 238, 93, 93) action Jump("swimming") alt "Swimming"
                hotspot (360, 62, 93, 93) action Jump("science") alt "Science"
                hotspot (726, 106, 93, 93) action Jump("art") alt "Art"
                hotspot (934, 461, 93, 93) action Jump("home") alt "Home"

        label imagemap_example:

            # Call the imagemap_example screen.
            call screen imagemap_example

        label swimming:

            e "You chose swimming."

            e "Swimming seems like a lot of fun, but I didn't bring my bathing suit with me."

            jump imagemap_done

        label science:

            e "You chose science."

            e "I've heard that some schools have a competitive science team, but to me research is something that can't be rushed."

            jump imagemap_done

        label art:
            e "You chose art."

            e "Really good background art is hard to make, which is why so many games use filtered photographs. Maybe you can change that."

            jump imagemap_done

        label home:

            e "You chose to go home."

            jump imagemap_done

        label imagemap_done:

            e "Anyway..."

    window show None
    window auto

    e "To demonstrate how imagemaps are put together, I'll show you the five images that make up a smaller imagemap."

    show imagemap volume idle:
        xalign 0.5 ypos 50
    with dissolve

    e "The idle image is used for the background of the imagemap, for hotspot buttons that aren't focused or selected, and for the empty part of an unfocused bar."

    show imagemap volume hover:
        xalign 0.5 ypos 50
    with dissolve

    e "The hover image is used for hotspots that are focused but not selected, and for the empty part of a focused bar."

    e "Notice how both the bar and button are highlighted in this image. When we display them as part of a screen, only one of them will show up as focused."

    show imagemap volume selected_idle:
        xalign 0.5 ypos 50
    with dissolve

    e "Selected images like this selected_idle image are used for parts of the bar that are filled, and for selected buttons, like the current screen and a checked checkbox."

    show imagemap volume selected_hover:
        xalign 0.5 ypos 50
    with dissolve

    e "Here's the selected_hover image. The button here will never be shown, since it will never be marked as selected."

    show imagemap volume insensitive:
        xalign 0.5 ypos 50
    with dissolve

    e "Finally, an insensitive image can be given, which is used when a hotspot can't be interacted with."

    hide imagemap
    with dissolve

    e "Imagemaps aren't limited to just images. Any displayable can be used where an image is expected."

    example large:
        screen volume_imagemap_example():
            imagemap:
                xalign 0.5 ypos 50
                idle "imagemap volume idle"
                hover "imagemap volume hover"
                selected_idle "imagemap volume selected_idle"
                selected_hover "imagemap volume selected_hover"
                insensitive "imagemap volume insensitive"

                hotspot (237, 171, 126, 50) action Return(True)
                hotbar (51, 96, 498, 52) value Preference("music volume")

    e "Here's an imagemap built using those five images. Now that it's an imagemap, you can interact with it if you want to."

    example large:
        screen volume_imagemap_auto_example():
            imagemap:
                xalign 0.5 ypos 50
                auto "imagemap volume %s"

                hotspot (237, 171, 126, 50) action Return(True)
                hotbar (51, 96, 498, 52) value Preference("music volume")


    e "To make this a little more concise, we can replace the five images with the auto property, which replaces '%%s' with 'idle', 'hover', 'selected_idle', 'selected_hover', or 'insensitive' as appropriate."

    e "Feel free to omit the selected and insensitive images if your game doesn't need them. Ren'Py will use the idle or hover images to replace them."

    e "The hotspot and hotbar statements describe areas of the imagemap that should act as buttons or bars, respectively."

    e "Both take the coordinates of the area, in (x, y, width, height) format."

    e "A hotspot takes an action that is run when the hotspot is activated. It can also take actions that are run when it's hovered and unhovered, just like a button can."

    e "A hotbar takes a BarValue object that describes how full the bar is, and the range of values the bar should display, just like a bar and vbar does."


    hide screen volume_imagemap_auto_example
    show example imagemap
    with dissolve

    e "A useful pattern is to define a screen with an imagemap that has hotspots that jump to labels, and call that using the call screen statement."

    e "That's what we did in the school example I showed before. Here's the script for it. It's long, but the imagemap itself is fairly simple."

    hide example

    e "Imagemaps have pluses and minuses. On one hand, they are easy for a designer to create, and can look very good. At the same time, they can be hard to translate, and text baked into images may be blurry when the window is scaled."

    e "It's up to you and your team to decide if imagemaps are right for your project."

    return


label viewport_displayables:

    e "Sometimes, you'll want to display something bigger than the screen. That's what the viewport displayable is for."

    example large:
        screen viewport_screen():

            viewport:
                xalign 0.5 ypos 50 xysize (700, 300)

                draggable True
                mousewheel True
                arrowkeys True

                add "bg band"

    with dissolve

    e "Here's an example of a simple viewport, used to display a single image that's far bigger than the screen. Since the viewport will expand to the size of the screen, we use the xysize property to make it smaller."

    e "By default the viewport can't be moved, so we give the draggable, mousewheel, and arrowkeys properties to allow it to be moved in multiple ways."

    example large:
        screen edgescroll_viewport_screen():

            viewport:
                xalign 0.5 ypos 50 xysize (700, 300)

                edgescroll (150, 500)
                mousewheel True
                arrowkeys True

                add "bg band"


    e "When I give the viewport the edgescroll property, the viewport automatically scrolls when the mouse is near its edges. The two numbers are the size of the edges, and the speed in pixels per second."

    example large:
        screen scrollbar_viewport_screen():

            viewport:
                xalign 0.5 ypos 50 xysize (700, 300)

                scrollbars "both"
                spacing 5

                draggable True
                mousewheel True
                arrowkeys True

                add "bg band"

    with dissolve

    e "Giving the viewport the scrollbars property surrounds it with scrollbars. The scrollbars property can take 'both', 'horizontal', and 'vertical' as values."

    e "The spacing property controls the space between the viewport and its scrollbars, in pixels."


    example large:
        screen initial_viewport_screen():

            viewport:
                xalign 0.5 ypos 50 xysize (700, 300)

                xinitial 0.5
                yinitial 1.0

                scrollbars "both"
                spacing 5

                draggable True
                mousewheel True
                arrowkeys True

                add "bg band"

    with dissolve

    e "The xinitial and yinitial properties set the initial amount of scrolling, as a fraction of the amount that can be scrolled."

    example large:
        screen vpgrid_screen():

            vpgrid:
                cols 6
                rows 4

                xalign 0.5 ypos 50 xysize (700, 300)

                child_size (1000, None)

                scrollbars "both"
                side_spacing 5

                draggable True
                mousewheel True
                arrowkeys True

                for i in range(6 * 4):
                    add "logo base"


    with dissolve

    e "Finally, there's the vpgrid displayable. It combines a viewport and a grid into a single displayable, except it's more efficient than either, since it doesn't have to draw every child."

    e "It takes the cols and rows properties, which give the number of rows and columns of children. If one is omitted, Ren'Py figures it out from the other and the number of children."


    hide example

    return