segross / UnrealImGui

Unreal plug-in that integrates Dear ImGui framework into Unreal Engine 4.
MIT License
687 stars 217 forks source link

Zoom / DPI awareness #29

Closed connorjak closed 4 years ago

connorjak commented 4 years ago

UE4.22.3 master branch (equivalent to 4.24 tag, I think)

Nice job on this implementation; the install was relatively painless. I did have some problems though with trying to add on some third party widgets; the most frequent issue was imgui_internal.h not being on the include directories (../Private/imgui_internal.h works).

Issue: I am on a 4K screen (200% scale in Windows), which makes my imgui windows in UE4 very small. I see there is a way to temporarily zoom in with the Alt+Shift controls; is there a way to choose a set zoom level, or otherwise make ImGui windows more DPI-aware?

I was going to refer you to the DX11 example on the imgui repo for good DPI awareness, but from some quick looks at your code, it seems like you're using Slate as the backend for imgui. A secondary question: does this plugin work for Mac and Linux packaged UE4 clients?

segross commented 4 years ago

Yes, I can imagine it looks small on 4K. I thought about it some time ago but didn't fully implement it. There is a sort of placeholder code in the SImGuiLayout.cpp. Lines 30-35 add and configure SDPIScaler, but the scale is fixed to 1.0. If the math and conversions in other widgets are good enough it should work right away. I just tried to change that scale to 2.0 and it seems to work fine.

Given the current work in 1.19, it would be a good moment to finish that feature. Please try upping that scale and see how that works for you. A potential issue with a non-unit scale would be breaking one-to-one mapping between sized in the viewport and ImGui canvas, so I was wondering at an alternative solution allowing to modify UI style or fonts based on screen size. In any case, if you have any suggestions please bring them forward and if you know the place where they handle that in the examples you can point me there.

It should work in Linux although I didn't try to compile it for a while so I might have pickup some errors. But there should be not many and should be easy to fix. Same story for XBox and PS4. I never tried Mac but I hope that it will be similar to other platforms.

When it comes to imgui_internal.h, this is sort of out of question ;) because as the internal file it is not meant for the game code. Unless I have a very good reason I would like to keep it this way. Possible solutions:

1) Including in the private folder in the modules that depends on it. In the same way, as I do that in the ImGui module. The most preferable option as you can only use it in modules that explicitly need it. 2) Implementing depending code in the ImGui module. 3) I would need to try to confirm it, but my understanding is that adding it to the public includes in the ImGui.Build.cs would open it for dependant modules. If that was the case, it would be possible to add a switch there. 4) Moving that file to the public folder. The least preferable option as it creates a dependency on the internal ImGui implementation.

connorjak commented 4 years ago

Ok, I agree about imgui_internal.h. I'll try out that scaling code. It might be possible to automatically pick a good scale based on resolution, which I think is exposed as a global in UE4; I'll check on that.

connorjak commented 4 years ago

Yep, changing to 2.f scales 2x properly. I think there is some blurriness in the text, but I bet that's because the default font texture isn't very high res.

I'm seeing some crashing, though, on ImGui::Begin(). The crashes only happen when I'm not running UE4 through the visual studio debugger (Development Editor configuration). Top of the stack trace is this: imgui.cpp line 1874 (GetVoidPtr())

connorjak commented 4 years ago

It appears, at least at 2x scale using the change above, that the ImGui canvas is made twice the size of the UE4 viewport in both directions. Is this by design? For my application for now, I want some of my ImGui UI anchored in screenspace along the edge of the window, and have them adapt in some way to changes in viewport resolution, aspect ratio, etc. Ideally, I would be able to use

const FVector2D ViewportSize = FVector2D(GEngine->GameViewport->Viewport->GetSizeXY());

to get the viewport size, and have the user specify a UI scale, then I can do math on my side to wrangle the UI element locations and sizes.

segross commented 4 years ago

Do you mean the adaptive canvas size? This is a feature that I agreed to merge, but it is not fully complete. I will however extend it and add zooming into account.

About the blurry text, I guess it will be as you say. There are some alternatives to the default fonts, but I'm not planning to work on that in any foreseeable future. You can check https://github.com/ocornut/imgui/blob/master/docs/FONTS.txt for more information. If you find a good solution that you would like to share you can do ite here or you can push it.

About the crash, I would need more details. Are you hot-reloading? Any information and call stack might be necessary because I run this plugin in editor and standalone, different build types and didn't have a crash like that. There is one scenario with hot-reloading that I know about but fix will be later.

connorjak commented 4 years ago

Where in the code is the functionality for the canvas size / panning? I would like to disable that for now, leaving me with a canvas that is the same size as and locked to the viewport.

Yes, I am using a hot reload when I get the crash. Running from the debugger gets around that. I’ll get some more info and a stack trace the next time I work on this.

segross commented 4 years ago

Do you have the latest version? One change list after the merge, I modified the adaptive canvas to block the zooming and panning functionality. Basically, all that should be blocked once you suppress the CanvasControlWidget:

void SImGuiWidget::UpdateCanvasControlMode(const FInputEvent& InputEvent)
{
    CanvasControlWidget->SetActive(!bAdaptiveCanvasSize && InputEvent.IsLeftAltDown() && InputEvent.IsLeftShiftDown());
}

As for the crash, you should find the discussion and a quick fix here: https://github.com/segross/UnrealImGui/issues/13. I assume that you hot reload from the outside (for instance building from the command line, etc.). Hot reloading of plugins this way seems to be not supported in the Unreal and you end-up in a weird mix where your executable is bound to a module that is never loaded. But in that thread you should find a work-around. Once I get enough time, I will finish that canvas merge and then make a proper fix for that hot-reload issue.

segross commented 4 years ago

I have added DPI Scale to the module settings.

The first solution is to scale everything in Slate. That works ok but it doesn't look sharp.

Another solution is to scale everything in the ImGui. That looks better but for the best effect I need to build fonts in the right size rather than scaling them. In contradiction to my previous comment, I will add it as soon as I find a moment.

Both solutions have different pros and cons, so most likely it will be possible to choose which one to use.

connorjak commented 4 years ago

Great, both those solutions sound workable. I'll probably be rotating back around to imgui work in a week or so, so I will be able to try it out.

segross commented 4 years ago

Hey. I finally got some time to finish and push DPI scaling improvements. Additionally to what was discussed above you can scale using DPI curve.

connorjak commented 4 years ago

Great! My best guess for when I can try this out is a 1-2 weeks from now.

segross commented 4 years ago

No problem and no rush. Just wanted to close the issue. Fell free to poke here if you find an issue or if you will have suggestions for better defaults as I work on 1080p monitor and cannot really tell.