#include "MenuFramework.h"
#include "../Renderer/Renderer.h"
#include "../Renderer/color.h"
#include "../Menu/Menu.h"
#include "../../Backend/Config/Settings.h"
#include "../../Backend/Config/Config.h"
#include "../../Backend/win32_utils/ClipboardUtils.h"
#include <chrono>
#include <map>

#pragma warning(disable : 4244)

using namespace GamesenseMenuFramework;
using namespace Globals;

// DPI scale lookup from config index: 0=1.0, 1=1.25, 2=1.5, 3=1.75, 4=2.0
// static float GetDpiScaleFromConfig() {
// 	int idx = CConfig::get()->i["menu_scale"];
// 	const float scales[] = { 1.0f, 1.25f, 1.5f, 1.75f, 2.0f };
// 	return scales[std::clamp(idx, 0, 4)];
// }

const char* keys[] = {"[-]","[M1]","[M2]","[CN]","[M3]","[M4]","[M5]","[-]","[BCK]","[TAB]","[-]","[-]","[CLR]","[RET]","[-]","[-]","[SHI]","[CTR]","[ALT]","[PAU]","[CAP]","[KAN]","[-]","[JUN]","[FIN]","[KAN]","[-]","[ESC]","[CON]","[NCO]","[ACC]","[MAD]","[SPA]","[PGU]","[PGD]","[END]","[HOM]","[LEF]","[UP]","[RIG]","[DOW]","[SEL]","[PRI]","[EXE]","[PRI]","[INS]","[DEL]","[HEL]","[0]","[1]","[2]","[3]","[4]","[5]","[6]","[7]","[8]","[9]","[0]","[-]","[-]","[-]","[-]","[-]","[-]","[A]","[B]","[C]","[D]","[E]","[F]","[G]","[H]","[I]","[J]","[K]","[L]","[M]","[N]","[O]","[P]","[Q]","[R]","[S]","[T]","[U]","[V]","[W]","[X]","[Y]","[Z]","[WIN]","[WIN]","[5D]","[-]","[SLE]","[KP0]","[KP1]","[KP2]","[KP3]","[KP4]","[KP5]","[KP6]","[KP7]","[KP8]","[KP9]","[KP*]","[KP+]","[SEP]","[KP-]","[KP.]","[KP/]","[F1]","[F2]","[F3]","[F4]","[F5]","[F6]","[F7]","[F8]","[F9]","[F10]","[F11]","[F12]","[F13]","[F14]","[F15]","[F16]","[F17]","[F18]","[F19]","[F20]","[F21]","[F22]","[F23]","[F24]","[-]","[-]","[-]","[-]","[-]","[-]","[-]","[-]","[NUM]","[SCR]","[EQU]","[MAS]","[TOY]","[OYA]","[OYA]","[-]","[-]","[-]","[-]","[-]","[-]","[-]","[-]","[-]","[SHI]","[SHI]","[CTR]","[CTR]","[ALT]","[ALT]"};

GuiContext* GamesenseMenuFramework::Globals::Gui_Ctx = NULL;
std::vector<DrawList::RenderObject> DrawList::Drawlist;

// Multi-key bind persistent cache (survives frames, avoids char[255] map write issues)
static std::map<std::string, std::string> g_multiKeyCache;
std::string& GamesenseMenuFramework::Globals::MultiKeyCache(const std::string& cfgKey) {
	return g_multiKeyCache[cfgKey];
}

void DrawList::AddText(const char* text, int x, int y, RLColor Color, RLFont font, bool bordered, Vec2 TextClipSize) {
	DrawList::Drawlist.emplace_back(DrawType_Text, Vec2(x, y), Vec2(0, 0), Color, RLColor{}, text, font, bordered, false, TextClipSize, false);
}

void DrawList::AddFilledRect(Vec2 Pos, Vec2 Size, RLColor Color) {
	DrawList::Drawlist.emplace_back(DrawType_FilledRect, Pos, Size, Color, RLColor{}, nullptr, RLFont{}, false, false, Vec2(0, 0), false);
}

void DrawList::AddRect(Vec2 Pos, Vec2 Size, RLColor Color, bool Antialias) {
	DrawList::Drawlist.emplace_back(DrawType_Rect, Pos, Size, Color, RLColor{}, nullptr, RLFont{}, false, false, Vec2(0, 0), Antialias);
}

void DrawList::AddGradient(Vec2 Pos, Vec2 Size, RLColor Color, RLColor OtherColor, bool Vertical, bool Antialias) {
	DrawList::Drawlist.emplace_back(DrawType_Gradient, Pos, Size, Color, OtherColor, nullptr, RLFont{}, false, Vertical, Vec2(0, 0), Antialias);
}

void ui::Shutdown(GuiContext* context) {
	GuiContext& g = *context;

	if (!g.Initialized)
		return;

	for (std::size_t i = 0; i < g.Windows.size(); i++)
		delete g.Windows[i];
	g.Windows.clear();
	g.WindowsByName.clear();

	g.Initialized = false;
}

void ui::Init(GuiContext* context) {
	GuiContext& g = *context;

	g.NextWindowInfo.PosCond = false;
	g.NextWindowInfo.SizeCond = false;
	memset(g.KeyState, 0, sizeof(g.KeyState));
	memset(g.PrevKeyState, 0, sizeof(g.PrevKeyState));

	g.Initialized = true;
}

GuiContext* ui::CreateContext() {
	GuiContext* ctx = new GuiContext();  // () ensures zero-initialization of KeyState/PrevKeyState arrays
	if (Gui_Ctx == NULL)
		Gui_Ctx = ctx;
	Init(ctx);
	return ctx;
}

void ui::DeleteContext(GuiContext* ctx) {
	if (ctx == NULL)
		ctx = Gui_Ctx;
	Shutdown(ctx);
	if (Gui_Ctx == ctx)
		Gui_Ctx = NULL;
	delete ctx;
}
// 查找窗口
GuiWindow* ui::FindWindowByName(const char*& name) {
	GuiContext& g = *Gui_Ctx;
	auto it = std::find(g.WindowsByName.begin(), g.WindowsByName.end(), name);
	int index;

	if (it != g.WindowsByName.end())
		index = it - g.WindowsByName.begin();
	else
		return NULL;

	return g.Windows.at(index);
}
// 创建新窗口
static GuiWindow* ui::CreateNewWindow(const char*& name, Vec2 size, GuiFlags flags) {
	GuiContext& g = *Gui_Ctx;

	GuiWindow* window = new GuiWindow;

	window->Init = false;
	window->Name = name;

	window->Pos = Vec2(0, 0);
	window->Size = size;
	window->CursorPos = Vec2(0, 0);
	window->PrevCursorPos = Vec2(0, 0);
	window->ScrollRatio = 0.f;

	window->Opened = false;
	window->Resizing = false;
	window->Dragging = false;
	window->Block = false;
	window->WidgetClicked = false;
	window->ParentWindow = NULL;
	window->ChildWindows;

	g.Windows.push_back(window);
	g.WindowsByName.push_back(name);

	return window;
}
// HWNDToString
std::string HWNDToString(HWND inputA)
{
	std::string s;
	int len = GetWindowTextLength(inputA);
	if (len > 0)
	{
		s.resize(len + 1);
		len = GetWindowText(inputA, LPWSTR(&s[0]), static_cast<int>(s.size()));
		s.resize(len);
	}
	return s;
}
// 获取窗口输入
void ui::GetInputFromWindow(const std::string& window_name) {	
	GuiContext& g = *Gui_Ctx;
	
	// Update DPI scale from config each frame
	// g.dpiScale = GetDpiScaleFromConfig();

	POINT p_mouse_pos;
	GetCursorPos(&p_mouse_pos);
	// Use FindWindowW because raylib creates the window via CreateWindowExW (Unicode title)
	int len = MultiByteToWideChar(CP_UTF8, 0, window_name.c_str(), -1, nullptr, 0);
	std::wstring wname(len, L'\0');
	MultiByteToWideChar(CP_UTF8, 0, window_name.c_str(), -1, &wname[0], len);
	ScreenToClient(FindWindowW(nullptr, wname.c_str()), &p_mouse_pos);

	for (int i = 0; i < 256; i++) {
		g.PrevKeyState[i] = g.KeyState[i];
		// Use MSB (bit 15) of GetAsyncKeyState: 1 = key currently held
		g.KeyState[i] = (GetAsyncKeyState(i) & 0x8000) != 0;
	}
		
	g.PrevMousePos = g.MousePos;
	// Mouse stays in physical pixel space (window/UI coords are already scaled)
	g.MousePos = Vec2{ (float)p_mouse_pos.x, (float)p_mouse_pos.y };
	g.IsBindingKey = false;
}
// 设置当前窗口
void ui::SetCurrentWindow(GuiWindow* window) {
	GuiContext& g = *Gui_Ctx;
	g.CurrentWindow = window;
}
// 获取当前窗口
GuiWindow* ui::GetCurrentWindow() {
	GuiContext& g = *Gui_Ctx;
	return g.CurrentWindow;
}
// 设置窗口大小
void ui::SetWindowSize(GuiWindow* window, const Vec2& size) {
	window->Size = size;
}
// 设置窗口大小
void ui::SetWindowSize(const Vec2& size) {
	ui::SetWindowSize(Gui_Ctx->CurrentWindow, size);
}
// 设置窗口大小
void ui::SetWindowSize(const char* name, const Vec2& size) {
	if (GuiWindow* window = ui::FindWindowByName(name))
		ui::SetWindowSize(window, size);
}
// 设置下一个窗口位置
void ui::SetNextWindowPos(const Vec2& pos) {
	GuiContext& g = *Gui_Ctx;
	g.NextWindowInfo.Pos = pos;
	g.NextWindowInfo.PosCond = true;
}
// 设置下一个窗口大小
void ui::SetNextWindowSize(const Vec2& size) {
	GuiContext& g = *Gui_Ctx;
	g.NextWindowInfo.Size = size;
	g.NextWindowInfo.SizeCond = true;

}
// 设置窗口位置
void ui::SetWindowPos(GuiWindow* window, const Vec2& pos) {
	const Vec2 old_pos = window->Pos;
	window->Pos = Vec2(floor(pos.x), floor(pos.y));
}
// 设置窗口位置
void ui::SetWindowPos(const Vec2& pos)
{
	GuiWindow* window = GetCurrentWindow();
	SetWindowPos(window, pos);
}
// 获取窗口位置
Vec2 ui::GetWindowPos() {
	return GetCurrentWindow()->Pos;
}
// 获取窗口大小
Vec2 ui::GetWindowSize() {
	GuiWindow* window = GetCurrentWindow();
	return window->Size;
}
// 检查按键是否按下按下
bool ui::KeyPressed(const int key) {
	GuiContext& g = *Gui_Ctx;
	return g.KeyState[key] && !g.PrevKeyState[key];
}
// 检查按键是否按下
bool ui::KeyDown(const int key) {
	GuiContext& g = *Gui_Ctx;
	return g.KeyState[key];
}
// 检查按键是否释放
bool ui::KeyReleased(const int key) {
	GuiContext& g = *Gui_Ctx;
	return !g.KeyState[key] && g.PrevKeyState[key];
}
// 检查鼠标是否在窗口内
bool ui::IsInside(const float x, const float y, const float w, const float h) {
	GuiContext& g = *Gui_Ctx;
	return g.MousePos.x > x && g.MousePos.y > y && g.MousePos.x < w + x && g.MousePos.y < h + y;
}
// 检查鼠标是否在窗口内
bool ui::IsInsideWindow(GuiWindow* Window) {
	if (!Gui_Ctx->Initialized)
		return false; 

	if (!Window)
		Window = Gui_Ctx->Windows.at(0);

	return IsInside(Window->Pos.x, Window->Pos.y, Window->Size.x, Window->Size.y);
}
// 检查窗口是否有激活的项
bool ui::NoItemsActive(GuiWindow* Window) {
	for (auto& it : Window->ItemActive) {
		if (it.second)
			return false;
	}

	return true;
}
// 检查窗口是否有打开的弹出窗口
bool ui::PopUpsAreClosed(GuiWindow* Window) {

	for (std::size_t i = 0; i < Window->PopUpWindows.size(); i++) {
		if (Window->PopUpWindows[i]->Opened)
			return false;
	}

	return true;
}
// 检查窗口是否有打开的子窗口
bool ui::ChildsAreStable(GuiWindow* Window) {
	for (std::size_t i = 0; i < Window->ChildWindows.size(); i++) {
		if (Window->ChildWindows[i]->Dragging || Window->ChildWindows[i]->Resizing || !NoItemsActive(Window->ChildWindows[i]) || !PopUpsAreClosed(Window->ChildWindows[i]))
			return false;
	}
	return true;
}
// 添加项到窗口
void ui::AddItemToWindow(GuiWindow* Window, Rect size, GuiFlags flags) {
	GuiContext& g = *Gui_Ctx;
	Window->PevCursorPos = Window->CursorPos;
	if (!(flags & GuiFlags_ColorPicker))
		Window->CursorPos = Window->CursorPos + Vec2(0, size.Max.y + ((flags & GuiFlags_ComboBox) || (flags & GuiFlags_PopUp) || (flags & GuiFlags_Listbox) ? 2 : g.ItemSpacing.y));
}
// 检查按钮是否被点击
bool ui::ButtonBehavior(GuiWindow* Window, const char* label, Rect bb, bool& hovered, bool& held, GuiFlags flags) {
	GuiWindow* current_window = GetCurrentWindow();
	bool prev_held = held;
	std::string* selected_item = !Window->ParentWindow ? &Window->SelectedItem : &Window->ParentWindow->SelectedItem;
	hovered = IsInside(bb.Min.x, bb.Min.y, bb.Max.x, bb.Max.y) && (*selected_item == "" || *selected_item == label);
	held = hovered && KeyDown(VK_LBUTTON);
	// Track whether press started on this item (fixes drag-to-click bug)
	static std::unordered_map<std::string, bool> pressStartedOnItem;
	if (hovered && KeyPressed(VK_LBUTTON)) {
		pressStartedOnItem[label] = true;
		// Block window drag immediately on press, not just on the committed event
		for (GuiWindow* w = Window; w; w = w->ParentWindow)
			w->WidgetClicked = true;
	}
	if (!(flags & GuiFlags_TabButton) && !(flags & GuiFlags_Selectable) && !(flags & GuiFlags_IntSlider) && !(flags & GuiFlags_ComboBox)) {
		if (hovered && ((flags & GuiFlags_ReturnKeyReleased) ? KeyReleased(VK_LBUTTON) : KeyPressed(VK_LBUTTON)) && !Window->ItemActive[label] && *selected_item == "") {
			Window->ItemActive[label] = true;
			*selected_item = label;
		}
		else if (!KeyDown(VK_LBUTTON) && Window->ItemActive[label]) {
			Window->ItemActive[label] = false;
			*selected_item = "";
		}
	}
	bool pressed;
	if (flags & GuiFlags_ReturnKeyReleased)
		pressed = hovered && KeyReleased(VK_LBUTTON) && pressStartedOnItem[label];
	else
		pressed = hovered && KeyPressed(VK_LBUTTON);
	if (!KeyDown(VK_LBUTTON))
		pressStartedOnItem[label] = false;
	if (pressed) {
		for (GuiWindow* w = Window; w; w = w->ParentWindow)
			w->WidgetClicked = true;
	}
	return pressed;
} 

