-
Notifications
You must be signed in to change notification settings - Fork 215
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
there's any example to start with this? #12
Comments
Hey, unfortunately there is no project with example how to use it. When I have a moment I’ll try to create one (I have one but I need to do something more publishable :). I assume that you already configured module dependancy as described in "How to use it" section. How well do you know ImGui? If you don’t then ImGui repository (https://github.com/ocornut/imgui) is a good place to start and imgui.h have extensive readme section. If you already know ImGui then all you need is to include imgui.h header and use it in your code. You can also register your own tick delegate and use ImGui code from there. I don’t think that one method is better than the other, so use whatever makes more sense in particular case. One thing to keep in mind is that I want to change the interface for ImGui tick delegates. To see examples how to use ImGui you can check FImGuiDemo class which calls original demo. This is usually the best place to see how to use ImGui and what is possible. You can also check SImGuiWidget to see its own debug code. To see them in action use ImGui.ShowDemo and ImGui.Debug.Widget cvars. If you don’t need to use custom textures that would be about it. If you do, then FImGuiModule has functions allowing to register textures before they can be used in ImGui. I see that I didn’t actually update readme with that information. Hope that it helps a bit. Let me know if something is not clear. |
First off, thank you for the work put into this plugin! After just getting this setup myself, using your plugin, I can see where part of the confusion lies. Create a class (FMyGameImGui) that is instanced somewhere (Globally? GameModule, GameInstance, GameSingleton) and have that class communicate with FImGuiModule using FImGuiModule::Get().AddWorldImGuiDelegate (Or AddMultiContextImGuiDelegate if in editor? This is the only one I was able to get to work in Editor). OnDraw will get called and then from there you can add your ImGui logic for MainMenuBars or Windows, etc. Pseudo code below...
Is this the intended way for users to interface with the plugin? Thanks, Gabe |
Thank you @gabeparamo for your post. First of all, thank you for pointing out possible confusion. I understand that this knowledge came from a personal struggle and for that I am sorry ;) I do see the problem and I maybe even better understand now what needs to be clarified. It is a bit rude of me to leave it without good example for that long but there is a reason to that. There is a bit of refactoring that I want to do which will almost surely affect the public API (those delegates that you mentioned) and I didn’t want to spread a soon-to-be depreciated knowledge. Taking from your example, the intention of those changes would be to:
This is important change for me before doing any official recommendations and that is why I'm postponing releasing of those examples for so long. But I appreciate the fact that in the meantime people might be confused, so I’ll use this thread as a temporary solution and will try to post a snippet demonstrating how it should be used from game... probably tomorrow as it is getting late here. |
Ah I see! That makes perfect sense. Thank you for your response!! Happy new year! |
Thank you @gabeparamo. Happy New Year to you too! Below is an example with three different methods to debug object (Actor in this case). A bit long but I just cleaned and copied one of my test actors that I use in my ImGui dev project: // ImGuiCommon.h
#pragma once
#ifdef IMGUI_API
#define WITH_IMGUI 1
#else
#define WITH_IMGUI 0
#endif // IMGUI_API
#if WITH_IMGUI
#include <ImGuiModule.h>
#include <ImGuiDelegates.h>
#include <imgui.h>
#endif // WITH_IMGUI // ImGuiDebugOrderTest.h
#pragma once
#include "ImGuiCommon.h"
#include <CoreMinimal.h>
#include <GameFramework/Actor.h>
#include "ImGuiDebugOrderTest.generated.h"
UCLASS()
class AImGuiDebugOrderTest : public AActor
{
GENERATED_BODY()
public:
// To register and unregister static multi-context delegate.
AImGuiDebugOrderTest();
virtual void BeginDestroy() override;
// To register and unregister per-object world delegate.
virtual void BeginPlay() override;
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
// To debug during world tick.
virtual void Tick(float DeltaTime) override;
#if WITH_IMGUI
void ImGuiTick();
static void ImGuiMultiContextTick();
FImGuiDelegateHandle ImGuiTickHandle;
static FImGuiDelegateHandle ImGuiMultiContextTickHandle;
#endif // WITH_IMGUI
}; // ImGuiDebugOrderTest.cpp
#include "ImGuiDebugOrderTest.h"
#include <Runtime/Engine/Public/EngineUtils.h>
FImGuiDelegateHandle AImGuiDebugOrderTest::ImGuiMultiContextTickHandle;
AImGuiDebugOrderTest::AImGuiDebugOrderTest()
{
// Let's say that this actor ticks and we want to debug it.
PrimaryActorTick.bCanEverTick = true;
// Register static multi-context delegate (only for default object for symmetry with destruction).
// Note that if module is not available at this point, registration can fail. This limitation of the API will be
// fixed in one of the next few updates but for now, if necessary, a solution would be to retry registration
// at a later stage (which I'm not doing here).
#if WITH_IMGUI
if (IsTemplate() && !ImGuiMultiContextTickHandle.IsValid() && FImGuiModule::IsAvailable())
{
ImGuiMultiContextTickHandle = FImGuiModule::Get().AddMultiContextImGuiDelegate(FImGuiDelegate::CreateStatic(&AImGuiDebugOrderTest::ImGuiMultiContextTick));
}
#endif // WITH_IMGUI
}
void AImGuiDebugOrderTest::BeginDestroy()
{
Super::BeginDestroy();
// Unregister static multi-context delegate. Failing to do so would result with multiplication of delegates during
// hot reloading. And we do it only once for the default object to make sure that we unregister only when class is
// not used anymore.
#if WITH_IMGUI
if (IsTemplate() && ImGuiMultiContextTickHandle.IsValid() && FImGuiModule::IsAvailable())
{
FImGuiModule::Get().RemoveImGuiDelegate(ImGuiMultiContextTickHandle);
ImGuiMultiContextTickHandle.Reset();
}
#endif // WITH_IMGUI
}
void AImGuiDebugOrderTest::BeginPlay()
{
Super::BeginPlay();
// Register object's debug delegate in current world context.
#if WITH_IMGUI
ImGuiTickHandle = FImGuiModule::Get().AddWorldImGuiDelegate(FImGuiDelegate::CreateUObject(this, &AImGuiDebugOrderTest::ImGuiTick));
#endif // WITH_IMGUI
}
void AImGuiDebugOrderTest::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
Super::EndPlay(EndPlayReason);
// Unregister object's delegate.
#if WITH_IMGUI
FImGuiModule::Get().RemoveImGuiDelegate(ImGuiTickHandle);
#endif // WITH_IMGUI
}
void AImGuiDebugOrderTest::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
// Debug during world tick.
#if WITH_IMGUI
ImGui::Begin("ImGui Debug Order Test");
ImGui::Text("Actor Tick: Actor = '%ls', World = '%ls', CurrentWorld = '%ls'",
*GetNameSafe(this), *GetNameSafe(GetWorld()), *GetNameSafe(GWorld));
ImGui::End();
#endif // WITH_IMGUI
}
#if WITH_IMGUI
void AImGuiDebugOrderTest::ImGuiTick()
{
ImGui::Begin("ImGui Debug Order Test");
ImGui::Text("ImGui World Tick: Actor = '%ls', World = '%ls', CurrentWorld = '%ls'",
*GetNameSafe(this), *GetNameSafe(GetWorld()), *GetNameSafe(GWorld));
ImGui::End();
}
void AImGuiDebugOrderTest::ImGuiMultiContextTick()
{
ImGui::Begin("ImGui Debug Order Test");
int32 Count = 0;
for (TActorIterator<AImGuiDebugOrderTest> It(GWorld); It; ++It, ++Count)
{
AImGuiDebugOrderTest* Actor = *It;
UWorld* World = Actor ? Actor->GetWorld() : nullptr;
ImGui::Text("ImGui Multi-Context Tick: Actor = '%ls', World = '%ls', CurrentWorld = '%ls'",
*GetNameSafe(Actor), *GetNameSafe(World), *GetNameSafe(GWorld));
}
ImGui::Text("ImGui Multi-Context Tick: %d actors in world '%ls'.", Count, *GetNameSafe(GWorld));
ImGui::End();
}
#endif // WITH_IMGUI |
A few comments to the above example and in general.
|
Ever think of recording a tutorial video for Youtube? If you have an nVidia card, recording is as simple as Alt+F9, preferably in one-take (https://signalvnoise.com/posts/1560-axl-vs-frank-more-time-doesnt-mean-a-better-product). Would love to listen to an overview of your code and decisions behind it. |
Hi @aoakenfo. I would like to upload to the GitHub a project showing how to set-up this plugin and a few different ways to add ImGui debug to the game code. Sort of "Hello, World" with a few examples demonstrating workflow. But for various reasons, I keep postponing it. Is there anything particular that you would be interested in?
|
The Actor you posted above was enough to get started. I think adding that to the README.md is the easiest way for others to get started. In fact, you can simplify it even further by removing the multi-context code. Yeah, I encourage a lot of people to just hit record and get it out there. (That's how all my Niagara tutorial vids were done.) Why not cover workflow in the video? You may think it's "just a wrapper" but it looks rather complex. I'm not sure where I would even begin to create an Imgui backend like this. Anyway, thanks for all your hard work, you've done the community a great service. Much appreciated. |
Thank you for your kind words. I didn't think about making a video because, well I'm not a very "video type" of person... whatever that means ;) But you are right that perhaps it would be good to put a simplified version of the above actor in the readme file, regardless plans for making a more complex example project. |
Hello, also thank you for the explanation above to integrate the plugin. But i'm having a small issue about inputs. Even though i enabled input and share mouse input from properties, clicking on Unreal Engine viewport during runtime stops imgui to detect any input from mouse. Setting Is there any way to fix this issue? |
sorry for posting here,,,
but I don't know how to start.
Plugin its copied to my project and detected and enabled fine.
The text was updated successfully, but these errors were encountered: