hokusai-zero 0.2.6.pre.pinephone2 → 0.2.6.pre.pinephone4

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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/ast/src/core/input.c +0 -135
  3. data/ast/src/core/input.h +0 -33
  4. data/ast/test/hokusai.c +0 -2
  5. data/hokusai.gemspec +1 -1
  6. data/ui/examples/forum/file.rb +1 -1
  7. data/ui/examples/forum/post.rb +0 -1
  8. data/ui/examples/forum.rb +7 -7
  9. data/ui/examples/keyboard.rb +47 -0
  10. data/ui/examples/shader/test.rb +28 -18
  11. data/ui/examples/spreadsheet.rb +12 -11
  12. data/ui/lib/lib_hokusai.rb +19 -37
  13. data/ui/spec/hokusai/e2e/keyboard_spec.rb +52 -0
  14. data/ui/src/hokusai/assets/icons/outline/arrow-big-up.svg +19 -0
  15. data/ui/src/hokusai/assets/icons/outline/backspace.svg +20 -0
  16. data/ui/src/hokusai/backends/raylib/config.rb +2 -1
  17. data/ui/src/hokusai/backends/raylib.rb +54 -20
  18. data/ui/src/hokusai/backends/sdl2/config.rb +9 -6
  19. data/ui/src/hokusai/backends/sdl2/font.rb +3 -1
  20. data/ui/src/hokusai/backends/sdl2.rb +164 -65
  21. data/ui/src/hokusai/blocks/input.rb +1 -1
  22. data/ui/src/hokusai/blocks/keyboard.rb +249 -0
  23. data/ui/src/hokusai/blocks/slider.rb +139 -0
  24. data/ui/src/hokusai/commands/rect.rb +2 -2
  25. data/ui/src/hokusai/events/touch.rb +5 -11
  26. data/ui/src/hokusai/mounting/loop_entry.rb +1 -1
  27. data/ui/src/hokusai/painter.rb +6 -2
  28. data/ui/src/hokusai/types.rb +160 -50
  29. data/ui/src/hokusai/util/wrap_stream.rb +197 -0
  30. data/ui/src/hokusai.rb +61 -30
  31. metadata +8 -6
  32. data/ast/test/input.c +0 -44
  33. data/ui/src/hokusai/backends/embedded/config.rb +0 -48
  34. data/ui/src/hokusai/backends/embedded/font.rb +0 -112
  35. data/ui/src/hokusai/backends/embedded/keys.rb +0 -124
  36. data/ui/src/hokusai/backends/embedded.rb +0 -540
