reight 0.1.2

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 (58) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/release-gem.yml +62 -0
  3. data/.github/workflows/tag.yml +35 -0
  4. data/.github/workflows/test.yml +37 -0
  5. data/.github/workflows/utils.rb +56 -0
  6. data/.gitignore +1 -0
  7. data/ChangeLog.md +23 -0
  8. data/Gemfile +6 -0
  9. data/LICENSE +21 -0
  10. data/README.md +62 -0
  11. data/Rakefile +30 -0
  12. data/VERSION +1 -0
  13. data/bin/r8 +35 -0
  14. data/lib/reight/all.rb +59 -0
  15. data/lib/reight/app/map/brush.rb +27 -0
  16. data/lib/reight/app/map/brush_base.rb +54 -0
  17. data/lib/reight/app/map/canvas.rb +150 -0
  18. data/lib/reight/app/map/chips.rb +84 -0
  19. data/lib/reight/app/map/editor.rb +117 -0
  20. data/lib/reight/app/map/line.rb +35 -0
  21. data/lib/reight/app/map/rect.rb +29 -0
  22. data/lib/reight/app/map/tool.rb +32 -0
  23. data/lib/reight/app/map.rb +8 -0
  24. data/lib/reight/app/music/editor.rb +25 -0
  25. data/lib/reight/app/music.rb +1 -0
  26. data/lib/reight/app/navigator.rb +172 -0
  27. data/lib/reight/app/runner.rb +275 -0
  28. data/lib/reight/app/sound/editor.rb +25 -0
  29. data/lib/reight/app/sound.rb +1 -0
  30. data/lib/reight/app/sprite/brush.rb +43 -0
  31. data/lib/reight/app/sprite/canvas.rb +254 -0
  32. data/lib/reight/app/sprite/chips.rb +92 -0
  33. data/lib/reight/app/sprite/color.rb +30 -0
  34. data/lib/reight/app/sprite/editor.rb +272 -0
  35. data/lib/reight/app/sprite/fill.rb +45 -0
  36. data/lib/reight/app/sprite/line.rb +37 -0
  37. data/lib/reight/app/sprite/select.rb +58 -0
  38. data/lib/reight/app/sprite/shape.rb +43 -0
  39. data/lib/reight/app/sprite/tool.rb +27 -0
  40. data/lib/reight/app/sprite.rb +10 -0
  41. data/lib/reight/app.rb +123 -0
  42. data/lib/reight/button.rb +93 -0
  43. data/lib/reight/chip.rb +150 -0
  44. data/lib/reight/extension.rb +24 -0
  45. data/lib/reight/helpers.rb +69 -0
  46. data/lib/reight/history.rb +135 -0
  47. data/lib/reight/map.rb +264 -0
  48. data/lib/reight/project.rb +115 -0
  49. data/lib/reight/reight.rb +83 -0
  50. data/lib/reight.rb +18 -0
  51. data/reight.gemspec +40 -0
  52. data/res/icons.png +0 -0
  53. data/test/helper.rb +15 -0
  54. data/test/test_chip.rb +108 -0
  55. data/test/test_chip_list.rb +68 -0
  56. data/test/test_map.rb +232 -0
  57. data/test/test_map_chunk.rb +226 -0
  58. metadata +244 -0
