hokusai-zero 0.2.5 → 0.2.6.pre.pinephone

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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +0 -1
  3. data/Gemfile.lock +0 -2
  4. data/README.md +1 -1
  5. data/ast/src/core/input.c +85 -0
  6. data/ast/src/core/input.h +31 -0
  7. data/ast/src/core/util.c +23 -23
  8. data/ast/src/core/util.h +7 -7
  9. data/ext/extconf.rb +7 -3
  10. data/hokusai.gemspec +1 -2
  11. data/ui/examples/drag.rb +154 -0
  12. data/ui/examples/embedded.rb +59 -0
  13. data/ui/examples/game.rb +143 -0
  14. data/ui/examples/overlay.rb +233 -0
  15. data/ui/examples/provider.rb +56 -0
  16. data/ui/examples/shader/test.rb +145 -0
  17. data/ui/examples/shader.rb +100 -0
  18. data/ui/examples/wiki.rb +82 -0
  19. data/ui/lib/lib_hokusai.rb +29 -8
  20. data/ui/spec/spec_helper.rb +1 -1
  21. data/ui/src/hokusai/assets/arrow-down-line.png +0 -0
  22. data/ui/src/hokusai/assets/arrow-down-wide-line.png +0 -0
  23. data/ui/src/hokusai/automation/server.rb +2 -3
  24. data/ui/src/hokusai/backends/embedded/config.rb +47 -0
  25. data/ui/src/hokusai/backends/embedded/font.rb +112 -0
  26. data/ui/src/hokusai/backends/embedded/keys.rb +124 -0
  27. data/ui/src/hokusai/backends/embedded.rb +564 -0
  28. data/ui/src/hokusai/backends/raylib.rb +80 -5
  29. data/ui/src/hokusai/blocks/color_picker.rb +1080 -0
  30. data/ui/src/hokusai/blocks/shader_begin.rb +22 -0
  31. data/ui/src/hokusai/blocks/shader_end.rb +12 -0
  32. data/ui/src/hokusai/blocks/texture.rb +23 -0
  33. data/ui/src/hokusai/commands/rect.rb +10 -1
  34. data/ui/src/hokusai/commands/shader.rb +33 -0
  35. data/ui/src/hokusai/commands/texture.rb +26 -0
  36. data/ui/src/hokusai/commands.rb +22 -0
  37. data/ui/src/hokusai/event.rb +2 -1
  38. data/ui/src/hokusai/events/embedded.rb +66 -0
  39. data/ui/src/hokusai/painter.rb +22 -0
  40. data/ui/src/hokusai/types.rb +29 -0
  41. data/ui/src/hokusai.rb +4 -9
  42. metadata +24 -22
  43. data/ui/src/hokusai/assets/chevron-down.svg +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 258655d3f20b0989fc428b59e1346fcce0cf2d3171cbd84734f76ab466147c41
4
- data.tar.gz: dba94b3629f93488d2629440aa70e3f8e60e005814ba3a189c26cac1cb213698
3
+ metadata.gz: ff2e748026518a381a084842d38e6499cbc21ba6ae82ef8eecea9fcf1caac01d
4
+ data.tar.gz: b6f6552079320c6345dc2332c1876e4ad4640ae91edd1b80b5886cbb7e5a2a81
5
5
  SHA512:
6
- metadata.gz: 05404fcf63164d6201d7ec3061ff2076a31dd3b2a8061940587aa099e84632afa07621fbbe9a79ac978ca374a22f72e2408d277db22b34c0076f0bffd3bcda4f
7
- data.tar.gz: c074724a12bf76772f9052fccbf06cbd49ff55e871d763c2477bc2a242650a74deaee9a5c3c67dedaae9058b89eefb3b94399ce1daf5d3eeb45c5098a8b3958b
6
+ metadata.gz: b4d95dbfd485c9948af925f0d824383198a8676fa87714c1b8937b1c34c22bd0f384c86774a67e44e1e941fcfcad745e7576d287edc23f064022369d5187fad2
7
+ data.tar.gz: 73f8f5e98862ff3c219a61f570298e634a3d4293d619b6c79b557a5f499da96992366eb0f5ecf1f7adc7998f98d83ae54a878ee3445c527d262045cd41305038
data/Gemfile CHANGED
@@ -3,7 +3,6 @@ source "https://www.rubygems.org"
3
3
  gem "ffi", github: "ffi/ffi", submodules: true
