1141 lines
25 KiB
C++
1141 lines
25 KiB
C++
#include "ui/dl_ui_manager.h"
|
||
|
||
#ifndef DL_DISABLE_RENDER
|
||
#include "io/dl_file.h"
|
||
#include "base/dl_string.h"
|
||
#include "render/dl_graphics.h"
|
||
#include "system/dl_system.h"
|
||
|
||
namespace dl::UI
|
||
{
|
||
|
||
UI::Text* Manager::CreateText(std::string_view name)
|
||
{
|
||
auto iter = _allText.find(std::string{ name });
|
||
if (iter == _allText.end())
|
||
{
|
||
log_err("UI::Text不存在,请使用Register注册:{}", name);
|
||
return UI::Text::Create(g_factory->CreateTextDefault());
|
||
}
|
||
return iter->second->Clone();
|
||
}
|
||
|
||
|
||
gcText Manager::CreateTextOnly(std::string_view name)
|
||
{
|
||
auto iter = _allText.find(std::string{ name });
|
||
if (iter == _allText.end())
|
||
{
|
||
log_err("UI::Text不存在,请使用Register注册:{}", name);
|
||
return g_factory->CreateTextDefault();
|
||
}
|
||
return g_factory->CloneText(iter->second->GetText());
|
||
}
|
||
|
||
UI::ButtonSprite* Manager::CreateButtonSprite(std::string_view name)
|
||
{
|
||
auto iter = _allBtnSprite.find(std::string{ name });
|
||
if (iter == _allBtnSprite.end())
|
||
{
|
||
log_err("ButtonSprite不存在,请使用Register注册:{}", name);
|
||
return CreateButtonSpriteDefault();
|
||
}
|
||
return iter->second->Clone();
|
||
}
|
||
|
||
Background* Manager::CreateBackground(std::string_view name)
|
||
{
|
||
auto iter = _allBackground.find(std::string{ name });
|
||
if (iter == _allBackground.end())
|
||
{
|
||
log_err("Background不存在,请使用Register注册:{}", name);
|
||
return CreateBackgroundDefault();
|
||
}
|
||
return iter->second->Clone();
|
||
}
|
||
|
||
dl::Locator::SL Manager::CreateLocator(std::string_view name)
|
||
{
|
||
auto iter = _allLocator.find(std::string{ name });
|
||
if (iter == _allLocator.end())
|
||
{
|
||
log_err("Locator不存在,请使用Register注册:{}", name);
|
||
return {};
|
||
}
|
||
return iter->second;
|
||
}
|
||
|
||
dl::UI::ListBox* Manager::CreateListBox(std::string_view name)
|
||
{
|
||
auto iter = _allListBox.find(std::string{ name });
|
||
if (iter == _allListBox.end())
|
||
{
|
||
log_err("ListBox不存在,请使用Register注册:{}", name);
|
||
return {};
|
||
}
|
||
return iter->second->Clone();
|
||
}
|
||
|
||
dl::UI::Text* Manager::CreateTextDefault()
|
||
{
|
||
return UI::Text::Create(g_factory->CreateTextDefault());
|
||
}
|
||
|
||
|
||
UI::ButtonSprite* Manager::CreateButtonSpriteDefault(ButtonStyle style)
|
||
{
|
||
//34/55 约等于 0.618
|
||
Position size;
|
||
switch (style)
|
||
{
|
||
case ButtonStyle::SMALL:
|
||
size = Math::CreatePositionByRatioGoldW(_arrSizeType[SizeType::SMALL]);
|
||
break;
|
||
case ButtonStyle::NORMAL:
|
||
size = Math::CreatePositionByRatioGoldW(_arrSizeType[SizeType::NORMAL]);
|
||
break;
|
||
case ButtonStyle::LARGE:
|
||
size = Math::CreatePositionByRatioGoldW(_arrSizeType[SizeType::LARGE]);
|
||
break;
|
||
case ButtonStyle::BOX:
|
||
size = { 30, 30 };
|
||
break;
|
||
case ButtonStyle::CLOSE:
|
||
size = { 24, 24 };
|
||
break;
|
||
case ButtonStyle::LONG:
|
||
size = { _arrSizeType[SizeType::LONG], 20 };
|
||
break;
|
||
case ButtonStyle::SWITCH:
|
||
size = { 18, 18 };
|
||
break;
|
||
default:
|
||
assert(0);
|
||
break;
|
||
}
|
||
|
||
std::vector<gcSprite> mul_spr;
|
||
mul_spr.resize(3);
|
||
for (size_t i = 0; i < 3; ++i)
|
||
{
|
||
mul_spr[i] = g_factory->CreateSpriteDefault();
|
||
mul_spr[i]->SetQuad(createQuad(size, false));
|
||
}
|
||
//
|
||
|
||
ButtonSprite* ret;
|
||
|
||
if (style == ButtonStyle::SWITCH)
|
||
{
|
||
mul_spr[0]->SetColor(ColorDef::GRAY_DARK);
|
||
mul_spr[1]->SetColor(ColorDef::WHITE);
|
||
mul_spr[2]->SetColor(ColorDef::GRAY_LIGHT);
|
||
ret = ButtonSprite::Create(mul_spr);
|
||
ret->SetMode(ButtonMode::SWITCH);
|
||
ret->AddText(g_factory->CreateTextDefault(),
|
||
toVector(ColorDef::BLACK, 5),
|
||
toVector(Position{40, 0}, 5));
|
||
ret->SetTextAlign(Align::LC);
|
||
|
||
ret->SetCustomRender([](Button* btn) {
|
||
// 描边
|
||
g_gfx->SetCoor(btn->GetCoor());
|
||
g_gfx->SetColor(ColorDef::BLACK);
|
||
g_gfx->Rectangle2D({}, btn->GetSize());
|
||
g_gfx->SetOrder(btn->GetOrder(-1));
|
||
//
|
||
Position size = btn->GetSize();
|
||
if (btn->IsSelect())
|
||
{
|
||
g_gfx->SetColor(ColorDef::GREEN_DARK);
|
||
g_gfx->StrokeLine({}, { size.w * 0.5f, size.h }, 2);
|
||
g_gfx->StrokeLine({ size.w * 0.5f, size.h } ,{ size.w , 0}, 2);
|
||
}
|
||
else
|
||
{
|
||
g_gfx->SetColor(ColorDef::RED);
|
||
g_gfx->StrokeLine({}, { size.w, size.h }, 2);
|
||
g_gfx->StrokeLine({ size.w, 0 }, { 0 , size.h }, 2);
|
||
}
|
||
});
|
||
}
|
||
else
|
||
{
|
||
mul_spr[0]->SetColor(ColorDef::GRAY_LIGHT);
|
||
mul_spr[1]->SetColor(ColorDef::WHITE);
|
||
mul_spr[2]->SetColor(ColorDef::GRAY);
|
||
ret = ButtonSprite::Create(mul_spr);
|
||
ret->AddTextDefault();
|
||
|
||
if (style != ButtonStyle::CLOSE)
|
||
{
|
||
ret->SetCustomRender([](Button* btn) {
|
||
Position size = btn->GetSize();
|
||
// 描边
|
||
g_gfx->SetCoor(btn->GetCoor());
|
||
g_gfx->SetColor(ColorDef::BLACK);
|
||
g_gfx->SetOrder(btn->GetOrder(-1));
|
||
|
||
g_gfx->Rectangle2D({}, size);
|
||
// 投影
|
||
if (!btn->IsDown())
|
||
{
|
||
g_gfx->SetOrder(btn->GetOrder(0));
|
||
g_gfx->Line2D({ size.w + 1, 0 }, { size.w + 1, size.h + 1 });
|
||
g_gfx->Line2D({ 1, size.h + 1 }, { size.w + 1, size.h + 1 });
|
||
}
|
||
else
|
||
{
|
||
g_gfx->Line2D({ 1, 1 }, { size.w, 1 });
|
||
g_gfx->Line2D({ 1, 1 }, { 1, size.h });
|
||
}
|
||
});
|
||
}
|
||
else
|
||
{
|
||
ret->SetCustomRender([](Button* btn) {
|
||
Position size = btn->GetSize();
|
||
// 描边
|
||
g_gfx->SetCoor(btn->GetCoor());
|
||
g_gfx->SetColor(ColorDef::BLACK);
|
||
g_gfx->SetOrder(btn->GetOrder(-1));
|
||
|
||
g_gfx->Rectangle2D({}, size);
|
||
// 投影
|
||
if (!btn->IsDown())
|
||
{
|
||
g_gfx->SetOrder(btn->GetOrder(0));
|
||
g_gfx->Line2D({ size.w + 1, 0 }, { size.w + 1, size.h + 1 });
|
||
g_gfx->Line2D({ 1, size.h + 1 }, { size.w + 1, size.h + 1 });
|
||
}
|
||
// 叉
|
||
g_gfx->SetOrder(btn->GetOrder(-1));
|
||
g_gfx->SetColor(ColorDef::GRAY_DARK);
|
||
g_gfx->StrokeLine(
|
||
{ size.w * 0.25f, size.h * 0.25f },
|
||
{ size.w * 0.75f, size.h * 0.75f }, 2);
|
||
g_gfx->StrokeLine(
|
||
{ size.w * 0.75f, size.h * 0.25f },
|
||
{ size.w * 0.25f , size.h * 0.75f }, 2);
|
||
});
|
||
}
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
Background* Manager::CreateBackgroundDefault()
|
||
{
|
||
Background* ret = Background::Create();
|
||
gcSprite spr = g_factory->CreateSpriteDefault();
|
||
spr->SetColor(ColorDef::GRAY);
|
||
ret->Set(spr);
|
||
ret->SetCustomRender([](Background* bg) {
|
||
Position size = bg->GetSize();
|
||
// 描边
|
||
g_gfx->SetCoor(bg->GetCoor());
|
||
g_gfx->SetColor(ColorDef::GREEN);
|
||
g_gfx->SetOrder(bg->GetOrder(-1));
|
||
|
||
g_gfx->Rectangle2D({}, size);
|
||
// 投影
|
||
if (true)
|
||
{
|
||
g_gfx->SetColor(createColor(ColorDef::BLACK, 0.5f));
|
||
g_gfx->SetOrder(bg->GetOrder(0));
|
||
g_gfx->Line2D({ size.w + 1, 0 }, { size.w + 1, size.h + 1 });
|
||
g_gfx->Line2D({ 1, size.h + 1 }, { size.w + 1, size.h + 1 });
|
||
}
|
||
});
|
||
return ret;
|
||
}
|
||
|
||
ListBox* Manager::CreateListBoxDefault(bool add_text)
|
||
{
|
||
// item
|
||
Panel* item = g_ui->CreatePanel();
|
||
item->SetLocator(createLocatorZero());
|
||
|
||
{
|
||
ButtonSprite* btn = g_ui->CreateButtonSpriteDefault();
|
||
btn->SetMode(ButtonMode::RADIO);
|
||
btn->SetSpriteQuad(ButtonState::MAX_NUM, createQuad(
|
||
Size{ (unsigned)_arrSizeType[SizeType::LONG], 16 }, false));
|
||
btn->SetSpriteColor(ButtonState::NORMAL, ColorDef::WHITE);
|
||
btn->SetSpriteColor(ButtonState::OVER, ColorDef::GREEN);
|
||
btn->SetSpriteColor(ButtonState::DOWN, ColorDef::BLUE);
|
||
if (add_text)
|
||
btn->AddTextDefault();
|
||
item->Add(btn);
|
||
item->SetSize(btn->GetSize());
|
||
}
|
||
ListBox* ret = ListBox::Create(item, 10);
|
||
ret->SetItemLocator(createLocatorY(16.0f));
|
||
return ret;
|
||
}
|
||
|
||
dl::UI::EditBox* Manager::CreateEditBoxDefault(bool single_line)
|
||
{
|
||
// item
|
||
Panel* panel = g_ui->CreatePanel();
|
||
panel->SetLocator(createLocatorZero());
|
||
|
||
ButtonSprite* btn = g_ui->CreateButtonSpriteDefault();
|
||
btn->SetMode(ButtonMode::RADIO);
|
||
if (single_line)
|
||
btn->SetSpriteQuad(ButtonState::MAX_NUM, createQuad(
|
||
Size{ (unsigned)_arrSizeType[SizeType::LONG], 16 }, false));
|
||
else
|
||
btn->SetSpriteQuad(ButtonState::MAX_NUM, createQuad(
|
||
Size{ (unsigned)_arrSizeType[SizeType::LONG], 120 }, false));
|
||
btn->SetSpriteColor(ButtonState::NORMAL, ColorDef::WHITE);
|
||
btn->SetSpriteColor(ButtonState::OVER, ColorDef::GREEN);
|
||
btn->SetSpriteColor(ButtonState::DOWN, ColorDef::BLUE);
|
||
panel->Add(btn);
|
||
|
||
EditBox* ret = EditBox::Create(panel, g_factory->CreateTextDefault());
|
||
ret->SetSingleLine(single_line);
|
||
ret->SetColor({ ColorDef::RED, ColorDef::RED, ColorDef::WHITE });
|
||
|
||
// 多行输入框自动换行
|
||
if (!single_line)
|
||
{
|
||
ret->GetText()->SetMaxW(btn->GetSize()[0]);
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
dl::UI::Tree* Manager::CreateTreeDefault()
|
||
{
|
||
// item
|
||
Panel* panel = g_ui->CreatePanel();
|
||
panel->SetLocator(createLocatorZero());
|
||
{
|
||
ButtonSprite* btn = g_ui->CreateButtonSpriteDefault();
|
||
btn->SetMode(ButtonMode::SWITCH);
|
||
btn->SetSpriteQuad(ButtonState::MAX_NUM, createQuad(Size{ 64, 20 }, false));
|
||
btn->SetSpriteColor(ButtonState::NORMAL, ColorDef::WHITE);
|
||
btn->SetSpriteColor(ButtonState::OVER, ColorDef::GREEN);
|
||
btn->SetSpriteColor(ButtonState::DOWN, ColorDef::BLUE);
|
||
panel->Add(btn);
|
||
}
|
||
Tree* ret = Tree::Create(panel);
|
||
ret->SetCallbackSetPosition([](UI::Panel* panel, size_t i, size_t extra) {
|
||
panel->SetPosPixel(Position{ 32.0f, (i + extra) * 20.0f });
|
||
});
|
||
return ret;
|
||
}
|
||
|
||
Menu* Manager::CreateMenuDefault()
|
||
{
|
||
Background* bg = g_ui->CreateBackgroundDefault();
|
||
Background* bg_combo = g_ui->CreateBackgroundDefault();
|
||
Panel* panel_menu = g_ui->CreatePanel();
|
||
panel_menu->SetLocator(createLocatorZero());
|
||
{
|
||
UI::Text* txt = g_ui->CreateTextDefault();
|
||
panel_menu->Add(txt);
|
||
}
|
||
Panel* panel_btn = g_ui->CreatePanel();
|
||
panel_btn->SetLocator(createLocatorZero());
|
||
{
|
||
UI::Text* txt = g_ui->CreateTextDefault();
|
||
panel_btn->Add(txt);
|
||
UI::Text* txt_hotkey = g_ui->CreateTextDefault();
|
||
panel_btn->Add(txt_hotkey);
|
||
}
|
||
|
||
Menu* ret = Menu::Create(
|
||
bg, panel_menu, createLocatorX(40, 0, 32) ,
|
||
bg_combo, panel_btn, createLocatorY(30, 0, 30));
|
||
return ret;
|
||
}
|
||
|
||
ProgressBar* Manager::CreateProgressBarDefault()
|
||
{
|
||
Background* bg = g_ui->CreateBackgroundDefault();
|
||
bg->SetSize({ 200, 24 });
|
||
bg->SetColor(ColorDef::WHITE);
|
||
Background* bg_mid = Background::Create();
|
||
bg_mid->Set(g_factory->CreateSpriteDefault(ColorDef::GRAY));
|
||
//Background* bg_front = g_ui->CreateBackgroundDefault();
|
||
Text* txt = g_ui->CreateTextDefault();
|
||
txt->GetText()->SetColor(ColorDef::GREEN);
|
||
txt->GetText()->SetOutline(1, ColorDef::BLACK);
|
||
|
||
ProgressBar* ret = ProgressBar::Create(bg, bg_mid, txt);
|
||
ret->SetMidRect({ 1, 1, 199, 23 });
|
||
return ret;
|
||
}
|
||
|
||
void Manager::Register(std::string_view json_path)
|
||
{
|
||
std::ifstream ifs = File::Get(json_path);
|
||
if (!ifs.is_open())
|
||
{
|
||
log_err("json文件并不存在:{}", json_path);
|
||
return;
|
||
}
|
||
json j = Json::ParseFile(json_path);
|
||
if (j.is_null())
|
||
return;
|
||
RegKey key;
|
||
|
||
//类型名字检查
|
||
std::string type;
|
||
Json::Get(j, "type", type);
|
||
if (type.empty())
|
||
{
|
||
log_err0("必须含有type字段!例如text");
|
||
return;
|
||
}
|
||
Json::Get(j, "name", key._name);
|
||
if (key._name.empty())
|
||
{
|
||
log_err0("必须含有name字段!例如normal");
|
||
return;
|
||
}
|
||
key._type = String2ElementType(type);
|
||
if (key._type == ElementType::UNKNOWN)
|
||
return;
|
||
|
||
key._json = j;
|
||
_allReg.push_back(key);
|
||
}
|
||
|
||
void Manager::_reg_background(json& j, const std::string& name)
|
||
{
|
||
if (_allBackground.contains(name))
|
||
{
|
||
log_err("name错误(不能为空,或重复):{}", name);
|
||
return;
|
||
}
|
||
Background* bg = nullptr;
|
||
std::string spr;
|
||
std::string spr9;
|
||
|
||
Json::DisableLog l;
|
||
Json::Get(j, "spr", spr);
|
||
Json::Get(j, "spr9", spr9);
|
||
|
||
if (!spr.empty())
|
||
{
|
||
gcSprite p_spr = g_factory->CreateSprite(spr);
|
||
bg = Background::Create();
|
||
bg->Set(p_spr);
|
||
}
|
||
else if (!spr9.empty())
|
||
{
|
||
Sprite9* p_spr9 = Sprite9::Create(spr9);
|
||
bg = Background::Create();
|
||
bg->Set(p_spr9);
|
||
}
|
||
|
||
if (bg)
|
||
{
|
||
/*Point extra;
|
||
if (Json::Get(j, "extra", extra))
|
||
bg->SetExtra(extra);
|
||
Point offset;
|
||
if (Json::Get(j, "offset", offset))
|
||
bg->SetOffset(offset);*/
|
||
|
||
_allBackground[name] = bg;
|
||
log_msg("成功注册一个Background:{}", name);
|
||
}
|
||
else
|
||
{
|
||
log_msg("没有有效的字段:{}(spr、spr9)", name);
|
||
}
|
||
}
|
||
|
||
void Manager::_reg_text(json& j, const std::string& name)
|
||
{
|
||
if (_allText.contains(name))
|
||
{
|
||
log_err("name错误(不能为空,或重复):{}", name);
|
||
return;
|
||
}
|
||
|
||
std::string color;
|
||
std::string color_o;
|
||
std::string color_s;
|
||
std::string anchor;
|
||
size_t id;
|
||
unsigned size;
|
||
unsigned size_o = 0;
|
||
unsigned size_s = 0;
|
||
std::string str;
|
||
std::optional<Color> opt_color;
|
||
std::optional<Color> opt_color_o;
|
||
std::optional<Color> opt_color_s;
|
||
Align::Direction2 hv;
|
||
|
||
//id、大小、颜色
|
||
Json::Get(j, "id", id);
|
||
if (id >= g_factory->GetFontSize())
|
||
{
|
||
log_err("id越界:{}", id);
|
||
return;
|
||
}
|
||
Json::Get(j, "size", size);
|
||
|
||
Json::DisableLog l;
|
||
Json::Get(j, "string", str);
|
||
|
||
// 大小
|
||
Json::Get(j, "size_o", size_o);
|
||
Json::Get(j, "size_s", size_s);
|
||
|
||
// 颜色
|
||
if (Json::Get(j, "color", color))
|
||
opt_color = g_factory->GetColorCheck(color);
|
||
if (Json::Get(j, "color_o", color_o))
|
||
opt_color_o = g_factory->GetColorCheck(color_o);
|
||
if (Json::Get(j, "color_s", color_s))
|
||
opt_color_s = g_factory->GetColorCheck(color_s);
|
||
|
||
// 对齐
|
||
if (Json::Get(j, "anchor", anchor))
|
||
{
|
||
hv = Align::Anchor2Direction(anchor);
|
||
}
|
||
|
||
gcText txt = g_factory->CreateText(id, size);
|
||
|
||
txt->SetOutline(size_o);
|
||
txt->SetShadow(size_s);
|
||
|
||
if (opt_color.has_value())
|
||
txt->SetColor(opt_color.value());
|
||
if (opt_color_o.has_value())
|
||
txt->SetColor(opt_color_o.value(), TextParam::OUTLINE);
|
||
if (opt_color_s.has_value())
|
||
txt->SetColor(opt_color_s.value(), TextParam::SHADOW);
|
||
|
||
txt->SetString(str);
|
||
UI::Text* ret = UI::Text::Create(txt);
|
||
ret->SetElementData(hv);
|
||
|
||
_allText[name] = ret;
|
||
log_msg("成功注册一个Text:{}", name);
|
||
}
|
||
|
||
void Manager::_reg_button(json& j, const std::string& name)
|
||
{
|
||
if (_allBtnSprite.contains(name))
|
||
{
|
||
log_err("name错误(不能为空,或重复):{}", name);
|
||
return;
|
||
}
|
||
|
||
std::string style;
|
||
std::string mode;
|
||
std::string spr;
|
||
std::string txt;
|
||
|
||
Json::Get(j, "style", style);
|
||
Json::DisableLog l;
|
||
Json::Get(j, "mode", mode);
|
||
Json::Get(j, "spr", spr);
|
||
Json::Get(j, "txt", txt);
|
||
|
||
if (style == "sprite")
|
||
{
|
||
std::vector<gcSprite> mul_spr = g_factory->CreateSpriteMulti(spr);
|
||
ButtonSprite* btn = ButtonSprite::Create(mul_spr);
|
||
if (!txt.empty())
|
||
{
|
||
gcText p_txt = CreateTextOnly(txt);
|
||
btn->AddText(p_txt, {}, {});
|
||
}
|
||
//mode
|
||
if (mode == "switch")
|
||
btn->SetMode(UI::Button::Mode::SWITCH);
|
||
else if (mode == "radio")
|
||
btn->SetMode(UI::Button::Mode::RADIO);
|
||
|
||
_allBtnSprite[name] = btn;
|
||
log_msg("成功注册一个ButtonSprite:{}", name);
|
||
}
|
||
else
|
||
{
|
||
log_msg("style未知:{}", style);
|
||
return;
|
||
}
|
||
|
||
}
|
||
|
||
void Manager::_reg_msg_box(json& j, const std::string& name)
|
||
{/*
|
||
if (_allMsgBox.contains(name))
|
||
{
|
||
log_err("name错误(不能为空,或重复):{}", name);
|
||
return;
|
||
}
|
||
|
||
std::string bg;
|
||
std::string txtTitle;
|
||
std::string txt;
|
||
std::string btn;
|
||
std::string btnClose;
|
||
Float dxBtn;
|
||
|
||
Json::Get(j, "bg", bg);
|
||
Json::Get(j, "txt_title", txtTitle);
|
||
Json::Get(j, "txt", txt);
|
||
Json::Get(j, "btn", btn);
|
||
Json::Get(j, "btn_close", btnClose);
|
||
Json::Get(j, "dx_btn", dxBtn);
|
||
|
||
Background* p_bg = CreateBackground(bg);
|
||
MsgBox* msg_box = MsgBox::Create(
|
||
p_bg,
|
||
CreateTextOnly(txtTitle),
|
||
CreateTextOnly(txt),
|
||
CreateButtonSprite(btn),
|
||
CreateButtonSprite(btnClose),
|
||
dxBtn);
|
||
|
||
_allMsgBox[name] = msg_box;
|
||
log_msg("成功注册一个MsgBox:{}", name);*/
|
||
}
|
||
|
||
void Manager::_reg_locator(json& j, std::string_view name)
|
||
{
|
||
if (_allLocator.contains(std::string{ name }))
|
||
{
|
||
log_err("name错误(不能为空,或重复):{}", name);
|
||
return;
|
||
}
|
||
|
||
Locator::SL loc;
|
||
std::string layout;
|
||
|
||
Json::DisableLog l;
|
||
Json::Get(j, "dt", loc._dt);
|
||
if (Json::Get(j, "layout", layout))
|
||
loc._layout = String2Layout(layout);
|
||
Json::Get(j, "num", loc._num);
|
||
Json::Get(j, "start", loc._start);
|
||
|
||
_allLocator[std::string{ name }] = loc;
|
||
log_msg("成功注册一个Locator:{}", name);
|
||
}
|
||
|
||
void Manager::_reg_list_box(json& j, std::string_view name)
|
||
{
|
||
if (_allListBox.contains(std::string{ name }))
|
||
{
|
||
log_err("name错误(不能为空,或重复):{}", name);
|
||
return;
|
||
}
|
||
|
||
std::string btn_name;
|
||
std::string txt_name;
|
||
size_t num = 10;
|
||
Float dy = 32.0_f;
|
||
Float scroll_k = 1.0_f;
|
||
|
||
Json::Get(j, "btn", btn_name);
|
||
Json::DisableLog l;
|
||
Json::Get(j, "text", txt_name);
|
||
Json::Get(j, "num", num);
|
||
Json::Get(j, "dy", dy);
|
||
Json::Get(j, "scroll_k", scroll_k);
|
||
|
||
ButtonSprite* btn = CreateButtonSprite(btn_name);
|
||
if (!txt_name.empty())
|
||
{
|
||
// todo 颜色
|
||
btn->AddText(CreateTextOnly(txt_name),
|
||
{ ColorDef::WHITE, ColorDef::WHITE, ColorDef::GREEN },
|
||
{ {}, {0, -1}, {0, 1} });
|
||
}
|
||
Panel* item = CreatePanel();
|
||
item->SetLocator(createLocatorZero());
|
||
item->Add(btn);
|
||
item->SetSize(btn->GetSize());
|
||
|
||
ListBox* list_box = ListBox::Create(item, num);
|
||
list_box->SetScrollK(scroll_k);
|
||
|
||
_allListBox[std::string{ name }] = list_box;
|
||
log_msg("成功注册一个ListBox:{}", name);
|
||
}
|
||
|
||
void Manager::RegisterEnd()
|
||
{
|
||
_allReg.sort();
|
||
|
||
for (RegKey& key : _allReg)
|
||
{
|
||
json& j = key._json;
|
||
|
||
switch (key._type)
|
||
{
|
||
case ElementType::BACKGROUND:
|
||
_reg_background(j, key._name);
|
||
break;
|
||
case ElementType::TEXT:
|
||
_reg_text(j, key._name);
|
||
break;
|
||
case ElementType::BUTTON:
|
||
_reg_button(j, key._name);
|
||
break;
|
||
case ElementType::MSG_BOX:
|
||
_reg_msg_box(j, key._name);
|
||
break;
|
||
case ElementType::LOCATOR:
|
||
_reg_locator(j, key._name);
|
||
break;
|
||
case ElementType::LIST_BOX:
|
||
_reg_list_box(j, key._name);
|
||
break;
|
||
default:
|
||
assert(0);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
void Manager::RegisterAll(std::string_view path)
|
||
{
|
||
std::vector<std::string> all_file;
|
||
File::GetPathFileAll(path, all_file, ".json");
|
||
for (auto& iter : all_file)
|
||
{
|
||
Register(iter);
|
||
}
|
||
RegisterEnd();
|
||
}
|
||
|
||
void Manager::_resize()
|
||
{
|
||
// 窗口大小为0,可能是最小化
|
||
if (Any::Zero(g_system->GetWindowSize()))
|
||
return;
|
||
// 更新ui缩放(未设置则不缩放)
|
||
_refresh_standard_size();
|
||
|
||
_resize_panel_root();
|
||
|
||
// 更新panel大小,和元素定位
|
||
auto fn = [&](Panel* p)
|
||
{
|
||
p->_refresh_size();
|
||
};
|
||
_allPanel.ForEach(fn);
|
||
|
||
// 根面板的所有子面板更新位置
|
||
for (auto* node : _panelRoot->_node->GetChild())
|
||
{
|
||
Panel* panel = node->GetValue();
|
||
if(panel->_bAutoCoor)
|
||
panel->_refresh_pos(_panelRoot->GetSize());
|
||
}
|
||
|
||
}
|
||
|
||
void Manager::_update_pre()
|
||
{
|
||
_bDebug = false;
|
||
_bHide = false;
|
||
|
||
|
||
for (auto& node : _allPanel)
|
||
{
|
||
node->GetValue()->_bUpdate = false;
|
||
node->GetValue()->_bRender = false;
|
||
}
|
||
}
|
||
|
||
void Manager::_update()
|
||
{
|
||
_update_window();
|
||
_panelRoot->Update();
|
||
}
|
||
|
||
void Manager::_render()
|
||
{
|
||
_panelRoot->Render();
|
||
if (_bDebug)
|
||
_debug_render();
|
||
}
|
||
|
||
void Manager::_resize_panel_root()
|
||
{
|
||
// 需要拉伸填充
|
||
Size size = g_system->GetWindowSize();
|
||
_panelRoot->SetSize(toPosition(size) / _uiScale);
|
||
}
|
||
|
||
void Manager::_refresh_standard_size()
|
||
{
|
||
if (Any::Zero(_sizeStandard))
|
||
return;
|
||
Position k = toPosition(g_system->GetWindowSize()) / toPosition(_sizeStandard);
|
||
Float s = Select::Min(k);
|
||
if (s < 0.1f)
|
||
s = 0.1f;
|
||
SetScale(s);
|
||
}
|
||
|
||
void Manager::RenderDebug()
|
||
{
|
||
_bDebug = true;
|
||
}
|
||
|
||
void Manager::_debug_render()
|
||
{
|
||
if (!_bDebug)
|
||
return;
|
||
|
||
for (auto& node : _allPanel)
|
||
{
|
||
Panel* panel = node->GetValue();
|
||
if (!panel->IsUpdate())
|
||
continue;
|
||
// 绘制:panel坐标
|
||
g_gfx->RenderCoor(panel->_coor,
|
||
panel->GetParent() != _panelRoot);
|
||
// 绘制:panel大小
|
||
/*g_gfx->SetCoor(panel->_coor);
|
||
g_gfx->SetColor(createColorRandom(0.1f));
|
||
g_gfx->RectangleSolid2D({}, panel->GetSize());*/
|
||
|
||
//组件处理
|
||
for (Components* cpts : panel->_allEle)
|
||
{
|
||
Cpt::GetCoor* comp_coor = cpts->Get<Cpt::GetCoor>();
|
||
Coor* coor = comp_coor ? comp_coor->Call() : nullptr;
|
||
if (coor)
|
||
{
|
||
if (Cpt::IsPickup* comp = cpts->Get<Cpt::IsPickup>())
|
||
{
|
||
if (comp->Call())
|
||
{
|
||
// 绘制:拾取到的组件坐标
|
||
g_gfx->RenderCoor(coor);
|
||
}
|
||
}
|
||
// 绘制:组件大小
|
||
if (Cpt::ElementData* comp = cpts->Get<Cpt::ElementData>())
|
||
{
|
||
RenderDebugElementData(coor, *comp);
|
||
}
|
||
}
|
||
|
||
// 绘制:组件自定义绘制
|
||
if (Cpt::RenderDebug* comp = cpts->Get<Cpt::RenderDebug>())
|
||
{
|
||
comp->Call();
|
||
}
|
||
}
|
||
}
|
||
|
||
Button* btn = Button::GetClickControl();
|
||
if (btn)
|
||
{
|
||
gcText txt = g_factory->RenderText();
|
||
txt->GetCoor()->SetParent(btn->GetCoor());
|
||
txt->SetString("当前锁定");
|
||
}
|
||
}
|
||
|
||
void Manager::_on_char(char32_t ch)
|
||
{
|
||
if (!_edtFocus)
|
||
return;
|
||
_edtFocus->_on_char(ch);
|
||
}
|
||
|
||
void Manager::_on_key(int action, bool ctrl)
|
||
{
|
||
if (!_edtFocus)
|
||
return;
|
||
KeyCode act = (KeyCode)action;
|
||
if (ctrl)
|
||
{
|
||
if (act == KeyCode::X)
|
||
{
|
||
g_system->SetClipboardString(_edtFocus->GetStringSelect());
|
||
_edtFocus->DeleteSelect();
|
||
}
|
||
else if (act == KeyCode::C)
|
||
g_system->SetClipboardString(_edtFocus->GetStringSelect());
|
||
else if (act == KeyCode::V)
|
||
_edtFocus->_on_string(g_system->GetClipboardString());
|
||
else if (act == KeyCode::A)
|
||
_edtFocus->_on_select_all();
|
||
}
|
||
else
|
||
{
|
||
if (act == KeyCode::BACKSPACE)
|
||
_edtFocus->_on_backspace();
|
||
else if (act == KeyCode::DELETE)
|
||
_edtFocus->_on_delete();
|
||
else if (act == KeyCode::LEFT)
|
||
_edtFocus->_on_left();
|
||
else if (act == KeyCode::RIGHT)
|
||
_edtFocus->_on_right();
|
||
else if (act == KeyCode::ENTER
|
||
|| act == KeyCode::KP_ENTER)
|
||
_edtFocus->_on_enter();
|
||
}
|
||
}
|
||
|
||
void Manager::SetFocusEditBox(EditBox* edt, bool focus /*= true*/)
|
||
{
|
||
if (focus)
|
||
{
|
||
if (_edtFocus == edt)
|
||
return;
|
||
// 前一个输入框,设为非激活
|
||
if(_edtFocus)
|
||
_edtFocus->_on_focus(false);
|
||
edt->_on_focus(true);
|
||
_edtFocus = edt;
|
||
}
|
||
else
|
||
{
|
||
if (_edtFocus == edt)
|
||
{
|
||
edt->_on_focus(false);
|
||
_edtFocus = nullptr;
|
||
}
|
||
}
|
||
}
|
||
|
||
void Manager::RenderDebugElementData(Coor* coor, const Cpt::ElementData& elem_data)
|
||
{
|
||
//Position p0 = coor->GetPosition() - elem_data.GetAnchor();
|
||
//Position p1 = p0 + elem_data.GetSize();
|
||
//g_gfx->SetCoor(coor->GetParent());
|
||
//g_gfx->SetColor(createColor(ColorDef::PURPLE, 1.0f));
|
||
//g_gfx->Rectangle2D(p0, p1);
|
||
|
||
/*Position p0 = coor->GetPosition();
|
||
Position p1 = p0 + elem_data.GetSize();
|
||
g_gfx->SetCoor(coor->GetParent());
|
||
g_gfx->SetColor(createColor(ColorDef::PURPLE, 1.0f));
|
||
g_gfx->Rectangle2D(p0, p1);*/
|
||
|
||
Position p0 = {};
|
||
Position p1 = elem_data.GetSize();
|
||
g_gfx->SetCoor(coor);
|
||
g_gfx->SetColor(createColor(ColorDef::PURPLE, 1.0f));
|
||
g_gfx->Rectangle2D(p0, p1);
|
||
}
|
||
|
||
Size Manager::GetStandardSize()
|
||
{
|
||
return Any::Zero(_sizeStandard) ?
|
||
g_system->GetWindowSize() : _sizeStandard;
|
||
}
|
||
|
||
void Manager::SetStandardSize(const Size& size)
|
||
{
|
||
if (!g_system->IsWindowExist())
|
||
{
|
||
log_err("必须创建窗口之后调用!");
|
||
return;
|
||
}
|
||
_sizeStandard = size;
|
||
_refresh_standard_size();
|
||
}
|
||
|
||
void Manager::AddWindow(std::string_view name, Window* win)
|
||
{
|
||
Window*& win_old = _allWindow[std::string{ name }];
|
||
if (win_old)
|
||
{
|
||
auto iter = std::find(_listShowWindow.begin(), _listShowWindow.end(), win_old);
|
||
if (iter != _listShowWindow.end())
|
||
{
|
||
_listShowWindow.erase(iter);
|
||
}
|
||
delete win_old;
|
||
log_info("已释放旧的同名窗口:{}", name);
|
||
}
|
||
win_old = win;
|
||
win->_bInManager = true;
|
||
win->_name = name;
|
||
|
||
_on_window_show_change(win, win->IsVisible());
|
||
}
|
||
|
||
Window* Manager::GetWindow(std::string_view name)
|
||
{
|
||
auto iter = _allWindow.find(std::string{ name });
|
||
if (iter == _allWindow.end())
|
||
{
|
||
log_warn("查找窗口失败:{}", name);
|
||
return nullptr;
|
||
}
|
||
return iter->second;
|
||
}
|
||
|
||
void Manager::_update_window()
|
||
{
|
||
// 防止遍历时删除自身
|
||
std::list<Window*> list_temp = _listShowWindow;
|
||
for (auto& iter : list_temp)
|
||
{
|
||
iter->Update();
|
||
}
|
||
}
|
||
|
||
void Manager::ShowWindow(Window* win, WindowShowMode mode /*= WindowShowMode::SHOW*/)
|
||
{
|
||
bool visible_old = win->IsVisible();
|
||
bool visible_new;
|
||
switch (mode)
|
||
{
|
||
case WindowShowMode::SHOW:
|
||
visible_new = true;
|
||
break;
|
||
case WindowShowMode::HIDE:
|
||
visible_new = false;
|
||
break;
|
||
case WindowShowMode::TOGGLE:
|
||
visible_new = !visible_old;
|
||
break;
|
||
default:
|
||
assert(0);
|
||
visible_new = true;
|
||
break;
|
||
}
|
||
|
||
if (visible_old != visible_new)
|
||
{
|
||
win->SetVisible(visible_new);
|
||
}
|
||
}
|
||
|
||
void Manager::ShowWindow(std::string_view name, WindowShowMode mode /*= WindowShowMode::SHOW*/)
|
||
{
|
||
Window* win = GetWindow(name);
|
||
if (!win)
|
||
return;
|
||
|
||
ShowWindow(win, mode);
|
||
}
|
||
|
||
void Manager::SetWindowTop(Window* win)
|
||
{
|
||
auto iter = std::find(_listShowWindow.begin(), _listShowWindow.end(), win);
|
||
if (iter == _listShowWindow.end())
|
||
{
|
||
log_warn("仅添加到管理器内调用有效!");
|
||
return;
|
||
}
|
||
|
||
// 只有自己一个,不处理
|
||
if (_listShowWindow.back() == win)
|
||
return;
|
||
_listShowWindow.erase(iter);
|
||
|
||
// 插入尾部
|
||
float order_min = _listShowWindow.back()->GetOrder();
|
||
if (order_min <= _orderMin)
|
||
{// 尾部已经即将超出范围,则重排order
|
||
_listShowWindow.push_back(win);
|
||
_refresh_window_order();
|
||
}
|
||
else
|
||
{
|
||
win->SetOrder(Math::OffsetOrder(order_min, -1));
|
||
_listShowWindow.push_back(win);
|
||
}
|
||
}
|
||
|
||
void Manager::_on_window_show_change(Window* win, bool visible)
|
||
{
|
||
if (visible)
|
||
{
|
||
if (_listShowWindow.empty())
|
||
{// 空列表直接插入
|
||
win->SetOrder(_orderMax);
|
||
_listShowWindow.push_back(win);
|
||
}
|
||
else
|
||
{
|
||
// 只有自己一个,不处理
|
||
if (_listShowWindow.back() == win)
|
||
return;
|
||
// 已存在则移除
|
||
auto iter = std::find(_listShowWindow.begin(), _listShowWindow.end(), win);
|
||
if(iter != _listShowWindow.end())
|
||
_listShowWindow.erase(iter);
|
||
|
||
// 插入尾部
|
||
float order_min = _listShowWindow.back()->GetOrder();
|
||
if (order_min <= _orderMin)
|
||
{// 尾部已经即将超出范围,则重排order
|
||
_listShowWindow.push_back(win);
|
||
_refresh_window_order();
|
||
}
|
||
else
|
||
{
|
||
win->SetOrder(Math::OffsetOrder(order_min, -1));
|
||
_listShowWindow.push_back(win);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
auto iter = std::find(_listShowWindow.begin(), _listShowWindow.end(), win);
|
||
if (iter != _listShowWindow.end())
|
||
{
|
||
_listShowWindow.erase(iter);
|
||
}
|
||
}
|
||
}
|
||
|
||
void Manager::_refresh_window_order()
|
||
{
|
||
float order = _orderMax;
|
||
for (auto& iter : _listShowWindow)
|
||
{
|
||
iter->SetOrder(order);
|
||
order = Math::OffsetOrder(order, -1);
|
||
}
|
||
}
|
||
|
||
void Manager::_release_window(Window* win)
|
||
{
|
||
if (!win->_bInManager)
|
||
return;
|
||
|
||
auto iter = _allWindow.find(win->_name);
|
||
if (iter != _allWindow.end())
|
||
{
|
||
_on_window_show_change(win, false);
|
||
_allWindow.erase(iter);
|
||
}
|
||
}
|
||
|
||
Manager::~Manager()
|
||
{
|
||
_release();
|
||
for (auto& node : _allPanel)
|
||
{
|
||
delete node->GetValue();
|
||
}
|
||
}
|
||
|
||
void Manager::_release_window_all()
|
||
{
|
||
auto temp = _allWindow;
|
||
for (auto& iter : temp)
|
||
{
|
||
delete iter.second;
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
#endif |