Implement parent component hover state handling.
This commit is contained in:
parent
1c4ec84d75
commit
18db45e6c3
@ -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,16 +90,19 @@ 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->disabled){
|
||||||
button->hovered=false;
|
button->hovered=false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if(!MOUSE_NAVIGATION){
|
if(!MOUSE_NAVIGATION){
|
||||||
if(selection!=vi2d{-1,-1})buttons[selection.y][selection.x]->hovered=true;
|
if(selection!=vi2d{-1,-1})buttons[selection.y][selection.x]->hovered=true;
|
||||||
}else{
|
}else{
|
||||||
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){
|
||||||
|
if(button->GetHoverState(game)){
|
||||||
button->hovered=true;
|
button->hovered=true;
|
||||||
selection.y=key.first;
|
selection.y=key.first;
|
||||||
selection.x=index;
|
selection.x=index;
|
||||||
@ -108,6 +111,7 @@ void Menu::Update(Crawler*game){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(draggingComponent!=nullptr&&selection!=vi2d{-1,-1}){
|
if(draggingComponent!=nullptr&&selection!=vi2d{-1,-1}){
|
||||||
MenuComponent*selectedComponent=buttons[selection.y][selection.x];
|
MenuComponent*selectedComponent=buttons[selection.y][selection.x];
|
||||||
@ -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,8 +29,20 @@ 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;
|
||||||
}
|
}
|
||||||
@ -32,3 +50,16 @@ MenuComponent*MenuComponent::PickUpDraggableItem(){
|
|||||||
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…
x
Reference in New Issue
Block a user