mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2026-04-27 12:51:42 +00:00
Merge branch 'options-menu' into options-menu-and-installer
This commit is contained in:
commit
7d19a7603e
19 changed files with 283 additions and 258 deletions
|
|
@ -82,7 +82,7 @@ set(SWA_APU_CXX_SOURCES
|
|||
if(SWA_XAUDIO2)
|
||||
list(APPEND SWA_APU_CXX_SOURCES "apu/driver/xaudio_driver.cpp")
|
||||
else()
|
||||
list(APPEND SWA_APU_CXX_SOURCES "apu/driver/sdl2_driver.cpp")
|
||||
list(APPEND SWA_APU_CXX_SOURCES "apu/driver/miniaudio_driver.cpp")
|
||||
endif()
|
||||
|
||||
set(SWA_HID_CXX_SOURCES
|
||||
|
|
@ -195,8 +195,8 @@ find_package(unofficial-concurrentqueue REQUIRED)
|
|||
find_package(imgui CONFIG REQUIRED)
|
||||
find_package(magic_enum CONFIG REQUIRED)
|
||||
find_package(unofficial-tiny-aes-c CONFIG REQUIRED)
|
||||
find_path(READERWRITERQUEUE_INCLUDE_DIRS "readerwriterqueue/atomicops.h")
|
||||
find_package(nfd CONFIG REQUIRED)
|
||||
find_path(MINIAUDIO_INCLUDE_DIRS "miniaudio.h")
|
||||
|
||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/D3D12)
|
||||
add_custom_command(TARGET UnleashedRecomp POST_BUILD
|
||||
|
|
@ -245,7 +245,7 @@ target_include_directories(UnleashedRecomp PRIVATE
|
|||
${LIBMSPACK_PATH}
|
||||
${Stb_INCLUDE_DIR}
|
||||
${SMOLV_SOURCE_DIR}
|
||||
${READERWRITERQUEUE_INCLUDE_DIRS}
|
||||
${MINIAUDIO_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_precompile_headers(UnleashedRecomp PUBLIC ${SWA_PRECOMPILED_HEADERS})
|
||||
|
|
@ -315,6 +315,7 @@ generate_aggregate_header(
|
|||
|
||||
set(RESOURCES_SOURCE_PATH "${PROJECT_SOURCE_DIR}/../UnleashedRecompResources")
|
||||
set(RESOURCES_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/res")
|
||||
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/achievements_menu/trophy.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/achievements_menu/trophy.dds" ARRAY_TYPE "unsigned char" ARRAY_NAME "g_trophy")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/arrow_circle.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/arrow_circle.dds" ARRAY_TYPE "unsigned char" ARRAY_NAME "g_arrow_circle")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_001.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_001.dds" ARRAY_TYPE "unsigned char" ARRAY_NAME "g_install_001")
|
||||
|
|
@ -326,6 +327,8 @@ BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/in
|
|||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_007.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_007.dds" ARRAY_TYPE "unsigned char" ARRAY_NAME "g_install_007")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_008.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_008.dds" ARRAY_TYPE "unsigned char" ARRAY_NAME "g_install_008")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/miles_electric_icon.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/miles_electric_icon.dds" ARRAY_TYPE "unsigned char" ARRAY_NAME "g_miles_electric_icon")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/general_window.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/general_window.dds" ARRAY_TYPE "unsigned char" ARRAY_NAME "g_general_window")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/select_fade.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/select_fade.dds" ARRAY_TYPE "unsigned char" ARRAY_NAME "g_select_fade")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/select_fill.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/select_fill.dds" ARRAY_TYPE "unsigned char" ARRAY_NAME "g_select_fill")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/game_icon.bmp" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/game_icon.bmp" ARRAY_TYPE "unsigned char" ARRAY_NAME "g_game_icon")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/game_icon_night.bmp" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/game_icon_night.bmp" ARRAY_TYPE "unsigned char" ARRAY_NAME "g_game_icon_night")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/pause.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/pause.dds" ARRAY_TYPE "unsigned char" ARRAY_NAME "g_pause")
|
||||
|
|
|
|||
56
UnleashedRecomp/apu/driver/miniaudio_driver.cpp
Normal file
56
UnleashedRecomp/apu/driver/miniaudio_driver.cpp
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
#include "miniaudio_driver.h"
|
||||
#include <cpu/code_cache.h>
|
||||
#include <cpu/guest_thread.h>
|
||||
#include <cpu/guest_code.h>
|
||||
#include <kernel/heap.h>
|
||||
|
||||
#define MINIAUDIO_IMPLEMENTATION
|
||||
#include <miniaudio.h>
|
||||
|
||||
static PPCFunc* g_clientCallback{};
|
||||
static DWORD g_clientCallbackParam{}; // pointer in guest memory
|
||||
static ma_device g_audioDevice{};
|
||||
static std::unique_ptr<GuestThreadContext> g_audioCtx;
|
||||
static uint32_t* g_audioOutput;
|
||||
|
||||
static void AudioCallback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
|
||||
{
|
||||
if (g_audioCtx == nullptr)
|
||||
g_audioCtx = std::make_unique<GuestThreadContext>(0);
|
||||
|
||||
g_audioCtx->ppcContext.r3.u64 = g_clientCallbackParam;
|
||||
g_audioOutput = reinterpret_cast<uint32_t*>(pOutput);
|
||||
(*g_clientCallback)(g_audioCtx->ppcContext, reinterpret_cast<uint8_t*>(g_memory.base));
|
||||
}
|
||||
|
||||
void XAudioInitializeSystem()
|
||||
{
|
||||
ma_device_config deviceConfig = ma_device_config_init(ma_device_type_playback);
|
||||
deviceConfig.sampleRate = XAUDIO_SAMPLES_HZ;
|
||||
deviceConfig.periodSizeInFrames = XAUDIO_NUM_SAMPLES;
|
||||
deviceConfig.noPreSilencedOutputBuffer = true;
|
||||
deviceConfig.dataCallback = AudioCallback;
|
||||
deviceConfig.playback.format = ma_format_f32;
|
||||
deviceConfig.playback.channels = XAUDIO_NUM_CHANNELS;
|
||||
ma_device_init(nullptr, &deviceConfig, &g_audioDevice);
|
||||
}
|
||||
|
||||
void XAudioRegisterClient(PPCFunc* callback, uint32_t param)
|
||||
{
|
||||
auto* pClientParam = static_cast<uint32_t*>(g_userHeap.Alloc(sizeof(param)));
|
||||
ByteSwap(param);
|
||||
*pClientParam = param;
|
||||
g_clientCallbackParam = g_memory.MapVirtual(pClientParam);
|
||||
g_clientCallback = callback;
|
||||
|
||||
ma_device_start(&g_audioDevice);
|
||||
}
|
||||
|
||||
void XAudioSubmitFrame(void* samples)
|
||||
{
|
||||
for (size_t i = 0; i < XAUDIO_NUM_SAMPLES; i++)
|
||||
{
|
||||
for (size_t j = 0; j < XAUDIO_NUM_CHANNELS; j++)
|
||||
g_audioOutput[i * XAUDIO_NUM_CHANNELS + j] = std::byteswap(((uint32_t*)samples)[j * XAUDIO_NUM_SAMPLES + i]);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,2 @@
|
|||
#pragma once
|
||||
#include <SDL.h>
|
||||
#include <apu/audio.h>
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
#include "sdl2_driver.h"
|
||||
#include <cpu/code_cache.h>
|
||||
#include <cpu/guest_thread.h>
|
||||
#include <cpu/guest_code.h>
|
||||
#include <kernel/heap.h>
|
||||
|
||||
#define SDLAUDIO_DRIVER_KEY (uint32_t)('SDLA')
|
||||
|
||||
static constexpr uint32_t AUDIO_FRAME_SIZE = XAUDIO_NUM_SAMPLES * XAUDIO_NUM_CHANNELS;
|
||||
|
||||
static std::atomic<PPCFunc*> g_clientCallback{};
|
||||
static DWORD g_clientCallbackParam{}; // pointer in guest memory
|
||||
|
||||
static SDL_AudioDeviceID g_audioDevice{};
|
||||
static moodycamel::BlockingReaderWriterCircularBuffer<std::array<uint32_t, AUDIO_FRAME_SIZE>> g_audioQueue(16);
|
||||
|
||||
static void SDLAudioCallback(void*, uint8_t* frames, int len)
|
||||
{
|
||||
std::array<uint32_t, AUDIO_FRAME_SIZE> audioFrame;
|
||||
if (g_audioQueue.try_dequeue(audioFrame))
|
||||
memcpy(frames, &audioFrame, sizeof(audioFrame));
|
||||
else
|
||||
memset(frames, 0, len);
|
||||
}
|
||||
|
||||
static PPC_FUNC(DriverLoop)
|
||||
{
|
||||
GuestThread::SetThreadName(GetCurrentThreadId(), "Audio Driver");
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (!g_clientCallback)
|
||||
continue;
|
||||
|
||||
ctx.r3.u64 = g_clientCallbackParam;
|
||||
GuestCode::Run((void*)g_clientCallback, &ctx);
|
||||
}
|
||||
}
|
||||
|
||||
void XAudioInitializeSystem()
|
||||
{
|
||||
SDL_SetHint(SDL_HINT_AUDIO_CATEGORY, "playback");
|
||||
SDL_SetHint(SDL_HINT_AUDIO_DEVICE_APP_NAME, "SWA");
|
||||
|
||||
auto err = SDL_InitSubSystem(SDL_INIT_AUDIO);
|
||||
SDL_AudioSpec spec{};
|
||||
spec.freq = XAUDIO_SAMPLES_HZ;
|
||||
spec.format = AUDIO_F32SYS;
|
||||
spec.channels = XAUDIO_NUM_CHANNELS;
|
||||
spec.samples = XAUDIO_NUM_SAMPLES;
|
||||
spec.callback = SDLAudioCallback;
|
||||
g_audioDevice = SDL_OpenAudioDevice(nullptr, false, &spec, &spec, 0);
|
||||
assert(g_audioDevice);
|
||||
|
||||
SDL_PauseAudioDevice(g_audioDevice, 0);
|
||||
KeInsertHostFunction(SDLAUDIO_DRIVER_KEY, DriverLoop);
|
||||
GuestThread::Start(SDLAUDIO_DRIVER_KEY, 0, 0, nullptr);
|
||||
}
|
||||
|
||||
void XAudioRegisterClient(PPCFunc* callback, uint32_t param)
|
||||
{
|
||||
auto* pClientParam = static_cast<uint32_t*>(g_userHeap.Alloc(sizeof(param)));
|
||||
ByteSwap(param);
|
||||
*pClientParam = param;
|
||||
g_clientCallbackParam = g_memory.MapVirtual(pClientParam);
|
||||
|
||||
g_clientCallback = callback;
|
||||
}
|
||||
|
||||
void XAudioSubmitFrame(void* samples)
|
||||
{
|
||||
std::array<uint32_t, AUDIO_FRAME_SIZE> audioFrame;
|
||||
|
||||
for (size_t i = 0; i < XAUDIO_NUM_SAMPLES; i++)
|
||||
{
|
||||
for (size_t j = 0; j < XAUDIO_NUM_CHANNELS; j++)
|
||||
audioFrame[i * XAUDIO_NUM_CHANNELS + j] = std::byteswap(((uint32_t*)samples)[j * XAUDIO_NUM_SAMPLES + i]);
|
||||
}
|
||||
|
||||
g_audioQueue.wait_enqueue(audioFrame);
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
struct GuestCode
|
||||
{
|
||||
inline static void Run(void* hostAddress, PPCContext* ctx, void* baseAddress, void* callStack)
|
||||
inline static void Run(void* hostAddress, PPCContext* ctx, void* baseAddress)
|
||||
{
|
||||
ctx->fpscr.loadFromHost();
|
||||
reinterpret_cast<PPCFunc*>(hostAddress)(*ctx, reinterpret_cast<uint8_t*>(baseAddress));
|
||||
|
|
|
|||
|
|
@ -11,24 +11,15 @@ constexpr size_t PCR_SIZE = 0xAB0;
|
|||
constexpr size_t TLS_SIZE = 0x100;
|
||||
constexpr size_t TEB_SIZE = 0x2E0;
|
||||
constexpr size_t STACK_SIZE = 0x40000;
|
||||
constexpr size_t CALL_STACK_SIZE = 0x8000;
|
||||
constexpr size_t TOTAL_SIZE = PCR_SIZE + TLS_SIZE + TEB_SIZE + STACK_SIZE + CALL_STACK_SIZE;
|
||||
constexpr size_t TOTAL_SIZE = PCR_SIZE + TLS_SIZE + TEB_SIZE + STACK_SIZE;
|
||||
|
||||
constexpr size_t TEB_OFFSET = PCR_SIZE + TLS_SIZE;
|
||||
|
||||
DWORD GuestThread::Start(uint32_t function)
|
||||
GuestThreadContext::GuestThreadContext(uint32_t cpuNumber)
|
||||
{
|
||||
const GuestThreadParameter parameter{ function };
|
||||
return Start(parameter);
|
||||
}
|
||||
|
||||
DWORD GuestThread::Start(const GuestThreadParameter& parameter)
|
||||
{
|
||||
auto* thread = (uint8_t*)g_userHeap.Alloc(TOTAL_SIZE);
|
||||
|
||||
const auto procMask = (uint8_t)(parameter.flags >> 24);
|
||||
const auto cpuNumber = procMask == 0 ? 0 : 7 - std::countl_zero(procMask);
|
||||
assert(thread == nullptr);
|
||||
|
||||
thread = (uint8_t*)g_userHeap.Alloc(TOTAL_SIZE);
|
||||
memset(thread, 0, TOTAL_SIZE);
|
||||
|
||||
*(uint32_t*)thread = std::byteswap(g_memory.MapVirtual(thread + PCR_SIZE)); // tls pointer
|
||||
|
|
@ -38,18 +29,36 @@ DWORD GuestThread::Start(const GuestThreadParameter& parameter)
|
|||
*(uint32_t*)(thread + PCR_SIZE + 0x10) = 0xFFFFFFFF; // that one TLS entry that felt quirky
|
||||
*(uint32_t*)(thread + PCR_SIZE + TLS_SIZE + 0x14C) = std::byteswap(GetCurrentThreadId()); // thread id
|
||||
|
||||
PPCContext ppcContext{};
|
||||
ppcContext.fn = (uint8_t*)g_codeCache.bucket;
|
||||
ppcContext.r1.u64 = g_memory.MapVirtual(thread + PCR_SIZE + TLS_SIZE + TEB_SIZE + STACK_SIZE); // stack pointer
|
||||
ppcContext.r3.u64 = parameter.value;
|
||||
ppcContext.r13.u64 = g_memory.MapVirtual(thread);
|
||||
|
||||
assert(GetPPCContext() == nullptr);
|
||||
SetPPCContext(ppcContext);
|
||||
}
|
||||
|
||||
GuestCode::Run(g_codeCache.Find(parameter.function), &ppcContext, g_memory.Translate(0), g_memory.Translate(ppcContext.r1.u32));
|
||||
GuestThreadContext::~GuestThreadContext()
|
||||
{
|
||||
g_userHeap.Free(thread);
|
||||
}
|
||||
|
||||
return (DWORD)ppcContext.r3.u64;
|
||||
DWORD GuestThread::Start(uint32_t function)
|
||||
{
|
||||
const GuestThreadParameter parameter{ function };
|
||||
return Start(parameter);
|
||||
}
|
||||
|
||||
DWORD GuestThread::Start(const GuestThreadParameter& parameter)
|
||||
{
|
||||
const auto procMask = (uint8_t)(parameter.flags >> 24);
|
||||
const auto cpuNumber = procMask == 0 ? 0 : 7 - std::countl_zero(procMask);
|
||||
|
||||
GuestThreadContext ctx(cpuNumber);
|
||||
ctx.ppcContext.r3.u64 = parameter.value;
|
||||
|
||||
GuestCode::Run(g_codeCache.Find(parameter.function), &ctx.ppcContext, g_memory.Translate(0));
|
||||
|
||||
return (DWORD)ctx.ppcContext.r3.u64;
|
||||
}
|
||||
|
||||
DWORD HostThreadStart(void* pParameter)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,15 @@ struct GuestThreadParameter
|
|||
uint32_t flags;
|
||||
};
|
||||
|
||||
struct GuestThreadContext
|
||||
{
|
||||
PPCContext ppcContext{};
|
||||
uint8_t* thread = nullptr;
|
||||
|
||||
GuestThreadContext(uint32_t cpuNumber);
|
||||
~GuestThreadContext();
|
||||
};
|
||||
|
||||
struct GuestThread
|
||||
{
|
||||
static DWORD Start(uint32_t function);
|
||||
|
|
|
|||
|
|
@ -4638,7 +4638,7 @@ static void EnqueueGraphicsPipelineCompilation(const PipelineState& pipelineStat
|
|||
if (shouldCompile)
|
||||
{
|
||||
if (databaseDataHolderPair.counter == nullptr && databaseDataHolderPair.holder.databaseData.get() != nullptr)
|
||||
databaseDataHolderPair.counter = std::make_unique<DatabaseDataHolder>(std::move(databaseDataHolderPair.holder));
|
||||
databaseDataHolderPair.counter = std::make_shared<DatabaseDataHolder>(std::move(databaseDataHolderPair.holder));
|
||||
|
||||
PipelineStateQueueItem queueItem;
|
||||
queueItem.pipelineHash = hash;
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ GUEST_FUNCTION_HOOK(sub_82BD4CA8, OutputDebugStringA);
|
|||
|
||||
GUEST_FUNCTION_HOOK(sub_82BD4AC8, QueryPerformanceCounterImpl);
|
||||
GUEST_FUNCTION_HOOK(sub_831CD040, QueryPerformanceFrequencyImpl);
|
||||
GUEST_FUNCTION_HOOK(sub_831CDAD0, GetTickCount);
|
||||
|
||||
GUEST_FUNCTION_HOOK(sub_82BD4BC0, GlobalMemoryStatusImpl);
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ bool AudioPatches::CanAttenuate()
|
|||
|
||||
auto version = GetPlatformVersion();
|
||||
|
||||
m_isAttenuationSupported = version.Major == 10 && version.Build >= 17763;
|
||||
m_isAttenuationSupported = version.Major >= 10 && version.Build >= 17763;
|
||||
|
||||
return m_isAttenuationSupported;
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@
|
|||
#include <wrl/client.h>
|
||||
#include <smolv.h>
|
||||
#include <print>
|
||||
#include <readerwriterqueue/readerwritercircularbuffer.h>
|
||||
|
||||
using Microsoft::WRL::ComPtr;
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@
|
|||
#include <user/config.h>
|
||||
#include <app.h>
|
||||
#include <exports.h>
|
||||
#include <res/images/achievements_menu/trophy.dds.h>
|
||||
#include <res/images/common/general_window.dds.h>
|
||||
#include <res/images/common/select_fill.dds.h>
|
||||
|
||||
constexpr double HEADER_CONTAINER_INTRO_MOTION_START = 0;
|
||||
constexpr double HEADER_CONTAINER_INTRO_MOTION_END = 15;
|
||||
|
|
@ -23,14 +26,12 @@ constexpr double CONTENT_CONTAINER_COMMON_MOTION_END = 12;
|
|||
|
||||
constexpr double COUNTER_INTRO_FADE_START = 15;
|
||||
constexpr double COUNTER_INTRO_FADE_END = 16;
|
||||
constexpr double COUNTER_SPRITE_FRAME_START = 0;
|
||||
constexpr double COUNTER_SPRITE_FRAME_END = 30;
|
||||
|
||||
constexpr double SELECTION_CONTAINER_BREATHE = 30;
|
||||
|
||||
static bool g_isClosing = false;
|
||||
|
||||
static double g_appearTime = 0;
|
||||
static double g_appearTime;
|
||||
|
||||
static std::vector<std::tuple<Achievement, time_t>> g_achievements;
|
||||
|
||||
|
|
@ -39,6 +40,8 @@ static ImFont* g_fntNewRodinDB;
|
|||
static ImFont* g_fntNewRodinUB;
|
||||
|
||||
static std::unique_ptr<GuestTexture> g_upTrophyIcon;
|
||||
static std::unique_ptr<GuestTexture> g_upSelectionCursor;
|
||||
static std::unique_ptr<GuestTexture> g_upWindow;
|
||||
|
||||
static int g_firstVisibleRowIndex;
|
||||
static int g_selectedRowIndex;
|
||||
|
|
@ -63,42 +66,8 @@ static void ResetSelection()
|
|||
static void DrawContainer(ImVec2 min, ImVec2 max, ImU32 gradientTop, ImU32 gradientBottom, float alpha = 1, float cornerRadius = 25)
|
||||
{
|
||||
auto drawList = ImGui::GetForegroundDrawList();
|
||||
auto vertices = GetPauseContainerVertices(min, max, cornerRadius);
|
||||
|
||||
// TODO: add a drop shadow.
|
||||
|
||||
SetGradient(min, max, gradientTop, gradientBottom);
|
||||
drawList->AddConvexPolyFilled(vertices.data(), vertices.size(), IM_COL32(255, 255, 255, 255 * alpha));
|
||||
ResetGradient();
|
||||
|
||||
drawList->AddPolyline(vertices.data(), vertices.size(), IM_COL32(247, 247, 247, 255 * alpha), true, Scale(2.5f));
|
||||
|
||||
for (int i = 0; i < vertices.size(); i++)
|
||||
{
|
||||
vertices[i].x -= Scale(0.4f);
|
||||
vertices[i].y -= Scale(0.2f);
|
||||
}
|
||||
|
||||
auto colLineTop = IM_COL32(165, 170, 165, 230 * alpha);
|
||||
auto colLineBottom = IM_COL32(190, 190, 190, 230 * alpha);
|
||||
auto lineThickness = Scale(1);
|
||||
|
||||
// Top left corner bottom to top left corner top.
|
||||
drawList->AddLine(vertices[0], vertices[1], colLineTop, lineThickness * Scale(0.5f));
|
||||
|
||||
// Top left corner bottom to bottom left.
|
||||
drawList->AddRectFilledMultiColor
|
||||
(
|
||||
{ /* X */ vertices[0].x - Scale(0.2f), /* Y */ vertices[0].y },
|
||||
{ /* X */ vertices[6].x + lineThickness - Scale(0.2f), /* Y */ vertices[6].y },
|
||||
colLineTop,
|
||||
colLineTop,
|
||||
colLineBottom,
|
||||
colLineBottom
|
||||
);
|
||||
|
||||
// Top left corner top to top right.
|
||||
drawList->AddLine(vertices[1], vertices[2], colLineTop, lineThickness);
|
||||
DrawPauseContainer(g_upWindow, min, max, alpha);
|
||||
|
||||
drawList->PushClipRect({ min.x, min.y + Scale(20) }, { max.x, max.y - Scale(5) });
|
||||
}
|
||||
|
|
@ -106,20 +75,39 @@ static void DrawContainer(ImVec2 min, ImVec2 max, ImU32 gradientTop, ImU32 gradi
|
|||
static void DrawSelectionContainer(ImVec2 min, ImVec2 max)
|
||||
{
|
||||
auto drawList = ImGui::GetForegroundDrawList();
|
||||
auto vertices = GetPauseContainerVertices(min, max, 10);
|
||||
|
||||
static auto breatheStart = ImGui::GetTime();
|
||||
auto alpha = Lerp(1.0f, 0.75f, (sin((ImGui::GetTime() - breatheStart) * (2.0f * M_PI / (55.0f / 60.0f))) + 1.0f) / 2.0f);
|
||||
auto colour = IM_COL32(255, 255, 255, 255 * alpha);
|
||||
|
||||
SetGradient(min, max, IM_COL32(255, 246, 0, 129), IM_COL32(255, 194, 0, 118 * alpha));
|
||||
drawList->AddConvexPolyFilled(vertices.data(), vertices.size(), IM_COL32(255, 255, 255, 255 * alpha));
|
||||
ResetGradient();
|
||||
auto commonWidth = Scale(11);
|
||||
auto commonHeight = Scale(24);
|
||||
|
||||
auto tl = PIXELS_TO_UV_COORDS(64, 64, 0, 0, 11, 24);
|
||||
auto tc = PIXELS_TO_UV_COORDS(64, 64, 11, 0, 8, 24);
|
||||
auto tr = PIXELS_TO_UV_COORDS(64, 64, 19, 0, 11, 24);
|
||||
auto cl = PIXELS_TO_UV_COORDS(64, 64, 0, 24, 11, 2);
|
||||
auto cc = PIXELS_TO_UV_COORDS(64, 64, 11, 24, 8, 2);
|
||||
auto cr = PIXELS_TO_UV_COORDS(64, 64, 19, 24, 11, 2);
|
||||
auto bl = PIXELS_TO_UV_COORDS(64, 64, 0, 26, 11, 24);
|
||||
auto bc = PIXELS_TO_UV_COORDS(64, 64, 11, 26, 8, 24);
|
||||
auto br = PIXELS_TO_UV_COORDS(64, 64, 19, 26, 11, 24);
|
||||
|
||||
drawList->AddImage(g_upSelectionCursor.get(), min, { min.x + commonWidth, min.y + commonHeight }, GET_UV_COORDS(tl), colour);
|
||||
drawList->AddImage(g_upSelectionCursor.get(), { min.x + commonWidth, min.y }, { max.x - commonWidth, min.y + commonHeight }, GET_UV_COORDS(tc), colour);
|
||||
drawList->AddImage(g_upSelectionCursor.get(), { max.x - commonWidth, min.y }, { max.x, min.y + commonHeight }, GET_UV_COORDS(tr), colour);
|
||||
drawList->AddImage(g_upSelectionCursor.get(), { min.x, min.y + commonHeight }, { min.x + commonWidth, max.y - commonHeight }, GET_UV_COORDS(cl), colour);
|
||||
drawList->AddImage(g_upSelectionCursor.get(), { min.x + commonWidth, min.y + commonHeight }, { max.x - commonWidth, max.y - commonHeight }, GET_UV_COORDS(cc), colour);
|
||||
drawList->AddImage(g_upSelectionCursor.get(), { max.x - commonWidth, min.y + commonHeight }, { max.x, max.y - commonHeight }, GET_UV_COORDS(cr), colour);
|
||||
drawList->AddImage(g_upSelectionCursor.get(), { min.x, max.y - commonHeight }, { min.x + commonWidth, max.y }, GET_UV_COORDS(bl), colour);
|
||||
drawList->AddImage(g_upSelectionCursor.get(), { min.x + commonWidth, max.y - commonHeight }, { max.x - commonWidth, max.y }, GET_UV_COORDS(bc), colour);
|
||||
drawList->AddImage(g_upSelectionCursor.get(), { max.x - commonWidth, max.y - commonHeight }, { max.x, max.y }, GET_UV_COORDS(br), colour);
|
||||
}
|
||||
|
||||
static void DrawHeaderContainer(const char* text)
|
||||
{
|
||||
auto drawList = ImGui::GetForegroundDrawList();
|
||||
auto fontSize = Scale(26);
|
||||
auto fontSize = Scale(24);
|
||||
auto textSize = g_fntNewRodinUB->CalcTextSizeA(fontSize, FLT_MAX, 0, text);
|
||||
auto cornerRadius = 23;
|
||||
auto textMarginX = Scale(16) + (Scale(cornerRadius) / 2);
|
||||
|
|
@ -134,26 +122,25 @@ static void DrawHeaderContainer(const char* text)
|
|||
|
||||
// Slide animation.
|
||||
auto containerMarginX = g_isClosing
|
||||
? Hermite(256, 156, containerMotion)
|
||||
: Hermite(156, 256, containerMotion);
|
||||
? Hermite(251, 151, containerMotion)
|
||||
: Hermite(151, 251, containerMotion);
|
||||
|
||||
// Transparency fade animation.
|
||||
auto alpha = g_isClosing
|
||||
? Lerp(1, 0, colourMotion)
|
||||
: Lerp(0, 1, colourMotion);
|
||||
|
||||
ImVec2 min = { Scale(containerMarginX), Scale(138) };
|
||||
ImVec2 max = { min.x + textMarginX * 2 + textSize.x, Scale(185) };
|
||||
ImVec2 min = { Scale(containerMarginX), Scale(136) };
|
||||
ImVec2 max = { min.x + textMarginX * 2 + textSize.x + Scale(5), Scale(196) };
|
||||
|
||||
DrawContainer(min, max, IM_COL32(140, 142, 140, 201), IM_COL32(66, 65, 66, 234), alpha, cornerRadius);
|
||||
drawList->PopClipRect();
|
||||
DrawPauseHeaderContainer(g_upWindow, min, max, alpha);
|
||||
|
||||
// TODO: skew this text and apply bevel.
|
||||
DrawTextWithOutline<int>
|
||||
(
|
||||
g_fntNewRodinUB,
|
||||
fontSize,
|
||||
{ /* X */ min.x + textMarginX, /* Y */ min.y + ((max.y - min.y) - textSize.y) / 2 },
|
||||
{ /* X */ min.x + textMarginX, /* Y */ min.y + ((max.y - min.y) - textSize.y) / 2 - Scale(5) },
|
||||
IM_COL32(255, 255, 255, 255 * alpha),
|
||||
text,
|
||||
3,
|
||||
|
|
@ -168,9 +155,9 @@ static void DrawAchievement(int rowIndex, float yOffset, Achievement& achievemen
|
|||
auto clipRectMin = drawList->GetClipRectMin();
|
||||
auto clipRectMax = drawList->GetClipRectMax();
|
||||
|
||||
auto itemWidth = Scale(708);
|
||||
auto itemWidth = Scale(700);
|
||||
auto itemHeight = Scale(94);
|
||||
auto itemMarginX = Scale(13);
|
||||
auto itemMarginX = Scale(18);
|
||||
auto imageMarginX = Scale(25);
|
||||
auto imageMarginY = Scale(18);
|
||||
auto imageSize = Scale(60);
|
||||
|
|
@ -371,10 +358,16 @@ static void DrawAchievementTotal(ImVec2 min, ImVec2 max)
|
|||
ImVec2 imageMin = { max.x - imageSize - imageMarginX, min.y - imageSize - imageMarginY };
|
||||
ImVec2 imageMax = { imageMin.x + imageSize, imageMin.y + imageSize };
|
||||
|
||||
auto frm = int32_t(floor(ImGui::GetTime() * 30.0f)) % 30;
|
||||
auto w = 256.0f / 7680.0f;
|
||||
auto uv0 = ImVec2(frm * w, 0);
|
||||
auto uv1 = ImVec2((frm + 1) * w, 1);
|
||||
constexpr auto columns = 8;
|
||||
constexpr auto rows = 4;
|
||||
constexpr auto spriteSize = 256.0f;
|
||||
constexpr auto textureWidth = 2048.0f;
|
||||
constexpr auto textureHeight = 1024.0f;
|
||||
auto frameIndex = int32_t(floor(ImGui::GetTime() * 30.0f)) % 30;
|
||||
auto columnIndex = frameIndex % columns;
|
||||
auto rowIndex = frameIndex / columns;
|
||||
auto uv0 = ImVec2(columnIndex * spriteSize / textureWidth, rowIndex * spriteSize / textureHeight);
|
||||
auto uv1 = ImVec2((columnIndex + 1) * spriteSize / textureWidth, (rowIndex + 1) * spriteSize / textureHeight);
|
||||
|
||||
drawList->AddImage(g_upTrophyIcon.get(), imageMin, imageMax, uv0, uv1, IM_COL32(255, 255, 255, 255 * alpha));
|
||||
|
||||
|
|
@ -404,20 +397,20 @@ static void DrawContentContainer()
|
|||
: ComputeMotion(g_appearTime, CONTENT_CONTAINER_COMMON_MOTION_START, CONTENT_CONTAINER_COMMON_MOTION_END);
|
||||
|
||||
auto minX = g_isClosing
|
||||
? Hermite(256, 306, motion)
|
||||
: Hermite(306, 256, motion);
|
||||
? Hermite(251, 301, motion)
|
||||
: Hermite(301, 251, motion);
|
||||
|
||||
auto minY = g_isClosing
|
||||
? Hermite(192, 209, motion)
|
||||
: Hermite(209, 192, motion);
|
||||
? Hermite(189, 206, motion)
|
||||
: Hermite(206, 189, motion);
|
||||
|
||||
auto maxX = g_isClosing
|
||||
? Hermite(1026, 973, motion)
|
||||
: Hermite(973, 1026, motion);
|
||||
? Hermite(1031, 978, motion)
|
||||
: Hermite(978, 1031, motion);
|
||||
|
||||
auto maxY = g_isClosing
|
||||
? Hermite(601, 569, motion)
|
||||
: Hermite(569, 601, motion);
|
||||
? Hermite(604, 573, motion)
|
||||
: Hermite(573, 604, motion);
|
||||
|
||||
ImVec2 min = { Scale(minX), Scale(minY) };
|
||||
ImVec2 max = { Scale(maxX), Scale(maxY) };
|
||||
|
|
@ -449,8 +442,8 @@ static void DrawContentContainer()
|
|||
// Draw separators.
|
||||
for (int i = 1; i <= 3; i++)
|
||||
{
|
||||
auto lineMarginLeft = Scale(31);
|
||||
auto lineMarginRight = Scale(46);
|
||||
auto lineMarginLeft = Scale(35);
|
||||
auto lineMarginRight = Scale(55);
|
||||
auto lineMarginY = Scale(2);
|
||||
|
||||
ImVec2 lineMin = { clipRectMin.x + lineMarginLeft, clipRectMin.y + itemHeight * i + lineMarginY };
|
||||
|
|
@ -568,34 +561,35 @@ static void DrawContentContainer()
|
|||
// Draw scroll bar
|
||||
if (rowCount > visibleRowCount)
|
||||
{
|
||||
float cornerRadius = Scale(25.0f);
|
||||
float totalHeight = (clipRectMax.y - clipRectMin.y - cornerRadius) - Scale(3.0f);
|
||||
float cornerRadius = Scale(25);
|
||||
float totalHeight = (clipRectMax.y - clipRectMin.y - cornerRadius) - Scale(3);
|
||||
float heightRatio = float(visibleRowCount) / float(rowCount);
|
||||
float offsetRatio = float(g_firstVisibleRowIndex) / float(rowCount);
|
||||
float offsetX = clipRectMax.x - Scale(31.0f);
|
||||
float offsetY = offsetRatio * totalHeight + clipRectMin.y + Scale(4.0f);
|
||||
float lineThickness = Scale(1.0f);
|
||||
float innerMarginX = Scale(2.0f);
|
||||
float outerMarginX = Scale(16.0f);
|
||||
float offsetX = clipRectMax.x - Scale(39);
|
||||
float offsetY = offsetRatio * totalHeight + clipRectMin.y + Scale(4);
|
||||
float maxY = max.y - cornerRadius - Scale(3);
|
||||
float lineThickness = Scale(1);
|
||||
float innerMarginX = Scale(2);
|
||||
float outerMarginX = Scale(24);
|
||||
|
||||
// Outline
|
||||
drawList->AddRect
|
||||
(
|
||||
{ /* X */ offsetX - lineThickness, /* Y */ clipRectMin.y - lineThickness },
|
||||
{ /* X */ clipRectMax.x - outerMarginX + lineThickness, /* Y */ max.y - cornerRadius + lineThickness },
|
||||
{ /* X */ clipRectMax.x - outerMarginX + lineThickness, /* Y */ maxY + lineThickness },
|
||||
IM_COL32(255, 255, 255, 155),
|
||||
Scale(0.5f)
|
||||
Scale(1)
|
||||
);
|
||||
|
||||
// Background
|
||||
drawList->AddRectFilledMultiColor
|
||||
(
|
||||
{ /* X */ offsetX, /* Y */ clipRectMin.y },
|
||||
{ /* X */ clipRectMax.x - outerMarginX, /* Y */ max.y - cornerRadius },
|
||||
IM_COL32(82, 85, 82, 186),
|
||||
IM_COL32(82, 85, 82, 186),
|
||||
IM_COL32(74, 73, 74, 185),
|
||||
IM_COL32(74, 73, 74, 185)
|
||||
{ /* X */ clipRectMax.x - outerMarginX, /* Y */ maxY },
|
||||
IM_COL32(123, 125, 123, 255),
|
||||
IM_COL32(123, 125, 123, 255),
|
||||
IM_COL32(97, 99, 97, 255),
|
||||
IM_COL32(97, 99, 97, 255)
|
||||
);
|
||||
|
||||
// Scroll Bar Outline
|
||||
|
|
@ -629,13 +623,9 @@ void AchievementMenu::Init()
|
|||
g_fntNewRodinDB = io.Fonts->AddFontFromFileTTF("FOT-NewRodinPro-DB.otf", 20.0f * FONT_SCALE);
|
||||
g_fntNewRodinUB = io.Fonts->AddFontFromFileTTF("FOT-NewRodinPro-UB.otf", 20.0f * FONT_SCALE);
|
||||
|
||||
size_t bufferSize = 0;
|
||||
auto buffer = ReadAllBytes("achievements_trophy.png", bufferSize);
|
||||
|
||||
if (!bufferSize)
|
||||
return;
|
||||
|
||||
g_upTrophyIcon = LoadTexture(buffer.get(), bufferSize);
|
||||
g_upTrophyIcon = LoadTexture(g_trophy, sizeof(g_trophy));
|
||||
g_upSelectionCursor = LoadTexture(g_select_fill, sizeof(g_select_fill));
|
||||
g_upWindow = LoadTexture(g_general_window, sizeof(g_general_window));
|
||||
}
|
||||
|
||||
void AchievementMenu::Draw()
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include <user/achievement_data.h>
|
||||
#include <app.h>
|
||||
#include <exports.h>
|
||||
#include <res/images/common/general_window.dds.h>
|
||||
|
||||
constexpr double OVERLAY_CONTAINER_COMMON_MOTION_START = 0;
|
||||
constexpr double OVERLAY_CONTAINER_COMMON_MOTION_END = 11;
|
||||
|
|
@ -26,6 +27,8 @@ static Achievement g_achievement;
|
|||
|
||||
static ImFont* g_fntSeurat;
|
||||
|
||||
static std::unique_ptr<GuestTexture> g_upWindow;
|
||||
|
||||
static bool DrawContainer(ImVec2 min, ImVec2 max, float cornerRadius = 25)
|
||||
{
|
||||
auto drawList = ImGui::GetForegroundDrawList();
|
||||
|
|
@ -51,8 +54,6 @@ static bool DrawContainer(ImVec2 min, ImVec2 max, float cornerRadius = 25)
|
|||
max.y = Hermite(centreY, max.y, containerMotion);
|
||||
}
|
||||
|
||||
auto vertices = GetPauseContainerVertices(min, max, cornerRadius);
|
||||
|
||||
// Transparency fade animation.
|
||||
auto colourMotion = g_isClosing
|
||||
? ComputeMotion(g_appearTime, OVERLAY_CONTAINER_OUTRO_FADE_START, OVERLAY_CONTAINER_OUTRO_FADE_END)
|
||||
|
|
@ -62,46 +63,7 @@ static bool DrawContainer(ImVec2 min, ImVec2 max, float cornerRadius = 25)
|
|||
? Hermite(1, 0, colourMotion)
|
||||
: Hermite(0, 1, colourMotion);
|
||||
|
||||
auto colShadow = IM_COL32(0, 0, 0, 156 * alpha);
|
||||
auto colGradientTop = IM_COL32(197, 194, 197, 200 * alpha);
|
||||
auto colGradientBottom = IM_COL32(115, 113, 115, 236 * alpha);
|
||||
|
||||
// TODO: add a drop shadow.
|
||||
|
||||
// Draw vertices with gradient.
|
||||
SetGradient(min, max, colGradientTop, colGradientBottom);
|
||||
drawList->AddConvexPolyFilled(vertices.data(), vertices.size(), IM_COL32(255, 255, 255, 255 * alpha));
|
||||
ResetGradient();
|
||||
|
||||
// Draw outline.
|
||||
drawList->AddPolyline
|
||||
(
|
||||
vertices.data(),
|
||||
vertices.size(),
|
||||
IM_COL32(247, 247, 247, 255 * alpha),
|
||||
true,
|
||||
Scale(2.5f)
|
||||
);
|
||||
|
||||
// Offset vertices to draw 3D effect lines.
|
||||
for (int i = 0; i < vertices.size(); i++)
|
||||
{
|
||||
vertices[i].x -= Scale(0.4f);
|
||||
vertices[i].y -= Scale(0.2f);
|
||||
}
|
||||
|
||||
auto colLineTop = IM_COL32(165, 170, 165, 230 * alpha);
|
||||
auto colLineBottom = IM_COL32(190, 190, 190, 230 * alpha);
|
||||
auto lineThickness = Scale(1.0f);
|
||||
|
||||
// Top left corner bottom to top left corner top.
|
||||
drawList->AddLine(vertices[0], vertices[1], colLineTop, lineThickness * 0.5f);
|
||||
|
||||
// Top left corner bottom to bottom left.
|
||||
drawList->AddRectFilledMultiColor({ vertices[0].x - 0.2f, vertices[0].y }, { vertices[6].x + lineThickness - 0.2f, vertices[6].y }, colLineTop, colLineTop, colLineBottom, colLineBottom);
|
||||
|
||||
// Top left corner top to top right.
|
||||
drawList->AddLine(vertices[1], vertices[2], colLineTop, lineThickness);
|
||||
DrawPauseContainer(g_upWindow, min, max, alpha);
|
||||
|
||||
drawList->PushClipRect(min, max);
|
||||
|
||||
|
|
@ -115,6 +77,8 @@ void AchievementOverlay::Init()
|
|||
constexpr float FONT_SCALE = 2.0f;
|
||||
|
||||
g_fntSeurat = io.Fonts->AddFontFromFileTTF("FOT-SeuratPro-M.otf", 24.0f * FONT_SCALE);
|
||||
|
||||
g_upWindow = LoadTexture(g_general_window, sizeof(g_general_window));
|
||||
}
|
||||
|
||||
void AchievementOverlay::Draw()
|
||||
|
|
@ -138,18 +102,18 @@ void AchievementOverlay::Draw()
|
|||
auto maxSize = std::max(headerSize.x, bodySize.x);
|
||||
|
||||
// Calculate image margins.
|
||||
auto imageMarginX = Scale(20);
|
||||
auto imageMarginY = Scale(20);
|
||||
auto imageMarginX = Scale(25);
|
||||
auto imageMarginY = Scale(22.5f);
|
||||
auto imageSize = Scale(60);
|
||||
|
||||
// Calculate text margins.
|
||||
auto textMarginX = imageMarginX * 2 + imageSize;
|
||||
auto textMarginX = imageMarginX * 2 + imageSize - Scale(5);
|
||||
auto textMarginY = imageMarginY + Scale(2);
|
||||
|
||||
auto containerWidth = imageMarginX + textMarginX + maxSize;
|
||||
|
||||
ImVec2 min = { (res.x / 2) - (containerWidth / 2), Scale(50) };
|
||||
ImVec2 max = { min.x + containerWidth, min.y + Scale(100) };
|
||||
ImVec2 min = { (res.x / 2) - (containerWidth / 2), Scale(55) };
|
||||
ImVec2 max = { min.x + containerWidth, min.y + Scale(105) };
|
||||
|
||||
if (DrawContainer(min, max))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <gpu/imgui_common.h>
|
||||
#include <gpu/video.h>
|
||||
#include <app.h>
|
||||
|
||||
#define PIXELS_TO_UV_COORDS(textureWidth, textureHeight, x, y, width, height) \
|
||||
|
|
@ -84,17 +85,65 @@ static std::vector<ImVec2> GetPauseContainerVertices(ImVec2 min, ImVec2 max, flo
|
|||
|
||||
return
|
||||
{
|
||||
{ min.x, min.y + cornerRadius },
|
||||
{ min.x + cornerRadius, min.y },
|
||||
{ max.x, min.y },
|
||||
{ max.x, min.y + cornerRadius },
|
||||
{ max.x, max.y - cornerRadius },
|
||||
{ max.x - cornerRadius, max.y },
|
||||
{ min.x, max.y },
|
||||
{ min.x, max.y - cornerRadius }
|
||||
{ min.x, min.y + cornerRadius }, // 0 - TL Corner Bottom
|
||||
{ min.x + cornerRadius, min.y }, // 1 - TL Corner Top
|
||||
{ max.x, min.y }, // 2 - TR Corner Top
|
||||
{ max.x, min.y + cornerRadius }, // 3 - TR Corner Bottom
|
||||
{ max.x, max.y - cornerRadius }, // 4 - BR Corner Top
|
||||
{ max.x - cornerRadius, max.y }, // 5 - BR Corner Bottom
|
||||
{ min.x, max.y }, // 6 - BL Corner Bottom
|
||||
{ min.x, max.y - cornerRadius } // 7 - BL Corner Top
|
||||
};
|
||||
}
|
||||
|
||||
static void DrawPauseContainer(std::unique_ptr<GuestTexture>& texture, ImVec2 min, ImVec2 max, float alpha = 1)
|
||||
{
|
||||
auto drawList = ImGui::GetForegroundDrawList();
|
||||
|
||||
auto commonWidth = Scale(35);
|
||||
auto commonHeight = Scale(35);
|
||||
auto bottomHeight = Scale(5);
|
||||
|
||||
auto tl = PIXELS_TO_UV_COORDS(512, 512, 0, 0, 35, 35);
|
||||
auto tc = PIXELS_TO_UV_COORDS(512, 512, 51, 0, 5, 35);
|
||||
auto tr = PIXELS_TO_UV_COORDS(512, 512, 70, 0, 35, 35);
|
||||
auto cl = PIXELS_TO_UV_COORDS(512, 512, 0, 35, 35, 235);
|
||||
auto cc = PIXELS_TO_UV_COORDS(512, 512, 51, 35, 5, 235);
|
||||
auto cr = PIXELS_TO_UV_COORDS(512, 512, 70, 35, 35, 235);
|
||||
auto bl = PIXELS_TO_UV_COORDS(512, 512, 0, 270, 35, 40);
|
||||
auto bc = PIXELS_TO_UV_COORDS(512, 512, 51, 270, 5, 40);
|
||||
auto br = PIXELS_TO_UV_COORDS(512, 512, 70, 270, 35, 40);
|
||||
|
||||
auto colour = IM_COL32(255, 255, 255, 255 * alpha);
|
||||
|
||||
drawList->AddImage(texture.get(), min, { min.x + commonWidth, min.y + commonHeight }, GET_UV_COORDS(tl), colour);
|
||||
drawList->AddImage(texture.get(), { min.x + commonWidth, min.y }, { max.x - commonWidth, min.y + commonHeight }, GET_UV_COORDS(tc), colour);
|
||||
drawList->AddImage(texture.get(), { max.x - commonWidth, min.y }, { max.x, min.y + commonHeight }, GET_UV_COORDS(tr), colour);
|
||||
drawList->AddImage(texture.get(), { min.x, min.y + commonHeight }, { min.x + commonWidth, max.y - commonHeight }, GET_UV_COORDS(cl), colour);
|
||||
drawList->AddImage(texture.get(), { min.x + commonWidth, min.y + commonHeight }, { max.x - commonWidth, max.y - commonHeight }, GET_UV_COORDS(cc), colour);
|
||||
drawList->AddImage(texture.get(), { max.x - commonWidth, min.y + commonHeight }, { max.x, max.y - commonHeight }, GET_UV_COORDS(cr), colour);
|
||||
drawList->AddImage(texture.get(), { min.x, max.y - commonHeight }, { min.x + commonWidth, max.y + bottomHeight }, GET_UV_COORDS(bl), colour);
|
||||
drawList->AddImage(texture.get(), { min.x + commonWidth, max.y - commonHeight }, { max.x - commonWidth, max.y + bottomHeight }, GET_UV_COORDS(bc), colour);
|
||||
drawList->AddImage(texture.get(), { max.x - commonWidth, max.y - commonHeight }, { max.x, max.y + bottomHeight }, GET_UV_COORDS(br), colour);
|
||||
}
|
||||
|
||||
static void DrawPauseHeaderContainer(std::unique_ptr<GuestTexture>& texture, ImVec2 min, ImVec2 max, float alpha = 1)
|
||||
{
|
||||
auto drawList = ImGui::GetForegroundDrawList();
|
||||
|
||||
auto commonWidth = Scale(35);
|
||||
|
||||
auto left = PIXELS_TO_UV_COORDS(512, 512, 0, 314, 35, 60);
|
||||
auto centre = PIXELS_TO_UV_COORDS(512, 512, 51, 314, 5, 60);
|
||||
auto right = PIXELS_TO_UV_COORDS(512, 512, 70, 314, 35, 60);
|
||||
|
||||
auto colour = IM_COL32(255, 255, 255, 255 * alpha);
|
||||
|
||||
drawList->AddImage(texture.get(), min, { min.x + commonWidth, max.y }, GET_UV_COORDS(left), colour);
|
||||
drawList->AddImage(texture.get(), { min.x + commonWidth, min.y }, { max.x - commonWidth, max.y }, GET_UV_COORDS(centre), colour);
|
||||
drawList->AddImage(texture.get(), { max.x - commonWidth, min.y }, max, GET_UV_COORDS(right), colour);
|
||||
}
|
||||
|
||||
static void DrawTextWithMarquee(const ImFont* font, float fontSize, const ImVec2& pos, const ImVec2& min, const ImVec2& max, ImU32 color, const char* text, double time, double delay, double speed)
|
||||
{
|
||||
auto drawList = ImGui::GetForegroundDrawList();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
#include <api/SWA.h>
|
||||
#include <gpu/video.h>
|
||||
#include <exports.h>
|
||||
#include <res/images/pause.dds.h>
|
||||
#include <res/images/common/select_fade.dds.h>
|
||||
|
||||
constexpr double OVERLAY_CONTAINER_COMMON_MOTION_START = 0;
|
||||
constexpr double OVERLAY_CONTAINER_COMMON_MOTION_END = 11;
|
||||
|
|
@ -139,9 +139,9 @@ void DrawButton(int rowIndex, float yOffset, float width, float height, std::str
|
|||
auto colour = IM_COL32(255, 255, 255, 255 * alpha);
|
||||
|
||||
auto width = Scale(11);
|
||||
auto left = PIXELS_TO_UV_COORDS(128, 128, 0, 0, 11, 50);
|
||||
auto centre = PIXELS_TO_UV_COORDS(128, 128, 11, 0, 8, 50);
|
||||
auto right = PIXELS_TO_UV_COORDS(128, 128, 19, 0, 11, 50);
|
||||
auto left = PIXELS_TO_UV_COORDS(64, 64, 0, 0, 11, 50);
|
||||
auto centre = PIXELS_TO_UV_COORDS(64, 64, 11, 0, 8, 50);
|
||||
auto right = PIXELS_TO_UV_COORDS(64, 64, 19, 0, 11, 50);
|
||||
|
||||
drawList->AddImage(g_upSelectionCursor.get(), min, { min.x + width, max.y }, GET_UV_COORDS(left), colour);
|
||||
drawList->AddImage(g_upSelectionCursor.get(), { min.x + width, min.y }, { max.x - width, max.y }, GET_UV_COORDS(centre), colour);
|
||||
|
|
@ -176,7 +176,7 @@ void MessageWindow::Init()
|
|||
|
||||
g_fntSeurat = io.Fonts->AddFontFromFileTTF("FOT-SeuratPro-M.otf", 28.0f * FONT_SCALE);
|
||||
|
||||
g_upSelectionCursor = LoadTexture(g_pause, sizeof(g_pause));
|
||||
g_upSelectionCursor = LoadTexture(g_select_fade, sizeof(g_select_fade));
|
||||
}
|
||||
|
||||
void MessageWindow::Draw()
|
||||
|
|
|
|||
|
|
@ -179,6 +179,10 @@ void Window::Init()
|
|||
SDL_GetWindowWMInfo(s_pWindow, &info);
|
||||
|
||||
s_handle = info.info.win.window;
|
||||
|
||||
SetDarkTitleBar(true);
|
||||
|
||||
SDL_ShowWindow(s_pWindow);
|
||||
}
|
||||
|
||||
void Window::Update()
|
||||
|
|
|
|||
|
|
@ -5,6 +5,12 @@
|
|||
#include <ui/window_events.h>
|
||||
#include <user/config.h>
|
||||
|
||||
#if _WIN32
|
||||
#include <dwmapi.h>
|
||||
#include <kernel/platform.h>
|
||||
#pragma comment(lib, "dwmapi.lib")
|
||||
#endif
|
||||
|
||||
#define DEFAULT_WIDTH 1280
|
||||
#define DEFAULT_HEIGHT 720
|
||||
|
||||
|
|
@ -67,6 +73,23 @@ public:
|
|||
SDL_SetWindowTitle(s_pWindow, title ? title : GetTitle());
|
||||
}
|
||||
|
||||
static void SetDarkTitleBar(bool isEnabled)
|
||||
{
|
||||
#if _WIN32
|
||||
auto version = GetPlatformVersion();
|
||||
|
||||
if (version.Major < 10 || version.Build <= 17763)
|
||||
return;
|
||||
|
||||
auto flag = version.Build >= 18985
|
||||
? DWMWA_USE_IMMERSIVE_DARK_MODE
|
||||
: 19; // DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1
|
||||
|
||||
const DWORD useImmersiveDarkMode = isEnabled;
|
||||
DwmSetWindowAttribute(s_handle, flag, &useImmersiveDarkMode, sizeof(useImmersiveDarkMode));
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool IsFullscreen()
|
||||
{
|
||||
return SDL_GetWindowFlags(s_pWindow) & SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
|
|
@ -144,7 +167,7 @@ public:
|
|||
|
||||
static uint32_t GetWindowFlags()
|
||||
{
|
||||
uint32_t flags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE;
|
||||
uint32_t flags = SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE;
|
||||
|
||||
if (Config::WindowState == EWindowState::Maximised)
|
||||
flags |= SDL_WINDOW_MAXIMIZED;
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit b04e3bdcd9e76a0717cec69822f4eb01cd97d5c6
|
||||
Subproject commit 5b5ad2794a2c78d50dc6a85e71954fb6b9e80ae2
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
"features": [ "sdl2-binding" ]
|
||||
},
|
||||
"magic-enum",
|
||||
"readerwriterqueue",
|
||||
"nativefiledialog-extended"
|
||||
"nativefiledialog-extended",
|
||||
"miniaudio"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue