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.
- checksums.yaml +7 -0
- data/.github/workflows/release-gem.yml +62 -0
- data/.github/workflows/tag.yml +35 -0
- data/.github/workflows/test.yml +37 -0
- data/.github/workflows/utils.rb +56 -0
- data/.gitignore +1 -0
- data/ChangeLog.md +23 -0
- data/Gemfile +6 -0
- data/LICENSE +21 -0
- data/README.md +62 -0
- data/Rakefile +30 -0
- data/VERSION +1 -0
- data/bin/r8 +35 -0
- data/lib/reight/all.rb +59 -0
- data/lib/reight/app/map/brush.rb +27 -0
- data/lib/reight/app/map/brush_base.rb +54 -0
- data/lib/reight/app/map/canvas.rb +150 -0
- data/lib/reight/app/map/chips.rb +84 -0
- data/lib/reight/app/map/editor.rb +117 -0
- data/lib/reight/app/map/line.rb +35 -0
- data/lib/reight/app/map/rect.rb +29 -0
- data/lib/reight/app/map/tool.rb +32 -0
- data/lib/reight/app/map.rb +8 -0
- data/lib/reight/app/music/editor.rb +25 -0
- data/lib/reight/app/music.rb +1 -0
- data/lib/reight/app/navigator.rb +172 -0
- data/lib/reight/app/runner.rb +275 -0
- data/lib/reight/app/sound/editor.rb +25 -0
- data/lib/reight/app/sound.rb +1 -0
- data/lib/reight/app/sprite/brush.rb +43 -0
- data/lib/reight/app/sprite/canvas.rb +254 -0
- data/lib/reight/app/sprite/chips.rb +92 -0
- data/lib/reight/app/sprite/color.rb +30 -0
- data/lib/reight/app/sprite/editor.rb +272 -0
- data/lib/reight/app/sprite/fill.rb +45 -0
- data/lib/reight/app/sprite/line.rb +37 -0
- data/lib/reight/app/sprite/select.rb +58 -0
- data/lib/reight/app/sprite/shape.rb +43 -0
- data/lib/reight/app/sprite/tool.rb +27 -0
- data/lib/reight/app/sprite.rb +10 -0
- data/lib/reight/app.rb +123 -0
- data/lib/reight/button.rb +93 -0
- data/lib/reight/chip.rb +150 -0
- data/lib/reight/extension.rb +24 -0
- data/lib/reight/helpers.rb +69 -0
- data/lib/reight/history.rb +135 -0
- data/lib/reight/map.rb +264 -0
- data/lib/reight/project.rb +115 -0
- data/lib/reight/reight.rb +83 -0
- data/lib/reight.rb +18 -0
- data/reight.gemspec +40 -0
- data/res/icons.png +0 -0
- data/test/helper.rb +15 -0
- data/test/test_chip.rb +108 -0
- data/test/test_chip_list.rb +68 -0
- data/test/test_map.rb +232 -0
- data/test/test_map_chunk.rb +226 -0
- 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
|