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
@@ -1,540 +0,0 @@
1
- require "raylib"
2
- require 'memory_profiler'
3
-
4
- # frozen_string_literal: true
5
-
6
- module Hokusai::Backends
7
- class EmbeddedBackend
8
-
9
- RAYLIB_PATH = ENV["RAYLIB_PATH"] || begin
10
- path = "#{__dir__}/../../../../vendor/lib"
11
- case RbConfig::CONFIG['host_os']
12
- when /darwin/
13
- "#{path}/libraylib.dylib"
14
- when /mswin|msys|mingw/
15
- "#{path}/libraylib.dll"
16
- when /linux/
17
- "#{path}/libraylib.so"
18
- end
19
- end
20
-
21
- attr_reader :config
22
- attr_accessor :last_touch, :last_gesture, :touches, :stuff
23
-
24
- def self.icons
25
- @icons ||= {}
26
- end
27
-
28
- def self.images
29
- @images ||= {}
30
- end
31
-
32
- def self.shaders
33
- @shaders ||= {}
34
- end
35
-
36
- def self.stopped?
37
- @stop = false if @stop.nil?
38
-
39
- @stop
40
- end
41
-
42
- def self.stop!
43
- @stop = true
44
- end
45
-
46
- def self.reset
47
- @stop = false
48
- end
49
-
50
- def initialize
51
- @config = Config.new
52
-
53
- yield(config)
54
- end
55
-
56
- def vec2(x, y, fresh = false)
57
- if @raylib_vec2.nil? || fresh
58
- @raylib_vec2 = Raylib::Vector2.new
59
- end
60
- @raylib_vec2[:x] = x
61
- @raylib_vec2[:y] = y
62
-
63
- @raylib_vec2
64
- end
65
-
66
- def hml_vec2(x, y)
67
- if @hml_vec2.nil?
68
- @hml_vec2 = LibHokusai::HmlVec2.create(x, y)
69
- else
70
- @hml_vec2[:x] = x
71
- @hml_vec2[:y] = y
72
- end
73
-
74
- @hml_vec2
75
- end
76
-
77
- def color(hc, fresh = false)
78
- if @raylib_color.nil? || fresh
79
- @raylib_color = Raylib::Color.from_u8(hc.red, hc.green, hc.blue, hc.alpha)
80
- else
81
- @raylib_color[:r] = hc.red
82
- @raylib_color[:g] = hc.green
83
- @raylib_color[:b] = hc.blue
84
- @raylib_color[:a] = hc.alpha
85
- end
86
-
87
- @raylib_color
88
- end
89
-
90
- def rect(arr)
91
- if @raylib_rect.nil?
92
- @raylib_rect = Raylib::Rectangle.create(arr[0], arr[1], arr[2], arr[3])
93
- else
94
- @raylib_rect[:x] = arr[0]
95
- @raylib_rect[:y] = arr[1]
96
- @raylib_rect[:width] = arr[2]
97
- @raylib_rect[:height] = arr[3]
98
- end
99
-
100
- @raylib_rect
101
- end
102
-
103
- def mouse_button(clicked: false, down: false, released: false, up: false)
104
- if @mouse_button.nil?
105
- @mouse_button = LibHokusai::HmlInputMouseButton.create(clicked: clicked, down: down, released: released, up: up)
106
- else
107
- @mouse_button[:clicked] = clicked
108
- @mouse_button[:down] = down
109
- @mouse_button[:released] = released
110
- @mouse_button[:up] = up
111
- end
112
-
113
- @mouse_button
114
- end
115
-
116
- def process_input(input)
117
- self.touches = Raylib.GetTouchPointCount
118
- if touches > 0
119
- touches.times do |i|
120
- vec = Raylib.GetTouchPosition
121
-
122
- if LibHokusai.hoku_input_record_touch(input.raw, i, vec.x, vec.y) == -1
123
- raise Hokusai::Error.new("Could not record touch")
124
- end
125
- end
126
- else
127
- config.max_touch_count.times do |i|
128
- LibHokusai.hoku_input_clear_touch(input.raw, i)
129
- end
130
- end
131
-
132
- # translate taps to clicks
133
- if input.touch.tapped?
134
- button = mouse_button(clicked: true, down: true, released: false, up: false)
135
- LibHokusai.hoku_input_mouse_set_button(input.raw, button, 0)
136
- else
137
- button = mouse_button(clicked: false, down: false, released: true, up: true)
138
- LibHokusai.hoku_input_mouse_set_button(input.raw, button, 0)
139
- end
140
- end
141
-
142
- def self.run(app)
143
- backend = new do |config|
144
- yield config
145
- end
146
-
147
- block = app.mount
148
- backend.run(block)
149
- end
150
-
151
- def run(block)
152
- self.class.reset
153
-
154
- Raylib.load_lib(RAYLIB_PATH)
155
-
156
- resize = false
157
- initial = true
158
- width = config.width
159
- height = config.height
160
-
161
- register_command_handlers
162
-
163
- ptr = FFI::MemoryPointer.new :pointer
164
- LibHokusai.hoku_input_init(ptr)
165
- raw = LibHokusai::HmlInput.new(ptr.get_pointer(0))
166
- LibHokusai.hoku_input_attach_touch(raw, config.max_touch_count)
167
-
168
- input = Hokusai::Input.new(raw)
169
- ptr.free
170
-
171
- Raylib.SetConfigFlags(config.config_flags)
172
- Raylib.InitWindow(config.width, config.height, config.title)
173
- Raylib.SetTargetFPS(config.fps)
174
- Raylib.SetWindowState(config.window_state_flags)
175
-
176
- unless Hokusai.fonts.get("default")
177
- Hokusai.fonts.register "default", Hokusai::Backends::EmbeddedBackend::Font.default
178
- Hokusai.fonts.activate "default"
179
- end
180
-
181
- config.after_load_cb&.call
182
-
183
- if config.automated
184
- config.start_automation_driver
185
- end
186
-
187
- canvas = Hokusai::Canvas.new(width.to_f, height.to_f, 0.0, 0.0)
188
- @texture = Raylib.LoadRenderTexture(width, height)
189
- Raylib.SetTextureFilter(@texture.texture, Raylib::TEXTURE_FILTER_POINT)
190
-
191
- width = nil
192
- height = nil
193
-
194
- MemoryProfiler.start if ENV["PROFILE"]
195
-
196
- Raylib.EnableEventWaiting if config.event_waiting
197
- last_input_hash = nil
198
-
199
- until Raylib.WindowShouldClose
200
- if Raylib.IsWindowFocused
201
- Raylib.DisableEventWaiting
202
- else
203
- Raylib.EnableEventWaiting
204
- end
205
-
206
- last_width = Raylib.GetScreenWidth
207
- last_height = Raylib.GetScreenHeight
208
-
209
- if last_width != width || last_height != height
210
- resize = true
211
- else
212
- resize = false
213
- end
214
-
215
- width = last_width
216
- height = last_height
217
-
218
- process_input(input)
219
- block.public_send(:before_updated) if block.respond_to?(:before_updated)
220
- block.update
221
- block.public_send(:after_updated) if block.respond_to?(:after_updated)
222
-
223
- canvas.reset(nil, nil, width.to_f, height.to_f)
224
-
225
- Raylib.BeginDrawing
226
- Raylib.ClearBackground(config.background)
227
-
228
- painter = Hokusai::Painter.new(block, input)
229
-
230
- if config.automation_driver
231
- painter.on_before_render do |blocks, canvas, input|
232
- config.automation_driver.process(blocks, canvas, input)
233
- end
234
-
235
- painter.on_after_render do
236
- config.automation_driver.complete
237
- end
238
-
239
- sleep 0.004
240
- end
241
-
242
- painter.render(canvas, resize)
243
-
244
- Raylib.DrawText("Touches: #{touches}", 10, 10, 14, color(Hokusai::Color.new(244,22,22)));
245
- Raylib.DrawText("Stuff: #{stuff}", 10, 24, 14, color(Hokusai::Color.new(244,22,22))) if stuff
246
-
247
- Raylib.DrawFPS(10, 10) if ENV["PROFILE"] || ENV["FPS"]
248
- Raylib.EndDrawing
249
-
250
-
251
- break if self.class.stopped?
252
- end
253
-
254
- Hokusai.fonts.fonts.each do |key, font|
255
- Raylib.UnloadFont(font.raw)
256
- end
257
-
258
- self.class.images.each do |_, texture|
259
- Raylib.UnloadTexture(texture)
260
- end
261
-
262
- self.class.shaders.each do |k, shader|
263
- Raylib.UnloadShader(shader)
264
- end
265
-
266
- LibHokusai.hoku_input_free(input.raw)
267
-
268
- if ENV["PROFILE"]
269
- report = MemoryProfiler.stop
270
- report.pretty_print(scale_bytes: true)
271
- end
272
-
273
- Raylib.CloseWindow
274
-
275
- config.automation_driver&.stop
276
- end
277
-
278
- def shader_value(value, type)
279
- case type
280
- when Hokusai::SHADER_UNIFORM_FLOAT
281
- ptr = FFI::MemoryPointer.new(:float)
282
- ptr.write_float(value)
283
- ptr
284
- when Hokusai::SHADER_UNIFORM_INT
285
- ptr = FFI::MemoryPointer.new(:int)
286
- ptr.write_int(value)
287
- ptr
288
- when Hokusai::SHADER_UNIFORM_IVEC2, Hokusai::SHADER_UNIFORM_UIVEC2, Hokusai::SHADER_UNIFORM_VEC2
289
- Raylib::Vector2.create(*value)
290
- when Hokusai::SHADER_UNIFORM_VEC3, Hokusai::SHADER_UNIFORM_IVEC3, Hokusai::SHADER_UNIFORM_UIVEC3
291
- Raylib::Vector3.create(*value)
292
- when Hokusai::SHADER_UNIFORM_VEC4, Hokusai::SHADER_UNIFORM_UIVEC4, Hokusai::SHADER_UNIFORM_IVEC4
293
- Raylib::Vector4.create(*value)
294
- end
295
- end
296
-
297
-
298
- def inside_scissor(x, y, h = 0)
299
- return true if @scissor.nil?
300
-
301
- val = y + h >= @scissor[1] && y <= @scissor[1] + @scissor[3]
302
- val
303
- end
304
-
305
- def register_command_handlers
306
- Hokusai.on_close_window do
307
- self.class.stop!
308
- end
309
-
310
- Hokusai.on_set_mouse_cursor do |type|
311
- raylib_type = {
312
- default: Raylib::MOUSE_CURSOR_DEFAULT,
313
- arrow: Raylib::MOUSE_CURSOR_ARROW,
314
- ibeam: Raylib::MOUSE_CURSOR_IBEAM,
315
- crosshair: Raylib::MOUSE_CURSOR_CROSSHAIR,
316
- pointer: Raylib::MOUSE_CURSOR_POINTING_HAND,
317
- none: -1,
318
- }[type]
319
-
320
- raise Hokusai::Error.new("Cursor #{type} not recognized") if raylib_type.nil?
321
-
322
- if raylib_type == -1
323
- Raylib.HideCursor
324
- else
325
- Raylib.ShowCursor
326
- Raylib::SetMouseCursor(raylib_type)
327
- end
328
- end
329
-
330
- Hokusai.on_set_mouse_position do |mouse|
331
- Raylib.SetMousePosition(mouse.pos.x, mouse.pos.y)
332
- end
333
-
334
- Hokusai.on_set_window_position do |(dx, dy)|
335
- wpos = Raylib.GetWindowPosition
336
-
337
- Raylib.SetWindowPosition(wpos.x + dx, wpos.y + dy)
338
- end
339
-
340
- Hokusai.on_restore_window do
341
- Raylib.RestoreWindow
342
- end
343
-
344
- Hokusai.on_maximize_window do
345
- if Raylib.IsWindowMaximized
346
- Raylib.RestoreWindow
347
- else
348
- Raylib.MaximizeWindow
349
- end
350
- end
351
-
352
- Hokusai.on_minimize_window do
353
- Raylib.MinimizeWindow
354
- end
355
-
356
- Hokusai.on_renderable do |canvas|
357
- inside_scissor(canvas.x, canvas.y, canvas.height)
358
- end
359
-
360
- Hokusai::Commands::ShaderBegin.on_draw do |command|
361
- self.class.shaders[command.hash] ||= Raylib.LoadShaderFromMemory(command.vertex_shader, command.fragment_shader)
362
-
363
- unless command.uniforms.empty?
364
- command.uniforms.each do |key, value|
365
- location = Raylib.GetShaderLocation(self.class.shaders[command.hash], key.to_s)
366
-
367
- ptr = shader_value(value[0], value[1])
368
- Raylib.SetShaderValue(self.class.shaders[command.hash], location, ptr, value[1])
369
- ptr.free if ptr.is_a?(FFI::MemoryPointer)
370
- end
371
- end
372
-
373
- Raylib.BeginShaderMode(self.class.shaders[command.hash])
374
-
375
- @shader = self.class.shaders[command.hash]
376
- end
377
-
378
- Hokusai::Commands::ShaderEnd.on_draw do |_|
379
- Raylib.EndShaderMode
380
-
381
- @shader = nil
382
- end
383
-
384
- Hokusai::Commands::Texture.on_draw do |command|
385
- self.class.images[command.hash] ||= begin
386
- image = Raylib.GenImageColor(command.width, command.height, Raylib::BLANK)
387
- Raylib.LoadTextureFromImage(image)
388
- end
389
- Raylib.DrawTexture(self.class.images[command.hash], command.x, command.y, Raylib::WHITE)
390
- end
391
-
392
- Hokusai::Commands::ScissorBegin.on_draw do |command|
393
- Raylib.BeginScissorMode(command.x, command.y, command.width, command.height)
394
- @scissor = [command.x, command.y, command.width, command.height]
395
- end
396
-
397
- Hokusai::Commands::ScissorEnd.on_draw do |_|
398
- Raylib.EndScissorMode
399
- @scissor = nil
400
- end
401
-
402
- Hokusai::Commands::Circle.on_draw do |command|
403
- next unless inside_scissor(command.x, command.y)
404
-
405
- radius = command.radius - command.outline
406
- rc = command.color
407
- color = Raylib::Color.from_u8(rc.r, rc.g, rc.b, rc.a)
408
- Raylib.DrawCircleV(vec2(command.x, command.y), radius, color)
409
-
410
- if command.outline > 0
411
- Raylib.DrawCircleLines(command.x.ceil.to_i, command.y.ceil.to_i, command.radius, color(command.color))
412
- end
413
- end
414
-
415
- Hokusai::Commands::SVG.on_draw do |command|
416
- texture = begin
417
- if self.class.images[command.source]
418
- self.class.images[command.source]
419
- else
420
- img = Raylib.LoadImageSVG(command.source, command.width, command.height)
421
- texture = Raylib.load_texture_from_image(img)
422
- Raylib.UnloadImage(img)
423
- self.class.images[command.source] = texture
424
- texture
425
- end
426
- end
427
-
428
- Raylib.DrawTexture(texture, command.x, command.y, color(command.color))
429
- end
430
-
431
- Hokusai::Commands::Image.on_draw do |command|
432
- next unless inside_scissor(command.x, command.y, command.height)
433
-
434
- texture = begin
435
- if self.class.images[command.cache]
436
- self.class.images[command.cache]
437
- else
438
- img = Raylib.LoadImage(command.source)
439
- Raylib.ImageResize(img.to_ptr, command.width, command.height)
440
-
441
- texture = Raylib.LoadTextureFromImage(img)
442
- Raylib.UnloadImage(img)
443
- self.class.images[command.cache] = texture
444
- texture
445
- end
446
- end
447
-
448
- Raylib.DrawTexture(texture, command.x, command.y, Raylib::WHITE)
449
- end
450
-
451
- Hokusai::Commands::Text.on_draw do |command|
452
- next unless inside_scissor(command.x, command.y, command.size)
453
-
454
- active_name = Hokusai.fonts.active_font_name
455
- font = Hokusai.fonts.active
456
-
457
- Hokusai.fonts.activate command.font.nil? ? active_name : command.font
458
- font = Hokusai.fonts.active
459
-
460
- c = color(command.color)
461
- x = command.x + command.padding.l
462
- y = command.y + command.padding.t
463
-
464
- if fnt = font
465
- # content = FFI::MemoryPointer.from_string(command.content)
466
- Raylib.DrawTextEx(fnt.raw, command.content.to_s, vec2(x, y), command.size, fnt.spacing, c)
467
- # content.free
468
- else
469
- Raylib.DrawText(command.content, x, y, command.size, c)
470
- end
471
-
472
- Hokusai.fonts.activate active_name
473
- end
474
-
475
- Hokusai::Commands::Rect.on_draw do |command|
476
- next unless inside_scissor(command.x, command.y, command.height)
477
-
478
- background_color = color(command.color)
479
- # the rect has an outline
480
- # so we want to render twice
481
- if command.outline?
482
- # for Raylib, the boundaries for background and outline are the same
483
- # rectangles render in from the boundary
484
- # and outlines render out from the boundary
485
- # background_rect = outline_rect
486
- outline_rect = rect(command.background_boundary)
487
- background_rect = outline_rect
488
- # rect is rounded so we need a rounded outline and
489
- # a regular one
490
- if command.rounding > 0
491
- Raylib.DrawRectangleRounded(background_rect, command.rounding, 50, background_color)
492
- else
493
- Raylib.DrawRectangleRec(background_rect, background_color)
494
- end
495
-
496
- outline_color = color(command.outline_color)
497
-
498
- # now draw the outlines
499
- if command.outline_uniform? && command.rounding > 0.0 && outline_color.a > 0
500
- Raylib.DrawRectangleRoundedLinesEx(outline_rect, command.rounding, 50, command.outline.top + 1, outline_color)
501
- elsif command.outline_uniform? && !(command.rounding <= 0.0) && outline_color.a > 0
502
- Raylib.DrawRectangleLinesEx(outline_rect, command.outline.top, outline_color)
503
- elsif !command.outline_uniform?
504
- ox, oy, ow, oh = command.background_boundary
505
-
506
- if command.outline.top > 0.0
507
- Raylib.DrawLineEx(vec2(ox, oy, true), vec2(ox + ow, oy, true), command.outline.top, outline_color)
508
- end
509
-
510
- if command.outline.left > 0.0
511
- Raylib.DrawLineEx(vec2(ox, oy, true), vec2(ox, oy + oh, true), command.outline.left, outline_color)
512
- end
513
-
514
- if command.outline.right > 0.0
515
- Raylib.DrawLineEx(vec2(ox + ow, oy, true), vec2(ox + ow, oy + oh, true), command.outline.right, outline_color)
516
- end
517
-
518
- if command.outline.bottom > 0.0
519
- Raylib.DrawLineEx(vec2(ox, oy + oh, true), vec2(ox + ow, oy + oh, true), command.outline.bottom, outline_color)
520
- end
521
- end
522
- else
523
- rect = rect(command.background_boundary)
524
- if command.gradient
525
- Raylib.DrawRectangleGradientEx(rect, color(command.gradient[0], true), color(command.gradient[1], true), color(command.gradient[2], true), color(command.gradient[3], true))
526
- elsif command.rounding > 0
527
- Raylib.DrawRectangleRounded(rect, command.rounding, 50, background_color)
528
- else
529
- Raylib.DrawRectangleRec(rect, background_color)
530
- end
531
- end
532
- end
533
- end
534
- end
535
- end
536
-
537
- require_relative "../../hokusai/font"
538
- require_relative "./embedded/config"
539
- require_relative "./embedded/font"
540
- require_relative "./embedded/keys"