mirror of
https://github.com/Ed94/Cog.git
synced 2026-08-01 04:10:06 +00:00
CogImGui: Add imgui viewport support
This commit is contained in:
@@ -1,227 +1,32 @@
|
||||
#include "CogImguiWidget.h"
|
||||
|
||||
#include "CogImguiInputHelper.h"
|
||||
#include "CogImguiInputHelper.h"
|
||||
#include "CogImGuiInputProcessor.h"
|
||||
#include "CogImguiModule.h"
|
||||
#include "CogImguiModule.h"
|
||||
#include "CogImguiTextureManager.h"
|
||||
#include "CogImguiWidget.h"
|
||||
#include "Engine/Console.h"
|
||||
#include "Engine/GameViewportClient.h"
|
||||
#include "Engine/LocalPlayer.h"
|
||||
#include "Framework/Application/SlateApplication.h"
|
||||
#include "GameFramework/PlayerController.h"
|
||||
#include "imgui.h"
|
||||
#include "imgui_internal.h"
|
||||
#include "implot.h"
|
||||
#include "SlateOptMacros.h"
|
||||
#include "UnrealClient.h"
|
||||
#include "Widgets/Layout/SBorder.h"
|
||||
#include "Widgets/Layout/SBox.h"
|
||||
#include "Widgets/SViewport.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
|
||||
void SCogImguiWidget::Construct(const FArguments& InArgs)
|
||||
{
|
||||
checkf(InArgs._GameViewport, TEXT("Null Game Viewport argument"));
|
||||
|
||||
GameViewport = InArgs._GameViewport;
|
||||
FontAtlas = InArgs._FontAtlas;
|
||||
Render = InArgs._Render;
|
||||
Context = InArgs._Context;
|
||||
|
||||
SetVisibility(EVisibility::SelfHitTestInvisible);
|
||||
|
||||
ImGuiContext = ImGui::CreateContext(FontAtlas);
|
||||
ImPlotContext = ImPlot::CreateContext();
|
||||
ImPlot::SetImGuiContext(ImGuiContext);
|
||||
|
||||
const char* InitFilenameTemp = TCHAR_TO_ANSI(*FCogImguiHelper::GetIniFilePath("imgui"));
|
||||
ImStrncpy(IniFilename, InitFilenameTemp, IM_ARRAYSIZE(IniFilename));
|
||||
|
||||
ImGuiIO& IO = ImGui::GetIO();
|
||||
IO.IniFilename = IniFilename;
|
||||
IO.DisplaySize = ImVec2(100, 100);
|
||||
IO.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
|
||||
IO.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
||||
IO.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
|
||||
IO.ConfigFlags |= ImGuiConfigFlags_NavNoCaptureKeyboard;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Register input processor to forward input events to imgui
|
||||
//--------------------------------------------------------------------
|
||||
if (FSlateApplication::IsInitialized())
|
||||
{
|
||||
UPlayerInput* PlayerInput = FCogImguiInputHelper::GetPlayerInput(*GameViewport->GetWorld());
|
||||
InputProcessor = MakeShared<FImGuiInputProcessor>(PlayerInput, this);
|
||||
FSlateApplication::Get().RegisterInputPreProcessor(InputProcessor.ToSharedRef(), 0);
|
||||
}
|
||||
}
|
||||
END_SLATE_FUNCTION_BUILD_OPTIMIZATION
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
SCogImguiWidget::~SCogImguiWidget()
|
||||
{
|
||||
if (FSlateApplication::IsInitialized())
|
||||
{
|
||||
if (InputProcessor.IsValid())
|
||||
{
|
||||
FSlateApplication::Get().UnregisterInputPreProcessor(InputProcessor);
|
||||
}
|
||||
}
|
||||
|
||||
DestroyImGuiContext();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SCogImguiWidget::DestroyImGuiContext()
|
||||
void SCogImguiWidget::SetDrawData(const ImDrawData* InDrawData)
|
||||
{
|
||||
if (ImPlotContext != nullptr)
|
||||
{
|
||||
ImPlot::DestroyContext(ImPlotContext);
|
||||
ImPlotContext = nullptr;
|
||||
}
|
||||
|
||||
if (ImGuiContext != nullptr)
|
||||
{
|
||||
ImGui::DestroyContext(ImGuiContext);
|
||||
ImGuiContext = nullptr;
|
||||
}
|
||||
DrawData = FCogImguiDrawData(InDrawData);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SCogImguiWidget::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime)
|
||||
{
|
||||
Super::Tick(AllottedGeometry, InCurrentTime, InDeltaTime);
|
||||
|
||||
TickKeyModifiers();
|
||||
TickFocus();
|
||||
TickImGui(InDeltaTime);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SCogImguiWidget::TickKeyModifiers()
|
||||
{
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
// Refresh modifiers otherwise, when pressing ALT-TAB, the Alt modifier is always true
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
FModifierKeysState ModifierKeys = FSlateApplication::Get().GetModifierKeys();
|
||||
|
||||
ImGuiIO& IO = ImGui::GetIO();
|
||||
if (ModifierKeys.IsControlDown() != IO.KeyCtrl) { IO.AddKeyEvent(ImGuiMod_Ctrl, ModifierKeys.IsControlDown()); }
|
||||
if (ModifierKeys.IsShiftDown() != IO.KeyShift) { IO.AddKeyEvent(ImGuiMod_Shift, ModifierKeys.IsShiftDown()); }
|
||||
if (ModifierKeys.IsAltDown() != IO.KeyAlt) { IO.AddKeyEvent(ImGuiMod_Alt, ModifierKeys.IsAltDown()); }
|
||||
if (ModifierKeys.IsCommandDown() != IO.KeySuper) { IO.AddKeyEvent(ImGuiMod_Super, ModifierKeys.IsCommandDown()); }
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SCogImguiWidget::TickImGui(float InDeltaTime)
|
||||
{
|
||||
if (ImGuiContext == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::SetCurrentContext(ImGuiContext);
|
||||
ImPlot::SetImGuiContext(ImGuiContext);
|
||||
ImPlot::SetCurrentContext(ImPlotContext);
|
||||
|
||||
ImGuiIO& IO = ImGui::GetIO();
|
||||
IO.DeltaTime = FApp::GetDeltaTime();
|
||||
IO.DisplaySize = FCogImguiHelper::ToImVec2(GetTickSpaceGeometry().GetAbsoluteSize());
|
||||
|
||||
ImGui::NewFrame();
|
||||
|
||||
Render(InDeltaTime);
|
||||
//DrawDebug();
|
||||
|
||||
ImGui::Render();
|
||||
|
||||
if ((IO.ConfigFlags & ImGuiConfigFlags_NoMouse) == 0)
|
||||
{
|
||||
SetCursor(FCogImguiInputHelper::ToSlateMouseCursor(ImGui::GetMouseCursor()));
|
||||
}
|
||||
|
||||
ImDrawData* DrawData = ImGui::GetDrawData();
|
||||
if (DrawData && DrawData->CmdListsCount > 0)
|
||||
{
|
||||
DrawLists.SetNum(DrawData->CmdListsCount, false);
|
||||
for (int i = 0; i < DrawData->CmdListsCount; i++)
|
||||
{
|
||||
DrawLists[i].TransferDrawData(*DrawData->CmdLists[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawLists.Empty();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SCogImguiWidget::TickFocus()
|
||||
{
|
||||
if (bEnableInput)
|
||||
{
|
||||
const auto& ViewportWidget = GameViewport->GetGameViewportWidget();
|
||||
if (!HasKeyboardFocus() && !IsConsoleOpened() && (ViewportWidget->HasKeyboardFocus() || ViewportWidget->HasFocusedDescendants()))
|
||||
{
|
||||
TakeFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SCogImguiWidget::TakeFocus()
|
||||
{
|
||||
FSlateApplication& SlateApplication = FSlateApplication::Get();
|
||||
|
||||
PreviousUserFocusedWidget = SlateApplication.GetUserFocusedWidget(SlateApplication.GetUserIndexForKeyboard());
|
||||
|
||||
if (ULocalPlayer* LocalPlayer = GetLocalPlayer())
|
||||
{
|
||||
TSharedRef<SWidget> FocusWidget = SharedThis(this);
|
||||
LocalPlayer->GetSlateOperations().CaptureMouse(FocusWidget);
|
||||
LocalPlayer->GetSlateOperations().SetUserFocus(FocusWidget);
|
||||
}
|
||||
else
|
||||
{
|
||||
SlateApplication.SetKeyboardFocus(SharedThis(this));
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SCogImguiWidget::ReturnFocus()
|
||||
{
|
||||
if (HasKeyboardFocus())
|
||||
{
|
||||
auto FocusWidgetPtr = PreviousUserFocusedWidget.IsValid()
|
||||
? PreviousUserFocusedWidget.Pin()
|
||||
: GameViewport->GetGameViewportWidget();
|
||||
|
||||
if (ULocalPlayer* LocalPlayer = GetLocalPlayer())
|
||||
{
|
||||
auto FocusWidgetRef = FocusWidgetPtr.ToSharedRef();
|
||||
|
||||
if (FocusWidgetPtr == GameViewport->GetGameViewportWidget())
|
||||
{
|
||||
LocalPlayer->GetSlateOperations().CaptureMouse(FocusWidgetRef);
|
||||
}
|
||||
|
||||
LocalPlayer->GetSlateOperations().SetUserFocus(FocusWidgetRef);
|
||||
}
|
||||
else
|
||||
{
|
||||
FSlateApplication& SlateApplication = FSlateApplication::Get();
|
||||
SlateApplication.ResetToDefaultPointerInputSettings();
|
||||
SlateApplication.SetUserFocus(SlateApplication.GetUserIndexForKeyboard(), FocusWidgetPtr);
|
||||
}
|
||||
}
|
||||
|
||||
PreviousUserFocusedWidget.Reset();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
int32 SCogImguiWidget::OnPaint(
|
||||
const FPaintArgs& Args,
|
||||
@@ -233,36 +38,56 @@ int32 SCogImguiWidget::OnPaint(
|
||||
bool bParentEnabled) const
|
||||
{
|
||||
|
||||
const FSlateRenderTransform& WidgetToScreen = AllottedGeometry.GetAccumulatedRenderTransform().GetTranslation();
|
||||
const FSlateRenderTransform ImGuiToScreen = FCogImguiHelper::RoundTranslation(ImGuiRenderTransform.Concatenate(WidgetToScreen));
|
||||
const FSlateRenderTransform Transform(FCogImguiHelper::RoundTranslation(AllottedGeometry.GetAccumulatedRenderTransform().GetTranslation() - FVector2d(DrawData.DisplayPos)));
|
||||
|
||||
FCogImguiTextureManager& TextureManager = FCogImguiModule::Get().GetTextureManager();
|
||||
|
||||
for (const auto& DrawList : DrawLists)
|
||||
FSlateBrush TextureBrush;
|
||||
for (const FCogImguiDrawList& DrawList : DrawData.DrawLists)
|
||||
{
|
||||
DrawList.CopyVertexData(VertexBuffer, ImGuiToScreen);
|
||||
|
||||
int IndexBufferOffset = 0;
|
||||
for (int i = 0; i < DrawList.NumCommands(); i++)
|
||||
TArray<FSlateVertex> Vertices;
|
||||
Vertices.SetNumUninitialized(DrawList.VtxBuffer.Size);
|
||||
for (int32 BufferIdx = 0; BufferIdx < Vertices.Num(); ++BufferIdx)
|
||||
{
|
||||
const auto& DrawCommand = DrawList.GetCommand(i, ImGuiToScreen);
|
||||
const ImDrawVert& Vtx = DrawList.VtxBuffer.Data[BufferIdx];
|
||||
Vertices[BufferIdx] = FSlateVertex::Make<ESlateVertexRounding::Disabled>(Transform, FCogImguiHelper::ToFVector2f(Vtx.pos), FCogImguiHelper::ToFVector2f(Vtx.uv), FVector2f::UnitVector, FCogImguiHelper::ToFColor(Vtx.col));
|
||||
}
|
||||
|
||||
DrawList.CopyIndexData(IndexBuffer, IndexBufferOffset, DrawCommand.NumElements);
|
||||
TArray<SlateIndex> Indices;
|
||||
Indices.SetNumUninitialized(DrawList.IdxBuffer.Size);
|
||||
for (int32 BufferIdx = 0; BufferIdx < Indices.Num(); ++BufferIdx)
|
||||
{
|
||||
Indices[BufferIdx] = DrawList.IdxBuffer.Data[BufferIdx];
|
||||
}
|
||||
|
||||
// Advance offset by number of copied elements to position it for the next command.
|
||||
IndexBufferOffset += DrawCommand.NumElements;
|
||||
for (const ImDrawCmd& DrawCmd : DrawList.CmdBuffer)
|
||||
{
|
||||
TArray VerticesSlice(Vertices.GetData() + DrawCmd.VtxOffset, Vertices.Num() - DrawCmd.VtxOffset);
|
||||
TArray IndicesSlice(Indices.GetData() + DrawCmd.IdxOffset, DrawCmd.ElemCount);
|
||||
|
||||
// Get texture resource handle for this draw command (null index will be also mapped to a valid texture).
|
||||
const FSlateResourceHandle& Handle = TextureManager.GetTextureHandle(DrawCommand.TextureId);
|
||||
UTexture2D* Texture = DrawCmd.GetTexID();
|
||||
if (TextureBrush.GetResourceObject() != Texture)
|
||||
{
|
||||
TextureBrush.SetResourceObject(Texture);
|
||||
if (IsValid(Texture))
|
||||
{
|
||||
TextureBrush.ImageSize.X = Texture->GetSizeX();
|
||||
TextureBrush.ImageSize.Y = Texture->GetSizeY();
|
||||
TextureBrush.ImageType = ESlateBrushImageType::FullColor;
|
||||
TextureBrush.DrawAs = ESlateBrushDrawType::Image;
|
||||
}
|
||||
else
|
||||
{
|
||||
TextureBrush.ImageSize.X = 0;
|
||||
TextureBrush.ImageSize.Y = 0;
|
||||
TextureBrush.ImageType = ESlateBrushImageType::NoImage;
|
||||
TextureBrush.DrawAs = ESlateBrushDrawType::NoDrawType;
|
||||
}
|
||||
}
|
||||
|
||||
// Transform clipping rectangle to screen space and apply to elements that we draw.
|
||||
const FSlateRect ClippingRect = DrawCommand.ClippingRect.IntersectionWith(MyClippingRect);
|
||||
|
||||
OutDrawElements.PushClip(FSlateClippingZone{ ClippingRect });
|
||||
|
||||
// Add elements to the list.
|
||||
FSlateDrawElement::MakeCustomVerts(OutDrawElements, LayerId, Handle, VertexBuffer, IndexBuffer, nullptr, 0, 0);
|
||||
FSlateRect ClipRect(DrawCmd.ClipRect.x, DrawCmd.ClipRect.y, DrawCmd.ClipRect.z, DrawCmd.ClipRect.w);
|
||||
ClipRect = TransformRect(Transform, ClipRect);
|
||||
|
||||
OutDrawElements.PushClip(FSlateClippingZone(ClipRect));
|
||||
FSlateDrawElement::MakeCustomVerts(OutDrawElements, LayerId, TextureBrush.GetRenderingResource(), VerticesSlice, IndicesSlice, nullptr, 0, 0);
|
||||
OutDrawElements.PopClip();
|
||||
}
|
||||
}
|
||||
@@ -274,128 +99,22 @@ int32 SCogImguiWidget::OnPaint(
|
||||
FVector2D SCogImguiWidget::ComputeDesiredSize(float Scale) const
|
||||
{
|
||||
return FVector2D::ZeroVector;
|
||||
//return Super::ComputeDesiredSize(Scale);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
ULocalPlayer* SCogImguiWidget::GetLocalPlayer() const
|
||||
{
|
||||
if (GameViewport.IsValid() == false)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UWorld* World = GameViewport->GetWorld();
|
||||
if (World == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ULocalPlayer* LocalPlayer = World->GetFirstLocalPlayerFromController();
|
||||
return LocalPlayer;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FVector2D SCogImguiWidget::TransformScreenPointToImGui(const FGeometry& MyGeometry, const FVector2D& Point) const
|
||||
{
|
||||
const FSlateRenderTransform ImGuiToScreen = MyGeometry.GetAccumulatedRenderTransform();
|
||||
return ImGuiToScreen.Inverse().TransformPoint(Point);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool SCogImguiWidget::IsConsoleOpened() const
|
||||
{
|
||||
return GameViewport->ViewportConsole && GameViewport->ViewportConsole->ConsoleState != NAME_None;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool SCogImguiWidget::IsCurrentContext() const
|
||||
{
|
||||
return ImGui::GetCurrentContext() == ImGuiContext;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SCogImguiWidget::SetAsCurrentContext()
|
||||
{
|
||||
ImGui::SetCurrentContext(ImGuiContext);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SCogImguiWidget::SetEnableInput(bool Value)
|
||||
{
|
||||
bEnableInput = Value;
|
||||
|
||||
if (bEnableInput)
|
||||
{
|
||||
TakeFocus();
|
||||
}
|
||||
else
|
||||
{
|
||||
ReturnFocus();
|
||||
}
|
||||
|
||||
ImGuiIO& IO = ImGui::GetIO();
|
||||
if (bEnableInput)
|
||||
{
|
||||
IO.ConfigFlags &= ~ImGuiConfigFlags_NoMouse;
|
||||
}
|
||||
else
|
||||
{
|
||||
IO.ConfigFlags |= ImGuiConfigFlags_NoMouse;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SCogImguiWidget::SetDPIScale(float Value)
|
||||
{
|
||||
if (DpiScale == Value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DpiScale = Value;
|
||||
OnDpiChanged();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SCogImguiWidget::OnDpiChanged()
|
||||
{
|
||||
if (FontAtlas == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FontAtlas->Clear();
|
||||
|
||||
ImFontConfig FontConfig = {};
|
||||
FontConfig.SizePixels = FMath::RoundFromZero(13.f * DpiScale);
|
||||
FontAtlas->AddFontDefault(&FontConfig);
|
||||
|
||||
unsigned char* Pixels;
|
||||
int Width, Height, Bpp;
|
||||
FontAtlas->GetTexDataAsRGBA32(&Pixels, &Width, &Height, &Bpp);
|
||||
const CogTextureIndex FontsTexureIndex = FCogImguiModule::Get().GetTextureManager().CreateTexture("xx", Width, Height, Bpp, Pixels);
|
||||
FontAtlas->TexID = FCogImguiHelper::ToImTextureID(FontsTexureIndex);
|
||||
|
||||
ImGuiStyle NewStyle = ImGuiStyle();
|
||||
ImGui::GetStyle() = MoveTemp(NewStyle);
|
||||
NewStyle.ScaleAllSizes(DpiScale);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FReply SCogImguiWidget::OnFocusReceived(const FGeometry& MyGeometry, const FFocusEvent& FocusEvent)
|
||||
{
|
||||
if (bEnableInput == false)
|
||||
{
|
||||
return FReply::Unhandled();
|
||||
}
|
||||
|
||||
Super::OnFocusReceived(MyGeometry, FocusEvent);
|
||||
|
||||
FSlateApplication::Get().ResetToDefaultPointerInputSettings();
|
||||
|
||||
return FReply::Handled();
|
||||
}
|
||||
////--------------------------------------------------------------------------------------------------------------------------
|
||||
//FReply SCogImguiWidget::OnFocusReceived(const FGeometry& MyGeometry, const FFocusEvent& FocusEvent)
|
||||
//{
|
||||
// if (bEnableInput == false)
|
||||
// {
|
||||
// return FReply::Unhandled();
|
||||
// }
|
||||
//
|
||||
// Super::OnFocusReceived(MyGeometry, FocusEvent);
|
||||
//
|
||||
// FSlateApplication::Get().ResetToDefaultPointerInputSettings();
|
||||
//
|
||||
// return FReply::Handled();
|
||||
//}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FReply SCogImguiWidget::OnKeyChar(const FGeometry& MyGeometry, const FCharacterEvent& CharacterEvent)
|
||||
@@ -408,33 +127,4 @@ FReply SCogImguiWidget::OnKeyChar(const FGeometry& MyGeometry, const FCharacterE
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SCogImguiWidget::DrawDebug()
|
||||
{
|
||||
if (ImGui::Begin("ImGui Integration Debug"))
|
||||
{
|
||||
ImGui::BeginDisabled();
|
||||
|
||||
ImVec2 AbsPos = FCogImguiHelper::ToImVec2(GetTickSpaceGeometry().GetAbsolutePosition());
|
||||
ImGui::InputFloat2("Widget Abs Pos", &AbsPos.x, "%0.1f");
|
||||
|
||||
ImVec2 AbsSize = FCogImguiHelper::ToImVec2(GetTickSpaceGeometry().GetAbsoluteSize());
|
||||
ImGui::InputFloat2("Widget Abs Size", &AbsSize.x, "%0.1f");
|
||||
|
||||
ImVec2 LocalSize = FCogImguiHelper::ToImVec2(GetTickSpaceGeometry().GetLocalSize());
|
||||
ImGui::InputFloat2("Widget Local Size", &LocalSize.x, "%0.1f");
|
||||
|
||||
FSlateApplication& SlateApp = FSlateApplication::Get();
|
||||
ImVec2 MousePosition = FCogImguiHelper::ToImVec2(SlateApp.GetCursorPos());
|
||||
ImGui::InputFloat2("Mouse", &MousePosition.x, "%0.1f");
|
||||
|
||||
ImGuiIO& IO = ImGui::GetIO();
|
||||
ImGui::InputFloat2("ImGui Mouse", &IO.MousePos.x, "%0.1f");
|
||||
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user