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.
- checksums.yaml +7 -0
- data/Dockerfile +26 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +91 -0
- data/LICENSE +21 -0
- data/README.md +28 -0
- data/ast/genheader +3 -0
- data/ast/include/hashmap.c +1151 -0
- data/ast/include/hashmap.c.license +20 -0
- data/ast/include/hashmap.h +54 -0
- data/ast/src/core/ast.c +448 -0
- data/ast/src/core/ast.h +259 -0
- data/ast/src/core/common.h +24 -0
- data/ast/src/core/component.c +85 -0
- data/ast/src/core/component.h +35 -0
- data/ast/src/core/hml.c +665 -0
- data/ast/src/core/hml.h +11 -0
- data/ast/src/core/input.c +458 -0
- data/ast/src/core/input.h +118 -0
- data/ast/src/core/style.c +101 -0
- data/ast/src/core/style.h +41 -0
- data/ast/src/core/text.c +784 -0
- data/ast/src/core/text.h +93 -0
- data/ast/src/core/util.c +140 -0
- data/ast/src/core/util.h +48 -0
- data/ast/src/hokusai.c +6 -0
- data/ast/src/hokusai.h +6 -0
- data/ast/test/fixtures/test.ui +13 -0
- data/ast/test/greatest.h +1266 -0
- data/ast/test/hokusai.c +14 -0
- data/ast/test/parser.c +234 -0
- data/ast/test/text.c +116 -0
- data/ext/extconf.rb +27 -0
- data/grammar/Cargo.lock +80 -0
- data/grammar/Cargo.toml +26 -0
- data/grammar/binding.gyp +20 -0
- data/grammar/bindings/node/binding.cc +28 -0
- data/grammar/bindings/node/index.js +19 -0
- data/grammar/bindings/rust/build.rs +40 -0
- data/grammar/bindings/rust/lib.rs +52 -0
- data/grammar/corpus/1_document.txt +131 -0
- data/grammar/corpus/2_selectors.txt +58 -0
- data/grammar/corpus/3_spaces.txt +69 -0
- data/grammar/corpus/4_errors.txt +10 -0
- data/grammar/corpus/5_macros.txt +175 -0
- data/grammar/corpus/6_styles.txt +81 -0
- data/grammar/grammar.js +275 -0
- data/grammar/package-lock.json +34 -0
- data/grammar/package.json +33 -0
- data/grammar/src/grammar.json +1269 -0
- data/grammar/src/node-types.json +474 -0
- data/grammar/src/parser.c +5772 -0
- data/grammar/src/scanner.c +258 -0
- data/grammar/src/tree_sitter/parser.h +230 -0
- data/grammar/src/tree_sitter/scanner.h +12 -0
- data/grammar/test.nml +10 -0
- data/hokusai.gemspec +19 -0
- data/ui/examples/assets/DigitalDisplay.ttf +0 -0
- data/ui/examples/assets/OpenSans-Regular.ttf +0 -0
- data/ui/examples/assets/addy.png +0 -0
- data/ui/examples/assets/baby_sean.png +0 -0
- data/ui/examples/assets/football-troll.png +0 -0
- data/ui/examples/assets/gear.png +0 -0
- data/ui/examples/assets/icecold.ttf +0 -0
- data/ui/examples/assets/science-troll.png +0 -0
- data/ui/examples/buddy.rb +31 -0
- data/ui/examples/clock.rb +58 -0
- data/ui/examples/counter.rb +123 -0
- data/ui/examples/dynamic.rb +147 -0
- data/ui/examples/foobar.rb +236 -0
- data/ui/examples/stock.rb +115 -0
- data/ui/examples/stock_decider/option.rb +74 -0
- data/ui/examples/tic_tac_toe.rb +246 -0
- data/ui/lib/lib_hokusai.rb +425 -0
- data/ui/spec/hokusai/ast_spec.rb +88 -0
- data/ui/spec/hokusai/automation/keys_transcoder_spec.rb +50 -0
- data/ui/spec/hokusai/automation/selector_spec.rb +68 -0
- data/ui/spec/hokusai/block_spec.rb +126 -0
- data/ui/spec/hokusai/directives_spec.rb +327 -0
- data/ui/spec/hokusai/e2e/client_spec.rb +58 -0
- data/ui/spec/hokusai/e2e/meta_spec.rb +42 -0
- data/ui/spec/hokusai/publisher_spec.rb +38 -0
- data/ui/spec/hokusai/slots_spec.rb +150 -0
- data/ui/spec/hokusai/util/piece_table_spec.rb +90 -0
- data/ui/spec/hokusai_spec.rb +0 -0
- data/ui/spec/spec_helper.rb +30 -0
- data/ui/src/hokusai/ast.rb +446 -0
- data/ui/src/hokusai/automation/client.rb +167 -0
- data/ui/src/hokusai/automation/constants.rb +98 -0
- data/ui/src/hokusai/automation/converters/selector_converter.rb +61 -0
- data/ui/src/hokusai/automation/driver.rb +54 -0
- data/ui/src/hokusai/automation/driver_command_queue.rb +50 -0
- data/ui/src/hokusai/automation/driver_commands/base.rb +79 -0
- data/ui/src/hokusai/automation/driver_commands/get_attribute.rb +41 -0
- data/ui/src/hokusai/automation/driver_commands/invoke.rb +33 -0
- data/ui/src/hokusai/automation/driver_commands/locate.rb +48 -0
- data/ui/src/hokusai/automation/driver_commands/trigger_keyboard.rb +94 -0
- data/ui/src/hokusai/automation/driver_commands/trigger_mouse.rb +213 -0
- data/ui/src/hokusai/automation/keys_transcoder.rb +128 -0
- data/ui/src/hokusai/automation/selector.rb +39 -0
- data/ui/src/hokusai/automation/server.rb +114 -0
- data/ui/src/hokusai/automation.rb +3 -0
- data/ui/src/hokusai/backends/raylib/config.rb +47 -0
- data/ui/src/hokusai/backends/raylib/font.rb +113 -0
- data/ui/src/hokusai/backends/raylib/keys.rb +124 -0
- data/ui/src/hokusai/backends/raylib.rb +449 -0
- data/ui/src/hokusai/backends/sdl2/Monaco.ttf +0 -0
- data/ui/src/hokusai/backends/sdl2/color.rb +12 -0
- data/ui/src/hokusai/backends/sdl2/config.rb +31 -0
- data/ui/src/hokusai/backends/sdl2/font.rb +127 -0
- data/ui/src/hokusai/backends/sdl2/keys.rb +119 -0
- data/ui/src/hokusai/backends/sdl2.rb +529 -0
- data/ui/src/hokusai/block.rb +237 -0
- data/ui/src/hokusai/blocks/button.rb +100 -0
- data/ui/src/hokusai/blocks/checkbox.rb +51 -0
- data/ui/src/hokusai/blocks/circle.rb +28 -0
- data/ui/src/hokusai/blocks/clipped.rb +23 -0
- data/ui/src/hokusai/blocks/cursor.rb +49 -0
- data/ui/src/hokusai/blocks/dynamic.rb +37 -0
- data/ui/src/hokusai/blocks/empty.rb +10 -0
- data/ui/src/hokusai/blocks/hblock.rb +35 -0
- data/ui/src/hokusai/blocks/image.rb +18 -0
- data/ui/src/hokusai/blocks/input.rb +200 -0
- data/ui/src/hokusai/blocks/label.rb +39 -0
- data/ui/src/hokusai/blocks/panel.rb +126 -0
- data/ui/src/hokusai/blocks/rect.rb +24 -0
- data/ui/src/hokusai/blocks/scissor_begin.rb +18 -0
- data/ui/src/hokusai/blocks/scissor_end.rb +12 -0
- data/ui/src/hokusai/blocks/scrollbar.rb +103 -0
- data/ui/src/hokusai/blocks/selectable.rb +77 -0
- data/ui/src/hokusai/blocks/svg.rb +20 -0
- data/ui/src/hokusai/blocks/text.rb +214 -0
- data/ui/src/hokusai/blocks/titlebar/osx.rb +145 -0
- data/ui/src/hokusai/blocks/toggle.rb +55 -0
- data/ui/src/hokusai/blocks/vblock.rb +35 -0
- data/ui/src/hokusai/commands/base.rb +22 -0
- data/ui/src/hokusai/commands/circle.rb +47 -0
- data/ui/src/hokusai/commands/image.rb +45 -0
- data/ui/src/hokusai/commands/rect.rb +158 -0
- data/ui/src/hokusai/commands/scissor.rb +22 -0
- data/ui/src/hokusai/commands/text.rb +92 -0
- data/ui/src/hokusai/commands.rb +87 -0
- data/ui/src/hokusai/diff.rb +124 -0
- data/ui/src/hokusai/error.rb +3 -0
- data/ui/src/hokusai/event.rb +54 -0
- data/ui/src/hokusai/events/keyboard.rb +84 -0
- data/ui/src/hokusai/events/mouse.rb +172 -0
- data/ui/src/hokusai/font.rb +280 -0
- data/ui/src/hokusai/meta.rb +152 -0
- data/ui/src/hokusai/mounting/loop_entry.rb +230 -0
- data/ui/src/hokusai/mounting/mount_entry.rb +74 -0
- data/ui/src/hokusai/mounting/update_entry.rb +101 -0
- data/ui/src/hokusai/node.rb +98 -0
- data/ui/src/hokusai/node_mounter.rb +102 -0
- data/ui/src/hokusai/painter.rb +214 -0
- data/ui/src/hokusai/publisher.rb +32 -0
- data/ui/src/hokusai/style.rb +72 -0
- data/ui/src/hokusai/types.rb +266 -0
- data/ui/src/hokusai/util/clamping_iterator.rb +202 -0
- data/ui/src/hokusai/util/piece_table.rb +111 -0
- data/ui/src/hokusai/util/selection.rb +145 -0
- data/ui/src/hokusai.rb +120 -0
- data/ui/vendor/.gitkeep +0 -0
- data/vendor/.gitkeep +0 -0
- data/xmake.lua +192 -0
- 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
|