@@ -113,31 +113,64 @@ 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
+ 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
+
122
+ input.raw[:mouse][:delta][:x] = raylib_mouse_delta.x
123
+ input.raw[:mouse][:delta][:y] = raylib_mouse_delta.y
124
+ end
125
+
126
+ if config.touch
127
+ count = Raylib.GetTouchPointCount
128
+ if count > 0
129
+ vec = Raylib.GetTouchPosition(0)
130
+ unless vec.x.zero? && vec.y.zero?
131
+ input.touch.record(0, vec.x, vec.y)
132
+ end
133
+ else
134
+ input.touch.clear
135
+ end
136
+ else
137
+ [0,1,2].each do |button_id|
138
+ clicked = Raylib.IsMouseButtonPressed(button_id)
139
+ down = Raylib.IsMouseButtonDown(button_id)
140
+ released = Raylib.IsMouseButtonReleased(button_id)
141
+ up = Raylib.IsMouseButtonUp(button_id)
142
+
143
+ button = mouse_button(clicked: clicked, down: down, released: released, up: up)
144
+ LibHokusai.hoku_input_mouse_set_button(input.raw, button, 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
+ LibHokusai.hoku_input_set_mouse_position(input.raw, hml_vec2(token[:x], token[:y]))
153
+ end
129
154
 
130
- button = mouse_button(clicked: clicked, down: down, released: released, up: up)
131
- LibHokusai.hoku_input_mouse_set_button(input.raw, button, button_id)
155
+ # translate taps to clicks
156
+ if input.touch.tapped?
157
+ button = mouse_button(clicked: true, down: true, released: false, up: false)
158
+ LibHokusai.hoku_input_mouse_set_button(input.raw, button, 0)
159
+ else
160
+ button = mouse_button(clicked: false, down: false, released: true, up: true)
161
+ LibHokusai.hoku_input_mouse_set_button(input.raw, button, 0)
162
+ end
132
163
  end
133
164
 
134
- LibHokusai.hoku_input_keyboard_start(input.raw)
165
+ if !input.keyboard_override
166
+ LibHokusai.hoku_input_keyboard_start(input.raw)
135
167
 
136
- Keys.each do |(hoku_key, raylib_key)|
137
- LibHokusai.hoku_input_keyboard_set_key(input.raw, hoku_key, Raylib.IsKeyDown(raylib_key))
138
- end
168
+ Keys.each do |(hoku_key, raylib_key)|
169
+ LibHokusai.hoku_input_keyboard_set_key(input.raw, hoku_key, Raylib.IsKeyDown(raylib_key))
170
+ end
139
171
 
140
- LibHokusai.hoku_input_keyboard_stop(input.raw)
172
+ LibHokusai.hoku_input_keyboard_stop(input.raw)
173
+ end
141
174
  end
142
175
 
143
176
  def self.run(app)
@@ -153,7 +186,6 @@ module Hokusai::Backends
153
186
  self.class.reset
154
187
 
155
188
  Raylib.load_lib(RAYLIB_PATH)
156
-
157
189
  resize = false
158
190
  initial = true
159
191
  width = config.width
@@ -166,6 +198,7 @@ module Hokusai::Backends
166
198
  raw = LibHokusai::HmlInput.new(ptr.get_pointer(0))
167
199
  input = Hokusai::Input.new(raw)
168
200
  ptr.free
201
+ input.support_touch! if config.touch
169
202
 
170
203
  Raylib.SetConfigFlags(config.config_flags)
171
204
  Raylib.InitWindow(config.width, config.height, config.title)
@@ -219,7 +252,7 @@ module Hokusai::Backends
219
252
  block.update
220
253
  block.public_send(:after_updated) if block.respond_to?(:after_updated)
221
254
 
222
- canvas.reset(nil, nil, width.to_f, height.to_f)
255
+ canvas.reset(0.0, 0.0, width.to_f, height.to_f)
223
256
 
224
257
  Raylib.BeginDrawing
225
258
  Raylib.ClearBackground(config.background)
@@ -243,6 +276,7 @@ module Hokusai::Backends
243
276
  Raylib.DrawFPS(10, 10) if ENV["PROFILE"] || ENV["FPS"]
244
277
  Raylib.EndDrawing
245
278
 
279
+ GC.start
246
280
 
247
281
  break if self.class.stopped?
248
282
  end
@@ -3,8 +3,8 @@ module Hokusai::Backends
3
3
  class Config
4
4
  attr_accessor :width, :height, :fps, :init_flags,
5
5
  :title, :background, :automation_driver,
6
- :after_load_cb, :host, :port, :automated,
7
- :window_config_flags
6
+ :after_load_cb, :host, :port, :automated, :mobile,
7
+ :window_config_flags, :touch
8
8
 
9
9
  def after_load(&block)
10
10
  self.after_load_cb = block
@@ -14,16 +14,19 @@ module Hokusai::Backends
14
14
  @width = 500
15
15
  @height = 500
16
16
  @fps = 60
17
+ @touch = false
17
18
 
18
19
  @init_flags = ::SDL::INIT_VIDEO | ::SDL::INIT_EVENTS
19
- @window_config_flags = SDL::WINDOW_RESIZABLE
20
+ @window_config_flags = SDL::WINDOW_RESIZABLE | SDL::WINDOW_ALLOW_HIGHDPI
20
21
  @title = "(Unknown Title)"
21
22
  @background = SDLBackend.color(255,255,255, 0)
22
23
 
23
24
  after_load do
24
- font = Hokusai::Backends::SDLBackend::Font.from "#{__dir__}/Monaco.ttf"
25
- Hokusai.fonts.register "default", font
26
- Hokusai.fonts.activate "default"
25
+ if Hokusai.fonts.get("default").nil?
26
+ font = Hokusai::Backends::SDLBackend::Font.from "#{__dir__}/Monaco.ttf"
27
+ Hokusai.fonts.register "default", font
28
+ Hokusai.fonts.activate "default"
29
+ end
27
30
  end
28
31
  end
29
32
  end
@@ -21,7 +21,7 @@ module Hokusai::Backends
21
21
  end
22
22
 
23
23
  class Font < Hokusai::Font
24
- def self.from(file = "#{__dir__}/Monaco.ttf", size=50)
24
+ def self.from(file = "#{__dir__}/Monaco.ttf", size=60)
25
25
  raw = SDL.TTF_OpenFont(file, size)
26
26
 
27
27
  raise Hokusai::Error.new("Cannot open font from #{file}: #{ttf_error}") if raw.null?
@@ -51,6 +51,8 @@ module Hokusai::Backends
51
51
  set_style(**args)
52
52
 
53
53
  render_color = SDLBackend.color(color.r, color.g, color.b, color.a)
54
+ # bg = SDLBackend.color(0, 0, 0, 0)
55
+
54
56
  SDL.TTF_RenderUTF8_Blended(raw, text, render_color)
55
57
  end
56
58
 
@@ -16,8 +16,7 @@ module Hokusai::Backends
16
16
  yield(config)
17
17
  end
18
18
 
19
- block = app.mount
20
- backend.run(block)
19
+ backend.run(app)
21
20
  end
22
21
 
23
22
  def self.cursors
@@ -30,6 +29,17 @@ module Hokusai::Backends
30
29
  }
31
30
  end
32
31
 
32
+ def hml_vec2(x, y)
33
+ if @hml_vec2.nil?
34
+ @hml_vec2 = LibHokusai::HmlVec2.create(x, y)
35
+ else
36
+ @hml_vec2[:x] = x
37
+ @hml_vec2[:y] = y
38
+ end
39
+
40
+ @hml_vec2
41
+ end
42
+
33
43
  def self.stopped
34
44
  @stopped ||= false
35
45
  end
@@ -56,7 +66,19 @@ module Hokusai::Backends
56
66
  yield @config
57
67
  end
58
68
 
59
- def run(block)
69
+ def get_size(window)
70
+ w = FFI::MemoryPointer.new :int
71
+ h = FFI::MemoryPointer.new :int
72
+
73
+ SDL.GL_GetDrawableSize(window, w, h)
74
+
75
+ res = { width: w.read_int, height: h.read_int }
76
+ w.free
77
+ h.free
78
+ res
79
+ end
80
+
81
+ def run(app)
60
82
  resize = true
61
83
  self.render_width = config.width
62
84
  self.render_height = config.height
@@ -80,6 +102,7 @@ module Hokusai::Backends
80
102
  image_libpath: "#{SDL_PATH}/libSDL2_image.so"
81
103
  )
82
104
  end
105
+
83
106
  SDL.Init(config.init_flags)
84
107
  SDL.TTF_Init
85
108
 
@@ -87,43 +110,73 @@ module Hokusai::Backends
87
110
  SDL.SetWindowPosition(window, SDL::WINDOWPOS_CENTERED_MASK, SDL::WINDOWPOS_CENTERED_MASK)
88
111
  renderer = SDL.CreateRenderer(window, -1, SDL::RENDERER_TARGETTEXTURE | SDL::RENDERER_ACCELERATED)
89
112
 
113
+ size = get_size(window)
114
+ SDL.RenderSetScale(renderer, size[:width] / render_width, size[:height] / render_height);
115
+
90
116
  Hokusai.fonts.register "default", SDLBackend::Font.from("#{__dir__}/sdl2/Monaco.ttf", 121)
91
117
  Hokusai.fonts.activate "default"
92
118
  config.after_load_cb&.call
93
119
 
94
120
  register_command_handlers(renderer, window)
121
+ block = app.mount
95
122
  # MemoryProfiler.start if ENV["PROFILE"]
96
123
 
97
124
  ptr = FFI::MemoryPointer.new :pointer
98
125
  LibHokusai.hoku_input_init(ptr)
99
126
  raw = LibHokusai::HmlInput.new(ptr.get_pointer(0))
100
127
  input = Hokusai::Input.new(raw)
128
+
129
+ if config.touch
130
+ input.support_touch!
131
+ end
132
+
101
133
  canvas = Hokusai::Canvas.new(render_width.to_f, render_height.to_f)
102
134
  event = SDL::Event.new
103
135
 
104
136
  loop do
