RunicVTT Open Source Virtual Tabletop for TTRPG using P2P
Loading...
Searching...
No Matches
BoardManager Class Reference

#include <BoardManager.h>

Inheritance diagram for BoardManager:
Collaboration diagram for BoardManager:

Public Member Functions

 BoardManager (flecs::world ecs, std::weak_ptr< NetworkManager > network_manager, std::shared_ptr< IdentityManager > identity_manager, std::shared_ptr< DirectoryWindow > map_directory, std::shared_ptr< DirectoryWindow > marker_directory)
 
 ~BoardManager ()
 
void renderBoard (VertexArray &va, IndexBuffer &ib, Shader &shader, Shader &grid_shader, Renderer &renderer)
 
void renderToolbar (const ImVec2 &window_position)
 
void resetCamera ()
 
flecs::entity createMarker (const std::string &imageFilePath, GLuint textureId, glm::vec2 position, glm::vec2 size)
 
void deleteMarker (flecs::entity markerEntity)
 
void handleMarkerDragging (glm::vec2 mousePos)
 
bool isMouseOverMarker (glm::vec2 mousePos)
 
bool canMoveMarker (const MarkerComponent *mc, flecs::entity markerEnt) const
 
glm::vec2 computeMarkerDrawSize_ARFit (const TextureComponent &tex, float basePx, float scale)
 
flecs::entity createFogOfWar (glm::vec2 startPos, glm::vec2 size)
 
void deleteFogOfWar (flecs::entity fogEntity)
 
void handleFogCreation (glm::vec2 end_world_position)
 
void panBoard (glm::vec2 currentMousePos)
 
Tool getCurrentTool () const
 
void setCurrentTool (Tool newTool)
 
bool isBoardActive ()
 
flecs::entity createBoard (std::string board_name, std::string map_image_path, GLuint texture_id, glm::vec2 size)
 
void closeBoard ()
 
void setActiveBoard (flecs::entity board_entity)
 
bool isEditWindowOpen () const
 
void renderEditWindow ()
 
void renderCameraWindow ()
 
void startMouseDrag (glm::vec2 mousePos, bool draggingMarker)
 
void endMouseDrag ()
 
glm::vec2 getMouseStartPosition () const
 
bool isPanning ()
 
bool isDraggingMarker (bool local_drag_only=true)
 
flecs::entity getEntityAtMousePosition (glm::vec2 mouse_position)
 
flecs::entity findBoardById (uint64_t boardId)
 
bool shouldSendMarkerMove (uint64_t markerId) const
 
uint64_t generateUniqueId ()
 
flecs::entity findEntityById (uint64_t target_id)
 
glm::vec2 snapToGrid (glm::vec2 raw_world_pos)
 
void renderGridWindow ()
 
void sendGameState ()
 
void sendEntityUpdate (flecs::entity entity)
 
flecs::entity getActiveBoard () const
 
void loadActiveBoard (const std::string &filePath)
 
void saveActiveBoard (const std::string &filePath)
 
void saveActiveBoard (std::filesystem::path &filePath)
 
bool isCreatingFog () const
 
bool getShowEditWindow () const
 
void setShowEditWindow (bool show, flecs::entity edit_entity=flecs::entity())
 
BoardImageData LoadTextureFromMemory (const unsigned char *bytes, size_t sizeBytes)
 
void killIfMouseUp (bool isMouseDown)
 
void resnapAllMarkersToNearest (const Grid &grid)
 
void onUsernameChanged (const std::string &uniqueId, const std::string &newUsername)
 

Public Attributes

std::string board_name
 
std::shared_ptr< DirectoryWindowmap_directory
 
std::shared_ptr< DirectoryWindowmarker_directory
 
Camera camera
 

Private Attributes

bool showEditWindow = false
 
bool showGridSettings = false
 
bool showCameraSettings = false
 
float markerBasePx = 50.0f
 
flecs::entity edit_window_entity = flecs::entity()
 
std::weak_ptr< NetworkManagernetwork_manager
 
std::shared_ptr< IdentityManageridentity_manager
 
glm::vec2 mouse_start_screen_pos
 
glm::vec2 mouse_start_world_pos
 
glm::vec2 mouse_current_world_pos
 
flecs::world ecs
 
flecs::entity active_board = flecs::entity()
 
flecs::entity grid_entity = flecs::entity()
 
bool is_creating_fog = false
 
Tool currentTool
 
Tool previousTool
 

Detailed Description

Definition at line 168 of file BoardManager.h.

Constructor & Destructor Documentation

◆ BoardManager()

BoardManager::BoardManager ( flecs::world ecs,
std::weak_ptr< NetworkManager > network_manager,
std::shared_ptr< IdentityManager > identity_manager,
std::shared_ptr< DirectoryWindow > map_directory,
std::shared_ptr< DirectoryWindow > marker_directory )

Definition at line 35 of file BoardManager.cpp.

35 :
37{
38
39 std::filesystem::path map_path = std::filesystem::path(map_directory->directoryPath);
40 std::filesystem::path base_path = map_path.parent_path();
41 std::filesystem::path marker_directory_path = base_path / "Markers";
42
43 marker_directory->directoryName = "MarkerDiretory";
44 marker_directory->directoryPath = marker_directory_path.string();
45 marker_directory->startMonitoring();
46 marker_directory->generateTextureIDs();
47}
glm::vec2 mouse_current_world_pos
glm::vec2 mouse_start_world_pos
std::shared_ptr< DirectoryWindow > marker_directory
std::weak_ptr< NetworkManager > network_manager
flecs::world ecs
std::shared_ptr< IdentityManager > identity_manager
std::shared_ptr< DirectoryWindow > map_directory
glm::vec2 mouse_start_screen_pos

◆ ~BoardManager()

BoardManager::~BoardManager ( )

Definition at line 49 of file BoardManager.cpp.

50{
51}

Member Function Documentation

◆ canMoveMarker()

bool BoardManager::canMoveMarker ( const MarkerComponent * mc,
flecs::entity markerEnt ) const

Definition at line 710 of file BoardManager.cpp.

711{
712 if (!mc || !markerEnt.is_valid())
713 return false;
714
715 auto nm = network_manager.lock();
716 if (!nm)
717 return false;
718
719 // Disallow if being dragged by anyone
720 if (markerEnt.has<Identifier>())
721 {
722 const auto mid = markerEnt.get<Identifier>()->id;
723 if (nm->isMarkerBeingDragged(mid))
724 return false;
725 }
726
727 const auto role = nm->getPeerRole();
728 if (role == Role::GAMEMASTER)
729 return true;
730
731 if (mc->locked)
732 return false;
733
734 if (mc->allowAllPlayersMove)
735 return true;
736
737 const std::string unique_id = identity_manager->myUniqueId();
738 if (!mc->ownerUniqueId.empty() && mc->ownerUniqueId == unique_id)
739 return true;
740
743 //if (auto vis = markerEnt.get<Visibility>(); vis && !vis->isVisible)
744 //{
745 // // Compute marker AABB
746 // auto pos = markerEnt.get<Position>();
747 // auto siz = markerEnt.get<Size>();
748 // if (pos && siz)
749 // {
750 // const float mx1 = pos->x - siz->width * 0.5f;
751 // const float mx2 = pos->x + siz->width * 0.5f;
752 // const float my1 = pos->y - siz->height * 0.5f;
753 // const float my2 = pos->y + siz->height * 0.5f;
754
755 // bool covered = false;
756 // active_board.children([&](flecs::entity child)
757 // {
758 // if (!child.has<FogOfWar>()) return;
759 // if (auto fvis = child.get<Visibility>(); !fvis || !fvis->isVisible) return; // fog must be visible
760
761 // auto fpos = child.get<Position>();
762 // auto fsz = child.get<Size>();
763 // if (!fpos || !fsz) return;
764
765 // const float fx1 = fpos->x - fsz->width * 0.5f;
766 // const float fx2 = fpos->x + fsz->width * 0.5f;
767 // const float fy1 = fpos->y - fsz->height * 0.5f;
768 // const float fy2 = fpos->y + fsz->height * 0.5f;
769
770 // // full containment
771 // if (mx1 >= fx1 && mx2 <= fx2 && my1 >= fy1 && my2 <= fy2)
772 // covered = true; });
773 // if (covered)
774 // return true;
775 // }
776 //}
777
778 return false;
779}
@ GAMEMASTER
Here is the caller graph for this function:

◆ closeBoard()

void BoardManager::closeBoard ( )

Definition at line 58 of file BoardManager.cpp.

59{
60 active_board = flecs::entity();
61}
flecs::entity active_board

◆ computeMarkerDrawSize_ARFit()

glm::vec2 BoardManager::computeMarkerDrawSize_ARFit ( const TextureComponent & tex,
float basePx,
float scale )

Definition at line 394 of file BoardManager.cpp.

395{
396 const glm::vec2 texPx = tex.size; // original pixels stored in your TextureComponent
397 if (texPx.x <= 0.0f || texPx.y <= 0.0f)
398 {
399 const float box = basePx * scale;
400 return {box, box};
401 }
402 const float box = basePx * scale;
403 const float s = std::min(box / texPx.x, box / texPx.y);
404 return texPx * s; // scaled to fit inside the box, AR preserved
405}
Here is the caller graph for this function:

◆ createBoard()

flecs::entity BoardManager::createBoard ( std::string board_name,
std::string map_image_path,
GLuint texture_id,
glm::vec2 size )

