Class: Zif::Services::InputService

Inherits:
Object
  • Object
show all
Defined in:
lib/zif/services/input_service.rb

Overview

This service keeps track of sprites and other objects interested in responding to clicks and scroll events, and passes the events over to them when they occur.

Specifically, every tick Game will invoke #process_click on this service.

In turn, this calls Clickable#clicked? on all Clickable objects which have been previously registered using #register_clickable.

It expects each clickable object to define a #clicked?(point, kind) method. If the sprite decides it has been clicked, it should return itself from this method. Clicks are passed through to sprites based on their z_index value - if this value is nil, the service considers it to be at the bottom.

#register_scrollable, is analogous to #register_clickable but for the scroll wheel. #scrolled? is expected to be defined, and it receives the mouse point and the direction of scrolling as arguments. Only Camera defines #scrolled? out of the box.

See Also:

Instance Method Summary collapse

Constructor Details

#initializeInputService

Returns a new instance of InputService.



21
22
23
24
# File 'lib/zif/services/input_service.rb', line 21

def initialize
  @last_mouse_bits = 0
  reset
end

Instance Method Details

#process_clickObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

rubocop:disable Metrics/PerceivedComplexity



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
# File 'lib/zif/services/input_service.rb', line 100

def process_click
  return if @clickables.empty?

  @mouse_point = [$args.inputs.mouse.x, $args.inputs.mouse.y]
  process_scroll # Hanging this here for now.  It also needs @mouse_point

  mouse_bits      = $gtk.args.inputs.mouse.button_bits
  mouse_up        = $gtk.args.inputs.mouse.up
  mouse_down      = $gtk.args.inputs.mouse.down # mouse_bits > @last_mouse_bits
  mouse_only_down = mouse_down && !mouse_up

  return unless mouse_down || mouse_up || @expecting_mouse_up.any?

  kind = if mouse_up
           :up
         else
           (mouse_down ? :down : :changed)
         end

  awaiting_clicks = mouse_only_down ? @clickables : @expecting_mouse_up

  # puts "Zif::Services::InputService#process_click: #{@mouse_point} point, #{mouse_bits} bits, kind: #{kind}."
  # puts "                                 #{awaiting_clicks.count} registered"

  awaiting_clicks.each do |clickable|
    # puts "Zif::Services::InputService#process_click: clickable: #{clickable.class} #{clickable} -> #{clickable.rect}"

    clicked_sprite = clickable.clicked?(@mouse_point, kind)
    next unless clicked_sprite

    @expecting_mouse_up |= [clicked_sprite] if mouse_only_down
    break if @absorb_list.include? clickable

    # puts "Zif::Services::InputService#process_click: #{@expecting_mouse_up.length} expecting"
    # puts "Zif::Services::InputService#process_click: -> sprite handled click #{clicked_sprite}"
  end

  @expecting_mouse_up = [] if mouse_up
  @last_mouse_bits = mouse_bits
end

#process_key_eventObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/zif/services/input_service.rb', line 143

def process_key_event
  return if @key_pressables.empty?

  text_keys = $gtk.args.inputs.text
  all_keys = $gtk.args.inputs.keyboard.key_down.truthy_keys

  text_keys << nil if text_keys.empty? && !all_keys.empty?

  text_keys.each do |key|
    @key_pressables.each do |key_pressable|
      # puts "Zif::Services::InputService#process_key_event:#{key} #{all_keys} key_pressable:#{key_pressable.class} #{key_pressable}"
      key_pressable.handle_key(key, all_keys)
    end
  end
  nil
end

#process_scrollObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/zif/services/input_service.rb', line 161

def process_scroll
  return if @scrollables.empty?

  wheel = $gtk.args.inputs.mouse.wheel
  return unless wheel

  wheel_direction = wheel.y.positive? ? :up : :down

  @scrollables.each do |scrollable|
    scrollable.scrolled?(@mouse_point, wheel_direction)
  end
end

#register_clickable(clickable, absorb_click: nil) ⇒ Object

Add a Clickable object to the list of clickables to check every tick. Clickables in this list are sorted by their z_index and checked in descending order. Clickable objects should respond to #clicked?(point, kind) and optionally #absorb_click?

Parameters:

  • clickable (Zif::Clickable)

    A clickable object

  • absorb_click (Boolean) (defaults to: nil)

    Should clickable absorb clicks? If clickable responds to #absorb_click?, this is true by default.



42
43
44
45
46
47
48
49
50
51
52
# File 'lib/zif/services/input_service.rb', line 42

def register_clickable(clickable, absorb_click: nil)
  @clickables << clickable
  @absorb_list << clickable if absorb_click || (clickable.respond_to?(:absorb_click?) && clickable.absorb_click?)
  @clickables.sort! do |a, b|
    next 1 unless a.respond_to?(:z_index)
    next -1 unless b.respond_to?(:z_index)

    b.z_index <=> a.z_index
  end
  clickable
end

#register_key_pressable(key_pressable) ⇒ Object

Add a KeyPressable object to the list of keypressables to check every tick. Keypressable objects should respond to handle_key(key, kind=:down)

Parameters:



64
65
66
67
# File 'lib/zif/services/input_service.rb', line 64

def register_key_pressable(key_pressable)
  @key_pressables << key_pressable
  key_pressable
end

#register_scrollable(scrollable, absorb_scroll = nil) ⇒ Object

TODO:

Add Zif::Scrollable ?

Scrollable objects should respond to #scroll?(point, direction) and optionally #absorb_scroll?



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/zif/services/input_service.rb', line 77

def register_scrollable(scrollable, absorb_scroll=nil)
  @scrollables << scrollable

  if absorb_scroll || (scrollable.respond_to?(:absorb_scroll?) && scrollable.absorb_scroll?)
    @absorb_list << scrollable
  end

  @scrollables.sort! do |a, b|
    next 1 unless a.respond_to?(:z_index)
    next -1 unless b.respond_to?(:z_index)

    b.z_index <=> a.z_index
  end
  scrollable
end

#remove_clickable(clickable) ⇒ Object

Removes an Clickable from the clickables array.

Parameters:



56
57
58
# File 'lib/zif/services/input_service.rb', line 56

def remove_clickable(clickable)
  @clickables.delete(clickable)
end

#remove_key_pressable(key_pressable) ⇒ Object

Removes an KeyPressable from the keypressables array.

Parameters:



71
72
73
# File 'lib/zif/services/input_service.rb', line 71

def remove_key_pressable(key_pressable)
  @key_pressables.delete(key_pressable)
end

#remove_scrollable(scrollable) ⇒ Object

Removes a scrollable from the scrollables array.



94
95
96
# File 'lib/zif/services/input_service.rb', line 94

def remove_scrollable(scrollable)
  @scrollables.delete(scrollable)
end

#resetObject

Resets the list of clickables, scrollables, etc.



27
28
29
30
31
32
33
# File 'lib/zif/services/input_service.rb', line 27

def reset
  @clickables = []
  @scrollables = []
  @absorb_list = []
  @expecting_mouse_up = []
  @key_pressables = []
end