RunicVTT Open Source Virtual Tabletop for TTRPG using P2P
Loading...
Searching...
No Matches
GameTableManager.h
Go to the documentation of this file.
1#pragma once
2#include "BoardManager.h"
3#include "UiTypingGuard.h"
4#include <vector>
5#include "flecs.h"
6#include "Components.h"
7#include "PathManager.h"
8#include "NetworkManager.h"
9#include "ChatManager.h"
10#include "IdentityManager.h"
11
12class GameTableManager : public std::enable_shared_from_this<GameTableManager>
13{
14public:
15 GameTableManager(flecs::world ecs, std::shared_ptr<DirectoryWindow> map_directory, std::shared_ptr<DirectoryWindow> marker_directory);
17
18 void saveGameTable();
19 void loadGameTable(std::filesystem::path game_table_file_path);
20 void setCameraFboDimensions(glm::vec2 fbo_dimensions);
21 bool isBoardActive();
22 bool isGameTableActive();
23 //bool isConnectionActive();
24 void setup();
25 bool isConnected() const;
26
28
29 void hostGameTablePopUp();
30 void networkCenterPopUp();
36
38 void createBoardPopUp();
39 void closeBoardPopUp();
40 void saveBoardPopUp();
41 void loadBoardPopUp();
42
43 void guidePopUp();
44 void aboutPopUp();
45
46 //void renderNetworkToasts(std::shared_ptr<NetworkManager> nm);
47 void render(VertexArray& va, IndexBuffer& ib, Shader& shader, Shader& grid_shader, Renderer& renderer);
48
49 void handleInputs(glm::vec2 current_mouse_fbo_pos);
50 void handleCursorInputs();
52 void handleScrollInputs();
53
54 void createGameTableFile(flecs::entity game_table);
55
56 std::vector<std::string> listBoardFiles();
57 std::vector<std::string> listGameTableFiles();
58 void setCameraWindowSizePos(glm::vec2 window_size, glm::vec2 window_pos);
59
60 std::shared_ptr<IdentityManager> identity_manager;
61 std::string game_table_name;
62 //Chat chat;
63 std::shared_ptr<ChatManager> chat_manager;
64 std::shared_ptr<DirectoryWindow> map_directory;
65 std::shared_ptr<NetworkManager> network_manager;
66 std::shared_ptr<BoardManager> board_manager;
67 flecs::entity active_game_table = flecs::entity();
68
69 void setActiveGameTableEntity(flecs::entity e)
70 {
72 }
73 flecs::entity getActiveGameTableEntity() const
74 {
75 return active_game_table;
76 }
77
78 void setToaster(std::shared_ptr<ImGuiToaster> t)
79 {
80 toaster_ = t;
81 network_manager->setToaster(t);
82 }
83 void pushStatusToast(const std::string& msg, ImGuiToaster::Level lvl, float durationSec = 5.0f)
84 {
85 if (toaster_)
86 toaster_->Push(lvl, msg, durationSec);
87 }
88
89 void processMouseInput(bool is_mouse_within_image_bounds, bool is_map_window_hovered)
90 {
91
92 ImGuiIO& io = ImGui::GetIO();
93
94 mouse_wheel_delta = io.MouseWheel;
95
96 if ((io.MouseClicked[0] || io.MouseClicked[1] || io.MouseClicked[2]) && !is_mouse_within_image_bounds && is_map_window_hovered)
97 {
99 }
100 if (io.MouseReleased[0] || io.MouseReleased[1] || io.MouseReleased[2])
101 {
103 }
104
107
109 {
110 if (is_mouse_within_image_bounds && is_map_window_hovered)
111 {
112 if (io.MouseClicked[0])
113 { // LEFT mouse button just clicked
114 mouse_left_clicked = true;
115 }
116 if (io.MouseClicked[1])
117 { // RIGHT mouse button just clicked
118 mouse_right_clicked = true;
119 }
120 if (io.MouseClicked[2])
121 { // MIDDLE mouse button just clicked
123 }
124 }
125 }
126
127 if (io.MouseReleased[0])
128 { // LEFT mouse button just released
129 mouse_left_released = true;
130 }
131 if (io.MouseReleased[1])
132 { // RIGHT mouse button just released
134 }
135 if (io.MouseReleased[2])
136 { // MIDDLE mouse button just released
138 }
139 }
140
141 // Label + value on one line
142 void UI_LabelValue(const char* label, const std::string& value)
143 {
144 ImGui::TextUnformatted(label);
145 ImGui::SameLine();
146 ImGui::TextUnformatted(value.c_str());
147 }
148
149 // Copy button with timed "Copied!" toast (per-id)
150 bool UI_CopyButtonWithToast(const char* btnId, const std::string& toCopy,
151 const char* toastId, float seconds = 1.5f)
152 {
153 static std::unordered_map<std::string, double> s_toasts; // toastId -> expire time
154 bool clicked = ImGui::Button(btnId);
155 if (clicked)
156 {
157 ImGui::SetClipboardText(toCopy.c_str());
158 s_toasts[toastId] = ImGui::GetTime() + seconds;
159 }
160 if (auto it = s_toasts.find(toastId); it != s_toasts.end())
161 {
162 if (ImGui::GetTime() < it->second)
163 {
164 ImGui::SameLine();
165 ImGui::TextColored(ImVec4(0.4f, 1.f, 0.4f, 1.f), "Copied!");
166 }
167 else
168 {
169 s_toasts.erase(it);
170 }
171 }
172 return clicked;
173 }
174
175 // Transient colored line (e.g., "Failed to connect!") that auto hides
176 void UI_TransientLine(const char* key, bool trigger, const ImVec4& color,
177 const char* text, float seconds = 2.0f)
178 {
179 static std::unordered_map<std::string, double> s_until; // key -> expire time
180 if (trigger)
181 s_until[key] = ImGui::GetTime() + seconds;
182 if (auto it = s_until.find(key); it != s_until.end())
183 {
184 if (ImGui::GetTime() < it->second)
185 {
186 ImGui::TextColored(color, "%s", text);
187 }
188 else
189 {
190 s_until.erase(it);
191 }
192 }
193 }
194
195 // Shared chunk for entering password + port (returns true if drew fields)
196 bool UI_RenderPortAndPassword(char* portBuf, size_t portBufSize,
197 char* passBuf, size_t passBufSize)
198 {
199 ImGui::InputText("Password", passBuf, passBufSize, ImGuiInputTextFlags_Password);
201 ImGui::InputText("Port", portBuf, portBufSize, ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsNoBlank);
203 return true;
204 }
205
206 // Reusable confirm modal
207 inline bool UI_ConfirmModal(const char* popupId, const char* title, const char* text)
208 {
209 bool confirmed = false;
210 ImVec2 center = ImGui::GetMainViewport()->GetCenter();
211 ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
212 if (ImGui::BeginPopupModal(popupId, nullptr, ImGuiWindowFlags_AlwaysAutoResize))
213 {
214 ImGui::TextUnformatted(title);
215 ImGui::Separator();
216 ImGui::TextWrapped("%s", text);
217 ImGui::Separator();
218 if (ImGui::Button("Yes"))
219 {
220 confirmed = true;
221 ImGui::CloseCurrentPopup();
222 }
223 ImGui::SameLine();
224 if (ImGui::Button("No"))
225 {
226 ImGui::CloseCurrentPopup();
227 }
228 ImGui::EndPopup();
229 }
230 return confirmed;
231 }
232
233private:
234 std::shared_ptr<ImGuiToaster> toaster_;
235
236 void handleMouseButtons(glm::vec2 current_mouse_fbo_pixels_bl_origin, int fbo_height);
237 void handleCursorMovement(glm::vec2 current_mouse_fbo_pixels_bl_origin);
238 void handleScroll(glm::vec2 current_mouse_fbo_pixels_bl_origin);
239
240 flecs::world ecs;
241
242 glm::vec2 current_mouse_pos; // Posição atual do mouse em snake_case
243
244 glm::vec2 current_mouse_ndc_pos; // Posição atual do mouse em snake_case
245 glm::vec2 current_mouse_world_pos; // Posição atual do mouse em world coordinates
246 glm::vec2 current_mouse_fbo_pos; // Posição atual do mouse em fbo pixels coordinates
247
248 char buffer[124] = "";
249 char pass_buffer[124] = "";
250 char port_buffer[6] = "7777";
251 char username_buffer[124] = "";
252
253 std::string map_image_path = "";
254
260
261 static inline flecs::entity findMarkerInBoard(flecs::entity boardEnt, uint64_t markerId)
262 {
263 flecs::entity out;
264 boardEnt.children([&](flecs::entity child)
265 {
266 if (!child.has<MarkerComponent>()) return;
267 if (auto id = child.get<Identifier>(); id && id->id == markerId)
268 out = child; });
269 return out;
270 }
271
272 static uint64_t nowMs()
273 {
274 using Clock = std::chrono::steady_clock;
275 using namespace std::chrono;
276 return duration_cast<milliseconds>(Clock::now().time_since_epoch()).count();
277 }
278};
std::chrono::steady_clock Clock
void processMouseInput(bool is_mouse_within_image_bounds, bool is_map_window_hovered)
std::vector< std::string > listBoardFiles()
bool UI_CopyButtonWithToast(const char *btnId, const std::string &toCopy, const char *toastId, float seconds=1.5f)
std::string game_table_name
void createGameTableFile(flecs::entity game_table)
bool UI_RenderPortAndPassword(char *portBuf, size_t portBufSize, char *passBuf, size_t passBufSize)
std::shared_ptr< ImGuiToaster > toaster_
static flecs::entity findMarkerInBoard(flecs::entity boardEnt, uint64_t markerId)
glm::vec2 current_mouse_pos
glm::vec2 current_mouse_world_pos
static uint64_t nowMs()
flecs::entity getActiveGameTableEntity() const
void handleInputs(glm::vec2 current_mouse_fbo_pos)
void setActiveGameTableEntity(flecs::entity e)
void UI_LabelValue(const char *label, const std::string &value)
void setCameraFboDimensions(glm::vec2 fbo_dimensions)
void setCameraWindowSizePos(glm::vec2 window_size, glm::vec2 window_pos)
std::shared_ptr< IdentityManager > identity_manager
void render(VertexArray &va, IndexBuffer &ib, Shader &shader, Shader &grid_shader, Renderer &renderer)
GameTableManager(flecs::world ecs, std::shared_ptr< DirectoryWindow > map_directory, std::shared_ptr< DirectoryWindow > marker_directory)
glm::vec2 current_mouse_fbo_pos
std::shared_ptr< NetworkManager > network_manager
void pushStatusToast(const std::string &msg, ImGuiToaster::Level lvl, float durationSec=5.0f)
bool UI_ConfirmModal(const char *popupId, const char *title, const char *text)
std::vector< std::string > listGameTableFiles()
void handleScroll(glm::vec2 current_mouse_fbo_pixels_bl_origin)
std::string map_image_path
std::shared_ptr< DirectoryWindow > map_directory
void handleMouseButtons(glm::vec2 current_mouse_fbo_pixels_bl_origin, int fbo_height)
std::shared_ptr< BoardManager > board_manager
void handleCursorMovement(glm::vec2 current_mouse_fbo_pixels_bl_origin)
void UI_TransientLine(const char *key, bool trigger, const ImVec4 &color, const char *text, float seconds=2.0f)
glm::vec2 current_mouse_ndc_pos
flecs::entity active_game_table
void loadGameTable(std::filesystem::path game_table_file_path)
std::shared_ptr< ChatManager > chat_manager
void setToaster(std::shared_ptr< ImGuiToaster > t)
void TrackThisInput()
Definition Message.h:28