reight 0.1.6 → 0.1.8

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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/.github/PULL_REQUEST_TEMPLATE.md +12 -0
  3. data/CONTRIBUTING.md +7 -0
  4. data/ChangeLog.md +76 -0
  5. data/README.md +6 -5
  6. data/Rakefile +5 -2
  7. data/VERSION +1 -1
  8. data/bin/r8 +18 -8
  9. data/lib/reight/all.rb +7 -2
  10. data/lib/reight/app/chips.rb +124 -0
  11. data/lib/reight/app/map/brush.rb +1 -1
  12. data/lib/reight/app/map/brush_base.rb +3 -3
  13. data/lib/reight/app/map/canvas.rb +10 -15
  14. data/lib/reight/app/map/editor.rb +44 -17
  15. data/lib/reight/app/map/line.rb +5 -5
  16. data/lib/reight/app/map/rect.rb +2 -2
  17. data/lib/reight/app/map.rb +0 -1
  18. data/lib/reight/app/navigator.rb +33 -47
  19. data/lib/reight/app/runner.rb +123 -86
  20. data/lib/reight/app/sound/brush.rb +32 -0
  21. data/lib/reight/app/sound/canvas.rb +190 -0
  22. data/lib/reight/app/sound/editor.rb +170 -10
  23. data/lib/reight/app/sound/eraser.rb +28 -0
  24. data/lib/reight/app/sound/tool.rb +29 -0
  25. data/lib/reight/app/sound.rb +4 -0
  26. data/lib/reight/app/sprite/canvas.rb +23 -18
  27. data/lib/reight/app/sprite/color.rb +3 -1
  28. data/lib/reight/app/sprite/editor.rb +58 -47
  29. data/lib/reight/app/sprite/line.rb +1 -1
  30. data/lib/reight/app/sprite/shape.rb +1 -1
  31. data/lib/reight/app/sprite.rb +0 -1
  32. data/lib/reight/app.rb +24 -5
  33. data/lib/reight/button.rb +10 -7
  34. data/lib/reight/chip.rb +32 -6
  35. data/lib/reight/context.rb +168 -0
  36. data/lib/reight/helpers.rb +2 -2
  37. data/lib/reight/index.rb +87 -0
  38. data/lib/reight/map.rb +141 -11
  39. data/lib/reight/project.rb +45 -6
  40. data/lib/reight/reight.rb +11 -15
  41. data/lib/reight/sound.rb +238 -0
  42. data/lib/reight/sprite.rb +42 -0
  43. data/lib/reight/text.rb +124 -0
  44. data/lib/reight.rb +7 -3
  45. data/reight.gemspec +7 -7
  46. data/res/icons.png +0 -0
  47. data/test/helper.rb +16 -0
  48. data/test/test_map.rb +7 -7
  49. data/test/test_map_chunk.rb +6 -6
  50. data/test/test_sprite.rb +28 -0
  51. metadata +42 -32
  52. data/lib/reight/app/map/chips.rb +0 -84
  53. data/lib/reight/app/music/editor.rb +0 -25
  54. data/lib/reight/app/music.rb +0 -1
  55. data/lib/reight/app/sprite/chips.rb +0 -92
@@ -0,0 +1,190 @@
1
+ using Reight
2
+
3
+
4
+ class Reight::SoundEditor::Canvas
5
+
6
+ include Reight::Hookable
7
+
8
+ SEQUENCE_LEN = 32
9
+ NOTE_HEIGHT = 3
10
+
11
+ def initialize(app)
12
+ hook :sound_changed
13
+
14
+ @app, @sound = app, app.project.sounds.first
15
+ @scrolly = NOTE_HEIGHT * Reight::Sound::Note::MAX / 3
16
+ end
17
+
18
+ attr_accessor :tone, :tool
19
+
20
+ attr_reader :sound
21
+
22
+ def sound=(sound)
23
+ @sound = sound
24
+ sound_changed! sound
25
+ end
26
+
27
+ def save()
28
+ @app.project.save
29
+ end
30
+
31
+ def begin_editing(&block)
32
+ @app.history.begin_grouping
33
+ block.call if block
34
+ ensure
35
+ end_editing if block
36
+ end
37
+
38
+ def end_editing()
39
+ @app.history.end_grouping
40
+ save
41
+ end
42
+
43
+ def note_pos_at(x, y)
44
+ sp = sprite
45
+ notew = sp.w / SEQUENCE_LEN
46
+ max = Reight::Sound::Note::MAX
47
+ time_index = (x / notew).floor
48
+ note_index = max - ((@scrolly + y) / NOTE_HEIGHT).floor
49
+ return time_index, note_index.clamp(0, max)
50
+ end
51
+
52
+ def put(x, y)
53
+ time_i, note_i = note_pos_at x, y
54
+
55
+ @sound.each_note(time_index: time_i)
56
+ .select {|note,| (note.index == note_i) != (note.tone == tone)}
57
+ .each {|note,| remove_note time_i, note.index, note.tone}
58
+ add_note time_i, note_i, tone
59
+
60
+ @app.flash note_name y
61
+ end
62
+
63
+ def delete(x, y)
64
+ time_i, note_i = note_pos_at x, y
65
+ note = @sound.at time_i, note_i
66
+ return unless note
67
+
68
+ remove_note time_i, note_i, note.tone
69
+
70
+ @app.flash note_name y
71
+ end
72
+
73
+ def sprite()
74
+ @sprite ||= RubySketch::Sprite.new.tap do |sp|
75
+ pos = -> {return sp.mouse_x, sp.mouse_y}
76
+ sp.draw {draw}
77
+ sp.mouse_pressed {mouse_pressed( *pos.call, sp.mouse_button)}
78
+ sp.mouse_released {mouse_released(*pos.call, sp.mouse_button)}
79
+ sp.mouse_moved {mouse_moved( *pos.call)}
80
+ sp.mouse_dragged {mouse_dragged( *pos.call, sp.mouse_button)}
81
+ sp.mouse_clicked {mouse_clicked( *pos.call, sp.mouse_button)}
82
+ end
83
+ end
84
+
85
+ private
86
+
87
+ def add_note(ti, ni, tone)
88
+ return if @sound.at(ti, ni)&.tone == tone
89
+ @sound.add ti, ni, tone
90
+ @sound.at(ti, ni)&.play 120
91
+ @app.history.append [:put_note, ti, ni, tone]
92
+ end
93
+
94
+ def remove_note(ti, ni, tone)
95
+ #@sound.at(ti, ni)&.play @sound.bpm
96
+ @sound.remove ti, ni
97
+ @app.history.append [:delete_note, ti, ni, tone]
98
+ end
99
+
100
+ def draw()
101
+ sp = sprite
102
+ clip sp.x, sp.y, sp.w, sp.h
103
+
104
+ no_stroke
105
+ fill 0
106
+ rect 0, 0, sp.w, sp.h
107
+
108
+ translate 0, -@scrolly
109
+ draw_grids
110
+ draw_notes
111
+ draw_note_names
112
+ end
113
+
114
+ TONE_COLORS = {
115
+ sine: 5,
116
+ triangle: 29,
117
+ square: 19,
118
+ sawtooth: 30,
119
+ pulse12_5: 27,
120
+ pulse25: 14,
121
+ noise: 12
122
+ }.transform_values {Reight::App::PALETTE_COLORS[_1]}
123
+
124
+ GRID_COLORS = [1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1]
125
+ .map.with_index {|n, i| i == 0 ? 100 : (n == 1 ? 80 : 60)}
126
+
127
+ def draw_grids()
128
+ sp = sprite
129
+ noteh = NOTE_HEIGHT
130
+ Reight::Sound::Note::MAX.downto(0).with_index do |y, index|
131
+ fill GRID_COLORS[index % GRID_COLORS.size]
132
+ rect 0, y * noteh, sp.w, noteh
133
+ end
134
+ end
135
+
136
+ def draw_notes()
137
+ sp = sprite
138
+ notew, noteh = sp.w / SEQUENCE_LEN, NOTE_HEIGHT
139
+ tones, max = Reight::Sound::Note::TONES, Reight::Sound::Note::MAX
140
+ @sound.each_note do |note, index|
141
+ fill TONE_COLORS[note.tone]
142
+ rect index * notew, (max - note.index) * noteh, notew, noteh
143
+ end
144
+ end
145
+
146
+ def draw_note_names()
147
+ fill 200
148
+ text_size 4
149
+ text_align LEFT, CENTER
150
+ noteh = NOTE_HEIGHT
151
+ max = Reight::Sound::Note::MAX
152
+ (0..Reight::Sound::Note::MAX).step(12).with_index do |y, index|
153
+ text "C#{index}", 2, (max - y) * noteh, 10, noteh
154
+ end
155
+ end
156
+
157
+ def mouse_pressed(...)
158
+ tool&.canvas_pressed(...) unless hand?
159
+ end
160
+
161
+ def mouse_released(...)
162
+ tool&.canvas_released(...) unless hand?
163
+ end
164
+
165
+ def mouse_moved(x, y)
166
+ tool&.canvas_moved(x, y)
167
+ @app.flash note_name y
168
+ end
169
+
170
+ def mouse_dragged(...)
171
+ if hand?
172
+ sp = sprite
173
+ @scrolly -= sp.mouse_y - sp.pmouse_y
174
+ else
175
+ tool&.canvas_dragged(...)
176
+ end
177
+ end
178
+
179
+ def mouse_clicked(...)
180
+ tool&.canvas_clicked(...) unless hand?
181
+ end
182
+
183
+ def hand? = @app.pressing?(SPACE)
184
+
185
+ def note_name(y)
186
+ _, note_i = note_pos_at 0, y
187
+ Reight::Sound::Note.new(note_i).to_s.split(':').first.capitalize
188
+ end
189
+
190
+ end# Canvas
@@ -3,23 +3,183 @@ using Reight
3
3
 
4
4
  class Reight::SoundEditor < Reight::App
5
5
 
6
+ def canvas()
7
+ @canvas ||= Canvas.new self
8
+ end
9
+
10
+ def setup()
11
+ super
12
+ history.disable do
13
+ tones[0].click
14
+ tools[0].click
15
+ end
16
+ end
17
+
6
18
  def draw()
7
19
  background 200
20
+ sprite(*sprites)
21
+ super
22
+ end
8
23
 
9
- push do
10
- text_align LEFT, CENTER
24
+ def key_pressed()
25
+ super
26
+ case key_code
27
+ when ENTER then play_or_stop.click
28
+ when :b then brush.click
29
+ when :e then eraser.click
30
+ when /^[#{(1..Reight::Sound::Note::TONES.size).to_a.join}]$/
31
+ tones[key_code.to_s.to_i - 1].click
32
+ end
33
+ end
11
34
 
12
- text_size 10
13
- fill 220; text "Sound Editor", 150, 1, 200, height
14
- fill 150; text "Sound Editor", 150, 0, 200, height
35
+ def window_resized()
36
+ super
37
+ index.sprite.tap do |sp|
38
+ sp.w, sp.h = 32, BUTTON_SIZE
39
+ sp.x = SPACE
40
+ sp.y = NAVIGATOR_HEIGHT + SPACE
41
+ end
42
+ bpm.sprite.tap do |sp|
43
+ sp.w, sp.h = 40, BUTTON_SIZE
44
+ sp.x = index.sprite.right + SPACE
45
+ sp.y = index.sprite.y
46
+ end
47
+ edits.map(&:sprite).each.with_index do |sp, i|
48
+ sp.w, sp.h = 32, BUTTON_SIZE
49
+ sp.x = bpm.sprite.right + SPACE + (sp.w + 1) * i
50
+ sp.y = bpm.sprite.y
51
+ end
52
+ controls.map(&:sprite).each.with_index do |sp, i|
53
+ sp.w, sp.h = 32, BUTTON_SIZE
54
+ sp.x = SPACE + (sp.w + 1) * i
55
+ sp.y = height - (SPACE + sp.h)
56
+ end
57
+ tools.map(&:sprite).each.with_index do |sp, i|
58
+ sp.w = sp.h = BUTTON_SIZE
59
+ sp.x = controls.last.sprite.right + SPACE * 2 + (sp.w + 1) * i
60
+ sp.y = controls.last.sprite.y
61
+ end
62
+ tones.map(&:sprite).each.with_index do |sp, i|
63
+ sp.w = sp.h = BUTTON_SIZE
64
+ sp.x = tools.last.sprite.right + SPACE * 2 + (sp.w + 1) * i
65
+ sp.y = tools.last.sprite.y
66
+ end
67
+ canvas.sprite.tap do |sp|
68
+ sp.x = SPACE
69
+ sp.y = index.sprite.bottom + SPACE
70
+ sp.right = width - SPACE
71
+ sp.bottom = tools.first.sprite.y - SPACE
72
+ end
73
+ end
15
74
 
16
- text_size 8
17
- dots = '.' * (frame_count / 60 % 4).to_i
18
- fill 220; text "is under construction#{dots}", 150, 11, 200, height
19
- fill 150; text "is under construction#{dots}", 150, 10, 200, height
75
+ def undo(flash: true)
76
+ history.undo do |action|
77
+ case action
78
+ in [:put_note, ti, ni, _] then canvas.sound.remove ti, ni
79
+ in [:delete_note, ti, ni, tone] then canvas.sound.add ti, ni, tone
80
+ end
81
+ self.flash 'Undo!' if flash
20
82
  end
83
+ end
21
84
 
22
- super
85
+ def redo(flash: true)
86
+ history.redo do |action|
87
+ case action
88
+ in [:put_note, ti, ni, tone] then canvas.sound.add ti, ni, tone
89
+ in [:delete_note, ti, ni, _] then canvas.sound.remove ti, ni
90
+ end
91
+ self.flash 'Redo!' if flash
92
+ end
93
+ end
94
+
95
+ private
96
+
97
+ def sprites()
98
+ [index, bpm, *edits, *controls, *tools, *tones, canvas]
99
+ .map(&:sprite) + super
100
+ end
101
+
102
+ def index()
103
+ @index ||= Reight::Index.new do |index|
104
+ canvas.sound = project.sounds[index] ||= Reight::Sound.new
105
+ end
106
+ end
107
+
108
+ def bpm()
109
+ @bpm ||= Reight::Text.new(
110
+ canvas.sound.bpm, label: 'BPM ', regexp: /^\-?\d+$/, editable: true
111
+ ) do |str, text|
112
+ bpm = str.to_i.clamp(0, Reight::Sound::BPM_MAX)
113
+ next text.revert if bpm <= 0
114
+ text.value = canvas.sound.bpm = bpm
115
+ canvas.save
116
+ end.tap do |text|
117
+ canvas.sound_changed {text.value = _1.bpm}
118
+ end
119
+ end
120
+
121
+ def edits()
122
+ @edits ||= [
123
+ Reight::Button.new(name: 'Clear All Notes', label: 'Clear') {
124
+ canvas.sound.clear
125
+ canvas.save
126
+ },
127
+ Reight::Button.new(name: 'Delete Sound', label: 'Delete') {
128
+ project.sounds.delete_at index.index
129
+ canvas.sound = project.sounds[index.index] ||= Reight::Sound.new
130
+ canvas.save
131
+ },
132
+ ]
133
+ end
134
+
135
+ def controls()
136
+ @controls ||= [play_or_stop]
137
+ end
138
+
139
+ def play_or_stop()
140
+ @play_or_stop ||= Reight::Button.new(name: 'Play Sound', label: 'Play') {|b|
141
+ played = -> {b.name, b.label = 'Stop Sound', 'Stop'}
142
+ stopped = -> {b.name, b.label = 'Play Sound', 'Play'}
143
+ if canvas.sound.playing?
144
+ canvas.sound.stop
145
+ stopped.call
146
+ else
147
+ canvas.sound.play {stopped.call}
148
+ played.call
149
+ end
150
+ }
151
+ end
152
+
153
+ def tools()
154
+ @tools ||= group brush, eraser
155
+ end
156
+
157
+ def brush = @brush ||= Brush.new(self) {canvas.tool = _1}
158
+ def eraser = @eraser ||= Eraser.new(self) {canvas.tool = _1}
159
+
160
+ def tones()
161
+ @tones ||= group(*Reight::Sound::Note::TONES.map.with_index {|tone, index|
162
+ name = tone.to_s.capitalize.gsub('_', '.')
163
+ name += ' Wave' if name !~ /noise/i
164
+ color = Canvas::TONE_COLORS[tone]
165
+ Reight::Button.new name: name, icon: icon(index, 3, 8) do
166
+ canvas.tone = tone
167
+ Reight::Sound::Note.new(60, tone).play 120 if active?
168
+ end.tap do |b|
169
+ b.instance_variable_set :@color, color
170
+ class << b
171
+ alias draw_ draw
172
+ def draw
173
+ draw_
174
+ no_fill
175
+ stroke @color
176
+ stroke_weight 1
177
+ w, h = sprite.width, sprite.height
178
+ line 3, h - 1, w - 3, h - 1
179
+ end
180
+ end
181
+ end
182
+ })
23
183
  end
24
184
 
25
185
  end# SoundEditor
@@ -0,0 +1,28 @@
1
+ class Reight::SoundEditor::Eraser < Reight::SoundEditor::Tool
2
+
3
+ def initialize(app, &block)
4
+ super app, icon: app.icon(3, 2, 8), &block
5
+ set_help left: name
6
+ end
7
+
8
+ def erase(x, y, button)
9
+ canvas.delete x, y
10
+ end
11
+
12
+ def canvas_pressed(x, y, button)
13
+ return unless button == LEFT
14
+ canvas.begin_editing
15
+ erase x, y, button
16
+ end
17
+
18
+ def canvas_released(x, y, button)
19
+ return unless button == LEFT
20
+ canvas.end_editing
21
+ end
22
+
23
+ def canvas_dragged(x, y, button)
24
+ return unless button == LEFT
25
+ erase x, y, button
26
+ end
27
+
28
+ end# Eraser
@@ -0,0 +1,29 @@
1
+ using Reight
2
+
3
+
4
+ class Reight::SoundEditor::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 name = self.class.name.split('::').last
18
+
19
+ def pick_tone(x, y)
20
+ canvas.tone = canvas.tone_at x, y
21
+ end
22
+
23
+ def canvas_pressed( x, y, button) = nil
24
+ def canvas_released(x, y, button) = nil
25
+ def canvas_moved( x, y) = nil
26
+ def canvas_dragged( x, y, button) = nil
27
+ def canvas_clicked( x, y, button) = nil
28
+
29
+ end# Tool
@@ -1 +1,5 @@
1
1
  require 'reight/app/sound/editor'
2
+ require 'reight/app/sound/canvas'
3
+ require 'reight/app/sound/tool'
4
+ require 'reight/app/sound/brush'
5
+ require 'reight/app/sound/eraser'
@@ -6,17 +6,21 @@ class Reight::SpriteEditor::Canvas
6
6
  include Reight::Hookable
7
7
 
8
8
  def initialize(app, image, path)
9
- hook :tool_changed, :color_changed
9
+ hook :frame_changed
10
+ hook :selection_changed
11
+ hook :color_changed
10
12
 
11
13
  @app, @image, @path = app, image, path
12
- @tool, @color, @selection = nil, [255, 255, 255], nil
14
+ @tool, @color, @selection = nil, [255, 255, 255, 255], nil
13
15
 
14
16
  @app.history.disable do
15
17
  set_frame 0, 0, 16, 16
16
18
  end
17
19
  end
18
20
 
19
- attr_reader :x, :y, :w, :h, :tool, :color
21
+ attr_accessor :tool
22
+
23
+ attr_reader :x, :y, :w, :h, :color
20
24
 
21
25
  def width = @image.width
22
26
 
@@ -27,17 +31,12 @@ class Reight::SpriteEditor::Canvas
27
31
  @app.project.save
28
32
  end
29
33
 
30
- def tool=(tool)
31
- @tool = tool
32
- tool_changed! tool
33
- end
34
-
35
34
  def set_frame(x, y, w, h)
36
35
  old = [@x, @y, @w, @h]
37
36
  new = correct_bounds x, y, w, h
38
37
  return if new == old
39
38
  @x, @y, @w, @h = new
40
- @app.history.append [:frame, old, new]
39
+ frame_changed! old, new
41
40
  end
42
41
 
43
42
  def frame = [x, y, w, h]
@@ -53,7 +52,7 @@ class Reight::SpriteEditor::Canvas
53
52
  new = correct_bounds x, y, w, h
54
53
  return if new == old
55
54
  @selection = new
56
- @app.history.append [:select, old, new]
55
+ selection_changed! old, new
57
56
  end
58
57
 
59
58
  def selection()
@@ -68,7 +67,7 @@ class Reight::SpriteEditor::Canvas
68
67
  def deselect()
69
68
  return if @selection == nil
70
69
  old, @selection = @selection, nil
71
- @app.history.append [:deselect, old]
70
+ selection_changed! old, nil
72
71
  end
73
72
 
74
73
  def paint(&block)
@@ -76,6 +75,7 @@ class Reight::SpriteEditor::Canvas
76
75
  g.clip(*(selection || frame))
77
76
  g.push do
78
77
  g.translate x, y
78
+ g.blend_mode REPLACE
79
79
  block.call g
80
80
  end
81
81
  end
@@ -85,24 +85,24 @@ class Reight::SpriteEditor::Canvas
85
85
  tmp = sub_image x, y, w, h
86
86
  tmp.update_pixels {|pixels| block.call pixels}
87
87
  @image.begin_draw do |g|
88
- g.copy tmp, 0, 0, w, h, x, y, w, h
88
+ g.blend tmp, 0, 0, w, h, x, y, w, h, REPLACE
89
89
  end
90
90
  end
91
91
 
92
92
  def sub_image(x, y, w, h)
93
93
  create_graphics(w, h).tap do |g|
94
- g.begin_draw {g.copy @image, x, y, w, h, 0, 0, w, h}
94
+ g.begin_draw {g.blend @image, x, y, w, h, 0, 0, w, h, REPLACE}
95
95
  end
96
96
  end
97
97
 
98
98
  def pixel_at(x, y)
99
- img = sub_image x, y, 1, 1
99
+ img = sub_image self.x + x, self.y + y, 1, 1
100
100
  img.load_pixels
101
101
  c = img.pixels[0]
102
102
  [red(c), green(c), blue(c), alpha(c)].map &:to_i
103
103
  end
104
104
 
105
- def clear(frame, color: [0, 0, 0])
105
+ def clear(frame, color:)
106
106
  paint do |g|
107
107
  g.fill(*color)
108
108
  g.no_stroke
@@ -127,7 +127,7 @@ class Reight::SpriteEditor::Canvas
127
127
  x, y, w, h = frame
128
128
  create_graphics(w, h).tap do |g|
129
129
  g.begin_draw do
130
- g.copy @image, x, y, w, h, 0, 0, w, h
130
+ g.blend @image, x, y, w, h, 0, 0, w, h, REPLACE
131
131
  end
132
132
  end
133
133
  end
@@ -135,13 +135,13 @@ class Reight::SpriteEditor::Canvas
135
135
  def apply_frame(image, x, y)
136
136
  @image.begin_draw do |g|
137
137
  w, h = image.width, image.height
138
- g.copy image, 0, 0, w, h, x, y, w, h
138
+ g.blend image, 0, 0, w, h, x, y, w, h, REPLACE
139
139
  end
140
140
  save
141
141
  end
142
142
 
143
143
  def sprite()
144
- @sprite ||= Sprite.new.tap do |sp|
144
+ @sprite ||= RubySketch::Sprite.new.tap do |sp|
145
145
  pos = -> {to_image sp.mouse_x, sp.mouse_y}
146
146
  sp.draw {draw}
147
147
  sp.mouse_pressed {tool&.canvas_pressed( *pos.call, sp.mouse_button)}
@@ -171,6 +171,11 @@ class Reight::SpriteEditor::Canvas
171
171
  def draw()
172
172
  sp = sprite
173
173
  clip sp.x, sp.y, sp.w, sp.h
174
+
175
+ fill 0
176
+ no_stroke
177
+ rect 0, 0, sp.w, sp.h
178
+
174
179
  copy @image, x, y, w, h, 0, 0, sp.w, sp.h if @image && x && y && w && h
175
180
 
176
181
  sx, sy = sp.w / w, sp.h / h
@@ -4,8 +4,9 @@ using Reight
4
4
  class Reight::SpriteEditor::Color < Reight::Button
5
5
 
6
6
  def initialize(color, &clicked)
7
- super name: '', &clicked
7
+ super name: color[0, 3].map {_1.to_s(16).upcase}.join, &clicked
8
8
  @color = color
9
+ set_help name: "##{name}"
9
10
  end
10
11
 
11
12
  attr_reader :color
@@ -15,6 +16,7 @@ class Reight::SpriteEditor::Color < Reight::Button
15
16
 
16
17
  fill(*color)
17
18
  no_stroke
19
+ blend_mode REPLACE
18
20
  rect 0, 0, sp.w, sp.h
19
21
 
20
22
  if active?