mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2025-10-30 07:11:05 +00:00
Implement text skew, grayscale image, and marquee fade.
Marquee fade currently does not work with text shadow as the repeatedly drawn font accumulates its alpha.
This commit is contained in:
parent
70268e41b5
commit
8ca852583b
8 changed files with 110 additions and 23 deletions
|
|
@ -4,6 +4,9 @@
|
||||||
#define IMGUI_SHADER_MODIFIER_SCANLINE 1
|
#define IMGUI_SHADER_MODIFIER_SCANLINE 1
|
||||||
#define IMGUI_SHADER_MODIFIER_CHECKERBOARD 2
|
#define IMGUI_SHADER_MODIFIER_CHECKERBOARD 2
|
||||||
#define IMGUI_SHADER_MODIFIER_SCANLINE_BUTTON 3
|
#define IMGUI_SHADER_MODIFIER_SCANLINE_BUTTON 3
|
||||||
|
#define IMGUI_SHADER_MODIFIER_TEXT_SKEW 4
|
||||||
|
#define IMGUI_SHADER_MODIFIER_MARQUEE_FADE 5
|
||||||
|
#define IMGUI_SHADER_MODIFIER_GRAYSCALE 6
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
|
@ -13,14 +16,16 @@ enum class ImGuiCallback : int32_t
|
||||||
SetShaderModifier = -2,
|
SetShaderModifier = -2,
|
||||||
SetOrigin = -3,
|
SetOrigin = -3,
|
||||||
SetScale = -4,
|
SetScale = -4,
|
||||||
|
SetMarqueeFade = -5,
|
||||||
|
// -8 is ImDrawCallback_ResetRenderState, don't use!
|
||||||
};
|
};
|
||||||
|
|
||||||
union ImGuiCallbackData
|
union ImGuiCallbackData
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
float gradientMin[2];
|
float boundsMin[2];
|
||||||
float gradientMax[2];
|
float boundsMax[2];
|
||||||
uint32_t gradientTop;
|
uint32_t gradientTop;
|
||||||
uint32_t gradientBottom;
|
uint32_t gradientBottom;
|
||||||
} setGradient;
|
} setGradient;
|
||||||
|
|
@ -39,6 +44,12 @@ union ImGuiCallbackData
|
||||||
{
|
{
|
||||||
float scale[2];
|
float scale[2];
|
||||||
} setScale;
|
} setScale;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
float boundsMin[2];
|
||||||
|
float boundsMax[2];
|
||||||
|
} setMarqueeFade;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ImGuiCallbackData* AddImGuiCallback(ImGuiCallback callback);
|
extern ImGuiCallbackData* AddImGuiCallback(ImGuiCallback callback);
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "../imgui_common.h"
|
||||||
|
|
||||||
struct PushConstants
|
struct PushConstants
|
||||||
{
|
{
|
||||||
float2 GradientMin;
|
float2 BoundsMin;
|
||||||
float2 GradientMax;
|
float2 BoundsMax;
|
||||||
uint GradientTop;
|
uint GradientTop;
|
||||||
uint GradientBottom;
|
uint GradientBottom;
|
||||||
uint ShaderModifier;
|
uint ShaderModifier;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
#include "imgui_common.hlsli"
|
#include "imgui_common.hlsli"
|
||||||
#include "../imgui_common.h"
|
|
||||||
|
|
||||||
float4 DecodeColor(uint color)
|
float4 DecodeColor(uint color)
|
||||||
{
|
{
|
||||||
|
|
@ -82,11 +81,22 @@ float4 main(in Interpolators interpolators) : SV_Target
|
||||||
if (g_PushConstants.Texture2DDescriptorIndex != 0)
|
if (g_PushConstants.Texture2DDescriptorIndex != 0)
|
||||||
color *= g_Texture2DDescriptorHeap[g_PushConstants.Texture2DDescriptorIndex].Sample(g_SamplerDescriptorHeap[0], interpolators.UV);
|
color *= g_Texture2DDescriptorHeap[g_PushConstants.Texture2DDescriptorIndex].Sample(g_SamplerDescriptorHeap[0], interpolators.UV);
|
||||||
|
|
||||||
if (any(g_PushConstants.GradientMin != g_PushConstants.GradientMax))
|
if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_MARQUEE_FADE)
|
||||||
{
|
{
|
||||||
float2 factor = saturate((interpolators.Position.xy - g_PushConstants.GradientMin) / (g_PushConstants.GradientMax - g_PushConstants.GradientMin));
|
float minAlpha = saturate((interpolators.Position.x - g_PushConstants.BoundsMin.x) / g_PushConstants.Scale.x);
|
||||||
color *= lerp(DecodeColor(g_PushConstants.GradientTop), DecodeColor(g_PushConstants.GradientBottom), factor.y);
|
float maxAlpha = saturate((g_PushConstants.BoundsMax.x - interpolators.Position.x) / g_PushConstants.Scale.x);
|
||||||
|
|
||||||
|
color.a *= minAlpha;
|
||||||
|
color.a *= maxAlpha;
|
||||||
}
|
}
|
||||||
|
else if (any(g_PushConstants.BoundsMin != g_PushConstants.BoundsMax))
|
||||||
|
{
|
||||||
|
float2 factor = saturate((interpolators.Position.xy - g_PushConstants.BoundsMin) / (g_PushConstants.BoundsMax - g_PushConstants.BoundsMin));
|
||||||
|
color *= lerp(DecodeColor(g_PushConstants.GradientTop), DecodeColor(g_PushConstants.GradientBottom), smoothstep(0.0, 1.0, factor.y));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_GRAYSCALE)
|
||||||
|
color.rgb = dot(color.rgb, float3(0.2126, 0.7152, 0.0722));
|
||||||
|
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,17 @@
|
||||||
|
|
||||||
void main(in float2 position : POSITION, in float2 uv : TEXCOORD, in float4 color : COLOR, out Interpolators interpolators)
|
void main(in float2 position : POSITION, in float2 uv : TEXCOORD, in float4 color : COLOR, out Interpolators interpolators)
|
||||||
{
|
{
|
||||||
float2 correctedPosition = g_PushConstants.Origin + (position - g_PushConstants.Origin) * g_PushConstants.Scale;
|
if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_TEXT_SKEW)
|
||||||
interpolators.Position = float4(correctedPosition * g_PushConstants.InverseDisplaySize * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
|
{
|
||||||
|
if (position.y < g_PushConstants.Origin.y)
|
||||||
|
position.x += g_PushConstants.Scale.x;
|
||||||
|
}
|
||||||
|
else if (g_PushConstants.ShaderModifier != IMGUI_SHADER_MODIFIER_MARQUEE_FADE)
|
||||||
|
{
|
||||||
|
position.xy = g_PushConstants.Origin + (position.xy - g_PushConstants.Origin) * g_PushConstants.Scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
interpolators.Position = float4(position.xy * g_PushConstants.InverseDisplaySize * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
|
||||||
interpolators.UV = uv;
|
interpolators.UV = uv;
|
||||||
interpolators.Color = color;
|
interpolators.Color = color;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1101,8 +1101,8 @@ static constexpr uint32_t PLACEMENT_ALIGNMENT = 0x200;
|
||||||
|
|
||||||
struct ImGuiPushConstants
|
struct ImGuiPushConstants
|
||||||
{
|
{
|
||||||
ImVec2 gradientMin{};
|
ImVec2 boundsMin{};
|
||||||
ImVec2 gradientMax{};
|
ImVec2 boundsMax{};
|
||||||
ImU32 gradientTop{};
|
ImU32 gradientTop{};
|
||||||
ImU32 gradientBottom{};
|
ImU32 gradientBottom{};
|
||||||
uint32_t shaderModifier{};
|
uint32_t shaderModifier{};
|
||||||
|
|
@ -1921,7 +1921,7 @@ 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, gradientMin), sizeof(callbackData->setGradient));
|
commandList->setGraphicsPushConstants(0, &callbackData->setGradient, offsetof(ImGuiPushConstants, boundsMin), sizeof(callbackData->setGradient));
|
||||||
break;
|
break;
|
||||||
case ImGuiCallback::SetShaderModifier:
|
case ImGuiCallback::SetShaderModifier:
|
||||||
commandList->setGraphicsPushConstants(0, &callbackData->setShaderModifier, offsetof(ImGuiPushConstants, shaderModifier), sizeof(callbackData->setShaderModifier));
|
commandList->setGraphicsPushConstants(0, &callbackData->setShaderModifier, offsetof(ImGuiPushConstants, shaderModifier), sizeof(callbackData->setShaderModifier));
|
||||||
|
|
@ -1932,6 +1932,9 @@ static void ProcDrawImGui(const RenderCommand& cmd)
|
||||||
case ImGuiCallback::SetScale:
|
case ImGuiCallback::SetScale:
|
||||||
commandList->setGraphicsPushConstants(0, &callbackData->setScale, offsetof(ImGuiPushConstants, scale), sizeof(callbackData->setScale));
|
commandList->setGraphicsPushConstants(0, &callbackData->setScale, offsetof(ImGuiPushConstants, scale), sizeof(callbackData->setScale));
|
||||||
break;
|
break;
|
||||||
|
case ImGuiCallback::SetMarqueeFade:
|
||||||
|
commandList->setGraphicsPushConstants(0, &callbackData->setScale, offsetof(ImGuiPushConstants, boundsMin), sizeof(callbackData->setMarqueeFade));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -388,6 +388,8 @@ SWA_API uint32_t XamInputGetState(uint32_t userIndex, uint32_t flags, XAMINPUT_S
|
||||||
|
|
||||||
if (GetAsyncKeyState(VK_RETURN) & 0x8000)
|
if (GetAsyncKeyState(VK_RETURN) & 0x8000)
|
||||||
state->Gamepad.wButtons |= XAMINPUT_GAMEPAD_START;
|
state->Gamepad.wButtons |= XAMINPUT_GAMEPAD_START;
|
||||||
|
if (GetAsyncKeyState(VK_BACK) & 0x8000)
|
||||||
|
state->Gamepad.wButtons |= XAMINPUT_GAMEPAD_BACK;
|
||||||
|
|
||||||
ByteSwap(state->Gamepad.wButtons);
|
ByteSwap(state->Gamepad.wButtons);
|
||||||
ByteSwap(state->Gamepad.sThumbLX);
|
ByteSwap(state->Gamepad.sThumbLX);
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,9 @@ static void DrawHeaderContainer(const char* text)
|
||||||
|
|
||||||
DrawPauseHeaderContainer(g_upWindow.get(), min, max, alpha);
|
DrawPauseHeaderContainer(g_upWindow.get(), min, max, alpha);
|
||||||
|
|
||||||
// TODO: skew this text and apply bevel.
|
SetTextSkew((min.y + max.y) / 2.0f, Scale(3.0f));
|
||||||
|
|
||||||
|
// TODO: Apply bevel.
|
||||||
DrawTextWithOutline<int>
|
DrawTextWithOutline<int>
|
||||||
(
|
(
|
||||||
g_fntNewRodinUB,
|
g_fntNewRodinUB,
|
||||||
|
|
@ -149,6 +151,8 @@ static void DrawHeaderContainer(const char* text)
|
||||||
3,
|
3,
|
||||||
IM_COL32(0, 0, 0, 255 * alpha)
|
IM_COL32(0, 0, 0, 255 * alpha)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ResetTextSkew();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DrawAchievement(int rowIndex, float yOffset, Achievement& achievement, bool isUnlocked)
|
static void DrawAchievement(int rowIndex, float yOffset, Achievement& achievement, bool isUnlocked)
|
||||||
|
|
@ -182,8 +186,10 @@ static void DrawAchievement(int rowIndex, float yOffset, Achievement& achievemen
|
||||||
auto titleTextY = Scale(20);
|
auto titleTextY = Scale(20);
|
||||||
auto descTextY = Scale(52);
|
auto descTextY = Scale(52);
|
||||||
|
|
||||||
|
if (!isUnlocked)
|
||||||
|
SetShaderModifier(IMGUI_SHADER_MODIFIER_GRAYSCALE);
|
||||||
|
|
||||||
// Draw achievement icon.
|
// Draw achievement icon.
|
||||||
// TODO: make icon greyscale if locked?
|
|
||||||
drawList->AddImage
|
drawList->AddImage
|
||||||
(
|
(
|
||||||
icon,
|
icon,
|
||||||
|
|
@ -194,6 +200,9 @@ static void DrawAchievement(int rowIndex, float yOffset, Achievement& achievemen
|
||||||
IM_COL32(255, 255, 255, 255 * (isUnlocked ? 1 : 0.5f))
|
IM_COL32(255, 255, 255, 255 * (isUnlocked ? 1 : 0.5f))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!isUnlocked)
|
||||||
|
SetShaderModifier(IMGUI_SHADER_MODIFIER_NONE);
|
||||||
|
|
||||||
drawList->PushClipRect(min, max, true);
|
drawList->PushClipRect(min, max, true);
|
||||||
|
|
||||||
auto colLockedText = IM_COL32(60, 60, 60, 29);
|
auto colLockedText = IM_COL32(60, 60, 60, 29);
|
||||||
|
|
@ -219,13 +228,16 @@ static void DrawAchievement(int rowIndex, float yOffset, Achievement& achievemen
|
||||||
|
|
||||||
if (isSelected && textX + textSize.x >= max.x - Scale(10))
|
if (isSelected && textX + textSize.x >= max.x - Scale(10))
|
||||||
{
|
{
|
||||||
|
ImVec2 marqueeMin = { textMarqueeX, min.y };
|
||||||
|
SetMarqueeFade(marqueeMin, max, Scale(32.0f));
|
||||||
|
|
||||||
// Draw achievement description with marquee.
|
// Draw achievement description with marquee.
|
||||||
DrawTextWithMarqueeShadow
|
DrawTextWithMarqueeShadow
|
||||||
(
|
(
|
||||||
g_fntSeurat,
|
g_fntSeurat,
|
||||||
fontSize,
|
fontSize,
|
||||||
{ textX, min.y + descTextY },
|
{ textX, min.y + descTextY },
|
||||||
{ textMarqueeX, min.y },
|
marqueeMin,
|
||||||
max,
|
max,
|
||||||
isUnlocked ? IM_COL32(255, 255, 255, 255) : colLockedText,
|
isUnlocked ? IM_COL32(255, 255, 255, 255) : colLockedText,
|
||||||
desc,
|
desc,
|
||||||
|
|
@ -236,6 +248,8 @@ static void DrawAchievement(int rowIndex, float yOffset, Achievement& achievemen
|
||||||
0.4f,
|
0.4f,
|
||||||
colTextShadow
|
colTextShadow
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ResetMarqueeFade();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,10 @@
|
||||||
static void SetGradient(const ImVec2& min, const ImVec2& max, ImU32 top, ImU32 bottom)
|
static void SetGradient(const ImVec2& min, const ImVec2& max, ImU32 top, ImU32 bottom)
|
||||||
{
|
{
|
||||||
auto callbackData = AddImGuiCallback(ImGuiCallback::SetGradient);
|
auto callbackData = AddImGuiCallback(ImGuiCallback::SetGradient);
|
||||||
callbackData->setGradient.gradientMin[0] = min.x;
|
callbackData->setGradient.boundsMin[0] = min.x;
|
||||||
callbackData->setGradient.gradientMin[1] = min.y;
|
callbackData->setGradient.boundsMin[1] = min.y;
|
||||||
callbackData->setGradient.gradientMax[0] = max.x;
|
callbackData->setGradient.boundsMax[0] = max.x;
|
||||||
callbackData->setGradient.gradientMax[1] = max.y;
|
callbackData->setGradient.boundsMax[1] = max.y;
|
||||||
callbackData->setGradient.gradientTop = top;
|
callbackData->setGradient.gradientTop = top;
|
||||||
callbackData->setGradient.gradientBottom = bottom;
|
callbackData->setGradient.gradientBottom = bottom;
|
||||||
}
|
}
|
||||||
|
|
@ -50,6 +50,39 @@ static void SetScale(ImVec2 scale)
|
||||||
callbackData->setScale.scale[1] = scale.y;
|
callbackData->setScale.scale[1] = scale.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void SetTextSkew(float yCenter, float skewScale)
|
||||||
|
{
|
||||||
|
SetShaderModifier(IMGUI_SHADER_MODIFIER_TEXT_SKEW);
|
||||||
|
SetOrigin({ 0.0f, yCenter });
|
||||||
|
SetScale({ skewScale, 1.0f });
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ResetTextSkew()
|
||||||
|
{
|
||||||
|
SetShaderModifier(IMGUI_SHADER_MODIFIER_NONE);
|
||||||
|
SetOrigin({ 0.0f, 0.0f });
|
||||||
|
SetScale({ 1.0f, 1.0f });
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetMarqueeFade(ImVec2 min, ImVec2 max, float fadeScale)
|
||||||
|
{
|
||||||
|
auto callbackData = AddImGuiCallback(ImGuiCallback::SetMarqueeFade);
|
||||||
|
callbackData->setMarqueeFade.boundsMin[0] = min.x;
|
||||||
|
callbackData->setMarqueeFade.boundsMin[1] = min.y;
|
||||||
|
callbackData->setMarqueeFade.boundsMax[0] = max.x;
|
||||||
|
callbackData->setMarqueeFade.boundsMax[1] = max.y;
|
||||||
|
|
||||||
|
SetShaderModifier(IMGUI_SHADER_MODIFIER_MARQUEE_FADE);
|
||||||
|
SetScale({ fadeScale, 1.0f });
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ResetMarqueeFade()
|
||||||
|
{
|
||||||
|
ResetGradient();
|
||||||
|
SetShaderModifier(IMGUI_SHADER_MODIFIER_NONE);
|
||||||
|
SetScale({ 1.0f, 1.0f });
|
||||||
|
}
|
||||||
|
|
||||||
// Aspect ratio aware.
|
// Aspect ratio aware.
|
||||||
static float Scale(float size)
|
static float Scale(float size)
|
||||||
{
|
{
|
||||||
|
|
@ -173,9 +206,12 @@ static void DrawTextWithOutline(const ImFont* font, float fontSize, const ImVec2
|
||||||
for (int32_t i = -outlineSize + 1; i < outlineSize; i++)
|
for (int32_t i = -outlineSize + 1; i < outlineSize; i++)
|
||||||
{
|
{
|
||||||
for (int32_t j = -outlineSize + 1; j < outlineSize; j++)
|
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.x + i, pos.y + j }, outlineColor, text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
drawList->AddText(font, fontSize, pos, color, text);
|
drawList->AddText(font, fontSize, pos, color, text);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue