hokusai-zero 0.2.6.pre.pinephone3 → 0.2.6.pre.pinephone5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/hokusai.gemspec +1 -1
- data/ui/examples/keyboard.rb +1 -1
- data/ui/src/hokusai/backends/raylib/config.rb +2 -1
- data/ui/src/hokusai/backends/raylib.rb +51 -24
- data/ui/src/hokusai/backends/sdl2.rb +1 -1
- data/ui/src/hokusai/blocks/keyboard.rb +52 -37
- data/ui/src/hokusai/events/keyboard.rb +2 -0
- data/ui/src/hokusai/events/mouse.rb +10 -8
- data/ui/src/hokusai/events/touch.rb +2 -0
- data/ui/src/hokusai/mounting/loop_entry.rb +1 -1
- data/ui/src/hokusai/painter.rb +12 -6
- data/ui/src/hokusai/types/display.rb +151 -0
- data/ui/src/hokusai/types/mouse.rb +36 -0
- data/ui/src/hokusai/types/primitives.rb +56 -0
- data/ui/src/hokusai/types/touch.rb +181 -0
- data/ui/src/hokusai/types.rb +8 -398
- metadata +5 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: db63632b958a6ee6aaa4322f1e8737f74a74167df845dbbc01b167fc73907305
|
4
|
+
data.tar.gz: 0cceed2907fdf38549b34ddd77e6503a9c504a3b1c6fbc6a14d3adfdab2984a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 277ef8ae488facee7aa4b43e25c7ea0e704343d0364dd2607eeb106deebf3b9529dcdfcd7672d3f291c2598821f6841ee4eac56c9f5b6026115a6e77a1887621
|
7
|
+
data.tar.gz: 0cce59cf2eaa17ff83d3e63f0c77ef7bd3acc8db4d4b07e2fbc0c28fc6f650dd9d7a5d6aa7614e10d07691211c12440be9f1476018b80efaf6688b24694de027
|
data/hokusai.gemspec
CHANGED
data/ui/examples/keyboard.rb
CHANGED
@@ -40,7 +40,7 @@ class KeyboardExample < Hokusai::Block
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
-
Hokusai::Backends::
|
43
|
+
Hokusai::Backends::RaylibBackend.run(KeyboardExample) do |config|
|
44
44
|
config.width = 370
|
45
45
|
config.height = 680
|
46
46
|
config.title = "keyboard example"
|
@@ -5,7 +5,7 @@ module Hokusai::Backends
|
|
5
5
|
attr_accessor :width, :height, :fps,
|
6
6
|
:title, :config_flags, :window_state_flags,
|
7
7
|
:automation_driver, :background, :after_load_cb,
|
8
|
-
:host, :port, :automated, :on_reload, :event_waiting
|
8
|
+
:host, :port, :automated, :on_reload, :event_waiting, :touch
|
9
9
|
|
10
10
|
def initialize
|
11
11
|
@width = 500
|
@@ -22,6 +22,7 @@ module Hokusai::Backends
|
|
22
22
|
@automated = false
|
23
23
|
@on_reload = ->(_){}
|
24
24
|
@event_waiting = false
|
25
|
+
@touch = false
|
25
26
|
end
|
26
27
|
|
27
28
|
def start_automation_driver
|
@@ -113,22 +113,58 @@ module Hokusai::Backends
|
|
113
113
|
end
|
114
114
|
|
115
115
|
def process_input(input)
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
116
|
+
if !config.touch
|
117
|
+
raylib_mouse_pos = Raylib.GetMousePosition
|
118
|
+
raylib_mouse_delta = Raylib.GetMouseDelta
|
119
|
+
|
120
|
+
input.mouse.pos.x = raylib_mouse_pos.x
|
121
|
+
input.mouse.pos.y = raylib_mouse_pos.y
|
122
|
+
input.mouse.delta.x = raylib_mouse_delta.x
|
123
|
+
input.mouse.delta.y = raylib_mouse_delta.y
|
124
|
+
input.mouse.scroll = Raylib.GetMouseWheelMove
|
125
|
+
end
|
126
|
+
|
127
|
+
if config.touch
|
128
|
+
count = Raylib.GetTouchPointCount
|
129
|
+
if count > 0
|
130
|
+
vec = Raylib.GetTouchPosition(0)
|
131
|
+
unless vec.x.zero? && vec.y.zero?
|
132
|
+
input.touch.record(0, vec.x, vec.y)
|
133
|
+
end
|
134
|
+
else
|
135
|
+
input.touch.clear
|
136
|
+
end
|
137
|
+
else
|
138
|
+
{left: 0, middle: 1, right: 2}.each do |key, button_id|
|
139
|
+
|
140
|
+
button = input.mouse.public_send(key)
|
141
|
+
button.clicked = Raylib.IsMouseButtonPressed(button_id)
|
142
|
+
button.down = Raylib.IsMouseButtonDown(button_id)
|
143
|
+
button.released = Raylib.IsMouseButtonReleased(button_id)
|
144
|
+
button.up = Raylib.IsMouseButtonUp(button_id)
|
145
|
+
end
|
146
|
+
end
|
120
147
|
|
121
|
-
|
122
|
-
|
148
|
+
if config.touch
|
149
|
+
if input.touch.touching?
|
150
|
+
token = input.touch.token
|
123
151
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
released = Raylib.IsMouseButtonReleased(button_id)
|
128
|
-
up = Raylib.IsMouseButtonUp(button_id)
|
152
|
+
input.mouse.pos.x = token[:x]
|
153
|
+
input.mouse.pos.y = token[:y]
|
154
|
+
end
|
129
155
|
|
130
|
-
|
131
|
-
|
156
|
+
# translate taps to clicks
|
157
|
+
if input.touch.tapped?
|
158
|
+
input.mouse.left.clicked = true
|
159
|
+
input.mouse.left.down = true
|
160
|
+
input.mouse.left.released = false
|
161
|
+
input.mouse.left.up = false
|
162
|
+
else
|
163
|
+
input.mouse.left.clicked = true
|
164
|
+
input.mouse.left.down = true
|
165
|
+
input.mouse.left.released = false
|
166
|
+
input.mouse.left.up = false
|
167
|
+
end
|
132
168
|
end
|
133
169
|
|
134
170
|
if !input.keyboard_override
|
@@ -155,7 +191,6 @@ module Hokusai::Backends
|
|
155
191
|
self.class.reset
|
156
192
|
|
157
193
|
Raylib.load_lib(RAYLIB_PATH)
|
158
|
-
|
159
194
|
resize = false
|
160
195
|
initial = true
|
161
196
|
width = config.width
|
@@ -168,6 +203,7 @@ module Hokusai::Backends
|
|
168
203
|
raw = LibHokusai::HmlInput.new(ptr.get_pointer(0))
|
169
204
|
input = Hokusai::Input.new(raw)
|
170
205
|
ptr.free
|
206
|
+
input.support_touch! if config.touch
|
171
207
|
|
172
208
|
Raylib.SetConfigFlags(config.config_flags)
|
173
209
|
Raylib.InitWindow(config.width, config.height, config.title)
|
@@ -221,7 +257,7 @@ module Hokusai::Backends
|
|
221
257
|
block.update
|
222
258
|
block.public_send(:after_updated) if block.respond_to?(:after_updated)
|
223
259
|
|
224
|
-
canvas.reset(
|
260
|
+
canvas.reset(0.0, 0.0, width.to_f, height.to_f)
|
225
261
|
|
226
262
|
Raylib.BeginDrawing
|
227
263
|
Raylib.ClearBackground(config.background)
|
@@ -245,7 +281,6 @@ module Hokusai::Backends
|
|
245
281
|
Raylib.DrawFPS(10, 10) if ENV["PROFILE"] || ENV["FPS"]
|
246
282
|
Raylib.EndDrawing
|
247
283
|
|
248
|
-
|
249
284
|
break if self.class.stopped?
|
250
285
|
end
|
251
286
|
|
@@ -351,14 +386,6 @@ module Hokusai::Backends
|
|
351
386
|
Raylib.MinimizeWindow
|
352
387
|
end
|
353
388
|
|
354
|
-
# Hokusai.on_set_shader_value do |location, value, type|
|
355
|
-
# Raylib.SetShaderValue(@shader, location, value, type)
|
356
|
-
# end
|
357
|
-
|
358
|
-
# Hokusai.on_shader_location do |name|
|
359
|
-
# Raylib.GetShaderLocation(@shader, name)
|
360
|
-
# end
|
361
|
-
|
362
389
|
Hokusai.on_renderable do |canvas|
|
363
390
|
inside_scissor(canvas.x, canvas.y, canvas.height)
|
364
391
|
end
|
@@ -162,7 +162,7 @@ module Hokusai::Backends
|
|
162
162
|
SDL.SetRenderDrawBlendMode(renderer, SDL::BLENDMODE_BLEND)
|
163
163
|
SDL.SetRenderDrawColor(renderer, config.background[:r], config.background[:g], config.background[:b], config.background[:a])
|
164
164
|
SDL.RenderClear(renderer)
|
165
|
-
canvas.reset(
|
165
|
+
canvas.reset(0.0, 0.0, render_width.to_f, render_height.to_f)
|
166
166
|
painter = Hokusai::Painter.new(block, input)
|
167
167
|
painter.render(canvas, resize)
|
168
168
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Hokusai::Blocks
|
2
4
|
class Key < Hokusai::Block
|
3
5
|
template <<~EOF
|
@@ -12,17 +14,21 @@ module Hokusai::Blocks
|
|
12
14
|
uses(empty: Hokusai::Blocks::Empty)
|
13
15
|
|
14
16
|
computed! :value
|
15
|
-
computed! :icons
|
16
17
|
computed :size, default: 24, convert: proc(&:to_i)
|
17
18
|
computed :background, default: Hokusai::Color.new(70, 70, 70), convert: Hokusai::Color
|
18
19
|
computed :color, default: Hokusai::Color.new(244, 244, 244), convert: Hokusai::Color
|
19
20
|
computed :background_down, default: Hokusai::Color.new(33,33,33), convert: Hokusai::Color
|
20
21
|
computed :margin, default: Hokusai::Padding.new(3.0, 2.5, 3.0, 2.5), convert: Hokusai::Padding
|
21
22
|
|
22
|
-
|
23
|
+
inject :keyboard_icons
|
24
|
+
|
25
|
+
attr_accessor :down, :last_commands, :last_canvas, :last_value
|
23
26
|
|
24
27
|
def initialize(**args)
|
25
28
|
@down = false
|
29
|
+
@last_commands = []
|
30
|
+
@last_canvas = nil
|
31
|
+
@last_value = nil
|
26
32
|
|
27
33
|
super
|
28
34
|
end
|
@@ -47,25 +53,44 @@ module Hokusai::Blocks
|
|
47
53
|
vpad = (canvas.height - margin.height - size) / 2
|
48
54
|
|
49
55
|
draw do
|
50
|
-
if
|
51
|
-
|
52
|
-
|
53
|
-
command.round = 6.0
|
54
|
-
end
|
56
|
+
if last_canvas != canvas && last_value != value
|
57
|
+
self.last_value = value
|
58
|
+
self.last_canvas = canvas
|
55
59
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
60
|
+
if icon = keyboard_icons[value[0]]
|
61
|
+
if icon[:width]
|
62
|
+
node.meta.set_prop(:width, icon[:width])
|
63
|
+
end
|
64
|
+
|
65
|
+
rect(canvas.x + margin.left, canvas.y + margin.top, canvas.width - margin.width, canvas.height - margin.height) do |command|
|
66
|
+
command.color = icon[:background]# down ? background_down : background
|
67
|
+
command.round = 0.2
|
68
|
+
|
69
|
+
last_commands << command
|
70
|
+
end
|
71
|
+
|
72
|
+
svg(icon[:file], canvas.x + icon[:size] / 3, canvas.y + icon[:size] / 3, icon[:size], icon[:size]) do |command|
|
73
|
+
command.color = icon[:color]
|
74
|
+
|
75
|
+
last_commands << command
|
76
|
+
end
|
77
|
+
else
|
78
|
+
rect(canvas.x + margin.left, canvas.y + margin.top, canvas.width - margin.width, canvas.height - margin.height) do |command|
|
79
|
+
command.color = down ? background_down : background
|
80
|
+
command.round = 0.2
|
64
81
|
|
65
|
-
|
66
|
-
|
67
|
-
|
82
|
+
last_commands << command
|
83
|
+
end
|
84
|
+
|
85
|
+
text(value[1].to_s, canvas.x + hpad + margin.width, canvas.y + margin.height) do |command|
|
86
|
+
command.color = color
|
87
|
+
command.size = size
|
88
|
+
|
89
|
+
last_commands << command
|
90
|
+
end
|
68
91
|
end
|
92
|
+
else
|
93
|
+
queue.concat(last_commands)
|
69
94
|
end
|
70
95
|
end
|
71
96
|
|
@@ -92,9 +117,7 @@ module Hokusai::Blocks
|
|
92
117
|
[for="number in keys"]
|
93
118
|
key {
|
94
119
|
...keyStyle
|
95
|
-
:
|
96
|
-
:icons="icons"
|
97
|
-
:key="loop_key(number)"
|
120
|
+
:key="index"
|
98
121
|
:value="number"
|
99
122
|
@clicked="emit_key"
|
100
123
|
@released="emit_released"
|
@@ -108,20 +131,12 @@ module Hokusai::Blocks
|
|
108
131
|
)
|
109
132
|
|
110
133
|
computed! :keys
|
111
|
-
computed! :icons
|
112
134
|
|
113
|
-
|
114
|
-
# node.meta.set_prop(:height, 48.0)
|
115
|
-
# end
|
116
|
-
|
117
|
-
def width(key)
|
118
|
-
if icon = icons[key[0]]
|
119
|
-
icon[:width]
|
120
|
-
end
|
121
|
-
end
|
135
|
+
inject :keyboard_icons
|
122
136
|
|
123
137
|
def loop_key(value)
|
124
|
-
|
138
|
+
@keys ||= {}
|
139
|
+
@keys[value] ||= "key-#{value}".freeze
|
125
140
|
end
|
126
141
|
|
127
142
|
def emit_key(key, event)
|
@@ -160,8 +175,7 @@ module Hokusai::Blocks
|
|
160
175
|
row: KeyboardRow
|
161
176
|
)
|
162
177
|
|
163
|
-
|
164
|
-
def self.icons
|
178
|
+
def icons
|
165
179
|
{
|
166
180
|
:shift => {
|
167
181
|
file: Hokusai.asset("icons/outline/arrow-big-up.svg"),
|
@@ -180,9 +194,10 @@ module Hokusai::Blocks
|
|
180
194
|
}
|
181
195
|
end
|
182
196
|
|
183
|
-
computed :icons, default: icons
|
184
197
|
computed :row_height, default: 48.0, convert: proc(&:to_f)
|
185
198
|
|
199
|
+
provide :keyboard_icons, :icons
|
200
|
+
|
186
201
|
def on_mounted
|
187
202
|
node.meta.set_prop(:height, row_height * 5.0 + 20)
|
188
203
|
end
|
@@ -210,8 +225,8 @@ module Hokusai::Blocks
|
|
210
225
|
@zxcv_keys ||= begin
|
211
226
|
keys = %w[z x c v b n m]
|
212
227
|
middle = keys.zip(keys)
|
213
|
-
middle << [:backspace, :backspace]
|
214
|
-
middle.unshift([:shift, :shift])
|
228
|
+
# middle << [:backspace, :backspace]
|
229
|
+
# middle.unshift([:shift, :shift])
|
215
230
|
middle
|
216
231
|
end
|
217
232
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Hokusai
|
2
4
|
class MouseEvent < Event
|
3
5
|
extend Forwardable
|
@@ -67,7 +69,7 @@ module Hokusai
|
|
67
69
|
protected
|
68
70
|
|
69
71
|
def hovered(canvas)
|
70
|
-
|
72
|
+
input.hovered?(canvas)
|
71
73
|
end
|
72
74
|
end
|
73
75
|
|
@@ -85,19 +87,19 @@ module Hokusai
|
|
85
87
|
name "click"
|
86
88
|
|
87
89
|
def capture(block, canvas)
|
88
|
-
if left
|
90
|
+
if left.clicked && clicked(canvas)
|
89
91
|
block.node.meta.focus
|
90
92
|
|
91
93
|
if matches(block)
|
92
94
|
captures << block
|
93
95
|
end
|
94
|
-
elsif left
|
96
|
+
elsif left.clicked
|
95
97
|
block.node.meta.blur
|
96
98
|
end
|
97
99
|
end
|
98
100
|
|
99
101
|
def clicked(canvas)
|
100
|
-
|
102
|
+
left.clicked && input.hovered?(canvas)
|
101
103
|
end
|
102
104
|
end
|
103
105
|
|
@@ -105,7 +107,7 @@ module Hokusai
|
|
105
107
|
name "mouseup"
|
106
108
|
|
107
109
|
def capture(block, _)
|
108
|
-
if left
|
110
|
+
if left.up && matches(block)
|
109
111
|
captures << block
|
110
112
|
end
|
111
113
|
end
|
@@ -115,7 +117,7 @@ module Hokusai
|
|
115
117
|
name "mousedown"
|
116
118
|
|
117
119
|
def capture(block, _)
|
118
|
-
if left
|
120
|
+
if left.down && matches(block)
|
119
121
|
captures << block
|
120
122
|
end
|
121
123
|
end
|
@@ -168,13 +170,13 @@ module Hokusai
|
|
168
170
|
def capture(block, canvas)
|
169
171
|
captures << block if matches(block)
|
170
172
|
|
171
|
-
if left
|
173
|
+
if left.clicked && !clicked(canvas)
|
172
174
|
block.node.meta.blur
|
173
175
|
end
|
174
176
|
end
|
175
177
|
|
176
178
|
def clicked(canvas)
|
177
|
-
|
179
|
+
left.clicked && input.hovered?(canvas)
|
178
180
|
end
|
179
181
|
end
|
180
182
|
end
|
@@ -65,7 +65,7 @@ module Hokusai
|
|
65
65
|
|
66
66
|
portal = Node.new(ast)
|
67
67
|
node = child_block_class.compile(ast.type, portal)
|
68
|
-
child_block = child_block_class.new(node: node)
|
68
|
+
child_block = child_block_class.new(node: node, providers: mount_providers)
|
69
69
|
child_block.node.add_styles(target.class)
|
70
70
|
child_block.node.add_props_from_block(target, context: ctx)
|
71
71
|
child_block.node.meta.set_prop(ast.loop.var.to_sym, value)
|
data/ui/src/hokusai/painter.rb
CHANGED
@@ -96,7 +96,7 @@ module Hokusai
|
|
96
96
|
root_entry = PainterEntry.new(root, canvas.x, canvas.y, canvas.width, canvas.height)
|
97
97
|
groups << [root_entry, measure(root_children, canvas)]
|
98
98
|
|
99
|
-
mouse_y = input.mouse.pos
|
99
|
+
mouse_y = input.mouse.pos.y
|
100
100
|
can_capture = mouse_y >= (canvas.y || 0.0) && mouse_y <= (canvas.y || 0.0) + canvas.height
|
101
101
|
|
102
102
|
hovered = false
|
@@ -110,7 +110,6 @@ module Hokusai
|
|
110
110
|
while group = group_children.shift
|
111
111
|
z = group.block.node.meta.get_prop(:z)&.to_i || 0
|
112
112
|
ztarget = group.block.node.meta.get_prop(:ztarget)
|
113
|
-
entry = PainterEntry.new(group.block, group.x, group.y, group.w, group.h)
|
114
113
|
|
115
114
|
if (zindex_counter > 0 || z > 0)
|
116
115
|
case ztarget
|
@@ -118,9 +117,14 @@ module Hokusai
|
|
118
117
|
entry = PainterEntry.new(group.block, zroot_x || 0.0, zroot_y || 0.0, zroot_w, zroot_h).freeze
|
119
118
|
when ZTARGET_PARENT
|
120
119
|
entry = PainterEntry.new(group.block, group_parent.x || 0.0, group_parent.y || 0.0, group_parent.w, group_parent.h).freeze
|
120
|
+
else
|
121
|
+
entry = PainterEntry.new(group.block, group.x, group.y, group.w, group.h).freeze
|
121
122
|
end
|
123
|
+
else
|
124
|
+
entry = PainterEntry.new(group.block, group.x, group.y, group.w, group.h).freeze
|
122
125
|
end
|
123
126
|
|
127
|
+
|
124
128
|
canvas.reset(entry.x, entry.y, entry.w, entry.h)
|
125
129
|
|
126
130
|
before_render&.call([group.block, group.parent], canvas, input.raw)
|
@@ -263,10 +267,12 @@ module Hokusai
|
|
263
267
|
return
|
264
268
|
end
|
265
269
|
|
266
|
-
|
267
|
-
|
270
|
+
|
271
|
+
|
272
|
+
# rect = canvas.to_hoku_rect
|
273
|
+
# block_is_hovered = LibHokusai.hoku_input_is_hovered(input.raw, rect)
|
268
274
|
|
269
|
-
if
|
275
|
+
if input.hovered?(canvas)
|
270
276
|
events[:hover].capture(block, canvas)
|
271
277
|
events[:click].capture(block, canvas)
|
272
278
|
events[:wheel].capture(block, canvas)
|
@@ -277,7 +283,7 @@ module Hokusai
|
|
277
283
|
end
|
278
284
|
events[:mousemove].capture(block, canvas)
|
279
285
|
|
280
|
-
if
|
286
|
+
if input.hovered?(canvas) || block.node.meta.focused || input.keyboard_override
|
281
287
|
events[:keyup].capture(block, canvas)
|
282
288
|
events[:keypress].capture(block, canvas)
|
283
289
|
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Hokusai
|
4
|
+
Outline = Struct.new(:top, :right, :bottom, :left) do
|
5
|
+
def self.default
|
6
|
+
new(0.0, 0.0, 0.0, 0.0)
|
7
|
+
end
|
8
|
+
|
9
|
+
def hash
|
10
|
+
[self.class, top, right, bottom, left].hash
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.convert(value)
|
14
|
+
case value
|
15
|
+
when String
|
16
|
+
if value =~ /,/
|
17
|
+
convert(value.split(",").map(&:to_f))
|
18
|
+
else
|
19
|
+
convert(value.to_f)
|
20
|
+
end
|
21
|
+
when Float
|
22
|
+
new(value, value, value, value)
|
23
|
+
when Array
|
24
|
+
new(value[0] || 0.0, value[1] || 0.0, value[2] || 0.0, value[3] || 0.0)
|
25
|
+
when Outline
|
26
|
+
value
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def present?
|
31
|
+
top > 0.0 || right > 0.0 || bottom > 0.0 || left > 0.0
|
32
|
+
end
|
33
|
+
|
34
|
+
def uniform?
|
35
|
+
top == right && top == bottom && top == left
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class Padding
|
40
|
+
attr_reader :top, :left, :right, :bottom
|
41
|
+
def initialize(top, right, bottom, left)
|
42
|
+
@top = top
|
43
|
+
@left = left
|
44
|
+
@right = right
|
45
|
+
@bottom = bottom
|
46
|
+
end
|
47
|
+
|
48
|
+
alias_method :t, :top
|
49
|
+
alias_method :l, :left
|
50
|
+
alias_method :r, :right
|
51
|
+
alias_method :b, :bottom
|
52
|
+
|
53
|
+
def width
|
54
|
+
right + left
|
55
|
+
end
|
56
|
+
|
57
|
+
def height
|
58
|
+
top + bottom
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.convert(value)
|
62
|
+
case value
|
63
|
+
when String
|
64
|
+
if value =~ /,/
|
65
|
+
convert(value.split(",").map(&:to_f))
|
66
|
+
else
|
67
|
+
convert(value.to_i)
|
68
|
+
end
|
69
|
+
when Integer
|
70
|
+
new(value, value, value, value)
|
71
|
+
when Array
|
72
|
+
new(value[0], value[1], value[2], value[3])
|
73
|
+
when Padding
|
74
|
+
value
|
75
|
+
else
|
76
|
+
raise Hokusai::Error.new("Unsupported conversion type #{value.class} for Hokusai::Padding")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def hash
|
81
|
+
[self.class, top, right, bottom, left].hash
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
class Canvas
|
86
|
+
attr_accessor :width, :height, :x, :y, :vertical, :reverse
|
87
|
+
def initialize(width, height, x = 0.0, y = 0.0, vertical = true, reverse = false)
|
88
|
+
@width = width
|
89
|
+
@height = height
|
90
|
+
@x = x
|
91
|
+
@y = y
|
92
|
+
@vertical = vertical
|
93
|
+
@reverse = reverse
|
94
|
+
end
|
95
|
+
|
96
|
+
def reset(x, y, width, height, vertical: true, reverse: false)
|
97
|
+
self.x = x
|
98
|
+
self.y = y
|
99
|
+
self.width = width
|
100
|
+
self.height = height
|
101
|
+
self.vertical = vertical
|
102
|
+
self.reverse = reverse
|
103
|
+
end
|
104
|
+
|
105
|
+
def to_bounds
|
106
|
+
Hokusai::Rect.new(x, y, width, height)
|
107
|
+
end
|
108
|
+
|
109
|
+
def hovered?(input)
|
110
|
+
input.hovered?(self)
|
111
|
+
end
|
112
|
+
|
113
|
+
def reverse?
|
114
|
+
reverse
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Color = Struct.new(:red, :green, :blue, :alpha) do
|
119
|
+
class Color
|
120
|
+
attr_reader :red, :green, :blue, :alpha
|
121
|
+
def initialize(red, green, blue, alpha = 255)
|
122
|
+
@red = red.freeze
|
123
|
+
@green = green.freeze
|
124
|
+
@blue = blue.freeze
|
125
|
+
@alpha = alpha.freeze
|
126
|
+
end
|
127
|
+
|
128
|
+
alias_method :r, :red
|
129
|
+
alias_method :b, :blue
|
130
|
+
alias_method :g, :green
|
131
|
+
alias_method :a, :alpha
|
132
|
+
|
133
|
+
def self.convert(value)
|
134
|
+
case value
|
135
|
+
when String
|
136
|
+
value = value.split(",").map(&:to_i)
|
137
|
+
when Array
|
138
|
+
when Color
|
139
|
+
return value
|
140
|
+
else
|
141
|
+
raise Hokusai::Error.new("Unsupported conversion type #{value.class} for Hokusai::Color")
|
142
|
+
end
|
143
|
+
|
144
|
+
new(value[0], value[1], value[2], value[3] || 255)
|
145
|
+
end
|
146
|
+
|
147
|
+
def hash
|
148
|
+
[self.class, r, g, b, a].hash
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Hokusai
|
4
|
+
class MouseButton
|
5
|
+
attr_accessor :up, :down, :clicked, :released
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@up = false
|
9
|
+
@down = false
|
10
|
+
@clicked = false
|
11
|
+
@released = false
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Mouse
|
16
|
+
attr_reader :pos, :delta, :left, :right, :middle, :scroll
|
17
|
+
attr_accessor :scroll_delta
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
@pos = Vec2.new(0.0, 0.0)
|
21
|
+
@delta = Vec2.new(0.0, 0.0)
|
22
|
+
@scroll = 0.0
|
23
|
+
@scroll_delta = 0.0
|
24
|
+
@left = MouseButton.new
|
25
|
+
@middle = MouseButton.new
|
26
|
+
@right = MouseButton.new
|
27
|
+
end
|
28
|
+
|
29
|
+
def scroll=(val)
|
30
|
+
last = scroll
|
31
|
+
new_y = (last >= val) ? last - val : val - last
|
32
|
+
self.scroll_delta = new_y
|
33
|
+
@scroll = val
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Hokusai
|
4
|
+
class Vec2
|
5
|
+
attr_accessor :x, :y
|
6
|
+
def initialize(x, y)
|
7
|
+
@x = x
|
8
|
+
@y = y
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Rect
|
13
|
+
attr_accessor :x, :y, :width, :height
|
14
|
+
|
15
|
+
def initialize(x, y, width, height)
|
16
|
+
@x = x
|
17
|
+
@y = y
|
18
|
+
@width = width
|
19
|
+
@height = height
|
20
|
+
end
|
21
|
+
def to_hoku_rect
|
22
|
+
@hoku_rect ||= LibHokusai::HmlRect.create(x, y, width, height)
|
23
|
+
end
|
24
|
+
|
25
|
+
def includes_y?(y)
|
26
|
+
LibHokusai.hoku_rect_includes_y(to_hoku_rect, y)
|
27
|
+
end
|
28
|
+
|
29
|
+
def includes_x?(x)
|
30
|
+
LibHokusai.hoku_rect_includes_x(to_hoku_rect, x)
|
31
|
+
end
|
32
|
+
|
33
|
+
def move_x_left(times = 1)
|
34
|
+
LibHokusai.hoku_rect_x_left(to_hoku_rect, times)
|
35
|
+
end
|
36
|
+
|
37
|
+
def move_x_right(times = 1)
|
38
|
+
LibHokusai.hoku_rect_x_right(to_hoku_rect, times)
|
39
|
+
end
|
40
|
+
|
41
|
+
def move_y_up(times = 1)
|
42
|
+
LibHokusai.hoku_rect_y_up(to_hoku_rect, times)
|
43
|
+
end
|
44
|
+
|
45
|
+
def move_y_down(times = 1)
|
46
|
+
LibHokusai.hoku_rect_y_down(to_hoku_rect, times)
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.from_hoku_rect(rect)
|
50
|
+
self.x = rect[:x]
|
51
|
+
self.y = rect[:y]
|
52
|
+
self.width = rect[:w]
|
53
|
+
self.height = rect[:h]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,181 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Hokusai
|
4
|
+
class Touch
|
5
|
+
attr_accessor :stack, :archive
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@stack = []
|
9
|
+
@archive = []
|
10
|
+
@tapped = false
|
11
|
+
@swiped = false
|
12
|
+
@pinched = false
|
13
|
+
# @file = File.open("touch.log", "w")
|
14
|
+
end
|
15
|
+
|
16
|
+
def tapped?
|
17
|
+
@tapped
|
18
|
+
end
|
19
|
+
|
20
|
+
def swiped?
|
21
|
+
@swiped
|
22
|
+
end
|
23
|
+
|
24
|
+
def pinched?
|
25
|
+
@pinched
|
26
|
+
end
|
27
|
+
|
28
|
+
def longtapping?(stuff = "ok")
|
29
|
+
log("#{touching?} - #{elapsed(token)} - #{stuff}") if touching?
|
30
|
+
touching? && elapsed(token) > 5
|
31
|
+
end
|
32
|
+
|
33
|
+
def longtapped?
|
34
|
+
@longtapped
|
35
|
+
end
|
36
|
+
|
37
|
+
def touching?
|
38
|
+
type == :down || type == :move
|
39
|
+
end
|
40
|
+
|
41
|
+
def duration
|
42
|
+
if longtapping?
|
43
|
+
return elapsed(token)
|
44
|
+
end
|
45
|
+
|
46
|
+
first, last = archive[-2..-1]
|
47
|
+
|
48
|
+
last[:start] - first[:start]
|
49
|
+
end
|
50
|
+
|
51
|
+
def distance
|
52
|
+
raise Hokusai::Error.new("Archive is empty") if archive.empty?
|
53
|
+
first, last = archive[-2..-1]
|
54
|
+
|
55
|
+
x = last[:x] - first[:x]
|
56
|
+
y = last[:y] - first[:y]
|
57
|
+
|
58
|
+
[x, y]
|
59
|
+
end
|
60
|
+
|
61
|
+
def direction
|
62
|
+
raise Hokusai::Error.new("Archive is empty") if archive.empty?
|
63
|
+
|
64
|
+
first, last = archive[-2..-1]
|
65
|
+
|
66
|
+
x = last[:x] - first[:x]
|
67
|
+
y = last[:y] - first[:y]
|
68
|
+
|
69
|
+
if x.abs > y.abs
|
70
|
+
# swiping left/right
|
71
|
+
last[:x] > first[:x] ? :right : :left
|
72
|
+
else
|
73
|
+
# swiping up/down
|
74
|
+
last[:y] > first[:y] ? :down : :up
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def angle
|
79
|
+
raise Hokusai::Error.new("Archive is empty") if archive.empty?
|
80
|
+
|
81
|
+
last, first = archive[-2..-1]
|
82
|
+
|
83
|
+
x = last[:x] - first[:x]
|
84
|
+
y = last[:y] - first[:y]
|
85
|
+
|
86
|
+
(Math.atan2(x, y) * (-180 / Math::PI)).round(0).to_i
|
87
|
+
end
|
88
|
+
|
89
|
+
def log(str)
|
90
|
+
# Thread.new do
|
91
|
+
# @file.write_nonblock("#{str}\n")
|
92
|
+
# end
|
93
|
+
end
|
94
|
+
|
95
|
+
def record(finger, x, y)
|
96
|
+
log("recording #{token}")
|
97
|
+
if type == :down
|
98
|
+
push(:move, finger, x, y)
|
99
|
+
log("state is move")
|
100
|
+
elsif type == :move
|
101
|
+
stack.last[:x] = x
|
102
|
+
stack.last[:y] = y
|
103
|
+
|
104
|
+
log("updated state move")
|
105
|
+
else
|
106
|
+
@longtapped = false
|
107
|
+
@swiped = false
|
108
|
+
@tapped = false
|
109
|
+
push(:down, finger, x, y)
|
110
|
+
log("state is down")
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def clear
|
115
|
+
# log("clearing")
|
116
|
+
if type == :move
|
117
|
+
log("elapsed: #{elapsed(token)}")
|
118
|
+
if elapsed(token) > 300 && within(10.0)
|
119
|
+
@longtapped = true
|
120
|
+
log('longtap')
|
121
|
+
elsif within(10.0)
|
122
|
+
@tapped = true
|
123
|
+
else
|
124
|
+
@swiped = true
|
125
|
+
log('swipe')
|
126
|
+
end
|
127
|
+
elsif type == :down
|
128
|
+
@tapped = true
|
129
|
+
log('tap')
|
130
|
+
else
|
131
|
+
@longtapped = false
|
132
|
+
@swiped = false
|
133
|
+
@tapped = false
|
134
|
+
end
|
135
|
+
|
136
|
+
self.archive = stack.dup
|
137
|
+
stack.clear
|
138
|
+
end
|
139
|
+
|
140
|
+
def elapsed(token)
|
141
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond) - token[:start]
|
142
|
+
end
|
143
|
+
|
144
|
+
def within(threshold)
|
145
|
+
move = stack.last
|
146
|
+
down = stack[-2]
|
147
|
+
|
148
|
+
t1 = (move[:x] - down[:x]).abs
|
149
|
+
t2 = (move[:y] - down[:y]).abs
|
150
|
+
|
151
|
+
t1 < threshold && t2 < threshold
|
152
|
+
end
|
153
|
+
|
154
|
+
def pop
|
155
|
+
stack.pop
|
156
|
+
end
|
157
|
+
|
158
|
+
def push(type, finger, x, y)
|
159
|
+
log("push: #{type}")
|
160
|
+
stack << {
|
161
|
+
type: type,
|
162
|
+
i: finger,
|
163
|
+
x: x,
|
164
|
+
y: y,
|
165
|
+
start: Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
|
166
|
+
}
|
167
|
+
end
|
168
|
+
|
169
|
+
def index
|
170
|
+
token&.[](:finger)
|
171
|
+
end
|
172
|
+
|
173
|
+
def type
|
174
|
+
token&.[](:type)
|
175
|
+
end
|
176
|
+
|
177
|
+
def token
|
178
|
+
@stack.last
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
data/ui/src/hokusai/types.rb
CHANGED
@@ -1,200 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
def initialize(x, y, width, height)
|
9
|
-
@x = x
|
10
|
-
@y = y
|
11
|
-
@width = width
|
12
|
-
@height = height
|
13
|
-
end
|
14
|
-
def to_hoku_rect
|
15
|
-
@hoku_rect ||= LibHokusai::HmlRect.create(x, y, width, height)
|
16
|
-
end
|
17
|
-
|
18
|
-
def includes_y?(y)
|
19
|
-
LibHokusai.hoku_rect_includes_y(to_hoku_rect, y)
|
20
|
-
end
|
21
|
-
|
22
|
-
def includes_x?(x)
|
23
|
-
LibHokusai.hoku_rect_includes_x(to_hoku_rect, x)
|
24
|
-
end
|
25
|
-
|
26
|
-
def move_x_left(times = 1)
|
27
|
-
LibHokusai.hoku_rect_x_left(to_hoku_rect, times)
|
28
|
-
end
|
29
|
-
|
30
|
-
def move_x_right(times = 1)
|
31
|
-
LibHokusai.hoku_rect_x_right(to_hoku_rect, times)
|
32
|
-
end
|
33
|
-
|
34
|
-
def move_y_up(times = 1)
|
35
|
-
LibHokusai.hoku_rect_y_up(to_hoku_rect, times)
|
36
|
-
end
|
37
|
-
|
38
|
-
def move_y_down(times = 1)
|
39
|
-
LibHokusai.hoku_rect_y_down(to_hoku_rect, times)
|
40
|
-
end
|
41
|
-
|
42
|
-
def self.from_hoku_rect(rect)
|
43
|
-
self.x = rect[:x]
|
44
|
-
self.y = rect[:y]
|
45
|
-
self.width = rect[:w]
|
46
|
-
self.height = rect[:h]
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
Outline = Struct.new(:top, :right, :bottom, :left) do
|
51
|
-
def self.default
|
52
|
-
new(0.0, 0.0, 0.0, 0.0)
|
53
|
-
end
|
54
|
-
|
55
|
-
def hash
|
56
|
-
[self.class, top, right, bottom, left].hash
|
57
|
-
end
|
58
|
-
|
59
|
-
def self.convert(value)
|
60
|
-
case value
|
61
|
-
when String
|
62
|
-
if value =~ /,/
|
63
|
-
convert(value.split(",").map(&:to_f))
|
64
|
-
else
|
65
|
-
convert(value.to_f)
|
66
|
-
end
|
67
|
-
when Float
|
68
|
-
new(value, value, value, value)
|
69
|
-
when Array
|
70
|
-
new(value[0] || 0.0, value[1] || 0.0, value[2] || 0.0, value[3] || 0.0)
|
71
|
-
when Outline
|
72
|
-
value
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def present?
|
77
|
-
top > 0.0 || right > 0.0 || bottom > 0.0 || left > 0.0
|
78
|
-
end
|
79
|
-
|
80
|
-
def uniform?
|
81
|
-
top == right && top == bottom && top == left
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
class Padding
|
86
|
-
attr_reader :top, :left, :right, :bottom
|
87
|
-
def initialize(top, right, bottom, left)
|
88
|
-
@top = top
|
89
|
-
@left = left
|
90
|
-
@right = right
|
91
|
-
@bottom = bottom
|
92
|
-
end
|
93
|
-
|
94
|
-
alias_method :t, :top
|
95
|
-
alias_method :l, :left
|
96
|
-
alias_method :r, :right
|
97
|
-
alias_method :b, :bottom
|
98
|
-
|
99
|
-
def width
|
100
|
-
right + left
|
101
|
-
end
|
102
|
-
|
103
|
-
def height
|
104
|
-
top + bottom
|
105
|
-
end
|
106
|
-
|
107
|
-
def self.convert(value)
|
108
|
-
case value
|
109
|
-
when String
|
110
|
-
if value =~ /,/
|
111
|
-
convert(value.split(",").map(&:to_f))
|
112
|
-
else
|
113
|
-
convert(value.to_i)
|
114
|
-
end
|
115
|
-
when Integer
|
116
|
-
new(value, value, value, value)
|
117
|
-
when Array
|
118
|
-
new(value[0], value[1], value[2], value[3])
|
119
|
-
when Padding
|
120
|
-
value
|
121
|
-
else
|
122
|
-
raise Hokusai::Error.new("Unsupported conversion type #{value.class} for Hokusai::Padding")
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
def hash
|
127
|
-
[self.class, top, right, bottom, left].hash
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
class Canvas
|
132
|
-
attr_accessor :width, :height, :x, :y, :vertical, :reverse
|
133
|
-
def initialize(width, height, x = 0.0, y = 0.0, vertical = true, reverse = false)
|
134
|
-
@width = width
|
135
|
-
@height = height
|
136
|
-
@x = x
|
137
|
-
@y = y
|
138
|
-
@vertical = vertical
|
139
|
-
@reverse = reverse
|
140
|
-
end
|
141
|
-
|
142
|
-
def reset(x, y, width, height, vertical: true, reverse: false)
|
143
|
-
self.x = x
|
144
|
-
self.y = y
|
145
|
-
self.width = width
|
146
|
-
self.height = height
|
147
|
-
self.vertical = vertical
|
148
|
-
self.reverse = reverse
|
149
|
-
end
|
150
|
-
|
151
|
-
def to_bounds
|
152
|
-
Hokusai::Rect.new(x, y, width, height)
|
153
|
-
end
|
154
|
-
|
155
|
-
def reverse?
|
156
|
-
reverse
|
157
|
-
end
|
158
|
-
|
159
|
-
def to_hoku_rect
|
160
|
-
LibHokusai::HmlRect.create(x, y, width, height)
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
# Color = Struct.new(:red, :green, :blue, :alpha) do
|
165
|
-
class Color
|
166
|
-
attr_reader :red, :green, :blue, :alpha
|
167
|
-
def initialize(red, green, blue, alpha = 255)
|
168
|
-
@red = red.freeze
|
169
|
-
@green = green.freeze
|
170
|
-
@blue = blue.freeze
|
171
|
-
@alpha = alpha.freeze
|
172
|
-
end
|
173
|
-
|
174
|
-
alias_method :r, :red
|
175
|
-
alias_method :b, :blue
|
176
|
-
alias_method :g, :green
|
177
|
-
alias_method :a, :alpha
|
178
|
-
|
179
|
-
def self.convert(value)
|
180
|
-
case value
|
181
|
-
when String
|
182
|
-
value = value.split(",").map(&:to_i)
|
183
|
-
when Array
|
184
|
-
when Color
|
185
|
-
return value
|
186
|
-
else
|
187
|
-
raise Hokusai::Error.new("Unsupported conversion type #{value.class} for Hokusai::Color")
|
188
|
-
end
|
189
|
-
|
190
|
-
new(value[0], value[1], value[2], value[3] || 255)
|
191
|
-
end
|
192
|
-
|
193
|
-
def hash
|
194
|
-
[self.class, r, g, b, a].hash
|
195
|
-
end
|
196
|
-
end
|
3
|
+
require_relative "./types/primitives"
|
4
|
+
require_relative "./types/display"
|
5
|
+
require_relative "./types/touch"
|
6
|
+
require_relative "./types/mouse"
|
197
7
|
|
8
|
+
module Hokusai
|
198
9
|
class Keyboard
|
199
10
|
attr_reader :raw
|
200
11
|
|
@@ -221,208 +32,6 @@ module Hokusai
|
|
221
32
|
end
|
222
33
|
end
|
223
34
|
|
224
|
-
class Mouse
|
225
|
-
attr_reader :raw
|
226
|
-
|
227
|
-
def initialize(raw)
|
228
|
-
@raw = raw
|
229
|
-
end
|
230
|
-
|
231
|
-
[
|
232
|
-
:pos, :delta, :scroll,
|
233
|
-
:scroll_delta, :selection,
|
234
|
-
:selection_type, :left,
|
235
|
-
:middle, :right
|
236
|
-
].each do |name|
|
237
|
-
define_method(name) do
|
238
|
-
# instance_variable_set("@#{name}", raw[name]) if instance_variable_get("@#{name}").nil?
|
239
|
-
#
|
240
|
-
# instance_variable_get("@#{name}")
|
241
|
-
|
242
|
-
raw[name]
|
243
|
-
end
|
244
|
-
|
245
|
-
define_method("#{name}=") do |val|
|
246
|
-
raw[name] = val
|
247
|
-
end
|
248
|
-
end
|
249
|
-
end
|
250
|
-
|
251
|
-
class Touch
|
252
|
-
attr_accessor :stack, :archive
|
253
|
-
def initialize
|
254
|
-
@stack = []
|
255
|
-
@archive = []
|
256
|
-
@tapped = false
|
257
|
-
@swiped = false
|
258
|
-
@pinched = false
|
259
|
-
# @file = File.open("touch.log", "w")
|
260
|
-
end
|
261
|
-
|
262
|
-
def tapped?
|
263
|
-
@tapped
|
264
|
-
end
|
265
|
-
|
266
|
-
def swiped?
|
267
|
-
@swiped
|
268
|
-
end
|
269
|
-
|
270
|
-
def pinched?
|
271
|
-
@pinched
|
272
|
-
end
|
273
|
-
|
274
|
-
def longtapping?(stuff = "ok")
|
275
|
-
log("#{touching?} - #{elapsed(token)} - #{stuff}") if touching?
|
276
|
-
touching? && elapsed(token) > 5
|
277
|
-
end
|
278
|
-
|
279
|
-
def longtapped?
|
280
|
-
@longtapped
|
281
|
-
end
|
282
|
-
|
283
|
-
def touching?
|
284
|
-
type == :down || type == :move
|
285
|
-
end
|
286
|
-
|
287
|
-
def duration
|
288
|
-
if longtapping?
|
289
|
-
return elapsed(token)
|
290
|
-
end
|
291
|
-
|
292
|
-
first, last = archive[-2..-1]
|
293
|
-
|
294
|
-
last[:start] - first[:start]
|
295
|
-
end
|
296
|
-
|
297
|
-
def distance
|
298
|
-
raise Hokusai::Error.new("Archive is empty") if archive.empty?
|
299
|
-
first, last = archive[-2..-1]
|
300
|
-
|
301
|
-
x = last[:x] - first[:x]
|
302
|
-
y = last[:y] - first[:y]
|
303
|
-
|
304
|
-
[x, y]
|
305
|
-
end
|
306
|
-
|
307
|
-
def direction
|
308
|
-
raise Hokusai::Error.new("Archive is empty") if archive.empty?
|
309
|
-
|
310
|
-
first, last = archive[-2..-1]
|
311
|
-
|
312
|
-
x = last[:x] - first[:x]
|
313
|
-
y = last[:y] - first[:y]
|
314
|
-
|
315
|
-
if x.abs > y.abs
|
316
|
-
# swiping left/right
|
317
|
-
last[:x] > first[:x] ? :right : :left
|
318
|
-
else
|
319
|
-
# swiping up/down
|
320
|
-
last[:y] > first[:y] ? :down : :up
|
321
|
-
end
|
322
|
-
end
|
323
|
-
|
324
|
-
def angle
|
325
|
-
raise Hokusai::Error.new("Archive is empty") if archive.empty?
|
326
|
-
|
327
|
-
last, first = archive[-2..-1]
|
328
|
-
|
329
|
-
x = last[:x] - first[:x]
|
330
|
-
y = last[:y] - first[:y]
|
331
|
-
|
332
|
-
(Math.atan2(x, y) * (-180 / Math::PI)).round(0).to_i
|
333
|
-
end
|
334
|
-
|
335
|
-
def log(str)
|
336
|
-
# Thread.new do
|
337
|
-
# @file.write_nonblock("#{str}\n")
|
338
|
-
# end
|
339
|
-
end
|
340
|
-
|
341
|
-
def record(finger, x, y)
|
342
|
-
log("recording #{token}")
|
343
|
-
if type == :down
|
344
|
-
push(:move, finger, x, y)
|
345
|
-
log("state is move")
|
346
|
-
elsif type == :move
|
347
|
-
stack.last[:x] = x
|
348
|
-
stack.last[:y] = y
|
349
|
-
|
350
|
-
log("updated state move")
|
351
|
-
else
|
352
|
-
@longtapped = false
|
353
|
-
@swiped = false
|
354
|
-
@tapped = false
|
355
|
-
push(:down, finger, x, y)
|
356
|
-
log("state is down")
|
357
|
-
end
|
358
|
-
end
|
359
|
-
|
360
|
-
def clear
|
361
|
-
log("clearing")
|
362
|
-
if type == :move
|
363
|
-
log("elapsed: #{elapsed(token)}")
|
364
|
-
if elapsed(token) > 0.05 && within(10.0)
|
365
|
-
@longtapped = true
|
366
|
-
log('longtap')
|
367
|
-
else
|
368
|
-
@swiped = true
|
369
|
-
log('swipe')
|
370
|
-
end
|
371
|
-
elsif type == :down
|
372
|
-
@tapped = true
|
373
|
-
log('tap')
|
374
|
-
else
|
375
|
-
@longtapped = false
|
376
|
-
@swiped = false
|
377
|
-
@tapped = false
|
378
|
-
end
|
379
|
-
|
380
|
-
self.archive = stack.dup
|
381
|
-
stack.clear
|
382
|
-
end
|
383
|
-
|
384
|
-
def elapsed(token)
|
385
|
-
Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond) - token[:start]
|
386
|
-
end
|
387
|
-
|
388
|
-
def within(threshold)
|
389
|
-
move = stack.last
|
390
|
-
down = stack[-2]
|
391
|
-
|
392
|
-
t1 = (move[:x] - down[:x]).abs
|
393
|
-
t2 = (move[:y] - down[:y]).abs
|
394
|
-
|
395
|
-
t1 < threshold && t2 < threshold
|
396
|
-
end
|
397
|
-
|
398
|
-
def pop
|
399
|
-
stack.pop
|
400
|
-
end
|
401
|
-
|
402
|
-
def push(type, finger, x, y)
|
403
|
-
log("push: #{type}")
|
404
|
-
stack << {
|
405
|
-
type: type,
|
406
|
-
i: finger,
|
407
|
-
x: x,
|
408
|
-
y: y,
|
409
|
-
start: Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
|
410
|
-
}
|
411
|
-
end
|
412
|
-
|
413
|
-
def index
|
414
|
-
token&.[](:finger)
|
415
|
-
end
|
416
|
-
|
417
|
-
def type
|
418
|
-
token&.[](:type)
|
419
|
-
end
|
420
|
-
|
421
|
-
def token
|
422
|
-
@stack.last
|
423
|
-
end
|
424
|
-
end
|
425
|
-
|
426
35
|
class Input
|
427
36
|
attr_accessor :keyboard_override
|
428
37
|
attr_reader :raw, :touch
|
@@ -448,11 +57,12 @@ module Hokusai
|
|
448
57
|
end
|
449
58
|
|
450
59
|
def mouse
|
451
|
-
@mouse ||= Mouse.new
|
60
|
+
@mouse ||= Mouse.new
|
452
61
|
end
|
453
62
|
|
454
63
|
def hovered?(canvas)
|
455
|
-
|
64
|
+
pos = mouse.pos
|
65
|
+
pos.x >= canvas.x && pos.x <= canvas.x + canvas.width && pos.y >= canvas.y && pos.y <= canvas.y + canvas.height
|
456
66
|
end
|
457
67
|
end
|
458
68
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hokusai-zero
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.6.pre.
|
4
|
+
version: 0.2.6.pre.pinephone5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- skinnyjames
|
@@ -292,6 +292,10 @@ files:
|
|
292
292
|
- ui/src/hokusai/publisher.rb
|
293
293
|
- ui/src/hokusai/style.rb
|
294
294
|
- ui/src/hokusai/types.rb
|
295
|
+
- ui/src/hokusai/types/display.rb
|
296
|
+
- ui/src/hokusai/types/mouse.rb
|
297
|
+
- ui/src/hokusai/types/primitives.rb
|
298
|
+
- ui/src/hokusai/types/touch.rb
|
295
299
|
- ui/src/hokusai/util/clamping_iterator.rb
|
296
300
|
- ui/src/hokusai/util/piece_table.rb
|
297
301
|
- ui/src/hokusai/util/selection.rb
|