1717{
1718 ImVec2 center = ImGui::GetMainViewport()->GetCenter();
1719 ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
1720
1721 if (ImGui::BeginPopupModal("Guide", nullptr, ImGuiWindowFlags_AlwaysAutoResize))
1722 {
1723
1724 static int section = 0;
1725 static const char* kSections[] = {
1726 "Getting Started",
1727 "Connecting to a Game",
1728 "Game Tables",
1729 "Boards",
1730 "Toolbar & Interface",
1731 "Markers",
1732 "Fog of War",
1733 "Networking & Security",
1734 "Known Issues",
1735 "Appendix"};
1736
1737
1738 auto Para = [](const char* s)
1739 {
1740 ImGui::TextWrapped("%s", s);
1741 ImGui::Dummy(ImVec2(0, 4));
1742 };
1743
1744 ImGui::TextUnformatted("RunicVTT Guide");
1745 ImGui::Separator();
1746
1747
1748 ImVec2 full = ImVec2(860, 520);
1749 ImGui::BeginChild("GuideContent", full, true);
1750
1751
1752 ImGui::BeginChild("GuideNav", ImVec2(240, 0), true);
1753 for (int i = 0; i < IM_ARRAYSIZE(kSections); ++i)
1754 {
1755 if (ImGui::Selectable(kSections[i], section == i))
1756 section = i;
1757 }
1758 ImGui::EndChild();
1759
1760 ImGui::SameLine();
1761
1762
1763 ImGui::BeginChild("GuideBody", ImVec2(0, 0), true, ImGuiWindowFlags_AlwaysVerticalScrollbar);
1764
1765 switch (section)
1766 {
1767 case 0:
1768 {
1769 ImGui::SeparatorText("Overview");
1770 Para("RunicVTT is a virtual tabletop for sharing boards, markers, and fog of war in real-time across peers.");
1771
1772 ImGui::SeparatorText("Basic Flow");
1773 Para("Create or load a Game Table -> Host or Join -> Add a Board -> Place Markers / Fog -> Play.");
1774
1775 ImGui::SeparatorText("Requirements");
1776 Para("- Windows 10/11 recommended.\n"
1777 "- Internet connection for WAN.\n"
1778 "- Allow the app in your firewall/antivirus.\n"
1779 "- Read/write access for assets (Boards/Markers folders).");
1780
1781 ImGui::SeparatorText("Terminology");
1782 Para("- Game Table: a saved session containing chat and world state.\n"
1783 "- Board: a map image displayed to all players.\n"
1784 "- Marker: a token/object placed on a board.\n"
1785 "- Fog: an overlay hiding/revealing areas.\n"
1786 "- Peer: a connected client (GM or Player).");
1787 break;
1788 }
1789
1790 case 1:
1791 {
1792 ImGui::SeparatorText("Connection String");
1793 Para("A connection string identifies the host session. Example formats:\n"
1794 "- https://runic-<yourLocalIp>.loca.lt?PASSWORD\n"
1795 "- runic:<host>:<port>?PASSWORD");
1796
1797 ImGui::SeparatorText("Hosting");
1798 Para("Choose a connection mode: LocalTunnel (public URL), Local (LAN), or External (WAN with port forwarding). "
1799 "Start hosting and copy the connection string from the Network Center.");
1800
1801 ImGui::SeparatorText("Joining");
1802 Para("Ask the host for a connection string and password, then use 'Connect to GameTable' and paste it.");
1803
1804 ImGui::SeparatorText("Troubleshooting");
1805 Para("- If connection closes over WAN: ensure firewall allows the app, port was fowarded manually or via UPnP and the host is reachable. \n"
1806 "- If connection closes over LAN: ensure firewall allows the app, and the moldem dont block local connections. \n"
1807 "- If connection closes over LocalTunnel: ensure firewall allows the app, and the generated URL is in the correct format https://runic-<YOURLOCALIP>.loca.lt. if not in the formar generate new by hosting again \n"
1808 "- Make sure you are connected to a Wifi or Ethernet moldem connection, 4G/5G mobile network arent supported due to their complex NAT protection. \n"
1809 "- Corporate networks or strict NAT may require TURN/relay.");
1810 break;
1811 }
1812
1813 case 2:
1814 {
1815 ImGui::SeparatorText("Create a Game Table");
1816 Para("Open 'Host GameTable' -> Create tab -> set name/username/password/port -> choose mode -> Host.");
1817
1818 ImGui::SeparatorText("Load a Game Table");
1819 Para("Open 'Host GameTable' -> Load tab -> select a saved table -> set credentials/port -> Host.");
1820
1821 ImGui::SeparatorText("Lifecycle");
1822 Para("Networking is tied to the Game Table. Closing it stops all connections. "
1823 "Chat and boards are saved per table.");
1824 break;
1825 }
1826
1827 case 3:
1828 {
1829 ImGui::SeparatorText("Create a Board");
1830 Para("Use 'Add Board' or board toolbar -> choose an image (PNG/JPG). The image is shared to peers.");
1831
1832 ImGui::SeparatorText("Edit Board");
1833 Para("Adjust size/scale, toggle grid, panning/zoom. Visibility affects whether players see it fully.");
1834
1835 ImGui::SeparatorText("Networking Notes");
1836 Para("Large images are chunked and sent reliably. Very large files transfer but take longer.");
1837 break;
1838 }
1839
1840 case 4:
1841 {
1842 ImGui::SeparatorText("Toolbar Overview");
1843 Para("- Move Tool: pan map or drag owned markers.\n"
1844 "- Fog Tool: create fog areas.\n"
1845 "- Edit/Delete: open edit window or remove entities.\n"
1846 "- Zoom/Pan: mouse wheel and drag (when panning).\n"
1847 "- Grid: open grid window to configure it.\n"
1848 "- Camera: open camera window to configure it.\n");
1849
1850 ImGui::SeparatorText("Windows & Panels");
1851 Para("- Chat Window: General chat + dice roller (/roll).\n"
1852 "- Edit Window: per-entity size/visibility/ownership.\n"
1853 "- Grid Window: per-board grid cell size/offset/visibility/snap to grid.\n"
1854 "- Camera Window: per-board camera zoom via button and sliders and reset.\n"
1855 "- Host Window: create or load gametable with credentials and port, start network and sets active gametable.\n"
1856 "- Connect Window: connect to hosted gametable, connection string and credential.\n"
1857 "- Network Center: peers, connection strings, status.");
1858
1859 break;
1860 }
1861
1862 case 5:
1863 {
1864 ImGui::SeparatorText("Create Fog");
1865 Para("Use the Fog tool to add opaque overlays to hide areas from players.");
1866
1867 ImGui::SeparatorText("Edit/Remove");
1868 Para("Move/resize fog areas or delete them. Fog updates are synchronized to all peers.");
1869
1870 ImGui::SeparatorText("Authority");
1871 Para("Fog is GM-controlled; players do not send fog updates.");
1872 break;
1873 }
1874
1875 case 6:
1876 {
1877 ImGui::SeparatorText("Create Markers");
1878 Para("Use the Marker directory to place tokens. Drag markers to the board from the Markers directory window.");
1879
1880 ImGui::SeparatorText("Edit & Ownership");
1881 Para("Edit window lets the GM set: owner peer ID, allow-all-players move, and locked state. \n"
1882 "Players can only move owned/unlocked markers; the GM can always move.");
1883
1884 ImGui::SeparatorText("Movement");
1885 Para("Drag markers to move. Updates are broadcast at a limited rate to reduce spam.");
1886 break;
1887 }
1888
1889 case 7:
1890 {
1891 ImGui::SeparatorText("How It Works");
1892 Para("Peer-to-peer data channels synchronize boards, markers, fog, and chat.");
1893
1894 ImGui::SeparatorText("Firewall / Antivirus");
1895 Para("Allow the executable on first run. Some AVs may slow initial connection.");
1896
1897 ImGui::SeparatorText("Quality & Reliability");
1898 Para("Images are sent on reliable channels.");
1899 break;
1900 }
1901
1902 case 8:
1903 {
1904 ImGui::SeparatorText("Limitations");
1905 Para("- Very large images transfer slowly.\n"
1906 "- Network Over the 4G/5G doesnt work due to NAT restrictions. \n"
1907 "- Network do not work on Mobile Internet of any form(USB Anchoring, Wifi Hotspot, Ethernet and Bluetooth). ");
1908
1909 ImGui::SeparatorText("Troubleshooting");
1910 Para("If desync occurs, rejoin the session or have the host re-broadcast state via Game Table snapshot.");
1911
1912 ImGui::SeparatorText("Reporting Bugs");
1913 Para("Collect logs from the log window/folder and describe steps to reproduce.");
1914 break;
1915 }
1916
1917 case 9:
1918 {
1919 ImGui::SeparatorText("File Paths");
1920 Para("- GameTables folder: <root path>/GameTables/ \n"
1921 "- Boards folder: <GameTableFolder>/<GameTableName>/Boards/ \n"
1922 "- Maps folder: <root path>/Maps/ \n"
1923 "- Marker folder: <root path>/Marker/.");
1924
1925 ImGui::SeparatorText("Glossary");
1926 Para("- GM: Game Master (host/authority).\n"
1927 "- Player: peer participant.\n"
1928 "- Peer: a connected client.");
1929
1930 break;
1931 }
1932 }
1933
1934 ImGui::EndChild();
1935 ImGui::EndChild();
1936
1937 ImGui::Separator();
1938 if (ImGui::Button("Close"))
1939 ImGui::CloseCurrentPopup();
1940
1941 ImGui::EndPopup();
1942 }
1943}