hokusai-zero 0.1.1

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 (166) hide show
  1. checksums.yaml +7 -0
  2. data/Dockerfile +26 -0
  3. data/Gemfile +15 -0
  4. data/Gemfile.lock +91 -0
  5. data/LICENSE +21 -0
  6. data/README.md +28 -0
  7. data/ast/genheader +3 -0
  8. data/ast/include/hashmap.c +1151 -0
  9. data/ast/include/hashmap.c.license +20 -0
  10. data/ast/include/hashmap.h +54 -0
  11. data/ast/src/core/ast.c +448 -0
  12. data/ast/src/core/ast.h +259 -0
  13. data/ast/src/core/common.h +24 -0
  14. data/ast/src/core/component.c +85 -0
  15. data/ast/src/core/component.h +35 -0
  16. data/ast/src/core/hml.c +665 -0
  17. data/ast/src/core/hml.h +11 -0
  18. data/ast/src/core/input.c +458 -0
  19. data/ast/src/core/input.h +118 -0
  20. data/ast/src/core/style.c +101 -0
  21. data/ast/src/core/style.h +41 -0
  22. data/ast/src/core/text.c +784 -0
  23. data/ast/src/core/text.h +93 -0
  24. data/ast/src/core/util.c +140 -0
  25. data/ast/src/core/util.h +48 -0
  26. data/ast/src/hokusai.c +6 -0
  27. data/ast/src/hokusai.h +6 -0
  28. data/ast/test/fixtures/test.ui +13 -0
  29. data/ast/test/greatest.h +1266 -0
  30. data/ast/test/hokusai.c +14 -0
  31. data/ast/test/parser.c +234 -0
  32. data/ast/test/text.c +116 -0
  33. data/ext/extconf.rb +27 -0
  34. data/grammar/Cargo.lock +80 -0
  35. data/grammar/Cargo.toml +26 -0
  36. data/grammar/binding.gyp +20 -0
  37. data/grammar/bindings/node/binding.cc +28 -0
  38. data/grammar/bindings/node/index.js +19 -0
  39. data/grammar/bindings/rust/build.rs +40 -0
  40. data/grammar/bindings/rust/lib.rs +52 -0
  41. data/grammar/corpus/1_document.txt +131 -0
  42. data/grammar/corpus/2_selectors.txt +58 -0
  43. data/grammar/corpus/3_spaces.txt +69 -0
  44. data/grammar/corpus/4_errors.txt +10 -0
  45. data/grammar/corpus/5_macros.txt +175 -0
  46. data/grammar/corpus/6_styles.txt +81 -0
  47. data/grammar/grammar.js +275 -0
  48. data/grammar/package-lock.json +34 -0
  49. data/grammar/package.json +33 -0
  50. data/grammar/src/grammar.json +1269 -0
  51. data/grammar/src/node-types.json +474 -0
  52. data/grammar/src/parser.c +5772 -0
  53. data/grammar/src/scanner.c +258 -0
  54. data/grammar/src/tree_sitter/parser.h +230 -0
  55. data/grammar/src/tree_sitter/scanner.h +12 -0
  56. data/grammar/test.nml +10 -0
  57. data/hokusai.gemspec +19 -0
  58. data/ui/examples/assets/DigitalDisplay.ttf +0 -0
  59. data/ui/examples/assets/OpenSans-Regular.ttf +0 -0
  60. data/ui/examples/assets/addy.png +0 -0
  61. data/ui/examples/assets/baby_sean.png +0 -0
  62. data/ui/examples/assets/football-troll.png +0 -0
  63. data/ui/examples/assets/gear.png +0 -0
  64. data/ui/examples/assets/icecold.ttf +0 -0
  65. data/ui/examples/assets/science-troll.png +0 -0
  66. data/ui/examples/buddy.rb +31 -0
  67. data/ui/examples/clock.rb +58 -0
  68. data/ui/examples/counter.rb +123 -0
  69. data/ui/examples/dynamic.rb +147 -0
  70. data/ui/examples/foobar.rb +236 -0
  71. data/ui/examples/stock.rb +115 -0
  72. data/ui/examples/stock_decider/option.rb +74 -0
  73. data/ui/examples/tic_tac_toe.rb +246 -0
  74. data/ui/lib/lib_hokusai.rb +425 -0
  75. data/ui/spec/hokusai/ast_spec.rb +88 -0
  76. data/ui/spec/hokusai/automation/keys_transcoder_spec.rb +50 -0
  77. data/ui/spec/hokusai/automation/selector_spec.rb +68 -0
  78. data/ui/spec/hokusai/block_spec.rb +126 -0
  79. data/ui/spec/hokusai/directives_spec.rb +327 -0
  80. data/ui/spec/hokusai/e2e/client_spec.rb +58 -0
  81. data/ui/spec/hokusai/e2e/meta_spec.rb +42 -0
  82. data/ui/spec/hokusai/publisher_spec.rb +38 -0
  83. data/ui/spec/hokusai/slots_spec.rb +150 -0
  84. data/ui/spec/hokusai/util/piece_table_spec.rb +90 -0
  85. data/ui/spec/hokusai_spec.rb +0 -0
  86. data/ui/spec/spec_helper.rb +30 -0
  87. data/ui/src/hokusai/ast.rb +446 -0
  88. data/ui/src/hokusai/automation/client.rb +167 -0
  89. data/ui/src/hokusai/automation/constants.rb +98 -0
  90. data/ui/src/hokusai/automation/converters/selector_converter.rb +61 -0
  91. data/ui/src/hokusai/automation/driver.rb +54 -0
  92. data/ui/src/hokusai/automation/driver_command_queue.rb +50 -0
  93. data/ui/src/hokusai/automation/driver_commands/base.rb +79 -0
  94. data/ui/src/hokusai/automation/driver_commands/get_attribute.rb +41 -0
  95. data/ui/src/hokusai/automation/driver_commands/invoke.rb +33 -0
  96. data/ui/src/hokusai/automation/driver_commands/locate.rb +48 -0
  97. data/ui/src/hokusai/automation/driver_commands/trigger_keyboard.rb +94 -0
  98. data/ui/src/hokusai/automation/driver_commands/trigger_mouse.rb +213 -0
  99. data/ui/src/hokusai/automation/keys_transcoder.rb +128 -0
  100. data/ui/src/hokusai/automation/selector.rb +39 -0
  101. data/ui/src/hokusai/automation/server.rb +114 -0
  102. data/ui/src/hokusai/automation.rb +3 -0
  103. data/ui/src/hokusai/backends/raylib/config.rb +47 -0
  104. data/ui/src/hokusai/backends/raylib/font.rb +113 -0
  105. data/ui/src/hokusai/backends/raylib/keys.rb +124 -0
  106. data/ui/src/hokusai/backends/raylib.rb +449 -0
  107. data/ui/src/hokusai/backends/sdl2/Monaco.ttf +0 -0
  108. data/ui/src/hokusai/backends/sdl2/color.rb +12 -0
  109. data/ui/src/hokusai/backends/sdl2/config.rb +31 -0
  110. data/ui/src/hokusai/backends/sdl2/font.rb +127 -0
  111. data/ui/src/hokusai/backends/sdl2/keys.rb +119 -0
  112. data/ui/src/hokusai/backends/sdl2.rb +529 -0
  113. data/ui/src/hokusai/block.rb +237 -0
  114. data/ui/src/hokusai/blocks/button.rb +100 -0
  115. data/ui/src/hokusai/blocks/checkbox.rb +51 -0
  116. data/ui/src/hokusai/blocks/circle.rb +28 -0
  117. data/ui/src/hokusai/blocks/clipped.rb +23 -0
  118. data/ui/src/hokusai/blocks/cursor.rb +49 -0
  119. data/ui/src/hokusai/blocks/dynamic.rb +37 -0
  120. data/ui/src/hokusai/blocks/empty.rb +10 -0
  121. data/ui/src/hokusai/blocks/hblock.rb +35 -0
  122. data/ui/src/hokusai/blocks/image.rb +18 -0
  123. data/ui/src/hokusai/blocks/input.rb +200 -0
  124. data/ui/src/hokusai/blocks/label.rb +39 -0
  125. data/ui/src/hokusai/blocks/panel.rb +126 -0
  126. data/ui/src/hokusai/blocks/rect.rb +24 -0
  127. data/ui/src/hokusai/blocks/scissor_begin.rb +18 -0
  128. data/ui/src/hokusai/blocks/scissor_end.rb +12 -0
  129. data/ui/src/hokusai/blocks/scrollbar.rb +103 -0
  130. data/ui/src/hokusai/blocks/selectable.rb +77 -0
  131. data/ui/src/hokusai/blocks/svg.rb +20 -0
  132. data/ui/src/hokusai/blocks/text.rb +214 -0
  133. data/ui/src/hokusai/blocks/titlebar/osx.rb +145 -0
  134. data/ui/src/hokusai/blocks/toggle.rb +55 -0
  135. data/ui/src/hokusai/blocks/vblock.rb +35 -0
  136. data/ui/src/hokusai/commands/base.rb +22 -0
  137. data/ui/src/hokusai/commands/circle.rb +47 -0
  138. data/ui/src/hokusai/commands/image.rb +45 -0
  139. data/ui/src/hokusai/commands/rect.rb +158 -0
  140. data/ui/src/hokusai/commands/scissor.rb +22 -0
  141. data/ui/src/hokusai/commands/text.rb +92 -0
  142. data/ui/src/hokusai/commands.rb +87 -0
  143. data/ui/src/hokusai/diff.rb +124 -0
  144. data/ui/src/hokusai/error.rb +3 -0
  145. data/ui/src/hokusai/event.rb +54 -0
  146. data/ui/src/hokusai/events/keyboard.rb +84 -0
  147. data/ui/src/hokusai/events/mouse.rb +172 -0
  148. data/ui/src/hokusai/font.rb +280 -0
  149. data/ui/src/hokusai/meta.rb +152 -0
  150. data/ui/src/hokusai/mounting/loop_entry.rb +230 -0
  151. data/ui/src/hokusai/mounting/mount_entry.rb +74 -0
  152. data/ui/src/hokusai/mounting/update_entry.rb +101 -0
  153. data/ui/src/hokusai/node.rb +98 -0
  154. data/ui/src/hokusai/node_mounter.rb +102 -0
  155. data/ui/src/hokusai/painter.rb +214 -0
  156. data/ui/src/hokusai/publisher.rb +32 -0
  157. data/ui/src/hokusai/style.rb +72 -0
  158. data/ui/src/hokusai/types.rb +266 -0
  159. data/ui/src/hokusai/util/clamping_iterator.rb +202 -0
  160. data/ui/src/hokusai/util/piece_table.rb +111 -0
  161. data/ui/src/hokusai/util/selection.rb +145 -0
  162. data/ui/src/hokusai.rb +120 -0
  163. data/ui/vendor/.gitkeep +0 -0
  164. data/vendor/.gitkeep +0 -0
  165. data/xmake.lua +192 -0
  166. metadata +222 -0
