├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ ├── msbuild_vs2022_dev.yml │ └── msbuild_vs2022_main.yml ├── .gitignore ├── Build ├── GenerateCompatibilityTest.bat ├── Sharpmake │ ├── Basic.Reference.Assemblies.Net50.dll │ ├── Microsoft.CodeAnalysis.CSharp.dll │ ├── Microsoft.CodeAnalysis.dll │ ├── Microsoft.VisualStudio.Setup.Configuration.Interop.dll │ ├── Sharpmake.Application │ ├── Sharpmake.Application.deps.json │ ├── Sharpmake.Application.dll │ ├── Sharpmake.Application.dll.config │ ├── Sharpmake.Application.exe │ ├── Sharpmake.Application.runtimeconfig.dev.json │ ├── Sharpmake.Application.runtimeconfig.json │ ├── Sharpmake.CommonPlatforms.deps.json │ ├── Sharpmake.CommonPlatforms.dll │ ├── Sharpmake.CommonPlatforms.xml │ ├── Sharpmake.Generators.deps.json │ ├── Sharpmake.Generators.dll │ ├── Sharpmake.Generators.xml │ ├── Sharpmake.deps.json │ ├── Sharpmake.dll │ └── Sharpmake.xml ├── compatibility.sharpmake.cs.1 ├── compatibility.sharpmake.cs.2 ├── compatibility.sharpmake.cs.3 ├── netImgui.sharpmake.cs ├── nocompatibility.sharpmake.cs ├── readme.txt ├── shared.sharpmake.cs └── shared.sharpmake_mac.cs ├── Clean.bat ├── Code ├── Client │ ├── NetImgui_Api.h │ ├── NetImgui_Config.h │ └── Private │ │ ├── NetImgui_Api.cpp │ │ ├── NetImgui_Client.cpp │ │ ├── NetImgui_Client.h │ │ ├── NetImgui_Client.inl │ │ ├── NetImgui_CmdPackets.h │ │ ├── NetImgui_CmdPackets.inl │ │ ├── NetImgui_CmdPackets_DrawFrame.cpp │ │ ├── NetImgui_CmdPackets_DrawFrame.h │ │ ├── NetImgui_Network.h │ │ ├── NetImgui_NetworkPosix.cpp │ │ ├── NetImgui_NetworkUE4.cpp │ │ ├── NetImgui_NetworkWin32.cpp │ │ ├── NetImgui_Shared.h │ │ ├── NetImgui_Shared.inl │ │ ├── NetImgui_WarningDisable.h │ │ ├── NetImgui_WarningDisableImgui.h │ │ ├── NetImgui_WarningDisableStd.h │ │ └── NetImgui_WarningReenable.h ├── Sample │ ├── Common │ │ ├── Sample.cpp │ │ ├── Sample.h │ │ └── main.cpp │ ├── SampleBackground │ │ └── SampleBackground.cpp │ ├── SampleBasic │ │ └── SampleBasic.cpp │ ├── SampleCompression │ │ ├── SampleCompression.cpp │ │ └── SampleNetworkWin32.cpp │ ├── SampleDisabled │ │ └── SampleDisabled.cpp │ ├── SampleDualUI │ │ └── SampleDualUI.cpp │ ├── SampleFontDPI │ │ └── SampleFontDPI.cpp │ ├── SampleIndex │ │ └── SampleIndex.cpp │ ├── SampleNewFrame │ │ └── SampleNewFrame.cpp │ ├── SampleNoBackend │ │ └── SampleNoBackend.cpp │ ├── SampleSingleInclude │ │ └── SampleSingleInclude.cpp │ └── SampleTextures │ │ └── SampleTextures.cpp ├── ServerApp │ ├── Background.png │ ├── Source │ │ ├── Custom │ │ │ └── NetImguiServer_App_Custom.cpp │ │ ├── Fonts │ │ │ └── Roboto_Medium.cpp │ │ ├── GlfwGL3 │ │ │ ├── NetImguiServer_App_GlfwGL3.cpp │ │ │ ├── NetImguiServer_HAL_GL3.cpp │ │ │ └── NetImguiServer_HAL_Glfw.cpp │ │ ├── NetImguiServer_App.cpp │ │ ├── NetImguiServer_App.h │ │ ├── NetImguiServer_Config.cpp │ │ ├── NetImguiServer_Config.h │ │ ├── NetImguiServer_Network.cpp │ │ ├── NetImguiServer_Network.h │ │ ├── NetImguiServer_RemoteClient.cpp │ │ ├── NetImguiServer_RemoteClient.h │ │ ├── NetImguiServer_UI.cpp │ │ ├── NetImguiServer_UI.h │ │ ├── Sokol │ │ │ ├── NetImguiServer_App_Sokol.cpp │ │ │ ├── NetImguiServer_HAL_SokolApp.cpp │ │ │ ├── NetImguiServer_HAL_SokolGfx.cpp │ │ │ └── sokol │ │ │ │ ├── sokol_app.h │ │ │ │ ├── sokol_gfx.h │ │ │ │ ├── sokol_glue.h │ │ │ │ ├── sokol_log.h │ │ │ │ └── util │ │ │ │ └── sokol_imgui.h │ │ └── Win32DX11 │ │ │ ├── NetImguiServer_App_win32dx11.cpp │ │ │ ├── NetImguiServer_HAL_dx11.cpp │ │ │ └── NetImguiServer_HAL_win32.cpp │ ├── info.plist │ ├── netImguiApp.ico │ ├── netImguiApp.rc │ ├── resource.h │ ├── small.ico │ └── targetver.h └── ThirdParty │ ├── DearImgui │ ├── .editorconfig │ ├── .gitattributes │ ├── .gitignore │ ├── LICENSE.txt │ ├── backends │ │ ├── imgui_impl_dx11.cpp │ │ ├── imgui_impl_dx11.h │ │ ├── imgui_impl_glfw.cpp │ │ ├── imgui_impl_glfw.h │ │ ├── imgui_impl_opengl3.cpp │ │ ├── imgui_impl_opengl3.h │ │ ├── imgui_impl_opengl3_loader.h │ │ ├── imgui_impl_win32.cpp │ │ └── imgui_impl_win32.h │ ├── imconfig.h │ ├── imgui.cpp │ ├── imgui.h │ ├── imgui_demo.cpp │ ├── imgui_draw.cpp │ ├── imgui_internal.h │ ├── imgui_tables.cpp │ ├── imgui_widgets.cpp │ ├── imstb_rectpack.h │ ├── imstb_textedit.h │ └── imstb_truetype.h │ ├── glfw │ ├── COPYING.txt │ ├── include │ │ └── GLFW │ │ │ ├── glfw3.h │ │ │ └── glfw3native.h │ ├── lib-macos-universal │ │ ├── libglfw.3.dylib │ │ └── libglfw3.a │ ├── lib-vc2017-64 │ │ └── glfw3_mt.lib │ ├── lib-vc2019-32 │ │ ├── glfw3_mt.lib │ │ └── glfw3_mtd.lib │ ├── lib-vc2019-64 │ │ ├── glfw3_mt.lib │ │ └── glfw3_mtd.lib │ ├── lib-vc2022-32 │ │ ├── glfw3_mt.lib │ │ └── glfw3_mtd.lib │ └── lib-vc2022-64 │ │ ├── glfw3_mt.lib │ │ └── glfw3_mtd.lib │ ├── nlohmann_json │ └── json.hpp │ ├── quicklz.cpp │ ├── quicklz.h │ └── stb_image.h ├── GenerateProject.bat ├── GenerateProject.sh ├── LICENSE.txt └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/msbuild_vs2022_dev.yml: -------------------------------------------------------------------------------- 1 | # Using 2 similars yml files, to get unique name displayed in build tag 2 | # (Can't seem to use variable object to retrieve branch name when setting action name) 3 | name: (Build VS2022 Dev) 4 | 5 | on: 6 | push: 7 | branches: [ "dev" ] 8 | pull_request: 9 | branches: [ "dev" ] 10 | 11 | env: 12 | # Path to the solution file relative to the root of the project. 13 | SOLUTION_FILE_PATH: ./_projects/vs2022_netImgui_All.sln 14 | 15 | # Configuration type to build. 16 | # You can convert this to a build matrix if you need coverage of multiple configuration types. 17 | # https://docs.github.com/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix 18 | BUILD_CONFIGURATION: MSBuild_Release 19 | 20 | permissions: 21 | contents: read 22 | 23 | jobs: 24 | build: 25 | runs-on: windows-latest 26 | 27 | steps: 28 | - uses: actions/checkout@v3 29 | 30 | - name: Add MSBuild to PATH 31 | uses: microsoft/setup-msbuild@v1.1 32 | 33 | - name: Setup dotnet 34 | uses: actions/setup-dotnet@v1 35 | with: 36 | dotnet-version: '5.0.408' 37 | 38 | - name: Generate Solutions 39 | working-directory: ${{env.GITHUB_WORKSPACE}} 40 | run: ./GenerateProject.bat 1 41 | 42 | - name: Restore NuGet packages 43 | working-directory: ${{env.GITHUB_WORKSPACE}} 44 | run: nuget restore ${{env.SOLUTION_FILE_PATH}} 45 | 46 | - name: Build 47 | working-directory: ${{env.GITHUB_WORKSPACE}} 48 | # Add additional options to the MSBuild command line here (like platform or verbosity level). 49 | # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference 50 | run: msbuild /m /p:Configuration=${{env.BUILD_CONFIGURATION}} ${{env.SOLUTION_FILE_PATH}} 51 | -------------------------------------------------------------------------------- /.github/workflows/msbuild_vs2022_main.yml: -------------------------------------------------------------------------------- 1 | # Using 2 similars yml files, to get unique name displayed in build tag 2 | # (Can't seem to use variable object to retrieve branch name when setting action name) 3 | name: (Build VS2022 Main) 4 | 5 | on: 6 | push: 7 | branches: [ "master" ] 8 | pull_request: 9 | branches: [ "master" ] 10 | 11 | env: 12 | # Path to the solution file relative to the root of the project. 13 | SOLUTION_FILE_PATH: ./_projects/vs2022_netImgui_All.sln 14 | 15 | # Configuration type to build. 16 | # You can convert this to a build matrix if you need coverage of multiple configuration types. 17 | # https://docs.github.com/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix 18 | BUILD_CONFIGURATION: MSBuild_Release 19 | 20 | permissions: 21 | contents: read 22 | 23 | jobs: 24 | build: 25 | runs-on: windows-latest 26 | 27 | steps: 28 | - uses: actions/checkout@v3 29 | 30 | - name: Add MSBuild to PATH 31 | uses: microsoft/setup-msbuild@v1.1 32 | 33 | - name: Setup dotnet 34 | uses: actions/setup-dotnet@v1 35 | with: 36 | dotnet-version: '5.0.408' # Check for latest at link at .NET 5 download page 37 | 38 | - name: Generate Solutions 39 | working-directory: ${{env.GITHUB_WORKSPACE}} 40 | run: ./GenerateProject.bat 1 41 | 42 | - name: Restore NuGet packages 43 | working-directory: ${{env.GITHUB_WORKSPACE}} 44 | run: nuget restore ${{env.SOLUTION_FILE_PATH}} 45 | 46 | - name: Build 47 | working-directory: ${{env.GITHUB_WORKSPACE}} 48 | # Add additional options to the MSBuild command line here (like platform or verbosity level). 49 | # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference 50 | run: msbuild /m /p:Configuration=${{env.BUILD_CONFIGURATION}} ${{env.SOLUTION_FILE_PATH}} 51 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | _*/ 25 | 26 | # Visual Studio 2015 cache/options directory 27 | .vs/ 28 | # Uncomment if you have tasks that create the project's static files in wwwroot 29 | #wwwroot/ 30 | 31 | # MSTest test Results 32 | [Tt]est[Rr]esult*/ 33 | [Bb]uild[Ll]og.* 34 | 35 | # NUNIT 36 | *.VisualState.xml 37 | TestResult.xml 38 | 39 | # Build Results of an ATL Project 40 | [Dd]ebugPS/ 41 | [Rr]eleasePS/ 42 | dlldata.c 43 | 44 | # DNX 45 | project.lock.json 46 | project.fragment.lock.json 47 | artifacts/ 48 | 49 | *_i.c 50 | *_p.c 51 | *_i.h 52 | *.ilk 53 | *.meta 54 | *.obj 55 | *.pch 56 | *.pdb 57 | *.pgc 58 | *.pgd 59 | *.rsp 60 | *.sbr 61 | *.tlb 62 | *.tli 63 | *.tlh 64 | *.tmp 65 | *.tmp_proj 66 | *.log 67 | *.vspscc 68 | *.vssscc 69 | .builds 70 | *.pidb 71 | *.svclog 72 | *.scc 73 | 74 | # Chutzpah Test files 75 | _Chutzpah* 76 | 77 | # Visual C++ cache files 78 | ipch/ 79 | *.aps 80 | *.ncb 81 | *.opendb 82 | *.opensdf 83 | *.sdf 84 | *.cachefile 85 | *.VC.db 86 | *.VC.VC.opendb 87 | 88 | # Visual Studio profiler 89 | *.psess 90 | *.vsp 91 | *.vspx 92 | *.sap 93 | 94 | # TFS 2012 Local Workspace 95 | $tf/ 96 | 97 | # Guidance Automation Toolkit 98 | *.gpState 99 | 100 | # ReSharper is a .NET coding add-in 101 | _ReSharper*/ 102 | *.[Rr]e[Ss]harper 103 | *.DotSettings.user 104 | 105 | # JustCode is a .NET coding add-in 106 | .JustCode 107 | 108 | # TeamCity is a build add-in 109 | _TeamCity* 110 | 111 | # DotCover is a Code Coverage Tool 112 | *.dotCover 113 | 114 | # NCrunch 115 | _NCrunch_* 116 | .*crunch*.local.xml 117 | nCrunchTemp_* 118 | 119 | # MightyMoose 120 | *.mm.* 121 | AutoTest.Net/ 122 | 123 | # Web workbench (sass) 124 | .sass-cache/ 125 | 126 | # Installshield output folder 127 | [Ee]xpress/ 128 | 129 | # DocProject is a documentation generator add-in 130 | DocProject/buildhelp/ 131 | DocProject/Help/*.HxT 132 | DocProject/Help/*.HxC 133 | DocProject/Help/*.hhc 134 | DocProject/Help/*.hhk 135 | DocProject/Help/*.hhp 136 | DocProject/Help/Html2 137 | DocProject/Help/html 138 | 139 | # Click-Once directory 140 | publish/ 141 | 142 | # Publish Web Output 143 | *.[Pp]ublish.xml 144 | *.azurePubxml 145 | # TODO: Comment the next line if you want to checkin your web deploy settings 146 | # but database connection strings (with potential passwords) will be unencrypted 147 | #*.pubxml 148 | *.publishproj 149 | 150 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 151 | # checkin your Azure Web App publish settings, but sensitive information contained 152 | # in these scripts will be unencrypted 153 | PublishScripts/ 154 | 155 | # NuGet Packages 156 | *.nupkg 157 | # The packages folder can be ignored because of Package Restore 158 | **/packages/* 159 | # except build/, which is used as an MSBuild target. 160 | !**/packages/build/ 161 | # Uncomment if necessary however generally it will be regenerated when needed 162 | #!**/packages/repositories.config 163 | # NuGet v3's project.json files produces more ignoreable files 164 | *.nuget.props 165 | *.nuget.targets 166 | 167 | # Microsoft Azure Build Output 168 | csx/ 169 | *.build.csdef 170 | 171 | # Microsoft Azure Emulator 172 | ecf/ 173 | rcf/ 174 | 175 | # Windows Store app package directories and files 176 | AppPackages/ 177 | BundleArtifacts/ 178 | Package.StoreAssociation.xml 179 | _pkginfo.txt 180 | 181 | # Visual Studio cache files 182 | # files ending in .cache can be ignored 183 | *.[Cc]ache 184 | # but keep track of directories ending in .cache 185 | !*.[Cc]ache/ 186 | 187 | # Others 188 | ClientBin/ 189 | ~$* 190 | *~ 191 | *.dbmdl 192 | *.dbproj.schemaview 193 | *.jfm 194 | *.pfx 195 | *.publishsettings 196 | node_modules/ 197 | orleans.codegen.cs 198 | 199 | # Since there are multiple workflows, uncomment next line to ignore bower_components 200 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 201 | #bower_components/ 202 | 203 | # RIA/Silverlight projects 204 | Generated_Code/ 205 | 206 | # Backup & report files from converting an old project file 207 | # to a newer Visual Studio version. Backup files are not needed, 208 | # because we have git ;-) 209 | _UpgradeReport_Files/ 210 | Backup*/ 211 | UpgradeLog*.XML 212 | UpgradeLog*.htm 213 | 214 | # SQL Server files 215 | *.mdf 216 | *.ldf 217 | 218 | # Business Intelligence projects 219 | *.rdl.data 220 | *.bim.layout 221 | *.bim_*.settings 222 | 223 | # Microsoft Fakes 224 | FakesAssemblies/ 225 | 226 | # GhostDoc plugin setting file 227 | *.GhostDoc.xml 228 | 229 | # Node.js Tools for Visual Studio 230 | .ntvs_analysis.dat 231 | 232 | # Visual Studio 6 build log 233 | *.plg 234 | 235 | # Visual Studio 6 workspace options file 236 | *.opt 237 | 238 | # Visual Studio LightSwitch build output 239 | **/*.HTMLClient/GeneratedArtifacts 240 | **/*.DesktopClient/GeneratedArtifacts 241 | **/*.DesktopClient/ModelManifest.xml 242 | **/*.Server/GeneratedArtifacts 243 | **/*.Server/ModelManifest.xml 244 | _Pvt_Extensions 245 | 246 | # Paket dependency manager 247 | .paket/paket.exe 248 | paket-files/ 249 | 250 | # FAKE - F# Make 251 | .fake/ 252 | 253 | # JetBrains Rider 254 | .idea/ 255 | *.sln.iml 256 | 257 | # CodeRush 258 | .cr/ 259 | 260 | # Python Tools for Visual Studio (PTVS) 261 | __pycache__/ 262 | *.pyc 263 | Web/raw/InputWithNetImgui.xcf 264 | Web/raw/HowItWorks.svg 265 | Web/raw/AppWithoutNetImgui.xcf 266 | Web/raw/AppWithNetImgui.xcf 267 | -------------------------------------------------------------------------------- /Build/GenerateCompatibilityTest.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | setlocal enabledelayedexpansion 3 | cls 4 | pushd %~dp0 5 | 6 | ::----------------------------------------------------------------------------------- 7 | :: SETTINGS 8 | ::----------------------------------------------------------------------------------- 9 | :: List of offical Dear ImGui (from official depot) 10 | set VERSIONS=(v1.71 v1.72 v1.73 v1.74 v1.75 v1.76 v1.77 v1.78 v1.79, v1.80, v1.81, v1.82, v1.83, v1.84, v1.85, v1.86, v1.87, v1.88, v1.89.1, v1.89.2, v1.89.3, v1.89.4, v1.89.5, v1.89.6, v1.89.7, v1.89.7-docking, v1.89.8, v1.89.8-docking, v1.89.9, v1.89.9-docking, v1.90, v1.90-docking, v1.90.1, v1.90.2, v1.90.3, v1.90.4, v1.90.5, v1.90.6, v1.90.6-docking, v1.90.7, v1.90.8, v1.90.9, v1.91.0, v1.91.0-docking, v1.91.1, v1.91.2, v1.91.3, v1.91.4, v1.91.5, v1.91.5-docking) 11 | 12 | :: List of custom Dear ImGui releases (from own depot) 13 | set EXTRA_VERSIONS=(dock-1-76, dock-1-80, dock-1-89) 14 | 15 | :: Output directory 16 | set IMGUI_DIR=%~dp0..\_generated\imgui 17 | 18 | :: Destination of Compatibility project config file 19 | set COMPAT_FILE=%IMGUI_DIR%\compatibility.sharpmake.cs 20 | 21 | :: goto SkipDownload 22 | 23 | :GetAllImgui 24 | echo ================================================================================ 25 | echo Download multiple versions of Dear Imgui. 26 | echo Unpack them and generates netImgui projects for each. 27 | echo Used to test compatibility against multiple version of Dear ImGui 28 | echo ================================================================================ 29 | echo. 30 | 31 | :: Only download new release 32 | 33 | :: if not exist %IMGUI_DIR% goto SkipDelete 34 | :: echo. 35 | :: echo -------------------------------------------------------------------------------- 36 | :: echo Clearing Releases 37 | :: echo -------------------------------------------------------------------------------- 38 | :: echo Removing: %IMGUI_DIR% 39 | :: rmdir /s /q %IMGUI_DIR% 40 | 41 | 42 | :SkipDelete 43 | if not exist %IMGUI_DIR% ( 44 | mkdir %IMGUI_DIR% 45 | ) 46 | 47 | echo. 48 | echo -------------------------------------------------------------------------------- 49 | echo Downloading and extracting Dear ImGui Releases 50 | echo -------------------------------------------------------------------------------- 51 | pushd %IMGUI_DIR% 52 | 53 | for %%v in %VERSIONS% do ( 54 | echo Extracting: %%v 55 | set IMGUI_FILE=%%v.tar.gz 56 | set IMGUI_FILEPATH="https://github.com/ocornut/imgui/archive/!IMGUI_FILE!" 57 | if not exist !IMGUI_FILE! curl -LJ !IMGUI_FILEPATH! --output !IMGUI_FILE! 58 | tar -xzf !IMGUI_FILE! 59 | ) 60 | 61 | for %%v in %EXTRA_VERSIONS% do ( 62 | echo Extracting: %%v 63 | set IMGUI_FILE=%%v.zip 64 | set IMGUI_FILEPATH="https://raw.githubusercontent.com/wiki/sammyfreg/netImgui/ImguiVersions/!IMGUI_FILE!" 65 | if not exist !IMGUI_FILE! curl -LJ !IMGUI_FILEPATH! --output !IMGUI_FILE! 66 | tar -xzf !IMGUI_FILE! 67 | ) 68 | popd 69 | 70 | :SkipDownload 71 | echo. 72 | echo -------------------------------------------------------------------------------- 73 | echo Generating Sharpmake config for compatibility projects 74 | echo -------------------------------------------------------------------------------- 75 | type compatibility.sharpmake.cs.1 > %COMPAT_FILE% 76 | :: Declare each compatibility project (1 per Imgui version) 77 | for /D %%d IN (%IMGUI_DIR%\*) DO ( 78 | call :GenerateProjectName %%d 79 | echo [Sharpmake.Generate] public class !NetImguiName! : ProjectNoBackend { public !NetImguiName!^(^): base^("!NetImguiName!", @"%%d"^){} } >> %COMPAT_FILE% 80 | ) 81 | 82 | type compatibility.sharpmake.cs.2 >> %COMPAT_FILE% 83 | :: Create function adding each project 84 | for /D %%d IN (%IMGUI_DIR%\*) DO ( 85 | call :GenerateProjectName %%d 86 | echo conf.AddProject^^(target, false, SolutionFolder^); >> %COMPAT_FILE% 87 | echo !NetImguiName! added 88 | ) 89 | type compatibility.sharpmake.cs.3 >> %COMPAT_FILE% 90 | 91 | echo. 92 | echo -------------------------------------------------------------------------------- 93 | echo Dear ImGui Older versions fetched 94 | echo Please regenerate the projects to have them included in compiling tests 95 | echo -------------------------------------------------------------------------------- 96 | pause 97 | 98 | popd 99 | exit /b %errorlevel% 100 | 101 | :: Take a Imgui install path, and make it into a NetImgui project name 102 | :: By keeping only the last directory name and removing '-' and '.' 103 | :GenerateProjectName 104 | set NetImguiName=%~nx1 105 | set NetImguiName=%NetImguiName:-=_% 106 | set NetImguiName=%NetImguiName:.=_% 107 | set NetImguiName=ProjectCompatibility_%NetImguiName% 108 | exit /b 0 109 | 110 | 111 | -------------------------------------------------------------------------------- /Build/Sharpmake/Basic.Reference.Assemblies.Net50.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sammyfreg/netImgui/47e7bf9059a5d551521cbaff61ea6bab902f7fcb/Build/Sharpmake/Basic.Reference.Assemblies.Net50.dll -------------------------------------------------------------------------------- /Build/Sharpmake/Microsoft.CodeAnalysis.CSharp.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sammyfreg/netImgui/47e7bf9059a5d551521cbaff61ea6bab902f7fcb/Build/Sharpmake/Microsoft.CodeAnalysis.CSharp.dll -------------------------------------------------------------------------------- /Build/Sharpmake/Microsoft.CodeAnalysis.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sammyfreg/netImgui/47e7bf9059a5d551521cbaff61ea6bab902f7fcb/Build/Sharpmake/Microsoft.CodeAnalysis.dll -------------------------------------------------------------------------------- /Build/Sharpmake/Microsoft.VisualStudio.Setup.Configuration.Interop.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sammyfreg/netImgui/47e7bf9059a5d551521cbaff61ea6bab902f7fcb/Build/Sharpmake/Microsoft.VisualStudio.Setup.Configuration.Interop.dll -------------------------------------------------------------------------------- /Build/Sharpmake/Sharpmake.Application: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sammyfreg/netImgui/47e7bf9059a5d551521cbaff61ea6bab902f7fcb/Build/Sharpmake/Sharpmake.Application -------------------------------------------------------------------------------- /Build/Sharpmake/Sharpmake.Application.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sammyfreg/netImgui/47e7bf9059a5d551521cbaff61ea6bab902f7fcb/Build/Sharpmake/Sharpmake.Application.dll -------------------------------------------------------------------------------- /Build/Sharpmake/Sharpmake.Application.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sammyfreg/netImgui/47e7bf9059a5d551521cbaff61ea6bab902f7fcb/Build/Sharpmake/Sharpmake.Application.exe -------------------------------------------------------------------------------- /Build/Sharpmake/Sharpmake.Application.runtimeconfig.dev.json: -------------------------------------------------------------------------------- 1 | { 2 | "runtimeOptions": { 3 | "additionalProbingPaths": [ 4 | "C:\\Users\\runneradmin\\.dotnet\\store\\|arch|\\|tfm|", 5 | "C:\\Users\\runneradmin\\.nuget\\packages", 6 | "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages", 7 | "C:\\Program Files (x86)\\Microsoft\\Xamarin\\NuGet", 8 | "C:\\Program Files\\dotnet\\sdk\\NuGetFallbackFolder" 9 | ] 10 | } 11 | } -------------------------------------------------------------------------------- /Build/Sharpmake/Sharpmake.Application.runtimeconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "runtimeOptions": { 3 | "tfm": "net5.0", 4 | "framework": { 5 | "name": "Microsoft.NETCore.App", 6 | "version": "5.0.0" 7 | }, 8 | "configProperties": { 9 | "System.Globalization.Invariant": true 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Build/Sharpmake/Sharpmake.CommonPlatforms.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sammyfreg/netImgui/47e7bf9059a5d551521cbaff61ea6bab902f7fcb/Build/Sharpmake/Sharpmake.CommonPlatforms.dll -------------------------------------------------------------------------------- /Build/Sharpmake/Sharpmake.CommonPlatforms.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Sharpmake.CommonPlatforms 5 | 6 | 7 | 8 | 9 | Android SDK path 10 | 11 | 12 | 13 | 14 | Android NDK path 15 | 16 | 17 | 18 | 19 | Java SE Development Kit path 20 | 21 | 22 | 23 | 24 | Apache Ant path 25 | 26 | 27 | 28 | 29 | Allows setting a custom provider for system paths 30 | 31 | 32 | 33 | 34 | Generates position-independent code, suitable for shared libraries. 35 | 36 | 37 | The corresponding clang flags is -fPIC. 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Build/Sharpmake/Sharpmake.Generators.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sammyfreg/netImgui/47e7bf9059a5d551521cbaff61ea6bab902f7fcb/Build/Sharpmake/Sharpmake.Generators.dll -------------------------------------------------------------------------------- /Build/Sharpmake/Sharpmake.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sammyfreg/netImgui/47e7bf9059a5d551521cbaff61ea6bab902f7fcb/Build/Sharpmake/Sharpmake.dll -------------------------------------------------------------------------------- /Build/compatibility.sharpmake.cs.1: -------------------------------------------------------------------------------- 1 | // Note: 2 | // The files 'Build\compatibility.sharpmake.cs.1 [2,3]' 3 | // are used by 'Build\GenerateCompatibilityTest.bat' 4 | // while generating '_generated\imgui\compatibility.sharpmake.cs' 5 | 6 | namespace NetImgui 7 | { 8 | -------------------------------------------------------------------------------- /Build/compatibility.sharpmake.cs.2: -------------------------------------------------------------------------------- 1 | 2 | public class Utility 3 | { 4 | public static void AddCompatibilityProjects(Sharpmake.Solution.Configuration conf, NetImguiTarget target) 5 | { 6 | string SolutionFolder = "CompatibilityTest"; 7 | -------------------------------------------------------------------------------- /Build/compatibility.sharpmake.cs.3: -------------------------------------------------------------------------------- 1 | } 2 | } 3 | } 4 | -------------------------------------------------------------------------------- /Build/nocompatibility.sharpmake.cs: -------------------------------------------------------------------------------- 1 | namespace NetImgui 2 | { 3 | public class Utility 4 | { 5 | public static void AddCompatibilityProjects(Sharpmake.Solution.Configuration conf, NetImguiTarget target) 6 | { 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Build/readme.txt: -------------------------------------------------------------------------------- 1 | This folder contains files needed to generate the various NetImgui projects. 2 | 3 | User can safely ignore its content; only "GenerateProject.bat" needs calling, or "GenerateProject.sh" on macOS. 4 | 5 | Optionally, "GenerateCompatibilityTest.bat" can be called to get older versions of Dear ImGui and test compatibility of NetImgui against all of them. 6 | -------------------------------------------------------------------------------- /Clean.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | FOR /d %%d IN ("_*") DO @IF EXIST "%%d" rd /s /q "%%d" 3 | -------------------------------------------------------------------------------- /Code/Client/NetImgui_Config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //================================================================================================= 4 | // Enable code compilation for this library 5 | // Note: Useful to disable 'netImgui' on unsupported builds while keeping functions declared 6 | //================================================================================================= 7 | #ifndef NETIMGUI_ENABLED 8 | #define NETIMGUI_ENABLED 1 9 | #endif 10 | 11 | #if NETIMGUI_ENABLED 12 | 13 | #include 14 | 15 | #ifdef NETIMGUI_INTERNAL_INCLUDE 16 | #include "Private/NetImgui_WarningDisableImgui.h" // Disable some extra warning generated by imgui_internal in '-Wall' 17 | #include // Only needed when compiling NetImgui, not when using the NetImgui Api 18 | #include "Private/NetImgui_WarningReenable.h" 19 | #endif 20 | 21 | #endif // NETIMGUI_ENABLED 22 | 23 | //================================================================================================= 24 | // Default Ports used to reach the Server or the Client (listen port for incoming connection) 25 | //================================================================================================= 26 | namespace NetImgui 27 | { 28 | enum Constants{ 29 | kDefaultServerPort = 8888, //!< Default port Server waits for a connection 30 | kDefaultClientPort = 8889 //!< Default port Client waits for a connection 31 | }; 32 | } 33 | 34 | //================================================================================================= 35 | // Enable default Win32/Posix networking code 36 | // Note: By default, netImgui uses Winsock on Windows and Posix sockets on other platforms 37 | // 38 | // The use your own code, turn off both NETIMGUI_WINSOCKET_ENABLED, 39 | // NETIMGUI_POSIX_SOCKETS_ENABLED and provide your own implementation of the functions 40 | // declared in 'NetImgui_Network.h'. 41 | // 42 | // As an example, 'SampleCompression' disable default com implementation and use its own 43 | //================================================================================================= 44 | #if !defined(NETIMGUI_WINSOCKET_ENABLED) && !defined(__UNREAL__) 45 | #ifdef _WIN32 46 | #define NETIMGUI_WINSOCKET_ENABLED 1 // Project needs 'ws2_32.lib' added to input libraries 47 | #else 48 | #define NETIMGUI_WINSOCKET_ENABLED 0 49 | #endif 50 | #endif 51 | 52 | #if !defined(NETIMGUI_POSIX_SOCKETS_ENABLED) && !defined(__UNREAL__) 53 | #define NETIMGUI_POSIX_SOCKETS_ENABLED !(NETIMGUI_WINSOCKET_ENABLED) 54 | #endif 55 | 56 | //================================================================================================= 57 | // Various build settings define 58 | // Note: for more information, please look in 'NetImgui_Api.h' for description and default values 59 | //================================================================================================= 60 | //#define NETIMGUI_IMGUI_CALLBACK_ENABLED (IMGUI_VERSION_NUM >= 18100) // Not supported pre Dear ImGui 1.81 61 | //#define NETIMGUI_FORCE_TCP_LISTEN_BINDING 0 // Doesn't seem to be needed on Window/Linux 62 | //#define NETIMGUI_API IMGUI_API // Use same value as defined by Dear ImGui by default 63 | -------------------------------------------------------------------------------- /Code/Client/Private/NetImgui_Client.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "NetImgui_Shared.h" 4 | #include "NetImgui_CmdPackets.h" 5 | 6 | //============================================================================= 7 | // Forward Declares 8 | //============================================================================= 9 | namespace NetImgui { namespace Internal { namespace Network { struct SocketInfo; } } } 10 | 11 | namespace NetImgui { namespace Internal { namespace Client 12 | { 13 | 14 | //============================================================================= 15 | // Keep a list of textures used by Imgui, needed by server 16 | //============================================================================= 17 | struct ClientTexture 18 | { 19 | inline void Set( CmdTexture* pCmdTexture ); 20 | inline bool IsValid()const; 21 | CmdTexture* mpCmdTexture= nullptr; 22 | bool mbSent = false; 23 | uint8_t mPadding[7] = {}; 24 | }; 25 | 26 | //============================================================================= 27 | // Keeps a list of ImGui context values NetImgui overrides (to restore) 28 | //============================================================================= 29 | struct SavedImguiContext 30 | { 31 | void Save(ImGuiContext* copyFrom); 32 | void Restore(ImGuiContext* copyTo); 33 | const char* mBackendPlatformName = nullptr; 34 | const char* mBackendRendererName = nullptr; 35 | void* mImeWindowHandle = nullptr; 36 | float mFontGlobalScale = 1.f; 37 | float mFontGeneratedSize = 0.f; 38 | ImGuiBackendFlags mBackendFlags = 0; 39 | ImGuiConfigFlags mConfigFlags = 0; 40 | bool mDrawMouse = false; 41 | bool mSavedContext = false; 42 | char mPadding1[2] = {}; 43 | void* mClipboardUserData = nullptr; 44 | #if IMGUI_VERSION_NUM < 19110 45 | const char* (*mGetClipboardTextFn)(void*) = nullptr; 46 | void (*mSetClipboardTextFn)(void*, const char*) = nullptr; 47 | #else 48 | const char* (*mGetClipboardTextFn)(ImGuiContext*) = nullptr; 49 | void (*mSetClipboardTextFn)(ImGuiContext*, const char*) = nullptr; 50 | #endif 51 | #if IMGUI_VERSION_NUM < 18700 52 | int mKeyMap[ImGuiKey_COUNT] = {}; 53 | char mPadding2[8 - (sizeof(mKeyMap) % 8)] = {}; 54 | #endif 55 | }; 56 | 57 | //============================================================================= 58 | // Keep all Client infos needed for communication with server 59 | //============================================================================= 60 | struct ClientInfo 61 | { 62 | using VecTexture = ImVector; 63 | using BufferKeys = Ringbuffer; 64 | using TimePoint = std::chrono::time_point; 65 | 66 | struct InputState 67 | { 68 | uint64_t mInputDownMask[(CmdInput::ImGuiKey_COUNT+63)/64] = {}; 69 | float mInputAnalog[CmdInput::kAnalog_Count] = {}; 70 | uint64_t mMouseDownMask = 0; 71 | float mMouseWheelVertPrev = 0.f; 72 | float mMouseWheelHorizPrev = 0.f; 73 | }; 74 | ClientInfo(); 75 | ~ClientInfo(); 76 | void ContextInitialize(); 77 | void ContextOverride(); 78 | void ContextRestore(); 79 | void ContextRemoveHooks(); 80 | inline bool IsContextOverriden()const; 81 | 82 | std::atomic mpSocketPending; // Hold socket info until communication is established 83 | std::atomic mpSocketComs; // Socket used for communications with server 84 | std::atomic mpSocketListen; // Socket used to wait for communication request from server 85 | std::atomic_bool mbDisconnectPending; // Terminate Client/Server coms 86 | std::atomic_bool mbDisconnectListen; // Terminate waiting connection from Server 87 | uint32_t mSocketListenPort = 0; // Socket Port number used to wait for communication request from server 88 | VecTexture mTextures; // List if textures created by this client (used un main thread) 89 | char mName[64] = {}; 90 | uint64_t mFrameIndex = 0; // Incremented everytime we send a DrawFrame Command 91 | CmdTexture* mTexturesPending[16] = {}; 92 | ExchangePtr mPendingFrameOut; 93 | ExchangePtr mPendingBackgroundOut; 94 | ExchangePtr mPendingInputIn; 95 | ExchangePtr mPendingClipboardIn; // Clipboard content received from Server and waiting to be taken by client 96 | ExchangePtr mPendingClipboardOut; // Clipboard content copied on Client and waiting to be sent to Server 97 | ImGuiContext* mpContext = nullptr; // Context that the remote drawing should use (either the one active when connection request happened, or a clone) 98 | PendingCom mPendingRcv; // Data being currently received from Server 99 | PendingCom mPendingSend; // Data being currently sent to Server 100 | uint32_t mPendingSendNext = 0; // Type of Cmd to next attempt sending, when channel is available 101 | CmdPendingRead mCmdPendingRead; // Used to get info on the next incoming command from Server 102 | CmdInput* mpCmdInputPending = nullptr; // Last Input Command from server, waiting to be processed by client 103 | CmdClipboard* mpCmdClipboard = nullptr; // Last received clipboad command 104 | CmdDrawFrame* mpCmdDrawLast = nullptr; // Last sent Draw Command. Used by data compression, to generate delta between previous and current frame 105 | CmdBackground mBGSetting; // Current value assigned to background appearance by user 106 | CmdBackground mBGSettingSent; // Last sent value to remote server 107 | BufferKeys mPendingKeyIn; // Keys pressed received. Results of 2 CmdInputs are concatenated if received before being processed 108 | TimePoint mLastOutgoingDrawCheckTime; // When we last checked if we have a pending draw command to send 109 | TimePoint mLastOutgoingDrawTime; // When we last sent an updated draw command to the server 110 | ImVec2 mSavedDisplaySize = {0, 0}; // Save original display size on 'NewFrame' and restore it on 'EndFrame' (making sure size is still valid after a disconnect) 111 | const void* mpFontTextureData = nullptr; // Last font texture data send to server (used to detect if font was changed) 112 | ImTextureID mFontTextureID; 113 | SavedImguiContext mSavedContextValues; 114 | std::atomic_uint32_t mTexturesPendingSent; 115 | std::atomic_uint32_t mTexturesPendingCreated; 116 | 117 | std::atomic_bool mbClientThreadActive; // True when connected and communicating with Server 118 | std::atomic_bool mbListenThreadActive; // True when listening from connection request from Server 119 | std::atomic_bool mbComInitActive; // True when attempting to initialize a new connection 120 | bool mbHasTextureUpdate = false; 121 | bool mbIsDrawing = false; // We are inside a 'NetImgui::NewFrame' / 'NetImgui::EndFrame' (even if not for a remote draw) 122 | bool mbIsRemoteDrawing = false; // True if the rendering it meant for the remote netImgui server 123 | bool mbRestorePending = false; // Original context has had some settings overridden, original values stored in mRestoreXXX 124 | bool mbFontUploaded = false; // Auto detect if font was sent to server 125 | bool mbInsideHook = false; // Currently inside ImGui hook callback 126 | bool mbInsideNewEnd = false; // Currently inside NetImgui::NewFrame() or NetImgui::EndFrame() (prevents recusrive hook call) 127 | bool mbValidDrawFrame = false; // If we should forward the drawdata to the server at the end of ImGui::Render() 128 | uint8_t mClientCompressionMode = eCompressionMode::kUseServerSetting; 129 | bool mServerCompressionEnabled = false; // If Server would like compression to be enabled (mClientCompressionMode value can override this value) 130 | bool mServerCompressionSkip = false; // Force ignore compression setting for 1 frame 131 | bool mServerForceConnectEnabled = true; // If another NetImguiServer can take connection away from the one currently active 132 | ThreadFunctPtr mThreadFunction = nullptr; // Function to use when laucnhing new threads 133 | FontCreateFuncPtr mFontCreationFunction = nullptr; // Method to call to generate the remote ImGui font. By default, re-use the local font, but this doesn't handle native DPI scaling on remote server 134 | float mFontCreationScaling = 1.f; // Last font scaling used when generating the NetImgui font 135 | float mDesiredFps = 30.f; // How often we should update the remote drawing. Received from server 136 | InputState mPreviousInputState; // Keeping track of last keyboard/mouse state 137 | ImGuiID mhImguiHookNewframe = 0; 138 | ImGuiID mhImguiHookEndframe = 0; 139 | 140 | void ProcessDrawData(const ImDrawData* pDearImguiData, ImGuiMouseCursor mouseCursor); 141 | void ProcessTexturePending(); 142 | inline bool IsConnected()const; 143 | inline bool IsConnectPending()const; 144 | inline bool IsActive()const; 145 | 146 | // Prevent warnings about implicitly created copy 147 | protected: 148 | ClientInfo(const ClientInfo&)=delete; 149 | ClientInfo(const ClientInfo&&)=delete; 150 | void operator=(const ClientInfo&)=delete; 151 | }; 152 | 153 | //============================================================================= 154 | // Main communication loop threads that are run in separate threads 155 | //============================================================================= 156 | void CommunicationsConnect(void* pClientVoid); 157 | void CommunicationsHost(void* pClientVoid); 158 | 159 | }}} //namespace NetImgui::Internal::Client 160 | 161 | #include "NetImgui_Client.inl" 162 | -------------------------------------------------------------------------------- /Code/Client/Private/NetImgui_Client.inl: -------------------------------------------------------------------------------- 1 | 2 | #include "NetImgui_Network.h" 3 | 4 | namespace NetImgui { namespace Internal { namespace Client { 5 | 6 | void ClientTexture::Set( CmdTexture* pCmdTexture ) 7 | { 8 | netImguiDeleteSafe(mpCmdTexture); 9 | mpCmdTexture = pCmdTexture; 10 | mbSent = pCmdTexture == nullptr; 11 | } 12 | 13 | bool ClientTexture::IsValid()const 14 | { 15 | return mpCmdTexture != nullptr; 16 | } 17 | 18 | bool ClientInfo::IsConnected()const 19 | { 20 | return mpSocketComs.load() != nullptr; 21 | } 22 | 23 | bool ClientInfo::IsConnectPending()const 24 | { 25 | return mbComInitActive || mpSocketPending.load() != nullptr || mpSocketListen.load() != nullptr; 26 | } 27 | 28 | bool ClientInfo::IsActive()const 29 | { 30 | return mbClientThreadActive || mbListenThreadActive; 31 | } 32 | 33 | bool ClientInfo::IsContextOverriden()const 34 | { 35 | return mSavedContextValues.mSavedContext; 36 | } 37 | 38 | }}} // namespace NetImgui::Internal::Client 39 | -------------------------------------------------------------------------------- /Code/Client/Private/NetImgui_CmdPackets.inl: -------------------------------------------------------------------------------- 1 | #include "NetImgui_CmdPackets.h" 2 | 3 | namespace NetImgui { namespace Internal 4 | { 5 | 6 | void CmdDrawFrame::ToPointers() 7 | { 8 | if( !mpDrawGroups.IsPointer() ) 9 | { 10 | mpDrawGroups.ToPointer(); 11 | for (uint32_t i(0); i < mDrawGroupCount; ++i) { 12 | mpDrawGroups[i].ToPointers(); 13 | } 14 | } 15 | } 16 | 17 | void CmdDrawFrame::ToOffsets() 18 | { 19 | if( !mpDrawGroups.IsOffset() ) 20 | { 21 | for (uint32_t i(0); i < mDrawGroupCount; ++i) { 22 | mpDrawGroups[i].ToOffsets(); 23 | } 24 | mpDrawGroups.ToOffset(); 25 | } 26 | } 27 | 28 | void ImguiDrawGroup::ToPointers() 29 | { 30 | if( !mpIndices.IsPointer() ) //Safer to test the first element after CmdHeader 31 | { 32 | mpIndices.ToPointer(); 33 | mpVertices.ToPointer(); 34 | mpDraws.ToPointer(); 35 | } 36 | } 37 | 38 | void ImguiDrawGroup::ToOffsets() 39 | { 40 | if( !mpIndices.IsOffset() ) //Safer to test the first element after CmdHeader 41 | { 42 | mpIndices.ToOffset(); 43 | mpVertices.ToOffset(); 44 | mpDraws.ToOffset(); 45 | } 46 | } 47 | 48 | bool CmdInput::IsKeyDown( CmdInput::NetImguiKeys netimguiKey) const 49 | { 50 | uint32_t valIndex = netimguiKey/64; 51 | uint64_t valMask = 0x0000000000000001ull << (netimguiKey%64); 52 | return mInputDownMask[valIndex] & valMask; 53 | } 54 | 55 | bool CmdBackground::operator==(const CmdBackground& cmp)const 56 | { 57 | bool sameValue(true); 58 | for(size_t i(0); i(this)[i] == reinterpret_cast(&cmp)[i]; 60 | } 61 | return sameValue; 62 | } 63 | 64 | bool CmdBackground::operator!=(const CmdBackground& cmp)const 65 | { 66 | return (*this == cmp) == false; 67 | } 68 | 69 | 70 | void CmdClipboard::ToPointers() 71 | { 72 | if( !mContentUTF8.IsPointer() ){ 73 | mContentUTF8.ToPointer(); 74 | } 75 | } 76 | 77 | void CmdClipboard::ToOffsets() 78 | { 79 | if( !mContentUTF8.IsOffset() ){ 80 | mContentUTF8.ToOffset(); 81 | } 82 | } 83 | 84 | CmdClipboard* CmdClipboard::Create(const char* clipboard) 85 | { 86 | if( clipboard ) 87 | { 88 | size_t clipboardByteSize(0); 89 | while(clipboard[clipboardByteSize++] != 0); 90 | size_t totalDataCount = sizeof(CmdClipboard) + DivUp(clipboardByteSize, ComDataSize); 91 | auto pNewClipboard = NetImgui::Internal::netImguiSizedNew(totalDataCount*ComDataSize); 92 | pNewClipboard->mSize = static_cast(totalDataCount*ComDataSize); 93 | pNewClipboard->mByteSize = clipboardByteSize; 94 | pNewClipboard->mContentUTF8.SetPtr(reinterpret_cast(&pNewClipboard[1])); 95 | memcpy(pNewClipboard->mContentUTF8.Get(), clipboard, clipboardByteSize); 96 | return pNewClipboard; 97 | } 98 | return nullptr; 99 | } 100 | 101 | }} // namespace NetImgui::Internal 102 | -------------------------------------------------------------------------------- /Code/Client/Private/NetImgui_CmdPackets_DrawFrame.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "NetImgui_Shared.h" 4 | 5 | namespace NetImgui { namespace Internal 6 | { 7 | 8 | struct ImguiVert 9 | { 10 | //Note: If updating this, increase 'CmdVersion::eVersion' 11 | enum Constants{ kUvRange_Min=0, kUvRange_Max=1, kPosRange_Min=-8192, kPosRange_Max=8192}; 12 | uint16_t mPos[2]; 13 | uint16_t mUV[2]; 14 | uint32_t mColor; 15 | }; 16 | 17 | struct ImguiDraw 18 | { 19 | uint64_t mTextureId; 20 | uint32_t mIdxCount; // Drawcall number of indices (3 indices per triangles) 21 | uint32_t mVtxOffset; // Drawcall start position in vertices buffer (considered index 0) 22 | uint32_t mIdxOffset; // Drawcall start position in indices buffer 23 | float mClipRect[4]; 24 | uint8_t PADDING[4]={}; 25 | }; 26 | 27 | // Each DearImgui window has its own vertex/index buffers with multiple drawcalls 28 | struct alignas(8) ImguiDrawGroup 29 | { 30 | static constexpr uint32_t kInvalidDrawGroup = 0xFFFFFFFF; 31 | uint64_t mGroupID = 0; // Unique ID to recognize DrawGroup between 2 frames 32 | uint32_t mVerticeCount = 0; 33 | uint32_t mIndiceCount = 0; 34 | uint32_t mDrawCount = 0; 35 | uint32_t mDrawGroupIdxPrev = kInvalidDrawGroup;// Group index in previous DrawFrame (kInvalidDrawGroup when not using delta compression) 36 | uint8_t mBytePerIndex = 2; // 2, 4 bytes 37 | uint8_t PADDING[7] = {}; 38 | float mReferenceCoord[2] = {}; // Reference position for the encoded vertices offsets (1st vertice top/left position) 39 | OffsetPointer mpIndices; 40 | OffsetPointer mpVertices; 41 | OffsetPointer mpDraws; 42 | inline void ToPointers(); 43 | inline void ToOffsets(); 44 | }; 45 | 46 | struct CmdDrawFrame* ConvertToCmdDrawFrame(const ImDrawData* pDearImguiData, ImGuiMouseCursor cursor); 47 | struct CmdDrawFrame* CompressCmdDrawFrame(const CmdDrawFrame* pDrawFramePrev, const CmdDrawFrame* pDrawFrameNew); 48 | struct CmdDrawFrame* DecompressCmdDrawFrame(const CmdDrawFrame* pDrawFramePrev, const CmdDrawFrame* pDrawFramePacked); 49 | 50 | }} // namespace NetImgui::Internal 51 | -------------------------------------------------------------------------------- /Code/Client/Private/NetImgui_Network.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace NetImgui { namespace Internal { struct PendingCom; }} 4 | 5 | namespace NetImgui { namespace Internal { namespace Network 6 | { 7 | 8 | struct SocketInfo; 9 | 10 | bool Startup (void); 11 | void Shutdown (void); 12 | 13 | SocketInfo* Connect (const char* ServerHost, uint32_t ServerPort); // Communication Socket expected to be blocking 14 | SocketInfo* ListenConnect (SocketInfo* ListenSocket); // Communication Socket expected to be blocking 15 | SocketInfo* ListenStart (uint32_t ListenPort); // Listening Socket expected to be non blocking 16 | void Disconnect (SocketInfo* pClientSocket); 17 | 18 | bool DataReceivePending (SocketInfo* pClientSocket); // True if some new data if waiting to be processed from remote connection 19 | void DataReceive (SocketInfo* pClientSocket, PendingCom& PendingComRcv); // Try reading X amount of bytes from remote connection, but can fall short. 20 | void DataSend (SocketInfo* pClientSocket, PendingCom& PendingComSend); // Try sending X amount of bytes to remote connection, but can fall short. 21 | 22 | }}} //namespace NetImgui::Internal::Network 23 | -------------------------------------------------------------------------------- /Code/Client/Private/NetImgui_NetworkUE4.cpp: -------------------------------------------------------------------------------- 1 | #include "NetImgui_Shared.h" 2 | 3 | // Tested with Unreal Engine 4.27, 5.3, 5.4, 5.5 4 | 5 | #if NETIMGUI_ENABLED && defined(__UNREAL__) 6 | 7 | #include "CoreMinimal.h" 8 | #include "Runtime/Launch/Resources/Version.h" 9 | #include "Misc/OutputDeviceRedirector.h" 10 | #include "SocketSubsystem.h" 11 | #include "Sockets.h" 12 | #include "HAL/PlatformProcess.h" 13 | #if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 2 14 | #include "IPAddressAsyncResolve.h" 15 | #endif 16 | 17 | namespace NetImgui { namespace Internal { namespace Network 18 | { 19 | 20 | //================================================================================================= 21 | // Wrapper around native socket object and init some socket options 22 | //================================================================================================= 23 | struct SocketInfo 24 | { 25 | SocketInfo(FSocket* pSocket) 26 | : mpSocket(pSocket) 27 | { 28 | if( mpSocket ) 29 | { 30 | mpSocket->SetNonBlocking(true); 31 | mpSocket->SetNoDelay(true); 32 | 33 | int32 NewSize(0); 34 | while( !mpSocket->SetSendBufferSize(2*mSendSize, NewSize) ){ 35 | mSendSize /= 2; 36 | } 37 | mSendSize = NewSize/2; 38 | } 39 | } 40 | 41 | ~SocketInfo() 42 | { 43 | Close(); 44 | } 45 | 46 | void Close() 47 | { 48 | if(mpSocket ) 49 | { 50 | mpSocket->Close(); 51 | ISocketSubsystem::Get()->DestroySocket(mpSocket); 52 | mpSocket = nullptr; 53 | } 54 | } 55 | FSocket* mpSocket = nullptr; 56 | int32 mSendSize = 1024*1024; // Limit tx data to avoid socket error on large amount (texture) 57 | }; 58 | 59 | bool Startup() 60 | { 61 | return true; 62 | } 63 | 64 | void Shutdown() 65 | { 66 | } 67 | 68 | //================================================================================================= 69 | // Try establishing a connection to a remote client at given address 70 | //================================================================================================= 71 | SocketInfo* Connect(const char* ServerHost, uint32_t ServerPort) 72 | { 73 | SocketInfo* pSocketInfo = nullptr; 74 | ISocketSubsystem* SocketSubSystem = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM); 75 | TSharedPtr IpAddressFind = SocketSubSystem->GetAddressFromString((TCHAR*)StringCast(static_cast(ServerHost)).Get()); 76 | if(IpAddressFind) 77 | { 78 | TSharedRef IpAddress = IpAddressFind->Clone(); 79 | IpAddress->SetPort(ServerPort); 80 | if (IpAddress->IsValid()) 81 | { 82 | FSocket* pNewSocket = SocketSubSystem->CreateSocket(NAME_Stream, "NetImgui", IpAddress->GetProtocolType()); 83 | if (pNewSocket) 84 | { 85 | pNewSocket->SetNonBlocking(true); 86 | if (pNewSocket->Connect(*IpAddress)) 87 | { 88 | bool bConnectionReady = false; 89 | pNewSocket->WaitForPendingConnection(bConnectionReady, FTimespan::FromSeconds(1.0f)); 90 | if( bConnectionReady ) 91 | { 92 | pSocketInfo = netImguiNew(pNewSocket); 93 | return pSocketInfo; 94 | } 95 | } 96 | } 97 | } 98 | } 99 | netImguiDelete(pSocketInfo); 100 | return nullptr; 101 | } 102 | 103 | //================================================================================================= 104 | // Start waiting for connection request on this socket 105 | //================================================================================================= 106 | SocketInfo* ListenStart(uint32_t ListenPort) 107 | { 108 | ISocketSubsystem* PlatformSocketSub = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM); 109 | TSharedPtr IpAddress = PlatformSocketSub->GetLocalBindAddr(*GLog); 110 | IpAddress->SetPort(ListenPort); 111 | 112 | FSocket* pNewListenSocket = PlatformSocketSub->CreateSocket(NAME_Stream, "NetImguiListen", IpAddress->GetProtocolType()); 113 | if( pNewListenSocket ) 114 | { 115 | SocketInfo* pListenSocketInfo = netImguiNew(pNewListenSocket); 116 | #if NETIMGUI_FORCE_TCP_LISTEN_BINDING 117 | pNewListenSocket->SetReuseAddr(); 118 | #endif 119 | pNewListenSocket->SetNonBlocking(false); 120 | pNewListenSocket->SetRecvErr(); 121 | if (pNewListenSocket->Bind(*IpAddress)) 122 | { 123 | if (pNewListenSocket->Listen(1)) 124 | { 125 | return pListenSocketInfo; 126 | } 127 | } 128 | netImguiDelete(pListenSocketInfo); 129 | } 130 | return nullptr; 131 | } 132 | 133 | //================================================================================================= 134 | // Establish a new connection to a remote request 135 | //================================================================================================= 136 | SocketInfo* ListenConnect(SocketInfo* pListenSocket) 137 | { 138 | if (pListenSocket) 139 | { 140 | FSocket* pNewSocket = pListenSocket->mpSocket->Accept(FString("NetImgui")); 141 | if( pNewSocket ) 142 | { 143 | SocketInfo* pSocketInfo = netImguiNew(pNewSocket); 144 | return pSocketInfo; 145 | } 146 | } 147 | return nullptr; 148 | } 149 | 150 | //================================================================================================= 151 | // Close a connection and free allocated object 152 | //================================================================================================= 153 | void Disconnect(SocketInfo* pClientSocket) 154 | { 155 | netImguiDelete(pClientSocket); 156 | } 157 | 158 | //================================================================================================= 159 | // Return true if data has been received, or there's a connection error 160 | //================================================================================================= 161 | bool DataReceivePending(SocketInfo* pClientSocket) 162 | { 163 | // Note: return true on a connection error, to exit code looping on the data wait. Will handle error after DataReceive() 164 | uint32 PendingDataSize; 165 | return !pClientSocket || pClientSocket->mpSocket->HasPendingData(PendingDataSize) || (pClientSocket->mpSocket->GetConnectionState() != ESocketConnectionState::SCS_Connected); 166 | } 167 | 168 | //================================================================================================= 169 | // Receive as much as possible a command and keep track of transfer status 170 | //================================================================================================= 171 | void DataReceive(SocketInfo* pClientSocket, NetImgui::Internal::PendingCom& PendingComRcv) 172 | { 173 | // Invalid command 174 | if( !pClientSocket || !PendingComRcv.pCommand || !pClientSocket->mpSocket || (pClientSocket->mpSocket->GetConnectionState() != ESocketConnectionState::SCS_Connected)){ 175 | PendingComRcv.bError = true; 176 | return; 177 | } 178 | 179 | int32 sizeRcv(0); 180 | if( pClientSocket->mpSocket->Recv( &reinterpret_cast(PendingComRcv.pCommand)[PendingComRcv.SizeCurrent], 181 | static_cast(PendingComRcv.pCommand->mSize-PendingComRcv.SizeCurrent), 182 | sizeRcv, 183 | ESocketReceiveFlags::None) ) 184 | { 185 | PendingComRcv.SizeCurrent += static_cast(sizeRcv); 186 | PendingComRcv.bError |= sizeRcv <= 0; // Error if no data read since DataReceivePending() said there was some available 187 | } 188 | else 189 | { 190 | // Connection error, abort transmission 191 | const ESocketErrors SocketError = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->GetLastErrorCode(); 192 | PendingComRcv.bError = SocketError != SE_NO_ERROR && SocketError != ESocketErrors::SE_EWOULDBLOCK; 193 | } 194 | } 195 | 196 | //================================================================================================= 197 | // Receive as much as possible a command and keep track of transfer status 198 | //================================================================================================= 199 | void DataSend(SocketInfo* pClientSocket, NetImgui::Internal::PendingCom& PendingComSend) 200 | { 201 | // Invalid command 202 | if( !pClientSocket || !PendingComSend.pCommand || !pClientSocket->mpSocket || (pClientSocket->mpSocket->GetConnectionState() != ESocketConnectionState::SCS_Connected) ){ 203 | PendingComSend.bError = true; 204 | return; 205 | } 206 | 207 | int32 sizeSent = 0; 208 | int32 sizeToSend = PendingComSend.pCommand->mSize-PendingComSend.SizeCurrent; 209 | sizeToSend = sizeToSend > pClientSocket->mSendSize ? pClientSocket->mSendSize : sizeToSend; 210 | 211 | if( pClientSocket->mpSocket->Send( &reinterpret_cast(PendingComSend.pCommand)[PendingComSend.SizeCurrent], 212 | static_cast(sizeToSend), 213 | sizeSent) ) 214 | { 215 | PendingComSend.SizeCurrent += static_cast(sizeSent); 216 | } 217 | else 218 | { 219 | // Connection error, abort transmission 220 | const ESocketErrors SocketError = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->GetLastErrorCode(); 221 | PendingComSend.bError = SocketError != SE_NO_ERROR && SocketError != ESocketErrors::SE_EWOULDBLOCK; 222 | } 223 | } 224 | 225 | }}} // namespace NetImgui::Internal::Network 226 | 227 | #else 228 | 229 | // Prevents Linker warning LNK4221 in Visual Studio (This object file does not define any previously undefined public symbols, so it will not be used by any link operation that consumes this library) 230 | extern int sSuppresstLNK4221_NetImgui_NetworkUE4; 231 | int sSuppresstLNK4221_NetImgui_NetworkUE4(0); 232 | 233 | #endif // #if NETIMGUI_ENABLED && defined(__UNREAL__) 234 | -------------------------------------------------------------------------------- /Code/Client/Private/NetImgui_Shared.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //================================================================================================= 4 | // Include NetImgui_Api.h with almost no warning suppression. 5 | // this is to make sure library user does not need to suppress any 6 | #if defined(_MSC_VER) 7 | #pragma warning (disable: 4464) // warning C4464: relative include path contains '..' 8 | #endif 9 | 10 | #ifndef NETIMGUI_INTERNAL_INCLUDE 11 | #define NETIMGUI_INTERNAL_INCLUDE 1 12 | #include "NetImgui_Api.h" 13 | #undef NETIMGUI_INTERNAL_INCLUDE 14 | #else 15 | #include "NetImgui_Api.h" 16 | #endif 17 | 18 | #if NETIMGUI_ENABLED 19 | 20 | //================================================================================================= 21 | // Include a few standard c++ header, with additional warning suppression 22 | #include "NetImgui_WarningDisableStd.h" 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include "NetImgui_WarningReenable.h" 28 | //================================================================================================= 29 | 30 | 31 | //================================================================================================= 32 | #include "NetImgui_WarningDisable.h" 33 | namespace NetImgui { namespace Internal 34 | { 35 | 36 | using ComDataType = uint64_t; 37 | constexpr size_t ComDataSize = sizeof(ComDataType); 38 | 39 | //============================================================================= 40 | // All allocations made by netImgui goes through here. 41 | // Relies in ImGui allocator 42 | //============================================================================= 43 | template TType* netImguiNew(Args... args); 44 | template TType* netImguiSizedNew(size_t placementSize); 45 | template void netImguiDelete(TType* pData); 46 | template void netImguiDeleteSafe(TType*& pData); 47 | 48 | class ScopedImguiContext 49 | { 50 | public: 51 | ScopedImguiContext(ImGuiContext* pNewContext) : mpSavedContext(ImGui::GetCurrentContext()){ ImGui::SetCurrentContext(pNewContext); } 52 | ~ScopedImguiContext() { ImGui::SetCurrentContext(mpSavedContext); } 53 | 54 | protected: 55 | ImGuiContext* mpSavedContext; 56 | }; 57 | 58 | template 59 | class ScopedValue 60 | { 61 | public: 62 | ScopedValue(TType& ValueRef, TType Value) 63 | : mValueRef(ValueRef) 64 | , mValueRestore(ValueRef) 65 | { 66 | mValueRef = Value; 67 | } 68 | ~ScopedValue() 69 | { 70 | mValueRef = mValueRestore; 71 | } 72 | protected: 73 | TType& mValueRef; 74 | TType mValueRestore; 75 | uint8_t mPadding[sizeof(void*)-(sizeof(TType)%8)]={}; 76 | 77 | // Prevents warning about implicitly delete functions 78 | ScopedValue(const ScopedValue&) = delete; 79 | ScopedValue(const ScopedValue&&) = delete; 80 | void operator=(const ScopedValue&) = delete; 81 | }; 82 | 83 | using ScopedBool = ScopedValue; 84 | 85 | //============================================================================= 86 | // Class to safely exchange a pointer between two threads 87 | //============================================================================= 88 | template 89 | class ExchangePtr 90 | { 91 | public: 92 | ExchangePtr():mpData(nullptr){} 93 | ~ExchangePtr(); 94 | inline TType* Release(); 95 | inline void Assign(TType*& pNewData); 96 | inline void Free(); 97 | inline bool IsNull()const { return mpData.load() == nullptr; } 98 | private: 99 | std::atomic mpData; 100 | 101 | // Prevents warning about implicitly delete functions 102 | private: 103 | ExchangePtr(const ExchangePtr&) = delete; 104 | ExchangePtr(const ExchangePtr&&) = delete; 105 | void operator=(const ExchangePtr&) = delete; 106 | }; 107 | 108 | //============================================================================= 109 | // Make data serialization easier 110 | //============================================================================= 111 | template 112 | struct OffsetPointer 113 | { 114 | inline OffsetPointer(); 115 | inline explicit OffsetPointer(TType* pPointer); 116 | inline explicit OffsetPointer(uint64_t offset); 117 | 118 | inline bool IsPointer()const; 119 | inline bool IsOffset()const; 120 | 121 | inline TType* ToPointer(); 122 | inline uint64_t ToOffset(); 123 | inline TType* operator->(); 124 | inline const TType* operator->()const; 125 | inline TType& operator[](size_t index); 126 | inline const TType& operator[](size_t index)const; 127 | 128 | inline TType* Get(); 129 | inline const TType* Get()const; 130 | inline const ComDataType* GetComData()const; 131 | inline uint64_t GetOff()const; 132 | inline void SetPtr(TType* pPointer); 133 | inline void SetComDataPtr(ComDataType* pPointer); 134 | inline void SetOff(uint64_t offset); 135 | 136 | private: 137 | union 138 | { 139 | uint64_t mOffset; 140 | TType* mPointer; 141 | }; 142 | }; 143 | 144 | //============================================================================= 145 | //============================================================================= 146 | template 147 | class Ringbuffer 148 | { 149 | public: 150 | Ringbuffer():mPosCur(0),mPosLast(0){} 151 | void AddData(const TType* pData, size_t& count); 152 | bool ReadData(TType* pData); 153 | private: 154 | TType mBuffer[TCount] = {0}; 155 | std::atomic_uint64_t mPosCur; 156 | std::atomic_uint64_t mPosLast; 157 | 158 | // Prevents warning about implicitly delete functions 159 | private: 160 | Ringbuffer(const Ringbuffer&) = delete; 161 | Ringbuffer(const Ringbuffer&&) = delete; 162 | void operator=(const Ringbuffer&) = delete; 163 | }; 164 | 165 | template 166 | constexpr std::size_t ArrayCount(T const (&)[N]) noexcept 167 | { 168 | return N; 169 | } 170 | 171 | //============================================================================= 172 | //============================================================================= 173 | template 174 | inline void StringCopy(char (&output)[charCount], const char* pSrc, size_t srcCharCount=0xFFFFFFFE); 175 | 176 | template 177 | int StringFormat(char(&output)[charCount], char const* const format, ...); 178 | 179 | //============================================================================= 180 | // Get the (value / Denominator) rounded up to the next int value big enough 181 | //============================================================================= 182 | template 183 | IntType DivUp(IntType Value, IntType Denominator); 184 | 185 | //============================================================================= 186 | // Get the rounded up value 187 | //============================================================================= 188 | template 189 | IntType RoundUp(IntType Value, IntType Round); 190 | 191 | inline uint64_t TextureCastFromID(ImTextureID textureID); 192 | inline ImTextureID TextureCastFromPtr(void* pTexture); 193 | inline ImTextureID TextureCastFromUInt(uint64_t textureID); 194 | 195 | }} //namespace NetImgui::Internal 196 | 197 | #include "NetImgui_Shared.inl" 198 | #include "NetImgui_WarningReenable.h" 199 | 200 | #endif //NETIMGUI_ENABLED 201 | -------------------------------------------------------------------------------- /Code/Client/Private/NetImgui_Shared.inl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace NetImgui { namespace Internal 7 | { 8 | 9 | template 10 | TType* netImguiNew(Args... args) 11 | { 12 | return new( ImGui::MemAlloc(sizeof(TType)) ) TType(args...); 13 | } 14 | 15 | template 16 | TType* netImguiSizedNew(size_t placementSize) 17 | { 18 | return new( ImGui::MemAlloc(placementSize > sizeof(TType) ? placementSize : sizeof(TType)) ) TType(); 19 | } 20 | 21 | template 22 | void netImguiDelete(TType* pData) 23 | { 24 | if( pData ) 25 | { 26 | pData->~TType(); 27 | ImGui::MemFree(pData); 28 | } 29 | } 30 | 31 | template 32 | void netImguiDeleteSafe(TType*& pData) 33 | { 34 | netImguiDelete(pData); 35 | pData = nullptr; 36 | } 37 | 38 | //============================================================================= 39 | // Acquire ownership of the resource 40 | //============================================================================= 41 | template 42 | TType* ExchangePtr::Release() 43 | { 44 | return mpData.exchange(nullptr); 45 | } 46 | 47 | //----------------------------------------------------------------------------- 48 | // Take ownership of the provided data. 49 | // If there's a previous unclaimed pointer to some data, release it 50 | //----------------------------------------------------------------------------- 51 | template 52 | void ExchangePtr::Assign(TType*& pNewData) 53 | { 54 | netImguiDelete( mpData.exchange(pNewData) ); 55 | pNewData = nullptr; 56 | } 57 | 58 | template 59 | void ExchangePtr::Free() 60 | { 61 | TType* pNull(nullptr); 62 | Assign(pNull); 63 | } 64 | 65 | template 66 | ExchangePtr::~ExchangePtr() 67 | { 68 | Free(); 69 | } 70 | 71 | //============================================================================= 72 | // 73 | //============================================================================= 74 | template 75 | OffsetPointer::OffsetPointer() 76 | : mOffset(0) 77 | { 78 | SetOff(0); 79 | } 80 | 81 | template 82 | OffsetPointer::OffsetPointer(TType* pPointer) 83 | { 84 | SetPtr(pPointer); 85 | } 86 | 87 | template 88 | OffsetPointer::OffsetPointer(uint64_t offset) 89 | { 90 | SetOff(offset); 91 | } 92 | 93 | template 94 | void OffsetPointer::SetPtr(TType* pPointer) 95 | { 96 | mOffset = 0; // Remove 'offset flag' that can be left active on non 64bits pointer 97 | mPointer = pPointer; 98 | } 99 | 100 | template 101 | void OffsetPointer::SetComDataPtr(ComDataType* pPointer) 102 | { 103 | SetPtr(reinterpret_cast(pPointer)); 104 | } 105 | 106 | template 107 | void OffsetPointer::SetOff(uint64_t offset) 108 | { 109 | mOffset = offset | 0x0000000000000001u; 110 | } 111 | 112 | template 113 | uint64_t OffsetPointer::GetOff()const 114 | { 115 | return mOffset & ~0x0000000000000001u; 116 | } 117 | 118 | template 119 | bool OffsetPointer::IsOffset()const 120 | { 121 | return (mOffset & 0x0000000000000001u) != 0; 122 | } 123 | 124 | template 125 | bool OffsetPointer::IsPointer()const 126 | { 127 | return !IsOffset(); 128 | } 129 | 130 | template 131 | TType* OffsetPointer::ToPointer() 132 | { 133 | assert(IsOffset()); 134 | SetPtr( reinterpret_cast( reinterpret_cast(&mPointer) + GetOff() ) ); 135 | return mPointer; 136 | } 137 | 138 | template 139 | uint64_t OffsetPointer::ToOffset() 140 | { 141 | assert(IsPointer()); 142 | SetOff( reinterpret_cast(mPointer) - reinterpret_cast(&mPointer) ); 143 | return mOffset; 144 | } 145 | 146 | template 147 | TType* OffsetPointer::operator->() 148 | { 149 | assert(IsPointer()); 150 | return mPointer; 151 | } 152 | 153 | template 154 | const TType* OffsetPointer::operator->()const 155 | { 156 | assert(IsPointer()); 157 | return mPointer; 158 | } 159 | 160 | template 161 | TType* OffsetPointer::Get() 162 | { 163 | assert(IsPointer()); 164 | return mPointer; 165 | } 166 | 167 | template 168 | const TType* OffsetPointer::Get()const 169 | { 170 | assert(IsPointer()); 171 | return mPointer; 172 | } 173 | 174 | template 175 | const ComDataType* OffsetPointer::GetComData()const 176 | { 177 | return reinterpret_cast(Get()); 178 | } 179 | 180 | template 181 | TType& OffsetPointer::operator[](size_t index) 182 | { 183 | assert(IsPointer()); 184 | return mPointer[index]; 185 | } 186 | 187 | template 188 | const TType& OffsetPointer::operator[](size_t index)const 189 | { 190 | assert(IsPointer()); 191 | return mPointer[index]; 192 | } 193 | 194 | //============================================================================= 195 | template 196 | void Ringbuffer::AddData(const TType* pData, size_t& count) 197 | //============================================================================= 198 | { 199 | size_t i(0); 200 | while (i < count && (mPosLast - mPosCur < TCount)) { 201 | mBuffer[mPosLast % TCount] = pData[i]; 202 | mPosLast++; 203 | i++; 204 | } 205 | count = i; 206 | } 207 | 208 | //============================================================================= 209 | template 210 | bool Ringbuffer::ReadData(TType* pData) 211 | //============================================================================= 212 | { 213 | if (mPosCur < mPosLast) 214 | { 215 | *pData = mBuffer[mPosCur % TCount]; 216 | mPosCur++; 217 | return true; 218 | } 219 | return false; 220 | } 221 | 222 | 223 | //============================================================================= 224 | // The _s string functions are a mess. There's really no way to do this right 225 | // in a cross-platform way. Best solution I've found is to set just use 226 | // strncpy, infer the buffer length, and null terminate. Still need to suppress 227 | // the warning on Windows. 228 | // See https://randomascii.wordpress.com/2013/04/03/stop-using-strncpy-already/ 229 | // and many other discussions online on the topic. 230 | //============================================================================= 231 | template 232 | void StringCopy(char (&output)[charCount], const char* pSrc, size_t srcCharCount) 233 | { 234 | #if defined(__clang__) 235 | #pragma clang diagnostic push 236 | #pragma clang diagnostic ignored "-Wdeprecated-declarations" 237 | #elif defined(_MSC_VER) 238 | #pragma warning (push) 239 | #pragma warning (disable: 4996) // warning C4996: 'strncpy': This function or variable may be unsafe. 240 | #endif 241 | 242 | size_t charToCopyCount = charCount < srcCharCount + 1 ? charCount : srcCharCount + 1; 243 | strncpy(output, pSrc, charToCopyCount - 1); 244 | output[charCount - 1] = 0; 245 | 246 | #if defined(_MSC_VER) && defined(__clang__) 247 | #pragma clang diagnostic pop 248 | #elif defined(_MSC_VER) 249 | #pragma warning (pop) 250 | #endif 251 | } 252 | 253 | template 254 | int StringFormat(char(&output)[charCount], char const* const format, ...) 255 | { 256 | #if defined(__clang__) 257 | #pragma clang diagnostic push 258 | #pragma clang diagnostic ignored "-Wformat-nonliteral" 259 | #endif 260 | 261 | va_list args; 262 | va_start(args, format); 263 | int w = vsnprintf(output, charCount, format, args); 264 | va_end(args); 265 | output[charCount - 1] = 0; 266 | return w; 267 | 268 | #if defined(__clang__) 269 | #pragma clang diagnostic pop 270 | #endif 271 | } 272 | 273 | //============================================================================= 274 | //============================================================================= 275 | template 276 | IntType DivUp(IntType Value, IntType Denominator) 277 | { 278 | return (Value + Denominator - 1) / Denominator; 279 | } 280 | 281 | template 282 | IntType RoundUp(IntType Value, IntType Round) 283 | { 284 | return DivUp(Value, Round) * Round; 285 | } 286 | 287 | union TextureCastHelperUnion 288 | { 289 | ImTextureID TextureID; 290 | uint64_t TextureUint; 291 | const void* TexturePtr; 292 | }; 293 | 294 | uint64_t TextureCastFromID(ImTextureID textureID) 295 | { 296 | TextureCastHelperUnion textureUnion; 297 | textureUnion.TextureUint = 0; 298 | textureUnion.TextureID = textureID; 299 | return textureUnion.TextureUint; 300 | } 301 | 302 | ImTextureID TextureCastFromPtr(void* pTexture) 303 | { 304 | TextureCastHelperUnion textureUnion; 305 | textureUnion.TextureUint = 0; 306 | textureUnion.TexturePtr = pTexture; 307 | return textureUnion.TextureID; 308 | } 309 | 310 | #ifndef IS_NETIMGUISERVER 311 | ImTextureID TextureCastFromUInt(uint64_t textureID) 312 | { 313 | TextureCastHelperUnion textureUnion; 314 | textureUnion.TextureUint = textureID; 315 | return textureUnion.TextureID; 316 | } 317 | #endif 318 | 319 | }} //namespace NetImgui::Internal 320 | -------------------------------------------------------------------------------- /Code/Client/Private/NetImgui_WarningDisable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // 3 | // Deactivate a few warnings to allow internal netImgui code to compile 4 | // with 'Warning as error' and '-Wall' compile actions enabled 5 | // 6 | 7 | //================================================================================================= 8 | // Clang 9 | //================================================================================================= 10 | #if defined (__clang__) 11 | #pragma clang diagnostic push 12 | #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" 13 | #pragma clang diagnostic ignored "-Wmissing-prototypes" 14 | 15 | //================================================================================================= 16 | // Visual Studio warnings 17 | //================================================================================================= 18 | #elif defined(_MSC_VER) 19 | #pragma warning (disable: 5032) // detected #pragma warning(push) with no corresponding #pragma warning(pop) 20 | 21 | #pragma warning (push) 22 | #pragma warning (disable: 4365) // conversion from 'long' to 'unsigned int', signed/unsigned mismatch for 23 | #pragma warning (disable: 4464) // relative include path contains '..' 24 | #pragma warning (disable: 4514) // unreferenced inline function has been removed 25 | #pragma warning (disable: 4577) // 'noexcept' used with no exception handling mode specified; termination on exception is not guaranteed. Specify 26 | #pragma warning (disable: 4710) // 'xxx': function not inlined 27 | #pragma warning (disable: 4711) // function 'xxx' selected for automatic inline expansion 28 | #pragma warning (disable: 4826) // Conversion from 'TType *' to 'uint64_t' is sign-extended. This may cause unexpected runtime behavior. 29 | #pragma warning (disable: 5031) // #pragma warning(pop): likely mismatch, popping warning state pushed in different file 30 | #pragma warning (disable: 5045) // Compiler will insert Spectre mitigation for memory load if / Qspectre switch specified 31 | #pragma warning (disable: 5264) // 'xxx': 'const' variable is not used 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /Code/Client/Private/NetImgui_WarningDisableImgui.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // 3 | // Deactivate a few warnings to allow Imgui header includes, 4 | // without generating warnings in '-Wall' compile actions enabled 5 | // 6 | 7 | //================================================================================================= 8 | // Clang 9 | //================================================================================================= 10 | #if defined (__clang__) 11 | #pragma clang diagnostic push 12 | #pragma clang diagnostic ignored "-Wunknown-warning-option" 13 | #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" 14 | #pragma clang diagnostic ignored "-Wnonportable-include-path" // Sharpmake convert include path to lowercase, avoid warning 15 | #pragma clang diagnostic ignored "-Wreserved-identifier" // Enuma values using '__' or member starting with '_' in imgui.h 16 | 17 | //================================================================================================= 18 | // Visual Studio warnings 19 | //================================================================================================= 20 | #elif defined(_MSC_VER) 21 | #pragma warning (push) 22 | #pragma warning (disable: 4514) // 'xxx': unreferenced inline function has been removed 23 | #pragma warning (disable: 4365) // '=': conversion from 'ImGuiTabItemFlags' to 'ImGuiID', signed/unsigned mismatch 24 | #pragma warning (disable: 4710) // 'xxx': function not inlined 25 | #pragma warning (disable: 4820) // 'xxx': 'yyy' bytes padding added after data member 'zzz' 26 | #pragma warning (disable: 5031) // #pragma warning(pop): likely mismatch, popping warning state pushed in different file 27 | #pragma warning (disable: 5045) // Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified 28 | #if _MSC_VER >= 1920 29 | #pragma warning (disable: 5219) // implicit conversion from 'int' to 'float', possible loss of data 30 | #endif 31 | #pragma warning (disable: 26495) // Code Analysis warning : Variable 'ImGuiStorage::ImGuiStoragePair::::val_p' is uninitialized. Always initialize a member variable (type.6). 32 | #endif 33 | 34 | -------------------------------------------------------------------------------- /Code/Client/Private/NetImgui_WarningDisableStd.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // 3 | // Deactivate a few more warnings to allow standard header includes, 4 | // without generating warnings in '-Wall' compile actions enabled 5 | // 6 | 7 | #include "NetImgui_WarningDisable.h" 8 | 9 | //================================================================================================= 10 | // Clang 11 | //================================================================================================= 12 | #if defined (__clang__) 13 | 14 | 15 | //================================================================================================= 16 | // Visual Studio warnings 17 | //================================================================================================= 18 | #elif defined(_MSC_VER) 19 | #pragma warning (disable: 4061) // enumerator xxx in switch of enum yyy is not explicitly handled by a case label (d3d11.h) 20 | #pragma warning (disable: 4548) // expression before comma has no effect; expected expression with side - effect (malloc.h VS2017) 21 | #pragma warning (disable: 4668) // xxx is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' (winsock2.h) 22 | #pragma warning (disable: 4574) // xxx is defined to be '0': did you mean to use yyy (winsock2.h VS2017) 23 | #pragma warning (disable: 4820) // xxx : yyy bytes padding added after data member zzz 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /Code/Client/Private/NetImgui_WarningReenable.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | //================================================================================================= 5 | // Clang 6 | //================================================================================================= 7 | #if defined(__clang__) 8 | #pragma clang diagnostic pop 9 | 10 | 11 | //================================================================================================= 12 | // Visual Studio warnings 13 | //================================================================================================= 14 | #elif defined(_MSC_VER) 15 | #pragma warning(pop) 16 | #endif 17 | 18 | 19 | -------------------------------------------------------------------------------- /Code/Sample/Common/Sample.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // Forward declares when NetImgui is not enabled 6 | #if !NETIMGUI_ENABLED 7 | struct ImGuiContext; 8 | struct ImDrawData; 9 | namespace NetImgui 10 | { 11 | using ThreadFunctPtr = void*; 12 | using FontCreateFuncPtr = void*; 13 | } 14 | #endif 15 | 16 | namespace Sample 17 | { 18 | 19 | class Base 20 | { 21 | public: 22 | Base(const char* sampleName); //!< Constructor receiving pointer to constant string that must remains valid 23 | virtual bool Startup(); //!< Called once when starting 24 | virtual void Shutdown(); //!< Called once when exiting 25 | virtual bool UpdateFont(float fontScaleDPI, bool isLocal); //!< Receive command to create/update the Font Atlas and its texture data 26 | virtual ImDrawData* Draw() = 0; //!< Each sample should have their Dear ImGui drawing routines in this overloaded method 27 | 28 | protected: 29 | void Draw_Connect(); //!< Display UI for initiating a connection to the remote NetImgui server application 30 | const char* mSampleName = nullptr; //!< Name displayed in the Main Menu bar (must receive string pointer in constructor that remains valid) 31 | ImGuiContext* mpContextMain = nullptr; //!< Pointer to main context created in main.cpp (used to detect when to update font texture) 32 | ImGuiContext* mpContextLocal = nullptr; //!< Pointer to context used for local draw. Most sample leave it to the same as mpContextMain (used to detect when to update font texture) 33 | NetImgui::ThreadFunctPtr mCallback_ThreadLaunch = nullptr; //!< [Optional] Thread launcher callback assigned on NetImgui connection. Used to start a new thread for coms with NetImgui server 34 | NetImgui::FontCreateFuncPtr mCallback_FontGenerate = nullptr; //!< [Optional] Font generation callback assigned on NetImgui connection. Used to adjust the font data to remote server DPI 35 | float mGeneratedFontScaleDPI = 0.f; //!< Current generated font texture DPI 36 | bool mbShowDemoWindow = false; //!< If we should show the Dear ImGui demo window 37 | char mConnect_HostnameServer[128] = {"localhost"}; //!< IP/Hostname used to send a connection request when when trying to reach the server 38 | int mConnect_PortServer = 0; //!< Port used to send a connection request when when trying to reach the server 39 | int mConnect_PortClient = 0; //!< Port opened when waiting for a server connection request 40 | }; 41 | 42 | //============================================================================= 43 | // The _s string functions are a mess. There's really no way to do this right 44 | // in a cross-platform way. Best solution I've found is to just use strncpy, 45 | // infer the buffer length, and null terminate. Still need to suppress 46 | // the warning on Windows. 47 | // See https://randomascii.wordpress.com/2013/04/03/stop-using-strncpy-already/ 48 | // and many other discussions online on the topic. 49 | //============================================================================= 50 | template 51 | inline void StringCopy(char (&output)[charCount], const char* pSrc, size_t srcCharCount=0xFFFFFFFE) 52 | { 53 | #if defined(__clang__) 54 | #pragma clang diagnostic push 55 | #pragma clang diagnostic ignored "-Wdeprecated-declarations" 56 | #elif defined(_MSC_VER) 57 | #pragma warning (push) 58 | #pragma warning (disable: 4996) // warning C4996: 'strncpy': This function or variable may be unsafe. 59 | #endif 60 | 61 | size_t charToCopyCount = charCount < srcCharCount + 1 ? charCount : srcCharCount + 1; 62 | strncpy(output, pSrc, charToCopyCount - 1); 63 | output[charCount - 1] = 0; 64 | 65 | #if defined(_MSC_VER) && defined(__clang__) 66 | #pragma clang diagnostic pop 67 | #elif defined(_MSC_VER) 68 | #pragma warning (pop) 69 | #endif 70 | } 71 | 72 | #if NETIMGUI_ENABLED 73 | 74 | union TextureCastHelperUnion 75 | { 76 | ImTextureID TextureID; 77 | uint64_t TextureUint; 78 | const void* TexturePtr; 79 | }; 80 | 81 | inline uint64_t TextureCastFromID(ImTextureID textureID) 82 | { 83 | TextureCastHelperUnion textureUnion; 84 | textureUnion.TextureUint = 0; 85 | textureUnion.TextureID = textureID; 86 | return textureUnion.TextureUint; 87 | } 88 | 89 | inline ImTextureID TextureCastFromPtr(void* pTexture) 90 | { 91 | TextureCastHelperUnion textureUnion; 92 | textureUnion.TextureUint = 0; 93 | textureUnion.TexturePtr = pTexture; 94 | return textureUnion.TextureID; 95 | } 96 | 97 | inline ImTextureID TextureCastFromUInt(uint64_t textureID) 98 | { 99 | TextureCastHelperUnion textureUnion; 100 | textureUnion.TextureUint = textureID; 101 | return textureUnion.TextureID; 102 | } 103 | #endif // NETIMGUI_ENABLED 104 | 105 | }; // namespace Sample 106 | 107 | Sample::Base& GetSample(); // Each Sample must implement this function and return a valid sample object 108 | 109 | #include 110 | -------------------------------------------------------------------------------- /Code/Sample/SampleBackground/SampleBackground.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================================= 2 | // SAMPLE BACKGROUND 3 | //------------------------------------------------------------------------------------------------- 4 | // Example of using the NetImgui 'Background' setting 5 | //================================================================================================= 6 | 7 | #include 8 | #include 9 | #include 10 | #include "../Common/Sample.h" 11 | 12 | // Methods declared in main.cpp, extern declare to avoid having to include 'd3d11.h' here 13 | extern void TextureCreate(const uint8_t* pPixelData, uint32_t width, uint32_t height, void*& pTextureViewOut); 14 | extern void TextureDestroy(void*& pTextureView); 15 | 16 | //================================================================================================= 17 | // SAMPLE CLASS 18 | //================================================================================================= 19 | class SampleBackground : public Sample::Base 20 | { 21 | public: 22 | SampleBackground() : Base("SampleBackground") {} 23 | virtual bool Startup() override; 24 | virtual void Shutdown() override; 25 | virtual ImDrawData* Draw() override; 26 | protected: 27 | void* mTextureView = nullptr; 28 | }; 29 | 30 | //================================================================================================= 31 | // GET SAMPLE 32 | // Each project must return a valid sample object 33 | //================================================================================================= 34 | Sample::Base& GetSample() 35 | { 36 | static SampleBackground sample; 37 | return sample; 38 | }; 39 | 40 | //================================================================================================= 41 | // STARTUP 42 | //================================================================================================= 43 | bool SampleBackground::Startup() 44 | { 45 | if (!Base::Startup()) 46 | return false; 47 | 48 | constexpr uint16_t kSize = 256; 49 | constexpr float kFadeSize = 16.f; 50 | uint32_t pixels[kSize][kSize]; 51 | for (uint32_t y(0); y < kSize; ++y) { 52 | for (uint32_t x(0); x < kSize; ++x) 53 | { 54 | float offsetX = static_cast(x) - static_cast(kSize/2); 55 | float offsetY = static_cast(y) - static_cast(kSize/2); 56 | float radius = static_cast(sqrt(offsetX*offsetX+offsetY*offsetY)); 57 | float alpha = 1.f - std::min(1.f, std::max(0.f, (radius - (static_cast(kSize/2)-kFadeSize))) / kFadeSize); 58 | pixels[y][x] = ImColor( static_cast(x), static_cast(y), (x+y) <= 255 ? 0 : 255-(x+y), static_cast(255.f*alpha)); 59 | } 60 | } 61 | TextureCreate(reinterpret_cast(pixels), kSize, kSize, mTextureView); // For local display 62 | NetImgui::SendDataTexture(Sample::TextureCastFromPtr(mTextureView), pixels, kSize, kSize, NetImgui::eTexFormat::kTexFmtRGBA8); // For remote display 63 | return true; 64 | } 65 | 66 | //================================================================================================= 67 | // SHUTDOWN 68 | //================================================================================================= 69 | void SampleBackground::Shutdown() 70 | { 71 | TextureDestroy(mTextureView); 72 | NetImgui::Shutdown(); 73 | } 74 | 75 | //================================================================================================= 76 | // DRAW 77 | //================================================================================================= 78 | ImDrawData* SampleBackground::Draw() 79 | { 80 | //--------------------------------------------------------------------------------------------- 81 | // (1) Start a new Frame 82 | //--------------------------------------------------------------------------------------------- 83 | if (NetImgui::NewFrame(true)) 84 | { 85 | //----------------------------------------------------------------------------------------- 86 | // (2) Draw ImGui Content 87 | //----------------------------------------------------------------------------------------- 88 | Base::Draw_Connect(); //Note: Connection to remote server done in there 89 | 90 | ImGui::SetNextWindowPos(ImVec2(32, 48), ImGuiCond_Once); 91 | ImGui::SetNextWindowSize(ImVec2(400, 400), ImGuiCond_Once); 92 | if (ImGui::Begin("Sample Background", nullptr)) 93 | { 94 | ImGui::TextColored(ImVec4(0.1, 1, 0.1, 1), "Demonstration of NetImgui's Background settings."); 95 | static ImVec4 sBgColor(0.2f,0.2f,0.2f,1.f); 96 | static ImVec4 sTextureTint(1,1,1,0.5f); 97 | static bool sUseTextureOverride(false); 98 | 99 | ImGui::ColorEdit4("Background", reinterpret_cast(&sBgColor), ImGuiColorEditFlags_Float | ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_PickerHueWheel); 100 | ImGui::ColorEdit4("Logo Tint", reinterpret_cast(&sTextureTint), ImGuiColorEditFlags_Float | ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_PickerHueWheel); 101 | ImGui::Checkbox("Replace Background Texture", &sUseTextureOverride); 102 | ImGui::Image(ImTextureID(mTextureView), ImVec2(64,64)); 103 | ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.5f, 0.5f, 0.5f, 1.f)); 104 | ImGui::TextWrapped("(Note: Custom background settings only applied on remote server)"); 105 | ImGui::PopStyleColor(); 106 | if( sUseTextureOverride ) 107 | { 108 | NetImgui::SetBackground(sBgColor, sTextureTint, Sample::TextureCastFromPtr(mTextureView)); 109 | } 110 | else 111 | { 112 | NetImgui::SetBackground(sBgColor, sTextureTint); 113 | } 114 | } 115 | ImGui::End(); 116 | 117 | //----------------------------------------------------------------------------------------- 118 | // (3) Finish the frame, preparing the drawing data and... 119 | // (3a) Send the data to the netImGui server when connected 120 | //----------------------------------------------------------------------------------------- 121 | NetImgui::EndFrame(); 122 | } 123 | 124 | //--------------------------------------------------------------------------------------------- 125 | // (4b) Render nothing locally (when connected) 126 | //--------------------------------------------------------------------------------------------- 127 | return !NetImgui::IsConnected() ? ImGui::GetDrawData() : nullptr; 128 | } 129 | 130 | -------------------------------------------------------------------------------- /Code/Sample/SampleBasic/SampleBasic.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================================= 2 | // SAMPLE BASIC 3 | //------------------------------------------------------------------------------------------------- 4 | // Barebone example of adding NetImgui to a code base. This demonstrate how little changes 5 | // are needed to be up and running. 6 | //================================================================================================= 7 | 8 | #include 9 | #include "../Common/Sample.h" 10 | 11 | //================================================================================================= 12 | // SAMPLE CLASS 13 | //================================================================================================= 14 | class SampleBasic : public Sample::Base 15 | { 16 | public: 17 | SampleBasic() : Base("SampleBasic") {} 18 | virtual ImDrawData* Draw() override; 19 | }; 20 | 21 | //================================================================================================= 22 | // GET SAMPLE 23 | // Each project must return a valid sample object 24 | //================================================================================================= 25 | Sample::Base& GetSample() 26 | { 27 | static SampleBasic sample; 28 | return sample; 29 | } 30 | 31 | //================================================================================================= 32 | // DRAW 33 | //================================================================================================= 34 | ImDrawData* SampleBasic::Draw() 35 | { 36 | //--------------------------------------------------------------------------------------------- 37 | // (1) Start a new Frame. 38 | // Note: With ImGui 1.81+ NetImgui can automatically intercept Imgui::NewFrame/Render. This 39 | // sample does this. For older Imgui releases, please look at 'Client_Draw_ModeAlways' 40 | // in 'SampleNewFrame' on how to tell NetImgui directly about NewFrame/EndFrame. 41 | // Other samples also avoid the auto intercept to allow drawing only when needed. 42 | //--------------------------------------------------------------------------------------------- 43 | ImGui::NewFrame(); 44 | 45 | //----------------------------------------------------------------------------------------- 46 | // (2) Draw ImGui Content 47 | //----------------------------------------------------------------------------------------- 48 | Base::Draw_Connect(); //Note: Connection to remote server done in there 49 | 50 | //Note: Some dummy text content 51 | ImGui::SetNextWindowPos(ImVec2(32,48), ImGuiCond_Once); 52 | ImGui::SetNextWindowSize(ImVec2(400,400), ImGuiCond_Once); 53 | if( ImGui::Begin("Sample Basic", nullptr) ) 54 | { 55 | ImGui::TextColored(ImVec4(0.1, 1, 0.1, 1), "Basic demonstration of NetImgui code integration."); 56 | ImGui::TextWrapped("Create a basic Window with some text."); 57 | ImGui::NewLine(); 58 | ImGui::TextColored(ImVec4(0.1, 1, 0.1, 1), "Where are we drawing: "); 59 | ImGui::SameLine(); 60 | ImGui::TextUnformatted(NetImgui::IsDrawingRemote() ? "Remote Draw" : "Local Draw"); 61 | ImGui::NewLine(); 62 | ImGui::TextColored(ImVec4(0.1, 1, 0.1, 1), "Filler content"); 63 | ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."); 64 | } 65 | ImGui::End(); 66 | 67 | //--------------------------------------------------------------------------------------------- 68 | // (3) Finish the frame 69 | // Note: Same note as in (1) 70 | //--------------------------------------------------------------------------------------------- 71 | ImGui::Render(); 72 | 73 | //--------------------------------------------------------------------------------------------- 74 | // (4) Return content to draw by local renderer. Stop drawing locally when remote connected 75 | //--------------------------------------------------------------------------------------------- 76 | return !NetImgui::IsConnected() ? ImGui::GetDrawData() : nullptr; 77 | } 78 | -------------------------------------------------------------------------------- /Code/Sample/SampleDisabled/SampleDisabled.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================================= 2 | // SAMPLE DISABLED 3 | //------------------------------------------------------------------------------------------------- 4 | // This sample demonstrate compiling your code with netImgui disabled but ImGui still active. 5 | // It relies on the Define 'NETIMGUI_ENABLED' assigned in the project properties to compile 6 | // with NetImfui inactive. 7 | //================================================================================================= 8 | 9 | #include 10 | // Since NetImgui is disabled in this sample, NetImgui_Api.h will not include this header, 11 | // so must include it manually 12 | #include "imgui.h" 13 | 14 | #include "../Common/Sample.h" 15 | 16 | //================================================================================================= 17 | // SAMPLE CLASS 18 | //================================================================================================= 19 | class SampleDisabled : public Sample::Base 20 | { 21 | public: 22 | SampleDisabled() : Base("SampleDisabled") {} 23 | virtual ImDrawData* Draw() override; 24 | }; 25 | 26 | //================================================================================================= 27 | // GET SAMPLE 28 | // Each project must return a valid sample object 29 | //================================================================================================= 30 | Sample::Base& GetSample() 31 | { 32 | static SampleDisabled sample; 33 | return sample; 34 | } 35 | 36 | //================================================================================================= 37 | // DRAW 38 | //================================================================================================= 39 | ImDrawData* SampleDisabled::Draw() 40 | { 41 | //--------------------------------------------------------------------------------------------- 42 | // (1) Start a new Frame 43 | //--------------------------------------------------------------------------------------------- 44 | ImGui::NewFrame(); 45 | 46 | //----------------------------------------------------------------------------------------- 47 | // (2) Draw ImGui Content 48 | //----------------------------------------------------------------------------------------- 49 | Base::Draw_Connect(); //Note: Connection to remote server done in there 50 | 51 | ImGui::SetNextWindowPos(ImVec2(32,48), ImGuiCond_Once); 52 | ImGui::SetNextWindowSize(ImVec2(400,400), ImGuiCond_Once); 53 | if( ImGui::Begin("Sample Disabled", nullptr) ) 54 | { 55 | ImGui::TextColored(ImVec4(0.1, 1, 0.1, 1), "Compiling with netImgui Disabled."); 56 | ImGui::TextWrapped( "This shows being able to continue using ImGui normally, while netImgui code has been disabled. " 57 | "No connection with the remote netImgui will be possible since the client code is entirely ifdef out "); 58 | ImGui::NewLine(); 59 | ImGui::TextColored(ImVec4(0.1, 1, 0.1, 1), "Filler content"); 60 | ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."); 61 | } 62 | ImGui::End(); 63 | 64 | //--------------------------------------------------------------------------------------------- 65 | // (3) Finish the frame, preparing the drawing data and... 66 | //--------------------------------------------------------------------------------------------- 67 | ImGui::Render(); 68 | 69 | //--------------------------------------------------------------------------------------------- 70 | // (4) Forward to drawing data our local renderer when not remotely drawing 71 | //--------------------------------------------------------------------------------------------- 72 | return ImGui::GetDrawData(); 73 | } 74 | 75 | -------------------------------------------------------------------------------- /Code/Sample/SampleIndex/SampleIndex.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================================= 2 | // SAMPLE INDEX 16/32Bits 3 | //------------------------------------------------------------------------------------------------- 4 | // Sample testing render of large amount of shapes, pushing the vertices count past the 65k 5 | // limit of 16bits indices. 6 | // 7 | // Note: This source file is compiled under 2 samples projects, one with Dear ImGui using 8 | // 16bits indices and the other one using 32 bits indices. 9 | // 10 | // Note: This sample is meant as a UnitTest ensuring large draws amount is handled properly on 11 | // NetImgui Server application 12 | //================================================================================================= 13 | 14 | #include 15 | #include 16 | #include "../Common/Sample.h" 17 | 18 | //================================================================================================= 19 | // SAMPLE CLASS 20 | //================================================================================================= 21 | class SampleIndex : public Sample::Base 22 | { 23 | public: 24 | SampleIndex() : Base(sizeof(ImDrawIdx) == 2 ? "SampleIndex16Bits" : "SampleIndex32Bits") {} 25 | virtual ImDrawData* Draw() override; 26 | }; 27 | 28 | //================================================================================================= 29 | // GET SAMPLE 30 | // Each project must return a valid sample object 31 | //================================================================================================= 32 | Sample::Base& GetSample() 33 | { 34 | static SampleIndex sample; 35 | return sample; 36 | } 37 | 38 | //================================================================================================= 39 | // Function used by the sample, to draw all ImGui Content 40 | //================================================================================================= 41 | ImDrawData* SampleIndex::Draw() 42 | { 43 | //--------------------------------------------------------------------------------------------- 44 | // (1) Start a new Frame 45 | //--------------------------------------------------------------------------------------------- 46 | if (NetImgui::NewFrame(true)) 47 | { 48 | //----------------------------------------------------------------------------------------- 49 | // (2) Draw ImGui Content 50 | //----------------------------------------------------------------------------------------- 51 | Base::Draw_Connect(); //Note: Connection to remote server done in there 52 | 53 | ImGui::SetNextWindowPos(ImVec2(32, 48), ImGuiCond_Once); 54 | ImGui::SetNextWindowSize(ImVec2(525, 820), ImGuiCond_Once); 55 | if (ImGui::Begin("Sample Index", nullptr)) 56 | { 57 | ImGui::TextColored(ImVec4(0.1, 1, 0.1, 1), "Large amount of mesh drawing."); 58 | ImGui::TextWrapped("This sample is meant as a UnitTest ensuring large draws amount is handled properly on NetImgui Server application"); 59 | ImGui::NewLine(); 60 | 61 | static size_t sIndexSize = sizeof(ImDrawIdx); // Using a static value to prevent VS warning :/ (C4127: Conditional Expression is Constant) 62 | if( sIndexSize == 2 ){ 63 | ImGui::TextWrapped("Note: This sample uses Dear ImGui compiled with 16bits indices. Meaning that each draw will be splitted in multiple drawcalls of less than 65k vertices each."); 64 | } 65 | else { 66 | ImGui::TextWrapped("Note: This sample uses Dear ImGui compiled with 32bits indices. Meaning that each draw can be sent as a single drawcall, even when having more than 65k vertices."); 67 | } 68 | 69 | ImGui::NewLine(); 70 | 71 | ImDrawList* draw_list = ImGui::GetWindowDrawList(); 72 | const ImVec2 winPos = ImGui::GetCursorScreenPos(); 73 | constexpr float th = 3.f;//(n == 0) ? 1.0f : thickness; 74 | constexpr int segments = 64; 75 | constexpr float size = 16.f; 76 | constexpr float spacing = 4.f; 77 | for (float y(0); y < 25.f; y++) { 78 | for (float x(0); x < 25.f; x++) { 79 | float posX = winPos.x + (x + 0.5f)*(size + spacing); 80 | float posY = winPos.y + (y + 0.5f)*(size + spacing); 81 | draw_list->AddCircle(ImVec2(posX, posY), size*0.5f, ImColor(1.f,1.f,1.f,1.f), segments, th); 82 | } 83 | } 84 | } 85 | ImGui::End(); 86 | 87 | 88 | //----------------------------------------------------------------------------------------- 89 | // (3) Finish the frame, preparing the drawing data and... 90 | // (3a) Send the data to the netImGui server when connected 91 | //----------------------------------------------------------------------------------------- 92 | NetImgui::EndFrame(); 93 | } 94 | 95 | //--------------------------------------------------------------------------------------------- 96 | // (4b) Render nothing locally (when connected) 97 | //--------------------------------------------------------------------------------------------- 98 | return !NetImgui::IsConnected() ? ImGui::GetDrawData() : nullptr; 99 | } 100 | -------------------------------------------------------------------------------- /Code/Sample/SampleNewFrame/SampleNewFrame.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================================= 2 | // SAMPLE NEW FRAME 3 | //------------------------------------------------------------------------------------------------- 4 | // Example of handling frame skipping. 5 | // When connected to NetImgui Server, we don't need to refresh the ImGui content every frame. 6 | // If your program can handle skipping drawing, saves CPU cycles when no refresh is expected. 7 | //================================================================================================= 8 | 9 | #include 10 | #include "../Common/Sample.h" 11 | 12 | //================================================================================================= 13 | // SAMPLE CLASS 14 | //================================================================================================= 15 | class SampleNewFrame : public Sample::Base 16 | { 17 | public: 18 | SampleNewFrame() : Base("SampleNewFrame") {} 19 | virtual ImDrawData* Draw() override; 20 | 21 | protected: 22 | enum class eDrawUpdateMode : int { Always, OnDemand }; 23 | void Draw_Content(); 24 | ImDrawData* Draw_ModeOnDemand(); 25 | ImDrawData* Draw_ModeAlways(); 26 | 27 | eDrawUpdateMode mFrameRefreshMode = eDrawUpdateMode::Always; 28 | uint32_t mFrameDrawnCount = 0; 29 | uint32_t mFrameSkippedCount = 0; 30 | }; 31 | 32 | //================================================================================================= 33 | // GET SAMPLE 34 | // Each project must return a valid sample object 35 | //================================================================================================= 36 | Sample::Base& GetSample() 37 | { 38 | static SampleNewFrame sample; 39 | return sample; 40 | } 41 | 42 | //================================================================================================= 43 | // Imgui content 44 | //================================================================================================= 45 | void SampleNewFrame::Draw_Content() 46 | { 47 | bool bModeChanged(false); 48 | 49 | Base::Draw_Connect(); //Note: Connection to remote server done in there 50 | 51 | ImGui::SetNextWindowPos(ImVec2(32,48), ImGuiCond_Once); 52 | ImGui::SetNextWindowSize(ImVec2(700,450), ImGuiCond_Once); 53 | if (ImGui::Begin("Sample NewFrame", nullptr)) 54 | { 55 | ImGui::TextColored(ImVec4(0.1, 1, 0.1, 1), "Demonstration of frame skip handling."); 56 | ImGui::TextWrapped( "Demonstrate how to reduce CPU usage by only redrawing ImGui content when needed. " 57 | "The netImgui remote server does not expect a UI refresh every frame, we can skip some redraw. " 58 | "When a codebase does not support skipping a frame, internally we just assign a placeholder " 59 | "ImGui context and discard the result."); 60 | 61 | ImGui::NewLine(); 62 | ImGui::AlignTextToFramePadding(); 63 | ImGui::TextUnformatted("Frame Refresh Mode :"); 64 | ImGui::SameLine(); bModeChanged |= ImGui::RadioButton("Always", reinterpret_cast(&mFrameRefreshMode), static_cast(eDrawUpdateMode::Always)); 65 | ImGui::SameLine(); bModeChanged |= ImGui::RadioButton("On Demand", reinterpret_cast(&mFrameRefreshMode), static_cast(eDrawUpdateMode::OnDemand)); 66 | if( bModeChanged ) 67 | mFrameDrawnCount = mFrameSkippedCount = 0; 68 | 69 | ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.75f,0.75f,0.75f,1.f)); 70 | ImGui::TextWrapped( NetImgui::IsDrawingRemote() ? "Note: The ratio of frames skipped depends on the 'Refresh Rate' configured in the Server's settings." 71 | : "Note: Frame skipping only happen when drawing for remote connection."); 72 | ImGui::PopStyleColor(); 73 | 74 | ImGui::NewLine(); 75 | ImGui::Text("Draw Count: %i", mFrameDrawnCount); 76 | ImGui::Text("Skip Count: %i", mFrameSkippedCount); 77 | ImGui::Text("Time Saved: %i%%", mFrameSkippedCount ? mFrameSkippedCount * 100 / (mFrameDrawnCount+mFrameSkippedCount) : 0); 78 | } 79 | ImGui::End(); 80 | } 81 | 82 | //================================================================================================= 83 | // Without Frame skip support. User redraw content every frame, even when netImgui doesn't 84 | // require a new drawframe 85 | //================================================================================================= 86 | ImDrawData* SampleNewFrame::Draw_ModeAlways() 87 | { 88 | //--------------------------------------------------------------------------------------------- 89 | // (1) Start a new Frame 90 | // If your codebase doesn't handle skipping drawing the menu for some frame 91 | // (either by not calling your Imgui 92 | //--------------------------------------------------------------------------------------------- 93 | NetImgui::NewFrame(false); 94 | 95 | //----------------------------------------------------------------------------------------- 96 | // (2) Draw ImGui Content 97 | //----------------------------------------------------------------------------------------- 98 | Draw_Content(); 99 | 100 | //--------------------------------------------------------------------------------------------- 101 | // (3) Finish the frame, preparing the drawing data and... 102 | // (3a) Send the data to the netImGui server when connected 103 | //--------------------------------------------------------------------------------------------- 104 | NetImgui::EndFrame(); 105 | mFrameDrawnCount++; 106 | 107 | //--------------------------------------------------------------------------------------------- 108 | // (4) Forward to drawing data our local renderer when not connected or 109 | // connected and wanting to mirror the remote content. 110 | //--------------------------------------------------------------------------------------------- 111 | return !NetImgui::IsConnected() ? ImGui::GetDrawData() : nullptr; 112 | } 113 | 114 | //============================================================================================= 115 | // With Frame skip support 116 | // This code path handle not rendering a frame when not needed. netImgui doesn't require 117 | // redrawing every frame. 118 | //============================================================================================= 119 | ImDrawData* SampleNewFrame::Draw_ModeOnDemand() 120 | { 121 | //--------------------------------------------------------------------------------------------- 122 | // (1) Start a new Frame 123 | // When 'NewFrame' returns false, we should skip drawing this frame 124 | // Note 1 : Key point is using the 'NewFrame()' return value to decide when to skip drawing 125 | // Note 2 : Instead of relying on 'NewFrame()' return value, 'IsDrawing()' can be queried 126 | // Note 3 : Frame skipping only happens when remote drawing 127 | // Note 4 : To enable this, we explicitly call NetImgui::NewFrame/EndFrame() instead of 128 | // relying on ImGui::NewFrame/Render interception by NetImgui. 129 | //--------------------------------------------------------------------------------------------- 130 | if (NetImgui::NewFrame(true)) 131 | { 132 | //----------------------------------------------------------------------------------------- 133 | // (2) Draw ImGui Content 134 | //----------------------------------------------------------------------------------------- 135 | Draw_Content(); 136 | 137 | //--------------------------------------------------------------------------------------------- 138 | // (3) Finish the frame, preparing the drawing data and... 139 | // (3a) Send the data to the netImGui server when connected 140 | //--------------------------------------------------------------------------------------------- 141 | NetImgui::EndFrame(); 142 | 143 | //--------------------------------------------------------------------------------------------- 144 | // (4) Forward to drawing data our local renderer when not connected or 145 | // connected and wanting to mirror the remote content. 146 | //--------------------------------------------------------------------------------------------- 147 | mFrameDrawnCount++; 148 | return !NetImgui::IsConnected() ? ImGui::GetDrawData() : nullptr; 149 | } 150 | 151 | mFrameSkippedCount++; 152 | return nullptr; 153 | } 154 | 155 | 156 | //================================================================================================= 157 | // Function used by the sample, to draw all ImGui Content 158 | //================================================================================================= 159 | ImDrawData* SampleNewFrame::Draw() 160 | { 161 | switch( mFrameRefreshMode ) 162 | { 163 | case eDrawUpdateMode::Always: return Draw_ModeAlways(); 164 | case eDrawUpdateMode::OnDemand: return Draw_ModeOnDemand(); 165 | } 166 | return nullptr; 167 | } 168 | 169 | -------------------------------------------------------------------------------- /Code/Sample/SampleNoBackend/SampleNoBackend.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================================= 2 | // SAMPLE NO BACKEND 3 | //------------------------------------------------------------------------------------------------- 4 | // Demonstration of using Dear ImGui without any Backend support. 5 | // This way, user can use DearImgui without any code needed for drawing / input management, 6 | // since it is all handled by the NetImgui remote server instead. Useful when this code 7 | // is running on hardward without any display and/or convenient input. 8 | // 9 | // Because we are not using any Backend code, this Sample is a little bit different from 10 | // the others. All of its code is included in this file (except for Dear ImGui sources) 11 | // and does not rely on some shared sample source file. 12 | // 13 | // This sample compile both 'Dear Imgui' and 'NetImgui' sources directly 14 | // (not using their project version in the solution) 15 | // 16 | // NOTE: This sample is also use in backward compatibility test with older Dear ImGui versions, 17 | // making it easier to compile Dear Imgui without any OS specific code (Backends) 18 | // 19 | // NOTE: This is also an excellent example of own little is needed to add NetImgui support 20 | // to a project. It doesn't handle Font DPI regeneration, keeping things simple. 21 | //================================================================================================= 22 | 23 | #include 24 | 25 | // By defining 'NETIMGUI_IMPLEMENTATION' before '#include ', you can tell the 26 | // library to pull all source files needed to compile NetImgui here. 27 | // 28 | // It should only be done in 1 source file (to avoid duplicate symbol at link time). 29 | // 30 | // Other location can still include 'NetImgui_Api.h', but without using the define 31 | // 32 | // Note: Another (more conventional) way of compiling 'NetImgui' with your code, 33 | // is to includes its sources file directly in your project. This single header include 34 | // approach was added for potential convenience, minimizing changes to a project, but 35 | // can prevent code change detection in these included files, when compiling. 36 | #define NETIMGUI_IMPLEMENTATION 37 | #include 38 | 39 | #include 40 | 41 | namespace SampleNoBackend 42 | { 43 | 44 | enum eSampleState : uint8_t { 45 | Start, 46 | Disconnected, 47 | Connected, 48 | }; 49 | 50 | //================================================================================================= 51 | // Initialize the Dear Imgui Context and the NetImgui library 52 | //================================================================================================= 53 | bool Client_Startup() 54 | { 55 | IMGUI_CHECKVERSION(); 56 | ImGui::CreateContext(); 57 | ImGuiIO& io = ImGui::GetIO(); 58 | io.Fonts->AddFontDefault(); 59 | io.Fonts->Build(); 60 | io.Fonts->SetTexID(0); 61 | io.DisplaySize = ImVec2(8,8); 62 | io.BackendFlags |= ImGuiBackendFlags_HasGamepad; // Enable NetImgui Gamepad support 63 | ImGui::StyleColorsDark(); 64 | 65 | if( !NetImgui::Startup() ) 66 | return false; 67 | 68 | return true; 69 | } 70 | 71 | //================================================================================================= 72 | // Release resources 73 | //================================================================================================= 74 | void Client_Shutdown() 75 | { 76 | NetImgui::Shutdown(); 77 | ImGui::DestroyContext(ImGui::GetCurrentContext()); 78 | } 79 | 80 | //================================================================================================= 81 | // Manage connection to NetImguiServer 82 | //================================================================================================= 83 | void Client_Connect(eSampleState& sampleState) 84 | { 85 | constexpr char zClientName[] = "SampleNoBackend (ImGui " IMGUI_VERSION ")"; 86 | if( sampleState == eSampleState::Start ) 87 | { 88 | printf("- Connecting to NetImguiServer to (127.0.0.1:%i)... ", NetImgui::kDefaultServerPort); 89 | NetImgui::ConnectToApp(zClientName, "localhost"); 90 | while( NetImgui::IsConnectionPending() ); 91 | bool bSuccess = NetImgui::IsConnected(); 92 | sampleState = bSuccess ? eSampleState::Connected : eSampleState::Disconnected; 93 | printf(bSuccess ? "Success\n" : "Failed\n"); 94 | if (!bSuccess) { 95 | printf("- Waiting for a connection from NetImguiServer on port %i... ", NetImgui::kDefaultClientPort); 96 | NetImgui::ConnectFromApp(zClientName); 97 | 98 | } 99 | } 100 | else if (sampleState == eSampleState::Disconnected && NetImgui::IsConnected()) 101 | { 102 | sampleState = eSampleState::Connected; 103 | printf("CONNECTED\n"); 104 | } 105 | else if (sampleState == eSampleState::Connected && !NetImgui::IsConnected()) 106 | { 107 | sampleState = eSampleState::Disconnected; 108 | printf("DISCONNECTED\n"); 109 | printf("- Waiting for a connection from NetImguiServer on port %i... ", NetImgui::kDefaultClientPort); 110 | NetImgui::ConnectFromApp(zClientName); 111 | } 112 | } 113 | 114 | //================================================================================================= 115 | // Render all of our Dear ImGui Content (when appropriate) 116 | //================================================================================================= 117 | void Client_Draw(bool& bQuit) 118 | { 119 | if( NetImgui::IsConnected() && NetImgui::NewFrame(true) ){ 120 | 121 | ImGui::ShowDemoWindow(); 122 | 123 | ImGui::SetNextWindowPos(ImVec2(32,48), ImGuiCond_Once); 124 | ImGui::SetNextWindowSize(ImVec2(400,400), ImGuiCond_Once); 125 | if( ImGui::Begin("Sample No Backend", nullptr) ) 126 | { 127 | ImGui::TextColored(ImVec4(0.1, 1, 0.1, 1), "Client:"); 128 | ImGui::TextUnformatted(" DearImgui Version: " IMGUI_VERSION); 129 | ImGui::TextUnformatted(" NetImgui Version: " NETIMGUI_VERSION); 130 | ImGui::TextUnformatted(""); ImGui::SameLine(); 131 | bQuit = ImGui::Button(" Quit "); 132 | if( ImGui::IsItemHovered() ) 133 | ImGui::SetTooltip("Terminate this sample."); 134 | ImGui::NewLine(); 135 | ImGui::TextColored(ImVec4(0.1, 1, 0.1, 1), "Description:"); 136 | ImGui::TextWrapped( "This sample demonstate the ability to use Dear ImGui without any Backend. " 137 | "Rely instead on NetImgui to remotely handle drawing and inputs. This avoids the need for rendering/input/window management code on the client itself."); 138 | } 139 | ImGui::End(); 140 | 141 | NetImgui::EndFrame(); 142 | } 143 | } 144 | 145 | } // namespace SampleNoBackend 146 | 147 | int main(int, char**) 148 | { 149 | printf("================================================================================\n"); 150 | printf(" NetImgui Sample: No Backend\n"); 151 | printf("================================================================================\n"); 152 | printf(" Demonstrate 'Dear ImGui' + 'NetImgui' for a UI displayed on a remote server.\n"); 153 | printf(" Dear ImGui : " IMGUI_VERSION "\n"); 154 | printf(" NetImgui : " NETIMGUI_VERSION "\n"); 155 | printf(" ['Ctrl + C' to quit]\n"); 156 | printf("--------------------------------------------------------------------------------\n"); 157 | if ( !SampleNoBackend::Client_Startup() ) { 158 | printf("Failed initializing NetImgui."); 159 | SampleNoBackend::Client_Shutdown(); 160 | return -1; 161 | } 162 | 163 | // Main loop 164 | bool bQuit = false; 165 | SampleNoBackend::eSampleState sampleState = SampleNoBackend::eSampleState::Start; 166 | while (!bQuit) 167 | { 168 | // Avoids high CPU/GPU usage by releasing this thread until enough time has passed 169 | static auto sLastTime = std::chrono::steady_clock::now(); 170 | std::chrono::duration elapsedSec = std::chrono::steady_clock::now() - sLastTime; 171 | if( elapsedSec.count() < 1.f/120.f ){ 172 | std::this_thread::sleep_for(std::chrono::microseconds(250)); 173 | continue; 174 | } 175 | sLastTime = std::chrono::steady_clock::now(); 176 | 177 | // Sample Update 178 | SampleNoBackend::Client_Connect(sampleState); 179 | SampleNoBackend::Client_Draw(bQuit); 180 | } 181 | 182 | // Cleanup 183 | SampleNoBackend::Client_Shutdown(); 184 | return 0; 185 | } 186 | -------------------------------------------------------------------------------- /Code/Sample/SampleSingleInclude/SampleSingleInclude.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================================= 2 | // SAMPLE Single Include 3 | //------------------------------------------------------------------------------------------------- 4 | // Identical to 'SampleBasic' except for how the NetImgui code is integrated to the project. 5 | // 6 | // Other samples use the 'NetImgui_Api.h' and link against a pre compiled 'NetImgui' library. 7 | // 8 | // By defining 'NETIMGUI_IMPLEMENTATION' before '#include ', you can tell the 9 | // library to pull all source files needed to compile NetImgui here. 10 | // 11 | // It should only be done in 1 source file (to avoid duplicate symbol at link time). 12 | // 13 | // Other location can still include 'NetImgui_Api.h', but without using the define 14 | // 15 | // Note: Another (more conventional) way of compiling 'NetImgui' with your code, 16 | // is to includes its sources file directly in your project. This single header include 17 | // approach was added for potential convenience, minimizing changes to a project, but 18 | // can prevent code change detection in these included files, when compiling. 19 | //================================================================================================= 20 | #define NETIMGUI_IMPLEMENTATION 21 | #include 22 | #include "../Common/Sample.h" 23 | 24 | //================================================================================================= 25 | // SAMPLE CLASS 26 | //================================================================================================= 27 | class SampleSingleInclude : public Sample::Base 28 | { 29 | public: 30 | SampleSingleInclude() : Base("SampleSingleInclude") {} 31 | virtual ImDrawData* Draw() override; 32 | }; 33 | 34 | //================================================================================================= 35 | // GET SAMPLE 36 | // Each project must return a valid sample object 37 | //================================================================================================= 38 | Sample::Base& GetSample() 39 | { 40 | static SampleSingleInclude sample; 41 | return sample; 42 | } 43 | 44 | //================================================================================================= 45 | // Function used by the sample, to draw all ImGui Content 46 | //================================================================================================= 47 | ImDrawData* SampleSingleInclude::Draw() 48 | { 49 | //--------------------------------------------------------------------------------------------- 50 | // (1) Start a new Frame. 51 | //--------------------------------------------------------------------------------------------- 52 | ImGui::NewFrame(); 53 | 54 | //----------------------------------------------------------------------------------------- 55 | // (2) Draw ImGui Content 56 | //----------------------------------------------------------------------------------------- 57 | Base::Draw_Connect(); //Note: Connection to remote server done in there 58 | 59 | ImGui::SetNextWindowPos(ImVec2(32,48), ImGuiCond_Once); 60 | ImGui::SetNextWindowSize(ImVec2(600,500), ImGuiCond_Once); 61 | if( ImGui::Begin("Sample Single Include", nullptr) ) 62 | { 63 | ImGui::TextColored(ImVec4(0.1, 1, 0.1, 1), "Basic demonstration of NetImgui code integration."); 64 | ImGui::TextWrapped("Create a basic Window with some text."); 65 | ImGui::NewLine(); 66 | ImGui::TextWrapped("Identical to SampleBasic, the only difference is how the client code was included in the project."); 67 | ImGui::NewLine(); 68 | ImGui::TextColored(ImVec4(0.1, 1, 0.1, 1), "Where are we drawing: "); 69 | ImGui::SameLine(); 70 | ImGui::TextUnformatted(NetImgui::IsDrawingRemote() ? "Remote Draw" : "Local Draw"); 71 | ImGui::NewLine(); 72 | ImGui::TextColored(ImVec4(0.1, 1, 0.1, 1), "Filler content"); 73 | ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."); 74 | } 75 | ImGui::End(); 76 | 77 | //--------------------------------------------------------------------------------------------- 78 | // (3) Finish the frame 79 | //--------------------------------------------------------------------------------------------- 80 | ImGui::Render(); 81 | 82 | //--------------------------------------------------------------------------------------------- 83 | // (4) Return content to draw by local renderer. Stop drawing locally when remote connected 84 | //--------------------------------------------------------------------------------------------- 85 | return !NetImgui::IsConnected() ? ImGui::GetDrawData() : nullptr; 86 | } 87 | -------------------------------------------------------------------------------- /Code/ServerApp/Background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sammyfreg/netImgui/47e7bf9059a5d551521cbaff61ea6bab902f7fcb/Code/ServerApp/Background.png -------------------------------------------------------------------------------- /Code/ServerApp/Source/Custom/NetImguiServer_App_Custom.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================================= 2 | // This file is meant to be edited by Library user, to add extra functionalities to 3 | // the NetImguiServer application. It allows to isolate custom user code without interferring 4 | // with NetImgui code updates. 5 | // 6 | // For now, it is used to handle user defined custom texture formats. 7 | //================================================================================================= 8 | 9 | #include "NetImguiServer_App.h" 10 | #include "NetImguiServer_RemoteClient.h" 11 | 12 | // Enable handling of a Custom Texture Format samples. 13 | // Only meant as an example, users are free to replace it with their own handling of 14 | // custom texture formats. Look for this define for implementation details. 15 | #define TEXTURE_CUSTOM_SAMPLE 1 16 | 17 | #if TEXTURE_CUSTOM_SAMPLE 18 | 19 | //================================================================================================= 20 | // This is our Custom texture data format, it must match when the NetImgui Client code send 21 | // It can be customized to anything needed, as long as Client/Server use the same content 22 | // For this sample, we rely on the struct size and a starting stamp to identify the custom data 23 | struct customTextureData1{ 24 | static constexpr uint64_t kStamp = 0x0123456789000001; 25 | uint64_t m_Stamp = kStamp; 26 | uint32_t m_ColorStart = 0; 27 | uint32_t m_ColorEnd = 0; 28 | }; 29 | 30 | struct customTextureData2{ 31 | static constexpr uint64_t kStamp = 0x0123456789000002; 32 | uint64_t m_Stamp = kStamp; 33 | uint64_t m_TimeUS = 0; 34 | }; 35 | //================================================================================================= 36 | #endif 37 | 38 | namespace NetImguiServer { namespace App 39 | { 40 | 41 | //================================================================================================= 42 | // This contains a sample of letting User create their own texture format, handling it on both 43 | // the NetImgui Client and the NetImgui Server side 44 | // 45 | // User are entirely free to manage custom texture content as they wish as long as it generates 46 | // a valid 'ServerTexture.mpHAL_Texture' GPU texture object for the Imgui Backend 47 | // 48 | // Sample was kept simple by reusing HAL_CreateTexture / HAL_DestroyTexture when updating 49 | // the texture, but User is free to create valid texture without these functions 50 | // 51 | //------------------------------------------------------------------------------------------------- 52 | // Return true if the command was handled 53 | //================================================================================================= 54 | bool CreateTexture_Custom( ServerTexture& serverTexture, const NetImgui::Internal::CmdTexture& cmdTexture, uint32_t customDataSize ) 55 | { 56 | IM_UNUSED(serverTexture); 57 | IM_UNUSED(cmdTexture); 58 | IM_UNUSED(customDataSize); 59 | #if TEXTURE_CUSTOM_SAMPLE 60 | auto eTexFmt = static_cast(cmdTexture.mFormat); 61 | if( eTexFmt == NetImgui::eTexFormat::kTexFmtCustom ){ 62 | 63 | // Process Custom Texture Type 1 64 | // This sample custom texture interpolate between 2 colors over the x axis 65 | const customTextureData1* pCustomData1 = reinterpret_cast(cmdTexture.mpTextureData.Get()); 66 | if( customDataSize == sizeof(customTextureData1) && pCustomData1->m_Stamp == customTextureData1::kStamp ) 67 | { 68 | ImColor colorStart = pCustomData1->m_ColorStart; 69 | ImColor colorEnd = pCustomData1->m_ColorEnd; 70 | uint32_t* pTempData = static_cast(malloc((size_t)cmdTexture.mWidth*(size_t)cmdTexture.mHeight*sizeof(uint32_t))); 71 | for(uint32_t x=0; pTempData && x(x) / static_cast(cmdTexture.mWidth); 73 | ImColor colorCurrent = ImColor( colorStart.Value.x * ratio + colorEnd.Value.x * (1.f - ratio), 74 | colorStart.Value.y * ratio + colorEnd.Value.y * (1.f - ratio), 75 | colorStart.Value.z * ratio + colorEnd.Value.z * (1.f - ratio), 76 | colorStart.Value.w * ratio + colorEnd.Value.w * (1.f - ratio)); 77 | for(uint32_t y=0; y(pTempData), serverTexture); 82 | free(pTempData); 83 | 84 | // Assign a custom texture information to the Server Texture 85 | // Here, it's just a stamp, but could be some user specific data, like allocated memory for extra info 86 | serverTexture.mCustomData = customTextureData1::kStamp; 87 | return true; 88 | } 89 | 90 | // Process Custom Texture Type 2 91 | // This sample custom texture display a moving sin wave 92 | const customTextureData2* pCustomData2 = reinterpret_cast(cmdTexture.mpTextureData.Get()); 93 | if( customDataSize == sizeof(customTextureData2) && pCustomData2->m_Stamp == customTextureData2::kStamp ) 94 | { 95 | uint32_t* pTempData = static_cast(malloc((size_t)cmdTexture.mWidth*(size_t)cmdTexture.mHeight*sizeof(uint32_t))); 96 | for(uint32_t x=0; pTempData && x(x) / static_cast(cmdTexture.mWidth); 100 | uint64_t timeRatio = pCustomData2->m_TimeUS % kLoopTimeUS; 101 | float sinRatio = (static_cast(timeRatio) / static_cast(kLoopTimeUS) + ratioX) * 3.1415f * 2.0f; 102 | float sinVal = static_cast(sin(sinRatio)); 103 | for(uint32_t y=0; y(y) / static_cast(cmdTexture.mHeight) * 2.f - 1.f; 105 | float dist = sinVal - ratioY; 106 | float r = dist > 0.f ? 1.f - dist/2.f : 0.f; 107 | float b = dist < 0.f ? 1.f + dist/2.f : 0.f; 108 | ImColor colorCurrent = ImColor(r, 0.f, b, 1.f); 109 | pTempData[y*static_cast(cmdTexture.mWidth)+x] = (ImU32)colorCurrent; 110 | } 111 | } 112 | NetImguiServer::App::HAL_CreateTexture(cmdTexture.mWidth, cmdTexture.mHeight, NetImgui::eTexFormat::kTexFmtRGBA8, reinterpret_cast(pTempData), serverTexture); 113 | free(pTempData); 114 | // Assign a custom texture information to the Server Texture 115 | // Here, it's just a stamp, but could be some user specific data, like allocated memory for extra info 116 | serverTexture.mCustomData = customTextureData2::kStamp; 117 | return true; 118 | } 119 | } 120 | #endif 121 | return false; 122 | } 123 | 124 | //================================================================================================= 125 | // Return true if the command was handled 126 | bool DestroyTexture_Custom( ServerTexture& serverTexture, const NetImgui::Internal::CmdTexture& cmdTexture, uint32_t customDataSize ) 127 | //================================================================================================= 128 | { 129 | IM_UNUSED(serverTexture); 130 | IM_UNUSED(cmdTexture); 131 | IM_UNUSED(customDataSize); 132 | 133 | #if TEXTURE_CUSTOM_SAMPLE 134 | if( serverTexture.mpHAL_Texture && serverTexture.mFormat == NetImgui::eTexFormat::kTexFmtCustom ){ 135 | if( serverTexture.mCustomData == customTextureData1::kStamp || 136 | serverTexture.mCustomData == customTextureData2::kStamp ) 137 | { 138 | // Could decide to only update the texture instead of recreating it 139 | // But this sample just delete it (like default behavior) 140 | if ( serverTexture.mFormat == cmdTexture.mFormat && 141 | serverTexture.mSize[0] == cmdTexture.mWidth && 142 | serverTexture.mSize[1] == cmdTexture.mHeight ) 143 | { 144 | NetImguiServer::App::EnqueueHALTextureDestroy(serverTexture); 145 | return true; 146 | } 147 | // Texture format changed or requested to be deleted 148 | else 149 | { 150 | NetImguiServer::App::EnqueueHALTextureDestroy(serverTexture); 151 | return true; 152 | } 153 | } 154 | } 155 | #endif 156 | return false; 157 | } 158 | 159 | } } //namespace NetImguiServer { namespace App 160 | -------------------------------------------------------------------------------- /Code/ServerApp/Source/GlfwGL3/NetImguiServer_HAL_GL3.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================================= 2 | // Source file handling renderer specific commands needed by NetImgui server. 3 | // It complement the rendering backend with a few more functionalities. 4 | // 5 | // @note: Thank you to github user A3Wypiok, for a lot of the OpenGL found in this file 6 | //================================================================================================= 7 | #include "NetImguiServer_App.h" 8 | 9 | #if HAL_API_PLATFORM_GLFW_GL3 10 | 11 | #include "NetImguiServer_RemoteClient.h" 12 | #include 13 | #include 14 | 15 | namespace NetImguiServer { namespace App 16 | { 17 | //================================================================================================= 18 | // HAL RENDER DRAW DATA 19 | // The drawing of remote clients is handled normally by the standard rendering backend, 20 | // but output is redirected to an allocated client texture instead default swapchain 21 | //================================================================================================= 22 | void HAL_RenderDrawData(RemoteClient::Client& client, ImDrawData* pDrawData) 23 | { 24 | if( client.mpHAL_AreaRT ) 25 | { 26 | glBindFramebuffer(GL_FRAMEBUFFER, static_cast(reinterpret_cast(client.mpHAL_AreaRT))); 27 | glClearColor(client.mBGSettings.mClearColor[0], client.mBGSettings.mClearColor[1], client.mBGSettings.mClearColor[2], client.mBGSettings.mClearColor[3]); 28 | glClear(GL_COLOR_BUFFER_BIT); 29 | { 30 | void* mainBackend = ImGui::GetIO().BackendRendererUserData; 31 | NetImgui::Internal::ScopedImguiContext scopedCtx(client.mpBGContext); 32 | ImGui::GetIO().BackendRendererUserData = mainBackend; // Re-appropriate the existing renderer backend, for this client rendeering 33 | ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); 34 | } 35 | if (pDrawData) 36 | { 37 | ImGui_ImplOpenGL3_RenderDrawData(pDrawData); 38 | } 39 | glBindFramebuffer(GL_FRAMEBUFFER, 0); 40 | } 41 | } 42 | 43 | //================================================================================================= 44 | // HAL CREATE RENDER TARGET 45 | // Allocate RenderTargetView / TextureView for each connected remote client. 46 | // The drawing of their menu content will be outputed in it, then displayed normally 47 | // inside our own 'NetImGui application' Imgui drawing 48 | //================================================================================================= 49 | bool HAL_CreateRenderTarget(uint16_t Width, uint16_t Height, void*& pOutRT, void*& pOutTexture) 50 | { 51 | HAL_DestroyRenderTarget(pOutRT, pOutTexture); 52 | 53 | GLuint pTextureView = 0u; 54 | glGenTextures(1, &pTextureView); 55 | glBindTexture(GL_TEXTURE_2D, pTextureView); 56 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 57 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 58 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 59 | 60 | GLuint pRenderTargetView = 0u; 61 | glGenFramebuffers(1, &pRenderTargetView); 62 | glBindFramebuffer(GL_FRAMEBUFFER, pRenderTargetView); 63 | 64 | //Attach 2D texture to this FBO 65 | glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pTextureView, 0); 66 | 67 | GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); 68 | bool bSuccess = status == GL_FRAMEBUFFER_COMPLETE; 69 | 70 | // Unbind resources 71 | glBindTexture(GL_TEXTURE_2D, 0); 72 | glBindFramebuffer(GL_FRAMEBUFFER, 0); 73 | 74 | if( bSuccess ){ 75 | pOutRT = reinterpret_cast(static_cast(pRenderTargetView)); 76 | pOutTexture = reinterpret_cast(static_cast(pTextureView)); 77 | return true; 78 | } 79 | return false; 80 | } 81 | 82 | //================================================================================================= 83 | // HAL DESTROY RENDER TARGET 84 | // Free up allocated resources tried to a RenderTarget 85 | //================================================================================================= 86 | void HAL_DestroyRenderTarget(void*& pOutRT, void*& pOutTexture) 87 | { 88 | if(pOutRT) 89 | { 90 | GLuint pRT = static_cast(reinterpret_cast(pOutRT)); 91 | pOutRT = nullptr; 92 | glDeleteFramebuffers(1, &pRT); 93 | } 94 | if(pOutTexture) 95 | { 96 | GLuint pTexture = static_cast(reinterpret_cast(pOutTexture)); 97 | pOutTexture = nullptr; 98 | glDeleteTextures(1, &pTexture); 99 | } 100 | } 101 | 102 | //================================================================================================= 103 | // HAL CREATE TEXTURE 104 | // Receive info on a Texture to allocate. At the moment, 'Dear ImGui' default rendering backend 105 | // only support RGBA8 format, so first convert any input format to a RGBA8 that we can use 106 | //================================================================================================= 107 | bool HAL_CreateTexture(uint16_t Width, uint16_t Height, NetImgui::eTexFormat Format, const uint8_t* pPixelData, ServerTexture& OutTexture) 108 | { 109 | NetImguiServer::App::EnqueueHALTextureDestroy(OutTexture); 110 | 111 | // Convert all incoming textures data to RGBA8 112 | uint32_t* pPixelDataAlloc = NetImgui::Internal::netImguiSizedNew(Width*Height*4); 113 | if(Format == NetImgui::eTexFormat::kTexFmtA8) 114 | { 115 | for (int i = 0; i < Width * Height; ++i){ 116 | pPixelDataAlloc[i] = 0x00FFFFFF | (static_cast(pPixelData[i])<<24); 117 | } 118 | pPixelData = reinterpret_cast(pPixelDataAlloc); 119 | } 120 | else if (Format == NetImgui::eTexFormat::kTexFmtRGBA8) 121 | { 122 | } 123 | else 124 | { 125 | // Unsupported format 126 | return false; 127 | } 128 | 129 | GLint last_texture; 130 | glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); // Save state 131 | 132 | // Create new texture 133 | GLuint texture = 0u; 134 | glGenTextures(1, &texture); 135 | 136 | //GLenum error = glGetError(); (void)error; 137 | if( texture != 0 ){ 138 | glBindTexture(GL_TEXTURE_2D, texture); 139 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 140 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 141 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pPixelData); 142 | OutTexture.mpHAL_Texture = reinterpret_cast(static_cast(texture)); 143 | glBindTexture(GL_TEXTURE_2D, last_texture); // Restore state 144 | } 145 | NetImgui::Internal::netImguiDeleteSafe(pPixelDataAlloc); 146 | return texture != 0; 147 | } 148 | 149 | //================================================================================================= 150 | // HAL DESTROY TEXTURE 151 | // Free up allocated resources tried to a Texture 152 | //================================================================================================= 153 | void HAL_DestroyTexture(ServerTexture& OutTexture) 154 | { 155 | GLuint pTexture = static_cast(reinterpret_cast(OutTexture.mpHAL_Texture)); 156 | glDeleteTextures(1, &pTexture); 157 | memset(&OutTexture, 0, sizeof(OutTexture)); 158 | } 159 | 160 | }} //namespace NetImguiServer { namespace App 161 | 162 | #endif // HAL_API_PLATFORM_GLFW_GL3 163 | -------------------------------------------------------------------------------- /Code/ServerApp/Source/GlfwGL3/NetImguiServer_HAL_Glfw.cpp: -------------------------------------------------------------------------------- 1 | #include "NetImguiServer_App.h" 2 | 3 | #if HAL_API_PLATFORM_GLFW_GL3 4 | 5 | #include 6 | 7 | //================================================================================================= 8 | // WINDOWS GLFW 9 | // Note: This file currently only has support for Windows application 10 | #ifdef _WIN32 11 | extern int main(int, char**); 12 | #ifndef WIN32_LEAN_AND_MEAN 13 | #define WIN32_LEAN_AND_MEAN 14 | #endif 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "../resource.h" 22 | 23 | // WIN MAIN 24 | // Main window method expected as as Win32 Application. 25 | // Original 'main' method used by Dear ImGui sample is intended for a console Application, so we 26 | // need to provided expected entry point and manually call main. 27 | int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) 28 | { 29 | IM_UNUSED(hInstance); 30 | IM_UNUSED(hPrevInstance); 31 | IM_UNUSED(lpCmdLine); 32 | IM_UNUSED(nCmdShow); 33 | return main(0, nullptr); 34 | } 35 | #endif // _WIN32 36 | //================================================================================================= 37 | 38 | 39 | namespace NetImguiServer { namespace App 40 | { 41 | 42 | //================================================================================================= 43 | // HAL STARTUP 44 | // Additional initialisation that are platform specific 45 | //================================================================================================= 46 | bool HAL_Startup(const char* CmdLine) 47 | { 48 | IM_UNUSED(CmdLine); 49 | 50 | #ifdef _WIN32 51 | // Change the icon for hwnd's window class. 52 | HICON appIconBig = LoadIcon(GetModuleHandle(nullptr), MAKEINTRESOURCE(IDI_NETIMGUIAPP)); 53 | HICON appIconSmall = LoadIcon(GetModuleHandle(nullptr), MAKEINTRESOURCE(IDI_SMALL)); 54 | ImGuiViewport* main_viewport = ImGui::GetMainViewport(); 55 | HWND hwnd = reinterpret_cast(main_viewport->PlatformHandleRaw); 56 | SendMessage(hwnd, WM_SETICON, ICON_BIG, reinterpret_cast(appIconBig)); 57 | SendMessage(hwnd, WM_SETICON, ICON_SMALL, reinterpret_cast(appIconSmall)); 58 | #endif 59 | return true; 60 | } 61 | 62 | //================================================================================================= 63 | // HAL SHUTDOWN 64 | // Prepare for shutdown of application, with platform specific code 65 | //================================================================================================= 66 | void HAL_Shutdown() 67 | { 68 | 69 | } 70 | 71 | //================================================================================================= 72 | // HAL GET SOCKET INFO 73 | // Take a platform specific socket (based on the NetImguiNetworkXXX.cpp implementation) and 74 | // fetch informations about the client IP connected 75 | //================================================================================================= 76 | bool HAL_GetSocketInfo(NetImgui::Internal::Network::SocketInfo* pClientSocket, char* pOutHostname, size_t HostNameLen, int& outPort) 77 | { 78 | #ifdef _WIN32 79 | sockaddr socketAdr; 80 | int sizeSocket(sizeof(sockaddr)); 81 | SOCKET* pClientSocketWin = reinterpret_cast(pClientSocket); 82 | if( getsockname(*pClientSocketWin, &socketAdr, &sizeSocket) == 0 ) 83 | { 84 | char zPortBuffer[32]; 85 | if( getnameinfo(&socketAdr, sizeSocket, pOutHostname, static_cast(HostNameLen), zPortBuffer, sizeof(zPortBuffer), NI_NUMERICSERV) == 0 ) 86 | { 87 | outPort = atoi(zPortBuffer); 88 | return true; 89 | } 90 | } 91 | #endif 92 | return false; 93 | } 94 | 95 | //================================================================================================= 96 | // HAL GET USER SETTING FOLDER 97 | // Request the directory where to the 'shared config' clients should be saved 98 | // Return 'nullptr' to disable this feature 99 | //================================================================================================= 100 | const char* HAL_GetUserSettingFolder() 101 | { 102 | #ifdef _WIN32 103 | static char sUserSettingFolder[1024]={}; 104 | if(sUserSettingFolder[0] == 0) 105 | { 106 | WCHAR* UserPath; 107 | HRESULT Ret = SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &UserPath); 108 | if( SUCCEEDED(Ret) ){ 109 | sprintf_s(sUserSettingFolder, "%ws\\NetImgui", UserPath); // convert from wchar to char 110 | DWORD ftyp = GetFileAttributesA(sUserSettingFolder); 111 | if (ftyp != INVALID_FILE_ATTRIBUTES && (ftyp & FILE_ATTRIBUTE_DIRECTORY) ){ 112 | return sUserSettingFolder; 113 | } 114 | else if (ftyp == INVALID_FILE_ATTRIBUTES && CreateDirectoryA(sUserSettingFolder, nullptr) ){ 115 | return sUserSettingFolder; 116 | } 117 | } 118 | sUserSettingFolder[0] = 0; 119 | return nullptr; 120 | } 121 | return sUserSettingFolder; 122 | #else 123 | return nullptr; 124 | #endif 125 | } 126 | 127 | //================================================================================================= 128 | // HAL GET CLIPBOARD UPDATED 129 | // Detect when clipboard had a content change and we should refetch it on the Server and 130 | // forward it to the Clients 131 | // 132 | // Note: We rely on Dear ImGui for Clipboard Get/Set but want to avoid constantly reading then 133 | // converting it to a UTF8 text. If the Server platform doesn't support tracking change, 134 | // return true. If the Server platform doesn't support any clipboard, return false; 135 | //================================================================================================= 136 | bool HAL_GetClipboardUpdated() 137 | { 138 | #ifdef _WIN32 139 | static DWORD sClipboardSequence(0); 140 | DWORD clipboardSequence = GetClipboardSequenceNumber(); 141 | if (sClipboardSequence != clipboardSequence){ 142 | sClipboardSequence = clipboardSequence; 143 | return true; 144 | } 145 | #else 146 | // Update Clipboard content every second 147 | static std::chrono::steady_clock::time_point sLastCheck = std::chrono::steady_clock::now(); 148 | std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); 149 | if( (now - sLastCheck) > std::chrono::seconds(1) ) 150 | { 151 | sLastCheck = now; 152 | return true; 153 | } 154 | #endif 155 | return false; 156 | } 157 | 158 | }} // namespace NetImguiServer { namespace App 159 | 160 | #endif // HAL_API_PLATFORM_WIN32DX11 -------------------------------------------------------------------------------- /Code/ServerApp/Source/NetImguiServer_App.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | //============================================================================================= 7 | // SELECT RENDERING/OS API HERE 8 | //============================================================================================= 9 | #define HAL_API_PLATFORM_WIN32_DX11 1 10 | #define HAL_API_PLATFORM_GLFW_GL3 0 // Currently only compiles in release (library include compatibility) 11 | #define HAL_API_PLATFORM_SOKOL 0 12 | #define HAL_API_RENDERTARGET_INVERT_Y (HAL_API_PLATFORM_GLFW_GL3 || HAL_API_PLATFORM_SOKOL) // Invert client render target Y axis (since OpenGL start texture UV from BottomLeft instead of DirectX TopLeft) 13 | //============================================================================================= 14 | 15 | // Forward declare 16 | namespace NetImguiServer { namespace RemoteClient { struct Client; } } 17 | namespace NetImgui { namespace Internal { struct CmdTexture; } } 18 | 19 | namespace NetImguiServer { namespace App 20 | { 21 | //============================================================================================= 22 | // Code specific to 'NetImgui Server' application and needed inside platform specific code 23 | //============================================================================================= 24 | // Additional initialisation needed by 'NetImGui Server' and not part of default ImGui sample code 25 | bool Startup(const char* CmdLine); 26 | // Prepare for shutdown of application 27 | void Shutdown(); 28 | // Receive rendering request of each Remote client and output it to their own RenderTarget 29 | void UpdateRemoteContent(); 30 | // Add a new remote client config to our list (to attempt connexion) 31 | bool AddTransientClientConfigFromString(const char* string); 32 | // Check for monitor DPI update and regenerate font when needed 33 | // (return true when font texture needs to be created) 34 | bool UpdateFont(); 35 | // Descriptor of each textures by Server. Format always RGBA8 36 | // @sammyfreg todo: make this safer with smart pointer instead of manually deleting the HALTexture 37 | struct ServerTexture 38 | { 39 | inline bool IsValid(){ return mpHAL_Texture != nullptr; } 40 | void* mpHAL_Texture = nullptr; 41 | ServerTexture* mpDeleteNext = nullptr; // Used to insert in a list of textures to be deleted next frame 42 | uint64_t mImguiId = 0u; // Associated ImGui TextureId in Imgui commandlist 43 | uint64_t mCustomData = 0u; // Memory available to custom command 44 | uint16_t mSize[2] = {0,0}; 45 | uint8_t mFormat = 0; 46 | uint8_t mPadding[3] = {}; 47 | }; 48 | 49 | //============================================================================================= 50 | // Handling of texture data 51 | //============================================================================================= 52 | bool CreateTexture(ServerTexture& serverTexture, const NetImgui::Internal::CmdTexture& cmdTexture, uint32_t customDataSize); 53 | void DestroyTexture(ServerTexture& serverTexture, const NetImgui::Internal::CmdTexture& cmdTexture, uint32_t customDataSize); 54 | 55 | // Library users can implement their own texture format (on client/server). Useful for vidoe streaming, new format, etc. 56 | bool CreateTexture_Custom(ServerTexture& serverTexture, const NetImgui::Internal::CmdTexture& cmdTexture, uint32_t customDataSize); 57 | bool DestroyTexture_Custom(ServerTexture& serverTexture, const NetImgui::Internal::CmdTexture& cmdTexture, uint32_t customDataSize); 58 | 59 | // Texture destruction is postponed until the end of the frame update to avoid rendering issues 60 | void EnqueueHALTextureDestroy(ServerTexture& serverTexture); 61 | void CompleteHALTextureDestroy(); 62 | 63 | //============================================================================================= 64 | // Note (H)ardware (A)bstraction (L)ayer 65 | // When porting the 'NetImgui Server' application to other platform, 66 | // theses are the few functions needed to be supported by each specific API that 67 | // are not already supported by de 'Dear ImGui' provided backends 68 | //============================================================================================= 69 | // Additional initialisation that are platform specific 70 | bool HAL_Startup(const char* CmdLine); 71 | // Prepare for shutdown of application, with platform specific code 72 | void HAL_Shutdown(); 73 | // Receive a platform specific socket, and return us with info on the connection 74 | bool HAL_GetSocketInfo(NetImgui::Internal::Network::SocketInfo* pClientSocket, char* pOutHostname, size_t HostNameLen, int& outPort); 75 | // Provide the current user setting folder (used to save the shared config file) 76 | const char* HAL_GetUserSettingFolder(); 77 | // Return true when new content should be retrieved from Clipboard (avoid constantly reading/converting content) 78 | bool HAL_GetClipboardUpdated(); 79 | // Receive a ImDrawData drawlist and request Dear ImGui's backend to output it into a texture 80 | void HAL_RenderDrawData(RemoteClient::Client& client, ImDrawData* pDrawData); 81 | // Allocate a texture resource 82 | bool HAL_CreateTexture(uint16_t Width, uint16_t Height, NetImgui::eTexFormat Format, const uint8_t* pPixelData, ServerTexture& OutTexture); 83 | // Free a Texture resource 84 | void HAL_DestroyTexture( ServerTexture& OutTexture ); 85 | // Allocate a RenderTarget that each client will use to output their ImGui drawing into. 86 | bool HAL_CreateRenderTarget(uint16_t Width, uint16_t Height, void*& pOutRT, void*& pOutTexture ); 87 | // Free a RenderTarget resource 88 | void HAL_DestroyRenderTarget(void*& pOutRT, void*& pOutTexture ); 89 | 90 | }} 91 | -------------------------------------------------------------------------------- /Code/ServerApp/Source/NetImguiServer_Config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace NetImguiServer { namespace Config 6 | { 7 | 8 | //================================================================================================= 9 | // Client Configs are used by this server to reach remote netImgui Clients. 10 | // 11 | // Note:For multihreading safety, we are always working with copies of the original data. 12 | // 13 | // Note:It is also possible for a remote netImgui client to connect to Server directly, 14 | // in which case they don't need to have an associated config. 15 | //================================================================================================= 16 | class Client 17 | { 18 | public: 19 | using RuntimeID = uint32_t; 20 | using TimeStamp = std::chrono::steady_clock::time_point; 21 | static constexpr RuntimeID kInvalidRuntimeID = static_cast(0); 22 | 23 | enum class eVersion : uint32_t { 24 | Initial = 1, // First version save file deployed 25 | Refresh = 2, // Added refresh rate support 26 | DPIScale = 3, // Added DPI scaling 27 | BlockTakeOver = 4, // Added Takeover Block 28 | _Count, 29 | _Latest = _Count-1 30 | }; 31 | enum class eConfigType : uint8_t 32 | { 33 | Pending, // New config, will try saving it in the local config 34 | Local, // Config fetched from local config file, in the current working directory 35 | Local2nd, // Config fetched from a second local config file, in the current working directory. Used when 'Local' file is read only 36 | Shared, // Config fetched from the shared user folder 37 | Transient, // Config created from connection request (command line, OS pipes), cannot be saved 38 | }; 39 | enum class eStatus : uint8_t 40 | { 41 | Disconnected, // No connection detected on client 42 | Connecting, // This server is connecting to client 43 | Connected, // This server is connect to client 44 | Available, // Client already taken, but this server can take over 45 | ErrorBusy, // Client already taken 46 | ErrorVer, // Server/Client network api mismatch 47 | }; 48 | 49 | // Config settings 50 | char mClientName[128]; //!< Client display name 51 | char mHostName[128]; //!< Client IP or remote host address to attempt connection at 52 | uint32_t mHostPort; //!< Client Port to attempt connection at 53 | RuntimeID mRuntimeID; //!< Unique RuntimeID used to find this Config 54 | eConfigType mConfigType; //!< Type of the configuration 55 | bool mDPIScaleEnabled; //!< Enable support of Font DPI scaling requests by Server 56 | bool mBlockTakeover; //!< If another NetImguiServer is allowed to forcefully disconnect this client to connect to it 57 | bool mReadOnly; //!< Config comes from read only file, can't be modified 58 | bool mConnectAuto; //!< Try automatically connecting to client 59 | 60 | // Transient values used while running 61 | mutable bool mConnectRequest; //!< Attempt connecting to Client, after user request 62 | mutable bool mConnectForce; //!< Attempt connecting to Client, after user request, even if already connected 63 | mutable eStatus mConnectStatus; //!< Connection status of associated client 64 | mutable TimeStamp mConnectLastTime; //!< Last connection attempt time (avoid quickly retrying same client) 65 | 66 | // Access methods 67 | public: 68 | Client(); 69 | Client(const Client& Copy) = default; 70 | 71 | inline bool IsReadOnly()const { return mReadOnly; }; 72 | inline bool IsTransient()const { return mConfigType == eConfigType::Transient; }; 73 | inline bool IsConnected()const { return mConnectStatus == eStatus::Connected; } 74 | inline bool IsConnecting()const { return mConnectStatus == eStatus::Connecting || mConnectRequest || mConnectForce; } 75 | inline bool IsConnectReady()const { 76 | bool bAvailable = mConnectStatus != eStatus::Connected && mConnectStatus != eStatus::Connecting; 77 | return bAvailable && (mConnectRequest || mConnectForce); 78 | } 79 | inline bool IsAutoConnectReady()const { 80 | bool bAvailable = mConnectStatus != eStatus::Connected && mConnectStatus != eStatus::Connecting; 81 | auto elapsedTime = std::chrono::steady_clock::now() - mConnectLastTime; 82 | int durationSec = static_cast(std::chrono::duration_cast(elapsedTime).count()); 83 | bool elapseOk = durationSec > (mConnectStatus == eStatus::Disconnected ? 5 : 30); 84 | return bAvailable && mConnectAuto && elapseOk; 85 | } 86 | 87 | // Add/Edit/Remove config 88 | static void SetConfig(const Client& config); //!< Add or replace a client configuration info 89 | static void DelConfig(uint32_t configID); //!< Remove a client configuration 90 | static bool GetConfigByID(uint32_t configID, Client& outConfig); //!< Find client configuration with this id (return true if found) 91 | static bool GetConfigByIndex(uint32_t index, Client& outConfig); //!< Find client configuration at the x position 92 | static uint32_t GetConfigCount(); 93 | 94 | // Set property value directly (without having to copy entire structure) 95 | static bool GetProperty_BlockTakeover(uint32_t configID); 96 | static void SetProperty_Status(uint32_t configID, eStatus Status); 97 | static void SetProperty_ConnectAuto(uint32_t configID, bool value); 98 | static void SetProperty_ConnectRequest(uint32_t configID, bool value, bool force); 99 | 100 | // Client Config list management 101 | static void SaveAll(); 102 | static void LoadAll(); 103 | static void Clear(); 104 | 105 | protected: 106 | static void SaveConfigFile(eConfigType fileConfigType, bool writeServerSettings); 107 | static void LoadConfigFile(eConfigType fileConfigType); 108 | inline bool ShouldSave(eConfigType fileConfigType) const; 109 | }; 110 | 111 | struct Server 112 | { 113 | static uint32_t sPort; //!< Port that Server should use for connection. (Note: not really a 'Client' setting, but easier to just bundle the value here for the moment) 114 | static float sRefreshFPSActive; //!< Refresh rate of active Window 115 | static float sRefreshFPSInactive; //!< Refresh rate of inactive Window 116 | static float sDPIScaleRatio; //!< Ratio of DPI scale applied to Font size (helps with high resolution monitor, default 1.0) 117 | static bool sCompressionEnable; //!< Ask the clients to compress their data before transmission 118 | }; 119 | 120 | }} // namespace NetImguiServer { namespace Config 121 | -------------------------------------------------------------------------------- /Code/ServerApp/Source/NetImguiServer_Network.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | namespace NetImguiServer { namespace Network 5 | { 6 | // Initialize application's networking 7 | bool Startup(); 8 | 9 | // Shutdown application's networking 10 | void Shutdown(); 11 | 12 | // True if this application is actively waiting for clients to reach it 13 | // Note: False when unable to open listen socket (probably because port number alreay in use) 14 | bool IsWaitingForConnection(); 15 | 16 | // Total amount of data sent to clients since start 17 | uint64_t GetStatsDataSent(); 18 | 19 | // Total amount of data received from clients since start 20 | uint64_t GetStatsDataRcvd(); 21 | 22 | }} 23 | -------------------------------------------------------------------------------- /Code/ServerApp/Source/NetImguiServer_RemoteClient.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "NetImguiServer_App.h" 8 | 9 | namespace NetImguiServer { namespace RemoteClient 10 | { 11 | 12 | //================================================================================================= 13 | // ImDrawData wrapper 14 | // 15 | // Allocate a single ImDrawList and assign it to itself. 16 | // 17 | // This child class leave the original ImDrawData behavior intact, but add the proper 18 | // memory freeing of the ImDrawList member. 19 | //================================================================================================= 20 | struct NetImguiImDrawData : ImDrawData 21 | { 22 | NetImguiImDrawData(); 23 | ImDrawList mCommandList; 24 | }; 25 | 26 | //================================================================================================= 27 | // All info needed by the server to communicate with a remote client, and render its content 28 | //================================================================================================= 29 | struct Client 30 | { 31 | static constexpr uint32_t kInvalidClient = static_cast(-1); 32 | using ExchPtrInput = NetImgui::Internal::ExchangePtr; 33 | using ExchPtrClipboard = NetImgui::Internal::ExchangePtr; 34 | using ExchPtrBackground = NetImgui::Internal::ExchangePtr; 35 | using ExchPtrImguiDraw = NetImgui::Internal::ExchangePtr; 36 | using TextureTable = std::unordered_map; 37 | 38 | Client(); 39 | ~Client(); 40 | Client(const Client&) = delete; 41 | Client(const Client&&) = delete; 42 | void operator=(const Client&) = delete; 43 | void Initialize(); 44 | void Uninitialize(); 45 | void Release(); 46 | bool IsValid()const; 47 | 48 | void ReceiveTexture(NetImgui::Internal::CmdTexture*); 49 | void ReceiveDrawFrame(NetImgui::Internal::CmdDrawFrame*); 50 | NetImguiImDrawData* ConvertToImguiDrawData(const NetImgui::Internal::CmdDrawFrame* pCmdDrawFrame); 51 | NetImguiImDrawData* GetImguiDrawData(void* pEmtpyTextureHAL); // Get current active Imgui draw data 52 | 53 | void CaptureImguiInput(); 54 | NetImgui::Internal::CmdInput* TakePendingInput(); 55 | NetImgui::Internal::CmdClipboard* TakePendingClipboard(); 56 | void ProcessPendingTextures(); 57 | 58 | static bool Startup(uint32_t clientCountMax); 59 | static void Shutdown(); 60 | static uint32_t GetCountMax(); 61 | static uint32_t GetFreeIndex(); 62 | static Client& Get(uint32_t index); 63 | 64 | void* mpHAL_AreaRT = nullptr; 65 | void* mpHAL_AreaTexture = nullptr; 66 | uint16_t mAreaRTSizeX = 0; //!< Currently allocated RenderTarget size 67 | uint16_t mAreaRTSizeY = 0; //!< Currently allocated RenderTarget size 68 | uint16_t mAreaSizeX = 0; //!< Available area size available to remote client 69 | uint16_t mAreaSizeY = 0; //!< Available area size available to remote client 70 | char mInfoName[128] = {}; 71 | char mWindowID[128+16] = {}; 72 | char mInfoImguiVerName[16] = {}; 73 | char mInfoNetImguiVerName[16]= {}; 74 | uint32_t mInfoImguiVerID = 0; 75 | uint32_t mInfoNetImguiVerID = 0; 76 | char mConnectHost[64] = {}; //!< Connected Hostname of this remote client 77 | int mConnectPort = 0; //!< Connected Port of this remote client 78 | 79 | NetImguiImDrawData* mpImguiDrawData = nullptr; //!< Current Imgui Data that this client is the owner of 80 | NetImgui::Internal::CmdDrawFrame* mpFrameDrawPrev = nullptr; //!< Last valid DrawDrame (used by com thread, to uncompress data) 81 | TextureTable mTextureTable; //!< Table of textures received and used by the client 82 | ExchPtrImguiDraw mPendingImguiDrawDataIn; //!< Pending received Imgui DrawData, waiting to be taken ownership of 83 | ExchPtrBackground mPendingBackgroundIn; //!< Background settings received and waiting to update client setting 84 | ExchPtrClipboard mPendingClipboardIn; //!< Clipboard received from Client and waiting to be processed on Server 85 | ExchPtrInput mPendingInputOut; //!< Input command waiting to be sent out to client 86 | ExchPtrClipboard mPendingClipboardOut; //!< Clipboard command waiting to be sent out to client 87 | std::vector mPendingInputChars; //!< Captured Imgui characters input waiting to be added to new InputCmd 88 | NetImgui::Internal::CmdTexture* mpPendingTextures[64] = {}; //!< Textures commands waiting to be processed in main update loop 89 | std::atomic_uint64_t mPendingTextureReadIndex; 90 | std::atomic_uint64_t mPendingTextureWriteIndex; 91 | bool mbIsVisible = false; //!< If currently shown 92 | bool mbIsActive = false; //!< Is the current active window (will receive input, only one is true at a time) 93 | bool mbIsReleased = false; //!< If released in com thread and main thread should delete resources 94 | bool mbIsConnected = false; //!< If connected to a remote client. Set to false in Unitialize, after mIsRelease is set to unload resources 95 | std::atomic_bool mbIsFree; //!< If available to use for a new connected client 96 | std::atomic_bool mbCompressionSkipOncePending; //!< When we detect invalid previous DrawFrame command, cancel compression for 1 frame, to get good data 97 | std::atomic_bool mbDisconnectPending; //!< Terminate Client/Server coms 98 | std::chrono::steady_clock::time_point mConnectedTime; //!< When the connection was established with this remote client 99 | std::chrono::steady_clock::time_point mLastUpdateTime; //!< When the client last send a content refresh request 100 | std::chrono::steady_clock::time_point mLastDrawFrame; //!< When we last receive a new drawframe commant 101 | std::chrono::steady_clock::time_point mLastIncomingComTime; //!< When we last received a valid command from client (to detect timeout) 102 | uint32_t mClientConfigID = 0; //!< ID of ClientConfig that connected (if connection came from our list of ClientConfigs) 103 | uint32_t mClientIndex = 0; //!< Entry idx into table of connected clients 104 | uint64_t mStatsDataRcvd = 0; //!< Current amount of Bytes received since connected 105 | uint64_t mStatsDataSent = 0; //!< Current amount of Bytes sent to client since connected 106 | uint64_t mStatsDataRcvdPrev = 0; //!< Last amount of Bytes received since connected 107 | uint64_t mStatsDataSentPrev = 0; //!< Last amount of Bytes sent to client since connected 108 | std::chrono::steady_clock::time_point mStatsTime; //!< Time when info was collected (with history of last x values) 109 | uint32_t mStatsRcvdBps = 0; //!< Average Bytes received per second 110 | uint32_t mStatsSentBps = 0; //!< Average Bytes sent per second 111 | float mStatsDrawElapsedMs = 0.f; //!< Average milliseconds between 2 draw requests 112 | uint32_t mStatsIndex = 0; 113 | float mMousePos[2] = {0,0}; 114 | float mMouseWheelPos[2] = {0,0}; 115 | ImGuiMouseCursor mMouseCursor = ImGuiMouseCursor_None; // Last mosue cursor remote client requested 116 | ImGuiContext* mpBGContext = nullptr; // Special Imgui Context used to render the background (only updated when needed) 117 | bool mBGNeedUpdate = true; // Let engine know that we should regenerate the background draw commands 118 | NetImgui::Internal::Network::SocketInfo* mpSocket = nullptr; //!< Socket used for communications 119 | NetImgui::Internal::CmdBackground mBGSettings; //!< Settings for client background drawing settings 120 | NetImgui::Internal::CmdPendingRead mCmdPendingRead; //!< Used to get info on the next incoming command from Client 121 | NetImgui::Internal::PendingCom mPendingRcv; //!< Data being currently received from Client 122 | NetImgui::Internal::PendingCom mPendingSend; //!< Data being currently sent to Client 123 | }; 124 | 125 | }} // namespace NetImguiServer { namespace Client -------------------------------------------------------------------------------- /Code/ServerApp/Source/NetImguiServer_UI.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace NetImguiServer { namespace App { struct ServerTexture; } } // Forward Declare 4 | 5 | namespace NetImguiServer { namespace UI 6 | { 7 | constexpr uint32_t kWindowDPIDefault = 96; 8 | bool Startup(); 9 | void Shutdown(); 10 | ImVec4 DrawImguiContent(); 11 | void DrawCenteredBackground( const App::ServerTexture& Texture, const ImVec4& tint=ImVec4(1.f,1.f,1.f,1.f)); 12 | float GetDisplayFPS(); 13 | const App::ServerTexture& GetBackgroundTexture(); 14 | void SetWindowDPI(uint32_t dpi); 15 | float GetFontDPIScale(); 16 | }} //namespace NetImguiServer { namespace UI -------------------------------------------------------------------------------- /Code/ServerApp/Source/Sokol/NetImguiServer_App_Sokol.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================================= 2 | // @SAMPLE_EDIT 3 | // Note: This file a duplicate of 'Dear ImGui Sample' : "examples\example_glfw_opengl3\main.cpp" 4 | // With a few editions added to customize it for our NetImGui server needs. 5 | // These fews edits will be found in a few location, using the tag '@SAMPLE_EDIT' 6 | #include "NetImguiServer_App.h" 7 | 8 | #if HAL_API_PLATFORM_SOKOL 9 | 10 | #include 11 | #include 12 | #include "NetImguiServer_UI.h" 13 | 14 | #define SOKOL_IMPL 15 | #define SOKOL_NO_ENTRY 16 | #ifdef __EMSCRIPTEN__ 17 | #define SOKOL_GLES3 18 | #else 19 | #define SOKOL_GLCORE33 20 | #endif 21 | #include "sokol/sokol_app.h" 22 | #include "sokol/sokol_gfx.h" 23 | #include "sokol/sokol_glue.h" 24 | #include "sokol/sokol_log.h" 25 | #include "imgui.h" 26 | #include "sokol/util/sokol_imgui.h" 27 | 28 | sg_pass_action pass_action{}; 29 | ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); 30 | std::string cmdArgs; 31 | 32 | void init() { 33 | sg_desc desc = {}; 34 | sg_context_desc context_desc = sapp_sgcontext(); 35 | context_desc.depth_format = SG_PIXELFORMAT_NONE; 36 | desc.context = context_desc; 37 | desc.logger.func = slog_func; 38 | desc.disable_validation = true; 39 | sg_setup(&desc); 40 | 41 | simgui_desc_t simgui_desc = {}; 42 | simgui_desc.no_default_font = true; 43 | simgui_desc.depth_format = SG_PIXELFORMAT_NONE; 44 | simgui_setup(&simgui_desc); 45 | 46 | pass_action.colors[0].load_action = SG_LOADACTION_CLEAR; 47 | 48 | // Setup Dear ImGui context 49 | IMGUI_CHECKVERSION(); 50 | ImGui::CreateContext(); 51 | ImGuiIO& io = ImGui::GetIO(); (void)io; 52 | io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls 53 | //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls 54 | io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking 55 | io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows 56 | //io.ConfigViewportsNoAutoMerge = true; 57 | //io.ConfigViewportsNoTaskBarIcon = true; 58 | 59 | // Setup Dear ImGui style 60 | ImGui::StyleColorsDark(); 61 | //ImGui::StyleColorsClassic(); 62 | 63 | // When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones. 64 | ImGuiStyle& style = ImGui::GetStyle(); 65 | if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) 66 | { 67 | style.WindowRounding = 0.0f; 68 | style.Colors[ImGuiCol_WindowBg].w = 1.0f; 69 | } 70 | 71 | bool ok = NetImguiServer::App::Startup(cmdArgs.c_str()); 72 | IM_ASSERT(ok); 73 | (void)ok; 74 | 75 | // IMGUI Font texture init 76 | { 77 | // Build texture atlas 78 | unsigned char* pixels; 79 | int width, height; 80 | io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bit (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory. 81 | 82 | sg_image_desc img_desc{}; 83 | img_desc.width = width; 84 | img_desc.height = height; 85 | img_desc.label = "font-texture"; 86 | img_desc.wrap_u = SG_WRAP_CLAMP_TO_EDGE; 87 | img_desc.wrap_v = SG_WRAP_CLAMP_TO_EDGE; 88 | img_desc.min_filter = SG_FILTER_LINEAR; 89 | img_desc.mag_filter = SG_FILTER_LINEAR; 90 | img_desc.data.subimage[0][0].ptr = pixels; 91 | img_desc.data.subimage[0][0].size = (width * height) * sizeof(uint32_t); 92 | 93 | sg_image img = sg_make_image(&img_desc); 94 | 95 | io.Fonts->TexID = (ImTextureID)(uintptr_t)img.id; 96 | } 97 | } 98 | 99 | void frame() { 100 | const int width = sapp_width(); 101 | const int height = sapp_height(); 102 | 103 | // sg_begin_default_pass(&pass_action, width, height); 104 | 105 | simgui_new_frame({ width, height, sapp_frame_duration(), sapp_dpi_scale() }); 106 | NetImguiServer::App::UpdateRemoteContent(); // @SAMPLE_EDIT (Request each client to update their drawing content ) 107 | clear_color = NetImguiServer::UI::DrawImguiContent(); 108 | pass_action.colors[0].clear_value.r = clear_color.x; 109 | pass_action.colors[0].clear_value.g = clear_color.y; 110 | pass_action.colors[0].clear_value.b = clear_color.z; 111 | pass_action.colors[0].clear_value.a = clear_color.w; 112 | 113 | sg_begin_default_pass(&pass_action, width, height); 114 | simgui_render(); 115 | sg_end_pass(); 116 | 117 | sg_commit(); 118 | } 119 | 120 | void cleanup() { 121 | simgui_shutdown(); 122 | sg_shutdown(); 123 | } 124 | 125 | void input(const sapp_event* event) { 126 | simgui_handle_event(event); 127 | } 128 | 129 | int main(int argc, const char* argv[]) { 130 | for (size_t i = 0; i < size_t(argc); ++i) { 131 | std::string arg(argv[i]); 132 | cmdArgs += arg + " "; 133 | } 134 | 135 | if (!cmdArgs.empty()) { 136 | cmdArgs.pop_back(); 137 | } 138 | 139 | 140 | sapp_desc desc = {}; 141 | desc.init_cb = init; 142 | desc.frame_cb = frame; 143 | desc.cleanup_cb = cleanup, 144 | desc.event_cb = input, 145 | desc.width = 1280, 146 | desc.height = 720, 147 | desc.window_title = "NetImgui Server", 148 | desc.icon.sokol_default = true, 149 | desc.logger.func = slog_func; 150 | sapp_run(desc); 151 | 152 | return EXIT_SUCCESS; 153 | } 154 | 155 | #endif // @SAMPLE_EDIT HAL_API_PLATFORM_SOKOL 156 | -------------------------------------------------------------------------------- /Code/ServerApp/Source/Sokol/NetImguiServer_HAL_SokolApp.cpp: -------------------------------------------------------------------------------- 1 | #include "NetImguiServer_App.h" 2 | 3 | #if HAL_API_PLATFORM_SOKOL 4 | #include 5 | 6 | 7 | namespace NetImguiServer { namespace App 8 | { 9 | 10 | //================================================================================================= 11 | // HAL STARTUP 12 | // Additional initialisation that are platform specific 13 | //================================================================================================= 14 | bool HAL_Startup(const char* CmdLine) 15 | { 16 | IM_UNUSED(CmdLine); 17 | return true; 18 | } 19 | 20 | //================================================================================================= 21 | // HAL SHUTDOWN 22 | // Prepare for shutdown of application, with platform specific code 23 | //================================================================================================= 24 | void HAL_Shutdown() 25 | { 26 | 27 | } 28 | 29 | //================================================================================================= 30 | // HAL GET SOCKET INFO 31 | // Take a platform specific socket (based on the NetImguiNetworkXXX.cpp implementation) and 32 | // fetch informations about the client IP connected 33 | //================================================================================================= 34 | bool HAL_GetSocketInfo(NetImgui::Internal::Network::SocketInfo* , char* , size_t , int& ) 35 | { 36 | return false; 37 | } 38 | 39 | //================================================================================================= 40 | // HAL GET USER SETTING FOLDER 41 | // Request the directory where to the 'shared config' clients should be saved 42 | // Return 'nullptr' to disable this feature 43 | //================================================================================================= 44 | const char* HAL_GetUserSettingFolder() 45 | { 46 | return nullptr; 47 | } 48 | 49 | //================================================================================================= 50 | // HAL GET CLIPBOARD UPDATED 51 | // Detect when clipboard had a content change and we should refetch it on the Server and 52 | // forward it to the Clients 53 | // 54 | // Note: We rely on Dear ImGui for Clipboard Get/Set but want to avoid constantly reading then 55 | // converting it to a UTF8 text. If the Server platform doesn't support tracking change, 56 | // return true. If the Server platform doesn't support any clipboard, return false; 57 | //================================================================================================= 58 | bool HAL_GetClipboardUpdated() 59 | { 60 | // Update Clipboard content every second 61 | static std::chrono::steady_clock::time_point sLastCheck = std::chrono::steady_clock::now(); 62 | std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); 63 | if( (now - sLastCheck) > std::chrono::seconds(1) ) 64 | { 65 | sLastCheck = now; 66 | return true; 67 | } 68 | return false; 69 | } 70 | }} // namespace NetImguiServer { namespace App 71 | 72 | #endif // HAL_API_PLATFORM_SOKOL -------------------------------------------------------------------------------- /Code/ServerApp/Source/Sokol/NetImguiServer_HAL_SokolGfx.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================================= 2 | // Source file handling renderer specific commands needed by NetImgui server. 3 | // It complement the rendering backend with a few more functionalities. 4 | // 5 | // @note: Thank you to github user A3Wypiok, for a lot of the OpenGL found in this file 6 | //================================================================================================= 7 | #include "NetImguiServer_App.h" 8 | 9 | #if HAL_API_PLATFORM_SOKOL 10 | 11 | #include "NetImguiServer_RemoteClient.h" 12 | #include "sokol/sokol_app.h" 13 | #include "sokol/sokol_gfx.h" 14 | #include "sokol/util/sokol_imgui.h" 15 | 16 | namespace NetImguiServer { namespace App 17 | { 18 | //================================================================================================= 19 | // HAL RENDER DRAW DATA 20 | // The drawing of remote clients is handled normally by the standard rendering backend, 21 | // but output is redirected to an allocated client texture instead default swapchain 22 | //================================================================================================= 23 | void HAL_RenderDrawData(RemoteClient::Client& client, ImDrawData* pDrawData) 24 | { 25 | if (client.mpHAL_AreaRT) 26 | { 27 | sg_pass_action pass_action{}; 28 | sg_pass_desc pass_desc{}; 29 | 30 | pass_desc.color_attachments[0].image.id = static_cast(reinterpret_cast(client.mpHAL_AreaRT)); 31 | pass_desc.depth_stencil_attachment.image.id = SG_INVALID_ID; 32 | pass_desc.label = "mpHAL_AreaRT"; 33 | 34 | pass_action.colors[0].load_action = SG_LOADACTION_CLEAR; 35 | pass_action.colors[0].clear_value.r = client.mBGSettings.mClearColor[0]; 36 | pass_action.colors[0].clear_value.g = client.mBGSettings.mClearColor[1]; 37 | pass_action.colors[0].clear_value.b = client.mBGSettings.mClearColor[2]; 38 | pass_action.colors[0].clear_value.a = client.mBGSettings.mClearColor[3]; 39 | 40 | sg_pass pass = sg_make_pass(&pass_desc); 41 | 42 | sg_begin_pass(pass, &pass_action); 43 | { 44 | { 45 | void* mainBackend = ImGui::GetIO().BackendRendererUserData; 46 | NetImgui::Internal::ScopedImguiContext scopedCtx(client.mpBGContext); 47 | ImGui::GetIO().BackendRendererUserData = mainBackend; // Re-appropriate the existing renderer backend, for this client rendeering 48 | simgui_render_draw_data(ImGui::GetDrawData()); 49 | } 50 | if (pDrawData) 51 | { 52 | simgui_render_draw_data(pDrawData); 53 | } 54 | } 55 | sg_end_pass(); 56 | 57 | sg_destroy_pass(pass); 58 | } 59 | } 60 | 61 | //================================================================================================= 62 | // HAL CREATE RENDER TARGET 63 | // Allocate RenderTargetView / TextureView for each connected remote client. 64 | // The drawing of their menu content will be outputed in it, then displayed normally 65 | // inside our own 'NetImGui application' Imgui drawing 66 | //================================================================================================= 67 | bool HAL_CreateRenderTarget(uint16_t Width, uint16_t Height, void*& pOutRT, void*& pOutTexture) 68 | { 69 | HAL_DestroyRenderTarget(pOutRT, pOutTexture); 70 | 71 | sg_image_desc img_desc{}; 72 | img_desc.render_target = true; 73 | img_desc.width = Width; 74 | img_desc.height = Height; 75 | img_desc.pixel_format = SG_PIXELFORMAT_RGBA8; 76 | img_desc.min_filter = SG_FILTER_LINEAR; 77 | img_desc.mag_filter = SG_FILTER_LINEAR; 78 | 79 | sg_image img = sg_make_image(&img_desc); 80 | 81 | bool bSuccess = img.id != SG_INVALID_ID; 82 | if( bSuccess ){ 83 | pOutRT = reinterpret_cast(static_cast(img.id)); 84 | pOutTexture = reinterpret_cast(static_cast(img.id)); 85 | return true; 86 | } 87 | 88 | return false; 89 | } 90 | 91 | //================================================================================================= 92 | // HAL DESTROY RENDER TARGET 93 | // Free up allocated resources tried to a RenderTarget 94 | //================================================================================================= 95 | void HAL_DestroyRenderTarget(void*& pOutRT, void*& pOutTexture) 96 | { 97 | if(pOutRT) 98 | { 99 | sg_image pRT{}; 100 | pRT.id = static_cast(reinterpret_cast(pOutRT)); 101 | pOutRT = nullptr; 102 | sg_destroy_image(pRT); 103 | } 104 | if(pOutTexture) 105 | { 106 | sg_image pTexture{}; 107 | pTexture.id = static_cast(reinterpret_cast(pOutTexture)); 108 | pOutTexture = nullptr; 109 | sg_destroy_image(pTexture); 110 | } 111 | } 112 | 113 | //================================================================================================= 114 | // HAL CREATE TEXTURE 115 | // Receive info on a Texture to allocate. At the moment, 'Dear ImGui' default rendering backend 116 | // only support RGBA8 format, so first convert any input format to a RGBA8 that we can use 117 | //================================================================================================= 118 | bool HAL_CreateTexture(uint16_t Width, uint16_t Height, NetImgui::eTexFormat Format, const uint8_t* pPixelData, ServerTexture& OutTexture) 119 | { 120 | NetImguiServer::App::EnqueueHALTextureDestroy(OutTexture); 121 | 122 | // Convert all incoming textures data to RGBA8 123 | uint32_t* pPixelDataAlloc = NetImgui::Internal::netImguiSizedNew(Width*Height*4); 124 | if(Format == NetImgui::eTexFormat::kTexFmtA8) 125 | { 126 | for (int i = 0; i < Width * Height; ++i){ 127 | pPixelDataAlloc[i] = 0x00FFFFFF | (static_cast(pPixelData[i])<<24); 128 | } 129 | pPixelData = reinterpret_cast(pPixelDataAlloc); 130 | } 131 | else if (Format == NetImgui::eTexFormat::kTexFmtRGBA8) 132 | { 133 | } 134 | else 135 | { 136 | // Unsupported format 137 | return false; 138 | } 139 | 140 | sg_image_desc img_desc{}; 141 | img_desc.width = Width; 142 | img_desc.height = Height; 143 | img_desc.pixel_format = SG_PIXELFORMAT_RGBA8; 144 | img_desc.usage = SG_USAGE_STREAM; 145 | 146 | sg_image img = sg_make_image(&img_desc); 147 | 148 | if (img.id != SG_INVALID_ID) 149 | { 150 | sg_image_data img_data{}; 151 | img_data.subimage[0][0].ptr = pPixelData; 152 | img_data.subimage[0][0].size = Width * Height * sizeof(uint32_t); 153 | sg_update_image(img, img_data); 154 | 155 | OutTexture.mSize[0] = Width; 156 | OutTexture.mSize[1] = Height; 157 | OutTexture.mpHAL_Texture = reinterpret_cast(static_cast(img.id)); 158 | } 159 | 160 | NetImgui::Internal::netImguiDeleteSafe(pPixelDataAlloc); 161 | return img.id != SG_INVALID_ID; 162 | } 163 | 164 | //================================================================================================= 165 | // HAL DESTROY TEXTURE 166 | // Free up allocated resources tried to a Texture 167 | //================================================================================================= 168 | void HAL_DestroyTexture(ServerTexture& OutTexture) 169 | { 170 | if(OutTexture.mpHAL_Texture) 171 | { 172 | sg_image image{}; 173 | image.id = static_cast(reinterpret_cast(OutTexture.mpHAL_Texture)); 174 | sg_destroy_image(image); 175 | OutTexture.mpHAL_Texture = nullptr; 176 | } 177 | } 178 | 179 | }} //namespace NetImguiServer { namespace App 180 | 181 | #endif // HAL_API_PLATFORM_SOKOL 182 | -------------------------------------------------------------------------------- /Code/ServerApp/Source/Sokol/sokol/sokol_glue.h: -------------------------------------------------------------------------------- 1 | #if defined(SOKOL_IMPL) && !defined(SOKOL_GLUE_IMPL) 2 | #define SOKOL_GLUE_IMPL 3 | #endif 4 | #ifndef SOKOL_GLUE_INCLUDED 5 | /* 6 | sokol_glue.h -- glue helper functions for sokol headers 7 | 8 | Project URL: https://github.com/floooh/sokol 9 | 10 | Do this: 11 | #define SOKOL_IMPL or 12 | #define SOKOL_GLUE_IMPL 13 | before you include this file in *one* C or C++ file to create the 14 | implementation. 15 | 16 | ...optionally provide the following macros to override defaults: 17 | 18 | SOKOL_ASSERT(c) - your own assert macro (default: assert(c)) 19 | SOKOL_GLUE_API_DECL - public function declaration prefix (default: extern) 20 | SOKOL_API_DECL - same as SOKOL_GLUE_API_DECL 21 | SOKOL_API_IMPL - public function implementation prefix (default: -) 22 | 23 | If sokol_glue.h is compiled as a DLL, define the following before 24 | including the declaration or implementation: 25 | 26 | SOKOL_DLL 27 | 28 | On Windows, SOKOL_DLL will define SOKOL_GLUE_API_DECL as __declspec(dllexport) 29 | or __declspec(dllimport) as needed. 30 | 31 | OVERVIEW 32 | ======== 33 | The sokol core headers should not depend on each other, but sometimes 34 | it's useful to have a set of helper functions as "glue" between 35 | two or more sokol headers. 36 | 37 | This is what sokol_glue.h is for. Simply include the header after other 38 | sokol headers (both for the implementation and declaration), and 39 | depending on what headers have been included before, sokol_glue.h 40 | will make available "glue functions". 41 | 42 | PROVIDED FUNCTIONS 43 | ================== 44 | 45 | - if sokol_app.h and sokol_gfx.h is included: 46 | 47 | sg_context_desc sapp_sgcontext(void): 48 | 49 | Returns an initialized sg_context_desc function initialized 50 | by calling sokol_app.h functions. 51 | 52 | LICENSE 53 | ======= 54 | zlib/libpng license 55 | 56 | Copyright (c) 2018 Andre Weissflog 57 | 58 | This software is provided 'as-is', without any express or implied warranty. 59 | In no event will the authors be held liable for any damages arising from the 60 | use of this software. 61 | 62 | Permission is granted to anyone to use this software for any purpose, 63 | including commercial applications, and to alter it and redistribute it 64 | freely, subject to the following restrictions: 65 | 66 | 1. The origin of this software must not be misrepresented; you must not 67 | claim that you wrote the original software. If you use this software in a 68 | product, an acknowledgment in the product documentation would be 69 | appreciated but is not required. 70 | 71 | 2. Altered source versions must be plainly marked as such, and must not 72 | be misrepresented as being the original software. 73 | 74 | 3. This notice may not be removed or altered from any source 75 | distribution. 76 | */ 77 | #define SOKOL_GLUE_INCLUDED 78 | 79 | #if defined(SOKOL_API_DECL) && !defined(SOKOL_GLUE_API_DECL) 80 | #define SOKOL_GLUE_API_DECL SOKOL_API_DECL 81 | #endif 82 | #ifndef SOKOL_GLUE_API_DECL 83 | #if defined(_WIN32) && defined(SOKOL_DLL) && defined(SOKOL_GLUE_IMPL) 84 | #define SOKOL_GLUE_API_DECL __declspec(dllexport) 85 | #elif defined(_WIN32) && defined(SOKOL_DLL) 86 | #define SOKOL_GLUE_API_DECL __declspec(dllimport) 87 | #else 88 | #define SOKOL_GLUE_API_DECL extern 89 | #endif 90 | #endif 91 | 92 | #ifdef __cplusplus 93 | extern "C" { 94 | #endif 95 | 96 | #if defined(SOKOL_GFX_INCLUDED) && defined(SOKOL_APP_INCLUDED) 97 | SOKOL_GLUE_API_DECL sg_context_desc sapp_sgcontext(void); 98 | #endif 99 | 100 | #ifdef __cplusplus 101 | } /* extern "C" */ 102 | #endif 103 | #endif /* SOKOL_GLUE_INCLUDED */ 104 | 105 | /*-- IMPLEMENTATION ----------------------------------------------------------*/ 106 | #ifdef SOKOL_GLUE_IMPL 107 | #define SOKOL_GLUE_IMPL_INCLUDED (1) 108 | #include /* memset */ 109 | 110 | #ifndef SOKOL_API_IMPL 111 | #define SOKOL_API_IMPL 112 | #endif 113 | 114 | #if defined(SOKOL_GFX_INCLUDED) && defined(SOKOL_APP_INCLUDED) 115 | SOKOL_API_IMPL sg_context_desc sapp_sgcontext(void) { 116 | sg_context_desc desc; 117 | memset(&desc, 0, sizeof(desc)); 118 | desc.color_format = (sg_pixel_format) sapp_color_format(); 119 | desc.depth_format = (sg_pixel_format) sapp_depth_format(); 120 | desc.sample_count = sapp_sample_count(); 121 | desc.metal.device = sapp_metal_get_device(); 122 | desc.metal.renderpass_descriptor_cb = sapp_metal_get_renderpass_descriptor; 123 | desc.metal.drawable_cb = sapp_metal_get_drawable; 124 | desc.d3d11.device = sapp_d3d11_get_device(); 125 | desc.d3d11.device_context = sapp_d3d11_get_device_context(); 126 | desc.d3d11.render_target_view_cb = sapp_d3d11_get_render_target_view; 127 | desc.d3d11.depth_stencil_view_cb = sapp_d3d11_get_depth_stencil_view; 128 | desc.wgpu.device = sapp_wgpu_get_device(); 129 | desc.wgpu.render_view_cb = sapp_wgpu_get_render_view; 130 | desc.wgpu.resolve_view_cb = sapp_wgpu_get_resolve_view; 131 | desc.wgpu.depth_stencil_view_cb = sapp_wgpu_get_depth_stencil_view; 132 | return desc; 133 | } 134 | #endif 135 | 136 | #endif /* SOKOL_GLUE_IMPL */ 137 | -------------------------------------------------------------------------------- /Code/ServerApp/info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.yourcompany.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Code/ServerApp/netImguiApp.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sammyfreg/netImgui/47e7bf9059a5d551521cbaff61ea6bab902f7fcb/Code/ServerApp/netImguiApp.ico -------------------------------------------------------------------------------- /Code/ServerApp/netImguiApp.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sammyfreg/netImgui/47e7bf9059a5d551521cbaff61ea6bab902f7fcb/Code/ServerApp/netImguiApp.rc -------------------------------------------------------------------------------- /Code/ServerApp/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by netImguiApp.rc 4 | // 5 | #define IDC_MYICON 2 6 | #define IDD_REMOTEIMGUIAPP_DIALOG 102 7 | #define IDS_APP_TITLE 103 8 | #define IDM_ABOUT 104 9 | #define IDM_EXIT 105 10 | #define IDI_NETIMGUIAPP 107 11 | #define IDI_SMALL 108 12 | #define IDC_NETIMGUIAPP 109 13 | #define IDR_MAINFRAME 128 14 | #define IDC_SYSLINK2 1002 15 | #define IDC_COMMAND1 1004 16 | #define ID_FILE 32771 17 | #define IDC_STATIC -1 18 | 19 | // Next default values for new objects 20 | // 21 | #ifdef APSTUDIO_INVOKED 22 | #ifndef APSTUDIO_READONLY_SYMBOLS 23 | #define _APS_NO_MFC 1 24 | #define _APS_NEXT_RESOURCE_VALUE 129 25 | #define _APS_NEXT_COMMAND_VALUE 32772 26 | #define _APS_NEXT_CONTROL_VALUE 1005 27 | #define _APS_NEXT_SYMED_VALUE 110 28 | #endif 29 | #endif 30 | -------------------------------------------------------------------------------- /Code/ServerApp/small.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sammyfreg/netImgui/47e7bf9059a5d551521cbaff61ea6bab902f7fcb/Code/ServerApp/small.ico -------------------------------------------------------------------------------- /Code/ServerApp/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /Code/ThirdParty/DearImgui/.editorconfig: -------------------------------------------------------------------------------- 1 | # See http://editorconfig.org to read about the EditorConfig format. 2 | # - In theory automatically supported by VS2017+ and most common IDE or text editors. 3 | # - In practice VS2019-VS2022 stills don't trim trailing whitespaces correctly :( 4 | # - Suggest installing this to trim whitespaces: 5 | # GitHub https://github.com/madskristensen/TrailingWhitespace 6 | # VS2019 https://marketplace.visualstudio.com/items?itemName=MadsKristensen.TrailingWhitespaceVisualizer 7 | # VS2022 https://marketplace.visualstudio.com/items?itemName=MadsKristensen.TrailingWhitespace64 8 | # (in spite of its name doesn't only visualize but also trims) 9 | # - Alternative for older VS2010 to VS2015: https://marketplace.visualstudio.com/items?itemName=EditorConfigTeam.EditorConfig 10 | 11 | # top-most EditorConfig file 12 | root = true 13 | 14 | # Default settings: 15 | # Use 4 spaces as indentation 16 | [*] 17 | indent_style = space 18 | indent_size = 4 19 | insert_final_newline = true 20 | trim_trailing_whitespace = true 21 | 22 | [imstb_*] 23 | indent_size = 3 24 | trim_trailing_whitespace = false 25 | 26 | [Makefile] 27 | indent_style = tab 28 | indent_size = 4 29 | -------------------------------------------------------------------------------- /Code/ThirdParty/DearImgui/.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | 3 | *.c text 4 | *.cpp text 5 | *.h text 6 | *.m text 7 | *.mm text 8 | *.md text 9 | *.txt text 10 | *.html text 11 | *.bat text 12 | *.frag text 13 | *.vert text 14 | *.mkb text 15 | *.icf text 16 | 17 | *.sln text eol=crlf 18 | *.vcxproj text eol=crlf 19 | *.vcxproj.filters text eol=crlf 20 | *.natvis text eol=crlf 21 | 22 | Makefile text eol=lf 23 | *.sh text eol=lf 24 | *.pbxproj text eol=lf 25 | *.storyboard text eol=lf 26 | *.plist text eol=lf 27 | 28 | *.png binary 29 | *.ttf binary 30 | *.lib binary 31 | -------------------------------------------------------------------------------- /Code/ThirdParty/DearImgui/.gitignore: -------------------------------------------------------------------------------- 1 | ## OSX artifacts 2 | .DS_Store 3 | 4 | ## Dear ImGui artifacts 5 | imgui.ini 6 | imgui*.ini 7 | 8 | ## General build artifacts 9 | *.o 10 | *.obj 11 | *.exe 12 | examples/*/Debug/* 13 | examples/*/Release/* 14 | examples/*/x64/* 15 | 16 | ## Visual Studio artifacts 17 | .vs 18 | ipch 19 | *.opensdf 20 | *.log 21 | *.pdb 22 | *.ilk 23 | *.user 24 | *.sdf 25 | *.suo 26 | *.VC.db 27 | *.VC.VC.opendb 28 | 29 | ## Getting files created in JSON/Schemas/Catalog/ from a VS2022 update 30 | JSON/ 31 | 32 | ## Commonly used CMake directories 33 | build*/ 34 | 35 | ## Xcode artifacts 36 | project.xcworkspace 37 | xcuserdata 38 | 39 | ## Emscripten artifacts 40 | examples/*.o.tmp 41 | examples/*.out.js 42 | examples/*.out.wasm 43 | examples/example_glfw_opengl3/web/* 44 | examples/example_glfw_wgpu/web/* 45 | examples/example_glfw_wgpu/external/* 46 | examples/example_sdl2_opengl3/web/* 47 | 48 | ## JetBrains IDE artifacts 49 | .idea 50 | cmake-build-* 51 | 52 | ## Unix executables from our example Makefiles 53 | examples/example_glfw_metal/example_glfw_metal 54 | examples/example_glfw_opengl2/example_glfw_opengl2 55 | examples/example_glfw_opengl3/example_glfw_opengl3 56 | examples/example_glut_opengl2/example_glut_opengl2 57 | examples/example_null/example_null 58 | examples/example_sdl2_metal/example_sdl2_metal 59 | examples/example_sdl2_opengl2/example_sdl2_opengl2 60 | examples/example_sdl2_opengl3/example_sdl2_opengl3 61 | examples/example_sdl2_sdlrenderer/example_sdl2_sdlrenderer 62 | -------------------------------------------------------------------------------- /Code/ThirdParty/DearImgui/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2024 Omar Cornut 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Code/ThirdParty/DearImgui/backends/imgui_impl_dx11.h: -------------------------------------------------------------------------------- 1 | // dear imgui: Renderer Backend for DirectX11 2 | // This needs to be used along with a Platform Backend (e.g. Win32) 3 | 4 | // Implemented features: 5 | // [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! 6 | // [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. 7 | // [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'. 8 | // [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. 9 | 10 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 11 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. 12 | // Learn about Dear ImGui: 13 | // - FAQ https://dearimgui.com/faq 14 | // - Getting Started https://dearimgui.com/getting-started 15 | // - Documentation https://dearimgui.com/docs (same as your local docs/ folder). 16 | // - Introduction, links and more at the top of imgui.cpp 17 | 18 | #pragma once 19 | #include "imgui.h" // IMGUI_IMPL_API 20 | #ifndef IMGUI_DISABLE 21 | 22 | struct ID3D11Device; 23 | struct ID3D11DeviceContext; 24 | struct ID3D11SamplerState; 25 | 26 | // Follow "Getting Started" link and check examples/ folder to learn about using backends! 27 | IMGUI_IMPL_API bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context); 28 | IMGUI_IMPL_API void ImGui_ImplDX11_Shutdown(); 29 | IMGUI_IMPL_API void ImGui_ImplDX11_NewFrame(); 30 | IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data); 31 | 32 | // Use if you want to reset your rendering device without losing Dear ImGui state. 33 | IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects(); 34 | IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects(); 35 | 36 | // [BETA] Selected render state data shared with callbacks. 37 | // This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplDX11_RenderDrawData() call. 38 | // (Please open an issue if you feel you need access to more data) 39 | struct ImGui_ImplDX11_RenderState 40 | { 41 | ID3D11Device* Device; 42 | ID3D11DeviceContext* DeviceContext; 43 | ID3D11SamplerState* SamplerDefault; 44 | }; 45 | 46 | #endif // #ifndef IMGUI_DISABLE 47 | -------------------------------------------------------------------------------- /Code/ThirdParty/DearImgui/backends/imgui_impl_glfw.h: -------------------------------------------------------------------------------- 1 | // dear imgui: Platform Backend for GLFW 2 | // This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan, WebGPU..) 3 | // (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) 4 | // (Requires: GLFW 3.1+. Prefer GLFW 3.3+ for full feature support.) 5 | 6 | // Implemented features: 7 | // [X] Platform: Clipboard support. 8 | // [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only). 9 | // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values are obsolete since 1.87 and not supported since 1.91.5] 10 | // [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. 11 | // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+). 12 | // [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. 13 | // Issues: 14 | // [ ] Platform: Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor). 15 | 16 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 17 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. 18 | // Learn about Dear ImGui: 19 | // - FAQ https://dearimgui.com/faq 20 | // - Getting Started https://dearimgui.com/getting-started 21 | // - Documentation https://dearimgui.com/docs (same as your local docs/ folder). 22 | // - Introduction, links and more at the top of imgui.cpp 23 | 24 | #pragma once 25 | #include "imgui.h" // IMGUI_IMPL_API 26 | #ifndef IMGUI_DISABLE 27 | 28 | struct GLFWwindow; 29 | struct GLFWmonitor; 30 | 31 | // Follow "Getting Started" link and check examples/ folder to learn about using backends! 32 | IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks); 33 | IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks); 34 | IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool install_callbacks); 35 | IMGUI_IMPL_API void ImGui_ImplGlfw_Shutdown(); 36 | IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame(); 37 | 38 | // Emscripten related initialization phase methods (call after ImGui_ImplGlfw_InitForOpenGL) 39 | #ifdef __EMSCRIPTEN__ 40 | IMGUI_IMPL_API void ImGui_ImplGlfw_InstallEmscriptenCallbacks(GLFWwindow* window, const char* canvas_selector); 41 | //static inline void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_selector) { ImGui_ImplGlfw_InstallEmscriptenCallbacks(nullptr, canvas_selector); } } // Renamed in 1.91.0 42 | #endif 43 | 44 | // GLFW callbacks install 45 | // - When calling Init with 'install_callbacks=true': ImGui_ImplGlfw_InstallCallbacks() is called. GLFW callbacks will be installed for you. They will chain-call user's previously installed callbacks, if any. 46 | // - When calling Init with 'install_callbacks=false': GLFW callbacks won't be installed. You will need to call individual function yourself from your own GLFW callbacks. 47 | IMGUI_IMPL_API void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window); 48 | IMGUI_IMPL_API void ImGui_ImplGlfw_RestoreCallbacks(GLFWwindow* window); 49 | 50 | // GFLW callbacks options: 51 | // - Set 'chain_for_all_windows=true' to enable chaining callbacks for all windows (including secondary viewports created by backends or by user) 52 | IMGUI_IMPL_API void ImGui_ImplGlfw_SetCallbacksChainForAllWindows(bool chain_for_all_windows); 53 | 54 | // GLFW callbacks (individual callbacks to call yourself if you didn't install callbacks) 55 | IMGUI_IMPL_API void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused); // Since 1.84 56 | IMGUI_IMPL_API void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered); // Since 1.84 57 | IMGUI_IMPL_API void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y); // Since 1.87 58 | IMGUI_IMPL_API void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods); 59 | IMGUI_IMPL_API void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset); 60 | IMGUI_IMPL_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); 61 | IMGUI_IMPL_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c); 62 | IMGUI_IMPL_API void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor* monitor, int event); 63 | 64 | // GLFW helpers 65 | IMGUI_IMPL_API void ImGui_ImplGlfw_Sleep(int milliseconds); 66 | 67 | #endif // #ifndef IMGUI_DISABLE 68 | -------------------------------------------------------------------------------- /Code/ThirdParty/DearImgui/backends/imgui_impl_opengl3.h: -------------------------------------------------------------------------------- 1 | // dear imgui: Renderer Backend for modern OpenGL with shaders / programmatic pipeline 2 | // - Desktop GL: 2.x 3.x 4.x 3 | // - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0) 4 | // This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..) 5 | 6 | // Implemented features: 7 | // [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID! 8 | // [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices (Desktop OpenGL only). 9 | // [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. 10 | 11 | // About WebGL/ES: 12 | // - You need to '#define IMGUI_IMPL_OPENGL_ES2' or '#define IMGUI_IMPL_OPENGL_ES3' to use WebGL or OpenGL ES. 13 | // - This is done automatically on iOS, Android and Emscripten targets. 14 | // - For other targets, the define needs to be visible from the imgui_impl_opengl3.cpp compilation unit. If unsure, define globally or in imconfig.h. 15 | 16 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 17 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. 18 | // Learn about Dear ImGui: 19 | // - FAQ https://dearimgui.com/faq 20 | // - Getting Started https://dearimgui.com/getting-started 21 | // - Documentation https://dearimgui.com/docs (same as your local docs/ folder). 22 | // - Introduction, links and more at the top of imgui.cpp 23 | 24 | // About GLSL version: 25 | // The 'glsl_version' initialization parameter should be nullptr (default) or a "#version XXX" string. 26 | // On computer platform the GLSL version default to "#version 130". On OpenGL ES 3 platform it defaults to "#version 300 es" 27 | // Only override if your GL version doesn't handle this GLSL version. See GLSL version table at the top of imgui_impl_opengl3.cpp. 28 | 29 | #pragma once 30 | #include "imgui.h" // IMGUI_IMPL_API 31 | #ifndef IMGUI_DISABLE 32 | 33 | // Follow "Getting Started" link and check examples/ folder to learn about using backends! 34 | IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = nullptr); 35 | IMGUI_IMPL_API void ImGui_ImplOpenGL3_Shutdown(); 36 | IMGUI_IMPL_API void ImGui_ImplOpenGL3_NewFrame(); 37 | IMGUI_IMPL_API void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data); 38 | 39 | // (Optional) Called by Init/NewFrame/Shutdown 40 | IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateFontsTexture(); 41 | IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyFontsTexture(); 42 | IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateDeviceObjects(); 43 | IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects(); 44 | 45 | // Configuration flags to add in your imconfig file: 46 | //#define IMGUI_IMPL_OPENGL_ES2 // Enable ES 2 (Auto-detected on Emscripten) 47 | //#define IMGUI_IMPL_OPENGL_ES3 // Enable ES 3 (Auto-detected on iOS/Android) 48 | 49 | // You can explicitly select GLES2 or GLES3 API by using one of the '#define IMGUI_IMPL_OPENGL_LOADER_XXX' in imconfig.h or compiler command-line. 50 | #if !defined(IMGUI_IMPL_OPENGL_ES2) \ 51 | && !defined(IMGUI_IMPL_OPENGL_ES3) 52 | 53 | // Try to detect GLES on matching platforms 54 | #if defined(__APPLE__) 55 | #include 56 | #endif 57 | #if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) || (defined(__ANDROID__)) 58 | #define IMGUI_IMPL_OPENGL_ES3 // iOS, Android -> GL ES 3, "#version 300 es" 59 | #elif defined(__EMSCRIPTEN__) || defined(__amigaos4__) 60 | #define IMGUI_IMPL_OPENGL_ES2 // Emscripten -> GL ES 2, "#version 100" 61 | #else 62 | // Otherwise imgui_impl_opengl3_loader.h will be used. 63 | #endif 64 | 65 | #endif 66 | 67 | #endif // #ifndef IMGUI_DISABLE 68 | -------------------------------------------------------------------------------- /Code/ThirdParty/DearImgui/backends/imgui_impl_win32.h: -------------------------------------------------------------------------------- 1 | // dear imgui: Platform Backend for Windows (standard windows API for 32-bits AND 64-bits applications) 2 | // This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) 3 | 4 | // Implemented features: 5 | // [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui) 6 | // [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen. 7 | // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy VK_* values are obsolete since 1.87 and not supported since 1.91.5] 8 | // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. 9 | // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. 10 | // [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. 11 | 12 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 13 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. 14 | // Learn about Dear ImGui: 15 | // - FAQ https://dearimgui.com/faq 16 | // - Getting Started https://dearimgui.com/getting-started 17 | // - Documentation https://dearimgui.com/docs (same as your local docs/ folder). 18 | // - Introduction, links and more at the top of imgui.cpp 19 | 20 | #pragma once 21 | #include "imgui.h" // IMGUI_IMPL_API 22 | #ifndef IMGUI_DISABLE 23 | 24 | // Follow "Getting Started" link and check examples/ folder to learn about using backends! 25 | IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd); 26 | IMGUI_IMPL_API bool ImGui_ImplWin32_InitForOpenGL(void* hwnd); 27 | IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown(); 28 | IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame(); 29 | 30 | // Win32 message handler your application need to call. 31 | // - Intentionally commented out in a '#if 0' block to avoid dragging dependencies on from this helper. 32 | // - You should COPY the line below into your .cpp code to forward declare the function and then you can call it. 33 | // - Call from your application's message handler. Keep calling your message handler unless this function returns TRUE. 34 | 35 | #if 0 36 | extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 37 | #endif 38 | 39 | // DPI-related helpers (optional) 40 | // - Use to enable DPI awareness without having to create an application manifest. 41 | // - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps. 42 | // - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc. 43 | // but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime, 44 | // neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies. 45 | IMGUI_IMPL_API void ImGui_ImplWin32_EnableDpiAwareness(); 46 | IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd); // HWND hwnd 47 | IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor); // HMONITOR monitor 48 | 49 | // Transparency related helpers (optional) [experimental] 50 | // - Use to enable alpha compositing transparency with the desktop. 51 | // - Use together with e.g. clearing your framebuffer with zero-alpha. 52 | IMGUI_IMPL_API void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd); // HWND hwnd 53 | 54 | #endif // #ifndef IMGUI_DISABLE 55 | -------------------------------------------------------------------------------- /Code/ThirdParty/glfw/COPYING.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2002-2006 Marcus Geelnard 2 | Copyright (c) 2006-2010 Camilla Berglund 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgment in the product documentation would 15 | be appreciated but is not required. 16 | 17 | 2. Altered source versions must be plainly marked as such, and must not 18 | be misrepresented as being the original software. 19 | 20 | 3. This notice may not be removed or altered from any source 21 | distribution. 22 | 23 | -------------------------------------------------------------------------------- /Code/ThirdParty/glfw/lib-macos-universal/libglfw.3.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sammyfreg/netImgui/47e7bf9059a5d551521cbaff61ea6bab902f7fcb/Code/ThirdParty/glfw/lib-macos-universal/libglfw.3.dylib -------------------------------------------------------------------------------- /Code/ThirdParty/glfw/lib-macos-universal/libglfw3.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sammyfreg/netImgui/47e7bf9059a5d551521cbaff61ea6bab902f7fcb/Code/ThirdParty/glfw/lib-macos-universal/libglfw3.a -------------------------------------------------------------------------------- /Code/ThirdParty/glfw/lib-vc2017-64/glfw3_mt.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sammyfreg/netImgui/47e7bf9059a5d551521cbaff61ea6bab902f7fcb/Code/ThirdParty/glfw/lib-vc2017-64/glfw3_mt.lib -------------------------------------------------------------------------------- /Code/ThirdParty/glfw/lib-vc2019-32/glfw3_mt.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sammyfreg/netImgui/47e7bf9059a5d551521cbaff61ea6bab902f7fcb/Code/ThirdParty/glfw/lib-vc2019-32/glfw3_mt.lib -------------------------------------------------------------------------------- /Code/ThirdParty/glfw/lib-vc2019-32/glfw3_mtd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sammyfreg/netImgui/47e7bf9059a5d551521cbaff61ea6bab902f7fcb/Code/ThirdParty/glfw/lib-vc2019-32/glfw3_mtd.lib -------------------------------------------------------------------------------- /Code/ThirdParty/glfw/lib-vc2019-64/glfw3_mt.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sammyfreg/netImgui/47e7bf9059a5d551521cbaff61ea6bab902f7fcb/Code/ThirdParty/glfw/lib-vc2019-64/glfw3_mt.lib -------------------------------------------------------------------------------- /Code/ThirdParty/glfw/lib-vc2019-64/glfw3_mtd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sammyfreg/netImgui/47e7bf9059a5d551521cbaff61ea6bab902f7fcb/Code/ThirdParty/glfw/lib-vc2019-64/glfw3_mtd.lib -------------------------------------------------------------------------------- /Code/ThirdParty/glfw/lib-vc2022-32/glfw3_mt.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sammyfreg/netImgui/47e7bf9059a5d551521cbaff61ea6bab902f7fcb/Code/ThirdParty/glfw/lib-vc2022-32/glfw3_mt.lib -------------------------------------------------------------------------------- /Code/ThirdParty/glfw/lib-vc2022-32/glfw3_mtd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sammyfreg/netImgui/47e7bf9059a5d551521cbaff61ea6bab902f7fcb/Code/ThirdParty/glfw/lib-vc2022-32/glfw3_mtd.lib -------------------------------------------------------------------------------- /Code/ThirdParty/glfw/lib-vc2022-64/glfw3_mt.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sammyfreg/netImgui/47e7bf9059a5d551521cbaff61ea6bab902f7fcb/Code/ThirdParty/glfw/lib-vc2022-64/glfw3_mt.lib -------------------------------------------------------------------------------- /Code/ThirdParty/glfw/lib-vc2022-64/glfw3_mtd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sammyfreg/netImgui/47e7bf9059a5d551521cbaff61ea6bab902f7fcb/Code/ThirdParty/glfw/lib-vc2022-64/glfw3_mtd.lib -------------------------------------------------------------------------------- /Code/ThirdParty/quicklz.h: -------------------------------------------------------------------------------- 1 | #ifndef QLZ_HEADER 2 | #define QLZ_HEADER 3 | 4 | // Fast data compression library 5 | // Copyright (C) 2006-2011 Lasse Mikkel Reinhold 6 | // lar@quicklz.com 7 | // 8 | // QuickLZ can be used for free under the GPL 1, 2 or 3 license (where anything 9 | // released into public must be open source) or under a commercial license if such 10 | // has been acquired (see http://www.quicklz.com/order.html). The commercial license 11 | // does not cover derived or ported versions created by third parties under GPL. 12 | 13 | // You can edit following user settings. Data must be decompressed with the same 14 | // setting of QLZ_COMPRESSION_LEVEL and QLZ_STREAMING_BUFFER as it was compressed 15 | // (see manual). If QLZ_STREAMING_BUFFER > 0, scratch buffers must be initially 16 | // zeroed out (see manual). First #ifndef makes it possible to define settings from 17 | // the outside like the compiler command line. 18 | 19 | // 1.5.0 final 20 | 21 | #ifndef QLZ_COMPRESSION_LEVEL 22 | 23 | // 1 gives fastest compression speed. 3 gives fastest decompression speed and best 24 | // compression ratio. 25 | #define QLZ_COMPRESSION_LEVEL 1 26 | //#define QLZ_COMPRESSION_LEVEL 2 27 | //#define QLZ_COMPRESSION_LEVEL 3 28 | 29 | // If > 0, zero out both states prior to first call to qlz_compress() or qlz_decompress() 30 | // and decompress packets in the same order as they were compressed 31 | #define QLZ_STREAMING_BUFFER 0 32 | //#define QLZ_STREAMING_BUFFER 100000 33 | //#define QLZ_STREAMING_BUFFER 1000000 34 | 35 | // Guarantees that decompression of corrupted data cannot crash. Decreases decompression 36 | // speed 10-20%. Compression speed not affected. 37 | //#define QLZ_MEMORY_SAFE 38 | #endif 39 | 40 | #define QLZ_VERSION_MAJOR 1 41 | #define QLZ_VERSION_MINOR 5 42 | #define QLZ_VERSION_REVISION 0 43 | 44 | // Using size_t, memset() and memcpy() 45 | #include 46 | 47 | // Verify compression level 48 | #if QLZ_COMPRESSION_LEVEL != 1 && QLZ_COMPRESSION_LEVEL != 2 && QLZ_COMPRESSION_LEVEL != 3 49 | #error QLZ_COMPRESSION_LEVEL must be 1, 2 or 3 50 | #endif 51 | 52 | typedef unsigned int ui32; 53 | typedef unsigned short int ui16; 54 | 55 | // Decrease QLZ_POINTERS for level 3 to increase compression speed. Do not touch any other values! 56 | #if QLZ_COMPRESSION_LEVEL == 1 57 | #define QLZ_POINTERS 1 58 | #define QLZ_HASH_VALUES 4096 59 | #elif QLZ_COMPRESSION_LEVEL == 2 60 | #define QLZ_POINTERS 4 61 | #define QLZ_HASH_VALUES 2048 62 | #elif QLZ_COMPRESSION_LEVEL == 3 63 | #define QLZ_POINTERS 16 64 | #define QLZ_HASH_VALUES 4096 65 | #endif 66 | 67 | // Detect if pointer size is 64-bit. It's not fatal if some 64-bit target is not detected because this is only for adding an optional 64-bit optimization. 68 | #if defined _LP64 || defined __LP64__ || defined __64BIT__ || _ADDR64 || defined _WIN64 || defined __arch64__ || __WORDSIZE == 64 || (defined __sparc && defined __sparcv9) || defined __x86_64 || defined __amd64 || defined __x86_64__ || defined _M_X64 || defined _M_IA64 || defined __ia64 || defined __IA64__ 69 | #define QLZ_PTR_64 70 | #endif 71 | 72 | // hash entry 73 | typedef struct 74 | { 75 | #if QLZ_COMPRESSION_LEVEL == 1 76 | ui32 cache; 77 | #if defined QLZ_PTR_64 && QLZ_STREAMING_BUFFER == 0 78 | unsigned int offset; 79 | #else 80 | const unsigned char *offset; 81 | #endif 82 | #else 83 | const unsigned char *offset[QLZ_POINTERS]; 84 | #endif 85 | 86 | } qlz_hash_compress; 87 | 88 | typedef struct 89 | { 90 | #if QLZ_COMPRESSION_LEVEL == 1 91 | const unsigned char *offset; 92 | #else 93 | const unsigned char *offset[QLZ_POINTERS]; 94 | #endif 95 | } qlz_hash_decompress; 96 | 97 | 98 | // states 99 | typedef struct 100 | { 101 | #if QLZ_STREAMING_BUFFER > 0 102 | unsigned char stream_buffer[QLZ_STREAMING_BUFFER]; 103 | #endif 104 | size_t stream_counter; 105 | qlz_hash_compress hash[QLZ_HASH_VALUES]; 106 | unsigned char hash_counter[QLZ_HASH_VALUES]; 107 | } qlz_state_compress; 108 | 109 | 110 | #if QLZ_COMPRESSION_LEVEL == 1 || QLZ_COMPRESSION_LEVEL == 2 111 | typedef struct 112 | { 113 | #if QLZ_STREAMING_BUFFER > 0 114 | unsigned char stream_buffer[QLZ_STREAMING_BUFFER]; 115 | #endif 116 | qlz_hash_decompress hash[QLZ_HASH_VALUES]; 117 | unsigned char hash_counter[QLZ_HASH_VALUES]; 118 | size_t stream_counter; 119 | } qlz_state_decompress; 120 | #elif QLZ_COMPRESSION_LEVEL == 3 121 | typedef struct 122 | { 123 | #if QLZ_STREAMING_BUFFER > 0 124 | unsigned char stream_buffer[QLZ_STREAMING_BUFFER]; 125 | #endif 126 | #if QLZ_COMPRESSION_LEVEL <= 2 127 | qlz_hash_decompress hash[QLZ_HASH_VALUES]; 128 | #endif 129 | size_t stream_counter; 130 | } qlz_state_decompress; 131 | #endif 132 | 133 | 134 | #if defined (__cplusplus) 135 | extern "C" { 136 | #endif 137 | 138 | // Public functions of QuickLZ 139 | size_t qlz_size_decompressed(const char *source); 140 | size_t qlz_size_compressed(const char *source); 141 | size_t qlz_compress(const void *source, char *destination, size_t size, qlz_state_compress *state); 142 | size_t qlz_decompress(const char *source, void *destination, qlz_state_decompress *state); 143 | int qlz_get_setting(int setting); 144 | 145 | #if defined (__cplusplus) 146 | } 147 | #endif 148 | 149 | #endif 150 | 151 | -------------------------------------------------------------------------------- /GenerateProject.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | pushd %~dp0 3 | 4 | :: Detect if user has fetched previous version of DearImgui to also generate some compatibility compiling test 5 | set CompatibilityCS=@'Build/nocompatibility.sharpmake.cs' 6 | if exist "_generated\imgui\compatibility.sharpmake.cs" set CompatibilityCS=@'_generated/imgui/compatibility.sharpmake.cs' 7 | 8 | .\Build\Sharpmake\Sharpmake.Application.exe /sources(@'Build/shared.sharpmake.cs', %CompatibilityCS%, @'Build/netImgui.sharpmake.cs') 9 | popd 10 | 11 | IF "%1" == "1" GOTO end 12 | pause 13 | 14 | :end -------------------------------------------------------------------------------- /GenerateProject.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd "$(dirname "$0")" 4 | 5 | # Detect if the compatibility.sharpmake.cs file exists, and set CompatibilityCS accordingly 6 | CompatibilityCS="Build/nocompatibility.sharpmake.cs" 7 | if [ -f "_generated/imgui/compatibility.sharpmake.cs" ]; then 8 | CompatibilityCS="_generated/imgui/compatibility.sharpmake.cs" 9 | fi 10 | 11 | ./Build/Sharpmake/Sharpmake.Application "/sources(@'Build/shared.sharpmake_mac.cs', @'$CompatibilityCS', @'Build/netImgui.sharpmake.cs') /verbose() " 12 | 13 | if [ "$1" = "1" ]; then 14 | exit 0 15 | fi 16 | 17 | read -p "Press any key to continue..." -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Sammy Fatnassi (Github: @Sammyfreg) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | --------------------------------------------------------------------------------