lib/fusuma/plugin/detectors/pinch_detector.rb in fusuma-2.0.0.pre vs lib/fusuma/plugin/detectors/pinch_detector.rb in fusuma-2.0.0.pre2
- old
+ new
@@ -1,133 +1,184 @@
# frozen_string_literal: true
-require_relative './detector.rb'
+require_relative './detector'
module Fusuma
module Plugin
module Detectors
class PinchDetector < Detector
+ SOURCES = ['gesture'].freeze
BUFFER_TYPE = 'gesture'
GESTURE_RECORD_TYPE = 'pinch'
FINGERS = [2, 3, 4].freeze
- BASE_THERESHOLD = 0.1
- BASE_INTERVAL = 0.1
+ BASE_THERESHOLD = 1.3
# @param buffers [Array<Buffer>]
- # @return [Event] if event is detected
+ # @return [Events::Event] if event is detected
# @return [NilClass] if event is NOT detected
def detect(buffers)
- buffer = buffers.find { |b| b.type == BUFFER_TYPE }
- .select_by_events { |e| e.record.gesture == GESTURE_RECORD_TYPE }
+ gesture_buffer = buffers.find { |b| b.type == BUFFER_TYPE }
+ .select_from_last_begin
+ .select_by_events { |e| e.record.gesture == GESTURE_RECORD_TYPE }
- return if buffer.empty?
+ updating_events = gesture_buffer.updating_events
+ return if updating_events.empty?
- finger = buffer.finger
+ finger = gesture_buffer.finger
- avg_zoom = buffer.avg_attrs(:zoom)
- first_zoom = buffer.events.first.record.direction.zoom
- diameter = avg_zoom / first_zoom
+ status = case gesture_buffer.events.last.record.status
+ when 'end'
+ 'end'
+ when 'update'
+ if updating_events.length == 1
+ 'begin'
+ else
+ 'update'
+ end
+ else
+ gesture_buffer.events.last.record.status
+ end
- direction = Direction.new(diameter: diameter).to_s
- quantity = Quantity.new(diameter: diameter).to_f
+ prev_event, event = if status == 'end'
+ [
+ gesture_buffer.events[-3],
+ gesture_buffer.events[-2]
+ ]
+ else
+ [
+ gesture_buffer.events[-2],
+ gesture_buffer.events[-1]
+ ]
+ end
+ delta = event.record.delta
+ prev_delta = prev_event.record.delta
- index = create_index(gesture: type,
- finger: finger,
- direction: direction)
+ repeat_direction = Direction.new(target: delta.zoom, base: (prev_delta&.zoom || 1.0)).to_s
+ # repeat_quantity = Quantity.new(target: delta.zoom, base: (prev_delta&.zoom || 1.0)).to_f
- return unless enough?(index: index, quantity: quantity)
+ repeat_index = create_repeat_index(gesture: type, finger: finger,
+ direction: repeat_direction,
+ status: status)
+ if status == 'update'
+ return unless moved?(prev_event, event)
- create_event(record: Events::Records::IndexRecord.new(index: index))
+ avg_zoom = gesture_buffer.avg_attrs(:zoom)
+ first_zoom = updating_events.first.record.delta.zoom
+
+ oneshot_quantity = Quantity.new(target: avg_zoom, base: first_zoom).to_f
+ oneshot_direction = Direction.new(target: avg_zoom, base: first_zoom).to_s
+ oneshot_index = create_oneshot_index(gesture: type, finger: finger,
+ direction: oneshot_direction)
+ if enough_oneshot_threshold?(index: oneshot_index, quantity: oneshot_quantity)
+ return [
+ create_event(record: Events::Records::IndexRecord.new(
+ index: oneshot_index, trigger: :oneshot, args: delta.to_h
+ )),
+ create_event(record: Events::Records::IndexRecord.new(
+ index: repeat_index, trigger: :repeat, args: delta.to_h
+ ))
+ ]
+ end
+ end
+ create_event(record: Events::Records::IndexRecord.new(
+ index: repeat_index, trigger: :repeat, args: delta.to_h
+ ))
end
# @param [String] gesture
# @param [Integer] finger
# @param [String] direction
+ # @param [String] status
# @return [Config::Index]
- def create_index(gesture:, finger:, direction:)
+ def create_repeat_index(gesture:, finger:, direction:, status:)
Config::Index.new(
[
Config::Index::Key.new(gesture),
+ Config::Index::Key.new(finger.to_i),
+ Config::Index::Key.new(direction, skippable: true),
+ Config::Index::Key.new(status)
+ ]
+ )
+ end
+
+ # @param [String] gesture
+ # @param [Integer] finger
+ # @param [String] direction
+ # @return [Config::Index]
+ def create_oneshot_index(gesture:, finger:, direction:)
+ Config::Index.new(
+ [
+ Config::Index::Key.new(gesture),
Config::Index::Key.new(finger.to_i, skippable: true),
Config::Index::Key.new(direction)
]
)
end
private
- def enough?(index:, quantity:)
- enough_interval?(index: index) && enough_diameter?(index: index, quantity: quantity)
+ def moved?(prev_event, event)
+ zoom_delta = (event.record.delta.zoom - prev_event.record.delta.zoom).abs
+ updating_time = (event.time - prev_event.time) * 100
+ zoom_delta / updating_time > 0.01
end
- def enough_diameter?(index:, quantity:)
+ def enough_oneshot_threshold?(index:, quantity:)
quantity >= threshold(index: index)
end
- def enough_interval?(index:)
- return true if first_time?
- return true if (Time.now - last_time) > interval_time(index: index)
-
- false
- end
-
def threshold(index:)
@threshold ||= {}
@threshold[index.cache_key] ||= begin
- keys_specific = Config::Index.new [*index.keys, 'threshold']
- keys_global = Config::Index.new ['threshold', type]
- config_value = Config.search(keys_specific) ||
- Config.search(keys_global) || 1
- BASE_THERESHOLD * config_value
- end
+ keys_specific = Config::Index.new [*index.keys, 'threshold']
+ keys_global = Config::Index.new ['threshold', type]
+ config_value = Config.search(keys_specific) ||
+ Config.search(keys_global) || 1
+ BASE_THERESHOLD * config_value
+ end
end
- def interval_time(index:)
- @interval_time ||= {}
- @interval_time[index.cache_key] ||= begin
- keys_specific = Config::Index.new [*index.keys, 'interval']
- keys_global = Config::Index.new ['interval', type]
- config_value = Config.search(keys_specific) ||
- Config.search(keys_global) || 1
- BASE_INTERVAL * config_value
- end
- end
-
# direction of gesture
class Direction
IN = 'in'
OUT = 'out'
- def initialize(diameter:)
- @diameter = diameter
+ def initialize(target:, base:)
+ @target = target.to_f
+ @base = base.to_f
end
def to_s
calc
end
def calc
- if @diameter > 1
+ if @target > @base
IN
else
OUT
end
end
end
# quantity of gesture
class Quantity
- def initialize(diameter:)
- @diameter = diameter
+ def initialize(target:, base:)
+ @target = target.to_f
+ @base = base.to_f
end
def to_f
calc.to_f
end
def calc
- (1.0 - @diameter).abs
+ if @target > @base
+ @target / @base
+ else
+ @base / @target
+ end
end
end
end
end
end