hokusai-zero 0.2.6 → 0.2.8

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 (86) 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/ast.c +3 -11
  6. data/ast/src/core/hml.c +214 -40
  7. data/ast/src/core/hml.h +1 -0
  8. data/ast/src/core/input.h +0 -1
  9. data/ast/src/core/log.c +87 -0
  10. data/ast/src/core/log.h +41 -0
  11. data/ast/src/core/util.c +23 -23
  12. data/ast/src/core/util.h +7 -7
  13. data/ast/test/parser.c +1 -0
  14. data/ext/extconf.rb +6 -6
  15. data/hokusai.gemspec +1 -2
  16. data/ui/examples/drag.rb +154 -0
  17. data/ui/examples/embedded.rb +58 -0
  18. data/ui/examples/forum/file.rb +1 -1
  19. data/ui/examples/forum/post.rb +0 -1
  20. data/ui/examples/forum.rb +7 -7
  21. data/ui/examples/game.rb +143 -0
  22. data/ui/examples/keyboard.rb +47 -0
  23. data/ui/examples/overlay.rb +233 -0
  24. data/ui/examples/provider.rb +56 -0
  25. data/ui/examples/shader/test.rb +155 -0
  26. data/ui/examples/shader.rb +100 -0
  27. data/ui/examples/spreadsheet.rb +12 -11
  28. data/ui/examples/wiki.rb +82 -0
  29. data/ui/lib/lib_hokusai.rb +43 -24
  30. data/ui/spec/hokusai/e2e/client_spec.rb +0 -1
  31. data/ui/spec/hokusai/e2e/keyboard_spec.rb +52 -0
  32. data/ui/spec/spec_helper.rb +1 -1
  33. data/ui/src/hokusai/assets/arrow-down-line.png +0 -0
  34. data/ui/src/hokusai/assets/arrow-down-wide-line.png +0 -0
  35. data/ui/src/hokusai/assets/icons/outline/arrow-big-up.svg +19 -0
  36. data/ui/src/hokusai/assets/icons/outline/backspace.svg +20 -0
  37. data/ui/src/hokusai/automation/driver_commands/base.rb +2 -8
  38. data/ui/src/hokusai/automation/driver_commands/trigger_keyboard.rb +3 -6
  39. data/ui/src/hokusai/automation/driver_commands/trigger_mouse.rb +12 -5
  40. data/ui/src/hokusai/automation/server.rb +2 -3
  41. data/ui/src/hokusai/backends/raylib/config.rb +2 -1
  42. data/ui/src/hokusai/backends/raylib/font.rb +55 -4
  43. data/ui/src/hokusai/backends/raylib.rb +199 -36
  44. data/ui/src/hokusai/backends/sdl2/config.rb +9 -6
  45. data/ui/src/hokusai/backends/sdl2/font.rb +3 -1
  46. data/ui/src/hokusai/backends/sdl2.rb +188 -93
  47. data/ui/src/hokusai/blocks/color_picker.rb +1080 -0
  48. data/ui/src/hokusai/blocks/dynamic.rb +2 -0
  49. data/ui/src/hokusai/blocks/input.rb +2 -2
  50. data/ui/src/hokusai/blocks/keyboard.rb +249 -0
  51. data/ui/src/hokusai/blocks/panel.rb +2 -0
  52. data/ui/src/hokusai/blocks/scrollbar.rb +7 -0
  53. data/ui/src/hokusai/blocks/selectable.rb +1 -0
  54. data/ui/src/hokusai/blocks/shader_begin.rb +22 -0
  55. data/ui/src/hokusai/blocks/shader_end.rb +12 -0
  56. data/ui/src/hokusai/blocks/slider.rb +139 -0
  57. data/ui/src/hokusai/blocks/text_stream.rb +130 -0
  58. data/ui/src/hokusai/blocks/texture.rb +23 -0
  59. data/ui/src/hokusai/blocks/translation.rb +91 -0
  60. data/ui/src/hokusai/commands/rect.rb +12 -3
  61. data/ui/src/hokusai/commands/rotation.rb +21 -0
  62. data/ui/src/hokusai/commands/scale.rb +20 -0
  63. data/ui/src/hokusai/commands/shader.rb +33 -0
  64. data/ui/src/hokusai/commands/texture.rb +26 -0
  65. data/ui/src/hokusai/commands/translation.rb +20 -0
  66. data/ui/src/hokusai/commands.rb +49 -3
  67. data/ui/src/hokusai/event.rb +2 -1
  68. data/ui/src/hokusai/events/keyboard.rb +11 -18
  69. data/ui/src/hokusai/events/mouse.rb +10 -8
  70. data/ui/src/hokusai/events/touch.rb +62 -0
  71. data/ui/src/hokusai/meta.rb +13 -6
  72. data/ui/src/hokusai/mounting/loop_entry.rb +4 -4
  73. data/ui/src/hokusai/mounting/update_entry.rb +5 -6
  74. data/ui/src/hokusai/painter.rb +31 -8
  75. data/ui/src/hokusai/types/display.rb +155 -0
  76. data/ui/src/hokusai/types/keyboard.rb +168 -0
  77. data/ui/src/hokusai/types/mouse.rb +36 -0
  78. data/ui/src/hokusai/types/primitives.rb +56 -0
  79. data/ui/src/hokusai/types/touch.rb +181 -0
  80. data/ui/src/hokusai/types.rb +20 -244
  81. data/ui/src/hokusai/util/selection.rb +28 -7
  82. data/ui/src/hokusai/util/wrap_stream.rb +268 -0
  83. data/ui/src/hokusai.rb +72 -35
  84. data/xmake.lua +2 -1
  85. metadata +39 -22
  86. data/ui/src/hokusai/assets/chevron-down.svg +0 -1
