Fix border display drawing for menus. Fix scrollable window components that went outside to use proper scrolling offsets. Fix issue with same-frame clicking and releasing causing a different button to be selected.
This commit is contained in:
parent
92c093c589
commit
025a89788e
@ -54,16 +54,16 @@ protected:
|
||||
virtual void inline Update(Crawler*game)override{
|
||||
MenuLabel::Update(game);
|
||||
}
|
||||
virtual void inline DrawDecal(ViewPort&window,vf2d parentPos,bool focused)override{
|
||||
MenuLabel::DrawDecal(window,parentPos,focused);
|
||||
vi2d iconPos=parentPos+rect.pos+vi2d{5,5};
|
||||
virtual void inline DrawDecal(ViewPort&window,bool focused)override{
|
||||
MenuLabel::DrawDecal(window,focused);
|
||||
vi2d iconPos=rect.pos+vi2d{5,5};
|
||||
vi2d textPos=iconPos;
|
||||
|
||||
float textWidth=game->GetTextSizeProp(ability->input->GetDisplayName()).x*0.5f+4;
|
||||
|
||||
float boxWidth=rect.size.y-4; //No, the y is not a typo. It's a square, we use the y to determine the x.
|
||||
|
||||
window.DrawRectDecal(parentPos+rect.pos+vi2d{2,2},vi2d{int(rect.size.y)-4,int(rect.size.y)-4});
|
||||
window.DrawRectDecal(rect.pos+vi2d{2,2},vi2d{int(rect.size.y)-4,int(rect.size.y)-4});
|
||||
window.DrawDecal(iconPos,GFX[ability->icon].Decal());
|
||||
|
||||
vi2d descriptionPos=iconPos+vi2d{int(rect.size.y)-2,-1};
|
||||
|
@ -53,10 +53,10 @@ INCLUDE_GFX
|
||||
void Menu::InitializeCharacterMenuWindow(){
|
||||
static bool equipmentWindowOpened=false;
|
||||
|
||||
vf2d windowSize=game->GetScreenSize()-vf2d{52,0};
|
||||
vf2d windowSize=game->GetScreenSize()-vf2d{52,52};
|
||||
Menu*characterMenuWindow=CreateMenu(CHARACTER_MENU,CENTERED,windowSize);
|
||||
|
||||
characterMenuWindow->ADD("Character Label",MenuLabel)({{0,2},{float(windowSize.x)-1,24}},"Character",2,ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND)END;
|
||||
characterMenuWindow->ADD("Character Label",MenuLabel)({{0,-4},{float(windowSize.x)-1,24}},"Character",2,ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND)END;
|
||||
characterMenuWindow->ADD("Equip Slot Outline",MenuComponent)({{0,28},{120,windowSize.y-48}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE)END;
|
||||
characterMenuWindow->ADD("Character Rotating Display",CharacterRotatingDisplay)({{135,28},{90,windowSize.y-48}},GFX[classutils::GetClassInfo(game->GetPlayer()->GetClassName()).classFullImgName].Decal())END;
|
||||
|
||||
@ -71,13 +71,13 @@ void Menu::InitializeCharacterMenuWindow(){
|
||||
};
|
||||
|
||||
|
||||
characterMenuWindow->ADD("Equip Selection Outline",MenuComponent)({{123,28},{120,windowSize.y-48}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE)END
|
||||
characterMenuWindow->ADD("Equip Selection Outline",MenuComponent)({{123,28},{120,windowSize.y-37}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE)END
|
||||
->Enable(false);
|
||||
characterMenuWindow->ADD("Equip List",ScrollableWindowComponent)({{123,28},{120,windowSize.y-48-24}})DEPTH -1 END
|
||||
characterMenuWindow->ADD("Equip List",ScrollableWindowComponent)({{123,28},{120,windowSize.y-37-24}})DEPTH -1 END
|
||||
->Enable(false);
|
||||
characterMenuWindow->ADD("Equip Selection Bottom Outline",MenuComponent)({{123,28+(windowSize.y-48-24)},{120,24}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE)END
|
||||
characterMenuWindow->ADD("Equip Selection Bottom Outline",MenuComponent)({{123,28+(windowSize.y-37-24)},{120,24}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE)END
|
||||
->Enable(false);
|
||||
auto equipSelectionSelectButton=characterMenuWindow->ADD("Equip Selection Select Button",MenuComponent)({{123+12,28+(windowSize.y-48-24)+6},{96,12}},"Select",
|
||||
auto equipSelectionSelectButton=characterMenuWindow->ADD("Equip Selection Select Button",MenuComponent)({{123+12,28+(windowSize.y-37-24)+6},{96,12}},"Select",
|
||||
[](MenuFuncData data){
|
||||
Component<MenuComponent>(data.component->parentMenu,"Equip Selection Outline")->Enable(false);
|
||||
Component<ScrollableWindowComponent>(data.component->parentMenu,"Equip List")->Enable(false);
|
||||
@ -218,7 +218,7 @@ void Menu::InitializeCharacterMenuWindow(){
|
||||
Menu::AddEquipStatListener(equipmentSlot);
|
||||
}
|
||||
|
||||
characterMenuWindow->ADD("Stat Display Outline",MenuComponent)({{245,28},{62,windowSize.y-48}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE)END;
|
||||
characterMenuWindow->ADD("Stat Display Outline",MenuComponent)({{245,28},{62,windowSize.y-37}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE)END;
|
||||
|
||||
int yOffset=0;
|
||||
for(ItemAttribute attribute:displayAttrs){
|
||||
@ -229,12 +229,12 @@ void Menu::InitializeCharacterMenuWindow(){
|
||||
yOffset+=20;
|
||||
}
|
||||
|
||||
characterMenuWindow->ADD("Back button",MenuComponent)({{windowSize.x/2-64,windowSize.y-16},{128,12}},"Back",[](MenuFuncData data){Menu::stack.pop_back();return true;})END;
|
||||
characterMenuWindow->ADD("Back button",MenuComponent)({{windowSize.x/2-64,windowSize.y},{128,12}},"Back",[](MenuFuncData data){Menu::stack.pop_back();return true;})END;
|
||||
|
||||
auto itemNameDisplay=characterMenuWindow->ADD("Item Name",MenuLabel)({{0,28},{120,12}},"",1,ComponentAttr::BACKGROUND|ComponentAttr::LEFT_ALIGN|ComponentAttr::OUTLINE|ComponentAttr::SHADOW)END;
|
||||
auto itemDescriptionDisplay=characterMenuWindow->ADD("Item Description",MenuLabel)({{0,40},{120,windowSize.y-60}},"",1,ComponentAttr::BACKGROUND|ComponentAttr::LEFT_ALIGN|ComponentAttr::OUTLINE|ComponentAttr::SHADOW)END;
|
||||
auto itemDescriptionDisplay=characterMenuWindow->ADD("Item Description",MenuLabel)({{0,40},{120,windowSize.y-49}},"",1,ComponentAttr::BACKGROUND|ComponentAttr::LEFT_ALIGN|ComponentAttr::OUTLINE|ComponentAttr::SHADOW)END;
|
||||
auto itemEquipNameDisplay=characterMenuWindow->ADD("Item Equip Name",MenuLabel)({{123,28},{120,12}},"",1,ComponentAttr::BACKGROUND|ComponentAttr::LEFT_ALIGN|ComponentAttr::OUTLINE|ComponentAttr::SHADOW)END;
|
||||
auto itemEquipDescriptionDisplay=characterMenuWindow->ADD("Item Equip Description",MenuLabel)({{123,40},{120,windowSize.y-60}},"",1,ComponentAttr::BACKGROUND|ComponentAttr::LEFT_ALIGN|ComponentAttr::OUTLINE|ComponentAttr::SHADOW)END;
|
||||
auto itemEquipDescriptionDisplay=characterMenuWindow->ADD("Item Equip Description",MenuLabel)({{123,40},{120,windowSize.y-49}},"",1,ComponentAttr::BACKGROUND|ComponentAttr::LEFT_ALIGN|ComponentAttr::OUTLINE|ComponentAttr::SHADOW)END;
|
||||
|
||||
itemNameDisplay->Enable(false);
|
||||
itemDescriptionDisplay->Enable(false);
|
||||
|
@ -62,7 +62,7 @@ protected:
|
||||
timer-=2*PI;
|
||||
}
|
||||
}
|
||||
virtual inline void DrawDecal(ViewPort&window,vf2d parentPos,bool focused)override{
|
||||
virtual inline void DrawDecal(ViewPort&window,bool focused)override{
|
||||
window.DrawWarpedDecal(icon,std::array<vf2d,4>{
|
||||
rect.pos+vf2d{abs(sin(timer)),sin(float(timer+PI))}*vf2d{rotatingFactor,perspectiveFactor},
|
||||
rect.pos+vf2d{0,rect.size.y}+vf2d{abs(sin(timer)),sin(timer)}*vf2d{rotatingFactor,perspectiveFactor},
|
||||
|
@ -215,7 +215,6 @@ bool Crawler::OnUserCreate(){
|
||||
}
|
||||
|
||||
bool Crawler::OnUserUpdate(float fElapsedTime){
|
||||
fElapsedTime=std::clamp(fElapsedTime,0.f,1/30.f); //HACK fix. We can't have a negative time. Although using a more precise system clock should make this never occur. Also make sure if the game is too slow we advance by only 1/30th of a second.
|
||||
levelTime+=fElapsedTime;
|
||||
if(!GamePaused()){
|
||||
GameState::STATE->OnUserUpdate(this);
|
||||
|
@ -54,6 +54,7 @@ All rights reserved.
|
||||
#define INCLUDE_ITEM_CATEGORIES extern safemap<std::string,std::set<std::string>>ITEM_CATEGORIES;
|
||||
#define DO_NOTHING [](MenuFuncData data){return true;}
|
||||
#define INCLUDE_LEVEL_NAMES extern safemap<std::string,MapName>LEVEL_NAMES;
|
||||
#define INCLUDE_WINDOW_SIZE extern vi2d WINDOW_SIZE;
|
||||
|
||||
#define INCLUDE_CENTERED extern const vf2d Menu::CENTERED;
|
||||
|
||||
|
@ -61,7 +61,8 @@ void Menu::InitializeConsumableInventoryWindow(){
|
||||
data.game->ClearLoadoutItem(data.menu.I(A::LOADOUT_SLOT));
|
||||
for(MenuComponent*component:data.parentComponent->GetComponents()){ //HACK ALERT! If we are accessing a parent component, it's because we are dealing with a scrolling window component, which has sub-components. So this should be a safe cast to make.
|
||||
if(component->GetName().starts_with("item")){
|
||||
MenuItemButton*button2=(MenuItemButton*)component;//HACK ALERT! This is probably an item since we populated item lists using this name for the components. So we assume these are MenuItemButton classes.
|
||||
MenuItemButton*button2=dynamic_cast<MenuItemButton*>(component);//HACK ALERT! This is probably an item since we populated item lists using this name for the components. So we assume these are MenuItemButton classes.
|
||||
if(button2==nullptr)continue;
|
||||
if(button2==button){
|
||||
if(button2->selected!=-1){
|
||||
data.game->ClearLoadoutItem(button2->selected);
|
||||
|
@ -69,13 +69,13 @@ std::string Menu::lastRegisteredComponent;
|
||||
|
||||
INCLUDE_game
|
||||
INCLUDE_GFX
|
||||
extern vi2d WINDOW_SIZE;
|
||||
INCLUDE_WINDOW_SIZE
|
||||
|
||||
using A=Attribute;
|
||||
|
||||
Menu::Menu(vf2d pos,vf2d size)
|
||||
:pos(pos==CENTERED?WINDOW_SIZE/2-size/2:vi2d{pos}),size(size){
|
||||
this->window=ViewPort::rectViewPort({0,0},size,this->pos);
|
||||
this->window=ViewPort::rectViewPort({-24,-24},this->size+vi2d{48,48},this->pos);
|
||||
}
|
||||
|
||||
Menu::~Menu(){
|
||||
@ -202,11 +202,14 @@ void Menu::Update(Crawler*game){
|
||||
itemHovered=true;
|
||||
selection.y=key;
|
||||
selection.x=index;
|
||||
goto selected;
|
||||
}
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
selected:
|
||||
int a;
|
||||
}
|
||||
|
||||
if(itemHovered&&draggingComponent==nullptr&&selection!=vi2d{-1,-1}&&(((!UsingMouseNavigation()&&(game->GetKey(ENTER).bHeld)||game->GetKey(SPACE).bHeld))||game->GetMouse(Mouse::LEFT).bHeld)){
|
||||
@ -305,11 +308,16 @@ void Menu::Draw(Crawler*game){
|
||||
MenuComponent*selectedComponent=buttons[selection.y][selection.x];
|
||||
vf2d drawOffset{};
|
||||
if(selectedComponent->parentComponent!=nullptr){
|
||||
drawOffset+=selectedComponent->parentComponent->V(A::SCROLL_OFFSET);
|
||||
ScrollableWindowComponent*scrollableComponent=dynamic_cast<ScrollableWindowComponent*>(selectedComponent->parentComponent);
|
||||
if(scrollableComponent!=nullptr){
|
||||
drawOffset+=scrollableComponent->GetScrollAmount();
|
||||
}
|
||||
}
|
||||
draggingComponent->DrawDecal(window,drawOffset+pos-offsetPos+selectedComponent->rect.pos+vi2d{1,-4},this==Menu::stack.back());
|
||||
draggingComponent->V(A::DRAW_OFFSET)=drawOffset+pos-offsetPos+selectedComponent->rect.pos+vi2d{1,-4};
|
||||
draggingComponent->DrawDecal(window,this==Menu::stack.back());
|
||||
}else{
|
||||
draggingComponent->DrawDecal(window,-offsetPos+game->GetMousePos(),this==Menu::stack.back());
|
||||
draggingComponent->V(A::DRAW_OFFSET)-offsetPos+game->GetMousePos();
|
||||
draggingComponent->DrawDecal(window,this==Menu::stack.back());
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -435,20 +443,7 @@ void Menu::KeyboardButtonNavigation(Crawler*game,vf2d menuPos){
|
||||
selection={0,firstInd};
|
||||
}
|
||||
}
|
||||
}else{//Mouse click.
|
||||
selection={-1,-1};
|
||||
for(auto&[key,value]:buttons){
|
||||
int index=0;
|
||||
for(auto&button:value){
|
||||
if(!button->disabled){
|
||||
if(geom2d::overlaps(geom2d::rect<float>{button->rect.pos+menuPos,button->rect.size},game->GetMousePos())){
|
||||
selection={index,key};
|
||||
break;
|
||||
}
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
buttonHoldTime=0;
|
||||
}
|
||||
}
|
||||
|
@ -55,10 +55,10 @@ protected:
|
||||
MenuIconButton::Update(game);
|
||||
animationTime+=game->GetElapsedTime();
|
||||
}
|
||||
virtual inline void DrawDecal(ViewPort&window,vf2d parentPos,bool focused)override{
|
||||
MenuComponent::DrawDecal(window,parentPos,focused); //INTENTIONAL! The way we draw animations is different from static images, we skip over MenuIconButton's draw!
|
||||
virtual inline void DrawDecal(ViewPort&window,bool focused)override{
|
||||
MenuComponent::DrawDecal(window,focused); //Skipping to MenuComponent's DrawDecal is INTENTIONAL! The way we draw animations is different from static images, we skip over MenuIconButton's draw!
|
||||
Decal*spr=ANIMATION_DATA[animation].GetFrame(animationTime).GetSourceImage()->Decal();
|
||||
geom2d::rect<int>sprRect=ANIMATION_DATA[animation].GetFrame(animationTime).GetSourceRect();
|
||||
window.DrawPartialDecal(parentPos+rect.middle()-sprRect.size/2,spr,sprRect.pos,sprRect.size);
|
||||
window.DrawPartialDecal(rect.middle()-sprRect.size/2,spr,sprRect.pos,sprRect.size);
|
||||
}
|
||||
};
|
@ -63,8 +63,8 @@ protected:
|
||||
hoverEffect="ThemeGlobal.HighlightTime"_F; //A hack that allows us to make it look like we have this selected.
|
||||
}
|
||||
}
|
||||
virtual inline void DrawDecal(ViewPort&window,vf2d parentPos,bool focused)override{
|
||||
MenuAnimatedIconButton::DrawDecal(window,parentPos,focused);
|
||||
virtual inline void DrawDecal(ViewPort&window,bool focused)override{
|
||||
MenuAnimatedIconButton::DrawDecal(window,focused);
|
||||
if(IsSelected()){
|
||||
window.DrawRectDecal(rect.pos+vi2d{2,2},rect.size-vi2d{4,4},YELLOW);
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ INCLUDE_game
|
||||
using A=Attribute;
|
||||
|
||||
MenuComponent::MenuComponent(geom2d::rect<float>rect,std::string label,MenuFunc onClick,ButtonAttr attributes)
|
||||
:rect(rect),label(label),menuDest(MenuType::ENUM_END),onClick(onClick),hoverEffect(0),selectable(!(attributes&ButtonAttr::UNSELECTABLE)),selectableViaKeyboard(!(attributes&ButtonAttr::UNSELECTABLE_VIA_KEYBOARD)),memoryLeakInfo(Menu::GetMemoryLeakReportInfo()){
|
||||
:rect(rect),originalPos(rect.pos),label(label),menuDest(MenuType::ENUM_END),onClick(onClick),hoverEffect(0),selectable(!(attributes&ButtonAttr::UNSELECTABLE)),selectableViaKeyboard(!(attributes&ButtonAttr::UNSELECTABLE_VIA_KEYBOARD)),memoryLeakInfo(Menu::GetMemoryLeakReportInfo()){
|
||||
Menu::unhandledComponents.push_back(this);
|
||||
}
|
||||
|
||||
@ -95,26 +95,26 @@ void MenuComponent::_Update(Crawler*game){
|
||||
|
||||
void MenuComponent::OnEquipStatsUpdate(){}
|
||||
|
||||
void MenuComponent::DrawDecal(ViewPort&window,vf2d parentPos,bool focused){
|
||||
void MenuComponent::DrawDecal(ViewPort&window,bool focused){
|
||||
if(background){
|
||||
window.FillRectDecal(rect.pos+parentPos,rect.size,PixelLerp(Menu::themes[Menu::themeSelection].GetButtonCol(),Menu::themes[Menu::themeSelection].GetHighlightCol(),hoverEffect/"ThemeGlobal.HighlightTime"_F));
|
||||
window.FillRectDecal(rect.pos+V(A::DRAW_OFFSET),rect.size,PixelLerp(Menu::themes[Menu::themeSelection].GetButtonCol(),Menu::themes[Menu::themeSelection].GetHighlightCol(),hoverEffect/"ThemeGlobal.HighlightTime"_F));
|
||||
}
|
||||
if(selected&&selectionType==HIGHLIGHT){
|
||||
window.FillRectDecal(rect.pos+parentPos,rect.size,PixelLerp(Menu::themes[Menu::themeSelection].GetButtonCol(),Menu::themes[Menu::themeSelection].GetHighlightCol(),util::lerp(0.75f,1.0f,hoverEffect/"ThemeGlobal.HighlightTime"_F)));
|
||||
window.FillRectDecal(rect.pos+V(A::DRAW_OFFSET),rect.size,PixelLerp(Menu::themes[Menu::themeSelection].GetButtonCol(),Menu::themes[Menu::themeSelection].GetHighlightCol(),util::lerp(0.75f,1.0f,hoverEffect/"ThemeGlobal.HighlightTime"_F)));
|
||||
}
|
||||
if(border){
|
||||
window.FillRectDecal(rect.pos+parentPos,{rect.size.x+1,1});
|
||||
window.FillRectDecal(rect.pos+parentPos,{1,rect.size.y+1});
|
||||
window.FillRectDecal(rect.pos+parentPos+vf2d{rect.size.x-1+1,0},{1,rect.size.y+1});
|
||||
window.FillRectDecal(rect.pos+parentPos+vf2d{0,rect.size.y-1+1},{rect.size.x+1,1});
|
||||
window.FillRectDecal(rect.pos+V(A::DRAW_OFFSET),{rect.size.x+1,1});
|
||||
window.FillRectDecal(rect.pos+V(A::DRAW_OFFSET),{1,rect.size.y+1});
|
||||
window.FillRectDecal(rect.pos+V(A::DRAW_OFFSET)+vf2d{rect.size.x-1+1,0},{1,rect.size.y+1});
|
||||
window.FillRectDecal(rect.pos+V(A::DRAW_OFFSET)+vf2d{0,rect.size.y-1+1},{rect.size.x+1,1});
|
||||
}
|
||||
if(showDefaultLabel){
|
||||
window.DrawStringPropDecal(rect.pos+parentPos+rect.size/2-vf2d(game->GetTextSizeProp(label))/2.f*labelScaling,label,WHITE,labelScaling);
|
||||
window.DrawStringPropDecal(rect.pos+V(A::DRAW_OFFSET)+rect.size/2-vf2d(game->GetTextSizeProp(label))/2.f*labelScaling,label,WHITE,labelScaling);
|
||||
}
|
||||
if(selected){
|
||||
switch(selectionType){
|
||||
case CROSSHAIR:drawutil::DrawCrosshairDecalViewPort(window,{parentPos+rect.pos,rect.size},0);break;
|
||||
case INNER_BOX:window.DrawRectDecal(rect.pos+parentPos+vi2d{1,1},rect.size-vi2d{2,2});break;
|
||||
case CROSSHAIR:drawutil::DrawCrosshairDecalViewPort(window,{rect.pos+V(A::DRAW_OFFSET),rect.size},0);break;
|
||||
case INNER_BOX:window.DrawRectDecal(rect.pos+V(A::DRAW_OFFSET)+vi2d{1,1},rect.size-vi2d{2,2});break;
|
||||
case HIGHLIGHT:break;//Not used.
|
||||
default:ERR("Undefined selection type selected: "<<int(selectionType));
|
||||
}
|
||||
@ -122,12 +122,8 @@ void MenuComponent::DrawDecal(ViewPort&window,vf2d parentPos,bool focused){
|
||||
}
|
||||
|
||||
void MenuComponent::_DrawDecal(ViewPort&window,bool focused){
|
||||
_DrawDecal(window,{0,0},focused);
|
||||
}
|
||||
|
||||
void MenuComponent::_DrawDecal(ViewPort&window,vf2d parentPos,bool focused){
|
||||
if(!disabled){
|
||||
DrawDecal(window,parentPos,focused);
|
||||
DrawDecal(window,focused);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,6 @@ private:
|
||||
virtual void BeforeUpdate(Crawler*game);
|
||||
void _Update(Crawler*game);
|
||||
void _DrawDecal(ViewPort&window,bool focused);
|
||||
void _DrawDecal(ViewPort&window,vf2d parentPos,bool focused);
|
||||
bool selected=false;
|
||||
SelectionType selectionType=CROSSHAIR;
|
||||
protected:
|
||||
@ -82,6 +81,7 @@ protected:
|
||||
float hoverEffect=0;
|
||||
std::string name="";
|
||||
geom2d::rect<float>rect;
|
||||
vf2d originalPos;
|
||||
std::string label;
|
||||
bool border=true;
|
||||
bool draggable=false;
|
||||
@ -96,7 +96,7 @@ protected:
|
||||
bool valid=true; //If set to false, this would cause the component to be removed.
|
||||
vf2d labelScaling={1,1};
|
||||
virtual void Update(Crawler*game);
|
||||
virtual void DrawDecal(ViewPort&window,vf2d parentPos,bool focused);
|
||||
virtual void DrawDecal(ViewPort&window,bool focused);
|
||||
virtual bool GetHoverState(Crawler*game,MenuComponent*child);
|
||||
virtual void AfterCreate(); //Called after the creation of all menus finish.
|
||||
//CALL THIS FOR A PARENT to check a child's DrawDecal validity!
|
||||
|
@ -59,11 +59,11 @@ protected:
|
||||
virtual inline void Update(Crawler*game)override{
|
||||
MenuComponent::Update(game);
|
||||
}
|
||||
virtual inline void DrawDecal(ViewPort&window,vf2d parentPos,bool focused)override{
|
||||
MenuComponent::DrawDecal(window,parentPos,focused);
|
||||
virtual inline void DrawDecal(ViewPort&window,bool focused)override{
|
||||
MenuComponent::DrawDecal(window,focused);
|
||||
if(icon!=nullptr){
|
||||
vf2d iconScale=rect.size/24.f;
|
||||
window.DrawDecal(parentPos+rect.middle()-icon->sprite->Size()*iconScale/2,icon,iconScale);
|
||||
window.DrawDecal(rect.middle()-icon->sprite->Size()*iconScale/2,icon,iconScale);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -133,10 +133,10 @@ protected:
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual inline void DrawDecal(ViewPort&window,vf2d parentPos,bool focused)override{
|
||||
MenuIconButton::DrawDecal(window,parentPos,focused);
|
||||
virtual inline void DrawDecal(ViewPort&window,bool focused)override{
|
||||
MenuIconButton::DrawDecal(window,focused);
|
||||
if(selected!=-1){
|
||||
drawutil::DrawCrosshairDecalViewPort(window,{parentPos+rect.pos,rect.size},0);
|
||||
drawutil::DrawCrosshairDecalViewPort(window,{rect.pos,rect.size},0);
|
||||
}
|
||||
if(valid){
|
||||
int itemQuantity=Inventory::GetItemCount(invRef.at(inventoryIndex).Name()); //Normally we'd retrieve how many of this item we have from our inventory...However Monster Loot and Stage Loot inventories are special and hold their own inventory counts...
|
||||
@ -146,7 +146,7 @@ protected:
|
||||
std::string quantityText="x"+std::to_string(itemQuantity);
|
||||
vf2d quantityTextScale=rect.size/48.f;
|
||||
vf2d textSize=vf2d(game->GetTextSizeProp(quantityText))*quantityTextScale;
|
||||
vf2d drawPos=parentPos+rect.pos+rect.size-textSize;
|
||||
vf2d drawPos=rect.pos+rect.size-textSize;
|
||||
geom2d::rect<float>boundingBox={drawPos,textSize};
|
||||
window.DrawShadowStringDecal(drawPos,quantityText,WHITE,BLACK,quantityTextScale,quantityTextScale.x);
|
||||
}
|
||||
|
@ -131,13 +131,13 @@ protected:
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual inline void DrawDecal(ViewPort&window,vf2d parentPos,bool focused)override{
|
||||
MenuIconButton::DrawDecal(window,parentPos,focused);
|
||||
virtual inline void DrawDecal(ViewPort&window,bool focused)override{
|
||||
MenuIconButton::DrawDecal(window,focused);
|
||||
if(valid&&!hideQty){
|
||||
std::string quantityText="x"+std::to_string(itemRef.get().Amt());
|
||||
vf2d quantityTextScale=rect.size/48.f;
|
||||
vf2d textSize=vf2d(game->GetTextSizeProp(quantityText))*quantityTextScale;
|
||||
vf2d drawPos=parentPos+rect.pos+rect.size-textSize;
|
||||
vf2d drawPos=rect.pos+rect.size-textSize;
|
||||
geom2d::rect<float>boundingBox={drawPos,textSize};
|
||||
window.DrawShadowStringDecal(drawPos,quantityText,WHITE,BLACK,quantityTextScale,quantityTextScale.x);
|
||||
}
|
||||
|
@ -64,12 +64,12 @@ protected:
|
||||
virtual void inline Update(Crawler*game)override{
|
||||
MenuComponent::Update(game);
|
||||
}
|
||||
virtual void inline DrawDecal(ViewPort&window,vf2d parentPos,bool focused)override{
|
||||
MenuComponent::DrawDecal(window,parentPos,focused);
|
||||
virtual void inline DrawDecal(ViewPort&window,bool focused)override{
|
||||
MenuComponent::DrawDecal(window,focused);
|
||||
std::string wrappedText=util::WrapText(game,label,int(rect.size.x),true,{float(scale),float(scale)});
|
||||
vf2d drawPos=parentPos+rect.middle()-vf2d{game->GetTextSizeProp(wrappedText)}*float(scale)/2; //Assume centered.
|
||||
vf2d drawPos=rect.middle()-vf2d{game->GetTextSizeProp(wrappedText)}*float(scale)/2; //Assume centered.
|
||||
if(!centered){
|
||||
drawPos=vf2d{rect.pos.x+2,rect.middle().y-game->GetTextSizeProp(wrappedText).y/2}+parentPos; //We should at least vertically align here.
|
||||
drawPos=vf2d{rect.pos.x+2,rect.middle().y-game->GetTextSizeProp(wrappedText).y/2}; //We should at least vertically align here.
|
||||
}
|
||||
if(shadow){
|
||||
window.DrawShadowStringPropDecal(drawPos,wrappedText,WHITE,BLACK,{float(scale),float(scale)});
|
||||
|
@ -65,11 +65,11 @@ enum class Attribute{
|
||||
JUMP_TOWARDS_PLAYER,
|
||||
HITS_UNTIL_DEATH, //When this is set, it is reduced by 1 each time the monster is hit.
|
||||
INDEXED_THEME,
|
||||
SCROLL_OFFSET,
|
||||
CLASS_SELECTION, //A class name that represents what the menu's class is.
|
||||
LOADOUT_SLOT, //Which loadout slot we are selecting an item for.
|
||||
ALLOW_DRAGGING, //Whether or not to allow inventory dragging.
|
||||
EQUIP_TYPE,
|
||||
BASE_TEXT,
|
||||
CATEGORY_NAME,
|
||||
DRAW_OFFSET,
|
||||
};
|
@ -57,21 +57,21 @@ protected:
|
||||
virtual void inline Update(Crawler*game)override{
|
||||
MenuLabel::Update(game);
|
||||
}
|
||||
virtual void inline DrawDecal(ViewPort&window,vf2d parentPos,bool focused)override{
|
||||
virtual void inline DrawDecal(ViewPort&window,bool focused)override{
|
||||
if(label.length()>0){
|
||||
std::string wrappedText=util::WrapText(game,label,int(rect.size.x-1),true,scale);
|
||||
vf2d drawPos=parentPos+rect.middle()-vf2d{game->GetTextSizeProp(wrappedText)}*scale/2; //Assume centered.
|
||||
vf2d drawPos=rect.middle()-vf2d{game->GetTextSizeProp(wrappedText)}*scale/2; //Assume centered.
|
||||
if(!centered){
|
||||
drawPos=vf2d{rect.pos.x+2,rect.middle().y-game->GetTextSizeProp(wrappedText).y/2}+parentPos; //We should at least vertically align here.
|
||||
drawPos=vf2d{rect.pos.x+2,rect.middle().y-game->GetTextSizeProp(wrappedText).y/2}; //We should at least vertically align here.
|
||||
}
|
||||
if(background){
|
||||
window.FillRectDecal(rect.pos+parentPos,rect.size,PixelLerp(Menu::themes[Menu::themeSelection].GetButtonCol(),Menu::themes[Menu::themeSelection].GetHighlightCol(),hoverEffect/"ThemeGlobal.HighlightTime"_F));
|
||||
window.FillRectDecal(rect.pos,rect.size,PixelLerp(Menu::themes[Menu::themeSelection].GetButtonCol(),Menu::themes[Menu::themeSelection].GetHighlightCol(),hoverEffect/"ThemeGlobal.HighlightTime"_F));
|
||||
}
|
||||
if(border){
|
||||
window.DrawRectDecal(rect.pos+parentPos,rect.size);
|
||||
window.DrawRectDecal(rect.pos,rect.size);
|
||||
}
|
||||
if(showDefaultLabel){
|
||||
window.DrawStringPropDecal(rect.pos+parentPos+rect.size/2-game->GetTextSizeProp(label)/2,label);
|
||||
window.DrawStringPropDecal(rect.pos+rect.size/2-game->GetTextSizeProp(label)/2,label);
|
||||
}
|
||||
if(shadow){
|
||||
window.DrawShadowStringPropDecal(drawPos,wrappedText,WHITE,BLACK,scale);
|
||||
|
@ -54,9 +54,10 @@ protected:
|
||||
float scrollBarTop=0;
|
||||
bool scrollBarSelected=false;
|
||||
float scrollBarHoverTime=0;
|
||||
vf2d scrollOffset;
|
||||
protected:
|
||||
inline bool OnScreen(MenuComponent*component){
|
||||
return geom2d::overlaps(geom2d::rect<float>{{},rect.size},geom2d::rect<float>{component->rect.pos+V(A::SCROLL_OFFSET)+vf2d{2,2},component->rect.size-vf2d{2,2}});
|
||||
return geom2d::overlaps(geom2d::rect<float>{{},rect.size},geom2d::rect<float>{component->rect.pos+vf2d{2,2},component->rect.size-vf2d{2,2}});
|
||||
}
|
||||
public:
|
||||
inline ScrollableWindowComponent(geom2d::rect<float>rect,ComponentAttr attributes=ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE)
|
||||
@ -93,11 +94,20 @@ public:
|
||||
Menu::menus[button->parentMenu]->RecalculateComponentCount();
|
||||
delete button;
|
||||
}
|
||||
virtual inline void SetScrollAmount(vf2d scrollOffset){
|
||||
this->scrollOffset=scrollOffset;
|
||||
for(MenuComponent*component:components){
|
||||
component->rect.pos=component->originalPos+scrollOffset;
|
||||
}
|
||||
}
|
||||
virtual inline vf2d GetScrollAmount(){
|
||||
return scrollOffset;
|
||||
}
|
||||
protected:
|
||||
virtual inline void AfterCreate()override{
|
||||
//Let's use the internal name of this component to add unique names for sub-components.
|
||||
upButton=Menu::menus[parentMenu]->ADD(name+vf2d(rect.pos+vf2d{rect.size.x-12,0}).str()+"_"+vf2d(12,12).str(),MenuComponent)({rect.pos+vf2d{rect.size.x-12,0},{12,12}},"^",[&](MenuFuncData dat){V(A::SCROLL_OFFSET).y+="ThemeGlobal.MenuButtonScrollSpeed"_I;return true;},ButtonAttr::UNSELECTABLE_VIA_KEYBOARD)DEPTH -1 END;
|
||||
downButton=Menu::menus[parentMenu]->ADD(name+vf2d(rect.pos+rect.size-vf2d{12,12}).str()+"_"+vf2d(12,12).str(),MenuComponent)({rect.pos+rect.size-vf2d{12,12},{12,12}},"v",[&](MenuFuncData dat){V(A::SCROLL_OFFSET).y-="ThemeGlobal.MenuButtonScrollSpeed"_I;return true;},ButtonAttr::UNSELECTABLE_VIA_KEYBOARD)DEPTH -1 END;
|
||||
upButton=Menu::menus[parentMenu]->ADD(name+vf2d(rect.pos+vf2d{rect.size.x-12,0}).str()+"_"+vf2d(12,12).str(),MenuComponent)({rect.pos+vf2d{rect.size.x-12,0},{12,12}},"^",[&](MenuFuncData dat){SetScrollAmount(GetScrollAmount()+vf2d{0,"ThemeGlobal.MenuButtonScrollSpeed"_F});return true;},ButtonAttr::UNSELECTABLE_VIA_KEYBOARD)DEPTH -1 END;
|
||||
downButton=Menu::menus[parentMenu]->ADD(name+vf2d(rect.pos+rect.size-vf2d{12,12}).str()+"_"+vf2d(12,12).str(),MenuComponent)({rect.pos+rect.size-vf2d{12,12},{12,12}},"v",[&](MenuFuncData dat){SetScrollAmount(GetScrollAmount()-vf2d{0,"ThemeGlobal.MenuButtonScrollSpeed"_F});return true;},ButtonAttr::UNSELECTABLE_VIA_KEYBOARD)DEPTH -1 END;
|
||||
subWindow=ViewPort::rectViewPort({},rect.size,Menu::menus[parentMenu]->pos+rect.pos);
|
||||
if(upButton){upButton->Enable(!disabled);}
|
||||
if(downButton){downButton->Enable(!disabled);}
|
||||
@ -132,7 +142,7 @@ protected:
|
||||
float scrollBarScale=(spaceBetweenTopAndBottomArrows/totalContentHeight);
|
||||
//The scroll amount moves centered on the position the mouse is at.
|
||||
float newScrollbarTop=(game->GetMousePos().y-windowAbsPos.y-12)-scrollBarHeight/2;
|
||||
V(A::SCROLL_OFFSET).y=(-newScrollbarTop+1)/scrollBarScale; //Derived formula from the draw code.
|
||||
SetScrollAmount({GetScrollAmount().x,(-newScrollbarTop+1)/scrollBarScale});
|
||||
}
|
||||
}else{
|
||||
scrollBarHoverTime=std::max(scrollBarHoverTime-game->GetElapsedTime(),0.f);
|
||||
@ -140,16 +150,16 @@ protected:
|
||||
|
||||
if(game->GetMouseWheel()!=0){
|
||||
if(game->GetMouseWheel()>0){
|
||||
V(A::SCROLL_OFFSET).y+="ThemeGlobal.MenuScrollWheelSpeed"_I;
|
||||
SetScrollAmount(GetScrollAmount()+vf2d{0,"ThemeGlobal.MenuScrollWheelSpeed"_F});
|
||||
}else{
|
||||
V(A::SCROLL_OFFSET).y-="ThemeGlobal.MenuScrollWheelSpeed"_I;
|
||||
SetScrollAmount(GetScrollAmount()-vf2d{0,"ThemeGlobal.MenuScrollWheelSpeed"_F});
|
||||
}
|
||||
}
|
||||
|
||||
if(bounds.size.y-rect.size.y>0){
|
||||
V(A::SCROLL_OFFSET).y=std::clamp(V(A::SCROLL_OFFSET).y,-(bounds.size.y-rect.size.y),0.f);
|
||||
SetScrollAmount({GetScrollAmount().x,std::clamp(GetScrollAmount().y,-(bounds.size.y-rect.size.y),0.f)});
|
||||
}else{
|
||||
V(A::SCROLL_OFFSET).y=0;
|
||||
SetScrollAmount({GetScrollAmount().x,0});
|
||||
}
|
||||
|
||||
std::sort(components.begin(),components.end(),[](MenuComponent*c1,MenuComponent*c2){return c1->depth>c2->depth;});
|
||||
@ -172,7 +182,7 @@ protected:
|
||||
if(totalContentHeight==0)totalContentHeight=1;
|
||||
float scrollBarScale=(spaceBetweenTopAndBottomArrows/totalContentHeight);
|
||||
scrollBarHeight=std::min(spaceBetweenTopAndBottomArrows,viewHeight*scrollBarScale-1);
|
||||
scrollBarTop=-V(A::SCROLL_OFFSET).y*scrollBarScale+1;
|
||||
scrollBarTop=-GetScrollAmount().y*scrollBarScale+1;
|
||||
|
||||
float focusedWindowColorMult=(focused?1:"ThemeGlobal.MenuUnfocusedColorMult"_F);
|
||||
|
||||
@ -180,18 +190,18 @@ protected:
|
||||
window.DrawRectDecal(rect.pos+parentPos+vf2d{rect.size.x-11.75f,scrollBarTop+12},{12,scrollBarHeight},WHITE*focusedWindowColorMult);
|
||||
}
|
||||
|
||||
virtual inline void DrawDecal(ViewPort&window,vf2d parentPos,bool focused)override{
|
||||
MenuComponent::DrawDecal(window,parentPos,focused);
|
||||
virtual inline void DrawDecal(ViewPort&window,bool focused)override{
|
||||
MenuComponent::DrawDecal(window,focused);
|
||||
if(border){
|
||||
window.DrawRectDecal(rect.pos,rect.size);
|
||||
}
|
||||
for(MenuComponent*component:components){
|
||||
component->_DrawDecal(subWindow,V(A::SCROLL_OFFSET),focused);
|
||||
component->_DrawDecal(subWindow,focused);
|
||||
}
|
||||
DrawScrollbar(window,{},focused);
|
||||
}
|
||||
virtual bool GetHoverState(Crawler*game,MenuComponent*child)override{
|
||||
return geom2d::overlaps(geom2d::rect<float>{Menu::menus[parentMenu]->pos+rect.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,child->rect.size},game->GetMousePos());
|
||||
}
|
||||
//Calculates the bounds of all components.
|
||||
geom2d::rect<float> inline CalculateBounds(){
|
||||
@ -255,8 +265,7 @@ public:
|
||||
}
|
||||
virtual inline bool HandleOutsideDisabledButtonSelection(MenuComponent*disabledButton)override{
|
||||
//Set the offset so the center is highlighted by this button.
|
||||
V(A::SCROLL_OFFSET).y=-(disabledButton->rect.pos.y-disabledButton->rect.size.y/2);
|
||||
V(A::SCROLL_OFFSET).y+=rect.size.y/2;
|
||||
SetScrollAmount(vf2d{GetScrollAmount().x,-disabledButton->rect.pos.y+disabledButton->rect.size.y});
|
||||
return true;
|
||||
};
|
||||
virtual void Cleanup()override{}
|
||||
|
@ -64,16 +64,16 @@ protected:
|
||||
MenuComponent::Update(game);
|
||||
anim.UpdateState(state,game->GetElapsedTime());
|
||||
}
|
||||
virtual void inline DrawDecal(ViewPort&window,vf2d parentPos,bool focused)override{
|
||||
virtual void inline DrawDecal(ViewPort&window,bool focused)override{
|
||||
const geom2d::rect<int>&imgRect=anim.GetFrame(state).GetSourceRect();
|
||||
vf2d imgSize=vf2d{rect.size.y,rect.size.y};
|
||||
vf2d imgScale=imgSize/vf2d{imgRect.size};
|
||||
window.DrawPartialDecal(parentPos+rect.pos,imgSize,anim.GetFrame(state).GetSourceImage()->Decal(),imgRect.pos,imgRect.size);
|
||||
window.DrawPartialDecal(rect.pos,imgSize,anim.GetFrame(state).GetSourceImage()->Decal(),imgRect.pos,imgRect.size);
|
||||
float verticalAlignYOffset=(rect.size.y-8)/2;
|
||||
std::string monsterName=MONSTER_DATA.at(monsterID).GetDisplayName();
|
||||
vf2d monsterNameTextSize=game->GetTextSizeProp(monsterName);
|
||||
float textXSpaceAvailable=rect.size.x-imgSize.x-4-16/*12 for the scrollbar*/;
|
||||
float textXScaling=textXSpaceAvailable/monsterNameTextSize.x;
|
||||
window.DrawShadowStringPropDecal(parentPos+rect.pos+vf2d{imgSize.x+4,verticalAlignYOffset},monsterName,WHITE,BLACK,{std::min(1.f,textXScaling),1});
|
||||
window.DrawShadowStringPropDecal(rect.pos+vf2d{imgSize.x+4,verticalAlignYOffset},monsterName,WHITE,BLACK,{std::min(1.f,textXScaling),1});
|
||||
}
|
||||
};
|
@ -39,7 +39,7 @@ All rights reserved.
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 2
|
||||
#define VERSION_PATCH 1
|
||||
#define VERSION_BUILD 3941
|
||||
#define VERSION_BUILD 3969
|
||||
|
||||
#define stringify(a) stringify_(a)
|
||||
#define stringify_(a) #a
|
||||
|
@ -4328,7 +4328,8 @@ namespace olc
|
||||
m_tp1 = m_tp2;
|
||||
|
||||
// Our time per frame coefficient
|
||||
float fElapsedTime = elapsedTime.count();
|
||||
float actualElapsedTime = elapsedTime.count();
|
||||
float fElapsedTime = std::clamp(elapsedTime.count(),0.f,1/30.f); //HACK fix. We can't have a negative time. Although using a more precise system clock should make this never occur. Also make sure if the game is too slow we advance by only 1/30th of a second.
|
||||
fLastElapsed = fElapsedTime;
|
||||
fRunTime += fElapsedTime;
|
||||
|
||||
@ -4441,7 +4442,7 @@ namespace olc
|
||||
renderer->DisplayFrame();
|
||||
|
||||
// Update Title Bar
|
||||
fFrameTimer += fElapsedTime;
|
||||
fFrameTimer += actualElapsedTime;
|
||||
nFrameCount++;
|
||||
if (fFrameTimer >= 1.0f)
|
||||
{
|
||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user