Add destructors for all menu components and sub components. Finish menu navigation for class selection window and class info window.

pull/28/head
sigonasr2 1 year ago
parent 5d939e866f
commit 800a5767f2
  1. 59
      Crawler/ClassSelectionWindow.cpp
  2. 2
      Crawler/Crawler.cpp
  3. 22
      Crawler/Menu.cpp
  4. 5
      Crawler/Menu.h
  5. 18
      Crawler/MenuComponent.cpp
  6. 1
      Crawler/MenuComponent.h
  7. 5
      Crawler/ScrollableWindowComponent.h
  8. 2
      Crawler/State_MainMenu.cpp
  9. 2
      Crawler/Version.h
  10. 1
      Crawler/assets/config/gfx/gfx.txt

@ -8,7 +8,64 @@ INCLUDE_game
typedef Attribute A;
void Menu::InitializeClassSelectionWindow(){
Menu*classSelectionWindow=CreateMenu(CLASS_SELECTION,CENTERED,game->GetScreenSize()-vi2d{4,4});
Menu*classSelectionWindow=CreateMenu(CLASS_SELECTION,CENTERED,game->GetScreenSize()-vi2d{24,24});
classSelectionWindow->S(A::CLASS_SELECTION)="Warrior"; //Default selected class.
vf2d outlineSize=classSelectionWindow->size-vf2d{13,13};
MenuLabel*outline=new MenuLabel(CLASS_SELECTION,{{4,4},outlineSize},"",1,true,false,true,false);
classSelectionWindow->AddComponent("Outline Border",outline);
vf2d buttonPadding={2,2};
vf2d buttonSize={outlineSize.y/3-buttonPadding.y*3,outlineSize.y/3-buttonPadding.y*3};
float buttonTotalWidth=(buttonSize.x+buttonPadding.x)*3;
vf2d buttonStartPos=outline->GetPos()+vf2d{outlineSize.x/2,outlineSize.y/3}-vf2d{buttonTotalWidth/2,0};
MenuComponent*warriorButton=new MenuComponent(CLASS_SELECTION,{buttonStartPos+(buttonSize+buttonPadding)*vf2d{0,0},buttonSize},Warrior::name,CLASS_INFO,
[](MenuFuncData data){
data.menu.S(A::CLASS_SELECTION)=Warrior::name;
delete Menu::menus[CLASS_INFO];
Menu::InitializeClassInfoWindow();
});
MenuComponent*rangerButton=new MenuComponent(CLASS_SELECTION,{buttonStartPos+(buttonSize+buttonPadding)*vf2d{1,0},buttonSize},Ranger::name,CLASS_INFO,
[](MenuFuncData data){
data.menu.S(A::CLASS_SELECTION)=Ranger::name;
delete Menu::menus[CLASS_INFO];
Menu::InitializeClassInfoWindow();
});
MenuComponent*wizardButton=new MenuComponent(CLASS_SELECTION,{buttonStartPos+(buttonSize+buttonPadding)*vf2d{2,0},buttonSize},Wizard::name,CLASS_INFO,
[](MenuFuncData data){
data.menu.S(A::CLASS_SELECTION)=Wizard::name;
delete Menu::menus[CLASS_INFO];
Menu::InitializeClassInfoWindow();
});
MenuComponent*thiefButton=new MenuComponent(CLASS_SELECTION,{buttonStartPos+(buttonSize+buttonPadding)*vf2d{0,1},buttonSize},Thief::name,CLASS_INFO,
[](MenuFuncData data){
data.menu.S(A::CLASS_SELECTION)=Thief::name;
delete Menu::menus[CLASS_INFO];
Menu::InitializeClassInfoWindow();
});
MenuComponent*trapperButton=new MenuComponent(CLASS_SELECTION,{buttonStartPos+(buttonSize+buttonPadding)*vf2d{1,1},buttonSize},Trapper::name,CLASS_INFO,
[](MenuFuncData data){
data.menu.S(A::CLASS_SELECTION)=Trapper::name;
delete Menu::menus[CLASS_INFO];
Menu::InitializeClassInfoWindow();
});
MenuComponent*witchButton=new MenuComponent(CLASS_SELECTION,{buttonStartPos+(buttonSize+buttonPadding)*vf2d{2,1},buttonSize},Witch::name,CLASS_INFO,
[](MenuFuncData data){
data.menu.S(A::CLASS_SELECTION)=Witch::name;
delete Menu::menus[CLASS_INFO];
Menu::InitializeClassInfoWindow();
});
classSelectionWindow->AddComponent("Warrior Button",warriorButton);
classSelectionWindow->AddComponent("Ranger Button",rangerButton);
classSelectionWindow->AddComponent("Wizard Button",wizardButton);
classSelectionWindow->AddComponent("Thief Button",thiefButton);
classSelectionWindow->AddComponent("Trapper Button",trapperButton);
classSelectionWindow->AddComponent("Witch Button",witchButton);
}

