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

#include <ApplicationHandler.h>

Collaboration diagram for ApplicationHandler:

Public Member Functions

 ApplicationHandler (GLFWwindow *window, std::shared_ptr< DirectoryWindow > map_directory, std::shared_ptr< DirectoryWindow > marker_directory)
 
 ~ApplicationHandler ()
 
int run ()
 
void pushStatusToast (const std::string &msg, ImGuiToaster::Level lvl, float durationSec=5.0f)
 

Private Member Functions

void renderMainMenuBar ()
 
void renderDockSpace ()
 
void renderMapFBO (VertexArray &va, IndexBuffer &ib, Shader &shader, Shader &grid_shader, Renderer &renderer)
 
void renderActiveGametable ()
 
void CreateMapFBO (int width, int height)
 
void ResizeMapFBO (int newWidth, int newHeight)
 
void DeleteMapFBO ()
 
void TickAutoSave ()
 
void GetMousePosInItem (ImVec2 &out_item_size, ImVec2 &item_screen_pos)
 
void DrawDebugCircle (ImVec2 coords, bool is_relative_to_window, ImU32 color, float radius=10.0f)
 

Private Attributes

std::shared_ptr< ImGuiToastertoaster_
 
std::shared_ptr< MapFBOmap_fbo
 
GLFWwindow * window
 
flecs::world ecs
 
std::shared_ptr< GameTableManagergame_table_manager
 
std::shared_ptr< DirectoryWindowmap_directory
 
std::shared_ptr< DirectoryWindowmarker_directory
 
std::shared_ptr< NotesManagernotes_manager
 
std::shared_ptr< NoteEditorUInote_editor_ui
 
bool g_dockspace_initialized = false
 
glm::vec2 current_fbo_mouse_pos = glm::vec2(0, 0)
 
ImVec2 current_map_relative_mouse_pos = ImVec2(0, 0)
 
bool g_draw_debug_circle = false
 

Detailed Description

Definition at line 55 of file ApplicationHandler.h.

Constructor & Destructor Documentation

◆ ApplicationHandler()

ApplicationHandler::ApplicationHandler ( GLFWwindow * window,
std::shared_ptr< DirectoryWindow > map_directory,
std::shared_ptr< DirectoryWindow > marker_directory )

Definition at line 12 of file ApplicationHandler.cpp.

12 :
14{
16 toaster_ = std::make_shared<ImGuiToaster>(cfg);
17 game_table_manager->setup();
18 game_table_manager->setToaster(toaster_);
19
20 auto note_cfg = NotesManagerConfig{
23
24 notes_manager = std::make_shared<NotesManager>(note_cfg, toaster_);
25 note_editor_ui = std::make_shared<NoteEditorUI>(notes_manager, toaster_);
26 note_editor_ui->setChatManager(game_table_manager->chat_manager);
27
28 ecs.component<Position>(); // .member<float>("x").member<float>("y");
29 ecs.component<Size>(); // .member<float>("width").member<float>("height");
30 ecs.component<Visibility>(); // .member<bool>("isVisible");
31 ecs.component<Moving>(); // .member<bool>("isDragging");
32 ecs.component<TextureComponent>(); // .member<GLuint>("textureID").member<std::string>("imagePath");
33 //ecs.component<Zoom>();// .member<float>("zoomLevel");
34 ecs.component<Panning>(); // .member<bool>("isPanning");
35 ecs.component<Grid>(); // .member<glm::vec2>("offset").member<glm::vec2>("scale");
36 ecs.component<Board>();
37 ecs.component<MarkerComponent>();
38 ecs.component<FogOfWar>();
39 ecs.component<GameTable>();
40 //ecs.component<Network>();
41 ecs.component<Notes>();
42 ecs.component<Identifier>();
43 ecs.component<NoteComponent>();
44 //ecs.component<PeerInfo>();
45 //ecs.component<ToolComponent>();
48}
std::shared_ptr< GameTableManager > game_table_manager
std::shared_ptr< DirectoryWindow > map_directory
std::shared_ptr< DirectoryWindow > marker_directory
std::shared_ptr< NotesManager > notes_manager
std::shared_ptr< MapFBO > map_fbo
std::shared_ptr< NoteEditorUI > note_editor_ui
std::shared_ptr< ImGuiToaster > toaster_
static fs::path getGameTablesPath()
Definition PathManager.h:76
static fs::path getNotesPath()
Definition PathManager.h:71
void RegisterAllDefaultToggles()
void RegisterToasterToggles(std::weak_ptr< ImGuiToaster > toaster_)
Here is the call graph for this function:

◆ ~ApplicationHandler()

ApplicationHandler::~ApplicationHandler ( )

Definition at line 50 of file ApplicationHandler.cpp.

51{
53}
Here is the call graph for this function:

Member Function Documentation

◆ CreateMapFBO()

void ApplicationHandler::CreateMapFBO ( int width,
int height )
private

Definition at line 55 of file ApplicationHandler.cpp.

56{
57 if (map_fbo->fboID != 0)
58 { // If FBO already exists, delete it first
60 }
61
62 if (width <= 0 || height <= 0)
63 {
64 std::cerr << "Warning: Attempted to create FBO with invalid dimensions: " << width << "x" << height << std::endl;
65 // Keep FBO as 0,0,0 if dimensions are invalid to avoid errors
66 map_fbo->width = 0;
67 map_fbo->height = 0;
68 return;
69 }
70
71 map_fbo->width = width;
72 map_fbo->height = height;
73
74 GLCall(glGenFramebuffers(1, &map_fbo->fboID));
75 GLCall(glBindFramebuffer(GL_FRAMEBUFFER, map_fbo->fboID));
76
77 // Create a color attachment texture
78 GLCall(glGenTextures(1, &map_fbo->textureID));
79 GLCall(glBindTexture(GL_TEXTURE_2D, map_fbo->textureID));
80 GLCall(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr));
81 GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
82 GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
83 GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); // Important for non-power-of-2 textures
84 GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
85 GLCall(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, map_fbo->textureID, 0));
86
87 // Create a renderbuffer object for depth and stencil attachment
88 // This is crucial for proper 3D rendering (correct Z-buffer, stencil for fog, etc.)
89 GLCall(glGenRenderbuffers(1, &map_fbo->rboID));
90 GLCall(glBindRenderbuffer(GL_RENDERBUFFER, map_fbo->rboID));
91 GLCall(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height));
92 GLCall(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, map_fbo->rboID));
93
94 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
95 {
96 std::cerr << "ERROR::FRAMEBUFFER:: Framebuffer is not complete! Status: " << glCheckFramebufferStatus(GL_FRAMEBUFFER) << std::endl;
97 }
98
99 GLCall(glBindFramebuffer(GL_FRAMEBUFFER, 0)); // Unbind FBO, return to default framebuffer
100}
#define GLCall(x)
Definition Renderer.h:12
Here is the call graph for this function:
Here is the caller graph for this function:

◆ DeleteMapFBO()

void ApplicationHandler::DeleteMapFBO ( )
private

Definition at line 124 of file ApplicationHandler.cpp.

125{
126 if (map_fbo->fboID != 0)
127 {
128 GLCall(glDeleteFramebuffers(1, &map_fbo->fboID));
129 map_fbo->fboID = 0;
130 }
131 if (map_fbo->textureID != 0)
132 {
133 GLCall(glDeleteTextures(1, &map_fbo->textureID));
134 map_fbo->textureID = 0;
135 }
136 if (map_fbo->rboID != 0)
137 {
138 GLCall(glDeleteRenderbuffers(1, &map_fbo->rboID));
139 map_fbo->rboID = 0;
140 }
141 map_fbo->width = 0;
142 map_fbo->height = 0;
143}
Here is the caller graph for this function:

◆ DrawDebugCircle()

void ApplicationHandler::DrawDebugCircle ( ImVec2 coords,
bool is_relative_to_window,
ImU32 color,
float radius = 10.0f )
inlineprivate

Definition at line 99 of file ApplicationHandler.h.

100 {
101 ImDrawList* draw_list = ImGui::GetForegroundDrawList();
102 ImVec2 final_screen_pos = coords;
103
104 if (is_relative_to_window)
105 {
106 // This conversion means 'coords' is relative to the current ImGui window's top-left.
107 // For debugging mouse clicks on an ImGui::Image, you generally calculate
108 // relative to the image, and then add the image's global position.
109 // So, for mouse click debug, you'll usually pass false for is_relative_to_window
110 // after converting your calculated points back to global screen space.
111 final_screen_pos.x += ImGui::GetWindowPos().x;
112 final_screen_pos.y += ImGui::GetWindowPos().y;
113 }
114
115 draw_list->AddCircleFilled(final_screen_pos, radius, color, 16);
116 }
Here is the caller graph for this function:

◆ GetMousePosInItem()

void ApplicationHandler::GetMousePosInItem ( ImVec2 & out_item_size,
ImVec2 & item_screen_pos )
private

◆ pushStatusToast()

void ApplicationHandler::pushStatusToast ( const std::string & msg,
ImGuiToaster::Level lvl,
float durationSec = 5.0f )
inline

Definition at line 63 of file ApplicationHandler.h.

64 {
65 if (toaster_)
66 toaster_->Push(lvl, msg, durationSec);
67 }
Definition Message.h:28

◆ renderActiveGametable()

void ApplicationHandler::renderActiveGametable ( )
private

Definition at line 450 of file ApplicationHandler.cpp.

451{
452 if (game_table_manager->isGameTableActive())
453 {
454
455 ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoScrollbar;
456
457 ImGui::SetNextWindowSizeConstraints(ImVec2(800, 600), ImVec2(FLT_MAX, FLT_MAX));
458 ImGui::Begin("MapWindow", nullptr, window_flags);
459 auto is_map_window_hovered = ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlappedByItem | ImGuiHoveredFlags_RootAndChildWindows);
460 ImVec2 content_size = ImGui::GetContentRegionAvail();
461
462 if (content_size.x > 0 && content_size.y > 0)
463 {
464 ResizeMapFBO(static_cast<int>(content_size.x), static_cast<int>(content_size.y));
465 }
466 ImVec2 window_size = ImGui::GetWindowSize();
467 ImVec2 window_pos = ImGui::GetWindowPos();
468
469 if (game_table_manager->isBoardActive())
470 {
471 if (map_fbo->textureID != 0)
472 {
473 ImGui::Image((void*)(intptr_t)map_fbo->textureID, content_size, ImVec2(0, 1), ImVec2(1, 0));
474
475 ImVec2 displayed_image_size = ImGui::GetItemRectSize();
476 ;
477 ImVec2 image_min_screen_pos = ImGui::GetItemRectMin();
478
479 ImVec2 toolbar_cursor_pos_in_parent = ImVec2(image_min_screen_pos.x - window_pos.x,
480 image_min_screen_pos.y - window_pos.y);
481 game_table_manager->board_manager->renderToolbar(toolbar_cursor_pos_in_parent);
482
483 ImGuiIO& io = ImGui::GetIO();
484 ImVec2 mouse_pos_global = ImGui::GetMousePos();
485
486 bool is_mouse_within_image_bounds = (mouse_pos_global.x >= image_min_screen_pos.x &&
487 mouse_pos_global.x < (image_min_screen_pos.x + displayed_image_size.x) &&
488 mouse_pos_global.y >= image_min_screen_pos.y &&
489 mouse_pos_global.y < (image_min_screen_pos.y + displayed_image_size.y));
490 game_table_manager->processMouseInput(is_mouse_within_image_bounds, is_map_window_hovered);
491
492 if (is_mouse_within_image_bounds)
493 {
494 current_map_relative_mouse_pos = ImVec2(mouse_pos_global.x - image_min_screen_pos.x, mouse_pos_global.y - image_min_screen_pos.y);
495 float fbo_x = (current_map_relative_mouse_pos.x / displayed_image_size.x) * map_fbo->width;
496 float fbo_y = (current_map_relative_mouse_pos.y / displayed_image_size.y) * map_fbo->height;
497 current_fbo_mouse_pos = glm::vec2(fbo_x, fbo_y);
499
500 //DEBUG purposes
502 {
503 DrawDebugCircle(mouse_pos_global, false, IM_COL32(0, 255, 0, 150), 10.0f); // Yellow for raw click
504 DrawDebugCircle(image_min_screen_pos, false, IM_COL32(0, 255, 0, 255), 10.0f); // Yellow for image pos
505 DrawDebugCircle(ImVec2(image_min_screen_pos.x + current_fbo_mouse_pos.x, image_min_screen_pos.y + current_fbo_mouse_pos.y), false, IM_COL32(255, 0, 0, 255), 5.0f); // Red for raw click
506 }
507 }
508
509 ImGui::SetCursorScreenPos(image_min_screen_pos);
510 ImGui::InvisibleButton("##MapDropArea", displayed_image_size);
511 // Handle the drop payload
512 if (ImGui::BeginDragDropTarget())
513 {
514 if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("MARKER_IMAGE"))
515 {
516
517 const DirectoryWindow::ImageData* markerImage = (const DirectoryWindow::ImageData*)payload->Data;
518
519 glm::vec2 world_position = game_table_manager->board_manager->camera.screenToWorldPosition(current_fbo_mouse_pos);
520 game_table_manager->board_manager->createMarker(markerImage->filename, markerImage->textureID, world_position, markerImage->size);
521 }
522 ImGui::EndDragDropTarget();
523 }
524 }
525 }
526
527 ImGui::End();
528 }
529}
void DrawDebugCircle(ImVec2 coords, bool is_relative_to_window, ImU32 color, float radius=10.0f)
void ResizeMapFBO(int newWidth, int newHeight)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ renderDockSpace()

void ApplicationHandler::renderDockSpace ( )
private

Definition at line 404 of file ApplicationHandler.cpp.

