Code Monkey home page Code Monkey logo

netimgui's Introduction

Summary

(Build VS2022 Main) (Build VS2022 Dev)

Release Version Release Date Downloads Forks Stars License

NetImgui is a library to remotely display and control Dear ImGui menus with an associated NetImgui Server application. Designed to painlessly integrate into existing codebase with few changes required. It allows any program using Dear ImGui to receives input from a remote PC and then forwards its UI rendering to it (textures, vertices, indices, draw commands).

NetImgui

Purpose

Initially created to assist game developers in debugging their game running on a game console or smartphone, from a PC. However, its use extends to wider applications. The only requirements are that a program is using Dear ImGui using C++ and available TCP/IP communications.

1. UI for devices without display/input.

Some applications lack display and inputs access, preventing feedbacks and easy control. It could be a program running on a Raspberry Pie device, or Unreal 4 running in server mode, etc . . . Using NetImgui allows the display of a user interface with full control on your PC while the logic remains on the client application itself.

Note: SampleNoBackend demonstrate using Dear ImGui without any backend implementation. It is a simple console application connecting to the NetImguiServer to draw its Imgui content. There is no rendering/input backend that's usually require by Dear ImGui

2. Ease of use

While inputs might be available on a particular device (keyboard, gamepad, . . .), it might still not be convenient for certain aspect. For example, text input is still more comfortable on a physical keyboard than on a smartphone. Idem for gaming consoles with gamepads control or VR development.

3. Declutter display

Dear ImGui is often used to display relevant debug information during development, but UI elements can obscure the regular content. NetImgui sends the UI content to a remote window, leaving the original display clutter-free and with the freedom to use the entire screen for more elaborate content.

Before

DearImGui

With NetImgui

NetImgui

How it works

Here is a quick overview of the logic behind using the NetImgui Server and one (or more) program using the NetImgui Client code.

NetImgui

1. (NetImgui Server) Capture user's inputs with mouse/keyboard

2. (NetImgui Server) Send the Inputs to client and request a draw update

3. (NetImgui Client) Draw the Dear ImGui content normally (without need to display on client)

4. (NetImgui Client) Send the drawing results to server

5. (NetImgui Server) Receives the drawing result and display them

6. Go back to 1

Note

The NetImgui Server application currently compiles under Windows and Mac, but few changes are required to properly have it running under other Operating Systems. To compile for Mac, modify NetImguiServer_App.h to enable the GLFW_GL3 rendering API.

Integration

  1. Download the latest version of the NetImgui library.
  2. Add the content of Code\Client to your codebase.
  3. In your codebase:
    • [once]
      • Call NetImgui::Startup() (at program start).
      • Call NetImgui::ConnectToApp() or NetImgui::ConnectFromApp().
      • Call NetImgui::Shutdown() (at program exit).
    • [every redraw]
      • Draw your ImGui menu as usual.
      • If Dear ImGui 1.80 and lower (or want frameskip support).
        • Replace call to ImGui::NewFrame() with NetImgui::NewFrame().
        • Replace call to ImGui::Render() / ImGui::EndFrame() with NetImgui::EndFrame().
  4. Start the NetImgui server application and connect your application to it.
  • More integration details can be found on the Wiki.
  • Multiple samples are also provided in the depot, providing additional insights.

Note

  • Connection between NetImgui Server and a netImGui Client can be achieved in 4 different ways.

  • Server waits for connection and :

    • (A) Client calls ConnectToApp() with the Server address.
  • Client calls ConnectFromApp() then waits for connection and :

    • (B) Server configure the Client's address and connect to it.
    • (C) Server is launched with the Client's address in the commandline.
    • (D) Server receives a Client's address from another application, through Windows named pipe : \.\pipe\netImgui'.
  • Advanced: Different Dear ImGui content can be displayed locally and remotely at the same time. Look at SampleDualUI for more information.

  • NetImgui::IsConnected() and NetImgui::IsDrawingRemote() can be used during Dear ImGui drawing, helping to make selective decisions on the content to draw based on where it will be displayed.

Dear Imgui versions

  • Tested against Dear ImGui versions 1.71 to 1.90.
  • Note: Should support other versions without too much difficulties.
  • Note: See Build\GenerateCompatibilityTest.bat for an exact list of tested versions.

Related

Related projects making use of NetImgui.

  • Unreal NetImgui : Unreal 4 plugin adding access to Dear ImGui and NetImgui functionalities. Unlike the next plugin, it is a simple implementation with only remote access possible (no Dear ImGui drawing over the game).
  • Unreal ImGui : Unreal 4 Plugin adding Dear ImGui drawing support over your game and editor display. The net_imgui branch of this repository contains an integration of this NetImgui library for remote access and is ready to go.
  • For Unreal 4 developpers with their own Dear ImGui integration, Unreal NetImgui has support for an Imgui Unreal Commands window that can be of interest. The code can easily be imported in your own codebase, with no dependency to Unreal NetImgui proper. NetImgui

Release notes

To do

  • Support of additional texture formats
  • Handle Linear/sRGB vertex color format
  • Add logging information to NetImgui Server Application
  • Add new Dear ImGui multi windows support (docking branch)
  • Commands to assign custom backgrounds
  • Add compression to data between Client and Server
  • Support of monitor DPI
  • Support for connection takeover

Version 1.11

(2024/05/26)

  • API Changes
    • None
  • Added Connection 'Take Over' support
    • When a NetImgui Client is already connected to a NetImgui Server, user of a second instance of a NetImgui Server now have the option of Taking over the connection.
    • This is useful when the Client Config on a NetImgui Server is set to Auto Connect and a user on a second PC wish to still connect to the client.
    • Users can enable the option Block TakerOver in their Client Config to prevent this possibility.
  • Various small changes and fixes
    • Tested Dear ImGui versions up to 1.90.6 and updated the NetImgui Server to it (docking branch).

Older

Release Notes

Contact

It seems that various gaming studios are making use of this code. I would enjoy hearing back from library users, for general comments and feedbacks. Always interested in learning of people usercase. I can be reached through my GitHub profile (email or twitter) or creating a new entry in GitHub Issue.

Credits

Sincere thanks to Omar Cornut for the incredible work on Dear ImGui.

Support of image formats via stb_image.h by Sean Barrett (public domain).

Support of Solutions generation via Sharpmake by Ubisoft (public domain).

Support of Posix sockets thanks to Aaron Lieberman.

Support of json save file via nlohmann json

netimgui's People

Contributors

aaronlieberman avatar dri-richard avatar lemantisee avatar rtjeffk avatar saarg avatar sammyfreg avatar theanswer avatar thisisagoodname avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

netimgui's Issues

Linux server application

Hello, is there any plan for a Linux server application?
i.e. one that can on Linux render the UI etc. from a remote session.
Or maybe some instructions how to build/port it for Linux?
If it's not too complex maybe I'll try it myself.

It crashes due to the balance between thread release and Shutdown()

Describe the bug

netimugiLib ใ‚’่‡ชๅˆ†ใฎใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆ(Win64)ใซๅฎŸ่ฃ…ใ—ใ‚ˆใ†ใจใ—ใŸ้š›ใ€
ใƒ—ใƒญใ‚ฐใƒฉใƒ ใ‚’็ต‚ไบ†ใ™ใ‚‹้š›ใซใ‚ฏใƒฉใƒƒใ‚ทใƒฅใ™ใ‚‹ใ“ใจใŒใ‚ใ‚Š่ชฟในใฆใฟใŸใจใ“ใ‚ใ€
ๅŽŸๅ› ใฏCommunicationsClient()/CommunicationsHost()ใงpClientใŒไธๅฎšใงใ‚จใƒฉใƒผใจใชใฃใฆใ„ใพใ—ใŸใ€‚
Shutdown()ใงใ‚นใƒฌใƒƒใƒ‰ใฎ็ต‚ไบ†ใ‚’ๅพ…ใฃใฆใ„ใชใ„ใฎใŒๅŽŸๅ› ใ ใจๆ€ใ†ใฎใงใ™ใŒใ„ใ‹ใŒใงใ—ใ‚‡ใ†ใ‹๏ผŸ
(่‹ฑ่ชžใŒ่‹ฆๆ‰‹ใชใฎใงใ€ๆ—ฅๆœฌ่ชžใ‚’Google็ฟป่จณใงๅค‰ๆ›ดใ—ใŸใ‚‚ใฎใ‚’ไธ‹่จ˜ใซ่จ˜่ผ‰ใ•ใ›ใฆใ„ใŸใ ใใพใ™)


When I tried to implement netimugiLib in my project (Win64)
When I checked it, it sometimes crashed when quitting the program.
The cause was CommunicationsClient () / CommunicationsHost () where pClient was undefined and an error occurred.
I think it's because Shutdown () isn't waiting for the thread to finish.
(Since I am not good at English, I will describe the Japanese translated by Google Translate below)

Desktop (please complete the following information):

  • OS : Windows
  • Build : VisualStudio2019

Additional context

Github ใงใฎไฝœๆณ•ใชใฉใฏใ‚ใ‹ใฃใฆใ„ใชใ„ใŸใ‚ใ€ๅ ฑๅ‘Šใชใฉใซๅ•้กŒใŒใ‚ใ‚Œใฐ็”ณใ—่จณใ‚ใ‚Šใพใ›ใ‚“ใ€‚


I don't know how to do it on Github, so I'm sorry if there is a problem with the report.

Server render delegates

In this PR I introduce the possible refactor of render specific platform callbacks on server side.
The main idea is separate library "core" code from user code. I made it with more OOP style and move render callback to delegate system. If user wants to change default render callbacks he just add own delegate and doesn't modifies library core code.
This also provides more smooth update process for new version of library on user side.
#30

Supporting websocket

Snipaste_2023-07-06_16-53-55

Hello,

I managed to make NetImguiServerApp running on html , but on html5 you can only use websocket API.
It would be fine if netImgui client will support websocket.

Thank you!

Texture callback

As described in issue #8.

When parsing the drawing commands, would be nice to auto-detect missing textures and let user know about them (using a callback). They could then send the data the the netImgui server. This would make it so less code change would be required in original user codebase, could be centralized into the callback.

However, this is not trivial, since user still need access to texture data, and often will have been release from CPU side memory and only reside on the GPU.

Usage of SO_REUSEPORT

During my tests on Linux I noticed that I could run two instanced of the server and both would listen on the same port (i.e. default 8888). After that the clients (SampleNoBackend in my case) would connect to one or the other instance of the server in an arbitrary manner.

I think this behavior is due to the use of SO_REUSEPORT found here

setsockopt(ListenSocket, SOL_SOCKET, SO_REUSEPORT, &flag, sizeof(flag));

I guess this is useful if the server(s) are making the connections to the client(s) but in the opposite direction it results in undefined behavior; we never know which server is going to accept the client's connection first.

I would expect that the client is capable of specifying which server port it wants to connect to (with existing default port) and the servers would open their own listening port (again with existing default). In this scenario the servers should fail to open the same listening port more than once.

Server draw lost message when "Use 32-bit vertex indices"

Describe the bug
A clear and concise description of what the bug is.

To Reproduce
Steps to reproduce the behavior:

  1. cancel annotation โ€˜#define ImDrawIdx unsigned intโ€™ in imconfig.h both in netImgui and UnrealImGui.
  2. compile this project and run.
  3. draw over ten thousand circle in imgui.
  4. server seem like not execute draw all circle.

Expected behavior
server behavior same like local

Screenshots
NetImguiServerError
NetImguiServerErrorGIF

Desktop (please complete the following information):

  • OS: Windows
  • Version [netImgui 1.5]

Additional context
Thank you upgrade UnrealImGui to netImgui 1.5! I want draw meta world all entity location (count will over ten thousand). But looks like remote server can't draw so many graphics.

Why is Client_AddFontTexture done from a modified back-end and not from user app?

Is your feature request related to a problem? Please describe.
In your sample, back-ends like imgui_impl_dx11.cpp were modified to add a call to Client_AddFontTexture().

Describe the solution you'd like
It seems like the SampleBasic could just call Client_AddFontTexture() itself, given the data provided by GetTexDataAsRGBA32()?
Not only this would make the call more visible, it would allow not modifying back-ends.
IHMO back-ends should never be modified.
Ditto for the const ImDrawData* why not casting on your end?

Missing texture replace

Hi! In our project client app provides the video stream witch I would like to embed in ui on server side. Previously we implement it very roughly:

  1. On client app draws texture with ImGui::Image and send texture and texture id via third party tool (NDI)
  2. On server side receive texture and texture id from third party tool
  3. Provides to netimgui on server side texture data by texture id which was used in ImGui::Image on client side

So, I interested is netimgui project interesting in this feature? I can make PR with describes the idea.
Seems it very close to #10 but difference in that I'm want to provide texture in each frame on server side.

Server app crashes when more than 64 textures are synchonized by network

Describe the bug
First for all, thank you for a greate library!

Server app crashes when more than 64 textures are synchonized by network.

I think the problem can be in undefined behavior between thread which read and thread which write texures to Client::mpPendingTextures buffer. Client::ReceiveTexture method can write texture to same array cell which is reading now in Client::ProcessPendingTextures method. This is"data race" and can crash the server app. There is no any multithread synchronization (mutex, conditional values, etc.) between this two calls. Only read/write operation on index is synced by atomic values.

If I change Client::mpPendingTextures to 128 size the problem is gone.

In my project I reimplement this logic in a way to use std::queue to push/pop textures in different threads and synchonize this calls wtith std::mutex (conditional values) and checking max size of queue (64). Made PR for this change #27 .

To Reproduce
Steps to reproduce the behavior:

  1. Sync more than 64 textures between client and server

Expected behavior
All textures synced correctlly without undefined behavior

Desktop (please complete the following information):

  • OS: Windows 10
  • Version 1.75

Multiple calls of ConnectFromApp results in multiple contextHooks being added

Hey Sammy, I love what you've done with netImgui, but I think I've found a bug.

Whenever ConnectFromApp() is called, it Disconnects() and then reconnects and calls client.ContextInitialize() which adds a new context hook (if NETIMGUI_IMGUI_CALLBACK_ENABLED is defined). Currently, the Disconnect doesn't remove the hook, so we end up with a new hook being added every time ConnectFromApp() is called.

You can repro this by running a client, connecting to a server then shutting the server down and then starting it and reconnecting. Every time you do this, a new hook is added and the result is that the server only displays a valid update once every 'N' frames.

Checking mhImguiHookNewframe in ContextInitialize() and only adding a new hook if it's zero works, as should removing the hook in Disconnect() (currently the destructor for ClientInfo is the only place that removes the hook.)

Simplifying integration with hook registration in Dear ImGui?

I added NetImGui to a test project today.
For reference, it took me 45 minutes to figure things out from scratch (quite good!), and the following lines of codes.

#pragma comment(lib, "Ws2_32")
#include <NetImgui_Api.h>
bool ret = NetImgui::Startup();
IM_ASSERT(ret);
if (NetImgui::ConnectToApp("Sandbox Client", "localhost", 8888U, true))
{
    ImFontAtlas* atlas = ImGui::GetIO().Fonts;
    app->NewFrame(app); // FIXME: enforce texture upload. Should do the upload lazily in the main loop instead
    unsigned char* pixels = NULL;
    atlas->GetTexDataAsRGBA32(&pixels, NULL, NULL, NULL);
    NetImgui::SendDataTexture(
             (uint64_t)atlas->TexID, atlas->TexPixelsRGBA32, 
             atlas->TexWidth, atlas->TexHeight, NetImgui::eTexFormat::kTexFmtRGBA8);
}
if (NetImgui::IsConnected())
    NetImgui::NewFrame();
else
    ImGui::NewFrame();
if (NetImgui::IsConnected())
    NetImgui::EndFrame();
else
    ImGui::Render();

As discussed in #8 i believe that NetImgui could handle the texture aspect automatically.

My suggestion:

I could add custom hook registrations in ImGui that would allow NetImgui to register function to be called in NewFrame() / EndFrame() / Render(). This way, the user wouldn't even have to call NetImgui::NewFrame(); or NetImgui::EndFrame();.

Do you think that would that be useful and you can use that?

The TestEngine already has custom hooks that ImGui calls and I would simply replace those specialized hooks with a more generic system, so it's not much work on ImGui side

Input broken with 1.89.9

Describe the bug
Using ImGui version 1.89.9, the server app seems to be having issues with input. Specifically, if the mouse if being moved, the mouse position updates properly. If you stop moving the mouse, the mouse alternates each frame between an invalid position and a valid position.

I did some debugging on the server app, and it seems ok, so my guess is that there is something that's changed with input that the client is not handling properly

This was working properly for us on 1.89.7

To Reproduce
Steps to reproduce the behavior:

  1. Use ImGui 1.89.9
  2. connect client to server
  3. draw a debug gui; its most useful if you output the mouse position somewhere in your gui so you can see it bouncing between valid and invalid values

Expected behavior
woudl expect teh mouse position to be consistent, regardless of whether you are moving the mouse or not

Screenshots

image

image

Desktop (please complete the following information):

Windows

Smartphone (please complete the following information):

Additional context

client and server on Linux

My embedded system (no keyboard/screen) processes data and I'm considering using netImgui to move that data to the PC (keyboard/screen) and use ImGui to visualize it and interact with the embedded system. They would both be Linux based and have opengl3 and glfw.

I'm little confused on what part of netImgui runs where and how it is referred to in the docs / code / comments. Would the server run on the embedded system and the client on the PC in my case, or is it the other way around?

Which ImGui render/input backend should the embedded system use?

Reading through some older issues I get a feeling that Linux support is there but not complete. Has that changed?

Can you point me to an existing sample code that would best fit the use case outlined above, please?

Thank you in advance!

Server segfault after client leaves (opengl3)

After compiling and running the server and client (#39 ) under Linux the server dies if the client leaves.
Code was compiled on Linux Mint 20 using system glfw and opengl3 libraries.

Here is the backtrace from gdb:

Thread 4 "netimgui_server" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff2819700 (LWP 373138)]
0x00007ffff74e5b69 in ?? () from /lib/x86_64-linux-gnu/libGLdispatch.so.0
(gdb) bt
#0  0x00007ffff74e5b69 in ?? () from /lib/x86_64-linux-gnu/libGLdispatch.so.0
#1  0x00005555556991b9 in NetImguiServer::App::HAL_DestroyRenderTarget (pOutRT=@0x555555c30bb8: 0x0, pOutTexture=@0x555555c30bc0: 0x4) at GlfwGL3/NetImguiServer_HAL_GL3.cpp:92
#2  0x00005555556747b2 in NetImguiServer::RemoteClient::Client::Reset (this=0x555555c30bb8) at NetImguiServer_RemoteClient.cpp:137
#3  0x0000555555670dd9 in NetImguiServer::Network::Communications_ClientExchangeLoop (pClientSocket=0x7fffec0014b0, pClient=0x555555c30bb8) at NetImguiServer_Network.cpp:198
#4  0x0000555555673d56 in std::__invoke_impl<void, void (*)(NetImgui::Internal::Network::SocketInfo*, NetImguiServer::RemoteClient::Client*), NetImgui::Internal::Network::SocketInfo*, NetImguiServer::RemoteClient::Client*> (
    __f=@0x7fffec0014e8: 0x555555670c96 <NetImguiServer::Network::Communications_ClientExchangeLoop(NetImgui::Internal::Network::SocketInfo*, NetImguiServer::RemoteClient::Client*)>)
    at /usr/include/c++/9/bits/invoke.h:60
