using System; using System.Numerics; using Dalamud.Bindings.ImGui; using Dalamud.Interface; using Dalamud.Interface.Utility.Raii; namespace Questionable.Windows.ChangelogComponents; internal sealed class ChangelogHeaderComponent { private float _animationTime; public void Reset() { _animationTime = 0f; } public void Draw(Action onCloseClicked) { _animationTime += ImGui.GetIO().DeltaTime; ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList(); Vector2 cursorScreenPos = ImGui.GetCursorScreenPos(); float x = ImGui.GetContentRegionAvail().X; float headerHeight = 120f; DrawBackground(windowDrawList, cursorScreenPos, x, headerHeight); DrawAnimatedBorder(windowDrawList, cursorScreenPos, x, headerHeight); DrawSparkles(windowDrawList, cursorScreenPos, x, headerHeight); DrawCloseButton(windowDrawList, cursorScreenPos, x, onCloseClicked); DrawHeaderContent(cursorScreenPos, x, headerHeight); DrawAccentLine(windowDrawList, cursorScreenPos, x, headerHeight); ImGui.SetCursorPosY(ImGui.GetCursorPosY() + 8f); } private void DrawBackground(ImDrawListPtr drawList, Vector2 headerStartPos, float contentWidth, float headerHeight) { float num = (MathF.Sin(_animationTime * 1.5f) + 1f) * 0.5f * 0.03f; uint num2 = ImGui.ColorConvertFloat4ToU32(new Vector4(0.15f + num, 0.1f + num, 0.2f + num, 0.95f)); uint num3 = ImGui.ColorConvertFloat4ToU32(new Vector4(0.08f, 0.05f, 0.12f, 0.95f)); drawList.AddRectFilledMultiColor(headerStartPos, headerStartPos + new Vector2(contentWidth, headerHeight), num2, num2, num3, num3); } private void DrawAnimatedBorder(ImDrawListPtr drawList, Vector2 headerStartPos, float contentWidth, float headerHeight) { float num = 100f; float num2 = 250f; float num3 = _animationTime * num % num2; float num4 = MathF.Ceiling(contentWidth / num2) + 2f; for (int i = 0; (float)i < num4; i++) { float num5 = (float)i * num2 - num3; float num6 = num5 + num2; if (!(num6 < 0f) && !(num5 > contentWidth)) { float num7 = MathF.Max(0f, num5); float num8 = MathF.Min(contentWidth, num6); float num9 = (num7 - num5) / num2; float num10 = (num8 - num5) / num2; float num11 = (MathF.Sin(num9 * (float)Math.PI * 2f - (float)Math.PI / 2f) + 1f) * 0.5f; float num12 = (MathF.Sin(num10 * (float)Math.PI * 2f - (float)Math.PI / 2f) + 1f) * 0.5f; Vector4 value = new Vector4(0.75f, 0.55f, 0.95f, num11 * 0.8f); Vector4 value2 = new Vector4(0.55f, 0.75f, 0.95f, num11 * 0.8f); Vector4 value3 = new Vector4(0.75f, 0.55f, 0.95f, num12 * 0.8f); Vector4 value4 = new Vector4(0.55f, 0.75f, 0.95f, num12 * 0.8f); float num13 = (num9 + num10) * 0.5f; Vector4 input = Vector4.Lerp(value, value2, num13); Vector4 input2 = Vector4.Lerp(value3, value4, num13 + 0.2f); drawList.AddRectFilledMultiColor(headerStartPos + new Vector2(num7, 0f), headerStartPos + new Vector2(num8, 3f), ImGui.ColorConvertFloat4ToU32(input), ImGui.ColorConvertFloat4ToU32(input2), ImGui.ColorConvertFloat4ToU32(input2), ImGui.ColorConvertFloat4ToU32(input)); } } } private void DrawSparkles(ImDrawListPtr drawList, Vector2 headerStartPos, float contentWidth, float headerHeight) { int num = 12; for (int i = 0; i < num; i++) { float num2 = (float)i * 123.456f; float num3 = 0.8f + (float)(i % 3) * 0.15f; float num4 = _animationTime * num3; float x = num2 * 12.345f % 1f * contentWidth; float y = (MathF.Sin(num4 + num2) + 1f) * 0.5f * headerHeight; Vector2 pos = headerStartPos + new Vector2(x, y); float num5 = (MathF.Sin(num4 * 3f + num2 * 2f) + 1f) * 0.5f; float alpha = num5 * 0.6f; float size = 2f + num5 * 1.5f; DrawSparkleShape(drawList, pos, size, alpha, i % 4, num4); } } private static void DrawSparkleShape(ImDrawListPtr drawList, Vector2 pos, float size, float alpha, int type, float time) { switch (type) { case 0: DrawCrossSparkle(drawList, pos, size, alpha); break; case 1: DrawDiamondSparkle(drawList, pos, size, alpha); break; case 2: DrawStarSparkle(drawList, pos, size, alpha, time); break; default: DrawCircleSparkle(drawList, pos, size, alpha); break; } } private static void DrawCrossSparkle(ImDrawListPtr drawList, Vector2 pos, float size, float alpha) { float num = size * 0.8f; float thickness = MathF.Max(1f, size * 0.3f); drawList.AddLine(pos - new Vector2(num, 0f), pos + new Vector2(num, 0f), ImGui.ColorConvertFloat4ToU32(new Vector4(0.9f, 0.8f, 1f, alpha)), thickness); drawList.AddLine(pos - new Vector2(0f, num), pos + new Vector2(0f, num), ImGui.ColorConvertFloat4ToU32(new Vector4(0.9f, 0.8f, 1f, alpha)), thickness); drawList.AddCircleFilled(pos, size * 1.5f, ImGui.ColorConvertFloat4ToU32(new Vector4(0.75f, 0.55f, 0.95f, alpha * 0.2f))); } private static void DrawDiamondSparkle(ImDrawListPtr drawList, Vector2 pos, float size, float alpha) { float num = size * 0.7f; Vector2 p = pos + new Vector2(0f, 0f - num); Vector2 p2 = pos + new Vector2(num, 0f); Vector2 p3 = pos + new Vector2(0f, num); Vector2 p4 = pos + new Vector2(0f - num, 0f); drawList.AddQuadFilled(p, p2, p3, p4, ImGui.ColorConvertFloat4ToU32(new Vector4(0.9f, 0.8f, 1f, alpha * 0.8f))); drawList.AddCircleFilled(pos, size * 1.6f, ImGui.ColorConvertFloat4ToU32(new Vector4(0.75f, 0.55f, 0.95f, alpha * 0.25f))); } private static void DrawStarSparkle(ImDrawListPtr drawList, Vector2 pos, float size, float alpha, float time) { for (int i = 0; i < 4; i++) { float num = (float)i * (float)Math.PI * 0.5f; float num2 = size * 0.3f; float num3 = size * 0.9f; float x = num - 0.3f; float x2 = num + 0.3f; Vector2 p = pos + new Vector2(MathF.Cos(x) * num2, MathF.Sin(x) * num2); Vector2 p2 = pos + new Vector2(MathF.Cos(num) * num3, MathF.Sin(num) * num3); Vector2 p3 = pos + new Vector2(MathF.Cos(x2) * num2, MathF.Sin(x2) * num2); drawList.AddTriangleFilled(p, p2, p3, ImGui.ColorConvertFloat4ToU32(new Vector4(0.9f, 0.8f, 1f, alpha))); } drawList.AddCircleFilled(pos, size * 1.7f, ImGui.ColorConvertFloat4ToU32(new Vector4(0.75f, 0.55f, 0.95f, alpha * 0.3f))); } private static void DrawCircleSparkle(ImDrawListPtr drawList, Vector2 pos, float size, float alpha) { drawList.AddCircleFilled(pos, size, ImGui.ColorConvertFloat4ToU32(new Vector4(0.9f, 0.8f, 1f, alpha))); drawList.AddCircleFilled(pos, size * 1.8f, ImGui.ColorConvertFloat4ToU32(new Vector4(0.75f, 0.55f, 0.95f, alpha * 0.3f))); } private void DrawCloseButton(ImDrawListPtr drawList, Vector2 headerStartPos, float contentWidth, Action onCloseClicked) { float num = 32f; Vector2 vector = headerStartPos + new Vector2(contentWidth - num - 8f, 8f); Vector2 center = vector + new Vector2(num * 0.5f, num * 0.5f); Vector2 mousePos = ImGui.GetMousePos(); bool flag = mousePos.X >= vector.X && mousePos.X <= vector.X + num && mousePos.Y >= vector.Y && mousePos.Y <= vector.Y + num; float w = (flag ? 0.9f : 0.5f); float num2 = (flag ? ((MathF.Sin(_animationTime * 4f) + 1f) * 0.5f * 0.1f) : 0f); uint col = (flag ? ImGui.ColorConvertFloat4ToU32(new Vector4(0.75f + num2, 0.55f, 0.95f, w)) : ImGui.ColorConvertFloat4ToU32(new Vector4(0.55f, 0.45f, 0.75f, w))); drawList.AddCircleFilled(center, num * 0.4f, col); DrawAnimatedCross(drawList, center, flag); ImGui.SetCursorScreenPos(vector); ImGui.InvisibleButton("CloseButton", new Vector2(num, num)); if (ImGui.IsItemClicked()) { onCloseClicked(obj: false); } } private void DrawAnimatedCross(ImDrawListPtr drawList, Vector2 center, bool isHovered) { float thickness = 2f; float w = (isHovered ? 1f : 0.8f); float x = (isHovered ? (MathF.Sin(_animationTime * 6f) * 0.1f) : 0f); float num = MathF.Cos(x); float num2 = MathF.Sin(x); float num3 = 8f * 0.5f; Vector2 vector = new Vector2((0f - num3) * num - (0f - num3) * num2, (0f - num3) * num2 + (0f - num3) * num); Vector2 vector2 = new Vector2(num3 * num - num3 * num2, num3 * num2 + num3 * num); Vector2 vector3 = new Vector2((0f - num3) * num - num3 * num2, (0f - num3) * num2 + num3 * num); Vector2 vector4 = new Vector2(num3 * num - (0f - num3) * num2, num3 * num2 + (0f - num3) * num); drawList.AddLine(center + vector, center + vector2, ImGui.ColorConvertFloat4ToU32(new Vector4(1f, 1f, 1f, w)), thickness); drawList.AddLine(center + vector3, center + vector4, ImGui.ColorConvertFloat4ToU32(new Vector4(1f, 1f, 1f, w)), thickness); } private void DrawHeaderContent(Vector2 headerStartPos, float contentWidth, float headerHeight) { float fadeIn = MathF.Min(1f, _animationTime * 2f); ImGui.SetCursorScreenPos(headerStartPos); ImGui.SetCursorPosY(ImGui.GetCursorPosY() + 30f); float centerX = contentWidth * 0.5f; DrawIcon(centerX, fadeIn); DrawTitle(centerX, fadeIn); DrawSubtitle(centerX); } private void DrawIcon(float centerX, float fadeIn) { float num = MathF.Sin(_animationTime * 2f) * 3f; float num2 = MathF.Sin(_animationTime * 1.5f + (float)Math.PI / 2f) * 1.5f; using (ImRaii.PushFont(UiBuilder.IconFont)) { string text = FontAwesomeIcon.FileAlt.ToIconString(); ImGui.SetCursorPosX(centerX - ImGui.CalcTextSize(text).X * 0.5f + num2); ImGui.SetCursorPosY(ImGui.GetCursorPosY() + num); float w = (MathF.Sin(_animationTime * 3f) + 1f) * 0.5f * 0.3f; Vector4 input = ((_animationTime * 0.5f % 1f < 0.5f) ? new Vector4(0.75f, 0.55f, 0.95f, w) : new Vector4(0.55f, 0.75f, 0.95f, w)); Vector2 cursorScreenPos = ImGui.GetCursorScreenPos(); ImGui.GetWindowDrawList().AddText(UiBuilder.IconFont, ImGui.GetFontSize() * 1.2f, cursorScreenPos + new Vector2(2f, 2f), ImGui.ColorConvertFloat4ToU32(input), text); ImGui.PushStyleVar(ImGuiStyleVar.Alpha, fadeIn); ImGui.TextColored(new Vector4(0.75f, 0.55f, 0.95f, 1f), text); ImGui.PopStyleVar(); } ImGui.SetCursorPosY(ImGui.GetCursorPosY() - num + 4f); } private void DrawTitle(float centerX, float fadeIn) { float num = MathF.Max(0f, 1f - (_animationTime - 0.1f) * 3f); float num2 = num * num * (3f - 2f * num) * 20f; using (ImRaii.PushFont(UiBuilder.MonoFont)) { string text = "What's New in Questionable?"; ImGui.SetCursorPosX(centerX - ImGui.CalcTextSize(text).X * 0.5f - num2); ImGui.PushStyleVar(ImGuiStyleVar.Alpha, fadeIn); ImGui.TextColored(new Vector4(0.95f, 0.95f, 1f, 1f), text); ImGui.PopStyleVar(); } ImGui.SetCursorPosY(ImGui.GetCursorPosY() + 6f); } private void DrawSubtitle(float centerX) { float val = MathF.Max(0f, MathF.Min(1f, (_animationTime - 0.3f) * 2f)); string text = "Stay up to date with the latest features and improvements"; ImGui.SetCursorPosX(centerX - ImGui.CalcTextSize(text).X * 0.5f); ImGui.PushStyleVar(ImGuiStyleVar.Alpha, val); ImGui.TextColored(new Vector4(0.7f, 0.7f, 0.8f, 0.9f), text); ImGui.PopStyleVar(); } private void DrawAccentLine(ImDrawListPtr drawList, Vector2 headerStartPos, float contentWidth, float headerHeight) { ImGui.SetCursorScreenPos(headerStartPos + new Vector2(0f, headerHeight)); Vector2 cursorScreenPos = ImGui.GetCursorScreenPos(); float num = (MathF.Sin(_animationTime * 2f + (float)Math.PI) + 1f) * 0.5f; drawList.AddRectFilledMultiColor(cursorScreenPos, cursorScreenPos + new Vector2(contentWidth, 2f), ImGui.ColorConvertFloat4ToU32(new Vector4(0.75f, 0.55f, 0.95f, 0.6f + num * 0.4f)), ImGui.ColorConvertFloat4ToU32(new Vector4(0.75f, 0.55f, 0.95f, 0.2f + num * 0.2f)), ImGui.ColorConvertFloat4ToU32(new Vector4(0.75f, 0.55f, 0.95f, 0.2f + num * 0.2f)), ImGui.ColorConvertFloat4ToU32(new Vector4(0.75f, 0.55f, 0.95f, 0.6f + num * 0.4f))); } }