New UI: Achievement toasts (#690)

* Rename Overlay -> GraphicsTuner, Popup -> MenuBar

* Update GraphicsTuner CSS

* WIP Overlay document & toasts

* Achievement toasts

* Cleanup
This commit is contained in:
Luke Street
2026-05-05 19:29:42 -06:00
committed by GitHub
parent 945ce3e4bc
commit 93ec3c7dbd
19 changed files with 798 additions and 574 deletions
+38 -12
View File
@@ -21,7 +21,10 @@ void load_font(const char* filename, bool fallback = false) {
}
bool sInitialized = false;
std::vector<std::unique_ptr<Document> > sDocuments;
std::vector<std::unique_ptr<Document> > sDocumentStack;
// Documents that don't participate in the focus stack
std::vector<std::unique_ptr<Document> > sPassiveDocuments;
std::deque<Toast> sToasts;
} // namespace
@@ -46,15 +49,20 @@ bool initialize() noexcept {
}
void shutdown() noexcept {
sDocuments.clear();
sDocumentStack.clear();
sPassiveDocuments.clear();
reset_input_state();
release_input_block();
sInitialized = false;
}
Document& push_document(std::unique_ptr<Document> doc, bool show) noexcept {
Document& push_document(std::unique_ptr<Document> doc, bool show, bool passive) noexcept {
Document& ret = *doc;
sDocuments.push_back({std::move(doc)});
if (passive) {
sPassiveDocuments.push_back(std::move(doc));
} else {
sDocumentStack.push_back({std::move(doc)});
}
if (show) {
ret.show();
}
@@ -70,19 +78,19 @@ void show_top_document() noexcept {
}
bool any_document_visible() noexcept {
return std::any_of(sDocuments.begin(), sDocuments.end(),
return std::any_of(sDocumentStack.begin(), sDocumentStack.end(),
[](const auto& doc) { return doc && doc->visible(); });
}
bool is_prelaunch_open() noexcept {
return std::any_of(sDocuments.begin(), sDocuments.end(), [](const auto& doc) {
return std::any_of(sDocumentStack.begin(), sDocumentStack.end(), [](const auto& doc) {
const auto* prelaunch = dynamic_cast<const Prelaunch*>(doc.get());
return prelaunch != nullptr && !prelaunch->pending_close() && !prelaunch->closed();
});
}
Document* top_document() noexcept {
for (auto& doc : std::views::reverse(sDocuments)) {
for (auto& doc : std::views::reverse(sDocumentStack)) {
if (!doc->closed() && !doc->pending_close()) {
return doc.get();
}
@@ -92,21 +100,31 @@ Document* top_document() noexcept {
void update() noexcept {
update_input();
for (const auto& doc : sDocuments) {
for (const auto& doc : sDocumentStack) {
doc->update();
}
for (const auto& doc : sPassiveDocuments) {
doc->update();
}
// Remove closed documents
const auto [first, last] =
std::ranges::remove_if(sDocuments, [](const auto& doc) { return doc->closed(); });
sDocuments.erase(first, last);
{
const auto [first, last] =
std::ranges::remove_if(sDocumentStack, [](const auto& doc) { return doc->closed(); });
sDocumentStack.erase(first, last);
}
{
const auto [first, last] = std::ranges::remove_if(
sPassiveDocuments, [](const auto& doc) { return doc->closed(); });
sPassiveDocuments.erase(first, last);
}
// If no documents have focus, explicitly focus the top one
if (auto* context = aurora::rmlui::get_context();
context != nullptr && (context->GetFocusElement() == nullptr ||
context->GetFocusElement() == context->GetRootElement()))
{
for (auto& doc : std::views::reverse(sDocuments)) {
for (auto& doc : std::views::reverse(sDocumentStack)) {
if (!doc->closed() && !doc->pending_close() && doc->focus()) {
break;
}
@@ -221,4 +239,12 @@ Insets safe_area_insets(Rml::Context* context) noexcept {
};
}
void push_toast(Toast toast) noexcept {
sToasts.push_back(std::move(toast));
}
std::deque<Toast>& get_toasts() noexcept {
return sToasts;
}
} // namespace dusk::ui