Definition at line 63 of file BoardManager.cpp.

64{
65 auto board = ecs.entity()
67 .set(Board{board_name})
68 .set(Panning{false})
69 .set(Grid{{0, 0}, 50.0f, false, false, false, 0.5f})
70 .set(TextureComponent{texture_id, map_image_path, size})
71 .set(Size{size.x, size.y});
72 setActiveBoard(board);
73 return board;
74}
uint64_t generateUniqueId()
std::string board_name
void setActiveBoard(flecs::entity board_entity)
Here is the call graph for this function:

◆ createFogOfWar()

flecs::entity BoardManager::createFogOfWar ( glm::vec2 startPos,
glm::vec2 size )

Definition at line 1127 of file BoardManager.cpp.

1128{
1129 auto nm = network_manager.lock();
1130 if (!nm)
1131 throw std::exception("[BoardManager] Network Manager expired!!");
1132
1133 auto fog = ecs.entity()
1135 .set(Position{startPos.x, startPos.y})
1136 .set(Size{size.x, size.y})
1137 .set(Visibility{true});
1138
1139 fog.add<FogOfWar>();
1140 fog.add(flecs::ChildOf, active_board);
1141
1142 auto board_id = active_board.get<Identifier>()->id;
1143 nm->broadcastFog(board_id, fog);
1144
1145 return fog;
1146}
float x
Definition Components.h:20
Here is the call graph for this function:
Here is the caller graph for this function:

◆ createMarker()

flecs::entity BoardManager::createMarker ( const std::string & imageFilePath,
GLuint textureId,
glm::vec2 position,
glm::vec2 size )

Definition at line 541 of file BoardManager.cpp.

542{
543 auto nm = network_manager.lock();
544 if (!nm)
545 throw std::exception("[BoardManager] Network Manager expired!!");
546
547 auto markerScale = marker_directory->getGlobalSizeSlider();
548 auto texture_marker = TextureComponent{textureId, imageFilePath, size};
549 const glm::vec2 drawSz = computeMarkerDrawSize_ARFit(texture_marker, markerBasePx, markerScale);
550
551 flecs::entity marker = ecs.entity()
553 .set(Position{position.x, position.y}) //World Position
554 .set(Size{drawSz.x, drawSz.y})
555 .set(texture_marker)
556 .set(Visibility{true})
557 .set(MarkerComponent{"", "", false, false})
558 .set(Moving{false});
559
560 marker.add(flecs::ChildOf, active_board);
561
562 auto board_id = active_board.get<Identifier>()->id;
563 nm->broadcastMarker(board_id, marker);
564 return marker;
565}
glm::vec2 computeMarkerDrawSize_ARFit(const TextureComponent &tex, float basePx, float scale)
Here is the call graph for this function:

◆ deleteFogOfWar()

void BoardManager::deleteFogOfWar ( flecs::entity fogEntity)

Definition at line 1122 of file BoardManager.cpp.

1123{
1124 fogEntity.destruct();
1125}

◆ deleteMarker()

void BoardManager::deleteMarker ( flecs::entity markerEntity)

Definition at line 567 of file BoardManager.cpp.

568{
569 markerEntity.destruct();
570}

◆ endMouseDrag()

void BoardManager::endMouseDrag ( )

Definition at line 975 of file BoardManager.cpp.

976{
977 if (!active_board.is_valid())
978 return;
979
980 active_board.set<Panning>({false});
981 auto nm = network_manager.lock();
982 if (!nm)
983 throw std::exception("[BoardManager] Network Manager expired!!");
984
985 const Grid* grid = active_board.get<Grid>();
986 const bool canSnap = (grid && grid->snap_to_grid && grid->cell_size > 0.0f);
987
988 ecs.defer_begin();
989 ecs.each([&](flecs::entity entity, const MarkerComponent& marker, Moving& moving, Position& pos)
990 {
991 if (!entity.has(flecs::ChildOf, active_board)) return;
992 if (!moving.isDragging) return;
993
994 const auto mid = entity.get<Identifier>()->id;
995 if (!nm->amIDragging(mid))
996 return; // skip markers dragged by others
997
998 if (canSnap)
999 {
1000 glm::vec2 snapped = snapToSquareCenter(glm::vec2(pos.x, pos.y), grid->offset, grid->cell_size);
1001 pos.x = snapped.x;
1002 pos.y = snapped.y;
1003 }
1004
1005 moving.isDragging = false;
1006
1007 const auto bid = active_board.get<Identifier>()->id;
1008
1009 nm->markDraggingLocal(mid, false); // <- local registry
1010 nm->broadcastMarkerMoveState(bid, entity); // end (isDragging=false + final pos)broadcastMarkerUpdate(bid, entity); // <- final pos + mov=false
1011 nm->forceCloseDrag(mid); });
1012
1013 ecs.defer_end();
1014 is_creating_fog = false;
1015}
static glm::vec2 snapToSquareCenter(const glm::vec2 &worldPos, const glm::vec2 &offset, float cell)
bool snap_to_grid
Definition Components.h:68
glm::vec2 offset
Definition Components.h:65
float cell_size
Definition Components.h:66
float y
Definition Components.h:21
Here is the call graph for this function:

◆ findBoardById()

flecs::entity BoardManager::findBoardById ( uint64_t boardId)

Definition at line 1763 of file BoardManager.cpp.

1764{
1765 flecs::entity result;
1766 ecs.each([&](flecs::entity e, const Board& b, const Identifier& id)
1767 {
1768 Logger::instance().log("localtunnel", Logger::Level::Info, "Board Name: " + b.board_name);
1769 if (e.is_valid() && id.id == boardId) {
1770 result = e;
1771 Logger::instance().log("localtunnel", Logger::Level::Info, "Found Board By ID!!");
1772 } });
1773
1774 return result; // will be invalid if not found
1775}
static Logger & instance()
Definition Logger.h:39
Here is the call graph for this function:

◆ findEntityById()

flecs::entity BoardManager::findEntityById ( uint64_t target_id)

Definition at line 665 of file BoardManager.cpp.

666{
667 flecs::entity result;
668
669 // Iterate over all entities with Identifier component
670 ecs.each<Identifier>([&](flecs::entity e, Identifier& identifier)
671 {
672 if (identifier.id == target_id) {
673 result = e; // Store matching entity
674 } });
675
676 return result; // Returns the found entity, or an empty entity if not found
677}

◆ generateUniqueId()

uint64_t BoardManager::generateUniqueId ( )

Definition at line 585 of file BoardManager.cpp.

586{
587 // 64-bit Snowflake layout:
588 // [ 42 bits timestamp(ms since 2020-01-01 UTC) ][ 10 bits node ][ 12 bits sequence ]
589 static constexpr uint64_t TS_BITS = 42;
590 static constexpr uint64_t NODE_BITS = 10;
591 static constexpr uint64_t SEQ_BITS = 12;
592
593 static constexpr uint64_t TS_MASK = (1ULL << TS_BITS) - 1;
594 static constexpr uint64_t NODE_MASK = (1ULL << NODE_BITS) - 1;
595 static constexpr uint64_t SEQ_MASK = (1ULL << SEQ_BITS) - 1;
596
597 // Custom epoch: 2020-01-01T00:00:00Z in UNIX ms
598 static constexpr int64_t EPOCH_MS = 1577836800000LL;
599
600 // Derive a stable 10-bit node id for this process/machine (once).
601 // Try COMPUTERNAME/HOSTNAME; fallback to random.
602 static const uint16_t NODE_ID = []() -> uint16_t
603 {
604 std::string basis;
605 if (const char* cn = std::getenv("COMPUTERNAME"); cn && *cn)
606 basis = cn;
607 else if (const char* hn = std::getenv("HOSTNAME"); hn && *hn)
608 basis = hn;
609 else
610 {
611 std::random_device rd;
612 basis = std::to_string(rd());
613 }
614 uint64_t h = std::hash<std::string>{}(basis);
615 // xor-fold a bit to mix high/low
616 h ^= (h >> 33) ^ (h >> 17) ^ (h >> 9);
617 return static_cast<uint16_t>(h) & NODE_MASK; // 10 bits
618 }();
619
620 // Per-process state
621 static std::atomic<uint64_t> lastMs{0};
622 static std::atomic<uint16_t> seq{0};
623
624 // Current ms since custom epoch
625 const auto nowEpoch = std::chrono::time_point_cast<std::chrono::milliseconds>(
626 std::chrono::system_clock::now())
627 .time_since_epoch()
628 .count();
629 uint64_t nowMs = (nowEpoch >= EPOCH_MS) ? static_cast<uint64_t>(nowEpoch - EPOCH_MS) : 0ULL;
630
631 uint64_t last = lastMs.load(std::memory_order_relaxed);
632 if (nowMs == last)
633 {
634 // Same millisecond -> increment sequence (12 bits)
635 uint16_t s = static_cast<uint16_t>(seq.fetch_add(1, std::memory_order_relaxed)) & SEQ_MASK;
636 if (s == 0)
637 {
638 // Overflowed the 12-bit sequence; wait for the next millisecond
639 do
640 {
641 std::this_thread::yield();
642 const auto now2 = std::chrono::time_point_cast<std::chrono::milliseconds>(
643 std::chrono::system_clock::now())
644 .time_since_epoch()
645 .count();
646 nowMs = (now2 >= EPOCH_MS) ? static_cast<uint64_t>(now2 - EPOCH_MS) : 0ULL;
647 } while (nowMs == last);
648 lastMs.store(nowMs, std::memory_order_relaxed);
649 seq.store(0, std::memory_order_relaxed);
650 s = 0;
651 }
652 // Pack: (ts << (10+12)) | (node << 12) | seq
653 return ((nowMs & TS_MASK) << (NODE_BITS + SEQ_BITS)) | ((static_cast<uint64_t>(NODE_ID) & NODE_MASK) << SEQ_BITS) | (static_cast<uint64_t>(s) & SEQ_MASK);
654 }
655 else
656 {
657 // New millisecond -> reset sequence
658 lastMs.store(nowMs, std::memory_order_relaxed);
659 seq.store(0, std::memory_order_relaxed);
660 return ((nowMs & TS_MASK) << (NODE_BITS + SEQ_BITS)) | ((static_cast<uint64_t>(NODE_ID) & NODE_MASK) << SEQ_BITS) | 0ULL;
661 }
662}
Here is the caller graph for this function:

◆ getActiveBoard()

flecs::entity BoardManager::getActiveBoard ( ) const

Definition at line 1323 of file BoardManager.cpp.

1324{
1325 return active_board;
1326}
Here is the caller graph for this function:

◆ getCurrentTool()

Tool BoardManager::getCurrentTool ( ) const

Definition at line 1174 of file BoardManager.cpp.

1175{
1176 return currentTool;
1177}

◆ getEntityAtMousePosition()

flecs::entity BoardManager::getEntityAtMousePosition ( glm::vec2 mouse_position)

Definition at line 1184 of file BoardManager.cpp.

1185{
1186
1187 auto entity_at_mouse = flecs::entity();
1188 ecs.defer_begin();
1189 ecs.each([&](flecs::entity entity, const Position& entity_pos, const Size& entity_size)
1190 {
1191 const bool isMarker = entity.has<MarkerComponent>();
1192 if (isMarker) {
1193 glm::vec2 world_position = mouse_position;
1194
1195 if (entity.has(flecs::ChildOf, active_board)) {
1196
1197 bool withinXBounds = (world_position.x >= (entity_pos.x - entity_size.width / 2)) &&
1198 (world_position.x <= (entity_pos.x + entity_size.width / 2));
1199
1200 bool withinYBounds = (world_position.y >= (entity_pos.y - entity_size.height / 2)) &&
1201 (world_position.y <= (entity_pos.y + entity_size.height / 2));
1202
1203 if (withinXBounds && withinYBounds) {
1204 entity_at_mouse = entity;
1205 }
1206 }
1207
1208 } });
1209 ecs.defer_end();
1210
1211 if (entity_at_mouse.is_valid())
1212 return entity_at_mouse;
1213
1214 ecs.defer_begin();
1215 ecs.each([&](flecs::entity entity, const Position& entity_pos, const Size& entity_size)
1216 {
1217
1218 glm::vec2 world_position = mouse_position;
1219
1220 if (entity.has(flecs::ChildOf, active_board)) {
1221
1222 bool withinXBounds = (world_position.x >= (entity_pos.x - entity_size.width / 2)) &&
1223 (world_position.x <= (entity_pos.x + entity_size.width / 2));
1224
1225 bool withinYBounds = (world_position.y >= (entity_pos.y - entity_size.height / 2)) &&
1226 (world_position.y <= (entity_pos.y + entity_size.height / 2));
1227
1228 if (withinXBounds && withinYBounds) {
1229 entity_at_mouse = entity;
1230 }
1231 } });
1232 ecs.defer_end();
1233 return entity_at_mouse;
1234}
Here is the caller graph for this function:

◆ getMouseStartPosition()

glm::vec2 BoardManager::getMouseStartPosition ( ) const

Definition at line 1102 of file BoardManager.cpp.

1103{
1104 return mouse_start_world_pos;
1105}
Here is the caller graph for this function:

◆ getShowEditWindow()

bool BoardManager::getShowEditWindow ( ) const
inline

Definition at line 244 of file BoardManager.h.

245 {
246 return showEditWindow;
247 };

◆ handleFogCreation()

void BoardManager::handleFogCreation ( glm::vec2 end_world_position)

Definition at line 1148 of file BoardManager.cpp.

1149{
1150 glm::vec2 start_world_position = getMouseStartPosition();
1151
1152 // Calculate size
1153 glm::vec2 size = end_world_position - start_world_position; //glm::abs(end_world_position - start_world_position); // Make sure size is positive
1154 glm::vec2 corrected_start_position;
1155 if (size.x < 0)
1156 {
1157 corrected_start_position.x = end_world_position.x + glm::abs(size.x) / 2;
1158 }
1159 else
1160 {
1161 corrected_start_position.x = start_world_position.x + size.x / 2;
1162 }
1163 if (size.y < 0)
1164 {
1165 corrected_start_position.y = end_world_position.y + glm::abs(size.y) / 2;
1166 }
1167 else
1168 {
1169 corrected_start_position.y = start_world_position.y + size.y / 2;
1170 }
1171 createFogOfWar(corrected_start_position, glm::abs(size));
1172}
glm::vec2 getMouseStartPosition() const
flecs::entity createFogOfWar(glm::vec2 startPos, glm::vec2 size)
Here is the call graph for this function:

◆ handleMarkerDragging()

void BoardManager::handleMarkerDragging ( glm::vec2 mousePos)

Definition at line 1017 of file BoardManager.cpp.

1018{
1019 auto nm = network_manager.lock();
1020 if (!nm)
1021 throw std::exception("[BoardManager] Network Manager expired!!");
1022
1023 ecs.defer_begin();
1024 ecs.each([&](flecs::entity entity, const MarkerComponent& marker, Moving& moving, Position& position)
1025 {
1026 if (!entity.has(flecs::ChildOf, active_board)) return;
1027 if (!moving.isDragging) return;
1028
1029 if (!entity.has<Identifier>())
1030 return;
1031 const auto mid = entity.get<Identifier>()->id;
1032
1033 // Only advance locally if I am the drag owner (prevents flicker)
1034 if (!nm->amIDragging(mid))
1035 return;
1036
1037 glm::vec2 delta = world_position - mouse_start_world_pos;
1038 position.x += delta.x;
1039 position.y += delta.y;
1040 mouse_start_world_pos = world_position;
1041
1042 const auto id = entity.get<Identifier>()->id;
1043 if (shouldSendMarkerMove(id))
1044 {
1045 //Logger::instance().log("localtunnel", Logger::Level::Info, "broadcastMarkerMove!");
1046 nm->broadcastMarkerMove(active_board.get<Identifier>()->id, entity);
1047 } });
1048 ecs.defer_end();
1049}
bool shouldSendMarkerMove(uint64_t markerId) const
uint64_t id
Definition Components.h:14
Here is the call graph for this function:

◆ isBoardActive()

bool BoardManager::isBoardActive ( )

Definition at line 53 of file BoardManager.cpp.

54{
55 return active_board.is_valid();
56}

◆ isCreatingFog()

bool BoardManager::isCreatingFog ( ) const
inline

Definition at line 240 of file BoardManager.h.

241 {
242 return is_creating_fog;
243 };

◆ isDraggingMarker()

bool BoardManager::isDraggingMarker ( bool local_drag_only = true)

Definition at line 1073 of file BoardManager.cpp.

1074{
1075 auto nm = network_manager.lock();
1076 if (!nm)
1077 return false;
1078
1079 bool any = false;
1080
1081 ecs.defer_begin();
1082 ecs.each([&](flecs::entity e, const MarkerComponent&, const Moving& mv, const Identifier& id)
1083 {
1084 if (any) return; // early out from further work in this lambda (flecs will still loop, but we do nothing)
1085 if (!e.has(flecs::ChildOf, active_board)) return;
1086 if (!mv.isDragging) return;
1087
1088 if (local_drag_only)
1089 {
1090 if (nm->amIDragging(id.id))
1091 any = true; // found a local-owned drag
1092 }
1093 else
1094 {
1095 any = true; // any drag at all
1096 } });
1097 ecs.defer_end();
1098
1099 return any;
1100}
Here is the caller graph for this function:

◆ isEditWindowOpen()

bool BoardManager::isEditWindowOpen ( ) const

Definition at line 1328 of file BoardManager.cpp.

1329{
1330 return showEditWindow;
1331}

◆ isMouseOverMarker()

bool BoardManager::isMouseOverMarker ( glm::vec2 mousePos)

Definition at line 886 of file BoardManager.cpp.

887{
888 bool hovered = false;
889 ecs.defer_begin();
890 ecs.each([&](flecs::entity entity, const MarkerComponent& marker_component, const Position& markerPos, const Size& markerSize, Moving& moving)
891 {
892
893 if (entity.has(flecs::ChildOf, active_board)) {
894 bool withinXBounds = (world_position.x >= (markerPos.x - markerSize.width / 2)) &&
895 (world_position.x <= (markerPos.x + markerSize.width / 2));
896
897 bool withinYBounds = (world_position.y >= (markerPos.y - markerSize.height / 2)) &&
898 (world_position.y <= (markerPos.y + markerSize.height / 2));
899
900 if (!(withinXBounds && withinYBounds))
901 return;
902 if (!canMoveMarker(&marker_component, entity))
903 return;
904
905 //moving.isDragging = true;
906 hovered = true;
907 //if (auto nm = network_manager.lock())
908 //{
909 // if (entity.has<Identifier>() && active_board.has<Identifier>())
910 // {
911 // const auto bid = active_board.get<Identifier>()->id;
912 // const auto mid = entity.get<Identifier>()->id;
913
914 // nm->markDraggingLocal(mid, true);
915 // nm->broadcastMarkerMoveState(bid, entity);
916 // }
917 //}
918 } });
919 ecs.defer_end();
920
921 return hovered;
922}