405{
406 auto dockspace_id = ImGui::GetID("Root");
407 ImGuiViewport* viewport = ImGui::GetMainViewport();
408 if (g_dockspace_initialized == false)
409 {
411 ImGui::DockBuilderRemoveNode(dockspace_id);
412 ImGui::DockBuilderAddNode(dockspace_id, ImGuiDockNodeFlags_DockSpace | ImGuiDockNodeFlags_PassthruCentralNode);
413 ImGui::DockBuilderSetNodeSize(dockspace_id, viewport->Size);
414 ImGui::DockBuilderSetNodePos(dockspace_id, viewport->Pos);
415 ImGuiID dock_panel_id;
416 ImGuiID dock_right_id = ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Right, 0.3f, nullptr, &dock_panel_id);
417
418 ImGui::DockBuilderDockWindow("MapWindow", dock_panel_id);
419 ImGui::DockBuilderDockWindow("ChatWindow", dock_right_id);
420 ImGui::DockBuilderDockWindow("MarkerDiretory", dock_right_id);
421 ImGui::DockBuilderFinish(dockspace_id);
422 }
423
424 ImGuiWindowFlags root_flags = ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoFocusOnAppearing /*<<--TESTING BEHAVIOUR FLAGS--*/
425 | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoBringToFrontOnFocus;
426 ImGui::SetNextWindowPos({viewport->Pos.x, viewport->Pos.y + ImGui::GetFrameHeight()}, ImGuiCond_Always);
427 ImGui::SetNextWindowSize({viewport->Size.x, viewport->Size.y - ImGui::GetFrameHeight()}, ImGuiCond_Always); //TESTING WITHOUT ImGuiCond_Once
428 ImGui::Begin("RootWindow", nullptr, root_flags);
429 ImGui::DockSpace(dockspace_id);
430 ImGui::End();
431}
Here is the caller graph for this function:

◆ renderMainMenuBar()

void ApplicationHandler::renderMainMenuBar ( )
private

Definition at line 531 of file ApplicationHandler.cpp.

