Explorar el Código

gui extension

Laserlicht hace 4 meses
padre
commit
c8f06b17f5

+ 60 - 12
client/windows/GUIClasses.cpp

@@ -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();
 

+ 8 - 0
client/windows/GUIClasses.h

@@ -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);

+ 2 - 2
config/gameConfig.json

@@ -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":

+ 1 - 1
lib/texts/TextLocalizationContainer.cpp

@@ -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)
 	{