4
4
 
5
5
  group :development, :test do
6
- gem "concurrent-ruby", require: "concurrent"
7
6
  gem "memory_profiler", require: false
8
7
  gem "mini_portile2", "~> 2.0.0"
9
8
  gem "raylib-bindings"
data/Gemfile.lock CHANGED
@@ -8,7 +8,6 @@ GIT
8
8
  GEM
9
9
  remote: https://www.rubygems.org/
10
10
  specs:
11
- concurrent-ruby (1.3.5)
12
11
  daemons (1.4.1)
13
12
  diff-lcs (1.6.1)
14
13
  domain_name (0.6.20240107)
@@ -77,7 +76,6 @@ PLATFORMS
77
76
  x86_64-linux
78
77
 
79
78
  DEPENDENCIES
80
- concurrent-ruby
81
79
  ffi!
82
80
  memory_profiler
83
81
  mini_portile2 (~> 2.0.0)
data/README.md CHANGED
@@ -12,7 +12,7 @@ A Ruby library for authoring GUI applications
12
12
  In your Gemfile
13
13
 
14
14
  ```ruby
15
- gem "hokusai-zero", "0.2.4"
15
+ gem "hokusai-zero", "0.2.6"
16
16
  ```
17
17
 
18
18
  ## In order to run an application, you will need to install a backend
data/ast/src/core/input.c CHANGED
@@ -4,6 +4,84 @@
4
4
  #include "input.h"
5
5
  #include <stdio.h>
6
6
 
7
+ int hoku_input_embedded_init(hoku_input_embedded** embedded)
8
+ {
9
+ hoku_input_embedded* out = malloc(sizeof(hoku_input_embedded));
10
+ if (!out) return -1;
11
+
12
+ out->drag_pos = malloc(sizeof(hoku_vec2));
13
+ if (out->drag_pos == NULL)
14
+ {
15
+ free(out);
16
+ return -1;
17
+ }
18
+
19
+ out->pinch_pos = malloc(sizeof(hoku_vec2));
20
+ if (out->pinch_pos == NULL)
21
+ {
22
+ free(out->drag_pos);
23
+ free(out);
24
+ return -1;
25
+ }
26
+
27
+ out->drag_pos->x = 0.0;
28
+ out->drag_pos->y = 0.0;
29
+ out->pinch_pos->x = 0.0;
30
+ out->pinch_pos->y = 0.0;
31
+ out->hold = false;
32
+ out->drag = false;
33
+ out->pinch = false;
34
+ out->drag_direction = HOKU_DRAG_UP;
35
+ out->pinch_direction = HOKU_PINCH_IN;
36
+ out->hold_duration = 0;
37
+ out->drag_angle = 0.0;
38
+ out->pinch_angle = 0.0;
39
+
40
+ *embedded = out;
41
+ return 0;
42
+ }
43
+
44
+ void hoku_input_embedded_set_hold(hoku_input* input, bool hold, int hold_duration)
45
+ {
46
+ input->embedded->hold = hold;
47
+ input->embedded->hold_duration = hold_duration;
48
+ }
49
+
50
+ void hoku_input_embedded_set_drag(hoku_input* input, bool drag, hoku_drag_direction drag_direction, float drag_x, float drag_y, float drag_angle)
51
+ {
52
+ input->embedded->drag = drag;
53
+ input->embedded->drag_direction = drag_direction;
54
+ input->embedded->drag_pos->x = drag_x;
55
+ input->embedded->drag_pos->y = drag_y;
56
+ input->embedded->drag_angle = drag_angle;
57
+ }
58
+
59
+ void hoku_input_embedded_set_pinch(hoku_input* input, bool pinch, hoku_pinch_direction pinch_direction, float pinch_x, float pinch_y, float pinch_angle)
60
+ {
61
+ input->embedded->pinch = pinch;
62
+ input->embedded->pinch_direction = pinch_direction;
63
+ input->embedded->pinch_pos->x = pinch_x;
64
+ input->embedded->pinch_pos->y = pinch_y;
65
+ input->embedded->pinch_angle = pinch_angle;
66
+ }
67
+
68
+ int hoku_input_attach_embedded(hoku_input* input)
69
+ {
70
+ hoku_input_embedded* embedded;
71
+ if (hoku_input_embedded_init(&embedded) == -1) return -1;
72
+ input->embedded = embedded;
73
+
74
+ return 0;
75
+ }
76
+
77
+ void hoku_input_embedded_free(hoku_input_embedded* embedded)
78
+ {
79
+ free(embedded->drag_pos);
80
+ free(embedded->pinch_pos);
81
+ free(embedded);
82
+ }
83
+
84
+
7
85
  static int hoku_keycodes[HOKU_KEY_MAX] = {
8
86
  0,39,44,45,46,47,48,49,50,51,52,53,54,55,56,57,59,61,65,66,67,68,69,
9
87
  70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,
@@ -273,6 +351,12 @@ void hoku_input_free(hoku_input* input)
273
351
  {
274
352
  hoku_input_keyboard_free(input->keyboard);
275
353
  hoku_input_mouse_free(input->mouse);
354
+
355
+ if (input->embedded)
356
+ {
357
+ hoku_input_embedded_free(input->embedded);
358
+ }
359
+
276
360
  free(input);
277
361
  }
278
362
 
@@ -298,6 +382,7 @@ int hoku_input_init(hoku_input** input)
298
382
  return -1;
299
383
  }
