Setup framework for scrollbar and buttons in ScrollableWindowComponent. Fixed a bug where disabled buttons would not increment selection check loop. CreateMenu function instead of creating pointer and returning, so windows can add stuff to menus easily.
This commit is contained in:
parent
b08002e61b
commit
ff3f4ba1c0
@ -1066,7 +1066,7 @@ void Crawler::RenderHud(){
|
||||
if("debug_player_info"_I){
|
||||
DrawShadowStringDecal({0,128},player->GetPos().str());
|
||||
DrawShadowStringDecal({0,136},"Spd: "+std::to_string(player->GetMoveSpdMult()));
|
||||
DrawShadowStringDecal({0,4},"Selection: "+Menu::menus[INVENTORY]->selection.str());
|
||||
DrawShadowStringDecal({0,1},"Selection: "+Menu::menus[INVENTORY]->selection.str());
|
||||
DrawShadowStringDecal({0,12},"Button Hold Time: "+std::to_string(Menu::menus[INVENTORY]->buttonHoldTime));
|
||||
}
|
||||
}
|
||||
@ -1752,9 +1752,17 @@ void Crawler::InitializeGraphics(){
|
||||
|
||||
for(auto&val:DATA["Images"].GetKeys()){
|
||||
std::string key=val.first;
|
||||
std::string imgFile=DATA["Images"][key].GetString();
|
||||
std::string imgFile=DATA["Images"][key].GetString(0);
|
||||
std::cout<<"Loading image "+imgFile+"..."<<std::endl;
|
||||
if(!GFX.count(imgFile)&&GFX[imgFile].Load("GFX_Prefix"_S+imgFile,nullptr,false,false)!=rcode::OK){
|
||||
bool filtering=false;
|
||||
bool clamping=false;
|
||||
if(DATA["Images"][key].GetValueCount()>1){
|
||||
filtering=bool(DATA["Images"][key].GetInt(1));
|
||||
}
|
||||
if(DATA["Images"][key].GetValueCount()>2){
|
||||
clamping=bool(DATA["Images"][key].GetInt(2));
|
||||
}
|
||||
if(!GFX.count(imgFile)&&GFX[imgFile].Load("GFX_Prefix"_S+imgFile,nullptr,filtering,clamping)!=rcode::OK){
|
||||
std::cout<<" WARNING! Failed to load "+imgFile+"!";
|
||||
throw;
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
INCLUDE_GFX
|
||||
typedef Attribute A;
|
||||
|
||||
Menu*Menu::InitializeInventoryWindow(){
|
||||
void Menu::InitializeInventoryWindow(){
|
||||
constexpr int invWidth=5;
|
||||
constexpr int initialInvHeight=3;
|
||||
|
||||
@ -19,11 +19,11 @@ Menu*Menu::InitializeInventoryWindow(){
|
||||
constexpr int buttonSize=24;
|
||||
constexpr int totalSpacing=buttonSize+itemSpacing;
|
||||
|
||||
vf2d windowSize={totalSpacing*invWidth-itemSpacing+1,totalSpacing*(3+1)-itemSpacing+24};
|
||||
vf2d windowSize={totalSpacing*invWidth-itemSpacing+2+24,totalSpacing*(3+1)-itemSpacing+24}; //Need space for the button.
|
||||
|
||||
Menu*inventoryWindow=new Menu(CENTERED,windowSize);
|
||||
Menu*inventoryWindow=CreateMenu(INVENTORY,CENTERED,windowSize);
|
||||
|
||||
ScrollableWindowComponent*inventory=new ScrollableWindowComponent(INVENTORY,{{0,0},{windowSize.x,totalSpacing*3-itemSpacing}},nullptr,[](MenuFuncData data){});
|
||||
ScrollableWindowComponent*inventory=new ScrollableWindowComponent(INVENTORY,{{1,0},{windowSize.x,totalSpacing*3-itemSpacing}},nullptr,[](MenuFuncData data){});
|
||||
inventoryWindow->AddComponent("inventory",inventory);
|
||||
|
||||
MenuFunc useItemFunc=[](MenuFuncData data){
|
||||
@ -43,6 +43,4 @@ Menu*Menu::InitializeInventoryWindow(){
|
||||
inventoryWindow->AddComponent("itemName",itemNameLabel);
|
||||
MenuLabel*itemDescriptionLabel=new MenuLabel{INVENTORY,geom2d::rect<float>(vf2d{2,initialInvHeight*totalSpacing+itemSpacing},{windowSize.x-4,windowSize.y-108}),"",true,true};
|
||||
inventoryWindow->AddComponent("itemDescription",itemDescriptionLabel);
|
||||
|
||||
return inventoryWindow;
|
||||
}
|
@ -15,8 +15,6 @@ extern vi2d WINDOW_SIZE;
|
||||
|
||||
typedef Attribute A;
|
||||
|
||||
Menu::Menu(){}
|
||||
|
||||
Menu::Menu(vf2d pos,vf2d size)
|
||||
:pos(pos==CENTERED?WINDOW_SIZE/2-size/2:vi2d{pos}),size(size){
|
||||
r.Create(size.x,size.y);
|
||||
@ -25,19 +23,28 @@ Menu::Menu(vf2d pos,vf2d size)
|
||||
|
||||
void Menu::InitializeMenus(){
|
||||
stack.reserve(32);
|
||||
menus[TEST]=InitializeTestMenu();
|
||||
menus[TEST_2]=InitializeTestSubMenu();
|
||||
menus[INVENTORY]=InitializeInventoryWindow();
|
||||
InitializeTestMenu();
|
||||
InitializeTestSubMenu();
|
||||
InitializeInventoryWindow();
|
||||
|
||||
for(MenuType type=TEST;type<MenuType::ENUM_END;type=MenuType(int(type+1))){
|
||||
if(menus.count(type)==0){
|
||||
std::cout<<"WARNING! Menu Type "<<type<<" does not exist!"<<std::endl;
|
||||
throw;
|
||||
}
|
||||
for(auto&key:menus[type]->components){
|
||||
MenuComponent*component=key.second;
|
||||
component->AfterCreate();
|
||||
}
|
||||
menus[type]->components.SetInitialized(); //Lock all known components to prevent invalid access.
|
||||
}
|
||||
}
|
||||
|
||||
Menu*Menu::CreateMenu(MenuType type,vf2d pos,vf2d size){
|
||||
menus[type]=new Menu(pos,size);
|
||||
return menus.at(type);
|
||||
}
|
||||
|
||||
void Menu::AddComponent(std::string key,MenuComponent*button){
|
||||
if(button->selectable){
|
||||
buttons[button->rect.pos.y].push_back(button);
|
||||
@ -59,13 +66,16 @@ void Menu::CheckClickAndPerformMenuSelect(Crawler*game){
|
||||
|
||||
void Menu::HoverMenuSelect(Crawler*game){
|
||||
if(selection==vi2d{-1,-1}||buttons[selection.y][selection.x]->disabled)return;
|
||||
if(buttons[selection.y][selection.x]->draggable)
|
||||
if(buttonHoldTime<"ThemeGlobal.MenuHoldTime"_F)CheckClickAndPerformMenuSelect(game);
|
||||
else{
|
||||
if(buttons[selection.y][selection.x]->draggable){
|
||||
if(buttonHoldTime<"ThemeGlobal.MenuHoldTime"_F){
|
||||
CheckClickAndPerformMenuSelect(game);
|
||||
}else{
|
||||
draggingComponent=buttons[selection.y][selection.x]->PickUpDraggableItem();
|
||||
buttonHoldTime=0;
|
||||
}
|
||||
else CheckClickAndPerformMenuSelect(game);
|
||||
}else{
|
||||
CheckClickAndPerformMenuSelect(game);
|
||||
}
|
||||
}
|
||||
|
||||
void Menu::MenuSelect(Crawler*game){
|
||||
@ -110,8 +120,8 @@ void Menu::Update(Crawler*game){
|
||||
selection.y=key.first;
|
||||
selection.x=index;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -161,6 +171,11 @@ void Menu::Draw(Crawler*game){
|
||||
Pixel::Mode prevMode=game->GetPixelMode();
|
||||
game->SetPixelMode(Pixel::MASK);
|
||||
game->Clear(BLANK);
|
||||
for(auto&component:displayComponents){
|
||||
if(component->renderInMain){
|
||||
component->_Draw(game,{0,0},this==Menu::stack.back());
|
||||
}
|
||||
}
|
||||
for(auto&key:buttons){
|
||||
for(auto&button:key.second){
|
||||
if(button->renderInMain){
|
||||
@ -168,15 +183,15 @@ void Menu::Draw(Crawler*game){
|
||||
}
|
||||
}
|
||||
}
|
||||
for(auto&component:displayComponents){
|
||||
if(component->renderInMain){
|
||||
component->_Draw(game,{0,0},this==Menu::stack.back());
|
||||
}
|
||||
}
|
||||
game->SetPixelMode(prevMode);
|
||||
game->SetDrawTarget(nullptr);
|
||||
r.Decal()->Update();
|
||||
game->DrawDecal(pos,r.Decal());
|
||||
for(auto&component:displayComponents){
|
||||
if(component->renderInMain){
|
||||
component->_DrawDecal(game,pos,this==Menu::stack.back());
|
||||
}
|
||||
}
|
||||
for(auto&key:buttons){
|
||||
for(auto&button:key.second){
|
||||
if(button->renderInMain){
|
||||
@ -184,11 +199,6 @@ void Menu::Draw(Crawler*game){
|
||||
}
|
||||
}
|
||||
}
|
||||
for(auto&component:displayComponents){
|
||||
if(component->renderInMain){
|
||||
component->_DrawDecal(game,pos,this==Menu::stack.back());
|
||||
}
|
||||
}
|
||||
|
||||
if(GetCurrentTheme().IsScaled()){
|
||||
DrawScaledWindowBorder(game,pos);
|
||||
@ -364,7 +374,9 @@ void Menu::KeyboardButtonNavigation(Crawler*game,vf2d menuPos){
|
||||
}
|
||||
}
|
||||
if(prevSelection!=selection){
|
||||
if(selection!=vi2d{-1,-1}&&buttons[selection.y][selection.x]->disabled)selection=prevSelection;
|
||||
if(selection!=vi2d{-1,-1}&&buttons[selection.y][selection.x]->disabled){
|
||||
selection=prevSelection;
|
||||
}
|
||||
// If the new selection of a button on this frame is disabled for some reason, we need to go back to what we had selected before.
|
||||
}
|
||||
}
|
||||
|
@ -34,8 +34,9 @@ class Menu:IAttributable{
|
||||
MenuComponent*draggingComponent=nullptr;
|
||||
Renderable r,overlay;
|
||||
public:
|
||||
Menu();
|
||||
Menu(vf2d pos,vf2d size);
|
||||
//The constructor is private. Use CreateMenu() instead!
|
||||
Menu()=default;
|
||||
virtual ~Menu()=default;
|
||||
void AddComponent(std::string key,MenuComponent*button);
|
||||
void Update(Crawler*game);
|
||||
void Draw(Crawler*game);
|
||||
@ -51,12 +52,15 @@ public:
|
||||
vf2d size; //Size in tiles (24x24), every menu will be tile-based
|
||||
|
||||
private:
|
||||
Menu(vf2d pos,vf2d size);
|
||||
void HoverMenuSelect(Crawler*game);
|
||||
void MenuSelect(Crawler*game);
|
||||
void CheckClickAndPerformMenuSelect(Crawler*game);
|
||||
static Menu*InitializeTestMenu();
|
||||
static Menu*InitializeTestSubMenu();
|
||||
static Menu*InitializeInventoryWindow();
|
||||
//Mandatory before any menu operations! This creates and sets up the menu in memory.
|
||||
static Menu*CreateMenu(MenuType type,vf2d pos,vf2d size);
|
||||
static void InitializeTestMenu();
|
||||
static void InitializeTestSubMenu();
|
||||
static void InitializeInventoryWindow();
|
||||
//X (0-3), Y (0-2) for specific 9-patch tile (tiled version).
|
||||
static Renderable&GetPatchPart(int x,int y);
|
||||
|
||||
|
@ -7,6 +7,8 @@ MenuComponent::MenuComponent(MenuType parent,geom2d::rect<float>rect,std::string
|
||||
MenuComponent::MenuComponent(MenuType parent,geom2d::rect<float>rect,std::string label,MenuType menuDest,MenuFunc onClick,bool selectable)
|
||||
:parentMenu(parent),rect(rect),label(label),menuDest(menuDest),onClick(onClick),hoverEffect(0),selectable(selectable){}
|
||||
|
||||
void MenuComponent::AfterCreate(){}
|
||||
|
||||
void MenuComponent::Update(Crawler*game){
|
||||
if(hovered){
|
||||
hoverEffect=std::min("ThemeGlobal.HighlightTime"_F,hoverEffect+game->GetElapsedTime());
|
||||
|
@ -27,6 +27,7 @@ protected:
|
||||
virtual void Draw(Crawler*game,vf2d parentPos,bool focused);
|
||||
virtual void DrawDecal(Crawler*game,vf2d parentPos,bool focused);
|
||||
virtual bool GetHoverState(Crawler*game,MenuComponent*child);
|
||||
virtual void AfterCreate(); //Called after the creation of all menus finish.
|
||||
public:
|
||||
MenuComponent(MenuType parent,geom2d::rect<float>rect,std::string label,MenuFunc onClick,bool selectable=true);
|
||||
MenuComponent(MenuType parent,geom2d::rect<float>rect,std::string label,MenuType menuDest,MenuFunc onClick,bool selectable=true);
|
||||
|
@ -9,6 +9,8 @@ class ScrollableWindowComponent:public MenuComponent{
|
||||
protected:
|
||||
Renderable r;
|
||||
std::vector<MenuComponent*>components;
|
||||
MenuComponent*upButton=nullptr;
|
||||
MenuComponent*downButton=nullptr;
|
||||
geom2d::rect<float>bounds; //It's for the scrollbar.
|
||||
private:
|
||||
inline bool OnScreen(MenuComponent*component){
|
||||
@ -19,6 +21,17 @@ public:
|
||||
:MenuComponent(parent,rect,"",onClick,false){
|
||||
r.Create(rect.size.x,rect.size.y);
|
||||
}
|
||||
|
||||
virtual inline ~ScrollableWindowComponent(){
|
||||
|
||||
}
|
||||
private:
|
||||
virtual inline void AfterCreate()override{
|
||||
upButton=new MenuComponent(parentMenu,{vf2d{rect.size.x-12,0},{12,12}},"^",[](MenuFuncData dat){std::cout<<"Clicked"<<std::endl;});
|
||||
downButton=new MenuComponent(parentMenu,{rect.size-vf2d{12,12},{12,12}},"v",[](MenuFuncData dat){});
|
||||
Menu::menus[parentMenu]->AddComponent("scrollableWindowButton"+upButton->rect.pos.str()+"_"+upButton->rect.size.str(),upButton);
|
||||
Menu::menus[parentMenu]->AddComponent("scrollableWindowButton"+downButton->rect.pos.str()+"_"+downButton->rect.size.str(),downButton);
|
||||
}
|
||||
protected:
|
||||
virtual inline void Update(Crawler*game)override{
|
||||
MenuComponent::Update(game);
|
||||
@ -42,20 +55,23 @@ protected:
|
||||
game->SetDrawTarget(r.Sprite());
|
||||
game->Clear(BLANK);
|
||||
for(MenuComponent*component:components){
|
||||
component->_Draw(game,V(A::SCROLL_OFFSET),focused);
|
||||
component->_Draw(game,rect.pos+V(A::SCROLL_OFFSET),focused);
|
||||
}
|
||||
game->SetDrawTarget(prevDrawTarget);
|
||||
game->DrawSprite(parentPos,r.Sprite());
|
||||
}
|
||||
virtual inline void DrawDecal(Crawler*game,vf2d parentPos,bool focused)override{
|
||||
MenuComponent::DrawDecal(game,parentPos,focused);
|
||||
game->DrawRectDecal(parentPos,rect.size);
|
||||
game->DrawRectDecal(rect.pos+parentPos,rect.size);
|
||||
for(MenuComponent*component:components){
|
||||
component->_DrawDecal(game,parentPos+V(A::SCROLL_OFFSET),focused);
|
||||
component->_DrawDecal(game,rect.pos+parentPos+V(A::SCROLL_OFFSET),focused);
|
||||
}
|
||||
game->DrawRectDecal(rect.pos+parentPos+vf2d{rect.size.x-12,0},{12,12});
|
||||
game->DrawRectDecal(rect.pos+parentPos+vf2d{rect.size.x-12,12},{12,rect.size.y-24});
|
||||
game->DrawRectDecal(rect.pos+parentPos+rect.size-vf2d{12,12},{12,12});
|
||||
}
|
||||
virtual bool GetHoverState(Crawler*game,MenuComponent*child)override{
|
||||
return geom2d::overlaps(geom2d::rect<float>{Menu::menus[parentMenu]->pos+child->rect.pos+V(A::SCROLL_OFFSET),child->rect.size},game->GetMousePos());
|
||||
return geom2d::overlaps(geom2d::rect<float>{Menu::menus[parentMenu]->pos+rect.pos+child->rect.pos+V(A::SCROLL_OFFSET),child->rect.size},game->GetMousePos());
|
||||
}
|
||||
public:
|
||||
void inline AddComponent(Menu*parentMenu,std::string key,MenuComponent*button){
|
||||
|
@ -1,8 +1,8 @@
|
||||
#include "Crawler.h"
|
||||
#include "MenuComponent.h"
|
||||
|
||||
Menu*Menu::InitializeTestMenu(){
|
||||
Menu*testMenu=new Menu(CENTERED,{24*8,24*6});
|
||||
void Menu::InitializeTestMenu(){
|
||||
Menu*testMenu=CreateMenu(TEST,CENTERED,{24*8,24*6});
|
||||
|
||||
MenuFunc quitWindow=[](MenuFuncData data){
|
||||
data.menu.stack.clear();
|
||||
@ -22,5 +22,4 @@ Menu*Menu::InitializeTestMenu(){
|
||||
|
||||
testMenu->AddComponent("Open SubMenu",new MenuComponent(TEST,{{24*2,24*4.5},{24*4,24*1}},"Open Another\n Menu",TEST_2,doNothing));
|
||||
|
||||
return testMenu;
|
||||
}
|
@ -8,8 +8,8 @@
|
||||
INCLUDE_GFX
|
||||
typedef Attribute A;
|
||||
|
||||
Menu*Menu::InitializeTestSubMenu(){
|
||||
Menu*testSubMenu=new Menu({30,30},{24*4,24*5});
|
||||
void Menu::InitializeTestSubMenu(){
|
||||
Menu*testSubMenu=CreateMenu(TEST_2,{30,30},{24*4,24*5});
|
||||
|
||||
MenuFunc goBack=[](MenuFuncData data){
|
||||
data.menu.stack.pop_back();
|
||||
@ -61,6 +61,4 @@ Menu*Menu::InitializeTestSubMenu(){
|
||||
};
|
||||
|
||||
testSubMenu->AddComponent("NEXT_THEME",new MenuComponent(TEST_2,{{24*3.5,24*3},{24*1,24*1}},">",themeNext));
|
||||
|
||||
return testSubMenu;
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 2
|
||||
#define VERSION_PATCH 0
|
||||
#define VERSION_BUILD 2026
|
||||
#define VERSION_BUILD 2066
|
||||
|
||||
#define stringify(a) stringify_(a)
|
||||
#define stringify_(a) #a
|
||||
|
@ -55,7 +55,7 @@ debug_access_options = 0
|
||||
debug_map_load_info = 0
|
||||
|
||||
# Shows extra info about the player on the HUD
|
||||
debug_player_info = 0
|
||||
debug_player_info = 1
|
||||
|
||||
# Shows collision boxes of tiles.
|
||||
debug_collision_boxes = 0
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.3 KiB |
BIN
Crawler/assets/knight_full_render1.png
Normal file
BIN
Crawler/assets/knight_full_render1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.4 KiB |
Loading…
x
Reference in New Issue
Block a user