#5  0x0000555555673c03 in std::__invoke<void (*)(NetImgui::Internal::Network::SocketInfo*, NetImguiServer::RemoteClient::Client*), NetImgui::Internal::Network::SocketInfo*, NetImguiServer::RemoteClient::Client*> (
    __fn=@0x7fffec0014e8: 0x555555670c96 <NetImguiServer::Network::Communications_ClientExchangeLoop(NetImgui::Internal::Network::SocketInfo*, NetImguiServer::RemoteClient::Client*)>)
    at /usr/include/c++/9/bits/invoke.h:95
#6  0x0000555555673a91 in std::thread::_Invoker<std::tuple<void (*)(NetImgui::Internal::Network::SocketInfo*, NetImguiServer::RemoteClient::Client*), NetImgui::Internal::Network::SocketInfo*, NetImguiServer::RemoteClient::Client*> >::_M_invoke<0ul, 1ul, 2ul> (this=0x7fffec0014d8) at /usr/include/c++/9/thread:244
#7  0x00005555556739e7 in std::thread::_Invoker<std::tuple<void (*)(NetImgui::Internal::Network::SocketInfo*, NetImguiServer::RemoteClient::Client*), NetImgui::Internal::Network::SocketInfo*, NetImguiServer::RemoteClient::Client*> >::operator() (this=0x7fffec0014d8) at /usr/include/c++/9/thread:251
#8  0x0000555555673976 in std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)(NetImgui::Internal::Network::SocketInfo*, NetImguiServer::RemoteClient::Client*), NetImgui::Internal::Network::SocketInfo*, NetImguiServer::RemoteClient::Client*> > >::_M_run (this=0x7fffec0014d0) at /usr/include/c++/9/thread:195
#9  0x00007ffff7e2fde4 in ?? () from /lib/x86_64-linux-gnu/libstdc++.so.6
#10 0x00007ffff7bd4609 in start_thread (arg=<optimized out>) at pthread_create.c:477
#11 0x00007ffff7af7133 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95

(gdb) f 1
#1  0x00005555556991b9 in NetImguiServer::App::HAL_DestroyRenderTarget (pOutRT=@0x555555c30bb8: 0x0, pOutTexture=@0x555555c30bc0: 0x4) at GlfwGL3/NetImguiServer_HAL_GL3.cpp:92

92			glDeleteFramebuffers(1, &pRT);
(gdb) p pRT

$1 = 1
(gdb) p *pRT
Cannot access memory at address 0x1

Supporting multiple imgui contexts in the same app

Hello,

In our app, we have multiple imgui contexts at the same time, because we have separate game and rendering threads which can call imgui. When using NetImgui, the result is that only the commands sent to one of the contexts are shown in the remote viewer (the context which was current when NetImgui::Connect* was called, since that's the context to which the hooks were added).

Is there a way you had envisioned supporting this? I can tell you what I have, but I'm not sure that's how it should work, ideally.

So what I did was to call NetImgui::Connect* for both contexts. This gives me two client windows in the remote viewer, which is not ideal. So I made some changes to the remote viewer so that when the connection client name (client.mInfoName) is the same for two connections, they both use the same client instance (and then I had to make changes so that a single client can have multiple imgui draw data, one for each connection). And finally, when rendering the imgui draw data, I made it clear the texture only for the first one. These changes have no effect if there is only one connection per client, of course.

If you're interested I can send a patch with these changes. But I'd be interested to know what the ideal solution would look like in your opinion.

Auto saving .ini settings of imgui

Found some specific bug with autosaving .ini settings file.
I have server and client apps which works from same directory. NetImgui server side in some case will rewrite .ini file from client app. It depends on life cycle, which app will be destroyed first. NetImgui server creates additional imgui context for each client to draw client background (NetImguiServer_App.cpp - DrawClientBackground():131). And on deleting this context in RemoteClient::Client dctor imgui will save .ini file. I fixed for me - just set ImGuiIO::IniFilename to nullptr on context creation.

Is this some specific bug for my case or it's common and we don't need settings file for RemoteClient::Client?

Invalid Server Listen port block netImguiServer startup

Describe the bug
When assigning a listening port that's already being used, the netImguiServer application won't be able to properly start after being closed.

Workaround
For the moment, manual editing of the netImgui.cfg file is needed, assigning a new valid ServerPort value.

ServerApp 100% crashes when connecting to client on Android

First cmd packets coming from the clients are ok (Ping, Background) but the first DrawFrame makes the app crash on read access violation. Inside void CmdDrawFrame::ToPointers() when checking if( !mpDrawGroups.IsPointer() ) the data has the right signature and looks ok (0x800000something) but crashes on first (i = 0) mpDrawGroups[i].ToPointers();

I guess we hit the limits of the following comment :)
// @sammyfreg TODO: Make Offset/Pointer test safer

