Add in support for subcomponents within subcomponents. Prioritize highest depth menu item when hovering over overlapping items.
This commit is contained in:
		
							parent
							
								
									59eb24b65b
								
							
						
					
					
						commit
						5fc5169ddd
					
				
							
								
								
									
										62
									
								
								Adventures in Lestoria/AccessoryRowItemDisplay.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								Adventures in Lestoria/AccessoryRowItemDisplay.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,62 @@ | |||||||
|  | #pragma region License | ||||||
|  | /*
 | ||||||
|  | License (OLC-3) | ||||||
|  | ~~~~~~~~~~~~~~~ | ||||||
|  | 
 | ||||||
|  | Copyright 2024 Joshua Sigona <sigonasr2@gmail.com> | ||||||
|  | 
 | ||||||
|  | Redistribution and use in source and binary forms, with or without modification, | ||||||
|  | are permitted provided that the following conditions are met: | ||||||
|  | 
 | ||||||
|  | 1. Redistributions or derivations of source code must retain the above copyright | ||||||
|  | notice, this list of conditions and the following disclaimer. | ||||||
|  | 
 | ||||||
|  | 2. Redistributions or derivative works in binary form must reproduce the above | ||||||
|  | copyright notice. This list of conditions and the following	disclaimer must be | ||||||
|  | reproduced in the documentation and/or other materials provided with the distribution. | ||||||
|  | 
 | ||||||
|  | 3. Neither the name of the copyright holder nor the names of its contributors may | ||||||
|  | be used to endorse or promote products derived from this software without specific | ||||||
|  | prior written permission. | ||||||
|  | 
 | ||||||
|  | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS	"AS IS" AND ANY | ||||||
|  | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||||||
|  | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT | ||||||
|  | SHALL THE COPYRIGHT	HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | ||||||
|  | INCIDENTAL,	SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | ||||||
|  | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||||||
|  | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  | CONTRACT, STRICT LIABILITY, OR TORT	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | ||||||
|  | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||||||
|  | SUCH DAMAGE. | ||||||
|  | 
 | ||||||
|  | Portions of this software are copyright © 2024 The FreeType | ||||||
|  | Project (www.freetype.org). Please see LICENSE_FT.txt for more information. | ||||||
|  | All rights reserved. | ||||||
|  | */ | ||||||
|  | #pragma endregion | ||||||
|  | #pragma once | ||||||
|  | #include "RowItemDisplay.h" | ||||||
|  | 
 | ||||||
|  | INCLUDE_game | ||||||
|  | INCLUDE_GFX | ||||||
|  | 
 | ||||||
