Tutorial: Creating your own window handlers

This tutorial describes how you can create your own window handlers for any windows that you use for your scene. Some other environments call them “event listeners”. For more information you can read the wiki article on the general concept.

Handlers allow the window to communicate with the scene. For example, when you’re in the item menu and selecting an item to use, when you press the OK button, the item window will tell the scene that the OK button was triggered, and the scene calls the “on_item_ok” method accordingly.

But how does the window know that it has an OK handler?
And how does the window know what method to call?

This tutorial will answer the two questions, and you should be able to create your own custom handlers.

Assigning Handlers

Handlers are usually assigned to windows in the scene, using the `set_handler` method. This method is defined as follows in Window_Selectable:

#--------------------------------------------------------------------------
# * Set Handler Corresponding to Operation
#     method : Method set as a handler (Method object)
#--------------------------------------------------------------------------
def set_handler(symbol, method)
  @handler[symbol] = method
end

The symbol is just any name you want to give for your handler.
The method is the method that will be called when this handler is called.

Look at how Scene_Item creates the item window:

def create_item_window
  wy = @category_window.y + @category_window.height
  wh = Graphics.height - wy
  @item_window = Window_ItemList.new(0, wy, Graphics.width, wh)
  @item_window.viewport = @viewport
  @item_window.help_window = @help_window
  @item_window.set_handler(:ok,     method(:on_item_ok))
  @item_window.set_handler(:cancel, method(:on_item_cancel))
  @category_window.item_window = @item_window
end

The important part is these two lines:

@item_window.set_handler(:ok,     method(:on_item_ok))
@item_window.set_handler(:cancel, method(:on_item_cancel))

The scene assigns two handlers to the item window, an “ok” handler, which will call the scene’s “on_item_ok” method, as well as a “cancel” handler, which will call the “on_item_cancel” method. Both of these methods are defined in the scene.

The way these handlers are called is done in the `process_handling` method in Window_Selectable:

def process_handling
  return unless open? && active
  return process_ok       if ok_enabled?        && Input.trigger?(:C)
  return process_cancel   if cancel_enabled?    && Input.trigger?(:B)
  return process_pagedown if handle?(:pagedown) && Input.trigger?(:R)
  return process_pageup   if handle?(:pageup)   && Input.trigger?(:L)
end

You can see that the selectable window checks for four types of handles, depending on which button is pressed. If you press the “C” button, it will call the method associated with the “ok” handler. If you press the “B” button, it will call the method that is associated with the “cancel” handler.

Creating your own handler

What you have seen above is basically all there is to handlers: the scene assigns some handlers to the window, giving the handler a name and a callback method, and the window then checks whether any of the handlers are called and calls the appropriate method attached to the handler.

The steps for creating your handlers is summarized below.

1. Choose a name for your handler. Something intuitive would be nice.

2. Decide how you want this handler to be triggered. It can be a keypress, or any other boolean expression. For example, maybe you want a handler to be triggered every 5 seconds by checking some sort of timer.

3. Decide what methods will be triggered for each handler.

4. Call `set_handler` and assign a handler to your window, using the name and method that you picked above.

5. add the handling logic inside `process_handling` to your window according to what you have decided in step 2.

Following this procedure, you should be able to easily define custom handlers for your windows.

Checking active window

One thing to be careful of is to remember that you must check whether the window is open and active. If you look at the process_handling method, you will notice that the first line is to check whether it is open and active.

You must remember to check this otherwise your handlers may not behave correctly.

Example

Here is a working example that adds custom handlers to the item window in the item scene that will be triggered whenever you press the left or right keys. I use the procedure described above.

1. Decide on handler names

Since the handlers will be triggered when I press the left or right keys, I will just call them `:left` and `:right`

2. Decide how the handlers are triggered

They will be triggered when I press the left or right keys. This can be accomplished using the following calls:

if Input.trigger?(:LEFT)
if Input.trigger?(:RIGHT)

3. Decide what methods will be triggered

For demonstration purposes, I will simply print out “left” or “right” to the console, depending on which key I pressed.

def on_item_left
  p 'LEFT'
  @item_window.activate
end

def on_item_right
  p 'RIGHT'
  @item_window.activate
end

4. Assign the handlers to the window

This is straightforward enough at this point. Just calling the set_handler method and assigning the two handlers as required:

@item_window.set_handler(:left,   method(:on_item_left))
@item_window.set_handler(:right,   method(:on_item_right))

5. Add the handling logic to the window

This is also pretty much just copying what you see from the default method

return call_handler(:left) if handle?(:left) && Input.trigger?(:LEFT)
return call_handler(:right) if handle?(:right) && Input.trigger?(:RIGHT)

It is not necessary to check whether the handlers are defined if you are using a custom window because chances are they will be defined. Window_Selectable is only written that way because you may have windows that do not assign all of those handlers.

At this point, if you load up your game, add some items to your inventory, and then scroll through your item list, you should see the appropriate string printed out to the console if you press left or right.

Here is the full code:

class Scene_Item < Scene_ItemBase

  alias :th_input_handler_create_item_window :create_item_window
  def create_item_window
    th_input_handler_create_item_window
    @item_window.set_handler(:left,   method(:on_item_left))
    @item_window.set_handler(:right,   method(:on_item_right))
  end

  def on_item_left
    p 'LEFT'
    @item_window.activate
  end

  def on_item_right
    p 'RIGHT'
    @item_window.activate
  end
end

class Window_ItemList < Window_Selectable

  alias :th_input_handler_process_handling :process_handling
  def process_handling
    return unless open? && active
    th_input_handler_process_handling
    return call_handler(:left) if handle?(:LEFT) && Input.trigger?(:LEFT)
    return call_handler(:right) if handle?(:RIGHT) && Input.trigger?(:RIGHT)
  end
end

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *