hokusai-zero 0.1.3 → 0.1.5
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 +4 -4
- data/Gemfile +3 -1
- data/Gemfile.lock +4 -0
- data/README.md +33 -83
- data/ast/src/core/hml.c +9 -9
- data/ast/src/core/text.c +21 -3
- data/ast/test/text.c +3 -3
- data/docs.sh +29 -0
- data/ext/extconf.rb +69 -14
- data/grammar/corpus/1_document.txt +24 -0
- data/grammar/corpus/6_styles.txt +23 -0
- data/grammar/grammar.js +4 -4
- data/grammar/src/grammar.json +19 -19
- data/grammar/src/parser.c +1904 -1956
- data/grammar/test.nml +10 -8
- data/hokusai.gemspec +3 -1
- data/ui/examples/assets/Delius-Regular.ttf +0 -0
- data/ui/examples/assets/DoHyeon.ttf +0 -0
- data/ui/examples/assets/Inter-Regular.ttf +0 -0
- data/ui/examples/assets/ernest.gif +0 -0
- data/ui/examples/assets/icons/audio-x-generic.png +0 -0
- data/ui/examples/assets/icons/image-x-generic.png +0 -0
- data/ui/examples/assets/icons/media-playback-pause.png +0 -0
- data/ui/examples/assets/icons/media-playback-start.png +0 -0
- data/ui/examples/assets/icons/media-playback-stop.png +0 -0
- data/ui/examples/assets/icons/package-x-generic.png +0 -0
- data/ui/examples/assets/icons/text-x-generic.png +0 -0
- data/ui/examples/assets/icons/video-x-generic.png +0 -0
- data/ui/examples/buddy.rb +16 -14
- data/ui/examples/clock.rb +38 -36
- data/ui/examples/counter.rb +100 -98
- data/ui/examples/dynamic.rb +115 -113
- data/ui/examples/foobar.rb +189 -187
- data/ui/examples/forum/file.rb +54 -0
- data/ui/examples/forum/music.rb +76 -0
- data/ui/examples/forum/post.rb +146 -0
- data/ui/examples/forum.rb +198 -0
- data/ui/examples/spreadsheet/csv.rb +261 -0
- data/ui/examples/spreadsheet.rb +138 -0
- data/ui/examples/stock.rb +86 -92
- data/ui/examples/stock_decider/option.rb +1 -1
- data/ui/examples/tic_tac_toe.rb +193 -191
- data/ui/lib/lib_hokusai.rb +2 -1
- data/ui/src/hokusai/assets/arrow-drop-down-line.png +0 -0
- data/ui/src/hokusai/assets/chevron-down.svg +1 -0
- data/ui/src/hokusai/assets/close-large-line.png +0 -0
- data/ui/src/hokusai/ast.rb +42 -43
- data/ui/src/hokusai/backends/raylib/font.rb +1 -2
- data/ui/src/hokusai/backends/raylib.rb +29 -17
- data/ui/src/hokusai/backends/sdl2/font.rb +13 -9
- data/ui/src/hokusai/backends/sdl2.rb +32 -5
- data/ui/src/hokusai/block.rb +14 -7
- data/ui/src/hokusai/blocks/dropdown.rb +205 -0
- data/ui/src/hokusai/blocks/hblock.rb +2 -2
- data/ui/src/hokusai/blocks/image.rb +6 -1
- data/ui/src/hokusai/blocks/input.rb +17 -0
- data/ui/src/hokusai/blocks/label.rb +5 -2
- data/ui/src/hokusai/blocks/modal.rb +62 -0
- data/ui/src/hokusai/blocks/panel.rb +2 -2
- data/ui/src/hokusai/blocks/scrollbar.rb +0 -2
- data/ui/src/hokusai/blocks/text.rb +12 -6
- data/ui/src/hokusai/blocks/titlebar/osx.rb +4 -4
- data/ui/src/hokusai/blocks/variable.rb +33 -0
- data/ui/src/hokusai/blocks/vblock.rb +1 -1
- data/ui/src/hokusai/commands/rect.rb +4 -4
- data/ui/src/hokusai/commands.rb +46 -29
- data/ui/src/hokusai/diff.rb +11 -0
- data/ui/src/hokusai/event.rb +19 -5
- data/ui/src/hokusai/events/mouse.rb +9 -1
- data/ui/src/hokusai/font.rb +60 -0
- data/ui/src/hokusai/meta.rb +11 -24
- data/ui/src/hokusai/node.rb +1 -1
- data/ui/src/hokusai/painter.rb +66 -8
- data/ui/src/hokusai/util/clamping_iterator.rb +5 -6
- data/ui/src/hokusai.rb +53 -4
- metadata +56 -3
data/ui/src/hokusai/ast.rb
CHANGED
@@ -25,15 +25,21 @@ module Hokusai
|
|
25
25
|
end
|
26
26
|
|
27
27
|
# The loop variable
|
28
|
+
#
|
28
29
|
# eg [for="item in list"]
|
29
30
|
# the var is `item`
|
31
|
+
#
|
32
|
+
# @return [String]
|
30
33
|
def var
|
31
34
|
@name ||= raw[:name].freeze
|
32
35
|
end
|
33
36
|
|
34
37
|
# The loop method
|
38
|
+
#
|
35
39
|
# eg [for="item in list"]
|
36
40
|
# the method is `list`
|
41
|
+
#
|
42
|
+
# @return [String]
|
37
43
|
def method
|
38
44
|
@list_name ||= raw[:list_name].freeze
|
39
45
|
end
|
@@ -49,6 +55,7 @@ module Hokusai
|
|
49
55
|
end
|
50
56
|
|
51
57
|
# Name of the func
|
58
|
+
#
|
52
59
|
# eg @target="run_this(one,two)"
|
53
60
|
# the name is `run_this`
|
54
61
|
#
|
@@ -58,6 +65,7 @@ module Hokusai
|
|
58
65
|
end
|
59
66
|
|
60
67
|
# Args of the func
|
68
|
+
#
|
61
69
|
# eg @target="run_this(one, two)"
|
62
70
|
# the args are [one, two]
|
63
71
|
#
|
@@ -74,6 +82,7 @@ module Hokusai
|
|
74
82
|
class Event
|
75
83
|
attr_reader :raw
|
76
84
|
|
85
|
+
# @param [LibHokusai::Event] raw event
|
77
86
|
def initialize(raw)
|
78
87
|
@raw = raw
|
79
88
|
end
|
@@ -93,6 +102,7 @@ module Hokusai
|
|
93
102
|
end
|
94
103
|
end
|
95
104
|
|
105
|
+
# A node representing an ast prop
|
96
106
|
class Prop
|
97
107
|
attr_reader :raw
|
98
108
|
|
@@ -100,14 +110,17 @@ module Hokusai
|
|
100
110
|
@raw = raw
|
101
111
|
end
|
102
112
|
|
113
|
+
# @return [Bool] is this prop computed?
|
103
114
|
def computed?
|
104
115
|
raw[:computed]
|
105
116
|
end
|
106
117
|
|
118
|
+
# @return [String] the props name
|
107
119
|
def name
|
108
120
|
@name ||= raw[:name].freeze
|
109
121
|
end
|
110
122
|
|
123
|
+
# @return [Ast::Func] the props value
|
111
124
|
def value
|
112
125
|
@call ||= raw[:call]
|
113
126
|
|
@@ -166,60 +179,74 @@ module Hokusai
|
|
166
179
|
end
|
167
180
|
end
|
168
181
|
|
182
|
+
# Marks this ast as dirty
|
183
|
+
# @return [Void]
|
169
184
|
def dirty!
|
170
185
|
@dirty = true
|
171
186
|
end
|
172
187
|
|
188
|
+
# Is this ast dirty?
|
189
|
+
# @return [Bool]
|
173
190
|
def dirty?
|
174
191
|
@dirty
|
175
192
|
end
|
176
193
|
|
194
|
+
# @return [Bool] is this node a slot?
|
177
195
|
def slot?
|
178
196
|
type == "slot"
|
179
197
|
end
|
180
198
|
|
199
|
+
# @return [Bool] is this node virtual?
|
181
200
|
def virtual?
|
182
201
|
type == "virtual"
|
183
202
|
end
|
184
203
|
|
204
|
+
# @return [Bool] does this node belong to a loop?
|
185
205
|
def loop?
|
186
206
|
@loop_condition = !raw[:loop].null? if @loop_condition.nil?
|
187
207
|
|
188
208
|
@loop_condition
|
189
209
|
end
|
190
210
|
|
211
|
+
# @return [Bool] does this node have an if condition?
|
191
212
|
def has_if_condition?
|
192
213
|
@if_condition = !raw[:cond].null? if @if_condition.nil?
|
193
214
|
|
194
215
|
@if_condition
|
195
216
|
end
|
196
217
|
|
218
|
+
# @return [Bool] does this node have an else condition?
|
197
219
|
def has_else_condition?
|
198
220
|
@else_condition = !raw[:else_relations].null? if @else_condition.nil?
|
199
221
|
|
200
222
|
@else_condition
|
201
223
|
end
|
202
224
|
|
225
|
+
# @return [Bool] is the else condition on this node currently active?
|
203
226
|
def else_condition_active?
|
204
227
|
has_else_condition? && @else_active == 1
|
205
228
|
end
|
206
229
|
|
230
|
+
# @param [Bool] else condition is active or not
|
207
231
|
def else_active=(val)
|
208
232
|
@else_active = val
|
209
233
|
end
|
210
234
|
|
235
|
+
# @return [Hokusai::Ast?] the ast of the else condition
|
211
236
|
def else_ast
|
212
237
|
return nil unless has_else_condition?
|
213
238
|
|
214
239
|
Ast.new(raw[:else_relations][:next_child])
|
215
240
|
end
|
216
241
|
|
242
|
+
# @return [Ast::Loop?] the loop that the ast belongs to
|
217
243
|
def loop
|
218
244
|
return nil unless loop?
|
219
245
|
|
220
246
|
@loop ||= Loop.new(raw[:loop])
|
221
247
|
end
|
222
248
|
|
249
|
+
# @return [Ast::Func?] the if condition of this ast
|
223
250
|
def if
|
224
251
|
@cond ||= raw[:cond]
|
225
252
|
|
@@ -232,14 +259,17 @@ module Hokusai
|
|
232
259
|
@func ||= Func.new(@call)
|
233
260
|
end
|
234
261
|
|
262
|
+
# @return [String] the node type
|
235
263
|
def type
|
236
264
|
@type ||= raw[:type].nil? ? "(null)" : raw[:type]
|
237
265
|
end
|
238
266
|
|
267
|
+
# @return [String] the node id
|
239
268
|
def id
|
240
269
|
@id ||= raw[:id].nil? ? "(null)" : raw[:id]
|
241
270
|
end
|
242
271
|
|
272
|
+
# @return [Array<String>] the list of classes for this node
|
243
273
|
def classes
|
244
274
|
return @classes unless @classes.nil?
|
245
275
|
|
@@ -251,6 +281,7 @@ module Hokusai
|
|
251
281
|
@classes
|
252
282
|
end
|
253
283
|
|
284
|
+
# @return [Array<Hokusai::Ast>] all the children of this node
|
254
285
|
def children
|
255
286
|
return @children unless @children.nil?
|
256
287
|
|
@@ -262,6 +293,7 @@ module Hokusai
|
|
262
293
|
@children
|
263
294
|
end
|
264
295
|
|
296
|
+
# @return [Array<Hokusai::Ast>] all the siblings of this node
|
265
297
|
def siblings
|
266
298
|
return @siblings unless @siblings.nil?
|
267
299
|
|
@@ -277,6 +309,7 @@ module Hokusai
|
|
277
309
|
@siblings
|
278
310
|
end
|
279
311
|
|
312
|
+
# @return [Array<Hokusai::Ast>] the children of the else condition for this node
|
280
313
|
def else_children
|
281
314
|
children = []
|
282
315
|
|
@@ -290,6 +323,7 @@ module Hokusai
|
|
290
323
|
children
|
291
324
|
end
|
292
325
|
|
326
|
+
# @return [Array<Ast::Prop>] all the props of this node
|
293
327
|
def props
|
294
328
|
return @props unless @props.nil?
|
295
329
|
|
@@ -302,6 +336,7 @@ module Hokusai
|
|
302
336
|
@props
|
303
337
|
end
|
304
338
|
|
339
|
+
# @return [Array<Ast::Event>] all the events of this node
|
305
340
|
def events
|
306
341
|
return @events unless @events.nil?
|
307
342
|
|
@@ -382,60 +417,24 @@ module Hokusai
|
|
382
417
|
i.free
|
383
418
|
end
|
384
419
|
|
420
|
+
# Fetches a prop by name
|
421
|
+
#
|
422
|
+
# @param [String] name of the prop
|
423
|
+
# @return [Ast::Prop?] the prop or nil
|
385
424
|
def prop(name)
|
386
425
|
props[name]
|
387
426
|
end
|
388
427
|
|
389
|
-
#
|
390
|
-
#
|
391
|
-
# @param [String] name the name of the prop to find
|
392
|
-
# @return [Hokusai::Ast::Prop?] the prop if found
|
393
|
-
# def prop(name)
|
394
|
-
# prop_ptr = FFI::MemoryPointer.new :pointer
|
395
|
-
# code = LibHokusai.hoku_ast_prop_init(prop_ptr, name)
|
428
|
+
# Fetches an event by name
|
396
429
|
#
|
397
|
-
#
|
398
|
-
#
|
399
|
-
# prop_ptr2 = prop_ptr.get_pointer(0)
|
400
|
-
# prop = LibHokusai::HmlAstProp.new(prop_ptr2)
|
401
|
-
# response = LibHokusai.hoku_ast_get_prop(raw, prop)
|
402
|
-
# return nil if response.null?
|
403
|
-
#
|
404
|
-
# Prop.new(response)
|
405
|
-
# ensure
|
406
|
-
# prop_ptr.free
|
407
|
-
# end
|
408
|
-
|
430
|
+
# @param [String] the name of the event
|
431
|
+
# @return [Ast::Event?] the event or nil
|
409
432
|
def event(name)
|
410
433
|
events[name]
|
411
434
|
end
|
412
435
|
|
413
|
-
# Search for an event by name
|
414
|
-
#
|
415
|
-
# @param [String] name the name of the prop to find
|
416
|
-
# @return [Prop?] the prop if found
|
417
|
-
# def event(name)
|
418
|
-
# event_ptr = FFI::MemoryPointer.new :pointer
|
419
|
-
# code = LibHokusai.hoku_ast_prop_init(event_ptr, name)
|
420
|
-
#
|
421
|
-
# raise Hokusai::Error.new("Failed to allocate prop") unless code.zero?
|
422
|
-
#
|
423
|
-
# event_ptr2 = event_ptr.get_pointer(0)
|
424
|
-
# event = LibHokusai::HmlAstEvent.new(event_ptr2)
|
425
|
-
# response = LibHokusai.hoku_ast_get_event(raw, event)
|
426
|
-
# event_ptr.free
|
427
|
-
#
|
428
|
-
# return nil if response.null?
|
429
|
-
#
|
430
|
-
# Event.new(response)
|
431
|
-
# ensure
|
432
|
-
# event_ptr.free
|
433
|
-
# end
|
434
|
-
|
435
436
|
def destroy
|
436
|
-
puts "before destroy"
|
437
437
|
LibHokusai.hoku_ast_free(raw)
|
438
|
-
puts "after destroy"
|
439
438
|
end
|
440
439
|
|
441
440
|
# dumps this ast to STDOUT
|
@@ -20,7 +20,7 @@ module Hokusai
|
|
20
20
|
OnWidthCb = Proc.new do |char, ffi_pointer|
|
21
21
|
data = DataForCb.new ffi_pointer
|
22
22
|
|
23
|
-
Raylib.MeasureTextEx(data[:raw], "#{char.chr}", data[:size], data[:spacing]).x + data[:spacing]
|
23
|
+
Raylib.MeasureTextEx(data[:raw], "#{char.chr}", data[:size], data[:spacing]).x + 1.565#@ data[:spacing]
|
24
24
|
end
|
25
25
|
|
26
26
|
class Font < Hokusai::Font
|
@@ -83,7 +83,6 @@ module Hokusai
|
|
83
83
|
raw.baseSize
|
84
84
|
end
|
85
85
|
|
86
|
-
|
87
86
|
def clamp_markdown(text, size, width, initial_offset = 0.0)
|
88
87
|
clamping_pointer = FFI::MemoryPointer.new :pointer
|
89
88
|
RaylibBackend::DataForCb.create(size, spacing, raw) do |ptr|
|
@@ -5,7 +5,18 @@ require 'memory_profiler'
|
|
5
5
|
|
6
6
|
module Hokusai::Backends
|
7
7
|
class RaylibBackend
|
8
|
-
|
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
|
9
20
|
|
10
21
|
attr_reader :config
|
11
22
|
|
@@ -37,8 +48,8 @@ module Hokusai::Backends
|
|
37
48
|
yield(config)
|
38
49
|
end
|
39
50
|
|
40
|
-
def vec2(x, y)
|
41
|
-
if @raylib_vec2.nil?
|
51
|
+
def vec2(x, y, fresh = false)
|
52
|
+
if @raylib_vec2.nil? || fresh
|
42
53
|
@raylib_vec2 = Raylib::Vector2.new
|
43
54
|
end
|
44
55
|
@raylib_vec2[:x] = x
|
@@ -137,14 +148,7 @@ module Hokusai::Backends
|
|
137
148
|
def run(block)
|
138
149
|
self.class.reset
|
139
150
|
|
140
|
-
|
141
|
-
when /darwin/
|
142
|
-
Raylib.load_lib("#{RAYLIB_PATH}/libraylib.dylib")
|
143
|
-
when /mswin|msys|mingw/
|
144
|
-
Raylib.load_lib("#{RAYLIB_PATH}/libraylib.dll")
|
145
|
-
when /linux/
|
146
|
-
Raylib.load_lib("#{RAYLIB_PATH}/libraylib.so")
|
147
|
-
end
|
151
|
+
Raylib.load_lib(RAYLIB_PATH)
|
148
152
|
|
149
153
|
resize = false
|
150
154
|
initial = true
|
@@ -201,7 +205,9 @@ module Hokusai::Backends
|
|
201
205
|
height = last_height
|
202
206
|
|
203
207
|
process_input(input)
|
208
|
+
block.public_send(:before_updated) if block.respond_to?(:before_updated)
|
204
209
|
block.update
|
210
|
+
block.public_send(:after_updated) if block.respond_to?(:after_updated)
|
205
211
|
|
206
212
|
canvas.reset(nil, nil, width.to_f, height.to_f)
|
207
213
|
|
@@ -327,7 +333,6 @@ module Hokusai::Backends
|
|
327
333
|
end
|
328
334
|
|
329
335
|
Hokusai::Commands::SVG.on_draw do |command|
|
330
|
-
command = command.as(Hokusai::Commands::SVG)
|
331
336
|
texture = begin
|
332
337
|
if self.class.images[command.source]
|
333
338
|
self.class.images[command.source]
|
@@ -368,7 +373,12 @@ module Hokusai::Backends
|
|
368
373
|
Hokusai::Commands::Text.on_draw do |command|
|
369
374
|
next unless inside_scissor(command.x, command.y, command.size)
|
370
375
|
|
376
|
+
active_name = Hokusai.fonts.active_font_name
|
371
377
|
font = Hokusai.fonts.active
|
378
|
+
|
379
|
+
Hokusai.fonts.activate command.font.nil? ? active_name : command.font
|
380
|
+
font = Hokusai.fonts.active
|
381
|
+
|
372
382
|
c = color(command.color)
|
373
383
|
x = command.x + command.padding.l
|
374
384
|
y = command.y + command.padding.t
|
@@ -380,6 +390,8 @@ module Hokusai::Backends
|
|
380
390
|
else
|
381
391
|
Raylib.DrawText(command.content, x, y, command.size, c)
|
382
392
|
end
|
393
|
+
|
394
|
+
Hokusai.fonts.activate active_name
|
383
395
|
end
|
384
396
|
|
385
397
|
Hokusai::Commands::Rect.on_draw do |command|
|
@@ -407,26 +419,26 @@ module Hokusai::Backends
|
|
407
419
|
|
408
420
|
# now draw the outlines
|
409
421
|
if command.outline_uniform? && command.rounding > 0.0 && outline_color.a > 0
|
410
|
-
Raylib.
|
422
|
+
Raylib.DrawRectangleRoundedLinesEx(outline_rect, command.rounding, 50, command.outline.top + 1, outline_color)
|
411
423
|
elsif command.outline_uniform? && !(command.rounding <= 0.0) && outline_color.a > 0
|
412
424
|
Raylib.DrawRectangleLinesEx(outline_rect, command.outline.top, outline_color)
|
413
425
|
elsif !command.outline_uniform?
|
414
426
|
ox, oy, ow, oh = command.background_boundary
|
415
427
|
|
416
428
|
if command.outline.top > 0.0
|
417
|
-
Raylib.DrawLineEx(vec2(ox, oy), vec2(ox + ow, oy), command.outline.top, outline_color)
|
429
|
+
Raylib.DrawLineEx(vec2(ox, oy, true), vec2(ox + ow, oy, true), command.outline.top, outline_color)
|
418
430
|
end
|
419
431
|
|
420
432
|
if command.outline.left > 0.0
|
421
|
-
Raylib.DrawLineEx(vec2(ox, oy), vec2(ox, oy + oh), command.outline.left, outline_color)
|
433
|
+
Raylib.DrawLineEx(vec2(ox, oy, true), vec2(ox, oy + oh, true), command.outline.left, outline_color)
|
422
434
|
end
|
423
435
|
|
424
436
|
if command.outline.right > 0.0
|
425
|
-
Raylib.DrawLineEx(vec2(ox + ow, oy), vec2(ox + ow, oy + oh), command.outline.right, outline_color)
|
437
|
+
Raylib.DrawLineEx(vec2(ox + ow, oy, true), vec2(ox + ow, oy + oh, true), command.outline.right, outline_color)
|
426
438
|
end
|
427
439
|
|
428
440
|
if command.outline.bottom > 0.0
|
429
|
-
Raylib.DrawLineEx(vec2(ox, oy + oh), vec2(ox + ow, oy + oh), command.outline.bottom, outline_color)
|
441
|
+
Raylib.DrawLineEx(vec2(ox, oy + oh, true), vec2(ox + ow, oy + oh, true), command.outline.bottom, outline_color)
|
430
442
|
end
|
431
443
|
end
|
432
444
|
else
|
@@ -80,7 +80,6 @@ module Hokusai::Backends
|
|
80
80
|
|
81
81
|
def clamp_markdown(text, size, width, initial_offset = 0.0)
|
82
82
|
self.size = size
|
83
|
-
|
84
83
|
clamping_pointer = FFI::MemoryPointer.new :pointer
|
85
84
|
|
86
85
|
ret = LibHokusai.hoku_text_md_clamp(clamping_pointer, text, width, initial_offset, raw, SDLBackend::OnWidthCb)
|
@@ -105,18 +104,23 @@ module Hokusai::Backends
|
|
105
104
|
end
|
106
105
|
|
107
106
|
def measure(text, size = 15)
|
108
|
-
|
109
|
-
|
107
|
+
begin
|
108
|
+
self.size = size
|
109
|
+
w = FFI::MemoryPointer.new :int
|
110
|
+
h = FFI::MemoryPointer.new :int
|
110
111
|
|
111
|
-
|
112
|
+
SDL.TTF_SizeText(raw, text, w, h)
|
112
113
|
|
113
|
-
|
114
|
-
|
114
|
+
width = w.read_int
|
115
|
+
height = h.read_int
|
115
116
|
|
116
|
-
|
117
|
-
|
117
|
+
w.free
|
118
|
+
h.free
|
118
119
|
|
119
|
-
|
120
|
+
[width, height]
|
121
|
+
ensure
|
122
|
+
self.size = height
|
123
|
+
end
|
120
124
|
end
|
121
125
|
|
122
126
|
def size=(val)
|
@@ -57,7 +57,7 @@ module Hokusai::Backends
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def run(block)
|
60
|
-
resize =
|
60
|
+
resize = true
|
61
61
|
self.render_width = config.width
|
62
62
|
self.render_height = config.height
|
63
63
|
|
@@ -89,7 +89,7 @@ module Hokusai::Backends
|
|
89
89
|
|
90
90
|
Hokusai.fonts.register "default", SDLBackend::Font.from("#{__dir__}/sdl2/Monaco.ttf", 121)
|
91
91
|
Hokusai.fonts.activate "default"
|
92
|
-
config.
|
92
|
+
config.after_load_cb&.call
|
93
93
|
|
94
94
|
register_command_handlers(renderer, window)
|
95
95
|
# MemoryProfiler.start if ENV["PROFILE"]
|
@@ -107,7 +107,7 @@ module Hokusai::Backends
|
|
107
107
|
if process_input(input, event)
|
108
108
|
# since we are using wait event, we need to process the render twice
|
109
109
|
# once to capture all events, and once after updating block state.
|
110
|
-
SDL.SetRenderDrawBlendMode(renderer, SDL::
|
110
|
+
SDL.SetRenderDrawBlendMode(renderer, SDL::BLENDMODE_NONE)
|
111
111
|
SDL.SetRenderDrawColor(renderer, config.background[:r], config.background[:g], config.background[:b], config.background[:a])
|
112
112
|
SDL.RenderClear(renderer)
|
113
113
|
canvas.reset(nil, nil, render_width.to_f, render_height.to_f)
|
@@ -116,7 +116,7 @@ module Hokusai::Backends
|
|
116
116
|
block.update
|
117
117
|
SDL.RenderPresent(renderer)
|
118
118
|
|
119
|
-
SDL.SetRenderDrawBlendMode(renderer, SDL::
|
119
|
+
SDL.SetRenderDrawBlendMode(renderer, SDL::BLENDMODE_NONE)
|
120
120
|
SDL.SetRenderDrawColor(renderer, config.background[:r], config.background[:g], config.background[:b], config.background[:a])
|
121
121
|
SDL.RenderClear(renderer)
|
122
122
|
canvas.reset(nil, nil, render_width.to_f, render_height.to_f)
|
@@ -402,9 +402,35 @@ module Hokusai::Backends
|
|
402
402
|
SDL.RenderCopy(renderer, texture, nil, rect)
|
403
403
|
end
|
404
404
|
|
405
|
-
Hokusai::Commands::
|
405
|
+
Hokusai::Commands::SVG.on_draw do |command|
|
406
406
|
next unless inside_scissor(command.x, command.y, command.height)
|
407
407
|
|
408
|
+
texture = begin
|
409
|
+
if self.class.images[command.source]
|
410
|
+
self.class.images[command.source]
|
411
|
+
else
|
412
|
+
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?
|
417
|
+
raise Hokusai::Error.new("Can't load Image: #{SDL.GetError.read_string}")
|
418
|
+
end
|
419
|
+
|
420
|
+
texture = SDL.CreateTextureFromSurface(renderer, surface_ptr)
|
421
|
+
self.class.images[command.source] = texture
|
422
|
+
SDL.FreeSurface(surface_ptr)
|
423
|
+
texture
|
424
|
+
end
|
425
|
+
end
|
426
|
+
|
427
|
+
SDL.SetTextureColorMod(texture, command.color.r, command.color.g, command.color.b)
|
428
|
+
rect = sdl_rect(command.x, command.y, command.width, command.height)
|
429
|
+
SDL.RenderCopy(renderer, texture, nil, rect)
|
430
|
+
end
|
431
|
+
|
432
|
+
Hokusai::Commands::Rect.on_draw do |command|
|
433
|
+
next unless inside_scissor(command.x, command.y, command.height)
|
408
434
|
# draw background first
|
409
435
|
x, y, w, h = [command.x, command.y, command.width, command.height]
|
410
436
|
|
@@ -480,6 +506,7 @@ module Hokusai::Backends
|
|
480
506
|
rounding = command.rounding
|
481
507
|
|
482
508
|
if command.rounding > 0
|
509
|
+
pp command.color
|
483
510
|
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)
|
484
511
|
else
|
485
512
|
rect = SDL::Rect.new
|
data/ui/src/hokusai/block.rb
CHANGED
@@ -4,6 +4,11 @@ require "forwardable"
|
|
4
4
|
|
5
5
|
module Hokusai
|
6
6
|
module Blocks; end
|
7
|
+
# A UI Component
|
8
|
+
#
|
9
|
+
# Blocks are reusable and can be mounted in other blocks via templates
|
10
|
+
#
|
11
|
+
# Blocks have `props`` and emit `events`
|
7
12
|
class Block
|
8
13
|
attr_reader :node
|
9
14
|
attr_reader :publisher
|
@@ -61,6 +66,8 @@ module Hokusai
|
|
61
66
|
@styles || {}
|
62
67
|
end
|
63
68
|
|
69
|
+
# Defines blocks that this block uses in it's template
|
70
|
+
# Keys map to template node names, values map to a `Hokusai::Block`
|
64
71
|
def self.uses(**args)
|
65
72
|
args.each do |key, value|
|
66
73
|
raise Hokusai::Error.new("#{key} value must be a Block, got #{value}") unless value.is_a?(Block.class)
|
@@ -172,23 +179,23 @@ module Hokusai
|
|
172
179
|
|
173
180
|
def draw(&block)
|
174
181
|
instance_eval(&block)
|
175
|
-
# node.meta.commands.each(&:draw)
|
176
|
-
# node.meta.commands.clear!
|
177
182
|
end
|
178
183
|
|
179
184
|
def method_missing(name, *args,**kwargs, &block)
|
180
|
-
if
|
181
|
-
return
|
185
|
+
if node.meta.commands.respond_to?(name)
|
186
|
+
return node.meta.commands.send(name, *args, **kwargs, &block)
|
182
187
|
end
|
183
188
|
|
184
189
|
super
|
185
190
|
end
|
186
191
|
|
187
192
|
def draw_with
|
188
|
-
yield
|
193
|
+
yield node.meta.commands
|
194
|
+
end
|
189
195
|
|
190
|
-
|
191
|
-
|
196
|
+
def execute_draw
|
197
|
+
node.meta.commands.execute
|
198
|
+
node.meta.commands.clear!
|
192
199
|
end
|
193
200
|
|
194
201
|
def render(canvas)
|