@@ -25,6 +25,8 @@ class Hokusai::Blocks::Dynamic < Hokusai::Block
25
25
  w += block.node.meta.get_prop?(:width)&.to_f || 0.0
26
26
  end
27
27
 
28
+ node.meta.set_prop(:height, h)
29
+
28
30
  [w, h]
29
31
  end
30
32
 
@@ -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"
@@ -154,7 +154,7 @@ class Hokusai::Blocks::Input < Hokusai::Block
154
154
  self.buffer_offset = offset
155
155
  end
156
156
 
157
- self.buffer += event.char
157
+ self.buffer += event.char unless event.char.nil?
158
158
  end
159
159
  end
160
160
 
@@ -0,0 +1,249 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hokusai::Blocks
4
+ class Key < Hokusai::Block
5
+ template <<~EOF
6
+ [template]
7
+ empty {
8
+ @mousedown="set_down"
9
+ @mouseup="set_up"
10
+ cursor="pointer"
11
+ }
12
+ EOF
13
+
14
+ uses(empty: Hokusai::Blocks::Empty)
15
+
16
+ computed! :value
17
+ computed :size, default: 24, convert: proc(&:to_i)
18
+ computed :background, default: Hokusai::Color.new(70, 70, 70), convert: Hokusai::Color
19
+ computed :color, default: Hokusai::Color.new(244, 244, 244), convert: Hokusai::Color
20
+ computed :background_down, default: Hokusai::Color.new(33,33,33), convert: Hokusai::Color
21
+ computed :margin, default: Hokusai::Padding.new(3.0, 2.5, 3.0, 2.5), convert: Hokusai::Padding
22
+
23
+ inject :keyboard_icons
24
+
25
+ attr_accessor :down, :last_commands, :last_canvas, :last_value
26
+
27
+ def initialize(**args)
28
+ @down = false
29
+ @last_commands = []
30
+ @last_canvas = nil
31
+ @last_value = nil
32
+
33
+ super
34
+ end
35
+
36
+ def set_down(event)
37
+ if !down
38
+ emit("clicked", value[0], event)
39
+
40
+ self.down = true
41
+ else
42
+ emit("released", value[0], event)
43
+ end
44
+ end
45
+
46
+ def set_up(event)
47
+ self.down = false
48
+ emit("released", value[0], event)
49
+ end
50
+
51
+ def render(canvas)
52
+ hpad = (canvas.width - size) / 2
53
+ vpad = (canvas.height - margin.height - size) / 2
54
+
55
+ draw do
56
+ if last_canvas != canvas && last_value != value
57
+ self.last_value = value
58
+ self.last_canvas = canvas
59
+
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
81
+
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
91
+ end
92
+ else
93
+ queue.concat(last_commands)
94
+ end
95
+ end
96
+
97
+ yield canvas
98
+ end
99
+ end
100
+
101
+ class KeyboardRow < Hokusai::Block
102
+ style <<~EOF
103
+ [style]
104
+ keyboardStyle {
105
+ background: rgb(28, 28, 28);
106
+ }
107
+ keyStyle {
108
+ background: rgb(46, 46, 46);
109
+ color: rgb(208, 205, 218);
110
+ background_down: rgb(37, 37, 37);
111
+ }
112
+ EOF
113
+
114
+ template <<~EOF
115
+ [template]
116
+ hblock { ...keyboardStyle }
117
+ [for="number in keys"]
118
+ key {
119
+ ...keyStyle
120
+ :key="index"
121
+ :value="number"
122
+ @clicked="emit_key"
123
+ @released="emit_released"
124
+ }
125
+ EOF
126
+
127
+ uses(
128
+ hblock: Hblock,
129
+ vblock: Vblock,
130
+ key: Key
131
+ )
132
+
133
+ computed! :keys
134
+
135
+ inject :keyboard_icons
136
+
137
+ def loop_key(value)
138
+ @keys ||= {}
139
+ @keys[value] ||= "key-#{value}".freeze
140
+ end
141
+
142
+ def emit_key(key, event)
143
+ emit("key", key, event)
144
+ end
145
+
146
+ def emit_released(key, event)
147
+ emit("released", key, event)
148
+ end
149
+ end
150
+
151
+ class Keyboard < Hokusai::Block
152
+ style <<~EOF
153
+ [style]
154
+ kstyle {
155
+ padding: padding(10.0, 5.0, 10.0, 5.0);
156
+ background: rgb(28, 28, 28);
157
+ }
158
+ EOF
159
+
160
+ template <<~EOF
161
+ [template]
162
+ vblock { ...kstyle }
163
+ [for="row in key_rows"]
164
+ row {
165
+ :icons="icons"
166
+ @released="handle_released"
167
+ @key="handle_keypress"
168
+ :key="index"
169
+ :keys="row"
170
+ }
171
+ EOF
172
+
173
+ uses(
174
+ vblock: Hokusai::Blocks::Vblock,
175
+ row: KeyboardRow
176
+ )
177
+
178
+ def icons
179
+ {
180
+ :shift => {
181
+ file: Hokusai.asset("icons/outline/arrow-big-up.svg"),
182
+ width: 54.0,
183
+ size: 30,
184
+ background: Hokusai::Color.new(50, 109, 70),
185
+ color: Hokusai::Color.new(172, 224, 189)
186
+ },
187
+ :backspace => {
188
+ file: Hokusai.asset("icons/outline/backspace.svg"),
189
+ width: 54.0,
190
+ size: 30,
191
+ background: Hokusai::Color.new(50, 109, 70),
192
+ color: Hokusai::Color.new(172, 224, 189)
193
+ }
194
+ }
195
+ end
196
+
197
+ computed :row_height, default: 48.0, convert: proc(&:to_f)
198
+
199
+ provide :keyboard_icons, :icons
200
+
201
+ def on_mounted
202
+ node.meta.set_prop(:height, row_height * 5.0 + 20)
203
+ end
204
+
205
+ def space_row
206
+ [[:comma, ","], [:space, ''], [:period, "."]]
207
+ end
208
+
209
+ def key_rows
210
+ [number_keys, querty_keys, asdf_keys, zxcv_keys, space_row]
211
+ end
212
+
213
+ def handle_released(key, event)
214
+ event.input.keyboard_override = false
215
+ end
216
+
217
+ def handle_keypress(key, event)
218
+ event.input.keyboard_override = true
219
+ LibHokusai.hoku_input_keyboard_start(event.input.raw)
220
+ LibHokusai.hoku_input_keyboard_set_key(event.input.raw, key.to_sym, true)
221
+ LibHokusai.hoku_input_keyboard_stop(event.input.raw)
222
+ end
223
+
224
+ def zxcv_keys
225
+ @zxcv_keys ||= begin
226
+ keys = %w[z x c v b n m]
227
+ middle = keys.zip(keys)
228
+ # middle << [:backspace, :backspace]
229
+ # middle.unshift([:shift, :shift])
230
+ middle
231
+ end
232
+ end
233
+
234
+ def asdf_keys
235
+ keys = %w[a s d f g h j k l]
236
+ @asdf_keys ||= keys.zip(keys)
237
+ end
238
+
239
+ def querty_keys
240
+ keys = %w[q w e r t y u i o p]
241
+ @querty_keys ||= keys.zip(keys)
242
+ end
243
+
244
+ def number_keys
245
+ keys = [[:one,1],[:two, 2], [:three,3], [:four,4],[:five, 5], [:six,6], [:seven,7], [:eight,8],[:nine,9], [:zero, 0]]
246
+ @number_keys ||= keys
247
+ end
248
+ end
249
+ end
@@ -39,6 +39,8 @@ class Hokusai::Blocks::Panel < Hokusai::Block
39
39
  provide :panel_height, :panel_height
