Added scaling/tiling capabilities for themes. Safe maps have unordered version.
This commit is contained in:
parent
999855c6e8
commit
10cfb009f7
@ -216,8 +216,6 @@ void sig::Animation::InitializeAnimations(){
|
||||
if(!ANIMATION_DATA.count(imgFile)){
|
||||
std::cout<<"WARNING! Animation data for "<<imgFile<<" not found! Auto-generating..."<<std::endl;
|
||||
CreateStillAnimation(imgFile,GFX[imgFile].Sprite()->Size());
|
||||
std::map<int,int>test;
|
||||
test.begin();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -78,6 +78,7 @@ Crawler::Crawler()
|
||||
utils::datafile::Read(DATA,CONFIG_PATH + "class_directory"_S + cl + ".txt");
|
||||
}
|
||||
utils::datafile::DEBUG_ACCESS_OPTIONS="debug_access_options"_I;
|
||||
utils::datafile::INITIAL_SETUP_COMPLETE=true;
|
||||
}
|
||||
|
||||
bool Crawler::OnUserCreate(){
|
||||
@ -1682,7 +1683,7 @@ void Crawler::InitializeGraphics(){
|
||||
std::string key=val.first;
|
||||
std::string imgFile=DATA["Images"][key].GetString();
|
||||
std::cout<<"Loading image "+imgFile+"..."<<std::endl;
|
||||
if(GFX[imgFile].Load("GFX_Prefix"_S+imgFile,nullptr,false,false)!=rcode::OK){
|
||||
if(!GFX.count(imgFile)&&GFX[imgFile].Load("GFX_Prefix"_S+imgFile,nullptr,false,false)!=rcode::OK){
|
||||
std::cout<<" WARNING! Failed to load "+imgFile+"!";
|
||||
throw;
|
||||
}
|
||||
@ -1692,23 +1693,38 @@ void Crawler::InitializeGraphics(){
|
||||
for(auto&key:DATA["Themes"].GetKeys()){
|
||||
std::string themeName=key.first;
|
||||
std::string imgPath=DATA["Themes"][themeName]["Name"].GetString();
|
||||
Renderable&patchImg=GFX["theme_img_directory"_S+imgPath+".png"];
|
||||
Renderable&img=GFX["theme_img_directory"_S+imgPath+".png"];
|
||||
img.Load("GFX_Prefix"_S+"theme_img_directory"_S+imgPath+".png");
|
||||
Renderable&sourceImg=img;
|
||||
Pixel::Mode prevMode=GetPixelMode();
|
||||
SetPixelMode(Pixel::Mode::MASK);
|
||||
for(int x=0;x<3;x++){
|
||||
for(int y=0;y<3;y++){
|
||||
std::string patchKey=imgPath+"_"+std::to_string(x)+std::to_string(y)+".png";
|
||||
GFX[patchKey].Create("Interface.9PatchSize"_i[0],"Interface.9PatchSize"_i[1],false,false);
|
||||
SetDrawTarget(GFX[patchKey].Sprite());
|
||||
std::string patchKey=themeName+"_"+std::to_string(x)+std::to_string(y)+".png";
|
||||
Renderable&patchImg=GFX[patchKey];
|
||||
patchImg.Create("Interface.9PatchSize"_i[0],"Interface.9PatchSize"_i[1],false,false);
|
||||
SetDrawTarget(patchImg.Sprite());
|
||||
Clear(BLANK);
|
||||
DrawPartialSprite({0,0},patchImg.Sprite(),{x*"Interface.9PatchSize"_i[0],y*"Interface.9PatchSize"_i[1]},{"Interface.9PatchSize"_i[0],"Interface.9PatchSize"_i[1]});
|
||||
GFX[patchKey].Decal()->Update();
|
||||
DrawPartialSprite({0,0},sourceImg.Sprite(),{x*"Interface.9PatchSize"_i[0],y*"Interface.9PatchSize"_i[1]},{"Interface.9PatchSize"_i[0],"Interface.9PatchSize"_i[1]});
|
||||
patchImg.Decal()->Update();
|
||||
SetDrawTarget(nullptr);
|
||||
}
|
||||
}
|
||||
SetPixelMode(prevMode);
|
||||
Menu::themes[imgPath]=Theme{themeName,imgPath,DATA["Themes"][themeName]["ButtonColor"].GetPixel(),DATA["Themes"][themeName]["HighlightColor"].GetPixel()};
|
||||
|
||||
std::cout<<"Theme "<<themeName<<" Loaded."<<std::endl;
|
||||
|
||||
if(DATA["Themes"][themeName].HasProperty("CustomBack")){
|
||||
std::string backPath=DATA["Themes"][themeName]["CustomBack"].GetString();
|
||||
std::cout<<" Custom background detected, Loading "<<backPath<<"..."<<std::endl;
|
||||
if(!GFX.count(backPath)){
|
||||
Renderable&background=GFX[backPath];
|
||||
background.Load("GFX_Prefix"_S+backPath,nullptr,false,false);
|
||||
}
|
||||
Menu::themes[themeName]=Theme{themeName,imgPath,bool(DATA["Themes"][themeName]["Tiled"].GetInt()),DATA["Themes"][themeName]["ButtonColor"].GetPixel(),DATA["Themes"][themeName]["HighlightColor"].GetPixel(),GFX.at(backPath).Decal()};
|
||||
}else{
|
||||
Menu::themes[themeName]=Theme{themeName,imgPath,bool(DATA["Themes"][themeName]["Tiled"].GetInt()),DATA["Themes"][themeName]["ButtonColor"].GetPixel(),DATA["Themes"][themeName]["HighlightColor"].GetPixel()};
|
||||
}
|
||||
}
|
||||
|
||||
Menu::themes.SetInitialized();
|
||||
|
@ -6,8 +6,8 @@
|
||||
bool Menu::MOUSE_NAVIGATION=true;
|
||||
std::vector<Menu*>Menu::stack;
|
||||
std::map<MenuType,Menu>Menu::menus;
|
||||
std::string Menu::themeSelection="9patch";
|
||||
safemap<std::string,Theme>Menu::themes;
|
||||
std::string Menu::themeSelection="BlueDefault";
|
||||
safeunorderedmap<std::string,Theme>Menu::themes;
|
||||
|
||||
INCLUDE_GFX
|
||||
|
||||
@ -90,7 +90,7 @@ void Menu::Update(Crawler*game){
|
||||
void Menu::Draw(Crawler*game){
|
||||
vf2d upperLeftPos=game->GetScreenSize()/2-size/2;
|
||||
|
||||
if(scaled){
|
||||
if(GetCurrentTheme().IsScaled()){
|
||||
DrawScaledWindow(game,upperLeftPos);
|
||||
}else{
|
||||
DrawTiledWindow(game,upperLeftPos);
|
||||
@ -239,31 +239,32 @@ void Menu::KeyboardButtonNavigation(Crawler*game,vf2d menuPos){
|
||||
}
|
||||
}
|
||||
|
||||
void Menu::SetScaledPatchBorder(bool scaled){
|
||||
this->scaled=scaled;
|
||||
}
|
||||
|
||||
void Menu::DrawScaledWindow(Crawler*game,vf2d menuPos){
|
||||
vf2d patchSize={"Interface.9PatchSize"_f[0],"Interface.9PatchSize"_f[1]};
|
||||
|
||||
//Upper-Left
|
||||
game->DrawPartialDecal(menuPos-patchSize,patchSize,GFX["9patch.png"].Decal(),{patchSize.x*0,patchSize.y*0},patchSize);
|
||||
game->DrawPartialDecal(menuPos-patchSize,patchSize,GetPatchPart(0,0).Decal(),{patchSize.x*0,patchSize.y*0},patchSize);
|
||||
//Upper-Right
|
||||
game->DrawPartialDecal(menuPos+vf2d{size.x,-patchSize.y},patchSize,GFX["9patch.png"].Decal(),{patchSize.x*2,patchSize.y*0},patchSize);
|
||||
game->DrawPartialDecal(menuPos+vf2d{size.x,-patchSize.y},patchSize,GetPatchPart(2,0).Decal(),{patchSize.x*2,patchSize.y*0},patchSize);
|
||||
//Bottom-Left
|
||||
game->DrawPartialDecal(menuPos+vf2d{-patchSize.x,size.y},patchSize,GFX["9patch.png"].Decal(),{patchSize.x*0,patchSize.y*2},patchSize);
|
||||
game->DrawPartialDecal(menuPos+vf2d{-patchSize.x,size.y},patchSize,GetPatchPart(0,2).Decal(),{patchSize.x*0,patchSize.y*2},patchSize);
|
||||
//Bottom-Right
|
||||
game->DrawPartialDecal(menuPos+vf2d{size.x,size.y},patchSize,GFX["9patch.png"].Decal(),{patchSize.x*2,patchSize.y*2},patchSize);
|
||||
game->DrawPartialDecal(menuPos+vf2d{size.x,size.y},patchSize,GetPatchPart(2,2).Decal(),{patchSize.x*2,patchSize.y*2},patchSize);
|
||||
//Top
|
||||
game->DrawPartialDecal(menuPos+vf2d{0,-patchSize.y},vf2d{size.x,patchSize.y},GFX["9patch.png"].Decal(),{patchSize.x*1,patchSize.y*0},patchSize);
|
||||
game->DrawPartialDecal(menuPos+vf2d{0,-patchSize.y},vf2d{size.x,patchSize.y},GetPatchPart(1,0).Decal(),{patchSize.x*1,patchSize.y*0},patchSize);
|
||||
//Left
|
||||
game->DrawPartialDecal(menuPos+vf2d{-patchSize.x,0},vf2d{patchSize.x,size.y},GFX["9patch.png"].Decal(),{patchSize.x*0,patchSize.y*1},patchSize);
|
||||
game->DrawPartialDecal(menuPos+vf2d{-patchSize.x,0},vf2d{patchSize.x,size.y},GetPatchPart(0,1).Decal(),{patchSize.x*0,patchSize.y*1},patchSize);
|
||||
//Right
|
||||
game->DrawPartialDecal(menuPos+vf2d{size.x,0},vf2d{patchSize.x,size.y},GFX["9patch.png"].Decal(),{patchSize.x*2,patchSize.y*1},patchSize);
|
||||
game->DrawPartialDecal(menuPos+vf2d{size.x,0},vf2d{patchSize.x,size.y},GetPatchPart(2,1).Decal(),{patchSize.x*2,patchSize.y*1},patchSize);
|
||||
//Bottom
|
||||
game->DrawPartialDecal(menuPos+vf2d{0,size.y},vf2d{size.x,patchSize.y},GFX["9patch.png"].Decal(),{patchSize.x*1,patchSize.y*2},patchSize);
|
||||
game->DrawPartialDecal(menuPos+vf2d{0,size.y},vf2d{size.x,patchSize.y},GetPatchPart(1,2).Decal(),{patchSize.x*1,patchSize.y*2},patchSize);
|
||||
//Center
|
||||
game->DrawPartialDecal(menuPos,size,GFX["9patch.png"].Decal(),{patchSize.x*1,patchSize.y*1},patchSize);
|
||||
if(GetCurrentTheme().HasBackground()){
|
||||
Decal*back=GetCurrentTheme().GetBackground();
|
||||
game->DrawPartialDecal(menuPos,size,back,{0,0},back->sprite->Size());
|
||||
}else{
|
||||
game->DrawPartialDecal(menuPos,size,GetPatchPart(1,1).Decal(),{patchSize.x*1,patchSize.y*1},patchSize);
|
||||
}
|
||||
}
|
||||
|
||||
void Menu::DrawTiledWindow(Crawler*game,vf2d menuPos){
|
||||
@ -286,9 +287,18 @@ void Menu::DrawTiledWindow(Crawler*game,vf2d menuPos){
|
||||
//Bottom
|
||||
game->DrawPartialDecal(menuPos+vf2d{0,size.y},vf2d{size.x,patchSize.y},GetPatchPart(1,2).Decal(),{0,0},vf2d{size.x,patchSize.y});
|
||||
//Center
|
||||
game->DrawPartialDecal(menuPos,size,GetPatchPart(1,1).Decal(),{0,0},patchSize);
|
||||
if(GetCurrentTheme().HasBackground()){
|
||||
Decal*back=GetCurrentTheme().GetBackground();
|
||||
game->DrawPartialDecal(menuPos,size,back,{0,0},size);
|
||||
}else{
|
||||
game->DrawPartialDecal(menuPos,size,GetPatchPart(1,1).Decal(),{0,0},patchSize);
|
||||
}
|
||||
}
|
||||
|
||||
Renderable&Menu::GetPatchPart(int x,int y){
|
||||
return GFX[themeSelection+"_"+std::to_string(x)+std::to_string(y)+".png"];
|
||||
}
|
||||
|
||||
Theme&Menu::GetCurrentTheme(){
|
||||
return themes[themeSelection];
|
||||
}
|
@ -19,19 +19,17 @@ class Menu:IAttributable{
|
||||
safemap<std::string,MenuComponent*>components; //A friendly way to interrogate any component we are interested in.
|
||||
vi2d selection={-1,-1};
|
||||
vf2d size; //Size in tiles (24x24), every menu will be tile-based
|
||||
bool scaled=false; //Whether or not the patch border is supposed to be scaled or tiled.
|
||||
public:
|
||||
Menu();
|
||||
Menu(vf2d size);
|
||||
void AddComponent(std::string key,MenuComponent*button);
|
||||
void Update(Crawler*game);
|
||||
void Draw(Crawler*game);
|
||||
void SetScaledPatchBorder(bool scaled);
|
||||
static void InitializeMenus();
|
||||
static void OpenMenu(MenuType menu);
|
||||
static std::vector<Menu*>stack;
|
||||
static std::string themeSelection;
|
||||
static safemap<std::string,Theme>themes;
|
||||
static safeunorderedmap<std::string,Theme>themes;
|
||||
private:
|
||||
void MenuSelect(Crawler*game);
|
||||
static const Menu InitializeTestMenu();
|
||||
@ -39,6 +37,8 @@ private:
|
||||
//X (0-3), Y (0-2) for specific 9-patch tile (tiled version).
|
||||
static Renderable&GetPatchPart(int x,int y);
|
||||
|
||||
static Theme&GetCurrentTheme();
|
||||
|
||||
void KeyboardButtonNavigation(Crawler*game,vf2d menuPos);
|
||||
void DrawScaledWindow(Crawler*game,vf2d menuPos);
|
||||
void DrawTiledWindow(Crawler*game,vf2d menuPos);
|
||||
|
@ -9,14 +9,14 @@ MenuComponent::MenuComponent(geom2d::rect<float>rect,std::string label,MenuType
|
||||
|
||||
void MenuComponent::Update(Crawler*game){
|
||||
if(hovered){
|
||||
hoverEffect=std::min(1.f,hoverEffect+game->GetElapsedTime());
|
||||
hoverEffect=std::min("ThemeGlobal.HighlightTime"_F,hoverEffect+game->GetElapsedTime());
|
||||
}else{
|
||||
hoverEffect=std::max(0.f,hoverEffect-game->GetElapsedTime());
|
||||
}
|
||||
}
|
||||
|
||||
void MenuComponent::Draw(Crawler*game,vf2d parentPos){
|
||||
game->FillRectDecal(rect.pos+parentPos,rect.size,PixelLerp(Menu::themes[Menu::themeSelection].GetButtonCol(),Menu::themes[Menu::themeSelection].GetHighlightCol(),hoverEffect));
|
||||
game->FillRectDecal(rect.pos+parentPos,rect.size,PixelLerp(Menu::themes[Menu::themeSelection].GetButtonCol(),Menu::themes[Menu::themeSelection].GetHighlightCol(),hoverEffect/"ThemeGlobal.HighlightTime"_F));
|
||||
if(border){
|
||||
game->DrawRectDecal(rect.pos+parentPos,rect.size,GREY);
|
||||
}
|
||||
|
@ -536,7 +536,7 @@ bool Player::Hurt(int damage,bool onUpperLevel,float z){
|
||||
}
|
||||
|
||||
void Player::AddAnimation(std::string state){
|
||||
animation.AddState(state,ANIMATION_DATA[state]);
|
||||
animation.AddState(state,ANIMATION_DATA.at(state));
|
||||
}
|
||||
|
||||
void Player::UpdateAnimation(std::string animState,int specificClass){
|
||||
|
@ -17,8 +17,15 @@ const Menu Menu::InitializeTestSubMenu(){
|
||||
};
|
||||
|
||||
testSubMenu.AddComponent("BACK",new MenuComponent({{24*1,24*1},{24*2,24*1}},"Go Back",goBack));
|
||||
|
||||
testSubMenu.I(A::INDEXED_THEME)=0;
|
||||
|
||||
int index=0;
|
||||
for(auto&theme:Menu::themes){
|
||||
if(theme.first==Menu::themeSelection){
|
||||
testSubMenu.I(A::INDEXED_THEME)=index;
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
MenuFunc themePrev=[](Menu&menu,Crawler*game){
|
||||
bool found=false;
|
||||
|
@ -5,11 +5,13 @@ class Theme{
|
||||
std::string displayName;
|
||||
std::string imgPath;
|
||||
|
||||
bool tiled=true;
|
||||
Pixel buttonCol,highlightCol;
|
||||
Decal*background;
|
||||
public:
|
||||
inline Theme(){}
|
||||
inline Theme(std::string displayName,std::string imgPath,Pixel buttonCol,Pixel highlightCol)
|
||||
:displayName(displayName),imgPath(imgPath),buttonCol(buttonCol),highlightCol(highlightCol){}
|
||||
inline Theme(std::string displayName,std::string imgPath,bool tiled,Pixel buttonCol,Pixel highlightCol,Decal*background=nullptr)
|
||||
:displayName(displayName),imgPath(imgPath),tiled(tiled),buttonCol(buttonCol),highlightCol(highlightCol),background(background){}
|
||||
inline Pixel GetButtonCol(){
|
||||
return buttonCol;
|
||||
}
|
||||
@ -19,4 +21,13 @@ public:
|
||||
inline std::string GetThemeName(){
|
||||
return displayName;
|
||||
}
|
||||
inline bool IsScaled(){
|
||||
return !tiled;
|
||||
}
|
||||
inline bool HasBackground(){
|
||||
return background!=nullptr;
|
||||
}
|
||||
inline Decal*GetBackground(){
|
||||
return background;
|
||||
}
|
||||
};
|
@ -2,7 +2,7 @@
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 2
|
||||
#define VERSION_PATCH 0
|
||||
#define VERSION_BUILD 1676
|
||||
#define VERSION_BUILD 1704
|
||||
|
||||
#define stringify(a) stringify_(a)
|
||||
#define stringify_(a) #a
|
||||
|
@ -39,9 +39,6 @@ Images
|
||||
GFX_SkillOverlayIcon = skill_overlay_icon.png
|
||||
GFX_SkillOverlayIconOverlay = skill_overlay_icon_overlay.png
|
||||
|
||||
GFX_9Patch = themes/9patch.png
|
||||
GFX_9Patch2 = themes/9patch_2.png
|
||||
|
||||
# Ability Icons
|
||||
GFX_Warrior_BattleCry_Icon = Ability Icons/battlecry.png
|
||||
GFX_Warrior_Block_Icon = Ability Icons/block.png
|
||||
|
@ -1,25 +1,63 @@
|
||||
ThemeGlobal
|
||||
{
|
||||
# How long it takes for the fade-in/fade-out effect to occur.
|
||||
HighlightTime = 0.6
|
||||
}
|
||||
|
||||
Themes
|
||||
{
|
||||
# Provide the patch image names without the .png extensions.
|
||||
|
||||
BlueDefault
|
||||
{
|
||||
Name = "9patch"
|
||||
Name = 9patch
|
||||
|
||||
ButtonColor = 0,0,64,255
|
||||
HighlightColor = 0,200,200,255
|
||||
|
||||
# If set to 0, stretches the edges and center instead of tiling it.
|
||||
Tiled = 1
|
||||
|
||||
# Specifying a custom background from the assets directory uses that instead.
|
||||
#CustomBack = image.png
|
||||
}
|
||||
Purple
|
||||
{
|
||||
Name = "9patch_2"
|
||||
Name = 9patch_2
|
||||
|
||||
ButtonColor = 40,16,71,255
|
||||
HighlightColor = 192,128,238,255
|
||||
|
||||
# If set to 0, stretches the edges and center instead of tiling it.
|
||||
Tiled = 1
|
||||
|
||||
# Specifying a custom background from the assets directory uses that instead.
|
||||
#CustomBack = themes/testback.png
|
||||
}
|
||||
NicoPink
|
||||
{
|
||||
Name = 9patch_3
|
||||
|
||||
ButtonColor = 208,73,182,255
|
||||
HighlightColor = 255,239,232,255
|
||||
|
||||
# If set to 0, stretches the edges and center instead of tiling it.
|
||||
Tiled = 0
|
||||
|
||||
# Specifying a custom background from the assets directory uses that instead.
|
||||
CustomBack = themes/testback.png
|
||||
}
|
||||
NicoPinkTiled
|
||||
{
|
||||
Name = 9patch_4
|
||||
|
||||
ButtonColor = 208,73,182,255
|
||||
HighlightColor = 255,239,232,255
|
||||
|
||||
# If set to 0, stretches the edges and center instead of tiling it.
|
||||
Tiled = 1
|
||||
|
||||
# Specifying a custom background from the assets directory uses that instead.
|
||||
CustomBack = themes/testtiledback.png
|
||||
}
|
||||
}
|
BIN
Crawler/assets/themes/9patch_3.png
Normal file
BIN
Crawler/assets/themes/9patch_3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.8 KiB |
BIN
Crawler/assets/themes/9patch_4.png
Normal file
BIN
Crawler/assets/themes/9patch_4.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.8 KiB |
BIN
Crawler/assets/themes/testback.png
Normal file
BIN
Crawler/assets/themes/testback.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 236 KiB |
BIN
Crawler/assets/themes/testtiledback.png
Normal file
BIN
Crawler/assets/themes/testtiledback.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 620 B |
@ -71,6 +71,7 @@ namespace olc::utils
|
||||
public:
|
||||
inline datafile() = default;
|
||||
inline static bool DEBUG_ACCESS_OPTIONS=false;
|
||||
inline static bool INITIAL_SETUP_COMPLETE=false;
|
||||
|
||||
public:
|
||||
// Sets the String Value of a Property (for a given index)
|
||||
@ -444,6 +445,10 @@ namespace olc::utils
|
||||
// Check if this "node"'s map already contains an object with this name...
|
||||
if (m_mapObjects.count(name) == 0)
|
||||
{
|
||||
if(INITIAL_SETUP_COMPLETE){
|
||||
std::cout<<"WARNING! Key "<<name<<" does not exist in datafile!"<<std::endl; //We're not going to allow manual creation of nodes.
|
||||
throw;
|
||||
}
|
||||
// ...it did not! So create this object in the map. First get a vector id
|
||||
// and link it with the name in the unordered_map
|
||||
m_mapObjects[name] = m_vecObjects.size();
|
||||
|
@ -12,7 +12,68 @@ public:
|
||||
std::cout<<"WARNING! Trying to get non-existent key "<<key<<"!"<<std::endl;
|
||||
throw;
|
||||
}
|
||||
return map[key];
|
||||
if(!initialized){
|
||||
size_t originalSize=map.size();
|
||||
O&val=map[key];
|
||||
if(originalSize==map.size()){
|
||||
std::cout<<"WARNING! A previously set value has been overwritten! Key: "<<key<<std::endl;
|
||||
throw;
|
||||
}
|
||||
return val;
|
||||
}else{
|
||||
return map[key];
|
||||
}
|
||||
}
|
||||
O&at(T key){
|
||||
return map.at(key);
|
||||
}
|
||||
size_t count(T key){
|
||||
return map.count(key);
|
||||
}
|
||||
void SetInitialized(){
|
||||
initialized=true;
|
||||
}
|
||||
size_t size(){
|
||||
return map.size();
|
||||
}
|
||||
//Clears the entire map and unlocks the map so items can be added to it again.
|
||||
void Reset(){
|
||||
initialized=false;
|
||||
map.clear();
|
||||
}
|
||||
auto begin()const{
|
||||
return map.begin();
|
||||
}
|
||||
auto end()const{
|
||||
return map.end();
|
||||
}
|
||||
};
|
||||
|
||||
//A class that has an initialization lock so that when the lock is activated, any further gets that are missing items in it will report themselves for easier debugging detection.
|
||||
template<typename T,typename O>
|
||||
class safeunorderedmap{
|
||||
std::unordered_map<T,O>map;
|
||||
bool initialized=false;
|
||||
public:
|
||||
O&operator[](T key){
|
||||
if(initialized&&map.count(key)==0){
|
||||
std::cout<<"WARNING! Trying to get non-existent key "<<key<<"!"<<std::endl;
|
||||
throw;
|
||||
}
|
||||
if(!initialized){
|
||||
size_t originalSize=map.size();
|
||||
O&val=map[key];
|
||||
if(originalSize==map.size()){
|
||||
std::cout<<"WARNING! A previously set value has been overwritten! Key: "<<key<<std::endl;
|
||||
throw;
|
||||
}
|
||||
return val;
|
||||
}else{
|
||||
return map[key];
|
||||
}
|
||||
}
|
||||
O&at(T key){
|
||||
return map.at(key);
|
||||
}
|
||||
size_t count(T key){
|
||||
return map.count(key);
|
||||
|
Loading…
x
Reference in New Issue
Block a user