@ -107,6 +107,7 @@ bool Crawler::OnUserCreate(){
ItemInfo::InitializeItems();
InitializeGraphics();
InitializeClasses();
Menu::InitializeMenus();
@ -138,7 +139,6 @@ bool Crawler::OnUserCreate(){
view=TileTransformedView{GetScreenSize(),{1,1}};
LoadLevel(LEVEL_NAMES["starting_map"_S]);
InitializeClasses();
ChangePlayerClass(WARRIOR);
GameState::Initialize();

@ -13,6 +13,7 @@ std::string Menu::themeSelection="BlueDefault";
safeunorderedmap<std::string,Theme>Menu::themes;
safemap<ITCategory,std::vector<MenuComponent*>>Menu::inventoryListeners;
const vf2d Menu::CENTERED = {-456,-456};
std::vector<MenuComponent*>Menu::unhandledComponents;
INCLUDE_GFX
extern vi2d WINDOW_SIZE;
@ -25,6 +26,12 @@ Menu::Menu(vf2d pos,vf2d size)
overlay.Create(WINDOW_SIZE.x,WINDOW_SIZE.y);
}
Menu::~Menu(){
for(auto key:components){
delete key.second;
}
}
void Menu::InitializeMenus(){
stack.reserve(32);
InitializeTestMenu();
@ -47,6 +54,18 @@ void Menu::InitializeMenus(){
component->AfterCreate();
}
}
if(Menu::unhandledComponents.size()>0){
std::cout<<"WARNING! There are "<<Menu::unhandledComponents.size()<<" components that were not added to any Menu! These have been leaked and should not be happening!"<<std::endl;
std::cout<<"See below for a report of unhandled components:"<<std::endl;
int count=0;
for(MenuComponent*component:Menu::unhandledComponents){
std::cout<<"\tComponent "<<(count+1)<<": "<<std::endl;
std::cout<<"\t-"<<component->name<<std::endl;
count++;
}
throw;
}
}
Menu*Menu::CreateMenu(MenuType type,vf2d pos,vf2d size){
@ -95,6 +114,7 @@ void Menu::AddComponent(std::string key,MenuComponent*button){
components.Unlock(); //It's possible we can add a component later on, so we will make sure we remove the lock first.
components[key]=button;
components.SetInitialized();
std::erase_if(Menu::unhandledComponents,[&](MenuComponent*b1){return b1==button;});
}
void Menu::CheckClickAndPerformMenuSelect(Crawler*game){
@ -119,6 +139,7 @@ void Menu::HoverMenuSelect(Crawler*game){
void Menu::MenuSelect(Crawler*game){
if(selection==vi2d{-1,-1}||buttons[selection.y][selection.x]->disabled)return;
buttons[selection.y][selection.x]->onClick(MenuFuncData{*this,game,buttons[selection.y][selection.x]});
if(buttons[selection.y][selection.x]->menuDest!=MenuType::ENUM_END){
if(stack.size()<32){
stack.push_back(menus[buttons[selection.y][selection.x]->menuDest]);//Navigate to the next menu.
@ -127,7 +148,6 @@ void Menu::MenuSelect(Crawler*game){
throw;
}
}
buttons[selection.y][selection.x]->onClick(MenuFuncData{*this,game,buttons[selection.y][selection.x]});
}
void Menu::Update(Crawler*game){

@ -27,7 +27,6 @@ class Menu:IAttributable{
friend class ItemInfo;
float buttonHoldTime=0;
std::vector<MenuComponent*>displayComponents; //Comp.onents that are only for displaying purposes.
vi2d selection={-1,-1};
vi2d lastActiveMousePos={};
@ -37,7 +36,7 @@ class Menu:IAttributable{
public:
//The constructor is private. Use CreateMenu() instead!
Menu()=default;
virtual ~Menu()=default;
~Menu();
void AddComponent(std::string key,MenuComponent*button);
void Update(Crawler*game);
void Draw(Crawler*game);
@ -47,8 +46,10 @@ public:
static std::vector<Menu*>stack;
static std::string themeSelection;
static safeunorderedmap<std::string,Theme>themes;
static std::vector<MenuComponent*>unhandledComponents; //This list contains MenuComponents that are created and haven't been assigned via AddComponent. If we get to the end of menu initialization and there are any components in this vector, we have leaked memory and will report this.
static const vf2d CENTERED;
safemap<std::string,MenuComponent*>components; //A friendly way to interrogate any component we are interested in.
std::vector<MenuComponent*>displayComponents; //Components that are only for displaying purposes.
static std::map<MenuType,Menu*>menus;
vf2d pos; //Specify the upper-left corner of the window. Using CENTERED will always put this where the upper-left corner would center the window.
vf2d size; //Size in tiles (24x24), every menu will be tile-based

@ -4,11 +4,27 @@
typedef Attribute A;
MenuComponent::MenuComponent(MenuType parent,geom2d::rect<float>rect,std::string label,MenuFunc onClick,bool selectable,bool selectableViaKeyboard)
:parentMenu(parent),rect(rect),label(label),menuDest(MenuType::ENUM_END),onClick(onClick),hoverEffect(0),selectable(selectable),selectableViaKeyboard(selectableViaKeyboard){}
:parentMenu(parent),rect(rect),label(label),menuDest(MenuType::ENUM_END),onClick(onClick),hoverEffect(0),selectable(selectable),selectableViaKeyboard(selectableViaKeyboard){
Menu::unhandledComponents.push_back(this);
}
MenuComponent::MenuComponent(MenuType parent,geom2d::rect<float>rect,std::string label,MenuType menuDest,MenuFunc onClick,bool selectable,bool selectableViaKeyboard)
:MenuComponent(parent,rect,label,onClick,selectable,selectableViaKeyboard){
this->menuDest=menuDest;
Menu::unhandledComponents.push_back(this);
}
MenuComponent::~MenuComponent(){
Menu*pMenu=Menu::menus[parentMenu];
for(auto key:pMenu->buttons){
std::vector<MenuComponent*>&components=key.second;
std::erase_if(components,[&](MenuComponent*component){return component==this;});
}
for(auto key:pMenu->keyboardButtons){
std::vector<MenuComponent*>&components=key.second;
std::erase_if(components,[&](MenuComponent*component){return component==this;});
}
std::erase_if(pMenu->displayComponents,[&](MenuComponent*component){return component==this;});
}
void MenuComponent::AfterCreate(){}

@ -37,6 +37,7 @@ protected:
public:
MenuComponent(MenuType parent,geom2d::rect<float>rect,std::string label,MenuFunc onClick,bool selectable=true,bool selectableViaKeyboard=true);
MenuComponent(MenuType parent,geom2d::rect<float>rect,std::string label,MenuType menuDest,MenuFunc onClick,bool selectable=true,bool selectableViaKeyboard=true);
virtual ~MenuComponent();
void _Update(Crawler*game);
void _Draw(Crawler*game,vf2d parentPos,bool focused);
void _DrawDecal(Crawler*game,vf2d parentPos,bool focused);

@ -28,7 +28,10 @@ public:
}
virtual inline ~ScrollableWindowComponent(){
MenuComponent::~MenuComponent();
for(MenuComponent*component:components){
delete component;
}
}
protected:
virtual inline void AfterCreate()override{

@ -3,7 +3,7 @@
#include "Menu.h"
void State_MainMenu::OnStateChange(GameState*prevState){
Menu::OpenMenu(MenuType::CLASS_INFO);
Menu::OpenMenu(MenuType::CLASS_SELECTION);
};
void State_MainMenu::OnUserUpdate(Crawler*game){

@ -2,7 +2,7 @@
#define VERSION_MAJOR 0
#define VERSION_MINOR 2
#define VERSION_PATCH 0
#define VERSION_BUILD 2306
#define VERSION_BUILD 2329
#define stringify(a) stringify_(a)
#define stringify_(a) #a

@ -57,4 +57,5 @@ Images
# Full Class Icons
GFX_Warrior_Full = knight_full_render1.png
GFX_Unknown_Full = unknown_full_render.png
}
Loading…
Cancel
Save