105
- SDL.WaitEvent(event)
106
- break if event[:common][:type] == SDL::QUIT || self.class.stopped
107
- if process_input(input, event)
108
- # since we are using wait event, we need to process the render twice
109
- # once to capture all events, and once after updating block state.
110
- SDL.SetRenderDrawBlendMode(renderer, SDL::BLENDMODE_NONE)
111
- SDL.SetRenderDrawColor(renderer, config.background[:r], config.background[:g], config.background[:b], config.background[:a])
112
- SDL.RenderClear(renderer)
113
- canvas.reset(nil, nil, render_width.to_f, render_height.to_f)
114
- painter = Hokusai::Painter.new(block, input)
115
- painter.render(canvas, resize)
116
- block.update
117
- SDL.RenderPresent(renderer)
118
-
119
- SDL.SetRenderDrawBlendMode(renderer, SDL::BLENDMODE_NONE)
120
- SDL.SetRenderDrawColor(renderer, config.background[:r], config.background[:g], config.background[:b], config.background[:a])
121
- SDL.RenderClear(renderer)
122
- canvas.reset(nil, nil, render_width.to_f, render_height.to_f)
123
- painter = Hokusai::Painter.new(block, input)
124
- painter.render(canvas, resize, capture: false)
125
- SDL.RenderPresent(renderer)
137
+ if SDL.PollEvent(event)
138
+ self.class.stopped = true if event[:common][:type] == SDL::QUIT || self.class.stopped
139
+
140
+ process_input(input, event)
141
+ if config.touch
142
+ if input.touch.touching?
143
+ token = input.touch.token
144
+
145
+ LibHokusai.hoku_input_set_mouse_position(input.raw, hml_vec2(token[:x], token[:y]))
146
+ end
147
+
148
+ # translate taps to clicks
149
+ if input.touch.tapped?
150
+ button = mouse_button(clicked: true, down: true, released: false, up: false)
151
+ LibHokusai.hoku_input_mouse_set_button(input.raw, button, 0)
152
+ else
153
+ button = mouse_button(clicked: false, down: false, released: true, up: true)
154
+ LibHokusai.hoku_input_mouse_set_button(input.raw, button, 0)
155
+ end
156
+ end
126
157
  end
158
+
159
+ break if self.class.stopped
160
+ # since we are using wait event, we need to process the render twice
161
+ # once to capture all events, and once after updating block state.
162
+ SDL.SetRenderDrawBlendMode(renderer, SDL::BLENDMODE_BLEND)
163
+ SDL.SetRenderDrawColor(renderer, config.background[:r], config.background[:g], config.background[:b], config.background[:a])
164
+ SDL.RenderClear(renderer)
165
+ canvas.reset(0.0, 0.0, render_width.to_f, render_height.to_f)
166
+ painter = Hokusai::Painter.new(block, input)
167
+ painter.render(canvas, resize)
168
+
169
+ SDL.RenderPresent(renderer)
170
+ block.update
171
+
172
+ # SDL.SetRenderDrawBlendMode(renderer, SDL::BLENDMODE_NONE)
173
+ # SDL.SetRenderDrawColor(renderer, config.background[:r], config.background[:g], config.background[:b], config.background[:a])
174
+ # SDL.RenderClear(renderer)
175
+ # canvas.reset(nil, nil, render_width.to_f, render_height.to_f)
176
+ # painter = Hokusai::Painter.new(block, input)
177
+ # painter.render(canvas, resize, capture: false)
178
+ # SDL.RenderPresent(renderer)
179
+ SDL.Delay(10)
127
180
  end
128
181
 
129
182
  LibHokusai.hoku_input_free(input.raw)
@@ -157,52 +210,78 @@ module Hokusai::Backends
157
210
  end
158
211
 
159
212
  def reset_keys(input)
160
- LibHokusai.hoku_input_keyboard_start(input.raw)
161
- Modifiers.each do |(sdlk, hkey)|
162
- LibHokusai.hoku_input_keyboard_set_key(input.raw, hkey, false)
163
- end
213
+ if !input.keyboard_override
214
+ LibHokusai.hoku_input_keyboard_start(input.raw)
215
+ Modifiers.each do |(sdlk, hkey)|
216
+ LibHokusai.hoku_input_keyboard_set_key(input.raw, hkey, false)
217
+ end
164
218
 
165
- Keys.values.each do |hkey|
166
- LibHokusai.hoku_input_keyboard_set_key(input.raw, hkey, false)
167
- end
219
+ Keys.values.each do |hkey|
220
+ LibHokusai.hoku_input_keyboard_set_key(input.raw, hkey, false)
221
+ end
168
222
 
169
- LibHokusai.hoku_input_keyboard_stop(input.raw)
223
+ LibHokusai.hoku_input_keyboard_stop(input.raw)
224
+ end
170
225
  end
171
226
 
172
227
  def process_input(input, event)
173
228
  reset_keys(input)
174
229
 