300
384
  init->keyboard = keyboard;
385
+ init->embedded = NULL;
301
386
 
302
387
  *input = init;
303
388
  return 0;
data/ast/src/core/input.h CHANGED
@@ -87,12 +87,43 @@ typedef struct HmlInputKeyboard
87
87
  bool collecting;
88
88
  } hoku_input_keyboard;
89
89
 
90
+ typedef enum HmlDragDirection {
91
+ HOKU_DRAG_UP,
92
+ HOKU_DRAG_DOWN,
93
+ HOKU_DRAG_LEFT,
94
+ HOKU_DRAG_RIGHT
95
+ } hoku_drag_direction;
96
+
97
+ typedef enum HmlPinchDirection {
98
+ HOKU_PINCH_IN,
99
+ HOKU_PINCH_OUT
100
+ } hoku_pinch_direction;
101
+
102
+ typedef struct HmlInputEmbedded
103
+ {
104
+ bool hold;
105
+ int hold_duration;
106
+ bool drag;
107
+ hoku_drag_direction drag_direction;
108
+ hoku_vec2* drag_pos;
109
+ float drag_angle;
110
+ bool pinch;
111
+ hoku_pinch_direction pinch_direction;
112
+ hoku_vec2* pinch_pos;
113
+ float pinch_angle;
114
+ } hoku_input_embedded;
115
+
90
116
  typedef struct HmlInput
91
117
  {
92
118
  hoku_input_keyboard* keyboard;
93
119
  hoku_input_mouse* mouse;
120
+ hoku_input_embedded* embedded;
94
121
  } hoku_input;
95
122
 
123
+ void hoku_input_embedded_set_hold(hoku_input* input, bool hold, int hold_duration);
124
+ void hoku_input_embedded_set_drag(hoku_input* input, bool drag, hoku_drag_direction drag_direction, float drag_x, float drag_y, float drag_angle);
125
+ void hoku_input_embedded_set_pinch(hoku_input* input, bool pinch, hoku_pinch_direction pinch_direction, float pinch_x, float pinch_y, float pinch_angle);
126
+ int hoku_input_attach_embedded(hoku_input* input);
96
127
 
97
128
  int hoku_input_keyboard_init(hoku_input_keyboard** keyboard);
98
129
  int hoku_input_mouse_init(hoku_input_mouse** mouse);
data/ast/src/core/util.c CHANGED
@@ -3,33 +3,33 @@
3
3
 
4
4
  #include "util.h"
5
5
 
6
- bool hoku_rect_includes_y(hoku_rect rect, float y)
6
+ bool hoku_rect_includes_y(hoku_rect* rect, float y)
7
7
  {
8
- return y > rect.y && y <= (rect.y + rect.h);
8
+ return y > rect->y && y <= (rect->y + rect->h);
9
9
  }
