@@ -111,16 +111,6 @@ auto optional_float(boost::json::object const &object, std::string_view field, s
|
||||
return static_cast<std::float32_t>(value);
|
||||
}
|
||||
|
||||
auto parse_hardware(std::string const &value) -> std::expected<vamp_zero::hardware_mode, modulus::error> {
|
||||
if (value == "fake") {
|
||||
return vamp_zero::hardware_mode::FAKE;
|
||||
}
|
||||
if (value == "real") {
|
||||
return vamp_zero::hardware_mode::REAL;
|
||||
}
|
||||
return std::unexpected(invalid("runtime.hardware must be fake or real"));
|
||||
}
|
||||
|
||||
auto parse_runtime(boost::json::object const &root, vamp_zero::runtime_config fallback) -> std::expected<vamp_zero::runtime_config, modulus::error> {
|
||||
auto object = optional_object(root, "runtime");
|
||||
if (!object) {
|
||||
@@ -129,14 +119,10 @@ auto parse_runtime(boost::json::object const &root, vamp_zero::runtime_config fa
|
||||
if (*object == nullptr) {
|
||||
return fallback;
|
||||
}
|
||||
auto hardware_text = optional_string(**object, "hardware", vamp_zero::to_string(fallback.hardware));
|
||||
auto headless = optional_bool(**object, "headless", fallback.headless);
|
||||
auto exit_after_startup = optional_bool(**object, "exit_after_startup", fallback.exit_after_startup);
|
||||
auto assets_path = optional_string(**object, "assets_path", fallback.assets_path);
|
||||
auto heartbeat_path = optional_string(**object, "heartbeat_path", fallback.heartbeat_path);
|
||||
if (!hardware_text) {
|
||||
return std::unexpected(hardware_text.error());
|
||||
}
|
||||
if (!headless) {
|
||||
return std::unexpected(headless.error());
|
||||
}
|
||||
@@ -149,12 +135,7 @@ auto parse_runtime(boost::json::object const &root, vamp_zero::runtime_config fa
|
||||
if (!heartbeat_path) {
|
||||
return std::unexpected(heartbeat_path.error());
|
||||
}
|
||||
auto hardware = parse_hardware(*hardware_text);
|
||||
if (!hardware) {
|
||||
return std::unexpected(hardware.error());
|
||||
}
|
||||
return vamp_zero::runtime_config{
|
||||
.hardware = *hardware,
|
||||
.headless = *headless,
|
||||
.exit_after_startup = *exit_after_startup,
|
||||
.assets_path = std::move(*assets_path),
|
||||
|
||||
@@ -9,16 +9,6 @@ auto vamp_zero::empty_catalogue() -> std::shared_ptr<vamp_zero::catalogue const>
|
||||
return empty;
|
||||
}
|
||||
|
||||
auto vamp_zero::to_string(vamp_zero::hardware_mode value) -> std::string {
|
||||
switch (value) {
|
||||
case vamp_zero::hardware_mode::FAKE:
|
||||
return "fake";
|
||||
case vamp_zero::hardware_mode::REAL:
|
||||
return "real";
|
||||
}
|
||||
return "fake";
|
||||
}
|
||||
|
||||
auto vamp_zero::to_string(vamp_zero::app_mode value) -> std::string {
|
||||
switch (value) {
|
||||
case vamp_zero::app_mode::MAIN_MENU:
|
||||
|
||||
+37
-120
@@ -152,6 +152,24 @@ auto first_visible_row(std::size_t selected, std::size_t total, std::size_t max_
|
||||
return selected - max_rows + 1U;
|
||||
}
|
||||
|
||||
auto draw_menu_rows(luma::draw_context &context, luma::rect bounds, std::size_t count, std::size_t selected, auto const &draw_item) -> void {
|
||||
auto total = count + 1U;
|
||||
auto visible = std::min<std::size_t>(total, 7U);
|
||||
auto first = first_visible_row(selected, total, visible);
|
||||
for (auto row = std::size_t{}; row < visible; ++row) {
|
||||
auto index = first + row;
|
||||
auto rectangle = luma::rect{.x = bounds.x + 36.0F,
|
||||
.y = bounds.y + 112.0F + static_cast<std::float32_t>(row) * 54.0F,
|
||||
.width = bounds.width - 72.0F,
|
||||
.height = 54.0F};
|
||||
if (index == 0U) {
|
||||
draw_row(context, rectangle, "BACK", "", selected == 0U);
|
||||
} else {
|
||||
draw_item(index - 1U, rectangle, index == selected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto draw_main_menu(luma::draw_context &context, luma::rect bounds, vamp_zero::app_state const &state) -> void {
|
||||
draw_text(context, bounds.x + 36.0F, bounds.y + 28.0F, "MODE", 4, vamp_style::ink, 260.0F);
|
||||
draw_text(context, bounds.x + 38.0F, bounds.y + 66.0F, "SELECT WORKFLOW", 1, vamp_style::muted, 320.0F);
|
||||
@@ -192,37 +210,12 @@ auto draw_main_menu(luma::draw_context &context, luma::rect bounds, vamp_zero::a
|
||||
auto draw_performance_song_menu(luma::draw_context &context, luma::rect bounds, vamp_zero::app_state const &state) -> void {
|
||||
draw_text(context, bounds.x + 36.0F, bounds.y + 28.0F, "PERFORMANCE", 4, vamp_style::ink, 360.0F);
|
||||
draw_text(context, bounds.x + 38.0F, bounds.y + 66.0F, std::to_string(state.catalog->performance.groups.size()) + " SONGS " + std::to_string(state.catalog->performance.parts.size()) + " PARTS", 1, vamp_style::muted, 320.0F);
|
||||
auto list_y = bounds.y + 112.0F;
|
||||
auto row_height = std::float32_t{54.0F};
|
||||
auto row_width = bounds.width - 72.0F;
|
||||
auto total_rows = state.catalog->performance.groups.size() + 1U;
|
||||
auto max_rows = std::min<std::size_t>(total_rows, 7U);
|
||||
auto first = first_visible_row(state.selected_song_index, total_rows, max_rows);
|
||||
for (auto row = std::size_t{}; row < max_rows; ++row) {
|
||||
auto index = first + row;
|
||||
if (index == 0U) {
|
||||
draw_row(context,
|
||||
{.x = bounds.x + 36.0F,
|
||||
.y = list_y + static_cast<std::float32_t>(row) * row_height,
|
||||
.width = row_width,
|
||||
.height = row_height},
|
||||
"BACK",
|
||||
"",
|
||||
state.selected_song_index == 0U);
|
||||
continue;
|
||||
}
|
||||
auto const &group = state.catalog->performance.groups[index - 1U];
|
||||
draw_row(context,
|
||||
{.x = bounds.x + 36.0F,
|
||||
.y = list_y + static_cast<std::float32_t>(row) * row_height,
|
||||
.width = row_width,
|
||||
.height = row_height},
|
||||
group.title,
|
||||
std::to_string(group.parts.size()) + " PARTS",
|
||||
index == state.selected_song_index);
|
||||
}
|
||||
draw_menu_rows(context, bounds, state.catalog->performance.groups.size(), state.selected_song_index, [&](std::size_t index, luma::rect row, std::bool_t selected) {
|
||||
auto const &group = state.catalog->performance.groups[index];
|
||||
draw_row(context, row, group.title, std::to_string(group.parts.size()) + " PARTS", selected);
|
||||
});
|
||||
if (state.catalog->performance.groups.empty()) {
|
||||
draw_text(context, bounds.x + 38.0F, list_y + row_height + 28.0F, "NO SONGS FOUND", 3, vamp_style::retrying, 420.0F);
|
||||
draw_text(context, bounds.x + 38.0F, bounds.y + 194.0F, "NO SONGS FOUND", 3, vamp_style::retrying, 420.0F);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,77 +233,27 @@ auto draw_performance_part_menu(luma::draw_context &context, luma::rect bounds,
|
||||
return;
|
||||
}
|
||||
draw_text(context, bounds.x + 38.0F, bounds.y + 66.0F, group->composer, 1, vamp_style::muted, bounds.width - 72.0F);
|
||||
auto list_y = bounds.y + 112.0F;
|
||||
auto row_height = std::float32_t{54.0F};
|
||||
auto row_width = bounds.width - 72.0F;
|
||||
auto total_rows = group->parts.size() + 1U;
|
||||
auto max_rows = std::min<std::size_t>(total_rows, 7U);
|
||||
auto first = first_visible_row(state.selected_part_index, total_rows, max_rows);
|
||||
for (auto row = std::size_t{}; row < max_rows; ++row) {
|
||||
auto index = first + row;
|
||||
if (index == 0U) {
|
||||
draw_row(context,
|
||||
{.x = bounds.x + 36.0F,
|
||||
.y = list_y + static_cast<std::float32_t>(row) * row_height,
|
||||
.width = row_width,
|
||||
.height = row_height},
|
||||
"BACK",
|
||||
"",
|
||||
state.selected_part_index == 0U);
|
||||
continue;
|
||||
}
|
||||
auto part_index = group->parts[index - 1U];
|
||||
draw_menu_rows(context, bounds, group->parts.size(), state.selected_part_index, [&](std::size_t index, luma::rect row, std::bool_t selected) {
|
||||
auto part_index = group->parts[index];
|
||||
if (part_index >= state.catalog->performance.parts.size()) {
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
auto const &part = state.catalog->performance.parts[part_index];
|
||||
draw_row(context,
|
||||
{.x = bounds.x + 36.0F,
|
||||
.y = list_y + static_cast<std::float32_t>(row) * row_height,
|
||||
.width = row_width,
|
||||
.height = row_height},
|
||||
part.part,
|
||||
std::to_string(part.total_pages) + " PAGES",
|
||||
index == state.selected_part_index);
|
||||
}
|
||||
draw_row(context, row, part.part, std::to_string(part.total_pages) + " PAGES", selected);
|
||||
});
|
||||
}
|
||||
|
||||
auto draw_practice_exercise_menu(luma::draw_context &context, luma::rect bounds, vamp_zero::app_state const &state) -> void {
|
||||
auto const &exercises = state.catalog->practice.exercises;
|
||||
draw_text(context, bounds.x + 36.0F, bounds.y + 28.0F, "PRACTICE", 4, vamp_style::ink, bounds.width - 72.0F);
|
||||
draw_text(context, bounds.x + 38.0F, bounds.y + 66.0F, std::to_string(exercises.size()) + " EXERCISES", 1, vamp_style::muted, 320.0F);
|
||||
auto list_y = bounds.y + 112.0F;
|
||||
auto row_height = std::float32_t{54.0F};
|
||||
auto row_width = bounds.width - 72.0F;
|
||||
auto total_rows = exercises.size() + 1U;
|
||||
auto max_rows = std::min<std::size_t>(total_rows, 7U);
|
||||
auto first = first_visible_row(state.selected_practice_exercise_index, total_rows, max_rows);
|
||||
for (auto row = std::size_t{}; row < max_rows; ++row) {
|
||||
auto index = first + row;
|
||||
if (index == 0U) {
|
||||
draw_row(context,
|
||||
{.x = bounds.x + 36.0F,
|
||||
.y = list_y + static_cast<std::float32_t>(row) * row_height,
|
||||
.width = row_width,
|
||||
.height = row_height},
|
||||
"BACK",
|
||||
"",
|
||||
state.selected_practice_exercise_index == 0U);
|
||||
continue;
|
||||
}
|
||||
auto const &exercise = exercises[index - 1U];
|
||||
draw_menu_rows(context, bounds, exercises.size(), state.selected_practice_exercise_index, [&](std::size_t index, luma::rect row, std::bool_t selected) {
|
||||
auto const &exercise = exercises[index];
|
||||
auto title = exercise.title == exercise.id ? exercise.id : exercise.id + " - " + exercise.title;
|
||||
draw_row(context,
|
||||
{.x = bounds.x + 36.0F,
|
||||
.y = list_y + static_cast<std::float32_t>(row) * row_height,
|
||||
.width = row_width,
|
||||
.height = row_height},
|
||||
title,
|
||||
"",
|
||||
index == state.selected_practice_exercise_index);
|
||||
}
|
||||
draw_row(context, row, title, "", selected);
|
||||
});
|
||||
if (exercises.empty()) {
|
||||
draw_text(context, bounds.x + 38.0F, list_y + row_height + 28.0F, "NO EXERCISES FOUND", 3, vamp_style::retrying, 440.0F);
|
||||
draw_text(context, bounds.x + 38.0F, bounds.y + 194.0F, "NO EXERCISES FOUND", 3, vamp_style::retrying, 440.0F);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,36 +267,10 @@ auto draw_practice_part_menu(luma::draw_context &context, luma::rect bounds, vam
|
||||
vamp_style::ink,
|
||||
bounds.width - 72.0F);
|
||||
draw_text(context, bounds.x + 38.0F, bounds.y + 66.0F, "SELECT PRACTICE PART", 1, vamp_style::muted, 360.0F);
|
||||
auto list_y = bounds.y + 112.0F;
|
||||
auto row_height = std::float32_t{54.0F};
|
||||
auto row_width = bounds.width - 72.0F;
|
||||
auto total_rows = (exercise == nullptr ? 0U : exercise->parts.size()) + 1U;
|
||||
auto max_rows = std::min<std::size_t>(total_rows, 7U);
|
||||
auto first = first_visible_row(state.selected_practice_part_index, total_rows, max_rows);
|
||||
for (auto row = std::size_t{}; row < max_rows; ++row) {
|
||||
auto index = first + row;
|
||||
if (index == 0U) {
|
||||
draw_row(context,
|
||||
{.x = bounds.x + 36.0F,
|
||||
.y = list_y + static_cast<std::float32_t>(row) * row_height,
|
||||
.width = row_width,
|
||||
.height = row_height},
|
||||
"BACK",
|
||||
"",
|
||||
state.selected_practice_part_index == 0U);
|
||||
continue;
|
||||
}
|
||||
auto part = exercise == nullptr ? std::string{} : exercise->parts[index - 1U].part;
|
||||
auto key = exercise == nullptr ? std::string{} : exercise->parts[index - 1U].key_signature;
|
||||
draw_row(context,
|
||||
{.x = bounds.x + 36.0F,
|
||||
.y = list_y + static_cast<std::float32_t>(row) * row_height,
|
||||
.width = row_width,
|
||||
.height = row_height},
|
||||
part,
|
||||
key,
|
||||
index == state.selected_practice_part_index);
|
||||
}
|
||||
draw_menu_rows(context, bounds, exercise == nullptr ? 0U : exercise->parts.size(), state.selected_practice_part_index, [&](std::size_t index, luma::rect row, std::bool_t selected) {
|
||||
auto const &part = exercise->parts[index];
|
||||
draw_row(context, row, part.part, part.key_signature, selected);
|
||||
});
|
||||
}
|
||||
|
||||
auto draw_score(luma::draw_context &context, luma::rect bounds, vamp_zero::app_state const &state, vamp_zero::score_load_state const &loaded, score_draw_cache &score_cache) -> void {
|
||||
|
||||
Reference in New Issue
Block a user