Implement parent component hover state handling.

pull/28/head
sigonasr2 1 year ago
parent 1c4ec84d75
commit 18db45e6c3
  1. 37
      Crawler/Menu.cpp
  2. 31
      Crawler/MenuComponent.cpp
  3. 13
      Crawler/MenuComponent.h
  4. 24
      Crawler/ScrollableWindowComponent.h
  5. 2
      Crawler/Version.h

@ -56,7 +56,7 @@ void Menu::CheckClickAndPerformMenuSelect(Crawler*game){
} }
void Menu::HoverMenuSelect(Crawler*game){ void Menu::HoverMenuSelect(Crawler*game){
if(selection==vi2d{-1,-1})return; if(selection==vi2d{-1,-1}||buttons[selection.y][selection.x]->disabled)return;
if(buttons[selection.y][selection.x]->draggable) if(buttons[selection.y][selection.x]->draggable)
if(buttonHoldTime<"ThemeGlobal.MenuHoldTime"_F)CheckClickAndPerformMenuSelect(game); if(buttonHoldTime<"ThemeGlobal.MenuHoldTime"_F)CheckClickAndPerformMenuSelect(game);
else{ else{
@ -67,7 +67,7 @@ void Menu::HoverMenuSelect(Crawler*game){
} }
void Menu::MenuSelect(Crawler*game){ void Menu::MenuSelect(Crawler*game){
if(selection==vi2d{-1,-1})return; 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]}); 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(buttons[selection.y][selection.x]->menuDest!=MenuType::ENUM_END){
if(stack.size()<32){ if(stack.size()<32){
@ -90,7 +90,9 @@ void Menu::Update(Crawler*game){
for(auto&key:buttons){ for(auto&key:buttons){
for(auto&button:key.second){ for(auto&button:key.second){
button->hovered=false; if(!button->disabled){
button->hovered=false;
}
} }
} }
if(!MOUSE_NAVIGATION){ if(!MOUSE_NAVIGATION){
@ -99,12 +101,14 @@ void Menu::Update(Crawler*game){
for(auto&key:buttons){ for(auto&key:buttons){
int index=0; int index=0;
for(auto&button:key.second){ for(auto&button:key.second){
if(geom2d::overlaps(geom2d::rect<float>{button->rect.pos+pos,button->rect.size},game->GetMousePos())){ if(!button->disabled){
button->hovered=true; if(button->GetHoverState(game)){
selection.y=key.first; button->hovered=true;
selection.x=index; selection.y=key.first;
selection.x=index;
}
index++;
} }
index++;
} }
} }
} }
@ -132,13 +136,13 @@ void Menu::Update(Crawler*game){
for(auto&key:buttons){ for(auto&key:buttons){
for(auto&button:key.second){ for(auto&button:key.second){
if(button->renderInMain){ if(button->renderInMain){
button->Update(game); button->_Update(game);
} }
} }
} }
for(auto&component:displayComponents){ for(auto&component:displayComponents){
if(component->renderInMain){ if(component->renderInMain){
component->Update(game); component->_Update(game);
} }
} }
}; };
@ -157,13 +161,13 @@ void Menu::Draw(Crawler*game){
for(auto&key:buttons){ for(auto&key:buttons){
for(auto&button:key.second){ for(auto&button:key.second){
if(button->renderInMain){ if(button->renderInMain){
button->Draw(game,{0,0},this==Menu::stack.back()); button->_Draw(game,{0,0},this==Menu::stack.back());
} }
} }
} }
for(auto&component:displayComponents){ for(auto&component:displayComponents){
if(component->renderInMain){ if(component->renderInMain){
component->Draw(game,{0,0},this==Menu::stack.back()); component->_Draw(game,{0,0},this==Menu::stack.back());
} }
} }
game->SetPixelMode(prevMode); game->SetPixelMode(prevMode);
@ -173,13 +177,13 @@ void Menu::Draw(Crawler*game){
for(auto&key:buttons){ for(auto&key:buttons){
for(auto&button:key.second){ for(auto&button:key.second){
if(button->renderInMain){ if(button->renderInMain){
button->DrawDecal(game,pos,this==Menu::stack.back()); button->_DrawDecal(game,pos,this==Menu::stack.back());
} }
} }
} }
for(auto&component:displayComponents){ for(auto&component:displayComponents){
if(component->renderInMain){ if(component->renderInMain){
component->DrawDecal(game,pos,this==Menu::stack.back()); component->_DrawDecal(game,pos,this==Menu::stack.back());
} }
} }
@ -220,6 +224,7 @@ void Menu::OpenMenu(MenuType menu){
} }
void Menu::KeyboardButtonNavigation(Crawler*game,vf2d menuPos){ void Menu::KeyboardButtonNavigation(Crawler*game,vf2d menuPos){
vi2d prevSelection=selection;
if(game->GetKey(RIGHT).bPressed){ if(game->GetKey(RIGHT).bPressed){
if(selection==vi2d{-1,-1})return; if(selection==vi2d{-1,-1})return;
MOUSE_NAVIGATION=false; MOUSE_NAVIGATION=false;
@ -345,6 +350,10 @@ void Menu::KeyboardButtonNavigation(Crawler*game,vf2d menuPos){
buttonHoldTime=0; buttonHoldTime=0;
} }
} }
if(prevSelection!=selection){
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.
}
} }
void Menu::DrawScaledWindowBorder(Crawler*game,vf2d menuPos){ void Menu::DrawScaledWindowBorder(Crawler*game,vf2d menuPos){

@ -15,6 +15,12 @@ void MenuComponent::Update(Crawler*game){
} }
} }
void MenuComponent::_Update(Crawler*game){
if(!disabled){
Update(game);
}
}
void MenuComponent::Draw(Crawler*game,vf2d parentPos,bool focused){ void MenuComponent::Draw(Crawler*game,vf2d parentPos,bool focused){
game->FillRect(rect.pos+parentPos,rect.size,PixelLerp(Menu::themes[Menu::themeSelection].GetButtonCol(),Menu::themes[Menu::themeSelection].GetHighlightCol(),hoverEffect/"ThemeGlobal.HighlightTime"_F)*(focused?1:"ThemeGlobal.MenuUnfocusedColorMult"_F)); game->FillRect(rect.pos+parentPos,rect.size,PixelLerp(Menu::themes[Menu::themeSelection].GetButtonCol(),Menu::themes[Menu::themeSelection].GetHighlightCol(),hoverEffect/"ThemeGlobal.HighlightTime"_F)*(focused?1:"ThemeGlobal.MenuUnfocusedColorMult"_F));
if(border){ if(border){
@ -23,12 +29,37 @@ void MenuComponent::Draw(Crawler*game,vf2d parentPos,bool focused){
game->DrawStringProp(rect.pos+parentPos+rect.size/2-game->GetTextSizeProp(label)/2,label,focused?WHITE:WHITE*"ThemeGlobal.MenuUnfocusedColorMult"_F); game->DrawStringProp(rect.pos+parentPos+rect.size/2-game->GetTextSizeProp(label)/2,label,focused?WHITE:WHITE*"ThemeGlobal.MenuUnfocusedColorMult"_F);
} }
void MenuComponent::_Draw(Crawler*game,vf2d parentPos,bool focused){
if(!disabled){
Draw(game,parentPos,focused);
}
}
void MenuComponent::DrawDecal(Crawler*game,vf2d parentPos,bool focused){} void MenuComponent::DrawDecal(Crawler*game,vf2d parentPos,bool focused){}
void MenuComponent::_DrawDecal(Crawler*game,vf2d parentPos,bool focused){
if(!disabled){
DrawDecal(game,parentPos,focused);
}
}
MenuComponent*MenuComponent::PickUpDraggableItem(){ MenuComponent*MenuComponent::PickUpDraggableItem(){
return nullptr; return nullptr;
} }
bool MenuComponent::DropDraggableItem(MenuComponent*draggable){ bool MenuComponent::DropDraggableItem(MenuComponent*draggable){
return false; return false;
}
bool MenuComponent::GetHoverState(Crawler*game){
if(parentComponent!=nullptr){
return parentComponent->GetHoverState(game,this);
}else{
vf2d parentWindowPos=Menu::menus[parentMenu]->pos;
return geom2d::overlaps(geom2d::rect<float>{rect.pos+parentWindowPos,rect.size},game->GetMousePos());
}
}
bool MenuComponent::GetHoverState(Crawler*game,MenuComponent*child){
return false;
} }

@ -8,6 +8,7 @@ class MenuComponent{
MenuType menuDest; MenuType menuDest;
private: private:
float hoverEffect=0; float hoverEffect=0;
virtual bool GetHoverState(Crawler*game);
protected: protected:
geom2d::rect<float>rect; geom2d::rect<float>rect;
std::string label; std::string label;
@ -15,15 +16,21 @@ protected:
bool draggable=false; bool draggable=false;
MenuFunc onClick; MenuFunc onClick;
MenuType parentMenu=MenuType::ENUM_END; MenuType parentMenu=MenuType::ENUM_END;
MenuComponent*parentComponent=nullptr;
bool hovered=false; bool hovered=false;
bool selectable=true; bool selectable=true;
bool disabled=false; //If set to true, this component will not be rendered or updated.
bool renderInMain=true; //If set to false, this component is the responsibility of some other windowing system and won't be rendered or updated via the main window loop. bool renderInMain=true; //If set to false, this component is the responsibility of some other windowing system and won't be rendered or updated via the main window loop.
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);
virtual void Update(Crawler*game); virtual void Update(Crawler*game);
virtual void Draw(Crawler*game,vf2d parentPos,bool focused); virtual void Draw(Crawler*game,vf2d parentPos,bool focused);
virtual void DrawDecal(Crawler*game,vf2d parentPos,bool focused); virtual void DrawDecal(Crawler*game,vf2d parentPos,bool focused);
virtual bool GetHoverState(Crawler*game,MenuComponent*child);
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);
void _Update(Crawler*game);
void _Draw(Crawler*game,vf2d parentPos,bool focused);
void _DrawDecal(Crawler*game,vf2d parentPos,bool focused);
//We picked up a draggable component, we should make a copy and return it here. If a nullptr is returned here, the pickup is not allowed. //We picked up a draggable component, we should make a copy and return it here. If a nullptr is returned here, the pickup is not allowed.
//WARNING!!! This allocates a brand new component when successful!!! Be prepared to clear it! //WARNING!!! This allocates a brand new component when successful!!! Be prepared to clear it!
virtual MenuComponent*PickUpDraggableItem(); virtual MenuComponent*PickUpDraggableItem();

@ -9,6 +9,10 @@ protected:
std::vector<MenuComponent*>components; std::vector<MenuComponent*>components;
vf2d scrollOffset{}; vf2d scrollOffset{};
geom2d::rect<float>bounds; geom2d::rect<float>bounds;
private:
inline bool OnScreen(MenuComponent*component){
return geom2d::overlaps(rect,geom2d::rect<float>{component->rect.pos+scrollOffset,component->rect.size});
}
public: public:
inline ScrollableWindowComponent(MenuType parent,geom2d::rect<float>rect,Decal*icon,MenuFunc onClick) inline ScrollableWindowComponent(MenuType parent,geom2d::rect<float>rect,Decal*icon,MenuFunc onClick)
:MenuComponent(parent,rect,"",onClick,false){ :MenuComponent(parent,rect,"",onClick,false){
@ -17,8 +21,18 @@ public:
protected: protected:
virtual inline void Update(Crawler*game)override{ virtual inline void Update(Crawler*game)override{
MenuComponent::Update(game); MenuComponent::Update(game);
if(game->GetMouseWheel()!=0){
if(game->GetMouseWheel()>0){
scrollOffset.y-=4;
}else{
scrollOffset.y+=4;
}
}
for(MenuComponent*component:components){ for(MenuComponent*component:components){
component->Update(game); component->disabled=!OnScreen(component);
component->_Update(game);
} }
} }
virtual inline void Draw(Crawler*game,vf2d parentPos,bool focused)override{ virtual inline void Draw(Crawler*game,vf2d parentPos,bool focused)override{
@ -27,7 +41,7 @@ protected:
game->SetDrawTarget(r.Sprite()); game->SetDrawTarget(r.Sprite());
game->Clear(BLANK); game->Clear(BLANK);
for(MenuComponent*component:components){ for(MenuComponent*component:components){
component->Draw(game,scrollOffset,focused); component->_Draw(game,scrollOffset,focused);
} }
game->SetDrawTarget(prevDrawTarget); game->SetDrawTarget(prevDrawTarget);
game->DrawSprite(parentPos,r.Sprite()); game->DrawSprite(parentPos,r.Sprite());
@ -36,13 +50,17 @@ protected:
MenuComponent::DrawDecal(game,parentPos,focused); MenuComponent::DrawDecal(game,parentPos,focused);
game->DrawRectDecal(parentPos,rect.size); game->DrawRectDecal(parentPos,rect.size);
for(MenuComponent*component:components){ for(MenuComponent*component:components){
component->DrawDecal(game,parentPos+scrollOffset,focused); component->_DrawDecal(game,parentPos+scrollOffset,focused);
} }
} }
virtual bool GetHoverState(Crawler*game,MenuComponent*child)override{
return geom2d::overlaps(geom2d::rect<float>{Menu::menus[parentMenu]->pos+child->rect.pos+scrollOffset,child->rect.size},game->GetMousePos());
}
public: public:
void inline AddComponent(Menu*parentMenu,std::string key,MenuComponent*button){ void inline AddComponent(Menu*parentMenu,std::string key,MenuComponent*button){
components.push_back(button); components.push_back(button);
button->renderInMain=false; //Now we are in control! button->renderInMain=false; //Now we are in control!
button->parentComponent=this;
if(button->rect.pos.x<bounds.pos.x){ if(button->rect.pos.x<bounds.pos.x){
float sizeIncrease=bounds.pos.x-button->rect.pos.x; float sizeIncrease=bounds.pos.x-button->rect.pos.x;

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

Loading…
Cancel
Save