mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2025-10-30 07:11:05 +00:00
Implement SDF fonts. (#24)
* Initial SDF font generation work. * Text now correctly displaying with proper spacing. * Fix untextured draws, implement custom rectangles. * Fix regular image display. * Slightly refactor ImGui rendering. * Implement outlines. * Implement bevel. * Create host device after loading the module if the installer wasn't run. * Move ImGui files to its own folder. * Fix outline sizes. * Fix default ImGui font and font scales. * Update font atlas files.
This commit is contained in:
parent
632cf2619e
commit
cdcacff53b
23 changed files with 536 additions and 154 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
|
@ -13,3 +13,6 @@
|
||||||
[submodule "UnleashedRecompResources"]
|
[submodule "UnleashedRecompResources"]
|
||||||
path = UnleashedRecompResources
|
path = UnleashedRecompResources
|
||||||
url = https://github.com/hedge-dev/UnleashedRecompResources.git
|
url = https://github.com/hedge-dev/UnleashedRecompResources.git
|
||||||
|
[submodule "thirdparty/msdf-atlas-gen"]
|
||||||
|
path = thirdparty/msdf-atlas-gen
|
||||||
|
url = https://github.com/Chlumsky/msdf-atlas-gen.git
|
||||||
|
|
|
||||||
|
|
@ -87,8 +87,9 @@ set(SWA_CPU_CXX_SOURCES
|
||||||
|
|
||||||
set(SWA_GPU_CXX_SOURCES
|
set(SWA_GPU_CXX_SOURCES
|
||||||
"gpu/video.cpp"
|
"gpu/video.cpp"
|
||||||
"gpu/imgui_common.cpp"
|
"gpu/imgui/imgui_common.cpp"
|
||||||
"gpu/imgui_snapshot.cpp"
|
"gpu/imgui/imgui_font_builder.cpp"
|
||||||
|
"gpu/imgui/imgui_snapshot.cpp"
|
||||||
"gpu/rhi/plume_d3d12.cpp"
|
"gpu/rhi/plume_d3d12.cpp"
|
||||||
"gpu/rhi/plume_vulkan.cpp"
|
"gpu/rhi/plume_vulkan.cpp"
|
||||||
)
|
)
|
||||||
|
|
@ -258,6 +259,7 @@ target_link_libraries(UnleashedRecomp PRIVATE
|
||||||
magic_enum::magic_enum
|
magic_enum::magic_enum
|
||||||
unofficial::tiny-aes-c::tiny-aes-c
|
unofficial::tiny-aes-c::tiny-aes-c
|
||||||
nfd::nfd
|
nfd::nfd
|
||||||
|
msdf-atlas-gen::msdf-atlas-gen
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(UnleashedRecomp PRIVATE
|
target_include_directories(UnleashedRecomp PRIVATE
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@
|
||||||
#define IMGUI_SHADER_MODIFIER_TEXT_SKEW 4
|
#define IMGUI_SHADER_MODIFIER_TEXT_SKEW 4
|
||||||
#define IMGUI_SHADER_MODIFIER_MARQUEE_FADE 5
|
#define IMGUI_SHADER_MODIFIER_MARQUEE_FADE 5
|
||||||
#define IMGUI_SHADER_MODIFIER_GRAYSCALE 6
|
#define IMGUI_SHADER_MODIFIER_GRAYSCALE 6
|
||||||
|
#define IMGUI_SHADER_MODIFIER_TITLE_BEVEL 7
|
||||||
|
#define IMGUI_SHADER_MODIFIER_CATEGORY_BEVEL 8
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
|
@ -17,6 +19,7 @@ enum class ImGuiCallback : int32_t
|
||||||
SetOrigin = -3,
|
SetOrigin = -3,
|
||||||
SetScale = -4,
|
SetScale = -4,
|
||||||
SetMarqueeFade = -5,
|
SetMarqueeFade = -5,
|
||||||
|
SetOutline = -6,
|
||||||
// -8 is ImDrawCallback_ResetRenderState, don't use!
|
// -8 is ImDrawCallback_ResetRenderState, don't use!
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -50,6 +53,11 @@ union ImGuiCallbackData
|
||||||
float boundsMin[2];
|
float boundsMin[2];
|
||||||
float boundsMax[2];
|
float boundsMax[2];
|
||||||
} setMarqueeFade;
|
} setMarqueeFade;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
float outline;
|
||||||
|
} setOutline;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ImGuiCallbackData* AddImGuiCallback(ImGuiCallback callback);
|
extern ImGuiCallbackData* AddImGuiCallback(ImGuiCallback callback);
|
||||||
274
UnleashedRecomp/gpu/imgui/imgui_font_builder.cpp
Normal file
274
UnleashedRecomp/gpu/imgui/imgui_font_builder.cpp
Normal file
|
|
@ -0,0 +1,274 @@
|
||||||
|
#include "imgui_font_builder.h"
|
||||||
|
|
||||||
|
#include <msdf-atlas-gen/msdf-atlas-gen.h>
|
||||||
|
|
||||||
|
// Taken directly from msdf-atlas-gen, modified to support custom rectangles.
|
||||||
|
struct TightAtlasPacker {
|
||||||
|
|
||||||
|
TightAtlasPacker() :
|
||||||
|
width(-1), height(-1),
|
||||||
|
spacing(0),
|
||||||
|
dimensionsConstraint(msdf_atlas::DimensionsConstraint::POWER_OF_TWO_SQUARE),
|
||||||
|
scale(-1),
|
||||||
|
minScale(1),
|
||||||
|
unitRange(0),
|
||||||
|
pxRange(0),
|
||||||
|
miterLimit(0),
|
||||||
|
pxAlignOriginX(false), pxAlignOriginY(false),
|
||||||
|
scaleMaximizationTolerance(.001)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int pack(msdf_atlas::GlyphGeometry* glyphs, int count, msdf_atlas::Rectangle* customRects, int customRectCount) {
|
||||||
|
double initialScale = scale > 0 ? scale : minScale;
|
||||||
|
if (initialScale > 0) {
|
||||||
|
if (int remaining = tryPack(glyphs, count, customRects, customRectCount, dimensionsConstraint, width, height, initialScale))
|
||||||
|
return remaining;
|
||||||
|
}
|
||||||
|
else if (width < 0 || height < 0)
|
||||||
|
return -1;
|
||||||
|
if (scale <= 0)
|
||||||
|
scale = packAndScale(glyphs, count, customRects, customRectCount);
|
||||||
|
if (scale <= 0)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int width, height;
|
||||||
|
int spacing;
|
||||||
|
msdf_atlas::DimensionsConstraint dimensionsConstraint;
|
||||||
|
double scale;
|
||||||
|
double minScale;
|
||||||
|
msdfgen::Range unitRange;
|
||||||
|
msdfgen::Range pxRange;
|
||||||
|
double miterLimit;
|
||||||
|
bool pxAlignOriginX, pxAlignOriginY;
|
||||||
|
msdf_atlas::Padding innerUnitPadding, outerUnitPadding;
|
||||||
|
msdf_atlas::Padding innerPxPadding, outerPxPadding;
|
||||||
|
double scaleMaximizationTolerance;
|
||||||
|
|
||||||
|
int tryPack(msdf_atlas::GlyphGeometry* glyphs, int count, msdf_atlas::Rectangle* customRects, int customRectCount, msdf_atlas::DimensionsConstraint dimensionsConstraint, int& width, int& height, double scale) const {
|
||||||
|
// Wrap glyphs into boxes
|
||||||
|
std::vector<msdf_atlas::Rectangle> rectangles;
|
||||||
|
std::vector<msdf_atlas::GlyphGeometry*> rectangleGlyphs;
|
||||||
|
rectangles.reserve(count + customRectCount);
|
||||||
|
rectangleGlyphs.reserve(count);
|
||||||
|
msdf_atlas::GlyphGeometry::GlyphAttributes attribs = { };
|
||||||
|
attribs.scale = scale;
|
||||||
|
attribs.range = { unitRange.lower + pxRange.lower / scale, unitRange.upper + pxRange.upper / scale };
|
||||||
|
attribs.innerPadding = innerUnitPadding + innerPxPadding / scale;
|
||||||
|
attribs.outerPadding = outerUnitPadding + outerPxPadding / scale;
|
||||||
|
attribs.miterLimit = miterLimit;
|
||||||
|
attribs.pxAlignOriginX = pxAlignOriginX;
|
||||||
|
attribs.pxAlignOriginY = pxAlignOriginY;
|
||||||
|
for (msdf_atlas::GlyphGeometry* glyph = glyphs, *end = glyphs + count; glyph < end; ++glyph) {
|
||||||
|
if (!glyph->isWhitespace()) {
|
||||||
|
msdf_atlas::Rectangle rect = { };
|
||||||
|
glyph->wrapBox(attribs);
|
||||||
|
glyph->getBoxSize(rect.w, rect.h);
|
||||||
|
if (rect.w > 0 && rect.h > 0) {
|
||||||
|
rectangles.push_back(rect);
|
||||||
|
rectangleGlyphs.push_back(glyph);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rectangles.insert(rectangles.end(), customRects, customRects + customRectCount);
|
||||||
|
// No non-zero size boxes?
|
||||||
|
if (rectangles.empty()) {
|
||||||
|
if (width < 0 || height < 0)
|
||||||
|
width = 0, height = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// Box rectangle packing
|
||||||
|
if (width < 0 || height < 0) {
|
||||||
|
std::pair<int, int> dimensions = std::make_pair(width, height);
|
||||||
|
switch (dimensionsConstraint) {
|
||||||
|
case msdf_atlas::DimensionsConstraint::POWER_OF_TWO_SQUARE:
|
||||||
|
dimensions = msdf_atlas::packRectangles<msdf_atlas::SquarePowerOfTwoSizeSelector>(rectangles.data(), rectangles.size(), spacing);
|
||||||
|
break;
|
||||||
|
case msdf_atlas::DimensionsConstraint::POWER_OF_TWO_RECTANGLE:
|
||||||
|
dimensions = msdf_atlas::packRectangles<msdf_atlas::PowerOfTwoSizeSelector>(rectangles.data(), rectangles.size(), spacing);
|
||||||
|
break;
|
||||||
|
case msdf_atlas::DimensionsConstraint::MULTIPLE_OF_FOUR_SQUARE:
|
||||||
|
dimensions = msdf_atlas::packRectangles<msdf_atlas::SquareSizeSelector<4> >(rectangles.data(), rectangles.size(), spacing);
|
||||||
|
break;
|
||||||
|
case msdf_atlas::DimensionsConstraint::EVEN_SQUARE:
|
||||||
|
dimensions = msdf_atlas::packRectangles<msdf_atlas::SquareSizeSelector<2> >(rectangles.data(), rectangles.size(), spacing);
|
||||||
|
break;
|
||||||
|
case msdf_atlas::DimensionsConstraint::SQUARE:
|
||||||
|
default:
|
||||||
|
dimensions = msdf_atlas::packRectangles<msdf_atlas::SquareSizeSelector<> >(rectangles.data(), rectangles.size(), spacing);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!(dimensions.first > 0 && dimensions.second > 0))
|
||||||
|
return -1;
|
||||||
|
width = dimensions.first, height = dimensions.second;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (int result = packRectangles(rectangles.data(), rectangles.size(), width, height, spacing))
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set glyph box placement
|
||||||
|
for (size_t i = 0; i < rectangleGlyphs.size(); ++i)
|
||||||
|
rectangleGlyphs[i]->placeBox(rectangles[i].x, height - (rectangles[i].y + rectangles[i].h));
|
||||||
|
|
||||||
|
for (int i = 0; i < customRectCount; ++i) {
|
||||||
|
customRects[i].x = rectangles[rectangleGlyphs.size() + i].x;
|
||||||
|
customRects[i].y = height - (rectangles[rectangleGlyphs.size() + i].y + rectangles[rectangleGlyphs.size() + i].h);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double packAndScale(msdf_atlas::GlyphGeometry* glyphs, int count, msdf_atlas::Rectangle* customRects, int customRectCount) const {
|
||||||
|
bool lastResult = false;
|
||||||
|
int w = width, h = height;
|
||||||
|
#define TRY_PACK(scale) (lastResult = !tryPack(glyphs, count, customRects, customRectCount, msdf_atlas::DimensionsConstraint(), w, h, (scale)))
|
||||||
|
double minScale = 1, maxScale = 1;
|
||||||
|
if (TRY_PACK(1)) {
|
||||||
|
while (maxScale < 1e+32 && ((maxScale = 2 * minScale), TRY_PACK(maxScale)))
|
||||||
|
minScale = maxScale;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
while (minScale > 1e-32 && ((minScale = .5 * maxScale), !TRY_PACK(minScale)))
|
||||||
|
maxScale = minScale;
|
||||||
|
}
|
||||||
|
if (minScale == maxScale)
|
||||||
|
return 0;
|
||||||
|
while (minScale / maxScale < 1 - scaleMaximizationTolerance) {
|
||||||
|
double midScale = .5 * (minScale + maxScale);
|
||||||
|
if (TRY_PACK(midScale))
|
||||||
|
minScale = midScale;
|
||||||
|
else
|
||||||
|
maxScale = midScale;
|
||||||
|
}
|
||||||
|
if (!lastResult)
|
||||||
|
TRY_PACK(minScale);
|
||||||
|
return minScale;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void ImFontAtlasBuildInit(ImFontAtlas* atlas);
|
||||||
|
extern void ImFontAtlasBuildFinish(ImFontAtlas* atlas);
|
||||||
|
|
||||||
|
static bool FontBuilder_Build(ImFontAtlas* atlas)
|
||||||
|
{
|
||||||
|
ImFontAtlasBuildInit(atlas);
|
||||||
|
|
||||||
|
auto freeType = msdfgen::initializeFreetype();
|
||||||
|
|
||||||
|
std::vector<msdf_atlas::GlyphGeometry> glyphs;
|
||||||
|
std::vector<std::pair<size_t, size_t>> ranges;
|
||||||
|
std::vector<msdf_atlas::Rectangle> customRects;
|
||||||
|
|
||||||
|
for (auto& config : atlas->ConfigData)
|
||||||
|
{
|
||||||
|
msdf_atlas::Charset charset;
|
||||||
|
const ImWchar* glyphRanges = config.GlyphRanges;
|
||||||
|
while (*glyphRanges != NULL)
|
||||||
|
{
|
||||||
|
for (ImWchar i = glyphRanges[0]; i <= glyphRanges[1]; i++)
|
||||||
|
charset.add(i);
|
||||||
|
|
||||||
|
glyphRanges += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t index = glyphs.size();
|
||||||
|
|
||||||
|
auto font = msdfgen::loadFontData(freeType, reinterpret_cast<const msdfgen::byte*>(config.FontData), config.FontDataSize);
|
||||||
|
|
||||||
|
msdf_atlas::FontGeometry fontGeometry(&glyphs);
|
||||||
|
fontGeometry.loadCharset(font, config.SizePixels, charset);
|
||||||
|
|
||||||
|
auto& metrics = fontGeometry.getMetrics();
|
||||||
|
config.DstFont->FontSize = config.SizePixels;
|
||||||
|
config.DstFont->ConfigData = &config;
|
||||||
|
config.DstFont->ConfigDataCount = 1;
|
||||||
|
config.DstFont->ContainerAtlas = atlas;
|
||||||
|
config.DstFont->Ascent = metrics.ascenderY;
|
||||||
|
config.DstFont->Descent = metrics.descenderY;
|
||||||
|
|
||||||
|
msdfgen::destroyFont(font);
|
||||||
|
|
||||||
|
ranges.emplace_back(index, glyphs.size() - index);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& glyph : glyphs)
|
||||||
|
glyph.edgeColoring(&msdfgen::edgeColoringByDistance, 3.0, 0);
|
||||||
|
|
||||||
|
for (auto& customRect : atlas->CustomRects)
|
||||||
|
customRects.emplace_back(0, 0, int(customRect.Width), int(customRect.Height));
|
||||||
|
|
||||||
|
TightAtlasPacker packer;
|
||||||
|
packer.spacing = 1;
|
||||||
|
packer.dimensionsConstraint = msdf_atlas::DimensionsConstraint::POWER_OF_TWO_RECTANGLE;
|
||||||
|
packer.miterLimit = 1.0;
|
||||||
|
packer.pxRange = 8.0;
|
||||||
|
packer.pack(glyphs.data(), glyphs.size(), customRects.data(), customRects.size());
|
||||||
|
|
||||||
|
for (size_t i = 0; i < customRects.size(); i++)
|
||||||
|
{
|
||||||
|
auto& srcRect = customRects[i];
|
||||||
|
auto& dstRect = atlas->CustomRects[i];
|
||||||
|
dstRect.X = srcRect.x;
|
||||||
|
dstRect.Y = srcRect.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
msdf_atlas::ImmediateAtlasGenerator<float, 3, &msdf_atlas::msdfGenerator, msdf_atlas::BitmapAtlasStorage<uint8_t, 3>> generator(packer.width, packer.height);
|
||||||
|
generator.generate(glyphs.data(), glyphs.size());
|
||||||
|
|
||||||
|
for (size_t i = 0; i < atlas->ConfigData.size(); i++)
|
||||||
|
{
|
||||||
|
auto& config = atlas->ConfigData[i];
|
||||||
|
auto& [index, count] = ranges[i];
|
||||||
|
for (size_t j = 0; j < count; j++)
|
||||||
|
{
|
||||||
|
auto& glyph = glyphs[index + j];
|
||||||
|
double x0, y0, x1, y1, u0, v0, u1, v1;
|
||||||
|
glyph.getQuadPlaneBounds(x0, y0, x1, y1);
|
||||||
|
glyph.getQuadAtlasBounds(u0, v0, u1, v1);
|
||||||
|
config.DstFont->AddGlyph(
|
||||||
|
&config,
|
||||||
|
glyph.getCodepoint(),
|
||||||
|
x0,
|
||||||
|
-y1 + config.DstFont->Ascent,
|
||||||
|
x1,
|
||||||
|
-y0 + config.DstFont->Ascent,
|
||||||
|
u0 / packer.width,
|
||||||
|
v1 / packer.height,
|
||||||
|
u1 / packer.width,
|
||||||
|
v0 / packer.height,
|
||||||
|
glyph.getAdvance());
|
||||||
|
}
|
||||||
|
|
||||||
|
config.DstFont->BuildLookupTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
atlas->TexPixelsRGBA32 = (unsigned int*)IM_ALLOC(packer.width * packer.height * 4);
|
||||||
|
atlas->TexWidth = packer.width;
|
||||||
|
atlas->TexHeight = packer.height;
|
||||||
|
atlas->TexUvScale = { 1.0f / packer.width, 1.0f / packer.height };
|
||||||
|
|
||||||
|
auto bitmapRef = (msdfgen::BitmapConstRef<uint8_t, 3>)generator.atlasStorage();
|
||||||
|
for (int y = 0; y < packer.height; y++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < packer.width; x++)
|
||||||
|
{
|
||||||
|
auto* srcPixels = bitmapRef(x, y);
|
||||||
|
auto* dstPixels = (uint8_t*)&atlas->TexPixelsRGBA32[y * packer.width + x];
|
||||||
|
dstPixels[0] = srcPixels[0];
|
||||||
|
dstPixels[1] = srcPixels[1];
|
||||||
|
dstPixels[2] = srcPixels[2];
|
||||||
|
dstPixels[3] = 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
msdfgen::deinitializeFreetype(freeType);
|
||||||
|
|
||||||
|
ImFontAtlasBuildFinish(atlas);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImFontBuilderIO g_fontBuilderIO = { FontBuilder_Build };
|
||||||
3
UnleashedRecomp/gpu/imgui/imgui_font_builder.h
Normal file
3
UnleashedRecomp/gpu/imgui/imgui_font_builder.h
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
extern ImFontBuilderIO g_fontBuilderIO;
|
||||||
|
|
@ -222,17 +222,14 @@ void ImFontAtlasSnapshot::GenerateGlyphRanges()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (App::s_isInit)
|
for (size_t i = XDBF_LANGUAGE_ENGLISH; i <= XDBF_LANGUAGE_ITALIAN; i++)
|
||||||
{
|
{
|
||||||
for (size_t i = XDBF_LANGUAGE_ENGLISH; i <= XDBF_LANGUAGE_ITALIAN; i++)
|
auto achievements = g_xdbfWrapper.GetAchievements(static_cast<EXDBFLanguage>(i));
|
||||||
|
for (auto& achievement : achievements)
|
||||||
{
|
{
|
||||||
auto achievements = g_xdbfWrapper.GetAchievements(static_cast<EXDBFLanguage>(i));
|
GetGlyphs(glyphs, achievement.Name);
|
||||||
for (auto& achievement : achievements)
|
GetGlyphs(glyphs, achievement.UnlockedDesc);
|
||||||
{
|
GetGlyphs(glyphs, achievement.LockedDesc);
|
||||||
GetGlyphs(glyphs, achievement.Name);
|
|
||||||
GetGlyphs(glyphs, achievement.UnlockedDesc);
|
|
||||||
GetGlyphs(glyphs, achievement.LockedDesc);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -252,12 +249,12 @@ void ImFontAtlasSnapshot::GenerateGlyphRanges()
|
||||||
g_glyphRanges.push_back(0);
|
g_glyphRanges.push_back(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImFont* ImFontAtlasSnapshot::GetFont(const char* name, float size)
|
ImFont* ImFontAtlasSnapshot::GetFont(const char* name)
|
||||||
{
|
{
|
||||||
auto fontAtlas = ImGui::GetIO().Fonts;
|
auto fontAtlas = ImGui::GetIO().Fonts;
|
||||||
for (auto& configData : fontAtlas->ConfigData)
|
for (auto& configData : fontAtlas->ConfigData)
|
||||||
{
|
{
|
||||||
if (strstr(configData.Name, name) != nullptr && abs(configData.SizePixels - size) < 0.001f)
|
if (strstr(configData.Name, name) != nullptr)
|
||||||
{
|
{
|
||||||
assert(configData.DstFont != nullptr);
|
assert(configData.DstFont != nullptr);
|
||||||
return configData.DstFont;
|
return configData.DstFont;
|
||||||
|
|
@ -268,5 +265,5 @@ ImFont* ImFontAtlasSnapshot::GetFont(const char* name, float size)
|
||||||
assert(false && "Unable to locate equivalent font in the atlas file.");
|
assert(false && "Unable to locate equivalent font in the atlas file.");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return fontAtlas->AddFontFromFileTTF(name, size, nullptr, g_glyphRanges.data());
|
return fontAtlas->AddFontFromFileTTF(name, 24.0f, nullptr, g_glyphRanges.data());
|
||||||
}
|
}
|
||||||
|
|
@ -34,7 +34,6 @@ struct ImDrawDataSnapshot
|
||||||
// Undefine this to generate a font atlas file in working directory.
|
// Undefine this to generate a font atlas file in working directory.
|
||||||
// You also need to do this if you are testing localization, as only
|
// You also need to do this if you are testing localization, as only
|
||||||
// characters in the locale get added to the atlas.
|
// characters in the locale get added to the atlas.
|
||||||
// Don't forget to compress the generated atlas texture to BC4 with no mips!
|
|
||||||
#define ENABLE_IM_FONT_ATLAS_SNAPSHOT
|
#define ENABLE_IM_FONT_ATLAS_SNAPSHOT
|
||||||
|
|
||||||
struct ImFontAtlasSnapshot
|
struct ImFontAtlasSnapshot
|
||||||
|
|
@ -59,5 +58,5 @@ struct ImFontAtlasSnapshot
|
||||||
static void GenerateGlyphRanges();
|
static void GenerateGlyphRanges();
|
||||||
|
|
||||||
// When ENABLE_IM_FONT_ATLAS_SNAPSHOT is undefined, this creates the font runtime instead.
|
// When ENABLE_IM_FONT_ATLAS_SNAPSHOT is undefined, this creates the font runtime instead.
|
||||||
static ImFont* GetFont(const char* name, float size);
|
static ImFont* GetFont(const char* name);
|
||||||
};
|
};
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../imgui_common.h"
|
#include "../imgui/imgui_common.h"
|
||||||
|
|
||||||
struct PushConstants
|
struct PushConstants
|
||||||
{
|
{
|
||||||
|
|
@ -13,6 +13,7 @@ struct PushConstants
|
||||||
float2 InverseDisplaySize;
|
float2 InverseDisplaySize;
|
||||||
float2 Origin;
|
float2 Origin;
|
||||||
float2 Scale;
|
float2 Scale;
|
||||||
|
float Outline;
|
||||||
};
|
};
|
||||||
|
|
||||||
Texture2D<float4> g_Texture2DDescriptorHeap[] : register(t0, space0);
|
Texture2D<float4> g_Texture2DDescriptorHeap[] : register(t0, space0);
|
||||||
|
|
|
||||||
|
|
@ -73,13 +73,67 @@ float4 PixelAntialiasing(float2 uvTexspace)
|
||||||
return SampleLinear(uvTexspace);
|
return SampleLinear(uvTexspace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float median(float r, float g, float b)
|
||||||
|
{
|
||||||
|
return max(min(r, g), min(max(r, g), b));
|
||||||
|
}
|
||||||
|
|
||||||
float4 main(in Interpolators interpolators) : SV_Target
|
float4 main(in Interpolators interpolators) : SV_Target
|
||||||
{
|
{
|
||||||
float4 color = interpolators.Color;
|
float4 color = interpolators.Color;
|
||||||
color *= PixelAntialiasing(interpolators.Position.xy - 0.5);
|
color *= PixelAntialiasing(interpolators.Position.xy - 0.5);
|
||||||
|
|
||||||
if (g_PushConstants.Texture2DDescriptorIndex != 0)
|
if (g_PushConstants.Texture2DDescriptorIndex != 0)
|
||||||
color *= g_Texture2DDescriptorHeap[g_PushConstants.Texture2DDescriptorIndex].Sample(g_SamplerDescriptorHeap[0], interpolators.UV);
|
{
|
||||||
|
Texture2D<float4> texture = g_Texture2DDescriptorHeap[g_PushConstants.Texture2DDescriptorIndex & 0x7FFFFFFF];
|
||||||
|
float4 textureColor = texture.Sample(g_SamplerDescriptorHeap[0], interpolators.UV);
|
||||||
|
|
||||||
|
if ((g_PushConstants.Texture2DDescriptorIndex & 0x80000000) != 0)
|
||||||
|
{
|
||||||
|
uint width, height;
|
||||||
|
texture.GetDimensions(width, height);
|
||||||
|
|
||||||
|
float pxRange = 8.0;
|
||||||
|
float2 unitRange = pxRange / float2(width, height);
|
||||||
|
float2 screenTexSize = 1.0 / fwidth(interpolators.UV);
|
||||||
|
float screenPxRange = max(0.5 * dot(unitRange, screenTexSize), 1.0);
|
||||||
|
|
||||||
|
float sd = median(textureColor.r, textureColor.g, textureColor.b) - 0.5;
|
||||||
|
float screenPxDistance = screenPxRange * (sd + g_PushConstants.Outline / (pxRange * 2.0));
|
||||||
|
|
||||||
|
if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_TITLE_BEVEL)
|
||||||
|
{
|
||||||
|
float2 normal = normalize(float3(ddx(sd), ddy(sd), 0.01)).xy;
|
||||||
|
float3 rimColor = float3(1, 0.8, 0.29);
|
||||||
|
float3 shadowColor = float3(0.84, 0.57, 0);
|
||||||
|
|
||||||
|
float cosTheta = dot(normal, normalize(float2(1, 1)));
|
||||||
|
float3 gradient = lerp(color.rgb, cosTheta >= 0.0 ? rimColor : shadowColor, abs(cosTheta));
|
||||||
|
color.rgb = lerp(gradient, color.rgb, pow(saturate(sd + 0.8), 32.0));
|
||||||
|
}
|
||||||
|
else if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_CATEGORY_BEVEL)
|
||||||
|
{
|
||||||
|
float2 normal = normalize(float3(ddx(sd), ddy(sd), 0.25)).xy;
|
||||||
|
float cosTheta = dot(normal, normalize(float2(1, 1)));
|
||||||
|
float gradient = 1.0 + cosTheta * 0.5;
|
||||||
|
color.rgb = saturate(color.rgb * gradient);
|
||||||
|
}
|
||||||
|
else if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_TEXT_SKEW)
|
||||||
|
{
|
||||||
|
float2 normal = normalize(float3(ddx(sd), ddy(sd), 0.5)).xy;
|
||||||
|
float cosTheta = dot(normal, normalize(float2(1, 1)));
|
||||||
|
float gradient = saturate(1.0 + cosTheta);
|
||||||
|
color.rgb = lerp(color.rgb * gradient, color.rgb, pow(saturate(sd + 0.77), 32.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
color.a *= saturate(screenPxDistance + 0.5);
|
||||||
|
color.a *= textureColor.a;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
color *= textureColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_MARQUEE_FADE)
|
if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_MARQUEE_FADE)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,35 +1,37 @@
|
||||||
#include <stdafx.h>
|
#include "video.h"
|
||||||
|
|
||||||
#include <kernel/function.h>
|
#include "imgui/imgui_common.h"
|
||||||
#include <kernel/heap.h>
|
#include "imgui/imgui_snapshot.h"
|
||||||
|
#include "imgui/imgui_font_builder.h"
|
||||||
|
|
||||||
|
#include <bc_diff.h>
|
||||||
#include <cpu/code_cache.h>
|
#include <cpu/code_cache.h>
|
||||||
#include <cpu/guest_code.h>
|
#include <cpu/guest_code.h>
|
||||||
#include <cpu/guest_thread.h>
|
#include <cpu/guest_thread.h>
|
||||||
|
#include <decompressor.h>
|
||||||
|
#include <kernel/function.h>
|
||||||
|
#include <kernel/heap.h>
|
||||||
#include <kernel/memory.h>
|
#include <kernel/memory.h>
|
||||||
#include <kernel/xdbf.h>
|
#include <kernel/xdbf.h>
|
||||||
#include <xxHashMap.h>
|
#include <res/bc_diff/button_bc_diff.bin.h>
|
||||||
|
#include <res/font/im_font_atlas.dds.h>
|
||||||
#include <shader/shader_cache.h>
|
#include <shader/shader_cache.h>
|
||||||
|
#include <SWA.h>
|
||||||
#include <ui/achievement_menu.h>
|
#include <ui/achievement_menu.h>
|
||||||
#include <ui/achievement_overlay.h>
|
#include <ui/achievement_overlay.h>
|
||||||
#include <ui/button_guide.h>
|
#include <ui/button_guide.h>
|
||||||
#include <ui/fader.h>
|
#include <ui/fader.h>
|
||||||
|
#include <ui/installer_wizard.h>
|
||||||
#include <ui/message_window.h>
|
#include <ui/message_window.h>
|
||||||
#include <ui/options_menu.h>
|
#include <ui/options_menu.h>
|
||||||
#include <ui/installer_wizard.h>
|
|
||||||
|
|
||||||
#include "imgui_snapshot.h"
|
|
||||||
#include "imgui_common.h"
|
|
||||||
#include "video.h"
|
|
||||||
#include <ui/sdl_listener.h>
|
#include <ui/sdl_listener.h>
|
||||||
#include <ui/window.h>
|
#include <ui/window.h>
|
||||||
#include <user/config.h>
|
#include <user/config.h>
|
||||||
|
#include <xxHashMap.h>
|
||||||
|
|
||||||
#include <res/font/im_font_atlas.dds.h>
|
#if defined(ASYNC_PSO_DEBUG) || defined(PSO_CACHING)
|
||||||
#include <res/bc_diff/button_bc_diff.bin.h>
|
#include <magic_enum.hpp>
|
||||||
#include <decompressor.h>
|
#endif
|
||||||
#include <bc_diff.h>
|
|
||||||
|
|
||||||
#include <SWA.h>
|
|
||||||
|
|
||||||
#include "../../thirdparty/ShaderRecomp/ShaderRecomp/shader_common.h"
|
#include "../../thirdparty/ShaderRecomp/ShaderRecomp/shader_common.h"
|
||||||
#include "shader/copy_vs.hlsl.dxil.h"
|
#include "shader/copy_vs.hlsl.dxil.h"
|
||||||
|
|
@ -38,6 +40,8 @@
|
||||||
#include "shader/csd_filter_ps.hlsl.spirv.h"
|
#include "shader/csd_filter_ps.hlsl.spirv.h"
|
||||||
#include "shader/enhanced_motion_blur_ps.hlsl.dxil.h"
|
#include "shader/enhanced_motion_blur_ps.hlsl.dxil.h"
|
||||||
#include "shader/enhanced_motion_blur_ps.hlsl.spirv.h"
|
#include "shader/enhanced_motion_blur_ps.hlsl.spirv.h"
|
||||||
|
#include "shader/gamma_correction_ps.hlsl.dxil.h"
|
||||||
|
#include "shader/gamma_correction_ps.hlsl.spirv.h"
|
||||||
#include "shader/gaussian_blur_3x3.hlsl.dxil.h"
|
#include "shader/gaussian_blur_3x3.hlsl.dxil.h"
|
||||||
#include "shader/gaussian_blur_3x3.hlsl.spirv.h"
|
#include "shader/gaussian_blur_3x3.hlsl.spirv.h"
|
||||||
#include "shader/gaussian_blur_5x5.hlsl.dxil.h"
|
#include "shader/gaussian_blur_5x5.hlsl.dxil.h"
|
||||||
|
|
@ -46,16 +50,14 @@
|
||||||
#include "shader/gaussian_blur_7x7.hlsl.spirv.h"
|
#include "shader/gaussian_blur_7x7.hlsl.spirv.h"
|
||||||
#include "shader/gaussian_blur_9x9.hlsl.dxil.h"
|
#include "shader/gaussian_blur_9x9.hlsl.dxil.h"
|
||||||
#include "shader/gaussian_blur_9x9.hlsl.spirv.h"
|
#include "shader/gaussian_blur_9x9.hlsl.spirv.h"
|
||||||
#include "shader/gamma_correction_ps.hlsl.dxil.h"
|
|
||||||
#include "shader/gamma_correction_ps.hlsl.spirv.h"
|
|
||||||
#include "shader/imgui_ps.hlsl.dxil.h"
|
#include "shader/imgui_ps.hlsl.dxil.h"
|
||||||
#include "shader/imgui_ps.hlsl.spirv.h"
|
#include "shader/imgui_ps.hlsl.spirv.h"
|
||||||
#include "shader/imgui_vs.hlsl.dxil.h"
|
#include "shader/imgui_vs.hlsl.dxil.h"
|
||||||
#include "shader/imgui_vs.hlsl.spirv.h"
|
#include "shader/imgui_vs.hlsl.spirv.h"
|
||||||
#include "shader/movie_vs.hlsl.dxil.h"
|
|
||||||
#include "shader/movie_vs.hlsl.spirv.h"
|
|
||||||
#include "shader/movie_ps.hlsl.dxil.h"
|
#include "shader/movie_ps.hlsl.dxil.h"
|
||||||
#include "shader/movie_ps.hlsl.spirv.h"
|
#include "shader/movie_ps.hlsl.spirv.h"
|
||||||
|
#include "shader/movie_vs.hlsl.dxil.h"
|
||||||
|
#include "shader/movie_vs.hlsl.spirv.h"
|
||||||
#include "shader/resolve_msaa_depth_2x.hlsl.dxil.h"
|
#include "shader/resolve_msaa_depth_2x.hlsl.dxil.h"
|
||||||
#include "shader/resolve_msaa_depth_2x.hlsl.spirv.h"
|
#include "shader/resolve_msaa_depth_2x.hlsl.spirv.h"
|
||||||
#include "shader/resolve_msaa_depth_4x.hlsl.dxil.h"
|
#include "shader/resolve_msaa_depth_4x.hlsl.dxil.h"
|
||||||
|
|
@ -63,10 +65,6 @@
|
||||||
#include "shader/resolve_msaa_depth_8x.hlsl.dxil.h"
|
#include "shader/resolve_msaa_depth_8x.hlsl.dxil.h"
|
||||||
#include "shader/resolve_msaa_depth_8x.hlsl.spirv.h"
|
#include "shader/resolve_msaa_depth_8x.hlsl.spirv.h"
|
||||||
|
|
||||||
#if defined(ASYNC_PSO_DEBUG) || defined(PSO_CACHING)
|
|
||||||
#include <magic_enum.hpp>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
__declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001;
|
__declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001;
|
||||||
|
|
@ -1110,8 +1108,11 @@ struct ImGuiPushConstants
|
||||||
ImVec2 inverseDisplaySize{};
|
ImVec2 inverseDisplaySize{};
|
||||||
ImVec2 origin{ 0.0f, 0.0f };
|
ImVec2 origin{ 0.0f, 0.0f };
|
||||||
ImVec2 scale{ 1.0f, 1.0f };
|
ImVec2 scale{ 1.0f, 1.0f };
|
||||||
|
float outline{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern ImFontBuilderIO g_fontBuilderIO;
|
||||||
|
|
||||||
static void CreateImGuiBackend()
|
static void CreateImGuiBackend()
|
||||||
{
|
{
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
@ -1123,7 +1124,6 @@ static void CreateImGuiBackend()
|
||||||
IM_DELETE(io.Fonts);
|
IM_DELETE(io.Fonts);
|
||||||
io.Fonts = ImFontAtlasSnapshot::Load();
|
io.Fonts = ImFontAtlasSnapshot::Load();
|
||||||
#else
|
#else
|
||||||
io.Fonts->TexDesiredWidth = 4096;
|
|
||||||
io.Fonts->AddFontDefault();
|
io.Fonts->AddFontDefault();
|
||||||
ImFontAtlasSnapshot::GenerateGlyphRanges();
|
ImFontAtlasSnapshot::GenerateGlyphRanges();
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1137,17 +1137,18 @@ static void CreateImGuiBackend()
|
||||||
|
|
||||||
ImGui_ImplSDL2_InitForOther(Window::s_pWindow);
|
ImGui_ImplSDL2_InitForOther(Window::s_pWindow);
|
||||||
|
|
||||||
RenderComponentMapping componentMapping(RenderSwizzle::ONE, RenderSwizzle::ONE, RenderSwizzle::ONE, RenderSwizzle::R);
|
|
||||||
|
|
||||||
#ifdef ENABLE_IM_FONT_ATLAS_SNAPSHOT
|
#ifdef ENABLE_IM_FONT_ATLAS_SNAPSHOT
|
||||||
g_imFontTexture = LoadTexture(decompressZstd(g_im_font_atlas_texture, g_im_font_atlas_texture_uncompressed_size).get(),
|
g_imFontTexture = LoadTexture(
|
||||||
g_im_font_atlas_texture_uncompressed_size, componentMapping);
|
decompressZstd(g_im_font_atlas_texture, g_im_font_atlas_texture_uncompressed_size).get(), g_im_font_atlas_texture_uncompressed_size);
|
||||||
#else
|
#else
|
||||||
|
io.Fonts->FontBuilderIO = &g_fontBuilderIO;
|
||||||
|
io.Fonts->Build();
|
||||||
|
|
||||||
g_imFontTexture = std::make_unique<GuestTexture>(ResourceType::Texture);
|
g_imFontTexture = std::make_unique<GuestTexture>(ResourceType::Texture);
|
||||||
|
|
||||||
uint8_t* pixels;
|
uint8_t* pixels;
|
||||||
int width, height;
|
int width, height;
|
||||||
io.Fonts->GetTexDataAsAlpha8(&pixels, &width, &height);
|
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
|
||||||
|
|
||||||
RenderTextureDesc textureDesc;
|
RenderTextureDesc textureDesc;
|
||||||
textureDesc.dimension = RenderTextureDimension::TEXTURE_2D;
|
textureDesc.dimension = RenderTextureDimension::TEXTURE_2D;
|
||||||
|
|
@ -1156,17 +1157,17 @@ static void CreateImGuiBackend()
|
||||||
textureDesc.depth = 1;
|
textureDesc.depth = 1;
|
||||||
textureDesc.mipLevels = 1;
|
textureDesc.mipLevels = 1;
|
||||||
textureDesc.arraySize = 1;
|
textureDesc.arraySize = 1;
|
||||||
textureDesc.format = RenderFormat::R8_UNORM;
|
textureDesc.format = RenderFormat::R8G8B8A8_UNORM;
|
||||||
|
|
||||||
g_imFontTexture->textureHolder = g_device->createTexture(textureDesc);
|
g_imFontTexture->textureHolder = g_device->createTexture(textureDesc);
|
||||||
g_imFontTexture->texture = g_imFontTexture->textureHolder.get();
|
g_imFontTexture->texture = g_imFontTexture->textureHolder.get();
|
||||||
|
|
||||||
uint32_t rowPitch = (width + PITCH_ALIGNMENT - 1) & ~(PITCH_ALIGNMENT - 1);
|
uint32_t rowPitch = (width * 4 + PITCH_ALIGNMENT - 1) & ~(PITCH_ALIGNMENT - 1);
|
||||||
uint32_t slicePitch = (rowPitch * height + PLACEMENT_ALIGNMENT - 1) & ~(PLACEMENT_ALIGNMENT - 1);
|
uint32_t slicePitch = (rowPitch * height + PLACEMENT_ALIGNMENT - 1) & ~(PLACEMENT_ALIGNMENT - 1);
|
||||||
auto uploadBuffer = g_device->createBuffer(RenderBufferDesc::UploadBuffer(slicePitch));
|
auto uploadBuffer = g_device->createBuffer(RenderBufferDesc::UploadBuffer(slicePitch));
|
||||||
uint8_t* mappedMemory = reinterpret_cast<uint8_t*>(uploadBuffer->map());
|
uint8_t* mappedMemory = reinterpret_cast<uint8_t*>(uploadBuffer->map());
|
||||||
|
|
||||||
if (rowPitch == width)
|
if (rowPitch == (width * 4))
|
||||||
{
|
{
|
||||||
memcpy(mappedMemory, pixels, slicePitch);
|
memcpy(mappedMemory, pixels, slicePitch);
|
||||||
}
|
}
|
||||||
|
|
@ -1174,8 +1175,8 @@ static void CreateImGuiBackend()
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < height; i++)
|
for (size_t i = 0; i < height; i++)
|
||||||
{
|
{
|
||||||
memcpy(mappedMemory, pixels, width);
|
memcpy(mappedMemory, pixels, width * 4);
|
||||||
pixels += width;
|
pixels += width * 4;
|
||||||
mappedMemory += rowPitch;
|
mappedMemory += rowPitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1188,7 +1189,7 @@ static void CreateImGuiBackend()
|
||||||
|
|
||||||
g_copyCommandList->copyTextureRegion(
|
g_copyCommandList->copyTextureRegion(
|
||||||
RenderTextureCopyLocation::Subresource(g_imFontTexture->texture, 0),
|
RenderTextureCopyLocation::Subresource(g_imFontTexture->texture, 0),
|
||||||
RenderTextureCopyLocation::PlacedFootprint(uploadBuffer.get(), RenderFormat::R8_UNORM, width, height, 1, rowPitch, 0));
|
RenderTextureCopyLocation::PlacedFootprint(uploadBuffer.get(), RenderFormat::R8G8B8A8_UNORM, width, height, 1, rowPitch / 4, 0));
|
||||||
});
|
});
|
||||||
|
|
||||||
g_imFontTexture->layout = RenderTextureLayout::COPY_DEST;
|
g_imFontTexture->layout = RenderTextureLayout::COPY_DEST;
|
||||||
|
|
@ -1197,7 +1198,6 @@ static void CreateImGuiBackend()
|
||||||
textureViewDesc.format = textureDesc.format;
|
textureViewDesc.format = textureDesc.format;
|
||||||
textureViewDesc.dimension = RenderTextureViewDimension::TEXTURE_2D;
|
textureViewDesc.dimension = RenderTextureViewDimension::TEXTURE_2D;
|
||||||
textureViewDesc.mipLevels = 1;
|
textureViewDesc.mipLevels = 1;
|
||||||
textureViewDesc.componentMapping = componentMapping;
|
|
||||||
g_imFontTexture->textureView = g_imFontTexture->texture->createTextureView(textureViewDesc);
|
g_imFontTexture->textureView = g_imFontTexture->texture->createTextureView(textureViewDesc);
|
||||||
|
|
||||||
g_imFontTexture->descriptorIndex = g_textureDescriptorAllocator.allocate();
|
g_imFontTexture->descriptorIndex = g_textureDescriptorAllocator.allocate();
|
||||||
|
|
@ -1261,7 +1261,7 @@ static void CreateImGuiBackend()
|
||||||
|
|
||||||
ddspp::Header header;
|
ddspp::Header header;
|
||||||
ddspp::HeaderDXT10 headerDX10;
|
ddspp::HeaderDXT10 headerDX10;
|
||||||
ddspp::encode_header(ddspp::R8_UNORM, width, height, 1, ddspp::Texture2D, 1, 1, header, headerDX10);
|
ddspp::encode_header(ddspp::R8G8B8A8_UNORM, width, height, 1, ddspp::Texture2D, 1, 1, header, headerDX10);
|
||||||
|
|
||||||
file = fopen("im_font_atlas.dds", "wb");
|
file = fopen("im_font_atlas.dds", "wb");
|
||||||
if (file)
|
if (file)
|
||||||
|
|
@ -1269,7 +1269,7 @@ static void CreateImGuiBackend()
|
||||||
fwrite(&ddspp::DDS_MAGIC, 4, 1, file);
|
fwrite(&ddspp::DDS_MAGIC, 4, 1, file);
|
||||||
fwrite(&header, sizeof(header), 1, file);
|
fwrite(&header, sizeof(header), 1, file);
|
||||||
fwrite(&headerDX10, sizeof(headerDX10), 1, file);
|
fwrite(&headerDX10, sizeof(headerDX10), 1, file);
|
||||||
fwrite(pixels, 1, width * height, file);
|
fwrite(pixels, 4, width * height, file);
|
||||||
fclose(file);
|
fclose(file);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1897,6 +1897,25 @@ static void ProcDrawImGui(const RenderCommand& cmd)
|
||||||
pushConstants.inverseDisplaySize = { 1.0f / drawData.DisplaySize.x, 1.0f / drawData.DisplaySize.y };
|
pushConstants.inverseDisplaySize = { 1.0f / drawData.DisplaySize.x, 1.0f / drawData.DisplaySize.y };
|
||||||
commandList->setGraphicsPushConstants(0, &pushConstants);
|
commandList->setGraphicsPushConstants(0, &pushConstants);
|
||||||
|
|
||||||
|
size_t pushConstantRangeMin = ~0;
|
||||||
|
size_t pushConstantRangeMax = 0;
|
||||||
|
|
||||||
|
auto setPushConstants = [&](void* destination, const void* source, size_t size)
|
||||||
|
{
|
||||||
|
bool dirty = memcmp(destination, source, size) != 0;
|
||||||
|
|
||||||
|
memcpy(destination, source, size);
|
||||||
|
|
||||||
|
if (dirty)
|
||||||
|
{
|
||||||
|
size_t offset = reinterpret_cast<size_t>(destination) - reinterpret_cast<size_t>(&pushConstants);
|
||||||
|
pushConstantRangeMin = std::min(pushConstantRangeMin, offset);
|
||||||
|
pushConstantRangeMax = std::max(pushConstantRangeMax, offset + size);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ImRect clipRect{};
|
||||||
|
|
||||||
for (int i = 0; i < drawData.CmdListsCount; i++)
|
for (int i = 0; i < drawData.CmdListsCount; i++)
|
||||||
{
|
{
|
||||||
auto& drawList = drawData.CmdLists[i];
|
auto& drawList = drawData.CmdLists[i];
|
||||||
|
|
@ -1921,19 +1940,25 @@ static void ProcDrawImGui(const RenderCommand& cmd)
|
||||||
switch (static_cast<ImGuiCallback>(reinterpret_cast<size_t>(drawCmd.UserCallback)))
|
switch (static_cast<ImGuiCallback>(reinterpret_cast<size_t>(drawCmd.UserCallback)))
|
||||||
{
|
{
|
||||||
case ImGuiCallback::SetGradient:
|
case ImGuiCallback::SetGradient:
|
||||||
commandList->setGraphicsPushConstants(0, &callbackData->setGradient, offsetof(ImGuiPushConstants, boundsMin), sizeof(callbackData->setGradient));
|
setPushConstants(&pushConstants.boundsMin, &callbackData->setGradient, sizeof(callbackData->setGradient));
|
||||||
break;
|
break;
|
||||||
case ImGuiCallback::SetShaderModifier:
|
case ImGuiCallback::SetShaderModifier:
|
||||||
commandList->setGraphicsPushConstants(0, &callbackData->setShaderModifier, offsetof(ImGuiPushConstants, shaderModifier), sizeof(callbackData->setShaderModifier));
|
setPushConstants(&pushConstants.shaderModifier, &callbackData->setShaderModifier, sizeof(callbackData->setShaderModifier));
|
||||||
break;
|
break;
|
||||||
case ImGuiCallback::SetOrigin:
|
case ImGuiCallback::SetOrigin:
|
||||||
commandList->setGraphicsPushConstants(0, &callbackData->setOrigin, offsetof(ImGuiPushConstants, origin), sizeof(callbackData->setOrigin));
|
setPushConstants(&pushConstants.origin, &callbackData->setOrigin, sizeof(callbackData->setOrigin));
|
||||||
break;
|
break;
|
||||||
case ImGuiCallback::SetScale:
|
case ImGuiCallback::SetScale:
|
||||||
commandList->setGraphicsPushConstants(0, &callbackData->setScale, offsetof(ImGuiPushConstants, scale), sizeof(callbackData->setScale));
|
setPushConstants(&pushConstants.scale, &callbackData->setScale, sizeof(callbackData->setScale));
|
||||||
break;
|
break;
|
||||||
case ImGuiCallback::SetMarqueeFade:
|
case ImGuiCallback::SetMarqueeFade:
|
||||||
commandList->setGraphicsPushConstants(0, &callbackData->setScale, offsetof(ImGuiPushConstants, boundsMin), sizeof(callbackData->setMarqueeFade));
|
setPushConstants(&pushConstants.boundsMin, &callbackData->setMarqueeFade, sizeof(callbackData->setMarqueeFade));
|
||||||
|
break;
|
||||||
|
case ImGuiCallback::SetOutline:
|
||||||
|
setPushConstants(&pushConstants.outline, &callbackData->setOutline, sizeof(callbackData->setOutline));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(false && "Unknown ImGui callback type.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1955,10 +1980,26 @@ static void ProcDrawImGui(const RenderCommand& cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
descriptorIndex = texture->descriptorIndex;
|
descriptorIndex = texture->descriptorIndex;
|
||||||
|
|
||||||
|
if (texture == g_imFontTexture.get())
|
||||||
|
descriptorIndex |= 0x80000000;
|
||||||
|
|
||||||
|
setPushConstants(&pushConstants.texture2DDescriptorIndex, &descriptorIndex, sizeof(descriptorIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pushConstantRangeMin < pushConstantRangeMax)
|
||||||
|
{
|
||||||
|
commandList->setGraphicsPushConstants(0, reinterpret_cast<const uint8_t*>(&pushConstants) + pushConstantRangeMin, pushConstantRangeMin, pushConstantRangeMax - pushConstantRangeMin);
|
||||||
|
pushConstantRangeMin = ~0;
|
||||||
|
pushConstantRangeMax = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(&clipRect, &drawCmd.ClipRect, sizeof(clipRect)) != 0)
|
||||||
|
{
|
||||||
|
commandList->setScissors(RenderRect(int32_t(drawCmd.ClipRect.x), int32_t(drawCmd.ClipRect.y), int32_t(drawCmd.ClipRect.z), int32_t(drawCmd.ClipRect.w)));
|
||||||
|
clipRect = drawCmd.ClipRect;
|
||||||
}
|
}
|
||||||
|
|
||||||
commandList->setGraphicsPushConstants(0, &descriptorIndex, offsetof(ImGuiPushConstants, texture2DDescriptorIndex), sizeof(descriptorIndex));
|
|
||||||
commandList->setScissors(RenderRect(int32_t(drawCmd.ClipRect.x), int32_t(drawCmd.ClipRect.y), int32_t(drawCmd.ClipRect.z), int32_t(drawCmd.ClipRect.w)));
|
|
||||||
commandList->drawIndexedInstanced(drawCmd.ElemCount, 1, drawCmd.IdxOffset, drawCmd.VtxOffset, 0);
|
commandList->drawIndexedInstanced(drawCmd.ElemCount, 1, drawCmd.IdxOffset, drawCmd.VtxOffset, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -156,11 +156,12 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
HostStartup();
|
HostStartup();
|
||||||
|
|
||||||
Video::CreateHostDevice();
|
|
||||||
|
|
||||||
bool isGameInstalled = Installer::checkGameInstall(".");
|
bool isGameInstalled = Installer::checkGameInstall(".");
|
||||||
if (forceInstaller || forceDLCInstaller || !isGameInstalled)
|
bool runInstallerWizard = forceInstaller || forceDLCInstaller || !isGameInstalled;
|
||||||
|
if (runInstallerWizard)
|
||||||
{
|
{
|
||||||
|
Video::CreateHostDevice();
|
||||||
|
|
||||||
if (!InstallerWizard::Run(isGameInstalled && forceDLCInstaller))
|
if (!InstallerWizard::Run(isGameInstalled && forceDLCInstaller))
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -173,6 +174,9 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
uint32_t entry = LdrLoadModule(FileSystem::TransformPath(GAME_XEX_PATH));
|
uint32_t entry = LdrLoadModule(FileSystem::TransformPath(GAME_XEX_PATH));
|
||||||
|
|
||||||
|
if (!runInstallerWizard)
|
||||||
|
Video::CreateHostDevice();
|
||||||
|
|
||||||
Video::StartPipelinePrecompilation();
|
Video::StartPipelinePrecompilation();
|
||||||
|
|
||||||
GuestThread::Start(entry);
|
GuestThread::Start(entry);
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
#include <res/images/achievements_menu/trophy.dds.h>
|
#include <res/images/achievements_menu/trophy.dds.h>
|
||||||
#include <res/images/common/general_window.dds.h>
|
#include <res/images/common/general_window.dds.h>
|
||||||
#include <res/images/common/select_fill.dds.h>
|
#include <res/images/common/select_fill.dds.h>
|
||||||
#include <gpu/imgui_snapshot.h>
|
#include <gpu/imgui/imgui_snapshot.h>
|
||||||
|
|
||||||
constexpr double HEADER_CONTAINER_INTRO_MOTION_START = 0;
|
constexpr double HEADER_CONTAINER_INTRO_MOTION_START = 0;
|
||||||
constexpr double HEADER_CONTAINER_INTRO_MOTION_END = 15;
|
constexpr double HEADER_CONTAINER_INTRO_MOTION_END = 15;
|
||||||
|
|
@ -141,14 +141,14 @@ static void DrawHeaderContainer(const char* text)
|
||||||
SetTextSkew((min.y + max.y) / 2.0f, Scale(3.0f));
|
SetTextSkew((min.y + max.y) / 2.0f, Scale(3.0f));
|
||||||
|
|
||||||
// TODO: Apply bevel.
|
// TODO: Apply bevel.
|
||||||
DrawTextWithOutline<float>
|
DrawTextWithOutline
|
||||||
(
|
(
|
||||||
g_fntNewRodinUB,
|
g_fntNewRodinUB,
|
||||||
fontSize,
|
fontSize,
|
||||||
{ /* X */ min.x + textMarginX, /* Y */ CENTRE_TEXT_VERT(min, max, textSize) - Scale(5) },
|
{ /* X */ min.x + textMarginX, /* Y */ CENTRE_TEXT_VERT(min, max, textSize) - Scale(5) },
|
||||||
IM_COL32(255, 255, 255, 255 * alpha),
|
IM_COL32(255, 255, 255, 255 * alpha),
|
||||||
text,
|
text,
|
||||||
1.65f,
|
4,
|
||||||
IM_COL32(0, 0, 0, 255 * alpha)
|
IM_COL32(0, 0, 0, 255 * alpha)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -222,7 +222,7 @@ static void DrawAchievement(int rowIndex, float yOffset, Achievement& achievemen
|
||||||
isUnlocked ? IM_COL32(252, 243, 5, 255) : colLockedText,
|
isUnlocked ? IM_COL32(252, 243, 5, 255) : colLockedText,
|
||||||
achievement.Name.c_str(),
|
achievement.Name.c_str(),
|
||||||
shadowOffset,
|
shadowOffset,
|
||||||
0.4f,
|
1.0f,
|
||||||
colTextShadow
|
colTextShadow
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -261,7 +261,7 @@ static void DrawAchievement(int rowIndex, float yOffset, Achievement& achievemen
|
||||||
isUnlocked ? IM_COL32_WHITE : colLockedText,
|
isUnlocked ? IM_COL32_WHITE : colLockedText,
|
||||||
desc,
|
desc,
|
||||||
shadowOffset,
|
shadowOffset,
|
||||||
0.4f,
|
1.0f,
|
||||||
colTextShadow
|
colTextShadow
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -349,14 +349,14 @@ static void DrawAchievement(int rowIndex, float yOffset, Achievement& achievemen
|
||||||
);
|
);
|
||||||
|
|
||||||
// Draw timestamp text.
|
// Draw timestamp text.
|
||||||
DrawTextWithOutline<int>
|
DrawTextWithOutline
|
||||||
(
|
(
|
||||||
g_fntNewRodinDB,
|
g_fntNewRodinDB,
|
||||||
fontSize,
|
fontSize,
|
||||||
{ /* X */ CENTRE_TEXT_HORZ(timestampMin, timestampMax, textSize), /* Y */ CENTRE_TEXT_VERT(timestampMin, timestampMax, textSize) },
|
{ /* X */ CENTRE_TEXT_HORZ(timestampMin, timestampMax, textSize), /* Y */ CENTRE_TEXT_VERT(timestampMin, timestampMax, textSize) },
|
||||||
IM_COL32(255, 255, 255, 255),
|
IM_COL32(255, 255, 255, 255),
|
||||||
buffer,
|
buffer,
|
||||||
2,
|
4,
|
||||||
IM_COL32(8, 8, 8, 255)
|
IM_COL32(8, 8, 8, 255)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -523,14 +523,14 @@ static void DrawAchievementTotal(ImVec2 min, ImVec2 max)
|
||||||
auto fontSize = Scale(20);
|
auto fontSize = Scale(20);
|
||||||
auto textSize = g_fntNewRodinDB->CalcTextSizeA(fontSize, FLT_MAX, 0, str.c_str());
|
auto textSize = g_fntNewRodinDB->CalcTextSizeA(fontSize, FLT_MAX, 0, str.c_str());
|
||||||
|
|
||||||
DrawTextWithOutline<int>
|
DrawTextWithOutline
|
||||||
(
|
(
|
||||||
g_fntNewRodinDB,
|
g_fntNewRodinDB,
|
||||||
fontSize,
|
fontSize,
|
||||||
{ /* X */ imageMin.x - textSize.x - Scale(6), /* Y */ CENTRE_TEXT_VERT(imageMin, imageMax, textSize) },
|
{ /* X */ imageMin.x - textSize.x - Scale(6), /* Y */ CENTRE_TEXT_VERT(imageMin, imageMax, textSize) },
|
||||||
IM_COL32(255, 255, 255, 255 * alpha),
|
IM_COL32(255, 255, 255, 255 * alpha),
|
||||||
str.c_str(),
|
str.c_str(),
|
||||||
2,
|
4,
|
||||||
IM_COL32(0, 0, 0, 255 * alpha)
|
IM_COL32(0, 0, 0, 255 * alpha)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -765,11 +765,9 @@ void AchievementMenu::Init()
|
||||||
{
|
{
|
||||||
auto& io = ImGui::GetIO();
|
auto& io = ImGui::GetIO();
|
||||||
|
|
||||||
constexpr float FONT_SCALE = 2.0f;
|
g_fntSeurat = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf");
|
||||||
|
g_fntNewRodinDB = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-DB.otf");
|
||||||
g_fntSeurat = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf", 24.0f * FONT_SCALE);
|
g_fntNewRodinUB = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-UB.otf");
|
||||||
g_fntNewRodinDB = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-DB.otf", 20.0f * FONT_SCALE);
|
|
||||||
g_fntNewRodinUB = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-UB.otf", 20.0f * FONT_SCALE);
|
|
||||||
|
|
||||||
g_upTrophyIcon = LOAD_ZSTD_TEXTURE(g_trophy);
|
g_upTrophyIcon = LOAD_ZSTD_TEXTURE(g_trophy);
|
||||||
g_upSelectionCursor = LOAD_ZSTD_TEXTURE(g_select_fill);
|
g_upSelectionCursor = LOAD_ZSTD_TEXTURE(g_select_fill);
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
#include <exports.h>
|
#include <exports.h>
|
||||||
#include <decompressor.h>
|
#include <decompressor.h>
|
||||||
#include <res/images/common/general_window.dds.h>
|
#include <res/images/common/general_window.dds.h>
|
||||||
#include <gpu/imgui_snapshot.h>
|
#include <gpu/imgui/imgui_snapshot.h>
|
||||||
|
|
||||||
constexpr double OVERLAY_CONTAINER_COMMON_MOTION_START = 0;
|
constexpr double OVERLAY_CONTAINER_COMMON_MOTION_START = 0;
|
||||||
constexpr double OVERLAY_CONTAINER_COMMON_MOTION_END = 11;
|
constexpr double OVERLAY_CONTAINER_COMMON_MOTION_END = 11;
|
||||||
|
|
@ -76,9 +76,7 @@ void AchievementOverlay::Init()
|
||||||
{
|
{
|
||||||
auto& io = ImGui::GetIO();
|
auto& io = ImGui::GetIO();
|
||||||
|
|
||||||
constexpr float FONT_SCALE = 2.0f;
|
g_fntSeurat = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf");
|
||||||
|
|
||||||
g_fntSeurat = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf", 24.0f * FONT_SCALE);
|
|
||||||
|
|
||||||
g_upWindow = LOAD_ZSTD_TEXTURE(g_general_window);
|
g_upWindow = LOAD_ZSTD_TEXTURE(g_general_window);
|
||||||
}
|
}
|
||||||
|
|
@ -145,7 +143,7 @@ void AchievementOverlay::Draw()
|
||||||
IM_COL32(252, 243, 5, 255), // colour
|
IM_COL32(252, 243, 5, 255), // colour
|
||||||
strAchievementUnlocked, // text
|
strAchievementUnlocked, // text
|
||||||
2, // offset
|
2, // offset
|
||||||
0.4f, // radius
|
1.0f, // radius
|
||||||
IM_COL32(0, 0, 0, 255) // shadowColour
|
IM_COL32(0, 0, 0, 255) // shadowColour
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -158,7 +156,7 @@ void AchievementOverlay::Draw()
|
||||||
IM_COL32(255, 255, 255, 255), // colour
|
IM_COL32(255, 255, 255, 255), // colour
|
||||||
strAchievementName, // text
|
strAchievementName, // text
|
||||||
2, // offset
|
2, // offset
|
||||||
0.4f, // radius
|
1.0f, // radius
|
||||||
IM_COL32(0, 0, 0, 255) // shadowColour
|
IM_COL32(0, 0, 0, 255) // shadowColour
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#include "button_guide.h"
|
#include "button_guide.h"
|
||||||
#include "imgui_utils.h"
|
#include "imgui_utils.h"
|
||||||
#include <gpu/imgui_snapshot.h>
|
#include <gpu/imgui/imgui_snapshot.h>
|
||||||
#include <gpu/video.h>
|
#include <gpu/video.h>
|
||||||
#include <hid/hid_detail.h>
|
#include <hid/hid_detail.h>
|
||||||
#include <user/config.h>
|
#include <user/config.h>
|
||||||
|
|
@ -188,7 +188,7 @@ static void DrawGuide(float* offset, ImVec2 regionMin, ImVec2 regionMax, EButton
|
||||||
|
|
||||||
ImVec2 textPosition = { textMarginX, textMarginY };
|
ImVec2 textPosition = { textMarginX, textMarginY };
|
||||||
|
|
||||||
DrawTextWithOutline<int>(font, fontSize, textPosition, IM_COL32_WHITE, text, 2, IM_COL32_BLACK);
|
DrawTextWithOutline(font, fontSize, textPosition, IM_COL32_WHITE, text, 4, IM_COL32_BLACK);
|
||||||
|
|
||||||
// Add extra luminance to low quality text.
|
// Add extra luminance to low quality text.
|
||||||
if (fontQuality == EFontQuality::Low)
|
if (fontQuality == EFontQuality::Low)
|
||||||
|
|
@ -214,10 +214,8 @@ void ButtonGuide::Init()
|
||||||
{
|
{
|
||||||
auto& io = ImGui::GetIO();
|
auto& io = ImGui::GetIO();
|
||||||
|
|
||||||
constexpr float FONT_SCALE = 2.0f;
|
g_fntNewRodin = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-M.otf");
|
||||||
|
g_fntNewRodinLQ = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-M.otf");
|
||||||
g_fntNewRodin = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-M.otf", 24.0f * FONT_SCALE);
|
|
||||||
g_fntNewRodinLQ = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-M.otf", 19.0f);
|
|
||||||
|
|
||||||
g_upControllerIcons = LOAD_ZSTD_TEXTURE(g_controller);
|
g_upControllerIcons = LOAD_ZSTD_TEXTURE(g_controller);
|
||||||
g_upKBMIcons = LOAD_ZSTD_TEXTURE(g_kbm);
|
g_upKBMIcons = LOAD_ZSTD_TEXTURE(g_kbm);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <gpu/imgui_common.h>
|
#include <gpu/imgui/imgui_common.h>
|
||||||
#include <gpu/video.h>
|
#include <gpu/video.h>
|
||||||
#include <app.h>
|
#include <app.h>
|
||||||
|
|
||||||
|
|
@ -83,6 +83,17 @@ static void ResetMarqueeFade()
|
||||||
SetScale({ 1.0f, 1.0f });
|
SetScale({ 1.0f, 1.0f });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void SetOutline(float outline)
|
||||||
|
{
|
||||||
|
auto callbackData = AddImGuiCallback(ImGuiCallback::SetOutline);
|
||||||
|
callbackData->setOutline.outline = outline;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ResetOutline()
|
||||||
|
{
|
||||||
|
SetOutline(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
// Aspect ratio aware.
|
// Aspect ratio aware.
|
||||||
static float Scale(float size)
|
static float Scale(float size)
|
||||||
{
|
{
|
||||||
|
|
@ -179,53 +190,32 @@ static void DrawTextWithMarquee(const ImFont* font, float fontSize, const ImVec2
|
||||||
drawList->PopClipRect();
|
drawList->PopClipRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
static void DrawTextWithOutline(const ImFont* font, float fontSize, const ImVec2& pos, ImU32 color, const char* text, float outlineSize, ImU32 outlineColor, uint32_t shaderModifier = IMGUI_SHADER_MODIFIER_NONE)
|
||||||
static void DrawTextWithOutline(const ImFont* font, float fontSize, const ImVec2& pos, ImU32 color, const char* text, T outlineSize, ImU32 outlineColor)
|
|
||||||
{
|
{
|
||||||
auto drawList = ImGui::GetForegroundDrawList();
|
auto drawList = ImGui::GetForegroundDrawList();
|
||||||
|
|
||||||
outlineSize = Scale(outlineSize);
|
SetOutline(outlineSize);
|
||||||
|
drawList->AddText(font, fontSize, pos, outlineColor, text);
|
||||||
|
ResetOutline();
|
||||||
|
|
||||||
if constexpr (std::is_same_v<float, T> || std::is_same_v<double, T>)
|
if (shaderModifier != IMGUI_SHADER_MODIFIER_NONE)
|
||||||
{
|
SetShaderModifier(shaderModifier);
|
||||||
auto step = outlineSize / 2.0f;
|
|
||||||
|
|
||||||
// TODO: This is still very inefficient!
|
|
||||||
for (float i = -outlineSize; i <= outlineSize; i += step)
|
|
||||||
{
|
|
||||||
for (float j = -outlineSize; j <= outlineSize; j += step)
|
|
||||||
{
|
|
||||||
if (i == 0.0f && j == 0.0f)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
drawList->AddText(font, fontSize, { pos.x + i, pos.y + j }, outlineColor, text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if constexpr (std::is_integral_v<T>)
|
|
||||||
{
|
|
||||||
// TODO: This is very inefficient!
|
|
||||||
for (int32_t i = -outlineSize + 1; i < outlineSize; i++)
|
|
||||||
{
|
|
||||||
for (int32_t j = -outlineSize + 1; j < outlineSize; j++)
|
|
||||||
{
|
|
||||||
if (i != 0 || j != 0)
|
|
||||||
drawList->AddText(font, fontSize, { pos.x + i, pos.y + j }, outlineColor, text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
drawList->AddText(font, fontSize, pos, color, text);
|
drawList->AddText(font, fontSize, pos, color, text);
|
||||||
|
|
||||||
|
if (shaderModifier != IMGUI_SHADER_MODIFIER_NONE)
|
||||||
|
SetShaderModifier(IMGUI_SHADER_MODIFIER_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DrawTextWithShadow(const ImFont* font, float fontSize, const ImVec2& pos, ImU32 colour, const char* text, float offset = 2.0f, float radius = 0.4f, ImU32 shadowColour = IM_COL32(0, 0, 0, 255))
|
static void DrawTextWithShadow(const ImFont* font, float fontSize, const ImVec2& pos, ImU32 colour, const char* text, float offset = 2.0f, float radius = 1.0f, ImU32 shadowColour = IM_COL32(0, 0, 0, 255))
|
||||||
{
|
{
|
||||||
auto drawList = ImGui::GetForegroundDrawList();
|
auto drawList = ImGui::GetForegroundDrawList();
|
||||||
|
|
||||||
offset = Scale(offset);
|
offset = Scale(offset);
|
||||||
radius = Scale(radius);
|
|
||||||
|
|
||||||
DrawTextWithOutline<float>(font, fontSize, { pos.x + offset, pos.y + offset }, shadowColour, text, radius, shadowColour);
|
SetOutline(radius);
|
||||||
|
drawList->AddText(font, fontSize, { pos.x + offset, pos.y + offset }, shadowColour, text);
|
||||||
|
ResetOutline();
|
||||||
|
|
||||||
drawList->AddText(font, fontSize, pos, colour, text, nullptr);
|
drawList->AddText(font, fontSize, pos, colour, text, nullptr);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
#include <install/installer.h>
|
#include <install/installer.h>
|
||||||
#include <gpu/video.h>
|
#include <gpu/video.h>
|
||||||
#include <gpu/imgui_snapshot.h>
|
#include <gpu/imgui/imgui_snapshot.h>
|
||||||
#include <hid/hid.h>
|
#include <hid/hid.h>
|
||||||
#include <hid/hid_detail.h>
|
#include <hid/hid_detail.h>
|
||||||
#include <locale/locale.h>
|
#include <locale/locale.h>
|
||||||
|
|
@ -559,7 +559,7 @@ static void DrawScanlineBars()
|
||||||
// Installer text
|
// Installer text
|
||||||
const std::string &headerText = Localise(g_currentPage == WizardPage::Installing ? "Installer_Header_Installing" : "Installer_Header_Installer");
|
const std::string &headerText = Localise(g_currentPage == WizardPage::Installing ? "Installer_Header_Installing" : "Installer_Header_Installer");
|
||||||
int textAlpha = std::lround(255.0f * ComputeMotionInstaller(g_appearTime, g_disappearTime, TITLE_ANIMATION_TIME, TITLE_ANIMATION_DURATION));
|
int textAlpha = std::lround(255.0f * ComputeMotionInstaller(g_appearTime, g_disappearTime, TITLE_ANIMATION_TIME, TITLE_ANIMATION_DURATION));
|
||||||
DrawTextWithOutline<int>(g_dfsogeistdFont, Scale(42.0f), { Scale(285.0f), Scale(57.0f) }, IM_COL32(255, 195, 0, textAlpha), headerText.c_str(), 4, IM_COL32(0, 0, 0, textAlpha));
|
DrawTextWithOutline(g_dfsogeistdFont, Scale(42.0f), { Scale(285.0f), Scale(57.0f) }, IM_COL32(255, 195, 0, textAlpha), headerText.c_str(), 4, IM_COL32(0, 0, 0, textAlpha), IMGUI_SHADER_MODIFIER_TITLE_BEVEL);
|
||||||
|
|
||||||
// Top bar line
|
// Top bar line
|
||||||
drawList->AddLine
|
drawList->AddLine
|
||||||
|
|
@ -761,14 +761,14 @@ static void DrawButton(ImVec2 min, ImVec2 max, const char *buttonText, bool sour
|
||||||
IM_COL32(baser + 128, baseg + 170, 0, 255)
|
IM_COL32(baser + 128, baseg + 170, 0, 255)
|
||||||
);
|
);
|
||||||
|
|
||||||
DrawTextWithOutline<int>
|
DrawTextWithOutline
|
||||||
(
|
(
|
||||||
font,
|
font,
|
||||||
size,
|
size,
|
||||||
min,
|
min,
|
||||||
IM_COL32(255, 255, 255, 255 * alpha),
|
IM_COL32(255, 255, 255, 255 * alpha),
|
||||||
buttonText,
|
buttonText,
|
||||||
2,
|
4,
|
||||||
IM_COL32(baser, baseg, 0, 255 * alpha)
|
IM_COL32(baser, baseg, 0, 255 * alpha)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -1334,10 +1334,9 @@ static void DrawMessagePrompt()
|
||||||
void InstallerWizard::Init()
|
void InstallerWizard::Init()
|
||||||
{
|
{
|
||||||
auto &io = ImGui::GetIO();
|
auto &io = ImGui::GetIO();
|
||||||
constexpr float FONT_SCALE = 2.0f;
|
g_seuratFont = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf");
|
||||||
g_seuratFont = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf", 24.0f * FONT_SCALE);
|
g_dfsogeistdFont = ImFontAtlasSnapshot::GetFont("DFSoGeiStd-W7.otf");
|
||||||
g_dfsogeistdFont = ImFontAtlasSnapshot::GetFont("DFSoGeiStd-W7.otf", 48.0f * FONT_SCALE);
|
g_newRodinFont = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-DB.otf");
|
||||||
g_newRodinFont = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-DB.otf", 20.0f * FONT_SCALE);
|
|
||||||
g_installTextures[0] = LOAD_ZSTD_TEXTURE(g_install_001);
|
g_installTextures[0] = LOAD_ZSTD_TEXTURE(g_install_001);
|
||||||
g_installTextures[1] = LOAD_ZSTD_TEXTURE(g_install_002);
|
g_installTextures[1] = LOAD_ZSTD_TEXTURE(g_install_002);
|
||||||
g_installTextures[2] = LOAD_ZSTD_TEXTURE(g_install_003);
|
g_installTextures[2] = LOAD_ZSTD_TEXTURE(g_install_003);
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
#include <res/images/common/general_window.dds.h>
|
#include <res/images/common/general_window.dds.h>
|
||||||
#include <decompressor.h>
|
#include <decompressor.h>
|
||||||
#include <res/images/common/select_fade.dds.h>
|
#include <res/images/common/select_fade.dds.h>
|
||||||
#include <gpu/imgui_snapshot.h>
|
#include <gpu/imgui/imgui_snapshot.h>
|
||||||
|
|
||||||
constexpr double OVERLAY_CONTAINER_COMMON_MOTION_START = 0;
|
constexpr double OVERLAY_CONTAINER_COMMON_MOTION_START = 0;
|
||||||
constexpr double OVERLAY_CONTAINER_COMMON_MOTION_END = 11;
|
constexpr double OVERLAY_CONTAINER_COMMON_MOTION_END = 11;
|
||||||
|
|
@ -256,9 +256,7 @@ void MessageWindow::Init()
|
||||||
{
|
{
|
||||||
auto& io = ImGui::GetIO();
|
auto& io = ImGui::GetIO();
|
||||||
|
|
||||||
constexpr float FONT_SCALE = 2.0f;
|
g_fntSeurat = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf");
|
||||||
|
|
||||||
g_fntSeurat = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf", 24.0f * FONT_SCALE);
|
|
||||||
|
|
||||||
g_upSelectionCursor = LOAD_ZSTD_TEXTURE(g_select_fade);
|
g_upSelectionCursor = LOAD_ZSTD_TEXTURE(g_select_fade);
|
||||||
g_upWindow = LOAD_ZSTD_TEXTURE(g_general_window);
|
g_upWindow = LOAD_ZSTD_TEXTURE(g_general_window);
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@
|
||||||
#include "exports.h"
|
#include "exports.h"
|
||||||
|
|
||||||
#include <api/SWA/System/InputState.h>
|
#include <api/SWA/System/InputState.h>
|
||||||
#include <gpu/imgui_common.h>
|
#include <gpu/imgui/imgui_common.h>
|
||||||
#include <gpu/video.h>
|
#include <gpu/video.h>
|
||||||
#include <gpu/imgui_snapshot.h>
|
#include <gpu/imgui/imgui_snapshot.h>
|
||||||
#include <kernel/heap.h>
|
#include <kernel/heap.h>
|
||||||
#include <kernel/memory.h>
|
#include <kernel/memory.h>
|
||||||
#include <locale/locale.h>
|
#include <locale/locale.h>
|
||||||
|
|
@ -138,7 +138,15 @@ static void DrawScanlineBars()
|
||||||
|
|
||||||
// Options text
|
// Options text
|
||||||
// TODO: localise this.
|
// TODO: localise this.
|
||||||
DrawTextWithOutline<int>(g_dfsogeistdFont, Scale(48.0f), { Scale(122.0f), Scale(56.0f) }, IM_COL32(255, 195, 0, 255), "OPTIONS", 4, IM_COL32_BLACK);
|
DrawTextWithOutline(
|
||||||
|
g_dfsogeistdFont,
|
||||||
|
Scale(48.0f),
|
||||||
|
{ Scale(122.0f), Scale(56.0f) },
|
||||||
|
IM_COL32(255, 190, 33, 255),
|
||||||
|
"OPTIONS",
|
||||||
|
4,
|
||||||
|
IM_COL32_BLACK,
|
||||||
|
IMGUI_SHADER_MODIFIER_TITLE_BEVEL);
|
||||||
|
|
||||||
// Top bar line
|
// Top bar line
|
||||||
drawList->AddLine
|
drawList->AddLine
|
||||||
|
|
@ -389,15 +397,16 @@ static bool DrawCategories()
|
||||||
IM_COL32(255, 192, 0, alpha)
|
IM_COL32(255, 192, 0, alpha)
|
||||||
);
|
);
|
||||||
|
|
||||||
DrawTextWithOutline<int>
|
DrawTextWithOutline
|
||||||
(
|
(
|
||||||
g_dfsogeistdFont,
|
g_dfsogeistdFont,
|
||||||
size,
|
size,
|
||||||
min,
|
min,
|
||||||
IM_COL32_WHITE,
|
IM_COL32_WHITE,
|
||||||
GetCategory(i).c_str(),
|
GetCategory(i).c_str(),
|
||||||
3,
|
4,
|
||||||
IM_COL32_BLACK
|
IM_COL32_BLACK,
|
||||||
|
IMGUI_SHADER_MODIFIER_CATEGORY_BEVEL
|
||||||
);
|
);
|
||||||
|
|
||||||
ResetGradient();
|
ResetGradient();
|
||||||
|
|
@ -755,14 +764,14 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef<T>* conf
|
||||||
IM_COL32(128, 170, 0, 255)
|
IM_COL32(128, 170, 0, 255)
|
||||||
);
|
);
|
||||||
|
|
||||||
DrawTextWithOutline<int>
|
DrawTextWithOutline
|
||||||
(
|
(
|
||||||
g_newRodinFont,
|
g_newRodinFont,
|
||||||
size,
|
size,
|
||||||
min,
|
min,
|
||||||
IM_COL32(255, 255, 255, 255 * alpha),
|
IM_COL32(255, 255, 255, 255 * alpha),
|
||||||
valueText.data(),
|
valueText.data(),
|
||||||
2,
|
4,
|
||||||
IM_COL32(0, 0, 0, 255 * alpha)
|
IM_COL32(0, 0, 0, 255 * alpha)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -990,11 +999,9 @@ void OptionsMenu::Init()
|
||||||
{
|
{
|
||||||
auto& io = ImGui::GetIO();
|
auto& io = ImGui::GetIO();
|
||||||
|
|
||||||
constexpr float FONT_SCALE = 2.0f;
|
g_seuratFont = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf");
|
||||||
|
g_dfsogeistdFont = ImFontAtlasSnapshot::GetFont("DFSoGeiStd-W7.otf");
|
||||||
g_seuratFont = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf", 24.0f * FONT_SCALE);
|
g_newRodinFont = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-DB.otf");
|
||||||
g_dfsogeistdFont = ImFontAtlasSnapshot::GetFont("DFSoGeiStd-W7.otf", 48.0f * FONT_SCALE);
|
|
||||||
g_newRodinFont = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-DB.otf", 20.0f * FONT_SCALE);
|
|
||||||
|
|
||||||
LoadThumbnails();
|
LoadThumbnails();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit c901d06b8e1fb1c60ad75f22c5e01452f291f949
|
Subproject commit a9019c0ab4f8990cbb09916df57e33d2dbed13e0
|
||||||
6
thirdparty/CMakeLists.txt
vendored
6
thirdparty/CMakeLists.txt
vendored
|
|
@ -1,4 +1,10 @@
|
||||||
|
set(MSDF_ATLAS_BUILD_STANDALONE OFF)
|
||||||
|
set(MSDF_ATLAS_USE_SKIA OFF)
|
||||||
|
set(MSDF_ATLAS_NO_ARTERY_FONT ON)
|
||||||
|
set(MSDFGEN_DISABLE_PNG ON)
|
||||||
|
|
||||||
add_subdirectory(${SWA_THIRDPARTY_ROOT}/PowerRecomp)
|
add_subdirectory(${SWA_THIRDPARTY_ROOT}/PowerRecomp)
|
||||||
add_subdirectory(${SWA_THIRDPARTY_ROOT}/ShaderRecomp)
|
add_subdirectory(${SWA_THIRDPARTY_ROOT}/ShaderRecomp)
|
||||||
add_subdirectory(${SWA_THIRDPARTY_ROOT}/o1heap)
|
add_subdirectory(${SWA_THIRDPARTY_ROOT}/o1heap)
|
||||||
add_subdirectory(${SWA_THIRDPARTY_ROOT}/fshasher)
|
add_subdirectory(${SWA_THIRDPARTY_ROOT}/fshasher)
|
||||||
|
add_subdirectory(${SWA_THIRDPARTY_ROOT}/msdf-atlas-gen)
|
||||||
|
|
|
||||||
1
thirdparty/msdf-atlas-gen
vendored
Submodule
1
thirdparty/msdf-atlas-gen
vendored
Submodule
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 7e8d34645a67c6e4def5d281f7adec1c2501dc49
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
},
|
},
|
||||||
"magic-enum",
|
"magic-enum",
|
||||||
"nativefiledialog-extended",
|
"nativefiledialog-extended",
|
||||||
"miniaudio"
|
"miniaudio",
|
||||||
|
"freetype"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue