yaze 0.2.0
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
music_editor.cc
Go to the documentation of this file.
1#include "music_editor.h"
2
3#include "imgui/imgui.h"
4
5#include "absl/strings/str_format.h"
7#include "app/gui/canvas.h"
8#include "app/gui/icons.h"
9#include "app/gui/input.h"
10
11namespace yaze {
12namespace app {
13namespace editor {
14
15absl::Status MusicEditor::Update() {
16 if (ImGui::BeginTable("MusicEditorColumns", 2, music_editor_flags_,
17 ImVec2(0, 0))) {
18 ImGui::TableSetupColumn("Assembly");
19 ImGui::TableSetupColumn("Composition");
20 ImGui::TableHeadersRow();
21 ImGui::TableNextRow();
22
23 ImGui::TableNextColumn();
25
26 ImGui::TableNextColumn();
30
31 ImGui::EndTable();
32 }
33
34 return absl::OkStatus();
35}
36
38 if (ImGui::BeginTabBar("MyTabBar", ImGuiTabBarFlags_None)) {
39 for (int i = 1; i <= 8; ++i) {
40 if (ImGui::BeginTabItem(absl::StrFormat("%d", i).data())) {
42 ImGui::EndTabItem();
43 }
44 }
45 ImGui::EndTabBar();
46 }
47}
48
49static const int NUM_KEYS = 25;
50static bool keys[NUM_KEYS];
51
53 if (ImGuiID child_id = ImGui::GetID((void*)(intptr_t)9);
54 ImGui::BeginChild(child_id, ImVec2(0, 170), false)) {
55 const int NUM_LINES = 5;
56 const int LINE_THICKNESS = 2;
57 const int LINE_SPACING = 40;
58
59 // Get the draw list for the current window
60 ImDrawList* draw_list = ImGui::GetWindowDrawList();
61
62 // Draw the staff lines
63 ImVec2 canvas_p0 =
64 ImVec2(ImGui::GetCursorScreenPos().x, ImGui::GetCursorScreenPos().y);
65 ImVec2 canvas_p1 = ImVec2(canvas_p0.x + ImGui::GetContentRegionAvail().x,
66 canvas_p0.y + ImGui::GetContentRegionAvail().y);
67 draw_list->AddRectFilled(canvas_p0, canvas_p1, IM_COL32(32, 32, 32, 255));
68 for (int i = 0; i < NUM_LINES; i++) {
69 auto line_start = ImVec2(canvas_p0.x, canvas_p0.y + i * LINE_SPACING);
70 auto line_end = ImVec2(canvas_p1.x + ImGui::GetContentRegionAvail().x,
71 canvas_p0.y + i * LINE_SPACING);
72 draw_list->AddLine(line_start, line_end, IM_COL32(200, 200, 200, 255),
73 LINE_THICKNESS);
74 }
75
76 // Draw the ledger lines
77 const int NUM_LEDGER_LINES = 3;
78 for (int i = -NUM_LEDGER_LINES; i <= NUM_LINES + NUM_LEDGER_LINES; i++) {
79 if (i % 2 == 0) continue; // skip every other line
80 auto line_start = ImVec2(canvas_p0.x, canvas_p0.y + i * LINE_SPACING / 2);
81 auto line_end = ImVec2(canvas_p1.x + ImGui::GetContentRegionAvail().x,
82 canvas_p0.y + i * LINE_SPACING / 2);
83 draw_list->AddLine(line_start, line_end, IM_COL32(150, 150, 150, 255),
84 LINE_THICKNESS);
85 }
86 }
87 ImGui::EndChild();
88}
89
91 // Render the piano roll
92 float key_width = ImGui::GetContentRegionAvail().x / NUM_KEYS;
93 float white_key_height = ImGui::GetContentRegionAvail().y * 0.8f;
94 float black_key_height = ImGui::GetContentRegionAvail().y * 0.5f;
95 ImGui::Text("Piano Roll");
96 ImGui::Separator();
97 ImDrawList* draw_list = ImGui::GetWindowDrawList();
98
99 // Draw the staff lines
100 ImVec2 canvas_p0 =
101 ImVec2(ImGui::GetCursorScreenPos().x, ImGui::GetCursorScreenPos().y);
102 ImVec2 canvas_p1 = ImVec2(canvas_p0.x + ImGui::GetContentRegionAvail().x,
103 canvas_p0.y + ImGui::GetContentRegionAvail().y);
104 draw_list->AddRectFilled(canvas_p0, canvas_p1, IM_COL32(200, 200, 200, 255));
105
106 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4.f, 0.f));
107 ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0.f);
108 for (int i = 0; i < NUM_KEYS; i++) {
109 // Calculate the position and size of the key
110 ImVec2 key_pos = ImVec2(i * key_width, 0.0f);
111 ImVec2 key_size;
112 ImVec4 key_color;
113 ImVec4 text_color;
114 if (i % 12 == 1 || i % 12 == 3 || i % 12 == 6 || i % 12 == 8 ||
115 i % 12 == 10) {
116 // This is a black key
117 key_size = ImVec2(key_width * 0.6f, black_key_height);
118 key_color = ImVec4(0, 0, 0, 255);
119 text_color = ImVec4(255, 255, 255, 255);
120 } else {
121 // This is a white key
122 key_size = ImVec2(key_width, white_key_height);
123 key_color = ImVec4(255, 255, 255, 255);
124 text_color = ImVec4(0, 0, 0, 255);
125 }
126
127 ImGui::PushID(i);
128 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.f, 0.f));
129 ImGui::PushStyleColor(ImGuiCol_Button, key_color);
130 ImGui::PushStyleColor(ImGuiCol_Text, text_color);
131 if (ImGui::Button(kSongNotes[i].data(), key_size)) {
132 keys[i] ^= 1;
133 }
134 ImGui::PopStyleColor();
135 ImGui::PopStyleColor();
136 ImGui::PopStyleVar();
137
138 ImVec2 button_pos = ImGui::GetItemRectMin();
139 ImVec2 button_size = ImGui::GetItemRectSize();
140 if (keys[i]) {
141 ImVec2 dest;
142 dest.x = button_pos.x + button_size.x;
143 dest.y = button_pos.y + button_size.y;
144 ImGui::GetWindowDrawList()->AddRectFilled(button_pos, dest,
145 IM_COL32(200, 200, 255, 200));
146 }
147 ImGui::PopID();
148 ImGui::SameLine();
149 }
150 ImGui::PopStyleVar();
151 ImGui::PopStyleVar();
152}
153
155 if (ImGui::BeginTable("DWToolset", 8, toolset_table_flags_, ImVec2(0, 0))) {
156 ImGui::TableSetupColumn("#1");
157 ImGui::TableSetupColumn("#play");
158 ImGui::TableSetupColumn("#rewind");
159 ImGui::TableSetupColumn("#fastforward");
160 ImGui::TableSetupColumn("volumeController");
161
162 ImGui::EndTable();
163 }
164}
165
167 static bool is_playing = false;
168 static int selected_option = 0;
169 static int current_volume = 0;
170 static bool has_loaded_song = false;
171 const int MAX_VOLUME = 100;
172
173 if (is_playing && !has_loaded_song) {
174 has_loaded_song = true;
175 }
176
177 gui::ItemLabel("Select a song to edit: ", gui::ItemLabelFlags::Left);
178 ImGui::Combo("#songs_in_game", &selected_option, kGameSongs, 30);
179
180 gui::ItemLabel("Controls: ", gui::ItemLabelFlags::Left);
181 if (ImGui::BeginTable("SongToolset", 6, toolset_table_flags_, ImVec2(0, 0))) {
182 ImGui::TableSetupColumn("#play");
183 ImGui::TableSetupColumn("#rewind");
184 ImGui::TableSetupColumn("#fastforward");
185 ImGui::TableSetupColumn("#volume");
186 ImGui::TableSetupColumn("#debug");
187
188 ImGui::TableSetupColumn("#slider");
189
190 ImGui::TableNextColumn();
191 if (ImGui::Button(is_playing ? ICON_MD_STOP : ICON_MD_PLAY_ARROW)) {
192 if (is_playing) {
193 has_loaded_song = false;
194 }
195 is_playing = !is_playing;
196 }
197
201 if (ImGui::Button(ICON_MD_ACCESS_TIME)) {
203 }
204 ImGui::TableNextColumn();
205 ImGui::SliderInt("Volume", &current_volume, 0, 100);
206 ImGui::EndTable();
207 }
208
209 const int SONG_DURATION = 120; // duration of the song in seconds
210 static int current_time = 0; // current time in the song in seconds
211
212 // Display the current time in the song
213 gui::ItemLabel("Current Time: ", gui::ItemLabelFlags::Left);
214 ImGui::Text("%d:%02d", current_time / 60, current_time % 60);
215 ImGui::SameLine();
216 // Display the song duration/progress using a progress bar
217 ImGui::ProgressBar((float)current_time / SONG_DURATION);
218}
219
220} // namespace editor
221} // namespace app
222} // namespace yaze
absl::Status Update() override
zelda3::music::Tracker music_tracker_
ImGuiTableFlags toolset_table_flags_
ImGuiTableFlags music_editor_flags_
#define BUTTON_COLUMN(w)
Definition constants.h:19
#define ICON_MD_VOLUME_UP
Definition icons.h:2106
#define ICON_MD_FAST_FORWARD
Definition icons.h:722
#define ICON_MD_PLAY_ARROW
Definition icons.h:1477
#define ICON_MD_STOP
Definition icons.h:1857
#define ICON_MD_FAST_REWIND
Definition icons.h:723
#define ICON_MD_ACCESS_TIME
Definition icons.h:71
void ItemLabel(absl::string_view title, ItemLabelFlags flags)
Definition input.cc:196
Definition common.cc:21