Added some menu scrolling helper functions. Implemented Artificer Enchant window. Added controller compatibility to Artificer Refining Window. Release Build 11652.
This commit is contained in:
parent
a5c10f35e6
commit
86e2976549
@ -251,15 +251,21 @@ namespace ItemTests
|
||||
std::weak_ptr<Item>slimeKingRing{Inventory::AddItem("Ring of the Slime King"s)};
|
||||
Assert::IsFalse(slimeKingRing.lock()->HasEnchant());
|
||||
for(int i:std::ranges::iota_view(0,1000)){
|
||||
slimeKingRing.lock()->_EnchantItem(ItemEnchant::RollRandomEnchant());
|
||||
std::string previousEnchantName{};
|
||||
if(slimeKingRing.lock()->HasEnchant())previousEnchantName=slimeKingRing.lock()->GetEnchant().value().Name();
|
||||
slimeKingRing.lock()->_EnchantItem(ItemEnchant::RollRandomEnchant(previousEnchantName));
|
||||
Assert::IsTrue(slimeKingRing.lock()->HasEnchant());
|
||||
Assert::AreNotEqual(previousEnchantName,slimeKingRing.lock()->GetEnchant().value().Name(),L"The previous enchant should never be the same as the new enchant attempt.");
|
||||
if(ItemEnchantInfo::ENCHANT_LIST.at(slimeKingRing.lock()->GetEnchant().value().Name()).GetClass().has_value())Assert::AreEqual(int(player->GetClass()),int(ItemEnchantInfo::ENCHANT_LIST.at(slimeKingRing.lock()->GetEnchant().value().Name()).GetClass().value())); //Validate enchant is only for this class if it's a class-based ability.
|
||||
}
|
||||
testGame->ChangePlayerClass(WIZARD);
|
||||
player=testGame->GetPlayer(); //The player pointer has been reassigned...
|
||||
for(int i:std::ranges::iota_view(0,1000)){
|
||||
slimeKingRing.lock()->_EnchantItem(ItemEnchant::RollRandomEnchant());
|
||||
std::string previousEnchantName{};
|
||||
if(slimeKingRing.lock()->HasEnchant())previousEnchantName=slimeKingRing.lock()->GetEnchant().value().Name();
|
||||
slimeKingRing.lock()->_EnchantItem(ItemEnchant::RollRandomEnchant(previousEnchantName));
|
||||
Assert::IsTrue(slimeKingRing.lock()->HasEnchant());
|
||||
Assert::AreNotEqual(previousEnchantName,slimeKingRing.lock()->GetEnchant().value().Name(),L"The previous enchant should never be the same as the new enchant attempt.");
|
||||
if(ItemEnchantInfo::ENCHANT_LIST.at(slimeKingRing.lock()->GetEnchant().value().Name()).GetClass().has_value())Assert::AreEqual(int(player->GetClass()),int(ItemEnchantInfo::ENCHANT_LIST.at(slimeKingRing.lock()->GetEnchant().value().Name()).GetClass().value())); //Validate enchant is only for this class if it's a class-based ability.
|
||||
}
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ void Menu::InitializeArtificerDisassembleWindow(){
|
||||
EnableDisassemblyDisplay();
|
||||
RowItemDisplay&item{*DYNAMIC_POINTER_CAST<RowItemDisplay>(data.component)};
|
||||
Component<MenuItemItemButton>(data.menu.type,"Item Icon")->SetItem(item.GetItem().lock());
|
||||
Component<MenuIconButton>(data.menu.type,"Disassembly Result")->SetIcon(GFX.at(item.GetItem().lock()->FragmentName()).Decal());
|
||||
Component<MenuIconButton>(data.menu.type,"Disassembly Result")->SetIcon(item.GetItem().lock()->Icon().Decal());
|
||||
Component<MenuLabel>(data.menu.type,"Disassembly Result Title")->SetLabel(item.GetItem().lock()->FragmentName());
|
||||
Component<MenuLabel>(data.menu.type,"Fragment Total Count")->SetLabel(std::format("Currently Owned: {}",Inventory::GetItemCount(item.GetItem().lock()->FragmentName())));
|
||||
return true;
|
||||
@ -119,7 +119,7 @@ void Menu::InitializeArtificerDisassembleWindow(){
|
||||
if(childComponent){
|
||||
RowItemDisplay&item{childComponent.value().get()};
|
||||
Component<MenuItemItemButton>(data.menu.type,"Item Icon")->SetItem(item.GetItem().lock());
|
||||
Component<MenuIconButton>(data.menu.type,"Disassembly Result")->SetIcon(GFX.at(item.GetItem().lock()->FragmentName()).Decal());
|
||||
Component<MenuIconButton>(data.menu.type,"Disassembly Result")->SetIcon(item.GetItem().lock()->Icon().Decal());
|
||||
Component<MenuLabel>(data.menu.type,"Disassembly Result Title")->SetLabel(item.GetItem().lock()->FragmentName());
|
||||
Component<MenuLabel>(data.menu.type,"Fragment Total Count")->SetLabel(std::format("Currently Owned: {}",Inventory::GetItemCount(item.GetItem().lock()->FragmentName())));
|
||||
EnableDisassemblyDisplay();
|
||||
@ -136,6 +136,8 @@ void Menu::InitializeArtificerDisassembleWindow(){
|
||||
|
||||
Menu::AddInventoryListener(inventoryDisplay,"Accessories");
|
||||
|
||||
ResetDisassemblyDisplay();
|
||||
|
||||
artificerDisassembleWindow->SetupKeyboardNavigation(
|
||||
[](MenuType type,Data&returnData){ //On Open
|
||||
returnData="";
|
||||
|
@ -40,6 +40,7 @@ All rights reserved.
|
||||
#include "AdventuresInLestoria.h"
|
||||
#include "MenuIconButton.h"
|
||||
#include "MenuItemLabel.h"
|
||||
#include "SoundEffect.h"
|
||||
|
||||
INCLUDE_game
|
||||
|
||||
@ -68,12 +69,32 @@ void Menu::InitializeArtificerEnchantConfirmWindow(){
|
||||
const float takeOldTextWidth{float(game->GetTextSize("Take Old").x)*2.f};
|
||||
auto takeOldButton{artificerEnchantConfirmWindow->ADD("Take Old Button",MenuComponent)(geom2d::rect<float>{{artificerEnchantConfirmWindow->size.x/4.f-takeOldTextWidth/2.f,138.f},{takeOldTextWidth-8.f,20.f}},"Take Old",[](MenuFuncData data){
|
||||
onClick:
|
||||
const std::string&oldEnchantName{Menu::menus[ARTIFICER_ENCHANT]->S(A::ENCHANT_TYPE)};
|
||||
std::weak_ptr<Item>newItem{std::get<std::weak_ptr<Item>>(Component<MenuItemLabel>(data.menu.GetType(),"New Item Description")->GetItem())}; //NOTE: We're making an assumption here that the new item description holds a weak pointer. This should be true because the only way to get here was to set it up through clicking the Enchant button in Artificer Enchant Window.
|
||||
newItem.lock()->_EnchantItem(oldEnchantName);
|
||||
Component<MenuComponent>(ARTIFICER_ENCHANT,"Fragment Enchant Button")->SetGrayedOut(!newItem.lock()->CanBeEnchanted());
|
||||
const std::string_view fragmentName{newItem.lock()->FragmentName()};
|
||||
const Pixel fragmentItemDisplayCol{Inventory::GetItemCount(fragmentName)>="Fragment Enchant Cost"_i[0]?WHITE:RED};
|
||||
const Pixel moneyCostDisplayCol{game->GetPlayer()->GetMoney()>="Fragment Enchant Cost"_i[1]?WHITE:RED};
|
||||
Component<MenuLabel>(ARTIFICER_ENCHANT,"Fragment Label")->SetLabel(std::format("{}{} x{} ({})",fragmentItemDisplayCol.toHTMLColorCode(),fragmentName,"Fragment Enchant Cost"_i[0],Inventory::GetItemCount(fragmentName)));
|
||||
Component<MenuLabel>(ARTIFICER_ENCHANT,"Fragment Money Cost Label")->SetLabel(std::format("{}{} gold",moneyCostDisplayCol.toHTMLColorCode(),"Fragment Enchant Cost"_i[1]));
|
||||
SoundEffect::PlaySFX("Take Enchant",SoundEffect::CENTERED);
|
||||
Menu::CloseMenu();
|
||||
return true;
|
||||
},vf2d{2.f,2.f})END};
|
||||
|
||||
const float takeNewTextWidth{float(game->GetTextSize("Take New").x)*2.f};
|
||||
auto takeNewButton{artificerEnchantConfirmWindow->ADD("Take New Button",MenuComponent)(geom2d::rect<float>{vf2d{artificerEnchantConfirmWindow->size.x/2.f+8.f+artificerEnchantConfirmWindow->size.x/4.f-takeNewTextWidth/2.f,138.f},{takeNewTextWidth-8.f,20.f}},"Take New",[](MenuFuncData data){
|
||||
onClick:
|
||||
std::weak_ptr<Item>newItem{std::get<std::weak_ptr<Item>>(Component<MenuItemLabel>(data.menu.GetType(),"New Item Description")->GetItem())};
|
||||
Component<MenuComponent>(ARTIFICER_ENCHANT,"Fragment Enchant Button")->SetGrayedOut(!newItem.lock()->CanBeEnchanted());
|
||||
const std::string_view fragmentName{newItem.lock()->FragmentName()};
|
||||
const Pixel fragmentItemDisplayCol{Inventory::GetItemCount(fragmentName)>="Fragment Enchant Cost"_i[0]?WHITE:RED};
|
||||
const Pixel moneyCostDisplayCol{game->GetPlayer()->GetMoney()>="Fragment Enchant Cost"_i[1]?WHITE:RED};
|
||||
Component<MenuLabel>(ARTIFICER_ENCHANT,"Fragment Label")->SetLabel(std::format("{}{} x{} ({})",fragmentItemDisplayCol.toHTMLColorCode(),fragmentName,"Fragment Enchant Cost"_i[0],Inventory::GetItemCount(fragmentName)));
|
||||
Component<MenuLabel>(ARTIFICER_ENCHANT,"Fragment Money Cost Label")->SetLabel(std::format("{}{} gold",moneyCostDisplayCol.toHTMLColorCode(),"Fragment Enchant Cost"_i[1]));
|
||||
SoundEffect::PlaySFX("Take Enchant",SoundEffect::CENTERED);
|
||||
Menu::CloseMenu();
|
||||
return true;
|
||||
},vf2d{2.f,2.f})END};
|
||||
|
||||
|
@ -157,7 +157,12 @@ void Menu::InitializeArtificerRefineWindow(){
|
||||
|
||||
artificerRefineWindow->SetupKeyboardNavigation(
|
||||
[](MenuType type,Data&returnData){ //On Open
|
||||
returnData="";
|
||||
auto&items{Component<RowInventoryScrollableWindowComponent>(type,"Accessory List")->GetComponents()};
|
||||
if(items.size()>0){
|
||||
returnData=items[0];
|
||||
}else{
|
||||
returnData="Back";
|
||||
}
|
||||
},
|
||||
{ //Button Key
|
||||
{game->KEY_SCROLL,{"Navigate",[](MenuType type){}}},
|
||||
@ -165,12 +170,51 @@ void Menu::InitializeArtificerRefineWindow(){
|
||||
Menu::CloseMenu();
|
||||
}}},
|
||||
{game->KEY_CONFIRM,{"Select",[](MenuType type){}}},
|
||||
{{game->KEY_SHOULDER2,Pressed},{"Scroll Up/Down",[](MenuType type){}}},
|
||||
{{game->KEY_SHOULDER,Pressed},{"Scroll Up/Down",[](MenuType type){}}},
|
||||
{{game->KEY_FASTSCROLLUP,PressedDAS},{"Scroll",[](MenuType type){
|
||||
Menu::menus[type]->GetSelection().lock()->parentComponent.lock()->DecreaseSelectionIndex(3.f);
|
||||
}}},
|
||||
{{game->KEY_FASTSCROLLDOWN,PressedDAS},{"Scroll",[](MenuType type){
|
||||
Menu::menus[type]->GetSelection().lock()->parentComponent.lock()->IncreaseSelectionIndex(3.f);
|
||||
}}},
|
||||
}
|
||||
,{ //Button Navigation Rules
|
||||
{"Sample Button",{
|
||||
.up="",
|
||||
.down="",
|
||||
.left="",
|
||||
.right="",}},
|
||||
});
|
||||
{"Accessory List",{
|
||||
.up=[&](MenuType type,Data&returnData){
|
||||
Menu::ScrollUp(type,"Accessory List",returnData,"Back");
|
||||
},
|
||||
.down=[&](MenuType type,Data&returnData){
|
||||
Menu::ScrollDown(type,"Accessory List",returnData,"Back");
|
||||
},
|
||||
.left="Back",
|
||||
.right=[&](MenuType type,Data&returnData){
|
||||
Menu::menus[type]->GetSelection().lock()->Click();
|
||||
returnData="Fragment Refine Button";
|
||||
},}},
|
||||
{"Back",{
|
||||
.up=[&](MenuType type,Data&returnData){
|
||||
if(Component<RowInventoryScrollableWindowComponent>(type,"Accessory List")->GetSelectedChild())returnData=Component<RowInventoryScrollableWindowComponent>(type,"Accessory List")->GetSelectedChild().value().get().GetName();
|
||||
else returnData=Component<RowInventoryScrollableWindowComponent>(type,"Accessory List")->GetComponents().back().lock()->GetName();
|
||||
},
|
||||
.down=[&](MenuType type,Data&returnData){
|
||||
if(Component<RowInventoryScrollableWindowComponent>(type,"Accessory List")->GetSelectedChild())returnData=Component<RowInventoryScrollableWindowComponent>(type,"Accessory List")->GetSelectedChild().value().get().GetName();
|
||||
else returnData=Component<RowInventoryScrollableWindowComponent>(type,"Accessory List")->GetComponents().front().lock()->GetName();
|
||||
},
|
||||
.left="Fragment Refine Button",
|
||||
.right="Fragment Refine Button",}},
|
||||
{"Fragment Refine Button",{
|
||||
.up=[&](MenuType type,Data&returnData){
|
||||
returnData=Component<RowInventoryScrollableWindowComponent>(type,"Accessory List")->GetComponents().back().lock()->GetName();
|
||||
},
|
||||
.down=[&](MenuType type,Data&returnData){
|
||||
returnData=Component<RowInventoryScrollableWindowComponent>(type,"Accessory List")->GetComponents().front().lock()->GetName();
|
||||
},
|
||||
.left=[&](MenuType type,Data&returnData){
|
||||
if(Component<RowInventoryScrollableWindowComponent>(type,"Accessory List")->GetSelectedChild())returnData=Component<RowInventoryScrollableWindowComponent>(type,"Accessory List")->GetSelectedChild().value().get().GetName();
|
||||
else returnData="Back";
|
||||
},
|
||||
.right="Back",}},
|
||||
}
|
||||
);
|
||||
}
|
@ -76,7 +76,7 @@ void Menu::InitializeArtificerWindow(){
|
||||
|
||||
artificerWindow->SetupKeyboardNavigation(
|
||||
[](MenuType type,Data&returnData){ //On Open
|
||||
returnData="Refine Button";
|
||||
returnData="Disassemble Button";
|
||||
},
|
||||
{ //Button Key
|
||||
{game->KEY_SCROLL,{"Navigate",[](MenuType type){}}},
|
||||
@ -86,14 +86,14 @@ void Menu::InitializeArtificerWindow(){
|
||||
{game->KEY_CONFIRM,{"Select",[](MenuType type){}}},
|
||||
}
|
||||
,{ //Button Navigation Rules
|
||||
{"Refine Button",{
|
||||
.up="Leave Button",
|
||||
.down="Disassemble Button",}},
|
||||
{"Disassemble Button",{
|
||||
.up="Refine Button",
|
||||
.up="Leave Button",
|
||||
.down="Refine Button",}},
|
||||
{"Refine Button",{
|
||||
.up="Disassemble Button",
|
||||
.down="Enchant Button",}},
|
||||
{"Enchant Button",{
|
||||
.up="Disassemble Button",
|
||||
.up="Refine Button",
|
||||
.down="Help Button",}},
|
||||
{"Help Button",{
|
||||
.up="Enchant Button",
|
||||
|
@ -476,28 +476,10 @@ void Menu::InitializeCharacterMenuWindow(){
|
||||
,{ //Button Navigation Rules
|
||||
{"Equip List",{
|
||||
.up=[](MenuType type,Data&returnData){
|
||||
if(!Menu::menus[type]->GetSelection().expired()){
|
||||
auto selection=Menu::menus[type]->GetSelection().lock();
|
||||
size_t index=Component<ScrollableWindowComponent>(type,"Equip List")->GetComponentIndex(selection);
|
||||
index--;
|
||||
if(index>=Component<ScrollableWindowComponent>(type,"Equip List")->GetComponents().size()){
|
||||
returnData="Equip Selection Select Button";
|
||||
}else{
|
||||
returnData=Component<ScrollableWindowComponent>(type,"Equip List")->GetComponents()[index];
|
||||
}
|
||||
}
|
||||
Menu::ScrollUp(type,"Equip List",returnData,"Equip Selection Select Button");
|
||||
},
|
||||
.down=[](MenuType type,Data&returnData){
|
||||
if(!Menu::menus[type]->GetSelection().expired()){
|
||||
auto selection=Menu::menus[type]->GetSelection().lock();
|
||||
size_t index=Component<ScrollableWindowComponent>(type,"Equip List")->GetComponentIndex(selection);
|
||||
index++;
|
||||
if(index>=Component<ScrollableWindowComponent>(type,"Equip List")->GetComponents().size()){
|
||||
returnData="Equip Selection Select Button";
|
||||
}else{
|
||||
returnData=Component<ScrollableWindowComponent>(type,"Equip List")->GetComponents()[index];
|
||||
}
|
||||
}
|
||||
Menu::ScrollDown(type,"Equip List",returnData,"Equip Selection Select Button");
|
||||
},
|
||||
.left=[](MenuType type,Data&returnData){
|
||||
auto equipList=Component<ScrollableWindowComponent>(type,"Equip List")->GetComponents();
|
||||
|
@ -1530,7 +1530,9 @@ const std::optional<std::string>&Item::FragmentIcon()const{
|
||||
|
||||
const ItemEnchantInfo Item::ApplyRandomEnchant(){
|
||||
if(!CanBeEnchanted())ERR("WARNING! Trying to enchant an item that cannot be enchanted! Make sure you are checking with CanBeEnchanted() before calling this function!");
|
||||
EnchantName randomEnchantName{ItemEnchant::RollRandomEnchant()};
|
||||
std::string currentEnchantName{""};
|
||||
if(HasEnchant())currentEnchantName=GetEnchant().value().Name();
|
||||
EnchantName randomEnchantName{ItemEnchant::RollRandomEnchant(currentEnchantName)};
|
||||
_EnchantItem(randomEnchantName);
|
||||
Inventory::RemoveItem(FragmentName(),"Fragment Enchant Cost"_i[0]);
|
||||
game->GetPlayer()->RemoveMoney("Fragment Enchant Cost"_i[1]);
|
||||
|
@ -246,7 +246,7 @@ const std::vector<ItemEnchantInfo>ItemEnchant::GetAvailableEnchants(){
|
||||
return filteredEnchants;
|
||||
}
|
||||
|
||||
const std::string ItemEnchant::RollRandomEnchant(){
|
||||
const std::string ItemEnchant::RollRandomEnchant(const std::string_view previousEnchantName){
|
||||
const std::vector<ItemEnchantInfo>filteredEnchants{GetAvailableEnchants()};
|
||||
|
||||
int randomRoll{int(util::random_range(0,100))};
|
||||
@ -256,11 +256,11 @@ const std::string ItemEnchant::RollRandomEnchant(){
|
||||
std::vector<ItemEnchantInfo>remainingAvailableEnchants;
|
||||
|
||||
if(randomRoll>=generalEnchantRange.first&&randomRoll<generalEnchantRange.second){
|
||||
std::copy_if(filteredEnchants.begin(),filteredEnchants.end(),std::back_inserter(remainingAvailableEnchants),[](const ItemEnchantInfo&enchant){return enchant.Category()==ItemEnchantInfo::ItemEnchantCategory::GENERAL;});
|
||||
std::copy_if(filteredEnchants.begin(),filteredEnchants.end(),std::back_inserter(remainingAvailableEnchants),[&previousEnchantName](const ItemEnchantInfo&enchant){return enchant.Name()!=previousEnchantName&&enchant.Category()==ItemEnchantInfo::ItemEnchantCategory::GENERAL;});
|
||||
}else if(randomRoll>=classEnchantRange.first&&randomRoll<classEnchantRange.second){
|
||||
std::copy_if(filteredEnchants.begin(),filteredEnchants.end(),std::back_inserter(remainingAvailableEnchants),[](const ItemEnchantInfo&enchant){return enchant.Category()==ItemEnchantInfo::ItemEnchantCategory::CLASS;});
|
||||
std::copy_if(filteredEnchants.begin(),filteredEnchants.end(),std::back_inserter(remainingAvailableEnchants),[&previousEnchantName](const ItemEnchantInfo&enchant){return enchant.Name()!=previousEnchantName&&enchant.Category()==ItemEnchantInfo::ItemEnchantCategory::CLASS;});
|
||||
}else if(randomRoll>=uniqueEnchantRange.first&&randomRoll<uniqueEnchantRange.second){
|
||||
std::copy_if(filteredEnchants.begin(),filteredEnchants.end(),std::back_inserter(remainingAvailableEnchants),[](const ItemEnchantInfo&enchant){return enchant.Category()==ItemEnchantInfo::ItemEnchantCategory::UNIQUE;});
|
||||
std::copy_if(filteredEnchants.begin(),filteredEnchants.end(),std::back_inserter(remainingAvailableEnchants),[&previousEnchantName](const ItemEnchantInfo&enchant){return enchant.Name()!=previousEnchantName&&enchant.Category()==ItemEnchantInfo::ItemEnchantCategory::UNIQUE;});
|
||||
}else ERR(std::format("WARNING! Somehow did not pick a value in any of the given ranges. Rolled value was: {}. Ranges were {}-{}, {}-{}, {}-{}",randomRoll,generalEnchantRange.first,generalEnchantRange.second,classEnchantRange.first,classEnchantRange.second,uniqueEnchantRange.first,uniqueEnchantRange.second));
|
||||
|
||||
return remainingAvailableEnchants[util::random()%remainingAvailableEnchants.size()].Name();
|
||||
|
@ -100,6 +100,8 @@ private:
|
||||
static std::unordered_map<ItemEnchantCategory,ItemEnchantCategoryData>ENCHANT_CATEGORIES;
|
||||
};
|
||||
|
||||
class Item;
|
||||
|
||||
class ItemEnchant{
|
||||
public:
|
||||
ItemEnchant(const std::string_view enchantName);
|
||||
@ -109,7 +111,7 @@ public:
|
||||
const std::optional<ItemEnchantInfo::AbilitySlot>&AbilitySlot()const;
|
||||
const static std::vector<ItemEnchantInfo>GetAvailableEnchants();
|
||||
//Rolls a class-appropriate random enchant.
|
||||
const static std::string RollRandomEnchant();
|
||||
const static std::string RollRandomEnchant(const std::string_view previousEnchantName);
|
||||
void SetAttribute(const std::string_view attr,const float val);
|
||||
const float&GetAttribute(const std::string_view attr)const;
|
||||
std::map<ItemAttribute,float>::const_iterator begin()const;
|
||||
|
@ -418,6 +418,7 @@ void Menu::KeyboardButtonNavigation(AiL*game,vf2d menuPos){
|
||||
if(std::holds_alternative<MenuDataFunc>(nav.up)){
|
||||
Data returnData;
|
||||
std::get<MenuDataFunc>(nav.up)(type,returnData);
|
||||
if(!std::holds_alternative<ButtonName>(returnData)&&!std::holds_alternative<std::weak_ptr<MenuComponent>>(returnData))ERR(std::format("WARNING! No valid return type set for up button navigation in menu {}",int(type)));
|
||||
SetSelection(returnData);
|
||||
}
|
||||
}
|
||||
@ -429,6 +430,7 @@ void Menu::KeyboardButtonNavigation(AiL*game,vf2d menuPos){
|
||||
if(std::holds_alternative<MenuDataFunc>(nav.down)){
|
||||
Data returnData;
|
||||
std::get<MenuDataFunc>(nav.down)(type,returnData);
|
||||
if(!std::holds_alternative<ButtonName>(returnData)&&!std::holds_alternative<std::weak_ptr<MenuComponent>>(returnData))ERR(std::format("WARNING! No valid return type set for down button navigation in menu {}",int(type)));
|
||||
SetSelection(returnData);
|
||||
}
|
||||
}
|
||||
@ -440,6 +442,7 @@ void Menu::KeyboardButtonNavigation(AiL*game,vf2d menuPos){
|
||||
if(std::holds_alternative<MenuDataFunc>(nav.left)){
|
||||
Data returnData;
|
||||
std::get<MenuDataFunc>(nav.left)(type,returnData);
|
||||
if(!std::holds_alternative<ButtonName>(returnData)&&!std::holds_alternative<std::weak_ptr<MenuComponent>>(returnData))ERR(std::format("WARNING! No valid return type set for left button navigation in menu {}",int(type)));
|
||||
SetSelection(returnData);
|
||||
}
|
||||
}
|
||||
@ -451,6 +454,7 @@ void Menu::KeyboardButtonNavigation(AiL*game,vf2d menuPos){
|
||||
if(std::holds_alternative<MenuDataFunc>(nav.right)){
|
||||
Data returnData;
|
||||
std::get<MenuDataFunc>(nav.right)(type,returnData);
|
||||
if(!std::holds_alternative<ButtonName>(returnData)&&!std::holds_alternative<std::weak_ptr<MenuComponent>>(returnData))ERR(std::format("WARNING! No valid return type set for right button navigation in menu {}",int(type)));
|
||||
SetSelection(returnData);
|
||||
}
|
||||
}
|
||||
@ -815,3 +819,31 @@ const bool Menu::IsMouseOverMenu(){
|
||||
if(Menu::stack.size()==0)return false;
|
||||
return geom2d::overlaps(game->GetMousePos(),geom2d::rect<float>{Menu::stack.back()->pos-"Interface.9PatchSize"_V.x,Menu::stack.back()->size+"Interface.9PatchSize"_V.y*2});
|
||||
}
|
||||
|
||||
void Menu::ScrollUp(const MenuType type,const std::string&componentName,Data&returnData,const std::optional<std::string>wrapDestination){
|
||||
if(!Menu::menus[type]->GetSelection().expired()){
|
||||
auto selection=Menu::menus[type]->GetSelection().lock();
|
||||
size_t index=Component<ScrollableWindowComponent>(type,componentName)->GetComponentIndex(selection);
|
||||
index--;
|
||||
if(index>=Component<ScrollableWindowComponent>(type,componentName)->GetComponents().size()){
|
||||
if(wrapDestination)returnData=wrapDestination.value();
|
||||
else returnData=Component<ScrollableWindowComponent>(type,componentName)->GetComponents().back();
|
||||
}else{
|
||||
returnData=Component<ScrollableWindowComponent>(type,componentName)->GetComponents()[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Menu::ScrollDown(const MenuType type,const std::string&componentName,Data&returnData,const std::optional<std::string>wrapDestination){
|
||||
if(!Menu::menus[type]->GetSelection().expired()){
|
||||
auto selection=Menu::menus[type]->GetSelection().lock();
|
||||
size_t index=Component<ScrollableWindowComponent>(type,componentName)->GetComponentIndex(selection);
|
||||
index++;
|
||||
if(index>=Component<ScrollableWindowComponent>(type,componentName)->GetComponents().size()){
|
||||
if(wrapDestination)returnData=wrapDestination.value();
|
||||
else returnData=Component<ScrollableWindowComponent>(type,componentName)->GetComponents().front();
|
||||
}else{
|
||||
returnData=Component<ScrollableWindowComponent>(type,componentName)->GetComponents()[index];
|
||||
}
|
||||
}
|
||||
}
|
@ -208,6 +208,10 @@ public:
|
||||
//Returns whether or not this menu type is currently in the foreground of the game, and thus being interacted with by the user.
|
||||
static bool IsCurrentlyActive(MenuType type);
|
||||
static const bool IsMouseOverMenu(); //Returns whether the mouse is hovering over any portion of the menu, thus can be used if a menu is not supposed to cover up everything to determine mouse interactions.
|
||||
//If a wrap destination is specified, will resolve the selection to that button when the top is reached, otherwise will default to wrapping around.
|
||||
static void ScrollUp(const MenuType type,const std::string&componentName,Data&returnData,const std::optional<std::string>wrapDestination="");
|
||||
//If a wrap destination is specified, will resolve the selection to that button when the bottom is reached, otherwise will default to wrapping around.
|
||||
static void ScrollDown(const MenuType type,const std::string&componentName,Data&returnData,const std::optional<std::string>wrapDestination="");
|
||||
private:
|
||||
Menu(vf2d pos,vf2d size);
|
||||
static MenuType lastMenuTypeCreated;
|
||||
|
@ -90,6 +90,9 @@ public:
|
||||
inline virtual void SetItem(std::variant<Item,std::weak_ptr<Item>>itemRef){
|
||||
this->itemRef=itemRef;
|
||||
}
|
||||
inline const std::variant<Item,std::weak_ptr<Item>>&GetItem()const{
|
||||
return itemRef;
|
||||
}
|
||||
protected:
|
||||
//DO NOT USE! Use MenuLabel::SetLabel() instead!
|
||||
inline virtual void SetLabel(std::string text){
|
||||
|
@ -68,6 +68,11 @@ protected:
|
||||
return geom2d::overlaps(geom2d::rect<float>{{},rect.size},geom2d::rect<float>{component.lock()->rect.pos+vf2d{2,2},component.lock()->rect.size-vf2d{2,2}});
|
||||
}
|
||||
public:
|
||||
enum ScrollResult{
|
||||
NOT_SCROLLED,
|
||||
SCROLLED,
|
||||
};
|
||||
|
||||
inline ScrollableWindowComponent(geom2d::rect<float>rect,ComponentAttr attributes=ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE)
|
||||
:MenuComponent(rect,"",[](MenuFuncData data){return true;},ButtonAttr::UNSELECTABLE|ButtonAttr::UNSELECTABLE_VIA_KEYBOARD){
|
||||
background=attributes&ComponentAttr::BACKGROUND;
|
||||
@ -139,10 +144,32 @@ public:
|
||||
if(size_t(prevIndex)!=size_t(selectionIndex)){Menu::menus[parentMenu]->SetSelection(components[size_t(selectionIndex)],false);}
|
||||
}
|
||||
|
||||
inline void IncreaseSelectionIndex(const float val){
|
||||
inline const size_t GetSelectionIndex()const{
|
||||
return selectionIndex;
|
||||
}
|
||||
|
||||
inline std::weak_ptr<MenuComponent>GetSelectedComponent(){
|
||||
return GetComponents().at(selectionIndex);
|
||||
}
|
||||
|
||||
inline ScrollResult IncreaseSelectionIndex(const float val){
|
||||
float prevIndex=selectionIndex;
|
||||
selectionIndex=std::clamp(selectionIndex+val,0.f,float(components.size()-1));
|
||||
if(size_t(prevIndex)!=size_t(selectionIndex)){Menu::menus[parentMenu]->SetSelection(components[size_t(selectionIndex)],false);}
|
||||
if(size_t(prevIndex)!=size_t(selectionIndex)){
|
||||
Menu::menus[parentMenu]->SetSelection(components[size_t(selectionIndex)],false);
|
||||
return SCROLLED;
|
||||
}
|
||||
return NOT_SCROLLED;
|
||||
}
|
||||
|
||||
inline ScrollResult DecreaseSelectionIndex(const float val){
|
||||
float prevIndex=selectionIndex;
|
||||
selectionIndex=std::clamp(selectionIndex-val,0.f,float(components.size()-1));
|
||||
if(size_t(prevIndex)!=size_t(selectionIndex)){
|
||||
Menu::menus[parentMenu]->SetSelection(components[size_t(selectionIndex)],false);
|
||||
return SCROLLED;
|
||||
}
|
||||
return NOT_SCROLLED;
|
||||
}
|
||||
protected:
|
||||
virtual inline vf2d GetScrollAmount()const{
|
||||
@ -402,6 +429,7 @@ public:
|
||||
button->renderInMain=false; //Now we are in control!
|
||||
button->parentComponent=DYNAMIC_POINTER_CAST<ScrollableWindowComponent>(Menu::menus[parentMenu]->components[this->GetName()]);
|
||||
button->disable=disable;
|
||||
button->name=key;
|
||||
|
||||
CalculateBounds();
|
||||
|
||||
|
@ -39,7 +39,7 @@ All rights reserved.
|
||||
#define VERSION_MAJOR 1
|
||||
#define VERSION_MINOR 3
|
||||
#define VERSION_PATCH 0
|
||||
#define VERSION_BUILD 11620
|
||||
#define VERSION_BUILD 11652
|
||||
|
||||
#define stringify(a) stringify_(a)
|
||||
#define stringify_(a) #a
|
||||
|
@ -417,6 +417,11 @@ Events
|
||||
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
|
||||
File[0] = rockland.ogg, 40%
|
||||
}
|
||||
Take Enchant
|
||||
{
|
||||
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
|
||||
File[0] = take_enchant.ogg, 80%
|
||||
}
|
||||
Toggle On
|
||||
{
|
||||
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
|
||||
|
BIN
Adventures in Lestoria/assets/sounds/take_enchant.ogg
Normal file
BIN
Adventures in Lestoria/assets/sounds/take_enchant.ogg
Normal file
Binary file not shown.
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user