◆ isPanning()

bool BoardManager::isPanning ( )

Definition at line 1067 of file BoardManager.cpp.

1068{
1069 const Panning* panning = active_board.get<Panning>();
1070 return panning->isPanning;
1071}
bool isPanning
Definition Components.h:59

◆ killIfMouseUp()

void BoardManager::killIfMouseUp ( bool isMouseDown)

Definition at line 781 of file BoardManager.cpp.

782{
783 if (isMouseDown)
784 return;
785
786 // Ensure panning is off
787 if (active_board.is_valid())
788 active_board.set<Panning>({false});
789
790 auto nm = network_manager.lock();
791
792 // If some marker still locally dragging (UI glitch), force-end it now
793 ecs.defer_begin();
794 ecs.each([&](flecs::entity entity, MarkerComponent& mc, Moving& moving, Position& pos)
795 {
796 if (!entity.has(flecs::ChildOf, active_board))
797 return;
798 if (!moving.isDragging)
799 return;
800 const auto mid = entity.get<Identifier>()->id;
801 if (!nm->amIDragging(mid))
802 return; // skip markers dragged by others
803
804 moving.isDragging = false;
805
806 const auto bid = active_board.get<Identifier>()->id;
807
808 nm->markDraggingLocal(mid, false);
809 nm->broadcastMarkerMoveState(bid, entity); // end (final)
810 nm->forceCloseDrag(mid); });
811
812 ecs.defer_end();
813}

◆ loadActiveBoard()

void BoardManager::loadActiveBoard ( const std::string & filePath)

Definition at line 1288 of file BoardManager.cpp.

1289{
1290 std::ifstream inFile(board_file_path, std::ios::binary);
1291 if (inFile)
1292 {
1293 std::vector<uint8_t> buffer((std::istreambuf_iterator<char>(inFile)), std::istreambuf_iterator<char>());
1294 inFile.close();
1295
1296 size_t offset = 0;
1298 auto texture = active_board.get_mut<TextureComponent>();
1299 auto map_image = map_directory->getImageByPath(texture->image_path);
1300 texture->textureID = map_image.textureID;
1301 texture->size = map_image.size;
1302
1303 ecs.defer_begin();
1304 active_board.children([&](flecs::entity child)
1305 {
1306 if (child.has<MarkerComponent>()) {
1307 auto child_texture = child.get_mut<TextureComponent>();
1308 auto marker_image = marker_directory->getImageByPath(child_texture->image_path);
1309 child_texture->textureID = marker_image.textureID;
1310 child_texture->size = marker_image.size;
1311 } });
1312 ecs.defer_end();
1313
1315 std::cout << "Board loaded successfully from " << board_file_path << std::endl;
1316 }
1317 else
1318 {
1319 std::cerr << "Failed to load board from " << board_file_path << std::endl;
1320 }
1321}
static flecs::entity deserializeBoardEntity(const std::vector< unsigned char > &buffer, size_t &offset, flecs::world &ecs)
Definition Serializer.h:244
Here is the call graph for this function:

◆ LoadTextureFromMemory()

BoardImageData BoardManager::LoadTextureFromMemory ( const unsigned char * bytes,
size_t sizeBytes )

Definition at line 1777 of file BoardManager.cpp.

1778{
1779 if (!bytes || sizeBytes == 0)
1780 {
1781 std::cerr << "LoadTextureFromMemory: empty buffer\n";
1782 return BoardImageData{};
1783 }
1784
1785 // stb_image: ensure vertical flip matches your expectations
1786 stbi_set_flip_vertically_on_load(0);
1787
1788 int width = 0, height = 0, nrChannels = 0;
1789 uint8_t* data = stbi_load_from_memory(bytes, (int)sizeBytes, &width, &height, &nrChannels, 4);
1790 if (!data)
1791 {
1792 std::cerr << "LoadTextureFromMemory: decode failed\n";
1793 return BoardImageData{};
1794 }
1795
1796 GLuint tex = 0;
1797 glGenTextures(1, &tex);
1798 glBindTexture(GL_TEXTURE_2D, tex);
1799
1800 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height,
1801 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
1802
1803 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1804 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1805 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1806 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1807
1808 stbi_image_free(data);
1809 return BoardImageData(tex, glm::vec2(width, height), /*path*/ "");
1810}

◆ onUsernameChanged()

void BoardManager::onUsernameChanged ( const std::string & uniqueId,
const std::string & newUsername )

Definition at line 1236 of file BoardManager.cpp.

1237{
1238 // Update all markers owned by uniqueId: only the DISPLAY name changes.
1239 ecs.each([&](flecs::entity e, MarkerComponent& mc)
1240 {
1241 // you will add/keep ownerUniqueId in MarkerComponent:
1242 // struct MarkerComponent {
1243 // std::string ownerUniqueId; // authoritative owner
1244 // std::string ownerPeerUsername; // purely visual
1245 // bool allowAllPlayersMove = false;
1246 // bool locked = false;
1247 // };
1248
1249 if (mc.ownerUniqueId == uniqueId)
1250 mc.ownerPeerUsername = newUsername; });
1251
1252 // If you draw any overlays/caches of names, invalidate them here (optional).
1253}

◆ panBoard()

void BoardManager::panBoard ( glm::vec2 currentMousePos)

Definition at line 1107 of file BoardManager.cpp.

1108{
1109 glm::vec2 delta_screen = mouse_start_screen_pos - current_mouse_fbo_pos;
1110 float world_scale_factor = camera.getZoom();
1111 glm::vec2 delta_world = delta_screen / world_scale_factor;
1112 camera.pan(delta_world);
1113 mouse_start_screen_pos = current_mouse_fbo_pos;
1114}
float getZoom() const
void pan(glm::vec2 delta)
Here is the call graph for this function:

◆ renderBoard()

void BoardManager::renderBoard ( VertexArray & va,
IndexBuffer & ib,
Shader & shader,
Shader & grid_shader,
Renderer & renderer )

Definition at line 407 of file BoardManager.cpp.

408{
409 auto nm = network_manager.lock();
410 if (!nm)
411 throw std::exception("[BoardManager] Network Manager expired!!");
412
413 const TextureComponent* texture = active_board.get<TextureComponent>();
414 if (texture->textureID != 0)
415 {
416 const Board* board = active_board.get<Board>();
417 const Grid* grid = active_board.get<Grid>();
418 const Size* size = active_board.get<Size>();
419
420 glm::mat4 viewMatrix = camera.getViewMatrix(); // Obtém a matriz de visualização da câmera (pan/zoom)
421 glm::mat4 projection = camera.getProjectionMatrix();
422 glm::mat4 board_model = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 0.0f));
423 board_model = glm::scale(board_model, glm::vec3(size->width, size->height, 1.0f));
424
425 shader.Bind();
426 shader.SetUniformMat4f("projection", projection);
427 shader.SetUniformMat4f("view", viewMatrix);
428 shader.SetUniformMat4f("model", board_model);
429 shader.SetUniform1f("u_Alpha", 1.0f);
430 shader.SetUniform1i("u_UseTexture", 1);
431 shader.SetUniform1i("u_Texture", 0);
432 shader.Unbind();
433
434 GLCall(glActiveTexture(GL_TEXTURE0));
435 GLCall(glBindTexture(GL_TEXTURE_2D, texture->textureID));
436
437 renderer.Draw(va, ib, shader);
438
439 if (grid)
440 {
441 if (grid->visible)
442 {
443 grid_shader.Bind();
444 grid_shader.SetUniformMat4f("projection", projection);
445 grid_shader.SetUniformMat4f("view", viewMatrix);
446 grid_shader.SetUniformMat4f("model", board_model); // Grid model is the same as the board
447 grid_shader.SetUniform1i("grid_type", grid->is_hex ? 1 : 0);
448 grid_shader.SetUniform1f("cell_size", grid->cell_size);
449 grid_shader.SetUniform2f("grid_offset", grid->offset.x, grid->offset.y);
450 grid_shader.SetUniform1f("opacity", grid->opacity);
451 grid_shader.Unbind();
452
453 renderer.Draw(va, ib, grid_shader);
454 }
455 }
456
457 ecs.defer_begin(); // Start deferring modifications
458 active_board.children([&](flecs::entity child)
459 {
460 if (child.has<MarkerComponent>()) {
461 const TextureComponent* texture_marker = child.get<TextureComponent>();
462 if (texture_marker->textureID != 0) {
463 const Position* position_marker = child.get<Position>();
464 const Visibility* visibility_marker = child.get<Visibility>();
465 const Size* size_marker = child.get<Size>();
466
467 glm::mat4 marker_model = glm::translate(glm::mat4(1.0f), glm::vec3(position_marker->x, position_marker->y, 0.0f));
468 marker_model = glm::scale(marker_model, glm::vec3(size_marker->width, size_marker->height, 1.0f));
469
470 //glm::mat4 mvp = projection * viewMatrix * marker_model; //Calculate Screen Position(Can use method to standize it, but alter to return the MVP
471 float alpha = 1.0f;
472 if (!visibility_marker->isVisible) {
473 if (nm->getPeerRole() == Role::GAMEMASTER)
474 {
475 alpha = 0.5f;
476 }
477 else {
478 alpha = 0.0f;
479 }
480 }
481
482 shader.Bind();
483 shader.SetUniformMat4f("projection", projection);
484 shader.SetUniformMat4f("view", viewMatrix);
485 shader.SetUniformMat4f("model", marker_model);
486 shader.SetUniform1f("u_Alpha", alpha);
487 shader.SetUniform1i("u_Texture", 0);
488 shader.SetUniform1i("u_UseTexture", 1);
489 shader.Unbind();
490
491 GLCall(glActiveTexture(GL_TEXTURE0));
492 GLCall(glBindTexture(GL_TEXTURE_2D, texture_marker->textureID));
493
494 renderer.Draw(va, ib, shader);
495 }
496 }
497
498 if (child.has<FogOfWar>()) {
499 const Position* position_marker = child.get<Position>();
500 const Visibility* visibility_marker = child.get<Visibility>();
501 const TextureComponent* texture_marker = child.get<TextureComponent>();
502 const Size* size_marker = child.get<Size>();
503
504 glm::mat4 fog_model = glm::translate(glm::mat4(1.0f), glm::vec3(position_marker->x, position_marker->y, 0.0f));
505 fog_model = glm::scale(fog_model, glm::vec3(size_marker->width, size_marker->height, 1.0f));
506
507 float alpha = 1.0f;
508
509 if (!visibility_marker->isVisible) {
510 if (nm->getPeerRole() == Role::GAMEMASTER) {
511 alpha = 0.3f;
512 }
513 else
514 {
515 alpha = 0.0f;
516 }
517 }
518 else
519 {
520 if (nm->getPeerRole() == Role::GAMEMASTER)
521 {
522 alpha = 0.6f;
523 }
524 }
525
526 shader.Bind();
527 shader.SetUniformMat4f("projection", projection);
528 shader.SetUniformMat4f("view", viewMatrix);
529 shader.SetUniformMat4f("model", fog_model);
530 shader.SetUniform1f("u_Alpha", alpha);
531 shader.SetUniform1i("u_UseTexture", 0);
532 shader.Unbind();
533
534 renderer.Draw(va, ib, shader);
535
536 } });
537 ecs.defer_end();
538 }
539}
#define GLCall(x)
Definition Renderer.h:12
glm::mat4 getViewMatrix() const
glm::mat4 getProjectionMatrix() const
Here is the call graph for this function:

◆ renderCameraWindow()

void BoardManager::renderCameraWindow ( )

Definition at line 1626 of file BoardManager.cpp.

1627{
1628 // Check if the window should be shown
1629 if (!showCameraSettings)
1630 {
1631 return;
1632 }
1633
1634 // Begin the ImGui window
1635 auto mouse_pos = ImGui::GetMousePos();
1636 ImGui::SetNextWindowPos(ImVec2(mouse_pos.x, mouse_pos.y + ImGui::GetFrameHeightWithSpacing()), ImGuiCond_Appearing);
1637 ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.1f, 0.2f, 1.0f)); // Set the background color (RGBA)
1638 ImGui::Begin("Camera", &showCameraSettings, ImGuiWindowFlags_AlwaysAutoResize);
1639 ImGui::PopStyleColor();
1640 auto zoom = camera.getZoom();
1641
1642 ImGui::Text("Zoom Buttons");
1643 if (ImGui::Button("-"))
1644 {
1645 zoom = zoom - 0.01f;
1646 }
1647 ImGui::SameLine();
1648 if (ImGui::Button("+"))
1649 {
1650 zoom = zoom + 0.01f;
1651 }
1652
1653 ImGui::Separator();
1654 ImGui::SliderFloat("Zoom Slider", &zoom, 0.1f, 10.0f);
1655 camera.setZoom(zoom);
1656 ImGui::Separator();
1657 if (ImGui::Button("Reset Camera"))
1658 {
1659 resetCamera();
1660 }
1661
1662 ImGui::End();
1663}
bool showCameraSettings
void setZoom(float newZoomLevel)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ renderEditWindow()

void BoardManager::renderEditWindow ( )

Definition at line 1333 of file BoardManager.cpp.