template<typename T>
// 检查滑块是否被点击
bool ui::SliderBehavior(const char* item_id, Rect bb, T value, T min_value, T max_value, GuiFlags flags) {
	GuiContext& g = *Gui_Ctx;
	GuiWindow* current_window = GetCurrentWindow();
	bool hovered = IsInside(bb.Min.x, bb.Min.y, bb.Max.x, bb.Max.y) && current_window->ParentWindow->SelectedItem == "";

	if (hovered && KeyPressed(VK_LBUTTON) && !current_window->ItemActive[item_id] ) {
		current_window->ItemActive[item_id] = true;
		current_window->ParentWindow->SelectedItem = item_id;
	}

	else if (KeyDown(VK_LBUTTON) && current_window->ItemActive[item_id] && current_window->ParentWindow->SelectedItem == item_id) {
		if (flags & GuiFlags_FloatSlider)
			*value = float(std::clamp(g.MousePos.x - bb.Min.x, 0.0f, (bb.Max.x - 1)) / (bb.Max.x - 1) * (*max_value - *min_value) + *min_value);
		else if (flags & GuiFlags_IntSlider)
			*value = int(std::clamp(g.MousePos.x - bb.Min.x, 0.0f, (bb.Max.x - 1)) / (bb.Max.x - 1) * (*max_value - *min_value) + *min_value);
	}

	else if (!KeyDown(VK_LBUTTON) && current_window->ItemActive[item_id]) {
		current_window->ParentWindow->SelectedItem = "";
		current_window->ItemActive[item_id] = false;
	}
	return hovered;
}
// 检查颜色选择器是否被点击
HSV ui::ColorPickerBehavior(GuiWindow* PickerWindow, Rect& RcColor, Rect& RcAlpha, Rect& RcHue, int col[4], bool reset) {
	GuiContext& g = *Gui_Ctx;

	// Per-window state to avoid sharing across multiple color picker instances
	static std::unordered_map<GuiWindow*, int> s_ActiveBar;
	static std::unordered_map<GuiWindow*, HSV> s_HsvState;

	int& ActiveBar = s_ActiveBar[PickerWindow];

	CColor Ccol = CColor(col[0], col[1], col[2], col[3]);

	if (reset || s_HsvState.find(PickerWindow) == s_HsvState.end())
		s_HsvState[PickerWindow] = HSV(Ccol.Hue(), Ccol.Saturation(), Ccol.Brightness(), Ccol.a());

	HSV& hsv = s_HsvState[PickerWindow];

	bool hovered, held;
	ButtonBehavior(PickerWindow->ParentWindow, PickerWindow->Name.c_str(), { PickerWindow->Pos, PickerWindow->Size }, hovered, held);

	if (KeyDown(VK_LBUTTON)) {
		if ((IsInside(RcColor.Min.x, RcColor.Min.y, RcColor.Max.x, RcColor.Max.y) || ActiveBar == 0) && ActiveBar != 1 && ActiveBar != 2)
			ActiveBar = 0;
		else if ((IsInside(RcHue.Min.x, RcHue.Min.y, RcHue.Max.x, RcHue.Max.y) || ActiveBar == 1) && ActiveBar != 0 && ActiveBar != 2)
			ActiveBar = 1;
		else if ((IsInside(RcAlpha.Min.x, RcAlpha.Min.y, RcAlpha.Max.x, RcAlpha.Max.y) || ActiveBar == 2) && ActiveBar != 0 && ActiveBar != 1)
			ActiveBar = 2;
	}
	else
		ActiveBar = -1;

	switch (ActiveBar) {
	case 0:
		hsv.s = std::clamp((g.MousePos.x - RcColor.Min.x) / RcColor.Max.x, 0.f, 1.f);
		hsv.v = std::clamp(1.f - (g.MousePos.y - RcColor.Min.y) / RcColor.Max.y, 0.f, 1.f); break;
	case 1:
		hsv.h = std::clamp(1.f - (g.MousePos.y - RcHue.Min.y) / RcHue.Max.y, 0.f, 1.f); break;
	case 2:
		hsv.a = std::clamp(((g.MousePos.x - RcAlpha.Min.x) / RcAlpha.Max.x) * 255, 0.f, 255.f); break;
	}

	return hsv;
}
// 处理窗口移动
void ui::HandleMoving(GuiWindow* Window, Rect Boundaries, Vec2* buffer) {
	GuiContext& g = *Gui_Ctx;
	if (!(Window->Flags & GuiFlags_ChildWindow)) {
		if (IsInside(Window->Pos.x, Window->Pos.y, Window->Size.x, Window->Size.y) && KeyPressed(VK_LBUTTON) && !Window->Dragging && !IsInside(Window->Pos.x + Window->Size.x - 15, Window->Pos.y + Window->Size.y - 15, 15, 15) && !Window->Resizing && !Window->Block && ChildsAreStable(Window) && !Window->WidgetClicked)
			Window->Dragging = true;

		else if (KeyDown(VK_LBUTTON) && Window->Dragging && !(Window->Flags & GuiFlags_NoMove)) {
			const Vec2 mouse_delta{ g.MousePos.x - g.PrevMousePos.x , g.MousePos.y - g.PrevMousePos.y };
			const Vec2 new_position{ Window->Pos.x + mouse_delta.x, Window->Pos.y + mouse_delta.y };

			Window->Pos = Vec2(std::clamp(new_position.x, Boundaries.Min.x, Boundaries.Max.x), std::clamp(new_position.y, Boundaries.Min.y, Boundaries.Max.y));
		}

		else if (!KeyDown(VK_LBUTTON) && Window->Dragging)
			Window->Dragging = false;
	}
	else if ((Window->Flags & GuiFlags_ChildWindow) && buffer) {
		static Vec2 ClickPos;
		bool locked = CConfig::get()->b["lock_menu_layout"];

		Vec2 MinSize = Vec2((Boundaries.Max.x - 2.f) * (22.4f / 100.f), (Boundaries.Max.y - 2.f) * (13.4f / 100.f));
		Vec2 Step = Vec2((Boundaries.Max.x - MinSize.x - 2.f) / 9, (Boundaries.Max.y - MinSize.y - 2) / 10);

		if (!locked) {
			if (IsInside(Window->Pos.x, Window->Pos.y, Window->Size.x, 17) && KeyDown(VK_LBUTTON) && !Window->Dragging && !Window->Resizing && !Window->ParentWindow->Resizing && !Window->ParentWindow->Dragging && ui::ChildsAreStable(Window->ParentWindow) && !Window->WidgetClicked && NoItemsActive(Window)) {
				ClickPos.x = g.MousePos.x - Window->Pos.x;
				ClickPos.y = g.MousePos.y - Window->Pos.y;
				Window->Dragging = true;
			}

			else if (KeyDown(VK_LBUTTON) && Window->Dragging && !(Window->Flags & GuiFlags_NoMove)) {
				Window->xPos = (int)round((g.MousePos.x - buffer->x - ClickPos.x) / Step.x);
				Window->yPos = (int)round((g.MousePos.y - buffer->y - ClickPos.y) / Step.y);

				Window->xPos = std::clamp(Window->xPos, 0, 9 - Window->xSize);
				Window->yPos = std::clamp(Window->yPos, strstr(Window->Name.c_str(), "#Legit") ? 2 : 0, 10 - Window->ySize);
			}

			else if (!KeyDown(VK_LBUTTON) && Window->Dragging)
				Window->Dragging = false;
		}

		buffer->x += Window->xPos * Step.x;
		buffer->y += Window->yPos * Step.y;
	}
}
// 处理窗口调整大小
void ui::HandleResize(GuiWindow* Window, Rect Boundaries, Vec2* buffer) {
	GuiContext& g = *Gui_Ctx;
	if (!(Window->Flags & GuiFlags_ChildWindow) && !(Window->Flags & GuiFlags_ComboBox)) {
		if (CConfig::get()->b["lock_menu_layout"])
			return;
		if (IsInside(Window->Pos.x + Window->Size.x - 15, Window->Pos.y + Window->Size.y - 15, 15, 15) && KeyDown(VK_LBUTTON) && !Window->Resizing && !Window->Dragging && !Window->WidgetClicked)
			Window->Resizing = true;
		else if (KeyDown(VK_LBUTTON) && Window->Resizing && !(Window->Flags & GuiFlags_NoMove)) {
			Window->Size.x = std::clamp(g.MousePos.x - Window->Pos.x, Boundaries.Min.x, Boundaries.Max.x);
			Window->Size.y = std::clamp(g.MousePos.y - Window->Pos.y, Boundaries.Min.y, Boundaries.Max.y);
		}
		else if (!ui::KeyDown(VK_LBUTTON) && Window->Resizing)
			Window->Resizing = false;
	}
	else if (Window->Flags & GuiFlags_ChildWindow) {
		bool locked = CConfig::get()->b["lock_menu_layout"];
		Vec2 MinSize = Vec2((Boundaries.Max.x - 2.f) * (22.4f / 100.f), (Boundaries.Max.y - 2.f) * (13.4f / 100.f));
		Vec2 Step = Vec2((Boundaries.Max.x - MinSize.x - 2.f) / 9, (Boundaries.Max.y - MinSize.y - 2) / 10);

		if (!locked) {
			if (IsInside(Window->Pos.x + Window->Size.x - 15, Window->Pos.y + Window->Size.y - 15, 15, 15) && KeyDown(VK_LBUTTON) && !Window->Resizing && !Window->Dragging && !Window->ParentWindow->Resizing && ui::ChildsAreStable(Window->ParentWindow) && NoItemsActive(Window))
				Window->Resizing = true;

			else if (KeyDown(VK_LBUTTON) && Window->Resizing && !(Window->Flags & GuiFlags_NoMove)) {
				if (g.MousePos.x >= Window->Pos.x + Window->Size.x + Step.x)
					Window->xSize = (int)round((g.MousePos.x - Window->Pos.x - MinSize.x) / Step.x);
				else if (g.MousePos.x <= Window->Pos.x + Window->Size.x - Step.x)
					Window->xSize = (int)round((g.MousePos.x - Window->Pos.x - MinSize.x) / Step.x);

				Window->xSize = std::clamp(Window->xSize, 0, 9 - Window->xPos);

				if (g.MousePos.y >= Window->Pos.y + Window->Size.y + Step.y)
					Window->ySize = (int)round((g.MousePos.y - Window->Pos.y - MinSize.y) / Step.y);
				else if (g.MousePos.y <= Window->Pos.y + Window->Size.y - Step.y)
					Window->ySize = (int)round((g.MousePos.y - Window->Pos.y - MinSize.y) / Step.y);

				Window->ySize = std::clamp(Window->ySize, 0, 10 - Window->yPos);
			}
			else if (!KeyDown(VK_LBUTTON) && Window->Resizing)
				Window->Resizing = false;
		}

		*buffer = Vec2(MinSize.x + (Step.x * Window->xSize), MinSize.y + (Step.y * Window->ySize));
	}
}
// 开始绘制窗口
void ui::Begin(const char* Name, GuiFlags flags) {
	GuiContext& g = *Gui_Ctx;
	static Vec2 size_on_first_use;
	GuiWindow* Window = FindWindowByName(Name);

	if (Window == NULL) {
		if (g.NextWindowInfo.SizeCond)
			size_on_first_use = g.NextWindowInfo.Size;
		else
			size_on_first_use = Vec2(10, 10);
		// Scale logical window size to physical pixels for rendering
		size_on_first_use.x *= g.dpiScale;
		size_on_first_use.y *= g.dpiScale;
		Window = CreateNewWindow(Name, size_on_first_use, flags);
	}

	if (g.NextWindowInfo.PosCond) {
		Window->Pos = g.NextWindowInfo.Pos;
		// Only scale non-child windows (child windows arrive pre-scaled from BeginChild)
		if (!(flags & GuiFlags_ChildWindow) && !(Window->Flags & GuiFlags_ChildWindow))
		{
			Window->Pos.x *= g.dpiScale;
			Window->Pos.y *= g.dpiScale;
		}
		g.NextWindowInfo.PosCond = false;
	}

	if ((Window->Flags & GuiFlags_ChildWindow) || (Window->Flags & GuiFlags_PopUp) || (Window->Flags & GuiFlags_Listbox) && g.NextWindowInfo.SizeCond) {
		Window->Size = g.NextWindowInfo.Size;
		// Only scale non-child windows (child windows arrive pre-scaled from BeginChild)
		if (!(flags & GuiFlags_ChildWindow) && !(Window->Flags & GuiFlags_ChildWindow))
		{
			Window->Size.x *= g.dpiScale;
			Window->Size.y *= g.dpiScale;
		}
		g.NextWindowInfo.SizeCond = false;
	}

	if (!(Window->Flags & GuiFlags_ChildWindow) && !(Window->Flags & GuiFlags_PopUp)  && !ui::ChildsAreStable(Window))
		Window->Block = true;
	else
		Window->Block = false;

	Window->CursorPos = Window->Pos;

	int offset = (int)Window->PrevCursorPos.y - (int)((int)Window->Pos.y + (int)Window->Size.y);

	Window->CursorPos.y -= !(Window->PrevCursorPos.y > Window->Pos.y + Window->Size.y) ? 0 : (int)(offset * Window->ScrollRatio);

	Window->Flags = flags;

	//Drawing
	if (!(flags & GuiFlags_ChildWindow) && !(flags & GuiFlags_PopUp) && !(flags & GuiFlags_Listbox)) {
		Render::Draw->FilledRect(Window->Pos, Vec2(Window->Size.x, Window->Size.y), RLColor{ (unsigned char)(0), (unsigned char)(0), (unsigned char)(0), (unsigned char)(g.MenuAlpha) });

		Render::Draw->Sprite(Render::Draw->GetBgTexture(), Window->Pos, Window->Size, RLColor{ (unsigned char)(255), (unsigned char)(255), (unsigned char)(255), (unsigned char)(g.MenuAlpha) });

		int OutlineColors[6] = { 12, 61, 43, 43, 43, 61 };
		for (int i = 0; i < 6; i++)
			Render::Draw->Rect(Window->Pos + Vec2((float)i, (float)i), Window->Size - Vec2(2 * (float)i, 2 * (float)i), 0, RLColor{ (unsigned char)(OutlineColors[i]), (unsigned char)(OutlineColors[i]), (unsigned char)(OutlineColors[i]), (unsigned char)(g.MenuAlpha) });

		Render::Draw->FilledRect(Window->Pos + Vec2(6, 6), Vec2(Window->Size.x - 12, 4), RLColor{ (unsigned char)(12), (unsigned char)(12), (unsigned char)(12), (unsigned char)(g.MenuAlpha) });
		Render::Draw->Gradient(Window->Pos + Vec2(7, 7), Vec2(Window->Size.x / 2 - 7, 2), RLColor{ (unsigned char)(55), (unsigned char)(177), (unsigned char)(218), (unsigned char)(g.MenuAlpha) }, RLColor{ (unsigned char)(204), (unsigned char)(70), (unsigned char)(205), (unsigned char)(g.MenuAlpha) }, false);
		Render::Draw->Gradient(Window->Pos + Vec2(7 + (Window->Size.x / 2 - 7), 7), Vec2(Window->Size.x / 2 - 7, 2), RLColor{ (unsigned char)(204), (unsigned char)(70), (unsigned char)(205), (unsigned char)(g.MenuAlpha) }, RLColor{ (unsigned char)(204), (unsigned char)(227), (unsigned char)(53), (unsigned char)(g.MenuAlpha) }, false);
		Render::Draw->FilledRect(Window->Pos + Vec2(7, 8), Vec2(Window->Size.x - 14, 1), RLColor{ (unsigned char)(0), (unsigned char)(0), (unsigned char)(0), (unsigned char)(std::clamp(119, 0, g.MenuAlpha)) });
		Render::Draw->Line(Window->Pos + Vec2(7, 9), Window->Pos + Vec2(Window->Size.x - 7, 9), RLColor{ (unsigned char)(6), (unsigned char)(6), (unsigned char)(6), (unsigned char)(g.MenuAlpha) });

		Render::Draw->FilledRect(Window->Pos + Vec2(6, 10), Vec2(74, 9), RLColor{ (unsigned char)(12), (unsigned char)(12), (unsigned char)(12), (unsigned char)(g.MenuAlpha) });
		Render::Draw->Line(Window->Pos + Vec2(81, 10), Window->Pos + Vec2(80, 19), RLColor{ (unsigned char)(40), (unsigned char)(40), (unsigned char)(40), (unsigned char)(g.MenuAlpha) });
		Render::Draw->Line(Window->Pos + Vec2(80, 10), Window->Pos + Vec2(79, 19), RLColor{ (unsigned char)(0), (unsigned char)(0), (unsigned char)(0), (unsigned char)(g.MenuAlpha) });

		Render::Draw->FilledRect(Window->Pos + Vec2(6, 546), Vec2(74, Window->Size.y - 552), RLColor{ (unsigned char)(12), (unsigned char)(12), (unsigned char)(12), (unsigned char)(g.MenuAlpha) });
		Render::Draw->Line(Window->Pos + Vec2(81, 546), Window->Pos + Vec2(80, Window->Size.y - 6), RLColor{ (unsigned char)(40), (unsigned char)(40), (unsigned char)(40), (unsigned char)(g.MenuAlpha) });
		Render::Draw->Line(Window->Pos + Vec2(80, 547), Window->Pos + Vec2(79, Window->Size.y - 6), RLColor{ (unsigned char)(0), (unsigned char)(0), (unsigned char)(0), (unsigned char)(g.MenuAlpha) });
	}
	else if (flags & GuiFlags_ChildWindow) {
		Vec2 label_size;

		std::string ChildName = Window->Name;

		if (Window->Name.find("#") != std::string::npos)
			ChildName = ChildName.substr(0, Window->Name.find("#"));

		if (!ChildName.empty())
			label_size = Render::Draw->GetTextSize(FM_Verdana(), ChildName.c_str());

		Window->Pos = Vec2(floor(Window->Pos.x), floor(Window->Pos.y));
		Window->Size = Vec2(floor(Window->Size.x), floor(Window->Size.y));

		RLColor border_color = Window->Resizing == true ? RLColor{ (unsigned char)(163), (unsigned char)(212), (unsigned char)(31), (unsigned char)(g.MenuAlpha) } : RLColor{ (unsigned char)(40), (unsigned char)(40), (unsigned char)(40), (unsigned char)(g.MenuAlpha) };

		Render::Draw->FilledRect(Window->Pos + Vec2(2, 2), Window->Size - Vec2(3, 3), RLColor{ (unsigned char)(23), (unsigned char)(23), (unsigned char)(23), (unsigned char)(g.MenuAlpha) });

		Render::Draw->Line(Window->Pos, Window->Pos + Vec2(0, Window->Size.y), RLColor{ (unsigned char)(12), (unsigned char)(12), (unsigned char)(12), (unsigned char)(g.MenuAlpha) });
		Render::Draw->Line(Window->Pos + Vec2(0, Window->Size.y - 1), Window->Pos + Window->Size - Vec2(0, 1), RLColor{ (unsigned char)(12), (unsigned char)(12), (unsigned char)(12), (unsigned char)(g.MenuAlpha) });
		Render::Draw->Line(Window->Pos + Window->Size - Vec2(1, 1), Window->Pos + Vec2(Window->Size.x - 1, 0), RLColor{ (unsigned char)(12), (unsigned char)(12), (unsigned char)(12), (unsigned char)(g.MenuAlpha) });
		Render::Draw->Line(Window->Pos, Window->Pos + Vec2(10, 0), RLColor{ (unsigned char)(12), (unsigned char)(12), (unsigned char)(12), (unsigned char)(g.MenuAlpha) });
		Render::Draw->Line(Window->Pos + Vec2(16 + label_size.x, 0), Window->Pos + Vec2(Window->Size.x, 0), RLColor{ (unsigned char)(12), (unsigned char)(12), (unsigned char)(12), (unsigned char)(g.MenuAlpha) });

		Render::Draw->Line(Window->Pos + Vec2(1, 1), Window->Pos + Vec2(1, Window->Size.y - 1), border_color);
		Render::Draw->Line(Window->Pos + Vec2(1, Window->Size.y - 2), Window->Pos + Window->Size - Vec2(1, 2), border_color);
		Render::Draw->Line(Window->Pos + Window->Size - Vec2(2, 2), Window->Pos + Vec2(Window->Size.x - 1, 1), border_color);
		Render::Draw->Line(Window->Pos + Vec2(1, 1), Window->Pos + Vec2(10, 1), border_color);
		Render::Draw->Line(Window->Pos + Vec2(16 + label_size.x, 1), Window->Pos + Vec2(Window->Size.x - 1, 1), border_color);

		Render::Draw->Triangle(Window->Pos + Window->Size - Vec2(2, 2), Window->Pos + Window->Size - Vec2(2, 8), Window->Pos + Window->Size - Vec2(8, 2), border_color, true);
	}
	else if (((flags & GuiFlags_ComboBox) || (flags & GuiFlags_PopUp)) && Window->Opened) {
		DrawList::AddRect(Window->Pos, Window->Size, RLColor{ (unsigned char)(12), (unsigned char)(12), (unsigned char)(12), (unsigned char)(g.MenuAlpha) });
		DrawList::AddFilledRect(Window->Pos + Vec2(1, 1), Window->Size - Vec2(2, 2), RLColor{ (unsigned char)(35), (unsigned char)(35), (unsigned char)(35), (unsigned char)(g.MenuAlpha) });
	}
	else if ((flags & GuiFlags_ColorPicker && Window->Opened)) {
		DrawList::AddRect(Window->Pos, Window->Size, RLColor{ (unsigned char)(12), (unsigned char)(12), (unsigned char)(12), (unsigned char)(g.MenuAlpha) });
		DrawList::AddRect(Window->Pos + Vec2(1, 1), Window->Size - Vec2(2, 2), RLColor{ (unsigned char)(60), (unsigned char)(60), (unsigned char)(60), (unsigned char)(g.MenuAlpha) });
		DrawList::AddFilledRect(Window->Pos + Vec2(2, 2), Window->Size - Vec2(4, 4), RLColor{ (unsigned char)(40), (unsigned char)(40), (unsigned char)(40), (unsigned char)(g.MenuAlpha) });
	}
	else if ((flags & GuiFlags_Listbox)) {
		Render::Draw->Rect(Window->Pos, Window->Size, 1, RLColor{ (unsigned char)(12), (unsigned char)(12), (unsigned char)(12), (unsigned char)(g.MenuAlpha) });
		Render::Draw->FilledRect(Window->Pos + Vec2(1, 1), Window->Size - Vec2(2, 2), RLColor{ (unsigned char)(35), (unsigned char)(35), (unsigned char)(35), (unsigned char)(g.MenuAlpha) });
	}	

	// Only reset WidgetClicked when mouse is released, so drag stays blocked during a hold
	if (!KeyDown(VK_LBUTTON))
		Window->WidgetClicked = false;

	SetCurrentWindow(Window);
}
// 结束绘制窗口
void ui::End() {
	GuiContext& g = *Gui_Ctx;
	GuiWindow* Window = GetCurrentWindow();
	GuiFlags flags = Window->Flags;

	if (GetCurrentWindow()->Flags == GuiFlags_None) {
		for (const auto obj : DrawList::Drawlist) {
			if (obj.Type == DrawType_Text)
				Render::Draw->Text(obj.Text, obj.Pos.x, obj.Pos.y, LEFT, obj.Font, false, obj.Color, obj.TextClipSize);
			else if (obj.Type == DrawType_FilledRect)
				Render::Draw->FilledRect(obj.Pos, obj.Size, obj.Color);
			else if (obj.Type == DrawType_Rect)
				Render::Draw->Rect(obj.Pos, obj.Size, 1, obj.Color, obj.Antialias);
			else if (obj.Type == DrawType_Gradient)
				Render::Draw->Gradient(obj.Pos, obj.Size, obj.Color, obj.OtherColor, obj.Vertical, obj.Antialias);
		}

		DrawList::Drawlist.clear();
		g.MouseWheel = 0.f;
	}

	if (!Window->Block && !(flags & GuiFlags_ChildWindow) && !(Window->Flags & GuiFlags_PopUp) && !(Window->Flags & GuiFlags_Listbox)) {
		HandleMoving(Window, Rect{ Vec2(0 - Window->Size.x / 2, 0 - Window->Size.y / 2), Vec2(Render::Draw->Screen.Width + Window->Size.x / 2, Render::Draw->Screen.Height + Window->Size.y / 2) });
		HandleResize(Window, Rect{ Vec2(660 * g.dpiScale, 560 * g.dpiScale), Vec2(1920 * g.dpiScale, 1080 * g.dpiScale) });
	}
}
// 开始绘制子窗口
void ui::BeginChild(const char* Name, Rect X, GuiFlags flags) {
	GuiContext& g = *Gui_Ctx;
	GuiWindow* parent_window = g.Windows.at(0);
	flags |= GuiFlags_ChildWindow;

	if (!parent_window->ChildWindows.empty()) {

		int idx = 0;
		auto iterration = std::find(parent_window->ChildWindows.begin(), parent_window->ChildWindows.end(), FindWindowByName(Name));

		if (iterration != parent_window->ChildWindows.end())
			idx = std::distance(parent_window->ChildWindows.begin(), iterration);

		if (parent_window->ChildWindows.at(idx)) {
			float s = g.dpiScale;
			Rect Boundaries = { parent_window->Pos.x + 99 * s, parent_window->Pos.y + 29 * s,
			                    parent_window->Size.x - (99 + 23) * s, parent_window->Size.y - (29 + 23) * s };

			Vec2 ChildPos = ui::GetWindowPos() + Vec2(100 * s, 30 * s);
			Vec2 ChildSize;

			if (!parent_window->ChildWindows.at(idx)->Block) {
				HandleMoving(parent_window->ChildWindows.at(idx), Boundaries, &ChildPos);
				HandleResize(parent_window->ChildWindows.at(idx), Boundaries, &ChildSize);
			}

			SetNextWindowPos(ChildPos);
			SetNextWindowSize(ChildSize);
		}
	}

	Begin(Name, flags);

	GuiWindow* child_window = GetCurrentWindow();
	child_window->ParentWindow = parent_window;

	float s = g.dpiScale;
	RECT ClipRect = { (LONG)child_window->Pos.x, (LONG)child_window->Pos.y + (LONG)(4 * s), LONG(child_window->Pos.x + child_window->Size.x - 15 * s), LONG(child_window->Pos.y + child_window->Size.y - 3 * s) };
	int sx = (int)child_window->Pos.x;
	int sy = (int)(child_window->Pos.y + 4 * s);
	int sw = (int)(child_window->Size.x - 15 * s);
	int sh = (int)(child_window->Size.y - 7 * s);
	if (sw < 0) sw = 0;
	if (sh < 0) sh = 0;
	RLBeginScissorMode(sx, sy, sw, sh);

	if (!child_window->Init) {
		parent_window->ChildWindows.push_back(FindWindowByName(Name));
		
		child_window->xPos = (int)X.Min.x;
		child_window->yPos = (int)X.Min.y;
		
		child_window->xSize = (int)X.Max.x;
		child_window->ySize = (int)X.Max.y;
		
		child_window->Init = true;
	}

	child_window->CursorPos += Vec2(22 * g.dpiScale, 26 * g.dpiScale);
}
// 结束绘制子窗口
void ui::EndChild() {
	GuiContext& g = *Gui_Ctx;
	GuiWindow* window = GetCurrentWindow();
	
	window->CursorPos.y += 8 * g.dpiScale;

	RLEndScissorMode();

	if (window->PrevCursorPos.y > window->Pos.y + window->Size.y && (window->ScrollRatio >= 0.f || (!window->ParentWindow->Dragging || !ChildsAreStable(window->ParentWindow)))) {
		if (window->ScrollRatio == -1.f)
			window->ScrollRatio = 0.f;

		int scroll_height = window->Size.y / ((window->PrevCursorPos.y - window->Pos.y) / (window->Size.y));
		int offset = (window->Size.y - scroll_height) * window->ScrollRatio;

		Render::Draw->FilledRect(Vec2(window->Pos.x + window->Size.x - 7, window->Pos.y + 1), Vec2(6, window->Size.y - 2), RLColor{ (unsigned char)(40), (unsigned char)(40), (unsigned char)(40), (unsigned char)(g.MenuAlpha) });
		Render::Draw->FilledRect(Vec2(window->Pos.x + window->Size.x - 6, window->Pos.y + 3 + offset), Vec2(4, scroll_height - 6), RLColor{ (unsigned char)(65), (unsigned char)(65), (unsigned char)(65), (unsigned char)(g.MenuAlpha) });

		if (IsInside(window->Pos.x, window->Pos.y, window->Size.x, window->Size.y))
			window->ScrollRatio = std::clamp(window->ScrollRatio - g.MouseWheel * (20.f / ((int)window->PrevCursorPos.y - (int)((int)window->Pos.y + (int)window->Size.y))), 0.f, 1.f);

		if (window->ScrollRatio > 0.0f) {
			Render::Draw->Gradient(window->Pos + Vec2(2, 2), Vec2(window->Size.x - 9, 22), RLColor{ (unsigned char)(23), (unsigned char)(23), (unsigned char)(23), (unsigned char)(g.MenuAlpha) }, RLColor{ (unsigned char)(23), (unsigned char)(23), (unsigned char)(23), (unsigned char)(0) }, true);
			Render::Draw->Triangle(Vec2((int)window->Pos.x, (int)window->Pos.y) + Vec2((int)window->Size.x - 15, 8), Vec2((int)window->Pos.x, (int)window->Pos.y) + Vec2((int)window->Size.x - 18, 12), Vec2((int)window->Pos.x, (int)window->Pos.y) + Vec2((int)window->Size.x - 12, 12), RLColor{ (unsigned char)(157), (unsigned char)(157), (unsigned char)(157), (unsigned char)(g.MenuAlpha) });
		}
		if (window->ScrollRatio < 1.0f) {
			Render::Draw->Gradient(window->Pos + Vec2(2, window->Size.y - 21), Vec2(window->Size.x - 9, 19), RLColor{ (unsigned char)(23), (unsigned char)(23), (unsigned char)(23), (unsigned char)(0) }, RLColor{ (unsigned char)(23), (unsigned char)(23), (unsigned char)(23), (unsigned char)(g.MenuAlpha) }, true);
			Render::Draw->Triangle(Vec2((int)window->Pos.x, (int)window->Pos.y + (int)window->Size.y) + Vec2((int)window->Size.x - 17, -11), Vec2((int)window->Pos.x, (int)window->Pos.y + (int)window->Size.y) + Vec2((int)window->Size.x - 15, -8), Vec2((int)window->Pos.x, (int)window->Pos.y + (int)window->Size.y) + Vec2((int)window->Size.x - 12, -11), RLColor{ (unsigned char)(157), (unsigned char)(157), (unsigned char)(157), (unsigned char)(g.MenuAlpha) });
		}
	}
	else {
		window->ScrollRatio = -1.f;
	}
		

	int offset = (int)window->PrevCursorPos.y - (int)((int)window->Pos.y + (int)window->Size.y);
	window->CursorPos.y += !(window->PrevCursorPos.y > (int)window->Pos.y + (int)window->Size.y) ? 0 : (int)(offset * window->ScrollRatio);
	window->PrevCursorPos = window->CursorPos;
	
	Vec2 text_size;
	std::string ChildName = window->Name;

	if (window->Name.find("#") != std::string::npos)
		ChildName = ChildName.substr(0, window->Name.find("#"));

	
	if (!ChildName.empty())
		text_size = Render::Draw->GetTextSize(FM_Verdana(), ChildName.c_str());
	
	Render::Draw->Text(ChildName.c_str(), window->Pos.x + 14, window->Pos.y + (text_size.y / -2) + 1, LEFT, FM_Verdana(), false, RLColor{ (unsigned char)(15), (unsigned char)(15), (unsigned char)(15), (unsigned char)(g.MenuAlpha) });
	Render::Draw->Text(ChildName.c_str(), window->Pos.x + 13, window->Pos.y + (text_size.y / -2), LEFT, FM_Verdana(), false, window->Dragging ? CMenu::get()->GetMenuColor() : RLColor{ (unsigned char)(205), (unsigned char)(205), (unsigned char)(205), (unsigned char)(g.MenuAlpha) });

	SetCurrentWindow(g.Windows.at(0));
}
// 绘制选项卡按钮
void ui::TabButton(const char* label, int* selected, int num, int total, GuiFlags flags) {
	GuiContext& g = *Gui_Ctx;
	GuiWindow* Window = GetCurrentWindow();
	
	Vec2 DrawPos = Window->Pos + Vec2(6, 19) + Vec2(0, float((461 + total) / total * num));
	Vec2 Size = Vec2(74, 66);

	const int sizes[] = { 69, 60, 82, 57, 70, 88 };
	const Vec2 positions[] = {Vec2(15, 17), Vec2(97, 12),  Vec2(170, 19), Vec2(265, 17),  Vec2(335, 15), Vec2(419, 16)};

	if (flags & GuiFlags_LegitTab) {
		Size = Vec2(sizes[num], 68);
		DrawPos = Window->Pos + positions[num];
	}

	const Vec2 label_size = Render::Draw->GetTextSize(FM_TabIcons(), label);
	const Rect bb = { DrawPos.x, DrawPos.y, Size.x, Size.y };
	
	if (!(flags & GuiFlags_LegitTab)) {
		if (*selected != num) {
			Render::Draw->Line(Vec2(DrawPos.x + Size.x + 1, DrawPos.y - 1), Vec2(DrawPos.x + Size.x, DrawPos.y + Size.y), RLColor{ (unsigned char)(40), (unsigned char)(40), (unsigned char)(40), (unsigned char)(g.MenuAlpha) });
			Render::Draw->Line(Vec2(DrawPos.x + Size.x, DrawPos.y), Vec2(DrawPos.x + Size.x - 1, DrawPos.y + Size.y), RLColor{ (unsigned char)(0), (unsigned char)(0), (unsigned char)(0), (unsigned char)(g.MenuAlpha) });
			Render::Draw->FilledRect(DrawPos + Vec2(0, 0), Size - Vec2(1, 0), RLColor{ (unsigned char)(12), (unsigned char)(12), (unsigned char)(12), (unsigned char)(g.MenuAlpha) });
		}
		else {
			Render::Draw->Line(DrawPos, DrawPos + Vec2(Size.x + 1, 0), RLColor{ (unsigned char)(40), (unsigned char)(40), (unsigned char)(40), (unsigned char)(g.MenuAlpha) });
			Render::Draw->Line(DrawPos - Vec2(0, 1), DrawPos + Vec2(Size.x, -1), RLColor{ (unsigned char)(0), (unsigned char)(0), (unsigned char)(0), (unsigned char)(g.MenuAlpha) });

			Render::Draw->Line(DrawPos + Vec2(0, Size.y - 2), DrawPos + Vec2(Size.x + 1, Size.y - 2), RLColor{ (unsigned char)(40), (unsigned char)(40), (unsigned char)(40), (unsigned char)(g.MenuAlpha) });
			Render::Draw->Line(DrawPos + Vec2(0, Size.y - 1), DrawPos + Vec2(Size.x, Size.y - 1), RLColor{ (unsigned char)(0), (unsigned char)(0), (unsigned char)(0), (unsigned char)(g.MenuAlpha) });
		}
	}

	bool hovered, held;
	bool pressed = ButtonBehavior(Window, label, bb, hovered, held, GuiFlags_TabButton);

	if (pressed && !Window->Resizing && ui::ChildsAreStable(Window))
		*selected = num;

	RLColor textColor = RLColor{ (unsigned char)(90), (unsigned char)(90), (unsigned char)(90), (unsigned char)(g.MenuAlpha) };
	if (hovered)
		textColor = RLColor{ (unsigned char)(140), (unsigned char)(140), (unsigned char)(140), (unsigned char)(g.MenuAlpha) };
	if (*selected == num)
		textColor = RLColor{ (unsigned char)(210), (unsigned char)(210), (unsigned char)(210), (unsigned char)(g.MenuAlpha) };

	if (flags & GuiFlags_LegitTab)
		Render::Draw->Text(label, DrawPos.x, DrawPos.y, LEFT, FM_LegitTabIcons(), false, textColor);
	else
		Render::Draw->Text(label, DrawPos.x + Size.x / 2 - label_size.x / 2, DrawPos.y + Size.y / 2 - label_size.y / 2 - 1, LEFT, FM_TabIcons(), false, textColor);
}
// 绘制复选框
bool ui::Checkbox(const char* label, bool* v, bool special, bool* rightClicked) {
	GuiContext& g = *Gui_Ctx;
	GuiWindow* Window = GetCurrentWindow();
	Vec2 DrawPos = Window->CursorPos;
	
	// Use fixed item height for consistent alignment
	const float itemHeight = 14.0f;
	Rect total_bb = { DrawPos, Vec2(150, itemHeight) };

	RLColor EnabledColor = CMenu::get()->GetMenuColor();

	AddItemToWindow(Window, total_bb);

	bool hovered, held;
	bool pressed = ButtonBehavior(Window, label, total_bb, hovered, held, GuiFlags_CheckBox | GuiFlags_ReturnKeyReleased);

	if (pressed && PopUpsAreClosed(Window))
		*v = !*v;

	// Right-click: toggle the rightClicked bool persistently
	if (rightClicked && hovered && KeyReleased(VK_RBUTTON) && PopUpsAreClosed(Window))
		*rightClicked = !*rightClicked;

	// Center checkbox vertically within item height
	float checkboxY = DrawPos.y + (itemHeight - 8.0f) / 2.0f;
	
	if (*v)
		Render::Draw->Gradient(Vec2(DrawPos.x + 1, checkboxY - 2), Vec2(6, 6), CMenu::get()->GetMenuColor(), RLColor{ (unsigned char)((EnabledColor).r), (unsigned char)((EnabledColor).g), (unsigned char)((EnabledColor).b), (unsigned char)(std::clamp(180, 0, int((EnabledColor).a))) }, true);
	else
		if (hovered)
			Render::Draw->Gradient(Vec2(DrawPos.x + 1, checkboxY - 2), Vec2(6, 6), RLColor{ (unsigned char)(85), (unsigned char)(85), (unsigned char)(85), (unsigned char)(std::clamp(255, 0, g.MenuAlpha)) }, RLColor{ (unsigned char)(55), (unsigned char)(55), (unsigned char)(55), (unsigned char)(std::clamp(255, 0, g.MenuAlpha)) }, true);
		else
			Render::Draw->Gradient(Vec2(DrawPos.x + 1, checkboxY - 2), Vec2(6, 6), RLColor{ (unsigned char)(77), (unsigned char)(77), (unsigned char)(77), (unsigned char)(std::clamp(255, 0, g.MenuAlpha)) }, RLColor{ (unsigned char)(47), (unsigned char)(47), (unsigned char)(47), (unsigned char)(std::clamp(255, 0, g.MenuAlpha)) }, true);

	Render::Draw->Rect(Vec2(DrawPos.x, checkboxY - 2), Vec2(8, 8), 1, RLColor{ (unsigned char)(12), (unsigned char)(12), (unsigned char)(12), (unsigned char)(g.MenuAlpha) });
	
	// Align text baseline with checkbox center
	float textY = DrawPos.y + (itemHeight - 12.0f) / 2.0f;
	Render::Draw->Text(label, DrawPos.x + 20, textY - 2, LEFT, FM_Verdana(), false, special ? RLColor{ (unsigned char)(182), (unsigned char)(182), (unsigned char)(101), (unsigned char)(g.MenuAlpha) } : RLColor{ (unsigned char)(205), (unsigned char)(205), (unsigned char)(205), (unsigned char)(g.MenuAlpha) });
	
	return *v;
}
// 绘制按钮
bool ui::Button(const char* label, const Vec2& size) {
	GuiContext& g = *Gui_Ctx;
	GuiWindow* Window = GetCurrentWindow();
	Vec2 label_size = Render::Draw->GetTextSize(FM_Verdana(), label);
	Vec2 sizea = (size.x == 0 || size.y == 0) ? Vec2(std::clamp(Window->Size.x - 90, 61.f, 200.f), 25) : size;
	Rect bb = { Window->CursorPos + Vec2(20, 0), sizea };

	AddItemToWindow(Window, bb);

	bool hovered, held;
	bool pressed = ButtonBehavior(Window, label, bb, hovered, held, GuiFlags_ReturnKeyReleased);

	if (held)
		Render::Draw->Gradient(bb.Min, bb.Max, RLColor{ (unsigned char)(26), (unsigned char)(26), (unsigned char)(26), (unsigned char)(g.MenuAlpha) }, RLColor{ (unsigned char)(34), (unsigned char)(34), (unsigned char)(34), (unsigned char)(g.MenuAlpha) }, true);
	else if (hovered)
		Render::Draw->Gradient(bb.Min, bb.Max, RLColor{ (unsigned char)(40), (unsigned char)(40), (unsigned char)(40), (unsigned char)(g.MenuAlpha) }, RLColor{ (unsigned char)(32), (unsigned char)(32), (unsigned char)(32), (unsigned char)(g.MenuAlpha) }, true);
	else
		Render::Draw->Gradient(bb.Min, bb.Max, RLColor{ (unsigned char)(34), (unsigned char)(34), (unsigned char)(34), (unsigned char)(g.MenuAlpha) }, RLColor{ (unsigned char)(26), (unsigned char)(26), (unsigned char)(26), (unsigned char)(g.MenuAlpha) }, true);

	Render::Draw->Rect(bb.Min, bb.Max, 1, RLColor{ (unsigned char)(12), (unsigned char)(12), (unsigned char)(12), (unsigned char)(g.MenuAlpha) });
	Render::Draw->Rect(bb.Min + Vec2(1, 1), bb.Max - Vec2(2, 2), 1, RLColor{ (unsigned char)(50), (unsigned char)(50), (unsigned char)(50), (unsigned char)(g.MenuAlpha) });

	Vec2 TextPos = Vec2(bb.Min.x + (bb.Max.x / 2) - (label_size.x / 2), bb.Min.y + (bb.Max.y / 2) - (label_size.y / 2));

	Render::Draw->Text(label, std::clamp(TextPos.x + 1, bb.Min.x + 3.f, bb.Min.x + bb.Max.x), TextPos.y + 1, LEFT, FM_Verdana(), false, RLColor{ (unsigned char)(15), (unsigned char)(15), (unsigned char)(15), (unsigned char)(g.MenuAlpha) }, bb.Min + bb.Max - Vec2(5, 0));
	Render::Draw->Text(label, std::clamp(TextPos.x, bb.Min.x + 3.f, bb.Min.x + bb.Max.x), TextPos.y, LEFT, FM_Verdana(), false, RLColor{ (unsigned char)(205), (unsigned char)(205), (unsigned char)(205), (unsigned char)(g.MenuAlpha) }, bb.Min + bb.Max - Vec2(5, 0));
	return pressed;
}