230
+ t = event[:common][:type]
231
+ if config.touch && t != SDL::FINGERDOWN && t != SDL::WINDOWEVENT && t != SDL::FINGERUP && t != SDL::FINGERMOTION && t != SDL::MOUSEMOTION && t != SDL::POLLSENTINEL
232
+ input.touch.clear
233
+ end
234
+
175
235
  case event[:common][:type]
176
- when SDL::KEYDOWN
177
- modifier = event[:key][:keysym][:mod]
178
- code = event[:key][:keysym][:sym]
179
- hkey = Keys[code]
236
+ when SDL::FINGERDOWN
237
+ x = event[:tfinger][:x] * render_width
238
+ y = event[:tfinger][:y] * render_height
180
239
 
181
- LibHokusai.hoku_input_keyboard_start(input.raw)
182
- Modifiers.each do |(sdlk, hkey)|
183
- if modifier & sdlk == sdlk
184
- LibHokusai.hoku_input_keyboard_set_key(input.raw, hkey, true)
240
+ input.touch.record(0, x, y)
241
+ return true
242
+ when SDL::FINGERUP
243
+ input.touch.clear
244
+ return true
245
+ when SDL::FINGERMOTION
246
+ x = event[:tfinger][:x] * render_width
247
+ y = event[:tfinger][:y] * render_height
248
+
249
+ input.touch.record(0, x, y)
250
+ return true
251
+ when SDL::KEYDOWN
252
+ if !input.keyboard_override
253
+ modifier = event[:key][:keysym][:mod]
254
+ code = event[:key][:keysym][:sym]
255
+ hkey = Keys[code]
256
+
257
+ LibHokusai.hoku_input_keyboard_start(input.raw)
258
+ Modifiers.each do |(sdlk, hkey)|
259
+ if modifier & sdlk == sdlk
260
+ LibHokusai.hoku_input_keyboard_set_key(input.raw, hkey, true)
261
+ end
185
262
  end
186
- end
187
263
 
188
- LibHokusai.hoku_input_keyboard_set_key(input.raw, hkey, true) unless hkey.nil?
189
- LibHokusai.hoku_input_keyboard_stop(input.raw)
264
+ LibHokusai.hoku_input_keyboard_set_key(input.raw, hkey, true) unless hkey.nil?
265
+ LibHokusai.hoku_input_keyboard_stop(input.raw)
266
+ end
190
267
 
191
268
  return true
192
269
  when SDL::KEYUP
193
- modifier = event[:key][:keysym][:mod]
194
- code = event[:key][:keysym][:sym]
195
- hkey = Keys[code]
196
-
197
- LibHokusai.hoku_input_keyboard_start(input.raw)
198
- Modifiers.each do |(sdlk, hkey)|
199
- if modifier & sdlk == sdlk
200
- LibHokusai.hoku_input_keyboard_set_key(input.raw, hkey, false)
270
+ if !input.keyboard_override
271
+ modifier = event[:key][:keysym][:mod]
272
+ code = event[:key][:keysym][:sym]
273
+ hkey = Keys[code]
274
+
275
+ LibHokusai.hoku_input_keyboard_start(input.raw)
276
+ Modifiers.each do |(sdlk, hkey)|
277
+ if modifier & sdlk == sdlk
278
+ LibHokusai.hoku_input_keyboard_set_key(input.raw, hkey, false)
279
+ end
201
280
  end
202
- end
203
281
 
204
- LibHokusai.hoku_input_keyboard_set_key(input.raw, hkey, false) unless hkey.nil?
205
- LibHokusai.hoku_input_keyboard_stop(input.raw)
282
+ LibHokusai.hoku_input_keyboard_set_key(input.raw, hkey, false) unless hkey.nil?
283
+ LibHokusai.hoku_input_keyboard_stop(input.raw)
284
+ end
206
285
  return true
207
286
  when SDL::WINDOWEVENT
208
287
  if event[:window][:event] == SDL::WINDOWEVENT_RESIZED
@@ -257,20 +336,34 @@ module Hokusai::Backends
257
336
  clicked = event[:button][:clicks] > 0
258
337
  button = mouse_button(down: true, clicked: clicked)
259
338
 
260
- # LibHokusai.hoku_input_mouse_set_scroll(input.raw, 0.0)
261
- # input.raw[:mouse][:delta][:y] = 0.0
339
+ LibHokusai.hoku_input_mouse_set_scroll(input.raw, 0.0)
340
+ input.raw[:mouse][:delta][:y] = 0.0
262
341
 
263
342
  LibHokusai.hoku_input_mouse_set_button(input.raw, button, event[:button][:which])
264
343
  return true