To Reproduce
Steps to reproduce the behavior:

  1. Launch Client (default ports) on Android
  2. Launch Server
  3. Wait for auto connection (Server settings bound to phone client on local IP)
  4. See error

Side Notes:

  1. I had only 1 client thread running on the ServerApp
  2. No issues when running clients on localhost PC
  3. Also tried getting your latest version, issue is the same.

netimgui_server_crash

Desktop (please complete the following information):

  • OS: Win64

Smartphone (please complete the following information):

  • Device: Google Pixel 6 Pro
  • OS: [latest]

Cmake build system

Hello. It's possible to add cmake build system to project? Cmake can helps to build NetImGui on Linux and makes possible to work in different IDE's.

Update rate changes for some reason

I've added ImPlot to the SampleNoBackend app. While observing the demo plot I noticed that the update rate of the plot changes for some reason. At times it runs normal and at times it runs slower. I do not know what triggers the change in update rate.

I've attached the video. I'm not clicking anywhere (except when scrolling), but just moving my mouse around.

This is with the code from master branch, ImPlot code is also master branch, both as of today.
OS is Linux.
FWIW, Server Configuration is set to refresh Active and Inactive Windows at 60 fps, compression is enabled.
Both Server and Client are on the same host, i.e. there is no network traffic involved - only localhost.

PS. This can also be observed with the ImGui demo with widgets under plotting.

Screencast.2023-11-17.14.10.09.mp4
Screencast.2023-11-17.14.44.19.mp4

Opengl2 backend

I would like to use netImgui on Linux with glfw and opengl2 but the displayed texture of client app is bad.
Client app and netimgui server are on the same machine (localhost).

Here is my client app :

with this loop :

while(!glfwWindowShouldClose(m_window))
{
    glfwPollEvents();

    glClear(GL_COLOR_BUFFER_BIT);

    ImGuiIO *io = &::ImGui::GetIO(); (void)io;
    glViewport(0, 0, (int)io->DisplaySize.x, (int)io->DisplaySize.y);

    ImGui_ImplOpenGL2_NewFrame();
    ImGui_ImplGlfw_NewFrame();
    ::NetImgui::NewFrame();

    if (NetImgui::IsConnected()) {
    } else // No connection
    {
        //-------------------------------------------------------------------------------------
        if (ImGui::BeginMenu("[ Connect to ]"))
        //-------------------------------------------------------------------------------------
        {
            if (ImGui::Button("Connect", ImVec2(ImGui::GetContentRegionAvailWidth(), 0))) {
                NetImgui::ConnectToApp(zAppName, sServerHostname, sServerPort);
            }
            ImGui::EndMenu();
        }
    }

    if( ImGui::Begin("Sample Basic 2", nullptr) )
    {
        ImGui::TextColored(ImVec4(0.1, 1, 0.1, 1), "Basic demonstration of netImgui code integration.");
        ImGui::TextWrapped("Create a basic Window with some text.");
        ImGui::NewLine();
        ImGui::TextColored(ImVec4(0.1, 1, 0.1, 1), "Where are we drawing: ");
        ImGui::SameLine();
        ImGui::TextUnformatted(NetImgui::IsDrawingRemote() ? "Remote Draw" : "Local Draw");
        ImGui::NewLine();
        ImGui::TextColored(ImVec4(0.1, 1, 0.1, 1), "Filler content");
        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.");
        ImGui::End();
    }

    ::NetImgui::EndFrame();
    ImGui_ImplOpenGL2_RenderDrawData(::ImGui::GetDrawData());

    glfwMakeContextCurrent(m_window);
    glfwSwapBuffers(m_window);
}

On the server side i created NetImguiServer_HAL_opengl2.cpp :

//=================================================================================================
// Source file handling renderer specific commands needed by NetImgui server.
// It complement the rendering backend with a few more functinoalities.
//=================================================================================================
#include <GL/glew.h>
#include "imgui_impl_opengl2.h"

#include "NetImguiServer_App.h"
#include "NetImguiServer_RemoteClient.h"
#include <Private/NetImgui_Shared.h>