template<typename T>
// 绘制滑块控件
void ui::Slider(const char* label, T* v, T v_min, T v_max, const char* format, GuiFlags flags, float scale, int remove) {
	GuiContext& g = *Gui_Ctx;
	GuiWindow* Window = GetCurrentWindow();
	Vec2 label_size = Render::Draw->GetTextSize(FM_Verdana(), label);
	char formatted_string[100];

	const float w = std::clamp(Window->Size.x - 90, 63.f, 202.f);
	Rect frame_bb = { Window->CursorPos - Vec2(-20 , 3), Vec2(w, label_size.y + 12) };
	Rect slider_bb = { frame_bb.Min + Vec2(0, label_size.y + 4), Vec2(frame_bb.Max.x, 6) };

	AddItemToWindow(Window, Rect(frame_bb.Min, frame_bb.Max));

	std::vector<RLColor> bg_color = { RLColor{ (unsigned char)(52), (unsigned char)(52), (unsigned char)(52), (unsigned char)(g.MenuAlpha) }, RLColor{ (unsigned char)(72), (unsigned char)(72), (unsigned char)(72), (unsigned char)(g.MenuAlpha) } };

	bool hovered, held;
	bool slider_hovered = false;;

	if (PopUpsAreClosed(Window)) {
		if (slider_hovered = SliderBehavior(label, slider_bb, v, &v_min, &v_max, flags))
			bg_color = { RLColor{ (unsigned char)(72), (unsigned char)(72), (unsigned char)(72), (unsigned char)(g.MenuAlpha) }, RLColor{ (unsigned char)(92), (unsigned char)(92), (unsigned char)(92), (unsigned char)(g.MenuAlpha) } };

		if (ButtonBehavior(Window, label, Rect(slider_bb.Min - Vec2(7, 0), Vec2(7, 7)), hovered, held, GuiFlags_IntSlider) || (slider_hovered && KeyPressed(VK_LEFT)))
			*v -= (float)*v - scale >= v_min ? scale : *v;
		if (hovered)
			bg_color = { RLColor{ (unsigned char)(72), (unsigned char)(72), (unsigned char)(72), (unsigned char)(g.MenuAlpha) }, RLColor{ (unsigned char)(92), (unsigned char)(92), (unsigned char)(92), (unsigned char)(g.MenuAlpha) } };

		if (ButtonBehavior(Window, label, Rect(slider_bb.Min + slider_bb.Max - Vec2(0, 7), Vec2(7, 7)), hovered, held, GuiFlags_IntSlider) || (slider_hovered && KeyPressed(VK_RIGHT)))
			*v += (float)*v + scale < v_max ? scale : v_max - *v;
		if (hovered)
			bg_color = { RLColor{ (unsigned char)(72), (unsigned char)(72), (unsigned char)(72), (unsigned char)(g.MenuAlpha) }, RLColor{ (unsigned char)(92), (unsigned char)(92), (unsigned char)(92), (unsigned char)(g.MenuAlpha) } };
	}
	const float rect_width = (static_cast<float>(*v) - v_min) / (v_max - v_min) * w - 1;

	if (!format && flags & GuiFlags_IntSlider)
		sprintf_s(formatted_string, "%d", (int)*v - remove);
	else if (!format && GuiFlags_FloatSlider)
		sprintf_s(formatted_string, "%f", (float)*v);
	else
		sprintf_s(formatted_string, format, T(*v) - remove);

	Vec2 value_width = Render::Draw->GetTextSize(FM_Verdana(), formatted_string);

	Render::Draw->Text(label, frame_bb.Min.x, frame_bb.Min.y, LEFT, FM_Verdana(), false, RLColor{ (unsigned char)(205), (unsigned char)(205), (unsigned char)(205), (unsigned char)(g.MenuAlpha) });

	Render::Draw->Gradient(slider_bb.Min + Vec2(0, 1), slider_bb.Max - Vec2(0, 1), bg_color[0], bg_color[1], true);

	Render::Draw->FilledRect(slider_bb.Min + Vec2(1, 1), Vec2(rect_width, slider_bb.Max.y), CMenu::get()->GetMenuColor());
	Render::Draw->Rect(slider_bb.Min, slider_bb.Max + Vec2(0, 1), 1, RLColor{ (unsigned char)(12), (unsigned char)(12), (unsigned char)(12), (unsigned char)(g.MenuAlpha) });
	Render::Draw->Gradient(slider_bb.Min + Vec2(1, 1), Vec2(rect_width, slider_bb.Max.y), RLColor{ (unsigned char)(0), (unsigned char)(0), (unsigned char)(0), (unsigned char)(0) }, RLColor{ (unsigned char)(0), (unsigned char)(0), (unsigned char)(0), (unsigned char)(std::clamp(120, 0, g.MenuAlpha)) }, true);

	Render::Draw->Text(formatted_string, slider_bb.Min.x + rect_width - value_width.x / 2, slider_bb.Min.y, LEFT, FM_Verdana(), true, RLColor{ (unsigned char)(255), (unsigned char)(255), (unsigned char)(255), (unsigned char)((std::min)(200, g.MenuAlpha)) });
}
// 绘制浮点数滑块控件
void ui::SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format, float scale) {
	return Slider(label, v, v_min, v_max, format, GuiFlags_FloatSlider, scale);
}
// 绘制整数滑块控件
void ui::SliderInt(const char* label, int* v, int v_min, int v_max, const char* format, int remove) {
	return Slider(label, v, v_min, v_max, format, GuiFlags_IntSlider, 1.f, remove);
}
// 绘制下拉选择框
bool ui::ComboSelectable(const char* label, bool selected, GuiFlags flags, const Vec2& size_arg) {
	GuiContext& g = *Gui_Ctx;
	GuiWindow* Window = GetCurrentWindow();
	Rect Framebb{ Window->CursorPos, Vec2(size_arg.x == 0 ? Window->Size.x - 2 : size_arg.x, size_arg.y == 0 ? 18 : size_arg.y) };

	bool hovered, held;
	bool pressed = ButtonBehavior(Window, label, Framebb, hovered, held, GuiFlags_Selectable | GuiFlags_ReturnKeyReleased);

	RLFont TextFont = selected || hovered ? FM_Verdana() : FM_Verdana();
	Vec2 label_size = Render::Draw->GetTextSize(TextFont, label);
	RLColor TextColor = selected ? CMenu::get()->GetMenuColor() : RLColor{ (unsigned char)(205), (unsigned char)(205), (unsigned char)(205), (unsigned char)(g.MenuAlpha) };

	AddItemToWindow(Window, Framebb, Window->Flags);

	if (hovered)
		DrawList::AddFilledRect(Framebb.Min, Framebb.Max, RLColor{ (unsigned char)(25), (unsigned char)(25), (unsigned char)(25), (unsigned char)(g.MenuAlpha) });

	DrawList::AddText(label, Framebb.Min.x + 10, Framebb.Min.y + (Framebb.Max.y / 2) - label_size.y / 2, TextColor, TextFont, false, Framebb.Min + Framebb.Max - Vec2(15, 0));

	return pressed;
}
// 绘制可选择项
bool ui::Selectable(const char* label, bool activated, const Vec2& size_arg) {
	GuiContext& g = *Gui_Ctx;
	GuiWindow* Window = GetCurrentWindow();
	Rect Framebb{ Window->CursorPos, Vec2(size_arg.x == 0 ? Window->Size.x - 2 : size_arg.x, size_arg.y == 0 ? 16 : size_arg.y) };

	// Clip hit-testing for listbox: reject clicks on items fully outside the visible area
	bool isListbox = (Window->Flags & GuiFlags_Listbox) != 0;
	if (isListbox) {
		float visTop = Window->Pos.y + 1;
		float visBot = Window->Pos.y + Window->Size.y - 1;
		if (Framebb.Min.y + Framebb.Max.y <= visTop || Framebb.Min.y >= visBot) {
			// Item is completely outside visible area — skip click, still advance cursor
			AddItemToWindow(Window, Framebb, Window->Flags);
			return false;
		}
	}

	bool hovered, held;
	bool pressed = ButtonBehavior(Window, label, Framebb, hovered, held, GuiFlags_Selectable);

	if (pressed)
		Window->SelectedItem = label;

	RLFont TextFont = Window->SelectedItem == label ? FM_Verdana() : FM_Verdana();
	Vec2 label_size = Render::Draw->GetTextSize(TextFont, label);
	RLColor TextColor = activated ? CMenu::get()->GetMenuColor() : RLColor{ (unsigned char)(205), (unsigned char)(205), (unsigned char)(205), (unsigned char)(g.MenuAlpha) };

	AddItemToWindow(Window, Framebb, Window->Flags);

	if (Window->SelectedItem == label)
		Render::Draw->FilledRect(Framebb.Min, Framebb.Max, RLColor{ (unsigned char)(25), (unsigned char)(25), (unsigned char)(25), (unsigned char)(g.MenuAlpha) });

	Render::Draw->Text(label, Framebb.Min.x + 10, Framebb.Min.y + (Framebb.Max.y / 2) - label_size.y / 2, LEFT, TextFont, false, TextColor);

	return pressed;
}
// 绘制下拉选择框
bool ui::BeginCombo(const char* label, const char* preview_value, int items, GuiFlags flags) {
	GuiContext& g = *Gui_Ctx;
	GuiWindow* Window = GetCurrentWindow();

	flags |= GuiFlags_PopUp | GuiFlags_ComboBox;

	Vec2 label_size = Render::Draw->GetTextSize(FM_Verdana(), label);
	Vec2 preview_size = Render::Draw->GetTextSize(FM_Verdana(), preview_value);

	Rect Fullbb = { Window->CursorPos + Vec2(20, - label_size.y / 3), label_size + Vec2(0, 4 + 20) };
	Rect Framebb = { Fullbb.Min + Vec2(0, label_size.y + 4), Vec2(std::clamp(Window->Size.x - 90, 63.f, 200.f), 20) };

	bool hovered, held;
	bool pressed = ButtonBehavior(Window, label, Framebb, hovered, held, GuiFlags_ComboBox | GuiFlags_ReturnKeyReleased);

	bool opened = false;

	AddItemToWindow(Window, Fullbb);

	Render::Draw->Text(label, Fullbb.Min.x, Fullbb.Min.y + 1, LEFT, FM_Verdana(), false, RLColor{ (unsigned char)(205), (unsigned char)(205), (unsigned char)(205), (unsigned char)(g.MenuAlpha) });

	if (hovered || opened)
		Render::Draw->Gradient(Framebb.Min + Vec2(1, 1), Framebb.Max - Vec2(2, 2), RLColor{ (unsigned char)(41), (unsigned char)(41), (unsigned char)(41), (unsigned char)(g.MenuAlpha) }, RLColor{ (unsigned char)(46), (unsigned char)(46), (unsigned char)(46), (unsigned char)(g.MenuAlpha) }, true);
	else
		Render::Draw->Gradient(Framebb.Min + Vec2(1, 1), Framebb.Max - Vec2(2, 2), RLColor{ (unsigned char)(31), (unsigned char)(31), (unsigned char)(31), (unsigned char)(g.MenuAlpha) }, RLColor{ (unsigned char)(36), (unsigned char)(36), (unsigned char)(36), (unsigned char)(g.MenuAlpha) }, true);

	Render::Draw->Rect(Framebb.Min, Framebb.Max, 1, RLColor{ (unsigned char)(12), (unsigned char)(12), (unsigned char)(12), (unsigned char)(g.MenuAlpha) });

	Render::Draw->Text(preview_value, Framebb.Min.x + 10, Framebb.Min.y + (Framebb.Max.y / 2) - preview_size.y / 2, LEFT, FM_Verdana(), false, RLColor{ (unsigned char)(157), (unsigned char)(157), (unsigned char)(157), (unsigned char)(g.MenuAlpha) }, Framebb.Min + Framebb.Max - Vec2(12 , 0));

	Render::Draw->Line(Framebb.Min + Vec2(Framebb.Max.x - 9, 7), Framebb.Min + Vec2(Framebb.Max.x - 4, 7), RLColor{ (unsigned char)(0), (unsigned char)(0), (unsigned char)(0), (unsigned char)(g.MenuAlpha) });
	Render::Draw->Triangle(Vec2((int)Framebb.Min.x, (int)Framebb.Min.y) + Vec2((int)Framebb.Max.x - 9, 8), Vec2((int)Framebb.Min.x, (int)Framebb.Min.y) + Vec2((int)Framebb.Max.x - 7, 11), Vec2((int)Framebb.Min.x, (int)Framebb.Min.y) + Vec2((int)Framebb.Max.x - 4, 8), RLColor{ (unsigned char)(157), (unsigned char)(157), (unsigned char)(157), (unsigned char)(g.MenuAlpha) });

	SetNextWindowPos(Fullbb.Min + Vec2(0, Fullbb.Max.y + 1));
	SetNextWindowSize(Vec2(Framebb.Max.x, (18 * items) + (items * 2)));

	Begin(label, flags);
	GuiWindow* Popup = GetCurrentWindow();
	Popup->ParentWindow = Window;

	if (!Popup->Init) {
		Window->PopUpWindows.push_back(Popup);
		Popup->Init = true;
	}

	Popup->CursorPos += Vec2(1, 1);

	opened = Popup->Opened;

	if (!Popup->Opened && hovered && !Window->ItemActive[label])
		Window->ItemActive[label] = true;
	else if (!Popup->Opened && !KeyDown(VK_LBUTTON) && Window->ItemActive[label])
		Window->ItemActive[label] = false;
	else if (Popup->Opened && IsInside(Framebb.Min.x, Framebb.Min.y, Framebb.Max.x, Framebb.Max.y + Popup->Size.y) && !Window->ItemActive[label])
		Window->ItemActive[label] = true;
	else if (Popup->Opened && !KeyDown(VK_LBUTTON) && Window->ItemActive[label])
		Window->ItemActive[label] = false;

	if (Popup->Opened && KeyPressed(VK_LBUTTON) && !IsInside(Framebb.Min.x, Framebb.Min.y, Framebb.Max.x, Framebb.Max.y + Popup->Size.y)) {
			Popup->Opened = false;
			return false;
	}

	if (pressed && PopUpsAreClosed(Window))
		Popup->Opened = true;
	else if (pressed && Popup->Opened)
		Popup->Opened = false;

	return Popup->Opened;
}
// 结束下拉选择框
void ui::EndCombo() {
	GuiWindow* PopUpWindow = GetCurrentWindow();
	
	SetCurrentWindow(PopUpWindow->ParentWindow);
}
// 绘制下拉选择框
bool ui::SingleSelect(const char* label, int* current_item, std::vector<const char*> items) {
	*current_item = std::clamp(*current_item, 0, int(items.size() - 1));

	static bool changed = false;

	if (ui::BeginCombo(label, items.at(*current_item), static_cast<int>(items.size()))) {

		for (size_t i = 0; i < items.size(); i++) {
			if (ui::ComboSelectable(items.at(i), *current_item == static_cast<int>(i), GuiFlags_SingleSelect))
				*current_item = static_cast<int>(i);
		}

		if (IsInside(GetWindowPos().x, GetWindowPos().y, GetWindowSize().x, GetWindowSize().y) && KeyReleased(VK_LBUTTON))
			GetCurrentWindow()->Opened = false;
	}

	ui::EndCombo();
	return true;
}
// 绘制下拉选择框
bool ui::MultiSelect(const char* label, std::unordered_map<int, bool>* data, std::vector<const char*> items) {
	std::unordered_map<int, bool> old_data = *data;

	std::string preview_str = "";

	for (auto const& it : *data) 
		if (it.second)
			preview_str = preview_str + items.at(it.first) + ", ";

	preview_str = preview_str.substr(0, preview_str.size() > 2 ? preview_str.size() - 2 : 0);

	if (ui::BeginCombo(label, preview_str.size() == 0 ? "-" : preview_str.c_str(), static_cast<int>(items.size())))
		for (size_t i = 0; i < items.size(); i++)
			if (ui::ComboSelectable(items.at(i), (*data)[static_cast<int>(i)]))
				(*data)[static_cast<int>(i)] = !(*data)[static_cast<int>(i)];

	ui::EndCombo();

	return old_data != *data;
}
// 绘制颜色选择器
bool ui::ColorPicker(const char* label, int col[4], GuiFlags flags) {
	GuiContext& g = *Gui_Ctx;
	GuiWindow* Window = GetCurrentWindow();

	flags |= GuiFlags_PopUp | GuiFlags_ColorPicker;

	Rect Fullbb = { Window->Pos.x + Window->Size.x - 41, Window->PevCursorPos.y , 17, 9 };

	bool hovered, held;
	bool pressed = ButtonBehavior(Window, label, Fullbb, hovered, held, GuiFlags_ColorPicker | GuiFlags_ReturnKeyReleased);

	// Per-label init state to avoid sharing across multiple color picker instances
	static std::unordered_map<std::string, bool> s_InitState;
	bool& init = s_InitState[std::string(label)];

	AddItemToWindow(Window, Fullbb, GuiFlags_ColorPicker);

	Render::Draw->Rect(Fullbb.Min, Fullbb.Max, 1, RLColor{ (unsigned char)(12), (unsigned char)(12), (unsigned char)(12), (unsigned char)(g.MenuAlpha) });
	Render::Draw->FilledRect(Fullbb.Min + Vec2(1, 1), Fullbb.Max - Vec2(2, 2), RLColor{ (unsigned char)(col[0]), (unsigned char)(col[1]), (unsigned char)(col[2]), (unsigned char)(g.MenuAlpha) });
	Render::Draw->Gradient(Fullbb.Min + Vec2(1, 1), Fullbb.Max - Vec2(2, 2), RLColor{ (unsigned char)(255), (unsigned char)(255), (unsigned char)(255), (unsigned char)(20) }, RLColor{ (unsigned char)(0), (unsigned char)(0), (unsigned char)(0), (unsigned char)(20) }, true);

	// Right-click context menu: copy/paste color via system clipboard
	static std::string s_contextLabel;
	static bool s_contextOpen = false;
	std::string ctxName = std::string(label) + "_ctx";

	if (hovered && KeyReleased(VK_RBUTTON)) {
		s_contextLabel = label;
		s_contextOpen = true;
	}

	if (s_contextOpen && s_contextLabel == label) {
		SetNextWindowPos(Fullbb.Min + Vec2(0, Fullbb.Max.y + 1));
		SetNextWindowSize(Vec2(48, 40));
		Begin(ctxName.c_str(), GuiFlags_PopUp | GuiFlags_NoResize | GuiFlags_NoMove);
		GuiWindow* ctxWnd = GetCurrentWindow();
		ctxWnd->ParentWindow = Window;
		ctxWnd->Opened = true;
		ctxWnd->CursorPos += Vec2(1, 1);

		if (ComboSelectable("复制", false, GuiFlags_ReturnKeyReleased)) {
			ClipboardUtils::CopyColor(col[0], col[1], col[2], col[3]);
			s_contextOpen = false;
		}
		bool hasClipboardText = ClipboardUtils::HasText();
		if (ComboSelectable("粘贴", false, hasClipboardText ? GuiFlags_ReturnKeyReleased : GuiFlags_None)) {
			ClipboardUtils::PasteColor(col);
			s_contextOpen = false;
		}
		if (!hasClipboardText) {
			// Gray out paste text when clipboard has no text
			Vec2 pasteSize = Render::Draw->GetTextSize(FM_Verdana(), "粘贴");
			Render::Draw->Text("粘贴", ctxWnd->Pos.x + 11, ctxWnd->Pos.y + 20 + (18 / 2) - pasteSize.y / 2, LEFT, FM_Verdana(), false, RLColor{ (unsigned char)(80), (unsigned char)(80), (unsigned char)(80), (unsigned char)(g.MenuAlpha) });
		}

		if (KeyPressed(VK_LBUTTON) && !IsInside(ctxWnd->Pos.x, ctxWnd->Pos.y, ctxWnd->Size.x, ctxWnd->Size.y))
			s_contextOpen = false;

		SetCurrentWindow(Window);
	}

	SetNextWindowPos(Fullbb.Min + Vec2(-1, Fullbb.Max.y + 1));
	SetNextWindowSize(Vec2(180, 175));

	Begin(label, flags);
	GuiWindow* PickerWindow = GetCurrentWindow();
	PickerWindow->ParentWindow = Window;

	if (!PickerWindow->Init) {
		Window->PopUpWindows.push_back(PickerWindow);
		PickerWindow->Init = true;
	}

	Rect ColorRect = { PickerWindow->Pos + Vec2(5, 5), Vec2(150, 150) };
	Rect AlphaRect = { PickerWindow->Pos + Vec2(5, 160), Vec2(150, 10) };
	Rect HueRect = { PickerWindow->Pos + Vec2(160, 5), Vec2(15, 150) };

	if (pressed)
		PickerWindow->Opened = init = !PickerWindow->Opened;

	// Click outside to close: use parent (main) window when available, otherwise current window
	GuiWindow* closeScope = Window->ParentWindow ? Window->ParentWindow : Window;
	if (KeyPressed(VK_LBUTTON) && IsInside(closeScope->Pos.x, closeScope->Pos.y, closeScope->Size.x, closeScope->Size.y)
	&& !IsInside(PickerWindow->Pos.x, PickerWindow->Pos.y, PickerWindow->Size.x, PickerWindow->Size.y)
	&& !IsInside(Fullbb.Min.x, Fullbb.Min.y, Fullbb.Max.x, Fullbb.Max.y)) {
		PickerWindow->Opened = false;
	}


	if (PickerWindow->Opened) {
		HSV ColHSV = ColorPickerBehavior(PickerWindow, ColorRect, AlphaRect, HueRect, col, init);
		init = false;  // Consume the reset flag immediately to avoid RGB->HSV roundtrip every frame
		CColor Topr = CColor::FromHSB(ColHSV.h, 1.f, 1.f);

		Vec2 ColorPos = { std::clamp(ColorRect.Min.x + int(std::roundf(ColHSV.s * ColorRect.Max.x)), ColorRect.Min.x, ColorRect.Min.x + ColorRect.Max.x), std::clamp(ColorRect.Min.y + int((1.f - ColHSV.v) * ColorRect.Max.y), ColorRect.Min.y, ColorRect.Min.y + ColorRect.Max.y) };
		Vec2 HuePos = { HueRect.Min.x, std::clamp(HueRect.Min.y + int((1.f - ColHSV.h) * HueRect.Max.y), HueRect.Min.y, HueRect.Min.y + HueRect.Max.y) };
		Vec2 AlphaPos = { std::clamp(AlphaRect.Min.x + int(AlphaRect.Max.x * (ColHSV.a / 255.f)), AlphaRect.Min.x, AlphaRect.Min.x + AlphaRect.Max.x), AlphaRect.Min.y };

		// Color Picker
		DrawList::AddGradient(ColorRect.Min, ColorRect.Max, RLColor{ (unsigned char)(255), (unsigned char)(255), (unsigned char)(255), (unsigned char)(g.MenuAlpha) }, RLColor{ (unsigned char)(Topr.r()), (unsigned char)(Topr.g()), (unsigned char)(Topr.b()), (unsigned char)(255) }, false, false);
		DrawList::AddGradient(ColorRect.Min, ColorRect.Max, RLColor{ (unsigned char)(0), (unsigned char)(0), (unsigned char)(0), (unsigned char)(std::clamp(0, 0, g.MenuAlpha)) }, RLColor{ (unsigned char)(0), (unsigned char)(0), (unsigned char)(0), (unsigned char)(g.MenuAlpha) }, true, false);
		DrawList::AddRect(ColorRect.Min - Vec2(1, 1), Vec2(152, 152), RLColor{ (unsigned char)(12), (unsigned char)(12), (unsigned char)(12), (unsigned char)(g.MenuAlpha) });

		//Alpha Bar
		DrawList::AddRect(AlphaRect.Min - Vec2(1, 1), Vec2(152, 12), RLColor{ (unsigned char)(12), (unsigned char)(12), (unsigned char)(12), (unsigned char)(g.MenuAlpha) });
		DrawList::AddFilledRect(AlphaRect.Min, AlphaRect.Max, RLColor{ (unsigned char)(col[0]), (unsigned char)(col[1]), (unsigned char)(col[2]), (unsigned char)(std::min(col[3], g.MenuAlpha)) });

		//Hue Bar
		DrawList::AddRect(HueRect.Min - Vec2(1, 1), Vec2(17, 152), RLColor{ (unsigned char)(12), (unsigned char)(12), (unsigned char)(12), (unsigned char)(g.MenuAlpha) });
		const RLColor hue_colors[6 + 1] = { RLColor{ (unsigned char)(220), (unsigned char)(30), (unsigned char)(34), (unsigned char)(255) }, RLColor{ (unsigned char)(220), (unsigned char)(30), (unsigned char)(216), (unsigned char)(255) }, RLColor{ (unsigned char)(30), (unsigned char)(34), (unsigned char)(220), (unsigned char)(255) }, RLColor{ (unsigned char)(30), (unsigned char)(220), (unsigned char)(216), (unsigned char)(255) }, RLColor{ (unsigned char)(34), (unsigned char)(219), (unsigned char)(30), (unsigned char)(255) }, RLColor{ (unsigned char)(220), (unsigned char)(187), (unsigned char)(30), (unsigned char)(255) }, RLColor{ (unsigned char)(220), (unsigned char)(33), (unsigned char)(30), (unsigned char)(255) } };
		for (int i = 0; i < 6; ++i)
			DrawList::AddGradient(PickerWindow->Pos + Vec2(160, 5 + (25 * i)), Vec2(15, 25), hue_colors[i], hue_colors[i + 1], true);

		//Picker Dot
		DrawList::AddRect(ColorPos - Vec2(2, 2), Vec2(4, 4), RLColor{ (unsigned char)(12), (unsigned char)(12), (unsigned char)(12), (unsigned char)(g.MenuAlpha) });
		DrawList::AddRect(ColorPos - Vec2(1, 1), Vec2(2, 2), RLColor{ (unsigned char)(255), (unsigned char)(255), (unsigned char)(255), (unsigned char)(std::clamp(127, 0, g.MenuAlpha)) });

		//Alpha Bar
		DrawList::AddRect(AlphaPos + Vec2(0, 0), Vec2(4, 10), RLColor{ (unsigned char)(12), (unsigned char)(12), (unsigned char)(12), (unsigned char)(std::clamp(255, 0, g.MenuAlpha)) });
		DrawList::AddRect(AlphaPos + Vec2(1, 1), Vec2(2, 8), RLColor{ (unsigned char)(255), (unsigned char)(255), (unsigned char)(255), (unsigned char)(std::clamp(140, 0, g.MenuAlpha)) });

		//Hue Indicator
		DrawList::AddRect(HuePos - Vec2(0, 2), Vec2(15, 4), RLColor{ (unsigned char)(12), (unsigned char)(12), (unsigned char)(12), (unsigned char)(std::clamp(180, 0, g.MenuAlpha)) });
		DrawList::AddRect(HuePos - Vec2(-1, 1), Vec2(13, 2), RLColor{ (unsigned char)(255), (unsigned char)(255), (unsigned char)(255), (unsigned char)(std::clamp(140, 0, g.MenuAlpha)) });

		CColor outcolor = CColor::FromHSB(ColHSV.h, ColHSV.s, ColHSV.v, ColHSV.a);
		col[0] = outcolor.r();
		col[1] = outcolor.g();
		col[2] = outcolor.b();
		col[3] = outcolor.a();
	}

	End();
	SetCurrentWindow(PickerWindow->ParentWindow);

	return true;
}
// 绘制键绑定绑定器
bool ui::KeyBind(const char* id, int* current_key, int* key_style, GuiFlags flags) {
	GuiContext& g = *Gui_Ctx;
	GuiWindow* Window = GetCurrentWindow();
	bool edit_requested = Window->ItemActive[id];

	Vec2 TextSize = Render::Draw->GetTextSize(FM_SmallFont(), keys[*current_key]);

	// Right-aligned: text occupies [textRight-TextSize, textRight]
	float textRight = Window->Pos.x + Window->Size.x - 40.0f;
	Rect Fullbb = { textRight - TextSize.x, Window->PevCursorPos.y, TextSize.x, TextSize.y };

	bool hovered, held;
	bool pressed = ButtonBehavior(Window, "KeyBind", Fullbb, hovered, held, GuiFlags_ReturnKeyReleased);

	if (pressed)
		Window->ItemActive[id] = true;

	if (edit_requested) {
		g.IsBindingKey = true; // prevent overlay from toggling menu during keybind
		for (int i = 7; i < 166; i++) { // start from 7 to skip mouse buttons (VK_LBUTTON=1, VK_RBUTTON=2, VK_MBUTTON=4, VK_XBUTTON1/2)
			if (g.KeyState[i] && !g.PrevKeyState[i]) {
				*current_key = i == VK_ESCAPE ? 0 : i;
				Window->ItemActive[id] = false;
				break;
			}
		}
	}

	RLColor TextColor = edit_requested ? RLColor{255, 0, 0, (unsigned char)g.MenuAlpha} : (hovered ? RLColor{141, 141, 141, (unsigned char)g.MenuAlpha} : RLColor{114, 114, 114, (unsigned char)g.MenuAlpha});
	Render::Draw->Text(keys[*current_key], textRight, Fullbb.Min.y, RIGHT, FM_SmallFont(), true, TextColor);

	SetNextWindowPos(Vec2(Fullbb.Min.x - 109, Fullbb.Min.y - 2));
	SetNextWindowSize(Vec2(100, 80));

	Begin(id, GuiFlags_PopUp);
	GuiWindow* Popup = GetCurrentWindow();
	Popup->ParentWindow = Window;

	if (!Popup->Init) {
		Window->PopUpWindows.push_back(Popup);
		Popup->Init = true;
	}
	Popup->CursorPos += Vec2(1, 1);

	if (hovered && KeyReleased(VK_RBUTTON) && !(flags & GuiFlags_NoKeyBindMenu))
		Popup->Opened = !Popup->Opened;

	if (Popup->Opened && KeyPressed(VK_LBUTTON) && !IsInside(GetWindowPos().x, GetWindowPos().y, GetWindowSize().x, GetWindowSize().y) && !IsInside(Fullbb.Min.x, Fullbb.Min.y, Fullbb.Max.x, Fullbb.Max.y))
		Popup->Opened = false;

	if (Popup->Opened) {
		if (ComboSelectable("Always on", *key_style == 0 ? true : false))
			*key_style = 0;
		else if (ComboSelectable("On hotkey", *key_style == 1 ? true : false))
			*key_style = 1;
		else if (ComboSelectable("Toggle", *key_style == 2 ? true : false))
			*key_style = 2;
		else if (ComboSelectable("Off hotkey", *key_style == 3 ? true : false))
			*key_style = 3;

		if (IsInside(GetWindowPos().x, GetWindowPos().y, GetWindowSize().x, GetWindowSize().y) && KeyReleased(VK_LBUTTON))
			Popup->Opened = false;
	}

	SetCurrentWindow(Window);

	return !edit_requested;
}
// 绘制多键组合绑定器
bool ui::MultiKeyBind(const char* label, int* keystyle, GuiFlags flags) {
	GuiContext& g = *Gui_Ctx;
	GuiWindow* Window = GetCurrentWindow();
	bool edit_requested = Window->ItemActive[label];

	std::string cfgKey = std::string(label) + "_bind";
	std::string& cached = GamesenseMenuFramework::Globals::MultiKeyCache(cfgKey);

	// Init cache from config on first read
	if (cached.empty()) {
		const char* src = CConfig::get()->s[cfgKey];
		if (src && src[0])
			cached = src;
	}

	// Build display string from cached VK codes
	std::string displayStr = "[-]";
	if (!cached.empty()) {
		displayStr.clear();
		const char* p = cached.c_str();
		while (*p) {
			int vk = atoi(p);
			if (vk > 0 && vk < 166)
				displayStr += keys[vk];
			const char* comma = strchr(p, ',');
			if (!comma) break;
			displayStr += "+";
			p = comma + 1;
		}
	}
	if (displayStr.empty()) displayStr = "[-]";

	// Per-session captured keys (static so survives across frames while binding)
	static std::vector<int> s_capturedKeys;
	static bool s_wasEditRequested = false;

	if (edit_requested) {
		g.IsBindingKey = true;

		// On first frame of binding, clear any residual captured keys
		if (!s_wasEditRequested) {
			s_capturedKeys.clear();
		}
		s_wasEditRequested = true;

		// ESC cancels without clearing the binding
		if (g.KeyState[VK_ESCAPE] && !g.PrevKeyState[VK_ESCAPE]) {
			Window->ItemActive[label] = false;
			s_capturedKeys.clear();
		}
		else {
			// Collect currently held keys via g.KeyState[] (skip mouse 1-6, skip generic modifier VKs 16-18)
			std::vector<int> heldKeys;
			for (int i = 7; i < 166; i++) {
				// VK_SHIFT=16, VK_CONTROL=17, VK_MENU=18 are generic; left/right VKs 160-165 provide the same info
				if (i == 16 || i == 17 || i == 18) continue;
				if (g.KeyState[i])
					heldKeys.push_back(i);
			}

			if (!heldKeys.empty()) {
				// Union: only add keys not already captured (never shrink on partial release)
				for (int vk : heldKeys) {
					if (std::find(s_capturedKeys.begin(), s_capturedKeys.end(), vk) == s_capturedKeys.end())
						s_capturedKeys.push_back(vk);
				}
			}
			else if (!s_capturedKeys.empty()) {
				// All released — commit
				std::string keyStr;
				for (size_t k = 0; k < s_capturedKeys.size(); k++) {
					if (k > 0) keyStr += ",";
					keyStr += std::to_string(s_capturedKeys[k]);
				}
				cached = keyStr;
				// Sync cache back to config s map for persistence
				auto it = CConfig::get()->s.find(cfgKey);
				if (it != CConfig::get()->s.end())
					strncpy_s(it->second, keyStr.c_str(), 254);
				*keystyle = 4;
				Window->ItemActive[label] = false;
				s_capturedKeys.clear();
			}
		}
	}
	else {
		s_wasEditRequested = false;
	}

	// Show live preview / committed display
	if (edit_requested && !s_capturedKeys.empty()) {
		displayStr.clear();
		for (size_t k = 0; k < s_capturedKeys.size(); k++) {
			displayStr += keys[s_capturedKeys[k]];
			if (k + 1 < s_capturedKeys.size()) displayStr += "+";
		}
	}

	// Final text layout — computed after displayStr is fully settled
	Vec2 TextSize = Render::Draw->GetTextSize(FM_SmallFont(), displayStr.c_str());

	// Right-aligned anchor: text occupies [textRight-TextSize, textRight]
	Rect Fullbb = { Window->Pos.x + Window->Size.x - TextSize.x - 25.0f, Window->PevCursorPos.y, TextSize.x, TextSize.y };

	bool hovered, held;
	bool pressed = ButtonBehavior(Window, "MultiKeyBind", Fullbb, hovered, held, GuiFlags_ReturnKeyReleased);

	if (pressed && !edit_requested)
		Window->ItemActive[label] = true;

	RLColor TextColor = edit_requested
		? RLColor{255, 0, 0, (unsigned char)g.MenuAlpha}
		: (hovered ? RLColor{181, 181, 181, (unsigned char)g.MenuAlpha}
				   : RLColor{114, 114, 114, (unsigned char)g.MenuAlpha});

	Render::Draw->Text(displayStr.c_str(), Fullbb.Min.x, Fullbb.Min.y, RIGHT, FM_SmallFont(), true, TextColor);
	return !edit_requested;
}
// 绘制标签
void ui::Label(const char* label, bool special, GuiFlags flags) {
	GuiContext& g = *Gui_Ctx;
	GuiWindow* Window = GetCurrentWindow();
	
	Vec2 label_size = Render::Draw->GetTextSize(FM_Verdana(), label);
	Rect bb = { Window->CursorPos + Vec2(20, -3),  Vec2(label_size.x, label_size.y)};

	AddItemToWindow(Window, bb, GuiFlags_Label);
	
	Render::Draw->Text(label, bb.Min.x, bb.Min.y, LEFT, FM_Verdana(), false, special ? RLColor{ (unsigned char)(182), (unsigned char)(182), (unsigned char)(101), (unsigned char)(g.MenuAlpha) } : RLColor{ (unsigned char)(205), (unsigned char)(205), (unsigned char)(205), (unsigned char)(g.MenuAlpha) });
}
// 绘制列表框
bool ui::BeginListbox(const char* id, const Vec2 Size, GuiFlags flags) {
	GuiWindow* Window = GetCurrentWindow();
	Rect Fullbb = {Window->CursorPos + Vec2(20, 0), Vec2(std::clamp(Window->Size.x - 90, 64.f, 200.f), 126.f)};

	flags |= GuiFlags_Listbox | GuiFlags_NoResize | GuiFlags_NoMove;

	AddItemToWindow(Window, Fullbb);

	SetNextWindowPos(Fullbb.Min);
	SetNextWindowSize(Fullbb.Max);

	Begin(id, flags);
	GuiWindow* ListBoxWnd = GetCurrentWindow();
	ListBoxWnd->ParentWindow = Window;
	ListBoxWnd->CursorPos += Vec2(1, 1);

	// Enable scissor clipping
	float s = Gui_Ctx->dpiScale;
	int sx = (int)ListBoxWnd->Pos.x + 1;
	int sy = (int)ListBoxWnd->Pos.y + 1;
	int sw = (int)ListBoxWnd->Size.x - 2;
	int sh = (int)ListBoxWnd->Size.y - 2;
	if (sw < 0) sw = 0;
	if (sh < 0) sh = 0;
	RLBeginScissorMode(sx, sy, sw, sh);

	return true;
}
// 结束列表框
void ui::EndListbox() {
	GuiContext& g = *Gui_Ctx;
	GuiWindow* ListBoxWnd = GetCurrentWindow();

	ListBoxWnd->CursorPos.y += 8 * g.dpiScale;

	RLEndScissorMode();

	// Scroll handling
	if (ListBoxWnd->PrevCursorPos.y > ListBoxWnd->Pos.y + ListBoxWnd->Size.y && (ListBoxWnd->ScrollRatio >= 0.f || (!ListBoxWnd->ParentWindow->Dragging || !ChildsAreStable(ListBoxWnd->ParentWindow)))) {
		if (ListBoxWnd->ScrollRatio == -1.f)
			ListBoxWnd->ScrollRatio = 0.f;

		int scroll_height = (int)ListBoxWnd->Size.y / ((ListBoxWnd->PrevCursorPos.y - ListBoxWnd->Pos.y) / ListBoxWnd->Size.y);
		int offset = (int)((ListBoxWnd->Size.y - scroll_height) * ListBoxWnd->ScrollRatio);

		Render::Draw->FilledRect(Vec2(ListBoxWnd->Pos.x + ListBoxWnd->Size.x - 7, ListBoxWnd->Pos.y + 1), Vec2(6, ListBoxWnd->Size.y - 2), RLColor{ (unsigned char)(40), (unsigned char)(40), (unsigned char)(40), (unsigned char)(g.MenuAlpha) });
		Render::Draw->FilledRect(Vec2(ListBoxWnd->Pos.x + ListBoxWnd->Size.x - 6, ListBoxWnd->Pos.y + 3 + offset), Vec2(4, scroll_height - 6), RLColor{ (unsigned char)(65), (unsigned char)(65), (unsigned char)(65), (unsigned char)(g.MenuAlpha) });

		if (IsInside(ListBoxWnd->Pos.x, ListBoxWnd->Pos.y, ListBoxWnd->Size.x, ListBoxWnd->Size.y))
			ListBoxWnd->ScrollRatio = std::clamp(ListBoxWnd->ScrollRatio - g.MouseWheel * (20.f / ((int)ListBoxWnd->PrevCursorPos.y - (int)((int)ListBoxWnd->Pos.y + (int)ListBoxWnd->Size.y))), 0.f, 1.f);
	} else {
		ListBoxWnd->ScrollRatio = -1.f;
	}

	int offset = (int)ListBoxWnd->PrevCursorPos.y - (int)((int)ListBoxWnd->Pos.y + (int)ListBoxWnd->Size.y);
	ListBoxWnd->CursorPos.y += !(ListBoxWnd->PrevCursorPos.y > (int)ListBoxWnd->Pos.y + (int)ListBoxWnd->Size.y) ? 0 : (int)(offset * ListBoxWnd->ScrollRatio);
	ListBoxWnd->PrevCursorPos = ListBoxWnd->CursorPos;

	SetCurrentWindow(ListBoxWnd->ParentWindow);
}
// 绘制输入文本框
void ui::InputText(const char* id, char* buffer, GuiFlags flags) {
	GuiContext& g = *Gui_Ctx;
	GuiWindow* Window = GetCurrentWindow();

	Rect Framebb = { Window->CursorPos + Vec2(20, 0), Vec2(std::clamp(Window->Size.x - 90, 63.f, 200.f), 20) };
	
	AddItemToWindow(Window, Framebb);
	
	static const char* selected_id = "";

	bool hovered, held;
	bool pressed = ButtonBehavior(Window, id, Framebb, hovered, held, flags);

	if (pressed) {
		selected_id = id;
		g.AwaitingInput = true;
	}	
	else if (!hovered && selected_id && KeyPressed(VK_LBUTTON)) {
		selected_id = "";
		g.AwaitingInput = false;
		g.LastInput = 0;
	}

	bool is_selected = selected_id == id;

	if (is_selected) {
		for (int i = 0x20; i <= 0x5A; i++) {
			if ((i == VK_SPACE || i >= 0x30) && /*((g.LastInput + 1) < std::time(0) ? (KeyDown(i) && Misc::Utilities->GetInterval(0.05f)) : KeyPressed(i))*/KeyPressed(i)) {

				char c[2] = { char(MapVirtualKeyA(i, 2)), 0 };

				if (i > 0x3A)
					c[0] += (KeyDown(VK_SHIFT) ? 0 : 32);
				
				if (strlen(buffer) < 63)
					strcat_s(buffer, 64, (char*)c);

				if (g.LastInput == 0)
					g.LastInput = std::time(0);

				break;
			}
		}

		if (KeyPressed(VK_BACK) && strlen(buffer) > 0)
			buffer[strlen(buffer) - 1] = '\0';
	}

	const int colors[3] = { 12, 50, 16 };

	RLColor text_col = is_selected ? CMenu::get()->GetMenuColor() : RLColor{ (unsigned char)(205), (unsigned char)(205), (unsigned char)(205), (unsigned char)(g.MenuAlpha) };
	
	for (int i = 0; i < 3; i++)
		Render::Draw->Rect(Framebb.Min + Vec2(i, i), Framebb.Max - Vec2(i * 2, i * 2), 1, RLColor{ (unsigned char)(colors[i]), (unsigned char)(colors[i]), (unsigned char)(colors[i]), (unsigned char)(g.MenuAlpha) });

	std::string out_str = std::string(buffer) + '_';
	
	Vec2 label_size = Render::Draw->GetTextSize(FM_Verdana(), out_str.c_str());
	Render::Draw->Text(out_str.c_str(), Framebb.Min.x + 5, Framebb.Min.y + ((Framebb.Max.y / 2) - label_size.y / 2), LEFT, FM_Verdana(), false, text_col, Framebb.Min + Framebb.Max - Vec2(4, 0));
}