|  | class AccessoryRowItemDisplay:public RowItemDisplay{ | ||||||
|  |     std::weak_ptr<MenuComponent>lockButton; | ||||||
|  | public: | ||||||
|  |     inline AccessoryRowItemDisplay(geom2d::rect<float>rect,const std::weak_ptr<Item>itemRef,MenuFunc onClick,std::string itemNameLabelName,std::string itemDescriptionLabelName,ButtonAttr attributes=ButtonAttr::NONE) | ||||||
|  |     :RowItemDisplay(rect,itemRef,onClick,itemNameLabelName,itemDescriptionLabelName,attributes){} | ||||||
|  |     inline ~AccessoryRowItemDisplay(){ | ||||||
|  |         if(!lockButton.expired()){ | ||||||
|  |             size_t subcomponentCount=parentComponent.lock()->GetSubcomponentCount(); | ||||||
|  |             parentComponent.lock()->RemoveButton(lockButton); | ||||||
|  |             if(parentComponent.lock()->GetSubcomponentCount()>=subcomponentCount)ERR(std::format("WARNING! The subcomponent count went from {} -> {} when trying to remove the lock button for item {}! THIS SHOULD NOT BE HAPPENING!",subcomponentCount,parentComponent.lock()->GetSubcomponentCount(),name)); | ||||||
|  |             lockButton.reset(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     virtual inline void AfterCreate()override final{ | ||||||
|  |         lockButton=parentComponent.lock()->ADDSUB(std::format("{}_lock",name),MenuComponent)(geom2d::rect<float>{rect.pos,vf2d{16.f,8.f}},"Lock",[](MenuFuncData data){ | ||||||
|  |             return true; | ||||||
|  |         })END; | ||||||
|  |     } | ||||||
|  | }; | ||||||
| @ -273,6 +273,7 @@ | |||||||
|   </ItemDefinitionGroup> |   </ItemDefinitionGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <ClInclude Include="Ability.h" /> |     <ClInclude Include="Ability.h" /> | ||||||
|  |     <ClInclude Include="AccessoryRowItemDisplay.h" /> | ||||||
|     <ClInclude Include="Animation.h" /> |     <ClInclude Include="Animation.h" /> | ||||||
|     <ClInclude Include="Attributable.h" /> |     <ClInclude Include="Attributable.h" /> | ||||||
|     <ClInclude Include="AttributableStat.h"> |     <ClInclude Include="AttributableStat.h"> | ||||||
|  | |||||||
| @ -477,6 +477,9 @@ | |||||||
|     <ClInclude Include="FloatingMenuComponent.h"> |     <ClInclude Include="FloatingMenuComponent.h"> | ||||||
|       <Filter>Header Files\Interface</Filter> |       <Filter>Header Files\Interface</Filter> | ||||||
|     </ClInclude> |     </ClInclude> | ||||||
|  |     <ClInclude Include="AccessoryRowItemDisplay.h"> | ||||||
|  |       <Filter>Header Files\Interface</Filter> | ||||||
|  |     </ClInclude> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <ClCompile Include="Player.cpp"> |     <ClCompile Include="Player.cpp"> | ||||||
|  | |||||||
| @ -37,6 +37,7 @@ All rights reserved. | |||||||
| #pragma endregion | #pragma endregion | ||||||
| #include "InventoryCreator.h" | #include "InventoryCreator.h" | ||||||
| #include "RowInventoryScrollableWindowComponent.h" | #include "RowInventoryScrollableWindowComponent.h" | ||||||
|  | #include "AccessoryRowItemDisplay.h" | ||||||
| 
 | 
 | ||||||
| #define DEFINE(SubName) InventoryCreator InventoryCreator::SubName##_InventoryUpdate(&InventoryCreator::SubName##_InventorySlotsUpdate,&InventoryCreator::SubName##_AddButtonOnSlotUpdate); | #define DEFINE(SubName) InventoryCreator InventoryCreator::SubName##_InventoryUpdate(&InventoryCreator::SubName##_InventorySlotsUpdate,&InventoryCreator::SubName##_AddButtonOnSlotUpdate); | ||||||
| 
 | 
 | ||||||
| @ -76,7 +77,7 @@ std::function<void(InventoryScrollableWindowComponent&component,ITCategory cat)> | |||||||
| std::function<void(InventoryScrollableWindowComponent&component,ITCategory cat)> InventoryCreator::RowPlayer_AddButtonOnSlotUpdate= | std::function<void(InventoryScrollableWindowComponent&component,ITCategory cat)> InventoryCreator::RowPlayer_AddButtonOnSlotUpdate= | ||||||
|     [](InventoryScrollableWindowComponent&component,ITCategory cat){ |     [](InventoryScrollableWindowComponent&component,ITCategory cat){ | ||||||
|         RowInventoryScrollableWindowComponent*c=DYNAMIC_CAST<RowInventoryScrollableWindowComponent*>(&component); |         RowInventoryScrollableWindowComponent*c=DYNAMIC_CAST<RowInventoryScrollableWindowComponent*>(&component); | ||||||
| 	    size_t invSize=c->components.size()+1; | 	    size_t invSize=c->GetMainComponentCount()+1; //Remove any subcomponents as they get in the way of the actual amount of items in the list.
 | ||||||
|         int invWidth=int(c->rect.size.x/(float(c->options.size.x)+c->options.padding)); |         int invWidth=int(c->rect.size.x/(float(c->options.size.x)+c->options.padding)); | ||||||
|         int x=int((invSize-1)%invWidth); |         int x=int((invSize-1)%invWidth); | ||||||
|         int y=int((invSize-1)/invWidth); |         int y=int((invSize-1)/invWidth); | ||||||
| @ -84,8 +85,12 @@ std::function<void(InventoryScrollableWindowComponent&component,ITCategory cat)> | |||||||
| 
 | 
 | ||||||
|         vf2d buttonSize=c->options.size; |         vf2d buttonSize=c->options.size; | ||||||
|         vf2d totalSpacing={c->options.padding+buttonSize.x,c->options.padding+buttonSize.y}; |         vf2d totalSpacing={c->options.padding+buttonSize.x,c->options.padding+buttonSize.y}; | ||||||
| 
 |         std::shared_ptr<RowItemDisplay>newItem; | ||||||
|         auto newItem=c->ADD("item_"+cat+"_"+std::to_string(itemIndex),RowItemDisplay)(geom2d::rect<float>{totalSpacing*vf2d{float(x),float(y)},buttonSize},Inventory::GetInventorySlot(cat,itemIndex),c->inventoryButtonClickAction,c->itemNameLabelName,c->itemDescriptionLabelName,c->inventoryButtonsActive?ButtonAttr::NONE:ButtonAttr::UNSELECTABLE)END; |         if(cat=="Accessories"){ | ||||||
|  |             newItem=c->ADD("item_"+cat+"_"+std::to_string(itemIndex),AccessoryRowItemDisplay)(geom2d::rect<float>{totalSpacing*vf2d{float(x),float(y)},buttonSize},Inventory::GetInventorySlot(cat,itemIndex),c->inventoryButtonClickAction,c->itemNameLabelName,c->itemDescriptionLabelName,c->inventoryButtonsActive?ButtonAttr::NONE:ButtonAttr::UNSELECTABLE)END; | ||||||
|  |         }else{ | ||||||
|  |             newItem=c->ADD("item_"+cat+"_"+std::to_string(itemIndex),RowItemDisplay)(geom2d::rect<float>{totalSpacing*vf2d{float(x),float(y)},buttonSize},Inventory::GetInventorySlot(cat,itemIndex),c->inventoryButtonClickAction,c->itemNameLabelName,c->itemDescriptionLabelName,c->inventoryButtonsActive?ButtonAttr::NONE:ButtonAttr::UNSELECTABLE)END; | ||||||
|  |         } | ||||||
|         newItem->SetCompactDescriptions(c->compact); |         newItem->SetCompactDescriptions(c->compact); | ||||||
|         newItem->SetPriceLabelType(c->priceLabel); |         newItem->SetPriceLabelType(c->priceLabel); | ||||||
|         newItem->SetHoverFunc(c->inventoryButtonHoverAction); |         newItem->SetHoverFunc(c->inventoryButtonHoverAction); | ||||||
|  | |||||||
| @ -167,6 +167,7 @@ void Menu::MenuSelect(AiL*game){ | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Menu::Update(AiL*game){ | void Menu::Update(AiL*game){ | ||||||
|  | 
 | ||||||
| 	if(!draggingComponent){ | 	if(!draggingComponent){ | ||||||
| 		HoverMenuSelect(game); | 		HoverMenuSelect(game); | ||||||
| 	} | 	} | ||||||
| @ -201,15 +202,19 @@ void Menu::Update(AiL*game){ | |||||||
| 		} | 		} | ||||||
| 	}else{ | 	}else{ | ||||||
| 		selection={}; | 		selection={}; | ||||||
| 		for(auto&[key,component]:components){ | 		std::vector<std::weak_ptr<MenuComponent>>allComponents; | ||||||
| 			if(component->selectable){ | 		std::for_each(components.begin(),components.end(),[&](auto&pair){allComponents.push_back(pair.second);}); | ||||||
| 				if(!component->disable&&!component->disableOutsideWindow&&!component->grayedOut){ | 		std::sort(allComponents.begin(),allComponents.end(),[](std::weak_ptr<MenuComponent>c1,std::weak_ptr<MenuComponent>c2){return c1.lock()->depth<c2.lock()->depth;}); | ||||||
| 					if(component->GetHoverState(game)){ | 		for(const auto&component:allComponents){ | ||||||
| 						if(!Menu::lastHover.expired()&&&*component!=&*Menu::lastHover.lock())SoundEffect::PlaySFX("Menu Navigate",SoundEffect::CENTERED); | 			if(component.lock()->selectable){ | ||||||
| 						Menu::lastHover=component; | 				if(!component.lock()->disable&&!component.lock()->disableOutsideWindow&&!component.lock()->grayedOut){ | ||||||
| 						component->hovered=true; | 					if(component.lock()->GetHoverState(game)){ | ||||||
|  | 						if(!Menu::lastHover.expired()&&&*component.lock()!=&*Menu::lastHover.lock())SoundEffect::PlaySFX("Menu Navigate",SoundEffect::CENTERED); | ||||||
|  | 						Menu::lastHover=component.lock(); | ||||||
|  | 						component.lock()->hovered=true; | ||||||
| 						itemHovered=true; | 						itemHovered=true; | ||||||
| 						SetSelection(std::weak_ptr<MenuComponent>(component)); | 						SetSelection(std::weak_ptr<MenuComponent>(component.lock())); | ||||||
|  | 						break; | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| @ -269,16 +274,16 @@ void Menu::Draw(AiL*game){ | |||||||
| 		DrawTiledWindowBackground(game,pos,size,GetRenderColor()); | 		DrawTiledWindowBackground(game,pos,size,GetRenderColor()); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	std::vector<std::weak_ptr<MenuComponent>>allComponents; |  | ||||||
| 	std::for_each(components.begin(),components.end(),[&](auto&pair){allComponents.push_back(pair.second);}); |  | ||||||
| 	std::sort(allComponents.begin(),allComponents.end(),[](std::weak_ptr<MenuComponent>c1,std::weak_ptr<MenuComponent>c2){return c1.lock()->depth>c2.lock()->depth;}); |  | ||||||
| 
 | 
 | ||||||
| 	if(GetCurrentTheme().IsScaled()){ | 	if(GetCurrentTheme().IsScaled()){ | ||||||
| 		DrawScaledWindowBorder(game,pos,size,GetRenderColor()); | 		DrawScaledWindowBorder(game,pos,size,GetRenderColor()); | ||||||
| 	}else{ | 	}else{ | ||||||
| 		DrawTiledWindowBorder(game,pos,size,GetRenderColor()); | 		DrawTiledWindowBorder(game,pos,size,GetRenderColor()); | ||||||
| 	} | 	} | ||||||
| 
 | 	 | ||||||
|  | 	std::vector<std::weak_ptr<MenuComponent>>allComponents; | ||||||
|  | 	std::for_each(components.begin(),components.end(),[&](auto&pair){allComponents.push_back(pair.second);}); | ||||||
|  | 	std::sort(allComponents.begin(),allComponents.end(),[](std::weak_ptr<MenuComponent>c1,std::weak_ptr<MenuComponent>c2){return c1.lock()->depth>c2.lock()->depth;}); | ||||||
| 	for(const auto&component:allComponents){ | 	for(const auto&component:allComponents){ | ||||||
| 		if(!component.expired()&&component.lock()->renderInMain){ | 		if(!component.expired()&&component.lock()->renderInMain){ | ||||||
| 			component.lock()->_DrawDecal(window,this==Menu::stack.back()); | 			component.lock()->_DrawDecal(window,this==Menu::stack.back()); | ||||||
| @ -688,11 +693,6 @@ void Menu::DrawThemedWindow(vf2d menuPos,vf2d size,Pixel renderColor){ | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| void Menu::RecalculateComponentCount(){ |  | ||||||
| 	componentCount=components.size(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const MenuType Menu::GetType()const{ | const MenuType Menu::GetType()const{ | ||||||
| 	return type; | 	return type; | ||||||
| } | } | ||||||
| @ -792,4 +792,8 @@ bool Menu::IsCurrentlyActive(MenuType type){ | |||||||
| 
 | 
 | ||||||
| void Menu::ReInitializeInputGroup(){ | void Menu::ReInitializeInputGroup(){ | ||||||
| 	helpDisplay.Initialize(inputGroups); | 	helpDisplay.Initialize(inputGroups); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const bool Menu::GameInitialized()const{ | ||||||
|  | 	return game->GameInitialized(); | ||||||
| } | } | ||||||
| @ -120,7 +120,6 @@ class Menu:public IAttributable{ | |||||||
| 
 | 
 | ||||||
|     float buttonHoldTime=0; |     float buttonHoldTime=0; | ||||||
|     static vi2d lastActiveMousePos; |     static vi2d lastActiveMousePos; | ||||||
|     int componentCount=0; |  | ||||||
|     float componentSelectionIndex=0.f; |     float componentSelectionIndex=0.f; | ||||||
|     //This variable is an override available to all menus that allows us to say we've clicked something, so do not handle any automatic clicking anymore of menus for this frame!
 |     //This variable is an override available to all menus that allows us to say we've clicked something, so do not handle any automatic clicking anymore of menus for this frame!
 | ||||||
|     static bool alreadyClicked; |     static bool alreadyClicked; | ||||||
| @ -140,7 +139,7 @@ public: | |||||||
|     std::shared_ptr<T>_AddComponent(std::string componentKey,std::shared_ptr<T>component,int depth=DEFAULT_DEPTH){ |     std::shared_ptr<T>_AddComponent(std::string componentKey,std::shared_ptr<T>component,int depth=DEFAULT_DEPTH){ | ||||||
| 	    component->parentMenu=type; | 	    component->parentMenu=type; | ||||||
|         if(depth==DEFAULT_DEPTH){ |         if(depth==DEFAULT_DEPTH){ | ||||||
| 		    component->depth=STARTING_DEPTH-componentCount; | 		    component->depth=STARTING_DEPTH-components.size(); | ||||||
| 	    }else{ | 	    }else{ | ||||||
| 		    component->depth=depth; | 		    component->depth=depth; | ||||||
| 	    } | 	    } | ||||||
| @ -151,7 +150,7 @@ public: | |||||||
| 	    components.SetInitialized(); | 	    components.SetInitialized(); | ||||||
| 	    lastRegisteredComponent=componentKey; | 	    lastRegisteredComponent=componentKey; | ||||||
| 
 | 
 | ||||||
| 	    RecalculateComponentCount(); |         if(GameInitialized())component->AfterCreate(); | ||||||
| 
 | 
 | ||||||
|         return component; |         return component; | ||||||
|     } |     } | ||||||
| @ -195,7 +194,6 @@ public: | |||||||
| 
 | 
 | ||||||
|     //X (0-2), Y (0-2) for specific 9-patch tile (tiled version).
 |     //X (0-2), Y (0-2) for specific 9-patch tile (tiled version).
 | ||||||
|     static Renderable&GetPatchPart(int x,int y); |     static Renderable&GetPatchPart(int x,int y); | ||||||
|     void RecalculateComponentCount(); |  | ||||||
|     void SetSelection(std::string_view button,const bool scroll=true,const bool reset=false); // Use the reset parameter when a window is opening up, as this will cause the window now to scroll to its previous target.
 |     void SetSelection(std::string_view button,const bool scroll=true,const bool reset=false); // Use the reset parameter when a window is opening up, as this will cause the window now to scroll to its previous target.
 | ||||||
|     void SetSelection(std::weak_ptr<MenuComponent>button,const bool scroll=true,const bool reset=false); // Use the reset parameter when a window is opening up, as this will cause the window now to scroll to its previous target.
 |     void SetSelection(std::weak_ptr<MenuComponent>button,const bool scroll=true,const bool reset=false); // Use the reset parameter when a window is opening up, as this will cause the window now to scroll to its previous target.
 | ||||||
|     void SetSelection(Data button,const bool reset=false); // Use the reset parameter when a window is opening up, as this will cause the window now to scroll to its previous target.
 |     void SetSelection(Data button,const bool reset=false); // Use the reset parameter when a window is opening up, as this will cause the window now to scroll to its previous target.
 | ||||||
| @ -224,6 +222,8 @@ private: | |||||||
|     //This triggers if we use a keyboard/controller input to try and select some off-screen menu item. We should ideally follow the menu cursor.
 |     //This triggers if we use a keyboard/controller input to try and select some off-screen menu item. We should ideally follow the menu cursor.
 | ||||||
|     bool HandleOutsideDisabledButtonSelection(std::weak_ptr<MenuComponent>disabledButton); |     bool HandleOutsideDisabledButtonSelection(std::weak_ptr<MenuComponent>disabledButton); | ||||||
| 
 | 
 | ||||||
|  |     const bool GameInitialized()const; | ||||||
|  | 
 | ||||||
|     Pixel GetRenderColor(); |     Pixel GetRenderColor(); | ||||||
|     MenuType type; |     MenuType type; | ||||||
|     MenuInputGroups inputGroups; |     MenuInputGroups inputGroups; | ||||||
|  | |||||||
| @ -42,6 +42,8 @@ All rights reserved. | |||||||
| 
 | 
 | ||||||
| using A=Attribute; | using A=Attribute; | ||||||
| 
 | 
 | ||||||
|  | #define ADDSUB(key,componentType) _AddSubcomponent<componentType>(key,std::make_shared<componentType> | ||||||
|  | 
 | ||||||
| INCLUDE_game | INCLUDE_game | ||||||
| 
 | 
 | ||||||
| class ScrollableWindowComponent:public MenuComponent{ | class ScrollableWindowComponent:public MenuComponent{ | ||||||
| @ -52,6 +54,7 @@ protected: | |||||||
|     std::weak_ptr<MenuComponent>upButton; |     std::weak_ptr<MenuComponent>upButton; | ||||||
|     std::weak_ptr<MenuComponent>downButton; |     std::weak_ptr<MenuComponent>downButton; | ||||||
|     geom2d::rect<float>bounds; //It's for the scrollbar.
 |     geom2d::rect<float>bounds; //It's for the scrollbar.
 | ||||||
|  |     std::vector<std::weak_ptr<MenuComponent>>subcomponents; //Subcomponents are anything that is created internally by another component.
 | ||||||
|     float scrollBarHeight=0; |     float scrollBarHeight=0; | ||||||
|     float scrollBarTop=0; |     float scrollBarTop=0; | ||||||
|     bool scrollBarSelected=false; |     bool scrollBarSelected=false; | ||||||
| @ -74,11 +77,26 @@ public: | |||||||
|         while(components.size()>0){ |         while(components.size()>0){ | ||||||
|             RemoveButton(components.back()); |             RemoveButton(components.back()); | ||||||
|         } |         } | ||||||
|  |         while(subcomponents.size()>0){ | ||||||
|  |             std::weak_ptr<MenuComponent>button=subcomponents.back(); | ||||||
|  |             std::string componentName=button.lock()->GetName(); | ||||||
|  |             subcomponents.erase(subcomponents.end()-1); | ||||||
|  |             size_t removedCount=0; | ||||||
|  | 
 | ||||||
|  |             MenuType parentMenu=button.lock()->parentMenu; | ||||||
|  | 
 | ||||||
|  |             removedCount+=Menu::menus[parentMenu]->components.erase(componentName); | ||||||
|  |             if(removedCount!=1){ | ||||||
|  |                 std::cout<<"WARNING! Attempted to remove subbuttons from button listing, but not found!"; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|     virtual inline void RemoveButton(std::weak_ptr<MenuComponent>button){ |     virtual inline void RemoveButton(std::weak_ptr<MenuComponent>button){ | ||||||
|         auto componentSearchResults=std::find_if(components.begin(),components.end(),[&](std::weak_ptr<MenuComponent>ptr){return &*ptr.lock()==&*button.lock();}); |         auto componentSearchResults=std::find_if(components.begin(),components.end(),[&](std::weak_ptr<MenuComponent>ptr){return &*ptr.lock()==&*button.lock();}); | ||||||
|         if(componentSearchResults==components.end())ERR("Could not find Component"<<std::quoted(button.lock()->GetName())<<" inside the component list!"); |         auto subcomponentSearchResults=std::find_if(subcomponents.begin(),subcomponents.end(),[&](std::weak_ptr<MenuComponent>ptr){return &*ptr.lock()==&*button.lock();}); | ||||||
|         components.erase(componentSearchResults); |         if(componentSearchResults==components.end()&&subcomponentSearchResults==subcomponents.end())ERR("Could not find Component "<<std::quoted(button.lock()->GetName())<<" inside the component or subcomponent lists!"); | ||||||
|  |         if(componentSearchResults!=components.end())components.erase(componentSearchResults); | ||||||
|  |         if(subcomponentSearchResults!=subcomponents.end())subcomponents.erase(subcomponentSearchResults); | ||||||
|         size_t removedCount=0; |         size_t removedCount=0; | ||||||
| 
 | 
 | ||||||
|         MenuType parentMenu=button.lock()->parentMenu; |         MenuType parentMenu=button.lock()->parentMenu; | ||||||
| @ -87,9 +105,14 @@ public: | |||||||
|         if(removedCount!=1){ |         if(removedCount!=1){ | ||||||
|             std::cout<<"WARNING! Attempted to remove buttons from button listing, but not found!"; |             std::cout<<"WARNING! Attempted to remove buttons from button listing, but not found!"; | ||||||
|         } |         } | ||||||
|         Menu::menus[parentMenu]->RecalculateComponentCount(); |  | ||||||
|         CalculateBounds(); |         CalculateBounds(); | ||||||
|     } |     } | ||||||
|  |     virtual inline size_t GetMainComponentCount()const{ | ||||||
|  |         return components.size(); | ||||||
|  |     } | ||||||
|  |     virtual inline size_t GetSubcomponentCount()const{ | ||||||
|  |         return subcomponents.size(); | ||||||
|  |     } | ||||||
|     virtual inline void SetScrollAmount(vf2d scrollOffset){ |     virtual inline void SetScrollAmount(vf2d scrollOffset){ | ||||||
|         this->targetScrollOffset=scrollOffset; |         this->targetScrollOffset=scrollOffset; | ||||||
|     } |     } | ||||||
| @ -148,6 +171,11 @@ protected: | |||||||
|             if(componentPtr->renderInMain)ERR(std::format("WARNING! Component {} is inside a ScrollableWindowComponent but renders in main instead! Parent Component: {}",componentPtr->GetName(),GetName())); |             if(componentPtr->renderInMain)ERR(std::format("WARNING! Component {} is inside a ScrollableWindowComponent but renders in main instead! Parent Component: {}",componentPtr->GetName(),GetName())); | ||||||
|             componentPtr->_BeforeUpdate(game); |             componentPtr->_BeforeUpdate(game); | ||||||
|         } |         } | ||||||
|  |         for(const auto&component:subcomponents){ | ||||||
|  |             std::shared_ptr<MenuComponent>componentPtr=component.lock(); | ||||||
|  |             if(componentPtr->renderInMain)ERR(std::format("WARNING! Subcomponent {} is inside a ScrollableWindowComponent but renders in main instead! Parent Component: {}",componentPtr->GetName(),GetName())); | ||||||
|  |             componentPtr->_BeforeUpdate(game); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|     virtual inline void Update(AiL*game)override{ |     virtual inline void Update(AiL*game)override{ | ||||||
| 	    MenuComponent::Update(game); | 	    MenuComponent::Update(game); | ||||||
| @ -210,6 +238,15 @@ protected: | |||||||
|             } |             } | ||||||
|             component.lock()->_Update(game); |             component.lock()->_Update(game); | ||||||
|         } |         } | ||||||
|  |         std::sort(subcomponents.begin(),subcomponents.end(),[](std::weak_ptr<MenuComponent>c1,std::weak_ptr<MenuComponent>c2){return c1.lock()->depth>c2.lock()->depth;});         | ||||||
|  |         for(std::weak_ptr<MenuComponent>component:subcomponents){ | ||||||
|  |             if(OnScreen(component.lock())){ | ||||||
|  |                 component.lock()->EnableOutsideWindow(); | ||||||
|  |             }else{ | ||||||
|  |                 component.lock()->DisableOutsideWindow(); | ||||||
|  |             } | ||||||
|  |             component.lock()->_Update(game); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         upButton.lock()->disable=false; |         upButton.lock()->disable=false; | ||||||
|         downButton.lock()->disable=false; |         downButton.lock()->disable=false; | ||||||
| @ -238,6 +275,9 @@ protected: | |||||||
|                 for(std::weak_ptr<MenuComponent>component:components){ |                 for(std::weak_ptr<MenuComponent>component:components){ | ||||||
|                     component.lock()->rect.pos=component.lock()->originalPos+scrollOffset; |                     component.lock()->rect.pos=component.lock()->originalPos+scrollOffset; | ||||||
|                 } |                 } | ||||||
|  |                 for(std::weak_ptr<MenuComponent>component:subcomponents){ | ||||||
|  |                     component.lock()->rect.pos=component.lock()->originalPos+scrollOffset; | ||||||
|  |                 } | ||||||
|                 lastScrollUpdate=1/60.f; |                 lastScrollUpdate=1/60.f; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @ -270,6 +310,9 @@ protected: | |||||||
|         for(std::weak_ptr<MenuComponent>component:components){ |         for(std::weak_ptr<MenuComponent>component:components){ | ||||||
|             component.lock()->_DrawDecal(subWindow,focused); |             component.lock()->_DrawDecal(subWindow,focused); | ||||||
|         } |         } | ||||||
|  |         for(std::weak_ptr<MenuComponent>component:subcomponents){ | ||||||
|  |             component.lock()->_DrawDecal(subWindow,focused); | ||||||
|  |         } | ||||||
|         if(!geom2d::contains(rect,bounds)){ |         if(!geom2d::contains(rect,bounds)){ | ||||||
|             DrawScrollbar(window,{},focused); |             DrawScrollbar(window,{},focused); | ||||||
|         } |         } | ||||||
| @ -298,8 +341,44 @@ public: | |||||||
|                 bounds.size.y+=sizeIncrease; |                 bounds.size.y+=sizeIncrease; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |         for(std::weak_ptr<MenuComponent>component:subcomponents){ | ||||||
|  |             if(component.lock()->rect.pos.x<bounds.pos.x){ | ||||||
|  |                 float sizeIncrease=bounds.pos.x-component.lock()->rect.pos.x; | ||||||
|  |                 bounds.size.x+=sizeIncrease; | ||||||
|  |                 bounds.pos.x=component.lock()->rect.pos.x; | ||||||
|  |             } | ||||||
|  |             if(component.lock()->rect.right().start.x>bounds.right().start.x){ | ||||||
|  |                 float sizeIncrease=component.lock()->rect.right().start.x-bounds.right().start.x; | ||||||
|  |                 bounds.size.x+=sizeIncrease; | ||||||
|  |             } | ||||||
|  |             if(component.lock()->rect.pos.y<bounds.pos.y){ | ||||||
|  |                 float sizeIncrease=bounds.pos.y-component.lock()->rect.pos.y; | ||||||
|  |                 bounds.size.y+=sizeIncrease; | ||||||
|  |                 bounds.pos.y=component.lock()->rect.pos.y; | ||||||
|  |             } | ||||||
|  |             if(component.lock()->rect.bottom().start.y>bounds.bottom().start.y){ | ||||||
|  |                 float sizeIncrease=component.lock()->rect.bottom().start.y-bounds.bottom().start.y; | ||||||
|  |                 bounds.size.y+=sizeIncrease; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| public: | public: | ||||||
|  |     template<class T> | ||||||
|  |     std::shared_ptr<T> _AddSubcomponent(std::string key,std::shared_ptr<T>button){ | ||||||
|  |         if(Menu::menus[parentMenu]->components.count(key)){ | ||||||
|  | 		    ERR("WARNING! Key "<<key<<" for menu"<<parentMenu<<" already exists! Key names must be unique!") | ||||||
|  | 	    } | ||||||
|  | 
 | ||||||
|  |         subcomponents.push_back(button); | ||||||
|  |         button->renderInMain=false; //Now we are in control!
 | ||||||
|  |         button->parentComponent=DYNAMIC_POINTER_CAST<ScrollableWindowComponent>(Menu::menus[parentMenu]->components[this->GetName()]); | ||||||
|  |         button->disable=disable; | ||||||
|  | 
 | ||||||
|  |         CalculateBounds(); | ||||||
|  | 
 | ||||||
|  |         Menu::menus[parentMenu]->_AddComponent(key,button); | ||||||
|  |         return button; | ||||||
|  |     } | ||||||
|     template<class T> |     template<class T> | ||||||
|     std::shared_ptr<T> _AddComponent(std::string key,std::shared_ptr<T>button){ |     std::shared_ptr<T> _AddComponent(std::string key,std::shared_ptr<T>button){ | ||||||
|         if(Menu::menus[parentMenu]->components.count(key)){ |         if(Menu::menus[parentMenu]->components.count(key)){ | ||||||
| @ -331,11 +410,17 @@ public: | |||||||
|     inline std::vector<std::weak_ptr<MenuComponent>>&GetComponents(){ |     inline std::vector<std::weak_ptr<MenuComponent>>&GetComponents(){ | ||||||
|         return components; |         return components; | ||||||
|     } |     } | ||||||
|  |     inline std::vector<std::weak_ptr<MenuComponent>>&GetSubcomponents(){ | ||||||
|  |         return subcomponents; | ||||||
|  |     } | ||||||
|     virtual inline void Enable()override final{ |     virtual inline void Enable()override final{ | ||||||
|         MenuComponent::Enable(); |         MenuComponent::Enable(); | ||||||
|         for(std::weak_ptr<MenuComponent>component:components){ |         for(std::weak_ptr<MenuComponent>component:components){ | ||||||
|             component.lock()->Enable(); |             component.lock()->Enable(); | ||||||
|         } |         } | ||||||
|  |         for(std::weak_ptr<MenuComponent>component:subcomponents){ | ||||||
|  |             component.lock()->Enable(); | ||||||
|  |         } | ||||||
|         if(upButton.lock()){upButton.lock()->Enable();} |         if(upButton.lock()){upButton.lock()->Enable();} | ||||||
|         if(downButton.lock()){downButton.lock()->Enable();} |         if(downButton.lock()){downButton.lock()->Enable();} | ||||||
|     }; |     }; | ||||||
| @ -344,6 +429,9 @@ public: | |||||||
|         for(std::weak_ptr<MenuComponent>component:components){ |         for(std::weak_ptr<MenuComponent>component:components){ | ||||||
|             component.lock()->Disable(); |             component.lock()->Disable(); | ||||||
|         } |         } | ||||||
|  |         for(std::weak_ptr<MenuComponent>component:subcomponents){ | ||||||
|  |             component.lock()->Disable(); | ||||||
|  |         } | ||||||
|         if(upButton.lock()){upButton.lock()->Disable();} |         if(upButton.lock()){upButton.lock()->Disable();} | ||||||
|         if(downButton.lock()){downButton.lock()->Disable();} |         if(downButton.lock()){downButton.lock()->Disable();} | ||||||
|     }; |     }; | ||||||
|  | |||||||
| @ -39,7 +39,7 @@ All rights reserved. | |||||||
| #define VERSION_MAJOR 0 | #define VERSION_MAJOR 0 | ||||||
| #define VERSION_MINOR 4 | #define VERSION_MINOR 4 | ||||||
| #define VERSION_PATCH 4 | #define VERSION_PATCH 4 | ||||||
| #define VERSION_BUILD 7910 | #define VERSION_BUILD 7947 | ||||||
| 
 | 
 | ||||||
| #define stringify(a) stringify_(a) | #define stringify(a) stringify_(a) | ||||||
| #define stringify_(a) #a | #define stringify_(a) #a | ||||||
|  | |||||||
										
											Binary file not shown.
										
									
								
							
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user