mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2026-04-28 05:11:37 +00:00
Merge branch 'options-menu-and-installer' of https://github.com/hedge-dev/UnleashedRecomp into options-menu-and-installer
This commit is contained in:
commit
7e701ca516
16 changed files with 620 additions and 46 deletions
|
|
@ -2,6 +2,7 @@ cmake_minimum_required (VERSION 3.20)
|
||||||
|
|
||||||
include($ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake)
|
include($ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake)
|
||||||
set(SWA_THIRDPARTY_ROOT ${CMAKE_SOURCE_DIR}/thirdparty)
|
set(SWA_THIRDPARTY_ROOT ${CMAKE_SOURCE_DIR}/thirdparty)
|
||||||
|
set(SWA_TOOLS_ROOT ${CMAKE_SOURCE_DIR}/tools)
|
||||||
set(CMAKE_CXX_STANDARD 23)
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
set(BUILD_SHARED_LIBS OFF)
|
set(BUILD_SHARED_LIBS OFF)
|
||||||
|
|
||||||
|
|
@ -14,9 +15,9 @@ endif()
|
||||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||||
|
|
||||||
add_subdirectory(${SWA_THIRDPARTY_ROOT})
|
add_subdirectory(${SWA_THIRDPARTY_ROOT})
|
||||||
project("UnleashedRecomp-ALL")
|
add_subdirectory(${SWA_TOOLS_ROOT})
|
||||||
|
|
||||||
include("thirdparty/PowerRecomp/cmake/bin2h.cmake")
|
project("UnleashedRecomp-ALL")
|
||||||
|
|
||||||
# Include sub-projects.
|
# Include sub-projects.
|
||||||
add_subdirectory("UnleashedRecompLib")
|
add_subdirectory("UnleashedRecompLib")
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,32 @@ set(TARGET_NAME "SWA")
|
||||||
|
|
||||||
option(SWA_XAUDIO2 "Use XAudio2 for audio playback" OFF)
|
option(SWA_XAUDIO2 "Use XAudio2 for audio playback" OFF)
|
||||||
|
|
||||||
|
function(BIN2C)
|
||||||
|
cmake_parse_arguments(BIN2C_ARGS "" "TARGET_OBJ;SOURCE_FILE;DEST_FILE;ARRAY_TYPE;ARRAY_NAME" "" ${ARGN})
|
||||||
|
|
||||||
|
if(NOT BIN2C_ARGS_TARGET_OBJ)
|
||||||
|
message(FATAL_ERROR "TARGET_OBJ not specified.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT BIN2C_ARGS_SOURCE_FILE)
|
||||||
|
message(FATAL_ERROR "SOURCE_FILE not specified.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT BIN2C_ARGS_DEST_FILE)
|
||||||
|
set(BIN2C_ARGS_DEST_FILE "${BIN2C_ARGS_SOURCE_FILE}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_custom_command(OUTPUT "${BIN2C_ARGS_DEST_FILE}.c"
|
||||||
|
COMMAND file_to_c "${BIN2C_ARGS_SOURCE_FILE}" "${BIN2C_ARGS_ARRAY_NAME}" "${BIN2C_ARGS_ARRAY_TYPE}" "${BIN2C_ARGS_DEST_FILE}.c" "${BIN2C_ARGS_DEST_FILE}.h"
|
||||||
|
DEPENDS "${BIN2C_ARGS_SOURCE_FILE}" file_to_c
|
||||||
|
BYPRODUCTS "${BIN2C_ARGS_DEST_FILE}.h"
|
||||||
|
COMMENT "Generating binary header for ${BIN2C_ARGS_SOURCE_FILE}..."
|
||||||
|
)
|
||||||
|
|
||||||
|
set_source_files_properties(${BIN2C_ARGS_DEST_FILE}.c PROPERTIES SKIP_PRECOMPILE_HEADERS ON)
|
||||||
|
target_sources(${BIN2C_ARGS_TARGET_OBJ} PRIVATE ${BIN2C_ARGS_DEST_FILE}.c)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
add_compile_options(
|
add_compile_options(
|
||||||
/fp:strict
|
/fp:strict
|
||||||
-march=sandybridge
|
-march=sandybridge
|
||||||
|
|
@ -23,10 +49,6 @@ add_compile_definitions(
|
||||||
_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR # Microsoft wtf?
|
_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR # Microsoft wtf?
|
||||||
_CRT_SECURE_NO_WARNINGS)
|
_CRT_SECURE_NO_WARNINGS)
|
||||||
|
|
||||||
# Generate icon bitmap header for SDL surface.
|
|
||||||
BIN2H(SOURCE_FILE "../UnleashedRecompResources/images/game_icon.bmp" HEADER_FILE "res/icon.h" ARRAY_TYPE "unsigned char" VARIABLE_NAME "g_icon")
|
|
||||||
BIN2H(SOURCE_FILE "../UnleashedRecompResources/images/game_icon_night.bmp" HEADER_FILE "res/icon_night.h" ARRAY_TYPE "unsigned char" VARIABLE_NAME "g_iconNight")
|
|
||||||
|
|
||||||
set(SWA_PRECOMPILED_HEADERS
|
set(SWA_PRECOMPILED_HEADERS
|
||||||
"stdafx.h"
|
"stdafx.h"
|
||||||
)
|
)
|
||||||
|
|
@ -86,6 +108,7 @@ set(SWA_UI_CXX_SOURCES
|
||||||
"ui/achievement_menu.cpp"
|
"ui/achievement_menu.cpp"
|
||||||
"ui/achievement_overlay.cpp"
|
"ui/achievement_overlay.cpp"
|
||||||
"ui/installer_wizard.cpp"
|
"ui/installer_wizard.cpp"
|
||||||
|
"ui/message_window.cpp"
|
||||||
"ui/options_menu.cpp"
|
"ui/options_menu.cpp"
|
||||||
"ui/sdl_listener.cpp"
|
"ui/sdl_listener.cpp"
|
||||||
"ui/window.cpp"
|
"ui/window.cpp"
|
||||||
|
|
@ -107,18 +130,6 @@ set(SWA_INSTALL_CXX_SOURCES
|
||||||
"install/hashes/update.cpp"
|
"install/hashes/update.cpp"
|
||||||
)
|
)
|
||||||
|
|
||||||
set(INSTALLER_IMAGES_DIR "../UnleashedRecompResources/images/installer")
|
|
||||||
BIN2H(SOURCE_FILE "${INSTALLER_IMAGES_DIR}/install_001.dds" HEADER_FILE "res/install_001_dds.h" ARRAY_TYPE "unsigned char" VARIABLE_NAME "g_install001DDS")
|
|
||||||
BIN2H(SOURCE_FILE "${INSTALLER_IMAGES_DIR}/install_002.dds" HEADER_FILE "res/install_002_dds.h" ARRAY_TYPE "unsigned char" VARIABLE_NAME "g_install002DDS")
|
|
||||||
BIN2H(SOURCE_FILE "${INSTALLER_IMAGES_DIR}/install_003.dds" HEADER_FILE "res/install_003_dds.h" ARRAY_TYPE "unsigned char" VARIABLE_NAME "g_install003DDS")
|
|
||||||
BIN2H(SOURCE_FILE "${INSTALLER_IMAGES_DIR}/install_004.dds" HEADER_FILE "res/install_004_dds.h" ARRAY_TYPE "unsigned char" VARIABLE_NAME "g_install004DDS")
|
|
||||||
BIN2H(SOURCE_FILE "${INSTALLER_IMAGES_DIR}/install_005.dds" HEADER_FILE "res/install_005_dds.h" ARRAY_TYPE "unsigned char" VARIABLE_NAME "g_install005DDS")
|
|
||||||
BIN2H(SOURCE_FILE "${INSTALLER_IMAGES_DIR}/install_006.dds" HEADER_FILE "res/install_006_dds.h" ARRAY_TYPE "unsigned char" VARIABLE_NAME "g_install006DDS")
|
|
||||||
BIN2H(SOURCE_FILE "${INSTALLER_IMAGES_DIR}/install_007.dds" HEADER_FILE "res/install_007_dds.h" ARRAY_TYPE "unsigned char" VARIABLE_NAME "g_install007DDS")
|
|
||||||
BIN2H(SOURCE_FILE "${INSTALLER_IMAGES_DIR}/install_008.dds" HEADER_FILE "res/install_008_dds.h" ARRAY_TYPE "unsigned char" VARIABLE_NAME "g_install008DDS")
|
|
||||||
BIN2H(SOURCE_FILE "${INSTALLER_IMAGES_DIR}/miles_electric_icon.dds" HEADER_FILE "res/miles_electric_icon_dds.h" ARRAY_TYPE "unsigned char" VARIABLE_NAME "g_milesElectricIconDDS")
|
|
||||||
BIN2H(SOURCE_FILE "${INSTALLER_IMAGES_DIR}/arrow_circle.dds" HEADER_FILE "res/arrow_circle_dds.h" ARRAY_TYPE "unsigned char" VARIABLE_NAME "g_arrowCircleDDS")
|
|
||||||
|
|
||||||
set(LIBMSPACK_PATH ${SWA_THIRDPARTY_ROOT}/libmspack/libmspack/mspack)
|
set(LIBMSPACK_PATH ${SWA_THIRDPARTY_ROOT}/libmspack/libmspack/mspack)
|
||||||
|
|
||||||
set(LIBMSPACK_C_SOURCES
|
set(LIBMSPACK_C_SOURCES
|
||||||
|
|
@ -301,3 +312,20 @@ generate_aggregate_header(
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/api"
|
"${CMAKE_CURRENT_SOURCE_DIR}/api"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/api/SWA.h"
|
"${CMAKE_CURRENT_SOURCE_DIR}/api/SWA.h"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
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")
|
||||||
|
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_002.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_002.dds" ARRAY_TYPE "unsigned char" ARRAY_NAME "g_install_002")
|
||||||
|
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_003.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_003.dds" ARRAY_TYPE "unsigned char" ARRAY_NAME "g_install_003")
|
||||||
|
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_004.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_004.dds" ARRAY_TYPE "unsigned char" ARRAY_NAME "g_install_004")
|
||||||
|
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_005.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_005.dds" ARRAY_TYPE "unsigned char" ARRAY_NAME "g_install_005")
|
||||||
|
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_006.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_006.dds" ARRAY_TYPE "unsigned char" ARRAY_NAME "g_install_006")
|
||||||
|
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/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")
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
#include <shader/shader_cache.h>
|
#include <shader/shader_cache.h>
|
||||||
#include <ui/achievement_menu.h>
|
#include <ui/achievement_menu.h>
|
||||||
#include <ui/achievement_overlay.h>
|
#include <ui/achievement_overlay.h>
|
||||||
|
#include <ui/message_window.h>
|
||||||
#include <ui/options_menu.h>
|
#include <ui/options_menu.h>
|
||||||
#include <ui/installer_wizard.h>
|
#include <ui/installer_wizard.h>
|
||||||
|
|
||||||
|
|
@ -1066,6 +1067,7 @@ static void CreateImGuiBackend()
|
||||||
|
|
||||||
AchievementMenu::Init();
|
AchievementMenu::Init();
|
||||||
AchievementOverlay::Init();
|
AchievementOverlay::Init();
|
||||||
|
MessageWindow::Init();
|
||||||
OptionsMenu::Init();
|
OptionsMenu::Init();
|
||||||
InstallerWizard::Init();
|
InstallerWizard::Init();
|
||||||
|
|
||||||
|
|
@ -1741,6 +1743,7 @@ static void DrawImGui()
|
||||||
OptionsMenu::Draw();
|
OptionsMenu::Draw();
|
||||||
AchievementOverlay::Draw();
|
AchievementOverlay::Draw();
|
||||||
InstallerWizard::Draw();
|
InstallerWizard::Draw();
|
||||||
|
MessageWindow::Draw();
|
||||||
|
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
|
|
||||||
|
|
|
||||||
1
UnleashedRecomp/res/.gitignore
vendored
1
UnleashedRecomp/res/.gitignore
vendored
|
|
@ -1,2 +1,3 @@
|
||||||
![Ww][Ii][Nn]32/
|
![Ww][Ii][Nn]32/
|
||||||
|
*.c
|
||||||
*.h
|
*.h
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <span>
|
||||||
#include <xbox.h>
|
#include <xbox.h>
|
||||||
#include <xxhash.h>
|
#include <xxhash.h>
|
||||||
#include <ankerl/unordered_dense.h>
|
#include <ankerl/unordered_dense.h>
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,12 @@
|
||||||
#include <gpu/imgui_common.h>
|
#include <gpu/imgui_common.h>
|
||||||
#include <app.h>
|
#include <app.h>
|
||||||
|
|
||||||
|
#define PIXELS_TO_UV_COORDS(textureWidth, textureHeight, x, y, width, height) \
|
||||||
|
std::make_tuple(ImVec2((float)x / (float)textureWidth, (float)y / (float)textureHeight), \
|
||||||
|
ImVec2(((float)x + (float)width) / (float)textureWidth, ((float)y + (float)height) / (float)textureHeight))
|
||||||
|
|
||||||
|
#define GET_UV_COORDS(tuple) std::get<0>(tuple), std::get<1>(tuple)
|
||||||
|
|
||||||
static std::vector<std::unique_ptr<ImGuiCallbackData>> g_callbackData;
|
static std::vector<std::unique_ptr<ImGuiCallbackData>> g_callbackData;
|
||||||
static uint32_t g_callbackDataIndex = 0;
|
static uint32_t g_callbackDataIndex = 0;
|
||||||
|
|
||||||
|
|
@ -150,7 +156,80 @@ static void DrawTextWithShadow(const ImFont* font, float fontSize, const ImVec2&
|
||||||
|
|
||||||
DrawTextWithOutline<float>(font, fontSize, { pos.x + offset, pos.y + offset }, shadowColour, text, radius, shadowColour);
|
DrawTextWithOutline<float>(font, fontSize, { pos.x + offset, pos.y + offset }, shadowColour, text, radius, shadowColour);
|
||||||
|
|
||||||
drawList->AddText(font, fontSize, pos, colour, text);
|
drawList->AddText(font, fontSize, pos, colour, text, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static float CalcWidestTextSize(const ImFont* font, float fontSize, std::span<std::string> strs)
|
||||||
|
{
|
||||||
|
auto result = 0.0f;
|
||||||
|
|
||||||
|
for (auto& str : strs)
|
||||||
|
result = std::max(result, font->CalcTextSizeA(fontSize, FLT_MAX, 0, str.c_str()).x);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<std::string> Split(const char* str, char delimiter)
|
||||||
|
{
|
||||||
|
std::vector<std::string> result;
|
||||||
|
|
||||||
|
if (!str)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
const char* start = str;
|
||||||
|
const char* current = str;
|
||||||
|
|
||||||
|
while (*current)
|
||||||
|
{
|
||||||
|
if (*current == delimiter)
|
||||||
|
{
|
||||||
|
result.emplace_back(start, current - start);
|
||||||
|
start = current + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
current++;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.emplace_back(start);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ImVec2 MeasureCentredParagraph(const ImFont* font, float fontSize, float lineMargin, std::vector<std::string> lines)
|
||||||
|
{
|
||||||
|
auto x = 0.0f;
|
||||||
|
auto y = 0.0f;
|
||||||
|
|
||||||
|
for (auto& str : lines)
|
||||||
|
{
|
||||||
|
auto textSize = font->CalcTextSizeA(fontSize, FLT_MAX, 0, str.c_str());
|
||||||
|
|
||||||
|
x = std::max(x, textSize.x);
|
||||||
|
y += textSize.y + Scale(lineMargin);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { x, y };
|
||||||
|
}
|
||||||
|
|
||||||
|
static ImVec2 MeasureCentredParagraph(const ImFont* font, float fontSize, float lineMargin, const char* text)
|
||||||
|
{
|
||||||
|
return MeasureCentredParagraph(font, fontSize, lineMargin, Split(text, '\n'));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DrawCentredParagraph(const ImFont* font, float fontSize, const ImVec2& centre, float lineMargin, const char* text, std::function<void(const char*, ImVec2)> drawMethod)
|
||||||
|
{
|
||||||
|
auto lines = Split(text, '\n');
|
||||||
|
auto paragraphSize = MeasureCentredParagraph(font, fontSize, lineMargin, lines);
|
||||||
|
auto offsetY = 0.0f;
|
||||||
|
|
||||||
|
for (auto& str : lines)
|
||||||
|
{
|
||||||
|
auto textSize = font->CalcTextSizeA(fontSize, FLT_MAX, 0, str.c_str());
|
||||||
|
|
||||||
|
drawMethod(str.c_str(), ImVec2(/* X */ centre.x - textSize.x / 2, /* Y */ centre.y - paragraphSize.y / 2 + offsetY));
|
||||||
|
|
||||||
|
offsetY += textSize.y + Scale(lineMargin);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DrawTextWithMarqueeShadow(const ImFont* font, float fontSize, const ImVec2& pos, const ImVec2& min, const ImVec2& max, ImU32 colour, const char* text, double time, double delay, double speed, float offset = 2.0f, float radius = 0.4f, ImU32 shadowColour = IM_COL32(0, 0, 0, 255))
|
static void DrawTextWithMarqueeShadow(const ImFont* font, float fontSize, const ImVec2& pos, const ImVec2& min, const ImVec2& max, ImU32 colour, const char* text, double time, double delay, double speed, float offset = 2.0f, float radius = 0.4f, ImU32 shadowColour = IM_COL32(0, 0, 0, 255))
|
||||||
|
|
|
||||||
|
|
@ -8,16 +8,16 @@
|
||||||
#include <ui/imgui_utils.h>
|
#include <ui/imgui_utils.h>
|
||||||
#include <ui/window.h>
|
#include <ui/window.h>
|
||||||
|
|
||||||
#include <res/install_001_dds.h>
|
#include <res/images/installer/install_001.dds.h>
|
||||||
#include <res/install_002_dds.h>
|
#include <res/images/installer/install_002.dds.h>
|
||||||
#include <res/install_003_dds.h>
|
#include <res/images/installer/install_003.dds.h>
|
||||||
#include <res/install_004_dds.h>
|
#include <res/images/installer/install_004.dds.h>
|
||||||
#include <res/install_005_dds.h>
|
#include <res/images/installer/install_005.dds.h>
|
||||||
#include <res/install_006_dds.h>
|
#include <res/images/installer/install_006.dds.h>
|
||||||
#include <res/install_007_dds.h>
|
#include <res/images/installer/install_007.dds.h>
|
||||||
#include <res/install_008_dds.h>
|
#include <res/images/installer/install_008.dds.h>
|
||||||
#include <res/miles_electric_icon_dds.h>
|
#include <res/images/installer/miles_electric_icon.dds.h>
|
||||||
#include <res/arrow_circle_dds.h>
|
#include <res/images/installer/arrow_circle.dds.h>
|
||||||
|
|
||||||
static constexpr double SCANLINES_ANIMATION_TIME = 0.0;
|
static constexpr double SCANLINES_ANIMATION_TIME = 0.0;
|
||||||
static constexpr double SCANLINES_ANIMATION_DURATION = 15.0;
|
static constexpr double SCANLINES_ANIMATION_DURATION = 15.0;
|
||||||
|
|
@ -999,16 +999,16 @@ void InstallerWizard::Init()
|
||||||
g_seuratFont = io.Fonts->AddFontFromFileTTF("FOT-SeuratPro-M.otf", 26.0f * FONT_SCALE);
|
g_seuratFont = io.Fonts->AddFontFromFileTTF("FOT-SeuratPro-M.otf", 26.0f * FONT_SCALE);
|
||||||
g_dfsogeistdFont = io.Fonts->AddFontFromFileTTF("DFSoGeiStd-W7.otf", 48.0f * FONT_SCALE);
|
g_dfsogeistdFont = io.Fonts->AddFontFromFileTTF("DFSoGeiStd-W7.otf", 48.0f * FONT_SCALE);
|
||||||
g_newRodinFont = io.Fonts->AddFontFromFileTTF("FOT-NewRodinPro-DB.otf", 20.0f * FONT_SCALE);
|
g_newRodinFont = io.Fonts->AddFontFromFileTTF("FOT-NewRodinPro-DB.otf", 20.0f * FONT_SCALE);
|
||||||
g_installTextures[0] = LoadTexture(g_install001DDS, g_install001DDS_size);
|
g_installTextures[0] = LoadTexture(g_install_001, sizeof(g_install_001));
|
||||||
g_installTextures[1] = LoadTexture(g_install002DDS, g_install002DDS_size);
|
g_installTextures[1] = LoadTexture(g_install_002, sizeof(g_install_002));
|
||||||
g_installTextures[2] = LoadTexture(g_install003DDS, g_install003DDS_size);
|
g_installTextures[2] = LoadTexture(g_install_003, sizeof(g_install_003));
|
||||||
g_installTextures[3] = LoadTexture(g_install004DDS, g_install004DDS_size);
|
g_installTextures[3] = LoadTexture(g_install_004, sizeof(g_install_004));
|
||||||
g_installTextures[4] = LoadTexture(g_install005DDS, g_install005DDS_size);
|
g_installTextures[4] = LoadTexture(g_install_005, sizeof(g_install_005));
|
||||||
g_installTextures[5] = LoadTexture(g_install006DDS, g_install006DDS_size);
|
g_installTextures[5] = LoadTexture(g_install_006, sizeof(g_install_006));
|
||||||
g_installTextures[6] = LoadTexture(g_install007DDS, g_install007DDS_size);
|
g_installTextures[6] = LoadTexture(g_install_007, sizeof(g_install_007));
|
||||||
g_installTextures[7] = LoadTexture(g_install008DDS, g_install008DDS_size);
|
g_installTextures[7] = LoadTexture(g_install_008, sizeof(g_install_008));
|
||||||
g_milesElectricIcon = LoadTexture(g_milesElectricIconDDS, g_milesElectricIconDDS_size);
|
g_milesElectricIcon = LoadTexture(g_miles_electric_icon, sizeof(g_miles_electric_icon));
|
||||||
g_arrowCircle = LoadTexture(g_arrowCircleDDS, g_arrowCircleDDS_size);
|
g_arrowCircle = LoadTexture(g_arrow_circle, sizeof(g_arrow_circle));
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstallerWizard::Draw()
|
void InstallerWizard::Draw()
|
||||||
|
|
|
||||||
335
UnleashedRecomp/ui/message_window.cpp
Normal file
335
UnleashedRecomp/ui/message_window.cpp
Normal file
|
|
@ -0,0 +1,335 @@
|
||||||
|
#include "message_window.h"
|
||||||
|
#include "imgui_utils.h"
|
||||||
|
#include <api/SWA.h>
|
||||||
|
#include <gpu/video.h>
|
||||||
|
#include <exports.h>
|
||||||
|
#include <res/images/pause.dds.h>
|
||||||
|
|
||||||
|
constexpr double OVERLAY_CONTAINER_COMMON_MOTION_START = 0;
|
||||||
|
constexpr double OVERLAY_CONTAINER_COMMON_MOTION_END = 11;
|
||||||
|
constexpr double OVERLAY_CONTAINER_INTRO_FADE_START = 5;
|
||||||
|
constexpr double OVERLAY_CONTAINER_INTRO_FADE_END = 9;
|
||||||
|
constexpr double OVERLAY_CONTAINER_OUTRO_FADE_START = 0;
|
||||||
|
constexpr double OVERLAY_CONTAINER_OUTRO_FADE_END = 4;
|
||||||
|
|
||||||
|
static bool g_isAwaitingResult = false;
|
||||||
|
static bool g_isClosing = false;
|
||||||
|
static bool g_isControlsVisible = false;
|
||||||
|
|
||||||
|
static int g_selectedRowIndex;
|
||||||
|
static int g_foregroundCount;
|
||||||
|
|
||||||
|
static bool g_upWasHeld;
|
||||||
|
static bool g_downWasHeld;
|
||||||
|
|
||||||
|
static double g_appearTime;
|
||||||
|
static double g_controlsAppearTime;
|
||||||
|
|
||||||
|
static ImFont* g_fntSeurat;
|
||||||
|
|
||||||
|
static std::unique_ptr<GuestTexture> g_upSelectionCursor;
|
||||||
|
|
||||||
|
std::string g_text;
|
||||||
|
int g_result;
|
||||||
|
std::vector<std::string> g_buttons;
|
||||||
|
int g_defaultButtonIndex;
|
||||||
|
|
||||||
|
bool DrawContainer(float appearTime, ImVec2 centre, ImVec2 max, bool isForeground = true)
|
||||||
|
{
|
||||||
|
auto drawList = ImGui::GetForegroundDrawList();
|
||||||
|
|
||||||
|
ImVec2 _min = { centre.x - max.x, centre.y - max.y };
|
||||||
|
ImVec2 _max = { centre.x + max.x, centre.y + max.y };
|
||||||
|
|
||||||
|
// Expand/retract animation.
|
||||||
|
auto containerMotion = ComputeMotion(appearTime, OVERLAY_CONTAINER_COMMON_MOTION_START, OVERLAY_CONTAINER_COMMON_MOTION_END);
|
||||||
|
|
||||||
|
if (g_isClosing)
|
||||||
|
{
|
||||||
|
_min.x = Hermite(_min.x, centre.x, containerMotion);
|
||||||
|
_max.x = Hermite(_max.x, centre.x, containerMotion);
|
||||||
|
_min.y = Hermite(_min.y, centre.y, containerMotion);
|
||||||
|
_max.y = Hermite(_max.y, centre.y, containerMotion);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_min.x = Hermite(centre.x, _min.x, containerMotion);
|
||||||
|
_max.x = Hermite(centre.x, _max.x, containerMotion);
|
||||||
|
_min.y = Hermite(centre.y, _min.y, containerMotion);
|
||||||
|
_max.y = Hermite(centre.y, _max.y, containerMotion);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto vertices = GetPauseContainerVertices(_min, _max);
|
||||||
|
|
||||||
|
// Transparency fade animation.
|
||||||
|
auto colourMotion = g_isClosing
|
||||||
|
? ComputeMotion(appearTime, OVERLAY_CONTAINER_OUTRO_FADE_START, OVERLAY_CONTAINER_OUTRO_FADE_END)
|
||||||
|
: ComputeMotion(appearTime, OVERLAY_CONTAINER_INTRO_FADE_START, OVERLAY_CONTAINER_INTRO_FADE_END);
|
||||||
|
|
||||||
|
auto alpha = g_isClosing
|
||||||
|
? Lerp(1, 0, colourMotion)
|
||||||
|
: Lerp(0, 1, colourMotion);
|
||||||
|
|
||||||
|
if (!isForeground)
|
||||||
|
g_foregroundCount++;
|
||||||
|
|
||||||
|
if (isForeground)
|
||||||
|
drawList->AddRectFilled({ 0.0f, 0.0f }, ImGui::GetIO().DisplaySize, IM_COL32(0, 0, 0, 223 * (g_foregroundCount ? 1 : alpha)));
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
drawList->PushClipRect(_min, _max);
|
||||||
|
|
||||||
|
return containerMotion >= 1.0f && !g_isClosing;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawButton(int rowIndex, float yOffset, float width, float height, std::string& text)
|
||||||
|
{
|
||||||
|
auto drawList = ImGui::GetForegroundDrawList();
|
||||||
|
|
||||||
|
auto clipRectMin = drawList->GetClipRectMin();
|
||||||
|
auto clipRectMax = drawList->GetClipRectMax();
|
||||||
|
|
||||||
|
ImVec2 min = { clipRectMin.x + ((clipRectMax.x - clipRectMin.x) - width) / 2, clipRectMin.y + height * rowIndex + yOffset };
|
||||||
|
ImVec2 max = { min.x + width, min.y + height };
|
||||||
|
|
||||||
|
bool isSelected = rowIndex == g_selectedRowIndex;
|
||||||
|
|
||||||
|
if (isSelected)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
drawList->AddImage(g_upSelectionCursor.get(), { max.x - width, min.y }, max, GET_UV_COORDS(right), colour);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto fontSize = Scale(28);
|
||||||
|
auto textSize = g_fntSeurat->CalcTextSizeA(fontSize, FLT_MAX, 0, text.c_str());
|
||||||
|
|
||||||
|
DrawTextWithShadow
|
||||||
|
(
|
||||||
|
g_fntSeurat,
|
||||||
|
fontSize,
|
||||||
|
{ /* X */ min.x + ((max.x - min.x) - textSize.x) / 2, /* Y */ min.y + ((max.y - min.y) - textSize.y) / 2 },
|
||||||
|
isSelected ? IM_COL32(255, 128, 0, 255) : IM_COL32(255, 255, 255, 255),
|
||||||
|
text.c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ResetSelection()
|
||||||
|
{
|
||||||
|
g_selectedRowIndex = g_defaultButtonIndex;
|
||||||
|
g_upWasHeld = false;
|
||||||
|
g_downWasHeld = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageWindow::Init()
|
||||||
|
{
|
||||||
|
auto& io = ImGui::GetIO();
|
||||||
|
|
||||||
|
constexpr float FONT_SCALE = 2.0f;
|
||||||
|
|
||||||
|
g_fntSeurat = io.Fonts->AddFontFromFileTTF("FOT-SeuratPro-M.otf", 28.0f * FONT_SCALE);
|
||||||
|
|
||||||
|
g_upSelectionCursor = LoadTexture(g_pause, sizeof(g_pause));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageWindow::Draw()
|
||||||
|
{
|
||||||
|
if (!s_isVisible)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto pInputState = SWA::CInputState::GetInstance();
|
||||||
|
auto drawList = ImGui::GetForegroundDrawList();
|
||||||
|
auto& res = ImGui::GetIO().DisplaySize;
|
||||||
|
|
||||||
|
ImVec2 centre = { res.x / 2, res.y / 2 };
|
||||||
|
|
||||||
|
auto fontSize = Scale(28);
|
||||||
|
auto textSize = MeasureCentredParagraph(g_fntSeurat, fontSize, 5, g_text.c_str());
|
||||||
|
auto textMarginX = Scale(32);
|
||||||
|
auto textMarginY = Scale(40);
|
||||||
|
|
||||||
|
if (DrawContainer(g_appearTime, centre, { textSize.x / 2 + textMarginX, textSize.y / 2 + textMarginY }, !g_isControlsVisible))
|
||||||
|
{
|
||||||
|
DrawCentredParagraph
|
||||||
|
(
|
||||||
|
g_fntSeurat,
|
||||||
|
fontSize,
|
||||||
|
{ centre.x, centre.y + Scale(3) },
|
||||||
|
5,
|
||||||
|
g_text.c_str(),
|
||||||
|
|
||||||
|
[=](const char* str, ImVec2 pos)
|
||||||
|
{
|
||||||
|
DrawTextWithShadow(g_fntSeurat, fontSize, pos, IM_COL32(255, 255, 255, 255), str);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
drawList->PopClipRect();
|
||||||
|
|
||||||
|
if (g_buttons.size())
|
||||||
|
{
|
||||||
|
auto itemWidth = std::max(Scale(162), Scale(CalcWidestTextSize(g_fntSeurat, fontSize, g_buttons)));
|
||||||
|
auto itemHeight = Scale(57);
|
||||||
|
auto windowMarginX = Scale(18);
|
||||||
|
auto windowMarginY = Scale(25);
|
||||||
|
|
||||||
|
ImVec2 controlsMax = { /* X */ itemWidth / 2 + windowMarginX, /* Y */ itemHeight / 2 * g_buttons.size() + windowMarginY };
|
||||||
|
|
||||||
|
if (g_isControlsVisible && DrawContainer(g_controlsAppearTime, centre, controlsMax))
|
||||||
|
{
|
||||||
|
auto rowCount = 0;
|
||||||
|
|
||||||
|
for (auto& button : g_buttons)
|
||||||
|
DrawButton(rowCount++, windowMarginY, itemWidth, itemHeight, button);
|
||||||
|
|
||||||
|
drawList->PopClipRect();
|
||||||
|
|
||||||
|
bool upIsHeld = pInputState->GetPadState().IsDown(SWA::eKeyState_DpadUp) ||
|
||||||
|
pInputState->GetPadState().LeftStickVertical > 0.5f;
|
||||||
|
|
||||||
|
bool downIsHeld = pInputState->GetPadState().IsDown(SWA::eKeyState_DpadDown) ||
|
||||||
|
pInputState->GetPadState().LeftStickVertical < -0.5f;
|
||||||
|
|
||||||
|
bool scrollUp = !g_upWasHeld && upIsHeld;
|
||||||
|
bool scrollDown = !g_downWasHeld && downIsHeld;
|
||||||
|
|
||||||
|
if (scrollUp)
|
||||||
|
{
|
||||||
|
--g_selectedRowIndex;
|
||||||
|
if (g_selectedRowIndex < 0)
|
||||||
|
g_selectedRowIndex = rowCount - 1;
|
||||||
|
}
|
||||||
|
else if (scrollDown)
|
||||||
|
{
|
||||||
|
++g_selectedRowIndex;
|
||||||
|
if (g_selectedRowIndex >= rowCount)
|
||||||
|
g_selectedRowIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scrollUp || scrollDown)
|
||||||
|
Game_PlaySound("sys_actstg_pausecursor");
|
||||||
|
|
||||||
|
g_upWasHeld = upIsHeld;
|
||||||
|
g_downWasHeld = downIsHeld;
|
||||||
|
|
||||||
|
if (pInputState->GetPadState().IsTapped(SWA::eKeyState_A))
|
||||||
|
{
|
||||||
|
g_result = g_selectedRowIndex;
|
||||||
|
|
||||||
|
Game_PlaySound("sys_actstg_pausedecide");
|
||||||
|
MessageWindow::Close();
|
||||||
|
}
|
||||||
|
else if (pInputState->GetPadState().IsTapped(SWA::eKeyState_B))
|
||||||
|
{
|
||||||
|
g_result = -1;
|
||||||
|
|
||||||
|
Game_PlaySound("sys_actstg_pausecansel");
|
||||||
|
MessageWindow::Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!g_isControlsVisible && pInputState->GetPadState().IsTapped(SWA::eKeyState_A))
|
||||||
|
{
|
||||||
|
g_controlsAppearTime = ImGui::GetTime();
|
||||||
|
g_isControlsVisible = true;
|
||||||
|
|
||||||
|
Game_PlaySound("sys_actstg_pausewinopen");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (pInputState->GetPadState().IsTapped(SWA::eKeyState_A))
|
||||||
|
MessageWindow::Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MessageWindow::Open(std::string text, int* result, std::span<std::string> buttons, int defaultButtonIndex)
|
||||||
|
{
|
||||||
|
if (!g_isAwaitingResult && *result == -1)
|
||||||
|
{
|
||||||
|
s_isVisible = true;
|
||||||
|
g_isClosing = false;
|
||||||
|
g_isControlsVisible = false;
|
||||||
|
g_foregroundCount = 0;
|
||||||
|
g_appearTime = ImGui::GetTime();
|
||||||
|
g_controlsAppearTime = ImGui::GetTime();
|
||||||
|
|
||||||
|
g_text = text;
|
||||||
|
g_buttons = std::vector(buttons.begin(), buttons.end());
|
||||||
|
g_defaultButtonIndex = defaultButtonIndex;
|
||||||
|
|
||||||
|
ResetSelection();
|
||||||
|
|
||||||
|
Game_PlaySound("sys_actstg_pausewinopen");
|
||||||
|
|
||||||
|
g_isAwaitingResult = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
*result = g_result;
|
||||||
|
|
||||||
|
return !g_isAwaitingResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageWindow::Close()
|
||||||
|
{
|
||||||
|
if (!g_isClosing)
|
||||||
|
{
|
||||||
|
g_appearTime = ImGui::GetTime();
|
||||||
|
g_controlsAppearTime = ImGui::GetTime();
|
||||||
|
g_isClosing = true;
|
||||||
|
g_isControlsVisible = false;
|
||||||
|
g_isAwaitingResult = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Game_PlaySound("sys_actstg_pausewinclose");
|
||||||
|
}
|
||||||
12
UnleashedRecomp/ui/message_window.h
Normal file
12
UnleashedRecomp/ui/message_window.h
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
class MessageWindow
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline static bool s_isVisible = false;
|
||||||
|
|
||||||
|
static void Init();
|
||||||
|
static void Draw();
|
||||||
|
static bool Open(std::string text, int* result, std::span<std::string> buttons = {}, int defaultButtonIndex = 0);
|
||||||
|
static void Close();
|
||||||
|
};
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include <api/SWA.h>
|
#include <api/SWA.h>
|
||||||
|
|
||||||
struct OptionsMenu
|
class OptionsMenu
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline static bool s_isVisible = false;
|
inline static bool s_isVisible = false;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <res/icon.h>
|
#include <res/images/game_icon.bmp.h>
|
||||||
#include <res/icon_night.h>
|
#include <res/images/game_icon_night.bmp.h>
|
||||||
#include <ui/window_events.h>
|
#include <ui/window_events.h>
|
||||||
#include <user/config.h>
|
#include <user/config.h>
|
||||||
|
|
||||||
|
|
@ -47,11 +47,11 @@ public:
|
||||||
{
|
{
|
||||||
if (isNight)
|
if (isNight)
|
||||||
{
|
{
|
||||||
SetIcon((void*)g_iconNight, g_iconNight_size);
|
SetIcon(g_game_icon_night, sizeof(g_game_icon_night));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SetIcon((void*)g_icon, g_icon_size);
|
SetIcon(g_game_icon, sizeof(g_game_icon));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 79a2a18cc8013dd6d76d8300f703f19f6e0ec484
|
Subproject commit b04e3bdcd9e76a0717cec69822f4eb01cd97d5c6
|
||||||
2
thirdparty/PowerRecomp
vendored
2
thirdparty/PowerRecomp
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit 675b482ec4852b873590fb999d24b426bade2b3a
|
Subproject commit ea3e60cb0d618ec8d24cc745d72b1ac39cc722cc
|
||||||
1
tools/CMakeLists.txt
Normal file
1
tools/CMakeLists.txt
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
add_subdirectory(${SWA_TOOLS_ROOT}/file_to_c)
|
||||||
8
tools/file_to_c/CMakeLists.txt
Normal file
8
tools/file_to_c/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
cmake_minimum_required(VERSION 3.20)
|
||||||
|
|
||||||
|
include(CMakeParseArguments)
|
||||||
|
|
||||||
|
project("file_to_c")
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
|
add_executable(file_to_c "file_to_c.cpp")
|
||||||
105
tools/file_to_c/file_to_c.cpp
Normal file
105
tools/file_to_c/file_to_c.cpp
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
/*
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024 RT64 Contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
std::vector<char> read_file(const char* path) {
|
||||||
|
std::ifstream input_file{path, std::ios::binary};
|
||||||
|
std::vector<char> ret{};
|
||||||
|
|
||||||
|
if (!input_file.good()) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the length of the file
|
||||||
|
input_file.seekg(0, std::ios::end);
|
||||||
|
ret.resize(input_file.tellg());
|
||||||
|
|
||||||
|
// Read the file contents into the vector
|
||||||
|
input_file.seekg(0, std::ios::beg);
|
||||||
|
input_file.read(ret.data(), ret.size());
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void create_parent_if_needed(const char* path) {
|
||||||
|
std::filesystem::path parent_path = std::filesystem::path{path}.parent_path();
|
||||||
|
if (!parent_path.empty()) {
|
||||||
|
std::filesystem::create_directories(parent_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, const char** argv) {
|
||||||
|
if (argc != 6) {
|
||||||
|
printf("Usage: %s [input file] [array name] [array type] [output C file] [output C header]\n", argv[0]);
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* input_path = argv[1];
|
||||||
|
const char* array_name = argv[2];
|
||||||
|
const char* array_type = argv[3];
|
||||||
|
const char* output_c_path = argv[4];
|
||||||
|
const char* output_h_path = argv[5];
|
||||||
|
|
||||||
|
// Read the input file's contents
|
||||||
|
std::vector<char> contents = read_file(input_path);
|
||||||
|
|
||||||
|
if (contents.empty()) {
|
||||||
|
fprintf(stderr, "Failed to open file %s! (Or it's empty)\n", input_path);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the output directories if they don't exist
|
||||||
|
create_parent_if_needed(output_c_path);
|
||||||
|
create_parent_if_needed(output_h_path);
|
||||||
|
|
||||||
|
// Write the C file with the array
|
||||||
|
{
|
||||||
|
std::ofstream output_c_file{output_c_path};
|
||||||
|
output_c_file << "extern " << array_type << " " << array_name << "[" << contents.size() << "];\n";
|
||||||
|
output_c_file << array_type << " " << array_name << "[" << contents.size() << "] = {";
|
||||||
|
|
||||||
|
for (char x : contents) {
|
||||||
|
output_c_file << (int)x << ", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
output_c_file << "};\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the header file with the extern array
|
||||||
|
{
|
||||||
|
std::ofstream output_h_file{output_h_path};
|
||||||
|
output_h_file <<
|
||||||
|
"#ifdef __cplusplus\n"
|
||||||
|
" extern \"C\" {\n"
|
||||||
|
"#endif\n"
|
||||||
|
"extern " << array_type << " " << array_name << "[" << contents.size() << "];\n"
|
||||||
|
"#ifdef __cplusplus\n"
|
||||||
|
" }\n"
|
||||||
|
"#endif\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue