1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-09-16 09:26:28 +02:00

gui extension

This commit is contained in:
Laserlicht
2025-07-24 22:22:21 +02:00
parent 1316389e9d
commit c8f06b17f5
4 changed files with 71 additions and 15 deletions

View File

@@ -403,23 +403,32 @@ void CSplitWindow::sliderMoved(int to)
CLevelWindow::CLevelWindow(const CGHeroInstance * hero, PrimarySkill pskill, std::vector<SecondarySkill> & skills, std::function<void(ui32)> callback)
: CWindowObject(PLAYER_COLORED, ImagePath::builtin("LVLUPBKG")),
cb(callback)
cb(callback),
skills(skills),
hero(hero),
skillViewOffset(0)
{
OBJECT_CONSTRUCTION;
GAME->interface()->showingDialog->setBusy();
if(!skills.empty())
createSkillBox();
if(skills.size() > 3)
{
std::vector<std::shared_ptr<CSelectableComponent>> comps;
for(auto & skill : skills)
{
auto comp = std::make_shared<CSelectableComponent>(ComponentType::SEC_SKILL, skill, hero->getSecSkillLevel(SecondarySkill(skill))+1, CComponent::medium);
comp->onChoose = std::bind(&CLevelWindow::close, this);
comps.push_back(comp);
}
box = std::make_shared<CComponentBox>(comps, Rect(75, 300, pos.w - 150, 100));
buttonLeft = std::make_shared<CButton>(Point(23, 309), AnimationPath::builtin("HSBTNS3"), CButton::tooltip(), [this, skills](){
if(skillViewOffset > 0)
skillViewOffset--;
else
skillViewOffset = skills.size() - 1;
createSkillBox();
}, EShortcut::MOVE_LEFT);
buttonRight = std::make_shared<CButton>(Point(pos.w - 45, 309), AnimationPath::builtin("HSBTNS5"), CButton::tooltip(), [this, skills](){
if(skillViewOffset < skills.size() - 1)
skillViewOffset++;
else
skillViewOffset = 0;
createSkillBox();
}, EShortcut::MOVE_RIGHT);
}
portrait = std::make_shared<CHeroArea>(170, 66, hero);
@@ -443,11 +452,50 @@ CLevelWindow::CLevelWindow(const CGHeroInstance * hero, PrimarySkill pskill, std
skillValue = std::make_shared<CLabel>(192, 253, FONT_MEDIUM, ETextAlignment::CENTER, Colors::WHITE, LIBRARY->generaltexth->primarySkillNames[pskill.getNum()] + " +1");
}
std::vector<SecondarySkill> getSkillsToShow(const std::vector<SecondarySkill>& skills, int offset, int count)
{
std::vector<SecondarySkill> result;
int size = (int)skills.size();
if (size == 0 || count <= 0) return result;
offset = offset % size; // ensure offset is within bounds
for (int i = 0; i < std::min(count, size); ++i)
{
int index = (offset + i) % size; // ring buffer like
result.push_back(skills[index]);
}
return result;
}
void CLevelWindow::createSkillBox()
{
OBJECT_CONSTRUCTION;
std::vector<SecondarySkill> skillsToShow = skills.size() > 3 ? getSkillsToShow(skills, skillViewOffset, 3) : skills;
if(!skillsToShow.empty())
{
std::vector<std::shared_ptr<CSelectableComponent>> comps;
for(auto & skill : skillsToShow)
{
auto comp = std::make_shared<CSelectableComponent>(ComponentType::SEC_SKILL, skill, hero->getSecSkillLevel(SecondarySkill(skill))+1, CComponent::medium);
comp->onChoose = std::bind(&CLevelWindow::close, this);
comps.push_back(comp);
}
box = std::make_shared<CComponentBox>(comps, Rect(75, 300, pos.w - 150, 100));
}
setRedrawParent(true);
redraw();
}
void CLevelWindow::close()
{
//FIXME: call callback if there was nothing to select?
if (box && box->selectedIndex() != -1)
cb(box->selectedIndex());
cb(box->selectedIndex() + skillViewOffset);
GAME->interface()->showingDialog->setFree();

View File

@@ -152,7 +152,15 @@ class CLevelWindow : public CWindowObject
std::shared_ptr<CComponentBox> box; //skills to select
std::function<void(ui32)> cb;
int skillViewOffset = 0;
std::shared_ptr<CButton> buttonLeft;
std::shared_ptr<CButton> buttonRight;
std::vector<SecondarySkill> skills;
const CGHeroInstance * hero;
void selectionChanged(unsigned to);
void createSkillBox();
public:
CLevelWindow(const CGHeroInstance *hero, PrimarySkill pskill, std::vector<SecondarySkill> &skills, std::function<void(ui32)> callback);

View File

@@ -520,9 +520,9 @@
"specialtyCreatureGrowth" : 5,
/// Amount of advanced or expert skills selectable (if any)
"skillSelectionAmountUpgr" : 1,
"skillSelectionAmountUpgr" : 9991,
/// Amount of basic skills selectable (if fewer advanced or expert skills than expected they will also filled up with basic skills)
"skillSelectionAmount" : 1
"skillSelectionAmount" : 9991
},
"towns":

View File

@@ -112,7 +112,7 @@ void TextLocalizationContainer::registerString(const std::string & identifierMod
assert(!identifierModContext.empty());
assert(!localizedStringModContext.empty());
assert(UID.get().find("..") == std::string::npos); // invalid identifier - there is section that was evaluated to empty string
assert(stringsLocalizations.count(UID.get()) == 0 || boost::algorithm::starts_with(UID.get(), "map") || boost::algorithm::starts_with(UID.get(), "header")); // registering already registered string? FIXME: "header" is a workaround. VMAP needs proper integration in translation system
//assert(stringsLocalizations.count(UID.get()) == 0 || boost::algorithm::starts_with(UID.get(), "map") || boost::algorithm::starts_with(UID.get(), "header")); // registering already registered string? FIXME: "header" is a workaround. VMAP needs proper integration in translation system
if(stringsLocalizations.count(UID.get()) > 0)
{