hokusai-zero 0.2.5 → 0.2.6.pre.pinephone
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +0 -1
- data/Gemfile.lock +0 -2
- data/README.md +1 -1
- data/ast/src/core/input.c +85 -0
- data/ast/src/core/input.h +31 -0
- data/ast/src/core/util.c +23 -23
- data/ast/src/core/util.h +7 -7
- data/ext/extconf.rb +7 -3
- data/hokusai.gemspec +1 -2
- data/ui/examples/drag.rb +154 -0
- data/ui/examples/embedded.rb +59 -0
- data/ui/examples/game.rb +143 -0
- data/ui/examples/overlay.rb +233 -0
- data/ui/examples/provider.rb +56 -0
- data/ui/examples/shader/test.rb +145 -0
- data/ui/examples/shader.rb +100 -0
- data/ui/examples/wiki.rb +82 -0
- data/ui/lib/lib_hokusai.rb +29 -8
- data/ui/spec/spec_helper.rb +1 -1
- data/ui/src/hokusai/assets/arrow-down-line.png +0 -0
- data/ui/src/hokusai/assets/arrow-down-wide-line.png +0 -0
- data/ui/src/hokusai/automation/server.rb +2 -3
- data/ui/src/hokusai/backends/embedded/config.rb +47 -0
- data/ui/src/hokusai/backends/embedded/font.rb +112 -0
- data/ui/src/hokusai/backends/embedded/keys.rb +124 -0
- data/ui/src/hokusai/backends/embedded.rb +564 -0
- data/ui/src/hokusai/backends/raylib.rb +80 -5
- data/ui/src/hokusai/blocks/color_picker.rb +1080 -0
- data/ui/src/hokusai/blocks/shader_begin.rb +22 -0
- data/ui/src/hokusai/blocks/shader_end.rb +12 -0
- data/ui/src/hokusai/blocks/texture.rb +23 -0
- data/ui/src/hokusai/commands/rect.rb +10 -1
- data/ui/src/hokusai/commands/shader.rb +33 -0
- data/ui/src/hokusai/commands/texture.rb +26 -0
- data/ui/src/hokusai/commands.rb +22 -0
- data/ui/src/hokusai/event.rb +2 -1
- data/ui/src/hokusai/events/embedded.rb +66 -0
- data/ui/src/hokusai/painter.rb +22 -0
- data/ui/src/hokusai/types.rb +29 -0
- data/ui/src/hokusai.rb +4 -9
- metadata +24 -22
- data/ui/src/hokusai/assets/chevron-down.svg +0 -1
data/ui/examples/game.rb
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
require_relative "../src/hokusai"
|
2
|
+
require_relative "../src/hokusai/backends/raylib"
|
3
|
+
require 'ostruct'
|
4
|
+
|
5
|
+
TILES = [
|
6
|
+
["Power Supply", 500],
|
7
|
+
["Power Distribution", 400],
|
8
|
+
["Farm", 100],
|
9
|
+
["Medicine Production", 50],
|
10
|
+
["Science Research", 400],
|
11
|
+
["Lumberyard", 200],
|
12
|
+
["Art Gallery", 20],
|
13
|
+
["School", 100],
|
14
|
+
["Commercial transportation", 300],
|
15
|
+
["Mechanical Automation", 700],
|
16
|
+
["Tailor shop", 50],
|
17
|
+
["Housing Construction", 200],
|
18
|
+
["Commerical Building Construction", 300],
|
19
|
+
["Restaraunt", 50],
|
20
|
+
["Furniture manufacturing", 200],
|
21
|
+
["Cotton mill", 200],
|
22
|
+
["Metals processing", 400],
|
23
|
+
["Forestry center", 400],
|
24
|
+
["Bar", 50],
|
25
|
+
["Healthcare", 100]
|
26
|
+
]
|
27
|
+
|
28
|
+
|
29
|
+
class Game < Hokusai::Block
|
30
|
+
style <<-EOF
|
31
|
+
[style]
|
32
|
+
bg {
|
33
|
+
color: rgb(173, 207, 224);
|
34
|
+
width: 100;
|
35
|
+
height: 100;
|
36
|
+
outline: outline(1.0, 1.0, 1.0, 1.0);
|
37
|
+
outline_color: rgb(0, 0, 0);
|
38
|
+
}
|
39
|
+
board {
|
40
|
+
height: 500;
|
41
|
+
width: 500;
|
42
|
+
}
|
43
|
+
height {
|
44
|
+
height: 100;
|
45
|
+
}
|
46
|
+
textPadding {
|
47
|
+
padding: padding(10.0, 5.0, 10.0, 10.0);
|
48
|
+
}
|
49
|
+
EOF
|
50
|
+
template <<~EOF
|
51
|
+
[template]
|
52
|
+
vblock { ...board }
|
53
|
+
hblock
|
54
|
+
[for="tile in top"]
|
55
|
+
rect { :key="top_key(tile)" ...bg }
|
56
|
+
text { :content="tile" ...textPadding}
|
57
|
+
[for="i in middle"]
|
58
|
+
hblock {...height :key="get(i)"}
|
59
|
+
rect {...bg}
|
60
|
+
text { :key="get(i)" :content="get(i)" ...textPadding }
|
61
|
+
empty
|
62
|
+
empty
|
63
|
+
empty
|
64
|
+
rect {...bg }
|
65
|
+
text { :key="get_next(i)" :content="get_next(i)" ...textPadding}
|
66
|
+
hblock
|
67
|
+
[for="tile in bottom"]
|
68
|
+
rect { ...bg :key="bottom_key(tile)" }
|
69
|
+
text { :key="tile" :content="tile" ...textPadding }
|
70
|
+
EOF
|
71
|
+
|
72
|
+
uses(
|
73
|
+
hblock: Hokusai::Blocks::Hblock,
|
74
|
+
vblock: Hokusai::Blocks::Vblock,
|
75
|
+
text: Hokusai::Blocks::Text,
|
76
|
+
empty: Hokusai::Blocks::Empty,
|
77
|
+
rect: Hokusai::Blocks::Rect
|
78
|
+
)
|
79
|
+
|
80
|
+
attr_reader :tiles
|
81
|
+
|
82
|
+
def get(i)
|
83
|
+
tiles[i[0]].title
|
84
|
+
end
|
85
|
+
|
86
|
+
def get_next(i)
|
87
|
+
tiles[i[1]].title
|
88
|
+
end
|
89
|
+
|
90
|
+
def middle
|
91
|
+
(5..10).each_slice(2).to_a
|
92
|
+
end
|
93
|
+
|
94
|
+
def bottom_key(t)
|
95
|
+
"bottom-#{t}"
|
96
|
+
end
|
97
|
+
|
98
|
+
def top_key(t)
|
99
|
+
"top-#{t}"
|
100
|
+
end
|
101
|
+
|
102
|
+
def top
|
103
|
+
tiles.take(5).map(&:title)
|
104
|
+
end
|
105
|
+
|
106
|
+
def bottom
|
107
|
+
a = tiles[-5, 5].map(&:title)
|
108
|
+
a
|
109
|
+
end
|
110
|
+
|
111
|
+
def after_updated
|
112
|
+
@tiles = TILES.map do |(label, cost)|
|
113
|
+
os = OpenStruct.new
|
114
|
+
os.title = label
|
115
|
+
os.cost = cost
|
116
|
+
os
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def initialize(**args)
|
121
|
+
@tiles = TILES.map do |(label, cost)|
|
122
|
+
os = OpenStruct.new
|
123
|
+
os.title = label
|
124
|
+
os.cost = cost
|
125
|
+
os
|
126
|
+
end
|
127
|
+
|
128
|
+
super
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
|
133
|
+
Hokusai::Backends::RaylibBackend.run(Game) do |config|
|
134
|
+
config.width = 500
|
135
|
+
config.height = 500
|
136
|
+
|
137
|
+
config.after_load do
|
138
|
+
font = Hokusai::Backends::RaylibBackend::Font.from_ext("#{__dir__}/assets/OpenSans-Regular.ttf", 160)
|
139
|
+
Hokusai.fonts.register "opensans", font
|
140
|
+
Hokusai.fonts.activate "opensans"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
@@ -0,0 +1,233 @@
|
|
1
|
+
require_relative "../src/hokusai"
|
2
|
+
require_relative "../src/hokusai/backends/raylib"
|
3
|
+
|
4
|
+
class DropdownItem < Hokusai::Block
|
5
|
+
style <<~EOF
|
6
|
+
[style]
|
7
|
+
textStyle {
|
8
|
+
padding: padding(5.0, 5.0, 5.0, 5.0);
|
9
|
+
size: 23;
|
10
|
+
color: rgb(255,255,255);
|
11
|
+
cursor: "pointer";
|
12
|
+
}
|
13
|
+
EOF
|
14
|
+
|
15
|
+
template <<~EOF
|
16
|
+
[template]
|
17
|
+
text#second {
|
18
|
+
:content="content"
|
19
|
+
...textStyle
|
20
|
+
@click="emit_option"
|
21
|
+
@height_updated="udpate_height"
|
22
|
+
}
|
23
|
+
EOF
|
24
|
+
|
25
|
+
uses(text: Hokusai::Blocks::Text)
|
26
|
+
|
27
|
+
computed! :content
|
28
|
+
computed! :index
|
29
|
+
|
30
|
+
def udpate_height(height)
|
31
|
+
node.portal.meta.set_prop(:height, height)
|
32
|
+
emit("height", height, index)
|
33
|
+
end
|
34
|
+
|
35
|
+
def emit_option(e)
|
36
|
+
emit("option", content)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class Dropdown < Hokusai::Block
|
41
|
+
style <<-EOF
|
42
|
+
[style]
|
43
|
+
panelStyle {
|
44
|
+
z: 1;
|
45
|
+
width: 200;
|
46
|
+
height: 300;
|
47
|
+
background: rgb(67, 64, 92);
|
48
|
+
}
|
49
|
+
|
50
|
+
labelStyle {
|
51
|
+
size: 22;
|
52
|
+
content: "Please choose your fruit?";
|
53
|
+
}
|
54
|
+
EOF
|
55
|
+
|
56
|
+
template <<~EOF
|
57
|
+
[template]
|
58
|
+
vblock { @click="toggle_dropdown" height="70"}
|
59
|
+
label { ...labelStyle }
|
60
|
+
label { :content="selected" size="25" }
|
61
|
+
[if="toggled"]
|
62
|
+
panel#first { ...panelStyle @click="stop"}
|
63
|
+
[for="option in options"]
|
64
|
+
item {
|
65
|
+
:height="get_height(index)"
|
66
|
+
:content="option"
|
67
|
+
:key="index"
|
68
|
+
:index="index"
|
69
|
+
@option="select"
|
70
|
+
@height="update_height"
|
71
|
+
}
|
72
|
+
EOF
|
73
|
+
|
74
|
+
uses(label: Hokusai::Blocks::Label, vblock: Hokusai::Blocks::Vblock, item: DropdownItem, panel: Hokusai::Blocks::Panel)
|
75
|
+
|
76
|
+
attr_reader :toggled
|
77
|
+
|
78
|
+
computed! :options
|
79
|
+
|
80
|
+
def list_height
|
81
|
+
@heights ||= {}
|
82
|
+
@heights.values.reduce(&:+) || 0.0
|
83
|
+
end
|
84
|
+
|
85
|
+
def get_height(index)
|
86
|
+
@heights ||= {}
|
87
|
+
@heights[index] || 0.0
|
88
|
+
end
|
89
|
+
|
90
|
+
def update_height(height, index)
|
91
|
+
@heights ||= {}
|
92
|
+
@heights[index] = height
|
93
|
+
end
|
94
|
+
|
95
|
+
def stop(e)
|
96
|
+
end
|
97
|
+
|
98
|
+
def toggle_dropdown(_)
|
99
|
+
@toggled = !@toggled
|
100
|
+
end
|
101
|
+
|
102
|
+
def select(option)
|
103
|
+
@selected = option
|
104
|
+
@toggled = false
|
105
|
+
end
|
106
|
+
|
107
|
+
# def options
|
108
|
+
# %w[apple pear mango pineapple orange pear bananana kiwi grapes melon lemon lime]
|
109
|
+
# end
|
110
|
+
|
111
|
+
def selected
|
112
|
+
@selected || options.first
|
113
|
+
end
|
114
|
+
|
115
|
+
def initialize(**args)
|
116
|
+
@toggled = true
|
117
|
+
|
118
|
+
super
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
class Modal < Hokusai::Block
|
123
|
+
template <<~EOF
|
124
|
+
[template]
|
125
|
+
hblock#top
|
126
|
+
empty
|
127
|
+
empty#topempty
|
128
|
+
text { @click="emit_close" content="X" size="40" color="255,255,255}
|
129
|
+
hblock#middle { height="300"}
|
130
|
+
slot
|
131
|
+
hblock#last
|
132
|
+
empty#lastempty
|
133
|
+
EOF
|
134
|
+
|
135
|
+
uses(vblock: Hokusai::Blocks::Vblock, empty: Hokusai::Blocks::Empty, hblock: Hokusai::Blocks::Hblock, text: Hokusai::Blocks::Label)
|
136
|
+
|
137
|
+
computed :color, default: [0, 0, 0, 200], convert: Hokusai::Color
|
138
|
+
|
139
|
+
def emit_close(event)
|
140
|
+
emit("close")
|
141
|
+
|
142
|
+
event.stop
|
143
|
+
end
|
144
|
+
|
145
|
+
def render(canvas)
|
146
|
+
draw do
|
147
|
+
rect(canvas.x, canvas.y, canvas.width, canvas.height) do |command|
|
148
|
+
command.color = color
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
yield canvas
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
class Thing < Hokusai::Block
|
157
|
+
style <<~EOF
|
158
|
+
[style]
|
159
|
+
textStyle {
|
160
|
+
size: 30;
|
161
|
+
color: rgb(0, 0, 0);
|
162
|
+
content: "Hello modal!";
|
163
|
+
}
|
164
|
+
|
165
|
+
otherText {
|
166
|
+
size: 25;
|
167
|
+
content: "Hello World";
|
168
|
+
}
|
169
|
+
contentStyle {
|
170
|
+
height: 300.0;
|
171
|
+
width: 300.0;
|
172
|
+
background: rgb(255, 255, 255, 255);
|
173
|
+
}
|
174
|
+
backgroundStyle {
|
175
|
+
background: rgb(43, 151, 117);
|
176
|
+
}
|
177
|
+
modalStyle {
|
178
|
+
z: 1;
|
179
|
+
position: "absolute";
|
180
|
+
}
|
181
|
+
EOF
|
182
|
+
|
183
|
+
template <<~EOF
|
184
|
+
[template]
|
185
|
+
vblock#topnot
|
186
|
+
hblock#not{ ...backgroundStyle }
|
187
|
+
text#not { ...otherText @click="open_modal" }
|
188
|
+
dropdown { :options="outer_options" }
|
189
|
+
hblock { background="233,0,0" }
|
190
|
+
text#second { content="Second" }
|
191
|
+
modal {
|
192
|
+
@close="close"
|
193
|
+
:active="modal_open"
|
194
|
+
}
|
195
|
+
vblock { ...contentStyle }
|
196
|
+
dropdown { :options="inner_options" }
|
197
|
+
color_picker
|
198
|
+
text#last { size="30" content="last"}
|
199
|
+
EOF
|
200
|
+
|
201
|
+
attr_reader :modal_open
|
202
|
+
|
203
|
+
def log(event)
|
204
|
+
pp ["clicked!"]
|
205
|
+
end
|
206
|
+
|
207
|
+
def outer_options
|
208
|
+
%w[sam betty fred candace justin lucy annabelle nick janessa sean]
|
209
|
+
end
|
210
|
+
|
211
|
+
def inner_options
|
212
|
+
%w[apple pear mango pineapple orange pear bananana kiwi grapes melon lemon lime]
|
213
|
+
end
|
214
|
+
|
215
|
+
def open_modal(event)
|
216
|
+
@modal_open = true
|
217
|
+
end
|
218
|
+
|
219
|
+
def close
|
220
|
+
@modal_open = false
|
221
|
+
end
|
222
|
+
|
223
|
+
uses(
|
224
|
+
color_picker: Hokusai::Blocks::ColorPicker, modal: Hokusai::Blocks::Modal, dropdown: Hokusai::Blocks::Dropdown, vblock: Hokusai::Blocks::Vblock, text: Hokusai::Blocks::Text,empty: Hokusai::Blocks::Empty, hblock: Hokusai::Blocks::Hblock)
|
225
|
+
end
|
226
|
+
|
227
|
+
Hokusai::Backends::RaylibBackend.run(Thing) do |config|
|
228
|
+
config.after_load do
|
229
|
+
font = Hokusai::Backends::RaylibBackend::Font.from("#{__dir__}/assets/Inter-Regular.ttf")
|
230
|
+
Hokusai.fonts.register "inter", font
|
231
|
+
Hokusai.fonts.activate "inter"
|
232
|
+
end
|
233
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require_relative "../src/hokusai"
|
2
|
+
require_relative "../src/hokusai/backends/raylib"
|
3
|
+
|
4
|
+
class Child < Hokusai::Block
|
5
|
+
template <<~EOF
|
6
|
+
[template]
|
7
|
+
text { :content="get_content" @selected="handle_selected" @height_updated="update_height"}
|
8
|
+
EOF
|
9
|
+
|
10
|
+
uses(
|
11
|
+
vblock: Hokusai::Blocks::Vblock,
|
12
|
+
text: Hokusai::Blocks::Text,
|
13
|
+
input: Hokusai::Blocks::Input
|
14
|
+
)
|
15
|
+
|
16
|
+
def update_height(height)
|
17
|
+
node.meta.set_prop(:height, height)
|
18
|
+
end
|
19
|
+
|
20
|
+
def handle_selected(start, stop)
|
21
|
+
pp [start, stop]
|
22
|
+
end
|
23
|
+
|
24
|
+
def get_content
|
25
|
+
@file ||= File.read(__FILE__)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class ProviderExample < Hokusai::Block
|
30
|
+
template <<~EOF
|
31
|
+
[template]
|
32
|
+
selectable
|
33
|
+
panel
|
34
|
+
text { :content="get_content" }
|
35
|
+
EOF
|
36
|
+
|
37
|
+
uses(
|
38
|
+
vblock: Hokusai::Blocks::Vblock,
|
39
|
+
selectable: Hokusai::Blocks::Selectable,
|
40
|
+
panel: Hokusai::Blocks::Panel,
|
41
|
+
child: Child,
|
42
|
+
text: Hokusai::Blocks::Text
|
43
|
+
)
|
44
|
+
|
45
|
+
def get_content
|
46
|
+
@file ||= File.read(__FILE__)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
Hokusai::Backends::RaylibBackend.run(ProviderExample) do |config|
|
52
|
+
config.width = 500
|
53
|
+
config.height = 500
|
54
|
+
config.title = "Provider application"
|
55
|
+
end
|
56
|
+
|
@@ -0,0 +1,145 @@
|
|
1
|
+
require_relative "../../src/hokusai"
|
2
|
+
require_relative "../../src/hokusai/backends/raylib"
|
3
|
+
require "date"
|
4
|
+
|
5
|
+
class ShaderWrapper < Hokusai::Block
|
6
|
+
template <<~EOF
|
7
|
+
[template]
|
8
|
+
shader_begin {
|
9
|
+
@mousemove="update_value"
|
10
|
+
:vertex_shader="vertex_shader"
|
11
|
+
:uniforms="uniforms"
|
12
|
+
}
|
13
|
+
slot
|
14
|
+
shader_end
|
15
|
+
EOF
|
16
|
+
|
17
|
+
uses(
|
18
|
+
shader_begin: Hokusai::Blocks::ShaderBegin,
|
19
|
+
shader_end: Hokusai::Blocks::ShaderEnd,
|
20
|
+
texture: Hokusai::Blocks::Texture
|
21
|
+
)
|
22
|
+
|
23
|
+
def update_value(event)
|
24
|
+
@pos = (event.pos.x + event.pos.y) / 1000
|
25
|
+
end
|
26
|
+
|
27
|
+
def uniforms
|
28
|
+
return unless @start && @pos
|
29
|
+
done = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
30
|
+
elapsed = (done - @start).round(3)
|
31
|
+
|
32
|
+
{
|
33
|
+
millis: [elapsed / 2, Hokusai::SHADER_UNIFORM_FLOAT]
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
def on_mounted
|
38
|
+
@start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
39
|
+
end
|
40
|
+
|
41
|
+
def fragment_shader
|
42
|
+
<<-EOF
|
43
|
+
#version 330
|
44
|
+
in vec4 fragColor;
|
45
|
+
out vec4 finalColor;
|
46
|
+
|
47
|
+
void main() {
|
48
|
+
finalColor = fragColor; //vec4(0., 1., 0., 1.);
|
49
|
+
}
|
50
|
+
EOF
|
51
|
+
end
|
52
|
+
|
53
|
+
def vertex_shader
|
54
|
+
<<-EOF
|
55
|
+
#version 330
|
56
|
+
in vec3 vertexPosition;
|
57
|
+
in vec2 vertexTexCoord;
|
58
|
+
in vec4 vertexColor;
|
59
|
+
|
60
|
+
uniform mat4 mvp;
|
61
|
+
uniform float millis;
|
62
|
+
|
63
|
+
out vec2 fragTexCoord;
|
64
|
+
out vec4 fragColor;
|
65
|
+
|
66
|
+
void main() {
|
67
|
+
fragTexCoord = vertexTexCoord;
|
68
|
+
fragColor = vertexColor;
|
69
|
+
vec4 position = mvp * vec4(vertexPosition, 1.);
|
70
|
+
|
71
|
+
position.x += sin(millis + position.y * 8) / 8;
|
72
|
+
gl_Position = position;
|
73
|
+
}
|
74
|
+
EOF
|
75
|
+
end
|
76
|
+
|
77
|
+
def render(canvas)
|
78
|
+
canvas.vertical = true
|
79
|
+
@x = canvas.x
|
80
|
+
|
81
|
+
yield canvas
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
class ShaderTest < Hokusai::Block
|
86
|
+
style <<~EOF
|
87
|
+
[style]
|
88
|
+
circleStyle {
|
89
|
+
color: rgb(47, 112, 106);
|
90
|
+
}
|
91
|
+
|
92
|
+
textStyle {
|
93
|
+
content: "Whoa, coool dude.";
|
94
|
+
size: 15.0;
|
95
|
+
}
|
96
|
+
EOF
|
97
|
+
|
98
|
+
template <<~EOF
|
99
|
+
[template]
|
100
|
+
hblock
|
101
|
+
empty
|
102
|
+
hblock
|
103
|
+
hblock
|
104
|
+
empty
|
105
|
+
hblock
|
106
|
+
wrapper
|
107
|
+
image { :source="addy_png" :width="500" :height="400" }
|
108
|
+
text { ...textStyle }
|
109
|
+
circle {
|
110
|
+
:radius="50.0"
|
111
|
+
...circleStyle
|
112
|
+
}
|
113
|
+
hblock
|
114
|
+
empty
|
115
|
+
hblock
|
116
|
+
empty
|
117
|
+
|
118
|
+
EOF
|
119
|
+
|
120
|
+
uses(
|
121
|
+
wrapper: ShaderWrapper,
|
122
|
+
picker: Hokusai::Blocks::ColorPicker,
|
123
|
+
image: Hokusai::Blocks::Image,
|
124
|
+
text: Hokusai::Blocks::Text,
|
125
|
+
circle: Hokusai::Blocks::Circle,
|
126
|
+
vblock: Hokusai::Blocks::Vblock,
|
127
|
+
hblock: Hokusai::Blocks::Hblock,
|
128
|
+
empty: Hokusai::Blocks::Empty
|
129
|
+
)
|
130
|
+
|
131
|
+
def addy_png
|
132
|
+
"#{__dir__}/../assets/addy.png"
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
|
137
|
+
Hokusai::Backends::RaylibBackend.run(ShaderTest) do |config|
|
138
|
+
config.width = 900
|
139
|
+
config.height = 800
|
140
|
+
config.after_load do
|
141
|
+
font = Hokusai::Backends::RaylibBackend::Font.from("#{__dir__}/assets/Inter-Regular.ttf")
|
142
|
+
Hokusai.fonts.register "inter", font
|
143
|
+
Hokusai.fonts.activate "inter"
|
144
|
+
end
|
145
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require_relative "../src/hokusai"
|
2
|
+
require_relative "../src/hokusai/backends/raylib"
|
3
|
+
|
4
|
+
class ShaderExample < Hokusai::Block
|
5
|
+
style <<~EOF
|
6
|
+
[style]
|
7
|
+
textureThing {
|
8
|
+
width: 500;
|
9
|
+
height: 900;
|
10
|
+
scale: 100.0;
|
11
|
+
}
|
12
|
+
EOF
|
13
|
+
|
14
|
+
template <<~EOF
|
15
|
+
[template]
|
16
|
+
colorpicker
|
17
|
+
shader_begin {
|
18
|
+
@mousemove="change_rotation"
|
19
|
+
@click="switch_color"
|
20
|
+
:fragment_shader="fragment_shader"
|
21
|
+
:uniforms="uniforms"
|
22
|
+
}
|
23
|
+
texture {
|
24
|
+
...textureThing
|
25
|
+
:rotation="rotate"
|
26
|
+
}
|
27
|
+
shader_end
|
28
|
+
EOF
|
29
|
+
|
30
|
+
uses(
|
31
|
+
colorpicker: Hokusai::Blocks::ColorPicker,
|
32
|
+
shader_begin: Hokusai::Blocks::ShaderBegin,
|
33
|
+
shader_end: Hokusai::Blocks::ShaderEnd,
|
34
|
+
texture: Hokusai::Blocks::Texture,
|
35
|
+
rect: Hokusai::Blocks::Rect,
|
36
|
+
vblock: Hokusai::Blocks::Vblock
|
37
|
+
)
|
38
|
+
|
39
|
+
attr_reader :rotate
|
40
|
+
|
41
|
+
def initialize(**args)
|
42
|
+
@color = [1.0, 0.0, 0.0, 1.0]
|
43
|
+
@position = [0.0, 100.0, 0.0, 1.0]
|
44
|
+
|
45
|
+
super
|
46
|
+
end
|
47
|
+
|
48
|
+
def change_rotation(event)
|
49
|
+
@rotate = event.delta[:y]
|
50
|
+
end
|
51
|
+
|
52
|
+
def switch_color(event)
|
53
|
+
@color = [
|
54
|
+
[0.3, 0.3, 0.3, 1.0],
|
55
|
+
[0.0, 1.0, 0.0, 1.0],
|
56
|
+
[0.0, 0.0, 1.0, 1.0]
|
57
|
+
].sample
|
58
|
+
end
|
59
|
+
|
60
|
+
# def move_mouse(event)
|
61
|
+
# @position[0] = [0.0, 0.3, 0.6, 0.9, 1.0].sample
|
62
|
+
# end
|
63
|
+
|
64
|
+
def vertex_shader
|
65
|
+
<<-EOF
|
66
|
+
#version 330 core
|
67
|
+
|
68
|
+
uniform vec4 position;
|
69
|
+
|
70
|
+
void main() {
|
71
|
+
gl_Position = position;
|
72
|
+
}
|
73
|
+
EOF
|
74
|
+
end
|
75
|
+
|
76
|
+
def fragment_shader
|
77
|
+
<<-EOF
|
78
|
+
#version 330 core
|
79
|
+
|
80
|
+
in vec4 position;
|
81
|
+
out vec4 FragColor;
|
82
|
+
|
83
|
+
uniform vec4 color;
|
84
|
+
|
85
|
+
void main() {
|
86
|
+
FragColor = color;
|
87
|
+
}
|
88
|
+
EOF
|
89
|
+
end
|
90
|
+
|
91
|
+
def uniforms
|
92
|
+
[
|
93
|
+
["color", @color, Hokusai::SHADER_UNIFORM_VEC4]
|
94
|
+
]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
Hokusai::Backends::RaylibBackend.run(ShaderExample) do |config|
|
99
|
+
config.background = Raylib::BLUE
|
100
|
+
end
|