Toggle Interface implementation. Class toggling connections created and class switching via class selection menu completed.

pull/28/head
sigonasr2 1 year ago
parent 598ce523e9
commit cedb465c79
  1. 4
      Crawler/CharacterAbilityPreviewComponent.h
  2. 4
      Crawler/CharacterRotatingDisplay.h
  3. 28
      Crawler/ClassSelectionWindow.cpp
  4. 13
      Crawler/Crawler.cpp
  5. 2
      Crawler/Crawler.h
  6. 2
      Crawler/Crawler.vcxproj
  7. 6
      Crawler/Crawler.vcxproj.filters
  8. 10
      Crawler/Menu.cpp
  9. 4
      Crawler/MenuAnimatedIconButton.h
  10. 34
      Crawler/MenuAnimatedIconToggleButton.h
  11. 18
      Crawler/MenuComponent.cpp
  12. 7
      Crawler/MenuComponent.h
  13. 6
      Crawler/MenuIconButton.h
  14. 8
      Crawler/MenuLabel.h
  15. 6
      Crawler/ScrollableWindowComponent.h
  16. 42
      Crawler/Toggleable.h
  17. 2
      Crawler/Version.h
  18. 3
      Crawler/assets/config/configuration.txt

@ -19,8 +19,8 @@ protected:
virtual void inline Update(Crawler*game)override{
MenuLabel::Update(game);
}
virtual void inline Draw(Crawler*game,vf2d parentPos,bool focused)override{
MenuLabel::Draw(game,parentPos,focused);
virtual void inline Draw(Crawler*game,vf2d parentPos)override{
MenuLabel::Draw(game,parentPos);
game->DrawRect(parentPos+rect.pos+vi2d{2,2},vi2d{int(rect.size.y)-4,int(rect.size.y)-4});
ICONPOS
game->DrawSprite(iconPos,GFX[ability->icon].Sprite());

@ -22,9 +22,7 @@ protected:
timer-=2*PI;
}
}
virtual inline void Draw(Crawler*game,vf2d parentPos,bool focused)override{
//MenuComponent::Draw(game,parentPos,focused);
}
virtual inline void Draw(Crawler*game,vf2d parentPos)override{}
virtual inline void DrawDecal(Crawler*game,vf2d parentPos,bool focused)override{
//MenuComponent::DrawDecal(game,parentPos,focused);
game->DrawWarpedDecal(icon,std::array<vf2d,4>{

@ -3,7 +3,7 @@
#include "DEFINES.h"
#include "Menu.h"
#include "MenuLabel.h"
#include "MenuAnimatedIconButton.h"
#include "MenuAnimatedIconToggleButton.h"
#include "GameState.h"
INCLUDE_game
@ -27,7 +27,17 @@ void Menu::InitializeClassSelectionWindow(){
MenuComponent*backButton=new MenuComponent(CLASS_SELECTION,{{4+2,outlineSize.y+4-navigationButtonSize.y-2},navigationButtonSize},"Back",[](MenuFuncData data){Menu::CloseMenu();});
classSelectionWindow->AddComponent("Back Button",backButton);
MenuComponent*confirmButton=new MenuComponent(CLASS_SELECTION,{{outlineSize.x+4-navigationButtonSize.x-2,outlineSize.y+4-navigationButtonSize.y-2},navigationButtonSize},"Confirm",[](MenuFuncData data){GameState::ChangeState(States::GAME_RUN);});
MenuComponent*confirmButton=new MenuComponent(CLASS_SELECTION,{{outlineSize.x+4-navigationButtonSize.x-2,outlineSize.y+4-navigationButtonSize.y-2},navigationButtonSize},"Confirm",[](MenuFuncData data){
std::string selectedClass=data.component->S(A::CLASS_SELECTION);
INCLUDE_DATA
std::vector<std::string>classList=DATA["class_list"].GetValues();
auto it=std::find(classList.begin(),classList.end(),selectedClass);
int element=std::distance(classList.begin(),it);
Class cl=Class(1<<element);
data.game->ChangePlayerClass(cl);
GameState::ChangeState(States::GAME_RUN);
});
confirmButton->disabled=true;
classSelectionWindow->AddComponent("Confirm",confirmButton);
vf2d buttonPadding={2,2};
@ -53,6 +63,8 @@ void Menu::InitializeClassSelectionWindow(){
Trapper::walk_s,
Witch::walk_s,
};
std::vector<IToggleable*>toggleGroup;
for(int i=0;i<6;i++){
std::string className=classNames[i];
@ -68,17 +80,25 @@ void Menu::InitializeClassSelectionWindow(){
vf2d backgroundSize={floor(outlineSize.y/3-buttonPadding.y*3),outlineSize.y/3-buttonPadding.y*3}; //The floor is for fixing a small pixel rounding bug.
MenuLabel*backgroundOutline=new MenuLabel(CLASS_SELECTION,{backgroundOffsetPos,backgroundSize},"",1,true,false,true,true);
MenuLabel*classLabel=new MenuLabel(CLASS_SELECTION,{backgroundOffsetPos,buttonSize},className,1,true,true);
MenuAnimatedIconButton*classSprite=new MenuAnimatedIconButton(CLASS_SELECTION,{backgroundOffsetPos+vf2d{0,12},backgroundSize+vf2d{0,-buttonSize.y-12}},classAnimationName,[](MenuFuncData data){},false);
MenuAnimatedIconToggleButton*classSprite=new MenuAnimatedIconToggleButton(CLASS_SELECTION,{backgroundOffsetPos+vf2d{0,12},backgroundSize+vf2d{0,-buttonSize.y-12}},classAnimationName,[](MenuFuncData data){
data.menu.components["Confirm"]->Enable(true);
data.menu.components["Confirm"]->S(A::CLASS_SELECTION)=data.component->S(A::CLASS_SELECTION);
});
toggleGroup.push_back(classSprite);
MenuComponent*classButton=new MenuComponent(CLASS_SELECTION,{offsetPos,buttonSize},"Info",CLASS_INFO,
[](MenuFuncData data){
data.menu.S(A::CLASS_SELECTION)=data.component->S(A::CLASS_SELECTION);
delete Menu::menus[CLASS_INFO];
Menu::InitializeClassInfoWindow();
});
classButton->S(A::CLASS_SELECTION)=className;
classSprite->S(A::CLASS_SELECTION)=classButton->S(A::CLASS_SELECTION)=className;
classSelectionWindow->AddComponent(className+" Button",classButton);
classSelectionWindow->AddComponent(className+" Background",backgroundOutline);
classSelectionWindow->AddComponent(className+" Label",classLabel);
classSelectionWindow->AddComponent(className+" Icon",classSprite);
}
for(IToggleable*item:toggleGroup){
item->SetToggleGroup(toggleGroup);
}
}

@ -20,6 +20,7 @@
#include "Menu.h"
#include "GameState.h"
#include "Item.h"
#include "Toggleable.h"
INCLUDE_EMITTER_LIST
@ -143,6 +144,8 @@ bool Crawler::OnUserCreate(){
GameState::Initialize();
ValidateGameStatus(); //Checks to make sure everything has been initialized properly.
return true;
}
@ -1818,4 +1821,14 @@ void Crawler::InitializeGraphics(){
MapTag Crawler::GetCurrentMap(){
return MAP_DATA[GetCurrentLevel()].MapData;
}
void Crawler::ValidateGameStatus(){
if(IToggleable::uninitializedToggleGroupItems.size()>0){
for(IToggleable*item:IToggleable::uninitializedToggleGroupItems){
std::cout<<"\tUninitialized Toggle Item Ptr: 0x"<<std::hex<<item<<std::endl;
}
std::cout<<"Error TOGGLE!!! Please turn on debug_toggleable_items in configuration.txt and re-run the program to see which toggleable item did not properly get a toggleable group set."<<std::endl;
throw;
}
}

@ -60,6 +60,8 @@ private:
int totalBossEncounterMobs=0;
std::vector<Monster>monstersToBeSpawned;
void ValidateGameStatus();
public:
Crawler();
bool OnUserCreate() override;

@ -276,6 +276,7 @@
<ClInclude Include="Emitter.h" />
<ClInclude Include="GameState.h" />
<ClInclude Include="Item.h" />
<ClInclude Include="MenuAnimatedIconToggleButton.h" />
<ClInclude Include="MenuComponent.h" />
<ClInclude Include="MenuIconButton.h" />
<ClInclude Include="MenuItemButton.h" />
@ -303,6 +304,7 @@
<ClInclude Include="State.h" />
<ClInclude Include="Theme.h" />
<ClInclude Include="TMXParser.h" />
<ClInclude Include="Toggleable.h" />
<ClInclude Include="TSXParser.h" />
<ClInclude Include="utils.h" />
<ClInclude Include="Version.h" />

@ -204,6 +204,12 @@
<ClInclude Include="CharacterAbilityPreviewComponent.h">
<Filter>Header Files\Interface</Filter>
</ClInclude>
<ClInclude Include="MenuAnimatedIconToggleButton.h">
<Filter>Header Files\Interface</Filter>
</ClInclude>
<ClInclude Include="Toggleable.h">
<Filter>Source Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Player.cpp">

@ -276,13 +276,13 @@ void Menu::Draw(Crawler*game){
game->Clear(BLANK);
for(auto&component:displayComponents){
if(component->renderInMain){
component->_Draw(game,{0,0},this==Menu::stack.back());
component->_Draw(game,{0,0});
}
}
for(auto&key:buttons){
for(auto&button:key.second){
if(button->renderInMain){
button->_Draw(game,{0,0},this==Menu::stack.back());
button->_Draw(game,{0,0});
}
}
}
@ -321,14 +321,14 @@ void Menu::Draw(Crawler*game){
if(selectedComponent->parentComponent!=nullptr){
drawOffset+=selectedComponent->parentComponent->V(A::SCROLL_OFFSET);
}
draggingComponent->Draw(game,drawOffset+pos-offsetPos+selectedComponent->rect.pos+vi2d{1,-4},this==Menu::stack.back());
draggingComponent->Draw(game,drawOffset+pos-offsetPos+selectedComponent->rect.pos+vi2d{1,-4});
}else{
draggingComponent->Draw(game,-offsetPos+game->GetMousePos(),this==Menu::stack.back());
draggingComponent->Draw(game,-offsetPos+game->GetMousePos());
}
game->SetPixelMode(prevMode);
game->SetDrawTarget(nullptr);
overlay.Decal()->Update();
game->DrawDecal({0,0},overlay.Decal());
game->DrawDecal({0,0},overlay.Decal(),{1,1},this==Menu::stack.back()?WHITE:WHITE*"ThemeGlobal.MenuUnfocusedColorMult"_F);
if(!UsingMouseNavigation()){
MenuComponent*selectedComponent=buttons[selection.y][selection.x];
vf2d drawOffset{};

@ -19,8 +19,8 @@ protected:
MenuIconButton::Update(game);
animationTime+=game->GetElapsedTime();
}
virtual inline void Draw(Crawler*game,vf2d parentPos,bool focused)override{
MenuComponent::Draw(game,parentPos,focused); //INTENTIONAL! The way we draw animations is different from static images, we skip over MenuIconButton's draw!
virtual inline void Draw(Crawler*game,vf2d parentPos)override{
MenuComponent::Draw(game,parentPos); //INTENTIONAL! The way we draw animations is different from static images, we skip over MenuIconButton's draw!
Sprite*spr=ANIMATION_DATA[animation].GetFrame(animationTime).GetSourceImage()->Sprite();
geom2d::rect<int>sprRect=ANIMATION_DATA[animation].GetFrame(animationTime).GetSourceRect();
game->DrawPartialSprite(parentPos+rect.middle()-sprRect.size/2,spr,sprRect.pos,sprRect.size,1,Sprite::Flip::NONE);

@ -0,0 +1,34 @@
#pragma once
#include "MenuAnimatedIconButton.h"
#include "DEFINES.h"
#include "Crawler.h"
#include "Toggleable.h"
INCLUDE_game
class MenuAnimatedIconToggleButton:public MenuAnimatedIconButton,public IToggleable{
protected:
MenuFunc _onClick; //What the user-defined behavior is. This toggle has its own custom-built onClick stuff to do.
private:
float animationTime=0;
public:
inline MenuAnimatedIconToggleButton(MenuType parent,geom2d::rect<float>rect,std::string animation,MenuFunc onClick)
:MenuAnimatedIconButton(parent,rect,animation,[](MenuFuncData data){
MenuAnimatedIconToggleButton*button=(MenuAnimatedIconToggleButton*)data.component;
button->Select();
button->_onClick(data);
}),_onClick(onClick){}
protected:
virtual inline void Update(Crawler*game)override{
MenuAnimatedIconButton::Update(game);
if(IsSelected()){
hoverEffect="ThemeGlobal.HighlightTime"_F; //A hack that allows us to make it look like we have this selected.
}
}
virtual inline void Draw(Crawler*game,vf2d parentPos)override{
MenuAnimatedIconButton::Draw(game,parentPos);
if(IsSelected()){
game->DrawRect(rect.pos+vi2d{2,2},rect.size-vi2d{4,4},YELLOW);
}
}
};

@ -43,21 +43,21 @@ void MenuComponent::_Update(Crawler*game){
}
}
void MenuComponent::Draw(Crawler*game,vf2d parentPos,bool focused){
void MenuComponent::Draw(Crawler*game,vf2d parentPos){
if(background){
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));
}
if(border){
game->DrawRect(rect.pos+parentPos,rect.size,focused?GREY:GREY*"ThemeGlobal.MenuUnfocusedColorMult"_F);
game->DrawRect(rect.pos+parentPos,rect.size);
}
if(showDefaultLabel){
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);
}
}
void MenuComponent::_Draw(Crawler*game,vf2d parentPos,bool focused){
void MenuComponent::_Draw(Crawler*game,vf2d parentPos){
if(!disabled){
Draw(game,parentPos,focused);
Draw(game,parentPos);
}
}
@ -110,4 +110,8 @@ void MenuComponent::OnInventorySlotsUpdate(ITCategory cat){}
std::string MenuComponent::GetLabel(){
return label;
}
}
void MenuComponent::Enable(bool enabled){
disabled=!enabled;
};

@ -8,12 +8,12 @@ class MenuComponent:IAttributable{
friend class InventoryScrollableWindowComponent;
MenuType menuDest;
private:
float hoverEffect=0;
virtual bool GetHoverState(Crawler*game);
//CALL THIS FOR A PARENT to check a child's DrawDecal validity!
virtual bool PointWithinParent(MenuComponent*child,vi2d drawPos);
std::pair<MenuType,std::string>memoryLeakInfo; //Used to identify memory leak hints for this component.
protected:
float hoverEffect=0;
std::string name="";
geom2d::rect<float>rect;
std::string label;
@ -31,7 +31,7 @@ protected:
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 valid=true; //If set to false, this would cause the component to be removed.
virtual void Update(Crawler*game);
virtual void Draw(Crawler*game,vf2d parentPos,bool focused);
virtual void Draw(Crawler*game,vf2d parentPos);
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.
@ -40,7 +40,7 @@ public:
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 _Draw(Crawler*game,vf2d parentPos);
void _DrawDecal(Crawler*game,vf2d parentPos,bool focused);
vf2d GetPos();
//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.
@ -53,4 +53,5 @@ public:
//Called whenever an inventory slot gets updated, whether it's adding or removing an item.
virtual void OnInventorySlotsUpdate(ITCategory cat);
std::string GetLabel();
void Enable(bool enabled);
};

@ -15,10 +15,10 @@ protected:
virtual inline void Update(Crawler*game)override{
MenuComponent::Update(game);
}
virtual inline void Draw(Crawler*game,vf2d parentPos,bool focused)override{
MenuComponent::Draw(game,parentPos,focused);
virtual inline void Draw(Crawler*game,vf2d parentPos)override{
MenuComponent::Draw(game,parentPos);
if(icon!=nullptr){
game->DrawSprite(parentPos+rect.middle()-icon->sprite->Size()/2,icon->sprite,1,Sprite::Flip::NONE,[&](Pixel&in){return focused?in:in*"ThemeGlobal.MenuUnfocusedColorMult"_F;});
game->DrawSprite(parentPos+rect.middle()-icon->sprite->Size()/2,icon->sprite,1,Sprite::Flip::NONE);
}
}
};

@ -24,17 +24,17 @@ protected:
virtual void inline Update(Crawler*game)override{
MenuComponent::Update(game);
}
virtual void inline Draw(Crawler*game,vf2d parentPos,bool focused)override{
MenuComponent::Draw(game,parentPos,focused);
virtual void inline Draw(Crawler*game,vf2d parentPos)override{
MenuComponent::Draw(game,parentPos);
std::string wrappedText=util::WrapText(game,label,rect.size.x,true,{float(scale),float(scale)});
vf2d drawPos=parentPos+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.
}
if(shadow){
game->DrawShadowStringProp(drawPos,wrappedText,focused?WHITE:WHITE*"ThemeGlobal.MenuUnfocusedColorMult"_F,BLACK,{float(scale),float(scale)});
game->DrawShadowStringProp(drawPos,wrappedText,WHITE,BLACK,{float(scale),float(scale)});
}else{
game->DrawStringProp(drawPos,wrappedText,focused?WHITE:WHITE*"ThemeGlobal.MenuUnfocusedColorMult"_F,scale);
game->DrawStringProp(drawPos,wrappedText,WHITE,scale);
}
}
};

@ -94,13 +94,13 @@ protected:
downButton->disabled=true;
}
}
virtual inline void Draw(Crawler*game,vf2d parentPos,bool focused)override{
MenuComponent::Draw(game,parentPos,focused);
virtual inline void Draw(Crawler*game,vf2d parentPos)override{
MenuComponent::Draw(game,parentPos);
Sprite*prevDrawTarget=game->GetDrawTarget();
game->SetDrawTarget(r.Sprite());
game->Clear(BLANK);
for(MenuComponent*component:components){
component->_Draw(game,rect.pos+V(A::SCROLL_OFFSET),focused);
component->_Draw(game,rect.pos+V(A::SCROLL_OFFSET));
}
game->SetDrawTarget(prevDrawTarget);
game->DrawSprite(parentPos,r.Sprite());

@ -0,0 +1,42 @@
#pragma once
class IToggleable{
friend class Crawler;
public:
inline std::vector<IToggleable*>GetToggleGroup(){
return toggleGroup;
}
inline void Select(){
for(IToggleable*item:toggleGroup){
item->selected=false;
}
selected=true;
}
inline bool IsSelected(){
return selected;
}
inline void SetToggleGroup(){
if(toggleGroupInitialized){
std::cout<<"WARNING! Toggle group for this component was set twice for some reason! THIS SHOULD NOT BE HAPPENING!"<<std::endl;
throw;
}
toggleGroupInitialized=true;
std::erase_if(uninitializedToggleGroupItems,[&](IToggleable*item){return this==item;});
}
inline void SetToggleGroup(std::vector<IToggleable*>toggleGroup){
this->toggleGroup=toggleGroup;
SetToggleGroup();
}
inline IToggleable(){
uninitializedToggleGroupItems.push_back(this);
if("debug_toggleable_items"_I){
std::cout<<"\tInitialized Toggle Item Ptr: 0x"<<std::hex<<this<<std::endl;
}
}
protected:
std::vector<IToggleable*>toggleGroup;
private:
bool selected=false;
bool toggleGroupInitialized=false;
inline static std::vector<IToggleable*>uninitializedToggleGroupItems;
};

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

@ -63,6 +63,9 @@ debug_collision_boxes = 0
# Shows pathfinding debugging
debug_pathfinding = 0
# Turn on to show when toggleable items are created and what their pointers are. This can help debug which toggleable item was not properly added to a tile group if you are getting Error TOGGLE.
debug_toggleable_items = 0
# ms precision of animation tile caching.
animation_tile_precision = 50

Loading…
Cancel
Save