265
344
  when SDL::MOUSEBUTTONUP
266
345
  button = mouse_button(up: true)
267
346
  #
268
- # LibHokusai.hoku_input_mouse_set_scroll(input.raw, 0.0)
269
- # input.raw[:mouse][:delta][:y] = 0.0
347
+ LibHokusai.hoku_input_mouse_set_scroll(input.raw, 0.0)
348
+ input.raw[:mouse][:delta][:y] = 0.0
270
349
 
271
350
  LibHokusai.hoku_input_mouse_set_button(input.raw, button, event[:button][:which])
272
351
  return true
273
352
  when SDL::TEXTINPUT
353
+ char = event[:text][:text].to_s
354
+ LibHokusai.hoku_input_keyboard_start(input.raw)
355
+
356
+ Modifiers.each do |(sdlk, hkey)|
357
+ LibHokusai.hoku_input_keyboard_set_key(input.raw, hkey, false)
358
+ end
359
+ LibHokusai.hoku_input_keyboard_set_key(input.raw, char.to_sym, true)
360
+ LibHokusai.hoku_input_keyboard_stop(input.raw)
361
+
362
+ return true
363
+ when SDL::TEXTEDITING
364
+ # start = event[:edit][:start]
365
+ # len = event[:edit][:length]
366
+ # text = event[:edit][:text]
274
367
  return false
275
368
  else
276
369
  false
@@ -410,16 +503,21 @@ module Hokusai::Backends
410
503
  self.class.images[command.source]
411
504
  else
412
505
  file = File.read(command.source)
413
-
414
- rw = SDL.RWFromConstMem(file, file.size)
415
- surface_ptr = SDL.IMG_Load_RW(rw, 1)
416
- if surface_ptr.null?
506
+ SDL.SetHint(SDL::HINT_RENDER_SCALE_QUALITY, "0");
507
+ texture = SDL.IMG_LoadTexture(renderer, command.source)
508
+ if texture.null?
417
509
  raise Hokusai::Error.new("Can't load Image: #{SDL.GetError.read_string}")
418
510
  end
419
511
 
420
- texture = SDL.CreateTextureFromSurface(renderer, surface_ptr)
512
+ # rw = SDL.RWFromConstMem(file, file.size)
513
+ # surface_ptr = SDL.IMG_LoadSVG_RW(rw)
514
+ # if surface_ptr.null?
515
+ # raise Hokusai::Error.new("Can't load Image: #{SDL.GetError.read_string}")
516
+ # end
517
+
518
+ # texture = SDL.CreateTextureFromSurface(renderer, surface_ptr)
421
519
  self.class.images[command.source] = texture
422
- SDL.FreeSurface(surface_ptr)
520
+ # SDL.FreeSurface(surface_ptr)
423
521
  texture
424
522
  end
425
523
  end
@@ -431,6 +529,7 @@ module Hokusai::Backends
431
529
 
432
530
  Hokusai::Commands::Rect.on_draw do |command|
433
531
  next unless inside_scissor(command.x, command.y, command.height)
532
+ next if command.color.a == 0
434
533
  # draw background first
435
534
  x, y, w, h = [command.x, command.y, command.width, command.height]
436
535
 
@@ -506,7 +605,6 @@ module Hokusai::Backends
506
605
  rounding = command.rounding
507
606
 
508
607
  if command.rounding > 0
509
- pp command.color
510
608
  SDL.roundedBoxRGBA(renderer, x, y, x + w, y + h, (command.rounding).ceil.to_i, command.color.r, command.color.g, command.color.b, command.color.a)
511
609
  else
512
610
  rect = SDL::Rect.new
@@ -515,6 +613,7 @@ module Hokusai::Backends
515
613
  rect[:w] = w
516
614
  rect[:h] = h
517
615
 
616
+ SDL.SetRenderDrawBlendMode(renderer, SDL::BLENDMODE_BLEND)
518
617
  SDL.SetRenderDrawColor(renderer, command.color.r, command.color.g, command.color.b, command.color.a)
519
618
  SDL.RenderFillRect(renderer, rect)
520
619
  end
@@ -87,7 +87,7 @@ class Hokusai::Blocks::Input < Hokusai::Block
87
87
  end
88
88
 
89
89
  def dynamic_keypress_handle(event)
90
- return unless node.meta.focused
90
+ return unless node.meta.focused || event.input.keyboard_override
91
91
  case event
92
92
  when proc(&:ctrl), proc(&:super)
93
93
  if event.char == "z"