mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-06-15 13:41:31 -04:00
Copy more imgui stuff from Metaforce
This commit is contained in:
@@ -134,6 +134,13 @@ target_compile_definitions(dusk PRIVATE TARGET_PC AVOID_UB=1 VERSION=0)
|
||||
target_include_directories(dusk PRIVATE include)
|
||||
target_link_libraries(dusk PRIVATE game aurora::main)
|
||||
|
||||
add_custom_command(TARGET dusk POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
"${CMAKE_SOURCE_DIR}/res"
|
||||
"$<TARGET_FILE_DIR:dusk>/res"
|
||||
COMMENT "Copying resources"
|
||||
)
|
||||
|
||||
include(extern/aurora/cmake/AuroraCopyRuntimeDLLs.cmake)
|
||||
aurora_copy_runtime_dlls(dusk game)
|
||||
|
||||
|
||||
Vendored
+1
-1
Submodule extern/aurora updated: 33ec54347d...37631c3bf3
@@ -1344,6 +1344,8 @@ set(DUSK_FILES
|
||||
#src/dusk/m_Do_ext_dusk.cpp
|
||||
src/dusk/imgui/ImGuiConsole.hpp
|
||||
src/dusk/imgui/ImGuiConsole.cpp
|
||||
src/dusk/imgui/ImGuiEngine.cpp
|
||||
src/dusk/imgui/ImGuiEngine.hpp
|
||||
src/dusk/imgui/ImGuiMenuGame.cpp
|
||||
src/dusk/imgui/ImGuiMenuGame.hpp
|
||||
src/dusk/imgui/ImGuiMenuTools.cpp
|
||||
|
||||
Binary file not shown.
@@ -26,7 +26,8 @@ namespace dusk {
|
||||
}
|
||||
|
||||
ImGui::SetNextWindowBgAlpha(0.65f);
|
||||
ImGui::SetNextWindowSizeConstraints(ImVec2(300, 0), ImVec2(FLT_MAX, FLT_MAX));
|
||||
ImGui::SetNextWindowSizeConstraints(ImVec2(300.f * ImGuiScale(), 0),
|
||||
ImVec2(FLT_MAX, FLT_MAX));
|
||||
|
||||
if (!ImGui::Begin("Camera Debug", nullptr, windowFlags)) {
|
||||
ImGui::End();
|
||||
|
||||
@@ -21,6 +21,8 @@ using namespace std::string_literals;
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
namespace dusk {
|
||||
float ImGuiScale() { return ImGui::GetIO().DisplayFramebufferScale.x; }
|
||||
|
||||
void ImGuiStringViewText(std::string_view text) {
|
||||
// begin()/end() do not work on MSVC
|
||||
ImGui::TextUnformatted(text.data(), text.data() + text.size());
|
||||
@@ -47,7 +49,7 @@ namespace dusk {
|
||||
ImVec2 workSize = viewport->WorkSize;
|
||||
ImVec2 windowPos;
|
||||
ImVec2 windowPosPivot;
|
||||
constexpr float padding = 10.0f;
|
||||
const float padding = 10.0f * ImGuiScale();
|
||||
windowPos.x = (corner & 1) != 0 ? (workPos.x + workSize.x - padding) : (workPos.x + padding);
|
||||
windowPos.y = (corner & 2) != 0 ? (workPos.y + workSize.y - padding) : (workPos.y + padding);
|
||||
windowPosPivot.x = (corner & 1) != 0 ? 1.0f : 0.0f;
|
||||
@@ -173,23 +175,32 @@ namespace dusk {
|
||||
ImGuiConsole::ImGuiConsole() {}
|
||||
|
||||
void ImGuiConsole::draw() {
|
||||
if (!m_isLaunchInitialized) {
|
||||
m_toasts.emplace_back("Press F1 to toggle menu"s, 5.f);
|
||||
m_isLaunchInitialized = true;
|
||||
}
|
||||
|
||||
if (CheckMenuViewToggle(ImGuiKey_F1, m_isHidden)) {
|
||||
ShowToasts();
|
||||
m_menuTools.afterDraw();
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: we need to be able to render the menu bar & any overlays separately
|
||||
// The code currently ties them all together, so hiding the menu hides all windows
|
||||
|
||||
if (ImGui::BeginMainMenuBar()) {
|
||||
m_menuGame.draw();
|
||||
m_menuTools.draw();
|
||||
m_menuEnhancements.draw();
|
||||
|
||||
ImGui::SetCursorPosX(ImGui::GetWindowWidth() - 80.0f);
|
||||
ImGui::SetCursorPosX(ImGui::GetWindowWidth() - 80.0f * ImGuiScale());
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiStringViewText(fmt::format(FMT_STRING("FPS: {:.2f}\n"), io.Framerate));
|
||||
|
||||
ImGui::EndMainMenuBar();
|
||||
}
|
||||
|
||||
ShowToasts();
|
||||
m_menuTools.afterDraw();
|
||||
}
|
||||
|
||||
@@ -223,4 +234,44 @@ namespace dusk {
|
||||
return "Null"sv;
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiConsole::ShowToasts() {
|
||||
if (m_toasts.empty()) {
|
||||
return;
|
||||
}
|
||||
auto& toast = m_toasts.front();
|
||||
const float dt = ImGui::GetIO().DeltaTime;
|
||||
toast.remain -= dt;
|
||||
toast.current += dt;
|
||||
|
||||
const ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||
const ImVec2 workPos = viewport->WorkPos;
|
||||
const ImVec2 workSize = viewport->WorkSize;
|
||||
constexpr float padding = 10.0f;
|
||||
const ImVec2 windowPos{workPos.x + workSize.x / 2, workPos.y + workSize.y - padding};
|
||||
ImGui::SetNextWindowPos(windowPos, ImGuiCond_Always, ImVec2{0.5f, 1.f});
|
||||
|
||||
const float alpha = std::min({toast.remain, toast.current, 1.f});
|
||||
ImGui::SetNextWindowBgAlpha(alpha * 0.65f);
|
||||
ImVec4 textColor = ImGui::GetStyleColorVec4(ImGuiCol_Text);
|
||||
textColor.w *= alpha;
|
||||
ImVec4 borderColor = ImGui::GetStyleColorVec4(ImGuiCol_Border);
|
||||
borderColor.w *= alpha;
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, textColor);
|
||||
ImGui::PushStyleColor(ImGuiCol_Border, borderColor);
|
||||
if (ImGui::Begin("Toast", nullptr,
|
||||
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize |
|
||||
ImGuiWindowFlags_NoSavedSettings |
|
||||
ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav |
|
||||
ImGuiWindowFlags_NoMove))
|
||||
{
|
||||
ImGuiStringViewText(toast.message);
|
||||
}
|
||||
ImGui::End();
|
||||
ImGui::PopStyleColor(2);
|
||||
|
||||
if (toast.remain <= 0.f) {
|
||||
m_toasts.pop_front();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,41 +2,56 @@
|
||||
#define DUSK_IMGUI_HPP
|
||||
|
||||
#include <aurora/aurora.h>
|
||||
#include <deque>
|
||||
#include <string>
|
||||
|
||||
#include "imgui.h"
|
||||
#include "ImGuiMenuEnhancements.hpp"
|
||||
#include "ImGuiMenuGame.hpp"
|
||||
#include "ImGuiMenuTools.hpp"
|
||||
#include "ImGuiMenuEnhancements.hpp"
|
||||
#include "imgui.h"
|
||||
|
||||
namespace dusk {
|
||||
class ImGuiConsole {
|
||||
public:
|
||||
ImGuiConsole();
|
||||
void draw();
|
||||
class ImGuiConsole {
|
||||
public:
|
||||
ImGuiConsole();
|
||||
void draw();
|
||||
|
||||
ImGuiMenuTools::CollisionViewSettings& getCollisionViewSettings() { return m_menuTools.getCollisionViewSettings(); }
|
||||
ImGuiMenuTools::CollisionViewSettings& getCollisionViewSettings() {
|
||||
return m_menuTools.getCollisionViewSettings();
|
||||
}
|
||||
|
||||
static bool CheckMenuViewToggle(ImGuiKey key, bool& active);
|
||||
static bool CheckMenuViewToggle(ImGuiKey key, bool& active);
|
||||
|
||||
private:
|
||||
bool m_isHidden = false;
|
||||
private:
|
||||
struct Toast {
|
||||
std::string message;
|
||||
float remain;
|
||||
float current = 0.f;
|
||||
Toast(std::string message, float duration) noexcept : message(std::move(message)),
|
||||
remain(duration) {}
|
||||
};
|
||||
|
||||
ImGuiMenuGame m_menuGame;
|
||||
ImGuiMenuTools m_menuTools;
|
||||
ImGuiMenuEnhancements m_menuEnhancements;
|
||||
};
|
||||
bool m_isHidden = true;
|
||||
bool m_isLaunchInitialized = false;
|
||||
std::deque<Toast> m_toasts;
|
||||
ImGuiMenuGame m_menuGame;
|
||||
ImGuiMenuTools m_menuTools;
|
||||
ImGuiMenuEnhancements m_menuEnhancements;
|
||||
|
||||
extern ImGuiConsole g_imguiConsole;
|
||||
void ShowToasts();
|
||||
};
|
||||
|
||||
std::string_view backend_name(AuroraBackend backend);
|
||||
std::string BytesToString(size_t bytes);
|
||||
void SetOverlayWindowLocation(int corner);
|
||||
bool ShowCornerContextMenu(int& corner, int avoidCorner);
|
||||
void ImGuiStringViewText(std::string_view text);
|
||||
void ImGuiBeginGroupPanel(const char* name, const ImVec2& size);
|
||||
void ImGuiEndGroupPanel();
|
||||
}
|
||||
extern ImGuiConsole g_imguiConsole;
|
||||
|
||||
std::string_view backend_name(AuroraBackend backend);
|
||||
std::string BytesToString(size_t bytes);
|
||||
void SetOverlayWindowLocation(int corner);
|
||||
bool ShowCornerContextMenu(int& corner, int avoidCorner);
|
||||
void ImGuiStringViewText(std::string_view text);
|
||||
void ImGuiBeginGroupPanel(const char* name, const ImVec2& size);
|
||||
void ImGuiEndGroupPanel();
|
||||
float ImGuiScale();
|
||||
} // namespace dusk
|
||||
|
||||
void DuskDebugPad();
|
||||
|
||||
|
||||
@@ -13,8 +13,6 @@ namespace dusk {
|
||||
ImGui::TextUnformatted(text.c_str());
|
||||
}
|
||||
|
||||
static inline float GetScale() { return ImGui::GetCurrentContext()->CurrentDpiScale; }
|
||||
|
||||
void ImGuiMenuGame::windowInputViewer() {
|
||||
if (!m_showInputViewer) {
|
||||
return;
|
||||
@@ -35,7 +33,7 @@ namespace dusk {
|
||||
|
||||
ImGui::SetNextWindowBgAlpha(0.65f);
|
||||
if (ImGui::Begin("Input Viewer", nullptr, windowFlags)) {
|
||||
float scale = GetScale();
|
||||
float scale = ImGuiScale();
|
||||
if (!m_controllerName.empty()) {
|
||||
TextCenter(m_controllerName);
|
||||
ImGui::Separator();
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
#include "ImGuiEngine.hpp"
|
||||
|
||||
#include <SDL3/SDL_filesystem.h>
|
||||
#include <SDL3/SDL_pixels.h>
|
||||
#include <SDL3/SDL_surface.h>
|
||||
#include <aurora/imgui.h>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
#include "dusk/logging.h"
|
||||
|
||||
#ifdef IMGUI_ENABLE_FREETYPE
|
||||
#include "misc/freetype/imgui_freetype.h"
|
||||
#endif
|
||||
|
||||
namespace dusk {
|
||||
namespace {
|
||||
std::string GetAssetPath(const char* assetName) {
|
||||
const char* basePath = SDL_GetBasePath();
|
||||
if (basePath != nullptr && basePath[0] != '\0') {
|
||||
return std::string(basePath) + "res/" + assetName;
|
||||
}
|
||||
return std::string("res/") + assetName;
|
||||
}
|
||||
|
||||
bool AssetExists(const std::string& path) {
|
||||
SDL_PathInfo pathInfo{};
|
||||
return SDL_GetPathInfo(path.c_str(), &pathInfo) && pathInfo.type == SDL_PATHTYPE_FILE;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
ImFont* ImGuiEngine::fontNormal;
|
||||
ImFont* ImGuiEngine::fontLarge;
|
||||
ImTextureID ImGuiEngine::duskIcon;
|
||||
|
||||
void ImGuiEngine_Initialize(float scale) {
|
||||
ImGui::GetCurrentContext();
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.Fonts->Clear();
|
||||
|
||||
const std::string fontPath = GetAssetPath("NotoMono-Regular.ttf");
|
||||
const bool hasFontFile = AssetExists(fontPath);
|
||||
|
||||
ImFontConfig fontConfig{};
|
||||
fontConfig.SizePixels = std::floor(15.f * scale);
|
||||
snprintf(static_cast<char*>(fontConfig.Name), sizeof(fontConfig.Name),
|
||||
"Noto Mono Regular, %dpx", static_cast<int>(fontConfig.SizePixels));
|
||||
ImGuiEngine::fontNormal =
|
||||
hasFontFile ?
|
||||
io.Fonts->AddFontFromFileTTF(fontPath.c_str(), fontConfig.SizePixels, &fontConfig) :
|
||||
nullptr;
|
||||
if (ImGuiEngine::fontNormal == nullptr) {
|
||||
if (hasFontFile) {
|
||||
DuskLog.warn("Failed to load font '{}': {}", fontPath, SDL_GetError());
|
||||
}
|
||||
ImGuiEngine::fontNormal = io.Fonts->AddFontDefault(&fontConfig);
|
||||
}
|
||||
|
||||
fontConfig.SizePixels = std::floor(26.f * scale);
|
||||
#ifdef IMGUI_ENABLE_FREETYPE
|
||||
fontConfig.FontBuilderFlags |= ImGuiFreeTypeBuilderFlags_Bold;
|
||||
snprintf(static_cast<char*>(fontConfig.Name), sizeof(fontConfig.Name), "Noto Mono Bold, %dpx",
|
||||
static_cast<int>(fontConfig.SizePixels));
|
||||
#else
|
||||
snprintf(static_cast<char*>(fontConfig.Name), sizeof(fontConfig.Name),
|
||||
"Noto Mono Regular, %dpx", static_cast<int>(fontConfig.SizePixels));
|
||||
#endif
|
||||
ImGuiEngine::fontLarge =
|
||||
hasFontFile ?
|
||||
io.Fonts->AddFontFromFileTTF(fontPath.c_str(), fontConfig.SizePixels, &fontConfig) :
|
||||
nullptr;
|
||||
if (ImGuiEngine::fontLarge == nullptr) {
|
||||
if (hasFontFile) {
|
||||
DuskLog.warn("Failed to load font '{}': {}", fontPath, SDL_GetError());
|
||||
}
|
||||
ImGuiEngine::fontLarge = io.Fonts->AddFontDefault(&fontConfig);
|
||||
}
|
||||
|
||||
auto& style = ImGui::GetStyle();
|
||||
style = {}; // Reset sizes
|
||||
style.WindowPadding = ImVec2(15, 15);
|
||||
style.WindowRounding = 5.0f;
|
||||
style.FrameBorderSize = 1.f;
|
||||
style.FramePadding = ImVec2(5, 5);
|
||||
style.FrameRounding = 4.0f;
|
||||
style.ItemSpacing = ImVec2(12, 8);
|
||||
style.ItemInnerSpacing = ImVec2(8, 6);
|
||||
style.IndentSpacing = 25.0f;
|
||||
style.ScrollbarSize = 15.0f;
|
||||
style.ScrollbarRounding = 9.0f;
|
||||
style.GrabMinSize = 5.0f;
|
||||
style.GrabRounding = 3.0f;
|
||||
style.PopupBorderSize = 1.f;
|
||||
style.PopupRounding = 7.0;
|
||||
style.TabBorderSize = 1.f;
|
||||
style.TabRounding = 3.f;
|
||||
|
||||
auto* colors = style.Colors;
|
||||
colors[ImGuiCol_Text] = ImVec4(0.95f, 0.96f, 0.98f, 1.00f);
|
||||
colors[ImGuiCol_TextDisabled] = ImVec4(0.36f, 0.42f, 0.47f, 1.00f);
|
||||
colors[ImGuiCol_WindowBg] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f);
|
||||
colors[ImGuiCol_ChildBg] = ImVec4(0.15f, 0.18f, 0.22f, 1.00f);
|
||||
colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.08f, 0.94f);
|
||||
colors[ImGuiCol_Border] = ImVec4(0.08f, 0.10f, 0.12f, 1.00f);
|
||||
colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
|
||||
colors[ImGuiCol_FrameBg] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f);
|
||||
colors[ImGuiCol_FrameBgHovered] = ImVec4(0.12f, 0.20f, 0.28f, 1.00f);
|
||||
colors[ImGuiCol_FrameBgActive] = ImVec4(0.09f, 0.12f, 0.14f, 1.00f);
|
||||
colors[ImGuiCol_TitleBg] = ImVec4(0.09f, 0.12f, 0.14f, 0.65f);
|
||||
colors[ImGuiCol_TitleBgActive] = ImVec4(0.08f, 0.10f, 0.12f, 1.00f);
|
||||
colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 0.51f);
|
||||
colors[ImGuiCol_MenuBarBg] = ImVec4(0.15f, 0.18f, 0.22f, 1.00f);
|
||||
colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.39f);
|
||||
colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f);
|
||||
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.18f, 0.22f, 0.25f, 1.00f);
|
||||
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.09f, 0.21f, 0.31f, 1.00f);
|
||||
colors[ImGuiCol_CheckMark] = ImVec4(0.28f, 0.56f, 1.00f, 1.00f);
|
||||
colors[ImGuiCol_SliderGrab] = ImVec4(0.28f, 0.56f, 1.00f, 1.00f);
|
||||
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.37f, 0.61f, 1.00f, 1.00f);
|
||||
colors[ImGuiCol_Button] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f);
|
||||
colors[ImGuiCol_ButtonHovered] = ImVec4(0.28f, 0.56f, 1.00f, 1.00f);
|
||||
colors[ImGuiCol_ButtonActive] = ImVec4(0.06f, 0.53f, 0.98f, 1.00f);
|
||||
colors[ImGuiCol_Header] = ImVec4(0.20f, 0.25f, 0.29f, 0.55f);
|
||||
colors[ImGuiCol_HeaderHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.80f);
|
||||
colors[ImGuiCol_HeaderActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
|
||||
colors[ImGuiCol_Separator] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f);
|
||||
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.10f, 0.40f, 0.75f, 0.78f);
|
||||
colors[ImGuiCol_SeparatorActive] = ImVec4(0.10f, 0.40f, 0.75f, 1.00f);
|
||||
colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.25f);
|
||||
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f);
|
||||
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
|
||||
colors[ImGuiCol_Tab] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f);
|
||||
colors[ImGuiCol_TabHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.80f);
|
||||
colors[ImGuiCol_TabActive] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f);
|
||||
colors[ImGuiCol_TabUnfocused] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f);
|
||||
colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f);
|
||||
colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f);
|
||||
colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);
|
||||
colors[ImGuiCol_PlotHistogram] = ImVec4(0.06f, 0.53f, 0.98f, 1.00f);
|
||||
colors[ImGuiCol_PlotHistogramHovered] = ImVec4(0.28f, 0.56f, 1.00f, 1.00f);
|
||||
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
|
||||
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
|
||||
colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
|
||||
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
|
||||
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
|
||||
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f);
|
||||
|
||||
style.ScaleAllSizes(scale);
|
||||
}
|
||||
|
||||
Icon GetIcon() {
|
||||
const std::string iconPath = GetAssetPath("icon.png");
|
||||
if (!AssetExists(iconPath)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
SDL_Surface* loadedSurface = SDL_LoadPNG(iconPath.c_str());
|
||||
if (loadedSurface == nullptr) {
|
||||
DuskLog.warn("Failed to load icon '{}': {}", iconPath, SDL_GetError());
|
||||
return {};
|
||||
}
|
||||
|
||||
SDL_Surface* rgbaSurface = SDL_ConvertSurface(loadedSurface, SDL_PIXELFORMAT_RGBA32);
|
||||
SDL_DestroySurface(loadedSurface);
|
||||
if (rgbaSurface == nullptr) {
|
||||
DuskLog.warn("Failed to convert icon '{}': {}", iconPath, SDL_GetError());
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto iconWidth = static_cast<uint32_t>(rgbaSurface->w);
|
||||
const auto iconHeight = static_cast<uint32_t>(rgbaSurface->h);
|
||||
const size_t rowSize = static_cast<size_t>(iconWidth) * 4;
|
||||
const size_t size = rowSize * static_cast<size_t>(iconHeight);
|
||||
auto ptr = std::make_unique<uint8_t[]>(size);
|
||||
for (uint32_t row = 0; row < iconHeight; ++row) {
|
||||
const auto* src = static_cast<const uint8_t*>(rgbaSurface->pixels) +
|
||||
static_cast<size_t>(row) * static_cast<size_t>(rgbaSurface->pitch);
|
||||
auto* dst = ptr.get() + static_cast<size_t>(row) * rowSize;
|
||||
std::memcpy(dst, src, rowSize);
|
||||
}
|
||||
|
||||
SDL_DestroySurface(rgbaSurface);
|
||||
return Icon{
|
||||
std::move(ptr),
|
||||
size,
|
||||
iconWidth,
|
||||
iconHeight,
|
||||
};
|
||||
}
|
||||
|
||||
void ImGuiEngine_AddTextures() {
|
||||
auto icon = GetIcon();
|
||||
if (icon.data == nullptr || icon.width == 0 || icon.height == 0) {
|
||||
ImGuiEngine::duskIcon = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
ImGuiEngine::duskIcon = aurora_imgui_add_texture(icon.width, icon.height, icon.data.get());
|
||||
}
|
||||
} // namespace dusk
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include "imgui.h"
|
||||
#include "misc/cpp/imgui_stdlib.h"
|
||||
|
||||
namespace dusk {
|
||||
class ImGuiEngine {
|
||||
public:
|
||||
static ImFont* fontNormal;
|
||||
static ImFont* fontLarge;
|
||||
static ImTextureID duskIcon;
|
||||
};
|
||||
|
||||
void ImGuiEngine_Initialize(float scale);
|
||||
void ImGuiEngine_AddTextures();
|
||||
|
||||
struct Icon {
|
||||
std::unique_ptr<uint8_t[]> data;
|
||||
size_t size;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
};
|
||||
Icon GetIcon();
|
||||
} // namespace dusk
|
||||
@@ -17,7 +17,8 @@ namespace dusk {
|
||||
ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav;
|
||||
|
||||
ImGui::SetNextWindowBgAlpha(0.65f);
|
||||
ImGui::SetNextWindowSizeConstraints(ImVec2(300, 0), ImVec2(FLT_MAX, FLT_MAX));
|
||||
ImGui::SetNextWindowSizeConstraints(ImVec2(300.f * ImGuiScale(), 0),
|
||||
ImVec2(FLT_MAX, FLT_MAX));
|
||||
|
||||
if (!ImGui::Begin("Map Loader", &m_showMapLoader, windowFlags)) {
|
||||
ImGui::End();
|
||||
|
||||
@@ -84,13 +84,14 @@ namespace dusk {
|
||||
}
|
||||
|
||||
static void drawVirtualStick(const char* id, const ImVec2& stick) {
|
||||
ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPos().x + 5, ImGui::GetCursorPos().y));
|
||||
float scale = ImGuiScale();
|
||||
ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPos().x + 5 * scale, ImGui::GetCursorPos().y));
|
||||
|
||||
ImGui::BeginChild(id, ImVec2(80, 80));
|
||||
ImGui::BeginChild(id, ImVec2(80 * scale, 80 * scale));
|
||||
ImDrawList* dl = ImGui::GetWindowDrawList();
|
||||
ImVec2 p = ImGui::GetCursorScreenPos();
|
||||
|
||||
float radius = ImGui::GetCurrentContext()->CurrentDpiScale * 30.0f;
|
||||
float radius = 30.0f * scale;
|
||||
ImVec2 pos = ImVec2(p.x + radius, p.y + radius);
|
||||
|
||||
constexpr ImU32 stickGray = IM_COL32(150, 150, 150, 255);
|
||||
@@ -98,7 +99,7 @@ namespace dusk {
|
||||
constexpr ImU32 red = IM_COL32(230, 0, 0, 255);
|
||||
|
||||
dl->AddCircleFilled(pos, radius, stickGray, 8);
|
||||
dl->AddCircleFilled(ImVec2(pos.x + stick.x * (radius), pos.y + -stick.y * (radius)), 3, red);
|
||||
dl->AddCircleFilled(ImVec2(pos.x + stick.x * (radius), pos.y + -stick.y * (radius)), 3 * scale, red);
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
@@ -139,12 +140,14 @@ namespace dusk {
|
||||
}
|
||||
}
|
||||
|
||||
float scale = ImGuiScale();
|
||||
ImGuiWindowFlags windowFlags =
|
||||
ImGuiWindowFlags_NoResize |
|
||||
ImGuiWindowFlags_AlwaysAutoResize;
|
||||
|
||||
ImGui::SetNextWindowBgAlpha(0.65f);
|
||||
ImGui::SetNextWindowSizeConstraints(ImVec2(850, 400), ImVec2(850, 400));
|
||||
ImGui::SetNextWindowSizeConstraints(ImVec2(850 * scale, 400 * scale),
|
||||
ImVec2(850 * scale, 400 * scale));
|
||||
|
||||
if (!ImGui::Begin("Controller Config", &m_showControllerConfig, windowFlags)) {
|
||||
ImGui::End();
|
||||
@@ -225,9 +228,9 @@ namespace dusk {
|
||||
}
|
||||
|
||||
// buttons panel
|
||||
constexpr float uiButtonSize = 40;
|
||||
const float uiButtonSize = 40 * scale;
|
||||
|
||||
ImGuiBeginGroupPanel("Buttons", ImVec2(150, 20));
|
||||
ImGuiBeginGroupPanel("Buttons", ImVec2(150 * scale, 20 * scale));
|
||||
|
||||
u32 buttonCount;
|
||||
PADButtonMapping* btnMappingList = PADGetButtonMappings(m_controllerConfig.m_selectedPort, &buttonCount);
|
||||
@@ -251,7 +254,7 @@ namespace dusk {
|
||||
dispName = fmt::format("{0}##-{1}", PADGetNativeButtonName(btnMappingList[i].nativeButton), i);
|
||||
}
|
||||
bool pressed = ImGui::Button(dispName.c_str(),
|
||||
ImVec2(100.0f, 20.0f));
|
||||
ImVec2(100.0f * scale, 20.0f * scale));
|
||||
|
||||
if (pressed) {
|
||||
m_controllerConfig.m_isReading = true;
|
||||
@@ -268,7 +271,7 @@ namespace dusk {
|
||||
uint32_t axisCount;
|
||||
PADAxisMapping* axisMappingList = PADGetAxisMappings(m_controllerConfig.m_selectedPort, &axisCount);
|
||||
|
||||
ImGuiBeginGroupPanel("Triggers", ImVec2(150, 20));
|
||||
ImGuiBeginGroupPanel("Triggers", ImVec2(150 * scale, 20 * scale));
|
||||
|
||||
PADAxis triggers[] = {PAD_AXIS_TRIGGER_L, PAD_AXIS_TRIGGER_R};
|
||||
if (axisMappingList != nullptr) {
|
||||
@@ -291,7 +294,7 @@ namespace dusk {
|
||||
dispName = fmt::format("{0}##-{1}", PADGetNativeAxisName(axisMappingList[trigger].nativeAxis), trigger);
|
||||
}
|
||||
bool pressed = ImGui::Button(dispName.c_str(),
|
||||
ImVec2(100.0f, 20.0f));
|
||||
ImVec2(100.0f * scale, 20.0f * scale));
|
||||
|
||||
if (pressed) {
|
||||
m_controllerConfig.m_isReading = true;
|
||||
@@ -308,7 +311,7 @@ namespace dusk {
|
||||
int port = m_controllerConfig.m_selectedPort;
|
||||
|
||||
// main stick panel
|
||||
ImGuiBeginGroupPanel("Control Stick", ImVec2(150, 20));
|
||||
ImGuiBeginGroupPanel("Control Stick", ImVec2(150 * scale, 20 * scale));
|
||||
|
||||
drawVirtualStick("##mainStick", ImVec2{ mDoCPd_c::getStickX(port), mDoCPd_c::getStickY(port) });
|
||||
|
||||
@@ -345,7 +348,7 @@ namespace dusk {
|
||||
dispName = fmt::format("{0}##-{1}", PADGetNativeButtonName(axisMappingList[axis].nativeButton), axis);
|
||||
}
|
||||
}
|
||||
bool pressed = ImGui::Button(dispName.c_str(), ImVec2(100.0f, 20.0f));
|
||||
bool pressed = ImGui::Button(dispName.c_str(), ImVec2(100.0f * scale, 20.0f * scale));
|
||||
|
||||
if (pressed) {
|
||||
m_controllerConfig.m_isReading = true;
|
||||
@@ -372,7 +375,7 @@ namespace dusk {
|
||||
ImGui::SameLine();
|
||||
|
||||
// sub stick panel
|
||||
ImGuiBeginGroupPanel("C Stick", ImVec2(150, 20));
|
||||
ImGuiBeginGroupPanel("C Stick", ImVec2(150 * scale, 20 * scale));
|
||||
|
||||
drawVirtualStick("##subStick", ImVec2{ mDoCPd_c::getSubStickX(port), mDoCPd_c::getSubStickY(port) });
|
||||
|
||||
@@ -409,7 +412,7 @@ namespace dusk {
|
||||
dispName = fmt::format("{0}##-{1}", PADGetNativeButtonName(axisMappingList[axis].nativeButton), axis);
|
||||
}
|
||||
}
|
||||
bool pressed = ImGui::Button(fmt::format("{0}##sub{1}", dispName, label).c_str(), ImVec2(100.0f, 20.0f));
|
||||
bool pressed = ImGui::Button(fmt::format("{0}##sub{1}", dispName, label).c_str(), ImVec2(100.0f * scale, 20.0f * scale));
|
||||
|
||||
if (pressed) {
|
||||
m_controllerConfig.m_isReading = true;
|
||||
@@ -434,7 +437,7 @@ namespace dusk {
|
||||
ImGui::SameLine();
|
||||
|
||||
// Triggers Panel
|
||||
ImGuiBeginGroupPanel("Triggers", ImVec2(150, 20));
|
||||
ImGuiBeginGroupPanel("Triggers", ImVec2(150 * scale, 20 * scale));
|
||||
|
||||
if (deadZones != nullptr) {
|
||||
ImGui::Text("L Threshold");
|
||||
@@ -460,7 +463,7 @@ namespace dusk {
|
||||
ImGui::SameLine();
|
||||
|
||||
// Options panel
|
||||
ImGuiBeginGroupPanel("Options", ImVec2(150, 20));
|
||||
ImGuiBeginGroupPanel("Options", ImVec2(150 * scale, 20 * scale));
|
||||
|
||||
if (deadZones != nullptr) {
|
||||
ImGui::Checkbox("Enable Dead Zones", &deadZones->useDeadzones);
|
||||
|
||||
@@ -131,6 +131,9 @@ namespace dusk {
|
||||
BytesToString(stats->lastVertSize + stats->lastUniformSize +
|
||||
stats->lastIndexSize + stats->lastStorageSize +
|
||||
stats->lastTextureUploadSize)));
|
||||
|
||||
// TODO: persist to config
|
||||
ShowCornerContextMenu(m_debugOverlayCorner, m_cameraOverlayCorner);
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace dusk {
|
||||
|
||||
private:
|
||||
bool m_showDebugOverlay = false;
|
||||
int m_debugOverlayCorner = 0; // top-left
|
||||
int m_debugOverlayCorner = 2; // bottom-left
|
||||
|
||||
bool m_showCameraOverlay = false;
|
||||
int m_cameraOverlayCorner = 3;
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
#include "dusk/logging.h"
|
||||
#include "dusk/time.h"
|
||||
#include "dusk/main.h"
|
||||
#include "dusk/imgui/ImGuiEngine.hpp"
|
||||
|
||||
#include <aurora/aurora.h>
|
||||
#include <aurora/event.h>
|
||||
@@ -225,6 +226,10 @@ static AuroraBackend ParseAuroraBackend(const std::string& value) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void aurora_imgui_init_callback(const AuroraWindowSize* size) {
|
||||
dusk::ImGuiEngine_Initialize(size->scale);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// PC ENTRY POINT
|
||||
// =========================================================================
|
||||
@@ -270,6 +275,7 @@ int game_main(int argc, char* argv[]) {
|
||||
config.mem1Size = 256 * 1024 * 1024;
|
||||
config.mem2Size = 24 * 1024 * 1024;
|
||||
config.allowJoystickBackgroundEvents = true;
|
||||
config.imGuiInitCallback = &aurora_imgui_init_callback;
|
||||
|
||||
auroraInfo = aurora_initialize(argc, argv, &config);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user