namespace NetImguiServer {
namespace App {

//=================================================================================================
// HAL RENDER DRAW DATA
// The drawing of remote clients is handled normally by the standard rendering backend,
// but output is redirected to an allocated client texture  instead default swapchain
//=================================================================================================
    void HAL_RenderDrawData(RemoteClient::Client& client, ImDrawData* pDrawData)
    {
        if( client.mpHAL_AreaRT )
        {
            glBindFramebuffer(GL_FRAMEBUFFER, (GLuint)(intptr_t)client.mpHAL_AreaRT);
            glClearColor(
                    client.mBGSettings.mClearColor[0] * client.mBGSettings.mClearColor[3],
                    client.mBGSettings.mClearColor[1] * client.mBGSettings.mClearColor[3],
                    client.mBGSettings.mClearColor[2] * client.mBGSettings.mClearColor[3],
                    client.mBGSettings.mClearColor[3]);
            glClear(GL_COLOR_BUFFER_BIT);

            {
                NetImgui::Internal::ScopedImguiContext scopedCtx(client.mpBGContext);
                ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData());
            }
            if (pDrawData)
            {
                ImGui_ImplOpenGL2_RenderDrawData(pDrawData);
            }

            glBindFramebuffer(GL_FRAMEBUFFER, 0);
        }
    }

//=================================================================================================
// HAL CREATE RENDER TARGET
// Allocate RenderTargetView / TextureView for each connected remote client. 
// The drawing of their menu content will be outputed in it, then displayed normally 
// inside our own 'NetImGui application' Imgui drawing
//=================================================================================================
    bool HAL_CreateRenderTarget(uint16_t Width, uint16_t Height, void*& pOutRT, void*& pOutTexture)
    {
        HAL_DestroyRenderTarget(pOutRT, pOutTexture);

        GLuint pTextureView = 0u;
        glGenTextures(1, &pTextureView);
        glBindTexture(GL_TEXTURE_2D, pTextureView);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

//        glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
		
        GLuint pRenderTargetView = 0u;
        glGenFramebuffers(1, &pRenderTargetView);
        glBindFramebuffer(GL_FRAMEBUFFER, pRenderTargetView);

        //Attach 2D texture to this FBO
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pTextureView, 0);

        GLenum status;
        status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
        switch(status)
        {
            case GL_FRAMEBUFFER_COMPLETE:
                printf("good\n");
                break;
            default:
                printf("error\n");
                return false;
        }

        glBindTexture(GL_TEXTURE_2D, 0);

        // switch back to window-system-provided framebuffer
        glBindFramebuffer(GL_FRAMEBUFFER, 0);

        pOutRT      = reinterpret_cast<void*>(pRenderTargetView);
        pOutTexture = reinterpret_cast<void*>(pTextureView);

        return true;
    }

//=================================================================================================
// HAL DESTROY RENDER TARGET
// Free up allocated resources tried to a RenderTarget
//=================================================================================================
    void HAL_DestroyRenderTarget(void*& pOutRT, void*& pOutTexture)
    {
        if(pOutRT)
        {
            GLuint pRT = (GLuint)(intptr_t)pOutRT;
            glDeleteFramebuffers(1, &pRT);
        }

        if (pOutTexture)
        {
            GLuint pTexture = (GLuint)(intptr_t)pOutTexture;
            glDeleteTextures(1, &pTexture);
        }
    }

//=================================================================================================
// HAL CREATE TEXTURE
// Receive info on a Texture to allocate. At the moment, 'Dear ImGui' default rendering backend
// only support RGBA8 format, so first convert any input format to a RGBA8 that we can use
//=================================================================================================
    bool HAL_CreateTexture(uint16_t Width, uint16_t Height, NetImgui::eTexFormat Format, const uint8_t* pPixelData /* TODO unsigned char */ , ServerTexture& OutTexture)
    {
        HAL_DestroyTexture(OutTexture);

        // Convert all incoming textures data to RGBA8
        uint32_t* pPixelDataAlloc = nullptr;
        if(Format == NetImgui::eTexFormat::kTexFmtA8)
        {
            pPixelDataAlloc = NetImgui::Internal::netImguiSizedNew<uint32_t>(Width*Height*4);
            for (int i = 0; i < Width * Height; ++i){
                pPixelDataAlloc[i] = 0x00FFFFFF | (static_cast<uint32_t>(pPixelData[i])<<24);
            }
            pPixelData = reinterpret_cast<const uint8_t*>(pPixelDataAlloc);
        }
        else if (Format == NetImgui::eTexFormat::kTexFmtRGBA8)
        {
            printf("format kTexFmtRGBA8\n");
        }
            // Unsupported format
        else
        {
            printf("unsupported format\n");

            return false;
        }

        // Save state
        GLint last_texture;
        glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);

        GLuint texture = 0u;
        glGenTextures(1, &texture);

        glBindTexture(GL_TEXTURE_2D, texture);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

        //glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pPixelData);

        OutTexture.mSize[0]         = Width;
        OutTexture.mSize[1]         = Height;
        OutTexture.mpHAL_Texture    = (void*)(intptr_t)(texture);

        // Restore state
        glBindTexture(GL_TEXTURE_2D, last_texture);

        if(pPixelDataAlloc)
        {
            NetImgui::Internal::netImguiDeleteSafe(pPixelDataAlloc);
        }

        return true;
    }

