Cytopia  0.3
A city building simulation game
UIManager.cxx
Go to the documentation of this file.
1 #include "UIManager.hxx"
2 
3 #include "Constants.hxx"
4 #include "ResourcesManager.hxx"
5 #include <MapFunctions.hxx>
6 #include "Map.hxx"
7 #include "basics/mapEdit.hxx"
8 #include "basics/Settings.hxx"
9 #include "basics/utils.hxx"
10 #include "LOG.hxx"
11 #include "Exception.hxx"
12 #include "GameStates.hxx"
13 #include "MapLayers.hxx"
14 #include "Filesystem.hxx"
15 #include "json.hxx"
16 #include "betterEnums.hxx"
17 #include <Camera.hxx>
18 
19 #ifdef USE_AUDIO
20 #include "../services/AudioMixer.hxx"
21 #endif
22 
23 #include <cmath>
24 #include <array>
25 
26 #include "imgui.h"
27 #include "imgui_impl_sdl.h"
28 #include "imgui_impl_sdlrenderer.h"
29 
30 #include <Settings.hxx>
31 
32 #ifdef MICROPROFILE_ENABLED
33 #include "microprofile/microprofile.h"
34 #endif
35 
36 namespace ui = ImGui;
37 
38 BETTER_ENUM(Action, int, RaiseTerrain, LowerTerrain, QuitGame, Demolish, ChangeTileType, ToggleVisibilityOfGroup, NewGame,
39  SaveGame, LoadGame, SaveSettings, ChangeResolution)
40 
41 void UIManager::init()
42 {
43  json uiLayout;
44 
45  loadSettings(uiLayout);
46  parseLayouts(uiLayout);
47 
49 }
50 
51 ImFont *UIManager::loadFont(const std::string &fontPath, uint32_t size)
52 {
53  auto *uiFonts = ImGui::GetIO().Fonts;
54  if (!fontDefault)
55  fontDefault = uiFonts->AddFontDefault();
56 
57  std::string hashName = fontPath;
58  hashName.append(std::to_string(size));
59  if (const auto it = m_loadedFonts.find(hashName); it != m_loadedFonts.end())
60  return it->second;
61 
62  ImFont *newFont = uiFonts->AddFontFromFileTTF(fontPath.c_str(), (float)size);
63  m_loadedFonts[hashName] = newFont;
64  uiFonts->Build();
65 
66  return newFont;
67 }
68 
70 {
71  std::string fontPath = fs::getBasePath() + Settings::instance().fontFileName.get(); // fix for macos, need to use abs path
72 
73  const auto names = {"MainMenuButtons", "PauseMenuButtons", "LoadDialogButtons", "BuildMenuButtons"};
74  for (const auto &name : names)
75  {
76  if (const auto it = m_layouts.find(name); it != m_layouts.end())
77  {
78  auto &layout = it->second;
79  layout.font = loadFont(fontPath, layout.fontSize);
80  }
81  }
82 }
83 
85 {
86  std::string jsonFileContent = fs::readFileAsString(Settings::instance().uiLayoutJSONFile.get());
87  uiLayout = json::parse(jsonFileContent, nullptr, false);
88 
89  // check if json file can be parsed
90  if (uiLayout.is_discarded())
91  throw ConfigurationError(TRACE_INFO "Error parsing JSON File " + Settings::instance().uiLayoutJSONFile.get());
92 }
93 
94 void UIManager::parseLayouts(const json &uiLayout)
95 {
96  // parse Layout
97  for (const auto &it : uiLayout["LayoutGroups"].items())
98  {
99  std::string layoutGroupName;
100 
101  // prepare empty layout groups with layout information from json
102  for (size_t id = 0; id < uiLayout["LayoutGroups"][it.key()].size(); id++)
103  {
104  layoutGroupName = uiLayout["LayoutGroups"][it.key()][id].value("GroupName", "");
105 
106  if (!layoutGroupName.empty())
107  {
108  LayoutData layout;
109  layout.layoutType = uiLayout["LayoutGroups"][it.key()][id].value("LayoutType", "");
110  layout.alignment = uiLayout["LayoutGroups"][it.key()][id].value("Alignment", "");
111 
112  if (layout.layoutType.empty())
113  {
114  LOG(LOG_WARNING) << "Skipping LayoutGroup " << layoutGroupName
115  << " because it has no parameter \"LayoutType\" set. Check your UiLayout.json file.";
116  continue;
117  }
118 
119  if (layout.alignment.empty())
120  {
121  LOG(LOG_WARNING) << "Skipping LayoutGroup " << layoutGroupName
122  << " because it has no parameter \"Alignment\" set. Check your UiLayout.json file.";
123  continue;
124  }
125 
126  layout.fontSize = uiLayout["LayoutGroups"][it.key()][id].value("FontSize", Settings::instance().defaultFontSize);
127  layout.padding = uiLayout["LayoutGroups"][it.key()][id].value("Padding", 0);
128  layout.paddingToParent = uiLayout["LayoutGroups"][it.key()][id].value("PaddingToParent", 0);
129  layout.alignmentOffset = uiLayout["LayoutGroups"][it.key()][id].value("AlignmentOffset", 0.0F);
130 
131  // add layout group information to container
132  m_layouts[layoutGroupName] = layout;
133  }
134  else
135  {
136  LOG(LOG_WARNING) << "Cannot add a Layout Group without a name. Check your UiLayout.json file.";
137  }
138  }
139  }
140 }
141 
143 
145 {
146  for (auto &m : m_persistentMenu)
147  {
148  m->closeSubmenus();
149  }
150 }
151 
153 {
154  if (std::none_of(std::begin(m_menuStack), std::end(m_menuStack), [&](const auto &m) { return m == menu; }))
155  {
156  m_menuStack.push_back(menu);
157 
158  Camera::instance().canScale(false);
159  Camera::instance().canMove(false);
160  }
161 }
162 
164 {
165  if (m_menuStack.empty())
166  return;
167 
168  m_menuStack.pop_back();
169 
172 }
173 
175 {
176  if (std::none_of(std::begin(m_persistentMenu), std::end(m_persistentMenu), [&](const auto &m) { return m == menu; }))
177  {
178  m_persistentMenu.push_back(menu);
179  }
180 }
181 
182 bool UIManager::isMouseHovered() const { return ImGui::IsAnyItemHovered(); }
183 
185 {
186 #ifdef MICROPROFILE_ENABLED
187  MICROPROFILE_SCOPEI("UI", "draw UI", MP_BLUE);
188 #endif
189  if (!m_menuStack.empty())
190  {
191  m_menuStack.back()->draw();
192  }
193 
194  for (const auto &m : m_persistentMenu)
195  {
196  m->draw();
197  }
198 
199  if (!m_tooltip.empty())
200  {
201  ImVec2 pos = ui::GetMousePos();
202  ui::SetCursorScreenPos(pos);
203  ui::Text(m_tooltip.c_str());
204  }
205 
206  if (m_showFpsCounter)
207  {
208  ui::SetNextWindowPos(ImVec2(0, 0));
209  ui::SetNextWindowSize(ImVec2(140, 20));
210 
211  bool open = true;
212  ui::Begin("##fpswindow", &open,
213  ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoScrollbar |
214  ImGuiWindowFlags_NoScrollWithMouse);
215  ui::Text(m_fpsCounter.c_str());
216  ui::SameLine();
217  ui::Checkbox("debug", &m_showDebugMenu);
218  ui::End();
219  }
220 }
221 
222 void UIManager::setTooltip(const std::string &tooltipText) { m_tooltip = tooltipText; }
223 
LayoutData::layoutType
std::string layoutType
<mandatory> how to layout, default = HORIZONTAL
Definition: Layout.hxx:10
TRACE_INFO
#define TRACE_INFO
Definition: Exception.hxx:12
GameMenu::Ptr
std::shared_ptr< GameMenu > Ptr
Definition: UIManager.hxx:13
LayoutData::alignmentOffset
float alignmentOffset
Offset in percent to the screen point. can be negative.
Definition: Layout.hxx:12
ConfigurationError
A configuration error.
Definition: Exception.hxx:36
UIManager::openMenu
void openMenu()
Definition: UIManager.hxx:96
UIManager::m_showFpsCounter
bool m_showFpsCounter
Definition: UIManager.hxx:148
UIManager::closeOpenMenus
void closeOpenMenus()
Close all open menus but the build menu.
Definition: UIManager.cxx:144
LOG
Definition: LOG.hxx:32
SettingsData::fontFileName
FilePath fontFileName
FilePath of the Font that should be used.
Definition: Settings.hxx:148
UIManager::setFPSCounterText
void setFPSCounterText(const std::string &fps)
Helper function to update the FPS Counter.
Definition: UIManager.cxx:142
LOG.hxx
UIManager::setTooltip
void setTooltip(const std::string &tooltipText)
Definition: UIManager.cxx:222
MapFunctions.hxx
UIManager::init
void init()
Parses the UiLayout.json files and creates UI Elements.
UIManager::m_loadedFonts
std::unordered_map< std::string, ImFont * > m_loadedFonts
Definition: UIManager.hxx:140
Camera.hxx
UIManager::m_fpsCounter
std::string m_fpsCounter
Definition: UIManager.hxx:147
Map.hxx
UIManager::m_tooltip
std::string m_tooltip
Definition: UIManager.hxx:138
UIManager::fontDefault
struct ImFont * fontDefault
pointer to the default font used for in-game text
Definition: UIManager.hxx:151
UIManager::m_layouts
std::unordered_map< std::string, LayoutData > m_layouts
map holding layput groups, accessible via the layoutgroup ID
Definition: UIManager.hxx:136
UIManager::parseLayouts
void parseLayouts(const json &uiLayout)
Definition: UIManager.cxx:94
UIManager::initializeImGuiFonts
void initializeImGuiFonts()
Definition: UIManager.cxx:69
UIManager::drawUI
void drawUI()
Renders all UI Widgets.
Definition: UIManager.cxx:184
readFileAsString
std::string readFileAsString(const std::string &fileName, bool binaryMode)
Read contents from a file as string.
Definition: Filesystem.cxx:12
GameStates.hxx
Camera::canMove
void canMove(bool move)
Definition: Camera.hxx:49
UIManager::closeMenu
void closeMenu()
Definition: UIManager.cxx:163
getBasePath
std::string getBasePath()
Get base path (where Cytopia is being run)
Definition: Filesystem.cxx:77
BETTER_ENUM
BETTER_ENUM(Action, int, RaiseTerrain, LowerTerrain, QuitGame, Demolish, ChangeTileType, ToggleVisibilityOfGroup, NewGame, SaveGame, LoadGame, SaveSettings, ChangeResolution) void UIManager
Definition: UIManager.cxx:38
ResourcesManager.hxx
mapEdit.hxx
Filesystem.hxx
LayoutData::fontSize
uint32_t fontSize
<internal> default font size of all elements in group
Definition: Layout.hxx:17
UIManager::isMouseHovered
bool isMouseHovered() const
Definition: UIManager.cxx:182
UIManager::m_menuStack
std::vector< GameMenu::Ptr > m_menuStack
Definition: UIManager.hxx:141
Settings.hxx
LayoutData::alignment
std::string alignment
<mandatory> where the element should be placed. e.g. CENTER
Definition: Layout.hxx:9
UIManager::m_persistentMenu
std::vector< GameMenu::Ptr > m_persistentMenu
Definition: UIManager.hxx:142
MapLayers.hxx
UIManager::loadSettings
void loadSettings(json &uiLayout)
Definition: UIManager.cxx:84
UIManager::clearTooltip
void clearTooltip()
Hides and resets the active tooltip.
Definition: UIManager.cxx:224
LayoutData::paddingToParent
int paddingToParent
padding between this group and the parent in pixels
Definition: Layout.hxx:14
UIManager::m_showDebugMenu
bool m_showDebugMenu
visibility of the debug menu
Definition: UIManager.hxx:145
utils.hxx
UIManager.hxx
UIManager::loadFont
struct ImFont * loadFont(const std::string &name, uint32_t size)
Definition: UIManager.cxx:51
Singleton< Settings >::instance
static Settings & instance(void)
Get an instance of the singleton.
Definition: Singleton.hxx:15
LayoutData::padding
int padding
padding between elements in pixels
Definition: Layout.hxx:13
UIManager::addPersistentMenu
void addPersistentMenu()
Definition: UIManager.hxx:126
Exception.hxx
json
nlohmann::json json
Definition: Settings.hxx:12
string
std::string string
Definition: AudioConfig.hxx:14
Camera::canScale
void canScale(bool value)
Definition: Camera.hxx:55
Constants.hxx
LayoutData
Definition: Layout.hxx:7
StrongType::get
WeakType & get() noexcept
Definition: Meta.hxx:126
LOG_WARNING
@ LOG_WARNING
Definition: LOG.hxx:27