Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NetImgui branch update #1

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Dear ImGui is an immediate-mode graphical user interface library that is very li
Status
------
- [ImGui `v1.89.7`](https://github.com/ocornut/imgui/releases/tag/v1.89.7)
- [NetImgui `v1.9`](https://github.com/sammyfreg/netImgui/releases/tag/v1.9.0)
- [ImPlot `v0.14+cc5e1daa`](https://github.com/epezent/implot/tree/cc5e1daa5c7f2335a9460ae79c829011dc5cef2d)

Supported Unreal Engine version: `4.26`, `5.0`, `5.1`, `5.2`
Expand All @@ -21,8 +22,6 @@ Please note that this is a forked project from [segross/UnrealImGui](https://git

Large portions of this `README.md` have been removed to keep redundant information between the base project and this fork to a minimum. If you wish to read the original `README.md`, please see [UnrealImGui `README.md`](https://github.com/segross/UnrealImGui/blob/master/README.md).

Also note that the NetImGui branch is not up to date with any of this fork's changes.

- Updated core source files for **Unreal Engine 5** while maintaining **Unreal Engine 4** compatibility.
- Updated Dear ImGui to `v1.89.7`.
- Added ImPlot `v0.14+cc5e1daa`.
Expand Down Expand Up @@ -104,6 +103,12 @@ void Init()
SceneCaptureComponent2D->CaptureSource = ESceneCaptureSource::SCS_FinalToneCurveHDR;
}
```
How to Set up NetImgui
----------------------

To remotely connect to your application's Imgui content using NetImgui, you need to run the **NetImgui Server application**. The appropriate version can be downloaded [here]("https://raw.githubusercontent.com/wiki/sammyfreg/netImgui/UnrealImgui/NetImguiServer_1_9.zip") and see the source project's [documentation](https://github.com/sammyfreg/netImgui) for instructions on its usage.

Once you establish connection, you can use acces the 'NetImgui' entry in the 'Main Menu' top bar to switch between contexts and modes. In standalone game it should be one context and in the editor one editor context, plus one for each PIE instance. Please, note that all those features are experimental and might evolve. Any input is welcomed.

### Troubleshooting
If you're using a scene capture and your quad is not drawing at all, make sure your scene capture "Capture Source" is set to "Final Color (with tone curve) in Linear sRGB gamut" to avoid alpha being set to 0 (since there's no way to instruct ImGui to ignore alpha without modding the core UnrealImGui plugin).
Expand Down Expand Up @@ -178,6 +183,7 @@ See also
- [Forked Project by WiggleWizard](https://github.com/WiggleWizard/UnrealImGui)
- [Dear ImGui](https://github.com/ocornut/imgui)
- [ImPlot](https://github.com/epezent/implot)
- [NetImgui](https://github.com/sammyfreg/netImgui)


License
Expand Down
5 changes: 3 additions & 2 deletions Source/ImGui/ImGui.Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ public ImGui(TargetInfo Target)
"Engine",
"InputCore",
"Slate",
"SlateCore"
// ... add private dependencies that you statically link with here ...
"SlateCore",
"NetImguiLibrary"
// ... add private dependencies that you statically link with here ...
}
);

Expand Down
30 changes: 26 additions & 4 deletions Source/ImGui/Private/ImGuiContextManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,20 @@
#include "ImGuiContextManager.h"

#include "ImGuiDelegatesContainer.h"
#include "ImGuiImplementation.h"
#include "ThirdPartyBuildNetImgui.h"
#include "ImGuiModuleSettings.h"
#include "ImGuiModule.h"
#include "Utilities/WorldContext.h"
#include "Utilities/WorldContextIndex.h"

#include <imgui.h>

#include "Fonts/Roboto_Medium.cpp"
#include "Fonts/Cousine_Regular.cpp"
#include "Fonts/Droid_Sans.cpp"
#include "Fonts/Karla_Regular.cpp"
#include "Fonts/Proggy_Tiny.cpp"

// MSVC warnings
#ifdef _MSC_VER
#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
Expand Down Expand Up @@ -89,6 +95,8 @@ FImGuiContextManager::~FImGuiContextManager()

void FImGuiContextManager::Tick(float DeltaSeconds)
{
NetImguiUpdate(Contexts);

// In editor, worlds can get invalid. We could remove corresponding entries, but that would mean resetting ImGui
// context every time when PIE session is restarted. Instead we freeze contexts until their worlds are re-created.

Expand Down Expand Up @@ -150,7 +158,7 @@ void FImGuiContextManager::OnWorldPostActorTick(UWorld* World, ELevelTick TickTy
#endif // ENGINE_COMPATIBILITY_WITH_WORLD_POST_ACTOR_TICK

#if WITH_EDITOR
FImGuiContextManager::FContextData& FImGuiContextManager::GetEditorContextData()
FContextData& FImGuiContextManager::GetEditorContextData()
{
FContextData* Data = Contexts.Find(Utilities::EDITOR_CONTEXT_INDEX);

Expand All @@ -165,7 +173,7 @@ FImGuiContextManager::FContextData& FImGuiContextManager::GetEditorContextData()
#endif // WITH_EDITOR

#if !WITH_EDITOR
FImGuiContextManager::FContextData& FImGuiContextManager::GetStandaloneWorldContextData()
FContextData& FImGuiContextManager::GetStandaloneWorldContextData()
{
FContextData* Data = Contexts.Find(Utilities::STANDALONE_GAME_CONTEXT_INDEX);

Expand All @@ -179,7 +187,7 @@ FImGuiContextManager::FContextData& FImGuiContextManager::GetStandaloneWorldCont
}
#endif // !WITH_EDITOR

FImGuiContextManager::FContextData& FImGuiContextManager::GetWorldContextData(const UWorld& World, int32* OutIndex)
FContextData& FImGuiContextManager::GetWorldContextData(const UWorld& World, int32* OutIndex)
{
using namespace Utilities;

Expand Down Expand Up @@ -263,9 +271,23 @@ void FImGuiContextManager::BuildFontAtlas(const TMap<FName, TSharedPtr<ImFontCon
{
if (!FontAtlas.IsBuilt())
{
//---------------------------------------------------------------------------------------------
// Load our Font (Must be loaded in same order as FImguiModule::eFont enum)
ImFontConfig FontConfig = {};
FontConfig.SizePixels = FMath::RoundFromZero(13.f * DPIScale);
FontAtlas.AddFontDefault(&FontConfig);
FPlatformString::Strcpy(FontConfig.Name, sizeof(FontConfig.Name), "Roboto Medium, 16px");
FontAtlas.AddFontFromMemoryCompressedTTF(Roboto_Medium_compressed_data, Roboto_Medium_compressed_size, 16.0f*DPIScale, &FontConfig);
FPlatformString::Strcpy(FontConfig.Name, sizeof(FontConfig.Name), "Cousine Regular, 15px");
FontAtlas.AddFontFromMemoryCompressedTTF(Cousine_Regular_compressed_data, Cousine_Regular_compressed_size, 15.0f*DPIScale, &FontConfig);
FPlatformString::Strcpy(FontConfig.Name, sizeof(FontConfig.Name), "Karla Regular, 16px");
FontAtlas.AddFontFromMemoryCompressedTTF(Karla_Regular_compressed_data, Karla_Regular_compressed_size, 16.0f*DPIScale, &FontConfig);
FPlatformString::Strcpy(FontConfig.Name, sizeof(FontConfig.Name), "Droid Sans, 16px");
FontAtlas.AddFontFromMemoryCompressedTTF(Droid_Sans_compressed_data, Droid_Sans_compressed_size, 16.0f*DPIScale, &FontConfig);
FPlatformString::Strcpy(FontConfig.Name, sizeof(FontConfig.Name), "Proggy Tiny, 10px");
FontAtlas.AddFontFromMemoryCompressedTTF(Proggy_Tiny_compressed_data, Proggy_Tiny_compressed_size, 10.0f*DPIScale, &FontConfig);

// ... add extra fonts here (and add extra entry in 'FImguiModule::eFont' enum)

// Build custom fonts
for (const TPair<FName, TSharedPtr<ImFontConfig>>& CustomFontPair : CustomFontConfigs)
Expand Down
34 changes: 20 additions & 14 deletions Source/ImGui/Private/ImGuiContextManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,26 @@ struct FImGuiDPIScaleInfo;
// @param ContextProxy - Created context proxy
DECLARE_MULTICAST_DELEGATE_TwoParams(FContextProxyCreatedDelegate, int32, FImGuiContextProxy&);

// NETIMGUI_ENABLED
// NOTE: Made this public, to share with NetImgui. Need access to the proxy and CanTick property
// Could be done other ways like building the data and sending it to NetImguiUpdate
// instead of accessing it directly)
struct FContextData
{
FContextData(const FString& ContextName, int32 ContextIndex, ImFontAtlas& FontAtlas, float DPIScale, int32 InPIEInstance = -1)
: PIEInstance(InPIEInstance)
, ContextProxy(new FImGuiContextProxy(ContextName, ContextIndex, &FontAtlas, DPIScale))
{
}

FORCEINLINE bool CanTick() const { return PIEInstance < 0 || GEngine->GetWorldContextFromPIEInstance(PIEInstance); }

int32 PIEInstance = -1;
TUniquePtr<FImGuiContextProxy> ContextProxy;
};
// NETIMGUI_ENABLED


// Manages ImGui context proxies.
class FImGuiContextManager
{
Expand Down Expand Up @@ -70,20 +90,6 @@ class FImGuiContextManager

private:

struct FContextData
{
FContextData(const FString& ContextName, int32 ContextIndex, ImFontAtlas& FontAtlas, float DPIScale, int32 InPIEInstance = -1)
: PIEInstance(InPIEInstance)
, ContextProxy(new FImGuiContextProxy(ContextName, ContextIndex, &FontAtlas, DPIScale))
{
}

FORCEINLINE bool CanTick() const { return PIEInstance < 0 || GEngine->GetWorldContextFromPIEInstance(PIEInstance); }

int32 PIEInstance = -1;
TUniquePtr<FImGuiContextProxy> ContextProxy;
};

#if ENGINE_COMPATIBILITY_LEGACY_WORLD_ACTOR_TICK
void OnWorldTickStart(ELevelTick TickType, float DeltaSeconds);
#endif
Expand Down
87 changes: 59 additions & 28 deletions Source/ImGui/Private/ImGuiContextProxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include "ImGuiContextProxy.h"

#include "ImGuiDelegatesContainer.h"
#include "ImGuiImplementation.h"
#include "ThirdPartyBuildNetImgui.h"
#include "ImGuiInteroperability.h"
#include "Utilities/Arrays.h"
#include "VersionCompatibility.h"
Expand Down Expand Up @@ -152,12 +152,20 @@ void FImGuiContextProxy::DrawEarlyDebug()
if (bIsFrameStarted && !bIsDrawEarlyDebugCalled)
{
bIsDrawEarlyDebugCalled = true;
if( NetImGuiCanDrawProxy(this) )
{
SetAsCurrent();

// Delegates called in order specified in FImGuiDelegates.
BroadcastMultiContextEarlyDebug();
BroadcastWorldEarlyDebug();
}

SetAsCurrent();

// Delegates called in order specified in FImGuiDelegates.
BroadcastMultiContextEarlyDebug();
BroadcastWorldEarlyDebug();
if( NetImGuiSetupDrawRemote(this) )
{
BroadcastMultiContextEarlyDebug();
BroadcastWorldEarlyDebug();
}
}
}

Expand All @@ -170,22 +178,29 @@ void FImGuiContextProxy::DrawDebug()
// Make sure that early debug is always called first to guarantee order specified in FImGuiDelegates.
DrawEarlyDebug();

SetAsCurrent();
if (NetImGuiCanDrawProxy(this))
{
SetAsCurrent();

// Delegates called in order specified in FImGuiDelegates.
BroadcastWorldDebug();
BroadcastMultiContextDebug();
// Delegates called in order specified in FImGuiDelegates.
BroadcastWorldDebug();
BroadcastMultiContextDebug();
}

if (NetImGuiSetupDrawRemote(this))
{
BroadcastWorldDebug();
BroadcastMultiContextDebug();
}
}
}

void FImGuiContextProxy::Tick(float DeltaSeconds)
{
// Making sure that we tick only once per frame.
if (LastFrameNumber < GFrameNumber)
if (LastFrameNumber < GFrameCounter)
{
LastFrameNumber = GFrameNumber;

SetAsCurrent();
LastFrameNumber = GFrameCounter;

if (bIsFrameStarted)
{
Expand Down Expand Up @@ -214,16 +229,17 @@ void FImGuiContextProxy::BeginFrame(float DeltaTime)
{
if (!bIsFrameStarted)
{
ImGuiIO& IO = ImGui::GetIO();
IO.DeltaTime = DeltaTime;
if( NetImGuiCanDrawProxy(this) )
{
SetAsCurrent();
ImGuiIO& IO = ImGui::GetIO();
IO.DeltaTime = DeltaTime;
IO.DisplaySize = { (float)DisplaySize.X, (float)DisplaySize.Y };
ImGuiInterops::CopyInput(IO, InputState);
ImGui::NewFrame();
}

ImGuiInterops::CopyInput(IO, InputState);
InputState.ClearUpdateState();

IO.DisplaySize = { (float)DisplaySize.X, (float)DisplaySize.Y };

ImGui::NewFrame();

bIsFrameStarted = true;
bIsDrawEarlyDebugCalled = false;
bIsDrawDebugCalled = false;
Expand All @@ -234,17 +250,32 @@ void FImGuiContextProxy::EndFrame()
{
if (bIsFrameStarted)
{
// Prepare draw data (after this call we cannot draw to this context until we start a new frame).
ImGui::Render();

// Update our draw data, so we can use them later during Slate rendering while ImGui is in the middle of the
// next frame.
UpdateDrawData(ImGui::GetDrawData());
if ( NetImGuiCanDrawProxy(this) )
{
// Prepare draw data (after this call we cannot draw to this context until we start a new frame).
SetAsCurrent();
ImGui::Render();

// Update our draw data, so we can use them later during Slate rendering while ImGui is in the middle of the
// next frame.
UpdateDrawData(ImGui::GetDrawData());
}
bIsFrameStarted = false;
}
}

// Is this context the current ImGui context.
bool FImGuiContextProxy::IsCurrentContext() const
{
return ImGui::GetCurrentContext() == Context;
}

// Set this context as current ImGui context.
void FImGuiContextProxy::SetAsCurrent()
{
ImGui::SetCurrentContext(Context);
}

void FImGuiContextProxy::UpdateDrawData(ImDrawData* DrawData)
{
if (DrawData && DrawData->CmdListsCount > 0)
Expand Down
11 changes: 5 additions & 6 deletions Source/ImGui/Private/ImGuiContextProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
#include <GenericPlatform/ICursor.h>

#include <imgui.h>

#include <string>


Expand Down Expand Up @@ -39,10 +38,10 @@ class FImGuiContextProxy
const FImGuiInputState& GetInputState() const { return InputState; }

// Is this context the current ImGui context.
bool IsCurrentContext() const { return ImGui::GetCurrentContext() == Context; }
bool IsCurrentContext() const;

// Set this context as current ImGui context.
void SetAsCurrent() { ImGui::SetCurrentContext(Context); }
void SetAsCurrent();

// Get the desired context display size.
const FVector2D& GetDisplaySize() const { return DisplaySize; }
Expand Down Expand Up @@ -81,12 +80,12 @@ class FImGuiContextProxy
// Tick to advance context to the next frame. Only one call per frame will be processed.
void Tick(float DeltaSeconds);

void UpdateDrawData(ImDrawData* DrawData);

private:

void BeginFrame(float DeltaTime = 1.f / 60.f);
void EndFrame();

void UpdateDrawData(ImDrawData* DrawData);
void EndFrame();

void BroadcastWorldEarlyDebug();
void BroadcastMultiContextEarlyDebug();
Expand Down
4 changes: 4 additions & 0 deletions Source/ImGui/Private/ImGuiDrawData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,8 @@ void FImGuiDrawList::TransferDrawData(ImDrawList& Src)
Src.CmdBuffer.swap(ImGuiCommandBuffer);
Src.IdxBuffer.swap(ImGuiIndexBuffer);
Src.VtxBuffer.swap(ImGuiVertexBuffer);

// ImGui seems to clear draw lists in every frame, but since source list can contain pointers to buffers that
// we just swapped, it is better to clear explicitly here.
Src._ResetForNewFrame();
}
Loading