//=================================================================================================
// HAL DESTROY TEXTURE
// Free up allocated resources tried to a Texture
//=================================================================================================
    void HAL_DestroyTexture(ServerTexture& OutTexture)
    {
        if (OutTexture.mpHAL_Texture)
        {
            GLuint texture = (GLuint)(intptr_t)OutTexture.mpHAL_Texture;
            glDeleteTextures(1, &texture);
            memset(&OutTexture, 0, sizeof(OutTexture));
        }
    }

} // namespace App
} // namespace NetImguiServer

My first problem was that the font texture was not correctly displayed :

This is because the function HAL_CreateTexture is not called from the main thread. This other thread doesn't have opengl context so glGenTextures call fails.

I have found a workaround and now it works :

But when i create two imgui "Sample Basic" window (the "Debug" window disappear when client is connected to server) :

now i have bad texture displayed on server (client app on left and netimgui server on right) :

I have tried with netimgui 1.6 and imgui 1.80, 1.84.2 and docking branch and i have the same results.

Including assets and multiple dear imgui copies in repository

Nothing critical but some loose suggestions (feel free to close)

Assets
Assets tends to bloat git repository fast (especially when updated, since git will locally keep every copies).
Two things I found worked:

  • Manual push assets into the wiki/ repo (it's another repository provided by gthub).
    Notice that e.g. https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v175/capture_readme_styles_0001.png is actually served from imgui's wiki repo.
  • Upload assets to Issues without submitting the issue, then save the link to the asset. As it happens it seems that GitHub is never garbage collecting those... I know it sounds strange, but I've been relying on this for years. The day, if ever, that GitHub decide to garbage collect assets not linked to issue we can react. I don't think I'm the only repository using that facility and when I asked GitHub about it on Twitter they suggested I do that..
  • Bonus: ServerApp/background.png could easily be rendered using ImDrawList. ALSO the current asset seems to have a wrong aspect ratio the circle is not a perfect circle which makes the whole thing looks squashed which in my subconscious makes the app look less polished that it actually is.

Multiple Dear ImGui copies
I realize you need this for testing but it makes the whole netimgui package less "library-ish" (and also bigger) that it contains all those copies of dear imgui. I would suggest either using a single submodule link either use a separate repo to distinguish lib vs example if needed (more handling!). Either way you can use scripting or GitHub actions if you want to test that stuff compiles with multiple versions.

Making those changes the file tree would goes from ~20 mb to ~1 mb.

GLFW texture corruption

Describe the bug

We're using GLFW backend, however textures get corrupted. This doesn't happen in the other sample applications, only when we're dealing with textures.

To Reproduce
Steps to reproduce the behavior:

  1. Run Sample Textures client
  2. Connect to a Server compiled with GLFW

You will see something like this:

image

Expected behavior
Not to corrupt textures.

Desktop (please complete the following information):

  • OS: Windows 10/11
  • Intel UHD GPU

Additional context

We noticed a few unsolved tickets regarding this at imgui, it seems they did some fixes in more recent versions of imgui, but none seem to completely solve this problem, as reference:

ocornut/imgui#5655
ocornut/imgui#3033

When using DX11 the corruption doesn't happen, however, if we start sending larger textures it eventually segfaults.

This issue doesn't happen at all (regardless of the backend) when using NVIDIA GPUs, it only seem to happen with Intel GPUs (we tested Iris and UHD devices)

NetImGui thinks it's connected when it isn't

Describe the bug

I noticed that ImGui wasn't drawing in my application, and eventually tracked it down to NetImGui return "true" for IsDrawingRemote. It seems that this only returns "true" if the API thinks it's connected.

To Reproduce
Steps to reproduce the behavior:

  1. Launch application
  2. Turn on an imgui menu
  3. Notice that it isn't drawing
  4. Inspect logs which are printing result if "IsDrawingRemote" - it's true, even though the server isn't turned on.

Expected behavior
IsDrawingRemote() only returns true when the server is connected and is drawing.

Screenshots
no screen shot

Desktop (please complete the following information):

  • OS: windows 10

Additional context
The thing I can't explain is that this only happens in a 'release' build of my app, not in debug. I've checked netstat and i can see my app listening on port 8889 but no connection has been established (in both the working case and broken case). I'm using a release version of NetImGui in both cases, so I'm not sure what's going on. When I do connect the remote server, I see my imgui drawing (in both the broken case and working case).

Is there something I can do further to debug this or provide more information?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.