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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f2b53ce8769964539f51ad894c33476cecb01095b7b5ce851355cbf7df17a707
4
- data.tar.gz: 430de1cd6a0ffae61fdf9ca547b15aa61e0065769f94472962047c0205df83ff
3
+ metadata.gz: db63632b958a6ee6aaa4322f1e8737f74a74167df845dbbc01b167fc73907305
4
+ data.tar.gz: 0cceed2907fdf38549b34ddd77e6503a9c504a3b1c6fbc6a14d3adfdab2984a8
5
5
  SHA512:
6
- metadata.gz: d571179fb72b52671eafceed834e76c7154e205faaff5bb67a95d7d1eb801c86d34f6e5525ade0247db57e48c3019098744dbef7d704630fc4ea7b7577854ab4
7
- data.tar.gz: '082837551a6b0ff70eda1779c4bde8232efe3108dad48359a05f597023895250faa07812878367229da734075bb0fb1c5c2ab180820b06e4040f7569fdb87306'
6
+ metadata.gz: 277ef8ae488facee7aa4b43e25c7ea0e704343d0364dd2607eeb106deebf3b9529dcdfcd7672d3f291c2598821f6841ee4eac56c9f5b6026115a6e77a1887621
7
+ data.tar.gz: 0cce59cf2eaa17ff83d3e63f0c77ef7bd3acc8db4d4b07e2fbc0c28fc6f650dd9d7a5d6aa7614e10d07691211c12440be9f1476018b80efaf6688b24694de027
data/hokusai.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'hokusai-zero'
3
- s.version = '0.2.6-pinephone3'
3
+ s.version = '0.2.6-pinephone5'
4
4
  s.licenses = ['MIT']
5
5
  s.summary = "A Ruby library for writing GUI applications"
6
6
  s.authors = ["skinnyjames"]
@@ -40,7 +40,7 @@ class KeyboardExample < Hokusai::Block
40
40
  end
41
41
  end
42
42
 
43
- Hokusai::Backends::SDLBackend.run(KeyboardExample) do |config|
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
- raylib_mouse_pos = Raylib.GetMousePosition
117
- raylib_mouse_delta = Raylib.GetMouseDelta
118
- LibHokusai.hoku_input_mouse_set_scroll(input.raw, Raylib.GetMouseWheelMove)
119
- LibHokusai.hoku_input_set_mouse_position(input.raw, hml_vec2(raylib_mouse_pos.x, raylib_mouse_pos.y))
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
- input.raw[:mouse][:delta][:x] = raylib_mouse_delta.x
122
- input.raw[:mouse][:delta][:y] = raylib_mouse_delta.y
148
+ if config.touch
149
+ if input.touch.touching?
150
+ token = input.touch.token
123
151
 
124
- [0,1,2].each do |button_id|
125
- clicked = Raylib.IsMouseButtonPressed(button_id)
126
- down = Raylib.IsMouseButtonDown(button_id)
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
- button = mouse_button(clicked: clicked, down: down, released: released, up: up)
131
- LibHokusai.hoku_input_mouse_set_button(input.raw, button, button_id)
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(nil, nil, width.to_f, height.to_f)
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(nil, nil, render_width.to_f, render_height.to_f)
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
- attr_accessor :down
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 icon = icons[value[0]]
51
- rect(canvas.x + margin.left, canvas.y + margin.top, canvas.width - margin.width, canvas.height - margin.height) do |command|
52
- command.color = icon[:background]# down ? background_down : background
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
- svg(icon[:file], canvas.x + icon[:size] / 3, canvas.y + icon[:size] / 3, icon[:size], icon[:size]) do |command|
57
- command.color = icon[:color]
58
- end
59
- else
60
- rect(canvas.x + margin.left, canvas.y + margin.top, canvas.width - margin.width, canvas.height - margin.height) do |command|
61
- command.color = down ? background_down : background
62
- command.round = 6.0
63
- end
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
- text(value[1].to_s, canvas.x + hpad + margin.width, canvas.y + margin.height) do |command|
66
- command.color = color
67
- command.size = size
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
- :width="width(number)"
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
- # def on_mounted
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
- "key-#{value}"
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 KeyboardEvent < Event
3
5
  extend Forwardable
@@ -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
- LibHokusai.hoku_input_is_hovered(input.raw, canvas.to_hoku_rect)
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[:clicked] && clicked(canvas)
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[:clicked]
96
+ elsif left.clicked
95
97
  block.node.meta.blur
96
98
  end
97
99
  end
98
100
 
99
101
  def clicked(canvas)
100
- LibHokusai.hoku_input_is_clicked(input.raw, canvas.to_hoku_rect)
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[:up] && matches(block)
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[:down] && matches(block)
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[:clicked] && !clicked(canvas)
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
- LibHokusai.hoku_input_is_clicked(input.raw, canvas.to_hoku_rect)
179
+ left.clicked && input.hovered?(canvas)
178
180
  end
179
181
  end
180
182
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Hokusai
2
4
  class TouchEvent < Event
3
5
  extend Forwardable
@@ -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)
@@ -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[:y]
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
- rect = canvas.to_hoku_rect
267
- block_is_hovered = LibHokusai.hoku_input_is_hovered(input.raw, rect)
270
+
271
+
272
+ # rect = canvas.to_hoku_rect
273
+ # block_is_hovered = LibHokusai.hoku_input_is_hovered(input.raw, rect)
268
274
 
269
- if block_is_hovered
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 block_is_hovered || block.node.meta.focused || input.keyboard_override
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
@@ -1,200 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Hokusai
4
- # Rect = Struct.new(:x, :y, :width, :height) do
5
- class Rect
6
- attr_accessor :x, :y, :width, :height
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(@raw[:mouse])
60
+ @mouse ||= Mouse.new
452
61
  end
453
62
 
454
63
  def hovered?(canvas)
455
- LibHokusai.hoku_input_is_hovered(raw, canvas.to_hoku_rect)
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.pinephone3
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