40
40
  provide :panel_top, :panel_top
41
41
 
42
+ inject :selection
43
+
42
44
  attr_accessor :top, :panel_height, :scroll_y, :scroll_percent,
43
45
  :scroll_goto_y, :clipped_offset, :clipped_content_height
44
46
 
@@ -1,7 +1,14 @@
1
1
  class Hokusai::Blocks::Scrollbar < Hokusai::Block
2
+ style <<~EOF
3
+ [style]
4
+ scrollbar {
5
+ cursor: "pointer";
6
+ }
7
+ EOF
2
8
  template <<~EOF
3
9
  [template]
4
10
  vblock.scrollbar {
11
+ ...scrollbar
5
12
  @mousedown="scroll_start"
6
13
  @mousemove="scroll_handle"
7
14
  :background="background"
@@ -38,6 +38,7 @@ module Hokusai::Blocks
38
38
 
39
39
  def start_selection(event)
40
40
  if event.left.down && !selection.active?
41
+ selection.clear
41
42
  selection.start(event.pos.x, event.pos.y)
42
43
  end
43
44
  end
@@ -0,0 +1,22 @@
1
+ class Hokusai::Blocks::ShaderBegin < Hokusai::Block
2
+ template <<~EOF
3
+ [template]
4
+ slot
5
+ EOF
6
+
7
+ computed :fragment_shader, default: nil
8
+ computed :vertex_shader, default: nil
9
+ computed :uniforms, default: []
10
+
11
+ def render(canvas)
12
+ draw do
13
+ shader_begin do |command|
14
+ command.vertex_shader = vertex_shader
15
+ command.fragment_shader = fragment_shader
16
+ command.uniforms = uniforms
17
+ end
18
+ end
19
+
20
+ yield canvas
21
+ end
22
+ end
@@ -0,0 +1,12 @@
1
+ class Hokusai::Blocks::ShaderEnd < Hokusai::Block
2
+ template <<~EOF
3
+ [template]
4
+ virtual
5
+ EOF
6
+
7
+ def render(canvas)
8
+ draw do
9
+ shader_end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,139 @@
1
+
2
+ module Hokusai::Blocks
3
+ class Slider < Hokusai::Block
4
+ template <<~EOF
5
+ [template]
6
+ empty {
7
+ @click="start_slider"
8
+ @mousemove="move_slider"
9
+ @mouseup="stop_slider"
10
+ }
11
+ EOF
12
+
13
+ uses(empty: Hokusai::Blocks::Empty)
14
+
15
+ computed :fill, default: [61,171,211], convert: Hokusai::Color
16
+ computed :initial, default: 0.0, convert: proc(&:to_f)
17
+ computed :size, default: 50.0, convert: proc(&:to_f)
18
+ computed :step, default: 20.0, convert: proc(&:to_f)
19
+ computed :min, default: 0.0, convert: proc(&:to_f)
20
+ computed :max, default: 100.0, convert: proc(&:to_f)
21
+
22
+ attr_reader :slider_width, :slider_start, :steps_x, :steps_val
23
+ attr_accessor :sliding, :slider_x, :last_index
24
+
25
+ def initialize(**args)
26
+ @sliding = false
27
+ @slider_width = 0.0
28
+ @slider_start = 0.0
29
+ @slider_x = 0.0
30
+ @last_index = 0
31
+ @configured = false
32
+
33
+ super
34
+
35
+ @last_max = nil
36
+ end
37
+
38
+ def start_slider(event)
39
+ self.sliding = true
40
+ end
41
+
42
+ def on_resize(canvas)
43
+ # create our buckets for steps
44
+ @slider_start = canvas.x
45
+ @slider_width = canvas.width
46
+
47
+ @steps_val = [*(min..max).step(step).to_a, max]
48
+ steps_val.pop if steps_val[-1] == steps_val[-2]
49
+
50
+ step_x = (slider_width) / (steps_val.size - 1)
51
+ @steps_x = (slider_start..(slider_start + slider_width)).step(step_x).to_a
52
+
53
+ (steps_val.size - steps_x.size).times do |i|
54
+ steps_x << steps_x.last + step_x * i
55
+ end
56
+
57
+ steps_x[-1] = slider_start + slider_width if slider_start + slider_width != steps_x.last
58
+ end
59
+
60
+ def move_slider(event)
61
+ if sliding && event.left.down
62
+ pos = event.pos.x
63
+ index = steps_x.size - 1
64
+
65
+ (0...steps_x.size - 1).each do |i|
66
+ next if steps_x[i + 1] && pos - steps_x[i + 1] > step
67
+
68
+ if pos - steps_x[i] > pos - steps_x[i + 1]
69
+ index = i
70
+ break
71
+ else
72
+ index = i + 1
73
+ break
74
+ end
75
+ end
76
+
77
+ self.last_index = index
78
+
79
+ emit("updated", steps_val[index])
80
+ else
81
+ self.sliding = false
82
+ end
83
+ end
84
+
85
+ def stop_slider(event)
86
+ if event.left.up
87
+ self.sliding = false
88
+ end
89
+ end
90
+
91
+ def render(canvas)
92
+ if max != @last_max
93
+ on_resize(canvas)
94
+
95
+ @last_max = max
96
+ end
97
+
98
+ unless @setup || steps_val.nil? || initial.nil?
99
+ steps_val.each_with_index do |val, index|
100
+ if val == initial
101
+ self.last_index = index
102
+
103
+ break
104
+ end
105
+ end
106
+
107
+ @setup = true
108
+ end
109
+
110
+ slider_x = steps_x[last_index]
111
+ padding = Hokusai::Padding.new(0.0, 0.0, 0.0, 0.0)
112
+ percent = slider_x * 100.00
113
+ x = slider_x + padding.left
114
+ x = (canvas.x + canvas.width) - (size / 2) - 2 if x > (canvas.x + canvas.width) - (size / 2)
115
+ x = canvas.x if x < canvas.x
116
+ cursor = (x + size / 2)
117
+
118
+ draw do
119
+ # draw background
120
+ rect(canvas.x + padding.left, canvas.y + padding.top, canvas.width - padding.right - padding.left, size) do |command|
121
+ command.round = size / 2
122
+ command.color = Hokusai::Color.new(33, 33, 33)
123
+ command.padding = Hokusai::Padding.new(5.0, 20.0, 5.0, 20.0)
124
+ end
125
+
126
+ rect(canvas.x + padding.left + 1, canvas.y + padding.top + 1, x + (size / 2) - canvas.x - 2, size - 2) do |command|
127
+ command.round = size / 2
128
+ command.color = fill
129
+ end
130
+
131
+ circle(cursor + padding.left, canvas.y + (size / 2) + padding.top, size / 2) do |command|
132
+ command.color = Hokusai::Color.new(233, 233, 233)
133
+ end
134
+ end
135
+
136
+ yield canvas
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,130 @@
1
+ class Hokusai::Blocks::TextStream < Hokusai::Block
2
+ template <<~EOF
3
+ [template]
4
+ empty {
5
+ cursor="ibeam"
6
+ }
7
+ EOF
8
+
9
+ uses(empty: Hokusai::Blocks::Empty)
10
+
11
+ computed! :content
12
+ computed :font, default: nil
13
+ computed :size, default: 16, convert: proc(&:to_i)
14
+ computed :color, default: Hokusai::Color.new(33, 33, 33), convert: Hokusai::Color
15
+ computed :selection_color, default: Hokusai::Color.new(233,233,233), convert: Hokusai::Color
16
+ computed :padding, default: Hokusai::Padding.new(5.0, 5.0, 5.0, 5.0), convert: Hokusai::Padding
17
+ computed :cursor_offset, default: nil
18
+
19
+ inject :selection
20
+ inject :panel_top
21
+ inject :panel_height
22
+ inject :panel_offset
23
+
24
+ attr_accessor :last_commands, :last_content, :last_coords, :last_height,
25
+ :last_width, :last_selector, :last_panel_offset, :copying, :buffer
26
+
27
+ attr_reader :stream
28
+
29
+ def initialize(**args)
30
+ @last_commands = []
31
+ @last_coords = nil
32
+ @last_height = 0.0
33
+ @last_width = nil
34
+ @last_selector = nil
35
+ @last_content = nil
36
+ @last_panel_offset = nil
37
+ @last_canvas = nil
38
+ @copying = false
39
+ @reset = false
40
+ @buffer = ""
41
+
42
+ super
43
+ end
44
+
45
+ def after_updated
46
+ @stream&.reset(last_width)
47
+ end
48
+
49
+ def render(canvas)
50
+ w = canvas.width - padding.left - padding.right
51
+ poff = panel_offset || 0.0 - panel_top || 0.0
52
+ selection&.offset_y = poff
53
+
54
+ lfont = Hokusai.fonts.active_font_name
55
+ Hokusai.fonts.activate font unless font.nil?
56
+
57
+ # if Hokusai.can_render(canvas)
58
+ # if (last_content != content ||
59
+ # last_width != w ||
60
+ # panel_offset != last_panel_offset ||
61
+ # last_coords != selection&.coords ||
62
+ # copying ||
63
+ # last_selector != selection&.type)
64
+
65
+ last_commands.clear
66
+ self.last_panel_offset = panel_offset
67
+ self.last_content = content
68
+ self.last_width = w
69
+ self.last_selector = selection&.type
70
+ self.last_coords = selection&.coords
71
+
72
+ @stream ||= WrapStream.new(w) do |string, extra|
73
+ [Hokusai.fonts.active.measure_char(string, size), size]
74
+ end
75
+
76
+ stream.origin_x = canvas.x + padding.left
77
+ stream.origin_y = canvas.y + padding.top
78
+ stream.offset_y = 0.0
79
+ stream.reset(w)
80
+
81
+ draw do
82
+ stream.on_text_selection(selection, nil) do |wrapped|
83
+ self.buffer << wrapped.buffer if copying
84
+ rect(wrapped.x, wrapped.y, wrapped.width, wrapped.height) do |command|
85
+ command.color = selection_color
86
+
87
+ last_commands << command
88
+ end
89
+ end
90
+
91
+ stream.on_text do |wrapped|
92
+ text(wrapped.text, wrapped.x, wrapped.y) do |command|
93
+ command.color = color
94
+ command.size = size
95
+ command.font = font
96
+
97
+ last_commands << command
98
+ end
99
+ end
100
+
101
+ stream.wrap(content, nil)
102
+ stream.flush
103
+ stream.y += size
104
+ end
105
+
106
+ self.last_height = stream.y - canvas.y + padding.top + padding.bottom
107
+ emit("height_updated", last_height)
108
+ node.meta.set_prop(:height, last_height)
109
+
110
+
111
+ # else
112
+ # draw do
113
+ # queue.concat last_commands
114
+ # end
115
+ # end
116
+
117
+ if copying
118
+ Hokusai.copy(buffer)
119
+ self.buffer = ""
120
+ self.copying = false
121
+ end
122
+
123
+ # node.portal&.meta&.set_prop(:height, last_height + padding.top + padding.bottom)
124
+
125
+ yield canvas
126
+ # end
127
+
128
+ Hokusai.fonts.activate lfont
129
+ end
130
+ end
@@ -0,0 +1,23 @@
1
+ class Hokusai::Blocks::Texture < Hokusai::Block
2
+ template <<~EOF
3
+ [template]
4
+ virtual
5
+ EOF
6
+
7
+ computed :width, default: nil, convert: proc(&:to_i)
8
+ computed :height, default: nil, convert: proc(&:to_i)
9
+ computed :x, default: nil
10
+ computed :y, default: nil
11
+ computed :rotation, default: nil
12
+ computed :scale, default: 100.0
13
+
14
+
15
+ def render(canvas)
16
+ draw do
17
+ texture(x || canvas.x, y || canvas.y, width || canvas.width, height || canvas.height) do |command|
18
+ command.rotation = rotation if rotation
19
+ command.scale = scale
20
+ end
21
+ end
22
+ end
23
+ end