10
10
 
11
- bool hoku_rect_includes_x(hoku_rect rect, float x)
11
+ bool hoku_rect_includes_x(hoku_rect* rect, float x)
12
12
  {
13
- return x > rect.x && x <= (rect.x + rect.w);
13
+ return x > rect->x && x <= (rect->x + rect->w);
14
14
  }
15
15
 
16
- float hoku_rect_x_left(hoku_rect rect, int times)
16
+ float hoku_rect_x_left(hoku_rect* rect, int times)
17
17
  {
18
- return (rect.x - ((rect.w / 2) * times));
18
+ return (rect->x - ((rect->w / 2) * times));
19
19
  }
20
- float hoku_rect_x_right(hoku_rect rect, int times)
20
+ float hoku_rect_x_right(hoku_rect* rect, int times)
21
21
  {
22
- return (rect.x + ((rect.w / 2) * times));
22
+ return (rect->x + ((rect->w / 2) * times));
23
23
  }
24
24
 
25
- float hoku_rect_y_up(hoku_rect rect, int times)
25
+ float hoku_rect_y_up(hoku_rect* rect, int times)
26
26
  {
27
- return (rect.y - ((rect.h / 2) * times));
27
+ return (rect->y - ((rect->h / 2) * times));
28
28
  }
29
29
 
30
- float hoku_rect_y_down(hoku_rect rect, int times)
30
+ float hoku_rect_y_down(hoku_rect* rect, int times)
31
31
  {
32
- return (rect.y + ((rect.h / 2) * times));
32
+ return (rect->y + ((rect->h / 2) * times));
33
33
  }
34
34
 
35
35
  int hoku_selection_init(hoku_selection** selection)