1334{
1335 bool is_hovered = false;
1336 // Get the current mouse position to set the window position
1337 ImVec2 mousePos = ImGui::GetMousePos();
1338 ImGui::SetNextWindowPos(mousePos, ImGuiCond_Appearing);
1339 ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.2f, 0.3f, 0.4f, 1.0f)); // Set the background color (RGBA)
1340 ImGui::Begin("EditEntity", &showEditWindow, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove);
1341
1342 // Retrieve the Size and Visibility components of the entity
1343 is_hovered = ImGui::IsWindowHovered();
1344 auto is_popup_open = false;
1346 {
1347 auto nm = network_manager.lock();
1348 auto boardEnt = getActiveBoard();
1349
1350 auto size = edit_window_entity.get_mut<Size>(); // Mutable access to the size
1351 auto visibility = edit_window_entity.get_mut<Visibility>(); // Mutable access to the visibility
1352
1353 ImGui::BeginGroup();
1354 if (ImGui::Button("+ Size"))
1355 {
1356 if (nm && boardEnt.is_valid())
1357 {
1358 size->width = size->width * 1.1;
1359 size->height = size->height * 1.1; // Adjust height proportionally to the width
1361 {
1362 nm->broadcastMarkerUpdate(boardEnt.get<Identifier>()->id, edit_window_entity);
1363 }
1364 else if (edit_window_entity.has<FogOfWar>())
1365 {
1366 nm->broadcastFogUpdate(boardEnt.get<Identifier>()->id, edit_window_entity);
1367 }
1368 }
1369 }
1370 ImGui::SameLine();
1371 if (ImGui::Button("- Size"))
1372 {
1373 if (nm && boardEnt.is_valid())
1374 {
1375 size->width = size->width * 0.90;
1376 size->height = size->height * 0.90; // Adjust height proportionally to the width
1378 {
1379 nm->broadcastMarkerUpdate(boardEnt.get<Identifier>()->id, edit_window_entity);
1380 }
1381 else if (edit_window_entity.has<FogOfWar>())
1382 {
1383 nm->broadcastFogUpdate(boardEnt.get<Identifier>()->id, edit_window_entity);
1384 }
1385 }
1386 }
1387
1388 ImGui::EndGroup();
1389 // Checkbox for visibility change
1390 auto vis_temp = visibility->isVisible;
1391 if (ImGui::Checkbox("Visible", &vis_temp))
1392 {
1393 if (nm && boardEnt.is_valid())
1394 {
1395 visibility->isVisible = vis_temp;
1397 {
1398 nm->broadcastMarkerUpdate(boardEnt.get<Identifier>()->id, edit_window_entity);
1399 }
1400 else if (edit_window_entity.has<FogOfWar>())
1401 {
1402 nm->broadcastFogUpdate(boardEnt.get<Identifier>()->id, edit_window_entity);
1403 }
1404 }
1405 }
1406
1407 ImGui::Separator();
1408
1409 // Button to delete the entity (with a confirmation popup)
1410
1411 if (ImGui::Button("Delete"))
1412 {
1413 ImGui::OpenPopup("Confirm Delete");
1414 is_popup_open = true;
1415 }
1416
1417 if (ImGui::IsPopupOpen("Confirm Delete"))
1418 is_popup_open = true;
1419 if (ImGui::BeginPopupModal("Confirm Delete", nullptr, ImGuiWindowFlags_AlwaysAutoResize))
1420 {
1421 ImGui::Text("Are you sure you want to delete this entity?");
1422 ImGui::Separator();
1423
1424 if (ImGui::Button("Yes", ImVec2(120, 0)))
1425 {
1426 if (edit_window_entity.is_alive())
1427 {
1428 if (nm && boardEnt.is_valid())
1429 {
1431 {
1432 nm->broadcastMarkerDelete(boardEnt.get<Identifier>()->id, edit_window_entity);
1433 }
1434 else if (edit_window_entity.has<FogOfWar>())
1435 {
1436 nm->broadcastFogDelete(boardEnt.get<Identifier>()->id, edit_window_entity);
1437 }
1438 edit_window_entity.destruct(); // Delete the entity
1439 showEditWindow = false;
1440 }
1441 }
1442 ImGui::CloseCurrentPopup(); // Close the popup after deletion
1443 }
1444 ImGui::SameLine();
1445 if (ImGui::Button("No", ImVec2(120, 0)))
1446 {
1447 ImGui::CloseCurrentPopup(); // Close the popup without deletion
1448 }
1449 ImGui::EndPopup();
1450 }
1451 }
1452 else
1453 {
1454 ImGui::Text("Invalid entity or missing components!");
1455 }
1456 // --- Ownership (only for markers) ---
1457 if (edit_window_entity.is_valid() && edit_window_entity.has<MarkerComponent>())
1458 {
1459 auto nm = network_manager.lock();
1460 auto mc = edit_window_entity.get_mut<MarkerComponent>();
1461 auto idm = identity_manager; // you already have this in BoardManager
1462
1463 ImGui::Separator();
1464 ImGui::TextUnformatted("Owner");
1465 ImGui::Spacing();
1466
1467 // Build options as (uniqueId, displayName). Index 0 = (none)
1468 struct Opt
1469 {
1470 std::string uid;
1471 std::string label;
1472 };
1473 std::vector<Opt> options;
1474 options.push_back(Opt{"", "(none)"}); // index 0
1475
1476 // Collect connected peers -> uniqueId (dedup by uid)
1477 std::set<std::string> seenUids;
1478 if (nm && idm)
1479 {
1480 for (auto& [peerId, link] : nm->getPeers())
1481 {
1482 if (!link)
1483 continue;
1484 auto uidOpt = idm->uniqueForPeer(peerId);
1485 if (!uidOpt || uidOpt->empty())
1486 continue;
1487
1488 const std::string& uid = *uidOpt;
1489 if (!seenUids.insert(uid).second)
1490 continue; // dedup
1491
1492 // label = current username for that uid
1493 std::string label = idm->usernameForUnique(uid);
1494 if (label.empty())
1495 label = uid.substr(0, std::min<size_t>(8, uid.size()));
1496 options.push_back(Opt{uid, label});
1497 }
1498 }
1499
1500 // If current owner is offline, include them so the selection stays visible
1501 if (idm && !mc->ownerUniqueId.empty() && !seenUids.count(mc->ownerUniqueId))
1502 {
1503 std::string label = idm->usernameForUnique(mc->ownerUniqueId);
1504 if (label.empty())
1505 label = mc->ownerUniqueId.substr(0, std::min<size_t>(8, mc->ownerUniqueId.size()));
1506 options.push_back(Opt{mc->ownerUniqueId, label});
1507 }
1508
1509 // Find current selection by ownerUniqueId
1510 int selectedIndex = 0;
1511 for (int i = 1; i < (int)options.size(); ++i)
1512 if (options[i].uid == mc->ownerUniqueId)
1513 {
1514 selectedIndex = i;
1515 break;
1516 }
1517
1518 // Pagination (unchanged UI)
1519 static int ownerPage = 0;
1520 const int rowsPerPage = 6;
1521 const int totalRows = (int)options.size();
1522 const int totalPages = (totalRows + rowsPerPage - 1) / rowsPerPage;
1523 ownerPage = std::clamp(ownerPage, 0, std::max(0, totalPages - 1));
1524 auto ToggleRow = [&](const char* label, bool selected, int id) -> bool
1525 {
1526 ImGui::PushID(id);
1527 if (selected)
1528 {
1529 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.20f, 0.50f, 0.80f, 1.0f));
1530 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.25f, 0.55f, 0.85f, 1.0f));
1531 ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.15f, 0.45f, 0.75f, 1.0f));
1532 }
1533 else
1534 {
1535 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.25f, 0.28f, 0.32f, 1.0f));
1536 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.30f, 0.33f, 0.38f, 1.0f));
1537 ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.22f, 0.25f, 0.29f, 1.0f));
1538 }
1539 bool clicked = ImGui::Button(label, ImVec2(-FLT_MIN, 0));
1540 ImGui::PopStyleColor(3);
1541 ImGui::PopID();
1542 return clicked;
1543 };
1544
1545 const int start = ownerPage * rowsPerPage;
1546 const int end = std::min(start + rowsPerPage, totalRows);
1547
1548 // Render visible rows
1549 for (int i = start; i < end; ++i)
1550 {
1551 const bool isSel = (selectedIndex == i);
1552 const char* label = options[i].label.c_str();
1553 if (ToggleRow(label, isSel, i))
1554 {
1555 selectedIndex = i;
1556
1557 // APPLY IMMEDIATELY (no "Apply Ownership" button)
1558 const std::string prevOwnerUid = mc->ownerUniqueId;
1559 mc->ownerUniqueId = options[i].uid; // << authoritative owner
1560 mc->ownerPeerUsername.clear();
1561 if (idm && !mc->ownerUniqueId.empty())
1562 mc->ownerPeerUsername = idm->usernameForUnique(mc->ownerUniqueId); // display only
1563
1564 // If owner changed, clear drag state so new owner can take over smoothly
1565 if (edit_window_entity.has<Identifier>() && nm)
1566 {
1567 const auto mid = edit_window_entity.get<Identifier>()->id;
1568 if (prevOwnerUid != mc->ownerUniqueId)
1569 nm->clearDragState(mid); // small helper: drag_.erase(mid)
1570 }
1571
1572 // Broadcast the change now
1573 if (nm)
1574 {
1575 auto boardEnt = getActiveBoard();
1576 if (boardEnt.is_valid())
1577 nm->broadcastMarkerUpdate(boardEnt.get<Identifier>()->id, edit_window_entity);
1578 }
1579 }
1580 }
1581
1582 // Pagination controls
1583 if (totalPages > 1)
1584 {
1585 ImGui::Spacing();
1586 ImGui::BeginDisabled(ownerPage <= 0);
1587 if (ImGui::Button("< Prev"))
1588 ownerPage--;
1589 ImGui::EndDisabled();
1590 ImGui::SameLine();
1591 ImGui::Text("Page %d / %d", ownerPage + 1, std::max(1, totalPages));
1592 ImGui::SameLine();
1593 ImGui::BeginDisabled(ownerPage >= totalPages - 1);
1594 if (ImGui::Button("Next >"))
1595 ownerPage++;
1596 ImGui::EndDisabled();
1597 }
1598
1599 // Flags — apply immediately when toggled
1600 bool flagsChanged = false;
1601 flagsChanged |= ImGui::Checkbox("Allow all players to move", &mc->allowAllPlayersMove);
1602 flagsChanged |= ImGui::Checkbox("Locked (players cannot move)", &mc->locked);
1603 if (flagsChanged && nm)
1604 {
1605 auto boardEnt = getActiveBoard();
1606 if (boardEnt.is_valid())
1607 nm->broadcastMarkerUpdate(boardEnt.get<Identifier>()->id, edit_window_entity);
1608 }
1609 }
1610
1611 ImGui::End();
1612 ImGui::PopStyleColor(); // Restore the original background color
1613
1614 if (!is_hovered && ImGui::IsMouseClicked(ImGuiMouseButton_Left) && !is_popup_open)
1615 {
1616 showEditWindow = false;
1617 }
1618
1619 if (!showEditWindow)
1620 {
1621 edit_window_entity = flecs::entity();
1622 }
1623 //close edit window when clicking outside it
1624}
flecs::entity edit_window_entity
flecs::entity getActiveBoard() const
Here is the call graph for this function:

◆ renderGridWindow()

void BoardManager::renderGridWindow ( )

Definition at line 1665 of file BoardManager.cpp.

1666{
1667 // Check if the window should be shown
1668 if (!showGridSettings)
1669 {
1670 return;
1671 }
1672
1673 // Begin the ImGui window
1674 auto mouse_pos = ImGui::GetMousePos();
1675 ImGui::SetNextWindowPos(ImVec2(mouse_pos.x, mouse_pos.y + ImGui::GetFrameHeightWithSpacing()), ImGuiCond_Appearing);
1676 ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.1f, 0.2f, 1.0f)); // Set the background color (RGBA)
1677 ImGui::Begin("Grid", &showGridSettings, ImGuiWindowFlags_AlwaysAutoResize);
1678
1679 ImGui::PopStyleColor();
1680 // Get a mutable reference to the Grid component from the active board
1681 auto grid = active_board.get_mut<Grid>();
1682 bool changed = false;
1683
1684 if (grid)
1685 {
1686 // --- BOOLEAN CHECKBOXES ---
1687 changed |= ImGui::Checkbox("Visible", &grid->visible);
1688 changed |= ImGui::Checkbox("Snap to Grid", &grid->snap_to_grid);
1689 //ImGui::Checkbox("Hexagonal Grid", &grid->is_hex);
1690
1691 // --- FLOAT SLIDERS ---
1692 changed |= ImGui::SliderFloat("Cell Size", &grid->cell_size, 10.0f, 200.0f);
1693 ImGui::SameLine();
1694 if (ImGui::Button("-##size"))
1695 {
1696 grid->cell_size = grid->cell_size - 0.01f;
1697 changed = true;
1698 }
1699 ImGui::SameLine();
1700 if (ImGui::Button("+##size"))
1701 {
1702 grid->cell_size = grid->cell_size + 0.01f;
1703 changed = true;
1704 }
1705 // --- OFFSET CONTROLS (SIMPLIFIED WITH SLIDERS) ---
1706 ImGui::Text("Grid Offset");
1707 changed |= ImGui::SliderFloat("Offset X", &grid->offset.x, -500.0f, 500.0f);
1708 ImGui::SameLine();
1709 if (ImGui::Button("-##offsetx"))
1710 {
1711 grid->offset.x = grid->offset.x - 0.01f;
1712 changed = true;
1713 }
1714 ImGui::SameLine();
1715 if (ImGui::Button("+##offsetx"))
1716 {
1717 grid->offset.x = grid->offset.x + 0.01f;
1718 changed = true;
1719 }
1720 changed |= ImGui::SliderFloat("Offset Y", &grid->offset.y, -500.0f, 500.0f);
1721
1722 ImGui::SameLine();
1723 if (ImGui::Button("-##offsety"))
1724 {
1725 grid->offset.y = grid->offset.y - 0.01f;
1726 changed = true;
1727 }
1728 ImGui::SameLine();
1729 if (ImGui::Button("+##offsety"))
1730 {
1731 grid->offset.y = grid->offset.y + 0.01f;
1732 changed = true;
1733 }
1734
1735 // Button to reset the offset
1736 if (ImGui::Button("Reset Offset"))
1737 {
1738 grid->offset = glm::vec2(0.0f);
1739 changed = true;
1740 }
1741
1742 if (changed)
1743 {
1744 if (grid->snap_to_grid)
1745 {
1747 }
1748 if (auto nm = network_manager.lock())
1749 {
1750 if (active_board.has<Identifier>())
1751 nm->broadcastGridUpdate(active_board.get<Identifier>()->id, active_board);
1752 }
1753 }
1754 }
1755 else
1756 {
1757 ImGui::Text("Active board entity does not have a Grid component.");
1758 }
1759
1760 ImGui::End();
1761}
bool showGridSettings
void resnapAllMarkersToNearest(const Grid &grid)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ renderToolbar()

