mirror of
https://github.com/izzy2lost/2ship2harkinian-Android.git
synced 2026-06-19 01:20:08 -07:00
Implement simple notifications system (#816)
* Implement simple notifications system * Remove demoWindow call * Fix initializer order
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
#include <Fast3D/gfx_pc.h>
|
||||
#include "UIWidgets.hpp"
|
||||
#include "HudEditor.h"
|
||||
#include "Notification.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include "graphic/Fast3D/gfx_metal.h"
|
||||
@@ -36,6 +37,7 @@ std::shared_ptr<CollisionViewerWindow> mCollisionViewerWindow;
|
||||
std::shared_ptr<EventLogWindow> mEventLogWindow;
|
||||
std::shared_ptr<BenMenu> mBenMenu;
|
||||
std::shared_ptr<BenInputEditorWindow> mBenInputEditorWindow;
|
||||
std::shared_ptr<Notification::Window> mNotificationWindow;
|
||||
|
||||
void SetupGuiElements() {
|
||||
auto gui = Ship::Context::GetInstance()->GetWindow()->GetGui();
|
||||
@@ -93,6 +95,10 @@ void SetupGuiElements() {
|
||||
mEventLogWindow = std::make_shared<EventLogWindow>("gWindows.EventLog", "Event Log", ImVec2(520, 600));
|
||||
gui->AddGuiWindow(mEventLogWindow);
|
||||
gui->SetPadBtnTogglesMenu();
|
||||
|
||||
mNotificationWindow = std::make_shared<Notification::Window>("gWindows.Notifications", "Notifications Window");
|
||||
gui->AddGuiWindow(mNotificationWindow);
|
||||
mNotificationWindow->Show();
|
||||
}
|
||||
|
||||
void Destroy() {
|
||||
@@ -104,6 +110,7 @@ void Destroy() {
|
||||
mGfxDebuggerWindow = nullptr;
|
||||
mCollisionViewerWindow = nullptr;
|
||||
mEventLogWindow = nullptr;
|
||||
mNotificationWindow = nullptr;
|
||||
|
||||
mSaveEditorWindow = nullptr;
|
||||
mHudEditorWindow = nullptr;
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
|
||||
#include "Notification.h"
|
||||
#include <libultraship/libultraship.h>
|
||||
|
||||
extern "C" {
|
||||
#include "functions.h"
|
||||
#include "macros.h"
|
||||
#include "variables.h"
|
||||
}
|
||||
|
||||
namespace Notification {
|
||||
|
||||
static uint32_t nextId = 0;
|
||||
static std::vector<Options> notifications = {};
|
||||
|
||||
void Window::Draw() {
|
||||
auto vp = ImGui::GetMainViewport();
|
||||
|
||||
const float margin = 30.0f;
|
||||
const float padding = 10.0f;
|
||||
|
||||
int position = CVarGetInteger("gNotifications.Position", 3);
|
||||
|
||||
// Top Left
|
||||
ImVec2 basePosition;
|
||||
switch (position) {
|
||||
case 0: // Top Left
|
||||
basePosition = ImVec2(vp->Pos.x + margin, vp->Pos.y + margin);
|
||||
break;
|
||||
case 1: // Top Right
|
||||
basePosition = ImVec2(vp->Pos.x + vp->Size.x - margin, vp->Pos.y + margin);
|
||||
break;
|
||||
case 2: // Bottom Left
|
||||
basePosition = ImVec2(vp->Pos.x + margin, vp->Pos.y + vp->Size.y - margin);
|
||||
break;
|
||||
case 3: // Bottom Right
|
||||
basePosition = ImVec2(vp->Pos.x + vp->Size.x - margin, vp->Pos.y + vp->Size.y - margin);
|
||||
break;
|
||||
case 4: // Hidden
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, CVarGetFloat("gNotifications.BgOpacity", 0.5f)));
|
||||
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 4.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(8.0f * CVarGetFloat("gNotifications.Size", 1.8f), 6.0f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8.0f * CVarGetFloat("gNotifications.Size", 1.8f), 8.0f));
|
||||
|
||||
for (int index = 0; index < notifications.size(); ++index) {
|
||||
auto& notification = notifications[index];
|
||||
int inverseIndex = -ABS(index - (notifications.size() - 1));
|
||||
|
||||
ImGui::SetNextWindowViewport(vp->ID);
|
||||
if (notification.remainingTime < 4.0f) {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, (notification.remainingTime - 1) / 3.0f);
|
||||
} else {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 1.0f);
|
||||
}
|
||||
|
||||
ImGui::Begin(("notification#" + std::to_string(notification.id)).c_str(), nullptr,
|
||||
ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoFocusOnAppearing |
|
||||
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoTitleBar |
|
||||
ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove |
|
||||
ImGuiWindowFlags_NoScrollbar);
|
||||
|
||||
ImGui::SetWindowFontScale(CVarGetFloat("gNotifications.Size", 1.8f));
|
||||
|
||||
ImVec2 notificationPos;
|
||||
switch (position) {
|
||||
case 0: // Top Left
|
||||
notificationPos =
|
||||
ImVec2(basePosition.x, basePosition.y + ((ImGui::GetWindowSize().y + padding) * inverseIndex));
|
||||
break;
|
||||
case 1: // Top Right
|
||||
notificationPos = ImVec2(basePosition.x - ImGui::GetWindowSize().x,
|
||||
basePosition.y + ((ImGui::GetWindowSize().y + padding) * inverseIndex));
|
||||
break;
|
||||
case 2: // Bottom Left
|
||||
notificationPos = ImVec2(basePosition.x,
|
||||
basePosition.y - ((ImGui::GetWindowSize().y + padding) * (inverseIndex + 1)));
|
||||
break;
|
||||
case 3: // Bottom Right
|
||||
notificationPos = ImVec2(basePosition.x - ImGui::GetWindowSize().x,
|
||||
basePosition.y - ((ImGui::GetWindowSize().y + padding) * (inverseIndex + 1)));
|
||||
break;
|
||||
}
|
||||
|
||||
ImGui::SetWindowPos(notificationPos);
|
||||
ImGui::AlignTextToFramePadding();
|
||||
|
||||
if (notification.itemIcon != nullptr) {
|
||||
ImGui::Image(
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(notification.itemIcon),
|
||||
ImVec2(22 * CVarGetFloat("gNotifications.Size", 1.8f), 22 * CVarGetFloat("gNotifications.Size", 1.8f)));
|
||||
ImGui::SameLine();
|
||||
}
|
||||
if (!notification.prefix.empty()) {
|
||||
ImGui::TextColored(notification.prefixColor, "%s", notification.prefix.c_str());
|
||||
ImGui::SameLine();
|
||||
}
|
||||
ImGui::TextColored(notification.messageColor, "%s", notification.message.c_str());
|
||||
if (!notification.suffix.empty()) {
|
||||
ImGui::SameLine();
|
||||
ImGui::TextColored(notification.suffixColor, "%s", notification.suffix.c_str());
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
|
||||
ImGui::PopStyleVar(3);
|
||||
ImGui::PopStyleColor(2);
|
||||
}
|
||||
|
||||
void Window::UpdateElement() {
|
||||
for (int index = 0; index < notifications.size(); ++index) {
|
||||
auto& notification = notifications[index];
|
||||
|
||||
// decrement remainingTime
|
||||
notification.remainingTime -= ImGui::GetIO().DeltaTime;
|
||||
|
||||
// remove notification if it has expired
|
||||
if (notification.remainingTime <= 0) {
|
||||
notifications.erase(notifications.begin() + index);
|
||||
--index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Emit(Options notification) {
|
||||
notification.id = nextId++;
|
||||
if (notification.remainingTime == 0.0f) {
|
||||
notification.remainingTime = CVarGetFloat("gNotifications.Duration", 10.0f);
|
||||
}
|
||||
notifications.push_back(notification);
|
||||
AudioSfx_PlaySfx(NA_SE_SY_METRONOME, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
|
||||
&gSfxDefaultReverb);
|
||||
}
|
||||
|
||||
} // namespace Notification
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifndef NOTIFICATION_H
|
||||
#define NOTIFICATION_H
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <string>
|
||||
#include <libultraship/libultraship.h>
|
||||
|
||||
namespace Notification {
|
||||
|
||||
struct Options {
|
||||
uint32_t id = 0;
|
||||
const char* itemIcon = nullptr;
|
||||
std::string prefix = "";
|
||||
ImVec4 prefixColor = ImVec4(0.5f, 0.5f, 1.0f, 1.0f);
|
||||
std::string message = "";
|
||||
ImVec4 messageColor = ImVec4(0.7f, 0.7f, 0.7f, 1.0f);
|
||||
std::string suffix = "";
|
||||
ImVec4 suffixColor = ImVec4(1.0f, 0.5f, 0.5f, 1.0f);
|
||||
float remainingTime = 0.0f; // Seconds
|
||||
};
|
||||
|
||||
class Window : public Ship::GuiWindow {
|
||||
public:
|
||||
using GuiWindow::GuiWindow;
|
||||
|
||||
void InitElement() override{};
|
||||
void DrawElement() override{};
|
||||
void Draw() override;
|
||||
void UpdateElement() override;
|
||||
};
|
||||
|
||||
void Emit(Options notification);
|
||||
|
||||
} // namespace Notification
|
||||
|
||||
#endif // __cplusplus
|
||||
#endif // NOTIFICATION_H
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "2s2h/DeveloperTools/DeveloperTools.h"
|
||||
#include "UIWidgets.hpp"
|
||||
#include "BenMenuBar.h"
|
||||
#include "Notification.h"
|
||||
#include "macros.h"
|
||||
#include "variables.h"
|
||||
#include <variant>
|
||||
@@ -420,6 +421,10 @@ static const std::unordered_map<int32_t, const char*> timeStopOptions = {
|
||||
{ TIME_STOP_TEMPLES_DUNGEONS, "Temples + Mini Dungeons" },
|
||||
};
|
||||
|
||||
static const std::unordered_map<int32_t, const char*> notificationPosition = {
|
||||
{ 0, "Top Left" }, { 1, "Top Right" }, { 2, "Bottom Left" }, { 3, "Bottom Right" }, { 4, "Hidden" },
|
||||
};
|
||||
|
||||
void FreeLookPitchMinMax() {
|
||||
f32 maxY = CVarGetFloat("gEnhancements.Camera.FreeLook.MaxPitch", 72.0f);
|
||||
f32 minY = CVarGetFloat("gEnhancements.Camera.FreeLook.MinPitch", -49.0f);
|
||||
@@ -716,6 +721,44 @@ void AddSettings() {
|
||||
WIDGET_WINDOW_BUTTON,
|
||||
{ .size = UIWidgets::Sizes::Inline, .windowName = "2S2H Input Editor" } } } } });
|
||||
|
||||
settingsSidebar.push_back({ "Notifications",
|
||||
1,
|
||||
{ {
|
||||
{ "Position",
|
||||
"gNotifications.Position",
|
||||
"Which corner of the screen notifications appear in.",
|
||||
WIDGET_CVAR_COMBOBOX,
|
||||
{ .defaultVariant = 3, .comboBoxOptions = notificationPosition } },
|
||||
{ "Duration: %.0f seconds",
|
||||
"gNotifications.Duration",
|
||||
"How long notifications are displayed for.",
|
||||
WIDGET_CVAR_SLIDER_FLOAT,
|
||||
{ .min = 300.0f, .max = 3000.0f, .defaultVariant = 1000.0f } },
|
||||
{ "Background Opacity: %.0f%%",
|
||||
"gNotifications.BgOpacity",
|
||||
"How opaque the background of notifications is.",
|
||||
WIDGET_CVAR_SLIDER_FLOAT,
|
||||
{ .min = 0.0f, .max = 100.0f, .defaultVariant = 50.0f, .isPercentage = true } },
|
||||
{ "Size %.1f",
|
||||
"gNotifications.Size",
|
||||
"How large notifications are.",
|
||||
WIDGET_CVAR_SLIDER_FLOAT,
|
||||
{ .min = 100.0f, .max = 500.0f, .defaultVariant = 180.0f } },
|
||||
{ "Test Notification",
|
||||
"",
|
||||
"Displays a test notification.",
|
||||
WIDGET_BUTTON,
|
||||
{},
|
||||
[](widgetInfo& info) {
|
||||
Notification::Emit({
|
||||
.itemIcon = "__OTR__icon_item_24_static_yar/gQuestIconGoldSkulltulaTex",
|
||||
.prefix = "This",
|
||||
.message = "is a",
|
||||
.suffix = "test.",
|
||||
});
|
||||
} },
|
||||
} } });
|
||||
|
||||
if (CVarGetInteger("gSettings.SidebarSearch", 0)) {
|
||||
settingsSidebar.insert(settingsSidebar.begin() + searchSidebarIndex, searchSidebarEntry);
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ CrowdControl* CrowdControl::Instance;
|
||||
#include "2s2h/DeveloperTools/DebugConsole.h"
|
||||
#include "2s2h/DeveloperTools/DeveloperTools.h"
|
||||
#include "2s2h/SaveManager/SaveManager.h"
|
||||
#include "2s2h/ShipUtils.h"
|
||||
|
||||
// Resource Types/Factories
|
||||
#include "resource/type/Blob.h"
|
||||
@@ -512,6 +513,7 @@ extern "C" void InitOTR() {
|
||||
|
||||
OTRGlobals::Instance = new OTRGlobals();
|
||||
GameInteractor::Instance = new GameInteractor();
|
||||
LoadGuiTextures();
|
||||
BenGui::SetupGuiElements();
|
||||
InitEnhancements();
|
||||
InitDeveloperTools();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "SaveEditor.h"
|
||||
#include "2s2h/BenGui/UIWidgets.hpp"
|
||||
#include "2s2h/GameInteractor/GameInteractor.h"
|
||||
#include "2s2h/BenGui/Notification.h"
|
||||
|
||||
#include "interface/icon_item_dungeon_static/icon_item_dungeon_static.h"
|
||||
#include "archives/icon_item_24_static/icon_item_24_static_yar.h"
|
||||
@@ -2011,24 +2012,6 @@ void SaveEditorWindow::DrawElement() {
|
||||
}
|
||||
}
|
||||
|
||||
const char* textureLoad[8] = { gDungeonStrayFairyWoodfallIconTex,
|
||||
gDungeonStrayFairySnowheadIconTex,
|
||||
gDungeonStrayFairyGreatBayIconTex,
|
||||
gDungeonStrayFairyStoneTowerIconTex,
|
||||
gQuestIconDungeonMapTex,
|
||||
gQuestIconCompassTex,
|
||||
gQuestIconSmallKeyTex,
|
||||
gQuestIconBossKeyTex };
|
||||
|
||||
void SaveEditorWindow::InitElement() {
|
||||
initSafeItemsForInventorySlot();
|
||||
|
||||
for (TexturePtr entry : gItemIcons) {
|
||||
const char* path = static_cast<const char*>(entry);
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(path, path, ImVec4(1, 1, 1, 1));
|
||||
}
|
||||
for (int i = 0; i <= 7; i++) {
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(textureLoad[i], textureLoad[i],
|
||||
ImVec4(1, 1, 1, 1));
|
||||
}
|
||||
}
|
||||
|
||||
+19
-2
@@ -1,6 +1,5 @@
|
||||
#include "ShipUtils.h"
|
||||
#include <libultraship/libultra.h>
|
||||
#include "PR/ultratypes.h"
|
||||
#include <libultraship/libultraship.h>
|
||||
#include "assets/2s2h_assets.h"
|
||||
|
||||
extern "C" {
|
||||
@@ -8,6 +7,9 @@ extern "C" {
|
||||
|
||||
extern f32 sNESFontWidths[160];
|
||||
extern const char* fontTbl[156];
|
||||
extern TexturePtr gItemIcons[131];
|
||||
extern TexturePtr gQuestIcons[14];
|
||||
extern TexturePtr gBombersNotebookPhotos[24];
|
||||
}
|
||||
|
||||
// Build vertex coordinates for a quad command
|
||||
@@ -54,3 +56,18 @@ extern "C" TexturePtr Ship_GetCharFontTextureNES(u8 character) {
|
||||
|
||||
return (TexturePtr)fontTbl[adjustedChar];
|
||||
}
|
||||
|
||||
void LoadGuiTextures() {
|
||||
for (TexturePtr entry : gItemIcons) {
|
||||
const char* path = static_cast<const char*>(entry);
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(path, path, ImVec4(1, 1, 1, 1));
|
||||
}
|
||||
for (TexturePtr entry : gQuestIcons) {
|
||||
const char* path = static_cast<const char*>(entry);
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(path, path, ImVec4(1, 1, 1, 1));
|
||||
}
|
||||
for (TexturePtr entry : gBombersNotebookPhotos) {
|
||||
const char* path = static_cast<const char*>(entry);
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(path, path, ImVec4(1, 1, 1, 1));
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -1,10 +1,13 @@
|
||||
#ifndef SHIP_UTILS_H
|
||||
#define SHIP_UTILS_H
|
||||
|
||||
#include <libultraship/libultra.h>
|
||||
#include <libultraship/libultraship.h>
|
||||
#include "PR/ultratypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
void LoadGuiTextures();
|
||||
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user