@@ -68,28 +68,28 @@ bool hoku_selection_selected(hoku_selection* selection, float x, float y, float
68
68
  bool right = selection->start_x <= selection->stop_x;
69
69
 
70
70
  hoku_rect hit_box = (hoku_rect){.x=x, .y=y, .w=width, .h=height};
71
- float x_shifted_right = hoku_rect_x_right(hit_box, 1);
72
- float y_shifted_up = hoku_rect_y_up(hit_box, 2);
73
- float y_shifted_down = hoku_rect_y_down(hit_box, 2);
71
+ float x_shifted_right = hoku_rect_x_right(&hit_box, 1);
72
+ float y_shifted_up = hoku_rect_y_up(&hit_box, 2);
73
+ float y_shifted_down = hoku_rect_y_down(&hit_box, 2);
74
74
  float end_y = y + height;
75
75
 
76
76
  return (
77
77
  (down &&
78
78
  // first line of multiline selection
79
- ((x_shifted_right > sx && end_y < ey && hoku_rect_includes_y(hit_box, sy)) ||
79
+ ((x_shifted_right > sx && end_y < ey && hoku_rect_includes_y(&hit_box, sy)) ||
80
80
  // last line of multiline selection
81
81
  (x_shifted_right <= ex && y_shifted_up + hit_box.h < ey && hit_box.y > sy) ||
82
82
  // middle line (all selected)
83
83
  (hit_box.y > sy && end_y < ey))) ||
84
84
  (up &&
85
85
  // first line of multiline selection
86
- ((x_shifted_right <= sx && hit_box.y > ey && hoku_rect_includes_y(hit_box, sy)) ||
86
+ ((x_shifted_right <= sx && hit_box.y > ey && hoku_rect_includes_y(&hit_box, sy)) ||
87
87
  // last line of multiline selection
88
88
  (x_shifted_right >= ex && y_shifted_down > ey && end_y < sy) ||
89
89
  // middle line (all selected)
90
90
  (hit_box.y > ey && hit_box.y + hit_box.h < sy))) ||
91
91
  // single line selection
92
- ((hoku_rect_includes_y(hit_box, sy) && hoku_rect_includes_y(hit_box, ey)) &&
92
+ ((hoku_rect_includes_y(&hit_box, sy) && hoku_rect_includes_y(&hit_box, ey)) &&
93
93
  ((left && x_shifted_right < sx && x_shifted_right > ex) || (right && x_shifted_right > sx && x_shifted_right < ex)))
94
94
  );
95
95
  }
@@ -108,7 +108,7 @@ hoku_cursor_position hoku_selection_cursor_get(hoku_selection* selection)
108
108
  return pos;
109
109
  }
110
110
 
111
- int hoku_selection_cursor_set(hoku_selection* selection, hoku_cursor_position cursor)
111
+ int hoku_selection_cursor_set(hoku_selection* selection, hoku_cursor_position* cursor)
112
112
  {
113
113
  if (selection->cursor == NULL)
114
114
  {
@@ -117,10 +117,10 @@ int hoku_selection_cursor_set(hoku_selection* selection, hoku_cursor_position cu
117
117
  if (selection->cursor == NULL) return -1;
118
118
  }
119
119
 
120
- selection->cursor->x = cursor.x;
121
- selection->cursor->y = cursor.y;
122
- selection->cursor->w = cursor.w;
123
- selection->cursor->h = cursor.h;
120
+ selection->cursor->x = cursor->x;
121
+ selection->cursor->y = cursor->y;
122
+ selection->cursor->w = cursor->w;
123
+ selection->cursor->h = cursor->h;
124
124
 
125
125
  return 0;
126
126
  }
data/ast/src/core/util.h CHANGED
@@ -30,16 +30,16 @@ typedef struct HokuSelection
30
30
  hoku_cursor_position* cursor;
31
31
  } hoku_selection;
32
32
 
33
- bool hoku_rect_includes_y(hoku_rect rect, float y);
34
- bool hoku_rect_includes_x(hoku_rect rect, float x);
35
- float hoku_rect_x_left(hoku_rect rect, int times);
36
- float hoku_rect_x_right(hoku_rect rect, int times);
37
- float hoku_rect_y_up(hoku_rect rect, int times);
38
- float hoku_rect_y_down(hoku_rect rect, int times);
33
+ bool hoku_rect_includes_y(hoku_rect* rect, float y);
34
+ bool hoku_rect_includes_x(hoku_rect* rect, float x);
35
+ float hoku_rect_x_left(hoku_rect* rect, int times);
36
+ float hoku_rect_x_right(hoku_rect* rect, int times);
37
+ float hoku_rect_y_up(hoku_rect* rect, int times);
38
+ float hoku_rect_y_down(hoku_rect* rect, int times);
39
39
 
40
40
  int hoku_selection_init(hoku_selection** selection);
41
41
  bool hoku_selection_selected(hoku_selection* selection, float x, float y, float width, float height);
42
- int hoku_selection_cursor_set(hoku_selection* selection, hoku_cursor_position cursor);
42
+ int hoku_selection_cursor_set(hoku_selection* selection, hoku_cursor_position* cursor);
43
43
  void hoku_selection_cursor_free(hoku_selection* selection);
44
44
  void hoku_selection_free(hoku_selection* selection);
45
45
 
data/ext/extconf.rb CHANGED
@@ -5,14 +5,17 @@ if MiniPortile.darwin?
5
5
  suffix = "dylib"
6
6
  ext = "tar.gz"
7
7
  md4cext = "a"
8
+ MDFLAGS = ""
8
9
  elsif MiniPortile.linux?
9
10
  suffix = "so"
10
11
  ext = "tar.gz"
11
- md4cext = "so"
12
+ md4cext = "a"
13
+ MDFLAGS = "-DCMAKE_POSITION_INDEPENDENT_CODE=ON"
12
14
  elsif MiniPortile.windows?
13
15
  suffix = "dll"
14
16
  ext = "zip"
15
17
  md4cext = "a"
18
+ MDFLAGS = ""
16
19
  else
17
20
  raise "Currently only supporting darwin and linux"
18
21
  end
@@ -29,6 +32,7 @@ tree_sitter.tap do |t|
29
32
  end
30
33
 
31
34
  def t.install
35
+
32
36
  execute('install', %Q(#{make_cmd} all install CC=gcc AR=ar PREFIX=#{File.expand_path(port_path)}), { env: { "PREFIX" => File.expand_path(port_path) }})
33
37
  end
34
38
 
@@ -41,7 +45,7 @@ md4c = MiniPortileCMake.new("md4c", "0.5.2")
41
45
  md4c.files = ["https://github.com/mity/md4c/archive/refs/tags/release-0.5.2.#{ext}"]
42
46
 
43
47
  def md4c.cmake_compile_flags
44
- [*super, "-DBUILD_SHARED_LIBS=OFF -DCMAKE_POSITION_INDEPENDENT_CODE=ON"]
48
+ [*super, "-DBUILD_SHARED_LIBS=OFF", "-DCMAKE_POSITION_INDEPENDENT_CODE=ON"]
45
49
  end
46
50
 
47
51
  md4c.cook
@@ -85,4 +89,4 @@ File.open("Makefile", "w") do |io|
85
89
  #{"\t"}rm -f #{File.expand_path("vendor/lib/libhokusai.*")}
86
90
  #{"\t"}rm -f #{File.expand_path("vendor/lib/libmd4c.*")}
87
91
  EOF
88
- end
92
+ end
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.5'
3
+ s.version = '0.2.6-pinephone'
4
4
  s.licenses = ['MIT']
5
5
  s.summary = "A Ruby library for writing GUI applications"
6
6
  s.authors = ["skinnyjames"]
@@ -16,7 +16,6 @@ Gem::Specification.new do |s|
16
16
  s.metadata = { "source_code_uri" => "https://codeberg.org/skinnyjames/hokusai" }
17
17
 
18
18
  s.add_dependency "ffi", "~> 1.16"
19
- s.add_dependency "concurrent-ruby", "~> 1.3.4"
20
19
  s.add_dependency "raylib-bindings", "~> 0.7.9"
21
20
  s.add_dependency "sdl2-bindings", "~> 0.2.3"
22
21
  s.add_dependency "memory_profiler"
@@ -0,0 +1,154 @@
1
+ require_relative "../src/hokusai"
2
+ require_relative "../src/hokusai/backends/raylib"
3
+ require "ostruct"
4
+
5
+ class Item < Hokusai::Block
6
+ style <<~EOF
7
+ [style]
8
+ circleStyle {
9
+ cursor: "pointer";
10
+ }
11
+ EOF
12
+ template <<~EOF
13
+ [template]
14
+ empty {
15
+ ...circleStyle
16
+ :color="color"
17
+ @mousedown="start_drag"
18
+ @mouseup="release_drag"
19
+ @mousemove="emit_drag"
20
+ }
21
+ EOF
22
+
23
+ uses(empty: Hokusai::Blocks::Empty)
24
+
25
+ computed :index
26
+ computed! :pos
27
+ computed! :color
28
+
29
+ attr_accessor :dragging
30
+
31
+ def initialize(**props)
32
+ @dragging = false
33
+
34
+ super
35
+ end
36
+
37
+ def contains(p)
38
+ (((p.x - pos[0]) * (p.x - pos[0]) + (p.y - pos[1]) * (p.y - pos[1])) <= 40 * 40)
39
+ end
40
+
41
+ def start_drag(event)
42
+ if event.left.down && contains(event.pos)
43
+
44
+ self.dragging = true
45
+ node.meta.set_prop(:z, 2)
46
+ node.meta.set_prop(:position, "absolute")
47
+ end
48
+ end
49
+
50
+ def release_drag(event)
51
+ if dragging
52
+ emit("done", index)
53
+ self.dragging = false
54
+
55
+ node.meta.set_prop(:z, nil)
56
+ node.meta.set_prop(:position, nil)
57
+ end
58
+ end
59
+
60
+ def emit_drag(event)
61
+ if dragging && event.left.down
62
+ emit("drag", index, [event.pos.x, event.pos.y])
63
+ elsif dragging
64
+ emit("done", index)
65
+
66
+ self.dragging = false
67
+ node.meta.set_prop(:z, nil)
68
+ node.meta.set_prop(:position, nil)
69
+ end
70
+ end
71
+
72
+ def render(canvas)
73
+ canvas.x = canvas.x + (canvas.width / 2)
74
+ canvas.y = canvas.y + canvas.height / 2
75
+
76
+ circle(pos[0], pos[1], 40) do |command|
77
+ command.color = color
78
+ end
79
+
80
+ yield canvas
81
+ end
82
+ end
83
+
84
+
85
+ class Drag < Hokusai::Block
86
+ template <<~EOF
87
+ [template]
88
+ vblock { background="233,233,233" }
89
+ [for="thing in items"]
90
+ item {
91
+ :z="z(index)"
92
+ :key="key(index, thing)"
93
+ :index="index"
94
+ @drag="update_position"
95
+ @done="update_drag_state"
96
+ :pos="pos(thing)"
97
+ :color="color(thing)"
98
+ }
99
+ EOF
100
+
101
+ uses(
102
+ vblock: Hokusai::Blocks::Vblock,
103
+ item: Item
104
+ )
105
+
106
+ attr_reader :items
107
+
108
+ def z(index)
109
+ items[index].dragging ? 2 : nil
110
+ end
111
+
112
+ def update_drag_state(index)
113
+ items[index].dragging = false
114
+ end
115
+
116
+ def key(index, thing)
117
+ "key-#{index}"
118
+ end
119
+
120
+ def pos(thing)
121
+ thing.position
122
+ end
123
+
124
+ def color(thing)
125
+ thing.color
126
+ end
127
+
128
+ def update_position(index, pos)
129
+ items[index].dragging = true
130
+ items[index].position = pos
131
+ end
132
+
133
+ def initialize(**args)
134
+ @items = [[0, 10, [222,222,0]], [100, 100, [0,222,222]], [300, 300, [0, 222, 0]]].map do |list|
135
+ item = OpenStruct.new
136
+ item.position = [list[0], list[1]]
137
+ item.color = Hokusai::Color.convert(list[2])
138
+ item.dragging = false
139
+ item
140
+ end
141
+
142
+ pp items
143
+
144
+ super
145
+ end
146
+ end
147
+
148
+ Hokusai::Backends::RaylibBackend.run(Drag) do |config|
149
+ config.after_load do
150
+ font = Hokusai::Backends::RaylibBackend::Font.from("#{__dir__}/assets/Inter-Regular.ttf")
151
+ Hokusai.fonts.register "inter", font
152
+ Hokusai.fonts.activate "inter"
153
+ end
154
+ end
@@ -0,0 +1,59 @@
1
+ require_relative "../src/hokusai"
2
+ require_relative "../src/hokusai/backends/embedded"
3
+
4
+ class App < Hokusai::Block
5
+ template <<~EOF
6
+ [template]
7
+ button {
8
+ @clicked="clear_text"
9
+ height="30"
10
+ content="clear"
11
+ }
12
+ panel {
13
+ @swipe="handle_swipe"
14
+ @taphold="handle_taphold"
15
+ @pinch="handle_pinch"
16
+ }
17
+ text {
18
+ :content="text"
19
+ :size="15"
20
+ }
21
+ EOF
22
+
23
+ uses(
24
+ button: Hokusai::Blocks::Button,
25
+ panel: Hokusai::Blocks::Panel,
26
+ text: Hokusai::Blocks::Text
27
+ )
28
+
29
+ attr_accessor :text
30
+
31
+ def initialize(**args)
32
+ @text = ""
33
+
34
+ super
35
+ end
36
+
37
+ def clear_text(event)
38
+ self.text = ""
39
+ pp ["clear", text]
40
+ end
41
+
42
+ def handle_pinch(event)
43
+ self.text += "Pinch: #{event.pinch_direction} - #{event.pinch_pos.x}x#{event.pinch_pos.y} (#{event.pinch_angle})\n\n"
44
+ end
45
+
46
+ def handle_swipe(event)
47
+ self.text += "Swipe: #{event.drag_direction} - #{event.drag_pos.x}x#{event.drag_pos.y} (#{event.drag_angle})\n\n"
48
+ end
49
+
50
+ def handle_taphold(event)
51
+ self.text += "Taphold #{event.hold_duration}\n\n"
52
+ end
53
+ end
54
+
55
+ Hokusai::Backends::EmbeddedBackend.run(App) do |config|
56
+ config.after_load do
57
+ Hokusai.maximize_window
58
+ end
59
+ end