Skip to content
Feniks Development
  • Start Here
  • Glossary
  • Tools
  • Resources
  • What’s New
  • About
  • Contact
Toggle the button to expand or collapse the Menu

KeyController and focused_on

  1. Home>
  2. Feniks Tools>
  3. KeyController and focused_on

Easy Blinking

  • EasyBlink Class
  • EasyBlink Examples

Controller Support Expansion

  • What is the Controller Support Expansion?
  • How do I…? + Common Issues
  • Controller Viewport
  • Controller Bar
  • Virtual Cursor
  • Virtual Keyboard
  • StickEvent
  • KeyController and focused_on
  • FocusDisplayable
  • Remapping Controls
  • Controller and Keyboard Icons
  • Configuration Variables
  • Screen Actions and Values
  • Helper Functions and Classes
  • Engine Override Notes

Sound Disabler and Captions Tool

  • Disabling Sounds and Sound Categorization
View Categories
  • Home
  • Feniks Tools
  • Controller Support Expansion
  • KeyController and focused_on

KeyController and focused_on

3 min read

Controller Support Expansion for Ren’Py includes several features to improve controller and keyboard support in Ren’Py. Pick up the tool from itch.io if you haven’t already:

Contents hide
Examples
Example 1
Example 2
Example 3
Properties
key
action
activate_sound
capture

The KeyController is a special class which helps declare relationships between buttons. It can be provided instructions like “if the player is focused on the button with ID "desk" and presses right, focus on the button with the ID "bed". It helps to fix focus problems, like Ren’Py focusing the wrong button when you’re navigating the UI, or skipping over buttons in hbox or vbox. If you’re wondering how to fix focus issues or add extra functionality to your buttons, the KeyController is a great solution.

Examples

The format to set up a KeyController is:

focused_on "DISPLAYABLE_ID" key "SOME_EVENT" action SomeAction()

In this case, "DISPLAYABLE_ID" should be the ID of a displayable in the screen. You assign IDs to displayables with the id property e.g. textbutton "Hello" id "my_hello_id". In order for the rest of the code to run, the displayable with the provided ID must be the currently focused one.

Next, "SOME_EVENT" will be an event or list of events as seen in Customizing the Keymap. Some examples are event names like "focus_left" (which covers any keyboard or controller presses which focus something to the left) or direct key presses like "K_DELETE". It can also be a list of either of these e.g. [ "toggle_skip", "pad_leftshoulder_press" ].

Finally, SomeAction() is any screen action you want to execute when the provided conditions are met (aka that Ren’Py is both currently focused on the displayable with the provided ID, and the provided event occurred).

Example 1

Let’s look at a full example, with the screen and everything. Say you have an image like the following:

An image of a gray bedroom with a bed on the left and a desk on the right.
Image from sigelus on itch.io

You can find the image from sigelus on itch.io here.

Let’s say that the horse picture above the desk and the bed on the left are buttons that can be interacted with.

screen bedroom():
    add "backgrounds/bedroom_day.jpg"
    imagebutton:
        id "horse"
        auto "bedroom/horse_image_%s.png"
        action Jump("view_horse_picture")
    imagebutton:
        id "bed"
        auto "bedroom/bed_%s.png"
        action Jump("go_to_bed")
An image of a bedroom. The bed on the left and horse image on the right are highlighted in red.

Let’s say that Ren’Py does not seem to want to focus the bed when you hit left while focused on the horse image. You can use focused_on to define that relationship:

screen bedroom():
    add "backgrounds/bedroom_day.jpg"
    imagebutton:
        id "horse"
        auto "bedroom/horse_image_%s.png"
        action Jump("view_horse_picture")
    imagebutton:
        id "bed"
        auto "bedroom/bed_%s.png"
        action Jump("go_to_bed")

    focused_on "horse" key "focus_left" action SetFocus("bedroom", "bed")

Example 2

You can also use the KeyController to do other special actions when particular buttons are pressed; say, for example, you have it set up so that pressing the “i” key on the keyboard or Y key on a controller while focused on a button will investigate it:

screen bedroom():
    add "backgrounds/bedroom_day.jpg"
    imagebutton:
        id "horse"
        auto "bedroom/horse_image_%s.png"
        action Jump("view_horse_picture")
    imagebutton:
        id "bed"
        auto "bedroom/bed_%s.png"
        action Jump("go_to_bed")

    focused_on "horse" key "focus_left" action SetFocus("bedroom", "bed")

    focused_on "horse" key ["K_i", "pad_y_press"] action Jump("investigate_horse")
    focused_on "bed" key ["K_i", "pad_y_press"] action Jump("investigate_bed")

You can add multiple focused_on key + action combos for the same ID, as seen above where there are two for the “horse” ID. This works because the events they are listening for are different.

Example 3

screen preferences():
    ## ... full screen omitted
    focused_on "pick_icons" key "focus_left" action CycleControllerLayout(reverse=True)
    focused_on "pick_icons" key "focus_right" action CycleControllerLayout(reverse=False)

This means that when the button with the ID "pick_icons" is focused, and the left arrow key or controller D-pad/stick is moved, it will run the action CycleControllerLayout(reverse=True) which cycles through the different controller layouts in reverse. The same happens for hitting right while focused on the "pick_icons" button, but it cycles normally (not in reverse order).

Properties

The full list of properties used by the KeyController are listed below.

key

This should be a string or a list of such strings corresponding to event names. See Customizing the Keymap in the docs for valid event names.

Note that this class does not convert custom gamepad events to their remapped format, so you may need to use the pad_config.get_event function to convert it e.g. key pad_config.get_event("investigate").

action

The action or a list of actions to execute if the provided event occurs while focused on a displayable with the given ID. e.g. action Notify("You pressed the button")

activate_sound

Optional. A sound to play when the action is triggered. e.g. activate_sound "oof.ogg"

capture

Optional. If True, the default, the KeyController will ignore the event afterwards, preventing it from being passed along to the rest of the UI. If False, the event will be passed along to the rest of the UI after executing the action. e.g. capture False

Updated on February 9, 2025
StickEventFocusDisplayable

Leave a Reply Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

© Copyright – Feniks with OceanWP
Close Menu