diff --git a/Crawler/Crawler.cpp b/Crawler/Crawler.cpp index 7130058f..80cec8ae 100644 --- a/Crawler/Crawler.cpp +++ b/Crawler/Crawler.cpp @@ -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+"..."<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; } diff --git a/Crawler/InventoryWindow.cpp b/Crawler/InventoryWindow.cpp index a335cd2a..2fcac464 100644 --- a/Crawler/InventoryWindow.cpp +++ b/Crawler/InventoryWindow.cpp @@ -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(vf2d{2,initialInvHeight*totalSpacing+itemSpacing},{windowSize.x-4,windowSize.y-108}),"",true,true}; inventoryWindow->AddComponent("itemDescription",itemDescriptionLabel); - - return inventoryWindow; } \ No newline at end of file diff --git a/Crawler/Menu.cpp b/Crawler/Menu.cpp index 0bdf3a41..3bb75289 100644 --- a/Crawler/Menu.cpp +++ b/Crawler/Menu.cpp @@ -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;typecomponents){ + 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. } } diff --git a/Crawler/Menu.h b/Crawler/Menu.h index 60480180..91431d9d 100644 --- a/Crawler/Menu.h +++ b/Crawler/Menu.h @@ -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); diff --git a/Crawler/MenuComponent.cpp b/Crawler/MenuComponent.cpp index 08e3f8f8..6c6a3044 100644 --- a/Crawler/MenuComponent.cpp +++ b/Crawler/MenuComponent.cpp @@ -7,6 +7,8 @@ MenuComponent::MenuComponent(MenuType parent,geom2d::rectrect,std::string MenuComponent::MenuComponent(MenuType parent,geom2d::rectrect,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()); diff --git a/Crawler/MenuComponent.h b/Crawler/MenuComponent.h index b262fe0a..72c8daed 100644 --- a/Crawler/MenuComponent.h +++ b/Crawler/MenuComponent.h @@ -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::rectrect,std::string label,MenuFunc onClick,bool selectable=true); MenuComponent(MenuType parent,geom2d::rectrect,std::string label,MenuType menuDest,MenuFunc onClick,bool selectable=true); diff --git a/Crawler/ScrollableWindowComponent.h b/Crawler/ScrollableWindowComponent.h index aa788b23..dfd0b2f9 100644 --- a/Crawler/ScrollableWindowComponent.h +++ b/Crawler/ScrollableWindowComponent.h @@ -9,6 +9,8 @@ class ScrollableWindowComponent:public MenuComponent{ protected: Renderable r; std::vectorcomponents; + MenuComponent*upButton=nullptr; + MenuComponent*downButton=nullptr; geom2d::rectbounds; //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"<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{Menu::menus[parentMenu]->pos+child->rect.pos+V(A::SCROLL_OFFSET),child->rect.size},game->GetMousePos()); + return geom2d::overlaps(geom2d::rect{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){ diff --git a/Crawler/TestMenu.cpp b/Crawler/TestMenu.cpp index c49b31e4..81859fa9 100644 --- a/Crawler/TestMenu.cpp +++ b/Crawler/TestMenu.cpp @@ -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; } \ No newline at end of file diff --git a/Crawler/TestSubMenu.cpp b/Crawler/TestSubMenu.cpp index 51dc8d56..a1c926bf 100644 --- a/Crawler/TestSubMenu.cpp +++ b/Crawler/TestSubMenu.cpp @@ -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; } \ No newline at end of file diff --git a/Crawler/Version.h b/Crawler/Version.h index d4125829..bfb39e87 100644 --- a/Crawler/Version.h +++ b/Crawler/Version.h @@ -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 diff --git a/Crawler/assets/config/configuration.txt b/Crawler/assets/config/configuration.txt index ed49527d..38be4c1c 100644 --- a/Crawler/assets/config/configuration.txt +++ b/Crawler/assets/config/configuration.txt @@ -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 diff --git a/Crawler/assets/knight_full3.png b/Crawler/assets/knight_full3.png index 6cb9af39..66af0a1d 100644 Binary files a/Crawler/assets/knight_full3.png and b/Crawler/assets/knight_full3.png differ diff --git a/Crawler/assets/knight_full_render1.png b/Crawler/assets/knight_full_render1.png new file mode 100644 index 00000000..04f620e1 Binary files /dev/null and b/Crawler/assets/knight_full_render1.png differ