void BoardManager::renderToolbar ( const ImVec2 & window_position)

Definition at line 204 of file BoardManager.cpp.

205{
206 ImGuiWindowFlags toolbar_child_flags =
207 ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoMove |
208 ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoTitleBar |
209 ImGuiWindowFlags_AlwaysAutoResize;
210
211 auto panel_color = ImVec4(0.18f, 0.22f, 0.27f, 1.00f); // toolbar panel
212 auto bg_color = ImVec4(0.12f, 0.14f, 0.17f, 1.00f);
213 auto old_bg_color = ImVec4(0.2f, 0.3f, 0.4f, 1.0f);
214
215 auto green_light_color = ImVec4(0.55f, 0.95f, 0.65f, 1.00f);
216 auto green_mid_color = ImVec4(0.20f, 0.75f, 0.35f, 1.00f);
217 auto green_dark_color = ImVec4(0.12f, 0.45f, 0.22f, 1.00f);
218 auto mint_color = ImVec4(0.50f, 0.95f, 0.85f, 1.00f);
219
220 auto blue_light_color = ImVec4(0.55f, 0.75f, 1.00f, 1.00f);
221 auto blue_mid_color = ImVec4(0.28f, 0.50f, 0.92f, 1.00f);
222 auto blue_dark_color = ImVec4(0.15f, 0.30f, 0.55f, 1.00f);
223
224 auto purple_color = ImVec4(0.70f, 0.45f, 0.95f, 1.00f);
225 auto violet_color = ImVec4(0.55f, 0.35f, 0.85f, 1.00f);
226 auto mid_purple_color = ImVec4(0.45f, 0.28f, 0.70f, 1.00f);
227
228 auto orange_color = ImVec4(0.98f, 0.60f, 0.20f, 1.00f);
229 auto amber_color = ImVec4(1.00f, 0.78f, 0.25f, 1.00f);
230 auto yellow_color = ImVec4(0.95f, 0.90f, 0.30f, 1.00f);
231
232 auto button_toggled_color = amber_color;
233 auto button_toggled_hover = orange_color;
234 auto button_toggled_active = yellow_color;
235
236 auto button_untoggled_color = blue_mid_color;
237 auto button_untoggled_hover = blue_light_color;
238 auto button_untoggled_active = yellow_color;
239
240 auto button_popup_color = green_dark_color;
241 auto button_popup_hover = green_mid_color;
242 auto button_popup_active = mint_color;
243
244 ImGui::SetCursorPos(window_position);
245
246 ImVec2 toolbar_size = ImVec2(0, 0); // Auto-size to content
247
248 // -------- Hotkeys (before rendering) ------------------------------------
249 auto nm = network_manager.lock();
250 if (!nm)
251 throw std::exception("[BoardManager] NetworkManager Expired");
252
253 ImGuiIO& io = ImGui::GetIO();
254 bool isGM = (nm->getPeerRole() == Role::GAMEMASTER);
255 bool allowHotkeys = !UiTypingGuard::IsTyping();
256
257 // We need a tiny bit of state for Space-hold override
258 static bool s_spaceHoldActive = false;
259 static Tool s_spaceReturnTool = Tool::MOVE; // Tool to restore on Space release
260
261 // Helper to change tool and always record previousTool
262 auto setTool = [&](Tool t)
263 {
264 if (currentTool != t)
265 {
266 previousTool = currentTool; // remember where we came from
267 currentTool = t;
268 }
269 };
270
271 if (allowHotkeys)
272 {
273 // Space: press => temp Move; release => restore the tool that was active at press time
274 if (ImGui::IsKeyPressed(ImGuiKey_Space))
275 {
276 if (!s_spaceHoldActive)
277 {
278 s_spaceHoldActive = true;
279 s_spaceReturnTool = currentTool; // snapshot tool active at press time
280 if (currentTool != Tool::MOVE)
281 {
283 }
284 }
285 }
286 if (s_spaceHoldActive && ImGui::IsKeyReleased(ImGuiKey_Space))
287 {
288 s_spaceHoldActive = false;
289 currentTool = s_spaceReturnTool; // restore exactly what was active at press time
290 }
291
292 // Regular hotkeys (don’t fire while Space-hold is active)
293 if (!s_spaceHoldActive)
294 {
295 if (ImGui::IsKeyPressed(ImGuiKey_M))
296 setTool(Tool::MOVE);
297 if (isGM && ImGui::IsKeyPressed(ImGuiKey_F))
298 setTool(Tool::FOG);
299 if (isGM && ImGui::IsKeyPressed(ImGuiKey_S))
300 setTool(Tool::SELECT);
301
302 if (ImGui::IsKeyPressed(ImGuiKey_C))
304
305 if (isGM && ImGui::IsKeyPressed(ImGuiKey_G))
307
308 if (ImGui::IsKeyPressed(ImGuiKey_Q))
309 std::swap(currentTool, previousTool);
310 }
311 }
312 // -------------------------------------------------------------------------
313
314 ImGui::PushStyleColor(ImGuiCol_WindowBg, panel_color);
315 ImGui::BeginChild("ToolbarChild", toolbar_size, false, toolbar_child_flags);
316
317 // Tool: Previous (Q)
318 ImGui::PushStyleColor(ImGuiCol_Button, purple_color);
319 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, violet_color);
320 ImGui::PushStyleColor(ImGuiCol_ButtonActive, mid_purple_color);
321 if (ImGui::Button("Prev.(Q)", ImVec2(65, 40)))
322 {
323 std::swap(currentTool, previousTool);
324 }
325 ImGui::PopStyleColor(3);
326 ImGui::SameLine();
327
328 // Tool: Move (M)
329 ImGui::PushStyleColor(ImGuiCol_Button, currentTool == Tool::MOVE ? button_toggled_color : button_untoggled_color);
330 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, currentTool == Tool::MOVE ? button_toggled_hover : button_untoggled_hover);
331 ImGui::PushStyleColor(ImGuiCol_ButtonActive, currentTool == Tool::MOVE ? button_toggled_active : button_untoggled_active);
332 if (ImGui::Button(" Move (M)\n(Hold Space)", ImVec2(100, 40)))
333 {
334 setTool(Tool::MOVE);
335 }
336 ImGui::PopStyleColor(3);
337 ImGui::SameLine();
338
339 if (isGM)
340 {
341 // Tool: Fog (F)
342 ImGui::PushStyleColor(ImGuiCol_Button, currentTool == Tool::FOG ? button_toggled_color : button_untoggled_color);
343 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, currentTool == Tool::FOG ? button_toggled_hover : button_untoggled_hover);
344 ImGui::PushStyleColor(ImGuiCol_ButtonActive, currentTool == Tool::FOG ? button_toggled_active : button_untoggled_active);
345 if (ImGui::Button("Fog (F)", ImVec2(100, 40)))
346 {
347 setTool(Tool::FOG);
348 }
349 ImGui::PopStyleColor(3);
350 ImGui::SameLine();
351
352 // Tool: Select (S)
353 ImGui::PushStyleColor(ImGuiCol_Button, currentTool == Tool::SELECT ? button_toggled_color : button_untoggled_color);
354 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, currentTool == Tool::SELECT ? button_toggled_hover : button_untoggled_hover);
355 ImGui::PushStyleColor(ImGuiCol_ButtonActive, currentTool == Tool::SELECT ? button_toggled_active : button_untoggled_active);
356 if (ImGui::Button("Select (S)", ImVec2(100, 40)))
357 {
358 setTool(Tool::SELECT);
359 }
360 ImGui::PopStyleColor(3);
361 ImGui::SameLine();
362 }
363
364 // Camera Settings (no hotkey here)
365 ImGui::PushStyleColor(ImGuiCol_Button, button_popup_color);
366 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, button_popup_hover);
367 ImGui::PushStyleColor(ImGuiCol_ButtonActive, button_popup_active);
368 if (ImGui::Button("Camera Settings (C)", ImVec2(150, 40)))
369 {
371 }
372 ImGui::PopStyleColor(3);
373
374 if (isGM)
375 {
376 ImGui::SameLine();
377 ImGui::PushStyleColor(ImGuiCol_Button, button_popup_color);
378 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, button_popup_hover);
379 ImGui::PushStyleColor(ImGuiCol_ButtonActive, button_popup_active);
380 if (ImGui::Button("Grid Settings (G)", ImVec2(150, 40)))
381 {
383 }
384 ImGui::PopStyleColor(3);
385 }
386
387 ImGui::PopStyleColor(); // toolbar bg
388 ImGui::EndChild();
389
392}
Tool
@ SELECT
void renderGridWindow()
void renderCameraWindow()
Here is the call graph for this function:

◆ resetCamera()

void BoardManager::resetCamera ( )