@@ -0,0 +1,119 @@
1
+ module Hokusai::Backends
2
+ class SDLBackend
3
+ Keys = [
4
+ [:null, SDL::SDLK_UNKNOWN],
5
+ # [:left_super, SDL::SDLK_LSUPER],
6
+ # [:right_super, SDL::SDLK_RSUPER],
7
+ [:apostrophe, SDL::SDLK_QUOTE],
8
+ [:comma, SDL::SDLK_COMMA],
9
+ [:minus, SDL::SDLK_MINUS],
10
+ [:period, SDL::SDLK_PERIOD],
11
+ [:slash, SDL::SDLK_SLASH],
12
+ [:zero, SDL::SDLK_0],
13
+ [:one, SDL::SDLK_1],
14
+ [:two, SDL::SDLK_2],
15
+ [:three, SDL::SDLK_3],
16
+ [:four, SDL::SDLK_4],
17
+ [:five, SDL::SDLK_5],
18
+ [:six, SDL::SDLK_6],
19
+ [:seven, SDL::SDLK_7],
20
+ [:eight, SDL::SDLK_8],
21
+ [:nine, SDL::SDLK_9],
22
+ [:semicolon, SDL::SDLK_SEMICOLON],
23
+ [:equal, SDL::SDLK_EQUALS],
24
+ [:a, SDL::SDLK_a],
25
+ [:b, SDL::SDLK_b],
26
+ [:c, SDL::SDLK_c],
27
+ [:d, SDL::SDLK_d],
28
+ [:e, SDL::SDLK_e],
29
+ [:f, SDL::SDLK_f],
30
+ [:g, SDL::SDLK_g],
31
+ [:h, SDL::SDLK_h],
32
+ [:i, SDL::SDLK_i],
33
+ [:j, SDL::SDLK_j],
34
+ [:k, SDL::SDLK_k],
35
+ [:l, SDL::SDLK_l],
36
+ [:m, SDL::SDLK_m],
37
+ [:n, SDL::SDLK_n],
38
+ [:o, SDL::SDLK_o],
39
+ [:p, SDL::SDLK_p],
40
+ [:q, SDL::SDLK_q],
41
+ [:r, SDL::SDLK_r],
42
+ [:s, SDL::SDLK_s],
43
+ [:t, SDL::SDLK_t],
44
+ [:u, SDL::SDLK_u],
45
+ [:v, SDL::SDLK_v],
46
+ [:w, SDL::SDLK_w],
47
+ [:x, SDL::SDLK_x],
48
+ [:y, SDL::SDLK_y],
49
+ [:z, SDL::SDLK_z],
50
+ [:left_bracket, SDL::SDLK_LEFTBRACKET],
51
+ [:backslash, SDL::SDLK_BACKSLASH],
52
+ [:right_bracket, SDL::SDLK_RIGHTBRACKET],
53
+ [:grave, SDL::SDLK_BACKQUOTE],
54
+ [:space, SDL::SDLK_SPACE],
55
+ [:escape, SDL::SDLK_ESCAPE],
56
+ [:enter, SDL::SDLK_RETURN],
57
+ [:tab, SDL::SDLK_TAB],
58
+ [:backspace, SDL::SDLK_BACKSPACE],
59
+ [:insert, SDL::SDLK_INSERT],
60
+ [:delete, SDL::SDLK_DELETE],
61
+ [:right, SDL::SDLK_RIGHT],
62
+ [:left, SDL::SDLK_LEFT],
63
+ [:down, SDL::SDLK_DOWN],
64
+ [:up, SDL::SDLK_UP],
65
+ [:page_up, SDL::SDLK_PAGEUP],
66
+ [:page_down, SDL::SDLK_PAGEDOWN],
67
+ [:home, SDL::SDLK_HOME],
68
+ [:end, SDL::SDLK_END],
69
+ [:caps_lock, SDL::SDLK_CAPSLOCK],
70
+ [:scroll_lock, SDL::SDLK_SCROLLLOCK],
71
+ [:num_lock, SDL::SDLK_NUMLOCKCLEAR],
72
+ [:print_screen, SDL::SDLK_PRINTSCREEN],
73
+ [:pause, SDL::SDLK_PAUSE],
74
+ [:f1, SDL::SDLK_F1],
75
+ [:f2, SDL::SDLK_F2],
76
+ [:f3, SDL::SDLK_F3],
77
+ [:f4, SDL::SDLK_F4],
78
+ [:f5, SDL::SDLK_F5],
79
+ [:f6, SDL::SDLK_F6],
80
+ [:f7, SDL::SDLK_F7],
81
+ [:f8, SDL::SDLK_F8],
82
+ [:f9, SDL::SDLK_F9],
83
+ [:f10, SDL::SDLK_F10],
84
+ [:f11, SDL::SDLK_F11],
85
+ [:f12, SDL::SDLK_F12],
86
+ [:kb_menu, SDL::SDLK_MENU],
87
+ [:kp_0, SDL::SDLK_KP_0],
88
+ [:kp_1, SDL::SDLK_KP_1],
89
+ [:kp_2, SDL::SDLK_KP_2],
90
+ [:kp_3, SDL::SDLK_KP_3],
91
+ [:kp_4, SDL::SDLK_KP_4],
92
+ [:kp_5, SDL::SDLK_KP_5],
93
+ [:kp_6, SDL::SDLK_KP_6],
94
+ [:kp_7, SDL::SDLK_KP_7],
95
+ [:kp_8, SDL::SDLK_KP_8],
96
+ [:kp_9, SDL::SDLK_KP_9],
97
+ [:kp_decimal, SDL::SDLK_KP_DECIMAL],
98
+ [:kp_divide, SDL::SDLK_KP_DIVIDE],
99
+ [:kp_multiply, SDL::SDLK_KP_MULTIPLY],
100
+ [:kp_subtract, SDL::SDLK_KP_MINUS],
101
+ [:kp_add, SDL::SDLK_KP_PLUS],
102
+ [:kp_enter, SDL::SDLK_KP_ENTER],
103
+ [:kp_equal, SDL::SDLK_KP_EQUALS],
104
+ [:back, SDL::SDLK_AC_BACK],
105
+ [:menu, SDL::SDLK_MENU],
106
+ [:volume_up, SDL::SDLK_VOLUMEUP],
107
+ [:volume_down, SDL::SDLK_VOLUMEDOWN]].to_h {|(k,v)| [v, k]}
108
+
109
+ Modifiers = [
110
+ [SDL::KMOD_LSHIFT, :left_shift],
111
+ [SDL::KMOD_RSHIFT, :right_shift],
112
+ [SDL::KMOD_RALT, :right_alt],
113
+ [SDL::KMOD_RCTRL, :right_control],
114
+ [SDL::KMOD_LALT, :left_alt],
115
+ [SDL::KMOD_LCTRL, :left_control],
116
+ ]
117
+
118
+ end
119
+ end
@@ -0,0 +1,529 @@
1
+ require "sdl2"
2
+ require_relative "./sdl2/color"
3
+ require_relative "./sdl2/config"
4
+ require_relative './sdl2/font'
5
+ require_relative './sdl2/keys'
6
+
7
+ module Hokusai::Backends
8
+ class SDLBackend
9
+ attr_reader :config
10
+ attr_accessor :render_width, :render_height
11
+
12
+ SDL_PATH = ENV["SDL_PATH"] || "#{__dir__}/../../../../vendor/lib"
13
+
14
+ def self.run(app)
15
+ backend = new do |config|
16
+ yield(config)
17
+ end
18
+
19
+ block = app.mount
20
+ backend.run(block)
21
+ end
22
+
23
+ def self.cursors
24
+ @cursors ||= {
25
+ default: SDL.CreateSystemCursor(SDL::SYSTEM_CURSOR_ARROW),
26
+ arrow: SDL.CreateSystemCursor(SDL::SYSTEM_CURSOR_ARROW),
27
+ ibeam: SDL.CreateSystemCursor(SDL::SYSTEM_CURSOR_IBEAM),
28
+ crosshair: SDL.CreateSystemCursor(SDL::SYSTEM_CURSOR_CROSSHAIR),
29
+ pointer: SDL.CreateSystemCursor(SDL::SYSTEM_CURSOR_HAND)
30
+ }
31
+ end
32
+
33
+ def self.stopped
34
+ @stopped ||= false
35
+ end
36
+
37
+ def self.stopped=(val)
38
+ @stopped = val
39
+ end
40
+
41
+ def self.images
42
+ @images ||= {}
43
+ end
44
+
45
+ def self.fonts
46
+ @fonts ||= {}
47
+ end
48
+
49
+ def self.font_textures
50
+ @font_textures ||= {}
51
+ end
52
+
53
+ def initialize
54
+ @config = Config.new
55
+
56
+ yield @config
57
+ end
58
+
59
+ def run(block)
60
+ resize = false
61
+ self.render_width = config.width
62
+ self.render_height = config.height
63
+
64
+ case RbConfig::CONFIG['host_os']
65
+ when /darwin/
66
+ SDL.load_lib(
67
+ "#{SDL_PATH}/libSDL2.dylib",
68
+ true,
69
+ gfx_libpath: "#{SDL_PATH}/libSDL2_gfx.dylib",
70
+ ttf_libpath: "#{SDL_PATH}/libSDL2_ttf.dylib",
71
+ image_libpath: "#{SDL_PATH}/libSDL2_image.dylib"
72
+ )
73
+ when /mswin|msys|mingw/
74
+ SDL.load_lib("#{SDL_PATH}/SDL2.dll", true, gfx_libpath: "#{SDL_PATH}/libSDL2_gfx.dll" )
75
+ when /linux/
76
+ SDL.load_lib(
77
+ "#{SDL_PATH}/libSDL2.so", true,
78
+ gfx_libpath: "#{SDL_PATH}/libSDL2_gfx.so",
79
+ ttf_libpath: "#{SDL_PATH}/libSDL2_ttf.so",
80
+ image_libpath: "#{SDL_PATH}/libSDL2_image.so"
81
+ )
82
+ end
83
+ SDL.Init(config.init_flags)
84
+ SDL.TTF_Init
85
+
86
+ window = SDL.CreateWindow(config.title, 30, 30, render_width, render_height, config.window_config_flags)
87
+ SDL.SetWindowPosition(window, SDL::WINDOWPOS_CENTERED_MASK, SDL::WINDOWPOS_CENTERED_MASK)
88
+ renderer = SDL.CreateRenderer(window, -1, SDL::RENDERER_TARGETTEXTURE | SDL::RENDERER_ACCELERATED)
89
+
90
+ Hokusai.fonts.register "default", SDLBackend::Font.from("#{__dir__}/sdl2/Monaco.ttf", 121)
91
+ Hokusai.fonts.activate "default"
92
+ config.after_load&.call
93
+
94
+ register_command_handlers(renderer, window)
95
+ # MemoryProfiler.start if ENV["PROFILE"]
96
+
97
+ ptr = FFI::MemoryPointer.new :pointer
98
+ LibHokusai.hoku_input_init(ptr)
99
+ raw = LibHokusai::HmlInput.new(ptr.get_pointer(0))
100
+ input = Hokusai::Input.new(raw)
101
+ canvas = Hokusai::Canvas.new(render_width.to_f, render_height.to_f)
102
+ event = SDL::Event.new
103
+
104
+ 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_BLEND)
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_BLEND)
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)
126
+ end
127
+ end
128
+
129
+ LibHokusai.hoku_input_free(input.raw)
130
+ if ENV["PROFILE"]
131
+ # report = MemoryProfiler.stop
132
+ # report.pretty_print
133
+ end
134
+ end
135
+
136
+ def mouse_button(clicked: false, down: false, released: false, up: false)
137
+ if @mouse_button.nil?
138
+ @mouse_button = LibHokusai::HmlInputMouseButton.create(clicked: clicked, down: down, released: released, up: up)
139
+ else
140
+ @mouse_button[:clicked] = clicked
141
+ @mouse_button[:down] = down
142
+ @mouse_button[:released] = released
143
+ @mouse_button[:up] = up
144
+ end
145
+
146
+ @mouse_button
147
+ end
148
+
149
+ def sdl_rect(x, y, w, h)
150
+ @sdl_rect ||= SDL::Rect.new
151
+ @sdl_rect[:x] = x
152
+ @sdl_rect[:y] = y
153
+ @sdl_rect[:w] = w
154
+ @sdl_rect[:h] = h
155
+
156
+ @sdl_rect
157
+ end
158
+
159
+ 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
164
+
165
+ Keys.values.each do |hkey|
166
+ LibHokusai.hoku_input_keyboard_set_key(input.raw, hkey, false)
167
+ end
168
+
169
+ LibHokusai.hoku_input_keyboard_stop(input.raw)
170
+ end
171
+
172
+ def process_input(input, event)
173
+ reset_keys(input)
174
+
175
+ case event[:common][:type]
176
+ when SDL::KEYDOWN
177
+ modifier = event[:key][:keysym][:mod]
178
+ code = event[:key][:keysym][:sym]
179
+ hkey = Keys[code]
180
+
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)
185
+ end
186
+ end
187
+
188
+ LibHokusai.hoku_input_keyboard_set_key(input.raw, hkey, true) unless hkey.nil?
189
+ LibHokusai.hoku_input_keyboard_stop(input.raw)
190
+
191
+ return true
192
+ 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)
201
+ end
202
+ end
203
+
204
+ LibHokusai.hoku_input_keyboard_set_key(input.raw, hkey, false) unless hkey.nil?
205
+ LibHokusai.hoku_input_keyboard_stop(input.raw)
206
+ return true
207
+ when SDL::WINDOWEVENT
208
+ if event[:window][:event] == SDL::WINDOWEVENT_RESIZED
209
+ self.render_width = event[:window][:data1]
210
+ self.render_height = event[:window][:data2]
211
+
212
+ # free all static font textures
213
+ self.class.fonts.each do |k, payload|
214
+ texture, *_ = payload
215
+
216
+ SDL.DestroyTexture(texture)
217
+ end
218
+
219
+ self.class.fonts.clear
220
+ elsif event[:window][:event] == SDL::WINDOWEVENT_MOVED
221
+ # pp ["moved", Time.now.strftime("%H:%M:%S %L")]
222
+ end
223
+
224
+ return true
225
+ when SDL::MOUSEMOTION
226
+ if input.raw[:mouse][:delta][:y] > 0
227
+ # LibHokusai.hoku_input_mouse_set_scroll(input.raw, 0.0)
228
+ input.raw[:mouse][:delta][:y] = 0.0
229
+ input.raw[:mouse][:scroll_delta] = 0.0
230
+ input.raw[:mouse][:scroll] = event[:motion][:y]
231
+ end
232
+
233
+ # pp ["set mouse", Time.now.strftime("%H:%M:%S %L")]
234
+ hoku_mouse_pos = LibHokusai::HmlVec2.create(event[:motion][:x], event[:motion][:y])
235
+ LibHokusai.hoku_input_set_mouse_position(input.raw, hoku_mouse_pos)
236
+
237
+ # clear any click events
238
+ [[:left, 0], [:right, 2], [:middle, 1]].each do |(btn, i)|
239
+ button = input.raw[:mouse][btn]
240
+ button[:clicked] = false
241
+ LibHokusai.hoku_input_mouse_set_button(input.raw, button, i)
242
+ end
243
+
244
+ return true
245
+ when SDL::MOUSEWHEEL
246
+ LibHokusai.hoku_input_mouse_set_scroll(input.raw, event[:wheel][:preciseY])
247
+ input.raw[:mouse][:delta][:y] = event[:wheel][:preciseY]
248
+
249
+ # clear any click events
250
+ [[:left, 0], [:right, 2], [:middle, 1]].each do |(btn, i)|
251
+ button = input.raw[:mouse][btn]
252
+ button[:clicked] = false
253
+ LibHokusai.hoku_input_mouse_set_button(input.raw, button, i)
254
+ end
255
+ return true
256
+ when SDL::MOUSEBUTTONDOWN
257
+ clicked = event[:button][:clicks] > 0
258
+ button = mouse_button(down: true, clicked: clicked)
259
+
260
+ # LibHokusai.hoku_input_mouse_set_scroll(input.raw, 0.0)
261
+ # input.raw[:mouse][:delta][:y] = 0.0
262
+
263
+ LibHokusai.hoku_input_mouse_set_button(input.raw, button, event[:button][:which])
264
+ return true
265
+ when SDL::MOUSEBUTTONUP
266
+ button = mouse_button(up: true)
267
+ #
268
+ # LibHokusai.hoku_input_mouse_set_scroll(input.raw, 0.0)
269
+ # input.raw[:mouse][:delta][:y] = 0.0
270
+
271
+ LibHokusai.hoku_input_mouse_set_button(input.raw, button, event[:button][:which])
272
+ return true
273
+ when SDL::TEXTINPUT
274
+ return false
275
+ else
276
+ false
277
+ end
278
+ end
279
+
280
+ def nine_slice(x, y, w, h, rounding)
281
+ tx = x + rounding
282
+ ty = y
283
+ tw = w - (rounding * 2)
284
+ th = rounding
285
+
286
+ mx = x + rounding
287
+ my = y + rounding
288
+ mw = w - (rounding * 2)
289
+ mh = h - (rounding * 2)
290
+
291
+ bx = x + rounding
292
+ by = h - rounding
293
+ bw = w - (rounding * 2)
294
+ bh = rounding
295
+
296
+ {
297
+ top_center: [tx, ty, tw, th],
298
+ middle_center: [mx, my, mw, mh],
299
+ bottom_center: [bx, by, bw, bh]
300
+ }
301
+ end
302
+
303
+ def inside_scissor(x, y, h = 0)
304
+ return true if @scissor.nil?
305
+
306
+ val = y + h >= @scissor[1] && y <= @scissor[1] + @scissor[3]
307
+ # pp ["inside scissor", val, [x,y], @scissor]
308
+ val
309
+ end
310
+
311
+
312
+ def register_command_handlers(renderer, window)
313
+ Hokusai.on_set_mouse_cursor do |type|
314
+ sdl = self.class.cursors[type]
315
+ SDL.SetCursor(sdl)
316
+ end
317
+
318
+ Hokusai.on_maximize_window do
319
+ SDL.MaximizeWindow(window)
320
+ end
321
+
322
+ Hokusai.on_close_window do
323
+ self.class.stopped = true
324
+ end
325
+
326
+ Hokusai.on_minimize_window do
327
+ SDL.MinimizeWindow(window)
328
+ end
329
+
330
+ Hokusai.on_set_window_position do |(ox, oy)|
331
+ xp = FFI::MemoryPointer.new :int
332
+ yp = FFI::MemoryPointer.new :int
333
+
334
+ SDL.GetWindowPosition(window, xp, yp)
335
+
336
+ x = xp.read_int
337
+ y = yp.read_int
338
+
339
+ SDL.SetWindowPosition(window, (x + ox).to_i, (y + oy).to_i)
340
+ xp.free
341
+ yp.free
342
+ end
343
+
344
+ Hokusai.on_renderable do |canvas|
345
+ inside_scissor(canvas.x, canvas.y, canvas.height)
346
+ end
347
+
348
+ Hokusai::Commands::ScissorBegin.on_draw do |command|
349
+ rect = sdl_rect(command.x, command.y, command.width, command.height)
350
+ SDL.RenderSetClipRect(renderer, rect)
351
+
352
+ @scissor = [command.x, command.y, command.width, command.height]
353
+ end
354
+
355
+ Hokusai::Commands::ScissorEnd.on_draw do |_|
356
+ SDL.RenderSetClipRect(renderer, nil)
357
+
358
+ @scissor = nil
359
+ end
360
+
361
+ Hokusai::Commands::Circle.on_draw do |command|
362
+ next unless inside_scissor(command.x, command.y)
363
+
364
+ if command.outline > 0 && command.outline_color.a > 0
365
+ SDL.filledCircleRGBA(
366
+ renderer,
367
+ command.x,
368
+ command.y,
369
+ command.radius + command.outline,
370
+ command.color.r, command.color.g, command.color.b, command.color.a)
371
+ end
372
+
373
+ SDL.filledCircleRGBA(
374
+ renderer,
375
+ command.x,
376
+ command.y,
377
+ command.radius,
378
+ command.color.r, command.color.g, command.color.b, command.color.a
379
+ )
380
+ end
381
+
382
+ Hokusai::Commands::Image.on_draw do |command|
383
+ next unless inside_scissor(command.x, command.y, command.height)
384
+
385
+ texture = begin
386
+ if self.class.images[command.source]
387
+ self.class.images[command.source]
388
+ else
389
+ surface_ptr = SDL.IMG_Load(command.source)
390
+ if surface_ptr.null?
391
+ raise Hokusai::Error.new("Can't load Image: #{SDL.GetError.read_string}")
392
+ end
393
+
394
+ texture = SDL.CreateTextureFromSurface(renderer, surface_ptr)
395
+ self.class.images[command.source] = texture
396
+ SDL.FreeSurface(surface_ptr)
397
+ texture
398
+ end
399
+ end
400
+
401
+ rect = sdl_rect(command.x, command.y, command.width, command.height)
402
+ SDL.RenderCopy(renderer, texture, nil, rect)
403
+ end
404
+
405
+ Hokusai::Commands::Rect.on_draw do |command|
406
+ next unless inside_scissor(command.x, command.y, command.height)
407
+
408
+ # draw background first
409
+ x, y, w, h = [command.x, command.y, command.width, command.height]
410
+
411
+ if command.outline_uniform? && command.rounding > 0 && command.outline_color.a > 0
412
+ SDL.roundedBoxRGBA(
413
+ renderer, x, y, x + w, y + h, (command.rounding).ceil.to_i,
414
+ command.outline_color.r,
415
+ command.outline_color.g,
416
+ command.outline_color.b,
417
+ command.outline_color.a
418
+ )
419
+ elsif command.outline_uniform? && command.rounding <= 0 && command.outline_color.a > 0
420
+ SDL.boxRGBA(
421
+ renderer, x, y, x + w, y + h,
422
+ command.outline_color.r,
423
+ command.outline_color.g,
424
+ command.outline_color.b,
425
+ command.outline_color.a
426
+ )
427
+ elsif command.outline_color.a > 0 && command.rounding <= 0
428
+ # x, y, w, h = command.background_boundary
429
+ if command.outline.top > 0
430
+ SDL.thickLineRGBA(
431
+ renderer,
432
+ x, y + (command.outline.top / 2), x + w, y + (command.outline.top / 2),
433
+ command.outline.top,
434
+ command.outline_color.r,
435
+ command.outline_color.g,
436
+ command.outline_color.b,
437
+ command.outline_color.a
438
+ )
439
+ end
440
+
441
+ if command.outline.right > 0
442
+ SDL.thickLineRGBA(
443
+ renderer,
444
+ x + w - (command.outline.right / 2), y, x + w - (command.outline.right / 2), y + h,
445
+ command.outline.right,
446
+ command.outline_color.r,
447
+ command.outline_color.g,
448
+ command.outline_color.b,
449
+ command.outline_color.a
450
+ )
451
+ end
452
+
453
+ if command.outline.bottom > 0
454
+ SDL.thickLineRGBA(
455
+ renderer,
456
+ x, y + h - (command.outline.bottom / 2), x + w, y + h - (command.outline.bottom / 2),
457
+ command.outline.bottom,
458
+ command.outline_color.r,
459
+ command.outline_color.g,
460
+ command.outline_color.b,
461
+ command.outline_color.a
462
+ )
463
+ end
464
+
465
+ if command.outline.left > 0
466
+ SDL.thickLineRGBA(
467
+ renderer,
468
+ x + (command.outline.left / 2), y , x + (command.outline.left / 2), y + h,
469
+ command.outline.left,
470
+ command.outline_color.r,
471
+ command.outline_color.g,
472
+ command.outline_color.b,
473
+ command.outline_color.a
474
+ )
475
+ end
476
+ end
477
+
478
+
479
+ x, y, w, h = command.background_boundary
480
+ rounding = command.rounding
481
+
482
+ if command.rounding > 0
483
+ 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
+ else
485
+ rect = SDL::Rect.new
486
+ rect[:x] = x
487
+ rect[:y] = y
488
+ rect[:w] = w
489
+ rect[:h] = h
490
+
491
+ SDL.SetRenderDrawColor(renderer, command.color.r, command.color.g, command.color.b, command.color.a)
492
+ SDL.RenderFillRect(renderer, rect)
493
+ end
494
+ end
495
+
496
+ Hokusai::Commands::Text.on_draw do |command|
497
+ next unless inside_scissor(command.x, command.y, command.size)
498
+
499
+ unless command.content.empty?
500
+ payload = begin
501
+ if self.class.fonts[command.hash] && command.static
502
+ self.class.fonts[command.hash]
503
+ else
504
+ font = (!command.font.nil? ? Hokusai.fonts.get(command.font) : Hokusai.fonts.active)
505
+ font.size = command.size
506
+ surface_ptr = font.render(command.content, command.color, bold: command.bold, italic: command.italic)
507
+ texture = SDL.CreateTextureFromSurface(renderer, surface_ptr)
508
+ surface = SDL::Surface.new(surface_ptr)
509
+ load = [texture, surface[:w], surface[:h]]
510
+ self.class.fonts[command.hash] = load
511
+ SDL.FreeSurface(surface_ptr)
512
+ load
513
+ end
514
+ end
515
+
516
+ texture, width, height = payload
517
+
518
+ SDL.RenderCopy(renderer, texture, nil, sdl_rect(
519
+ command.x + command.padding.left,
520
+ command.y + command.padding.top,
521
+ width,# - (command.padding.left + command.padding.right),
522
+ height# - (command.padding.top + command.padding.bottom)
523
+ ))
524
+ SDL.DestroyTexture(texture) unless command.static
525
+ end
526
+ end
527
+ end
528
+ end
529
+ end