@@ -0,0 +1,272 @@
1
+ using Reight
2
+
3
+
4
+ class Reight::SpriteEditor < Reight::App
5
+
6
+ def canvas()
7
+ @canvas ||= Canvas.new(
8
+ self,
9
+ project.chips_image,
10
+ project.chips_image_path
11
+ ).tap do |canvas|
12
+ canvas. tool_changed {update_active_tool}
13
+ canvas.color_changed {update_active_color}
14
+ end
15
+ end
16
+
17
+ def activated()
18
+ super
19
+ history.disable do
20
+ colors[7].click
21
+ tools[1].click
22
+ chip_sizes[0].click
23
+ brush_sizes[0].click
24
+ end
25
+ end
26
+
27
+ def draw()
28
+ background 200
29
+ sprite(*sprites)
30
+ super
31
+ end
32
+
33
+ def key_pressed()
34
+ super
35
+ shift, ctrl, cmd = %i[shift control command].map {pressing? _1}
36
+ ch = chips
37
+ case key_code
38
+ when LEFT then ch.set_frame ch.x - ch.size, ch.y, ch.size, ch.size
39
+ when RIGHT then ch.set_frame ch.x + ch.size, ch.y, ch.size, ch.size
40
+ when UP then ch.set_frame ch.x, ch.y - ch.size, ch.size, ch.size
41
+ when DOWN then ch.set_frame ch.x, ch.y + ch.size, ch.size, ch.size
42
+ when :c then copy if ctrl || cmd
43
+ when :x then cut if ctrl || cmd
44
+ when :v then paste if ctrl || cmd
45
+ when :z then shift ? self.redo : undo if ctrl || cmd
46
+ when :s then select.click
47
+ when :b then brush.click
48
+ when :l then line.click
49
+ when :f then fill.click
50
+ when :r then (shift ? fill_rect : stroke_rect ).click
51
+ when :e then (shift ? fill_ellipse : stroke_ellipse).click
52
+ end
53
+ end
54
+
55
+ def window_resized()
56
+ super
57
+ [colors, tools, chip_sizes, brush_sizes].flatten.map(&:sprite)
58
+ .each {|sp| sp.w = sp.h = BUTTON_SIZE}
59
+
60
+ chips.sprite.tap do |sp|
61
+ sp.x = SPACE
62
+ sp.y = NAVIGATOR_HEIGHT + SPACE
63
+ sp.w = CHIPS_WIDTH
64
+ sp.bottom = height - SPACE
65
+ end
66
+ colors.map {_1.sprite}.each.with_index do |sp, index|
67
+ sp.x = chips.sprite.right + SPACE + sp.w * (index % 4)
68
+ sp.y = height - (SPACE + sp.h * (4 - index / 4))
69
+ end
70
+ tools.map {_1.sprite}.each.with_index do |sp, index|
71
+ line = index < 3 ? 0 : 1
72
+ index -= 3 if line == 1
73
+ sp.x = colors.last.sprite.right + SPACE + (sp.w + 1) * index
74
+ sp.y = colors.first.sprite.y + (sp.h + 1) * line
75
+ end
76
+ canvas.sprite.tap do |sp|
77
+ sp.x = chips.sprite.right + SPACE
78
+ sp.y = chips.sprite.y
79
+ sp.bottom = colors.first.sprite.top - SPACE
80
+ sp.w = sp.h
81
+ end
82
+ chip_sizes.map {_1.sprite}.each.with_index do |sp, index|
83
+ sp.x = canvas.sprite.right + SPACE + (sp.w + 1) * index
84
+ sp.y = canvas.sprite.y
85
+ end
86
+ brush_sizes.map {_1.sprite}.each.with_index do |sp, index|
87
+ sp.x = chip_sizes.first.sprite.x + (sp.w + 1) * index
88
+ sp.y = chip_sizes.last.sprite.bottom + SPACE
89
+ end
90
+ shapes.map {_1.sprite}.each.with_index do |sp, index|
91
+ sp.w = 30
92
+ sp.h = BUTTON_SIZE
93
+ sp.x = brush_sizes.first.sprite.x + (sp.w + 1) * index
94
+ sp.y = brush_sizes.last.sprite.bottom + SPACE
95
+ end
96
+ types.map {_1.sprite}.each.with_index do |sp, index|
97
+ sp.w = 50
98
+ sp.h = BUTTON_SIZE
99
+ sp.x = shapes.first.sprite.x + (sp.w + 1) * index
100
+ sp.y = shapes.last.sprite.bottom + SPACE
101
+ end
102
+ end
103
+
104
+ def undo(flash: true)
105
+ history.undo do |action|
106
+ case action
107
+ in [:frame, [x, y, w, h], _] then chips.set_frame x, y, w, h
108
+ in [:capture, before, _, x, y] then canvas.apply_frame before, x, y
109
+ in [ :select, sel, _] then sel ? canvas.select(*sel) : canvas.deselect
110
+ in [:deselect, sel] then canvas.select(*sel)
111
+ end
112
+ self.flash 'Undo!' if flash
113
+ end
114
+ end
115
+
116
+ def redo(flash: true)
117
+ history.redo do |action|
118
+ case action
119
+ in [:frame, _, [x, y, w, h]] then chips.set_frame x, y, w, h
120
+ in [:capture, _, after, x, y] then canvas.apply_frame after, x, y
121
+ in [ :select, _, sel] then canvas.select(*sel)
122
+ in [:deselect, _] then canvas.deselect
123
+ end
124
+ self.flash 'Redo!' if flash
125
+ end
126
+ end
127
+
128
+ def cut(flash: true)
129
+ copy flash: false
130
+ image, x, y = @copy || return
131
+ canvas.begin_editing do
132
+ clear_canvas x, y, image.width, image.height
133
+ end
134
+ self.flash 'Cut!' if flash
135
+ end
136
+
137
+ def copy(flash: true)
138
+ sel = canvas.selection || canvas.frame
139
+ image = canvas.capture_frame(sel) || return
140
+ x, y, = sel
141
+ @copy = [image, x - canvas.x, y - canvas.y]
142
+ self.flash 'Copy!' if flash
143
+ end
144
+
145
+ def paste(flash: true)
146
+ image, x, y = @copy || return
147
+ w, h = image.width, image.height
148
+ history.group do
149
+ canvas.deselect
150
+ canvas.begin_editing do
151
+ canvas.paint do |g|
152
+ g.copy image, 0, 0, w, h, x, y, w, h
153
+ end
154
+ end
155
+ canvas.select canvas.x + x, canvas.y + y, w, h
156
+ end
157
+ self.flash 'Paste!' if flash
158
+ end
159
+
160
+ def can_cut? = true
161
+ def can_copy? = true
162
+ def can_paste? = @copy
163
+
164
+ def clear_canvas(x, y, w, h)
165
+ canvas.clear [x, y, w, h], color: colors.first.color
166
+ end
167
+
168
+ private
169
+
170
+ def sprites()
171
+ [canvas, chips, *chip_sizes, *colors, *tools, *brush_sizes, *shapes, *types]
172
+ .map(&:sprite) + super
173
+ end
174
+
175
+ def chips()
176
+ @chips ||= Chips.new self, project.chips_image do |x, y, w, h|
177
+ canvas.set_frame x, y, w, h
178
+ chip_changed x, y, w, h
179
+ end
180
+ end
181
+
182
+ def chip_sizes()
183
+ @chip_sizes ||= group(*[8, 16, 32].map {|size|
184
+ Reight::Button.new name: "#{size}x#{size}", label: size do
185
+ chips.set_frame chips.x, chips.y, size, size
186
+ end
187
+ })
188
+ end
189
+
190
+ def tools()
191
+ @tools ||= group(
192
+ select,
193
+ brush,
194
+ fill,
195
+ stroke_line,
196
+ stroke_rect,
197
+ fill_rect,
198
+ stroke_ellipse,
199
+ fill_ellipse
200
+ )
201
+ end
202
+
203
+ def select = @select ||= Select.new(self) {canvas.tool = _1}
204
+ def brush = @brush ||= Brush.new(self) {canvas.tool = _1}
205
+ def fill = @fill ||= Fill.new(self) {canvas.tool = _1}
206
+ def stroke_line = @stroke_line ||= Line.new(self) {canvas.tool = _1}
207
+ def stroke_rect = @stroke_rect ||= Shape.new(self, :rect, false) {canvas.tool = _1}
208
+ def fill_rect = @fill_rect ||= Shape.new(self, :rect, true) {canvas.tool = _1}
209
+ def stroke_ellipse = @stroke_ellipse ||= Shape.new(self, :ellipse, false) {canvas.tool = _1}
210
+ def fill_ellipse = @fill_ellipse ||= Shape.new(self, :ellipse, true) {canvas.tool = _1}
211
+
212
+ def brush_sizes()
213
+ @brush_sizes ||= group(*[1, 2, 3, 5, 10].map {|size|
214
+ Reight::Button.new name: "Button Size #{size}", label: size do
215
+ brush.size = size
216
+ flash "Brush Size #{size}"
217
+ end
218
+ })
219
+ end
220
+
221
+ def colors()
222
+ @colors ||= project.palette_colors.map {|color|
223
+ rgb = self.color(color)
224
+ .then {[red(_1), green(_1), blue(_1), alpha(_1)]}.map &:to_i
225
+ Color.new(rgb) {canvas.color = rgb}
226
+ }
227
+ end
228
+
229
+ def shapes()
230
+ @shapes ||= group(
231
+ Reight::Button.new(name: 'No Shape', label: 'None') {
232
+ project.chips.at(*canvas.frame).shape = nil
233
+ },
234
+ Reight::Button.new(name: 'Rect Shape', label: 'Rect') {
235
+ project.chips.at(*canvas.frame).shape = :rect
236
+ },
237
+ Reight::Button.new(name: 'Circle Shape', label: 'Circle') {
238
+ project.chips.at(*canvas.frame).shape = :circle
239
+ },
240
+ )
241
+ end
242
+
243
+ def types()
244
+ @types ||= group(
245
+ Reight::Button.new(name: 'Object', label: 'Object') {
246
+ project.chips.at(*canvas.frame).sensor = false
247
+ },
248
+ Reight::Button.new(name: 'Sensor', label: 'Sensor') {
249
+ project.chips.at(*canvas.frame).sensor = true
250
+ },
251
+ )
252
+ end
253
+
254
+ def chip_changed(x, y, w, h)
255
+ chip = project.chips.at x, y, w, h
256
+ shapes[[nil, :rect, :circle].index(chip.shape)].click
257
+ types[chip.sensor? ? 1 : 0].click
258
+ end
259
+
260
+ def update_active_tool()
261
+ tools.each do |tool|
262
+ tool.active = tool == canvas.tool
263
+ end
264
+ end
265
+
266
+ def update_active_color()
267
+ colors.each do |button|
268
+ button.active = button.color == canvas.color
269
+ end
270
+ end
271
+
272
+ end# SpriteEditor
@@ -0,0 +1,45 @@
1
+ using Reight
2
+
3
+
4
+ class Reight::SpriteEditor::Fill < Reight::SpriteEditor::Tool
5
+
6
+ def initialize(app, &block)
7
+ super app, icon: app.icon(2, 2, 8), &block
8
+ set_help left: 'Fill', right: 'Pick Color'
9
+ end
10
+
11
+ def canvas_pressed(x, y, button)
12
+ return unless button == LEFT
13
+ x, y = [x, y].map &:to_i
14
+ fx, fy, fw, = canvas.frame
15
+ sx, sy, sw, sh = canvas.selection || canvas.frame
16
+ sx -= fx
17
+ sy -= fy
18
+ return unless (sx...(sx + sw)).include?(x) && (sy...(sy + sh)).include?(y)
19
+ canvas.begin_editing
20
+ count = 0
21
+ canvas.update_pixels do |pixels|
22
+ from = pixels[y * fw + x]
23
+ to = color(*canvas.color)
24
+ rest = [[x, y]]
25
+ until rest.empty?
26
+ xx, yy = rest.shift
27
+ next if pixels[yy * fw + xx] == to
28
+ pixels[yy * fw + xx] = to
29
+ count += 1
30
+ _x, x_ = xx - 1, xx + 1
31
+ _y, y_ = yy - 1, yy + 1
32
+ rest << [_x, yy] if _x >= sx && pixels[yy * fw + _x] == from
33
+ rest << [x_, yy] if x_ < sx + sw && pixels[yy * fw + x_] == from
34
+ rest << [xx, _y] if _y >= sy && pixels[_y * fw + xx] == from
35
+ rest << [xx, y_] if y_ < sy + sh && pixels[y_ * fw + xx] == from
36
+ end
37
+ end
38
+ canvas.end_editing if count > 0
39
+ end
40
+
41
+ def canvas_clicked(x, y, button)
42
+ pick_color x, y if button == RIGHT
43
+ end
44
+
45
+ end# Fill
@@ -0,0 +1,37 @@
1
+ using Reight
2
+
3
+
4
+ class Reight::SpriteEditor::Line < Reight::SpriteEditor::Tool
5
+
6
+ def initialize(app, &block)
7
+ super app, icon: app.icon(3, 2, 8), &block
8
+ set_help left: name, right: 'Pick Color'
9
+ end
10
+
11
+ def draw_line(x, y)
12
+ canvas.begin_editing do
13
+ canvas.paint do |g|
14
+ g.stroke(*canvas.color)
15
+ g.stroke_weight 0
16
+ g.line @x, @y, x, y
17
+ end
18
+ end
19
+ end
20
+
21
+ def canvas_pressed(x, y, button)
22
+ return unless button == LEFT
23
+ @x, @y = x, y
24
+ draw_line x, y
25
+ end
26
+
27
+ def canvas_dragged(x, y, button)
28
+ return unless button == LEFT
29
+ app.undo flash: false
30
+ draw_line x, y
31
+ end
32
+
33
+ def canvas_clicked(x, y, button)
34
+ pick_color x, y if button == RIGHT
35
+ end
36
+
37
+ end# Line
@@ -0,0 +1,58 @@
1
+ using Reight
2
+
3
+
4
+ class Reight::SpriteEditor::Select < Reight::SpriteEditor::Tool
5
+
6
+ def initialize(app, &block)
7
+ super app, icon: app.icon(0, 2, 8), &block
8
+ set_help left: 'Select or Move'
9
+ end
10
+
11
+ def move_or_select(x, y)
12
+ x0, y0 = @press_pos&.to_a || return
13
+ if @moving
14
+ sx, sy, sw, sh = canvas.selection
15
+ dx, dy = (x - x0).to_i, (y - y0).to_i
16
+ history.group do
17
+ canvas.begin_editing do
18
+ image = canvas.capture_frame [sx, sy, sw, sh]
19
+ app.clear_canvas sx, sy, sw, sh
20
+ canvas.apply_frame image, sx + dx, sy + dy
21
+ canvas.select sx + dx, sy + dy, sw, sh
22
+ end
23
+ end
24
+ else
25
+ canvas.select canvas.x + x0, canvas.y + y0, x - x0, y - y0
26
+ end
27
+ end
28
+
29
+ def canvas_pressed(x, y, button)
30
+ @press_pos = create_vector x, y
31
+ @moving = button == LEFT && is_in_selection?(x, y)
32
+ move_or_select x, y
33
+ end
34
+
35
+ def canvas_released(x, y, button)
36
+ @press_pos = nil
37
+ @moving = false
38
+ end
39
+
40
+ def canvas_dragged(x, y, button)
41
+ app.undo flash: false
42
+ move_or_select x, y
43
+ end
44
+
45
+ def canvas_clicked(x, y, button)
46
+ app.undo flash: false
47
+ canvas.deselect
48
+ end
49
+
50
+ private
51
+
52
+ def is_in_selection?(x, y)
53
+ return false unless sel = canvas.selection
54
+ sx, sy, sw, sh = sel
55
+ (sx..(sx + sw)).include?(canvas.x + x) && (sy..(sy + sh)).include?(canvas.y + y)
56
+ end
57
+
58
+ end# Select
@@ -0,0 +1,43 @@
1
+ using Reight
2
+
3
+
4
+ class Reight::SpriteEditor::Shape < Reight::SpriteEditor::Tool
5
+
6
+ def initialize(app, shape, fill, &block)
7
+ @shape, @fill = shape, fill
8
+ icon_index = [:rect, :ellipse].product([false, true]).index([shape, fill])
9
+ super app, icon: app.icon(icon_index + 4, 2, 8), &block
10
+ set_help left: name, right: 'Pick Color'
11
+ end
12
+
13
+ def name = "#{@fill ? :Fill : :Stroke} #{@shape.capitalize}"
14
+
15
+ def draw_shape(x, y)
16
+ canvas.begin_editing do
17
+ canvas.paint do |g|
18
+ @fill ? g.fill(*canvas.color) : g.no_fill
19
+ g.stroke(*canvas.color)
20
+ g.rect_mode CORNER
21
+ g.ellipse_mode CORNER
22
+ g.send @shape, @x, @y, x - @x, y - @y
23
+ end
24
+ end
25
+ end
26
+
27
+ def canvas_pressed(x, y, button)
28
+ return unless button == LEFT
29
+ @x, @y = x, y
30
+ draw_shape x, y
31
+ end
32
+
33
+ def canvas_dragged(x, y, button)
34
+ return unless button == LEFT
35
+ app.undo flash: false
36
+ draw_shape x, y
37
+ end
38
+
39
+ def canvas_clicked(x, y, button)
40
+ pick_color x, y if button == RIGHT
41
+ end
42
+
43
+ end# Shape
@@ -0,0 +1,27 @@
1
+ using Reight
2
+
3
+
4
+ class Reight::SpriteEditor::Tool < Reight::Button
5
+
6
+ def initialize(app, *a, **k, &b)
7
+ super(*a, **k, &b)
8
+ @app = app
9
+ end
10
+
11
+ attr_reader :app
12
+
13
+ def canvas = app.canvas
14
+
15
+ def history = app.history
16
+
17
+ def pick_color(x, y)
18
+ canvas.color = canvas.pixel_at x, y
19
+ end
20
+
21
+ def canvas_pressed( x, y, button) = nil
22
+ def canvas_released(x, y, button) = nil
23
+ def canvas_moved( x, y) = nil
24
+ def canvas_dragged( x, y, button) = nil
25
+ def canvas_clicked( x, y, button) = nil
26
+
27
+ end# Tool
@@ -0,0 +1,10 @@
1
+ require 'reight/app/sprite/editor'
2
+ require 'reight/app/sprite/canvas'
3
+ require 'reight/app/sprite/chips'
4
+ require 'reight/app/sprite/color'
5
+ require 'reight/app/sprite/tool'
6
+ require 'reight/app/sprite/select'
7
+ require 'reight/app/sprite/brush'
8
+ require 'reight/app/sprite/fill'
9
+ require 'reight/app/sprite/line'
10
+ require 'reight/app/sprite/shape'
data/lib/reight/app.rb ADDED
@@ -0,0 +1,123 @@
1
+ using Reight
2
+
3
+
4
+ class Reight::App
5
+
6
+ SCREEN_WIDTH = 400
7
+ SCREEN_HEIGHT = 224
8
+
9
+ SPACE = 6
10
+ BUTTON_SIZE = 12
11
+ NAVIGATOR_HEIGHT = BUTTON_SIZE + 2
12
+ CHIPS_WIDTH = 128
13
+
14
+ def initialize(project)
15
+ @project = project
16
+ end
17
+
18
+ attr_reader :project
19
+
20
+ def flash(...)
21
+ navigator.flash(...) if history.enabled?
22
+ end
23
+
24
+ def group(*buttons)
25
+ buttons.each.with_index do |button, index|
26
+ button.clicked do
27
+ buttons.each.with_index {|b, i| b.active = i == index}
28
+ end
29
+ end
30
+ buttons
31
+ end
32
+
33
+ def pressing?(key)
34
+ pressing_keys.include? key
35
+ end
36
+
37
+ def name()
38
+ self.class.name
39
+ end
40
+
41
+ def history()
42
+ @history ||= Reight::History.new
43
+ end
44
+
45
+ def sprites()
46
+ navigator.sprites
47
+ end
48
+
49
+ def icon(xi, yi, size)
50
+ (@icon ||= {})[[xi, yi, size]] ||= createGraphics(size, size).tap do |g|
51
+ g.beginDraw do
52
+ g.copy r8.icons, xi * size, yi * size, size, size, 0, 0, size, size
53
+ end
54
+ end
55
+ # TODO: ||= r8.icons.sub_image xi * size, yi * size, size, size
56
+ end
57
+
58
+ def activated()
59
+ add_world world if world
60
+ end
61
+
62
+ def deactivated()
63
+ remove_world world if world
64
+ end
65
+
66
+ def draw()
67
+ navigator.draw
68
+ end
69
+
70
+ def key_pressed()
71
+ navigator.key_pressed
72
+ pressing_keys.add key_code
73
+ end
74
+
75
+ def key_released()
76
+ pressing_keys.delete key_code
77
+ end
78
+
79
+ def window_resized()
80
+ navigator.window_resized
81
+ end
82
+
83
+ def key_typed() = nil
84
+ def mouse_pressed() = nil
85
+ def mouse_released() = nil
86
+ def mouse_moved() = nil
87
+ def mouse_dragged() = nil
88
+ def mouse_clicked() = nil
89
+ def double_clicked() = nil
90
+ def mouse_wheel() = nil
91
+ def touch_started() = nil
92
+ def touch_ended() = nil
93
+ def touch_moved() = nil
94
+ def window_moved() = nil
95
+
96
+ #def undo(flash: true) = nil
97
+ #def redo(flash: true) = nil
98
+
99
+ #def cut( flash: true) = nil
100
+ #def copy( flash: true) = nil
101
+ #def paste(flash: true) = nil
102
+
103
+ def inspect()
104
+ "#<#{self.class.name}:0x#{object_id}>"
105
+ end
106
+
107
+ private
108
+
109
+ def navigator()
110
+ @navigator ||= Reight::Navigator.new self
111
+ end
112
+
113
+ def world()
114
+ @world ||= SpriteWorld.new.tap do |w|
115
+ w.add_sprite(*sprites)
116
+ end
117
+ end
118
+
119
+ def pressing_keys()
120
+ @pressing_keys ||= Set.new
121
+ end
122
+
123
+ end# App
@@ -0,0 +1,93 @@
1
+ using Reight
2
+
3
+
4
+ class Reight::Button
5
+
6
+ include Reight::Activatable
7
+ include Reight::Hookable
8
+ include Reight::HasHelp
9
+
10
+ def initialize(name: nil, icon: nil, label: nil, &clicked)
11
+ raise if icon && label
12
+ @name, @icon, @label = name, icon, label
13
+ super()
14
+
15
+ hook :clicked
16
+ self.clicked(&clicked)
17
+ self.clicked {r8.flash name}
18
+ end
19
+
20
+ def draw()
21
+ sp = sprite
22
+ no_stroke
23
+
24
+ if @label
25
+ fill 210
26
+ rect 0, pressing? ? 2 : 1, sp.w, sp.h - 1, 2
27
+ end
28
+
29
+ if active?
30
+ fill 230
31
+ rect 0, pressing? ? 1 : 0, sp.w, sp.h, 2
32
+ end
33
+
34
+ if @icon
35
+ x = (sp.w - @icon.width) / 2
36
+ y = (sp.h - @icon.height) / 2
37
+ y += 1 if pressing?
38
+ image enabled? ? @icon : disabled_icon, x, y
39
+ end
40
+
41
+ if @label
42
+ text_size r8.project.font_size - 1
43
+ text_align CENTER, CENTER
44
+ fill 100, 100, 100
45
+ text @label, 0, 1, sp.w, sp.h
46
+ fill 255, 255, 255
47
+ text @label, 0, 0, sp.w, sp.h
48
+ end
49
+ end
50
+
51
+ def pressed(x, y)
52
+ @pressing = true if enabled?
53
+ end
54
+
55
+ def released(x, y)
56
+ @pressing = false
57
+ end
58
+
59
+ def pressing? = @pressing
60
+
61
+ def hover(x, y)
62
+ r8.flash help, priority: 0.5
63
+ end
64
+
65
+ def click() = clicked! self
66
+
67
+ def enabled?(&block)
68
+ @enabled_block = block if block
69
+ @enabled_block ? @enabled_block.call : true
70
+ end
71
+
72
+ def disabled? = !enabled?
73
+
74
+ def sprite()
75
+ @sprite ||= Sprite.new(physics: false).tap do |sp|
76
+ sp.draw {draw}
77
+ sp.mouse_pressed {pressed sp.mouse_x, sp.mouse_y}
78
+ sp.mouse_released {released sp.mouse_x, sp.mouse_y}
79
+ sp.mouse_moved {hover sp.mouse_x, sp.mouse_y}
80
+ sp.mouse_clicked {clicked! self if enabled?}
81
+ end
82
+ end
83
+
84
+ def disabled_icon()
85
+ @disabled_icon ||= createGraphics(@icon.width, @icon.height).tap do |g|
86
+ g.beginDraw {g.image @icon, 0, 0}
87
+ g.load_pixels
88
+ g.pixels.map! {|c| alpha(c) > 0 ? color(180) : c}
89
+ g.update_pixels
90
+ end
91
+ end
92
+
93
+ end# Button