Definition at line 1116 of file BoardManager.cpp.

1117{
1118 camera.setPosition(glm::vec2(0.0f, 0.0f));
1119 camera.setZoom(1.0f);
1120}
void setPosition(glm::vec2 newPosition)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ resnapAllMarkersToNearest()

void BoardManager::resnapAllMarkersToNearest ( const Grid & grid)

Definition at line 837 of file BoardManager.cpp.

838{
839 if (grid.cell_size <= 0.0f)
840 return;
841
842 auto nm = network_manager.lock();
843
844 ecs.defer_begin();
845 active_board.children([&](flecs::entity e)
846 {
847 if (!e.has<MarkerComponent>()) return;
848
849 Position* pos = e.get_mut<Position>();
850 if (!pos) return;
851
852 glm::vec2 p(pos->x, pos->y);
853 glm::vec2 goal = snapToSquareCenter(p, grid.offset, grid.cell_size);
854
855 // Only write if it actually changes (avoid network spam)
856 if (glm::any(glm::epsilonNotEqual(p, goal, glm::vec2(1e-4f)))) {
857 pos->x = goal.x;
858 pos->y = goal.y;
859
860 // If you're broadcasting grid-driven corrections:
861 if (nm && e.has<Identifier>()) {
862 const auto bid = active_board.get<Identifier>()->id;
863 nm->broadcastMarkerUpdate(bid, e); // or your existing "final pos" message
864 }
865 } });
866 ecs.defer_end();
867}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ saveActiveBoard() [1/2]

void BoardManager::saveActiveBoard ( const std::string & filePath)

◆ saveActiveBoard() [2/2]

void BoardManager::saveActiveBoard ( std::filesystem::path & filePath)

Definition at line 1257 of file BoardManager.cpp.

1258{
1259 if (!active_board.is_alive())
1260 {
1261 std::cerr << "No active board to save." << std::endl;
1262 return;
1263 }
1264 auto board = active_board.get<Board>();
1265 if (!std::filesystem::exists(board_directory_path))
1266 {
1267 std::filesystem::create_directory(board_directory_path);
1268 }
1269
1270 auto board_file_path = board_directory_path / (board->board_name + ".runic");
1271
1272 std::vector<uint8_t> buffer;
1274
1275 std::ofstream outFile(board_file_path, std::ios::binary);
1276 if (outFile)
1277 {
1278 outFile.write(reinterpret_cast<const char*>(buffer.data()), buffer.size());
1279 outFile.close();
1280 std::cout << "Board saved successfully to " << board_directory_path << std::endl;
1281 }
1282 else
1283 {
1284 std::cerr << "Failed to save board to " << board_directory_path << std::endl;
1285 }
1286}
static void serializeBoardEntity(std::vector< unsigned char > &buffer, const flecs::entity entity, flecs::world &ecs)
Definition Serializer.h:192
Here is the call graph for this function:

◆ sendEntityUpdate()

void BoardManager::sendEntityUpdate ( flecs::entity entity)

◆ sendGameState()

void BoardManager::sendGameState ( )

◆ setActiveBoard()

void BoardManager::setActiveBoard ( flecs::entity board_entity)

Definition at line 76 of file BoardManager.cpp.

77{
78 active_board = board_entity;
79 auto nm = network_manager.lock();
80 if (!nm)
81 if (nm->getPeerRole() == Role::GAMEMASTER)
82 nm->broadcastBoard(active_board);
83}
Here is the caller graph for this function:

◆ setCurrentTool()

void BoardManager::setCurrentTool ( Tool newTool)

Definition at line 1179 of file BoardManager.cpp.

1180{
1181 currentTool = newTool;
1182}

◆ setShowEditWindow()

void BoardManager::setShowEditWindow ( bool show,
flecs::entity edit_entity = flecs::entity() )
inline

Definition at line 248 of file BoardManager.h.

249 {
250 if (showEditWindow && edit_window_entity.is_valid())
251 return;
252 showEditWindow = show;
253 edit_window_entity = edit_entity;
254 };

◆ shouldSendMarkerMove()

bool BoardManager::shouldSendMarkerMove ( uint64_t markerId) const

Definition at line 1051 of file BoardManager.cpp.

1052{
1053 using namespace std::chrono;
1054 static std::unordered_map<uint64_t, steady_clock::time_point> lastSent;
1055 static constexpr auto kMinInterval = milliseconds(33); // ~30 Hz. Use 50ms for ~20 Hz if you prefer.
1056
1057 const auto now = steady_clock::now();
1058 auto it = lastSent.find(markerId);
1059 if (it == lastSent.end() || (now - it->second) >= kMinInterval)
1060 {
1061 lastSent[markerId] = now;
1062 return true; // allow this send
1063 }
1064 return false; // too soon, skip this tick
1065}
Here is the caller graph for this function:

◆ snapToGrid()

glm::vec2 BoardManager::snapToGrid ( glm::vec2 raw_world_pos)

◆ startMouseDrag()

void BoardManager::startMouseDrag ( glm::vec2 mousePos,
bool draggingMarker )

Definition at line 924 of file BoardManager.cpp.

925{
926 mouse_start_world_pos = mousePos;
928
929 if (currentTool == Tool::MOVE)
930 {
931 if (draggingMap)
932 {
933 active_board.set<Panning>({true});
934 return;
935 }
936
937 // Marker drag start:
938 auto ent = getEntityAtMousePosition(mousePos);
939 if (!ent.is_valid() || !ent.has<MarkerComponent>() || !ent.has<Moving>() || !ent.has<Identifier>())
940 return;
941
942 auto nm = network_manager.lock();
943 if (!nm)
944 return;
945
946 const auto mid = ent.get<Identifier>()->id;
947
948 // Do NOT start if someone else is already dragging this marker.
949 if (nm->isMarkerBeingDragged(mid) && !nm->amIDragging(mid))
950 return;
951
952 // Optional: prevent starting a second local drag (you said players shouldn’t drag 2 markers)
953 if (isDraggingMarker())
954 return;
955
956 if (!canMoveMarker(ent.get<MarkerComponent>(), ent))
957 return;
958
959 // Local start
960 ent.set<Moving>(Moving{true});
961 nm->markDraggingLocal(mid, true);
962
963 if (active_board.has<Identifier>())
964 {
965 const auto bid = active_board.get<Identifier>()->id;
966 nm->broadcastMarkerMoveState(bid, ent); // START (isDragging=true)
967 }
968 }
969 else if (currentTool == Tool::FOG)
970 {
971 is_creating_fog = true;
972 }
973}
flecs::entity getEntityAtMousePosition(glm::vec2 mouse_position)
bool canMoveMarker(const MarkerComponent *mc, flecs::entity markerEnt) const
bool isDraggingMarker(bool local_drag_only=true)
glm::vec2 worldToScreenPosition(glm::vec2 world_position) const
Here is the call graph for this function:

Member Data Documentation

◆ active_board

flecs::entity BoardManager::active_board = flecs::entity()
private

Definition at line 280 of file BoardManager.h.

◆ board_name

std::string BoardManager::board_name

Definition at line 235 of file BoardManager.h.

◆ camera

Camera BoardManager::camera

Definition at line 238 of file BoardManager.h.

◆ currentTool

Tool BoardManager::currentTool
private

Definition at line 284 of file BoardManager.h.

◆ ecs

flecs::world BoardManager::ecs
private

Definition at line 279 of file BoardManager.h.

◆ edit_window_entity

flecs::entity BoardManager::edit_window_entity = flecs::entity()
private

Definition at line 270 of file BoardManager.h.

◆ grid_entity

flecs::entity BoardManager::grid_entity = flecs::entity()
private

Definition at line 281 of file BoardManager.h.

◆ identity_manager

std::shared_ptr<IdentityManager> BoardManager::identity_manager
private

Definition at line 272 of file BoardManager.h.

◆ is_creating_fog

bool BoardManager::is_creating_fog = false
private

Definition at line 283 of file BoardManager.h.

◆ map_directory

std::shared_ptr<DirectoryWindow> BoardManager::map_directory

Definition at line 236 of file BoardManager.h.

◆ marker_directory

std::shared_ptr<DirectoryWindow> BoardManager::marker_directory

Definition at line 237 of file BoardManager.h.

◆ markerBasePx

float BoardManager::markerBasePx = 50.0f
private

Definition at line 269 of file BoardManager.h.

◆ mouse_current_world_pos

glm::vec2 BoardManager::mouse_current_world_pos
private

Definition at line 277 of file BoardManager.h.

◆ mouse_start_screen_pos

glm::vec2 BoardManager::mouse_start_screen_pos
private

Definition at line 275 of file BoardManager.h.

◆ mouse_start_world_pos

glm::vec2 BoardManager::mouse_start_world_pos
private

Definition at line 276 of file BoardManager.h.

◆ network_manager

std::weak_ptr<NetworkManager> BoardManager::network_manager
private

Definition at line 271 of file BoardManager.h.

◆ previousTool

Tool BoardManager::previousTool
private

Definition at line 285 of file BoardManager.h.

◆ showCameraSettings

bool BoardManager::showCameraSettings = false
private

Definition at line 268 of file BoardManager.h.

◆ showEditWindow

bool BoardManager::showEditWindow = false
private

Definition at line 266 of file BoardManager.h.

◆ showGridSettings

bool BoardManager::showGridSettings = false
private

Definition at line 267 of file BoardManager.h.


The documentation for this class was generated from the following files: