hokusai-zero 0.2.6.pre.pinephone4 → 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/src/hokusai/backends/raylib.rb +22 -27
- 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/painter.rb +7 -5
- 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 -405
- 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
@@ -116,11 +116,12 @@ module Hokusai::Backends
|
|
116
116
|
if !config.touch
|
117
117
|
raylib_mouse_pos = Raylib.GetMousePosition
|
118
118
|
raylib_mouse_delta = Raylib.GetMouseDelta
|
119
|
-
LibHokusai.hoku_input_mouse_set_scroll(input.raw, Raylib.GetMouseWheelMove)
|
120
|
-
LibHokusai.hoku_input_set_mouse_position(input.raw, hml_vec2(raylib_mouse_pos.x, raylib_mouse_pos.y))
|
121
119
|
|
122
|
-
input.
|
123
|
-
input.
|
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
|
124
125
|
end
|
125
126
|
|
126
127
|
if config.touch
|
@@ -134,14 +135,13 @@ module Hokusai::Backends
|
|
134
135
|
input.touch.clear
|
135
136
|
end
|
136
137
|
else
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
button =
|
144
|
-
LibHokusai.hoku_input_mouse_set_button(input.raw, button, button_id)
|
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
145
|
end
|
146
146
|
end
|
147
147
|
|
@@ -149,16 +149,21 @@ module Hokusai::Backends
|
|
149
149
|
if input.touch.touching?
|
150
150
|
token = input.touch.token
|
151
151
|
|
152
|
-
|
152
|
+
input.mouse.pos.x = token[:x]
|
153
|
+
input.mouse.pos.y = token[:y]
|
153
154
|
end
|
154
155
|
|
155
156
|
# translate taps to clicks
|
156
157
|
if input.touch.tapped?
|
157
|
-
|
158
|
-
|
158
|
+
input.mouse.left.clicked = true
|
159
|
+
input.mouse.left.down = true
|
160
|
+
input.mouse.left.released = false
|
161
|
+
input.mouse.left.up = false
|
159
162
|
else
|
160
|
-
|
161
|
-
|
163
|
+
input.mouse.left.clicked = true
|
164
|
+
input.mouse.left.down = true
|
165
|
+
input.mouse.left.released = false
|
166
|
+
input.mouse.left.up = false
|
162
167
|
end
|
163
168
|
end
|
164
169
|
|
@@ -276,8 +281,6 @@ module Hokusai::Backends
|
|
276
281
|
Raylib.DrawFPS(10, 10) if ENV["PROFILE"] || ENV["FPS"]
|
277
282
|
Raylib.EndDrawing
|
278
283
|
|
279
|
-
GC.start
|
280
|
-
|
281
284
|
break if self.class.stopped?
|
282
285
|
end
|
283
286
|
|
@@ -383,14 +386,6 @@ module Hokusai::Backends
|
|
383
386
|
Raylib.MinimizeWindow
|
384
387
|
end
|
385
388
|
|
386
|
-
# Hokusai.on_set_shader_value do |location, value, type|
|
387
|
-
# Raylib.SetShaderValue(@shader, location, value, type)
|
388
|
-
# end
|
389
|
-
|
390
|
-
# Hokusai.on_shader_location do |name|
|
391
|
-
# Raylib.GetShaderLocation(@shader, name)
|
392
|
-
# end
|
393
|
-
|
394
389
|
Hokusai.on_renderable do |canvas|
|
395
390
|
inside_scissor(canvas.x, canvas.y, canvas.height)
|
396
391
|
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
|
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
|
@@ -267,10 +267,12 @@ module Hokusai
|
|
267
267
|
return
|
268
268
|
end
|
269
269
|
|
270
|
-
|
271
|
-
|
270
|
+
|
271
|
+
|
272
|
+
# rect = canvas.to_hoku_rect
|
273
|
+
# block_is_hovered = LibHokusai.hoku_input_is_hovered(input.raw, rect)
|
272
274
|
|
273
|
-
if
|
275
|
+
if input.hovered?(canvas)
|
274
276
|
events[:hover].capture(block, canvas)
|
275
277
|
events[:click].capture(block, canvas)
|
276
278
|
events[:wheel].capture(block, canvas)
|
@@ -281,7 +283,7 @@ module Hokusai
|
|
281
283
|
end
|
282
284
|
events[:mousemove].capture(block, canvas)
|
283
285
|
|
284
|
-
if
|
286
|
+
if input.hovered?(canvas) || block.node.meta.focused || input.keyboard_override
|
285
287
|
events[:keyup].capture(block, canvas)
|
286
288
|
events[:keypress].capture(block, canvas)
|
287
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,205 +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
|
-
@hoku_rect = LibHokusai::HmlRect.create(x, y, width, height)
|
141
|
-
end
|
142
|
-
|
143
|
-
def reset(x, y, width, height, vertical: true, reverse: false)
|
144
|
-
self.x = x
|
145
|
-
self.y = y
|
146
|
-
self.width = width
|
147
|
-
self.height = height
|
148
|
-
self.vertical = vertical
|
149
|
-
self.reverse = reverse
|
150
|
-
@hoku_rect[:x] = x
|
151
|
-
@hoku_rect[:y] = y
|
152
|
-
@hoku_rect[:w] = width
|
153
|
-
@hoku_rect[:h] = height
|
154
|
-
end
|
155
|
-
|
156
|
-
def to_bounds
|
157
|
-
Hokusai::Rect.new(x, y, width, height)
|
158
|
-
end
|
159
|
-
|
160
|
-
def reverse?
|
161
|
-
reverse
|
162
|
-
end
|
163
|
-
|
164
|
-
def to_hoku_rect
|
165
|
-
@hoku_rect
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
# Color = Struct.new(:red, :green, :blue, :alpha) do
|
170
|
-
class Color
|
171
|
-
attr_reader :red, :green, :blue, :alpha
|
172
|
-
def initialize(red, green, blue, alpha = 255)
|
173
|
-
@red = red.freeze
|
174
|
-
@green = green.freeze
|
175
|
-
@blue = blue.freeze
|
176
|
-
@alpha = alpha.freeze
|
177
|
-
end
|
178
|
-
|
179
|
-
alias_method :r, :red
|
180
|
-
alias_method :b, :blue
|
181
|
-
alias_method :g, :green
|
182
|
-
alias_method :a, :alpha
|
183
|
-
|
184
|
-
def self.convert(value)
|
185
|
-
case value
|
186
|
-
when String
|
187
|
-
value = value.split(",").map(&:to_i)
|
188
|
-
when Array
|
189
|
-
when Color
|
190
|
-
return value
|
191
|
-
else
|
192
|
-
raise Hokusai::Error.new("Unsupported conversion type #{value.class} for Hokusai::Color")
|
193
|
-
end
|
194
|
-
|
195
|
-
new(value[0], value[1], value[2], value[3] || 255)
|
196
|
-
end
|
197
|
-
|
198
|
-
def hash
|
199
|
-
[self.class, r, g, b, a].hash
|
200
|
-
end
|
201
|
-
end
|
3
|
+
require_relative "./types/primitives"
|
4
|
+
require_relative "./types/display"
|
5
|
+
require_relative "./types/touch"
|
6
|
+
require_relative "./types/mouse"
|
202
7
|
|
8
|
+
module Hokusai
|
203
9
|
class Keyboard
|
204
10
|
attr_reader :raw
|
205
11
|
|
@@ -226,210 +32,6 @@ module Hokusai
|
|
226
32
|
end
|
227
33
|
end
|
228
34
|
|
229
|
-
class Mouse
|
230
|
-
attr_reader :raw
|
231
|
-
|
232
|
-
def initialize(raw)
|
233
|
-
@raw = raw
|
234
|
-
end
|
235
|
-
|
236
|
-
[
|
237
|
-
:pos, :delta, :scroll,
|
238
|
-
:scroll_delta, :selection,
|
239
|
-
:selection_type, :left,
|
240
|
-
:middle, :right
|
241
|
-
].each do |name|
|
242
|
-
define_method(name) do
|
243
|
-
# instance_variable_set("@#{name}", raw[name]) if instance_variable_get("@#{name}").nil?
|
244
|
-
#
|
245
|
-
# instance_variable_get("@#{name}")
|
246
|
-
|
247
|
-
raw[name]
|
248
|
-
end
|
249
|
-
|
250
|
-
define_method("#{name}=") do |val|
|
251
|
-
raw[name] = val
|
252
|
-
end
|
253
|
-
end
|
254
|
-
end
|
255
|
-
|
256
|
-
class Touch
|
257
|
-
attr_accessor :stack, :archive
|
258
|
-
def initialize
|
259
|
-
@stack = []
|
260
|
-
@archive = []
|
261
|
-
@tapped = false
|
262
|
-
@swiped = false
|
263
|
-
@pinched = false
|
264
|
-
# @file = File.open("touch.log", "w")
|
265
|
-
end
|
266
|
-
|
267
|
-
def tapped?
|
268
|
-
@tapped
|
269
|
-
end
|
270
|
-
|
271
|
-
def swiped?
|
272
|
-
@swiped
|
273
|
-
end
|
274
|
-
|
275
|
-
def pinched?
|
276
|
-
@pinched
|
277
|
-
end
|
278
|
-
|
279
|
-
def longtapping?(stuff = "ok")
|
280
|
-
log("#{touching?} - #{elapsed(token)} - #{stuff}") if touching?
|
281
|
-
touching? && elapsed(token) > 5
|
282
|
-
end
|
283
|
-
|
284
|
-
def longtapped?
|
285
|
-
@longtapped
|
286
|
-
end
|
287
|
-
|
288
|
-
def touching?
|
289
|
-
type == :down || type == :move
|
290
|
-
end
|
291
|
-
|
292
|
-
def duration
|
293
|
-
if longtapping?
|
294
|
-
return elapsed(token)
|
295
|
-
end
|
296
|
-
|
297
|
-
first, last = archive[-2..-1]
|
298
|
-
|
299
|
-
last[:start] - first[:start]
|
300
|
-
end
|
301
|
-
|
302
|
-
def distance
|
303
|
-
raise Hokusai::Error.new("Archive is empty") if archive.empty?
|
304
|
-
first, last = archive[-2..-1]
|
305
|
-
|
306
|
-
x = last[:x] - first[:x]
|
307
|
-
y = last[:y] - first[:y]
|
308
|
-
|
309
|
-
[x, y]
|
310
|
-
end
|
311
|
-
|
312
|
-
def direction
|
313
|
-
raise Hokusai::Error.new("Archive is empty") if archive.empty?
|
314
|
-
|
315
|
-
first, last = archive[-2..-1]
|
316
|
-
|
317
|
-
x = last[:x] - first[:x]
|
318
|
-
y = last[:y] - first[:y]
|
319
|
-
|
320
|
-
if x.abs > y.abs
|
321
|
-
# swiping left/right
|
322
|
-
last[:x] > first[:x] ? :right : :left
|
323
|
-
else
|
324
|
-
# swiping up/down
|
325
|
-
last[:y] > first[:y] ? :down : :up
|
326
|
-
end
|
327
|
-
end
|
328
|
-
|
329
|
-
def angle
|
330
|
-
raise Hokusai::Error.new("Archive is empty") if archive.empty?
|
331
|
-
|
332
|
-
last, first = archive[-2..-1]
|
333
|
-
|
334
|
-
x = last[:x] - first[:x]
|
335
|
-
y = last[:y] - first[:y]
|
336
|
-
|
337
|
-
(Math.atan2(x, y) * (-180 / Math::PI)).round(0).to_i
|
338
|
-
end
|
339
|
-
|
340
|
-
def log(str)
|
341
|
-
# Thread.new do
|
342
|
-
# @file.write_nonblock("#{str}\n")
|
343
|
-
# end
|
344
|
-
end
|
345
|
-
|
346
|
-
def record(finger, x, y)
|
347
|
-
log("recording #{token}")
|
348
|
-
if type == :down
|
349
|
-
push(:move, finger, x, y)
|
350
|
-
log("state is move")
|
351
|
-
elsif type == :move
|
352
|
-
stack.last[:x] = x
|
353
|
-
stack.last[:y] = y
|
354
|
-
|
355
|
-
log("updated state move")
|
356
|
-
else
|
357
|
-
@longtapped = false
|
358
|
-
@swiped = false
|
359
|
-
@tapped = false
|
360
|
-
push(:down, finger, x, y)
|
361
|
-
log("state is down")
|
362
|
-
end
|
363
|
-
end
|
364
|
-
|
365
|
-
def clear
|
366
|
-
# log("clearing")
|
367
|
-
if type == :move
|
368
|
-
log("elapsed: #{elapsed(token)}")
|
369
|
-
if elapsed(token) > 300 && within(10.0)
|
370
|
-
@longtapped = true
|
371
|
-
log('longtap')
|
372
|
-
elsif within(10.0)
|
373
|
-
@tapped = true
|
374
|
-
else
|
375
|
-
@swiped = true
|
376
|
-
log('swipe')
|
377
|
-
end
|
378
|
-
elsif type == :down
|
379
|
-
@tapped = true
|
380
|
-
log('tap')
|
381
|
-
else
|
382
|
-
@longtapped = false
|
383
|
-
@swiped = false
|
384
|
-
@tapped = false
|
385
|
-
end
|
386
|
-
|
387
|
-
self.archive = stack.dup
|
388
|
-
stack.clear
|
389
|
-
end
|
390
|
-
|
391
|
-
def elapsed(token)
|
392
|
-
Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond) - token[:start]
|
393
|
-
end
|
394
|
-
|
395
|
-
def within(threshold)
|
396
|
-
move = stack.last
|
397
|
-
down = stack[-2]
|
398
|
-
|
399
|
-
t1 = (move[:x] - down[:x]).abs
|
400
|
-
t2 = (move[:y] - down[:y]).abs
|
401
|
-
|
402
|
-
t1 < threshold && t2 < threshold
|
403
|
-
end
|
404
|
-
|
405
|
-
def pop
|
406
|
-
stack.pop
|
407
|
-
end
|
408
|
-
|
409
|
-
def push(type, finger, x, y)
|
410
|
-
log("push: #{type}")
|
411
|
-
stack << {
|
412
|
-
type: type,
|
413
|
-
i: finger,
|
414
|
-
x: x,
|
415
|
-
y: y,
|
416
|
-
start: Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
|
417
|
-
}
|
418
|
-
end
|
419
|
-
|
420
|
-
def index
|
421
|
-
token&.[](:finger)
|
422
|
-
end
|
423
|
-
|
424
|
-
def type
|
425
|
-
token&.[](:type)
|
426
|
-
end
|
427
|
-
|
428
|
-
def token
|
429
|
-
@stack.last
|
430
|
-
end
|
431
|
-
end
|
432
|
-
|
433
35
|
class Input
|
434
36
|
attr_accessor :keyboard_override
|
435
37
|
attr_reader :raw, :touch
|
@@ -455,11 +57,12 @@ module Hokusai
|
|
455
57
|
end
|
456
58
|
|
457
59
|
def mouse
|
458
|
-
@mouse ||= Mouse.new
|
60
|
+
@mouse ||= Mouse.new
|
459
61
|
end
|
460
62
|
|
461
63
|
def hovered?(canvas)
|
462
|
-
|
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
|
463
66
|
end
|
464
67
|
end
|
465
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
|