161 lines
5.2 KiB
C++
161 lines
5.2 KiB
C++
|
// MassBuilderSaveTool
|
||
|
// Copyright (C) 2021 Guillaume Jacquemin
|
||
|
//
|
||
|
// This program is free software: you can redistribute it and/or modify
|
||
|
// it under the terms of the GNU General Public License as published by
|
||
|
// the Free Software Foundation, either version 3 of the License, or
|
||
|
// (at your option) any later version.
|
||
|
//
|
||
|
// This program is distributed in the hope that it will be useful,
|
||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
// GNU General Public License for more details.
|
||
|
//
|
||
|
// You should have received a copy of the GNU General Public License
|
||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||
|
|
||
|
#include <Corrade/Utility/FormatStl.h>
|
||
|
|
||
|
#include <Magnum/Math/Functions.h>
|
||
|
|
||
|
#include <imgui.h>
|
||
|
|
||
|
#include "../FontAwesome/IconsFontAwesome5.h"
|
||
|
|
||
|
#include "ToastQueue.h"
|
||
|
|
||
|
using namespace Corrade;
|
||
|
|
||
|
constexpr UnsignedInt success_colour = 0xff67d23bu;
|
||
|
constexpr UnsignedInt info_colour = 0xffcc832fu;
|
||
|
constexpr UnsignedInt warning_colour = 0xff2fcfc7u;
|
||
|
constexpr UnsignedInt error_colour = 0xff3134cdu;
|
||
|
|
||
|
constexpr UnsignedInt fade_time = 150;
|
||
|
constexpr Float base_opacity = 1.0f;
|
||
|
constexpr Vector2 padding{20.0f, 20.0f};
|
||
|
constexpr Float toast_spacing = 10.0f;
|
||
|
|
||
|
Toast::Toast(Type type, const std::string& message, std::chrono::milliseconds timeout):
|
||
|
_type{type}, _message{message}, _timeout{timeout}, _creationTime{std::chrono::steady_clock::now()}
|
||
|
{
|
||
|
_phaseTrack = Animation::Track<UnsignedInt, Phase>{{
|
||
|
{0, Phase::FadeIn},
|
||
|
{fade_time, Phase::Wait},
|
||
|
{fade_time + timeout.count(), Phase::FadeOut},
|
||
|
{(fade_time * 2) + timeout.count(), Phase::TimedOut}
|
||
|
}, Math::select, Animation::Extrapolation::Constant};
|
||
|
}
|
||
|
|
||
|
auto Toast::type() -> Type {
|
||
|
return _type;
|
||
|
}
|
||
|
|
||
|
auto Toast::message() -> const std::string& {
|
||
|
return _message;
|
||
|
}
|
||
|
|
||
|
auto Toast::timeout() -> std::chrono::milliseconds {
|
||
|
return _timeout;
|
||
|
}
|
||
|
|
||
|
auto Toast::creationTime() -> std::chrono::steady_clock::time_point {
|
||
|
return _creationTime;
|
||
|
}
|
||
|
|
||
|
auto Toast::elapsedTime() -> std::chrono::milliseconds {
|
||
|
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - _creationTime);
|
||
|
}
|
||
|
|
||
|
auto Toast::phase() -> Phase {
|
||
|
return _phaseTrack.at(elapsedTime().count());
|
||
|
}
|
||
|
|
||
|
auto Toast::opacity() -> Float {
|
||
|
Phase phase = this->phase();
|
||
|
Long elapsed_time = elapsedTime().count();
|
||
|
|
||
|
if(phase == Phase::FadeIn) {
|
||
|
return Float(elapsed_time) / Float(fade_time);
|
||
|
}
|
||
|
else if(phase == Phase::FadeOut) {
|
||
|
return 1.0f - ((Float(elapsed_time) - Float(fade_time) - Float(_timeout.count())) / Float(fade_time));
|
||
|
}
|
||
|
|
||
|
return 1.0f;
|
||
|
}
|
||
|
|
||
|
void ToastQueue::addToast(Toast&& toast) {
|
||
|
_toasts.push_back(std::move(toast));
|
||
|
}
|
||
|
|
||
|
void ToastQueue::addToast(Toast::Type type, const std::string& message, std::chrono::milliseconds timeout) {
|
||
|
_toasts.emplace_back(type, message, timeout);
|
||
|
}
|
||
|
|
||
|
void ToastQueue::draw(Vector2i viewport_size) {
|
||
|
Float height = 0.0f;
|
||
|
|
||
|
for(UnsignedInt i = 0; i < _toasts.size(); i++) {
|
||
|
Toast* current = &_toasts[i];
|
||
|
|
||
|
if(current->phase() == Toast::Phase::TimedOut) {
|
||
|
removeToast(i);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
std::string win_id = Utility::formatString("##Toast{}", i);
|
||
|
|
||
|
Float opacity = base_opacity * current->opacity();
|
||
|
|
||
|
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, opacity);
|
||
|
|
||
|
ImGui::SetNextWindowPos({viewport_size.x() - padding.x(), viewport_size.y() - padding.y() - height}, ImGuiCond_Always, {1.0f, 1.0f});
|
||
|
if(ImGui::Begin(win_id.c_str(), nullptr,
|
||
|
ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoDecoration|
|
||
|
ImGuiWindowFlags_NoInputs|ImGuiWindowFlags_NoNav|ImGuiWindowFlags_NoFocusOnAppearing))
|
||
|
{
|
||
|
ImColor colour = 0xffffffff;
|
||
|
|
||
|
switch(current->type()) {
|
||
|
case Toast::Type::Default:
|
||
|
break;
|
||
|
case Toast::Type::Success:
|
||
|
colour = success_colour;
|
||
|
ImGui::TextColored(colour, ICON_FA_CHECK_CIRCLE);
|
||
|
break;
|
||
|
case Toast::Type::Info:
|
||
|
colour = info_colour;
|
||
|
ImGui::TextColored(colour, ICON_FA_INFO_CIRCLE);
|
||
|
break;
|
||
|
case Toast::Type::Warning:
|
||
|
colour = warning_colour;
|
||
|
ImGui::TextColored(colour, ICON_FA_EXCLAMATION_TRIANGLE);
|
||
|
break;
|
||
|
case Toast::Type::Error:
|
||
|
colour = error_colour;
|
||
|
ImGui::TextColored(colour, ICON_FA_TIMES_CIRCLE);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
ImGui::SameLine();
|
||
|
|
||
|
if(current->message().length() > 127) {
|
||
|
ImGui::TextColored(colour, "%.*s...", 127, current->message().c_str());
|
||
|
}
|
||
|
else {
|
||
|
ImGui::TextColored(colour, current->message().c_str());
|
||
|
}
|
||
|
|
||
|
height += ImGui::GetWindowHeight() + toast_spacing;
|
||
|
}
|
||
|
ImGui::End();
|
||
|
|
||
|
ImGui::PopStyleVar();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ToastQueue::removeToast(Long index) {
|
||
|
_toasts.erase(_toasts.begin() + index);
|
||
|
}
|