532{
533 // one-shot flags to open popups
534 bool open_host_gametable = false;
535 bool open_manage_gametable = false;
536 bool connect_to_gametable = false;
537 bool close_current_gametable = false;
538
539 bool open_network_center = false;
540 bool open_username_change = false;
541
542 bool open_create_board = false;
543 bool close_current_board = false;
544 bool load_active_board = false;
545
546 bool open_remove_assets = false;
547
548 bool about = false;
549 bool guide = false;
550
551 ImGui::BeginMainMenuBar();
552
553 // ---------------- Game Table ----------------
554 if (ImGui::BeginMenu("Game Table"))
555 {
556 if (ImGui::MenuItem("Host..."))
557 {
558 open_host_gametable = true;
559 }
560 if (ImGui::MenuItem("Connect..."))
561 {
562 connect_to_gametable = true;
563 }
564 if (ImGui::MenuItem("Manage..."))
565 {
566 open_manage_gametable = true;
567 }
568
569 if (game_table_manager->isGameTableActive() && game_table_manager->network_manager->getPeerRole() == Role::GAMEMASTER)
570 {
571 if (ImGui::MenuItem("Save"))
572 {
573 game_table_manager->saveGameTable();
574 }
575 if (ImGui::MenuItem("Close"))
576 {
577 close_current_gametable = true;
578 }
579 }
580 ImGui::EndMenu();
581 }
582 bool showNetwork = (game_table_manager->network_manager && game_table_manager->network_manager->getPeerRole() != Role::NONE);
583 // ---------------- Network ----------------
584 if (showNetwork)
585 {
586 if (ImGui::BeginMenu("Network"))
587 {
588 if (ImGui::MenuItem("Network Center"))
589 {
590 open_network_center = true;
591 }
592
593 if (ImGui::MenuItem("Change Username"))
594 {
595 open_username_change = true;
596 }
597 ImGui::EndMenu();
598 }
599 }
600
601 // ---------------- Board ----------------
602 if (game_table_manager->isGameTableActive())
603 {
604 if (ImGui::BeginMenu("Board"))
605 {
606 if (ImGui::MenuItem("Create"))
607 {
608 open_create_board = true;
609 }
610 if (ImGui::MenuItem("Open"))
611 {
612 load_active_board = true;
613 }
614 if (game_table_manager->board_manager->isBoardActive() && game_table_manager->network_manager->getPeerRole() == Role::GAMEMASTER)
615 {
616 if (ImGui::MenuItem("Save"))
617 {
618 auto board_folder_path = PathManager::getGameTablesPath() / game_table_manager->game_table_name / "Boards";
619 game_table_manager->board_manager->saveActiveBoard(board_folder_path);
620 }
621 if (ImGui::MenuItem("Close"))
622 {
623 close_current_board = true;
624 }
625 }
626
627 ImGui::EndMenu();
628 }
629 }
630 if (ImGui::BeginMenu("Notes"))
631 {
632 bool vis = note_editor_ui->isVisible();
633 if (ImGui::MenuItem("Note Editor", nullptr, vis))
634 {
635 note_editor_ui->setVisible(!vis);
636 }
637 ImGui::EndMenu();
638 }
639 if (ImGui::BeginMenu("Assets"))
640 {
641 if (ImGui::MenuItem("Add Marker (from file)"))
642 {
643 std::vector<std::filesystem::path> dst;
644 std::string err;
646 {
647 // toast/log error if needed
648 std::cerr << "Import marker failed: " << err << "\n";
649 toaster_->Push(ImGuiToaster::Level::Error, "Imported Marker ERROR: " + err);
650 }
651 else
652 {
653 toaster_->Push(ImGuiToaster::Level::Good, "Imported Marker Successfully!!" + err);
654 }
655 }
656 if (ImGui::MenuItem("Add Map (from file)"))
657 {
658 std::vector<std::filesystem::path> dst;
659 std::string err;
661 {
662 // toast/log error if needed
663 std::cerr << "Import map failed: " << err << "\n";
664 toaster_->Push(ImGuiToaster::Level::Error, "Imported Map ERROR: " + err);
665 }
666 else
667 {
668 toaster_->Push(ImGuiToaster::Level::Good, "Imported Map Successfully!! " + err);
669 }
670 }
671 if (ImGui::MenuItem("Remove Assets..."))
672 {
673 open_remove_assets = true;
674 }
675 ImGui::EndMenu();
676 }
677
678 if (ImGui::BeginMenu("Help"))
679 {
680 if (ImGui::MenuItem("Guide"))
681 {
682 guide = true;
683 }
684
685 if (ImGui::MenuItem("About"))
686 {
687 about = true;
688 }
689
690 bool vis = DebugConsole::isVisible();
691 if (ImGui::MenuItem("Console", nullptr, vis))
692 {
694 }
695
696 ImGui::EndMenu();
697 }
698
699 ImGui::EndMainMenuBar();
700
701 // ---------------- Popups (open + render) ----------------
702
703 if (open_remove_assets)
704 ImGui::OpenPopup("DeleteAssets");
705 if (ImGui::IsPopupOpen("DeleteAssets"))
707
708 if (open_host_gametable)
709 ImGui::OpenPopup("Host GameTable");
710 if (ImGui::IsPopupOpen("Host GameTable"))
711 game_table_manager->hostGameTablePopUp();
712
713 if (open_manage_gametable)
714 ImGui::OpenPopup("Manage GameTables");
715 if (ImGui::IsPopupOpen("Manage GameTables"))
716 game_table_manager->manageGameTablesPopUp();
717
718 if (connect_to_gametable)
719 ImGui::OpenPopup("ConnectToGameTable");
720 if (ImGui::IsPopupOpen("ConnectToGameTable"))
721 game_table_manager->connectToGameTablePopUp();
722
723 if (close_current_gametable)
724 ImGui::OpenPopup("CloseGameTable");
725 if (ImGui::IsPopupOpen("CloseGameTable"))
726 game_table_manager->closeGameTablePopUp();
727
728 if (open_network_center)
729 ImGui::OpenPopup("Network Center");
730 if (ImGui::IsPopupOpen("Network Center"))
731 game_table_manager->networkCenterPopUp();
732
733 if (open_username_change)
734 ImGui::OpenPopup("Change Username");
735 if (ImGui::IsPopupOpen("Change Username"))
736 game_table_manager->renderUsernameChangePopup();
737
738 if (open_create_board)
739 ImGui::OpenPopup("CreateBoard");
740 if (ImGui::IsPopupOpen("CreateBoard"))
741 game_table_manager->createBoardPopUp();
742
743 if (load_active_board)
744 ImGui::OpenPopup("LoadBoard");
745 if (ImGui::IsPopupOpen("LoadBoard"))
746 game_table_manager->loadBoardPopUp();
747
748 if (close_current_board)
749 ImGui::OpenPopup("CloseBoard");
750 if (ImGui::IsPopupOpen("CloseBoard"))
751 game_table_manager->closeBoardPopUp();
752
753 if (guide)
754 ImGui::OpenPopup("Guide");
755 if (ImGui::IsPopupOpen("Guide"))
756 game_table_manager->guidePopUp();
757
758 if (about)
759 ImGui::OpenPopup("About");
760 if (ImGui::IsPopupOpen("About"))
761 game_table_manager->aboutPopUp();
762}
@ GAMEMASTER
static bool isVisible()
static void setVisible(bool v)
void openDeleteAssetPopUp(std::weak_ptr< ImGuiToaster > toaster_)
Definition AssetIO.h:401
bool importManyFromPicker(AssetKind kind, std::vector< std::filesystem::path > *outDsts=nullptr, std::string *outError=nullptr)
Definition AssetIO.h:240
Here is the call graph for this function:
Here is the caller graph for this function:

◆ renderMapFBO()

void ApplicationHandler::renderMapFBO ( VertexArray & va,
IndexBuffer & ib,
Shader & shader,
Shader & grid_shader,
Renderer & renderer )
private

Definition at line 433 of file ApplicationHandler.cpp.

434{
435 if (map_fbo->fboID != 0 && map_fbo->width > 0 && map_fbo->height > 0)
436 {
437 GLCall(glBindFramebuffer(GL_FRAMEBUFFER, map_fbo->fboID));
438 GLCall(glViewport(0, 0, map_fbo->width, map_fbo->height)); // Crucial: Viewport matches FBO size
439 GLCall(glClearColor(0.0f, 0.0f, 0.0f, 0.0f)); // Clear FBO background
440 GLCall(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
441
442 // Inform the camera about the FBO's current dimensions for projection
443 game_table_manager->setCameraFboDimensions(glm::vec2(map_fbo->width, map_fbo->height));
444 game_table_manager->render(va, ib, shader, grid_shader, renderer); // Your board_manager->render() call
445
446 GLCall(glBindFramebuffer(GL_FRAMEBUFFER, 0)); // Unbind FBO, return to default framebuffer
447 }
448}
Here is the caller graph for this function:

◆ ResizeMapFBO()

void ApplicationHandler::ResizeMapFBO ( int newWidth,
int newHeight )
private

Definition at line 102 of file ApplicationHandler.cpp.

103{
104 if (map_fbo->width == newWidth && map_fbo->height == newHeight)
105 {
106 return; // No resize needed
107 }
108
109 if (newWidth <= 0 && newHeight <= 0)
110 {
111 // Prevent creating FBO with invalid sizes, might occur when window is minimized
112 if (map_fbo->fboID != 0)
113 DeleteMapFBO(); // Clean up if it exists
114 return;
115 }
116 // Only recreate if dimensions actually changed
117 if (map_fbo->width == newWidth && map_fbo->height == newHeight)
118 {
119 return;
120 }
121 CreateMapFBO(newWidth, newHeight); // Recreate FBO with new dimensions
122}
void CreateMapFBO(int width, int height)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ run()

int ApplicationHandler::run ( )

Definition at line 247 of file ApplicationHandler.cpp.

248{
249 /* Make the window's context current */
250 glfwMakeContextCurrent(window);
251 glfwSwapInterval(1);
252
253 glfwSetWindowUserPointer(window, &game_table_manager);
254 int minWidth = 1280; // AJUSTAR TAMANHOS, VERIFICAR TAMANHO MINIMO QUE NÂO QUEBRA O LAYOUT
255 int minHeight = 960;
256 glfwSetWindowSizeLimits(window, minWidth, minHeight, GLFW_DONT_CARE, GLFW_DONT_CARE);
257
258 // Force the window to maximize
259 glfwMaximizeWindow(window);
260
261 std::cout << glGetString(GL_VERSION) << std::endl;
262 { //Escopo para finalizar OPenGL antes GlFW
263 GLCall(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
264 GLCall(glEnable(GL_BLEND));
265 GLCall(glDisable(GL_DEPTH_TEST));
266
267 //float positions[] = {
268 // -1.0f, -1.0f, 0.0f, 0.0f,//0
269 // 1.0f, -1.0f, 1.0f, 0.0f,//1
270 // 1.0f, 1.0f, 1.0f, 1.0f,//2
271 // -1.0f, 1.0f, 0.0f, 1.0f //3
272 //};
273 float positions[] = {
274 0.5f, 0.5f, 1.0f, 1.0f, // top-right corner
275 0.5f, -0.5f, 1.0f, 0.0f, // bottom-right corner
276 -0.5f, -0.5f, 0.0f, 0.0f, // bottom-left corner
277 -0.5f, 0.5f, 0.0f, 1.0f // top-left corner
278 };
279
280 unsigned int indices[] = {
281 0, 1, 2,
282 2, 3, 0};
283
284 VertexArray va;
285 VertexBuffer vb(positions, 4 /*number of vertexes*/ * 4 /*floats per vertex*/ * sizeof(float));
286 VertexBufferLayout layout;
287
288 layout.Push<float>(2);
289 layout.Push<float>(2);
290 va.AddBuffer(vb, layout);
291
292 IndexBuffer ib(indices, 6);
293
294 glm::mat4 proj = glm::ortho(-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f);
295 glm::mat4 identity = glm::mat4(1.0f);
296
297 std::filesystem::path shader_path = PathManager::getShaderPath() / "Basic.shader";
298 std::filesystem::path grid_shader_path = PathManager::getShaderPath() / "GridShader.shader";
299 Shader shader(shader_path.string());
300 Shader grid_shader(grid_shader_path.string());
301
302 grid_shader.Bind();
303 grid_shader.SetUniformMat4f("projection", proj);
304 grid_shader.SetUniformMat4f("view", identity);
305 grid_shader.SetUniformMat4f("model", identity);
306 grid_shader.SetUniform1i("grid_type", 0);
307 grid_shader.SetUniform1f("cell_size", 1.0f);
308 grid_shader.SetUniform2f("grid_offset", 1.0f, 1.0f);
309 grid_shader.SetUniform1f("opacity", 1.0f);
310
311 shader.Bind();
312 shader.SetUniform1i("u_Texture", 0);
313 shader.SetUniformMat4f("projection", proj);
314 shader.SetUniformMat4f("view", identity);
315 shader.SetUniformMat4f("model", identity);
316 shader.SetUniform1i("u_UseTexture", 1);
317 shader.SetUniform1f("u_Alpha", 0.5f);
318
319 va.Unbind();
320 vb.Unbind();
321 ib.Unbind();
322 shader.Unbind();
323
324 Renderer renderer;
325
326 IMGUI_CHECKVERSION();
327 ImGui::CreateContext();
328 ImGuiIO& io = ImGui::GetIO();
329 (void)io;
330 io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
331 io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
332 io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
333 io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
334 //io.ConfigViewportsNoAutoMerge = true;
335 io.ConfigWindowsMoveFromTitleBarOnly = true;
336
337 // Setup Dear ImGui style
338 ImGui::StyleColorsDark();
339
340 ImGuiStyle& style = ImGui::GetStyle();
341 if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
342 {
343 style.WindowRounding = 0.0f;
344 style.Colors[ImGuiCol_WindowBg].w = 0.0f;
345 }
346 // Setup Platform/Renderer backends
347 const char* glsl_version = "#version 330 core";
348 ImGui_ImplGlfw_InitForOpenGL(window, true);
349 ImGui_ImplOpenGL3_Init();
350
351 /* Loop until the user closes the window */
352 while (!glfwWindowShouldClose(window))
353 {
354 /* Poll for and process events */
355 glfwPollEvents();
356 marker_directory->applyPendingAssetChanges();
357 map_directory->applyPendingAssetChanges();
358 game_table_manager->processReceivedMessages();
359 TickAutoSave();
360
361 /* Render here */
362 GLCall(glClearColor(0.0f, 0.0f, 0.0f, 1.0f));
363 GLCall(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
364
365 // Start the Dear ImGui frame
366 ImGui_ImplOpenGL3_NewFrame();
367 ImGui_ImplGlfw_NewFrame();
368 ImGui::NewFrame();
369
372
375 note_editor_ui->render();
376 renderMapFBO(va, ib, shader, grid_shader, renderer);
378 toaster_->Render();
379
380 //ImGui::ShowMetricsWindow();
381 ImGui::Render();
382 ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
383
384 if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
385 {
386 GLFWwindow* backup_current_context = glfwGetCurrentContext();
387 ImGui::UpdatePlatformWindows();
388 ImGui::RenderPlatformWindowsDefault();
389 glfwMakeContextCurrent(backup_current_context);
390 }
391 /* Swap front and back buffers */
392 glfwSwapBuffers(window);
393 }
394
395 map_directory->stopMonitoring();
396 marker_directory->stopMonitoring();
397 }
398
399 glfwDestroyWindow(window);
400 glfwTerminate();
401 return 0;
402}
void renderMapFBO(VertexArray &va, IndexBuffer &ib, Shader &shader, Shader &grid_shader, Renderer &renderer)
static void RunActiveDebugToggles()
static void Render()
static fs::path getShaderPath()
void Push(unsigned int count)
Here is the call graph for this function:

◆ TickAutoSave()

void ApplicationHandler::TickAutoSave ( )
private

Definition at line 145 of file ApplicationHandler.cpp.

146{
147 using clock = std::chrono::steady_clock;
148 static clock::time_point s_last = clock::now();
149
150 // Early-out if not time yet (every 60s)
151 constexpr auto kInterval = std::chrono::minutes(1);
152 const auto now = clock::now();
153 if (now - s_last < kInterval)
154 return;
155 s_last = now;
156 if (game_table_manager->network_manager)
157 {
158 if (game_table_manager->network_manager->getPeerRole() == Role::GAMEMASTER)
159 {
160
162 {
163 if (toaster_)
164 toaster_->Push(ImGuiToaster::Level::Warning, "Autosave skipped: GameTableManager missing", 4.0f);
165 return;
166 }
167
168 bool ok = true;
169 std::string err;
170
171 // 1) Save active GameTable (your method name as provided)
172 try
173 {
174 auto gametable_entity = game_table_manager->getActiveGameTableEntity();
175 if (gametable_entity.is_valid())
176 {
177 game_table_manager->saveGameTable(); // (or saveActiveGametable() if that's your actual name)
178 }
179 }
180 catch (const std::exception& e)
181 {
182 ok = false;
183 err += std::string("GameTable: ") + e.what();
184 }
185 catch (...)
186 {
187 ok = false;
188 err += "GameTable: unknown error";
189 }
190
191 // 2) Save active Board
192 try
193 {
194 if (game_table_manager->board_manager)
195 {
196 auto gametable_entity = game_table_manager->getActiveGameTableEntity();
197 if (gametable_entity.is_valid())
198 {
199 auto game_table_name = gametable_entity.get<GameTable>()->gameTableName;
200 auto board_dir_path = PathManager::getBoardsPath(game_table_name);
201 game_table_manager->board_manager->saveActiveBoard(board_dir_path);
202 }
203 }
204 else
205 {
206 ok = false;
207 if (!err.empty())
208 err += " | ";
209 err += "BoardManager missing";
210 }
211 }
212 catch (const std::exception& e)
213 {
214 ok = false;
215 if (!err.empty())
216 err += " | ";
217 err += std::string("Board: ") + e.what();
218 }
219 catch (...)
220 {
221 ok = false;
222 if (!err.empty())
223 err += " | ";
224 err += "Board: unknown error";
225 }
226
227 // Toast result
228 if (toaster_)
229 {
230 if (ok)
231 toaster_->Push(ImGuiToaster::Level::Good, "Autosave complete: GameTable & Board", 5.0f);
232 else
233 toaster_->Push(ImGuiToaster::Level::Error, std::string("Autosave failed: ") + err, 6.0f);
234 }
235 }
236 }
237 else
238 {
239 return;
240 }
241
242 // Sanity checks
243 // 3) Notes (not implemented) — left as-is
244 // notes_manager->saveOpenNotes();
245}
static fs::path getBoardsPath(std::string gametable_name)
Definition PathManager.h:81
Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ current_fbo_mouse_pos

glm::vec2 ApplicationHandler::current_fbo_mouse_pos = glm::vec2(0, 0)
private

Definition at line 93 of file ApplicationHandler.h.

◆ current_map_relative_mouse_pos

ImVec2 ApplicationHandler::current_map_relative_mouse_pos = ImVec2(0, 0)
private

Definition at line 94 of file ApplicationHandler.h.

◆ ecs

flecs::world ApplicationHandler::ecs
private

Definition at line 84 of file ApplicationHandler.h.

◆ g_dockspace_initialized

bool ApplicationHandler::g_dockspace_initialized = false
private

Definition at line 91 of file ApplicationHandler.h.

◆ g_draw_debug_circle

bool ApplicationHandler::g_draw_debug_circle = false
private

Definition at line 98 of file ApplicationHandler.h.

◆ game_table_manager

std::shared_ptr<GameTableManager> ApplicationHandler::game_table_manager
private

Definition at line 85 of file ApplicationHandler.h.

◆ map_directory

std::shared_ptr<DirectoryWindow> ApplicationHandler::map_directory
private

Definition at line 86 of file ApplicationHandler.h.

◆ map_fbo

std::shared_ptr<MapFBO> ApplicationHandler::map_fbo
private

Definition at line 82 of file ApplicationHandler.h.

◆ marker_directory

std::shared_ptr<DirectoryWindow> ApplicationHandler::marker_directory
private

Definition at line 87 of file ApplicationHandler.h.

◆ note_editor_ui

std::shared_ptr<NoteEditorUI> ApplicationHandler::note_editor_ui
private

Definition at line 89 of file ApplicationHandler.h.

◆ notes_manager

std::shared_ptr<NotesManager> ApplicationHandler::notes_manager
private

Definition at line 88 of file ApplicationHandler.h.

◆ toaster_

std::shared_ptr<ImGuiToaster> ApplicationHandler::toaster_
private

Definition at line 70 of file ApplicationHandler.h.

◆ window

GLFWwindow* ApplicationHandler::window
private

Definition at line 83 of file ApplicationHandler.h.


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